summaryrefslogtreecommitdiffstats
path: root/src/object
diff options
context:
space:
mode:
authorPiotr Dziwinski <piotrdz@gmail.com>2012-06-26 22:23:05 +0200
committerPiotr Dziwinski <piotrdz@gmail.com>2012-06-26 22:23:05 +0200
commitebed57aa22b772211387a5561f995eee8f5faed1 (patch)
tree9a0b08371df54c125957e63c7ecff81c001d4eaf /src/object
parentfc5389d18816799ba2698914384cd099ba8a7a6c (diff)
downloadcolobot-ebed57aa22b772211387a5561f995eee8f5faed1.tar.gz
colobot-ebed57aa22b772211387a5561f995eee8f5faed1.tar.bz2
colobot-ebed57aa22b772211387a5561f995eee8f5faed1.zip
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 <d3d.h> in d3dengine.h
Diffstat (limited to 'src/object')
-rw-r--r--src/object/auto/auto.cpp874
-rw-r--r--src/object/auto/auto.h222
-rw-r--r--src/object/auto/autobase.cpp2882
-rw-r--r--src/object/auto/autobase.h224
-rw-r--r--src/object/auto/autoconvert.cpp1054
-rw-r--r--src/object/auto/autoconvert.h140
-rw-r--r--src/object/auto/autoderrick.cpp1178
-rw-r--r--src/object/auto/autoderrick.h142
-rw-r--r--src/object/auto/autodestroyer.cpp748
-rw-r--r--src/object/auto/autodestroyer.h130
-rw-r--r--src/object/auto/autoegg.cpp718
-rw-r--r--src/object/auto/autoegg.h138
-rw-r--r--src/object/auto/autoenergy.cpp1294
-rw-r--r--src/object/auto/autoenergy.h142
-rw-r--r--src/object/auto/autofactory.cpp1882
-rw-r--r--src/object/auto/autofactory.h148
-rw-r--r--src/object/auto/autoflag.cpp324
-rw-r--r--src/object/auto/autoflag.h92
-rw-r--r--src/object/auto/autohuston.cpp592
-rw-r--r--src/object/auto/autohuston.h130
-rw-r--r--src/object/auto/autoinfo.cpp1034
-rw-r--r--src/object/auto/autoinfo.h136
-rw-r--r--src/object/auto/autojostle.cpp284
-rw-r--r--src/object/auto/autojostle.h96
-rw-r--r--src/object/auto/autokid.cpp402
-rw-r--r--src/object/auto/autokid.h94
-rw-r--r--src/object/auto/autolabo.cpp1220
-rw-r--r--src/object/auto/autolabo.h150
-rw-r--r--src/object/auto/automush.cpp688
-rw-r--r--src/object/auto/automush.h122
-rw-r--r--src/object/auto/autonest.cpp550
-rw-r--r--src/object/auto/autonest.h122
-rw-r--r--src/object/auto/autonuclear.cpp968
-rw-r--r--src/object/auto/autonuclear.h136
-rw-r--r--src/object/auto/autopara.cpp654
-rw-r--r--src/object/auto/autopara.h130
-rw-r--r--src/object/auto/autoportico.cpp850
-rw-r--r--src/object/auto/autoportico.h138
-rw-r--r--src/object/auto/autoradar.cpp612
-rw-r--r--src/object/auto/autoradar.h128
-rw-r--r--src/object/auto/autorepair.cpp678
-rw-r--r--src/object/auto/autorepair.h130
-rw-r--r--src/object/auto/autoresearch.cpp1216
-rw-r--r--src/object/auto/autoresearch.h140
-rw-r--r--src/object/auto/autoroot.cpp240
-rw-r--r--src/object/auto/autoroot.h88
-rw-r--r--src/object/auto/autosafe.cpp1224
-rw-r--r--src/object/auto/autosafe.h148
-rw-r--r--src/object/auto/autostation.cpp740
-rw-r--r--src/object/auto/autostation.h112
-rw-r--r--src/object/auto/autotower.cpp1082
-rw-r--r--src/object/auto/autotower.h148
-rw-r--r--src/object/brain.cpp5998
-rw-r--r--src/object/brain.h436
-rw-r--r--src/object/mainmovie.cpp476
-rw-r--r--src/object/mainmovie.h160
-rw-r--r--src/object/motion/motion.cpp478
-rw-r--r--src/object/motion/motion.h186
-rw-r--r--src/object/motion/motionant.cpp1742
-rw-r--r--src/object/motion/motionant.h146
-rw-r--r--src/object/motion/motionbee.cpp1288
-rw-r--r--src/object/motion/motionbee.h132
-rw-r--r--src/object/motion/motionhuman.cpp3540
-rw-r--r--src/object/motion/motionhuman.h188
-rw-r--r--src/object/motion/motionmother.cpp1048
-rw-r--r--src/object/motion/motionmother.h108
-rw-r--r--src/object/motion/motionspider.cpp1518
-rw-r--r--src/object/motion/motionspider.h142
-rw-r--r--src/object/motion/motiontoto.cpp1738
-rw-r--r--src/object/motion/motiontoto.h140
-rw-r--r--src/object/motion/motionvehicle.cpp4146
-rw-r--r--src/object/motion/motionvehicle.h138
-rw-r--r--src/object/motion/motionworm.cpp730
-rw-r--r--src/object/motion/motionworm.h124
-rw-r--r--src/object/object.cpp15212
-rw-r--r--src/object/object.h1550
-rw-r--r--src/object/robotmain.cpp14064
-rw-r--r--src/object/robotmain.h918
-rw-r--r--src/object/task/task.cpp178
-rw-r--r--src/object/task/task.h172
-rw-r--r--src/object/task/taskadvance.cpp292
-rw-r--r--src/object/task/taskadvance.h100
-rw-r--r--src/object/task/taskbuild.cpp1612
-rw-r--r--src/object/task/taskbuild.h170
-rw-r--r--src/object/task/taskfire.cpp768
-rw-r--r--src/object/task/taskfire.h104
-rw-r--r--src/object/task/taskfireant.cpp424
-rw-r--r--src/object/task/taskfireant.h126
-rw-r--r--src/object/task/taskflag.cpp610
-rw-r--r--src/object/task/taskflag.h116
-rw-r--r--src/object/task/taskgoto.cpp4682
-rw-r--r--src/object/task/taskgoto.h314
-rw-r--r--src/object/task/taskgungoal.cpp298
-rw-r--r--src/object/task/taskgungoal.h96
-rw-r--r--src/object/task/taskinfo.cpp438
-rw-r--r--src/object/task/taskinfo.h94
-rw-r--r--src/object/task/taskmanager.cpp556
-rw-r--r--src/object/task/taskmanager.h142
-rw-r--r--src/object/task/taskmanip.cpp2766
-rw-r--r--src/object/task/taskmanip.h198
-rw-r--r--src/object/task/taskpen.cpp574
-rw-r--r--src/object/task/taskpen.h136
-rw-r--r--src/object/task/taskrecover.cpp834
-rw-r--r--src/object/task/taskrecover.h132
-rw-r--r--src/object/task/taskreset.cpp660
-rw-r--r--src/object/task/taskreset.h126
-rw-r--r--src/object/task/tasksearch.cpp642
-rw-r--r--src/object/task/tasksearch.h140
-rw-r--r--src/object/task/taskshield.cpp1120
-rw-r--r--src/object/task/taskshield.h168
-rw-r--r--src/object/task/taskspiderexplo.cpp220
-rw-r--r--src/object/task/taskspiderexplo.h88
-rw-r--r--src/object/task/tasktake.cpp1192
-rw-r--r--src/object/task/tasktake.h150
-rw-r--r--src/object/task/taskterraform.cpp832
-rw-r--r--src/object/task/taskterraform.h124
-rw-r--r--src/object/task/taskturn.cpp268
-rw-r--r--src/object/task/taskturn.h92
-rw-r--r--src/object/task/taskwait.cpp148
-rw-r--r--src/object/task/taskwait.h88
120 files changed, 52925 insertions, 52925 deletions
diff --git a/src/object/auto/auto.cpp b/src/object/auto/auto.cpp
index 9635265..f2764e2 100644
--- a/src/object/auto/auto.cpp
+++ b/src/object/auto/auto.cpp
@@ -1,437 +1,437 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/auto.h"
-
-
-#include "common/iman.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/gauge.h"
-#include "ui/window.h"
-
-
-
-
-// Object's constructor.
-
-CAuto::CAuto(CInstanceManager* iMan, CObject* object)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_AUTO, this, 100);
-
- m_object = object;
- m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
- m_cloud = (CCloud*)m_iMan->SearchInstance(CLASS_CLOUD);
- m_planet = (CPlanet*)m_iMan->SearchInstance(CLASS_PLANET);
- m_blitz = (CBlitz*)m_iMan->SearchInstance(CLASS_BLITZ);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
-
- m_type = m_object->RetType();
- m_time = 0.0f;
- m_lastUpdateTime = 0.0f;
- m_bMotor = false;
- m_progressTime = 0.0f;
- m_progressTotal = 1.0f;
-
- Init();
-}
-
-// Object's destructor.
-
-CAuto::~CAuto()
-{
- m_iMan->DeleteInstance(CLASS_AUTO, this);
-}
-
-
-// Destroys the object.
-
-void CAuto::DeleteObject(bool bAll)
-{
-}
-
-
-// Initialize the object.
-
-void CAuto::Init()
-{
- m_bBusy = false;
-}
-
-// Starts the object.
-
-void CAuto::Start(int param)
-{
-}
-
-
-// Give a type.
-
-bool CAuto::SetType(ObjectType type)
-{
- return false;
-}
-
-// Gives a value.
-
-bool CAuto::SetValue(int rank, float value)
-{
- return false;
-}
-
-// Gives the string.
-
-bool CAuto::SetString(char *string)
-{
- return false;
-}
-
-
-// Management of an event.
-
-bool CAuto::EventProcess(const Event &event)
-{
- if ( event.event == EVENT_FRAME &&
- !m_engine->RetPause() )
- {
- m_time += event.rTime;
- UpdateInterface(event.rTime);
- }
-
- if ( !m_object->RetSelect() ) // robot not selected?
- {
- return true;
- }
-
- return true;
-}
-
-// Indicates whether the controller has finished its activity.
-
-Error CAuto::IsEnded()
-{
- return ERR_CONTINUE;
-}
-
-// Stops the controller
-
-bool CAuto::Abort()
-{
- return false;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAuto::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, dim, ddim;
- float ox, oy, sx, sy;
- char name[100];
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw != 0 )
- {
- pw->Flush(); // destroys the window buttons
- m_interface->DeleteControl(EVENT_WINDOW0); // destroys the window
- }
-
- if ( !bSelect ) return true;
-
- pos.x = 0.0f;
- pos.y = 0.0f;
- dim.x = 540.0f/640.0f;
-//? dim.y = 70.0f/480.0f;
- dim.y = 86.0f/480.0f;
- m_interface->CreateWindows(pos, dim, 3, EVENT_WINDOW0);
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- m_object->GetTooltipName(name);
- pos.x = 0.0f;
- pos.y = 64.0f/480.0f;
- ddim.x = 540.0f/640.0f;
- ddim.y = 16.0f/480.0f;
- pw->CreateLabel(pos, ddim, 0, EVENT_LABEL0, name);
-
- dim.x = 33.0f/640.0f;
- dim.y = 33.0f/480.0f;
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*7.0f;
- pos.y = oy+sy*0.6f;
- ddim.x = 160.0f/640.0f;
- ddim.y = 26.0f/480.0f;
- pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GPROGRESS);
-
- if ( m_type != OBJECT_BASE &&
- m_type != OBJECT_SAFE &&
- m_type != OBJECT_HUSTON )
- {
- pos.x = ox+sx*2.1f;
- pos.y = oy+sy*0;
- ddim.x = dim.x*0.6f;
- ddim.y = dim.y*0.6f;
- pw->CreateButton(pos, ddim, 12, EVENT_OBJECT_DELETE);
- }
-
-#if 0
- pos.x = ox+sx*12.4f;
- pos.y = oy+sy*1;
- pw->CreateButton(pos, dim, 63, EVENT_OBJECT_BHELP);
-
- pos.x = ox+sx*12.4f;
- pos.y = oy+sy*0;
- pw->CreateButton(pos, dim, 19, EVENT_OBJECT_HELP);
-
- if ( m_main->RetSceneSoluce() )
- {
- pos.x = ox+sx*13.4f;
- pos.y = oy+sy*1;
- pw->CreateButton(pos, dim, 20, EVENT_OBJECT_SOLUCE);
- }
-
- pos.x = ox+sx*13.4f;
- pos.y = oy+sy*0;
- pw->CreateButton(pos, dim, 10, EVENT_OBJECT_DESELECT);
-#else
- pos.x = ox+sx*12.3f;
- pos.y = oy+sy*-0.1f;
- ddim.x = dim.x*1.0f;
- ddim.y = dim.y*2.1f;
- pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue background
-
- pos.x = ox+sx*12.3f;
- pos.y = oy+sy*1;
- pw->CreateGroup(pos, dim, 19, EVENT_NULL); // sign SatCom
-
- pos.x = ox+sx*12.4f;
- pos.y = oy+sy*0.5f;
- ddim.x = dim.x*0.8f;
- ddim.y = dim.y*0.5f;
- pw->CreateButton(pos, ddim, 18, EVENT_OBJECT_BHELP);
- pos.y = oy+sy*0.0f;
- pw->CreateButton(pos, ddim, 19, EVENT_OBJECT_HELP);
-
- pos.x = ox+sx*13.4f;
- pos.y = oy+sy*0;
- pw->CreateButton(pos, dim, 10, EVENT_OBJECT_DESELECT);
-#endif
-
- pos.x = ox+sx*14.9f;
- pos.y = oy+sy*0;
- ddim.x = 14.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGauge(pos, ddim, 3, EVENT_OBJECT_GSHIELD);
-
- UpdateInterface();
- m_lastUpdateTime = 0.0f;
- UpdateInterface(0.0f);
-
- return true;
-}
-
-// Change the state of a button interface.
-
-void CAuto::CheckInterface(CWindow *pw, EventMsg event, bool bState)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_CHECK, bState);
-}
-
-// Change the state of a button interface.
-
-void CAuto::EnableInterface(CWindow *pw, EventMsg event, bool bState)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_ENABLE, bState);
-}
-
-// Change the state of a button interface.
-
-void CAuto::VisibleInterface(CWindow *pw, EventMsg event, bool bState)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_VISIBLE, bState);
-}
-
-// Change the state of a button interface.
-
-void CAuto::DeadInterface(CWindow *pw, EventMsg event, bool bState)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_DEAD, !bState);
-}
-
-// Change the state of a button interface.
-
-void CAuto::UpdateInterface()
-{
- CWindow* pw;
-
- if ( !m_object->RetSelect() ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- VisibleInterface(pw, EVENT_OBJECT_GPROGRESS, m_bBusy);
-}
-
-// Updates the state of all buttons on the interface,
-// following the time that elapses ...
-
-void CAuto::UpdateInterface(float rTime)
-{
- CWindow* pw;
- CGauge* pg;
-
- if ( m_time < m_lastUpdateTime+0.1f ) return;
- m_lastUpdateTime = m_time;
-
- if ( !m_object->RetSelect() ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GSHIELD);
- if ( pg != 0 )
- {
- pg->SetLevel(m_object->RetShield());
- }
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GPROGRESS);
- if ( pg != 0 )
- {
- pg->SetLevel(m_progressTime);
- }
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAuto::RetError()
-{
- return ERR_OK;
-}
-
-
-// Management of the occupation.
-
-bool CAuto::RetBusy()
-{
- return m_bBusy;
-}
-
-void CAuto::SetBusy(bool bBusy)
-{
- m_bBusy = bBusy;
-}
-
-void CAuto::InitProgressTotal(float total)
-{
- m_progressTime = 0.0f;
- m_progressTotal = total;
-}
-
-void CAuto::EventProgress(float rTime)
-{
- m_progressTime += rTime/m_progressTotal;
-}
-
-
-// Engine management.
-
-bool CAuto::RetMotor()
-{
- return m_bMotor;
-}
-
-void CAuto::SetMotor(bool bMotor)
-{
- m_bMotor = bMotor;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAuto::Write(char *line)
-{
- char name[100];
-
- sprintf(name, " aType=%d", m_type);
- strcat(line, name);
-
- sprintf(name, " aBusy=%d", m_bBusy);
- strcat(line, name);
-
- sprintf(name, " aTime=%.2f", m_time);
- strcat(line, name);
-
- sprintf(name, " aProgressTime=%.2f", m_progressTime);
- strcat(line, name);
-
- sprintf(name, " aProgressTotal=%.2f", m_progressTotal);
- strcat(line, name);
-
- return false;
-}
-
-// Return all settings to the controller.
-
-bool CAuto::Read(char *line)
-{
- m_type = (ObjectType)OpInt(line, "aType", OBJECT_NULL);
- m_bBusy = OpInt(line, "aBusy", 0);
- m_time = OpFloat(line, "aTime", 0.0f);
- m_progressTime = OpFloat(line, "aProgressTime", 0.0f);
- m_progressTotal = OpFloat(line, "aProgressTotal", 0.0f);
-
- return false;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/auto.h"
+
+
+#include "common/iman.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/gauge.h"
+#include "ui/window.h"
+
+
+
+
+// Object's constructor.
+
+CAuto::CAuto(CInstanceManager* iMan, CObject* object)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_AUTO, this, 100);
+
+ m_object = object;
+ m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ m_cloud = (CCloud*)m_iMan->SearchInstance(CLASS_CLOUD);
+ m_planet = (CPlanet*)m_iMan->SearchInstance(CLASS_PLANET);
+ m_blitz = (CBlitz*)m_iMan->SearchInstance(CLASS_BLITZ);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+
+ m_type = m_object->RetType();
+ m_time = 0.0f;
+ m_lastUpdateTime = 0.0f;
+ m_bMotor = false;
+ m_progressTime = 0.0f;
+ m_progressTotal = 1.0f;
+
+ Init();
+}
+
+// Object's destructor.
+
+CAuto::~CAuto()
+{
+ m_iMan->DeleteInstance(CLASS_AUTO, this);
+}
+
+
+// Destroys the object.
+
+void CAuto::DeleteObject(bool bAll)
+{
+}
+
+
+// Initialize the object.
+
+void CAuto::Init()
+{
+ m_bBusy = false;
+}
+
+// Starts the object.
+
+void CAuto::Start(int param)
+{
+}
+
+
+// Give a type.
+
+bool CAuto::SetType(ObjectType type)
+{
+ return false;
+}
+
+// Gives a value.
+
+bool CAuto::SetValue(int rank, float value)
+{
+ return false;
+}
+
+// Gives the string.
+
+bool CAuto::SetString(char *string)
+{
+ return false;
+}
+
+
+// Management of an event.
+
+bool CAuto::EventProcess(const Event &event)
+{
+ if ( event.event == EVENT_FRAME &&
+ !m_engine->RetPause() )
+ {
+ m_time += event.rTime;
+ UpdateInterface(event.rTime);
+ }
+
+ if ( !m_object->RetSelect() ) // robot not selected?
+ {
+ return true;
+ }
+
+ return true;
+}
+
+// Indicates whether the controller has finished its activity.
+
+Error CAuto::IsEnded()
+{
+ return ERR_CONTINUE;
+}
+
+// Stops the controller
+
+bool CAuto::Abort()
+{
+ return false;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAuto::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, dim, ddim;
+ float ox, oy, sx, sy;
+ char name[100];
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw != 0 )
+ {
+ pw->Flush(); // destroys the window buttons
+ m_interface->DeleteControl(EVENT_WINDOW0); // destroys the window
+ }
+
+ if ( !bSelect ) return true;
+
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ dim.x = 540.0f/640.0f;
+//? dim.y = 70.0f/480.0f;
+ dim.y = 86.0f/480.0f;
+ m_interface->CreateWindows(pos, dim, 3, EVENT_WINDOW0);
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ m_object->GetTooltipName(name);
+ pos.x = 0.0f;
+ pos.y = 64.0f/480.0f;
+ ddim.x = 540.0f/640.0f;
+ ddim.y = 16.0f/480.0f;
+ pw->CreateLabel(pos, ddim, 0, EVENT_LABEL0, name);
+
+ dim.x = 33.0f/640.0f;
+ dim.y = 33.0f/480.0f;
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*7.0f;
+ pos.y = oy+sy*0.6f;
+ ddim.x = 160.0f/640.0f;
+ ddim.y = 26.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GPROGRESS);
+
+ if ( m_type != OBJECT_BASE &&
+ m_type != OBJECT_SAFE &&
+ m_type != OBJECT_HUSTON )
+ {
+ pos.x = ox+sx*2.1f;
+ pos.y = oy+sy*0;
+ ddim.x = dim.x*0.6f;
+ ddim.y = dim.y*0.6f;
+ pw->CreateButton(pos, ddim, 12, EVENT_OBJECT_DELETE);
+ }
+
+#if 0
+ pos.x = ox+sx*12.4f;
+ pos.y = oy+sy*1;
+ pw->CreateButton(pos, dim, 63, EVENT_OBJECT_BHELP);
+
+ pos.x = ox+sx*12.4f;
+ pos.y = oy+sy*0;
+ pw->CreateButton(pos, dim, 19, EVENT_OBJECT_HELP);
+
+ if ( m_main->RetSceneSoluce() )
+ {
+ pos.x = ox+sx*13.4f;
+ pos.y = oy+sy*1;
+ pw->CreateButton(pos, dim, 20, EVENT_OBJECT_SOLUCE);
+ }
+
+ pos.x = ox+sx*13.4f;
+ pos.y = oy+sy*0;
+ pw->CreateButton(pos, dim, 10, EVENT_OBJECT_DESELECT);
+#else
+ pos.x = ox+sx*12.3f;
+ pos.y = oy+sy*-0.1f;
+ ddim.x = dim.x*1.0f;
+ ddim.y = dim.y*2.1f;
+ pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue background
+
+ pos.x = ox+sx*12.3f;
+ pos.y = oy+sy*1;
+ pw->CreateGroup(pos, dim, 19, EVENT_NULL); // sign SatCom
+
+ pos.x = ox+sx*12.4f;
+ pos.y = oy+sy*0.5f;
+ ddim.x = dim.x*0.8f;
+ ddim.y = dim.y*0.5f;
+ pw->CreateButton(pos, ddim, 18, EVENT_OBJECT_BHELP);
+ pos.y = oy+sy*0.0f;
+ pw->CreateButton(pos, ddim, 19, EVENT_OBJECT_HELP);
+
+ pos.x = ox+sx*13.4f;
+ pos.y = oy+sy*0;
+ pw->CreateButton(pos, dim, 10, EVENT_OBJECT_DESELECT);
+#endif
+
+ pos.x = ox+sx*14.9f;
+ pos.y = oy+sy*0;
+ ddim.x = 14.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 3, EVENT_OBJECT_GSHIELD);
+
+ UpdateInterface();
+ m_lastUpdateTime = 0.0f;
+ UpdateInterface(0.0f);
+
+ return true;
+}
+
+// Change the state of a button interface.
+
+void CAuto::CheckInterface(CWindow *pw, EventMsg event, bool bState)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_CHECK, bState);
+}
+
+// Change the state of a button interface.
+
+void CAuto::EnableInterface(CWindow *pw, EventMsg event, bool bState)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_ENABLE, bState);
+}
+
+// Change the state of a button interface.
+
+void CAuto::VisibleInterface(CWindow *pw, EventMsg event, bool bState)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_VISIBLE, bState);
+}
+
+// Change the state of a button interface.
+
+void CAuto::DeadInterface(CWindow *pw, EventMsg event, bool bState)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_DEAD, !bState);
+}
+
+// Change the state of a button interface.
+
+void CAuto::UpdateInterface()
+{
+ CWindow* pw;
+
+ if ( !m_object->RetSelect() ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ VisibleInterface(pw, EVENT_OBJECT_GPROGRESS, m_bBusy);
+}
+
+// Updates the state of all buttons on the interface,
+// following the time that elapses ...
+
+void CAuto::UpdateInterface(float rTime)
+{
+ CWindow* pw;
+ CGauge* pg;
+
+ if ( m_time < m_lastUpdateTime+0.1f ) return;
+ m_lastUpdateTime = m_time;
+
+ if ( !m_object->RetSelect() ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GSHIELD);
+ if ( pg != 0 )
+ {
+ pg->SetLevel(m_object->RetShield());
+ }
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GPROGRESS);
+ if ( pg != 0 )
+ {
+ pg->SetLevel(m_progressTime);
+ }
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAuto::RetError()
+{
+ return ERR_OK;
+}
+
+
+// Management of the occupation.
+
+bool CAuto::RetBusy()
+{
+ return m_bBusy;
+}
+
+void CAuto::SetBusy(bool bBusy)
+{
+ m_bBusy = bBusy;
+}
+
+void CAuto::InitProgressTotal(float total)
+{
+ m_progressTime = 0.0f;
+ m_progressTotal = total;
+}
+
+void CAuto::EventProgress(float rTime)
+{
+ m_progressTime += rTime/m_progressTotal;
+}
+
+
+// Engine management.
+
+bool CAuto::RetMotor()
+{
+ return m_bMotor;
+}
+
+void CAuto::SetMotor(bool bMotor)
+{
+ m_bMotor = bMotor;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAuto::Write(char *line)
+{
+ char name[100];
+
+ sprintf(name, " aType=%d", m_type);
+ strcat(line, name);
+
+ sprintf(name, " aBusy=%d", m_bBusy);
+ strcat(line, name);
+
+ sprintf(name, " aTime=%.2f", m_time);
+ strcat(line, name);
+
+ sprintf(name, " aProgressTime=%.2f", m_progressTime);
+ strcat(line, name);
+
+ sprintf(name, " aProgressTotal=%.2f", m_progressTotal);
+ strcat(line, name);
+
+ return false;
+}
+
+// Return all settings to the controller.
+
+bool CAuto::Read(char *line)
+{
+ m_type = (ObjectType)OpInt(line, "aType", OBJECT_NULL);
+ m_bBusy = OpInt(line, "aBusy", 0);
+ m_time = OpFloat(line, "aTime", 0.0f);
+ m_progressTime = OpFloat(line, "aProgressTime", 0.0f);
+ m_progressTotal = OpFloat(line, "aProgressTotal", 0.0f);
+
+ return false;
+}
+
diff --git a/src/object/auto/auto.h b/src/object/auto/auto.h
index 3928d28..09efdd9 100644
--- a/src/object/auto/auto.h
+++ b/src/object/auto/auto.h
@@ -1,111 +1,111 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// auto.h
-
-#pragma once
-
-
-#include "common/misc.h"
-#include "object/object.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CParticule;
-class CLight;
-class CTerrain;
-class CWater;
-class CCloud;
-class CPlanet;
-class CBlitz;
-class CCamera;
-class CInterface;
-class CRobotMain;
-class CDisplayText;
-class CWindow;
-class CSound;
-
-
-
-
-class CAuto
-{
-public:
- CAuto(CInstanceManager* iMan, CObject* object);
- virtual ~CAuto();
-
- virtual void DeleteObject(bool bAll=false);
-
- virtual void Init();
- virtual void Start(int param);
- virtual bool EventProcess(const Event &event);
- virtual Error IsEnded();
- virtual bool Abort();
-
- virtual bool SetType(ObjectType type);
- virtual bool SetValue(int rank, float value);
- virtual bool SetString(char *string);
-
- virtual bool CreateInterface(bool bSelect);
- virtual Error RetError();
-
- virtual bool RetBusy();
- virtual void SetBusy(bool bBuse);
- virtual void InitProgressTotal(float total);
- virtual void EventProgress(float rTime);
-
- virtual bool RetMotor();
- virtual void SetMotor(bool bMotor);
-
- virtual bool Write(char *line);
- virtual bool Read(char *line);
-
-protected:
- void CheckInterface(CWindow *pw, EventMsg event, bool bState);
- void EnableInterface(CWindow *pw, EventMsg event, bool bState);
- void VisibleInterface(CWindow *pw, EventMsg event, bool bState);
- void DeadInterface(CWindow *pw, EventMsg event, bool bState);
- void UpdateInterface();
- void UpdateInterface(float rTime);
-
-protected:
- CInstanceManager* m_iMan;
- CEvent* m_event;
- CD3DEngine* m_engine;
- CParticule* m_particule;
- CLight* m_light;
- CTerrain* m_terrain;
- CWater* m_water;
- CCloud * m_cloud;
- CPlanet * m_planet;
- CBlitz* m_blitz;
- CCamera* m_camera;
- CInterface* m_interface;
- CRobotMain* m_main;
- CDisplayText* m_displayText;
- CObject* m_object;
- CSound* m_sound;
-
- ObjectType m_type;
- bool m_bBusy;
- bool m_bMotor;
- float m_time;
- float m_lastUpdateTime;
- float m_progressTime;
- float m_progressTotal;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// auto.h
+
+#pragma once
+
+
+#include "common/misc.h"
+#include "object/object.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CLight;
+class CTerrain;
+class CWater;
+class CCloud;
+class CPlanet;
+class CBlitz;
+class CCamera;
+class CInterface;
+class CRobotMain;
+class CDisplayText;
+class CWindow;
+class CSound;
+
+
+
+
+class CAuto
+{
+public:
+ CAuto(CInstanceManager* iMan, CObject* object);
+ virtual ~CAuto();
+
+ virtual void DeleteObject(bool bAll=false);
+
+ virtual void Init();
+ virtual void Start(int param);
+ virtual bool EventProcess(const Event &event);
+ virtual Error IsEnded();
+ virtual bool Abort();
+
+ virtual bool SetType(ObjectType type);
+ virtual bool SetValue(int rank, float value);
+ virtual bool SetString(char *string);
+
+ virtual bool CreateInterface(bool bSelect);
+ virtual Error RetError();
+
+ virtual bool RetBusy();
+ virtual void SetBusy(bool bBuse);
+ virtual void InitProgressTotal(float total);
+ virtual void EventProgress(float rTime);
+
+ virtual bool RetMotor();
+ virtual void SetMotor(bool bMotor);
+
+ virtual bool Write(char *line);
+ virtual bool Read(char *line);
+
+protected:
+ void CheckInterface(CWindow *pw, EventMsg event, bool bState);
+ void EnableInterface(CWindow *pw, EventMsg event, bool bState);
+ void VisibleInterface(CWindow *pw, EventMsg event, bool bState);
+ void DeadInterface(CWindow *pw, EventMsg event, bool bState);
+ void UpdateInterface();
+ void UpdateInterface(float rTime);
+
+protected:
+ CInstanceManager* m_iMan;
+ CEvent* m_event;
+ CD3DEngine* m_engine;
+ CParticule* m_particule;
+ CLight* m_light;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CCloud * m_cloud;
+ CPlanet * m_planet;
+ CBlitz* m_blitz;
+ CCamera* m_camera;
+ CInterface* m_interface;
+ CRobotMain* m_main;
+ CDisplayText* m_displayText;
+ CObject* m_object;
+ CSound* m_sound;
+
+ ObjectType m_type;
+ bool m_bBusy;
+ bool m_bMotor;
+ float m_time;
+ float m_lastUpdateTime;
+ float m_progressTime;
+ float m_progressTotal;
+};
+
diff --git a/src/object/auto/autobase.cpp b/src/object/auto/autobase.cpp
index a13232f..19382b7 100644
--- a/src/object/auto/autobase.cpp
+++ b/src/object/auto/autobase.cpp
@@ -1,1441 +1,1441 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autobase.h"
-
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "old/cloud.h"
-#include "old/planet.h"
-#include "old/blitz.h"
-#include "math/geometry.h"
-#include "object/robotmain.h"
-#include "physics/physics.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-
-
-
-const float BASE_LAND_TIME = 7.5f; // hard landing
-const float BASE_TAKO_TIME = 10.0f; // hard landing
-const float BASE_DOOR_TIME = 6.0f; // time opening / closing
-const float BASE_DOOR_TIME2 = 2.0f; // time opening / closing suppl.
-const float BASE_PORTICO_TIME_MOVE = 16.0f; // gate advance time
-const float BASE_PORTICO_TIME_DOWN = 4.0f; // gate length down
-const float BASE_PORTICO_TIME_OPEN = 4.0f; // gate opening duration
-const float BASE_TRANSIT_TIME = 15.0f; // transit duration
-
-
-
-
-// Object's constructor.
-
-CAutoBase::CAutoBase(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- m_fogStart = m_engine->RetFogStart();
- m_deepView = m_engine->RetDeepView();
- Init();
- m_phase = ABP_WAIT;
- m_soundChannel = -1;
-}
-
-// Object's destructor.
-
-CAutoBase::~CAutoBase()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoBase::DeleteObject(bool bAll)
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoBase::Init()
-{
- m_bOpen = false;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- m_lastMotorParticule = 0.0f;
-
- m_pos = m_object->RetPosition(0);
- m_lastPos = m_pos;
-
- m_phase = ABP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-}
-
-
-// Start the object.
-
-void CAutoBase::Start(int param)
-{
- m_phase = ABP_START;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- m_param = param;
-}
-
-
-// Management of an event.
-
-bool CAutoBase::EventProcess(const Event &event)
-{
- Math::Matrix* mat;
- Event newEvent;
- CObject* pObj;
- Math::Vector pos, speed, vibCir, iPos;
- Math::Point dim, p;
- Error err;
- float angle, dist, time, h, len, vSpeed;
- int i, max;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
-
-begin:
- iPos = m_object->RetPosition(0);
-
- if ( m_phase == ABP_START )
- {
- if ( m_param != PARAM_STOP && // not placed on the ground?
- m_param != PARAM_FIXSCENE )
- {
- FreezeCargo(true); // freeze whole cargo
- }
-
- if ( m_param == PARAM_STOP ) // raises the ground?
- {
- m_phase = ABP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
- m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
- m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
- m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
- m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
- }
-
- pObj = m_main->RetSelectObject();
- m_main->SelectObject(pObj);
- m_camera->SetObject(pObj);
- if ( pObj == 0 )
- {
- m_camera->SetType(CAMERA_BACK);
- }
- else
- {
- m_camera->SetType(pObj->RetCameraType());
- m_camera->SetDist(pObj->RetCameraDist());
- }
-
- m_main->StartMusic();
- }
-
- if ( m_param == PARAM_FIXSCENE ) // raises the ground?
- {
- m_phase = ABP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
- m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
- m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
- m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
- m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
- }
- }
-
- if ( m_param == PARAM_LANDING ) // Landing?
- {
- m_phase = ABP_LAND;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_LAND_TIME;
-
- m_main->SetMovieLock(true); // blocks everything until the end of the landing
- m_bMotor = true; // lights the jet engine
-
- m_camera->SetType(CAMERA_SCRIPT);
-
- pos = m_pos;
- pos.x -= 150.0f;
- m_terrain->MoveOnFloor(pos);
- pos.y += 10.0f;
- m_camera->SetScriptEye(pos);
- m_posSound = pos;
-
- pos = m_object->RetPosition(0);
- pos.y += 300.0f+50.0f;
- m_camera->SetScriptLookat(pos);
-
- m_camera->FixCamera();
- m_engine->SetFocus(2.0f);
-
- m_engine->SetFogStart(0.9f);
-
- if ( m_soundChannel == -1 )
- {
- m_soundChannel = m_sound->Play(SOUND_FLY, m_posSound, 0.3f, 2.0f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, BASE_LAND_TIME, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 2.0f, SOPER_STOP);
- }
-
- m_main->StartMusic();
- }
-
- if ( m_param == PARAM_PORTICO ) // gate on the porch?
- {
- pos = m_object->RetPosition(0);
- m_finalPos = pos;
- pos.z += BASE_PORTICO_TIME_MOVE*5.0f; // back
- pos.y += 10.0f; // rises (the gate)
- m_object->SetPosition(0, pos);
- MoveCargo(); // all cargo moves
-
- m_phase = ABP_PORTICO_MOVE;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_PORTICO_TIME_MOVE;
-
- m_main->StartMusic();
- }
-
- if ( m_param == PARAM_TRANSIT1 ||
- m_param == PARAM_TRANSIT2 ||
- m_param == PARAM_TRANSIT3 ) // transit in space?
- {
- m_phase = ABP_TRANSIT_MOVE;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_TRANSIT_TIME;
-
- m_object->SetAngleZ(0, -Math::PI/2.0f);
- pos = m_object->RetPosition(0);
- pos.y += 10000.0f; // in space
- m_finalPos = pos;
- m_object->SetPosition(0, pos);
-
- m_main->SetMovieLock(true); // blocks everything until the end of the landing
- m_bMotor = true; // lights the jet engine
-
- m_camera->SetType(CAMERA_SCRIPT);
- pos.x += 1000.0f;
- pos.z -= 60.0f;
- pos.y += 80.0f;
- m_camera->SetScriptEye(pos);
- m_posSound = pos;
- m_camera->FixCamera();
- m_engine->SetFocus(1.0f);
-
- BeginTransit();
-
- mat = m_object->RetWorldMatrix(0);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 10.0f;
- dim.y = dim.x;
- pos = Math::Vector(42.0f, -2.0f, 17.0f);
- pos = Transform(*mat, pos);
- m_partiChannel[0] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
- pos = Math::Vector(17.0f, -2.0f, 42.0f);
- pos = Transform(*mat, pos);
- m_partiChannel[1] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
- pos = Math::Vector(42.0f, -2.0f, -17.0f);
- pos = Transform(*mat, pos);
- m_partiChannel[2] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
- pos = Math::Vector(17.0f, -2.0f, -42.0f);
- pos = Transform(*mat, pos);
- m_partiChannel[3] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
- pos = Math::Vector(-42.0f, -2.0f, 17.0f);
- pos = Transform(*mat, pos);
- m_partiChannel[4] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
- pos = Math::Vector(-17.0f, -2.0f, 42.0f);
- pos = Transform(*mat, pos);
- m_partiChannel[5] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
- pos = Math::Vector(-42.0f, -2.0f, -17.0f);
- pos = Transform(*mat, pos);
- m_partiChannel[6] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
- pos = Math::Vector(-17.0f, -2.0f, -42.0f);
- pos = Transform(*mat, pos);
- m_partiChannel[7] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
-
- if ( m_soundChannel == -1 )
- {
- m_soundChannel = m_sound->Play(SOUND_FLY, m_posSound, 0.0f, 1.2f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, BASE_TRANSIT_TIME*0.55f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.8f, BASE_TRANSIT_TIME*0.45f, SOPER_STOP);
- }
- }
- }
-
- if ( event.event == EVENT_UPDINTERFACE )
- {
- if ( m_object->RetSelect() ) CreateInterface(true);
- }
-
- if ( event.event == EVENT_OBJECT_BTAKEOFF )
- {
- err = CheckCloseDoor();
- if ( err != ERR_OK )
- {
- m_displayText->DisplayError(err, m_object);
- return false;
- }
-
- err = m_main->CheckEndMission(false);
- if ( err != ERR_OK )
- {
- m_displayText->DisplayError(err, m_object);
- return false;
- }
-
- FreezeCargo(true); // freeze whole cargo
- m_main->SetMovieLock(true); // blocks everything until the end
- m_main->DeselectAll();
-
- m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
- m_event->AddEvent(newEvent);
-
- m_camera->SetType(CAMERA_SCRIPT);
-
- pos = m_pos;
- pos.x -= 110.0f;
- m_terrain->MoveOnFloor(pos);
- pos.y += 10.0f;
- m_camera->SetScriptEye(pos);
- m_posSound = pos;
-
- pos = m_object->RetPosition(0);
- pos.y += 50.0f;
- m_camera->SetScriptLookat(pos);
-
- m_engine->SetFocus(1.0f);
-
- m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.3f, 1.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.5f, BASE_DOOR_TIME2, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.5f, 0.5f, SOPER_STOP);
-
- m_phase = ABP_CLOSE2;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_DOOR_TIME2;
- return true;
- }
-
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_phase == ABP_WAIT ) return true;
-
- m_progress += event.rTime*m_speed;
-
- if ( m_phase == ABP_LAND )
- {
- if ( m_progress < 1.0f )
- {
- pos = m_pos;
- pos.y += powf(1.0f-m_progress, 2.0f)*300.0f;
- m_object->SetPosition(0, pos);
- MoveCargo(); // all cargo moves
-
- vibCir.z = sinf(m_time*Math::PI* 2.01f)*(Math::PI/150.0f)+
- sinf(m_time*Math::PI* 2.51f)*(Math::PI/200.0f)+
- sinf(m_time*Math::PI*19.01f)*(Math::PI/400.0f);
- vibCir.x = sinf(m_time*Math::PI* 2.03f)*(Math::PI/150.0f)+
- sinf(m_time*Math::PI* 2.52f)*(Math::PI/200.0f)+
- sinf(m_time*Math::PI*19.53f)*(Math::PI/400.0f);
- vibCir.y = 0.0f;
- vibCir *= Math::Min(1.0f, (1.0f-m_progress)*3.0f);
- m_object->SetCirVibration(vibCir);
-
- pos = m_pos;
- pos.x -= 150.0f;
- m_terrain->MoveOnFloor(pos);
- pos.y += 10.0f;
- m_camera->SetScriptEye(pos);
-
- pos = m_object->RetPosition(0);
- pos.y += 50.0f;
- m_camera->SetScriptLookat(pos);
-
- m_engine->SetFocus(1.0f+(1.0f-m_progress));
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- // Dust thrown to the ground.
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- angle = Math::Rand()*(Math::PI*2.0f);
- dist = m_progress*50.0f;
- p = Math::RotatePoint(angle, dist);
- speed.x = p.x;
- speed.z = p.y;
- speed.y = 0.0f;
- dim.x = (Math::Rand()*15.0f+15.0f)*m_progress;
- dim.y = dim.x;
- if ( dim.x >= 1.0f )
- {
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 2.0f);
- }
-
- // Particles are ejected from the jet engine.
- pos = m_object->RetPosition(0);
- pos.y += 6.0f;
- h = m_terrain->RetFloorHeight(pos)/300.0f;
- speed.x = (Math::Rand()-0.5f)*(80.0f-50.0f*h);
- speed.z = (Math::Rand()-0.5f)*(80.0f-50.0f*h);
- speed.y = -(Math::Rand()*(h+1.0f)*40.0f+(h+1.0f)*40.0f);
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 2.0f, 10.0f, 2.0f);
-
- // Black smoke from the jet engine.
- if ( m_progress > 0.8f )
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*8.0f;
- pos.z += (Math::Rand()-0.5f)*8.0f;
- pos.y += 3.0f;
- speed.x = (Math::Rand()-0.5f)*8.0f;
- speed.z = (Math::Rand()-0.5f)*8.0f;
- speed.y = 0.0f;
- dim.x = Math::Rand()*4.0f+4.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 2.0f);
- }
- }
- }
- else
- {
- m_bMotor = false; // put out the reactor
-
- m_object->SetPosition(0, m_pos); // setting down
- m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- MoveCargo(); // all cargo moves
-
- // Impact with the ground.
- max = (int)(50.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<max ; i++ )
- {
- angle = Math::Rand()*(Math::PI*2.0f);
- p = Math::RotatePoint(angle, 46.0f);
- pos = m_pos;
- pos.x += p.x;
- pos.z += p.y;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*10.0f+10.0f;
- dim.y = dim.x;
- time = Math::Rand()*2.0f+1.5f;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, time, 0.0f, 2.0f);
- }
-
-//? m_camera->StartEffect(CE_CRASH, m_pos, 1.0f);
- m_camera->StartEffect(CE_EXPLO, m_pos, 2.0f);
- m_engine->SetFocus(1.0f);
- m_sound->Play(SOUND_BOUM, m_posSound, 0.6f, 0.5f);
-
- m_phase = ABP_OPENWAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == ABP_OPENWAIT )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- // Black smoke from the reactor.
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*8.0f;
- pos.z += (Math::Rand()-0.5f)*8.0f;
- pos.y += 3.0f;
- speed.x = (Math::Rand()-0.5f)*8.0f;
- speed.z = (Math::Rand()-0.5f)*8.0f;
- speed.y = 0.0f;
- dim.x = Math::Rand()*4.0f+4.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 2.0f);
- }
- }
- else
- {
- m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.0f, 0.3f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.3f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.0f, BASE_DOOR_TIME-1.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 1.0f, SOPER_STOP);
-
- m_phase = ABP_OPEN;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_DOOR_TIME;
- }
- }
-
- if ( m_phase == ABP_OPEN )
- {
- if ( m_progress < 1.0f )
- {
- angle = -m_progress*124.0f*Math::PI/180.0f;
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetAngleZ(1+i, Math::PI/2.0f+angle);
- }
-
- if ( m_param != PARAM_PORTICO )
- {
- angle = m_progress*Math::PI*2.0f;
- p = Math::RotatePoint(angle, -150.0f);
- pos = m_pos;
- pos.x += p.x;
- pos.z += p.y;
- m_terrain->MoveOnFloor(pos);
- pos.y += 10.0f;
- pos.y += m_progress*40.0f;
- m_camera->SetScriptEye(pos);
-
- m_engine->SetFogStart(0.9f-(0.9f-m_fogStart)*m_progress);
- }
- }
- else
- {
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
- }
-
- // Clash the doors with the ground.
- max = (int)(20.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<max ; i++ )
- {
- angle = Math::Rand()*(20.0f*Math::PI/180.0f)-(10.0f*Math::PI/180.0f);
- angle += (Math::PI/4.0f)*(rand()%8);
- p = Math::RotatePoint(angle, 74.0f);
- pos = m_pos;
- pos.x += p.x;
- pos.z += p.y;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*8.0f+8.0f;
- dim.y = dim.x;
- time = Math::Rand()*2.0f+1.5f;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, time, 0.0f, 2.0f);
- }
-
- m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.3f, 1.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.5f, BASE_DOOR_TIME2, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.5f, 0.5f, SOPER_STOP);
-
- m_phase = ABP_OPEN2;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_DOOR_TIME2;
- }
- }
-
- if ( m_phase == ABP_OPEN2 )
- {
- if ( m_progress < 1.0f )
- {
- len = 7.0f-m_progress*(7.0f+11.5f);
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, len));
- m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, -len));
- m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f*m_progress);
- m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f*m_progress);
- }
-
- if ( m_param != PARAM_PORTICO )
- {
- angle = m_progress*Math::PI/2.0f;
- p = Math::RotatePoint(angle, -150.0f);
- pos = m_pos;
- pos.x += p.x;
- pos.z += p.y;
- m_terrain->MoveOnFloor(pos);
- pos.y += 10.0f;
- pos.y += m_progress*40.0f;
- m_camera->SetScriptEye(pos);
-
- m_engine->SetFogStart(0.9f-(0.9f-m_fogStart)*m_progress);
- }
- }
- else
- {
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
- m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
- m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
- m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
- }
-
- m_phase = ABP_LDWAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ABP_LDWAIT )
- {
- if ( m_progress >= 1.0f )
- {
- FreezeCargo(false); // frees all cargo
-
- if ( m_param != PARAM_PORTICO )
- {
- m_main->SetMovieLock(false); // you can play!
-
- pObj = m_main->RetSelectObject();
- m_main->SelectObject(pObj);
- m_camera->SetObject(pObj);
- if ( pObj == 0 )
- {
- m_camera->SetType(CAMERA_BACK);
- }
- else
- {
- m_camera->SetType(pObj->RetCameraType());
- m_camera->SetDist(pObj->RetCameraDist());
- }
- m_sound->Play(SOUND_BOUM, m_object->RetPosition(0));
- m_soundChannel = -1;
-
- m_engine->SetFogStart(m_fogStart);
- }
-
- m_bOpen = true;
- m_phase = ABP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ABP_CLOSE2 )
- {
- if ( m_progress < 1.0f )
- {
- len = 7.0f-(1.0f-m_progress)*(7.0f+11.5f);
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, len));
- m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, -len));
- m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f*(1.0f-m_progress));
- m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f*(1.0f-m_progress));
- }
- }
- else
- {
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, 7.0f));
- m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, -7.0f));
- m_object->SetAngleX(10+i, 0.0f);
- m_object->SetAngleX(18+i, 0.0f);
- }
-
- m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.0f, 0.3f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.3f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.0f, BASE_DOOR_TIME-1.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 1.0f, SOPER_STOP);
-
- m_phase = ABP_CLOSE;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_DOOR_TIME;
- }
- }
-
- if ( m_phase == ABP_CLOSE )
- {
- if ( m_progress < 1.0f )
- {
- angle = -(1.0f-m_progress)*124.0f*Math::PI/180.0f;
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetAngleZ(1+i, Math::PI/2.0f+angle);
- }
- }
- else
- {
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetAngleZ(1+i, Math::PI/2.0f);
- }
- m_bMotor = true; // lights the jet engine
-
- // Shock of the closing doors.
- max = (int)(20.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<max ; i++ )
- {
- angle = Math::Rand()*Math::PI*2.0f;
- p = Math::RotatePoint(angle, 32.0f);
- pos = m_pos;
- pos.x += p.x;
- pos.z += p.y;
- pos.y += 85.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*3.0f+3.0f;
- dim.y = dim.x;
- time = Math::Rand()*1.0f+1.0f;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, time);
- }
- m_sound->Play(SOUND_BOUM, m_object->RetPosition(0));
-
- m_soundChannel = -1;
- m_bOpen = false;
- m_phase = ABP_TOWAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == ABP_TOWAIT )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_soundChannel == -1 )
- {
- m_soundChannel = m_sound->Play(SOUND_FLY, m_posSound, 0.0f, 0.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 2.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 2.0f, BASE_TAKO_TIME, SOPER_STOP);
- }
-
- vibCir.z = sinf(m_time*Math::PI*19.01f)*(Math::PI/400.0f);
- vibCir.x = sinf(m_time*Math::PI*19.53f)*(Math::PI/400.0f);
- vibCir.y = 0.0f;
- vibCir *= m_progress*1.0f;
- m_object->SetCirVibration(vibCir);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- // Particles are ejected from the reactor.
- pos = m_object->RetPosition(0);
- pos.y += 6.0f;
- speed.x = (Math::Rand()-0.5f)*160.0f;
- speed.z = (Math::Rand()-0.5f)*160.0f;
- speed.y = -(Math::Rand()*10.0f+10.0f);
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 2.0f, 10.0f, 2.0f);
- }
-
- m_engine->SetFogStart(m_fogStart+(0.9f-m_fogStart)*m_progress);
- }
- else
- {
- m_engine->SetFogStart(0.9f);
-
- m_phase = ABP_TAKEOFF;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_TAKO_TIME;
- }
- }
-
- if ( m_phase == ABP_TAKEOFF )
- {
- if ( m_progress < 1.0f )
- {
- pos = m_pos;
- pos.y += powf(m_progress, 2.0f)*600.0f;
- m_object->SetPosition(0, pos);
- MoveCargo(); // all cargo moves
-
- vibCir.z = sinf(m_time*Math::PI*19.01f)*(Math::PI/400.0f);
- vibCir.x = sinf(m_time*Math::PI*19.53f)*(Math::PI/400.0f);
- vibCir.y = 0.0f;
- m_object->SetCirVibration(vibCir);
-
- pos = m_pos;
- pos.x -= 110.0f+m_progress*250.0f;
- m_terrain->MoveOnFloor(pos);
- pos.y += 10.0f;
- m_camera->SetScriptEye(pos);
-
- pos = m_object->RetPosition(0);
- pos.y += 50.0f;
- m_camera->SetScriptLookat(pos);
-
- m_engine->SetFocus(1.0f+m_progress);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- // Dust thrown to the ground.
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- angle = Math::Rand()*(Math::PI*2.0f);
- dist = (1.0f-m_progress)*50.0f;
- p = Math::RotatePoint(angle, dist);
- speed.x = p.x;
- speed.z = p.y;
- speed.y = 0.0f;
- dim.x = (Math::Rand()*10.0f+10.0f)*(1.0f-m_progress);
- dim.y = dim.x;
- if ( dim.x >= 1.0f )
- {
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 2.0f);
- }
-
- // Particles are ejected from the reactor.
- pos = m_object->RetPosition(0);
- pos.y += 6.0f;
- speed.x = (Math::Rand()-0.5f)*40.0f;
- speed.z = (Math::Rand()-0.5f)*40.0f;
- time = 5.0f+150.0f*m_progress;
- speed.y = -(Math::Rand()*time+time);
- time = 2.0f+m_progress*12.0f;
- dim.x = Math::Rand()*time+time;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 2.0f, 10.0f, 2.0f);
-
- // Black smoke from the reactor.
- pos = m_object->RetPosition(0);
- pos.y += 3.0f;
- speed.x = (Math::Rand()-0.5f)*10.0f*(4.0f-m_progress*3.0f);
- speed.z = (Math::Rand()-0.5f)*10.0f*(4.0f-m_progress*3.0f);
- speed.y = 0.0f;
- dim.x = Math::Rand()*20.0f+20.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 10.0f, 0.0f, 2.0f);
- }
- }
- else
- {
- m_soundChannel = -1;
- m_event->MakeEvent(newEvent, EVENT_WIN);
- m_event->AddEvent(newEvent);
-
- m_phase = ABP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == ABP_PORTICO_MOVE ) // advance of the gate?
- {
- if ( m_progress < 1.0f )
- {
- pos = m_object->RetPosition(0);
- pos.z -= event.rTime*5.0f;
- m_object->SetPosition(0, pos);
- MoveCargo(); // all cargo moves
- }
- else
- {
- m_phase = ABP_PORTICO_WAIT1;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ABP_PORTICO_WAIT1 ) // expectation the gate?
- {
- if ( m_progress >= 1.0f )
- {
- m_phase = ABP_PORTICO_DOWN;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_PORTICO_TIME_DOWN;
- }
- }
-
- if ( m_phase == ABP_PORTICO_DOWN ) // down the gate?
- {
- if ( m_progress < 1.0f )
- {
- pos = m_object->RetPosition(0);
- pos.y -= event.rTime*(10.0f/BASE_PORTICO_TIME_DOWN);
- m_object->SetPosition(0, pos);
- MoveCargo(); // all cargo moves
- }
- else
- {
- // Impact with the ground.
- max = (int)(50.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<max ; i++ )
- {
- angle = Math::Rand()*(Math::PI*2.0f);
- p = Math::RotatePoint(angle, 46.0f);
- pos = m_pos;
- pos.x += p.x;
- pos.z += p.y;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*10.0f+10.0f;
- dim.y = dim.x;
- time = Math::Rand()*2.0f+1.5f;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, time, 0.0f, 2.0f);
- }
-
- m_phase = ABP_PORTICO_WAIT2;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ABP_PORTICO_WAIT2 ) // expectation the gate?
- {
- if ( m_progress >= 1.0f )
- {
- m_phase = ABP_PORTICO_OPEN;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_PORTICO_TIME_OPEN;
- }
- }
-
- if ( m_phase == ABP_PORTICO_OPEN ) // opening the gate?
- {
- if ( m_progress < 1.0f )
- {
- }
- else
- {
- m_phase = ABP_OPEN;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == ABP_TRANSIT_MOVE ) // transit in space?
- {
- if ( m_progress < 1.0f )
- {
- pos = m_object->RetPosition(0);
- pos.x += event.rTime*(2000.0f/BASE_TRANSIT_TIME);
- m_object->SetPosition(0, pos);
- pos.x += 60.0f;
- m_camera->SetScriptLookat(pos);
- }
- else
- {
- m_object->SetAngleZ(0, 0.0f);
-
- m_param = PARAM_LANDING;
- m_phase = ABP_START;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- EndTransit();
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.8f, 0.01f, SOPER_STOP);
- m_soundChannel = -1;
- }
- goto begin;
- }
- }
-
- if ( m_bMotor )
- {
- if ( m_lastMotorParticule+m_engine->ParticuleAdapt(0.02f) <= m_time )
- {
- m_lastMotorParticule = m_time;
-
- mat = m_object->RetWorldMatrix(0);
-
- if ( event.rTime == 0.0f )
- {
- vSpeed = 0.0f;
- }
- else
- {
- pos = m_object->RetPosition(0);
- if ( m_phase == ABP_TRANSIT_MOVE )
- {
- vSpeed = (pos.x-iPos.x)/event.rTime;
- }
- else
- {
- vSpeed = (pos.y-iPos.y)/event.rTime;
- }
- if ( vSpeed < 0.0f ) vSpeed *= 1.5f;
- }
-
- pos = Math::Vector(0.0f, 6.0f, 0.0f);
- speed.x = (Math::Rand()-0.5f)*4.0f;
- speed.z = (Math::Rand()-0.5f)*4.0f;
- speed.y = vSpeed*0.8f-(8.0f+Math::Rand()*6.0f);
- speed += pos;
- pos = Transform(*mat, pos);
- speed = Transform(*mat, speed);
- speed -= pos;
-
- dim.x = 4.0f+Math::Rand()*4.0f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIBASE, 3.0f, 0.0f, 0.0f);
-
- if ( m_phase == ABP_TRANSIT_MOVE )
- {
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 12.0f;
- dim.y = dim.x;
- pos = Math::Vector(0.0f, 7.0f, 0.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 1.0f, 0.0f, 0.0f);
-
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 4.0f;
- dim.y = dim.x;
- pos = Math::Vector(42.0f, 0.0f, 17.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
- pos = Math::Vector(17.0f, 0.0f, 42.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
- pos = Math::Vector(42.0f, 0.0f, -17.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
- pos = Math::Vector(17.0f, 0.0f, -42.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
- pos = Math::Vector(-42.0f, 0.0f, 17.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
- pos = Math::Vector(-17.0f, 0.0f, 42.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
- pos = Math::Vector(-42.0f, 0.0f, -17.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
- pos = Math::Vector(-17.0f, 0.0f, -42.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
-
- pos = Math::Vector(42.0f, -2.0f, 17.0f);
- pos = Transform(*mat, pos);
- m_particule->SetPosition(m_partiChannel[0], pos);
- pos = Math::Vector(17.0f, -2.0f, 42.0f);
- pos = Transform(*mat, pos);
- m_particule->SetPosition(m_partiChannel[1], pos);
- pos = Math::Vector(42.0f, -2.0f, -17.0f);
- pos = Transform(*mat, pos);
- m_particule->SetPosition(m_partiChannel[2], pos);
- pos = Math::Vector(17.0f, -2.0f, -42.0f);
- pos = Transform(*mat, pos);
- m_particule->SetPosition(m_partiChannel[3], pos);
- pos = Math::Vector(-42.0f, -2.0f, 17.0f);
- pos = Transform(*mat, pos);
- m_particule->SetPosition(m_partiChannel[4], pos);
- pos = Math::Vector(-17.0f, -2.0f, 42.0f);
- pos = Transform(*mat, pos);
- m_particule->SetPosition(m_partiChannel[5], pos);
- pos = Math::Vector(-42.0f, -2.0f, -17.0f);
- pos = Transform(*mat, pos);
- m_particule->SetPosition(m_partiChannel[6], pos);
- pos = Math::Vector(-17.0f, -2.0f, -42.0f);
- pos = Transform(*mat, pos);
- m_particule->SetPosition(m_partiChannel[7], pos);
- }
- }
- }
-
- if ( m_soundChannel != -1 )
- {
- pos = m_engine->RetEyePt();
- m_sound->Position(m_soundChannel, pos);
- }
-
- return true;
-}
-
-// Stops the controller.
-
-bool CAutoBase::Abort()
-{
- Event newEvent;
- CObject* pObj;
- int i;
-
- if ( m_phase == ABP_TRANSIT_MOVE ) // transit ?
- {
- m_object->SetAngleZ(0, 0.0f);
-
- m_param = PARAM_LANDING;
- m_phase = ABP_START;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- EndTransit();
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.8f, 0.01f, SOPER_STOP);
- m_soundChannel = -1;
- }
- return true;
- }
-
- if ( m_param == PARAM_PORTICO ) // gate on the porch?
- {
- m_object->SetPosition(0, m_finalPos);
- MoveCargo(); // all cargo moves
-
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
- m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
- m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
- m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
- m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
- }
- }
- else
- {
- if ( m_phase == ABP_LAND ||
- m_phase == ABP_OPENWAIT ||
- m_phase == ABP_OPEN ||
- m_phase == ABP_OPEN2 ) // Landing?
- {
- m_bMotor = false; // put out the jet engine
- m_bOpen = true;
-
- m_object->SetPosition(0, m_pos); // setting down
- m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- MoveCargo(); // all cargo moves
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
- m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
- m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
- m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
- m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
- }
-
- m_main->SetMovieLock(false); // you can play!
-
- pObj = m_main->RetSelectObject();
- m_main->SelectObject(pObj);
- m_camera->SetObject(pObj);
- if ( pObj == 0 )
- {
- m_camera->SetType(CAMERA_BACK);
- }
- else
- {
- m_camera->SetType(pObj->RetCameraType());
- m_camera->SetDist(pObj->RetCameraDist());
- }
-
- m_engine->SetFogStart(m_fogStart);
- }
-
- if ( m_phase == ABP_CLOSE2 ||
- m_phase == ABP_CLOSE ||
- m_phase == ABP_TOWAIT ||
- m_phase == ABP_TAKEOFF ) // off?
- {
- m_event->MakeEvent(newEvent, EVENT_WIN);
- m_event->AddEvent(newEvent);
- }
- }
-
- m_object->SetAngleZ(0, 0.0f);
- FreezeCargo(false); // frees all cargo
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- m_phase = ABP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoBase::RetError()
-{
- return ERR_OK;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoBase::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, dim, ddim;
- float ox, oy, sx, sy;
- float sleep, delay, magnetic, progress;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- dim.x = 33.0f/640.0f;
- dim.y = 33.0f/480.0f;
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- ddim.x = dim.x*1.5f;
- ddim.y = dim.y*1.5f;
-
-//? pos.x = ox+sx*7.25f;
-//? pos.y = oy+sy*0.25f;
-//? pw->CreateButton(pos, ddim, 63, EVENT_OBJECT_BHELP);
-
- pos.x = ox+sx*8.00f;
- pos.y = oy+sy*0.25f;
- pw->CreateButton(pos, ddim, 28, EVENT_OBJECT_BTAKEOFF);
-
- if ( m_blitz->GetStatus(sleep, delay, magnetic, progress) )
- {
- pos.x = ox+sx*10.2f;
- pos.y = oy+sy*0.5f;
- ddim.x = dim.x*1.0f;
- ddim.y = dim.y*1.0f;
- pw->CreateButton(pos, ddim, 41, EVENT_OBJECT_LIMIT);
- }
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 100, EVENT_OBJECT_TYPE);
-
- UpdateInterface();
-
- return true;
-}
-
-// Updates the status of all interface buttons.
-
-void CAutoBase::UpdateInterface()
-{
- CWindow* pw;
-
- if ( !m_object->RetSelect() ) return;
-
- CAuto::UpdateInterface();
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
-}
-
-
-// Freeze or frees all cargo.
-
-void CAutoBase::FreezeCargo(bool bFreeze)
-{
- CObject* pObj;
- CPhysics* physics;
- Math::Vector oPos;
- float dist;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- pObj->SetCargo(false);
-
- if ( pObj == m_object ) continue; // yourself?
- if ( pObj->RetTruck() != 0 ) continue; // transport object?
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(m_pos, oPos);
- if ( dist < 32.0f )
- {
- if ( bFreeze )
- {
- pObj->SetCargo(true);
- }
-
- physics = pObj->RetPhysics();
- if ( physics != 0 )
- {
- physics->SetFreeze(bFreeze);
- }
- }
- }
-}
-
-// All cargo moves vertically with the ship.
-
-void CAutoBase::MoveCargo()
-{
- CObject* pObj;
- Math::Vector oPos, sPos;
- int i;
-
- sPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetCargo() ) continue;
-
- oPos = pObj->RetPosition(0);
- oPos.y = sPos.y+30.0f;
- oPos.y += pObj->RetCharacter()->height;
- oPos.x += sPos.x-m_lastPos.x;
- oPos.z += sPos.z-m_lastPos.z;
- pObj->SetPosition(0, oPos);
- }
-
- m_lastPos = sPos;
-}
-
-
-// Checks whether it is possible to close the doors.
-
-Error CAutoBase::CheckCloseDoor()
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- float oRad, dist;
- int i, j;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue; // yourself?
- if ( !pObj->RetActif() ) continue; // inactive?
-
- type = pObj->RetType();
- if ( type == OBJECT_PORTICO ) continue;
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRad) )
- {
- dist = Math::DistanceProjected(m_pos, oPos);
- if ( dist+oRad > 32.0f &&
- dist-oRad < 72.0f )
- {
- return ERR_BASE_DLOCK;
- }
-
- if ( type == OBJECT_HUMAN &&
- dist+oRad > 32.0f )
- {
- return ERR_BASE_DHUMAN;
- }
- }
- }
- return ERR_OK;
-}
-
-
-// Start a transit.
-
-void CAutoBase::BeginTransit()
-{
- bool bFull, bQuarter;
-
- if ( m_param == PARAM_TRANSIT2 )
- {
- strcpy(m_bgBack, "back01.tga"); // clouds orange / blue
- }
- else if ( m_param == PARAM_TRANSIT3 )
- {
- strcpy(m_bgBack, "back22.tga"); // blueberries clouds
- }
- else
- {
-#if _DEMO
- strcpy(m_bgBack, "back46b.tga"); // paintings
-#else
- strcpy(m_bgBack, "back46.tga"); // paintings
-#endif
- }
-
- m_engine->SetFogStart(0.9f); // hardly any fog
- m_engine->SetDeepView(2000.0f); // we see very far
- m_engine->ApplyChange();
-
- m_engine->RetBackground(m_bgName, m_bgUp, m_bgDown, m_bgCloudUp, m_bgCloudDown, bFull, bQuarter);
- m_engine->FreeTexture(m_bgName);
-
- m_engine->SetBackground(m_bgBack, 0x00000000, 0x00000000, 0x00000000, 0x00000000);
- m_engine->LoadTexture(m_bgBack);
-
- m_cloud->SetEnable(false); // cache clouds
- m_planet->SetMode(1);
-}
-
-// End of a transit.
-
-void CAutoBase::EndTransit()
-{
- m_engine->SetFogStart(m_fogStart); // gives initial fog
- m_engine->SetDeepView(m_deepView); // gives initial depth
- m_engine->ApplyChange();
-
- m_engine->FreeTexture(m_bgBack);
-
- m_engine->SetBackground(m_bgName, m_bgUp, m_bgDown, m_bgCloudUp, m_bgCloudDown);
- m_engine->LoadTexture(m_bgName);
-
- m_cloud->SetEnable(true); // gives the clouds
- m_planet->SetMode(0);
-
- m_main->StartMusic();
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autobase.h"
+
+#include "common/iman.h"
+#include "old/terrain.h"
+#include "old/cloud.h"
+#include "old/planet.h"
+#include "old/blitz.h"
+#include "math/geometry.h"
+#include "object/robotmain.h"
+#include "physics/physics.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+
+
+
+const float BASE_LAND_TIME = 7.5f; // hard landing
+const float BASE_TAKO_TIME = 10.0f; // hard landing
+const float BASE_DOOR_TIME = 6.0f; // time opening / closing
+const float BASE_DOOR_TIME2 = 2.0f; // time opening / closing suppl.
+const float BASE_PORTICO_TIME_MOVE = 16.0f; // gate advance time
+const float BASE_PORTICO_TIME_DOWN = 4.0f; // gate length down
+const float BASE_PORTICO_TIME_OPEN = 4.0f; // gate opening duration
+const float BASE_TRANSIT_TIME = 15.0f; // transit duration
+
+
+
+
+// Object's constructor.
+
+CAutoBase::CAutoBase(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ m_fogStart = m_engine->RetFogStart();
+ m_deepView = m_engine->RetDeepView();
+ Init();
+ m_phase = ABP_WAIT;
+ m_soundChannel = -1;
+}
+
+// Object's destructor.
+
+CAutoBase::~CAutoBase()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoBase::DeleteObject(bool bAll)
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoBase::Init()
+{
+ m_bOpen = false;
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+ m_lastMotorParticule = 0.0f;
+
+ m_pos = m_object->RetPosition(0);
+ m_lastPos = m_pos;
+
+ m_phase = ABP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+}
+
+
+// Start the object.
+
+void CAutoBase::Start(int param)
+{
+ m_phase = ABP_START;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ m_param = param;
+}
+
+
+// Management of an event.
+
+bool CAutoBase::EventProcess(const Event &event)
+{
+ Math::Matrix* mat;
+ Event newEvent;
+ CObject* pObj;
+ Math::Vector pos, speed, vibCir, iPos;
+ Math::Point dim, p;
+ Error err;
+ float angle, dist, time, h, len, vSpeed;
+ int i, max;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+
+begin:
+ iPos = m_object->RetPosition(0);
+
+ if ( m_phase == ABP_START )
+ {
+ if ( m_param != PARAM_STOP && // not placed on the ground?
+ m_param != PARAM_FIXSCENE )
+ {
+ FreezeCargo(true); // freeze whole cargo
+ }
+
+ if ( m_param == PARAM_STOP ) // raises the ground?
+ {
+ m_phase = ABP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
+ m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
+ m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
+ m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
+ m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
+ }
+
+ pObj = m_main->RetSelectObject();
+ m_main->SelectObject(pObj);
+ m_camera->SetObject(pObj);
+ if ( pObj == 0 )
+ {
+ m_camera->SetType(CAMERA_BACK);
+ }
+ else
+ {
+ m_camera->SetType(pObj->RetCameraType());
+ m_camera->SetDist(pObj->RetCameraDist());
+ }
+
+ m_main->StartMusic();
+ }
+
+ if ( m_param == PARAM_FIXSCENE ) // raises the ground?
+ {
+ m_phase = ABP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
+ m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
+ m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
+ m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
+ m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
+ }
+ }
+
+ if ( m_param == PARAM_LANDING ) // Landing?
+ {
+ m_phase = ABP_LAND;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_LAND_TIME;
+
+ m_main->SetMovieLock(true); // blocks everything until the end of the landing
+ m_bMotor = true; // lights the jet engine
+
+ m_camera->SetType(CAMERA_SCRIPT);
+
+ pos = m_pos;
+ pos.x -= 150.0f;
+ m_terrain->MoveOnFloor(pos);
+ pos.y += 10.0f;
+ m_camera->SetScriptEye(pos);
+ m_posSound = pos;
+
+ pos = m_object->RetPosition(0);
+ pos.y += 300.0f+50.0f;
+ m_camera->SetScriptLookat(pos);
+
+ m_camera->FixCamera();
+ m_engine->SetFocus(2.0f);
+
+ m_engine->SetFogStart(0.9f);
+
+ if ( m_soundChannel == -1 )
+ {
+ m_soundChannel = m_sound->Play(SOUND_FLY, m_posSound, 0.3f, 2.0f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, BASE_LAND_TIME, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 2.0f, SOPER_STOP);
+ }
+
+ m_main->StartMusic();
+ }
+
+ if ( m_param == PARAM_PORTICO ) // gate on the porch?
+ {
+ pos = m_object->RetPosition(0);
+ m_finalPos = pos;
+ pos.z += BASE_PORTICO_TIME_MOVE*5.0f; // back
+ pos.y += 10.0f; // rises (the gate)
+ m_object->SetPosition(0, pos);
+ MoveCargo(); // all cargo moves
+
+ m_phase = ABP_PORTICO_MOVE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_PORTICO_TIME_MOVE;
+
+ m_main->StartMusic();
+ }
+
+ if ( m_param == PARAM_TRANSIT1 ||
+ m_param == PARAM_TRANSIT2 ||
+ m_param == PARAM_TRANSIT3 ) // transit in space?
+ {
+ m_phase = ABP_TRANSIT_MOVE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_TRANSIT_TIME;
+
+ m_object->SetAngleZ(0, -Math::PI/2.0f);
+ pos = m_object->RetPosition(0);
+ pos.y += 10000.0f; // in space
+ m_finalPos = pos;
+ m_object->SetPosition(0, pos);
+
+ m_main->SetMovieLock(true); // blocks everything until the end of the landing
+ m_bMotor = true; // lights the jet engine
+
+ m_camera->SetType(CAMERA_SCRIPT);
+ pos.x += 1000.0f;
+ pos.z -= 60.0f;
+ pos.y += 80.0f;
+ m_camera->SetScriptEye(pos);
+ m_posSound = pos;
+ m_camera->FixCamera();
+ m_engine->SetFocus(1.0f);
+
+ BeginTransit();
+
+ mat = m_object->RetWorldMatrix(0);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 10.0f;
+ dim.y = dim.x;
+ pos = Math::Vector(42.0f, -2.0f, 17.0f);
+ pos = Transform(*mat, pos);
+ m_partiChannel[0] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
+ pos = Math::Vector(17.0f, -2.0f, 42.0f);
+ pos = Transform(*mat, pos);
+ m_partiChannel[1] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
+ pos = Math::Vector(42.0f, -2.0f, -17.0f);
+ pos = Transform(*mat, pos);
+ m_partiChannel[2] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
+ pos = Math::Vector(17.0f, -2.0f, -42.0f);
+ pos = Transform(*mat, pos);
+ m_partiChannel[3] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
+ pos = Math::Vector(-42.0f, -2.0f, 17.0f);
+ pos = Transform(*mat, pos);
+ m_partiChannel[4] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
+ pos = Math::Vector(-17.0f, -2.0f, 42.0f);
+ pos = Transform(*mat, pos);
+ m_partiChannel[5] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
+ pos = Math::Vector(-42.0f, -2.0f, -17.0f);
+ pos = Transform(*mat, pos);
+ m_partiChannel[6] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
+ pos = Math::Vector(-17.0f, -2.0f, -42.0f);
+ pos = Transform(*mat, pos);
+ m_partiChannel[7] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
+
+ if ( m_soundChannel == -1 )
+ {
+ m_soundChannel = m_sound->Play(SOUND_FLY, m_posSound, 0.0f, 1.2f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, BASE_TRANSIT_TIME*0.55f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.8f, BASE_TRANSIT_TIME*0.45f, SOPER_STOP);
+ }
+ }
+ }
+
+ if ( event.event == EVENT_UPDINTERFACE )
+ {
+ if ( m_object->RetSelect() ) CreateInterface(true);
+ }
+
+ if ( event.event == EVENT_OBJECT_BTAKEOFF )
+ {
+ err = CheckCloseDoor();
+ if ( err != ERR_OK )
+ {
+ m_displayText->DisplayError(err, m_object);
+ return false;
+ }
+
+ err = m_main->CheckEndMission(false);
+ if ( err != ERR_OK )
+ {
+ m_displayText->DisplayError(err, m_object);
+ return false;
+ }
+
+ FreezeCargo(true); // freeze whole cargo
+ m_main->SetMovieLock(true); // blocks everything until the end
+ m_main->DeselectAll();
+
+ m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
+ m_event->AddEvent(newEvent);
+
+ m_camera->SetType(CAMERA_SCRIPT);
+
+ pos = m_pos;
+ pos.x -= 110.0f;
+ m_terrain->MoveOnFloor(pos);
+ pos.y += 10.0f;
+ m_camera->SetScriptEye(pos);
+ m_posSound = pos;
+
+ pos = m_object->RetPosition(0);
+ pos.y += 50.0f;
+ m_camera->SetScriptLookat(pos);
+
+ m_engine->SetFocus(1.0f);
+
+ m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.3f, 1.5f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.5f, BASE_DOOR_TIME2, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.5f, 0.5f, SOPER_STOP);
+
+ m_phase = ABP_CLOSE2;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_DOOR_TIME2;
+ return true;
+ }
+
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_phase == ABP_WAIT ) return true;
+
+ m_progress += event.rTime*m_speed;
+
+ if ( m_phase == ABP_LAND )
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos = m_pos;
+ pos.y += powf(1.0f-m_progress, 2.0f)*300.0f;
+ m_object->SetPosition(0, pos);
+ MoveCargo(); // all cargo moves
+
+ vibCir.z = sinf(m_time*Math::PI* 2.01f)*(Math::PI/150.0f)+
+ sinf(m_time*Math::PI* 2.51f)*(Math::PI/200.0f)+
+ sinf(m_time*Math::PI*19.01f)*(Math::PI/400.0f);
+ vibCir.x = sinf(m_time*Math::PI* 2.03f)*(Math::PI/150.0f)+
+ sinf(m_time*Math::PI* 2.52f)*(Math::PI/200.0f)+
+ sinf(m_time*Math::PI*19.53f)*(Math::PI/400.0f);
+ vibCir.y = 0.0f;
+ vibCir *= Math::Min(1.0f, (1.0f-m_progress)*3.0f);
+ m_object->SetCirVibration(vibCir);
+
+ pos = m_pos;
+ pos.x -= 150.0f;
+ m_terrain->MoveOnFloor(pos);
+ pos.y += 10.0f;
+ m_camera->SetScriptEye(pos);
+
+ pos = m_object->RetPosition(0);
+ pos.y += 50.0f;
+ m_camera->SetScriptLookat(pos);
+
+ m_engine->SetFocus(1.0f+(1.0f-m_progress));
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ // Dust thrown to the ground.
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ angle = Math::Rand()*(Math::PI*2.0f);
+ dist = m_progress*50.0f;
+ p = Math::RotatePoint(angle, dist);
+ speed.x = p.x;
+ speed.z = p.y;
+ speed.y = 0.0f;
+ dim.x = (Math::Rand()*15.0f+15.0f)*m_progress;
+ dim.y = dim.x;
+ if ( dim.x >= 1.0f )
+ {
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 2.0f);
+ }
+
+ // Particles are ejected from the jet engine.
+ pos = m_object->RetPosition(0);
+ pos.y += 6.0f;
+ h = m_terrain->RetFloorHeight(pos)/300.0f;
+ speed.x = (Math::Rand()-0.5f)*(80.0f-50.0f*h);
+ speed.z = (Math::Rand()-0.5f)*(80.0f-50.0f*h);
+ speed.y = -(Math::Rand()*(h+1.0f)*40.0f+(h+1.0f)*40.0f);
+ dim.x = Math::Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 2.0f, 10.0f, 2.0f);
+
+ // Black smoke from the jet engine.
+ if ( m_progress > 0.8f )
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*8.0f;
+ pos.z += (Math::Rand()-0.5f)*8.0f;
+ pos.y += 3.0f;
+ speed.x = (Math::Rand()-0.5f)*8.0f;
+ speed.z = (Math::Rand()-0.5f)*8.0f;
+ speed.y = 0.0f;
+ dim.x = Math::Rand()*4.0f+4.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 2.0f);
+ }
+ }
+ }
+ else
+ {
+ m_bMotor = false; // put out the reactor
+
+ m_object->SetPosition(0, m_pos); // setting down
+ m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ MoveCargo(); // all cargo moves
+
+ // Impact with the ground.
+ max = (int)(50.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<max ; i++ )
+ {
+ angle = Math::Rand()*(Math::PI*2.0f);
+ p = Math::RotatePoint(angle, 46.0f);
+ pos = m_pos;
+ pos.x += p.x;
+ pos.z += p.y;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*10.0f+10.0f;
+ dim.y = dim.x;
+ time = Math::Rand()*2.0f+1.5f;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, time, 0.0f, 2.0f);
+ }
+
+//? m_camera->StartEffect(CE_CRASH, m_pos, 1.0f);
+ m_camera->StartEffect(CE_EXPLO, m_pos, 2.0f);
+ m_engine->SetFocus(1.0f);
+ m_sound->Play(SOUND_BOUM, m_posSound, 0.6f, 0.5f);
+
+ m_phase = ABP_OPENWAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == ABP_OPENWAIT )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ // Black smoke from the reactor.
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*8.0f;
+ pos.z += (Math::Rand()-0.5f)*8.0f;
+ pos.y += 3.0f;
+ speed.x = (Math::Rand()-0.5f)*8.0f;
+ speed.z = (Math::Rand()-0.5f)*8.0f;
+ speed.y = 0.0f;
+ dim.x = Math::Rand()*4.0f+4.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 2.0f);
+ }
+ }
+ else
+ {
+ m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.0f, 0.3f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.3f, 1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.0f, BASE_DOOR_TIME-1.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 1.0f, SOPER_STOP);
+
+ m_phase = ABP_OPEN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_DOOR_TIME;
+ }
+ }
+
+ if ( m_phase == ABP_OPEN )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = -m_progress*124.0f*Math::PI/180.0f;
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, Math::PI/2.0f+angle);
+ }
+
+ if ( m_param != PARAM_PORTICO )
+ {
+ angle = m_progress*Math::PI*2.0f;
+ p = Math::RotatePoint(angle, -150.0f);
+ pos = m_pos;
+ pos.x += p.x;
+ pos.z += p.y;
+ m_terrain->MoveOnFloor(pos);
+ pos.y += 10.0f;
+ pos.y += m_progress*40.0f;
+ m_camera->SetScriptEye(pos);
+
+ m_engine->SetFogStart(0.9f-(0.9f-m_fogStart)*m_progress);
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
+ }
+
+ // Clash the doors with the ground.
+ max = (int)(20.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<max ; i++ )
+ {
+ angle = Math::Rand()*(20.0f*Math::PI/180.0f)-(10.0f*Math::PI/180.0f);
+ angle += (Math::PI/4.0f)*(rand()%8);
+ p = Math::RotatePoint(angle, 74.0f);
+ pos = m_pos;
+ pos.x += p.x;
+ pos.z += p.y;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*8.0f+8.0f;
+ dim.y = dim.x;
+ time = Math::Rand()*2.0f+1.5f;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, time, 0.0f, 2.0f);
+ }
+
+ m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.3f, 1.5f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.5f, BASE_DOOR_TIME2, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.5f, 0.5f, SOPER_STOP);
+
+ m_phase = ABP_OPEN2;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_DOOR_TIME2;
+ }
+ }
+
+ if ( m_phase == ABP_OPEN2 )
+ {
+ if ( m_progress < 1.0f )
+ {
+ len = 7.0f-m_progress*(7.0f+11.5f);
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, len));
+ m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, -len));
+ m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f*m_progress);
+ m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f*m_progress);
+ }
+
+ if ( m_param != PARAM_PORTICO )
+ {
+ angle = m_progress*Math::PI/2.0f;
+ p = Math::RotatePoint(angle, -150.0f);
+ pos = m_pos;
+ pos.x += p.x;
+ pos.z += p.y;
+ m_terrain->MoveOnFloor(pos);
+ pos.y += 10.0f;
+ pos.y += m_progress*40.0f;
+ m_camera->SetScriptEye(pos);
+
+ m_engine->SetFogStart(0.9f-(0.9f-m_fogStart)*m_progress);
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
+ m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
+ m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
+ m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
+ }
+
+ m_phase = ABP_LDWAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ABP_LDWAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ FreezeCargo(false); // frees all cargo
+
+ if ( m_param != PARAM_PORTICO )
+ {
+ m_main->SetMovieLock(false); // you can play!
+
+ pObj = m_main->RetSelectObject();
+ m_main->SelectObject(pObj);
+ m_camera->SetObject(pObj);
+ if ( pObj == 0 )
+ {
+ m_camera->SetType(CAMERA_BACK);
+ }
+ else
+ {
+ m_camera->SetType(pObj->RetCameraType());
+ m_camera->SetDist(pObj->RetCameraDist());
+ }
+ m_sound->Play(SOUND_BOUM, m_object->RetPosition(0));
+ m_soundChannel = -1;
+
+ m_engine->SetFogStart(m_fogStart);
+ }
+
+ m_bOpen = true;
+ m_phase = ABP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ABP_CLOSE2 )
+ {
+ if ( m_progress < 1.0f )
+ {
+ len = 7.0f-(1.0f-m_progress)*(7.0f+11.5f);
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, len));
+ m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, -len));
+ m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f*(1.0f-m_progress));
+ m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f*(1.0f-m_progress));
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, 7.0f));
+ m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, -7.0f));
+ m_object->SetAngleX(10+i, 0.0f);
+ m_object->SetAngleX(18+i, 0.0f);
+ }
+
+ m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.0f, 0.3f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.3f, 1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.0f, BASE_DOOR_TIME-1.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 1.0f, SOPER_STOP);
+
+ m_phase = ABP_CLOSE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_DOOR_TIME;
+ }
+ }
+
+ if ( m_phase == ABP_CLOSE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = -(1.0f-m_progress)*124.0f*Math::PI/180.0f;
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, Math::PI/2.0f+angle);
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, Math::PI/2.0f);
+ }
+ m_bMotor = true; // lights the jet engine
+
+ // Shock of the closing doors.
+ max = (int)(20.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<max ; i++ )
+ {
+ angle = Math::Rand()*Math::PI*2.0f;
+ p = Math::RotatePoint(angle, 32.0f);
+ pos = m_pos;
+ pos.x += p.x;
+ pos.z += p.y;
+ pos.y += 85.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*3.0f+3.0f;
+ dim.y = dim.x;
+ time = Math::Rand()*1.0f+1.0f;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, time);
+ }
+ m_sound->Play(SOUND_BOUM, m_object->RetPosition(0));
+
+ m_soundChannel = -1;
+ m_bOpen = false;
+ m_phase = ABP_TOWAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == ABP_TOWAIT )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_soundChannel == -1 )
+ {
+ m_soundChannel = m_sound->Play(SOUND_FLY, m_posSound, 0.0f, 0.5f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 2.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 2.0f, BASE_TAKO_TIME, SOPER_STOP);
+ }
+
+ vibCir.z = sinf(m_time*Math::PI*19.01f)*(Math::PI/400.0f);
+ vibCir.x = sinf(m_time*Math::PI*19.53f)*(Math::PI/400.0f);
+ vibCir.y = 0.0f;
+ vibCir *= m_progress*1.0f;
+ m_object->SetCirVibration(vibCir);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ // Particles are ejected from the reactor.
+ pos = m_object->RetPosition(0);
+ pos.y += 6.0f;
+ speed.x = (Math::Rand()-0.5f)*160.0f;
+ speed.z = (Math::Rand()-0.5f)*160.0f;
+ speed.y = -(Math::Rand()*10.0f+10.0f);
+ dim.x = Math::Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 2.0f, 10.0f, 2.0f);
+ }
+
+ m_engine->SetFogStart(m_fogStart+(0.9f-m_fogStart)*m_progress);
+ }
+ else
+ {
+ m_engine->SetFogStart(0.9f);
+
+ m_phase = ABP_TAKEOFF;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_TAKO_TIME;
+ }
+ }
+
+ if ( m_phase == ABP_TAKEOFF )
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos = m_pos;
+ pos.y += powf(m_progress, 2.0f)*600.0f;
+ m_object->SetPosition(0, pos);
+ MoveCargo(); // all cargo moves
+
+ vibCir.z = sinf(m_time*Math::PI*19.01f)*(Math::PI/400.0f);
+ vibCir.x = sinf(m_time*Math::PI*19.53f)*(Math::PI/400.0f);
+ vibCir.y = 0.0f;
+ m_object->SetCirVibration(vibCir);
+
+ pos = m_pos;
+ pos.x -= 110.0f+m_progress*250.0f;
+ m_terrain->MoveOnFloor(pos);
+ pos.y += 10.0f;
+ m_camera->SetScriptEye(pos);
+
+ pos = m_object->RetPosition(0);
+ pos.y += 50.0f;
+ m_camera->SetScriptLookat(pos);
+
+ m_engine->SetFocus(1.0f+m_progress);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ // Dust thrown to the ground.
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ angle = Math::Rand()*(Math::PI*2.0f);
+ dist = (1.0f-m_progress)*50.0f;
+ p = Math::RotatePoint(angle, dist);
+ speed.x = p.x;
+ speed.z = p.y;
+ speed.y = 0.0f;
+ dim.x = (Math::Rand()*10.0f+10.0f)*(1.0f-m_progress);
+ dim.y = dim.x;
+ if ( dim.x >= 1.0f )
+ {
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 2.0f);
+ }
+
+ // Particles are ejected from the reactor.
+ pos = m_object->RetPosition(0);
+ pos.y += 6.0f;
+ speed.x = (Math::Rand()-0.5f)*40.0f;
+ speed.z = (Math::Rand()-0.5f)*40.0f;
+ time = 5.0f+150.0f*m_progress;
+ speed.y = -(Math::Rand()*time+time);
+ time = 2.0f+m_progress*12.0f;
+ dim.x = Math::Rand()*time+time;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 2.0f, 10.0f, 2.0f);
+
+ // Black smoke from the reactor.
+ pos = m_object->RetPosition(0);
+ pos.y += 3.0f;
+ speed.x = (Math::Rand()-0.5f)*10.0f*(4.0f-m_progress*3.0f);
+ speed.z = (Math::Rand()-0.5f)*10.0f*(4.0f-m_progress*3.0f);
+ speed.y = 0.0f;
+ dim.x = Math::Rand()*20.0f+20.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 10.0f, 0.0f, 2.0f);
+ }
+ }
+ else
+ {
+ m_soundChannel = -1;
+ m_event->MakeEvent(newEvent, EVENT_WIN);
+ m_event->AddEvent(newEvent);
+
+ m_phase = ABP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == ABP_PORTICO_MOVE ) // advance of the gate?
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos = m_object->RetPosition(0);
+ pos.z -= event.rTime*5.0f;
+ m_object->SetPosition(0, pos);
+ MoveCargo(); // all cargo moves
+ }
+ else
+ {
+ m_phase = ABP_PORTICO_WAIT1;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ABP_PORTICO_WAIT1 ) // expectation the gate?
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_phase = ABP_PORTICO_DOWN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_PORTICO_TIME_DOWN;
+ }
+ }
+
+ if ( m_phase == ABP_PORTICO_DOWN ) // down the gate?
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos = m_object->RetPosition(0);
+ pos.y -= event.rTime*(10.0f/BASE_PORTICO_TIME_DOWN);
+ m_object->SetPosition(0, pos);
+ MoveCargo(); // all cargo moves
+ }
+ else
+ {
+ // Impact with the ground.
+ max = (int)(50.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<max ; i++ )
+ {
+ angle = Math::Rand()*(Math::PI*2.0f);
+ p = Math::RotatePoint(angle, 46.0f);
+ pos = m_pos;
+ pos.x += p.x;
+ pos.z += p.y;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*10.0f+10.0f;
+ dim.y = dim.x;
+ time = Math::Rand()*2.0f+1.5f;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, time, 0.0f, 2.0f);
+ }
+
+ m_phase = ABP_PORTICO_WAIT2;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ABP_PORTICO_WAIT2 ) // expectation the gate?
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_phase = ABP_PORTICO_OPEN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_PORTICO_TIME_OPEN;
+ }
+ }
+
+ if ( m_phase == ABP_PORTICO_OPEN ) // opening the gate?
+ {
+ if ( m_progress < 1.0f )
+ {
+ }
+ else
+ {
+ m_phase = ABP_OPEN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == ABP_TRANSIT_MOVE ) // transit in space?
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += event.rTime*(2000.0f/BASE_TRANSIT_TIME);
+ m_object->SetPosition(0, pos);
+ pos.x += 60.0f;
+ m_camera->SetScriptLookat(pos);
+ }
+ else
+ {
+ m_object->SetAngleZ(0, 0.0f);
+
+ m_param = PARAM_LANDING;
+ m_phase = ABP_START;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ EndTransit();
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.8f, 0.01f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+ goto begin;
+ }
+ }
+
+ if ( m_bMotor )
+ {
+ if ( m_lastMotorParticule+m_engine->ParticuleAdapt(0.02f) <= m_time )
+ {
+ m_lastMotorParticule = m_time;
+
+ mat = m_object->RetWorldMatrix(0);
+
+ if ( event.rTime == 0.0f )
+ {
+ vSpeed = 0.0f;
+ }
+ else
+ {
+ pos = m_object->RetPosition(0);
+ if ( m_phase == ABP_TRANSIT_MOVE )
+ {
+ vSpeed = (pos.x-iPos.x)/event.rTime;
+ }
+ else
+ {
+ vSpeed = (pos.y-iPos.y)/event.rTime;
+ }
+ if ( vSpeed < 0.0f ) vSpeed *= 1.5f;
+ }
+
+ pos = Math::Vector(0.0f, 6.0f, 0.0f);
+ speed.x = (Math::Rand()-0.5f)*4.0f;
+ speed.z = (Math::Rand()-0.5f)*4.0f;
+ speed.y = vSpeed*0.8f-(8.0f+Math::Rand()*6.0f);
+ speed += pos;
+ pos = Transform(*mat, pos);
+ speed = Transform(*mat, speed);
+ speed -= pos;
+
+ dim.x = 4.0f+Math::Rand()*4.0f;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTIBASE, 3.0f, 0.0f, 0.0f);
+
+ if ( m_phase == ABP_TRANSIT_MOVE )
+ {
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 12.0f;
+ dim.y = dim.x;
+ pos = Math::Vector(0.0f, 7.0f, 0.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 1.0f, 0.0f, 0.0f);
+
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 4.0f;
+ dim.y = dim.x;
+ pos = Math::Vector(42.0f, 0.0f, 17.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = Math::Vector(17.0f, 0.0f, 42.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = Math::Vector(42.0f, 0.0f, -17.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = Math::Vector(17.0f, 0.0f, -42.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = Math::Vector(-42.0f, 0.0f, 17.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = Math::Vector(-17.0f, 0.0f, 42.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = Math::Vector(-42.0f, 0.0f, -17.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = Math::Vector(-17.0f, 0.0f, -42.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+
+ pos = Math::Vector(42.0f, -2.0f, 17.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[0], pos);
+ pos = Math::Vector(17.0f, -2.0f, 42.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[1], pos);
+ pos = Math::Vector(42.0f, -2.0f, -17.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[2], pos);
+ pos = Math::Vector(17.0f, -2.0f, -42.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[3], pos);
+ pos = Math::Vector(-42.0f, -2.0f, 17.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[4], pos);
+ pos = Math::Vector(-17.0f, -2.0f, 42.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[5], pos);
+ pos = Math::Vector(-42.0f, -2.0f, -17.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[6], pos);
+ pos = Math::Vector(-17.0f, -2.0f, -42.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[7], pos);
+ }
+ }
+ }
+
+ if ( m_soundChannel != -1 )
+ {
+ pos = m_engine->RetEyePt();
+ m_sound->Position(m_soundChannel, pos);
+ }
+
+ return true;
+}
+
+// Stops the controller.
+
+bool CAutoBase::Abort()
+{
+ Event newEvent;
+ CObject* pObj;
+ int i;
+
+ if ( m_phase == ABP_TRANSIT_MOVE ) // transit ?
+ {
+ m_object->SetAngleZ(0, 0.0f);
+
+ m_param = PARAM_LANDING;
+ m_phase = ABP_START;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ EndTransit();
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.8f, 0.01f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+ return true;
+ }
+
+ if ( m_param == PARAM_PORTICO ) // gate on the porch?
+ {
+ m_object->SetPosition(0, m_finalPos);
+ MoveCargo(); // all cargo moves
+
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
+ m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
+ m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
+ m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
+ m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
+ }
+ }
+ else
+ {
+ if ( m_phase == ABP_LAND ||
+ m_phase == ABP_OPENWAIT ||
+ m_phase == ABP_OPEN ||
+ m_phase == ABP_OPEN2 ) // Landing?
+ {
+ m_bMotor = false; // put out the jet engine
+ m_bOpen = true;
+
+ m_object->SetPosition(0, m_pos); // setting down
+ m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ MoveCargo(); // all cargo moves
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
+ m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
+ m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
+ m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
+ m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
+ }
+
+ m_main->SetMovieLock(false); // you can play!
+
+ pObj = m_main->RetSelectObject();
+ m_main->SelectObject(pObj);
+ m_camera->SetObject(pObj);
+ if ( pObj == 0 )
+ {
+ m_camera->SetType(CAMERA_BACK);
+ }
+ else
+ {
+ m_camera->SetType(pObj->RetCameraType());
+ m_camera->SetDist(pObj->RetCameraDist());
+ }
+
+ m_engine->SetFogStart(m_fogStart);
+ }
+
+ if ( m_phase == ABP_CLOSE2 ||
+ m_phase == ABP_CLOSE ||
+ m_phase == ABP_TOWAIT ||
+ m_phase == ABP_TAKEOFF ) // off?
+ {
+ m_event->MakeEvent(newEvent, EVENT_WIN);
+ m_event->AddEvent(newEvent);
+ }
+ }
+
+ m_object->SetAngleZ(0, 0.0f);
+ FreezeCargo(false); // frees all cargo
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ m_phase = ABP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoBase::RetError()
+{
+ return ERR_OK;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoBase::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, dim, ddim;
+ float ox, oy, sx, sy;
+ float sleep, delay, magnetic, progress;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ dim.x = 33.0f/640.0f;
+ dim.y = 33.0f/480.0f;
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ ddim.x = dim.x*1.5f;
+ ddim.y = dim.y*1.5f;
+
+//? pos.x = ox+sx*7.25f;
+//? pos.y = oy+sy*0.25f;
+//? pw->CreateButton(pos, ddim, 63, EVENT_OBJECT_BHELP);
+
+ pos.x = ox+sx*8.00f;
+ pos.y = oy+sy*0.25f;
+ pw->CreateButton(pos, ddim, 28, EVENT_OBJECT_BTAKEOFF);
+
+ if ( m_blitz->GetStatus(sleep, delay, magnetic, progress) )
+ {
+ pos.x = ox+sx*10.2f;
+ pos.y = oy+sy*0.5f;
+ ddim.x = dim.x*1.0f;
+ ddim.y = dim.y*1.0f;
+ pw->CreateButton(pos, ddim, 41, EVENT_OBJECT_LIMIT);
+ }
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 100, EVENT_OBJECT_TYPE);
+
+ UpdateInterface();
+
+ return true;
+}
+
+// Updates the status of all interface buttons.
+
+void CAutoBase::UpdateInterface()
+{
+ CWindow* pw;
+
+ if ( !m_object->RetSelect() ) return;
+
+ CAuto::UpdateInterface();
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+}
+
+
+// Freeze or frees all cargo.
+
+void CAutoBase::FreezeCargo(bool bFreeze)
+{
+ CObject* pObj;
+ CPhysics* physics;
+ Math::Vector oPos;
+ float dist;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ pObj->SetCargo(false);
+
+ if ( pObj == m_object ) continue; // yourself?
+ if ( pObj->RetTruck() != 0 ) continue; // transport object?
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(m_pos, oPos);
+ if ( dist < 32.0f )
+ {
+ if ( bFreeze )
+ {
+ pObj->SetCargo(true);
+ }
+
+ physics = pObj->RetPhysics();
+ if ( physics != 0 )
+ {
+ physics->SetFreeze(bFreeze);
+ }
+ }
+ }
+}
+
+// All cargo moves vertically with the ship.
+
+void CAutoBase::MoveCargo()
+{
+ CObject* pObj;
+ Math::Vector oPos, sPos;
+ int i;
+
+ sPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetCargo() ) continue;
+
+ oPos = pObj->RetPosition(0);
+ oPos.y = sPos.y+30.0f;
+ oPos.y += pObj->RetCharacter()->height;
+ oPos.x += sPos.x-m_lastPos.x;
+ oPos.z += sPos.z-m_lastPos.z;
+ pObj->SetPosition(0, oPos);
+ }
+
+ m_lastPos = sPos;
+}
+
+
+// Checks whether it is possible to close the doors.
+
+Error CAutoBase::CheckCloseDoor()
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ ObjectType type;
+ float oRad, dist;
+ int i, j;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue; // yourself?
+ if ( !pObj->RetActif() ) continue; // inactive?
+
+ type = pObj->RetType();
+ if ( type == OBJECT_PORTICO ) continue;
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRad) )
+ {
+ dist = Math::DistanceProjected(m_pos, oPos);
+ if ( dist+oRad > 32.0f &&
+ dist-oRad < 72.0f )
+ {
+ return ERR_BASE_DLOCK;
+ }
+
+ if ( type == OBJECT_HUMAN &&
+ dist+oRad > 32.0f )
+ {
+ return ERR_BASE_DHUMAN;
+ }
+ }
+ }
+ return ERR_OK;
+}
+
+
+// Start a transit.
+
+void CAutoBase::BeginTransit()
+{
+ bool bFull, bQuarter;
+
+ if ( m_param == PARAM_TRANSIT2 )
+ {
+ strcpy(m_bgBack, "back01.tga"); // clouds orange / blue
+ }
+ else if ( m_param == PARAM_TRANSIT3 )
+ {
+ strcpy(m_bgBack, "back22.tga"); // blueberries clouds
+ }
+ else
+ {
+#if _DEMO
+ strcpy(m_bgBack, "back46b.tga"); // paintings
+#else
+ strcpy(m_bgBack, "back46.tga"); // paintings
+#endif
+ }
+
+ m_engine->SetFogStart(0.9f); // hardly any fog
+ m_engine->SetDeepView(2000.0f); // we see very far
+ m_engine->ApplyChange();
+
+ m_engine->RetBackground(m_bgName, m_bgUp, m_bgDown, m_bgCloudUp, m_bgCloudDown, bFull, bQuarter);
+ m_engine->FreeTexture(m_bgName);
+
+ m_engine->SetBackground(m_bgBack, 0x00000000, 0x00000000, 0x00000000, 0x00000000);
+ m_engine->LoadTexture(m_bgBack);
+
+ m_cloud->SetEnable(false); // cache clouds
+ m_planet->SetMode(1);
+}
+
+// End of a transit.
+
+void CAutoBase::EndTransit()
+{
+ m_engine->SetFogStart(m_fogStart); // gives initial fog
+ m_engine->SetDeepView(m_deepView); // gives initial depth
+ m_engine->ApplyChange();
+
+ m_engine->FreeTexture(m_bgBack);
+
+ m_engine->SetBackground(m_bgName, m_bgUp, m_bgDown, m_bgCloudUp, m_bgCloudDown);
+ m_engine->LoadTexture(m_bgName);
+
+ m_cloud->SetEnable(true); // gives the clouds
+ m_planet->SetMode(0);
+
+ m_main->StartMusic();
+}
+
diff --git a/src/object/auto/autobase.h b/src/object/auto/autobase.h
index 0f71ef6..eb47a93 100644
--- a/src/object/auto/autobase.h
+++ b/src/object/auto/autobase.h
@@ -1,112 +1,112 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autobase.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoBaseParam
-{
- PARAM_STOP = 0, // run=0 -> stops and open
- PARAM_LANDING = 1, // run=1 -> landing
- PARAM_PORTICO = 2, // run=2 -> gate on the ground
- PARAM_FIXSCENE = 3, // run=3 -> open and stops to win / lost
- PARAM_TRANSIT1 = 11, // run=11 -> transit in space
- PARAM_TRANSIT2 = 12, // run=12 -> transit in space
- PARAM_TRANSIT3 = 13 // run=13 -> transit in space
-};
-
-enum AutoBasePhase
-{
- ABP_WAIT = 1, // expected
- ABP_START = 2, // start-up
-
- ABP_LAND = 3, // landing
- ABP_OPENWAIT = 4, // wait before opening
- ABP_OPEN = 5, // opens the gate
- ABP_OPEN2 = 6, // opens supplements
- ABP_LDWAIT = 7, // expected
-
- ABP_CLOSE2 = 8, // closes supplements
- ABP_CLOSE = 9, // closes gate
- ABP_TOWAIT = 10, // wait before takeoff
- ABP_TAKEOFF = 11, // take-off
-
- ABP_PORTICO_MOVE = 12, // gate advance
- ABP_PORTICO_WAIT1= 13, // gate expected
- ABP_PORTICO_DOWN = 14, // gate down
- ABP_PORTICO_WAIT2= 15, // gate expected
- ABP_PORTICO_OPEN = 16, // gate opens
-
- ABP_TRANSIT_MOVE = 17, // transit - moving
-};
-
-
-
-class CAutoBase : public CAuto
-{
-public:
- CAutoBase(CInstanceManager* iMan, CObject* object);
- ~CAutoBase();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- void Start(int param);
- bool EventProcess(const Event &event);
- bool Abort();
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
-protected:
- void UpdateInterface();
- void FreezeCargo(bool bFreeze);
- void MoveCargo();
- Error CheckCloseDoor();
- void BeginTransit();
- void EndTransit();
-
-protected:
- AutoBasePhase m_phase;
- bool m_bOpen;
- float m_progress;
- float m_speed;
- float m_lastParticule;
- float m_lastMotorParticule;
- float m_fogStart;
- float m_deepView;
- Math::Vector m_pos;
- Math::Vector m_posSound;
- Math::Vector m_finalPos;
- Math::Vector m_lastPos;
- int m_param;
- int m_soundChannel;
- int m_partiChannel[8];
-
- char m_bgBack[100];
- char m_bgName[100];
- D3DCOLOR m_bgUp;
- D3DCOLOR m_bgDown;
- D3DCOLOR m_bgCloudUp;
- D3DCOLOR m_bgCloudDown;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autobase.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoBaseParam
+{
+ PARAM_STOP = 0, // run=0 -> stops and open
+ PARAM_LANDING = 1, // run=1 -> landing
+ PARAM_PORTICO = 2, // run=2 -> gate on the ground
+ PARAM_FIXSCENE = 3, // run=3 -> open and stops to win / lost
+ PARAM_TRANSIT1 = 11, // run=11 -> transit in space
+ PARAM_TRANSIT2 = 12, // run=12 -> transit in space
+ PARAM_TRANSIT3 = 13 // run=13 -> transit in space
+};
+
+enum AutoBasePhase
+{
+ ABP_WAIT = 1, // expected
+ ABP_START = 2, // start-up
+
+ ABP_LAND = 3, // landing
+ ABP_OPENWAIT = 4, // wait before opening
+ ABP_OPEN = 5, // opens the gate
+ ABP_OPEN2 = 6, // opens supplements
+ ABP_LDWAIT = 7, // expected
+
+ ABP_CLOSE2 = 8, // closes supplements
+ ABP_CLOSE = 9, // closes gate
+ ABP_TOWAIT = 10, // wait before takeoff
+ ABP_TAKEOFF = 11, // take-off
+
+ ABP_PORTICO_MOVE = 12, // gate advance
+ ABP_PORTICO_WAIT1= 13, // gate expected
+ ABP_PORTICO_DOWN = 14, // gate down
+ ABP_PORTICO_WAIT2= 15, // gate expected
+ ABP_PORTICO_OPEN = 16, // gate opens
+
+ ABP_TRANSIT_MOVE = 17, // transit - moving
+};
+
+
+
+class CAutoBase : public CAuto
+{
+public:
+ CAutoBase(CInstanceManager* iMan, CObject* object);
+ ~CAutoBase();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ void Start(int param);
+ bool EventProcess(const Event &event);
+ bool Abort();
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+protected:
+ void UpdateInterface();
+ void FreezeCargo(bool bFreeze);
+ void MoveCargo();
+ Error CheckCloseDoor();
+ void BeginTransit();
+ void EndTransit();
+
+protected:
+ AutoBasePhase m_phase;
+ bool m_bOpen;
+ float m_progress;
+ float m_speed;
+ float m_lastParticule;
+ float m_lastMotorParticule;
+ float m_fogStart;
+ float m_deepView;
+ Math::Vector m_pos;
+ Math::Vector m_posSound;
+ Math::Vector m_finalPos;
+ Math::Vector m_lastPos;
+ int m_param;
+ int m_soundChannel;
+ int m_partiChannel[8];
+
+ char m_bgBack[100];
+ char m_bgName[100];
+ D3DCOLOR m_bgUp;
+ D3DCOLOR m_bgDown;
+ D3DCOLOR m_bgCloudUp;
+ D3DCOLOR m_bgCloudDown;
+};
+
diff --git a/src/object/auto/autoconvert.cpp b/src/object/auto/autoconvert.cpp
index ffe7d59..b5ad43a 100644
--- a/src/object/auto/autoconvert.cpp
+++ b/src/object/auto/autoconvert.cpp
@@ -1,527 +1,527 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoconvert.h"
-
-#include "common/iman.h"
-#include "math/geometry.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-
-
-
-
-// Object's constructor.
-
-CAutoConvert::CAutoConvert(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
- m_phase = ACP_STOP;
- m_bResetDelete = false;
- m_soundChannel = -1;
-}
-
-// Object's destructor.
-
-CAutoConvert::~CAutoConvert()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoConvert::DeleteObject(bool bAll)
-{
- CObject* fret;
-
- if ( !bAll )
- {
- fret = SearchStone(OBJECT_STONE);
- if ( fret != 0 )
- {
- fret->DeleteObject(); // destroy the stone
- delete fret;
- }
- }
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoConvert::Init()
-{
- m_phase = ACP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastParticule = 0.0f;
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoConvert::EventProcess(const Event &event)
-{
- CObject* fret;
- Math::Vector pos, speed;
- Math::Point dim, c, p;
- float angle;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
-
- angle = (Math::Rand()-0.5f)*0.3f;
- m_object->SetAngleY(1, angle);
- m_object->SetAngleY(2, angle);
- m_object->SetAngleY(3, angle+Math::PI);
-
- m_object->SetAngleX(2, -Math::PI*0.35f*(0.8f+Math::Rand()*0.2f));
- m_object->SetAngleX(3, -Math::PI*0.35f*(0.8f+Math::Rand()*0.2f));
- }
- return true;
- }
-
- EventProgress(event.rTime);
-
- if ( m_phase == ACP_STOP ) return true;
-
- if ( m_phase == ACP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- fret = SearchStone(OBJECT_STONE); // Has stone transformed?
- if ( fret == 0 || SearchVehicle() )
- {
- m_phase = ACP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- else
- {
- fret->SetLock(true); // stone usable
-
- SetBusy(true);
- InitProgressTotal(3.0f+10.0f+1.5f);
- UpdateInterface();
-
- m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.0f);
- m_bSoundClose = false;
-
- m_phase = ACP_CLOSE;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- }
- }
- }
-
- if ( m_phase == ACP_CLOSE )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_progress >= 0.8f && !m_bSoundClose )
- {
- m_bSoundClose = true;
- m_sound->Play(SOUND_CLOSE, m_object->RetPosition(0), 1.0f, 0.8f);
- }
- angle = -Math::PI*0.35f*(1.0f-Math::Bounce(m_progress, 0.85f, 0.05f));
- m_object->SetAngleX(2, angle);
- m_object->SetAngleX(3, angle);
- }
- else
- {
- m_object->SetAngleX(2, 0.0f);
- m_object->SetAngleX(3, 0.0f);
-
- m_soundChannel = m_sound->Play(SOUND_CONVERT, m_object->RetPosition(0), 0.0f, 0.25f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.25f, 0.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.00f, 4.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.25f, 4.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.25f, 0.5f, SOPER_STOP);
-
- m_phase = ACP_ROTATE;
- m_progress = 0.0f;
- m_speed = 1.0f/10.0f;
- }
- }
-
- if ( m_phase == ACP_ROTATE )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_progress < 0.5f )
- {
- angle = powf((m_progress*2.0f)*5.0f, 2.0f); // accelerates
- }
- else
- {
- angle = -powf((2.0f-m_progress*2.0f)*5.0f, 2.0f); // slows
- }
- m_object->SetAngleY(1, angle);
- m_object->SetAngleY(2, angle);
- m_object->SetAngleY(3, angle+Math::PI);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- c.x = pos.x;
- c.y = pos.z;
- p.x = c.x;
- p.y = c.y+6.0f;
- p = Math::RotatePoint(c, Math::Rand()*Math::PI*2.0f, p);
- pos.x = p.x;
- pos.z = p.y;
- pos.y += 1.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*2.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 1.0f, 0.0f, 0.0f);
- }
- }
- else
- {
- m_object->SetAngleY(1, 0.0f);
- m_object->SetAngleY(2, 0.0f);
- m_object->SetAngleY(3, Math::PI);
-
- fret = SearchStone(OBJECT_STONE);
- if ( fret != 0 )
- {
- m_bResetDelete = ( fret->RetResetCap() != RESET_NONE );
- fret->DeleteObject(); // destroy the stone
- delete fret;
- }
-
- CreateMetal(); // Create the metal
- m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.5f);
-
- m_phase = ACP_OPEN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
-
- if ( m_phase == ACP_OPEN )
- {
- if ( m_progress < 1.0f )
- {
- angle = -Math::PI*0.35f*Math::Bounce(m_progress, 0.7f, 0.2f);
- m_object->SetAngleX(2, angle);
- m_object->SetAngleX(3, angle);
-
- if ( m_progress < 0.9f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*6.0f;
- pos.z += (Math::Rand()-0.5f)*6.0f;
- pos.y += Math::Rand()*4.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*4.0f+3.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
- }
- }
- else
- {
- m_soundChannel = -1;
- m_object->SetAngleX(2, -Math::PI*0.35f);
- m_object->SetAngleX(3, -Math::PI*0.35f);
-
- SetBusy(false);
- UpdateInterface();
-
- m_phase = ACP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- return true;
-}
-
-// Returns an error due the state of the automation.
-
-Error CAutoConvert::RetError()
-{
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- if ( m_phase == ACP_WAIT ) return ERR_CONVERT_EMPTY;
- return ERR_OK;
-}
-
-// Cancels the current transformation.
-
-bool CAutoConvert::Abort()
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- m_object->SetAngleY(1, 0.0f);
- m_object->SetAngleY(2, 0.0f);
- m_object->SetAngleY(3, Math::PI);
- m_object->SetAngleX(2, -Math::PI*0.35f);
- m_object->SetAngleX(3, -Math::PI*0.35f);
-
- m_phase = ACP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- SetBusy(false);
- UpdateInterface();
-
- return true;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoConvert::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 103, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoConvert::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == ACP_STOP ||
- m_phase == ACP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoConvert::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoConvertPhase)OpInt(line, "aPhase", ACP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
-// Searches for the object before or during processing.
-
-CObject* CAutoConvert::SearchStone(ObjectType type)
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType oType;
- float dist;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( oType != type ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, cPos);
-
- if ( dist <= 5.0f ) return pObj;
- }
-
- return 0;
-}
-
-// Search if a vehicle is too close.
-
-bool CAutoConvert::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType type;
- float oRadius, dist;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr &&
- type != OBJECT_METAL &&
- type != OBJECT_URANIUM &&
- type != OBJECT_POWER &&
- type != OBJECT_ATOMIC &&
- type != OBJECT_BULLET &&
- type != OBJECT_BBOX &&
- type != OBJECT_TNT &&
- type != OBJECT_MOTHER &&
- type != OBJECT_ANT &&
- type != OBJECT_SPIDER &&
- type != OBJECT_BEE &&
- type != OBJECT_WORM ) continue;
-
- if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
- dist = Math::Distance(oPos, cPos)-oRadius;
-
- if ( dist < 8.0f ) return true;
- }
-
- return false;
-}
-
-// Creates an object metal.
-
-void CAutoConvert::CreateMetal()
-{
- Math::Vector pos;
- float angle;
- CObject* fret;
-
- pos = m_object->RetPosition(0);
- angle = m_object->RetAngleY(0);
-
- fret = new CObject(m_iMan);
- if ( !fret->CreateResource(pos, angle, OBJECT_METAL) )
- {
- delete fret;
- m_displayText->DisplayError(ERR_TOOMANY, m_object);
- return;
- }
-
- if ( m_bResetDelete )
- {
- fret->SetResetCap(RESET_DELETE);
- }
-
- m_displayText->DisplayError(INFO_CONVERT, m_object);
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoconvert.h"
+
+#include "common/iman.h"
+#include "math/geometry.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+
+
+
+
+// Object's constructor.
+
+CAutoConvert::CAutoConvert(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+ m_phase = ACP_STOP;
+ m_bResetDelete = false;
+ m_soundChannel = -1;
+}
+
+// Object's destructor.
+
+CAutoConvert::~CAutoConvert()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoConvert::DeleteObject(bool bAll)
+{
+ CObject* fret;
+
+ if ( !bAll )
+ {
+ fret = SearchStone(OBJECT_STONE);
+ if ( fret != 0 )
+ {
+ fret->DeleteObject(); // destroy the stone
+ delete fret;
+ }
+ }
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoConvert::Init()
+{
+ m_phase = ACP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoConvert::EventProcess(const Event &event)
+{
+ CObject* fret;
+ Math::Vector pos, speed;
+ Math::Point dim, c, p;
+ float angle;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+
+ angle = (Math::Rand()-0.5f)*0.3f;
+ m_object->SetAngleY(1, angle);
+ m_object->SetAngleY(2, angle);
+ m_object->SetAngleY(3, angle+Math::PI);
+
+ m_object->SetAngleX(2, -Math::PI*0.35f*(0.8f+Math::Rand()*0.2f));
+ m_object->SetAngleX(3, -Math::PI*0.35f*(0.8f+Math::Rand()*0.2f));
+ }
+ return true;
+ }
+
+ EventProgress(event.rTime);
+
+ if ( m_phase == ACP_STOP ) return true;
+
+ if ( m_phase == ACP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ fret = SearchStone(OBJECT_STONE); // Has stone transformed?
+ if ( fret == 0 || SearchVehicle() )
+ {
+ m_phase = ACP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ else
+ {
+ fret->SetLock(true); // stone usable
+
+ SetBusy(true);
+ InitProgressTotal(3.0f+10.0f+1.5f);
+ UpdateInterface();
+
+ m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.0f);
+ m_bSoundClose = false;
+
+ m_phase = ACP_CLOSE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ }
+ }
+ }
+
+ if ( m_phase == ACP_CLOSE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_progress >= 0.8f && !m_bSoundClose )
+ {
+ m_bSoundClose = true;
+ m_sound->Play(SOUND_CLOSE, m_object->RetPosition(0), 1.0f, 0.8f);
+ }
+ angle = -Math::PI*0.35f*(1.0f-Math::Bounce(m_progress, 0.85f, 0.05f));
+ m_object->SetAngleX(2, angle);
+ m_object->SetAngleX(3, angle);
+ }
+ else
+ {
+ m_object->SetAngleX(2, 0.0f);
+ m_object->SetAngleX(3, 0.0f);
+
+ m_soundChannel = m_sound->Play(SOUND_CONVERT, m_object->RetPosition(0), 0.0f, 0.25f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.25f, 0.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.00f, 4.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.25f, 4.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.25f, 0.5f, SOPER_STOP);
+
+ m_phase = ACP_ROTATE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/10.0f;
+ }
+ }
+
+ if ( m_phase == ACP_ROTATE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_progress < 0.5f )
+ {
+ angle = powf((m_progress*2.0f)*5.0f, 2.0f); // accelerates
+ }
+ else
+ {
+ angle = -powf((2.0f-m_progress*2.0f)*5.0f, 2.0f); // slows
+ }
+ m_object->SetAngleY(1, angle);
+ m_object->SetAngleY(2, angle);
+ m_object->SetAngleY(3, angle+Math::PI);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ c.x = pos.x;
+ c.y = pos.z;
+ p.x = c.x;
+ p.y = c.y+6.0f;
+ p = Math::RotatePoint(c, Math::Rand()*Math::PI*2.0f, p);
+ pos.x = p.x;
+ pos.z = p.y;
+ pos.y += 1.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*2.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 1.0f, 0.0f, 0.0f);
+ }
+ }
+ else
+ {
+ m_object->SetAngleY(1, 0.0f);
+ m_object->SetAngleY(2, 0.0f);
+ m_object->SetAngleY(3, Math::PI);
+
+ fret = SearchStone(OBJECT_STONE);
+ if ( fret != 0 )
+ {
+ m_bResetDelete = ( fret->RetResetCap() != RESET_NONE );
+ fret->DeleteObject(); // destroy the stone
+ delete fret;
+ }
+
+ CreateMetal(); // Create the metal
+ m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.5f);
+
+ m_phase = ACP_OPEN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+
+ if ( m_phase == ACP_OPEN )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = -Math::PI*0.35f*Math::Bounce(m_progress, 0.7f, 0.2f);
+ m_object->SetAngleX(2, angle);
+ m_object->SetAngleX(3, angle);
+
+ if ( m_progress < 0.9f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*6.0f;
+ pos.z += (Math::Rand()-0.5f)*6.0f;
+ pos.y += Math::Rand()*4.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*4.0f+3.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
+ }
+ }
+ else
+ {
+ m_soundChannel = -1;
+ m_object->SetAngleX(2, -Math::PI*0.35f);
+ m_object->SetAngleX(3, -Math::PI*0.35f);
+
+ SetBusy(false);
+ UpdateInterface();
+
+ m_phase = ACP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ return true;
+}
+
+// Returns an error due the state of the automation.
+
+Error CAutoConvert::RetError()
+{
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ if ( m_phase == ACP_WAIT ) return ERR_CONVERT_EMPTY;
+ return ERR_OK;
+}
+
+// Cancels the current transformation.
+
+bool CAutoConvert::Abort()
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ m_object->SetAngleY(1, 0.0f);
+ m_object->SetAngleY(2, 0.0f);
+ m_object->SetAngleY(3, Math::PI);
+ m_object->SetAngleX(2, -Math::PI*0.35f);
+ m_object->SetAngleX(3, -Math::PI*0.35f);
+
+ m_phase = ACP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ SetBusy(false);
+ UpdateInterface();
+
+ return true;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoConvert::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 103, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoConvert::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == ACP_STOP ||
+ m_phase == ACP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoConvert::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoConvertPhase)OpInt(line, "aPhase", ACP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
+// Searches for the object before or during processing.
+
+CObject* CAutoConvert::SearchStone(ObjectType type)
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType oType;
+ float dist;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( oType != type ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, cPos);
+
+ if ( dist <= 5.0f ) return pObj;
+ }
+
+ return 0;
+}
+
+// Search if a vehicle is too close.
+
+bool CAutoConvert::SearchVehicle()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType type;
+ float oRadius, dist;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_HUMAN &&
+ type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis &&
+ type != OBJECT_MOBILErt &&
+ type != OBJECT_MOBILErc &&
+ type != OBJECT_MOBILErr &&
+ type != OBJECT_MOBILErs &&
+ type != OBJECT_MOBILEsa &&
+ type != OBJECT_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_MOBILEdr &&
+ type != OBJECT_METAL &&
+ type != OBJECT_URANIUM &&
+ type != OBJECT_POWER &&
+ type != OBJECT_ATOMIC &&
+ type != OBJECT_BULLET &&
+ type != OBJECT_BBOX &&
+ type != OBJECT_TNT &&
+ type != OBJECT_MOTHER &&
+ type != OBJECT_ANT &&
+ type != OBJECT_SPIDER &&
+ type != OBJECT_BEE &&
+ type != OBJECT_WORM ) continue;
+
+ if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
+ dist = Math::Distance(oPos, cPos)-oRadius;
+
+ if ( dist < 8.0f ) return true;
+ }
+
+ return false;
+}
+
+// Creates an object metal.
+
+void CAutoConvert::CreateMetal()
+{
+ Math::Vector pos;
+ float angle;
+ CObject* fret;
+
+ pos = m_object->RetPosition(0);
+ angle = m_object->RetAngleY(0);
+
+ fret = new CObject(m_iMan);
+ if ( !fret->CreateResource(pos, angle, OBJECT_METAL) )
+ {
+ delete fret;
+ m_displayText->DisplayError(ERR_TOOMANY, m_object);
+ return;
+ }
+
+ if ( m_bResetDelete )
+ {
+ fret->SetResetCap(RESET_DELETE);
+ }
+
+ m_displayText->DisplayError(INFO_CONVERT, m_object);
+}
+
diff --git a/src/object/auto/autoconvert.h b/src/object/auto/autoconvert.h
index b907c3a..c2042cf 100644
--- a/src/object/auto/autoconvert.h
+++ b/src/object/auto/autoconvert.h
@@ -1,70 +1,70 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoconvert.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoConvertPhase
-{
- ACP_STOP = 1,
- ACP_WAIT = 2,
- ACP_CLOSE = 3, // close the cover
- ACP_ROTATE = 4, // turn the cover
- ACP_OPEN = 5, // opens the cover
-};
-
-
-
-class CAutoConvert : public CAuto
-{
-public:
- CAutoConvert(CInstanceManager* iMan, CObject* object);
- ~CAutoConvert();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
- bool Abort();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- CObject* SearchStone(ObjectType type);
- bool SearchVehicle();
- void CreateMetal();
-
-protected:
- AutoConvertPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
- bool m_bResetDelete;
- bool m_bSoundClose;
- int m_soundChannel;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoconvert.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoConvertPhase
+{
+ ACP_STOP = 1,
+ ACP_WAIT = 2,
+ ACP_CLOSE = 3, // close the cover
+ ACP_ROTATE = 4, // turn the cover
+ ACP_OPEN = 5, // opens the cover
+};
+
+
+
+class CAutoConvert : public CAuto
+{
+public:
+ CAutoConvert(CInstanceManager* iMan, CObject* object);
+ ~CAutoConvert();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+ bool Abort();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ CObject* SearchStone(ObjectType type);
+ bool SearchVehicle();
+ void CreateMetal();
+
+protected:
+ AutoConvertPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+ bool m_bResetDelete;
+ bool m_bSoundClose;
+ int m_soundChannel;
+};
+
diff --git a/src/object/auto/autoderrick.cpp b/src/object/auto/autoderrick.cpp
index fa7cff9..3f1cda5 100644
--- a/src/object/auto/autoderrick.cpp
+++ b/src/object/auto/autoderrick.cpp
@@ -1,589 +1,589 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoderrick.h"
-
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "math/geometry.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-
-
-
-
-const float DERRICK_DELAY = 10.0f; // duration of the extraction
-const float DERRICK_DELAYu = 30.0f; // same, but for uranium
-
-
-
-
-// Object's constructor.
-
-CAutoDerrick::CAutoDerrick(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
- m_phase = ADP_WAIT; // paused until the first Init ()
- m_soundChannel = -1;
-}
-
-// Object's destructor.
-
-CAutoDerrick::~CAutoDerrick()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoDerrick::DeleteObject(bool bAll)
-{
- CObject* fret;
-
- if ( !bAll )
- {
- fret = SearchFret();
- if ( fret != 0 && fret->RetLock() )
- {
- fret->DeleteObject();
- delete fret;
- }
- }
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoDerrick::Init()
-{
- Math::Matrix* mat;
- Math::Vector pos;
- TerrainRes res;
-
- pos = m_object->RetPosition(0);
- res = m_terrain->RetResource(pos);
-
- if ( res == TR_STONE ||
- res == TR_URANIUM ||
- res == TR_KEYa ||
- res == TR_KEYb ||
- res == TR_KEYc ||
- res == TR_KEYd )
- {
- m_type = OBJECT_FRET;
- if ( res == TR_STONE ) m_type = OBJECT_STONE;
- if ( res == TR_URANIUM ) m_type = OBJECT_URANIUM;
- if ( res == TR_KEYa ) m_type = OBJECT_KEYa;
- if ( res == TR_KEYb ) m_type = OBJECT_KEYb;
- if ( res == TR_KEYc ) m_type = OBJECT_KEYc;
- if ( res == TR_KEYd ) m_type = OBJECT_KEYd;
-
- m_phase = ADP_EXCAVATE;
- m_progress = 0.0f;
- m_speed = 1.0f/(m_type==OBJECT_URANIUM?DERRICK_DELAYu:DERRICK_DELAY);
- }
- else
- {
- m_phase = ADP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f;
- }
-
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastParticule = 0.0f;
- m_lastTrack = 0.0f;
-
- pos = Math::Vector(7.0f, 0.0f, 0.0f);
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Transform(*mat, pos);
- m_terrain->MoveOnFloor(pos);
- m_fretPos = pos;
-}
-
-
-// Management of an event.
-
-bool CAutoDerrick::EventProcess(const Event &event)
-{
- CObject* fret;
- Math::Vector pos, speed;
- Math::Point dim;
- float angle, duration, factor;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_phase == ADP_WAIT ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
-
- pos.x = 0.0f;
- pos.z = 0.0f;
- pos.y = -2.0f*Math::Rand();
- m_object->SetPosition(1, pos); // up / down the drill
-
- m_object->SetAngleY(1, Math::Rand()*0.5f); // rotates the drill
- }
- return true;
- }
-
- if ( m_phase == ADP_EXCAVATE )
- {
- if ( m_soundChannel == -1 )
- {
- if ( m_type == OBJECT_URANIUM )
- {
- factor = DERRICK_DELAYu/DERRICK_DELAY;
- }
- else
- {
- factor = 1.0f;
- }
- m_soundChannel = m_sound->Play(SOUND_DERRICK, m_object->RetPosition(0), 1.0f, 0.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 4.0f*factor, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.3f, 6.0f*factor, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 4.0f, SOPER_STOP);
- }
-
- if ( m_progress >= 6.0f/16.0f && // penetrates into the ground?
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = Math::Rand()*5.0f;
- dim.x = Math::Rand()*3.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
-
- if ( m_progress >= 6.0f/16.0f && // penetrates into the ground?
- m_lastTrack+m_engine->ParticuleAdapt(0.5f) <= m_time )
- {
- m_lastTrack = m_time;
-
- pos = m_object->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*12.0f;
- speed.z = (Math::Rand()-0.5f)*12.0f;
- speed.y = Math::Rand()*10.0f+10.0f;
- dim.x = 0.6f;
- dim.y = dim.x;
- pos.y += dim.y;
- duration = Math::Rand()*2.0f+2.0f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK5,
- duration, Math::Rand()*10.0f+15.0f,
- duration*0.2f, 1.0f);
- }
-
- if ( m_progress < 1.0f )
- {
- pos.x = 0.0f;
- pos.z = 0.0f;
- pos.y = -m_progress*16.0f;
- m_object->SetPosition(1, pos); // down the drill
-
- angle = m_object->RetAngleY(1);
- angle += event.rTime*8.0f;
- m_object->SetAngleY(1, angle); // rotates the drill
- }
- else
- {
- m_phase = ADP_ASCEND;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- }
- }
-
- if ( m_phase == ADP_ASCEND )
- {
- if ( m_progress <= 7.0f/16.0f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = Math::Rand()*5.0f;
- dim.x = Math::Rand()*3.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
-
- if ( m_progress <= 4.0f/16.0f &&
- m_lastTrack+m_engine->ParticuleAdapt(1.0f) <= m_time )
- {
- m_lastTrack = m_time;
-
- pos = m_object->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*12.0f;
- speed.z = (Math::Rand()-0.5f)*12.0f;
- speed.y = Math::Rand()*10.0f+10.0f;
- dim.x = 0.6f;
- dim.y = dim.x;
- pos.y += dim.y;
- duration = Math::Rand()*2.0f+2.0f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK5,
- duration, Math::Rand()*10.0f+15.0f,
- duration*0.2f, 1.0f);
- }
-
- if ( m_progress < 1.0f )
- {
- pos.x = 0.0f;
- pos.z = 0.0f;
- pos.y = -(1.0f-m_progress)*16.0f;
- m_object->SetPosition(1, pos); // back the drill
-
- angle = m_object->RetAngleY(1);
- angle -= event.rTime*2.0f;
- m_object->SetAngleY(1, angle); // rotates the drill
- }
- else
- {
- m_soundChannel = -1;
- m_bSoundFall = false;
-
- m_phase = ADP_EXPORT;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- }
- }
-
- if ( m_phase == ADP_ISFREE )
- {
- if ( m_progress >= 1.0f )
- {
- m_bSoundFall = false;
-
- m_phase = ADP_EXPORT;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- }
- }
-
- if ( m_phase == ADP_EXPORT )
- {
- if ( m_progress == 0.0f )
- {
- if ( SearchFree(m_fretPos) )
- {
- angle = m_object->RetAngleY(0);
- CreateFret(m_fretPos, angle, m_type, 16.0f);
- }
- else
- {
- m_phase = ADP_ISFREE;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- return true;
- }
- }
-
- fret = SearchFret();
-
- if ( fret != 0 &&
- m_progress <= 0.5f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
- {
- m_lastParticule = m_time;
-
- if ( m_progress < 0.3f )
- {
- pos = fret->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- pos.y += (Math::Rand()-0.5f)*5.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 3.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFIRE, 1.0f, 0.0f, 0.0f);
- }
- else
- {
- pos = fret->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- pos.y += Math::Rand()*2.5f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
- }
- }
-
- if ( m_progress < 1.0f )
- {
- if ( fret != 0 )
- {
- pos = fret->RetPosition(0);
- pos.y -= event.rTime*20.0f; // grave
- if ( !m_bSoundFall && pos.y < m_fretPos.y )
- {
- m_sound->Play(SOUND_BOUM, m_fretPos);
- m_bSoundFall = true;
- }
- if ( pos.y < m_fretPos.y )
- {
- pos.y = m_fretPos.y;
- fret->SetLock(false); // object usable
- }
- fret->SetPosition(0, pos);
- }
- }
- else
- {
- if ( ExistKey() ) // key already exists?
- {
- m_phase = ADP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/10.0f;
- }
- else
- {
- m_phase = ADP_EXCAVATE;
- m_progress = 0.0f;
- m_speed = 1.0f/(m_type==OBJECT_URANIUM?DERRICK_DELAYu:DERRICK_DELAY);
- }
- }
- }
-
- return true;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoDerrick::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 109, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoDerrick::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == ADP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoDerrick::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoDerrickPhase)OpInt(line, "aPhase", ADP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
-// Seeks the subject cargo.
-
-CObject* CAutoDerrick::SearchFret()
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_DERRICK ) continue;
-
- oPos = pObj->RetPosition(0);
-
- if ( oPos.x == m_fretPos.x &&
- oPos.z == m_fretPos.z ) return pObj;
- }
-
- return 0;
-}
-
-// Seeks if a site is free.
-
-bool CAutoDerrick::SearchFree(Math::Vector pos)
-{
- CObject* pObj;
- Math::Vector sPos;
- ObjectType type;
- float sRadius, distance;
- int i, j;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_DERRICK ) continue;
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, sPos, sRadius) )
- {
- distance = Math::Distance(sPos, pos);
- distance -= sRadius;
- if ( distance < 2.0f ) return false; // location occupied
- }
- }
-
- return true; // location free
-}
-
-// Create a transportable object.
-
-void CAutoDerrick::CreateFret(Math::Vector pos, float angle, ObjectType type,
- float height)
-{
- CObject* fret;
-
- fret = new CObject(m_iMan);
- if ( !fret->CreateResource(pos, angle, type) )
- {
- delete fret;
- m_displayText->DisplayError(ERR_TOOMANY, m_object);
- return;
- }
- fret->SetLock(true); // object not yet usable
-
- if ( m_object->RetResetCap() == RESET_MOVE )
- {
- fret->SetResetCap(RESET_DELETE);
- }
-
- pos = fret->RetPosition(0);
- pos.y += height;
- fret->SetPosition(0, pos);
-}
-
-// Look if there is already a key.
-
-bool CAutoDerrick::ExistKey()
-{
- CObject* pObj;
- ObjectType type;
- int i;
-
- if ( m_type != OBJECT_KEYa &&
- m_type != OBJECT_KEYb &&
- m_type != OBJECT_KEYc &&
- m_type != OBJECT_KEYd ) return false;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == m_type ) return true;
- }
-
- return false;
-}
-
-
-// Returns an error due the state of the automaton.
-
-Error CAutoDerrick::RetError()
-{
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- if ( m_phase == ADP_WAIT ) return ERR_DERRICK_NULL;
- return ERR_OK;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoderrick.h"
+
+#include "common/iman.h"
+#include "old/terrain.h"
+#include "math/geometry.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+
+
+
+
+const float DERRICK_DELAY = 10.0f; // duration of the extraction
+const float DERRICK_DELAYu = 30.0f; // same, but for uranium
+
+
+
+
+// Object's constructor.
+
+CAutoDerrick::CAutoDerrick(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+ m_phase = ADP_WAIT; // paused until the first Init ()
+ m_soundChannel = -1;
+}
+
+// Object's destructor.
+
+CAutoDerrick::~CAutoDerrick()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoDerrick::DeleteObject(bool bAll)
+{
+ CObject* fret;
+
+ if ( !bAll )
+ {
+ fret = SearchFret();
+ if ( fret != 0 && fret->RetLock() )
+ {
+ fret->DeleteObject();
+ delete fret;
+ }
+ }
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoDerrick::Init()
+{
+ Math::Matrix* mat;
+ Math::Vector pos;
+ TerrainRes res;
+
+ pos = m_object->RetPosition(0);
+ res = m_terrain->RetResource(pos);
+
+ if ( res == TR_STONE ||
+ res == TR_URANIUM ||
+ res == TR_KEYa ||
+ res == TR_KEYb ||
+ res == TR_KEYc ||
+ res == TR_KEYd )
+ {
+ m_type = OBJECT_FRET;
+ if ( res == TR_STONE ) m_type = OBJECT_STONE;
+ if ( res == TR_URANIUM ) m_type = OBJECT_URANIUM;
+ if ( res == TR_KEYa ) m_type = OBJECT_KEYa;
+ if ( res == TR_KEYb ) m_type = OBJECT_KEYb;
+ if ( res == TR_KEYc ) m_type = OBJECT_KEYc;
+ if ( res == TR_KEYd ) m_type = OBJECT_KEYd;
+
+ m_phase = ADP_EXCAVATE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/(m_type==OBJECT_URANIUM?DERRICK_DELAYu:DERRICK_DELAY);
+ }
+ else
+ {
+ m_phase = ADP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f;
+ }
+
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+ m_lastTrack = 0.0f;
+
+ pos = Math::Vector(7.0f, 0.0f, 0.0f);
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Transform(*mat, pos);
+ m_terrain->MoveOnFloor(pos);
+ m_fretPos = pos;
+}
+
+
+// Management of an event.
+
+bool CAutoDerrick::EventProcess(const Event &event)
+{
+ CObject* fret;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float angle, duration, factor;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_phase == ADP_WAIT ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+
+ pos.x = 0.0f;
+ pos.z = 0.0f;
+ pos.y = -2.0f*Math::Rand();
+ m_object->SetPosition(1, pos); // up / down the drill
+
+ m_object->SetAngleY(1, Math::Rand()*0.5f); // rotates the drill
+ }
+ return true;
+ }
+
+ if ( m_phase == ADP_EXCAVATE )
+ {
+ if ( m_soundChannel == -1 )
+ {
+ if ( m_type == OBJECT_URANIUM )
+ {
+ factor = DERRICK_DELAYu/DERRICK_DELAY;
+ }
+ else
+ {
+ factor = 1.0f;
+ }
+ m_soundChannel = m_sound->Play(SOUND_DERRICK, m_object->RetPosition(0), 1.0f, 0.5f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 4.0f*factor, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.3f, 6.0f*factor, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 4.0f, SOPER_STOP);
+ }
+
+ if ( m_progress >= 6.0f/16.0f && // penetrates into the ground?
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = Math::Rand()*5.0f;
+ dim.x = Math::Rand()*3.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+
+ if ( m_progress >= 6.0f/16.0f && // penetrates into the ground?
+ m_lastTrack+m_engine->ParticuleAdapt(0.5f) <= m_time )
+ {
+ m_lastTrack = m_time;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*12.0f;
+ speed.z = (Math::Rand()-0.5f)*12.0f;
+ speed.y = Math::Rand()*10.0f+10.0f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ pos.y += dim.y;
+ duration = Math::Rand()*2.0f+2.0f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK5,
+ duration, Math::Rand()*10.0f+15.0f,
+ duration*0.2f, 1.0f);
+ }
+
+ if ( m_progress < 1.0f )
+ {
+ pos.x = 0.0f;
+ pos.z = 0.0f;
+ pos.y = -m_progress*16.0f;
+ m_object->SetPosition(1, pos); // down the drill
+
+ angle = m_object->RetAngleY(1);
+ angle += event.rTime*8.0f;
+ m_object->SetAngleY(1, angle); // rotates the drill
+ }
+ else
+ {
+ m_phase = ADP_ASCEND;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ }
+ }
+
+ if ( m_phase == ADP_ASCEND )
+ {
+ if ( m_progress <= 7.0f/16.0f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = Math::Rand()*5.0f;
+ dim.x = Math::Rand()*3.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+
+ if ( m_progress <= 4.0f/16.0f &&
+ m_lastTrack+m_engine->ParticuleAdapt(1.0f) <= m_time )
+ {
+ m_lastTrack = m_time;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*12.0f;
+ speed.z = (Math::Rand()-0.5f)*12.0f;
+ speed.y = Math::Rand()*10.0f+10.0f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ pos.y += dim.y;
+ duration = Math::Rand()*2.0f+2.0f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK5,
+ duration, Math::Rand()*10.0f+15.0f,
+ duration*0.2f, 1.0f);
+ }
+
+ if ( m_progress < 1.0f )
+ {
+ pos.x = 0.0f;
+ pos.z = 0.0f;
+ pos.y = -(1.0f-m_progress)*16.0f;
+ m_object->SetPosition(1, pos); // back the drill
+
+ angle = m_object->RetAngleY(1);
+ angle -= event.rTime*2.0f;
+ m_object->SetAngleY(1, angle); // rotates the drill
+ }
+ else
+ {
+ m_soundChannel = -1;
+ m_bSoundFall = false;
+
+ m_phase = ADP_EXPORT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ }
+ }
+
+ if ( m_phase == ADP_ISFREE )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_bSoundFall = false;
+
+ m_phase = ADP_EXPORT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ }
+ }
+
+ if ( m_phase == ADP_EXPORT )
+ {
+ if ( m_progress == 0.0f )
+ {
+ if ( SearchFree(m_fretPos) )
+ {
+ angle = m_object->RetAngleY(0);
+ CreateFret(m_fretPos, angle, m_type, 16.0f);
+ }
+ else
+ {
+ m_phase = ADP_ISFREE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ return true;
+ }
+ }
+
+ fret = SearchFret();
+
+ if ( fret != 0 &&
+ m_progress <= 0.5f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ if ( m_progress < 0.3f )
+ {
+ pos = fret->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ pos.y += (Math::Rand()-0.5f)*5.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 3.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFIRE, 1.0f, 0.0f, 0.0f);
+ }
+ else
+ {
+ pos = fret->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ pos.y += Math::Rand()*2.5f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
+ }
+ }
+
+ if ( m_progress < 1.0f )
+ {
+ if ( fret != 0 )
+ {
+ pos = fret->RetPosition(0);
+ pos.y -= event.rTime*20.0f; // grave
+ if ( !m_bSoundFall && pos.y < m_fretPos.y )
+ {
+ m_sound->Play(SOUND_BOUM, m_fretPos);
+ m_bSoundFall = true;
+ }
+ if ( pos.y < m_fretPos.y )
+ {
+ pos.y = m_fretPos.y;
+ fret->SetLock(false); // object usable
+ }
+ fret->SetPosition(0, pos);
+ }
+ }
+ else
+ {
+ if ( ExistKey() ) // key already exists?
+ {
+ m_phase = ADP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/10.0f;
+ }
+ else
+ {
+ m_phase = ADP_EXCAVATE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/(m_type==OBJECT_URANIUM?DERRICK_DELAYu:DERRICK_DELAY);
+ }
+ }
+ }
+
+ return true;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoDerrick::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 109, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoDerrick::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == ADP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoDerrick::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoDerrickPhase)OpInt(line, "aPhase", ADP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
+// Seeks the subject cargo.
+
+CObject* CAutoDerrick::SearchFret()
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ ObjectType type;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_DERRICK ) continue;
+
+ oPos = pObj->RetPosition(0);
+
+ if ( oPos.x == m_fretPos.x &&
+ oPos.z == m_fretPos.z ) return pObj;
+ }
+
+ return 0;
+}
+
+// Seeks if a site is free.
+
+bool CAutoDerrick::SearchFree(Math::Vector pos)
+{
+ CObject* pObj;
+ Math::Vector sPos;
+ ObjectType type;
+ float sRadius, distance;
+ int i, j;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_DERRICK ) continue;
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, sPos, sRadius) )
+ {
+ distance = Math::Distance(sPos, pos);
+ distance -= sRadius;
+ if ( distance < 2.0f ) return false; // location occupied
+ }
+ }
+
+ return true; // location free
+}
+
+// Create a transportable object.
+
+void CAutoDerrick::CreateFret(Math::Vector pos, float angle, ObjectType type,
+ float height)
+{
+ CObject* fret;
+
+ fret = new CObject(m_iMan);
+ if ( !fret->CreateResource(pos, angle, type) )
+ {
+ delete fret;
+ m_displayText->DisplayError(ERR_TOOMANY, m_object);
+ return;
+ }
+ fret->SetLock(true); // object not yet usable
+
+ if ( m_object->RetResetCap() == RESET_MOVE )
+ {
+ fret->SetResetCap(RESET_DELETE);
+ }
+
+ pos = fret->RetPosition(0);
+ pos.y += height;
+ fret->SetPosition(0, pos);
+}
+
+// Look if there is already a key.
+
+bool CAutoDerrick::ExistKey()
+{
+ CObject* pObj;
+ ObjectType type;
+ int i;
+
+ if ( m_type != OBJECT_KEYa &&
+ m_type != OBJECT_KEYb &&
+ m_type != OBJECT_KEYc &&
+ m_type != OBJECT_KEYd ) return false;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == m_type ) return true;
+ }
+
+ return false;
+}
+
+
+// Returns an error due the state of the automaton.
+
+Error CAutoDerrick::RetError()
+{
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ if ( m_phase == ADP_WAIT ) return ERR_DERRICK_NULL;
+ return ERR_OK;
+}
+
+
diff --git a/src/object/auto/autoderrick.h b/src/object/auto/autoderrick.h
index e211c0f..61a1ff1 100644
--- a/src/object/auto/autoderrick.h
+++ b/src/object/auto/autoderrick.h
@@ -1,71 +1,71 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoderrick.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoDerrickPhase
-{
- ADP_WAIT = 1,
- ADP_EXCAVATE = 2, // down the drill
- ADP_ASCEND = 3, // up the drill
- ADP_EXPORT = 4, // exports matter
- ADP_ISFREE = 5, // expected material loss
-};
-
-
-
-class CAutoDerrick : public CAuto
-{
-public:
- CAutoDerrick(CInstanceManager* iMan, CObject* object);
- ~CAutoDerrick();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- CObject* SearchFret();
- bool SearchFree(Math::Vector pos);
- void CreateFret(Math::Vector pos, float angle, ObjectType type, float height);
- bool ExistKey();
-
-protected:
- AutoDerrickPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
- float m_lastTrack;
- Math::Vector m_fretPos;
- int m_soundChannel;
- bool m_bSoundFall;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoderrick.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoDerrickPhase
+{
+ ADP_WAIT = 1,
+ ADP_EXCAVATE = 2, // down the drill
+ ADP_ASCEND = 3, // up the drill
+ ADP_EXPORT = 4, // exports matter
+ ADP_ISFREE = 5, // expected material loss
+};
+
+
+
+class CAutoDerrick : public CAuto
+{
+public:
+ CAutoDerrick(CInstanceManager* iMan, CObject* object);
+ ~CAutoDerrick();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ CObject* SearchFret();
+ bool SearchFree(Math::Vector pos);
+ void CreateFret(Math::Vector pos, float angle, ObjectType type, float height);
+ bool ExistKey();
+
+protected:
+ AutoDerrickPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+ float m_lastTrack;
+ Math::Vector m_fretPos;
+ int m_soundChannel;
+ bool m_bSoundFall;
+};
+
diff --git a/src/object/auto/autodestroyer.cpp b/src/object/auto/autodestroyer.cpp
index f1f018c..b40c374 100644
--- a/src/object/auto/autodestroyer.cpp
+++ b/src/object/auto/autodestroyer.cpp
@@ -1,374 +1,374 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autodestroyer.h"
-
-#include "common/iman.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-
-
-
-
-// Object's constructor.
-
-CAutoDestroyer::CAutoDestroyer(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
- m_phase = ADEP_WAIT; // paused until the first Init ()
-}
-
-// Destructive of the object.
-
-CAutoDestroyer::~CAutoDestroyer()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoDestroyer::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoDestroyer::Init()
-{
- m_phase = ADEP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/0.5f;
-
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastParticule = 0.0f;
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoDestroyer::EventProcess(const Event &event)
-{
- CObject* scrap;
- CPyro* pyro;
- Math::Vector pos, speed;
- Math::Point dim;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
- }
- return true;
- }
-
- if ( m_phase == ADEP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- scrap = SearchPlastic();
- if ( scrap == 0 )
- {
- m_phase = ADEP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/0.5f;
- }
- else
- {
- scrap->SetLock(true); // usable waste
-//? scrap->SetTruck(m_object); // usable waste
-
- if ( SearchVehicle() )
- {
- m_phase = ADEP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/0.5f;
- }
- else
- {
- m_sound->Play(SOUND_PSHHH2, m_object->RetPosition(0), 1.0f, 1.0f);
-
- m_phase = ADEP_DOWN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- m_bExplo = false;
- }
- }
- }
- }
-
- if ( m_phase == ADEP_DOWN )
- {
- if ( m_progress >= 0.3f-0.05f && !m_bExplo )
- {
- scrap = SearchPlastic();
- if ( scrap != 0 )
- {
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FRAGT, scrap);
- }
- m_bExplo = true;
- }
-
- if ( m_progress < 1.0f )
- {
- pos = Math::Vector(0.0f, -10.0f, 0.0f);
- pos.y = -Math::Bounce(m_progress, 0.3f)*10.0f;
- m_object->SetPosition(1, pos);
- }
- else
- {
- m_object->SetPosition(1, Math::Vector(0.0f, -10.0f, 0.0f));
- m_sound->Play(SOUND_REPAIR, m_object->RetPosition(0));
-
- m_phase = ADEP_REPAIR;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ADEP_REPAIR )
- {
- if ( m_progress < 1.0f )
- {
- }
- else
- {
- m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 0.8f);
-
- m_phase = ADEP_UP;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- }
- }
-
- if ( m_phase == ADEP_UP )
- {
- if ( m_progress < 1.0f )
- {
- pos = Math::Vector(0.0f, -10.0f, 0.0f);
- pos.y = -(1.0f-m_progress)*10.0f;
- m_object->SetPosition(1, pos);
- }
- else
- {
- m_object->SetPosition(1, Math::Vector(0.0f, 0.0f, 0.0f));
-
- m_phase = ADEP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/0.5f;
- }
- }
-
- return true;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoDestroyer::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 106, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-
-// Seeks plate waste in the destroyer.
-
-CObject* CAutoDestroyer::SearchPlastic()
-{
- CObject* pObj;
- Math::Vector sPos, oPos;
- ObjectType type;
- float dist;
- int i;
-
- sPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_SCRAP4 &&
- type != OBJECT_SCRAP5 ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, sPos);
- if ( dist <= 5.0f ) return pObj;
- }
-
- return 0;
-}
-
-// Seeks if one vehicle is too close.
-
-bool CAutoDestroyer::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType type;
- float oRadius, dist;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr &&
- type != OBJECT_MOTHER &&
- type != OBJECT_ANT &&
- type != OBJECT_SPIDER &&
- type != OBJECT_BEE &&
- type != OBJECT_WORM ) continue;
-
- if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
- dist = Math::Distance(oPos, cPos)-oRadius;
-
- if ( dist < 20.0f ) return true;
- }
-
- return false;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoDestroyer::RetError()
-{
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- return ERR_OK;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoDestroyer::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == ADEP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoDestroyer::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoDestroyerPhase)OpInt(line, "aPhase", ADEP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autodestroyer.h"
+
+#include "common/iman.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+
+
+
+
+// Object's constructor.
+
+CAutoDestroyer::CAutoDestroyer(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+ m_phase = ADEP_WAIT; // paused until the first Init ()
+}
+
+// Destructive of the object.
+
+CAutoDestroyer::~CAutoDestroyer()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoDestroyer::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoDestroyer::Init()
+{
+ m_phase = ADEP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/0.5f;
+
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoDestroyer::EventProcess(const Event &event)
+{
+ CObject* scrap;
+ CPyro* pyro;
+ Math::Vector pos, speed;
+ Math::Point dim;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+ }
+ return true;
+ }
+
+ if ( m_phase == ADEP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ scrap = SearchPlastic();
+ if ( scrap == 0 )
+ {
+ m_phase = ADEP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/0.5f;
+ }
+ else
+ {
+ scrap->SetLock(true); // usable waste
+//? scrap->SetTruck(m_object); // usable waste
+
+ if ( SearchVehicle() )
+ {
+ m_phase = ADEP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/0.5f;
+ }
+ else
+ {
+ m_sound->Play(SOUND_PSHHH2, m_object->RetPosition(0), 1.0f, 1.0f);
+
+ m_phase = ADEP_DOWN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ m_bExplo = false;
+ }
+ }
+ }
+ }
+
+ if ( m_phase == ADEP_DOWN )
+ {
+ if ( m_progress >= 0.3f-0.05f && !m_bExplo )
+ {
+ scrap = SearchPlastic();
+ if ( scrap != 0 )
+ {
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FRAGT, scrap);
+ }
+ m_bExplo = true;
+ }
+
+ if ( m_progress < 1.0f )
+ {
+ pos = Math::Vector(0.0f, -10.0f, 0.0f);
+ pos.y = -Math::Bounce(m_progress, 0.3f)*10.0f;
+ m_object->SetPosition(1, pos);
+ }
+ else
+ {
+ m_object->SetPosition(1, Math::Vector(0.0f, -10.0f, 0.0f));
+ m_sound->Play(SOUND_REPAIR, m_object->RetPosition(0));
+
+ m_phase = ADEP_REPAIR;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ADEP_REPAIR )
+ {
+ if ( m_progress < 1.0f )
+ {
+ }
+ else
+ {
+ m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 0.8f);
+
+ m_phase = ADEP_UP;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ }
+ }
+
+ if ( m_phase == ADEP_UP )
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos = Math::Vector(0.0f, -10.0f, 0.0f);
+ pos.y = -(1.0f-m_progress)*10.0f;
+ m_object->SetPosition(1, pos);
+ }
+ else
+ {
+ m_object->SetPosition(1, Math::Vector(0.0f, 0.0f, 0.0f));
+
+ m_phase = ADEP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/0.5f;
+ }
+ }
+
+ return true;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoDestroyer::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 106, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+
+// Seeks plate waste in the destroyer.
+
+CObject* CAutoDestroyer::SearchPlastic()
+{
+ CObject* pObj;
+ Math::Vector sPos, oPos;
+ ObjectType type;
+ float dist;
+ int i;
+
+ sPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_SCRAP4 &&
+ type != OBJECT_SCRAP5 ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, sPos);
+ if ( dist <= 5.0f ) return pObj;
+ }
+
+ return 0;
+}
+
+// Seeks if one vehicle is too close.
+
+bool CAutoDestroyer::SearchVehicle()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType type;
+ float oRadius, dist;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_HUMAN &&
+ type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis &&
+ type != OBJECT_MOBILErt &&
+ type != OBJECT_MOBILErc &&
+ type != OBJECT_MOBILErr &&
+ type != OBJECT_MOBILErs &&
+ type != OBJECT_MOBILEsa &&
+ type != OBJECT_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_MOBILEdr &&
+ type != OBJECT_MOTHER &&
+ type != OBJECT_ANT &&
+ type != OBJECT_SPIDER &&
+ type != OBJECT_BEE &&
+ type != OBJECT_WORM ) continue;
+
+ if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
+ dist = Math::Distance(oPos, cPos)-oRadius;
+
+ if ( dist < 20.0f ) return true;
+ }
+
+ return false;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoDestroyer::RetError()
+{
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ return ERR_OK;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoDestroyer::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == ADEP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoDestroyer::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoDestroyerPhase)OpInt(line, "aPhase", ADEP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autodestroyer.h b/src/object/auto/autodestroyer.h
index a233b88..88c93ea 100644
--- a/src/object/auto/autodestroyer.h
+++ b/src/object/auto/autodestroyer.h
@@ -1,65 +1,65 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autodestroyer.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoDestroyerPhase
-{
- ADEP_WAIT = 1, // expected metal
- ADEP_DOWN = 2, // down the cover
- ADEP_REPAIR = 3, // built the vehicle
- ADEP_UP = 4, // up the cover
-};
-
-
-
-class CAutoDestroyer : public CAuto
-{
-public:
- CAutoDestroyer(CInstanceManager* iMan, CObject* object);
- ~CAutoDestroyer();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- CObject* SearchPlastic();
- bool SearchVehicle();
-
-protected:
- AutoDestroyerPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
- bool m_bExplo;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autodestroyer.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoDestroyerPhase
+{
+ ADEP_WAIT = 1, // expected metal
+ ADEP_DOWN = 2, // down the cover
+ ADEP_REPAIR = 3, // built the vehicle
+ ADEP_UP = 4, // up the cover
+};
+
+
+
+class CAutoDestroyer : public CAuto
+{
+public:
+ CAutoDestroyer(CInstanceManager* iMan, CObject* object);
+ ~CAutoDestroyer();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ CObject* SearchPlastic();
+ bool SearchVehicle();
+
+protected:
+ AutoDestroyerPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+ bool m_bExplo;
+};
+
diff --git a/src/object/auto/autoegg.cpp b/src/object/auto/autoegg.cpp
index 773718c..b1e1c03 100644
--- a/src/object/auto/autoegg.cpp
+++ b/src/object/auto/autoegg.cpp
@@ -1,359 +1,359 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoegg.h"
-
-#include "math/geometry.h"
-#include "common/iman.h"
-#include "script/cmdtoken.h"
-
-
-
-
-// Object's constructor.
-
-CAutoEgg::CAutoEgg(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- m_type = OBJECT_NULL;
- m_value = 0.0f;
- m_string[0] = 0;
-
- m_param = 0;
- m_phase = AEP_NULL;
- Init();
-}
-
-// Object's destructor.
-
-CAutoEgg::~CAutoEgg()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoEgg::DeleteObject(bool bAll)
-{
- CObject* alien;
-
- CAuto::DeleteObject(bAll);
-
- if ( !bAll )
- {
- alien = SearchAlien();
- if ( alien != 0 )
- {
- // Probably the intended action
- // Original code: ( alien->RetZoom(0) == 1.0f )
- if ( alien->RetZoomY(0) == 1.0f )
- {
- alien->SetLock(false);
- alien->SetActivity(true); // the insect is active
- }
- else
- {
- alien->DeleteObject();
- delete alien;
- }
- }
- }
-}
-
-
-// Initialize the object.
-
-void CAutoEgg::Init()
-{
- CObject* alien;
-
- alien = SearchAlien();
- if ( alien == 0 )
- {
- m_phase = AEP_NULL;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- m_time = 0.0f;
- return;
- }
-
- m_phase = AEP_INCUB;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- m_time = 0.0f;
-
- m_type = alien->RetType();
-
- if ( m_type == OBJECT_ANT ||
- m_type == OBJECT_SPIDER ||
- m_type == OBJECT_BEE )
- {
- alien->SetZoom(0, 0.2f);
- }
- if ( m_type == OBJECT_WORM )
- {
- alien->SetZoom(0, 0.01f); // invisible !
- }
- alien->SetLock(true);
- alien->SetActivity(false);
-}
-
-
-// Gives a value.
-
-bool CAutoEgg::SetType(ObjectType type)
-{
- m_type = type;
- return true;
-}
-
-// Gives a value.
-
-bool CAutoEgg::SetValue(int rank, float value)
-{
- if ( rank != 0 ) return false;
- m_value = value;
- return true;
-}
-
-// Gives the string.
-
-bool CAutoEgg::SetString(char *string)
-{
- strcpy(m_string, string);
- return true;
-}
-
-
-// Start object.
-
-void CAutoEgg::Start(int param)
-{
- if ( m_type == OBJECT_NULL ) return;
- if ( m_value == 0.0f ) return;
-
- m_phase = AEP_DELAY;
- m_progress = 0.0f;
- m_speed = 1.0f/m_value;
-
- m_param = param;
-}
-
-
-// Management of an event.
-
-bool CAutoEgg::EventProcess(const Event &event)
-{
- CObject* alien;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
-
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_phase == AEP_NULL ) return true;
-
- if ( m_phase == AEP_DELAY )
- {
- m_progress += event.rTime*m_speed;
- if ( m_progress < 1.0f ) return true;
-
- alien = new CObject(m_iMan);
- if ( !alien->CreateInsect(m_object->RetPosition(0), m_object->RetAngleY(0), m_type) )
- {
- delete alien;
- m_phase = AEP_DELAY;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- return true;
- }
- alien->SetActivity(false);
- alien->ReadProgram(0, m_string);
- alien->RunProgram(0);
- Init();
- }
-
- alien = SearchAlien();
- if ( alien == 0 ) return true;
- alien->SetActivity(false);
-
- m_progress += event.rTime*m_speed;
-
- if ( m_phase == AEP_ZOOM )
- {
- if ( m_type == OBJECT_ANT ||
- m_type == OBJECT_SPIDER ||
- m_type == OBJECT_BEE )
- {
- alien->SetZoom(0, 0.2f+m_progress*0.8f); // Others push
- }
- }
-
- return true;
-}
-
-// Indicates whether the controller has completed its activity.
-
-Error CAutoEgg::IsEnded()
-{
- CObject* alien;
- CPyro* pyro;
-
- if ( m_phase == AEP_DELAY )
- {
- return ERR_CONTINUE;
- }
-
- alien = SearchAlien();
- if ( alien == 0 ) return ERR_STOP;
-
- if ( m_phase == AEP_INCUB )
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_phase = AEP_ZOOM;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- }
-
- if ( m_phase == AEP_ZOOM )
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_EGG, m_object); // exploding egg
-
- alien->SetZoom(0, 1.0f); // this is a big boy now
-
- m_phase = AEP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- }
-
- if ( m_phase == AEP_WAIT )
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- alien->SetLock(false);
- alien->SetActivity(true); // the insect is active
- }
-
- return ERR_STOP;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoEgg::RetError()
-{
- return ERR_OK;
-}
-
-
-// Seeking the insect that starts in the egg.
-
-CObject* CAutoEgg::SearchAlien()
-{
- CObject* pObj;
- CObject* pBest;
- Math::Vector cPos, oPos;
- ObjectType type;
- float dist, min;
- int i;
-
- cPos = m_object->RetPosition(0);
- min = 100000.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetTruck() != 0 ) continue;
-
- type = pObj->RetType();
- if ( type != OBJECT_ANT &&
- type != OBJECT_BEE &&
- type != OBJECT_SPIDER &&
- type != OBJECT_WORM ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, cPos);
- if ( dist < 8.0f && dist < min )
- {
- min = dist;
- pBest = pObj;
- }
- }
- return pBest;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoEgg::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == AEP_NULL ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.5f", m_speed);
- strcat(line, name);
-
- sprintf(name, " aParamType=%s", GetTypeObject(m_type));
- strcat(line, name);
-
- sprintf(name, " aParamValue1=%.2f", m_value);
- strcat(line, name);
-
- sprintf(name, " aParamString=\"%s\"", m_string);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoEgg::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoEggPhase)OpInt(line, "aPhase", AEP_NULL);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
- m_type = OpTypeObject(line, "aParamType", OBJECT_NULL);
- m_value = OpFloat(line, "aParamValue1", 0.0f);
- OpString(line, "aParamString", m_string);
-
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoegg.h"
+
+#include "math/geometry.h"
+#include "common/iman.h"
+#include "script/cmdtoken.h"
+
+
+
+
+// Object's constructor.
+
+CAutoEgg::CAutoEgg(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ m_type = OBJECT_NULL;
+ m_value = 0.0f;
+ m_string[0] = 0;
+
+ m_param = 0;
+ m_phase = AEP_NULL;
+ Init();
+}
+
+// Object's destructor.
+
+CAutoEgg::~CAutoEgg()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoEgg::DeleteObject(bool bAll)
+{
+ CObject* alien;
+
+ CAuto::DeleteObject(bAll);
+
+ if ( !bAll )
+ {
+ alien = SearchAlien();
+ if ( alien != 0 )
+ {
+ // Probably the intended action
+ // Original code: ( alien->RetZoom(0) == 1.0f )
+ if ( alien->RetZoomY(0) == 1.0f )
+ {
+ alien->SetLock(false);
+ alien->SetActivity(true); // the insect is active
+ }
+ else
+ {
+ alien->DeleteObject();
+ delete alien;
+ }
+ }
+ }
+}
+
+
+// Initialize the object.
+
+void CAutoEgg::Init()
+{
+ CObject* alien;
+
+ alien = SearchAlien();
+ if ( alien == 0 )
+ {
+ m_phase = AEP_NULL;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ m_time = 0.0f;
+ return;
+ }
+
+ m_phase = AEP_INCUB;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ m_time = 0.0f;
+
+ m_type = alien->RetType();
+
+ if ( m_type == OBJECT_ANT ||
+ m_type == OBJECT_SPIDER ||
+ m_type == OBJECT_BEE )
+ {
+ alien->SetZoom(0, 0.2f);
+ }
+ if ( m_type == OBJECT_WORM )
+ {
+ alien->SetZoom(0, 0.01f); // invisible !
+ }
+ alien->SetLock(true);
+ alien->SetActivity(false);
+}
+
+
+// Gives a value.
+
+bool CAutoEgg::SetType(ObjectType type)
+{
+ m_type = type;
+ return true;
+}
+
+// Gives a value.
+
+bool CAutoEgg::SetValue(int rank, float value)
+{
+ if ( rank != 0 ) return false;
+ m_value = value;
+ return true;
+}
+
+// Gives the string.
+
+bool CAutoEgg::SetString(char *string)
+{
+ strcpy(m_string, string);
+ return true;
+}
+
+
+// Start object.
+
+void CAutoEgg::Start(int param)
+{
+ if ( m_type == OBJECT_NULL ) return;
+ if ( m_value == 0.0f ) return;
+
+ m_phase = AEP_DELAY;
+ m_progress = 0.0f;
+ m_speed = 1.0f/m_value;
+
+ m_param = param;
+}
+
+
+// Management of an event.
+
+bool CAutoEgg::EventProcess(const Event &event)
+{
+ CObject* alien;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_phase == AEP_NULL ) return true;
+
+ if ( m_phase == AEP_DELAY )
+ {
+ m_progress += event.rTime*m_speed;
+ if ( m_progress < 1.0f ) return true;
+
+ alien = new CObject(m_iMan);
+ if ( !alien->CreateInsect(m_object->RetPosition(0), m_object->RetAngleY(0), m_type) )
+ {
+ delete alien;
+ m_phase = AEP_DELAY;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ return true;
+ }
+ alien->SetActivity(false);
+ alien->ReadProgram(0, m_string);
+ alien->RunProgram(0);
+ Init();
+ }
+
+ alien = SearchAlien();
+ if ( alien == 0 ) return true;
+ alien->SetActivity(false);
+
+ m_progress += event.rTime*m_speed;
+
+ if ( m_phase == AEP_ZOOM )
+ {
+ if ( m_type == OBJECT_ANT ||
+ m_type == OBJECT_SPIDER ||
+ m_type == OBJECT_BEE )
+ {
+ alien->SetZoom(0, 0.2f+m_progress*0.8f); // Others push
+ }
+ }
+
+ return true;
+}
+
+// Indicates whether the controller has completed its activity.
+
+Error CAutoEgg::IsEnded()
+{
+ CObject* alien;
+ CPyro* pyro;
+
+ if ( m_phase == AEP_DELAY )
+ {
+ return ERR_CONTINUE;
+ }
+
+ alien = SearchAlien();
+ if ( alien == 0 ) return ERR_STOP;
+
+ if ( m_phase == AEP_INCUB )
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_phase = AEP_ZOOM;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ }
+
+ if ( m_phase == AEP_ZOOM )
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_EGG, m_object); // exploding egg
+
+ alien->SetZoom(0, 1.0f); // this is a big boy now
+
+ m_phase = AEP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ }
+
+ if ( m_phase == AEP_WAIT )
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ alien->SetLock(false);
+ alien->SetActivity(true); // the insect is active
+ }
+
+ return ERR_STOP;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoEgg::RetError()
+{
+ return ERR_OK;
+}
+
+
+// Seeking the insect that starts in the egg.
+
+CObject* CAutoEgg::SearchAlien()
+{
+ CObject* pObj;
+ CObject* pBest;
+ Math::Vector cPos, oPos;
+ ObjectType type;
+ float dist, min;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+ min = 100000.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_ANT &&
+ type != OBJECT_BEE &&
+ type != OBJECT_SPIDER &&
+ type != OBJECT_WORM ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, cPos);
+ if ( dist < 8.0f && dist < min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+ return pBest;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoEgg::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == AEP_NULL ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.5f", m_speed);
+ strcat(line, name);
+
+ sprintf(name, " aParamType=%s", GetTypeObject(m_type));
+ strcat(line, name);
+
+ sprintf(name, " aParamValue1=%.2f", m_value);
+ strcat(line, name);
+
+ sprintf(name, " aParamString=\"%s\"", m_string);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoEgg::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoEggPhase)OpInt(line, "aPhase", AEP_NULL);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+ m_type = OpTypeObject(line, "aParamType", OBJECT_NULL);
+ m_value = OpFloat(line, "aParamValue1", 0.0f);
+ OpString(line, "aParamString", m_string);
+
+ return true;
+}
+
diff --git a/src/object/auto/autoegg.h b/src/object/auto/autoegg.h
index fcdf760..443dff6 100644
--- a/src/object/auto/autoegg.h
+++ b/src/object/auto/autoegg.h
@@ -1,69 +1,69 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoegg.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-enum AutoEggPhase
-{
- AEP_NULL = 0,
- AEP_DELAY = 1,
- AEP_INCUB = 3,
- AEP_ZOOM = 4,
- AEP_WAIT = 5,
-};
-
-
-
-class CAutoEgg : public CAuto
-{
-public:
- CAutoEgg(CInstanceManager* iMan, CObject* object);
- ~CAutoEgg();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- void Start(int param);
- bool EventProcess(const Event &event);
- Error IsEnded();
- Error RetError();
-
- bool SetType(ObjectType type);
- bool SetValue(int rank, float value);
- bool SetString(char *string);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- CObject* SearchAlien();
-
-protected:
- ObjectType m_type;
- float m_value;
- char m_string[100];
- int m_param;
- AutoEggPhase m_phase;
- float m_progress;
- float m_speed;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoegg.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+enum AutoEggPhase
+{
+ AEP_NULL = 0,
+ AEP_DELAY = 1,
+ AEP_INCUB = 3,
+ AEP_ZOOM = 4,
+ AEP_WAIT = 5,
+};
+
+
+
+class CAutoEgg : public CAuto
+{
+public:
+ CAutoEgg(CInstanceManager* iMan, CObject* object);
+ ~CAutoEgg();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ void Start(int param);
+ bool EventProcess(const Event &event);
+ Error IsEnded();
+ Error RetError();
+
+ bool SetType(ObjectType type);
+ bool SetValue(int rank, float value);
+ bool SetString(char *string);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ CObject* SearchAlien();
+
+protected:
+ ObjectType m_type;
+ float m_value;
+ char m_string[100];
+ int m_param;
+ AutoEggPhase m_phase;
+ float m_progress;
+ float m_speed;
+};
+
diff --git a/src/object/auto/autoenergy.cpp b/src/object/auto/autoenergy.cpp
index 74db234..37c2f29 100644
--- a/src/object/auto/autoenergy.cpp
+++ b/src/object/auto/autoenergy.cpp
@@ -1,647 +1,647 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoenergy.h"
-
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "math/geometry.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/gauge.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-
-
-
-const float ENERGY_POWER = 0.4f; // Necessary energy for a battery
-const float ENERGY_DELAY = 12.0f; // processing time
-
-
-
-
-// Object's constructor.
-
-CAutoEnergy::CAutoEnergy(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- m_partiSphere = -1;
- Init();
-}
-
-// Object's destructor.
-
-CAutoEnergy::~CAutoEnergy()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoEnergy::DeleteObject(bool bAll)
-{
- CObject* fret;
-
- if ( m_partiSphere != -1 )
- {
- m_particule->DeleteParticule(m_partiSphere);
- m_partiSphere = -1;
- }
-
- if ( !bAll )
- {
- fret = SearchMetal();
- if ( fret != 0 )
- {
- fret->DeleteObject(); // destroys the metal
- delete fret;
- }
-
- fret = SearchPower();
- if ( fret != 0 )
- {
- fret->DeleteObject(); // destroys the cell
- delete fret;
- }
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoEnergy::Init()
-{
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastUpdateTime = 0.0f;
- m_lastParticule = 0.0f;
-
- m_phase = AENP_WAIT; // waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoEnergy::EventProcess(const Event &event)
-{
- CObject* fret;
- Math::Vector pos, ppos, speed;
- Math::Point dim, c, p;
- TerrainRes res;
- float big;
- bool bGO;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
- pos = m_object->RetPosition(0);
- pos.y += 10.0f;
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = -7.0f;
- dim.x = Math::Rand()*0.5f+0.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ, 1.0f, 0.0f, 0.0f);
- }
- }
- return true;
- }
-
- UpdateInterface(event.rTime);
- EventProgress(event.rTime);
-
- big = m_object->RetEnergy();
-
- res = m_terrain->RetResource(m_object->RetPosition(0));
- if ( res == TR_POWER )
- {
- big += event.rTime*0.01f; // recharges the big pile
- }
-
- if ( m_phase == AENP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- bGO = false;
- fret = SearchMetal(); // transform metal?
- if ( fret != 0 )
- {
- if ( fret->RetType() == OBJECT_METAL )
- {
- if ( big > ENERGY_POWER ) bGO = true;
- }
- else
- {
- if ( !SearchVehicle() ) bGO = true;
- }
- }
-
- if ( bGO )
- {
- if ( fret->RetType() == OBJECT_METAL )
- {
- fret->SetLock(true); // usable metal
- CreatePower(); // creates the battery
- }
-
- SetBusy(true);
- InitProgressTotal(ENERGY_DELAY);
- CAuto::UpdateInterface();
-
- pos = m_object->RetPosition(0);
- pos.y += 4.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 3.0f;
- dim.y = dim.x;
- m_partiSphere = m_particule->CreateParticule(pos, speed, dim, PARTISPHERE1, ENERGY_DELAY, 0.0f, 0.0f);
-
- m_phase = AENP_CREATE;
- m_progress = 0.0f;
- m_speed = 1.0f/ENERGY_DELAY;
- }
- else
- {
- if ( rand()%3 == 0 && big > 0.01f )
- {
- m_phase = AENP_BLITZ;
- m_progress = 0.0f;
- m_speed = 1.0f/Math::Rand()*1.0f+1.0f;
- }
- else
- {
- m_phase = AENP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
- }
- }
-
- if ( m_phase == AENP_BLITZ )
- {
- if ( m_progress < 1.0f && big > 0.01f )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
- pos = m_object->RetPosition(0);
- pos.y += 10.0f;
- speed.x = (Math::Rand()-0.5f)*1.0f;
- speed.z = (Math::Rand()-0.5f)*1.0f;
- speed.y = -7.0f;
- dim.x = Math::Rand()*0.5f+0.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ, 1.0f, 0.0f, 0.0f);
- }
- }
- else
- {
- m_phase = AENP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == AENP_CREATE )
- {
- if ( m_progress < 1.0f )
- {
- fret = SearchMetal();
- if ( fret != 0 )
- {
- if ( fret->RetType() == OBJECT_METAL )
- {
- big -= event.rTime/ENERGY_DELAY*ENERGY_POWER;
- }
- else
- {
- big += event.rTime/ENERGY_DELAY*0.25f;
- }
- fret->SetZoom(0, 1.0f-m_progress);
- }
-
- fret = SearchPower();
- if ( fret != 0 )
- {
- fret->SetZoom(0, m_progress);
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- c.x = pos.x;
- c.y = pos.z;
- p.x = c.x;
- p.y = c.y+2.0f;
- p = Math::RotatePoint(c, Math::Rand()*Math::PI*2.0f, p);
- pos.x = p.x;
- pos.z = p.y;
- pos.y += 2.5f+Math::Rand()*3.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*2.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 1.0f, 0.0f, 0.0f);
-
- pos = m_object->RetPosition(0);
- pos.y += 3.0f;
- speed.x = (Math::Rand()-0.5f)*30.0f;
- speed.z = (Math::Rand()-0.5f)*30.0f;
- speed.y = Math::Rand()*20.0f+10.0f;
- dim.x = Math::Rand()*0.4f+0.4f;
- dim.y = dim.x;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK2, 2.0f, 50.0f, 1.2f, 1.2f);
-
- pos = m_object->RetPosition(0);
- pos.y += 10.0f;
- speed.x = (Math::Rand()-0.5f)*1.5f;
- speed.z = (Math::Rand()-0.5f)*1.5f;
- speed.y = -6.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ, 1.0f, 0.0f, 0.0f);
-
- m_sound->Play(SOUND_ENERGY, m_object->RetPosition(0),
- 1.0f, 1.0f+Math::Rand()*1.5f);
- }
- }
- else
- {
- fret = SearchMetal();
- if ( fret != 0 )
- {
- m_object->SetPower(0);
- fret->DeleteObject(); // destroys the metal
- delete fret;
- }
-
- fret = SearchPower();
- if ( fret != 0 )
- {
- fret->SetZoom(0, 1.0f);
- fret->SetLock(false); // usable battery
- fret->SetTruck(m_object);
- fret->SetPosition(0, Math::Vector(0.0f, 3.0f, 0.0f));
- m_object->SetPower(fret);
-
- m_displayText->DisplayError(INFO_ENERGY, m_object);
- }
-
- SetBusy(false);
- CAuto::UpdateInterface();
-
- m_phase = AENP_SMOKE;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- }
- }
-
- if ( m_phase == AENP_SMOKE )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.y += 17.0f;
- pos.x += (Math::Rand()-0.5f)*3.0f;
- pos.z += (Math::Rand()-0.5f)*3.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 6.0f+Math::Rand()*6.0f;
- dim.x = Math::Rand()*1.5f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
- }
- }
- else
- {
- m_phase = AENP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( big < 0.0f ) big = 0.0f;
- if ( big > 1.0f ) big = 1.0f;
- m_object->SetEnergy(big); // shift the big pile
-
- return true;
-}
-
-
-// Seeking the metal object.
-
-CObject* CAutoEnergy::SearchMetal()
-{
- CObject* pObj;
- ObjectType type;
-
- pObj = m_object->RetPower();
- if ( pObj == 0 ) return 0;
-
- type = pObj->RetType();
- if ( type == OBJECT_METAL ||
- type == OBJECT_SCRAP1 ||
- type == OBJECT_SCRAP2 ||
- type == OBJECT_SCRAP3 ) return pObj;
-
- return 0;
-}
-
-// Search if a vehicle is too close.
-
-bool CAutoEnergy::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType type;
- float oRadius, dist;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr &&
- type != OBJECT_MOTHER &&
- type != OBJECT_ANT &&
- type != OBJECT_SPIDER &&
- type != OBJECT_BEE &&
- type != OBJECT_WORM ) continue;
-
- if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
- dist = Math::Distance(oPos, cPos)-oRadius;
-
- if ( dist < 10.0f ) return true;
- }
-
- return false;
-}
-
-// Create a cell.
-
-void CAutoEnergy::CreatePower()
-{
- CObject* power;
- Math::Vector pos;
- float angle;
-
- pos = m_object->RetPosition(0);
- angle = m_object->RetAngleY(0);
-
- power = new CObject(m_iMan);
- if ( !power->CreateResource(pos, angle, OBJECT_POWER) )
- {
- delete power;
- m_displayText->DisplayError(ERR_TOOMANY, m_object);
- return;
- }
- power->SetLock(true); // battery not yet usable
-
- pos = power->RetPosition(0);
- pos.y += 3.0f;
- power->SetPosition(0, pos);
-}
-
-// Seeking the battery during manufacture.
-
-CObject* CAutoEnergy::SearchPower()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType type;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetLock() ) continue;
-
- type = pObj->RetType();
- if ( type != OBJECT_POWER ) continue;
-
- oPos = pObj->RetPosition(0);
- if ( oPos.x == cPos.x &&
- oPos.z == cPos.z )
- {
- return pObj;
- }
- }
-
- return 0;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoEnergy::RetError()
-{
- CObject* pObj;
- ObjectType type;
- TerrainRes res;
-
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- if ( m_phase != AENP_WAIT &&
- m_phase != AENP_BLITZ ) return ERR_OK;
-
- res = m_terrain->RetResource(m_object->RetPosition(0));
- if ( res != TR_POWER ) return ERR_ENERGY_NULL;
-
- if ( m_object->RetEnergy() < ENERGY_POWER ) return ERR_ENERGY_LOW;
-
- pObj = m_object->RetPower();
- if ( pObj == 0 ) return ERR_ENERGY_EMPTY;
- type = pObj->RetType();
- if ( type == OBJECT_POWER ) return ERR_OK;
- if ( type != OBJECT_METAL &&
- type != OBJECT_SCRAP1 &&
- type != OBJECT_SCRAP2 &&
- type != OBJECT_SCRAP3 ) return ERR_ENERGY_BAD;
-
- return ERR_OK;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoEnergy::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*14.5f;
- pos.y = oy+sy*0;
- ddim.x = 14.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 108, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-// Updates the state of all buttons on the interface,
-// following the time that elapses ...
-
-void CAutoEnergy::UpdateInterface(float rTime)
-{
- CWindow* pw;
- CGauge* pg;
-
- CAuto::UpdateInterface(rTime);
-
- if ( m_time < m_lastUpdateTime+0.1f ) return;
- m_lastUpdateTime = m_time;
-
- if ( !m_object->RetSelect() ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
- if ( pg != 0 )
- {
- pg->SetLevel(m_object->RetEnergy());
- }
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoEnergy::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == AENP_STOP ||
- m_phase == AENP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoEnergy::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoEnergyPhase)OpInt(line, "aPhase", AENP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastUpdateTime = 0.0f;
- m_lastParticule = 0.0f;
-
- return true;
-}
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoenergy.h"
+
+#include "common/iman.h"
+#include "old/terrain.h"
+#include "math/geometry.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/gauge.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+
+
+
+const float ENERGY_POWER = 0.4f; // Necessary energy for a battery
+const float ENERGY_DELAY = 12.0f; // processing time
+
+
+
+
+// Object's constructor.
+
+CAutoEnergy::CAutoEnergy(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ m_partiSphere = -1;
+ Init();
+}
+
+// Object's destructor.
+
+CAutoEnergy::~CAutoEnergy()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoEnergy::DeleteObject(bool bAll)
+{
+ CObject* fret;
+
+ if ( m_partiSphere != -1 )
+ {
+ m_particule->DeleteParticule(m_partiSphere);
+ m_partiSphere = -1;
+ }
+
+ if ( !bAll )
+ {
+ fret = SearchMetal();
+ if ( fret != 0 )
+ {
+ fret->DeleteObject(); // destroys the metal
+ delete fret;
+ }
+
+ fret = SearchPower();
+ if ( fret != 0 )
+ {
+ fret->DeleteObject(); // destroys the cell
+ delete fret;
+ }
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoEnergy::Init()
+{
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastUpdateTime = 0.0f;
+ m_lastParticule = 0.0f;
+
+ m_phase = AENP_WAIT; // waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoEnergy::EventProcess(const Event &event)
+{
+ CObject* fret;
+ Math::Vector pos, ppos, speed;
+ Math::Point dim, c, p;
+ TerrainRes res;
+ float big;
+ bool bGO;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+ pos = m_object->RetPosition(0);
+ pos.y += 10.0f;
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = -7.0f;
+ dim.x = Math::Rand()*0.5f+0.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ, 1.0f, 0.0f, 0.0f);
+ }
+ }
+ return true;
+ }
+
+ UpdateInterface(event.rTime);
+ EventProgress(event.rTime);
+
+ big = m_object->RetEnergy();
+
+ res = m_terrain->RetResource(m_object->RetPosition(0));
+ if ( res == TR_POWER )
+ {
+ big += event.rTime*0.01f; // recharges the big pile
+ }
+
+ if ( m_phase == AENP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ bGO = false;
+ fret = SearchMetal(); // transform metal?
+ if ( fret != 0 )
+ {
+ if ( fret->RetType() == OBJECT_METAL )
+ {
+ if ( big > ENERGY_POWER ) bGO = true;
+ }
+ else
+ {
+ if ( !SearchVehicle() ) bGO = true;
+ }
+ }
+
+ if ( bGO )
+ {
+ if ( fret->RetType() == OBJECT_METAL )
+ {
+ fret->SetLock(true); // usable metal
+ CreatePower(); // creates the battery
+ }
+
+ SetBusy(true);
+ InitProgressTotal(ENERGY_DELAY);
+ CAuto::UpdateInterface();
+
+ pos = m_object->RetPosition(0);
+ pos.y += 4.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 3.0f;
+ dim.y = dim.x;
+ m_partiSphere = m_particule->CreateParticule(pos, speed, dim, PARTISPHERE1, ENERGY_DELAY, 0.0f, 0.0f);
+
+ m_phase = AENP_CREATE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/ENERGY_DELAY;
+ }
+ else
+ {
+ if ( rand()%3 == 0 && big > 0.01f )
+ {
+ m_phase = AENP_BLITZ;
+ m_progress = 0.0f;
+ m_speed = 1.0f/Math::Rand()*1.0f+1.0f;
+ }
+ else
+ {
+ m_phase = AENP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+ }
+ }
+
+ if ( m_phase == AENP_BLITZ )
+ {
+ if ( m_progress < 1.0f && big > 0.01f )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+ pos = m_object->RetPosition(0);
+ pos.y += 10.0f;
+ speed.x = (Math::Rand()-0.5f)*1.0f;
+ speed.z = (Math::Rand()-0.5f)*1.0f;
+ speed.y = -7.0f;
+ dim.x = Math::Rand()*0.5f+0.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ, 1.0f, 0.0f, 0.0f);
+ }
+ }
+ else
+ {
+ m_phase = AENP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == AENP_CREATE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ fret = SearchMetal();
+ if ( fret != 0 )
+ {
+ if ( fret->RetType() == OBJECT_METAL )
+ {
+ big -= event.rTime/ENERGY_DELAY*ENERGY_POWER;
+ }
+ else
+ {
+ big += event.rTime/ENERGY_DELAY*0.25f;
+ }
+ fret->SetZoom(0, 1.0f-m_progress);
+ }
+
+ fret = SearchPower();
+ if ( fret != 0 )
+ {
+ fret->SetZoom(0, m_progress);
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ c.x = pos.x;
+ c.y = pos.z;
+ p.x = c.x;
+ p.y = c.y+2.0f;
+ p = Math::RotatePoint(c, Math::Rand()*Math::PI*2.0f, p);
+ pos.x = p.x;
+ pos.z = p.y;
+ pos.y += 2.5f+Math::Rand()*3.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*2.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 1.0f, 0.0f, 0.0f);
+
+ pos = m_object->RetPosition(0);
+ pos.y += 3.0f;
+ speed.x = (Math::Rand()-0.5f)*30.0f;
+ speed.z = (Math::Rand()-0.5f)*30.0f;
+ speed.y = Math::Rand()*20.0f+10.0f;
+ dim.x = Math::Rand()*0.4f+0.4f;
+ dim.y = dim.x;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK2, 2.0f, 50.0f, 1.2f, 1.2f);
+
+ pos = m_object->RetPosition(0);
+ pos.y += 10.0f;
+ speed.x = (Math::Rand()-0.5f)*1.5f;
+ speed.z = (Math::Rand()-0.5f)*1.5f;
+ speed.y = -6.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ, 1.0f, 0.0f, 0.0f);
+
+ m_sound->Play(SOUND_ENERGY, m_object->RetPosition(0),
+ 1.0f, 1.0f+Math::Rand()*1.5f);
+ }
+ }
+ else
+ {
+ fret = SearchMetal();
+ if ( fret != 0 )
+ {
+ m_object->SetPower(0);
+ fret->DeleteObject(); // destroys the metal
+ delete fret;
+ }
+
+ fret = SearchPower();
+ if ( fret != 0 )
+ {
+ fret->SetZoom(0, 1.0f);
+ fret->SetLock(false); // usable battery
+ fret->SetTruck(m_object);
+ fret->SetPosition(0, Math::Vector(0.0f, 3.0f, 0.0f));
+ m_object->SetPower(fret);
+
+ m_displayText->DisplayError(INFO_ENERGY, m_object);
+ }
+
+ SetBusy(false);
+ CAuto::UpdateInterface();
+
+ m_phase = AENP_SMOKE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ }
+ }
+
+ if ( m_phase == AENP_SMOKE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.y += 17.0f;
+ pos.x += (Math::Rand()-0.5f)*3.0f;
+ pos.z += (Math::Rand()-0.5f)*3.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 6.0f+Math::Rand()*6.0f;
+ dim.x = Math::Rand()*1.5f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
+ }
+ }
+ else
+ {
+ m_phase = AENP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( big < 0.0f ) big = 0.0f;
+ if ( big > 1.0f ) big = 1.0f;
+ m_object->SetEnergy(big); // shift the big pile
+
+ return true;
+}
+
+
+// Seeking the metal object.
+
+CObject* CAutoEnergy::SearchMetal()
+{
+ CObject* pObj;
+ ObjectType type;
+
+ pObj = m_object->RetPower();
+ if ( pObj == 0 ) return 0;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_METAL ||
+ type == OBJECT_SCRAP1 ||
+ type == OBJECT_SCRAP2 ||
+ type == OBJECT_SCRAP3 ) return pObj;
+
+ return 0;
+}
+
+// Search if a vehicle is too close.
+
+bool CAutoEnergy::SearchVehicle()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType type;
+ float oRadius, dist;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_HUMAN &&
+ type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis &&
+ type != OBJECT_MOBILErt &&
+ type != OBJECT_MOBILErc &&
+ type != OBJECT_MOBILErr &&
+ type != OBJECT_MOBILErs &&
+ type != OBJECT_MOBILEsa &&
+ type != OBJECT_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_MOBILEdr &&
+ type != OBJECT_MOTHER &&
+ type != OBJECT_ANT &&
+ type != OBJECT_SPIDER &&
+ type != OBJECT_BEE &&
+ type != OBJECT_WORM ) continue;
+
+ if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
+ dist = Math::Distance(oPos, cPos)-oRadius;
+
+ if ( dist < 10.0f ) return true;
+ }
+
+ return false;
+}
+
+// Create a cell.
+
+void CAutoEnergy::CreatePower()
+{
+ CObject* power;
+ Math::Vector pos;
+ float angle;
+
+ pos = m_object->RetPosition(0);
+ angle = m_object->RetAngleY(0);
+
+ power = new CObject(m_iMan);
+ if ( !power->CreateResource(pos, angle, OBJECT_POWER) )
+ {
+ delete power;
+ m_displayText->DisplayError(ERR_TOOMANY, m_object);
+ return;
+ }
+ power->SetLock(true); // battery not yet usable
+
+ pos = power->RetPosition(0);
+ pos.y += 3.0f;
+ power->SetPosition(0, pos);
+}
+
+// Seeking the battery during manufacture.
+
+CObject* CAutoEnergy::SearchPower()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType type;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetLock() ) continue;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_POWER ) continue;
+
+ oPos = pObj->RetPosition(0);
+ if ( oPos.x == cPos.x &&
+ oPos.z == cPos.z )
+ {
+ return pObj;
+ }
+ }
+
+ return 0;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoEnergy::RetError()
+{
+ CObject* pObj;
+ ObjectType type;
+ TerrainRes res;
+
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ if ( m_phase != AENP_WAIT &&
+ m_phase != AENP_BLITZ ) return ERR_OK;
+
+ res = m_terrain->RetResource(m_object->RetPosition(0));
+ if ( res != TR_POWER ) return ERR_ENERGY_NULL;
+
+ if ( m_object->RetEnergy() < ENERGY_POWER ) return ERR_ENERGY_LOW;
+
+ pObj = m_object->RetPower();
+ if ( pObj == 0 ) return ERR_ENERGY_EMPTY;
+ type = pObj->RetType();
+ if ( type == OBJECT_POWER ) return ERR_OK;
+ if ( type != OBJECT_METAL &&
+ type != OBJECT_SCRAP1 &&
+ type != OBJECT_SCRAP2 &&
+ type != OBJECT_SCRAP3 ) return ERR_ENERGY_BAD;
+
+ return ERR_OK;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoEnergy::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*14.5f;
+ pos.y = oy+sy*0;
+ ddim.x = 14.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 108, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+// Updates the state of all buttons on the interface,
+// following the time that elapses ...
+
+void CAutoEnergy::UpdateInterface(float rTime)
+{
+ CWindow* pw;
+ CGauge* pg;
+
+ CAuto::UpdateInterface(rTime);
+
+ if ( m_time < m_lastUpdateTime+0.1f ) return;
+ m_lastUpdateTime = m_time;
+
+ if ( !m_object->RetSelect() ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
+ if ( pg != 0 )
+ {
+ pg->SetLevel(m_object->RetEnergy());
+ }
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoEnergy::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == AENP_STOP ||
+ m_phase == AENP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoEnergy::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoEnergyPhase)OpInt(line, "aPhase", AENP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastUpdateTime = 0.0f;
+ m_lastParticule = 0.0f;
+
+ return true;
+}
diff --git a/src/object/auto/autoenergy.h b/src/object/auto/autoenergy.h
index 300ee45..727f2c3 100644
--- a/src/object/auto/autoenergy.h
+++ b/src/object/auto/autoenergy.h
@@ -1,71 +1,71 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoenergy.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoEnergyPhase
-{
- AENP_STOP = 1,
- AENP_WAIT = 2,
- AENP_BLITZ = 3,
- AENP_CREATE = 4,
- AENP_SMOKE = 5,
-};
-
-
-
-class CAutoEnergy : public CAuto
-{
-public:
- CAutoEnergy(CInstanceManager* iMan, CObject* object);
- ~CAutoEnergy();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- void UpdateInterface(float rTime);
-
- CObject* SearchMetal();
- bool SearchVehicle();
- void CreatePower();
- CObject* SearchPower();
-
-protected:
- AutoEnergyPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastUpdateTime;
- float m_lastParticule;
- int m_partiSphere;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoenergy.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoEnergyPhase
+{
+ AENP_STOP = 1,
+ AENP_WAIT = 2,
+ AENP_BLITZ = 3,
+ AENP_CREATE = 4,
+ AENP_SMOKE = 5,
+};
+
+
+
+class CAutoEnergy : public CAuto
+{
+public:
+ CAutoEnergy(CInstanceManager* iMan, CObject* object);
+ ~CAutoEnergy();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ void UpdateInterface(float rTime);
+
+ CObject* SearchMetal();
+ bool SearchVehicle();
+ void CreatePower();
+ CObject* SearchPower();
+
+protected:
+ AutoEnergyPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastUpdateTime;
+ float m_lastParticule;
+ int m_partiSphere;
+};
+
diff --git a/src/object/auto/autofactory.cpp b/src/object/auto/autofactory.cpp
index be5a189..f02195c 100644
--- a/src/object/auto/autofactory.cpp
+++ b/src/object/auto/autofactory.cpp
@@ -1,941 +1,941 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autofactory.h"
-
-#include "common/global.h"
-#include "common/iman.h"
-#include "math/geometry.h"
-#include "object/robotmain.h"
-#include "physics/physics.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-
-
-
-
-
-// Object's constructor.
-
-CAutoFactory::CAutoFactory(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
- m_type = OBJECT_MOBILEws;
- m_phase = AFP_WAIT; // paused until the first Init ()
- m_channelSound = -1;
-}
-
-// Object's destructor.
-
-CAutoFactory::~CAutoFactory()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoFactory::DeleteObject(bool bAll)
-{
- CObject* fret;
- CObject* vehicle;
-
- if ( !bAll )
- {
- fret = SearchFret(); // transform metal?
- if ( fret != 0 )
- {
- fret->DeleteObject(); // destroys the metal
- delete fret;
- }
-
- vehicle = SearchVehicle();
- if ( vehicle != 0 )
- {
- vehicle->DeleteObject(); // destroys the vehicle
- delete vehicle;
- }
- }
-
- if ( m_channelSound != -1 )
- {
- m_sound->FlushEnvelope(m_channelSound);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_channelSound = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoFactory::Init()
-{
- m_phase = AFP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- m_time = 0.0f;
- m_lastParticule = 0.0f;
-
- m_fretPos = m_object->RetPosition(0);
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoFactory::EventProcess(const Event &event)
-{
- CObject* fret;
- CObject* vehicle;
- Math::Matrix* mat;
- CPhysics* physics;
- Math::Vector pos, speed;
- Math::Point dim;
- ObjectType type;
- float zoom, angle, prog;
- int i;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
-
- if ( m_object->RetSelect() ) // factory selected?
- {
- if ( event.event == EVENT_UPDINTERFACE )
- {
- CreateInterface(true);
- }
-
- type = OBJECT_NULL;
- if ( event.event == EVENT_OBJECT_FACTORYwa ) type = OBJECT_MOBILEwa;
- if ( event.event == EVENT_OBJECT_FACTORYta ) type = OBJECT_MOBILEta;
- if ( event.event == EVENT_OBJECT_FACTORYfa ) type = OBJECT_MOBILEfa;
- if ( event.event == EVENT_OBJECT_FACTORYia ) type = OBJECT_MOBILEia;
- if ( event.event == EVENT_OBJECT_FACTORYws ) type = OBJECT_MOBILEws;
- if ( event.event == EVENT_OBJECT_FACTORYts ) type = OBJECT_MOBILEts;
- if ( event.event == EVENT_OBJECT_FACTORYfs ) type = OBJECT_MOBILEfs;
- if ( event.event == EVENT_OBJECT_FACTORYis ) type = OBJECT_MOBILEis;
- if ( event.event == EVENT_OBJECT_FACTORYwc ) type = OBJECT_MOBILEwc;
- if ( event.event == EVENT_OBJECT_FACTORYtc ) type = OBJECT_MOBILEtc;
- if ( event.event == EVENT_OBJECT_FACTORYfc ) type = OBJECT_MOBILEfc;
- if ( event.event == EVENT_OBJECT_FACTORYic ) type = OBJECT_MOBILEic;
- if ( event.event == EVENT_OBJECT_FACTORYwi ) type = OBJECT_MOBILEwi;
- if ( event.event == EVENT_OBJECT_FACTORYti ) type = OBJECT_MOBILEti;
- if ( event.event == EVENT_OBJECT_FACTORYfi ) type = OBJECT_MOBILEfi;
- if ( event.event == EVENT_OBJECT_FACTORYii ) type = OBJECT_MOBILEii;
- if ( event.event == EVENT_OBJECT_FACTORYrt ) type = OBJECT_MOBILErt;
- if ( event.event == EVENT_OBJECT_FACTORYrc ) type = OBJECT_MOBILErc;
- if ( event.event == EVENT_OBJECT_FACTORYrr ) type = OBJECT_MOBILErr;
- if ( event.event == EVENT_OBJECT_FACTORYrs ) type = OBJECT_MOBILErs;
- if ( event.event == EVENT_OBJECT_FACTORYsa ) type = OBJECT_MOBILEsa;
-
- if ( type != OBJECT_NULL )
- {
- m_type = type;
-
- if ( m_phase != AFP_WAIT )
- {
- return false;
- }
-
- fret = SearchFret(); // transform metal?
- if ( fret == 0 )
- {
- m_displayText->DisplayError(ERR_FACTORY_NULL, m_object);
- return false;
- }
- if ( NearestVehicle() )
- {
- m_displayText->DisplayError(ERR_FACTORY_NEAR, m_object);
- return false;
- }
-
- SetBusy(true);
- InitProgressTotal(3.0f+2.0f+15.0f+2.0f+3.0f);
- UpdateInterface();
-
- fret->SetLock(true); // usable metal
- SoundManip(3.0f, 1.0f, 0.5f);
-
- m_phase = AFP_CLOSE_S;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- return true;
- }
- }
-
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- EventProgress(event.rTime);
-
- if ( m_phase == AFP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- m_phase = AFP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == AFP_CLOSE_S )
- {
- if ( m_progress < 1.0f )
- {
- for ( i=0 ; i<9 ; i++ )
- {
- zoom = 0.30f+(m_progress-0.5f+i/16.0f)*2.0f*0.70f;
- if ( zoom < 0.30f ) zoom = 0.30f;
- if ( zoom > 1.00f ) zoom = 1.00f;
- m_object->SetZoomZ( 1+i, zoom);
- m_object->SetZoomZ(10+i, zoom);
- }
- }
- else
- {
- for ( i=0 ; i<9 ; i++ )
- {
- m_object->SetZoomZ( 1+i, 1.0f);
- m_object->SetZoomZ(10+i, 1.0f);
- }
-
- SoundManip(2.0f, 1.0f, 1.2f);
-
- m_phase = AFP_CLOSE_T;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == AFP_CLOSE_T )
- {
- if ( m_progress < 1.0f )
- {
- for ( i=0 ; i<9 ; i++ )
- {
- angle = -m_progress*(Math::PI/2.0f)+Math::PI/2.0f;
- m_object->SetAngleZ( 1+i, angle);
- m_object->SetAngleZ(10+i, -angle);
- }
- }
- else
- {
- for ( i=0 ; i<9 ; i++ )
- {
- m_object->SetAngleZ( 1+i, 0.0f);
- m_object->SetAngleZ(10+i, 0.0f);
- }
-
- m_channelSound = m_sound->Play(SOUND_FACTORY, m_object->RetPosition(0), 0.0f, 1.0f, true);
- m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 11.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP);
-
- m_phase = AFP_BUILD;
- m_progress = 0.0f;
- m_speed = 1.0f/15.0f;
- }
- }
-
- if ( m_phase == AFP_BUILD )
- {
- if ( m_progress == 0.0f )
- {
- if ( !CreateVehicle() )
- {
- fret = SearchFret(); // transform metal?
- if ( fret != 0 )
- {
- fret->SetLock(false); // metal usable again
- }
-
- if ( m_channelSound != -1 )
- {
- m_sound->FlushEnvelope(m_channelSound);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_channelSound = -1;
- }
-
- m_phase = AFP_OPEN_T;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- return true;
- }
- }
-
- if ( m_progress < 1.0f )
- {
- if ( m_type == OBJECT_MOBILErt ||
- m_type == OBJECT_MOBILErc ||
- m_type == OBJECT_MOBILErr ||
- m_type == OBJECT_MOBILErs )
- {
- prog = 1.0f-m_progress*1.5f;
- if ( prog < 0.0f ) prog = 0.0f;
- }
- else
- {
- prog = 1.0f-m_progress;
- }
- angle = powf(prog*10.0f, 2.0f)+m_object->RetAngleY(0);
-
- vehicle = SearchVehicle();
- if ( vehicle != 0 )
- {
- vehicle->SetAngleY(0, angle+Math::PI);
- vehicle->SetZoom(0, m_progress);
- }
-
- fret = SearchFret(); // transform metal?
- if ( fret != 0 )
- {
- fret->SetZoom(0, 1.0f-m_progress);
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
-#if 0
- pos = m_fretPos;
- pos.x += (Math::Rand()-0.5f)*20.0f;
- pos.z += (Math::Rand()-0.5f)*20.0f;
- pos.y += 1.0f;
- speed.x = (Math::Rand()-0.5f)*12.0f;
- speed.z = (Math::Rand()-0.5f)*12.0f;
- speed.y = Math::Rand()*12.0f;
- dim.x = Math::Rand()*12.0f+10.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
-#else
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(-12.0f, 20.0f, -4.0f); // position of chimney
- pos = Math::Transform(*mat, pos);
- pos.y += 2.0f;
- pos.x += (Math::Rand()-0.5f)*2.0f;
- pos.z += (Math::Rand()-0.5f)*2.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 6.0f+Math::Rand()*6.0f;
- dim.x = Math::Rand()*1.5f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
-#endif
- }
- }
- else
- {
- m_displayText->DisplayError(INFO_FACTORY, m_object);
- SoundManip(2.0f, 1.0f, 1.2f);
-
- fret = SearchFret(); // transform metal?
- if ( fret != 0 )
- {
- fret->DeleteObject(); // removes the metal
- delete fret;
- }
-
- vehicle = SearchVehicle();
- if ( vehicle != 0 )
- {
- physics = vehicle->RetPhysics();
- if ( physics != 0 )
- {
- physics->SetFreeze(false); // can move
- }
-
- vehicle->SetLock(false); // vehicle useable
-//? vehicle->RetPhysics()->RetBrain()->StartTaskAdvance(16.0f);
- vehicle->SetAngleY(0, m_object->RetAngleY(0)+Math::PI);
- vehicle->SetZoom(0, 1.0f);
- }
-
- m_main->CreateShortcuts();
-
- m_phase = AFP_OPEN_T;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == AFP_OPEN_T )
- {
- if ( m_progress < 1.0f )
- {
- for ( i=0 ; i<9 ; i++ )
- {
- angle = -(1.0f-m_progress)*(Math::PI/2.0f)+Math::PI/2.0f;
- m_object->SetAngleZ( 1+i, angle);
- m_object->SetAngleZ(10+i, -angle);
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_fretPos;
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- pos.y += Math::Rand()*10.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
- }
- }
- else
- {
- for ( i=0 ; i<9 ; i++ )
- {
- m_object->SetAngleZ( 1+i, Math::PI/2.0f);
- m_object->SetAngleZ(10+i, -Math::PI/2.0f);
- }
-
- SoundManip(3.0f, 1.0f, 0.5f);
-
- m_phase = AFP_OPEN_S;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- }
- }
-
- if ( m_phase == AFP_OPEN_S )
- {
- if ( m_progress < 1.0f )
- {
- for ( i=0 ; i<9 ; i++ )
- {
- zoom = 0.30f+((1.0f-m_progress)-0.5f+i/16.0f)*2.0f*0.70f;
- if ( zoom < 0.30f ) zoom = 0.30f;
- if ( zoom > 1.00f ) zoom = 1.00f;
- m_object->SetZoomZ( 1+i, zoom);
- m_object->SetZoomZ(10+i, zoom);
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_fretPos;
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- pos.y += Math::Rand()*10.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
- }
- }
- else
- {
- for ( i=0 ; i<9 ; i++ )
- {
- m_object->SetZoomZ( 1+i, 0.30f);
- m_object->SetZoomZ(10+i, 0.30f);
- }
-
- SetBusy(false);
- UpdateInterface();
-
- m_phase = AFP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- return true;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoFactory::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == AFP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller
-
-bool CAutoFactory::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoFactoryPhase)OpInt(line, "aPhase", AFP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
- m_fretPos = m_object->RetPosition(0);
-
- return true;
-}
-
-
-//Seeks the cargo.
-
-CObject* CAutoFactory::SearchFret()
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- float dist;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_METAL ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, m_fretPos);
-
- if ( dist < 8.0f ) return pObj;
- }
-
- return 0;
-}
-
-// Search if a vehicle is too close.
-
-bool CAutoFactory::NearestVehicle()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType type;
- float oRadius, dist;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr &&
- type != OBJECT_MOTHER &&
- type != OBJECT_ANT &&
- type != OBJECT_SPIDER &&
- type != OBJECT_BEE &&
- type != OBJECT_WORM ) continue;
-
- if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
- dist = Math::Distance(oPos, cPos)-oRadius;
-
- if ( dist < 10.0f ) return true;
- }
-
- return false;
-}
-
-
-// Creates a vehicle.
-
-bool CAutoFactory::CreateVehicle()
-{
- CObject* vehicle;
- Math::Matrix* mat;
- CPhysics* physics;
- Math::Vector pos;
- float angle;
- char* name;
- int i;
-
- angle = m_object->RetAngleY(0);
-
- mat = m_object->RetWorldMatrix(0);
- if ( m_type == OBJECT_MOBILErt ||
- m_type == OBJECT_MOBILErc ||
- m_type == OBJECT_MOBILErr ||
- m_type == OBJECT_MOBILErs )
- {
- pos = Math::Vector(2.0f, 0.0f, 0.0f);
- }
- else
- {
- pos = Math::Vector(4.0f, 0.0f, 0.0f);
- }
- pos = Transform(*mat, pos);
-
- vehicle = new CObject(m_iMan);
- if ( !vehicle->CreateVehicle(pos, angle, m_type, -1.0f, false, false) )
- {
- delete vehicle;
- m_displayText->DisplayError(ERR_TOOMANY, m_object);
- return false;
- }
- vehicle->UpdateMapping();
- vehicle->SetLock(true); // not usable
- vehicle->SetRange(30.0f);
-
- physics = vehicle->RetPhysics();
- if ( physics != 0 )
- {
- physics->SetFreeze(true); // it doesn't move
- }
-
- for ( i=0 ; i<10 ; i++ )
- {
- name = m_main->RetNewScriptName(m_type, i);
- if ( name == 0 ) break;
- vehicle->ReadProgram(i, name);
- }
-
- return true;
-}
-
-// Seeking the vehicle during manufacture.
-
-CObject* CAutoFactory::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- float dist;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetLock() ) continue;
-
- type = pObj->RetType();
- if ( type != m_type ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, m_fretPos);
-
- if ( dist < 8.0f ) return pObj;
- }
-
- return 0;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoFactory::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, dim, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- dim.x = 33.0f/640.0f;
- dim.y = 33.0f/480.0f;
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = 0.0f;
- pos.y = oy+sy*2.6f;
- ddim.x = 138.0f/640.0f;
- ddim.y = 222.0f/480.0f;
- pw->CreateGroup(pos, ddim, 6, EVENT_WINDOW3);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*8.2f;
- pw->CreateButton(pos, dim, 128+9, EVENT_OBJECT_FACTORYwa);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+10, EVENT_OBJECT_FACTORYta);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+11, EVENT_OBJECT_FACTORYfa);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+22, EVENT_OBJECT_FACTORYia);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*7.1f;
- pw->CreateButton(pos, dim, 128+12, EVENT_OBJECT_FACTORYws);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+13, EVENT_OBJECT_FACTORYts);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+14, EVENT_OBJECT_FACTORYfs);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+24, EVENT_OBJECT_FACTORYis);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*6.0f;
- pw->CreateButton(pos, dim, 128+15, EVENT_OBJECT_FACTORYwc);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+16, EVENT_OBJECT_FACTORYtc);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+17, EVENT_OBJECT_FACTORYfc);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+23, EVENT_OBJECT_FACTORYic);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*4.9f;
- pw->CreateButton(pos, dim, 128+25, EVENT_OBJECT_FACTORYwi);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+26, EVENT_OBJECT_FACTORYti);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+27, EVENT_OBJECT_FACTORYfi);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+28, EVENT_OBJECT_FACTORYii);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*3.8f;
- pw->CreateButton(pos, dim, 128+18, EVENT_OBJECT_FACTORYrt);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+19, EVENT_OBJECT_FACTORYrc);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+20, EVENT_OBJECT_FACTORYrr);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+29, EVENT_OBJECT_FACTORYrs);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*2.7f;
- pw->CreateButton(pos, dim, 128+21, EVENT_OBJECT_FACTORYsa);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 101, EVENT_OBJECT_TYPE);
-
- UpdateInterface();
- return true;
-}
-
-// Updates the status of all interface buttons.
-
-void CAutoFactory::UpdateInterface()
-{
- CWindow* pw;
-
- if ( !m_object->RetSelect() ) return;
-
- CAuto::UpdateInterface();
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
-
- UpdateButton(pw, EVENT_OBJECT_FACTORYwa, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYta, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYfa, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYia, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYws, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYts, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYfs, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYis, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYwc, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYtc, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYfc, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYic, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYwi, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYti, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYfi, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYii, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYrt, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYrc, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYrr, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYrs, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYsa, m_bBusy);
-}
-
-// Updates the status of one interface button.
-
-void CAutoFactory::UpdateButton(CWindow *pw, EventMsg event, bool bBusy)
-{
- bool bEnable = true;
-
- EnableInterface(pw, event, !bBusy);
-
- if ( event == EVENT_OBJECT_FACTORYta )
- {
- bEnable = g_researchDone&RESEARCH_TANK;
- }
- if ( event == EVENT_OBJECT_FACTORYfa )
- {
- bEnable = g_researchDone&RESEARCH_FLY;
- }
- if ( event == EVENT_OBJECT_FACTORYia )
- {
- bEnable = g_researchDone&RESEARCH_iPAW;
- }
-
- if ( event == EVENT_OBJECT_FACTORYws )
- {
- bEnable = g_researchDone&RESEARCH_SNIFFER;
- }
- if ( event == EVENT_OBJECT_FACTORYts )
- {
- bEnable = ( (g_researchDone&RESEARCH_SNIFFER) &&
- (g_researchDone&RESEARCH_TANK) );
- }
- if ( event == EVENT_OBJECT_FACTORYfs )
- {
- bEnable = ( (g_researchDone&RESEARCH_SNIFFER) &&
- (g_researchDone&RESEARCH_FLY) );
- }
- if ( event == EVENT_OBJECT_FACTORYis )
- {
- bEnable = ( (g_researchDone&RESEARCH_SNIFFER) &&
- (g_researchDone&RESEARCH_iPAW) );
- }
-
- if ( event == EVENT_OBJECT_FACTORYwc )
- {
- bEnable = g_researchDone&RESEARCH_CANON;
- }
- if ( event == EVENT_OBJECT_FACTORYtc )
- {
- bEnable = ( (g_researchDone&RESEARCH_CANON) &&
- (g_researchDone&RESEARCH_TANK) );
- }
- if ( event == EVENT_OBJECT_FACTORYfc )
- {
- bEnable = ( (g_researchDone&RESEARCH_CANON) &&
- (g_researchDone&RESEARCH_FLY) );
- }
- if ( event == EVENT_OBJECT_FACTORYic )
- {
- bEnable = ( (g_researchDone&RESEARCH_CANON) &&
- (g_researchDone&RESEARCH_iPAW) );
- }
-
- if ( event == EVENT_OBJECT_FACTORYwi )
- {
- bEnable = g_researchDone&RESEARCH_iGUN;
- }
- if ( event == EVENT_OBJECT_FACTORYti )
- {
- bEnable = ( (g_researchDone&RESEARCH_iGUN) &&
- (g_researchDone&RESEARCH_TANK) );
- }
- if ( event == EVENT_OBJECT_FACTORYfi )
- {
- bEnable = ( (g_researchDone&RESEARCH_iGUN) &&
- (g_researchDone&RESEARCH_FLY) );
- }
- if ( event == EVENT_OBJECT_FACTORYii )
- {
- bEnable = ( (g_researchDone&RESEARCH_iGUN) &&
- (g_researchDone&RESEARCH_iPAW) );
- }
-
- if ( event == EVENT_OBJECT_FACTORYrt )
- {
- bEnable = ( (g_researchDone&RESEARCH_THUMP) &&
- (g_researchDone&RESEARCH_TANK) );
- }
- if ( event == EVENT_OBJECT_FACTORYrc )
- {
- bEnable = ( (g_researchDone&RESEARCH_PHAZER) &&
- (g_researchDone&RESEARCH_TANK) );
- }
- if ( event == EVENT_OBJECT_FACTORYrr )
- {
- bEnable = ( (g_researchDone&RESEARCH_RECYCLER) &&
- (g_researchDone&RESEARCH_TANK) );
- }
- if ( event == EVENT_OBJECT_FACTORYrs )
- {
- bEnable = ( (g_researchDone&RESEARCH_SHIELD) &&
- (g_researchDone&RESEARCH_TANK) );
- }
-
- if ( event == EVENT_OBJECT_FACTORYsa )
- {
- bEnable = g_researchDone&RESEARCH_SUBM;
- }
-
- DeadInterface(pw, event, bEnable);
-}
-
-// Plays the sound of the manipulator arm.
-
-void CAutoFactory::SoundManip(float time, float amplitude, float frequency)
-{
- int i;
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autofactory.h"
+
+#include "common/global.h"
+#include "common/iman.h"
+#include "math/geometry.h"
+#include "object/robotmain.h"
+#include "physics/physics.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+
+
+
+
+
+// Object's constructor.
+
+CAutoFactory::CAutoFactory(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+ m_type = OBJECT_MOBILEws;
+ m_phase = AFP_WAIT; // paused until the first Init ()
+ m_channelSound = -1;
+}
+
+// Object's destructor.
+
+CAutoFactory::~CAutoFactory()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoFactory::DeleteObject(bool bAll)
+{
+ CObject* fret;
+ CObject* vehicle;
+
+ if ( !bAll )
+ {
+ fret = SearchFret(); // transform metal?
+ if ( fret != 0 )
+ {
+ fret->DeleteObject(); // destroys the metal
+ delete fret;
+ }
+
+ vehicle = SearchVehicle();
+ if ( vehicle != 0 )
+ {
+ vehicle->DeleteObject(); // destroys the vehicle
+ delete vehicle;
+ }
+ }
+
+ if ( m_channelSound != -1 )
+ {
+ m_sound->FlushEnvelope(m_channelSound);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_channelSound = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoFactory::Init()
+{
+ m_phase = AFP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+
+ m_fretPos = m_object->RetPosition(0);
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoFactory::EventProcess(const Event &event)
+{
+ CObject* fret;
+ CObject* vehicle;
+ Math::Matrix* mat;
+ CPhysics* physics;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ ObjectType type;
+ float zoom, angle, prog;
+ int i;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+
+ if ( m_object->RetSelect() ) // factory selected?
+ {
+ if ( event.event == EVENT_UPDINTERFACE )
+ {
+ CreateInterface(true);
+ }
+
+ type = OBJECT_NULL;
+ if ( event.event == EVENT_OBJECT_FACTORYwa ) type = OBJECT_MOBILEwa;
+ if ( event.event == EVENT_OBJECT_FACTORYta ) type = OBJECT_MOBILEta;
+ if ( event.event == EVENT_OBJECT_FACTORYfa ) type = OBJECT_MOBILEfa;
+ if ( event.event == EVENT_OBJECT_FACTORYia ) type = OBJECT_MOBILEia;
+ if ( event.event == EVENT_OBJECT_FACTORYws ) type = OBJECT_MOBILEws;
+ if ( event.event == EVENT_OBJECT_FACTORYts ) type = OBJECT_MOBILEts;
+ if ( event.event == EVENT_OBJECT_FACTORYfs ) type = OBJECT_MOBILEfs;
+ if ( event.event == EVENT_OBJECT_FACTORYis ) type = OBJECT_MOBILEis;
+ if ( event.event == EVENT_OBJECT_FACTORYwc ) type = OBJECT_MOBILEwc;
+ if ( event.event == EVENT_OBJECT_FACTORYtc ) type = OBJECT_MOBILEtc;
+ if ( event.event == EVENT_OBJECT_FACTORYfc ) type = OBJECT_MOBILEfc;
+ if ( event.event == EVENT_OBJECT_FACTORYic ) type = OBJECT_MOBILEic;
+ if ( event.event == EVENT_OBJECT_FACTORYwi ) type = OBJECT_MOBILEwi;
+ if ( event.event == EVENT_OBJECT_FACTORYti ) type = OBJECT_MOBILEti;
+ if ( event.event == EVENT_OBJECT_FACTORYfi ) type = OBJECT_MOBILEfi;
+ if ( event.event == EVENT_OBJECT_FACTORYii ) type = OBJECT_MOBILEii;
+ if ( event.event == EVENT_OBJECT_FACTORYrt ) type = OBJECT_MOBILErt;
+ if ( event.event == EVENT_OBJECT_FACTORYrc ) type = OBJECT_MOBILErc;
+ if ( event.event == EVENT_OBJECT_FACTORYrr ) type = OBJECT_MOBILErr;
+ if ( event.event == EVENT_OBJECT_FACTORYrs ) type = OBJECT_MOBILErs;
+ if ( event.event == EVENT_OBJECT_FACTORYsa ) type = OBJECT_MOBILEsa;
+
+ if ( type != OBJECT_NULL )
+ {
+ m_type = type;
+
+ if ( m_phase != AFP_WAIT )
+ {
+ return false;
+ }
+
+ fret = SearchFret(); // transform metal?
+ if ( fret == 0 )
+ {
+ m_displayText->DisplayError(ERR_FACTORY_NULL, m_object);
+ return false;
+ }
+ if ( NearestVehicle() )
+ {
+ m_displayText->DisplayError(ERR_FACTORY_NEAR, m_object);
+ return false;
+ }
+
+ SetBusy(true);
+ InitProgressTotal(3.0f+2.0f+15.0f+2.0f+3.0f);
+ UpdateInterface();
+
+ fret->SetLock(true); // usable metal
+ SoundManip(3.0f, 1.0f, 0.5f);
+
+ m_phase = AFP_CLOSE_S;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ return true;
+ }
+ }
+
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ EventProgress(event.rTime);
+
+ if ( m_phase == AFP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_phase = AFP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == AFP_CLOSE_S )
+ {
+ if ( m_progress < 1.0f )
+ {
+ for ( i=0 ; i<9 ; i++ )
+ {
+ zoom = 0.30f+(m_progress-0.5f+i/16.0f)*2.0f*0.70f;
+ if ( zoom < 0.30f ) zoom = 0.30f;
+ if ( zoom > 1.00f ) zoom = 1.00f;
+ m_object->SetZoomZ( 1+i, zoom);
+ m_object->SetZoomZ(10+i, zoom);
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<9 ; i++ )
+ {
+ m_object->SetZoomZ( 1+i, 1.0f);
+ m_object->SetZoomZ(10+i, 1.0f);
+ }
+
+ SoundManip(2.0f, 1.0f, 1.2f);
+
+ m_phase = AFP_CLOSE_T;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == AFP_CLOSE_T )
+ {
+ if ( m_progress < 1.0f )
+ {
+ for ( i=0 ; i<9 ; i++ )
+ {
+ angle = -m_progress*(Math::PI/2.0f)+Math::PI/2.0f;
+ m_object->SetAngleZ( 1+i, angle);
+ m_object->SetAngleZ(10+i, -angle);
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<9 ; i++ )
+ {
+ m_object->SetAngleZ( 1+i, 0.0f);
+ m_object->SetAngleZ(10+i, 0.0f);
+ }
+
+ m_channelSound = m_sound->Play(SOUND_FACTORY, m_object->RetPosition(0), 0.0f, 1.0f, true);
+ m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 11.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP);
+
+ m_phase = AFP_BUILD;
+ m_progress = 0.0f;
+ m_speed = 1.0f/15.0f;
+ }
+ }
+
+ if ( m_phase == AFP_BUILD )
+ {
+ if ( m_progress == 0.0f )
+ {
+ if ( !CreateVehicle() )
+ {
+ fret = SearchFret(); // transform metal?
+ if ( fret != 0 )
+ {
+ fret->SetLock(false); // metal usable again
+ }
+
+ if ( m_channelSound != -1 )
+ {
+ m_sound->FlushEnvelope(m_channelSound);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_channelSound = -1;
+ }
+
+ m_phase = AFP_OPEN_T;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ return true;
+ }
+ }
+
+ if ( m_progress < 1.0f )
+ {
+ if ( m_type == OBJECT_MOBILErt ||
+ m_type == OBJECT_MOBILErc ||
+ m_type == OBJECT_MOBILErr ||
+ m_type == OBJECT_MOBILErs )
+ {
+ prog = 1.0f-m_progress*1.5f;
+ if ( prog < 0.0f ) prog = 0.0f;
+ }
+ else
+ {
+ prog = 1.0f-m_progress;
+ }
+ angle = powf(prog*10.0f, 2.0f)+m_object->RetAngleY(0);
+
+ vehicle = SearchVehicle();
+ if ( vehicle != 0 )
+ {
+ vehicle->SetAngleY(0, angle+Math::PI);
+ vehicle->SetZoom(0, m_progress);
+ }
+
+ fret = SearchFret(); // transform metal?
+ if ( fret != 0 )
+ {
+ fret->SetZoom(0, 1.0f-m_progress);
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+#if 0
+ pos = m_fretPos;
+ pos.x += (Math::Rand()-0.5f)*20.0f;
+ pos.z += (Math::Rand()-0.5f)*20.0f;
+ pos.y += 1.0f;
+ speed.x = (Math::Rand()-0.5f)*12.0f;
+ speed.z = (Math::Rand()-0.5f)*12.0f;
+ speed.y = Math::Rand()*12.0f;
+ dim.x = Math::Rand()*12.0f+10.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
+#else
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(-12.0f, 20.0f, -4.0f); // position of chimney
+ pos = Math::Transform(*mat, pos);
+ pos.y += 2.0f;
+ pos.x += (Math::Rand()-0.5f)*2.0f;
+ pos.z += (Math::Rand()-0.5f)*2.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 6.0f+Math::Rand()*6.0f;
+ dim.x = Math::Rand()*1.5f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
+#endif
+ }
+ }
+ else
+ {
+ m_displayText->DisplayError(INFO_FACTORY, m_object);
+ SoundManip(2.0f, 1.0f, 1.2f);
+
+ fret = SearchFret(); // transform metal?
+ if ( fret != 0 )
+ {
+ fret->DeleteObject(); // removes the metal
+ delete fret;
+ }
+
+ vehicle = SearchVehicle();
+ if ( vehicle != 0 )
+ {
+ physics = vehicle->RetPhysics();
+ if ( physics != 0 )
+ {
+ physics->SetFreeze(false); // can move
+ }
+
+ vehicle->SetLock(false); // vehicle useable
+//? vehicle->RetPhysics()->RetBrain()->StartTaskAdvance(16.0f);
+ vehicle->SetAngleY(0, m_object->RetAngleY(0)+Math::PI);
+ vehicle->SetZoom(0, 1.0f);
+ }
+
+ m_main->CreateShortcuts();
+
+ m_phase = AFP_OPEN_T;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == AFP_OPEN_T )
+ {
+ if ( m_progress < 1.0f )
+ {
+ for ( i=0 ; i<9 ; i++ )
+ {
+ angle = -(1.0f-m_progress)*(Math::PI/2.0f)+Math::PI/2.0f;
+ m_object->SetAngleZ( 1+i, angle);
+ m_object->SetAngleZ(10+i, -angle);
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_fretPos;
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ pos.y += Math::Rand()*10.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<9 ; i++ )
+ {
+ m_object->SetAngleZ( 1+i, Math::PI/2.0f);
+ m_object->SetAngleZ(10+i, -Math::PI/2.0f);
+ }
+
+ SoundManip(3.0f, 1.0f, 0.5f);
+
+ m_phase = AFP_OPEN_S;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ }
+ }
+
+ if ( m_phase == AFP_OPEN_S )
+ {
+ if ( m_progress < 1.0f )
+ {
+ for ( i=0 ; i<9 ; i++ )
+ {
+ zoom = 0.30f+((1.0f-m_progress)-0.5f+i/16.0f)*2.0f*0.70f;
+ if ( zoom < 0.30f ) zoom = 0.30f;
+ if ( zoom > 1.00f ) zoom = 1.00f;
+ m_object->SetZoomZ( 1+i, zoom);
+ m_object->SetZoomZ(10+i, zoom);
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_fretPos;
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ pos.y += Math::Rand()*10.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<9 ; i++ )
+ {
+ m_object->SetZoomZ( 1+i, 0.30f);
+ m_object->SetZoomZ(10+i, 0.30f);
+ }
+
+ SetBusy(false);
+ UpdateInterface();
+
+ m_phase = AFP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ return true;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoFactory::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == AFP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller
+
+bool CAutoFactory::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoFactoryPhase)OpInt(line, "aPhase", AFP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+ m_fretPos = m_object->RetPosition(0);
+
+ return true;
+}
+
+
+//Seeks the cargo.
+
+CObject* CAutoFactory::SearchFret()
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ ObjectType type;
+ float dist;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_METAL ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, m_fretPos);
+
+ if ( dist < 8.0f ) return pObj;
+ }
+
+ return 0;
+}
+
+// Search if a vehicle is too close.
+
+bool CAutoFactory::NearestVehicle()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType type;
+ float oRadius, dist;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_HUMAN &&
+ type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis &&
+ type != OBJECT_MOBILErt &&
+ type != OBJECT_MOBILErc &&
+ type != OBJECT_MOBILErr &&
+ type != OBJECT_MOBILErs &&
+ type != OBJECT_MOBILEsa &&
+ type != OBJECT_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_MOBILEdr &&
+ type != OBJECT_MOTHER &&
+ type != OBJECT_ANT &&
+ type != OBJECT_SPIDER &&
+ type != OBJECT_BEE &&
+ type != OBJECT_WORM ) continue;
+
+ if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
+ dist = Math::Distance(oPos, cPos)-oRadius;
+
+ if ( dist < 10.0f ) return true;
+ }
+
+ return false;
+}
+
+
+// Creates a vehicle.
+
+bool CAutoFactory::CreateVehicle()
+{
+ CObject* vehicle;
+ Math::Matrix* mat;
+ CPhysics* physics;
+ Math::Vector pos;
+ float angle;
+ char* name;
+ int i;
+
+ angle = m_object->RetAngleY(0);
+
+ mat = m_object->RetWorldMatrix(0);
+ if ( m_type == OBJECT_MOBILErt ||
+ m_type == OBJECT_MOBILErc ||
+ m_type == OBJECT_MOBILErr ||
+ m_type == OBJECT_MOBILErs )
+ {
+ pos = Math::Vector(2.0f, 0.0f, 0.0f);
+ }
+ else
+ {
+ pos = Math::Vector(4.0f, 0.0f, 0.0f);
+ }
+ pos = Transform(*mat, pos);
+
+ vehicle = new CObject(m_iMan);
+ if ( !vehicle->CreateVehicle(pos, angle, m_type, -1.0f, false, false) )
+ {
+ delete vehicle;
+ m_displayText->DisplayError(ERR_TOOMANY, m_object);
+ return false;
+ }
+ vehicle->UpdateMapping();
+ vehicle->SetLock(true); // not usable
+ vehicle->SetRange(30.0f);
+
+ physics = vehicle->RetPhysics();
+ if ( physics != 0 )
+ {
+ physics->SetFreeze(true); // it doesn't move
+ }
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ name = m_main->RetNewScriptName(m_type, i);
+ if ( name == 0 ) break;
+ vehicle->ReadProgram(i, name);
+ }
+
+ return true;
+}
+
+// Seeking the vehicle during manufacture.
+
+CObject* CAutoFactory::SearchVehicle()
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ ObjectType type;
+ float dist;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetLock() ) continue;
+
+ type = pObj->RetType();
+ if ( type != m_type ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, m_fretPos);
+
+ if ( dist < 8.0f ) return pObj;
+ }
+
+ return 0;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoFactory::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, dim, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ dim.x = 33.0f/640.0f;
+ dim.y = 33.0f/480.0f;
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = 0.0f;
+ pos.y = oy+sy*2.6f;
+ ddim.x = 138.0f/640.0f;
+ ddim.y = 222.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 6, EVENT_WINDOW3);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*8.2f;
+ pw->CreateButton(pos, dim, 128+9, EVENT_OBJECT_FACTORYwa);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+10, EVENT_OBJECT_FACTORYta);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+11, EVENT_OBJECT_FACTORYfa);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+22, EVENT_OBJECT_FACTORYia);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*7.1f;
+ pw->CreateButton(pos, dim, 128+12, EVENT_OBJECT_FACTORYws);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+13, EVENT_OBJECT_FACTORYts);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+14, EVENT_OBJECT_FACTORYfs);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+24, EVENT_OBJECT_FACTORYis);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*6.0f;
+ pw->CreateButton(pos, dim, 128+15, EVENT_OBJECT_FACTORYwc);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+16, EVENT_OBJECT_FACTORYtc);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+17, EVENT_OBJECT_FACTORYfc);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+23, EVENT_OBJECT_FACTORYic);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*4.9f;
+ pw->CreateButton(pos, dim, 128+25, EVENT_OBJECT_FACTORYwi);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+26, EVENT_OBJECT_FACTORYti);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+27, EVENT_OBJECT_FACTORYfi);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+28, EVENT_OBJECT_FACTORYii);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*3.8f;
+ pw->CreateButton(pos, dim, 128+18, EVENT_OBJECT_FACTORYrt);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+19, EVENT_OBJECT_FACTORYrc);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+20, EVENT_OBJECT_FACTORYrr);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+29, EVENT_OBJECT_FACTORYrs);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*2.7f;
+ pw->CreateButton(pos, dim, 128+21, EVENT_OBJECT_FACTORYsa);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 101, EVENT_OBJECT_TYPE);
+
+ UpdateInterface();
+ return true;
+}
+
+// Updates the status of all interface buttons.
+
+void CAutoFactory::UpdateInterface()
+{
+ CWindow* pw;
+
+ if ( !m_object->RetSelect() ) return;
+
+ CAuto::UpdateInterface();
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+
+ UpdateButton(pw, EVENT_OBJECT_FACTORYwa, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYta, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYfa, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYia, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYws, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYts, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYfs, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYis, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYwc, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYtc, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYfc, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYic, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYwi, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYti, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYfi, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYii, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYrt, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYrc, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYrr, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYrs, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYsa, m_bBusy);
+}
+
+// Updates the status of one interface button.
+
+void CAutoFactory::UpdateButton(CWindow *pw, EventMsg event, bool bBusy)
+{
+ bool bEnable = true;
+
+ EnableInterface(pw, event, !bBusy);
+
+ if ( event == EVENT_OBJECT_FACTORYta )
+ {
+ bEnable = g_researchDone&RESEARCH_TANK;
+ }
+ if ( event == EVENT_OBJECT_FACTORYfa )
+ {
+ bEnable = g_researchDone&RESEARCH_FLY;
+ }
+ if ( event == EVENT_OBJECT_FACTORYia )
+ {
+ bEnable = g_researchDone&RESEARCH_iPAW;
+ }
+
+ if ( event == EVENT_OBJECT_FACTORYws )
+ {
+ bEnable = g_researchDone&RESEARCH_SNIFFER;
+ }
+ if ( event == EVENT_OBJECT_FACTORYts )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_SNIFFER) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYfs )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_SNIFFER) &&
+ (g_researchDone&RESEARCH_FLY) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYis )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_SNIFFER) &&
+ (g_researchDone&RESEARCH_iPAW) );
+ }
+
+ if ( event == EVENT_OBJECT_FACTORYwc )
+ {
+ bEnable = g_researchDone&RESEARCH_CANON;
+ }
+ if ( event == EVENT_OBJECT_FACTORYtc )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_CANON) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYfc )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_CANON) &&
+ (g_researchDone&RESEARCH_FLY) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYic )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_CANON) &&
+ (g_researchDone&RESEARCH_iPAW) );
+ }
+
+ if ( event == EVENT_OBJECT_FACTORYwi )
+ {
+ bEnable = g_researchDone&RESEARCH_iGUN;
+ }
+ if ( event == EVENT_OBJECT_FACTORYti )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_iGUN) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYfi )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_iGUN) &&
+ (g_researchDone&RESEARCH_FLY) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYii )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_iGUN) &&
+ (g_researchDone&RESEARCH_iPAW) );
+ }
+
+ if ( event == EVENT_OBJECT_FACTORYrt )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_THUMP) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYrc )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_PHAZER) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYrr )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_RECYCLER) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYrs )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_SHIELD) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+
+ if ( event == EVENT_OBJECT_FACTORYsa )
+ {
+ bEnable = g_researchDone&RESEARCH_SUBM;
+ }
+
+ DeadInterface(pw, event, bEnable);
+}
+
+// Plays the sound of the manipulator arm.
+
+void CAutoFactory::SoundManip(float time, float amplitude, float frequency)
+{
+ int i;
+
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
+ m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
+}
+
diff --git a/src/object/auto/autofactory.h b/src/object/auto/autofactory.h
index d41dd62..acbdf40 100644
--- a/src/object/auto/autofactory.h
+++ b/src/object/auto/autofactory.h
@@ -1,74 +1,74 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autofactory.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoFactoryPhase
-{
- AFP_WAIT = 1, // expected metal
- AFP_CLOSE_S = 2, // closes doors (shift)
- AFP_CLOSE_T = 3, // closes doors (turn)
- AFP_BUILD = 4, // building the vehicle
- AFP_OPEN_T = 5, // opens the doors (turn)
- AFP_OPEN_S = 6, // opens the doors (shift)
- AFP_ADVANCE = 7, // advance at the door
-};
-
-
-
-class CAutoFactory : public CAuto
-{
-public:
- CAutoFactory(CInstanceManager* iMan, CObject* object);
- ~CAutoFactory();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- void UpdateInterface();
- void UpdateButton(CWindow *pw, EventMsg event, bool bBusy);
-
- CObject* SearchFret();
- bool NearestVehicle();
- bool CreateVehicle();
- CObject* SearchVehicle();
-
- void SoundManip(float time, float amplitude, float frequency);
-
-protected:
- AutoFactoryPhase m_phase;
- float m_progress;
- float m_speed;
- float m_lastParticule;
- Math::Vector m_fretPos;
- int m_channelSound;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autofactory.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoFactoryPhase
+{
+ AFP_WAIT = 1, // expected metal
+ AFP_CLOSE_S = 2, // closes doors (shift)
+ AFP_CLOSE_T = 3, // closes doors (turn)
+ AFP_BUILD = 4, // building the vehicle
+ AFP_OPEN_T = 5, // opens the doors (turn)
+ AFP_OPEN_S = 6, // opens the doors (shift)
+ AFP_ADVANCE = 7, // advance at the door
+};
+
+
+
+class CAutoFactory : public CAuto
+{
+public:
+ CAutoFactory(CInstanceManager* iMan, CObject* object);
+ ~CAutoFactory();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ void UpdateInterface();
+ void UpdateButton(CWindow *pw, EventMsg event, bool bBusy);
+
+ CObject* SearchFret();
+ bool NearestVehicle();
+ bool CreateVehicle();
+ CObject* SearchVehicle();
+
+ void SoundManip(float time, float amplitude, float frequency);
+
+protected:
+ AutoFactoryPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_lastParticule;
+ Math::Vector m_fretPos;
+ int m_channelSound;
+};
+
diff --git a/src/object/auto/autoflag.cpp b/src/object/auto/autoflag.cpp
index 2c9ebdc..ea74b17 100644
--- a/src/object/auto/autoflag.cpp
+++ b/src/object/auto/autoflag.cpp
@@ -1,162 +1,162 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoflag.h"
-
-#include "math/geometry.h"
-#include "old/terrain.h"
-
-
-
-#define ADJUST_ANGLE false // true -> adjusts the angles of the members
-
-
-#if ADJUST_ANGLE
-static float g_flag1 = 6.00f;
-static float g_flag2 = 0.10f;
-static float g_flag3 = 2.00f;
-#endif
-
-
-// Object's constructor.
-
-CAutoFlag::CAutoFlag(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
-}
-
-// Object's destructor.
-
-CAutoFlag::~CAutoFlag()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoFlag::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoFlag::Init()
-{
- Math::Vector wind;
- float angle;
-
- m_time = 0.0f;
- m_param = 0;
- m_progress = 0.0f;
-
- wind = m_terrain->RetWind();
- angle = Math::RotateAngle(wind.x, -wind.z);
- m_object->SetAngleY(0, angle); // directs the flag in the wind
-
- m_strong = wind.Length();
-}
-
-
-// Beginning of an action (1 = shakes).
-
-void CAutoFlag::Start(int param)
-{
- if ( m_param == 0 )
- {
- m_param = param;
- m_progress = 0.0f;
- }
-}
-
-
-// Management of an event.
-
-bool CAutoFlag::EventProcess(const Event &event)
-{
- float angle;
- int i;
-
- CAuto::EventProcess(event);
-
-#if ADJUST_ANGLE
- if ( event.event == EVENT_KEYDOWN )
- {
- if ( event.param == 'E' ) g_flag1 += 0.1f;
- if ( event.param == 'D' ) g_flag1 -= 0.1f;
- if ( event.param == 'R' ) g_flag2 += 0.1f;
- if ( event.param == 'F' ) g_flag2 -= 0.1f;
- if ( event.param == 'T' ) g_flag3 += 0.1f;
- if ( event.param == 'G' ) g_flag3 -= 0.1f;
- }
-#endif
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- if ( m_param == 1 ) // shakes?
- {
- m_progress += event.rTime*(1.0f/2.0f);
- if ( m_progress < 1.0f )
- {
- angle = sinf(m_progress*Math::PI*8.0f)*0.3f*(1.0f-m_progress);
- m_object->SetAngleX(0, angle);
- angle = sinf(m_progress*Math::PI*4.0f)*0.3f*(1.0f-m_progress);
- m_object->SetAngleZ(0, angle);
- }
- else
- {
- m_object->SetAngleX(0, 0.0f);
- m_object->SetAngleZ(0, 0.0f);
- m_param = 0;
- m_progress = 0.0f;
- }
- }
-
- if ( m_strong == 0.0f ) return true; // no wind?
-
- for ( i=0 ; i<4 ; i++ )
- {
-#if ADJUST_ANGLE
- angle = sinf(m_time*g_flag1+i*2.0f)*((i+g_flag3)*g_flag2);
-#else
- angle = sinf(m_time*6.0f+i*2.0f)*((i+2.0f)*0.1f);
-#endif
- m_object->SetAngleY(1+i, angle);
- }
-
-#if ADJUST_ANGLE
- char s[100];
- sprintf(s, "a=%.2f b=%.2f c=%.2f", g_flag1, g_flag2, g_flag3);
- m_engine->SetInfoText(4, s);
-#endif
- return true;
-}
-
-
-// Returns an error due the state of the automation
-
-Error CAutoFlag::RetError()
-{
- return ERR_OK;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoflag.h"
+
+#include "math/geometry.h"
+#include "old/terrain.h"
+
+
+
+#define ADJUST_ANGLE false // true -> adjusts the angles of the members
+
+
+#if ADJUST_ANGLE
+static float g_flag1 = 6.00f;
+static float g_flag2 = 0.10f;
+static float g_flag3 = 2.00f;
+#endif
+
+
+// Object's constructor.
+
+CAutoFlag::CAutoFlag(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+}
+
+// Object's destructor.
+
+CAutoFlag::~CAutoFlag()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoFlag::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoFlag::Init()
+{
+ Math::Vector wind;
+ float angle;
+
+ m_time = 0.0f;
+ m_param = 0;
+ m_progress = 0.0f;
+
+ wind = m_terrain->RetWind();
+ angle = Math::RotateAngle(wind.x, -wind.z);
+ m_object->SetAngleY(0, angle); // directs the flag in the wind
+
+ m_strong = wind.Length();
+}
+
+
+// Beginning of an action (1 = shakes).
+
+void CAutoFlag::Start(int param)
+{
+ if ( m_param == 0 )
+ {
+ m_param = param;
+ m_progress = 0.0f;
+ }
+}
+
+
+// Management of an event.
+
+bool CAutoFlag::EventProcess(const Event &event)
+{
+ float angle;
+ int i;
+
+ CAuto::EventProcess(event);
+
+#if ADJUST_ANGLE
+ if ( event.event == EVENT_KEYDOWN )
+ {
+ if ( event.param == 'E' ) g_flag1 += 0.1f;
+ if ( event.param == 'D' ) g_flag1 -= 0.1f;
+ if ( event.param == 'R' ) g_flag2 += 0.1f;
+ if ( event.param == 'F' ) g_flag2 -= 0.1f;
+ if ( event.param == 'T' ) g_flag3 += 0.1f;
+ if ( event.param == 'G' ) g_flag3 -= 0.1f;
+ }
+#endif
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ if ( m_param == 1 ) // shakes?
+ {
+ m_progress += event.rTime*(1.0f/2.0f);
+ if ( m_progress < 1.0f )
+ {
+ angle = sinf(m_progress*Math::PI*8.0f)*0.3f*(1.0f-m_progress);
+ m_object->SetAngleX(0, angle);
+ angle = sinf(m_progress*Math::PI*4.0f)*0.3f*(1.0f-m_progress);
+ m_object->SetAngleZ(0, angle);
+ }
+ else
+ {
+ m_object->SetAngleX(0, 0.0f);
+ m_object->SetAngleZ(0, 0.0f);
+ m_param = 0;
+ m_progress = 0.0f;
+ }
+ }
+
+ if ( m_strong == 0.0f ) return true; // no wind?
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+#if ADJUST_ANGLE
+ angle = sinf(m_time*g_flag1+i*2.0f)*((i+g_flag3)*g_flag2);
+#else
+ angle = sinf(m_time*6.0f+i*2.0f)*((i+2.0f)*0.1f);
+#endif
+ m_object->SetAngleY(1+i, angle);
+ }
+
+#if ADJUST_ANGLE
+ char s[100];
+ sprintf(s, "a=%.2f b=%.2f c=%.2f", g_flag1, g_flag2, g_flag3);
+ m_engine->SetInfoText(4, s);
+#endif
+ return true;
+}
+
+
+// Returns an error due the state of the automation
+
+Error CAutoFlag::RetError()
+{
+ return ERR_OK;
+}
+
+
diff --git a/src/object/auto/autoflag.h b/src/object/auto/autoflag.h
index b503363..fdec682 100644
--- a/src/object/auto/autoflag.h
+++ b/src/object/auto/autoflag.h
@@ -1,46 +1,46 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoflag.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-class CAutoFlag : public CAuto
-{
-public:
- CAutoFlag(CInstanceManager* iMan, CObject* object);
- ~CAutoFlag();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- void Start(int param);
- bool EventProcess(const Event &event);
- Error RetError();
-
-protected:
-
-protected:
- float m_strong;
- int m_param;
- float m_progress;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoflag.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+class CAutoFlag : public CAuto
+{
+public:
+ CAutoFlag(CInstanceManager* iMan, CObject* object);
+ ~CAutoFlag();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ void Start(int param);
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+protected:
+
+protected:
+ float m_strong;
+ int m_param;
+ float m_progress;
+};
+
diff --git a/src/object/auto/autohuston.cpp b/src/object/auto/autohuston.cpp
index 3495437..a96bcb8 100644
--- a/src/object/auto/autohuston.cpp
+++ b/src/object/auto/autohuston.cpp
@@ -1,296 +1,296 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autohuston.h"
-
-#include "ui/interface.h"
-#include "ui/window.h"
-
-
-
-
-// Object's constructor.
-
-CAutoHuston::CAutoHuston(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Math::Vector pos;
- int i;
-
- for ( i=0 ; i<HUSTONMAXLENS ; i++ )
- {
- m_lens[i].parti = -1;
- }
-
- pos = m_object->RetPosition(0);
- m_lens[0].type = PARTISELR;
- m_lens[1].type = PARTISELR;
- m_lens[2].type = PARTISELR;
- m_lens[3].type = PARTISELR;
- m_lens[0].pos = pos+Math::Vector(0.0f+13.0f, 34.0f, 30.0f );
- m_lens[1].pos = pos+Math::Vector(0.0f-13.0f, 34.0f, 30.0f );
- m_lens[2].pos = pos+Math::Vector(0.0f , 34.0f, 30.0f+13.0f);
- m_lens[3].pos = pos+Math::Vector(0.0f , 34.0f, 30.0f-13.0f);
- m_lens[0].dim = 4.0f;
- m_lens[1].dim = 4.0f;
- m_lens[2].dim = 4.0f;
- m_lens[3].dim = 4.0f;
- m_lens[0].total = 1.0f;
- m_lens[1].total = 1.0f;
- m_lens[2].total = 1.0f;
- m_lens[3].total = 1.0f;
- m_lens[0].off = 0.4f;
- m_lens[1].off = 0.4f;
- m_lens[2].off = 0.4f;
- m_lens[3].off = 0.4f;
-
- // Part under the radar.
- i = 4;
- m_lens[i].type = PARTISELR;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 9.9f, 40.1f);
- m_lens[i].dim = 1.8f;
- m_lens[i].total = 0.4f;
- m_lens[i].off = 0.2f;
- i ++;
-
- m_lens[i].type = PARTISELY;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 7.2f, 34.8f);
- m_lens[i].dim = 0.4f;
- m_lens[i].total = 0.7f;
- m_lens[i].off = 0.3f;
- i ++;
- m_lens[i].type = PARTISELY;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 34.3f);
- m_lens[i].dim = 0.4f;
- m_lens[i].total = 0.7f;
- m_lens[i].off = 0.3f;
- i ++;
- m_lens[i].type = PARTISELR;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.4f);
- m_lens[i].dim = 0.4f;
- m_lens[i].total = 0.0f;
- m_lens[i].off = 0.0f;
- i ++;
- m_lens[i].type = PARTISELR;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.0f);
- m_lens[i].dim = 0.4f;
- m_lens[i].total = 1.0f;
- m_lens[i].off = 0.5f;
- i ++;
-
- m_lens[i].type = PARTISELY;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 8.5f, 14.0f);
- m_lens[i].dim = 1.2f;
- m_lens[i].total = 0.8f;
- m_lens[i].off = 0.2f;
- i ++;
-
- m_lens[i].type = PARTISELR;
- m_lens[i].pos = pos+Math::Vector(4.0f, 6.0f, 8.6f);
- m_lens[i].dim = 1.0f;
- m_lens[i].total = 0.9f;
- m_lens[i].off = 0.7f;
- i ++;
-
- // Part with three windows.
- m_lens[i].type = PARTISELR;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 9.9f, -19.9f);
- m_lens[i].dim = 1.0f;
- m_lens[i].total = 0.6f;
- m_lens[i].off = 0.3f;
- i ++;
-
- m_lens[i].type = PARTISELY;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 7.2f, 34.8f-60.0f);
- m_lens[i].dim = 0.4f;
- m_lens[i].total = 0.7f;
- m_lens[i].off = 0.3f;
- i ++;
- m_lens[i].type = PARTISELY;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 34.3f-60.0f);
- m_lens[i].dim = 0.4f;
- m_lens[i].total = 0.0f;
- m_lens[i].off = 0.0f;
- i ++;
- m_lens[i].type = PARTISELR;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.4f-60.0f);
- m_lens[i].dim = 0.4f;
- m_lens[i].total = 0.6f;
- m_lens[i].off = 0.4f;
- i ++;
- m_lens[i].type = PARTISELR;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.0f-60.0f);
- m_lens[i].dim = 0.4f;
- m_lens[i].total = 0.8f;
- m_lens[i].off = 0.2f;
- i ++;
-
- m_lens[i].type = PARTISELY;
- m_lens[i].pos = pos+Math::Vector(-6.5f, 13.5f, -37.0f);
- m_lens[i].dim = 1.0f;
- m_lens[i].total = 0.0f;
- m_lens[i].off = 0.0f;
- i ++;
-
- m_lens[i].type = PARTISELY;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 12.2f, -39.8f);
- m_lens[i].dim = 1.8f;
- m_lens[i].total = 1.5f;
- m_lens[i].off = 0.5f;
- i ++;
-
- m_lens[i].type = PARTISELY;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 8.5f, -47.0f);
- m_lens[i].dim = 0.6f;
- m_lens[i].total = 0.7f;
- m_lens[i].off = 0.5f;
- i ++;
-
- m_lensTotal = i;
-
- Init();
-}
-
-// Object's destructor.
-
-CAutoHuston::~CAutoHuston()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoHuston::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoHuston::Init()
-{
- m_time = 0.0f;
-
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-}
-
-
-// Start the object.
-
-void CAutoHuston::Start(int param)
-{
-}
-
-
-// Management of an event.
-
-bool CAutoHuston::EventProcess(const Event &event)
-{
- Math::Vector speed;
- Math::Point dim;
- float angle;
- int i;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
-
- angle = -m_time*1.0f;
- m_object->SetAngleY(1, angle); // rotates the radar
- angle = sinf(m_time*4.0f)*0.3f;
- m_object->SetAngleX(2, angle);
-
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
-
- // Flashes the keys.
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- for ( i=0 ; i<m_lensTotal ; i++ )
- {
- if ( m_lens[i].total != 0.0f &&
- Math::Mod(m_time, m_lens[i].total) < m_lens[i].off )
- {
- if ( m_lens[i].parti != -1 )
- {
- m_particule->DeleteParticule(m_lens[i].parti);
- m_lens[i].parti = -1;
- }
- }
- else
- {
- if ( m_lens[i].parti == -1 )
- {
- dim.x = m_lens[i].dim;
- dim.y = dim.x;
- m_lens[i].parti = m_particule->CreateParticule(m_lens[i].pos, speed, dim, m_lens[i].type, 1.0f, 0.0f, 0.0f);
- }
- }
- }
-
- return true;
-}
-
-// Stops the controller.
-
-bool CAutoHuston::Abort()
-{
- return true;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoHuston::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 115, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-
-// Returns an error due to state of the automation.
-
-Error CAutoHuston::RetError()
-{
- return ERR_OK;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autohuston.h"
+
+#include "ui/interface.h"
+#include "ui/window.h"
+
+
+
+
+// Object's constructor.
+
+CAutoHuston::CAutoHuston(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Math::Vector pos;
+ int i;
+
+ for ( i=0 ; i<HUSTONMAXLENS ; i++ )
+ {
+ m_lens[i].parti = -1;
+ }
+
+ pos = m_object->RetPosition(0);
+ m_lens[0].type = PARTISELR;
+ m_lens[1].type = PARTISELR;
+ m_lens[2].type = PARTISELR;
+ m_lens[3].type = PARTISELR;
+ m_lens[0].pos = pos+Math::Vector(0.0f+13.0f, 34.0f, 30.0f );
+ m_lens[1].pos = pos+Math::Vector(0.0f-13.0f, 34.0f, 30.0f );
+ m_lens[2].pos = pos+Math::Vector(0.0f , 34.0f, 30.0f+13.0f);
+ m_lens[3].pos = pos+Math::Vector(0.0f , 34.0f, 30.0f-13.0f);
+ m_lens[0].dim = 4.0f;
+ m_lens[1].dim = 4.0f;
+ m_lens[2].dim = 4.0f;
+ m_lens[3].dim = 4.0f;
+ m_lens[0].total = 1.0f;
+ m_lens[1].total = 1.0f;
+ m_lens[2].total = 1.0f;
+ m_lens[3].total = 1.0f;
+ m_lens[0].off = 0.4f;
+ m_lens[1].off = 0.4f;
+ m_lens[2].off = 0.4f;
+ m_lens[3].off = 0.4f;
+
+ // Part under the radar.
+ i = 4;
+ m_lens[i].type = PARTISELR;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 9.9f, 40.1f);
+ m_lens[i].dim = 1.8f;
+ m_lens[i].total = 0.4f;
+ m_lens[i].off = 0.2f;
+ i ++;
+
+ m_lens[i].type = PARTISELY;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 7.2f, 34.8f);
+ m_lens[i].dim = 0.4f;
+ m_lens[i].total = 0.7f;
+ m_lens[i].off = 0.3f;
+ i ++;
+ m_lens[i].type = PARTISELY;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 34.3f);
+ m_lens[i].dim = 0.4f;
+ m_lens[i].total = 0.7f;
+ m_lens[i].off = 0.3f;
+ i ++;
+ m_lens[i].type = PARTISELR;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.4f);
+ m_lens[i].dim = 0.4f;
+ m_lens[i].total = 0.0f;
+ m_lens[i].off = 0.0f;
+ i ++;
+ m_lens[i].type = PARTISELR;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.0f);
+ m_lens[i].dim = 0.4f;
+ m_lens[i].total = 1.0f;
+ m_lens[i].off = 0.5f;
+ i ++;
+
+ m_lens[i].type = PARTISELY;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 8.5f, 14.0f);
+ m_lens[i].dim = 1.2f;
+ m_lens[i].total = 0.8f;
+ m_lens[i].off = 0.2f;
+ i ++;
+
+ m_lens[i].type = PARTISELR;
+ m_lens[i].pos = pos+Math::Vector(4.0f, 6.0f, 8.6f);
+ m_lens[i].dim = 1.0f;
+ m_lens[i].total = 0.9f;
+ m_lens[i].off = 0.7f;
+ i ++;
+
+ // Part with three windows.
+ m_lens[i].type = PARTISELR;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 9.9f, -19.9f);
+ m_lens[i].dim = 1.0f;
+ m_lens[i].total = 0.6f;
+ m_lens[i].off = 0.3f;
+ i ++;
+
+ m_lens[i].type = PARTISELY;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 7.2f, 34.8f-60.0f);
+ m_lens[i].dim = 0.4f;
+ m_lens[i].total = 0.7f;
+ m_lens[i].off = 0.3f;
+ i ++;
+ m_lens[i].type = PARTISELY;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 34.3f-60.0f);
+ m_lens[i].dim = 0.4f;
+ m_lens[i].total = 0.0f;
+ m_lens[i].off = 0.0f;
+ i ++;
+ m_lens[i].type = PARTISELR;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.4f-60.0f);
+ m_lens[i].dim = 0.4f;
+ m_lens[i].total = 0.6f;
+ m_lens[i].off = 0.4f;
+ i ++;
+ m_lens[i].type = PARTISELR;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.0f-60.0f);
+ m_lens[i].dim = 0.4f;
+ m_lens[i].total = 0.8f;
+ m_lens[i].off = 0.2f;
+ i ++;
+
+ m_lens[i].type = PARTISELY;
+ m_lens[i].pos = pos+Math::Vector(-6.5f, 13.5f, -37.0f);
+ m_lens[i].dim = 1.0f;
+ m_lens[i].total = 0.0f;
+ m_lens[i].off = 0.0f;
+ i ++;
+
+ m_lens[i].type = PARTISELY;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 12.2f, -39.8f);
+ m_lens[i].dim = 1.8f;
+ m_lens[i].total = 1.5f;
+ m_lens[i].off = 0.5f;
+ i ++;
+
+ m_lens[i].type = PARTISELY;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 8.5f, -47.0f);
+ m_lens[i].dim = 0.6f;
+ m_lens[i].total = 0.7f;
+ m_lens[i].off = 0.5f;
+ i ++;
+
+ m_lensTotal = i;
+
+ Init();
+}
+
+// Object's destructor.
+
+CAutoHuston::~CAutoHuston()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoHuston::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoHuston::Init()
+{
+ m_time = 0.0f;
+
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+}
+
+
+// Start the object.
+
+void CAutoHuston::Start(int param)
+{
+}
+
+
+// Management of an event.
+
+bool CAutoHuston::EventProcess(const Event &event)
+{
+ Math::Vector speed;
+ Math::Point dim;
+ float angle;
+ int i;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+
+ angle = -m_time*1.0f;
+ m_object->SetAngleY(1, angle); // rotates the radar
+ angle = sinf(m_time*4.0f)*0.3f;
+ m_object->SetAngleX(2, angle);
+
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+
+ // Flashes the keys.
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ for ( i=0 ; i<m_lensTotal ; i++ )
+ {
+ if ( m_lens[i].total != 0.0f &&
+ Math::Mod(m_time, m_lens[i].total) < m_lens[i].off )
+ {
+ if ( m_lens[i].parti != -1 )
+ {
+ m_particule->DeleteParticule(m_lens[i].parti);
+ m_lens[i].parti = -1;
+ }
+ }
+ else
+ {
+ if ( m_lens[i].parti == -1 )
+ {
+ dim.x = m_lens[i].dim;
+ dim.y = dim.x;
+ m_lens[i].parti = m_particule->CreateParticule(m_lens[i].pos, speed, dim, m_lens[i].type, 1.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+
+ return true;
+}
+
+// Stops the controller.
+
+bool CAutoHuston::Abort()
+{
+ return true;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoHuston::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 115, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+
+// Returns an error due to state of the automation.
+
+Error CAutoHuston::RetError()
+{
+ return ERR_OK;
+}
+
diff --git a/src/object/auto/autohuston.h b/src/object/auto/autohuston.h
index a12c4f2..a59f8f2 100644
--- a/src/object/auto/autohuston.h
+++ b/src/object/auto/autohuston.h
@@ -1,65 +1,65 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autohuston.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-#include "old/particule.h"
-
-
-
-struct HustonLens
-{
- int parti;
- ParticuleType type;
- Math::Vector pos;
- float dim;
- float total;
- float off;
-};
-
-
-const int HUSTONMAXLENS = 20;
-
-
-class CAutoHuston : public CAuto
-{
-public:
- CAutoHuston(CInstanceManager* iMan, CObject* object);
- ~CAutoHuston();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- void Start(int param);
- bool EventProcess(const Event &event);
- bool Abort();
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
-protected:
-
-protected:
- float m_progress;
- float m_speed;
- HustonLens m_lens[HUSTONMAXLENS];
- int m_lensTotal;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autohuston.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+#include "old/particule.h"
+
+
+
+struct HustonLens
+{
+ int parti;
+ ParticuleType type;
+ Math::Vector pos;
+ float dim;
+ float total;
+ float off;
+};
+
+
+const int HUSTONMAXLENS = 20;
+
+
+class CAutoHuston : public CAuto
+{
+public:
+ CAutoHuston(CInstanceManager* iMan, CObject* object);
+ ~CAutoHuston();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ void Start(int param);
+ bool EventProcess(const Event &event);
+ bool Abort();
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+protected:
+
+protected:
+ float m_progress;
+ float m_speed;
+ HustonLens m_lens[HUSTONMAXLENS];
+ int m_lensTotal;
+};
+
diff --git a/src/object/auto/autoinfo.cpp b/src/object/auto/autoinfo.cpp
index 6e00d44..56fd8c7 100644
--- a/src/object/auto/autoinfo.cpp
+++ b/src/object/auto/autoinfo.cpp
@@ -1,517 +1,517 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoinfo.h"
-
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/list.h"
-#include "ui/window.h"
-
-
-
-
-
-// Object's constructor.
-
-CAutoInfo::CAutoInfo(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
-}
-
-// Object's destructor.
-
-CAutoInfo::~CAutoInfo()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoInfo::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoInfo::Init()
-{
- m_phase = AIP_WAIT;
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_bLastVirus = false;
-
- CAuto::Init();
-}
-
-
-// Start a emission.
-
-void CAutoInfo::Start(int param)
-{
- Math::Vector pos, speed;
- Math::Point dim;
-
- if ( param == 0 ) // instruction "receive" ?
- {
- m_phase = AIP_EMETTE;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- else if ( param == 2 ) // instruction "send" ?
- {
- m_phase = AIP_RECEIVE;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- else
- {
- m_phase = AIP_ERROR;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
-
- m_lastParticule = 0;
- m_goal = m_object->RetPosition(0);
-
- if ( m_phase == AIP_EMETTE )
- {
- pos = m_goal;
- pos.y += 9.5f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 30.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISPHERE4, 1.5f, 0.0f, 0.0f);
-
- m_sound->Play(SOUND_LABO, pos, 1.0f, 2.0f);
- }
- if ( m_phase == AIP_RECEIVE )
- {
- pos = m_goal;
- pos.y += 9.5f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 50.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISPHERE6, 1.5f, 0.0f, 0.0f);
-
- m_sound->Play(SOUND_LABO, pos, 1.0f, 2.0f);
- }
- if ( m_phase == AIP_ERROR )
- {
- m_sound->Play(SOUND_GGG, pos, 1.0f, 0.5f);
- }
-}
-
-
-// Management of an event.
-
-bool CAutoInfo::EventProcess(const Event &event)
-{
- Math::Vector pos, speed;
- Math::Point dim;
- float duration, angle, rTime;
- int i;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
-
- angle = m_object->RetAngleY(1);
- angle += Math::Rand()*0.3f;
- m_object->SetAngleY(1, angle);
-
- m_object->SetAngleX(2, (Math::Rand()-0.5f)*0.3f);
- m_object->SetAngleX(4, (Math::Rand()-0.5f)*0.3f);
- m_object->SetAngleX(6, (Math::Rand()-0.5f)*0.3f);
-
- m_object->SetAngleZ(2, (Math::Rand()-0.5f)*0.3f);
- m_object->SetAngleZ(4, (Math::Rand()-0.5f)*0.3f);
- m_object->SetAngleZ(6, (Math::Rand()-0.5f)*0.3f);
-
- UpdateListVirus();
- }
- m_bLastVirus = true;
- return true;
- }
- else
- {
- if ( m_bLastVirus )
- {
- m_bLastVirus = false;
- UpdateList(); // normally returns the list
- }
- else
- {
- if ( m_object->RetInfoUpdate() )
- {
- UpdateList(); // updates the list
- }
- }
- }
-
- UpdateInterface(event.rTime);
-
- rTime = event.rTime;
-
- if ( m_phase == AIP_EMETTE ) // instruction "receive" ?
- {
- if ( m_progress < 0.5f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- for ( i=0 ; i<4 ; i++ )
- {
- pos = m_goal;
- pos.y += 9.5f;
- speed.x = (Math::Rand()-0.5f)*50.0f;
- speed.z = (Math::Rand()-0.5f)*50.0f;
- speed.y = (Math::Rand()-0.5f)*50.0f;
- speed *= 0.5f+m_progress*0.5f;
- dim.x = 0.6f;
- dim.y = dim.x;
- duration = Math::Rand()*0.5f+0.5f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
- duration, 0.0f,
- duration*0.9f, 0.7f);
- }
- }
-
- if ( m_progress < 1.0f )
- {
- m_progress += rTime*m_speed;
-
- m_object->SetAngleZ(2, m_progress*2.0f*Math::PI);
- m_object->SetAngleZ(4, m_progress*2.0f*Math::PI);
- m_object->SetAngleZ(6, m_progress*2.0f*Math::PI);
- }
- else
- {
- m_phase = AIP_WAIT;
-
- m_object->SetAngleX(2, 0.0f);
- m_object->SetAngleX(4, 0.0f);
- m_object->SetAngleX(6, 0.0f);
-
- m_object->SetAngleZ(2, 0.0f);
- m_object->SetAngleZ(4, 0.0f);
- m_object->SetAngleZ(6, 0.0f);
- }
- }
-
- if ( m_phase == AIP_RECEIVE ) // instruction "send" ?
- {
- if ( m_progress < 0.5f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- for ( i=0 ; i<4 ; i++ )
- {
- pos = m_goal;
- pos.y += 9.5f;
- speed = pos;
- pos.x += (Math::Rand()-0.5f)*40.0f;
- pos.y += (Math::Rand()-0.5f)*40.0f;
- pos.z += (Math::Rand()-0.5f)*40.0f;
- speed = (speed-pos)*1.0f;
-//? speed *= 0.5f+m_progress*0.5f;
- dim.x = 0.6f;
- dim.y = dim.x;
- duration = Math::Rand()*0.5f+0.5f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
- duration, 0.0f,
- duration*0.9f, 0.7f);
- }
- }
-
- if ( m_progress < 1.0f )
- {
- m_progress += rTime*m_speed;
-
- m_object->SetAngleZ(2, m_progress*2.0f*Math::PI);
- m_object->SetAngleZ(4, m_progress*2.0f*Math::PI);
- m_object->SetAngleZ(6, m_progress*2.0f*Math::PI);
- }
- else
- {
- m_phase = AIP_WAIT;
-
- m_object->SetAngleX(2, 0.0f);
- m_object->SetAngleX(4, 0.0f);
- m_object->SetAngleX(6, 0.0f);
-
- m_object->SetAngleZ(2, 0.0f);
- m_object->SetAngleZ(4, 0.0f);
- m_object->SetAngleZ(6, 0.0f);
- }
- }
-
- if ( m_phase == AIP_ERROR )
- {
- if ( m_progress < 0.5f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_goal;
- speed.x = (Math::Rand()-0.5f)*5.0f;
- speed.z = (Math::Rand()-0.5f)*5.0f;
- speed.y = 5.0f+Math::Rand()*5.0f;
- dim.x = 5.0f+Math::Rand()*5.0f;
- dim.y = dim.x;
- duration = Math::Rand()*0.5f+0.5f;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 4.0f);
- }
-
- if ( m_progress < 1.0f )
- {
- m_progress += rTime*m_speed;
- rTime = 0.0f; // stops the rotation
-
- if ( m_progress < 0.5f )
- {
- angle = m_progress/0.5f;
- }
- else
- {
- angle = 1.0f-(m_progress-0.5f)/0.5f;
- }
- m_object->SetAngleX(2, angle*0.5f);
- m_object->SetAngleX(4, angle*0.5f);
- m_object->SetAngleX(6, angle*0.5f);
-
- m_object->SetAngleZ(2, (Math::Rand()-0.5f)*0.2f);
- m_object->SetAngleZ(4, (Math::Rand()-0.5f)*0.2f);
- m_object->SetAngleZ(6, (Math::Rand()-0.5f)*0.2f);
- }
- else
- {
- m_phase = AIP_WAIT;
-
- m_object->SetAngleX(2, 0.0f);
- m_object->SetAngleX(4, 0.0f);
- m_object->SetAngleX(6, 0.0f);
-
- m_object->SetAngleZ(2, 0.0f);
- m_object->SetAngleZ(4, 0.0f);
- m_object->SetAngleZ(6, 0.0f);
- }
- }
-
- angle = m_object->RetAngleY(1);
- angle += rTime*0.5f;
- m_object->SetAngleY(1, angle);
-
- m_object->SetAngleX(3, sinf(m_time*6.0f+Math::PI*0.0f/3.0f)*0.3f);
- m_object->SetAngleX(5, sinf(m_time*6.0f+Math::PI*2.0f/3.0f)*0.3f);
- m_object->SetAngleX(7, sinf(m_time*6.0f+Math::PI*4.0f/3.0f)*0.3f);
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoInfo::RetError()
-{
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- return ERR_OK;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoInfo::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- CList* pl;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*7.0f;
- pos.y = oy+sy*0.0f;
- ddim.x = 160.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pl = pw->CreateList(pos, ddim, 1, EVENT_OBJECT_GINFO, 1.10f);
- pl->SetSelectCap(false);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 112, EVENT_OBJECT_TYPE);
-
- UpdateList();
- return true;
-}
-
-// Updates the state of all buttons on the interface,
-// following the time that elapses ...
-
-void CAutoInfo::UpdateInterface(float rTime)
-{
- CAuto::UpdateInterface(rTime);
-}
-
-
-// Updates the contents of the list.
-
-void CAutoInfo::UpdateList()
-{
- CWindow* pw;
- CList* pl;
- Info info;
- int total, i;
- char text[100];
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pl = (CList*)pw->SearchControl(EVENT_OBJECT_GINFO);
- if ( pl == 0 ) return;
-
- pl->Flush();
- total = m_object->RetInfoTotal();
- if ( total == 0 )
- {
- pl->ClearState(STATE_ENABLE);
- }
- else
- {
- pl->SetState(STATE_ENABLE);
-
- for ( i=0 ; i<total ; i++ )
- {
- info = m_object->RetInfo(i);
- sprintf(text, "%s = %.2f", info.name, info.value);
- pl->SetName(i, text);
- }
- }
-
- m_object->SetInfoUpdate(false);
-}
-
-// Updates the content of contaminating the list.
-
-void CAutoInfo::UpdateListVirus()
-{
- CWindow* pw;
- CList* pl;
- int i, j, max;
- char text[100];
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pl = (CList*)pw->SearchControl(EVENT_OBJECT_GINFO);
- if ( pl == 0 ) return;
-
- pl->SetState(STATE_ENABLE);
-
- pl->Flush();
- for ( i=0 ; i<4 ; i++ )
- {
- max = (int)(2.0f+Math::Rand()*10.0f);
- for ( j=0 ; j<max ; j++ )
- {
- do
- {
- text[j] = ' '+(int)(Math::Rand()*94.0f);
- }
- while ( text[j] == '\\' );
- }
- text[j] = 0;
-
- pl->SetName(i, text);
- }
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoInfo::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == AIP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoInfo::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoInfoPhase)OpInt(line, "aPhase", AIP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoinfo.h"
+
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/list.h"
+#include "ui/window.h"
+
+
+
+
+
+// Object's constructor.
+
+CAutoInfo::CAutoInfo(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+}
+
+// Object's destructor.
+
+CAutoInfo::~CAutoInfo()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoInfo::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoInfo::Init()
+{
+ m_phase = AIP_WAIT;
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_bLastVirus = false;
+
+ CAuto::Init();
+}
+
+
+// Start a emission.
+
+void CAutoInfo::Start(int param)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+
+ if ( param == 0 ) // instruction "receive" ?
+ {
+ m_phase = AIP_EMETTE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ else if ( param == 2 ) // instruction "send" ?
+ {
+ m_phase = AIP_RECEIVE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ else
+ {
+ m_phase = AIP_ERROR;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+
+ m_lastParticule = 0;
+ m_goal = m_object->RetPosition(0);
+
+ if ( m_phase == AIP_EMETTE )
+ {
+ pos = m_goal;
+ pos.y += 9.5f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 30.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISPHERE4, 1.5f, 0.0f, 0.0f);
+
+ m_sound->Play(SOUND_LABO, pos, 1.0f, 2.0f);
+ }
+ if ( m_phase == AIP_RECEIVE )
+ {
+ pos = m_goal;
+ pos.y += 9.5f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 50.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISPHERE6, 1.5f, 0.0f, 0.0f);
+
+ m_sound->Play(SOUND_LABO, pos, 1.0f, 2.0f);
+ }
+ if ( m_phase == AIP_ERROR )
+ {
+ m_sound->Play(SOUND_GGG, pos, 1.0f, 0.5f);
+ }
+}
+
+
+// Management of an event.
+
+bool CAutoInfo::EventProcess(const Event &event)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float duration, angle, rTime;
+ int i;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+
+ angle = m_object->RetAngleY(1);
+ angle += Math::Rand()*0.3f;
+ m_object->SetAngleY(1, angle);
+
+ m_object->SetAngleX(2, (Math::Rand()-0.5f)*0.3f);
+ m_object->SetAngleX(4, (Math::Rand()-0.5f)*0.3f);
+ m_object->SetAngleX(6, (Math::Rand()-0.5f)*0.3f);
+
+ m_object->SetAngleZ(2, (Math::Rand()-0.5f)*0.3f);
+ m_object->SetAngleZ(4, (Math::Rand()-0.5f)*0.3f);
+ m_object->SetAngleZ(6, (Math::Rand()-0.5f)*0.3f);
+
+ UpdateListVirus();
+ }
+ m_bLastVirus = true;
+ return true;
+ }
+ else
+ {
+ if ( m_bLastVirus )
+ {
+ m_bLastVirus = false;
+ UpdateList(); // normally returns the list
+ }
+ else
+ {
+ if ( m_object->RetInfoUpdate() )
+ {
+ UpdateList(); // updates the list
+ }
+ }
+ }
+
+ UpdateInterface(event.rTime);
+
+ rTime = event.rTime;
+
+ if ( m_phase == AIP_EMETTE ) // instruction "receive" ?
+ {
+ if ( m_progress < 0.5f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ pos = m_goal;
+ pos.y += 9.5f;
+ speed.x = (Math::Rand()-0.5f)*50.0f;
+ speed.z = (Math::Rand()-0.5f)*50.0f;
+ speed.y = (Math::Rand()-0.5f)*50.0f;
+ speed *= 0.5f+m_progress*0.5f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ duration = Math::Rand()*0.5f+0.5f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
+ duration, 0.0f,
+ duration*0.9f, 0.7f);
+ }
+ }
+
+ if ( m_progress < 1.0f )
+ {
+ m_progress += rTime*m_speed;
+
+ m_object->SetAngleZ(2, m_progress*2.0f*Math::PI);
+ m_object->SetAngleZ(4, m_progress*2.0f*Math::PI);
+ m_object->SetAngleZ(6, m_progress*2.0f*Math::PI);
+ }
+ else
+ {
+ m_phase = AIP_WAIT;
+
+ m_object->SetAngleX(2, 0.0f);
+ m_object->SetAngleX(4, 0.0f);
+ m_object->SetAngleX(6, 0.0f);
+
+ m_object->SetAngleZ(2, 0.0f);
+ m_object->SetAngleZ(4, 0.0f);
+ m_object->SetAngleZ(6, 0.0f);
+ }
+ }
+
+ if ( m_phase == AIP_RECEIVE ) // instruction "send" ?
+ {
+ if ( m_progress < 0.5f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ pos = m_goal;
+ pos.y += 9.5f;
+ speed = pos;
+ pos.x += (Math::Rand()-0.5f)*40.0f;
+ pos.y += (Math::Rand()-0.5f)*40.0f;
+ pos.z += (Math::Rand()-0.5f)*40.0f;
+ speed = (speed-pos)*1.0f;
+//? speed *= 0.5f+m_progress*0.5f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ duration = Math::Rand()*0.5f+0.5f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
+ duration, 0.0f,
+ duration*0.9f, 0.7f);
+ }
+ }
+
+ if ( m_progress < 1.0f )
+ {
+ m_progress += rTime*m_speed;
+
+ m_object->SetAngleZ(2, m_progress*2.0f*Math::PI);
+ m_object->SetAngleZ(4, m_progress*2.0f*Math::PI);
+ m_object->SetAngleZ(6, m_progress*2.0f*Math::PI);
+ }
+ else
+ {
+ m_phase = AIP_WAIT;
+
+ m_object->SetAngleX(2, 0.0f);
+ m_object->SetAngleX(4, 0.0f);
+ m_object->SetAngleX(6, 0.0f);
+
+ m_object->SetAngleZ(2, 0.0f);
+ m_object->SetAngleZ(4, 0.0f);
+ m_object->SetAngleZ(6, 0.0f);
+ }
+ }
+
+ if ( m_phase == AIP_ERROR )
+ {
+ if ( m_progress < 0.5f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_goal;
+ speed.x = (Math::Rand()-0.5f)*5.0f;
+ speed.z = (Math::Rand()-0.5f)*5.0f;
+ speed.y = 5.0f+Math::Rand()*5.0f;
+ dim.x = 5.0f+Math::Rand()*5.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*0.5f+0.5f;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 4.0f);
+ }
+
+ if ( m_progress < 1.0f )
+ {
+ m_progress += rTime*m_speed;
+ rTime = 0.0f; // stops the rotation
+
+ if ( m_progress < 0.5f )
+ {
+ angle = m_progress/0.5f;
+ }
+ else
+ {
+ angle = 1.0f-(m_progress-0.5f)/0.5f;
+ }
+ m_object->SetAngleX(2, angle*0.5f);
+ m_object->SetAngleX(4, angle*0.5f);
+ m_object->SetAngleX(6, angle*0.5f);
+
+ m_object->SetAngleZ(2, (Math::Rand()-0.5f)*0.2f);
+ m_object->SetAngleZ(4, (Math::Rand()-0.5f)*0.2f);
+ m_object->SetAngleZ(6, (Math::Rand()-0.5f)*0.2f);
+ }
+ else
+ {
+ m_phase = AIP_WAIT;
+
+ m_object->SetAngleX(2, 0.0f);
+ m_object->SetAngleX(4, 0.0f);
+ m_object->SetAngleX(6, 0.0f);
+
+ m_object->SetAngleZ(2, 0.0f);
+ m_object->SetAngleZ(4, 0.0f);
+ m_object->SetAngleZ(6, 0.0f);
+ }
+ }
+
+ angle = m_object->RetAngleY(1);
+ angle += rTime*0.5f;
+ m_object->SetAngleY(1, angle);
+
+ m_object->SetAngleX(3, sinf(m_time*6.0f+Math::PI*0.0f/3.0f)*0.3f);
+ m_object->SetAngleX(5, sinf(m_time*6.0f+Math::PI*2.0f/3.0f)*0.3f);
+ m_object->SetAngleX(7, sinf(m_time*6.0f+Math::PI*4.0f/3.0f)*0.3f);
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoInfo::RetError()
+{
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ return ERR_OK;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoInfo::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ CList* pl;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*7.0f;
+ pos.y = oy+sy*0.0f;
+ ddim.x = 160.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pl = pw->CreateList(pos, ddim, 1, EVENT_OBJECT_GINFO, 1.10f);
+ pl->SetSelectCap(false);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 112, EVENT_OBJECT_TYPE);
+
+ UpdateList();
+ return true;
+}
+
+// Updates the state of all buttons on the interface,
+// following the time that elapses ...
+
+void CAutoInfo::UpdateInterface(float rTime)
+{
+ CAuto::UpdateInterface(rTime);
+}
+
+
+// Updates the contents of the list.
+
+void CAutoInfo::UpdateList()
+{
+ CWindow* pw;
+ CList* pl;
+ Info info;
+ int total, i;
+ char text[100];
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pl = (CList*)pw->SearchControl(EVENT_OBJECT_GINFO);
+ if ( pl == 0 ) return;
+
+ pl->Flush();
+ total = m_object->RetInfoTotal();
+ if ( total == 0 )
+ {
+ pl->ClearState(STATE_ENABLE);
+ }
+ else
+ {
+ pl->SetState(STATE_ENABLE);
+
+ for ( i=0 ; i<total ; i++ )
+ {
+ info = m_object->RetInfo(i);
+ sprintf(text, "%s = %.2f", info.name, info.value);
+ pl->SetName(i, text);
+ }
+ }
+
+ m_object->SetInfoUpdate(false);
+}
+
+// Updates the content of contaminating the list.
+
+void CAutoInfo::UpdateListVirus()
+{
+ CWindow* pw;
+ CList* pl;
+ int i, j, max;
+ char text[100];
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pl = (CList*)pw->SearchControl(EVENT_OBJECT_GINFO);
+ if ( pl == 0 ) return;
+
+ pl->SetState(STATE_ENABLE);
+
+ pl->Flush();
+ for ( i=0 ; i<4 ; i++ )
+ {
+ max = (int)(2.0f+Math::Rand()*10.0f);
+ for ( j=0 ; j<max ; j++ )
+ {
+ do
+ {
+ text[j] = ' '+(int)(Math::Rand()*94.0f);
+ }
+ while ( text[j] == '\\' );
+ }
+ text[j] = 0;
+
+ pl->SetName(i, text);
+ }
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoInfo::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == AIP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoInfo::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoInfoPhase)OpInt(line, "aPhase", AIP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autoinfo.h b/src/object/auto/autoinfo.h
index cf3d1d4..cfe3c1b 100644
--- a/src/object/auto/autoinfo.h
+++ b/src/object/auto/autoinfo.h
@@ -1,68 +1,68 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoinfo.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoInfoPhase
-{
- AIP_WAIT = 1,
- AIP_EMETTE = 2,
- AIP_RECEIVE = 3,
- AIP_ERROR = 4,
-};
-
-
-
-class CAutoInfo : public CAuto
-{
-public:
- CAutoInfo(CInstanceManager* iMan, CObject* object);
- ~CAutoInfo();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- void Start(int param);
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- void UpdateInterface(float rTime);
- void UpdateList();
- void UpdateListVirus();
-
-protected:
- AutoInfoPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
- Math::Vector m_goal;
- bool m_bLastVirus;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoinfo.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoInfoPhase
+{
+ AIP_WAIT = 1,
+ AIP_EMETTE = 2,
+ AIP_RECEIVE = 3,
+ AIP_ERROR = 4,
+};
+
+
+
+class CAutoInfo : public CAuto
+{
+public:
+ CAutoInfo(CInstanceManager* iMan, CObject* object);
+ ~CAutoInfo();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ void Start(int param);
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ void UpdateInterface(float rTime);
+ void UpdateList();
+ void UpdateListVirus();
+
+protected:
+ AutoInfoPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+ Math::Vector m_goal;
+ bool m_bLastVirus;
+};
+
diff --git a/src/object/auto/autojostle.cpp b/src/object/auto/autojostle.cpp
index 6917ae7..3944297 100644
--- a/src/object/auto/autojostle.cpp
+++ b/src/object/auto/autojostle.cpp
@@ -1,142 +1,142 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autojostle.h"
-
-
-
-
-// Object's constructor.
-
-CAutoJostle::CAutoJostle(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
-}
-
-// Object's destructor.
-
-CAutoJostle::~CAutoJostle()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoJostle::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoJostle::Init()
-{
- m_time = 0.0f;
- m_error = ERR_CONTINUE;
-
- CAuto::Init();
-}
-
-
-// Start an emission.
-
-void CAutoJostle::Start(int param, float force)
-{
- ObjectType type;
-
- if ( force < 0.0f ) force = 0.0f;
- if ( force > 1.0f ) force = 1.0f;
-
- m_force = force;
- m_progress = 0.0f;
- m_speed = 1.0f/(0.5f+force*1.0f); // 0.5 .. 1.5
- m_time = 0.0f;
- m_error = ERR_CONTINUE;
-
- type = m_object->RetType();
- if ( type >= OBJECT_PLANT5 &&
- type <= OBJECT_PLANT7 ) // clover?
- {
- m_force *= 3.0f;
- }
-}
-
-
-// Management of an event.
-
-bool CAutoJostle::EventProcess(const Event &event)
-{
- Math::Vector dir;
- float factor, angle, zoom;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- if ( m_progress < 1.0f )
- {
- m_progress += event.rTime*m_speed;
-
- if ( m_progress < 0.5f )
- {
- factor = m_progress/0.5f;
- }
- else
- {
- factor = 2.0f-m_progress/0.5f;
- }
- factor *= m_force;
-
- dir.x = sinf(m_progress*Math::PI*4.0f);
- dir.z = cosf(m_progress*Math::PI*4.0f);
-
- angle = sinf(m_time*10.0f)*factor*0.04f;
- m_object->SetAngleX(0, angle*dir.z);
- m_object->SetAngleZ(0, angle*dir.x);
-
- zoom = 1.0f+sinf(m_time*8.0f)*factor*0.06f;
- m_object->SetZoomX(0, zoom);
- zoom = 1.0f+sinf(m_time*5.0f)*factor*0.06f;
- m_object->SetZoomY(0, zoom);
- zoom = 1.0f+sinf(m_time*7.0f)*factor*0.06f;
- m_object->SetZoomZ(0, zoom);
- }
- else
- {
- m_object->SetAngleX(0, 0.0f);
- m_object->SetAngleZ(0, 0.0f);
- m_object->SetZoom(0, Math::Vector(1.0f, 1.0f, 1.0f));
- m_error = ERR_STOP;
- }
-
- return true;
-}
-
-
-// Indicates whether the controller has completed its activity.
-
-Error CAutoJostle::IsEnded()
-{
- return m_error;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autojostle.h"
+
+
+
+
+// Object's constructor.
+
+CAutoJostle::CAutoJostle(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+}
+
+// Object's destructor.
+
+CAutoJostle::~CAutoJostle()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoJostle::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoJostle::Init()
+{
+ m_time = 0.0f;
+ m_error = ERR_CONTINUE;
+
+ CAuto::Init();
+}
+
+
+// Start an emission.
+
+void CAutoJostle::Start(int param, float force)
+{
+ ObjectType type;
+
+ if ( force < 0.0f ) force = 0.0f;
+ if ( force > 1.0f ) force = 1.0f;
+
+ m_force = force;
+ m_progress = 0.0f;
+ m_speed = 1.0f/(0.5f+force*1.0f); // 0.5 .. 1.5
+ m_time = 0.0f;
+ m_error = ERR_CONTINUE;
+
+ type = m_object->RetType();
+ if ( type >= OBJECT_PLANT5 &&
+ type <= OBJECT_PLANT7 ) // clover?
+ {
+ m_force *= 3.0f;
+ }
+}
+
+
+// Management of an event.
+
+bool CAutoJostle::EventProcess(const Event &event)
+{
+ Math::Vector dir;
+ float factor, angle, zoom;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ if ( m_progress < 1.0f )
+ {
+ m_progress += event.rTime*m_speed;
+
+ if ( m_progress < 0.5f )
+ {
+ factor = m_progress/0.5f;
+ }
+ else
+ {
+ factor = 2.0f-m_progress/0.5f;
+ }
+ factor *= m_force;
+
+ dir.x = sinf(m_progress*Math::PI*4.0f);
+ dir.z = cosf(m_progress*Math::PI*4.0f);
+
+ angle = sinf(m_time*10.0f)*factor*0.04f;
+ m_object->SetAngleX(0, angle*dir.z);
+ m_object->SetAngleZ(0, angle*dir.x);
+
+ zoom = 1.0f+sinf(m_time*8.0f)*factor*0.06f;
+ m_object->SetZoomX(0, zoom);
+ zoom = 1.0f+sinf(m_time*5.0f)*factor*0.06f;
+ m_object->SetZoomY(0, zoom);
+ zoom = 1.0f+sinf(m_time*7.0f)*factor*0.06f;
+ m_object->SetZoomZ(0, zoom);
+ }
+ else
+ {
+ m_object->SetAngleX(0, 0.0f);
+ m_object->SetAngleZ(0, 0.0f);
+ m_object->SetZoom(0, Math::Vector(1.0f, 1.0f, 1.0f));
+ m_error = ERR_STOP;
+ }
+
+ return true;
+}
+
+
+// Indicates whether the controller has completed its activity.
+
+Error CAutoJostle::IsEnded()
+{
+ return m_error;
+}
+
+
diff --git a/src/object/auto/autojostle.h b/src/object/auto/autojostle.h
index c76f953..70bb5e6 100644
--- a/src/object/auto/autojostle.h
+++ b/src/object/auto/autojostle.h
@@ -1,48 +1,48 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autojostle.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-class CAutoJostle : public CAuto
-{
-public:
- CAutoJostle(CInstanceManager* iMan, CObject* object);
- ~CAutoJostle();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- void Start(int param, float force);
- bool EventProcess(const Event &event);
- Error IsEnded();
-
-protected:
-
-protected:
- float m_force;
- float m_progress;
- float m_speed;
- float m_lastParticule;
- Error m_error;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autojostle.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+class CAutoJostle : public CAuto
+{
+public:
+ CAutoJostle(CInstanceManager* iMan, CObject* object);
+ ~CAutoJostle();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ void Start(int param, float force);
+ bool EventProcess(const Event &event);
+ Error IsEnded();
+
+protected:
+
+protected:
+ float m_force;
+ float m_progress;
+ float m_speed;
+ float m_lastParticule;
+ Error m_error;
+};
+
diff --git a/src/object/auto/autokid.cpp b/src/object/auto/autokid.cpp
index 9177aa8..e5987cc 100644
--- a/src/object/auto/autokid.cpp
+++ b/src/object/auto/autokid.cpp
@@ -1,201 +1,201 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autokid.h"
-
-#include "old/particule.h"
-#include "old/water.h"
-
-
-
-// Object's constructor.
-
-CAutoKid::CAutoKid(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- m_soundChannel = -1;
- Init();
-}
-
-// Object's constructor.
-
-CAutoKid::~CAutoKid()
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-}
-
-
-// Destroys the object.
-
-void CAutoKid::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoKid::Init()
-{
- Math::Vector pos;
-
- m_speed = 1.0f/1.0f;
- m_progress = 0.0f;
- m_lastParticule = 0.0f;
-
- if ( m_type == OBJECT_TEEN36 ) // trunk ?
- {
- pos = m_object->RetPosition(0);
- m_speed = 1.0f/(1.0f+(Math::Mod(pos.x/10.0f-0.5f, 1.0f)*0.2f));
- m_progress = Math::Mod(pos.x/10.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_TEEN37 ) // boat?
- {
- pos = m_object->RetPosition(0);
- m_speed = 1.0f/(1.0f+(Math::Mod(pos.x/10.0f-0.5f, 1.0f)*0.2f))*2.5f;
- m_progress = Math::Mod(pos.x/10.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_TEEN38 ) // fan?
- {
- if ( m_soundChannel == -1 )
- {
-//? m_soundChannel = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 1.0f, 0.5f, true);
- m_bSilent = false;
- }
- }
-}
-
-
-// Management of an event.
-
-bool CAutoKid::EventProcess(const Event &event)
-{
- Math::Vector vib, pos, speed;
- Math::Point dim;
-
- CAuto::EventProcess(event);
-
- if ( m_soundChannel != -1 )
- {
- if ( m_engine->RetPause() )
- {
- if ( !m_bSilent )
- {
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.1f, SOPER_CONTINUE);
- m_bSilent = true;
- }
- }
- else
- {
- if ( m_bSilent )
- {
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 0.1f, SOPER_CONTINUE);
- m_bSilent = false;
- }
- }
- }
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
-
- if ( m_type == OBJECT_TEEN36 ) // trunk?
- {
- vib.x = 0.0f;
- vib.y = sinf(m_progress)*1.0f;
- vib.z = 0.0f;
- m_object->SetLinVibration(vib);
-
- vib.x = 0.0f;
- vib.y = 0.0f;
- vib.z = sinf(m_progress*0.5f)*0.05f;
- m_object->SetCirVibration(vib);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.15f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.y = m_water->RetLevel()+1.0f;
- pos.x += (Math::Rand()-0.5f)*50.0f;
- pos.z += (Math::Rand()-0.5f)*50.0f;
- speed.y = 0.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- dim.x = 50.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFLIC, 3.0f, 0.0f, 0.0f);
- }
- }
-
- if ( m_type == OBJECT_TEEN37 ) // boat?
- {
- vib.x = 0.0f;
- vib.y = sinf(m_progress)*1.0f;
- vib.z = 0.0f;
- m_object->SetLinVibration(vib);
-
- vib.x = 0.0f;
- vib.y = 0.0f;
- vib.z = sinf(m_progress*0.5f)*0.15f;
- m_object->SetCirVibration(vib);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.15f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.y = m_water->RetLevel()+1.0f;
- pos.x += (Math::Rand()-0.5f)*20.0f;
- pos.z += (Math::Rand()-0.5f)*20.0f;
- speed.y = 0.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- dim.x = 20.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFLIC, 3.0f, 0.0f, 0.0f);
- }
- }
-
- if ( m_type == OBJECT_TEEN38 ) // fan?
- {
- m_object->SetAngleY(1, sinf(m_progress*0.6f)*0.4f);
- m_object->SetAngleX(2, m_progress*5.0f);
- }
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoKid::RetError()
-{
- return ERR_OK;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autokid.h"
+
+#include "old/particule.h"
+#include "old/water.h"
+
+
+
+// Object's constructor.
+
+CAutoKid::CAutoKid(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ m_soundChannel = -1;
+ Init();
+}
+
+// Object's constructor.
+
+CAutoKid::~CAutoKid()
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+}
+
+
+// Destroys the object.
+
+void CAutoKid::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoKid::Init()
+{
+ Math::Vector pos;
+
+ m_speed = 1.0f/1.0f;
+ m_progress = 0.0f;
+ m_lastParticule = 0.0f;
+
+ if ( m_type == OBJECT_TEEN36 ) // trunk ?
+ {
+ pos = m_object->RetPosition(0);
+ m_speed = 1.0f/(1.0f+(Math::Mod(pos.x/10.0f-0.5f, 1.0f)*0.2f));
+ m_progress = Math::Mod(pos.x/10.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_TEEN37 ) // boat?
+ {
+ pos = m_object->RetPosition(0);
+ m_speed = 1.0f/(1.0f+(Math::Mod(pos.x/10.0f-0.5f, 1.0f)*0.2f))*2.5f;
+ m_progress = Math::Mod(pos.x/10.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_TEEN38 ) // fan?
+ {
+ if ( m_soundChannel == -1 )
+ {
+//? m_soundChannel = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 1.0f, 0.5f, true);
+ m_bSilent = false;
+ }
+ }
+}
+
+
+// Management of an event.
+
+bool CAutoKid::EventProcess(const Event &event)
+{
+ Math::Vector vib, pos, speed;
+ Math::Point dim;
+
+ CAuto::EventProcess(event);
+
+ if ( m_soundChannel != -1 )
+ {
+ if ( m_engine->RetPause() )
+ {
+ if ( !m_bSilent )
+ {
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.1f, SOPER_CONTINUE);
+ m_bSilent = true;
+ }
+ }
+ else
+ {
+ if ( m_bSilent )
+ {
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 0.1f, SOPER_CONTINUE);
+ m_bSilent = false;
+ }
+ }
+ }
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+
+ if ( m_type == OBJECT_TEEN36 ) // trunk?
+ {
+ vib.x = 0.0f;
+ vib.y = sinf(m_progress)*1.0f;
+ vib.z = 0.0f;
+ m_object->SetLinVibration(vib);
+
+ vib.x = 0.0f;
+ vib.y = 0.0f;
+ vib.z = sinf(m_progress*0.5f)*0.05f;
+ m_object->SetCirVibration(vib);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.15f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.y = m_water->RetLevel()+1.0f;
+ pos.x += (Math::Rand()-0.5f)*50.0f;
+ pos.z += (Math::Rand()-0.5f)*50.0f;
+ speed.y = 0.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ dim.x = 50.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFLIC, 3.0f, 0.0f, 0.0f);
+ }
+ }
+
+ if ( m_type == OBJECT_TEEN37 ) // boat?
+ {
+ vib.x = 0.0f;
+ vib.y = sinf(m_progress)*1.0f;
+ vib.z = 0.0f;
+ m_object->SetLinVibration(vib);
+
+ vib.x = 0.0f;
+ vib.y = 0.0f;
+ vib.z = sinf(m_progress*0.5f)*0.15f;
+ m_object->SetCirVibration(vib);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.15f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.y = m_water->RetLevel()+1.0f;
+ pos.x += (Math::Rand()-0.5f)*20.0f;
+ pos.z += (Math::Rand()-0.5f)*20.0f;
+ speed.y = 0.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ dim.x = 20.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFLIC, 3.0f, 0.0f, 0.0f);
+ }
+ }
+
+ if ( m_type == OBJECT_TEEN38 ) // fan?
+ {
+ m_object->SetAngleY(1, sinf(m_progress*0.6f)*0.4f);
+ m_object->SetAngleX(2, m_progress*5.0f);
+ }
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoKid::RetError()
+{
+ return ERR_OK;
+}
+
+
diff --git a/src/object/auto/autokid.h b/src/object/auto/autokid.h
index 900eb92..6d4258f 100644
--- a/src/object/auto/autokid.h
+++ b/src/object/auto/autokid.h
@@ -1,47 +1,47 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autokid.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-class CAutoKid : public CAuto
-{
-public:
- CAutoKid(CInstanceManager* iMan, CObject* object);
- ~CAutoKid();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
-protected:
-
-protected:
- float m_speed;
- float m_progress;
- float m_lastParticule;
- int m_soundChannel;
- bool m_bSilent;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autokid.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+class CAutoKid : public CAuto
+{
+public:
+ CAutoKid(CInstanceManager* iMan, CObject* object);
+ ~CAutoKid();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+protected:
+
+protected:
+ float m_speed;
+ float m_progress;
+ float m_lastParticule;
+ int m_soundChannel;
+ bool m_bSilent;
+};
+
diff --git a/src/object/auto/autolabo.cpp b/src/object/auto/autolabo.cpp
index b675581..4239f49 100644
--- a/src/object/auto/autolabo.cpp
+++ b/src/object/auto/autolabo.cpp
@@ -1,610 +1,610 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autolabo.h"
-
-#include "common/global.h"
-#include "common/misc.h"
-#include "math/geometry.h"
-#include "object/robotmain.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-
-
-
-const float LABO_DELAY = 20.0f; // duration of the analysis
-
-
-
-
-// Object's constructor.
-
-CAutoLabo::CAutoLabo(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- int i;
-
- for ( i=0 ; i<3 ; i++ )
- {
- m_partiRank[i] = -1;
- }
- m_partiSphere = -1;
-
- m_soundChannel = -1;
- Init();
-}
-
-// Object's destructor.
-
-CAutoLabo::~CAutoLabo()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoLabo::DeleteObject(bool bAll)
-{
- int i;
-
- for ( i=0 ; i<3 ; i++ )
- {
- if ( m_partiRank[i] != -1 )
- {
- m_particule->DeleteParticule(m_partiRank[i]);
- m_partiRank[i] = -1;
- }
- }
-
- if ( m_partiSphere != -1 )
- {
- m_particule->DeleteParticule(m_partiSphere);
- m_partiSphere = -1;
- }
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoLabo::Init()
-{
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastParticule = 0.0f;
-
- m_phase = ALAP_WAIT; // waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoLabo::EventProcess(const Event &event)
-{
- CObject* power;
- Math::Vector pos, goal, speed;
- Math::Point dim, rot;
- float angle;
- int i;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
-
- if ( event.event == EVENT_UPDINTERFACE )
- {
- if ( m_object->RetSelect() ) CreateInterface(true);
- }
-
- if ( m_object->RetSelect() && // center selected?
- (event.event == EVENT_OBJECT_RiPAW ||
- event.event == EVENT_OBJECT_RiGUN) )
- {
- if ( m_phase != ALAP_WAIT )
- {
- return false;
- }
-
- m_research = event.event;
-
- if ( TestResearch(m_research) )
- {
- m_displayText->DisplayError(ERR_LABO_ALREADY, m_object);
- return false;
- }
-
- power = m_object->RetPower();
- if ( power == 0 )
- {
- m_displayText->DisplayError(ERR_LABO_NULL, m_object);
- return false;
- }
- if ( power->RetType() != OBJECT_BULLET )
- {
- m_displayText->DisplayError(ERR_LABO_BAD, m_object);
- return false;
- }
-
- SetBusy(true);
- InitProgressTotal(1.0f+1.5f+1.5f+LABO_DELAY+1.5f+1.5f+1.0f);
- UpdateInterface();
-
- power->SetLock(true); // ball longer usable
-
- SoundManip(1.0f, 1.0f, 1.0f);
- m_phase = ALAP_OPEN1;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- return true;
- }
-
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
- }
- return true;
- }
-
- EventProgress(event.rTime);
-
- if ( m_phase == ALAP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- m_phase = ALAP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == ALAP_OPEN1 )
- {
- if ( m_progress < 1.0f )
- {
- angle = 80.0f-(35.0f*m_progress);
- m_object->SetAngleZ(3, angle*Math::PI/180.0f);
- m_object->SetAngleZ(4, angle*Math::PI/180.0f);
- m_object->SetAngleZ(5, angle*Math::PI/180.0f);
- }
- else
- {
- m_object->SetAngleZ(3, 45.0f*Math::PI/180.0f);
- m_object->SetAngleZ(4, 45.0f*Math::PI/180.0f);
- m_object->SetAngleZ(5, 45.0f*Math::PI/180.0f);
-
- SoundManip(1.5f, 1.0f, 0.7f);
- m_phase = ALAP_OPEN2;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
-
- if ( m_phase == ALAP_OPEN2 )
- {
- if ( m_progress < 1.0f )
- {
- pos.x = -9.0f;
- pos.y = 3.0f+m_progress*10.0f;
- pos.z = 0.0f;
- m_object->SetPosition(1, pos);
- }
- else
- {
- m_object->SetPosition(1, Math::Vector(-9.0f, 13.0f, 0.0f));
-
- SoundManip(1.5f, 1.0f, 0.5f);
- m_phase = ALAP_OPEN3;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
-
- if ( m_phase == ALAP_OPEN3 )
- {
- if ( m_progress < 1.0f )
- {
- angle = (1.0f-m_progress)*Math::PI/2.0f;
- m_object->SetAngleZ(1, angle);
- }
- else
- {
- m_object->SetAngleZ(1, 0.0f);
-
- goal = m_object->RetPosition(0);
- goal.y += 3.0f;
- pos = goal;
- pos.x -= 4.0f;
- pos.y += 4.0f;
- for ( i=0 ; i<3 ; i++ )
- {
- m_partiRank[i] = m_particule->CreateRay(pos, goal,
- PARTIRAY2,
- Math::Point(2.9f, 2.9f),
- LABO_DELAY);
- }
-
- m_soundChannel = m_sound->Play(SOUND_LABO, m_object->RetPosition(0), 0.0f, 0.25f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.60f, 2.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.00f, 8.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.60f, 8.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.25f, 2.0f, SOPER_STOP);
-
- pos = m_object->RetPosition(0);
- pos.y += 4.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 4.0f;
- dim.y = dim.x;
- m_partiSphere = m_particule->CreateParticule(pos, speed, dim, PARTISPHERE2, LABO_DELAY, 0.0f, 0.0f);
-
- m_phase = ALAP_ANALYSE;
- m_progress = 0.0f;
- m_speed = 1.0f/LABO_DELAY;
- }
- }
-
- if ( m_phase == ALAP_ANALYSE )
- {
- if ( m_progress < 1.0f )
- {
- power = m_object->RetPower();
- if ( power != 0 )
- {
- power->SetZoom(0, 1.0f-m_progress);
- }
-
- angle = m_object->RetAngleY(2);
- if ( m_progress < 0.5f )
- {
- angle -= event.rTime*m_progress*20.0f;
- }
- else
- {
- angle -= event.rTime*(20.0f-m_progress*20.0f);
- }
- m_object->SetAngleY(2, angle); // rotates the analyzer
-
- angle += m_object->RetAngleY(0);
- for ( i=0 ; i<3 ; i++ )
- {
- rot = Math::RotatePoint(-angle, -4.0f);
- pos = m_object->RetPosition(0);
- pos.x += rot.x;
- pos.z += rot.y;
- pos.y += 3.0f+4.0f;;
- m_particule->SetPosition(m_partiRank[i], pos); // adjusts ray
-
- angle += Math::PI*2.0f/3.0f;
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- if ( m_progress > 0.25f &&
- m_progress < 0.80f )
- {
- pos = m_object->RetPosition(0);
- pos.y += 3.0f;
- pos.x += (Math::Rand()-0.5f)*2.0f;
- pos.z += (Math::Rand()-0.5f)*2.0f;
- speed.y = Math::Rand()*5.0f+5.0f;
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- dim.x = Math::Rand()*0.4f*m_progress+1.0f;
- dim.y = dim.x;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK2,
- 2.0f+2.0f*m_progress, 10.0f, 1.5f, 1.4f);
- }
- }
- }
- else
- {
- SetResearch(m_research); // research done
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- m_object->SetPower(0);
- power->DeleteObject(); // destroys the ball
- delete power;
- }
-
- m_displayText->DisplayError(INFO_LABO, m_object);
-
- SoundManip(1.5f, 1.0f, 0.5f);
- m_phase = ALAP_CLOSE1;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
-
- if ( m_phase == ALAP_CLOSE1 )
- {
- if ( m_progress < 1.0f )
- {
- angle = m_progress*Math::PI/2.0f;
- m_object->SetAngleZ(1, angle);
- }
- else
- {
- m_object->SetAngleZ(1, Math::PI/2.0f);
-
- SoundManip(1.5f, 1.0f, 0.7f);
- m_phase = ALAP_CLOSE2;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
-
- if ( m_phase == ALAP_CLOSE2 )
- {
- if ( m_progress < 1.0f )
- {
- pos.x = -9.0f;
- pos.y = 3.0f+(1.0f-m_progress)*10.0f;;
- pos.z = 0.0f;
- m_object->SetPosition(1, pos);
- }
- else
- {
- m_object->SetPosition(1, Math::Vector(-9.0f, 3.0f, 0.0f));
-
- SoundManip(1.0f, 1.0f, 1.0f);
- m_phase = ALAP_CLOSE3;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ALAP_CLOSE3 )
- {
- if ( m_progress < 1.0f )
- {
- angle = 45.0f+(35.0f*m_progress);
- m_object->SetAngleZ(3, angle*Math::PI/180.0f);
- m_object->SetAngleZ(4, angle*Math::PI/180.0f);
- m_object->SetAngleZ(5, angle*Math::PI/180.0f);
- }
- else
- {
- m_object->SetAngleZ(3, 80.0f*Math::PI/180.0f);
- m_object->SetAngleZ(4, 80.0f*Math::PI/180.0f);
- m_object->SetAngleZ(5, 80.0f*Math::PI/180.0f);
-
- SetBusy(false);
- UpdateInterface();
-
- m_phase = ALAP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoLabo::RetError()
-{
- CObject* pObj;
- ObjectType type;
-
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- pObj = m_object->RetPower();
- if ( pObj == 0 ) return ERR_LABO_NULL;
- type = pObj->RetType();
- if ( type != OBJECT_BULLET ) return ERR_LABO_BAD;
-
- return ERR_OK;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoLabo::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, dim, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- dim.x = 33.0f/640.0f;
- dim.y = 33.0f/480.0f;
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*7.0f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 64+45, EVENT_OBJECT_RiPAW);
-
- pos.x = ox+sx*8.0f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 64+46, EVENT_OBJECT_RiGUN);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 111, EVENT_OBJECT_TYPE);
-
- UpdateInterface();
-
- return true;
-}
-
-// Updates the status of all interface buttons.
-
-void CAutoLabo::UpdateInterface()
-{
- CWindow* pw;
-
- if ( !m_object->RetSelect() ) return;
-
- CAuto::UpdateInterface();
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- DeadInterface(pw, EVENT_OBJECT_RiPAW, g_researchEnable&RESEARCH_iPAW);
- DeadInterface(pw, EVENT_OBJECT_RiGUN, g_researchEnable&RESEARCH_iGUN);
-
- OkayButton(pw, EVENT_OBJECT_RiPAW);
- OkayButton(pw, EVENT_OBJECT_RiGUN);
-
- VisibleInterface(pw, EVENT_OBJECT_RiPAW, !m_bBusy);
- VisibleInterface(pw, EVENT_OBJECT_RiGUN, !m_bBusy);
-}
-
-// Indicates the research conducted for a button.
-
-void CAutoLabo::OkayButton(CWindow *pw, EventMsg event)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_OKAY, TestResearch(event));
-}
-
-
-// Test whether a search has already been done.
-
-bool CAutoLabo::TestResearch(EventMsg event)
-{
- if ( event == EVENT_OBJECT_RiPAW ) return (g_researchDone & RESEARCH_iPAW);
- if ( event == EVENT_OBJECT_RiGUN ) return (g_researchDone & RESEARCH_iGUN);
-
- return false;
-}
-
-// Indicates a search as made.
-
-void CAutoLabo::SetResearch(EventMsg event)
-{
- Event newEvent;
-
- if ( event == EVENT_OBJECT_RiPAW ) g_researchDone |= RESEARCH_iPAW;
- if ( event == EVENT_OBJECT_RiGUN ) g_researchDone |= RESEARCH_iGUN;
-
- m_main->WriteFreeParam();
-
- m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
- m_event->AddEvent(newEvent);
- UpdateInterface();
-}
-
-// Plays the sound of the manipulator arm.
-
-void CAutoLabo::SoundManip(float time, float amplitude, float frequency)
-{
- int i;
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoLabo::Write(char *line)
-{
- Math::Vector pos;
- char name[100];
-
- if ( m_phase == ALAP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- sprintf(name, " aResearch=%d", m_research);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoLabo::Read(char *line)
-{
- Math::Vector pos;
-
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoLaboPhase)OpInt(line, "aPhase", ALAP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
- m_research = (EventMsg)OpInt(line, "aResearch", 0);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autolabo.h"
+
+#include "common/global.h"
+#include "common/misc.h"
+#include "math/geometry.h"
+#include "object/robotmain.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+
+
+
+const float LABO_DELAY = 20.0f; // duration of the analysis
+
+
+
+
+// Object's constructor.
+
+CAutoLabo::CAutoLabo(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ int i;
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ m_partiRank[i] = -1;
+ }
+ m_partiSphere = -1;
+
+ m_soundChannel = -1;
+ Init();
+}
+
+// Object's destructor.
+
+CAutoLabo::~CAutoLabo()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoLabo::DeleteObject(bool bAll)
+{
+ int i;
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ if ( m_partiRank[i] != -1 )
+ {
+ m_particule->DeleteParticule(m_partiRank[i]);
+ m_partiRank[i] = -1;
+ }
+ }
+
+ if ( m_partiSphere != -1 )
+ {
+ m_particule->DeleteParticule(m_partiSphere);
+ m_partiSphere = -1;
+ }
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoLabo::Init()
+{
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+
+ m_phase = ALAP_WAIT; // waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoLabo::EventProcess(const Event &event)
+{
+ CObject* power;
+ Math::Vector pos, goal, speed;
+ Math::Point dim, rot;
+ float angle;
+ int i;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+
+ if ( event.event == EVENT_UPDINTERFACE )
+ {
+ if ( m_object->RetSelect() ) CreateInterface(true);
+ }
+
+ if ( m_object->RetSelect() && // center selected?
+ (event.event == EVENT_OBJECT_RiPAW ||
+ event.event == EVENT_OBJECT_RiGUN) )
+ {
+ if ( m_phase != ALAP_WAIT )
+ {
+ return false;
+ }
+
+ m_research = event.event;
+
+ if ( TestResearch(m_research) )
+ {
+ m_displayText->DisplayError(ERR_LABO_ALREADY, m_object);
+ return false;
+ }
+
+ power = m_object->RetPower();
+ if ( power == 0 )
+ {
+ m_displayText->DisplayError(ERR_LABO_NULL, m_object);
+ return false;
+ }
+ if ( power->RetType() != OBJECT_BULLET )
+ {
+ m_displayText->DisplayError(ERR_LABO_BAD, m_object);
+ return false;
+ }
+
+ SetBusy(true);
+ InitProgressTotal(1.0f+1.5f+1.5f+LABO_DELAY+1.5f+1.5f+1.0f);
+ UpdateInterface();
+
+ power->SetLock(true); // ball longer usable
+
+ SoundManip(1.0f, 1.0f, 1.0f);
+ m_phase = ALAP_OPEN1;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ return true;
+ }
+
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+ }
+ return true;
+ }
+
+ EventProgress(event.rTime);
+
+ if ( m_phase == ALAP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_phase = ALAP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == ALAP_OPEN1 )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = 80.0f-(35.0f*m_progress);
+ m_object->SetAngleZ(3, angle*Math::PI/180.0f);
+ m_object->SetAngleZ(4, angle*Math::PI/180.0f);
+ m_object->SetAngleZ(5, angle*Math::PI/180.0f);
+ }
+ else
+ {
+ m_object->SetAngleZ(3, 45.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(4, 45.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(5, 45.0f*Math::PI/180.0f);
+
+ SoundManip(1.5f, 1.0f, 0.7f);
+ m_phase = ALAP_OPEN2;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+
+ if ( m_phase == ALAP_OPEN2 )
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos.x = -9.0f;
+ pos.y = 3.0f+m_progress*10.0f;
+ pos.z = 0.0f;
+ m_object->SetPosition(1, pos);
+ }
+ else
+ {
+ m_object->SetPosition(1, Math::Vector(-9.0f, 13.0f, 0.0f));
+
+ SoundManip(1.5f, 1.0f, 0.5f);
+ m_phase = ALAP_OPEN3;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+
+ if ( m_phase == ALAP_OPEN3 )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = (1.0f-m_progress)*Math::PI/2.0f;
+ m_object->SetAngleZ(1, angle);
+ }
+ else
+ {
+ m_object->SetAngleZ(1, 0.0f);
+
+ goal = m_object->RetPosition(0);
+ goal.y += 3.0f;
+ pos = goal;
+ pos.x -= 4.0f;
+ pos.y += 4.0f;
+ for ( i=0 ; i<3 ; i++ )
+ {
+ m_partiRank[i] = m_particule->CreateRay(pos, goal,
+ PARTIRAY2,
+ Math::Point(2.9f, 2.9f),
+ LABO_DELAY);
+ }
+
+ m_soundChannel = m_sound->Play(SOUND_LABO, m_object->RetPosition(0), 0.0f, 0.25f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.60f, 2.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.00f, 8.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.60f, 8.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.25f, 2.0f, SOPER_STOP);
+
+ pos = m_object->RetPosition(0);
+ pos.y += 4.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 4.0f;
+ dim.y = dim.x;
+ m_partiSphere = m_particule->CreateParticule(pos, speed, dim, PARTISPHERE2, LABO_DELAY, 0.0f, 0.0f);
+
+ m_phase = ALAP_ANALYSE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/LABO_DELAY;
+ }
+ }
+
+ if ( m_phase == ALAP_ANALYSE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ power->SetZoom(0, 1.0f-m_progress);
+ }
+
+ angle = m_object->RetAngleY(2);
+ if ( m_progress < 0.5f )
+ {
+ angle -= event.rTime*m_progress*20.0f;
+ }
+ else
+ {
+ angle -= event.rTime*(20.0f-m_progress*20.0f);
+ }
+ m_object->SetAngleY(2, angle); // rotates the analyzer
+
+ angle += m_object->RetAngleY(0);
+ for ( i=0 ; i<3 ; i++ )
+ {
+ rot = Math::RotatePoint(-angle, -4.0f);
+ pos = m_object->RetPosition(0);
+ pos.x += rot.x;
+ pos.z += rot.y;
+ pos.y += 3.0f+4.0f;;
+ m_particule->SetPosition(m_partiRank[i], pos); // adjusts ray
+
+ angle += Math::PI*2.0f/3.0f;
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ if ( m_progress > 0.25f &&
+ m_progress < 0.80f )
+ {
+ pos = m_object->RetPosition(0);
+ pos.y += 3.0f;
+ pos.x += (Math::Rand()-0.5f)*2.0f;
+ pos.z += (Math::Rand()-0.5f)*2.0f;
+ speed.y = Math::Rand()*5.0f+5.0f;
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ dim.x = Math::Rand()*0.4f*m_progress+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK2,
+ 2.0f+2.0f*m_progress, 10.0f, 1.5f, 1.4f);
+ }
+ }
+ }
+ else
+ {
+ SetResearch(m_research); // research done
+
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ m_object->SetPower(0);
+ power->DeleteObject(); // destroys the ball
+ delete power;
+ }
+
+ m_displayText->DisplayError(INFO_LABO, m_object);
+
+ SoundManip(1.5f, 1.0f, 0.5f);
+ m_phase = ALAP_CLOSE1;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+
+ if ( m_phase == ALAP_CLOSE1 )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = m_progress*Math::PI/2.0f;
+ m_object->SetAngleZ(1, angle);
+ }
+ else
+ {
+ m_object->SetAngleZ(1, Math::PI/2.0f);
+
+ SoundManip(1.5f, 1.0f, 0.7f);
+ m_phase = ALAP_CLOSE2;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+
+ if ( m_phase == ALAP_CLOSE2 )
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos.x = -9.0f;
+ pos.y = 3.0f+(1.0f-m_progress)*10.0f;;
+ pos.z = 0.0f;
+ m_object->SetPosition(1, pos);
+ }
+ else
+ {
+ m_object->SetPosition(1, Math::Vector(-9.0f, 3.0f, 0.0f));
+
+ SoundManip(1.0f, 1.0f, 1.0f);
+ m_phase = ALAP_CLOSE3;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ALAP_CLOSE3 )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = 45.0f+(35.0f*m_progress);
+ m_object->SetAngleZ(3, angle*Math::PI/180.0f);
+ m_object->SetAngleZ(4, angle*Math::PI/180.0f);
+ m_object->SetAngleZ(5, angle*Math::PI/180.0f);
+ }
+ else
+ {
+ m_object->SetAngleZ(3, 80.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(4, 80.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(5, 80.0f*Math::PI/180.0f);
+
+ SetBusy(false);
+ UpdateInterface();
+
+ m_phase = ALAP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoLabo::RetError()
+{
+ CObject* pObj;
+ ObjectType type;
+
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ pObj = m_object->RetPower();
+ if ( pObj == 0 ) return ERR_LABO_NULL;
+ type = pObj->RetType();
+ if ( type != OBJECT_BULLET ) return ERR_LABO_BAD;
+
+ return ERR_OK;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoLabo::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, dim, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ dim.x = 33.0f/640.0f;
+ dim.y = 33.0f/480.0f;
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*7.0f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 64+45, EVENT_OBJECT_RiPAW);
+
+ pos.x = ox+sx*8.0f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 64+46, EVENT_OBJECT_RiGUN);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 111, EVENT_OBJECT_TYPE);
+
+ UpdateInterface();
+
+ return true;
+}
+
+// Updates the status of all interface buttons.
+
+void CAutoLabo::UpdateInterface()
+{
+ CWindow* pw;
+
+ if ( !m_object->RetSelect() ) return;
+
+ CAuto::UpdateInterface();
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ DeadInterface(pw, EVENT_OBJECT_RiPAW, g_researchEnable&RESEARCH_iPAW);
+ DeadInterface(pw, EVENT_OBJECT_RiGUN, g_researchEnable&RESEARCH_iGUN);
+
+ OkayButton(pw, EVENT_OBJECT_RiPAW);
+ OkayButton(pw, EVENT_OBJECT_RiGUN);
+
+ VisibleInterface(pw, EVENT_OBJECT_RiPAW, !m_bBusy);
+ VisibleInterface(pw, EVENT_OBJECT_RiGUN, !m_bBusy);
+}
+
+// Indicates the research conducted for a button.
+
+void CAutoLabo::OkayButton(CWindow *pw, EventMsg event)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_OKAY, TestResearch(event));
+}
+
+
+// Test whether a search has already been done.
+
+bool CAutoLabo::TestResearch(EventMsg event)
+{
+ if ( event == EVENT_OBJECT_RiPAW ) return (g_researchDone & RESEARCH_iPAW);
+ if ( event == EVENT_OBJECT_RiGUN ) return (g_researchDone & RESEARCH_iGUN);
+
+ return false;
+}
+
+// Indicates a search as made.
+
+void CAutoLabo::SetResearch(EventMsg event)
+{
+ Event newEvent;
+
+ if ( event == EVENT_OBJECT_RiPAW ) g_researchDone |= RESEARCH_iPAW;
+ if ( event == EVENT_OBJECT_RiGUN ) g_researchDone |= RESEARCH_iGUN;
+
+ m_main->WriteFreeParam();
+
+ m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
+ m_event->AddEvent(newEvent);
+ UpdateInterface();
+}
+
+// Plays the sound of the manipulator arm.
+
+void CAutoLabo::SoundManip(float time, float amplitude, float frequency)
+{
+ int i;
+
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
+ m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoLabo::Write(char *line)
+{
+ Math::Vector pos;
+ char name[100];
+
+ if ( m_phase == ALAP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ sprintf(name, " aResearch=%d", m_research);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoLabo::Read(char *line)
+{
+ Math::Vector pos;
+
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoLaboPhase)OpInt(line, "aPhase", ALAP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+ m_research = (EventMsg)OpInt(line, "aResearch", 0);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autolabo.h b/src/object/auto/autolabo.h
index d94eb9e..244e633 100644
--- a/src/object/auto/autolabo.h
+++ b/src/object/auto/autolabo.h
@@ -1,75 +1,75 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autolabo.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoLaboPhase
-{
- ALAP_WAIT = 1,
- ALAP_OPEN1 = 2,
- ALAP_OPEN2 = 3,
- ALAP_OPEN3 = 4,
- ALAP_ANALYSE = 5,
- ALAP_CLOSE1 = 6,
- ALAP_CLOSE2 = 7,
- ALAP_CLOSE3 = 8,
-};
-
-
-
-class CAutoLabo : public CAuto
-{
-public:
- CAutoLabo(CInstanceManager* iMan, CObject* object);
- ~CAutoLabo();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- void UpdateInterface();
- void OkayButton(CWindow *pw, EventMsg event);
- bool TestResearch(EventMsg event);
- void SetResearch(EventMsg event);
- void SoundManip(float time, float amplitude, float frequency);
-
-protected:
- AutoLaboPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
- EventMsg m_research;
- int m_partiRank[3];
- int m_partiSphere;
- int m_soundChannel;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autolabo.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoLaboPhase
+{
+ ALAP_WAIT = 1,
+ ALAP_OPEN1 = 2,
+ ALAP_OPEN2 = 3,
+ ALAP_OPEN3 = 4,
+ ALAP_ANALYSE = 5,
+ ALAP_CLOSE1 = 6,
+ ALAP_CLOSE2 = 7,
+ ALAP_CLOSE3 = 8,
+};
+
+
+
+class CAutoLabo : public CAuto
+{
+public:
+ CAutoLabo(CInstanceManager* iMan, CObject* object);
+ ~CAutoLabo();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ void UpdateInterface();
+ void OkayButton(CWindow *pw, EventMsg event);
+ bool TestResearch(EventMsg event);
+ void SetResearch(EventMsg event);
+ void SoundManip(float time, float amplitude, float frequency);
+
+protected:
+ AutoLaboPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+ EventMsg m_research;
+ int m_partiRank[3];
+ int m_partiSphere;
+ int m_soundChannel;
+};
+
diff --git a/src/object/auto/automush.cpp b/src/object/auto/automush.cpp
index 366dbb5..c3eaaaf 100644
--- a/src/object/auto/automush.cpp
+++ b/src/object/auto/automush.cpp
@@ -1,344 +1,344 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/automush.h"
-
-#include "common/iman.h"
-#include "script/cmdtoken.h"
-
-
-
-
-// Object's constructor.
-
-CAutoMush::CAutoMush(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
-}
-
-// Object's destructor.
-
-CAutoMush::~CAutoMush()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoMush::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoMush::Init()
-{
- m_phase = AMP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/4.0f;
-
- m_time = 0.0f;
- m_lastParticule = 0.0f;
-}
-
-
-// Management of an event.
-
-bool CAutoMush::EventProcess(const Event &event)
-{
- Math::Vector pos, speed, dir;
- Math::Point dim;
- float factor, zoom, size, angle;
- int i, channel;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
-
- factor = 0.0f;
- size = 1.0f;
-
- if ( m_phase == AMP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- if ( !SearchTarget() )
- {
- m_phase = AMP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/(2.0f+Math::Rand()*2.0f);
- }
- else
- {
- m_phase = AMP_SNIF;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
- }
-
- if ( m_phase == AMP_SNIF )
- {
- if ( m_progress < 1.0f )
- {
- factor = m_progress;
- }
- else
- {
- m_phase = AMP_ZOOM;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == AMP_ZOOM )
- {
- if ( m_progress < 1.0f )
- {
- factor = 1.0f;
- size = 1.0f+m_progress*0.3f;
- }
- else
- {
- m_sound->Play(SOUND_MUSHROOM, m_object->RetPosition(0));
-
- m_phase = AMP_FIRE;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == AMP_FIRE )
- {
- if ( m_progress < 1.0f )
- {
- factor = 1.0f-m_progress;
- size = 1.0f+(1.0f-m_progress)*0.3f;
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- for ( i=0 ; i<10 ; i++ )
- {
- pos = m_object->RetPosition(0);
- pos.y += 5.0f;
- speed.x = (Math::Rand()-0.5f)*200.0f;
- speed.z = (Math::Rand()-0.5f)*200.0f;
- speed.y = -(20.0f+Math::Rand()*20.0f);
- dim.x = 1.0f;
- dim.y = dim.x;
- channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN2, 2.0f, 100.0f, 0.0f);
- m_particule->SetObjectFather(channel, m_object);
- }
- }
- }
- else
- {
- m_phase = AMP_SMOKE;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == AMP_SMOKE )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.y += 5.0f;
- speed.x = (Math::Rand()-0.5f)*4.0f;
- speed.z = (Math::Rand()-0.5f)*4.0f;
- speed.y = -(0.5f+Math::Rand()*0.5f);
- dim.x = Math::Rand()*2.5f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 0.0f);
- }
- }
- else
- {
- m_phase = AMP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/(2.0f+Math::Rand()*2.0f);
- }
- }
-
- if ( factor != 0.0f || size != 1.0f )
- {
- dir.x = sinf(m_time*Math::PI*4.0f);
- dir.z = cosf(m_time*Math::PI*4.0f);
-
- angle = sinf(m_time*10.0f)*factor*0.04f;
- m_object->SetAngleX(0, angle*dir.z);
- m_object->SetAngleZ(0, angle*dir.x);
-
- zoom = 1.0f+sinf(m_time*8.0f)*factor*0.06f;
- m_object->SetZoomX(0, zoom*size);
- zoom = 1.0f+sinf(m_time*5.0f)*factor*0.06f;
- m_object->SetZoomY(0, zoom*size);
- zoom = 1.0f+sinf(m_time*7.0f)*factor*0.06f;
- m_object->SetZoomZ(0, zoom*size);
- }
- else
- {
- m_object->SetAngleX(0, 0.0f);
- m_object->SetAngleZ(0, 0.0f);
- m_object->SetZoom(0, Math::Vector(1.0f, 1.0f, 1.0f));
- }
-
- return true;
-}
-
-
-// Seeking a nearby target.
-
-bool CAutoMush::SearchTarget()
-{
- CObject* pObj;
- Math::Vector iPos, oPos;
- ObjectType type;
- float dist;
- int i;
-
- iPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetLock() ) continue;
-
- type = pObj->RetType();
- if ( type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr &&
- type != OBJECT_DERRICK &&
- type != OBJECT_STATION &&
- type != OBJECT_FACTORY &&
- type != OBJECT_REPAIR &&
- type != OBJECT_DESTROYER&&
- type != OBJECT_CONVERT &&
- type != OBJECT_TOWER &&
- type != OBJECT_RESEARCH &&
- type != OBJECT_RADAR &&
- type != OBJECT_INFO &&
- type != OBJECT_ENERGY &&
- type != OBJECT_LABO &&
- type != OBJECT_NUCLEAR &&
- type != OBJECT_PARA &&
- type != OBJECT_HUMAN ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, iPos);
- if ( dist < 50.0f ) return true;
- }
-
- return false;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoMush::RetError()
-{
- return ERR_OK;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoMush::Write(char *line)
-{
- Math::Vector pos;
- char name[100];
-
- if ( m_phase == AMP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoMush::Read(char *line)
-{
- Math::Vector pos;
-
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoMushPhase)OpInt(line, "aPhase", AMP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/automush.h"
+
+#include "common/iman.h"
+#include "script/cmdtoken.h"
+
+
+
+
+// Object's constructor.
+
+CAutoMush::CAutoMush(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+}
+
+// Object's destructor.
+
+CAutoMush::~CAutoMush()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoMush::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoMush::Init()
+{
+ m_phase = AMP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/4.0f;
+
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+}
+
+
+// Management of an event.
+
+bool CAutoMush::EventProcess(const Event &event)
+{
+ Math::Vector pos, speed, dir;
+ Math::Point dim;
+ float factor, zoom, size, angle;
+ int i, channel;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+
+ factor = 0.0f;
+ size = 1.0f;
+
+ if ( m_phase == AMP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ if ( !SearchTarget() )
+ {
+ m_phase = AMP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/(2.0f+Math::Rand()*2.0f);
+ }
+ else
+ {
+ m_phase = AMP_SNIF;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+ }
+
+ if ( m_phase == AMP_SNIF )
+ {
+ if ( m_progress < 1.0f )
+ {
+ factor = m_progress;
+ }
+ else
+ {
+ m_phase = AMP_ZOOM;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == AMP_ZOOM )
+ {
+ if ( m_progress < 1.0f )
+ {
+ factor = 1.0f;
+ size = 1.0f+m_progress*0.3f;
+ }
+ else
+ {
+ m_sound->Play(SOUND_MUSHROOM, m_object->RetPosition(0));
+
+ m_phase = AMP_FIRE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == AMP_FIRE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ factor = 1.0f-m_progress;
+ size = 1.0f+(1.0f-m_progress)*0.3f;
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ pos = m_object->RetPosition(0);
+ pos.y += 5.0f;
+ speed.x = (Math::Rand()-0.5f)*200.0f;
+ speed.z = (Math::Rand()-0.5f)*200.0f;
+ speed.y = -(20.0f+Math::Rand()*20.0f);
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN2, 2.0f, 100.0f, 0.0f);
+ m_particule->SetObjectFather(channel, m_object);
+ }
+ }
+ }
+ else
+ {
+ m_phase = AMP_SMOKE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == AMP_SMOKE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.y += 5.0f;
+ speed.x = (Math::Rand()-0.5f)*4.0f;
+ speed.z = (Math::Rand()-0.5f)*4.0f;
+ speed.y = -(0.5f+Math::Rand()*0.5f);
+ dim.x = Math::Rand()*2.5f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 0.0f);
+ }
+ }
+ else
+ {
+ m_phase = AMP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/(2.0f+Math::Rand()*2.0f);
+ }
+ }
+
+ if ( factor != 0.0f || size != 1.0f )
+ {
+ dir.x = sinf(m_time*Math::PI*4.0f);
+ dir.z = cosf(m_time*Math::PI*4.0f);
+
+ angle = sinf(m_time*10.0f)*factor*0.04f;
+ m_object->SetAngleX(0, angle*dir.z);
+ m_object->SetAngleZ(0, angle*dir.x);
+
+ zoom = 1.0f+sinf(m_time*8.0f)*factor*0.06f;
+ m_object->SetZoomX(0, zoom*size);
+ zoom = 1.0f+sinf(m_time*5.0f)*factor*0.06f;
+ m_object->SetZoomY(0, zoom*size);
+ zoom = 1.0f+sinf(m_time*7.0f)*factor*0.06f;
+ m_object->SetZoomZ(0, zoom*size);
+ }
+ else
+ {
+ m_object->SetAngleX(0, 0.0f);
+ m_object->SetAngleZ(0, 0.0f);
+ m_object->SetZoom(0, Math::Vector(1.0f, 1.0f, 1.0f));
+ }
+
+ return true;
+}
+
+
+// Seeking a nearby target.
+
+bool CAutoMush::SearchTarget()
+{
+ CObject* pObj;
+ Math::Vector iPos, oPos;
+ ObjectType type;
+ float dist;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetLock() ) continue;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis &&
+ type != OBJECT_MOBILErt &&
+ type != OBJECT_MOBILErc &&
+ type != OBJECT_MOBILErr &&
+ type != OBJECT_MOBILErs &&
+ type != OBJECT_MOBILEsa &&
+ type != OBJECT_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_MOBILEdr &&
+ type != OBJECT_DERRICK &&
+ type != OBJECT_STATION &&
+ type != OBJECT_FACTORY &&
+ type != OBJECT_REPAIR &&
+ type != OBJECT_DESTROYER&&
+ type != OBJECT_CONVERT &&
+ type != OBJECT_TOWER &&
+ type != OBJECT_RESEARCH &&
+ type != OBJECT_RADAR &&
+ type != OBJECT_INFO &&
+ type != OBJECT_ENERGY &&
+ type != OBJECT_LABO &&
+ type != OBJECT_NUCLEAR &&
+ type != OBJECT_PARA &&
+ type != OBJECT_HUMAN ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, iPos);
+ if ( dist < 50.0f ) return true;
+ }
+
+ return false;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoMush::RetError()
+{
+ return ERR_OK;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoMush::Write(char *line)
+{
+ Math::Vector pos;
+ char name[100];
+
+ if ( m_phase == AMP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoMush::Read(char *line)
+{
+ Math::Vector pos;
+
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoMushPhase)OpInt(line, "aPhase", AMP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/automush.h b/src/object/auto/automush.h
index 5c8d62d..113d22f 100644
--- a/src/object/auto/automush.h
+++ b/src/object/auto/automush.h
@@ -1,61 +1,61 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// automush.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoMushPhase
-{
- AMP_WAIT = 1,
- AMP_SNIF = 2,
- AMP_ZOOM = 3,
- AMP_FIRE = 4,
- AMP_SMOKE = 5,
-};
-
-
-
-class CAutoMush : public CAuto
-{
-public:
- CAutoMush(CInstanceManager* iMan, CObject* object);
- ~CAutoMush();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- bool SearchTarget();
-
-protected:
- AutoMushPhase m_phase;
- float m_progress;
- float m_speed;
- float m_lastParticule;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// automush.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoMushPhase
+{
+ AMP_WAIT = 1,
+ AMP_SNIF = 2,
+ AMP_ZOOM = 3,
+ AMP_FIRE = 4,
+ AMP_SMOKE = 5,
+};
+
+
+
+class CAutoMush : public CAuto
+{
+public:
+ CAutoMush(CInstanceManager* iMan, CObject* object);
+ ~CAutoMush();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ bool SearchTarget();
+
+protected:
+ AutoMushPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_lastParticule;
+};
+
diff --git a/src/object/auto/autonest.cpp b/src/object/auto/autonest.cpp
index a1fdf67..f3c70fb 100644
--- a/src/object/auto/autonest.cpp
+++ b/src/object/auto/autonest.cpp
@@ -1,275 +1,275 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autonest.h"
-
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "script/cmdtoken.h"
-
-
-
-
-// Object's constructor.
-
-CAutoNest::CAutoNest(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
-}
-
-// Object's destructor.
-
-CAutoNest::~CAutoNest()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoNest::DeleteObject(bool bAll)
-{
- CObject* fret;
-
- if ( !bAll )
- {
- fret = SearchFret();
- if ( fret != 0 )
- {
- fret->DeleteObject();
- delete fret;
- }
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoNest::Init()
-{
- Math::Vector pos;
-
- m_phase = ANP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/4.0f;
-
- m_time = 0.0f;
- m_lastParticule = 0.0f;
-
- pos = m_object->RetPosition(0);
- m_terrain->MoveOnFloor(pos);
- m_fretPos = pos;
-}
-
-
-// Management of an event.
-
-bool CAutoNest::EventProcess(const Event &event)
-{
- CObject* fret;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
-
- if ( m_phase == ANP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- if ( !SearchFree(m_fretPos) )
- {
- m_phase = ANP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/4.0f;
- }
- else
- {
- CreateFret(m_fretPos, 0.0f, OBJECT_BULLET);
- m_phase = ANP_BIRTH;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- }
- }
- }
-
- if ( m_phase == ANP_BIRTH )
- {
- fret = SearchFret();
-
- if ( m_progress < 1.0f )
- {
- if ( fret != 0 )
- {
- fret->SetZoom(0, m_progress);
- }
- }
- else
- {
- if ( fret != 0 )
- {
- fret->SetZoom(0, 1.0f);
- fret->SetLock(false);
- }
-
- m_phase = ANP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- }
- }
-
- return true;
-}
-
-
-// Seeks if a site is free.
-
-bool CAutoNest::SearchFree(Math::Vector pos)
-{
- CObject* pObj;
- Math::Vector sPos;
- ObjectType type;
- float sRadius, distance;
- int i, j;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_NEST ) continue;
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, sPos, sRadius) )
- {
- distance = Math::Distance(sPos, pos);
- distance -= sRadius;
- if ( distance < 2.0f ) return false; // location occupied
- }
- }
-
- return true; // free location
-}
-
-// Create a transportable object.
-
-void CAutoNest::CreateFret(Math::Vector pos, float angle, ObjectType type)
-{
- CObject* fret;
-
- fret = new CObject(m_iMan);
- if ( !fret->CreateResource(pos, angle, type) )
- {
- delete fret;
- return;
- }
- fret->SetLock(true); // not usable
- fret->SetZoom(0, 0.0f);
-}
-
-// Looking for the ball during manufacture.
-
-CObject* CAutoNest::SearchFret()
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetLock() ) continue;
-
- type = pObj->RetType();
- if ( type != OBJECT_BULLET ) continue;
-
- oPos = pObj->RetPosition(0);
- if ( oPos.x == m_fretPos.x &&
- oPos.z == m_fretPos.z )
- {
- return pObj;
- }
- }
-
- return 0;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoNest::RetError()
-{
- return ERR_OK;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoNest::Write(char *line)
-{
- Math::Vector pos;
- char name[100];
-
- if ( m_phase == ANP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoNest::Read(char *line)
-{
- Math::Vector pos;
-
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoNestPhase)OpInt(line, "aPhase", ANP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autonest.h"
+
+#include "common/iman.h"
+#include "old/terrain.h"
+#include "script/cmdtoken.h"
+
+
+
+
+// Object's constructor.
+
+CAutoNest::CAutoNest(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+}
+
+// Object's destructor.
+
+CAutoNest::~CAutoNest()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoNest::DeleteObject(bool bAll)
+{
+ CObject* fret;
+
+ if ( !bAll )
+ {
+ fret = SearchFret();
+ if ( fret != 0 )
+ {
+ fret->DeleteObject();
+ delete fret;
+ }
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoNest::Init()
+{
+ Math::Vector pos;
+
+ m_phase = ANP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/4.0f;
+
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+
+ pos = m_object->RetPosition(0);
+ m_terrain->MoveOnFloor(pos);
+ m_fretPos = pos;
+}
+
+
+// Management of an event.
+
+bool CAutoNest::EventProcess(const Event &event)
+{
+ CObject* fret;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+
+ if ( m_phase == ANP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ if ( !SearchFree(m_fretPos) )
+ {
+ m_phase = ANP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/4.0f;
+ }
+ else
+ {
+ CreateFret(m_fretPos, 0.0f, OBJECT_BULLET);
+ m_phase = ANP_BIRTH;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ }
+ }
+ }
+
+ if ( m_phase == ANP_BIRTH )
+ {
+ fret = SearchFret();
+
+ if ( m_progress < 1.0f )
+ {
+ if ( fret != 0 )
+ {
+ fret->SetZoom(0, m_progress);
+ }
+ }
+ else
+ {
+ if ( fret != 0 )
+ {
+ fret->SetZoom(0, 1.0f);
+ fret->SetLock(false);
+ }
+
+ m_phase = ANP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ }
+ }
+
+ return true;
+}
+
+
+// Seeks if a site is free.
+
+bool CAutoNest::SearchFree(Math::Vector pos)
+{
+ CObject* pObj;
+ Math::Vector sPos;
+ ObjectType type;
+ float sRadius, distance;
+ int i, j;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_NEST ) continue;
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, sPos, sRadius) )
+ {
+ distance = Math::Distance(sPos, pos);
+ distance -= sRadius;
+ if ( distance < 2.0f ) return false; // location occupied
+ }
+ }
+
+ return true; // free location
+}
+
+// Create a transportable object.
+
+void CAutoNest::CreateFret(Math::Vector pos, float angle, ObjectType type)
+{
+ CObject* fret;
+
+ fret = new CObject(m_iMan);
+ if ( !fret->CreateResource(pos, angle, type) )
+ {
+ delete fret;
+ return;
+ }
+ fret->SetLock(true); // not usable
+ fret->SetZoom(0, 0.0f);
+}
+
+// Looking for the ball during manufacture.
+
+CObject* CAutoNest::SearchFret()
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ ObjectType type;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetLock() ) continue;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_BULLET ) continue;
+
+ oPos = pObj->RetPosition(0);
+ if ( oPos.x == m_fretPos.x &&
+ oPos.z == m_fretPos.z )
+ {
+ return pObj;
+ }
+ }
+
+ return 0;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoNest::RetError()
+{
+ return ERR_OK;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoNest::Write(char *line)
+{
+ Math::Vector pos;
+ char name[100];
+
+ if ( m_phase == ANP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoNest::Read(char *line)
+{
+ Math::Vector pos;
+
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoNestPhase)OpInt(line, "aPhase", ANP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autonest.h b/src/object/auto/autonest.h
index e697a3b..612551d 100644
--- a/src/object/auto/autonest.h
+++ b/src/object/auto/autonest.h
@@ -1,61 +1,61 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autonest.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoNestPhase
-{
- ANP_WAIT = 1,
- ANP_BIRTH = 2, // appearance of a ball
-};
-
-
-
-class CAutoNest : public CAuto
-{
-public:
- CAutoNest(CInstanceManager* iMan, CObject* object);
- ~CAutoNest();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- bool SearchFree(Math::Vector pos);
- void CreateFret(Math::Vector pos, float angle, ObjectType type);
- CObject* SearchFret();
-
-protected:
- AutoNestPhase m_phase;
- float m_progress;
- float m_speed;
- float m_lastParticule;
- Math::Vector m_fretPos;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autonest.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoNestPhase
+{
+ ANP_WAIT = 1,
+ ANP_BIRTH = 2, // appearance of a ball
+};
+
+
+
+class CAutoNest : public CAuto
+{
+public:
+ CAutoNest(CInstanceManager* iMan, CObject* object);
+ ~CAutoNest();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ bool SearchFree(Math::Vector pos);
+ void CreateFret(Math::Vector pos, float angle, ObjectType type);
+ CObject* SearchFret();
+
+protected:
+ AutoNestPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_lastParticule;
+ Math::Vector m_fretPos;
+};
+
diff --git a/src/object/auto/autonuclear.cpp b/src/object/auto/autonuclear.cpp
index 435bfc6..05f0b29 100644
--- a/src/object/auto/autonuclear.cpp
+++ b/src/object/auto/autonuclear.cpp
@@ -1,484 +1,484 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autonuclear.h"
-
-#include "common/iman.h"
-#include "math/geometry.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-
-
-
-const float NUCLEAR_DELAY = 30.0f; // duration of the generation
-
-
-
-
-// Object's constructor.
-
-CAutoNuclear::CAutoNuclear(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- m_channelSound = -1;
- Init();
-}
-
-// Object's destructor.
-
-CAutoNuclear::~CAutoNuclear()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoNuclear::DeleteObject(bool bAll)
-{
- CObject* fret;
-
- if ( !bAll )
- {
- fret = SearchUranium();
- if ( fret != 0 )
- {
- fret->DeleteObject(); // destroys the metal
- delete fret;
- }
- }
-
- if ( m_channelSound != -1 )
- {
- m_sound->FlushEnvelope(m_channelSound);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_channelSound = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoNuclear::Init()
-{
- Math::Matrix* mat;
-
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastParticule = 0.0f;
-
- mat = m_object->RetWorldMatrix(0);
- m_pos = Math::Transform(*mat, Math::Vector(22.0f, 4.0f, 0.0f));
-
- m_phase = ANUP_WAIT; // waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoNuclear::EventProcess(const Event &event)
-{
- CObject* fret;
- Math::Matrix* mat;
- Math::Vector pos, goal, speed;
- Math::Point dim, rot;
- float angle;
- int i, max;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
- }
- return true;
- }
-
- EventProgress(event.rTime);
-
- if ( m_phase == ANUP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- fret = SearchUranium(); // transform uranium?
- if ( fret == 0 || SearchVehicle() )
- {
- m_phase = ANUP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- else
- {
- fret->SetLock(true); // usable uranium
-
- SetBusy(true);
- InitProgressTotal(1.5f+NUCLEAR_DELAY+1.5f);
- UpdateInterface();
-
- m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.4f);
-
- m_phase = ANUP_CLOSE;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
- }
-
- if ( m_phase == ANUP_CLOSE )
- {
- if ( m_progress < 1.0f )
- {
- angle = (1.0f-m_progress)*(135.0f*Math::PI/180.0f);
- m_object->SetAngleZ(1, angle);
- }
- else
- {
- m_object->SetAngleZ(1, 0.0f);
-
- mat = m_object->RetWorldMatrix(0);
- max = (int)(10.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<max ; i++ )
- {
- pos.x = 27.0f;
- pos.y = 0.0f;
- pos.z = (Math::Rand()-0.5f)*8.0f;
- pos = Transform(*mat, pos);
- speed.y = 0.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH);
- }
-
- m_sound->Play(SOUND_CLOSE, m_object->RetPosition(0), 1.0f, 1.0f);
-
- m_channelSound = m_sound->Play(SOUND_NUCLEAR, m_object->RetPosition(0), 1.0f, 0.1f, true);
- m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, NUCLEAR_DELAY-1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP);
-
- m_phase = ANUP_GENERATE;
- m_progress = 0.0f;
- m_speed = 1.0f/NUCLEAR_DELAY;
- }
- }
-
- if ( m_phase == ANUP_GENERATE )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.y += 30.0f;
- pos.x += (Math::Rand()-0.5f)*6.0f;
- pos.z += (Math::Rand()-0.5f)*6.0f;
- speed.y = Math::Rand()*15.0f+15.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- dim.x = Math::Rand()*8.0f+8.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH);
-
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.y = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- dim.x = 2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 1.0f, 0.0f, 0.0f);
- }
- }
- else
- {
- fret = SearchUranium();
- if ( fret != 0 )
- {
- fret->DeleteObject(); // destroyed uranium
- delete fret;
- m_object->SetPower(0);
- }
-
- CreatePower(); // creates the atomic cell
-
- max = (int)(20.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<max ; i++ )
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*3.0f;
- pos.y += (Math::Rand()-0.5f)*3.0f;
- pos.z += (Math::Rand()-0.5f)*3.0f;
- speed.y = 0.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, Math::Rand()*5.0f+5.0f, 0.0f, 0.0f);
- }
-
- m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.4f);
-
- m_phase = ANUP_OPEN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
-
- if ( m_phase == ANUP_OPEN )
- {
- if ( m_progress < 1.0f )
- {
- angle = m_progress*(135.0f*Math::PI/180.0f);
- m_object->SetAngleZ(1, angle);
- }
- else
- {
- m_object->SetAngleZ(1, 135.0f*Math::PI/180.0f);
-
- SetBusy(false);
- UpdateInterface();
-
- m_displayText->DisplayError(INFO_NUCLEAR, m_object);
-
- m_phase = ANUP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- return true;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoNuclear::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 110, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-
-// Seeking the uranium.
-
-CObject* CAutoNuclear::SearchUranium()
-{
- CObject* pObj;
-
- pObj = m_object->RetPower();
- if ( pObj == 0 ) return 0;
- if ( pObj->RetType() == OBJECT_URANIUM ) return pObj;
- return 0;
-}
-
-// Seeks if a vehicle is too close.
-
-bool CAutoNuclear::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- float oRadius, dist;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr &&
- type != OBJECT_MOTHER &&
- type != OBJECT_ANT &&
- type != OBJECT_SPIDER &&
- type != OBJECT_BEE &&
- type != OBJECT_WORM ) continue;
-
- if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
- dist = Math::Distance(oPos, m_pos)-oRadius;
-
- if ( dist < 10.0f ) return true;
- }
-
- return false;
-}
-
-// Creates an object stack.
-
-void CAutoNuclear::CreatePower()
-{
- CObject* power;
- Math::Vector pos;
- float angle;
-
- pos = m_object->RetPosition(0);
- angle = m_object->RetAngleY(0);
-
- power = new CObject(m_iMan);
- if ( !power->CreateResource(pos, angle, OBJECT_ATOMIC) )
- {
- delete power;
- m_displayText->DisplayError(ERR_TOOMANY, m_object);
- return;
- }
-
- power->SetTruck(m_object);
- power->SetPosition(0, Math::Vector(22.0f, 3.0f, 0.0f));
- m_object->SetPower(power);
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoNuclear::RetError()
-{
- CObject* pObj;
- ObjectType type;
-//? TerrainRes res;
-
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
-//? res = m_terrain->RetResource(m_object->RetPosition(0));
-//? if ( res != TR_POWER ) return ERR_NUCLEAR_NULL;
-
-//? if ( m_object->RetEnergy() < ENERGY_POWER ) return ERR_NUCLEAR_LOW;
-
- pObj = m_object->RetPower();
- if ( pObj == 0 ) return ERR_NUCLEAR_EMPTY;
- if ( pObj->RetLock() ) return ERR_OK;
- type = pObj->RetType();
- if ( type == OBJECT_ATOMIC ) return ERR_OK;
- if ( type != OBJECT_URANIUM ) return ERR_NUCLEAR_BAD;
-
- return ERR_OK;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoNuclear::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == ANUP_STOP ||
- m_phase == ANUP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoNuclear::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoNuclearPhase)OpInt(line, "aPhase", ANUP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autonuclear.h"
+
+#include "common/iman.h"
+#include "math/geometry.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+
+
+
+const float NUCLEAR_DELAY = 30.0f; // duration of the generation
+
+
+
+
+// Object's constructor.
+
+CAutoNuclear::CAutoNuclear(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ m_channelSound = -1;
+ Init();
+}
+
+// Object's destructor.
+
+CAutoNuclear::~CAutoNuclear()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoNuclear::DeleteObject(bool bAll)
+{
+ CObject* fret;
+
+ if ( !bAll )
+ {
+ fret = SearchUranium();
+ if ( fret != 0 )
+ {
+ fret->DeleteObject(); // destroys the metal
+ delete fret;
+ }
+ }
+
+ if ( m_channelSound != -1 )
+ {
+ m_sound->FlushEnvelope(m_channelSound);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_channelSound = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoNuclear::Init()
+{
+ Math::Matrix* mat;
+
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+
+ mat = m_object->RetWorldMatrix(0);
+ m_pos = Math::Transform(*mat, Math::Vector(22.0f, 4.0f, 0.0f));
+
+ m_phase = ANUP_WAIT; // waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoNuclear::EventProcess(const Event &event)
+{
+ CObject* fret;
+ Math::Matrix* mat;
+ Math::Vector pos, goal, speed;
+ Math::Point dim, rot;
+ float angle;
+ int i, max;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+ }
+ return true;
+ }
+
+ EventProgress(event.rTime);
+
+ if ( m_phase == ANUP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ fret = SearchUranium(); // transform uranium?
+ if ( fret == 0 || SearchVehicle() )
+ {
+ m_phase = ANUP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ else
+ {
+ fret->SetLock(true); // usable uranium
+
+ SetBusy(true);
+ InitProgressTotal(1.5f+NUCLEAR_DELAY+1.5f);
+ UpdateInterface();
+
+ m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.4f);
+
+ m_phase = ANUP_CLOSE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+ }
+
+ if ( m_phase == ANUP_CLOSE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = (1.0f-m_progress)*(135.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(1, angle);
+ }
+ else
+ {
+ m_object->SetAngleZ(1, 0.0f);
+
+ mat = m_object->RetWorldMatrix(0);
+ max = (int)(10.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<max ; i++ )
+ {
+ pos.x = 27.0f;
+ pos.y = 0.0f;
+ pos.z = (Math::Rand()-0.5f)*8.0f;
+ pos = Transform(*mat, pos);
+ speed.y = 0.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH);
+ }
+
+ m_sound->Play(SOUND_CLOSE, m_object->RetPosition(0), 1.0f, 1.0f);
+
+ m_channelSound = m_sound->Play(SOUND_NUCLEAR, m_object->RetPosition(0), 1.0f, 0.1f, true);
+ m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, NUCLEAR_DELAY-1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP);
+
+ m_phase = ANUP_GENERATE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/NUCLEAR_DELAY;
+ }
+ }
+
+ if ( m_phase == ANUP_GENERATE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.y += 30.0f;
+ pos.x += (Math::Rand()-0.5f)*6.0f;
+ pos.z += (Math::Rand()-0.5f)*6.0f;
+ speed.y = Math::Rand()*15.0f+15.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ dim.x = Math::Rand()*8.0f+8.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH);
+
+ pos = m_pos;
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.y = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ dim.x = 2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 1.0f, 0.0f, 0.0f);
+ }
+ }
+ else
+ {
+ fret = SearchUranium();
+ if ( fret != 0 )
+ {
+ fret->DeleteObject(); // destroyed uranium
+ delete fret;
+ m_object->SetPower(0);
+ }
+
+ CreatePower(); // creates the atomic cell
+
+ max = (int)(20.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<max ; i++ )
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*3.0f;
+ pos.y += (Math::Rand()-0.5f)*3.0f;
+ pos.z += (Math::Rand()-0.5f)*3.0f;
+ speed.y = 0.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ dim.x = Math::Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, Math::Rand()*5.0f+5.0f, 0.0f, 0.0f);
+ }
+
+ m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.4f);
+
+ m_phase = ANUP_OPEN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+
+ if ( m_phase == ANUP_OPEN )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = m_progress*(135.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(1, angle);
+ }
+ else
+ {
+ m_object->SetAngleZ(1, 135.0f*Math::PI/180.0f);
+
+ SetBusy(false);
+ UpdateInterface();
+
+ m_displayText->DisplayError(INFO_NUCLEAR, m_object);
+
+ m_phase = ANUP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ return true;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoNuclear::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 110, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+
+// Seeking the uranium.
+
+CObject* CAutoNuclear::SearchUranium()
+{
+ CObject* pObj;
+
+ pObj = m_object->RetPower();
+ if ( pObj == 0 ) return 0;
+ if ( pObj->RetType() == OBJECT_URANIUM ) return pObj;
+ return 0;
+}
+
+// Seeks if a vehicle is too close.
+
+bool CAutoNuclear::SearchVehicle()
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ ObjectType type;
+ float oRadius, dist;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_HUMAN &&
+ type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis &&
+ type != OBJECT_MOBILErt &&
+ type != OBJECT_MOBILErc &&
+ type != OBJECT_MOBILErr &&
+ type != OBJECT_MOBILErs &&
+ type != OBJECT_MOBILEsa &&
+ type != OBJECT_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_MOBILEdr &&
+ type != OBJECT_MOTHER &&
+ type != OBJECT_ANT &&
+ type != OBJECT_SPIDER &&
+ type != OBJECT_BEE &&
+ type != OBJECT_WORM ) continue;
+
+ if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
+ dist = Math::Distance(oPos, m_pos)-oRadius;
+
+ if ( dist < 10.0f ) return true;
+ }
+
+ return false;
+}
+
+// Creates an object stack.
+
+void CAutoNuclear::CreatePower()
+{
+ CObject* power;
+ Math::Vector pos;
+ float angle;
+
+ pos = m_object->RetPosition(0);
+ angle = m_object->RetAngleY(0);
+
+ power = new CObject(m_iMan);
+ if ( !power->CreateResource(pos, angle, OBJECT_ATOMIC) )
+ {
+ delete power;
+ m_displayText->DisplayError(ERR_TOOMANY, m_object);
+ return;
+ }
+
+ power->SetTruck(m_object);
+ power->SetPosition(0, Math::Vector(22.0f, 3.0f, 0.0f));
+ m_object->SetPower(power);
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoNuclear::RetError()
+{
+ CObject* pObj;
+ ObjectType type;
+//? TerrainRes res;
+
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+//? res = m_terrain->RetResource(m_object->RetPosition(0));
+//? if ( res != TR_POWER ) return ERR_NUCLEAR_NULL;
+
+//? if ( m_object->RetEnergy() < ENERGY_POWER ) return ERR_NUCLEAR_LOW;
+
+ pObj = m_object->RetPower();
+ if ( pObj == 0 ) return ERR_NUCLEAR_EMPTY;
+ if ( pObj->RetLock() ) return ERR_OK;
+ type = pObj->RetType();
+ if ( type == OBJECT_ATOMIC ) return ERR_OK;
+ if ( type != OBJECT_URANIUM ) return ERR_NUCLEAR_BAD;
+
+ return ERR_OK;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoNuclear::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == ANUP_STOP ||
+ m_phase == ANUP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoNuclear::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoNuclearPhase)OpInt(line, "aPhase", ANUP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autonuclear.h b/src/object/auto/autonuclear.h
index 3054887..8a4b0da 100644
--- a/src/object/auto/autonuclear.h
+++ b/src/object/auto/autonuclear.h
@@ -1,68 +1,68 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autonuclear.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoNuclearPhase
-{
- ANUP_STOP = 1,
- ANUP_WAIT = 2,
- ANUP_CLOSE = 3,
- ANUP_GENERATE = 4,
- ANUP_OPEN = 5,
-};
-
-
-
-class CAutoNuclear : public CAuto
-{
-public:
- CAutoNuclear(CInstanceManager* iMan, CObject* object);
- ~CAutoNuclear();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- CObject* SearchUranium();
- bool SearchVehicle();
- void CreatePower();
-
-protected:
- AutoNuclearPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
- Math::Vector m_pos;
- int m_channelSound;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autonuclear.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoNuclearPhase
+{
+ ANUP_STOP = 1,
+ ANUP_WAIT = 2,
+ ANUP_CLOSE = 3,
+ ANUP_GENERATE = 4,
+ ANUP_OPEN = 5,
+};
+
+
+
+class CAutoNuclear : public CAuto
+{
+public:
+ CAutoNuclear(CInstanceManager* iMan, CObject* object);
+ ~CAutoNuclear();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ CObject* SearchUranium();
+ bool SearchVehicle();
+ void CreatePower();
+
+protected:
+ AutoNuclearPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+ Math::Vector m_pos;
+ int m_channelSound;
+};
+
diff --git a/src/object/auto/autopara.cpp b/src/object/auto/autopara.cpp
index 31e214d..80ce90a 100644
--- a/src/object/auto/autopara.cpp
+++ b/src/object/auto/autopara.cpp
@@ -1,327 +1,327 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autopara.h"
-
-
-#include "common/iman.h"
-#include "math/geometry.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-
-
-
-
-// Object's constructor.
-
-CAutoPara::CAutoPara(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- m_channelSound = -1;
- Init();
-}
-
-// Object's destructor.
-
-CAutoPara::~CAutoPara()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoPara::DeleteObject(bool bAll)
-{
- if ( m_channelSound != -1 )
- {
- m_sound->FlushEnvelope(m_channelSound);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_channelSound = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoPara::Init()
-{
- Math::Matrix* mat;
-
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastParticule = 0.0f;
-
- mat = m_object->RetWorldMatrix(0);
- m_pos = Math::Transform(*mat, Math::Vector(22.0f, 4.0f, 0.0f));
-
- m_phase = APAP_WAIT; // waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- CAuto::Init();
-}
-
-
-// Reception of lightning.
-
-void CAutoPara::StartBlitz()
-{
- m_phase = APAP_BLITZ;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-}
-
-
-// Management of an event.
-
-bool CAutoPara::EventProcess(const Event &event)
-{
- Math::Vector pos, speed;
- Math::Point dim;
- int i;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
- }
- return true;
- }
-
- EventProgress(event.rTime);
-
- if ( m_phase == APAP_BLITZ )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- for ( i=0 ; i<10 ; i++ )
- {
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*m_progress*40.0f;
- pos.z += (Math::Rand()-0.5f)*m_progress*40.0f;
- pos.y += 50.0f-m_progress*50.0f;
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = 5.0f+Math::Rand()*5.0f;
- dim.x = 2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 1.0f, 20.0f, 0.5f);
- }
- }
- }
- else
- {
- m_phase = APAP_CHARGE;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == APAP_CHARGE )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- for ( i=0 ; i<2 ; i++ )
- {
- pos = m_object->RetPosition(0);
- pos.y += 16.0f;
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = -Math::Rand()*30.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 1.0f, 0.0f, 0.0f);
- }
- }
-
- ChargeObject(event.rTime);
- }
- else
- {
- m_phase = APAP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- return true;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoPara::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 113, EVENT_OBJECT_TYPE);
-
- pos.x = ox+sx*10.2f;
- pos.y = oy+sy*0.5f;
- ddim.x = 33.0f/640.0f;
- ddim.y = 33.0f/480.0f;
- pw->CreateButton(pos, ddim, 41, EVENT_OBJECT_LIMIT);
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoPara::RetError()
-{
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
- return ERR_OK;
-}
-
-
-// Load all objects under the lightning rod.
-
-void CAutoPara::ChargeObject(float rTime)
-{
- CObject* pObj;
- CObject* power;
- Math::Vector sPos, oPos;
- float dist, energy;
- int i;
-
- sPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, sPos);
- if ( dist > 20.0f ) continue;
-
- if ( pObj->RetTruck() == 0 && pObj->RetType() == OBJECT_POWER )
- {
- energy = pObj->RetEnergy();
- energy += rTime/2.0f;
- if ( energy > 1.0f ) energy = 1.0f;
- pObj->SetEnergy(energy);
- }
-
- power = pObj->RetPower();
- if ( power != 0 && power->RetType() == OBJECT_POWER )
- {
- energy = power->RetEnergy();
- energy += rTime/2.0f;
- if ( energy > 1.0f ) energy = 1.0f;
- power->SetEnergy(energy);
- }
-
- power = pObj->RetFret();
- if ( power != 0 && power->RetType() == OBJECT_POWER )
- {
- energy = power->RetEnergy();
- energy += rTime/2.0f;
- if ( energy > 1.0f ) energy = 1.0f;
- power->SetEnergy(energy);
- }
- }
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoPara::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == APAP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoPara::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoParaPhase)OpInt(line, "aPhase", APAP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autopara.h"
+
+
+#include "common/iman.h"
+#include "math/geometry.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+
+
+
+
+// Object's constructor.
+
+CAutoPara::CAutoPara(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ m_channelSound = -1;
+ Init();
+}
+
+// Object's destructor.
+
+CAutoPara::~CAutoPara()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoPara::DeleteObject(bool bAll)
+{
+ if ( m_channelSound != -1 )
+ {
+ m_sound->FlushEnvelope(m_channelSound);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_channelSound = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoPara::Init()
+{
+ Math::Matrix* mat;
+
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+
+ mat = m_object->RetWorldMatrix(0);
+ m_pos = Math::Transform(*mat, Math::Vector(22.0f, 4.0f, 0.0f));
+
+ m_phase = APAP_WAIT; // waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ CAuto::Init();
+}
+
+
+// Reception of lightning.
+
+void CAutoPara::StartBlitz()
+{
+ m_phase = APAP_BLITZ;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+}
+
+
+// Management of an event.
+
+bool CAutoPara::EventProcess(const Event &event)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+ int i;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+ }
+ return true;
+ }
+
+ EventProgress(event.rTime);
+
+ if ( m_phase == APAP_BLITZ )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*m_progress*40.0f;
+ pos.z += (Math::Rand()-0.5f)*m_progress*40.0f;
+ pos.y += 50.0f-m_progress*50.0f;
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ speed.y = 5.0f+Math::Rand()*5.0f;
+ dim.x = 2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 1.0f, 20.0f, 0.5f);
+ }
+ }
+ }
+ else
+ {
+ m_phase = APAP_CHARGE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == APAP_CHARGE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ for ( i=0 ; i<2 ; i++ )
+ {
+ pos = m_object->RetPosition(0);
+ pos.y += 16.0f;
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = -Math::Rand()*30.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 1.0f, 0.0f, 0.0f);
+ }
+ }
+
+ ChargeObject(event.rTime);
+ }
+ else
+ {
+ m_phase = APAP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ return true;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoPara::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 113, EVENT_OBJECT_TYPE);
+
+ pos.x = ox+sx*10.2f;
+ pos.y = oy+sy*0.5f;
+ ddim.x = 33.0f/640.0f;
+ ddim.y = 33.0f/480.0f;
+ pw->CreateButton(pos, ddim, 41, EVENT_OBJECT_LIMIT);
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoPara::RetError()
+{
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+ return ERR_OK;
+}
+
+
+// Load all objects under the lightning rod.
+
+void CAutoPara::ChargeObject(float rTime)
+{
+ CObject* pObj;
+ CObject* power;
+ Math::Vector sPos, oPos;
+ float dist, energy;
+ int i;
+
+ sPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, sPos);
+ if ( dist > 20.0f ) continue;
+
+ if ( pObj->RetTruck() == 0 && pObj->RetType() == OBJECT_POWER )
+ {
+ energy = pObj->RetEnergy();
+ energy += rTime/2.0f;
+ if ( energy > 1.0f ) energy = 1.0f;
+ pObj->SetEnergy(energy);
+ }
+
+ power = pObj->RetPower();
+ if ( power != 0 && power->RetType() == OBJECT_POWER )
+ {
+ energy = power->RetEnergy();
+ energy += rTime/2.0f;
+ if ( energy > 1.0f ) energy = 1.0f;
+ power->SetEnergy(energy);
+ }
+
+ power = pObj->RetFret();
+ if ( power != 0 && power->RetType() == OBJECT_POWER )
+ {
+ energy = power->RetEnergy();
+ energy += rTime/2.0f;
+ if ( energy > 1.0f ) energy = 1.0f;
+ power->SetEnergy(energy);
+ }
+ }
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoPara::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == APAP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoPara::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoParaPhase)OpInt(line, "aPhase", APAP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autopara.h b/src/object/auto/autopara.h
index e28aa47..b230fd2 100644
--- a/src/object/auto/autopara.h
+++ b/src/object/auto/autopara.h
@@ -1,65 +1,65 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autopara.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoParaPhase
-{
- APAP_WAIT = 1,
- APAP_BLITZ = 2,
- APAP_CHARGE = 3,
-};
-
-
-
-class CAutoPara : public CAuto
-{
-public:
- CAutoPara(CInstanceManager* iMan, CObject* object);
- ~CAutoPara();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
- void StartBlitz();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- void ChargeObject(float rTime);
-
-protected:
- AutoParaPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
- Math::Vector m_pos;
- int m_channelSound;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autopara.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoParaPhase
+{
+ APAP_WAIT = 1,
+ APAP_BLITZ = 2,
+ APAP_CHARGE = 3,
+};
+
+
+
+class CAutoPara : public CAuto
+{
+public:
+ CAutoPara(CInstanceManager* iMan, CObject* object);
+ ~CAutoPara();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+ void StartBlitz();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ void ChargeObject(float rTime);
+
+protected:
+ AutoParaPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+ Math::Vector m_pos;
+ int m_channelSound;
+};
+
diff --git a/src/object/auto/autoportico.cpp b/src/object/auto/autoportico.cpp
index ee3376f..5665556 100644
--- a/src/object/auto/autoportico.cpp
+++ b/src/object/auto/autoportico.cpp
@@ -1,425 +1,425 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoportico.h"
-
-
-#include "object/robotmain.h"
-
-
-
-
-const int PARAM_DEPOSE = 2; // run=2 -> deposits the spaceship
-
-const float PORTICO_POSa = 75.0f;
-const float PORTICO_POSb = 65.0f;
-const float PORTICO_ANGLE1a = ( 25.0f*Math::PI/180.0f);
-const float PORTICO_ANGLE1b = ( 70.0f*Math::PI/180.0f);
-const float PORTICO_ANGLE2a = (-37.5f*Math::PI/180.0f);
-const float PORTICO_ANGLE2b = (-62.5f*Math::PI/180.0f);
-const float PORTICO_ANGLE3a = (-77.5f*Math::PI/180.0f);
-const float PORTICO_ANGLE3b = (-30.0f*Math::PI/180.0f);
-
-const float PORTICO_TIME_MOVE = 16.0f;
-const float PORTICO_TIME_DOWN = 4.0f;
-const float PORTICO_TIME_OPEN = 12.0f;
-
-
-
-
-// Si progress=0, return a.
-// Si progress=1, return b.
-
-float Progress(float a, float b, float progress)
-{
- return a+(b-a)*progress;
-}
-
-
-
-// Object's constructor.
-
-CAutoPortico::CAutoPortico(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
- m_phase = APOP_WAIT;
- m_soundChannel = -1;
-}
-
-// Object's destructor.
-
-CAutoPortico::~CAutoPortico()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoPortico::DeleteObject(bool bAll)
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoPortico::Init()
-{
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- m_posTrack = 0.0f;
-
- m_phase = APOP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- m_cameraProgress = 0.0f;
- m_cameraSpeed = 1.0f/(PORTICO_TIME_MOVE-2.0f);
-}
-
-
-// Starts the object.
-
-void CAutoPortico::Start(int param)
-{
- Math::Vector pos;
-
- pos = m_object->RetPosition(0);
- m_finalPos = pos;
- pos.z += PORTICO_TIME_MOVE*5.0f; // back to start
- m_object->SetPosition(0, pos);
- m_finalPos.z += PORTICO_TIME_OPEN*5.3f;
-
- m_object->SetPosition(1, Math::Vector(0.0f, PORTICO_POSa, 0.0f));
- m_object->SetAngleY(2, PORTICO_ANGLE1a);
- m_object->SetAngleY(3, PORTICO_ANGLE2a);
- m_object->SetAngleY(4, PORTICO_ANGLE3a);
- m_object->SetAngleY(5, -PORTICO_ANGLE1a);
- m_object->SetAngleY(6, -PORTICO_ANGLE2a);
- m_object->SetAngleY(7, -PORTICO_ANGLE3a);
-
- m_phase = APOP_START;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- m_param = param;
-}
-
-
-// Management of an event.
-
-bool CAutoPortico::EventProcess(const Event &event)
-{
- CObject* pObj;
- Math::Vector pos;
- float angle;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
-
- if ( m_phase == APOP_START )
- {
- if ( m_param == PARAM_DEPOSE ) // deposits the ship?
- {
- m_startPos = m_object->RetPosition(0);
-
- m_soundChannel = m_sound->Play(SOUND_MOTORr, m_object->RetPosition(0), 0.0f, 0.3f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, 0.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, PORTICO_TIME_MOVE-0.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 0.5f, SOPER_STOP);
-
- m_phase = APOP_MOVE;
- m_progress = 0.0f;
- m_speed = 1.0f/PORTICO_TIME_MOVE;
-
- m_main->SetMovieLock(true); // blocks everything until the end of the landing
-
- m_camera->SetType(CAMERA_SCRIPT);
-
- pos = m_startPos;
- pos.x += -100.0f;
- pos.y += 9.0f;
- pos.z += -200.0f;
- m_camera->SetScriptEye(pos);
-
- pos = m_object->RetPosition(0);
- pos.x += 0.0f;
- pos.y += 10.0f;
- pos.z += -40.0f;
- m_camera->SetScriptLookat(pos);
-
- m_camera->FixCamera();
- }
- }
-
- angle = -m_time*1.0f;
- m_object->SetAngleY(8, angle); // rotates the radar right
- angle = sinf(m_time*4.0f)*0.3f;
- m_object->SetAngleX(9, angle);
-
- angle = -m_time*1.0f+Math::PI/2.3f;
- m_object->SetAngleY(10, angle); // turns the left side radar
- angle = sinf(m_time*4.0f)*0.3f;
- m_object->SetAngleX(11, angle);
-
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_phase == APOP_WAIT ) return true;
-
- m_progress += event.rTime*m_speed;
- m_cameraProgress += event.rTime*m_cameraSpeed;
-
- if ( m_phase == APOP_MOVE )
- {
- if ( m_progress < 1.0f )
- {
- pos = m_object->RetPosition(0);
- pos.z -= event.rTime*5.0f; // advance
- m_object->SetPosition(0, pos);
-
- m_posTrack += event.rTime*0.5f;
- UpdateTrackMapping(m_posTrack, m_posTrack);
- }
- else
- {
- m_phase = APOP_WAIT1;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == APOP_WAIT1 )
- {
- if ( m_progress >= 1.0f )
- {
- m_soundChannel = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.5f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.6f, PORTICO_TIME_DOWN-1.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 1.0f, SOPER_STOP);
-
- m_phase = APOP_DOWN;
- m_progress = 0.0f;
- m_speed = 1.0f/PORTICO_TIME_DOWN;
- }
- }
-
- if ( m_phase == APOP_DOWN )
- {
- if ( m_progress < 1.0f )
- {
- pos.x = 0.0f;
- pos.y = Progress(PORTICO_POSa, PORTICO_POSb, m_progress);
- pos.z = 0.0f;
- m_object->SetPosition(1, pos);
- }
- else
- {
- pos.x = 0.0f;
- pos.y = PORTICO_POSb;
- pos.z = 0.0f;
- m_object->SetPosition(1, pos);
-
- m_phase = APOP_WAIT2;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == APOP_WAIT2 )
- {
- if ( m_progress >= 1.0f )
- {
- m_soundChannel = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 1.0f, 0.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 1.0f, PORTICO_TIME_OPEN/2.0f-0.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP);
-
- m_soundChannel = m_sound->Play(SOUND_MOTORr, m_object->RetPosition(0), 0.0f, 0.3f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, 0.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, PORTICO_TIME_OPEN-0.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 0.5f, SOPER_STOP);
-
- m_phase = APOP_OPEN;
- m_progress = 0.0f;
- m_speed = 1.0f/PORTICO_TIME_OPEN;
- }
- }
-
- if ( m_phase == APOP_OPEN )
- {
- if ( m_progress < 1.0f )
- {
- pos = m_object->RetPosition(0);
- pos.z += event.rTime*5.3f; // back
- m_object->SetPosition(0, pos);
-
- m_posTrack -= event.rTime*1.0f;
- UpdateTrackMapping(m_posTrack, m_posTrack);
-
- if ( m_progress < 0.5f )
- {
- angle = Progress(PORTICO_ANGLE1a, PORTICO_ANGLE1b, m_progress/0.5f);
- m_object->SetAngleY(2, angle);
- m_object->SetAngleY(5, -angle);
- angle = Progress(PORTICO_ANGLE2a, PORTICO_ANGLE2b, m_progress/0.5f);
- m_object->SetAngleY(3, angle);
- m_object->SetAngleY(6, -angle);
- angle = Progress(PORTICO_ANGLE3a, PORTICO_ANGLE3b, m_progress/0.5f);
- m_object->SetAngleY(4, angle);
- m_object->SetAngleY(7, -angle);
- }
- else
- {
- m_object->SetAngleY(2, PORTICO_ANGLE1b);
- m_object->SetAngleY(3, PORTICO_ANGLE2b);
- m_object->SetAngleY(4, PORTICO_ANGLE3b);
- m_object->SetAngleY(5, -PORTICO_ANGLE1b);
- m_object->SetAngleY(6, -PORTICO_ANGLE2b);
- m_object->SetAngleY(7, -PORTICO_ANGLE3b);
- }
- }
- else
- {
- m_main->SetMovieLock(false); // you can play!
-
- pObj = m_main->SearchHuman();
- m_main->SelectObject(pObj);
- m_camera->SetObject(pObj);
- m_camera->SetType(CAMERA_BACK);
-
- m_phase = APOP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_soundChannel != -1 )
- {
-//? m_sound->Position(m_soundChannel, m_object->RetPosition(0));
- pos = m_engine->RetEyePt();
- m_sound->Position(m_soundChannel, pos);
- }
-
- if ( m_cameraProgress < 1.0f )
- {
- if ( m_cameraProgress < 0.5f )
- {
- }
- else
- {
- pos = m_startPos;
- pos.x += -100.0f-(m_cameraProgress-0.5f)*1.0f*120.0f;
- pos.y += 9.0f;
- pos.z += -200.0f+(m_cameraProgress-0.5f)*1.0f*210.0f;
- m_camera->SetScriptEye(pos);
- }
-
- pos = m_object->RetPosition(0);
- pos.x += 0.0f;
- pos.y += 10.0f;
- pos.z += -40.0f;
- m_camera->SetScriptLookat(pos);
- }
-
- return true;
-}
-
-// Stops the controller.
-
-bool CAutoPortico::Abort()
-{
- CObject* pObj;
-
- m_object->SetPosition(0, m_finalPos);
- m_object->SetPosition(1, Math::Vector(0.0f, PORTICO_POSb, 0.0f));
- m_object->SetAngleY(2, PORTICO_ANGLE1b);
- m_object->SetAngleY(3, PORTICO_ANGLE2b);
- m_object->SetAngleY(4, PORTICO_ANGLE3b);
- m_object->SetAngleY(5, -PORTICO_ANGLE1b);
- m_object->SetAngleY(6, -PORTICO_ANGLE2b);
- m_object->SetAngleY(7, -PORTICO_ANGLE3b);
-
- m_main->SetMovieLock(false); // you can play!
-
- pObj = m_main->SearchHuman();
- m_main->SelectObject(pObj);
- m_camera->SetObject(pObj);
- m_camera->SetType(CAMERA_BACK);
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- m_phase = APOP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoPortico::RetError()
-{
- return ERR_OK;
-}
-
-
-// Updates the mapping of the texture of the caterpillars.
-
-void CAutoPortico::UpdateTrackMapping(float left, float right)
-{
- D3DMATERIAL7 mat;
- float limit[2];
- int rank;
-
- ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
- mat.diffuse.r = 1.0f;
- mat.diffuse.g = 1.0f;
- mat.diffuse.b = 1.0f; // blank
- mat.ambient.r = 0.5f;
- mat.ambient.g = 0.5f;
- mat.ambient.b = 0.5f;
-
- rank = m_object->RetObjectRank(0);
-
- limit[0] = 0.0f;
- limit[1] = 1000000.0f;
-
- m_engine->TrackTextureMapping(rank, mat, D3DSTATEPART1, "lemt.tga", "",
- limit[0], limit[1], D3DMAPPINGX,
- right, 8.0f, 8.0f, 192.0f, 256.0f);
-
- m_engine->TrackTextureMapping(rank, mat, D3DSTATEPART2, "lemt.tga", "",
- limit[0], limit[1], D3DMAPPINGX,
- left, 8.0f, 8.0f, 192.0f, 256.0f);
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoportico.h"
+
+
+#include "object/robotmain.h"
+
+
+
+
+const int PARAM_DEPOSE = 2; // run=2 -> deposits the spaceship
+
+const float PORTICO_POSa = 75.0f;
+const float PORTICO_POSb = 65.0f;
+const float PORTICO_ANGLE1a = ( 25.0f*Math::PI/180.0f);
+const float PORTICO_ANGLE1b = ( 70.0f*Math::PI/180.0f);
+const float PORTICO_ANGLE2a = (-37.5f*Math::PI/180.0f);
+const float PORTICO_ANGLE2b = (-62.5f*Math::PI/180.0f);
+const float PORTICO_ANGLE3a = (-77.5f*Math::PI/180.0f);
+const float PORTICO_ANGLE3b = (-30.0f*Math::PI/180.0f);
+
+const float PORTICO_TIME_MOVE = 16.0f;
+const float PORTICO_TIME_DOWN = 4.0f;
+const float PORTICO_TIME_OPEN = 12.0f;
+
+
+
+
+// Si progress=0, return a.
+// Si progress=1, return b.
+
+float Progress(float a, float b, float progress)
+{
+ return a+(b-a)*progress;
+}
+
+
+
+// Object's constructor.
+
+CAutoPortico::CAutoPortico(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+ m_phase = APOP_WAIT;
+ m_soundChannel = -1;
+}
+
+// Object's destructor.
+
+CAutoPortico::~CAutoPortico()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoPortico::DeleteObject(bool bAll)
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoPortico::Init()
+{
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+ m_posTrack = 0.0f;
+
+ m_phase = APOP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ m_cameraProgress = 0.0f;
+ m_cameraSpeed = 1.0f/(PORTICO_TIME_MOVE-2.0f);
+}
+
+
+// Starts the object.
+
+void CAutoPortico::Start(int param)
+{
+ Math::Vector pos;
+
+ pos = m_object->RetPosition(0);
+ m_finalPos = pos;
+ pos.z += PORTICO_TIME_MOVE*5.0f; // back to start
+ m_object->SetPosition(0, pos);
+ m_finalPos.z += PORTICO_TIME_OPEN*5.3f;
+
+ m_object->SetPosition(1, Math::Vector(0.0f, PORTICO_POSa, 0.0f));
+ m_object->SetAngleY(2, PORTICO_ANGLE1a);
+ m_object->SetAngleY(3, PORTICO_ANGLE2a);
+ m_object->SetAngleY(4, PORTICO_ANGLE3a);
+ m_object->SetAngleY(5, -PORTICO_ANGLE1a);
+ m_object->SetAngleY(6, -PORTICO_ANGLE2a);
+ m_object->SetAngleY(7, -PORTICO_ANGLE3a);
+
+ m_phase = APOP_START;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ m_param = param;
+}
+
+
+// Management of an event.
+
+bool CAutoPortico::EventProcess(const Event &event)
+{
+ CObject* pObj;
+ Math::Vector pos;
+ float angle;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+
+ if ( m_phase == APOP_START )
+ {
+ if ( m_param == PARAM_DEPOSE ) // deposits the ship?
+ {
+ m_startPos = m_object->RetPosition(0);
+
+ m_soundChannel = m_sound->Play(SOUND_MOTORr, m_object->RetPosition(0), 0.0f, 0.3f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, 0.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, PORTICO_TIME_MOVE-0.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 0.5f, SOPER_STOP);
+
+ m_phase = APOP_MOVE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/PORTICO_TIME_MOVE;
+
+ m_main->SetMovieLock(true); // blocks everything until the end of the landing
+
+ m_camera->SetType(CAMERA_SCRIPT);
+
+ pos = m_startPos;
+ pos.x += -100.0f;
+ pos.y += 9.0f;
+ pos.z += -200.0f;
+ m_camera->SetScriptEye(pos);
+
+ pos = m_object->RetPosition(0);
+ pos.x += 0.0f;
+ pos.y += 10.0f;
+ pos.z += -40.0f;
+ m_camera->SetScriptLookat(pos);
+
+ m_camera->FixCamera();
+ }
+ }
+
+ angle = -m_time*1.0f;
+ m_object->SetAngleY(8, angle); // rotates the radar right
+ angle = sinf(m_time*4.0f)*0.3f;
+ m_object->SetAngleX(9, angle);
+
+ angle = -m_time*1.0f+Math::PI/2.3f;
+ m_object->SetAngleY(10, angle); // turns the left side radar
+ angle = sinf(m_time*4.0f)*0.3f;
+ m_object->SetAngleX(11, angle);
+
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_phase == APOP_WAIT ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_cameraProgress += event.rTime*m_cameraSpeed;
+
+ if ( m_phase == APOP_MOVE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos = m_object->RetPosition(0);
+ pos.z -= event.rTime*5.0f; // advance
+ m_object->SetPosition(0, pos);
+
+ m_posTrack += event.rTime*0.5f;
+ UpdateTrackMapping(m_posTrack, m_posTrack);
+ }
+ else
+ {
+ m_phase = APOP_WAIT1;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == APOP_WAIT1 )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_soundChannel = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.5f, 1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.6f, PORTICO_TIME_DOWN-1.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 1.0f, SOPER_STOP);
+
+ m_phase = APOP_DOWN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/PORTICO_TIME_DOWN;
+ }
+ }
+
+ if ( m_phase == APOP_DOWN )
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos.x = 0.0f;
+ pos.y = Progress(PORTICO_POSa, PORTICO_POSb, m_progress);
+ pos.z = 0.0f;
+ m_object->SetPosition(1, pos);
+ }
+ else
+ {
+ pos.x = 0.0f;
+ pos.y = PORTICO_POSb;
+ pos.z = 0.0f;
+ m_object->SetPosition(1, pos);
+
+ m_phase = APOP_WAIT2;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == APOP_WAIT2 )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_soundChannel = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.5f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.5f, 1.0f, 0.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.5f, 1.0f, PORTICO_TIME_OPEN/2.0f-0.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP);
+
+ m_soundChannel = m_sound->Play(SOUND_MOTORr, m_object->RetPosition(0), 0.0f, 0.3f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, 0.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, PORTICO_TIME_OPEN-0.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 0.5f, SOPER_STOP);
+
+ m_phase = APOP_OPEN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/PORTICO_TIME_OPEN;
+ }
+ }
+
+ if ( m_phase == APOP_OPEN )
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos = m_object->RetPosition(0);
+ pos.z += event.rTime*5.3f; // back
+ m_object->SetPosition(0, pos);
+
+ m_posTrack -= event.rTime*1.0f;
+ UpdateTrackMapping(m_posTrack, m_posTrack);
+
+ if ( m_progress < 0.5f )
+ {
+ angle = Progress(PORTICO_ANGLE1a, PORTICO_ANGLE1b, m_progress/0.5f);
+ m_object->SetAngleY(2, angle);
+ m_object->SetAngleY(5, -angle);
+ angle = Progress(PORTICO_ANGLE2a, PORTICO_ANGLE2b, m_progress/0.5f);
+ m_object->SetAngleY(3, angle);
+ m_object->SetAngleY(6, -angle);
+ angle = Progress(PORTICO_ANGLE3a, PORTICO_ANGLE3b, m_progress/0.5f);
+ m_object->SetAngleY(4, angle);
+ m_object->SetAngleY(7, -angle);
+ }
+ else
+ {
+ m_object->SetAngleY(2, PORTICO_ANGLE1b);
+ m_object->SetAngleY(3, PORTICO_ANGLE2b);
+ m_object->SetAngleY(4, PORTICO_ANGLE3b);
+ m_object->SetAngleY(5, -PORTICO_ANGLE1b);
+ m_object->SetAngleY(6, -PORTICO_ANGLE2b);
+ m_object->SetAngleY(7, -PORTICO_ANGLE3b);
+ }
+ }
+ else
+ {
+ m_main->SetMovieLock(false); // you can play!
+
+ pObj = m_main->SearchHuman();
+ m_main->SelectObject(pObj);
+ m_camera->SetObject(pObj);
+ m_camera->SetType(CAMERA_BACK);
+
+ m_phase = APOP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_soundChannel != -1 )
+ {
+//? m_sound->Position(m_soundChannel, m_object->RetPosition(0));
+ pos = m_engine->RetEyePt();
+ m_sound->Position(m_soundChannel, pos);
+ }
+
+ if ( m_cameraProgress < 1.0f )
+ {
+ if ( m_cameraProgress < 0.5f )
+ {
+ }
+ else
+ {
+ pos = m_startPos;
+ pos.x += -100.0f-(m_cameraProgress-0.5f)*1.0f*120.0f;
+ pos.y += 9.0f;
+ pos.z += -200.0f+(m_cameraProgress-0.5f)*1.0f*210.0f;
+ m_camera->SetScriptEye(pos);
+ }
+
+ pos = m_object->RetPosition(0);
+ pos.x += 0.0f;
+ pos.y += 10.0f;
+ pos.z += -40.0f;
+ m_camera->SetScriptLookat(pos);
+ }
+
+ return true;
+}
+
+// Stops the controller.
+
+bool CAutoPortico::Abort()
+{
+ CObject* pObj;
+
+ m_object->SetPosition(0, m_finalPos);
+ m_object->SetPosition(1, Math::Vector(0.0f, PORTICO_POSb, 0.0f));
+ m_object->SetAngleY(2, PORTICO_ANGLE1b);
+ m_object->SetAngleY(3, PORTICO_ANGLE2b);
+ m_object->SetAngleY(4, PORTICO_ANGLE3b);
+ m_object->SetAngleY(5, -PORTICO_ANGLE1b);
+ m_object->SetAngleY(6, -PORTICO_ANGLE2b);
+ m_object->SetAngleY(7, -PORTICO_ANGLE3b);
+
+ m_main->SetMovieLock(false); // you can play!
+
+ pObj = m_main->SearchHuman();
+ m_main->SelectObject(pObj);
+ m_camera->SetObject(pObj);
+ m_camera->SetType(CAMERA_BACK);
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ m_phase = APOP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoPortico::RetError()
+{
+ return ERR_OK;
+}
+
+
+// Updates the mapping of the texture of the caterpillars.
+
+void CAutoPortico::UpdateTrackMapping(float left, float right)
+{
+ D3DMATERIAL7 mat;
+ float limit[2];
+ int rank;
+
+ ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
+ mat.diffuse.r = 1.0f;
+ mat.diffuse.g = 1.0f;
+ mat.diffuse.b = 1.0f; // blank
+ mat.ambient.r = 0.5f;
+ mat.ambient.g = 0.5f;
+ mat.ambient.b = 0.5f;
+
+ rank = m_object->RetObjectRank(0);
+
+ limit[0] = 0.0f;
+ limit[1] = 1000000.0f;
+
+ m_engine->TrackTextureMapping(rank, mat, D3DSTATEPART1, "lemt.tga", "",
+ limit[0], limit[1], D3DMAPPINGX,
+ right, 8.0f, 8.0f, 192.0f, 256.0f);
+
+ m_engine->TrackTextureMapping(rank, mat, D3DSTATEPART2, "lemt.tga", "",
+ limit[0], limit[1], D3DMAPPINGX,
+ left, 8.0f, 8.0f, 192.0f, 256.0f);
+}
+
diff --git a/src/object/auto/autoportico.h b/src/object/auto/autoportico.h
index 566c358..f2cd6d1 100644
--- a/src/object/auto/autoportico.h
+++ b/src/object/auto/autoportico.h
@@ -1,69 +1,69 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoportico.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoPorticoPhase
-{
- APOP_WAIT = 1, // waits
- APOP_START = 2, // start of the action
- APOP_MOVE = 3, // advance
- APOP_WAIT1 = 4, // waits
- APOP_DOWN = 5, // down
- APOP_WAIT2 = 6, // waits
- APOP_OPEN = 7, // opens
-};
-
-
-
-class CAutoPortico : public CAuto
-{
-public:
- CAutoPortico(CInstanceManager* iMan, CObject* object);
- ~CAutoPortico();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- void Start(int param);
- bool EventProcess(const Event &event);
- bool Abort();
- Error RetError();
-
-protected:
- void UpdateTrackMapping(float left, float right);
-
-protected:
- AutoPorticoPhase m_phase;
- float m_progress;
- float m_speed;
- float m_cameraProgress;
- float m_cameraSpeed;
- float m_lastParticule;
- Math::Vector m_finalPos;
- Math::Vector m_startPos;
- float m_posTrack;
- int m_param;
- int m_soundChannel;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoportico.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoPorticoPhase
+{
+ APOP_WAIT = 1, // waits
+ APOP_START = 2, // start of the action
+ APOP_MOVE = 3, // advance
+ APOP_WAIT1 = 4, // waits
+ APOP_DOWN = 5, // down
+ APOP_WAIT2 = 6, // waits
+ APOP_OPEN = 7, // opens
+};
+
+
+
+class CAutoPortico : public CAuto
+{
+public:
+ CAutoPortico(CInstanceManager* iMan, CObject* object);
+ ~CAutoPortico();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ void Start(int param);
+ bool EventProcess(const Event &event);
+ bool Abort();
+ Error RetError();
+
+protected:
+ void UpdateTrackMapping(float left, float right);
+
+protected:
+ AutoPorticoPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_cameraProgress;
+ float m_cameraSpeed;
+ float m_lastParticule;
+ Math::Vector m_finalPos;
+ Math::Vector m_startPos;
+ float m_posTrack;
+ int m_param;
+ int m_soundChannel;
+};
+
diff --git a/src/object/auto/autoradar.cpp b/src/object/auto/autoradar.cpp
index b8bee44..1cb20d6 100644
--- a/src/object/auto/autoradar.cpp
+++ b/src/object/auto/autoradar.cpp
@@ -1,306 +1,306 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoradar.h"
-
-#include "common/iman.h"
-#include "math/geometry.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-#include "ui/gauge.h"
-
-
-// Object's constructor.
-
-CAutoRadar::CAutoRadar(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
- m_phase = ARAP_WAIT;
- m_totalDetect = 0;
-}
-
-// Object's destructor.
-
-CAutoRadar::~CAutoRadar()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoRadar::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoRadar::Init()
-{
- m_phase = ARAP_SEARCH;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
-
- m_aTime = 0.0f;
- m_time = 0.0f;
- m_timeVirus = 0.0f;
-}
-
-
-// Management of an event.
-
-bool CAutoRadar::EventProcess(const Event &event)
-{
- Math::Vector pos, ePos;
- float speed, angle, prog, freq, ampl;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_phase == ARAP_WAIT ) return true;
-
- m_progress += event.rTime*m_speed;
- m_aTime += event.rTime;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
-
- angle = m_object->RetAngleY(1);
- angle += (Math::Rand()-0.2f)*0.5f;
- m_object->SetAngleY(1, angle);
-
- angle = m_object->RetAngleY(2);
- angle += (Math::Rand()-0.8f)*1.0f;
- m_object->SetAngleY(2, angle);
-
- m_object->SetAngleX(3, (Math::Rand()-0.5f)*0.3f);
-
- m_totalDetect = (int)(Math::Rand()*10.0f);
- UpdateInterface();
- }
- return true;
- }
-
- if ( m_phase == ARAP_SEARCH )
- {
- if ( m_progress < 1.0f )
- {
- speed = Math::Min(10.0f, m_progress*50.0f);
- angle = m_object->RetAngleY(1);
- angle += event.rTime*speed;
- m_object->SetAngleY(1, angle);
- }
- else
- {
- if ( !SearchEnemy(ePos) )
- {
- m_phase = ARAP_SEARCH;
- m_progress = 10.0f/50.0f; // full speed immediately
- m_speed = 1.0f/3.0f;
- }
- else
- {
- pos = m_object->RetPosition(0);
- m_start = m_object->RetAngleY(1);
- m_angle = m_start-Math::NormAngle(m_start)+Math::PI*2.0f;
- m_angle += Math::RotateAngle(pos.x-ePos.x, ePos.z-pos.z);
- m_angle += Math::PI-m_object->RetAngleY(0);
-
- m_phase = ARAP_SHOW;
- m_progress = 0.0f;
- m_speed = 1.0f/(fabs(m_angle-m_start)/10.0f);
- }
- }
- }
-
- if ( m_phase == ARAP_SHOW )
- {
- if ( m_progress < 1.0f )
- {
- angle = m_start + (m_angle-m_start)*m_progress;
- m_object->SetAngleY(1, angle);
- }
- else
- {
- m_sound->Play(SOUND_RADAR, m_object->RetPosition(0));
-
- m_phase = ARAP_SINUS;
- m_progress = 0.0f;
- m_speed = 1.0f/4.0f;
- m_time = 0.0f;
- }
- }
-
- if ( m_phase == ARAP_SINUS )
- {
- if ( m_progress < 1.0f )
- {
- prog = Math::Min(1.0f, m_progress*2.0f);
- freq = 16.0f*(prog+1.0f);
- ampl = 0.2f-prog*0.2f;
- angle = m_angle + sinf(m_time*freq)*ampl;
- m_object->SetAngleY(1, angle);
- }
- else
- {
- m_phase = ARAP_SEARCH;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- }
- }
-
- angle = -m_aTime*2.0f;
- m_object->SetAngleY(2, angle);
-
- angle = sinf(m_aTime*4.0f)*0.3f;
- m_object->SetAngleX(3, angle);
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoRadar::RetError()
-{
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- return ERR_OK;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoRadar::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, dim, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*7.0f;
- pos.y = oy+sy*0.6f;
- dim.x = 160.0f/640.0f;
- dim.y = 26.0f/480.0f;
- pw->CreateGauge(pos, dim, 1, EVENT_OBJECT_GRADAR);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 105, EVENT_OBJECT_TYPE);
-
- UpdateInterface();
- return true;
-}
-
-// Updates the status of all interface buttons.
-
-void CAutoRadar::UpdateInterface()
-{
- CWindow* pw;
- CGauge* pg;
- float level;
-
- if ( !m_object->RetSelect() ) return;
-
- CAuto::UpdateInterface();
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GRADAR);
- if ( pg != 0 )
- {
- level = (float)m_totalDetect*(1.0f/8.0f);
- if ( level > 1.0f ) level = 1.0f;
- pg->SetLevel(level);
- }
-}
-
-
-// Seeking the position of an enemy.
-
-bool CAutoRadar::SearchEnemy(Math::Vector &pos)
-{
- CObject* pObj;
- CObject* pBest = 0;
- Math::Vector iPos, oPos;
- ObjectType oType;
- float distance, min;
- int i;
-
- iPos = m_object->RetPosition(0);
- min = 1000000.0f;
- m_totalDetect = 0;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue;
-
- oType = pObj->RetType();
- if ( oType != OBJECT_ANT &&
- oType != OBJECT_SPIDER &&
- oType != OBJECT_BEE &&
- oType != OBJECT_WORM &&
- oType != OBJECT_MOTHER ) continue;
-
- m_totalDetect ++;
-
- oPos = pObj->RetPosition(0);
- distance = Math::Distance(oPos, iPos);
- if ( distance < min )
- {
- min = distance;
- pBest = pObj;
- }
- }
-
- UpdateInterface();
-
- if ( pBest == 0 ) return false;
- pos = pBest->RetPosition(0);
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoradar.h"
+
+#include "common/iman.h"
+#include "math/geometry.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+#include "ui/gauge.h"
+
+
+// Object's constructor.
+
+CAutoRadar::CAutoRadar(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+ m_phase = ARAP_WAIT;
+ m_totalDetect = 0;
+}
+
+// Object's destructor.
+
+CAutoRadar::~CAutoRadar()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoRadar::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoRadar::Init()
+{
+ m_phase = ARAP_SEARCH;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+
+ m_aTime = 0.0f;
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+}
+
+
+// Management of an event.
+
+bool CAutoRadar::EventProcess(const Event &event)
+{
+ Math::Vector pos, ePos;
+ float speed, angle, prog, freq, ampl;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_phase == ARAP_WAIT ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_aTime += event.rTime;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+
+ angle = m_object->RetAngleY(1);
+ angle += (Math::Rand()-0.2f)*0.5f;
+ m_object->SetAngleY(1, angle);
+
+ angle = m_object->RetAngleY(2);
+ angle += (Math::Rand()-0.8f)*1.0f;
+ m_object->SetAngleY(2, angle);
+
+ m_object->SetAngleX(3, (Math::Rand()-0.5f)*0.3f);
+
+ m_totalDetect = (int)(Math::Rand()*10.0f);
+ UpdateInterface();
+ }
+ return true;
+ }
+
+ if ( m_phase == ARAP_SEARCH )
+ {
+ if ( m_progress < 1.0f )
+ {
+ speed = Math::Min(10.0f, m_progress*50.0f);
+ angle = m_object->RetAngleY(1);
+ angle += event.rTime*speed;
+ m_object->SetAngleY(1, angle);
+ }
+ else
+ {
+ if ( !SearchEnemy(ePos) )
+ {
+ m_phase = ARAP_SEARCH;
+ m_progress = 10.0f/50.0f; // full speed immediately
+ m_speed = 1.0f/3.0f;
+ }
+ else
+ {
+ pos = m_object->RetPosition(0);
+ m_start = m_object->RetAngleY(1);
+ m_angle = m_start-Math::NormAngle(m_start)+Math::PI*2.0f;
+ m_angle += Math::RotateAngle(pos.x-ePos.x, ePos.z-pos.z);
+ m_angle += Math::PI-m_object->RetAngleY(0);
+
+ m_phase = ARAP_SHOW;
+ m_progress = 0.0f;
+ m_speed = 1.0f/(fabs(m_angle-m_start)/10.0f);
+ }
+ }
+ }
+
+ if ( m_phase == ARAP_SHOW )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = m_start + (m_angle-m_start)*m_progress;
+ m_object->SetAngleY(1, angle);
+ }
+ else
+ {
+ m_sound->Play(SOUND_RADAR, m_object->RetPosition(0));
+
+ m_phase = ARAP_SINUS;
+ m_progress = 0.0f;
+ m_speed = 1.0f/4.0f;
+ m_time = 0.0f;
+ }
+ }
+
+ if ( m_phase == ARAP_SINUS )
+ {
+ if ( m_progress < 1.0f )
+ {
+ prog = Math::Min(1.0f, m_progress*2.0f);
+ freq = 16.0f*(prog+1.0f);
+ ampl = 0.2f-prog*0.2f;
+ angle = m_angle + sinf(m_time*freq)*ampl;
+ m_object->SetAngleY(1, angle);
+ }
+ else
+ {
+ m_phase = ARAP_SEARCH;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ }
+ }
+
+ angle = -m_aTime*2.0f;
+ m_object->SetAngleY(2, angle);
+
+ angle = sinf(m_aTime*4.0f)*0.3f;
+ m_object->SetAngleX(3, angle);
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoRadar::RetError()
+{
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ return ERR_OK;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoRadar::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, dim, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*7.0f;
+ pos.y = oy+sy*0.6f;
+ dim.x = 160.0f/640.0f;
+ dim.y = 26.0f/480.0f;
+ pw->CreateGauge(pos, dim, 1, EVENT_OBJECT_GRADAR);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 105, EVENT_OBJECT_TYPE);
+
+ UpdateInterface();
+ return true;
+}
+
+// Updates the status of all interface buttons.
+
+void CAutoRadar::UpdateInterface()
+{
+ CWindow* pw;
+ CGauge* pg;
+ float level;
+
+ if ( !m_object->RetSelect() ) return;
+
+ CAuto::UpdateInterface();
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GRADAR);
+ if ( pg != 0 )
+ {
+ level = (float)m_totalDetect*(1.0f/8.0f);
+ if ( level > 1.0f ) level = 1.0f;
+ pg->SetLevel(level);
+ }
+}
+
+
+// Seeking the position of an enemy.
+
+bool CAutoRadar::SearchEnemy(Math::Vector &pos)
+{
+ CObject* pObj;
+ CObject* pBest = 0;
+ Math::Vector iPos, oPos;
+ ObjectType oType;
+ float distance, min;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+ min = 1000000.0f;
+ m_totalDetect = 0;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue;
+
+ oType = pObj->RetType();
+ if ( oType != OBJECT_ANT &&
+ oType != OBJECT_SPIDER &&
+ oType != OBJECT_BEE &&
+ oType != OBJECT_WORM &&
+ oType != OBJECT_MOTHER ) continue;
+
+ m_totalDetect ++;
+
+ oPos = pObj->RetPosition(0);
+ distance = Math::Distance(oPos, iPos);
+ if ( distance < min )
+ {
+ min = distance;
+ pBest = pObj;
+ }
+ }
+
+ UpdateInterface();
+
+ if ( pBest == 0 ) return false;
+ pos = pBest->RetPosition(0);
+ return true;
+}
+
+
diff --git a/src/object/auto/autoradar.h b/src/object/auto/autoradar.h
index 5a5020b..8b38ff9 100644
--- a/src/object/auto/autoradar.h
+++ b/src/object/auto/autoradar.h
@@ -1,64 +1,64 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoradar.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoRadarPhase
-{
- ARAP_WAIT = 1, // waiting
- ARAP_SEARCH = 2, // seeking
- ARAP_SHOW = 3, // watching
- ARAP_SINUS = 4, // oscillates
-};
-
-
-
-class CAutoRadar : public CAuto
-{
-public:
- CAutoRadar(CInstanceManager* iMan, CObject* object);
- ~CAutoRadar();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- bool CreateInterface(bool bSelect);
- Error RetError();
-
-protected:
- void UpdateInterface();
- bool SearchEnemy(Math::Vector &pos);
-
-protected:
- AutoRadarPhase m_phase;
- float m_progress;
- float m_speed;
- float m_aTime;
- float m_timeVirus;
- float m_lastParticule;
- float m_angle;
- float m_start;
- int m_totalDetect;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoradar.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoRadarPhase
+{
+ ARAP_WAIT = 1, // waiting
+ ARAP_SEARCH = 2, // seeking
+ ARAP_SHOW = 3, // watching
+ ARAP_SINUS = 4, // oscillates
+};
+
+
+
+class CAutoRadar : public CAuto
+{
+public:
+ CAutoRadar(CInstanceManager* iMan, CObject* object);
+ ~CAutoRadar();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ bool CreateInterface(bool bSelect);
+ Error RetError();
+
+protected:
+ void UpdateInterface();
+ bool SearchEnemy(Math::Vector &pos);
+
+protected:
+ AutoRadarPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_aTime;
+ float m_timeVirus;
+ float m_lastParticule;
+ float m_angle;
+ float m_start;
+ int m_totalDetect;
+};
+
diff --git a/src/object/auto/autorepair.cpp b/src/object/auto/autorepair.cpp
index b56f771..ad5deee 100644
--- a/src/object/auto/autorepair.cpp
+++ b/src/object/auto/autorepair.cpp
@@ -1,339 +1,339 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autorepair.h"
-
-#include "common/iman.h"
-#include "physics/physics.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-
-
-// Object's constructor.
-
-CAutoRepair::CAutoRepair(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
- m_phase = ARP_WAIT; // paused until the first Init ()
-}
-
-// Object's destructor.
-
-CAutoRepair::~CAutoRepair()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoRepair::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoRepair::Init()
-{
- m_phase = ARP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastParticule = 0.0f;
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoRepair::EventProcess(const Event &event)
-{
- CObject* vehicule;
- Math::Vector pos, speed;
- Math::Point dim;
- float angle, shield;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
- }
- return true;
- }
-
- if ( m_phase == ARP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- if ( SearchVehicle() == 0 )
- {
- m_phase = ARP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- else
- {
- m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 0.8f);
-
- m_phase = ARP_DOWN;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- }
- }
- }
-
- if ( m_phase == ARP_DOWN )
- {
- if ( m_progress < 1.0f )
- {
- angle = -m_progress*(Math::PI/2.0f)+Math::PI/2.0f;
- m_object->SetAngleZ(1, angle);
- }
- else
- {
- m_object->SetAngleZ(1, 0.0f);
- m_sound->Play(SOUND_REPAIR, m_object->RetPosition(0));
-
- m_phase = ARP_REPAIR;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ARP_REPAIR )
- {
- vehicule = SearchVehicle();
- if ( m_progress < 1.0f ||
- (vehicule != 0 && vehicule->RetShield() < 1.0f) )
- {
- if ( vehicule != 0 )
- {
- shield = vehicule->RetShield();
- shield += event.rTime*0.2f;
- if ( shield > 1.0f ) shield = 1.0f;
- vehicule->SetShield(shield);
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- pos.y += 1.0f;
- speed.x = (Math::Rand()-0.5f)*12.0f;
- speed.z = (Math::Rand()-0.5f)*12.0f;
- speed.y = Math::Rand()*15.0f;
- dim.x = Math::Rand()*6.0f+4.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
- }
- }
- else
- {
- m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 0.8f);
-
- m_phase = ARP_UP;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- }
- }
-
- if ( m_phase == ARP_UP )
- {
- if ( m_progress < 1.0f )
- {
- angle = -(1.0f-m_progress)*(Math::PI/2.0f)+Math::PI/2.0f;
- m_object->SetAngleZ(1, angle);
- }
- else
- {
- m_object->SetAngleZ(1, Math::PI/2.0f);
-
- m_phase = ARP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- return true;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoRepair::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 106, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-
-// Seeking the vehicle on the station.
-
-CObject* CAutoRepair::SearchVehicle()
-{
- CObject* pObj;
- CPhysics* physics;
- Math::Vector sPos, oPos;
- ObjectType type;
- float dist;
- int i;
-
- sPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr ) continue;
-
- physics = pObj->RetPhysics();
- if ( physics != 0 && !physics->RetLand() ) continue; // in flight?
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, sPos);
- if ( dist <= 5.0f ) return pObj;
- }
-
- return 0;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoRepair::RetError()
-{
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- return ERR_OK;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoRepair::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == ARP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoRepair::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoRepairPhase)OpInt(line, "aPhase", ARP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autorepair.h"
+
+#include "common/iman.h"
+#include "physics/physics.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+
+
+// Object's constructor.
+
+CAutoRepair::CAutoRepair(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+ m_phase = ARP_WAIT; // paused until the first Init ()
+}
+
+// Object's destructor.
+
+CAutoRepair::~CAutoRepair()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoRepair::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoRepair::Init()
+{
+ m_phase = ARP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoRepair::EventProcess(const Event &event)
+{
+ CObject* vehicule;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float angle, shield;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+ }
+ return true;
+ }
+
+ if ( m_phase == ARP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ if ( SearchVehicle() == 0 )
+ {
+ m_phase = ARP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ else
+ {
+ m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 0.8f);
+
+ m_phase = ARP_DOWN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ }
+ }
+ }
+
+ if ( m_phase == ARP_DOWN )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = -m_progress*(Math::PI/2.0f)+Math::PI/2.0f;
+ m_object->SetAngleZ(1, angle);
+ }
+ else
+ {
+ m_object->SetAngleZ(1, 0.0f);
+ m_sound->Play(SOUND_REPAIR, m_object->RetPosition(0));
+
+ m_phase = ARP_REPAIR;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ARP_REPAIR )
+ {
+ vehicule = SearchVehicle();
+ if ( m_progress < 1.0f ||
+ (vehicule != 0 && vehicule->RetShield() < 1.0f) )
+ {
+ if ( vehicule != 0 )
+ {
+ shield = vehicule->RetShield();
+ shield += event.rTime*0.2f;
+ if ( shield > 1.0f ) shield = 1.0f;
+ vehicule->SetShield(shield);
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ pos.y += 1.0f;
+ speed.x = (Math::Rand()-0.5f)*12.0f;
+ speed.z = (Math::Rand()-0.5f)*12.0f;
+ speed.y = Math::Rand()*15.0f;
+ dim.x = Math::Rand()*6.0f+4.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
+ }
+ }
+ else
+ {
+ m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 0.8f);
+
+ m_phase = ARP_UP;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ }
+ }
+
+ if ( m_phase == ARP_UP )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = -(1.0f-m_progress)*(Math::PI/2.0f)+Math::PI/2.0f;
+ m_object->SetAngleZ(1, angle);
+ }
+ else
+ {
+ m_object->SetAngleZ(1, Math::PI/2.0f);
+
+ m_phase = ARP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ return true;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoRepair::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 106, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+
+// Seeking the vehicle on the station.
+
+CObject* CAutoRepair::SearchVehicle()
+{
+ CObject* pObj;
+ CPhysics* physics;
+ Math::Vector sPos, oPos;
+ ObjectType type;
+ float dist;
+ int i;
+
+ sPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis &&
+ type != OBJECT_MOBILErt &&
+ type != OBJECT_MOBILErc &&
+ type != OBJECT_MOBILErr &&
+ type != OBJECT_MOBILErs &&
+ type != OBJECT_MOBILEsa &&
+ type != OBJECT_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_MOBILEdr ) continue;
+
+ physics = pObj->RetPhysics();
+ if ( physics != 0 && !physics->RetLand() ) continue; // in flight?
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, sPos);
+ if ( dist <= 5.0f ) return pObj;
+ }
+
+ return 0;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoRepair::RetError()
+{
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ return ERR_OK;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoRepair::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == ARP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoRepair::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoRepairPhase)OpInt(line, "aPhase", ARP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autorepair.h b/src/object/auto/autorepair.h
index 1178529..1279ba3 100644
--- a/src/object/auto/autorepair.h
+++ b/src/object/auto/autorepair.h
@@ -1,65 +1,65 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autorepair.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoRepairPhase
-{
- ARP_WAIT = 1, // expected metal
- ARP_DOWN = 2, // down the cover
- ARP_REPAIR = 3, // repair the vehicle
- ARP_UP = 4, // back cover
-
-};
-
-
-
-class CAutoRepair : public CAuto
-{
-public:
- CAutoRepair(CInstanceManager* iMan, CObject* object);
- ~CAutoRepair();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- CObject* SearchVehicle();
-
-protected:
- AutoRepairPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autorepair.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoRepairPhase
+{
+ ARP_WAIT = 1, // expected metal
+ ARP_DOWN = 2, // down the cover
+ ARP_REPAIR = 3, // repair the vehicle
+ ARP_UP = 4, // back cover
+
+};
+
+
+
+class CAutoRepair : public CAuto
+{
+public:
+ CAutoRepair(CInstanceManager* iMan, CObject* object);
+ ~CAutoRepair();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ CObject* SearchVehicle();
+
+protected:
+ AutoRepairPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+};
+
+
diff --git a/src/object/auto/autoresearch.cpp b/src/object/auto/autoresearch.cpp
index abf228c..bc6dbd0 100644
--- a/src/object/auto/autoresearch.cpp
+++ b/src/object/auto/autoresearch.cpp
@@ -1,608 +1,608 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoresearch.h"
-
-#include "common/global.h"
-#include "math/geometry.h"
-#include "object/robotmain.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/gauge.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-
-
-
-const float SEARCH_TIME = 30.0f; // duration of a research
-
-
-
-// Object's constructor.
-
-CAutoResearch::CAutoResearch(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- int i;
-
- for ( i=0 ; i<6 ; i++ )
- {
- m_partiStop[i] = -1;
- }
- m_channelSound = -1;
-
- Init();
-}
-
-// Object's destructor.
-
-CAutoResearch::~CAutoResearch()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoResearch::DeleteObject(bool bAll)
-{
- if ( m_channelSound != -1 )
- {
- m_sound->FlushEnvelope(m_channelSound);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_channelSound = -1;
- }
-
- FireStopUpdate(0.0f, false);
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoResearch::Init()
-{
- m_phase = ALP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastUpdateTime = 0.0f;
- m_lastParticule = 0.0f;
-}
-
-
-// Management of an event.
-
-bool CAutoResearch::EventProcess(const Event &event)
-{
- CObject* power;
- Math::Vector pos, speed;
- Error message;
- Math::Point dim;
- float angle, time;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
-
- if ( event.event == EVENT_UPDINTERFACE )
- {
- if ( m_object->RetSelect() ) CreateInterface(true);
- }
-
- if ( m_object->RetSelect() && // center selected?
- (event.event == EVENT_OBJECT_RTANK ||
- event.event == EVENT_OBJECT_RFLY ||
- event.event == EVENT_OBJECT_RTHUMP ||
- event.event == EVENT_OBJECT_RCANON ||
- event.event == EVENT_OBJECT_RTOWER ||
- event.event == EVENT_OBJECT_RPHAZER ||
- event.event == EVENT_OBJECT_RSHIELD ||
- event.event == EVENT_OBJECT_RATOMIC ) )
- {
- if ( m_phase != ALP_WAIT )
- {
- return false;
- }
-
- m_research = event.event;
-
- if ( TestResearch(m_research) )
- {
- m_displayText->DisplayError(ERR_RESEARCH_ALREADY, m_object);
- return false;
- }
-
- power = m_object->RetPower();
- if ( power == 0 )
- {
- m_displayText->DisplayError(ERR_RESEARCH_POWER, m_object);
- return false;
- }
- if ( power->RetCapacity() > 1.0f )
- {
- m_displayText->DisplayError(ERR_RESEARCH_TYPE, m_object);
- return false;
- }
- if ( power->RetEnergy() < 1.0f )
- {
- m_displayText->DisplayError(ERR_RESEARCH_ENERGY, m_object);
- return false;
- }
-
- time = SEARCH_TIME;
- if ( event.event == EVENT_OBJECT_RTANK ) time *= 0.3f;
- if ( event.event == EVENT_OBJECT_RFLY ) time *= 0.3f;
- if ( event.event == EVENT_OBJECT_RATOMIC ) time *= 2.0f;
-
- SetBusy(true);
- InitProgressTotal(time);
- UpdateInterface();
-
- m_channelSound = m_sound->Play(SOUND_RESEARCH, m_object->RetPosition(0), 0.0f, 1.0f, true);
- m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, time-4.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP);
-
- m_phase = ALP_SEARCH;
- m_progress = 0.0f;
- m_speed = 1.0f/time;
- return true;
- }
-
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
- }
- return true;
- }
-
- UpdateInterface(event.rTime);
- EventProgress(event.rTime);
-
- angle = m_time*0.1f;
- m_object->SetAngleY(1, angle); // rotates the antenna
-
- angle = (30.0f+sinf(m_time*0.3f)*20.0f)*Math::PI/180.0f;
- m_object->SetAngleZ(2, angle); // directs the antenna
-
- if ( m_phase == ALP_WAIT )
- {
- FireStopUpdate(m_progress, false); // extinguished
- return true;
- }
-
- if ( m_phase == ALP_SEARCH )
- {
- FireStopUpdate(m_progress, true); // flashes
- if ( m_progress < 1.0f )
- {
- power = m_object->RetPower();
- if ( power == 0 ) // more battery?
- {
- SetBusy(false);
- UpdateInterface();
-
- m_phase = ALP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- return true;
- }
- power->SetEnergy(1.0f-m_progress);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*6.0f;
- pos.z += (Math::Rand()-0.5f)*6.0f;
- pos.y += 11.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = Math::Rand()*20.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIVAPOR);
- }
- }
- else
- {
- SetResearch(m_research); // research done
- m_displayText->DisplayError(INFO_RESEARCH, m_object);
-
- message = ERR_OK;
- if ( m_research == EVENT_OBJECT_RTANK ) message = INFO_RESEARCHTANK;
- if ( m_research == EVENT_OBJECT_RFLY ) message = INFO_RESEARCHFLY;
- if ( m_research == EVENT_OBJECT_RTHUMP ) message = INFO_RESEARCHTHUMP;
- if ( m_research == EVENT_OBJECT_RCANON ) message = INFO_RESEARCHCANON;
- if ( m_research == EVENT_OBJECT_RTOWER ) message = INFO_RESEARCHTOWER;
- if ( m_research == EVENT_OBJECT_RPHAZER ) message = INFO_RESEARCHPHAZER;
- if ( m_research == EVENT_OBJECT_RSHIELD ) message = INFO_RESEARCHSHIELD;
- if ( m_research == EVENT_OBJECT_RATOMIC ) message = INFO_RESEARCHATOMIC;
- if ( message != ERR_OK )
- {
- m_displayText->DisplayError(message, m_object);
- }
-
- SetBusy(false);
- UpdateInterface();
-
- m_phase = ALP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoResearch::RetError()
-{
- CObject* power;
-
- if ( m_phase == ALP_SEARCH )
- {
- return ERR_OK;
- }
-
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- power = m_object->RetPower();
- if ( power == 0 )
- {
- return ERR_RESEARCH_POWER;
- }
- if ( power != 0 && power->RetCapacity() > 1.0f )
- {
- return ERR_RESEARCH_TYPE;
- }
- if ( power != 0 && power->RetEnergy() < 1.0f )
- {
- return ERR_RESEARCH_ENERGY;
- }
-
- return ERR_OK;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoResearch::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, dim, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- dim.x = 33.0f/640.0f;
- dim.y = 33.0f/480.0f;
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*7.0f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, dim, 64+0, EVENT_OBJECT_RTANK);
-
- pos.x = ox+sx*8.0f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, dim, 64+1, EVENT_OBJECT_RFLY);
-
- pos.x = ox+sx*9.0f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, dim, 64+3, EVENT_OBJECT_RCANON);
-
- pos.x = ox+sx*10.0f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, dim, 64+4, EVENT_OBJECT_RTOWER);
-
- pos.x = ox+sx*7.0f;
- pos.y = oy+sy*0.0f;
- pw->CreateButton(pos, dim, 64+7, EVENT_OBJECT_RATOMIC);
-
- pos.x = ox+sx*8.0f;
- pos.y = oy+sy*0.0f;
- pw->CreateButton(pos, dim, 64+2, EVENT_OBJECT_RTHUMP);
-
- pos.x = ox+sx*9.0f;
- pos.y = oy+sy*0.0f;
- pw->CreateButton(pos, dim, 64+6, EVENT_OBJECT_RSHIELD);
-
- pos.x = ox+sx*10.0f;
- pos.y = oy+sy*0.0f;
- pw->CreateButton(pos, dim, 64+5, EVENT_OBJECT_RPHAZER);
-
- pos.x = ox+sx*14.5f;
- pos.y = oy+sy*0;
- ddim.x = 14.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 102, EVENT_OBJECT_TYPE);
-
- UpdateInterface();
-
- return true;
-}
-
-// Updates the status of all interface buttons.
-
-void CAutoResearch::UpdateInterface()
-{
- CWindow* pw;
-
- if ( !m_object->RetSelect() ) return;
-
- CAuto::UpdateInterface();
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- DeadInterface(pw, EVENT_OBJECT_RTANK, g_researchEnable&RESEARCH_TANK);
- DeadInterface(pw, EVENT_OBJECT_RFLY, g_researchEnable&RESEARCH_FLY);
- DeadInterface(pw, EVENT_OBJECT_RTHUMP, g_researchEnable&RESEARCH_THUMP);
- DeadInterface(pw, EVENT_OBJECT_RCANON, g_researchEnable&RESEARCH_CANON);
- DeadInterface(pw, EVENT_OBJECT_RTOWER, g_researchEnable&RESEARCH_TOWER);
- DeadInterface(pw, EVENT_OBJECT_RPHAZER, g_researchEnable&RESEARCH_PHAZER);
- DeadInterface(pw, EVENT_OBJECT_RSHIELD, g_researchEnable&RESEARCH_SHIELD);
- DeadInterface(pw, EVENT_OBJECT_RATOMIC, g_researchEnable&RESEARCH_ATOMIC);
-
- OkayButton(pw, EVENT_OBJECT_RTANK);
- OkayButton(pw, EVENT_OBJECT_RFLY);
- OkayButton(pw, EVENT_OBJECT_RTHUMP);
- OkayButton(pw, EVENT_OBJECT_RCANON);
- OkayButton(pw, EVENT_OBJECT_RTOWER);
- OkayButton(pw, EVENT_OBJECT_RPHAZER);
- OkayButton(pw, EVENT_OBJECT_RSHIELD);
- OkayButton(pw, EVENT_OBJECT_RATOMIC);
-
- VisibleInterface(pw, EVENT_OBJECT_RTANK, !m_bBusy);
- VisibleInterface(pw, EVENT_OBJECT_RFLY, !m_bBusy);
- VisibleInterface(pw, EVENT_OBJECT_RTHUMP, !m_bBusy);
- VisibleInterface(pw, EVENT_OBJECT_RCANON, !m_bBusy);
- VisibleInterface(pw, EVENT_OBJECT_RTOWER, !m_bBusy);
- VisibleInterface(pw, EVENT_OBJECT_RPHAZER, !m_bBusy);
- VisibleInterface(pw, EVENT_OBJECT_RSHIELD, !m_bBusy);
- VisibleInterface(pw, EVENT_OBJECT_RATOMIC, !m_bBusy);
-}
-
-// Updates the state of all buttons on the interface,
-// following the time that elapses ...
-
-void CAutoResearch::UpdateInterface(float rTime)
-{
- CWindow* pw;
- CGauge* pg;
- CObject* power;
- float energy;
-
- CAuto::UpdateInterface(rTime);
-
- if ( m_time < m_lastUpdateTime+0.1f ) return;
- m_lastUpdateTime = m_time;
-
- if ( !m_object->RetSelect() ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
- if ( pg != 0 )
- {
- energy = 0.0f;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- }
- pg->SetLevel(energy);
- }
-}
-
-// Research shows already performed button.
-
-void CAutoResearch::OkayButton(CWindow *pw, EventMsg event)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_OKAY, TestResearch(event));
-}
-
-
-// Test whether a search has already been done.
-
-bool CAutoResearch::TestResearch(EventMsg event)
-{
- if ( event == EVENT_OBJECT_RTANK ) return (g_researchDone & RESEARCH_TANK );
- if ( event == EVENT_OBJECT_RFLY ) return (g_researchDone & RESEARCH_FLY );
- if ( event == EVENT_OBJECT_RTHUMP ) return (g_researchDone & RESEARCH_THUMP );
- if ( event == EVENT_OBJECT_RCANON ) return (g_researchDone & RESEARCH_CANON );
- if ( event == EVENT_OBJECT_RTOWER ) return (g_researchDone & RESEARCH_TOWER );
- if ( event == EVENT_OBJECT_RPHAZER ) return (g_researchDone & RESEARCH_PHAZER );
- if ( event == EVENT_OBJECT_RSHIELD ) return (g_researchDone & RESEARCH_SHIELD);
- if ( event == EVENT_OBJECT_RATOMIC ) return (g_researchDone & RESEARCH_ATOMIC);
-
- return false;
-}
-
-// Indicates a search as made.
-
-void CAutoResearch::SetResearch(EventMsg event)
-{
- Event newEvent;
-
- if ( event == EVENT_OBJECT_RTANK ) g_researchDone |= RESEARCH_TANK;
- if ( event == EVENT_OBJECT_RFLY ) g_researchDone |= RESEARCH_FLY;
- if ( event == EVENT_OBJECT_RTHUMP ) g_researchDone |= RESEARCH_THUMP;
- if ( event == EVENT_OBJECT_RCANON ) g_researchDone |= RESEARCH_CANON;
- if ( event == EVENT_OBJECT_RTOWER ) g_researchDone |= RESEARCH_TOWER;
- if ( event == EVENT_OBJECT_RPHAZER ) g_researchDone |= RESEARCH_PHAZER;
- if ( event == EVENT_OBJECT_RSHIELD ) g_researchDone |= RESEARCH_SHIELD;
- if ( event == EVENT_OBJECT_RATOMIC ) g_researchDone |= RESEARCH_ATOMIC;
-
- m_main->WriteFreeParam();
-
- m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
- m_event->AddEvent(newEvent);
- UpdateInterface();
-}
-
-
-// Updates the stop lights.
-
-void CAutoResearch::FireStopUpdate(float progress, bool bLightOn)
-{
- Math::Matrix* mat;
- Math::Vector pos, speed;
- Math::Point dim;
- int i;
-
- static float listpos[12] =
- {
- 9.5f, 0.0f,
- 4.7f, 8.2f,
- -4.7f, 8.2f,
- -9.5f, 0.0f,
- -4.7f, -8.2f,
- 4.7f, -8.2f,
- };
-
- if ( !bLightOn ) // �teint ?
- {
- for ( i=0 ; i<6 ; i++ )
- {
- if ( m_partiStop[i] != -1 )
- {
- m_particule->DeleteParticule(m_partiStop[i]);
- m_partiStop[i] = -1;
- }
- }
- return;
- }
-
- mat = m_object->RetWorldMatrix(0);
-
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 2.0f;
- dim.y = dim.x;
-
- for ( i=0 ; i<6 ; i++ )
- {
- if ( Math::Mod(progress, 0.025f) < 0.005f )
- {
- if ( m_partiStop[i] != -1 )
- {
- m_particule->DeleteParticule(m_partiStop[i]);
- m_partiStop[i] = -1;
- }
- }
- else
- {
- if ( m_partiStop[i] == -1 )
- {
- pos.x = listpos[i*2+0];
- pos.y = 11.5f;
- pos.z = listpos[i*2+1];
- pos = Math::Transform(*mat, pos);
- m_partiStop[i] = m_particule->CreateParticule(pos, speed,
- dim, PARTISELY,
- 1.0f, 0.0f, 0.0f);
- }
- }
- }
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoResearch::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == ALP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- sprintf(name, " aResearch=%d", m_research);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoResearch::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoResearchPhase)OpInt(line, "aPhase", ALP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
- m_research = (EventMsg)OpInt(line, "aResearch", 0);
-
- m_lastUpdateTime = 0.0f;
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoresearch.h"
+
+#include "common/global.h"
+#include "math/geometry.h"
+#include "object/robotmain.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/gauge.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+
+
+
+const float SEARCH_TIME = 30.0f; // duration of a research
+
+
+
+// Object's constructor.
+
+CAutoResearch::CAutoResearch(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ int i;
+
+ for ( i=0 ; i<6 ; i++ )
+ {
+ m_partiStop[i] = -1;
+ }
+ m_channelSound = -1;
+
+ Init();
+}
+
+// Object's destructor.
+
+CAutoResearch::~CAutoResearch()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoResearch::DeleteObject(bool bAll)
+{
+ if ( m_channelSound != -1 )
+ {
+ m_sound->FlushEnvelope(m_channelSound);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_channelSound = -1;
+ }
+
+ FireStopUpdate(0.0f, false);
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoResearch::Init()
+{
+ m_phase = ALP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastUpdateTime = 0.0f;
+ m_lastParticule = 0.0f;
+}
+
+
+// Management of an event.
+
+bool CAutoResearch::EventProcess(const Event &event)
+{
+ CObject* power;
+ Math::Vector pos, speed;
+ Error message;
+ Math::Point dim;
+ float angle, time;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+
+ if ( event.event == EVENT_UPDINTERFACE )
+ {
+ if ( m_object->RetSelect() ) CreateInterface(true);
+ }
+
+ if ( m_object->RetSelect() && // center selected?
+ (event.event == EVENT_OBJECT_RTANK ||
+ event.event == EVENT_OBJECT_RFLY ||
+ event.event == EVENT_OBJECT_RTHUMP ||
+ event.event == EVENT_OBJECT_RCANON ||
+ event.event == EVENT_OBJECT_RTOWER ||
+ event.event == EVENT_OBJECT_RPHAZER ||
+ event.event == EVENT_OBJECT_RSHIELD ||
+ event.event == EVENT_OBJECT_RATOMIC ) )
+ {
+ if ( m_phase != ALP_WAIT )
+ {
+ return false;
+ }
+
+ m_research = event.event;
+
+ if ( TestResearch(m_research) )
+ {
+ m_displayText->DisplayError(ERR_RESEARCH_ALREADY, m_object);
+ return false;
+ }
+
+ power = m_object->RetPower();
+ if ( power == 0 )
+ {
+ m_displayText->DisplayError(ERR_RESEARCH_POWER, m_object);
+ return false;
+ }
+ if ( power->RetCapacity() > 1.0f )
+ {
+ m_displayText->DisplayError(ERR_RESEARCH_TYPE, m_object);
+ return false;
+ }
+ if ( power->RetEnergy() < 1.0f )
+ {
+ m_displayText->DisplayError(ERR_RESEARCH_ENERGY, m_object);
+ return false;
+ }
+
+ time = SEARCH_TIME;
+ if ( event.event == EVENT_OBJECT_RTANK ) time *= 0.3f;
+ if ( event.event == EVENT_OBJECT_RFLY ) time *= 0.3f;
+ if ( event.event == EVENT_OBJECT_RATOMIC ) time *= 2.0f;
+
+ SetBusy(true);
+ InitProgressTotal(time);
+ UpdateInterface();
+
+ m_channelSound = m_sound->Play(SOUND_RESEARCH, m_object->RetPosition(0), 0.0f, 1.0f, true);
+ m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, time-4.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP);
+
+ m_phase = ALP_SEARCH;
+ m_progress = 0.0f;
+ m_speed = 1.0f/time;
+ return true;
+ }
+
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+ }
+ return true;
+ }
+
+ UpdateInterface(event.rTime);
+ EventProgress(event.rTime);
+
+ angle = m_time*0.1f;
+ m_object->SetAngleY(1, angle); // rotates the antenna
+
+ angle = (30.0f+sinf(m_time*0.3f)*20.0f)*Math::PI/180.0f;
+ m_object->SetAngleZ(2, angle); // directs the antenna
+
+ if ( m_phase == ALP_WAIT )
+ {
+ FireStopUpdate(m_progress, false); // extinguished
+ return true;
+ }
+
+ if ( m_phase == ALP_SEARCH )
+ {
+ FireStopUpdate(m_progress, true); // flashes
+ if ( m_progress < 1.0f )
+ {
+ power = m_object->RetPower();
+ if ( power == 0 ) // more battery?
+ {
+ SetBusy(false);
+ UpdateInterface();
+
+ m_phase = ALP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ return true;
+ }
+ power->SetEnergy(1.0f-m_progress);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*6.0f;
+ pos.z += (Math::Rand()-0.5f)*6.0f;
+ pos.y += 11.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = Math::Rand()*20.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIVAPOR);
+ }
+ }
+ else
+ {
+ SetResearch(m_research); // research done
+ m_displayText->DisplayError(INFO_RESEARCH, m_object);
+
+ message = ERR_OK;
+ if ( m_research == EVENT_OBJECT_RTANK ) message = INFO_RESEARCHTANK;
+ if ( m_research == EVENT_OBJECT_RFLY ) message = INFO_RESEARCHFLY;
+ if ( m_research == EVENT_OBJECT_RTHUMP ) message = INFO_RESEARCHTHUMP;
+ if ( m_research == EVENT_OBJECT_RCANON ) message = INFO_RESEARCHCANON;
+ if ( m_research == EVENT_OBJECT_RTOWER ) message = INFO_RESEARCHTOWER;
+ if ( m_research == EVENT_OBJECT_RPHAZER ) message = INFO_RESEARCHPHAZER;
+ if ( m_research == EVENT_OBJECT_RSHIELD ) message = INFO_RESEARCHSHIELD;
+ if ( m_research == EVENT_OBJECT_RATOMIC ) message = INFO_RESEARCHATOMIC;
+ if ( message != ERR_OK )
+ {
+ m_displayText->DisplayError(message, m_object);
+ }
+
+ SetBusy(false);
+ UpdateInterface();
+
+ m_phase = ALP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoResearch::RetError()
+{
+ CObject* power;
+
+ if ( m_phase == ALP_SEARCH )
+ {
+ return ERR_OK;
+ }
+
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ power = m_object->RetPower();
+ if ( power == 0 )
+ {
+ return ERR_RESEARCH_POWER;
+ }
+ if ( power != 0 && power->RetCapacity() > 1.0f )
+ {
+ return ERR_RESEARCH_TYPE;
+ }
+ if ( power != 0 && power->RetEnergy() < 1.0f )
+ {
+ return ERR_RESEARCH_ENERGY;
+ }
+
+ return ERR_OK;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoResearch::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, dim, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ dim.x = 33.0f/640.0f;
+ dim.y = 33.0f/480.0f;
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*7.0f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, dim, 64+0, EVENT_OBJECT_RTANK);
+
+ pos.x = ox+sx*8.0f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, dim, 64+1, EVENT_OBJECT_RFLY);
+
+ pos.x = ox+sx*9.0f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, dim, 64+3, EVENT_OBJECT_RCANON);
+
+ pos.x = ox+sx*10.0f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, dim, 64+4, EVENT_OBJECT_RTOWER);
+
+ pos.x = ox+sx*7.0f;
+ pos.y = oy+sy*0.0f;
+ pw->CreateButton(pos, dim, 64+7, EVENT_OBJECT_RATOMIC);
+
+ pos.x = ox+sx*8.0f;
+ pos.y = oy+sy*0.0f;
+ pw->CreateButton(pos, dim, 64+2, EVENT_OBJECT_RTHUMP);
+
+ pos.x = ox+sx*9.0f;
+ pos.y = oy+sy*0.0f;
+ pw->CreateButton(pos, dim, 64+6, EVENT_OBJECT_RSHIELD);
+
+ pos.x = ox+sx*10.0f;
+ pos.y = oy+sy*0.0f;
+ pw->CreateButton(pos, dim, 64+5, EVENT_OBJECT_RPHAZER);
+
+ pos.x = ox+sx*14.5f;
+ pos.y = oy+sy*0;
+ ddim.x = 14.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 102, EVENT_OBJECT_TYPE);
+
+ UpdateInterface();
+
+ return true;
+}
+
+// Updates the status of all interface buttons.
+
+void CAutoResearch::UpdateInterface()
+{
+ CWindow* pw;
+
+ if ( !m_object->RetSelect() ) return;
+
+ CAuto::UpdateInterface();
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ DeadInterface(pw, EVENT_OBJECT_RTANK, g_researchEnable&RESEARCH_TANK);
+ DeadInterface(pw, EVENT_OBJECT_RFLY, g_researchEnable&RESEARCH_FLY);
+ DeadInterface(pw, EVENT_OBJECT_RTHUMP, g_researchEnable&RESEARCH_THUMP);
+ DeadInterface(pw, EVENT_OBJECT_RCANON, g_researchEnable&RESEARCH_CANON);
+ DeadInterface(pw, EVENT_OBJECT_RTOWER, g_researchEnable&RESEARCH_TOWER);
+ DeadInterface(pw, EVENT_OBJECT_RPHAZER, g_researchEnable&RESEARCH_PHAZER);
+ DeadInterface(pw, EVENT_OBJECT_RSHIELD, g_researchEnable&RESEARCH_SHIELD);
+ DeadInterface(pw, EVENT_OBJECT_RATOMIC, g_researchEnable&RESEARCH_ATOMIC);
+
+ OkayButton(pw, EVENT_OBJECT_RTANK);
+ OkayButton(pw, EVENT_OBJECT_RFLY);
+ OkayButton(pw, EVENT_OBJECT_RTHUMP);
+ OkayButton(pw, EVENT_OBJECT_RCANON);
+ OkayButton(pw, EVENT_OBJECT_RTOWER);
+ OkayButton(pw, EVENT_OBJECT_RPHAZER);
+ OkayButton(pw, EVENT_OBJECT_RSHIELD);
+ OkayButton(pw, EVENT_OBJECT_RATOMIC);
+
+ VisibleInterface(pw, EVENT_OBJECT_RTANK, !m_bBusy);
+ VisibleInterface(pw, EVENT_OBJECT_RFLY, !m_bBusy);
+ VisibleInterface(pw, EVENT_OBJECT_RTHUMP, !m_bBusy);
+ VisibleInterface(pw, EVENT_OBJECT_RCANON, !m_bBusy);
+ VisibleInterface(pw, EVENT_OBJECT_RTOWER, !m_bBusy);
+ VisibleInterface(pw, EVENT_OBJECT_RPHAZER, !m_bBusy);
+ VisibleInterface(pw, EVENT_OBJECT_RSHIELD, !m_bBusy);
+ VisibleInterface(pw, EVENT_OBJECT_RATOMIC, !m_bBusy);
+}
+
+// Updates the state of all buttons on the interface,
+// following the time that elapses ...
+
+void CAutoResearch::UpdateInterface(float rTime)
+{
+ CWindow* pw;
+ CGauge* pg;
+ CObject* power;
+ float energy;
+
+ CAuto::UpdateInterface(rTime);
+
+ if ( m_time < m_lastUpdateTime+0.1f ) return;
+ m_lastUpdateTime = m_time;
+
+ if ( !m_object->RetSelect() ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
+ if ( pg != 0 )
+ {
+ energy = 0.0f;
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ }
+ pg->SetLevel(energy);
+ }
+}
+
+// Research shows already performed button.
+
+void CAutoResearch::OkayButton(CWindow *pw, EventMsg event)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_OKAY, TestResearch(event));
+}
+
+
+// Test whether a search has already been done.
+
+bool CAutoResearch::TestResearch(EventMsg event)
+{
+ if ( event == EVENT_OBJECT_RTANK ) return (g_researchDone & RESEARCH_TANK );
+ if ( event == EVENT_OBJECT_RFLY ) return (g_researchDone & RESEARCH_FLY );
+ if ( event == EVENT_OBJECT_RTHUMP ) return (g_researchDone & RESEARCH_THUMP );
+ if ( event == EVENT_OBJECT_RCANON ) return (g_researchDone & RESEARCH_CANON );
+ if ( event == EVENT_OBJECT_RTOWER ) return (g_researchDone & RESEARCH_TOWER );
+ if ( event == EVENT_OBJECT_RPHAZER ) return (g_researchDone & RESEARCH_PHAZER );
+ if ( event == EVENT_OBJECT_RSHIELD ) return (g_researchDone & RESEARCH_SHIELD);
+ if ( event == EVENT_OBJECT_RATOMIC ) return (g_researchDone & RESEARCH_ATOMIC);
+
+ return false;
+}
+
+// Indicates a search as made.
+
+void CAutoResearch::SetResearch(EventMsg event)
+{
+ Event newEvent;
+
+ if ( event == EVENT_OBJECT_RTANK ) g_researchDone |= RESEARCH_TANK;
+ if ( event == EVENT_OBJECT_RFLY ) g_researchDone |= RESEARCH_FLY;
+ if ( event == EVENT_OBJECT_RTHUMP ) g_researchDone |= RESEARCH_THUMP;
+ if ( event == EVENT_OBJECT_RCANON ) g_researchDone |= RESEARCH_CANON;
+ if ( event == EVENT_OBJECT_RTOWER ) g_researchDone |= RESEARCH_TOWER;
+ if ( event == EVENT_OBJECT_RPHAZER ) g_researchDone |= RESEARCH_PHAZER;
+ if ( event == EVENT_OBJECT_RSHIELD ) g_researchDone |= RESEARCH_SHIELD;
+ if ( event == EVENT_OBJECT_RATOMIC ) g_researchDone |= RESEARCH_ATOMIC;
+
+ m_main->WriteFreeParam();
+
+ m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
+ m_event->AddEvent(newEvent);
+ UpdateInterface();
+}
+
+
+// Updates the stop lights.
+
+void CAutoResearch::FireStopUpdate(float progress, bool bLightOn)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ int i;
+
+ static float listpos[12] =
+ {
+ 9.5f, 0.0f,
+ 4.7f, 8.2f,
+ -4.7f, 8.2f,
+ -9.5f, 0.0f,
+ -4.7f, -8.2f,
+ 4.7f, -8.2f,
+ };
+
+ if ( !bLightOn ) // �teint ?
+ {
+ for ( i=0 ; i<6 ; i++ )
+ {
+ if ( m_partiStop[i] != -1 )
+ {
+ m_particule->DeleteParticule(m_partiStop[i]);
+ m_partiStop[i] = -1;
+ }
+ }
+ return;
+ }
+
+ mat = m_object->RetWorldMatrix(0);
+
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 2.0f;
+ dim.y = dim.x;
+
+ for ( i=0 ; i<6 ; i++ )
+ {
+ if ( Math::Mod(progress, 0.025f) < 0.005f )
+ {
+ if ( m_partiStop[i] != -1 )
+ {
+ m_particule->DeleteParticule(m_partiStop[i]);
+ m_partiStop[i] = -1;
+ }
+ }
+ else
+ {
+ if ( m_partiStop[i] == -1 )
+ {
+ pos.x = listpos[i*2+0];
+ pos.y = 11.5f;
+ pos.z = listpos[i*2+1];
+ pos = Math::Transform(*mat, pos);
+ m_partiStop[i] = m_particule->CreateParticule(pos, speed,
+ dim, PARTISELY,
+ 1.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoResearch::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == ALP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ sprintf(name, " aResearch=%d", m_research);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoResearch::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoResearchPhase)OpInt(line, "aPhase", ALP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+ m_research = (EventMsg)OpInt(line, "aResearch", 0);
+
+ m_lastUpdateTime = 0.0f;
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autoresearch.h b/src/object/auto/autoresearch.h
index c36edd6..b60f4bd 100644
--- a/src/object/auto/autoresearch.h
+++ b/src/object/auto/autoresearch.h
@@ -1,70 +1,70 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoresearch.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoResearchPhase
-{
- ALP_WAIT = 1,
- ALP_SEARCH = 2, // research in progress
-};
-
-
-
-class CAutoResearch : public CAuto
-{
-public:
- CAutoResearch(CInstanceManager* iMan, CObject* object);
- ~CAutoResearch();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- void UpdateInterface();
- void UpdateInterface(float rTime);
- void OkayButton(CWindow *pw, EventMsg event);
- bool TestResearch(EventMsg event);
- void SetResearch(EventMsg event);
- void FireStopUpdate(float progress, bool bLightOn);
-
-protected:
- AutoResearchPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastUpdateTime;
- float m_lastParticule;
- EventMsg m_research;
- int m_partiStop[6];
- int m_channelSound;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoresearch.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoResearchPhase
+{
+ ALP_WAIT = 1,
+ ALP_SEARCH = 2, // research in progress
+};
+
+
+
+class CAutoResearch : public CAuto
+{
+public:
+ CAutoResearch(CInstanceManager* iMan, CObject* object);
+ ~CAutoResearch();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ void UpdateInterface();
+ void UpdateInterface(float rTime);
+ void OkayButton(CWindow *pw, EventMsg event);
+ bool TestResearch(EventMsg event);
+ void SetResearch(EventMsg event);
+ void FireStopUpdate(float progress, bool bLightOn);
+
+protected:
+ AutoResearchPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastUpdateTime;
+ float m_lastParticule;
+ EventMsg m_research;
+ int m_partiStop[6];
+ int m_channelSound;
+};
+
diff --git a/src/object/auto/autoroot.cpp b/src/object/auto/autoroot.cpp
index cd3435e..9282a01 100644
--- a/src/object/auto/autoroot.cpp
+++ b/src/object/auto/autoroot.cpp
@@ -1,120 +1,120 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoroot.h"
-
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "math/geometry.h"
-
-
-
-
-// Object's constructor.
-
-CAutoRoot::CAutoRoot(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
-}
-
-// Object's destructor.
-
-CAutoRoot::~CAutoRoot()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoRoot::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoRoot::Init()
-{
- Math::Matrix* mat;
- Math::Vector pos, speed;
- Math::Point dim;
-
- m_time = 0.0f;
- m_lastParticule = 0.0f;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(-5.0f, 28.0f, -4.0f); // peak position
- pos = Math::Transform(*mat, pos);
- m_center = pos;
-
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 100.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(m_center, speed, dim, PARTISPHERE5, 0.5f, 0.0f, 0.0f);
-
- m_terrain->AddFlyingLimit(pos, 100.0f, 80.0f, pos.y-60.0f);
-}
-
-
-// Management of an event.
-
-bool CAutoRoot::EventProcess(const Event &event)
-{
- Math::Vector pos, speed;
- Math::Point dim;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_object->SetZoomX(1, 1.0f+sinf(m_time*2.0f)*0.2f);
- m_object->SetZoomY(1, 1.0f+sinf(m_time*2.3f)*0.2f);
- m_object->SetZoomZ(1, 1.0f+sinf(m_time*2.7f)*0.2f);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_center;
- pos.x += (Math::Rand()-0.5f)*8.0f;
- pos.z += (Math::Rand()-0.5f)*8.0f;
- pos.y += 0.0f;
- speed.x = (Math::Rand()-0.5f)*12.0f;
- speed.z = (Math::Rand()-0.5f)*12.0f;
- speed.y = Math::Rand()*12.0f;
- dim.x = Math::Rand()*6.0f+4.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIROOT, 1.0f, 0.0f, 0.0f);
- }
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoRoot::RetError()
-{
- return ERR_OK;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoroot.h"
+
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "math/geometry.h"
+
+
+
+
+// Object's constructor.
+
+CAutoRoot::CAutoRoot(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+}
+
+// Object's destructor.
+
+CAutoRoot::~CAutoRoot()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoRoot::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoRoot::Init()
+{
+ Math::Matrix* mat;
+ Math::Vector pos, speed;
+ Math::Point dim;
+
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(-5.0f, 28.0f, -4.0f); // peak position
+ pos = Math::Transform(*mat, pos);
+ m_center = pos;
+
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 100.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(m_center, speed, dim, PARTISPHERE5, 0.5f, 0.0f, 0.0f);
+
+ m_terrain->AddFlyingLimit(pos, 100.0f, 80.0f, pos.y-60.0f);
+}
+
+
+// Management of an event.
+
+bool CAutoRoot::EventProcess(const Event &event)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_object->SetZoomX(1, 1.0f+sinf(m_time*2.0f)*0.2f);
+ m_object->SetZoomY(1, 1.0f+sinf(m_time*2.3f)*0.2f);
+ m_object->SetZoomZ(1, 1.0f+sinf(m_time*2.7f)*0.2f);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_center;
+ pos.x += (Math::Rand()-0.5f)*8.0f;
+ pos.z += (Math::Rand()-0.5f)*8.0f;
+ pos.y += 0.0f;
+ speed.x = (Math::Rand()-0.5f)*12.0f;
+ speed.z = (Math::Rand()-0.5f)*12.0f;
+ speed.y = Math::Rand()*12.0f;
+ dim.x = Math::Rand()*6.0f+4.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIROOT, 1.0f, 0.0f, 0.0f);
+ }
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoRoot::RetError()
+{
+ return ERR_OK;
+}
+
+
diff --git a/src/object/auto/autoroot.h b/src/object/auto/autoroot.h
index 8bf397d..1ecd5ba 100644
--- a/src/object/auto/autoroot.h
+++ b/src/object/auto/autoroot.h
@@ -1,44 +1,44 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoroot.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-class CAutoRoot : public CAuto
-{
-public:
- CAutoRoot(CInstanceManager* iMan, CObject* object);
- ~CAutoRoot();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
-protected:
-
-protected:
- float m_lastParticule;
- Math::Vector m_center;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoroot.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+class CAutoRoot : public CAuto
+{
+public:
+ CAutoRoot(CInstanceManager* iMan, CObject* object);
+ ~CAutoRoot();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+protected:
+
+protected:
+ float m_lastParticule;
+ Math::Vector m_center;
+};
+
diff --git a/src/object/auto/autosafe.cpp b/src/object/auto/autosafe.cpp
index 6965851..11aac18 100644
--- a/src/object/auto/autosafe.cpp
+++ b/src/object/auto/autosafe.cpp
@@ -1,612 +1,612 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autosafe.h"
-
-#include "common/iman.h"
-#include "math/geometry.h"
-#include "object/robotmain.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-
-
-const float OPEN_DELAY = 8.0f; // duration of opening
-
-
-// Object's constructor.
-
-CAutoSafe::CAutoSafe(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- int i;
-
- for ( i=0 ; i<4 ; i++ )
- {
- m_bKey[i] = false;
- m_keyParti[i] = -1;
- }
-
- m_bLock = false;
- m_lastParticule = 0.0f;
- m_channelSound = -1;
- Init();
-}
-
-// Object's destructor.
-
-CAutoSafe::~CAutoSafe()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoSafe::DeleteObject(bool bAll)
-{
- CObject* pObj;
-
- pObj = SearchVehicle();
- if ( pObj != 0 )
- {
- pObj->DeleteObject();
- delete pObj;
- }
-
- if ( m_channelSound != -1 )
- {
- m_sound->FlushEnvelope(m_channelSound);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_channelSound = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoSafe::Init()
-{
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastParticule = 0.0f;
-
- m_countKeys = 0;
- m_actualAngle = 0.0f;
- m_finalAngle = 0.0f;
-
- m_phase = ASAP_WAIT; // waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoSafe::EventProcess(const Event &event)
-{
- CObject* pObj;
- Math::Vector pos, speed;
- Math::Point dim;
- int i, count;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
- }
- return true;
- }
-
- EventProgress(event.rTime);
-
- if ( !m_bLock )
- {
- pObj = SearchVehicle();
- if ( pObj != 0 )
- {
- pObj->SetLock(true); // object not yet usable
- m_main->CreateShortcuts();
- m_bLock = true;
- }
- }
-
- if ( m_phase == ASAP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- count = CountKeys(); // count these key
- if ( count != m_countKeys )
- {
- m_countKeys = count;
-
- if ( count == 0 ) m_finalAngle = 0.0f*Math::PI/180.0f;
- if ( count == 1 ) m_finalAngle = 5.0f*Math::PI/180.0f;
- if ( count == 2 ) m_finalAngle = 10.0f*Math::PI/180.0f;
- if ( count == 3 ) m_finalAngle = 15.0f*Math::PI/180.0f;
- if ( count == 4 ) m_finalAngle = 120.0f*Math::PI/180.0f;
-
- if ( count == 4 ) // all the keys?
- {
- LockKeys();
-
- m_channelSound = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 1.0f, 0.25f, true);
- m_sound->AddEnvelope(m_channelSound, 1.0f, 2.00f, OPEN_DELAY, SOPER_STOP);
-
- m_phase = ASAP_OPEN;
- m_progress = 0.0f;
- m_speed = 1.0f/OPEN_DELAY;
- return true;
- }
- else
- {
- m_channelSound = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 1.0f, 0.25f, true);
- m_sound->AddEnvelope(m_channelSound, 1.0f, 0.35f, 0.5f, SOPER_STOP);
- }
- }
-
- m_phase = ASAP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ASAP_OPEN )
- {
- if ( m_progress < 1.0f )
- {
- DownKeys(m_progress);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- for ( i=0 ; i<10 ; i++ )
- {
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- speed.x = (Math::Rand()-0.5f)*4.0f;
- speed.z = (Math::Rand()-0.5f)*4.0f;
- speed.y = Math::Rand()*15.0f;
- dim.x = Math::Rand()*6.0f+4.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
- }
-
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- speed.x = (Math::Rand()-0.5f)*4.0f;
- speed.z = (Math::Rand()-0.5f)*4.0f;
- speed.y = Math::Rand()*10.0f;
- dim.x = Math::Rand()*3.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 1.0f, 0.0f, 0.0f);
-
- for ( i=0 ; i<4 ; i++ )
- {
- pos = m_keyPos[i];
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = 1.0f+Math::Rand()*1.0f;
- dim.x = Math::Rand()*1.5f+1.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 0.0f);
- }
- }
- }
- else
- {
- DeleteKeys();
-
- pObj = SearchVehicle();
- if ( pObj != 0 )
- {
- pObj->SetLock(false); // object usable
- m_main->CreateShortcuts();
- }
-
- m_object->FlushCrashShere();
- m_object->SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 0.0f);
-
- m_sound->Play(SOUND_FINDING, m_object->RetPosition(0));
-
- m_phase = ASAP_FINISH;
- m_progress = 0.0f;
- m_speed = 1.0f/100.0f;
- }
- }
-
- if ( m_phase == ASAP_FINISH )
- {
- if ( m_progress >= 1.0f )
- {
- m_phase = ASAP_FINISH;
- m_progress = 0.0f;
- m_speed = 1.0f/100.0f;
- }
- }
-
- // Opens or closes the doors.
- if ( m_actualAngle != m_finalAngle )
- {
- if ( m_actualAngle < m_finalAngle )
- {
- m_actualAngle += (105.0f*Math::PI/180.0f)*event.rTime/OPEN_DELAY;
- if ( m_actualAngle > m_finalAngle ) m_actualAngle = m_finalAngle;
- }
- else
- {
- m_actualAngle -= (105.0f*Math::PI/180.0f)*event.rTime/OPEN_DELAY;
- if ( m_actualAngle < m_finalAngle ) m_actualAngle = m_finalAngle;
- }
- m_object->SetAngleZ(1, m_actualAngle);
- m_object->SetAngleZ(2, -m_actualAngle);
- }
-
- // Blinks the keys.
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 2.0f;
- dim.y = dim.x;
- for ( i=0 ; i<4 ; i++ )
- {
- if ( m_phase != ASAP_WAIT || !m_bKey[i] || Math::Mod(m_time, 1.0f) < 0.4f )
- {
- if ( m_keyParti[i] != -1 )
- {
- m_particule->DeleteParticule(m_keyParti[i]);
- m_keyParti[i] = -1;
- }
- }
- else
- {
- if ( m_keyParti[i] == -1 )
- {
- pos = m_keyPos[i];
- pos.y += 2.2f;
- m_keyParti[i] = m_particule->CreateParticule(pos, speed, dim, PARTISELY, 1.0f, 0.0f, 0.0f);
- }
- }
- }
-
- return true;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoSafe::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 114, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoSafe::RetError()
-{
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
- return ERR_OK;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoSafe::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == ASAP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoSafe::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoSafePhase)OpInt(line, "aPhase", ASAP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
-// Counts the number of keys
-
-int CAutoSafe::CountKeys()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- Math::Point rot;
- ObjectType oType;
- float dist, angle, limit, cAngle, oAngle;
- int i, index;
-
- cPos = m_object->RetPosition(0);
- cAngle = m_object->RetAngleY(0);
-
- for ( index=0 ; index<4 ; index++ )
- {
- m_bKey[index] = false;
- m_keyPos[index] = cPos;
- }
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( pObj->RetTruck() != 0 ) continue;
-
- if ( oType != OBJECT_KEYa &&
- oType != OBJECT_KEYb &&
- oType != OBJECT_KEYc &&
- oType != OBJECT_KEYd ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, cPos);
- if ( dist > 20.0f ) continue;
-
- if ( oType == OBJECT_KEYa )
- {
- limit = Math::PI*1.0f;
- oAngle = Math::PI*0.0f;
- index = 0;
- }
- if ( oType == OBJECT_KEYb )
- {
- limit = Math::PI*0.0f;
- oAngle = Math::PI*1.0f;
- index = 1;
- }
- if ( oType == OBJECT_KEYc )
- {
- limit = Math::PI*1.5f;
- oAngle = Math::PI*0.5f;
- index = 2;
- }
- if ( oType == OBJECT_KEYd )
- {
- limit = Math::PI*0.5f;
- oAngle = Math::PI*0.0f;
- index = 3;
- }
-
- angle = Math::RotateAngle(oPos.x-cPos.x, oPos.z-cPos.z)+cAngle;
- if ( !Math::TestAngle(angle, limit-8.0f*Math::PI/180.0f, limit+8.0f*Math::PI/180.0f) ) continue;
-
- // Key changes the shape of the base.
- rot = Math::RotatePoint(Math::Point(cPos.x, cPos.z), limit-cAngle, Math::Point(cPos.x+16.0f, cPos.z));
- oPos.x = rot.x;
- oPos.z = rot.y;
- oPos.y = cPos.y+1.0f;
- pObj->SetPosition(0, oPos);
- pObj->SetAngleY(0, oAngle+cAngle);
- m_keyPos[index] = oPos;
-
- m_bKey[index] = true;
- }
-
- i = 0;
- for ( index=0 ; index<4 ; index++ )
- {
- if ( m_bKey[index] ) i++;
- }
- return i;
-}
-
-// Blocks all keys.
-
-void CAutoSafe::LockKeys()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType oType;
- float dist;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( pObj->RetTruck() != 0 ) continue;
-
- if ( oType != OBJECT_KEYa &&
- oType != OBJECT_KEYb &&
- oType != OBJECT_KEYc &&
- oType != OBJECT_KEYd ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, cPos);
- if ( dist > 20.0f ) continue;
-
- pObj->SetLock(true);
- }
-}
-
-// Sent down all the keys.
-
-void CAutoSafe::DownKeys(float progress)
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType oType;
- float dist;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( pObj->RetTruck() != 0 ) continue;
-
- if ( oType != OBJECT_KEYa &&
- oType != OBJECT_KEYb &&
- oType != OBJECT_KEYc &&
- oType != OBJECT_KEYd ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, cPos);
- if ( dist > 20.0f ) continue;
-
- oPos.y = cPos.y+1.0f-progress*2.2f;
- pObj->SetPosition(0, oPos);
- }
-}
-
-// Delete all the keys.
-
-void CAutoSafe::DeleteKeys()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType oType;
- float dist;
- int i;
- bool bDelete;
-
- cPos = m_object->RetPosition(0);
-
- do
- {
- bDelete = false;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( pObj->RetTruck() != 0 ) continue;
-
- if ( oType != OBJECT_KEYa &&
- oType != OBJECT_KEYb &&
- oType != OBJECT_KEYc &&
- oType != OBJECT_KEYd ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, cPos);
- if ( dist > 20.0f ) continue;
-
- pObj->DeleteObject();
- delete pObj;
- bDelete = true;
- }
- }
- while ( bDelete );
-}
-
-// Seeking a vehicle in the safe.
-
-CObject* CAutoSafe::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType oType;
- float dist;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( pObj == m_object ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, cPos);
- if ( dist <= 4.0f ) return pObj;
- }
- return 0;
-}
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autosafe.h"
+
+#include "common/iman.h"
+#include "math/geometry.h"
+#include "object/robotmain.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+
+
+const float OPEN_DELAY = 8.0f; // duration of opening
+
+
+// Object's constructor.
+
+CAutoSafe::CAutoSafe(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ int i;
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ m_bKey[i] = false;
+ m_keyParti[i] = -1;
+ }
+
+ m_bLock = false;
+ m_lastParticule = 0.0f;
+ m_channelSound = -1;
+ Init();
+}
+
+// Object's destructor.
+
+CAutoSafe::~CAutoSafe()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoSafe::DeleteObject(bool bAll)
+{
+ CObject* pObj;
+
+ pObj = SearchVehicle();
+ if ( pObj != 0 )
+ {
+ pObj->DeleteObject();
+ delete pObj;
+ }
+
+ if ( m_channelSound != -1 )
+ {
+ m_sound->FlushEnvelope(m_channelSound);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_channelSound = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoSafe::Init()
+{
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+
+ m_countKeys = 0;
+ m_actualAngle = 0.0f;
+ m_finalAngle = 0.0f;
+
+ m_phase = ASAP_WAIT; // waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoSafe::EventProcess(const Event &event)
+{
+ CObject* pObj;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ int i, count;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+ }
+ return true;
+ }
+
+ EventProgress(event.rTime);
+
+ if ( !m_bLock )
+ {
+ pObj = SearchVehicle();
+ if ( pObj != 0 )
+ {
+ pObj->SetLock(true); // object not yet usable
+ m_main->CreateShortcuts();
+ m_bLock = true;
+ }
+ }
+
+ if ( m_phase == ASAP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ count = CountKeys(); // count these key
+ if ( count != m_countKeys )
+ {
+ m_countKeys = count;
+
+ if ( count == 0 ) m_finalAngle = 0.0f*Math::PI/180.0f;
+ if ( count == 1 ) m_finalAngle = 5.0f*Math::PI/180.0f;
+ if ( count == 2 ) m_finalAngle = 10.0f*Math::PI/180.0f;
+ if ( count == 3 ) m_finalAngle = 15.0f*Math::PI/180.0f;
+ if ( count == 4 ) m_finalAngle = 120.0f*Math::PI/180.0f;
+
+ if ( count == 4 ) // all the keys?
+ {
+ LockKeys();
+
+ m_channelSound = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 1.0f, 0.25f, true);
+ m_sound->AddEnvelope(m_channelSound, 1.0f, 2.00f, OPEN_DELAY, SOPER_STOP);
+
+ m_phase = ASAP_OPEN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/OPEN_DELAY;
+ return true;
+ }
+ else
+ {
+ m_channelSound = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 1.0f, 0.25f, true);
+ m_sound->AddEnvelope(m_channelSound, 1.0f, 0.35f, 0.5f, SOPER_STOP);
+ }
+ }
+
+ m_phase = ASAP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ASAP_OPEN )
+ {
+ if ( m_progress < 1.0f )
+ {
+ DownKeys(m_progress);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ speed.x = (Math::Rand()-0.5f)*4.0f;
+ speed.z = (Math::Rand()-0.5f)*4.0f;
+ speed.y = Math::Rand()*15.0f;
+ dim.x = Math::Rand()*6.0f+4.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
+ }
+
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ speed.x = (Math::Rand()-0.5f)*4.0f;
+ speed.z = (Math::Rand()-0.5f)*4.0f;
+ speed.y = Math::Rand()*10.0f;
+ dim.x = Math::Rand()*3.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 1.0f, 0.0f, 0.0f);
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ pos = m_keyPos[i];
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = 1.0f+Math::Rand()*1.0f;
+ dim.x = Math::Rand()*1.5f+1.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+ else
+ {
+ DeleteKeys();
+
+ pObj = SearchVehicle();
+ if ( pObj != 0 )
+ {
+ pObj->SetLock(false); // object usable
+ m_main->CreateShortcuts();
+ }
+
+ m_object->FlushCrashShere();
+ m_object->SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 0.0f);
+
+ m_sound->Play(SOUND_FINDING, m_object->RetPosition(0));
+
+ m_phase = ASAP_FINISH;
+ m_progress = 0.0f;
+ m_speed = 1.0f/100.0f;
+ }
+ }
+
+ if ( m_phase == ASAP_FINISH )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_phase = ASAP_FINISH;
+ m_progress = 0.0f;
+ m_speed = 1.0f/100.0f;
+ }
+ }
+
+ // Opens or closes the doors.
+ if ( m_actualAngle != m_finalAngle )
+ {
+ if ( m_actualAngle < m_finalAngle )
+ {
+ m_actualAngle += (105.0f*Math::PI/180.0f)*event.rTime/OPEN_DELAY;
+ if ( m_actualAngle > m_finalAngle ) m_actualAngle = m_finalAngle;
+ }
+ else
+ {
+ m_actualAngle -= (105.0f*Math::PI/180.0f)*event.rTime/OPEN_DELAY;
+ if ( m_actualAngle < m_finalAngle ) m_actualAngle = m_finalAngle;
+ }
+ m_object->SetAngleZ(1, m_actualAngle);
+ m_object->SetAngleZ(2, -m_actualAngle);
+ }
+
+ // Blinks the keys.
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 2.0f;
+ dim.y = dim.x;
+ for ( i=0 ; i<4 ; i++ )
+ {
+ if ( m_phase != ASAP_WAIT || !m_bKey[i] || Math::Mod(m_time, 1.0f) < 0.4f )
+ {
+ if ( m_keyParti[i] != -1 )
+ {
+ m_particule->DeleteParticule(m_keyParti[i]);
+ m_keyParti[i] = -1;
+ }
+ }
+ else
+ {
+ if ( m_keyParti[i] == -1 )
+ {
+ pos = m_keyPos[i];
+ pos.y += 2.2f;
+ m_keyParti[i] = m_particule->CreateParticule(pos, speed, dim, PARTISELY, 1.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+
+ return true;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoSafe::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 114, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoSafe::RetError()
+{
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+ return ERR_OK;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoSafe::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == ASAP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoSafe::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoSafePhase)OpInt(line, "aPhase", ASAP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
+// Counts the number of keys
+
+int CAutoSafe::CountKeys()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ Math::Point rot;
+ ObjectType oType;
+ float dist, angle, limit, cAngle, oAngle;
+ int i, index;
+
+ cPos = m_object->RetPosition(0);
+ cAngle = m_object->RetAngleY(0);
+
+ for ( index=0 ; index<4 ; index++ )
+ {
+ m_bKey[index] = false;
+ m_keyPos[index] = cPos;
+ }
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ if ( oType != OBJECT_KEYa &&
+ oType != OBJECT_KEYb &&
+ oType != OBJECT_KEYc &&
+ oType != OBJECT_KEYd ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, cPos);
+ if ( dist > 20.0f ) continue;
+
+ if ( oType == OBJECT_KEYa )
+ {
+ limit = Math::PI*1.0f;
+ oAngle = Math::PI*0.0f;
+ index = 0;
+ }
+ if ( oType == OBJECT_KEYb )
+ {
+ limit = Math::PI*0.0f;
+ oAngle = Math::PI*1.0f;
+ index = 1;
+ }
+ if ( oType == OBJECT_KEYc )
+ {
+ limit = Math::PI*1.5f;
+ oAngle = Math::PI*0.5f;
+ index = 2;
+ }
+ if ( oType == OBJECT_KEYd )
+ {
+ limit = Math::PI*0.5f;
+ oAngle = Math::PI*0.0f;
+ index = 3;
+ }
+
+ angle = Math::RotateAngle(oPos.x-cPos.x, oPos.z-cPos.z)+cAngle;
+ if ( !Math::TestAngle(angle, limit-8.0f*Math::PI/180.0f, limit+8.0f*Math::PI/180.0f) ) continue;
+
+ // Key changes the shape of the base.
+ rot = Math::RotatePoint(Math::Point(cPos.x, cPos.z), limit-cAngle, Math::Point(cPos.x+16.0f, cPos.z));
+ oPos.x = rot.x;
+ oPos.z = rot.y;
+ oPos.y = cPos.y+1.0f;
+ pObj->SetPosition(0, oPos);
+ pObj->SetAngleY(0, oAngle+cAngle);
+ m_keyPos[index] = oPos;
+
+ m_bKey[index] = true;
+ }
+
+ i = 0;
+ for ( index=0 ; index<4 ; index++ )
+ {
+ if ( m_bKey[index] ) i++;
+ }
+ return i;
+}
+
+// Blocks all keys.
+
+void CAutoSafe::LockKeys()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType oType;
+ float dist;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ if ( oType != OBJECT_KEYa &&
+ oType != OBJECT_KEYb &&
+ oType != OBJECT_KEYc &&
+ oType != OBJECT_KEYd ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, cPos);
+ if ( dist > 20.0f ) continue;
+
+ pObj->SetLock(true);
+ }
+}
+
+// Sent down all the keys.
+
+void CAutoSafe::DownKeys(float progress)
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType oType;
+ float dist;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ if ( oType != OBJECT_KEYa &&
+ oType != OBJECT_KEYb &&
+ oType != OBJECT_KEYc &&
+ oType != OBJECT_KEYd ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, cPos);
+ if ( dist > 20.0f ) continue;
+
+ oPos.y = cPos.y+1.0f-progress*2.2f;
+ pObj->SetPosition(0, oPos);
+ }
+}
+
+// Delete all the keys.
+
+void CAutoSafe::DeleteKeys()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType oType;
+ float dist;
+ int i;
+ bool bDelete;
+
+ cPos = m_object->RetPosition(0);
+
+ do
+ {
+ bDelete = false;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ if ( oType != OBJECT_KEYa &&
+ oType != OBJECT_KEYb &&
+ oType != OBJECT_KEYc &&
+ oType != OBJECT_KEYd ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, cPos);
+ if ( dist > 20.0f ) continue;
+
+ pObj->DeleteObject();
+ delete pObj;
+ bDelete = true;
+ }
+ }
+ while ( bDelete );
+}
+
+// Seeking a vehicle in the safe.
+
+CObject* CAutoSafe::SearchVehicle()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType oType;
+ float dist;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( pObj == m_object ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, cPos);
+ if ( dist <= 4.0f ) return pObj;
+ }
+ return 0;
+}
+
+
+
diff --git a/src/object/auto/autosafe.h b/src/object/auto/autosafe.h
index 4194349..d17435b 100644
--- a/src/object/auto/autosafe.h
+++ b/src/object/auto/autosafe.h
@@ -1,74 +1,74 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autosafe.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoSafePhase
-{
- ASAP_WAIT = 1,
- ASAP_OPEN = 2,
- ASAP_FINISH = 3,
-};
-
-
-
-class CAutoSafe : public CAuto
-{
-public:
- CAutoSafe(CInstanceManager* iMan, CObject* object);
- ~CAutoSafe();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- int CountKeys();
- void LockKeys();
- void DownKeys(float progress);
- void DeleteKeys();
- CObject* SearchVehicle();
-
-protected:
- AutoSafePhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
- int m_channelSound;
- bool m_bLock;
- int m_countKeys;
- float m_actualAngle;
- float m_finalAngle;
- bool m_bKey[4];
- Math::Vector m_keyPos[4];
- int m_keyParti[4];
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autosafe.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoSafePhase
+{
+ ASAP_WAIT = 1,
+ ASAP_OPEN = 2,
+ ASAP_FINISH = 3,
+};
+
+
+
+class CAutoSafe : public CAuto
+{
+public:
+ CAutoSafe(CInstanceManager* iMan, CObject* object);
+ ~CAutoSafe();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ int CountKeys();
+ void LockKeys();
+ void DownKeys(float progress);
+ void DeleteKeys();
+ CObject* SearchVehicle();
+
+protected:
+ AutoSafePhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+ int m_channelSound;
+ bool m_bLock;
+ int m_countKeys;
+ float m_actualAngle;
+ float m_finalAngle;
+ bool m_bKey[4];
+ Math::Vector m_keyPos[4];
+ int m_keyParti[4];
+};
+
diff --git a/src/object/auto/autostation.cpp b/src/object/auto/autostation.cpp
index ddd5888..dba4ed8 100644
--- a/src/object/auto/autostation.cpp
+++ b/src/object/auto/autostation.cpp
@@ -1,370 +1,370 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autostation.h"
-
-#include "common/iman.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "math/geometry.h"
-#include "ui/interface.h"
-#include "ui/gauge.h"
-#include "ui/window.h"
-
-
-
-
-// Object's constructor.
-
-CAutoStation::CAutoStation(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
-}
-
-// Object's destructor.
-
-CAutoStation::~CAutoStation()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoStation::DeleteObject(bool bAll)
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->Stop(m_soundChannel);
- m_soundChannel = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoStation::Init()
-{
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastUpdateTime = 0.0f;
- m_lastParticule = 0.0f;
- m_soundChannel = -1;
- m_bLastVirus = false;
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoStation::EventProcess(const Event &event)
-{
- Math::Matrix* mat;
- Math::Vector pos, ppos, speed;
- Math::Point dim;
- CObject* vehicule;
- CObject* power;
- TerrainRes res;
- float big, energy, used, add, freq;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( !m_bLastVirus )
- {
- m_bLastVirus = true;
- m_energyVirus = m_object->RetEnergy();
- }
-
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
-
- m_object->SetEnergy(Math::Rand());
- }
- return true;
- }
- else
- {
- if ( m_bLastVirus )
- {
- m_bLastVirus = false;
- m_object->SetEnergy(m_energyVirus);
- }
- }
-
- UpdateInterface(event.rTime);
-
- big = m_object->RetEnergy();
-
- res = m_terrain->RetResource(m_object->RetPosition(0));
- if ( res == TR_POWER )
- {
- big += event.rTime*0.01f; // recharges the large battery
- }
-
- used = big;
- freq = 1.0f;
- if ( big > 0.0f )
- {
- vehicule = SearchVehicle();
- if ( vehicule != 0 )
- {
- power = vehicule->RetPower();
- if ( power != 0 && power->RetCapacity() == 1.0f )
- {
- energy = power->RetEnergy();
- add = event.rTime*0.2f;
- if ( add > big*4.0f ) add = big*4.0f;
- if ( add > 1.0f-energy ) add = 1.0f-energy;
- energy += add; // Charging the battery
- power->SetEnergy(energy);
- if ( energy < freq ) freq = energy;
- big -= add/4.0f; // discharge the large battery
- }
-
- power = vehicule->RetFret();
- if ( power != 0 && power->RetType() == OBJECT_POWER )
- {
- energy = power->RetEnergy();
- add = event.rTime*0.2f;
- if ( add > big*4.0f ) add = big*4.0f;
- if ( add > 1.0f-energy ) add = 1.0f-energy;
- energy += add; // Charging the battery
- power->SetEnergy(energy);
- if ( energy < freq ) freq = energy;
- big -= add/4.0f; // discharge the large battery
- }
- }
- }
- used -= big; // energy used
-
- if ( freq < 1.0f ) // charging in progress?
- {
- freq = 1.0f+3.0f*freq;
- if ( m_soundChannel == -1 )
- {
- m_soundChannel = m_sound->Play(SOUND_STATION, m_object->RetPosition(0),
- 0.3f, freq, true);
- }
- m_sound->Frequency(m_soundChannel, freq);
- }
- else
- {
- if ( m_soundChannel != -1 )
- {
- m_sound->Stop(m_soundChannel);
- m_soundChannel = -1;
- }
- }
-
- if ( used != 0.0f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(-15.0f, 7.0f, 0.0f); // battery position
- pos = Math::Transform(*mat, pos);
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.y = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- ppos.x = pos.x;
- ppos.y = pos.y+(Math::Rand()-0.5f)*4.0f;
- ppos.z = pos.z;
- dim.x = 1.5f;
- dim.y = 1.5f;
- m_particule->CreateParticule(ppos, speed, dim, PARTIBLITZ, 1.0f, 0.0f, 0.0f);
-
-#if 0
- ppos = pos;
- ppos.y += 1.0f;
- ppos.x += (Math::Rand()-0.5f)*3.0f;
- ppos.z += (Math::Rand()-0.5f)*3.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 2.5f+Math::Rand()*6.0f;
- dim.x = Math::Rand()*1.5f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(ppos, speed, dim, PARTISMOKE3, 4.0f);
-#else
- ppos = pos;
- ppos.y += 1.0f;
- ppos.x += (Math::Rand()-0.5f)*3.0f;
- ppos.z += (Math::Rand()-0.5f)*3.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 2.5f+Math::Rand()*5.0f;
- dim.x = Math::Rand()*1.0f+0.6f;
- dim.y = dim.x;
- m_particule->CreateParticule(ppos, speed, dim, PARTIVAPOR, 3.0f);
-#endif
- }
-
- if ( big < 0.0f ) big = 0.0f;
- if ( big > 1.0f ) big = 1.0f;
- m_object->SetEnergy(big); // Shift the large battery
-
- return true;
-}
-
-
-// Seeking the vehicle on the station.
-
-CObject* CAutoStation::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector sPos, oPos;
- ObjectType type;
- float dist;
- int i;
-
- sPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, sPos);
- if ( dist <= 5.0f ) return pObj;
- }
-
- return 0;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoStation::RetError()
-{
- TerrainRes res;
-
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- res = m_terrain->RetResource(m_object->RetPosition(0));
- if ( res != TR_POWER ) return ERR_STATION_NULL;
-
- return ERR_OK;
-}
-
-
-// Crée toute l'interface lorsque l'objet est sélectionné .
-
-bool CAutoStation::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*14.5f;
- pos.y = oy+sy*0;
- ddim.x = 14.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 104, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-// Updates the state of all buttons on the interface,
-// following the time that elapses ...
-
-void CAutoStation::UpdateInterface(float rTime)
-{
- CWindow* pw;
- CGauge* pg;
-
- CAuto::UpdateInterface(rTime);
-
- if ( m_time < m_lastUpdateTime+0.1f ) return;
- m_lastUpdateTime = m_time;
-
- if ( !m_object->RetSelect() ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
- if ( pg != 0 )
- {
- pg->SetLevel(m_object->RetEnergy());
- }
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autostation.h"
+
+#include "common/iman.h"
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "math/geometry.h"
+#include "ui/interface.h"
+#include "ui/gauge.h"
+#include "ui/window.h"
+
+
+
+
+// Object's constructor.
+
+CAutoStation::CAutoStation(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+}
+
+// Object's destructor.
+
+CAutoStation::~CAutoStation()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoStation::DeleteObject(bool bAll)
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->Stop(m_soundChannel);
+ m_soundChannel = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoStation::Init()
+{
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastUpdateTime = 0.0f;
+ m_lastParticule = 0.0f;
+ m_soundChannel = -1;
+ m_bLastVirus = false;
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoStation::EventProcess(const Event &event)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, ppos, speed;
+ Math::Point dim;
+ CObject* vehicule;
+ CObject* power;
+ TerrainRes res;
+ float big, energy, used, add, freq;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( !m_bLastVirus )
+ {
+ m_bLastVirus = true;
+ m_energyVirus = m_object->RetEnergy();
+ }
+
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+
+ m_object->SetEnergy(Math::Rand());
+ }
+ return true;
+ }
+ else
+ {
+ if ( m_bLastVirus )
+ {
+ m_bLastVirus = false;
+ m_object->SetEnergy(m_energyVirus);
+ }
+ }
+
+ UpdateInterface(event.rTime);
+
+ big = m_object->RetEnergy();
+
+ res = m_terrain->RetResource(m_object->RetPosition(0));
+ if ( res == TR_POWER )
+ {
+ big += event.rTime*0.01f; // recharges the large battery
+ }
+
+ used = big;
+ freq = 1.0f;
+ if ( big > 0.0f )
+ {
+ vehicule = SearchVehicle();
+ if ( vehicule != 0 )
+ {
+ power = vehicule->RetPower();
+ if ( power != 0 && power->RetCapacity() == 1.0f )
+ {
+ energy = power->RetEnergy();
+ add = event.rTime*0.2f;
+ if ( add > big*4.0f ) add = big*4.0f;
+ if ( add > 1.0f-energy ) add = 1.0f-energy;
+ energy += add; // Charging the battery
+ power->SetEnergy(energy);
+ if ( energy < freq ) freq = energy;
+ big -= add/4.0f; // discharge the large battery
+ }
+
+ power = vehicule->RetFret();
+ if ( power != 0 && power->RetType() == OBJECT_POWER )
+ {
+ energy = power->RetEnergy();
+ add = event.rTime*0.2f;
+ if ( add > big*4.0f ) add = big*4.0f;
+ if ( add > 1.0f-energy ) add = 1.0f-energy;
+ energy += add; // Charging the battery
+ power->SetEnergy(energy);
+ if ( energy < freq ) freq = energy;
+ big -= add/4.0f; // discharge the large battery
+ }
+ }
+ }
+ used -= big; // energy used
+
+ if ( freq < 1.0f ) // charging in progress?
+ {
+ freq = 1.0f+3.0f*freq;
+ if ( m_soundChannel == -1 )
+ {
+ m_soundChannel = m_sound->Play(SOUND_STATION, m_object->RetPosition(0),
+ 0.3f, freq, true);
+ }
+ m_sound->Frequency(m_soundChannel, freq);
+ }
+ else
+ {
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->Stop(m_soundChannel);
+ m_soundChannel = -1;
+ }
+ }
+
+ if ( used != 0.0f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(-15.0f, 7.0f, 0.0f); // battery position
+ pos = Math::Transform(*mat, pos);
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.y = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ ppos.x = pos.x;
+ ppos.y = pos.y+(Math::Rand()-0.5f)*4.0f;
+ ppos.z = pos.z;
+ dim.x = 1.5f;
+ dim.y = 1.5f;
+ m_particule->CreateParticule(ppos, speed, dim, PARTIBLITZ, 1.0f, 0.0f, 0.0f);
+
+#if 0
+ ppos = pos;
+ ppos.y += 1.0f;
+ ppos.x += (Math::Rand()-0.5f)*3.0f;
+ ppos.z += (Math::Rand()-0.5f)*3.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 2.5f+Math::Rand()*6.0f;
+ dim.x = Math::Rand()*1.5f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(ppos, speed, dim, PARTISMOKE3, 4.0f);
+#else
+ ppos = pos;
+ ppos.y += 1.0f;
+ ppos.x += (Math::Rand()-0.5f)*3.0f;
+ ppos.z += (Math::Rand()-0.5f)*3.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 2.5f+Math::Rand()*5.0f;
+ dim.x = Math::Rand()*1.0f+0.6f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(ppos, speed, dim, PARTIVAPOR, 3.0f);
+#endif
+ }
+
+ if ( big < 0.0f ) big = 0.0f;
+ if ( big > 1.0f ) big = 1.0f;
+ m_object->SetEnergy(big); // Shift the large battery
+
+ return true;
+}
+
+
+// Seeking the vehicle on the station.
+
+CObject* CAutoStation::SearchVehicle()
+{
+ CObject* pObj;
+ Math::Vector sPos, oPos;
+ ObjectType type;
+ float dist;
+ int i;
+
+ sPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_HUMAN &&
+ type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis &&
+ type != OBJECT_MOBILErt &&
+ type != OBJECT_MOBILErc &&
+ type != OBJECT_MOBILErr &&
+ type != OBJECT_MOBILErs &&
+ type != OBJECT_MOBILEsa &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_MOBILEdr ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, sPos);
+ if ( dist <= 5.0f ) return pObj;
+ }
+
+ return 0;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoStation::RetError()
+{
+ TerrainRes res;
+
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ res = m_terrain->RetResource(m_object->RetPosition(0));
+ if ( res != TR_POWER ) return ERR_STATION_NULL;
+
+ return ERR_OK;
+}
+
+
+// Crée toute l'interface lorsque l'objet est sélectionné .
+
+bool CAutoStation::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*14.5f;
+ pos.y = oy+sy*0;
+ ddim.x = 14.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 104, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+// Updates the state of all buttons on the interface,
+// following the time that elapses ...
+
+void CAutoStation::UpdateInterface(float rTime)
+{
+ CWindow* pw;
+ CGauge* pg;
+
+ CAuto::UpdateInterface(rTime);
+
+ if ( m_time < m_lastUpdateTime+0.1f ) return;
+ m_lastUpdateTime = m_time;
+
+ if ( !m_object->RetSelect() ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
+ if ( pg != 0 )
+ {
+ pg->SetLevel(m_object->RetEnergy());
+ }
+}
+
+
diff --git a/src/object/auto/autostation.h b/src/object/auto/autostation.h
index b4584f2..5bf2b72 100644
--- a/src/object/auto/autostation.h
+++ b/src/object/auto/autostation.h
@@ -1,56 +1,56 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autostation.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-class CAutoStation : public CAuto
-{
-public:
- CAutoStation(CInstanceManager* iMan, CObject* object);
- ~CAutoStation();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
-protected:
- void UpdateInterface(float rTime);
-
- CObject* SearchVehicle();
-
-protected:
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastUpdateTime;
- float m_lastParticule;
- int m_soundChannel;
- Math::Vector m_fretPos;
- bool m_bLastVirus;
- float m_energyVirus;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autostation.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+class CAutoStation : public CAuto
+{
+public:
+ CAutoStation(CInstanceManager* iMan, CObject* object);
+ ~CAutoStation();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+protected:
+ void UpdateInterface(float rTime);
+
+ CObject* SearchVehicle();
+
+protected:
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastUpdateTime;
+ float m_lastParticule;
+ int m_soundChannel;
+ Math::Vector m_fretPos;
+ bool m_bLastVirus;
+ float m_energyVirus;
+};
+
diff --git a/src/object/auto/autotower.cpp b/src/object/auto/autotower.cpp
index ec92341..5f185fe 100644
--- a/src/object/auto/autotower.cpp
+++ b/src/object/auto/autotower.cpp
@@ -1,541 +1,541 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autotower.h"
-
-#include "common/iman.h"
-#include "math/geometry.h"
-#include "physics/physics.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/displaytext.h"
-#include "ui/window.h"
-#include "ui/gauge.h"
-
-
-const float TOWER_SCOPE = 200.0f; // range of beam
-const float ENERGY_FIRE = 0.125f; // energy consumed by fire
-
-
-// Object's constructor.
-
-CAutoTower::CAutoTower(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- int i;
-
- for ( i=0 ; i<4 ; i++ )
- {
- m_partiStop[i] = -1;
- }
-
- Init();
- m_phase = ATP_WAIT; // paused until the first Init ()
- m_time = 0.0f;
- m_lastUpdateTime = 0.0f;
-}
-
-// Object's destructor.
-
-CAutoTower::~CAutoTower()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoTower::DeleteObject(bool bAll)
-{
- FireStopUpdate(0.0f, false);
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoTower::Init()
-{
- m_phase = ATP_ZERO;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastUpdateTime = 0.0f;
- m_lastParticule = 0.0f;
-}
-
-
-// Management of an event.
-
-bool CAutoTower::EventProcess(const Event &event)
-{
- CObject* power;
- CObject* target;
- Math::Vector pos;
- float angle, energy, quick;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
-
- angle = m_object->RetAngleY(1);
- angle += Math::Rand()*0.5f;
- m_object->SetAngleY(1, angle);
-
- m_object->SetAngleZ(2, Math::Rand()*0.5f);
- }
- return true;
- }
-
- UpdateInterface(event.rTime);
-
- if ( m_phase == ATP_WAIT ) return true;
-
- m_progress += event.rTime*m_speed;
-
- if ( m_phase == ATP_ZERO )
- {
- FireStopUpdate(m_progress, true); // blinks
- if ( m_progress < 1.0f )
- {
- energy = 0.0f;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- }
- if ( energy >= ENERGY_FIRE )
- {
- m_phase = ATP_SEARCH;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- }
- }
- else
- {
- m_phase = ATP_ZERO;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ATP_SEARCH )
- {
- FireStopUpdate(m_progress, false); // extinguished
- if ( m_progress < 1.0f )
- {
- quick = 1.0f;
-//? if ( g_researchDone & RESEARCH_QUICK ) quick = 3.0f;
-
- angle = m_object->RetAngleY(1);
- angle -= event.rTime*quick*2.0f;
- m_object->SetAngleY(1, angle);
-
- angle = m_object->RetAngleZ(2);
- angle += event.rTime*quick*0.5f;
- if ( angle > 0.0f ) angle = 0.0f;
- m_object->SetAngleZ(2, angle);
- }
- else
- {
- energy = 0.0f;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- }
-
- target = SearchTarget(m_targetPos);
- if ( energy < ENERGY_FIRE )
- {
- m_displayText->DisplayError(ERR_TOWER_ENERGY, m_object);
- }
- if ( target == 0 || energy < ENERGY_FIRE )
- {
- m_phase = ATP_ZERO;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- else
- {
- pos = m_object->RetPosition(0);
- pos.y += 24.5f;
- m_angleYfinal = Math::RotateAngle(m_targetPos.x-pos.x, pos.z-m_targetPos.z); // CW !
- m_angleYfinal += Math::PI*2.0f;
- m_angleYfinal -= m_object->RetAngleY(0);
- m_angleYactual = Math::NormAngle(m_object->RetAngleY(1));
-
- m_angleZfinal = -Math::PI/2.0f;
- m_angleZfinal -= Math::RotateAngle(Math::DistanceProjected(m_targetPos, pos), pos.y-m_targetPos.y); // CW !
- m_angleZactual = m_object->RetAngleZ(2);
-
- m_phase = ATP_TURN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-//? if ( g_researchDone & RESEARCH_QUICK ) m_speed = 1.0f/0.2f;
- }
- }
- }
-
- if ( m_phase == ATP_TURN )
- {
- if ( m_progress < 1.0f )
- {
- angle = m_angleYactual+(m_angleYfinal-m_angleYactual)*m_progress;
- m_object->SetAngleY(1, angle);
-
- angle = m_angleZactual+(m_angleZfinal-m_angleZactual)*m_progress;
- m_object->SetAngleZ(2, angle);
- }
- else
- {
- m_object->SetAngleY(1, m_angleYfinal);
- m_object->SetAngleZ(2, m_angleZfinal);
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- energy -= ENERGY_FIRE/power->RetCapacity();
- power->SetEnergy(energy);
- }
-
- m_sound->Play(SOUND_GGG, m_object->RetPosition(0));
-
- m_phase = ATP_FIRE;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
-
- if ( m_phase == ATP_FIRE )
- {
- if ( m_progress == 0.0f )
- {
- pos = m_object->RetPosition(0);
- pos.y += 24.5f;
- m_particule->CreateRay(pos, m_targetPos, PARTIRAY1,
- Math::Point(5.0f, 5.0f), 1.5f);
- }
- if ( m_progress >= 1.0f )
- {
- m_phase = ATP_ZERO;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- return true;
-}
-
-
-// Seeks the nearest target object.
-
-CObject* CAutoTower::SearchTarget(Math::Vector &impact)
-{
- CObject* pObj;
- CObject* pBest = 0;
- CPhysics* physics;
- Math::Vector iPos, oPos;
- ObjectType oType;
- float distance, min, radius, speed;
- int i;
-
- iPos = m_object->RetPosition(0);
- min = 1000000.0f;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( oType != OBJECT_MOTHER &&
- oType != OBJECT_ANT &&
- oType != OBJECT_SPIDER &&
- oType != OBJECT_BEE &&
- oType != OBJECT_WORM ) continue;
-
- if ( !pObj->RetActif() ) continue; // inactive?
-
-//? if ( g_researchDone & RESEARCH_QUICK )
- if ( false )
- {
- physics = pObj->RetPhysics();
- if ( physics != 0 )
- {
- speed = fabs(physics->RetLinMotionX(MO_REASPEED));
- if ( speed > 20.0f ) continue; // moving too fast?
- }
- }
-
- if ( !pObj->GetCrashSphere(0, oPos, radius) ) continue;
- distance = Math::Distance(oPos, iPos);
- if ( distance > TOWER_SCOPE ) continue; // too far
- if ( distance < min )
- {
- min = distance;
- pBest = pObj;
- }
- }
- if ( pBest == 0 ) return 0;
-
- impact = pBest->RetPosition(0);
- return pBest;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoTower::RetError()
-{
- CObject* power;
-
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- power = m_object->RetPower();
- if ( power == 0 )
- {
- return ERR_TOWER_POWER; // no battery
- }
- else
- {
- if ( power->RetEnergy() < ENERGY_FIRE )
- {
- return ERR_TOWER_ENERGY; // not enough energy
- }
- }
- return ERR_OK;
-}
-
-
-// Updates the stop lights.
-
-void CAutoTower::FireStopUpdate(float progress, bool bLightOn)
-{
- Math::Matrix* mat;
- Math::Vector pos, speed;
- Math::Point dim;
- int i;
-
- static float listpos[8] =
- {
- 4.5f, 0.0f,
- 0.0f, 4.5f,
- -4.5f, 0.0f,
- 0.0f, -4.5f,
- };
-
- if ( !bLightOn ) // extinguished?
- {
- for ( i=0 ; i<4 ; i++ )
- {
- if ( m_partiStop[i] != -1 )
- {
- m_particule->DeleteParticule(m_partiStop[i]);
- m_partiStop[i] = -1;
- }
- }
- return;
- }
-
- mat = m_object->RetWorldMatrix(0);
-
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 2.0f;
- dim.y = dim.x;
-
- for ( i=0 ; i<4 ; i++ )
- {
- if ( Math::Mod(progress+i*0.125f, 0.5f) < 0.2f )
- {
- if ( m_partiStop[i] != -1 )
- {
- m_particule->DeleteParticule(m_partiStop[i]);
- m_partiStop[i] = -1;
- }
- }
- else
- {
- if ( m_partiStop[i] == -1 )
- {
- pos.x = listpos[i*2+0];
- pos.y = 18.0f;
- pos.z = listpos[i*2+1];
- pos = Transform(*mat, pos);
- m_partiStop[i] = m_particule->CreateParticule(pos, speed,
- dim, PARTISELR,
- 1.0f, 0.0f, 0.0f);
- }
- }
- }
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoTower::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*14.5f;
- pos.y = oy+sy*0;
- ddim.x = 14.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 107, EVENT_OBJECT_TYPE);
-
- pos.x = ox+sx*10.2f;
- pos.y = oy+sy*0.5f;
- ddim.x = 33.0f/640.0f;
- ddim.y = 33.0f/480.0f;
- pw->CreateButton(pos, ddim, 41, EVENT_OBJECT_LIMIT);
-
- return true;
-}
-
-// Updates the state of all buttons on the interface,
-// following the time that elapses ...
-
-void CAutoTower::UpdateInterface(float rTime)
-{
- CWindow* pw;
- CGauge* pg;
- CObject* power;
- float energy;
-
- CAuto::UpdateInterface(rTime);
-
- if ( m_time < m_lastUpdateTime+0.1f ) return;
- m_lastUpdateTime = m_time;
-
- if ( !m_object->RetSelect() ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
- if ( pg != 0 )
- {
- energy = 0.0f;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- }
- pg->SetLevel(energy);
- }
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoTower::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == ATP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- sprintf(name, " aTargetPos=%.2f;%.2f;%.2f", m_targetPos.x, m_targetPos.y, m_targetPos.z);
- strcat(line, name);
-
- sprintf(name, " aAngleYactual=%.2f", m_angleYactual);
- strcat(line, name);
-
- sprintf(name, " aAngleZactual=%.2f", m_angleZactual);
- strcat(line, name);
-
- sprintf(name, " aAngleYfinal=%.2f", m_angleYfinal);
- strcat(line, name);
-
- sprintf(name, " aAngleZfinal=%.2f", m_angleZfinal);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoTower::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoTowerPhase)OpInt(line, "aPhase", ATP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
- m_targetPos = OpDir(line, "aTargetPos");
- m_angleYactual = OpFloat(line, "aAngleYactual", 0.0f);
- m_angleZactual = OpFloat(line, "aAngleZactual", 0.0f);
- m_angleYfinal = OpFloat(line, "aAngleYfinal", 0.0f);
- m_angleZfinal = OpFloat(line, "aAngleZfinal", 0.0f);
-
- m_lastUpdateTime = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autotower.h"
+
+#include "common/iman.h"
+#include "math/geometry.h"
+#include "physics/physics.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/displaytext.h"
+#include "ui/window.h"
+#include "ui/gauge.h"
+
+
+const float TOWER_SCOPE = 200.0f; // range of beam
+const float ENERGY_FIRE = 0.125f; // energy consumed by fire
+
+
+// Object's constructor.
+
+CAutoTower::CAutoTower(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ int i;
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ m_partiStop[i] = -1;
+ }
+
+ Init();
+ m_phase = ATP_WAIT; // paused until the first Init ()
+ m_time = 0.0f;
+ m_lastUpdateTime = 0.0f;
+}
+
+// Object's destructor.
+
+CAutoTower::~CAutoTower()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoTower::DeleteObject(bool bAll)
+{
+ FireStopUpdate(0.0f, false);
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoTower::Init()
+{
+ m_phase = ATP_ZERO;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastUpdateTime = 0.0f;
+ m_lastParticule = 0.0f;
+}
+
+
+// Management of an event.
+
+bool CAutoTower::EventProcess(const Event &event)
+{
+ CObject* power;
+ CObject* target;
+ Math::Vector pos;
+ float angle, energy, quick;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+
+ angle = m_object->RetAngleY(1);
+ angle += Math::Rand()*0.5f;
+ m_object->SetAngleY(1, angle);
+
+ m_object->SetAngleZ(2, Math::Rand()*0.5f);
+ }
+ return true;
+ }
+
+ UpdateInterface(event.rTime);
+
+ if ( m_phase == ATP_WAIT ) return true;
+
+ m_progress += event.rTime*m_speed;
+
+ if ( m_phase == ATP_ZERO )
+ {
+ FireStopUpdate(m_progress, true); // blinks
+ if ( m_progress < 1.0f )
+ {
+ energy = 0.0f;
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ }
+ if ( energy >= ENERGY_FIRE )
+ {
+ m_phase = ATP_SEARCH;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ }
+ }
+ else
+ {
+ m_phase = ATP_ZERO;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ATP_SEARCH )
+ {
+ FireStopUpdate(m_progress, false); // extinguished
+ if ( m_progress < 1.0f )
+ {
+ quick = 1.0f;
+//? if ( g_researchDone & RESEARCH_QUICK ) quick = 3.0f;
+
+ angle = m_object->RetAngleY(1);
+ angle -= event.rTime*quick*2.0f;
+ m_object->SetAngleY(1, angle);
+
+ angle = m_object->RetAngleZ(2);
+ angle += event.rTime*quick*0.5f;
+ if ( angle > 0.0f ) angle = 0.0f;
+ m_object->SetAngleZ(2, angle);
+ }
+ else
+ {
+ energy = 0.0f;
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ }
+
+ target = SearchTarget(m_targetPos);
+ if ( energy < ENERGY_FIRE )
+ {
+ m_displayText->DisplayError(ERR_TOWER_ENERGY, m_object);
+ }
+ if ( target == 0 || energy < ENERGY_FIRE )
+ {
+ m_phase = ATP_ZERO;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ else
+ {
+ pos = m_object->RetPosition(0);
+ pos.y += 24.5f;
+ m_angleYfinal = Math::RotateAngle(m_targetPos.x-pos.x, pos.z-m_targetPos.z); // CW !
+ m_angleYfinal += Math::PI*2.0f;
+ m_angleYfinal -= m_object->RetAngleY(0);
+ m_angleYactual = Math::NormAngle(m_object->RetAngleY(1));
+
+ m_angleZfinal = -Math::PI/2.0f;
+ m_angleZfinal -= Math::RotateAngle(Math::DistanceProjected(m_targetPos, pos), pos.y-m_targetPos.y); // CW !
+ m_angleZactual = m_object->RetAngleZ(2);
+
+ m_phase = ATP_TURN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+//? if ( g_researchDone & RESEARCH_QUICK ) m_speed = 1.0f/0.2f;
+ }
+ }
+ }
+
+ if ( m_phase == ATP_TURN )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = m_angleYactual+(m_angleYfinal-m_angleYactual)*m_progress;
+ m_object->SetAngleY(1, angle);
+
+ angle = m_angleZactual+(m_angleZfinal-m_angleZactual)*m_progress;
+ m_object->SetAngleZ(2, angle);
+ }
+ else
+ {
+ m_object->SetAngleY(1, m_angleYfinal);
+ m_object->SetAngleZ(2, m_angleZfinal);
+
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ energy -= ENERGY_FIRE/power->RetCapacity();
+ power->SetEnergy(energy);
+ }
+
+ m_sound->Play(SOUND_GGG, m_object->RetPosition(0));
+
+ m_phase = ATP_FIRE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+
+ if ( m_phase == ATP_FIRE )
+ {
+ if ( m_progress == 0.0f )
+ {
+ pos = m_object->RetPosition(0);
+ pos.y += 24.5f;
+ m_particule->CreateRay(pos, m_targetPos, PARTIRAY1,
+ Math::Point(5.0f, 5.0f), 1.5f);
+ }
+ if ( m_progress >= 1.0f )
+ {
+ m_phase = ATP_ZERO;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ return true;
+}
+
+
+// Seeks the nearest target object.
+
+CObject* CAutoTower::SearchTarget(Math::Vector &impact)
+{
+ CObject* pObj;
+ CObject* pBest = 0;
+ CPhysics* physics;
+ Math::Vector iPos, oPos;
+ ObjectType oType;
+ float distance, min, radius, speed;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+ min = 1000000.0f;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( oType != OBJECT_MOTHER &&
+ oType != OBJECT_ANT &&
+ oType != OBJECT_SPIDER &&
+ oType != OBJECT_BEE &&
+ oType != OBJECT_WORM ) continue;
+
+ if ( !pObj->RetActif() ) continue; // inactive?
+
+//? if ( g_researchDone & RESEARCH_QUICK )
+ if ( false )
+ {
+ physics = pObj->RetPhysics();
+ if ( physics != 0 )
+ {
+ speed = fabs(physics->RetLinMotionX(MO_REASPEED));
+ if ( speed > 20.0f ) continue; // moving too fast?
+ }
+ }
+
+ if ( !pObj->GetCrashSphere(0, oPos, radius) ) continue;
+ distance = Math::Distance(oPos, iPos);
+ if ( distance > TOWER_SCOPE ) continue; // too far
+ if ( distance < min )
+ {
+ min = distance;
+ pBest = pObj;
+ }
+ }
+ if ( pBest == 0 ) return 0;
+
+ impact = pBest->RetPosition(0);
+ return pBest;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoTower::RetError()
+{
+ CObject* power;
+
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ power = m_object->RetPower();
+ if ( power == 0 )
+ {
+ return ERR_TOWER_POWER; // no battery
+ }
+ else
+ {
+ if ( power->RetEnergy() < ENERGY_FIRE )
+ {
+ return ERR_TOWER_ENERGY; // not enough energy
+ }
+ }
+ return ERR_OK;
+}
+
+
+// Updates the stop lights.
+
+void CAutoTower::FireStopUpdate(float progress, bool bLightOn)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ int i;
+
+ static float listpos[8] =
+ {
+ 4.5f, 0.0f,
+ 0.0f, 4.5f,
+ -4.5f, 0.0f,
+ 0.0f, -4.5f,
+ };
+
+ if ( !bLightOn ) // extinguished?
+ {
+ for ( i=0 ; i<4 ; i++ )
+ {
+ if ( m_partiStop[i] != -1 )
+ {
+ m_particule->DeleteParticule(m_partiStop[i]);
+ m_partiStop[i] = -1;
+ }
+ }
+ return;
+ }
+
+ mat = m_object->RetWorldMatrix(0);
+
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 2.0f;
+ dim.y = dim.x;
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ if ( Math::Mod(progress+i*0.125f, 0.5f) < 0.2f )
+ {
+ if ( m_partiStop[i] != -1 )
+ {
+ m_particule->DeleteParticule(m_partiStop[i]);
+ m_partiStop[i] = -1;
+ }
+ }
+ else
+ {
+ if ( m_partiStop[i] == -1 )
+ {
+ pos.x = listpos[i*2+0];
+ pos.y = 18.0f;
+ pos.z = listpos[i*2+1];
+ pos = Transform(*mat, pos);
+ m_partiStop[i] = m_particule->CreateParticule(pos, speed,
+ dim, PARTISELR,
+ 1.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoTower::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*14.5f;
+ pos.y = oy+sy*0;
+ ddim.x = 14.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 107, EVENT_OBJECT_TYPE);
+
+ pos.x = ox+sx*10.2f;
+ pos.y = oy+sy*0.5f;
+ ddim.x = 33.0f/640.0f;
+ ddim.y = 33.0f/480.0f;
+ pw->CreateButton(pos, ddim, 41, EVENT_OBJECT_LIMIT);
+
+ return true;
+}
+
+// Updates the state of all buttons on the interface,
+// following the time that elapses ...
+
+void CAutoTower::UpdateInterface(float rTime)
+{
+ CWindow* pw;
+ CGauge* pg;
+ CObject* power;
+ float energy;
+
+ CAuto::UpdateInterface(rTime);
+
+ if ( m_time < m_lastUpdateTime+0.1f ) return;
+ m_lastUpdateTime = m_time;
+
+ if ( !m_object->RetSelect() ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
+ if ( pg != 0 )
+ {
+ energy = 0.0f;
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ }
+ pg->SetLevel(energy);
+ }
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoTower::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == ATP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ sprintf(name, " aTargetPos=%.2f;%.2f;%.2f", m_targetPos.x, m_targetPos.y, m_targetPos.z);
+ strcat(line, name);
+
+ sprintf(name, " aAngleYactual=%.2f", m_angleYactual);
+ strcat(line, name);
+
+ sprintf(name, " aAngleZactual=%.2f", m_angleZactual);
+ strcat(line, name);
+
+ sprintf(name, " aAngleYfinal=%.2f", m_angleYfinal);
+ strcat(line, name);
+
+ sprintf(name, " aAngleZfinal=%.2f", m_angleZfinal);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoTower::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoTowerPhase)OpInt(line, "aPhase", ATP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+ m_targetPos = OpDir(line, "aTargetPos");
+ m_angleYactual = OpFloat(line, "aAngleYactual", 0.0f);
+ m_angleZactual = OpFloat(line, "aAngleZactual", 0.0f);
+ m_angleYfinal = OpFloat(line, "aAngleYfinal", 0.0f);
+ m_angleZfinal = OpFloat(line, "aAngleZfinal", 0.0f);
+
+ m_lastUpdateTime = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autotower.h b/src/object/auto/autotower.h
index b64ad3d..c9393ff 100644
--- a/src/object/auto/autotower.h
+++ b/src/object/auto/autotower.h
@@ -1,74 +1,74 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autotower.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoTowerPhase
-{
- ATP_WAIT = 1,
- ATP_ZERO = 2, // more energy
- ATP_SEARCH = 3, // search a target
- ATP_TURN = 4, // turns to the target
- ATP_FIRE = 5, // shoots on the target
-};
-
-
-
-class CAutoTower : public CAuto
-{
-public:
- CAutoTower(CInstanceManager* iMan, CObject* object);
- ~CAutoTower();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- void UpdateInterface(float rTime);
-
- CObject* SearchTarget(Math::Vector &impact);
- void FireStopUpdate(float progress, bool bLightOn);
-
-protected:
- AutoTowerPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastUpdateTime;
- float m_lastParticule;
- Math::Vector m_targetPos;
- float m_angleYactual;
- float m_angleZactual;
- float m_angleYfinal;
- float m_angleZfinal;
- int m_partiStop[4];
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autotower.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoTowerPhase
+{
+ ATP_WAIT = 1,
+ ATP_ZERO = 2, // more energy
+ ATP_SEARCH = 3, // search a target
+ ATP_TURN = 4, // turns to the target
+ ATP_FIRE = 5, // shoots on the target
+};
+
+
+
+class CAutoTower : public CAuto
+{
+public:
+ CAutoTower(CInstanceManager* iMan, CObject* object);
+ ~CAutoTower();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ void UpdateInterface(float rTime);
+
+ CObject* SearchTarget(Math::Vector &impact);
+ void FireStopUpdate(float progress, bool bLightOn);
+
+protected:
+ AutoTowerPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastUpdateTime;
+ float m_lastParticule;
+ Math::Vector m_targetPos;
+ float m_angleYactual;
+ float m_angleZactual;
+ float m_angleYfinal;
+ float m_angleZfinal;
+ int m_partiStop[4];
+};
+
diff --git a/src/object/brain.cpp b/src/object/brain.cpp
index afc9903..b720992 100644
--- a/src/object/brain.cpp
+++ b/src/object/brain.cpp
@@ -1,2999 +1,2999 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/brain.h"
-
-#include "CBot/CBotDll.h"
-#include "common/struct.h"
-#include "math/geometry.h"
-#include "math/const.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/language.h"
-#include "common/global.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "old/math3d.h"
-#include "object/robotmain.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "old/camera.h"
-#include "object/object.h"
-#include "physics/physics.h"
-#include "object/motion/motion.h"
-#include "object/motion/motionspider.h"
-#include "old/pyro.h"
-#include "object/task/taskmanager.h"
-#include "object/task/task.h"
-#include "object/task/taskmanip.h"
-#include "object/task/taskflag.h"
-#include "object/task/taskshield.h"
-#include "script/script.h"
-#include "ui/studio.h"
-#include "ui/interface.h"
-#include "ui/button.h"
-#include "ui/color.h"
-#include "ui/edit.h"
-#include "ui/list.h"
-#include "ui/label.h"
-#include "ui/group.h"
-#include "ui/gauge.h"
-#include "ui/slider.h"
-#include "ui/compass.h"
-#include "ui/target.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-#include "old/text.h"
-#include "old/sound.h"
-#include "old/particule.h"
-#include "script/cmdtoken.h"
-
-
-
-const int MAXTRACERECORD = 1000;
-
-
-
-// Object's constructor.
-
-CBrain::CBrain(CInstanceManager* iMan, CObject* object)
-{
- int i;
-
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_BRAIN, this, 100);
-
- m_object = object;
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
- m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_physics = 0;
- m_motion = 0;
- m_primaryTask = 0;
- m_secondaryTask = 0;
- m_studio = 0;
-
- m_program = -1;
- m_bActivity = true;
- m_bBurn = false;
- m_bActiveVirus = false;
- m_time = 0.0f;
- m_burnTime = 0.0f;
- m_lastUpdateTime = 0.0f;
- m_lastHumanTime = 0.0f;
- m_lastWormTime = 0.0f;
- m_antTarget = 0;
- m_beeBullet = 0;
- m_lastAlarmTime = 0.0f;
- m_soundChannelAlarm = -1;
- m_flagColor = 0;
-
- m_buttonAxe = EVENT_NULL;
- m_defaultEnter = EVENT_NULL;
- m_manipStyle = EVENT_OBJECT_MFRONT;
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- m_script[i] = 0;
- m_scriptName[i][0] = 0;
- }
- m_scriptRun = -1;
- m_soluceName[0] = 0;
- m_selScript = 0;
-
- m_bTraceRecord = false;
- m_traceRecordBuffer = 0;
-}
-
-// Object's destructor.
-
-CBrain::~CBrain()
-{
- int i;
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- delete m_script[i];
- }
-
- delete m_primaryTask;
- delete m_secondaryTask;
- delete m_studio;
- delete m_traceRecordBuffer;
- m_iMan->DeleteInstance(CLASS_BRAIN, this);
-}
-
-
-// Destroys the object.
-
-void CBrain::DeleteObject(bool bAll)
-{
- if ( m_soundChannelAlarm != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannelAlarm);
- m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 0.5f, 0.5f, SOPER_STOP);
- m_soundChannelAlarm = -1;
- }
-
- if ( !bAll )
- {
- if ( m_beeBullet != 0 )
- {
- m_beeBullet->DeleteObject();
- delete m_beeBullet;
- m_beeBullet = 0;
- }
- }
-
- if ( m_studio != 0 ) // current edition?
- {
- StopEditScript(true);
- }
-}
-
-
-void CBrain::SetPhysics(CPhysics* physics)
-{
- m_physics = physics;
-}
-
-void CBrain::SetMotion(CMotion* motion)
-{
- m_motion = motion;
-}
-
-
-// Saves all parameters of the object.
-
-bool CBrain::Write(char *line)
-{
- char name[100];
-
- sprintf(name, " bVirusActive=%d", m_bActiveVirus);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the object.
-
-bool CBrain::Read(char *line)
-{
- m_bActiveVirus = OpInt(line, "bVirusActive", 0);
-
- return true;
-}
-
-
-// Management of an event.
-
-bool CBrain::EventProcess(const Event &event)
-{
- CWindow* pw;
- CControl* pc;
- CSlider* ps;
- EventMsg action;
- ObjectType type;
- Error err;
- float axeX, axeY, axeZ, factor;
-
- type = m_object->RetType();
-
- if ( m_primaryTask != 0 ) // current task?
- {
- m_primaryTask->EventProcess(event);
- }
-
- if ( m_secondaryTask != 0 ) // current task?
- {
- m_secondaryTask->EventProcess(event);
- }
-
- action = EVENT_NULL;
-
- if ( event.event == EVENT_KEYDOWN &&
- (event.param == m_engine->RetKey(KEYRANK_ACTION, 0) ||
- event.param == m_engine->RetKey(KEYRANK_ACTION, 1) ) &&
- !m_main->RetEditLock() )
- {
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw != 0 )
- {
- pc = pw->SearchControl(m_defaultEnter);
- if ( pc != 0 )
- {
- if ( pc->TestState(STATE_ENABLE) )
- {
- action = m_defaultEnter;
- }
- }
- }
- }
- else
- {
- action = event.event;
- }
-
- if ( action == EVENT_NULL ) return true;
-
- if ( action == EVENT_UPDINTERFACE )
- {
- if ( m_object->RetSelect() ) CreateInterface(true);
- }
-
- if ( action == EVENT_FRAME )
- {
- EventFrame(event);
- }
-
- if ( m_object->RetSelect() && // robot selected?
- m_studio != 0 ) // current issue?
- {
- m_studio->EventProcess(event);
-
- if ( action == EVENT_OBJECT_PROGRUN )
- {
- if ( m_program == -1 )
- {
- RunProgram(m_selScript);
- }
- else
- {
- StopProgram();
- }
- }
- if ( action == EVENT_OBJECT_PROGSTART )
- {
- m_main->SaveOneScript(m_object);
- RunProgram(m_selScript);
- }
- if ( action == EVENT_OBJECT_PROGSTOP )
- {
- StopProgram();
- }
- if ( action == EVENT_STUDIO_OK )
- {
- StopEditScript(false);
- m_main->SaveOneScript(m_object);
- }
- if ( action == EVENT_STUDIO_CANCEL )
- {
- StopEditScript(true);
- m_main->SaveOneScript(m_object);
- }
- return true;
- }
-
- if ( !m_object->RetSelect() && // robot pas sélectionné ?
- m_program == -1 &&
- m_primaryTask == 0 )
- {
- axeX = 0.0f;
- axeY = 0.0f;
- axeZ = 0.0f;
- if ( m_object->RetBurn() ) // Gifted?
- {
- if ( !m_bBurn ) // beginning?
- {
- m_bBurn = true;
- m_burnTime = 0.0f;
- }
-
- axeZ = -1.0f; // tomb
-
- if ( !m_object->RetFixed() &&
- (type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_WORM ) )
- {
- axeY = 2.0f; // zigzag disorganized fast
- if ( type == OBJECT_WORM ) axeY = 5.0f;
- axeX = 0.5f+sinf(m_time* 1.0f)*0.5f+
- sinf(m_time* 6.0f)*2.0f+
- sinf(m_time*21.0f)*0.2f;
- factor = 1.0f-m_burnTime/15.0f; // slow motion
- if ( factor < 0.0f ) factor = 0.0f;
- axeY *= factor;
- axeX *= factor;
- }
- }
- m_physics->SetMotorSpeedX(axeY); // move forward/move back
- m_physics->SetMotorSpeedY(axeZ); // up / down
- m_physics->SetMotorSpeedZ(axeX); // rotate
- return true;
- }
-
- if ( m_program != -1 &&
- m_object->RetRuin() )
- {
- StopProgram();
- return true;
- }
-
- if ( !m_object->RetSelect() ) // robot not selected?
- {
- return true;
- }
-
- if ( m_secondaryTask != 0 ) // current task?
- {
- if ( action == EVENT_OBJECT_ENDSHIELD )
- {
- m_secondaryTask->StartTaskShield(TSM_DOWN, 0.0f);
- }
- }
- if ( m_primaryTask != 0 || // current task?
- m_program != -1 )
- {
- if ( action == EVENT_OBJECT_PROGRUN )
- {
- StopProgram();
- }
- if ( action == EVENT_OBJECT_PROGEDIT )
- {
- StartEditScript(m_selScript, m_main->RetScriptName());
- }
- if ( m_primaryTask == 0 || !m_primaryTask->IsPilot() ) return true;
- }
-
- if ( action == EVENT_OBJECT_LEFT ||
- action == EVENT_OBJECT_RIGHT ||
- action == EVENT_OBJECT_UP ||
- action == EVENT_OBJECT_DOWN ||
- action == EVENT_OBJECT_GASUP ||
- action == EVENT_OBJECT_GASDOWN )
- {
- m_buttonAxe = action;
- }
- if ( action == EVENT_LBUTTONUP ||
- action == EVENT_RBUTTONUP )
- {
- m_buttonAxe = EVENT_NULL;
- }
-
- axeX = event.axeX;
- axeY = event.axeY;
- axeZ = event.axeZ;
-
- if ( !m_main->RetTrainerPilot() &&
- m_object->RetTrainer() ) // drive vehicle?
- {
- axeX = 0.0f;
- axeY = 0.0f;
- axeZ = 0.0f; // Remote control impossible!
- }
-
- if ( m_buttonAxe == EVENT_OBJECT_LEFT ) axeX = -1.0f;
- if ( m_buttonAxe == EVENT_OBJECT_RIGHT ) axeX = 1.0f;
- if ( m_buttonAxe == EVENT_OBJECT_UP ) axeY = 1.0f;
- if ( m_buttonAxe == EVENT_OBJECT_DOWN ) axeY = -1.0f;
- if ( m_buttonAxe == EVENT_OBJECT_GASUP ) axeZ = 1.0f;
- if ( m_buttonAxe == EVENT_OBJECT_GASDOWN ) axeZ = -1.0f;
-
- if ( m_object->RetManual() ) // scribbler in manual mode?
- {
- if ( axeX != 0.0f ) axeY = 0.0f; // if running -> not moving!
- axeX *= 0.5f;
- axeY *= 0.5f;
- }
-
- if ( (g_researchDone&RESEARCH_FLY) == 0 )
- {
- axeZ = -1.0f; // tomb
- }
-
- axeX += m_camera->RetMotorTurn(); // additional power according to camera
- if ( axeX > 1.0f ) axeX = 1.0f;
- if ( axeX < -1.0f ) axeX = -1.0f;
-
- m_physics->SetMotorSpeedX(axeY); // move forward/move back
- m_physics->SetMotorSpeedY(axeZ); // up/down
- m_physics->SetMotorSpeedZ(axeX); // rotate
-
- if ( action == EVENT_OBJECT_PROGLIST )
- {
- m_selScript = RetSelScript();
- UpdateInterface();
- }
-
- if ( action == EVENT_OBJECT_PROGEDIT )
- {
- StartEditScript(m_selScript, m_main->RetScriptName());
- }
-
- if ( action == EVENT_OBJECT_PROGRUN )
- {
- StopProgram(); // stops the current program
- RunProgram(m_selScript);
- UpdateInterface();
- }
-
- err = ERR_OK;
-
- if ( m_program == -1 )
- {
- if ( action == EVENT_OBJECT_HTAKE )
- {
- err = StartTaskTake();
- }
-
- if ( action == EVENT_OBJECT_MFRONT ||
- action == EVENT_OBJECT_MBACK ||
- action == EVENT_OBJECT_MPOWER )
- {
- m_manipStyle = action;
- UpdateInterface();
- }
-
- if ( action == EVENT_OBJECT_MTAKE )
- {
- if ( m_manipStyle == EVENT_OBJECT_MFRONT )
- {
- err = StartTaskManip(TMO_AUTO, TMA_FFRONT);
- }
- if ( m_manipStyle == EVENT_OBJECT_MBACK )
- {
- err = StartTaskManip(TMO_AUTO, TMA_FBACK);
- if ( err == ERR_OK )
- {
- m_manipStyle = EVENT_OBJECT_MFRONT;
- UpdateInterface();
- }
- }
- if ( m_manipStyle == EVENT_OBJECT_MPOWER )
- {
- err = StartTaskManip(TMO_AUTO, TMA_POWER);
- if ( err == ERR_OK )
- {
- m_manipStyle = EVENT_OBJECT_MFRONT;
- UpdateInterface();
- }
- }
- }
-
- if ( action == EVENT_OBJECT_BDERRICK )
- {
- err = StartTaskBuild(OBJECT_DERRICK);
- }
- if ( action == EVENT_OBJECT_BSTATION )
- {
- err = StartTaskBuild(OBJECT_STATION);
- }
- if ( action == EVENT_OBJECT_BFACTORY )
- {
- err = StartTaskBuild(OBJECT_FACTORY);
- }
- if ( action == EVENT_OBJECT_BREPAIR )
- {
- err = StartTaskBuild(OBJECT_REPAIR);
- }
- if ( action == EVENT_OBJECT_BCONVERT )
- {
- err = StartTaskBuild(OBJECT_CONVERT);
- }
- if ( action == EVENT_OBJECT_BTOWER )
- {
- err = StartTaskBuild(OBJECT_TOWER);
- }
- if ( action == EVENT_OBJECT_BRESEARCH )
- {
- err = StartTaskBuild(OBJECT_RESEARCH);
- }
- if ( action == EVENT_OBJECT_BRADAR )
- {
- err = StartTaskBuild(OBJECT_RADAR);
- }
- if ( action == EVENT_OBJECT_BENERGY )
- {
- err = StartTaskBuild(OBJECT_ENERGY);
- }
- if ( action == EVENT_OBJECT_BLABO )
- {
- err = StartTaskBuild(OBJECT_LABO);
- }
- if ( action == EVENT_OBJECT_BNUCLEAR )
- {
- err = StartTaskBuild(OBJECT_NUCLEAR);
- }
- if ( action == EVENT_OBJECT_BPARA )
- {
- err = StartTaskBuild(OBJECT_PARA);
- }
- if ( action == EVENT_OBJECT_BINFO )
- {
- err = StartTaskBuild(OBJECT_INFO);
- }
-
- if ( action == EVENT_OBJECT_GFLAT )
- {
- GroundFlat();
- }
- if ( action == EVENT_OBJECT_FCREATE )
- {
- err = StartTaskFlag(TFL_CREATE, m_flagColor);
- }
- if ( action == EVENT_OBJECT_FDELETE )
- {
- err = StartTaskFlag(TFL_DELETE, m_flagColor);
- }
- if ( action == EVENT_OBJECT_FCOLORb ||
- action == EVENT_OBJECT_FCOLORr ||
- action == EVENT_OBJECT_FCOLORg ||
- action == EVENT_OBJECT_FCOLORy ||
- action == EVENT_OBJECT_FCOLORv )
- {
- ColorFlag(action-EVENT_OBJECT_FCOLORb);
- }
-
- if ( action == EVENT_OBJECT_SEARCH )
- {
- err = StartTaskSearch();
- }
-
- if ( action == EVENT_OBJECT_TERRAFORM )
- {
- err = StartTaskTerraform();
- }
-
- if ( action == EVENT_OBJECT_RECOVER )
- {
- err = StartTaskRecover();
- }
-
- if ( action == EVENT_OBJECT_BEGSHIELD )
- {
- err = StartTaskShield(TSM_UP);
- }
-
- if ( action == EVENT_OBJECT_DIMSHIELD )
- {
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw != 0 )
- {
- ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_DIMSHIELD);
- if ( ps != 0 )
- {
- m_object->SetParam((ps->RetVisibleValue()-(RADIUS_SHIELD_MIN/g_unit))/((RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)/g_unit));
- }
- }
- }
-
- if ( action == EVENT_OBJECT_FIRE && m_primaryTask == 0 && !m_object->RetTrainer())
- {
- if ( m_camera->RetType() != CAMERA_ONBOARD )
- {
- m_camera->SetType(CAMERA_ONBOARD);
- }
- err = StartTaskFire(0.0f);
- }
- if ( action == EVENT_OBJECT_TARGET && !m_object->RetTrainer() )
- {
- err = StartTaskGunGoal((event.pos.y-0.50f)*1.3f, (event.pos.x-0.50f)*2.0f);
- }
-
- if ( action == EVENT_OBJECT_FIREANT )
- {
-//? err = StartTaskFireAnt();
- }
-
- if ( action == EVENT_OBJECT_PEN0 ) // up
- {
- err = StartTaskPen(false, m_object->RetTraceColor());
- m_object->SetTraceDown(false);
- }
- if ( action == EVENT_OBJECT_PEN1 ) // black
- {
- err = StartTaskPen(true, 1);
- m_object->SetTraceDown(true);
- m_object->SetTraceColor(1);
- }
- if ( action == EVENT_OBJECT_PEN2 ) // yellow
- {
- err = StartTaskPen(true, 8);
- m_object->SetTraceDown(true);
- m_object->SetTraceColor(8);
- }
- if ( action == EVENT_OBJECT_PEN3 ) // orange
- {
- err = StartTaskPen(true, 7);
- m_object->SetTraceDown(true);
- m_object->SetTraceColor(7);
- }
- if ( action == EVENT_OBJECT_PEN4 ) // red
- {
- err = StartTaskPen(true, 4);
- m_object->SetTraceDown(true);
- m_object->SetTraceColor(4);
- }
- if ( action == EVENT_OBJECT_PEN5 ) // violet
- {
- err = StartTaskPen(true, 6);
- m_object->SetTraceDown(true);
- m_object->SetTraceColor(6);
- }
- if ( action == EVENT_OBJECT_PEN6 ) // blue
- {
- err = StartTaskPen(true, 14);
- m_object->SetTraceDown(true);
- m_object->SetTraceColor(14);
- }
- if ( action == EVENT_OBJECT_PEN7 ) // green
- {
- err = StartTaskPen(true, 12);
- m_object->SetTraceDown(true);
- m_object->SetTraceColor(12);
- }
- if ( action == EVENT_OBJECT_PEN8 ) // brown
- {
- err = StartTaskPen(true, 10);
- m_object->SetTraceDown(true);
- m_object->SetTraceColor(10);
- }
-
- if ( action == EVENT_OBJECT_REC ) // registered?
- {
- if ( m_bTraceRecord )
- {
- m_bTraceRecord = false;
- TraceRecordStop();
- }
- else
- {
- m_bTraceRecord = true;
- TraceRecordStart();
- }
- UpdateInterface();
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw != 0 )
- {
- UpdateScript(pw);
- }
- }
- if ( action == EVENT_OBJECT_STOP ) // stops?
- {
- if ( m_bTraceRecord )
- {
- m_bTraceRecord = false;
- TraceRecordStop();
- }
- UpdateInterface();
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw != 0 )
- {
- UpdateScript(pw);
- }
- }
-
- if ( action == EVENT_OBJECT_RESET )
- {
- m_main->ResetObject(); // reset all objects
- UpdateInterface();
- }
-
-#if 0
- if ( event.param == 'T' )
- {
- Math::Vector p1, p2;
- float h;
- p1 = m_object->RetPosition(0);
- h = m_terrain->RetFloorLevel(p1);
- p2 = p1;
- p1.x -= 20.0f;
- p1.z -= 20.0f;
- p2.x += 20.0f;
- p2.z += 20.0f;
- m_terrain->Terraform(p1, p2, h+1.0f);
- }
- if ( event.param == 'R' )
- {
- Math::Vector p1, p2;
- float h;
- p1 = m_object->RetPosition(0);
- h = m_terrain->RetFloorLevel(p1);
- p2 = p1;
- p1.x -= 20.0f;
- p1.z -= 20.0f;
- p2.x += 20.0f;
- p2.z += 20.0f;
- m_terrain->Terraform(p1, p2, h-1.0f);
- }
-#endif
- }
-
- if ( err != ERR_OK )
- {
- m_displayText->DisplayError(err, m_object);
- }
-
- return true;
-}
-
-
-// The brain is changing by time.
-
-bool CBrain::EventFrame(const Event &event)
-{
- m_time += event.rTime;
- if ( m_bBurn ) m_burnTime += event.rTime;
-
- if ( m_soundChannelAlarm != -1 )
- {
- m_sound->Position(m_soundChannelAlarm, m_object->RetPosition(0));
- }
-
- if ( m_studio != 0 ) // �urrent edition?
- {
- m_studio->EventProcess(event);
- }
-
- UpdateInterface(event.rTime);
-
- if ( m_engine->RetPause() ) return true;
- if ( !m_bActivity ) return true; // expected if idle
- if ( EndedTask() == ERR_CONTINUE ) return true; // expected if not finished ...
-
- if ( m_program != -1 ) // current program?
- {
- if ( m_script[m_program]->Continue(event) )
- {
- StopProgram();
- }
- }
-
- if ( m_bTraceRecord ) // registration of the design in progress?
- {
- TraceRecordFrame();
- }
-
- return true;
-}
-
-
-// Stops the running program.
-
-void CBrain::StopProgram()
-{
- StopTask();
-
- if ( m_object->RetType() == OBJECT_HUMAN ||
- m_object->RetType() == OBJECT_TECH ) return;
-
- if ( m_program != -1 &&
- m_script[m_program] != 0 )
- {
- m_script[m_program]->Stop();
- }
-
- BlinkScript(false); // stops flashing
-
- m_program = -1;
-
- m_physics->SetMotorSpeedX(0.0f);
- m_physics->SetMotorSpeedY(0.0f);
- m_physics->SetMotorSpeedZ(0.0f);
-
- m_motion->SetAction(-1);
-
- UpdateInterface();
- m_main->UpdateShortcuts();
- m_object->CreateSelectParticule();
-}
-
-// Stops the current task.
-
-void CBrain::StopTask()
-{
- if ( m_primaryTask != 0 )
- {
- m_primaryTask->Abort();
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-}
-
-
-// Introduces a virus into a program.
-// Returns true if it was inserted.
-
-bool CBrain::IntroduceVirus()
-{
- int i, j;
-
- for ( i=0 ; i<50 ; i++ )
- {
- j = rand()%BRAINMAXSCRIPT;
- if ( m_script[j] != 0 )
- {
- if ( m_script[j]->IntroduceVirus() ) // tries to introduce
- {
- m_bActiveVirus = true; // active virus
- return true;
- }
- }
- }
- return false;
-}
-
-// Active Virus indicates that the object is contaminated. Unlike ch'tites (??? - Programerus)
-// letters which automatically disappear after a while,
-// ActiveVirus does not disappear after you edit the program
-// (Even if the virus is not fixed).
-
-
-void CBrain::SetActiveVirus(bool bActive)
-{
- m_bActiveVirus = bActive;
-
- if ( !m_bActiveVirus ) // virus disabled?
- {
- m_object->SetVirusMode(false); // chtites (??? - Programerus) letters also
- }
-}
-
-bool CBrain::RetActiveVirus()
-{
- return m_bActiveVirus;
-}
-
-
-// Start editing a program.
-
-void CBrain::StartEditScript(int rank, char* name)
-{
- CreateInterface(false); // removes the control buttons
-
- if ( m_script[rank] == 0 )
- {
- m_script[rank] = new CScript(m_iMan, m_object, &m_secondaryTask);
- }
-
- m_studio = new CStudio(m_iMan);
- m_studio->StartEditScript(m_script[rank], name, rank);
-}
-
-// End of editing a program.
-
-void CBrain::StopEditScript(bool bCancel)
-{
- if ( !bCancel ) SetActiveVirus(false);
-
- if ( !m_studio->StopEditScript(bCancel) ) return;
-
- delete m_studio;
- m_studio = 0;
-
- CreateInterface(true); // puts the control buttons
-}
-
-
-
-// Move the manipulator arm.
-
-Error CBrain::StartTaskTake()
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskTake();
- UpdateInterface();
- return err;
-}
-
-// Move the manipulator arm.
-
-Error CBrain::StartTaskManip(TaskManipOrder order, TaskManipArm arm)
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskManip(order, arm);
- UpdateInterface();
- return err;
-}
-
-// Puts or removes a flag.
-
-Error CBrain::StartTaskFlag(TaskFlagOrder order, int rank)
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskFlag(order, rank);
- UpdateInterface();
- return err;
-}
-
-// Built a building.
-
-Error CBrain::StartTaskBuild(ObjectType type)
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskBuild(type);
- UpdateInterface();
- return err;
-}
-
-// Probe the ground.
-
-Error CBrain::StartTaskSearch()
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskSearch();
- UpdateInterface();
- return err;
-}
-
-// Terraformed the ground.
-
-Error CBrain::StartTaskTerraform()
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskTerraform();
- UpdateInterface();
- return err;
-}
-
-// Change pencil.
-
-Error CBrain::StartTaskPen(bool bDown, int color)
-{
- Error err;
-
- m_physics->SetMotorSpeedX(0.0f);
- m_physics->SetMotorSpeedY(0.0f);
- m_physics->SetMotorSpeedZ(0.0f);
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskPen(bDown, color);
- UpdateInterface();
- return err;
-}
-
-// Recovers a ruin.
-
-Error CBrain::StartTaskRecover()
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskRecover();
- UpdateInterface();
- return err;
-}
-
-// Deploys the shield.
-
-Error CBrain::StartTaskShield(TaskShieldMode mode)
-{
- Error err;
-
- if ( m_secondaryTask != 0 )
- {
- delete m_secondaryTask; // stops the current task
- m_secondaryTask = 0;
- }
-
- m_secondaryTask = new CTaskManager(m_iMan, m_object);
- err = m_secondaryTask->StartTaskShield(mode, 1000.0f);
- UpdateInterface();
- return err;
-}
-
-// Shoots.
-
-Error CBrain::StartTaskFire(float delay)
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskFire(delay);
- UpdateInterface();
- return err;
-}
-
-// Shoots to the ant.
-
-Error CBrain::StartTaskFireAnt(Math::Vector impact)
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskFireAnt(impact);
- UpdateInterface();
- return err;
-}
-
-// Adjusts upward.
-
-Error CBrain::StartTaskGunGoal(float dirV, float dirH)
-{
- Error err;
-
- if ( m_secondaryTask != 0 )
- {
- delete m_secondaryTask; // stops the current task
- m_secondaryTask = 0;
- }
-
- m_secondaryTask = new CTaskManager(m_iMan, m_object);
- err = m_secondaryTask->StartTaskGunGoal(dirV, dirH);
- UpdateInterface();
- return err;
-}
-
-// Reset.
-
-Error CBrain::StartTaskReset(Math::Vector goal, Math::Vector angle)
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskReset(goal, angle);
- UpdateInterface();
- return err;
-}
-
-// Completes the task when the time came.
-
-Error CBrain::EndedTask()
-{
- Error err;
-
- if ( m_secondaryTask != 0 ) // current task?
- {
- err = m_secondaryTask->IsEnded();
- if ( err != ERR_CONTINUE ) // job ended?
- {
- delete m_secondaryTask;
- m_secondaryTask = 0;
- UpdateInterface();
- }
- }
-
- if ( m_primaryTask != 0 ) // current task?
- {
- err = m_primaryTask->IsEnded();
- if ( err != ERR_CONTINUE ) // job ended?
- {
- delete m_primaryTask;
- m_primaryTask = 0;
- UpdateInterface();
- }
- return err;
- }
- return ERR_STOP;
-}
-
-
-
-// Shows flat areas in the field.
-
-void CBrain::GroundFlat()
-{
- Math::Vector pos, speed;
- Math::Point dim;
- Error err;
- float level;
-
- if ( !m_physics->RetLand() )
- {
- err = ERR_FLAG_FLY;
- pos = m_object->RetPosition(0);
- if ( pos.y < m_water->RetLevel() ) err = ERR_FLAG_WATER;
- m_displayText->DisplayError(err, m_object);
- return;
- }
-
- pos = m_object->RetPosition(0);
- m_terrain->GroundFlat(pos);
- m_sound->Play(SOUND_GFLAT, pos);
-
- level = m_terrain->RetFloorLevel(pos)+2.0f;
- if ( pos.y < level ) pos.y = level; // not below the soil
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 40.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGFLAT, 1.0f);
-}
-
-
-// Not below the soil.
-
-void CBrain::ColorFlag(int color)
-{
- m_flagColor = color;
- UpdateInterface();
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CBrain::CreateInterface(bool bSelect)
-{
- ObjectType type;
- CWindow* pw;
- CButton* pb;
- CColor* pc;
- CSlider* ps;
- CTarget* pt;
- CLabel* pl;
- Math::Point pos, dim, ddim;
- float ox, oy, sx, sy;
- char name[100];
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw != 0 )
- {
- pw->Flush(); // destroys the window buttons
- m_interface->DeleteControl(EVENT_WINDOW0); // destroys the window
- }
- m_defaultEnter = EVENT_NULL;
-
- if ( !bSelect ) return true;
-
- pos.x = 0.0f;
- pos.y = 0.0f;
- dim.x = 540.0f/640.0f;
- if ( !m_main->RetShowMap() ) dim.x = 640.0f/640.0f;
- dim.y = 86.0f/480.0f;
- m_interface->CreateWindows(pos, dim, 3, EVENT_WINDOW0);
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- m_object->GetTooltipName(name);
- pos.x = 0.0f;
- pos.y = 64.0f/480.0f;
- ddim.x = 540.0f/640.0f;
- if ( !m_main->RetShowMap() ) ddim.x = 640.0f/640.0f;
- ddim.y = 16.0f/480.0f;
- pw->CreateLabel(pos, ddim, 0, EVENT_LABEL0, name);
-
- dim.x = 33.0f/640.0f;
- dim.y = 33.0f/480.0f;
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- type = m_object->RetType();
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr ||
- type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ) // vehicle?
- {
- ddim.x = dim.x*5.1f;
- ddim.y = dim.y*2.0f;
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0.0f;
- pw->CreateList(pos, ddim, -1, EVENT_OBJECT_PROGLIST, 1.10f);
- UpdateScript(pw);
-
- pos.x = ox+sx*5.2f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, dim, 8, EVENT_OBJECT_PROGRUN);
- pos.y = oy+sy*0.0f;
- pw->CreateButton(pos, dim, 22, EVENT_OBJECT_PROGEDIT);
- }
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_BEE ) // driving?
- {
- pos.x = ox+sx*6.4f;
- pos.y = oy+sy*0;
- pb = pw->CreateButton(pos, dim, 29, EVENT_OBJECT_GASDOWN);
- pb->SetImmediat(true);
-
- pos.x = ox+sx*6.4f;
- pos.y = oy+sy*1;
- pb = pw->CreateButton(pos, dim, 28, EVENT_OBJECT_GASUP);
- pb->SetImmediat(true);
-
- if ( type != OBJECT_HUMAN ||
- m_object->RetOption() != 2 )
- {
- pos.x = ox+sx*15.3f;
- pos.y = oy+sy*0;
- ddim.x = 14.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGauge(pos, ddim, 2, EVENT_OBJECT_GRANGE);
- }
- }
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH )
- {
- pos.x = ox+sx*7.7f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 31, EVENT_OBJECT_HTAKE);
- DefaultEnter(pw, EVENT_OBJECT_HTAKE);
- }
-
- if ( (type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ) && // arm?
- !m_object->RetTrainer() )
- {
- pos.x = ox+sx*7.7f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 32, EVENT_OBJECT_MTAKE);
- DefaultEnter(pw, EVENT_OBJECT_MTAKE);
-
- pos.x = ox+sx*8.9f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 34, EVENT_OBJECT_MBACK);
-
- pos.x = ox+sx*9.9f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 35, EVENT_OBJECT_MPOWER);
-
- pos.x = ox+sx*10.9f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 33, EVENT_OBJECT_MFRONT);
- }
-
- if ( type == OBJECT_MOBILEsa && // underwater?
- !m_object->RetTrainer() )
- {
- pos.x = ox+sx*7.7f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 32, EVENT_OBJECT_MTAKE);
- DefaultEnter(pw, EVENT_OBJECT_MTAKE);
- }
-
- if ( type == OBJECT_HUMAN ) // builder?
- {
- pos.x = 1.0f/640.0f;
- pos.y = 4.0f/480.0f;
- ddim.x = 212.0f/640.0f;
- ddim.y = 64.0f/480.0f;
- pw->CreateGroup(pos, ddim, 27, EVENT_NULL);
-
- ddim.x = dim.x*0.9f;
- ddim.y = dim.y*0.9f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, ddim, 128+35, EVENT_OBJECT_BRESEARCH);
- DeadInterface(pw, EVENT_OBJECT_BRESEARCH, g_build&BUILD_RESEARCH);
-
- pos.x = ox+sx*0.9f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, ddim, 128+32, EVENT_OBJECT_BFACTORY);
- DeadInterface(pw, EVENT_OBJECT_BFACTORY, g_build&BUILD_FACTORY);
-
- pos.x = ox+sx*1.8f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, ddim, 128+34, EVENT_OBJECT_BCONVERT);
- DeadInterface(pw, EVENT_OBJECT_BCONVERT, g_build&BUILD_CONVERT);
-
- pos.x = ox+sx*2.7f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, ddim, 128+36, EVENT_OBJECT_BSTATION);
- DeadInterface(pw, EVENT_OBJECT_BSTATION, g_build&BUILD_STATION);
-
- pos.x = ox+sx*3.6f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, ddim, 128+40, EVENT_OBJECT_BRADAR);
- DeadInterface(pw, EVENT_OBJECT_BRADAR, g_build&BUILD_RADAR);
-
- pos.x = ox+sx*4.5f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, ddim, 128+41, EVENT_OBJECT_BREPAIR);
- DeadInterface(pw, EVENT_OBJECT_BREPAIR, g_build&BUILD_REPAIR);
-
- pos.x = ox+sx*5.4f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, ddim, 128+44, EVENT_OBJECT_BINFO);
- DeadInterface(pw, EVENT_OBJECT_BINFO, g_build&BUILD_INFO);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0.1f;
- pw->CreateButton(pos, ddim, 128+37, EVENT_OBJECT_BTOWER);
- DeadInterface(pw, EVENT_OBJECT_BTOWER,
- (g_build&BUILD_TOWER) &&
- (g_researchDone & RESEARCH_TOWER));
-
- pos.x = ox+sx*0.9f;
- pos.y = oy+sy*0.1f;
- pw->CreateButton(pos, ddim, 128+39, EVENT_OBJECT_BENERGY);
- DeadInterface(pw, EVENT_OBJECT_BENERGY, g_build&BUILD_ENERGY);
-
- pos.x = ox+sx*1.8f;
- pos.y = oy+sy*0.1f;
- pw->CreateButton(pos, ddim, 128+33, EVENT_OBJECT_BDERRICK);
- DeadInterface(pw, EVENT_OBJECT_BDERRICK, g_build&BUILD_DERRICK);
-
- pos.x = ox+sx*2.7f;
- pos.y = oy+sy*0.1f;
- pw->CreateButton(pos, ddim, 128+42, EVENT_OBJECT_BNUCLEAR);
- DeadInterface(pw, EVENT_OBJECT_BNUCLEAR,
- (g_build&BUILD_NUCLEAR) &&
- (g_researchDone & RESEARCH_ATOMIC));
-
- pos.x = ox+sx*3.6f;
- pos.y = oy+sy*0.1f;
- pw->CreateButton(pos, ddim, 128+38, EVENT_OBJECT_BLABO);
- DeadInterface(pw, EVENT_OBJECT_BLABO, g_build&BUILD_LABO);
-
- pos.x = ox+sx*4.5f;
- pos.y = oy+sy*0.1f;
- pw->CreateButton(pos, ddim, 128+46, EVENT_OBJECT_BPARA);
- DeadInterface(pw, EVENT_OBJECT_BPARA, g_build&BUILD_PARA);
-
- pos.x = ox+sx*5.4f;
- pos.y = oy+sy*0.1f;
- pw->CreateButton(pos, ddim, 128+56, EVENT_OBJECT_BXXXX);
- DeadInterface(pw, EVENT_OBJECT_BXXXX, false);
-
- if ( g_build&BUILD_GFLAT )
- {
- pos.x = ox+sx*9.0f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 64+47, EVENT_OBJECT_GFLAT);
- }
-
- if ( g_build&BUILD_FLAG )
- {
- pos.x = ox+sx*10.1f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 64+54, EVENT_OBJECT_FCREATE);
-
- pos.x = ox+sx*11.1f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 64+55, EVENT_OBJECT_FDELETE);
-
- ddim.x = dim.x*0.4f;
- ddim.y = dim.y*0.4f;
- pos.x = ox+sx*10.1f;
- pos.y = oy+sy*2.0f-ddim.y;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORb);
- pc->SetColor(RetColor((D3DCOLOR)0x004890ff));
- pos.x += ddim.x;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORr);
- pc->SetColor(RetColor((D3DCOLOR)0x00ff0000));
- pos.x += ddim.x;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORg);
- pc->SetColor(RetColor((D3DCOLOR)0x0000ce00));
- pos.x += ddim.x;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORy);
- pc->SetColor(RetColor((D3DCOLOR)0x00ffec00));
- pos.x += ddim.x;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORv);
- pc->SetColor(RetColor((D3DCOLOR)0x00d101fe));
- }
- }
-
- if ( (type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ) && // Investigator?
- !m_object->RetTrainer() )
- {
- pos.x = ox+sx*7.7f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 40, EVENT_OBJECT_SEARCH);
- DefaultEnter(pw, EVENT_OBJECT_SEARCH);
- }
-
- if ( type == OBJECT_MOBILErt && // Terraformer?
- !m_object->RetTrainer() )
- {
- pos.x = ox+sx*7.7f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 128+18, EVENT_OBJECT_TERRAFORM);
- DefaultEnter(pw, EVENT_OBJECT_TERRAFORM);
-
- pos.x = ox+sx*10.2f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT);
- }
-
- if ( type == OBJECT_MOBILErr && // recoverer?
- !m_object->RetTrainer() )
- {
- pos.x = ox+sx*7.7f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 128+20, EVENT_OBJECT_RECOVER);
- DefaultEnter(pw, EVENT_OBJECT_RECOVER);
- }
-
- if ( type == OBJECT_MOBILErs && // shield?
- !m_object->RetTrainer() )
- {
- pos.x = ox+sx*7.7f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 39, EVENT_OBJECT_BEGSHIELD);
- DefaultEnter(pw, EVENT_OBJECT_BEGSHIELD);
-
- pos.x = ox+sx*9.0f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 47, EVENT_OBJECT_ENDSHIELD);
-
-//? pos.x = ox+sx*10.2f;
-//? pos.y = oy+sy*0.5f;
-//? pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT);
-
- pos.x = ox+sx*10.5f;
- pos.y = oy+sy*0.0f;
- ddim.x = dim.x*0.5f;
- ddim.y = dim.y*2.0f;
- ps = pw->CreateSlider(pos, ddim, 0, EVENT_OBJECT_DIMSHIELD);
- ps->SetState(STATE_VALUE);
- ps->SetLimit((RADIUS_SHIELD_MIN/g_unit), (RADIUS_SHIELD_MAX/g_unit));
- ps->SetArrowStep(1.0f);
- }
-
- if ( (type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILErc ) && // cannon?
- !m_object->RetTrainer() )
- {
- pos.x = ox+sx*7.7f;
- pos.y = oy+sy*0.5f;
- pb = pw->CreateButton(pos, dim, 42, EVENT_OBJECT_FIRE);
- pb->SetImmediat(true);
- DefaultEnter(pw, EVENT_OBJECT_FIRE);
-
-//? pos.x = ox+sx*10.2f;
-//? pos.y = oy+sy*0.5f;
-//? pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT);
- }
-
- if ( type == OBJECT_MOBILEdr &&
- m_object->RetManual() ) // scribbler in manual mode?
- {
- pos.x = ox+sx*6.9f;
- pos.y = oy+sy*0.0f;
- ddim.x = dim.x*2.2f;
- ddim.y = dim.y*2.0f;
- pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
-
- pos.x = ox+sx*9.3f;
- pos.y = oy+sy*0.0f;
- ddim.x = dim.x*2.2f;
- ddim.y = dim.y*2.0f;
- pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
-
- pos.x = ox+sx*9.90f;
- pos.y = oy+sy*0.50f;
- pw->CreateButton(pos, dim, 43, EVENT_OBJECT_PEN0);
-
- ddim.x = dim.x*0.5f;
- ddim.y = dim.y*0.5f;
- pos.x = ox+sx*10.15f;
- pos.y = oy+sy*1.50f;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN1); // black
- pc->SetColor(RetColor((D3DCOLOR)0x00000000));
- pos.x = ox+sx*10.65f;
- pos.y = oy+sy*1.25f;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN2); // yellow
- pc->SetColor(RetColor((D3DCOLOR)0x00ffff00));
- pos.x = ox+sx*10.90f;
- pos.y = oy+sy*0.75f;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN3); // orange
- pc->SetColor(RetColor((D3DCOLOR)0x00ff8800));
- pos.x = ox+sx*10.65f;
- pos.y = oy+sy*0.25f;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN4); // red
- pc->SetColor(RetColor((D3DCOLOR)0x00ff0000));
- pos.x = ox+sx*10.15f;
- pos.y = oy+sy*0.00f;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN5); // violet
- pc->SetColor(RetColor((D3DCOLOR)0x00ff00ff));
- pos.x = ox+sx*9.65f;
- pos.y = oy+sy*0.25f;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN6); // blue
- pc->SetColor(RetColor((D3DCOLOR)0x000066ff));
- pos.x = ox+sx*9.40f;
- pos.y = oy+sy*0.75f;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN7); // green
- pc->SetColor(RetColor((D3DCOLOR)0x0000cc00));
- pos.x = ox+sx*9.65f;
- pos.y = oy+sy*1.25f;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN8); // brown
- pc->SetColor(RetColor((D3DCOLOR)0x00884400));
-
- pos.x = ox+sx*6.9f;
- pos.y = oy+sy*1.2f;
- ddim.x = dim.x*2.2f;
- ddim.y = dim.y*0.4f;
- GetResource(RES_TEXT, RT_INTERFACE_REC, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, name);
- pl->SetFontSize(9.0f);
-
- pos.x = ox+sx*7.0f;
- pos.y = oy+sy*0.3f;
- pw->CreateButton(pos, dim, 44, EVENT_OBJECT_REC);
- pos.x = ox+sx*8.0f;
- pos.y = oy+sy*0.3f;
- pw->CreateButton(pos, dim, 45, EVENT_OBJECT_STOP);
- }
-
- if ( m_object->RetToy() )
- {
- pos.x = ox+sx*12.1f;
- pos.y = oy+sy*-0.1f;
- ddim.x = dim.x*1.2f;
- ddim.y = dim.y*2.1f;
- pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
-
- pos.x = ox+sx*12.2f;
- pos.y = oy+sy*1;
- pw->CreateGroup(pos, dim, 19, EVENT_NULL); // sign SatCom
-
- pos.x = ox+sx*12.2f;
- pos.y = oy+sy*0.0f;
- pw->CreateButton(pos, dim, 128+57, EVENT_OBJECT_BHELP);
- }
- else
- {
- pos.x = ox+sx*12.3f;
- pos.y = oy+sy*-0.1f;
- ddim.x = dim.x*1.0f;
- ddim.y = dim.y*2.1f;
- pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
-
- pos.x = ox+sx*12.3f;
- pos.y = oy+sy*1;
- pw->CreateGroup(pos, dim, 19, EVENT_NULL); // sign SatCom
-
- pos.x = ox+sx*12.4f;
- pos.y = oy+sy*0.5f;
- ddim.x = dim.x*0.8f;
- ddim.y = dim.y*0.5f;
- pw->CreateButton(pos, ddim, 18, EVENT_OBJECT_BHELP);
- pos.y = oy+sy*0.0f;
- pw->CreateButton(pos, ddim, 19, EVENT_OBJECT_HELP);
- }
-
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_TECH &&
- !m_object->RetCameraLock() )
- {
-//? if ( m_main->RetShowMap() )
- if ( true )
- {
- pos.x = ox+sx*13.4f;
- pos.y = oy+sy*1;
- pw->CreateButton(pos, dim, 13, EVENT_OBJECT_CAMERA);
- }
- else
- {
- ddim.x = dim.x*0.66f;
- ddim.y = dim.y*0.66f;
- pos.x = ox+sx*(17.0f+0.66f);
- pos.y = oy+sy*0.66f;
- pw->CreateButton(pos, ddim, 13, EVENT_OBJECT_CAMERA);
- }
- }
-
- if ( m_object->RetToy() && !m_object->RetManual() )
- {
-#if 0
- ddim.x = dim.x*0.66f;
- ddim.y = dim.y*0.66f;
- pos.x = ox+sx*10.0f;
- pos.y = oy+sy*0.66f;
- pb = pw->CreateButton(pos, ddim, 55, EVENT_OBJECT_CAMERAleft);
- pb->SetImmediat(true);
- pos.x = ox+sx*(10.0f+0.66f*2.0f);
- pos.y = oy+sy*0.66f;
- pb = pw->CreateButton(pos, ddim, 48, EVENT_OBJECT_CAMERAright);
- pb->SetImmediat(true);
- pos.x = ox+sx*(10.0f+0.66f);
- pos.y = oy+sy*(0.66f*2.0f);
- pb = pw->CreateButton(pos, ddim, 49, EVENT_OBJECT_CAMERAnear);
- pb->SetImmediat(true);
- pos.x = ox+sx*(10.0f+0.66f);
- pos.y = oy+sy*0.0f;
- pb = pw->CreateButton(pos, ddim, 50, EVENT_OBJECT_CAMERAaway);
- pb->SetImmediat(true);
-#else
- pos.x = ox+sx*9.0f;
- pos.y = oy+sy*0;
- pb = pw->CreateButton(pos, dim, 55, EVENT_OBJECT_CAMERAleft);
- pb->SetImmediat(true);
- pos.x = ox+sx*11.0f;
- pos.y = oy+sy*0;
- pb = pw->CreateButton(pos, dim, 48, EVENT_OBJECT_CAMERAright);
- pb->SetImmediat(true);
- pos.x = ox+sx*10.0f;
- pos.y = oy+sy*1;
- pb = pw->CreateButton(pos, dim, 49, EVENT_OBJECT_CAMERAnear);
- pb->SetImmediat(true);
- pos.x = ox+sx*10.0f;
- pos.y = oy+sy*0;
- pb = pw->CreateButton(pos, dim, 50, EVENT_OBJECT_CAMERAaway);
- pb->SetImmediat(true);
-#endif
- }
-
- pos.x = ox+sx*13.4f;
- pos.y = oy+sy*0;
-#if _TEEN
- pw->CreateButton(pos, dim, 9, EVENT_OBJECT_RESET);
-#else
- if ( m_object->RetTrainer() ) // Training?
- {
- pw->CreateButton(pos, dim, 9, EVENT_OBJECT_RESET);
- }
- else
- {
- pw->CreateButton(pos, dim, 10, EVENT_OBJECT_DESELECT);
- }
-#endif
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ) // vehicle?
- {
- pos.x = ox+sx*14.5f;
- pos.y = oy+sy*0;
- ddim.x = 14.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
- }
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH ||
- type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ) // vehicle?
- {
- pos.x = ox+sx*14.9f;
- pos.y = oy+sy*0;
- ddim.x = 14.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGauge(pos, ddim, 3, EVENT_OBJECT_GSHIELD);
- }
-
-#if 0
- if ( false )
- {
- pos.x = 505.0f/640.0f;
- pos.y = 3.0f/480.0f;
- ddim.x = 33.0f/640.0f;
- ddim.y = 33.0f/480.0f;
- pw->CreateCompass(pos, ddim, 0, EVENT_OBJECT_COMPASS);
-
- pc = (CCompass*)pw->SearchControl(EVENT_OBJECT_COMPASS);
- if ( pc != 0 )
- {
- pc->SetState(STATE_VISIBLE, m_main->RetShowMap());
- }
- }
-#endif
-
- if ( type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILErc ) // cannon?
- {
- ddim.x = 64.0f/640.0f;
- ddim.y = 64.0f/480.0f;
- pos.x = 0.5f-ddim.x/2.0f;
- pos.y = 0.5f-ddim.y/2.0f;
- pw->CreateGroup(pos, ddim, 12, EVENT_OBJECT_CROSSHAIR);
-
- pos.x = 20.0f/640.0f;
- pos.y = 100.0f/480.0f;
- ddim.x = 600.0f/640.0f;
- ddim.y = 340.0f/480.0f;
- pt = pw->CreateTarget(pos, ddim, 0, EVENT_OBJECT_TARGET);
- pt->ClearState(STATE_GLINT);
- }
-
- ddim.x = 64.0f/640.0f;
- ddim.y = 64.0f/480.0f;
- pos.x = 30.0f/640.0f;
- pos.y = 430.0f/480.0f-ddim.y;
- pw->CreateGroup(pos, ddim, 13, EVENT_OBJECT_CORNERul);
-
- ddim.x = 64.0f/640.0f;
- ddim.y = 64.0f/480.0f;
- pos.x = 610.0f/640.0f-ddim.x;
- pos.y = 430.0f/480.0f-ddim.y;
- pw->CreateGroup(pos, ddim, 14, EVENT_OBJECT_CORNERur);
-
- ddim.x = 64.0f/640.0f;
- ddim.y = 64.0f/480.0f;
- pos.x = 30.0f/640.0f;
- pos.y = 110.0f/480.0f;
- pw->CreateGroup(pos, ddim, 15, EVENT_OBJECT_CORNERdl);
-
- ddim.x = 64.0f/640.0f;
- ddim.y = 64.0f/480.0f;
- pos.x = 610.0f/640.0f-ddim.x;
- pos.y = 110.0f/480.0f;
- pw->CreateGroup(pos, ddim, 16, EVENT_OBJECT_CORNERdr);
-
- UpdateInterface();
- m_lastUpdateTime = 0.0f;
- UpdateInterface(0.0f);
-
- return true;
-}
-
-// Updates the state of all buttons on the interface,
-// following the time that elapses ...
-
-void CBrain::UpdateInterface(float rTime)
-{
- CWindow* pw;
-#if _TEEN
- CButton* pb;
-#endif
- CGauge* pg;
- CCompass* pc;
- CGroup* pgr;
- CTarget* ptg;
- CObject* power;
- Math::Vector pos, hPos;
- Math::Point ppos;
- float energy, limit, angle, range;
- int icon;
- bool bOnBoard;
-
- m_lastAlarmTime += rTime;
- if ( m_time < m_lastUpdateTime+0.1f ) return;
- m_lastUpdateTime = m_time;
-
- if ( !m_object->RetSelect() )
- {
- if ( m_soundChannelAlarm != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannelAlarm);
- m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 1.0f, 0.1f, SOPER_STOP);
- m_soundChannelAlarm = -1;
- }
- return;
- }
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
- if ( pg != 0 )
- {
- power = m_object->RetPower();
- if ( power == 0 )
- {
- energy = 0.0f;
- }
- else
- {
- energy = power->RetEnergy();
- limit = energy*power->RetCapacity();
- }
- icon = 0; // red/green
-
- if ( limit < 0.2f && energy != 0.0f ) // low but not zero?
- {
- if ( m_lastAlarmTime >= 0.8f ) // blinks?
- {
- energy = 1.0f;
- icon = 1; // brun
- }
- if ( m_lastAlarmTime >= 1.0f )
- {
- m_sound->Play(SOUND_ALARM, 0.5f); // bip-bip-bip
- m_lastAlarmTime = 0.0f;
- }
- }
- pg->SetLevel(energy);
- pg->SetIcon(icon);
- }
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GSHIELD);
- if ( pg != 0 )
- {
- pg->SetLevel(m_object->RetShield());
- }
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GRANGE);
- if ( pg != 0 )
- {
- icon = 2; // blue/red
- range = m_physics->RetReactorRange();
-
- if ( range < 0.2f && range != 0.0f && !m_physics->RetLand() )
- {
- if ( Math::Mod(m_time, 0.5f) >= 0.2f ) // blinks?
- {
- range = 1.0f;
- icon = 1; // yellow
- }
- if ( m_soundChannelAlarm == -1 )
- {
- m_soundChannelAlarm = m_sound->Play(SOUND_ALARMt, m_object->RetPosition(0), 0.0f, 0.1f, true);
- m_sound->AddEnvelope(m_soundChannelAlarm, 1.0f, 1.0f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannelAlarm, 1.0f, 1.0f, 1.0f, SOPER_LOOP);
- }
- }
- else
- {
- if ( m_soundChannelAlarm != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannelAlarm);
- m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 0.1f, 1.0f, SOPER_STOP);
- m_soundChannelAlarm = -1;
- }
- }
-
- pg->SetLevel(1.0f-range);
- pg->SetIcon(icon);
- }
-
- pc = (CCompass*)pw->SearchControl(EVENT_OBJECT_COMPASS);
- if ( pc != 0 )
- {
- angle = -(m_object->RetAngleY(0)+Math::PI/2.0f);
- pc->SetDirection(angle);
-
- pc->SetState(STATE_VISIBLE, m_main->RetShowMap());
- }
-
-#if _TEEN
- pb = (CButton*)pw->SearchControl(EVENT_OBJECT_REC);
- if ( pb != 0 )
- {
- if ( m_bTraceRecord && Math::Mod(m_time, 0.4f) >= 0.2f )
- {
- pb->SetState(STATE_CHECK);
- }
- else
- {
- pb->ClearState(STATE_CHECK);
- }
- }
-#endif
-
- bOnBoard = m_camera->RetType() == CAMERA_ONBOARD;
-
- pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CROSSHAIR);
- if ( pgr != 0 )
- {
- if ( bOnBoard )
- {
-#if 0
- angle = m_object->RetGunGoalV();
- if ( m_object->RetType() != OBJECT_MOBILErc )
- {
- angle += 10.0f*Math::PI/360.0f;
- }
- ppos.x = 0.5f-(64.0f/640.0f)/2.0f;
- ppos.y = 0.5f-(64.0f/480.0f)/2.0f;
- ppos.y += sinf(angle)*0.6f;
- pgr->SetPos(ppos);
-#else
- ppos.x = 0.50f-(64.0f/640.0f)/2.0f;
- ppos.y = 0.50f-(64.0f/480.0f)/2.0f;
- ppos.x += m_object->RetGunGoalH()/2.0f;
- ppos.y += m_object->RetGunGoalV()/1.3f;
- pgr->SetPos(ppos);
-#endif
- pgr->SetState(STATE_VISIBLE, !m_main->RetFriendAim());
- }
- else
- {
- pgr->ClearState(STATE_VISIBLE);
- }
- }
-
- ptg = (CTarget*)pw->SearchControl(EVENT_OBJECT_TARGET);
- if ( ptg != 0 )
- {
- if ( bOnBoard )
- {
- ptg->SetState(STATE_VISIBLE);
- }
- else
- {
- ptg->ClearState(STATE_VISIBLE);
- }
- }
-
- pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERul);
- if ( pgr != 0 )
- {
- pgr->SetState(STATE_VISIBLE, bOnBoard);
- }
-
- pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERur);
- if ( pgr != 0 )
- {
- pgr->SetState(STATE_VISIBLE, bOnBoard);
- }
-
- pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERdl);
- if ( pgr != 0 )
- {
- pgr->SetState(STATE_VISIBLE, bOnBoard);
- }
-
- pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERdr);
- if ( pgr != 0 )
- {
- pgr->SetState(STATE_VISIBLE, bOnBoard);
- }
-}
-
-// Updates the status of all interface buttons.
-
-void CBrain::UpdateInterface()
-{
- ObjectType type;
- CWindow* pw;
- CButton* pb;
- CSlider* ps;
-#if _TEEN
- CColor* pc;
- int color;
-#endif
- bool bEnable, bFly, bRun;
- char title[100];
-
- if ( !m_object->RetSelect() ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- type = m_object->RetType();
-
- bEnable = ( m_secondaryTask == 0 && m_program == -1 );
-
- bEnable = ( m_primaryTask == 0 && m_program == -1 );
-
- EnableInterface(pw, EVENT_OBJECT_PROGEDIT, (m_primaryTask == 0 && !m_bTraceRecord));
- EnableInterface(pw, EVENT_OBJECT_PROGLIST, bEnable && !m_bTraceRecord);
- EnableInterface(pw, EVENT_OBJECT_LEFT, bEnable);
- EnableInterface(pw, EVENT_OBJECT_RIGHT, bEnable);
- EnableInterface(pw, EVENT_OBJECT_UP, bEnable);
- EnableInterface(pw, EVENT_OBJECT_DOWN, bEnable);
- EnableInterface(pw, EVENT_OBJECT_HTAKE, bEnable);
- EnableInterface(pw, EVENT_OBJECT_MTAKE, bEnable);
- EnableInterface(pw, EVENT_OBJECT_MBACK, bEnable);
- EnableInterface(pw, EVENT_OBJECT_MPOWER, bEnable);
- EnableInterface(pw, EVENT_OBJECT_MFRONT, bEnable);
- EnableInterface(pw, EVENT_OBJECT_GFLAT, bEnable);
- EnableInterface(pw, EVENT_OBJECT_FCREATE, bEnable);
- EnableInterface(pw, EVENT_OBJECT_FDELETE, bEnable);
- EnableInterface(pw, EVENT_OBJECT_SEARCH, bEnable);
- EnableInterface(pw, EVENT_OBJECT_TERRAFORM, bEnable);
- EnableInterface(pw, EVENT_OBJECT_RECOVER, bEnable);
- EnableInterface(pw, EVENT_OBJECT_FIRE, bEnable);
- EnableInterface(pw, EVENT_OBJECT_RESET, bEnable);
-#if _TEEN
- EnableInterface(pw, EVENT_OBJECT_PEN0, bEnable);
- EnableInterface(pw, EVENT_OBJECT_PEN1, bEnable);
- EnableInterface(pw, EVENT_OBJECT_PEN2, bEnable);
- EnableInterface(pw, EVENT_OBJECT_PEN3, bEnable);
- EnableInterface(pw, EVENT_OBJECT_PEN4, bEnable);
- EnableInterface(pw, EVENT_OBJECT_PEN5, bEnable);
- EnableInterface(pw, EVENT_OBJECT_PEN6, bEnable);
- EnableInterface(pw, EVENT_OBJECT_PEN7, bEnable);
- EnableInterface(pw, EVENT_OBJECT_PEN8, bEnable);
- EnableInterface(pw, EVENT_OBJECT_REC, bEnable);
- EnableInterface(pw, EVENT_OBJECT_STOP, bEnable);
-#endif
-
- if ( type == OBJECT_HUMAN ) // builder?
- {
- EnableInterface(pw, EVENT_OBJECT_BFACTORY, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BDERRICK, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BCONVERT, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BSTATION, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BREPAIR, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BTOWER, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BRESEARCH, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BRADAR, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BENERGY, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BLABO, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BNUCLEAR, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BPARA, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BINFO, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BXXXX, bEnable);
- }
-
- pb = (CButton*)pw->SearchControl(EVENT_OBJECT_GFLAT);
- if ( pb != 0 )
- {
- pb->SetState(STATE_VISIBLE, m_engine->RetGroundSpot());
- }
-
- if ( type == OBJECT_HUMAN || // builder?
- type == OBJECT_TECH )
- {
- CheckInterface(pw, EVENT_OBJECT_FCOLORb, m_flagColor==0);
- CheckInterface(pw, EVENT_OBJECT_FCOLORr, m_flagColor==1);
- CheckInterface(pw, EVENT_OBJECT_FCOLORg, m_flagColor==2);
- CheckInterface(pw, EVENT_OBJECT_FCOLORy, m_flagColor==3);
- CheckInterface(pw, EVENT_OBJECT_FCOLORv, m_flagColor==4);
- }
-
- if ( type == OBJECT_MOBILErs ) // shield?
- {
- if ( (m_secondaryTask == 0 || !m_secondaryTask->IsBusy()) && m_program == -1 )
- {
- EnableInterface(pw, EVENT_OBJECT_BEGSHIELD, (m_secondaryTask == 0));
- EnableInterface(pw, EVENT_OBJECT_ENDSHIELD, (m_secondaryTask != 0));
- DefaultEnter (pw, EVENT_OBJECT_BEGSHIELD, (m_secondaryTask == 0));
- DefaultEnter (pw, EVENT_OBJECT_ENDSHIELD, (m_secondaryTask != 0));
- }
- else
- {
- EnableInterface(pw, EVENT_OBJECT_BEGSHIELD, false);
- EnableInterface(pw, EVENT_OBJECT_ENDSHIELD, false);
- DefaultEnter (pw, EVENT_OBJECT_BEGSHIELD, false);
- DefaultEnter (pw, EVENT_OBJECT_ENDSHIELD, false);
- }
-
- ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_DIMSHIELD);
- if ( ps != 0 )
- {
- ps->SetVisibleValue((RADIUS_SHIELD_MIN/g_unit)+m_object->RetParam()*((RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)/g_unit));
- }
- }
-
- bFly = bEnable;
- if ( bFly && (type == OBJECT_HUMAN || type == OBJECT_TECH) )
- {
- if ( m_object->RetFret() != 0 ) bFly = false; // if holder -> not fly
- }
- EnableInterface(pw, EVENT_OBJECT_GASUP, bFly);
- EnableInterface(pw, EVENT_OBJECT_GASDOWN, bFly);
- if ( m_object->RetTrainer() ) // Training?
- {
- DeadInterface(pw, EVENT_OBJECT_GASUP, false);
- DeadInterface(pw, EVENT_OBJECT_GASDOWN, false);
- }
- else
- {
- DeadInterface(pw, EVENT_OBJECT_GASUP, g_researchDone&RESEARCH_FLY);
- DeadInterface(pw, EVENT_OBJECT_GASDOWN, g_researchDone&RESEARCH_FLY);
- }
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH ||
- type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr ||
- type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ) // vehicle?
- {
- bRun = false;
- if ( m_script[m_selScript] != 0 )
- {
- m_script[m_selScript]->GetTitle(title);
- if ( title[0] != 0 )
- {
- bRun = true;
- }
- }
- if ( !bEnable && m_program == -1 ) bRun = false;
- if ( m_bTraceRecord ) bRun = false;
- EnableInterface(pw, EVENT_OBJECT_PROGRUN, bRun);
-
- pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PROGRUN);
- if ( pb != 0 )
- {
- pb->SetIcon(m_program==-1?21:8); // run/stop
- }
-
-//? pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PROGEDIT);
-//? if ( pb != 0 )
-//? {
-//? pb->SetIcon(m_program==-1?22:40); // edit/debug
-//? }
-
- BlinkScript(m_program != -1); // blinks if script execution
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ) // arm?
- {
- CheckInterface(pw, EVENT_OBJECT_MPOWER, m_manipStyle==EVENT_OBJECT_MPOWER);
- CheckInterface(pw, EVENT_OBJECT_MBACK, m_manipStyle==EVENT_OBJECT_MBACK);
- CheckInterface(pw, EVENT_OBJECT_MFRONT, m_manipStyle==EVENT_OBJECT_MFRONT);
- }
-
-#if _TEEN
- if ( m_object->RetTraceDown() )
- {
- pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PEN0);
- if ( pb != 0 )
- {
- pb->ClearState(STATE_CHECK);
- }
-
- color = m_object->RetTraceColor();
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN1);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, color==1);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN2);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, color==8);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN3);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, color==7);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN4);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, color==4);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN5);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, color==6);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN6);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, color==14);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN7);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, color==12);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN8);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, color==10);
- }
- }
- else
- {
- pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PEN0);
- if ( pb != 0 )
- {
- pb->SetState(STATE_CHECK);
- }
-
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN1);
- if ( pc != 0 )
- {
- pc->ClearState(STATE_CHECK);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN2);
- if ( pc != 0 )
- {
- pc->ClearState(STATE_CHECK);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN3);
- if ( pc != 0 )
- {
- pc->ClearState(STATE_CHECK);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN4);
- if ( pc != 0 )
- {
- pc->ClearState(STATE_CHECK);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN5);
- if ( pc != 0 )
- {
- pc->ClearState(STATE_CHECK);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN6);
- if ( pc != 0 )
- {
- pc->ClearState(STATE_CHECK);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN7);
- if ( pc != 0 )
- {
- pc->ClearState(STATE_CHECK);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN8);
- if ( pc != 0 )
- {
- pc->ClearState(STATE_CHECK);
- }
- }
-#endif
-}
-
-// Updates the list of programs.
-
-void CBrain::UpdateScript(CWindow *pw)
-{
- CList* pl;
- char name[100];
- char title[100];
- int i;
- bool bSoluce;
-
- pl = (CList*)pw->SearchControl(EVENT_OBJECT_PROGLIST);
- if ( pl == 0 ) return;
-
-#if _SCHOOL
- bSoluce = m_main->RetSoluce4();
-#else
- bSoluce = true;
-#endif
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- sprintf(name, "%d", i+1);
-
- if ( m_script[i] != 0 )
- {
- m_script[i]->GetTitle(title);
- if ( !bSoluce && i == 3 )
- {
- title[0] = 0;
- }
- if ( title[0] != 0 )
- {
- sprintf(name, "%d: %s", i+1, title);
- }
- }
-
- pl->SetName(i, name);
- }
-
- if ( !bSoluce )
- {
- pl->SetEnable(3, false);
- }
-
- pl->SetSelect(m_selScript);
- pl->ShowSelect(true);
-}
-
-// Returns the rank of selected script.
-
-int CBrain::RetSelScript()
-{
- CWindow* pw;
- CList* pl;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return -1;
-
- pl = (CList*)pw->SearchControl(EVENT_OBJECT_PROGLIST);
- if ( pl == 0 ) return -1;
-
- return pl->RetSelect();
-}
-
-// Blinks the running program.
-
-void CBrain::BlinkScript(bool bEnable)
-{
- CWindow* pw;
- CList* pl;
-
- if ( !m_object->RetSelect() ) return; // robot not selected?
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pl = (CList*)pw->SearchControl(EVENT_OBJECT_PROGLIST);
- if ( pl == 0 ) return;
-
- pl->SetBlink(bEnable);
-}
-
-// Check the status of a button interface.
-
-void CBrain::CheckInterface(CWindow *pw, EventMsg event, bool bState)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_CHECK, bState);
-}
-
-// Changes the state of a button interface.
-
-void CBrain::EnableInterface(CWindow *pw, EventMsg event, bool bState)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_ENABLE, bState);
-}
-
-// Changes the state of a button on the interface.
-
-void CBrain::DeadInterface(CWindow *pw, EventMsg event, bool bState)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_DEAD, !bState);
-}
-
-// Change the default input state of a button interface.
-
-void CBrain::DefaultEnter(CWindow *pw, EventMsg event, bool bState)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- if ( bState )
- {
- control->SetState(STATE_DEFAULT);
- m_defaultEnter = event;
- }
- else
- {
- control->ClearState(STATE_DEFAULT);
- }
-}
-
-
-// Indicates whether the object is busy with a task.
-
-bool CBrain::IsBusy()
-{
- return (m_primaryTask != 0);
-}
-
-// Management of the activity of an object.
-
-void CBrain::SetActivity(bool bMode)
-{
- m_bActivity = bMode;
-}
-
-bool CBrain::RetActivity()
-{
- return m_bActivity;
-}
-
-// Indicates whether a program is running.
-
-bool CBrain::IsProgram()
-{
- return ( m_program != -1 );
-}
-
-// Indicates whether a program exists.
-
-bool CBrain::ProgramExist(int rank)
-{
- return ( m_script[rank] != 0 );
-}
-
-// Starts a program.
-
-void CBrain::RunProgram(int rank)
-{
- if ( rank < 0 ) return;
-
- if ( m_script[rank] != 0 &&
- m_script[rank]->Run() )
- {
- m_program = rank; // start new program
- BlinkScript(true); // blink
- m_object->CreateSelectParticule();
- m_main->UpdateShortcuts();
- }
-}
-
-// Returns the first free program.
-
-int CBrain::FreeProgram()
-{
- int i;
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- if ( m_script[i] == 0 ) return i;
- }
- return -1;
-}
-
-
-// Returns the current program.
-
-int CBrain::RetProgram()
-{
- return m_program;
-}
-
-
-// Name management scripts to load.
-
-void CBrain::SetScriptRun(int rank)
-{
- m_scriptRun = rank;
-}
-
-int CBrain::RetScriptRun()
-{
- return m_scriptRun;
-}
-
-void CBrain::SetScriptName(int rank, char *name)
-{
- strcpy(m_scriptName[rank], name);
-}
-
-char* CBrain::RetScriptName(int rank)
-{
- return m_scriptName[rank];
-}
-
-void CBrain::SetSoluceName(char *name)
-{
- strcpy(m_soluceName, name);
-}
-
-char* CBrain::RetSoluceName()
-{
- return m_soluceName;
-}
-
-
-// Load a script solution, in the first free script.
-// If there is already an identical script, nothing is loaded.
-
-bool CBrain::ReadSoluce(char* filename)
-{
- int rank, i;
-
- rank = FreeProgram();
- if ( rank == -1 ) return false;
-
- if ( !ReadProgram(rank, filename) ) return false; // load solution
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- if ( i == rank || m_script[i] == 0 ) continue;
-
- if ( m_script[i]->Compare(m_script[rank]) ) // the same already?
- {
- delete m_script[rank];
- m_script[rank] = 0;
- return false;
- }
- }
-
- return true;
-}
-
-// Load a script with a text file.
-
-bool CBrain::ReadProgram(int rank, char* filename)
-{
- if ( m_script[rank] == 0 )
- {
- m_script[rank] = new CScript(m_iMan, m_object, &m_secondaryTask);
- }
-
- if ( m_script[rank]->ReadScript(filename) ) return true;
-
- delete m_script[rank];
- m_script[rank] = 0;
-
- return false;
-}
-
-// Indicates whether a program is compiled correctly.
-
-bool CBrain::RetCompile(int rank)
-{
- if ( m_script[rank] == 0 ) return false;
- return m_script[rank]->RetCompile();
-}
-
-// Saves a script in a text file.
-
-bool CBrain::WriteProgram(int rank, char* filename)
-{
- if ( m_script[rank] == 0 )
- {
- m_script[rank] = new CScript(m_iMan, m_object, &m_secondaryTask);
- }
-
- if ( m_script[rank]->WriteScript(filename) ) return true;
-
- delete m_script[rank];
- m_script[rank] = 0;
-
- return false;
-}
-
-
-// Load a stack of script implementation from a file.
-
-bool CBrain::ReadStack(FILE *file)
-{
- short op;
-
- fRead(&op, sizeof(short), 1, file);
- if ( op == 1 ) // run ?
- {
- fRead(&op, sizeof(short), 1, file); // program rank
- if ( op >= 0 && op < BRAINMAXSCRIPT )
- {
- m_program = op; // program restarts
- m_selScript = op;
- BlinkScript(true); // blink
-
- if ( m_script[op] == 0 )
- {
- m_script[op] = new CScript(m_iMan, m_object, &m_secondaryTask);
- }
- if ( !m_script[op]->ReadStack(file) ) return false;
- }
- }
-
- return true;
-}
-
-// ave the script implementation stack of a file.
-
-bool CBrain::WriteStack(FILE *file)
-{
- short op;
-
- if ( m_program != -1 && // current program?
- m_script[m_program]->IsRunning() )
- {
- op = 1; // run
- fWrite(&op, sizeof(short), 1, file);
-
- op = m_program;
- fWrite(&op, sizeof(short), 1, file);
-
- return m_script[m_program]->WriteStack(file);
- }
-
- op = 0; // stop
- fWrite(&op, sizeof(short), 1, file);
- return true;
-}
-
-
-
-// Start of registration of the design.
-
-void CBrain::TraceRecordStart()
-{
- m_traceOper = TO_STOP;
-
- m_tracePos = m_object->RetPosition(0);
- m_traceAngle = m_object->RetAngleY(0);
-
- if ( m_object->RetTraceDown() ) // pencil down?
- {
- m_traceColor = m_object->RetTraceColor();
- }
- else // pen up?
- {
- m_traceColor = -1;
- }
-
- delete m_traceRecordBuffer;
- m_traceRecordBuffer = (TraceRecord*)malloc(sizeof(TraceRecord)*MAXTRACERECORD);
- m_traceRecordIndex = 0;
-}
-
-// Saving the current drawing.
-
-void CBrain::TraceRecordFrame()
-{
- TraceOper oper = TO_STOP;
- Math::Vector pos;
- float angle, len, speed;
- int color;
-
- speed = m_physics->RetLinMotionX(MO_REASPEED);
- if ( speed > 0.0f ) oper = TO_ADVANCE;
- if ( speed < 0.0f ) oper = TO_RECEDE;
-
- speed = m_physics->RetCirMotionY(MO_REASPEED);
- if ( speed != 0.0f ) oper = TO_TURN;
-
- if ( m_object->RetTraceDown() ) // pencil down?
- {
- color = m_object->RetTraceColor();
- }
- else // pen up?
- {
- color = -1;
- }
-
- if ( oper != m_traceOper ||
- color != m_traceColor )
- {
- if ( m_traceOper == TO_ADVANCE ||
- m_traceOper == TO_RECEDE )
- {
- pos = m_object->RetPosition(0);
- len = Math::DistanceProjected(pos, m_tracePos);
- TraceRecordOper(m_traceOper, len);
- }
- if ( m_traceOper == TO_TURN )
- {
- angle = m_object->RetAngleY(0)-m_traceAngle;
- TraceRecordOper(m_traceOper, angle);
- }
-
- if ( color != m_traceColor )
- {
- TraceRecordOper(TO_PEN, (float)color);
- }
-
- m_traceOper = oper;
- m_tracePos = m_object->RetPosition(0);
- m_traceAngle = m_object->RetAngleY(0);
- m_traceColor = color;
- }
-}
-
-// End of the registration of the design. Program generates the CBOT.
-
-void CBrain::TraceRecordStop()
-{
- TraceOper lastOper, curOper;
- float lastParam, curParam;
- int max, i;
- char* buffer;
-
- if ( m_traceRecordBuffer == 0 ) return;
-
- max = 10000;
- buffer = (char*)malloc(max);
- *buffer = 0;
- strncat(buffer, "extern void object::AutoDraw()\n{\n", max-1);
-
- lastOper = TO_STOP;
- lastParam = 0.0f;
- for ( i=0 ; i<m_traceRecordIndex ; i++ )
- {
- curOper = m_traceRecordBuffer[i].oper;
- curParam = m_traceRecordBuffer[i].param;
-
- if ( curOper == lastOper )
- {
- if ( curOper == TO_PEN )
- {
- lastParam = curParam;
- }
- else
- {
- lastParam += curParam;
- }
- }
- else
- {
- TraceRecordPut(buffer, max, lastOper, lastParam);
- lastOper = curOper;
- lastParam = curParam;
- }
- }
- TraceRecordPut(buffer, max, lastOper, lastParam);
-
- delete m_traceRecordBuffer;
- m_traceRecordBuffer = 0;
-
- strncat(buffer, "}\n", max-1);
- buffer[max-1] = 0;
-
- i = m_selScript;
- if ( m_script[i] == 0 )
- {
- m_script[i] = new CScript(m_iMan, m_object, &m_secondaryTask);
- }
- m_script[i]->SendScript(buffer);
- delete buffer;
-}
-
-// Saves an instruction CBOT.
-
-bool CBrain::TraceRecordOper(TraceOper oper, float param)
-{
- int i;
-
- i = m_traceRecordIndex;
- if ( i >= MAXTRACERECORD ) return false;
-
- m_traceRecordBuffer[i].oper = oper;
- m_traceRecordBuffer[i].param = param;
-
- m_traceRecordIndex = i+1;
- return true;
-}
-
-// Generates an instruction CBOT.
-
-bool CBrain::TraceRecordPut(char *buffer, int max, TraceOper oper, float param)
-{
- char line[100];
- int color;
-
- if ( oper == TO_ADVANCE )
- {
- param /= g_unit;
- sprintf(line, "\tmove(%.1f);\n", param);
- strncat(buffer, line, max-1);
- }
-
- if ( oper == TO_RECEDE )
- {
- param /= g_unit;
- sprintf(line, "\tmove(-%.1f);\n", param);
- strncat(buffer, line, max-1);
- }
-
- if ( oper == TO_TURN )
- {
- param = -param*180.0f/Math::PI;
- sprintf(line, "\tturn(%d);\n", (int)param);
-//? sprintf(line, "\tturn(%.1f);\n", param);
- strncat(buffer, line, max-1);
- }
-
- if ( oper == TO_PEN )
- {
- color = (int)param;
- if ( color == -1 ) strncat(buffer, "\tpenup();\n", max-1);
- if ( color == 1 ) strncat(buffer, "\tpendown(Black);\n", max-1);
- if ( color == 8 ) strncat(buffer, "\tpendown(Yellow);\n", max-1);
- if ( color == 7 ) strncat(buffer, "\tpendown(Orange);\n", max-1);
- if ( color == 4 ) strncat(buffer, "\tpendown(Red);\n", max-1);
- if ( color == 6 ) strncat(buffer, "\tpendown(Purple);\n", max-1);
- if ( color == 14 ) strncat(buffer, "\tpendown(Blue);\n", max-1);
- if ( color == 12 ) strncat(buffer, "\tpendown(Green);\n", max-1);
- if ( color == 10 ) strncat(buffer, "\tpendown(Brown);\n", max-1);
- }
-
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/brain.h"
+
+#include "CBot/CBotDll.h"
+#include "common/struct.h"
+#include "math/geometry.h"
+#include "math/const.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/language.h"
+#include "common/global.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "old/math3d.h"
+#include "object/robotmain.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "old/camera.h"
+#include "object/object.h"
+#include "physics/physics.h"
+#include "object/motion/motion.h"
+#include "object/motion/motionspider.h"
+#include "old/pyro.h"
+#include "object/task/taskmanager.h"
+#include "object/task/task.h"
+#include "object/task/taskmanip.h"
+#include "object/task/taskflag.h"
+#include "object/task/taskshield.h"
+#include "script/script.h"
+#include "ui/studio.h"
+#include "ui/interface.h"
+#include "ui/button.h"
+#include "ui/color.h"
+#include "ui/edit.h"
+#include "ui/list.h"
+#include "ui/label.h"
+#include "ui/group.h"
+#include "ui/gauge.h"
+#include "ui/slider.h"
+#include "ui/compass.h"
+#include "ui/target.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+#include "old/text.h"
+#include "old/sound.h"
+#include "old/particule.h"
+#include "script/cmdtoken.h"
+
+
+
+const int MAXTRACERECORD = 1000;
+
+
+
+// Object's constructor.
+
+CBrain::CBrain(CInstanceManager* iMan, CObject* object)
+{
+ int i;
+
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_BRAIN, this, 100);
+
+ m_object = object;
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+ m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_physics = 0;
+ m_motion = 0;
+ m_primaryTask = 0;
+ m_secondaryTask = 0;
+ m_studio = 0;
+
+ m_program = -1;
+ m_bActivity = true;
+ m_bBurn = false;
+ m_bActiveVirus = false;
+ m_time = 0.0f;
+ m_burnTime = 0.0f;
+ m_lastUpdateTime = 0.0f;
+ m_lastHumanTime = 0.0f;
+ m_lastWormTime = 0.0f;
+ m_antTarget = 0;
+ m_beeBullet = 0;
+ m_lastAlarmTime = 0.0f;
+ m_soundChannelAlarm = -1;
+ m_flagColor = 0;
+
+ m_buttonAxe = EVENT_NULL;
+ m_defaultEnter = EVENT_NULL;
+ m_manipStyle = EVENT_OBJECT_MFRONT;
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ m_script[i] = 0;
+ m_scriptName[i][0] = 0;
+ }
+ m_scriptRun = -1;
+ m_soluceName[0] = 0;
+ m_selScript = 0;
+
+ m_bTraceRecord = false;
+ m_traceRecordBuffer = 0;
+}
+
+// Object's destructor.
+
+CBrain::~CBrain()
+{
+ int i;
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ delete m_script[i];
+ }
+
+ delete m_primaryTask;
+ delete m_secondaryTask;
+ delete m_studio;
+ delete m_traceRecordBuffer;
+ m_iMan->DeleteInstance(CLASS_BRAIN, this);
+}
+
+
+// Destroys the object.
+
+void CBrain::DeleteObject(bool bAll)
+{
+ if ( m_soundChannelAlarm != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannelAlarm);
+ m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 0.5f, 0.5f, SOPER_STOP);
+ m_soundChannelAlarm = -1;
+ }
+
+ if ( !bAll )
+ {
+ if ( m_beeBullet != 0 )
+ {
+ m_beeBullet->DeleteObject();
+ delete m_beeBullet;
+ m_beeBullet = 0;
+ }
+ }
+
+ if ( m_studio != 0 ) // current edition?
+ {
+ StopEditScript(true);
+ }
+}
+
+
+void CBrain::SetPhysics(CPhysics* physics)
+{
+ m_physics = physics;
+}
+
+void CBrain::SetMotion(CMotion* motion)
+{
+ m_motion = motion;
+}
+
+
+// Saves all parameters of the object.
+
+bool CBrain::Write(char *line)
+{
+ char name[100];
+
+ sprintf(name, " bVirusActive=%d", m_bActiveVirus);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the object.
+
+bool CBrain::Read(char *line)
+{
+ m_bActiveVirus = OpInt(line, "bVirusActive", 0);
+
+ return true;
+}
+
+
+// Management of an event.
+
+bool CBrain::EventProcess(const Event &event)
+{
+ CWindow* pw;
+ CControl* pc;
+ CSlider* ps;
+ EventMsg action;
+ ObjectType type;
+ Error err;
+ float axeX, axeY, axeZ, factor;
+
+ type = m_object->RetType();
+
+ if ( m_primaryTask != 0 ) // current task?
+ {
+ m_primaryTask->EventProcess(event);
+ }
+
+ if ( m_secondaryTask != 0 ) // current task?
+ {
+ m_secondaryTask->EventProcess(event);
+ }
+
+ action = EVENT_NULL;
+
+ if ( event.event == EVENT_KEYDOWN &&
+ (event.param == m_engine->RetKey(KEYRANK_ACTION, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_ACTION, 1) ) &&
+ !m_main->RetEditLock() )
+ {
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw != 0 )
+ {
+ pc = pw->SearchControl(m_defaultEnter);
+ if ( pc != 0 )
+ {
+ if ( pc->TestState(STATE_ENABLE) )
+ {
+ action = m_defaultEnter;
+ }
+ }
+ }
+ }
+ else
+ {
+ action = event.event;
+ }
+
+ if ( action == EVENT_NULL ) return true;
+
+ if ( action == EVENT_UPDINTERFACE )
+ {
+ if ( m_object->RetSelect() ) CreateInterface(true);
+ }
+
+ if ( action == EVENT_FRAME )
+ {
+ EventFrame(event);
+ }
+
+ if ( m_object->RetSelect() && // robot selected?
+ m_studio != 0 ) // current issue?
+ {
+ m_studio->EventProcess(event);
+
+ if ( action == EVENT_OBJECT_PROGRUN )
+ {
+ if ( m_program == -1 )
+ {
+ RunProgram(m_selScript);
+ }
+ else
+ {
+ StopProgram();
+ }
+ }
+ if ( action == EVENT_OBJECT_PROGSTART )
+ {
+ m_main->SaveOneScript(m_object);
+ RunProgram(m_selScript);
+ }
+ if ( action == EVENT_OBJECT_PROGSTOP )
+ {
+ StopProgram();
+ }
+ if ( action == EVENT_STUDIO_OK )
+ {
+ StopEditScript(false);
+ m_main->SaveOneScript(m_object);
+ }
+ if ( action == EVENT_STUDIO_CANCEL )
+ {
+ StopEditScript(true);
+ m_main->SaveOneScript(m_object);
+ }
+ return true;
+ }
+
+ if ( !m_object->RetSelect() && // robot pas sélectionné ?
+ m_program == -1 &&
+ m_primaryTask == 0 )
+ {
+ axeX = 0.0f;
+ axeY = 0.0f;
+ axeZ = 0.0f;
+ if ( m_object->RetBurn() ) // Gifted?
+ {
+ if ( !m_bBurn ) // beginning?
+ {
+ m_bBurn = true;
+ m_burnTime = 0.0f;
+ }
+
+ axeZ = -1.0f; // tomb
+
+ if ( !m_object->RetFixed() &&
+ (type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_WORM ) )
+ {
+ axeY = 2.0f; // zigzag disorganized fast
+ if ( type == OBJECT_WORM ) axeY = 5.0f;
+ axeX = 0.5f+sinf(m_time* 1.0f)*0.5f+
+ sinf(m_time* 6.0f)*2.0f+
+ sinf(m_time*21.0f)*0.2f;
+ factor = 1.0f-m_burnTime/15.0f; // slow motion
+ if ( factor < 0.0f ) factor = 0.0f;
+ axeY *= factor;
+ axeX *= factor;
+ }
+ }
+ m_physics->SetMotorSpeedX(axeY); // move forward/move back
+ m_physics->SetMotorSpeedY(axeZ); // up / down
+ m_physics->SetMotorSpeedZ(axeX); // rotate
+ return true;
+ }
+
+ if ( m_program != -1 &&
+ m_object->RetRuin() )
+ {
+ StopProgram();
+ return true;
+ }
+
+ if ( !m_object->RetSelect() ) // robot not selected?
+ {
+ return true;
+ }
+
+ if ( m_secondaryTask != 0 ) // current task?
+ {
+ if ( action == EVENT_OBJECT_ENDSHIELD )
+ {
+ m_secondaryTask->StartTaskShield(TSM_DOWN, 0.0f);
+ }
+ }
+ if ( m_primaryTask != 0 || // current task?
+ m_program != -1 )
+ {
+ if ( action == EVENT_OBJECT_PROGRUN )
+ {
+ StopProgram();
+ }
+ if ( action == EVENT_OBJECT_PROGEDIT )
+ {
+ StartEditScript(m_selScript, m_main->RetScriptName());
+ }
+ if ( m_primaryTask == 0 || !m_primaryTask->IsPilot() ) return true;
+ }
+
+ if ( action == EVENT_OBJECT_LEFT ||
+ action == EVENT_OBJECT_RIGHT ||
+ action == EVENT_OBJECT_UP ||
+ action == EVENT_OBJECT_DOWN ||
+ action == EVENT_OBJECT_GASUP ||
+ action == EVENT_OBJECT_GASDOWN )
+ {
+ m_buttonAxe = action;
+ }
+ if ( action == EVENT_LBUTTONUP ||
+ action == EVENT_RBUTTONUP )
+ {
+ m_buttonAxe = EVENT_NULL;
+ }
+
+ axeX = event.axeX;
+ axeY = event.axeY;
+ axeZ = event.axeZ;
+
+ if ( !m_main->RetTrainerPilot() &&
+ m_object->RetTrainer() ) // drive vehicle?
+ {
+ axeX = 0.0f;
+ axeY = 0.0f;
+ axeZ = 0.0f; // Remote control impossible!
+ }
+
+ if ( m_buttonAxe == EVENT_OBJECT_LEFT ) axeX = -1.0f;
+ if ( m_buttonAxe == EVENT_OBJECT_RIGHT ) axeX = 1.0f;
+ if ( m_buttonAxe == EVENT_OBJECT_UP ) axeY = 1.0f;
+ if ( m_buttonAxe == EVENT_OBJECT_DOWN ) axeY = -1.0f;
+ if ( m_buttonAxe == EVENT_OBJECT_GASUP ) axeZ = 1.0f;
+ if ( m_buttonAxe == EVENT_OBJECT_GASDOWN ) axeZ = -1.0f;
+
+ if ( m_object->RetManual() ) // scribbler in manual mode?
+ {
+ if ( axeX != 0.0f ) axeY = 0.0f; // if running -> not moving!
+ axeX *= 0.5f;
+ axeY *= 0.5f;
+ }
+
+ if ( (g_researchDone&RESEARCH_FLY) == 0 )
+ {
+ axeZ = -1.0f; // tomb
+ }
+
+ axeX += m_camera->RetMotorTurn(); // additional power according to camera
+ if ( axeX > 1.0f ) axeX = 1.0f;
+ if ( axeX < -1.0f ) axeX = -1.0f;
+
+ m_physics->SetMotorSpeedX(axeY); // move forward/move back
+ m_physics->SetMotorSpeedY(axeZ); // up/down
+ m_physics->SetMotorSpeedZ(axeX); // rotate
+
+ if ( action == EVENT_OBJECT_PROGLIST )
+ {
+ m_selScript = RetSelScript();
+ UpdateInterface();
+ }
+
+ if ( action == EVENT_OBJECT_PROGEDIT )
+ {
+ StartEditScript(m_selScript, m_main->RetScriptName());
+ }
+
+ if ( action == EVENT_OBJECT_PROGRUN )
+ {
+ StopProgram(); // stops the current program
+ RunProgram(m_selScript);
+ UpdateInterface();
+ }
+
+ err = ERR_OK;
+
+ if ( m_program == -1 )
+ {
+ if ( action == EVENT_OBJECT_HTAKE )
+ {
+ err = StartTaskTake();
+ }
+
+ if ( action == EVENT_OBJECT_MFRONT ||
+ action == EVENT_OBJECT_MBACK ||
+ action == EVENT_OBJECT_MPOWER )
+ {
+ m_manipStyle = action;
+ UpdateInterface();
+ }
+
+ if ( action == EVENT_OBJECT_MTAKE )
+ {
+ if ( m_manipStyle == EVENT_OBJECT_MFRONT )
+ {
+ err = StartTaskManip(TMO_AUTO, TMA_FFRONT);
+ }
+ if ( m_manipStyle == EVENT_OBJECT_MBACK )
+ {
+ err = StartTaskManip(TMO_AUTO, TMA_FBACK);
+ if ( err == ERR_OK )
+ {
+ m_manipStyle = EVENT_OBJECT_MFRONT;
+ UpdateInterface();
+ }
+ }
+ if ( m_manipStyle == EVENT_OBJECT_MPOWER )
+ {
+ err = StartTaskManip(TMO_AUTO, TMA_POWER);
+ if ( err == ERR_OK )
+ {
+ m_manipStyle = EVENT_OBJECT_MFRONT;
+ UpdateInterface();
+ }
+ }
+ }
+
+ if ( action == EVENT_OBJECT_BDERRICK )
+ {
+ err = StartTaskBuild(OBJECT_DERRICK);
+ }
+ if ( action == EVENT_OBJECT_BSTATION )
+ {
+ err = StartTaskBuild(OBJECT_STATION);
+ }
+ if ( action == EVENT_OBJECT_BFACTORY )
+ {
+ err = StartTaskBuild(OBJECT_FACTORY);
+ }
+ if ( action == EVENT_OBJECT_BREPAIR )
+ {
+ err = StartTaskBuild(OBJECT_REPAIR);
+ }
+ if ( action == EVENT_OBJECT_BCONVERT )
+ {
+ err = StartTaskBuild(OBJECT_CONVERT);
+ }
+ if ( action == EVENT_OBJECT_BTOWER )
+ {
+ err = StartTaskBuild(OBJECT_TOWER);
+ }
+ if ( action == EVENT_OBJECT_BRESEARCH )
+ {
+ err = StartTaskBuild(OBJECT_RESEARCH);
+ }
+ if ( action == EVENT_OBJECT_BRADAR )
+ {
+ err = StartTaskBuild(OBJECT_RADAR);
+ }
+ if ( action == EVENT_OBJECT_BENERGY )
+ {
+ err = StartTaskBuild(OBJECT_ENERGY);
+ }
+ if ( action == EVENT_OBJECT_BLABO )
+ {
+ err = StartTaskBuild(OBJECT_LABO);
+ }
+ if ( action == EVENT_OBJECT_BNUCLEAR )
+ {
+ err = StartTaskBuild(OBJECT_NUCLEAR);
+ }
+ if ( action == EVENT_OBJECT_BPARA )
+ {
+ err = StartTaskBuild(OBJECT_PARA);
+ }
+ if ( action == EVENT_OBJECT_BINFO )
+ {
+ err = StartTaskBuild(OBJECT_INFO);
+ }
+
+ if ( action == EVENT_OBJECT_GFLAT )
+ {
+ GroundFlat();
+ }
+ if ( action == EVENT_OBJECT_FCREATE )
+ {
+ err = StartTaskFlag(TFL_CREATE, m_flagColor);
+ }
+ if ( action == EVENT_OBJECT_FDELETE )
+ {
+ err = StartTaskFlag(TFL_DELETE, m_flagColor);
+ }
+ if ( action == EVENT_OBJECT_FCOLORb ||
+ action == EVENT_OBJECT_FCOLORr ||
+ action == EVENT_OBJECT_FCOLORg ||
+ action == EVENT_OBJECT_FCOLORy ||
+ action == EVENT_OBJECT_FCOLORv )
+ {
+ ColorFlag(action-EVENT_OBJECT_FCOLORb);
+ }
+
+ if ( action == EVENT_OBJECT_SEARCH )
+ {
+ err = StartTaskSearch();
+ }
+
+ if ( action == EVENT_OBJECT_TERRAFORM )
+ {
+ err = StartTaskTerraform();
+ }
+
+ if ( action == EVENT_OBJECT_RECOVER )
+ {
+ err = StartTaskRecover();
+ }
+
+ if ( action == EVENT_OBJECT_BEGSHIELD )
+ {
+ err = StartTaskShield(TSM_UP);
+ }
+
+ if ( action == EVENT_OBJECT_DIMSHIELD )
+ {
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw != 0 )
+ {
+ ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_DIMSHIELD);
+ if ( ps != 0 )
+ {
+ m_object->SetParam((ps->RetVisibleValue()-(RADIUS_SHIELD_MIN/g_unit))/((RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)/g_unit));
+ }
+ }
+ }
+
+ if ( action == EVENT_OBJECT_FIRE && m_primaryTask == 0 && !m_object->RetTrainer())
+ {
+ if ( m_camera->RetType() != CAMERA_ONBOARD )
+ {
+ m_camera->SetType(CAMERA_ONBOARD);
+ }
+ err = StartTaskFire(0.0f);
+ }
+ if ( action == EVENT_OBJECT_TARGET && !m_object->RetTrainer() )
+ {
+ err = StartTaskGunGoal((event.pos.y-0.50f)*1.3f, (event.pos.x-0.50f)*2.0f);
+ }
+
+ if ( action == EVENT_OBJECT_FIREANT )
+ {
+//? err = StartTaskFireAnt();
+ }
+
+ if ( action == EVENT_OBJECT_PEN0 ) // up
+ {
+ err = StartTaskPen(false, m_object->RetTraceColor());
+ m_object->SetTraceDown(false);
+ }
+ if ( action == EVENT_OBJECT_PEN1 ) // black
+ {
+ err = StartTaskPen(true, 1);
+ m_object->SetTraceDown(true);
+ m_object->SetTraceColor(1);
+ }
+ if ( action == EVENT_OBJECT_PEN2 ) // yellow
+ {
+ err = StartTaskPen(true, 8);
+ m_object->SetTraceDown(true);
+ m_object->SetTraceColor(8);
+ }
+ if ( action == EVENT_OBJECT_PEN3 ) // orange
+ {
+ err = StartTaskPen(true, 7);
+ m_object->SetTraceDown(true);
+ m_object->SetTraceColor(7);
+ }
+ if ( action == EVENT_OBJECT_PEN4 ) // red
+ {
+ err = StartTaskPen(true, 4);
+ m_object->SetTraceDown(true);
+ m_object->SetTraceColor(4);
+ }
+ if ( action == EVENT_OBJECT_PEN5 ) // violet
+ {
+ err = StartTaskPen(true, 6);
+ m_object->SetTraceDown(true);
+ m_object->SetTraceColor(6);
+ }
+ if ( action == EVENT_OBJECT_PEN6 ) // blue
+ {
+ err = StartTaskPen(true, 14);
+ m_object->SetTraceDown(true);
+ m_object->SetTraceColor(14);
+ }
+ if ( action == EVENT_OBJECT_PEN7 ) // green
+ {
+ err = StartTaskPen(true, 12);
+ m_object->SetTraceDown(true);
+ m_object->SetTraceColor(12);
+ }
+ if ( action == EVENT_OBJECT_PEN8 ) // brown
+ {
+ err = StartTaskPen(true, 10);
+ m_object->SetTraceDown(true);
+ m_object->SetTraceColor(10);
+ }
+
+ if ( action == EVENT_OBJECT_REC ) // registered?
+ {
+ if ( m_bTraceRecord )
+ {
+ m_bTraceRecord = false;
+ TraceRecordStop();
+ }
+ else
+ {
+ m_bTraceRecord = true;
+ TraceRecordStart();
+ }
+ UpdateInterface();
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw != 0 )
+ {
+ UpdateScript(pw);
+ }
+ }
+ if ( action == EVENT_OBJECT_STOP ) // stops?
+ {
+ if ( m_bTraceRecord )
+ {
+ m_bTraceRecord = false;
+ TraceRecordStop();
+ }
+ UpdateInterface();
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw != 0 )
+ {
+ UpdateScript(pw);
+ }
+ }
+
+ if ( action == EVENT_OBJECT_RESET )
+ {
+ m_main->ResetObject(); // reset all objects
+ UpdateInterface();
+ }
+
+#if 0
+ if ( event.param == 'T' )
+ {
+ Math::Vector p1, p2;
+ float h;
+ p1 = m_object->RetPosition(0);
+ h = m_terrain->RetFloorLevel(p1);
+ p2 = p1;
+ p1.x -= 20.0f;
+ p1.z -= 20.0f;
+ p2.x += 20.0f;
+ p2.z += 20.0f;
+ m_terrain->Terraform(p1, p2, h+1.0f);
+ }
+ if ( event.param == 'R' )
+ {
+ Math::Vector p1, p2;
+ float h;
+ p1 = m_object->RetPosition(0);
+ h = m_terrain->RetFloorLevel(p1);
+ p2 = p1;
+ p1.x -= 20.0f;
+ p1.z -= 20.0f;
+ p2.x += 20.0f;
+ p2.z += 20.0f;
+ m_terrain->Terraform(p1, p2, h-1.0f);
+ }
+#endif
+ }
+
+ if ( err != ERR_OK )
+ {
+ m_displayText->DisplayError(err, m_object);
+ }
+
+ return true;
+}
+
+
+// The brain is changing by time.
+
+bool CBrain::EventFrame(const Event &event)
+{
+ m_time += event.rTime;
+ if ( m_bBurn ) m_burnTime += event.rTime;
+
+ if ( m_soundChannelAlarm != -1 )
+ {
+ m_sound->Position(m_soundChannelAlarm, m_object->RetPosition(0));
+ }
+
+ if ( m_studio != 0 ) // �urrent edition?
+ {
+ m_studio->EventProcess(event);
+ }
+
+ UpdateInterface(event.rTime);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( !m_bActivity ) return true; // expected if idle
+ if ( EndedTask() == ERR_CONTINUE ) return true; // expected if not finished ...
+
+ if ( m_program != -1 ) // current program?
+ {
+ if ( m_script[m_program]->Continue(event) )
+ {
+ StopProgram();
+ }
+ }
+
+ if ( m_bTraceRecord ) // registration of the design in progress?
+ {
+ TraceRecordFrame();
+ }
+
+ return true;
+}
+
+
+// Stops the running program.
+
+void CBrain::StopProgram()
+{
+ StopTask();
+
+ if ( m_object->RetType() == OBJECT_HUMAN ||
+ m_object->RetType() == OBJECT_TECH ) return;
+
+ if ( m_program != -1 &&
+ m_script[m_program] != 0 )
+ {
+ m_script[m_program]->Stop();
+ }
+
+ BlinkScript(false); // stops flashing
+
+ m_program = -1;
+
+ m_physics->SetMotorSpeedX(0.0f);
+ m_physics->SetMotorSpeedY(0.0f);
+ m_physics->SetMotorSpeedZ(0.0f);
+
+ m_motion->SetAction(-1);
+
+ UpdateInterface();
+ m_main->UpdateShortcuts();
+ m_object->CreateSelectParticule();
+}
+
+// Stops the current task.
+
+void CBrain::StopTask()
+{
+ if ( m_primaryTask != 0 )
+ {
+ m_primaryTask->Abort();
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+}
+
+
+// Introduces a virus into a program.
+// Returns true if it was inserted.
+
+bool CBrain::IntroduceVirus()
+{
+ int i, j;
+
+ for ( i=0 ; i<50 ; i++ )
+ {
+ j = rand()%BRAINMAXSCRIPT;
+ if ( m_script[j] != 0 )
+ {
+ if ( m_script[j]->IntroduceVirus() ) // tries to introduce
+ {
+ m_bActiveVirus = true; // active virus
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// Active Virus indicates that the object is contaminated. Unlike ch'tites (??? - Programerus)
+// letters which automatically disappear after a while,
+// ActiveVirus does not disappear after you edit the program
+// (Even if the virus is not fixed).
+
+
+void CBrain::SetActiveVirus(bool bActive)
+{
+ m_bActiveVirus = bActive;
+
+ if ( !m_bActiveVirus ) // virus disabled?
+ {
+ m_object->SetVirusMode(false); // chtites (??? - Programerus) letters also
+ }
+}
+
+bool CBrain::RetActiveVirus()
+{
+ return m_bActiveVirus;
+}
+
+
+// Start editing a program.
+
+void CBrain::StartEditScript(int rank, char* name)
+{
+ CreateInterface(false); // removes the control buttons
+
+ if ( m_script[rank] == 0 )
+ {
+ m_script[rank] = new CScript(m_iMan, m_object, &m_secondaryTask);
+ }
+
+ m_studio = new CStudio(m_iMan);
+ m_studio->StartEditScript(m_script[rank], name, rank);
+}
+
+// End of editing a program.
+
+void CBrain::StopEditScript(bool bCancel)
+{
+ if ( !bCancel ) SetActiveVirus(false);
+
+ if ( !m_studio->StopEditScript(bCancel) ) return;
+
+ delete m_studio;
+ m_studio = 0;
+
+ CreateInterface(true); // puts the control buttons
+}
+
+
+
+// Move the manipulator arm.
+
+Error CBrain::StartTaskTake()
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskTake();
+ UpdateInterface();
+ return err;
+}
+
+// Move the manipulator arm.
+
+Error CBrain::StartTaskManip(TaskManipOrder order, TaskManipArm arm)
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskManip(order, arm);
+ UpdateInterface();
+ return err;
+}
+
+// Puts or removes a flag.
+
+Error CBrain::StartTaskFlag(TaskFlagOrder order, int rank)
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskFlag(order, rank);
+ UpdateInterface();
+ return err;
+}
+
+// Built a building.
+
+Error CBrain::StartTaskBuild(ObjectType type)
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskBuild(type);
+ UpdateInterface();
+ return err;
+}
+
+// Probe the ground.
+
+Error CBrain::StartTaskSearch()
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskSearch();
+ UpdateInterface();
+ return err;
+}
+
+// Terraformed the ground.
+
+Error CBrain::StartTaskTerraform()
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskTerraform();
+ UpdateInterface();
+ return err;
+}
+
+// Change pencil.
+
+Error CBrain::StartTaskPen(bool bDown, int color)
+{
+ Error err;
+
+ m_physics->SetMotorSpeedX(0.0f);
+ m_physics->SetMotorSpeedY(0.0f);
+ m_physics->SetMotorSpeedZ(0.0f);
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskPen(bDown, color);
+ UpdateInterface();
+ return err;
+}
+
+// Recovers a ruin.
+
+Error CBrain::StartTaskRecover()
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskRecover();
+ UpdateInterface();
+ return err;
+}
+
+// Deploys the shield.
+
+Error CBrain::StartTaskShield(TaskShieldMode mode)
+{
+ Error err;
+
+ if ( m_secondaryTask != 0 )
+ {
+ delete m_secondaryTask; // stops the current task
+ m_secondaryTask = 0;
+ }
+
+ m_secondaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_secondaryTask->StartTaskShield(mode, 1000.0f);
+ UpdateInterface();
+ return err;
+}
+
+// Shoots.
+
+Error CBrain::StartTaskFire(float delay)
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskFire(delay);
+ UpdateInterface();
+ return err;
+}
+
+// Shoots to the ant.
+
+Error CBrain::StartTaskFireAnt(Math::Vector impact)
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskFireAnt(impact);
+ UpdateInterface();
+ return err;
+}
+
+// Adjusts upward.
+
+Error CBrain::StartTaskGunGoal(float dirV, float dirH)
+{
+ Error err;
+
+ if ( m_secondaryTask != 0 )
+ {
+ delete m_secondaryTask; // stops the current task
+ m_secondaryTask = 0;
+ }
+
+ m_secondaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_secondaryTask->StartTaskGunGoal(dirV, dirH);
+ UpdateInterface();
+ return err;
+}
+
+// Reset.
+
+Error CBrain::StartTaskReset(Math::Vector goal, Math::Vector angle)
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskReset(goal, angle);
+ UpdateInterface();
+ return err;
+}
+
+// Completes the task when the time came.
+
+Error CBrain::EndedTask()
+{
+ Error err;
+
+ if ( m_secondaryTask != 0 ) // current task?
+ {
+ err = m_secondaryTask->IsEnded();
+ if ( err != ERR_CONTINUE ) // job ended?
+ {
+ delete m_secondaryTask;
+ m_secondaryTask = 0;
+ UpdateInterface();
+ }
+ }
+
+ if ( m_primaryTask != 0 ) // current task?
+ {
+ err = m_primaryTask->IsEnded();
+ if ( err != ERR_CONTINUE ) // job ended?
+ {
+ delete m_primaryTask;
+ m_primaryTask = 0;
+ UpdateInterface();
+ }
+ return err;
+ }
+ return ERR_STOP;
+}
+
+
+
+// Shows flat areas in the field.
+
+void CBrain::GroundFlat()
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+ Error err;
+ float level;
+
+ if ( !m_physics->RetLand() )
+ {
+ err = ERR_FLAG_FLY;
+ pos = m_object->RetPosition(0);
+ if ( pos.y < m_water->RetLevel() ) err = ERR_FLAG_WATER;
+ m_displayText->DisplayError(err, m_object);
+ return;
+ }
+
+ pos = m_object->RetPosition(0);
+ m_terrain->GroundFlat(pos);
+ m_sound->Play(SOUND_GFLAT, pos);
+
+ level = m_terrain->RetFloorLevel(pos)+2.0f;
+ if ( pos.y < level ) pos.y = level; // not below the soil
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 40.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGFLAT, 1.0f);
+}
+
+
+// Not below the soil.
+
+void CBrain::ColorFlag(int color)
+{
+ m_flagColor = color;
+ UpdateInterface();
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CBrain::CreateInterface(bool bSelect)
+{
+ ObjectType type;
+ CWindow* pw;
+ CButton* pb;
+ CColor* pc;
+ CSlider* ps;
+ CTarget* pt;
+ CLabel* pl;
+ Math::Point pos, dim, ddim;
+ float ox, oy, sx, sy;
+ char name[100];
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw != 0 )
+ {
+ pw->Flush(); // destroys the window buttons
+ m_interface->DeleteControl(EVENT_WINDOW0); // destroys the window
+ }
+ m_defaultEnter = EVENT_NULL;
+
+ if ( !bSelect ) return true;
+
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ dim.x = 540.0f/640.0f;
+ if ( !m_main->RetShowMap() ) dim.x = 640.0f/640.0f;
+ dim.y = 86.0f/480.0f;
+ m_interface->CreateWindows(pos, dim, 3, EVENT_WINDOW0);
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ m_object->GetTooltipName(name);
+ pos.x = 0.0f;
+ pos.y = 64.0f/480.0f;
+ ddim.x = 540.0f/640.0f;
+ if ( !m_main->RetShowMap() ) ddim.x = 640.0f/640.0f;
+ ddim.y = 16.0f/480.0f;
+ pw->CreateLabel(pos, ddim, 0, EVENT_LABEL0, name);
+
+ dim.x = 33.0f/640.0f;
+ dim.y = 33.0f/480.0f;
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ type = m_object->RetType();
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr ||
+ type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ) // vehicle?
+ {
+ ddim.x = dim.x*5.1f;
+ ddim.y = dim.y*2.0f;
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0.0f;
+ pw->CreateList(pos, ddim, -1, EVENT_OBJECT_PROGLIST, 1.10f);
+ UpdateScript(pw);
+
+ pos.x = ox+sx*5.2f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, dim, 8, EVENT_OBJECT_PROGRUN);
+ pos.y = oy+sy*0.0f;
+ pw->CreateButton(pos, dim, 22, EVENT_OBJECT_PROGEDIT);
+ }
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_BEE ) // driving?
+ {
+ pos.x = ox+sx*6.4f;
+ pos.y = oy+sy*0;
+ pb = pw->CreateButton(pos, dim, 29, EVENT_OBJECT_GASDOWN);
+ pb->SetImmediat(true);
+
+ pos.x = ox+sx*6.4f;
+ pos.y = oy+sy*1;
+ pb = pw->CreateButton(pos, dim, 28, EVENT_OBJECT_GASUP);
+ pb->SetImmediat(true);
+
+ if ( type != OBJECT_HUMAN ||
+ m_object->RetOption() != 2 )
+ {
+ pos.x = ox+sx*15.3f;
+ pos.y = oy+sy*0;
+ ddim.x = 14.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 2, EVENT_OBJECT_GRANGE);
+ }
+ }
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH )
+ {
+ pos.x = ox+sx*7.7f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 31, EVENT_OBJECT_HTAKE);
+ DefaultEnter(pw, EVENT_OBJECT_HTAKE);
+ }
+
+ if ( (type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ) && // arm?
+ !m_object->RetTrainer() )
+ {
+ pos.x = ox+sx*7.7f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 32, EVENT_OBJECT_MTAKE);
+ DefaultEnter(pw, EVENT_OBJECT_MTAKE);
+
+ pos.x = ox+sx*8.9f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 34, EVENT_OBJECT_MBACK);
+
+ pos.x = ox+sx*9.9f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 35, EVENT_OBJECT_MPOWER);
+
+ pos.x = ox+sx*10.9f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 33, EVENT_OBJECT_MFRONT);
+ }
+
+ if ( type == OBJECT_MOBILEsa && // underwater?
+ !m_object->RetTrainer() )
+ {
+ pos.x = ox+sx*7.7f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 32, EVENT_OBJECT_MTAKE);
+ DefaultEnter(pw, EVENT_OBJECT_MTAKE);
+ }
+
+ if ( type == OBJECT_HUMAN ) // builder?
+ {
+ pos.x = 1.0f/640.0f;
+ pos.y = 4.0f/480.0f;
+ ddim.x = 212.0f/640.0f;
+ ddim.y = 64.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 27, EVENT_NULL);
+
+ ddim.x = dim.x*0.9f;
+ ddim.y = dim.y*0.9f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, ddim, 128+35, EVENT_OBJECT_BRESEARCH);
+ DeadInterface(pw, EVENT_OBJECT_BRESEARCH, g_build&BUILD_RESEARCH);
+
+ pos.x = ox+sx*0.9f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, ddim, 128+32, EVENT_OBJECT_BFACTORY);
+ DeadInterface(pw, EVENT_OBJECT_BFACTORY, g_build&BUILD_FACTORY);
+
+ pos.x = ox+sx*1.8f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, ddim, 128+34, EVENT_OBJECT_BCONVERT);
+ DeadInterface(pw, EVENT_OBJECT_BCONVERT, g_build&BUILD_CONVERT);
+
+ pos.x = ox+sx*2.7f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, ddim, 128+36, EVENT_OBJECT_BSTATION);
+ DeadInterface(pw, EVENT_OBJECT_BSTATION, g_build&BUILD_STATION);
+
+ pos.x = ox+sx*3.6f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, ddim, 128+40, EVENT_OBJECT_BRADAR);
+ DeadInterface(pw, EVENT_OBJECT_BRADAR, g_build&BUILD_RADAR);
+
+ pos.x = ox+sx*4.5f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, ddim, 128+41, EVENT_OBJECT_BREPAIR);
+ DeadInterface(pw, EVENT_OBJECT_BREPAIR, g_build&BUILD_REPAIR);
+
+ pos.x = ox+sx*5.4f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, ddim, 128+44, EVENT_OBJECT_BINFO);
+ DeadInterface(pw, EVENT_OBJECT_BINFO, g_build&BUILD_INFO);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0.1f;
+ pw->CreateButton(pos, ddim, 128+37, EVENT_OBJECT_BTOWER);
+ DeadInterface(pw, EVENT_OBJECT_BTOWER,
+ (g_build&BUILD_TOWER) &&
+ (g_researchDone & RESEARCH_TOWER));
+
+ pos.x = ox+sx*0.9f;
+ pos.y = oy+sy*0.1f;
+ pw->CreateButton(pos, ddim, 128+39, EVENT_OBJECT_BENERGY);
+ DeadInterface(pw, EVENT_OBJECT_BENERGY, g_build&BUILD_ENERGY);
+
+ pos.x = ox+sx*1.8f;
+ pos.y = oy+sy*0.1f;
+ pw->CreateButton(pos, ddim, 128+33, EVENT_OBJECT_BDERRICK);
+ DeadInterface(pw, EVENT_OBJECT_BDERRICK, g_build&BUILD_DERRICK);
+
+ pos.x = ox+sx*2.7f;
+ pos.y = oy+sy*0.1f;
+ pw->CreateButton(pos, ddim, 128+42, EVENT_OBJECT_BNUCLEAR);
+ DeadInterface(pw, EVENT_OBJECT_BNUCLEAR,
+ (g_build&BUILD_NUCLEAR) &&
+ (g_researchDone & RESEARCH_ATOMIC));
+
+ pos.x = ox+sx*3.6f;
+ pos.y = oy+sy*0.1f;
+ pw->CreateButton(pos, ddim, 128+38, EVENT_OBJECT_BLABO);
+ DeadInterface(pw, EVENT_OBJECT_BLABO, g_build&BUILD_LABO);
+
+ pos.x = ox+sx*4.5f;
+ pos.y = oy+sy*0.1f;
+ pw->CreateButton(pos, ddim, 128+46, EVENT_OBJECT_BPARA);
+ DeadInterface(pw, EVENT_OBJECT_BPARA, g_build&BUILD_PARA);
+
+ pos.x = ox+sx*5.4f;
+ pos.y = oy+sy*0.1f;
+ pw->CreateButton(pos, ddim, 128+56, EVENT_OBJECT_BXXXX);
+ DeadInterface(pw, EVENT_OBJECT_BXXXX, false);
+
+ if ( g_build&BUILD_GFLAT )
+ {
+ pos.x = ox+sx*9.0f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 64+47, EVENT_OBJECT_GFLAT);
+ }
+
+ if ( g_build&BUILD_FLAG )
+ {
+ pos.x = ox+sx*10.1f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 64+54, EVENT_OBJECT_FCREATE);
+
+ pos.x = ox+sx*11.1f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 64+55, EVENT_OBJECT_FDELETE);
+
+ ddim.x = dim.x*0.4f;
+ ddim.y = dim.y*0.4f;
+ pos.x = ox+sx*10.1f;
+ pos.y = oy+sy*2.0f-ddim.y;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORb);
+ pc->SetColor(RetColor((D3DCOLOR)0x004890ff));
+ pos.x += ddim.x;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORr);
+ pc->SetColor(RetColor((D3DCOLOR)0x00ff0000));
+ pos.x += ddim.x;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORg);
+ pc->SetColor(RetColor((D3DCOLOR)0x0000ce00));
+ pos.x += ddim.x;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORy);
+ pc->SetColor(RetColor((D3DCOLOR)0x00ffec00));
+ pos.x += ddim.x;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORv);
+ pc->SetColor(RetColor((D3DCOLOR)0x00d101fe));
+ }
+ }
+
+ if ( (type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ) && // Investigator?
+ !m_object->RetTrainer() )
+ {
+ pos.x = ox+sx*7.7f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 40, EVENT_OBJECT_SEARCH);
+ DefaultEnter(pw, EVENT_OBJECT_SEARCH);
+ }
+
+ if ( type == OBJECT_MOBILErt && // Terraformer?
+ !m_object->RetTrainer() )
+ {
+ pos.x = ox+sx*7.7f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 128+18, EVENT_OBJECT_TERRAFORM);
+ DefaultEnter(pw, EVENT_OBJECT_TERRAFORM);
+
+ pos.x = ox+sx*10.2f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT);
+ }
+
+ if ( type == OBJECT_MOBILErr && // recoverer?
+ !m_object->RetTrainer() )
+ {
+ pos.x = ox+sx*7.7f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 128+20, EVENT_OBJECT_RECOVER);
+ DefaultEnter(pw, EVENT_OBJECT_RECOVER);
+ }
+
+ if ( type == OBJECT_MOBILErs && // shield?
+ !m_object->RetTrainer() )
+ {
+ pos.x = ox+sx*7.7f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 39, EVENT_OBJECT_BEGSHIELD);
+ DefaultEnter(pw, EVENT_OBJECT_BEGSHIELD);
+
+ pos.x = ox+sx*9.0f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 47, EVENT_OBJECT_ENDSHIELD);
+
+//? pos.x = ox+sx*10.2f;
+//? pos.y = oy+sy*0.5f;
+//? pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT);
+
+ pos.x = ox+sx*10.5f;
+ pos.y = oy+sy*0.0f;
+ ddim.x = dim.x*0.5f;
+ ddim.y = dim.y*2.0f;
+ ps = pw->CreateSlider(pos, ddim, 0, EVENT_OBJECT_DIMSHIELD);
+ ps->SetState(STATE_VALUE);
+ ps->SetLimit((RADIUS_SHIELD_MIN/g_unit), (RADIUS_SHIELD_MAX/g_unit));
+ ps->SetArrowStep(1.0f);
+ }
+
+ if ( (type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILErc ) && // cannon?
+ !m_object->RetTrainer() )
+ {
+ pos.x = ox+sx*7.7f;
+ pos.y = oy+sy*0.5f;
+ pb = pw->CreateButton(pos, dim, 42, EVENT_OBJECT_FIRE);
+ pb->SetImmediat(true);
+ DefaultEnter(pw, EVENT_OBJECT_FIRE);
+
+//? pos.x = ox+sx*10.2f;
+//? pos.y = oy+sy*0.5f;
+//? pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT);
+ }
+
+ if ( type == OBJECT_MOBILEdr &&
+ m_object->RetManual() ) // scribbler in manual mode?
+ {
+ pos.x = ox+sx*6.9f;
+ pos.y = oy+sy*0.0f;
+ ddim.x = dim.x*2.2f;
+ ddim.y = dim.y*2.0f;
+ pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
+
+ pos.x = ox+sx*9.3f;
+ pos.y = oy+sy*0.0f;
+ ddim.x = dim.x*2.2f;
+ ddim.y = dim.y*2.0f;
+ pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
+
+ pos.x = ox+sx*9.90f;
+ pos.y = oy+sy*0.50f;
+ pw->CreateButton(pos, dim, 43, EVENT_OBJECT_PEN0);
+
+ ddim.x = dim.x*0.5f;
+ ddim.y = dim.y*0.5f;
+ pos.x = ox+sx*10.15f;
+ pos.y = oy+sy*1.50f;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN1); // black
+ pc->SetColor(RetColor((D3DCOLOR)0x00000000));
+ pos.x = ox+sx*10.65f;
+ pos.y = oy+sy*1.25f;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN2); // yellow
+ pc->SetColor(RetColor((D3DCOLOR)0x00ffff00));
+ pos.x = ox+sx*10.90f;
+ pos.y = oy+sy*0.75f;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN3); // orange
+ pc->SetColor(RetColor((D3DCOLOR)0x00ff8800));
+ pos.x = ox+sx*10.65f;
+ pos.y = oy+sy*0.25f;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN4); // red
+ pc->SetColor(RetColor((D3DCOLOR)0x00ff0000));
+ pos.x = ox+sx*10.15f;
+ pos.y = oy+sy*0.00f;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN5); // violet
+ pc->SetColor(RetColor((D3DCOLOR)0x00ff00ff));
+ pos.x = ox+sx*9.65f;
+ pos.y = oy+sy*0.25f;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN6); // blue
+ pc->SetColor(RetColor((D3DCOLOR)0x000066ff));
+ pos.x = ox+sx*9.40f;
+ pos.y = oy+sy*0.75f;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN7); // green
+ pc->SetColor(RetColor((D3DCOLOR)0x0000cc00));
+ pos.x = ox+sx*9.65f;
+ pos.y = oy+sy*1.25f;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN8); // brown
+ pc->SetColor(RetColor((D3DCOLOR)0x00884400));
+
+ pos.x = ox+sx*6.9f;
+ pos.y = oy+sy*1.2f;
+ ddim.x = dim.x*2.2f;
+ ddim.y = dim.y*0.4f;
+ GetResource(RES_TEXT, RT_INTERFACE_REC, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, name);
+ pl->SetFontSize(9.0f);
+
+ pos.x = ox+sx*7.0f;
+ pos.y = oy+sy*0.3f;
+ pw->CreateButton(pos, dim, 44, EVENT_OBJECT_REC);
+ pos.x = ox+sx*8.0f;
+ pos.y = oy+sy*0.3f;
+ pw->CreateButton(pos, dim, 45, EVENT_OBJECT_STOP);
+ }
+
+ if ( m_object->RetToy() )
+ {
+ pos.x = ox+sx*12.1f;
+ pos.y = oy+sy*-0.1f;
+ ddim.x = dim.x*1.2f;
+ ddim.y = dim.y*2.1f;
+ pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
+
+ pos.x = ox+sx*12.2f;
+ pos.y = oy+sy*1;
+ pw->CreateGroup(pos, dim, 19, EVENT_NULL); // sign SatCom
+
+ pos.x = ox+sx*12.2f;
+ pos.y = oy+sy*0.0f;
+ pw->CreateButton(pos, dim, 128+57, EVENT_OBJECT_BHELP);
+ }
+ else
+ {
+ pos.x = ox+sx*12.3f;
+ pos.y = oy+sy*-0.1f;
+ ddim.x = dim.x*1.0f;
+ ddim.y = dim.y*2.1f;
+ pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
+
+ pos.x = ox+sx*12.3f;
+ pos.y = oy+sy*1;
+ pw->CreateGroup(pos, dim, 19, EVENT_NULL); // sign SatCom
+
+ pos.x = ox+sx*12.4f;
+ pos.y = oy+sy*0.5f;
+ ddim.x = dim.x*0.8f;
+ ddim.y = dim.y*0.5f;
+ pw->CreateButton(pos, ddim, 18, EVENT_OBJECT_BHELP);
+ pos.y = oy+sy*0.0f;
+ pw->CreateButton(pos, ddim, 19, EVENT_OBJECT_HELP);
+ }
+
+ if ( type != OBJECT_HUMAN &&
+ type != OBJECT_TECH &&
+ !m_object->RetCameraLock() )
+ {
+//? if ( m_main->RetShowMap() )
+ if ( true )
+ {
+ pos.x = ox+sx*13.4f;
+ pos.y = oy+sy*1;
+ pw->CreateButton(pos, dim, 13, EVENT_OBJECT_CAMERA);
+ }
+ else
+ {
+ ddim.x = dim.x*0.66f;
+ ddim.y = dim.y*0.66f;
+ pos.x = ox+sx*(17.0f+0.66f);
+ pos.y = oy+sy*0.66f;
+ pw->CreateButton(pos, ddim, 13, EVENT_OBJECT_CAMERA);
+ }
+ }
+
+ if ( m_object->RetToy() && !m_object->RetManual() )
+ {
+#if 0
+ ddim.x = dim.x*0.66f;
+ ddim.y = dim.y*0.66f;
+ pos.x = ox+sx*10.0f;
+ pos.y = oy+sy*0.66f;
+ pb = pw->CreateButton(pos, ddim, 55, EVENT_OBJECT_CAMERAleft);
+ pb->SetImmediat(true);
+ pos.x = ox+sx*(10.0f+0.66f*2.0f);
+ pos.y = oy+sy*0.66f;
+ pb = pw->CreateButton(pos, ddim, 48, EVENT_OBJECT_CAMERAright);
+ pb->SetImmediat(true);
+ pos.x = ox+sx*(10.0f+0.66f);
+ pos.y = oy+sy*(0.66f*2.0f);
+ pb = pw->CreateButton(pos, ddim, 49, EVENT_OBJECT_CAMERAnear);
+ pb->SetImmediat(true);
+ pos.x = ox+sx*(10.0f+0.66f);
+ pos.y = oy+sy*0.0f;
+ pb = pw->CreateButton(pos, ddim, 50, EVENT_OBJECT_CAMERAaway);
+ pb->SetImmediat(true);
+#else
+ pos.x = ox+sx*9.0f;
+ pos.y = oy+sy*0;
+ pb = pw->CreateButton(pos, dim, 55, EVENT_OBJECT_CAMERAleft);
+ pb->SetImmediat(true);
+ pos.x = ox+sx*11.0f;
+ pos.y = oy+sy*0;
+ pb = pw->CreateButton(pos, dim, 48, EVENT_OBJECT_CAMERAright);
+ pb->SetImmediat(true);
+ pos.x = ox+sx*10.0f;
+ pos.y = oy+sy*1;
+ pb = pw->CreateButton(pos, dim, 49, EVENT_OBJECT_CAMERAnear);
+ pb->SetImmediat(true);
+ pos.x = ox+sx*10.0f;
+ pos.y = oy+sy*0;
+ pb = pw->CreateButton(pos, dim, 50, EVENT_OBJECT_CAMERAaway);
+ pb->SetImmediat(true);
+#endif
+ }
+
+ pos.x = ox+sx*13.4f;
+ pos.y = oy+sy*0;
+#if _TEEN
+ pw->CreateButton(pos, dim, 9, EVENT_OBJECT_RESET);
+#else
+ if ( m_object->RetTrainer() ) // Training?
+ {
+ pw->CreateButton(pos, dim, 9, EVENT_OBJECT_RESET);
+ }
+ else
+ {
+ pw->CreateButton(pos, dim, 10, EVENT_OBJECT_DESELECT);
+ }
+#endif
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ) // vehicle?
+ {
+ pos.x = ox+sx*14.5f;
+ pos.y = oy+sy*0;
+ ddim.x = 14.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
+ }
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH ||
+ type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ) // vehicle?
+ {
+ pos.x = ox+sx*14.9f;
+ pos.y = oy+sy*0;
+ ddim.x = 14.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 3, EVENT_OBJECT_GSHIELD);
+ }
+
+#if 0
+ if ( false )
+ {
+ pos.x = 505.0f/640.0f;
+ pos.y = 3.0f/480.0f;
+ ddim.x = 33.0f/640.0f;
+ ddim.y = 33.0f/480.0f;
+ pw->CreateCompass(pos, ddim, 0, EVENT_OBJECT_COMPASS);
+
+ pc = (CCompass*)pw->SearchControl(EVENT_OBJECT_COMPASS);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_VISIBLE, m_main->RetShowMap());
+ }
+ }
+#endif
+
+ if ( type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILErc ) // cannon?
+ {
+ ddim.x = 64.0f/640.0f;
+ ddim.y = 64.0f/480.0f;
+ pos.x = 0.5f-ddim.x/2.0f;
+ pos.y = 0.5f-ddim.y/2.0f;
+ pw->CreateGroup(pos, ddim, 12, EVENT_OBJECT_CROSSHAIR);
+
+ pos.x = 20.0f/640.0f;
+ pos.y = 100.0f/480.0f;
+ ddim.x = 600.0f/640.0f;
+ ddim.y = 340.0f/480.0f;
+ pt = pw->CreateTarget(pos, ddim, 0, EVENT_OBJECT_TARGET);
+ pt->ClearState(STATE_GLINT);
+ }
+
+ ddim.x = 64.0f/640.0f;
+ ddim.y = 64.0f/480.0f;
+ pos.x = 30.0f/640.0f;
+ pos.y = 430.0f/480.0f-ddim.y;
+ pw->CreateGroup(pos, ddim, 13, EVENT_OBJECT_CORNERul);
+
+ ddim.x = 64.0f/640.0f;
+ ddim.y = 64.0f/480.0f;
+ pos.x = 610.0f/640.0f-ddim.x;
+ pos.y = 430.0f/480.0f-ddim.y;
+ pw->CreateGroup(pos, ddim, 14, EVENT_OBJECT_CORNERur);
+
+ ddim.x = 64.0f/640.0f;
+ ddim.y = 64.0f/480.0f;
+ pos.x = 30.0f/640.0f;
+ pos.y = 110.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 15, EVENT_OBJECT_CORNERdl);
+
+ ddim.x = 64.0f/640.0f;
+ ddim.y = 64.0f/480.0f;
+ pos.x = 610.0f/640.0f-ddim.x;
+ pos.y = 110.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 16, EVENT_OBJECT_CORNERdr);
+
+ UpdateInterface();
+ m_lastUpdateTime = 0.0f;
+ UpdateInterface(0.0f);
+
+ return true;
+}
+
+// Updates the state of all buttons on the interface,
+// following the time that elapses ...
+
+void CBrain::UpdateInterface(float rTime)
+{
+ CWindow* pw;
+#if _TEEN
+ CButton* pb;
+#endif
+ CGauge* pg;
+ CCompass* pc;
+ CGroup* pgr;
+ CTarget* ptg;
+ CObject* power;
+ Math::Vector pos, hPos;
+ Math::Point ppos;
+ float energy, limit, angle, range;
+ int icon;
+ bool bOnBoard;
+
+ m_lastAlarmTime += rTime;
+ if ( m_time < m_lastUpdateTime+0.1f ) return;
+ m_lastUpdateTime = m_time;
+
+ if ( !m_object->RetSelect() )
+ {
+ if ( m_soundChannelAlarm != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannelAlarm);
+ m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 1.0f, 0.1f, SOPER_STOP);
+ m_soundChannelAlarm = -1;
+ }
+ return;
+ }
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
+ if ( pg != 0 )
+ {
+ power = m_object->RetPower();
+ if ( power == 0 )
+ {
+ energy = 0.0f;
+ }
+ else
+ {
+ energy = power->RetEnergy();
+ limit = energy*power->RetCapacity();
+ }
+ icon = 0; // red/green
+
+ if ( limit < 0.2f && energy != 0.0f ) // low but not zero?
+ {
+ if ( m_lastAlarmTime >= 0.8f ) // blinks?
+ {
+ energy = 1.0f;
+ icon = 1; // brun
+ }
+ if ( m_lastAlarmTime >= 1.0f )
+ {
+ m_sound->Play(SOUND_ALARM, 0.5f); // bip-bip-bip
+ m_lastAlarmTime = 0.0f;
+ }
+ }
+ pg->SetLevel(energy);
+ pg->SetIcon(icon);
+ }
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GSHIELD);
+ if ( pg != 0 )
+ {
+ pg->SetLevel(m_object->RetShield());
+ }
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GRANGE);
+ if ( pg != 0 )
+ {
+ icon = 2; // blue/red
+ range = m_physics->RetReactorRange();
+
+ if ( range < 0.2f && range != 0.0f && !m_physics->RetLand() )
+ {
+ if ( Math::Mod(m_time, 0.5f) >= 0.2f ) // blinks?
+ {
+ range = 1.0f;
+ icon = 1; // yellow
+ }
+ if ( m_soundChannelAlarm == -1 )
+ {
+ m_soundChannelAlarm = m_sound->Play(SOUND_ALARMt, m_object->RetPosition(0), 0.0f, 0.1f, true);
+ m_sound->AddEnvelope(m_soundChannelAlarm, 1.0f, 1.0f, 1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannelAlarm, 1.0f, 1.0f, 1.0f, SOPER_LOOP);
+ }
+ }
+ else
+ {
+ if ( m_soundChannelAlarm != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannelAlarm);
+ m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 0.1f, 1.0f, SOPER_STOP);
+ m_soundChannelAlarm = -1;
+ }
+ }
+
+ pg->SetLevel(1.0f-range);
+ pg->SetIcon(icon);
+ }
+
+ pc = (CCompass*)pw->SearchControl(EVENT_OBJECT_COMPASS);
+ if ( pc != 0 )
+ {
+ angle = -(m_object->RetAngleY(0)+Math::PI/2.0f);
+ pc->SetDirection(angle);
+
+ pc->SetState(STATE_VISIBLE, m_main->RetShowMap());
+ }
+
+#if _TEEN
+ pb = (CButton*)pw->SearchControl(EVENT_OBJECT_REC);
+ if ( pb != 0 )
+ {
+ if ( m_bTraceRecord && Math::Mod(m_time, 0.4f) >= 0.2f )
+ {
+ pb->SetState(STATE_CHECK);
+ }
+ else
+ {
+ pb->ClearState(STATE_CHECK);
+ }
+ }
+#endif
+
+ bOnBoard = m_camera->RetType() == CAMERA_ONBOARD;
+
+ pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CROSSHAIR);
+ if ( pgr != 0 )
+ {
+ if ( bOnBoard )
+ {
+#if 0
+ angle = m_object->RetGunGoalV();
+ if ( m_object->RetType() != OBJECT_MOBILErc )
+ {
+ angle += 10.0f*Math::PI/360.0f;
+ }
+ ppos.x = 0.5f-(64.0f/640.0f)/2.0f;
+ ppos.y = 0.5f-(64.0f/480.0f)/2.0f;
+ ppos.y += sinf(angle)*0.6f;
+ pgr->SetPos(ppos);
+#else
+ ppos.x = 0.50f-(64.0f/640.0f)/2.0f;
+ ppos.y = 0.50f-(64.0f/480.0f)/2.0f;
+ ppos.x += m_object->RetGunGoalH()/2.0f;
+ ppos.y += m_object->RetGunGoalV()/1.3f;
+ pgr->SetPos(ppos);
+#endif
+ pgr->SetState(STATE_VISIBLE, !m_main->RetFriendAim());
+ }
+ else
+ {
+ pgr->ClearState(STATE_VISIBLE);
+ }
+ }
+
+ ptg = (CTarget*)pw->SearchControl(EVENT_OBJECT_TARGET);
+ if ( ptg != 0 )
+ {
+ if ( bOnBoard )
+ {
+ ptg->SetState(STATE_VISIBLE);
+ }
+ else
+ {
+ ptg->ClearState(STATE_VISIBLE);
+ }
+ }
+
+ pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERul);
+ if ( pgr != 0 )
+ {
+ pgr->SetState(STATE_VISIBLE, bOnBoard);
+ }
+
+ pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERur);
+ if ( pgr != 0 )
+ {
+ pgr->SetState(STATE_VISIBLE, bOnBoard);
+ }
+
+ pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERdl);
+ if ( pgr != 0 )
+ {
+ pgr->SetState(STATE_VISIBLE, bOnBoard);
+ }
+
+ pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERdr);
+ if ( pgr != 0 )
+ {
+ pgr->SetState(STATE_VISIBLE, bOnBoard);
+ }
+}
+
+// Updates the status of all interface buttons.
+
+void CBrain::UpdateInterface()
+{
+ ObjectType type;
+ CWindow* pw;
+ CButton* pb;
+ CSlider* ps;
+#if _TEEN
+ CColor* pc;
+ int color;
+#endif
+ bool bEnable, bFly, bRun;
+ char title[100];
+
+ if ( !m_object->RetSelect() ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ type = m_object->RetType();
+
+ bEnable = ( m_secondaryTask == 0 && m_program == -1 );
+
+ bEnable = ( m_primaryTask == 0 && m_program == -1 );
+
+ EnableInterface(pw, EVENT_OBJECT_PROGEDIT, (m_primaryTask == 0 && !m_bTraceRecord));
+ EnableInterface(pw, EVENT_OBJECT_PROGLIST, bEnable && !m_bTraceRecord);
+ EnableInterface(pw, EVENT_OBJECT_LEFT, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_RIGHT, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_UP, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_DOWN, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_HTAKE, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_MTAKE, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_MBACK, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_MPOWER, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_MFRONT, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_GFLAT, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_FCREATE, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_FDELETE, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_SEARCH, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_TERRAFORM, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_RECOVER, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_FIRE, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_RESET, bEnable);
+#if _TEEN
+ EnableInterface(pw, EVENT_OBJECT_PEN0, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_PEN1, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_PEN2, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_PEN3, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_PEN4, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_PEN5, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_PEN6, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_PEN7, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_PEN8, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_REC, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_STOP, bEnable);
+#endif
+
+ if ( type == OBJECT_HUMAN ) // builder?
+ {
+ EnableInterface(pw, EVENT_OBJECT_BFACTORY, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BDERRICK, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BCONVERT, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BSTATION, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BREPAIR, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BTOWER, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BRESEARCH, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BRADAR, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BENERGY, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BLABO, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BNUCLEAR, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BPARA, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BINFO, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BXXXX, bEnable);
+ }
+
+ pb = (CButton*)pw->SearchControl(EVENT_OBJECT_GFLAT);
+ if ( pb != 0 )
+ {
+ pb->SetState(STATE_VISIBLE, m_engine->RetGroundSpot());
+ }
+
+ if ( type == OBJECT_HUMAN || // builder?
+ type == OBJECT_TECH )
+ {
+ CheckInterface(pw, EVENT_OBJECT_FCOLORb, m_flagColor==0);
+ CheckInterface(pw, EVENT_OBJECT_FCOLORr, m_flagColor==1);
+ CheckInterface(pw, EVENT_OBJECT_FCOLORg, m_flagColor==2);
+ CheckInterface(pw, EVENT_OBJECT_FCOLORy, m_flagColor==3);
+ CheckInterface(pw, EVENT_OBJECT_FCOLORv, m_flagColor==4);
+ }
+
+ if ( type == OBJECT_MOBILErs ) // shield?
+ {
+ if ( (m_secondaryTask == 0 || !m_secondaryTask->IsBusy()) && m_program == -1 )
+ {
+ EnableInterface(pw, EVENT_OBJECT_BEGSHIELD, (m_secondaryTask == 0));
+ EnableInterface(pw, EVENT_OBJECT_ENDSHIELD, (m_secondaryTask != 0));
+ DefaultEnter (pw, EVENT_OBJECT_BEGSHIELD, (m_secondaryTask == 0));
+ DefaultEnter (pw, EVENT_OBJECT_ENDSHIELD, (m_secondaryTask != 0));
+ }
+ else
+ {
+ EnableInterface(pw, EVENT_OBJECT_BEGSHIELD, false);
+ EnableInterface(pw, EVENT_OBJECT_ENDSHIELD, false);
+ DefaultEnter (pw, EVENT_OBJECT_BEGSHIELD, false);
+ DefaultEnter (pw, EVENT_OBJECT_ENDSHIELD, false);
+ }
+
+ ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_DIMSHIELD);
+ if ( ps != 0 )
+ {
+ ps->SetVisibleValue((RADIUS_SHIELD_MIN/g_unit)+m_object->RetParam()*((RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)/g_unit));
+ }
+ }
+
+ bFly = bEnable;
+ if ( bFly && (type == OBJECT_HUMAN || type == OBJECT_TECH) )
+ {
+ if ( m_object->RetFret() != 0 ) bFly = false; // if holder -> not fly
+ }
+ EnableInterface(pw, EVENT_OBJECT_GASUP, bFly);
+ EnableInterface(pw, EVENT_OBJECT_GASDOWN, bFly);
+ if ( m_object->RetTrainer() ) // Training?
+ {
+ DeadInterface(pw, EVENT_OBJECT_GASUP, false);
+ DeadInterface(pw, EVENT_OBJECT_GASDOWN, false);
+ }
+ else
+ {
+ DeadInterface(pw, EVENT_OBJECT_GASUP, g_researchDone&RESEARCH_FLY);
+ DeadInterface(pw, EVENT_OBJECT_GASDOWN, g_researchDone&RESEARCH_FLY);
+ }
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH ||
+ type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr ||
+ type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ) // vehicle?
+ {
+ bRun = false;
+ if ( m_script[m_selScript] != 0 )
+ {
+ m_script[m_selScript]->GetTitle(title);
+ if ( title[0] != 0 )
+ {
+ bRun = true;
+ }
+ }
+ if ( !bEnable && m_program == -1 ) bRun = false;
+ if ( m_bTraceRecord ) bRun = false;
+ EnableInterface(pw, EVENT_OBJECT_PROGRUN, bRun);
+
+ pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PROGRUN);
+ if ( pb != 0 )
+ {
+ pb->SetIcon(m_program==-1?21:8); // run/stop
+ }
+
+//? pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PROGEDIT);
+//? if ( pb != 0 )
+//? {
+//? pb->SetIcon(m_program==-1?22:40); // edit/debug
+//? }
+
+ BlinkScript(m_program != -1); // blinks if script execution
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ) // arm?
+ {
+ CheckInterface(pw, EVENT_OBJECT_MPOWER, m_manipStyle==EVENT_OBJECT_MPOWER);
+ CheckInterface(pw, EVENT_OBJECT_MBACK, m_manipStyle==EVENT_OBJECT_MBACK);
+ CheckInterface(pw, EVENT_OBJECT_MFRONT, m_manipStyle==EVENT_OBJECT_MFRONT);
+ }
+
+#if _TEEN
+ if ( m_object->RetTraceDown() )
+ {
+ pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PEN0);
+ if ( pb != 0 )
+ {
+ pb->ClearState(STATE_CHECK);
+ }
+
+ color = m_object->RetTraceColor();
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN1);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, color==1);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN2);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, color==8);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN3);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, color==7);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN4);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, color==4);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN5);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, color==6);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN6);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, color==14);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN7);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, color==12);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN8);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, color==10);
+ }
+ }
+ else
+ {
+ pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PEN0);
+ if ( pb != 0 )
+ {
+ pb->SetState(STATE_CHECK);
+ }
+
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN1);
+ if ( pc != 0 )
+ {
+ pc->ClearState(STATE_CHECK);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN2);
+ if ( pc != 0 )
+ {
+ pc->ClearState(STATE_CHECK);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN3);
+ if ( pc != 0 )
+ {
+ pc->ClearState(STATE_CHECK);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN4);
+ if ( pc != 0 )
+ {
+ pc->ClearState(STATE_CHECK);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN5);
+ if ( pc != 0 )
+ {
+ pc->ClearState(STATE_CHECK);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN6);
+ if ( pc != 0 )
+ {
+ pc->ClearState(STATE_CHECK);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN7);
+ if ( pc != 0 )
+ {
+ pc->ClearState(STATE_CHECK);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN8);
+ if ( pc != 0 )
+ {
+ pc->ClearState(STATE_CHECK);
+ }
+ }
+#endif
+}
+
+// Updates the list of programs.
+
+void CBrain::UpdateScript(CWindow *pw)
+{
+ CList* pl;
+ char name[100];
+ char title[100];
+ int i;
+ bool bSoluce;
+
+ pl = (CList*)pw->SearchControl(EVENT_OBJECT_PROGLIST);
+ if ( pl == 0 ) return;
+
+#if _SCHOOL
+ bSoluce = m_main->RetSoluce4();
+#else
+ bSoluce = true;
+#endif
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ sprintf(name, "%d", i+1);
+
+ if ( m_script[i] != 0 )
+ {
+ m_script[i]->GetTitle(title);
+ if ( !bSoluce && i == 3 )
+ {
+ title[0] = 0;
+ }
+ if ( title[0] != 0 )
+ {
+ sprintf(name, "%d: %s", i+1, title);
+ }
+ }
+
+ pl->SetName(i, name);
+ }
+
+ if ( !bSoluce )
+ {
+ pl->SetEnable(3, false);
+ }
+
+ pl->SetSelect(m_selScript);
+ pl->ShowSelect(true);
+}
+
+// Returns the rank of selected script.
+
+int CBrain::RetSelScript()
+{
+ CWindow* pw;
+ CList* pl;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return -1;
+
+ pl = (CList*)pw->SearchControl(EVENT_OBJECT_PROGLIST);
+ if ( pl == 0 ) return -1;
+
+ return pl->RetSelect();
+}
+
+// Blinks the running program.
+
+void CBrain::BlinkScript(bool bEnable)
+{
+ CWindow* pw;
+ CList* pl;
+
+ if ( !m_object->RetSelect() ) return; // robot not selected?
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pl = (CList*)pw->SearchControl(EVENT_OBJECT_PROGLIST);
+ if ( pl == 0 ) return;
+
+ pl->SetBlink(bEnable);
+}
+
+// Check the status of a button interface.
+
+void CBrain::CheckInterface(CWindow *pw, EventMsg event, bool bState)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_CHECK, bState);
+}
+
+// Changes the state of a button interface.
+
+void CBrain::EnableInterface(CWindow *pw, EventMsg event, bool bState)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_ENABLE, bState);
+}
+
+// Changes the state of a button on the interface.
+
+void CBrain::DeadInterface(CWindow *pw, EventMsg event, bool bState)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_DEAD, !bState);
+}
+
+// Change the default input state of a button interface.
+
+void CBrain::DefaultEnter(CWindow *pw, EventMsg event, bool bState)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ if ( bState )
+ {
+ control->SetState(STATE_DEFAULT);
+ m_defaultEnter = event;
+ }
+ else
+ {
+ control->ClearState(STATE_DEFAULT);
+ }
+}
+
+
+// Indicates whether the object is busy with a task.
+
+bool CBrain::IsBusy()
+{
+ return (m_primaryTask != 0);
+}
+
+// Management of the activity of an object.
+
+void CBrain::SetActivity(bool bMode)
+{
+ m_bActivity = bMode;
+}
+
+bool CBrain::RetActivity()
+{
+ return m_bActivity;
+}
+
+// Indicates whether a program is running.
+
+bool CBrain::IsProgram()
+{
+ return ( m_program != -1 );
+}
+
+// Indicates whether a program exists.
+
+bool CBrain::ProgramExist(int rank)
+{
+ return ( m_script[rank] != 0 );
+}
+
+// Starts a program.
+
+void CBrain::RunProgram(int rank)
+{
+ if ( rank < 0 ) return;
+
+ if ( m_script[rank] != 0 &&
+ m_script[rank]->Run() )
+ {
+ m_program = rank; // start new program
+ BlinkScript(true); // blink
+ m_object->CreateSelectParticule();
+ m_main->UpdateShortcuts();
+ }
+}
+
+// Returns the first free program.
+
+int CBrain::FreeProgram()
+{
+ int i;
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ if ( m_script[i] == 0 ) return i;
+ }
+ return -1;
+}
+
+
+// Returns the current program.
+
+int CBrain::RetProgram()
+{
+ return m_program;
+}
+
+
+// Name management scripts to load.
+
+void CBrain::SetScriptRun(int rank)
+{
+ m_scriptRun = rank;
+}
+
+int CBrain::RetScriptRun()
+{
+ return m_scriptRun;
+}
+
+void CBrain::SetScriptName(int rank, char *name)
+{
+ strcpy(m_scriptName[rank], name);
+}
+
+char* CBrain::RetScriptName(int rank)
+{
+ return m_scriptName[rank];
+}
+
+void CBrain::SetSoluceName(char *name)
+{
+ strcpy(m_soluceName, name);
+}
+
+char* CBrain::RetSoluceName()
+{
+ return m_soluceName;
+}
+
+
+// Load a script solution, in the first free script.
+// If there is already an identical script, nothing is loaded.
+
+bool CBrain::ReadSoluce(char* filename)
+{
+ int rank, i;
+
+ rank = FreeProgram();
+ if ( rank == -1 ) return false;
+
+ if ( !ReadProgram(rank, filename) ) return false; // load solution
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ if ( i == rank || m_script[i] == 0 ) continue;
+
+ if ( m_script[i]->Compare(m_script[rank]) ) // the same already?
+ {
+ delete m_script[rank];
+ m_script[rank] = 0;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Load a script with a text file.
+
+bool CBrain::ReadProgram(int rank, char* filename)
+{
+ if ( m_script[rank] == 0 )
+ {
+ m_script[rank] = new CScript(m_iMan, m_object, &m_secondaryTask);
+ }
+
+ if ( m_script[rank]->ReadScript(filename) ) return true;
+
+ delete m_script[rank];
+ m_script[rank] = 0;
+
+ return false;
+}
+
+// Indicates whether a program is compiled correctly.
+
+bool CBrain::RetCompile(int rank)
+{
+ if ( m_script[rank] == 0 ) return false;
+ return m_script[rank]->RetCompile();
+}
+
+// Saves a script in a text file.
+
+bool CBrain::WriteProgram(int rank, char* filename)
+{
+ if ( m_script[rank] == 0 )
+ {
+ m_script[rank] = new CScript(m_iMan, m_object, &m_secondaryTask);
+ }
+
+ if ( m_script[rank]->WriteScript(filename) ) return true;
+
+ delete m_script[rank];
+ m_script[rank] = 0;
+
+ return false;
+}
+
+
+// Load a stack of script implementation from a file.
+
+bool CBrain::ReadStack(FILE *file)
+{
+ short op;
+
+ fRead(&op, sizeof(short), 1, file);
+ if ( op == 1 ) // run ?
+ {
+ fRead(&op, sizeof(short), 1, file); // program rank
+ if ( op >= 0 && op < BRAINMAXSCRIPT )
+ {
+ m_program = op; // program restarts
+ m_selScript = op;
+ BlinkScript(true); // blink
+
+ if ( m_script[op] == 0 )
+ {
+ m_script[op] = new CScript(m_iMan, m_object, &m_secondaryTask);
+ }
+ if ( !m_script[op]->ReadStack(file) ) return false;
+ }
+ }
+
+ return true;
+}
+
+// ave the script implementation stack of a file.
+
+bool CBrain::WriteStack(FILE *file)
+{
+ short op;
+
+ if ( m_program != -1 && // current program?
+ m_script[m_program]->IsRunning() )
+ {
+ op = 1; // run
+ fWrite(&op, sizeof(short), 1, file);
+
+ op = m_program;
+ fWrite(&op, sizeof(short), 1, file);
+
+ return m_script[m_program]->WriteStack(file);
+ }
+
+ op = 0; // stop
+ fWrite(&op, sizeof(short), 1, file);
+ return true;
+}
+
+
+
+// Start of registration of the design.
+
+void CBrain::TraceRecordStart()
+{
+ m_traceOper = TO_STOP;
+
+ m_tracePos = m_object->RetPosition(0);
+ m_traceAngle = m_object->RetAngleY(0);
+
+ if ( m_object->RetTraceDown() ) // pencil down?
+ {
+ m_traceColor = m_object->RetTraceColor();
+ }
+ else // pen up?
+ {
+ m_traceColor = -1;
+ }
+
+ delete m_traceRecordBuffer;
+ m_traceRecordBuffer = (TraceRecord*)malloc(sizeof(TraceRecord)*MAXTRACERECORD);
+ m_traceRecordIndex = 0;
+}
+
+// Saving the current drawing.
+
+void CBrain::TraceRecordFrame()
+{
+ TraceOper oper = TO_STOP;
+ Math::Vector pos;
+ float angle, len, speed;
+ int color;
+
+ speed = m_physics->RetLinMotionX(MO_REASPEED);
+ if ( speed > 0.0f ) oper = TO_ADVANCE;
+ if ( speed < 0.0f ) oper = TO_RECEDE;
+
+ speed = m_physics->RetCirMotionY(MO_REASPEED);
+ if ( speed != 0.0f ) oper = TO_TURN;
+
+ if ( m_object->RetTraceDown() ) // pencil down?
+ {
+ color = m_object->RetTraceColor();
+ }
+ else // pen up?
+ {
+ color = -1;
+ }
+
+ if ( oper != m_traceOper ||
+ color != m_traceColor )
+ {
+ if ( m_traceOper == TO_ADVANCE ||
+ m_traceOper == TO_RECEDE )
+ {
+ pos = m_object->RetPosition(0);
+ len = Math::DistanceProjected(pos, m_tracePos);
+ TraceRecordOper(m_traceOper, len);
+ }
+ if ( m_traceOper == TO_TURN )
+ {
+ angle = m_object->RetAngleY(0)-m_traceAngle;
+ TraceRecordOper(m_traceOper, angle);
+ }
+
+ if ( color != m_traceColor )
+ {
+ TraceRecordOper(TO_PEN, (float)color);
+ }
+
+ m_traceOper = oper;
+ m_tracePos = m_object->RetPosition(0);
+ m_traceAngle = m_object->RetAngleY(0);
+ m_traceColor = color;
+ }
+}
+
+// End of the registration of the design. Program generates the CBOT.
+
+void CBrain::TraceRecordStop()
+{
+ TraceOper lastOper, curOper;
+ float lastParam, curParam;
+ int max, i;
+ char* buffer;
+
+ if ( m_traceRecordBuffer == 0 ) return;
+
+ max = 10000;
+ buffer = (char*)malloc(max);
+ *buffer = 0;
+ strncat(buffer, "extern void object::AutoDraw()\n{\n", max-1);
+
+ lastOper = TO_STOP;
+ lastParam = 0.0f;
+ for ( i=0 ; i<m_traceRecordIndex ; i++ )
+ {
+ curOper = m_traceRecordBuffer[i].oper;
+ curParam = m_traceRecordBuffer[i].param;
+
+ if ( curOper == lastOper )
+ {
+ if ( curOper == TO_PEN )
+ {
+ lastParam = curParam;
+ }
+ else
+ {
+ lastParam += curParam;
+ }
+ }
+ else
+ {
+ TraceRecordPut(buffer, max, lastOper, lastParam);
+ lastOper = curOper;
+ lastParam = curParam;
+ }
+ }
+ TraceRecordPut(buffer, max, lastOper, lastParam);
+
+ delete m_traceRecordBuffer;
+ m_traceRecordBuffer = 0;
+
+ strncat(buffer, "}\n", max-1);
+ buffer[max-1] = 0;
+
+ i = m_selScript;
+ if ( m_script[i] == 0 )
+ {
+ m_script[i] = new CScript(m_iMan, m_object, &m_secondaryTask);
+ }
+ m_script[i]->SendScript(buffer);
+ delete buffer;
+}
+
+// Saves an instruction CBOT.
+
+bool CBrain::TraceRecordOper(TraceOper oper, float param)
+{
+ int i;
+
+ i = m_traceRecordIndex;
+ if ( i >= MAXTRACERECORD ) return false;
+
+ m_traceRecordBuffer[i].oper = oper;
+ m_traceRecordBuffer[i].param = param;
+
+ m_traceRecordIndex = i+1;
+ return true;
+}
+
+// Generates an instruction CBOT.
+
+bool CBrain::TraceRecordPut(char *buffer, int max, TraceOper oper, float param)
+{
+ char line[100];
+ int color;
+
+ if ( oper == TO_ADVANCE )
+ {
+ param /= g_unit;
+ sprintf(line, "\tmove(%.1f);\n", param);
+ strncat(buffer, line, max-1);
+ }
+
+ if ( oper == TO_RECEDE )
+ {
+ param /= g_unit;
+ sprintf(line, "\tmove(-%.1f);\n", param);
+ strncat(buffer, line, max-1);
+ }
+
+ if ( oper == TO_TURN )
+ {
+ param = -param*180.0f/Math::PI;
+ sprintf(line, "\tturn(%d);\n", (int)param);
+//? sprintf(line, "\tturn(%.1f);\n", param);
+ strncat(buffer, line, max-1);
+ }
+
+ if ( oper == TO_PEN )
+ {
+ color = (int)param;
+ if ( color == -1 ) strncat(buffer, "\tpenup();\n", max-1);
+ if ( color == 1 ) strncat(buffer, "\tpendown(Black);\n", max-1);
+ if ( color == 8 ) strncat(buffer, "\tpendown(Yellow);\n", max-1);
+ if ( color == 7 ) strncat(buffer, "\tpendown(Orange);\n", max-1);
+ if ( color == 4 ) strncat(buffer, "\tpendown(Red);\n", max-1);
+ if ( color == 6 ) strncat(buffer, "\tpendown(Purple);\n", max-1);
+ if ( color == 14 ) strncat(buffer, "\tpendown(Blue);\n", max-1);
+ if ( color == 12 ) strncat(buffer, "\tpendown(Green);\n", max-1);
+ if ( color == 10 ) strncat(buffer, "\tpendown(Brown);\n", max-1);
+ }
+
+ return true;
+}
+
diff --git a/src/object/brain.h b/src/object/brain.h
index 7c258ae..0220ffc 100644
--- a/src/object/brain.h
+++ b/src/object/brain.h
@@ -1,218 +1,218 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// brain.h
-
-#pragma once
-
-
-#include <stdio.h>
-
-#include "common/misc.h"
-#include "common/event.h"
-#include "object/object.h"
-#include "object/task/taskmanip.h"
-#include "object/task/taskflag.h"
-#include "object/task/taskshield.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CTerrain;
-class CWater;
-class CCamera;
-class CObject;
-class CPhysics;
-class CMotion;
-class CTaskManager;
-class CInterface;
-class CWindow;
-class CDisplayText;
-class CScript;
-class CRobotMain;
-class CStudio;
-class CSound;
-class CParticule;
-
-
-const int BRAINMAXSCRIPT = 10;
-
-
-
-enum TraceOper
-{
- TO_STOP = 0, // stop
- TO_ADVANCE = 1, // advance
- TO_RECEDE = 2, // back
- TO_TURN = 3, // rotate
- TO_PEN = 4, // color change
-};
-
-struct TraceRecord
-{
- TraceOper oper;
- float param;
-};
-
-
-
-class CBrain
-{
-public:
- CBrain(CInstanceManager* iMan, CObject* object);
- ~CBrain();
-
- void DeleteObject(bool bAll=false);
-
- void SetPhysics(CPhysics* physics);
- void SetMotion(CMotion* motion);
-
- bool EventProcess(const Event &event);
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
- bool IsBusy();
- void SetActivity(bool bMode);
- bool RetActivity();
- bool IsProgram();
- bool ProgramExist(int rank);
- void RunProgram(int rank);
- int FreeProgram();
- int RetProgram();
- void StopProgram();
- void StopTask();
-
- bool IntroduceVirus();
- void SetActiveVirus(bool bActive);
- bool RetActiveVirus();
-
- void SetScriptRun(int rank);
- int RetScriptRun();
- void SetScriptName(int rank, char *name);
- char* RetScriptName(int rank);
- void SetSoluceName(char *name);
- char* RetSoluceName();
-
- bool ReadSoluce(char* filename);
- bool ReadProgram(int rank, char* filename);
- bool RetCompile(int rank);
- bool WriteProgram(int rank, char* filename);
- bool ReadStack(FILE *file);
- bool WriteStack(FILE *file);
-
- Error StartTaskTake();
- Error StartTaskManip(TaskManipOrder order, TaskManipArm arm);
- Error StartTaskFlag(TaskFlagOrder order, int rank);
- Error StartTaskBuild(ObjectType type);
- Error StartTaskSearch();
- Error StartTaskTerraform();
- Error StartTaskPen(bool bDown, int color);
- Error StartTaskRecover();
- Error StartTaskShield(TaskShieldMode mode);
- Error StartTaskFire(float delay);
- Error StartTaskFireAnt(Math::Vector impact);
- Error StartTaskGunGoal(float dirV, float dirH);
- Error StartTaskReset(Math::Vector goal, Math::Vector angle);
-
- void UpdateInterface(float rTime);
- void UpdateInterface();
-
-protected:
- bool EventFrame(const Event &event);
-
- void StartEditScript(int rank, char* name);
- void StopEditScript(bool bCancel);
-
- Error EndedTask();
-
- void GroundFlat();
- void ColorFlag(int color);
-
- void UpdateScript(CWindow *pw);
- int RetSelScript();
- void BlinkScript(bool bEnable);
-
- void CheckInterface(CWindow *pw, EventMsg event, bool bState);
- void EnableInterface(CWindow *pw, EventMsg event, bool bState);
- void DeadInterface(CWindow *pw, EventMsg event, bool bState);
- void DefaultEnter(CWindow *pw, EventMsg event, bool bState=true);
-
- void TraceRecordStart();
- void TraceRecordFrame();
- void TraceRecordStop();
- bool TraceRecordOper(TraceOper oper, float param);
- bool TraceRecordPut(char *buffer, int max, TraceOper oper, float param);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CTerrain* m_terrain;
- CWater* m_water;
- CCamera* m_camera;
- CObject* m_object;
- CPhysics* m_physics;
- CMotion* m_motion;
- CInterface* m_interface;
- CDisplayText* m_displayText;
- CRobotMain* m_main;
- CStudio* m_studio;
- CSound* m_sound;
- CParticule* m_particule;
- CTaskManager* m_primaryTask;
- CTaskManager* m_secondaryTask;
-
- CScript* m_script[BRAINMAXSCRIPT];
- int m_selScript; // rank of the selected script
- int m_program; // rank of the executed program / ​​-1
- bool m_bActivity;
- bool m_bBurn;
- bool m_bActiveVirus;
-
- int m_scriptRun;
- char m_scriptName[BRAINMAXSCRIPT][50];
- char m_soluceName[50];
-
- EventMsg m_buttonAxe;
- EventMsg m_manipStyle;
- EventMsg m_defaultEnter;
- EventMsg m_interfaceEvent[100];
-
- CObject* m_antTarget;
- CObject* m_beeBullet;
- float m_beeBulletSpeed;
- Math::Vector m_startPos;
- float m_time;
- float m_burnTime;
- float m_lastUpdateTime;
- float m_lastHumanTime;
- float m_lastSpiderTime;
- float m_lastWormTime;
- float m_lastBulletTime;
- float m_lastAlarmTime;
- int m_soundChannelAlarm;
- int m_flagColor;
-
- bool m_bTraceRecord;
- TraceOper m_traceOper;
- Math::Vector m_tracePos;
- float m_traceAngle;
- int m_traceColor;
- int m_traceRecordIndex;
- TraceRecord* m_traceRecordBuffer;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// brain.h
+
+#pragma once
+
+
+#include <stdio.h>
+
+#include "common/misc.h"
+#include "common/event.h"
+#include "object/object.h"
+#include "object/task/taskmanip.h"
+#include "object/task/taskflag.h"
+#include "object/task/taskshield.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CTerrain;
+class CWater;
+class CCamera;
+class CObject;
+class CPhysics;
+class CMotion;
+class CTaskManager;
+class CInterface;
+class CWindow;
+class CDisplayText;
+class CScript;
+class CRobotMain;
+class CStudio;
+class CSound;
+class CParticule;
+
+
+const int BRAINMAXSCRIPT = 10;
+
+
+
+enum TraceOper
+{
+ TO_STOP = 0, // stop
+ TO_ADVANCE = 1, // advance
+ TO_RECEDE = 2, // back
+ TO_TURN = 3, // rotate
+ TO_PEN = 4, // color change
+};
+
+struct TraceRecord
+{
+ TraceOper oper;
+ float param;
+};
+
+
+
+class CBrain
+{
+public:
+ CBrain(CInstanceManager* iMan, CObject* object);
+ ~CBrain();
+
+ void DeleteObject(bool bAll=false);
+
+ void SetPhysics(CPhysics* physics);
+ void SetMotion(CMotion* motion);
+
+ bool EventProcess(const Event &event);
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+ bool IsBusy();
+ void SetActivity(bool bMode);
+ bool RetActivity();
+ bool IsProgram();
+ bool ProgramExist(int rank);
+ void RunProgram(int rank);
+ int FreeProgram();
+ int RetProgram();
+ void StopProgram();
+ void StopTask();
+
+ bool IntroduceVirus();
+ void SetActiveVirus(bool bActive);
+ bool RetActiveVirus();
+
+ void SetScriptRun(int rank);
+ int RetScriptRun();
+ void SetScriptName(int rank, char *name);
+ char* RetScriptName(int rank);
+ void SetSoluceName(char *name);
+ char* RetSoluceName();
+
+ bool ReadSoluce(char* filename);
+ bool ReadProgram(int rank, char* filename);
+ bool RetCompile(int rank);
+ bool WriteProgram(int rank, char* filename);
+ bool ReadStack(FILE *file);
+ bool WriteStack(FILE *file);
+
+ Error StartTaskTake();
+ Error StartTaskManip(TaskManipOrder order, TaskManipArm arm);
+ Error StartTaskFlag(TaskFlagOrder order, int rank);
+ Error StartTaskBuild(ObjectType type);
+ Error StartTaskSearch();
+ Error StartTaskTerraform();
+ Error StartTaskPen(bool bDown, int color);
+ Error StartTaskRecover();
+ Error StartTaskShield(TaskShieldMode mode);
+ Error StartTaskFire(float delay);
+ Error StartTaskFireAnt(Math::Vector impact);
+ Error StartTaskGunGoal(float dirV, float dirH);
+ Error StartTaskReset(Math::Vector goal, Math::Vector angle);
+
+ void UpdateInterface(float rTime);
+ void UpdateInterface();
+
+protected:
+ bool EventFrame(const Event &event);
+
+ void StartEditScript(int rank, char* name);
+ void StopEditScript(bool bCancel);
+
+ Error EndedTask();
+
+ void GroundFlat();
+ void ColorFlag(int color);
+
+ void UpdateScript(CWindow *pw);
+ int RetSelScript();
+ void BlinkScript(bool bEnable);
+
+ void CheckInterface(CWindow *pw, EventMsg event, bool bState);
+ void EnableInterface(CWindow *pw, EventMsg event, bool bState);
+ void DeadInterface(CWindow *pw, EventMsg event, bool bState);
+ void DefaultEnter(CWindow *pw, EventMsg event, bool bState=true);
+
+ void TraceRecordStart();
+ void TraceRecordFrame();
+ void TraceRecordStop();
+ bool TraceRecordOper(TraceOper oper, float param);
+ bool TraceRecordPut(char *buffer, int max, TraceOper oper, float param);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CCamera* m_camera;
+ CObject* m_object;
+ CPhysics* m_physics;
+ CMotion* m_motion;
+ CInterface* m_interface;
+ CDisplayText* m_displayText;
+ CRobotMain* m_main;
+ CStudio* m_studio;
+ CSound* m_sound;
+ CParticule* m_particule;
+ CTaskManager* m_primaryTask;
+ CTaskManager* m_secondaryTask;
+
+ CScript* m_script[BRAINMAXSCRIPT];
+ int m_selScript; // rank of the selected script
+ int m_program; // rank of the executed program / ​​-1
+ bool m_bActivity;
+ bool m_bBurn;
+ bool m_bActiveVirus;
+
+ int m_scriptRun;
+ char m_scriptName[BRAINMAXSCRIPT][50];
+ char m_soluceName[50];
+
+ EventMsg m_buttonAxe;
+ EventMsg m_manipStyle;
+ EventMsg m_defaultEnter;
+ EventMsg m_interfaceEvent[100];
+
+ CObject* m_antTarget;
+ CObject* m_beeBullet;
+ float m_beeBulletSpeed;
+ Math::Vector m_startPos;
+ float m_time;
+ float m_burnTime;
+ float m_lastUpdateTime;
+ float m_lastHumanTime;
+ float m_lastSpiderTime;
+ float m_lastWormTime;
+ float m_lastBulletTime;
+ float m_lastAlarmTime;
+ int m_soundChannelAlarm;
+ int m_flagColor;
+
+ bool m_bTraceRecord;
+ TraceOper m_traceOper;
+ Math::Vector m_tracePos;
+ float m_traceAngle;
+ int m_traceColor;
+ int m_traceRecordIndex;
+ TraceRecord* m_traceRecordBuffer;
+};
+
diff --git a/src/object/mainmovie.cpp b/src/object/mainmovie.cpp
index 082027d..7049842 100644
--- a/src/object/mainmovie.cpp
+++ b/src/object/mainmovie.cpp
@@ -1,238 +1,238 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// mainmovie.cpp
-
-
-#include <stdio.h>
-
-
-#include "object/mainmovie.h"
-
-#include "math/geometry.h"
-#include "common/iman.h"
-#include "object/motion/motionhuman.h"
-#include "object/robotmain.h"
-
-
-
-
-// Constructor of the application card.
-
-CMainMovie::CMainMovie(CInstanceManager* iMan)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_SHORT, this);
-
- m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
- m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
-
- Flush();
-}
-
-// Destructor of the application card.
-
-CMainMovie::~CMainMovie()
-{
-}
-
-
-// Stops the current movie.
-
-void CMainMovie::Flush()
-{
- m_type = MM_NONE;
-}
-
-
-// Start of a film.
-
-bool CMainMovie::Start(MainMovieType type, float time)
-{
- Math::Matrix* mat;
- Math::Vector pos;
- CObject* pObj;
- CMotion* motion;
-
- m_type = type;
- m_speed = 1.0f/time;
- m_progress = 0.0f;
-
- if ( m_type == MM_SATCOMopen )
- {
- pObj = m_main->SearchHuman();
- if ( pObj == 0 )
- {
- m_type = MM_NONE; // it's over!
- return true;
- }
-
- motion = pObj->RetMotion();
- if ( motion != 0 )
- {
- motion->SetAction(MHS_SATCOM, 0.5f); // reads the SatCom
- }
-
- m_camera->RetCamera(m_initialEye, m_initialLookat);
- m_camera->SetType(CAMERA_SCRIPT);
- m_camera->SetSmooth(CS_HARD);
- m_camera->SetScriptEye(m_initialEye);
- m_camera->SetScriptLookat(m_initialLookat);
- m_camera->FixCamera();
-
- mat = pObj->RetWorldMatrix(0);
- m_finalLookat[0] = Math::Transform(*mat, Math::Vector( 1.6f, 1.0f, 1.2f));
- m_finalEye[0] = Math::Transform(*mat, Math::Vector(-1.5f, 5.0f, 3.0f));
- m_finalLookat[1] = Math::Transform(*mat, Math::Vector( 1.6f, 1.0f, 1.2f));
- m_finalEye[1] = Math::Transform(*mat, Math::Vector( 0.8f, 3.0f, 0.8f));
- }
-
- if ( m_type == MM_SATCOMclose )
- {
- pObj = m_main->SearchHuman();
- if ( pObj != 0 )
- {
- motion = pObj->RetMotion();
- if ( motion != 0 )
- {
- motion->SetAction(-1); // finishes reading SatCom
- }
- }
-
- m_camera->SetType(CAMERA_BACK);
- m_type = MM_NONE; // it's already over!
- }
-
- return true;
-}
-
-// Stop a current movie.
-
-bool CMainMovie::Stop()
-{
- CObject* pObj;
- CMotion* motion;
-
- if ( m_type == MM_SATCOMopen )
- {
- pObj = m_main->SearchHuman();
- if ( pObj != 0 )
- {
- motion = pObj->RetMotion();
- if ( motion != 0 )
- {
- motion->SetAction(-1); // finishes reading SatCom
- }
- }
- }
-
- m_type = MM_NONE;
- return true;
-}
-
-// Indicates whether a film is in progress.
-
-bool CMainMovie::IsExist()
-{
- return (m_type != MM_NONE);
-}
-
-
-// Processing an event.
-
-bool CMainMovie::EventProcess(const Event &event)
-{
- Math::Vector initialEye, initialLookat, finalEye, finalLookat, eye, lookat;
- float progress;
-
- if ( m_type == MM_NONE ) return true;
-
- m_progress += event.rTime*m_speed;
-
- if ( m_type == MM_SATCOMopen )
- {
- if ( m_progress < 1.0f )
- {
- progress = 1.0f-powf(1.0f-m_progress, 3.0f);
-
- if ( progress < 0.6f )
- {
- progress = progress/0.6f;
- initialEye = m_initialEye;
- initialLookat = m_initialLookat;
- finalEye = m_finalEye[0];
- finalLookat = m_finalLookat[0];
- }
- else
- {
- progress = (progress-0.6f)/0.3f;
- initialEye = m_finalEye[0];
- initialLookat = m_finalLookat[0];
- finalEye = m_finalEye[1];
- finalLookat = m_finalLookat[1];
- }
- if ( progress > 1.0f ) progress = 1.0f;
-
- eye = (finalEye-initialEye)*progress+initialEye;
- lookat = (finalLookat-initialLookat)*progress+initialLookat;
- m_camera->SetScriptEye(eye);
- m_camera->SetScriptLookat(lookat);
-// m_camera->FixCamera();
- }
- else
- {
- m_stopType = m_type;
- Flush();
- return false;
- }
- }
-
- if ( m_type == MM_SATCOMclose )
- {
- if ( m_progress < 1.0f )
- {
- }
- else
- {
- m_stopType = m_type;
- Flush();
- return false;
- }
- }
-
- return true;
-}
-
-
-// Returns the type of the current movie.
-
-MainMovieType CMainMovie::RetType()
-{
- return m_type;
-}
-
-// Returns the type of movie stop.
-
-MainMovieType CMainMovie::RetStopType()
-{
- return m_stopType;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// mainmovie.cpp
+
+
+#include <stdio.h>
+
+
+#include "object/mainmovie.h"
+
+#include "math/geometry.h"
+#include "common/iman.h"
+#include "object/motion/motionhuman.h"
+#include "object/robotmain.h"
+
+
+
+
+// Constructor of the application card.
+
+CMainMovie::CMainMovie(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_SHORT, this);
+
+ m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+ m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+
+ Flush();
+}
+
+// Destructor of the application card.
+
+CMainMovie::~CMainMovie()
+{
+}
+
+
+// Stops the current movie.
+
+void CMainMovie::Flush()
+{
+ m_type = MM_NONE;
+}
+
+
+// Start of a film.
+
+bool CMainMovie::Start(MainMovieType type, float time)
+{
+ Math::Matrix* mat;
+ Math::Vector pos;
+ CObject* pObj;
+ CMotion* motion;
+
+ m_type = type;
+ m_speed = 1.0f/time;
+ m_progress = 0.0f;
+
+ if ( m_type == MM_SATCOMopen )
+ {
+ pObj = m_main->SearchHuman();
+ if ( pObj == 0 )
+ {
+ m_type = MM_NONE; // it's over!
+ return true;
+ }
+
+ motion = pObj->RetMotion();
+ if ( motion != 0 )
+ {
+ motion->SetAction(MHS_SATCOM, 0.5f); // reads the SatCom
+ }
+
+ m_camera->RetCamera(m_initialEye, m_initialLookat);
+ m_camera->SetType(CAMERA_SCRIPT);
+ m_camera->SetSmooth(CS_HARD);
+ m_camera->SetScriptEye(m_initialEye);
+ m_camera->SetScriptLookat(m_initialLookat);
+ m_camera->FixCamera();
+
+ mat = pObj->RetWorldMatrix(0);
+ m_finalLookat[0] = Math::Transform(*mat, Math::Vector( 1.6f, 1.0f, 1.2f));
+ m_finalEye[0] = Math::Transform(*mat, Math::Vector(-1.5f, 5.0f, 3.0f));
+ m_finalLookat[1] = Math::Transform(*mat, Math::Vector( 1.6f, 1.0f, 1.2f));
+ m_finalEye[1] = Math::Transform(*mat, Math::Vector( 0.8f, 3.0f, 0.8f));
+ }
+
+ if ( m_type == MM_SATCOMclose )
+ {
+ pObj = m_main->SearchHuman();
+ if ( pObj != 0 )
+ {
+ motion = pObj->RetMotion();
+ if ( motion != 0 )
+ {
+ motion->SetAction(-1); // finishes reading SatCom
+ }
+ }
+
+ m_camera->SetType(CAMERA_BACK);
+ m_type = MM_NONE; // it's already over!
+ }
+
+ return true;
+}
+
+// Stop a current movie.
+
+bool CMainMovie::Stop()
+{
+ CObject* pObj;
+ CMotion* motion;
+
+ if ( m_type == MM_SATCOMopen )
+ {
+ pObj = m_main->SearchHuman();
+ if ( pObj != 0 )
+ {
+ motion = pObj->RetMotion();
+ if ( motion != 0 )
+ {
+ motion->SetAction(-1); // finishes reading SatCom
+ }
+ }
+ }
+
+ m_type = MM_NONE;
+ return true;
+}
+
+// Indicates whether a film is in progress.
+
+bool CMainMovie::IsExist()
+{
+ return (m_type != MM_NONE);
+}
+
+
+// Processing an event.
+
+bool CMainMovie::EventProcess(const Event &event)
+{
+ Math::Vector initialEye, initialLookat, finalEye, finalLookat, eye, lookat;
+ float progress;
+
+ if ( m_type == MM_NONE ) return true;
+
+ m_progress += event.rTime*m_speed;
+
+ if ( m_type == MM_SATCOMopen )
+ {
+ if ( m_progress < 1.0f )
+ {
+ progress = 1.0f-powf(1.0f-m_progress, 3.0f);
+
+ if ( progress < 0.6f )
+ {
+ progress = progress/0.6f;
+ initialEye = m_initialEye;
+ initialLookat = m_initialLookat;
+ finalEye = m_finalEye[0];
+ finalLookat = m_finalLookat[0];
+ }
+ else
+ {
+ progress = (progress-0.6f)/0.3f;
+ initialEye = m_finalEye[0];
+ initialLookat = m_finalLookat[0];
+ finalEye = m_finalEye[1];
+ finalLookat = m_finalLookat[1];
+ }
+ if ( progress > 1.0f ) progress = 1.0f;
+
+ eye = (finalEye-initialEye)*progress+initialEye;
+ lookat = (finalLookat-initialLookat)*progress+initialLookat;
+ m_camera->SetScriptEye(eye);
+ m_camera->SetScriptLookat(lookat);
+// m_camera->FixCamera();
+ }
+ else
+ {
+ m_stopType = m_type;
+ Flush();
+ return false;
+ }
+ }
+
+ if ( m_type == MM_SATCOMclose )
+ {
+ if ( m_progress < 1.0f )
+ {
+ }
+ else
+ {
+ m_stopType = m_type;
+ Flush();
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+// Returns the type of the current movie.
+
+MainMovieType CMainMovie::RetType()
+{
+ return m_type;
+}
+
+// Returns the type of movie stop.
+
+MainMovieType CMainMovie::RetStopType()
+{
+ return m_stopType;
+}
+
+
diff --git a/src/object/mainmovie.h b/src/object/mainmovie.h
index 3d4f375..23721fb 100644
--- a/src/object/mainmovie.h
+++ b/src/object/mainmovie.h
@@ -1,80 +1,80 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// mainmovie.h
-
-#pragma once
-
-
-#include "common/event.h"
-#include "math/vector.h"
-
-
-class CInstanceManager;
-class CEvent;
-class CD3DEngine;
-class CInterface;
-class CRobotMain;
-class CCamera;
-class CSound;
-
-
-
-
-enum MainMovieType
-{
- MM_NONE,
- MM_SATCOMopen,
- MM_SATCOMclose,
-};
-
-
-
-class CMainMovie
-{
-public:
- CMainMovie(CInstanceManager* iMan);
- ~CMainMovie();
-
- void Flush();
- bool Start(MainMovieType type, float time);
- bool Stop();
- bool IsExist();
- bool EventProcess(const Event &event);
- MainMovieType RetType();
- MainMovieType RetStopType();
-
-protected:
-
-protected:
- CInstanceManager* m_iMan;
- CEvent* m_event;
- CD3DEngine* m_engine;
- CInterface* m_interface;
- CRobotMain* m_main;
- CCamera* m_camera;
- CSound* m_sound;
-
- MainMovieType m_type;
- MainMovieType m_stopType;
- float m_speed;
- float m_progress;
- Math::Vector m_initialEye;
- Math::Vector m_initialLookat;
- Math::Vector m_finalEye[2];
- Math::Vector m_finalLookat[2];
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// mainmovie.h
+
+#pragma once
+
+
+#include "common/event.h"
+#include "math/vector.h"
+
+
+class CInstanceManager;
+class CEvent;
+class CD3DEngine;
+class CInterface;
+class CRobotMain;
+class CCamera;
+class CSound;
+
+
+
+
+enum MainMovieType
+{
+ MM_NONE,
+ MM_SATCOMopen,
+ MM_SATCOMclose,
+};
+
+
+
+class CMainMovie
+{
+public:
+ CMainMovie(CInstanceManager* iMan);
+ ~CMainMovie();
+
+ void Flush();
+ bool Start(MainMovieType type, float time);
+ bool Stop();
+ bool IsExist();
+ bool EventProcess(const Event &event);
+ MainMovieType RetType();
+ MainMovieType RetStopType();
+
+protected:
+
+protected:
+ CInstanceManager* m_iMan;
+ CEvent* m_event;
+ CD3DEngine* m_engine;
+ CInterface* m_interface;
+ CRobotMain* m_main;
+ CCamera* m_camera;
+ CSound* m_sound;
+
+ MainMovieType m_type;
+ MainMovieType m_stopType;
+ float m_speed;
+ float m_progress;
+ Math::Vector m_initialEye;
+ Math::Vector m_initialLookat;
+ Math::Vector m_finalEye[2];
+ Math::Vector m_finalLookat[2];
+};
+
diff --git a/src/object/motion/motion.cpp b/src/object/motion/motion.cpp
index 3231f7a..5ffa63c 100644
--- a/src/object/motion/motion.cpp
+++ b/src/object/motion/motion.cpp
@@ -1,239 +1,239 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motion.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motion.h"
-
-#include "common/iman.h"
-#include "script/cmdtoken.h"
-
-
-
-
-// Object's constructor.
-
-CMotion::CMotion(CInstanceManager* iMan, CObject* object)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_MOTION, this, 100);
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
-
- m_object = object;
- m_physics = 0;
- m_brain = 0;
-
- m_actionType = -1;
- m_actionTime = 0.0f;
- m_progress = 0.0f;
-
- m_linVibration = Math::Vector(0.0f, 0.0f, 0.0f);
- m_cirVibration = Math::Vector(0.0f, 0.0f, 0.0f);
- m_inclinaison = Math::Vector(0.0f, 0.0f, 0.0f);
-}
-
-// Object's destructor.
-
-CMotion::~CMotion()
-{
- m_iMan->DeleteInstance(CLASS_MOTION, this);
-}
-
-// Deletes the object.
-
-void CMotion::DeleteObject(bool bAll)
-{
-}
-
-
-void CMotion::SetPhysics(CPhysics* physics)
-{
- m_physics = physics;
-}
-
-void CMotion::SetBrain(CBrain* brain)
-{
- m_brain = brain;
-}
-
-
-// Creates.
-
-bool CMotion::Create(Math::Vector pos, float angle, ObjectType type, float power)
-{
- return true;
-}
-
-// Management of an event.
-
-bool CMotion::EventProcess(const Event &event)
-{
- Math::Vector pos, dir;
- float time;
-
- if ( m_object->RetType() != OBJECT_TOTO &&
- m_engine->RetPause() ) return true;
-
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_actionTime;
- if ( m_progress > 1.0f ) m_progress = 1.0f; // (*)
-
- pos = m_object->RetPosition(0);
- if ( pos.y < m_water->RetLevel(m_object) ) // underwater?
- {
- time = event.rTime*3.0f; // everything is slower
- }
- else
- {
- time = event.rTime*10.0f;
- }
-
- dir = m_object->RetLinVibration();
- dir.x = Math::Smooth(dir.x, m_linVibration.x, time);
- dir.y = Math::Smooth(dir.y, m_linVibration.y, time);
- dir.z = Math::Smooth(dir.z, m_linVibration.z, time);
- m_object->SetLinVibration(dir);
-
- dir = m_object->RetCirVibration();
- dir.x = Math::Smooth(dir.x, m_cirVibration.x, time);
- dir.y = Math::Smooth(dir.y, m_cirVibration.y, time);
- dir.z = Math::Smooth(dir.z, m_cirVibration.z, time);
- m_object->SetCirVibration(dir);
-
- dir = m_object->RetInclinaison();
- dir.x = Math::Smooth(dir.x, m_inclinaison.x, time);
- dir.y = Math::Smooth(dir.y, m_inclinaison.y, time);
- dir.z = Math::Smooth(dir.z, m_inclinaison.z, time);
- m_object->SetInclinaison(dir);
-
- return true;
-}
-
-// (*) Avoids the bug of ants returned by the thumper and
-// whose abdomen grown to infinity!
-
-
-// Start an action.
-
-Error CMotion::SetAction(int action, float time)
-{
- m_actionType = action;
- m_actionTime = 1.0f/time;
- m_progress = 0.0f;
- return ERR_OK;
-}
-
-// Returns the current action.
-
-int CMotion::RetAction()
-{
- return m_actionType;
-}
-
-
-// Specifies a special parameter.
-
-bool CMotion::SetParam(int rank, float value)
-{
- return false;
-}
-
-float CMotion::RetParam(int rank)
-{
- return 0.0f;
-}
-
-
-// Saves all parameters of the object.
-
-bool CMotion::Write(char *line)
-{
- char name[100];
-
- if ( m_actionType == -1 ) return false;
-
- sprintf(name, " mType=%d", m_actionType);
- strcat(line, name);
-
- sprintf(name, " mTime=%.2f", m_actionTime);
- strcat(line, name);
-
- sprintf(name, " mProgress=%.2f", m_progress);
- strcat(line, name);
-
- return false;
-}
-
-// Restores all parameters of the object.
-
-bool CMotion::Read(char *line)
-{
- m_actionType = OpInt(line, "mType", -1);
- m_actionTime = OpFloat(line, "mTime", 0.0f);
- m_progress = OpFloat(line, "mProgress", 0.0f);
-
- return false;
-}
-
-
-// Gives the linear vibration.
-
-void CMotion::SetLinVibration(Math::Vector dir)
-{
- m_linVibration = dir;
-}
-
-Math::Vector CMotion::RetLinVibration()
-{
- return m_linVibration;
-}
-
-// Gives the circular vibration.
-
-void CMotion::SetCirVibration(Math::Vector dir)
-{
- m_cirVibration = dir;
-}
-
-Math::Vector CMotion::RetCirVibration()
-{
- return m_cirVibration;
-}
-
-// Gives the tilt.
-
-void CMotion::SetInclinaison(Math::Vector dir)
-{
- m_inclinaison = dir;
-}
-
-Math::Vector CMotion::RetInclinaison()
-{
- return m_inclinaison;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motion.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motion.h"
+
+#include "common/iman.h"
+#include "script/cmdtoken.h"
+
+
+
+
+// Object's constructor.
+
+CMotion::CMotion(CInstanceManager* iMan, CObject* object)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_MOTION, this, 100);
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+
+ m_object = object;
+ m_physics = 0;
+ m_brain = 0;
+
+ m_actionType = -1;
+ m_actionTime = 0.0f;
+ m_progress = 0.0f;
+
+ m_linVibration = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_cirVibration = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_inclinaison = Math::Vector(0.0f, 0.0f, 0.0f);
+}
+
+// Object's destructor.
+
+CMotion::~CMotion()
+{
+ m_iMan->DeleteInstance(CLASS_MOTION, this);
+}
+
+// Deletes the object.
+
+void CMotion::DeleteObject(bool bAll)
+{
+}
+
+
+void CMotion::SetPhysics(CPhysics* physics)
+{
+ m_physics = physics;
+}
+
+void CMotion::SetBrain(CBrain* brain)
+{
+ m_brain = brain;
+}
+
+
+// Creates.
+
+bool CMotion::Create(Math::Vector pos, float angle, ObjectType type, float power)
+{
+ return true;
+}
+
+// Management of an event.
+
+bool CMotion::EventProcess(const Event &event)
+{
+ Math::Vector pos, dir;
+ float time;
+
+ if ( m_object->RetType() != OBJECT_TOTO &&
+ m_engine->RetPause() ) return true;
+
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_actionTime;
+ if ( m_progress > 1.0f ) m_progress = 1.0f; // (*)
+
+ pos = m_object->RetPosition(0);
+ if ( pos.y < m_water->RetLevel(m_object) ) // underwater?
+ {
+ time = event.rTime*3.0f; // everything is slower
+ }
+ else
+ {
+ time = event.rTime*10.0f;
+ }
+
+ dir = m_object->RetLinVibration();
+ dir.x = Math::Smooth(dir.x, m_linVibration.x, time);
+ dir.y = Math::Smooth(dir.y, m_linVibration.y, time);
+ dir.z = Math::Smooth(dir.z, m_linVibration.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir = m_object->RetCirVibration();
+ dir.x = Math::Smooth(dir.x, m_cirVibration.x, time);
+ dir.y = Math::Smooth(dir.y, m_cirVibration.y, time);
+ dir.z = Math::Smooth(dir.z, m_cirVibration.z, time);
+ m_object->SetCirVibration(dir);
+
+ dir = m_object->RetInclinaison();
+ dir.x = Math::Smooth(dir.x, m_inclinaison.x, time);
+ dir.y = Math::Smooth(dir.y, m_inclinaison.y, time);
+ dir.z = Math::Smooth(dir.z, m_inclinaison.z, time);
+ m_object->SetInclinaison(dir);
+
+ return true;
+}
+
+// (*) Avoids the bug of ants returned by the thumper and
+// whose abdomen grown to infinity!
+
+
+// Start an action.
+
+Error CMotion::SetAction(int action, float time)
+{
+ m_actionType = action;
+ m_actionTime = 1.0f/time;
+ m_progress = 0.0f;
+ return ERR_OK;
+}
+
+// Returns the current action.
+
+int CMotion::RetAction()
+{
+ return m_actionType;
+}
+
+
+// Specifies a special parameter.
+
+bool CMotion::SetParam(int rank, float value)
+{
+ return false;
+}
+
+float CMotion::RetParam(int rank)
+{
+ return 0.0f;
+}
+
+
+// Saves all parameters of the object.
+
+bool CMotion::Write(char *line)
+{
+ char name[100];
+
+ if ( m_actionType == -1 ) return false;
+
+ sprintf(name, " mType=%d", m_actionType);
+ strcat(line, name);
+
+ sprintf(name, " mTime=%.2f", m_actionTime);
+ strcat(line, name);
+
+ sprintf(name, " mProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ return false;
+}
+
+// Restores all parameters of the object.
+
+bool CMotion::Read(char *line)
+{
+ m_actionType = OpInt(line, "mType", -1);
+ m_actionTime = OpFloat(line, "mTime", 0.0f);
+ m_progress = OpFloat(line, "mProgress", 0.0f);
+
+ return false;
+}
+
+
+// Gives the linear vibration.
+
+void CMotion::SetLinVibration(Math::Vector dir)
+{
+ m_linVibration = dir;
+}
+
+Math::Vector CMotion::RetLinVibration()
+{
+ return m_linVibration;
+}
+
+// Gives the circular vibration.
+
+void CMotion::SetCirVibration(Math::Vector dir)
+{
+ m_cirVibration = dir;
+}
+
+Math::Vector CMotion::RetCirVibration()
+{
+ return m_cirVibration;
+}
+
+// Gives the tilt.
+
+void CMotion::SetInclinaison(Math::Vector dir)
+{
+ m_inclinaison = dir;
+}
+
+Math::Vector CMotion::RetInclinaison()
+{
+ return m_inclinaison;
+}
+
diff --git a/src/object/motion/motion.h b/src/object/motion/motion.h
index bdb9ce0..9828283 100644
--- a/src/object/motion/motion.h
+++ b/src/object/motion/motion.h
@@ -1,93 +1,93 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motion.h
-
-#pragma once
-
-
-#include "common/event.h"
-#include "common/misc.h"
-#include "object/object.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CLight;
-class CParticule;
-class CTerrain;
-class CWater;
-class CCamera;
-class CBrain;
-class CPhysics;
-class CObject;
-class CRobotMain;
-class CSound;
-
-
-class CMotion
-{
-public:
- CMotion(CInstanceManager* iMan, CObject* object);
- virtual ~CMotion();
-
- void SetPhysics(CPhysics* physics);
- void SetBrain(CBrain* brain);
-
- virtual void DeleteObject(bool bAll=false);
- virtual bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- virtual bool EventProcess(const Event &event);
- virtual Error SetAction(int action, float time=0.2f);
- virtual int RetAction();
-
- virtual bool SetParam(int rank, float value);
- virtual float RetParam(int rank);
-
- virtual bool Write(char *line);
- virtual bool Read(char *line);
-
- virtual void SetLinVibration(Math::Vector dir);
- virtual Math::Vector RetLinVibration();
- virtual void SetCirVibration(Math::Vector dir);
- virtual Math::Vector RetCirVibration();
- virtual void SetInclinaison(Math::Vector dir);
- virtual Math::Vector RetInclinaison();
-
-protected:
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CLight* m_light;
- CParticule* m_particule;
- CTerrain* m_terrain;
- CWater* m_water;
- CCamera* m_camera;
- CObject* m_object;
- CBrain* m_brain;
- CPhysics* m_physics;
- CRobotMain* m_main;
- CSound* m_sound;
-
- int m_actionType;
- float m_actionTime;
- float m_progress;
-
- Math::Vector m_linVibration; // linear vibration
- Math::Vector m_cirVibration; // circular vibration
- Math::Vector m_inclinaison; // tilt
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motion.h
+
+#pragma once
+
+
+#include "common/event.h"
+#include "common/misc.h"
+#include "object/object.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CLight;
+class CParticule;
+class CTerrain;
+class CWater;
+class CCamera;
+class CBrain;
+class CPhysics;
+class CObject;
+class CRobotMain;
+class CSound;
+
+
+class CMotion
+{
+public:
+ CMotion(CInstanceManager* iMan, CObject* object);
+ virtual ~CMotion();
+
+ void SetPhysics(CPhysics* physics);
+ void SetBrain(CBrain* brain);
+
+ virtual void DeleteObject(bool bAll=false);
+ virtual bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ virtual bool EventProcess(const Event &event);
+ virtual Error SetAction(int action, float time=0.2f);
+ virtual int RetAction();
+
+ virtual bool SetParam(int rank, float value);
+ virtual float RetParam(int rank);
+
+ virtual bool Write(char *line);
+ virtual bool Read(char *line);
+
+ virtual void SetLinVibration(Math::Vector dir);
+ virtual Math::Vector RetLinVibration();
+ virtual void SetCirVibration(Math::Vector dir);
+ virtual Math::Vector RetCirVibration();
+ virtual void SetInclinaison(Math::Vector dir);
+ virtual Math::Vector RetInclinaison();
+
+protected:
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CLight* m_light;
+ CParticule* m_particule;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CCamera* m_camera;
+ CObject* m_object;
+ CBrain* m_brain;
+ CPhysics* m_physics;
+ CRobotMain* m_main;
+ CSound* m_sound;
+
+ int m_actionType;
+ float m_actionTime;
+ float m_progress;
+
+ Math::Vector m_linVibration; // linear vibration
+ Math::Vector m_cirVibration; // circular vibration
+ Math::Vector m_inclinaison; // tilt
+};
+
diff --git a/src/object/motion/motionant.cpp b/src/object/motion/motionant.cpp
index c85a631..c6a9357 100644
--- a/src/object/motion/motionant.cpp
+++ b/src/object/motion/motionant.cpp
@@ -1,871 +1,871 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionant.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motionant.h"
-
-#include "old/modfile.h"
-#include "old/particule.h"
-#include "physics/physics.h"
-
-
-
-#define ADJUST_ANGLE false // true -> adjusts the angles of the members
-const float START_TIME = 1000.0f; // beginning of the relative time
-
-
-
-// Object's constructor.
-
-CMotionAnt::CMotionAnt(CInstanceManager* iMan, CObject* object)
- : CMotion(iMan, object)
-{
- m_armMember = START_TIME;
- m_armTimeAbs = START_TIME;
- m_armTimeMarch = START_TIME;
- m_armTimeAction = START_TIME;
- m_armTimeIndex = 0;
- m_armPartIndex = 0;
- m_armMemberIndex = 0;
- m_armLastAction = -1;
- m_bArmStop = false;
- m_lastParticule = 0.0f;
-}
-
-// Object's destructor.
-
-CMotionAnt::~CMotionAnt()
-{
-}
-
-
-// Removes an object.
-
-void CMotionAnt::DeleteObject(bool bAll)
-{
-}
-
-
-// Creates a vehicle poses some rolling on the floor.
-
-bool CMotionAnt::Create(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 3+18 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- m_object->SetType(type);
-
- // Creates the main base.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
-
- pModFile->ReadModel("objects\\ant1.mod");
- pModFile->CreateEngineObject(rank);
-
- m_object->SetPosition(0, pos);
- m_object->SetAngleY(0, angle);
-
- // A vehicle must have necessarily a collision
- //with a sphere of center (0, y, 0) (see GetCrashSphere).
- m_object->CreateCrashSphere(Math::Vector(0.0f, -2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
- m_object->SetGlobalSphere(Math::Vector(-0.5f, 1.0f, 0.0f), 4.0f);
-
- // Creates the head.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\ant2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(2.0f, 0.0f, 0.0f));
-
- // Creates the tail.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\ant3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(-1.0f, 0.0f, 0.0f));
-
- // Creates a right-back thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(-0.4f, -0.1f, -0.3f));
-
- // Creates a right-back leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(4, rank);
- m_object->SetObjectParent(4, 3);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(4, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates a right-back foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(5, rank);
- m_object->SetObjectParent(5, 4);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(5, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates two middle-right thighs.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(0.1f, -0.1f, -0.4f));
-
- // Creates two middle-right legs.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 6);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates two middle-right foots.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 7);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates the right front thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(9, rank);
- m_object->SetObjectParent(9, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(9, Math::Vector(1.4f, -0.1f, -0.6f));
-
- // Creates the right front leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(10, rank);
- m_object->SetObjectParent(10, 9);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(10, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates the right front foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(11, rank);
- m_object->SetObjectParent(11, 10);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(11, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates a left-back thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(12, rank);
- m_object->SetObjectParent(12, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(12, Math::Vector(-0.4f, -0.1f, 0.3f));
-
- // Creates a left-back leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(13, rank);
- m_object->SetObjectParent(13, 12);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(13, Math::Vector(0.0f, 0.0f, 1.0f));
-
- // Creates a left-back foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(14, rank);
- m_object->SetObjectParent(14, 13);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(14, Math::Vector(0.0f, 0.0f, 2.0f));
-
- // Creates two middle-left thighs.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(15, rank);
- m_object->SetObjectParent(15, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(15, Math::Vector(0.1f, -0.1f, 0.4f));
-
- // Creates two middle-left legs.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(16, rank);
- m_object->SetObjectParent(16, 15);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(16, Math::Vector(0.0f, 0.0f, 1.0f));
-
- // Creates two middle-left foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(17, rank);
- m_object->SetObjectParent(17, 16);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(17, Math::Vector(0.0f, 0.0f, 2.0f));
-
- // Creates the left front thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(18, rank);
- m_object->SetObjectParent(18, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(18, Math::Vector(1.4f, -0.1f, 0.6f));
-
- // Creates the left front leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(19, rank);
- m_object->SetObjectParent(19, 18);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(19, Math::Vector(0.0f, 0.0f, 1.0f));
-
- // Creates the left front foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(20, rank);
- m_object->SetObjectParent(20, 19);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(20, Math::Vector(0.0f, 0.0f, 2.0f));
-
- m_object->CreateShadowCircle(4.0f, 0.5f);
-
- CreatePhysics();
- m_object->SetFloorHeight(0.0f);
-
- pos = m_object->RetPosition(0);
- m_object->SetPosition(0, pos); // to display the shadows immediately
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-// Creates the physics of the object.
-
-void CMotionAnt::CreatePhysics()
-{
- Character* character;
- int i;
-
- int member_march[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
- 0,45,0, 0,45,0, 0,50,0, // t0: thighs 1..3
- 30,-70,0, 20,-105,20, 25,-100,0, // t0: legs 1..3
- -70,75,0, -30,80,0, -80,80,0, // t0: feet 1..3
- // on the ground:
- 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3
- -15,-50,0, -20,-60,0, -10,-75,0, // t1: legs 1..3
- -40,50,0, -25,15,0, -50,35,0, // t1: feet 1..3
- // on the ground back:
- 0,35,0, 0,30,0, 0,20,0, // t2: thighs 1..3
- -20,-15,0, -30,-55,0, -25,-70,15, // t2: legs 1..3
- -25,25,0, -20,60,0, -30,95,0, // t2: feet 1..3
- };
-
- int member_stop[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
- 0,30,0, 0,20,0, 0,15,0, // t0: thighs 1..3
- -15,-35,0, -20,-60,0, -15,-75,0, // t0: legs 1..3
- -35,35,0, -25,40,0, -40,65,0, // t0: feet 1..3
- // on the ground:
- 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3
- -15,-35,0, -20,-60,0, -15,-75,0, // t1: legs 1..3
- -35,35,0, -25,40,0, -40,65,0, // t1: feet 1..3
- // on the ground back:
- 0,30,0, 0,20,0, 0,15,0, // t2: thighs 1..3
- -15,-35,0, -20,-60,0, -15,-75,0, // t2: legs 1..3
- -35,35,0, -25,40,0, -40,65,0, // t2: feet 1..3
- };
-
- int member_spec[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // prepares the fire:
- 0,20,0, 0,10,0, 0,50,0, // s0: thighs 1..3
- -50,-30,0, -20,-15,0, 35,-65,0, // s0: legs 1..3
- -5,-40,0, 20,-70,0, -10,-40,0, // s0: feet 1..3
- // shot:
- 0,20,0, 0,10,0, 0,50,0, // s1: thighs 1..3
- -50,-30,0, -20,-15,0, 35,-65,0, // s1: legs 1..3
- -5,-40,0, 20,-70,0, -10,-40,0, // s1: feet 1..3
- // ends the fire:
- 0,30,0, 0,20,0, 0,15,0, // s2: thighs 1..3
- -15,-50,0, -20,-60,0, -10,-75,0, // s2: legs 1..3
- -40,50,0, -25,15,0, -50,35,0, // s2: feet 1..3
- // burning:
- 0,30,0, 0,20,0, 0,15,0, // s3: thighs 1..3
- -15,-35,0, -20,-60,0, -15,-75,0, // s3: legs 1..3
- -35,35,0, -25,40,0, -40,65,0, // s3: feet 1..3
- // destroyed:
- 0,30,0, 0,20,0, 0,15,0, // s4: thighs 1..3
- -15,-35,0, -20,-60,0, -15,-75,0, // s4: legs 1..3
- -35,35,0, -25,40,0, -40,65,0, // s4: feet 1..3
- // back1 :
- 0,30,0, 0,20,0, 0,15,0, // s5: thighs 1..3
- -15,-35,0, -20,-60,0, -15,-75,0, // s5: legs 1..3
- -35,35,0, -25,40,0, -40,65,0, // s5: feet 1..3
- // back2 :
- 0,45,0, 0,45,0, 0,50,0, // s6: thighs 1..3
- -35,-70,0, -20,-85,-25, -25,-100,0, // s6: legs 1..3
- -110,75,-15, -130,80,-25, -125,40,0, // s6: feet 1..3
- // back3 :
- 0,30,0, 0,20,0, 0,15,0, // s7: thighs 1..3
- -15,-35,0, -20,-60,0, -15,-75,0, // s7: legs 1..3
- -35,35,0, -25,40,0, -40,65,0, // s7: feet 1..3
- };
-
- m_physics->SetType(TYPE_ROLLING);
-
- character = m_object->RetCharacter();
- character->wheelFront = 3.0f;
- character->wheelBack = 3.0f;
- character->wheelLeft = 5.0f;
- character->wheelRight = 5.0f;
- character->height = 1.2f;
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 12.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 12.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 15.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 10.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 20.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 40.0f);
-
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MA_MARCH+i] = member_march[i];
- }
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MA_STOP+i] = member_stop[i];
- }
- for ( i=0 ; i<3*3*3*8 ; i++ )
- {
- m_armAngles[3*3*3*3*MA_SPEC+i] = member_spec[i];
- }
-}
-
-
-// Management of an event.
-
-bool CMotionAnt::EventProcess(const Event &event)
-{
- CMotion::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
-#if ADJUST_ANGLE
- int i;
-
- if ( event.param == 'A' ) m_armTimeIndex++;
- if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
-
- if ( event.param == 'Q' ) m_armPartIndex++;
- if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
-
- if ( event.param == 'W' ) m_armMemberIndex++;
- if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
-
- i = m_armMemberIndex*3;
- i += m_armPartIndex*3*3;
- i += m_armTimeIndex*3*3*3;
-//? i += 3*3*3*3;
-
- if ( event.param == 'E' ) m_armAngles[i+0] += 5;
- if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
- if ( event.param == 'R' ) m_armAngles[i+1] += 5;
- if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
- if ( event.param == 'T' ) m_armAngles[i+2] += 5;
- if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
-
- if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
-#endif
- }
-
- return true;
-}
-
-// Management of an event.
-
-bool CMotionAnt::EventFrame(const Event &event)
-{
- Math::Vector dir, pos, speed;
- Math::Point dim;
- float s, a, prog, time;
- float tSt[9], tNd[9];
- int i, ii, st, nd, action;
- bool bStop;
-
- if ( m_engine->RetPause() ) return true;
- if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
-
- s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
- a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f);
-
- if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
-
- m_armTimeAbs += event.rTime;
- m_armTimeMarch += (s)*event.rTime*0.15f;
- m_armMember += (s+a)*event.rTime*0.15f;
-
- bStop = ( a == 0.0f && s == 0.0f ); // stopped?
-
- action = MA_MARCH; // walking
- if ( s == 0.0f && a == 0.0f )
- {
- action = MA_STOP; // stop
- }
-
- if ( bStop )
- {
- prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
- a = Math::Mod(m_armMember, 1.0f);
- a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly
- m_armMember += a;
- }
-
- if ( m_object->RetRuin() ) // destroyed?
- {
- m_actionType = MAS_RUIN;
- }
- if ( m_object->RetBurn() ) // burning?
- {
- if ( m_object->RetFixed() )
- {
- m_actionType = MAS_BURN;
- }
- else
- {
- m_actionType = -1;
- }
- }
-
- for ( i=0 ; i<6 ; i++ ) // the six legs
- {
- if ( m_actionType != -1 ) // special action in progress?
- {
- st = 3*3*3*3*MA_SPEC + 3*3*3*m_actionType + (i%3)*3;
- nd = st;
- time = event.rTime*m_actionTime;
- m_armTimeAction = 0.0f;
- }
- else
- {
- if ( i < 3 ) prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
- else prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
- if ( m_bArmStop )
- {
- prog = (float)m_armTimeIndex/3.0f;
- }
- if ( prog < 0.33f ) // t0..t1 ?
- {
- prog = prog/0.33f; // 0..1
- st = 0; // index start
- nd = 1; // index end
- }
- else if ( prog < 0.67f ) // t1..t2 ?
- {
- prog = (prog-0.33f)/0.33f; // 0..1
- st = 1; // index start
- nd = 2; // index end
- }
- else // t2..t0 ?
- {
- prog = (prog-0.67f)/0.33f; // 0..1
- st = 2; // index start
- nd = 0; // index end
- }
- st = 3*3*3*3*action + st*3*3*3 + (i%3)*3;
- nd = 3*3*3*3*action + nd*3*3*3 + (i%3)*3;
-
- // More and more soft ...
- time = event.rTime*(10.0f+Math::Min(m_armTimeAction*100.0f, 200.0f));
- }
-
- tSt[0] = m_armAngles[st+ 0]; // x
- tSt[1] = m_armAngles[st+ 1]; // y
- tSt[2] = m_armAngles[st+ 2]; // z
- tSt[3] = m_armAngles[st+ 9]; // x
- tSt[4] = m_armAngles[st+10]; // y
- tSt[5] = m_armAngles[st+11]; // z
- tSt[6] = m_armAngles[st+18]; // x
- tSt[7] = m_armAngles[st+19]; // y
- tSt[8] = m_armAngles[st+20]; // z
-
- tNd[0] = m_armAngles[nd+ 0]; // x
- tNd[1] = m_armAngles[nd+ 1]; // y
- tNd[2] = m_armAngles[nd+ 2]; // z
- tNd[3] = m_armAngles[nd+ 9]; // x
- tNd[4] = m_armAngles[nd+10]; // y
- tNd[5] = m_armAngles[nd+11]; // z
- tNd[6] = m_armAngles[nd+18]; // x
- tNd[7] = m_armAngles[nd+19]; // y
- tNd[8] = m_armAngles[nd+20]; // z
-
- if ( m_actionType == MAS_BACK2 ) // on the back?
- {
- for ( ii=0 ; ii<9 ; ii++ )
- {
- tSt[ii] += Math::Rand()*50.0f;
- tNd[ii] = tSt[ii];
- }
-//? time = 100.0f;
- time = event.rTime*10.0f;
- }
-
- if ( i < 3 ) // right leg (1..3) ?
- {
- m_object->SetAngleX(3+3*i+0, Math::Smooth(m_object->RetAngleX(3+3*i+0), Math::PropAngle(tSt[0], tNd[0], prog), time));
- m_object->SetAngleY(3+3*i+0, Math::Smooth(m_object->RetAngleY(3+3*i+0), Math::PropAngle(tSt[1], tNd[1], prog), time));
- m_object->SetAngleZ(3+3*i+0, Math::Smooth(m_object->RetAngleZ(3+3*i+0), Math::PropAngle(tSt[2], tNd[2], prog), time));
- m_object->SetAngleX(3+3*i+1, Math::Smooth(m_object->RetAngleX(3+3*i+1), Math::PropAngle(tSt[3], tNd[3], prog), time));
- m_object->SetAngleY(3+3*i+1, Math::Smooth(m_object->RetAngleY(3+3*i+1), Math::PropAngle(tSt[4], tNd[4], prog), time));
- m_object->SetAngleZ(3+3*i+1, Math::Smooth(m_object->RetAngleZ(3+3*i+1), Math::PropAngle(tSt[5], tNd[5], prog), time));
- m_object->SetAngleX(3+3*i+2, Math::Smooth(m_object->RetAngleX(3+3*i+2), Math::PropAngle(tSt[6], tNd[6], prog), time));
- m_object->SetAngleY(3+3*i+2, Math::Smooth(m_object->RetAngleY(3+3*i+2), Math::PropAngle(tSt[7], tNd[7], prog), time));
- m_object->SetAngleZ(3+3*i+2, Math::Smooth(m_object->RetAngleZ(3+3*i+2), Math::PropAngle(tSt[8], tNd[8], prog), time));
- }
- else // left leg (4..6) ?
- {
- m_object->SetAngleX(3+3*i+0, Math::Smooth(m_object->RetAngleX(3+3*i+0), Math::PropAngle(-tSt[0], -tNd[0], prog), time));
- m_object->SetAngleY(3+3*i+0, Math::Smooth(m_object->RetAngleY(3+3*i+0), Math::PropAngle(-tSt[1], -tNd[1], prog), time));
- m_object->SetAngleZ(3+3*i+0, Math::Smooth(m_object->RetAngleZ(3+3*i+0), Math::PropAngle( tSt[2], tNd[2], prog), time));
- m_object->SetAngleX(3+3*i+1, Math::Smooth(m_object->RetAngleX(3+3*i+1), Math::PropAngle(-tSt[3], -tNd[3], prog), time));
- m_object->SetAngleY(3+3*i+1, Math::Smooth(m_object->RetAngleY(3+3*i+1), Math::PropAngle(-tSt[4], -tNd[4], prog), time));
- m_object->SetAngleZ(3+3*i+1, Math::Smooth(m_object->RetAngleZ(3+3*i+1), Math::PropAngle( tSt[5], tNd[5], prog), time));
- m_object->SetAngleX(3+3*i+2, Math::Smooth(m_object->RetAngleX(3+3*i+2), Math::PropAngle(-tSt[6], -tNd[6], prog), time));
- m_object->SetAngleY(3+3*i+2, Math::Smooth(m_object->RetAngleY(3+3*i+2), Math::PropAngle(-tSt[7], -tNd[7], prog), time));
- m_object->SetAngleZ(3+3*i+2, Math::Smooth(m_object->RetAngleZ(3+3*i+2), Math::PropAngle( tSt[8], tNd[8], prog), time));
- }
- }
-
-#if ADJUST_ANGLE
- if ( m_object->RetSelect() )
- {
- char s[100];
- sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
- m_engine->SetInfoText(4, s);
- }
-#endif
-
- if ( m_actionType == MAS_PREPARE ) // prepares the shooting?
- {
- prog = m_progress;
-
- dir.x = 0.0f;
- dir.y = 0.0f;
- dir.z = Math::PropAngle(0, -50, prog);
- SetInclinaison(dir);
- m_object->SetAngleZ(1, Math::PropAngle(0, 65, prog)); // head
- m_object->SetAngleZ(2, Math::PropAngle(0, -95, prog)); // tail
- }
- else if ( m_actionType == MAS_FIRE ) // shooting?
- {
- if ( m_progress < 0.75f ) a = m_progress/0.75f;
- else a = (1.0f-m_progress)/0.25f;
- m_object->SetZoom(2, (a*0.5f)+1.0f); // tail
- m_object->SetAngleX(2, (Math::Rand()-0.5f)*0.3f*a);
- m_object->SetAngleY(2, (Math::Rand()-0.5f)*0.3f*a);
-
- dir.x = (Math::Rand()-0.5f)*0.02f*a;
- dir.y = (Math::Rand()-0.5f)*0.05f*a;
- dir.z = (Math::Rand()-0.5f)*0.03f*a;
- SetCirVibration(dir);
- }
- else if ( m_actionType == MAS_TERMINATE ) // ends the shooting?
- {
- prog = 1.0f-m_progress;
-
- dir.x = 0.0f;
- dir.y = 0.0f;
- dir.z = Math::PropAngle(0, -50, prog);
- SetInclinaison(dir);
- m_object->SetAngleZ(1, Math::PropAngle(0, 65, prog)); // head
- m_object->SetAngleZ(2, Math::PropAngle(0, -95, prog)); // tail
- }
- else if ( m_actionType == MAS_BURN ) // burning?
- {
- dir = Math::Vector(Math::PI, 0.0f, 0.0f);
- SetCirVibration(dir);
- dir = Math::Vector(0.0f, -1.5f, 0.0f);
- SetLinVibration(dir);
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetInclinaison(dir);
-
- time = event.rTime*1.0f;
- m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), 0.0f, time)); // head
- m_object->SetAngleZ(2, Math::Smooth(m_object->RetAngleZ(2), 0.0f, time)); // tail
- }
- else if ( m_actionType == MAS_RUIN ) // destroyed?
- {
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetLinVibration(dir);
- SetCirVibration(dir);
- SetInclinaison(dir);
- }
- else if ( m_actionType == MAS_BACK1 ) // starts on the back?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
- {
- m_lastParticule = m_armTimeAbs;
-
- pos = m_object->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = Math::Rand()*5.0f;
- dim.x = Math::Rand()*3.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
-
- if ( m_progress < 0.5f )
- {
- dir.x = 0.0f;
- dir.y = powf(m_progress/0.5f, 2.0f)*12.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
- else
- {
- dir.x = 0.0f;
- dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*12.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
- dir.x = m_progress*Math::PI;
- dir.y = 0.0f;
- dir.z = 0.0f;
- SetCirVibration(dir);
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetInclinaison(dir);
-
- if ( m_progress >= 1.0f )
- {
- SetAction(MAS_BACK2, 55.0f+Math::Rand()*10.0f);
- }
- }
- else if ( m_actionType == MAS_BACK2 ) // moves on the back?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
- {
- m_lastParticule = m_armTimeAbs;
-
- if ( rand()%10 == 0 )
- {
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- pos.y -= 1.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = Math::Rand()*2.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
- }
-
- dir = Math::Vector(0.0f, -1.0f, 0.0f);
- SetLinVibration(dir);
- dir.x = sinf(m_armTimeAbs* 4.0f)*0.10f+
- sinf(m_armTimeAbs* 7.0f)*0.20f+
- sinf(m_armTimeAbs*10.0f)*0.40f+
- sinf(m_armTimeAbs*21.0f)*0.50f+Math::PI;
- dir.y = sinf(m_armTimeAbs* 3.0f)*0.01f+
- sinf(m_armTimeAbs* 6.0f)*0.02f+
- sinf(m_armTimeAbs*11.0f)*0.04f+
- sinf(m_armTimeAbs*20.0f)*0.02f;
- dir.z = sinf(m_armTimeAbs* 5.0f)*0.01f+
- sinf(m_armTimeAbs* 8.0f)*0.02f+
- sinf(m_armTimeAbs* 9.0f)*0.04f+
- sinf(m_armTimeAbs*23.0f)*0.03f;
- SetCirVibration(dir);
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetInclinaison(dir);
-
- m_object->SetAngleY(1, sinf(m_armTimeAbs*8.0f)*0.7f); // head
- m_object->SetAngleY(2, cosf(m_armTimeAbs*8.0f)*0.7f); // tail
- m_object->SetAngleZ(1, 0.0f); // head
- m_object->SetAngleZ(2, 0.0f); // tail
-
- if ( m_progress >= 1.0f )
- {
- SetAction(MAS_BACK3, 0.4f);
- }
- }
- else if ( m_actionType == MAS_BACK3 ) // goes back on the legs?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
- {
- m_lastParticule = m_armTimeAbs;
-
- pos = m_object->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = Math::Rand()*5.0f;
- dim.x = Math::Rand()*3.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
-
- if ( m_progress < 0.5f )
- {
- dir.x = 0.0f;
- dir.y = powf(m_progress/0.5f, 2.0f)*5.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
- else
- {
- dir.x = 0.0f;
- dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*5.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
- dir.x = (1.0f-m_progress)*Math::PI;
- dir.y = 0.0f;
- dir.z = 0.0f;
- SetCirVibration(dir);
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetInclinaison(dir);
-
- if ( m_progress >= 1.0f )
- {
- SetAction(-1);
- m_object->SetFixed(false); // moving again
- }
- }
- else
- {
- m_object->SetZoom(2, 1.0f); // tail
- m_object->SetAngleX(2, 0.0f);
- m_object->SetAngleY(2, 0.0f);
-
- if ( bStop )
- {
- m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.7f)*0.15f); // tail
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetLinVibration(dir);
- SetInclinaison(dir);
- }
- else
- {
- a = Math::Mod(m_armTimeMarch, 1.0f);
- if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
- else a = 3.0f-4.0f*a; // 1..-1
- dir.x = sinf(a)*0.05f;
-
- s = Math::Mod(m_armTimeMarch/2.0f, 1.0f);
- if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
- else s = 3.0f-4.0f*s; // 1..-1
- dir.z = sinf(s)*0.1f;
-
- dir.y = 0.0f;
- SetInclinaison(dir);
-
- m_object->SetAngleZ(2, -sinf(a)*0.3f); // tail
-
- a = Math::Mod(m_armMember-0.1f, 1.0f);
- if ( a < 0.33f )
- {
- dir.y = -(1.0f-(a/0.33f))*0.3f;
- }
- else if ( a < 0.67f )
- {
- dir.y = 0.0f;
- }
- else
- {
- dir.y = -(a-0.67f)/0.33f*0.3f;
- }
- dir.x = 0.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetCirVibration(dir);
-
- m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.4f)*0.20f); // head
- m_object->SetAngleX(1, sinf(m_armTimeAbs*1.9f)*0.10f); // head
- m_object->SetAngleY(1, sinf(m_armTimeAbs*2.1f)*0.50f); // head
- }
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionant.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motionant.h"
+
+#include "old/modfile.h"
+#include "old/particule.h"
+#include "physics/physics.h"
+
+
+
+#define ADJUST_ANGLE false // true -> adjusts the angles of the members
+const float START_TIME = 1000.0f; // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionAnt::CMotionAnt(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeMarch = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLastAction = -1;
+ m_bArmStop = false;
+ m_lastParticule = 0.0f;
+}
+
+// Object's destructor.
+
+CMotionAnt::~CMotionAnt()
+{
+}
+
+
+// Removes an object.
+
+void CMotionAnt::DeleteObject(bool bAll)
+{
+}
+
+
+// Creates a vehicle poses some rolling on the floor.
+
+bool CMotionAnt::Create(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 3+18 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates the main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+
+ pModFile->ReadModel("objects\\ant1.mod");
+ pModFile->CreateEngineObject(rank);
+
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have necessarily a collision
+ //with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(Math::Vector(0.0f, -2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
+ m_object->SetGlobalSphere(Math::Vector(-0.5f, 1.0f, 0.0f), 4.0f);
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\ant2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(2.0f, 0.0f, 0.0f));
+
+ // Creates the tail.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\ant3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(-1.0f, 0.0f, 0.0f));
+
+ // Creates a right-back thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(-0.4f, -0.1f, -0.3f));
+
+ // Creates a right-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 3);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates a right-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 4);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates two middle-right thighs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(0.1f, -0.1f, -0.4f));
+
+ // Creates two middle-right legs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 6);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates two middle-right foots.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 7);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates the right front thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, Math::Vector(1.4f, -0.1f, -0.6f));
+
+ // Creates the right front leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10, rank);
+ m_object->SetObjectParent(10, 9);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates the right front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(11, rank);
+ m_object->SetObjectParent(11, 10);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(11, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates a left-back thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(12, rank);
+ m_object->SetObjectParent(12, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(12, Math::Vector(-0.4f, -0.1f, 0.3f));
+
+ // Creates a left-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(13, rank);
+ m_object->SetObjectParent(13, 12);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(13, Math::Vector(0.0f, 0.0f, 1.0f));
+
+ // Creates a left-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(14, rank);
+ m_object->SetObjectParent(14, 13);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(14, Math::Vector(0.0f, 0.0f, 2.0f));
+
+ // Creates two middle-left thighs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(15, rank);
+ m_object->SetObjectParent(15, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(15, Math::Vector(0.1f, -0.1f, 0.4f));
+
+ // Creates two middle-left legs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(16, rank);
+ m_object->SetObjectParent(16, 15);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(16, Math::Vector(0.0f, 0.0f, 1.0f));
+
+ // Creates two middle-left foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(17, rank);
+ m_object->SetObjectParent(17, 16);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(17, Math::Vector(0.0f, 0.0f, 2.0f));
+
+ // Creates the left front thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(18, rank);
+ m_object->SetObjectParent(18, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(18, Math::Vector(1.4f, -0.1f, 0.6f));
+
+ // Creates the left front leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(19, rank);
+ m_object->SetObjectParent(19, 18);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(19, Math::Vector(0.0f, 0.0f, 1.0f));
+
+ // Creates the left front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(20, rank);
+ m_object->SetObjectParent(20, 19);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(20, Math::Vector(0.0f, 0.0f, 2.0f));
+
+ m_object->CreateShadowCircle(4.0f, 0.5f);
+
+ CreatePhysics();
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+// Creates the physics of the object.
+
+void CMotionAnt::CreatePhysics()
+{
+ Character* character;
+ int i;
+
+ int member_march[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 0,45,0, 0,45,0, 0,50,0, // t0: thighs 1..3
+ 30,-70,0, 20,-105,20, 25,-100,0, // t0: legs 1..3
+ -70,75,0, -30,80,0, -80,80,0, // t0: feet 1..3
+ // on the ground:
+ 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3
+ -15,-50,0, -20,-60,0, -10,-75,0, // t1: legs 1..3
+ -40,50,0, -25,15,0, -50,35,0, // t1: feet 1..3
+ // on the ground back:
+ 0,35,0, 0,30,0, 0,20,0, // t2: thighs 1..3
+ -20,-15,0, -30,-55,0, -25,-70,15, // t2: legs 1..3
+ -25,25,0, -20,60,0, -30,95,0, // t2: feet 1..3
+ };
+
+ int member_stop[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 0,30,0, 0,20,0, 0,15,0, // t0: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // t0: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // t0: feet 1..3
+ // on the ground:
+ 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // t1: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // t1: feet 1..3
+ // on the ground back:
+ 0,30,0, 0,20,0, 0,15,0, // t2: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // t2: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // t2: feet 1..3
+ };
+
+ int member_spec[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // prepares the fire:
+ 0,20,0, 0,10,0, 0,50,0, // s0: thighs 1..3
+ -50,-30,0, -20,-15,0, 35,-65,0, // s0: legs 1..3
+ -5,-40,0, 20,-70,0, -10,-40,0, // s0: feet 1..3
+ // shot:
+ 0,20,0, 0,10,0, 0,50,0, // s1: thighs 1..3
+ -50,-30,0, -20,-15,0, 35,-65,0, // s1: legs 1..3
+ -5,-40,0, 20,-70,0, -10,-40,0, // s1: feet 1..3
+ // ends the fire:
+ 0,30,0, 0,20,0, 0,15,0, // s2: thighs 1..3
+ -15,-50,0, -20,-60,0, -10,-75,0, // s2: legs 1..3
+ -40,50,0, -25,15,0, -50,35,0, // s2: feet 1..3
+ // burning:
+ 0,30,0, 0,20,0, 0,15,0, // s3: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // s3: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // s3: feet 1..3
+ // destroyed:
+ 0,30,0, 0,20,0, 0,15,0, // s4: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // s4: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // s4: feet 1..3
+ // back1 :
+ 0,30,0, 0,20,0, 0,15,0, // s5: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // s5: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // s5: feet 1..3
+ // back2 :
+ 0,45,0, 0,45,0, 0,50,0, // s6: thighs 1..3
+ -35,-70,0, -20,-85,-25, -25,-100,0, // s6: legs 1..3
+ -110,75,-15, -130,80,-25, -125,40,0, // s6: feet 1..3
+ // back3 :
+ 0,30,0, 0,20,0, 0,15,0, // s7: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // s7: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // s7: feet 1..3
+ };
+
+ m_physics->SetType(TYPE_ROLLING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 3.0f;
+ character->wheelBack = 3.0f;
+ character->wheelLeft = 5.0f;
+ character->wheelRight = 5.0f;
+ character->height = 1.2f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 12.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 12.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 15.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 10.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 40.0f);
+
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MA_MARCH+i] = member_march[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MA_STOP+i] = member_stop[i];
+ }
+ for ( i=0 ; i<3*3*3*8 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MA_SPEC+i] = member_spec[i];
+ }
+}
+
+
+// Management of an event.
+
+bool CMotionAnt::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if ADJUST_ANGLE
+ int i;
+
+ if ( event.param == 'A' ) m_armTimeIndex++;
+ if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
+
+ if ( event.param == 'Q' ) m_armPartIndex++;
+ if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
+
+ if ( event.param == 'W' ) m_armMemberIndex++;
+ if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
+
+ i = m_armMemberIndex*3;
+ i += m_armPartIndex*3*3;
+ i += m_armTimeIndex*3*3*3;
+//? i += 3*3*3*3;
+
+ if ( event.param == 'E' ) m_armAngles[i+0] += 5;
+ if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
+ if ( event.param == 'R' ) m_armAngles[i+1] += 5;
+ if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
+ if ( event.param == 'T' ) m_armAngles[i+2] += 5;
+ if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
+
+ if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
+#endif
+ }
+
+ return true;
+}
+
+// Management of an event.
+
+bool CMotionAnt::EventFrame(const Event &event)
+{
+ Math::Vector dir, pos, speed;
+ Math::Point dim;
+ float s, a, prog, time;
+ float tSt[9], tNd[9];
+ int i, ii, st, nd, action;
+ bool bStop;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
+ a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f);
+
+ if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armTimeMarch += (s)*event.rTime*0.15f;
+ m_armMember += (s+a)*event.rTime*0.15f;
+
+ bStop = ( a == 0.0f && s == 0.0f ); // stopped?
+
+ action = MA_MARCH; // walking
+ if ( s == 0.0f && a == 0.0f )
+ {
+ action = MA_STOP; // stop
+ }
+
+ if ( bStop )
+ {
+ prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
+ a = Math::Mod(m_armMember, 1.0f);
+ a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly
+ m_armMember += a;
+ }
+
+ if ( m_object->RetRuin() ) // destroyed?
+ {
+ m_actionType = MAS_RUIN;
+ }
+ if ( m_object->RetBurn() ) // burning?
+ {
+ if ( m_object->RetFixed() )
+ {
+ m_actionType = MAS_BURN;
+ }
+ else
+ {
+ m_actionType = -1;
+ }
+ }
+
+ for ( i=0 ; i<6 ; i++ ) // the six legs
+ {
+ if ( m_actionType != -1 ) // special action in progress?
+ {
+ st = 3*3*3*3*MA_SPEC + 3*3*3*m_actionType + (i%3)*3;
+ nd = st;
+ time = event.rTime*m_actionTime;
+ m_armTimeAction = 0.0f;
+ }
+ else
+ {
+ if ( i < 3 ) prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
+ else prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
+ if ( m_bArmStop )
+ {
+ prog = (float)m_armTimeIndex/3.0f;
+ }
+ if ( prog < 0.33f ) // t0..t1 ?
+ {
+ prog = prog/0.33f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.67f ) // t1..t2 ?
+ {
+ prog = (prog-0.33f)/0.33f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.67f)/0.33f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ st = 3*3*3*3*action + st*3*3*3 + (i%3)*3;
+ nd = 3*3*3*3*action + nd*3*3*3 + (i%3)*3;
+
+ // More and more soft ...
+ time = event.rTime*(10.0f+Math::Min(m_armTimeAction*100.0f, 200.0f));
+ }
+
+ tSt[0] = m_armAngles[st+ 0]; // x
+ tSt[1] = m_armAngles[st+ 1]; // y
+ tSt[2] = m_armAngles[st+ 2]; // z
+ tSt[3] = m_armAngles[st+ 9]; // x
+ tSt[4] = m_armAngles[st+10]; // y
+ tSt[5] = m_armAngles[st+11]; // z
+ tSt[6] = m_armAngles[st+18]; // x
+ tSt[7] = m_armAngles[st+19]; // y
+ tSt[8] = m_armAngles[st+20]; // z
+
+ tNd[0] = m_armAngles[nd+ 0]; // x
+ tNd[1] = m_armAngles[nd+ 1]; // y
+ tNd[2] = m_armAngles[nd+ 2]; // z
+ tNd[3] = m_armAngles[nd+ 9]; // x
+ tNd[4] = m_armAngles[nd+10]; // y
+ tNd[5] = m_armAngles[nd+11]; // z
+ tNd[6] = m_armAngles[nd+18]; // x
+ tNd[7] = m_armAngles[nd+19]; // y
+ tNd[8] = m_armAngles[nd+20]; // z
+
+ if ( m_actionType == MAS_BACK2 ) // on the back?
+ {
+ for ( ii=0 ; ii<9 ; ii++ )
+ {
+ tSt[ii] += Math::Rand()*50.0f;
+ tNd[ii] = tSt[ii];
+ }
+//? time = 100.0f;
+ time = event.rTime*10.0f;
+ }
+
+ if ( i < 3 ) // right leg (1..3) ?
+ {
+ m_object->SetAngleX(3+3*i+0, Math::Smooth(m_object->RetAngleX(3+3*i+0), Math::PropAngle(tSt[0], tNd[0], prog), time));
+ m_object->SetAngleY(3+3*i+0, Math::Smooth(m_object->RetAngleY(3+3*i+0), Math::PropAngle(tSt[1], tNd[1], prog), time));
+ m_object->SetAngleZ(3+3*i+0, Math::Smooth(m_object->RetAngleZ(3+3*i+0), Math::PropAngle(tSt[2], tNd[2], prog), time));
+ m_object->SetAngleX(3+3*i+1, Math::Smooth(m_object->RetAngleX(3+3*i+1), Math::PropAngle(tSt[3], tNd[3], prog), time));
+ m_object->SetAngleY(3+3*i+1, Math::Smooth(m_object->RetAngleY(3+3*i+1), Math::PropAngle(tSt[4], tNd[4], prog), time));
+ m_object->SetAngleZ(3+3*i+1, Math::Smooth(m_object->RetAngleZ(3+3*i+1), Math::PropAngle(tSt[5], tNd[5], prog), time));
+ m_object->SetAngleX(3+3*i+2, Math::Smooth(m_object->RetAngleX(3+3*i+2), Math::PropAngle(tSt[6], tNd[6], prog), time));
+ m_object->SetAngleY(3+3*i+2, Math::Smooth(m_object->RetAngleY(3+3*i+2), Math::PropAngle(tSt[7], tNd[7], prog), time));
+ m_object->SetAngleZ(3+3*i+2, Math::Smooth(m_object->RetAngleZ(3+3*i+2), Math::PropAngle(tSt[8], tNd[8], prog), time));
+ }
+ else // left leg (4..6) ?
+ {
+ m_object->SetAngleX(3+3*i+0, Math::Smooth(m_object->RetAngleX(3+3*i+0), Math::PropAngle(-tSt[0], -tNd[0], prog), time));
+ m_object->SetAngleY(3+3*i+0, Math::Smooth(m_object->RetAngleY(3+3*i+0), Math::PropAngle(-tSt[1], -tNd[1], prog), time));
+ m_object->SetAngleZ(3+3*i+0, Math::Smooth(m_object->RetAngleZ(3+3*i+0), Math::PropAngle( tSt[2], tNd[2], prog), time));
+ m_object->SetAngleX(3+3*i+1, Math::Smooth(m_object->RetAngleX(3+3*i+1), Math::PropAngle(-tSt[3], -tNd[3], prog), time));
+ m_object->SetAngleY(3+3*i+1, Math::Smooth(m_object->RetAngleY(3+3*i+1), Math::PropAngle(-tSt[4], -tNd[4], prog), time));
+ m_object->SetAngleZ(3+3*i+1, Math::Smooth(m_object->RetAngleZ(3+3*i+1), Math::PropAngle( tSt[5], tNd[5], prog), time));
+ m_object->SetAngleX(3+3*i+2, Math::Smooth(m_object->RetAngleX(3+3*i+2), Math::PropAngle(-tSt[6], -tNd[6], prog), time));
+ m_object->SetAngleY(3+3*i+2, Math::Smooth(m_object->RetAngleY(3+3*i+2), Math::PropAngle(-tSt[7], -tNd[7], prog), time));
+ m_object->SetAngleZ(3+3*i+2, Math::Smooth(m_object->RetAngleZ(3+3*i+2), Math::PropAngle( tSt[8], tNd[8], prog), time));
+ }
+ }
+
+#if ADJUST_ANGLE
+ if ( m_object->RetSelect() )
+ {
+ char s[100];
+ sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
+ m_engine->SetInfoText(4, s);
+ }
+#endif
+
+ if ( m_actionType == MAS_PREPARE ) // prepares the shooting?
+ {
+ prog = m_progress;
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = Math::PropAngle(0, -50, prog);
+ SetInclinaison(dir);
+ m_object->SetAngleZ(1, Math::PropAngle(0, 65, prog)); // head
+ m_object->SetAngleZ(2, Math::PropAngle(0, -95, prog)); // tail
+ }
+ else if ( m_actionType == MAS_FIRE ) // shooting?
+ {
+ if ( m_progress < 0.75f ) a = m_progress/0.75f;
+ else a = (1.0f-m_progress)/0.25f;
+ m_object->SetZoom(2, (a*0.5f)+1.0f); // tail
+ m_object->SetAngleX(2, (Math::Rand()-0.5f)*0.3f*a);
+ m_object->SetAngleY(2, (Math::Rand()-0.5f)*0.3f*a);
+
+ dir.x = (Math::Rand()-0.5f)*0.02f*a;
+ dir.y = (Math::Rand()-0.5f)*0.05f*a;
+ dir.z = (Math::Rand()-0.5f)*0.03f*a;
+ SetCirVibration(dir);
+ }
+ else if ( m_actionType == MAS_TERMINATE ) // ends the shooting?
+ {
+ prog = 1.0f-m_progress;
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = Math::PropAngle(0, -50, prog);
+ SetInclinaison(dir);
+ m_object->SetAngleZ(1, Math::PropAngle(0, 65, prog)); // head
+ m_object->SetAngleZ(2, Math::PropAngle(0, -95, prog)); // tail
+ }
+ else if ( m_actionType == MAS_BURN ) // burning?
+ {
+ dir = Math::Vector(Math::PI, 0.0f, 0.0f);
+ SetCirVibration(dir);
+ dir = Math::Vector(0.0f, -1.5f, 0.0f);
+ SetLinVibration(dir);
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ time = event.rTime*1.0f;
+ m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), 0.0f, time)); // head
+ m_object->SetAngleZ(2, Math::Smooth(m_object->RetAngleZ(2), 0.0f, time)); // tail
+ }
+ else if ( m_actionType == MAS_RUIN ) // destroyed?
+ {
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ SetCirVibration(dir);
+ SetInclinaison(dir);
+ }
+ else if ( m_actionType == MAS_BACK1 ) // starts on the back?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = Math::Rand()*5.0f;
+ dim.x = Math::Rand()*3.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+
+ if ( m_progress < 0.5f )
+ {
+ dir.x = 0.0f;
+ dir.y = powf(m_progress/0.5f, 2.0f)*12.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*12.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ dir.x = m_progress*Math::PI;
+ dir.y = 0.0f;
+ dir.z = 0.0f;
+ SetCirVibration(dir);
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(MAS_BACK2, 55.0f+Math::Rand()*10.0f);
+ }
+ }
+ else if ( m_actionType == MAS_BACK2 ) // moves on the back?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ if ( rand()%10 == 0 )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ pos.y -= 1.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = Math::Rand()*2.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+ }
+
+ dir = Math::Vector(0.0f, -1.0f, 0.0f);
+ SetLinVibration(dir);
+ dir.x = sinf(m_armTimeAbs* 4.0f)*0.10f+
+ sinf(m_armTimeAbs* 7.0f)*0.20f+
+ sinf(m_armTimeAbs*10.0f)*0.40f+
+ sinf(m_armTimeAbs*21.0f)*0.50f+Math::PI;
+ dir.y = sinf(m_armTimeAbs* 3.0f)*0.01f+
+ sinf(m_armTimeAbs* 6.0f)*0.02f+
+ sinf(m_armTimeAbs*11.0f)*0.04f+
+ sinf(m_armTimeAbs*20.0f)*0.02f;
+ dir.z = sinf(m_armTimeAbs* 5.0f)*0.01f+
+ sinf(m_armTimeAbs* 8.0f)*0.02f+
+ sinf(m_armTimeAbs* 9.0f)*0.04f+
+ sinf(m_armTimeAbs*23.0f)*0.03f;
+ SetCirVibration(dir);
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*8.0f)*0.7f); // head
+ m_object->SetAngleY(2, cosf(m_armTimeAbs*8.0f)*0.7f); // tail
+ m_object->SetAngleZ(1, 0.0f); // head
+ m_object->SetAngleZ(2, 0.0f); // tail
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(MAS_BACK3, 0.4f);
+ }
+ }
+ else if ( m_actionType == MAS_BACK3 ) // goes back on the legs?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = Math::Rand()*5.0f;
+ dim.x = Math::Rand()*3.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+
+ if ( m_progress < 0.5f )
+ {
+ dir.x = 0.0f;
+ dir.y = powf(m_progress/0.5f, 2.0f)*5.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*5.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ dir.x = (1.0f-m_progress)*Math::PI;
+ dir.y = 0.0f;
+ dir.z = 0.0f;
+ SetCirVibration(dir);
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(-1);
+ m_object->SetFixed(false); // moving again
+ }
+ }
+ else
+ {
+ m_object->SetZoom(2, 1.0f); // tail
+ m_object->SetAngleX(2, 0.0f);
+ m_object->SetAngleY(2, 0.0f);
+
+ if ( bStop )
+ {
+ m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.7f)*0.15f); // tail
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ SetInclinaison(dir);
+ }
+ else
+ {
+ a = Math::Mod(m_armTimeMarch, 1.0f);
+ if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
+ else a = 3.0f-4.0f*a; // 1..-1
+ dir.x = sinf(a)*0.05f;
+
+ s = Math::Mod(m_armTimeMarch/2.0f, 1.0f);
+ if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
+ else s = 3.0f-4.0f*s; // 1..-1
+ dir.z = sinf(s)*0.1f;
+
+ dir.y = 0.0f;
+ SetInclinaison(dir);
+
+ m_object->SetAngleZ(2, -sinf(a)*0.3f); // tail
+
+ a = Math::Mod(m_armMember-0.1f, 1.0f);
+ if ( a < 0.33f )
+ {
+ dir.y = -(1.0f-(a/0.33f))*0.3f;
+ }
+ else if ( a < 0.67f )
+ {
+ dir.y = 0.0f;
+ }
+ else
+ {
+ dir.y = -(a-0.67f)/0.33f*0.3f;
+ }
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetCirVibration(dir);
+
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.4f)*0.20f); // head
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.9f)*0.10f); // head
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*2.1f)*0.50f); // head
+ }
+
+ return true;
+}
+
+
diff --git a/src/object/motion/motionant.h b/src/object/motion/motionant.h
index 71a11e4..8ddd789 100644
--- a/src/object/motion/motionant.h
+++ b/src/object/motion/motionant.h
@@ -1,73 +1,73 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionant.h
-
-#pragma once
-
-
-#include "object/motion/motion.h"
-
-
-
-enum MotionAntAction
-{
- MA_MARCH = 0,
- MA_STOP = 1,
- MA_SPEC = 2
-};
-
-enum MotionAntSpecialAction
-{
- MAS_PREPARE = 0,
- MAS_FIRE = 1,
- MAS_TERMINATE = 2,
- MAS_BURN = 3,
- MAS_RUIN = 4,
- MAS_BACK1 = 5,
- MAS_BACK2 = 6,
- MAS_BACK3 = 7
-};
-
-
-class CMotionAnt : public CMotion
-{
-public:
- CMotionAnt(CInstanceManager* iMan, CObject* object);
- ~CMotionAnt();
-
- void DeleteObject(bool bAll=false);
- bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- bool EventProcess(const Event &event);
-
-protected:
- void CreatePhysics();
- bool EventFrame(const Event &event);
-
-protected:
- float m_armMember;
- float m_armTimeAbs;
- float m_armTimeMarch;
- float m_armTimeAction;
- short m_armAngles[3*3*3*3*3 + 3*3*3*8];
- int m_armTimeIndex;
- int m_armPartIndex;
- int m_armMemberIndex;
- int m_armLastAction;
- bool m_bArmStop;
- float m_lastParticule;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionant.h
+
+#pragma once
+
+
+#include "object/motion/motion.h"
+
+
+
+enum MotionAntAction
+{
+ MA_MARCH = 0,
+ MA_STOP = 1,
+ MA_SPEC = 2
+};
+
+enum MotionAntSpecialAction
+{
+ MAS_PREPARE = 0,
+ MAS_FIRE = 1,
+ MAS_TERMINATE = 2,
+ MAS_BURN = 3,
+ MAS_RUIN = 4,
+ MAS_BACK1 = 5,
+ MAS_BACK2 = 6,
+ MAS_BACK3 = 7
+};
+
+
+class CMotionAnt : public CMotion
+{
+public:
+ CMotionAnt(CInstanceManager* iMan, CObject* object);
+ ~CMotionAnt();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ bool EventProcess(const Event &event);
+
+protected:
+ void CreatePhysics();
+ bool EventFrame(const Event &event);
+
+protected:
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeMarch;
+ float m_armTimeAction;
+ short m_armAngles[3*3*3*3*3 + 3*3*3*8];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ bool m_bArmStop;
+ float m_lastParticule;
+};
+
diff --git a/src/object/motion/motionbee.cpp b/src/object/motion/motionbee.cpp
index c5d9ed2..e5c6b24 100644
--- a/src/object/motion/motionbee.cpp
+++ b/src/object/motion/motionbee.cpp
@@ -1,644 +1,644 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionbee.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motionbee.h"
-
-#include "old/modfile.h"
-#include "physics/physics.h"
-
-
-
-#define ADJUST_ANGLE false // true -> adjusts the angles of the members
-const float START_TIME = 1000.0f; // beginning of the relative time
-
-
-
-// Object's constructor.
-
-CMotionBee::CMotionBee(CInstanceManager* iMan, CObject* object)
- : CMotion(iMan, object)
-{
- m_armMember = START_TIME;
- m_armTimeAbs = START_TIME;
- m_armTimeMarch = START_TIME;
- m_armTimeAction = START_TIME;
- m_armTimeIndex = 0;
- m_armPartIndex = 0;
- m_armMemberIndex = 0;
- m_armLastAction = -1;
- m_bArmStop = false;
-}
-
-// Object's destructor.
-
-CMotionBee::~CMotionBee()
-{
-}
-
-
-// Removes an object.
-
-void CMotionBee::DeleteObject(bool bAll)
-{
-}
-
-
-// Creates a vehicle traveling any lands on the ground.
-
-bool CMotionBee::Create(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 3+18+2 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- m_object->SetType(type);
-
- // Creates main base.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
-
- pModFile->ReadModel("objects\\bee1.mod");
- pModFile->CreateEngineObject(rank);
-
- m_object->SetPosition(0, pos);
- m_object->SetAngleY(0, angle);
-
- // A vehicle must have an obligatory collision
- // with a sphere of center (0, y, 0) (see GetCrashSphere).
- m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
- m_object->SetGlobalSphere(Math::Vector(-1.0f, 1.0f, 0.0f), 5.0f);
-
- // Creates the head.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\bee2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(1.6f, 0.3f, 0.0f));
-
- // Creates the tail.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\bee3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(-0.8f, 0.0f, 0.0f));
-
- // Creates a right-back thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(-0.3f, -0.1f, -0.2f));
-
- // Creates a right-back leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(4, rank);
- m_object->SetObjectParent(4, 3);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(4, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates a right-back foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(5, rank);
- m_object->SetObjectParent(5, 4);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(5, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates two middle-right thighs.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(0.3f, -0.1f, -0.4f));
-
- // Creates two middle-right legs.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 6);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates two middle-right feet.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 7);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates the right front thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(9, rank);
- m_object->SetObjectParent(9, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(9, Math::Vector(1.0f, -0.1f, -0.7f));
-
- // Creates the right front leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(10, rank);
- m_object->SetObjectParent(10, 9);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(10, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates the right front foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(11, rank);
- m_object->SetObjectParent(11, 10);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(11, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates a left-back thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(12, rank);
- m_object->SetObjectParent(12, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(12, Math::Vector(-0.3f, -0.1f, 0.2f));
- m_object->SetAngleY(12, Math::PI);
-
- // Creates a left-back leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(13, rank);
- m_object->SetObjectParent(13, 12);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(13, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates a left-back foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(14, rank);
- m_object->SetObjectParent(14, 13);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(14, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates two middle-left thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(15, rank);
- m_object->SetObjectParent(15, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(15, Math::Vector(0.3f, -0.1f, 0.4f));
- m_object->SetAngleY(15, Math::PI);
-
- // Creates two middle-left legs.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(16, rank);
- m_object->SetObjectParent(16, 15);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(16, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates two middle-left feet.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(17, rank);
- m_object->SetObjectParent(17, 16);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(17, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates front-left thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(18, rank);
- m_object->SetObjectParent(18, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(18, Math::Vector(1.0f, -0.1f, 0.7f));
- m_object->SetAngleY(18, Math::PI);
-
- // Creates front-left leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(19, rank);
- m_object->SetObjectParent(19, 18);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(19, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates front-left foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(20, rank);
- m_object->SetObjectParent(20, 19);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(20, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates the right wing.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(21, rank);
- m_object->SetObjectParent(21, 0);
- pModFile->ReadModel("objects\\bee7.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(21, Math::Vector(0.8f, 0.4f, -0.5f));
-
- // Creates the left wing.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(22, rank);
- m_object->SetObjectParent(22, 0);
- pModFile->ReadModel("objects\\bee7.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(22, Math::Vector(0.8f, 0.4f, 0.5f));
-
- m_object->CreateShadowCircle(6.0f, 0.5f);
-
- CreatePhysics();
- m_object->SetFloorHeight(0.0f);
-
- pos = m_object->RetPosition(0);
- m_object->SetPosition(0, pos); // to display the shadows immediately
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-// Creates the physical object.
-
-void CMotionBee::CreatePhysics()
-{
- Character* character;
- int i;
-
- int member_march[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
- 0,45,0, 0,45,0, 0,50,0, // t0: thighs 1..3
- 30,-70,0, 20,-105,20, 25,-100,0, // t0: legs 1..3
- -70,75,0, -30,80,0, -80,80,0, // t0: feet 1..3
- // on the ground:
- 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3
- -15,-50,0, -20,-60,0, -10,-75,0, // t1: legs 1..3
- -40,50,0, -25,15,0, -50,35,0, // t1: feet 1..3
- // on the ground back:
- 0,35,0, 0,30,0, 0,20,0, // t2: thighs 1..3
- -20,-15,0, -30,-55,0, -25,-70,15, // t2: legs 1..3
- -25,25,0, -20,60,0, -30,95,0, // t2: feet 1..3
- };
-
- int member_spec[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // ball carrier:
- 0,45,0, 0,45,0, 0,50,0, // s0: thighs 1..3
- -35,-70,0, -20,-85,-25, -25,-100,0, // s0: legs 1..3
- -110,75,-15, -130,80,-25, -125,40,0, // s0: feet 1..3
- // burning:
- 0,45,0, 0,45,0, 0,50,0, // s1: thighs 1..3
- -35,-70,0, -20,-85,-25, -25,-100,0, // s1: legs 1..3
- -110,75,-15, -130,80,-25, -125,40,0, // s1: feet 1..3
- // destroyed:
- 0,45,0, 0,45,0, 0,50,0, // s2: thighs 1..3
- -35,-70,0, -20,-85,-25, -25,-100,0, // s2: legs 1..3
- -110,75,-15, -130,80,-25, -125,40,0, // s2: feet 1..3
- };
-
- m_physics->SetType(TYPE_FLYING);
-
- character = m_object->RetCharacter();
- character->wheelFront = 3.0f;
- character->wheelBack = 3.0f;
- character->wheelLeft = 5.0f;
- character->wheelRight = 5.0f;
- character->height = 2.5f;
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 50.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 10.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
- m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
- m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
- m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
- m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 20.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 40.0f);
-
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MB_MARCH+i] = member_march[i];
- }
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MB_SPEC+i] = member_spec[i];
- }
-}
-
-
-// Management of an event.
-
-bool CMotionBee::EventProcess(const Event &event)
-{
- CMotion::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
-#if ADJUST_ANGLE
- int i;
-
- if ( event.param == 'A' ) m_armTimeIndex++;
- if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
-
- if ( event.param == 'Q' ) m_armPartIndex++;
- if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
-
- if ( event.param == 'W' ) m_armMemberIndex++;
- if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
-
- i = m_armMemberIndex*3;
- i += m_armPartIndex*3*3;
- i += m_armTimeIndex*3*3*3;
-//? i += 3*3*3*3;
-
- if ( event.param == 'E' ) m_armAngles[i+0] += 5;
- if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
- if ( event.param == 'R' ) m_armAngles[i+1] += 5;
- if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
- if ( event.param == 'T' ) m_armAngles[i+2] += 5;
- if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
-
- if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
-#endif
- }
-
- return true;
-}
-
-// Management of an event.
-
-bool CMotionBee::EventFrame(const Event &event)
-{
- Math::Vector dir;
- float s, a, prog;
- int action, i, st, nd;
- bool bStop;
-
- if ( m_engine->RetPause() ) return true;
- if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
-
- s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.30f;
- a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.00f);
-
- if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
-
- m_armTimeAbs += event.rTime;
- m_armTimeMarch += (s)*event.rTime*0.15f;
- m_armMember += (s+a)*event.rTime*0.15f;
-
- bStop = ( a == 0.0f && s == 0.0f ); // stopped?
- if ( !m_physics->RetLand() ) bStop = true;
-
- if ( bStop )
- {
- prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
- a = Math::Mod(m_armMember, 1.0f);
- a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly
- m_armMember += a;
- }
-
- action = MB_MARCH; // flying
-
- m_actionType = -1;
- if ( m_object->RetFret() != 0 ) m_actionType = MBS_HOLD; // carries the ball
-
- if ( m_object->RetRuin() ) // destroyed?
- {
- m_actionType = MBS_RUIN;
- }
- if ( m_object->RetBurn() ) // burning?
- {
- m_actionType = MBS_BURN;
- }
-
- for ( i=0 ; i<6 ; i++ ) // the six legs
- {
- if ( m_actionType != -1 ) // special action in progress?
- {
- st = 3*3*3*3*MB_SPEC + 3*3*3*m_actionType + (i%3)*3;
- nd = st;
- }
- else
- {
- if ( i < 3 ) prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
- else prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
- if ( m_bArmStop )
- {
- prog = (float)m_armTimeIndex/3.0f;
- }
- if ( prog < 0.33f ) // t0..t1 ?
- {
- prog = prog/0.33f; // 0..1
- st = 0; // index start
- nd = 1; // index end
- }
- else if ( prog < 0.67f ) // t1..t2 ?
- {
- prog = (prog-0.33f)/0.33f; // 0..1
- st = 1; // index start
- nd = 2; // index end
- }
- else // t2..t0 ?
- {
- prog = (prog-0.67f)/0.33f; // 0..1
- st = 2; // index start
- nd = 0; // index end
- }
- st = 3*3*3*3*action + st*3*3*3 + (i%3)*3;
- nd = 3*3*3*3*action + nd*3*3*3 + (i%3)*3;
- }
-
- if ( i < 3 ) // right leg (1..3) ?
- {
- m_object->SetAngleX(3+3*i+0, Math::PropAngle(m_armAngles[st+ 0], m_armAngles[nd+ 0], prog));
- m_object->SetAngleY(3+3*i+0, Math::PropAngle(m_armAngles[st+ 1], m_armAngles[nd+ 1], prog));
- m_object->SetAngleZ(3+3*i+0, Math::PropAngle(m_armAngles[st+ 2], m_armAngles[nd+ 2], prog));
- m_object->SetAngleX(3+3*i+1, Math::PropAngle(m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
- m_object->SetAngleY(3+3*i+1, Math::PropAngle(m_armAngles[st+10], m_armAngles[nd+10], prog));
- m_object->SetAngleZ(3+3*i+1, Math::PropAngle(m_armAngles[st+11], m_armAngles[nd+11], prog));
- m_object->SetAngleX(3+3*i+2, Math::PropAngle(m_armAngles[st+18], m_armAngles[nd+18], prog));
- m_object->SetAngleY(3+3*i+2, Math::PropAngle(m_armAngles[st+19], m_armAngles[nd+19], prog));
- m_object->SetAngleZ(3+3*i+2, Math::PropAngle(m_armAngles[st+20], m_armAngles[nd+20], prog));
- }
- else // left leg(4..6) ?
- {
- m_object->SetAngleX(3+3*i+0, Math::PropAngle( -m_armAngles[st+ 0], -m_armAngles[nd+ 0], prog));
- m_object->SetAngleY(3+3*i+0, Math::PropAngle(180-m_armAngles[st+ 1], 180-m_armAngles[nd+ 1], prog));
- m_object->SetAngleZ(3+3*i+0, Math::PropAngle( -m_armAngles[st+ 2], -m_armAngles[nd+ 2], prog));
- m_object->SetAngleX(3+3*i+1, Math::PropAngle( m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
- m_object->SetAngleY(3+3*i+1, Math::PropAngle( -m_armAngles[st+10], -m_armAngles[nd+10], prog));
- m_object->SetAngleZ(3+3*i+1, Math::PropAngle( -m_armAngles[st+11], -m_armAngles[nd+11], prog));
- m_object->SetAngleX(3+3*i+2, Math::PropAngle( m_armAngles[st+18], m_armAngles[nd+18], prog));
- m_object->SetAngleY(3+3*i+2, Math::PropAngle( -m_armAngles[st+19], -m_armAngles[nd+19], prog));
- m_object->SetAngleZ(3+3*i+2, Math::PropAngle( -m_armAngles[st+20], -m_armAngles[nd+20], prog));
- }
- }
-
-#if ADJUST_ANGLE
- if ( m_object->RetSelect() )
- {
- char s[100];
- sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
- m_engine->SetInfoText(4, s);
- }
-#endif
-
- if ( m_physics->RetLand() ) // on the ground?
- {
- if ( m_object->RetRuin() )
- {
- }
- else if ( bStop || m_object->RetBurn() )
- {
- m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.7f)*0.15f+0.35f); // tail
- }
- else
- {
- a = Math::Mod(m_armTimeMarch, 1.0f);
- if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
- else a = 3.0f-4.0f*a; // 1..-1
- dir.x = sinf(a)*0.05f;
-
- s = Math::Mod(m_armTimeMarch/2.0f, 1.0f);
- if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
- else s = 3.0f-4.0f*s; // 1..-1
- dir.z = sinf(s)*0.1f;
-
- dir.y = 0.0f;
- m_object->SetInclinaison(dir);
-
- m_object->SetAngleZ(2, -sinf(a)*0.3f); // tail
-
- a = Math::Mod(m_armMember-0.1f, 1.0f);
- if ( a < 0.33f )
- {
- dir.y = -(1.0f-(a/0.33f))*0.3f;
- }
- else if ( a < 0.67f )
- {
- dir.y = 0.0f;
- }
- else
- {
- dir.y = -(a-0.67f)/0.33f*0.3f;
- }
- dir.x = 0.0f;
- dir.z = 0.0f;
- m_object->SetLinVibration(dir);
- }
- }
-
- if ( m_physics->RetLand() )
- {
- if ( bStop ) prog = 0.05f;
- else prog = 0.15f;
- }
- else
- {
- prog = 1.00f;
- }
-
-#if 0
- a = Math::Rand()*Math::PI/2.0f*prog;
- m_object->SetAngleX(21, a); // right wing
- a = -Math::Rand()*Math::PI/4.0f*prog;
- m_object->SetAngleY(21, a);
-
- a = -Math::Rand()*Math::PI/2.0f*prog;
- m_object->SetAngleX(22, a); // left wing
- a = Math::Rand()*Math::PI/4.0f*prog;
- m_object->SetAngleY(22, a);
-#else
- m_object->SetAngleX(21, (sinf(m_armTimeAbs*30.0f)+1.0f)*(Math::PI/4.0f)*prog);
- m_object->SetAngleY(21, -Math::Rand()*Math::PI/6.0f*prog);
-
- m_object->SetAngleX(22, -(sinf(m_armTimeAbs*30.0f)+1.0f)*(Math::PI/4.0f)*prog);
- m_object->SetAngleY(22, Math::Rand()*Math::PI/6.0f*prog);
-#endif
-
- m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.4f)*0.20f); // head
- m_object->SetAngleX(1, sinf(m_armTimeAbs*1.9f)*0.10f); // head
- m_object->SetAngleY(1, sinf(m_armTimeAbs*2.1f)*0.50f); // head
-
-#if 0
- h = m_terrain->RetFloorHeight(RetPosition(0));
- radius = 4.0f+h/4.0f;
- color.r = 0.3f+h/80.0f;
- color.g = color.r;
- color.b = color.r;
- color.a = color.r;
- m_engine->SetObjectShadowRadius(m_objectPart[0].object, radius);
- m_engine->SetObjectShadowColor(m_objectPart[0].object, color);
-#endif
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionbee.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motionbee.h"
+
+#include "old/modfile.h"
+#include "physics/physics.h"
+
+
+
+#define ADJUST_ANGLE false // true -> adjusts the angles of the members
+const float START_TIME = 1000.0f; // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionBee::CMotionBee(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeMarch = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLastAction = -1;
+ m_bArmStop = false;
+}
+
+// Object's destructor.
+
+CMotionBee::~CMotionBee()
+{
+}
+
+
+// Removes an object.
+
+void CMotionBee::DeleteObject(bool bAll)
+{
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+bool CMotionBee::Create(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 3+18+2 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+
+ pModFile->ReadModel("objects\\bee1.mod");
+ pModFile->CreateEngineObject(rank);
+
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have an obligatory collision
+ // with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
+ m_object->SetGlobalSphere(Math::Vector(-1.0f, 1.0f, 0.0f), 5.0f);
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\bee2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(1.6f, 0.3f, 0.0f));
+
+ // Creates the tail.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\bee3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(-0.8f, 0.0f, 0.0f));
+
+ // Creates a right-back thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(-0.3f, -0.1f, -0.2f));
+
+ // Creates a right-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 3);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates a right-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 4);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates two middle-right thighs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(0.3f, -0.1f, -0.4f));
+
+ // Creates two middle-right legs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 6);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates two middle-right feet.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 7);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates the right front thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, Math::Vector(1.0f, -0.1f, -0.7f));
+
+ // Creates the right front leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10, rank);
+ m_object->SetObjectParent(10, 9);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates the right front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(11, rank);
+ m_object->SetObjectParent(11, 10);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(11, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates a left-back thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(12, rank);
+ m_object->SetObjectParent(12, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(12, Math::Vector(-0.3f, -0.1f, 0.2f));
+ m_object->SetAngleY(12, Math::PI);
+
+ // Creates a left-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(13, rank);
+ m_object->SetObjectParent(13, 12);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(13, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates a left-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(14, rank);
+ m_object->SetObjectParent(14, 13);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(14, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates two middle-left thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(15, rank);
+ m_object->SetObjectParent(15, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(15, Math::Vector(0.3f, -0.1f, 0.4f));
+ m_object->SetAngleY(15, Math::PI);
+
+ // Creates two middle-left legs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(16, rank);
+ m_object->SetObjectParent(16, 15);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(16, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates two middle-left feet.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(17, rank);
+ m_object->SetObjectParent(17, 16);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(17, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates front-left thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(18, rank);
+ m_object->SetObjectParent(18, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(18, Math::Vector(1.0f, -0.1f, 0.7f));
+ m_object->SetAngleY(18, Math::PI);
+
+ // Creates front-left leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(19, rank);
+ m_object->SetObjectParent(19, 18);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(19, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates front-left foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(20, rank);
+ m_object->SetObjectParent(20, 19);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(20, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates the right wing.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(21, rank);
+ m_object->SetObjectParent(21, 0);
+ pModFile->ReadModel("objects\\bee7.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(21, Math::Vector(0.8f, 0.4f, -0.5f));
+
+ // Creates the left wing.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(22, rank);
+ m_object->SetObjectParent(22, 0);
+ pModFile->ReadModel("objects\\bee7.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(22, Math::Vector(0.8f, 0.4f, 0.5f));
+
+ m_object->CreateShadowCircle(6.0f, 0.5f);
+
+ CreatePhysics();
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+// Creates the physical object.
+
+void CMotionBee::CreatePhysics()
+{
+ Character* character;
+ int i;
+
+ int member_march[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 0,45,0, 0,45,0, 0,50,0, // t0: thighs 1..3
+ 30,-70,0, 20,-105,20, 25,-100,0, // t0: legs 1..3
+ -70,75,0, -30,80,0, -80,80,0, // t0: feet 1..3
+ // on the ground:
+ 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3
+ -15,-50,0, -20,-60,0, -10,-75,0, // t1: legs 1..3
+ -40,50,0, -25,15,0, -50,35,0, // t1: feet 1..3
+ // on the ground back:
+ 0,35,0, 0,30,0, 0,20,0, // t2: thighs 1..3
+ -20,-15,0, -30,-55,0, -25,-70,15, // t2: legs 1..3
+ -25,25,0, -20,60,0, -30,95,0, // t2: feet 1..3
+ };
+
+ int member_spec[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // ball carrier:
+ 0,45,0, 0,45,0, 0,50,0, // s0: thighs 1..3
+ -35,-70,0, -20,-85,-25, -25,-100,0, // s0: legs 1..3
+ -110,75,-15, -130,80,-25, -125,40,0, // s0: feet 1..3
+ // burning:
+ 0,45,0, 0,45,0, 0,50,0, // s1: thighs 1..3
+ -35,-70,0, -20,-85,-25, -25,-100,0, // s1: legs 1..3
+ -110,75,-15, -130,80,-25, -125,40,0, // s1: feet 1..3
+ // destroyed:
+ 0,45,0, 0,45,0, 0,50,0, // s2: thighs 1..3
+ -35,-70,0, -20,-85,-25, -25,-100,0, // s2: legs 1..3
+ -110,75,-15, -130,80,-25, -125,40,0, // s2: feet 1..3
+ };
+
+ m_physics->SetType(TYPE_FLYING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 3.0f;
+ character->wheelBack = 3.0f;
+ character->wheelLeft = 5.0f;
+ character->wheelRight = 5.0f;
+ character->height = 2.5f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 50.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+ m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
+ m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 40.0f);
+
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MB_MARCH+i] = member_march[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MB_SPEC+i] = member_spec[i];
+ }
+}
+
+
+// Management of an event.
+
+bool CMotionBee::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if ADJUST_ANGLE
+ int i;
+
+ if ( event.param == 'A' ) m_armTimeIndex++;
+ if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
+
+ if ( event.param == 'Q' ) m_armPartIndex++;
+ if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
+
+ if ( event.param == 'W' ) m_armMemberIndex++;
+ if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
+
+ i = m_armMemberIndex*3;
+ i += m_armPartIndex*3*3;
+ i += m_armTimeIndex*3*3*3;
+//? i += 3*3*3*3;
+
+ if ( event.param == 'E' ) m_armAngles[i+0] += 5;
+ if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
+ if ( event.param == 'R' ) m_armAngles[i+1] += 5;
+ if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
+ if ( event.param == 'T' ) m_armAngles[i+2] += 5;
+ if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
+
+ if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
+#endif
+ }
+
+ return true;
+}
+
+// Management of an event.
+
+bool CMotionBee::EventFrame(const Event &event)
+{
+ Math::Vector dir;
+ float s, a, prog;
+ int action, i, st, nd;
+ bool bStop;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.30f;
+ a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.00f);
+
+ if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armTimeMarch += (s)*event.rTime*0.15f;
+ m_armMember += (s+a)*event.rTime*0.15f;
+
+ bStop = ( a == 0.0f && s == 0.0f ); // stopped?
+ if ( !m_physics->RetLand() ) bStop = true;
+
+ if ( bStop )
+ {
+ prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
+ a = Math::Mod(m_armMember, 1.0f);
+ a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly
+ m_armMember += a;
+ }
+
+ action = MB_MARCH; // flying
+
+ m_actionType = -1;
+ if ( m_object->RetFret() != 0 ) m_actionType = MBS_HOLD; // carries the ball
+
+ if ( m_object->RetRuin() ) // destroyed?
+ {
+ m_actionType = MBS_RUIN;
+ }
+ if ( m_object->RetBurn() ) // burning?
+ {
+ m_actionType = MBS_BURN;
+ }
+
+ for ( i=0 ; i<6 ; i++ ) // the six legs
+ {
+ if ( m_actionType != -1 ) // special action in progress?
+ {
+ st = 3*3*3*3*MB_SPEC + 3*3*3*m_actionType + (i%3)*3;
+ nd = st;
+ }
+ else
+ {
+ if ( i < 3 ) prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
+ else prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
+ if ( m_bArmStop )
+ {
+ prog = (float)m_armTimeIndex/3.0f;
+ }
+ if ( prog < 0.33f ) // t0..t1 ?
+ {
+ prog = prog/0.33f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.67f ) // t1..t2 ?
+ {
+ prog = (prog-0.33f)/0.33f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.67f)/0.33f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ st = 3*3*3*3*action + st*3*3*3 + (i%3)*3;
+ nd = 3*3*3*3*action + nd*3*3*3 + (i%3)*3;
+ }
+
+ if ( i < 3 ) // right leg (1..3) ?
+ {
+ m_object->SetAngleX(3+3*i+0, Math::PropAngle(m_armAngles[st+ 0], m_armAngles[nd+ 0], prog));
+ m_object->SetAngleY(3+3*i+0, Math::PropAngle(m_armAngles[st+ 1], m_armAngles[nd+ 1], prog));
+ m_object->SetAngleZ(3+3*i+0, Math::PropAngle(m_armAngles[st+ 2], m_armAngles[nd+ 2], prog));
+ m_object->SetAngleX(3+3*i+1, Math::PropAngle(m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
+ m_object->SetAngleY(3+3*i+1, Math::PropAngle(m_armAngles[st+10], m_armAngles[nd+10], prog));
+ m_object->SetAngleZ(3+3*i+1, Math::PropAngle(m_armAngles[st+11], m_armAngles[nd+11], prog));
+ m_object->SetAngleX(3+3*i+2, Math::PropAngle(m_armAngles[st+18], m_armAngles[nd+18], prog));
+ m_object->SetAngleY(3+3*i+2, Math::PropAngle(m_armAngles[st+19], m_armAngles[nd+19], prog));
+ m_object->SetAngleZ(3+3*i+2, Math::PropAngle(m_armAngles[st+20], m_armAngles[nd+20], prog));
+ }
+ else // left leg(4..6) ?
+ {
+ m_object->SetAngleX(3+3*i+0, Math::PropAngle( -m_armAngles[st+ 0], -m_armAngles[nd+ 0], prog));
+ m_object->SetAngleY(3+3*i+0, Math::PropAngle(180-m_armAngles[st+ 1], 180-m_armAngles[nd+ 1], prog));
+ m_object->SetAngleZ(3+3*i+0, Math::PropAngle( -m_armAngles[st+ 2], -m_armAngles[nd+ 2], prog));
+ m_object->SetAngleX(3+3*i+1, Math::PropAngle( m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
+ m_object->SetAngleY(3+3*i+1, Math::PropAngle( -m_armAngles[st+10], -m_armAngles[nd+10], prog));
+ m_object->SetAngleZ(3+3*i+1, Math::PropAngle( -m_armAngles[st+11], -m_armAngles[nd+11], prog));
+ m_object->SetAngleX(3+3*i+2, Math::PropAngle( m_armAngles[st+18], m_armAngles[nd+18], prog));
+ m_object->SetAngleY(3+3*i+2, Math::PropAngle( -m_armAngles[st+19], -m_armAngles[nd+19], prog));
+ m_object->SetAngleZ(3+3*i+2, Math::PropAngle( -m_armAngles[st+20], -m_armAngles[nd+20], prog));
+ }
+ }
+
+#if ADJUST_ANGLE
+ if ( m_object->RetSelect() )
+ {
+ char s[100];
+ sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
+ m_engine->SetInfoText(4, s);
+ }
+#endif
+
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ if ( m_object->RetRuin() )
+ {
+ }
+ else if ( bStop || m_object->RetBurn() )
+ {
+ m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.7f)*0.15f+0.35f); // tail
+ }
+ else
+ {
+ a = Math::Mod(m_armTimeMarch, 1.0f);
+ if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
+ else a = 3.0f-4.0f*a; // 1..-1
+ dir.x = sinf(a)*0.05f;
+
+ s = Math::Mod(m_armTimeMarch/2.0f, 1.0f);
+ if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
+ else s = 3.0f-4.0f*s; // 1..-1
+ dir.z = sinf(s)*0.1f;
+
+ dir.y = 0.0f;
+ m_object->SetInclinaison(dir);
+
+ m_object->SetAngleZ(2, -sinf(a)*0.3f); // tail
+
+ a = Math::Mod(m_armMember-0.1f, 1.0f);
+ if ( a < 0.33f )
+ {
+ dir.y = -(1.0f-(a/0.33f))*0.3f;
+ }
+ else if ( a < 0.67f )
+ {
+ dir.y = 0.0f;
+ }
+ else
+ {
+ dir.y = -(a-0.67f)/0.33f*0.3f;
+ }
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ m_object->SetLinVibration(dir);
+ }
+ }
+
+ if ( m_physics->RetLand() )
+ {
+ if ( bStop ) prog = 0.05f;
+ else prog = 0.15f;
+ }
+ else
+ {
+ prog = 1.00f;
+ }
+
+#if 0
+ a = Math::Rand()*Math::PI/2.0f*prog;
+ m_object->SetAngleX(21, a); // right wing
+ a = -Math::Rand()*Math::PI/4.0f*prog;
+ m_object->SetAngleY(21, a);
+
+ a = -Math::Rand()*Math::PI/2.0f*prog;
+ m_object->SetAngleX(22, a); // left wing
+ a = Math::Rand()*Math::PI/4.0f*prog;
+ m_object->SetAngleY(22, a);
+#else
+ m_object->SetAngleX(21, (sinf(m_armTimeAbs*30.0f)+1.0f)*(Math::PI/4.0f)*prog);
+ m_object->SetAngleY(21, -Math::Rand()*Math::PI/6.0f*prog);
+
+ m_object->SetAngleX(22, -(sinf(m_armTimeAbs*30.0f)+1.0f)*(Math::PI/4.0f)*prog);
+ m_object->SetAngleY(22, Math::Rand()*Math::PI/6.0f*prog);
+#endif
+
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.4f)*0.20f); // head
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.9f)*0.10f); // head
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*2.1f)*0.50f); // head
+
+#if 0
+ h = m_terrain->RetFloorHeight(RetPosition(0));
+ radius = 4.0f+h/4.0f;
+ color.r = 0.3f+h/80.0f;
+ color.g = color.r;
+ color.b = color.r;
+ color.a = color.r;
+ m_engine->SetObjectShadowRadius(m_objectPart[0].object, radius);
+ m_engine->SetObjectShadowColor(m_objectPart[0].object, color);
+#endif
+
+ return true;
+}
+
+
diff --git a/src/object/motion/motionbee.h b/src/object/motion/motionbee.h
index 94ac7fa..aa8e5a6 100644
--- a/src/object/motion/motionbee.h
+++ b/src/object/motion/motionbee.h
@@ -1,66 +1,66 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionbee.h
-
-#pragma once
-
-
-#include "object/motion/motion.h"
-
-
-
-enum MotionBeeAction
-{
- MB_MARCH = 0,
- MB_SPEC = 1
-};
-
-enum MotionBeeSpecialAction
-{
- MBS_HOLD = 0,
- MBS_BURN = 1,
- MBS_RUIN = 2
-};
-
-
-class CMotionBee : public CMotion
-{
-public:
- CMotionBee(CInstanceManager* iMan, CObject* object);
- ~CMotionBee();
-
- void DeleteObject(bool bAll=false);
- bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- bool EventProcess(const Event &event);
-
-protected:
- void CreatePhysics();
- bool EventFrame(const Event &event);
-
-protected:
- float m_armMember;
- float m_armTimeAbs;
- float m_armTimeMarch;
- float m_armTimeAction;
- short m_armAngles[3*3*3*3*2];
- int m_armTimeIndex;
- int m_armPartIndex;
- int m_armMemberIndex;
- int m_armLastAction;
- bool m_bArmStop;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionbee.h
+
+#pragma once
+
+
+#include "object/motion/motion.h"
+
+
+
+enum MotionBeeAction
+{
+ MB_MARCH = 0,
+ MB_SPEC = 1
+};
+
+enum MotionBeeSpecialAction
+{
+ MBS_HOLD = 0,
+ MBS_BURN = 1,
+ MBS_RUIN = 2
+};
+
+
+class CMotionBee : public CMotion
+{
+public:
+ CMotionBee(CInstanceManager* iMan, CObject* object);
+ ~CMotionBee();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ bool EventProcess(const Event &event);
+
+protected:
+ void CreatePhysics();
+ bool EventFrame(const Event &event);
+
+protected:
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeMarch;
+ float m_armTimeAction;
+ short m_armAngles[3*3*3*3*2];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ bool m_bArmStop;
+};
+
diff --git a/src/object/motion/motionhuman.cpp b/src/object/motion/motionhuman.cpp
index 6bdcf7e..06db454 100644
--- a/src/object/motion/motionhuman.cpp
+++ b/src/object/motion/motionhuman.cpp
@@ -1,1770 +1,1770 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionhuman.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motionhuman.h"
-
-#include "old/modfile.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "math/geometry.h"
-#include "object/robotmain.h"
-#include "physics/physics.h"
-
-
-
-#define ADJUST_ANGLE false // true -> adjusts the angles of the members
-const int ADJUST_ACTION = (3*3*3*3*MH_SPEC+3*3*3*MHS_SATCOM);
-
-const float START_TIME = 1000.0f; // beginning of the relative time
-
-
-
-// Object's constructor.
-
-CMotionHuman::CMotionHuman(CInstanceManager* iMan, CObject* object)
- : CMotion(iMan, object)
-{
- m_partiReactor = -1;
- m_armMember = START_TIME;
- m_armTimeAbs = START_TIME;
- m_armTimeAction = START_TIME;
- m_armTimeSwim = START_TIME;
- m_armTimeIndex = 0;
- m_armPartIndex = 0;
- m_armMemberIndex = 0;
- m_armLastAction = -1;
- m_bArmStop = false;
- m_lastSoundMarch = 0.0f;
- m_lastSoundHhh = 0.0f;
- m_time = 0.0f;
- m_tired = 0.0f;
- m_bDisplayPerso = false;
-}
-
-// Object's constructor.
-
-CMotionHuman::~CMotionHuman()
-{
-}
-
-
-// Removes an object.
-
-void CMotionHuman::DeleteObject(bool bAll)
-{
- if ( m_partiReactor != -1 )
- {
- m_particule->DeleteParticule(m_partiReactor);
- m_partiReactor = -1;
- }
-}
-
-
-// Starts an action.
-
-Error CMotionHuman::SetAction(int action, float time)
-{
- CMotion::SetAction(action, time);
- m_time = 0.0f;
- return ERR_OK;
-}
-
-
-// Creates cosmonaut on the ground.
-
-bool CMotionHuman::Create(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- char filename[100];
- int rank, option, face, glasses;
-
- if ( m_engine->RetRestCreate() < 16 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- m_object->SetType(type);
- option = m_object->RetOption();
-
- if ( m_main->RetGamerOnlyHead() )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
- face = m_main->RetGamerFace();
- sprintf(filename, "objects\\human2h%d.mod", face+1);
- pModFile->ReadModel(filename);
- pModFile->CreateEngineObject(rank);
-
- glasses = m_main->RetGamerGlasses();
- if ( glasses != 0 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- sprintf(filename, "objects\\human2g%d.mod", glasses);
- pModFile->ReadModel(filename);
- pModFile->CreateEngineObject(rank);
- }
-
- CreatePhysics(type);
- m_object->SetFloorHeight(0.0f);
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
- }
-
- // Creates the main base.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
-
- if ( option == 0 ) // head in helmet?
- {
- pModFile->ReadModel("objects\\human1c.mod");
- }
- if ( option == 1 ) // head without helmet?
- {
- pModFile->ReadModel("objects\\human1h.mod");
- }
- if ( option == 2 ) // without a backpack?
- {
- pModFile->ReadModel("objects\\human1v.mod");
- }
- pModFile->CreateEngineObject(rank);
-
- m_object->SetPosition(0, pos);
- m_object->SetAngleY(0, angle);
-
- // A vehicle must have an obligatory collision with a sphere of center (0, y, 0) (see GetCrashSphere).
- m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 2.0f, SOUND_AIE, 0.20f);
- m_object->SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 4.0f);
-
- // Creates the head.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
-
- if ( type == OBJECT_HUMAN )
- {
- if ( option == 0 ) // head in helmet?
- {
- face = m_main->RetGamerFace();
- sprintf(filename, "objects\\human2c%d.mod", face+1);
- pModFile->ReadModel(filename);
- }
- if ( option == 1 || // head without helmet?
- option == 2 ) // without a backpack?
- {
- face = m_main->RetGamerFace();
- sprintf(filename, "objects\\human2h%d.mod", face+1);
- pModFile->ReadModel(filename);
- }
- }
- if ( type == OBJECT_TECH )
- {
- pModFile->ReadModel("objects\\human2t.mod");
- }
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(0.0f, 2.7f, 0.0f));
- if ( option == 1 || // head without helmet?
- option == 2 ) // without a backpack?
- {
- m_object->SetZoom(1, Math::Vector(1.0f, 1.05f, 1.0f));
- }
-
- // Creates the glasses.
- glasses = m_main->RetGamerGlasses();
- if ( glasses != 0 && type == OBJECT_HUMAN )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(15, rank);
- m_object->SetObjectParent(15, 1);
- sprintf(filename, "objects\\human2g%d.mod", glasses);
- pModFile->ReadModel(filename);
- pModFile->CreateEngineObject(rank);
- }
-
- // Creates the right arm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\human3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(0.0f, 2.3f, -1.2f));
- m_object->SetAngle(2, Math::Vector(90.0f*Math::PI/180.0f, 90.0f*Math::PI/180.0f, -50.0f*Math::PI/180.0f));
-
- // Creates the right forearm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\human4r.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(1.3f, 0.0f, 0.0f));
- m_object->SetAngle(3, Math::Vector(0.0f*Math::PI/180.0f, -20.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f));
-
- // Creates right hand.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(4, rank);
- m_object->SetObjectParent(4, 3);
- pModFile->ReadModel("objects\\human5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(4, Math::Vector(1.2f, 0.0f, 0.0f));
-
- // Creates the right thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(5, rank);
- m_object->SetObjectParent(5, 0);
- pModFile->ReadModel("objects\\human6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(5, Math::Vector(0.0f, 0.0f, -0.7f));
- m_object->SetAngle(5, Math::Vector(10.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f));
-
- // Creates the right leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 5);
- pModFile->ReadModel("objects\\human7.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(0.0f, -1.5f, 0.0f));
- m_object->SetAngle(6, Math::Vector(0.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f, -10.0f*Math::PI/180.0f));
-
- // Creates the right foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 6);
- pModFile->ReadModel("objects\\human8.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, -1.5f, 0.0f));
- m_object->SetAngle(7, Math::Vector(-10.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f));
-
- // Creates the left arm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 0);
- pModFile->ReadModel("objects\\human3.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(0.0f, 2.3f, 1.2f));
- m_object->SetAngle(8, Math::Vector(-90.0f*Math::PI/180.0f, -90.0f*Math::PI/180.0f, -50.0f*Math::PI/180.0f));
-
- // Creates the left forearm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(9, rank);
- m_object->SetObjectParent(9, 8);
- pModFile->ReadModel("objects\\human4l.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(9, Math::Vector(1.3f, 0.0f, 0.0f));
- m_object->SetAngle(9, Math::Vector(0.0f*Math::PI/180.0f, 20.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f));
-
- // Creates left hand.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(10, rank);
- m_object->SetObjectParent(10, 9);
- pModFile->ReadModel("objects\\human5.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(10, Math::Vector(1.2f, 0.0f, 0.0f));
-
- // Creates the left thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(11, rank);
- m_object->SetObjectParent(11, 0);
- pModFile->ReadModel("objects\\human6.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(11, Math::Vector(0.0f, 0.0f, 0.7f));
- m_object->SetAngle(11, Math::Vector(-10.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f));
-
- // Creates the left leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(12, rank);
- m_object->SetObjectParent(12, 11);
- pModFile->ReadModel("objects\\human7.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(12, Math::Vector(0.0f, -1.5f, 0.0f));
- m_object->SetAngle(12, Math::Vector(0.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f, -10.0f*Math::PI/180.0f));
-
- // Creates the left foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(13, rank);
- m_object->SetObjectParent(13, 12);
- pModFile->ReadModel("objects\\human8.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(13, Math::Vector(0.0f, -1.5f, 0.0f));
- m_object->SetAngle(13, Math::Vector(10.0f*Math::PI/180.0f, -5.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f));
-
- // Creates the neutron gun.
- if ( option != 2 ) // with backpack?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(14, rank);
- m_object->SetObjectParent(14, 0);
- pModFile->ReadModel("objects\\human9.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(14, Math::Vector(-1.5f, 0.3f, -1.35f));
- m_object->SetAngleZ(14, Math::PI);
- }
-
- m_object->CreateShadowCircle(2.0f, 0.8f);
-
- CreatePhysics(type);
- m_object->SetFloorHeight(0.0f);
-
- pos = m_object->RetPosition(0);
- m_object->SetPosition(0, pos); // to display the shadows immediately
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-// Creates the physical object.
-
-void CMotionHuman::CreatePhysics(ObjectType type)
-{
- Character* character;
- int i;
-
- int member_march[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
- 90,90,-50, 10,0,55, 0,0,0, // t0: arms/thighs/-
- 0,-20,0, -5,0,-110, 0,0,0, // t0: forearm/legs/-
- 0,0,0, -5,0,40, 0,0,0, // t0: hands/feet/-
- // on the ground:
- 125,115,-45, 10,0,50, 0,0,0, // t1: arms/thighs/-
- 0,-20,0, -5,0,-15, 0,0,0, // t1: forearm/legs/-
- 0,0,0, -5,0,0, 0,0,0, // t1: hands/feet/-
- // on the ground back:
- 25,55,-40, 10,0,-15, 0,0,0, // t2: arms/thighs/-
- 30,-50,40, -5,0,-55, 0,0,0, // t2: forearm/legs/-
- 0,0,0, -5,0,25, 0,0,0, // t2: hands/feet/-
- };
-
- int member_march_take[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
- 15,50,-50, 10,0,55, 0,0,0, // t0: arms/thighs/-
- 45,-70,10, -5,0,-110, 0,0,0, // t0: forearm/legs/-
- -10,25,0, -5,0,40, 0,0,0, // t0: hands/feet/-
- // on the ground:
- 15,50,-55, 10,0,50, 0,0,0, // t1: arms/thighs/-
- 45,-70,10, -5,0,-15, 0,0,0, // t1: forearm/legs/-
- -10,25,0, -5,0,0, 0,0,0, // t1: hands/feet/-
- // on the ground back:
- 15,50,-45, 10,0,-15, 0,0,0, // t2: arms/thighs/-
- 45,-70,10, -5,0,-55, 0,0,0, // t2: forearm/legs/-
- -10,25,0, -5,0,45, 0,0,0, // t2: hands/feet/-
- };
-
- int member_turn[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
- 90,90,-50, 10,0,30, 0,0,0, // t0: arms/thighs/-
- 0,-20,0, -5,0,-60, 0,0,0, // t0: forearm/legs/-
- 0,0,0, -5,0,30, 0,0,0, // t0: hands/feet/-
- // on the ground:
- 90,110,-45, 10,0,0, 0,0,0, // t1: arms/thighs/-
- 0,-20,0, -5,5,0, 0,0,0, // t1: forearm/legs/-
- 0,0,0, -5,10,0, 0,0,0, // t1: hands/feet/-
- // on the ground back:
- 90,70,-45, 10,0,0, 0,0,0, // t2: arms/thighs/-
- 0,-20,10, -5,-5,0, 0,0,0, // t2: forearm/legs/-
- 0,0,0, -5,-10,0, 0,0,0, // t2: hands/feet/-
- };
-
- int member_stop[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3,
- 90,90,-50, 10,0,5, 0,0,0, // arms/thighs/-
- 0,-20,0, 0,0,-10, 0,0,0, // forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // hands/feet/-
- //
- 90,90,-55, 10,0,5, 0,0,0, // arms/thighs/-
- 0,-15,0, 0,0,-10, 0,0,0, // forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // hands/feet/-
- //
- 90,90,-60, 10,0,5, 0,0,0, // arms/thighs/-
- 0,-10,0, 0,0,-10, 0,0,0, // forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // hands/feet/-
- };
-
- int member_fly[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3,
- -5,90,-60, 20,5,-25, 0,0,0, // arms/thighs/-
- 85,-40,-25, 10,0,-30, 0,0,0, // forearm/legs/-
- 40,10,25, 0,15,0, 0,0,0, // hands/feet/-
- //
- -15,90,-40, 20,5,-35, 0,0,0, // arms/thighs/-
- 85,-40,-25, 10,0,-40, 0,0,0, // forearm/legs/-
- 45,5,20, 0,15,0, 0,0,0, // hands/feet/-
- //
- -25,90,-50, 20,5,-20, 0,0,0, // arms/thighs/-
- 85,-40,-25, 10,0,-10, 0,0,0, // forearm/legs/-
- 30,15,25, 0,15,0, 0,0,0, // hands/feet/-
- };
-
- int member_swim[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3,
-#if 1
- 130,-70,200, 10,20,55, 0,0,0, // arms/thighs/-
- 115,-125,0, -5,0,-110, 0,0,0, // forearm/legs/-
- 0,0,0, -5,10,-5, 0,0,0, // hands/feet/-
- //
- 130,-95,115,55,5,5, 0,0,0, // arms/thighs/-
- 75,-50,25, -5,0,-15, 0,0,0, // forearm/legs/-
- 0,0,0, -5,5,-30, 0,0,0, // hands/feet/-
- //
- 130,-100,220,5,0,0, 0,0,0, // arms/thighs/-
- 150,5,0, -5,0,-15, 0,0,0, // forearm/legs/-
- 0,0,0, -5,30,-20, 0,0,0, // hands/feet/-
-#endif
-#if 0
- 130,-70,200,5,0,0, 0,0,0, // arms/thighs/-
- 115,-125,0, -5,0,-15, 0,0,0, // forearm/legs/-
- 0,0,0, -5,30,-20, 0,0,0, // hands/feet/-
- //
- 130,-95,115, 10,20,55, 0,0,0, // arms/thighs/-
- 75,-50,25, -5,0,-110, 0,0,0, // forearm/legs/-
- 0,0,0, -5,10,-5, 0,0,0, // hands/feet/-
- //
- 130,-100,220, 55,5,5, 0,0,0, // arms/thighs/-
- 150,5,0, -5,0,-15, 0,0,0, // forearm/legs/-
- 0,0,0, -5,5,-30, 0,0,0, // hands/feet/-
-#endif
-#if 0
- 130,-70,200, 55,5,5, 0,0,0, // arms/thighs/-
- 115,-125,0, -5,0,-15, 0,0,0, // forearm/legs/-
- 0,0,0, -5,5,-30, 0,0,0, // hands/feet/-
- //
- 130,-95,115, 5,0,0, 0,0,0, // arms/thighs/-
- 75,-50,25, -5,0,-15, 0,0,0, // forearm/legs/-
- 0,0,0, -5,30,-20, 0,0,0, // hands/feet/-
- //
- 130,-100,220, 10,20,55, 0,0,0, // arms/thighs/-
- 150,5,0, -5,0,-110, 0,0,0, // forearm/legs/-
- 0,0,0, -5,10,-5, 0,0,0, // hands/feet/-
-#endif
- };
-
- int member_spec[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // shooting:
- 65,5,-20, 10,0,40, 0,0,0, // s0: arms/thighs/-
- -50,-30,50, 0,0,-70, 0,0,0, // s0: forearm/legs/-
- 0,50,0, -10,0,35, 0,0,0, // s0: hands/feet/-
- // takes weapon:
- 160,135,-20,10,0,5, 0,0,0, // s1: arms/thighs/-
- 10,-60,40, 0,0,-10, 0,0,0, // s1: forearm/legs/-
- 0,-5,-25, -10,5,5, 0,0,0, // s1: hands/feet/-
- // carries earth:
- 25,40,-40, 10,0,60, 0,0,0, // s2: arms/thighs/-
- 0,-45,0, 0,0,-120, 0,0,0, // s2: forearm/legs/-
- 0,15,5, -10,0,70, 0,0,0, // s2: hands/feet/-
- // carries in front:
- 25,20,5, 10,0,55, 0,0,0, // s3: arms/thighs/-
- -15,-30,10, 0,0,-110, 0,0,0, // s3: forearm/legs/-
- 0,0,0, -10,0,65, 0,0,0, // s3: hands/feet/-
- // carries vertically:
- -30,15,-5, 10,0,15, 0,0,0, // s4: arms/thighs/-
- 0,-15,15, 0,0,-30, 0,0,0, // s4: forearm/legs/-
- 35,0,-15, -10,0,25, 0,0,0, // s4: hands/feet/-
- // rises:
- 15,50,-50, 10,0,5, 0,0,0, // s5: arms/thighs/-
- 45,-70,10, 0,0,-10, 0,0,0, // s5: forearm/legs/-
- -10,25,0, -10,5,5, 0,0,0, // s5: hands/feet/-
- // wins:
- 90,90,-30, 20,0,5, 0,0,0, // s6: arms/thighs/-
- 0,-90,0, -10,0,-10, 0,0,0, // s6: forearm/legs/-
- 0,25,0, -10,5,5, 0,0,0, // s6: hands/feet/-
- // lose:
- -70,45,35, 10,0,40, 0,0,0, // s7: arms/thighs/-
- 15,-95,-5, 0,0,-70, 0,0,0, // s7: forearm/legs/-
- 0,0,0, -10,0,35, 0,0,0, // s7: hands/feet/-
- // shooting death (falls):
- 90,90,-50, 10,0,5, 0,0,0, // s8: arms/thighs/-
- 0,-20,0, 0,0,-10, 0,0,0, // s8: forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // s8: hands/feet/-
- // shooting death (knees):
- 110,105,-5, 10,0,25, 0,0,0, // s9: arms/thighs/-
- 0,-40,20, 0,0,-120, 0,0,0, // s9: forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // s9: hands/feet/-
- // shooting death (knees):
- 110,120,-25, 10,0,25, 0,0,0, // s10: arms/thighs/-
- 0,-40,20, 0,0,-120, 0,0,0, // s10: forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // s10: hands/feet/-
- // shooting death (face down):
- 110,100,-25, 25,0,10, 0,0,0, // s11: arms/thighs/-
- 0,-40,20, 0,0,-25, 0,0,0, // s11: forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // s11: hands/feet/-
- // shooting death (face down):
- 110,100,-25, 25,0,10, 0,0,0, // s12: arms/thighs/-
- 0,-40,20, 0,0,-25, 0,0,0, // s12: forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // s12: hands/feet/-
- // drowned:
- 110,100,-25, 25,0,10, 0,0,0, // s13: arms/thighs/-
- 0,-40,20, 0,0,-25, 0,0,0, // s13: forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // s13: hands/feet/-
- // puts / removes flag:
- 85,45,-50, 10,0,60, 0,0,0, // s14: arms/thighs/-
- -60,15,65, 0,0,-105, 0,0,0, // s14: forearm/legs/-
- 0,10,0, -10,0,60, 0,0,0, // s14: hands/feet/-
- // reads SatCom:
- 70,30,-20, 10,0,5, 0,0,0, // s15: arms/thighs/-
- 115,-65,60, 0,0,-10, 0,0,0, // s15: forearm/legs/-
- 0,20,0, -10,5,5, 0,0,0, // s15: hands/feet/-
- };
-
- m_physics->SetType(TYPE_FLYING);
-
- character = m_object->RetCharacter();
- character->wheelFront = 4.0f;
- character->wheelBack = 4.0f;
- character->wheelLeft = 4.0f;
- character->wheelRight = 4.0f;
- character->height = 3.5f;
-
- if ( type == OBJECT_HUMAN )
- {
- m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 35.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 70.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 40.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
- m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
- m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
- m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
- m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 6.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 6.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 4.0f);
- }
- else
- {
- m_physics->SetLinMotionX(MO_ADVSPEED, 40.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 15.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 8.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 8.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 8.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 50.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
- m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
- m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
- m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
- m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.6f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.6f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 4.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 4.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 3.0f);
- }
-
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MH_MARCH+i] = member_march[i];
- }
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MH_MARCHTAKE+i] = member_march_take[i];
- }
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MH_TURN+i] = member_turn[i];
- }
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MH_STOP+i] = member_stop[i];
- }
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MH_FLY+i] = member_fly[i];
- }
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MH_SWIM+i] = member_swim[i];
- }
- for ( i=0 ; i<3*3*3*16 ; i++ )
- {
- m_armAngles[3*3*3*3*MH_SPEC+i] = member_spec[i];
- }
-}
-
-
-// Management of an event.
-
-bool CMotionHuman::EventProcess(const Event &event)
-{
- CMotion::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
-#if ADJUST_ANGLE
- int i;
-
- if ( event.param == 'A' ) m_armTimeIndex++;
- if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
-
- if ( event.param == 'Q' ) m_armPartIndex++;
- if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
-
- if ( event.param == 'W' ) m_armMemberIndex++;
- if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
-
- i = m_armMemberIndex*3;
- i += m_armPartIndex*3*3;
- i += m_armTimeIndex*3*3*3;
- i += ADJUST_ACTION;
-
- if ( event.param == 'E' ) m_armAngles[i+0] += 5;
- if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
- if ( event.param == 'R' ) m_armAngles[i+1] += 5;
- if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
- if ( event.param == 'T' ) m_armAngles[i+2] += 5;
- if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
-
- if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
-
- if ( event.param == 'Y' )
- {
- char s[100];
- sprintf(s, "index dans table = %d %d %d\n", i, i+9, i+18);
- OutputDebugString(s);
- }
-#endif
- }
-
- return true;
-}
-
-// Management of an event.
-
-bool CMotionHuman::EventFrame(const Event &event)
-{
- Math::Matrix* mat;
- Math::Vector dir, actual, pos, speed, pf;
- Math::Point center, dim, p2;
- float s, a, prog, rTime[2], lTime[2], time, rot, hr, hl;
- float al, ar, af;
- float tSt[9], tNd[9];
- float aa, bb, shield, deadFactor, level;
- int i, ii, st, nd, action, legAction, armAction;
- bool bOnBoard, bSwim, bStop;
-
- if ( m_engine->RetPause() )
- {
- if ( m_actionType == MHS_SATCOM )
- {
- m_progress += event.rTime*m_actionTime;
- }
- else
- {
- return true;
- }
- }
-
- bOnBoard = false;
- if ( m_object->RetSelect() &&
- m_camera->RetType() == CAMERA_ONBOARD )
- {
- bOnBoard = true;
- }
-
- if ( m_bDisplayPerso && m_main->RetGamerOnlyHead() )
- {
- m_time += event.rTime;
- m_object->SetLinVibration(Math::Vector(0.0f, -0.55f, 0.0f));
- m_object->SetCirVibration(Math::Vector(0.0f, m_main->RetPersoAngle(), 0.0f));
- return true;
- }
- if ( m_bDisplayPerso )
- {
- m_object->SetCirVibration(Math::Vector(0.0f, m_main->RetPersoAngle()+0.2f, 0.0f));
- }
-
- shield = m_object->RetShield();
- shield += event.rTime*(1.0f/120.0f); // regeneration in 120 seconds
- if ( shield > 1.0f ) shield = 1.0f;
- m_object->SetShield(shield);
-
- bSwim = m_physics->RetSwim();
-
-#if 0
- rot = m_physics->RetCirMotionY(MO_MOTSPEED);
- s = m_physics->RetLinMotionX(MO_REASPEED)*2.0f;
- a = m_physics->RetLinMotionX(MO_TERSPEED);
- if ( a < 0.0f ) // rises?
- {
- if ( s > 0.0f && s < 20.0f ) s = 20.0f; // moving slowly?
-//? if ( s < 0.0f && s > -10.0f ) s = 0.0f; // falling slowly?
- }
- if ( a > 0.0f && !bSwim ) // falls?
- {
- if ( s > 0.0f && s < 10.0f ) s = 0.0f; // moving slowly?
-//? if ( s < 0.0f && s > -5.0f ) s = -5.0f; // falling slowly?
- }
- a = fabs(rot*12.0f);
-
- if ( !m_physics->RetLand() && !bSwim ) // in flight?
- {
- s = 0.0f;
- }
-
- if ( m_object->RetFret() != 0 ) // carries something?
- {
- s *= 1.3f;
- }
-#else
- rot = m_physics->RetCirMotionY(MO_MOTSPEED);
-#if 0
- s = m_physics->RetLinMotionX(MO_REASPEED);
-#else
- a = m_physics->RetLinMotionX(MO_REASPEED);
- s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.2f;
- if ( fabs(a) > fabs(s) ) s = a; // the highest value
-#endif
- a = m_physics->RetLinMotionX(MO_TERSPEED);
- if ( a < 0.0f ) // rises?
- {
- a += m_physics->RetLinMotionX(MO_TERSLIDE);
- if ( a < 0.0f ) s -= a;
- }
- if ( a > 0.0f ) // falls?
- {
- a -= m_physics->RetLinMotionX(MO_TERSLIDE);
- if ( a > 0.0f ) s -= a;
- }
- s *= 2.0f;
- a = fabs(rot*12.0f);
-
- if ( !m_physics->RetLand() && !bSwim ) // in flight?
- {
- s = 0.0f;
- }
-
- if ( m_object->RetFret() != 0 ) // carries something?
- {
- s *= 1.3f;
- }
-#endif
-
- m_time += event.rTime;
- m_armTimeAbs += event.rTime;
- m_armTimeAction += event.rTime;
- m_armMember += s*event.rTime*0.05f;
-
- // Fatigue management when short.
- if ( m_physics->RetLand() && s != 0.0f ) // on the ground?
- {
- m_tired += event.rTime*0.1f;
- if ( m_tired > 1.0f )
- {
- m_tired = 1.0f;
- if ( m_lastSoundHhh > 3.0f ) m_lastSoundHhh = 0.5f;
- }
- }
- else
- {
- m_tired -= event.rTime*0.2f;
- if ( m_tired < 0.0f ) m_tired = 0.0f;
- }
-
- if ( bSwim ) // swims?
- {
- s += fabs(m_physics->RetLinMotionY(MO_REASPEED)*2.0f);
- a *= 2.0f;
- m_armTimeSwim += Math::Min(Math::Max(s,a,3.0f),15.0f)*event.rTime*0.05f;
- }
-
- bStop = ( s == 0.0f ); // stop?
- prog = 0.0f;
-
- if ( m_physics->RetLand() ) // on the ground?
- {
- if ( s == 0.0f && a == 0.0f )
- {
- action = MH_STOP; // stop
- rTime[0] = rTime[1] = m_armTimeAbs*0.21f;
- lTime[0] = lTime[1] = m_armTimeAbs*0.25f;
- m_armMember = START_TIME;
- }
- else
- {
- if ( s == 0.0f )
- {
- action = MH_TURN; // turn
- rTime[0] = rTime[1] = m_armTimeAbs;
- lTime[0] = lTime[1] = m_armTimeAbs+0.5f;
- if ( rot < 0.0f )
- {
- rTime[1] = 1000000.0f-rTime[1];
- }
- else
- {
- lTime[1] = 1000000.0f-lTime[1];
- }
- m_armMember = START_TIME;
- }
- else
- {
- action = MH_MARCH; // walking
- if ( m_object->RetFret() != 0 ) action = MH_MARCHTAKE; // take walking
- rTime[0] = rTime[1] = m_armMember;
- lTime[0] = lTime[1] = m_armMember+0.5f;
- }
- }
- if ( bSwim )
- {
- rTime[0] *= 0.6f;
- rTime[1] *= 0.6f;
- lTime[0] = rTime[0]+0.5f;
- lTime[1] = rTime[1]+0.5f;
- }
- }
- else
- {
- if ( bSwim )
- {
- action = MH_SWIM; // swim
- rTime[0] = rTime[1] = m_armTimeSwim;
- lTime[0] = lTime[1] = m_armTimeSwim;
- }
- else
- {
- action = MH_FLY; // fly
- rTime[0] = rTime[1] = m_armTimeAbs*0.30f;
- lTime[0] = lTime[1] = m_armTimeAbs*0.31f;
- m_armMember = START_TIME;
- }
- }
-
- if ( action != m_armLastAction )
- {
- m_armLastAction = action;
- m_armTimeAction = 0.0f;
- }
-
- armAction = action;
- legAction = action;
-
- if ( m_object->RetFret() != 0 ) // carries something?
- {
- armAction = MH_MARCHTAKE; // take walking
- }
-
- if ( m_physics->RetLand() ) // on the ground?
- {
- a = m_object->RetAngleY(0);
- pos = m_object->RetPosition(0);
- m_terrain->MoveOnFloor(pos);
-
- pf.x = pos.x+cosf(a+Math::PI*1.5f)*0.7f;
- pf.y = pos.y;
- pf.z = pos.z-sinf(a+Math::PI*1.5f)*0.7f;
- m_terrain->MoveOnFloor(pf);
- al = atanf((pf.y-pos.y)/0.7f); // angle for left leg
-
- pf = pos;
- pf.x = pos.x+cosf(a+Math::PI*0.5f)*0.7f;
- pf.y = pos.y;
- pf.z = pos.z-sinf(a+Math::PI*0.5f)*0.7f;
- m_terrain->MoveOnFloor(pf);
- ar = atanf((pf.y-pos.y)/0.7f); // angle to right leg
-
- pf.x = pos.x+cosf(a+Math::PI)*0.3f;
- pf.y = pos.y;
- pf.z = pos.z-sinf(a+Math::PI)*0.3f;
- m_terrain->MoveOnFloor(pf);
- af = atanf((pf.y-pos.y)/0.3f); // angle for feet
- }
- else
- {
- al = 0.0f;
- ar = 0.0f;
- af = 0.0f;
- }
-
- for ( i=0 ; i<4 ; i++ ) // 4 members
- {
- if ( m_bArmStop ) // focus?
- {
- st = ADJUST_ACTION + (i%2)*3;
- nd = st;
- time = 100.0f;
- m_armTimeAction = 0.0f;
- }
- else if ( m_actionType != -1 ) // special action in progress?
- {
- st = 3*3*3*3*MH_SPEC + 3*3*3*m_actionType + (i%2)*3;
- nd = st;
- time = event.rTime*m_actionTime;
- m_armTimeAction = 0.0f;
- }
- else
- {
- if ( i < 2 ) prog = Math::Mod(rTime[i%2], 1.0f);
- else prog = Math::Mod(lTime[i%2], 1.0f);
- if ( prog < 0.25f ) // t0..t1 ?
- {
- prog = prog/0.25f; // 0..1
- st = 0; // index start
- nd = 1; // index end
- }
- else if ( prog < 0.75f ) // t1..t2 ?
- {
- prog = (prog-0.25f)/0.50f; // 0..1
- st = 1; // index start
- nd = 2; // index end
- }
- else // t2..t0 ?
- {
- prog = (prog-0.75f)/0.25f; // 0..1
- st = 2; // index start
- nd = 0; // index end
- }
- if ( i%2 == 0 ) // arm?
- {
- st = 3*3*3*3*armAction + st*3*3*3 + (i%2)*3;
- nd = 3*3*3*3*armAction + nd*3*3*3 + (i%2)*3;
- }
- else // leg?
- {
- st = 3*3*3*3*legAction + st*3*3*3 + (i%2)*3;
- nd = 3*3*3*3*legAction + nd*3*3*3 + (i%2)*3;
- }
-
- // Less soft ...
- time = event.rTime*(5.0f+Math::Min(m_armTimeAction*50.0f, 100.0f));
- if ( bSwim ) time *= 0.25f;
- }
-
- tSt[0] = m_armAngles[st+ 0]; // x
- tSt[1] = m_armAngles[st+ 1]; // y
- tSt[2] = m_armAngles[st+ 2]; // z
- tSt[3] = m_armAngles[st+ 9]; // x
- tSt[4] = m_armAngles[st+10]; // y
- tSt[5] = m_armAngles[st+11]; // z
- tSt[6] = m_armAngles[st+18]; // x
- tSt[7] = m_armAngles[st+19]; // y
- tSt[8] = m_armAngles[st+20]; // z
-
- tNd[0] = m_armAngles[nd+ 0]; // x
- tNd[1] = m_armAngles[nd+ 1]; // y
- tNd[2] = m_armAngles[nd+ 2]; // z
- tNd[3] = m_armAngles[nd+ 9]; // x
- tNd[4] = m_armAngles[nd+10]; // y
- tNd[5] = m_armAngles[nd+11]; // z
- tNd[6] = m_armAngles[nd+18]; // x
- tNd[7] = m_armAngles[nd+19]; // y
- tNd[8] = m_armAngles[nd+20]; // z
-
- aa = 0.5f;
- if ( i%2 == 0 ) // arm?
- {
- if ( m_object->RetFret() == 0 ) // does nothing?
- {
- aa = 2.0f; // moves a lot
- }
- else
- {
- aa = 0.0f; // immobile
- }
- }
-
- if ( i < 2 ) // left?
- {
- bb = sinf(m_time*1.1f)*aa; tSt[0] += bb; tNd[0] += bb;
- bb = sinf(m_time*1.0f)*aa; tSt[1] += bb; tNd[1] += bb;
- bb = sinf(m_time*1.2f)*aa; tSt[2] += bb; tNd[2] += bb;
- bb = sinf(m_time*2.5f)*aa; tSt[3] += bb; tNd[3] += bb;
- bb = sinf(m_time*2.0f)*aa; tSt[4] += bb; tNd[4] += bb;
- bb = sinf(m_time*3.8f)*aa; tSt[5] += bb; tNd[5] += bb;
- bb = sinf(m_time*3.0f)*aa; tSt[6] += bb; tNd[6] += bb;
- bb = sinf(m_time*2.3f)*aa; tSt[7] += bb; tNd[7] += bb;
- bb = sinf(m_time*4.0f)*aa; tSt[8] += bb; tNd[8] += bb;
- }
- else // right?
- {
- bb = sinf(m_time*0.9f)*aa; tSt[0] += bb; tNd[0] += bb;
- bb = sinf(m_time*1.2f)*aa; tSt[1] += bb; tNd[1] += bb;
- bb = sinf(m_time*1.4f)*aa; tSt[2] += bb; tNd[2] += bb;
- bb = sinf(m_time*2.9f)*aa; tSt[3] += bb; tNd[3] += bb;
- bb = sinf(m_time*1.4f)*aa; tSt[4] += bb; tNd[4] += bb;
- bb = sinf(m_time*3.1f)*aa; tSt[5] += bb; tNd[5] += bb;
- bb = sinf(m_time*3.7f)*aa; tSt[6] += bb; tNd[6] += bb;
- bb = sinf(m_time*2.0f)*aa; tSt[7] += bb; tNd[7] += bb;
- bb = sinf(m_time*3.1f)*aa; tSt[8] += bb; tNd[8] += bb;
- }
-
-#if 1
- if ( i%2 == 1 && // leg?
- m_actionType == -1 ) // no special action?
- {
- if ( i == 1 ) // right leg?
- {
- ii = 5;
- a = ar*0.25f;
- }
- else
- {
- ii = 11;
- a = al*0.25f;
- }
- if ( a < -0.2f ) a = -0.2f;
- if ( a > 0.2f ) a = 0.2f;
-
- pos = m_object->RetPosition(ii+0);
- pos.y = 0.0f+a;
- m_object->SetPosition(ii+0, pos); // lengthens / shortcuts thigh
-
- pos = m_object->RetPosition(ii+1);
- pos.y = -1.5f+a;
- m_object->SetPosition(ii+1, pos); // lengthens / shortcuts leg
-
- pos = m_object->RetPosition(ii+2);
- pos.y = -1.5f+a;
- m_object->SetPosition(ii+2, pos); // lengthens / shortcuts foot
-
- if ( i == 1 ) // right leg?
- {
- aa = (ar*180.0f/Math::PI*0.5f);
- }
- else // left leg?
- {
- aa = (al*180.0f/Math::PI*0.5f);
- }
- tSt[6] += aa;
- tNd[6] += aa; // increases the angle X of the foot
-
- if ( i == 1 ) // right leg?
- {
- aa = (ar*180.0f/Math::PI);
- }
- else // left leg?
- {
- aa = (al*180.0f/Math::PI);
- }
- if ( aa < 0.0f ) aa = 0.0f;
- if ( aa > 30.0f ) aa = 30.0f;
-
- tSt[2] += aa;
- tNd[2] += aa; // increases the angle Z of the thigh
- tSt[5] -= aa*2;
- tNd[5] -= aa*2; // increases the angle Z of the leg
- tSt[8] += aa;
- tNd[8] += aa; // increases the angle Z of the foot
-
- aa = (af*180.0f/Math::PI)*0.7f;
- if ( aa < -30.0f ) aa = -30.0f;
- if ( aa > 30.0f ) aa = 30.0f;
-
- tSt[8] -= aa;
- tNd[8] -= aa; // increases the angle Z of the foot
- }
-#endif
-
- if ( m_actionType == MHS_DEADw ) // drowned?
- {
- if ( m_progress < 0.5f )
- {
- deadFactor = m_progress/0.5f;
- }
- else
- {
- deadFactor = 1.0f-(m_progress-0.5f)/0.5f;
- }
- if ( deadFactor < 0.0f ) deadFactor = 0.0f;
- if ( deadFactor > 1.0f ) deadFactor = 1.0f;
-
- for ( ii=0 ; ii<9 ; ii++ )
- {
- tSt[ii] += Math::Rand()*20.0f*deadFactor;
- tNd[ii] = tSt[ii];
- }
- time = 100.0f;
- }
-
- if ( i < 2 ) // right member (0..1) ?
- {
- m_object->SetAngleX(2+3*i+0, Math::Smooth(m_object->RetAngleX(2+3*i+0), Math::PropAngle(tSt[0], tNd[0], prog), time));
- m_object->SetAngleY(2+3*i+0, Math::Smooth(m_object->RetAngleY(2+3*i+0), Math::PropAngle(tSt[1], tNd[1], prog), time));
- m_object->SetAngleZ(2+3*i+0, Math::Smooth(m_object->RetAngleZ(2+3*i+0), Math::PropAngle(tSt[2], tNd[2], prog), time));
- m_object->SetAngleX(2+3*i+1, Math::Smooth(m_object->RetAngleX(2+3*i+1), Math::PropAngle(tSt[3], tNd[3], prog), time));
- m_object->SetAngleY(2+3*i+1, Math::Smooth(m_object->RetAngleY(2+3*i+1), Math::PropAngle(tSt[4], tNd[4], prog), time));
- m_object->SetAngleZ(2+3*i+1, Math::Smooth(m_object->RetAngleZ(2+3*i+1), Math::PropAngle(tSt[5], tNd[5], prog), time));
- m_object->SetAngleX(2+3*i+2, Math::Smooth(m_object->RetAngleX(2+3*i+2), Math::PropAngle(tSt[6], tNd[6], prog), time));
- m_object->SetAngleY(2+3*i+2, Math::Smooth(m_object->RetAngleY(2+3*i+2), Math::PropAngle(tSt[7], tNd[7], prog), time));
- m_object->SetAngleZ(2+3*i+2, Math::Smooth(m_object->RetAngleZ(2+3*i+2), Math::PropAngle(tSt[8], tNd[8], prog), time));
- }
- else // left member (2..3) ?
- {
- m_object->SetAngleX(2+3*i+0, Math::Smooth(m_object->RetAngleX(2+3*i+0), Math::PropAngle(-tSt[0], -tNd[0], prog), time));
- m_object->SetAngleY(2+3*i+0, Math::Smooth(m_object->RetAngleY(2+3*i+0), Math::PropAngle(-tSt[1], -tNd[1], prog), time));
- m_object->SetAngleZ(2+3*i+0, Math::Smooth(m_object->RetAngleZ(2+3*i+0), Math::PropAngle( tSt[2], tNd[2], prog), time));
- m_object->SetAngleX(2+3*i+1, Math::Smooth(m_object->RetAngleX(2+3*i+1), Math::PropAngle(-tSt[3], -tNd[3], prog), time));
- m_object->SetAngleY(2+3*i+1, Math::Smooth(m_object->RetAngleY(2+3*i+1), Math::PropAngle(-tSt[4], -tNd[4], prog), time));
- m_object->SetAngleZ(2+3*i+1, Math::Smooth(m_object->RetAngleZ(2+3*i+1), Math::PropAngle( tSt[5], tNd[5], prog), time));
- m_object->SetAngleX(2+3*i+2, Math::Smooth(m_object->RetAngleX(2+3*i+2), Math::PropAngle(-tSt[6], -tNd[6], prog), time));
- m_object->SetAngleY(2+3*i+2, Math::Smooth(m_object->RetAngleY(2+3*i+2), Math::PropAngle(-tSt[7], -tNd[7], prog), time));
- m_object->SetAngleZ(2+3*i+2, Math::Smooth(m_object->RetAngleZ(2+3*i+2), Math::PropAngle( tSt[8], tNd[8], prog), time));
- }
- }
-
-#if ADJUST_ANGLE
- if ( m_object->RetSelect() )
- {
- char s[100];
- sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
- m_engine->SetInfoText(4, s);
- }
-#endif
-
- // calculates the height lowering as a function
- // of the position of the legs.
- hr = 1.5f*(1.0f-cosf(m_object->RetAngleZ(5))) +
- 1.5f*(1.0f-cosf(m_object->RetAngleZ(5)+m_object->RetAngleZ(6)));
- a = 1.0f*sinf(m_object->RetAngleZ(5)+m_object->RetAngleZ(6)+m_object->RetAngleZ(7));
- if ( a < 0.0f ) hr += a;
-
- hl = 1.5f*(1.0f-cosf(m_object->RetAngleZ(11))) +
- 1.5f*(1.0f-cosf(m_object->RetAngleZ(11)+m_object->RetAngleZ(12)));
- a = 1.0f*sinf(m_object->RetAngleZ(11)+m_object->RetAngleZ(12)+m_object->RetAngleZ(13));
- if ( a < 0.0f ) hl += a;
-
- hr = Math::Min(hr, hl);
-
- if ( m_actionType == MHS_FIRE ) // shooting?
- {
- time = event.rTime*m_actionTime;
-
- dir.x = (Math::Rand()-0.5f)/8.0f;
- dir.z = (Math::Rand()-0.5f)/8.0f;
- dir.y = -0.5f; // slightly lower
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
-//? dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.y = -hr;
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetLinVibration(dir);
-
- dir.x = 0.0f;
- dir.y = (Math::Rand()-0.5f)/3.0f;
- dir.z = -0.1f; // slightly leaning forward
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
- }
- else if ( m_actionType == MHS_TAKE || // carrying?
- m_actionType == MHS_TAKEOTHER ) // flag?
- {
- time = event.rTime*m_actionTime*2.0f;
-
- dir.x = 0.0f;
- dir.z = 0.0f;
- dir.y = -1.5f; // slightly lower
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
-//? dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.y = -hr;
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetLinVibration(dir);
-
- dir.x = 0.0f;
- dir.y = 0.0f;
- dir.z = -0.2f;
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
- }
- else if ( m_actionType == MHS_TAKEHIGH ) // carrying?
- {
- time = event.rTime*m_actionTime*2.0f;
-
- dir.x = 0.4f; // slightly forward
- dir.z = 0.0f;
- dir.y = 0.0f;
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
-//? dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.y = -hr;
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetLinVibration(dir);
-
- dir.x = 0.0f;
- dir.y = 0.0f;
- dir.z = -0.2f;
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
- }
- else if ( m_actionType == MHS_FLAG ) // flag?
- {
- time = event.rTime*m_actionTime*2.0f;
-
- dir.x = 0.0f;
- dir.z = 0.0f;
- dir.y = -2.0f; // slightly lower
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
-//? dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.y = -hr;
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetLinVibration(dir);
-
- dir.x = 0.0f;
- dir.y = 0.0f;
- dir.z = -0.4f;
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
- }
- else if ( m_actionType == MHS_DEADg ) // shooting death (falls)?
- {
- if ( m_physics->RetLand() ) // on the ground?
- {
- SetAction(MHS_DEADg1, 0.5f); // knees
- }
- }
- else if ( m_actionType == MHS_DEADg1 ) // shooting death (knees)?
- {
- prog = m_progress;
- if ( prog >= 1.0f )
- {
- prog = 1.0f;
-
- for ( i=0 ; i<10 ; i++ )
- {
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*4.0f;
- pos.z += (Math::Rand()-0.5f)*4.0f;
- m_terrain->MoveOnFloor(pos);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 1.2f+Math::Rand()*1.2f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f);
- }
- m_sound->Play(SOUND_BOUMv, m_object->RetPosition(0));
-
- SetAction(MHS_DEADg2, 1.0f); // expects knees
- }
-
- time = 100.0f;
-
- dir.x = 0.0f;
- dir.z = 0.0f;
- dir.y = -1.5f*prog;
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetLinVibration(dir);
-
- dir.x = 0.0f;
- dir.y = 0.0f;
- dir.z = -(20.0f*Math::PI/180.0f)*prog;
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
- }
- else if ( m_actionType == MHS_DEADg2 ) // shooting death (knees)?
- {
- if ( m_progress >= 1.0f )
- {
- SetAction(MHS_DEADg3, 1.0f); // face down
- }
-
- time = 100.0f;
-
- dir.x = 0.0f;
- dir.z = 0.0f;
- dir.y = -1.5f;
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetLinVibration(dir);
-
- dir.x = 0.0f;
- dir.y = 0.0f;
- dir.z = -(20.0f*Math::PI/180.0f);
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
- }
- else if ( m_actionType == MHS_DEADg3 ) // shooting death (face down)?
- {
- prog = m_progress;
- if ( prog >= 1.0f )
- {
- prog = 1.0f;
-
- for ( i=0 ; i<20 ; i++ )
- {
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*8.0f;
- pos.z += (Math::Rand()-0.5f)*8.0f;
- m_terrain->MoveOnFloor(pos);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 2.0f+Math::Rand()*1.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f);
- }
- m_sound->Play(SOUND_BOUMv, m_object->RetPosition(0));
-
- SetAction(MHS_DEADg4, 3.0f); // expects face down
- }
-
- time = 100.0f;
- prog = powf(prog, 3.0f);
-
- dir.y = -(1.5f+1.5f*prog);
- dir.x = 0.0f;
- dir.z = 0.0f;
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetLinVibration(dir);
-
- dir.z = -((20.0f*Math::PI/180.0f)+(70.0f*Math::PI/180.0f)*prog);
- dir.x = 0.0f;
- dir.y = 0.0f;
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
- }
- else if ( m_actionType == MHS_DEADg4 ) // shooting death (face down)?
- {
- if ( m_progress >= 1.0f )
- {
- m_object->SetEnable(false);
- }
-
- time = 100.0f;
-
- dir.y = -(1.5f+1.5f);
- dir.x = 0.0f;
- dir.z = 0.0f;
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetLinVibration(dir);
-
- dir.z = -((20.0f*Math::PI/180.0f)+(70.0f*Math::PI/180.0f));
- dir.x = 0.0f;
- dir.y = 0.0f;
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
- }
- else if ( m_actionType == MHS_DEADw ) // drowned?
- {
- pos = m_object->RetPosition(0);
- level = m_water->RetLevel()-0.5f;
- if ( pos.y < level )
- {
- pos.y += 4.0f*event.rTime; // back to the surface
- if ( pos.y > level ) pos.y = level;
- m_object->SetPosition(0, pos);
- }
- if ( pos.y > level )
- {
- pos.y -= 10.0f*event.rTime; // down quickly
- if ( pos.y < level ) pos.y = level;
- m_object->SetPosition(0, pos);
- }
-
- prog = m_progress;
- if ( prog >= 1.0f )
- {
- prog = 1.0f;
- if ( pos.y >= level ) m_object->SetEnable(false);
- }
-
- prog *= 2.0f;
- if ( prog > 1.0f ) prog = 1.0f;
-
- time = 100.0f;
-
- dir.z = -(90.0f*Math::PI/180.0f)*prog;
- dir.x = Math::Rand()*0.3f*deadFactor;
- dir.y = Math::Rand()*0.3f*deadFactor;
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
-
- m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- }
- else if ( m_actionType == MHS_LOST ) // lost?
- {
- time = m_time;
- if ( time < 10.0f ) time *= time/10.0f; // starts slowly
-
- dir.x = time*2.0f;
- dir.y = sinf(m_time*0.8f)*0.8f;
- dir.z = sinf(m_time*0.6f)*0.5f;
- m_object->SetInclinaison(dir);
- SetInclinaison(dir);
-
-//? dir.x = -(sinf(time*0.05f+Math::PI*1.5f)+1.0f)*100.0f;
- // original code: Math::Min(time/30.0f) (?) changed to time/30.0f
- dir.x = -(powf(time/30.0f, 4.0f))*1000.0f; // from the distance
- dir.y = 0.0f;
- dir.z = 0.0f;
- m_object->SetLinVibration(dir);
- SetLinVibration(dir);
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(0.5f, 3.7f, 0.0f);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.y += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- pos = Transform(*mat, pos);
- speed.x = (Math::Rand()-0.5f)*0.5f;
- speed.y = (Math::Rand()-0.5f)*0.5f;
- speed.z = (Math::Rand()-0.5f)*0.5f;
- dim.x = 0.5f+Math::Rand()*0.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTILENS1, 5.0f, 0.0f, 0.0f);
- }
- else if ( m_actionType == MHS_SATCOM ) // look at the SatCom?
- {
- SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- SetLinVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
- }
- else
- {
- if ( m_physics->RetLand() ) // on the ground?
- {
- time = event.rTime*8.0f;
- if ( bSwim ) time *= 0.25f;
-
- if ( action == MH_MARCH ) // walking?
- {
- dir.x = sinf(Math::Mod(rTime[0]+0.5f, 1.0f)*Math::PI*2.0f)*0.10f;
- dir.y = sinf(Math::Mod(rTime[0]+0.6f, 1.0f)*Math::PI*2.0f)*0.20f;
- s = m_physics->RetLinMotionX(MO_REASPEED)*0.03f;
- }
- else if ( action == MH_MARCHTAKE ) // takes walking?
- {
- dir.x = sinf(Math::Mod(rTime[0]+0.5f, 1.0f)*Math::PI*2.0f)*0.10f;
- dir.y = sinf(Math::Mod(rTime[0]+0.6f, 1.0f)*Math::PI*2.0f)*0.15f;
- s = m_physics->RetLinMotionX(MO_REASPEED)*0.02f;
- }
- else
- {
- dir.x = 0.0f;
- dir.y = 0.0f;
- s = m_physics->RetLinMotionX(MO_REASPEED)*0.03f;
- }
-
- if ( s < 0.0f ) s *= 0.5f;
- dir.z = -s*0.7f;
-
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- if ( bOnBoard ) dir *= 0.3f;
- m_object->SetInclinaison(dir);
- SetInclinaison(dir);
-
- if ( action == MH_MARCH ) // walking?
- {
- p2.x = 0.0f;
- p2.y = sinf(Math::Mod(rTime[0]+0.5f, 1.0f)*Math::PI*2.0f)*0.5f;
- p2 = Math::RotatePoint(-m_object->RetAngleY(0), p2);
- dir.x = p2.x;
- dir.z = p2.y;
- dir.y = sinf(Math::Mod(rTime[0]*2.0f, 1.0f)*Math::PI*2.0f)*0.3f;
- }
- else if ( action == MH_MARCHTAKE ) // takes walking?
- {
- p2.x = 0.0f;
- p2.y = sinf(Math::Mod(rTime[0]+0.5f, 1.0f)*Math::PI*2.0f)*0.25f;
- p2 = Math::RotatePoint(-m_object->RetAngleY(0), p2);
- dir.x = p2.x;
- dir.z = p2.y;
- dir.y = sinf(Math::Mod(rTime[0]*2.0f, 1.0f)*Math::PI*2.0f)*0.05f-0.3f;
- }
- else
- {
- dir.x = 0.0f;
- dir.z = 0.0f;
- dir.y = 0.0f;
- }
-
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- if ( action == MH_MARCHTAKE ) // takes walking?
- {
- dir.y = -hr;
- }
- else
- {
- s = Math::Min(m_armTimeAction, 1.0f);
- dir.y = Math::Smooth(actual.y, dir.y, time)*s;
- dir.y += -hr*(1.0f-s);
- }
- dir.z = Math::Smooth(actual.z, dir.z, time);
- if ( bOnBoard ) dir *= 0.3f;
- m_object->SetLinVibration(dir);
-
- dir.x = 0.0f;
- dir.z = 0.0f;
- dir.y = 0.0f;
- SetCirVibration(dir);
- }
- }
-
- // Management of the head.
- if ( m_actionType == MHS_TAKE || // takes?
- m_actionType == MHS_FLAG ) // takes?
- {
- m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f-0.6f, event.rTime*5.0f));
- m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f);
- m_object->SetAngleY(1, Math::Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f));
- }
- else if ( m_actionType == MHS_TAKEOTHER || // takes?
- m_actionType == MHS_TAKEHIGH ) // takes?
- {
- m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f-0.3f, event.rTime*5.0f));
- m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f);
- m_object->SetAngleY(1, Math::Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f));
- }
- else if ( m_actionType == MHS_WIN ) // win
- {
- float factor = 0.6f+(sinf(m_armTimeAbs*0.5f)*0.40f);
- m_object->SetAngleZ(1, sinf(m_armTimeAbs*5.0f)*0.20f*factor);
- m_object->SetAngleX(1, sinf(m_armTimeAbs*0.6f)*0.10f);
- m_object->SetAngleY(1, sinf(m_armTimeAbs*1.5f)*0.15f);
- }
- else if ( m_actionType == MHS_LOST ) // lost?
- {
- float factor = 0.6f+(sinf(m_armTimeAbs*0.5f)*0.40f);
- m_object->SetAngleZ(1, sinf(m_armTimeAbs*0.6f)*0.10f);
- m_object->SetAngleX(1, sinf(m_armTimeAbs*0.7f)*0.10f);
- m_object->SetAngleY(1, sinf(m_armTimeAbs*3.0f)*0.30f*factor);
- }
- else if ( m_object->RetDead() ) // dead?
- {
- }
- else
- {
- m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f, event.rTime*5.0f));
- m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f);
- m_object->SetAngleY(1, Math::Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f));
- }
-
- if ( bOnBoard )
- {
- m_object->SetAngleZ(1, 0.0f);
- m_object->SetAngleX(1, 0.0f);
- m_object->SetAngleY(1, 0.0f);
- }
-
- // Steps sound effects.
- if ( legAction == MH_MARCH ||
- legAction == MH_MARCHTAKE )
- {
- Sound sound[2];
- float speed, synchro, volume[2], freq[2], hard, level;
-
- speed = m_physics->RetLinMotionX(MO_REASPEED);
-
- if ( m_object->RetFret() == 0 )
- {
- if ( speed > 0.0f ) synchro = 0.21f; // synchro forward
- else synchro = 0.29f; // synchro backward
- }
- else
- {
- if ( speed > 0.0f ) synchro = 0.15f; // synchro forward
- else synchro = 0.35f; // synchro backward
- }
- time = rTime[1]+synchro;
-
- if ( fabs(m_lastSoundMarch-time) > 0.4f &&
- Math::Mod(time, 0.5f) < 0.1f )
- {
- volume[0] = 0.5f;
- freq[0] = 1.0f;
- if ( m_object->RetFret() != 0 )
- {
-//? volume[0] *= 2.0f;
- freq[0] = 0.7f;
- }
- volume[1] = volume[0];
- freq[1] = freq[0];
- sound[0] = SOUND_CLICK;
- sound[1] = SOUND_CLICK;
-
- pos = m_object->RetPosition(0);
-
- level = m_water->RetLevel();
- if ( pos.y <= level+3.0f ) // underwater?
- {
- sound[0] = SOUND_STEPw;
- }
- else
- {
- hard = m_terrain->RetHardness(pos);
-
- if ( hard >= 0.875 )
- {
- sound[0] = SOUND_STEPm; // metal
- }
- else
- {
- hard /= 0.875;
- sound[0] = SOUND_STEPs; // smooth
- sound[1] = SOUND_STEPh; // hard
-
- volume[0] *= 1.0f-hard;
- volume[1] *= hard;
- if ( hard < 0.5f )
- {
- volume[0] *= 1.0f+hard*2.0f;
- volume[1] *= 1.0f+hard*2.0f;
- }
- else
- {
- volume[0] *= 3.0f-hard*2.0f;
- volume[1] *= 3.0f-hard*2.0f;
- }
- freq[0] *= 1.0f+hard;
- freq[1] *= 0.5f+hard;
- }
- }
-
- if ( sound[0] != SOUND_CLICK )
- {
- m_sound->Play(sound[0], pos, volume[0], freq[0]);
- }
- if ( sound[1] != SOUND_CLICK )
- {
- m_sound->Play(sound[1], pos, volume[1], freq[1]);
- }
- m_lastSoundMarch = time;
- }
- }
-
- if ( legAction == MH_SWIM )
- {
- time = rTime[0]+0.5f;
-
- if ( fabs(m_lastSoundMarch-time) > 0.9f &&
- Math::Mod(time, 1.0f) < 0.1f )
- {
- m_sound->Play(SOUND_SWIM, m_object->RetPosition(0), 0.5f);
- m_lastSoundMarch = time;
- }
- }
-
- m_lastSoundHhh -= event.rTime;
- if ( m_lastSoundHhh <= 0.0f &&
- m_object->RetSelect() &&
- m_object->RetOption() == 0 ) // helmet?
- {
- m_sound->Play(SOUND_HUMAN1, m_object->RetPosition(0), (0.5f+m_tired*0.2f));
- m_lastSoundHhh = (4.0f-m_tired*2.5f)+(4.0f-m_tired*2.5f)*Math::Rand();
- }
-
- return true;
-}
-
-
-// Management of the display mode when customizing the personal.
-
-void CMotionHuman::StartDisplayPerso()
-{
- m_bDisplayPerso = true;
-}
-
-void CMotionHuman::StopDisplayPerso()
-{
- m_bDisplayPerso = false;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionhuman.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motionhuman.h"
+
+#include "old/modfile.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "math/geometry.h"
+#include "object/robotmain.h"
+#include "physics/physics.h"
+
+
+
+#define ADJUST_ANGLE false // true -> adjusts the angles of the members
+const int ADJUST_ACTION = (3*3*3*3*MH_SPEC+3*3*3*MHS_SATCOM);
+
+const float START_TIME = 1000.0f; // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionHuman::CMotionHuman(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ m_partiReactor = -1;
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeSwim = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLastAction = -1;
+ m_bArmStop = false;
+ m_lastSoundMarch = 0.0f;
+ m_lastSoundHhh = 0.0f;
+ m_time = 0.0f;
+ m_tired = 0.0f;
+ m_bDisplayPerso = false;
+}
+
+// Object's constructor.
+
+CMotionHuman::~CMotionHuman()
+{
+}
+
+
+// Removes an object.
+
+void CMotionHuman::DeleteObject(bool bAll)
+{
+ if ( m_partiReactor != -1 )
+ {
+ m_particule->DeleteParticule(m_partiReactor);
+ m_partiReactor = -1;
+ }
+}
+
+
+// Starts an action.
+
+Error CMotionHuman::SetAction(int action, float time)
+{
+ CMotion::SetAction(action, time);
+ m_time = 0.0f;
+ return ERR_OK;
+}
+
+
+// Creates cosmonaut on the ground.
+
+bool CMotionHuman::Create(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ char filename[100];
+ int rank, option, face, glasses;
+
+ if ( m_engine->RetRestCreate() < 16 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+ option = m_object->RetOption();
+
+ if ( m_main->RetGamerOnlyHead() )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+ face = m_main->RetGamerFace();
+ sprintf(filename, "objects\\human2h%d.mod", face+1);
+ pModFile->ReadModel(filename);
+ pModFile->CreateEngineObject(rank);
+
+ glasses = m_main->RetGamerGlasses();
+ if ( glasses != 0 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ sprintf(filename, "objects\\human2g%d.mod", glasses);
+ pModFile->ReadModel(filename);
+ pModFile->CreateEngineObject(rank);
+ }
+
+ CreatePhysics(type);
+ m_object->SetFloorHeight(0.0f);
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+ }
+
+ // Creates the main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+
+ if ( option == 0 ) // head in helmet?
+ {
+ pModFile->ReadModel("objects\\human1c.mod");
+ }
+ if ( option == 1 ) // head without helmet?
+ {
+ pModFile->ReadModel("objects\\human1h.mod");
+ }
+ if ( option == 2 ) // without a backpack?
+ {
+ pModFile->ReadModel("objects\\human1v.mod");
+ }
+ pModFile->CreateEngineObject(rank);
+
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have an obligatory collision with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 2.0f, SOUND_AIE, 0.20f);
+ m_object->SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 4.0f);
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+
+ if ( type == OBJECT_HUMAN )
+ {
+ if ( option == 0 ) // head in helmet?
+ {
+ face = m_main->RetGamerFace();
+ sprintf(filename, "objects\\human2c%d.mod", face+1);
+ pModFile->ReadModel(filename);
+ }
+ if ( option == 1 || // head without helmet?
+ option == 2 ) // without a backpack?
+ {
+ face = m_main->RetGamerFace();
+ sprintf(filename, "objects\\human2h%d.mod", face+1);
+ pModFile->ReadModel(filename);
+ }
+ }
+ if ( type == OBJECT_TECH )
+ {
+ pModFile->ReadModel("objects\\human2t.mod");
+ }
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(0.0f, 2.7f, 0.0f));
+ if ( option == 1 || // head without helmet?
+ option == 2 ) // without a backpack?
+ {
+ m_object->SetZoom(1, Math::Vector(1.0f, 1.05f, 1.0f));
+ }
+
+ // Creates the glasses.
+ glasses = m_main->RetGamerGlasses();
+ if ( glasses != 0 && type == OBJECT_HUMAN )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(15, rank);
+ m_object->SetObjectParent(15, 1);
+ sprintf(filename, "objects\\human2g%d.mod", glasses);
+ pModFile->ReadModel(filename);
+ pModFile->CreateEngineObject(rank);
+ }
+
+ // Creates the right arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\human3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(0.0f, 2.3f, -1.2f));
+ m_object->SetAngle(2, Math::Vector(90.0f*Math::PI/180.0f, 90.0f*Math::PI/180.0f, -50.0f*Math::PI/180.0f));
+
+ // Creates the right forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\human4r.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(1.3f, 0.0f, 0.0f));
+ m_object->SetAngle(3, Math::Vector(0.0f*Math::PI/180.0f, -20.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f));
+
+ // Creates right hand.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 3);
+ pModFile->ReadModel("objects\\human5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, Math::Vector(1.2f, 0.0f, 0.0f));
+
+ // Creates the right thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 0);
+ pModFile->ReadModel("objects\\human6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, Math::Vector(0.0f, 0.0f, -0.7f));
+ m_object->SetAngle(5, Math::Vector(10.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f));
+
+ // Creates the right leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 5);
+ pModFile->ReadModel("objects\\human7.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(0.0f, -1.5f, 0.0f));
+ m_object->SetAngle(6, Math::Vector(0.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f, -10.0f*Math::PI/180.0f));
+
+ // Creates the right foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 6);
+ pModFile->ReadModel("objects\\human8.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, -1.5f, 0.0f));
+ m_object->SetAngle(7, Math::Vector(-10.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f));
+
+ // Creates the left arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\human3.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(0.0f, 2.3f, 1.2f));
+ m_object->SetAngle(8, Math::Vector(-90.0f*Math::PI/180.0f, -90.0f*Math::PI/180.0f, -50.0f*Math::PI/180.0f));
+
+ // Creates the left forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 8);
+ pModFile->ReadModel("objects\\human4l.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, Math::Vector(1.3f, 0.0f, 0.0f));
+ m_object->SetAngle(9, Math::Vector(0.0f*Math::PI/180.0f, 20.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f));
+
+ // Creates left hand.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10, rank);
+ m_object->SetObjectParent(10, 9);
+ pModFile->ReadModel("objects\\human5.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10, Math::Vector(1.2f, 0.0f, 0.0f));
+
+ // Creates the left thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(11, rank);
+ m_object->SetObjectParent(11, 0);
+ pModFile->ReadModel("objects\\human6.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(11, Math::Vector(0.0f, 0.0f, 0.7f));
+ m_object->SetAngle(11, Math::Vector(-10.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f));
+
+ // Creates the left leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(12, rank);
+ m_object->SetObjectParent(12, 11);
+ pModFile->ReadModel("objects\\human7.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(12, Math::Vector(0.0f, -1.5f, 0.0f));
+ m_object->SetAngle(12, Math::Vector(0.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f, -10.0f*Math::PI/180.0f));
+
+ // Creates the left foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(13, rank);
+ m_object->SetObjectParent(13, 12);
+ pModFile->ReadModel("objects\\human8.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(13, Math::Vector(0.0f, -1.5f, 0.0f));
+ m_object->SetAngle(13, Math::Vector(10.0f*Math::PI/180.0f, -5.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f));
+
+ // Creates the neutron gun.
+ if ( option != 2 ) // with backpack?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(14, rank);
+ m_object->SetObjectParent(14, 0);
+ pModFile->ReadModel("objects\\human9.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(14, Math::Vector(-1.5f, 0.3f, -1.35f));
+ m_object->SetAngleZ(14, Math::PI);
+ }
+
+ m_object->CreateShadowCircle(2.0f, 0.8f);
+
+ CreatePhysics(type);
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+// Creates the physical object.
+
+void CMotionHuman::CreatePhysics(ObjectType type)
+{
+ Character* character;
+ int i;
+
+ int member_march[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 90,90,-50, 10,0,55, 0,0,0, // t0: arms/thighs/-
+ 0,-20,0, -5,0,-110, 0,0,0, // t0: forearm/legs/-
+ 0,0,0, -5,0,40, 0,0,0, // t0: hands/feet/-
+ // on the ground:
+ 125,115,-45, 10,0,50, 0,0,0, // t1: arms/thighs/-
+ 0,-20,0, -5,0,-15, 0,0,0, // t1: forearm/legs/-
+ 0,0,0, -5,0,0, 0,0,0, // t1: hands/feet/-
+ // on the ground back:
+ 25,55,-40, 10,0,-15, 0,0,0, // t2: arms/thighs/-
+ 30,-50,40, -5,0,-55, 0,0,0, // t2: forearm/legs/-
+ 0,0,0, -5,0,25, 0,0,0, // t2: hands/feet/-
+ };
+
+ int member_march_take[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 15,50,-50, 10,0,55, 0,0,0, // t0: arms/thighs/-
+ 45,-70,10, -5,0,-110, 0,0,0, // t0: forearm/legs/-
+ -10,25,0, -5,0,40, 0,0,0, // t0: hands/feet/-
+ // on the ground:
+ 15,50,-55, 10,0,50, 0,0,0, // t1: arms/thighs/-
+ 45,-70,10, -5,0,-15, 0,0,0, // t1: forearm/legs/-
+ -10,25,0, -5,0,0, 0,0,0, // t1: hands/feet/-
+ // on the ground back:
+ 15,50,-45, 10,0,-15, 0,0,0, // t2: arms/thighs/-
+ 45,-70,10, -5,0,-55, 0,0,0, // t2: forearm/legs/-
+ -10,25,0, -5,0,45, 0,0,0, // t2: hands/feet/-
+ };
+
+ int member_turn[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 90,90,-50, 10,0,30, 0,0,0, // t0: arms/thighs/-
+ 0,-20,0, -5,0,-60, 0,0,0, // t0: forearm/legs/-
+ 0,0,0, -5,0,30, 0,0,0, // t0: hands/feet/-
+ // on the ground:
+ 90,110,-45, 10,0,0, 0,0,0, // t1: arms/thighs/-
+ 0,-20,0, -5,5,0, 0,0,0, // t1: forearm/legs/-
+ 0,0,0, -5,10,0, 0,0,0, // t1: hands/feet/-
+ // on the ground back:
+ 90,70,-45, 10,0,0, 0,0,0, // t2: arms/thighs/-
+ 0,-20,10, -5,-5,0, 0,0,0, // t2: forearm/legs/-
+ 0,0,0, -5,-10,0, 0,0,0, // t2: hands/feet/-
+ };
+
+ int member_stop[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3,
+ 90,90,-50, 10,0,5, 0,0,0, // arms/thighs/-
+ 0,-20,0, 0,0,-10, 0,0,0, // forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // hands/feet/-
+ //
+ 90,90,-55, 10,0,5, 0,0,0, // arms/thighs/-
+ 0,-15,0, 0,0,-10, 0,0,0, // forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // hands/feet/-
+ //
+ 90,90,-60, 10,0,5, 0,0,0, // arms/thighs/-
+ 0,-10,0, 0,0,-10, 0,0,0, // forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // hands/feet/-
+ };
+
+ int member_fly[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3,
+ -5,90,-60, 20,5,-25, 0,0,0, // arms/thighs/-
+ 85,-40,-25, 10,0,-30, 0,0,0, // forearm/legs/-
+ 40,10,25, 0,15,0, 0,0,0, // hands/feet/-
+ //
+ -15,90,-40, 20,5,-35, 0,0,0, // arms/thighs/-
+ 85,-40,-25, 10,0,-40, 0,0,0, // forearm/legs/-
+ 45,5,20, 0,15,0, 0,0,0, // hands/feet/-
+ //
+ -25,90,-50, 20,5,-20, 0,0,0, // arms/thighs/-
+ 85,-40,-25, 10,0,-10, 0,0,0, // forearm/legs/-
+ 30,15,25, 0,15,0, 0,0,0, // hands/feet/-
+ };
+
+ int member_swim[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3,
+#if 1
+ 130,-70,200, 10,20,55, 0,0,0, // arms/thighs/-
+ 115,-125,0, -5,0,-110, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,10,-5, 0,0,0, // hands/feet/-
+ //
+ 130,-95,115,55,5,5, 0,0,0, // arms/thighs/-
+ 75,-50,25, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,5,-30, 0,0,0, // hands/feet/-
+ //
+ 130,-100,220,5,0,0, 0,0,0, // arms/thighs/-
+ 150,5,0, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,30,-20, 0,0,0, // hands/feet/-
+#endif
+#if 0
+ 130,-70,200,5,0,0, 0,0,0, // arms/thighs/-
+ 115,-125,0, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,30,-20, 0,0,0, // hands/feet/-
+ //
+ 130,-95,115, 10,20,55, 0,0,0, // arms/thighs/-
+ 75,-50,25, -5,0,-110, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,10,-5, 0,0,0, // hands/feet/-
+ //
+ 130,-100,220, 55,5,5, 0,0,0, // arms/thighs/-
+ 150,5,0, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,5,-30, 0,0,0, // hands/feet/-
+#endif
+#if 0
+ 130,-70,200, 55,5,5, 0,0,0, // arms/thighs/-
+ 115,-125,0, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,5,-30, 0,0,0, // hands/feet/-
+ //
+ 130,-95,115, 5,0,0, 0,0,0, // arms/thighs/-
+ 75,-50,25, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,30,-20, 0,0,0, // hands/feet/-
+ //
+ 130,-100,220, 10,20,55, 0,0,0, // arms/thighs/-
+ 150,5,0, -5,0,-110, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,10,-5, 0,0,0, // hands/feet/-
+#endif
+ };
+
+ int member_spec[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // shooting:
+ 65,5,-20, 10,0,40, 0,0,0, // s0: arms/thighs/-
+ -50,-30,50, 0,0,-70, 0,0,0, // s0: forearm/legs/-
+ 0,50,0, -10,0,35, 0,0,0, // s0: hands/feet/-
+ // takes weapon:
+ 160,135,-20,10,0,5, 0,0,0, // s1: arms/thighs/-
+ 10,-60,40, 0,0,-10, 0,0,0, // s1: forearm/legs/-
+ 0,-5,-25, -10,5,5, 0,0,0, // s1: hands/feet/-
+ // carries earth:
+ 25,40,-40, 10,0,60, 0,0,0, // s2: arms/thighs/-
+ 0,-45,0, 0,0,-120, 0,0,0, // s2: forearm/legs/-
+ 0,15,5, -10,0,70, 0,0,0, // s2: hands/feet/-
+ // carries in front:
+ 25,20,5, 10,0,55, 0,0,0, // s3: arms/thighs/-
+ -15,-30,10, 0,0,-110, 0,0,0, // s3: forearm/legs/-
+ 0,0,0, -10,0,65, 0,0,0, // s3: hands/feet/-
+ // carries vertically:
+ -30,15,-5, 10,0,15, 0,0,0, // s4: arms/thighs/-
+ 0,-15,15, 0,0,-30, 0,0,0, // s4: forearm/legs/-
+ 35,0,-15, -10,0,25, 0,0,0, // s4: hands/feet/-
+ // rises:
+ 15,50,-50, 10,0,5, 0,0,0, // s5: arms/thighs/-
+ 45,-70,10, 0,0,-10, 0,0,0, // s5: forearm/legs/-
+ -10,25,0, -10,5,5, 0,0,0, // s5: hands/feet/-
+ // wins:
+ 90,90,-30, 20,0,5, 0,0,0, // s6: arms/thighs/-
+ 0,-90,0, -10,0,-10, 0,0,0, // s6: forearm/legs/-
+ 0,25,0, -10,5,5, 0,0,0, // s6: hands/feet/-
+ // lose:
+ -70,45,35, 10,0,40, 0,0,0, // s7: arms/thighs/-
+ 15,-95,-5, 0,0,-70, 0,0,0, // s7: forearm/legs/-
+ 0,0,0, -10,0,35, 0,0,0, // s7: hands/feet/-
+ // shooting death (falls):
+ 90,90,-50, 10,0,5, 0,0,0, // s8: arms/thighs/-
+ 0,-20,0, 0,0,-10, 0,0,0, // s8: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s8: hands/feet/-
+ // shooting death (knees):
+ 110,105,-5, 10,0,25, 0,0,0, // s9: arms/thighs/-
+ 0,-40,20, 0,0,-120, 0,0,0, // s9: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s9: hands/feet/-
+ // shooting death (knees):
+ 110,120,-25, 10,0,25, 0,0,0, // s10: arms/thighs/-
+ 0,-40,20, 0,0,-120, 0,0,0, // s10: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s10: hands/feet/-
+ // shooting death (face down):
+ 110,100,-25, 25,0,10, 0,0,0, // s11: arms/thighs/-
+ 0,-40,20, 0,0,-25, 0,0,0, // s11: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s11: hands/feet/-
+ // shooting death (face down):
+ 110,100,-25, 25,0,10, 0,0,0, // s12: arms/thighs/-
+ 0,-40,20, 0,0,-25, 0,0,0, // s12: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s12: hands/feet/-
+ // drowned:
+ 110,100,-25, 25,0,10, 0,0,0, // s13: arms/thighs/-
+ 0,-40,20, 0,0,-25, 0,0,0, // s13: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s13: hands/feet/-
+ // puts / removes flag:
+ 85,45,-50, 10,0,60, 0,0,0, // s14: arms/thighs/-
+ -60,15,65, 0,0,-105, 0,0,0, // s14: forearm/legs/-
+ 0,10,0, -10,0,60, 0,0,0, // s14: hands/feet/-
+ // reads SatCom:
+ 70,30,-20, 10,0,5, 0,0,0, // s15: arms/thighs/-
+ 115,-65,60, 0,0,-10, 0,0,0, // s15: forearm/legs/-
+ 0,20,0, -10,5,5, 0,0,0, // s15: hands/feet/-
+ };
+
+ m_physics->SetType(TYPE_FLYING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.0f;
+ character->wheelRight = 4.0f;
+ character->height = 3.5f;
+
+ if ( type == OBJECT_HUMAN )
+ {
+ m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 35.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 70.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 40.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+ m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
+ m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 6.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 6.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 4.0f);
+ }
+ else
+ {
+ m_physics->SetLinMotionX(MO_ADVSPEED, 40.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 8.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 8.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 8.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+ m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
+ m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.6f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.6f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 4.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 4.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 3.0f);
+ }
+
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_MARCH+i] = member_march[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_MARCHTAKE+i] = member_march_take[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_TURN+i] = member_turn[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_STOP+i] = member_stop[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_FLY+i] = member_fly[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_SWIM+i] = member_swim[i];
+ }
+ for ( i=0 ; i<3*3*3*16 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_SPEC+i] = member_spec[i];
+ }
+}
+
+
+// Management of an event.
+
+bool CMotionHuman::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if ADJUST_ANGLE
+ int i;
+
+ if ( event.param == 'A' ) m_armTimeIndex++;
+ if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
+
+ if ( event.param == 'Q' ) m_armPartIndex++;
+ if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
+
+ if ( event.param == 'W' ) m_armMemberIndex++;
+ if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
+
+ i = m_armMemberIndex*3;
+ i += m_armPartIndex*3*3;
+ i += m_armTimeIndex*3*3*3;
+ i += ADJUST_ACTION;
+
+ if ( event.param == 'E' ) m_armAngles[i+0] += 5;
+ if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
+ if ( event.param == 'R' ) m_armAngles[i+1] += 5;
+ if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
+ if ( event.param == 'T' ) m_armAngles[i+2] += 5;
+ if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
+
+ if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
+
+ if ( event.param == 'Y' )
+ {
+ char s[100];
+ sprintf(s, "index dans table = %d %d %d\n", i, i+9, i+18);
+ OutputDebugString(s);
+ }
+#endif
+ }
+
+ return true;
+}
+
+// Management of an event.
+
+bool CMotionHuman::EventFrame(const Event &event)
+{
+ Math::Matrix* mat;
+ Math::Vector dir, actual, pos, speed, pf;
+ Math::Point center, dim, p2;
+ float s, a, prog, rTime[2], lTime[2], time, rot, hr, hl;
+ float al, ar, af;
+ float tSt[9], tNd[9];
+ float aa, bb, shield, deadFactor, level;
+ int i, ii, st, nd, action, legAction, armAction;
+ bool bOnBoard, bSwim, bStop;
+
+ if ( m_engine->RetPause() )
+ {
+ if ( m_actionType == MHS_SATCOM )
+ {
+ m_progress += event.rTime*m_actionTime;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ bOnBoard = false;
+ if ( m_object->RetSelect() &&
+ m_camera->RetType() == CAMERA_ONBOARD )
+ {
+ bOnBoard = true;
+ }
+
+ if ( m_bDisplayPerso && m_main->RetGamerOnlyHead() )
+ {
+ m_time += event.rTime;
+ m_object->SetLinVibration(Math::Vector(0.0f, -0.55f, 0.0f));
+ m_object->SetCirVibration(Math::Vector(0.0f, m_main->RetPersoAngle(), 0.0f));
+ return true;
+ }
+ if ( m_bDisplayPerso )
+ {
+ m_object->SetCirVibration(Math::Vector(0.0f, m_main->RetPersoAngle()+0.2f, 0.0f));
+ }
+
+ shield = m_object->RetShield();
+ shield += event.rTime*(1.0f/120.0f); // regeneration in 120 seconds
+ if ( shield > 1.0f ) shield = 1.0f;
+ m_object->SetShield(shield);
+
+ bSwim = m_physics->RetSwim();
+
+#if 0
+ rot = m_physics->RetCirMotionY(MO_MOTSPEED);
+ s = m_physics->RetLinMotionX(MO_REASPEED)*2.0f;
+ a = m_physics->RetLinMotionX(MO_TERSPEED);
+ if ( a < 0.0f ) // rises?
+ {
+ if ( s > 0.0f && s < 20.0f ) s = 20.0f; // moving slowly?
+//? if ( s < 0.0f && s > -10.0f ) s = 0.0f; // falling slowly?
+ }
+ if ( a > 0.0f && !bSwim ) // falls?
+ {
+ if ( s > 0.0f && s < 10.0f ) s = 0.0f; // moving slowly?
+//? if ( s < 0.0f && s > -5.0f ) s = -5.0f; // falling slowly?
+ }
+ a = fabs(rot*12.0f);
+
+ if ( !m_physics->RetLand() && !bSwim ) // in flight?
+ {
+ s = 0.0f;
+ }
+
+ if ( m_object->RetFret() != 0 ) // carries something?
+ {
+ s *= 1.3f;
+ }
+#else
+ rot = m_physics->RetCirMotionY(MO_MOTSPEED);
+#if 0
+ s = m_physics->RetLinMotionX(MO_REASPEED);
+#else
+ a = m_physics->RetLinMotionX(MO_REASPEED);
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.2f;
+ if ( fabs(a) > fabs(s) ) s = a; // the highest value
+#endif
+ a = m_physics->RetLinMotionX(MO_TERSPEED);
+ if ( a < 0.0f ) // rises?
+ {
+ a += m_physics->RetLinMotionX(MO_TERSLIDE);
+ if ( a < 0.0f ) s -= a;
+ }
+ if ( a > 0.0f ) // falls?
+ {
+ a -= m_physics->RetLinMotionX(MO_TERSLIDE);
+ if ( a > 0.0f ) s -= a;
+ }
+ s *= 2.0f;
+ a = fabs(rot*12.0f);
+
+ if ( !m_physics->RetLand() && !bSwim ) // in flight?
+ {
+ s = 0.0f;
+ }
+
+ if ( m_object->RetFret() != 0 ) // carries something?
+ {
+ s *= 1.3f;
+ }
+#endif
+
+ m_time += event.rTime;
+ m_armTimeAbs += event.rTime;
+ m_armTimeAction += event.rTime;
+ m_armMember += s*event.rTime*0.05f;
+
+ // Fatigue management when short.
+ if ( m_physics->RetLand() && s != 0.0f ) // on the ground?
+ {
+ m_tired += event.rTime*0.1f;
+ if ( m_tired > 1.0f )
+ {
+ m_tired = 1.0f;
+ if ( m_lastSoundHhh > 3.0f ) m_lastSoundHhh = 0.5f;
+ }
+ }
+ else
+ {
+ m_tired -= event.rTime*0.2f;
+ if ( m_tired < 0.0f ) m_tired = 0.0f;
+ }
+
+ if ( bSwim ) // swims?
+ {
+ s += fabs(m_physics->RetLinMotionY(MO_REASPEED)*2.0f);
+ a *= 2.0f;
+ m_armTimeSwim += Math::Min(Math::Max(s,a,3.0f),15.0f)*event.rTime*0.05f;
+ }
+
+ bStop = ( s == 0.0f ); // stop?
+ prog = 0.0f;
+
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ if ( s == 0.0f && a == 0.0f )
+ {
+ action = MH_STOP; // stop
+ rTime[0] = rTime[1] = m_armTimeAbs*0.21f;
+ lTime[0] = lTime[1] = m_armTimeAbs*0.25f;
+ m_armMember = START_TIME;
+ }
+ else
+ {
+ if ( s == 0.0f )
+ {
+ action = MH_TURN; // turn
+ rTime[0] = rTime[1] = m_armTimeAbs;
+ lTime[0] = lTime[1] = m_armTimeAbs+0.5f;
+ if ( rot < 0.0f )
+ {
+ rTime[1] = 1000000.0f-rTime[1];
+ }
+ else
+ {
+ lTime[1] = 1000000.0f-lTime[1];
+ }
+ m_armMember = START_TIME;
+ }
+ else
+ {
+ action = MH_MARCH; // walking
+ if ( m_object->RetFret() != 0 ) action = MH_MARCHTAKE; // take walking
+ rTime[0] = rTime[1] = m_armMember;
+ lTime[0] = lTime[1] = m_armMember+0.5f;
+ }
+ }
+ if ( bSwim )
+ {
+ rTime[0] *= 0.6f;
+ rTime[1] *= 0.6f;
+ lTime[0] = rTime[0]+0.5f;
+ lTime[1] = rTime[1]+0.5f;
+ }
+ }
+ else
+ {
+ if ( bSwim )
+ {
+ action = MH_SWIM; // swim
+ rTime[0] = rTime[1] = m_armTimeSwim;
+ lTime[0] = lTime[1] = m_armTimeSwim;
+ }
+ else
+ {
+ action = MH_FLY; // fly
+ rTime[0] = rTime[1] = m_armTimeAbs*0.30f;
+ lTime[0] = lTime[1] = m_armTimeAbs*0.31f;
+ m_armMember = START_TIME;
+ }
+ }
+
+ if ( action != m_armLastAction )
+ {
+ m_armLastAction = action;
+ m_armTimeAction = 0.0f;
+ }
+
+ armAction = action;
+ legAction = action;
+
+ if ( m_object->RetFret() != 0 ) // carries something?
+ {
+ armAction = MH_MARCHTAKE; // take walking
+ }
+
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ a = m_object->RetAngleY(0);
+ pos = m_object->RetPosition(0);
+ m_terrain->MoveOnFloor(pos);
+
+ pf.x = pos.x+cosf(a+Math::PI*1.5f)*0.7f;
+ pf.y = pos.y;
+ pf.z = pos.z-sinf(a+Math::PI*1.5f)*0.7f;
+ m_terrain->MoveOnFloor(pf);
+ al = atanf((pf.y-pos.y)/0.7f); // angle for left leg
+
+ pf = pos;
+ pf.x = pos.x+cosf(a+Math::PI*0.5f)*0.7f;
+ pf.y = pos.y;
+ pf.z = pos.z-sinf(a+Math::PI*0.5f)*0.7f;
+ m_terrain->MoveOnFloor(pf);
+ ar = atanf((pf.y-pos.y)/0.7f); // angle to right leg
+
+ pf.x = pos.x+cosf(a+Math::PI)*0.3f;
+ pf.y = pos.y;
+ pf.z = pos.z-sinf(a+Math::PI)*0.3f;
+ m_terrain->MoveOnFloor(pf);
+ af = atanf((pf.y-pos.y)/0.3f); // angle for feet
+ }
+ else
+ {
+ al = 0.0f;
+ ar = 0.0f;
+ af = 0.0f;
+ }
+
+ for ( i=0 ; i<4 ; i++ ) // 4 members
+ {
+ if ( m_bArmStop ) // focus?
+ {
+ st = ADJUST_ACTION + (i%2)*3;
+ nd = st;
+ time = 100.0f;
+ m_armTimeAction = 0.0f;
+ }
+ else if ( m_actionType != -1 ) // special action in progress?
+ {
+ st = 3*3*3*3*MH_SPEC + 3*3*3*m_actionType + (i%2)*3;
+ nd = st;
+ time = event.rTime*m_actionTime;
+ m_armTimeAction = 0.0f;
+ }
+ else
+ {
+ if ( i < 2 ) prog = Math::Mod(rTime[i%2], 1.0f);
+ else prog = Math::Mod(lTime[i%2], 1.0f);
+ if ( prog < 0.25f ) // t0..t1 ?
+ {
+ prog = prog/0.25f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.75f ) // t1..t2 ?
+ {
+ prog = (prog-0.25f)/0.50f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.75f)/0.25f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ if ( i%2 == 0 ) // arm?
+ {
+ st = 3*3*3*3*armAction + st*3*3*3 + (i%2)*3;
+ nd = 3*3*3*3*armAction + nd*3*3*3 + (i%2)*3;
+ }
+ else // leg?
+ {
+ st = 3*3*3*3*legAction + st*3*3*3 + (i%2)*3;
+ nd = 3*3*3*3*legAction + nd*3*3*3 + (i%2)*3;
+ }
+
+ // Less soft ...
+ time = event.rTime*(5.0f+Math::Min(m_armTimeAction*50.0f, 100.0f));
+ if ( bSwim ) time *= 0.25f;
+ }
+
+ tSt[0] = m_armAngles[st+ 0]; // x
+ tSt[1] = m_armAngles[st+ 1]; // y
+ tSt[2] = m_armAngles[st+ 2]; // z
+ tSt[3] = m_armAngles[st+ 9]; // x
+ tSt[4] = m_armAngles[st+10]; // y
+ tSt[5] = m_armAngles[st+11]; // z
+ tSt[6] = m_armAngles[st+18]; // x
+ tSt[7] = m_armAngles[st+19]; // y
+ tSt[8] = m_armAngles[st+20]; // z
+
+ tNd[0] = m_armAngles[nd+ 0]; // x
+ tNd[1] = m_armAngles[nd+ 1]; // y
+ tNd[2] = m_armAngles[nd+ 2]; // z
+ tNd[3] = m_armAngles[nd+ 9]; // x
+ tNd[4] = m_armAngles[nd+10]; // y
+ tNd[5] = m_armAngles[nd+11]; // z
+ tNd[6] = m_armAngles[nd+18]; // x
+ tNd[7] = m_armAngles[nd+19]; // y
+ tNd[8] = m_armAngles[nd+20]; // z
+
+ aa = 0.5f;
+ if ( i%2 == 0 ) // arm?
+ {
+ if ( m_object->RetFret() == 0 ) // does nothing?
+ {
+ aa = 2.0f; // moves a lot
+ }
+ else
+ {
+ aa = 0.0f; // immobile
+ }
+ }
+
+ if ( i < 2 ) // left?
+ {
+ bb = sinf(m_time*1.1f)*aa; tSt[0] += bb; tNd[0] += bb;
+ bb = sinf(m_time*1.0f)*aa; tSt[1] += bb; tNd[1] += bb;
+ bb = sinf(m_time*1.2f)*aa; tSt[2] += bb; tNd[2] += bb;
+ bb = sinf(m_time*2.5f)*aa; tSt[3] += bb; tNd[3] += bb;
+ bb = sinf(m_time*2.0f)*aa; tSt[4] += bb; tNd[4] += bb;
+ bb = sinf(m_time*3.8f)*aa; tSt[5] += bb; tNd[5] += bb;
+ bb = sinf(m_time*3.0f)*aa; tSt[6] += bb; tNd[6] += bb;
+ bb = sinf(m_time*2.3f)*aa; tSt[7] += bb; tNd[7] += bb;
+ bb = sinf(m_time*4.0f)*aa; tSt[8] += bb; tNd[8] += bb;
+ }
+ else // right?
+ {
+ bb = sinf(m_time*0.9f)*aa; tSt[0] += bb; tNd[0] += bb;
+ bb = sinf(m_time*1.2f)*aa; tSt[1] += bb; tNd[1] += bb;
+ bb = sinf(m_time*1.4f)*aa; tSt[2] += bb; tNd[2] += bb;
+ bb = sinf(m_time*2.9f)*aa; tSt[3] += bb; tNd[3] += bb;
+ bb = sinf(m_time*1.4f)*aa; tSt[4] += bb; tNd[4] += bb;
+ bb = sinf(m_time*3.1f)*aa; tSt[5] += bb; tNd[5] += bb;
+ bb = sinf(m_time*3.7f)*aa; tSt[6] += bb; tNd[6] += bb;
+ bb = sinf(m_time*2.0f)*aa; tSt[7] += bb; tNd[7] += bb;
+ bb = sinf(m_time*3.1f)*aa; tSt[8] += bb; tNd[8] += bb;
+ }
+
+#if 1
+ if ( i%2 == 1 && // leg?
+ m_actionType == -1 ) // no special action?
+ {
+ if ( i == 1 ) // right leg?
+ {
+ ii = 5;
+ a = ar*0.25f;
+ }
+ else
+ {
+ ii = 11;
+ a = al*0.25f;
+ }
+ if ( a < -0.2f ) a = -0.2f;
+ if ( a > 0.2f ) a = 0.2f;
+
+ pos = m_object->RetPosition(ii+0);
+ pos.y = 0.0f+a;
+ m_object->SetPosition(ii+0, pos); // lengthens / shortcuts thigh
+
+ pos = m_object->RetPosition(ii+1);
+ pos.y = -1.5f+a;
+ m_object->SetPosition(ii+1, pos); // lengthens / shortcuts leg
+
+ pos = m_object->RetPosition(ii+2);
+ pos.y = -1.5f+a;
+ m_object->SetPosition(ii+2, pos); // lengthens / shortcuts foot
+
+ if ( i == 1 ) // right leg?
+ {
+ aa = (ar*180.0f/Math::PI*0.5f);
+ }
+ else // left leg?
+ {
+ aa = (al*180.0f/Math::PI*0.5f);
+ }
+ tSt[6] += aa;
+ tNd[6] += aa; // increases the angle X of the foot
+
+ if ( i == 1 ) // right leg?
+ {
+ aa = (ar*180.0f/Math::PI);
+ }
+ else // left leg?
+ {
+ aa = (al*180.0f/Math::PI);
+ }
+ if ( aa < 0.0f ) aa = 0.0f;
+ if ( aa > 30.0f ) aa = 30.0f;
+
+ tSt[2] += aa;
+ tNd[2] += aa; // increases the angle Z of the thigh
+ tSt[5] -= aa*2;
+ tNd[5] -= aa*2; // increases the angle Z of the leg
+ tSt[8] += aa;
+ tNd[8] += aa; // increases the angle Z of the foot
+
+ aa = (af*180.0f/Math::PI)*0.7f;
+ if ( aa < -30.0f ) aa = -30.0f;
+ if ( aa > 30.0f ) aa = 30.0f;
+
+ tSt[8] -= aa;
+ tNd[8] -= aa; // increases the angle Z of the foot
+ }
+#endif
+
+ if ( m_actionType == MHS_DEADw ) // drowned?
+ {
+ if ( m_progress < 0.5f )
+ {
+ deadFactor = m_progress/0.5f;
+ }
+ else
+ {
+ deadFactor = 1.0f-(m_progress-0.5f)/0.5f;
+ }
+ if ( deadFactor < 0.0f ) deadFactor = 0.0f;
+ if ( deadFactor > 1.0f ) deadFactor = 1.0f;
+
+ for ( ii=0 ; ii<9 ; ii++ )
+ {
+ tSt[ii] += Math::Rand()*20.0f*deadFactor;
+ tNd[ii] = tSt[ii];
+ }
+ time = 100.0f;
+ }
+
+ if ( i < 2 ) // right member (0..1) ?
+ {
+ m_object->SetAngleX(2+3*i+0, Math::Smooth(m_object->RetAngleX(2+3*i+0), Math::PropAngle(tSt[0], tNd[0], prog), time));
+ m_object->SetAngleY(2+3*i+0, Math::Smooth(m_object->RetAngleY(2+3*i+0), Math::PropAngle(tSt[1], tNd[1], prog), time));
+ m_object->SetAngleZ(2+3*i+0, Math::Smooth(m_object->RetAngleZ(2+3*i+0), Math::PropAngle(tSt[2], tNd[2], prog), time));
+ m_object->SetAngleX(2+3*i+1, Math::Smooth(m_object->RetAngleX(2+3*i+1), Math::PropAngle(tSt[3], tNd[3], prog), time));
+ m_object->SetAngleY(2+3*i+1, Math::Smooth(m_object->RetAngleY(2+3*i+1), Math::PropAngle(tSt[4], tNd[4], prog), time));
+ m_object->SetAngleZ(2+3*i+1, Math::Smooth(m_object->RetAngleZ(2+3*i+1), Math::PropAngle(tSt[5], tNd[5], prog), time));
+ m_object->SetAngleX(2+3*i+2, Math::Smooth(m_object->RetAngleX(2+3*i+2), Math::PropAngle(tSt[6], tNd[6], prog), time));
+ m_object->SetAngleY(2+3*i+2, Math::Smooth(m_object->RetAngleY(2+3*i+2), Math::PropAngle(tSt[7], tNd[7], prog), time));
+ m_object->SetAngleZ(2+3*i+2, Math::Smooth(m_object->RetAngleZ(2+3*i+2), Math::PropAngle(tSt[8], tNd[8], prog), time));
+ }
+ else // left member (2..3) ?
+ {
+ m_object->SetAngleX(2+3*i+0, Math::Smooth(m_object->RetAngleX(2+3*i+0), Math::PropAngle(-tSt[0], -tNd[0], prog), time));
+ m_object->SetAngleY(2+3*i+0, Math::Smooth(m_object->RetAngleY(2+3*i+0), Math::PropAngle(-tSt[1], -tNd[1], prog), time));
+ m_object->SetAngleZ(2+3*i+0, Math::Smooth(m_object->RetAngleZ(2+3*i+0), Math::PropAngle( tSt[2], tNd[2], prog), time));
+ m_object->SetAngleX(2+3*i+1, Math::Smooth(m_object->RetAngleX(2+3*i+1), Math::PropAngle(-tSt[3], -tNd[3], prog), time));
+ m_object->SetAngleY(2+3*i+1, Math::Smooth(m_object->RetAngleY(2+3*i+1), Math::PropAngle(-tSt[4], -tNd[4], prog), time));
+ m_object->SetAngleZ(2+3*i+1, Math::Smooth(m_object->RetAngleZ(2+3*i+1), Math::PropAngle( tSt[5], tNd[5], prog), time));
+ m_object->SetAngleX(2+3*i+2, Math::Smooth(m_object->RetAngleX(2+3*i+2), Math::PropAngle(-tSt[6], -tNd[6], prog), time));
+ m_object->SetAngleY(2+3*i+2, Math::Smooth(m_object->RetAngleY(2+3*i+2), Math::PropAngle(-tSt[7], -tNd[7], prog), time));
+ m_object->SetAngleZ(2+3*i+2, Math::Smooth(m_object->RetAngleZ(2+3*i+2), Math::PropAngle( tSt[8], tNd[8], prog), time));
+ }
+ }
+
+#if ADJUST_ANGLE
+ if ( m_object->RetSelect() )
+ {
+ char s[100];
+ sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
+ m_engine->SetInfoText(4, s);
+ }
+#endif
+
+ // calculates the height lowering as a function
+ // of the position of the legs.
+ hr = 1.5f*(1.0f-cosf(m_object->RetAngleZ(5))) +
+ 1.5f*(1.0f-cosf(m_object->RetAngleZ(5)+m_object->RetAngleZ(6)));
+ a = 1.0f*sinf(m_object->RetAngleZ(5)+m_object->RetAngleZ(6)+m_object->RetAngleZ(7));
+ if ( a < 0.0f ) hr += a;
+
+ hl = 1.5f*(1.0f-cosf(m_object->RetAngleZ(11))) +
+ 1.5f*(1.0f-cosf(m_object->RetAngleZ(11)+m_object->RetAngleZ(12)));
+ a = 1.0f*sinf(m_object->RetAngleZ(11)+m_object->RetAngleZ(12)+m_object->RetAngleZ(13));
+ if ( a < 0.0f ) hl += a;
+
+ hr = Math::Min(hr, hl);
+
+ if ( m_actionType == MHS_FIRE ) // shooting?
+ {
+ time = event.rTime*m_actionTime;
+
+ dir.x = (Math::Rand()-0.5f)/8.0f;
+ dir.z = (Math::Rand()-0.5f)/8.0f;
+ dir.y = -0.5f; // slightly lower
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+//? dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.y = -hr;
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = (Math::Rand()-0.5f)/3.0f;
+ dir.z = -0.1f; // slightly leaning forward
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_TAKE || // carrying?
+ m_actionType == MHS_TAKEOTHER ) // flag?
+ {
+ time = event.rTime*m_actionTime*2.0f;
+
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = -1.5f; // slightly lower
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+//? dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.y = -hr;
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = -0.2f;
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_TAKEHIGH ) // carrying?
+ {
+ time = event.rTime*m_actionTime*2.0f;
+
+ dir.x = 0.4f; // slightly forward
+ dir.z = 0.0f;
+ dir.y = 0.0f;
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+//? dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.y = -hr;
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = -0.2f;
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_FLAG ) // flag?
+ {
+ time = event.rTime*m_actionTime*2.0f;
+
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = -2.0f; // slightly lower
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+//? dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.y = -hr;
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = -0.4f;
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_DEADg ) // shooting death (falls)?
+ {
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ SetAction(MHS_DEADg1, 0.5f); // knees
+ }
+ }
+ else if ( m_actionType == MHS_DEADg1 ) // shooting death (knees)?
+ {
+ prog = m_progress;
+ if ( prog >= 1.0f )
+ {
+ prog = 1.0f;
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*4.0f;
+ pos.z += (Math::Rand()-0.5f)*4.0f;
+ m_terrain->MoveOnFloor(pos);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 1.2f+Math::Rand()*1.2f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f);
+ }
+ m_sound->Play(SOUND_BOUMv, m_object->RetPosition(0));
+
+ SetAction(MHS_DEADg2, 1.0f); // expects knees
+ }
+
+ time = 100.0f;
+
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = -1.5f*prog;
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = -(20.0f*Math::PI/180.0f)*prog;
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_DEADg2 ) // shooting death (knees)?
+ {
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(MHS_DEADg3, 1.0f); // face down
+ }
+
+ time = 100.0f;
+
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = -1.5f;
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = -(20.0f*Math::PI/180.0f);
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_DEADg3 ) // shooting death (face down)?
+ {
+ prog = m_progress;
+ if ( prog >= 1.0f )
+ {
+ prog = 1.0f;
+
+ for ( i=0 ; i<20 ; i++ )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*8.0f;
+ pos.z += (Math::Rand()-0.5f)*8.0f;
+ m_terrain->MoveOnFloor(pos);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 2.0f+Math::Rand()*1.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f);
+ }
+ m_sound->Play(SOUND_BOUMv, m_object->RetPosition(0));
+
+ SetAction(MHS_DEADg4, 3.0f); // expects face down
+ }
+
+ time = 100.0f;
+ prog = powf(prog, 3.0f);
+
+ dir.y = -(1.5f+1.5f*prog);
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.z = -((20.0f*Math::PI/180.0f)+(70.0f*Math::PI/180.0f)*prog);
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_DEADg4 ) // shooting death (face down)?
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_object->SetEnable(false);
+ }
+
+ time = 100.0f;
+
+ dir.y = -(1.5f+1.5f);
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.z = -((20.0f*Math::PI/180.0f)+(70.0f*Math::PI/180.0f));
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_DEADw ) // drowned?
+ {
+ pos = m_object->RetPosition(0);
+ level = m_water->RetLevel()-0.5f;
+ if ( pos.y < level )
+ {
+ pos.y += 4.0f*event.rTime; // back to the surface
+ if ( pos.y > level ) pos.y = level;
+ m_object->SetPosition(0, pos);
+ }
+ if ( pos.y > level )
+ {
+ pos.y -= 10.0f*event.rTime; // down quickly
+ if ( pos.y < level ) pos.y = level;
+ m_object->SetPosition(0, pos);
+ }
+
+ prog = m_progress;
+ if ( prog >= 1.0f )
+ {
+ prog = 1.0f;
+ if ( pos.y >= level ) m_object->SetEnable(false);
+ }
+
+ prog *= 2.0f;
+ if ( prog > 1.0f ) prog = 1.0f;
+
+ time = 100.0f;
+
+ dir.z = -(90.0f*Math::PI/180.0f)*prog;
+ dir.x = Math::Rand()*0.3f*deadFactor;
+ dir.y = Math::Rand()*0.3f*deadFactor;
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+
+ m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ }
+ else if ( m_actionType == MHS_LOST ) // lost?
+ {
+ time = m_time;
+ if ( time < 10.0f ) time *= time/10.0f; // starts slowly
+
+ dir.x = time*2.0f;
+ dir.y = sinf(m_time*0.8f)*0.8f;
+ dir.z = sinf(m_time*0.6f)*0.5f;
+ m_object->SetInclinaison(dir);
+ SetInclinaison(dir);
+
+//? dir.x = -(sinf(time*0.05f+Math::PI*1.5f)+1.0f)*100.0f;
+ // original code: Math::Min(time/30.0f) (?) changed to time/30.0f
+ dir.x = -(powf(time/30.0f, 4.0f))*1000.0f; // from the distance
+ dir.y = 0.0f;
+ dir.z = 0.0f;
+ m_object->SetLinVibration(dir);
+ SetLinVibration(dir);
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(0.5f, 3.7f, 0.0f);
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.y += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ pos = Transform(*mat, pos);
+ speed.x = (Math::Rand()-0.5f)*0.5f;
+ speed.y = (Math::Rand()-0.5f)*0.5f;
+ speed.z = (Math::Rand()-0.5f)*0.5f;
+ dim.x = 0.5f+Math::Rand()*0.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTILENS1, 5.0f, 0.0f, 0.0f);
+ }
+ else if ( m_actionType == MHS_SATCOM ) // look at the SatCom?
+ {
+ SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ SetLinVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
+ }
+ else
+ {
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ time = event.rTime*8.0f;
+ if ( bSwim ) time *= 0.25f;
+
+ if ( action == MH_MARCH ) // walking?
+ {
+ dir.x = sinf(Math::Mod(rTime[0]+0.5f, 1.0f)*Math::PI*2.0f)*0.10f;
+ dir.y = sinf(Math::Mod(rTime[0]+0.6f, 1.0f)*Math::PI*2.0f)*0.20f;
+ s = m_physics->RetLinMotionX(MO_REASPEED)*0.03f;
+ }
+ else if ( action == MH_MARCHTAKE ) // takes walking?
+ {
+ dir.x = sinf(Math::Mod(rTime[0]+0.5f, 1.0f)*Math::PI*2.0f)*0.10f;
+ dir.y = sinf(Math::Mod(rTime[0]+0.6f, 1.0f)*Math::PI*2.0f)*0.15f;
+ s = m_physics->RetLinMotionX(MO_REASPEED)*0.02f;
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ s = m_physics->RetLinMotionX(MO_REASPEED)*0.03f;
+ }
+
+ if ( s < 0.0f ) s *= 0.5f;
+ dir.z = -s*0.7f;
+
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ if ( bOnBoard ) dir *= 0.3f;
+ m_object->SetInclinaison(dir);
+ SetInclinaison(dir);
+
+ if ( action == MH_MARCH ) // walking?
+ {
+ p2.x = 0.0f;
+ p2.y = sinf(Math::Mod(rTime[0]+0.5f, 1.0f)*Math::PI*2.0f)*0.5f;
+ p2 = Math::RotatePoint(-m_object->RetAngleY(0), p2);
+ dir.x = p2.x;
+ dir.z = p2.y;
+ dir.y = sinf(Math::Mod(rTime[0]*2.0f, 1.0f)*Math::PI*2.0f)*0.3f;
+ }
+ else if ( action == MH_MARCHTAKE ) // takes walking?
+ {
+ p2.x = 0.0f;
+ p2.y = sinf(Math::Mod(rTime[0]+0.5f, 1.0f)*Math::PI*2.0f)*0.25f;
+ p2 = Math::RotatePoint(-m_object->RetAngleY(0), p2);
+ dir.x = p2.x;
+ dir.z = p2.y;
+ dir.y = sinf(Math::Mod(rTime[0]*2.0f, 1.0f)*Math::PI*2.0f)*0.05f-0.3f;
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = 0.0f;
+ }
+
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ if ( action == MH_MARCHTAKE ) // takes walking?
+ {
+ dir.y = -hr;
+ }
+ else
+ {
+ s = Math::Min(m_armTimeAction, 1.0f);
+ dir.y = Math::Smooth(actual.y, dir.y, time)*s;
+ dir.y += -hr*(1.0f-s);
+ }
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ if ( bOnBoard ) dir *= 0.3f;
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = 0.0f;
+ SetCirVibration(dir);
+ }
+ }
+
+ // Management of the head.
+ if ( m_actionType == MHS_TAKE || // takes?
+ m_actionType == MHS_FLAG ) // takes?
+ {
+ m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f-0.6f, event.rTime*5.0f));
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f);
+ m_object->SetAngleY(1, Math::Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f));
+ }
+ else if ( m_actionType == MHS_TAKEOTHER || // takes?
+ m_actionType == MHS_TAKEHIGH ) // takes?
+ {
+ m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f-0.3f, event.rTime*5.0f));
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f);
+ m_object->SetAngleY(1, Math::Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f));
+ }
+ else if ( m_actionType == MHS_WIN ) // win
+ {
+ float factor = 0.6f+(sinf(m_armTimeAbs*0.5f)*0.40f);
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*5.0f)*0.20f*factor);
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*0.6f)*0.10f);
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*1.5f)*0.15f);
+ }
+ else if ( m_actionType == MHS_LOST ) // lost?
+ {
+ float factor = 0.6f+(sinf(m_armTimeAbs*0.5f)*0.40f);
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*0.6f)*0.10f);
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*0.7f)*0.10f);
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*3.0f)*0.30f*factor);
+ }
+ else if ( m_object->RetDead() ) // dead?
+ {
+ }
+ else
+ {
+ m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f, event.rTime*5.0f));
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f);
+ m_object->SetAngleY(1, Math::Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f));
+ }
+
+ if ( bOnBoard )
+ {
+ m_object->SetAngleZ(1, 0.0f);
+ m_object->SetAngleX(1, 0.0f);
+ m_object->SetAngleY(1, 0.0f);
+ }
+
+ // Steps sound effects.
+ if ( legAction == MH_MARCH ||
+ legAction == MH_MARCHTAKE )
+ {
+ Sound sound[2];
+ float speed, synchro, volume[2], freq[2], hard, level;
+
+ speed = m_physics->RetLinMotionX(MO_REASPEED);
+
+ if ( m_object->RetFret() == 0 )
+ {
+ if ( speed > 0.0f ) synchro = 0.21f; // synchro forward
+ else synchro = 0.29f; // synchro backward
+ }
+ else
+ {
+ if ( speed > 0.0f ) synchro = 0.15f; // synchro forward
+ else synchro = 0.35f; // synchro backward
+ }
+ time = rTime[1]+synchro;
+
+ if ( fabs(m_lastSoundMarch-time) > 0.4f &&
+ Math::Mod(time, 0.5f) < 0.1f )
+ {
+ volume[0] = 0.5f;
+ freq[0] = 1.0f;
+ if ( m_object->RetFret() != 0 )
+ {
+//? volume[0] *= 2.0f;
+ freq[0] = 0.7f;
+ }
+ volume[1] = volume[0];
+ freq[1] = freq[0];
+ sound[0] = SOUND_CLICK;
+ sound[1] = SOUND_CLICK;
+
+ pos = m_object->RetPosition(0);
+
+ level = m_water->RetLevel();
+ if ( pos.y <= level+3.0f ) // underwater?
+ {
+ sound[0] = SOUND_STEPw;
+ }
+ else
+ {
+ hard = m_terrain->RetHardness(pos);
+
+ if ( hard >= 0.875 )
+ {
+ sound[0] = SOUND_STEPm; // metal
+ }
+ else
+ {
+ hard /= 0.875;
+ sound[0] = SOUND_STEPs; // smooth
+ sound[1] = SOUND_STEPh; // hard
+
+ volume[0] *= 1.0f-hard;
+ volume[1] *= hard;
+ if ( hard < 0.5f )
+ {
+ volume[0] *= 1.0f+hard*2.0f;
+ volume[1] *= 1.0f+hard*2.0f;
+ }
+ else
+ {
+ volume[0] *= 3.0f-hard*2.0f;
+ volume[1] *= 3.0f-hard*2.0f;
+ }
+ freq[0] *= 1.0f+hard;
+ freq[1] *= 0.5f+hard;
+ }
+ }
+
+ if ( sound[0] != SOUND_CLICK )
+ {
+ m_sound->Play(sound[0], pos, volume[0], freq[0]);
+ }
+ if ( sound[1] != SOUND_CLICK )
+ {
+ m_sound->Play(sound[1], pos, volume[1], freq[1]);
+ }
+ m_lastSoundMarch = time;
+ }
+ }
+
+ if ( legAction == MH_SWIM )
+ {
+ time = rTime[0]+0.5f;
+
+ if ( fabs(m_lastSoundMarch-time) > 0.9f &&
+ Math::Mod(time, 1.0f) < 0.1f )
+ {
+ m_sound->Play(SOUND_SWIM, m_object->RetPosition(0), 0.5f);
+ m_lastSoundMarch = time;
+ }
+ }
+
+ m_lastSoundHhh -= event.rTime;
+ if ( m_lastSoundHhh <= 0.0f &&
+ m_object->RetSelect() &&
+ m_object->RetOption() == 0 ) // helmet?
+ {
+ m_sound->Play(SOUND_HUMAN1, m_object->RetPosition(0), (0.5f+m_tired*0.2f));
+ m_lastSoundHhh = (4.0f-m_tired*2.5f)+(4.0f-m_tired*2.5f)*Math::Rand();
+ }
+
+ return true;
+}
+
+
+// Management of the display mode when customizing the personal.
+
+void CMotionHuman::StartDisplayPerso()
+{
+ m_bDisplayPerso = true;
+}
+
+void CMotionHuman::StopDisplayPerso()
+{
+ m_bDisplayPerso = false;
+}
+
+
diff --git a/src/object/motion/motionhuman.h b/src/object/motion/motionhuman.h
index ab7b0f9..b365a77 100644
--- a/src/object/motion/motionhuman.h
+++ b/src/object/motion/motionhuman.h
@@ -1,94 +1,94 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionhuman.h
-
-#pragma once
-
-
-#include "object/motion/motion.h"
-
-
-
-enum MotionHumanAction
-{
- MH_MARCH = 0,
- MH_MARCHTAKE = 1,
- MH_TURN = 2,
- MH_STOP = 3,
- MH_FLY = 4,
- MH_SWIM = 5,
- MH_SPEC = 6
-};
-
-enum MotionHumanSpecialAction
-{
- MHS_FIRE = 0,
- MHS_GUN = 1,
- MHS_TAKE = 2,
- MHS_TAKEOTHER = 3,
- MHS_TAKEHIGH = 4,
- MHS_UPRIGHT = 5,
- MHS_WIN = 6,
- MHS_LOST = 7,
- MHS_DEADg = 8,
- MHS_DEADg1 = 9,
- MHS_DEADg2 = 10,
- MHS_DEADg3 = 11,
- MHS_DEADg4 = 12,
- MHS_DEADw = 13,
- MHS_FLAG = 14,
- MHS_SATCOM = 15
-};
-
-
-class CMotionHuman : public CMotion
-{
-public:
- CMotionHuman(CInstanceManager* iMan, CObject* object);
- ~CMotionHuman();
-
- void DeleteObject(bool bAll=false);
- bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- bool EventProcess(const Event &event);
- Error SetAction(int action, float time=0.2f);
-
- void StartDisplayPerso();
- void StopDisplayPerso();
-
-protected:
- void CreatePhysics(ObjectType type);
- bool EventFrame(const Event &event);
-
-protected:
- int m_partiReactor;
- float m_armMember;
- float m_armTimeAbs;
- float m_armTimeAction;
- float m_armTimeSwim;
- short m_armAngles[3*3*3*3*7 + 3*3*3*16];
- int m_armTimeIndex;
- int m_armPartIndex;
- int m_armMemberIndex;
- int m_armLastAction;
- bool m_bArmStop;
- float m_lastSoundMarch;
- float m_lastSoundHhh;
- float m_time;
- float m_tired;
- bool m_bDisplayPerso;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionhuman.h
+
+#pragma once
+
+
+#include "object/motion/motion.h"
+
+
+
+enum MotionHumanAction
+{
+ MH_MARCH = 0,
+ MH_MARCHTAKE = 1,
+ MH_TURN = 2,
+ MH_STOP = 3,
+ MH_FLY = 4,
+ MH_SWIM = 5,
+ MH_SPEC = 6
+};
+
+enum MotionHumanSpecialAction
+{
+ MHS_FIRE = 0,
+ MHS_GUN = 1,
+ MHS_TAKE = 2,
+ MHS_TAKEOTHER = 3,
+ MHS_TAKEHIGH = 4,
+ MHS_UPRIGHT = 5,
+ MHS_WIN = 6,
+ MHS_LOST = 7,
+ MHS_DEADg = 8,
+ MHS_DEADg1 = 9,
+ MHS_DEADg2 = 10,
+ MHS_DEADg3 = 11,
+ MHS_DEADg4 = 12,
+ MHS_DEADw = 13,
+ MHS_FLAG = 14,
+ MHS_SATCOM = 15
+};
+
+
+class CMotionHuman : public CMotion
+{
+public:
+ CMotionHuman(CInstanceManager* iMan, CObject* object);
+ ~CMotionHuman();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ bool EventProcess(const Event &event);
+ Error SetAction(int action, float time=0.2f);
+
+ void StartDisplayPerso();
+ void StopDisplayPerso();
+
+protected:
+ void CreatePhysics(ObjectType type);
+ bool EventFrame(const Event &event);
+
+protected:
+ int m_partiReactor;
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeAction;
+ float m_armTimeSwim;
+ short m_armAngles[3*3*3*3*7 + 3*3*3*16];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ bool m_bArmStop;
+ float m_lastSoundMarch;
+ float m_lastSoundHhh;
+ float m_time;
+ float m_tired;
+ bool m_bDisplayPerso;
+};
+
diff --git a/src/object/motion/motionmother.cpp b/src/object/motion/motionmother.cpp
index 26e28d5..0b783a3 100644
--- a/src/object/motion/motionmother.cpp
+++ b/src/object/motion/motionmother.cpp
@@ -1,524 +1,524 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionmother.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motionmother.h"
-
-#include "old/modfile.h"
-#include "physics/physics.h"
-
-
-
-#define ADJUST_ANGLE false // true -> adjusts the angles of the members
-const float START_TIME = 1000.0f; // beginning of the relative time
-
-
-
-// Object's constructor.
-
-CMotionMother::CMotionMother(CInstanceManager* iMan, CObject* object)
- : CMotion(iMan, object)
-{
- m_armMember = START_TIME;
- m_armTimeAbs = START_TIME;
- m_armTimeMarch = START_TIME;
- m_armTimeAction = START_TIME;
- m_armTimeIndex = 0;
- m_armPartIndex = 0;
- m_armMemberIndex = 0;
- m_armLastAction = -1;
- m_specAction = -1;
- m_bArmStop = false;
-}
-
-// Object's destructor.
-
-CMotionMother::~CMotionMother()
-{
-}
-
-
-// Removes an object.
-
-void CMotionMother::DeleteObject(bool bAll)
-{
-}
-
-
-// Creates a vehicle traveling any lands on the ground.
-
-bool CMotionMother::Create(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 2+12+6 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- m_object->SetType(type);
-
- // Creates main base.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
-
- pModFile->ReadModel("objects\\mother1.mod");
- pModFile->CreateEngineObject(rank);
-
- m_object->SetPosition(0, pos);
- m_object->SetAngleY(0, angle);
-
- // A vehicle must have a obligatory collision
- //with a sphere of center (0, y, 0) (see GetCrashSphere).
- m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 20.0f, SOUND_BOUM, 0.20f);
- m_object->SetGlobalSphere(Math::Vector(-2.0f, 10.0f, 0.0f), 25.0f);
-
- // Creates the head.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\mother2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(16.0f, 3.0f, 0.0f));
-
- // Creates a right-back leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\mother3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(-5.0f, -1.0f, -12.0f));
-
- // Creates a right-back foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\mother4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(0.0f, 0.0f, -8.5f));
-
- // Creates a middle-right leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(4, rank);
- m_object->SetObjectParent(4, 0);
- pModFile->ReadModel("objects\\mother3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(4, Math::Vector(3.5f, -1.0f, -12.0f));
-
- // Creates a middle-right foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(5, rank);
- m_object->SetObjectParent(5, 4);
- pModFile->ReadModel("objects\\mother4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(5, Math::Vector(0.0f, 0.0f, -8.5f));
-
- // Creates a right-front leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\mother3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(10.0f, -1.0f, -10.0f));
-
- // Creates a right-front foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 6);
- pModFile->ReadModel("objects\\mother4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, 0.0f, -8.5f));
-
- // Creates a left-back leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 0);
- pModFile->ReadModel("objects\\mother3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(-5.0f, -1.0f, 12.0f));
- m_object->SetAngleY(8, Math::PI);
-
- // Creates a left-back foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(9, rank);
- m_object->SetObjectParent(9, 8);
- pModFile->ReadModel("objects\\mother4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(9, Math::Vector(0.0f, 0.0f, -8.5f));
-
- // Creates a middle-left leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(10, rank);
- m_object->SetObjectParent(10, 0);
- pModFile->ReadModel("objects\\mother3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(10, Math::Vector(3.5f, -1.0f, 12.0f));
- m_object->SetAngleY(10, Math::PI);
-
- // Creates a middle-left foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(11, rank);
- m_object->SetObjectParent(11, 10);
- pModFile->ReadModel("objects\\mother4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(11, Math::Vector(0.0f, 0.0f, -8.5f));
-
- // Creates a left-front leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(12, rank);
- m_object->SetObjectParent(12, 0);
- pModFile->ReadModel("objects\\mother3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(12, Math::Vector(10.0f, -1.0f, 10.0f));
- m_object->SetAngleY(12, Math::PI);
-
- // Creates a left-front foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(13, rank);
- m_object->SetObjectParent(13, 12);
- pModFile->ReadModel("objects\\mother4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(13, Math::Vector(0.0f, 0.0f, -8.5f));
-
- // Creates the right antenna.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(14, rank);
- m_object->SetObjectParent(14, 1);
- pModFile->ReadModel("objects\\mother5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(14, Math::Vector(6.0f, 1.0f, -2.5f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(15, rank);
- m_object->SetObjectParent(15, 14);
- pModFile->ReadModel("objects\\mother6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(15, Math::Vector(8.0f, 0.0f, 0.0f));
-
- // Creates the left antenna.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(16, rank);
- m_object->SetObjectParent(16, 1);
- pModFile->ReadModel("objects\\mother5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(16, Math::Vector(6.0f, 1.0f, 2.5f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(17, rank);
- m_object->SetObjectParent(17, 16);
- pModFile->ReadModel("objects\\mother6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(17, Math::Vector(8.0f, 0.0f, 0.0f));
-
- // Creates the right claw.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(18, rank);
- m_object->SetObjectParent(18, 1);
- pModFile->ReadModel("objects\\mother7.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(18, Math::Vector(-4.0f, -3.5f, -8.0f));
- m_object->SetZoomX(18, 1.2f);
-
- // Creates the left claw.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(19, rank);
- m_object->SetObjectParent(19, 1);
- pModFile->ReadModel("objects\\mother7.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(19, Math::Vector(-4.0f, -3.5f, 8.0f));
- m_object->SetZoomX(19, 1.2f);
-
- m_object->CreateShadowCircle(18.0f, 0.8f);
-
- CreatePhysics();
- m_object->SetFloorHeight(0.0f);
-
- pos = m_object->RetPosition(0);
- m_object->SetPosition(0, pos); // to display the shadows immediately
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-// Creates the physics of the object.
-
-void CMotionMother::CreatePhysics()
-{
- Character* character;
- int i;
-
- int member[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
- 30,30,10, 35,-15,10, 35,-35,10, // t0: legs 1..3
- -80,-45,-35, -115,-40,-35, -90,10,-55, // t0: feet 1..3
- 0,0,0, 0,0,0, 0,0,0, // t0: unused
- // on the ground:
- 15,-5,10, 10,-30,10, 5,-50,10, // t1: legs 1..3
- -90,-15,-15, -110,-55,-35, -75,-75,-30, // t1: feet 1..3
- 0,0,0, 0,0,0, 0,0,0, // t1: unused
- // on the ground back:
- 0,40,10, 5,5,10, 0,-15,10, // t2: legs 1..3
- -45,0,-55, -65,10,-50, -125,-85,-45, // t2: feet 1..3
- 0,0,0, 0,0,0, 0,0,0, // t2: unused
- };
-
- m_physics->SetType(TYPE_ROLLING);
-
- character = m_object->RetCharacter();
- character->wheelFront = 10.0f;
- character->wheelBack = 10.0f;
- character->wheelLeft = 20.0f;
- character->wheelRight = 20.0f;
- character->height = 3.0f;
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 8.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 8.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 30.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 20.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.1f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.1f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 20.0f);
-
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[i] = member[i];
- }
-}
-
-
-// Management of an event.
-
-bool CMotionMother::EventProcess(const Event &event)
-{
- CMotion::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
-#if ADJUST_ANGLE
- int i;
-
- if ( event.param == 'A' ) m_armTimeIndex++;
- if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
-
- if ( event.param == 'Q' ) m_armPartIndex++;
- if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
-
- if ( event.param == 'W' ) m_armMemberIndex++;
- if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
-
- i = m_armMemberIndex*3;
- i += m_armPartIndex*3*3;
- i += m_armTimeIndex*3*3*3;
-//? i += 3*3*3*3;
-
- if ( event.param == 'E' ) m_armAngles[i+0] += 5;
- if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
- if ( event.param == 'R' ) m_armAngles[i+1] += 5;
- if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
- if ( event.param == 'T' ) m_armAngles[i+2] += 5;
- if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
-
- if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
-#endif
- }
-
- return true;
-}
-
-// Management of an event.
-
-bool CMotionMother::EventFrame(const Event &event)
-{
- Math::Vector dir;
- float s, a, prog;
- int i, st, nd;
- bool bStop;
-
- if ( m_engine->RetPause() ) return true;
- if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
-
- s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
- a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*26.0f);
-
- if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
-
- m_armTimeAbs += event.rTime;
- m_armTimeMarch += (s)*event.rTime*0.05f;
- m_armMember += (s+a)*event.rTime*0.05f;
-
- bStop = ( a == 0.0f && s == 0.0f ); // stop?
-
- if ( bStop )
- {
- prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
- a = Math::Mod(m_armMember, 1.0f);
- a = (prog-a)*event.rTime*1.0f; // stop position just pleasantly
- m_armMember += a;
- }
-
- for ( i=0 ; i<6 ; i++ ) // the six legs
- {
- if ( i < 3 ) prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
- else prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
- if ( m_bArmStop )
- {
- prog = (float)m_armTimeIndex/3.0f;
- }
- if ( prog < 0.33f ) // t0..t1 ?
- {
- prog = prog/0.33f; // 0..1
- st = 0; // index start
- nd = 1; // index end
- }
- else if ( prog < 0.67f ) // t1..t2 ?
- {
- prog = (prog-0.33f)/0.33f; // 0..1
- st = 1; // index start
- nd = 2; // index end
- }
- else // t2..t0 ?
- {
- prog = (prog-0.67f)/0.33f; // 0..1
- st = 2; // index start
- nd = 0; // index end
- }
- st = st*27+(i%3)*3;
- nd = nd*27+(i%3)*3;
- if ( i < 3 ) // right leg (1..3) ?
- {
- m_object->SetAngleX(2+2*i+0, Math::PropAngle(m_armAngles[st+ 0], m_armAngles[nd+ 0], prog));
- m_object->SetAngleY(2+2*i+0, Math::PropAngle(m_armAngles[st+ 1], m_armAngles[nd+ 1], prog));
- m_object->SetAngleZ(2+2*i+0, Math::PropAngle(m_armAngles[st+ 2], m_armAngles[nd+ 2], prog));
- m_object->SetAngleX(2+2*i+1, Math::PropAngle(m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
- m_object->SetAngleY(2+2*i+1, Math::PropAngle(m_armAngles[st+10], m_armAngles[nd+10], prog));
- m_object->SetAngleZ(2+2*i+1, Math::PropAngle(m_armAngles[st+11], m_armAngles[nd+11], prog));
- }
- else // left leg (4..6) ?
- {
- m_object->SetAngleX(2+2*i+0, Math::PropAngle( m_armAngles[st+ 0], m_armAngles[nd+ 0], prog));
- m_object->SetAngleY(2+2*i+0, Math::PropAngle(180-m_armAngles[st+ 1], 180-m_armAngles[nd+ 1], prog));
- m_object->SetAngleZ(2+2*i+0, Math::PropAngle( -m_armAngles[st+ 2], -m_armAngles[nd+ 2], prog));
- m_object->SetAngleX(2+2*i+1, Math::PropAngle( m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
- m_object->SetAngleY(2+2*i+1, Math::PropAngle( -m_armAngles[st+10], -m_armAngles[nd+10], prog));
- m_object->SetAngleZ(2+2*i+1, Math::PropAngle( -m_armAngles[st+11], -m_armAngles[nd+11], prog));
- }
- }
-
-#if ADJUST_ANGLE
- if ( m_object->RetSelect() )
- {
- char s[100];
- sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
- m_engine->SetInfoText(4, s);
- }
-#endif
-
- if ( !bStop && !m_object->RetRuin() )
- {
- a = Math::Mod(m_armTimeMarch, 1.0f);
- if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
- else a = 3.0f-4.0f*a; // 1..-1
- dir.x = sinf(a)*0.03f;
-
- s = Math::Mod(m_armTimeMarch/2.0f, 1.0f);
- if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
- else s = 3.0f-4.0f*s; // 1..-1
- dir.z = sinf(s)*0.05f;
-
- dir.y = 0.0f;
- m_object->SetInclinaison(dir);
-
- a = Math::Mod(m_armMember-0.1f, 1.0f);
- if ( a < 0.33f )
- {
- dir.y = -(1.0f-(a/0.33f))*0.3f;
- }
- else if ( a < 0.67f )
- {
- dir.y = 0.0f;
- }
- else
- {
- dir.y = -(a-0.67f)/0.33f*0.3f;
- }
- dir.x = 0.0f;
- dir.z = 0.0f;
- m_object->SetLinVibration(dir);
- }
-
- m_object->SetAngleZ(1, sinf(m_armTimeAbs*0.5f)*0.20f); // head
- m_object->SetAngleX(1, sinf(m_armTimeAbs*0.6f)*0.10f); // head
- m_object->SetAngleY(1, sinf(m_armTimeAbs*0.7f)*0.20f); // head
-
- m_object->SetAngleZ(14, 0.50f);
- m_object->SetAngleZ(16, 0.50f);
- m_object->SetAngleY(14, 0.80f+sinf(m_armTimeAbs*1.1f)*0.53f); // right antenna
- m_object->SetAngleY(15, 0.70f-sinf(m_armTimeAbs*1.7f)*0.43f);
- m_object->SetAngleY(16, -0.80f+sinf(m_armTimeAbs*0.9f)*0.53f); // left antenna
- m_object->SetAngleY(17, -0.70f-sinf(m_armTimeAbs*1.3f)*0.43f);
-
- m_object->SetAngleY(18, sinf(m_armTimeAbs*1.1f)*0.20f); // right claw
- m_object->SetAngleZ(18, -0.20f);
- m_object->SetAngleY(19, sinf(m_armTimeAbs*0.9f)*0.20f); // left claw
- m_object->SetAngleZ(19, -0.20f);
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionmother.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motionmother.h"
+
+#include "old/modfile.h"
+#include "physics/physics.h"
+
+
+
+#define ADJUST_ANGLE false // true -> adjusts the angles of the members
+const float START_TIME = 1000.0f; // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionMother::CMotionMother(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeMarch = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLastAction = -1;
+ m_specAction = -1;
+ m_bArmStop = false;
+}
+
+// Object's destructor.
+
+CMotionMother::~CMotionMother()
+{
+}
+
+
+// Removes an object.
+
+void CMotionMother::DeleteObject(bool bAll)
+{
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+bool CMotionMother::Create(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 2+12+6 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+
+ pModFile->ReadModel("objects\\mother1.mod");
+ pModFile->CreateEngineObject(rank);
+
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have a obligatory collision
+ //with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 20.0f, SOUND_BOUM, 0.20f);
+ m_object->SetGlobalSphere(Math::Vector(-2.0f, 10.0f, 0.0f), 25.0f);
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\mother2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(16.0f, 3.0f, 0.0f));
+
+ // Creates a right-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(-5.0f, -1.0f, -12.0f));
+
+ // Creates a right-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(0.0f, 0.0f, -8.5f));
+
+ // Creates a middle-right leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, Math::Vector(3.5f, -1.0f, -12.0f));
+
+ // Creates a middle-right foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 4);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, Math::Vector(0.0f, 0.0f, -8.5f));
+
+ // Creates a right-front leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(10.0f, -1.0f, -10.0f));
+
+ // Creates a right-front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 6);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, 0.0f, -8.5f));
+
+ // Creates a left-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(-5.0f, -1.0f, 12.0f));
+ m_object->SetAngleY(8, Math::PI);
+
+ // Creates a left-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 8);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, Math::Vector(0.0f, 0.0f, -8.5f));
+
+ // Creates a middle-left leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10, rank);
+ m_object->SetObjectParent(10, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10, Math::Vector(3.5f, -1.0f, 12.0f));
+ m_object->SetAngleY(10, Math::PI);
+
+ // Creates a middle-left foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(11, rank);
+ m_object->SetObjectParent(11, 10);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(11, Math::Vector(0.0f, 0.0f, -8.5f));
+
+ // Creates a left-front leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(12, rank);
+ m_object->SetObjectParent(12, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(12, Math::Vector(10.0f, -1.0f, 10.0f));
+ m_object->SetAngleY(12, Math::PI);
+
+ // Creates a left-front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(13, rank);
+ m_object->SetObjectParent(13, 12);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(13, Math::Vector(0.0f, 0.0f, -8.5f));
+
+ // Creates the right antenna.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(14, rank);
+ m_object->SetObjectParent(14, 1);
+ pModFile->ReadModel("objects\\mother5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(14, Math::Vector(6.0f, 1.0f, -2.5f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(15, rank);
+ m_object->SetObjectParent(15, 14);
+ pModFile->ReadModel("objects\\mother6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(15, Math::Vector(8.0f, 0.0f, 0.0f));
+
+ // Creates the left antenna.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(16, rank);
+ m_object->SetObjectParent(16, 1);
+ pModFile->ReadModel("objects\\mother5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(16, Math::Vector(6.0f, 1.0f, 2.5f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(17, rank);
+ m_object->SetObjectParent(17, 16);
+ pModFile->ReadModel("objects\\mother6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(17, Math::Vector(8.0f, 0.0f, 0.0f));
+
+ // Creates the right claw.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(18, rank);
+ m_object->SetObjectParent(18, 1);
+ pModFile->ReadModel("objects\\mother7.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(18, Math::Vector(-4.0f, -3.5f, -8.0f));
+ m_object->SetZoomX(18, 1.2f);
+
+ // Creates the left claw.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(19, rank);
+ m_object->SetObjectParent(19, 1);
+ pModFile->ReadModel("objects\\mother7.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(19, Math::Vector(-4.0f, -3.5f, 8.0f));
+ m_object->SetZoomX(19, 1.2f);
+
+ m_object->CreateShadowCircle(18.0f, 0.8f);
+
+ CreatePhysics();
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+// Creates the physics of the object.
+
+void CMotionMother::CreatePhysics()
+{
+ Character* character;
+ int i;
+
+ int member[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 30,30,10, 35,-15,10, 35,-35,10, // t0: legs 1..3
+ -80,-45,-35, -115,-40,-35, -90,10,-55, // t0: feet 1..3
+ 0,0,0, 0,0,0, 0,0,0, // t0: unused
+ // on the ground:
+ 15,-5,10, 10,-30,10, 5,-50,10, // t1: legs 1..3
+ -90,-15,-15, -110,-55,-35, -75,-75,-30, // t1: feet 1..3
+ 0,0,0, 0,0,0, 0,0,0, // t1: unused
+ // on the ground back:
+ 0,40,10, 5,5,10, 0,-15,10, // t2: legs 1..3
+ -45,0,-55, -65,10,-50, -125,-85,-45, // t2: feet 1..3
+ 0,0,0, 0,0,0, 0,0,0, // t2: unused
+ };
+
+ m_physics->SetType(TYPE_ROLLING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 10.0f;
+ character->wheelBack = 10.0f;
+ character->wheelLeft = 20.0f;
+ character->wheelRight = 20.0f;
+ character->height = 3.0f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 8.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 8.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 30.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.1f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.1f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 20.0f);
+
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[i] = member[i];
+ }
+}
+
+
+// Management of an event.
+
+bool CMotionMother::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if ADJUST_ANGLE
+ int i;
+
+ if ( event.param == 'A' ) m_armTimeIndex++;
+ if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
+
+ if ( event.param == 'Q' ) m_armPartIndex++;
+ if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
+
+ if ( event.param == 'W' ) m_armMemberIndex++;
+ if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
+
+ i = m_armMemberIndex*3;
+ i += m_armPartIndex*3*3;
+ i += m_armTimeIndex*3*3*3;
+//? i += 3*3*3*3;
+
+ if ( event.param == 'E' ) m_armAngles[i+0] += 5;
+ if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
+ if ( event.param == 'R' ) m_armAngles[i+1] += 5;
+ if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
+ if ( event.param == 'T' ) m_armAngles[i+2] += 5;
+ if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
+
+ if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
+#endif
+ }
+
+ return true;
+}
+
+// Management of an event.
+
+bool CMotionMother::EventFrame(const Event &event)
+{
+ Math::Vector dir;
+ float s, a, prog;
+ int i, st, nd;
+ bool bStop;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
+ a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*26.0f);
+
+ if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armTimeMarch += (s)*event.rTime*0.05f;
+ m_armMember += (s+a)*event.rTime*0.05f;
+
+ bStop = ( a == 0.0f && s == 0.0f ); // stop?
+
+ if ( bStop )
+ {
+ prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
+ a = Math::Mod(m_armMember, 1.0f);
+ a = (prog-a)*event.rTime*1.0f; // stop position just pleasantly
+ m_armMember += a;
+ }
+
+ for ( i=0 ; i<6 ; i++ ) // the six legs
+ {
+ if ( i < 3 ) prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
+ else prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
+ if ( m_bArmStop )
+ {
+ prog = (float)m_armTimeIndex/3.0f;
+ }
+ if ( prog < 0.33f ) // t0..t1 ?
+ {
+ prog = prog/0.33f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.67f ) // t1..t2 ?
+ {
+ prog = (prog-0.33f)/0.33f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.67f)/0.33f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ st = st*27+(i%3)*3;
+ nd = nd*27+(i%3)*3;
+ if ( i < 3 ) // right leg (1..3) ?
+ {
+ m_object->SetAngleX(2+2*i+0, Math::PropAngle(m_armAngles[st+ 0], m_armAngles[nd+ 0], prog));
+ m_object->SetAngleY(2+2*i+0, Math::PropAngle(m_armAngles[st+ 1], m_armAngles[nd+ 1], prog));
+ m_object->SetAngleZ(2+2*i+0, Math::PropAngle(m_armAngles[st+ 2], m_armAngles[nd+ 2], prog));
+ m_object->SetAngleX(2+2*i+1, Math::PropAngle(m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
+ m_object->SetAngleY(2+2*i+1, Math::PropAngle(m_armAngles[st+10], m_armAngles[nd+10], prog));
+ m_object->SetAngleZ(2+2*i+1, Math::PropAngle(m_armAngles[st+11], m_armAngles[nd+11], prog));
+ }
+ else // left leg (4..6) ?
+ {
+ m_object->SetAngleX(2+2*i+0, Math::PropAngle( m_armAngles[st+ 0], m_armAngles[nd+ 0], prog));
+ m_object->SetAngleY(2+2*i+0, Math::PropAngle(180-m_armAngles[st+ 1], 180-m_armAngles[nd+ 1], prog));
+ m_object->SetAngleZ(2+2*i+0, Math::PropAngle( -m_armAngles[st+ 2], -m_armAngles[nd+ 2], prog));
+ m_object->SetAngleX(2+2*i+1, Math::PropAngle( m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
+ m_object->SetAngleY(2+2*i+1, Math::PropAngle( -m_armAngles[st+10], -m_armAngles[nd+10], prog));
+ m_object->SetAngleZ(2+2*i+1, Math::PropAngle( -m_armAngles[st+11], -m_armAngles[nd+11], prog));
+ }
+ }
+
+#if ADJUST_ANGLE
+ if ( m_object->RetSelect() )
+ {
+ char s[100];
+ sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
+ m_engine->SetInfoText(4, s);
+ }
+#endif
+
+ if ( !bStop && !m_object->RetRuin() )
+ {
+ a = Math::Mod(m_armTimeMarch, 1.0f);
+ if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
+ else a = 3.0f-4.0f*a; // 1..-1
+ dir.x = sinf(a)*0.03f;
+
+ s = Math::Mod(m_armTimeMarch/2.0f, 1.0f);
+ if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
+ else s = 3.0f-4.0f*s; // 1..-1
+ dir.z = sinf(s)*0.05f;
+
+ dir.y = 0.0f;
+ m_object->SetInclinaison(dir);
+
+ a = Math::Mod(m_armMember-0.1f, 1.0f);
+ if ( a < 0.33f )
+ {
+ dir.y = -(1.0f-(a/0.33f))*0.3f;
+ }
+ else if ( a < 0.67f )
+ {
+ dir.y = 0.0f;
+ }
+ else
+ {
+ dir.y = -(a-0.67f)/0.33f*0.3f;
+ }
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ m_object->SetLinVibration(dir);
+ }
+
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*0.5f)*0.20f); // head
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*0.6f)*0.10f); // head
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*0.7f)*0.20f); // head
+
+ m_object->SetAngleZ(14, 0.50f);
+ m_object->SetAngleZ(16, 0.50f);
+ m_object->SetAngleY(14, 0.80f+sinf(m_armTimeAbs*1.1f)*0.53f); // right antenna
+ m_object->SetAngleY(15, 0.70f-sinf(m_armTimeAbs*1.7f)*0.43f);
+ m_object->SetAngleY(16, -0.80f+sinf(m_armTimeAbs*0.9f)*0.53f); // left antenna
+ m_object->SetAngleY(17, -0.70f-sinf(m_armTimeAbs*1.3f)*0.43f);
+
+ m_object->SetAngleY(18, sinf(m_armTimeAbs*1.1f)*0.20f); // right claw
+ m_object->SetAngleZ(18, -0.20f);
+ m_object->SetAngleY(19, sinf(m_armTimeAbs*0.9f)*0.20f); // left claw
+ m_object->SetAngleZ(19, -0.20f);
+
+ return true;
+}
+
+
diff --git a/src/object/motion/motionmother.h b/src/object/motion/motionmother.h
index 7d67f5b..5060315 100644
--- a/src/object/motion/motionmother.h
+++ b/src/object/motion/motionmother.h
@@ -1,54 +1,54 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionmother.h
-
-#pragma once
-
-
-#include "object/motion/motion.h"
-
-
-
-class CMotionMother : public CMotion
-{
-public:
- CMotionMother(CInstanceManager* iMan, CObject* object);
- ~CMotionMother();
-
- void DeleteObject(bool bAll=false);
- bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- bool EventProcess(const Event &event);
-
-protected:
- void CreatePhysics();
- bool EventFrame(const Event &event);
-
-protected:
- float m_armMember;
- float m_armTimeAbs;
- float m_armTimeMarch;
- float m_armTimeAction;
- short m_armAngles[3*3*3*3*10];
- int m_armTimeIndex;
- int m_armPartIndex;
- int m_armMemberIndex;
- int m_armLastAction;
- int m_specAction;
- float m_specTime;
- bool m_bArmStop;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionmother.h
+
+#pragma once
+
+
+#include "object/motion/motion.h"
+
+
+
+class CMotionMother : public CMotion
+{
+public:
+ CMotionMother(CInstanceManager* iMan, CObject* object);
+ ~CMotionMother();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ bool EventProcess(const Event &event);
+
+protected:
+ void CreatePhysics();
+ bool EventFrame(const Event &event);
+
+protected:
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeMarch;
+ float m_armTimeAction;
+ short m_armAngles[3*3*3*3*10];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ int m_specAction;
+ float m_specTime;
+ bool m_bArmStop;
+};
+
diff --git a/src/object/motion/motionspider.cpp b/src/object/motion/motionspider.cpp
index fa5d649..be16e08 100644
--- a/src/object/motion/motionspider.cpp
+++ b/src/object/motion/motionspider.cpp
@@ -1,759 +1,759 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionspider.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motionspider.h"
-
-#include "old/modfile.h"
-#include "old/particule.h"
-#include "physics/physics.h"
-
-
-
-#define ADJUST_ANGLE false // true -> adjusts the angles of the members
-const float START_TIME = 1000.0f; // beginning of the relative time
-
-
-
-// Object's constructor.
-
-CMotionSpider::CMotionSpider(CInstanceManager* iMan, CObject* object)
- : CMotion(iMan, object)
-{
- m_armMember = START_TIME;
- m_armTimeAbs = START_TIME;
- m_armTimeMarch = START_TIME;
- m_armTimeAction = START_TIME;
- m_armTimeIndex = 0;
- m_armPartIndex = 0;
- m_armMemberIndex = 0;
- m_armLastAction = -1;
- m_bArmStop = false;
- m_lastParticule = 0.0f;
-}
-
-// Object's destructor.
-
-CMotionSpider::~CMotionSpider()
-{
-}
-
-
-// Removes an object.
-
-void CMotionSpider::DeleteObject(bool bAll)
-{
-}
-
-
-// Creates a vehicle traveling any lands on the ground.
-
-bool CMotionSpider::Create(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- int rank, i, j, parent;
- char name[50];
-
- float table[] =
- {
- // x y z
- 0.6f, 0.0f, 0.0f, // back leg
- 0.0f, 0.0f, -2.0f,
- 0.0f, 0.0f, -2.0f,
- 0.0f, 0.0f, -2.0f,
-
- 0.8f, 0.0f, -0.2f, // middle-back leg
- 0.0f, 0.0f, -2.0f,
- 0.0f, 0.0f, -2.0f,
- 0.0f, 0.0f, -2.0f,
-
- 1.0f, 0.0f, -0.2f, // middle-front leg
- 0.0f, 0.0f, -2.0f,
- 0.0f, 0.0f, -2.0f,
- 0.0f, 0.0f, -2.0f,
-
- 1.2f, 0.0f, 0.0f, // front leg
- 0.0f, 0.0f, -2.0f,
- 0.0f, 0.0f, -2.0f,
- 0.0f, 0.0f, -2.0f,
- };
-
- if ( m_engine->RetRestCreate() < 3+32+2 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- m_object->SetType(type);
-
- // Creates the main base.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\spider0.mod"); // doesn't exist
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(0, pos);
- m_object->SetAngleY(0, angle);
-
- // A vehicle must have a obligatory collision
- // with a sphere of center (0, y, 0) (see GetCrashSphere).
- m_object->CreateCrashSphere(Math::Vector(0.0f, -2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
- m_object->SetGlobalSphere(Math::Vector(-0.5f, 1.0f, 0.0f), 4.0f);
-
- // Creates the abdomen.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\spider1.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(1.0f, 0.0f, 0.0f));
-
- // Creates the head.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\spider2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(1.0f, 0.0f, 0.0f));
-
- // Creates legs.
- for ( i=0 ; i<4 ; i++ )
- {
- for ( j=0 ; j<4 ; j++ )
- {
- sprintf(name, "objects\\spider%d.mod", j+3); // 3..6
-
- // Creates the right leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3+i*4+j, rank);
- if ( j == 0 ) parent = 0;
- else parent = 3+i*4+j-1;
- m_object->SetObjectParent(3+i*4+j, parent);
- pModFile->ReadModel(name);
- pModFile->CreateEngineObject(rank);
- pos.x = table[i*12+j*3+0];
- pos.y = table[i*12+j*3+1];
- pos.z = table[i*12+j*3+2];
- m_object->SetPosition(3+i*4+j, pos);
-
- // Creates the left leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(19+i*4+j, rank);
- if ( j == 0 ) parent = 0;
- else parent = 19+i*4+j-1;
- m_object->SetObjectParent(19+i*4+j, parent);
- pModFile->ReadModel(name);
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- pos.x = table[i*12+j*3+0];
- pos.y = table[i*12+j*3+1];
- pos.z = -table[i*12+j*3+2];
- m_object->SetPosition(19+i*4+j, pos);
- }
- }
-
- // Creates the right mandible.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(35, rank);
- m_object->SetObjectParent(35, 1);
- pModFile->ReadModel("objects\\spider7.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(35, Math::Vector(0.0f, 0.0f, -0.3f));
-
- // Creates the left mandible.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(36, rank);
- m_object->SetObjectParent(36, 1);
- pModFile->ReadModel("objects\\spider7.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(36, Math::Vector(0.0f, 0.0f, 0.3f));
-
- m_object->CreateShadowCircle(4.0f, 0.5f);
-
- CreatePhysics();
- m_object->SetFloorHeight(0.0f);
-
- pos = m_object->RetPosition(0);
- m_object->SetPosition(0, pos); // to display the shadows immediately
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-// Creates the physics of the object.
-
-void CMotionSpider::CreatePhysics()
-{
- Character* character;
- int i;
-
- int member_march[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // in the air:
- 60,25,0, 60,0,0, 60,-25,0, 60,-50,0, // t0: thighs 1..4
- -35,40,0, -35,0,0, -35,0,0, -35,-40,0, // t0: legs 1..4
- -65,0,-30, -65,0,0, -65,0,0, -65,0,30, // t0: feet 1..4
- 25,0,0, 25,0,0, 25,0,0, 25,0,0, // t0: fingers 1..4
- // on the ground:
- 30,15,0, 30,-10,0, 30,-35,0, 30,-60,0, // t1: thighs 1..4
- -10,40,0, -45,0,0, -45,0,0, -45,-40,0, // t1: legs 1..4
- -90,0,0, -20,0,0, -20,0,0, -20,0,0, // t1: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t1: fingers 1..4
- // on the ground back:
- 35,35,0, 40,10,0, 40,-15,0, 40,-40,0, // t2: thighs 1..4
- -35,40,0, -35,0,0, -35,0,0, -25,-40,0, // t2: legs 1..4
- -50,-25,-30, -65,0,0, -65,0,0, -90,0,30, // t2: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t2: fingers 1..4
- };
-
- int member_stop[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // in the air:
- 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t0: thighs 1..4
- -35,40,0, -45,0,0, -45,0,0, -45,-40,0, // t0: legs 1..4
- -50,-25,-30, -20,0,0, -20,0,0, -20,0,30, // t0: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t0: fingers 1..4
- // on the ground:
- 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t1: thighs 1..4
- -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // t1: legs 1..4
- -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // t1: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t1: fingers 1..4
- // on the ground back:
- 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t2: thighs 1..4
- -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // t2: legs 1..4
- -50,-25,-30, -20,0,0, -20,0,0, -20,0,30, // t2: feet 1..4
- -10,0,0, -10,0,0, -10,0,0, -10,0,0, // t2: fingers 1..4
- };
-
- int member_spec[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // burning:
- 30,25,0, 30,0,0, 30,-25,0, 30,-50,0, // s0: thighs 1..4
- -45,0,0, -45,0,0, -45,0,0, -45,0,0, // s0: legs 1..4
- -20,0,0, -20,0,0, -20,0,0, -20,0,0, // s0: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s0: fingers 1..4
- // destroyed:
- 30,25,0, 30,0,0, 30,-25,0, 30,-50,0, // s1: thighs 1..4
- -45,0,0, -45,0,0, -45,0,0, -45,0,0, // s1: legs 1..4
- -20,0,0, -20,0,0, -20,0,0, -20,0,0, // s1: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s1: fingers 1..4
- // explodes:
- 40,25,0, 40,0,0, 40,-25,0, 40,-50,0, // s2: thighs 1..4
- -55,0,0, -55,0,0, -55,0,0, -55,0,0, // s2: legs 1..4
- -30,0,0, -30,0,0, -30,0,0, -30,0,0, // s2: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s2: fingers 1..4
- // back1 :
- 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // s3: thighs 1..4
- -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // s3: legs 1..4
- -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // s3: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s3: fingers 1..4
- // back2 :
- 15,35,0, 15,0,0, 15,-25,0, 15,-50,0, // s4: thighs 1..4
- -60,40,0, -60,0,0, -60,0,0, -60,-40,0, // s4: legs 1..4
- -65,-25,-30, -65,0,0, -65,0,0, -65,0,0, // s4: feet 1..4
- -15,0,0, -15,0,0, -15,0,0, -15,0,0, // s4: fingers 1..4
- // back3 :
- 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // s5: thighs 1..4
- -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // s5: legs 1..4
- -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // s5: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s5: fingers 1..4
- };
-
- m_physics->SetType(TYPE_ROLLING);
-
- character = m_object->RetCharacter();
- character->wheelFront = 4.0f;
- character->wheelBack = 4.0f;
- character->wheelLeft = 6.0f;
- character->wheelRight = 6.0f;
- character->height = 0.6f;
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 12.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 12.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 15.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 10.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 20.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 40.0f);
-
- for ( i=0 ; i<3*4*4*3 ; i++ )
- {
- m_armAngles[3*4*4*3*MS_MARCH+i] = member_march[i];
- }
- for ( i=0 ; i<3*4*4*3 ; i++ )
- {
- m_armAngles[3*4*4*3*MS_STOP+i] = member_stop[i];
- }
- for ( i=0 ; i<3*4*4*6 ; i++ )
- {
- m_armAngles[3*4*4*3*MS_SPEC+i] = member_spec[i];
- }
-}
-
-
-// Management of an event.
-
-bool CMotionSpider::EventProcess(const Event &event)
-{
- CMotion::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
-#if ADJUST_ANGLE
- int i;
-
- if ( event.param == 'A' ) m_armTimeIndex++;
- if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
-
- if ( event.param == 'Q' ) m_armPartIndex++;
- if ( m_armPartIndex >= 4 ) m_armPartIndex = 0;
-
- if ( event.param == 'W' ) m_armMemberIndex++;
- if ( m_armMemberIndex >= 4 ) m_armMemberIndex = 0;
-
- i = m_armMemberIndex*3;
- i += m_armPartIndex*3*4;
- i += m_armTimeIndex*3*4*4;
-
- if ( event.param == 'E' ) m_armAngles[i+0] += 5;
- if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
- if ( event.param == 'R' ) m_armAngles[i+1] += 5;
- if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
- if ( event.param == 'T' ) m_armAngles[i+2] += 5;
- if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
- if ( event.param == 'Z' ) m_armAngles[i+3] += 5;
- if ( event.param == 'H' ) m_armAngles[i+3] -= 5;
-
- if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
-#endif
- }
-
- return true;
-}
-
-// Management of an event.
-
-bool CMotionSpider::EventFrame(const Event &event)
-{
- Math::Vector dir, pos, speed;
- Math::Point dim;
- float s, a, prog, time;
- float tSt[12], tNd[12];
- int i, ii, st, nd, action;
- bool bStop;
-
- if ( m_engine->RetPause() ) return true;
- if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
-
- s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
- a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f);
-
- if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
-
- m_armTimeAbs += event.rTime;
- m_armTimeAction += event.rTime;
- m_armTimeMarch += (s)*event.rTime*0.15f;
- m_armMember += (s+a)*event.rTime*0.15f;
-
- bStop = ( a == 0.0f && s == 0.0f ); // stop?
-
- action = MS_MARCH; // waslking
- if ( s == 0.0f && a == 0.0f )
- {
- action = MS_STOP; // stop
- }
-
- if ( bStop )
- {
- prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
- a = Math::Mod(m_armMember, 1.0f);
- a = (prog-a)*event.rTime*2.0f; // stop position just pleasantly
- m_armMember += a;
- }
-
- if ( m_object->RetRuin() ) // destroyed?
- {
- m_actionType = MSS_RUIN;
- }
- if ( m_object->RetBurn() ) // burning?
- {
- if ( m_object->RetFixed() )
- {
- m_actionType = MSS_BURN;
- }
- else
- {
- m_actionType = -1;
- }
- }
-
- for ( i=0 ; i<8 ; i++ ) // the 8 legs
- {
- if ( m_actionType != -1 ) // special action in progress?
- {
- st = 3*4*4*3*MS_SPEC + 3*4*4*m_actionType + (i%4)*3;
- nd = st;
- time = event.rTime*m_actionTime;
- m_armTimeAction = 0.0f;
- }
- else
- {
-//? if ( i < 4 ) prog = Math::Mod(m_armMember+(2.0f-(i%4))*0.25f+0.0f, 1.0f);
-//? else prog = Math::Mod(m_armMember+(2.0f-(i%4))*0.25f+0.3f, 1.0f);
- if ( i < 4 ) prog = Math::Mod(m_armMember+(2.0f-(i%4))*0.25f+0.0f, 1.0f);
- else prog = Math::Mod(m_armMember+(2.0f-(i%4))*0.25f+0.5f, 1.0f);
- if ( m_bArmStop )
- {
- prog = (float)m_armTimeIndex/3.0f;
- action = MS_MARCH;
- }
- if ( prog < 0.33f ) // t0..t1 ?
- {
- prog = prog/0.33f; // 0..1
- st = 0; // index start
- nd = 1; // index end
- }
- else if ( prog < 0.67f ) // t1..t2 ?
- {
- prog = (prog-0.33f)/0.33f; // 0..1
- st = 1; // index start
- nd = 2; // index end
- }
- else // t2..t0 ?
- {
- prog = (prog-0.67f)/0.33f; // 0..1
- st = 2; // index start
- nd = 0; // index end
- }
- st = 3*4*4*3*action + st*3*4*4 + (i%4)*3;
- nd = 3*4*4*3*action + nd*3*4*4 + (i%4)*3;
-
- // Less and less soft ...
-//? time = event.rTime*(2.0f+Math::Min(m_armTimeAction*20.0f, 40.0f));
- time = event.rTime*10.0f;
- }
-
- tSt[ 0] = m_armAngles[st+ 0]; // x
- tSt[ 1] = m_armAngles[st+ 1]; // y
- tSt[ 2] = m_armAngles[st+ 2]; // z
- tSt[ 3] = m_armAngles[st+12]; // x
- tSt[ 4] = m_armAngles[st+13]; // y
- tSt[ 5] = m_armAngles[st+14]; // z
- tSt[ 6] = m_armAngles[st+24]; // x
- tSt[ 7] = m_armAngles[st+25]; // y
- tSt[ 8] = m_armAngles[st+26]; // z
- tSt[ 9] = m_armAngles[st+36]; // x
- tSt[10] = m_armAngles[st+37]; // y
- tSt[11] = m_armAngles[st+38]; // z
-
- tNd[ 0] = m_armAngles[nd+ 0]; // x
- tNd[ 1] = m_armAngles[nd+ 1]; // y
- tNd[ 2] = m_armAngles[nd+ 2]; // z
- tNd[ 3] = m_armAngles[nd+12]; // x
- tNd[ 4] = m_armAngles[nd+13]; // y
- tNd[ 5] = m_armAngles[nd+14]; // z
- tNd[ 6] = m_armAngles[nd+24]; // x
- tNd[ 7] = m_armAngles[nd+25]; // y
- tNd[ 8] = m_armAngles[nd+26]; // z
- tNd[ 9] = m_armAngles[nd+36]; // z
- tNd[10] = m_armAngles[nd+37]; // z
- tNd[11] = m_armAngles[nd+38]; // z
-
- if ( m_actionType == MSS_BACK2 ) // on the back?
- {
- for ( ii=0 ; ii<12 ; ii++ )
- {
- tSt[ii] += Math::Rand()*20.0f;
- tNd[ii] = tSt[ii];
- }
-//? time = 100.0f;
- time = event.rTime*10.0f;
- }
-
- if ( i < 4 ) // right leg (1..4) ?
- {
- m_object->SetAngleX(3+4*i+0, Math::Smooth(m_object->RetAngleX(3+4*i+0), Math::PropAngle(tSt[ 0], tNd[ 0], prog), time));
- m_object->SetAngleY(3+4*i+0, Math::Smooth(m_object->RetAngleY(3+4*i+0), Math::PropAngle(tSt[ 1], tNd[ 1], prog), time));
- m_object->SetAngleZ(3+4*i+0, Math::Smooth(m_object->RetAngleZ(3+4*i+0), Math::PropAngle(tSt[ 2], tNd[ 2], prog), time));
- m_object->SetAngleX(3+4*i+1, Math::Smooth(m_object->RetAngleX(3+4*i+1), Math::PropAngle(tSt[ 3], tNd[ 3], prog), time));
- m_object->SetAngleY(3+4*i+1, Math::Smooth(m_object->RetAngleY(3+4*i+1), Math::PropAngle(tSt[ 4], tNd[ 4], prog), time));
- m_object->SetAngleZ(3+4*i+1, Math::Smooth(m_object->RetAngleZ(3+4*i+1), Math::PropAngle(tSt[ 5], tNd[ 5], prog), time));
- m_object->SetAngleX(3+4*i+2, Math::Smooth(m_object->RetAngleX(3+4*i+2), Math::PropAngle(tSt[ 6], tNd[ 6], prog), time));
- m_object->SetAngleY(3+4*i+2, Math::Smooth(m_object->RetAngleY(3+4*i+2), Math::PropAngle(tSt[ 7], tNd[ 7], prog), time));
- m_object->SetAngleZ(3+4*i+2, Math::Smooth(m_object->RetAngleZ(3+4*i+2), Math::PropAngle(tSt[ 8], tNd[ 8], prog), time));
- m_object->SetAngleX(3+4*i+3, Math::Smooth(m_object->RetAngleX(3+4*i+3), Math::PropAngle(tSt[ 9], tNd[ 9], prog), time));
- m_object->SetAngleY(3+4*i+3, Math::Smooth(m_object->RetAngleY(3+4*i+3), Math::PropAngle(tSt[10], tNd[10], prog), time));
- m_object->SetAngleZ(3+4*i+3, Math::Smooth(m_object->RetAngleZ(3+4*i+3), Math::PropAngle(tSt[11], tNd[11], prog), time));
- }
- else // left leg (5..8) ?
- {
- m_object->SetAngleX(3+4*i+0, Math::Smooth(m_object->RetAngleX(3+4*i+0), Math::PropAngle(-tSt[ 0], -tNd[ 0], prog), time));
- m_object->SetAngleY(3+4*i+0, Math::Smooth(m_object->RetAngleY(3+4*i+0), Math::PropAngle(-tSt[ 1], -tNd[ 1], prog), time));
- m_object->SetAngleZ(3+4*i+0, Math::Smooth(m_object->RetAngleZ(3+4*i+0), Math::PropAngle( tSt[ 2], tNd[ 2], prog), time));
- m_object->SetAngleX(3+4*i+1, Math::Smooth(m_object->RetAngleX(3+4*i+1), Math::PropAngle(-tSt[ 3], -tNd[ 3], prog), time));
- m_object->SetAngleY(3+4*i+1, Math::Smooth(m_object->RetAngleY(3+4*i+1), Math::PropAngle(-tSt[ 4], -tNd[ 4], prog), time));
- m_object->SetAngleZ(3+4*i+1, Math::Smooth(m_object->RetAngleZ(3+4*i+1), Math::PropAngle( tSt[ 5], tNd[ 5], prog), time));
- m_object->SetAngleX(3+4*i+2, Math::Smooth(m_object->RetAngleX(3+4*i+2), Math::PropAngle(-tSt[ 6], -tNd[ 6], prog), time));
- m_object->SetAngleY(3+4*i+2, Math::Smooth(m_object->RetAngleY(3+4*i+2), Math::PropAngle(-tSt[ 7], -tNd[ 7], prog), time));
- m_object->SetAngleZ(3+4*i+2, Math::Smooth(m_object->RetAngleZ(3+4*i+2), Math::PropAngle( tSt[ 8], tNd[ 8], prog), time));
- m_object->SetAngleX(3+4*i+3, Math::Smooth(m_object->RetAngleX(3+4*i+3), Math::PropAngle(-tSt[ 9], -tNd[ 9], prog), time));
- m_object->SetAngleY(3+4*i+3, Math::Smooth(m_object->RetAngleY(3+4*i+3), Math::PropAngle(-tSt[10], -tNd[10], prog), time));
- m_object->SetAngleZ(3+4*i+3, Math::Smooth(m_object->RetAngleZ(3+4*i+3), Math::PropAngle( tSt[11], tNd[11], prog), time));
- }
- }
-
-#if ADJUST_ANGLE
- if ( m_object->RetSelect() )
- {
- char s[100];
- sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
- m_engine->SetInfoText(4, s);
- }
-#endif
-
- if ( m_actionType == MSS_BURN ) // burning?
- {
- dir = Math::Vector(Math::PI, 0.0f, 0.0f);
- SetCirVibration(dir);
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetLinVibration(dir);
- SetInclinaison(dir);
-
- time = event.rTime*1.0f;
- m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), 0.0f, time)); // head
- }
- else if ( m_actionType == MSS_RUIN ) // destroyed?
- {
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetLinVibration(dir);
- SetCirVibration(dir);
- SetInclinaison(dir);
- }
- else if ( m_actionType == MSS_EXPLO ) // exploded?
- {
- m_object->SetZoomY(1, 1.0f+m_progress);
- m_object->SetZoomZ(1, 1.0f+m_progress);
- m_object->SetZoomX(1, 1.0f+m_progress/2.0f);
-
- dir.x = (Math::Rand()-0.5f)*0.1f*m_progress;
- dir.y = (Math::Rand()-0.5f)*0.1f*m_progress;
- dir.z = (Math::Rand()-0.5f)*0.1f*m_progress;
- m_object->SetCirVibration(dir);
- }
- else if ( m_actionType == MSS_BACK1 ) // turns on the back?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
- {
- m_lastParticule = m_armTimeAbs;
-
- pos = m_object->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = Math::Rand()*5.0f;
- dim.x = Math::Rand()*3.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
-
- if ( m_progress < 0.5f )
- {
- dir.x = 0.0f;
- dir.y = powf(m_progress/0.5f, 2.0f)*12.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
- else
- {
- dir.x = 0.0f;
- dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*12.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
- dir.x = m_progress*Math::PI;
- dir.y = 0.0f;
- dir.z = 0.0f;
- SetCirVibration(dir);
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetInclinaison(dir);
-
- if ( m_progress >= 1.0f )
- {
- SetAction(MSS_BACK2, 55.0f+Math::Rand()*10.0f);
- }
- }
- else if ( m_actionType == MSS_BACK2 ) // moves on the back?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
- {
- m_lastParticule = m_armTimeAbs;
-
- if ( rand()%10 == 0 )
- {
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*8.0f;
- pos.z += (Math::Rand()-0.5f)*8.0f;
- pos.y -= 1.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = Math::Rand()*2.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
- }
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetLinVibration(dir);
- dir.x = sinf(m_armTimeAbs* 3.0f)*0.20f+
- sinf(m_armTimeAbs* 6.0f)*0.20f+
- sinf(m_armTimeAbs*10.0f)*0.20f+
- sinf(m_armTimeAbs*17.0f)*0.30f+Math::PI;
- dir.y = sinf(m_armTimeAbs* 4.0f)*0.02f+
- sinf(m_armTimeAbs* 5.0f)*0.02f+
- sinf(m_armTimeAbs*11.0f)*0.02f+
- sinf(m_armTimeAbs*18.0f)*0.03f;
- dir.z = sinf(m_armTimeAbs* 2.0f)*0.02f+
- sinf(m_armTimeAbs* 7.0f)*0.02f+
- sinf(m_armTimeAbs*13.0f)*0.02f+
- sinf(m_armTimeAbs*15.0f)*0.03f;
- SetCirVibration(dir);
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetInclinaison(dir);
-
- m_object->SetAngleY(1, sinf(m_armTimeAbs*5.0f)*0.05f); // tail
- m_object->SetAngleY(2, cosf(m_armTimeAbs*5.0f)*0.20f); // head
- m_object->SetAngleZ(1, 0.4f); // tail
- m_object->SetAngleZ(2, 0.0f); // head
-
- if ( m_progress >= 1.0f )
- {
- SetAction(MSS_BACK3, 0.4f);
- }
- }
- else if ( m_actionType == MSS_BACK3 ) // recovers on the legs?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
- {
- m_lastParticule = m_armTimeAbs;
-
- pos = m_object->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = Math::Rand()*5.0f;
- dim.x = Math::Rand()*3.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
-
- if ( m_progress < 0.5f )
- {
- dir.x = 0.0f;
- dir.y = powf(m_progress/0.5f, 2.0f)*5.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
- else
- {
- dir.x = 0.0f;
- dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*5.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
- dir.x = (1.0f-m_progress)*Math::PI;
- dir.y = 0.0f;
- dir.z = 0.0f;
- SetCirVibration(dir);
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetInclinaison(dir);
-
- if ( m_progress >= 1.0f )
- {
- SetAction(-1);
- m_object->SetFixed(false); // moving again
- }
- }
- else
- {
- if ( bStop )
- {
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetInclinaison(dir);
- }
- else
- {
- a = Math::Mod(m_armMember, 1.0f);
- if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
- else a = 3.0f-4.0f*a; // 1..-1
- dir.x = sinf(a)*0.05f;
-
- s = Math::Mod(m_armMember/2.0f, 1.0f);
- if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
- else s = 3.0f-4.0f*s; // 1..-1
- dir.z = sinf(s)*0.1f;
-
- dir.y = 0.0f;
- SetInclinaison(dir);
- }
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetLinVibration(dir);
- SetCirVibration(dir);
-
- m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.7f)*0.02f); // tail
- m_object->SetAngleX(1, sinf(m_armTimeAbs*1.3f)*0.05f);
- m_object->SetAngleY(1, sinf(m_armTimeAbs*2.4f)*0.10f);
- m_object->SetZoom(1, 1.0f+sinf(m_armTimeAbs*3.3f)*0.05f);
-
- m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.4f)*0.20f); // head
- m_object->SetAngleX(2, sinf(m_armTimeAbs*1.9f)*0.10f);
- m_object->SetAngleY(2, sinf(m_armTimeAbs*2.1f)*0.10f);
-
- m_object->SetAngleY(35, sinf(m_armTimeAbs*3.1f)*0.20f); // mandible
- m_object->SetAngleY(36, -sinf(m_armTimeAbs*3.1f)*0.20f); // mandible
- }
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionspider.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motionspider.h"
+
+#include "old/modfile.h"
+#include "old/particule.h"
+#include "physics/physics.h"
+
+
+
+#define ADJUST_ANGLE false // true -> adjusts the angles of the members
+const float START_TIME = 1000.0f; // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionSpider::CMotionSpider(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeMarch = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLastAction = -1;
+ m_bArmStop = false;
+ m_lastParticule = 0.0f;
+}
+
+// Object's destructor.
+
+CMotionSpider::~CMotionSpider()
+{
+}
+
+
+// Removes an object.
+
+void CMotionSpider::DeleteObject(bool bAll)
+{
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+bool CMotionSpider::Create(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank, i, j, parent;
+ char name[50];
+
+ float table[] =
+ {
+ // x y z
+ 0.6f, 0.0f, 0.0f, // back leg
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+
+ 0.8f, 0.0f, -0.2f, // middle-back leg
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+
+ 1.0f, 0.0f, -0.2f, // middle-front leg
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+
+ 1.2f, 0.0f, 0.0f, // front leg
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+ };
+
+ if ( m_engine->RetRestCreate() < 3+32+2 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates the main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\spider0.mod"); // doesn't exist
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have a obligatory collision
+ // with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(Math::Vector(0.0f, -2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
+ m_object->SetGlobalSphere(Math::Vector(-0.5f, 1.0f, 0.0f), 4.0f);
+
+ // Creates the abdomen.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\spider1.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(1.0f, 0.0f, 0.0f));
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\spider2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(1.0f, 0.0f, 0.0f));
+
+ // Creates legs.
+ for ( i=0 ; i<4 ; i++ )
+ {
+ for ( j=0 ; j<4 ; j++ )
+ {
+ sprintf(name, "objects\\spider%d.mod", j+3); // 3..6
+
+ // Creates the right leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3+i*4+j, rank);
+ if ( j == 0 ) parent = 0;
+ else parent = 3+i*4+j-1;
+ m_object->SetObjectParent(3+i*4+j, parent);
+ pModFile->ReadModel(name);
+ pModFile->CreateEngineObject(rank);
+ pos.x = table[i*12+j*3+0];
+ pos.y = table[i*12+j*3+1];
+ pos.z = table[i*12+j*3+2];
+ m_object->SetPosition(3+i*4+j, pos);
+
+ // Creates the left leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(19+i*4+j, rank);
+ if ( j == 0 ) parent = 0;
+ else parent = 19+i*4+j-1;
+ m_object->SetObjectParent(19+i*4+j, parent);
+ pModFile->ReadModel(name);
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ pos.x = table[i*12+j*3+0];
+ pos.y = table[i*12+j*3+1];
+ pos.z = -table[i*12+j*3+2];
+ m_object->SetPosition(19+i*4+j, pos);
+ }
+ }
+
+ // Creates the right mandible.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(35, rank);
+ m_object->SetObjectParent(35, 1);
+ pModFile->ReadModel("objects\\spider7.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(35, Math::Vector(0.0f, 0.0f, -0.3f));
+
+ // Creates the left mandible.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(36, rank);
+ m_object->SetObjectParent(36, 1);
+ pModFile->ReadModel("objects\\spider7.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(36, Math::Vector(0.0f, 0.0f, 0.3f));
+
+ m_object->CreateShadowCircle(4.0f, 0.5f);
+
+ CreatePhysics();
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+// Creates the physics of the object.
+
+void CMotionSpider::CreatePhysics()
+{
+ Character* character;
+ int i;
+
+ int member_march[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // in the air:
+ 60,25,0, 60,0,0, 60,-25,0, 60,-50,0, // t0: thighs 1..4
+ -35,40,0, -35,0,0, -35,0,0, -35,-40,0, // t0: legs 1..4
+ -65,0,-30, -65,0,0, -65,0,0, -65,0,30, // t0: feet 1..4
+ 25,0,0, 25,0,0, 25,0,0, 25,0,0, // t0: fingers 1..4
+ // on the ground:
+ 30,15,0, 30,-10,0, 30,-35,0, 30,-60,0, // t1: thighs 1..4
+ -10,40,0, -45,0,0, -45,0,0, -45,-40,0, // t1: legs 1..4
+ -90,0,0, -20,0,0, -20,0,0, -20,0,0, // t1: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t1: fingers 1..4
+ // on the ground back:
+ 35,35,0, 40,10,0, 40,-15,0, 40,-40,0, // t2: thighs 1..4
+ -35,40,0, -35,0,0, -35,0,0, -25,-40,0, // t2: legs 1..4
+ -50,-25,-30, -65,0,0, -65,0,0, -90,0,30, // t2: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t2: fingers 1..4
+ };
+
+ int member_stop[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // in the air:
+ 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t0: thighs 1..4
+ -35,40,0, -45,0,0, -45,0,0, -45,-40,0, // t0: legs 1..4
+ -50,-25,-30, -20,0,0, -20,0,0, -20,0,30, // t0: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t0: fingers 1..4
+ // on the ground:
+ 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t1: thighs 1..4
+ -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // t1: legs 1..4
+ -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // t1: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t1: fingers 1..4
+ // on the ground back:
+ 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t2: thighs 1..4
+ -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // t2: legs 1..4
+ -50,-25,-30, -20,0,0, -20,0,0, -20,0,30, // t2: feet 1..4
+ -10,0,0, -10,0,0, -10,0,0, -10,0,0, // t2: fingers 1..4
+ };
+
+ int member_spec[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // burning:
+ 30,25,0, 30,0,0, 30,-25,0, 30,-50,0, // s0: thighs 1..4
+ -45,0,0, -45,0,0, -45,0,0, -45,0,0, // s0: legs 1..4
+ -20,0,0, -20,0,0, -20,0,0, -20,0,0, // s0: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s0: fingers 1..4
+ // destroyed:
+ 30,25,0, 30,0,0, 30,-25,0, 30,-50,0, // s1: thighs 1..4
+ -45,0,0, -45,0,0, -45,0,0, -45,0,0, // s1: legs 1..4
+ -20,0,0, -20,0,0, -20,0,0, -20,0,0, // s1: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s1: fingers 1..4
+ // explodes:
+ 40,25,0, 40,0,0, 40,-25,0, 40,-50,0, // s2: thighs 1..4
+ -55,0,0, -55,0,0, -55,0,0, -55,0,0, // s2: legs 1..4
+ -30,0,0, -30,0,0, -30,0,0, -30,0,0, // s2: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s2: fingers 1..4
+ // back1 :
+ 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // s3: thighs 1..4
+ -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // s3: legs 1..4
+ -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // s3: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s3: fingers 1..4
+ // back2 :
+ 15,35,0, 15,0,0, 15,-25,0, 15,-50,0, // s4: thighs 1..4
+ -60,40,0, -60,0,0, -60,0,0, -60,-40,0, // s4: legs 1..4
+ -65,-25,-30, -65,0,0, -65,0,0, -65,0,0, // s4: feet 1..4
+ -15,0,0, -15,0,0, -15,0,0, -15,0,0, // s4: fingers 1..4
+ // back3 :
+ 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // s5: thighs 1..4
+ -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // s5: legs 1..4
+ -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // s5: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s5: fingers 1..4
+ };
+
+ m_physics->SetType(TYPE_ROLLING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 6.0f;
+ character->wheelRight = 6.0f;
+ character->height = 0.6f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 12.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 12.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 15.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 10.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 40.0f);
+
+ for ( i=0 ; i<3*4*4*3 ; i++ )
+ {
+ m_armAngles[3*4*4*3*MS_MARCH+i] = member_march[i];
+ }
+ for ( i=0 ; i<3*4*4*3 ; i++ )
+ {
+ m_armAngles[3*4*4*3*MS_STOP+i] = member_stop[i];
+ }
+ for ( i=0 ; i<3*4*4*6 ; i++ )
+ {
+ m_armAngles[3*4*4*3*MS_SPEC+i] = member_spec[i];
+ }
+}
+
+
+// Management of an event.
+
+bool CMotionSpider::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if ADJUST_ANGLE
+ int i;
+
+ if ( event.param == 'A' ) m_armTimeIndex++;
+ if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
+
+ if ( event.param == 'Q' ) m_armPartIndex++;
+ if ( m_armPartIndex >= 4 ) m_armPartIndex = 0;
+
+ if ( event.param == 'W' ) m_armMemberIndex++;
+ if ( m_armMemberIndex >= 4 ) m_armMemberIndex = 0;
+
+ i = m_armMemberIndex*3;
+ i += m_armPartIndex*3*4;
+ i += m_armTimeIndex*3*4*4;
+
+ if ( event.param == 'E' ) m_armAngles[i+0] += 5;
+ if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
+ if ( event.param == 'R' ) m_armAngles[i+1] += 5;
+ if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
+ if ( event.param == 'T' ) m_armAngles[i+2] += 5;
+ if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
+ if ( event.param == 'Z' ) m_armAngles[i+3] += 5;
+ if ( event.param == 'H' ) m_armAngles[i+3] -= 5;
+
+ if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
+#endif
+ }
+
+ return true;
+}
+
+// Management of an event.
+
+bool CMotionSpider::EventFrame(const Event &event)
+{
+ Math::Vector dir, pos, speed;
+ Math::Point dim;
+ float s, a, prog, time;
+ float tSt[12], tNd[12];
+ int i, ii, st, nd, action;
+ bool bStop;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
+ a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f);
+
+ if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armTimeAction += event.rTime;
+ m_armTimeMarch += (s)*event.rTime*0.15f;
+ m_armMember += (s+a)*event.rTime*0.15f;
+
+ bStop = ( a == 0.0f && s == 0.0f ); // stop?
+
+ action = MS_MARCH; // waslking
+ if ( s == 0.0f && a == 0.0f )
+ {
+ action = MS_STOP; // stop
+ }
+
+ if ( bStop )
+ {
+ prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
+ a = Math::Mod(m_armMember, 1.0f);
+ a = (prog-a)*event.rTime*2.0f; // stop position just pleasantly
+ m_armMember += a;
+ }
+
+ if ( m_object->RetRuin() ) // destroyed?
+ {
+ m_actionType = MSS_RUIN;
+ }
+ if ( m_object->RetBurn() ) // burning?
+ {
+ if ( m_object->RetFixed() )
+ {
+ m_actionType = MSS_BURN;
+ }
+ else
+ {
+ m_actionType = -1;
+ }
+ }
+
+ for ( i=0 ; i<8 ; i++ ) // the 8 legs
+ {
+ if ( m_actionType != -1 ) // special action in progress?
+ {
+ st = 3*4*4*3*MS_SPEC + 3*4*4*m_actionType + (i%4)*3;
+ nd = st;
+ time = event.rTime*m_actionTime;
+ m_armTimeAction = 0.0f;
+ }
+ else
+ {
+//? if ( i < 4 ) prog = Math::Mod(m_armMember+(2.0f-(i%4))*0.25f+0.0f, 1.0f);
+//? else prog = Math::Mod(m_armMember+(2.0f-(i%4))*0.25f+0.3f, 1.0f);
+ if ( i < 4 ) prog = Math::Mod(m_armMember+(2.0f-(i%4))*0.25f+0.0f, 1.0f);
+ else prog = Math::Mod(m_armMember+(2.0f-(i%4))*0.25f+0.5f, 1.0f);
+ if ( m_bArmStop )
+ {
+ prog = (float)m_armTimeIndex/3.0f;
+ action = MS_MARCH;
+ }
+ if ( prog < 0.33f ) // t0..t1 ?
+ {
+ prog = prog/0.33f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.67f ) // t1..t2 ?
+ {
+ prog = (prog-0.33f)/0.33f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.67f)/0.33f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ st = 3*4*4*3*action + st*3*4*4 + (i%4)*3;
+ nd = 3*4*4*3*action + nd*3*4*4 + (i%4)*3;
+
+ // Less and less soft ...
+//? time = event.rTime*(2.0f+Math::Min(m_armTimeAction*20.0f, 40.0f));
+ time = event.rTime*10.0f;
+ }
+
+ tSt[ 0] = m_armAngles[st+ 0]; // x
+ tSt[ 1] = m_armAngles[st+ 1]; // y
+ tSt[ 2] = m_armAngles[st+ 2]; // z
+ tSt[ 3] = m_armAngles[st+12]; // x
+ tSt[ 4] = m_armAngles[st+13]; // y
+ tSt[ 5] = m_armAngles[st+14]; // z
+ tSt[ 6] = m_armAngles[st+24]; // x
+ tSt[ 7] = m_armAngles[st+25]; // y
+ tSt[ 8] = m_armAngles[st+26]; // z
+ tSt[ 9] = m_armAngles[st+36]; // x
+ tSt[10] = m_armAngles[st+37]; // y
+ tSt[11] = m_armAngles[st+38]; // z
+
+ tNd[ 0] = m_armAngles[nd+ 0]; // x
+ tNd[ 1] = m_armAngles[nd+ 1]; // y
+ tNd[ 2] = m_armAngles[nd+ 2]; // z
+ tNd[ 3] = m_armAngles[nd+12]; // x
+ tNd[ 4] = m_armAngles[nd+13]; // y
+ tNd[ 5] = m_armAngles[nd+14]; // z
+ tNd[ 6] = m_armAngles[nd+24]; // x
+ tNd[ 7] = m_armAngles[nd+25]; // y
+ tNd[ 8] = m_armAngles[nd+26]; // z
+ tNd[ 9] = m_armAngles[nd+36]; // z
+ tNd[10] = m_armAngles[nd+37]; // z
+ tNd[11] = m_armAngles[nd+38]; // z
+
+ if ( m_actionType == MSS_BACK2 ) // on the back?
+ {
+ for ( ii=0 ; ii<12 ; ii++ )
+ {
+ tSt[ii] += Math::Rand()*20.0f;
+ tNd[ii] = tSt[ii];
+ }
+//? time = 100.0f;
+ time = event.rTime*10.0f;
+ }
+
+ if ( i < 4 ) // right leg (1..4) ?
+ {
+ m_object->SetAngleX(3+4*i+0, Math::Smooth(m_object->RetAngleX(3+4*i+0), Math::PropAngle(tSt[ 0], tNd[ 0], prog), time));
+ m_object->SetAngleY(3+4*i+0, Math::Smooth(m_object->RetAngleY(3+4*i+0), Math::PropAngle(tSt[ 1], tNd[ 1], prog), time));
+ m_object->SetAngleZ(3+4*i+0, Math::Smooth(m_object->RetAngleZ(3+4*i+0), Math::PropAngle(tSt[ 2], tNd[ 2], prog), time));
+ m_object->SetAngleX(3+4*i+1, Math::Smooth(m_object->RetAngleX(3+4*i+1), Math::PropAngle(tSt[ 3], tNd[ 3], prog), time));
+ m_object->SetAngleY(3+4*i+1, Math::Smooth(m_object->RetAngleY(3+4*i+1), Math::PropAngle(tSt[ 4], tNd[ 4], prog), time));
+ m_object->SetAngleZ(3+4*i+1, Math::Smooth(m_object->RetAngleZ(3+4*i+1), Math::PropAngle(tSt[ 5], tNd[ 5], prog), time));
+ m_object->SetAngleX(3+4*i+2, Math::Smooth(m_object->RetAngleX(3+4*i+2), Math::PropAngle(tSt[ 6], tNd[ 6], prog), time));
+ m_object->SetAngleY(3+4*i+2, Math::Smooth(m_object->RetAngleY(3+4*i+2), Math::PropAngle(tSt[ 7], tNd[ 7], prog), time));
+ m_object->SetAngleZ(3+4*i+2, Math::Smooth(m_object->RetAngleZ(3+4*i+2), Math::PropAngle(tSt[ 8], tNd[ 8], prog), time));
+ m_object->SetAngleX(3+4*i+3, Math::Smooth(m_object->RetAngleX(3+4*i+3), Math::PropAngle(tSt[ 9], tNd[ 9], prog), time));
+ m_object->SetAngleY(3+4*i+3, Math::Smooth(m_object->RetAngleY(3+4*i+3), Math::PropAngle(tSt[10], tNd[10], prog), time));
+ m_object->SetAngleZ(3+4*i+3, Math::Smooth(m_object->RetAngleZ(3+4*i+3), Math::PropAngle(tSt[11], tNd[11], prog), time));
+ }
+ else // left leg (5..8) ?
+ {
+ m_object->SetAngleX(3+4*i+0, Math::Smooth(m_object->RetAngleX(3+4*i+0), Math::PropAngle(-tSt[ 0], -tNd[ 0], prog), time));
+ m_object->SetAngleY(3+4*i+0, Math::Smooth(m_object->RetAngleY(3+4*i+0), Math::PropAngle(-tSt[ 1], -tNd[ 1], prog), time));
+ m_object->SetAngleZ(3+4*i+0, Math::Smooth(m_object->RetAngleZ(3+4*i+0), Math::PropAngle( tSt[ 2], tNd[ 2], prog), time));
+ m_object->SetAngleX(3+4*i+1, Math::Smooth(m_object->RetAngleX(3+4*i+1), Math::PropAngle(-tSt[ 3], -tNd[ 3], prog), time));
+ m_object->SetAngleY(3+4*i+1, Math::Smooth(m_object->RetAngleY(3+4*i+1), Math::PropAngle(-tSt[ 4], -tNd[ 4], prog), time));
+ m_object->SetAngleZ(3+4*i+1, Math::Smooth(m_object->RetAngleZ(3+4*i+1), Math::PropAngle( tSt[ 5], tNd[ 5], prog), time));
+ m_object->SetAngleX(3+4*i+2, Math::Smooth(m_object->RetAngleX(3+4*i+2), Math::PropAngle(-tSt[ 6], -tNd[ 6], prog), time));
+ m_object->SetAngleY(3+4*i+2, Math::Smooth(m_object->RetAngleY(3+4*i+2), Math::PropAngle(-tSt[ 7], -tNd[ 7], prog), time));
+ m_object->SetAngleZ(3+4*i+2, Math::Smooth(m_object->RetAngleZ(3+4*i+2), Math::PropAngle( tSt[ 8], tNd[ 8], prog), time));
+ m_object->SetAngleX(3+4*i+3, Math::Smooth(m_object->RetAngleX(3+4*i+3), Math::PropAngle(-tSt[ 9], -tNd[ 9], prog), time));
+ m_object->SetAngleY(3+4*i+3, Math::Smooth(m_object->RetAngleY(3+4*i+3), Math::PropAngle(-tSt[10], -tNd[10], prog), time));
+ m_object->SetAngleZ(3+4*i+3, Math::Smooth(m_object->RetAngleZ(3+4*i+3), Math::PropAngle( tSt[11], tNd[11], prog), time));
+ }
+ }
+
+#if ADJUST_ANGLE
+ if ( m_object->RetSelect() )
+ {
+ char s[100];
+ sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
+ m_engine->SetInfoText(4, s);
+ }
+#endif
+
+ if ( m_actionType == MSS_BURN ) // burning?
+ {
+ dir = Math::Vector(Math::PI, 0.0f, 0.0f);
+ SetCirVibration(dir);
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ SetInclinaison(dir);
+
+ time = event.rTime*1.0f;
+ m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), 0.0f, time)); // head
+ }
+ else if ( m_actionType == MSS_RUIN ) // destroyed?
+ {
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ SetCirVibration(dir);
+ SetInclinaison(dir);
+ }
+ else if ( m_actionType == MSS_EXPLO ) // exploded?
+ {
+ m_object->SetZoomY(1, 1.0f+m_progress);
+ m_object->SetZoomZ(1, 1.0f+m_progress);
+ m_object->SetZoomX(1, 1.0f+m_progress/2.0f);
+
+ dir.x = (Math::Rand()-0.5f)*0.1f*m_progress;
+ dir.y = (Math::Rand()-0.5f)*0.1f*m_progress;
+ dir.z = (Math::Rand()-0.5f)*0.1f*m_progress;
+ m_object->SetCirVibration(dir);
+ }
+ else if ( m_actionType == MSS_BACK1 ) // turns on the back?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = Math::Rand()*5.0f;
+ dim.x = Math::Rand()*3.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+
+ if ( m_progress < 0.5f )
+ {
+ dir.x = 0.0f;
+ dir.y = powf(m_progress/0.5f, 2.0f)*12.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*12.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ dir.x = m_progress*Math::PI;
+ dir.y = 0.0f;
+ dir.z = 0.0f;
+ SetCirVibration(dir);
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(MSS_BACK2, 55.0f+Math::Rand()*10.0f);
+ }
+ }
+ else if ( m_actionType == MSS_BACK2 ) // moves on the back?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ if ( rand()%10 == 0 )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*8.0f;
+ pos.z += (Math::Rand()-0.5f)*8.0f;
+ pos.y -= 1.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = Math::Rand()*2.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+ }
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ dir.x = sinf(m_armTimeAbs* 3.0f)*0.20f+
+ sinf(m_armTimeAbs* 6.0f)*0.20f+
+ sinf(m_armTimeAbs*10.0f)*0.20f+
+ sinf(m_armTimeAbs*17.0f)*0.30f+Math::PI;
+ dir.y = sinf(m_armTimeAbs* 4.0f)*0.02f+
+ sinf(m_armTimeAbs* 5.0f)*0.02f+
+ sinf(m_armTimeAbs*11.0f)*0.02f+
+ sinf(m_armTimeAbs*18.0f)*0.03f;
+ dir.z = sinf(m_armTimeAbs* 2.0f)*0.02f+
+ sinf(m_armTimeAbs* 7.0f)*0.02f+
+ sinf(m_armTimeAbs*13.0f)*0.02f+
+ sinf(m_armTimeAbs*15.0f)*0.03f;
+ SetCirVibration(dir);
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*5.0f)*0.05f); // tail
+ m_object->SetAngleY(2, cosf(m_armTimeAbs*5.0f)*0.20f); // head
+ m_object->SetAngleZ(1, 0.4f); // tail
+ m_object->SetAngleZ(2, 0.0f); // head
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(MSS_BACK3, 0.4f);
+ }
+ }
+ else if ( m_actionType == MSS_BACK3 ) // recovers on the legs?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = Math::Rand()*5.0f;
+ dim.x = Math::Rand()*3.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+
+ if ( m_progress < 0.5f )
+ {
+ dir.x = 0.0f;
+ dir.y = powf(m_progress/0.5f, 2.0f)*5.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*5.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ dir.x = (1.0f-m_progress)*Math::PI;
+ dir.y = 0.0f;
+ dir.z = 0.0f;
+ SetCirVibration(dir);
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(-1);
+ m_object->SetFixed(false); // moving again
+ }
+ }
+ else
+ {
+ if ( bStop )
+ {
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+ }
+ else
+ {
+ a = Math::Mod(m_armMember, 1.0f);
+ if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
+ else a = 3.0f-4.0f*a; // 1..-1
+ dir.x = sinf(a)*0.05f;
+
+ s = Math::Mod(m_armMember/2.0f, 1.0f);
+ if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
+ else s = 3.0f-4.0f*s; // 1..-1
+ dir.z = sinf(s)*0.1f;
+
+ dir.y = 0.0f;
+ SetInclinaison(dir);
+ }
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ SetCirVibration(dir);
+
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.7f)*0.02f); // tail
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.3f)*0.05f);
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*2.4f)*0.10f);
+ m_object->SetZoom(1, 1.0f+sinf(m_armTimeAbs*3.3f)*0.05f);
+
+ m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.4f)*0.20f); // head
+ m_object->SetAngleX(2, sinf(m_armTimeAbs*1.9f)*0.10f);
+ m_object->SetAngleY(2, sinf(m_armTimeAbs*2.1f)*0.10f);
+
+ m_object->SetAngleY(35, sinf(m_armTimeAbs*3.1f)*0.20f); // mandible
+ m_object->SetAngleY(36, -sinf(m_armTimeAbs*3.1f)*0.20f); // mandible
+ }
+
+ return true;
+}
+
+
diff --git a/src/object/motion/motionspider.h b/src/object/motion/motionspider.h
index 6b34974..e9f052c 100644
--- a/src/object/motion/motionspider.h
+++ b/src/object/motion/motionspider.h
@@ -1,71 +1,71 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionspider.h
-
-#pragma once
-
-
-#include "object/motion/motion.h"
-
-
-
-enum MotionSpiderAction
-{
- MS_MARCH = 0,
- MS_STOP = 1,
- MS_SPEC = 2
-};
-
-enum MotionSpiderSpecialAction
-{
- MSS_BURN = 0,
- MSS_RUIN = 1,
- MSS_EXPLO = 2,
- MSS_BACK1 = 3,
- MSS_BACK2 = 4,
- MSS_BACK3 = 5
-};
-
-
-class CMotionSpider : public CMotion
-{
-public:
- CMotionSpider(CInstanceManager* iMan, CObject* object);
- ~CMotionSpider();
-
- void DeleteObject(bool bAll=false);
- bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- bool EventProcess(const Event &event);
-
-protected:
- void CreatePhysics();
- bool EventFrame(const Event &event);
-
-protected:
- float m_armMember;
- float m_armTimeAbs;
- float m_armTimeMarch;
- float m_armTimeAction;
- short m_armAngles[3*4*4*3*3 + 3*4*4*6];
- int m_armTimeIndex;
- int m_armPartIndex;
- int m_armMemberIndex;
- int m_armLastAction;
- bool m_bArmStop;
- float m_lastParticule;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionspider.h
+
+#pragma once
+
+
+#include "object/motion/motion.h"
+
+
+
+enum MotionSpiderAction
+{
+ MS_MARCH = 0,
+ MS_STOP = 1,
+ MS_SPEC = 2
+};
+
+enum MotionSpiderSpecialAction
+{
+ MSS_BURN = 0,
+ MSS_RUIN = 1,
+ MSS_EXPLO = 2,
+ MSS_BACK1 = 3,
+ MSS_BACK2 = 4,
+ MSS_BACK3 = 5
+};
+
+
+class CMotionSpider : public CMotion
+{
+public:
+ CMotionSpider(CInstanceManager* iMan, CObject* object);
+ ~CMotionSpider();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ bool EventProcess(const Event &event);
+
+protected:
+ void CreatePhysics();
+ bool EventFrame(const Event &event);
+
+protected:
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeMarch;
+ float m_armTimeAction;
+ short m_armAngles[3*4*4*3*3 + 3*4*4*6];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ bool m_bArmStop;
+ float m_lastParticule;
+};
+
diff --git a/src/object/motion/motiontoto.cpp b/src/object/motion/motiontoto.cpp
index 71e872a..f64570e 100644
--- a/src/object/motion/motiontoto.cpp
+++ b/src/object/motion/motiontoto.cpp
@@ -1,869 +1,869 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motiontoto.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motiontoto.h"
-
-#include "math/geometry.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "old/modfile.h"
-#include "object/robotmain.h"
-
-
-
-const float START_TIME = 1000.0f; // beginning of the relative time
-
-
-
-// Object's constructor.
-
-CMotionToto::CMotionToto(CInstanceManager* iMan, CObject* object)
- : CMotion(iMan, object)
-{
- m_time = 0.0f;
- m_bDisplayInfo = false;
- m_bQuickPos = false;
- m_bStartAction = false;
- m_speedAction = 20.0f;
- m_soundChannel = -1;
- m_clownRadius = 0.0f;
- m_clownDelay = 0.0f;
- m_clownTime = 0.0f;
- m_blinkTime = 0.0f;
- m_blinkProgress = -1.0f;
- m_lastMotorParticule = 0.0f;
- m_type = OBJECT_NULL;
- m_mousePos = Math::Point(0.0f, 0.0f);
-}
-
-// Object's destructor.
-
-CMotionToto::~CMotionToto()
-{
-}
-
-
-// Removes an object.
-
-void CMotionToto::DeleteObject(bool bAll)
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->Stop(m_soundChannel);
- m_soundChannel = -1;
- }
-}
-
-
-// Creates a vehicle traveling any lands on the ground.
-
-bool CMotionToto::Create(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 10 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- m_object->SetType(type);
-
- // Creates the head.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\toto1.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(0, pos);
- m_object->SetAngleY(0, angle);
-
- // Creates mouth.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\toto2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(1.00f, 0.17f, 0.00f));
-
- // Creates the left eye.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\toto3.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(0.85f, 1.04f, 0.25f));
- m_object->SetAngleY(2, -20.0f*Math::PI/180.0f);
-
- // Creates the right eye.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 0);
- pModFile->ReadModel("objects\\toto3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(0.85f, 1.04f, -0.25f));
- m_object->SetAngleY(3, 20.0f*Math::PI/180.0f);
-
- // Creates left antenna.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(4, rank);
- m_object->SetObjectParent(4, 0);
- pModFile->ReadModel("objects\\toto4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(4, Math::Vector(0.0f, 1.9f, 0.3f));
- m_object->SetAngleX(4, 30.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(5, rank);
- m_object->SetObjectParent(5, 4);
- pModFile->ReadModel("objects\\toto4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(5, Math::Vector(0.0f, 0.67f, 0.0f));
- m_object->SetAngleX(5, 30.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 5);
- pModFile->ReadModel("objects\\toto5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(0.0f, 0.70f, 0.0f));
- m_object->SetAngleX(6, 30.0f*Math::PI/180.0f);
-
- // Creates right antenna.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\toto4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, 1.9f, -0.3f));
- m_object->SetAngleX(7, -30.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 7);
- pModFile->ReadModel("objects\\toto4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(0.0f, 0.67f, 0.0f));
- m_object->SetAngleX(8, -30.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(9, rank);
- m_object->SetObjectParent(9, 8);
- pModFile->ReadModel("objects\\toto5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(9, Math::Vector(0.0f, 0.70f, 0.0f));
- m_object->SetAngleX(9, -30.0f*Math::PI/180.0f);
-
- m_object->SetZoom(0, 0.5f); // is little
- m_object->SetFloorHeight(0.0f);
-
- pos = m_object->RetPosition(0);
- m_object->SetPosition(0, pos); // to display the shadows immediately
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-
-// Beginning of the display of informations, with foo in the left margin.
-
-void CMotionToto::StartDisplayInfo()
-{
-return;
-//?
- m_bDisplayInfo = true;
-
- m_actionType = -1;
- m_actionTime = 0.0f;
- m_progress = 0.0f;
-
- m_object->SetAngleY(0, 0.0f);
- m_mousePos = Math::Point(0.5f, 0.5f);
-}
-
-// End of the display of informations.
-
-void CMotionToto::StopDisplayInfo()
-{
- m_bDisplayInfo = false;
- m_bQuickPos = true;
-}
-
-// Gives the position of the mouse.
-
-void CMotionToto::SetMousePos(Math::Point pos)
-{
- m_mousePos = pos;
-}
-
-
-// Management of an event.
-
-bool CMotionToto::EventProcess(const Event &event)
-{
- CMotion::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- return true;
-}
-
-// Management of an event.
-
-bool CMotionToto::EventFrame(const Event &event)
-{
- Math::Matrix* mat;
- Math::Vector eye, lookat, dir, perp, nPos, aPos, pos, speed;
- Math::Vector vibLin, vibCir, dirSpeed, aAntenna;
- Math::Point dim;
- POINT wDim;
- ParticuleType type;
- float progress, focus, distance, shift, verti, level, zoom;
- float aAngle, nAngle, mAngle, angle, linSpeed, cirSpeed;
- int sheet, i, r;
- bool bHidden;
-
- if ( m_engine->RetPause() &&
- !m_main->RetInfoLock() ) return true;
-
- if ( m_bDisplayInfo ) // "looks" mouse?
- {
- bHidden = false;
- }
- else
- {
- bHidden = false;
-
- if ( m_main->RetMovieLock() ) // current movie?
- {
- bHidden = true;
- }
- if ( !m_engine->RetTotoMode() )
- {
- if ( !m_main->RetEditLock() ) // current edition?
- {
- bHidden = true;
- }
- }
- }
-
- if ( bHidden )
- {
- nPos = m_object->RetPosition(0);
- m_terrain->MoveOnFloor(nPos, true);
- nPos.y -= 100.0f; // hidden under the ground!
- m_object->SetPosition(0, nPos);
- return true;
- }
-
- m_time += event.rTime;
- m_blinkTime -= event.rTime;
-
- progress = 0.0f;
- if ( m_actionType != -1 ) // current action?
- {
- if ( m_progress < 0.15f )
- {
- progress = m_progress/0.15f;
- }
- else if ( m_progress < 0.85f )
- {
- progress = 1.0f;
- }
- else
- {
- progress = (1.0f-m_progress)/0.15f;
- }
- }
-
- if ( m_progress >= 1.0f )
- {
- m_actionType = -1; // action ended
- m_actionTime = 0.0f;
- m_progress = 0.0f;
-
- m_clownTime = 0.0f;
- m_clownDelay = 0.0f;
- }
-
- focus = m_engine->RetFocus();
- eye = m_engine->RetEyePt();
- lookat = m_engine->RetLookatPt();
-
- vibLin = Math::Vector(0.0f, 0.0f, 0.0f);
- vibCir = Math::Vector(0.0f, 0.0f, 0.0f);
- aAntenna = Math::Vector(0.0f, 0.0f, 0.0f);
- aAntenna.x += 30.0f*Math::PI/180.0f;
-
- // Calculates the new position.
- if ( m_bDisplayInfo )
- {
- wDim = m_engine->RetDim();
- nPos.x = -4.0f*((float)wDim.x/(float)wDim.y)/(640.0f/480.0f);
- nPos.y = -0.5f;
- nPos.z = 7.0f; // in the left margin
-
- linSpeed = 0.0f;
- }
- else
- {
-#if 0
- distance = 30.0f-progress*24.5f; // remoteness
- shift = 18.0f-progress*15.4f; // shift is left
- verti = 10.0f-progress* 9.6f; // shift at the top
-#else
- distance = 30.0f-progress*18.0f; // remoteness
- shift = 18.0f-progress*11.0f; // shift is left
- verti = 10.0f-progress* 8.0f; // shift at the top
-#endif
-
- if ( m_actionType == -1 &&
- (m_type == OBJECT_HUMAN ||
- m_type == OBJECT_TECH ||
- m_type == OBJECT_MOBILEwa ||
- m_type == OBJECT_MOBILEta ||
- m_type == OBJECT_MOBILEfa ||
- m_type == OBJECT_MOBILEia ||
- m_type == OBJECT_MOBILEwc ||
- m_type == OBJECT_MOBILEtc ||
- m_type == OBJECT_MOBILEfc ||
- m_type == OBJECT_MOBILEic ||
- m_type == OBJECT_MOBILEwi ||
- m_type == OBJECT_MOBILEti ||
- m_type == OBJECT_MOBILEfi ||
- m_type == OBJECT_MOBILEii ||
- m_type == OBJECT_MOBILEws ||
- m_type == OBJECT_MOBILEts ||
- m_type == OBJECT_MOBILEfs ||
- m_type == OBJECT_MOBILEis ||
- m_type == OBJECT_MOBILErt ||
- m_type == OBJECT_MOBILErc ||
- m_type == OBJECT_MOBILErr ||
- m_type == OBJECT_MOBILErs ||
- m_type == OBJECT_MOBILEsa ||
- m_type == OBJECT_MOBILEwt ||
- m_type == OBJECT_MOBILEtt ||
- m_type == OBJECT_MOBILEft ||
- m_type == OBJECT_MOBILEit ||
- m_type == OBJECT_MOBILEdr ) ) // vehicle?
- {
- m_clownTime += event.rTime;
- if ( m_clownTime >= m_clownDelay )
- {
- if ( rand()%10 < 2 )
- {
- m_clownRadius = 2.0f+Math::Rand()*10.0f;
-//? m_clownDelay = m_clownRadius/(2.0f+Math::Rand()*2.0f);
- m_clownDelay = 1.5f+Math::Rand()*1.0f;
- }
- else
- {
- m_clownRadius = 0.0f;
- m_clownDelay = 2.0f+Math::Rand()*2.0f;
- }
- pos = m_object->RetPosition(0);
- if ( pos.y < m_water->RetLevel() ) // underwater?
- {
- m_clownRadius /= 1.5f;
- m_clownDelay *= 2.0f;
- }
- m_clownTime = 0.0f;
- }
- else
- {
- distance -= m_clownRadius*sinf(m_clownTime*Math::PI*2.0f/m_clownDelay);
- shift -= m_clownRadius-m_clownRadius*cosf(m_clownTime*Math::PI*2.0f/m_clownDelay);
- }
-
- verti += (18.0f-shift)*0.2f;
- }
-
- distance /= focus;
-//? shift *= focus;
- verti /= focus;
-
- dir = Normalize(lookat-eye);
- nPos = eye + dir*distance;
-
- perp.x = -dir.z;
- perp.y = dir.y;
- perp.z = dir.x;
- nPos = nPos + perp*shift;
-
- nPos.y += verti;
-
- if ( m_bQuickPos ) // immediately in place?
- {
- m_bQuickPos = false;
- linSpeed = 0.0f;
- }
- else
- {
- aPos = m_object->RetPosition(0);
- if ( m_actionType == -1 )
- {
- level = 4.0f;
- }
- else
- {
- if ( m_bStartAction )
- {
- m_bStartAction = false;
- m_speedAction = Math::Distance(nPos, aPos)/15.0f;
- if ( m_speedAction < 20.0f ) m_speedAction = 20.0f;
- }
- level = m_speedAction;
- }
- if ( level > 1.0f/event.rTime ) level = 1.0f/event.rTime;
- nPos = aPos + (nPos-aPos)*event.rTime*level; // progression aPos -> nPos
-
- linSpeed = Math::DistanceProjected(nPos, aPos)/event.rTime;
- dirSpeed = (nPos-aPos)/event.rTime;
- nPos.y -= linSpeed*0.015f*(1.0f-progress); // at ground level if moving fast
- }
- }
-
- // Calculate the new angle.
- nAngle = Math::NormAngle(Math::RotateAngle(eye.x-lookat.x, lookat.z-eye.z)-0.9f);
- if ( linSpeed == 0.0f || m_actionType != -1 )
- {
- mAngle = nAngle;
- }
- else
- {
- mAngle = Math::NormAngle(Math::RotateAngle(dirSpeed.x, -dirSpeed.z));
- }
- level = Math::Min(linSpeed*0.1f, 1.0f);
- nAngle = nAngle*(1.0f-level) + mAngle*level;
- aAngle = Math::NormAngle(m_object->RetAngleY(0));
-
- if ( nAngle < aAngle )
- {
- if ( nAngle+Math::PI*2.0f-aAngle < aAngle-nAngle ) nAngle += Math::PI*2.0f;
- }
- else
- {
- if ( aAngle+Math::PI*2.0f-nAngle < nAngle-aAngle ) aAngle += Math::PI*2.0f;
- }
- nAngle = aAngle + (nAngle-aAngle)*event.rTime*4.0f;
-
- // Leans quotes if running.
- cirSpeed = (aAngle-nAngle)/event.rTime;
- angle = cirSpeed*0.3f*(1.0f-progress);
- if ( angle > 0.7f ) angle = 0.7f;
- if ( angle < -0.7f ) angle = -0.7f;
- vibCir.x += angle*1.5f;
- aAntenna.x += fabs(angle)*0.8f; // deviates
-
- // Leans forward so quickly advance.
- angle = linSpeed*0.10f*(1.0f-progress);
- if ( angle > 1.0f ) angle = 1.0f;
- vibCir.z -= angle/2.0f; // leans forward
- aAntenna.z -= angle; // leans forward
-
- // Calculates the residual motion.
-#if 1
- vibLin.y += (sinf(m_time*2.00f)*0.5f+
- sinf(m_time*2.11f)*0.2f)*(1.0f-progress);
-
- vibCir.z += sinf(m_time*Math::PI* 2.01f)*(Math::PI/ 75.0f)+
- sinf(m_time*Math::PI* 2.51f)*(Math::PI/100.0f)+
- sinf(m_time*Math::PI*19.01f)*(Math::PI/200.0f);
-
- vibCir.x += sinf(m_time*Math::PI* 2.03f)*(Math::PI/ 75.0f)+
- sinf(m_time*Math::PI* 2.52f)*(Math::PI/100.0f)+
- sinf(m_time*Math::PI*19.53f)*(Math::PI/200.0f);
-
- vibCir.y += (sinf(m_time*Math::PI* 1.07f)*(Math::PI/ 10.0f)+
- sinf(m_time*Math::PI* 1.19f)*(Math::PI/ 17.0f)+
- sinf(m_time*Math::PI* 1.57f)*(Math::PI/ 31.0f))*(1.0f-progress);
-#endif
-
- // Calculates the animations in action.
- if ( m_actionType == MT_ERROR ) // no-no?
- {
- vibCir.y += progress*sinf(m_progress*Math::PI*11.0f)*1.0f;
- vibCir.z -= progress*0.5f; // leans forward
-
- aAntenna.x -= progress*0.4f; // narrows
- aAntenna.z += progress*1.0f; // leaning back
- }
-
- if ( m_actionType == MT_WARNING ) // warning?
- {
- vibCir.x += progress*sinf(m_progress*Math::PI*17.0f)*0.5f;
-
- aAntenna.x += progress*sinf(m_progress*Math::PI*17.0f)*0.5f; // deviates
- aAntenna.z += progress*cosf(m_progress*Math::PI*17.0f)*0.5f; // turns
- }
-
- if ( m_actionType == MT_INFO ) // yes-yes?
- {
- vibCir.z += progress*sinf(m_progress*Math::PI*19.0f)*0.7f;
-
- aAntenna.x -= progress*0.2f; // narrows
- aAntenna.z -= progress*cosf(m_progress*Math::PI*19.0f)*0.9f; // turns
- }
-
- if ( m_actionType == MT_MESSAGE ) // message?
- {
- vibCir.x += progress*sinf(m_progress*Math::PI*15.0f)*0.3f;
- vibCir.z += progress*cosf(m_progress*Math::PI*15.0f)*0.3f;
-
- aAntenna.x -= progress*0.4f; // narrows
- aAntenna.z -= progress*cosf(m_progress*Math::PI*19.0f)*0.8f;
- }
-
- // Initialize the object.
- if ( m_bDisplayInfo ) // "looks" mouse?
- {
- if ( m_mousePos.x < 0.15f )
- {
- progress = 1.0f-m_mousePos.x/0.15f;
- vibCir.y += progress*Math::PI/2.0f;
- }
- else
- {
- progress = (m_mousePos.x-0.15f)/0.85f;
- vibCir.y -= progress*Math::PI/3.0f;
- }
-
- angle = Math::RotateAngle(m_mousePos.x-0.1f, m_mousePos.y-0.5f-vibLin.y*0.2f);
- if ( angle < Math::PI )
- {
- if ( angle > Math::PI*0.5f ) angle = Math::PI-angle;
- if ( angle > Math::PI*0.3f ) angle = Math::PI*0.3f;
- vibCir.z += angle;
- }
- else
- {
- angle = Math::PI*2.0f-angle;
- if ( angle > Math::PI*0.5f ) angle = Math::PI-angle;
- if ( angle > Math::PI*0.3f ) angle = Math::PI*0.3f;
- vibCir.z -= angle;
- }
- }
- else
- {
- nPos.y += vibLin.y;
- level = m_terrain->RetFloorLevel(nPos);
- if ( nPos.y < level+2.0f )
- {
- nPos.y = level+2.0f; // just above the ground
- }
- nPos.y -= vibLin.y;
- }
- m_object->SetPosition(0, nPos);
- m_object->SetAngleY(0, nAngle);
-
- SetLinVibration(vibLin);
- SetCirVibration(vibCir);
-
- // Calculates the residual movement of the antennas.
- pos = aAntenna*0.40f;
- pos.x += sinf(m_time*Math::PI*2.07f)*(Math::PI/50.0f)+
- sinf(m_time*Math::PI*2.59f)*(Math::PI/70.0f)+
- sinf(m_time*Math::PI*2.67f)*(Math::PI/90.0f);
-
- pos.y += sinf(m_time*Math::PI*2.22f)*(Math::PI/50.0f)+
- sinf(m_time*Math::PI*2.36f)*(Math::PI/70.0f)+
- sinf(m_time*Math::PI*3.01f)*(Math::PI/90.0f);
-
- pos.z += sinf(m_time*Math::PI*2.11f)*(Math::PI/50.0f)+
- sinf(m_time*Math::PI*2.83f)*(Math::PI/70.0f)+
- sinf(m_time*Math::PI*3.09f)*(Math::PI/90.0f);
-
- m_object->SetAngle(4, pos); // left antenna
- m_object->SetAngle(5, pos); // left antenna
- m_object->SetAngle(6, pos); // left antenna
-
- pos = aAntenna*0.40f;
- pos.x = -pos.x;
- pos.x += sinf(m_time*Math::PI*2.33f)*(Math::PI/50.0f)+
- sinf(m_time*Math::PI*2.19f)*(Math::PI/70.0f)+
- sinf(m_time*Math::PI*2.07f)*(Math::PI/90.0f);
-
- pos.y += sinf(m_time*Math::PI*2.44f)*(Math::PI/50.0f)+
- sinf(m_time*Math::PI*2.77f)*(Math::PI/70.0f)+
- sinf(m_time*Math::PI*3.22f)*(Math::PI/90.0f);
-
- pos.z += sinf(m_time*Math::PI*2.05f)*(Math::PI/50.0f)+
- sinf(m_time*Math::PI*2.38f)*(Math::PI/70.0f)+
- sinf(m_time*Math::PI*2.79f)*(Math::PI/90.0f);
-
- m_object->SetAngle(7, pos); // right antenna
- m_object->SetAngle(8, pos); // right antenna
- m_object->SetAngle(9, pos); // right antenna
-
- // Movement of the mouth.
- if ( m_actionType == MT_ERROR ) // no-no?
- {
- m_object->SetAngleX(1, 0.0f);
- m_object->SetAngleZ(1, 0.2f+sinf(m_time*10.0f)*0.2f);
- m_object->SetZoomY(1, 2.0f+sinf(m_time*10.0f));
- m_object->SetZoomZ(1, 1.0f);
- }
- else if ( m_actionType == MT_WARNING ) // warning?
- {
- m_object->SetAngleX(1, 15.0f*Math::PI/180.0f);
- m_object->SetAngleZ(1, 0.0f);
- m_object->SetZoomY(1, 1.0f);
- m_object->SetZoomZ(1, 1.0f);
- }
- else if ( m_actionType == MT_INFO ) // yes-yes?
- {
- m_object->SetAngleX(1, 0.0f);
- m_object->SetAngleZ(1, 0.0f);
- m_object->SetZoomY(1, 1.0f);
- m_object->SetZoomZ(1, 0.7f+sinf(m_time*10.0f)*0.3f);
- }
- else if ( m_actionType == MT_MESSAGE ) // message?
- {
- m_object->SetAngleX(1, 0.0f);
- m_object->SetAngleZ(1, 0.0f);
- m_object->SetZoomY(1, 1.0f);
- m_object->SetZoomZ(1, 0.8f+sinf(m_time*7.0f)*0.2f);
- }
- else
- {
- m_object->SetAngleX(1, 0.0f);
- m_object->SetAngleZ(1, 0.0f);
- m_object->SetZoomY(1, 1.0f);
- m_object->SetZoomZ(1, 1.0f);
- }
-
- // Eye blinking management.
- if ( m_blinkTime <= 0.0f && m_blinkProgress == -1.0f )
- {
- m_blinkProgress = 0.0f;
- }
-
- if ( m_blinkProgress >= 0.0f )
- {
- m_blinkProgress += event.rTime*3.2f;
-
- if ( m_blinkProgress < 1.0f )
- {
- if ( m_blinkProgress < 0.5f ) zoom = m_blinkProgress/0.5f;
- else zoom = 2.0f-m_blinkProgress/0.5f;
- m_object->SetZoomY(2, 1.0f-zoom*0.9f);
- m_object->SetZoomY(3, 1.0f-zoom*0.9f);
- }
- else
- {
- m_blinkProgress = -1.0f;
- m_blinkTime = 0.1f+Math::Rand()*4.0f;
- m_object->SetZoomY(2, 1.0f);
- m_object->SetZoomY(3, 1.0f);
- }
- }
-
- if ( m_actionType == MT_ERROR ) // no-no?
- {
- m_object->SetAngleX(2, -30.0f*Math::PI/180.0f);
- m_object->SetAngleX(3, 30.0f*Math::PI/180.0f);
- }
- else if ( m_actionType == MT_WARNING ) // warning?
- {
- m_object->SetAngleX(2, -15.0f*Math::PI/180.0f);
- m_object->SetAngleX(3, 15.0f*Math::PI/180.0f);
- }
- else if ( m_actionType == MT_INFO ) // yes-yes?
- {
- m_object->SetAngleX(2, 40.0f*Math::PI/180.0f);
- m_object->SetAngleX(3, -40.0f*Math::PI/180.0f);
- }
- else if ( m_actionType == MT_MESSAGE ) // message?
- {
- m_object->SetAngleX(2, 20.0f*Math::PI/180.0f);
- m_object->SetAngleX(3, -20.0f*Math::PI/180.0f);
- }
- else
- {
- m_object->SetAngleX(2, 0.0f);
- m_object->SetAngleX(3, 0.0f);
- }
-
- mat = m_object->RetWorldMatrix(0); // must be done every time!
-
- // Generates particles.
- if ( m_time-m_lastMotorParticule >= m_engine->ParticuleAdapt(0.05f) )
- {
- m_lastMotorParticule = m_time;
-
- if ( m_bDisplayInfo ) sheet = SH_FRONT;
- else sheet = SH_WORLD;
-
- pos = m_object->RetPosition(0);
- if ( !m_bDisplayInfo &&
- pos.y < m_water->RetLevel() ) // underwater?
- {
- float t = Math::Mod(m_time, 3.5f);
- if ( t >= 2.2f || ( t >= 1.2f && t <= 1.4f ) ) // breathe?
- {
- pos = Math::Vector(1.0f, 0.2f, 0.0f);
- pos.z += (Math::Rand()-0.5f)*0.5f;
-
- speed = pos;
- speed.y += 5.0f+Math::Rand()*5.0f;
- speed.x += Math::Rand()*2.0f;
- speed.z += (Math::Rand()-0.5f)*2.0f;
-
- pos = Transform(*mat, pos);
- speed = Transform(*mat, speed)-pos;
-
- dim.x = 0.12f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBUBBLE, 3.0f, 0.0f, 0.0f);
- }
- }
- else // out of water?
- {
- pos = Math::Vector(0.0f, -0.5f, 0.0f);
- pos.z += (Math::Rand()-0.5f)*0.5f;
-
- speed = pos;
- speed.y -= (1.5f+Math::Rand()*1.5f) + vibLin.y;
- speed.x += (Math::Rand()-0.5f)*2.0f;
- speed.z += (Math::Rand()-0.5f)*2.0f;
-
-// mat = m_object->RetWorldMatrix(0);
- pos = Transform(*mat, pos);
- speed = Transform(*mat, speed)-pos;
-
- dim.x = (Math::Rand()*0.4f+0.4f)*(1.0f+Math::Min(linSpeed*0.1f, 5.0f));
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTITOTO, 1.0f+Math::Rand()*1.0f, 0.0f, 1.0f, sheet);
- }
-
- if ( m_actionType != -1 && // current action?
- m_progress <= 0.85f )
- {
- pos.x = (Math::Rand()-0.5f)*1.0f;
- pos.y = (Math::Rand()-0.5f)*1.0f+3.5f;
- pos.z = (Math::Rand()-0.5f)*1.0f;
- pos = Transform(*mat, pos);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = (Math::Rand()*0.3f+0.3f);
- dim.y = dim.x;
- if ( m_actionType == MT_ERROR ) type = PARTIERROR;
- if ( m_actionType == MT_WARNING ) type = PARTIWARNING;
- if ( m_actionType == MT_INFO ) type = PARTIINFO;
- if ( m_actionType == MT_MESSAGE ) type = PARTIWARNING;
- m_particule->CreateParticule(pos, speed, dim, type, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, sheet);
-
- pos.x = 0.50f+(Math::Rand()-0.5f)*0.80f;
- pos.y = 0.86f+(Math::Rand()-0.5f)*0.08f;
- pos.z = 0.00f;
- dim.x = (Math::Rand()*0.04f+0.04f);
- dim.y = dim.x/0.75f;
- m_particule->CreateParticule(pos, speed, dim, type, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, SH_INTERFACE);
- }
-
-//? if ( m_bDisplayInfo && m_main->RetGlint() )
- if ( false )
- {
- pos.x = (Math::Rand()-0.5f)*1.4f;
- pos.y = (Math::Rand()-0.5f)*1.4f+3.5f;
- pos.z = (Math::Rand()-0.5f)*1.4f;
- pos = Transform(*mat, pos);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = (Math::Rand()*0.5f+0.5f);
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, sheet);
-
- for ( i=0 ; i<10 ; i++ )
- {
- pos.x = 0.60f+(Math::Rand()-0.5f)*0.76f;
- pos.y = 0.47f+(Math::Rand()-0.5f)*0.90f;
- pos.z = 0.00f;
- r = rand()%4;
- if ( r == 0 ) pos.x = 0.21f; // the left edge
- else if ( r == 1 ) pos.x = 0.98f; // the right edge
- else if ( r == 2 ) pos.y = 0.02f; // on the lower edge
- else pos.y = 0.92f; // on the upper edge
- dim.x = (Math::Rand()*0.02f+0.02f);
- dim.y = dim.x/0.75f;
- m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, SH_INTERFACE);
- }
- }
- }
-
- // Move the sound.
- if ( m_soundChannel != -1 )
- {
- if ( !m_sound->Position(m_soundChannel, m_object->RetPosition(0)) )
- {
- m_soundChannel = -1;
- }
- }
-
- return true;
-}
-
-
-// Starts an action.
-
-Error CMotionToto::SetAction(int action, float time)
-{
- Sound sound;
-
- CMotion::SetAction(action, time);
-
- m_bStartAction = true;
-
- sound = SOUND_CLICK;
- if ( action == MT_ERROR ) sound = SOUND_ERROR;
- if ( action == MT_WARNING ) sound = SOUND_WARNING;
- if ( action == MT_INFO ) sound = SOUND_INFO;
- if ( action == MT_MESSAGE ) sound = SOUND_MESSAGE;
-
- if ( sound != SOUND_CLICK )
- {
- m_soundChannel = m_sound->Play(sound, m_object->RetPosition(0));
- }
-
- return ERR_OK;
-}
-
-// Specifies the type of the object is attached to toto.
-
-void CMotionToto::SetLinkType(ObjectType type)
-{
- m_type = type;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motiontoto.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motiontoto.h"
+
+#include "math/geometry.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "old/modfile.h"
+#include "object/robotmain.h"
+
+
+
+const float START_TIME = 1000.0f; // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionToto::CMotionToto(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ m_time = 0.0f;
+ m_bDisplayInfo = false;
+ m_bQuickPos = false;
+ m_bStartAction = false;
+ m_speedAction = 20.0f;
+ m_soundChannel = -1;
+ m_clownRadius = 0.0f;
+ m_clownDelay = 0.0f;
+ m_clownTime = 0.0f;
+ m_blinkTime = 0.0f;
+ m_blinkProgress = -1.0f;
+ m_lastMotorParticule = 0.0f;
+ m_type = OBJECT_NULL;
+ m_mousePos = Math::Point(0.0f, 0.0f);
+}
+
+// Object's destructor.
+
+CMotionToto::~CMotionToto()
+{
+}
+
+
+// Removes an object.
+
+void CMotionToto::DeleteObject(bool bAll)
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->Stop(m_soundChannel);
+ m_soundChannel = -1;
+ }
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+bool CMotionToto::Create(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 10 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\toto1.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // Creates mouth.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\toto2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(1.00f, 0.17f, 0.00f));
+
+ // Creates the left eye.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\toto3.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(0.85f, 1.04f, 0.25f));
+ m_object->SetAngleY(2, -20.0f*Math::PI/180.0f);
+
+ // Creates the right eye.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 0);
+ pModFile->ReadModel("objects\\toto3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(0.85f, 1.04f, -0.25f));
+ m_object->SetAngleY(3, 20.0f*Math::PI/180.0f);
+
+ // Creates left antenna.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 0);
+ pModFile->ReadModel("objects\\toto4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, Math::Vector(0.0f, 1.9f, 0.3f));
+ m_object->SetAngleX(4, 30.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 4);
+ pModFile->ReadModel("objects\\toto4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, Math::Vector(0.0f, 0.67f, 0.0f));
+ m_object->SetAngleX(5, 30.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 5);
+ pModFile->ReadModel("objects\\toto5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(0.0f, 0.70f, 0.0f));
+ m_object->SetAngleX(6, 30.0f*Math::PI/180.0f);
+
+ // Creates right antenna.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\toto4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, 1.9f, -0.3f));
+ m_object->SetAngleX(7, -30.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 7);
+ pModFile->ReadModel("objects\\toto4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(0.0f, 0.67f, 0.0f));
+ m_object->SetAngleX(8, -30.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 8);
+ pModFile->ReadModel("objects\\toto5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, Math::Vector(0.0f, 0.70f, 0.0f));
+ m_object->SetAngleX(9, -30.0f*Math::PI/180.0f);
+
+ m_object->SetZoom(0, 0.5f); // is little
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+
+// Beginning of the display of informations, with foo in the left margin.
+
+void CMotionToto::StartDisplayInfo()
+{
+return;
+//?
+ m_bDisplayInfo = true;
+
+ m_actionType = -1;
+ m_actionTime = 0.0f;
+ m_progress = 0.0f;
+
+ m_object->SetAngleY(0, 0.0f);
+ m_mousePos = Math::Point(0.5f, 0.5f);
+}
+
+// End of the display of informations.
+
+void CMotionToto::StopDisplayInfo()
+{
+ m_bDisplayInfo = false;
+ m_bQuickPos = true;
+}
+
+// Gives the position of the mouse.
+
+void CMotionToto::SetMousePos(Math::Point pos)
+{
+ m_mousePos = pos;
+}
+
+
+// Management of an event.
+
+bool CMotionToto::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ return true;
+}
+
+// Management of an event.
+
+bool CMotionToto::EventFrame(const Event &event)
+{
+ Math::Matrix* mat;
+ Math::Vector eye, lookat, dir, perp, nPos, aPos, pos, speed;
+ Math::Vector vibLin, vibCir, dirSpeed, aAntenna;
+ Math::Point dim;
+ POINT wDim;
+ ParticuleType type;
+ float progress, focus, distance, shift, verti, level, zoom;
+ float aAngle, nAngle, mAngle, angle, linSpeed, cirSpeed;
+ int sheet, i, r;
+ bool bHidden;
+
+ if ( m_engine->RetPause() &&
+ !m_main->RetInfoLock() ) return true;
+
+ if ( m_bDisplayInfo ) // "looks" mouse?
+ {
+ bHidden = false;
+ }
+ else
+ {
+ bHidden = false;
+
+ if ( m_main->RetMovieLock() ) // current movie?
+ {
+ bHidden = true;
+ }
+ if ( !m_engine->RetTotoMode() )
+ {
+ if ( !m_main->RetEditLock() ) // current edition?
+ {
+ bHidden = true;
+ }
+ }
+ }
+
+ if ( bHidden )
+ {
+ nPos = m_object->RetPosition(0);
+ m_terrain->MoveOnFloor(nPos, true);
+ nPos.y -= 100.0f; // hidden under the ground!
+ m_object->SetPosition(0, nPos);
+ return true;
+ }
+
+ m_time += event.rTime;
+ m_blinkTime -= event.rTime;
+
+ progress = 0.0f;
+ if ( m_actionType != -1 ) // current action?
+ {
+ if ( m_progress < 0.15f )
+ {
+ progress = m_progress/0.15f;
+ }
+ else if ( m_progress < 0.85f )
+ {
+ progress = 1.0f;
+ }
+ else
+ {
+ progress = (1.0f-m_progress)/0.15f;
+ }
+ }
+
+ if ( m_progress >= 1.0f )
+ {
+ m_actionType = -1; // action ended
+ m_actionTime = 0.0f;
+ m_progress = 0.0f;
+
+ m_clownTime = 0.0f;
+ m_clownDelay = 0.0f;
+ }
+
+ focus = m_engine->RetFocus();
+ eye = m_engine->RetEyePt();
+ lookat = m_engine->RetLookatPt();
+
+ vibLin = Math::Vector(0.0f, 0.0f, 0.0f);
+ vibCir = Math::Vector(0.0f, 0.0f, 0.0f);
+ aAntenna = Math::Vector(0.0f, 0.0f, 0.0f);
+ aAntenna.x += 30.0f*Math::PI/180.0f;
+
+ // Calculates the new position.
+ if ( m_bDisplayInfo )
+ {
+ wDim = m_engine->RetDim();
+ nPos.x = -4.0f*((float)wDim.x/(float)wDim.y)/(640.0f/480.0f);
+ nPos.y = -0.5f;
+ nPos.z = 7.0f; // in the left margin
+
+ linSpeed = 0.0f;
+ }
+ else
+ {
+#if 0
+ distance = 30.0f-progress*24.5f; // remoteness
+ shift = 18.0f-progress*15.4f; // shift is left
+ verti = 10.0f-progress* 9.6f; // shift at the top
+#else
+ distance = 30.0f-progress*18.0f; // remoteness
+ shift = 18.0f-progress*11.0f; // shift is left
+ verti = 10.0f-progress* 8.0f; // shift at the top
+#endif
+
+ if ( m_actionType == -1 &&
+ (m_type == OBJECT_HUMAN ||
+ m_type == OBJECT_TECH ||
+ m_type == OBJECT_MOBILEwa ||
+ m_type == OBJECT_MOBILEta ||
+ m_type == OBJECT_MOBILEfa ||
+ m_type == OBJECT_MOBILEia ||
+ m_type == OBJECT_MOBILEwc ||
+ m_type == OBJECT_MOBILEtc ||
+ m_type == OBJECT_MOBILEfc ||
+ m_type == OBJECT_MOBILEic ||
+ m_type == OBJECT_MOBILEwi ||
+ m_type == OBJECT_MOBILEti ||
+ m_type == OBJECT_MOBILEfi ||
+ m_type == OBJECT_MOBILEii ||
+ m_type == OBJECT_MOBILEws ||
+ m_type == OBJECT_MOBILEts ||
+ m_type == OBJECT_MOBILEfs ||
+ m_type == OBJECT_MOBILEis ||
+ m_type == OBJECT_MOBILErt ||
+ m_type == OBJECT_MOBILErc ||
+ m_type == OBJECT_MOBILErr ||
+ m_type == OBJECT_MOBILErs ||
+ m_type == OBJECT_MOBILEsa ||
+ m_type == OBJECT_MOBILEwt ||
+ m_type == OBJECT_MOBILEtt ||
+ m_type == OBJECT_MOBILEft ||
+ m_type == OBJECT_MOBILEit ||
+ m_type == OBJECT_MOBILEdr ) ) // vehicle?
+ {
+ m_clownTime += event.rTime;
+ if ( m_clownTime >= m_clownDelay )
+ {
+ if ( rand()%10 < 2 )
+ {
+ m_clownRadius = 2.0f+Math::Rand()*10.0f;
+//? m_clownDelay = m_clownRadius/(2.0f+Math::Rand()*2.0f);
+ m_clownDelay = 1.5f+Math::Rand()*1.0f;
+ }
+ else
+ {
+ m_clownRadius = 0.0f;
+ m_clownDelay = 2.0f+Math::Rand()*2.0f;
+ }
+ pos = m_object->RetPosition(0);
+ if ( pos.y < m_water->RetLevel() ) // underwater?
+ {
+ m_clownRadius /= 1.5f;
+ m_clownDelay *= 2.0f;
+ }
+ m_clownTime = 0.0f;
+ }
+ else
+ {
+ distance -= m_clownRadius*sinf(m_clownTime*Math::PI*2.0f/m_clownDelay);
+ shift -= m_clownRadius-m_clownRadius*cosf(m_clownTime*Math::PI*2.0f/m_clownDelay);
+ }
+
+ verti += (18.0f-shift)*0.2f;
+ }
+
+ distance /= focus;
+//? shift *= focus;
+ verti /= focus;
+
+ dir = Normalize(lookat-eye);
+ nPos = eye + dir*distance;
+
+ perp.x = -dir.z;
+ perp.y = dir.y;
+ perp.z = dir.x;
+ nPos = nPos + perp*shift;
+
+ nPos.y += verti;
+
+ if ( m_bQuickPos ) // immediately in place?
+ {
+ m_bQuickPos = false;
+ linSpeed = 0.0f;
+ }
+ else
+ {
+ aPos = m_object->RetPosition(0);
+ if ( m_actionType == -1 )
+ {
+ level = 4.0f;
+ }
+ else
+ {
+ if ( m_bStartAction )
+ {
+ m_bStartAction = false;
+ m_speedAction = Math::Distance(nPos, aPos)/15.0f;
+ if ( m_speedAction < 20.0f ) m_speedAction = 20.0f;
+ }
+ level = m_speedAction;
+ }
+ if ( level > 1.0f/event.rTime ) level = 1.0f/event.rTime;
+ nPos = aPos + (nPos-aPos)*event.rTime*level; // progression aPos -> nPos
+
+ linSpeed = Math::DistanceProjected(nPos, aPos)/event.rTime;
+ dirSpeed = (nPos-aPos)/event.rTime;
+ nPos.y -= linSpeed*0.015f*(1.0f-progress); // at ground level if moving fast
+ }
+ }
+
+ // Calculate the new angle.
+ nAngle = Math::NormAngle(Math::RotateAngle(eye.x-lookat.x, lookat.z-eye.z)-0.9f);
+ if ( linSpeed == 0.0f || m_actionType != -1 )
+ {
+ mAngle = nAngle;
+ }
+ else
+ {
+ mAngle = Math::NormAngle(Math::RotateAngle(dirSpeed.x, -dirSpeed.z));
+ }
+ level = Math::Min(linSpeed*0.1f, 1.0f);
+ nAngle = nAngle*(1.0f-level) + mAngle*level;
+ aAngle = Math::NormAngle(m_object->RetAngleY(0));
+
+ if ( nAngle < aAngle )
+ {
+ if ( nAngle+Math::PI*2.0f-aAngle < aAngle-nAngle ) nAngle += Math::PI*2.0f;
+ }
+ else
+ {
+ if ( aAngle+Math::PI*2.0f-nAngle < nAngle-aAngle ) aAngle += Math::PI*2.0f;
+ }
+ nAngle = aAngle + (nAngle-aAngle)*event.rTime*4.0f;
+
+ // Leans quotes if running.
+ cirSpeed = (aAngle-nAngle)/event.rTime;
+ angle = cirSpeed*0.3f*(1.0f-progress);
+ if ( angle > 0.7f ) angle = 0.7f;
+ if ( angle < -0.7f ) angle = -0.7f;
+ vibCir.x += angle*1.5f;
+ aAntenna.x += fabs(angle)*0.8f; // deviates
+
+ // Leans forward so quickly advance.
+ angle = linSpeed*0.10f*(1.0f-progress);
+ if ( angle > 1.0f ) angle = 1.0f;
+ vibCir.z -= angle/2.0f; // leans forward
+ aAntenna.z -= angle; // leans forward
+
+ // Calculates the residual motion.
+#if 1
+ vibLin.y += (sinf(m_time*2.00f)*0.5f+
+ sinf(m_time*2.11f)*0.2f)*(1.0f-progress);
+
+ vibCir.z += sinf(m_time*Math::PI* 2.01f)*(Math::PI/ 75.0f)+
+ sinf(m_time*Math::PI* 2.51f)*(Math::PI/100.0f)+
+ sinf(m_time*Math::PI*19.01f)*(Math::PI/200.0f);
+
+ vibCir.x += sinf(m_time*Math::PI* 2.03f)*(Math::PI/ 75.0f)+
+ sinf(m_time*Math::PI* 2.52f)*(Math::PI/100.0f)+
+ sinf(m_time*Math::PI*19.53f)*(Math::PI/200.0f);
+
+ vibCir.y += (sinf(m_time*Math::PI* 1.07f)*(Math::PI/ 10.0f)+
+ sinf(m_time*Math::PI* 1.19f)*(Math::PI/ 17.0f)+
+ sinf(m_time*Math::PI* 1.57f)*(Math::PI/ 31.0f))*(1.0f-progress);
+#endif
+
+ // Calculates the animations in action.
+ if ( m_actionType == MT_ERROR ) // no-no?
+ {
+ vibCir.y += progress*sinf(m_progress*Math::PI*11.0f)*1.0f;
+ vibCir.z -= progress*0.5f; // leans forward
+
+ aAntenna.x -= progress*0.4f; // narrows
+ aAntenna.z += progress*1.0f; // leaning back
+ }
+
+ if ( m_actionType == MT_WARNING ) // warning?
+ {
+ vibCir.x += progress*sinf(m_progress*Math::PI*17.0f)*0.5f;
+
+ aAntenna.x += progress*sinf(m_progress*Math::PI*17.0f)*0.5f; // deviates
+ aAntenna.z += progress*cosf(m_progress*Math::PI*17.0f)*0.5f; // turns
+ }
+
+ if ( m_actionType == MT_INFO ) // yes-yes?
+ {
+ vibCir.z += progress*sinf(m_progress*Math::PI*19.0f)*0.7f;
+
+ aAntenna.x -= progress*0.2f; // narrows
+ aAntenna.z -= progress*cosf(m_progress*Math::PI*19.0f)*0.9f; // turns
+ }
+
+ if ( m_actionType == MT_MESSAGE ) // message?
+ {
+ vibCir.x += progress*sinf(m_progress*Math::PI*15.0f)*0.3f;
+ vibCir.z += progress*cosf(m_progress*Math::PI*15.0f)*0.3f;
+
+ aAntenna.x -= progress*0.4f; // narrows
+ aAntenna.z -= progress*cosf(m_progress*Math::PI*19.0f)*0.8f;
+ }
+
+ // Initialize the object.
+ if ( m_bDisplayInfo ) // "looks" mouse?
+ {
+ if ( m_mousePos.x < 0.15f )
+ {
+ progress = 1.0f-m_mousePos.x/0.15f;
+ vibCir.y += progress*Math::PI/2.0f;
+ }
+ else
+ {
+ progress = (m_mousePos.x-0.15f)/0.85f;
+ vibCir.y -= progress*Math::PI/3.0f;
+ }
+
+ angle = Math::RotateAngle(m_mousePos.x-0.1f, m_mousePos.y-0.5f-vibLin.y*0.2f);
+ if ( angle < Math::PI )
+ {
+ if ( angle > Math::PI*0.5f ) angle = Math::PI-angle;
+ if ( angle > Math::PI*0.3f ) angle = Math::PI*0.3f;
+ vibCir.z += angle;
+ }
+ else
+ {
+ angle = Math::PI*2.0f-angle;
+ if ( angle > Math::PI*0.5f ) angle = Math::PI-angle;
+ if ( angle > Math::PI*0.3f ) angle = Math::PI*0.3f;
+ vibCir.z -= angle;
+ }
+ }
+ else
+ {
+ nPos.y += vibLin.y;
+ level = m_terrain->RetFloorLevel(nPos);
+ if ( nPos.y < level+2.0f )
+ {
+ nPos.y = level+2.0f; // just above the ground
+ }
+ nPos.y -= vibLin.y;
+ }
+ m_object->SetPosition(0, nPos);
+ m_object->SetAngleY(0, nAngle);
+
+ SetLinVibration(vibLin);
+ SetCirVibration(vibCir);
+
+ // Calculates the residual movement of the antennas.
+ pos = aAntenna*0.40f;
+ pos.x += sinf(m_time*Math::PI*2.07f)*(Math::PI/50.0f)+
+ sinf(m_time*Math::PI*2.59f)*(Math::PI/70.0f)+
+ sinf(m_time*Math::PI*2.67f)*(Math::PI/90.0f);
+
+ pos.y += sinf(m_time*Math::PI*2.22f)*(Math::PI/50.0f)+
+ sinf(m_time*Math::PI*2.36f)*(Math::PI/70.0f)+
+ sinf(m_time*Math::PI*3.01f)*(Math::PI/90.0f);
+
+ pos.z += sinf(m_time*Math::PI*2.11f)*(Math::PI/50.0f)+
+ sinf(m_time*Math::PI*2.83f)*(Math::PI/70.0f)+
+ sinf(m_time*Math::PI*3.09f)*(Math::PI/90.0f);
+
+ m_object->SetAngle(4, pos); // left antenna
+ m_object->SetAngle(5, pos); // left antenna
+ m_object->SetAngle(6, pos); // left antenna
+
+ pos = aAntenna*0.40f;
+ pos.x = -pos.x;
+ pos.x += sinf(m_time*Math::PI*2.33f)*(Math::PI/50.0f)+
+ sinf(m_time*Math::PI*2.19f)*(Math::PI/70.0f)+
+ sinf(m_time*Math::PI*2.07f)*(Math::PI/90.0f);
+
+ pos.y += sinf(m_time*Math::PI*2.44f)*(Math::PI/50.0f)+
+ sinf(m_time*Math::PI*2.77f)*(Math::PI/70.0f)+
+ sinf(m_time*Math::PI*3.22f)*(Math::PI/90.0f);
+
+ pos.z += sinf(m_time*Math::PI*2.05f)*(Math::PI/50.0f)+
+ sinf(m_time*Math::PI*2.38f)*(Math::PI/70.0f)+
+ sinf(m_time*Math::PI*2.79f)*(Math::PI/90.0f);
+
+ m_object->SetAngle(7, pos); // right antenna
+ m_object->SetAngle(8, pos); // right antenna
+ m_object->SetAngle(9, pos); // right antenna
+
+ // Movement of the mouth.
+ if ( m_actionType == MT_ERROR ) // no-no?
+ {
+ m_object->SetAngleX(1, 0.0f);
+ m_object->SetAngleZ(1, 0.2f+sinf(m_time*10.0f)*0.2f);
+ m_object->SetZoomY(1, 2.0f+sinf(m_time*10.0f));
+ m_object->SetZoomZ(1, 1.0f);
+ }
+ else if ( m_actionType == MT_WARNING ) // warning?
+ {
+ m_object->SetAngleX(1, 15.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(1, 0.0f);
+ m_object->SetZoomY(1, 1.0f);
+ m_object->SetZoomZ(1, 1.0f);
+ }
+ else if ( m_actionType == MT_INFO ) // yes-yes?
+ {
+ m_object->SetAngleX(1, 0.0f);
+ m_object->SetAngleZ(1, 0.0f);
+ m_object->SetZoomY(1, 1.0f);
+ m_object->SetZoomZ(1, 0.7f+sinf(m_time*10.0f)*0.3f);
+ }
+ else if ( m_actionType == MT_MESSAGE ) // message?
+ {
+ m_object->SetAngleX(1, 0.0f);
+ m_object->SetAngleZ(1, 0.0f);
+ m_object->SetZoomY(1, 1.0f);
+ m_object->SetZoomZ(1, 0.8f+sinf(m_time*7.0f)*0.2f);
+ }
+ else
+ {
+ m_object->SetAngleX(1, 0.0f);
+ m_object->SetAngleZ(1, 0.0f);
+ m_object->SetZoomY(1, 1.0f);
+ m_object->SetZoomZ(1, 1.0f);
+ }
+
+ // Eye blinking management.
+ if ( m_blinkTime <= 0.0f && m_blinkProgress == -1.0f )
+ {
+ m_blinkProgress = 0.0f;
+ }
+
+ if ( m_blinkProgress >= 0.0f )
+ {
+ m_blinkProgress += event.rTime*3.2f;
+
+ if ( m_blinkProgress < 1.0f )
+ {
+ if ( m_blinkProgress < 0.5f ) zoom = m_blinkProgress/0.5f;
+ else zoom = 2.0f-m_blinkProgress/0.5f;
+ m_object->SetZoomY(2, 1.0f-zoom*0.9f);
+ m_object->SetZoomY(3, 1.0f-zoom*0.9f);
+ }
+ else
+ {
+ m_blinkProgress = -1.0f;
+ m_blinkTime = 0.1f+Math::Rand()*4.0f;
+ m_object->SetZoomY(2, 1.0f);
+ m_object->SetZoomY(3, 1.0f);
+ }
+ }
+
+ if ( m_actionType == MT_ERROR ) // no-no?
+ {
+ m_object->SetAngleX(2, -30.0f*Math::PI/180.0f);
+ m_object->SetAngleX(3, 30.0f*Math::PI/180.0f);
+ }
+ else if ( m_actionType == MT_WARNING ) // warning?
+ {
+ m_object->SetAngleX(2, -15.0f*Math::PI/180.0f);
+ m_object->SetAngleX(3, 15.0f*Math::PI/180.0f);
+ }
+ else if ( m_actionType == MT_INFO ) // yes-yes?
+ {
+ m_object->SetAngleX(2, 40.0f*Math::PI/180.0f);
+ m_object->SetAngleX(3, -40.0f*Math::PI/180.0f);
+ }
+ else if ( m_actionType == MT_MESSAGE ) // message?
+ {
+ m_object->SetAngleX(2, 20.0f*Math::PI/180.0f);
+ m_object->SetAngleX(3, -20.0f*Math::PI/180.0f);
+ }
+ else
+ {
+ m_object->SetAngleX(2, 0.0f);
+ m_object->SetAngleX(3, 0.0f);
+ }
+
+ mat = m_object->RetWorldMatrix(0); // must be done every time!
+
+ // Generates particles.
+ if ( m_time-m_lastMotorParticule >= m_engine->ParticuleAdapt(0.05f) )
+ {
+ m_lastMotorParticule = m_time;
+
+ if ( m_bDisplayInfo ) sheet = SH_FRONT;
+ else sheet = SH_WORLD;
+
+ pos = m_object->RetPosition(0);
+ if ( !m_bDisplayInfo &&
+ pos.y < m_water->RetLevel() ) // underwater?
+ {
+ float t = Math::Mod(m_time, 3.5f);
+ if ( t >= 2.2f || ( t >= 1.2f && t <= 1.4f ) ) // breathe?
+ {
+ pos = Math::Vector(1.0f, 0.2f, 0.0f);
+ pos.z += (Math::Rand()-0.5f)*0.5f;
+
+ speed = pos;
+ speed.y += 5.0f+Math::Rand()*5.0f;
+ speed.x += Math::Rand()*2.0f;
+ speed.z += (Math::Rand()-0.5f)*2.0f;
+
+ pos = Transform(*mat, pos);
+ speed = Transform(*mat, speed)-pos;
+
+ dim.x = 0.12f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBUBBLE, 3.0f, 0.0f, 0.0f);
+ }
+ }
+ else // out of water?
+ {
+ pos = Math::Vector(0.0f, -0.5f, 0.0f);
+ pos.z += (Math::Rand()-0.5f)*0.5f;
+
+ speed = pos;
+ speed.y -= (1.5f+Math::Rand()*1.5f) + vibLin.y;
+ speed.x += (Math::Rand()-0.5f)*2.0f;
+ speed.z += (Math::Rand()-0.5f)*2.0f;
+
+// mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+ speed = Transform(*mat, speed)-pos;
+
+ dim.x = (Math::Rand()*0.4f+0.4f)*(1.0f+Math::Min(linSpeed*0.1f, 5.0f));
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTITOTO, 1.0f+Math::Rand()*1.0f, 0.0f, 1.0f, sheet);
+ }
+
+ if ( m_actionType != -1 && // current action?
+ m_progress <= 0.85f )
+ {
+ pos.x = (Math::Rand()-0.5f)*1.0f;
+ pos.y = (Math::Rand()-0.5f)*1.0f+3.5f;
+ pos.z = (Math::Rand()-0.5f)*1.0f;
+ pos = Transform(*mat, pos);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = (Math::Rand()*0.3f+0.3f);
+ dim.y = dim.x;
+ if ( m_actionType == MT_ERROR ) type = PARTIERROR;
+ if ( m_actionType == MT_WARNING ) type = PARTIWARNING;
+ if ( m_actionType == MT_INFO ) type = PARTIINFO;
+ if ( m_actionType == MT_MESSAGE ) type = PARTIWARNING;
+ m_particule->CreateParticule(pos, speed, dim, type, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, sheet);
+
+ pos.x = 0.50f+(Math::Rand()-0.5f)*0.80f;
+ pos.y = 0.86f+(Math::Rand()-0.5f)*0.08f;
+ pos.z = 0.00f;
+ dim.x = (Math::Rand()*0.04f+0.04f);
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim, type, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, SH_INTERFACE);
+ }
+
+//? if ( m_bDisplayInfo && m_main->RetGlint() )
+ if ( false )
+ {
+ pos.x = (Math::Rand()-0.5f)*1.4f;
+ pos.y = (Math::Rand()-0.5f)*1.4f+3.5f;
+ pos.z = (Math::Rand()-0.5f)*1.4f;
+ pos = Transform(*mat, pos);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = (Math::Rand()*0.5f+0.5f);
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, sheet);
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ pos.x = 0.60f+(Math::Rand()-0.5f)*0.76f;
+ pos.y = 0.47f+(Math::Rand()-0.5f)*0.90f;
+ pos.z = 0.00f;
+ r = rand()%4;
+ if ( r == 0 ) pos.x = 0.21f; // the left edge
+ else if ( r == 1 ) pos.x = 0.98f; // the right edge
+ else if ( r == 2 ) pos.y = 0.02f; // on the lower edge
+ else pos.y = 0.92f; // on the upper edge
+ dim.x = (Math::Rand()*0.02f+0.02f);
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, SH_INTERFACE);
+ }
+ }
+ }
+
+ // Move the sound.
+ if ( m_soundChannel != -1 )
+ {
+ if ( !m_sound->Position(m_soundChannel, m_object->RetPosition(0)) )
+ {
+ m_soundChannel = -1;
+ }
+ }
+
+ return true;
+}
+
+
+// Starts an action.
+
+Error CMotionToto::SetAction(int action, float time)
+{
+ Sound sound;
+
+ CMotion::SetAction(action, time);
+
+ m_bStartAction = true;
+
+ sound = SOUND_CLICK;
+ if ( action == MT_ERROR ) sound = SOUND_ERROR;
+ if ( action == MT_WARNING ) sound = SOUND_WARNING;
+ if ( action == MT_INFO ) sound = SOUND_INFO;
+ if ( action == MT_MESSAGE ) sound = SOUND_MESSAGE;
+
+ if ( sound != SOUND_CLICK )
+ {
+ m_soundChannel = m_sound->Play(sound, m_object->RetPosition(0));
+ }
+
+ return ERR_OK;
+}
+
+// Specifies the type of the object is attached to toto.
+
+void CMotionToto::SetLinkType(ObjectType type)
+{
+ m_type = type;
+}
+
+
diff --git a/src/object/motion/motiontoto.h b/src/object/motion/motiontoto.h
index 8edeec0..9df2d99 100644
--- a/src/object/motion/motiontoto.h
+++ b/src/object/motion/motiontoto.h
@@ -1,70 +1,70 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motiontoto.h
-
-#pragma once
-
-
-#include "object/motion/motion.h"
-
-
-
-enum MotionTotoAction
-{
- MT_ERROR = 0,
- MT_WARNING = 1,
- MT_INFO = 2,
- MT_MESSAGE = 3
-};
-
-
-class CMotionToto : public CMotion
-{
-public:
- CMotionToto(CInstanceManager* iMan, CObject* object);
- ~CMotionToto();
-
- void DeleteObject(bool bAll=false);
- bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- bool EventProcess(const Event &event);
- Error SetAction(int action, float time=0.2f);
- void SetLinkType(ObjectType type);
-
- void StartDisplayInfo();
- void StopDisplayInfo();
- void SetMousePos(Math::Point pos);
-
-protected:
- bool EventFrame(const Event &event);
-
-protected:
- float m_time;
- float m_lastMotorParticule;
- bool m_bDisplayInfo;
- bool m_bQuickPos;
- bool m_bStartAction;
- float m_speedAction;
- float m_clownRadius;
- float m_clownDelay;
- float m_clownTime;
- float m_blinkTime;
- float m_blinkProgress;
- int m_soundChannel;
- ObjectType m_type;
- Math::Point m_mousePos;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motiontoto.h
+
+#pragma once
+
+
+#include "object/motion/motion.h"
+
+
+
+enum MotionTotoAction
+{
+ MT_ERROR = 0,
+ MT_WARNING = 1,
+ MT_INFO = 2,
+ MT_MESSAGE = 3
+};
+
+
+class CMotionToto : public CMotion
+{
+public:
+ CMotionToto(CInstanceManager* iMan, CObject* object);
+ ~CMotionToto();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ bool EventProcess(const Event &event);
+ Error SetAction(int action, float time=0.2f);
+ void SetLinkType(ObjectType type);
+
+ void StartDisplayInfo();
+ void StopDisplayInfo();
+ void SetMousePos(Math::Point pos);
+
+protected:
+ bool EventFrame(const Event &event);
+
+protected:
+ float m_time;
+ float m_lastMotorParticule;
+ bool m_bDisplayInfo;
+ bool m_bQuickPos;
+ bool m_bStartAction;
+ float m_speedAction;
+ float m_clownRadius;
+ float m_clownDelay;
+ float m_clownTime;
+ float m_blinkTime;
+ float m_blinkProgress;
+ int m_soundChannel;
+ ObjectType m_type;
+ Math::Point m_mousePos;
+};
+
diff --git a/src/object/motion/motionvehicle.cpp b/src/object/motion/motionvehicle.cpp
index 6f96991..ff05695 100644
--- a/src/object/motion/motionvehicle.cpp
+++ b/src/object/motion/motionvehicle.cpp
@@ -1,2073 +1,2073 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionvehicle.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motionvehicle.h"
-
-#include "old/modfile.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "math/geometry.h"
-#include "object/brain.h"
-#include "physics/physics.h"
-
-
-
-
-
-
-// Object's constructor.
-
-CMotionVehicle::CMotionVehicle(CInstanceManager* iMan, CObject* object)
- : CMotion(iMan, object)
-{
- int i;
-
- for ( i=0 ; i<4 ; i++ )
- {
- m_wheelTurn[i] = 0.0f;
- }
- for ( i=0 ; i<3 ; i++ )
- {
- m_flyPaw[i] = 0.0f;
- }
- m_posTrackLeft = 0.0f;
- m_posTrackRight = 0.0f;
- m_partiReactor = -1;
- m_armTimeAbs = 1000.0f;
- m_armMember = 1000.0f;
- m_canonTime = 0.0f;
- m_lastTimeCanon = 0.0f;
- m_wheelLastPos = Math::Vector(0.0f, 0.0f, 0.0f);
- m_wheelLastAngle = Math::Vector(0.0f, 0.0f, 0.0f);
- m_posKey = Math::Vector(0.0f, 0.0f, 0.0f);
- m_bFlyFix = false;
-
- m_bTraceDown = false;
- m_traceColor = 1; // black
- m_traceWidth = 0.5f;
-}
-
-// Object's destructor.
-
-CMotionVehicle::~CMotionVehicle()
-{
-}
-
-
-// Removes an object.
-
-void CMotionVehicle::DeleteObject(bool bAll)
-{
- if ( m_partiReactor != -1 )
- {
- m_particule->DeleteParticule(m_partiReactor);
- m_partiReactor = -1;
- }
-}
-
-
-// Creates a vehicle traveling any lands on the ground.
-
-bool CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- CObject* pPower;
- int rank, i, j, parent;
- D3DCOLORVALUE color;
- char name[50];
-
- if ( m_engine->RetRestCreate() < 1+5+18+1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- m_object->SetType(type);
-
- // Creates the main base.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEfs )
- {
- pModFile->ReadModel("objects\\lem1f.mod");
- }
- if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts )
- {
- pModFile->ReadModel("objects\\lem1t.mod");
- }
- if ( type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEws )
- {
- if ( m_object->RetTrainer() )
- {
- pModFile->ReadModel("objects\\lem1wt.mod");
- }
- else
- {
- pModFile->ReadModel("objects\\lem1w.mod");
- }
- }
- if ( type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEis )
- {
- pModFile->ReadModel("objects\\lem1i.mod");
- }
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs )
- {
- pModFile->ReadModel("objects\\roller1.mod");
- }
- if ( type == OBJECT_MOBILEsa )
- {
- pModFile->ReadModel("objects\\subm1.mod");
- }
- if ( type == OBJECT_MOBILEtg )
- {
- pModFile->ReadModel("objects\\target.mod");
- }
- if ( type == OBJECT_MOBILEwt )
- {
- pModFile->ReadModel("objects\\trainerw.mod");
- }
- if ( type == OBJECT_MOBILEft )
- {
- pModFile->ReadModel("objects\\trainerf.mod");
- }
- if ( type == OBJECT_MOBILEtt )
- {
- pModFile->ReadModel("objects\\trainert.mod");
- }
- if ( type == OBJECT_MOBILEit )
- {
- pModFile->ReadModel("objects\\traineri.mod");
- }
- if ( type == OBJECT_MOBILEdr )
- {
- pModFile->ReadModel("objects\\drawer1.mod");
- }
- if ( type == OBJECT_APOLLO2 )
- {
- pModFile->ReadModel("objects\\apolloj1.mod");
- }
- pModFile->CreateEngineObject(rank);
-
- m_object->SetPosition(0, pos);
- m_object->SetAngleY(0, angle);
-
- // A vehicle must have a obligatory collision
- // with a sphere of center (0, y, 0) (see GetCrashSphere).
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs )
- {
- m_object->CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 6.5f, SOUND_BOUMm, 0.45f);
- m_object->SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 7.0f);
- }
- else if ( type == OBJECT_MOBILEsa )
- {
- m_object->CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 4.5f, SOUND_BOUMm, 0.45f);
- m_object->SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f);
- }
- else if ( type == OBJECT_MOBILEdr )
- {
- m_object->CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- m_object->SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 7.0f);
- }
- else if ( type == OBJECT_APOLLO2 )
- {
- m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 8.0f, SOUND_BOUMm, 0.45f);
- }
- else
- {
- m_object->CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 4.5f, SOUND_BOUMm, 0.45f);
- m_object->SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 6.0f);
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia )
- {
- // Creates the arm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\lem2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
- m_object->SetAngleZ(1, ARM_NEUTRAL_ANGLE1);
-
- // Creates the forearm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\lem3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(5.0f, 0.0f, 0.0f));
- m_object->SetAngleZ(2, ARM_NEUTRAL_ANGLE2);
-
- // Creates the hand.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\lem4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(3.5f, 0.0f, 0.0f));
- m_object->SetAngleZ(3, ARM_NEUTRAL_ANGLE3);
- m_object->SetAngleX(3, Math::PI/2.0f);
-
- // Creates the close clamp.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(4, rank);
- m_object->SetObjectParent(4, 3);
- pModFile->ReadModel("objects\\lem5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(4, Math::Vector(1.5f, 0.0f, 0.0f));
- m_object->SetAngleZ(4, -Math::PI*0.10f);
-
- // Creates the remote clamp.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(5, rank);
- m_object->SetObjectParent(5, 3);
- pModFile->ReadModel("objects\\lem6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(5, Math::Vector(1.5f, 0.0f, 0.0f));
- m_object->SetAngleZ(5, Math::PI*0.10f);
- }
-
- if ( type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis )
- {
- // Creates the arm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\lem2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
- m_object->SetAngleZ(1, 110.0f*Math::PI/180.0f);
-
- // Creates the forearm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\lem3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(5.0f, 0.0f, 0.0f));
- m_object->SetAngleZ(2, -110.0f*Math::PI/180.0f);
-
- // Creates the sensor.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\lem4s.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(3.5f, 0.0f, 0.0f));
- m_object->SetAngleZ(3, -65.0f*Math::PI/180.0f);
- }
-
- if ( type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic )
- {
- // Creates the cannon.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\canon.mod");
- pModFile->CreateEngineObject(rank);
-//? m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
- m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
- m_object->SetAngleZ(1, 0.0f);
- }
-
- if ( type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii )
- {
- // Creates the insect cannon.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\canoni1.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
- m_object->SetAngleZ(1, 0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\canoni2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(0.0f, 2.5f, 0.0f));
- m_object->SetAngleZ(2, 0.0f);
- }
-
- if ( type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEwt )
- {
- // Creates the right-back wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\lem2w.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(-3.0f, 1.0f, -3.0f));
-
- // Creates the left-back wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\lem2w.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(-3.0f, 1.0f, 3.0f));
- m_object->SetAngleY(7, Math::PI);
-
- // Creates the right-front wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 0);
- pModFile->ReadModel("objects\\lem2w.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(2.0f, 1.0f, -3.0f));
-
- // Creates the left-front wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(9, rank);
- m_object->SetObjectParent(9, 0);
- pModFile->ReadModel("objects\\lem2w.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(9, Math::Vector(2.0f, 1.0f, 3.0f));
- m_object->SetAngleY(9, Math::PI);
- }
-
- if ( type == OBJECT_MOBILEtg )
- {
- // Creates the right-back wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\lem2w.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(-2.0f, 1.0f, -3.0f));
-
- // Creates the left-back wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\lem2w.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(-2.0f, 1.0f, 3.0f));
- m_object->SetAngleY(7, Math::PI);
-
- // Creates the right-front wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 0);
- pModFile->ReadModel("objects\\lem2w.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(3.0f, 1.0f, -3.0f));
-
- // Creates the left-front wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(9, rank);
- m_object->SetObjectParent(9, 0);
- pModFile->ReadModel("objects\\lem2w.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(9, Math::Vector(3.0f, 1.0f, 3.0f));
- m_object->SetAngleY(9, Math::PI);
- }
-
- if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts ) // caterpillars?
- {
- // Creates the right caterpillar.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\lem2t.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(0.0f, 2.0f, -3.0f));
-
- // Creates the left caterpillar.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\lem3t.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, 2.0f, 3.0f));
- }
-
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ) // large caterpillars?
- {
- // Creates the right caterpillar.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\roller2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(0.0f, 2.0f, -3.0f));
-
- // Creates the left caterpillar.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\roller3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, 2.0f, 3.0f));
- }
-
- if ( type == OBJECT_MOBILEsa ) // underwater caterpillars?
- {
- // Creates the right caterpillar.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\subm4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(0.0f, 1.0f, -3.0f));
-
- // Creates the left caterpillar.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\subm5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, 1.0f, 3.0f));
- }
-
- if ( type == OBJECT_MOBILEdr ) // caterpillars?
- {
- // Creates the right caterpillar.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\drawer2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(0.0f, 1.0f, -3.0f));
-
- // Creates the left caterpillar.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\drawer3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, 1.0f, 3.0f));
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEft ) // flying?
- {
- // Creates the front foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\lem2f.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(1.7f, 3.0f, 0.0f));
-
- // Creates the right-back foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\lem2f.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(-1.8f, 3.0f, -1.5f));
- m_object->SetAngleY(7, 120.0f*Math::PI/180.0f);
-
- // Creates the left-back foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 0);
- pModFile->ReadModel("objects\\lem2f.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(-1.8f, 3.0f, 1.5f));
- m_object->SetAngleY(8, -120.0f*Math::PI/180.0f);
- }
-
- if ( type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILEii ) // insect legs?
- {
- float table[] =
- {
- // x y z
- -1.5f, 1.2f, -0.7f, // back leg
- 0.0f, 0.0f, -1.0f,
- 0.0f, 0.0f, -2.0f,
-
- 0.0f, 1.2f, -0.9f, // middle leg
- 0.0f, 0.0f, -1.0f,
- 0.0f, 0.0f, -2.0f,
-
- 1.5f, 1.2f, -0.7f, // front leg
- 0.0f, 0.0f, -1.0f,
- 0.0f, 0.0f, -2.0f,
- };
-
- for ( i=0 ; i<3 ; i++ )
- {
- for ( j=0 ; j<3 ; j++ )
- {
- sprintf(name, "objects\\ant%d.mod", j+4); // 4..6
-
- // Creates the right leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6+i*3+j, rank);
- if ( j == 0 ) parent = 0;
- else parent = 6+i*3+j-1;
- m_object->SetObjectParent(6+i*3+j, parent);
- pModFile->ReadModel(name);
- pModFile->CreateEngineObject(rank);
- pos.x = table[i*9+j*3+0];
- pos.y = table[i*9+j*3+1];
- pos.z = table[i*9+j*3+2];
- m_object->SetPosition(6+i*3+j, pos);
-
- // Creates the left leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(15+i*3+j, rank);
- if ( j == 0 ) parent = 0;
- else parent = 15+i*3+j-1;
- m_object->SetObjectParent(15+i*3+j, parent);
- pModFile->ReadModel(name);
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- pos.x = table[i*9+j*3+0];
- pos.y = table[i*9+j*3+1];
- pos.z = -table[i*9+j*3+2];
- m_object->SetPosition(15+i*3+j, pos);
- }
- }
- }
-
- if ( type == OBJECT_MOBILErt )
- {
- // Creates the holder.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\roller2t.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetAngleZ(1, 0.0f);
-
- // Creates the pestle.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\roller3t.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(9.0f, 4.0f, 0.0f));
- m_object->SetAngleZ(2, 0.0f);
- }
-
- if ( type == OBJECT_MOBILErc )
- {
- // Creates the holder.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\roller2c.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(3.0f, 4.6f, 0.0f));
- m_object->SetAngleZ(1, Math::PI/8.0f);
-
- // Creates the cannon.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\roller3p.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(7.0f, 6.5f, 0.0f));
- m_object->SetAngleZ(2, 0.0f);
- }
-
- if ( type == OBJECT_MOBILErr )
- {
- // Creates the holder.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\recover1.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(2.0f, 5.0f, 0.0f));
-
- // Creates the right arm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\recover2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(0.1f, 0.0f, -5.0f));
- m_object->SetAngleZ(2, 126.0f*Math::PI/180.0f);
-
- // Creates the right forearm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\recover3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(5.0f, 0.0f, -0.5f));
- m_object->SetAngleZ(3, -144.0f*Math::PI/180.0f);
-
- // Creates the left arm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(4, rank);
- m_object->SetObjectParent(4, 1);
- pModFile->ReadModel("objects\\recover2.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(4, Math::Vector(0.1f, 0.0f, 5.0f));
- m_object->SetAngleZ(4, 126.0f*Math::PI/180.0f);
-
- // Creates the left forearm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(5, rank);
- m_object->SetObjectParent(5, 4);
- pModFile->ReadModel("objects\\recover3.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(5, Math::Vector(5.0f, 0.0f, 0.5f));
- m_object->SetAngleZ(5, -144.0f*Math::PI/180.0f);
- }
-
- if ( type == OBJECT_MOBILErs )
- {
- // Creates the holder.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\roller2s.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetAngleZ(1, 0.0f);
-
- // Creates the intermediate piston.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\roller3s.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(7.0f, 4.5f, 0.0f));
- m_object->SetAngleZ(2, 0.0f);
-
- // Creates the piston with the sphere.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\roller4s.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(0.0f, 1.0f, 0.0f));
- m_object->SetAngleZ(3, 0.0f);
- }
-
- if ( type == OBJECT_MOBILEsa )
- {
- // Creates the holder.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\subm2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(4.2f, 3.0f, 0.0f));
-
- // Creates the right tong.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\subm3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(0.5f, 0.0f, -1.5f));
-
- // Creates the left tong.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 1);
- pModFile->ReadModel("objects\\subm3.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(0.5f, 0.0f, 1.5f));
- }
-
- if ( type == OBJECT_MOBILEdr )
- {
- // Creates the carousel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\drawer4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(-3.0f, 3.0f, 0.0f));
-
- // Creates the key.
- if ( m_object->RetToy() )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\drawer5.mod");
- pModFile->CreateEngineObject(rank);
- m_posKey = Math::Vector(3.0f, 5.7f, 0.0f);
- m_object->SetPosition(2, m_posKey);
- m_object->SetAngleY(2, 90.0f*Math::PI/180.0f);
- }
-
- // Creates pencils.
- for ( i=0 ; i<8 ; i++ )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(10+i, rank);
- m_object->SetObjectParent(10+i, 1);
- sprintf(name, "objects\\drawer%d.mod", 10+i);
- pModFile->ReadModel(name);
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(10+i, Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetAngleY(10+i, 45.0f*Math::PI/180.0f*i);
- }
- }
-
- if ( type == OBJECT_MOBILEwt )
- {
- // Creates the key.
- if ( m_object->RetToy() )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\drawer5.mod");
- pModFile->CreateEngineObject(rank);
- m_posKey = Math::Vector(0.2f, 4.1f, 0.0f);
- m_object->SetPosition(2, m_posKey);
- m_object->SetAngleY(2, 90.0f*Math::PI/180.0f);
- }
- }
-
- if ( type == OBJECT_APOLLO2 )
- {
- // Creates the accessories.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\apolloj2.mod"); // antenna
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(5.5f, 8.8f, 2.0f));
- m_object->SetAngleY(1, -120.0f*Math::PI/180.0f);
- m_object->SetAngleZ(1, 45.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\apolloj3.mod"); // camera
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(5.5f, 2.8f, -2.0f));
- m_object->SetAngleY(2, 30.0f*Math::PI/180.0f);
-
- // Creates the wheels.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(-5.75f, 1.65f, -5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(-5.75f, 1.65f, 5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 0);
- pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(5.75f, 1.65f, -5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(9, rank);
- m_object->SetObjectParent(9, 0);
- pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(9, Math::Vector(5.75f, 1.65f, 5.00f));
-
- // Creates mud guards.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(10, rank);
- m_object->SetObjectParent(10, 0);
- pModFile->ReadModel("objects\\apolloj6.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(10, Math::Vector(-5.75f, 1.65f, -5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(11, rank);
- m_object->SetObjectParent(11, 0);
- pModFile->ReadModel("objects\\apolloj6.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(11, Math::Vector(-5.75f, 1.65f, 5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(12, rank);
- m_object->SetObjectParent(12, 0);
- pModFile->ReadModel("objects\\apolloj5.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(12, Math::Vector(5.75f, 1.65f, -5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(13, rank);
- m_object->SetObjectParent(13, 0);
- pModFile->ReadModel("objects\\apolloj5.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(13, Math::Vector(5.75f, 1.65f, 5.00f));
- }
-
-#if 1
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs )
- {
- m_object->CreateShadowCircle(6.0f, 1.0f);
- }
- else if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEsa )
- {
- m_object->CreateShadowCircle(5.0f, 1.0f);
- }
- else if ( type == OBJECT_MOBILEdr )
- {
- m_object->CreateShadowCircle(4.5f, 1.0f);
- }
- else if ( type == OBJECT_APOLLO2 )
- {
- m_object->CreateShadowCircle(7.0f, 0.8f);
- }
- else
- {
- m_object->CreateShadowCircle(4.0f, 1.0f);
- }
-#else
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs )
- {
- m_object->CreateShadowCircle(6.0f, 1.0f, D3DSHADOWTANK);
- }
- else if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts )
- {
- m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWTANK);
- }
- else if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEfs )
- {
- m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWFLY);
- }
- else if ( type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEws )
- {
- m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWWHEEL);
- }
- else if ( type == OBJECT_APOLLO2 )
- {
- m_object->CreateShadowCircle(6.0f, 0.8f);
- }
- else
- {
- m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWNORM);
- }
-#endif
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEft ) // flying?
- {
-//? color.r = 0.5f-1.0f;
-//? color.g = 0.2f-1.0f;
-//? color.b = 0.0f-1.0f; // orange
-//? color.r = 0.8f;
-//? color.g = 0.6f;
-//? color.b = 0.0f; // yellow-orange
- color.r = 0.0f;
- color.g = 0.4f;
- color.b = 0.8f; // blue
- color.a = 0.0f;
- m_object->CreateShadowLight(50.0f, color);
- }
-
- CreatePhysics(type);
- m_object->SetFloorHeight(0.0f);
-
- if ( power > 0.0f &&
- type != OBJECT_MOBILEdr &&
- type != OBJECT_APOLLO2 )
- {
- color.r = 1.0f;
- color.g = 1.0f;
- color.b = 0.0f; // yellow
- color.a = 0.0f;
- m_object->CreateEffectLight(20.0f, color);
-
- // Creates the battery.
- pPower = new CObject(m_iMan);
- pPower->SetType(power<=1.0f?OBJECT_POWER:OBJECT_ATOMIC);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- pPower->SetObjectRank(0, rank);
-
- if ( power <= 1.0f ) pModFile->ReadModel("objects\\power.mod");
- else pModFile->ReadModel("objects\\atomic.mod");
- pModFile->CreateEngineObject(rank);
-
- pPower->SetPosition(0, m_object->RetCharacter()->posPower);
- pPower->CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- pPower->SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.5f);
-
- pPower->SetTruck(m_object);
- m_object->SetPower(pPower);
-
- if ( power <= 1.0f ) pPower->SetEnergy(power);
- else pPower->SetEnergy(power/100.0f);
- }
-
- pos = m_object->RetPosition(0);
- m_object->SetPosition(0, pos); //to display the shadows immediately
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-// Creates the physics of the object.
-
-void CMotionVehicle::CreatePhysics(ObjectType type)
-{
- Character* character;
-
- character = m_object->RetCharacter();
-
- if ( type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEwt ) // wheels?
- {
- m_physics->SetType(TYPE_ROLLING);
-
- character->wheelFront = 3.0f;
- character->wheelBack = 4.0f;
- character->wheelLeft = 4.0f;
- character->wheelRight = 4.0f;
- character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 20.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 30.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 8.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 8.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 12.0f);
- }
-
- if ( type == OBJECT_MOBILEtg )
- {
- m_physics->SetType(TYPE_ROLLING);
-
- character->wheelFront = 4.0f;
- character->wheelBack = 3.0f;
- character->wheelLeft = 4.0f;
- character->wheelRight = 4.0f;
- character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 20.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 20.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 15.0f);
- }
-
- if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts ) // caterpillars?
- {
- m_physics->SetType(TYPE_ROLLING);
-
- character->wheelFront = 4.0f;
- character->wheelBack = 4.0f;
- character->wheelLeft = 4.8f;
- character->wheelRight = 4.8f;
- character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 8.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 8.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 6.0f);
- }
-
- if ( type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEis ) // legs?
- {
- m_physics->SetType(TYPE_ROLLING);
-
- character->wheelFront = 4.0f;
- character->wheelBack = 4.0f;
- character->wheelLeft = 5.0f;
- character->wheelRight = 5.0f;
- character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 8.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 10.0f);
-//? m_physics->SetLinMotionX(MO_TERFORCE, 15.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 15.0f);
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEft ) // flying?
- {
- m_physics->SetType(TYPE_FLYING);
-
- character->wheelFront = 5.0f;
- character->wheelBack = 4.0f;
- character->wheelLeft = 4.5f;
- character->wheelRight = 4.5f;
- character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 50.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 50.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
- m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
- m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
- m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
- m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.4f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.4f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 2.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 2.0f);
- }
-
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ) // large caterpillars?
- {
- m_physics->SetType(TYPE_ROLLING);
-
- character->wheelFront = 5.0f;
- character->wheelBack = 5.0f;
- character->wheelLeft = 6.0f;
- character->wheelRight = 6.0f;
- character->posPower = Math::Vector(-5.8f, 4.0f, 0.0f);
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 10.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 5.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 5.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.3f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.3f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 2.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 4.0f);
- }
-
- if ( type == OBJECT_MOBILEsa )
- {
- m_physics->SetType(TYPE_ROLLING);
-
- character->wheelFront = 4.0f;
- character->wheelBack = 4.0f;
- character->wheelLeft = 4.0f;
- character->wheelRight = 4.0f;
- character->posPower = Math::Vector(-5.0f, 3.0f, 0.0f);
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 5.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 5.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 10.0f);
- }
-
- if ( type == OBJECT_MOBILEdr )
- {
- m_physics->SetType(TYPE_ROLLING);
-
- character->wheelFront = 4.0f;
- character->wheelBack = 4.0f;
- character->wheelLeft = 4.0f;
- character->wheelRight = 4.0f;
- character->posPower = Math::Vector(-5.0f, 3.0f, 0.0f);
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 5.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 5.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 10.0f);
- }
-
- if ( type == OBJECT_APOLLO2 ) // jeep?
- {
- m_physics->SetType(TYPE_ROLLING);
-
- character->wheelFront = 6.0f;
- character->wheelBack = 6.0f;
- character->wheelLeft = 5.0f;
- character->wheelRight = 5.0f;
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 2.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 2.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 30.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.4f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.4f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 2.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 4.0f);
- }
-}
-
-
-// Management of an event.
-
-bool CMotionVehicle::EventProcess(const Event &event)
-{
- CMotion::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
- }
-
- return true;
-}
-
-// Management of an event.
-
-bool CMotionVehicle::EventFrame(const Event &event)
-{
- Math::Matrix* mat;
- Character* character;
- Math::Vector pos, angle, floor;
- ObjectType type;
- float s, a, speedBL, speedBR, speedFL, speedFR, h, a1, a2;
- float back, front, dist, radius, limit[2];
-
- if ( m_engine->RetPause() ) return true;
- if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
-
- type = m_object->RetType();
-
- if ( type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_APOLLO2 ) // wheels?
- {
- s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.0f;
- a = m_physics->RetCirMotionY(MO_MOTSPEED)*3.0f;
-
- if ( type == OBJECT_APOLLO2 ) s *= 0.5f;
-
- speedBR = -s+a;
- speedBL = s+a;
- speedFR = -s+a;
- speedFL = s+a;
-
- m_object->SetAngleZ(6, m_object->RetAngleZ(6)+event.rTime*speedBR); // turning the wheels
- m_object->SetAngleZ(7, m_object->RetAngleZ(7)+event.rTime*speedBL);
- m_object->SetAngleZ(8, m_object->RetAngleZ(8)+event.rTime*speedFR);
- m_object->SetAngleZ(9, m_object->RetAngleZ(9)+event.rTime*speedFL);
-
- if ( s > 0.0f )
- {
- m_wheelTurn[0] = -a*0.05f;
- m_wheelTurn[1] = -a*0.05f+Math::PI;
- m_wheelTurn[2] = a*0.05f;
- m_wheelTurn[3] = a*0.05f+Math::PI;
- }
- else if ( s < 0.0f )
- {
- m_wheelTurn[0] = a*0.05f;
- m_wheelTurn[1] = a*0.05f+Math::PI;
- m_wheelTurn[2] = -a*0.05f;
- m_wheelTurn[3] = -a*0.05f+Math::PI;
- }
- else
- {
- m_wheelTurn[0] = fabs(a)*0.05f;
- m_wheelTurn[1] = -fabs(a)*0.05f+Math::PI;
- m_wheelTurn[2] = -fabs(a)*0.05f;
- m_wheelTurn[3] = fabs(a)*0.05f+Math::PI;
- }
- m_object->SetAngleY(6, m_object->RetAngleY(6)+(m_wheelTurn[0]-m_object->RetAngleY(6))*event.rTime*8.0f);
- m_object->SetAngleY(7, m_object->RetAngleY(7)+(m_wheelTurn[1]-m_object->RetAngleY(7))*event.rTime*8.0f);
- m_object->SetAngleY(8, m_object->RetAngleY(8)+(m_wheelTurn[2]-m_object->RetAngleY(8))*event.rTime*8.0f);
- m_object->SetAngleY(9, m_object->RetAngleY(9)+(m_wheelTurn[3]-m_object->RetAngleY(9))*event.rTime*8.0f);
-
- if ( type == OBJECT_APOLLO2 )
- {
- m_object->SetAngleY(10, m_object->RetAngleY(6)+(m_wheelTurn[0]-m_object->RetAngleY(6))*event.rTime*8.0f);
- m_object->SetAngleY(11, m_object->RetAngleY(7)+(m_wheelTurn[1]-m_object->RetAngleY(7))*event.rTime*8.0f+Math::PI);
- m_object->SetAngleY(12, m_object->RetAngleY(8)+(m_wheelTurn[2]-m_object->RetAngleY(8))*event.rTime*8.0f);
- m_object->SetAngleY(13, m_object->RetAngleY(9)+(m_wheelTurn[3]-m_object->RetAngleY(9))*event.rTime*8.0f+Math::PI);
- }
-
- pos = m_object->RetPosition(0);
- angle = m_object->RetAngle(0);
- if ( pos.x != m_wheelLastPos.x ||
- pos.y != m_wheelLastPos.y ||
- pos.z != m_wheelLastPos.z ||
- angle.x != m_wheelLastAngle.x ||
- angle.y != m_wheelLastAngle.y ||
- angle.z != m_wheelLastAngle.z )
- {
- m_wheelLastPos = pos;
- m_wheelLastAngle = angle;
-
- if ( type == OBJECT_MOBILEtg )
- {
- back = -2.0f; // back wheels position
- front = 3.0f; // front wheels position
- dist = 3.0f; // distancing wheels Z
- radius = 1.0f;
- }
- else if ( type == OBJECT_APOLLO2 )
- {
- back = -5.75f; // back wheels position
- front = 5.75f; // front wheels position
- dist = 5.00f; // distancing wheels Z
- radius = 1.65f;
- }
- else
- {
- back = -3.0f; // back wheels position
- front = 2.0f; // front wheels position
- dist = 3.0f; // distancing wheels Z
- radius = 1.0f;
- }
-
- if ( Math::Distance(pos, m_engine->RetEyePt()) < 50.0f ) // suspension?
- {
- character = m_object->RetCharacter();
- mat = m_object->RetWorldMatrix(0);
-
- pos.x = -character->wheelBack; // right back wheel
- pos.z = -character->wheelRight;
- pos.y = 0.0f;
- pos = Math::Transform(*mat, pos);
- h = m_terrain->RetFloorHeight(pos);
- if ( h > 0.5f ) h = 0.5f;
- if ( h < -0.5f ) h = -0.5f;
- pos.x = back;
- pos.y = radius-h;
- pos.z = -dist;
- m_object->SetPosition(6, pos);
- if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(10, pos);
-
- pos.x = -character->wheelBack; // left back wheel
- pos.z = character->wheelLeft;
- pos.y = 0.0f;
- pos = Math::Transform(*mat, pos);
- h = m_terrain->RetFloorHeight(pos);
- if ( h > 0.5f ) h = 0.5f;
- if ( h < -0.5f ) h = -0.5f;
- pos.x = back;
- pos.y = radius-h;
- pos.z = dist;
- m_object->SetPosition(7, pos);
- if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(11, pos);
-
- pos.x = character->wheelFront; // right front wheel
- pos.z = -character->wheelRight;
- pos.y = 0.0f;
- pos = Math::Transform(*mat, pos);
- h = m_terrain->RetFloorHeight(pos);
- if ( h > 0.5f ) h = 0.5f;
- if ( h < -0.5f ) h = -0.5f;
- pos.x = front;
- pos.y = radius-h;
- pos.z = -dist;
- m_object->SetPosition(8, pos);
- if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(12, pos);
-
- pos.x = character->wheelFront; // left front wheel
- pos.z = character->wheelLeft;
- pos.y = 0.0f;
- pos = Math::Transform(*mat, pos);
- h = m_terrain->RetFloorHeight(pos);
- if ( h > 0.5f ) h = 0.5f;
- if ( h < -0.5f ) h = -0.5f;
- pos.x = front;
- pos.y = radius-h;
- pos.z = dist;
- m_object->SetPosition(9, pos);
- if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(13, pos);
- }
- else
- {
- m_object->SetPosition(6, Math::Vector(back, radius, -dist));
- m_object->SetPosition(7, Math::Vector(back, radius, dist));
- m_object->SetPosition(8, Math::Vector(front, radius, -dist));
- m_object->SetPosition(9, Math::Vector(front, radius, dist));
-
- if ( type == OBJECT_APOLLO2 )
- {
- m_object->SetPosition(10, Math::Vector(back, radius, -dist));
- m_object->SetPosition(11, Math::Vector(back, radius, dist));
- m_object->SetPosition(12, Math::Vector(front, radius, -dist));
- m_object->SetPosition(13, Math::Vector(front, radius, dist));
- }
- }
- }
- }
-
- if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEdr ) // caterpillars?
- {
- s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.7f;
- a = m_physics->RetCirMotionY(MO_MOTSPEED)*2.5f;
-
- m_posTrackLeft += event.rTime*(s+a);
- m_posTrackRight += event.rTime*(s-a);
-
- UpdateTrackMapping(m_posTrackLeft, m_posTrackRight, type);
-
- pos = m_object->RetPosition(0);
- angle = m_object->RetAngle(0);
- if ( pos.x != m_wheelLastPos.x ||
- pos.y != m_wheelLastPos.y ||
- pos.z != m_wheelLastPos.z ||
- angle.x != m_wheelLastAngle.x ||
- angle.y != m_wheelLastAngle.y ||
- angle.z != m_wheelLastAngle.z )
- {
- m_wheelLastPos = pos;
- m_wheelLastAngle = angle;
-
- if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts )
- {
- limit[0] = 8.0f*Math::PI/180.0f;
- limit[1] = -12.0f*Math::PI/180.0f;
- }
- else if ( type == OBJECT_MOBILEsa )
- {
- limit[0] = 15.0f*Math::PI/180.0f;
- limit[1] = -15.0f*Math::PI/180.0f;
- }
- else if ( type == OBJECT_MOBILEdr )
- {
- limit[0] = 10.0f*Math::PI/180.0f;
- limit[1] = -10.0f*Math::PI/180.0f;
- }
- else
- {
- limit[0] = 15.0f*Math::PI/180.0f;
- limit[1] = -10.0f*Math::PI/180.0f;
- }
-
- if ( Math::Distance(pos, m_engine->RetEyePt()) < 50.0f ) // suspension?
- {
- character = m_object->RetCharacter();
- mat = m_object->RetWorldMatrix(0);
-
- pos.x = character->wheelFront; // right front wheel
- pos.z = -character->wheelRight;
- pos.y = 0.0f;
- pos = Transform(*mat, pos);
- a1 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelFront);
-
- pos.x = -character->wheelBack; // right back wheel
- pos.z = -character->wheelRight;
- pos.y = 0.0f;
- pos = Transform(*mat, pos);
- a2 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelBack);
-
- a = (a2-a1)/2.0f;
- if ( a > limit[0] ) a = limit[0];
- if ( a < limit[1] ) a = limit[1];
- m_object->SetAngleZ(6, a);
-
- pos.x = character->wheelFront; // left front wheel
- pos.z = character->wheelLeft;
- pos.y = 0.0f;
- pos = Transform(*mat, pos);
- a1 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelFront);
-
- pos.x = -character->wheelBack; // left back wheel
- pos.z = character->wheelLeft;
- pos.y = 0.0f;
- pos = Transform(*mat, pos);
- a2 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelBack);
-
- a = (a2-a1)/2.0f;
- if ( a > limit[0] ) a = limit[0];
- if ( a < limit[1] ) a = limit[1];
- m_object->SetAngleZ(7, a);
- }
- else
- {
- m_object->SetAngleZ(6, 0.0f);
- m_object->SetAngleZ(7, 0.0f);
- }
- }
- }
-
- if ( type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEdr ) // toy is key?
- {
- pos = m_posKey;
- if ( m_object->RetSelect() &&
- m_camera->RetType() == CAMERA_ONBOARD )
- {
- pos.y += 10.0f; // out of sight!
- }
- m_object->SetPosition(2, pos);
-
- s = -fabs(m_physics->RetLinMotionX(MO_MOTSPEED)*0.1f);
- s += -fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*1.5f);
- m_object->SetAngleY(2, m_object->RetAngleY(2)+event.rTime*s); // turns the key
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEft ) // flying?
- {
- EventFrameFly(event);
- }
-
- if ( type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEis ) // legs?
- {
- EventFrameInsect(event);
- }
-
- if ( type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEii ) // insect cannon?
- {
- EventFrameCanoni(event);
- }
-
- return true;
-}
-
-// Managing an event for a flying robot.
-
-bool CMotionVehicle::EventFrameFly(const Event &event)
-{
- Math::Matrix* mat;
- Math::Vector pos, angle, paw[3];
- float hope[3], actual, final, h, a;
- int i;
-
- pos = m_object->RetPosition(0);
- angle = m_object->RetAngle(0);
- if ( m_bFlyFix &&
- pos.x == m_wheelLastPos.x &&
- pos.y == m_wheelLastPos.y &&
- pos.z == m_wheelLastPos.z &&
- angle.x == m_wheelLastAngle.x &&
- angle.y == m_wheelLastAngle.y &&
- angle.z == m_wheelLastAngle.z ) return true;
-
- m_wheelLastPos = pos;
- m_wheelLastAngle = angle;
-
- if ( m_physics->RetLand() ) // on the ground?
- {
- mat = m_object->RetWorldMatrix(0);
- paw[0] = Transform(*mat, Math::Vector( 4.2f, 0.0f, 0.0f)); // front
- paw[1] = Transform(*mat, Math::Vector(-3.0f, 0.0f, -3.7f)); // right back
- paw[2] = Transform(*mat, Math::Vector(-3.0f, 0.0f, 3.7f)); // left back
-
- for ( i=0 ; i<3 ; i++ )
- {
- h = m_terrain->RetFloorHeight(paw[i]);
- a = -atanf(h*0.5f);
- if ( a > Math::PI*0.2f ) a = Math::PI*0.2f;
- if ( a < -Math::PI*0.2f ) a = -Math::PI*0.2f;
- hope[i] = a;
- }
- }
- else // in flight?
- {
- hope[0] = 0.0f; // front
- hope[1] = 0.0f; // right back
- hope[2] = 0.0f; // left back
- }
-
- m_bFlyFix = true;
- for ( i=0 ; i<3 ; i++ )
- {
- actual = m_object->RetAngleZ(6+i);
- final = Math::Smooth(actual, hope[i], event.rTime*5.0f);
- if ( final != actual )
- {
- m_bFlyFix = false; // it is moving
- m_object->SetAngleZ(6+i, final);
- }
- }
-
- return true;
-}
-
-// Event management for insect legs.
-
-bool CMotionVehicle::EventFrameInsect(const Event &event)
-{
- Math::Vector dir;
- float s, a, prog, time;
- int i, st, nd, action;
- bool bStop, bOnBoard;
-
- static int table[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
- 60,25,0, 60,0,0, 60,-25,0, // t0: thighs 1..4
- -35,0,0, -35,0,0, -35,0,0, // t0: legs 1..4
- -65,0,0, -65,0,0, -65,0,0, // t0: feet 1..4
- // on the ground:
- 30,10,0, 30,-15,0, 30,-40,0, // t1: thighs 1..4
- -45,0,0, -45,0,0, -45,0,0, // t1: legs 1..4
- -20,0,0, -20,0,0, -20,0,0, // t1: feet 1..4
- // on the ground back:
- 35,40,0, 40,15,0, 40,-10,0, // t2: thighs 1..4
- -35,0,0, -35,0,0, -35,0,0, // t2: legs 1..4
- -50,0,0, -65,0,0, -65,0,0, // t2: feet 1..4
- // stop:
- 35,35,0, 40,10,0, 40,-15,0, // s0: thighs 1..4
- -35,0,0, -35,0,0, -35,0,0, // s0: legs 1..4
- -50,0,0, -65,0,0, -65,0,0, // s0: feet 1..4
- };
-
- bOnBoard = false;
- if ( m_object->RetSelect() &&
- m_camera->RetType() == CAMERA_ONBOARD )
- {
- bOnBoard = true;
- }
-
- s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
- a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f);
-
- if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
-
- m_armTimeAbs += event.rTime;
- m_armMember += (s+a)*event.rTime*0.15f;
-
- bStop = ( a == 0.0f && s == 0.0f ); // stop?
-
- action = 0; // walking
- if ( s == 0.0f && a == 0.0f )
- {
- action = 3; // stop
- }
-
- if ( bStop )
- {
- prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
- a = Math::Mod(m_armMember, 1.0f);
- a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly
- m_armMember += a;
- }
-
- if ( m_object->RetRuin() ) // burn or explode?
- {
- action = 3;
- }
-
- for ( i=0 ; i<6 ; i++ ) // the six legs
- {
- if ( action != 0 ) // special action in progress?
- {
- st = 3*3*3*action + (i%3)*3;
- nd = st;
- time = event.rTime*5.0f;
- }
- else
- {
- if ( i < 3 ) prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
- else prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
- if ( prog < 0.33f ) // t0..t1 ?
- {
- prog = prog/0.33f; // 0..1
- st = 0; // index start
- nd = 1; // index end
- }
- else if ( prog < 0.67f ) // t1..t2 ?
- {
- prog = (prog-0.33f)/0.33f; // 0..1
- st = 1; // index start
- nd = 2; // index end
- }
- else // t2..t0 ?
- {
- prog = (prog-0.67f)/0.33f; // 0..1
- st = 2; // index start
- nd = 0; // index end
- }
- st = 3*3*3*action + st*3*3*3 + (i%3)*3;
- nd = 3*3*3*action + nd*3*3*3 + (i%3)*3;
-
- // Less and less soft ...
- time = event.rTime*20.0f;
- }
-
- if ( i < 3 ) // right leg (1..3) ?
- {
- m_object->SetAngleX(6+3*i+0, Math::Smooth(m_object->RetAngleX(6+3*i+0), Math::PropAngle(table[st+ 0], table[nd+ 0], prog), time));
- m_object->SetAngleY(6+3*i+0, Math::Smooth(m_object->RetAngleY(6+3*i+0), Math::PropAngle(table[st+ 1], table[nd+ 1], prog), time));
- m_object->SetAngleZ(6+3*i+0, Math::Smooth(m_object->RetAngleZ(6+3*i+0), Math::PropAngle(table[st+ 2], table[nd+ 2], prog), time));
- m_object->SetAngleX(6+3*i+1, Math::Smooth(m_object->RetAngleX(6+3*i+1), Math::PropAngle(table[st+ 9], table[nd+ 9], prog), time));
- m_object->SetAngleY(6+3*i+1, Math::Smooth(m_object->RetAngleY(6+3*i+1), Math::PropAngle(table[st+10], table[nd+10], prog), time));
- m_object->SetAngleZ(6+3*i+1, Math::Smooth(m_object->RetAngleZ(6+3*i+1), Math::PropAngle(table[st+11], table[nd+11], prog), time));
- m_object->SetAngleX(6+3*i+2, Math::Smooth(m_object->RetAngleX(6+3*i+2), Math::PropAngle(table[st+18], table[nd+18], prog), time));
- m_object->SetAngleY(6+3*i+2, Math::Smooth(m_object->RetAngleY(6+3*i+2), Math::PropAngle(table[st+19], table[nd+19], prog), time));
- m_object->SetAngleZ(6+3*i+2, Math::Smooth(m_object->RetAngleZ(6+3*i+2), Math::PropAngle(table[st+20], table[nd+20], prog), time));
- }
- else // left leg (4..6) ?
- {
- m_object->SetAngleX(6+3*i+0, Math::Smooth(m_object->RetAngleX(6+3*i+0), Math::PropAngle(-table[st+ 0], -table[nd+ 0], prog), time));
- m_object->SetAngleY(6+3*i+0, Math::Smooth(m_object->RetAngleY(6+3*i+0), Math::PropAngle(-table[st+ 1], -table[nd+ 1], prog), time));
- m_object->SetAngleZ(6+3*i+0, Math::Smooth(m_object->RetAngleZ(6+3*i+0), Math::PropAngle( table[st+ 2], table[nd+ 2], prog), time));
- m_object->SetAngleX(6+3*i+1, Math::Smooth(m_object->RetAngleX(6+3*i+1), Math::PropAngle(-table[st+ 9], -table[nd+ 9], prog), time));
- m_object->SetAngleY(6+3*i+1, Math::Smooth(m_object->RetAngleY(6+3*i+1), Math::PropAngle(-table[st+10], -table[nd+10], prog), time));
- m_object->SetAngleZ(6+3*i+1, Math::Smooth(m_object->RetAngleZ(6+3*i+1), Math::PropAngle( table[st+11], table[nd+11], prog), time));
- m_object->SetAngleX(6+3*i+2, Math::Smooth(m_object->RetAngleX(6+3*i+2), Math::PropAngle(-table[st+18], -table[nd+18], prog), time));
- m_object->SetAngleY(6+3*i+2, Math::Smooth(m_object->RetAngleY(6+3*i+2), Math::PropAngle(-table[st+19], -table[nd+19], prog), time));
- m_object->SetAngleZ(6+3*i+2, Math::Smooth(m_object->RetAngleZ(6+3*i+2), Math::PropAngle( table[st+20], table[nd+20], prog), time));
- }
- }
-
- if ( bStop )
- {
- }
- else
- {
- a = Math::Mod(m_armMember, 1.0f);
- if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
- else a = 3.0f-4.0f*a; // 1..-1
- dir.x = sinf(a)*0.05f;
-
- s = Math::Mod(m_armMember/2.0f, 1.0f);
- if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
- else s = 3.0f-4.0f*s; // 1..-1
- dir.z = sinf(s)*0.1f;
-
- dir.y = 0.0f;
-
- if ( bOnBoard ) dir *= 0.6f;
- SetInclinaison(dir);
- }
-
- return true;
-}
-
-// Event management for a insect cannon.
-
-bool CMotionVehicle::EventFrameCanoni(const Event &event)
-{
- CObject* power;
- Math::Vector pos, speed;
- Math::Point dim;
- float zoom, angle, energy, factor;
- bool bOnBoard = false;
-
- m_canonTime += event.rTime;
-
- if ( m_object->RetSelect() &&
- m_camera->RetType() == CAMERA_ONBOARD )
- {
- bOnBoard = true;
- }
-
- power = m_object->RetPower();
- if ( power == 0 )
- {
- energy = 0.0f;
- }
- else
- {
- energy = power->RetEnergy();
- }
- if ( energy == 0.0f ) return true;
-
- factor = 0.5f+energy*0.5f;
- if ( bOnBoard ) factor *= 0.8f;
-
- zoom = 1.3f+
- sinf(m_canonTime*Math::PI*0.31f)*0.10f+
- sinf(m_canonTime*Math::PI*0.52f)*0.08f+
- sinf(m_canonTime*Math::PI*1.53f)*0.05f;
- zoom *= factor;
- m_object->SetZoomY(2, zoom);
-
- zoom = 1.0f+
- sinf(m_canonTime*Math::PI*0.27f)*0.07f+
- sinf(m_canonTime*Math::PI*0.62f)*0.06f+
- sinf(m_canonTime*Math::PI*1.73f)*0.03f;
- zoom *= factor;
- m_object->SetZoomZ(2, zoom);
-
- angle = sinf(m_canonTime*1.0f)*0.10f+
- sinf(m_canonTime*1.3f)*0.15f+
- sinf(m_canonTime*2.7f)*0.05f;
- m_object->SetAngleX(2, angle);
-
-#if 0
- m_lastTimeCanon -= event.rTime;
- if ( m_lastTimeCanon <= 0.0f )
- {
- m_lastTimeCanon = m_engine->ParticuleAdapt(0.5f+Math::Rand()*0.5f);
-
- pos = m_object->RetPosition(0);
- pos.y += 8.0f;
- speed.y = 7.0f+Math::Rand()*3.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = 2.0f+Math::Rand()*2.0f;
- if ( Math::Rand() < 0.5f ) speed.z = -speed.z;
- mat = m_object->RetRotateMatrix(0);
- speed = Transform(*mat, speed);
- dim.x = Math::Rand()*0.1f+0.1f;
- if ( bOnBoard ) dim.x *= 0.4f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIORGANIC2, 2.0f, 10.0f);
- }
-#endif
-
- return true;
-}
-
-
-// Updates the mapping of the texture of the caterpillars.
-
-void CMotionVehicle::UpdateTrackMapping(float left, float right, ObjectType type)
-{
- D3DMATERIAL7 mat;
- float limit[4];
- int rRank, lRank, i;
-
- ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
- mat.diffuse.r = 1.0f;
- mat.diffuse.g = 1.0f;
- mat.diffuse.b = 1.0f; // white
- mat.ambient.r = 0.5f;
- mat.ambient.g = 0.5f;
- mat.ambient.b = 0.5f;
-
- rRank = m_object->RetObjectRank(6);
- lRank = m_object->RetObjectRank(7);
-
-
- if ( type == OBJECT_MOBILEdr )
- {
- limit[0] = 0.0f;
- limit[1] = 1000000.0f;
- limit[2] = limit[1];
- limit[3] = m_engine->RetLimitLOD(1);
-
- m_engine->TrackTextureMapping(rRank, mat, D3DSTATEPART1, "drawer.tga", "",
- limit[0], limit[1], D3DMAPPINGX,
- right, 1.0f, 8.0f, 192.0f, 256.0f);
-
- m_engine->TrackTextureMapping(lRank, mat, D3DSTATEPART2, "drawer.tga", "",
- limit[0], limit[1], D3DMAPPINGX,
- left, 1.0f, 8.0f, 192.0f, 256.0f);
- }
- else
- {
- limit[0] = 0.0f;
- limit[1] = m_engine->RetLimitLOD(0);
- limit[2] = limit[1];
- limit[3] = m_engine->RetLimitLOD(1);
-
- for ( i=0 ; i<2 ; i++ )
- {
- m_engine->TrackTextureMapping(rRank, mat, D3DSTATEPART1, "lemt.tga", "",
- limit[i*2+0], limit[i*2+1], D3DMAPPINGX,
- right, 1.0f, 8.0f, 192.0f, 256.0f);
-
- m_engine->TrackTextureMapping(lRank, mat, D3DSTATEPART2, "lemt.tga", "",
- limit[i*2+0], limit[i*2+1], D3DMAPPINGX,
- left, 1.0f, 8.0f, 192.0f, 256.0f);
- }
- }
-
-}
-
-
-
-// State management of the pencil drawing robot.
-
-bool CMotionVehicle::RetTraceDown()
-{
- return m_bTraceDown;
-}
-
-void CMotionVehicle::SetTraceDown(bool bDown)
-{
- m_bTraceDown = bDown;
-}
-
-int CMotionVehicle::RetTraceColor()
-{
- return m_traceColor;
-}
-
-void CMotionVehicle::SetTraceColor(int color)
-{
- m_traceColor = color;
-}
-
-float CMotionVehicle::RetTraceWidth()
-{
- return m_traceWidth;
-}
-
-void CMotionVehicle::SetTraceWidth(float width)
-{
- m_traceWidth = width;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionvehicle.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motionvehicle.h"
+
+#include "old/modfile.h"
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "math/geometry.h"
+#include "object/brain.h"
+#include "physics/physics.h"
+
+
+
+
+
+
+// Object's constructor.
+
+CMotionVehicle::CMotionVehicle(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ int i;
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ m_wheelTurn[i] = 0.0f;
+ }
+ for ( i=0 ; i<3 ; i++ )
+ {
+ m_flyPaw[i] = 0.0f;
+ }
+ m_posTrackLeft = 0.0f;
+ m_posTrackRight = 0.0f;
+ m_partiReactor = -1;
+ m_armTimeAbs = 1000.0f;
+ m_armMember = 1000.0f;
+ m_canonTime = 0.0f;
+ m_lastTimeCanon = 0.0f;
+ m_wheelLastPos = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_wheelLastAngle = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_posKey = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_bFlyFix = false;
+
+ m_bTraceDown = false;
+ m_traceColor = 1; // black
+ m_traceWidth = 0.5f;
+}
+
+// Object's destructor.
+
+CMotionVehicle::~CMotionVehicle()
+{
+}
+
+
+// Removes an object.
+
+void CMotionVehicle::DeleteObject(bool bAll)
+{
+ if ( m_partiReactor != -1 )
+ {
+ m_particule->DeleteParticule(m_partiReactor);
+ m_partiReactor = -1;
+ }
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+bool CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ CObject* pPower;
+ int rank, i, j, parent;
+ D3DCOLORVALUE color;
+ char name[50];
+
+ if ( m_engine->RetRestCreate() < 1+5+18+1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates the main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs )
+ {
+ pModFile->ReadModel("objects\\lem1f.mod");
+ }
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts )
+ {
+ pModFile->ReadModel("objects\\lem1t.mod");
+ }
+ if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEws )
+ {
+ if ( m_object->RetTrainer() )
+ {
+ pModFile->ReadModel("objects\\lem1wt.mod");
+ }
+ else
+ {
+ pModFile->ReadModel("objects\\lem1w.mod");
+ }
+ }
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEis )
+ {
+ pModFile->ReadModel("objects\\lem1i.mod");
+ }
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ pModFile->ReadModel("objects\\roller1.mod");
+ }
+ if ( type == OBJECT_MOBILEsa )
+ {
+ pModFile->ReadModel("objects\\subm1.mod");
+ }
+ if ( type == OBJECT_MOBILEtg )
+ {
+ pModFile->ReadModel("objects\\target.mod");
+ }
+ if ( type == OBJECT_MOBILEwt )
+ {
+ pModFile->ReadModel("objects\\trainerw.mod");
+ }
+ if ( type == OBJECT_MOBILEft )
+ {
+ pModFile->ReadModel("objects\\trainerf.mod");
+ }
+ if ( type == OBJECT_MOBILEtt )
+ {
+ pModFile->ReadModel("objects\\trainert.mod");
+ }
+ if ( type == OBJECT_MOBILEit )
+ {
+ pModFile->ReadModel("objects\\traineri.mod");
+ }
+ if ( type == OBJECT_MOBILEdr )
+ {
+ pModFile->ReadModel("objects\\drawer1.mod");
+ }
+ if ( type == OBJECT_APOLLO2 )
+ {
+ pModFile->ReadModel("objects\\apolloj1.mod");
+ }
+ pModFile->CreateEngineObject(rank);
+
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have a obligatory collision
+ // with a sphere of center (0, y, 0) (see GetCrashSphere).
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 6.5f, SOUND_BOUMm, 0.45f);
+ m_object->SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 7.0f);
+ }
+ else if ( type == OBJECT_MOBILEsa )
+ {
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 4.5f, SOUND_BOUMm, 0.45f);
+ m_object->SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f);
+ }
+ else if ( type == OBJECT_MOBILEdr )
+ {
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ m_object->SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 7.0f);
+ }
+ else if ( type == OBJECT_APOLLO2 )
+ {
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ }
+ else
+ {
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 4.5f, SOUND_BOUMm, 0.45f);
+ m_object->SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 6.0f);
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia )
+ {
+ // Creates the arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\lem2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
+ m_object->SetAngleZ(1, ARM_NEUTRAL_ANGLE1);
+
+ // Creates the forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\lem3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(5.0f, 0.0f, 0.0f));
+ m_object->SetAngleZ(2, ARM_NEUTRAL_ANGLE2);
+
+ // Creates the hand.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\lem4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(3.5f, 0.0f, 0.0f));
+ m_object->SetAngleZ(3, ARM_NEUTRAL_ANGLE3);
+ m_object->SetAngleX(3, Math::PI/2.0f);
+
+ // Creates the close clamp.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 3);
+ pModFile->ReadModel("objects\\lem5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, Math::Vector(1.5f, 0.0f, 0.0f));
+ m_object->SetAngleZ(4, -Math::PI*0.10f);
+
+ // Creates the remote clamp.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 3);
+ pModFile->ReadModel("objects\\lem6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, Math::Vector(1.5f, 0.0f, 0.0f));
+ m_object->SetAngleZ(5, Math::PI*0.10f);
+ }
+
+ if ( type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis )
+ {
+ // Creates the arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\lem2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
+ m_object->SetAngleZ(1, 110.0f*Math::PI/180.0f);
+
+ // Creates the forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\lem3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(5.0f, 0.0f, 0.0f));
+ m_object->SetAngleZ(2, -110.0f*Math::PI/180.0f);
+
+ // Creates the sensor.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\lem4s.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(3.5f, 0.0f, 0.0f));
+ m_object->SetAngleZ(3, -65.0f*Math::PI/180.0f);
+ }
+
+ if ( type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic )
+ {
+ // Creates the cannon.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\canon.mod");
+ pModFile->CreateEngineObject(rank);
+//? m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
+ m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
+ m_object->SetAngleZ(1, 0.0f);
+ }
+
+ if ( type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii )
+ {
+ // Creates the insect cannon.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\canoni1.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
+ m_object->SetAngleZ(1, 0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\canoni2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(0.0f, 2.5f, 0.0f));
+ m_object->SetAngleZ(2, 0.0f);
+ }
+
+ if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEwt )
+ {
+ // Creates the right-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(-3.0f, 1.0f, -3.0f));
+
+ // Creates the left-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(-3.0f, 1.0f, 3.0f));
+ m_object->SetAngleY(7, Math::PI);
+
+ // Creates the right-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(2.0f, 1.0f, -3.0f));
+
+ // Creates the left-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, Math::Vector(2.0f, 1.0f, 3.0f));
+ m_object->SetAngleY(9, Math::PI);
+ }
+
+ if ( type == OBJECT_MOBILEtg )
+ {
+ // Creates the right-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(-2.0f, 1.0f, -3.0f));
+
+ // Creates the left-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(-2.0f, 1.0f, 3.0f));
+ m_object->SetAngleY(7, Math::PI);
+
+ // Creates the right-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(3.0f, 1.0f, -3.0f));
+
+ // Creates the left-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, Math::Vector(3.0f, 1.0f, 3.0f));
+ m_object->SetAngleY(9, Math::PI);
+ }
+
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts ) // caterpillars?
+ {
+ // Creates the right caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\lem2t.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(0.0f, 2.0f, -3.0f));
+
+ // Creates the left caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\lem3t.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, 2.0f, 3.0f));
+ }
+
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ) // large caterpillars?
+ {
+ // Creates the right caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\roller2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(0.0f, 2.0f, -3.0f));
+
+ // Creates the left caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\roller3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, 2.0f, 3.0f));
+ }
+
+ if ( type == OBJECT_MOBILEsa ) // underwater caterpillars?
+ {
+ // Creates the right caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\subm4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(0.0f, 1.0f, -3.0f));
+
+ // Creates the left caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\subm5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, 1.0f, 3.0f));
+ }
+
+ if ( type == OBJECT_MOBILEdr ) // caterpillars?
+ {
+ // Creates the right caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\drawer2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(0.0f, 1.0f, -3.0f));
+
+ // Creates the left caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\drawer3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, 1.0f, 3.0f));
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEft ) // flying?
+ {
+ // Creates the front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\lem2f.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(1.7f, 3.0f, 0.0f));
+
+ // Creates the right-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\lem2f.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(-1.8f, 3.0f, -1.5f));
+ m_object->SetAngleY(7, 120.0f*Math::PI/180.0f);
+
+ // Creates the left-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\lem2f.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(-1.8f, 3.0f, 1.5f));
+ m_object->SetAngleY(8, -120.0f*Math::PI/180.0f);
+ }
+
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILEii ) // insect legs?
+ {
+ float table[] =
+ {
+ // x y z
+ -1.5f, 1.2f, -0.7f, // back leg
+ 0.0f, 0.0f, -1.0f,
+ 0.0f, 0.0f, -2.0f,
+
+ 0.0f, 1.2f, -0.9f, // middle leg
+ 0.0f, 0.0f, -1.0f,
+ 0.0f, 0.0f, -2.0f,
+
+ 1.5f, 1.2f, -0.7f, // front leg
+ 0.0f, 0.0f, -1.0f,
+ 0.0f, 0.0f, -2.0f,
+ };
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ for ( j=0 ; j<3 ; j++ )
+ {
+ sprintf(name, "objects\\ant%d.mod", j+4); // 4..6
+
+ // Creates the right leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6+i*3+j, rank);
+ if ( j == 0 ) parent = 0;
+ else parent = 6+i*3+j-1;
+ m_object->SetObjectParent(6+i*3+j, parent);
+ pModFile->ReadModel(name);
+ pModFile->CreateEngineObject(rank);
+ pos.x = table[i*9+j*3+0];
+ pos.y = table[i*9+j*3+1];
+ pos.z = table[i*9+j*3+2];
+ m_object->SetPosition(6+i*3+j, pos);
+
+ // Creates the left leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(15+i*3+j, rank);
+ if ( j == 0 ) parent = 0;
+ else parent = 15+i*3+j-1;
+ m_object->SetObjectParent(15+i*3+j, parent);
+ pModFile->ReadModel(name);
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ pos.x = table[i*9+j*3+0];
+ pos.y = table[i*9+j*3+1];
+ pos.z = -table[i*9+j*3+2];
+ m_object->SetPosition(15+i*3+j, pos);
+ }
+ }
+ }
+
+ if ( type == OBJECT_MOBILErt )
+ {
+ // Creates the holder.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\roller2t.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(0.0f, 0.0f, 0.0f));
+ m_object->SetAngleZ(1, 0.0f);
+
+ // Creates the pestle.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\roller3t.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(9.0f, 4.0f, 0.0f));
+ m_object->SetAngleZ(2, 0.0f);
+ }
+
+ if ( type == OBJECT_MOBILErc )
+ {
+ // Creates the holder.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\roller2c.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(3.0f, 4.6f, 0.0f));
+ m_object->SetAngleZ(1, Math::PI/8.0f);
+
+ // Creates the cannon.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\roller3p.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(7.0f, 6.5f, 0.0f));
+ m_object->SetAngleZ(2, 0.0f);
+ }
+
+ if ( type == OBJECT_MOBILErr )
+ {
+ // Creates the holder.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\recover1.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(2.0f, 5.0f, 0.0f));
+
+ // Creates the right arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\recover2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(0.1f, 0.0f, -5.0f));
+ m_object->SetAngleZ(2, 126.0f*Math::PI/180.0f);
+
+ // Creates the right forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\recover3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(5.0f, 0.0f, -0.5f));
+ m_object->SetAngleZ(3, -144.0f*Math::PI/180.0f);
+
+ // Creates the left arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 1);
+ pModFile->ReadModel("objects\\recover2.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, Math::Vector(0.1f, 0.0f, 5.0f));
+ m_object->SetAngleZ(4, 126.0f*Math::PI/180.0f);
+
+ // Creates the left forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 4);
+ pModFile->ReadModel("objects\\recover3.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, Math::Vector(5.0f, 0.0f, 0.5f));
+ m_object->SetAngleZ(5, -144.0f*Math::PI/180.0f);
+ }
+
+ if ( type == OBJECT_MOBILErs )
+ {
+ // Creates the holder.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\roller2s.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(0.0f, 0.0f, 0.0f));
+ m_object->SetAngleZ(1, 0.0f);
+
+ // Creates the intermediate piston.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\roller3s.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(7.0f, 4.5f, 0.0f));
+ m_object->SetAngleZ(2, 0.0f);
+
+ // Creates the piston with the sphere.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\roller4s.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(0.0f, 1.0f, 0.0f));
+ m_object->SetAngleZ(3, 0.0f);
+ }
+
+ if ( type == OBJECT_MOBILEsa )
+ {
+ // Creates the holder.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\subm2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(4.2f, 3.0f, 0.0f));
+
+ // Creates the right tong.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\subm3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(0.5f, 0.0f, -1.5f));
+
+ // Creates the left tong.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 1);
+ pModFile->ReadModel("objects\\subm3.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(0.5f, 0.0f, 1.5f));
+ }
+
+ if ( type == OBJECT_MOBILEdr )
+ {
+ // Creates the carousel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\drawer4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(-3.0f, 3.0f, 0.0f));
+
+ // Creates the key.
+ if ( m_object->RetToy() )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\drawer5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_posKey = Math::Vector(3.0f, 5.7f, 0.0f);
+ m_object->SetPosition(2, m_posKey);
+ m_object->SetAngleY(2, 90.0f*Math::PI/180.0f);
+ }
+
+ // Creates pencils.
+ for ( i=0 ; i<8 ; i++ )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10+i, rank);
+ m_object->SetObjectParent(10+i, 1);
+ sprintf(name, "objects\\drawer%d.mod", 10+i);
+ pModFile->ReadModel(name);
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10+i, Math::Vector(0.0f, 0.0f, 0.0f));
+ m_object->SetAngleY(10+i, 45.0f*Math::PI/180.0f*i);
+ }
+ }
+
+ if ( type == OBJECT_MOBILEwt )
+ {
+ // Creates the key.
+ if ( m_object->RetToy() )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\drawer5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_posKey = Math::Vector(0.2f, 4.1f, 0.0f);
+ m_object->SetPosition(2, m_posKey);
+ m_object->SetAngleY(2, 90.0f*Math::PI/180.0f);
+ }
+ }
+
+ if ( type == OBJECT_APOLLO2 )
+ {
+ // Creates the accessories.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\apolloj2.mod"); // antenna
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(5.5f, 8.8f, 2.0f));
+ m_object->SetAngleY(1, -120.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(1, 45.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\apolloj3.mod"); // camera
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(5.5f, 2.8f, -2.0f));
+ m_object->SetAngleY(2, 30.0f*Math::PI/180.0f);
+
+ // Creates the wheels.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(-5.75f, 1.65f, -5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(-5.75f, 1.65f, 5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(5.75f, 1.65f, -5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, Math::Vector(5.75f, 1.65f, 5.00f));
+
+ // Creates mud guards.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10, rank);
+ m_object->SetObjectParent(10, 0);
+ pModFile->ReadModel("objects\\apolloj6.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10, Math::Vector(-5.75f, 1.65f, -5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(11, rank);
+ m_object->SetObjectParent(11, 0);
+ pModFile->ReadModel("objects\\apolloj6.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(11, Math::Vector(-5.75f, 1.65f, 5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(12, rank);
+ m_object->SetObjectParent(12, 0);
+ pModFile->ReadModel("objects\\apolloj5.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(12, Math::Vector(5.75f, 1.65f, -5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(13, rank);
+ m_object->SetObjectParent(13, 0);
+ pModFile->ReadModel("objects\\apolloj5.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(13, Math::Vector(5.75f, 1.65f, 5.00f));
+ }
+
+#if 1
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ m_object->CreateShadowCircle(6.0f, 1.0f);
+ }
+ else if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEsa )
+ {
+ m_object->CreateShadowCircle(5.0f, 1.0f);
+ }
+ else if ( type == OBJECT_MOBILEdr )
+ {
+ m_object->CreateShadowCircle(4.5f, 1.0f);
+ }
+ else if ( type == OBJECT_APOLLO2 )
+ {
+ m_object->CreateShadowCircle(7.0f, 0.8f);
+ }
+ else
+ {
+ m_object->CreateShadowCircle(4.0f, 1.0f);
+ }
+#else
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ m_object->CreateShadowCircle(6.0f, 1.0f, D3DSHADOWTANK);
+ }
+ else if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts )
+ {
+ m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWTANK);
+ }
+ else if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs )
+ {
+ m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWFLY);
+ }
+ else if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEws )
+ {
+ m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWWHEEL);
+ }
+ else if ( type == OBJECT_APOLLO2 )
+ {
+ m_object->CreateShadowCircle(6.0f, 0.8f);
+ }
+ else
+ {
+ m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWNORM);
+ }
+#endif
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEft ) // flying?
+ {
+//? color.r = 0.5f-1.0f;
+//? color.g = 0.2f-1.0f;
+//? color.b = 0.0f-1.0f; // orange
+//? color.r = 0.8f;
+//? color.g = 0.6f;
+//? color.b = 0.0f; // yellow-orange
+ color.r = 0.0f;
+ color.g = 0.4f;
+ color.b = 0.8f; // blue
+ color.a = 0.0f;
+ m_object->CreateShadowLight(50.0f, color);
+ }
+
+ CreatePhysics(type);
+ m_object->SetFloorHeight(0.0f);
+
+ if ( power > 0.0f &&
+ type != OBJECT_MOBILEdr &&
+ type != OBJECT_APOLLO2 )
+ {
+ color.r = 1.0f;
+ color.g = 1.0f;
+ color.b = 0.0f; // yellow
+ color.a = 0.0f;
+ m_object->CreateEffectLight(20.0f, color);
+
+ // Creates the battery.
+ pPower = new CObject(m_iMan);
+ pPower->SetType(power<=1.0f?OBJECT_POWER:OBJECT_ATOMIC);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ pPower->SetObjectRank(0, rank);
+
+ if ( power <= 1.0f ) pModFile->ReadModel("objects\\power.mod");
+ else pModFile->ReadModel("objects\\atomic.mod");
+ pModFile->CreateEngineObject(rank);
+
+ pPower->SetPosition(0, m_object->RetCharacter()->posPower);
+ pPower->CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ pPower->SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.5f);
+
+ pPower->SetTruck(m_object);
+ m_object->SetPower(pPower);
+
+ if ( power <= 1.0f ) pPower->SetEnergy(power);
+ else pPower->SetEnergy(power/100.0f);
+ }
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); //to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+// Creates the physics of the object.
+
+void CMotionVehicle::CreatePhysics(ObjectType type)
+{
+ Character* character;
+
+ character = m_object->RetCharacter();
+
+ if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEwt ) // wheels?
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 3.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.0f;
+ character->wheelRight = 4.0f;
+ character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 20.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 30.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 8.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 8.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 12.0f);
+ }
+
+ if ( type == OBJECT_MOBILEtg )
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 4.0f;
+ character->wheelBack = 3.0f;
+ character->wheelLeft = 4.0f;
+ character->wheelRight = 4.0f;
+ character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 20.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 15.0f);
+ }
+
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts ) // caterpillars?
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.8f;
+ character->wheelRight = 4.8f;
+ character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 8.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 8.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 6.0f);
+ }
+
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEis ) // legs?
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 5.0f;
+ character->wheelRight = 5.0f;
+ character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 8.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 10.0f);
+//? m_physics->SetLinMotionX(MO_TERFORCE, 15.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 15.0f);
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEft ) // flying?
+ {
+ m_physics->SetType(TYPE_FLYING);
+
+ character->wheelFront = 5.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.5f;
+ character->wheelRight = 4.5f;
+ character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 50.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+ m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
+ m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.4f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.4f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 2.0f);
+ }
+
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ) // large caterpillars?
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 5.0f;
+ character->wheelBack = 5.0f;
+ character->wheelLeft = 6.0f;
+ character->wheelRight = 6.0f;
+ character->posPower = Math::Vector(-5.8f, 4.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 5.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 5.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.3f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.3f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 4.0f);
+ }
+
+ if ( type == OBJECT_MOBILEsa )
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.0f;
+ character->wheelRight = 4.0f;
+ character->posPower = Math::Vector(-5.0f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 5.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 5.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 10.0f);
+ }
+
+ if ( type == OBJECT_MOBILEdr )
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.0f;
+ character->wheelRight = 4.0f;
+ character->posPower = Math::Vector(-5.0f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 5.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 5.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 10.0f);
+ }
+
+ if ( type == OBJECT_APOLLO2 ) // jeep?
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 6.0f;
+ character->wheelBack = 6.0f;
+ character->wheelLeft = 5.0f;
+ character->wheelRight = 5.0f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 2.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 2.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 30.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.4f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.4f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 4.0f);
+ }
+}
+
+
+// Management of an event.
+
+bool CMotionVehicle::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+ }
+
+ return true;
+}
+
+// Management of an event.
+
+bool CMotionVehicle::EventFrame(const Event &event)
+{
+ Math::Matrix* mat;
+ Character* character;
+ Math::Vector pos, angle, floor;
+ ObjectType type;
+ float s, a, speedBL, speedBR, speedFL, speedFR, h, a1, a2;
+ float back, front, dist, radius, limit[2];
+
+ if ( m_engine->RetPause() ) return true;
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
+
+ type = m_object->RetType();
+
+ if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_APOLLO2 ) // wheels?
+ {
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.0f;
+ a = m_physics->RetCirMotionY(MO_MOTSPEED)*3.0f;
+
+ if ( type == OBJECT_APOLLO2 ) s *= 0.5f;
+
+ speedBR = -s+a;
+ speedBL = s+a;
+ speedFR = -s+a;
+ speedFL = s+a;
+
+ m_object->SetAngleZ(6, m_object->RetAngleZ(6)+event.rTime*speedBR); // turning the wheels
+ m_object->SetAngleZ(7, m_object->RetAngleZ(7)+event.rTime*speedBL);
+ m_object->SetAngleZ(8, m_object->RetAngleZ(8)+event.rTime*speedFR);
+ m_object->SetAngleZ(9, m_object->RetAngleZ(9)+event.rTime*speedFL);
+
+ if ( s > 0.0f )
+ {
+ m_wheelTurn[0] = -a*0.05f;
+ m_wheelTurn[1] = -a*0.05f+Math::PI;
+ m_wheelTurn[2] = a*0.05f;
+ m_wheelTurn[3] = a*0.05f+Math::PI;
+ }
+ else if ( s < 0.0f )
+ {
+ m_wheelTurn[0] = a*0.05f;
+ m_wheelTurn[1] = a*0.05f+Math::PI;
+ m_wheelTurn[2] = -a*0.05f;
+ m_wheelTurn[3] = -a*0.05f+Math::PI;
+ }
+ else
+ {
+ m_wheelTurn[0] = fabs(a)*0.05f;
+ m_wheelTurn[1] = -fabs(a)*0.05f+Math::PI;
+ m_wheelTurn[2] = -fabs(a)*0.05f;
+ m_wheelTurn[3] = fabs(a)*0.05f+Math::PI;
+ }
+ m_object->SetAngleY(6, m_object->RetAngleY(6)+(m_wheelTurn[0]-m_object->RetAngleY(6))*event.rTime*8.0f);
+ m_object->SetAngleY(7, m_object->RetAngleY(7)+(m_wheelTurn[1]-m_object->RetAngleY(7))*event.rTime*8.0f);
+ m_object->SetAngleY(8, m_object->RetAngleY(8)+(m_wheelTurn[2]-m_object->RetAngleY(8))*event.rTime*8.0f);
+ m_object->SetAngleY(9, m_object->RetAngleY(9)+(m_wheelTurn[3]-m_object->RetAngleY(9))*event.rTime*8.0f);
+
+ if ( type == OBJECT_APOLLO2 )
+ {
+ m_object->SetAngleY(10, m_object->RetAngleY(6)+(m_wheelTurn[0]-m_object->RetAngleY(6))*event.rTime*8.0f);
+ m_object->SetAngleY(11, m_object->RetAngleY(7)+(m_wheelTurn[1]-m_object->RetAngleY(7))*event.rTime*8.0f+Math::PI);
+ m_object->SetAngleY(12, m_object->RetAngleY(8)+(m_wheelTurn[2]-m_object->RetAngleY(8))*event.rTime*8.0f);
+ m_object->SetAngleY(13, m_object->RetAngleY(9)+(m_wheelTurn[3]-m_object->RetAngleY(9))*event.rTime*8.0f+Math::PI);
+ }
+
+ pos = m_object->RetPosition(0);
+ angle = m_object->RetAngle(0);
+ if ( pos.x != m_wheelLastPos.x ||
+ pos.y != m_wheelLastPos.y ||
+ pos.z != m_wheelLastPos.z ||
+ angle.x != m_wheelLastAngle.x ||
+ angle.y != m_wheelLastAngle.y ||
+ angle.z != m_wheelLastAngle.z )
+ {
+ m_wheelLastPos = pos;
+ m_wheelLastAngle = angle;
+
+ if ( type == OBJECT_MOBILEtg )
+ {
+ back = -2.0f; // back wheels position
+ front = 3.0f; // front wheels position
+ dist = 3.0f; // distancing wheels Z
+ radius = 1.0f;
+ }
+ else if ( type == OBJECT_APOLLO2 )
+ {
+ back = -5.75f; // back wheels position
+ front = 5.75f; // front wheels position
+ dist = 5.00f; // distancing wheels Z
+ radius = 1.65f;
+ }
+ else
+ {
+ back = -3.0f; // back wheels position
+ front = 2.0f; // front wheels position
+ dist = 3.0f; // distancing wheels Z
+ radius = 1.0f;
+ }
+
+ if ( Math::Distance(pos, m_engine->RetEyePt()) < 50.0f ) // suspension?
+ {
+ character = m_object->RetCharacter();
+ mat = m_object->RetWorldMatrix(0);
+
+ pos.x = -character->wheelBack; // right back wheel
+ pos.z = -character->wheelRight;
+ pos.y = 0.0f;
+ pos = Math::Transform(*mat, pos);
+ h = m_terrain->RetFloorHeight(pos);
+ if ( h > 0.5f ) h = 0.5f;
+ if ( h < -0.5f ) h = -0.5f;
+ pos.x = back;
+ pos.y = radius-h;
+ pos.z = -dist;
+ m_object->SetPosition(6, pos);
+ if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(10, pos);
+
+ pos.x = -character->wheelBack; // left back wheel
+ pos.z = character->wheelLeft;
+ pos.y = 0.0f;
+ pos = Math::Transform(*mat, pos);
+ h = m_terrain->RetFloorHeight(pos);
+ if ( h > 0.5f ) h = 0.5f;
+ if ( h < -0.5f ) h = -0.5f;
+ pos.x = back;
+ pos.y = radius-h;
+ pos.z = dist;
+ m_object->SetPosition(7, pos);
+ if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(11, pos);
+
+ pos.x = character->wheelFront; // right front wheel
+ pos.z = -character->wheelRight;
+ pos.y = 0.0f;
+ pos = Math::Transform(*mat, pos);
+ h = m_terrain->RetFloorHeight(pos);
+ if ( h > 0.5f ) h = 0.5f;
+ if ( h < -0.5f ) h = -0.5f;
+ pos.x = front;
+ pos.y = radius-h;
+ pos.z = -dist;
+ m_object->SetPosition(8, pos);
+ if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(12, pos);
+
+ pos.x = character->wheelFront; // left front wheel
+ pos.z = character->wheelLeft;
+ pos.y = 0.0f;
+ pos = Math::Transform(*mat, pos);
+ h = m_terrain->RetFloorHeight(pos);
+ if ( h > 0.5f ) h = 0.5f;
+ if ( h < -0.5f ) h = -0.5f;
+ pos.x = front;
+ pos.y = radius-h;
+ pos.z = dist;
+ m_object->SetPosition(9, pos);
+ if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(13, pos);
+ }
+ else
+ {
+ m_object->SetPosition(6, Math::Vector(back, radius, -dist));
+ m_object->SetPosition(7, Math::Vector(back, radius, dist));
+ m_object->SetPosition(8, Math::Vector(front, radius, -dist));
+ m_object->SetPosition(9, Math::Vector(front, radius, dist));
+
+ if ( type == OBJECT_APOLLO2 )
+ {
+ m_object->SetPosition(10, Math::Vector(back, radius, -dist));
+ m_object->SetPosition(11, Math::Vector(back, radius, dist));
+ m_object->SetPosition(12, Math::Vector(front, radius, -dist));
+ m_object->SetPosition(13, Math::Vector(front, radius, dist));
+ }
+ }
+ }
+ }
+
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEdr ) // caterpillars?
+ {
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.7f;
+ a = m_physics->RetCirMotionY(MO_MOTSPEED)*2.5f;
+
+ m_posTrackLeft += event.rTime*(s+a);
+ m_posTrackRight += event.rTime*(s-a);
+
+ UpdateTrackMapping(m_posTrackLeft, m_posTrackRight, type);
+
+ pos = m_object->RetPosition(0);
+ angle = m_object->RetAngle(0);
+ if ( pos.x != m_wheelLastPos.x ||
+ pos.y != m_wheelLastPos.y ||
+ pos.z != m_wheelLastPos.z ||
+ angle.x != m_wheelLastAngle.x ||
+ angle.y != m_wheelLastAngle.y ||
+ angle.z != m_wheelLastAngle.z )
+ {
+ m_wheelLastPos = pos;
+ m_wheelLastAngle = angle;
+
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts )
+ {
+ limit[0] = 8.0f*Math::PI/180.0f;
+ limit[1] = -12.0f*Math::PI/180.0f;
+ }
+ else if ( type == OBJECT_MOBILEsa )
+ {
+ limit[0] = 15.0f*Math::PI/180.0f;
+ limit[1] = -15.0f*Math::PI/180.0f;
+ }
+ else if ( type == OBJECT_MOBILEdr )
+ {
+ limit[0] = 10.0f*Math::PI/180.0f;
+ limit[1] = -10.0f*Math::PI/180.0f;
+ }
+ else
+ {
+ limit[0] = 15.0f*Math::PI/180.0f;
+ limit[1] = -10.0f*Math::PI/180.0f;
+ }
+
+ if ( Math::Distance(pos, m_engine->RetEyePt()) < 50.0f ) // suspension?
+ {
+ character = m_object->RetCharacter();
+ mat = m_object->RetWorldMatrix(0);
+
+ pos.x = character->wheelFront; // right front wheel
+ pos.z = -character->wheelRight;
+ pos.y = 0.0f;
+ pos = Transform(*mat, pos);
+ a1 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelFront);
+
+ pos.x = -character->wheelBack; // right back wheel
+ pos.z = -character->wheelRight;
+ pos.y = 0.0f;
+ pos = Transform(*mat, pos);
+ a2 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelBack);
+
+ a = (a2-a1)/2.0f;
+ if ( a > limit[0] ) a = limit[0];
+ if ( a < limit[1] ) a = limit[1];
+ m_object->SetAngleZ(6, a);
+
+ pos.x = character->wheelFront; // left front wheel
+ pos.z = character->wheelLeft;
+ pos.y = 0.0f;
+ pos = Transform(*mat, pos);
+ a1 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelFront);
+
+ pos.x = -character->wheelBack; // left back wheel
+ pos.z = character->wheelLeft;
+ pos.y = 0.0f;
+ pos = Transform(*mat, pos);
+ a2 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelBack);
+
+ a = (a2-a1)/2.0f;
+ if ( a > limit[0] ) a = limit[0];
+ if ( a < limit[1] ) a = limit[1];
+ m_object->SetAngleZ(7, a);
+ }
+ else
+ {
+ m_object->SetAngleZ(6, 0.0f);
+ m_object->SetAngleZ(7, 0.0f);
+ }
+ }
+ }
+
+ if ( type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEdr ) // toy is key?
+ {
+ pos = m_posKey;
+ if ( m_object->RetSelect() &&
+ m_camera->RetType() == CAMERA_ONBOARD )
+ {
+ pos.y += 10.0f; // out of sight!
+ }
+ m_object->SetPosition(2, pos);
+
+ s = -fabs(m_physics->RetLinMotionX(MO_MOTSPEED)*0.1f);
+ s += -fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*1.5f);
+ m_object->SetAngleY(2, m_object->RetAngleY(2)+event.rTime*s); // turns the key
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEft ) // flying?
+ {
+ EventFrameFly(event);
+ }
+
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEis ) // legs?
+ {
+ EventFrameInsect(event);
+ }
+
+ if ( type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEii ) // insect cannon?
+ {
+ EventFrameCanoni(event);
+ }
+
+ return true;
+}
+
+// Managing an event for a flying robot.
+
+bool CMotionVehicle::EventFrameFly(const Event &event)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, angle, paw[3];
+ float hope[3], actual, final, h, a;
+ int i;
+
+ pos = m_object->RetPosition(0);
+ angle = m_object->RetAngle(0);
+ if ( m_bFlyFix &&
+ pos.x == m_wheelLastPos.x &&
+ pos.y == m_wheelLastPos.y &&
+ pos.z == m_wheelLastPos.z &&
+ angle.x == m_wheelLastAngle.x &&
+ angle.y == m_wheelLastAngle.y &&
+ angle.z == m_wheelLastAngle.z ) return true;
+
+ m_wheelLastPos = pos;
+ m_wheelLastAngle = angle;
+
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ mat = m_object->RetWorldMatrix(0);
+ paw[0] = Transform(*mat, Math::Vector( 4.2f, 0.0f, 0.0f)); // front
+ paw[1] = Transform(*mat, Math::Vector(-3.0f, 0.0f, -3.7f)); // right back
+ paw[2] = Transform(*mat, Math::Vector(-3.0f, 0.0f, 3.7f)); // left back
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ h = m_terrain->RetFloorHeight(paw[i]);
+ a = -atanf(h*0.5f);
+ if ( a > Math::PI*0.2f ) a = Math::PI*0.2f;
+ if ( a < -Math::PI*0.2f ) a = -Math::PI*0.2f;
+ hope[i] = a;
+ }
+ }
+ else // in flight?
+ {
+ hope[0] = 0.0f; // front
+ hope[1] = 0.0f; // right back
+ hope[2] = 0.0f; // left back
+ }
+
+ m_bFlyFix = true;
+ for ( i=0 ; i<3 ; i++ )
+ {
+ actual = m_object->RetAngleZ(6+i);
+ final = Math::Smooth(actual, hope[i], event.rTime*5.0f);
+ if ( final != actual )
+ {
+ m_bFlyFix = false; // it is moving
+ m_object->SetAngleZ(6+i, final);
+ }
+ }
+
+ return true;
+}
+
+// Event management for insect legs.
+
+bool CMotionVehicle::EventFrameInsect(const Event &event)
+{
+ Math::Vector dir;
+ float s, a, prog, time;
+ int i, st, nd, action;
+ bool bStop, bOnBoard;
+
+ static int table[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 60,25,0, 60,0,0, 60,-25,0, // t0: thighs 1..4
+ -35,0,0, -35,0,0, -35,0,0, // t0: legs 1..4
+ -65,0,0, -65,0,0, -65,0,0, // t0: feet 1..4
+ // on the ground:
+ 30,10,0, 30,-15,0, 30,-40,0, // t1: thighs 1..4
+ -45,0,0, -45,0,0, -45,0,0, // t1: legs 1..4
+ -20,0,0, -20,0,0, -20,0,0, // t1: feet 1..4
+ // on the ground back:
+ 35,40,0, 40,15,0, 40,-10,0, // t2: thighs 1..4
+ -35,0,0, -35,0,0, -35,0,0, // t2: legs 1..4
+ -50,0,0, -65,0,0, -65,0,0, // t2: feet 1..4
+ // stop:
+ 35,35,0, 40,10,0, 40,-15,0, // s0: thighs 1..4
+ -35,0,0, -35,0,0, -35,0,0, // s0: legs 1..4
+ -50,0,0, -65,0,0, -65,0,0, // s0: feet 1..4
+ };
+
+ bOnBoard = false;
+ if ( m_object->RetSelect() &&
+ m_camera->RetType() == CAMERA_ONBOARD )
+ {
+ bOnBoard = true;
+ }
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
+ a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f);
+
+ if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armMember += (s+a)*event.rTime*0.15f;
+
+ bStop = ( a == 0.0f && s == 0.0f ); // stop?
+
+ action = 0; // walking
+ if ( s == 0.0f && a == 0.0f )
+ {
+ action = 3; // stop
+ }
+
+ if ( bStop )
+ {
+ prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
+ a = Math::Mod(m_armMember, 1.0f);
+ a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly
+ m_armMember += a;
+ }
+
+ if ( m_object->RetRuin() ) // burn or explode?
+ {
+ action = 3;
+ }
+
+ for ( i=0 ; i<6 ; i++ ) // the six legs
+ {
+ if ( action != 0 ) // special action in progress?
+ {
+ st = 3*3*3*action + (i%3)*3;
+ nd = st;
+ time = event.rTime*5.0f;
+ }
+ else
+ {
+ if ( i < 3 ) prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
+ else prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
+ if ( prog < 0.33f ) // t0..t1 ?
+ {
+ prog = prog/0.33f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.67f ) // t1..t2 ?
+ {
+ prog = (prog-0.33f)/0.33f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.67f)/0.33f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ st = 3*3*3*action + st*3*3*3 + (i%3)*3;
+ nd = 3*3*3*action + nd*3*3*3 + (i%3)*3;
+
+ // Less and less soft ...
+ time = event.rTime*20.0f;
+ }
+
+ if ( i < 3 ) // right leg (1..3) ?
+ {
+ m_object->SetAngleX(6+3*i+0, Math::Smooth(m_object->RetAngleX(6+3*i+0), Math::PropAngle(table[st+ 0], table[nd+ 0], prog), time));
+ m_object->SetAngleY(6+3*i+0, Math::Smooth(m_object->RetAngleY(6+3*i+0), Math::PropAngle(table[st+ 1], table[nd+ 1], prog), time));
+ m_object->SetAngleZ(6+3*i+0, Math::Smooth(m_object->RetAngleZ(6+3*i+0), Math::PropAngle(table[st+ 2], table[nd+ 2], prog), time));
+ m_object->SetAngleX(6+3*i+1, Math::Smooth(m_object->RetAngleX(6+3*i+1), Math::PropAngle(table[st+ 9], table[nd+ 9], prog), time));
+ m_object->SetAngleY(6+3*i+1, Math::Smooth(m_object->RetAngleY(6+3*i+1), Math::PropAngle(table[st+10], table[nd+10], prog), time));
+ m_object->SetAngleZ(6+3*i+1, Math::Smooth(m_object->RetAngleZ(6+3*i+1), Math::PropAngle(table[st+11], table[nd+11], prog), time));
+ m_object->SetAngleX(6+3*i+2, Math::Smooth(m_object->RetAngleX(6+3*i+2), Math::PropAngle(table[st+18], table[nd+18], prog), time));
+ m_object->SetAngleY(6+3*i+2, Math::Smooth(m_object->RetAngleY(6+3*i+2), Math::PropAngle(table[st+19], table[nd+19], prog), time));
+ m_object->SetAngleZ(6+3*i+2, Math::Smooth(m_object->RetAngleZ(6+3*i+2), Math::PropAngle(table[st+20], table[nd+20], prog), time));
+ }
+ else // left leg (4..6) ?
+ {
+ m_object->SetAngleX(6+3*i+0, Math::Smooth(m_object->RetAngleX(6+3*i+0), Math::PropAngle(-table[st+ 0], -table[nd+ 0], prog), time));
+ m_object->SetAngleY(6+3*i+0, Math::Smooth(m_object->RetAngleY(6+3*i+0), Math::PropAngle(-table[st+ 1], -table[nd+ 1], prog), time));
+ m_object->SetAngleZ(6+3*i+0, Math::Smooth(m_object->RetAngleZ(6+3*i+0), Math::PropAngle( table[st+ 2], table[nd+ 2], prog), time));
+ m_object->SetAngleX(6+3*i+1, Math::Smooth(m_object->RetAngleX(6+3*i+1), Math::PropAngle(-table[st+ 9], -table[nd+ 9], prog), time));
+ m_object->SetAngleY(6+3*i+1, Math::Smooth(m_object->RetAngleY(6+3*i+1), Math::PropAngle(-table[st+10], -table[nd+10], prog), time));
+ m_object->SetAngleZ(6+3*i+1, Math::Smooth(m_object->RetAngleZ(6+3*i+1), Math::PropAngle( table[st+11], table[nd+11], prog), time));
+ m_object->SetAngleX(6+3*i+2, Math::Smooth(m_object->RetAngleX(6+3*i+2), Math::PropAngle(-table[st+18], -table[nd+18], prog), time));
+ m_object->SetAngleY(6+3*i+2, Math::Smooth(m_object->RetAngleY(6+3*i+2), Math::PropAngle(-table[st+19], -table[nd+19], prog), time));
+ m_object->SetAngleZ(6+3*i+2, Math::Smooth(m_object->RetAngleZ(6+3*i+2), Math::PropAngle( table[st+20], table[nd+20], prog), time));
+ }
+ }
+
+ if ( bStop )
+ {
+ }
+ else
+ {
+ a = Math::Mod(m_armMember, 1.0f);
+ if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
+ else a = 3.0f-4.0f*a; // 1..-1
+ dir.x = sinf(a)*0.05f;
+
+ s = Math::Mod(m_armMember/2.0f, 1.0f);
+ if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
+ else s = 3.0f-4.0f*s; // 1..-1
+ dir.z = sinf(s)*0.1f;
+
+ dir.y = 0.0f;
+
+ if ( bOnBoard ) dir *= 0.6f;
+ SetInclinaison(dir);
+ }
+
+ return true;
+}
+
+// Event management for a insect cannon.
+
+bool CMotionVehicle::EventFrameCanoni(const Event &event)
+{
+ CObject* power;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float zoom, angle, energy, factor;
+ bool bOnBoard = false;
+
+ m_canonTime += event.rTime;
+
+ if ( m_object->RetSelect() &&
+ m_camera->RetType() == CAMERA_ONBOARD )
+ {
+ bOnBoard = true;
+ }
+
+ power = m_object->RetPower();
+ if ( power == 0 )
+ {
+ energy = 0.0f;
+ }
+ else
+ {
+ energy = power->RetEnergy();
+ }
+ if ( energy == 0.0f ) return true;
+
+ factor = 0.5f+energy*0.5f;
+ if ( bOnBoard ) factor *= 0.8f;
+
+ zoom = 1.3f+
+ sinf(m_canonTime*Math::PI*0.31f)*0.10f+
+ sinf(m_canonTime*Math::PI*0.52f)*0.08f+
+ sinf(m_canonTime*Math::PI*1.53f)*0.05f;
+ zoom *= factor;
+ m_object->SetZoomY(2, zoom);
+
+ zoom = 1.0f+
+ sinf(m_canonTime*Math::PI*0.27f)*0.07f+
+ sinf(m_canonTime*Math::PI*0.62f)*0.06f+
+ sinf(m_canonTime*Math::PI*1.73f)*0.03f;
+ zoom *= factor;
+ m_object->SetZoomZ(2, zoom);
+
+ angle = sinf(m_canonTime*1.0f)*0.10f+
+ sinf(m_canonTime*1.3f)*0.15f+
+ sinf(m_canonTime*2.7f)*0.05f;
+ m_object->SetAngleX(2, angle);
+
+#if 0
+ m_lastTimeCanon -= event.rTime;
+ if ( m_lastTimeCanon <= 0.0f )
+ {
+ m_lastTimeCanon = m_engine->ParticuleAdapt(0.5f+Math::Rand()*0.5f);
+
+ pos = m_object->RetPosition(0);
+ pos.y += 8.0f;
+ speed.y = 7.0f+Math::Rand()*3.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = 2.0f+Math::Rand()*2.0f;
+ if ( Math::Rand() < 0.5f ) speed.z = -speed.z;
+ mat = m_object->RetRotateMatrix(0);
+ speed = Transform(*mat, speed);
+ dim.x = Math::Rand()*0.1f+0.1f;
+ if ( bOnBoard ) dim.x *= 0.4f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIORGANIC2, 2.0f, 10.0f);
+ }
+#endif
+
+ return true;
+}
+
+
+// Updates the mapping of the texture of the caterpillars.
+
+void CMotionVehicle::UpdateTrackMapping(float left, float right, ObjectType type)
+{
+ D3DMATERIAL7 mat;
+ float limit[4];
+ int rRank, lRank, i;
+
+ ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
+ mat.diffuse.r = 1.0f;
+ mat.diffuse.g = 1.0f;
+ mat.diffuse.b = 1.0f; // white
+ mat.ambient.r = 0.5f;
+ mat.ambient.g = 0.5f;
+ mat.ambient.b = 0.5f;
+
+ rRank = m_object->RetObjectRank(6);
+ lRank = m_object->RetObjectRank(7);
+
+
+ if ( type == OBJECT_MOBILEdr )
+ {
+ limit[0] = 0.0f;
+ limit[1] = 1000000.0f;
+ limit[2] = limit[1];
+ limit[3] = m_engine->RetLimitLOD(1);
+
+ m_engine->TrackTextureMapping(rRank, mat, D3DSTATEPART1, "drawer.tga", "",
+ limit[0], limit[1], D3DMAPPINGX,
+ right, 1.0f, 8.0f, 192.0f, 256.0f);
+
+ m_engine->TrackTextureMapping(lRank, mat, D3DSTATEPART2, "drawer.tga", "",
+ limit[0], limit[1], D3DMAPPINGX,
+ left, 1.0f, 8.0f, 192.0f, 256.0f);
+ }
+ else
+ {
+ limit[0] = 0.0f;
+ limit[1] = m_engine->RetLimitLOD(0);
+ limit[2] = limit[1];
+ limit[3] = m_engine->RetLimitLOD(1);
+
+ for ( i=0 ; i<2 ; i++ )
+ {
+ m_engine->TrackTextureMapping(rRank, mat, D3DSTATEPART1, "lemt.tga", "",
+ limit[i*2+0], limit[i*2+1], D3DMAPPINGX,
+ right, 1.0f, 8.0f, 192.0f, 256.0f);
+
+ m_engine->TrackTextureMapping(lRank, mat, D3DSTATEPART2, "lemt.tga", "",
+ limit[i*2+0], limit[i*2+1], D3DMAPPINGX,
+ left, 1.0f, 8.0f, 192.0f, 256.0f);
+ }
+ }
+
+}
+
+
+
+// State management of the pencil drawing robot.
+
+bool CMotionVehicle::RetTraceDown()
+{
+ return m_bTraceDown;
+}
+
+void CMotionVehicle::SetTraceDown(bool bDown)
+{
+ m_bTraceDown = bDown;
+}
+
+int CMotionVehicle::RetTraceColor()
+{
+ return m_traceColor;
+}
+
+void CMotionVehicle::SetTraceColor(int color)
+{
+ m_traceColor = color;
+}
+
+float CMotionVehicle::RetTraceWidth()
+{
+ return m_traceWidth;
+}
+
+void CMotionVehicle::SetTraceWidth(float width)
+{
+ m_traceWidth = width;
+}
+
+
diff --git a/src/object/motion/motionvehicle.h b/src/object/motion/motionvehicle.h
index d3e00f9..5ca97cd 100644
--- a/src/object/motion/motionvehicle.h
+++ b/src/object/motion/motionvehicle.h
@@ -1,69 +1,69 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionvehicle.h
-
-#pragma once
-
-
-#include "object/motion/motion.h"
-
-
-
-class CMotionVehicle : public CMotion
-{
-public:
- CMotionVehicle(CInstanceManager* iMan, CObject* object);
- ~CMotionVehicle();
-
- void DeleteObject(bool bAll=false);
- bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- bool EventProcess(const Event &event);
-
- bool RetTraceDown();
- void SetTraceDown(bool bDown);
- int RetTraceColor();
- void SetTraceColor(int color);
- float RetTraceWidth();
- void SetTraceWidth(float width);
-
-protected:
- void CreatePhysics(ObjectType type);
- bool EventFrame(const Event &event);
- bool EventFrameFly(const Event &event);
- bool EventFrameInsect(const Event &event);
- bool EventFrameCanoni(const Event &event);
- void UpdateTrackMapping(float left, float right, ObjectType type);
-
-protected:
- float m_wheelTurn[4];
- float m_flyPaw[3];
- float m_posTrackLeft;
- float m_posTrackRight;
- int m_partiReactor;
- float m_armTimeAbs;
- float m_armMember;
- float m_canonTime;
- float m_lastTimeCanon;
- Math::Vector m_wheelLastPos;
- Math::Vector m_wheelLastAngle;
- Math::Vector m_posKey;
- bool m_bFlyFix;
- bool m_bTraceDown;
- int m_traceColor;
- float m_traceWidth;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionvehicle.h
+
+#pragma once
+
+
+#include "object/motion/motion.h"
+
+
+
+class CMotionVehicle : public CMotion
+{
+public:
+ CMotionVehicle(CInstanceManager* iMan, CObject* object);
+ ~CMotionVehicle();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ bool EventProcess(const Event &event);
+
+ bool RetTraceDown();
+ void SetTraceDown(bool bDown);
+ int RetTraceColor();
+ void SetTraceColor(int color);
+ float RetTraceWidth();
+ void SetTraceWidth(float width);
+
+protected:
+ void CreatePhysics(ObjectType type);
+ bool EventFrame(const Event &event);
+ bool EventFrameFly(const Event &event);
+ bool EventFrameInsect(const Event &event);
+ bool EventFrameCanoni(const Event &event);
+ void UpdateTrackMapping(float left, float right, ObjectType type);
+
+protected:
+ float m_wheelTurn[4];
+ float m_flyPaw[3];
+ float m_posTrackLeft;
+ float m_posTrackRight;
+ int m_partiReactor;
+ float m_armTimeAbs;
+ float m_armMember;
+ float m_canonTime;
+ float m_lastTimeCanon;
+ Math::Vector m_wheelLastPos;
+ Math::Vector m_wheelLastAngle;
+ Math::Vector m_posKey;
+ bool m_bFlyFix;
+ bool m_bTraceDown;
+ int m_traceColor;
+ float m_traceWidth;
+};
+
diff --git a/src/object/motion/motionworm.cpp b/src/object/motion/motionworm.cpp
index a18b7c4..daf74ff 100644
--- a/src/object/motion/motionworm.cpp
+++ b/src/object/motion/motionworm.cpp
@@ -1,365 +1,365 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionworm.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motionworm.h"
-
-#include "old/modfile.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "math/geometry.h"
-#include "physics/physics.h"
-
-
-
-
-const float START_TIME = 1000.0f; // beginning of the relative time
-const float TIME_UPDOWN = 2.0f; // time for up / down
-const float DOWN_ALTITUDE = 3.0f; // underground distance
-const int WORM_PART = 7; // number of parts of a worm
-
-
-
-// Object's constructor.
-
-CMotionWorm::CMotionWorm(CInstanceManager* iMan, CObject* object)
- : CMotion(iMan, object)
-{
- m_timeUp = 18.0f;
- m_timeDown = 18.0f;
- m_armMember = START_TIME;
- m_armTimeAbs = START_TIME;
- m_armTimeMarch = START_TIME;
- m_armTimeAction = START_TIME;
- m_armTimeIndex = 0;
- m_armPartIndex = 0;
- m_armMemberIndex = 0;
- m_armLinSpeed = 0.0f;
- m_armCirSpeed = 0.0f;
- m_armLastAction = -1;
- m_specAction = -1;
- m_lastParticule = 0.0f;
- m_bArmStop = false;
-}
-
-// Object's destructor.
-
-CMotionWorm::~CMotionWorm()
-{
-}
-
-
-// Removes an object.
-
-void CMotionWorm::DeleteObject(bool bAll)
-{
-}
-
-
-// Creates a vehicle traveling any lands on the ground.
-
-bool CMotionWorm::Create(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- int rank, i;
- float px;
-
- if ( m_engine->RetRestCreate() < 2+WORM_PART+1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- m_object->SetType(type);
-
- // Creates the main base.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\worm0.mod"); // there is no purpose!
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(0, pos);
- m_object->SetAngleY(0, angle);
-
- // A vehicle must have a obligatory collision with a sphere of center (0, y, 0) (see GetCrashSphere).
- m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
- m_object->SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 5.0f);
-
- px = 1.0f+WORM_PART/2;
-
- // Creates the head.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\worm1.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(px, 0.0f, 0.0f));
- px -= 1.0f;
-
- // Creates the body.
- for ( i=0 ; i<WORM_PART ; i++ )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2+i, rank);
- m_object->SetObjectParent(2+i, 0);
- pModFile->ReadModel("objects\\worm2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2+i, Math::Vector(px, 0.0f, 0.0f));
- px -= 1.0f;
- }
-
- // Creates the tail.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2+WORM_PART, rank);
- m_object->SetObjectParent(2+WORM_PART, 0);
- pModFile->ReadModel("objects\\worm3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2+WORM_PART, Math::Vector(px, 0.0f, 0.0f));
-
- m_object->CreateShadowCircle(0.0f, 1.0f, D3DSHADOWWORM);
-
- CreatePhysics();
- m_object->SetFloorHeight(0.0f);
-
- pos = m_object->RetPosition(0);
- m_object->SetPosition(0, pos); // to display the shadows immediately
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-// Creates the physics of the object.
-
-void CMotionWorm::CreatePhysics()
-{
- Character* character;
-
- m_physics->SetType(TYPE_ROLLING);
-
- character = m_object->RetCharacter();
- character->wheelFront = 10.0f;
- character->wheelBack = 10.0f;
- character->wheelLeft = 2.0f;
- character->wheelRight = 2.0f;
- character->height = -0.2f;
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 3.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 3.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.2f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.2f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 20.0f);
-}
-
-
-
-// Specifies a special parameter.
-
-bool CMotionWorm::SetParam(int rank, float value)
-{
- if ( rank == 0 )
- {
- m_timeDown = value;
- return true;
- }
-
- if ( rank == 1 )
- {
- m_timeUp = value;
- return true;
- }
-
- return false;
-}
-
-float CMotionWorm::RetParam(int rank)
-{
- if ( rank == 0 ) return m_timeDown;
- if ( rank == 1 ) return m_timeUp;
- return 0.0f;
-}
-
-
-
-// Management of an event.
-
-bool CMotionWorm::EventProcess(const Event &event)
-{
- CMotion::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
- }
-
- return true;
-}
-
-// Management of an event.
-
-bool CMotionWorm::EventFrame(const Event &event)
-{
- Math::Matrix* mat;
- Math::Vector pos, p, angle, speed;
- Math::Point center, pp, dim;
- float height[WORM_PART+2];
- float floor, a, s, px, curve, phase, h, zoom, radius;
- int i, under;
-
- if ( m_engine->RetPause() ) return true;
-
- s = m_physics->RetLinMotionX(MO_MOTSPEED)/m_physics->RetLinMotionX(MO_ADVSPEED);
- a = m_physics->RetCirMotionY(MO_MOTSPEED)/m_physics->RetCirMotionY(MO_ADVSPEED);
-
- if ( s == 0.0f && a != 0.0f ) s = a;
-
- m_armLinSpeed += (s-m_armLinSpeed)*event.rTime*3.0f;
- m_armCirSpeed += (a-m_armCirSpeed)*event.rTime*1.5f;
-
- m_armTimeAbs += event.rTime;
- m_armTimeMarch += event.rTime*m_armLinSpeed;
-
- under = 0; // no piece under the ground
- for ( i=0 ; i<WORM_PART+2 ; i++ )
- {
- phase = Math::Mod(m_armTimeMarch-START_TIME-i*0.3f, TIME_UPDOWN+m_timeDown+TIME_UPDOWN+m_timeUp);
- if ( phase < TIME_UPDOWN ) // descends?
- {
- h = -(phase/TIME_UPDOWN)*DOWN_ALTITUDE;
- }
- else if ( phase < TIME_UPDOWN+m_timeDown ) // advance underground?
- {
- h = -DOWN_ALTITUDE;
- under ++; // the most of a piece entirely under ground
- }
- else if ( phase < TIME_UPDOWN+m_timeDown+TIME_UPDOWN ) // up?
- {
- h = -(1.0f-(phase-TIME_UPDOWN-m_timeDown)/TIME_UPDOWN)*DOWN_ALTITUDE;
- }
- else // advance on earth?
- {
- h = 0.0f;
- }
- if ( m_object->RetBurn() ) // is burning?
- {
- h = 0.0f; // remains on earth
- }
- h += 0.3f;
- height[i] = h;
- }
- m_object->SetVisible(under!=WORM_PART+2);
-
- if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
-
- pos = m_object->RetPosition(0);
- floor = m_terrain->RetFloorLevel(pos, true);
-
- mat = m_object->RetWorldMatrix(0);
-
- px = 1.0f+WORM_PART/2;
- for ( i=0 ; i<WORM_PART+2 ; i++ )
- {
- radius = 1.0f+(height[i]-0.3f)/DOWN_ALTITUDE; // 0 = underground, 1 = surface
- radius = radius*1.3f-0.3f;
- if ( radius < 0.0f ) radius = 0.0f;
- radius *= 5.0f;
- m_engine->SetObjectShadowRadius(m_object->RetObjectRank(0), radius);
-
- pos.x = px+ sinf(m_armTimeMarch*4.0f+0.5f*i)*0.6f;
- pos.y = height[i]+sinf(m_armTimeMarch*4.0f+0.5f*i)*0.2f*m_armLinSpeed;
- pos.y += sinf(m_armTimeAbs *1.3f+0.2f*i)*0.1f;
- pos.z = sinf(m_armTimeAbs *2.0f+0.7f*i)*0.2f;
-
- curve = ((float)i-(WORM_PART+2)/2)*m_armCirSpeed*0.1f;
- center.x = 0.0f;
- center.y = 0.0f;
- pp.x = pos.x;
- pp.y = pos.z;
- pp = Math::RotatePoint(center, curve, pp);
- pos.x = pp.x;
- pos.z = pp.y;
-
- p = Transform(*mat, pos);
- pos.y += m_terrain->RetFloorLevel(p, true)-floor;
- m_object->SetPosition(i+1, pos);
-
- zoom = Math::Mod(m_armTimeAbs*0.5f+100.0f-i*0.1f, 2.0f);
- if ( zoom > 1.0f ) zoom = 2.0f-zoom;
- zoom *= 1.6f;
- if ( zoom < 1.0f ) zoom = 1.0f;
- m_object->SetZoomY(i+1, 0.2f+zoom*0.8f);
- m_object->SetZoomZ(i+1, zoom);
-
- if ( height[i] >= -1.0f && height[i] < -0.2f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.2f) <= m_armTimeMarch )
- {
- m_lastParticule = m_armTimeMarch;
-
- pos = p;
- pos.y += -height[i];
- pos.x += (Math::Rand()-0.5f)*4.0f;
- pos.z += (Math::Rand()-0.5f)*4.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*2.0f+1.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
-
- px -= 1.0f;
- }
-
- for ( i=0 ; i<WORM_PART+1 ; i++ )
- {
- pos = m_object->RetPosition(i+2);
- pos -= m_object->RetPosition(i+1);
-
- angle.z = -Math::RotateAngle(Math::Point(pos.x, pos.z).Length(), pos.y);
- angle.y = Math::PI-Math::RotateAngle(pos.x, pos.z);
- angle.x = 0.0f;
- m_object->SetAngle(i+1, angle);
-
- if ( i == WORM_PART )
- {
- m_object->SetAngle(i+2, angle);
- }
- }
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionworm.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motionworm.h"
+
+#include "old/modfile.h"
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "math/geometry.h"
+#include "physics/physics.h"
+
+
+
+
+const float START_TIME = 1000.0f; // beginning of the relative time
+const float TIME_UPDOWN = 2.0f; // time for up / down
+const float DOWN_ALTITUDE = 3.0f; // underground distance
+const int WORM_PART = 7; // number of parts of a worm
+
+
+
+// Object's constructor.
+
+CMotionWorm::CMotionWorm(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ m_timeUp = 18.0f;
+ m_timeDown = 18.0f;
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeMarch = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLinSpeed = 0.0f;
+ m_armCirSpeed = 0.0f;
+ m_armLastAction = -1;
+ m_specAction = -1;
+ m_lastParticule = 0.0f;
+ m_bArmStop = false;
+}
+
+// Object's destructor.
+
+CMotionWorm::~CMotionWorm()
+{
+}
+
+
+// Removes an object.
+
+void CMotionWorm::DeleteObject(bool bAll)
+{
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+bool CMotionWorm::Create(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank, i;
+ float px;
+
+ if ( m_engine->RetRestCreate() < 2+WORM_PART+1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates the main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\worm0.mod"); // there is no purpose!
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have a obligatory collision with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
+ m_object->SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 5.0f);
+
+ px = 1.0f+WORM_PART/2;
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\worm1.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(px, 0.0f, 0.0f));
+ px -= 1.0f;
+
+ // Creates the body.
+ for ( i=0 ; i<WORM_PART ; i++ )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2+i, rank);
+ m_object->SetObjectParent(2+i, 0);
+ pModFile->ReadModel("objects\\worm2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2+i, Math::Vector(px, 0.0f, 0.0f));
+ px -= 1.0f;
+ }
+
+ // Creates the tail.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2+WORM_PART, rank);
+ m_object->SetObjectParent(2+WORM_PART, 0);
+ pModFile->ReadModel("objects\\worm3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2+WORM_PART, Math::Vector(px, 0.0f, 0.0f));
+
+ m_object->CreateShadowCircle(0.0f, 1.0f, D3DSHADOWWORM);
+
+ CreatePhysics();
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+// Creates the physics of the object.
+
+void CMotionWorm::CreatePhysics()
+{
+ Character* character;
+
+ m_physics->SetType(TYPE_ROLLING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 10.0f;
+ character->wheelBack = 10.0f;
+ character->wheelLeft = 2.0f;
+ character->wheelRight = 2.0f;
+ character->height = -0.2f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 3.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 3.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.2f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.2f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 20.0f);
+}
+
+
+
+// Specifies a special parameter.
+
+bool CMotionWorm::SetParam(int rank, float value)
+{
+ if ( rank == 0 )
+ {
+ m_timeDown = value;
+ return true;
+ }
+
+ if ( rank == 1 )
+ {
+ m_timeUp = value;
+ return true;
+ }
+
+ return false;
+}
+
+float CMotionWorm::RetParam(int rank)
+{
+ if ( rank == 0 ) return m_timeDown;
+ if ( rank == 1 ) return m_timeUp;
+ return 0.0f;
+}
+
+
+
+// Management of an event.
+
+bool CMotionWorm::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+ }
+
+ return true;
+}
+
+// Management of an event.
+
+bool CMotionWorm::EventFrame(const Event &event)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, p, angle, speed;
+ Math::Point center, pp, dim;
+ float height[WORM_PART+2];
+ float floor, a, s, px, curve, phase, h, zoom, radius;
+ int i, under;
+
+ if ( m_engine->RetPause() ) return true;
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)/m_physics->RetLinMotionX(MO_ADVSPEED);
+ a = m_physics->RetCirMotionY(MO_MOTSPEED)/m_physics->RetCirMotionY(MO_ADVSPEED);
+
+ if ( s == 0.0f && a != 0.0f ) s = a;
+
+ m_armLinSpeed += (s-m_armLinSpeed)*event.rTime*3.0f;
+ m_armCirSpeed += (a-m_armCirSpeed)*event.rTime*1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armTimeMarch += event.rTime*m_armLinSpeed;
+
+ under = 0; // no piece under the ground
+ for ( i=0 ; i<WORM_PART+2 ; i++ )
+ {
+ phase = Math::Mod(m_armTimeMarch-START_TIME-i*0.3f, TIME_UPDOWN+m_timeDown+TIME_UPDOWN+m_timeUp);
+ if ( phase < TIME_UPDOWN ) // descends?
+ {
+ h = -(phase/TIME_UPDOWN)*DOWN_ALTITUDE;
+ }
+ else if ( phase < TIME_UPDOWN+m_timeDown ) // advance underground?
+ {
+ h = -DOWN_ALTITUDE;
+ under ++; // the most of a piece entirely under ground
+ }
+ else if ( phase < TIME_UPDOWN+m_timeDown+TIME_UPDOWN ) // up?
+ {
+ h = -(1.0f-(phase-TIME_UPDOWN-m_timeDown)/TIME_UPDOWN)*DOWN_ALTITUDE;
+ }
+ else // advance on earth?
+ {
+ h = 0.0f;
+ }
+ if ( m_object->RetBurn() ) // is burning?
+ {
+ h = 0.0f; // remains on earth
+ }
+ h += 0.3f;
+ height[i] = h;
+ }
+ m_object->SetVisible(under!=WORM_PART+2);
+
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
+
+ pos = m_object->RetPosition(0);
+ floor = m_terrain->RetFloorLevel(pos, true);
+
+ mat = m_object->RetWorldMatrix(0);
+
+ px = 1.0f+WORM_PART/2;
+ for ( i=0 ; i<WORM_PART+2 ; i++ )
+ {
+ radius = 1.0f+(height[i]-0.3f)/DOWN_ALTITUDE; // 0 = underground, 1 = surface
+ radius = radius*1.3f-0.3f;
+ if ( radius < 0.0f ) radius = 0.0f;
+ radius *= 5.0f;
+ m_engine->SetObjectShadowRadius(m_object->RetObjectRank(0), radius);
+
+ pos.x = px+ sinf(m_armTimeMarch*4.0f+0.5f*i)*0.6f;
+ pos.y = height[i]+sinf(m_armTimeMarch*4.0f+0.5f*i)*0.2f*m_armLinSpeed;
+ pos.y += sinf(m_armTimeAbs *1.3f+0.2f*i)*0.1f;
+ pos.z = sinf(m_armTimeAbs *2.0f+0.7f*i)*0.2f;
+
+ curve = ((float)i-(WORM_PART+2)/2)*m_armCirSpeed*0.1f;
+ center.x = 0.0f;
+ center.y = 0.0f;
+ pp.x = pos.x;
+ pp.y = pos.z;
+ pp = Math::RotatePoint(center, curve, pp);
+ pos.x = pp.x;
+ pos.z = pp.y;
+
+ p = Transform(*mat, pos);
+ pos.y += m_terrain->RetFloorLevel(p, true)-floor;
+ m_object->SetPosition(i+1, pos);
+
+ zoom = Math::Mod(m_armTimeAbs*0.5f+100.0f-i*0.1f, 2.0f);
+ if ( zoom > 1.0f ) zoom = 2.0f-zoom;
+ zoom *= 1.6f;
+ if ( zoom < 1.0f ) zoom = 1.0f;
+ m_object->SetZoomY(i+1, 0.2f+zoom*0.8f);
+ m_object->SetZoomZ(i+1, zoom);
+
+ if ( height[i] >= -1.0f && height[i] < -0.2f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.2f) <= m_armTimeMarch )
+ {
+ m_lastParticule = m_armTimeMarch;
+
+ pos = p;
+ pos.y += -height[i];
+ pos.x += (Math::Rand()-0.5f)*4.0f;
+ pos.z += (Math::Rand()-0.5f)*4.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*2.0f+1.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+
+ px -= 1.0f;
+ }
+
+ for ( i=0 ; i<WORM_PART+1 ; i++ )
+ {
+ pos = m_object->RetPosition(i+2);
+ pos -= m_object->RetPosition(i+1);
+
+ angle.z = -Math::RotateAngle(Math::Point(pos.x, pos.z).Length(), pos.y);
+ angle.y = Math::PI-Math::RotateAngle(pos.x, pos.z);
+ angle.x = 0.0f;
+ m_object->SetAngle(i+1, angle);
+
+ if ( i == WORM_PART )
+ {
+ m_object->SetAngle(i+2, angle);
+ }
+ }
+
+ return true;
+}
+
+
diff --git a/src/object/motion/motionworm.h b/src/object/motion/motionworm.h
index f159e5c..1b2abf9 100644
--- a/src/object/motion/motionworm.h
+++ b/src/object/motion/motionworm.h
@@ -1,62 +1,62 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionworm.h
-
-#pragma once
-
-
-#include "object/motion/motion.h"
-
-
-
-class CMotionWorm : public CMotion
-{
-public:
- CMotionWorm(CInstanceManager* iMan, CObject* object);
- ~CMotionWorm();
-
- void DeleteObject(bool bAll=false);
- bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- bool EventProcess(const Event &event);
-
- bool SetParam(int rank, float value);
- float RetParam(int rank);
-
-protected:
- void CreatePhysics();
- bool EventFrame(const Event &event);
-
-protected:
- float m_timeUp;
- float m_timeDown;
- float m_armMember;
- float m_armTimeAbs;
- float m_armTimeMarch;
- float m_armTimeAction;
- short m_armAngles[3*3*3*3*10];
- int m_armTimeIndex;
- int m_armPartIndex;
- int m_armMemberIndex;
- int m_armLastAction;
- float m_armLinSpeed;
- float m_armCirSpeed;
- int m_specAction;
- float m_specTime;
- bool m_bArmStop;
- float m_lastParticule;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionworm.h
+
+#pragma once
+
+
+#include "object/motion/motion.h"
+
+
+
+class CMotionWorm : public CMotion
+{
+public:
+ CMotionWorm(CInstanceManager* iMan, CObject* object);
+ ~CMotionWorm();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ bool EventProcess(const Event &event);
+
+ bool SetParam(int rank, float value);
+ float RetParam(int rank);
+
+protected:
+ void CreatePhysics();
+ bool EventFrame(const Event &event);
+
+protected:
+ float m_timeUp;
+ float m_timeDown;
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeMarch;
+ float m_armTimeAction;
+ short m_armAngles[3*3*3*3*10];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ float m_armLinSpeed;
+ float m_armCirSpeed;
+ int m_specAction;
+ float m_specTime;
+ bool m_bArmStop;
+ float m_lastParticule;
+};
+
diff --git a/src/object/object.cpp b/src/object/object.cpp
index 6931bd2..692a9c9 100644
--- a/src/object/object.cpp
+++ b/src/object/object.cpp
@@ -1,7606 +1,7606 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// object.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "CBot/CBotDll.h"
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "old/d3dutil.h"
-#include "common/global.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "old/math3d.h"
-#include "object/mainmovie.h"
-#include "object/robotmain.h"
-#include "old/light.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "old/blitz.h"
-#include "old/camera.h"
-#include "old/particule.h"
-#include "physics/physics.h"
-#include "object/brain.h"
-#include "object/motion/motion.h"
-#include "object/motion/motionhuman.h"
-#include "object/motion/motiontoto.h"
-#include "object/motion/motionvehicle.h"
-#include "object/motion/motionmother.h"
-#include "object/motion/motionant.h"
-#include "object/motion/motionspider.h"
-#include "object/motion/motionbee.h"
-#include "object/motion/motionworm.h"
-#include "old/modfile.h"
-#include "object/auto/auto.h"
-#include "object/auto/autobase.h"
-#include "object/auto/autoportico.h"
-#include "object/auto/autoderrick.h"
-#include "object/auto/autofactory.h"
-#include "object/auto/autorepair.h"
-#include "object/auto/autodestroyer.h"
-#include "object/auto/autostation.h"
-#include "object/auto/autoenergy.h"
-#include "object/auto/autoconvert.h"
-#include "object/auto/autotower.h"
-#include "object/auto/autoresearch.h"
-#include "object/auto/autolabo.h"
-#include "object/auto/autonuclear.h"
-#include "object/auto/autoradar.h"
-#include "object/auto/autoegg.h"
-#include "object/auto/autonest.h"
-#include "object/auto/autoroot.h"
-#include "object/auto/autoflag.h"
-#include "object/auto/autoinfo.h"
-#include "object/auto/autojostle.h"
-#include "object/auto/autopara.h"
-#include "object/auto/autosafe.h"
-#include "object/auto/autohuston.h"
-#include "object/auto/automush.h"
-#include "object/auto/autokid.h"
-#include "object/task/task.h"
-#include "old/pyro.h"
-#include "ui/displaytext.h"
-#include "script/cmdtoken.h"
-#include "script/cbottoken.h"
-#include "old/sound.h"
-#include "object/object.h"
-
-
-
-#define ADJUST_ONBOARD false // true -> adjusts the camera ONBOARD
-#define ADJUST_ARM false // true -> adjusts the manipulator arm
-const float VIRUS_DELAY = 60.0f; // duration of virus infection
-const float LOSS_SHIELD = 0.24f; // loss of the shield by shot
-const float LOSS_SHIELD_H = 0.10f; // loss of the shield for humans
-const float LOSS_SHIELD_M = 0.02f; // loss of the shield for the laying
-
-#if ADJUST_ONBOARD
-static float debug_x = 0.0f;
-static float debug_y = 0.0f;
-static float debug_z = 0.0f;
-#endif
-
-#if ADJUST_ARM
-static float debug_arm1 = 0.0f;
-static float debug_arm2 = 0.0f;
-static float debug_arm3 = 0.0f;
-#endif
-
-
-
-
-// Updates the class Object.
-
-void uObject(CBotVar* botThis, void* user)
-{
- CObject* object = (CObject*)user;
- CObject* power;
- CObject* fret;
- CPhysics* physics;
- CBotVar *pVar, *pSub;
- ObjectType type;
- Math::Vector pos;
- float value;
- int iValue;
-
- if ( object == 0 ) return;
-
- physics = object->RetPhysics();
-
- // Updates the object's type.
- pVar = botThis->GivItemList(); // "category"
- type = object->RetType();
- pVar->SetValInt(type, object->RetName());
-
- // Updates the position of the object.
- pVar = pVar->GivNext(); // "position"
- if ( object->RetTruck() == 0 )
- {
- pos = object->RetPosition(0);
- pos.y -= object->RetWaterLevel(); // relative to sea level!
- pSub = pVar->GivItemList(); // "x"
- pSub->SetValFloat(pos.x/g_unit);
- pSub = pSub->GivNext(); // "y"
- pSub->SetValFloat(pos.z/g_unit);
- pSub = pSub->GivNext(); // "z"
- pSub->SetValFloat(pos.y/g_unit);
- }
- else // object transported?
- {
- pSub = pVar->GivItemList(); // "x"
- pSub->SetInit(IS_NAN);
- pSub = pSub->GivNext(); // "y"
- pSub->SetInit(IS_NAN);
- pSub = pSub->GivNext(); // "z"
- pSub->SetInit(IS_NAN);
- }
-
- // Updates the angle.
- pos = object->RetAngle(0);
- pos += object->RetInclinaison();
- pVar = pVar->GivNext(); // "orientation"
- pVar->SetValFloat(360.0f-Math::Mod(pos.y*180.0f/Math::PI, 360.0f));
- pVar = pVar->GivNext(); // "pitch"
- pVar->SetValFloat(pos.z*180.0f/Math::PI);
- pVar = pVar->GivNext(); // "roll"
- pVar->SetValFloat(pos.x*180.0f/Math::PI);
-
- // Updates the energy level of the object.
- pVar = pVar->GivNext(); // "energyLevel"
- value = object->RetEnergy();
- pVar->SetValFloat(value);
-
- // Updates the shield level of the object.
- pVar = pVar->GivNext(); // "shieldLevel"
- value = object->RetShield();
- pVar->SetValFloat(value);
-
- // Updates the temperature of the reactor.
- pVar = pVar->GivNext(); // "temperature"
- if ( physics == 0 ) value = 0.0f;
- else value = 1.0f-physics->RetReactorRange();
- pVar->SetValFloat(value);
-
- // Updates the height above the ground.
- pVar = pVar->GivNext(); // "altitude"
- if ( physics == 0 ) value = 0.0f;
- else value = physics->RetFloorHeight();
- pVar->SetValFloat(value/g_unit);
-
- // Updates the lifetime of the object.
- pVar = pVar->GivNext(); // "lifeTime"
- value = object->RetAbsTime();
- pVar->SetValFloat(value);
-
- // Updates the material of the object.
- pVar = pVar->GivNext(); // "material"
- iValue = object->RetMaterial();
- pVar->SetValInt(iValue);
-
- // Updates the type of battery.
- pVar = pVar->GivNext(); // "energyCell"
- power = object->RetPower();
- if ( power == 0 ) pVar->SetPointer(0);
- else pVar->SetPointer(power->RetBotVar());
-
- // Updates the transported object's type.
- pVar = pVar->GivNext(); // "load"
- fret = object->RetFret();
- if ( fret == 0 ) pVar->SetPointer(0);
- else pVar->SetPointer(fret->RetBotVar());
-}
-
-
-
-
-// Object's constructor.
-
-CObject::CObject(CInstanceManager* iMan)
-{
- int i;
-
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_OBJECT, this, 500);
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- m_physics = 0;
- m_brain = 0;
- m_motion = 0;
- m_auto = 0;
- m_runScript = 0;
-
- m_type = OBJECT_FIX;
- m_id = ++g_id;
- m_option = 0;
- m_name[0] = 0;
- m_partiReactor = -1;
- m_shadowLight = -1;
- m_effectLight = -1;
- m_linVibration = Math::Vector(0.0f, 0.0f, 0.0f);
- m_cirVibration = Math::Vector(0.0f, 0.0f, 0.0f);
- m_inclinaison = Math::Vector(0.0f, 0.0f, 0.0f);
- m_lastParticule = 0.0f;
-
- m_power = 0;
- m_fret = 0;
- m_truck = 0;
- m_truckLink = 0;
- m_energy = 1.0f;
- m_capacity = 1.0f;
- m_shield = 1.0f;
- m_range = 0.0f;
- m_transparency = 0.0f;
- m_lastEnergy = 999.9f;
- m_bHilite = false;
- m_bSelect = false;
- m_bSelectable = true;
- m_bCheckToken = true;
- m_bVisible = true;
- m_bEnable = true;
- m_bGadget = false;
- m_bProxyActivate = false;
- m_bTrainer = false;
- m_bToy = false;
- m_bManual = false;
- m_bFixed = false;
- m_bClip = true;
- m_bShowLimit = false;
- m_showLimitRadius = 0.0f;
- m_aTime = 0.0f;
- m_shotTime = 0.0f;
- m_bVirusMode = false;
- m_virusTime = 0.0f;
- m_lastVirusParticule = 0.0f;
- m_totalDesectList = 0;
- m_bLock = false;
- m_bExplo = false;
- m_bCargo = false;
- m_bBurn = false;
- m_bDead = false;
- m_bFlat = false;
- m_gunGoalV = 0.0f;
- m_gunGoalH = 0.0f;
- m_shieldRadius = 0.0f;
- m_defRank = -1;
- m_magnifyDamage = 1.0f;
- m_proxyDistance = 60.0f;
- m_param = 0.0f;
-
- ZeroMemory(&m_character, sizeof(Character));
- m_character.wheelFront = 1.0f;
- m_character.wheelBack = 1.0f;
- m_character.wheelLeft = 1.0f;
- m_character.wheelRight = 1.0f;
-
- m_resetCap = RESET_NONE;
- m_bResetBusy = false;
- m_resetPosition = Math::Vector(0.0f, 0.0f, 0.0f);
- m_resetAngle = Math::Vector(0.0f, 0.0f, 0.0f);
- m_resetRun = -1;
-
- m_cameraType = CAMERA_BACK;
- m_cameraDist = 50.0f;
- m_bCameraLock = false;
-
- m_infoTotal = 0;
- m_infoReturn = NAN;
- m_bInfoUpdate = false;
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- m_objectPart[i].bUsed = false;
- }
- m_totalPart = 0;
-
- for ( i=0 ; i<4 ; i++ )
- {
- m_partiSel[i] = -1;
- }
-
- for ( i=0 ; i<OBJECTMAXCMDLINE ; i++ )
- {
- m_cmdLine[i] = NAN;
- }
-
- FlushCrashShere();
- m_globalSpherePos = Math::Vector(0.0f, 0.0f, 0.0f);
- m_globalSphereRadius = 0.0f;
- m_jotlerSpherePos = Math::Vector(0.0f, 0.0f, 0.0f);
- m_jotlerSphereRadius = 0.0f;
-
- CBotClass* bc = CBotClass::Find("object");
- if ( bc != 0 )
- {
- bc->AddUpdateFunc(uObject);
- }
-
- m_botVar = CBotVar::Create("", CBotTypResult(CBotTypClass, "object"));
- m_botVar->SetUserPtr(this);
- m_botVar->SetIdent(m_id);
-}
-
-// Object's destructor.
-
-CObject::~CObject()
-{
- if ( m_botVar != 0 )
- {
- m_botVar->SetUserPtr(OBJECTDELETED);
- delete m_botVar;
- }
-
- delete m_physics;
- delete m_brain;
- delete m_motion;
- delete m_auto;
-
- m_iMan->DeleteInstance(CLASS_OBJECT, this);
-}
-
-
-// Removes an object.
-// If bAll = true, it does not help,
-// because all objects in the scene are quickly destroyed!
-
-void CObject::DeleteObject(bool bAll)
-{
- CObject* pObj;
- CPyro* pPyro;
- int i;
-
- if ( m_botVar != 0 )
- {
- m_botVar->SetUserPtr(OBJECTDELETED);
- }
-
- if ( m_camera->RetObject() == this )
- {
- m_camera->SetObject(0);
- }
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- pObj->DeleteDeselList(this);
- }
-
- if ( !bAll )
- {
-#if 0
- type = m_camera->RetType();
- if ( (type == CAMERA_BACK ||
- type == CAMERA_FIX ||
- type == CAMERA_EXPLO ||
- type == CAMERA_ONBOARD) &&
- m_camera->RetObject() == this )
- {
- pObj = m_main->SearchNearest(RetPosition(0), this);
- if ( pObj == 0 )
- {
- m_camera->SetObject(0);
- m_camera->SetType(CAMERA_FREE);
- }
- else
- {
- m_camera->SetObject(pObj);
- m_camera->SetType(CAMERA_BACK);
- }
- }
-#endif
- for ( i=0 ; i<1000000 ; i++ )
- {
- pPyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, i);
- if ( pPyro == 0 ) break;
-
- pPyro->CutObjectLink(this); // the object no longer exists
- }
-
- if ( m_bSelect )
- {
- SetSelect(false);
- }
-
- if ( m_type == OBJECT_BASE ||
- m_type == OBJECT_FACTORY ||
- m_type == OBJECT_REPAIR ||
- m_type == OBJECT_DESTROYER||
- m_type == OBJECT_DERRICK ||
- m_type == OBJECT_STATION ||
- m_type == OBJECT_CONVERT ||
- m_type == OBJECT_TOWER ||
- m_type == OBJECT_RESEARCH ||
- m_type == OBJECT_RADAR ||
- m_type == OBJECT_INFO ||
- m_type == OBJECT_ENERGY ||
- m_type == OBJECT_LABO ||
- m_type == OBJECT_NUCLEAR ||
- m_type == OBJECT_PARA ||
- m_type == OBJECT_SAFE ||
- m_type == OBJECT_HUSTON ||
- m_type == OBJECT_START ||
- m_type == OBJECT_END ) // building?
- {
- m_terrain->DeleteBuildingLevel(RetPosition(0)); // flattens the field
- }
- }
-
- m_type = OBJECT_NULL; // invalid object until complete destruction
-
- if ( m_partiReactor != -1 )
- {
- m_particule->DeleteParticule(m_partiReactor);
- m_partiReactor = -1;
- }
-
- if ( m_shadowLight != -1 )
- {
- m_light->DeleteLight(m_shadowLight);
- m_shadowLight = -1;
- }
-
- if ( m_effectLight != -1 )
- {
- m_light->DeleteLight(m_effectLight);
- m_effectLight = -1;
- }
-
- if ( m_physics != 0 )
- {
- m_physics->DeleteObject(bAll);
- }
-
- if ( m_brain != 0 )
- {
- m_brain->DeleteObject(bAll);
- }
-
- if ( m_motion != 0 )
- {
- m_motion->DeleteObject(bAll);
- }
-
- if ( m_auto != 0 )
- {
- m_auto->DeleteObject(bAll);
- }
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- if ( m_objectPart[i].bUsed )
- {
- m_objectPart[i].bUsed = false;
- m_engine->DeleteObject(m_objectPart[i].object);
-
- if ( m_objectPart[i].masterParti != -1 )
- {
- m_particule->DeleteParticule(m_objectPart[i].masterParti);
- m_objectPart[i].masterParti = -1;
- }
- }
- }
-
- if ( m_bShowLimit )
- {
- m_main->FlushShowLimit(0);
- m_bShowLimit = false;
- }
-
- if ( !bAll ) m_main->CreateShortcuts();
-}
-
-// Simplifies a object (he was the brain, among others).
-
-void CObject::Simplify()
-{
- if ( m_brain != 0 )
- {
- m_brain->StopProgram();
- }
- m_main->SaveOneScript(this);
-
- if ( m_physics != 0 )
- {
- m_physics->DeleteObject();
- delete m_physics;
- m_physics = 0;
- }
-
- if ( m_brain != 0 )
- {
- m_brain->DeleteObject();
- delete m_brain;
- m_brain = 0;
- }
-
- if ( m_motion != 0 )
- {
- m_motion->DeleteObject();
- delete m_motion;
- m_motion = 0;
- }
-
- if ( m_auto != 0 )
- {
- m_auto->DeleteObject();
- delete m_auto;
- m_auto = 0;
- }
-
- m_main->CreateShortcuts();
-}
-
-
-// Detonates an object, when struck by a shot.
-// If false is returned, the object is still screwed.
-// If true is returned, the object is destroyed.
-
-bool CObject::ExploObject(ExploType type, float force, float decay)
-{
- PyroType pyroType;
- CPyro* pyro;
- float loss, shield;
-
- if ( type == EXPLO_BURN )
- {
- if ( m_type == OBJECT_MOBILEtg ||
- m_type == OBJECT_TEEN28 || // cylinder?
- m_type == OBJECT_METAL ||
- m_type == OBJECT_POWER ||
- m_type == OBJECT_ATOMIC ||
- m_type == OBJECT_TNT ||
- m_type == OBJECT_SCRAP1 ||
- m_type == OBJECT_SCRAP2 ||
- m_type == OBJECT_SCRAP3 ||
- m_type == OBJECT_SCRAP4 ||
- m_type == OBJECT_SCRAP5 ||
- m_type == OBJECT_BULLET ||
- m_type == OBJECT_EGG ) // object that isn't burning?
- {
- type = EXPLO_BOUM;
- force = 1.0f;
- decay = 1.0f;
- }
- }
-
- if ( EXPLO_BOUM )
- {
- if ( m_shotTime < 0.5f ) return false;
- m_shotTime = 0.0f;
- }
-
- if ( m_type == OBJECT_HUMAN && m_bDead ) return false;
-
- // Calculate the power lost by the explosion.
- if ( force == 0.0f )
- {
- if ( m_type == OBJECT_HUMAN )
- {
- loss = LOSS_SHIELD_H;
- }
- else if ( m_type == OBJECT_MOTHER )
- {
- loss = LOSS_SHIELD_M;
- }
- else
- {
- loss = LOSS_SHIELD;
- }
- }
- else
- {
- loss = force;
- }
- loss *= m_magnifyDamage;
- loss *= decay;
-
- // Decreases the power of the shield.
- shield = RetShield();
- shield -= loss;
- if ( shield < 0.0f ) shield = 0.0f;
- SetShield(shield);
-
- if ( shield > 0.0f ) // not dead yet?
- {
- if ( type == EXPLO_WATER )
- {
- if ( m_type == OBJECT_HUMAN )
- {
- pyroType = PT_SHOTH;
- }
- else
- {
- pyroType = PT_SHOTW;
- }
- }
- else
- {
- if ( m_type == OBJECT_HUMAN )
- {
- pyroType = PT_SHOTH;
- }
- else if ( m_type == OBJECT_MOTHER )
- {
- pyroType = PT_SHOTM;
- }
- else
- {
- pyroType = PT_SHOTT;
- }
- }
- }
- else // completely dead?
- {
- if ( type == EXPLO_BURN ) // burning?
- {
- if ( m_type == OBJECT_MOTHER ||
- m_type == OBJECT_ANT ||
- m_type == OBJECT_SPIDER ||
- m_type == OBJECT_BEE ||
- m_type == OBJECT_WORM ||
- m_type == OBJECT_BULLET )
- {
- pyroType = PT_BURNO;
- SetBurn(true);
- }
- else if ( m_type == OBJECT_HUMAN )
- {
- pyroType = PT_DEADG;
- }
- else
- {
- pyroType = PT_BURNT;
- SetBurn(true);
- }
- SetVirusMode(false);
- }
- else if ( type == EXPLO_WATER )
- {
- if ( m_type == OBJECT_HUMAN )
- {
- pyroType = PT_DEADW;
- }
- else
- {
- pyroType = PT_FRAGW;
- }
- }
- else // explosion?
- {
- if ( m_type == OBJECT_ANT ||
- m_type == OBJECT_SPIDER ||
- m_type == OBJECT_BEE ||
- m_type == OBJECT_WORM )
- {
- pyroType = PT_EXPLOO;
- }
- else if ( m_type == OBJECT_MOTHER ||
- m_type == OBJECT_NEST ||
- m_type == OBJECT_BULLET )
- {
- pyroType = PT_FRAGO;
- }
- else if ( m_type == OBJECT_HUMAN )
- {
- pyroType = PT_DEADG;
- }
- else if ( m_type == OBJECT_BASE ||
- m_type == OBJECT_DERRICK ||
- m_type == OBJECT_FACTORY ||
- m_type == OBJECT_STATION ||
- m_type == OBJECT_CONVERT ||
- m_type == OBJECT_REPAIR ||
- m_type == OBJECT_DESTROYER||
- m_type == OBJECT_TOWER ||
- m_type == OBJECT_NEST ||
- m_type == OBJECT_RESEARCH ||
- m_type == OBJECT_RADAR ||
- m_type == OBJECT_INFO ||
- m_type == OBJECT_ENERGY ||
- m_type == OBJECT_LABO ||
- m_type == OBJECT_NUCLEAR ||
- m_type == OBJECT_PARA ||
- m_type == OBJECT_SAFE ||
- m_type == OBJECT_HUSTON ||
- m_type == OBJECT_START ||
- m_type == OBJECT_END ) // building?
- {
- pyroType = PT_FRAGT;
- }
- else if ( m_type == OBJECT_MOBILEtg ||
- m_type == OBJECT_TEEN28 || // cylinder?
- m_type == OBJECT_TEEN31 ) // basket?
- {
- pyroType = PT_FRAGT;
- }
- else
- {
- pyroType = PT_EXPLOT;
- }
- }
-
- loss = 1.0f;
- }
-
- pyro = new CPyro(m_iMan);
- pyro->Create(pyroType, this, loss);
-
- if ( shield == 0.0f ) // dead?
- {
- if ( m_brain != 0 )
- {
- m_brain->StopProgram();
- }
- m_main->SaveOneScript(this);
- }
-
- if ( shield > 0.0f ) return false; // not dead yet
-
- if ( RetSelect() )
- {
- SetSelect(false); // deselects the object
- m_camera->SetType(CAMERA_EXPLO);
- m_main->DeselectAll();
- }
- DeleteDeselList(this);
-
- if ( m_botVar != 0 )
- {
- if ( m_type == OBJECT_STONE ||
- m_type == OBJECT_URANIUM ||
- m_type == OBJECT_METAL ||
- m_type == OBJECT_POWER ||
- m_type == OBJECT_ATOMIC ||
- m_type == OBJECT_BULLET ||
- m_type == OBJECT_BBOX ||
- m_type == OBJECT_TNT ||
- m_type == OBJECT_SCRAP1 ||
- m_type == OBJECT_SCRAP2 ||
- m_type == OBJECT_SCRAP3 ||
- m_type == OBJECT_SCRAP4 ||
- m_type == OBJECT_SCRAP5 ) // (*)
- {
- m_botVar->SetUserPtr(OBJECTDELETED);
- }
- }
-
- return true;
-}
-
-// (*) If a robot or cosmonaut dies, the subject must continue to exist,
-// so that programs of the ants continue to operate as usual.
-
-
-// Initializes a new part.
-
-void CObject::InitPart(int part)
-{
- m_objectPart[part].bUsed = true;
- m_objectPart[part].object = -1;
- m_objectPart[part].parentPart = -1;
-
- m_objectPart[part].position = Math::Vector(0.0f, 0.0f, 0.0f);
- m_objectPart[part].angle.y = 0.0f;
- m_objectPart[part].angle.x = 0.0f;
- m_objectPart[part].angle.z = 0.0f;
- m_objectPart[part].zoom = Math::Vector(1.0f, 1.0f, 1.0f);
-
- m_objectPart[part].bTranslate = true;
- m_objectPart[part].bRotate = true;
- m_objectPart[part].bZoom = false;
-
- m_objectPart[part].matTranslate.LoadIdentity();
- m_objectPart[part].matRotate.LoadIdentity();
- m_objectPart[part].matTransform.LoadIdentity();
- m_objectPart[part].matWorld.LoadIdentity();;
-
- m_objectPart[part].masterParti = -1;
-}
-
-// Creates a new part, and returns its number.
-// Returns -1 on error.
-
-int CObject::CreatePart()
-{
- int i;
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- if ( m_objectPart[i].bUsed ) continue;
-
- InitPart(i);
- UpdateTotalPart();
- return i;
- }
- return -1;
-}
-
-// Removes part.
-
-void CObject::DeletePart(int part)
-{
- if ( !m_objectPart[part].bUsed ) return;
-
- if ( m_objectPart[part].masterParti != -1 )
- {
- m_particule->DeleteParticule(m_objectPart[part].masterParti);
- m_objectPart[part].masterParti = -1;
- }
-
- m_objectPart[part].bUsed = false;
- m_engine->DeleteObject(m_objectPart[part].object);
- UpdateTotalPart();
-}
-
-void CObject::UpdateTotalPart()
-{
- int i;
-
- m_totalPart = 0;
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- if ( m_objectPart[i].bUsed )
- {
- m_totalPart = i+1;
- }
- }
-}
-
-
-// Specifies the number of the object of a part.
-
-void CObject::SetObjectRank(int part, int objRank)
-{
- if ( !m_objectPart[part].bUsed ) // object not created?
- {
- InitPart(part);
- UpdateTotalPart();
- }
- m_objectPart[part].object = objRank;
-}
-
-// Returns the number of part.
-
-int CObject::RetObjectRank(int part)
-{
- if ( !m_objectPart[part].bUsed ) return -1;
- return m_objectPart[part].object;
-}
-
-// Specifies what is the parent of a part.
-// Reminder: Part 0 is always the father of all
-// and therefore the main part (eg the chassis of a car).
-
-void CObject::SetObjectParent(int part, int parent)
-{
- m_objectPart[part].parentPart = parent;
-}
-
-
-// Specifies the type of the object.
-
-void CObject::SetType(ObjectType type)
-{
- m_type = type;
- strcpy(m_name, RetObjectName(m_type));
-
- if ( m_type == OBJECT_MOBILErs )
- {
- m_param = 1.0f; // shield up to default
- }
-
- if ( m_type == OBJECT_ATOMIC )
- {
- m_capacity = 10.0f;
- }
- else
- {
- m_capacity = 1.0f;
- }
-
- if ( m_type == OBJECT_MOBILEwc ||
- m_type == OBJECT_MOBILEtc ||
- m_type == OBJECT_MOBILEfc ||
- m_type == OBJECT_MOBILEic ||
- m_type == OBJECT_MOBILEwi ||
- m_type == OBJECT_MOBILEti ||
- m_type == OBJECT_MOBILEfi ||
- m_type == OBJECT_MOBILEii ||
- m_type == OBJECT_MOBILErc ) // cannon vehicle?
- {
- m_cameraType = CAMERA_ONBOARD;
- }
-}
-
-ObjectType CObject::RetType()
-{
- return m_type;
-}
-
-char* CObject::RetName()
-{
- return m_name;
-}
-
-
-// Choosing the option to use.
-
-void CObject::SetOption(int option)
-{
- m_option = option;
-}
-
-int CObject::RetOption()
-{
- return m_option;
-}
-
-
-// Management of the unique identifier of an object.
-
-void CObject::SetID(int id)
-{
- m_id = id;
-
- if ( m_botVar != 0 )
- {
- m_botVar->SetIdent(m_id);
- }
-}
-
-int CObject::RetID()
-{
- return m_id;
-}
-
-
-// Saves all the parameters of the object.
-
-bool CObject::Write(char *line)
-{
- Math::Vector pos;
- Info info;
- char name[100];
- float value;
- int i;
-
- sprintf(name, " camera=%s", GetCamera(RetCameraType()));
- strcat(line, name);
-
- if ( RetCameraLock() != 0 )
- {
- sprintf(name, " cameraLock=%d", RetCameraLock());
- strcat(line, name);
- }
-
- if ( RetEnergy() != 0.0f )
- {
- sprintf(name, " energy=%.2f", RetEnergy());
- strcat(line, name);
- }
-
- if ( RetCapacity() != 1.0f )
- {
- sprintf(name, " capacity=%.2f", RetCapacity());
- strcat(line, name);
- }
-
- if ( RetShield() != 1.0f )
- {
- sprintf(name, " shield=%.2f", RetShield());
- strcat(line, name);
- }
-
- if ( RetRange() != 1.0f )
- {
- sprintf(name, " range=%.2f", RetRange());
- strcat(line, name);
- }
-
- if ( RetSelectable() != 1 )
- {
- sprintf(name, " selectable=%d", RetSelectable());
- strcat(line, name);
- }
-
- if ( RetEnable() != 1 )
- {
- sprintf(name, " enable=%d", RetEnable());
- strcat(line, name);
- }
-
- if ( RetFixed() != 0 )
- {
- sprintf(name, " fixed=%d", RetFixed());
- strcat(line, name);
- }
-
- if ( RetClip() != 1 )
- {
- sprintf(name, " clip=%d", RetClip());
- strcat(line, name);
- }
-
- if ( RetLock() != 0 )
- {
- sprintf(name, " lock=%d", RetLock());
- strcat(line, name);
- }
-
- if ( RetProxyActivate() != 0 )
- {
- sprintf(name, " proxyActivate=%d", RetProxyActivate());
- strcat(line, name);
-
- sprintf(name, " proxyDistance=%.2f", RetProxyDistance()/g_unit);
- strcat(line, name);
- }
-
- if ( RetMagnifyDamage() != 1.0f )
- {
- sprintf(name, " magnifyDamage=%.2f", RetMagnifyDamage());
- strcat(line, name);
- }
-
- if ( RetGunGoalV() != 0.0f )
- {
- sprintf(name, " aimV=%.2f", RetGunGoalV());
- strcat(line, name);
- }
- if ( RetGunGoalH() != 0.0f )
- {
- sprintf(name, " aimH=%.2f", RetGunGoalH());
- strcat(line, name);
- }
-
- if ( RetParam() != 0.0f )
- {
- sprintf(name, " param=%.2f", RetParam());
- strcat(line, name);
- }
-
- if ( RetResetCap() != 0 )
- {
- sprintf(name, " resetCap=%d", RetResetCap());
- strcat(line, name);
-
- pos = RetResetPosition()/g_unit;
- sprintf(name, " resetPos=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
- strcat(line, name);
-
- pos = RetResetAngle()/(Math::PI/180.0f);
- sprintf(name, " resetAngle=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
- strcat(line, name);
-
- sprintf(name, " resetRun=%d", RetResetRun());
- strcat(line, name);
- }
-
- if ( m_bVirusMode != 0 )
- {
- sprintf(name, " virusMode=%d", m_bVirusMode);
- strcat(line, name);
- }
-
- if ( m_virusTime != 0.0f )
- {
- sprintf(name, " virusTime=%.2f", m_virusTime);
- strcat(line, name);
- }
-
- // Puts information in terminal (OBJECT_INFO).
- for ( i=0 ; i<m_infoTotal ; i++ )
- {
- info = RetInfo(i);
- if ( info.name[0] == 0 ) break;
-
- sprintf(name, " info%d=\"%s=%.2f\"", i+1, info.name, info.value);
- strcat(line, name);
- }
-
- // Sets the parameters of the command line.
- for ( i=0 ; i<OBJECTMAXCMDLINE ; i++ )
- {
- value = RetCmdLine(i);
- if ( value == NAN ) break;
-
- if ( i == 0 ) sprintf(name, " cmdline=%.2f", value);
- else sprintf(name, ";%.2f", value);
- strcat(line, name);
- }
-
- if ( m_motion != 0 )
- {
- m_motion->Write(line);
- }
-
- if ( m_brain != 0 )
- {
- m_brain->Write(line);
- }
-
- if ( m_physics != 0 )
- {
- m_physics->Write(line);
- }
-
- if ( m_auto != 0 )
- {
- m_auto->Write(line);
- }
-
- return true;
-}
-
-// Returns all parameters of the object.
-
-bool CObject::Read(char *line)
-{
- Math::Vector pos, dir;
- Info info;
- CameraType cType;
- char op[20];
- char text[100];
- char* p;
- float value;
- int i;
-
- cType = OpCamera(line, "camera");
- if ( cType != CAMERA_NULL )
- {
- SetCameraType(cType);
- }
-
- SetCameraLock(OpInt(line, "cameraLock", 0));
- SetEnergy(OpFloat(line, "energy", 0.0f));
- SetCapacity(OpFloat(line, "capacity", 1.0f));
- SetShield(OpFloat(line, "shield", 1.0f));
- SetRange(OpFloat(line, "range", 1.0f));
- SetSelectable(OpInt(line, "selectable", 1));
- SetEnable(OpInt(line, "enable", 1));
- SetFixed(OpInt(line, "fixed", 0));
- SetClip(OpInt(line, "clip", 1));
- SetLock(OpInt(line, "lock", 0));
- SetProxyActivate(OpInt(line, "proxyActivate", 0));
- SetProxyDistance(OpFloat(line, "proxyDistance", 15.0f)*g_unit);
- SetRange(OpFloat(line, "range", 30.0f));
- SetMagnifyDamage(OpFloat(line, "magnifyDamage", 1.0f));
- SetGunGoalV(OpFloat(line, "aimV", 0.0f));
- SetGunGoalH(OpFloat(line, "aimH", 0.0f));
- SetParam(OpFloat(line, "param", 0.0f));
- SetResetCap((ResetCap)OpInt(line, "resetCap", 0));
- SetResetPosition(OpDir(line, "resetPos")*g_unit);
- SetResetAngle(OpDir(line, "resetAngle")*(Math::PI/180.0f));
- SetResetRun(OpInt(line, "resetRun", 0));
- m_bBurn = OpInt(line, "burnMode", 0);
- m_bVirusMode = OpInt(line, "virusMode", 0);
- m_virusTime = OpFloat(line, "virusTime", 0.0f);
-
- // Puts information in terminal (OBJECT_INFO).
- for ( i=0 ; i<OBJECTMAXINFO ; i++ )
- {
- sprintf(op, "info%d", i+1);
- OpString(line, op, text);
- if ( text[0] == 0 ) break;
- p = strchr(text, '=');
- if ( p == 0 ) break;
- *p = 0;
- strcpy(info.name, text);
- sscanf(p+1, "%f", &info.value);
- SetInfo(i, info);
- }
-
- // Sets the parameters of the command line.
- p = SearchOp(line, "cmdline");
- for ( i=0 ; i<OBJECTMAXCMDLINE ; i++ )
- {
- value = GetFloat(p, i, NAN);
- if ( value == NAN ) break;
- SetCmdLine(i, value);
- }
-
- if ( m_motion != 0 )
- {
- m_motion->Read(line);
- }
-
- if ( m_brain != 0 )
- {
- m_brain->Read(line);
- }
-
- if ( m_physics != 0 )
- {
- m_physics->Read(line);
- }
-
- if ( m_auto != 0 )
- {
- m_auto->Read(line);
- }
-
- return true;
-}
-
-
-
-// Seeking the nth son of a father.
-
-int CObject::SearchDescendant(int parent, int n)
-{
- int i;
-
- for ( i=0 ; i<m_totalPart ; i++ )
- {
- if ( !m_objectPart[i].bUsed ) continue;
-
- if ( parent == m_objectPart[i].parentPart )
- {
- if ( n-- == 0 ) return i;
- }
- }
- return -1;
-}
-
-
-// Removes all spheres used for collisions.
-
-void CObject::FlushCrashShere()
-{
- m_crashSphereUsed = 0;
-}
-
-// Adds a new sphere.
-
-int CObject::CreateCrashSphere(Math::Vector pos, float radius, Sound sound,
- float hardness)
-{
- float zoom;
-
- if ( m_crashSphereUsed >= MAXCRASHSPHERE ) return -1;
-
- zoom = RetZoomX(0);
- m_crashSpherePos[m_crashSphereUsed] = pos;
- m_crashSphereRadius[m_crashSphereUsed] = radius*zoom;
- m_crashSphereHardness[m_crashSphereUsed] = hardness;
- m_crashSphereSound[m_crashSphereUsed] = sound;
- return m_crashSphereUsed++;
-}
-
-// Returns the number of spheres.
-
-int CObject::RetCrashSphereTotal()
-{
- return m_crashSphereUsed;
-}
-
-// Returns a sphere for collisions.
-// The position is absolute in the world.
-
-bool CObject::GetCrashSphere(int rank, Math::Vector &pos, float &radius)
-{
- if ( rank < 0 || rank >= m_crashSphereUsed )
- {
- pos = m_objectPart[0].position;
- radius = 0.0f;
- return false;
- }
-
- // Returns to the sphere collisions,
- // which ignores the inclination of the vehicle.
- // This is necessary to collisions with vehicles,
- // so as not to reflect SetInclinaison, for example.
- // The sphere must necessarily have a center (0, y, 0).
- if ( rank == 0 && m_crashSphereUsed == 1 &&
- m_crashSpherePos[0].x == 0.0f &&
- m_crashSpherePos[0].z == 0.0f )
- {
- pos = m_objectPart[0].position + m_crashSpherePos[0];
- radius = m_crashSphereRadius[0];
- return true;
- }
-
- if ( m_objectPart[0].bTranslate ||
- m_objectPart[0].bRotate )
- {
- UpdateTransformObject();
- }
- pos = Math::Transform(m_objectPart[0].matWorld, m_crashSpherePos[rank]);
- radius = m_crashSphereRadius[rank];
- return true;
-}
-
-// Returns the hardness of a sphere.
-
-Sound CObject::RetCrashSphereSound(int rank)
-{
- return m_crashSphereSound[rank];
-}
-
-// Returns the hardness of a sphere.
-
-float CObject::RetCrashSphereHardness(int rank)
-{
- return m_crashSphereHardness[rank];
-}
-
-// Deletes a sphere.
-
-void CObject::DeleteCrashSphere(int rank)
-{
- int i;
-
- if ( rank < 0 || rank >= m_crashSphereUsed ) return;
-
- for ( i=rank+1 ; i<MAXCRASHSPHERE ; i++ )
- {
- m_crashSpherePos[i-1] = m_crashSpherePos[i];
- m_crashSphereRadius[i-1] = m_crashSphereRadius[i];
- }
- m_crashSphereUsed --;
-}
-
-// Specifies the global sphere, relative to the object.
-
-void CObject::SetGlobalSphere(Math::Vector pos, float radius)
-{
- float zoom;
-
- zoom = RetZoomX(0);
- m_globalSpherePos = pos;
- m_globalSphereRadius = radius*zoom;
-}
-
-// Returns the global sphere, in the world.
-
-void CObject::GetGlobalSphere(Math::Vector &pos, float &radius)
-{
- pos = Math::Transform(m_objectPart[0].matWorld, m_globalSpherePos);
- radius = m_globalSphereRadius;
-}
-
-
-// Specifies the sphere of jostling, relative to the object.
-
-void CObject::SetJotlerSphere(Math::Vector pos, float radius)
-{
- m_jotlerSpherePos = pos;
- m_jotlerSphereRadius = radius;
-}
-
-// Specifies the sphere of jostling, in the world.
-
-void CObject::GetJotlerSphere(Math::Vector &pos, float &radius)
-{
- pos = Math::Transform(m_objectPart[0].matWorld, m_jotlerSpherePos);
- radius = m_jotlerSphereRadius;
-}
-
-
-// Specifies the radius of the shield.
-
-void CObject::SetShieldRadius(float radius)
-{
- m_shieldRadius = radius;
-}
-
-// Returns the radius of the shield.
-
-float CObject::RetShieldRadius()
-{
- return m_shieldRadius;
-}
-
-
-// Positioning an object on a certain height, above the ground.
-
-void CObject::SetFloorHeight(float height)
-{
- Math::Vector pos;
-
- pos = m_objectPart[0].position;
- m_terrain->MoveOnFloor(pos);
-
- if ( m_physics != 0 )
- {
- m_physics->SetLand(height == 0.0f);
- m_physics->SetMotor(height != 0.0f);
- }
-
- m_objectPart[0].position.y = pos.y+height+m_character.height;
- m_objectPart[0].bTranslate = true; // it will recalculate the matrices
-}
-
-// Adjust the inclination of an object laying on the ground.
-
-void CObject::FloorAdjust()
-{
- Math::Vector pos, n;
- Math::Point nn;
- float a;
-
- pos = RetPosition(0);
- if ( m_terrain->GetNormal(n, pos) )
- {
-#if 0
- SetAngleX(0, sinf(n.z));
- SetAngleZ(0, -sinf(n.x));
- SetAngleY(0, 0.0f);
-#else
- a = RetAngleY(0);
- nn = Math::RotatePoint(-a, Math::Point(n.z, n.x));
- SetAngleX(0, sinf(nn.x));
- SetAngleZ(0, -sinf(nn.y));
-#endif
- }
-}
-
-
-// Gives the linear vibration.
-
-void CObject::SetLinVibration(Math::Vector dir)
-{
- if ( m_linVibration.x != dir.x ||
- m_linVibration.y != dir.y ||
- m_linVibration.z != dir.z )
- {
- m_linVibration = dir;
- m_objectPart[0].bTranslate = true;
- }
-}
-
-Math::Vector CObject::RetLinVibration()
-{
- return m_linVibration;
-}
-
-// Gives the circular vibration.
-
-void CObject::SetCirVibration(Math::Vector dir)
-{
- if ( m_cirVibration.x != dir.x ||
- m_cirVibration.y != dir.y ||
- m_cirVibration.z != dir.z )
- {
- m_cirVibration = dir;
- m_objectPart[0].bRotate = true;
- }
-}
-
-Math::Vector CObject::RetCirVibration()
-{
- return m_cirVibration;
-}
-
-// Gives the inclination.
-
-void CObject::SetInclinaison(Math::Vector dir)
-{
- if ( m_inclinaison.x != dir.x ||
- m_inclinaison.y != dir.y ||
- m_inclinaison.z != dir.z )
- {
- m_inclinaison = dir;
- m_objectPart[0].bRotate = true;
- }
-}
-
-Math::Vector CObject::RetInclinaison()
-{
- return m_inclinaison;
-}
-
-
-// Gives the position of center of the object.
-
-void CObject::SetPosition(int part, const Math::Vector &pos)
-{
- Math::Vector shPos, n[20], norm;
- float height, radius;
- int rank, i, j;
-
- m_objectPart[part].position = pos;
- m_objectPart[part].bTranslate = true; // it will recalculate the matrices
-
- if ( part == 0 && !m_bFlat ) // main part?
- {
- rank = m_objectPart[0].object;
-
- shPos = pos;
- m_terrain->MoveOnFloor(shPos, true);
- m_engine->SetObjectShadowPos(rank, shPos);
-
- if ( m_physics != 0 && m_physics->RetType() == TYPE_FLYING )
- {
- height = pos.y-shPos.y;
- }
- else
- {
- height = 0.0f;
- }
- m_engine->SetObjectShadowHeight(rank, height);
-
- // Calculating the normal to the ground in nine strategic locations,
- // then perform a weighted average (the dots in the center are more important).
- radius = m_engine->RetObjectShadowRadius(rank);
- i = 0;
-
- m_terrain->GetNormal(norm, pos);
- n[i++] = norm;
- n[i++] = norm;
- n[i++] = norm;
-
- shPos = pos;
- shPos.x += radius*0.6f;
- shPos.z += radius*0.6f;
- m_terrain->GetNormal(norm, shPos);
- n[i++] = norm;
- n[i++] = norm;
-
- shPos = pos;
- shPos.x -= radius*0.6f;
- shPos.z += radius*0.6f;
- m_terrain->GetNormal(norm, shPos);
- n[i++] = norm;
- n[i++] = norm;
-
- shPos = pos;
- shPos.x += radius*0.6f;
- shPos.z -= radius*0.6f;
- m_terrain->GetNormal(norm, shPos);
- n[i++] = norm;
- n[i++] = norm;
-
- shPos = pos;
- shPos.x -= radius*0.6f;
- shPos.z -= radius*0.6f;
- m_terrain->GetNormal(norm, shPos);
- n[i++] = norm;
- n[i++] = norm;
-
- shPos = pos;
- shPos.x += radius;
- shPos.z += radius;
- m_terrain->GetNormal(norm, shPos);
- n[i++] = norm;
-
- shPos = pos;
- shPos.x -= radius;
- shPos.z += radius;
- m_terrain->GetNormal(norm, shPos);
- n[i++] = norm;
-
- shPos = pos;
- shPos.x += radius;
- shPos.z -= radius;
- m_terrain->GetNormal(norm, shPos);
- n[i++] = norm;
-
- shPos = pos;
- shPos.x -= radius;
- shPos.z -= radius;
- m_terrain->GetNormal(norm, shPos);
- n[i++] = norm;
-
- norm.LoadZero();
- for ( j=0 ; j<i ; j++ )
- {
- norm += n[j];
- }
- norm /= (float)i; // average vector
-
- m_engine->SetObjectShadowNormal(rank, norm);
-
- if ( m_shadowLight != -1 )
- {
- shPos = pos;
- shPos.y += m_shadowHeight;
- m_light->SetLightPos(m_shadowLight, shPos);
- }
-
- if ( m_effectLight != -1 )
- {
- shPos = pos;
- shPos.y += m_effectHeight;
- m_light->SetLightPos(m_effectLight, shPos);
- }
-
- if ( m_bShowLimit )
- {
- m_main->AdjustShowLimit(0, pos);
- }
- }
-}
-
-Math::Vector CObject::RetPosition(int part)
-{
- return m_objectPart[part].position;
-}
-
-// Gives the rotation around three axis.
-
-void CObject::SetAngle(int part, const Math::Vector &angle)
-{
- m_objectPart[part].angle = angle;
- m_objectPart[part].bRotate = true; // it will recalculate the matrices
-
- if ( part == 0 && !m_bFlat ) // main part?
- {
- m_engine->SetObjectShadowAngle(m_objectPart[0].object, m_objectPart[0].angle.y);
- }
-}
-
-Math::Vector CObject::RetAngle(int part)
-{
- return m_objectPart[part].angle;
-}
-
-// Gives the rotation about the axis Y.
-
-void CObject::SetAngleY(int part, float angle)
-{
- m_objectPart[part].angle.y = angle;
- m_objectPart[part].bRotate = true; // it will recalculate the matrices
-
- if ( part == 0 && !m_bFlat ) // main part?
- {
- m_engine->SetObjectShadowAngle(m_objectPart[0].object, m_objectPart[0].angle.y);
- }
-}
-
-// Gives the rotation about the axis X.
-
-void CObject::SetAngleX(int part, float angle)
-{
- m_objectPart[part].angle.x = angle;
- m_objectPart[part].bRotate = true; // it will recalculate the matrices
-}
-
-// Gives the rotation about the axis Z.
-
-void CObject::SetAngleZ(int part, float angle)
-{
- m_objectPart[part].angle.z = angle;
- m_objectPart[part].bRotate = true; //it will recalculate the matrices
-}
-
-float CObject::RetAngleY(int part)
-{
- return m_objectPart[part].angle.y;
-}
-
-float CObject::RetAngleX(int part)
-{
- return m_objectPart[part].angle.x;
-}
-
-float CObject::RetAngleZ(int part)
-{
- return m_objectPart[part].angle.z;
-}
-
-
-// Gives the global zoom.
-
-void CObject::SetZoom(int part, float zoom)
-{
- m_objectPart[part].bTranslate = true; // it will recalculate the matrices
- m_objectPart[part].zoom.x = zoom;
- m_objectPart[part].zoom.y = zoom;
- m_objectPart[part].zoom.z = zoom;
-
- m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
- m_objectPart[part].zoom.y != 1.0f ||
- m_objectPart[part].zoom.z != 1.0f );
-}
-
-void CObject::SetZoom(int part, Math::Vector zoom)
-{
- m_objectPart[part].bTranslate = true; // it will recalculate the matrices
- m_objectPart[part].zoom = zoom;
-
- m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
- m_objectPart[part].zoom.y != 1.0f ||
- m_objectPart[part].zoom.z != 1.0f );
-}
-
-Math::Vector CObject::RetZoom(int part)
-{
- return m_objectPart[part].zoom;
-}
-
-void CObject::SetZoomX(int part, float zoom)
-{
- m_objectPart[part].bTranslate = true; // it will recalculate the matrices
- m_objectPart[part].zoom.x = zoom;
-
- m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
- m_objectPart[part].zoom.y != 1.0f ||
- m_objectPart[part].zoom.z != 1.0f );
-}
-
-void CObject::SetZoomY(int part, float zoom)
-{
- m_objectPart[part].bTranslate = true; // it will recalculate the matrices
- m_objectPart[part].zoom.y = zoom;
-
- m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
- m_objectPart[part].zoom.y != 1.0f ||
- m_objectPart[part].zoom.z != 1.0f );
-}
-
-void CObject::SetZoomZ(int part, float zoom)
-{
- m_objectPart[part].bTranslate = true; // it will recalculate the matrices
- m_objectPart[part].zoom.z = zoom;
-
- m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
- m_objectPart[part].zoom.y != 1.0f ||
- m_objectPart[part].zoom.z != 1.0f );
-}
-
-float CObject::RetZoomX(int part)
-{
- return m_objectPart[part].zoom.x;
-}
-
-float CObject::RetZoomY(int part)
-{
- return m_objectPart[part].zoom.y;
-}
-
-float CObject::RetZoomZ(int part)
-{
- return m_objectPart[part].zoom.z;
-}
-
-
-// Returns the water level.
-
-float CObject::RetWaterLevel()
-{
- return m_water->RetLevel();
-}
-
-
-void CObject::SetTrainer(bool bEnable)
-{
- m_bTrainer = bEnable;
-
- if ( m_bTrainer ) // training?
- {
- m_cameraType = CAMERA_FIX;
- }
-}
-
-bool CObject::RetTrainer()
-{
- return m_bTrainer;
-}
-
-void CObject::SetToy(bool bEnable)
-{
- m_bToy = bEnable;
-}
-
-bool CObject::RetToy()
-{
- return m_bToy;
-}
-
-void CObject::SetManual(bool bManual)
-{
- m_bManual = bManual;
-}
-
-bool CObject::RetManual()
-{
- return m_bManual;
-}
-
-void CObject::SetResetCap(ResetCap cap)
-{
- m_resetCap = cap;
-}
-
-ResetCap CObject::RetResetCap()
-{
- return m_resetCap;
-}
-
-void CObject::SetResetBusy(bool bBusy)
-{
- m_bResetBusy = bBusy;
-}
-
-bool CObject::RetResetBusy()
-{
- return m_bResetBusy;
-}
-
-void CObject::SetResetPosition(const Math::Vector &pos)
-{
- m_resetPosition = pos;
-}
-
-Math::Vector CObject::RetResetPosition()
-{
- return m_resetPosition;
-}
-
-void CObject::SetResetAngle(const Math::Vector &angle)
-{
- m_resetAngle = angle;
-}
-
-Math::Vector CObject::RetResetAngle()
-{
- return m_resetAngle;
-}
-
-int CObject::RetResetRun()
-{
- return m_resetRun;
-}
-
-void CObject::SetResetRun(int run)
-{
- m_resetRun = run;
-}
-
-
-// Management of the particle master.
-
-void CObject::SetMasterParticule(int part, int parti)
-{
- m_objectPart[part].masterParti = parti;
-}
-
-int CObject::RetMasterParticule(int part)
-{
- return m_objectPart[part].masterParti;
-}
-
-
-// Management of the stack transport.
-
-void CObject::SetPower(CObject* power)
-{
- m_power = power;
-}
-
-CObject* CObject::RetPower()
-{
- return m_power;
-}
-
-// Management of the object transport.
-
-void CObject::SetFret(CObject* fret)
-{
- m_fret = fret;
-}
-
-CObject* CObject::RetFret()
-{
- return m_fret;
-}
-
-// Management of the object "truck" that transports it.
-
-void CObject::SetTruck(CObject* truck)
-{
- m_truck = truck;
-
- // Invisible shadow if the object is transported.
- m_engine->SetObjectShadowHide(m_objectPart[0].object, (m_truck != 0));
-}
-
-CObject* CObject::RetTruck()
-{
- return m_truck;
-}
-
-// Management of the conveying portion.
-
-void CObject::SetTruckPart(int part)
-{
- m_truckLink = part;
-}
-
-int CObject::RetTruckPart()
-{
- return m_truckLink;
-}
-
-
-// Management of user information.
-
-void CObject::InfoFlush()
-{
- m_infoTotal = 0;
- m_bInfoUpdate = true;
-}
-
-void CObject::DeleteInfo(int rank)
-{
- int i;
-
- if ( rank < 0 || rank >= m_infoTotal ) return;
-
- for ( i=rank ; i<m_infoTotal-1 ; i++ )
- {
- m_info[i] = m_info[i+1];
- }
- m_infoTotal --;
- m_bInfoUpdate = true;
-}
-
-void CObject::SetInfo(int rank, Info info)
-{
- if ( rank < 0 || rank >= OBJECTMAXINFO ) return;
- m_info[rank] = info;
-
- if ( rank+1 > m_infoTotal ) m_infoTotal = rank+1;
- m_bInfoUpdate = true;
-}
-
-Info CObject::RetInfo(int rank)
-{
- if ( rank < 0 || rank >= OBJECTMAXINFO ) rank = 0;
- return m_info[rank];
-}
-
-int CObject::RetInfoTotal()
-{
- return m_infoTotal;
-}
-
-void CObject::SetInfoReturn(float value)
-{
- m_infoReturn = value;
-}
-
-float CObject::RetInfoReturn()
-{
- return m_infoReturn;
-}
-
-void CObject::SetInfoUpdate(bool bUpdate)
-{
- m_bInfoUpdate = bUpdate;
-}
-
-bool CObject::RetInfoUpdate()
-{
- return m_bInfoUpdate;
-}
-
-
-bool CObject::SetCmdLine(int rank, float value)
-{
- if ( rank < 0 || rank >= OBJECTMAXCMDLINE ) return false;
- m_cmdLine[rank] = value;
- return true;
-}
-
-float CObject::RetCmdLine(int rank)
-{
- if ( rank < 0 || rank >= OBJECTMAXCMDLINE ) return 0.0f;
- return m_cmdLine[rank];
-}
-
-
-// Returns matrices of an object portion.
-
-Math::Matrix* CObject::RetRotateMatrix(int part)
-{
- return &m_objectPart[part].matRotate;
-}
-
-Math::Matrix* CObject::RetTranslateMatrix(int part)
-{
- return &m_objectPart[part].matTranslate;
-}
-
-Math::Matrix* CObject::RetTransformMatrix(int part)
-{
- return &m_objectPart[part].matTransform;
-}
-
-Math::Matrix* CObject::RetWorldMatrix(int part)
-{
- if ( m_objectPart[0].bTranslate ||
- m_objectPart[0].bRotate )
- {
- UpdateTransformObject();
- }
-
- return &m_objectPart[part].matWorld;
-}
-
-
-// Indicates whether the object should be drawn below the interface.
-
-void CObject::SetDrawWorld(bool bDraw)
-{
- int i;
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- if ( m_objectPart[i].bUsed )
- {
- m_engine->SetDrawWorld(m_objectPart[i].object, bDraw);
- }
- }
-}
-
-// Indicates whether the object should be drawn over the interface.
-
-void CObject::SetDrawFront(bool bDraw)
-{
- int i;
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- if ( m_objectPart[i].bUsed )
- {
- m_engine->SetDrawFront(m_objectPart[i].object, bDraw);
- }
- }
-}
-
-
-// Creates a vehicle traveling any pose on the floor.
-
-bool CObject::CreateVehicle(Math::Vector pos, float angle, ObjectType type,
- float power, bool bTrainer, bool bToy)
-{
- m_type = type;
-
- if ( type == OBJECT_TOTO )
- {
- m_motion = new CMotionToto(m_iMan, this);
- m_motion->Create(pos, angle, type, 1.0f);
- return true;
- }
-
- SetTrainer(bTrainer);
- SetToy(bToy);
-
- m_physics = new CPhysics(m_iMan, this);
- m_brain = new CBrain(m_iMan, this);
-
- m_physics->SetBrain(m_brain);
- m_brain->SetPhysics(m_physics);
-
-#if 0
- if ( type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ) // fireball cannon?
- {
- m_showLimitRadius = 160.0f;
- }
- if ( type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ) // orgaball cannon?
- {
- m_showLimitRadius = 160.0f;
- }
- if ( type == OBJECT_MOBILErc ) // phazer cannon?
- {
- m_showLimitRadius = 160.0f;
- }
- if ( type == OBJECT_MOBILErs ) // robot shield?
- {
- m_showLimitRadius = 50.0f;
- }
-#endif
- if ( type == OBJECT_MOBILErt ) // robot thumper?
- {
- m_showLimitRadius = 400.0f;
- }
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH )
- {
- m_motion = new CMotionHuman(m_iMan, this);
- }
- else
- {
- m_motion = new CMotionVehicle(m_iMan, this);
- }
- if ( m_motion == 0 ) return false;
-
- m_physics->SetMotion(m_motion);
- m_brain->SetMotion(m_motion);
- m_motion->SetPhysics(m_physics);
- m_motion->SetBrain(m_brain);
- if ( !m_motion->Create(pos, angle, type, power) )
- {
- if ( m_physics != 0 )
- {
- m_physics->DeleteObject();
- delete m_physics;
- m_physics = 0;
- }
- if ( m_brain != 0 )
- {
- m_brain->DeleteObject();
- delete m_brain;
- m_brain = 0;
- }
- if ( m_motion != 0 )
- {
- m_motion->DeleteObject();
- delete m_motion;
- m_motion = 0;
- }
- return false;
- }
-
- return true;
-}
-
-// Creates an insect lands on any ground.
-
-bool CObject::CreateInsect(Math::Vector pos, float angle, ObjectType type)
-{
- m_type = type;
-
- m_physics = new CPhysics(m_iMan, this);
- m_brain = new CBrain(m_iMan, this);
-
- m_physics->SetBrain(m_brain);
- m_brain->SetPhysics(m_physics);
-
- if ( type == OBJECT_MOTHER )
- {
- m_motion = new CMotionMother(m_iMan, this);
- }
- if ( type == OBJECT_ANT )
- {
- m_motion = new CMotionAnt(m_iMan, this);
- }
- if ( type == OBJECT_SPIDER )
- {
- m_motion = new CMotionSpider(m_iMan, this);
- }
- if ( type == OBJECT_BEE )
- {
- m_motion = new CMotionBee(m_iMan, this);
- }
- if ( type == OBJECT_WORM )
- {
- m_motion = new CMotionWorm(m_iMan, this);
- }
- if ( m_motion == 0 ) return false;
-
- m_physics->SetMotion(m_motion);
- m_brain->SetMotion(m_motion);
- m_motion->SetPhysics(m_physics);
- m_motion->SetBrain(m_brain);
- if ( !m_motion->Create(pos, angle, type, 0.0f) )
- {
- if ( m_physics != 0 )
- {
- m_physics->DeleteObject();
- delete m_physics;
- m_physics = 0;
- }
- if ( m_brain != 0 )
- {
- m_brain->DeleteObject();
- delete m_brain;
- m_brain = 0;
- }
- if ( m_motion != 0 )
- {
- m_motion->DeleteObject();
- delete m_motion;
- m_motion = 0;
- }
- return false;
- }
-
- return true;
-}
-
-// Creates shade under a vehicle as a negative light.
-
-bool CObject::CreateShadowLight(float height, D3DCOLORVALUE color)
-{
- D3DLIGHT7 light;
- Math::Vector pos;
-
- if ( !m_engine->RetLightMode() ) return true;
-
- pos = RetPosition(0);
- m_shadowHeight = height;
-
- ZeroMemory( &light, sizeof(light) );
- light.dltType = D3DLIGHT_SPOT;
- light.dcvDiffuse.r = color.r;
- light.dcvDiffuse.g = color.g;
- light.dcvDiffuse.b = color.b;
- light.dvPosition.x = pos.x;
- light.dvPosition.y = pos.y+height;
- light.dvPosition.z = pos.z;
- light.dvDirection.x = 0.0f;
- light.dvDirection.y = -1.0f; // against the bottom
- light.dvDirection.z = 0.0f;
- light.dvRange = D3DLIGHT_RANGE_MAX;
- light.dvFalloff = 1.0f;
- light.dvAttenuation0 = 1.0f;
- light.dvAttenuation1 = 0.0f;
- light.dvAttenuation2 = 0.0f;
- light.dvTheta = 0.0f;
- light.dvPhi = Math::PI/4.0f;
-
- m_shadowLight = m_light->CreateLight();
- if ( m_shadowLight == -1 ) return false;
-
- m_light->SetLight(m_shadowLight, light);
-
- // Only illuminates the objects on the ground.
- m_light->SetLightIncluType(m_shadowLight, TYPETERRAIN);
-
- return true;
-}
-
-// Returns the number of negative light shade.
-
-int CObject::RetShadowLight()
-{
- return m_shadowLight;
-}
-
-// Creates light for the effects of a vehicle.
-
-bool CObject::CreateEffectLight(float height, D3DCOLORVALUE color)
-{
- D3DLIGHT7 light;
-
- if ( !m_engine->RetLightMode() ) return true;
-
- m_effectHeight = height;
-
- ZeroMemory( &light, sizeof(light) );
- light.dltType = D3DLIGHT_SPOT;
- light.dcvDiffuse.r = color.r;
- light.dcvDiffuse.g = color.g;
- light.dcvDiffuse.b = color.b;
- light.dvPosition.x = 0.0f;
- light.dvPosition.y = 0.0f+height;
- light.dvPosition.z = 0.0f;
- light.dvDirection.x = 0.0f;
- light.dvDirection.y = -1.0f; // against the bottom
- light.dvDirection.z = 0.0f;
- light.dvRange = D3DLIGHT_RANGE_MAX;
- light.dvFalloff = 1.0f;
- light.dvAttenuation0 = 1.0f;
- light.dvAttenuation1 = 0.0f;
- light.dvAttenuation2 = 0.0f;
- light.dvTheta = 0.0f;
- light.dvPhi = Math::PI/4.0f;
-
- m_effectLight = m_light->CreateLight();
- if ( m_effectLight == -1 ) return false;
-
- m_light->SetLight(m_effectLight, light);
- m_light->SetLightIntensity(m_effectLight, 0.0f);
-
- return true;
-}
-
-// Returns the number of light effects.
-
-int CObject::RetEffectLight()
-{
- return m_effectLight;
-}
-
-// Creates the circular shadow underneath a vehicle.
-
-bool CObject::CreateShadowCircle(float radius, float intensity,
- D3DShadowType type)
-{
- float zoom;
-
- if ( intensity == 0.0f ) return true;
-
- zoom = RetZoomX(0);
-
- m_engine->ShadowCreate(m_objectPart[0].object);
-
- m_engine->SetObjectShadowRadius(m_objectPart[0].object, radius*zoom);
- m_engine->SetObjectShadowIntensity(m_objectPart[0].object, intensity);
- m_engine->SetObjectShadowHeight(m_objectPart[0].object, 0.0f);
- m_engine->SetObjectShadowAngle(m_objectPart[0].object, m_objectPart[0].angle.y);
- m_engine->SetObjectShadowType(m_objectPart[0].object, type);
-
- return true;
-}
-
-// Creates a building laying on the ground.
-
-bool CObject::CreateBuilding(Math::Vector pos, float angle, float height,
- ObjectType type, float power)
-{
- CModFile* pModFile;
- Math::Point p;
- int rank, i;
-
- if ( m_engine->RetRestCreate() < 20 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
- SetObjectRank(0, rank);
-
- if ( m_type == OBJECT_PORTICO )
- {
- pModFile->ReadModel("objects\\portico1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\portico2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 67.0f, 0.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\portico3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(0.0f, 0.0f, -33.0f));
- SetAngleY(2, 45.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(3, rank);
- SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\portico4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(3, Math::Vector(50.0f, 0.0f, 0.0f));
- SetAngleY(3, -60.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(4, rank);
- SetObjectParent(4, 3);
- pModFile->ReadModel("objects\\portico5.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(4, Math::Vector(35.0f, 0.0f, 0.0f));
- SetAngleY(4, -55.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(5, rank);
- SetObjectParent(5, 1);
- pModFile->ReadModel("objects\\portico3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(5, Math::Vector(0.0f, 0.0f, 33.0f));
- SetAngleY(5, -45.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(6, rank);
- SetObjectParent(6, 5);
- pModFile->ReadModel("objects\\portico4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(6, Math::Vector(50.0f, 0.0f, 0.0f));
- SetAngleY(6, 60.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(7, rank);
- SetObjectParent(7, 6);
- pModFile->ReadModel("objects\\portico5.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(7, Math::Vector(35.0f, 0.0f, 0.0f));
- SetAngleY(7, 55.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(8, rank);
- SetObjectParent(8, 0);
- pModFile->ReadModel("objects\\portico6.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(8, Math::Vector(-35.0f, 50.0f, -35.0f));
- SetAngleY(8, -Math::PI/2.0f);
- SetZoom(8, 2.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(9, rank);
- SetObjectParent(9, 8);
- pModFile->ReadModel("objects\\portico7.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(9, Math::Vector(0.0f, 4.5f, 1.9f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(10, rank);
- SetObjectParent(10, 0);
- pModFile->ReadModel("objects\\portico6.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(10, Math::Vector(-35.0f, 50.0f, 35.0f));
- SetAngleY(10, -Math::PI/2.0f);
- SetZoom(10, 2.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(11, rank);
- SetObjectParent(11, 10);
- pModFile->ReadModel("objects\\portico7.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(11, Math::Vector(0.0f, 4.5f, 1.9f));
-
- CreateCrashSphere(Math::Vector( 0.0f, 28.0f, 0.0f), 45.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 27.0f, 10.0f, -42.0f), 15.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 10.0f, -42.0f), 15.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-27.0f, 10.0f, -42.0f), 15.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 27.0f, 10.0f, 42.0f), 15.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 10.0f, 42.0f), 15.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-27.0f, 10.0f, 42.0f), 15.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-32.0f, 45.0f, -32.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-32.0f, 45.0f, 32.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 32.0f, 45.0f, -32.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 32.0f, 45.0f, 32.0f), 10.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 35.0f, 0.0f), 50.0f);
-
- CreateShadowCircle(50.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_BASE )
- {
- pModFile->ReadModel("objects\\base1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- for ( i=0 ; i<8 ; i++ )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1+i, rank);
- SetObjectParent(1+i, 0);
- pModFile->ReadModel("objects\\base2.mod");
- pModFile->CreateEngineObject(rank);
- p = Math::RotatePoint(-Math::PI/4.0f*i, 27.8f);
- SetPosition(1+i, Math::Vector(p.x, 30.0f, p.y));
- SetAngleY(1+i, Math::PI/4.0f*i);
- SetAngleZ(1+i, Math::PI/2.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(10+i, rank);
- SetObjectParent(10+i, 1+i);
- pModFile->ReadModel("objects\\base4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(10+i, Math::Vector(23.5f, 0.0f, 7.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(18+i, rank);
- SetObjectParent(18+i, 1+i);
- pModFile->ReadModel("objects\\base4.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- SetPosition(18+i, Math::Vector(23.5f, 0.0f, -7.0f));
- }
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(9, rank);
- SetObjectParent(9, 0);
- pModFile->ReadModel("objects\\base3.mod"); // central pillar
- pModFile->CreateEngineObject(rank);
-
- CreateCrashSphere(Math::Vector( 0.0f, 33.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 39.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 45.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 51.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 57.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 63.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 69.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 82.0f, 0.0f), 8.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 18.0f, 94.0f, 0.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-18.0f, 94.0f, 0.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 94.0f, 18.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 94.0f, -18.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 13.0f, 94.0f, 13.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-13.0f, 94.0f, 13.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 13.0f, 94.0f, -13.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-13.0f, 94.0f, -13.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f,104.0f, 0.0f), 14.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 45.0f, 0.0f), 10.0f);
-
- CreateShadowCircle(60.0f, 1.0f);
- m_showLimitRadius = 200.0f;
-
- m_terrain->AddBuildingLevel(pos, 28.6f, 73.4f, 30.0f, 0.4f);
- }
-
- if ( m_type == OBJECT_DERRICK )
- {
- pModFile->ReadModel("objects\\derrick1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\derrick2.mod");
- pModFile->CreateEngineObject(rank);
-
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 17.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 26.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(7.0f, 17.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 10.0f);
-
- CreateShadowCircle(10.0f, 0.4f);
- }
-
- if ( m_type == OBJECT_RESEARCH )
- {
- pModFile->ReadModel("objects\\search1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\search2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 13.0f, 0.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\search3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(0.0f, 4.0f, 0.0f));
- SetAngleZ(2, 35.0f*Math::PI/180.0f);
-
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 6.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 14.0f, 0.0f), 7.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 8.0f, 0.0f), 12.0f);
-
- m_character.posPower = Math::Vector(7.5f, 3.0f, 0.0f);
-
- CreateShadowCircle(12.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_RADAR )
- {
- pModFile->ReadModel("objects\\radar1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\radar2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 5.0f, 0.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\radar3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(0.0f, 11.0f, 0.0f));
- SetAngleY(2, -Math::PI/2.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(3, rank);
- SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\radar4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(3, Math::Vector(0.0f, 4.5f, 1.9f));
-
- CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 11.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 7.0f, 0.0f), 7.0f);
-
- CreateShadowCircle(8.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_INFO )
- {
- pModFile->ReadModel("objects\\info1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\info2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 5.0f, 0.0f));
-
- for ( i=0 ; i<3 ; i++ )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2+i*2, rank);
- SetObjectParent(2+i*2, 1);
- pModFile->ReadModel("objects\\info3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(2+i*2, Math::Vector(0.0f, 4.5f, 0.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(3+i*2, rank);
- SetObjectParent(3+i*2, 2+i*2);
- pModFile->ReadModel("objects\\radar4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(3+i*2, Math::Vector(0.0f, 0.0f, -4.0f));
-
- SetAngleY(2+i*2, 2.0f*Math::PI/3.0f*i);
- }
-
- CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 11.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 6.0f);
-
- CreateShadowCircle(8.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_ENERGY )
- {
- pModFile->ReadModel("objects\\energy.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- CreateCrashSphere(Math::Vector(-2.0f, 13.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-7.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(-7.0f, 5.0f, 0.0f), 5.0f);
-
- m_character.posPower = Math::Vector(0.0f, 3.0f, 0.0f);
- m_energy = power; // initializes the energy level
-
- CreateShadowCircle(6.0f, 0.5f);
- }
-
- if ( m_type == OBJECT_LABO )
- {
- pModFile->ReadModel("objects\\labo1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\labo2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(-9.0f, 3.0f, 0.0f));
- SetAngleZ(1, Math::PI/2.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\labo3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(9.0f, -1.0f, 0.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(3, rank);
- SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\labo4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(3, Math::Vector(0.0f, 0.0f, 0.0f));
- SetAngleZ(3, 80.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(4, rank);
- SetObjectParent(4, 2);
- pModFile->ReadModel("objects\\labo4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(4, Math::Vector(0.0f, 0.0f, 0.0f));
- SetAngleZ(4, 80.0f*Math::PI/180.0f);
- SetAngleY(4, Math::PI*2.0f/3.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(5, rank);
- SetObjectParent(5, 2);
- pModFile->ReadModel("objects\\labo4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(5, Math::Vector(0.0f, 0.0f, 0.0f));
- SetAngleZ(5, 80.0f*Math::PI/180.0f);
- SetAngleY(5, -Math::PI*2.0f/3.0f);
-
- CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 11.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 10.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-12.0f, 3.0f, 3.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-12.0f, 3.0f, -3.0f), 4.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(-10.0f, 5.0f, 0.0f), 7.0f);
-
- m_character.posPower = Math::Vector(0.0f, 3.0f, 0.0f);
-
- CreateShadowCircle(7.0f, 0.5f);
- }
-
- if ( m_type == OBJECT_FACTORY )
- {
- pModFile->ReadModel("objects\\factory1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- for ( i=0 ; i<9 ; i++ )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1+i, rank);
- SetObjectParent(1+i, 0);
- pModFile->ReadModel("objects\\factory2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1+i, Math::Vector(10.0f, 2.0f*i, 10.0f));
- SetAngleZ(1+i, Math::PI/2.0f);
- SetZoomZ(1+i, 0.30f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(10+i, rank);
- SetObjectParent(10+i, 0);
- pModFile->ReadModel("objects\\factory2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(10+i, Math::Vector(10.0f, 2.0f*i, -10.0f));
- SetAngleZ(10+i, -Math::PI/2.0f);
- SetAngleY(10+i, Math::PI);
- SetZoomZ(10+i, 0.30f);
- }
-
- for ( i=0 ; i<2 ; i++ )
- {
- float s = (float)(i*2-1);
- CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -3.0f, 2.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.0f, 2.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 2.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 9.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -3.0f, 9.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.0f, 9.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 9.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 16.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -3.0f, 16.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.0f, 16.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 16.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 16.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -3.0f, 16.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.0f, 16.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 16.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 9.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- }
- CreateCrashSphere(Math::Vector(-10.0f, 21.0f, -4.0f), 3.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 18.0f);
-
- CreateShadowCircle(24.0f, 0.3f);
- }
-
- if ( m_type == OBJECT_REPAIR )
- {
- pModFile->ReadModel("objects\\repair1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\repair2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(-11.0f, 13.5f, 0.0f));
- SetAngleZ(1, Math::PI/2.0f);
-
- m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
-
- CreateCrashSphere(Math::Vector(-11.0f, 0.0f, 4.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 0.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 0.0f, -4.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 10.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(-11.0f, 13.0f, 0.0f), 15.0f);
- }
-
- if ( m_type == OBJECT_DESTROYER )
- {
- pModFile->ReadModel("objects\\destroy1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\destroy2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 0.0f, 0.0f));
-
- m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
-
- CreateCrashSphere(Math::Vector(-3.5f, 0.0f, -13.5f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.5f, 0.0f, -13.5f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-3.5f, 0.0f, 13.5f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.5f, 0.0f, 13.5f), 4.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(19.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_STATION )
- {
- pModFile->ReadModel("objects\\station.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
-
- CreateCrashSphere(Math::Vector(-15.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-15.0f, 6.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(-15.0f, 5.0f, 0.0f), 6.0f);
-
- m_energy = power; // initialise le niveau d'�nergie
- }
-
- if ( m_type == OBJECT_CONVERT )
- {
- pModFile->ReadModel("objects\\convert1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\convert2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 14.0f, 0.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\convert3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(0.0f, 11.5f, 0.0f));
- SetAngleX(2, -Math::PI*0.35f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(3, rank);
- SetObjectParent(3, 0);
- pModFile->ReadModel("objects\\convert3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(3, Math::Vector(0.0f, 11.5f, 0.0f));
- SetAngleY(3, Math::PI);
- SetAngleX(3, -Math::PI*0.35f);
-
- m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
-
- CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 4.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 2.0f, -4.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 9.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 14.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(-3.0f, 8.0f, 0.0f), 14.0f);
- }
-
- if ( m_type == OBJECT_TOWER )
- {
- pModFile->ReadModel("objects\\tower.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\roller2c.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 20.0f, 0.0f));
- SetAngleZ(1, Math::PI/2.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\roller3c.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(4.5f, 0.0f, 0.0f));
- SetAngleZ(2, 0.0f);
-
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 6.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 8.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 15.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 24.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 7.0f);
-
- m_character.posPower = Math::Vector(5.0f, 3.0f, 0.0f);
-
- CreateShadowCircle(6.0f, 1.0f);
- m_showLimitRadius = BLITZPARA;
- }
-
- if ( m_type == OBJECT_NUCLEAR )
- {
- pModFile->ReadModel("objects\\nuclear1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\nuclear2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(20.0f, 10.0f, 0.0f));
- SetAngleZ(1, 135.0f*Math::PI/180.0f);
-
- CreateCrashSphere(Math::Vector( 0.0f, 0.0f, 0.0f), 19.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 24.0f, 0.0f), 15.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(22.0f, 1.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 17.0f, 0.0f), 26.0f);
-
- m_character.posPower = Math::Vector(22.0f, 3.0f, 0.0f);
-
- CreateShadowCircle(21.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_PARA )
- {
- pModFile->ReadModel("objects\\para.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- m_terrain->AddBuildingLevel(pos, 16.0f, 18.0f, 1.0f, 0.5f);
-
- CreateCrashSphere(Math::Vector( 13.0f, 3.0f, 13.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 11.0f, 15.0f, 11.0f), 2.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-13.0f, 3.0f, 13.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 15.0f, -11.0f), 2.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 13.0f, 3.0f, -13.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 11.0f, 15.0f, -11.0f), 2.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-13.0f, 3.0f, -13.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 15.0f, -11.0f), 2.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 26.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 54.0f, 0.0f), 14.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 20.0f);
-
- CreateShadowCircle(21.0f, 1.0f);
- m_showLimitRadius = BLITZPARA;
- }
-
- if ( m_type == OBJECT_SAFE )
- {
- pModFile->ReadModel("objects\\safe1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\safe2.mod");
- pModFile->CreateEngineObject(rank);
- SetZoom(1, 1.05f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\safe3.mod");
- pModFile->CreateEngineObject(rank);
- SetZoom(2, 1.05f);
-
- m_terrain->AddBuildingLevel(pos, 18.0f, 20.0f, 1.0f, 0.5f);
-
- CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 13.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 13.0f);
-
- CreateShadowCircle(23.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_HUSTON )
- {
- pModFile->ReadModel("objects\\huston1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\huston2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 39.0f, 30.0f));
- SetAngleY(1, -Math::PI/2.0f);
- SetZoom(1, 3.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\huston3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(0.0f, 4.5f, 1.9f));
-
- CreateCrashSphere(Math::Vector( 15.0f, 6.0f, -53.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-15.0f, 6.0f, -53.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 15.0f, 6.0f, -26.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-15.0f, 6.0f, -26.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 15.0f, 6.0f, 0.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-15.0f, 6.0f, 0.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 15.0f, 6.0f, 26.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-15.0f, 6.0f, 26.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 15.0f, 6.0f, 53.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-15.0f, 6.0f, 53.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 27.0f, 30.0f), 12.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 45.0f, 30.0f), 14.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 26.0f, 4.0f, -61.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-26.0f, 4.0f, -61.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 26.0f, 4.0f, 61.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-26.0f, 4.0f, 61.0f), 5.0f, SOUND_BOUMm, 0.45f);
- }
-
- if ( m_type == OBJECT_TARGET1 )
- {
- pModFile->ReadModel("objects\\target1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 1.5f);
- SetFloorHeight(0.0f);
-
- CreateCrashSphere(Math::Vector( 0.0f, 50.0f+14.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -7.0f, 50.0f+12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 7.0f, 50.0f+12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-12.0f, 50.0f+ 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 12.0f, 50.0f+ 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-14.0f, 50.0f+ 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 14.0f, 50.0f+ 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-12.0f, 50.0f- 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 12.0f, 50.0f- 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -7.0f, 50.0f-12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 7.0f, 50.0f-12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 50.0f-14.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
-
- CreateCrashSphere(Math::Vector(0.0f, 30.0f, 0.0f), 2.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 24.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 16.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 8.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(15.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_TARGET2 )
- {
- pModFile->ReadModel("objects\\target2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- height += 50.0f*1.5f;
- }
-
- if ( m_type == OBJECT_NEST )
- {
- pModFile->ReadModel("objects\\nest.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- m_terrain->AddBuildingLevel(pos, 3.0f, 5.0f, 1.0f, 0.5f);
-
- CreateShadowCircle(4.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_START )
- {
- pModFile->ReadModel("objects\\start.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
- }
-
- if ( m_type == OBJECT_END )
- {
- pModFile->ReadModel("objects\\end.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
- }
-
-#if 0
- if ( power > 0.0f ) // creates a battery?
- {
- CObject* pPower;
-
- pPower = new CObject(m_iMan);
- pPower->SetType(power<=1.0f?OBJECT_POWER:OBJECT_ATOMIC);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- pPower->SetObjectRank(0, rank);
-
- if ( power <= 1.0f ) pModFile->ReadModel("objects\\power.mod");
- else pModFile->ReadModel("objects\\atomic.mod");
- pModFile->CreateEngineObject(rank);
-
- pPower->SetPosition(0, RetCharacter()->posPower);
- pPower->CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- pPower->SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.5f);
-
- pPower->SetTruck(this);
- SetPower(pPower);
-
- if ( power <= 1.0f ) pPower->SetEnergy(power);
- else pPower->SetEnergy(power/100.0f);
- }
-#endif
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos); // to display the shadows immediately
-
- CreateOtherObject(type);
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-// Creates a small resource set on the ground.
-
-bool CObject::CreateResource(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- char name[50];
- int rank;
- float radius, height;
-
- if ( type != OBJECT_SHOW )
- {
- if ( m_engine->RetRestCreate() < 1 ) return false;
- }
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
- SetObjectRank(0, rank);
- SetEnergy(power);
-
- name[0] = 0;
- if ( type == OBJECT_STONE ) strcpy(name, "objects\\stone.mod");
- if ( type == OBJECT_URANIUM ) strcpy(name, "objects\\uranium.mod");
- if ( type == OBJECT_METAL ) strcpy(name, "objects\\metal.mod");
- if ( type == OBJECT_POWER ) strcpy(name, "objects\\power.mod");
- if ( type == OBJECT_ATOMIC ) strcpy(name, "objects\\atomic.mod");
- if ( type == OBJECT_BULLET ) strcpy(name, "objects\\bullet.mod");
- if ( type == OBJECT_BBOX ) strcpy(name, "objects\\bbox.mod");
- if ( type == OBJECT_KEYa ) strcpy(name, "objects\\keya.mod");
- if ( type == OBJECT_KEYb ) strcpy(name, "objects\\keyb.mod");
- if ( type == OBJECT_KEYc ) strcpy(name, "objects\\keyc.mod");
- if ( type == OBJECT_KEYd ) strcpy(name, "objects\\keyd.mod");
- if ( type == OBJECT_TNT ) strcpy(name, "objects\\tnt.mod");
- if ( type == OBJECT_SCRAP1 ) strcpy(name, "objects\\scrap1.mod");
- if ( type == OBJECT_SCRAP2 ) strcpy(name, "objects\\scrap2.mod");
- if ( type == OBJECT_SCRAP3 ) strcpy(name, "objects\\scrap3.mod");
- if ( type == OBJECT_SCRAP4 ) strcpy(name, "objects\\scrap4.mod");
- if ( type == OBJECT_SCRAP5 ) strcpy(name, "objects\\scrap5.mod");
- if ( type == OBJECT_BOMB ) strcpy(name, "objects\\bomb.mod");
- if ( type == OBJECT_WAYPOINT ) strcpy(name, "objects\\waypoint.mod");
- if ( type == OBJECT_SHOW ) strcpy(name, "objects\\show.mod");
- if ( type == OBJECT_WINFIRE ) strcpy(name, "objects\\winfire.mod");
- if ( type == OBJECT_BAG ) strcpy(name, "objects\\bag.mod");
- if ( type == OBJECT_MARKSTONE ) strcpy(name, "objects\\cross1.mod");
- if ( type == OBJECT_MARKURANIUM ) strcpy(name, "objects\\cross3.mod");
- if ( type == OBJECT_MARKPOWER ) strcpy(name, "objects\\cross2.mod");
- if ( type == OBJECT_MARKKEYa ) strcpy(name, "objects\\crossa.mod");
- if ( type == OBJECT_MARKKEYb ) strcpy(name, "objects\\crossb.mod");
- if ( type == OBJECT_MARKKEYc ) strcpy(name, "objects\\crossc.mod");
- if ( type == OBJECT_MARKKEYd ) strcpy(name, "objects\\crossd.mod");
- if ( type == OBJECT_EGG ) strcpy(name, "objects\\egg.mod");
-
- pModFile->ReadModel(name);
- pModFile->CreateEngineObject(rank);
-
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- if ( type == OBJECT_SHOW ) // remains in the air?
- {
- delete pModFile;
- return true;
- }
-
- radius = 1.5f;
- height = 0.0f;
-
- if ( type == OBJECT_MARKSTONE ||
- type == OBJECT_MARKURANIUM ||
- type == OBJECT_MARKKEYa ||
- type == OBJECT_MARKKEYb ||
- type == OBJECT_MARKKEYc ||
- type == OBJECT_MARKKEYd ||
- type == OBJECT_MARKPOWER ||
- type == OBJECT_WAYPOINT )
- {
- }
- else if ( type == OBJECT_EGG )
- {
- CreateCrashSphere(Math::Vector(-1.0f, 2.8f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
- radius = 3.0f;
- }
- else if ( type == OBJECT_BOMB )
- {
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 3.0f);
- radius = 3.0f;
- }
- else if ( type == OBJECT_BAG )
- {
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f);
- SetZoom(0, 1.5f);
- radius = 5.0f;
- height = -1.4f;
- }
- else
- {
- CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.5f);
- }
- CreateShadowCircle(radius, 1.0f);
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
- m_engine->LoadAllTexture();
- FloorAdjust();
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos); // to display the shadows immediately
-
- delete pModFile;
- return true;
-}
-
-// Creates a flag placed on the ground.
-
-bool CObject::CreateFlag(Math::Vector pos, float angle, ObjectType type)
-{
- CModFile* pModFile;
- char name[50];
- int rank, i;
-
- if ( m_engine->RetRestCreate() < 1+4 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- name[0] = 0;
- if ( type == OBJECT_FLAGb ) strcpy(name, "objects\\flag1b.mod");
- if ( type == OBJECT_FLAGr ) strcpy(name, "objects\\flag1r.mod");
- if ( type == OBJECT_FLAGg ) strcpy(name, "objects\\flag1g.mod");
- if ( type == OBJECT_FLAGy ) strcpy(name, "objects\\flag1y.mod");
- if ( type == OBJECT_FLAGv ) strcpy(name, "objects\\flag1v.mod");
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
- SetObjectRank(0, rank);
- pModFile->ReadModel(name);
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- name[0] = 0;
- if ( type == OBJECT_FLAGb ) strcpy(name, "objects\\flag2b.mod");
- if ( type == OBJECT_FLAGr ) strcpy(name, "objects\\flag2r.mod");
- if ( type == OBJECT_FLAGg ) strcpy(name, "objects\\flag2g.mod");
- if ( type == OBJECT_FLAGy ) strcpy(name, "objects\\flag2y.mod");
- if ( type == OBJECT_FLAGv ) strcpy(name, "objects\\flag2v.mod");
-
- for ( i=0 ; i<4 ; i++ )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1+i, rank);
- SetObjectParent(1+i, i);
- pModFile->ReadModel(name);
- pModFile->CreateEngineObject(rank);
- if ( i == 0 ) SetPosition(1+i, Math::Vector(0.15f, 5.0f, 0.0f));
- else SetPosition(1+i, Math::Vector(0.79f, 0.0f, 0.0f));
- }
-
- SetJotlerSphere(Math::Vector(0.0f, 4.0f, 0.0f), 1.0f);
- CreateShadowCircle(2.0f, 0.3f);
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
- m_engine->LoadAllTexture();
- FloorAdjust();
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- delete pModFile;
- return true;
-}
-
-// Creates a barrier placed on the ground.
-
-bool CObject::CreateBarrier(Math::Vector pos, float angle, float height,
- ObjectType type)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- if ( type == OBJECT_BARRIER0 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\barrier0.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(6.0f, 0.5f, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_BARRIER1 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\barrier1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector( 8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(12.0f, 0.5f, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_BARRIER2 ) // cardboard?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\barrier2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector( 8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(12.0f, 0.8f, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_BARRIER3 ) // match + straw?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\barrier3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector( 8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(10.0f, 0.5f, D3DSHADOWWORM);
- }
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
- FloorAdjust();
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos);
-
- delete pModFile;
- return true;
-}
-
-// Creates a plant placed on the ground.
-
-bool CObject::CreatePlant(Math::Vector pos, float angle, float height,
- ObjectType type)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- if ( type == OBJECT_PLANT0 ||
- type == OBJECT_PLANT1 ||
- type == OBJECT_PLANT2 ||
- type == OBJECT_PLANT3 ||
- type == OBJECT_PLANT4 ) // standard?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- if ( type == OBJECT_PLANT0 ) pModFile->ReadModel("objects\\plant0.mod");
- if ( type == OBJECT_PLANT1 ) pModFile->ReadModel("objects\\plant1.mod");
- if ( type == OBJECT_PLANT2 ) pModFile->ReadModel("objects\\plant2.mod");
- if ( type == OBJECT_PLANT3 ) pModFile->ReadModel("objects\\plant3.mod");
- if ( type == OBJECT_PLANT4 ) pModFile->ReadModel("objects\\plant4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- height -= 2.0f;
-
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f);
- SetJotlerSphere(Math::Vector(0.0f, 0.0f, 0.0f), 8.0f);
-
- CreateShadowCircle(8.0f, 0.5f);
- }
-
- if ( type == OBJECT_PLANT5 ||
- type == OBJECT_PLANT6 ||
- type == OBJECT_PLANT7 ) // clover?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- if ( type == OBJECT_PLANT5 ) pModFile->ReadModel("objects\\plant5.mod");
- if ( type == OBJECT_PLANT6 ) pModFile->ReadModel("objects\\plant6.mod");
- if ( type == OBJECT_PLANT7 ) pModFile->ReadModel("objects\\plant7.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
-//? CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 3.0f, SOUND_BOUM, 0.10f);
- SetJotlerSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f);
-
- CreateShadowCircle(5.0f, 0.3f);
- }
-
- if ( type == OBJECT_PLANT8 ||
- type == OBJECT_PLANT9 ) // squash?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- if ( type == OBJECT_PLANT8 ) pModFile->ReadModel("objects\\plant8.mod");
- if ( type == OBJECT_PLANT9 ) pModFile->ReadModel("objects\\plant9.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
-
- CreateShadowCircle(10.0f, 0.5f);
- }
-
- if ( type == OBJECT_PLANT10 ||
- type == OBJECT_PLANT11 ||
- type == OBJECT_PLANT12 ||
- type == OBJECT_PLANT13 ||
- type == OBJECT_PLANT14 ) // succulent?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- if ( type == OBJECT_PLANT10 ) pModFile->ReadModel("objects\\plant10.mod");
- if ( type == OBJECT_PLANT11 ) pModFile->ReadModel("objects\\plant11.mod");
- if ( type == OBJECT_PLANT12 ) pModFile->ReadModel("objects\\plant12.mod");
- if ( type == OBJECT_PLANT13 ) pModFile->ReadModel("objects\\plant13.mod");
- if ( type == OBJECT_PLANT14 ) pModFile->ReadModel("objects\\plant14.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 12.0f, 0.0f), 5.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 6.0f);
- SetJotlerSphere(Math::Vector(0.0f, 4.0f, 0.0f), 8.0f);
-
- CreateShadowCircle(8.0f, 0.3f);
- }
-
- if ( type == OBJECT_PLANT15 ||
- type == OBJECT_PLANT16 ||
- type == OBJECT_PLANT17 ||
- type == OBJECT_PLANT18 ||
- type == OBJECT_PLANT19 ) // fern?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- if ( type == OBJECT_PLANT15 ) pModFile->ReadModel("objects\\plant15.mod");
- if ( type == OBJECT_PLANT16 ) pModFile->ReadModel("objects\\plant16.mod");
- if ( type == OBJECT_PLANT17 ) pModFile->ReadModel("objects\\plant17.mod");
- if ( type == OBJECT_PLANT18 ) pModFile->ReadModel("objects\\plant18.mod");
- if ( type == OBJECT_PLANT19 ) pModFile->ReadModel("objects\\plant19.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- if ( type != OBJECT_PLANT19 )
- {
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f);
- }
- SetJotlerSphere(Math::Vector(0.0f, 0.0f, 0.0f), 8.0f);
-
- CreateShadowCircle(8.0f, 0.5f);
- }
-
- if ( type == OBJECT_TREE0 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\tree0.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 2.0f), 3.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(-1.0f, 10.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 0.0f, 17.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 1.0f, 27.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
-
- CreateShadowCircle(8.0f, 0.5f);
- }
-
- if ( type == OBJECT_TREE1 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\tree1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 2.0f), 3.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(-2.0f, 11.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(-2.0f, 19.0f, 2.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 2.0f, 26.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 2.0f, 34.0f,-2.0f), 2.0f, SOUND_BOUMs, 0.20f);
-
- CreateShadowCircle(8.0f, 0.5f);
- }
-
- if ( type == OBJECT_TREE2 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\tree2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 1.0f), 3.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(-2.0f, 10.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(-2.0f, 19.0f, 2.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 2.0f, 25.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 3.0f, 32.0f,-2.0f), 2.0f, SOUND_BOUMs, 0.20f);
-
- CreateShadowCircle(8.0f, 0.5f);
- }
-
- if ( type == OBJECT_TREE3 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\tree3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(-2.0f, 3.0f, 2.0f), 3.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(-3.0f, 9.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 0.0f, 18.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 0.0f, 27.0f, 7.0f), 2.0f, SOUND_BOUMs, 0.20f);
-
- CreateShadowCircle(8.0f, 0.5f);
- }
-
- if ( type == OBJECT_TREE4 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\tree4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 10.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(0.0f, 21.0f, 0.0f), 8.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(0.0f, 32.0f, 0.0f), 7.0f, SOUND_BOUMs, 0.20f);
-
- CreateShadowCircle(8.0f, 0.5f);
- }
-
- if ( type == OBJECT_TREE5 ) // giant tree (for the world "teen")
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\tree5.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector( 0.0f, 5.0f,-10.0f), 25.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(-65.0f, 5.0f, 65.0f), 20.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 38.0f, 5.0f, 21.0f), 18.0f, SOUND_BOUMs, 0.20f);
-
- CreateShadowCircle(50.0f, 0.5f);
- }
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos);
-
- delete pModFile;
- return true;
-}
-
-// Creates a mushroom placed on the ground.
-
-bool CObject::CreateMushroom(Math::Vector pos, float angle, float height,
- ObjectType type)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- if ( type == OBJECT_MUSHROOM1 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\mush1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 3.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 5.5f);
- SetJotlerSphere(Math::Vector(0.0f, 3.0f, 0.0f), 5.5f);
-
- CreateShadowCircle(6.0f, 0.5f);
- }
-
- if ( type == OBJECT_MUSHROOM2 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\mush2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 5.0f, 0.0f), 3.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 5.5f);
- SetJotlerSphere(Math::Vector(0.0f, 4.0f, 0.0f), 5.5f);
-
- CreateShadowCircle(5.0f, 0.5f);
- }
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos);
-
- delete pModFile;
- return true;
-}
-
-// Creates a toy placed on the ground.
-
-bool CObject::CreateTeen(Math::Vector pos, float angle, float zoom, float height,
- ObjectType type)
-{
- CModFile* pModFile;
- Math::Matrix* mat;
- D3DCOLORVALUE color;
- int rank;
- float fShadow;
- bool bFloorAdjust = true;
-
- if ( m_engine->RetRestCreate() < 1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- fShadow = Math::Norm(1.0f-height/10.0f);
-
- if ( type == OBJECT_TEEN0 ) // orange pencil lg=10
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen0.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 5.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 2.5f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-2.5f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(5.0f, 0.8f*fShadow, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_TEEN1 ) // blue pencil lg=14
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 6.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 2.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-2.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-4.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-6.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(6.0f, 0.8f*fShadow, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_TEEN2 ) // red pencil lg=16
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 7.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.7f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 2.3f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-2.3f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-4.7f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-7.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(6.0f, 0.8f*fShadow, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_TEEN3 ) // jar with pencils
- {
- rank = m_engine->CreateObject();
-//? m_engine->SetObjectType(rank, TYPEFIX);
- m_engine->SetObjectType(rank, TYPEMETAL);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 4.0f);
- CreateShadowCircle(6.0f, 0.5f*fShadow);
- }
-
- if ( type == OBJECT_TEEN4 ) // scissors
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-9.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-6.0f, 1.0f, 0.0f), 1.1f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-3.0f, 1.0f, 0.0f), 1.2f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.3f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 5.1f, 1.0f,-1.3f), 2.6f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 8.0f, 1.0f, 2.2f), 2.3f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 9.4f, 1.0f,-2.0f), 2.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(10.0f, 0.5f*fShadow, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_TEEN5 ) // CD
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen5.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
- SetFloorHeight(0.0f);
- bFloorAdjust = false;
-
- m_terrain->AddBuildingLevel(pos, 5.9f, 6.1f, 0.2f, 0.5f);
- CreateShadowCircle(8.0f, 0.2f*fShadow);
- }
-
- if ( type == OBJECT_TEEN6 ) // book 1
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen6.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(20.0f, 0.2f*fShadow);
- }
-
- if ( type == OBJECT_TEEN7 ) // book 2
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen7.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(20.0f, 0.2f*fShadow);
- }
-
- if ( type == OBJECT_TEEN8 ) // a stack of books 1
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen8.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 12.0f);
- CreateShadowCircle(20.0f, 0.2f*fShadow);
- }
-
- if ( type == OBJECT_TEEN9 ) // a stack of books 2
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen9.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 12.0f);
- CreateShadowCircle(20.0f, 0.2f*fShadow);
- }
-
- if ( type == OBJECT_TEEN10 ) // bookcase
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen10.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-26.0f, 3.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-15.0f, 3.0f,-4.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-15.0f, 3.0f, 5.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -4.0f, 3.0f,-4.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -4.0f, 3.0f, 5.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 6.0f, 3.0f,-4.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 6.0f, 3.0f, 4.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 14.0f, 3.0f,-3.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 14.0f, 3.0f, 2.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 24.0f, 3.0f, 5.0f), 6.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 20.0f);
- CreateShadowCircle(40.0f, 0.2f*fShadow);
- }
-
- if ( type == OBJECT_TEEN11 ) // lamp
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen11.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
- SetZoom(0, zoom);
-
- mat = RetWorldMatrix(0);
- pos = Math::Transform(*mat, Math::Vector(-56.0f, 22.0f, 0.0f));
- m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(20.0f, 20.0f), PARTISELY, 1.0f, 0.0f, 0.0f);
-
- pos = Math::Transform(*mat, Math::Vector(-65.0f, 40.0f, 0.0f));
- color.r = 4.0f;
- color.g = 2.0f;
- color.b = 0.0f; // yellow-orange
- color.a = 0.0f;
- m_main->CreateSpot(pos, color);
- }
-
- if ( type == OBJECT_TEEN12 ) // coke
- {
- rank = m_engine->CreateObject();
-//? m_engine->SetObjectType(rank, TYPEFIX);
- m_engine->SetObjectType(rank, TYPEMETAL);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen12.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 9.0f, 0.0f), 5.0f);
- CreateShadowCircle(4.5f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN13 ) // cardboard farm
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen13.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 15.0f);
- CreateShadowCircle(20.0f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN14 ) // open box
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen14.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 15.0f);
- CreateShadowCircle(20.0f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN15 ) // stack of cartons
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen15.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 15.0f);
- CreateShadowCircle(20.0f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN16 ) // watering can
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen16.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-8.0f, 4.0f, 0.0f), 12.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 8.0f, 4.0f, 0.0f), 12.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 13.0f, 0.0f), 20.0f);
- CreateShadowCircle(18.0f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN17 ) // wheel |
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen17.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 0.0f, 31.0f, 0.0f), 31.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 31.0f, 0.0f), 31.0f);
- CreateShadowCircle(24.0f, 0.5f*fShadow);
- }
-
- if ( type == OBJECT_TEEN18 ) // wheel /
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen18.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 0.0f, 31.0f, 0.0f), 31.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 31.0f, 0.0f), 31.0f);
- CreateShadowCircle(24.0f, 0.5f*fShadow);
- }
-
- if ( type == OBJECT_TEEN19 ) // wheel =
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen19.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 0.0f, 10.0f, 0.0f), 32.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 32.0f);
- CreateShadowCircle(33.0f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN20 ) // wall with shelf
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen20.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-175.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-175.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -55.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -55.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -37.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -37.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 83.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 83.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
- }
-
- if ( type == OBJECT_TEEN21 ) // wall with window
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen21.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
- }
-
- if ( type == OBJECT_TEEN22 ) // wall with door and shelf
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen22.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-135.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-135.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -15.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -15.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
- }
-
- if ( type == OBJECT_TEEN23 ) // skateboard on wheels
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen23.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- if ( m_option == 1 ) // passage under the prohibited skateboard?
- {
- CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 0.0f), 11.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 2.0f, 0.0f), 11.0f, SOUND_BOUMm, 0.45f);
- }
-
- CreateCrashSphere(Math::Vector(-23.0f, 2.0f, 7.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-23.0f, 2.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-23.0f, 2.0f,-7.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 23.0f, 2.0f, 7.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 23.0f, 2.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 23.0f, 2.0f,-7.0f), 3.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(35.0f, 0.8f*fShadow, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_TEEN24 ) // skate /
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen24.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-12.0f, 0.0f, -3.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-12.0f, 0.0f, 3.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateShadowCircle(20.0f, 0.2f*fShadow);
- }
-
- if ( type == OBJECT_TEEN25 ) // skate /
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen25.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-12.0f, 0.0f, -3.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-12.0f, 0.0f, 3.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateShadowCircle(20.0f, 0.2f*fShadow);
- }
-
- if ( type == OBJECT_TEEN26 ) // ceiling lamp
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen26.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
- SetFloorHeight(0.0f);
-
- mat = RetWorldMatrix(0);
- pos = Math::Transform(*mat, Math::Vector(0.0f, 50.0f, 0.0f));
- m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(100.0f, 100.0f), PARTISELY, 1.0f, 0.0f, 0.0f);
-
- pos = Math::Transform(*mat, Math::Vector(0.0f, 50.0f, 0.0f));
- color.r = 4.0f;
- color.g = 2.0f;
- color.b = 0.0f; // yellow-orange
- color.a = 0.0f;
- m_main->CreateSpot(pos, color);
- }
-
- if ( type == OBJECT_TEEN27 ) // large plant?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen27.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
- CreateShadowCircle(40.0f, 0.5f);
- }
-
- if ( type == OBJECT_TEEN28 ) // bottle?
- {
- rank = m_engine->CreateObject();
-//? m_engine->SetObjectType(rank, TYPEFIX);
- m_engine->SetObjectType(rank, TYPEMETAL);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen28.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUM, 0.10f);
- CreateShadowCircle(7.0f, 0.6f*fShadow);
- }
-
- if ( type == OBJECT_TEEN29 ) // bridge?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen29.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
- bFloorAdjust = false;
- }
-
- if ( type == OBJECT_TEEN30 ) // jump?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen30.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 15.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 15.0f, 0.0f), 17.0f);
- CreateShadowCircle(20.0f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN31 ) // basket?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen31.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector( 0.0f, 2.0f, 0.0f), 6.0f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector( 9.0f, 4.0f, 1.0f), 6.0f, SOUND_BOUM, 0.10f);
-
- SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 10.0f);
- CreateShadowCircle(16.0f, 0.6f*fShadow);
- }
-
- if ( type == OBJECT_TEEN32 ) // chair?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen32.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 17.5f, 1.0f, 17.5f), 3.5f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector( 17.5f, 1.0f, -17.5f), 3.5f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector(-17.5f, 1.0f, 17.5f), 3.5f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector(-17.5f, 1.0f, -17.5f), 3.5f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 26.0f);
- CreateShadowCircle(35.0f, 0.3f*fShadow);
- }
-
- if ( type == OBJECT_TEEN33 ) // panel?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen33.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
- CreateShadowCircle(10.0f, 0.3f*fShadow);
- }
-
- if ( type == OBJECT_TEEN34 ) // stone?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen34.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
- CreateShadowCircle(3.0f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN35 ) // pipe?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen35.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-40.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector(-20.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector( 0.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector( 20.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector( 40.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
- CreateShadowCircle(40.0f, 0.8f*fShadow, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_TEEN36 ) // trunk?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen36.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
- bFloorAdjust = false;
- }
-
- if ( type == OBJECT_TEEN37 ) // boat?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen37.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
- bFloorAdjust = false;
- }
-
- if ( type == OBJECT_TEEN38 ) // fan?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen38a.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\teen38b.mod"); // engine
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 30.0f, 0.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\teen38c.mod"); // propeller
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(0.0f, 0.0f, 0.0f));
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 2.0f, 0.0f), 10.0f);
- CreateShadowCircle(15.0f, 0.5f*fShadow);
- }
-
- if ( type == OBJECT_TEEN39 ) // potted plant?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen39.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 8.5f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 2.0f, 0.0f), 8.5f);
- CreateShadowCircle(10.0f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN40 ) // balloon?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen40.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 5.0f, 0.0f), 11.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 14.0f, 0.0f), 15.0f);
- CreateShadowCircle(15.0f, 0.7f*fShadow);
- }
-
- if ( type == OBJECT_TEEN41 ) // fence?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen41.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
- }
-
- if ( type == OBJECT_TEEN42 ) // clover?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen42.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 2.0f, SOUND_BOUM, 0.10f);
- CreateShadowCircle(15.0f, 0.4f*fShadow);
- }
-
- if ( type == OBJECT_TEEN43 ) // clover?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen43.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 2.0f, SOUND_BOUM, 0.10f);
- CreateShadowCircle(15.0f, 0.4f*fShadow);
- }
-
- if ( type == OBJECT_TEEN44 ) // car?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen44.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 55.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 55.0f);
- CreateShadowCircle(55.0f, 1.0f*fShadow);
- }
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- if ( bFloorAdjust )
- {
- SetFloorHeight(0.0f);
- FloorAdjust();
- }
-
- CreateOtherObject(type);
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos);
-
- delete pModFile;
- return true;
-}
-
-// Creates a crystal placed on the ground.
-
-bool CObject::CreateQuartz(Math::Vector pos, float angle, float height,
- ObjectType type)
-{
- CModFile* pModFile;
- float radius;
- int rank;
-
- if ( m_engine->RetRestCreate() < 1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- if ( type == OBJECT_QUARTZ0 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEQUARTZ);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\quartz0.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 3.5f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 2.0f, 0.0f), 3.5f);
-
- CreateShadowCircle(4.0f, 0.5f);
- }
- if ( type == OBJECT_QUARTZ1 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEQUARTZ);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\quartz1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 5.0f);
-
- CreateShadowCircle(5.0f, 0.5f);
- }
- if ( type == OBJECT_QUARTZ2 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEQUARTZ);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\quartz2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 6.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 6.0f);
-
- CreateShadowCircle(6.0f, 0.5f);
- }
- if ( type == OBJECT_QUARTZ3 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEQUARTZ);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\quartz3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 10.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 10.0f);
-
- CreateShadowCircle(10.0f, 0.5f);
- }
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos);
-
- if ( type == OBJECT_QUARTZ0 )
- {
- pos.y += 4.0f;
- radius = 2.0f;
- }
- if ( type == OBJECT_QUARTZ1 )
- {
- pos.y += 6.0f;
- radius = 4.0f;
- }
- if ( type == OBJECT_QUARTZ2 )
- {
- pos.y += 10.0f;
- radius = 5.0f;
- }
- if ( type == OBJECT_QUARTZ3 )
- {
- pos.y += 16.0f;
- radius = 8.0f;
- }
- m_particule->CreateParticule(pos, pos, Math::Point(2.0f, 2.0f), PARTIQUARTZ, 0.7f+Math::Rand()*0.7f, radius, 0.0f);
- m_particule->CreateParticule(pos, pos, Math::Point(2.0f, 2.0f), PARTIQUARTZ, 0.7f+Math::Rand()*0.7f, radius, 0.0f);
-
- delete pModFile;
- return true;
-}
-
-// Creates a root placed on the ground.
-
-bool CObject::CreateRoot(Math::Vector pos, float angle, float height,
- ObjectType type)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- if ( type == OBJECT_ROOT0 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\root0.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 2.0f);
-
- CreateCrashSphere(Math::Vector(-5.0f, 1.0f, 0.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 4.0f, 1.0f, 2.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 4.0f, 1.0f, -3.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 2.0f, 5.0f, -1.0f), 1.5f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector(-4.0f, 5.0f, -1.0f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector(-2.0f, 8.0f, -0.5f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 0.0f, 10.0f, -0.5f), 1.0f, SOUND_BOUMv, 0.15f);
-//? SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 11.0f);
-
- CreateShadowCircle(16.0f, 0.5f);
- }
- if ( type == OBJECT_ROOT1 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\root1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 2.0f);
-
- CreateCrashSphere(Math::Vector(-4.0f, 1.0f, 1.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 2.0f), 1.5f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 3.0f, 1.0f, -2.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector(-2.0f, 5.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 2.0f, 5.0f, 0.0f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 0.0f, 8.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 0.0f, 12.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
-//? SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 12.0f);
-
- CreateShadowCircle(16.0f, 0.5f);
- }
- if ( type == OBJECT_ROOT2 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\root2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 2.0f);
-
- CreateCrashSphere(Math::Vector(-3.0f, 1.0f, 0.5f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 3.0f, 1.0f, -1.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector(-1.0f, 4.5f, 0.0f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 3.0f, 7.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 0.0f, 7.0f, -1.0f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 4.0f, 11.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
-//? SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 10.0f);
-
- CreateShadowCircle(16.0f, 0.5f);
- }
- if ( type == OBJECT_ROOT3 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\root3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 2.0f);
-
- CreateCrashSphere(Math::Vector(-4.0f, 1.0f, 1.0f), 3.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 4.0f, 1.0f, -3.0f), 3.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 6.0f, 1.0f, 4.0f), 3.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector(-2.5f, 7.0f, 2.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 4.0f, 7.0f, 2.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 3.0f, 6.0f, -1.0f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 0.0f, 12.0f, 0.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 1.0f, 16.0f, 0.0f), 1.0f, SOUND_BOUMv, 0.15f);
-//? SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 14.0f);
-
- CreateShadowCircle(22.0f, 0.5f);
- }
- if ( type == OBJECT_ROOT4 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\root4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 2.0f);
-
- CreateCrashSphere(Math::Vector( -7.0f, 2.0f, 3.0f), 4.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 5.0f, 2.0f, -6.0f), 4.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 6.0f, 2.0f, 6.0f), 3.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector(-11.0f, 1.0f, -2.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 1.0f, 1.0f, -7.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( -4.0f, 10.0f, 3.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 1.0f, 11.0f, 7.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 3.0f, 11.0f, -3.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( -3.0f, 17.0f, 1.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( -3.0f, 23.0f, -1.0f), 2.0f, SOUND_BOUMv, 0.15f);
-//? SetGlobalSphere(Math::Vector(0.0f, 12.0f, 0.0f), 20.0f);
-
- CreateShadowCircle(30.0f, 0.5f);
- }
- if ( type == OBJECT_ROOT5 ) // gravity root ?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\root4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 2.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\root5.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(-5.0f, 28.0f, -4.0f));
- SetAngleX(1, -30.0f*Math::PI/180.0f);
- SetAngleZ(1, 20.0f*Math::PI/180.0f);
-
- CreateCrashSphere(Math::Vector( -7.0f, 2.0f, 3.0f), 4.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 5.0f, 2.0f, -6.0f), 4.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 6.0f, 2.0f, 6.0f), 3.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector(-11.0f, 1.0f, -2.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 1.0f, 1.0f, -7.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( -4.0f, 10.0f, 3.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 1.0f, 11.0f, 7.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 3.0f, 11.0f, -3.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( -3.0f, 17.0f, 1.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( -3.0f, 23.0f, -1.0f), 2.0f, SOUND_BOUMv, 0.15f);
-//? SetGlobalSphere(Math::Vector(0.0f, 12.0f, 0.0f), 20.0f);
-
- CreateShadowCircle(30.0f, 0.5f);
- }
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos);
-
- delete pModFile;
- return true;
-}
-
-// Creates a small home.
-
-bool CObject::CreateHome(Math::Vector pos, float angle, float height,
- ObjectType type)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- if ( type == OBJECT_HOME1 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\home1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 1.3f);
-
- CreateCrashSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUMs, 0.25f);
-//? SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 11.0f);
- CreateShadowCircle(16.0f, 0.5f);
- }
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos);
-
- delete pModFile;
- return true;
-}
-
-// Creates ruin placed on the ground.
-
-bool CObject::CreateRuin(Math::Vector pos, float angle, float height,
- ObjectType type)
-{
- CModFile* pModFile;
- char name[50];
- int rank;
-
- if ( m_engine->RetRestCreate() < 1+4 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
- SetObjectRank(0, rank);
-
- name[0] = 0;
- if ( type == OBJECT_RUINmobilew1 ) strcpy(name, "objects\\ruin1.mod");
- if ( type == OBJECT_RUINmobilew2 ) strcpy(name, "objects\\ruin1.mod");
- if ( type == OBJECT_RUINmobilet1 ) strcpy(name, "objects\\ruin2.mod");
- if ( type == OBJECT_RUINmobilet2 ) strcpy(name, "objects\\ruin2.mod");
- if ( type == OBJECT_RUINmobiler1 ) strcpy(name, "objects\\ruin3.mod");
- if ( type == OBJECT_RUINmobiler2 ) strcpy(name, "objects\\ruin3.mod");
- if ( type == OBJECT_RUINfactory ) strcpy(name, "objects\\ruin4.mod");
- if ( type == OBJECT_RUINdoor ) strcpy(name, "objects\\ruin5.mod");
- if ( type == OBJECT_RUINsupport ) strcpy(name, "objects\\ruin6.mod");
- if ( type == OBJECT_RUINradar ) strcpy(name, "objects\\ruin7.mod");
- if ( type == OBJECT_RUINconvert ) strcpy(name, "objects\\ruin8.mod");
- if ( type == OBJECT_RUINbase ) strcpy(name, "objects\\ruin9.mod");
- if ( type == OBJECT_RUINhead ) strcpy(name, "objects\\ruin10.mod");
-
- pModFile->ReadModel(name);
- pModFile->CreateEngineObject(rank);
-
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- if ( type == OBJECT_RUINmobilew1 ) // vehicle had wheels?
- {
- // Creates the right-back wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(6, rank);
- SetObjectParent(6, 0);
-
- pModFile->ReadModel("objects\\ruin1w.mod");
- pModFile->CreateEngineObject(rank);
-
- SetPosition(6, Math::Vector(-3.0f, 1.8f, -4.0f));
- SetAngleX(6, -Math::PI/2.0f);
-
- // Creates the left-back wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(7, rank);
- SetObjectParent(7, 0);
-
- pModFile->ReadModel("objects\\ruin1w.mod");
- pModFile->CreateEngineObject(rank);
-
- SetPosition(7, Math::Vector(-3.0f, 1.0f, 3.0f));
- SetAngleY(7, Math::PI-0.3f);
- SetAngleX(7, -0.3f);
-
- // Creates the right-front wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(8, rank);
- SetObjectParent(8, 0);
-
- pModFile->ReadModel("objects\\ruin1w.mod");
- pModFile->CreateEngineObject(rank);
-
- SetPosition(8, Math::Vector(2.0f, 1.6f, -3.0f));
- SetAngleY(8, 0.3f);
-
- // Creates the left-front wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(9, rank);
- SetObjectParent(9, 0);
-
- pModFile->ReadModel("objects\\ruin1w.mod");
- pModFile->CreateEngineObject(rank);
-
- SetPosition(9, Math::Vector(2.0f, 1.0f, 3.0f));
- SetAngleY(9, Math::PI-0.2f);
- SetAngleX(9, 0.2f);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.8f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
-//? SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
-
- CreateShadowCircle(4.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINmobilew2 ) // vehicle has wheels?
- {
- // Creates the left-back wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(7, rank);
- SetObjectParent(7, 0);
-
- pModFile->ReadModel("objects\\ruin1w.mod");
- pModFile->CreateEngineObject(rank);
-
- SetPosition(7, Math::Vector(-3.0f, 1.0f, 3.0f));
- SetAngleY(7, Math::PI+0.3f);
- SetAngleX(7, 0.4f);
-
- // Creates the left-front wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(9, rank);
- SetObjectParent(9, 0);
-
- pModFile->ReadModel("objects\\ruin1w.mod");
- pModFile->CreateEngineObject(rank);
-
- SetPosition(9, Math::Vector(2.0f, 1.0f, 3.0f));
- SetAngleY(9, Math::PI+0.3f);
- SetAngleX(9, -0.3f);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.8f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
-//? SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
-
- CreateShadowCircle(4.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINmobilet1 ) // vehicle have caterpillars?
- {
- // Creates the cannon.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
-
- pModFile->ReadModel("objects\\ruin2c.mod");
- pModFile->CreateEngineObject(rank);
-
- SetPosition(1, Math::Vector(3.0f, 5.0f, -2.5f));
- SetAngleX(1, -Math::PI*0.85f);
- SetAngleY(1, -0.4f);
- SetAngleZ(1, -0.1f);
-
- CreateCrashSphere(Math::Vector(1.0f, 2.8f, -1.0f), 5.0f, SOUND_BOUMm, 0.45f);
-//? SetGlobalSphere(Math::Vector(1.0f, 5.0f, -1.0f), 10.0f);
-
- CreateShadowCircle(5.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINmobilet2 ) // vehicle have caterpillars?
- {
- CreateCrashSphere(Math::Vector(0.0f, 2.8f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
-//? SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
-
- CreateShadowCircle(5.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINmobiler1 ) // vehicle skating?
- {
- CreateCrashSphere(Math::Vector(1.0f, 2.8f, -1.0f), 5.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(1.0f, 5.0f, -1.0f), 10.0f);
-
- CreateShadowCircle(5.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINmobiler2 ) // vehicle skating?
- {
- CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
-
- CreateShadowCircle(6.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINfactory ) // factory ?
- {
- CreateCrashSphere(Math::Vector( 9.0f, 1.0f, -11.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 2.0f, -11.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f, -10.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-12.0f, 11.0f, -4.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f, -2.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 8.0f, 3.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 2.0f, 4.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 2.0f, 10.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -4.0f, 0.0f, 10.0f), 3.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 18.0f);
-
- CreateShadowCircle(20.0f, 0.7f);
- }
-
- if ( type == OBJECT_RUINdoor ) // converter holder?
- {
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
-//? SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 6.0f);
-
- CreateShadowCircle(6.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINsupport ) // radar holder?
- {
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
-//? SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f);
-
- CreateShadowCircle(3.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINradar ) // radar base?
- {
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
-//? SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 6.0f);
-
- CreateShadowCircle(6.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINconvert ) // converter?
- {
- m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
-
- CreateCrashSphere(Math::Vector(-10.0f, 0.0f, 4.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 0.0f, -4.0f), 5.0f, SOUND_BOUMm, 0.45f);
-//? SetGlobalSphere(Math::Vector(-3.0f, 0.0f, 0.0f), 14.0f);
- }
-
- if ( type == OBJECT_RUINbase ) // base?
- {
- CreateCrashSphere(Math::Vector( 0.0f, 15.0f, 0.0f),28.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 17.0f, 6.0f, 42.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 17.0f, 17.0f, 42.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-17.0f, 6.0f, 42.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-17.0f, 17.0f, 42.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-42.0f, 6.0f, 17.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-42.0f, 17.0f, 17.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-42.0f, 6.0f, -17.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-42.0f, 17.0f, -17.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-17.0f, 6.0f, -42.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-17.0f, 10.0f, -42.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 15.0f, 13.0f, -34.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 31.0f, 15.0f, -13.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 21.0f, 8.0f, -39.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 26.0f, 8.0f, -33.0f), 5.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 48.0f);
-
- CreateShadowCircle(40.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINhead ) // base cap?
- {
- CreateCrashSphere(Math::Vector( 0.0f, 13.0f, 0.0f),20.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, -8.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f,-16.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f,-22.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-21.0f, 7.0f, 9.0f), 8.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -9.0f, 7.0f, 21.0f), 8.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 21.0f, 7.0f, 9.0f), 8.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 9.0f, 7.0f, 21.0f), 8.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-21.0f, 7.0f, -9.0f), 8.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -9.0f, 7.0f, -21.0f), 8.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 21.0f, 7.0f, -9.0f), 8.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 9.0f, 7.0f, -21.0f), 8.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 35.0f);
-
- CreateShadowCircle(30.0f, 1.0f);
- }
-
- pos = RetPosition(0);
- SetPosition(0, pos); //to display the shadows immediately
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
-
- if ( type != OBJECT_RUINfactory &&
- type != OBJECT_RUINconvert &&
- type != OBJECT_RUINbase )
- {
- FloorAdjust();
- }
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos); //to display the shadows immediately
-
- if ( type == OBJECT_RUINmobilew1 )
- {
- pos = RetPosition(0);
- pos.y -= 0.5f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)-0.1f;
- SetAngleX(0, angle);
- }
-
- if ( type == OBJECT_RUINmobilew2 )
- {
- pos = RetPosition(0);
- pos.y -= 1.5f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)-0.9f;
- SetAngleX(0, angle);
-
- angle = RetAngleZ(0)-0.1f;
- SetAngleZ(0, angle);
- }
-
- if ( type == OBJECT_RUINmobilet1 )
- {
- pos = RetPosition(0);
- pos.y -= 0.9f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)-0.3f;
- SetAngleX(0, angle);
- }
-
- if ( type == OBJECT_RUINmobilet2 )
- {
- pos = RetPosition(0);
- pos.y -= 1.5f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)-0.3f;
- SetAngleX(0, angle);
-
- angle = RetAngleZ(0)+0.8f;
- SetAngleZ(0, angle);
- }
-
- if ( type == OBJECT_RUINmobiler1 )
- {
- pos = RetPosition(0);
- pos.y += 4.0f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)-Math::PI*0.6f;
- SetAngleX(0, angle);
-
- angle = RetAngleZ(0)-0.2f;
- SetAngleZ(0, angle);
- }
-
- if ( type == OBJECT_RUINmobiler2 )
- {
- pos = RetPosition(0);
- pos.y += 2.0f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)-0.1f;
- SetAngleX(0, angle);
-
- angle = RetAngleZ(0)-0.3f;
- SetAngleZ(0, angle);
- }
-
- if ( type == OBJECT_RUINdoor )
- {
- pos = RetPosition(0);
- pos.y -= 0.5f;
- SetPosition(0, pos);
-
- angle = RetAngleZ(0)-0.1f;
- SetAngleZ(0, angle);
- }
-
- if ( type == OBJECT_RUINsupport )
- {
- pos = RetPosition(0);
- pos.y += 0.5f;
- SetPosition(0, pos);
-
-//? angle = RetAngleY(0)+0.1f;
-//? SetAngleY(0, angle);
-
- angle = RetAngleX(0)+0.1f;
- SetAngleX(0, angle);
-
- angle = RetAngleZ(0)+0.1f;
- SetAngleZ(0, angle);
- }
-
- if ( type == OBJECT_RUINradar )
- {
- pos = RetPosition(0);
- pos.y -= 0.5f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)+0.15f;
- SetAngleX(0, angle);
-
- angle = RetAngleZ(0)+0.1f;
- SetAngleZ(0, angle);
- }
-
- if ( type == OBJECT_RUINconvert )
- {
- pos = RetPosition(0);
- pos.y -= 1.0f;
- SetPosition(0, pos);
- }
-
- if ( type == OBJECT_RUINbase )
- {
- pos = RetPosition(0);
- pos.y -= 1.0f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)+0.15f;
- SetAngleX(0, angle);
- }
-
- if ( type == OBJECT_RUINhead )
- {
- pos = RetPosition(0);
- pos.y += 8.0f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)+Math::PI*0.4f;
- SetAngleX(0, angle);
- }
-
- delete pModFile;
- return true;
-}
-
-// Creates a gadget apollo.
-
-bool CObject::CreateApollo(Math::Vector pos, float angle, ObjectType type)
-{
- CModFile* pModFile;
- int rank, i;
-
- if ( m_engine->RetRestCreate() < 6 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- if ( type == OBJECT_APOLLO1 ) // LEM ?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\apollol1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 1.2f);
- SetFloorHeight(0.0f);
-
- for ( i=0 ; i<4 ; i++ ) // creates feet
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(i+1, rank);
- SetObjectParent(i+1, 0);
- pModFile->ReadModel("objects\\apollol2.mod");
- pModFile->CreateEngineObject(rank);
- SetAngleY(i+1, Math::PI/2.0f*i);
- }
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(5, rank);
- SetObjectParent(5, 0);
- pModFile->ReadModel("objects\\apollol3.mod"); // ladder
- pModFile->CreateEngineObject(rank);
-
-//? m_terrain->AddBuildingLevel(pos, 10.0f, 13.0f, 12.0f, 0.0f);
-
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 11.0f, 5.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 5.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 5.0f, -11.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 5.0f, 11.0f), 3.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 9.0f);
-
- CreateShadowCircle(16.0f, 0.5f);
- }
-
- if ( type == OBJECT_APOLLO2 ) // jeep
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); //it is a stationary object
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\apolloj1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- // Wheels.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(-5.75f, 1.65f, -5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(-5.75f, 1.65f, 5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(3, rank);
- SetObjectParent(3, 0);
- pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- SetPosition(3, Math::Vector(5.75f, 1.65f, -5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(4, rank);
- SetObjectParent(4, 0);
- pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- SetPosition(4, Math::Vector(5.75f, 1.65f, 5.0f));
-
- // Accessories:
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(5, rank);
- SetObjectParent(5, 0);
- pModFile->ReadModel("objects\\apolloj2.mod"); // antenna
- pModFile->CreateEngineObject(rank);
- SetPosition(5, Math::Vector(5.5f, 8.8f, 2.0f));
- SetAngleY(5, -120.0f*Math::PI/180.0f);
- SetAngleZ(5, 45.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(6, rank);
- SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\apolloj3.mod"); // camera
- pModFile->CreateEngineObject(rank);
- SetPosition(6, Math::Vector(5.5f, 2.8f, -2.0f));
- SetAngleY(6, 30.0f*Math::PI/180.0f);
-
- CreateCrashSphere(Math::Vector( 3.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-3.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 7.0f, 9.0f, 2.0f), 2.0f, SOUND_BOUMm, 0.20f);
-
- CreateShadowCircle(7.0f, 0.8f);
-
- FloorAdjust();
- }
-
- if ( type == OBJECT_APOLLO3 ) // flag?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\apollof.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- SetJotlerSphere(Math::Vector(0.0f, 4.0f, 0.0f), 1.0f);
- CreateShadowCircle(2.0f, 0.3f);
- }
-
- if ( type == OBJECT_APOLLO4 ) // module?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\apollom.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 2.0f, SOUND_BOUMm, 0.45f);
- CreateShadowCircle(5.0f, 0.8f);
-
- FloorAdjust();
- }
-
- if ( type == OBJECT_APOLLO5 ) // antenna?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\apolloa.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\apolloj2.mod"); // antenna
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 5.0f, 0.0f));
- SetAngleY(1, -120.0f*Math::PI/180.0f);
- SetAngleZ(1, 45.0f*Math::PI/180.0f);
-
- CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.35f);
- CreateShadowCircle(3.0f, 0.7f);
- }
-
- CreateOtherObject(type);
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- delete pModFile;
- return true;
-}
-
-// Creates all sub-objects for managing the object.
-
-void CObject::CreateOtherObject(ObjectType type)
-{
- if ( type == OBJECT_BASE )
- {
- m_auto = new CAutoBase(m_iMan, this);
- }
- if ( type == OBJECT_PORTICO )
- {
- m_auto = new CAutoPortico(m_iMan, this);
- }
- if ( type == OBJECT_DERRICK )
- {
- m_auto = new CAutoDerrick(m_iMan, this);
- }
- if ( type == OBJECT_FACTORY )
- {
- m_auto = new CAutoFactory(m_iMan, this);
- }
- if ( type == OBJECT_REPAIR )
- {
- m_auto = new CAutoRepair(m_iMan, this);
- }
- if ( type == OBJECT_DESTROYER )
- {
- m_auto = new CAutoDestroyer(m_iMan, this);
- }
- if ( type == OBJECT_STATION )
- {
- m_auto = new CAutoStation(m_iMan, this);
- }
- if ( type == OBJECT_CONVERT )
- {
- m_auto = new CAutoConvert(m_iMan, this);
- }
- if ( type == OBJECT_TOWER )
- {
- m_auto = new CAutoTower(m_iMan, this);
- }
- if ( type == OBJECT_RESEARCH )
- {
- m_auto = new CAutoResearch(m_iMan, this);
- }
- if ( type == OBJECT_RADAR )
- {
- m_auto = new CAutoRadar(m_iMan, this);
- }
- if ( type == OBJECT_INFO )
- {
- m_auto = new CAutoInfo(m_iMan, this);
- }
- if ( type == OBJECT_ENERGY )
- {
- m_auto = new CAutoEnergy(m_iMan, this);
- }
- if ( type == OBJECT_LABO )
- {
- m_auto = new CAutoLabo(m_iMan, this);
- }
- if ( type == OBJECT_NUCLEAR )
- {
- m_auto = new CAutoNuclear(m_iMan, this);
- }
- if ( type == OBJECT_PARA )
- {
- m_auto = new CAutoPara(m_iMan, this);
- }
- if ( type == OBJECT_SAFE )
- {
- m_auto = new CAutoSafe(m_iMan, this);
- }
- if ( type == OBJECT_HUSTON )
- {
- m_auto = new CAutoHuston(m_iMan, this);
- }
- if ( type == OBJECT_EGG )
- {
- m_auto = new CAutoEgg(m_iMan, this);
- }
- if ( type == OBJECT_NEST )
- {
- m_auto = new CAutoNest(m_iMan, this);
- }
- if ( type == OBJECT_ROOT5 )
- {
- m_auto = new CAutoRoot(m_iMan, this);
- }
- if ( type == OBJECT_MUSHROOM2 )
- {
- m_auto = new CAutoMush(m_iMan, this);
- }
- if ( type == OBJECT_FLAGb ||
- type == OBJECT_FLAGr ||
- type == OBJECT_FLAGg ||
- type == OBJECT_FLAGy ||
- type == OBJECT_FLAGv )
- {
- m_auto = new CAutoFlag(m_iMan, this);
- }
- if ( type == OBJECT_TEEN36 || // trunk?
- type == OBJECT_TEEN37 || // boat?
- type == OBJECT_TEEN38 ) // fan?
- {
- m_auto = new CAutoKid(m_iMan, this);
- }
-}
-
-
-// Reads a program.
-
-bool CObject::ReadProgram(int rank, char* filename)
-{
- if ( m_brain != 0 )
- {
- return m_brain->ReadProgram(rank, filename);
- }
- return false;
-}
-
-// Writes a program.
-
-bool CObject::WriteProgram(int rank, char* filename)
-{
- if ( m_brain != 0 )
- {
- return m_brain->WriteProgram(rank, filename);
- }
- return false;
-}
-
-// Starts a program.
-
-bool CObject::RunProgram(int rank)
-{
- if ( m_brain != 0 )
- {
- m_brain->RunProgram(rank);
- return true;
- }
- if ( m_auto != 0 )
- {
- m_auto->Start(rank);
- return true;
- }
- return false;
-}
-
-
-
-
-// Calculates the matrix for transforming the object.
-// Returns true if the matrix has changed.
-// The rotations occur in the order Y, Z and X.
-
-bool CObject::UpdateTransformObject(int part, bool bForceUpdate)
-{
- Math::Vector position, angle, eye;
- bool bModif = false;
- int parent;
-
- if ( m_truck != 0 ) // transported by truck?
- {
- m_objectPart[part].bTranslate = true;
- m_objectPart[part].bRotate = true;
- }
-
- if ( !bForceUpdate &&
- !m_objectPart[part].bTranslate &&
- !m_objectPart[part].bRotate ) return false;
-
- position = m_objectPart[part].position;
- angle = m_objectPart[part].angle;
-
- if ( part == 0 ) // main part?
- {
- position += m_linVibration;
- angle += m_cirVibration+m_inclinaison;
- }
-
- if ( m_objectPart[part].bTranslate ||
- m_objectPart[part].bRotate )
- {
- if ( m_objectPart[part].bTranslate )
- {
- m_objectPart[part].matTranslate.LoadIdentity();
- m_objectPart[part].matTranslate.Set(1, 4, position.x);
- m_objectPart[part].matTranslate.Set(2, 4, position.y);
- m_objectPart[part].matTranslate.Set(3, 4, position.z);
- }
-
- if ( m_objectPart[part].bRotate )
- {
- Math::LoadRotationZXYMatrix(m_objectPart[part].matRotate, angle);
- }
-
- if ( m_objectPart[part].bZoom )
- {
- Math::Matrix mz;
- mz.LoadIdentity();
- mz.Set(1, 1, m_objectPart[part].zoom.x);
- mz.Set(2, 2, m_objectPart[part].zoom.y);
- mz.Set(3, 3, m_objectPart[part].zoom.z);
- m_objectPart[part].matTransform = Math::MultiplyMatrices(m_objectPart[part].matTranslate,
- Math::MultiplyMatrices(m_objectPart[part].matRotate, mz));
- }
- else
- {
- m_objectPart[part].matTransform = Math::MultiplyMatrices(m_objectPart[part].matTranslate,
- m_objectPart[part].matRotate);
- }
- bModif = true;
- }
-
- if ( bForceUpdate ||
- m_objectPart[part].bTranslate ||
- m_objectPart[part].bRotate )
- {
- parent = m_objectPart[part].parentPart;
-
- if ( part == 0 && m_truck != 0 ) // transported by a truck?
- {
- Math::Matrix* matWorldTruck;
- matWorldTruck = m_truck->RetWorldMatrix(m_truckLink);
- m_objectPart[part].matWorld = Math::MultiplyMatrices(*matWorldTruck,
- m_objectPart[part].matTransform);
- }
- else
- {
- if ( parent == -1 ) // no parent?
- {
- m_objectPart[part].matWorld = m_objectPart[part].matTransform;
- }
- else
- {
- m_objectPart[part].matWorld = Math::MultiplyMatrices(m_objectPart[parent].matWorld,
- m_objectPart[part].matTransform);
- }
- }
- bModif = true;
- }
-
- if ( bModif )
- {
- m_engine->SetObjectTransform(m_objectPart[part].object,
- m_objectPart[part].matWorld);
- }
-
- m_objectPart[part].bTranslate = false;
- m_objectPart[part].bRotate = false;
-
- return bModif;
-}
-
-// Updates all matrices to transform the object father and all his sons.
-// Assume a maximum of 4 degrees of freedom.
-// Appropriate, for example, to a body, an arm, forearm, hand and fingers.
-
-bool CObject::UpdateTransformObject()
-{
- bool bUpdate1, bUpdate2, bUpdate3, bUpdate4;
- int level1, level2, level3, level4, rank;
- int parent1, parent2, parent3, parent4;
-
- if ( m_bFlat )
- {
- for ( level1=0 ; level1<m_totalPart ; level1++ )
- {
- if ( !m_objectPart[level1].bUsed ) continue;
- UpdateTransformObject(level1, false);
- }
- }
- else
- {
- parent1 = 0;
- bUpdate1 = UpdateTransformObject(parent1, false);
-
- for ( level1=0 ; level1<m_totalPart ; level1++ )
- {
- rank = SearchDescendant(parent1, level1);
- if ( rank == -1 ) break;
-
- parent2 = rank;
- bUpdate2 = UpdateTransformObject(rank, bUpdate1);
-
- for ( level2=0 ; level2<m_totalPart ; level2++ )
- {
- rank = SearchDescendant(parent2, level2);
- if ( rank == -1 ) break;
-
- parent3 = rank;
- bUpdate3 = UpdateTransformObject(rank, bUpdate2);
-
- for ( level3=0 ; level3<m_totalPart ; level3++ )
- {
- rank = SearchDescendant(parent3, level3);
- if ( rank == -1 ) break;
-
- parent4 = rank;
- bUpdate4 = UpdateTransformObject(rank, bUpdate3);
-
- for ( level4=0 ; level4<m_totalPart ; level4++ )
- {
- rank = SearchDescendant(parent4, level4);
- if ( rank == -1 ) break;
-
- UpdateTransformObject(rank, bUpdate4);
- }
- }
- }
- }
- }
-
- return true;
-}
-
-
-// Puts all the progeny flat (there is more than fathers).
-// This allows for debris independently from each other in all directions.
-
-void CObject::FlatParent()
-{
- int i;
-
- for ( i=0 ; i<m_totalPart ; i++ )
- {
- m_objectPart[i].position.x = m_objectPart[i].matWorld.Get(1, 4);
- m_objectPart[i].position.y = m_objectPart[i].matWorld.Get(2, 4);
- m_objectPart[i].position.z = m_objectPart[i].matWorld.Get(3, 4);
-
- m_objectPart[i].matWorld.Set(1, 4, 0.0f);
- m_objectPart[i].matWorld.Set(2, 4, 0.0f);
- m_objectPart[i].matWorld.Set(3, 4, 0.0f);
-
- m_objectPart[i].matTranslate.Set(1, 4, 0.0f);
- m_objectPart[i].matTranslate.Set(2, 4, 0.0f);
- m_objectPart[i].matTranslate.Set(3, 4, 0.0f);
-
- m_objectPart[i].parentPart = -1; // more parents
- }
-
- m_bFlat = true;
-}
-
-
-
-// Updates the mapping of the texture of the pile.
-
-void CObject::UpdateEnergyMapping()
-{
- D3DMATERIAL7 mat;
- float a, b, i, s, au, bu;
- float limit[6];
- int j;
-
- if ( fabs(m_energy-m_lastEnergy) < 0.01f ) return;
- m_lastEnergy = m_energy;
-
- ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
- mat.diffuse.r = 1.0f;
- mat.diffuse.g = 1.0f;
- mat.diffuse.b = 1.0f; // white
- mat.ambient.r = 0.5f;
- mat.ambient.g = 0.5f;
- mat.ambient.b = 0.5f;
-
- if ( m_type == OBJECT_POWER ||
- m_type == OBJECT_ATOMIC )
- {
- a = 2.0f;
- b = 0.0f; // dimensions of the battery (according to y)
- }
- if ( m_type == OBJECT_STATION )
- {
- a = 10.0f;
- b = 4.0f; // dimensions of the battery (according to y)
- }
- if ( m_type == OBJECT_ENERGY )
- {
- a = 9.0f;
- b = 3.0f; // dimensions of the battery (according to y)
- }
-
- i = 0.50f+0.25f*m_energy; // origin
- s = i+0.25f; // width
-
- au = (s-i)/(b-a);
- bu = s-b*(s-i)/(b-a);
-
- limit[0] = 0.0f;
- limit[1] = m_engine->RetLimitLOD(0);
- limit[2] = limit[1];
- limit[3] = m_engine->RetLimitLOD(1);
- limit[4] = limit[3];
- limit[5] = 1000000.0f;
-
- for ( j=0 ; j<3 ; j++ )
- {
- m_engine->ChangeTextureMapping(m_objectPart[0].object,
- mat, D3DSTATEPART3, "lemt.tga", "",
- limit[j*2+0], limit[j*2+1], D3DMAPPING1Y,
- au, bu, 1.0f, 0.0f);
- }
-}
-
-
-// Manual action.
-
-bool CObject::EventProcess(const Event &event)
-{
- if ( event.event == EVENT_KEYDOWN )
- {
-#if ADJUST_ONBOARD
- if ( m_bSelect )
- {
- if ( event.param == 'E' ) debug_x += 0.1f;
- if ( event.param == 'D' ) debug_x -= 0.1f;
- if ( event.param == 'R' ) debug_y += 0.1f;
- if ( event.param == 'F' ) debug_y -= 0.1f;
- if ( event.param == 'T' ) debug_z += 0.1f;
- if ( event.param == 'G' ) debug_z -= 0.1f;
- }
-#endif
-#if ADJUST_ARM
- if ( m_bSelect )
- {
- if ( event.param == 'X' ) debug_arm1 += 5.0f*Math::PI/180.0f;
- if ( event.param == 'C' ) debug_arm1 -= 5.0f*Math::PI/180.0f;
- if ( event.param == 'V' ) debug_arm2 += 5.0f*Math::PI/180.0f;
- if ( event.param == 'B' ) debug_arm2 -= 5.0f*Math::PI/180.0f;
- if ( event.param == 'N' ) debug_arm3 += 5.0f*Math::PI/180.0f;
- if ( event.param == 'M' ) debug_arm3 -= 5.0f*Math::PI/180.0f;
- if ( event.param == 'X' ||
- event.param == 'C' ||
- event.param == 'V' ||
- event.param == 'B' ||
- event.param == 'N' ||
- event.param == 'M' )
- {
- SetAngleZ(1, debug_arm1);
- SetAngleZ(2, debug_arm2);
- SetAngleZ(3, debug_arm3);
- char s[100];
- sprintf(s, "a=%.2f b=%.2f c=%.2f", debug_arm1*180.0f/Math::PI, debug_arm2*180.0f/Math::PI, debug_arm3*180.0f/Math::PI);
- m_engine->SetInfoText(5, s);
- }
- }
-#endif
- }
-
- if ( m_physics != 0 )
- {
- if ( !m_physics->EventProcess(event) ) // object destroyed?
- {
- if ( RetSelect() &&
- m_type != OBJECT_ANT &&
- m_type != OBJECT_SPIDER &&
- m_type != OBJECT_BEE )
- {
- if ( !m_bDead ) m_camera->SetType(CAMERA_EXPLO);
- m_main->DeselectAll();
- }
- return false;
- }
- }
-
- if ( m_auto != 0 )
- {
- m_auto->EventProcess(event);
-
- if ( event.event == EVENT_FRAME &&
- m_auto->IsEnded() != ERR_CONTINUE )
- {
- m_auto->DeleteObject();
- delete m_auto;
- m_auto = 0;
- }
- }
-
- if ( m_motion != 0 )
- {
- m_motion->EventProcess(event);
- }
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- return true;
-}
-
-
-// Animates the object.
-
-bool CObject::EventFrame(const Event &event)
-{
- if ( m_type == OBJECT_HUMAN && m_main->RetMainMovie() == MM_SATCOMopen )
- {
- UpdateTransformObject();
- return true;
- }
-
- if ( m_type != OBJECT_SHOW && m_engine->RetPause() ) return true;
-
- m_aTime += event.rTime;
- m_shotTime += event.rTime;
-
- VirusFrame(event.rTime);
- PartiFrame(event.rTime);
-
- UpdateMapping();
- UpdateTransformObject();
- UpdateSelectParticule();
-
- if ( m_bProxyActivate ) // active if it is near?
- {
- CPyro* pyro;
- Math::Vector eye;
- float dist;
-
- eye = m_engine->RetLookatPt();
- dist = Math::Distance(eye, RetPosition(0));
- if ( dist < m_proxyDistance )
- {
- m_bProxyActivate = false;
- m_main->CreateShortcuts();
- m_sound->Play(SOUND_FINDING);
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FINDING, this, 0.0f);
- m_displayText->DisplayError(INFO_FINDING, this);
- }
- }
-
- return true;
-}
-
-// Updates the mapping of the object.
-
-void CObject::UpdateMapping()
-{
- if ( m_type == OBJECT_POWER ||
- m_type == OBJECT_ATOMIC ||
- m_type == OBJECT_STATION ||
- m_type == OBJECT_ENERGY )
- {
- UpdateEnergyMapping();
- }
-}
-
-
-// Management of viruses.
-
-void CObject::VirusFrame(float rTime)
-{
- ParticuleType type;
- Math::Vector pos, speed;
- Math::Point dim;
- int r;
-
- if ( !m_bVirusMode ) return; // healthy object?
-
- m_virusTime += rTime;
- if ( m_virusTime >= VIRUS_DELAY )
- {
- m_bVirusMode = false; // the virus is no longer active
- }
-
- if ( m_lastVirusParticule+m_engine->ParticuleAdapt(0.2f) <= m_aTime )
- {
- m_lastVirusParticule = m_aTime;
-
- r = rand()%10;
- if ( r == 0 ) type = PARTIVIRUS1;
- if ( r == 1 ) type = PARTIVIRUS2;
- if ( r == 2 ) type = PARTIVIRUS3;
- if ( r == 3 ) type = PARTIVIRUS4;
- if ( r == 4 ) type = PARTIVIRUS5;
- if ( r == 5 ) type = PARTIVIRUS6;
- if ( r == 6 ) type = PARTIVIRUS7;
- if ( r == 7 ) type = PARTIVIRUS8;
- if ( r == 8 ) type = PARTIVIRUS9;
- if ( r == 9 ) type = PARTIVIRUS10;
-
- pos = RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = Math::Rand()*4.0f+4.0f;
- dim.x = Math::Rand()*0.3f+0.3f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, type, 3.0f);
- }
-}
-
-// Management particles mistresses.
-
-void CObject::PartiFrame(float rTime)
-{
- Math::Vector pos, angle, factor;
- int i, channel;
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- if ( !m_objectPart[i].bUsed ) continue;
-
- channel = m_objectPart[i].masterParti;
- if ( channel == -1 ) continue;
-
- if ( !m_particule->GetPosition(channel, pos) )
- {
- m_objectPart[i].masterParti = -1; // particle no longer exists!
- continue;
- }
-
- SetPosition(i, pos);
-
- // Each song spins differently.
- switch( i%5 )
- {
- case 0: factor = Math::Vector( 0.5f, 0.3f, 0.6f); break;
- case 1: factor = Math::Vector(-0.3f, 0.4f,-0.2f); break;
- case 2: factor = Math::Vector( 0.4f,-0.6f,-0.3f); break;
- case 3: factor = Math::Vector(-0.6f,-0.2f, 0.0f); break;
- case 4: factor = Math::Vector( 0.4f, 0.1f,-0.7f); break;
- }
-
- angle = RetAngle(i);
- angle += rTime*Math::PI*factor;
- SetAngle(i, angle);
- }
-}
-
-
-// Changes the perspective to view if it was like in the vehicle,
-// or behind the vehicle.
-
-void CObject::SetViewFromHere(Math::Vector &eye, float &dirH, float &dirV,
- Math::Vector &lookat, Math::Vector &upVec,
- CameraType type)
-{
- float speed;
- int part;
-
- UpdateTransformObject();
-
- part = 0;
- if ( m_type == OBJECT_HUMAN ||
- m_type == OBJECT_TECH )
- {
- eye.x = -0.2f;
- eye.y = 3.3f;
- eye.z = 0.0f;
-//? eye.x = 1.0f;
-//? eye.y = 3.3f;
-//? eye.z = 0.0f;
- }
- else if ( m_type == OBJECT_MOBILErt ||
- m_type == OBJECT_MOBILErr ||
- m_type == OBJECT_MOBILErs )
- {
- eye.x = -1.1f; // on the cap
- eye.y = 7.9f;
- eye.z = 0.0f;
- }
- else if ( m_type == OBJECT_MOBILEwc ||
- m_type == OBJECT_MOBILEtc ||
- m_type == OBJECT_MOBILEfc ||
- m_type == OBJECT_MOBILEic ) // fireball?
- {
-//? eye.x = -0.9f; // on the cannon
-//? eye.y = 3.0f;
-//? eye.z = 0.0f;
-//? part = 1;
- eye.x = -0.9f; // on the cannon
- eye.y = 8.3f;
- eye.z = 0.0f;
- }
- else if ( m_type == OBJECT_MOBILEwi ||
- m_type == OBJECT_MOBILEti ||
- m_type == OBJECT_MOBILEfi ||
- m_type == OBJECT_MOBILEii ) // orgaball ?
- {
-//? eye.x = -3.5f; // on the cannon
-//? eye.y = 5.1f;
-//? eye.z = 0.0f;
-//? part = 1;
- eye.x = -2.5f; // on the cannon
- eye.y = 10.4f;
- eye.z = 0.0f;
- }
- else if ( m_type == OBJECT_MOBILErc )
- {
-//? eye.x = 2.0f; // in the cannon
-//? eye.y = 0.0f;
-//? eye.z = 0.0f;
-//? part = 2;
- eye.x = 4.0f; // on the cannon
- eye.y = 11.0f;
- eye.z = 0.0f;
- }
- else if ( m_type == OBJECT_MOBILEsa )
- {
- eye.x = 3.0f;
- eye.y = 4.5f;
- eye.z = 0.0f;
- }
- else if ( m_type == OBJECT_MOBILEdr )
- {
- eye.x = 1.0f;
- eye.y = 6.5f;
- eye.z = 0.0f;
- }
- else if ( m_type == OBJECT_APOLLO2 )
- {
- eye.x = -3.0f;
- eye.y = 6.0f;
- eye.z = -2.0f;
- }
- else
- {
- eye.x = 0.7f; // between the brackets
- eye.y = 4.8f;
- eye.z = 0.0f;
- }
-#if ADJUST_ONBOARD
- eye.x += debug_x;
- eye.y += debug_y;
- eye.z += debug_z;
- char s[100];
- sprintf(s, "x=%.2f y=%.2f z=%.2f", eye.x, eye.y, eye.z);
- m_engine->SetInfoText(4, s);
-#endif
-
- if ( type == CAMERA_BACK )
- {
- eye.x -= 20.0f;
- eye.y += 1.0f;
- }
-
- lookat.x = eye.x+1.0f;
- lookat.y = eye.y+0.0f;
- lookat.z = eye.z+0.0f;
-
- eye = Math::Transform(m_objectPart[part].matWorld, eye);
- lookat = Math::Transform(m_objectPart[part].matWorld, lookat);
-
- // Camera tilts when turning.
- upVec = Math::Vector(0.0f, 1.0f, 0.0f);
- if ( m_physics != 0 )
- {
- if ( m_physics->RetLand() ) // on ground?
- {
- speed = m_physics->RetLinMotionX(MO_REASPEED);
- lookat.y -= speed*0.002f;
-
- speed = m_physics->RetCirMotionY(MO_REASPEED);
- upVec.z -= speed*0.04f;
- }
- else // in flight?
- {
- speed = m_physics->RetLinMotionX(MO_REASPEED);
- lookat.y += speed*0.002f;
-
- speed = m_physics->RetCirMotionY(MO_REASPEED);
- upVec.z += speed*0.08f;
- }
- }
- upVec = Math::Transform(m_objectPart[0].matRotate, upVec);
-
- dirH = -(m_objectPart[part].angle.y+Math::PI/2.0f);
- dirV = 0.0f;
-
-}
-
-
-// Management of features.
-
-void CObject::SetCharacter(Character* character)
-{
- CopyMemory(&m_character, character, sizeof(Character));
-}
-
-void CObject::GetCharacter(Character* character)
-{
- CopyMemory(character, &m_character, sizeof(Character));
-}
-
-Character* CObject::RetCharacter()
-{
- return &m_character;
-}
-
-
-// Returns the absolute time.
-
-float CObject::RetAbsTime()
-{
- return m_aTime;
-}
-
-
-// Management of energy contained in a battery.
-// Single subject possesses the battery energy, but not the vehicle that carries the battery!
-
-void CObject::SetEnergy(float level)
-{
- if ( level < 0.0f ) level = 0.0f;
- if ( level > 1.0f ) level = 1.0f;
- m_energy = level;
-}
-
-float CObject::RetEnergy()
-{
- if ( m_type != OBJECT_POWER &&
- m_type != OBJECT_ATOMIC &&
- m_type != OBJECT_STATION &&
- m_type != OBJECT_ENERGY ) return 0.0f;
- return m_energy;
-}
-
-
-// Management of the capacity of a battery.
-// Single subject possesses a battery capacity,
-// but not the vehicle that carries the battery!
-
-void CObject::SetCapacity(float capacity)
-{
- m_capacity = capacity;
-}
-
-float CObject::RetCapacity()
-{
- return m_capacity;
-}
-
-
-// Management of the shield.
-
-void CObject::SetShield(float level)
-{
- m_shield = level;
-}
-
-float CObject::RetShield()
-{
- if ( m_type == OBJECT_FRET ||
- m_type == OBJECT_STONE ||
- m_type == OBJECT_URANIUM ||
- m_type == OBJECT_BULLET ||
- m_type == OBJECT_METAL ||
- m_type == OBJECT_BBOX ||
- m_type == OBJECT_KEYa ||
- m_type == OBJECT_KEYb ||
- m_type == OBJECT_KEYc ||
- m_type == OBJECT_KEYd ||
- m_type == OBJECT_TNT ||
- m_type == OBJECT_TEEN31 || // basket?
- m_type == OBJECT_SCRAP1 ||
- m_type == OBJECT_SCRAP2 ||
- m_type == OBJECT_SCRAP3 ||
- m_type == OBJECT_SCRAP4 ||
- m_type == OBJECT_SCRAP5 ||
- m_type == OBJECT_BOMB ||
- m_type == OBJECT_WAYPOINT ||
- m_type == OBJECT_FLAGb ||
- m_type == OBJECT_FLAGr ||
- m_type == OBJECT_FLAGg ||
- m_type == OBJECT_FLAGy ||
- m_type == OBJECT_FLAGv ||
- m_type == OBJECT_POWER ||
- m_type == OBJECT_ATOMIC ||
- m_type == OBJECT_ANT ||
- m_type == OBJECT_SPIDER ||
- m_type == OBJECT_BEE ||
- m_type == OBJECT_WORM ) return 0.0f;
- return m_shield;
-}
-
-
-// Management of flight range (zero = infinity).
-
-void CObject::SetRange(float delay)
-{
- m_range = delay;
-}
-
-float CObject::RetRange()
-{
- return m_range;
-}
-
-
-// Management of transparency of the object.
-
-void CObject::SetTransparency(float value)
-{
- int i;
-
- m_transparency = value;
-
- for ( i=0 ; i<m_totalPart ; i++ )
- {
- if ( m_objectPart[i].bUsed )
- {
- if ( m_type == OBJECT_BASE )
- {
- if ( i != 9 ) continue; // no central pillar?
- }
-
- m_engine->SetObjectTransparency(m_objectPart[i].object, value);
- }
- }
-}
-
-float CObject::RetTransparency()
-{
- return m_transparency;
-}
-
-
-// Management of the object matter.
-
-ObjectMaterial CObject::RetMaterial()
-{
- if ( m_type == OBJECT_HUMAN )
- {
- return OM_HUMAN;
- }
-
- if ( m_type == OBJECT_SCRAP4 ||
- m_type == OBJECT_SCRAP5 )
- {
- return OM_HUMAN;
- }
-
- return OM_METAL;
-}
-
-
-// Indicates whether the gadget is a nonessential.
-
-void CObject::SetGadget(bool bMode)
-{
- m_bGadget = bMode;
-}
-
-bool CObject::RetGadget()
-{
- return m_bGadget;
-}
-
-
-// Indicates whether an object is stationary (ant on the back).
-
-void CObject::SetFixed(bool bFixed)
-{
- m_bFixed = bFixed;
-}
-
-bool CObject::RetFixed()
-{
- return m_bFixed;
-}
-
-
-// Indicates whether an object is subjected to clipping (obstacles).
-
-void CObject::SetClip(bool bClip)
-{
- m_bClip = bClip;
-}
-
-bool CObject::RetClip()
-{
- return m_bClip;
-}
-
-
-
-// Pushes an object.
-
-bool CObject::JostleObject(float force)
-{
- CAutoJostle* pa;
-
- if ( m_type == OBJECT_FLAGb ||
- m_type == OBJECT_FLAGr ||
- m_type == OBJECT_FLAGg ||
- m_type == OBJECT_FLAGy ||
- m_type == OBJECT_FLAGv ) // flag?
- {
- if ( m_auto == 0 ) return false;
-
- m_auto->Start(1);
- }
- else
- {
- if ( m_auto != 0 ) return false;
-
- m_auto = new CAutoJostle(m_iMan, this);
- pa = (CAutoJostle*)m_auto;
- pa->Start(0, force);
- }
-
- return true;
-}
-
-
-// Beginning of the effect when the instruction "detect" is used.
-
-void CObject::StartDetectEffect(CObject *target, bool bFound)
-{
- Math::Matrix* mat;
- Math::Vector pos, goal;
- Math::Point dim;
-
- mat = RetWorldMatrix(0);
- pos = Math::Transform(*mat, Math::Vector(2.0f, 3.0f, 0.0f));
-
- if ( target == 0 )
- {
- goal = Math::Transform(*mat, Math::Vector(50.0f, 3.0f, 0.0f));
- }
- else
- {
- goal = target->RetPosition(0);
- goal.y += 3.0f;
- goal = Math::SegmentPoint(pos, goal, Math::Distance(pos, goal)-3.0f);
- }
-
- dim.x = 3.0f;
- dim.y = dim.x;
- m_particule->CreateRay(pos, goal, PARTIRAY2, dim, 0.2f);
-
- if ( target != 0 )
- {
- goal = target->RetPosition(0);
- goal.y += 3.0f;
- goal = Math::SegmentPoint(pos, goal, Math::Distance(pos, goal)-1.0f);
- dim.x = 6.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(goal, Math::Vector(0.0f, 0.0f, 0.0f), dim,
- bFound?PARTIGLINT:PARTIGLINTr, 0.5f);
- }
-
- m_sound->Play(bFound?SOUND_BUILD:SOUND_RECOVER);
-}
-
-
-// Management of time from which a virus is active.
-
-void CObject::SetVirusMode(bool bEnable)
-{
- m_bVirusMode = bEnable;
- m_virusTime = 0.0f;
-
- if ( m_bVirusMode && m_brain != 0 )
- {
- if ( !m_brain->IntroduceVirus() ) // tries to infect
- {
- m_bVirusMode = false; // program was not contaminated!
- }
- }
-}
-
-bool CObject::RetVirusMode()
-{
- return m_bVirusMode;
-}
-
-float CObject::RetVirusTime()
-{
- return m_virusTime;
-}
-
-
-// Management mode of the camera.
-
-void CObject::SetCameraType(CameraType type)
-{
- m_cameraType = type;
-}
-
-CameraType CObject::RetCameraType()
-{
- return m_cameraType;
-}
-
-void CObject::SetCameraDist(float dist)
-{
- m_cameraDist = dist;
-}
-
-float CObject::RetCameraDist()
-{
- return m_cameraDist;
-}
-
-void CObject::SetCameraLock(bool bLock)
-{
- m_bCameraLock = bLock;
-}
-
-bool CObject::RetCameraLock()
-{
- return m_bCameraLock;
-}
-
-
-
-// Management of the demonstration of the object.
-
-void CObject::SetHilite(bool bMode)
-{
- int list[OBJECTMAXPART+1];
- int i, j;
-
- m_bHilite = bMode;
-
- if ( m_bHilite )
- {
- j = 0;
- for ( i=0 ; i<m_totalPart ; i++ )
- {
- if ( m_objectPart[i].bUsed )
- {
- list[j++] = m_objectPart[i].object;
- }
- }
- list[j] = -1; // terminate
-
- m_engine->SetHiliteRank(list); // gives the list of selected parts
- }
-}
-
-bool CObject::RetHilite()
-{
- return m_bHilite;
-}
-
-
-// Indicates whether the object is selected or not.
-
-void CObject::SetSelect(bool bMode, bool bDisplayError)
-{
- Error err;
-
- m_bSelect = bMode;
-
- if ( m_physics != 0 )
- {
- m_physics->CreateInterface(m_bSelect);
- }
-
- if ( m_auto != 0 )
- {
- m_auto->CreateInterface(m_bSelect);
- }
-
- CreateSelectParticule(); // creates / removes particles
-
- if ( !m_bSelect )
- {
- SetGunGoalH(0.0f); // puts the cannon right
- return; // selects if not finished
- }
-
- err = ERR_OK;
- if ( m_physics != 0 )
- {
- err = m_physics->RetError();
- }
- if ( m_auto != 0 )
- {
- err = m_auto->RetError();
- }
- if ( err != ERR_OK && bDisplayError )
- {
- m_displayText->DisplayError(err, this);
- }
-}
-
-// Indicates whether the object is selected or not.
-
-bool CObject::RetSelect(bool bReal)
-{
- if ( !bReal && m_main->RetFixScene() ) return false;
- return m_bSelect;
-}
-
-
-// Indicates whether the object is selectable or not.
-
-void CObject::SetSelectable(bool bMode)
-{
- m_bSelectable = bMode;
-}
-
-// Indicates whether the object is selecionnable or not.
-
-bool CObject::RetSelectable()
-{
- return m_bSelectable;
-}
-
-
-// Management of the activities of an object.
-
-void CObject::SetActivity(bool bMode)
-{
- if ( m_brain != 0 )
- {
- m_brain->SetActivity(bMode);
- }
-}
-
-bool CObject::RetActivity()
-{
- if ( m_brain != 0 )
- {
- return m_brain->RetActivity();
- }
- return false;
-}
-
-
-// Indicates if necessary to check the tokens of the object.
-
-void CObject::SetCheckToken(bool bMode)
-{
- m_bCheckToken = bMode;
-}
-
-// Indicates if necessary to check the tokens of the object.
-
-bool CObject::RetCheckToken()
-{
- return m_bCheckToken;
-}
-
-
-// Management of the visibility of an object.
-// The object is not hidden or visually disabled, but ignores detections!
-// For example: underground worm.
-
-void CObject::SetVisible(bool bVisible)
-{
- m_bVisible = bVisible;
-}
-
-bool CObject::RetVisible()
-{
- return m_bVisible;
-}
-
-
-// Management mode of operation of an object.
-// An inactive object is an object destroyed, nonexistent.
-// This mode is used for objects "resetables"
-// during training to simulate destruction.
-
-void CObject::SetEnable(bool bEnable)
-{
- m_bEnable = bEnable;
-}
-
-bool CObject::RetEnable()
-{
- return m_bEnable;
-}
-
-
-// Management mode or an object is only active when you're close.
-
-void CObject::SetProxyActivate(bool bActivate)
-{
- m_bProxyActivate = bActivate;
-}
-
-bool CObject::RetProxyActivate()
-{
- return m_bProxyActivate;
-}
-
-void CObject::SetProxyDistance(float distance)
-{
- m_proxyDistance = distance;
-}
-
-float CObject::RetProxyDistance()
-{
- return m_proxyDistance;
-}
-
-
-// Management of the method of increasing damage.
-
-void CObject::SetMagnifyDamage(float factor)
-{
- m_magnifyDamage = factor;
-}
-
-float CObject::RetMagnifyDamage()
-{
- return m_magnifyDamage;
-}
-
-
-// Management of free parameter.
-
-void CObject::SetParam(float value)
-{
- m_param = value;
-}
-
-float CObject::RetParam()
-{
- return m_param;
-}
-
-
-// Management of the mode "blocked" of an object.
-// For example, a cube of titanium is blocked while it is used to make something,
-//or a vehicle is blocked as its construction is not finished.
-
-void CObject::SetLock(bool bLock)
-{
- m_bLock = bLock;
-}
-
-bool CObject::RetLock()
-{
- return m_bLock;
-}
-
-// Management of the mode "current explosion" of an object.
-// An object in this mode is not saving.
-
-void CObject::SetExplo(bool bExplo)
-{
- m_bExplo = bExplo;
-}
-
-bool CObject::RetExplo()
-{
- return m_bExplo;
-}
-
-
-// Mode management "cargo ship" during movies.
-
-void CObject::SetCargo(bool bCargo)
-{
- m_bCargo = bCargo;
-}
-
-bool CObject::RetCargo()
-{
- return m_bCargo;
-}
-
-
-// Management of the HS mode of an object.
-
-void CObject::SetBurn(bool bBurn)
-{
- m_bBurn = bBurn;
-
-//? if ( m_botVar != 0 )
-//? {
-//? if ( m_bBurn ) m_botVar->SetUserPtr(OBJECTDELETED);
-//? else m_botVar->SetUserPtr(this);
-//? }
-}
-
-bool CObject::RetBurn()
-{
- return m_bBurn;
-}
-
-void CObject::SetDead(bool bDead)
-{
- m_bDead = bDead;
-
- if ( bDead && m_brain != 0 )
- {
- m_brain->StopProgram(); // stops the current task
- }
-
-//? if ( m_botVar != 0 )
-//? {
-//? if ( m_bDead ) m_botVar->SetUserPtr(OBJECTDELETED);
-//? else m_botVar->SetUserPtr(this);
-//? }
-}
-
-bool CObject::RetDead()
-{
- return m_bDead;
-}
-
-bool CObject::RetRuin()
-{
- return m_bBurn|m_bFlat;
-}
-
-bool CObject::RetActif()
-{
- return !m_bLock && !m_bBurn && !m_bFlat && m_bVisible && m_bEnable;
-}
-
-
-// Management of the point of aim.
-
-void CObject::SetGunGoalV(float gunGoal)
-{
- if ( m_type == OBJECT_MOBILEfc ||
- m_type == OBJECT_MOBILEtc ||
- m_type == OBJECT_MOBILEwc ||
- m_type == OBJECT_MOBILEic ) // fireball?
- {
- if ( gunGoal > 10.0f*Math::PI/180.0f ) gunGoal = 10.0f*Math::PI/180.0f;
- if ( gunGoal < -20.0f*Math::PI/180.0f ) gunGoal = -20.0f*Math::PI/180.0f;
- SetAngleZ(1, gunGoal);
- }
- else if ( m_type == OBJECT_MOBILEfi ||
- m_type == OBJECT_MOBILEti ||
- m_type == OBJECT_MOBILEwi ||
- m_type == OBJECT_MOBILEii ) // orgaball?
- {
- if ( gunGoal > 20.0f*Math::PI/180.0f ) gunGoal = 20.0f*Math::PI/180.0f;
- if ( gunGoal < -20.0f*Math::PI/180.0f ) gunGoal = -20.0f*Math::PI/180.0f;
- SetAngleZ(1, gunGoal);
- }
- else if ( m_type == OBJECT_MOBILErc ) // phazer?
- {
- if ( gunGoal > 45.0f*Math::PI/180.0f ) gunGoal = 45.0f*Math::PI/180.0f;
- if ( gunGoal < -20.0f*Math::PI/180.0f ) gunGoal = -20.0f*Math::PI/180.0f;
- SetAngleZ(2, gunGoal);
- }
- else
- {
- gunGoal = 0.0f;
- }
-
- m_gunGoalV = gunGoal;
-}
-
-void CObject::SetGunGoalH(float gunGoal)
-{
- if ( m_type == OBJECT_MOBILEfc ||
- m_type == OBJECT_MOBILEtc ||
- m_type == OBJECT_MOBILEwc ||
- m_type == OBJECT_MOBILEic ) // fireball?
- {
- if ( gunGoal > 40.0f*Math::PI/180.0f ) gunGoal = 40.0f*Math::PI/180.0f;
- if ( gunGoal < -40.0f*Math::PI/180.0f ) gunGoal = -40.0f*Math::PI/180.0f;
- SetAngleY(1, gunGoal);
- }
- else if ( m_type == OBJECT_MOBILEfi ||
- m_type == OBJECT_MOBILEti ||
- m_type == OBJECT_MOBILEwi ||
- m_type == OBJECT_MOBILEii ) // orgaball?
- {
- if ( gunGoal > 40.0f*Math::PI/180.0f ) gunGoal = 40.0f*Math::PI/180.0f;
- if ( gunGoal < -40.0f*Math::PI/180.0f ) gunGoal = -40.0f*Math::PI/180.0f;
- SetAngleY(1, gunGoal);
- }
- else if ( m_type == OBJECT_MOBILErc ) // phazer?
- {
- if ( gunGoal > 40.0f*Math::PI/180.0f ) gunGoal = 40.0f*Math::PI/180.0f;
- if ( gunGoal < -40.0f*Math::PI/180.0f ) gunGoal = -40.0f*Math::PI/180.0f;
- SetAngleY(2, gunGoal);
- }
- else
- {
- gunGoal = 0.0f;
- }
-
- m_gunGoalH = gunGoal;
-}
-
-float CObject::RetGunGoalV()
-{
- return m_gunGoalV;
-}
-
-float CObject::RetGunGoalH()
-{
- return m_gunGoalH;
-}
-
-
-
-// Shows the limits of the object.
-
-bool CObject::StartShowLimit()
-{
- if ( m_showLimitRadius == 0.0f ) return false;
-
- m_main->SetShowLimit(0, PARTILIMIT1, this, RetPosition(0), m_showLimitRadius);
- m_bShowLimit = true;
- return true;
-}
-
-void CObject::StopShowLimit()
-{
- m_bShowLimit = false;
-}
-
-
-
-// Indicates whether a program is under execution.
-
-bool CObject::IsProgram()
-{
- if ( m_brain == 0 ) return false;
- return m_brain->IsProgram();
-}
-
-
-// Creates or removes particles associated to the object.
-
-void CObject::CreateSelectParticule()
-{
- Math::Vector pos, speed;
- Math::Point dim;
- int i;
-
- // Removes particles preceding.
- for ( i=0 ; i<4 ; i++ )
- {
- if ( m_partiSel[i] != -1 )
- {
- m_particule->DeleteParticule(m_partiSel[i]);
- m_partiSel[i] = -1;
- }
- }
-
- if ( m_bSelect || IsProgram() )
- {
- // Creates particles lens for the headlights.
- if ( m_type == OBJECT_MOBILEfa ||
- m_type == OBJECT_MOBILEta ||
- m_type == OBJECT_MOBILEwa ||
- m_type == OBJECT_MOBILEia ||
- m_type == OBJECT_MOBILEfc ||
- m_type == OBJECT_MOBILEtc ||
- m_type == OBJECT_MOBILEwc ||
- m_type == OBJECT_MOBILEic ||
- m_type == OBJECT_MOBILEfi ||
- m_type == OBJECT_MOBILEti ||
- m_type == OBJECT_MOBILEwi ||
- m_type == OBJECT_MOBILEii ||
- m_type == OBJECT_MOBILEfs ||
- m_type == OBJECT_MOBILEts ||
- m_type == OBJECT_MOBILEws ||
- m_type == OBJECT_MOBILEis ||
- m_type == OBJECT_MOBILErt ||
- m_type == OBJECT_MOBILErc ||
- m_type == OBJECT_MOBILErr ||
- m_type == OBJECT_MOBILErs ||
- m_type == OBJECT_MOBILEsa ||
- m_type == OBJECT_MOBILEtg ||
- m_type == OBJECT_MOBILEft ||
- m_type == OBJECT_MOBILEtt ||
- m_type == OBJECT_MOBILEwt ||
- m_type == OBJECT_MOBILEit ||
- m_type == OBJECT_MOBILEdr ) // vehicle?
- {
- pos = Math::Vector(0.0f, 0.0f, 0.0f);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 0.0f;
- dim.y = 0.0f;
- m_partiSel[0] = m_particule->CreateParticule(pos, speed, dim, PARTISELY, 1.0f, 0.0f, 0.0f);
- m_partiSel[1] = m_particule->CreateParticule(pos, speed, dim, PARTISELY, 1.0f, 0.0f, 0.0f);
- m_partiSel[2] = m_particule->CreateParticule(pos, speed, dim, PARTISELR, 1.0f, 0.0f, 0.0f);
- m_partiSel[3] = m_particule->CreateParticule(pos, speed, dim, PARTISELR, 1.0f, 0.0f, 0.0f);
- UpdateSelectParticule();
- }
- }
-}
-
-// Updates the particles associated to the object.
-
-void CObject::UpdateSelectParticule()
-{
- Math::Vector pos[4];
- Math::Point dim[4];
- float zoom[4];
- float angle;
- int i;
-
- if ( !m_bSelect && !IsProgram() ) return;
-
- dim[0].x = 1.0f;
- dim[1].x = 1.0f;
- dim[2].x = 1.2f;
- dim[3].x = 1.2f;
-
- // Lens front yellow.
- if ( m_type == OBJECT_MOBILErt ||
- m_type == OBJECT_MOBILErc ||
- m_type == OBJECT_MOBILErr ||
- m_type == OBJECT_MOBILErs ) // large caterpillars?
- {
- pos[0] = Math::Vector(4.2f, 2.8f, 1.5f);
- pos[1] = Math::Vector(4.2f, 2.8f, -1.5f);
- dim[0].x = 1.5f;
- dim[1].x = 1.5f;
- }
- else if ( m_type == OBJECT_MOBILEwt ||
- m_type == OBJECT_MOBILEtt ||
- m_type == OBJECT_MOBILEft ||
- m_type == OBJECT_MOBILEit ) // trainer ?
- {
- pos[0] = Math::Vector(4.2f, 2.5f, 1.2f);
- pos[1] = Math::Vector(4.2f, 2.5f, -1.2f);
- dim[0].x = 1.5f;
- dim[1].x = 1.5f;
- }
- else if ( m_type == OBJECT_MOBILEsa ) // submarine?
- {
- pos[0] = Math::Vector(3.6f, 4.0f, 2.0f);
- pos[1] = Math::Vector(3.6f, 4.0f, -2.0f);
- }
- else if ( m_type == OBJECT_MOBILEtg ) // target?
- {
- pos[0] = Math::Vector(3.4f, 6.5f, 2.0f);
- pos[1] = Math::Vector(3.4f, 6.5f, -2.0f);
- }
- else if ( m_type == OBJECT_MOBILEdr ) // designer?
- {
- pos[0] = Math::Vector(4.9f, 3.5f, 2.5f);
- pos[1] = Math::Vector(4.9f, 3.5f, -2.5f);
- }
- else
- {
- pos[0] = Math::Vector(4.2f, 2.5f, 1.5f);
- pos[1] = Math::Vector(4.2f, 2.5f, -1.5f);
- }
-
- // Red back lens
- if ( m_type == OBJECT_MOBILEfa ||
- m_type == OBJECT_MOBILEfc ||
- m_type == OBJECT_MOBILEfi ||
- m_type == OBJECT_MOBILEfs ||
- m_type == OBJECT_MOBILEft ) // flying?
- {
- pos[2] = Math::Vector(-4.0f, 3.1f, 4.5f);
- pos[3] = Math::Vector(-4.0f, 3.1f, -4.5f);
- dim[2].x = 0.6f;
- dim[3].x = 0.6f;
- }
- if ( m_type == OBJECT_MOBILEwa ||
- m_type == OBJECT_MOBILEwc ||
- m_type == OBJECT_MOBILEwi ||
- m_type == OBJECT_MOBILEws ) // wheels?
- {
- pos[2] = Math::Vector(-4.5f, 2.7f, 2.8f);
- pos[3] = Math::Vector(-4.5f, 2.7f, -2.8f);
- }
- if ( m_type == OBJECT_MOBILEwt ) // wheels?
- {
- pos[2] = Math::Vector(-4.0f, 2.5f, 2.2f);
- pos[3] = Math::Vector(-4.0f, 2.5f, -2.2f);
- }
- if ( m_type == OBJECT_MOBILEia ||
- m_type == OBJECT_MOBILEic ||
- m_type == OBJECT_MOBILEii ||
- m_type == OBJECT_MOBILEis ||
- m_type == OBJECT_MOBILEit ) // legs?
- {
- pos[2] = Math::Vector(-4.5f, 2.7f, 2.8f);
- pos[3] = Math::Vector(-4.5f, 2.7f, -2.8f);
- }
- if ( m_type == OBJECT_MOBILEta ||
- m_type == OBJECT_MOBILEtc ||
- m_type == OBJECT_MOBILEti ||
- m_type == OBJECT_MOBILEts ||
- m_type == OBJECT_MOBILEtt ) // caterpillars?
- {
- pos[2] = Math::Vector(-3.6f, 4.2f, 3.0f);
- pos[3] = Math::Vector(-3.6f, 4.2f, -3.0f);
- }
- if ( m_type == OBJECT_MOBILErt ||
- m_type == OBJECT_MOBILErc ||
- m_type == OBJECT_MOBILErr ||
- m_type == OBJECT_MOBILErs ) // large caterpillars?
- {
- pos[2] = Math::Vector(-5.0f, 5.2f, 2.5f);
- pos[3] = Math::Vector(-5.0f, 5.2f, -2.5f);
- }
- if ( m_type == OBJECT_MOBILEsa ) // submarine?
- {
- pos[2] = Math::Vector(-3.6f, 4.0f, 2.0f);
- pos[3] = Math::Vector(-3.6f, 4.0f, -2.0f);
- }
- if ( m_type == OBJECT_MOBILEtg ) // target?
- {
- pos[2] = Math::Vector(-2.4f, 6.5f, 2.0f);
- pos[3] = Math::Vector(-2.4f, 6.5f, -2.0f);
- }
- if ( m_type == OBJECT_MOBILEdr ) // designer?
- {
- pos[2] = Math::Vector(-5.3f, 2.7f, 1.8f);
- pos[3] = Math::Vector(-5.3f, 2.7f, -1.8f);
- }
-
- angle = RetAngleY(0)/Math::PI;
-
- zoom[0] = 1.0f;
- zoom[1] = 1.0f;
- zoom[2] = 1.0f;
- zoom[3] = 1.0f;
-
- if ( IsProgram() && // current program?
- Math::Mod(m_aTime, 0.7f) < 0.3f )
- {
- zoom[0] = 0.0f; // blinks
- zoom[1] = 0.0f;
- zoom[2] = 0.0f;
- zoom[3] = 0.0f;
- }
-
- // Updates lens.
- for ( i=0 ; i<4 ; i++ )
- {
- pos[i] = Math::Transform(m_objectPart[0].matWorld, pos[i]);
- dim[i].y = dim[i].x;
- m_particule->SetParam(m_partiSel[i], pos[i], dim[i], zoom[i], angle, 1.0f);
- }
-}
-
-
-// Gives the pointer to the current script execution.
-
-void CObject::SetRunScript(CScript* script)
-{
- m_runScript = script;
-}
-
-CScript* CObject::RetRunScript()
-{
- return m_runScript;
-}
-
-// Returns the variables of "this" for CBOT.
-
-CBotVar* CObject::RetBotVar()
-{
- return m_botVar;
-}
-
-// Returns the physics associated to the object.
-
-CPhysics* CObject::RetPhysics()
-{
- return m_physics;
-}
-
-// Returns the brain associated to the object.
-
-CBrain* CObject::RetBrain()
-{
- return m_brain;
-}
-
-// Returns the movement associated to the object.
-
-CMotion* CObject::RetMotion()
-{
- return m_motion;
-}
-
-// Returns the controller associated to the object.
-
-CAuto* CObject::RetAuto()
-{
- return m_auto;
-}
-
-void CObject::SetAuto(CAuto* automat)
-{
- m_auto = automat;
-}
-
-
-
-// Management of the position in the file definition.
-
-void CObject::SetDefRank(int rank)
-{
- m_defRank = rank;
-}
-
-int CObject::RetDefRank()
-{
- return m_defRank;
-}
-
-
-// Gives the object name for the tooltip.
-
-bool CObject::GetTooltipName(char* name)
-{
- GetResource(RES_OBJECT, m_type, name);
- return ( name[0] != 0 );
-}
-
-
-// Adds the object previously selected in the list.
-
-void CObject::AddDeselList(CObject* pObj)
-{
- int i;
-
- if ( m_totalDesectList >= OBJECTMAXDESELLIST )
- {
- for ( i=0 ; i<OBJECTMAXDESELLIST-1 ; i++ )
- {
- m_objectDeselectList[i] = m_objectDeselectList[i+1];
- }
- m_totalDesectList --;
- }
-
- m_objectDeselectList[m_totalDesectList++] = pObj;
-}
-
-// Removes the previously selected object in the list.
-
-CObject* CObject::SubDeselList()
-{
- if ( m_totalDesectList == 0 ) return 0;
-
- return m_objectDeselectList[--m_totalDesectList];
-}
-
-// Removes an object reference if it is in the list.
-
-void CObject::DeleteDeselList(CObject* pObj)
-{
- int i, j;
-
- j = 0;
- for ( i=0 ; i<m_totalDesectList ; i++ )
- {
- if ( m_objectDeselectList[i] != pObj )
- {
- m_objectDeselectList[j++] = m_objectDeselectList[i];
- }
- }
- m_totalDesectList = j;
-}
-
-
-
-// Management of the state of the pencil drawing robot.
-
-bool CObject::RetTraceDown()
-{
- CMotionVehicle* mv;
- if ( m_motion == 0 ) return false;
- mv = (CMotionVehicle*)m_motion;
- return mv->RetTraceDown();
-}
-
-void CObject::SetTraceDown(bool bDown)
-{
- CMotionVehicle* mv;
- if ( m_motion == 0 ) return;
- mv = (CMotionVehicle*)m_motion;
- mv->SetTraceDown(bDown);
-}
-
-int CObject::RetTraceColor()
-{
- CMotionVehicle* mv;
- if ( m_motion == 0 ) return 0;
- mv = (CMotionVehicle*)m_motion;
- return mv->RetTraceColor();
-}
-
-void CObject::SetTraceColor(int color)
-{
- CMotionVehicle* mv;
- if ( m_motion == 0 ) return;
- mv = (CMotionVehicle*)m_motion;
- mv->SetTraceColor(color);
-}
-
-float CObject::RetTraceWidth()
-{
- CMotionVehicle* mv;
- if ( m_motion == 0 ) return 0.0f;
- mv = (CMotionVehicle*)m_motion;
- return mv->RetTraceWidth();
-}
-
-void CObject::SetTraceWidth(float width)
-{
- CMotionVehicle* mv;
- if ( m_motion == 0 ) return;
- mv = (CMotionVehicle*)m_motion;
- mv->SetTraceWidth(width);
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// object.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "CBot/CBotDll.h"
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "old/d3dutil.h"
+#include "common/global.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "old/math3d.h"
+#include "object/mainmovie.h"
+#include "object/robotmain.h"
+#include "old/light.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "old/blitz.h"
+#include "old/camera.h"
+#include "old/particule.h"
+#include "physics/physics.h"
+#include "object/brain.h"
+#include "object/motion/motion.h"
+#include "object/motion/motionhuman.h"
+#include "object/motion/motiontoto.h"
+#include "object/motion/motionvehicle.h"
+#include "object/motion/motionmother.h"
+#include "object/motion/motionant.h"
+#include "object/motion/motionspider.h"
+#include "object/motion/motionbee.h"
+#include "object/motion/motionworm.h"
+#include "old/modfile.h"
+#include "object/auto/auto.h"
+#include "object/auto/autobase.h"
+#include "object/auto/autoportico.h"
+#include "object/auto/autoderrick.h"
+#include "object/auto/autofactory.h"
+#include "object/auto/autorepair.h"
+#include "object/auto/autodestroyer.h"
+#include "object/auto/autostation.h"
+#include "object/auto/autoenergy.h"
+#include "object/auto/autoconvert.h"
+#include "object/auto/autotower.h"
+#include "object/auto/autoresearch.h"
+#include "object/auto/autolabo.h"
+#include "object/auto/autonuclear.h"
+#include "object/auto/autoradar.h"
+#include "object/auto/autoegg.h"
+#include "object/auto/autonest.h"
+#include "object/auto/autoroot.h"
+#include "object/auto/autoflag.h"
+#include "object/auto/autoinfo.h"
+#include "object/auto/autojostle.h"
+#include "object/auto/autopara.h"
+#include "object/auto/autosafe.h"
+#include "object/auto/autohuston.h"
+#include "object/auto/automush.h"
+#include "object/auto/autokid.h"
+#include "object/task/task.h"
+#include "old/pyro.h"
+#include "ui/displaytext.h"
+#include "script/cmdtoken.h"
+#include "script/cbottoken.h"
+#include "old/sound.h"
+#include "object/object.h"
+
+
+
+#define ADJUST_ONBOARD false // true -> adjusts the camera ONBOARD
+#define ADJUST_ARM false // true -> adjusts the manipulator arm
+const float VIRUS_DELAY = 60.0f; // duration of virus infection
+const float LOSS_SHIELD = 0.24f; // loss of the shield by shot
+const float LOSS_SHIELD_H = 0.10f; // loss of the shield for humans
+const float LOSS_SHIELD_M = 0.02f; // loss of the shield for the laying
+
+#if ADJUST_ONBOARD
+static float debug_x = 0.0f;
+static float debug_y = 0.0f;
+static float debug_z = 0.0f;
+#endif
+
+#if ADJUST_ARM
+static float debug_arm1 = 0.0f;
+static float debug_arm2 = 0.0f;
+static float debug_arm3 = 0.0f;
+#endif
+
+
+
+
+// Updates the class Object.
+
+void uObject(CBotVar* botThis, void* user)
+{
+ CObject* object = (CObject*)user;
+ CObject* power;
+ CObject* fret;
+ CPhysics* physics;
+ CBotVar *pVar, *pSub;
+ ObjectType type;
+ Math::Vector pos;
+ float value;
+ int iValue;
+
+ if ( object == 0 ) return;
+
+ physics = object->RetPhysics();
+
+ // Updates the object's type.
+ pVar = botThis->GivItemList(); // "category"
+ type = object->RetType();
+ pVar->SetValInt(type, object->RetName());
+
+ // Updates the position of the object.
+ pVar = pVar->GivNext(); // "position"
+ if ( object->RetTruck() == 0 )
+ {
+ pos = object->RetPosition(0);
+ pos.y -= object->RetWaterLevel(); // relative to sea level!
+ pSub = pVar->GivItemList(); // "x"
+ pSub->SetValFloat(pos.x/g_unit);
+ pSub = pSub->GivNext(); // "y"
+ pSub->SetValFloat(pos.z/g_unit);
+ pSub = pSub->GivNext(); // "z"
+ pSub->SetValFloat(pos.y/g_unit);
+ }
+ else // object transported?
+ {
+ pSub = pVar->GivItemList(); // "x"
+ pSub->SetInit(IS_NAN);
+ pSub = pSub->GivNext(); // "y"
+ pSub->SetInit(IS_NAN);
+ pSub = pSub->GivNext(); // "z"
+ pSub->SetInit(IS_NAN);
+ }
+
+ // Updates the angle.
+ pos = object->RetAngle(0);
+ pos += object->RetInclinaison();
+ pVar = pVar->GivNext(); // "orientation"
+ pVar->SetValFloat(360.0f-Math::Mod(pos.y*180.0f/Math::PI, 360.0f));
+ pVar = pVar->GivNext(); // "pitch"
+ pVar->SetValFloat(pos.z*180.0f/Math::PI);
+ pVar = pVar->GivNext(); // "roll"
+ pVar->SetValFloat(pos.x*180.0f/Math::PI);
+
+ // Updates the energy level of the object.
+ pVar = pVar->GivNext(); // "energyLevel"
+ value = object->RetEnergy();
+ pVar->SetValFloat(value);
+
+ // Updates the shield level of the object.
+ pVar = pVar->GivNext(); // "shieldLevel"
+ value = object->RetShield();
+ pVar->SetValFloat(value);
+
+ // Updates the temperature of the reactor.
+ pVar = pVar->GivNext(); // "temperature"
+ if ( physics == 0 ) value = 0.0f;
+ else value = 1.0f-physics->RetReactorRange();
+ pVar->SetValFloat(value);
+
+ // Updates the height above the ground.
+ pVar = pVar->GivNext(); // "altitude"
+ if ( physics == 0 ) value = 0.0f;
+ else value = physics->RetFloorHeight();
+ pVar->SetValFloat(value/g_unit);
+
+ // Updates the lifetime of the object.
+ pVar = pVar->GivNext(); // "lifeTime"
+ value = object->RetAbsTime();
+ pVar->SetValFloat(value);
+
+ // Updates the material of the object.
+ pVar = pVar->GivNext(); // "material"
+ iValue = object->RetMaterial();
+ pVar->SetValInt(iValue);
+
+ // Updates the type of battery.
+ pVar = pVar->GivNext(); // "energyCell"
+ power = object->RetPower();
+ if ( power == 0 ) pVar->SetPointer(0);
+ else pVar->SetPointer(power->RetBotVar());
+
+ // Updates the transported object's type.
+ pVar = pVar->GivNext(); // "load"
+ fret = object->RetFret();
+ if ( fret == 0 ) pVar->SetPointer(0);
+ else pVar->SetPointer(fret->RetBotVar());
+}
+
+
+
+
+// Object's constructor.
+
+CObject::CObject(CInstanceManager* iMan)
+{
+ int i;
+
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_OBJECT, this, 500);
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ m_physics = 0;
+ m_brain = 0;
+ m_motion = 0;
+ m_auto = 0;
+ m_runScript = 0;
+
+ m_type = OBJECT_FIX;
+ m_id = ++g_id;
+ m_option = 0;
+ m_name[0] = 0;
+ m_partiReactor = -1;
+ m_shadowLight = -1;
+ m_effectLight = -1;
+ m_linVibration = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_cirVibration = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_inclinaison = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_lastParticule = 0.0f;
+
+ m_power = 0;
+ m_fret = 0;
+ m_truck = 0;
+ m_truckLink = 0;
+ m_energy = 1.0f;
+ m_capacity = 1.0f;
+ m_shield = 1.0f;
+ m_range = 0.0f;
+ m_transparency = 0.0f;
+ m_lastEnergy = 999.9f;
+ m_bHilite = false;
+ m_bSelect = false;
+ m_bSelectable = true;
+ m_bCheckToken = true;
+ m_bVisible = true;
+ m_bEnable = true;
+ m_bGadget = false;
+ m_bProxyActivate = false;
+ m_bTrainer = false;
+ m_bToy = false;
+ m_bManual = false;
+ m_bFixed = false;
+ m_bClip = true;
+ m_bShowLimit = false;
+ m_showLimitRadius = 0.0f;
+ m_aTime = 0.0f;
+ m_shotTime = 0.0f;
+ m_bVirusMode = false;
+ m_virusTime = 0.0f;
+ m_lastVirusParticule = 0.0f;
+ m_totalDesectList = 0;
+ m_bLock = false;
+ m_bExplo = false;
+ m_bCargo = false;
+ m_bBurn = false;
+ m_bDead = false;
+ m_bFlat = false;
+ m_gunGoalV = 0.0f;
+ m_gunGoalH = 0.0f;
+ m_shieldRadius = 0.0f;
+ m_defRank = -1;
+ m_magnifyDamage = 1.0f;
+ m_proxyDistance = 60.0f;
+ m_param = 0.0f;
+
+ ZeroMemory(&m_character, sizeof(Character));
+ m_character.wheelFront = 1.0f;
+ m_character.wheelBack = 1.0f;
+ m_character.wheelLeft = 1.0f;
+ m_character.wheelRight = 1.0f;
+
+ m_resetCap = RESET_NONE;
+ m_bResetBusy = false;
+ m_resetPosition = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_resetAngle = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_resetRun = -1;
+
+ m_cameraType = CAMERA_BACK;
+ m_cameraDist = 50.0f;
+ m_bCameraLock = false;
+
+ m_infoTotal = 0;
+ m_infoReturn = NAN;
+ m_bInfoUpdate = false;
+
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ m_objectPart[i].bUsed = false;
+ }
+ m_totalPart = 0;
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ m_partiSel[i] = -1;
+ }
+
+ for ( i=0 ; i<OBJECTMAXCMDLINE ; i++ )
+ {
+ m_cmdLine[i] = NAN;
+ }
+
+ FlushCrashShere();
+ m_globalSpherePos = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_globalSphereRadius = 0.0f;
+ m_jotlerSpherePos = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_jotlerSphereRadius = 0.0f;
+
+ CBotClass* bc = CBotClass::Find("object");
+ if ( bc != 0 )
+ {
+ bc->AddUpdateFunc(uObject);
+ }
+
+ m_botVar = CBotVar::Create("", CBotTypResult(CBotTypClass, "object"));
+ m_botVar->SetUserPtr(this);
+ m_botVar->SetIdent(m_id);
+}
+
+// Object's destructor.
+
+CObject::~CObject()
+{
+ if ( m_botVar != 0 )
+ {
+ m_botVar->SetUserPtr(OBJECTDELETED);
+ delete m_botVar;
+ }
+
+ delete m_physics;
+ delete m_brain;
+ delete m_motion;
+ delete m_auto;
+
+ m_iMan->DeleteInstance(CLASS_OBJECT, this);
+}
+
+
+// Removes an object.
+// If bAll = true, it does not help,
+// because all objects in the scene are quickly destroyed!
+
+void CObject::DeleteObject(bool bAll)
+{
+ CObject* pObj;
+ CPyro* pPyro;
+ int i;
+
+ if ( m_botVar != 0 )
+ {
+ m_botVar->SetUserPtr(OBJECTDELETED);
+ }
+
+ if ( m_camera->RetObject() == this )
+ {
+ m_camera->SetObject(0);
+ }
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ pObj->DeleteDeselList(this);
+ }
+
+ if ( !bAll )
+ {
+#if 0
+ type = m_camera->RetType();
+ if ( (type == CAMERA_BACK ||
+ type == CAMERA_FIX ||
+ type == CAMERA_EXPLO ||
+ type == CAMERA_ONBOARD) &&
+ m_camera->RetObject() == this )
+ {
+ pObj = m_main->SearchNearest(RetPosition(0), this);
+ if ( pObj == 0 )
+ {
+ m_camera->SetObject(0);
+ m_camera->SetType(CAMERA_FREE);
+ }
+ else
+ {
+ m_camera->SetObject(pObj);
+ m_camera->SetType(CAMERA_BACK);
+ }
+ }
+#endif
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pPyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, i);
+ if ( pPyro == 0 ) break;
+
+ pPyro->CutObjectLink(this); // the object no longer exists
+ }
+
+ if ( m_bSelect )
+ {
+ SetSelect(false);
+ }
+
+ if ( m_type == OBJECT_BASE ||
+ m_type == OBJECT_FACTORY ||
+ m_type == OBJECT_REPAIR ||
+ m_type == OBJECT_DESTROYER||
+ m_type == OBJECT_DERRICK ||
+ m_type == OBJECT_STATION ||
+ m_type == OBJECT_CONVERT ||
+ m_type == OBJECT_TOWER ||
+ m_type == OBJECT_RESEARCH ||
+ m_type == OBJECT_RADAR ||
+ m_type == OBJECT_INFO ||
+ m_type == OBJECT_ENERGY ||
+ m_type == OBJECT_LABO ||
+ m_type == OBJECT_NUCLEAR ||
+ m_type == OBJECT_PARA ||
+ m_type == OBJECT_SAFE ||
+ m_type == OBJECT_HUSTON ||
+ m_type == OBJECT_START ||
+ m_type == OBJECT_END ) // building?
+ {
+ m_terrain->DeleteBuildingLevel(RetPosition(0)); // flattens the field
+ }
+ }
+
+ m_type = OBJECT_NULL; // invalid object until complete destruction
+
+ if ( m_partiReactor != -1 )
+ {
+ m_particule->DeleteParticule(m_partiReactor);
+ m_partiReactor = -1;
+ }
+
+ if ( m_shadowLight != -1 )
+ {
+ m_light->DeleteLight(m_shadowLight);
+ m_shadowLight = -1;
+ }
+
+ if ( m_effectLight != -1 )
+ {
+ m_light->DeleteLight(m_effectLight);
+ m_effectLight = -1;
+ }
+
+ if ( m_physics != 0 )
+ {
+ m_physics->DeleteObject(bAll);
+ }
+
+ if ( m_brain != 0 )
+ {
+ m_brain->DeleteObject(bAll);
+ }
+
+ if ( m_motion != 0 )
+ {
+ m_motion->DeleteObject(bAll);
+ }
+
+ if ( m_auto != 0 )
+ {
+ m_auto->DeleteObject(bAll);
+ }
+
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ if ( m_objectPart[i].bUsed )
+ {
+ m_objectPart[i].bUsed = false;
+ m_engine->DeleteObject(m_objectPart[i].object);
+
+ if ( m_objectPart[i].masterParti != -1 )
+ {
+ m_particule->DeleteParticule(m_objectPart[i].masterParti);
+ m_objectPart[i].masterParti = -1;
+ }
+ }
+ }
+
+ if ( m_bShowLimit )
+ {
+ m_main->FlushShowLimit(0);
+ m_bShowLimit = false;
+ }
+
+ if ( !bAll ) m_main->CreateShortcuts();
+}
+
+// Simplifies a object (he was the brain, among others).
+
+void CObject::Simplify()
+{
+ if ( m_brain != 0 )
+ {
+ m_brain->StopProgram();
+ }
+ m_main->SaveOneScript(this);
+
+ if ( m_physics != 0 )
+ {
+ m_physics->DeleteObject();
+ delete m_physics;
+ m_physics = 0;
+ }
+
+ if ( m_brain != 0 )
+ {
+ m_brain->DeleteObject();
+ delete m_brain;
+ m_brain = 0;
+ }
+
+ if ( m_motion != 0 )
+ {
+ m_motion->DeleteObject();
+ delete m_motion;
+ m_motion = 0;
+ }
+
+ if ( m_auto != 0 )
+ {
+ m_auto->DeleteObject();
+ delete m_auto;
+ m_auto = 0;
+ }
+
+ m_main->CreateShortcuts();
+}
+
+
+// Detonates an object, when struck by a shot.
+// If false is returned, the object is still screwed.
+// If true is returned, the object is destroyed.
+
+bool CObject::ExploObject(ExploType type, float force, float decay)
+{
+ PyroType pyroType;
+ CPyro* pyro;
+ float loss, shield;
+
+ if ( type == EXPLO_BURN )
+ {
+ if ( m_type == OBJECT_MOBILEtg ||
+ m_type == OBJECT_TEEN28 || // cylinder?
+ m_type == OBJECT_METAL ||
+ m_type == OBJECT_POWER ||
+ m_type == OBJECT_ATOMIC ||
+ m_type == OBJECT_TNT ||
+ m_type == OBJECT_SCRAP1 ||
+ m_type == OBJECT_SCRAP2 ||
+ m_type == OBJECT_SCRAP3 ||
+ m_type == OBJECT_SCRAP4 ||
+ m_type == OBJECT_SCRAP5 ||
+ m_type == OBJECT_BULLET ||
+ m_type == OBJECT_EGG ) // object that isn't burning?
+ {
+ type = EXPLO_BOUM;
+ force = 1.0f;
+ decay = 1.0f;
+ }
+ }
+
+ if ( EXPLO_BOUM )
+ {
+ if ( m_shotTime < 0.5f ) return false;
+ m_shotTime = 0.0f;
+ }
+
+ if ( m_type == OBJECT_HUMAN && m_bDead ) return false;
+
+ // Calculate the power lost by the explosion.
+ if ( force == 0.0f )
+ {
+ if ( m_type == OBJECT_HUMAN )
+ {
+ loss = LOSS_SHIELD_H;
+ }
+ else if ( m_type == OBJECT_MOTHER )
+ {
+ loss = LOSS_SHIELD_M;
+ }
+ else
+ {
+ loss = LOSS_SHIELD;
+ }
+ }
+ else
+ {
+ loss = force;
+ }
+ loss *= m_magnifyDamage;
+ loss *= decay;
+
+ // Decreases the power of the shield.
+ shield = RetShield();
+ shield -= loss;
+ if ( shield < 0.0f ) shield = 0.0f;
+ SetShield(shield);
+
+ if ( shield > 0.0f ) // not dead yet?
+ {
+ if ( type == EXPLO_WATER )
+ {
+ if ( m_type == OBJECT_HUMAN )
+ {
+ pyroType = PT_SHOTH;
+ }
+ else
+ {
+ pyroType = PT_SHOTW;
+ }
+ }
+ else
+ {
+ if ( m_type == OBJECT_HUMAN )
+ {
+ pyroType = PT_SHOTH;
+ }
+ else if ( m_type == OBJECT_MOTHER )
+ {
+ pyroType = PT_SHOTM;
+ }
+ else
+ {
+ pyroType = PT_SHOTT;
+ }
+ }
+ }
+ else // completely dead?
+ {
+ if ( type == EXPLO_BURN ) // burning?
+ {
+ if ( m_type == OBJECT_MOTHER ||
+ m_type == OBJECT_ANT ||
+ m_type == OBJECT_SPIDER ||
+ m_type == OBJECT_BEE ||
+ m_type == OBJECT_WORM ||
+ m_type == OBJECT_BULLET )
+ {
+ pyroType = PT_BURNO;
+ SetBurn(true);
+ }
+ else if ( m_type == OBJECT_HUMAN )
+ {
+ pyroType = PT_DEADG;
+ }
+ else
+ {
+ pyroType = PT_BURNT;
+ SetBurn(true);
+ }
+ SetVirusMode(false);
+ }
+ else if ( type == EXPLO_WATER )
+ {
+ if ( m_type == OBJECT_HUMAN )
+ {
+ pyroType = PT_DEADW;
+ }
+ else
+ {
+ pyroType = PT_FRAGW;
+ }
+ }
+ else // explosion?
+ {
+ if ( m_type == OBJECT_ANT ||
+ m_type == OBJECT_SPIDER ||
+ m_type == OBJECT_BEE ||
+ m_type == OBJECT_WORM )
+ {
+ pyroType = PT_EXPLOO;
+ }
+ else if ( m_type == OBJECT_MOTHER ||
+ m_type == OBJECT_NEST ||
+ m_type == OBJECT_BULLET )
+ {
+ pyroType = PT_FRAGO;
+ }
+ else if ( m_type == OBJECT_HUMAN )
+ {
+ pyroType = PT_DEADG;
+ }
+ else if ( m_type == OBJECT_BASE ||
+ m_type == OBJECT_DERRICK ||
+ m_type == OBJECT_FACTORY ||
+ m_type == OBJECT_STATION ||
+ m_type == OBJECT_CONVERT ||
+ m_type == OBJECT_REPAIR ||
+ m_type == OBJECT_DESTROYER||
+ m_type == OBJECT_TOWER ||
+ m_type == OBJECT_NEST ||
+ m_type == OBJECT_RESEARCH ||
+ m_type == OBJECT_RADAR ||
+ m_type == OBJECT_INFO ||
+ m_type == OBJECT_ENERGY ||
+ m_type == OBJECT_LABO ||
+ m_type == OBJECT_NUCLEAR ||
+ m_type == OBJECT_PARA ||
+ m_type == OBJECT_SAFE ||
+ m_type == OBJECT_HUSTON ||
+ m_type == OBJECT_START ||
+ m_type == OBJECT_END ) // building?
+ {
+ pyroType = PT_FRAGT;
+ }
+ else if ( m_type == OBJECT_MOBILEtg ||
+ m_type == OBJECT_TEEN28 || // cylinder?
+ m_type == OBJECT_TEEN31 ) // basket?
+ {
+ pyroType = PT_FRAGT;
+ }
+ else
+ {
+ pyroType = PT_EXPLOT;
+ }
+ }
+
+ loss = 1.0f;
+ }
+
+ pyro = new CPyro(m_iMan);
+ pyro->Create(pyroType, this, loss);
+
+ if ( shield == 0.0f ) // dead?
+ {
+ if ( m_brain != 0 )
+ {
+ m_brain->StopProgram();
+ }
+ m_main->SaveOneScript(this);
+ }
+
+ if ( shield > 0.0f ) return false; // not dead yet
+
+ if ( RetSelect() )
+ {
+ SetSelect(false); // deselects the object
+ m_camera->SetType(CAMERA_EXPLO);
+ m_main->DeselectAll();
+ }
+ DeleteDeselList(this);
+
+ if ( m_botVar != 0 )
+ {
+ if ( m_type == OBJECT_STONE ||
+ m_type == OBJECT_URANIUM ||
+ m_type == OBJECT_METAL ||
+ m_type == OBJECT_POWER ||
+ m_type == OBJECT_ATOMIC ||
+ m_type == OBJECT_BULLET ||
+ m_type == OBJECT_BBOX ||
+ m_type == OBJECT_TNT ||
+ m_type == OBJECT_SCRAP1 ||
+ m_type == OBJECT_SCRAP2 ||
+ m_type == OBJECT_SCRAP3 ||
+ m_type == OBJECT_SCRAP4 ||
+ m_type == OBJECT_SCRAP5 ) // (*)
+ {
+ m_botVar->SetUserPtr(OBJECTDELETED);
+ }
+ }
+
+ return true;
+}
+
+// (*) If a robot or cosmonaut dies, the subject must continue to exist,
+// so that programs of the ants continue to operate as usual.
+
+
+// Initializes a new part.
+
+void CObject::InitPart(int part)
+{
+ m_objectPart[part].bUsed = true;
+ m_objectPart[part].object = -1;
+ m_objectPart[part].parentPart = -1;
+
+ m_objectPart[part].position = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_objectPart[part].angle.y = 0.0f;
+ m_objectPart[part].angle.x = 0.0f;
+ m_objectPart[part].angle.z = 0.0f;
+ m_objectPart[part].zoom = Math::Vector(1.0f, 1.0f, 1.0f);
+
+ m_objectPart[part].bTranslate = true;
+ m_objectPart[part].bRotate = true;
+ m_objectPart[part].bZoom = false;
+
+ m_objectPart[part].matTranslate.LoadIdentity();
+ m_objectPart[part].matRotate.LoadIdentity();
+ m_objectPart[part].matTransform.LoadIdentity();
+ m_objectPart[part].matWorld.LoadIdentity();;
+
+ m_objectPart[part].masterParti = -1;
+}
+
+// Creates a new part, and returns its number.
+// Returns -1 on error.
+
+int CObject::CreatePart()
+{
+ int i;
+
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ if ( m_objectPart[i].bUsed ) continue;
+
+ InitPart(i);
+ UpdateTotalPart();
+ return i;
+ }
+ return -1;
+}
+
+// Removes part.
+
+void CObject::DeletePart(int part)
+{
+ if ( !m_objectPart[part].bUsed ) return;
+
+ if ( m_objectPart[part].masterParti != -1 )
+ {
+ m_particule->DeleteParticule(m_objectPart[part].masterParti);
+ m_objectPart[part].masterParti = -1;
+ }
+
+ m_objectPart[part].bUsed = false;
+ m_engine->DeleteObject(m_objectPart[part].object);
+ UpdateTotalPart();
+}
+
+void CObject::UpdateTotalPart()
+{
+ int i;
+
+ m_totalPart = 0;
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ if ( m_objectPart[i].bUsed )
+ {
+ m_totalPart = i+1;
+ }
+ }
+}
+
+
+// Specifies the number of the object of a part.
+
+void CObject::SetObjectRank(int part, int objRank)
+{
+ if ( !m_objectPart[part].bUsed ) // object not created?
+ {
+ InitPart(part);
+ UpdateTotalPart();
+ }
+ m_objectPart[part].object = objRank;
+}
+
+// Returns the number of part.
+
+int CObject::RetObjectRank(int part)
+{
+ if ( !m_objectPart[part].bUsed ) return -1;
+ return m_objectPart[part].object;
+}
+
+// Specifies what is the parent of a part.
+// Reminder: Part 0 is always the father of all
+// and therefore the main part (eg the chassis of a car).
+
+void CObject::SetObjectParent(int part, int parent)
+{
+ m_objectPart[part].parentPart = parent;
+}
+
+
+// Specifies the type of the object.
+
+void CObject::SetType(ObjectType type)
+{
+ m_type = type;
+ strcpy(m_name, RetObjectName(m_type));
+
+ if ( m_type == OBJECT_MOBILErs )
+ {
+ m_param = 1.0f; // shield up to default
+ }
+
+ if ( m_type == OBJECT_ATOMIC )
+ {
+ m_capacity = 10.0f;
+ }
+ else
+ {
+ m_capacity = 1.0f;
+ }
+
+ if ( m_type == OBJECT_MOBILEwc ||
+ m_type == OBJECT_MOBILEtc ||
+ m_type == OBJECT_MOBILEfc ||
+ m_type == OBJECT_MOBILEic ||
+ m_type == OBJECT_MOBILEwi ||
+ m_type == OBJECT_MOBILEti ||
+ m_type == OBJECT_MOBILEfi ||
+ m_type == OBJECT_MOBILEii ||
+ m_type == OBJECT_MOBILErc ) // cannon vehicle?
+ {
+ m_cameraType = CAMERA_ONBOARD;
+ }
+}
+
+ObjectType CObject::RetType()
+{
+ return m_type;
+}
+
+char* CObject::RetName()
+{
+ return m_name;
+}
+
+
+// Choosing the option to use.
+
+void CObject::SetOption(int option)
+{
+ m_option = option;
+}
+
+int CObject::RetOption()
+{
+ return m_option;
+}
+
+
+// Management of the unique identifier of an object.
+
+void CObject::SetID(int id)
+{
+ m_id = id;
+
+ if ( m_botVar != 0 )
+ {
+ m_botVar->SetIdent(m_id);
+ }
+}
+
+int CObject::RetID()
+{
+ return m_id;
+}
+
+
+// Saves all the parameters of the object.
+
+bool CObject::Write(char *line)
+{
+ Math::Vector pos;
+ Info info;
+ char name[100];
+ float value;
+ int i;
+
+ sprintf(name, " camera=%s", GetCamera(RetCameraType()));
+ strcat(line, name);
+
+ if ( RetCameraLock() != 0 )
+ {
+ sprintf(name, " cameraLock=%d", RetCameraLock());
+ strcat(line, name);
+ }
+
+ if ( RetEnergy() != 0.0f )
+ {
+ sprintf(name, " energy=%.2f", RetEnergy());
+ strcat(line, name);
+ }
+
+ if ( RetCapacity() != 1.0f )
+ {
+ sprintf(name, " capacity=%.2f", RetCapacity());
+ strcat(line, name);
+ }
+
+ if ( RetShield() != 1.0f )
+ {
+ sprintf(name, " shield=%.2f", RetShield());
+ strcat(line, name);
+ }
+
+ if ( RetRange() != 1.0f )
+ {
+ sprintf(name, " range=%.2f", RetRange());
+ strcat(line, name);
+ }
+
+ if ( RetSelectable() != 1 )
+ {
+ sprintf(name, " selectable=%d", RetSelectable());
+ strcat(line, name);
+ }
+
+ if ( RetEnable() != 1 )
+ {
+ sprintf(name, " enable=%d", RetEnable());
+ strcat(line, name);
+ }
+
+ if ( RetFixed() != 0 )
+ {
+ sprintf(name, " fixed=%d", RetFixed());
+ strcat(line, name);
+ }
+
+ if ( RetClip() != 1 )
+ {
+ sprintf(name, " clip=%d", RetClip());
+ strcat(line, name);
+ }
+
+ if ( RetLock() != 0 )
+ {
+ sprintf(name, " lock=%d", RetLock());
+ strcat(line, name);
+ }
+
+ if ( RetProxyActivate() != 0 )
+ {
+ sprintf(name, " proxyActivate=%d", RetProxyActivate());
+ strcat(line, name);
+
+ sprintf(name, " proxyDistance=%.2f", RetProxyDistance()/g_unit);
+ strcat(line, name);
+ }
+
+ if ( RetMagnifyDamage() != 1.0f )
+ {
+ sprintf(name, " magnifyDamage=%.2f", RetMagnifyDamage());
+ strcat(line, name);
+ }
+
+ if ( RetGunGoalV() != 0.0f )
+ {
+ sprintf(name, " aimV=%.2f", RetGunGoalV());
+ strcat(line, name);
+ }
+ if ( RetGunGoalH() != 0.0f )
+ {
+ sprintf(name, " aimH=%.2f", RetGunGoalH());
+ strcat(line, name);
+ }
+
+ if ( RetParam() != 0.0f )
+ {
+ sprintf(name, " param=%.2f", RetParam());
+ strcat(line, name);
+ }
+
+ if ( RetResetCap() != 0 )
+ {
+ sprintf(name, " resetCap=%d", RetResetCap());
+ strcat(line, name);
+
+ pos = RetResetPosition()/g_unit;
+ sprintf(name, " resetPos=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
+ strcat(line, name);
+
+ pos = RetResetAngle()/(Math::PI/180.0f);
+ sprintf(name, " resetAngle=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
+ strcat(line, name);
+
+ sprintf(name, " resetRun=%d", RetResetRun());
+ strcat(line, name);
+ }
+
+ if ( m_bVirusMode != 0 )
+ {
+ sprintf(name, " virusMode=%d", m_bVirusMode);
+ strcat(line, name);
+ }
+
+ if ( m_virusTime != 0.0f )
+ {
+ sprintf(name, " virusTime=%.2f", m_virusTime);
+ strcat(line, name);
+ }
+
+ // Puts information in terminal (OBJECT_INFO).
+ for ( i=0 ; i<m_infoTotal ; i++ )
+ {
+ info = RetInfo(i);
+ if ( info.name[0] == 0 ) break;
+
+ sprintf(name, " info%d=\"%s=%.2f\"", i+1, info.name, info.value);
+ strcat(line, name);
+ }
+
+ // Sets the parameters of the command line.
+ for ( i=0 ; i<OBJECTMAXCMDLINE ; i++ )
+ {
+ value = RetCmdLine(i);
+ if ( value == NAN ) break;
+
+ if ( i == 0 ) sprintf(name, " cmdline=%.2f", value);
+ else sprintf(name, ";%.2f", value);
+ strcat(line, name);
+ }
+
+ if ( m_motion != 0 )
+ {
+ m_motion->Write(line);
+ }
+
+ if ( m_brain != 0 )
+ {
+ m_brain->Write(line);
+ }
+
+ if ( m_physics != 0 )
+ {
+ m_physics->Write(line);
+ }
+
+ if ( m_auto != 0 )
+ {
+ m_auto->Write(line);
+ }
+
+ return true;
+}
+
+// Returns all parameters of the object.
+
+bool CObject::Read(char *line)
+{
+ Math::Vector pos, dir;
+ Info info;
+ CameraType cType;
+ char op[20];
+ char text[100];
+ char* p;
+ float value;
+ int i;
+
+ cType = OpCamera(line, "camera");
+ if ( cType != CAMERA_NULL )
+ {
+ SetCameraType(cType);
+ }
+
+ SetCameraLock(OpInt(line, "cameraLock", 0));
+ SetEnergy(OpFloat(line, "energy", 0.0f));
+ SetCapacity(OpFloat(line, "capacity", 1.0f));
+ SetShield(OpFloat(line, "shield", 1.0f));
+ SetRange(OpFloat(line, "range", 1.0f));
+ SetSelectable(OpInt(line, "selectable", 1));
+ SetEnable(OpInt(line, "enable", 1));
+ SetFixed(OpInt(line, "fixed", 0));
+ SetClip(OpInt(line, "clip", 1));
+ SetLock(OpInt(line, "lock", 0));
+ SetProxyActivate(OpInt(line, "proxyActivate", 0));
+ SetProxyDistance(OpFloat(line, "proxyDistance", 15.0f)*g_unit);
+ SetRange(OpFloat(line, "range", 30.0f));
+ SetMagnifyDamage(OpFloat(line, "magnifyDamage", 1.0f));
+ SetGunGoalV(OpFloat(line, "aimV", 0.0f));
+ SetGunGoalH(OpFloat(line, "aimH", 0.0f));
+ SetParam(OpFloat(line, "param", 0.0f));
+ SetResetCap((ResetCap)OpInt(line, "resetCap", 0));
+ SetResetPosition(OpDir(line, "resetPos")*g_unit);
+ SetResetAngle(OpDir(line, "resetAngle")*(Math::PI/180.0f));
+ SetResetRun(OpInt(line, "resetRun", 0));
+ m_bBurn = OpInt(line, "burnMode", 0);
+ m_bVirusMode = OpInt(line, "virusMode", 0);
+ m_virusTime = OpFloat(line, "virusTime", 0.0f);
+
+ // Puts information in terminal (OBJECT_INFO).
+ for ( i=0 ; i<OBJECTMAXINFO ; i++ )
+ {
+ sprintf(op, "info%d", i+1);
+ OpString(line, op, text);
+ if ( text[0] == 0 ) break;
+ p = strchr(text, '=');
+ if ( p == 0 ) break;
+ *p = 0;
+ strcpy(info.name, text);
+ sscanf(p+1, "%f", &info.value);
+ SetInfo(i, info);
+ }
+
+ // Sets the parameters of the command line.
+ p = SearchOp(line, "cmdline");
+ for ( i=0 ; i<OBJECTMAXCMDLINE ; i++ )
+ {
+ value = GetFloat(p, i, NAN);
+ if ( value == NAN ) break;
+ SetCmdLine(i, value);
+ }
+
+ if ( m_motion != 0 )
+ {
+ m_motion->Read(line);
+ }
+
+ if ( m_brain != 0 )
+ {
+ m_brain->Read(line);
+ }
+
+ if ( m_physics != 0 )
+ {
+ m_physics->Read(line);
+ }
+
+ if ( m_auto != 0 )
+ {
+ m_auto->Read(line);
+ }
+
+ return true;
+}
+
+
+
+// Seeking the nth son of a father.
+
+int CObject::SearchDescendant(int parent, int n)
+{
+ int i;
+
+ for ( i=0 ; i<m_totalPart ; i++ )
+ {
+ if ( !m_objectPart[i].bUsed ) continue;
+
+ if ( parent == m_objectPart[i].parentPart )
+ {
+ if ( n-- == 0 ) return i;
+ }
+ }
+ return -1;
+}
+
+
+// Removes all spheres used for collisions.
+
+void CObject::FlushCrashShere()
+{
+ m_crashSphereUsed = 0;
+}
+
+// Adds a new sphere.
+
+int CObject::CreateCrashSphere(Math::Vector pos, float radius, Sound sound,
+ float hardness)
+{
+ float zoom;
+
+ if ( m_crashSphereUsed >= MAXCRASHSPHERE ) return -1;
+
+ zoom = RetZoomX(0);
+ m_crashSpherePos[m_crashSphereUsed] = pos;
+ m_crashSphereRadius[m_crashSphereUsed] = radius*zoom;
+ m_crashSphereHardness[m_crashSphereUsed] = hardness;
+ m_crashSphereSound[m_crashSphereUsed] = sound;
+ return m_crashSphereUsed++;
+}
+
+// Returns the number of spheres.
+
+int CObject::RetCrashSphereTotal()
+{
+ return m_crashSphereUsed;
+}
+
+// Returns a sphere for collisions.
+// The position is absolute in the world.
+
+bool CObject::GetCrashSphere(int rank, Math::Vector &pos, float &radius)
+{
+ if ( rank < 0 || rank >= m_crashSphereUsed )
+ {
+ pos = m_objectPart[0].position;
+ radius = 0.0f;
+ return false;
+ }
+
+ // Returns to the sphere collisions,
+ // which ignores the inclination of the vehicle.
+ // This is necessary to collisions with vehicles,
+ // so as not to reflect SetInclinaison, for example.
+ // The sphere must necessarily have a center (0, y, 0).
+ if ( rank == 0 && m_crashSphereUsed == 1 &&
+ m_crashSpherePos[0].x == 0.0f &&
+ m_crashSpherePos[0].z == 0.0f )
+ {
+ pos = m_objectPart[0].position + m_crashSpherePos[0];
+ radius = m_crashSphereRadius[0];
+ return true;
+ }
+
+ if ( m_objectPart[0].bTranslate ||
+ m_objectPart[0].bRotate )
+ {
+ UpdateTransformObject();
+ }
+ pos = Math::Transform(m_objectPart[0].matWorld, m_crashSpherePos[rank]);
+ radius = m_crashSphereRadius[rank];
+ return true;
+}
+
+// Returns the hardness of a sphere.
+
+Sound CObject::RetCrashSphereSound(int rank)
+{
+ return m_crashSphereSound[rank];
+}
+
+// Returns the hardness of a sphere.
+
+float CObject::RetCrashSphereHardness(int rank)
+{
+ return m_crashSphereHardness[rank];
+}
+
+// Deletes a sphere.
+
+void CObject::DeleteCrashSphere(int rank)
+{
+ int i;
+
+ if ( rank < 0 || rank >= m_crashSphereUsed ) return;
+
+ for ( i=rank+1 ; i<MAXCRASHSPHERE ; i++ )
+ {
+ m_crashSpherePos[i-1] = m_crashSpherePos[i];
+ m_crashSphereRadius[i-1] = m_crashSphereRadius[i];
+ }
+ m_crashSphereUsed --;
+}
+
+// Specifies the global sphere, relative to the object.
+
+void CObject::SetGlobalSphere(Math::Vector pos, float radius)
+{
+ float zoom;
+
+ zoom = RetZoomX(0);
+ m_globalSpherePos = pos;
+ m_globalSphereRadius = radius*zoom;
+}
+
+// Returns the global sphere, in the world.
+
+void CObject::GetGlobalSphere(Math::Vector &pos, float &radius)
+{
+ pos = Math::Transform(m_objectPart[0].matWorld, m_globalSpherePos);
+ radius = m_globalSphereRadius;
+}
+
+
+// Specifies the sphere of jostling, relative to the object.
+
+void CObject::SetJotlerSphere(Math::Vector pos, float radius)
+{
+ m_jotlerSpherePos = pos;
+ m_jotlerSphereRadius = radius;
+}
+
+// Specifies the sphere of jostling, in the world.
+
+void CObject::GetJotlerSphere(Math::Vector &pos, float &radius)
+{
+ pos = Math::Transform(m_objectPart[0].matWorld, m_jotlerSpherePos);
+ radius = m_jotlerSphereRadius;
+}
+
+
+// Specifies the radius of the shield.
+
+void CObject::SetShieldRadius(float radius)
+{
+ m_shieldRadius = radius;
+}
+
+// Returns the radius of the shield.
+
+float CObject::RetShieldRadius()
+{
+ return m_shieldRadius;
+}
+
+
+// Positioning an object on a certain height, above the ground.
+
+void CObject::SetFloorHeight(float height)
+{
+ Math::Vector pos;
+
+ pos = m_objectPart[0].position;
+ m_terrain->MoveOnFloor(pos);
+
+ if ( m_physics != 0 )
+ {
+ m_physics->SetLand(height == 0.0f);
+ m_physics->SetMotor(height != 0.0f);
+ }
+
+ m_objectPart[0].position.y = pos.y+height+m_character.height;
+ m_objectPart[0].bTranslate = true; // it will recalculate the matrices
+}
+
+// Adjust the inclination of an object laying on the ground.
+
+void CObject::FloorAdjust()
+{
+ Math::Vector pos, n;
+ Math::Point nn;
+ float a;
+
+ pos = RetPosition(0);
+ if ( m_terrain->GetNormal(n, pos) )
+ {
+#if 0
+ SetAngleX(0, sinf(n.z));
+ SetAngleZ(0, -sinf(n.x));
+ SetAngleY(0, 0.0f);
+#else
+ a = RetAngleY(0);
+ nn = Math::RotatePoint(-a, Math::Point(n.z, n.x));
+ SetAngleX(0, sinf(nn.x));
+ SetAngleZ(0, -sinf(nn.y));
+#endif
+ }
+}
+
+
+// Gives the linear vibration.
+
+void CObject::SetLinVibration(Math::Vector dir)
+{
+ if ( m_linVibration.x != dir.x ||
+ m_linVibration.y != dir.y ||
+ m_linVibration.z != dir.z )
+ {
+ m_linVibration = dir;
+ m_objectPart[0].bTranslate = true;
+ }
+}
+
+Math::Vector CObject::RetLinVibration()
+{
+ return m_linVibration;
+}
+
+// Gives the circular vibration.
+
+void CObject::SetCirVibration(Math::Vector dir)
+{
+ if ( m_cirVibration.x != dir.x ||
+ m_cirVibration.y != dir.y ||
+ m_cirVibration.z != dir.z )
+ {
+ m_cirVibration = dir;
+ m_objectPart[0].bRotate = true;
+ }
+}
+
+Math::Vector CObject::RetCirVibration()
+{
+ return m_cirVibration;
+}
+
+// Gives the inclination.
+
+void CObject::SetInclinaison(Math::Vector dir)
+{
+ if ( m_inclinaison.x != dir.x ||
+ m_inclinaison.y != dir.y ||
+ m_inclinaison.z != dir.z )
+ {
+ m_inclinaison = dir;
+ m_objectPart[0].bRotate = true;
+ }
+}
+
+Math::Vector CObject::RetInclinaison()
+{
+ return m_inclinaison;
+}
+
+
+// Gives the position of center of the object.
+
+void CObject::SetPosition(int part, const Math::Vector &pos)
+{
+ Math::Vector shPos, n[20], norm;
+ float height, radius;
+ int rank, i, j;
+
+ m_objectPart[part].position = pos;
+ m_objectPart[part].bTranslate = true; // it will recalculate the matrices
+
+ if ( part == 0 && !m_bFlat ) // main part?
+ {
+ rank = m_objectPart[0].object;
+
+ shPos = pos;
+ m_terrain->MoveOnFloor(shPos, true);
+ m_engine->SetObjectShadowPos(rank, shPos);
+
+ if ( m_physics != 0 && m_physics->RetType() == TYPE_FLYING )
+ {
+ height = pos.y-shPos.y;
+ }
+ else
+ {
+ height = 0.0f;
+ }
+ m_engine->SetObjectShadowHeight(rank, height);
+
+ // Calculating the normal to the ground in nine strategic locations,
+ // then perform a weighted average (the dots in the center are more important).
+ radius = m_engine->RetObjectShadowRadius(rank);
+ i = 0;
+
+ m_terrain->GetNormal(norm, pos);
+ n[i++] = norm;
+ n[i++] = norm;
+ n[i++] = norm;
+
+ shPos = pos;
+ shPos.x += radius*0.6f;
+ shPos.z += radius*0.6f;
+ m_terrain->GetNormal(norm, shPos);
+ n[i++] = norm;
+ n[i++] = norm;
+
+ shPos = pos;
+ shPos.x -= radius*0.6f;
+ shPos.z += radius*0.6f;
+ m_terrain->GetNormal(norm, shPos);
+ n[i++] = norm;
+ n[i++] = norm;
+
+ shPos = pos;
+ shPos.x += radius*0.6f;
+ shPos.z -= radius*0.6f;
+ m_terrain->GetNormal(norm, shPos);
+ n[i++] = norm;
+ n[i++] = norm;
+
+ shPos = pos;
+ shPos.x -= radius*0.6f;
+ shPos.z -= radius*0.6f;
+ m_terrain->GetNormal(norm, shPos);
+ n[i++] = norm;
+ n[i++] = norm;
+
+ shPos = pos;
+ shPos.x += radius;
+ shPos.z += radius;
+ m_terrain->GetNormal(norm, shPos);
+ n[i++] = norm;
+
+ shPos = pos;
+ shPos.x -= radius;
+ shPos.z += radius;
+ m_terrain->GetNormal(norm, shPos);
+ n[i++] = norm;
+
+ shPos = pos;
+ shPos.x += radius;
+ shPos.z -= radius;
+ m_terrain->GetNormal(norm, shPos);
+ n[i++] = norm;
+
+ shPos = pos;
+ shPos.x -= radius;
+ shPos.z -= radius;
+ m_terrain->GetNormal(norm, shPos);
+ n[i++] = norm;
+
+ norm.LoadZero();
+ for ( j=0 ; j<i ; j++ )
+ {
+ norm += n[j];
+ }
+ norm /= (float)i; // average vector
+
+ m_engine->SetObjectShadowNormal(rank, norm);
+
+ if ( m_shadowLight != -1 )
+ {
+ shPos = pos;
+ shPos.y += m_shadowHeight;
+ m_light->SetLightPos(m_shadowLight, shPos);
+ }
+
+ if ( m_effectLight != -1 )
+ {
+ shPos = pos;
+ shPos.y += m_effectHeight;
+ m_light->SetLightPos(m_effectLight, shPos);
+ }
+
+ if ( m_bShowLimit )
+ {
+ m_main->AdjustShowLimit(0, pos);
+ }
+ }
+}
+
+Math::Vector CObject::RetPosition(int part)
+{
+ return m_objectPart[part].position;
+}
+
+// Gives the rotation around three axis.
+
+void CObject::SetAngle(int part, const Math::Vector &angle)
+{
+ m_objectPart[part].angle = angle;
+ m_objectPart[part].bRotate = true; // it will recalculate the matrices
+
+ if ( part == 0 && !m_bFlat ) // main part?
+ {
+ m_engine->SetObjectShadowAngle(m_objectPart[0].object, m_objectPart[0].angle.y);
+ }
+}
+
+Math::Vector CObject::RetAngle(int part)
+{
+ return m_objectPart[part].angle;
+}
+
+// Gives the rotation about the axis Y.
+
+void CObject::SetAngleY(int part, float angle)
+{
+ m_objectPart[part].angle.y = angle;
+ m_objectPart[part].bRotate = true; // it will recalculate the matrices
+
+ if ( part == 0 && !m_bFlat ) // main part?
+ {
+ m_engine->SetObjectShadowAngle(m_objectPart[0].object, m_objectPart[0].angle.y);
+ }
+}
+
+// Gives the rotation about the axis X.
+
+void CObject::SetAngleX(int part, float angle)
+{
+ m_objectPart[part].angle.x = angle;
+ m_objectPart[part].bRotate = true; // it will recalculate the matrices
+}
+
+// Gives the rotation about the axis Z.
+
+void CObject::SetAngleZ(int part, float angle)
+{
+ m_objectPart[part].angle.z = angle;
+ m_objectPart[part].bRotate = true; //it will recalculate the matrices
+}
+
+float CObject::RetAngleY(int part)
+{
+ return m_objectPart[part].angle.y;
+}
+
+float CObject::RetAngleX(int part)
+{
+ return m_objectPart[part].angle.x;
+}
+
+float CObject::RetAngleZ(int part)
+{
+ return m_objectPart[part].angle.z;
+}
+
+
+// Gives the global zoom.
+
+void CObject::SetZoom(int part, float zoom)
+{
+ m_objectPart[part].bTranslate = true; // it will recalculate the matrices
+ m_objectPart[part].zoom.x = zoom;
+ m_objectPart[part].zoom.y = zoom;
+ m_objectPart[part].zoom.z = zoom;
+
+ m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
+ m_objectPart[part].zoom.y != 1.0f ||
+ m_objectPart[part].zoom.z != 1.0f );
+}
+
+void CObject::SetZoom(int part, Math::Vector zoom)
+{
+ m_objectPart[part].bTranslate = true; // it will recalculate the matrices
+ m_objectPart[part].zoom = zoom;
+
+ m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
+ m_objectPart[part].zoom.y != 1.0f ||
+ m_objectPart[part].zoom.z != 1.0f );
+}
+
+Math::Vector CObject::RetZoom(int part)
+{
+ return m_objectPart[part].zoom;
+}
+
+void CObject::SetZoomX(int part, float zoom)
+{
+ m_objectPart[part].bTranslate = true; // it will recalculate the matrices
+ m_objectPart[part].zoom.x = zoom;
+
+ m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
+ m_objectPart[part].zoom.y != 1.0f ||
+ m_objectPart[part].zoom.z != 1.0f );
+}
+
+void CObject::SetZoomY(int part, float zoom)
+{
+ m_objectPart[part].bTranslate = true; // it will recalculate the matrices
+ m_objectPart[part].zoom.y = zoom;
+
+ m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
+ m_objectPart[part].zoom.y != 1.0f ||
+ m_objectPart[part].zoom.z != 1.0f );
+}
+
+void CObject::SetZoomZ(int part, float zoom)
+{
+ m_objectPart[part].bTranslate = true; // it will recalculate the matrices
+ m_objectPart[part].zoom.z = zoom;
+
+ m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
+ m_objectPart[part].zoom.y != 1.0f ||
+ m_objectPart[part].zoom.z != 1.0f );
+}
+
+float CObject::RetZoomX(int part)
+{
+ return m_objectPart[part].zoom.x;
+}
+
+float CObject::RetZoomY(int part)
+{
+ return m_objectPart[part].zoom.y;
+}
+
+float CObject::RetZoomZ(int part)
+{
+ return m_objectPart[part].zoom.z;
+}
+
+
+// Returns the water level.
+
+float CObject::RetWaterLevel()
+{
+ return m_water->RetLevel();
+}
+
+
+void CObject::SetTrainer(bool bEnable)
+{
+ m_bTrainer = bEnable;
+
+ if ( m_bTrainer ) // training?
+ {
+ m_cameraType = CAMERA_FIX;
+ }
+}
+
+bool CObject::RetTrainer()
+{
+ return m_bTrainer;
+}
+
+void CObject::SetToy(bool bEnable)
+{
+ m_bToy = bEnable;
+}
+
+bool CObject::RetToy()
+{
+ return m_bToy;
+}
+
+void CObject::SetManual(bool bManual)
+{
+ m_bManual = bManual;
+}
+
+bool CObject::RetManual()
+{
+ return m_bManual;
+}
+
+void CObject::SetResetCap(ResetCap cap)
+{
+ m_resetCap = cap;
+}
+
+ResetCap CObject::RetResetCap()
+{
+ return m_resetCap;
+}
+
+void CObject::SetResetBusy(bool bBusy)
+{
+ m_bResetBusy = bBusy;
+}
+
+bool CObject::RetResetBusy()
+{
+ return m_bResetBusy;
+}
+
+void CObject::SetResetPosition(const Math::Vector &pos)
+{
+ m_resetPosition = pos;
+}
+
+Math::Vector CObject::RetResetPosition()
+{
+ return m_resetPosition;
+}
+
+void CObject::SetResetAngle(const Math::Vector &angle)
+{
+ m_resetAngle = angle;
+}
+
+Math::Vector CObject::RetResetAngle()
+{
+ return m_resetAngle;
+}
+
+int CObject::RetResetRun()
+{
+ return m_resetRun;
+}
+
+void CObject::SetResetRun(int run)
+{
+ m_resetRun = run;
+}
+
+
+// Management of the particle master.
+
+void CObject::SetMasterParticule(int part, int parti)
+{
+ m_objectPart[part].masterParti = parti;
+}
+
+int CObject::RetMasterParticule(int part)
+{
+ return m_objectPart[part].masterParti;
+}
+
+
+// Management of the stack transport.
+
+void CObject::SetPower(CObject* power)
+{
+ m_power = power;
+}
+
+CObject* CObject::RetPower()
+{
+ return m_power;
+}
+
+// Management of the object transport.
+
+void CObject::SetFret(CObject* fret)
+{
+ m_fret = fret;
+}
+
+CObject* CObject::RetFret()
+{
+ return m_fret;
+}
+
+// Management of the object "truck" that transports it.
+
+void CObject::SetTruck(CObject* truck)
+{
+ m_truck = truck;
+
+ // Invisible shadow if the object is transported.
+ m_engine->SetObjectShadowHide(m_objectPart[0].object, (m_truck != 0));
+}
+
+CObject* CObject::RetTruck()
+{
+ return m_truck;
+}
+
+// Management of the conveying portion.
+
+void CObject::SetTruckPart(int part)
+{
+ m_truckLink = part;
+}
+
+int CObject::RetTruckPart()
+{
+ return m_truckLink;
+}
+
+
+// Management of user information.
+
+void CObject::InfoFlush()
+{
+ m_infoTotal = 0;
+ m_bInfoUpdate = true;
+}
+
+void CObject::DeleteInfo(int rank)
+{
+ int i;
+
+ if ( rank < 0 || rank >= m_infoTotal ) return;
+
+ for ( i=rank ; i<m_infoTotal-1 ; i++ )
+ {
+ m_info[i] = m_info[i+1];
+ }
+ m_infoTotal --;
+ m_bInfoUpdate = true;
+}
+
+void CObject::SetInfo(int rank, Info info)
+{
+ if ( rank < 0 || rank >= OBJECTMAXINFO ) return;
+ m_info[rank] = info;
+
+ if ( rank+1 > m_infoTotal ) m_infoTotal = rank+1;
+ m_bInfoUpdate = true;
+}
+
+Info CObject::RetInfo(int rank)
+{
+ if ( rank < 0 || rank >= OBJECTMAXINFO ) rank = 0;
+ return m_info[rank];
+}
+
+int CObject::RetInfoTotal()
+{
+ return m_infoTotal;
+}
+
+void CObject::SetInfoReturn(float value)
+{
+ m_infoReturn = value;
+}
+
+float CObject::RetInfoReturn()
+{
+ return m_infoReturn;
+}
+
+void CObject::SetInfoUpdate(bool bUpdate)
+{
+ m_bInfoUpdate = bUpdate;
+}
+
+bool CObject::RetInfoUpdate()
+{
+ return m_bInfoUpdate;
+}
+
+
+bool CObject::SetCmdLine(int rank, float value)
+{
+ if ( rank < 0 || rank >= OBJECTMAXCMDLINE ) return false;
+ m_cmdLine[rank] = value;
+ return true;
+}
+
+float CObject::RetCmdLine(int rank)
+{
+ if ( rank < 0 || rank >= OBJECTMAXCMDLINE ) return 0.0f;
+ return m_cmdLine[rank];
+}
+
+
+// Returns matrices of an object portion.
+
+Math::Matrix* CObject::RetRotateMatrix(int part)
+{
+ return &m_objectPart[part].matRotate;
+}
+
+Math::Matrix* CObject::RetTranslateMatrix(int part)
+{
+ return &m_objectPart[part].matTranslate;
+}
+
+Math::Matrix* CObject::RetTransformMatrix(int part)
+{
+ return &m_objectPart[part].matTransform;
+}
+
+Math::Matrix* CObject::RetWorldMatrix(int part)
+{
+ if ( m_objectPart[0].bTranslate ||
+ m_objectPart[0].bRotate )
+ {
+ UpdateTransformObject();
+ }
+
+ return &m_objectPart[part].matWorld;
+}
+
+
+// Indicates whether the object should be drawn below the interface.
+
+void CObject::SetDrawWorld(bool bDraw)
+{
+ int i;
+
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ if ( m_objectPart[i].bUsed )
+ {
+ m_engine->SetDrawWorld(m_objectPart[i].object, bDraw);
+ }
+ }
+}
+
+// Indicates whether the object should be drawn over the interface.
+
+void CObject::SetDrawFront(bool bDraw)
+{
+ int i;
+
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ if ( m_objectPart[i].bUsed )
+ {
+ m_engine->SetDrawFront(m_objectPart[i].object, bDraw);
+ }
+ }
+}
+
+
+// Creates a vehicle traveling any pose on the floor.
+
+bool CObject::CreateVehicle(Math::Vector pos, float angle, ObjectType type,
+ float power, bool bTrainer, bool bToy)
+{
+ m_type = type;
+
+ if ( type == OBJECT_TOTO )
+ {
+ m_motion = new CMotionToto(m_iMan, this);
+ m_motion->Create(pos, angle, type, 1.0f);
+ return true;
+ }
+
+ SetTrainer(bTrainer);
+ SetToy(bToy);
+
+ m_physics = new CPhysics(m_iMan, this);
+ m_brain = new CBrain(m_iMan, this);
+
+ m_physics->SetBrain(m_brain);
+ m_brain->SetPhysics(m_physics);
+
+#if 0
+ if ( type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ) // fireball cannon?
+ {
+ m_showLimitRadius = 160.0f;
+ }
+ if ( type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ) // orgaball cannon?
+ {
+ m_showLimitRadius = 160.0f;
+ }
+ if ( type == OBJECT_MOBILErc ) // phazer cannon?
+ {
+ m_showLimitRadius = 160.0f;
+ }
+ if ( type == OBJECT_MOBILErs ) // robot shield?
+ {
+ m_showLimitRadius = 50.0f;
+ }
+#endif
+ if ( type == OBJECT_MOBILErt ) // robot thumper?
+ {
+ m_showLimitRadius = 400.0f;
+ }
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH )
+ {
+ m_motion = new CMotionHuman(m_iMan, this);
+ }
+ else
+ {
+ m_motion = new CMotionVehicle(m_iMan, this);
+ }
+ if ( m_motion == 0 ) return false;
+
+ m_physics->SetMotion(m_motion);
+ m_brain->SetMotion(m_motion);
+ m_motion->SetPhysics(m_physics);
+ m_motion->SetBrain(m_brain);
+ if ( !m_motion->Create(pos, angle, type, power) )
+ {
+ if ( m_physics != 0 )
+ {
+ m_physics->DeleteObject();
+ delete m_physics;
+ m_physics = 0;
+ }
+ if ( m_brain != 0 )
+ {
+ m_brain->DeleteObject();
+ delete m_brain;
+ m_brain = 0;
+ }
+ if ( m_motion != 0 )
+ {
+ m_motion->DeleteObject();
+ delete m_motion;
+ m_motion = 0;
+ }
+ return false;
+ }
+
+ return true;
+}
+
+// Creates an insect lands on any ground.
+
+bool CObject::CreateInsect(Math::Vector pos, float angle, ObjectType type)
+{
+ m_type = type;
+
+ m_physics = new CPhysics(m_iMan, this);
+ m_brain = new CBrain(m_iMan, this);
+
+ m_physics->SetBrain(m_brain);
+ m_brain->SetPhysics(m_physics);
+
+ if ( type == OBJECT_MOTHER )
+ {
+ m_motion = new CMotionMother(m_iMan, this);
+ }
+ if ( type == OBJECT_ANT )
+ {
+ m_motion = new CMotionAnt(m_iMan, this);
+ }
+ if ( type == OBJECT_SPIDER )
+ {
+ m_motion = new CMotionSpider(m_iMan, this);
+ }
+ if ( type == OBJECT_BEE )
+ {
+ m_motion = new CMotionBee(m_iMan, this);
+ }
+ if ( type == OBJECT_WORM )
+ {
+ m_motion = new CMotionWorm(m_iMan, this);
+ }
+ if ( m_motion == 0 ) return false;
+
+ m_physics->SetMotion(m_motion);
+ m_brain->SetMotion(m_motion);
+ m_motion->SetPhysics(m_physics);
+ m_motion->SetBrain(m_brain);
+ if ( !m_motion->Create(pos, angle, type, 0.0f) )
+ {
+ if ( m_physics != 0 )
+ {
+ m_physics->DeleteObject();
+ delete m_physics;
+ m_physics = 0;
+ }
+ if ( m_brain != 0 )
+ {
+ m_brain->DeleteObject();
+ delete m_brain;
+ m_brain = 0;
+ }
+ if ( m_motion != 0 )
+ {
+ m_motion->DeleteObject();
+ delete m_motion;
+ m_motion = 0;
+ }
+ return false;
+ }
+
+ return true;
+}
+
+// Creates shade under a vehicle as a negative light.
+
+bool CObject::CreateShadowLight(float height, D3DCOLORVALUE color)
+{
+ D3DLIGHT7 light;
+ Math::Vector pos;
+
+ if ( !m_engine->RetLightMode() ) return true;
+
+ pos = RetPosition(0);
+ m_shadowHeight = height;
+
+ ZeroMemory( &light, sizeof(light) );
+ light.dltType = D3DLIGHT_SPOT;
+ light.dcvDiffuse.r = color.r;
+ light.dcvDiffuse.g = color.g;
+ light.dcvDiffuse.b = color.b;
+ light.dvPosition.x = pos.x;
+ light.dvPosition.y = pos.y+height;
+ light.dvPosition.z = pos.z;
+ light.dvDirection.x = 0.0f;
+ light.dvDirection.y = -1.0f; // against the bottom
+ light.dvDirection.z = 0.0f;
+ light.dvRange = D3DLIGHT_RANGE_MAX;
+ light.dvFalloff = 1.0f;
+ light.dvAttenuation0 = 1.0f;
+ light.dvAttenuation1 = 0.0f;
+ light.dvAttenuation2 = 0.0f;
+ light.dvTheta = 0.0f;
+ light.dvPhi = Math::PI/4.0f;
+
+ m_shadowLight = m_light->CreateLight();
+ if ( m_shadowLight == -1 ) return false;
+
+ m_light->SetLight(m_shadowLight, light);
+
+ // Only illuminates the objects on the ground.
+ m_light->SetLightIncluType(m_shadowLight, TYPETERRAIN);
+
+ return true;
+}
+
+// Returns the number of negative light shade.
+
+int CObject::RetShadowLight()
+{
+ return m_shadowLight;
+}
+
+// Creates light for the effects of a vehicle.
+
+bool CObject::CreateEffectLight(float height, D3DCOLORVALUE color)
+{
+ D3DLIGHT7 light;
+
+ if ( !m_engine->RetLightMode() ) return true;
+
+ m_effectHeight = height;
+
+ ZeroMemory( &light, sizeof(light) );
+ light.dltType = D3DLIGHT_SPOT;
+ light.dcvDiffuse.r = color.r;
+ light.dcvDiffuse.g = color.g;
+ light.dcvDiffuse.b = color.b;
+ light.dvPosition.x = 0.0f;
+ light.dvPosition.y = 0.0f+height;
+ light.dvPosition.z = 0.0f;
+ light.dvDirection.x = 0.0f;
+ light.dvDirection.y = -1.0f; // against the bottom
+ light.dvDirection.z = 0.0f;
+ light.dvRange = D3DLIGHT_RANGE_MAX;
+ light.dvFalloff = 1.0f;
+ light.dvAttenuation0 = 1.0f;
+ light.dvAttenuation1 = 0.0f;
+ light.dvAttenuation2 = 0.0f;
+ light.dvTheta = 0.0f;
+ light.dvPhi = Math::PI/4.0f;
+
+ m_effectLight = m_light->CreateLight();
+ if ( m_effectLight == -1 ) return false;
+
+ m_light->SetLight(m_effectLight, light);
+ m_light->SetLightIntensity(m_effectLight, 0.0f);
+
+ return true;
+}
+
+// Returns the number of light effects.
+
+int CObject::RetEffectLight()
+{
+ return m_effectLight;
+}
+
+// Creates the circular shadow underneath a vehicle.
+
+bool CObject::CreateShadowCircle(float radius, float intensity,
+ D3DShadowType type)
+{
+ float zoom;
+
+ if ( intensity == 0.0f ) return true;
+
+ zoom = RetZoomX(0);
+
+ m_engine->ShadowCreate(m_objectPart[0].object);
+
+ m_engine->SetObjectShadowRadius(m_objectPart[0].object, radius*zoom);
+ m_engine->SetObjectShadowIntensity(m_objectPart[0].object, intensity);
+ m_engine->SetObjectShadowHeight(m_objectPart[0].object, 0.0f);
+ m_engine->SetObjectShadowAngle(m_objectPart[0].object, m_objectPart[0].angle.y);
+ m_engine->SetObjectShadowType(m_objectPart[0].object, type);
+
+ return true;
+}
+
+// Creates a building laying on the ground.
+
+bool CObject::CreateBuilding(Math::Vector pos, float angle, float height,
+ ObjectType type, float power)
+{
+ CModFile* pModFile;
+ Math::Point p;
+ int rank, i;
+
+ if ( m_engine->RetRestCreate() < 20 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
+ SetObjectRank(0, rank);
+
+ if ( m_type == OBJECT_PORTICO )
+ {
+ pModFile->ReadModel("objects\\portico1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\portico2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 67.0f, 0.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\portico3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(0.0f, 0.0f, -33.0f));
+ SetAngleY(2, 45.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(3, rank);
+ SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\portico4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(3, Math::Vector(50.0f, 0.0f, 0.0f));
+ SetAngleY(3, -60.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(4, rank);
+ SetObjectParent(4, 3);
+ pModFile->ReadModel("objects\\portico5.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(4, Math::Vector(35.0f, 0.0f, 0.0f));
+ SetAngleY(4, -55.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(5, rank);
+ SetObjectParent(5, 1);
+ pModFile->ReadModel("objects\\portico3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(5, Math::Vector(0.0f, 0.0f, 33.0f));
+ SetAngleY(5, -45.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(6, rank);
+ SetObjectParent(6, 5);
+ pModFile->ReadModel("objects\\portico4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(6, Math::Vector(50.0f, 0.0f, 0.0f));
+ SetAngleY(6, 60.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(7, rank);
+ SetObjectParent(7, 6);
+ pModFile->ReadModel("objects\\portico5.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(7, Math::Vector(35.0f, 0.0f, 0.0f));
+ SetAngleY(7, 55.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(8, rank);
+ SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\portico6.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(8, Math::Vector(-35.0f, 50.0f, -35.0f));
+ SetAngleY(8, -Math::PI/2.0f);
+ SetZoom(8, 2.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(9, rank);
+ SetObjectParent(9, 8);
+ pModFile->ReadModel("objects\\portico7.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(9, Math::Vector(0.0f, 4.5f, 1.9f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(10, rank);
+ SetObjectParent(10, 0);
+ pModFile->ReadModel("objects\\portico6.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(10, Math::Vector(-35.0f, 50.0f, 35.0f));
+ SetAngleY(10, -Math::PI/2.0f);
+ SetZoom(10, 2.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(11, rank);
+ SetObjectParent(11, 10);
+ pModFile->ReadModel("objects\\portico7.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(11, Math::Vector(0.0f, 4.5f, 1.9f));
+
+ CreateCrashSphere(Math::Vector( 0.0f, 28.0f, 0.0f), 45.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 27.0f, 10.0f, -42.0f), 15.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 10.0f, -42.0f), 15.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-27.0f, 10.0f, -42.0f), 15.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 27.0f, 10.0f, 42.0f), 15.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 10.0f, 42.0f), 15.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-27.0f, 10.0f, 42.0f), 15.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-32.0f, 45.0f, -32.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-32.0f, 45.0f, 32.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 32.0f, 45.0f, -32.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 32.0f, 45.0f, 32.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 35.0f, 0.0f), 50.0f);
+
+ CreateShadowCircle(50.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_BASE )
+ {
+ pModFile->ReadModel("objects\\base1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ for ( i=0 ; i<8 ; i++ )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1+i, rank);
+ SetObjectParent(1+i, 0);
+ pModFile->ReadModel("objects\\base2.mod");
+ pModFile->CreateEngineObject(rank);
+ p = Math::RotatePoint(-Math::PI/4.0f*i, 27.8f);
+ SetPosition(1+i, Math::Vector(p.x, 30.0f, p.y));
+ SetAngleY(1+i, Math::PI/4.0f*i);
+ SetAngleZ(1+i, Math::PI/2.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(10+i, rank);
+ SetObjectParent(10+i, 1+i);
+ pModFile->ReadModel("objects\\base4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(10+i, Math::Vector(23.5f, 0.0f, 7.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(18+i, rank);
+ SetObjectParent(18+i, 1+i);
+ pModFile->ReadModel("objects\\base4.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ SetPosition(18+i, Math::Vector(23.5f, 0.0f, -7.0f));
+ }
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(9, rank);
+ SetObjectParent(9, 0);
+ pModFile->ReadModel("objects\\base3.mod"); // central pillar
+ pModFile->CreateEngineObject(rank);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 33.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 39.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 45.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 51.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 57.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 63.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 69.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 82.0f, 0.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 18.0f, 94.0f, 0.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-18.0f, 94.0f, 0.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 94.0f, 18.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 94.0f, -18.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 13.0f, 94.0f, 13.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-13.0f, 94.0f, 13.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 13.0f, 94.0f, -13.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-13.0f, 94.0f, -13.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f,104.0f, 0.0f), 14.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 45.0f, 0.0f), 10.0f);
+
+ CreateShadowCircle(60.0f, 1.0f);
+ m_showLimitRadius = 200.0f;
+
+ m_terrain->AddBuildingLevel(pos, 28.6f, 73.4f, 30.0f, 0.4f);
+ }
+
+ if ( m_type == OBJECT_DERRICK )
+ {
+ pModFile->ReadModel("objects\\derrick1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\derrick2.mod");
+ pModFile->CreateEngineObject(rank);
+
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 17.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 26.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(7.0f, 17.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 10.0f);
+
+ CreateShadowCircle(10.0f, 0.4f);
+ }
+
+ if ( m_type == OBJECT_RESEARCH )
+ {
+ pModFile->ReadModel("objects\\search1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\search2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 13.0f, 0.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\search3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(0.0f, 4.0f, 0.0f));
+ SetAngleZ(2, 35.0f*Math::PI/180.0f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 6.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 14.0f, 0.0f), 7.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 8.0f, 0.0f), 12.0f);
+
+ m_character.posPower = Math::Vector(7.5f, 3.0f, 0.0f);
+
+ CreateShadowCircle(12.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_RADAR )
+ {
+ pModFile->ReadModel("objects\\radar1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\radar2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 5.0f, 0.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\radar3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(0.0f, 11.0f, 0.0f));
+ SetAngleY(2, -Math::PI/2.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(3, rank);
+ SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\radar4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(3, Math::Vector(0.0f, 4.5f, 1.9f));
+
+ CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 11.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 7.0f, 0.0f), 7.0f);
+
+ CreateShadowCircle(8.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_INFO )
+ {
+ pModFile->ReadModel("objects\\info1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\info2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 5.0f, 0.0f));
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2+i*2, rank);
+ SetObjectParent(2+i*2, 1);
+ pModFile->ReadModel("objects\\info3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2+i*2, Math::Vector(0.0f, 4.5f, 0.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(3+i*2, rank);
+ SetObjectParent(3+i*2, 2+i*2);
+ pModFile->ReadModel("objects\\radar4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(3+i*2, Math::Vector(0.0f, 0.0f, -4.0f));
+
+ SetAngleY(2+i*2, 2.0f*Math::PI/3.0f*i);
+ }
+
+ CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 11.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 6.0f);
+
+ CreateShadowCircle(8.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_ENERGY )
+ {
+ pModFile->ReadModel("objects\\energy.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ CreateCrashSphere(Math::Vector(-2.0f, 13.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-7.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(-7.0f, 5.0f, 0.0f), 5.0f);
+
+ m_character.posPower = Math::Vector(0.0f, 3.0f, 0.0f);
+ m_energy = power; // initializes the energy level
+
+ CreateShadowCircle(6.0f, 0.5f);
+ }
+
+ if ( m_type == OBJECT_LABO )
+ {
+ pModFile->ReadModel("objects\\labo1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\labo2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(-9.0f, 3.0f, 0.0f));
+ SetAngleZ(1, Math::PI/2.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\labo3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(9.0f, -1.0f, 0.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(3, rank);
+ SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\labo4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(3, Math::Vector(0.0f, 0.0f, 0.0f));
+ SetAngleZ(3, 80.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(4, rank);
+ SetObjectParent(4, 2);
+ pModFile->ReadModel("objects\\labo4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(4, Math::Vector(0.0f, 0.0f, 0.0f));
+ SetAngleZ(4, 80.0f*Math::PI/180.0f);
+ SetAngleY(4, Math::PI*2.0f/3.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(5, rank);
+ SetObjectParent(5, 2);
+ pModFile->ReadModel("objects\\labo4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(5, Math::Vector(0.0f, 0.0f, 0.0f));
+ SetAngleZ(5, 80.0f*Math::PI/180.0f);
+ SetAngleY(5, -Math::PI*2.0f/3.0f);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 11.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 10.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-12.0f, 3.0f, 3.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-12.0f, 3.0f, -3.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(-10.0f, 5.0f, 0.0f), 7.0f);
+
+ m_character.posPower = Math::Vector(0.0f, 3.0f, 0.0f);
+
+ CreateShadowCircle(7.0f, 0.5f);
+ }
+
+ if ( m_type == OBJECT_FACTORY )
+ {
+ pModFile->ReadModel("objects\\factory1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ for ( i=0 ; i<9 ; i++ )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1+i, rank);
+ SetObjectParent(1+i, 0);
+ pModFile->ReadModel("objects\\factory2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1+i, Math::Vector(10.0f, 2.0f*i, 10.0f));
+ SetAngleZ(1+i, Math::PI/2.0f);
+ SetZoomZ(1+i, 0.30f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(10+i, rank);
+ SetObjectParent(10+i, 0);
+ pModFile->ReadModel("objects\\factory2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(10+i, Math::Vector(10.0f, 2.0f*i, -10.0f));
+ SetAngleZ(10+i, -Math::PI/2.0f);
+ SetAngleY(10+i, Math::PI);
+ SetZoomZ(10+i, 0.30f);
+ }
+
+ for ( i=0 ; i<2 ; i++ )
+ {
+ float s = (float)(i*2-1);
+ CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -3.0f, 2.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.0f, 2.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 2.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 9.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -3.0f, 9.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.0f, 9.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 9.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 16.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -3.0f, 16.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.0f, 16.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 16.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 16.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -3.0f, 16.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.0f, 16.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 16.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 9.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ }
+ CreateCrashSphere(Math::Vector(-10.0f, 21.0f, -4.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 18.0f);
+
+ CreateShadowCircle(24.0f, 0.3f);
+ }
+
+ if ( m_type == OBJECT_REPAIR )
+ {
+ pModFile->ReadModel("objects\\repair1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\repair2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(-11.0f, 13.5f, 0.0f));
+ SetAngleZ(1, Math::PI/2.0f);
+
+ m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
+
+ CreateCrashSphere(Math::Vector(-11.0f, 0.0f, 4.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 0.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 0.0f, -4.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 10.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(-11.0f, 13.0f, 0.0f), 15.0f);
+ }
+
+ if ( m_type == OBJECT_DESTROYER )
+ {
+ pModFile->ReadModel("objects\\destroy1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\destroy2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 0.0f, 0.0f));
+
+ m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
+
+ CreateCrashSphere(Math::Vector(-3.5f, 0.0f, -13.5f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.5f, 0.0f, -13.5f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-3.5f, 0.0f, 13.5f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.5f, 0.0f, 13.5f), 4.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(19.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_STATION )
+ {
+ pModFile->ReadModel("objects\\station.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
+
+ CreateCrashSphere(Math::Vector(-15.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-15.0f, 6.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(-15.0f, 5.0f, 0.0f), 6.0f);
+
+ m_energy = power; // initialise le niveau d'�nergie
+ }
+
+ if ( m_type == OBJECT_CONVERT )
+ {
+ pModFile->ReadModel("objects\\convert1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\convert2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 14.0f, 0.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\convert3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(0.0f, 11.5f, 0.0f));
+ SetAngleX(2, -Math::PI*0.35f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(3, rank);
+ SetObjectParent(3, 0);
+ pModFile->ReadModel("objects\\convert3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(3, Math::Vector(0.0f, 11.5f, 0.0f));
+ SetAngleY(3, Math::PI);
+ SetAngleX(3, -Math::PI*0.35f);
+
+ m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
+
+ CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 4.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 2.0f, -4.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 9.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 14.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(-3.0f, 8.0f, 0.0f), 14.0f);
+ }
+
+ if ( m_type == OBJECT_TOWER )
+ {
+ pModFile->ReadModel("objects\\tower.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\roller2c.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 20.0f, 0.0f));
+ SetAngleZ(1, Math::PI/2.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\roller3c.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(4.5f, 0.0f, 0.0f));
+ SetAngleZ(2, 0.0f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 6.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 8.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 15.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 24.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 7.0f);
+
+ m_character.posPower = Math::Vector(5.0f, 3.0f, 0.0f);
+
+ CreateShadowCircle(6.0f, 1.0f);
+ m_showLimitRadius = BLITZPARA;
+ }
+
+ if ( m_type == OBJECT_NUCLEAR )
+ {
+ pModFile->ReadModel("objects\\nuclear1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\nuclear2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(20.0f, 10.0f, 0.0f));
+ SetAngleZ(1, 135.0f*Math::PI/180.0f);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 0.0f, 0.0f), 19.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 24.0f, 0.0f), 15.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(22.0f, 1.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 17.0f, 0.0f), 26.0f);
+
+ m_character.posPower = Math::Vector(22.0f, 3.0f, 0.0f);
+
+ CreateShadowCircle(21.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_PARA )
+ {
+ pModFile->ReadModel("objects\\para.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ m_terrain->AddBuildingLevel(pos, 16.0f, 18.0f, 1.0f, 0.5f);
+
+ CreateCrashSphere(Math::Vector( 13.0f, 3.0f, 13.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 11.0f, 15.0f, 11.0f), 2.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-13.0f, 3.0f, 13.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 15.0f, -11.0f), 2.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 13.0f, 3.0f, -13.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 11.0f, 15.0f, -11.0f), 2.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-13.0f, 3.0f, -13.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 15.0f, -11.0f), 2.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 26.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 54.0f, 0.0f), 14.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 20.0f);
+
+ CreateShadowCircle(21.0f, 1.0f);
+ m_showLimitRadius = BLITZPARA;
+ }
+
+ if ( m_type == OBJECT_SAFE )
+ {
+ pModFile->ReadModel("objects\\safe1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\safe2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetZoom(1, 1.05f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\safe3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetZoom(2, 1.05f);
+
+ m_terrain->AddBuildingLevel(pos, 18.0f, 20.0f, 1.0f, 0.5f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 13.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 13.0f);
+
+ CreateShadowCircle(23.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_HUSTON )
+ {
+ pModFile->ReadModel("objects\\huston1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\huston2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 39.0f, 30.0f));
+ SetAngleY(1, -Math::PI/2.0f);
+ SetZoom(1, 3.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\huston3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(0.0f, 4.5f, 1.9f));
+
+ CreateCrashSphere(Math::Vector( 15.0f, 6.0f, -53.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-15.0f, 6.0f, -53.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 15.0f, 6.0f, -26.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-15.0f, 6.0f, -26.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 15.0f, 6.0f, 0.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-15.0f, 6.0f, 0.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 15.0f, 6.0f, 26.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-15.0f, 6.0f, 26.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 15.0f, 6.0f, 53.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-15.0f, 6.0f, 53.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 27.0f, 30.0f), 12.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 45.0f, 30.0f), 14.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 26.0f, 4.0f, -61.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-26.0f, 4.0f, -61.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 26.0f, 4.0f, 61.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-26.0f, 4.0f, 61.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ }
+
+ if ( m_type == OBJECT_TARGET1 )
+ {
+ pModFile->ReadModel("objects\\target1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 1.5f);
+ SetFloorHeight(0.0f);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 50.0f+14.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -7.0f, 50.0f+12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 7.0f, 50.0f+12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-12.0f, 50.0f+ 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 12.0f, 50.0f+ 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-14.0f, 50.0f+ 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 14.0f, 50.0f+ 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-12.0f, 50.0f- 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 12.0f, 50.0f- 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -7.0f, 50.0f-12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 7.0f, 50.0f-12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 50.0f-14.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 30.0f, 0.0f), 2.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 24.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 16.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 8.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(15.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_TARGET2 )
+ {
+ pModFile->ReadModel("objects\\target2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ height += 50.0f*1.5f;
+ }
+
+ if ( m_type == OBJECT_NEST )
+ {
+ pModFile->ReadModel("objects\\nest.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ m_terrain->AddBuildingLevel(pos, 3.0f, 5.0f, 1.0f, 0.5f);
+
+ CreateShadowCircle(4.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_START )
+ {
+ pModFile->ReadModel("objects\\start.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
+ }
+
+ if ( m_type == OBJECT_END )
+ {
+ pModFile->ReadModel("objects\\end.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
+ }
+
+#if 0
+ if ( power > 0.0f ) // creates a battery?
+ {
+ CObject* pPower;
+
+ pPower = new CObject(m_iMan);
+ pPower->SetType(power<=1.0f?OBJECT_POWER:OBJECT_ATOMIC);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ pPower->SetObjectRank(0, rank);
+
+ if ( power <= 1.0f ) pModFile->ReadModel("objects\\power.mod");
+ else pModFile->ReadModel("objects\\atomic.mod");
+ pModFile->CreateEngineObject(rank);
+
+ pPower->SetPosition(0, RetCharacter()->posPower);
+ pPower->CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ pPower->SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.5f);
+
+ pPower->SetTruck(this);
+ SetPower(pPower);
+
+ if ( power <= 1.0f ) pPower->SetEnergy(power);
+ else pPower->SetEnergy(power/100.0f);
+ }
+#endif
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos); // to display the shadows immediately
+
+ CreateOtherObject(type);
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a small resource set on the ground.
+
+bool CObject::CreateResource(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ char name[50];
+ int rank;
+ float radius, height;
+
+ if ( type != OBJECT_SHOW )
+ {
+ if ( m_engine->RetRestCreate() < 1 ) return false;
+ }
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
+ SetObjectRank(0, rank);
+ SetEnergy(power);
+
+ name[0] = 0;
+ if ( type == OBJECT_STONE ) strcpy(name, "objects\\stone.mod");
+ if ( type == OBJECT_URANIUM ) strcpy(name, "objects\\uranium.mod");
+ if ( type == OBJECT_METAL ) strcpy(name, "objects\\metal.mod");
+ if ( type == OBJECT_POWER ) strcpy(name, "objects\\power.mod");
+ if ( type == OBJECT_ATOMIC ) strcpy(name, "objects\\atomic.mod");
+ if ( type == OBJECT_BULLET ) strcpy(name, "objects\\bullet.mod");
+ if ( type == OBJECT_BBOX ) strcpy(name, "objects\\bbox.mod");
+ if ( type == OBJECT_KEYa ) strcpy(name, "objects\\keya.mod");
+ if ( type == OBJECT_KEYb ) strcpy(name, "objects\\keyb.mod");
+ if ( type == OBJECT_KEYc ) strcpy(name, "objects\\keyc.mod");
+ if ( type == OBJECT_KEYd ) strcpy(name, "objects\\keyd.mod");
+ if ( type == OBJECT_TNT ) strcpy(name, "objects\\tnt.mod");
+ if ( type == OBJECT_SCRAP1 ) strcpy(name, "objects\\scrap1.mod");
+ if ( type == OBJECT_SCRAP2 ) strcpy(name, "objects\\scrap2.mod");
+ if ( type == OBJECT_SCRAP3 ) strcpy(name, "objects\\scrap3.mod");
+ if ( type == OBJECT_SCRAP4 ) strcpy(name, "objects\\scrap4.mod");
+ if ( type == OBJECT_SCRAP5 ) strcpy(name, "objects\\scrap5.mod");
+ if ( type == OBJECT_BOMB ) strcpy(name, "objects\\bomb.mod");
+ if ( type == OBJECT_WAYPOINT ) strcpy(name, "objects\\waypoint.mod");
+ if ( type == OBJECT_SHOW ) strcpy(name, "objects\\show.mod");
+ if ( type == OBJECT_WINFIRE ) strcpy(name, "objects\\winfire.mod");
+ if ( type == OBJECT_BAG ) strcpy(name, "objects\\bag.mod");
+ if ( type == OBJECT_MARKSTONE ) strcpy(name, "objects\\cross1.mod");
+ if ( type == OBJECT_MARKURANIUM ) strcpy(name, "objects\\cross3.mod");
+ if ( type == OBJECT_MARKPOWER ) strcpy(name, "objects\\cross2.mod");
+ if ( type == OBJECT_MARKKEYa ) strcpy(name, "objects\\crossa.mod");
+ if ( type == OBJECT_MARKKEYb ) strcpy(name, "objects\\crossb.mod");
+ if ( type == OBJECT_MARKKEYc ) strcpy(name, "objects\\crossc.mod");
+ if ( type == OBJECT_MARKKEYd ) strcpy(name, "objects\\crossd.mod");
+ if ( type == OBJECT_EGG ) strcpy(name, "objects\\egg.mod");
+
+ pModFile->ReadModel(name);
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ if ( type == OBJECT_SHOW ) // remains in the air?
+ {
+ delete pModFile;
+ return true;
+ }
+
+ radius = 1.5f;
+ height = 0.0f;
+
+ if ( type == OBJECT_MARKSTONE ||
+ type == OBJECT_MARKURANIUM ||
+ type == OBJECT_MARKKEYa ||
+ type == OBJECT_MARKKEYb ||
+ type == OBJECT_MARKKEYc ||
+ type == OBJECT_MARKKEYd ||
+ type == OBJECT_MARKPOWER ||
+ type == OBJECT_WAYPOINT )
+ {
+ }
+ else if ( type == OBJECT_EGG )
+ {
+ CreateCrashSphere(Math::Vector(-1.0f, 2.8f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
+ radius = 3.0f;
+ }
+ else if ( type == OBJECT_BOMB )
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 3.0f);
+ radius = 3.0f;
+ }
+ else if ( type == OBJECT_BAG )
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f);
+ SetZoom(0, 1.5f);
+ radius = 5.0f;
+ height = -1.4f;
+ }
+ else
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.5f);
+ }
+ CreateShadowCircle(radius, 1.0f);
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+ m_engine->LoadAllTexture();
+ FloorAdjust();
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos); // to display the shadows immediately
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a flag placed on the ground.
+
+bool CObject::CreateFlag(Math::Vector pos, float angle, ObjectType type)
+{
+ CModFile* pModFile;
+ char name[50];
+ int rank, i;
+
+ if ( m_engine->RetRestCreate() < 1+4 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ name[0] = 0;
+ if ( type == OBJECT_FLAGb ) strcpy(name, "objects\\flag1b.mod");
+ if ( type == OBJECT_FLAGr ) strcpy(name, "objects\\flag1r.mod");
+ if ( type == OBJECT_FLAGg ) strcpy(name, "objects\\flag1g.mod");
+ if ( type == OBJECT_FLAGy ) strcpy(name, "objects\\flag1y.mod");
+ if ( type == OBJECT_FLAGv ) strcpy(name, "objects\\flag1v.mod");
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
+ SetObjectRank(0, rank);
+ pModFile->ReadModel(name);
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ name[0] = 0;
+ if ( type == OBJECT_FLAGb ) strcpy(name, "objects\\flag2b.mod");
+ if ( type == OBJECT_FLAGr ) strcpy(name, "objects\\flag2r.mod");
+ if ( type == OBJECT_FLAGg ) strcpy(name, "objects\\flag2g.mod");
+ if ( type == OBJECT_FLAGy ) strcpy(name, "objects\\flag2y.mod");
+ if ( type == OBJECT_FLAGv ) strcpy(name, "objects\\flag2v.mod");
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1+i, rank);
+ SetObjectParent(1+i, i);
+ pModFile->ReadModel(name);
+ pModFile->CreateEngineObject(rank);
+ if ( i == 0 ) SetPosition(1+i, Math::Vector(0.15f, 5.0f, 0.0f));
+ else SetPosition(1+i, Math::Vector(0.79f, 0.0f, 0.0f));
+ }
+
+ SetJotlerSphere(Math::Vector(0.0f, 4.0f, 0.0f), 1.0f);
+ CreateShadowCircle(2.0f, 0.3f);
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+ m_engine->LoadAllTexture();
+ FloorAdjust();
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a barrier placed on the ground.
+
+bool CObject::CreateBarrier(Math::Vector pos, float angle, float height,
+ ObjectType type)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ if ( type == OBJECT_BARRIER0 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\barrier0.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(6.0f, 0.5f, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_BARRIER1 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\barrier1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector( 8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(12.0f, 0.5f, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_BARRIER2 ) // cardboard?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\barrier2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector( 8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(12.0f, 0.8f, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_BARRIER3 ) // match + straw?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\barrier3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector( 8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(10.0f, 0.5f, D3DSHADOWWORM);
+ }
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+ FloorAdjust();
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos);
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a plant placed on the ground.
+
+bool CObject::CreatePlant(Math::Vector pos, float angle, float height,
+ ObjectType type)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ if ( type == OBJECT_PLANT0 ||
+ type == OBJECT_PLANT1 ||
+ type == OBJECT_PLANT2 ||
+ type == OBJECT_PLANT3 ||
+ type == OBJECT_PLANT4 ) // standard?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ if ( type == OBJECT_PLANT0 ) pModFile->ReadModel("objects\\plant0.mod");
+ if ( type == OBJECT_PLANT1 ) pModFile->ReadModel("objects\\plant1.mod");
+ if ( type == OBJECT_PLANT2 ) pModFile->ReadModel("objects\\plant2.mod");
+ if ( type == OBJECT_PLANT3 ) pModFile->ReadModel("objects\\plant3.mod");
+ if ( type == OBJECT_PLANT4 ) pModFile->ReadModel("objects\\plant4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ height -= 2.0f;
+
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f);
+ SetJotlerSphere(Math::Vector(0.0f, 0.0f, 0.0f), 8.0f);
+
+ CreateShadowCircle(8.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_PLANT5 ||
+ type == OBJECT_PLANT6 ||
+ type == OBJECT_PLANT7 ) // clover?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ if ( type == OBJECT_PLANT5 ) pModFile->ReadModel("objects\\plant5.mod");
+ if ( type == OBJECT_PLANT6 ) pModFile->ReadModel("objects\\plant6.mod");
+ if ( type == OBJECT_PLANT7 ) pModFile->ReadModel("objects\\plant7.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+//? CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 3.0f, SOUND_BOUM, 0.10f);
+ SetJotlerSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f);
+
+ CreateShadowCircle(5.0f, 0.3f);
+ }
+
+ if ( type == OBJECT_PLANT8 ||
+ type == OBJECT_PLANT9 ) // squash?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ if ( type == OBJECT_PLANT8 ) pModFile->ReadModel("objects\\plant8.mod");
+ if ( type == OBJECT_PLANT9 ) pModFile->ReadModel("objects\\plant9.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
+
+ CreateShadowCircle(10.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_PLANT10 ||
+ type == OBJECT_PLANT11 ||
+ type == OBJECT_PLANT12 ||
+ type == OBJECT_PLANT13 ||
+ type == OBJECT_PLANT14 ) // succulent?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ if ( type == OBJECT_PLANT10 ) pModFile->ReadModel("objects\\plant10.mod");
+ if ( type == OBJECT_PLANT11 ) pModFile->ReadModel("objects\\plant11.mod");
+ if ( type == OBJECT_PLANT12 ) pModFile->ReadModel("objects\\plant12.mod");
+ if ( type == OBJECT_PLANT13 ) pModFile->ReadModel("objects\\plant13.mod");
+ if ( type == OBJECT_PLANT14 ) pModFile->ReadModel("objects\\plant14.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 12.0f, 0.0f), 5.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 6.0f);
+ SetJotlerSphere(Math::Vector(0.0f, 4.0f, 0.0f), 8.0f);
+
+ CreateShadowCircle(8.0f, 0.3f);
+ }
+
+ if ( type == OBJECT_PLANT15 ||
+ type == OBJECT_PLANT16 ||
+ type == OBJECT_PLANT17 ||
+ type == OBJECT_PLANT18 ||
+ type == OBJECT_PLANT19 ) // fern?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ if ( type == OBJECT_PLANT15 ) pModFile->ReadModel("objects\\plant15.mod");
+ if ( type == OBJECT_PLANT16 ) pModFile->ReadModel("objects\\plant16.mod");
+ if ( type == OBJECT_PLANT17 ) pModFile->ReadModel("objects\\plant17.mod");
+ if ( type == OBJECT_PLANT18 ) pModFile->ReadModel("objects\\plant18.mod");
+ if ( type == OBJECT_PLANT19 ) pModFile->ReadModel("objects\\plant19.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ if ( type != OBJECT_PLANT19 )
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f);
+ }
+ SetJotlerSphere(Math::Vector(0.0f, 0.0f, 0.0f), 8.0f);
+
+ CreateShadowCircle(8.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_TREE0 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\tree0.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 2.0f), 3.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(-1.0f, 10.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 0.0f, 17.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 1.0f, 27.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
+
+ CreateShadowCircle(8.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_TREE1 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\tree1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 2.0f), 3.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(-2.0f, 11.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(-2.0f, 19.0f, 2.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 2.0f, 26.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 2.0f, 34.0f,-2.0f), 2.0f, SOUND_BOUMs, 0.20f);
+
+ CreateShadowCircle(8.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_TREE2 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\tree2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 1.0f), 3.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(-2.0f, 10.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(-2.0f, 19.0f, 2.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 2.0f, 25.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 3.0f, 32.0f,-2.0f), 2.0f, SOUND_BOUMs, 0.20f);
+
+ CreateShadowCircle(8.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_TREE3 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\tree3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(-2.0f, 3.0f, 2.0f), 3.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(-3.0f, 9.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 0.0f, 18.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 0.0f, 27.0f, 7.0f), 2.0f, SOUND_BOUMs, 0.20f);
+
+ CreateShadowCircle(8.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_TREE4 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\tree4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 10.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(0.0f, 21.0f, 0.0f), 8.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(0.0f, 32.0f, 0.0f), 7.0f, SOUND_BOUMs, 0.20f);
+
+ CreateShadowCircle(8.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_TREE5 ) // giant tree (for the world "teen")
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\tree5.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 5.0f,-10.0f), 25.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(-65.0f, 5.0f, 65.0f), 20.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 38.0f, 5.0f, 21.0f), 18.0f, SOUND_BOUMs, 0.20f);
+
+ CreateShadowCircle(50.0f, 0.5f);
+ }
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos);
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a mushroom placed on the ground.
+
+bool CObject::CreateMushroom(Math::Vector pos, float angle, float height,
+ ObjectType type)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ if ( type == OBJECT_MUSHROOM1 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\mush1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 3.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 5.5f);
+ SetJotlerSphere(Math::Vector(0.0f, 3.0f, 0.0f), 5.5f);
+
+ CreateShadowCircle(6.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_MUSHROOM2 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\mush2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 5.0f, 0.0f), 3.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 5.5f);
+ SetJotlerSphere(Math::Vector(0.0f, 4.0f, 0.0f), 5.5f);
+
+ CreateShadowCircle(5.0f, 0.5f);
+ }
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos);
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a toy placed on the ground.
+
+bool CObject::CreateTeen(Math::Vector pos, float angle, float zoom, float height,
+ ObjectType type)
+{
+ CModFile* pModFile;
+ Math::Matrix* mat;
+ D3DCOLORVALUE color;
+ int rank;
+ float fShadow;
+ bool bFloorAdjust = true;
+
+ if ( m_engine->RetRestCreate() < 1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ fShadow = Math::Norm(1.0f-height/10.0f);
+
+ if ( type == OBJECT_TEEN0 ) // orange pencil lg=10
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen0.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 5.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 2.5f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-2.5f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(5.0f, 0.8f*fShadow, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_TEEN1 ) // blue pencil lg=14
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 6.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 2.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-2.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-4.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-6.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(6.0f, 0.8f*fShadow, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_TEEN2 ) // red pencil lg=16
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 7.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.7f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 2.3f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-2.3f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-4.7f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-7.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(6.0f, 0.8f*fShadow, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_TEEN3 ) // jar with pencils
+ {
+ rank = m_engine->CreateObject();
+//? m_engine->SetObjectType(rank, TYPEFIX);
+ m_engine->SetObjectType(rank, TYPEMETAL);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 4.0f);
+ CreateShadowCircle(6.0f, 0.5f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN4 ) // scissors
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-9.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-6.0f, 1.0f, 0.0f), 1.1f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-3.0f, 1.0f, 0.0f), 1.2f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.3f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 5.1f, 1.0f,-1.3f), 2.6f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 8.0f, 1.0f, 2.2f), 2.3f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 9.4f, 1.0f,-2.0f), 2.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(10.0f, 0.5f*fShadow, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_TEEN5 ) // CD
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen5.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+ SetFloorHeight(0.0f);
+ bFloorAdjust = false;
+
+ m_terrain->AddBuildingLevel(pos, 5.9f, 6.1f, 0.2f, 0.5f);
+ CreateShadowCircle(8.0f, 0.2f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN6 ) // book 1
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen6.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(20.0f, 0.2f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN7 ) // book 2
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen7.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(20.0f, 0.2f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN8 ) // a stack of books 1
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen8.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 12.0f);
+ CreateShadowCircle(20.0f, 0.2f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN9 ) // a stack of books 2
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen9.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 12.0f);
+ CreateShadowCircle(20.0f, 0.2f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN10 ) // bookcase
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen10.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-26.0f, 3.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-15.0f, 3.0f,-4.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-15.0f, 3.0f, 5.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -4.0f, 3.0f,-4.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -4.0f, 3.0f, 5.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 6.0f, 3.0f,-4.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 6.0f, 3.0f, 4.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 14.0f, 3.0f,-3.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 14.0f, 3.0f, 2.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 24.0f, 3.0f, 5.0f), 6.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 20.0f);
+ CreateShadowCircle(40.0f, 0.2f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN11 ) // lamp
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen11.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+ SetZoom(0, zoom);
+
+ mat = RetWorldMatrix(0);
+ pos = Math::Transform(*mat, Math::Vector(-56.0f, 22.0f, 0.0f));
+ m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(20.0f, 20.0f), PARTISELY, 1.0f, 0.0f, 0.0f);
+
+ pos = Math::Transform(*mat, Math::Vector(-65.0f, 40.0f, 0.0f));
+ color.r = 4.0f;
+ color.g = 2.0f;
+ color.b = 0.0f; // yellow-orange
+ color.a = 0.0f;
+ m_main->CreateSpot(pos, color);
+ }
+
+ if ( type == OBJECT_TEEN12 ) // coke
+ {
+ rank = m_engine->CreateObject();
+//? m_engine->SetObjectType(rank, TYPEFIX);
+ m_engine->SetObjectType(rank, TYPEMETAL);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen12.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 9.0f, 0.0f), 5.0f);
+ CreateShadowCircle(4.5f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN13 ) // cardboard farm
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen13.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 15.0f);
+ CreateShadowCircle(20.0f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN14 ) // open box
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen14.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 15.0f);
+ CreateShadowCircle(20.0f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN15 ) // stack of cartons
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen15.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 15.0f);
+ CreateShadowCircle(20.0f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN16 ) // watering can
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen16.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-8.0f, 4.0f, 0.0f), 12.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 8.0f, 4.0f, 0.0f), 12.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 13.0f, 0.0f), 20.0f);
+ CreateShadowCircle(18.0f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN17 ) // wheel |
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen17.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 31.0f, 0.0f), 31.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 31.0f, 0.0f), 31.0f);
+ CreateShadowCircle(24.0f, 0.5f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN18 ) // wheel /
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen18.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 31.0f, 0.0f), 31.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 31.0f, 0.0f), 31.0f);
+ CreateShadowCircle(24.0f, 0.5f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN19 ) // wheel =
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen19.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 10.0f, 0.0f), 32.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 32.0f);
+ CreateShadowCircle(33.0f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN20 ) // wall with shelf
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen20.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-175.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-175.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -55.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -55.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -37.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -37.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 83.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 83.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ }
+
+ if ( type == OBJECT_TEEN21 ) // wall with window
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen21.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+ }
+
+ if ( type == OBJECT_TEEN22 ) // wall with door and shelf
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen22.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-135.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-135.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -15.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -15.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ }
+
+ if ( type == OBJECT_TEEN23 ) // skateboard on wheels
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen23.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ if ( m_option == 1 ) // passage under the prohibited skateboard?
+ {
+ CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 0.0f), 11.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 2.0f, 0.0f), 11.0f, SOUND_BOUMm, 0.45f);
+ }
+
+ CreateCrashSphere(Math::Vector(-23.0f, 2.0f, 7.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-23.0f, 2.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-23.0f, 2.0f,-7.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 23.0f, 2.0f, 7.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 23.0f, 2.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 23.0f, 2.0f,-7.0f), 3.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(35.0f, 0.8f*fShadow, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_TEEN24 ) // skate /
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen24.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-12.0f, 0.0f, -3.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-12.0f, 0.0f, 3.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateShadowCircle(20.0f, 0.2f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN25 ) // skate /
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen25.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-12.0f, 0.0f, -3.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-12.0f, 0.0f, 3.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateShadowCircle(20.0f, 0.2f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN26 ) // ceiling lamp
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen26.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+ SetFloorHeight(0.0f);
+
+ mat = RetWorldMatrix(0);
+ pos = Math::Transform(*mat, Math::Vector(0.0f, 50.0f, 0.0f));
+ m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(100.0f, 100.0f), PARTISELY, 1.0f, 0.0f, 0.0f);
+
+ pos = Math::Transform(*mat, Math::Vector(0.0f, 50.0f, 0.0f));
+ color.r = 4.0f;
+ color.g = 2.0f;
+ color.b = 0.0f; // yellow-orange
+ color.a = 0.0f;
+ m_main->CreateSpot(pos, color);
+ }
+
+ if ( type == OBJECT_TEEN27 ) // large plant?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen27.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
+ CreateShadowCircle(40.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_TEEN28 ) // bottle?
+ {
+ rank = m_engine->CreateObject();
+//? m_engine->SetObjectType(rank, TYPEFIX);
+ m_engine->SetObjectType(rank, TYPEMETAL);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen28.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUM, 0.10f);
+ CreateShadowCircle(7.0f, 0.6f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN29 ) // bridge?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen29.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+ bFloorAdjust = false;
+ }
+
+ if ( type == OBJECT_TEEN30 ) // jump?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen30.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 15.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 15.0f, 0.0f), 17.0f);
+ CreateShadowCircle(20.0f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN31 ) // basket?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen31.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector( 0.0f, 2.0f, 0.0f), 6.0f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector( 9.0f, 4.0f, 1.0f), 6.0f, SOUND_BOUM, 0.10f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 10.0f);
+ CreateShadowCircle(16.0f, 0.6f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN32 ) // chair?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen32.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 17.5f, 1.0f, 17.5f), 3.5f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector( 17.5f, 1.0f, -17.5f), 3.5f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector(-17.5f, 1.0f, 17.5f), 3.5f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector(-17.5f, 1.0f, -17.5f), 3.5f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 26.0f);
+ CreateShadowCircle(35.0f, 0.3f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN33 ) // panel?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen33.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
+ CreateShadowCircle(10.0f, 0.3f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN34 ) // stone?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen34.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
+ CreateShadowCircle(3.0f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN35 ) // pipe?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen35.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-40.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector(-20.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector( 0.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector( 20.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector( 40.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
+ CreateShadowCircle(40.0f, 0.8f*fShadow, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_TEEN36 ) // trunk?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen36.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+ bFloorAdjust = false;
+ }
+
+ if ( type == OBJECT_TEEN37 ) // boat?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen37.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+ bFloorAdjust = false;
+ }
+
+ if ( type == OBJECT_TEEN38 ) // fan?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen38a.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\teen38b.mod"); // engine
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 30.0f, 0.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\teen38c.mod"); // propeller
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(0.0f, 0.0f, 0.0f));
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 2.0f, 0.0f), 10.0f);
+ CreateShadowCircle(15.0f, 0.5f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN39 ) // potted plant?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen39.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 8.5f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 2.0f, 0.0f), 8.5f);
+ CreateShadowCircle(10.0f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN40 ) // balloon?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen40.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 5.0f, 0.0f), 11.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 14.0f, 0.0f), 15.0f);
+ CreateShadowCircle(15.0f, 0.7f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN41 ) // fence?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen41.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+ }
+
+ if ( type == OBJECT_TEEN42 ) // clover?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen42.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 2.0f, SOUND_BOUM, 0.10f);
+ CreateShadowCircle(15.0f, 0.4f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN43 ) // clover?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen43.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 2.0f, SOUND_BOUM, 0.10f);
+ CreateShadowCircle(15.0f, 0.4f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN44 ) // car?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen44.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 55.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 55.0f);
+ CreateShadowCircle(55.0f, 1.0f*fShadow);
+ }
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ if ( bFloorAdjust )
+ {
+ SetFloorHeight(0.0f);
+ FloorAdjust();
+ }
+
+ CreateOtherObject(type);
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos);
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a crystal placed on the ground.
+
+bool CObject::CreateQuartz(Math::Vector pos, float angle, float height,
+ ObjectType type)
+{
+ CModFile* pModFile;
+ float radius;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ if ( type == OBJECT_QUARTZ0 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEQUARTZ);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\quartz0.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 3.5f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 2.0f, 0.0f), 3.5f);
+
+ CreateShadowCircle(4.0f, 0.5f);
+ }
+ if ( type == OBJECT_QUARTZ1 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEQUARTZ);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\quartz1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 5.0f);
+
+ CreateShadowCircle(5.0f, 0.5f);
+ }
+ if ( type == OBJECT_QUARTZ2 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEQUARTZ);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\quartz2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 6.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 6.0f);
+
+ CreateShadowCircle(6.0f, 0.5f);
+ }
+ if ( type == OBJECT_QUARTZ3 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEQUARTZ);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\quartz3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 10.0f);
+
+ CreateShadowCircle(10.0f, 0.5f);
+ }
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos);
+
+ if ( type == OBJECT_QUARTZ0 )
+ {
+ pos.y += 4.0f;
+ radius = 2.0f;
+ }
+ if ( type == OBJECT_QUARTZ1 )
+ {
+ pos.y += 6.0f;
+ radius = 4.0f;
+ }
+ if ( type == OBJECT_QUARTZ2 )
+ {
+ pos.y += 10.0f;
+ radius = 5.0f;
+ }
+ if ( type == OBJECT_QUARTZ3 )
+ {
+ pos.y += 16.0f;
+ radius = 8.0f;
+ }
+ m_particule->CreateParticule(pos, pos, Math::Point(2.0f, 2.0f), PARTIQUARTZ, 0.7f+Math::Rand()*0.7f, radius, 0.0f);
+ m_particule->CreateParticule(pos, pos, Math::Point(2.0f, 2.0f), PARTIQUARTZ, 0.7f+Math::Rand()*0.7f, radius, 0.0f);
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a root placed on the ground.
+
+bool CObject::CreateRoot(Math::Vector pos, float angle, float height,
+ ObjectType type)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ if ( type == OBJECT_ROOT0 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\root0.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 2.0f);
+
+ CreateCrashSphere(Math::Vector(-5.0f, 1.0f, 0.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 4.0f, 1.0f, 2.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 4.0f, 1.0f, -3.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 2.0f, 5.0f, -1.0f), 1.5f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector(-4.0f, 5.0f, -1.0f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector(-2.0f, 8.0f, -0.5f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 0.0f, 10.0f, -0.5f), 1.0f, SOUND_BOUMv, 0.15f);
+//? SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 11.0f);
+
+ CreateShadowCircle(16.0f, 0.5f);
+ }
+ if ( type == OBJECT_ROOT1 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\root1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 2.0f);
+
+ CreateCrashSphere(Math::Vector(-4.0f, 1.0f, 1.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 2.0f), 1.5f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 3.0f, 1.0f, -2.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector(-2.0f, 5.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 2.0f, 5.0f, 0.0f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 0.0f, 8.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 0.0f, 12.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
+//? SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 12.0f);
+
+ CreateShadowCircle(16.0f, 0.5f);
+ }
+ if ( type == OBJECT_ROOT2 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\root2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 2.0f);
+
+ CreateCrashSphere(Math::Vector(-3.0f, 1.0f, 0.5f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 3.0f, 1.0f, -1.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector(-1.0f, 4.5f, 0.0f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 3.0f, 7.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 0.0f, 7.0f, -1.0f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 4.0f, 11.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
+//? SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 10.0f);
+
+ CreateShadowCircle(16.0f, 0.5f);
+ }
+ if ( type == OBJECT_ROOT3 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\root3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 2.0f);
+
+ CreateCrashSphere(Math::Vector(-4.0f, 1.0f, 1.0f), 3.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 4.0f, 1.0f, -3.0f), 3.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 6.0f, 1.0f, 4.0f), 3.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector(-2.5f, 7.0f, 2.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 4.0f, 7.0f, 2.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 3.0f, 6.0f, -1.0f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 0.0f, 12.0f, 0.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 1.0f, 16.0f, 0.0f), 1.0f, SOUND_BOUMv, 0.15f);
+//? SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 14.0f);
+
+ CreateShadowCircle(22.0f, 0.5f);
+ }
+ if ( type == OBJECT_ROOT4 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\root4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 2.0f);
+
+ CreateCrashSphere(Math::Vector( -7.0f, 2.0f, 3.0f), 4.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 5.0f, 2.0f, -6.0f), 4.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 6.0f, 2.0f, 6.0f), 3.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector(-11.0f, 1.0f, -2.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 1.0f, 1.0f, -7.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( -4.0f, 10.0f, 3.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 1.0f, 11.0f, 7.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 3.0f, 11.0f, -3.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( -3.0f, 17.0f, 1.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( -3.0f, 23.0f, -1.0f), 2.0f, SOUND_BOUMv, 0.15f);
+//? SetGlobalSphere(Math::Vector(0.0f, 12.0f, 0.0f), 20.0f);
+
+ CreateShadowCircle(30.0f, 0.5f);
+ }
+ if ( type == OBJECT_ROOT5 ) // gravity root ?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\root4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 2.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\root5.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(-5.0f, 28.0f, -4.0f));
+ SetAngleX(1, -30.0f*Math::PI/180.0f);
+ SetAngleZ(1, 20.0f*Math::PI/180.0f);
+
+ CreateCrashSphere(Math::Vector( -7.0f, 2.0f, 3.0f), 4.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 5.0f, 2.0f, -6.0f), 4.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 6.0f, 2.0f, 6.0f), 3.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector(-11.0f, 1.0f, -2.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 1.0f, 1.0f, -7.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( -4.0f, 10.0f, 3.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 1.0f, 11.0f, 7.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 3.0f, 11.0f, -3.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( -3.0f, 17.0f, 1.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( -3.0f, 23.0f, -1.0f), 2.0f, SOUND_BOUMv, 0.15f);
+//? SetGlobalSphere(Math::Vector(0.0f, 12.0f, 0.0f), 20.0f);
+
+ CreateShadowCircle(30.0f, 0.5f);
+ }
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos);
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a small home.
+
+bool CObject::CreateHome(Math::Vector pos, float angle, float height,
+ ObjectType type)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ if ( type == OBJECT_HOME1 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\home1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 1.3f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUMs, 0.25f);
+//? SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 11.0f);
+ CreateShadowCircle(16.0f, 0.5f);
+ }
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos);
+
+ delete pModFile;
+ return true;
+}
+
+// Creates ruin placed on the ground.
+
+bool CObject::CreateRuin(Math::Vector pos, float angle, float height,
+ ObjectType type)
+{
+ CModFile* pModFile;
+ char name[50];
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 1+4 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
+ SetObjectRank(0, rank);
+
+ name[0] = 0;
+ if ( type == OBJECT_RUINmobilew1 ) strcpy(name, "objects\\ruin1.mod");
+ if ( type == OBJECT_RUINmobilew2 ) strcpy(name, "objects\\ruin1.mod");
+ if ( type == OBJECT_RUINmobilet1 ) strcpy(name, "objects\\ruin2.mod");
+ if ( type == OBJECT_RUINmobilet2 ) strcpy(name, "objects\\ruin2.mod");
+ if ( type == OBJECT_RUINmobiler1 ) strcpy(name, "objects\\ruin3.mod");
+ if ( type == OBJECT_RUINmobiler2 ) strcpy(name, "objects\\ruin3.mod");
+ if ( type == OBJECT_RUINfactory ) strcpy(name, "objects\\ruin4.mod");
+ if ( type == OBJECT_RUINdoor ) strcpy(name, "objects\\ruin5.mod");
+ if ( type == OBJECT_RUINsupport ) strcpy(name, "objects\\ruin6.mod");
+ if ( type == OBJECT_RUINradar ) strcpy(name, "objects\\ruin7.mod");
+ if ( type == OBJECT_RUINconvert ) strcpy(name, "objects\\ruin8.mod");
+ if ( type == OBJECT_RUINbase ) strcpy(name, "objects\\ruin9.mod");
+ if ( type == OBJECT_RUINhead ) strcpy(name, "objects\\ruin10.mod");
+
+ pModFile->ReadModel(name);
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ if ( type == OBJECT_RUINmobilew1 ) // vehicle had wheels?
+ {
+ // Creates the right-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(6, rank);
+ SetObjectParent(6, 0);
+
+ pModFile->ReadModel("objects\\ruin1w.mod");
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(6, Math::Vector(-3.0f, 1.8f, -4.0f));
+ SetAngleX(6, -Math::PI/2.0f);
+
+ // Creates the left-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(7, rank);
+ SetObjectParent(7, 0);
+
+ pModFile->ReadModel("objects\\ruin1w.mod");
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(7, Math::Vector(-3.0f, 1.0f, 3.0f));
+ SetAngleY(7, Math::PI-0.3f);
+ SetAngleX(7, -0.3f);
+
+ // Creates the right-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(8, rank);
+ SetObjectParent(8, 0);
+
+ pModFile->ReadModel("objects\\ruin1w.mod");
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(8, Math::Vector(2.0f, 1.6f, -3.0f));
+ SetAngleY(8, 0.3f);
+
+ // Creates the left-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(9, rank);
+ SetObjectParent(9, 0);
+
+ pModFile->ReadModel("objects\\ruin1w.mod");
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(9, Math::Vector(2.0f, 1.0f, 3.0f));
+ SetAngleY(9, Math::PI-0.2f);
+ SetAngleX(9, 0.2f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.8f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+//? SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
+
+ CreateShadowCircle(4.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINmobilew2 ) // vehicle has wheels?
+ {
+ // Creates the left-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(7, rank);
+ SetObjectParent(7, 0);
+
+ pModFile->ReadModel("objects\\ruin1w.mod");
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(7, Math::Vector(-3.0f, 1.0f, 3.0f));
+ SetAngleY(7, Math::PI+0.3f);
+ SetAngleX(7, 0.4f);
+
+ // Creates the left-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(9, rank);
+ SetObjectParent(9, 0);
+
+ pModFile->ReadModel("objects\\ruin1w.mod");
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(9, Math::Vector(2.0f, 1.0f, 3.0f));
+ SetAngleY(9, Math::PI+0.3f);
+ SetAngleX(9, -0.3f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.8f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+//? SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
+
+ CreateShadowCircle(4.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINmobilet1 ) // vehicle have caterpillars?
+ {
+ // Creates the cannon.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+
+ pModFile->ReadModel("objects\\ruin2c.mod");
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(1, Math::Vector(3.0f, 5.0f, -2.5f));
+ SetAngleX(1, -Math::PI*0.85f);
+ SetAngleY(1, -0.4f);
+ SetAngleZ(1, -0.1f);
+
+ CreateCrashSphere(Math::Vector(1.0f, 2.8f, -1.0f), 5.0f, SOUND_BOUMm, 0.45f);
+//? SetGlobalSphere(Math::Vector(1.0f, 5.0f, -1.0f), 10.0f);
+
+ CreateShadowCircle(5.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINmobilet2 ) // vehicle have caterpillars?
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 2.8f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+//? SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
+
+ CreateShadowCircle(5.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINmobiler1 ) // vehicle skating?
+ {
+ CreateCrashSphere(Math::Vector(1.0f, 2.8f, -1.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(1.0f, 5.0f, -1.0f), 10.0f);
+
+ CreateShadowCircle(5.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINmobiler2 ) // vehicle skating?
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
+
+ CreateShadowCircle(6.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINfactory ) // factory ?
+ {
+ CreateCrashSphere(Math::Vector( 9.0f, 1.0f, -11.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 2.0f, -11.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f, -10.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-12.0f, 11.0f, -4.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f, -2.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 8.0f, 3.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 2.0f, 4.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 2.0f, 10.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -4.0f, 0.0f, 10.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 18.0f);
+
+ CreateShadowCircle(20.0f, 0.7f);
+ }
+
+ if ( type == OBJECT_RUINdoor ) // converter holder?
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+//? SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 6.0f);
+
+ CreateShadowCircle(6.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINsupport ) // radar holder?
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+//? SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f);
+
+ CreateShadowCircle(3.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINradar ) // radar base?
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+//? SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 6.0f);
+
+ CreateShadowCircle(6.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINconvert ) // converter?
+ {
+ m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
+
+ CreateCrashSphere(Math::Vector(-10.0f, 0.0f, 4.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 0.0f, -4.0f), 5.0f, SOUND_BOUMm, 0.45f);
+//? SetGlobalSphere(Math::Vector(-3.0f, 0.0f, 0.0f), 14.0f);
+ }
+
+ if ( type == OBJECT_RUINbase ) // base?
+ {
+ CreateCrashSphere(Math::Vector( 0.0f, 15.0f, 0.0f),28.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 17.0f, 6.0f, 42.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 17.0f, 17.0f, 42.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-17.0f, 6.0f, 42.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-17.0f, 17.0f, 42.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-42.0f, 6.0f, 17.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-42.0f, 17.0f, 17.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-42.0f, 6.0f, -17.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-42.0f, 17.0f, -17.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-17.0f, 6.0f, -42.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-17.0f, 10.0f, -42.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 15.0f, 13.0f, -34.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 31.0f, 15.0f, -13.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 21.0f, 8.0f, -39.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 26.0f, 8.0f, -33.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 48.0f);
+
+ CreateShadowCircle(40.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINhead ) // base cap?
+ {
+ CreateCrashSphere(Math::Vector( 0.0f, 13.0f, 0.0f),20.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, -8.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f,-16.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f,-22.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-21.0f, 7.0f, 9.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -9.0f, 7.0f, 21.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 21.0f, 7.0f, 9.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 9.0f, 7.0f, 21.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-21.0f, 7.0f, -9.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -9.0f, 7.0f, -21.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 21.0f, 7.0f, -9.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 9.0f, 7.0f, -21.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 35.0f);
+
+ CreateShadowCircle(30.0f, 1.0f);
+ }
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); //to display the shadows immediately
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+
+ if ( type != OBJECT_RUINfactory &&
+ type != OBJECT_RUINconvert &&
+ type != OBJECT_RUINbase )
+ {
+ FloorAdjust();
+ }
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos); //to display the shadows immediately
+
+ if ( type == OBJECT_RUINmobilew1 )
+ {
+ pos = RetPosition(0);
+ pos.y -= 0.5f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)-0.1f;
+ SetAngleX(0, angle);
+ }
+
+ if ( type == OBJECT_RUINmobilew2 )
+ {
+ pos = RetPosition(0);
+ pos.y -= 1.5f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)-0.9f;
+ SetAngleX(0, angle);
+
+ angle = RetAngleZ(0)-0.1f;
+ SetAngleZ(0, angle);
+ }
+
+ if ( type == OBJECT_RUINmobilet1 )
+ {
+ pos = RetPosition(0);
+ pos.y -= 0.9f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)-0.3f;
+ SetAngleX(0, angle);
+ }
+
+ if ( type == OBJECT_RUINmobilet2 )
+ {
+ pos = RetPosition(0);
+ pos.y -= 1.5f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)-0.3f;
+ SetAngleX(0, angle);
+
+ angle = RetAngleZ(0)+0.8f;
+ SetAngleZ(0, angle);
+ }
+
+ if ( type == OBJECT_RUINmobiler1 )
+ {
+ pos = RetPosition(0);
+ pos.y += 4.0f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)-Math::PI*0.6f;
+ SetAngleX(0, angle);
+
+ angle = RetAngleZ(0)-0.2f;
+ SetAngleZ(0, angle);
+ }
+
+ if ( type == OBJECT_RUINmobiler2 )
+ {
+ pos = RetPosition(0);
+ pos.y += 2.0f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)-0.1f;
+ SetAngleX(0, angle);
+
+ angle = RetAngleZ(0)-0.3f;
+ SetAngleZ(0, angle);
+ }
+
+ if ( type == OBJECT_RUINdoor )
+ {
+ pos = RetPosition(0);
+ pos.y -= 0.5f;
+ SetPosition(0, pos);
+
+ angle = RetAngleZ(0)-0.1f;
+ SetAngleZ(0, angle);
+ }
+
+ if ( type == OBJECT_RUINsupport )
+ {
+ pos = RetPosition(0);
+ pos.y += 0.5f;
+ SetPosition(0, pos);
+
+//? angle = RetAngleY(0)+0.1f;
+//? SetAngleY(0, angle);
+
+ angle = RetAngleX(0)+0.1f;
+ SetAngleX(0, angle);
+
+ angle = RetAngleZ(0)+0.1f;
+ SetAngleZ(0, angle);
+ }
+
+ if ( type == OBJECT_RUINradar )
+ {
+ pos = RetPosition(0);
+ pos.y -= 0.5f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)+0.15f;
+ SetAngleX(0, angle);
+
+ angle = RetAngleZ(0)+0.1f;
+ SetAngleZ(0, angle);
+ }
+
+ if ( type == OBJECT_RUINconvert )
+ {
+ pos = RetPosition(0);
+ pos.y -= 1.0f;
+ SetPosition(0, pos);
+ }
+
+ if ( type == OBJECT_RUINbase )
+ {
+ pos = RetPosition(0);
+ pos.y -= 1.0f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)+0.15f;
+ SetAngleX(0, angle);
+ }
+
+ if ( type == OBJECT_RUINhead )
+ {
+ pos = RetPosition(0);
+ pos.y += 8.0f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)+Math::PI*0.4f;
+ SetAngleX(0, angle);
+ }
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a gadget apollo.
+
+bool CObject::CreateApollo(Math::Vector pos, float angle, ObjectType type)
+{
+ CModFile* pModFile;
+ int rank, i;
+
+ if ( m_engine->RetRestCreate() < 6 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ if ( type == OBJECT_APOLLO1 ) // LEM ?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\apollol1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 1.2f);
+ SetFloorHeight(0.0f);
+
+ for ( i=0 ; i<4 ; i++ ) // creates feet
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(i+1, rank);
+ SetObjectParent(i+1, 0);
+ pModFile->ReadModel("objects\\apollol2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetAngleY(i+1, Math::PI/2.0f*i);
+ }
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(5, rank);
+ SetObjectParent(5, 0);
+ pModFile->ReadModel("objects\\apollol3.mod"); // ladder
+ pModFile->CreateEngineObject(rank);
+
+//? m_terrain->AddBuildingLevel(pos, 10.0f, 13.0f, 12.0f, 0.0f);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 11.0f, 5.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 5.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 5.0f, -11.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 5.0f, 11.0f), 3.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 9.0f);
+
+ CreateShadowCircle(16.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_APOLLO2 ) // jeep
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); //it is a stationary object
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\apolloj1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ // Wheels.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(-5.75f, 1.65f, -5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(-5.75f, 1.65f, 5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(3, rank);
+ SetObjectParent(3, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ SetPosition(3, Math::Vector(5.75f, 1.65f, -5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(4, rank);
+ SetObjectParent(4, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ SetPosition(4, Math::Vector(5.75f, 1.65f, 5.0f));
+
+ // Accessories:
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(5, rank);
+ SetObjectParent(5, 0);
+ pModFile->ReadModel("objects\\apolloj2.mod"); // antenna
+ pModFile->CreateEngineObject(rank);
+ SetPosition(5, Math::Vector(5.5f, 8.8f, 2.0f));
+ SetAngleY(5, -120.0f*Math::PI/180.0f);
+ SetAngleZ(5, 45.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(6, rank);
+ SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\apolloj3.mod"); // camera
+ pModFile->CreateEngineObject(rank);
+ SetPosition(6, Math::Vector(5.5f, 2.8f, -2.0f));
+ SetAngleY(6, 30.0f*Math::PI/180.0f);
+
+ CreateCrashSphere(Math::Vector( 3.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-3.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 7.0f, 9.0f, 2.0f), 2.0f, SOUND_BOUMm, 0.20f);
+
+ CreateShadowCircle(7.0f, 0.8f);
+
+ FloorAdjust();
+ }
+
+ if ( type == OBJECT_APOLLO3 ) // flag?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\apollof.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ SetJotlerSphere(Math::Vector(0.0f, 4.0f, 0.0f), 1.0f);
+ CreateShadowCircle(2.0f, 0.3f);
+ }
+
+ if ( type == OBJECT_APOLLO4 ) // module?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\apollom.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 2.0f, SOUND_BOUMm, 0.45f);
+ CreateShadowCircle(5.0f, 0.8f);
+
+ FloorAdjust();
+ }
+
+ if ( type == OBJECT_APOLLO5 ) // antenna?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\apolloa.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\apolloj2.mod"); // antenna
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 5.0f, 0.0f));
+ SetAngleY(1, -120.0f*Math::PI/180.0f);
+ SetAngleZ(1, 45.0f*Math::PI/180.0f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.35f);
+ CreateShadowCircle(3.0f, 0.7f);
+ }
+
+ CreateOtherObject(type);
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ delete pModFile;
+ return true;
+}
+
+// Creates all sub-objects for managing the object.
+
+void CObject::CreateOtherObject(ObjectType type)
+{
+ if ( type == OBJECT_BASE )
+ {
+ m_auto = new CAutoBase(m_iMan, this);
+ }
+ if ( type == OBJECT_PORTICO )
+ {
+ m_auto = new CAutoPortico(m_iMan, this);
+ }
+ if ( type == OBJECT_DERRICK )
+ {
+ m_auto = new CAutoDerrick(m_iMan, this);
+ }
+ if ( type == OBJECT_FACTORY )
+ {
+ m_auto = new CAutoFactory(m_iMan, this);
+ }
+ if ( type == OBJECT_REPAIR )
+ {
+ m_auto = new CAutoRepair(m_iMan, this);
+ }
+ if ( type == OBJECT_DESTROYER )
+ {
+ m_auto = new CAutoDestroyer(m_iMan, this);
+ }
+ if ( type == OBJECT_STATION )
+ {
+ m_auto = new CAutoStation(m_iMan, this);
+ }
+ if ( type == OBJECT_CONVERT )
+ {
+ m_auto = new CAutoConvert(m_iMan, this);
+ }
+ if ( type == OBJECT_TOWER )
+ {
+ m_auto = new CAutoTower(m_iMan, this);
+ }
+ if ( type == OBJECT_RESEARCH )
+ {
+ m_auto = new CAutoResearch(m_iMan, this);
+ }
+ if ( type == OBJECT_RADAR )
+ {
+ m_auto = new CAutoRadar(m_iMan, this);
+ }
+ if ( type == OBJECT_INFO )
+ {
+ m_auto = new CAutoInfo(m_iMan, this);
+ }
+ if ( type == OBJECT_ENERGY )
+ {
+ m_auto = new CAutoEnergy(m_iMan, this);
+ }
+ if ( type == OBJECT_LABO )
+ {
+ m_auto = new CAutoLabo(m_iMan, this);
+ }
+ if ( type == OBJECT_NUCLEAR )
+ {
+ m_auto = new CAutoNuclear(m_iMan, this);
+ }
+ if ( type == OBJECT_PARA )
+ {
+ m_auto = new CAutoPara(m_iMan, this);
+ }
+ if ( type == OBJECT_SAFE )
+ {
+ m_auto = new CAutoSafe(m_iMan, this);
+ }
+ if ( type == OBJECT_HUSTON )
+ {
+ m_auto = new CAutoHuston(m_iMan, this);
+ }
+ if ( type == OBJECT_EGG )
+ {
+ m_auto = new CAutoEgg(m_iMan, this);
+ }
+ if ( type == OBJECT_NEST )
+ {
+ m_auto = new CAutoNest(m_iMan, this);
+ }
+ if ( type == OBJECT_ROOT5 )
+ {
+ m_auto = new CAutoRoot(m_iMan, this);
+ }
+ if ( type == OBJECT_MUSHROOM2 )
+ {
+ m_auto = new CAutoMush(m_iMan, this);
+ }
+ if ( type == OBJECT_FLAGb ||
+ type == OBJECT_FLAGr ||
+ type == OBJECT_FLAGg ||
+ type == OBJECT_FLAGy ||
+ type == OBJECT_FLAGv )
+ {
+ m_auto = new CAutoFlag(m_iMan, this);
+ }
+ if ( type == OBJECT_TEEN36 || // trunk?
+ type == OBJECT_TEEN37 || // boat?
+ type == OBJECT_TEEN38 ) // fan?
+ {
+ m_auto = new CAutoKid(m_iMan, this);
+ }
+}
+
+
+// Reads a program.
+
+bool CObject::ReadProgram(int rank, char* filename)
+{
+ if ( m_brain != 0 )
+ {
+ return m_brain->ReadProgram(rank, filename);
+ }
+ return false;
+}
+
+// Writes a program.
+
+bool CObject::WriteProgram(int rank, char* filename)
+{
+ if ( m_brain != 0 )
+ {
+ return m_brain->WriteProgram(rank, filename);
+ }
+ return false;
+}
+
+// Starts a program.
+
+bool CObject::RunProgram(int rank)
+{
+ if ( m_brain != 0 )
+ {
+ m_brain->RunProgram(rank);
+ return true;
+ }
+ if ( m_auto != 0 )
+ {
+ m_auto->Start(rank);
+ return true;
+ }
+ return false;
+}
+
+
+
+
+// Calculates the matrix for transforming the object.
+// Returns true if the matrix has changed.
+// The rotations occur in the order Y, Z and X.
+
+bool CObject::UpdateTransformObject(int part, bool bForceUpdate)
+{
+ Math::Vector position, angle, eye;
+ bool bModif = false;
+ int parent;
+
+ if ( m_truck != 0 ) // transported by truck?
+ {
+ m_objectPart[part].bTranslate = true;
+ m_objectPart[part].bRotate = true;
+ }
+
+ if ( !bForceUpdate &&
+ !m_objectPart[part].bTranslate &&
+ !m_objectPart[part].bRotate ) return false;
+
+ position = m_objectPart[part].position;
+ angle = m_objectPart[part].angle;
+
+ if ( part == 0 ) // main part?
+ {
+ position += m_linVibration;
+ angle += m_cirVibration+m_inclinaison;
+ }
+
+ if ( m_objectPart[part].bTranslate ||
+ m_objectPart[part].bRotate )
+ {
+ if ( m_objectPart[part].bTranslate )
+ {
+ m_objectPart[part].matTranslate.LoadIdentity();
+ m_objectPart[part].matTranslate.Set(1, 4, position.x);
+ m_objectPart[part].matTranslate.Set(2, 4, position.y);
+ m_objectPart[part].matTranslate.Set(3, 4, position.z);
+ }
+
+ if ( m_objectPart[part].bRotate )
+ {
+ Math::LoadRotationZXYMatrix(m_objectPart[part].matRotate, angle);
+ }
+
+ if ( m_objectPart[part].bZoom )
+ {
+ Math::Matrix mz;
+ mz.LoadIdentity();
+ mz.Set(1, 1, m_objectPart[part].zoom.x);
+ mz.Set(2, 2, m_objectPart[part].zoom.y);
+ mz.Set(3, 3, m_objectPart[part].zoom.z);
+ m_objectPart[part].matTransform = Math::MultiplyMatrices(m_objectPart[part].matTranslate,
+ Math::MultiplyMatrices(m_objectPart[part].matRotate, mz));
+ }
+ else
+ {
+ m_objectPart[part].matTransform = Math::MultiplyMatrices(m_objectPart[part].matTranslate,
+ m_objectPart[part].matRotate);
+ }
+ bModif = true;
+ }
+
+ if ( bForceUpdate ||
+ m_objectPart[part].bTranslate ||
+ m_objectPart[part].bRotate )
+ {
+ parent = m_objectPart[part].parentPart;
+
+ if ( part == 0 && m_truck != 0 ) // transported by a truck?
+ {
+ Math::Matrix* matWorldTruck;
+ matWorldTruck = m_truck->RetWorldMatrix(m_truckLink);
+ m_objectPart[part].matWorld = Math::MultiplyMatrices(*matWorldTruck,
+ m_objectPart[part].matTransform);
+ }
+ else
+ {
+ if ( parent == -1 ) // no parent?
+ {
+ m_objectPart[part].matWorld = m_objectPart[part].matTransform;
+ }
+ else
+ {
+ m_objectPart[part].matWorld = Math::MultiplyMatrices(m_objectPart[parent].matWorld,
+ m_objectPart[part].matTransform);
+ }
+ }
+ bModif = true;
+ }
+
+ if ( bModif )
+ {
+ m_engine->SetObjectTransform(m_objectPart[part].object,
+ m_objectPart[part].matWorld);
+ }
+
+ m_objectPart[part].bTranslate = false;
+ m_objectPart[part].bRotate = false;
+
+ return bModif;
+}
+
+// Updates all matrices to transform the object father and all his sons.
+// Assume a maximum of 4 degrees of freedom.
+// Appropriate, for example, to a body, an arm, forearm, hand and fingers.
+
+bool CObject::UpdateTransformObject()
+{
+ bool bUpdate1, bUpdate2, bUpdate3, bUpdate4;
+ int level1, level2, level3, level4, rank;
+ int parent1, parent2, parent3, parent4;
+
+ if ( m_bFlat )
+ {
+ for ( level1=0 ; level1<m_totalPart ; level1++ )
+ {
+ if ( !m_objectPart[level1].bUsed ) continue;
+ UpdateTransformObject(level1, false);
+ }
+ }
+ else
+ {
+ parent1 = 0;
+ bUpdate1 = UpdateTransformObject(parent1, false);
+
+ for ( level1=0 ; level1<m_totalPart ; level1++ )
+ {
+ rank = SearchDescendant(parent1, level1);
+ if ( rank == -1 ) break;
+
+ parent2 = rank;
+ bUpdate2 = UpdateTransformObject(rank, bUpdate1);
+
+ for ( level2=0 ; level2<m_totalPart ; level2++ )
+ {
+ rank = SearchDescendant(parent2, level2);
+ if ( rank == -1 ) break;
+
+ parent3 = rank;
+ bUpdate3 = UpdateTransformObject(rank, bUpdate2);
+
+ for ( level3=0 ; level3<m_totalPart ; level3++ )
+ {
+ rank = SearchDescendant(parent3, level3);
+ if ( rank == -1 ) break;
+
+ parent4 = rank;
+ bUpdate4 = UpdateTransformObject(rank, bUpdate3);
+
+ for ( level4=0 ; level4<m_totalPart ; level4++ )
+ {
+ rank = SearchDescendant(parent4, level4);
+ if ( rank == -1 ) break;
+
+ UpdateTransformObject(rank, bUpdate4);
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+
+// Puts all the progeny flat (there is more than fathers).
+// This allows for debris independently from each other in all directions.
+
+void CObject::FlatParent()
+{
+ int i;
+
+ for ( i=0 ; i<m_totalPart ; i++ )
+ {
+ m_objectPart[i].position.x = m_objectPart[i].matWorld.Get(1, 4);
+ m_objectPart[i].position.y = m_objectPart[i].matWorld.Get(2, 4);
+ m_objectPart[i].position.z = m_objectPart[i].matWorld.Get(3, 4);
+
+ m_objectPart[i].matWorld.Set(1, 4, 0.0f);
+ m_objectPart[i].matWorld.Set(2, 4, 0.0f);
+ m_objectPart[i].matWorld.Set(3, 4, 0.0f);
+
+ m_objectPart[i].matTranslate.Set(1, 4, 0.0f);
+ m_objectPart[i].matTranslate.Set(2, 4, 0.0f);
+ m_objectPart[i].matTranslate.Set(3, 4, 0.0f);
+
+ m_objectPart[i].parentPart = -1; // more parents
+ }
+
+ m_bFlat = true;
+}
+
+
+
+// Updates the mapping of the texture of the pile.
+
+void CObject::UpdateEnergyMapping()
+{
+ D3DMATERIAL7 mat;
+ float a, b, i, s, au, bu;
+ float limit[6];
+ int j;
+
+ if ( fabs(m_energy-m_lastEnergy) < 0.01f ) return;
+ m_lastEnergy = m_energy;
+
+ ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
+ mat.diffuse.r = 1.0f;
+ mat.diffuse.g = 1.0f;
+ mat.diffuse.b = 1.0f; // white
+ mat.ambient.r = 0.5f;
+ mat.ambient.g = 0.5f;
+ mat.ambient.b = 0.5f;
+
+ if ( m_type == OBJECT_POWER ||
+ m_type == OBJECT_ATOMIC )
+ {
+ a = 2.0f;
+ b = 0.0f; // dimensions of the battery (according to y)
+ }
+ if ( m_type == OBJECT_STATION )
+ {
+ a = 10.0f;
+ b = 4.0f; // dimensions of the battery (according to y)
+ }
+ if ( m_type == OBJECT_ENERGY )
+ {
+ a = 9.0f;
+ b = 3.0f; // dimensions of the battery (according to y)
+ }
+
+ i = 0.50f+0.25f*m_energy; // origin
+ s = i+0.25f; // width
+
+ au = (s-i)/(b-a);
+ bu = s-b*(s-i)/(b-a);
+
+ limit[0] = 0.0f;
+ limit[1] = m_engine->RetLimitLOD(0);
+ limit[2] = limit[1];
+ limit[3] = m_engine->RetLimitLOD(1);
+ limit[4] = limit[3];
+ limit[5] = 1000000.0f;
+
+ for ( j=0 ; j<3 ; j++ )
+ {
+ m_engine->ChangeTextureMapping(m_objectPart[0].object,
+ mat, D3DSTATEPART3, "lemt.tga", "",
+ limit[j*2+0], limit[j*2+1], D3DMAPPING1Y,
+ au, bu, 1.0f, 0.0f);
+ }
+}
+
+
+// Manual action.
+
+bool CObject::EventProcess(const Event &event)
+{
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if ADJUST_ONBOARD
+ if ( m_bSelect )
+ {
+ if ( event.param == 'E' ) debug_x += 0.1f;
+ if ( event.param == 'D' ) debug_x -= 0.1f;
+ if ( event.param == 'R' ) debug_y += 0.1f;
+ if ( event.param == 'F' ) debug_y -= 0.1f;
+ if ( event.param == 'T' ) debug_z += 0.1f;
+ if ( event.param == 'G' ) debug_z -= 0.1f;
+ }
+#endif
+#if ADJUST_ARM
+ if ( m_bSelect )
+ {
+ if ( event.param == 'X' ) debug_arm1 += 5.0f*Math::PI/180.0f;
+ if ( event.param == 'C' ) debug_arm1 -= 5.0f*Math::PI/180.0f;
+ if ( event.param == 'V' ) debug_arm2 += 5.0f*Math::PI/180.0f;
+ if ( event.param == 'B' ) debug_arm2 -= 5.0f*Math::PI/180.0f;
+ if ( event.param == 'N' ) debug_arm3 += 5.0f*Math::PI/180.0f;
+ if ( event.param == 'M' ) debug_arm3 -= 5.0f*Math::PI/180.0f;
+ if ( event.param == 'X' ||
+ event.param == 'C' ||
+ event.param == 'V' ||
+ event.param == 'B' ||
+ event.param == 'N' ||
+ event.param == 'M' )
+ {
+ SetAngleZ(1, debug_arm1);
+ SetAngleZ(2, debug_arm2);
+ SetAngleZ(3, debug_arm3);
+ char s[100];
+ sprintf(s, "a=%.2f b=%.2f c=%.2f", debug_arm1*180.0f/Math::PI, debug_arm2*180.0f/Math::PI, debug_arm3*180.0f/Math::PI);
+ m_engine->SetInfoText(5, s);
+ }
+ }
+#endif
+ }
+
+ if ( m_physics != 0 )
+ {
+ if ( !m_physics->EventProcess(event) ) // object destroyed?
+ {
+ if ( RetSelect() &&
+ m_type != OBJECT_ANT &&
+ m_type != OBJECT_SPIDER &&
+ m_type != OBJECT_BEE )
+ {
+ if ( !m_bDead ) m_camera->SetType(CAMERA_EXPLO);
+ m_main->DeselectAll();
+ }
+ return false;
+ }
+ }
+
+ if ( m_auto != 0 )
+ {
+ m_auto->EventProcess(event);
+
+ if ( event.event == EVENT_FRAME &&
+ m_auto->IsEnded() != ERR_CONTINUE )
+ {
+ m_auto->DeleteObject();
+ delete m_auto;
+ m_auto = 0;
+ }
+ }
+
+ if ( m_motion != 0 )
+ {
+ m_motion->EventProcess(event);
+ }
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ return true;
+}
+
+
+// Animates the object.
+
+bool CObject::EventFrame(const Event &event)
+{
+ if ( m_type == OBJECT_HUMAN && m_main->RetMainMovie() == MM_SATCOMopen )
+ {
+ UpdateTransformObject();
+ return true;
+ }
+
+ if ( m_type != OBJECT_SHOW && m_engine->RetPause() ) return true;
+
+ m_aTime += event.rTime;
+ m_shotTime += event.rTime;
+
+ VirusFrame(event.rTime);
+ PartiFrame(event.rTime);
+
+ UpdateMapping();
+ UpdateTransformObject();
+ UpdateSelectParticule();
+
+ if ( m_bProxyActivate ) // active if it is near?
+ {
+ CPyro* pyro;
+ Math::Vector eye;
+ float dist;
+
+ eye = m_engine->RetLookatPt();
+ dist = Math::Distance(eye, RetPosition(0));
+ if ( dist < m_proxyDistance )
+ {
+ m_bProxyActivate = false;
+ m_main->CreateShortcuts();
+ m_sound->Play(SOUND_FINDING);
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FINDING, this, 0.0f);
+ m_displayText->DisplayError(INFO_FINDING, this);
+ }
+ }
+
+ return true;
+}
+
+// Updates the mapping of the object.
+
+void CObject::UpdateMapping()
+{
+ if ( m_type == OBJECT_POWER ||
+ m_type == OBJECT_ATOMIC ||
+ m_type == OBJECT_STATION ||
+ m_type == OBJECT_ENERGY )
+ {
+ UpdateEnergyMapping();
+ }
+}
+
+
+// Management of viruses.
+
+void CObject::VirusFrame(float rTime)
+{
+ ParticuleType type;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ int r;
+
+ if ( !m_bVirusMode ) return; // healthy object?
+
+ m_virusTime += rTime;
+ if ( m_virusTime >= VIRUS_DELAY )
+ {
+ m_bVirusMode = false; // the virus is no longer active
+ }
+
+ if ( m_lastVirusParticule+m_engine->ParticuleAdapt(0.2f) <= m_aTime )
+ {
+ m_lastVirusParticule = m_aTime;
+
+ r = rand()%10;
+ if ( r == 0 ) type = PARTIVIRUS1;
+ if ( r == 1 ) type = PARTIVIRUS2;
+ if ( r == 2 ) type = PARTIVIRUS3;
+ if ( r == 3 ) type = PARTIVIRUS4;
+ if ( r == 4 ) type = PARTIVIRUS5;
+ if ( r == 5 ) type = PARTIVIRUS6;
+ if ( r == 6 ) type = PARTIVIRUS7;
+ if ( r == 7 ) type = PARTIVIRUS8;
+ if ( r == 8 ) type = PARTIVIRUS9;
+ if ( r == 9 ) type = PARTIVIRUS10;
+
+ pos = RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = Math::Rand()*4.0f+4.0f;
+ dim.x = Math::Rand()*0.3f+0.3f;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, type, 3.0f);
+ }
+}
+
+// Management particles mistresses.
+
+void CObject::PartiFrame(float rTime)
+{
+ Math::Vector pos, angle, factor;
+ int i, channel;
+
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ if ( !m_objectPart[i].bUsed ) continue;
+
+ channel = m_objectPart[i].masterParti;
+ if ( channel == -1 ) continue;
+
+ if ( !m_particule->GetPosition(channel, pos) )
+ {
+ m_objectPart[i].masterParti = -1; // particle no longer exists!
+ continue;
+ }
+
+ SetPosition(i, pos);
+
+ // Each song spins differently.
+ switch( i%5 )
+ {
+ case 0: factor = Math::Vector( 0.5f, 0.3f, 0.6f); break;
+ case 1: factor = Math::Vector(-0.3f, 0.4f,-0.2f); break;
+ case 2: factor = Math::Vector( 0.4f,-0.6f,-0.3f); break;
+ case 3: factor = Math::Vector(-0.6f,-0.2f, 0.0f); break;
+ case 4: factor = Math::Vector( 0.4f, 0.1f,-0.7f); break;
+ }
+
+ angle = RetAngle(i);
+ angle += rTime*Math::PI*factor;
+ SetAngle(i, angle);
+ }
+}
+
+
+// Changes the perspective to view if it was like in the vehicle,
+// or behind the vehicle.
+
+void CObject::SetViewFromHere(Math::Vector &eye, float &dirH, float &dirV,
+ Math::Vector &lookat, Math::Vector &upVec,
+ CameraType type)
+{
+ float speed;
+ int part;
+
+ UpdateTransformObject();
+
+ part = 0;
+ if ( m_type == OBJECT_HUMAN ||
+ m_type == OBJECT_TECH )
+ {
+ eye.x = -0.2f;
+ eye.y = 3.3f;
+ eye.z = 0.0f;
+//? eye.x = 1.0f;
+//? eye.y = 3.3f;
+//? eye.z = 0.0f;
+ }
+ else if ( m_type == OBJECT_MOBILErt ||
+ m_type == OBJECT_MOBILErr ||
+ m_type == OBJECT_MOBILErs )
+ {
+ eye.x = -1.1f; // on the cap
+ eye.y = 7.9f;
+ eye.z = 0.0f;
+ }
+ else if ( m_type == OBJECT_MOBILEwc ||
+ m_type == OBJECT_MOBILEtc ||
+ m_type == OBJECT_MOBILEfc ||
+ m_type == OBJECT_MOBILEic ) // fireball?
+ {
+//? eye.x = -0.9f; // on the cannon
+//? eye.y = 3.0f;
+//? eye.z = 0.0f;
+//? part = 1;
+ eye.x = -0.9f; // on the cannon
+ eye.y = 8.3f;
+ eye.z = 0.0f;
+ }
+ else if ( m_type == OBJECT_MOBILEwi ||
+ m_type == OBJECT_MOBILEti ||
+ m_type == OBJECT_MOBILEfi ||
+ m_type == OBJECT_MOBILEii ) // orgaball ?
+ {
+//? eye.x = -3.5f; // on the cannon
+//? eye.y = 5.1f;
+//? eye.z = 0.0f;
+//? part = 1;
+ eye.x = -2.5f; // on the cannon
+ eye.y = 10.4f;
+ eye.z = 0.0f;
+ }
+ else if ( m_type == OBJECT_MOBILErc )
+ {
+//? eye.x = 2.0f; // in the cannon
+//? eye.y = 0.0f;
+//? eye.z = 0.0f;
+//? part = 2;
+ eye.x = 4.0f; // on the cannon
+ eye.y = 11.0f;
+ eye.z = 0.0f;
+ }
+ else if ( m_type == OBJECT_MOBILEsa )
+ {
+ eye.x = 3.0f;
+ eye.y = 4.5f;
+ eye.z = 0.0f;
+ }
+ else if ( m_type == OBJECT_MOBILEdr )
+ {
+ eye.x = 1.0f;
+ eye.y = 6.5f;
+ eye.z = 0.0f;
+ }
+ else if ( m_type == OBJECT_APOLLO2 )
+ {
+ eye.x = -3.0f;
+ eye.y = 6.0f;
+ eye.z = -2.0f;
+ }
+ else
+ {
+ eye.x = 0.7f; // between the brackets
+ eye.y = 4.8f;
+ eye.z = 0.0f;
+ }
+#if ADJUST_ONBOARD
+ eye.x += debug_x;
+ eye.y += debug_y;
+ eye.z += debug_z;
+ char s[100];
+ sprintf(s, "x=%.2f y=%.2f z=%.2f", eye.x, eye.y, eye.z);
+ m_engine->SetInfoText(4, s);
+#endif
+
+ if ( type == CAMERA_BACK )
+ {
+ eye.x -= 20.0f;
+ eye.y += 1.0f;
+ }
+
+ lookat.x = eye.x+1.0f;
+ lookat.y = eye.y+0.0f;
+ lookat.z = eye.z+0.0f;
+
+ eye = Math::Transform(m_objectPart[part].matWorld, eye);
+ lookat = Math::Transform(m_objectPart[part].matWorld, lookat);
+
+ // Camera tilts when turning.
+ upVec = Math::Vector(0.0f, 1.0f, 0.0f);
+ if ( m_physics != 0 )
+ {
+ if ( m_physics->RetLand() ) // on ground?
+ {
+ speed = m_physics->RetLinMotionX(MO_REASPEED);
+ lookat.y -= speed*0.002f;
+
+ speed = m_physics->RetCirMotionY(MO_REASPEED);
+ upVec.z -= speed*0.04f;
+ }
+ else // in flight?
+ {
+ speed = m_physics->RetLinMotionX(MO_REASPEED);
+ lookat.y += speed*0.002f;
+
+ speed = m_physics->RetCirMotionY(MO_REASPEED);
+ upVec.z += speed*0.08f;
+ }
+ }
+ upVec = Math::Transform(m_objectPart[0].matRotate, upVec);
+
+ dirH = -(m_objectPart[part].angle.y+Math::PI/2.0f);
+ dirV = 0.0f;
+
+}
+
+
+// Management of features.
+
+void CObject::SetCharacter(Character* character)
+{
+ CopyMemory(&m_character, character, sizeof(Character));
+}
+
+void CObject::GetCharacter(Character* character)
+{
+ CopyMemory(character, &m_character, sizeof(Character));
+}
+
+Character* CObject::RetCharacter()
+{
+ return &m_character;
+}
+
+
+// Returns the absolute time.
+
+float CObject::RetAbsTime()
+{
+ return m_aTime;
+}
+
+
+// Management of energy contained in a battery.
+// Single subject possesses the battery energy, but not the vehicle that carries the battery!
+
+void CObject::SetEnergy(float level)
+{
+ if ( level < 0.0f ) level = 0.0f;
+ if ( level > 1.0f ) level = 1.0f;
+ m_energy = level;
+}
+
+float CObject::RetEnergy()
+{
+ if ( m_type != OBJECT_POWER &&
+ m_type != OBJECT_ATOMIC &&
+ m_type != OBJECT_STATION &&
+ m_type != OBJECT_ENERGY ) return 0.0f;
+ return m_energy;
+}
+
+
+// Management of the capacity of a battery.
+// Single subject possesses a battery capacity,
+// but not the vehicle that carries the battery!
+
+void CObject::SetCapacity(float capacity)
+{
+ m_capacity = capacity;
+}
+
+float CObject::RetCapacity()
+{
+ return m_capacity;
+}
+
+
+// Management of the shield.
+
+void CObject::SetShield(float level)
+{
+ m_shield = level;
+}
+
+float CObject::RetShield()
+{
+ if ( m_type == OBJECT_FRET ||
+ m_type == OBJECT_STONE ||
+ m_type == OBJECT_URANIUM ||
+ m_type == OBJECT_BULLET ||
+ m_type == OBJECT_METAL ||
+ m_type == OBJECT_BBOX ||
+ m_type == OBJECT_KEYa ||
+ m_type == OBJECT_KEYb ||
+ m_type == OBJECT_KEYc ||
+ m_type == OBJECT_KEYd ||
+ m_type == OBJECT_TNT ||
+ m_type == OBJECT_TEEN31 || // basket?
+ m_type == OBJECT_SCRAP1 ||
+ m_type == OBJECT_SCRAP2 ||
+ m_type == OBJECT_SCRAP3 ||
+ m_type == OBJECT_SCRAP4 ||
+ m_type == OBJECT_SCRAP5 ||
+ m_type == OBJECT_BOMB ||
+ m_type == OBJECT_WAYPOINT ||
+ m_type == OBJECT_FLAGb ||
+ m_type == OBJECT_FLAGr ||
+ m_type == OBJECT_FLAGg ||
+ m_type == OBJECT_FLAGy ||
+ m_type == OBJECT_FLAGv ||
+ m_type == OBJECT_POWER ||
+ m_type == OBJECT_ATOMIC ||
+ m_type == OBJECT_ANT ||
+ m_type == OBJECT_SPIDER ||
+ m_type == OBJECT_BEE ||
+ m_type == OBJECT_WORM ) return 0.0f;
+ return m_shield;
+}
+
+
+// Management of flight range (zero = infinity).
+
+void CObject::SetRange(float delay)
+{
+ m_range = delay;
+}
+
+float CObject::RetRange()
+{
+ return m_range;
+}
+
+
+// Management of transparency of the object.
+
+void CObject::SetTransparency(float value)
+{
+ int i;
+
+ m_transparency = value;
+
+ for ( i=0 ; i<m_totalPart ; i++ )
+ {
+ if ( m_objectPart[i].bUsed )
+ {
+ if ( m_type == OBJECT_BASE )
+ {
+ if ( i != 9 ) continue; // no central pillar?
+ }
+
+ m_engine->SetObjectTransparency(m_objectPart[i].object, value);
+ }
+ }
+}
+
+float CObject::RetTransparency()
+{
+ return m_transparency;
+}
+
+
+// Management of the object matter.
+
+ObjectMaterial CObject::RetMaterial()
+{
+ if ( m_type == OBJECT_HUMAN )
+ {
+ return OM_HUMAN;
+ }
+
+ if ( m_type == OBJECT_SCRAP4 ||
+ m_type == OBJECT_SCRAP5 )
+ {
+ return OM_HUMAN;
+ }
+
+ return OM_METAL;
+}
+
+
+// Indicates whether the gadget is a nonessential.
+
+void CObject::SetGadget(bool bMode)
+{
+ m_bGadget = bMode;
+}
+
+bool CObject::RetGadget()
+{
+ return m_bGadget;
+}
+
+
+// Indicates whether an object is stationary (ant on the back).
+
+void CObject::SetFixed(bool bFixed)
+{
+ m_bFixed = bFixed;
+}
+
+bool CObject::RetFixed()
+{
+ return m_bFixed;
+}
+
+
+// Indicates whether an object is subjected to clipping (obstacles).
+
+void CObject::SetClip(bool bClip)
+{
+ m_bClip = bClip;
+}
+
+bool CObject::RetClip()
+{
+ return m_bClip;
+}
+
+
+
+// Pushes an object.
+
+bool CObject::JostleObject(float force)
+{
+ CAutoJostle* pa;
+
+ if ( m_type == OBJECT_FLAGb ||
+ m_type == OBJECT_FLAGr ||
+ m_type == OBJECT_FLAGg ||
+ m_type == OBJECT_FLAGy ||
+ m_type == OBJECT_FLAGv ) // flag?
+ {
+ if ( m_auto == 0 ) return false;
+
+ m_auto->Start(1);
+ }
+ else
+ {
+ if ( m_auto != 0 ) return false;
+
+ m_auto = new CAutoJostle(m_iMan, this);
+ pa = (CAutoJostle*)m_auto;
+ pa->Start(0, force);
+ }
+
+ return true;
+}
+
+
+// Beginning of the effect when the instruction "detect" is used.
+
+void CObject::StartDetectEffect(CObject *target, bool bFound)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, goal;
+ Math::Point dim;
+
+ mat = RetWorldMatrix(0);
+ pos = Math::Transform(*mat, Math::Vector(2.0f, 3.0f, 0.0f));
+
+ if ( target == 0 )
+ {
+ goal = Math::Transform(*mat, Math::Vector(50.0f, 3.0f, 0.0f));
+ }
+ else
+ {
+ goal = target->RetPosition(0);
+ goal.y += 3.0f;
+ goal = Math::SegmentPoint(pos, goal, Math::Distance(pos, goal)-3.0f);
+ }
+
+ dim.x = 3.0f;
+ dim.y = dim.x;
+ m_particule->CreateRay(pos, goal, PARTIRAY2, dim, 0.2f);
+
+ if ( target != 0 )
+ {
+ goal = target->RetPosition(0);
+ goal.y += 3.0f;
+ goal = Math::SegmentPoint(pos, goal, Math::Distance(pos, goal)-1.0f);
+ dim.x = 6.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(goal, Math::Vector(0.0f, 0.0f, 0.0f), dim,
+ bFound?PARTIGLINT:PARTIGLINTr, 0.5f);
+ }
+
+ m_sound->Play(bFound?SOUND_BUILD:SOUND_RECOVER);
+}
+
+
+// Management of time from which a virus is active.
+
+void CObject::SetVirusMode(bool bEnable)
+{
+ m_bVirusMode = bEnable;
+ m_virusTime = 0.0f;
+
+ if ( m_bVirusMode && m_brain != 0 )
+ {
+ if ( !m_brain->IntroduceVirus() ) // tries to infect
+ {
+ m_bVirusMode = false; // program was not contaminated!
+ }
+ }
+}
+
+bool CObject::RetVirusMode()
+{
+ return m_bVirusMode;
+}
+
+float CObject::RetVirusTime()
+{
+ return m_virusTime;
+}
+
+
+// Management mode of the camera.
+
+void CObject::SetCameraType(CameraType type)
+{
+ m_cameraType = type;
+}
+
+CameraType CObject::RetCameraType()
+{
+ return m_cameraType;
+}
+
+void CObject::SetCameraDist(float dist)
+{
+ m_cameraDist = dist;
+}
+
+float CObject::RetCameraDist()
+{
+ return m_cameraDist;
+}
+
+void CObject::SetCameraLock(bool bLock)
+{
+ m_bCameraLock = bLock;
+}
+
+bool CObject::RetCameraLock()
+{
+ return m_bCameraLock;
+}
+
+
+
+// Management of the demonstration of the object.
+
+void CObject::SetHilite(bool bMode)
+{
+ int list[OBJECTMAXPART+1];
+ int i, j;
+
+ m_bHilite = bMode;
+
+ if ( m_bHilite )
+ {
+ j = 0;
+ for ( i=0 ; i<m_totalPart ; i++ )
+ {
+ if ( m_objectPart[i].bUsed )
+ {
+ list[j++] = m_objectPart[i].object;
+ }
+ }
+ list[j] = -1; // terminate
+
+ m_engine->SetHiliteRank(list); // gives the list of selected parts
+ }
+}
+
+bool CObject::RetHilite()
+{
+ return m_bHilite;
+}
+
+
+// Indicates whether the object is selected or not.
+
+void CObject::SetSelect(bool bMode, bool bDisplayError)
+{
+ Error err;
+
+ m_bSelect = bMode;
+
+ if ( m_physics != 0 )
+ {
+ m_physics->CreateInterface(m_bSelect);
+ }
+
+ if ( m_auto != 0 )
+ {
+ m_auto->CreateInterface(m_bSelect);
+ }
+
+ CreateSelectParticule(); // creates / removes particles
+
+ if ( !m_bSelect )
+ {
+ SetGunGoalH(0.0f); // puts the cannon right
+ return; // selects if not finished
+ }
+
+ err = ERR_OK;
+ if ( m_physics != 0 )
+ {
+ err = m_physics->RetError();
+ }
+ if ( m_auto != 0 )
+ {
+ err = m_auto->RetError();
+ }
+ if ( err != ERR_OK && bDisplayError )
+ {
+ m_displayText->DisplayError(err, this);
+ }
+}
+
+// Indicates whether the object is selected or not.
+
+bool CObject::RetSelect(bool bReal)
+{
+ if ( !bReal && m_main->RetFixScene() ) return false;
+ return m_bSelect;
+}
+
+
+// Indicates whether the object is selectable or not.
+
+void CObject::SetSelectable(bool bMode)
+{
+ m_bSelectable = bMode;
+}
+
+// Indicates whether the object is selecionnable or not.
+
+bool CObject::RetSelectable()
+{
+ return m_bSelectable;
+}
+
+
+// Management of the activities of an object.
+
+void CObject::SetActivity(bool bMode)
+{
+ if ( m_brain != 0 )
+ {
+ m_brain->SetActivity(bMode);
+ }
+}
+
+bool CObject::RetActivity()
+{
+ if ( m_brain != 0 )
+ {
+ return m_brain->RetActivity();
+ }
+ return false;
+}
+
+
+// Indicates if necessary to check the tokens of the object.
+
+void CObject::SetCheckToken(bool bMode)
+{
+ m_bCheckToken = bMode;
+}
+
+// Indicates if necessary to check the tokens of the object.
+
+bool CObject::RetCheckToken()
+{
+ return m_bCheckToken;
+}
+
+
+// Management of the visibility of an object.
+// The object is not hidden or visually disabled, but ignores detections!
+// For example: underground worm.
+
+void CObject::SetVisible(bool bVisible)
+{
+ m_bVisible = bVisible;
+}
+
+bool CObject::RetVisible()
+{
+ return m_bVisible;
+}
+
+
+// Management mode of operation of an object.
+// An inactive object is an object destroyed, nonexistent.
+// This mode is used for objects "resetables"
+// during training to simulate destruction.
+
+void CObject::SetEnable(bool bEnable)
+{
+ m_bEnable = bEnable;
+}
+
+bool CObject::RetEnable()
+{
+ return m_bEnable;
+}
+
+
+// Management mode or an object is only active when you're close.
+
+void CObject::SetProxyActivate(bool bActivate)
+{
+ m_bProxyActivate = bActivate;
+}
+
+bool CObject::RetProxyActivate()
+{
+ return m_bProxyActivate;
+}
+
+void CObject::SetProxyDistance(float distance)
+{
+ m_proxyDistance = distance;
+}
+
+float CObject::RetProxyDistance()
+{
+ return m_proxyDistance;
+}
+
+
+// Management of the method of increasing damage.
+
+void CObject::SetMagnifyDamage(float factor)
+{
+ m_magnifyDamage = factor;
+}
+
+float CObject::RetMagnifyDamage()
+{
+ return m_magnifyDamage;
+}
+
+
+// Management of free parameter.
+
+void CObject::SetParam(float value)
+{
+ m_param = value;
+}
+
+float CObject::RetParam()
+{
+ return m_param;
+}
+
+
+// Management of the mode "blocked" of an object.
+// For example, a cube of titanium is blocked while it is used to make something,
+//or a vehicle is blocked as its construction is not finished.
+
+void CObject::SetLock(bool bLock)
+{
+ m_bLock = bLock;
+}
+
+bool CObject::RetLock()
+{
+ return m_bLock;
+}
+
+// Management of the mode "current explosion" of an object.
+// An object in this mode is not saving.
+
+void CObject::SetExplo(bool bExplo)
+{
+ m_bExplo = bExplo;
+}
+
+bool CObject::RetExplo()
+{
+ return m_bExplo;
+}
+
+
+// Mode management "cargo ship" during movies.
+
+void CObject::SetCargo(bool bCargo)
+{
+ m_bCargo = bCargo;
+}
+
+bool CObject::RetCargo()
+{
+ return m_bCargo;
+}
+
+
+// Management of the HS mode of an object.
+
+void CObject::SetBurn(bool bBurn)
+{
+ m_bBurn = bBurn;
+
+//? if ( m_botVar != 0 )
+//? {
+//? if ( m_bBurn ) m_botVar->SetUserPtr(OBJECTDELETED);
+//? else m_botVar->SetUserPtr(this);
+//? }
+}
+
+bool CObject::RetBurn()
+{
+ return m_bBurn;
+}
+
+void CObject::SetDead(bool bDead)
+{
+ m_bDead = bDead;
+
+ if ( bDead && m_brain != 0 )
+ {
+ m_brain->StopProgram(); // stops the current task
+ }
+
+//? if ( m_botVar != 0 )
+//? {
+//? if ( m_bDead ) m_botVar->SetUserPtr(OBJECTDELETED);
+//? else m_botVar->SetUserPtr(this);
+//? }
+}
+
+bool CObject::RetDead()
+{
+ return m_bDead;
+}
+
+bool CObject::RetRuin()
+{
+ return m_bBurn|m_bFlat;
+}
+
+bool CObject::RetActif()
+{
+ return !m_bLock && !m_bBurn && !m_bFlat && m_bVisible && m_bEnable;
+}
+
+
+// Management of the point of aim.
+
+void CObject::SetGunGoalV(float gunGoal)
+{
+ if ( m_type == OBJECT_MOBILEfc ||
+ m_type == OBJECT_MOBILEtc ||
+ m_type == OBJECT_MOBILEwc ||
+ m_type == OBJECT_MOBILEic ) // fireball?
+ {
+ if ( gunGoal > 10.0f*Math::PI/180.0f ) gunGoal = 10.0f*Math::PI/180.0f;
+ if ( gunGoal < -20.0f*Math::PI/180.0f ) gunGoal = -20.0f*Math::PI/180.0f;
+ SetAngleZ(1, gunGoal);
+ }
+ else if ( m_type == OBJECT_MOBILEfi ||
+ m_type == OBJECT_MOBILEti ||
+ m_type == OBJECT_MOBILEwi ||
+ m_type == OBJECT_MOBILEii ) // orgaball?
+ {
+ if ( gunGoal > 20.0f*Math::PI/180.0f ) gunGoal = 20.0f*Math::PI/180.0f;
+ if ( gunGoal < -20.0f*Math::PI/180.0f ) gunGoal = -20.0f*Math::PI/180.0f;
+ SetAngleZ(1, gunGoal);
+ }
+ else if ( m_type == OBJECT_MOBILErc ) // phazer?
+ {
+ if ( gunGoal > 45.0f*Math::PI/180.0f ) gunGoal = 45.0f*Math::PI/180.0f;
+ if ( gunGoal < -20.0f*Math::PI/180.0f ) gunGoal = -20.0f*Math::PI/180.0f;
+ SetAngleZ(2, gunGoal);
+ }
+ else
+ {
+ gunGoal = 0.0f;
+ }
+
+ m_gunGoalV = gunGoal;
+}
+
+void CObject::SetGunGoalH(float gunGoal)
+{
+ if ( m_type == OBJECT_MOBILEfc ||
+ m_type == OBJECT_MOBILEtc ||
+ m_type == OBJECT_MOBILEwc ||
+ m_type == OBJECT_MOBILEic ) // fireball?
+ {
+ if ( gunGoal > 40.0f*Math::PI/180.0f ) gunGoal = 40.0f*Math::PI/180.0f;
+ if ( gunGoal < -40.0f*Math::PI/180.0f ) gunGoal = -40.0f*Math::PI/180.0f;
+ SetAngleY(1, gunGoal);
+ }
+ else if ( m_type == OBJECT_MOBILEfi ||
+ m_type == OBJECT_MOBILEti ||
+ m_type == OBJECT_MOBILEwi ||
+ m_type == OBJECT_MOBILEii ) // orgaball?
+ {
+ if ( gunGoal > 40.0f*Math::PI/180.0f ) gunGoal = 40.0f*Math::PI/180.0f;
+ if ( gunGoal < -40.0f*Math::PI/180.0f ) gunGoal = -40.0f*Math::PI/180.0f;
+ SetAngleY(1, gunGoal);
+ }
+ else if ( m_type == OBJECT_MOBILErc ) // phazer?
+ {
+ if ( gunGoal > 40.0f*Math::PI/180.0f ) gunGoal = 40.0f*Math::PI/180.0f;
+ if ( gunGoal < -40.0f*Math::PI/180.0f ) gunGoal = -40.0f*Math::PI/180.0f;
+ SetAngleY(2, gunGoal);
+ }
+ else
+ {
+ gunGoal = 0.0f;
+ }
+
+ m_gunGoalH = gunGoal;
+}
+
+float CObject::RetGunGoalV()
+{
+ return m_gunGoalV;
+}
+
+float CObject::RetGunGoalH()
+{
+ return m_gunGoalH;
+}
+
+
+
+// Shows the limits of the object.
+
+bool CObject::StartShowLimit()
+{
+ if ( m_showLimitRadius == 0.0f ) return false;
+
+ m_main->SetShowLimit(0, PARTILIMIT1, this, RetPosition(0), m_showLimitRadius);
+ m_bShowLimit = true;
+ return true;
+}
+
+void CObject::StopShowLimit()
+{
+ m_bShowLimit = false;
+}
+
+
+
+// Indicates whether a program is under execution.
+
+bool CObject::IsProgram()
+{
+ if ( m_brain == 0 ) return false;
+ return m_brain->IsProgram();
+}
+
+
+// Creates or removes particles associated to the object.
+
+void CObject::CreateSelectParticule()
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+ int i;
+
+ // Removes particles preceding.
+ for ( i=0 ; i<4 ; i++ )
+ {
+ if ( m_partiSel[i] != -1 )
+ {
+ m_particule->DeleteParticule(m_partiSel[i]);
+ m_partiSel[i] = -1;
+ }
+ }
+
+ if ( m_bSelect || IsProgram() )
+ {
+ // Creates particles lens for the headlights.
+ if ( m_type == OBJECT_MOBILEfa ||
+ m_type == OBJECT_MOBILEta ||
+ m_type == OBJECT_MOBILEwa ||
+ m_type == OBJECT_MOBILEia ||
+ m_type == OBJECT_MOBILEfc ||
+ m_type == OBJECT_MOBILEtc ||
+ m_type == OBJECT_MOBILEwc ||
+ m_type == OBJECT_MOBILEic ||
+ m_type == OBJECT_MOBILEfi ||
+ m_type == OBJECT_MOBILEti ||
+ m_type == OBJECT_MOBILEwi ||
+ m_type == OBJECT_MOBILEii ||
+ m_type == OBJECT_MOBILEfs ||
+ m_type == OBJECT_MOBILEts ||
+ m_type == OBJECT_MOBILEws ||
+ m_type == OBJECT_MOBILEis ||
+ m_type == OBJECT_MOBILErt ||
+ m_type == OBJECT_MOBILErc ||
+ m_type == OBJECT_MOBILErr ||
+ m_type == OBJECT_MOBILErs ||
+ m_type == OBJECT_MOBILEsa ||
+ m_type == OBJECT_MOBILEtg ||
+ m_type == OBJECT_MOBILEft ||
+ m_type == OBJECT_MOBILEtt ||
+ m_type == OBJECT_MOBILEwt ||
+ m_type == OBJECT_MOBILEit ||
+ m_type == OBJECT_MOBILEdr ) // vehicle?
+ {
+ pos = Math::Vector(0.0f, 0.0f, 0.0f);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 0.0f;
+ dim.y = 0.0f;
+ m_partiSel[0] = m_particule->CreateParticule(pos, speed, dim, PARTISELY, 1.0f, 0.0f, 0.0f);
+ m_partiSel[1] = m_particule->CreateParticule(pos, speed, dim, PARTISELY, 1.0f, 0.0f, 0.0f);
+ m_partiSel[2] = m_particule->CreateParticule(pos, speed, dim, PARTISELR, 1.0f, 0.0f, 0.0f);
+ m_partiSel[3] = m_particule->CreateParticule(pos, speed, dim, PARTISELR, 1.0f, 0.0f, 0.0f);
+ UpdateSelectParticule();
+ }
+ }
+}
+
+// Updates the particles associated to the object.
+
+void CObject::UpdateSelectParticule()
+{
+ Math::Vector pos[4];
+ Math::Point dim[4];
+ float zoom[4];
+ float angle;
+ int i;
+
+ if ( !m_bSelect && !IsProgram() ) return;
+
+ dim[0].x = 1.0f;
+ dim[1].x = 1.0f;
+ dim[2].x = 1.2f;
+ dim[3].x = 1.2f;
+
+ // Lens front yellow.
+ if ( m_type == OBJECT_MOBILErt ||
+ m_type == OBJECT_MOBILErc ||
+ m_type == OBJECT_MOBILErr ||
+ m_type == OBJECT_MOBILErs ) // large caterpillars?
+ {
+ pos[0] = Math::Vector(4.2f, 2.8f, 1.5f);
+ pos[1] = Math::Vector(4.2f, 2.8f, -1.5f);
+ dim[0].x = 1.5f;
+ dim[1].x = 1.5f;
+ }
+ else if ( m_type == OBJECT_MOBILEwt ||
+ m_type == OBJECT_MOBILEtt ||
+ m_type == OBJECT_MOBILEft ||
+ m_type == OBJECT_MOBILEit ) // trainer ?
+ {
+ pos[0] = Math::Vector(4.2f, 2.5f, 1.2f);
+ pos[1] = Math::Vector(4.2f, 2.5f, -1.2f);
+ dim[0].x = 1.5f;
+ dim[1].x = 1.5f;
+ }
+ else if ( m_type == OBJECT_MOBILEsa ) // submarine?
+ {
+ pos[0] = Math::Vector(3.6f, 4.0f, 2.0f);
+ pos[1] = Math::Vector(3.6f, 4.0f, -2.0f);
+ }
+ else if ( m_type == OBJECT_MOBILEtg ) // target?
+ {
+ pos[0] = Math::Vector(3.4f, 6.5f, 2.0f);
+ pos[1] = Math::Vector(3.4f, 6.5f, -2.0f);
+ }
+ else if ( m_type == OBJECT_MOBILEdr ) // designer?
+ {
+ pos[0] = Math::Vector(4.9f, 3.5f, 2.5f);
+ pos[1] = Math::Vector(4.9f, 3.5f, -2.5f);
+ }
+ else
+ {
+ pos[0] = Math::Vector(4.2f, 2.5f, 1.5f);
+ pos[1] = Math::Vector(4.2f, 2.5f, -1.5f);
+ }
+
+ // Red back lens
+ if ( m_type == OBJECT_MOBILEfa ||
+ m_type == OBJECT_MOBILEfc ||
+ m_type == OBJECT_MOBILEfi ||
+ m_type == OBJECT_MOBILEfs ||
+ m_type == OBJECT_MOBILEft ) // flying?
+ {
+ pos[2] = Math::Vector(-4.0f, 3.1f, 4.5f);
+ pos[3] = Math::Vector(-4.0f, 3.1f, -4.5f);
+ dim[2].x = 0.6f;
+ dim[3].x = 0.6f;
+ }
+ if ( m_type == OBJECT_MOBILEwa ||
+ m_type == OBJECT_MOBILEwc ||
+ m_type == OBJECT_MOBILEwi ||
+ m_type == OBJECT_MOBILEws ) // wheels?
+ {
+ pos[2] = Math::Vector(-4.5f, 2.7f, 2.8f);
+ pos[3] = Math::Vector(-4.5f, 2.7f, -2.8f);
+ }
+ if ( m_type == OBJECT_MOBILEwt ) // wheels?
+ {
+ pos[2] = Math::Vector(-4.0f, 2.5f, 2.2f);
+ pos[3] = Math::Vector(-4.0f, 2.5f, -2.2f);
+ }
+ if ( m_type == OBJECT_MOBILEia ||
+ m_type == OBJECT_MOBILEic ||
+ m_type == OBJECT_MOBILEii ||
+ m_type == OBJECT_MOBILEis ||
+ m_type == OBJECT_MOBILEit ) // legs?
+ {
+ pos[2] = Math::Vector(-4.5f, 2.7f, 2.8f);
+ pos[3] = Math::Vector(-4.5f, 2.7f, -2.8f);
+ }
+ if ( m_type == OBJECT_MOBILEta ||
+ m_type == OBJECT_MOBILEtc ||
+ m_type == OBJECT_MOBILEti ||
+ m_type == OBJECT_MOBILEts ||
+ m_type == OBJECT_MOBILEtt ) // caterpillars?
+ {
+ pos[2] = Math::Vector(-3.6f, 4.2f, 3.0f);
+ pos[3] = Math::Vector(-3.6f, 4.2f, -3.0f);
+ }
+ if ( m_type == OBJECT_MOBILErt ||
+ m_type == OBJECT_MOBILErc ||
+ m_type == OBJECT_MOBILErr ||
+ m_type == OBJECT_MOBILErs ) // large caterpillars?
+ {
+ pos[2] = Math::Vector(-5.0f, 5.2f, 2.5f);
+ pos[3] = Math::Vector(-5.0f, 5.2f, -2.5f);
+ }
+ if ( m_type == OBJECT_MOBILEsa ) // submarine?
+ {
+ pos[2] = Math::Vector(-3.6f, 4.0f, 2.0f);
+ pos[3] = Math::Vector(-3.6f, 4.0f, -2.0f);
+ }
+ if ( m_type == OBJECT_MOBILEtg ) // target?
+ {
+ pos[2] = Math::Vector(-2.4f, 6.5f, 2.0f);
+ pos[3] = Math::Vector(-2.4f, 6.5f, -2.0f);
+ }
+ if ( m_type == OBJECT_MOBILEdr ) // designer?
+ {
+ pos[2] = Math::Vector(-5.3f, 2.7f, 1.8f);
+ pos[3] = Math::Vector(-5.3f, 2.7f, -1.8f);
+ }
+
+ angle = RetAngleY(0)/Math::PI;
+
+ zoom[0] = 1.0f;
+ zoom[1] = 1.0f;
+ zoom[2] = 1.0f;
+ zoom[3] = 1.0f;
+
+ if ( IsProgram() && // current program?
+ Math::Mod(m_aTime, 0.7f) < 0.3f )
+ {
+ zoom[0] = 0.0f; // blinks
+ zoom[1] = 0.0f;
+ zoom[2] = 0.0f;
+ zoom[3] = 0.0f;
+ }
+
+ // Updates lens.
+ for ( i=0 ; i<4 ; i++ )
+ {
+ pos[i] = Math::Transform(m_objectPart[0].matWorld, pos[i]);
+ dim[i].y = dim[i].x;
+ m_particule->SetParam(m_partiSel[i], pos[i], dim[i], zoom[i], angle, 1.0f);
+ }
+}
+
+
+// Gives the pointer to the current script execution.
+
+void CObject::SetRunScript(CScript* script)
+{
+ m_runScript = script;
+}
+
+CScript* CObject::RetRunScript()
+{
+ return m_runScript;
+}
+
+// Returns the variables of "this" for CBOT.
+
+CBotVar* CObject::RetBotVar()
+{
+ return m_botVar;
+}
+
+// Returns the physics associated to the object.
+
+CPhysics* CObject::RetPhysics()
+{
+ return m_physics;
+}
+
+// Returns the brain associated to the object.
+
+CBrain* CObject::RetBrain()
+{
+ return m_brain;
+}
+
+// Returns the movement associated to the object.
+
+CMotion* CObject::RetMotion()
+{
+ return m_motion;
+}
+
+// Returns the controller associated to the object.
+
+CAuto* CObject::RetAuto()
+{
+ return m_auto;
+}
+
+void CObject::SetAuto(CAuto* automat)
+{
+ m_auto = automat;
+}
+
+
+
+// Management of the position in the file definition.
+
+void CObject::SetDefRank(int rank)
+{
+ m_defRank = rank;
+}
+
+int CObject::RetDefRank()
+{
+ return m_defRank;
+}
+
+
+// Gives the object name for the tooltip.
+
+bool CObject::GetTooltipName(char* name)
+{
+ GetResource(RES_OBJECT, m_type, name);
+ return ( name[0] != 0 );
+}
+
+
+// Adds the object previously selected in the list.
+
+void CObject::AddDeselList(CObject* pObj)
+{
+ int i;
+
+ if ( m_totalDesectList >= OBJECTMAXDESELLIST )
+ {
+ for ( i=0 ; i<OBJECTMAXDESELLIST-1 ; i++ )
+ {
+ m_objectDeselectList[i] = m_objectDeselectList[i+1];
+ }
+ m_totalDesectList --;
+ }
+
+ m_objectDeselectList[m_totalDesectList++] = pObj;
+}
+
+// Removes the previously selected object in the list.
+
+CObject* CObject::SubDeselList()
+{
+ if ( m_totalDesectList == 0 ) return 0;
+
+ return m_objectDeselectList[--m_totalDesectList];
+}
+
+// Removes an object reference if it is in the list.
+
+void CObject::DeleteDeselList(CObject* pObj)
+{
+ int i, j;
+
+ j = 0;
+ for ( i=0 ; i<m_totalDesectList ; i++ )
+ {
+ if ( m_objectDeselectList[i] != pObj )
+ {
+ m_objectDeselectList[j++] = m_objectDeselectList[i];
+ }
+ }
+ m_totalDesectList = j;
+}
+
+
+
+// Management of the state of the pencil drawing robot.
+
+bool CObject::RetTraceDown()
+{
+ CMotionVehicle* mv;
+ if ( m_motion == 0 ) return false;
+ mv = (CMotionVehicle*)m_motion;
+ return mv->RetTraceDown();
+}
+
+void CObject::SetTraceDown(bool bDown)
+{
+ CMotionVehicle* mv;
+ if ( m_motion == 0 ) return;
+ mv = (CMotionVehicle*)m_motion;
+ mv->SetTraceDown(bDown);
+}
+
+int CObject::RetTraceColor()
+{
+ CMotionVehicle* mv;
+ if ( m_motion == 0 ) return 0;
+ mv = (CMotionVehicle*)m_motion;
+ return mv->RetTraceColor();
+}
+
+void CObject::SetTraceColor(int color)
+{
+ CMotionVehicle* mv;
+ if ( m_motion == 0 ) return;
+ mv = (CMotionVehicle*)m_motion;
+ mv->SetTraceColor(color);
+}
+
+float CObject::RetTraceWidth()
+{
+ CMotionVehicle* mv;
+ if ( m_motion == 0 ) return 0.0f;
+ mv = (CMotionVehicle*)m_motion;
+ return mv->RetTraceWidth();
+}
+
+void CObject::SetTraceWidth(float width)
+{
+ CMotionVehicle* mv;
+ if ( m_motion == 0 ) return;
+ mv = (CMotionVehicle*)m_motion;
+ mv->SetTraceWidth(width);
+}
+
+
diff --git a/src/object/object.h b/src/object/object.h
index 735da8a..75283d6 100644
--- a/src/object/object.h
+++ b/src/object/object.h
@@ -1,775 +1,775 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// object.h
-
-#pragma once
-
-
-#include "old/d3dengine.h"
-#include "old/camera.h"
-#include "old/sound.h"
-
-
-class CInstanceManager;
-class CLight;
-class CTerrain;
-class CWater;
-class CParticule;
-class CPhysics;
-class CBrain;
-class CMotion;
-class CAuto;
-class CDisplayText;
-class CRobotMain;
-class CBotVar;
-class CScript;
-
-
-
-// The father of all parts must always be the part number zero!
-
-const int OBJECTMAXPART = 40;
-const int MAXCRASHSPHERE = 40;
-const int OBJECTMAXDESELLIST = 10;
-const int OBJECTMAXINFO = 10;
-const int OBJECTMAXCMDLINE = 20;
-
-enum ObjectType
-{
- OBJECT_NULL = 0, // object destroyed
- OBJECT_FIX = 1, // stationary scenery
- OBJECT_PORTICO = 2, // gantry
- OBJECT_BASE = 3, // great main base
- OBJECT_DERRICK = 4, // derrick set
- OBJECT_FACTORY = 5, // factory set
- OBJECT_STATION = 6, // recharging station
- OBJECT_CONVERT = 7, // converter station
- OBJECT_REPAIR = 8, // reparation
- OBJECT_TOWER = 9, // defense tower
- OBJECT_NEST = 10, // nest
- OBJECT_RESEARCH = 11, // research center
- OBJECT_RADAR = 12, // radar
- OBJECT_ENERGY = 13, // energy factory
- OBJECT_LABO = 14, // analytical laboratory for insect
- OBJECT_NUCLEAR = 15, // nuclear power plant
- OBJECT_START = 16, // starting
- OBJECT_END = 17, // finish
- OBJECT_INFO = 18, // information terminal
- OBJECT_PARA = 19, // lightning conductor
- OBJECT_TARGET1 = 20, // gate target
- OBJECT_TARGET2 = 21, // center target
- OBJECT_SAFE = 22, // safe
- OBJECT_HUSTON = 23, // control centre
- OBJECT_DESTROYER = 24, // destroyer
- OBJECT_FRET = 30, // transportable
- OBJECT_STONE = 31, // stone
- OBJECT_URANIUM = 32, // uranium
- OBJECT_METAL = 33, // metal
- OBJECT_POWER = 34, // normal battery
- OBJECT_ATOMIC = 35, // atomic battery
- OBJECT_BULLET = 36, // bullet
- OBJECT_BBOX = 37, // black-box
- OBJECT_TNT = 38, // box of TNT
- OBJECT_SCRAP1 = 40, // metal waste
- OBJECT_SCRAP2 = 41, // metal waste
- OBJECT_SCRAP3 = 42, // metal waste
- OBJECT_SCRAP4 = 43, // plastic waste
- OBJECT_SCRAP5 = 44, // plastic waste
- OBJECT_MARKPOWER = 50, // mark underground energy source
- OBJECT_MARKSTONE = 51, // mark underground ore
- OBJECT_MARKURANIUM = 52, // mark underground uranium
- OBJECT_MARKKEYa = 53, // mark underground key
- OBJECT_MARKKEYb = 54, // mark underground key
- OBJECT_MARKKEYc = 55, // mark underground key
- OBJECT_MARKKEYd = 56, // mark underground key
- OBJECT_BOMB = 60, // bomb
- OBJECT_WINFIRE = 61, // fireworks
- OBJECT_SHOW = 62, // shows a place
- OBJECT_BAG = 63, // survival bag
- OBJECT_PLANT0 = 70, // plant 0
- OBJECT_PLANT1 = 71, // plant 1
- OBJECT_PLANT2 = 72, // plant 2
- OBJECT_PLANT3 = 73, // plant 3
- OBJECT_PLANT4 = 74, // plant 4
- OBJECT_PLANT5 = 75, // plant 5
- OBJECT_PLANT6 = 76, // plant 6
- OBJECT_PLANT7 = 77, // plant 7
- OBJECT_PLANT8 = 78, // plant 8
- OBJECT_PLANT9 = 79, // plant 9
- OBJECT_PLANT10 = 80, // plant 10
- OBJECT_PLANT11 = 81, // plant 11
- OBJECT_PLANT12 = 82, // plant 12
- OBJECT_PLANT13 = 83, // plant 13
- OBJECT_PLANT14 = 84, // plant 14
- OBJECT_PLANT15 = 85, // plant 15
- OBJECT_PLANT16 = 86, // plant 16
- OBJECT_PLANT17 = 87, // plant 17
- OBJECT_PLANT18 = 88, // plant 18
- OBJECT_PLANT19 = 89, // plant 19
- OBJECT_TREE0 = 90, // tree 0
- OBJECT_TREE1 = 91, // tree 1
- OBJECT_TREE2 = 92, // tree 2
- OBJECT_TREE3 = 93, // tree 3
- OBJECT_TREE4 = 94, // tree 4
- OBJECT_TREE5 = 95, // tree 5
- OBJECT_TREE6 = 96, // tree 6
- OBJECT_TREE7 = 97, // tree 7
- OBJECT_TREE8 = 98, // tree 8
- OBJECT_TREE9 = 99, // tree 9
- OBJECT_MOBILEwt = 100, // wheel-trainer
- OBJECT_MOBILEtt = 101, // track-trainer
- OBJECT_MOBILEft = 102, // fly-trainer
- OBJECT_MOBILEit = 103, // insect-trainer
- OBJECT_MOBILEwa = 110, // wheel-arm
- OBJECT_MOBILEta = 111, // track-arm
- OBJECT_MOBILEfa = 112, // fly-arm
- OBJECT_MOBILEia = 113, // insect-arm
- OBJECT_MOBILEwc = 120, // wheel-cannon
- OBJECT_MOBILEtc = 121, // track-cannon
- OBJECT_MOBILEfc = 122, // fly-cannon
- OBJECT_MOBILEic = 123, // insect-cannon
- OBJECT_MOBILEwi = 130, // wheel-insect-cannon
- OBJECT_MOBILEti = 131, // track-insect-cannon
- OBJECT_MOBILEfi = 132, // fly-insect-cannon
- OBJECT_MOBILEii = 133, // insect-insect-cannon
- OBJECT_MOBILEws = 140, // wheel-search
- OBJECT_MOBILEts = 141, // track-search
- OBJECT_MOBILEfs = 142, // fly-search
- OBJECT_MOBILEis = 143, // insect-search
- OBJECT_MOBILErt = 200, // roller-terraform
- OBJECT_MOBILErc = 201, // roller-canon
- OBJECT_MOBILErr = 202, // roller-recover
- OBJECT_MOBILErs = 203, // roller-shield
- OBJECT_MOBILEsa = 210, // submarine
- OBJECT_MOBILEtg = 211, // training target
- OBJECT_MOBILEdr = 212, // robot drawing
- OBJECT_WAYPOINT = 250, // waypoint
- OBJECT_FLAGb = 260, // blue flag
- OBJECT_FLAGr = 261, // red flag
- OBJECT_FLAGg = 262, // green flag
- OBJECT_FLAGy = 263, // yellow flag
- OBJECT_FLAGv = 264, // violet flag
- OBJECT_KEYa = 270, // key a
- OBJECT_KEYb = 271, // key b
- OBJECT_KEYc = 272, // key c
- OBJECT_KEYd = 273, // key d
- OBJECT_HUMAN = 300, // human
- OBJECT_TOTO = 301, // toto
- OBJECT_TECH = 302, // technician
- OBJECT_BARRIER0 = 400, // barrier
- OBJECT_BARRIER1 = 401, // barrier
- OBJECT_BARRIER2 = 402, // barrier
- OBJECT_BARRIER3 = 403, // barrier
- OBJECT_BARRIER4 = 404, // barrier
- OBJECT_MOTHER = 500, // insect queen
- OBJECT_EGG = 501, // egg
- OBJECT_ANT = 502, // ant
- OBJECT_SPIDER = 503, // spider
- OBJECT_BEE = 504, // bee
- OBJECT_WORM = 505, // worm
- OBJECT_RUINmobilew1 = 600, // ruin 1
- OBJECT_RUINmobilew2 = 601, // ruin 1
- OBJECT_RUINmobilet1 = 602, // ruin 2
- OBJECT_RUINmobilet2 = 603, // ruin 2
- OBJECT_RUINmobiler1 = 604, // ruin 3
- OBJECT_RUINmobiler2 = 605, // ruin 3
- OBJECT_RUINfactory = 606, // ruin 4
- OBJECT_RUINdoor = 607, // ruin 5
- OBJECT_RUINsupport = 608, // ruin 6
- OBJECT_RUINradar = 609, // ruin 7
- OBJECT_RUINconvert = 610, // ruin 8
- OBJECT_RUINbase = 611, // ruin 9
- OBJECT_RUINhead = 612, // ruin 10
- OBJECT_TEEN0 = 620, // toy
- OBJECT_TEEN1 = 621, // toy
- OBJECT_TEEN2 = 622, // toy
- OBJECT_TEEN3 = 623, // toy
- OBJECT_TEEN4 = 624, // toy
- OBJECT_TEEN5 = 625, // toy
- OBJECT_TEEN6 = 626, // toy
- OBJECT_TEEN7 = 627, // toy
- OBJECT_TEEN8 = 628, // toy
- OBJECT_TEEN9 = 629, // toy
- OBJECT_TEEN10 = 630, // toy
- OBJECT_TEEN11 = 631, // toy
- OBJECT_TEEN12 = 632, // toy
- OBJECT_TEEN13 = 633, // toy
- OBJECT_TEEN14 = 634, // toy
- OBJECT_TEEN15 = 635, // toy
- OBJECT_TEEN16 = 636, // toy
- OBJECT_TEEN17 = 637, // toy
- OBJECT_TEEN18 = 638, // toy
- OBJECT_TEEN19 = 639, // toy
- OBJECT_TEEN20 = 640, // toy
- OBJECT_TEEN21 = 641, // toy
- OBJECT_TEEN22 = 642, // toy
- OBJECT_TEEN23 = 643, // toy
- OBJECT_TEEN24 = 644, // toy
- OBJECT_TEEN25 = 645, // toy
- OBJECT_TEEN26 = 646, // toy
- OBJECT_TEEN27 = 647, // toy
- OBJECT_TEEN28 = 648, // toy
- OBJECT_TEEN29 = 649, // toy
- OBJECT_TEEN30 = 650, // toy
- OBJECT_TEEN31 = 651, // toy
- OBJECT_TEEN32 = 652, // toy
- OBJECT_TEEN33 = 653, // toy
- OBJECT_TEEN34 = 654, // toy
- OBJECT_TEEN35 = 655, // toy
- OBJECT_TEEN36 = 656, // toy
- OBJECT_TEEN37 = 657, // toy
- OBJECT_TEEN38 = 658, // toy
- OBJECT_TEEN39 = 659, // toy
- OBJECT_TEEN40 = 660, // toy
- OBJECT_TEEN41 = 661, // toy
- OBJECT_TEEN42 = 662, // toy
- OBJECT_TEEN43 = 663, // toy
- OBJECT_TEEN44 = 664, // toy
- OBJECT_TEEN45 = 665, // toy
- OBJECT_TEEN46 = 666, // toy
- OBJECT_TEEN47 = 667, // toy
- OBJECT_TEEN48 = 668, // toy
- OBJECT_TEEN49 = 669, // toy
- OBJECT_QUARTZ0 = 700, // crystal 0
- OBJECT_QUARTZ1 = 701, // crystal 1
- OBJECT_QUARTZ2 = 702, // crystal 2
- OBJECT_QUARTZ3 = 703, // crystal 3
- OBJECT_QUARTZ4 = 704, // crystal 4
- OBJECT_QUARTZ5 = 705, // crystal 5
- OBJECT_QUARTZ6 = 706, // crystal 6
- OBJECT_QUARTZ7 = 707, // crystal 7
- OBJECT_QUARTZ8 = 708, // crystal 8
- OBJECT_QUARTZ9 = 709, // crystal 9
- OBJECT_ROOT0 = 710, // root 0
- OBJECT_ROOT1 = 711, // root 1
- OBJECT_ROOT2 = 712, // root 2
- OBJECT_ROOT3 = 713, // root 3
- OBJECT_ROOT4 = 714, // root 4
- OBJECT_ROOT5 = 715, // root 5
- OBJECT_ROOT6 = 716, // root 6
- OBJECT_ROOT7 = 717, // root 7
- OBJECT_ROOT8 = 718, // root 8
- OBJECT_ROOT9 = 719, // root 9
- OBJECT_SEAWEED0 = 720, // seaweed 0
- OBJECT_SEAWEED1 = 721, // seaweed 1
- OBJECT_SEAWEED2 = 722, // seaweed 2
- OBJECT_SEAWEED3 = 723, // seaweed 3
- OBJECT_SEAWEED4 = 724, // seaweed 4
- OBJECT_SEAWEED5 = 725, // seaweed 5
- OBJECT_SEAWEED6 = 726, // seaweed 6
- OBJECT_SEAWEED7 = 727, // seaweed 7
- OBJECT_SEAWEED8 = 728, // seaweed 8
- OBJECT_SEAWEED9 = 729, // seaweed 9
- OBJECT_MUSHROOM0 = 730, // mushroom 0
- OBJECT_MUSHROOM1 = 731, // mushroom 1
- OBJECT_MUSHROOM2 = 732, // mushroom 2
- OBJECT_MUSHROOM3 = 733, // mushroom 3
- OBJECT_MUSHROOM4 = 734, // mushroom 4
- OBJECT_MUSHROOM5 = 735, // mushroom 5
- OBJECT_MUSHROOM6 = 736, // mushroom 6
- OBJECT_MUSHROOM7 = 737, // mushroom 7
- OBJECT_MUSHROOM8 = 738, // mushroom 8
- OBJECT_MUSHROOM9 = 739, // mushroom 9
- OBJECT_APOLLO1 = 900, // apollo lem
- OBJECT_APOLLO2 = 901, // apollo jeep
- OBJECT_APOLLO3 = 902, // apollo flag
- OBJECT_APOLLO4 = 903, // apollo module
- OBJECT_APOLLO5 = 904, // apollo antenna
- OBJECT_HOME1 = 910, // home 1
- OBJECT_MAX = 1000,
-};
-
-enum ObjectMaterial
-{
- OM_METAL = 0, // metal
- OM_PLASTIC = 1, // plastic
- OM_HUMAN = 2, // cosmonaut
- OM_ANIMAL = 3, // insect
- OM_VEGETAL = 4, // plant
- OM_MINERAL = 5, // stone
-};
-
-struct ObjectPart
-{
- char bUsed;
- int object; // number of the object in CD3DEngine
- int parentPart; // number of father part
- int masterParti; // master canal of the particle
- Math::Vector position;
- Math::Vector angle;
- Math::Vector zoom;
- char bTranslate;
- char bRotate;
- char bZoom;
- Math::Matrix matTranslate;
- Math::Matrix matRotate;
- Math::Matrix matTransform;
- Math::Matrix matWorld;
-};
-
-struct Character
-{
- float wheelFront; // position X of the front wheels
- float wheelBack; // position X of the back wheels
- float wheelLeft; // position Z of the left wheels
- float wheelRight; // position Z of the right wheels
- float height; // normal height on top of ground
- Math::Vector posPower; // position of the battery
-};
-
-struct Info
-{
- char name[20]; // name of the information
- float value; // value of the information
-};
-
-enum ExploType
-{
- EXPLO_BOUM = 1,
- EXPLO_BURN = 2,
- EXPLO_WATER = 3,
-};
-
-enum ResetCap
-{
- RESET_NONE = 0,
- RESET_MOVE = 1,
- RESET_DELETE = 2,
-};
-
-enum RadarFilter
-{
- FILTER_NONE = 0,
- FILTER_ONLYLANDING = 1,
- FILTER_ONLYFLYING = 2,
-};
-
-
-
-
-class CObject
-{
-public:
- CObject(CInstanceManager* iMan);
- ~CObject();
-
- void DeleteObject(bool bAll=false);
- void Simplify();
- bool ExploObject(ExploType type, float force, float decay=1.0f);
-
- bool EventProcess(const Event &event);
- void UpdateMapping();
-
- int CreatePart();
- void DeletePart(int part);
- void SetObjectRank(int part, int objRank);
- int RetObjectRank(int part);
- void SetObjectParent(int part, int parent);
- void SetType(ObjectType type);
- ObjectType RetType();
- char* RetName();
- void SetOption(int option);
- int RetOption();
-
- void SetID(int id);
- int RetID();
-
- bool Write(char *line);
- bool Read(char *line);
-
- void SetDrawWorld(bool bDraw);
- void SetDrawFront(bool bDraw);
-
- bool CreateVehicle(Math::Vector pos, float angle, ObjectType type, float power, bool bTrainer, bool bToy);
- bool CreateInsect(Math::Vector pos, float angle, ObjectType type);
- bool CreateBuilding(Math::Vector pos, float angle, float height, ObjectType type, float power=1.0f);
- bool CreateResource(Math::Vector pos, float angle, ObjectType type, float power=1.0f);
- bool CreateFlag(Math::Vector pos, float angle, ObjectType type);
- bool CreateBarrier(Math::Vector pos, float angle, float height, ObjectType type);
- bool CreatePlant(Math::Vector pos, float angle, float height, ObjectType type);
- bool CreateMushroom(Math::Vector pos, float angle, float height, ObjectType type);
- bool CreateTeen(Math::Vector pos, float angle, float zoom, float height, ObjectType type);
- bool CreateQuartz(Math::Vector pos, float angle, float height, ObjectType type);
- bool CreateRoot(Math::Vector pos, float angle, float height, ObjectType type);
- bool CreateHome(Math::Vector pos, float angle, float height, ObjectType type);
- bool CreateRuin(Math::Vector pos, float angle, float height, ObjectType type);
- bool CreateApollo(Math::Vector pos, float angle, ObjectType type);
-
- bool ReadProgram(int rank, char* filename);
- bool WriteProgram(int rank, char* filename);
- bool RunProgram(int rank);
-
- int RetShadowLight();
- int RetEffectLight();
-
- void FlushCrashShere();
- int CreateCrashSphere(Math::Vector pos, float radius, Sound sound, float hardness=0.45f);
- int RetCrashSphereTotal();
- bool GetCrashSphere(int rank, Math::Vector &pos, float &radius);
- float RetCrashSphereHardness(int rank);
- Sound RetCrashSphereSound(int rank);
- void DeleteCrashSphere(int rank);
- void SetGlobalSphere(Math::Vector pos, float radius);
- void GetGlobalSphere(Math::Vector &pos, float &radius);
- void SetJotlerSphere(Math::Vector pos, float radius);
- void GetJotlerSphere(Math::Vector &pos, float &radius);
- void SetShieldRadius(float radius);
- float RetShieldRadius();
-
- void SetFloorHeight(float height);
- void FloorAdjust();
-
- void SetLinVibration(Math::Vector dir);
- Math::Vector RetLinVibration();
- void SetCirVibration(Math::Vector dir);
- Math::Vector RetCirVibration();
- void SetInclinaison(Math::Vector dir);
- Math::Vector RetInclinaison();
-
- void SetPosition(int part, const Math::Vector &pos);
- Math::Vector RetPosition(int part);
- void SetAngle(int part, const Math::Vector &angle);
- Math::Vector RetAngle(int part);
- void SetAngleY(int part, float angle);
- void SetAngleX(int part, float angle);
- void SetAngleZ(int part, float angle);
- float RetAngleY(int part);
- float RetAngleX(int part);
- float RetAngleZ(int part);
- void SetZoom(int part, float zoom);
- void SetZoom(int part, Math::Vector zoom);
- Math::Vector RetZoom(int part);
- void SetZoomX(int part, float zoom);
- float RetZoomX(int part);
- void SetZoomY(int part, float zoom);
- float RetZoomY(int part);
- void SetZoomZ(int part, float zoom);
- float RetZoomZ(int part);
-
- float RetWaterLevel();
-
- void SetTrainer(bool bEnable);
- bool RetTrainer();
-
- void SetToy(bool bEnable);
- bool RetToy();
-
- void SetManual(bool bManual);
- bool RetManual();
-
- void SetResetCap(ResetCap cap);
- ResetCap RetResetCap();
- void SetResetBusy(bool bBusy);
- bool RetResetBusy();
- void SetResetPosition(const Math::Vector &pos);
- Math::Vector RetResetPosition();
- void SetResetAngle(const Math::Vector &angle);
- Math::Vector RetResetAngle();
- void SetResetRun(int run);
- int RetResetRun();
-
- void SetMasterParticule(int part, int parti);
- int RetMasterParticule(int part);
-
- void SetPower(CObject* power);
- CObject* RetPower();
- void SetFret(CObject* fret);
- CObject* RetFret();
- void SetTruck(CObject* truck);
- CObject* RetTruck();
- void SetTruckPart(int part);
- int RetTruckPart();
-
- void InfoFlush();
- void DeleteInfo(int rank);
- void SetInfo(int rank, Info info);
- Info RetInfo(int rank);
- int RetInfoTotal();
- void SetInfoReturn(float value);
- float RetInfoReturn();
- void SetInfoUpdate(bool bUpdate);
- bool RetInfoUpdate();
-
- bool SetCmdLine(int rank, float value);
- float RetCmdLine(int rank);
-
- Math::Matrix* RetRotateMatrix(int part);
- Math::Matrix* RetTranslateMatrix(int part);
- Math::Matrix* RetTransformMatrix(int part);
- Math::Matrix* RetWorldMatrix(int part);
-
- void SetViewFromHere(Math::Vector &eye, float &dirH, float &dirV, Math::Vector &lookat, Math::Vector &upVec, CameraType type);
-
- void SetCharacter(Character* character);
- void GetCharacter(Character* character);
- Character* RetCharacter();
-
- float RetAbsTime();
-
- void SetEnergy(float level);
- float RetEnergy();
-
- void SetCapacity(float capacity);
- float RetCapacity();
-
- void SetShield(float level);
- float RetShield();
-
- void SetRange(float delay);
- float RetRange();
-
- void SetTransparency(float value);
- float RetTransparency();
-
- ObjectMaterial RetMaterial();
-
- void SetGadget(bool bMode);
- bool RetGadget();
-
- void SetFixed(bool bFixed);
- bool RetFixed();
-
- void SetClip(bool bClip);
- bool RetClip();
-
- bool JostleObject(float force);
-
- void StartDetectEffect(CObject *target, bool bFound);
-
- void SetVirusMode(bool bEnable);
- bool RetVirusMode();
- float RetVirusTime();
-
- void SetCameraType(CameraType type);
- CameraType RetCameraType();
- void SetCameraDist(float dist);
- float RetCameraDist();
- void SetCameraLock(bool bLock);
- bool RetCameraLock();
-
- void SetHilite(bool bMode);
- bool RetHilite();
-
- void SetSelect(bool bMode, bool bDisplayError=true);
- bool RetSelect(bool bReal=false);
-
- void SetSelectable(bool bMode);
- bool RetSelectable();
-
- void SetActivity(bool bMode);
- bool RetActivity();
-
- void SetVisible(bool bVisible);
- bool RetVisible();
-
- void SetEnable(bool bEnable);
- bool RetEnable();
-
- void SetCheckToken(bool bMode);
- bool RetCheckToken();
-
- void SetProxyActivate(bool bActivate);
- bool RetProxyActivate();
- void SetProxyDistance(float distance);
- float RetProxyDistance();
-
- void SetMagnifyDamage(float factor);
- float RetMagnifyDamage();
-
- void SetParam(float value);
- float RetParam();
-
- void SetExplo(bool bExplo);
- bool RetExplo();
- void SetLock(bool bLock);
- bool RetLock();
- void SetCargo(bool bCargo);
- bool RetCargo();
- void SetBurn(bool bBurn);
- bool RetBurn();
- void SetDead(bool bDead);
- bool RetDead();
- bool RetRuin();
- bool RetActif();
-
- void SetGunGoalV(float gunGoal);
- void SetGunGoalH(float gunGoal);
- float RetGunGoalV();
- float RetGunGoalH();
-
- bool StartShowLimit();
- void StopShowLimit();
-
- bool IsProgram();
- void CreateSelectParticule();
-
- void SetRunScript(CScript* script);
- CScript* RetRunScript();
- CBotVar* RetBotVar();
- CPhysics* RetPhysics();
- CBrain* RetBrain();
- CMotion* RetMotion();
- CAuto* RetAuto();
- void SetAuto(CAuto* automat);
-
- void SetDefRank(int rank);
- int RetDefRank();
-
- bool GetTooltipName(char* name);
-
- void AddDeselList(CObject* pObj);
- CObject* SubDeselList();
- void DeleteDeselList(CObject* pObj);
-
- bool CreateShadowCircle(float radius, float intensity, D3DShadowType type=D3DSHADOWNORM);
- bool CreateShadowLight(float height, D3DCOLORVALUE color);
- bool CreateEffectLight(float height, D3DCOLORVALUE color);
-
- void FlatParent();
-
- bool RetTraceDown();
- void SetTraceDown(bool bDown);
- int RetTraceColor();
- void SetTraceColor(int color);
- float RetTraceWidth();
- void SetTraceWidth(float width);
-
-protected:
- bool EventFrame(const Event &event);
- void VirusFrame(float rTime);
- void PartiFrame(float rTime);
- void CreateOtherObject(ObjectType type);
- void InitPart(int part);
- void UpdateTotalPart();
- int SearchDescendant(int parent, int n);
- void UpdateEnergyMapping();
- bool UpdateTransformObject(int part, bool bForceUpdate);
- bool UpdateTransformObject();
- void UpdateSelectParticule();
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CLight* m_light;
- CTerrain* m_terrain;
- CWater* m_water;
- CCamera* m_camera;
- CParticule* m_particule;
- CPhysics* m_physics;
- CBrain* m_brain;
- CMotion* m_motion;
- CAuto* m_auto;
- CDisplayText* m_displayText;
- CRobotMain* m_main;
- CSound* m_sound;
- CBotVar* m_botVar;
- CScript* m_runScript;
-
- ObjectType m_type; // OBJECT_*
- int m_id; // unique identifier
- char m_name[50]; // name of the object
- Character m_character; // characteristic
- int m_option; // option
- int m_partiReactor; // number of the particle of the reactor
- int m_shadowLight; // number of light from the shadows
- float m_shadowHeight; // height of light from the shadows
- int m_effectLight; // number of light effects
- float m_effectHeight; // height of light effects
- Math::Vector m_linVibration; // linear vibration
- Math::Vector m_cirVibration; // circular vibration
- Math::Vector m_inclinaison; // tilt
- CObject* m_power; // battery used by the vehicle
- CObject* m_fret; // object transported
- CObject* m_truck; // object with the latter
- int m_truckLink; // part
- float m_energy; // energy contained (if battery)
- float m_lastEnergy;
- float m_capacity; // capacity (if battery)
- float m_shield; // shield
- float m_range; // flight range
- float m_transparency; // transparency (0..1)
- int m_material; // matter(0..n)
- float m_aTime;
- float m_shotTime; // time since last shot
- bool m_bVirusMode; // virus activated/triggered
- float m_virusTime; // lifetime of the virus
- float m_lastVirusParticule;
- float m_lastParticule;
- bool m_bHilite;
- bool m_bSelect; // object selected
- bool m_bSelectable; // selectable object
- bool m_bCheckToken; // object with audited tokens
- bool m_bVisible; // object active but undetectable
- bool m_bEnable; // dead object
- bool m_bProxyActivate; // active object so close
- bool m_bGadget; // object nonessential
- bool m_bLock;
- bool m_bExplo;
- bool m_bCargo;
- bool m_bBurn;
- bool m_bDead;
- bool m_bFlat;
- bool m_bTrainer; // drive vehicle (without remote)
- bool m_bToy; // toy key
- bool m_bManual; // manual control (Scribbler)
- bool m_bFixed;
- bool m_bClip;
- bool m_bShowLimit;
- float m_showLimitRadius;
- float m_gunGoalV;
- float m_gunGoalH;
- CameraType m_cameraType;
- float m_cameraDist;
- bool m_bCameraLock;
- int m_defRank;
- float m_magnifyDamage;
- float m_proxyDistance;
- float m_param;
-
- int m_crashSphereUsed; // number of spheres used
- Math::Vector m_crashSpherePos[MAXCRASHSPHERE];
- float m_crashSphereRadius[MAXCRASHSPHERE];
- float m_crashSphereHardness[MAXCRASHSPHERE];
- Sound m_crashSphereSound[MAXCRASHSPHERE];
- Math::Vector m_globalSpherePos;
- float m_globalSphereRadius;
- Math::Vector m_jotlerSpherePos;
- float m_jotlerSphereRadius;
- float m_shieldRadius;
-
- int m_totalPart;
- ObjectPart m_objectPart[OBJECTMAXPART];
-
- int m_totalDesectList;
- CObject* m_objectDeselectList[OBJECTMAXDESELLIST];
-
- int m_partiSel[4];
-
- ResetCap m_resetCap;
- bool m_bResetBusy;
- Math::Vector m_resetPosition;
- Math::Vector m_resetAngle;
- int m_resetRun;
-
- int m_infoTotal;
- Info m_info[OBJECTMAXINFO];
- float m_infoReturn;
- bool m_bInfoUpdate;
-
- float m_cmdLine[OBJECTMAXCMDLINE];
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// object.h
+
+#pragma once
+
+
+#include "old/d3dengine.h"
+#include "old/camera.h"
+#include "old/sound.h"
+
+
+class CInstanceManager;
+class CLight;
+class CTerrain;
+class CWater;
+class CParticule;
+class CPhysics;
+class CBrain;
+class CMotion;
+class CAuto;
+class CDisplayText;
+class CRobotMain;
+class CBotVar;
+class CScript;
+
+
+
+// The father of all parts must always be the part number zero!
+
+const int OBJECTMAXPART = 40;
+const int MAXCRASHSPHERE = 40;
+const int OBJECTMAXDESELLIST = 10;
+const int OBJECTMAXINFO = 10;
+const int OBJECTMAXCMDLINE = 20;
+
+enum ObjectType
+{
+ OBJECT_NULL = 0, // object destroyed
+ OBJECT_FIX = 1, // stationary scenery
+ OBJECT_PORTICO = 2, // gantry
+ OBJECT_BASE = 3, // great main base
+ OBJECT_DERRICK = 4, // derrick set
+ OBJECT_FACTORY = 5, // factory set
+ OBJECT_STATION = 6, // recharging station
+ OBJECT_CONVERT = 7, // converter station
+ OBJECT_REPAIR = 8, // reparation
+ OBJECT_TOWER = 9, // defense tower
+ OBJECT_NEST = 10, // nest
+ OBJECT_RESEARCH = 11, // research center
+ OBJECT_RADAR = 12, // radar
+ OBJECT_ENERGY = 13, // energy factory
+ OBJECT_LABO = 14, // analytical laboratory for insect
+ OBJECT_NUCLEAR = 15, // nuclear power plant
+ OBJECT_START = 16, // starting
+ OBJECT_END = 17, // finish
+ OBJECT_INFO = 18, // information terminal
+ OBJECT_PARA = 19, // lightning conductor
+ OBJECT_TARGET1 = 20, // gate target
+ OBJECT_TARGET2 = 21, // center target
+ OBJECT_SAFE = 22, // safe
+ OBJECT_HUSTON = 23, // control centre
+ OBJECT_DESTROYER = 24, // destroyer
+ OBJECT_FRET = 30, // transportable
+ OBJECT_STONE = 31, // stone
+ OBJECT_URANIUM = 32, // uranium
+ OBJECT_METAL = 33, // metal
+ OBJECT_POWER = 34, // normal battery
+ OBJECT_ATOMIC = 35, // atomic battery
+ OBJECT_BULLET = 36, // bullet
+ OBJECT_BBOX = 37, // black-box
+ OBJECT_TNT = 38, // box of TNT
+ OBJECT_SCRAP1 = 40, // metal waste
+ OBJECT_SCRAP2 = 41, // metal waste
+ OBJECT_SCRAP3 = 42, // metal waste
+ OBJECT_SCRAP4 = 43, // plastic waste
+ OBJECT_SCRAP5 = 44, // plastic waste
+ OBJECT_MARKPOWER = 50, // mark underground energy source
+ OBJECT_MARKSTONE = 51, // mark underground ore
+ OBJECT_MARKURANIUM = 52, // mark underground uranium
+ OBJECT_MARKKEYa = 53, // mark underground key
+ OBJECT_MARKKEYb = 54, // mark underground key
+ OBJECT_MARKKEYc = 55, // mark underground key
+ OBJECT_MARKKEYd = 56, // mark underground key
+ OBJECT_BOMB = 60, // bomb
+ OBJECT_WINFIRE = 61, // fireworks
+ OBJECT_SHOW = 62, // shows a place
+ OBJECT_BAG = 63, // survival bag
+ OBJECT_PLANT0 = 70, // plant 0
+ OBJECT_PLANT1 = 71, // plant 1
+ OBJECT_PLANT2 = 72, // plant 2
+ OBJECT_PLANT3 = 73, // plant 3
+ OBJECT_PLANT4 = 74, // plant 4
+ OBJECT_PLANT5 = 75, // plant 5
+ OBJECT_PLANT6 = 76, // plant 6
+ OBJECT_PLANT7 = 77, // plant 7
+ OBJECT_PLANT8 = 78, // plant 8
+ OBJECT_PLANT9 = 79, // plant 9
+ OBJECT_PLANT10 = 80, // plant 10
+ OBJECT_PLANT11 = 81, // plant 11
+ OBJECT_PLANT12 = 82, // plant 12
+ OBJECT_PLANT13 = 83, // plant 13
+ OBJECT_PLANT14 = 84, // plant 14
+ OBJECT_PLANT15 = 85, // plant 15
+ OBJECT_PLANT16 = 86, // plant 16
+ OBJECT_PLANT17 = 87, // plant 17
+ OBJECT_PLANT18 = 88, // plant 18
+ OBJECT_PLANT19 = 89, // plant 19
+ OBJECT_TREE0 = 90, // tree 0
+ OBJECT_TREE1 = 91, // tree 1
+ OBJECT_TREE2 = 92, // tree 2
+ OBJECT_TREE3 = 93, // tree 3
+ OBJECT_TREE4 = 94, // tree 4
+ OBJECT_TREE5 = 95, // tree 5
+ OBJECT_TREE6 = 96, // tree 6
+ OBJECT_TREE7 = 97, // tree 7
+ OBJECT_TREE8 = 98, // tree 8
+ OBJECT_TREE9 = 99, // tree 9
+ OBJECT_MOBILEwt = 100, // wheel-trainer
+ OBJECT_MOBILEtt = 101, // track-trainer
+ OBJECT_MOBILEft = 102, // fly-trainer
+ OBJECT_MOBILEit = 103, // insect-trainer
+ OBJECT_MOBILEwa = 110, // wheel-arm
+ OBJECT_MOBILEta = 111, // track-arm
+ OBJECT_MOBILEfa = 112, // fly-arm
+ OBJECT_MOBILEia = 113, // insect-arm
+ OBJECT_MOBILEwc = 120, // wheel-cannon
+ OBJECT_MOBILEtc = 121, // track-cannon
+ OBJECT_MOBILEfc = 122, // fly-cannon
+ OBJECT_MOBILEic = 123, // insect-cannon
+ OBJECT_MOBILEwi = 130, // wheel-insect-cannon
+ OBJECT_MOBILEti = 131, // track-insect-cannon
+ OBJECT_MOBILEfi = 132, // fly-insect-cannon
+ OBJECT_MOBILEii = 133, // insect-insect-cannon
+ OBJECT_MOBILEws = 140, // wheel-search
+ OBJECT_MOBILEts = 141, // track-search
+ OBJECT_MOBILEfs = 142, // fly-search
+ OBJECT_MOBILEis = 143, // insect-search
+ OBJECT_MOBILErt = 200, // roller-terraform
+ OBJECT_MOBILErc = 201, // roller-canon
+ OBJECT_MOBILErr = 202, // roller-recover
+ OBJECT_MOBILErs = 203, // roller-shield
+ OBJECT_MOBILEsa = 210, // submarine
+ OBJECT_MOBILEtg = 211, // training target
+ OBJECT_MOBILEdr = 212, // robot drawing
+ OBJECT_WAYPOINT = 250, // waypoint
+ OBJECT_FLAGb = 260, // blue flag
+ OBJECT_FLAGr = 261, // red flag
+ OBJECT_FLAGg = 262, // green flag
+ OBJECT_FLAGy = 263, // yellow flag
+ OBJECT_FLAGv = 264, // violet flag
+ OBJECT_KEYa = 270, // key a
+ OBJECT_KEYb = 271, // key b
+ OBJECT_KEYc = 272, // key c
+ OBJECT_KEYd = 273, // key d
+ OBJECT_HUMAN = 300, // human
+ OBJECT_TOTO = 301, // toto
+ OBJECT_TECH = 302, // technician
+ OBJECT_BARRIER0 = 400, // barrier
+ OBJECT_BARRIER1 = 401, // barrier
+ OBJECT_BARRIER2 = 402, // barrier
+ OBJECT_BARRIER3 = 403, // barrier
+ OBJECT_BARRIER4 = 404, // barrier
+ OBJECT_MOTHER = 500, // insect queen
+ OBJECT_EGG = 501, // egg
+ OBJECT_ANT = 502, // ant
+ OBJECT_SPIDER = 503, // spider
+ OBJECT_BEE = 504, // bee
+ OBJECT_WORM = 505, // worm
+ OBJECT_RUINmobilew1 = 600, // ruin 1
+ OBJECT_RUINmobilew2 = 601, // ruin 1
+ OBJECT_RUINmobilet1 = 602, // ruin 2
+ OBJECT_RUINmobilet2 = 603, // ruin 2
+ OBJECT_RUINmobiler1 = 604, // ruin 3
+ OBJECT_RUINmobiler2 = 605, // ruin 3
+ OBJECT_RUINfactory = 606, // ruin 4
+ OBJECT_RUINdoor = 607, // ruin 5
+ OBJECT_RUINsupport = 608, // ruin 6
+ OBJECT_RUINradar = 609, // ruin 7
+ OBJECT_RUINconvert = 610, // ruin 8
+ OBJECT_RUINbase = 611, // ruin 9
+ OBJECT_RUINhead = 612, // ruin 10
+ OBJECT_TEEN0 = 620, // toy
+ OBJECT_TEEN1 = 621, // toy
+ OBJECT_TEEN2 = 622, // toy
+ OBJECT_TEEN3 = 623, // toy
+ OBJECT_TEEN4 = 624, // toy
+ OBJECT_TEEN5 = 625, // toy
+ OBJECT_TEEN6 = 626, // toy
+ OBJECT_TEEN7 = 627, // toy
+ OBJECT_TEEN8 = 628, // toy
+ OBJECT_TEEN9 = 629, // toy
+ OBJECT_TEEN10 = 630, // toy
+ OBJECT_TEEN11 = 631, // toy
+ OBJECT_TEEN12 = 632, // toy
+ OBJECT_TEEN13 = 633, // toy
+ OBJECT_TEEN14 = 634, // toy
+ OBJECT_TEEN15 = 635, // toy
+ OBJECT_TEEN16 = 636, // toy
+ OBJECT_TEEN17 = 637, // toy
+ OBJECT_TEEN18 = 638, // toy
+ OBJECT_TEEN19 = 639, // toy
+ OBJECT_TEEN20 = 640, // toy
+ OBJECT_TEEN21 = 641, // toy
+ OBJECT_TEEN22 = 642, // toy
+ OBJECT_TEEN23 = 643, // toy
+ OBJECT_TEEN24 = 644, // toy
+ OBJECT_TEEN25 = 645, // toy
+ OBJECT_TEEN26 = 646, // toy
+ OBJECT_TEEN27 = 647, // toy
+ OBJECT_TEEN28 = 648, // toy
+ OBJECT_TEEN29 = 649, // toy
+ OBJECT_TEEN30 = 650, // toy
+ OBJECT_TEEN31 = 651, // toy
+ OBJECT_TEEN32 = 652, // toy
+ OBJECT_TEEN33 = 653, // toy
+ OBJECT_TEEN34 = 654, // toy
+ OBJECT_TEEN35 = 655, // toy
+ OBJECT_TEEN36 = 656, // toy
+ OBJECT_TEEN37 = 657, // toy
+ OBJECT_TEEN38 = 658, // toy
+ OBJECT_TEEN39 = 659, // toy
+ OBJECT_TEEN40 = 660, // toy
+ OBJECT_TEEN41 = 661, // toy
+ OBJECT_TEEN42 = 662, // toy
+ OBJECT_TEEN43 = 663, // toy
+ OBJECT_TEEN44 = 664, // toy
+ OBJECT_TEEN45 = 665, // toy
+ OBJECT_TEEN46 = 666, // toy
+ OBJECT_TEEN47 = 667, // toy
+ OBJECT_TEEN48 = 668, // toy
+ OBJECT_TEEN49 = 669, // toy
+ OBJECT_QUARTZ0 = 700, // crystal 0
+ OBJECT_QUARTZ1 = 701, // crystal 1
+ OBJECT_QUARTZ2 = 702, // crystal 2
+ OBJECT_QUARTZ3 = 703, // crystal 3
+ OBJECT_QUARTZ4 = 704, // crystal 4
+ OBJECT_QUARTZ5 = 705, // crystal 5
+ OBJECT_QUARTZ6 = 706, // crystal 6
+ OBJECT_QUARTZ7 = 707, // crystal 7
+ OBJECT_QUARTZ8 = 708, // crystal 8
+ OBJECT_QUARTZ9 = 709, // crystal 9
+ OBJECT_ROOT0 = 710, // root 0
+ OBJECT_ROOT1 = 711, // root 1
+ OBJECT_ROOT2 = 712, // root 2
+ OBJECT_ROOT3 = 713, // root 3
+ OBJECT_ROOT4 = 714, // root 4
+ OBJECT_ROOT5 = 715, // root 5
+ OBJECT_ROOT6 = 716, // root 6
+ OBJECT_ROOT7 = 717, // root 7
+ OBJECT_ROOT8 = 718, // root 8
+ OBJECT_ROOT9 = 719, // root 9
+ OBJECT_SEAWEED0 = 720, // seaweed 0
+ OBJECT_SEAWEED1 = 721, // seaweed 1
+ OBJECT_SEAWEED2 = 722, // seaweed 2
+ OBJECT_SEAWEED3 = 723, // seaweed 3
+ OBJECT_SEAWEED4 = 724, // seaweed 4
+ OBJECT_SEAWEED5 = 725, // seaweed 5
+ OBJECT_SEAWEED6 = 726, // seaweed 6
+ OBJECT_SEAWEED7 = 727, // seaweed 7
+ OBJECT_SEAWEED8 = 728, // seaweed 8
+ OBJECT_SEAWEED9 = 729, // seaweed 9
+ OBJECT_MUSHROOM0 = 730, // mushroom 0
+ OBJECT_MUSHROOM1 = 731, // mushroom 1
+ OBJECT_MUSHROOM2 = 732, // mushroom 2
+ OBJECT_MUSHROOM3 = 733, // mushroom 3
+ OBJECT_MUSHROOM4 = 734, // mushroom 4
+ OBJECT_MUSHROOM5 = 735, // mushroom 5
+ OBJECT_MUSHROOM6 = 736, // mushroom 6
+ OBJECT_MUSHROOM7 = 737, // mushroom 7
+ OBJECT_MUSHROOM8 = 738, // mushroom 8
+ OBJECT_MUSHROOM9 = 739, // mushroom 9
+ OBJECT_APOLLO1 = 900, // apollo lem
+ OBJECT_APOLLO2 = 901, // apollo jeep
+ OBJECT_APOLLO3 = 902, // apollo flag
+ OBJECT_APOLLO4 = 903, // apollo module
+ OBJECT_APOLLO5 = 904, // apollo antenna
+ OBJECT_HOME1 = 910, // home 1
+ OBJECT_MAX = 1000,
+};
+
+enum ObjectMaterial
+{
+ OM_METAL = 0, // metal
+ OM_PLASTIC = 1, // plastic
+ OM_HUMAN = 2, // cosmonaut
+ OM_ANIMAL = 3, // insect
+ OM_VEGETAL = 4, // plant
+ OM_MINERAL = 5, // stone
+};
+
+struct ObjectPart
+{
+ char bUsed;
+ int object; // number of the object in CD3DEngine
+ int parentPart; // number of father part
+ int masterParti; // master canal of the particle
+ Math::Vector position;
+ Math::Vector angle;
+ Math::Vector zoom;
+ char bTranslate;
+ char bRotate;
+ char bZoom;
+ Math::Matrix matTranslate;
+ Math::Matrix matRotate;
+ Math::Matrix matTransform;
+ Math::Matrix matWorld;
+};
+
+struct Character
+{
+ float wheelFront; // position X of the front wheels
+ float wheelBack; // position X of the back wheels
+ float wheelLeft; // position Z of the left wheels
+ float wheelRight; // position Z of the right wheels
+ float height; // normal height on top of ground
+ Math::Vector posPower; // position of the battery
+};
+
+struct Info
+{
+ char name[20]; // name of the information
+ float value; // value of the information
+};
+
+enum ExploType
+{
+ EXPLO_BOUM = 1,
+ EXPLO_BURN = 2,
+ EXPLO_WATER = 3,
+};
+
+enum ResetCap
+{
+ RESET_NONE = 0,
+ RESET_MOVE = 1,
+ RESET_DELETE = 2,
+};
+
+enum RadarFilter
+{
+ FILTER_NONE = 0,
+ FILTER_ONLYLANDING = 1,
+ FILTER_ONLYFLYING = 2,
+};
+
+
+
+
+class CObject
+{
+public:
+ CObject(CInstanceManager* iMan);
+ ~CObject();
+
+ void DeleteObject(bool bAll=false);
+ void Simplify();
+ bool ExploObject(ExploType type, float force, float decay=1.0f);
+
+ bool EventProcess(const Event &event);
+ void UpdateMapping();
+
+ int CreatePart();
+ void DeletePart(int part);
+ void SetObjectRank(int part, int objRank);
+ int RetObjectRank(int part);
+ void SetObjectParent(int part, int parent);
+ void SetType(ObjectType type);
+ ObjectType RetType();
+ char* RetName();
+ void SetOption(int option);
+ int RetOption();
+
+ void SetID(int id);
+ int RetID();
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+ void SetDrawWorld(bool bDraw);
+ void SetDrawFront(bool bDraw);
+
+ bool CreateVehicle(Math::Vector pos, float angle, ObjectType type, float power, bool bTrainer, bool bToy);
+ bool CreateInsect(Math::Vector pos, float angle, ObjectType type);
+ bool CreateBuilding(Math::Vector pos, float angle, float height, ObjectType type, float power=1.0f);
+ bool CreateResource(Math::Vector pos, float angle, ObjectType type, float power=1.0f);
+ bool CreateFlag(Math::Vector pos, float angle, ObjectType type);
+ bool CreateBarrier(Math::Vector pos, float angle, float height, ObjectType type);
+ bool CreatePlant(Math::Vector pos, float angle, float height, ObjectType type);
+ bool CreateMushroom(Math::Vector pos, float angle, float height, ObjectType type);
+ bool CreateTeen(Math::Vector pos, float angle, float zoom, float height, ObjectType type);
+ bool CreateQuartz(Math::Vector pos, float angle, float height, ObjectType type);
+ bool CreateRoot(Math::Vector pos, float angle, float height, ObjectType type);
+ bool CreateHome(Math::Vector pos, float angle, float height, ObjectType type);
+ bool CreateRuin(Math::Vector pos, float angle, float height, ObjectType type);
+ bool CreateApollo(Math::Vector pos, float angle, ObjectType type);
+
+ bool ReadProgram(int rank, char* filename);
+ bool WriteProgram(int rank, char* filename);
+ bool RunProgram(int rank);
+
+ int RetShadowLight();
+ int RetEffectLight();
+
+ void FlushCrashShere();
+ int CreateCrashSphere(Math::Vector pos, float radius, Sound sound, float hardness=0.45f);
+ int RetCrashSphereTotal();
+ bool GetCrashSphere(int rank, Math::Vector &pos, float &radius);
+ float RetCrashSphereHardness(int rank);
+ Sound RetCrashSphereSound(int rank);
+ void DeleteCrashSphere(int rank);
+ void SetGlobalSphere(Math::Vector pos, float radius);
+ void GetGlobalSphere(Math::Vector &pos, float &radius);
+ void SetJotlerSphere(Math::Vector pos, float radius);
+ void GetJotlerSphere(Math::Vector &pos, float &radius);
+ void SetShieldRadius(float radius);
+ float RetShieldRadius();
+
+ void SetFloorHeight(float height);
+ void FloorAdjust();
+
+ void SetLinVibration(Math::Vector dir);
+ Math::Vector RetLinVibration();
+ void SetCirVibration(Math::Vector dir);
+ Math::Vector RetCirVibration();
+ void SetInclinaison(Math::Vector dir);
+ Math::Vector RetInclinaison();
+
+ void SetPosition(int part, const Math::Vector &pos);
+ Math::Vector RetPosition(int part);
+ void SetAngle(int part, const Math::Vector &angle);
+ Math::Vector RetAngle(int part);
+ void SetAngleY(int part, float angle);
+ void SetAngleX(int part, float angle);
+ void SetAngleZ(int part, float angle);
+ float RetAngleY(int part);
+ float RetAngleX(int part);
+ float RetAngleZ(int part);
+ void SetZoom(int part, float zoom);
+ void SetZoom(int part, Math::Vector zoom);
+ Math::Vector RetZoom(int part);
+ void SetZoomX(int part, float zoom);
+ float RetZoomX(int part);
+ void SetZoomY(int part, float zoom);
+ float RetZoomY(int part);
+ void SetZoomZ(int part, float zoom);
+ float RetZoomZ(int part);
+
+ float RetWaterLevel();
+
+ void SetTrainer(bool bEnable);
+ bool RetTrainer();
+
+ void SetToy(bool bEnable);
+ bool RetToy();
+
+ void SetManual(bool bManual);
+ bool RetManual();
+
+ void SetResetCap(ResetCap cap);
+ ResetCap RetResetCap();
+ void SetResetBusy(bool bBusy);
+ bool RetResetBusy();
+ void SetResetPosition(const Math::Vector &pos);
+ Math::Vector RetResetPosition();
+ void SetResetAngle(const Math::Vector &angle);
+ Math::Vector RetResetAngle();
+ void SetResetRun(int run);
+ int RetResetRun();
+
+ void SetMasterParticule(int part, int parti);
+ int RetMasterParticule(int part);
+
+ void SetPower(CObject* power);
+ CObject* RetPower();
+ void SetFret(CObject* fret);
+ CObject* RetFret();
+ void SetTruck(CObject* truck);
+ CObject* RetTruck();
+ void SetTruckPart(int part);
+ int RetTruckPart();
+
+ void InfoFlush();
+ void DeleteInfo(int rank);
+ void SetInfo(int rank, Info info);
+ Info RetInfo(int rank);
+ int RetInfoTotal();
+ void SetInfoReturn(float value);
+ float RetInfoReturn();
+ void SetInfoUpdate(bool bUpdate);
+ bool RetInfoUpdate();
+
+ bool SetCmdLine(int rank, float value);
+ float RetCmdLine(int rank);
+
+ Math::Matrix* RetRotateMatrix(int part);
+ Math::Matrix* RetTranslateMatrix(int part);
+ Math::Matrix* RetTransformMatrix(int part);
+ Math::Matrix* RetWorldMatrix(int part);
+
+ void SetViewFromHere(Math::Vector &eye, float &dirH, float &dirV, Math::Vector &lookat, Math::Vector &upVec, CameraType type);
+
+ void SetCharacter(Character* character);
+ void GetCharacter(Character* character);
+ Character* RetCharacter();
+
+ float RetAbsTime();
+
+ void SetEnergy(float level);
+ float RetEnergy();
+
+ void SetCapacity(float capacity);
+ float RetCapacity();
+
+ void SetShield(float level);
+ float RetShield();
+
+ void SetRange(float delay);
+ float RetRange();
+
+ void SetTransparency(float value);
+ float RetTransparency();
+
+ ObjectMaterial RetMaterial();
+
+ void SetGadget(bool bMode);
+ bool RetGadget();
+
+ void SetFixed(bool bFixed);
+ bool RetFixed();
+
+ void SetClip(bool bClip);
+ bool RetClip();
+
+ bool JostleObject(float force);
+
+ void StartDetectEffect(CObject *target, bool bFound);
+
+ void SetVirusMode(bool bEnable);
+ bool RetVirusMode();
+ float RetVirusTime();
+
+ void SetCameraType(CameraType type);
+ CameraType RetCameraType();
+ void SetCameraDist(float dist);
+ float RetCameraDist();
+ void SetCameraLock(bool bLock);
+ bool RetCameraLock();
+
+ void SetHilite(bool bMode);
+ bool RetHilite();
+
+ void SetSelect(bool bMode, bool bDisplayError=true);
+ bool RetSelect(bool bReal=false);
+
+ void SetSelectable(bool bMode);
+ bool RetSelectable();
+
+ void SetActivity(bool bMode);
+ bool RetActivity();
+
+ void SetVisible(bool bVisible);
+ bool RetVisible();
+
+ void SetEnable(bool bEnable);
+ bool RetEnable();
+
+ void SetCheckToken(bool bMode);
+ bool RetCheckToken();
+
+ void SetProxyActivate(bool bActivate);
+ bool RetProxyActivate();
+ void SetProxyDistance(float distance);
+ float RetProxyDistance();
+
+ void SetMagnifyDamage(float factor);
+ float RetMagnifyDamage();
+
+ void SetParam(float value);
+ float RetParam();
+
+ void SetExplo(bool bExplo);
+ bool RetExplo();
+ void SetLock(bool bLock);
+ bool RetLock();
+ void SetCargo(bool bCargo);
+ bool RetCargo();
+ void SetBurn(bool bBurn);
+ bool RetBurn();
+ void SetDead(bool bDead);
+ bool RetDead();
+ bool RetRuin();
+ bool RetActif();
+
+ void SetGunGoalV(float gunGoal);
+ void SetGunGoalH(float gunGoal);
+ float RetGunGoalV();
+ float RetGunGoalH();
+
+ bool StartShowLimit();
+ void StopShowLimit();
+
+ bool IsProgram();
+ void CreateSelectParticule();
+
+ void SetRunScript(CScript* script);
+ CScript* RetRunScript();
+ CBotVar* RetBotVar();
+ CPhysics* RetPhysics();
+ CBrain* RetBrain();
+ CMotion* RetMotion();
+ CAuto* RetAuto();
+ void SetAuto(CAuto* automat);
+
+ void SetDefRank(int rank);
+ int RetDefRank();
+
+ bool GetTooltipName(char* name);
+
+ void AddDeselList(CObject* pObj);
+ CObject* SubDeselList();
+ void DeleteDeselList(CObject* pObj);
+
+ bool CreateShadowCircle(float radius, float intensity, D3DShadowType type=D3DSHADOWNORM);
+ bool CreateShadowLight(float height, D3DCOLORVALUE color);
+ bool CreateEffectLight(float height, D3DCOLORVALUE color);
+
+ void FlatParent();
+
+ bool RetTraceDown();
+ void SetTraceDown(bool bDown);
+ int RetTraceColor();
+ void SetTraceColor(int color);
+ float RetTraceWidth();
+ void SetTraceWidth(float width);
+
+protected:
+ bool EventFrame(const Event &event);
+ void VirusFrame(float rTime);
+ void PartiFrame(float rTime);
+ void CreateOtherObject(ObjectType type);
+ void InitPart(int part);
+ void UpdateTotalPart();
+ int SearchDescendant(int parent, int n);
+ void UpdateEnergyMapping();
+ bool UpdateTransformObject(int part, bool bForceUpdate);
+ bool UpdateTransformObject();
+ void UpdateSelectParticule();
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CLight* m_light;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CCamera* m_camera;
+ CParticule* m_particule;
+ CPhysics* m_physics;
+ CBrain* m_brain;
+ CMotion* m_motion;
+ CAuto* m_auto;
+ CDisplayText* m_displayText;
+ CRobotMain* m_main;
+ CSound* m_sound;
+ CBotVar* m_botVar;
+ CScript* m_runScript;
+
+ ObjectType m_type; // OBJECT_*
+ int m_id; // unique identifier
+ char m_name[50]; // name of the object
+ Character m_character; // characteristic
+ int m_option; // option
+ int m_partiReactor; // number of the particle of the reactor
+ int m_shadowLight; // number of light from the shadows
+ float m_shadowHeight; // height of light from the shadows
+ int m_effectLight; // number of light effects
+ float m_effectHeight; // height of light effects
+ Math::Vector m_linVibration; // linear vibration
+ Math::Vector m_cirVibration; // circular vibration
+ Math::Vector m_inclinaison; // tilt
+ CObject* m_power; // battery used by the vehicle
+ CObject* m_fret; // object transported
+ CObject* m_truck; // object with the latter
+ int m_truckLink; // part
+ float m_energy; // energy contained (if battery)
+ float m_lastEnergy;
+ float m_capacity; // capacity (if battery)
+ float m_shield; // shield
+ float m_range; // flight range
+ float m_transparency; // transparency (0..1)
+ int m_material; // matter(0..n)
+ float m_aTime;
+ float m_shotTime; // time since last shot
+ bool m_bVirusMode; // virus activated/triggered
+ float m_virusTime; // lifetime of the virus
+ float m_lastVirusParticule;
+ float m_lastParticule;
+ bool m_bHilite;
+ bool m_bSelect; // object selected
+ bool m_bSelectable; // selectable object
+ bool m_bCheckToken; // object with audited tokens
+ bool m_bVisible; // object active but undetectable
+ bool m_bEnable; // dead object
+ bool m_bProxyActivate; // active object so close
+ bool m_bGadget; // object nonessential
+ bool m_bLock;
+ bool m_bExplo;
+ bool m_bCargo;
+ bool m_bBurn;
+ bool m_bDead;
+ bool m_bFlat;
+ bool m_bTrainer; // drive vehicle (without remote)
+ bool m_bToy; // toy key
+ bool m_bManual; // manual control (Scribbler)
+ bool m_bFixed;
+ bool m_bClip;
+ bool m_bShowLimit;
+ float m_showLimitRadius;
+ float m_gunGoalV;
+ float m_gunGoalH;
+ CameraType m_cameraType;
+ float m_cameraDist;
+ bool m_bCameraLock;
+ int m_defRank;
+ float m_magnifyDamage;
+ float m_proxyDistance;
+ float m_param;
+
+ int m_crashSphereUsed; // number of spheres used
+ Math::Vector m_crashSpherePos[MAXCRASHSPHERE];
+ float m_crashSphereRadius[MAXCRASHSPHERE];
+ float m_crashSphereHardness[MAXCRASHSPHERE];
+ Sound m_crashSphereSound[MAXCRASHSPHERE];
+ Math::Vector m_globalSpherePos;
+ float m_globalSphereRadius;
+ Math::Vector m_jotlerSpherePos;
+ float m_jotlerSphereRadius;
+ float m_shieldRadius;
+
+ int m_totalPart;
+ ObjectPart m_objectPart[OBJECTMAXPART];
+
+ int m_totalDesectList;
+ CObject* m_objectDeselectList[OBJECTMAXDESELLIST];
+
+ int m_partiSel[4];
+
+ ResetCap m_resetCap;
+ bool m_bResetBusy;
+ Math::Vector m_resetPosition;
+ Math::Vector m_resetAngle;
+ int m_resetRun;
+
+ int m_infoTotal;
+ Info m_info[OBJECTMAXINFO];
+ float m_infoReturn;
+ bool m_bInfoUpdate;
+
+ float m_cmdLine[OBJECTMAXCMDLINE];
+};
+
diff --git a/src/object/robotmain.cpp b/src/object/robotmain.cpp
index 902c1cb..d519688 100644
--- a/src/object/robotmain.cpp
+++ b/src/object/robotmain.cpp
@@ -1,7032 +1,7032 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// robotmain.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "CBot/CBotDll.h"
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "math/conv.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/language.h"
-#include "common/global.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/profile.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "old/math3d.h"
-#include "old/light.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "old/cloud.h"
-#include "old/blitz.h"
-#include "old/planet.h"
-#include "object/object.h"
-#include "object/motion/motion.h"
-#include "object/motion/motiontoto.h"
-#include "object/motion/motionhuman.h"
-#include "physics/physics.h"
-#include "object/brain.h"
-#include "old/pyro.h"
-#include "old/modfile.h"
-#include "old/model.h"
-#include "old/camera.h"
-#include "object/task/task.h"
-#include "object/task/taskmanip.h"
-#include "object/task/taskbuild.h"
-#include "object/auto/auto.h"
-#include "object/auto/autobase.h"
-#include "ui/displayinfo.h"
-#include "ui/interface.h"
-#include "ui/shortcut.h"
-#include "ui/map.h"
-#include "ui/label.h"
-#include "ui/button.h"
-#include "ui/slider.h"
-#include "ui/window.h"
-#include "ui/edit.h"
-#include "ui/displaytext.h"
-#include "old/text.h"
-#include "old/sound.h"
-#include "script/cbottoken.h"
-#include "script/cmdtoken.h"
-#include "object/mainmovie.h"
-#include "ui/maindialog.h"
-#include "ui/mainshort.h"
-#include "ui/mainmap.h"
-#include "script/script.h"
-#include "object/robotmain.h"
-
-
-
-#define CBOT_STACK true // saves the stack of programs CBOT
-const float UNIT = 4.0f;
-
-
-
-// Global variables.
-
-long g_id; // unique identifier
-long g_build; // constructible buildings
-long g_researchDone; // research done
-long g_researchEnable; // research available
-float g_unit; // conversion factor
-
-
-
-#include "script/ClassFILE.cpp"
-
-
-
-// Compilation of class "point".
-
-CBotTypResult cPoint(CBotVar* pThis, CBotVar* &var)
-{
- if ( !pThis->IsElemOfClass("point") ) return CBotTypResult(CBotErrBadNum);
-
- if ( var == NULL ) return CBotTypResult(0); // ok if no parameter
-
- // First parameter (x):
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- // Second parameter (y):
- if ( var == NULL ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- // Third parameter (z):
- if ( var == NULL ) // only 2 parameters?
- {
- return CBotTypResult(0); // this function returns void
- }
-
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
- if ( var != NULL ) return CBotTypResult(CBotErrOverParam);
-
- return CBotTypResult(0); // this function returns void
-}
-
-//Execution of the class "point".
-
-bool rPoint(CBotVar* pThis, CBotVar* var, CBotVar* pResult, int& Exception)
-{
- CBotVar *pX, *pY, *pZ;
-
- if ( var == NULL ) return true; // constructor with no parameters is ok
-
- if ( var->GivType() > CBotTypDouble )
- {
- Exception = CBotErrBadNum; return false;
- }
-
- pX = pThis->GivItem("x");
- if ( pX == NULL )
- {
- Exception = CBotErrUndefItem; return false;
- }
- pX->SetValFloat( var->GivValFloat() );
- var = var->GivNext();
-
- if ( var == NULL )
- {
- Exception = CBotErrLowParam; return false;
- }
-
- if ( var->GivType() > CBotTypDouble )
- {
- Exception = CBotErrBadNum; return false;
- }
-
- pY = pThis->GivItem("y");
- if ( pY == NULL )
- {
- Exception = CBotErrUndefItem; return false;
- }
- pY->SetValFloat( var->GivValFloat() );
- var = var->GivNext();
-
- if ( var == NULL )
- {
- return true; // ok with only two parameters
- }
-
- pZ = pThis->GivItem("z");
- if ( pZ == NULL )
- {
- Exception = CBotErrUndefItem; return false;
- }
- pZ->SetValFloat( var->GivValFloat() );
- var = var->GivNext();
-
- if ( var != NULL )
- {
- Exception = CBotErrOverParam; return false;
- }
-
- return true; // no interruption
-}
-
-
-
-
-// Constructor of robot application.
-
-CRobotMain::CRobotMain(CInstanceManager* iMan)
-{
- ObjectType type;
- float fValue;
- int iValue, i;
- char* token;
-
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_MAIN, this);
-
- m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
- m_cloud = (CCloud*)m_iMan->SearchInstance(CLASS_CLOUD);
- m_blitz = (CBlitz*)m_iMan->SearchInstance(CLASS_BLITZ);
- m_planet = (CPlanet*)m_iMan->SearchInstance(CLASS_PLANET);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
-
- m_interface = new CInterface(m_iMan);
- m_terrain = new CTerrain(m_iMan);
- m_model = new CModel(m_iMan);
- m_camera = new CCamera(m_iMan);
- m_displayText = new CDisplayText(m_iMan);
- m_movie = new CMainMovie(m_iMan);
- m_dialog = new CMainDialog(m_iMan);
- m_short = new CMainShort(m_iMan);
- m_map = new CMainMap(m_iMan);
- m_displayInfo = 0;
-
- m_engine->SetTerrain(m_terrain);
- m_filesDir = m_dialog->RetFilesDir();
-
- m_time = 0.0f;
- m_gameTime = 0.0f;
- m_checkEndTime = 0.0f;
-
- m_phase = PHASE_NAME;
- m_cameraRank = -1;
- m_visitLast = EVENT_NULL;
- m_visitObject = 0;
- m_visitArrow = 0;
- m_audioTrack = 0;
- m_bAudioRepeat = true;
- m_delayWriteMessage = 0;
- m_selectObject = 0;
- m_infoUsed = 0;
-
- m_bBeginSatCom = false;
- m_bMovieLock = false;
- m_bSatComLock = false;
- m_bEditLock = false;
- m_bEditFull = false;
- m_bPause = false;
- m_bHilite = false;
- m_bFreePhoto = false;
- m_bShowPos = false;
- m_bSelectInsect = false;
- m_bShowSoluce = false;
- m_bShowAll = false;
- m_bCheatRadar = false;
- m_bFixScene = false;
- m_bTrainerPilot = false;
- m_bSuspend = false;
- m_bFriendAim = false;
- m_bResetCreate = false;
- m_bShortCut = true;
-
- m_engine->SetMovieLock(m_bMovieLock);
-
- m_movie->Flush();
- m_movieInfoIndex = -1;
-
- m_tooltipPos = Math::Point(0.0f, 0.0f);
- m_tooltipName[0] = 0;
- m_tooltipTime = 0.0f;
-
- m_endingWinRank = 0;
- m_endingLostRank = 0;
- m_bWinTerminate = false;
-
- FlushDisplayInfo();
-
- m_fontSize = 9.0f;
- m_windowPos = Math::Point(0.15f, 0.17f);
- m_windowDim = Math::Point(0.70f, 0.66f);
-
- if ( GetProfileFloat("Edit", "FontSize", fValue) ) m_fontSize = fValue;
- if ( GetProfileFloat("Edit", "WindowPos.x", fValue) ) m_windowPos.x = fValue;
- if ( GetProfileFloat("Edit", "WindowPos.y", fValue) ) m_windowPos.y = fValue;
- if ( GetProfileFloat("Edit", "WindowDim.x", fValue) ) m_windowDim.x = fValue;
- if ( GetProfileFloat("Edit", "WindowDim.y", fValue) ) m_windowDim.y = fValue;
-
- m_IOPublic = false;
- m_IODim = Math::Point(320.0f/640.0f, (121.0f+18.0f*8)/480.0f);
- m_IOPos.x = (1.0f-m_IODim.x)/2.0f; // in the middle
- m_IOPos.y = (1.0f-m_IODim.y)/2.0f;
-
- if ( GetProfileInt ("Edit", "IOPublic", iValue) ) m_IOPublic = iValue;
- if ( GetProfileFloat("Edit", "IOPos.x", fValue) ) m_IOPos.x = fValue;
- if ( GetProfileFloat("Edit", "IOPos.y", fValue) ) m_IOPos.y = fValue;
- if ( GetProfileFloat("Edit", "IODim.x", fValue) ) m_IODim.x = fValue;
- if ( GetProfileFloat("Edit", "IODim.y", fValue) ) m_IODim.y = fValue;
-
- m_short->FlushShortcuts();
- InitEye();
-
- m_engine->SetTracePrecision(1.0f);
-
- m_cameraPan = 0.0f;
- m_cameraZoom = 0.0f;
-
- g_id = 0;
- g_build = 0;
- g_researchDone = 0; // no research done
- g_researchEnable = 0;
- g_unit = 4.0f;
-
- m_gamerName[0] = 0;
- GetProfileString("Gamer", "LastName", m_gamerName, 100);
- SetGlobalGamerName(m_gamerName);
- ReadFreeParam();
- m_dialog->SetupRecall();
-
- for ( i=0 ; i<MAXSHOWLIMIT ; i++ )
- {
- m_showLimit[i].bUsed = false;
- m_showLimit[i].total = 0;
- m_showLimit[i].link = 0;
- }
-
- CBotProgram::SetTimer(100);
- CBotProgram::Init();
-
- for ( i=0 ; i<OBJECT_MAX ; i++ )
- {
- type = (ObjectType)i;
- token = RetObjectName(type);
- if ( token[0] != 0 )
- {
- CBotProgram::DefineNum(token, type);
- }
- token = RetObjectAlias(type);
- if ( token[0] != 0 )
- {
- CBotProgram::DefineNum(token, type);
- }
- }
-
- CBotProgram::DefineNum("White", 0);
- CBotProgram::DefineNum("Black", 1);
- CBotProgram::DefineNum("Gray", 2);
- CBotProgram::DefineNum("LightGray", 3);
- CBotProgram::DefineNum("Red", 4);
- CBotProgram::DefineNum("Pink", 5);
- CBotProgram::DefineNum("Purple", 6);
- CBotProgram::DefineNum("Orange", 7);
- CBotProgram::DefineNum("Yellow", 8);
- CBotProgram::DefineNum("Beige", 9);
- CBotProgram::DefineNum("Brown", 10);
- CBotProgram::DefineNum("Skin", 11);
- CBotProgram::DefineNum("Green", 12);
- CBotProgram::DefineNum("LightGreen", 13);
- CBotProgram::DefineNum("Blue", 14);
- CBotProgram::DefineNum("LightBlue", 15);
- CBotProgram::DefineNum("BlackArrow", 16);
- CBotProgram::DefineNum("RedArrow", 17);
-
- CBotProgram::DefineNum("Metal", OM_METAL);
- CBotProgram::DefineNum("Plastic", OM_PLASTIC);
-
- CBotProgram::DefineNum("InFront", TMA_FFRONT);
- CBotProgram::DefineNum("Behind", TMA_FBACK);
- CBotProgram::DefineNum("EnergyCell", TMA_POWER);
-
- CBotProgram::DefineNum("DisplayError", TT_ERROR);
- CBotProgram::DefineNum("DisplayWarning", TT_WARNING);
- CBotProgram::DefineNum("DisplayInfo", TT_INFO);
- CBotProgram::DefineNum("DisplayMessage", TT_MESSAGE);
-
- CBotProgram::DefineNum("FilterNone", FILTER_NONE);
- CBotProgram::DefineNum("FilterOnlyLanding", FILTER_ONLYLANDING);
- CBotProgram::DefineNum("FilterOnlyFliying", FILTER_ONLYFLYING);
-
- // Add the class Point.
- CBotClass* bc;
- bc = new CBotClass("point", NULL, true); // intrinsic class
- bc->AddItem("x", CBotTypFloat);
- bc->AddItem("y", CBotTypFloat);
- bc->AddItem("z", CBotTypFloat);
- bc->AddFunction("point", rPoint, cPoint);
-
- // Adds the class Object.
- bc = new CBotClass("object", NULL);
- bc->AddItem("category", CBotTypResult(CBotTypInt), PR_READ);
- bc->AddItem("position", CBotTypResult(CBotTypClass, "point"), PR_READ);
- bc->AddItem("orientation", CBotTypResult(CBotTypFloat), PR_READ);
- bc->AddItem("pitch", CBotTypResult(CBotTypFloat), PR_READ);
- bc->AddItem("roll", CBotTypResult(CBotTypFloat), PR_READ);
- bc->AddItem("energyLevel", CBotTypResult(CBotTypFloat), PR_READ);
- bc->AddItem("shieldLevel", CBotTypResult(CBotTypFloat), PR_READ);
- bc->AddItem("temperature", CBotTypResult(CBotTypFloat), PR_READ);
- bc->AddItem("altitude", CBotTypResult(CBotTypFloat), PR_READ);
- bc->AddItem("lifeTime", CBotTypResult(CBotTypFloat), PR_READ);
- bc->AddItem("material", CBotTypResult(CBotTypInt), PR_READ);
- bc->AddItem("energyCell", CBotTypResult(CBotTypPointer, "object"), PR_READ);
- bc->AddItem("load", CBotTypResult(CBotTypPointer, "object"), PR_READ);
-
- // Initializes the class FILE.
- InitClassFILE();
-
- CScript::InitFonctions();
-}
-
-// Destructor of robot application.
-
-CRobotMain::~CRobotMain()
-{
- delete m_movie;
- delete m_dialog;
- delete m_short;
- delete m_map;
- delete m_terrain;
- delete m_model;
-}
-
-
-// Creates the file colobot.ini at the first time.
-
-void CRobotMain::CreateIni()
-{
- int iValue;
-
- // colobot.ini don't exist?
- if ( !GetProfileInt("Setup", "TotoMode", iValue) )
- {
- m_dialog->SetupMemorize();
- }
-}
-
-
-// Changes phase.
-
-void CRobotMain::ChangePhase(Phase phase)
-{
- CEdit* pe;
- CButton* pb;
- D3DCOLORVALUE color;
- Math::Point pos, dim, ddim;
- float ox, oy, sx, sy;
- char* read;
- int rank, numTry;
- bool bLoading;
-
- if ( m_phase == PHASE_SIMUL ) // ends a simulation?
- {
- SaveAllScript();
- m_sound->StopMusic();
- m_camera->SetObject(0);
-
-#if _SCHOOL
- if ( true )
-#else
- if ( m_gameTime > 10.0f ) // did you play at least 10 seconds?
-#endif
- {
- rank = m_dialog->RetSceneRank();
- numTry = m_dialog->RetGamerInfoTry(rank);
- m_dialog->SetGamerInfoTry(rank, numTry+1);
- m_dialog->WriteGamerInfo();
- }
- }
-
- if ( phase == PHASE_WIN ) // wins a simulation?
- {
- rank = m_dialog->RetSceneRank();
- m_dialog->SetGamerInfoPassed(rank, true);
- m_dialog->NextMission(); // passes to the next mission
- m_dialog->WriteGamerInfo();
- }
-
- DeleteAllObjects(); // removes all the current 3D Scene
-
- m_phase = phase;
- m_winDelay = 0.0f;
- m_lostDelay = 0.0f;
- m_bBeginSatCom = false;
- m_bMovieLock = false;
- m_bSatComLock = false;
- m_bEditLock = false;
- m_bFreePhoto = false;
- m_bResetCreate = false;
-
- m_engine->SetMovieLock(m_bMovieLock);
- ChangePause(false);
- FlushDisplayInfo();
- m_engine->SetRankView(0);
- m_engine->FlushObject();
- color.r = color.g = color.b = color.a = 0.0f;
- m_engine->SetWaterAddColor(color);
- m_engine->SetBackground("");
- m_engine->SetBackForce(false);
- m_engine->SetFrontsizeName("");
- m_engine->SetOverColor();
- m_engine->GroundMarkDelete(0);
- SetSpeed(1.0f);
- m_terrain->SetWind(Math::Vector(0.0f, 0.0f, 0.0f));
- m_terrain->FlushBuildingLevel();
- m_terrain->FlushFlyingLimit();
- m_light->FlushLight();
- m_particule->FlushParticule();
- m_water->Flush();
- m_cloud->Flush();
- m_blitz->Flush();
- m_planet->Flush();
- m_iMan->Flush(CLASS_OBJECT);
- m_iMan->Flush(CLASS_PHYSICS);
- m_iMan->Flush(CLASS_BRAIN);
- m_iMan->Flush(CLASS_PYRO);
- m_model->StopUserAction();
- m_interface->Flush();
- ClearInterface();
- FlushNewScriptName();
- m_sound->SetListener(Math::Vector(0.0f, 0.0f, 0.0f), Math::Vector(0.0f, 0.0f, 1.0f));
- m_camera->SetType(CAMERA_DIALOG);
- m_movie->Flush();
- m_movieInfoIndex = -1;
- m_cameraPan = 0.0f;
- m_cameraZoom = 0.0f;
- m_bShortCut = true;
-
- // Creates and hide the command console.
- dim.x = 200.0f/640.0f;
- dim.y = 18.0f/480.0f;
- pos.x = 50.0f/640.0f;
- pos.y = 452.0f/480.0f;
- pe = m_interface->CreateEdit(pos, dim, 0, EVENT_CMD);
- if ( pe == 0 ) return;
- pe->ClearState(STATE_VISIBLE);
- m_bCmdEdit = false; // hidden for now
-
- // Creates the speedometer.
-#if _TEEN
- dim.x = 30.0f/640.0f;
- dim.y = 20.0f/480.0f;
- pos.x = 4.0f/640.0f;
- pos.y = 454.0f/480.0f;
-#else
- dim.x = 30.0f/640.0f;
- dim.y = 20.0f/480.0f;
- pos.x = 4.0f/640.0f;
- pos.y = 426.0f/480.0f;
-#endif
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_SPEED);
- if ( pb == 0 ) return;
- pb->SetState(STATE_SIMPLY);
- pb->ClearState(STATE_VISIBLE);
-
- m_dialog->ChangePhase(m_phase);
-
- dim.x = 32.0f/640.0f;
- dim.y = 32.0f/480.0f;
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = (32.0f+2.0f)/640.0f;
- sy = (32.0f+2.0f)/480.0f;
-
- if ( m_phase != PHASE_PERSO )
- {
- m_engine->SetDrawWorld(true);
- m_engine->SetDrawFront(false);
- m_bFixScene = false;
- }
-
- if ( m_phase == PHASE_INIT )
- {
-#if _NEWLOOK
- m_engine->FreeTexture("generna.tga");
- m_engine->FreeTexture("genernb.tga");
- m_engine->FreeTexture("genernc.tga");
- m_engine->FreeTexture("genernd.tga");
-#else
-#if _FRENCH
-#if _DEMO
- m_engine->FreeTexture("genedfa.tga");
- m_engine->FreeTexture("genedfb.tga");
- m_engine->FreeTexture("genedfc.tga");
- m_engine->FreeTexture("genedfd.tga");
-#else
- m_engine->FreeTexture("generfa.tga");
- m_engine->FreeTexture("generfb.tga");
- m_engine->FreeTexture("generfc.tga");
- m_engine->FreeTexture("generfd.tga");
-#endif
-#endif
-#if _ENGLISH
-#if _DEMO
- m_engine->FreeTexture("genedea.tga");
- m_engine->FreeTexture("genedeb.tga");
- m_engine->FreeTexture("genedec.tga");
- m_engine->FreeTexture("geneded.tga");
-#else
- m_engine->FreeTexture("generea.tga");
- m_engine->FreeTexture("genereb.tga");
- m_engine->FreeTexture("generec.tga");
- m_engine->FreeTexture("genered.tga");
-#endif
-#endif
-#if _GERMAN
-#if _DEMO
- m_engine->FreeTexture("genedda.tga");
- m_engine->FreeTexture("geneddb.tga");
- m_engine->FreeTexture("geneddc.tga");
- m_engine->FreeTexture("geneddd.tga");
-#else
- m_engine->FreeTexture("generea.tga");
- m_engine->FreeTexture("genereb.tga");
- m_engine->FreeTexture("generec.tga");
- m_engine->FreeTexture("genered.tga");
-#endif
-#endif
-#if _WG
-#if _DEMO
- m_engine->FreeTexture("genedda.tga");
- m_engine->FreeTexture("geneddb.tga");
- m_engine->FreeTexture("geneddc.tga");
- m_engine->FreeTexture("geneddd.tga");
-#else
- m_engine->FreeTexture("generda.tga");
- m_engine->FreeTexture("generdb.tga");
- m_engine->FreeTexture("generdc.tga");
- m_engine->FreeTexture("generdd.tga");
-#endif
-#endif
-#if _POLISH
-#if _DEMO
- m_engine->FreeTexture("genedpa.tga");
- m_engine->FreeTexture("genedpb.tga");
- m_engine->FreeTexture("genedpc.tga");
- m_engine->FreeTexture("genedpd.tga");
-#else
- m_engine->FreeTexture("generpa.tga");
- m_engine->FreeTexture("generpb.tga");
- m_engine->FreeTexture("generpc.tga");
- m_engine->FreeTexture("generpd.tga");
-#endif
-#endif
-#endif
- }
-
- if ( m_phase == PHASE_SIMUL )
- {
- m_engine->FreeTexture("inter01a.tga");
- m_engine->FreeTexture("inter01b.tga");
- m_engine->FreeTexture("inter01c.tga");
- m_engine->FreeTexture("inter01d.tga");
-
- read = m_dialog->RetSceneRead();
- bLoading = (read[0] != 0);
-
- m_map->CreateMap();
- CreateScene(m_dialog->RetSceneSoluce(), false, false); // interactive scene
- if ( m_bMapImage )
- {
- m_map->SetFixImage(m_mapFilename);
- }
-
- pos.x = 620.0f/640.0f;
- pos.y = 460.0f/480.0f;
- ddim.x = 20.0f/640.0f;
- ddim.y = 20.0f/480.0f;
- m_interface->CreateButton(pos, ddim, 11, EVENT_BUTTON_QUIT);
-
- if ( m_bImmediatSatCom && !bLoading &&
- m_infoFilename[SATCOM_HUSTON][0] != 0 )
- {
- StartDisplayInfo(SATCOM_HUSTON, false); // shows the instructions
- }
-
- m_sound->StopMusic();
- if ( !m_bBase || bLoading ) StartMusic();
- }
-
- if ( m_phase == PHASE_WIN )
- {
- if ( m_endingWinRank == -1 )
- {
- ChangePhase(PHASE_TERM);
- }
- else
- {
-#if _TEEN
- m_bWinTerminate = (m_endingWinRank == 900);
- m_dialog->SetSceneName("teenw");
-#else
- m_bWinTerminate = (m_endingWinRank == 904);
- m_dialog->SetSceneName("win");
-#endif
- m_dialog->SetSceneRank(m_endingWinRank);
- CreateScene(false, true, false); // sets scene
-
- pos.x = ox+sx*1; pos.y = oy+sy*1;
- ddim.x = dim.x*2; ddim.y = dim.y*2;
- m_interface->CreateButton(pos, ddim, 16, EVENT_BUTTON_OK);
-
- if ( m_bWinTerminate )
- {
-#if _TEEN
- pos.x = ox+sx*3; pos.y = oy+sy*1;
- ddim.x = dim.x*15; ddim.y = dim.y*2;
- pe = m_interface->CreateEdit(pos, ddim, 0, EVENT_EDIT0);
- pe->SetFontType(FONT_COLOBOT);
- pe->SetEditCap(false);
- pe->SetHiliteCap(false);
- pe->ReadText("help\\teenw.txt");
-#else
- pos.x = ox+sx*3; pos.y = oy+sy*0.2f;
- ddim.x = dim.x*15; ddim.y = dim.y*3.0f;
- pe = m_interface->CreateEdit(pos, ddim, 0, EVENT_EDIT0);
- pe->SetGenericMode(true);
- pe->SetFontType(FONT_COLOBOT);
- pe->SetEditCap(false);
- pe->SetHiliteCap(false);
- pe->ReadText("help\\win.txt");
-#endif
- }
- else
- {
- m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f), 15.0f, 60.0f, 1000.0f);
- }
- }
- m_sound->StopAll();
- StartMusic();
- }
-
- if ( m_phase == PHASE_LOST )
- {
- if ( m_endingLostRank == -1 )
- {
- ChangePhase(PHASE_TERM);
- }
- else
- {
- m_bWinTerminate = false;
- m_dialog->SetSceneName("lost");
- m_dialog->SetSceneRank(m_endingLostRank);
- CreateScene(false, true, false); // sets scene
-
- pos.x = ox+sx*1; pos.y = oy+sy*1;
- ddim.x = dim.x*2; ddim.y = dim.y*2;
- m_interface->CreateButton(pos, ddim, 16, EVENT_BUTTON_OK);
- m_displayText->DisplayError(INFO_LOST, Math::Vector(0.0f,0.0f,0.0f), 15.0f, 60.0f, 1000.0f);
- }
- m_sound->StopAll();
- StartMusic();
- }
-
- if ( m_phase == PHASE_MODEL )
- {
- pos.x = ox+sx*0; pos.y = oy+sy*0;
- m_interface->CreateButton(pos, dim, 11, EVENT_BUTTON_CANCEL);
-
- CreateModel();
- }
-
- if ( m_phase == PHASE_LOADING )
- {
- m_engine->SetMouseHide(true);
- }
- else
- {
- m_engine->SetMouseHide(false);
- }
-
- m_engine->LoadAllTexture();
-}
-
-
-// Processes an event.
-
-bool CRobotMain::EventProcess(const Event &event)
-{
- CEdit* pe;
- CObject* pObj;
- Event newEvent;
- MainMovieType type;
- int i;
-
- if ( event.event == EVENT_FRAME )
- {
- if ( !m_movie->EventProcess(event) ) // end of the movie?
- {
- type = m_movie->RetStopType();
- if ( type == MM_SATCOMopen )
- {
- ChangePause(false);
- SelectObject(m_infoObject, false); // hands over the command buttons
- m_map->ShowMap(m_bMapShow);
- m_displayText->HideText(false);
- i = m_movieInfoIndex;
- StartDisplayInfo(m_movieInfoIndex, false);
- m_movieInfoIndex = i;
- }
- }
-
- m_dialog->EventProcess(event);
- m_displayText->EventProcess(event);
- RemoteCamera(m_cameraPan, m_cameraZoom, event.rTime);
-
- m_interface->EventProcess(event);
- if ( m_displayInfo != 0 ) // current edition?
- {
- m_displayInfo->EventProcess(event);
- }
- return EventFrame(event);
- }
-
- // Management of the console.
-#if 0
- if ( m_phase != PHASE_NAME &&
- !m_movie->IsExist() &&
- event.event == EVENT_KEYDOWN &&
- event.param == VK_PAUSE &&
- (event.keyState&KS_CONTROL) != 0 )
-#else
- if ( m_phase != PHASE_NAME &&
- !m_movie->IsExist() &&
- event.event == EVENT_KEYDOWN &&
- event.param == VK_CANCEL ) // Ctrl+Pause ?
-#endif
- {
- pe = (CEdit*)m_interface->SearchControl(EVENT_CMD);
- if ( pe == 0 ) return false;
- pe->SetState(STATE_VISIBLE);
- pe->SetFocus(true);
- if ( m_phase == PHASE_SIMUL ) ChangePause(true);
- m_bCmdEdit = true;
- return false;
- }
- if ( event.event == EVENT_KEYDOWN &&
- event.param == VK_RETURN && m_bCmdEdit )
- {
- char cmd[50];
- pe = (CEdit*)m_interface->SearchControl(EVENT_CMD);
- if ( pe == 0 ) return false;
- pe->GetText(cmd, 50);
- pe->SetText("");
- pe->ClearState(STATE_VISIBLE);
- if ( m_phase == PHASE_SIMUL ) ChangePause(false);
- ExecuteCmd(cmd);
- m_bCmdEdit = false;
- return false;
- }
-
- // Management of the speed change.
- if ( event.event == EVENT_SPEED )
- {
- SetSpeed(1.0f);
- }
-
- if ( !m_dialog->EventProcess(event) )
- {
- if ( event.event == EVENT_MOUSEMOVE )
- {
- m_lastMousePos = event.pos;
- HiliteObject(event.pos);
- }
- return false;
- }
-
- if ( !m_displayText->EventProcess(event) )
- {
- return false;
- }
-
- if ( event.event == EVENT_MOUSEMOVE )
- {
- m_lastMousePos = event.pos;
- HiliteObject(event.pos);
- }
-
- if ( m_displayInfo != 0 ) // current info?
- {
- m_displayInfo->EventProcess(event);
-
- if ( event.event == EVENT_KEYDOWN )
- {
- if ( event.param == m_engine->RetKey(KEYRANK_HELP, 0) ||
- event.param == m_engine->RetKey(KEYRANK_HELP, 1) ||
- event.param == m_engine->RetKey(KEYRANK_PROG, 0) ||
- event.param == m_engine->RetKey(KEYRANK_PROG, 1) ||
- event.param == VK_ESCAPE )
- {
- StopDisplayInfo();
- }
- }
- if ( event.event == EVENT_OBJECT_INFOOK )
- {
- StopDisplayInfo();
- }
- return false;
- }
-
- // Simulation phase of the game
- if ( m_phase == PHASE_SIMUL )
- {
- UpdateInfoText();
-
- if ( !m_bEditFull )
- {
- m_camera->EventProcess(event);
- }
-
- switch( event.event )
- {
- case EVENT_KEYDOWN:
- KeyCamera(event.event, event.param);
- HiliteClear();
- if ( event.param == VK_F11 )
- {
- m_particule->WriteWheelTrace("Savegame\\t.bmp", 256, 256, Math::Vector(16.0f, 0.0f, -368.0f), Math::Vector(140.0f, 0.0f, -248.0f));
- return false;
- }
- if ( m_bEditLock ) // current edition?
- {
- if ( event.param == m_engine->RetKey(KEYRANK_HELP, 0) ||
- event.param == m_engine->RetKey(KEYRANK_HELP, 1) )
- {
- StartDisplayInfo(SATCOM_HUSTON, false);
- return false;
- }
- if ( event.param == m_engine->RetKey(KEYRANK_PROG, 0) ||
- event.param == m_engine->RetKey(KEYRANK_PROG, 1) )
- {
- StartDisplayInfo(SATCOM_PROG, false);
- return false;
- }
- break;
- }
- if ( m_bMovieLock ) // current movie?
- {
- if ( event.param == m_engine->RetKey(KEYRANK_QUIT, 0) ||
- event.param == m_engine->RetKey(KEYRANK_QUIT, 1) ||
- event.param == VK_ESCAPE )
- {
- AbortMovie();
- }
- return false;
- }
- if ( m_camera->RetType() == CAMERA_VISIT )
- {
- if ( event.param == m_engine->RetKey(KEYRANK_VISIT, 0) ||
- event.param == m_engine->RetKey(KEYRANK_VISIT, 1) )
- {
- StartDisplayVisit(EVENT_NULL);
- }
- if ( event.param == m_engine->RetKey(KEYRANK_QUIT, 0) ||
- event.param == m_engine->RetKey(KEYRANK_QUIT, 1) ||
- event.param == VK_ESCAPE )
- {
- StopDisplayVisit();
- }
- return false;
- }
- if ( event.param == m_engine->RetKey(KEYRANK_QUIT, 0) ||
- event.param == m_engine->RetKey(KEYRANK_QUIT, 1) )
- {
- if ( m_movie->IsExist() )
- {
- StartDisplayInfo(SATCOM_HUSTON, false);
- }
- else if ( m_winDelay > 0.0f )
- {
- ChangePhase(PHASE_WIN);
- }
- else if ( m_lostDelay > 0.0f )
- {
- ChangePhase(PHASE_LOST);
- }
- else
- {
- m_dialog->StartAbort(); // do you want to leave?
- }
- }
- if ( event.param == VK_PAUSE )
- {
- if ( !m_bMovieLock && !m_bEditLock && !m_bCmdEdit &&
- m_camera->RetType() != CAMERA_VISIT &&
- !m_movie->IsExist() )
- {
- ChangePause(!m_engine->RetPause());
- }
- }
- if ( event.param == m_engine->RetKey(KEYRANK_CAMERA, 0) ||
- event.param == m_engine->RetKey(KEYRANK_CAMERA, 1) )
- {
- ChangeCamera();
- }
- if ( event.param == m_engine->RetKey(KEYRANK_DESEL, 0) ||
- event.param == m_engine->RetKey(KEYRANK_DESEL, 1) )
- {
- if ( m_bShortCut )
- {
- DeselectObject();
- }
- }
- if ( event.param == m_engine->RetKey(KEYRANK_HUMAN, 0) ||
- event.param == m_engine->RetKey(KEYRANK_HUMAN, 1) )
- {
- SelectHuman();
- }
- if ( event.param == m_engine->RetKey(KEYRANK_NEXT, 0) ||
- event.param == m_engine->RetKey(KEYRANK_NEXT, 1) )
- {
- if ( m_bShortCut )
- {
- m_short->SelectNext();
- }
- }
- if ( event.param == m_engine->RetKey(KEYRANK_HELP, 0) ||
- event.param == m_engine->RetKey(KEYRANK_HELP, 1) )
- {
- StartDisplayInfo(SATCOM_HUSTON, true);
- }
- if ( event.param == m_engine->RetKey(KEYRANK_PROG, 0) ||
- event.param == m_engine->RetKey(KEYRANK_PROG, 1) )
- {
- StartDisplayInfo(SATCOM_PROG, true);
- }
- if ( event.param == m_engine->RetKey(KEYRANK_VISIT, 0) ||
- event.param == m_engine->RetKey(KEYRANK_VISIT, 1) )
- {
- StartDisplayVisit(EVENT_NULL);
- }
- if ( event.param == m_engine->RetKey(KEYRANK_SPEED10, 0) ||
- event.param == m_engine->RetKey(KEYRANK_SPEED10, 1) )
- {
- SetSpeed(1.0f);
- }
- if ( event.param == m_engine->RetKey(KEYRANK_SPEED15, 0) ||
- event.param == m_engine->RetKey(KEYRANK_SPEED15, 1) )
- {
- SetSpeed(1.5f);
- }
- if ( event.param == m_engine->RetKey(KEYRANK_SPEED20, 0) ||
- event.param == m_engine->RetKey(KEYRANK_SPEED20, 1) )
- {
- SetSpeed(2.0f);
- }
- if ( event.param == m_engine->RetKey(KEYRANK_SPEED30, 0) ||
- event.param == m_engine->RetKey(KEYRANK_SPEED30, 1) )
- {
- SetSpeed(3.0f);
- }
- break;
-
- case EVENT_KEYUP:
- KeyCamera(event.event, event.param);
- break;
-
- case EVENT_LBUTTONDOWN:
- pObj = DetectObject(event.pos);
- if ( !m_bShortCut ) pObj = 0;
- if ( pObj != 0 && pObj->RetType() == OBJECT_TOTO )
- {
- if ( m_displayInfo != 0 ) // current info?
- {
- StopDisplayInfo();
- }
- else
- {
- if ( !m_bEditLock )
- {
- StartDisplayInfo(SATCOM_HUSTON, true);
- }
- }
- }
- else
- {
- SelectObject(pObj);
- }
- break;
-
- case EVENT_LBUTTONUP:
- m_cameraPan = 0.0f;
- m_cameraZoom = 0.0f;
- break;
-
- case EVENT_BUTTON_QUIT:
- if ( m_movie->IsExist() )
- {
- StartDisplayInfo(SATCOM_HUSTON, false);
- }
- else if ( m_winDelay > 0.0f )
- {
- ChangePhase(PHASE_WIN);
- }
- else if ( m_lostDelay > 0.0f )
- {
- ChangePhase(PHASE_LOST);
- }
- else
- {
- m_dialog->StartAbort(); // do you want to leave?
- }
- break;
-
- case EVENT_OBJECT_LIMIT:
- StartShowLimit();
- break;
-
- case EVENT_OBJECT_DESELECT:
- if ( m_bShortCut )
- {
- DeselectObject();
- }
- break;
-
- case EVENT_OBJECT_HELP:
- HelpObject();
- break;
-
- case EVENT_OBJECT_CAMERA:
- ChangeCamera();
- break;
-
- case EVENT_OBJECT_CAMERAleft:
- m_cameraPan = -1.0f;
- break;
- case EVENT_OBJECT_CAMERAright:
- m_cameraPan = 1.0f;
- break;
- case EVENT_OBJECT_CAMERAnear:
- m_cameraZoom = -1.0f;
- break;
- case EVENT_OBJECT_CAMERAaway:
- m_cameraZoom = 1.0f;
- break;
-
- case EVENT_OBJECT_DELETE:
- m_dialog->StartDeleteObject(); // do you want to destroy it?
- break;
-
- case EVENT_OBJECT_BHELP:
- StartDisplayInfo(SATCOM_HUSTON, true);
- break;
-
- case EVENT_OBJECT_SOLUCE:
- StartDisplayInfo(SATCOM_SOLUCE, true);
- break;
-
- case EVENT_OBJECT_MAPZOOM:
- m_map->ZoomMap();
- break;
-
- case EVENT_DT_VISIT0:
- case EVENT_DT_VISIT1:
- case EVENT_DT_VISIT2:
- case EVENT_DT_VISIT3:
- case EVENT_DT_VISIT4:
- StartDisplayVisit(event.event);
- break;
-
- case EVENT_DT_END:
- StopDisplayVisit();
- break;
-
- case EVENT_OBJECT_SHORTCUT00:
- case EVENT_OBJECT_SHORTCUT01:
- case EVENT_OBJECT_SHORTCUT02:
- case EVENT_OBJECT_SHORTCUT03:
- case EVENT_OBJECT_SHORTCUT04:
- case EVENT_OBJECT_SHORTCUT05:
- case EVENT_OBJECT_SHORTCUT06:
- case EVENT_OBJECT_SHORTCUT07:
- case EVENT_OBJECT_SHORTCUT08:
- case EVENT_OBJECT_SHORTCUT09:
- case EVENT_OBJECT_SHORTCUT10:
- case EVENT_OBJECT_SHORTCUT11:
- case EVENT_OBJECT_SHORTCUT12:
- case EVENT_OBJECT_SHORTCUT13:
- case EVENT_OBJECT_SHORTCUT14:
- case EVENT_OBJECT_SHORTCUT15:
- case EVENT_OBJECT_SHORTCUT16:
- case EVENT_OBJECT_SHORTCUT17:
- case EVENT_OBJECT_SHORTCUT18:
- case EVENT_OBJECT_SHORTCUT19:
- m_short->SelectShortcut(event.event);
- break;
-
- case EVENT_OBJECT_MOVIELOCK:
- AbortMovie();
- break;
-
- case EVENT_WIN:
- ChangePhase(PHASE_WIN);
- break;
-
- case EVENT_LOST:
- ChangePhase(PHASE_LOST);
- break;
- }
-
- EventObject(event);
- return false;
- }
-
- if ( m_phase == PHASE_PERSO )
- {
- EventObject(event);
- }
-
- if ( m_phase == PHASE_WIN ||
- m_phase == PHASE_LOST )
- {
- EventObject(event);
-
- switch( event.event )
- {
- case EVENT_KEYDOWN:
- if ( event.param == VK_ESCAPE ||
- event.param == VK_RETURN )
- {
- if ( m_bWinTerminate )
- {
- ChangePhase(PHASE_INIT);
- }
- else
- {
- ChangePhase(PHASE_TERM);
- }
- }
- break;
-
- case EVENT_BUTTON_OK:
- if ( m_bWinTerminate )
- {
- ChangePhase(PHASE_INIT);
- }
- else
- {
- ChangePhase(PHASE_TERM);
- }
- break;
- }
- }
-
- if ( m_phase == PHASE_MODEL )
- {
- switch( event.event )
- {
- case EVENT_KEYDOWN:
- if ( event.param == VK_ESCAPE )
- {
- ChangePhase(PHASE_INIT);
- }
- if ( event.param == VK_HOME )
- {
- InitEye();
- }
- break;
-
- case EVENT_BUTTON_CANCEL:
- ChangePhase(PHASE_INIT);
- break;
- }
-
- m_model->EventProcess(event);
- return false;
- }
-
- return true;
-}
-
-
-
-// Executes a command.
-
-void CRobotMain::ExecuteCmd(char *cmd)
-{
- if ( cmd[0] == 0 ) return;
-
- if ( m_phase == PHASE_SIMUL )
- {
- if ( strcmp(cmd, "winmission") == 0 )
- {
- Event newEvent;
- m_event->MakeEvent(newEvent, EVENT_WIN);
- m_event->AddEvent(newEvent);
- }
-
- if ( strcmp(cmd, "lostmission") == 0 )
- {
- Event newEvent;
- m_event->MakeEvent(newEvent, EVENT_LOST);
- m_event->AddEvent(newEvent);
- }
-
- if ( strcmp(cmd, "trainerpilot") == 0 )
- {
- m_bTrainerPilot = !m_bTrainerPilot;
- return;
- }
-
- if ( strcmp(cmd, "fly") == 0 )
- {
- Event newEvent;
-
- g_researchDone |= RESEARCH_FLY;
-
- m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
- m_event->AddEvent(newEvent);
- return;
- }
-
- if ( strcmp(cmd, "allresearch") == 0 )
- {
- Event newEvent;
-
- g_researchDone = -1; // all research are done
-
- m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
- m_event->AddEvent(newEvent);
- return;
- }
-
- if ( strcmp(cmd, "nolimit") == 0 )
- {
- m_terrain->SetFlyingMaxHeight(280.0f);
- return;
- }
-
- if ( strcmp(cmd, "photo1") == 0 )
- {
- m_bFreePhoto = !m_bFreePhoto;
- if ( m_bFreePhoto )
- {
- m_camera->SetType(CAMERA_FREE);
- ChangePause(true);
- }
- else
- {
- m_camera->SetType(CAMERA_BACK);
- ChangePause(false);
- }
- return;
- }
-
- if ( strcmp(cmd, "photo2") == 0 )
- {
- m_bFreePhoto = !m_bFreePhoto;
- if ( m_bFreePhoto )
- {
- m_camera->SetType(CAMERA_FREE);
- ChangePause(true);
- DeselectAll(); // removes the control buttons
- m_map->ShowMap(false);
- m_displayText->HideText(true);
- }
- else
- {
- m_camera->SetType(CAMERA_BACK);
- ChangePause(false);
- m_map->ShowMap(m_bMapShow);
- m_displayText->HideText(false);
- }
- return;
- }
-
- if ( strcmp(cmd, "noclip") == 0 )
- {
- CObject* object;
-
- object = RetSelect();
- if ( object != 0 )
- {
- object->SetClip(false);
- }
- return;
- }
-
- if ( strcmp(cmd, "clip") == 0 )
- {
- CObject* object;
-
- object = RetSelect();
- if ( object != 0 )
- {
- object->SetClip(true);
- }
- return;
- }
-
- if ( strcmp(cmd, "addhusky") == 0 )
- {
- CObject* object;
-
- object = RetSelect();
- if ( object != 0 )
- {
- object->SetMagnifyDamage(object->RetMagnifyDamage()*0.1f);
- }
- return;
- }
-
- if ( strcmp(cmd, "addfreezer") == 0 )
- {
- CObject* object;
-
- object = RetSelect();
- if ( object != 0 )
- {
- object->SetRange(object->RetRange()*10.0f);
- }
- return;
- }
-
- if ( strcmp(cmd, "fullpower") == 0 )
- {
- CObject* object;
- CObject* power;
- CPhysics* physics;
-
- object = RetSelect();
- if ( object != 0 )
- {
- power = object->RetPower();
- if ( power != 0 )
- {
- power->SetEnergy(1.0f);
- }
- object->SetShield(1.0f);
- physics = object->RetPhysics();
- if ( physics != 0 )
- {
- physics->SetReactorRange(1.0f);
- }
- }
- return;
- }
-
- if ( strcmp(cmd, "fullenergy") == 0 )
- {
- CObject* object;
- CObject* power;
-
- object = RetSelect();
- if ( object != 0 )
- {
- power = object->RetPower();
- if ( power != 0 )
- {
- power->SetEnergy(1.0f);
- }
- }
- return;
- }
-
- if ( strcmp(cmd, "fullshield") == 0 )
- {
- CObject* object;
-
- object = RetSelect();
- if ( object != 0 )
- {
- object->SetShield(1.0f);
- }
- return;
- }
-
- if ( strcmp(cmd, "fullrange") == 0 )
- {
- CObject* object;
- CPhysics* physics;
-
- object = RetSelect();
- if ( object != 0 )
- {
- physics = object->RetPhysics();
- if ( physics != 0 )
- {
- physics->SetReactorRange(1.0f);
- }
- }
- return;
- }
- }
-
- if ( strcmp(cmd, "debugmode") == 0 )
- {
- m_engine->SetDebugMode(!m_engine->RetDebugMode());
- return;
- }
-
- if ( strcmp(cmd, "showstat") == 0 )
- {
- m_engine->SetShowStat(!m_engine->RetShowStat());
- return;
- }
-
- if ( strcmp(cmd, "invshadow") == 0 )
- {
- m_engine->SetShadow(!m_engine->RetShadow());
- return;
- }
-
- if ( strcmp(cmd, "invdirty") == 0 )
- {
- m_engine->SetDirty(!m_engine->RetDirty());
- return;
- }
-
- if ( strcmp(cmd, "invfog") == 0 )
- {
- m_engine->SetFog(!m_engine->RetFog());
- return;
- }
-
- if ( strcmp(cmd, "invlens") == 0 )
- {
- m_engine->SetLensMode(!m_engine->RetLensMode());
- return;
- }
-
- if ( strcmp(cmd, "invwater") == 0 )
- {
- m_engine->SetWaterMode(!m_engine->RetWaterMode());
- return;
- }
-
- if ( strcmp(cmd, "invsky") == 0 )
- {
- m_engine->SetSkyMode(!m_engine->RetSkyMode());
- return;
- }
-
- if ( strcmp(cmd, "invplanet") == 0 )
- {
- m_engine->SetPlanetMode(!m_engine->RetPlanetMode());
- return;
- }
-
- if ( strcmp(cmd, "showpos") == 0 )
- {
- m_bShowPos = !m_bShowPos;
- return;
- }
-
- if ( strcmp(cmd, "selectinsect") == 0 )
- {
- m_bSelectInsect = !m_bSelectInsect;
- return;
- }
-
- if ( strcmp(cmd, "showsoluce") == 0 )
- {
- m_bShowSoluce = !m_bShowSoluce;
- m_dialog->ShowSoluceUpdate();
- return;
- }
-
-#if _TEEN
- if ( strcmp(cmd, "allteens") == 0 )
-#else
- if ( strcmp(cmd, "allmission") == 0 )
-#endif
- {
- m_bShowAll = !m_bShowAll;
- m_dialog->AllMissionUpdate();
- return;
- }
-
- if ( strcmp(cmd, "invradar") == 0 )
- {
- m_bCheatRadar = !m_bCheatRadar;
- return;
- }
-
- if ( m_phase == PHASE_SIMUL )
- {
- m_displayText->DisplayError(ERR_CMD, Math::Vector(0.0f,0.0f,0.0f));
- }
-}
-
-
-
-// Returns the type of current movie.
-
-MainMovieType CRobotMain::RetMainMovie()
-{
- return m_movie->RetType();
-}
-
-
-// Clears the display of instructions.
-
-void CRobotMain::FlushDisplayInfo()
-{
- int i;
-
- for ( i=0 ; i<SATCOM_MAX ; i++ )
- {
- m_infoFilename[i][0] = 0;
- m_infoPos[i] = 0;
- }
- strcpy(m_infoFilename[SATCOM_OBJECT], "help\\objects.txt");
- m_infoIndex = 0;
-}
-
-// Beginning of the displaying of instructions.
-// index: SATCOM_*
-
-void CRobotMain::StartDisplayInfo(int index, bool bMovie)
-{
- CObject* pObj;
- CMotion* motion;
- bool bHuman;
-
- if ( m_bCmdEdit || m_bSatComLock ) return;
-
- pObj = RetSelect();
- bHuman = ( pObj != 0 && pObj->RetType() == OBJECT_HUMAN );
-
- if ( !m_bEditLock && bMovie && !m_movie->IsExist() && bHuman )
- {
- motion = pObj->RetMotion();
- if ( motion != 0 && motion->RetAction() == -1 )
- {
- m_movieInfoIndex = index;
- m_movie->Start(MM_SATCOMopen, 2.5f);
- ChangePause(true);
-//? m_map->ShowMap(false);
- m_infoObject = DeselectAll(); // removes the control buttons
- m_displayText->HideText(true);
- return;
- }
- }
-
- if ( m_movie->IsExist() )
- {
- m_movie->Stop();
- ChangePause(false);
- SelectObject(m_infoObject, false); // hands over the command buttons
-//? m_map->ShowMap(m_bMapShow);
- m_displayText->HideText(false);
- }
-
- StartDisplayInfo(m_infoFilename[index], index);
-}
-
-// Beginning of the displaying of instructions.
-
-void CRobotMain::StartDisplayInfo(char *filename, int index)
-{
- CButton* pb;
- bool bSoluce;
-
- if ( m_bCmdEdit ) return;
-
- m_movieInfoIndex = -1;
- ClearInterface(); // removes setting evidence and tooltip
-
- if ( !m_bEditLock )
- {
-//? m_map->ShowMap(false);
- m_infoObject = DeselectAll(); // removes the control buttons
- m_displayText->HideText(true);
- m_sound->MuteAll(true);
- }
-
- pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
- if ( pb != 0 )
- {
- pb->ClearState(STATE_VISIBLE);
- }
-
- bSoluce = m_dialog->RetSceneSoluce();
-
- m_displayInfo = new CDisplayInfo(m_iMan);
- m_displayInfo->StartDisplayInfo(filename, index, bSoluce);
-
- m_infoIndex = index;
- if ( index != -1 )
- {
- m_displayInfo->SetPosition(m_infoPos[index]);
- }
-}
-
-// End of displaying of instructions.
-
-void CRobotMain::StopDisplayInfo()
-{
- CButton* pb;
-
- if ( m_movieInfoIndex != -1 ) // film to read the SatCom?
- {
- m_movie->Start(MM_SATCOMclose, 2.0f);
- }
-
- if ( m_infoIndex != -1 )
- {
- m_infoPos[m_infoIndex] = m_displayInfo->RetPosition();
- }
- m_displayInfo->StopDisplayInfo();
-
- delete m_displayInfo;
- m_displayInfo = 0;
-
- if ( !m_bEditLock )
- {
- pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
- if ( pb != 0 )
- {
- pb->SetState(STATE_VISIBLE);
- }
-
- SelectObject(m_infoObject, false); // gives the command buttons
-//? m_map->ShowMap(m_bMapShow);
- m_displayText->HideText(false);
-
- m_sound->MuteAll(false);
- }
-
- if ( m_infoUsed == 0 )
- {
- m_displayText->ClearText(); // removes message "see SatCom ..."
- }
- m_infoUsed ++;
-}
-
-// Returns the name of the text display.
-
-char* CRobotMain::RetDisplayInfoName(int index)
-{
- return m_infoFilename[index];
-}
-
-// Returns the name of the text display.
-
-int CRobotMain::RetDisplayInfoPosition(int index)
-{
- return m_infoPos[index];
-}
-
-// Returns the name of the text display.
-
-void CRobotMain::SetDisplayInfoPosition(int index, int pos)
-{
- m_infoPos[index] = pos;
-}
-
-
-// Beginning of a dialogue during the game,
-
-void CRobotMain::StartSuspend()
-{
- CButton* pb;
-
- m_map->ShowMap(false);
- m_infoObject = DeselectAll(); // removes the control buttons
- m_displayText->HideText(true);
-
- pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
- if ( pb != 0 )
- {
- pb->ClearState(STATE_VISIBLE);
- }
-
- m_bSuspend = true;
-}
-
-// End of dialogue during the game,
-
-void CRobotMain::StopSuspend()
-{
- CButton* pb;
-
- pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
- if ( pb != 0 )
- {
- pb->SetState(STATE_VISIBLE);
- }
-
- SelectObject(m_infoObject, false); // gives the command buttons
- m_map->ShowMap(m_bMapShow);
- m_displayText->HideText(false);
-
- m_bSuspend = false;
-}
-
-
-// Returns the absolute time of the game
-
-float CRobotMain::RetGameTime()
-{
- return m_gameTime;
-}
-
-
-
-// Managing the size of the default fonts.
-
-void CRobotMain::SetFontSize(float size)
-{
- m_fontSize = size;
- SetProfileFloat("Edit", "FontSize", m_fontSize);
-}
-
-float CRobotMain::RetFontSize()
-{
- return m_fontSize;
-}
-
-// Managing the size of the default window.
-
-void CRobotMain::SetWindowPos(Math::Point pos)
-{
- m_windowPos = pos;
- SetProfileFloat("Edit", "WindowPos.x", m_windowPos.x);
- SetProfileFloat("Edit", "WindowPos.y", m_windowPos.y);
-}
-
-Math::Point CRobotMain::RetWindowPos()
-{
- return m_windowPos;
-}
-
-void CRobotMain::SetWindowDim(Math::Point dim)
-{
- m_windowDim = dim;
- SetProfileFloat("Edit", "WindowDim.x", m_windowDim.x);
- SetProfileFloat("Edit", "WindowDim.y", m_windowDim.y);
-}
-
-Math::Point CRobotMain::RetWindowDim()
-{
- return m_windowDim;
-}
-
-
-// Managing windows open/save.
-
-void CRobotMain::SetIOPublic(bool bMode)
-{
- m_IOPublic = bMode;
- SetProfileInt("Edit", "IOPublic", m_IOPublic);
-}
-
-bool CRobotMain::RetIOPublic()
-{
- return m_IOPublic;
-}
-
-void CRobotMain::SetIOPos(Math::Point pos)
-{
- m_IOPos = pos;
- SetProfileFloat("Edit", "IOPos.x", m_IOPos.x);
- SetProfileFloat("Edit", "IOPos.y", m_IOPos.y);
-}
-
-Math::Point CRobotMain::RetIOPos()
-{
- return m_IOPos;
-}
-
-void CRobotMain::SetIODim(Math::Point dim)
-{
- m_IODim = dim;
- SetProfileFloat("Edit", "IODim.x", m_IODim.x);
- SetProfileFloat("Edit", "IODim.y", m_IODim.y);
-}
-
-Math::Point CRobotMain::RetIODim()
-{
- return m_IODim;
-}
-
-
-
-// Start of the visit instead of an error.
-
-void CRobotMain::StartDisplayVisit(EventMsg event)
-{
- CWindow* pw;
- CButton* button;
- CGroup* group;
- Math::Vector goal;
- Math::Point pos, dim;
- int i, j;
-
- if ( m_bEditLock ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
- if ( pw == 0 ) return;
-
- if ( event == EVENT_NULL ) // visit by keyboard shortcut?
- {
- if ( m_visitLast != EVENT_NULL ) // already a current visit?
- {
- i = m_visitLast-EVENT_DT_VISIT0;
- }
- else
- {
- i = MAXDTLINE;
- }
-
- // Seeks the last.
- for ( j=0 ; j<MAXDTLINE ; j++ )
- {
- i --;
- if ( i < 0 ) i = MAXDTLINE-1;
-
- button = (CButton*)pw->SearchControl(EventMsg(EVENT_DT_VISIT0+i));
- if ( button == 0 || !button->TestState(STATE_ENABLE) ) continue;
-
- group = (CGroup*)pw->SearchControl(EventMsg(EVENT_DT_GROUP0+i));
- if ( group != 0 )
- {
- event = EventMsg(EVENT_DT_VISIT0+i);
- break;
- }
- }
- }
- if ( event == EVENT_NULL )
- {
- m_sound->Play(SOUND_TZOING); // nothing to do!
- return;
- }
-
- m_visitLast = event;
-
- ClearInterface(); // removes setting evidence and tooltip
-
- if ( m_camera->RetType() == CAMERA_VISIT ) // already a current visit?
- {
- m_camera->StopVisit();
- m_displayText->ClearVisit();
- }
- else
- {
- m_visitObject = DeselectAll(); // removes the control buttons
- }
-
- // Creates the "continue" button.
- if ( m_interface->SearchControl(EVENT_DT_END) == 0 )
- {
- pos.x = 10.0f/640.0f;
- pos.y = 10.0f/480.0f;
- dim.x = 50.0f/640.0f;
- dim.y = 50.0f/480.0f;
- m_interface->CreateButton(pos, dim, 16, EVENT_DT_END);
- }
-
- // Creates the arrow to show the place.
- if ( m_visitArrow != 0 )
- {
- m_visitArrow->DeleteObject();
- delete m_visitArrow;
- m_visitArrow = 0;
- }
- goal = m_displayText->RetVisitGoal(event);
- m_visitArrow = CreateObject(goal, 0.0f, 1.0f, 10.0f, OBJECT_SHOW, false, false, 0);
-
- m_visitPos = m_visitArrow->RetPosition(0);
- m_visitPosArrow = m_visitPos;
- m_visitPosArrow.y += m_displayText->RetVisitHeight(event);
- m_visitArrow->SetPosition(0, m_visitPosArrow);
-
- m_visitTime = 0.0;
- m_visitParticule = 0.0f;
-
- m_particule->DeleteParticule(PARTISHOW);
-
- m_camera->StartVisit(m_displayText->RetVisitGoal(event),
- m_displayText->RetVisitDist(event));
- m_displayText->SetVisit(event);
- ChangePause(true);
-}
-
-// Move the arrow to visit.
-
-void CRobotMain::FrameVisit(float rTime)
-{
- Math::Vector pos, speed;
- Math::Point dim;
- float level;
-
- if ( m_visitArrow == 0 ) return;
-
- // Moves the arrow.
- m_visitTime += rTime;
-
- pos = m_visitPosArrow;
- pos.y += 1.5f+sinf(m_visitTime*4.0f)*4.0f;
- m_visitArrow->SetPosition(0, pos);
- m_visitArrow->SetAngleY(0, m_visitTime*2.0f);
-
- // Manages the particles "arrows".
- m_visitParticule -= rTime;
- if ( m_visitParticule <= 0.0f )
- {
- m_visitParticule = 1.5f;
-
- pos = m_visitPos;
- level = m_terrain->RetFloorLevel(pos)+2.0f;
- if ( pos.y < level ) pos.y = level; // not below the ground
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 30.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISHOW, 2.0f);
- }
-}
-
-// End of the visit instead of an error.
-
-void CRobotMain::StopDisplayVisit()
-{
- m_visitLast = EVENT_NULL;
-
- // Removes the button.
- m_interface->DeleteControl(EVENT_DT_END);
-
- // Removes the arrow.
- if ( m_visitArrow != 0 )
- {
- m_visitArrow->DeleteObject();
- delete m_visitArrow;
- m_visitArrow = 0;
- }
-
- // Removes particles "arrows".
- m_particule->DeleteParticule(PARTISHOW);
-
- m_camera->StopVisit();
- m_displayText->ClearVisit();
- ChangePause(false);
- if ( m_visitObject != 0 )
- {
- SelectObject(m_visitObject, false); // gives the command buttons
- m_visitObject = 0;
- }
-}
-
-
-
-// Updates all the shortcuts.
-
-void CRobotMain::UpdateShortcuts()
-{
- m_short->UpdateShortcuts();
-}
-
-// Returns the object that default was select after the creation of a scene.
-
-CObject* CRobotMain::RetSelectObject()
-{
- if ( m_selectObject != 0 ) return m_selectObject;
- return SearchHuman();
-}
-
-// Deselects everything, and returns the object that was selected.
-
-CObject* CRobotMain::DeselectAll()
-{
- CObject* pObj;
- CObject* pPrev;
- int i;
-
- pPrev = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetSelect() ) pPrev = pObj;
- pObj->SetSelect(false);
- }
- return pPrev;
-}
-
-// Selects an object, without attending to deselect the rest.
-
-void CRobotMain::SelectOneObject(CObject* pObj, bool bDisplayError)
-{
- ObjectType type;
- CObject* toto;
- CMotionToto* mt;
-
- pObj->SetSelect(true, bDisplayError);
- m_camera->SetObject(pObj);
-
- type = pObj->RetType();
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr ||
- type == OBJECT_APOLLO2 )
- {
- m_camera->SetType(pObj->RetCameraType());
- m_camera->SetDist(pObj->RetCameraDist());
- }
- else
- {
- m_camera->SetType(CAMERA_BACK);
- }
-
- toto = SearchToto();
- if ( toto != 0 )
- {
- mt = (CMotionToto*)toto->RetMotion();
- if ( mt != 0 )
- {
- mt->SetLinkType(type);
- }
- }
-}
-
-// Selects the object aimed by the mouse.
-
-bool CRobotMain::SelectObject(CObject* pObj, bool bDisplayError)
-{
- CObject* pPrev;
-
- if ( m_camera->RetType() == CAMERA_VISIT )
- {
- StopDisplayVisit();
- }
-
- if ( m_bMovieLock || m_bEditLock || m_bPause ) return false;
- if ( m_movie->IsExist() ) return false;
- if ( pObj == 0 || !IsSelectable(pObj) ) return false;
-
- pPrev = DeselectAll();
-
- if ( pPrev != 0 && pPrev != pObj )
- {
- pObj->AddDeselList(pPrev);
- }
-
- SelectOneObject(pObj, bDisplayError);
- m_short->UpdateShortcuts();
- return true;
-}
-
-// Deselects the selected object.
-
-bool CRobotMain::DeselectObject()
-{
- CObject* pObj;
- CObject* pPrev;
-
- pPrev = DeselectAll();
-
- if ( pPrev == 0 )
- {
- pObj = SearchHuman();
- }
- else
- {
- pObj = pPrev->SubDeselList();
- }
- if ( pObj == 0 )
- {
- pObj = SearchHuman();
- }
-
- if ( pObj != 0 )
- {
- SelectOneObject(pObj);
- }
- else
- {
- m_camera->SetType(CAMERA_FREE);
- }
-
- m_short->UpdateShortcuts();
- return true;
-}
-
-// Quickly removes all objects.
-
-void CRobotMain::DeleteAllObjects()
-{
- CPyro* pyro;
- CObject* pObj;
- int i;
-
- // Removes all pyrotechnic effects in progress.
- while ( true )
- {
- pyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, 0);
- if ( pyro == 0 ) break;
-
- pyro->DeleteObject();
- delete pyro;
- }
-
- // Removes the arrow.
- if ( m_visitArrow != 0 )
- {
- m_visitArrow->DeleteObject();
- delete m_visitArrow;
- m_visitArrow = 0;
- }
-
- for ( i=0 ; i<MAXSHOWLIMIT ; i++ )
- {
- FlushShowLimit(i);
- }
-
- while ( true )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, 0);
- if ( pObj == 0 ) break;
-
- pObj->DeleteObject(true); // destroys rapidly
- delete pObj;
- }
-}
-
-// Selects the human.
-
-void CRobotMain::SelectHuman()
-{
- SelectObject(SearchHuman());
-}
-
-// Returns the object human.
-
-CObject* CRobotMain::SearchHuman()
-{
- ObjectType type;
- CObject* pObj;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_HUMAN )
- {
- return pObj;
- }
- }
- return 0;
-}
-
-// Returns the object toto.
-
-CObject* CRobotMain::SearchToto()
-{
- ObjectType type;
- CObject* pObj;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_TOTO )
- {
- return pObj;
- }
- }
- return 0;
-}
-
-// Returns the nearest selectable object from a given position.
-
-CObject* CRobotMain::SearchNearest(Math::Vector pos, CObject* pExclu)
-{
- ObjectType type;
- CObject *pObj, *pBest;
- Math::Vector oPos;
- float min, dist;
- int i;
-
- min = 100000.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == pExclu ) continue;
- if ( !IsSelectable(pObj) ) continue;
-
- type = pObj->RetType();
- if ( type == OBJECT_TOTO ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, pos);
- if ( dist < min )
- {
- min = dist;
- pBest = pObj;
- }
- }
- return pBest;
-}
-
-// Returns the selected object.
-
-CObject* CRobotMain::RetSelect()
-{
- CObject* pObj;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetSelect() )
- {
- return pObj;
- }
- }
- return 0;
-}
-
-CObject* CRobotMain::SearchObject(ObjectType type)
-{
- CObject* pObj;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetType() == type )
- {
- return pObj;
- }
- }
- return 0;
-}
-
-// Detects the object aimed by the mouse.
-
-CObject* CRobotMain::DetectObject(Math::Point pos)
-{
- ObjectType type;
- CObject *pObj, *pTarget;
- int objRank, i, j, rank;
-
- objRank = m_engine->DetectObject(pos);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue;
- if ( pObj->RetProxyActivate() ) continue;
-
- pTarget = 0;
- type = pObj->RetType();
- if ( type == OBJECT_PORTICO ||
- type == OBJECT_BASE ||
- type == OBJECT_DERRICK ||
- type == OBJECT_FACTORY ||
- type == OBJECT_REPAIR ||
- type == OBJECT_DESTROYER ||
- type == OBJECT_STATION ||
- type == OBJECT_CONVERT ||
- type == OBJECT_TOWER ||
- type == OBJECT_RESEARCH ||
- type == OBJECT_RADAR ||
- type == OBJECT_INFO ||
- type == OBJECT_ENERGY ||
- type == OBJECT_LABO ||
- type == OBJECT_NUCLEAR ||
- type == OBJECT_PARA ||
- type == OBJECT_SAFE ||
- type == OBJECT_HUSTON ||
- type == OBJECT_TARGET1 ||
- type == OBJECT_TARGET2 ||
- type == OBJECT_START ||
- type == OBJECT_END ||
- type == OBJECT_STONE ||
- type == OBJECT_URANIUM ||
- type == OBJECT_BULLET ||
- type == OBJECT_METAL ||
- type == OBJECT_BBOX ||
- type == OBJECT_KEYa ||
- type == OBJECT_KEYb ||
- type == OBJECT_KEYc ||
- type == OBJECT_KEYd ||
- type == OBJECT_TNT ||
- type == OBJECT_SCRAP1 ||
- type == OBJECT_SCRAP2 ||
- type == OBJECT_SCRAP3 ||
- type == OBJECT_SCRAP4 ||
- type == OBJECT_SCRAP5 ||
- type == OBJECT_BOMB ||
- type == OBJECT_BAG ||
- type == OBJECT_WAYPOINT ||
- type == OBJECT_FLAGb ||
- type == OBJECT_FLAGr ||
- type == OBJECT_FLAGg ||
- type == OBJECT_FLAGy ||
- type == OBJECT_FLAGv ||
- type == OBJECT_MARKPOWER ||
- type == OBJECT_MARKSTONE ||
- type == OBJECT_MARKURANIUM ||
- type == OBJECT_MARKKEYa ||
- type == OBJECT_MARKKEYb ||
- type == OBJECT_MARKKEYc ||
- type == OBJECT_MARKKEYd ||
- type == OBJECT_HUMAN ||
- type == OBJECT_TECH ||
- type == OBJECT_TOTO ||
- type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr ||
- type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ||
- type == OBJECT_EGG ||
- type == OBJECT_RUINmobilew1 ||
- type == OBJECT_RUINmobilew2 ||
- type == OBJECT_RUINmobilet1 ||
- type == OBJECT_RUINmobilet2 ||
- type == OBJECT_RUINmobiler1 ||
- type == OBJECT_RUINmobiler2 ||
- type == OBJECT_RUINfactory ||
- type == OBJECT_RUINdoor ||
- type == OBJECT_RUINsupport ||
- type == OBJECT_RUINradar ||
- type == OBJECT_RUINconvert ||
- type == OBJECT_RUINbase ||
- type == OBJECT_RUINhead ||
- type == OBJECT_APOLLO1 ||
- type == OBJECT_APOLLO2 ||
- type == OBJECT_APOLLO3 ||
- type == OBJECT_APOLLO4 ||
- type == OBJECT_APOLLO5 )
- {
- pTarget = pObj;
- }
- else if ( (type == OBJECT_POWER ||
- type == OBJECT_ATOMIC ) &&
- pObj->RetTruck() != 0 ) // battery used?
- {
- pTarget = pObj->RetTruck();
- }
- else if ( type == OBJECT_POWER ||
- type == OBJECT_ATOMIC )
- {
- pTarget = pObj;
- }
-
- for ( j=0 ; j<OBJECTMAXPART ; j++ )
- {
- rank = pObj->RetObjectRank(j);
- if ( rank == -1 ) continue;
- if ( rank != objRank ) continue;
- return pTarget;
- }
- }
- return 0;
-}
-
-// Indicates whether an object is selectable.
-
-bool CRobotMain::IsSelectable(CObject* pObj)
-{
- ObjectType type;
-
- if ( !pObj->RetSelectable() ) return false;
-
- type = pObj->RetType();
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TOTO ||
- type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr ||
- type == OBJECT_APOLLO2 ||
- type == OBJECT_BASE ||
- type == OBJECT_DERRICK ||
- type == OBJECT_FACTORY ||
- type == OBJECT_REPAIR ||
- type == OBJECT_DESTROYER||
- type == OBJECT_STATION ||
- type == OBJECT_CONVERT ||
- type == OBJECT_TOWER ||
- type == OBJECT_RESEARCH ||
- type == OBJECT_RADAR ||
- type == OBJECT_INFO ||
- type == OBJECT_ENERGY ||
- type == OBJECT_LABO ||
- type == OBJECT_NUCLEAR ||
- type == OBJECT_PARA ||
- type == OBJECT_SAFE ||
- type == OBJECT_HUSTON )
- {
- return true;
- }
-
- if ( m_bSelectInsect )
- {
- if ( type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ||
- type == OBJECT_MOBILEtg )
- {
- return true;
- }
- }
-
- return false;
-}
-
-
-// Deletes the selected object.
-
-bool CRobotMain::DeleteObject()
-{
- CObject* pObj;
- CPyro* pyro;
-
- pObj = RetSelect();
- if ( pObj == 0 ) return false;
-
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FRAGT, pObj);
-
- pObj->SetSelect(false); // deselects the object
- m_camera->SetType(CAMERA_EXPLO);
- DeselectAll();
- pObj->DeleteDeselList(pObj);
-
- return true;
-}
-
-
-// Removes setting evidence of the object with the mouse hovers over.
-
-void CRobotMain::HiliteClear()
-{
- CObject* pObj;
- int i;
-
- ClearTooltip();
- m_tooltipName[0] = 0; // really removes the tooltip
-
- if ( !m_bHilite ) return;
-
- i = -1;
- m_engine->SetHiliteRank(&i); // nothing more selected
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- pObj->SetHilite(false);
- m_map->SetHilite(0);
- m_short->SetHilite(0);
- }
-
- m_bHilite = false;
-}
-
-// Highlights the object with the mouse hovers over.
-
-void CRobotMain::HiliteObject(Math::Point pos)
-{
- CObject* pObj;
- char name[100];
- bool bInMap;
-
- if ( m_bFixScene && m_phase != PHASE_PERSO ) return;
- if ( m_bMovieLock ) return;
- if ( m_movie->IsExist() ) return;
- if ( m_engine->RetMouseHide() ) return;
-
- ClearInterface(); // removes setting evidence and tooltip
-
- pObj = m_short->DetectShort(pos);
-
- if ( m_dialog->RetTooltip() && m_interface->GetTooltip(pos, name) )
- {
- m_tooltipPos = pos;
- strcpy(m_tooltipName, name);
- m_tooltipTime = 0.0f;
- if ( pObj == 0 ) return;
- }
-
- if ( m_bSuspend ) return;
-
- if ( pObj == 0 )
- {
- pObj = m_map->DetectMap(pos, bInMap);
- if ( pObj == 0 )
- {
- if ( bInMap ) return;
-
- pObj = DetectObject(pos);
-
- if ( m_camera->RetType() == CAMERA_ONBOARD &&
- m_camera->RetObject() == pObj )
- {
- return;
- }
- }
- }
-
- if ( pObj != 0 )
- {
- if ( m_dialog->RetTooltip() && pObj->GetTooltipName(name) )
- {
- m_tooltipPos = pos;
- strcpy(m_tooltipName, name);
- m_tooltipTime = 0.0f;
- }
-
- if ( IsSelectable(pObj) )
- {
- pObj->SetHilite(true);
- m_map->SetHilite(pObj);
- m_short->SetHilite(pObj);
- m_bHilite = true;
- }
- }
-}
-
-// Highlights the object with the mouse hovers over.
-
-void CRobotMain::HiliteFrame(float rTime)
-{
- if ( m_bFixScene && m_phase != PHASE_PERSO ) return;
- if ( m_bMovieLock ) return;
- if ( m_movie->IsExist() ) return;
-
- m_tooltipTime += rTime;
-
- ClearTooltip();
-
- if ( m_tooltipTime >= 0.2f &&
- m_tooltipName[0] != 0 )
- {
- CreateTooltip(m_tooltipPos, m_tooltipName);
- }
-}
-
-// Creates a tooltip.
-
-void CRobotMain::CreateTooltip(Math::Point pos, char* text)
-{
- CWindow* pw;
- Math::Point start, end, dim, offset, corner;
-
- corner.x = pos.x+0.022f;
- corner.y = pos.y-0.052f;
-
- m_engine->RetText()->DimText(text, corner, 1,
- SMALLFONT, NORMSTRETCH, FONT_COLOBOT,
- start, end);
- start.x -= 0.010f;
- start.y -= 0.002f;
- end.x += 0.010f;
- end.y += 0.004f; // ch'tite (?) margin
-
- pos.x = start.x;
- pos.y = start.y;
- dim.x = end.x-start.x;
- dim.y = end.y-start.y;
-
- offset.x = 0.0f;
- offset.y = 0.0f;
- if ( pos.x+dim.x > 1.0f ) offset.x = 1.0f-(pos.x+dim.x);
- if ( pos.y < 0.0f ) offset.y = -pos.y;
-
- corner.x += offset.x;
- corner.y += offset.y;
- pos.x += offset.x;
- pos.y += offset.y;
-
- m_interface->CreateWindows(pos, dim, 1, EVENT_TOOLTIP);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_TOOLTIP);
- if ( pw != 0 )
- {
- pw->SetState(STATE_SHADOW);
- pw->SetTrashEvent(false);
-
- pos.y -= m_engine->RetText()->RetHeight(SMALLFONT, FONT_COLOBOT)/2.0f;
- pw->CreateLabel(pos, dim, -1, EVENT_LABEL2, text);
- }
-}
-
-// Clears the previous tooltip.
-
-void CRobotMain::ClearTooltip()
-{
- m_interface->DeleteControl(EVENT_TOOLTIP);
-}
-
-
-// Displays help for an object.
-
-void CRobotMain::HelpObject()
-{
- CObject* pObj;
- char* filename;
-
- pObj = RetSelect();
- if ( pObj == 0 ) return;
-
- filename = RetHelpFilename(pObj->RetType());
- if ( filename[0] == 0 ) return;
-
- StartDisplayInfo(filename, -1);
-}
-
-
-// Change the mode of the camera.
-
-void CRobotMain::ChangeCamera()
-{
- CObject* pObj;
- ObjectType oType;
- CameraType type;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetSelect() )
- {
- if ( pObj->RetCameraLock() ) return;
-
- oType = pObj->RetType();
- type = pObj->RetCameraType();
-
- if ( oType != OBJECT_MOBILEfa &&
- oType != OBJECT_MOBILEta &&
- oType != OBJECT_MOBILEwa &&
- oType != OBJECT_MOBILEia &&
- oType != OBJECT_MOBILEfc &&
- oType != OBJECT_MOBILEtc &&
- oType != OBJECT_MOBILEwc &&
- oType != OBJECT_MOBILEic &&
- oType != OBJECT_MOBILEfi &&
- oType != OBJECT_MOBILEti &&
- oType != OBJECT_MOBILEwi &&
- oType != OBJECT_MOBILEii &&
- oType != OBJECT_MOBILEfs &&
- oType != OBJECT_MOBILEts &&
- oType != OBJECT_MOBILEws &&
- oType != OBJECT_MOBILEis &&
- oType != OBJECT_MOBILErt &&
- oType != OBJECT_MOBILErc &&
- oType != OBJECT_MOBILErr &&
- oType != OBJECT_MOBILErs &&
- oType != OBJECT_MOBILEsa &&
- oType != OBJECT_MOBILEtg &&
- oType != OBJECT_MOBILEft &&
- oType != OBJECT_MOBILEtt &&
- oType != OBJECT_MOBILEwt &&
- oType != OBJECT_MOBILEit &&
- oType != OBJECT_MOBILEdr &&
- oType != OBJECT_APOLLO2 ) return;
-
- if ( oType == OBJECT_MOBILEdr ) // designer?
- {
- if ( type == CAMERA_PLANE ) type = CAMERA_BACK;
- else if ( type == CAMERA_BACK ) type = CAMERA_PLANE;
- }
- else if ( pObj->RetTrainer() ) // trainer?
- {
- if ( type == CAMERA_ONBOARD ) type = CAMERA_FIX;
- else if ( type == CAMERA_FIX ) type = CAMERA_PLANE;
- else if ( type == CAMERA_PLANE ) type = CAMERA_BACK;
- else if ( type == CAMERA_BACK ) type = CAMERA_ONBOARD;
- }
- else
- {
- if ( type == CAMERA_ONBOARD ) type = CAMERA_BACK;
- else if ( type == CAMERA_BACK ) type = CAMERA_ONBOARD;
- }
-
- pObj->SetCameraType(type);
- m_camera->SetType(type);
- }
- }
-}
-
-// Remote control the camera using the arrow keys.
-
-void CRobotMain::KeyCamera(EventMsg event, long param)
-{
- CObject* pObj;
-
- if ( event == EVENT_KEYUP )
- {
- if ( param == m_engine->RetKey(KEYRANK_LEFT, 0) ||
- param == m_engine->RetKey(KEYRANK_LEFT, 1) )
- {
- m_cameraPan = 0.0f;
- }
-
- if ( param == m_engine->RetKey(KEYRANK_RIGHT, 0) ||
- param == m_engine->RetKey(KEYRANK_RIGHT, 1) )
- {
- m_cameraPan = 0.0f;
- }
-
- if ( param == m_engine->RetKey(KEYRANK_UP, 0) ||
- param == m_engine->RetKey(KEYRANK_UP, 1) )
- {
- m_cameraZoom = 0.0f;
- }
-
- if ( param == m_engine->RetKey(KEYRANK_DOWN, 0) ||
- param == m_engine->RetKey(KEYRANK_DOWN, 1) )
- {
- m_cameraZoom = 0.0f;
- }
- }
-
- if ( m_phase != PHASE_SIMUL ) return;
- if ( m_bEditLock ) return; // current edition?
- if ( m_bTrainerPilot ) return;
-
- pObj = RetSelect();
- if ( pObj == 0 ) return;
- if ( !pObj->RetTrainer() ) return;
-
- if ( event == EVENT_KEYDOWN )
- {
- if ( param == m_engine->RetKey(KEYRANK_LEFT, 0) ||
- param == m_engine->RetKey(KEYRANK_LEFT, 1) )
- {
- m_cameraPan = -1.0f;
- }
-
- if ( param == m_engine->RetKey(KEYRANK_RIGHT, 0) ||
- param == m_engine->RetKey(KEYRANK_RIGHT, 1) )
- {
- m_cameraPan = 1.0f;
- }
-
- if ( param == m_engine->RetKey(KEYRANK_UP, 0) ||
- param == m_engine->RetKey(KEYRANK_UP, 1) )
- {
- m_cameraZoom = -1.0f;
- }
-
- if ( param == m_engine->RetKey(KEYRANK_DOWN, 0) ||
- param == m_engine->RetKey(KEYRANK_DOWN, 1) )
- {
- m_cameraZoom = 1.0f;
- }
- }
-}
-
-// Panned with the camera if a button is pressed.
-
-void CRobotMain::RemoteCamera(float pan, float zoom, float rTime)
-{
- float value;
-
- if ( pan != 0.0f )
- {
- value = m_camera->RetRemotePan();
- value += pan*rTime*1.5f;
- m_camera->SetRemotePan(value);
- }
-
- if ( zoom != 0.0f )
- {
- value = m_camera->RetRemoteZoom();
- value += zoom*rTime*0.3f;
- m_camera->SetRemoteZoom(value);
- }
-}
-
-
-
-// Cancels the current movie.
-
-void CRobotMain::AbortMovie()
-{
- CObject* pObj;
- CAuto* automat;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- automat = pObj->RetAuto();
- if ( automat != 0 )
- {
- automat->Abort();
- }
- }
-
- m_engine->SetMouseHide(false);
-}
-
-
-
-// Updates the text information.
-
-void CRobotMain::UpdateInfoText()
-{
- CObject* pObj;
- Math::Vector pos;
- char info[100];
-
- if ( m_bShowPos )
- {
- pObj = RetSelect();
- if ( pObj != 0 )
- {
- pos = pObj->RetPosition(0);
- sprintf(info, "Pos = %.2f ; %.2f", pos.x/g_unit, pos.z/g_unit);
- m_engine->SetInfoText(4, info);
- }
- }
-}
-
-
-// Initializes the view.
-
-void CRobotMain::InitEye()
-{
- if ( m_phase == PHASE_SIMUL )
- {
- m_camera->Init(Math::Vector( 0.0f, 10.0f, 0.0f),
- Math::Vector(10.0f, 5.0f, 0.0f), 0.0f);
- }
-
- if ( m_phase == PHASE_MODEL )
- {
- m_model->InitView();
- }
-}
-
-// Advances the entire scene.
-
-bool CRobotMain::EventFrame(const Event &event)
-{
- ObjectType type;
- CObject *pObj, *toto;
- CPyro* pPyro;
- CWindow* pw;
- CMap* pm;
- int i;
-
- m_time += event.rTime;
- if ( !m_bMovieLock ) m_gameTime += event.rTime;
-
- if ( !m_bImmediatSatCom && !m_bBeginSatCom &&
- m_gameTime > 0.1f && m_phase == PHASE_SIMUL )
- {
- m_displayText->DisplayError(INFO_BEGINSATCOM, Math::Vector(0.0f,0.0f,0.0f));
- m_bBeginSatCom = true; // message appears
- }
-
- m_water->EventProcess(event);
- m_cloud->EventProcess(event);
- m_blitz->EventProcess(event);
- m_planet->EventProcess(event);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw == 0 )
- {
- pm = 0;
- }
- else
- {
- pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
- if ( pm != 0 ) pm->FlushObject();
- }
-
- toto = 0;
- if ( !m_bFreePhoto )
- {
- // Advances all the robots, but not toto.
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
- if ( pm != 0 ) pm->UpdateObject(pObj);
- if ( pObj->RetTruck() != 0 ) continue;
- type = pObj->RetType();
- if ( type == OBJECT_TOTO )
- {
- toto = pObj;
- }
- else
- {
- pObj->EventProcess(event);
- }
- }
- // Advances all objects transported by robots.
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
- if ( pObj->RetTruck() == 0 ) continue;
- pObj->EventProcess(event);
- }
-
- // Advances pyrotechnic effects.
- for ( i=0 ; i<1000000 ; i++ )
- {
- pPyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, i);
- if ( pPyro == 0 ) break;
-
- pPyro->EventProcess(event);
- if ( pPyro->IsEnded() != ERR_CONTINUE )
- {
- pPyro->DeleteObject();
- delete pPyro;
- }
- }
- }
-
- // The camera follows the object, because its position
- // may depend on the selected object (CAMERA_ONBOARD or CAMERA_BACK).
- if ( m_phase == PHASE_SIMUL && !m_bEditFull )
- {
- m_camera->EventProcess(event);
-
- if ( m_engine->RetFog() )
- {
- m_camera->SetOverBaseColor(m_particule->RetFogColor(m_engine->RetEyePt()));
- }
- }
- if ( m_phase == PHASE_PERSO ||
- m_phase == PHASE_WIN ||
- m_phase == PHASE_LOST )
- {
- m_camera->EventProcess(event);
- }
-
- // Advances toto following the camera, because its position depends on the camera.
- if ( toto != 0 )
- {
- toto->EventProcess(event);
- }
-
- // Advances model.
- if ( m_phase == PHASE_MODEL )
- {
- m_model->ViewMove(event, 2.0f);
- m_model->UpdateView();
- m_model->EventProcess(event);
- }
-
- HiliteFrame(event.rTime);
-
- // Moves the film indicator.
- if ( m_bMovieLock && !m_bEditLock ) // movie in progress?
- {
- CControl* pc;
- Math::Point pos, dim;
- float zoom;
-
- pc = m_interface->SearchControl(EVENT_OBJECT_MOVIELOCK);
- if ( pc != 0 )
- {
- dim.x = 32.0f/640.0f;
- dim.y = 32.0f/480.0f;
- pos.x = 20.0f/640.0f;
- pos.y = (480.0f-24.0f)/480.0f;
-
- zoom = 1.0f+sinf(m_time*6.0f)*0.1f; // 0.9 .. 1.1
- dim.x *= zoom;
- dim.y *= zoom;
- pos.x -= dim.x/2.0f;
- pos.y -= dim.y/2.0f;
-
- pc->SetPos(pos);
- pc->SetDim(dim);
- }
- }
-
- // Moves edition indicator.
- if ( m_bEditLock || m_bPause ) // edition in progress?
- {
- CControl* pc;
- Math::Point pos, dim;
- float zoom;
-
- pc = m_interface->SearchControl(EVENT_OBJECT_EDITLOCK);
- if ( pc != 0 )
- {
- if ( m_bEditFull || m_bEditLock )
- {
- dim.x = 10.0f/640.0f;
- dim.y = 10.0f/480.0f;
- pos.x = -20.0f/640.0f;
- pos.y = -20.0f/480.0f; // invisible!
- }
- else
- {
- dim.x = 32.0f/640.0f;
- dim.y = 32.0f/480.0f;
- pos.x = 20.0f/640.0f;
- pos.y = (480.0f-24.0f)/480.0f;
-
- zoom = 1.0f+sinf(m_time*6.0f)*0.1f; // 0.9 .. 1.1
- dim.x *= zoom;
- dim.y *= zoom;
- pos.x -= dim.x/2.0f;
- pos.y -= dim.y/2.0f;
- }
- pc->SetPos(pos);
- pc->SetDim(dim);
- }
- }
-
- // Will move the arrow to visit.
- if ( m_camera->RetType() == CAMERA_VISIT )
- {
- FrameVisit(event.rTime);
- }
-
- // Moves the boundaries.
- FrameShowLimit(event.rTime);
-
- if ( m_phase == PHASE_SIMUL )
- {
- if ( !m_bEditLock && m_checkEndTime+1.0f < m_time )
- {
- m_checkEndTime = m_time;
- CheckEndMission(true);
- }
-
- if ( m_winDelay > 0.0f && !m_bEditLock )
- {
- m_winDelay -= event.rTime;
- if ( m_winDelay <= 0.0f )
- {
- if ( m_bMovieLock )
- {
- m_winDelay = 1.0f;
- }
- else
- {
- Event newEvent;
- m_event->MakeEvent(newEvent, EVENT_WIN);
- m_event->AddEvent(newEvent);
- }
- }
- }
-
- if ( m_lostDelay > 0.0f && !m_bEditLock )
- {
- m_lostDelay -= event.rTime;
- if ( m_lostDelay <= 0.0f )
- {
- if ( m_bMovieLock )
- {
- m_winDelay = 1.0f;
- }
- else
- {
- Event newEvent;
- m_event->MakeEvent(newEvent, EVENT_LOST);
- m_event->AddEvent(newEvent);
- }
- }
- }
- }
-
- if ( m_delayWriteMessage > 0 )
- {
- m_delayWriteMessage --;
- if ( m_delayWriteMessage == 0 )
- {
- m_displayText->DisplayError(INFO_WRITEOK, Math::Vector(0.0f,0.0f,0.0f));
- }
- }
-
- return S_OK;
-}
-
-// Makes the event for all robots.
-
-bool CRobotMain::EventObject(const Event &event)
-{
- CObject* pObj;
- int i;
-
- if ( m_bFreePhoto ) return S_OK;
-
- m_bResetCreate = false;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- pObj->EventProcess(event);
- }
-
- if ( m_bResetCreate )
- {
- ResetCreate();
- }
-
- return S_OK;
-}
-
-
-// Calculates the point of arrival of the camera.
-
-Math::Vector CRobotMain::LookatPoint(Math::Vector eye, float angleH, float angleV,
- float length)
-{
- Math::Vector lookat;
-
- lookat = eye;
- lookat.z += length;
-
- RotatePoint(eye, angleH, angleV, lookat);
- return lookat;
-}
-
-
-
-char* SkipNum(char *p)
-{
- while ( *p == ' ' || *p == '.' || *p == '-' || (*p >= '0' && *p <= '9') )
- {
- p++;
- }
- return p;
-}
-
-// Conversion of units.
-
-void CRobotMain::Convert()
-{
- FILE* file = NULL;
- FILE* fileNew = NULL;
- char line[500];
- char lineNew[500];
- char s[200];
- char* base;
- char* p;
- int rank;
- Math::Vector pos;
- float value;
-
- base = m_dialog->RetSceneName();
- rank = m_dialog->RetSceneRank();
-
- m_dialog->BuildSceneName(line, base, rank);
- file = fopen(line, "r");
- if ( file == NULL ) return;
-
- strcpy(line+strlen(line)-4, ".new");
- fileNew = fopen(line, "w");
- if ( fileNew == NULL ) return;
-
- while ( fgets(line, 500, file) != NULL )
- {
- strcpy(lineNew, line);
-
- if ( Cmd(line, "DeepView") )
- {
- p = strstr(line, "air=");
- if ( p != 0 )
- {
- value = OpFloat(line, "air", 500.0f);
- value /= g_unit;
- p[0] = 0;
- p = SkipNum(p+4);
- strcpy(lineNew, line);
- strcat(lineNew, "air=");
- sprintf(s, "%.2f", value);
- strcat(lineNew, s);
- strcat(lineNew, " ");
- strcat(lineNew, p);
- }
- strcpy(line, lineNew);
-
- p = strstr(line, "water=");
- if ( p != 0 )
- {
- value = OpFloat(line, "water", 100.0f);
- value /= g_unit;
- p[0] = 0;
- p = SkipNum(p+6);
- strcpy(lineNew, line);
- strcat(lineNew, "water=");
- sprintf(s, "%.2f", value);
- strcat(lineNew, s);
- strcat(lineNew, " ");
- strcat(lineNew, p);
- }
- strcpy(line, lineNew);
- }
-
- if ( Cmd(line, "TerrainGenerate") )
- {
- p = strstr(line, "vision=");
- if ( p != 0 )
- {
- value = OpFloat(line, "vision", 500.0f);
- value /= g_unit;
- p[0] = 0;
- p = SkipNum(p+7);
- strcpy(lineNew, line);
- strcat(lineNew, "vision=");
- sprintf(s, "%.2f", value);
- strcat(lineNew, s);
- strcat(lineNew, " ");
- strcat(lineNew, p);
- }
- }
-
- if ( Cmd(line, "CreateObject") ||
- Cmd(line, "CreateSpot") )
- {
- p = strstr(line, "pos=");
- if ( p != 0 )
- {
- pos = OpPos(line, "pos");
- pos.x /= g_unit;
- pos.y /= g_unit;
- pos.z /= g_unit;
- p[0] = 0;
- p = SkipNum(p+4);
- p = SkipNum(p+1);
- strcpy(lineNew, line);
- strcat(lineNew, "pos=");
- sprintf(s, "%.2f", pos.x);
- strcat(lineNew, s);
- strcat(lineNew, ";");
- sprintf(s, "%.2f", pos.z);
- strcat(lineNew, s);
- strcat(lineNew, " ");
- strcat(lineNew, p);
- }
- }
-
- if ( Cmd(line, "EndMissionTake") )
- {
- p = strstr(line, "pos=");
- if ( p != 0 )
- {
- pos = OpPos(line, "pos");
- pos.x /= g_unit;
- pos.y /= g_unit;
- pos.z /= g_unit;
- p[0] = 0;
- p = SkipNum(p+4);
- p = SkipNum(p+1);
- strcpy(lineNew, line);
- strcat(lineNew, "pos=");
- sprintf(s, "%.2f", pos.x);
- strcat(lineNew, s);
- strcat(lineNew, ";");
- sprintf(s, "%.2f", pos.z);
- strcat(lineNew, s);
- strcat(lineNew, " ");
- strcat(lineNew, p);
- }
- strcpy(line, lineNew);
-
- p = strstr(line, "dist=");
- if ( p != 0 )
- {
- value = OpFloat(line, "dist", 32.0f);
- value /= g_unit;
- p[0] = 0;
- p = SkipNum(p+5);
- strcpy(lineNew, line);
- strcat(lineNew, "dist=");
- sprintf(s, "%.2f", value);
- strcat(lineNew, s);
- strcat(lineNew, " ");
- strcat(lineNew, p);
- }
- strcpy(line, lineNew);
- }
-
- if ( Cmd(line, "Camera") )
- {
- p = strstr(line, "pos=");
- if ( p != 0 )
- {
- pos = OpPos(line, "pos");
- pos.x /= g_unit;
- pos.y /= g_unit;
- pos.z /= g_unit;
- p[0] = 0;
- p = SkipNum(p+4);
- p = SkipNum(p+1);
- strcpy(lineNew, line);
- strcat(lineNew, "pos=");
- sprintf(s, "%.2f", pos.x);
- strcat(lineNew, s);
- strcat(lineNew, ";");
- sprintf(s, "%.2f", pos.z);
- strcat(lineNew, s);
- strcat(lineNew, " ");
- strcat(lineNew, p);
- }
- strcpy(line, lineNew);
-
- p = strstr(line, "h=");
- if ( p != 0 )
- {
- value = OpFloat(line, "h", 32.0f);
- value /= g_unit;
- p[0] = 0;
- p = SkipNum(p+2);
- strcpy(lineNew, line);
- strcat(lineNew, "h=");
- sprintf(s, "%.2f", value);
- strcat(lineNew, s);
- strcat(lineNew, " ");
- strcat(lineNew, p);
- }
- strcpy(line, lineNew);
- }
-
- fputs(lineNew, fileNew);
- }
-
- fclose(fileNew);
- fclose(file);
-}
-
-// Load the scene for the character.
-
-void CRobotMain::ScenePerso()
-{
- CObject* pObj;
-
- DeleteAllObjects(); // removes all the current 3D Scene
- m_engine->FlushObject();
- m_terrain->FlushRelief(); // all flat
- m_terrain->FlushBuildingLevel();
- m_terrain->FlushFlyingLimit();
- m_light->FlushLight();
- m_particule->FlushParticule();
- m_iMan->Flush(CLASS_OBJECT);
- m_iMan->Flush(CLASS_PHYSICS);
- m_iMan->Flush(CLASS_BRAIN);
- m_iMan->Flush(CLASS_PYRO);
-
- m_dialog->SetSceneName("perso");
- m_dialog->SetSceneRank(0);
- CreateScene(false, true, false); // sets scene
-
- m_engine->SetDrawWorld(false); // does not draw anything on the interface
- m_engine->SetDrawFront(true); // draws on the human interface
- pObj = SearchHuman();
- if ( pObj != 0 )
- {
- CMotionHuman* mh;
-
- pObj->SetDrawFront(true); // draws the interface
-
- mh = (CMotionHuman*)pObj->RetMotion();
- if ( mh != 0 )
- {
- mh->StartDisplayPerso();
- }
- }
-}
-
-// Creates the whole stage.
-
-void CRobotMain::CreateScene(bool bSoluce, bool bFixScene, bool bResetObject)
-{
- CObject* pObj;
- CObject* pSel;
- CMotion* motion;
- FILE* file = NULL;
- char line[500];
- char name[200];
- char dir[100];
- char op[100];
- char* read;
- char* stack;
- char* base;
- D3DCOLORVALUE color;
- Math::Vector pos;
- int rank, obj, i, rankObj, rankGadget;
-
-//? Convert();
-
- base = m_dialog->RetSceneName();
- rank = m_dialog->RetSceneRank();
- read = m_dialog->RetSceneRead();
- stack = m_dialog->RetStackRead();
- m_dialog->SetUserDir(base, rank);
-
- m_bFixScene = bFixScene;
-
- g_id = 0;
- m_bBase = false;
-
- if ( !bResetObject )
- {
- g_build = 0;
- g_researchDone = 0; // no research done
- g_researchEnable = 0;
-
- FlushDisplayInfo();
- m_terrain->LevelFlush();
- m_audioTrack = 0;
- m_bAudioRepeat = true;
- m_displayText->SetDelay(1.0f);
- m_displayText->SetEnable(true);
- m_bImmediatSatCom = false;
- m_endingWinRank = 0;
- m_endingLostRank = 0;
- m_endTakeTotal = 0;
- m_endTakeResearch = 0;
- m_endTakeWinDelay = 2.0f;
- m_endTakeLostDelay = 2.0f;
- m_obligatoryTotal = 0;
- m_prohibitedTotal = 0;
- m_bMapShow = true;
- m_bMapImage = false;
- m_mapFilename[0] = 0;
-
- m_colorRefBot.r = 10.0f/256.0f;
- m_colorRefBot.g = 166.0f/256.0f;
- m_colorRefBot.b = 254.0f/256.0f; // blue
- m_colorRefBot.a = 0.0f;
- m_colorNewBot = m_colorRefBot;
-
- m_colorRefAlien.r = 135.0f/256.0f;
- m_colorRefAlien.g = 170.0f/256.0f;
- m_colorRefAlien.b = 13.0f/256.0f; // green
- m_colorRefAlien.a = 0.0f;
- m_colorNewAlien = m_colorRefAlien;
-
- m_colorRefGreen.r = 135.0f/256.0f;
- m_colorRefGreen.g = 170.0f/256.0f;
- m_colorRefGreen.b = 13.0f/256.0f; // green
- m_colorRefGreen.a = 0.0f;
- m_colorNewGreen = m_colorRefGreen;
-
- m_colorRefWater.r = 25.0f/256.0f;
- m_colorRefWater.g = 255.0f/256.0f;
- m_colorRefWater.b = 240.0f/256.0f; // cyan
- m_colorRefWater.a = 0.0f;
- m_colorNewWater = m_colorRefWater;
-
- m_dialog->BuildResumeName(m_title, base, rank);
- m_dialog->BuildResumeName(m_resume, base, rank);
- GetResource(RES_TEXT, RT_SCRIPT_NEW, m_scriptName);
- m_scriptFile[0] = 0;
- }
-
- m_dialog->BuildSceneName(line, base, rank);
- file = fopen(line, "r");
- if ( file == NULL ) return;
-
- rankObj = 0;
- rankGadget = 0;
- pSel = 0;
-
- while ( fgets(line, 500, file) != NULL )
- {
- for ( i=0 ; i<500 ; i++ )
- {
- if ( line[i] == '\t' ) line[i] = ' '; // replace tab by space
- if ( line[i] == '/' && line[i+1] == '/' )
- {
- line[i] = 0;
- break;
- }
- }
-
- sprintf(op, "Title.%c", RetLanguageLetter());
- if ( Cmd(line, op) && !bResetObject )
- {
- OpString(line, "text", m_title);
- }
-
- sprintf(op, "Resume.%c", RetLanguageLetter());
- if ( Cmd(line, op) && !bResetObject )
- {
- OpString(line, "text", m_resume);
- }
-
- sprintf(op, "ScriptName.%c", RetLanguageLetter());
- if ( Cmd(line, op) && !bResetObject )
- {
- OpString(line, "text", m_scriptName);
- }
-
- if ( Cmd(line, "ScriptFile") && !bResetObject )
- {
- OpString(line, "name", m_scriptFile);
- }
-
- if ( Cmd(line, "Instructions") && !bResetObject )
- {
- OpString(line, "name", name);
-//? sprintf(m_infoFilename[SATCOM_HUSTON], "help\\%s", name);
- UserDir(m_infoFilename[SATCOM_HUSTON], name, "help");
-
- m_bImmediatSatCom = OpInt(line, "immediat", 0);
- }
-
- if ( Cmd(line, "Satellite") && !bResetObject )
- {
- OpString(line, "name", name);
-//? sprintf(m_infoFilename[SATCOM_SAT], "help\\%s", name);
- UserDir(m_infoFilename[SATCOM_SAT], name, "help");
- }
-
- if ( Cmd(line, "Loading") && !bResetObject )
- {
- OpString(line, "name", name);
-//? sprintf(m_infoFilename[SATCOM_LOADING], "help\\%s", name);
- UserDir(m_infoFilename[SATCOM_LOADING], name, "help");
- }
-
- if ( Cmd(line, "HelpFile") && !bResetObject )
- {
- OpString(line, "name", name);
-//? sprintf(m_infoFilename[SATCOM_PROG], "help\\%s", name);
- UserDir(m_infoFilename[SATCOM_PROG], name, "help");
- }
- if ( Cmd(line, "SoluceFile") && !bResetObject )
- {
- OpString(line, "name", name);
-//? sprintf(m_infoFilename[SATCOM_SOLUCE], "help\\%s", name);
- UserDir(m_infoFilename[SATCOM_SOLUCE], name, "help");
- }
-
- if ( Cmd(line, "EndingFile") && !bResetObject )
- {
- m_endingWinRank = OpInt(line, "win", 0);
- m_endingLostRank = OpInt(line, "lost", 0);
- }
-
- if ( Cmd(line, "MessageDelay") && !bResetObject )
- {
- m_displayText->SetDelay(OpFloat(line, "factor", 1.0f));
- }
-
- if ( Cmd(line, "Audio") && !bResetObject )
- {
- m_audioTrack = OpInt(line, "track", 0);
- m_bAudioRepeat = OpInt(line, "repeat", 1);
- }
-
- if ( Cmd(line, "AmbiantColor") && !bResetObject )
- {
- m_engine->SetAmbiantColor(OpColor(line, "air", 0x88888888), 0);
- m_engine->SetAmbiantColor(OpColor(line, "water", 0x88888888), 1);
- }
-
- if ( Cmd(line, "FogColor") && !bResetObject )
- {
- m_engine->SetFogColor(OpColor(line, "air", 0x88888888), 0);
- m_engine->SetFogColor(OpColor(line, "water", 0x88888888), 1);
- }
-
- if ( Cmd(line, "VehicleColor") && !bResetObject )
- {
- m_colorNewBot = RetColor(OpColor(line, "color", 0x88888888));
- }
-
- if ( Cmd(line, "InsectColor") && !bResetObject )
- {
- m_colorNewAlien = RetColor(OpColor(line, "color", 0x88888888));
- }
-
- if ( Cmd(line, "GreeneryColor") && !bResetObject )
- {
- m_colorNewGreen = RetColor(OpColor(line, "color", 0x88888888));
- }
-
- if ( Cmd(line, "DeepView") && !bResetObject )
- {
- m_engine->SetDeepView(OpFloat(line, "air", 500.0f)*UNIT, 0, true);
- m_engine->SetDeepView(OpFloat(line, "water", 100.0f)*UNIT, 1, true);
- }
-
- if ( Cmd(line, "FogStart") && !bResetObject )
- {
- m_engine->SetFogStart(OpFloat(line, "air", 0.5f), 0);
- m_engine->SetFogStart(OpFloat(line, "water", 0.5f), 1);
- }
-
- if ( Cmd(line, "SecondTexture") && !bResetObject )
- {
- m_engine->SetSecondTexture(OpInt(line, "rank", 1));
- }
-
- if ( Cmd(line, "Background") && !bResetObject )
- {
- OpString(line, "image", name);
- UserDir(dir, name, "");
- m_engine->SetBackground(dir,
- OpColor(line, "up", 0x00000000),
- OpColor(line, "down", 0x00000000),
- OpColor(line, "cloudUp", 0x00000000),
- OpColor(line, "cloudDown", 0x00000000),
- OpInt(line, "full", 0));
- }
-
- if ( Cmd(line, "Planet") && !bResetObject )
- {
- Math::Vector ppos, uv1, uv2;
-
- ppos = OpPos(line, "pos");
- uv1 = OpPos(line, "uv1");
- uv2 = OpPos(line, "uv2");
- OpString(line, "image", name);
- UserDir(dir, name, "");
- m_planet->Create(OpInt(line, "mode", 0),
- Math::Point(ppos.x, ppos.z),
- OpFloat(line, "dim", 0.2f),
- OpFloat(line, "speed", 0.0f),
- OpFloat(line, "dir", 0.0f),
- dir,
- Math::Point(uv1.x, uv1.z),
- Math::Point(uv2.x, uv2.z));
- }
-
- if ( Cmd(line, "FrontsizeName") && !bResetObject )
- {
- OpString(line, "image", name);
- UserDir(dir, name, "");
- m_engine->SetFrontsizeName(dir);
- }
-
- if ( Cmd(line, "Global") && !bResetObject )
- {
- g_unit = OpFloat(line, "unitScale", 4.0f);
- m_engine->SetTracePrecision(OpFloat(line, "traceQuality", 1.0f));
- m_bShortCut = OpInt(line, "shortcut", 1);
- }
-
- if ( Cmd(line, "TerrainGenerate") && !bResetObject )
- {
- m_terrain->Generate(OpInt(line, "mosaic", 20),
- OpInt(line, "brick", 3),
- OpFloat(line, "size", 20.0f),
- OpFloat(line, "vision", 500.0f)*UNIT,
- OpInt(line, "depth", 2),
- OpFloat(line, "hard", 0.5f));
- }
-
- if ( Cmd(line, "TerrainWind") && !bResetObject )
- {
- m_terrain->SetWind(OpPos(line, "speed"));
- }
-
- if ( Cmd(line, "TerrainRelief") && !bResetObject )
- {
- OpString(line, "image", name);
- UserDir(dir, name, "textures");
- m_terrain->ReliefFromBMP(dir, OpFloat(line, "factor", 1.0f), OpInt(line, "border", 1));
- }
-
- if ( Cmd(line, "TerrainReliefDXF") && !bResetObject )
- {
- OpString(line, "image", name);
- UserDir(dir, name, "textures");
- m_terrain->ReliefFromDXF(dir, OpFloat(line, "factor", 1.0f));
- }
-
- if ( Cmd(line, "TerrainResource") && !bResetObject )
- {
- OpString(line, "image", name);
- UserDir(dir, name, "textures");
- m_terrain->ResFromBMP(dir);
- }
-
- if ( Cmd(line, "TerrainWater") && !bResetObject )
- {
- OpString(line, "image", name);
- UserDir(dir, name, "");
- pos.x = OpFloat(line, "moveX", 0.0f);
- pos.y = OpFloat(line, "moveY", 0.0f);
- pos.z = pos.x;
- m_water->Create(OpTypeWater(line, "air", WATER_TT),
- OpTypeWater(line, "water", WATER_TT),
- dir,
- RetColor(OpColor(line, "diffuse", 0xffffffff)),
- RetColor(OpColor(line, "ambiant", 0xffffffff)),
- OpFloat(line, "level", 100.0f)*UNIT,
- OpFloat(line, "glint", 1.0f),
- pos);
- m_colorNewWater = RetColor(OpColor(line, "color", RetColor(m_colorRefWater)));
- m_colorShiftWater = OpFloat(line, "brightness", 0.0f);
- }
-
- if ( Cmd(line, "TerrainLava") && !bResetObject )
- {
- m_water->SetLava(OpInt(line, "mode", 0));
- }
-
- if ( Cmd(line, "TerrainCloud") && !bResetObject )
- {
- OpString(line, "image", name);
- UserDir(dir, name, "");
- m_cloud->Create(dir,
- RetColor(OpColor(line, "diffuse", 0xffffffff)),
- RetColor(OpColor(line, "ambiant", 0xffffffff)),
- OpFloat(line, "level", 500.0f)*UNIT);
- }
-
- if ( Cmd(line, "TerrainBlitz") && !bResetObject )
- {
- m_blitz->Create(OpFloat(line, "sleep", 0.0f),
- OpFloat(line, "delay", 3.0f),
- OpFloat(line, "magnetic", 50.0f)*UNIT);
- }
-
- if ( Cmd(line, "TerrainInitTextures") && !bResetObject )
- {
- int dx, dy, tt[100];
- char* op;
-
- OpString(line, "image", name);
- AddExt(name, ".tga");
- dx = OpInt(line, "dx", 1);
- dy = OpInt(line, "dy", 1);
- op = SearchOp(line, "table");
- for ( i=0 ; i<dx*dy ; i++ )
- {
- tt[i] = GetInt(op, i, 0);
- }
-
- if ( strstr(name, "%user%") != 0 )
- {
- CopyFileListToTemp(name, tt, dx*dy);
- }
-
- m_terrain->InitTextures(name, tt, dx, dy);
- }
-
- if ( Cmd(line, "TerrainInit") && !bResetObject )
- {
- m_terrain->LevelInit(OpInt(line, "id", 1));
- }
-
- if ( Cmd(line, "TerrainMaterial") && !bResetObject )
- {
- OpString(line, "image", name);
- AddExt(name, ".tga");
- if ( strstr(name, "%user%") != 0 )
- {
- CopyFileToTemp(name);
- }
-
- m_terrain->LevelMaterial(OpInt(line, "id", 0),
- name,
- OpFloat(line, "u", 0.0f),
- OpFloat(line, "v", 0.0f),
- OpInt(line, "up", 1),
- OpInt(line, "right", 1),
- OpInt(line, "down", 1),
- OpInt(line, "left", 1),
- OpFloat(line, "hard", 0.5f));
- }
-
- if ( Cmd(line, "TerrainLevel") && !bResetObject )
- {
- int id[50];
- char* op;
-
- op = SearchOp(line, "id");
- i = 0;
- while ( true )
- {
- id[i] = GetInt(op, i, 0);
- if ( id[i++] == 0 ) break;
- }
-
- m_terrain->LevelGenerate(id,
- OpFloat(line, "min", 0.0f)*UNIT,
- OpFloat(line, "max", 100.0f)*UNIT,
- OpFloat(line, "slope", 5.0f),
- OpFloat(line, "freq", 100.0f),
- OpPos(line, "center")*g_unit,
- OpFloat(line, "radius", 0.0f)*g_unit);
- }
-
- if ( Cmd(line, "TerrainCreate") && !bResetObject )
- {
- m_terrain->CreateObjects(true);
- }
-
- if ( Cmd(line, "BeginObject") )
- {
- InitEye();
- SetMovieLock(false);
- if ( !m_bFixScene )
- {
-//? CreateObject(Math::Vector(0.0f, 0.0f, 0.0f), 0.0f, 0.0f, OBJECT_TOTO);
- }
-
- if ( read[0] != 0 ) // loading file ?
- {
- pSel = IOReadScene(read, stack);
- }
- }
-
- if ( Cmd(line, "CreateObject") && read[0] == 0 )
- {
- CObject* pObj;
- CBrain* pBrain;
- CAuto* pAuto;
- CPyro* pyro;
- ObjectType type;
- PyroType pType;
- CameraType cType;
- Info info;
- float dir;
- char op[20];
- char text[100];
- char* p;
- int run, gadget;
-
- type = OpTypeObject(line, "type", OBJECT_NULL);
-
- gadget = OpInt(line, "gadget", -1);
- if ( gadget == -1 )
- {
- gadget = 0;
- if ( type == OBJECT_TECH ||
- (type >= OBJECT_PLANT0 &&
- type <= OBJECT_PLANT19 ) ||
- (type >= OBJECT_TREE0 &&
- type <= OBJECT_TREE9 ) ||
- (type >= OBJECT_TEEN0 &&
- type <= OBJECT_TEEN49 ) ||
- (type >= OBJECT_QUARTZ0 &&
- type <= OBJECT_QUARTZ9 ) ||
- (type >= OBJECT_ROOT0 &&
- type <= OBJECT_ROOT4 ) ) // not ROOT5!
- {
- if ( type != OBJECT_TEEN11 && // lamp?
- type != OBJECT_TEEN12 && // coke?
- type != OBJECT_TEEN20 && // wall?
- type != OBJECT_TEEN21 && // wall?
- type != OBJECT_TEEN22 && // wall?
- type != OBJECT_TEEN26 && // lamp?
- type != OBJECT_TEEN28 && // bottle?
- type != OBJECT_TEEN34 ) // stone?
- {
- gadget = 1;
- }
- }
- }
- if ( gadget != 0 ) // is this a gadget?
- {
- if ( !TestGadgetQuantity(rankGadget++) ) continue;
- }
-
- pos = OpPos(line, "pos")*g_unit;
- dir = OpFloat(line, "dir", 0.0f)*Math::PI;
- pObj = CreateObject(pos, dir,
- OpFloat(line, "z", 1.0f),
- OpFloat(line, "h", 0.0f),
- type,
- OpFloat(line, "power", 1.0f),
- OpInt(line, "trainer", 0),
- OpInt(line, "toy", 0),
- OpInt(line, "option", 0));
-
- if ( pObj != 0 )
- {
- pObj->SetDefRank(rankObj);
-
- if ( type == OBJECT_BASE ) m_bBase = true;
-
- cType = OpCamera(line, "camera");
- if ( cType != CAMERA_NULL )
- {
- pObj->SetCameraType(cType);
- }
- pObj->SetCameraDist(OpFloat(line, "cameraDist", 50.0f));
- pObj->SetCameraLock(OpInt(line, "cameraLock", 0));
-
- pType = OpPyro(line, "pyro");
- if ( pType != PT_NULL )
- {
- pyro = new CPyro(m_iMan);
- pyro->Create(pType, pObj);
- }
-
- // Puts information in terminal (OBJECT_INFO).
- for ( i=0 ; i<OBJECTMAXINFO ; i++ )
- {
- sprintf(op, "info%d", i+1);
- OpString(line, op, text);
- if ( text[0] == 0 ) break;
- p = strchr(text, '=');
- if ( p == 0 ) break;
- *p = 0;
- strcpy(info.name, text);
- sscanf(p+1, "%f", &info.value);
- pObj->SetInfo(i, info);
- }
-
- // Sets the parameters of the command line.
- p = SearchOp(line, "cmdline");
- for ( i=0 ; i<OBJECTMAXCMDLINE ; i++ )
- {
- float value;
- value = GetFloat(p, i, NAN);
- if ( value == NAN ) break;
- pObj->SetCmdLine(i, value);
- }
-
- if ( OpInt(line, "select", 0) == 1 )
- {
- pSel = pObj;
- }
-
- pObj->SetSelectable(OpInt(line, "selectable", 1));
- pObj->SetEnable(OpInt(line, "enable", 1));
- pObj->SetProxyActivate(OpInt(line, "proxyActivate", 0));
- pObj->SetProxyDistance(OpFloat(line, "proxyDistance", 15.0f)*g_unit);
- pObj->SetRange(OpFloat(line, "range", 30.0f));
- pObj->SetShield(OpFloat(line, "shield", 1.0f));
- pObj->SetMagnifyDamage(OpFloat(line, "magnifyDamage", 1.0f));
- pObj->SetClip(OpInt(line, "clip", 1));
- pObj->SetCheckToken(OpInt(line, "checkToken", 1));
- pObj->SetManual(OpInt(line, "manual", 0));
-
- motion = pObj->RetMotion();
- if ( motion != 0 )
- {
- p = SearchOp(line, "param");
- for ( i=0 ; i<10 ; i++ )
- {
- float value;
- value = GetFloat(p, i, NAN);
- if ( value == NAN ) break;
- motion->SetParam(i, value);
- }
- }
-
- run = -1;
- pBrain = pObj->RetBrain();
- if ( pBrain != 0 )
- {
- for ( i=0 ; i<10 ; i++ )
- {
- sprintf(op, "script%d", i+1); // script1..script10
- OpString(line, op, name);
-#if _SCHOOL
- if ( !m_dialog->RetSoluce4() && i == 3 ) continue;
-#endif
- if ( name[0] != 0 )
- {
- pBrain->SetScriptName(i, name);
- }
- }
-
- i = OpInt(line, "run", 0);
- if ( i != 0 )
- {
- run = i-1;
- pBrain->SetScriptRun(run);
- }
- }
- pAuto = pObj->RetAuto();
- if ( pAuto != 0 )
- {
- type = OpTypeObject(line, "autoType", OBJECT_NULL);
- pAuto->SetType(type);
- for ( i=0 ; i<5 ; i++ )
- {
- sprintf(op, "autoValue%d", i+1); // autoValue1..autoValue5
- pAuto->SetValue(i, OpFloat(line, op, 0.0f));
- }
- OpString(line, "autoString", name);
- pAuto->SetString(name);
-
- i = OpInt(line, "run", -1);
- if ( i != -1 )
- {
- if ( i != PARAM_FIXSCENE &&
- !m_dialog->RetMovies() ) i = 0;
- pAuto->Start(i); // starts the film
- }
- }
-
- OpString(line, "soluce", name);
- if ( bSoluce && pBrain != 0 && name[0] != 0 )
- {
- pBrain->SetSoluceName(name);
- }
-
- pObj->SetResetPosition(pObj->RetPosition(0));
- pObj->SetResetAngle(pObj->RetAngle(0));
- pObj->SetResetRun(run);
-
- if ( OpInt(line, "reset", 0) == 1 )
- {
- pObj->SetResetCap(RESET_MOVE);
- }
- }
-
- rankObj ++;
- }
-
- if ( Cmd(line, "CreateFog") && !bResetObject )
- {
- ParticuleType type;
- Math::Point dim;
- float height, ddim, delay;
-
- type = (ParticuleType)(PARTIFOG0+OpInt(line, "type", 0));
- pos = OpPos(line, "pos")*g_unit;
- height = OpFloat(line, "height", 1.0f)*g_unit;
- ddim = OpFloat(line, "dim", 50.0f)*g_unit;
- delay = OpFloat(line, "delay", 2.0f);
- m_terrain->MoveOnFloor(pos);
- pos.y += height;
- dim.x = ddim;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), dim, type, delay, 0.0f, 0.0f);
- }
-
- if ( Cmd(line, "CreateLight") && !bResetObject )
- {
- D3DTypeObj type;
-
- color.r = 0.5f;
- color.g = 0.5f;
- color.b = 0.5f;
- color.a = 1.0f;
- obj = CreateLight(OpDir(line, "dir"),
- OpColorValue(line, "color", color));
-
- type = OpTypeTerrain(line, "type", TYPENULL);
- if ( type == TYPETERRAIN )
- {
- m_light->SetLightIncluType(obj, TYPETERRAIN);
- }
- if ( type == TYPEQUARTZ )
- {
- m_light->SetLightIncluType(obj, TYPEQUARTZ);
- }
- if ( type == TYPEMETAL )
- {
- m_light->SetLightIncluType(obj, TYPEMETAL);
- }
- if ( type == TYPEFIX )
- {
- m_light->SetLightExcluType(obj, TYPETERRAIN);
- }
- }
- if ( Cmd(line, "CreateSpot") && !bResetObject )
- {
- D3DTypeObj type;
-
- color.r = 0.5f;
- color.g = 0.5f;
- color.b = 0.5f;
- color.a = 1.0f;
- obj = CreateSpot(OpDir(line, "pos")*g_unit,
- OpColorValue(line, "color", color));
-
- type = OpTypeTerrain(line, "type", TYPENULL);
- if ( type == TYPETERRAIN )
- {
- m_light->SetLightIncluType(obj, TYPETERRAIN);
- }
- if ( type == TYPEQUARTZ )
- {
- m_light->SetLightIncluType(obj, TYPEQUARTZ);
- }
- if ( type == TYPEMETAL )
- {
- m_light->SetLightIncluType(obj, TYPEMETAL);
- }
- if ( type == TYPEFIX )
- {
- m_light->SetLightExcluType(obj, TYPETERRAIN);
- }
- }
-
- if ( Cmd(line, "GroundSpot") && !bResetObject )
- {
- rank = m_engine->GroundSpotCreate();
- if ( rank != -1 )
- {
- m_engine->SetObjectGroundSpotPos(rank, OpPos(line, "pos")*g_unit);
- m_engine->SetObjectGroundSpotRadius(rank, OpFloat(line, "radius", 10.0f)*g_unit);
- m_engine->SetObjectGroundSpotColor(rank, RetColor(OpColor(line, "color", 0x88888888)));
- m_engine->SetObjectGroundSpotSmooth(rank, OpFloat(line, "smooth", 1.0f));
- m_engine->SetObjectGroundSpotMinMax(rank, OpFloat(line, "min", 0.0f)*g_unit,
- OpFloat(line, "max", 0.0f)*g_unit);
- }
- }
-
- if ( Cmd(line, "WaterColor") && !bResetObject )
- {
- color.r = 0.0f;
- color.g = 0.0f;
- color.b = 0.0f;
- color.a = 1.0f;
- m_engine->SetWaterAddColor(OpColorValue(line, "color", color));
- }
-
- if ( Cmd(line, "MapColor") && !bResetObject )
- {
- m_map->FloorColorMap(RetColor(OpColor(line, "floor", 0x88888888)),
- RetColor(OpColor(line, "water", 0x88888888)));
- m_bMapShow = OpInt(line, "show", 1);
- m_map->ShowMap(m_bMapShow);
- m_map->SetToy(OpInt(line, "toyIcon", 0));
- m_bMapImage = OpInt(line, "image", 0);
- if ( m_bMapImage )
- {
- Math::Vector offset;
- OpString(line, "filename", m_mapFilename);
- offset = OpPos(line, "offset");
- m_map->SetFixParam(OpFloat(line, "zoom", 1.0f),
- offset.x, offset.z,
- OpFloat(line, "angle", 0.0f)*Math::PI/180.0f,
- OpInt(line, "mode", 0),
- OpInt(line, "debug", 0));
- }
- }
- if ( Cmd(line, "MapZoom") && !bResetObject )
- {
- m_map->ZoomMap(OpFloat(line, "factor", 2.0f));
- m_map->MapEnable(OpInt(line, "enable", 1));
- }
-
- if ( Cmd(line, "MaxFlyingHeight") && !bResetObject )
- {
- m_terrain->SetFlyingMaxHeight(OpFloat(line, "max", 280.0f)*g_unit);
- }
- if ( Cmd(line, "AddFlyingHeight") && !bResetObject )
- {
- m_terrain->AddFlyingLimit(OpPos(line, "center")*g_unit,
- OpFloat(line, "extRadius", 20.0f)*g_unit,
- OpFloat(line, "intRadius", 10.0f)*g_unit,
- OpFloat(line, "maxHeight", 200.0f));
- }
-
- if ( Cmd(line, "Camera") )
- {
- m_camera->Init(OpDir(line, "eye")*g_unit,
- OpDir(line, "lookat")*g_unit,
- bResetObject?0.0f:OpFloat(line, "delay", 0.0f));
-
- if ( OpInt(line, "fadeIn", 0) == 1 )
- {
- m_camera->StartOver(OE_FADEINw, Math::Vector(0.0f, 0.0f, 0.0f), 1.0f);
- }
- m_camera->SetFixDirection(OpFloat(line, "fixDirection", 0.25f)*Math::PI);
- }
-
- if ( Cmd(line, "EndMissionTake") && !bResetObject )
- {
- i = m_endTakeTotal;
- if ( i < 10 )
- {
- m_endTake[i].pos = OpPos(line, "pos")*g_unit;
- m_endTake[i].dist = OpFloat(line, "dist", 8.0f)*g_unit;
- m_endTake[i].type = OpTypeObject(line, "type", OBJECT_NULL);
- m_endTake[i].min = OpInt(line, "min", 1);
- m_endTake[i].max = OpInt(line, "max", 9999);
- m_endTake[i].lost = OpInt(line, "lost", -1);
- m_endTake[i].bImmediat = OpInt(line, "immediat", 0);
- OpString(line, "message", m_endTake[i].message);
- m_endTakeTotal ++;
- }
- }
- if ( Cmd(line, "EndMissionDelay") && !bResetObject )
- {
- m_endTakeWinDelay = OpFloat(line, "win", 2.0f);
- m_endTakeLostDelay = OpFloat(line, "lost", 2.0f);
- }
- if ( Cmd(line, "EndMissionResearch") && !bResetObject )
- {
- m_endTakeResearch |= OpResearch(line, "type");
- }
-
- if ( Cmd(line, "ObligatoryToken") && !bResetObject )
- {
- i = m_obligatoryTotal;
- if ( i < 100 )
- {
- OpString(line, "text", m_obligatoryToken[i]);
- m_obligatoryTotal ++;
- }
- }
-
- if ( Cmd(line, "ProhibitedToken") && !bResetObject )
- {
- i = m_prohibitedTotal;
- if ( i < 100 )
- {
- OpString(line, "text", m_prohibitedToken[i]);
- m_prohibitedTotal ++;
- }
- }
-
- if ( Cmd(line, "EnableBuild") && !bResetObject )
- {
- g_build |= OpBuild(line, "type");
- }
-
- if ( Cmd(line, "EnableResearch") && !bResetObject )
- {
- g_researchEnable |= OpResearch(line, "type");
- }
- if ( Cmd(line, "DoneResearch") && read[0] == 0 && !bResetObject ) // not loading file?
- {
- g_researchDone |= OpResearch(line, "type");
- }
-
- if ( Cmd(line, "NewScript") && !bResetObject )
- {
- OpString(line, "name", name);
- AddNewScriptName(OpTypeObject(line, "type", OBJECT_NULL), name);
- }
- }
-
- fclose(file);
-
- if ( read[0] == 0 )
- {
- CompileScript(bSoluce); // compiles all scripts
- }
-
- if ( strcmp(base, "scene") == 0 && !bResetObject ) // mission?
- {
- WriteFreeParam();
- }
- if ( strcmp(base, "free") == 0 && !bResetObject ) // free play?
- {
- g_researchDone = m_freeResearch;
-
- g_build = m_freeBuild;
- g_build &= ~BUILD_RESEARCH;
- g_build &= ~BUILD_LABO;
- g_build |= BUILD_FACTORY;
- g_build |= BUILD_GFLAT;
- g_build |= BUILD_FLAG;
- }
-
- if ( !bResetObject )
- {
- ChangeColor(); // changes the colors of texture
- m_short->SetMode(false); // vehicles?
- }
-
- CreateShortcuts();
- m_map->UpdateMap();
- m_engine->TimeInit();
- m_engine->FlushPressKey();
- m_time = 0.0f;
- m_gameTime = 0.0f;
- m_checkEndTime = 0.0f;
- m_infoUsed = 0;
-
- m_selectObject = pSel;
-
- if ( !m_bBase && // no main base?
- !m_bFixScene ) // interractive scene?
- {
- if ( pSel == 0 )
- {
- pObj = SearchHuman();
- }
- else
- {
- pObj = pSel;
- }
- if ( pObj != 0 )
- {
- SelectObject(pObj);
- m_camera->SetObject(pObj);
-//? m_camera->SetType(CAMERA_BACK);
- m_camera->SetType(pObj->RetCameraType());
- }
- }
- if ( m_bFixScene )
- {
- m_camera->SetType(CAMERA_SCRIPT);
- }
-
- if ( read[0] != 0 && pSel != 0 ) // loading file?
- {
- pos = pSel->RetPosition(0);
- m_camera->Init(pos, pos, 0.0f);
- m_camera->FixCamera();
-
- SelectObject(pSel);
- m_camera->SetObject(pSel);
-
- m_bBeginSatCom = true; // message already displayed
- }
- m_dialog->SetSceneRead("");
- m_dialog->SetStackRead("");
-}
-
-// Creates an object of decoration mobile or stationary.
-
-CObject* CRobotMain::CreateObject(Math::Vector pos, float angle, float zoom, float height,
- ObjectType type, float power,
- bool bTrainer, bool bToy,
- int option)
-{
- CObject* pObject = 0;
- CAuto* automat;
-
- if ( type == OBJECT_NULL ) return 0;
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH )
- {
- bTrainer = false; // necessarily
- }
-
- if ( type == OBJECT_PORTICO ||
- type == OBJECT_BASE ||
- type == OBJECT_DERRICK ||
- type == OBJECT_FACTORY ||
- type == OBJECT_STATION ||
- type == OBJECT_CONVERT ||
- type == OBJECT_REPAIR ||
- type == OBJECT_DESTROYER||
- type == OBJECT_TOWER ||
- type == OBJECT_NEST ||
- type == OBJECT_RESEARCH ||
- type == OBJECT_RADAR ||
- type == OBJECT_INFO ||
- type == OBJECT_ENERGY ||
- type == OBJECT_LABO ||
- type == OBJECT_NUCLEAR ||
- type == OBJECT_PARA ||
- type == OBJECT_SAFE ||
- type == OBJECT_HUSTON ||
- type == OBJECT_TARGET1 ||
- type == OBJECT_TARGET2 ||
- type == OBJECT_START ||
- type == OBJECT_END )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateBuilding(pos, angle, height, type, power);
-
- automat = pObject->RetAuto();
- if ( automat != 0 )
- {
- automat->Init();
- }
- }
- else
- if ( type == OBJECT_FRET ||
- type == OBJECT_STONE ||
- type == OBJECT_URANIUM ||
- type == OBJECT_METAL ||
- type == OBJECT_POWER ||
- type == OBJECT_ATOMIC ||
- type == OBJECT_BULLET ||
- type == OBJECT_BBOX ||
- type == OBJECT_KEYa ||
- type == OBJECT_KEYb ||
- type == OBJECT_KEYc ||
- type == OBJECT_KEYd ||
- type == OBJECT_TNT ||
- type == OBJECT_SCRAP1 ||
- type == OBJECT_SCRAP2 ||
- type == OBJECT_SCRAP3 ||
- type == OBJECT_SCRAP4 ||
- type == OBJECT_SCRAP5 ||
- type == OBJECT_BOMB ||
- type == OBJECT_WAYPOINT ||
- type == OBJECT_SHOW ||
- type == OBJECT_WINFIRE ||
- type == OBJECT_BAG ||
- type == OBJECT_MARKPOWER ||
- type == OBJECT_MARKSTONE ||
- type == OBJECT_MARKURANIUM ||
- type == OBJECT_MARKKEYa ||
- type == OBJECT_MARKKEYb ||
- type == OBJECT_MARKKEYc ||
- type == OBJECT_MARKKEYd ||
- type == OBJECT_EGG )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateResource(pos, angle, type, power);
- }
- else
- if ( type == OBJECT_FLAGb ||
- type == OBJECT_FLAGr ||
- type == OBJECT_FLAGg ||
- type == OBJECT_FLAGy ||
- type == OBJECT_FLAGv )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateFlag(pos, angle, type);
- }
- else
- if ( type == OBJECT_BARRIER0 ||
- type == OBJECT_BARRIER1 ||
- type == OBJECT_BARRIER2 ||
- type == OBJECT_BARRIER3 ||
- type == OBJECT_BARRIER4 )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateBarrier(pos, angle, height, type);
- }
- else
- if ( type == OBJECT_PLANT0 ||
- type == OBJECT_PLANT1 ||
- type == OBJECT_PLANT2 ||
- type == OBJECT_PLANT3 ||
- type == OBJECT_PLANT4 ||
- type == OBJECT_PLANT5 ||
- type == OBJECT_PLANT6 ||
- type == OBJECT_PLANT7 ||
- type == OBJECT_PLANT8 ||
- type == OBJECT_PLANT9 ||
- type == OBJECT_PLANT10 ||
- type == OBJECT_PLANT11 ||
- type == OBJECT_PLANT12 ||
- type == OBJECT_PLANT13 ||
- type == OBJECT_PLANT14 ||
- type == OBJECT_PLANT15 ||
- type == OBJECT_PLANT16 ||
- type == OBJECT_PLANT17 ||
- type == OBJECT_PLANT18 ||
- type == OBJECT_PLANT19 ||
- type == OBJECT_TREE0 ||
- type == OBJECT_TREE1 ||
- type == OBJECT_TREE2 ||
- type == OBJECT_TREE3 ||
- type == OBJECT_TREE4 ||
- type == OBJECT_TREE5 ||
- type == OBJECT_TREE6 ||
- type == OBJECT_TREE7 ||
- type == OBJECT_TREE8 ||
- type == OBJECT_TREE9 )
- {
- pObject = new CObject(m_iMan);
- pObject->CreatePlant(pos, angle, height, type);
- }
- else
- if ( type == OBJECT_MUSHROOM0 ||
- type == OBJECT_MUSHROOM1 ||
- type == OBJECT_MUSHROOM2 ||
- type == OBJECT_MUSHROOM3 ||
- type == OBJECT_MUSHROOM4 ||
- type == OBJECT_MUSHROOM5 ||
- type == OBJECT_MUSHROOM6 ||
- type == OBJECT_MUSHROOM7 ||
- type == OBJECT_MUSHROOM8 ||
- type == OBJECT_MUSHROOM9 )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateMushroom(pos, angle, height, type);
- }
- else
- if ( type == OBJECT_TEEN0 ||
- type == OBJECT_TEEN1 ||
- type == OBJECT_TEEN2 ||
- type == OBJECT_TEEN3 ||
- type == OBJECT_TEEN4 ||
- type == OBJECT_TEEN5 ||
- type == OBJECT_TEEN6 ||
- type == OBJECT_TEEN7 ||
- type == OBJECT_TEEN8 ||
- type == OBJECT_TEEN9 ||
- type == OBJECT_TEEN10 ||
- type == OBJECT_TEEN11 ||
- type == OBJECT_TEEN12 ||
- type == OBJECT_TEEN13 ||
- type == OBJECT_TEEN14 ||
- type == OBJECT_TEEN15 ||
- type == OBJECT_TEEN16 ||
- type == OBJECT_TEEN17 ||
- type == OBJECT_TEEN18 ||
- type == OBJECT_TEEN19 ||
- type == OBJECT_TEEN20 ||
- type == OBJECT_TEEN21 ||
- type == OBJECT_TEEN22 ||
- type == OBJECT_TEEN23 ||
- type == OBJECT_TEEN24 ||
- type == OBJECT_TEEN25 ||
- type == OBJECT_TEEN26 ||
- type == OBJECT_TEEN27 ||
- type == OBJECT_TEEN28 ||
- type == OBJECT_TEEN29 ||
- type == OBJECT_TEEN30 ||
- type == OBJECT_TEEN31 ||
- type == OBJECT_TEEN32 ||
- type == OBJECT_TEEN33 ||
- type == OBJECT_TEEN34 ||
- type == OBJECT_TEEN35 ||
- type == OBJECT_TEEN36 ||
- type == OBJECT_TEEN37 ||
- type == OBJECT_TEEN38 ||
- type == OBJECT_TEEN39 ||
- type == OBJECT_TEEN40 ||
- type == OBJECT_TEEN41 ||
- type == OBJECT_TEEN42 ||
- type == OBJECT_TEEN43 ||
- type == OBJECT_TEEN44 ||
- type == OBJECT_TEEN45 ||
- type == OBJECT_TEEN46 ||
- type == OBJECT_TEEN47 ||
- type == OBJECT_TEEN48 ||
- type == OBJECT_TEEN49 )
- {
- pObject = new CObject(m_iMan);
- pObject->SetOption(option);
- pObject->CreateTeen(pos, angle, zoom, height, type);
- }
- else
- if ( type == OBJECT_QUARTZ0 ||
- type == OBJECT_QUARTZ1 ||
- type == OBJECT_QUARTZ2 ||
- type == OBJECT_QUARTZ3 ||
- type == OBJECT_QUARTZ4 ||
- type == OBJECT_QUARTZ5 ||
- type == OBJECT_QUARTZ6 ||
- type == OBJECT_QUARTZ7 ||
- type == OBJECT_QUARTZ8 ||
- type == OBJECT_QUARTZ9 )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateQuartz(pos, angle, height, type);
- }
- else
- if ( type == OBJECT_ROOT0 ||
- type == OBJECT_ROOT1 ||
- type == OBJECT_ROOT2 ||
- type == OBJECT_ROOT3 ||
- type == OBJECT_ROOT4 ||
- type == OBJECT_ROOT5 ||
- type == OBJECT_ROOT6 ||
- type == OBJECT_ROOT7 ||
- type == OBJECT_ROOT8 ||
- type == OBJECT_ROOT9 )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateRoot(pos, angle, height, type);
- }
- else
- if ( type == OBJECT_HOME1 )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateHome(pos, angle, height, type);
- }
- else
- if ( type == OBJECT_RUINmobilew1 ||
- type == OBJECT_RUINmobilew2 ||
- type == OBJECT_RUINmobilet1 ||
- type == OBJECT_RUINmobilet2 ||
- type == OBJECT_RUINmobiler1 ||
- type == OBJECT_RUINmobiler2 ||
- type == OBJECT_RUINfactory ||
- type == OBJECT_RUINdoor ||
- type == OBJECT_RUINsupport ||
- type == OBJECT_RUINradar ||
- type == OBJECT_RUINconvert ||
- type == OBJECT_RUINbase ||
- type == OBJECT_RUINhead )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateRuin(pos, angle, height, type);
- }
- else
- if ( type == OBJECT_APOLLO1 ||
- type == OBJECT_APOLLO3 ||
- type == OBJECT_APOLLO4 ||
- type == OBJECT_APOLLO5 )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateApollo(pos, angle, type);
- }
- else
- if ( type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateInsect(pos, angle, type); // no eggs
- }
- else
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH ||
- type == OBJECT_TOTO ||
- type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr ||
- type == OBJECT_APOLLO2 )
- {
- pObject = new CObject(m_iMan);
- pObject->SetOption(option);
- pObject->CreateVehicle(pos, angle, type, power, bTrainer, bToy);
- }
-
- if ( m_bFixScene && type == OBJECT_HUMAN )
- {
- CMotion* motion;
-
- motion = pObject->RetMotion();
- if ( m_phase == PHASE_WIN ) motion->SetAction(MHS_WIN, 0.4f);
- if ( m_phase == PHASE_LOST ) motion->SetAction(MHS_LOST, 0.5f);
- }
-
- return pObject;
-}
-
-
-// Creates the editable model.
-
-void CRobotMain::CreateModel()
-{
- Math::Vector direction;
- D3DCOLORVALUE color;
-
- m_engine->SetAmbiantColor(0xC0C0C0C0); // gray
- m_engine->SetBackground("", 0x80808080, 0x80808080, 0x80808080, 0x80808080);
- m_engine->SetFogColor(0x80808080);
- m_engine->SetDeepView(500.0f, 0);
- m_engine->SetDeepView(100.0f, 1);
- m_engine->SetFogStart(0.5f);
-
- m_model->StartUserAction();
-
- direction = Math::Vector(1.0f, -1.0f, 1.0f);
- color.r = 0.7f;
- color.g = 0.7f;
- color.b = 0.7f; // white
- CreateLight(direction, color);
-
- direction = Math::Vector(-1.0f, -1.0f, 1.0f);
- color.r = 0.7f;
- color.g = 0.7f;
- color.b = 0.7f; // white
- CreateLight(direction, color);
-
- direction = Math::Vector(1.0f, -1.0f, -1.0f);
- color.r = 0.7f;
- color.g = 0.7f;
- color.b = 0.7f; // white
- CreateLight(direction, color);
-
- direction = Math::Vector(-1.0f, -1.0f, -1.0f);
- color.r = 0.7f;
- color.g = 0.7f;
- color.b = 0.7f; // white
- CreateLight(direction, color);
-
- direction = Math::Vector(0.0f, 1.0f, 0.0f);
- color.r = 0.7f;
- color.g = 0.7f;
- color.b = 0.7f; // white
- CreateLight(direction, color);
-
- InitEye();
-
- m_engine->TimeInit();
- m_time = 0.0f;
- m_gameTime = 0.0f;
- m_checkEndTime = 0.0f;
-}
-
-
-// Creates a directional light.
-
-int CRobotMain::CreateLight(Math::Vector direction, D3DCOLORVALUE color)
-{
- D3DLIGHT7 light;
- int obj;
-
- if ( direction.x == 0.0f &&
- direction.y == 0.0f &&
- direction.z == 0.0f )
- {
- direction.y = -1.0f;
- }
-
- ZeroMemory(&light, sizeof(D3DLIGHT7));
- light.dltType = D3DLIGHT_DIRECTIONAL;
- light.dcvDiffuse.r = color.r;
- light.dcvDiffuse.g = color.g;
- light.dcvDiffuse.b = color.b;
- light.dvDirection = VEC_TO_D3DVEC(direction);
- obj = m_light->CreateLight();
- m_light->SetLight(obj, light);
-
- return obj;
-}
-
-// Creates a light spot.
-
-int CRobotMain::CreateSpot(Math::Vector pos, D3DCOLORVALUE color)
-{
- D3DLIGHT7 light;
- int obj;
-
- if ( !m_engine->RetLightMode() ) return -1;
-
- pos.y += m_terrain->RetFloorLevel(pos);
-
- ZeroMemory(&light, sizeof(D3DLIGHT7));
- light.dltType = D3DLIGHT_SPOT;
- light.dcvDiffuse.r = color.r;
- light.dcvDiffuse.g = color.g;
- light.dcvDiffuse.b = color.b;
- light.dvPosition = VEC_TO_D3DVEC(pos);
- light.dvDirection = D3DVECTOR(0.0f, -1.0f, 0.0f);
- light.dvRange = D3DLIGHT_RANGE_MAX;
- light.dvFalloff = 1.0f;
- light.dvTheta = 10.0f*Math::PI/180.0f;
- light.dvPhi = 90.0f*Math::PI/180.0f;
- light.dvAttenuation0 = 2.0f;
- light.dvAttenuation1 = 0.0f;
- light.dvAttenuation2 = 0.0f;
- obj = m_light->CreateLight();
- m_light->SetLight(obj, light);
-
- return obj;
-}
-
-
-// Change the colors and textures.
-
-void CRobotMain::ChangeColor()
-{
- D3DCOLORVALUE colorRef1, colorNew1, colorRef2, colorNew2;
- Math::Point ts, ti;
- Math::Point exclu[6];
- char name[100];
- int face;
- float tolerance;
-
- ts = Math::Point(0.0f, 0.0f);
- ti = Math::Point(1.0f, 1.0f); // the entire image
-
- colorRef1.a = 0.0f;
- colorRef2.a = 0.0f;
-
- colorRef1.r = 206.0f/256.0f;
- colorRef1.g = 206.0f/256.0f;
- colorRef1.b = 204.0f/256.0f; // ~white
- colorNew1 = m_dialog->RetGamerColorCombi();
- colorRef2.r = 255.0f/256.0f;
- colorRef2.g = 132.0f/256.0f;
- colorRef2.b = 1.0f/256.0f; // orange
- colorNew2 = m_dialog->RetGamerColorBand();
- exclu[0] = Math::Point(192.0f/256.0f, 0.0f/256.0f);
- exclu[1] = Math::Point(256.0f/256.0f, 64.0f/256.0f); // crystals + cylinders
- exclu[2] = Math::Point(208.0f/256.0f, 224.0f/256.0f);
- exclu[3] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // SatCom screen
- exclu[4] = Math::Point(0.0f, 0.0f);
- exclu[5] = Math::Point(0.0f, 0.0f); // terminator
- m_engine->ChangeColor("human.tga", colorRef1, colorNew1, colorRef2, colorNew2, 0.30f, 0.01f, ts, ti, exclu);
-
- face = RetGamerFace();
- if ( face == 0 ) // normal?
- {
- colorRef1.r = 90.0f/256.0f;
- colorRef1.g = 95.0f/256.0f;
- colorRef1.b = 85.0f/256.0f; // black
- tolerance = 0.15f;
- }
- if ( face == 1 ) // bald?
- {
- colorRef1.r = 74.0f/256.0f;
- colorRef1.g = 58.0f/256.0f;
- colorRef1.b = 46.0f/256.0f; // brown
- tolerance = 0.20f;
- }
- if ( face == 2 ) // carlos?
- {
- colorRef1.r = 70.0f/256.0f;
- colorRef1.g = 40.0f/256.0f;
- colorRef1.b = 8.0f/256.0f; // brown
- tolerance = 0.30f;
- }
- if ( face == 3 ) // blonde?
- {
- colorRef1.r = 74.0f/256.0f;
- colorRef1.g = 16.0f/256.0f;
- colorRef1.b = 0.0f/256.0f; // yellow
- tolerance = 0.20f;
- }
- colorNew1 = m_dialog->RetGamerColorHair();
- colorRef2.r = 0.0f;
- colorRef2.g = 0.0f;
- colorRef2.b = 0.0f;
- colorNew2.r = 0.0f;
- colorNew2.g = 0.0f;
- colorNew2.b = 0.0f;
- sprintf(name, "face%.2d.tga", face+1);
- exclu[0] = Math::Point(105.0f/256.0f, 47.0f/166.0f);
- exclu[1] = Math::Point(153.0f/256.0f, 79.0f/166.0f); // blue canister
- exclu[2] = Math::Point(0.0f, 0.0f);
- exclu[3] = Math::Point(0.0f, 0.0f); // terminator
- m_engine->ChangeColor(name, colorRef1, colorNew1, colorRef2, colorNew2, tolerance, 0.00f, ts, ti, exclu);
-
- colorRef2.r = 0.0f;
- colorRef2.g = 0.0f;
- colorRef2.b = 0.0f;
- colorNew2.r = 0.0f;
- colorNew2.g = 0.0f;
- colorNew2.b = 0.0f;
-
- m_engine->ChangeColor("base1.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
- m_engine->ChangeColor("convert.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
- m_engine->ChangeColor("derrick.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
- m_engine->ChangeColor("factory.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
- m_engine->ChangeColor("lemt.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
- m_engine->ChangeColor("roller.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
- m_engine->ChangeColor("search.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
-
- exclu[0] = Math::Point( 0.0f/256.0f, 160.0f/256.0f);
- exclu[1] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // pencils
- exclu[2] = Math::Point(0.0f, 0.0f);
- exclu[3] = Math::Point(0.0f, 0.0f); // terminator
- m_engine->ChangeColor("drawer.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true);
-
- exclu[0] = Math::Point(237.0f/256.0f, 176.0f/256.0f);
- exclu[1] = Math::Point(256.0f/256.0f, 220.0f/256.0f); // blue canister
- exclu[2] = Math::Point(106.0f/256.0f, 150.0f/256.0f);
- exclu[3] = Math::Point(130.0f/256.0f, 214.0f/256.0f); // safe location
- exclu[4] = Math::Point(0.0f, 0.0f);
- exclu[5] = Math::Point(0.0f, 0.0f); // terminator
- m_engine->ChangeColor("subm.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true);
-
- exclu[0] = Math::Point(128.0f/256.0f, 160.0f/256.0f);
- exclu[1] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // SatCom
- exclu[2] = Math::Point(0.0f, 0.0f);
- exclu[3] = Math::Point(0.0f, 0.0f); // terminator
- m_engine->ChangeColor("ant.tga", m_colorRefAlien, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti, exclu);
- m_engine->ChangeColor("mother.tga", m_colorRefAlien, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti);
-
- m_engine->ChangeColor("plant.tga", m_colorRefGreen, m_colorNewGreen, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti);
-
- // PARTIPLOUF0 and PARTIDROP :
- ts = Math::Point(0.500f, 0.500f);
- ti = Math::Point(0.875f, 0.750f);
- m_engine->ChangeColor("effect00.tga", m_colorRefWater, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, 0, m_colorShiftWater, true);
-
- // PARTIFLIC :
- ts = Math::Point(0.00f, 0.75f);
- ti = Math::Point(0.25f, 1.00f);
- m_engine->ChangeColor("effect02.tga", m_colorRefWater, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, 0, m_colorShiftWater, true);
-}
-
-// Updates the number of unnecessary objects.
-
-bool CRobotMain::TestGadgetQuantity(int rank)
-{
- float percent;
- int *table;
-
- static int table10[10] = {0,1,0,0,0,0,0,0,0,0};
- static int table20[10] = {0,1,0,0,0,1,0,0,0,0};
- static int table30[10] = {0,1,0,1,0,1,0,0,0,0};
- static int table40[10] = {0,1,0,1,0,1,0,1,0,0};
- static int table50[10] = {0,1,0,1,0,1,0,1,0,1};
- static int table60[10] = {0,1,0,1,1,1,0,1,0,1};
- static int table70[10] = {0,1,0,1,1,1,0,1,1,1};
- static int table80[10] = {0,1,1,1,1,1,0,1,1,1};
- static int table90[10] = {0,1,1,1,1,1,1,1,1,1};
-
- percent = m_engine->RetGadgetQuantity();
- if ( percent == 0.0f ) return false;
- if ( percent == 1.0f ) return true;
-
- if ( percent <= 0.15f ) table = table10;
- else if ( percent <= 0.25f ) table = table20;
- else if ( percent <= 0.35f ) table = table30;
- else if ( percent <= 0.45f ) table = table40;
- else if ( percent <= 0.55f ) table = table50;
- else if ( percent <= 0.65f ) table = table60;
- else if ( percent <= 0.75f ) table = table70;
- else if ( percent <= 0.85f ) table = table80;
- else table = table90;
-
- return table[rank%10];
-}
-
-
-
-// Calculates the distance to the nearest object.
-
-float CRobotMain::SearchNearestObject(Math::Vector center, CObject *exclu)
-{
- CObject* pObj;
- ObjectType type;
- Math::Vector oPos;
- float min, dist, oRadius;
- int i, j;
-
- min = 100000.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object carries?
- if ( pObj == exclu ) continue;
-
- type = pObj->RetType();
-
- if ( type == OBJECT_BASE )
- {
- oPos = pObj->RetPosition(0);
- if ( oPos.x != center.x ||
- oPos.z != center.z )
- {
- dist = Math::Distance(center, oPos)-80.0f;
- if ( dist < 0.0f ) dist = 0.0f;
- min = Math::Min(min, dist);
- continue;
- }
- }
-
- if ( type == OBJECT_STATION ||
- type == OBJECT_REPAIR ||
- type == OBJECT_DESTROYER )
- {
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(center, oPos)-8.0f;
- if ( dist < 0.0f ) dist = 0.0f;
- min = Math::Min(min, dist);
- }
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- dist = Math::Distance(center, oPos)-oRadius;
- if ( dist < 0.0f ) dist = 0.0f;
- min = Math::Min(min, dist);
- }
- }
- return min;
-}
-
-// Calculates a free space.
-
-bool CRobotMain::FreeSpace(Math::Vector &center, float minRadius, float maxRadius,
- float space, CObject *exclu)
-{
- Math::Vector pos;
- Math::Point p;
- float radius, ia, angle, dist, flat;
-
- if ( minRadius < maxRadius ) // from internal to external?
- {
- for ( radius=minRadius ; radius<=maxRadius ; radius+=space )
- {
- ia = space/radius;
- for ( angle=0.0f ; angle<Math::PI*2.0f ; angle+=ia )
- {
- p.x = center.x+radius;
- p.y = center.z;
- p = Math::RotatePoint(Math::Point(center.x, center.z), angle, p);
- pos.x = p.x;
- pos.z = p.y;
- pos.y = 0.0f;
- m_terrain->MoveOnFloor(pos, true);
- dist = SearchNearestObject(pos, exclu);
- if ( dist >= space )
- {
- flat = m_terrain->RetFlatZoneRadius(pos, dist/2.0f);
- if ( flat >= dist/2.0f )
- {
- center = pos;
- return true;
- }
- }
- }
- }
- }
- else // from external to internal?
- {
- for ( radius=maxRadius ; radius>=minRadius ; radius-=space )
- {
- ia = space/radius;
- for ( angle=0.0f ; angle<Math::PI*2.0f ; angle+=ia )
- {
- p.x = center.x+radius;
- p.y = center.z;
- p = Math::RotatePoint(Math::Point(center.x, center.z), angle, p);
- pos.x = p.x;
- pos.z = p.y;
- pos.y = 0.0f;
- m_terrain->MoveOnFloor(pos, true);
- dist = SearchNearestObject(pos, exclu);
- if ( dist >= space )
- {
- flat = m_terrain->RetFlatZoneRadius(pos, dist/2.0f);
- if ( flat >= dist/2.0f )
- {
- center = pos;
- return true;
- }
- }
- }
- }
- }
- return false;
-}
-
-// Calculates the maximum radius of a free space.
-
-float CRobotMain::RetFlatZoneRadius(Math::Vector center, float maxRadius,
- CObject *exclu)
-{
- float dist;
-
- dist = SearchNearestObject(center, exclu);
- if ( dist == 0.0f ) return 0.0f;
- if ( dist < maxRadius )
- {
- maxRadius = dist;
- }
- return m_terrain->RetFlatZoneRadius(center, maxRadius);
-}
-
-
-// Hides buildable area when a cube of metal is taken up.
-
-void CRobotMain::HideDropZone(CObject* metal)
-{
- if ( m_showLimit[1].bUsed &&
- m_showLimit[1].link == metal )
- {
- FlushShowLimit(1);
- }
-
- if ( m_showLimit[2].bUsed &&
- m_showLimit[2].link == metal )
- {
- FlushShowLimit(2);
- }
-}
-
-// Shows the buildable area when a cube of metal is deposited.
-
-void CRobotMain::ShowDropZone(CObject* metal, CObject* truck)
-{
- CObject* pObj;
- ObjectType type;
- Math::Vector center, oPos;
- float oMax, tMax, dist, oRadius, radius;
- int i, j;
-
- if ( metal == 0 ) return;
-
- center = metal->RetPosition(0);
-
- // Calculates the maximum radius possible depending on other items.
- oMax = 30.0f; // radius to build the biggest building
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object carried?
- if ( pObj == metal ) continue;
- if ( pObj == truck ) continue;
-
- type = pObj->RetType();
- if ( type == OBJECT_BASE )
- {
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(center, oPos)-80.0f;
- oMax = Math::Min(oMax, dist);
- }
- else
- {
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- dist = Math::Distance(center, oPos)-oRadius;
- oMax = Math::Min(oMax, dist);
- }
- }
-
- if ( type == OBJECT_DERRICK ||
- type == OBJECT_FACTORY ||
- type == OBJECT_STATION ||
- type == OBJECT_CONVERT ||
- type == OBJECT_REPAIR ||
- type == OBJECT_DESTROYER||
- type == OBJECT_TOWER ||
- type == OBJECT_RESEARCH ||
- type == OBJECT_RADAR ||
- type == OBJECT_ENERGY ||
- type == OBJECT_LABO ||
- type == OBJECT_NUCLEAR ||
- type == OBJECT_START ||
- type == OBJECT_END ||
- type == OBJECT_INFO ||
- type == OBJECT_PARA ||
- type == OBJECT_SAFE ||
- type == OBJECT_HUSTON ) // building?
- {
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- dist = Math::Distance(center, oPos)-oRadius-BUILDMARGIN;
- oMax = Math::Min(oMax, dist);
- }
- }
- }
-
- // Calculates the maximum possible radius depending on terrain.
- if ( oMax >= 2.0f )
- {
- tMax = m_terrain->RetFlatZoneRadius(center, 30.0f);
- }
- else
- {
- tMax = 0.0f;
- }
-
- radius = Math::Min(oMax, tMax);
- if ( radius >= 2.0f )
- {
- SetShowLimit(1, PARTILIMIT2, metal, center, radius, 10.0f);
- }
-}
-
-// Erases the boundaries shown.
-
-void CRobotMain::FlushShowLimit(int i)
-{
- int j;
-
- if ( m_showLimit[i].link != 0 )
- {
- m_showLimit[i].link->StopShowLimit();
- }
-
- for ( j=0 ; j<m_showLimit[i].total ; j++ )
- {
- if ( m_showLimit[i].parti[j] == 0 ) continue;
-
- m_particule->DeleteParticule(m_showLimit[i].parti[j]);
- m_showLimit[i].parti[j] = 0;
- }
-
- m_showLimit[i].total = 0;
- m_showLimit[i].link = 0;
- m_showLimit[i].bUsed = false;
-}
-
-// Specifies the boundaries to show.
-
-void CRobotMain::SetShowLimit(int i, ParticuleType parti, CObject *pObj,
- Math::Vector pos, float radius, float duration)
-{
- Math::Point dim;
- float dist;
- int j;
-
- FlushShowLimit(i); // erases the current boundaries
-
- if ( radius <= 0.0f ) return;
-
- if ( radius <= 50.0f )
- {
- dim = Math::Point(0.3f, 0.3f);
- dist = 2.5f;
- }
- else
- {
- dim = Math::Point(1.5f, 1.5f);
- dist = 10.0f;
- }
-
- m_showLimit[i].bUsed = true;
- m_showLimit[i].link = pObj;
- m_showLimit[i].pos = pos;
- m_showLimit[i].radius = radius;
- m_showLimit[i].duration = duration;
- m_showLimit[i].total = (int)((radius*2.0f*Math::PI)/dist);
- if ( m_showLimit[i].total > MAXSHOWPARTI ) m_showLimit[i].total = MAXSHOWPARTI;
- m_showLimit[i].time = 0.0f;
-
- for ( j=0 ; j<m_showLimit[i].total ; j++ )
- {
- m_showLimit[i].parti[j] = m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), dim, parti, duration);
- }
-}
-
-// Adjusts the boundaries to show.
-
-void CRobotMain::AdjustShowLimit(int i, Math::Vector pos)
-{
- m_showLimit[i].pos = pos;
-}
-
-// Mount the boundaries of the selected object.
-
-void CRobotMain::StartShowLimit()
-{
- CObject* pObj;
-
- pObj = RetSelect();
- if ( pObj == 0 ) return;
-
- pObj->StartShowLimit();
-}
-
-// Advances the boundaries shown.
-
-void CRobotMain::FrameShowLimit(float rTime)
-{
- Math::Vector pos;
- Math::Point center, rotate;
- float angle, factor, speed;
- int i, j;
-
- if ( m_engine->RetPause() ) return;
-
- for ( i=0 ; i<MAXSHOWLIMIT ; i++ )
- {
- if ( !m_showLimit[i].bUsed ) continue;
-
- m_showLimit[i].time += rTime;
-
- if ( m_showLimit[i].time >= m_showLimit[i].duration )
- {
- FlushShowLimit(i);
- continue;
- }
-
- if ( m_showLimit[i].time < 1.0f )
- {
- factor = m_showLimit[i].time;
- }
- else if ( m_showLimit[i].time > m_showLimit[i].duration-1.0f )
- {
- factor = m_showLimit[i].duration-m_showLimit[i].time;
- }
- else
- {
- factor = 1.0f;
- }
-
- speed = 0.4f-m_showLimit[i].radius*0.001f;
- if ( speed < 0.1f ) speed = 0.1f;
- angle = m_showLimit[i].time*speed;
-
- for ( j=0 ; j<m_showLimit[i].total ; j++ )
- {
- if ( m_showLimit[i].parti[j] == 0 ) continue;
-
- center.x = m_showLimit[i].pos.x;
- center.y = m_showLimit[i].pos.z;
- rotate.x = center.x+m_showLimit[i].radius*factor;
- rotate.y = center.y;
- rotate = Math::RotatePoint(center, angle, rotate);
-
- pos.x = rotate.x;
- pos.z = rotate.y;
- pos.y = 0.0f;
- m_terrain->MoveOnFloor(pos, true);
- if ( m_showLimit[i].radius <= 50.0f ) pos.y += 0.5f;
- else pos.y += 2.0f;
- m_particule->SetPosition(m_showLimit[i].parti[j], pos);
-//? m_particule->SetAngle(m_showLimit[i].parti[j], angle-Math::PI/2.0f);
-
- angle += (2.0f*Math::PI)/m_showLimit[i].total;
- }
- }
-}
-
-
-
-// Returns a pointer to the last backslash in a filename.
-
-char* SearchLastDir(char *filename)
-{
- char* p = filename;
-
- while ( *p++ != 0 );
- p --; // ^on the zero terminator
-
- while ( p != filename )
- {
- if ( *(--p) == '\\' ) return p;
- }
- return 0;
-}
-
-
-// Compiles all scripts of robots.
-
-void CRobotMain::CompileScript(bool bSoluce)
-{
- CObject* pObj;
- CBrain* brain;
- int i, j, nbError, lastError, run;
- char* name;
-
- nbError = 0;
- do
- {
- lastError = nbError;
- nbError = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
- if ( pObj->RetTruck() != 0 ) continue;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) continue;
-
- for ( j=0 ; j<10 ; j++ )
- {
- if ( brain->RetCompile(j) ) continue;
-
- name = brain->RetScriptName(j);
- if ( name[0] != 0 )
- {
- brain->ReadProgram(j, name);
- if ( !brain->RetCompile(j) ) nbError++;
- }
- }
-
- LoadOneScript(pObj, nbError);
- }
- }
- while ( nbError > 0 && nbError != lastError );
-
- // Load all solutions.
- if ( bSoluce )
- {
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
- if ( pObj->RetTruck() != 0 ) continue;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) continue;
-
- name = brain->RetSoluceName();
- if ( name[0] != 0 )
- {
- brain->ReadSoluce(name); // load solution
- }
- }
- }
-
- // Start all programs according to the command "run".
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
- if ( pObj->RetTruck() != 0 ) continue;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) continue;
-
- run = brain->RetScriptRun();
- if ( run != -1 )
- {
- brain->RunProgram(run); // starts the program
- }
- }
-}
-
-// Load all programs of the robot.
-
-void CRobotMain::LoadOneScript(CObject *pObj, int &nbError)
-{
- ObjectType type;
- CBrain* brain;
- char filename[_MAX_FNAME];
- char* name;
- int rank, i, objRank;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) return;
-
- if ( !IsSelectable(pObj) ) return;
-
- type = pObj->RetType();
- if ( type == OBJECT_HUMAN ) return;
-
- objRank = pObj->RetDefRank();
- if ( objRank == -1 ) return;
-
- name = m_dialog->RetSceneName();
- rank = m_dialog->RetSceneRank();
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- if ( brain->RetCompile(i) ) continue;
-//? if ( brain->ProgramExist(i) ) continue;
-
- sprintf(filename, "%s\\%s\\%c%.3d%.3d%.1d.txt",
- RetSavegameDir(), m_gamerName, name[0], rank, objRank, i);
- brain->ReadProgram(i, filename);
- if ( !brain->RetCompile(i) ) nbError++;
- }
-}
-
-// Load all programs of the robot.
-
-void CRobotMain::LoadFileScript(CObject *pObj, char* filename, int objRank,
- int &nbError)
-{
- ObjectType type;
- CBrain* brain;
- char fn[_MAX_FNAME];
- char* ldir;
- char* name;
- int rank, i;
-
- if ( objRank == -1 ) return;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) return;
-
- type = pObj->RetType();
- if ( type == OBJECT_HUMAN ) return;
-
- name = m_dialog->RetSceneName();
- rank = m_dialog->RetSceneRank();
-
- strcpy(fn, filename);
- ldir = SearchLastDir(fn);
- if ( ldir == 0 ) return;
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- if ( brain->RetCompile(i) ) continue;
-//? if ( brain->ProgramExist(i) ) continue;
-
- sprintf(ldir, "\\prog%.3d%.1d.txt", objRank, i);
- brain->ReadProgram(i, fn);
- if ( !brain->RetCompile(i) ) nbError++;
- }
-}
-
-// Saves all programs of all the robots.
-
-void CRobotMain::SaveAllScript()
-{
- CObject* pObj;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- SaveOneScript(pObj);
- }
-}
-
-// Saves all programs of the robot.
-// If a program does not exist, the corresponding file is destroyed.
-
-void CRobotMain::SaveOneScript(CObject *pObj)
-{
- ObjectType type;
- CBrain* brain;
- char filename[_MAX_FNAME];
- char* name;
- int rank, i, objRank;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) return;
-
- if ( !IsSelectable(pObj) ) return;
-
- type = pObj->RetType();
- if ( type == OBJECT_HUMAN ) return;
-
- objRank = pObj->RetDefRank();
- if ( objRank == -1 ) return;
-
- name = m_dialog->RetSceneName();
- rank = m_dialog->RetSceneRank();
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- sprintf(filename, "%s\\%s\\%c%.3d%.3d%.1d.txt",
- RetSavegameDir(), m_gamerName, name[0], rank, objRank, i);
- brain->WriteProgram(i, filename);
- }
-}
-
-// Saves all programs of the robot.
-// If a program does not exist, the corresponding file is destroyed.
-
-void CRobotMain::SaveFileScript(CObject *pObj, char* filename, int objRank)
-{
- ObjectType type;
- CBrain* brain;
- char fn[_MAX_FNAME];
- char* ldir;
- char* name;
- int rank, i;
-
- if ( objRank == -1 ) return;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) return;
-
- type = pObj->RetType();
- if ( type == OBJECT_HUMAN ) return;
-
- name = m_dialog->RetSceneName();
- rank = m_dialog->RetSceneRank();
-
- strcpy(fn, filename);
- ldir = SearchLastDir(fn);
- if ( ldir == 0 ) return;
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- sprintf(ldir, "\\prog%.3d%.1d.txt", objRank, i);
- brain->WriteProgram(i, fn);
- }
-}
-
-// Saves the stack of the program in execution of a robot.
-
-bool CRobotMain::SaveFileStack(CObject *pObj, FILE *file, int objRank)
-{
- ObjectType type;
- CBrain* brain;
-
- if ( objRank == -1 ) return true;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) return true;
-
- type = pObj->RetType();
- if ( type == OBJECT_HUMAN ) return true;
-
- return brain->WriteStack(file);
-}
-
-// Resumes the execution stack of the program in a robot.
-
-bool CRobotMain::ReadFileStack(CObject *pObj, FILE *file, int objRank)
-{
- ObjectType type;
- CBrain* brain;
-
- if ( objRank == -1 ) return true;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) return true;
-
- type = pObj->RetType();
- if ( type == OBJECT_HUMAN ) return true;
-
- return brain->ReadStack(file);
-}
-
-
-// Empty the list.
-
-bool CRobotMain::FlushNewScriptName()
-{
- int i;
-
- for ( i=0 ; i<MAXNEWSCRIPTNAME ; i++ )
- {
- m_newScriptName[i].bUsed = false;
- }
- return true;
-}
-
-// Adds a script name.
-
-bool CRobotMain::AddNewScriptName(ObjectType type, char *name)
-{
- int i;
-
- for ( i=0 ; i<MAXNEWSCRIPTNAME ; i++ )
- {
- if ( !m_newScriptName[i].bUsed )
- {
- m_newScriptName[i].bUsed = true;
- m_newScriptName[i].type = type;
- strcpy(m_newScriptName[i].name, name);
- return true;
- }
- }
- return false;
-}
-
-// Seeks a script name for a given type.
-
-char* CRobotMain::RetNewScriptName(ObjectType type, int rank)
-{
- int i;
-
- for ( i=0 ; i<MAXNEWSCRIPTNAME ; i++ )
- {
- if ( m_newScriptName[i].bUsed &&
- (m_newScriptName[i].type == type ||
- m_newScriptName[i].type == OBJECT_NULL ) )
- {
- if ( rank == 0 ) return m_newScriptName[i].name;
- else rank --;
- }
- }
-
- return 0;
-}
-
-
-// Seeks if an object occupies in a spot, to prevent a backup of the game.
-
-bool CRobotMain::IsBusy()
-{
- CObject* pObj;
- CBrain* pBrain;
-//? CAuto* pAuto;
- int i;
-
- if ( m_CompteurFileOpen > 0 ) return true;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- pBrain = pObj->RetBrain();
- if ( pBrain != 0 )
- {
- if ( pBrain->IsBusy() ) return true;
- }
-
-//? pAuto = pObj->RetAuto();
-//? if ( pAuto != 0 )
-//? {
-//? if ( pAuto->RetBusy() ) return true;
-//? }
- }
- return false;
-}
-
-// Writes an object into the backup file.
-
-void CRobotMain::IOWriteObject(FILE *file, CObject* pObj, char *cmd)
-{
- Math::Vector pos;
- CBrain* pBrain;
- char line[3000];
- char name[100];
- int run, i;
-
- if ( pObj->RetType() == OBJECT_FIX ) return;
-
- strcpy(line, cmd);
-
- sprintf(name, " type=%s", GetTypeObject(pObj->RetType()));
- strcat(line, name);
-
- sprintf(name, " id=%d", pObj->RetID());
- strcat(line, name);
-
- pos = pObj->RetPosition(0)/g_unit;
- sprintf(name, " pos=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
- strcat(line, name);
-
- pos = pObj->RetAngle(0)/(Math::PI/180.0f);
- sprintf(name, " angle=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
- strcat(line, name);
-
- pos = pObj->RetZoom(0);
- sprintf(name, " zoom=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
- strcat(line, name);
-
- for ( i=1 ; i<OBJECTMAXPART ; i++ )
- {
- if ( pObj->RetObjectRank(i) == -1 ) continue;
-
- pos = pObj->RetPosition(i);
- if ( pos.x != 0.0f || pos.y != 0.0f || pos.z != 0.0f )
- {
- pos /= g_unit;
- sprintf(name, " p%d=%.2f;%.2f;%.2f", i, pos.x, pos.y, pos.z);
- strcat(line, name);
- }
-
- pos = pObj->RetAngle(i);
- if ( pos.x != 0.0f || pos.y != 0.0f || pos.z != 0.0f )
- {
- pos /= (Math::PI/180.0f);
- sprintf(name, " a%d=%.2f;%.2f;%.2f", i, pos.x, pos.y, pos.z);
- strcat(line, name);
- }
-
- pos = pObj->RetZoom(i);
- if ( pos.x != 1.0f || pos.y != 1.0f || pos.z != 1.0f )
- {
- sprintf(name, " z%d=%.2f;%.2f;%.2f", i, pos.x, pos.y, pos.z);
- strcat(line, name);
- }
- }
-
- sprintf(name, " trainer=%d", pObj->RetTrainer());
- strcat(line, name);
-
- sprintf(name, " option=%d", pObj->RetOption());
- strcat(line, name);
-
- if ( pObj == m_infoObject ) // selects object?
- {
- sprintf(name, " select=1");
- strcat(line, name);
- }
-
- pObj->Write(line);
-
- if ( pObj->RetType() == OBJECT_BASE )
- {
- sprintf(name, " run=3"); // stops and open (PARAM_FIXSCENE)
- strcat(line, name);
- }
-
- pBrain = pObj->RetBrain();
- if ( pBrain != 0 )
- {
- run = pBrain->RetProgram();
- if ( run != -1 )
- {
- sprintf(name, " run=%d", run+1);
- strcat(line, name);
- }
- }
-
- strcat(line, "\n");
- fputs(line, file);
-}
-
-// Saves the current game.
-
-bool CRobotMain::IOWriteScene(char *filename, char *filecbot, char *info)
-{
- FILE* file;
- char line[500];
- char* name;
- CObject *pObj, *pPower, *pFret;
- float sleep, delay, magnetic, progress;
- int i, objRank;
- long version;
-
- file = fopen(filename, "w");
- if ( file == NULL ) return false;
-
- sprintf(line, "Title text=\"%s\"\n", info);
- fputs(line, file);
-
- sprintf(line, "Version maj=%d min=%d\n", 0, 1);
- fputs(line, file);
-
- name = m_dialog->RetSceneName();
- if ( strcmp(name, "user") == 0 )
- {
- sprintf(line, "Mission base=\"%s\" rank=%.3d dir=\"%s\"\n", name, m_dialog->RetSceneRank(), m_dialog->RetSceneDir());
- }
- else
- {
- sprintf(line, "Mission base=\"%s\" rank=%.3d\n", name, m_dialog->RetSceneRank());
- }
- fputs(line, file);
-
- sprintf(line, "Map zoom=%.2f\n", m_map->RetZoomMap());
- fputs(line, file);
-
- sprintf(line, "DoneResearch bits=%d\n", g_researchDone);
- fputs(line, file);
-
- if ( m_blitz->GetStatus(sleep, delay, magnetic, progress) )
- {
- sprintf(line, "BlitzMode sleep=%.2f delay=%.2f magnetic=%.2f progress=%.2f\n", sleep, delay, magnetic/g_unit, progress);
- fputs(line, file);
- }
-
- objRank = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetType() == OBJECT_TOTO ) continue;
- if ( pObj->RetType() == OBJECT_FIX ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
- if ( pObj->RetBurn() ) continue;
- if ( pObj->RetDead() ) continue;
- if ( pObj->RetExplo() ) continue;
-
- pPower = pObj->RetPower();
- pFret = pObj->RetFret();
-
- if ( pFret != 0 ) // object transported?
- {
- IOWriteObject(file, pFret, "CreateFret");
- }
-
- if ( pPower != 0 ) // battery transported?
- {
- IOWriteObject(file, pPower, "CreatePower");
- }
-
- IOWriteObject(file, pObj, "CreateObject");
-
- SaveFileScript(pObj, filename, objRank++);
- }
- fclose(file);
-
-#if CBOT_STACK
- // Writes the file of stacks of execution.
- file = fOpen(filecbot, "wb");
- if ( file == NULL ) return false;
-
- version = 1;
- fWrite(&version, sizeof(long), 1, file); // version of COLOBOT
- version = CBotProgram::GivVersion();
- fWrite(&version, sizeof(long), 1, file); // version of CBOT
-
- objRank = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetType() == OBJECT_TOTO ) continue;
- if ( pObj->RetType() == OBJECT_FIX ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
- if ( pObj->RetBurn() ) continue;
- if ( pObj->RetDead() ) continue;
-
- if ( !SaveFileStack(pObj, file, objRank++) ) break;
- }
- CBotClass::SaveStaticState(file);
- fClose(file);
-#endif
-
- m_delayWriteMessage = 4; // displays message in 3 frames
- return true;
-}
-
-// Resumes the game.
-
-CObject* CRobotMain::IOReadObject(char *line, char* filename, int objRank)
-{
- CObject* pObj;
-//? CBrain* pBrain;
- CAuto* pAuto;
- Math::Vector pos, dir, zoom;
- ObjectType type;
- int id, run, trainer, toy, option, i;
- char op[10];
-
- pos = OpDir(line, "pos")*g_unit;
- dir = OpDir(line, "angle")*(Math::PI/180.0f);
- zoom = OpDir(line, "zoom");
- type = OpTypeObject(line, "type", OBJECT_NULL);
- id = OpInt(line, "id", 0);
- if ( type == OBJECT_NULL ) return 0;
- trainer = OpInt(line, "trainer", 0);
- toy = OpInt(line, "toy", 0);
- option = OpInt(line, "option", 0);
- pObj = CreateObject(pos, dir.y, 1.0f, 0.0f, type, 0.0f, trainer, toy, option);
- pObj->SetDefRank(objRank);
- pObj->SetPosition(0, pos);
- pObj->SetAngle(0, dir);
- pObj->SetID(id);
- if ( g_id < id ) g_id = id;
-
- if ( zoom.x != 0.0f || zoom.y != 0.0f || zoom.z != 0.0f )
- {
- pObj->SetZoom(0, zoom);
- }
-
- for ( i=1 ; i<OBJECTMAXPART ; i++ )
- {
- if ( pObj->RetObjectRank(i) == -1 ) continue;
-
- sprintf(op, "p%d", i);
- pos = OpDir(line, op);
- if ( pos.x != 0.0f || pos.y != 0.0f || pos.z != 0.0f )
- {
- pObj->SetPosition(i, pos*g_unit);
- }
-
- sprintf(op, "a%d", i);
- dir = OpDir(line, op);
- if ( dir.x != 0.0f || dir.y != 0.0f || dir.z != 0.0f )
- {
- pObj->SetAngle(i, dir*(Math::PI/180.0f));
- }
-
- sprintf(op, "z%d", i);
- zoom = OpDir(line, op);
- if ( zoom.x != 0.0f || zoom.y != 0.0f || zoom.z != 0.0f )
- {
- pObj->SetZoom(i, zoom);
- }
- }
-
- if ( type == OBJECT_BASE ) m_bBase = true;
-
- pObj->Read(line);
-
-#if CBOT_STACK
-#else
- LoadFileScript(pObj, filename, objRank, i);
-#endif
-
- run = OpInt(line, "run", -1);
- if ( run != -1 )
- {
-#if CBOT_STACK
-#else
- pBrain = pObj->RetBrain();
- if ( pBrain != 0 )
- {
- pBrain->RunProgram(run-1); // starts the program
- }
-#endif
-
- pAuto = pObj->RetAuto();
- if ( pAuto != 0 )
- {
- pAuto->Start(run); // starts the film
- }
- }
-
- return pObj;
-}
-
-// Resumes some part of the game.
-
-CObject* CRobotMain::IOReadScene(char *filename, char *filecbot)
-{
- FILE* file;
- CObject *pObj, *pPower, *pFret, *pSel;
- char line[3000];
- float sleep, delay, progress, magnetic;
- int i, objRank, nbError, lastError;
- long version;
-
- m_bBase = false;
-
- file = fopen(filename, "r");
- if ( file == NULL ) return 0;
-
- pFret = 0;
- pPower = 0;
- pSel = 0;
- objRank = 0;
- while ( fgets(line, 3000, file) != NULL )
- {
- for ( i=0 ; i<3000 ; i++ )
- {
- if ( line[i] == '\t' ) line[i] = ' '; // replace tab by space
- if ( line[i] == '/' && line[i+1] == '/' )
- {
- line[i] = 0;
- break;
- }
- }
-
- if ( Cmd(line, "Map") )
- {
- m_map->ZoomMap(OpFloat(line, "zoom", 1.0f));
- }
-
- if ( Cmd(line, "DoneResearch") )
- {
- g_researchDone = OpInt(line, "bits", 0);
- }
-
- if ( Cmd(line, "BlitzMode") )
- {
- sleep = OpFloat(line, "sleep", 0.0f);
- delay = OpFloat(line, "delay", 3.0f);
- magnetic = OpFloat(line, "magnetic", 50.0f)*g_unit;
- progress = OpFloat(line, "progress", 0.0f);
- m_blitz->SetStatus(sleep, delay, magnetic, progress);
- }
-
- if ( Cmd(line, "CreateFret") )
- {
- pFret = IOReadObject(line, filename, -1);
- }
-
- if ( Cmd(line, "CreatePower") )
- {
- pPower = IOReadObject(line, filename, -1);
- }
-
- if ( Cmd(line, "CreateObject") )
- {
- pObj = IOReadObject(line, filename, objRank++);
-
- if ( OpInt(line, "select", 0) )
- {
- pSel = pObj;
- }
-
- if ( pFret != 0 )
- {
- CTaskManip* task;
-
- pObj->SetFret(pFret);
- task = new CTaskManip(m_iMan, pObj);
- task->Start(TMO_AUTO, TMA_GRAB); // holds the object!
- delete task;
- }
-
- if ( pPower != 0 )
- {
- pObj->SetPower(pPower);
- pPower->SetTruck(pObj);
- }
-
- pFret = 0;
- pPower = 0;
- }
- }
- fclose(file);
-
-#if CBOT_STACK
- // Compiles scripts.
- nbError = 0;
- do
- {
- lastError = nbError;
- nbError = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
- if ( pObj->RetTruck() != 0 ) continue;
-
- objRank = pObj->RetDefRank();
- if ( objRank == -1 ) continue;
-
- LoadFileScript(pObj, filename, objRank, nbError);
- }
- }
- while ( nbError > 0 && nbError != lastError );
-
- // Reads the file of stacks of execution.
- file = fOpen(filecbot, "rb");
- if ( file != NULL )
- {
- fRead(&version, sizeof(long), 1, file); // version of COLOBOT
- if ( version == 1 )
- {
- fRead(&version, sizeof(long), 1, file); // version of CBOT
- if ( version == CBotProgram::GivVersion() )
- {
- objRank = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetType() == OBJECT_TOTO ) continue;
- if ( pObj->RetType() == OBJECT_FIX ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
- if ( pObj->RetBurn() ) continue;
- if ( pObj->RetDead() ) continue;
-
- if ( !ReadFileStack(pObj, file, objRank++) ) break;
- }
- }
- }
- CBotClass::RestoreStaticState(file);
- fClose(file);
- }
-#endif
-
- return pSel;
-}
-
-
-// Writes the global parameters for free play.
-
-void CRobotMain::WriteFreeParam()
-{
- FILE* file;
- char filename[_MAX_FNAME];
- char line[100];
-
- m_freeResearch |= g_researchDone;
- m_freeBuild |= g_build;
-
- if ( m_gamerName[0] == 0 ) return;
-
- sprintf(filename, "%s\\%s\\research.gam", RetSavegameDir(), m_gamerName);
- file = fopen(filename, "w");
- if ( file == NULL ) return;
-
- sprintf(line, "research=%d build=%d\n", m_freeResearch, m_freeBuild);
- fputs(line, file);
- fclose(file);
-}
-
-// Reads the global parameters for free play.
-
-void CRobotMain::ReadFreeParam()
-{
- FILE* file;
- char filename[_MAX_FNAME];
- char line[100];
-
- m_freeResearch = 0;
- m_freeBuild = 0;
-
- if ( m_gamerName[0] == 0 ) return;
-
- sprintf(filename, "%s\\%s\\research.gam", RetSavegameDir(), m_gamerName);
- file = fopen(filename, "r");
- if ( file == NULL ) return;
-
- if ( fgets(line, 100, file) != NULL )
- {
- sscanf(line, "research=%d build=%d\n", &m_freeResearch, &m_freeBuild);
- }
-
- fclose(file);
-}
-
-
-// Resets all objects to their original position.
-
-void CRobotMain::ResetObject()
-{
-#if 0
- CObject* pObj;
- CObject* pTruck;
- CAuto* pAuto;
- CBrain* brain;
- CPyro* pyro;
- ResetCap cap;
- Math::Vector pos, angle;
- int i;
-
- // Removes all pyrotechnic effects in progress.
- while ( true )
- {
- pyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, 0);
- if ( pyro == 0 ) break;
-
- pyro->DeleteObject();
- delete pyro;
- }
-
- // Removes all bullets in progress.
- m_particule->DeleteParticule(PARTIGUN1);
- m_particule->DeleteParticule(PARTIGUN2);
- m_particule->DeleteParticule(PARTIGUN3);
- m_particule->DeleteParticule(PARTIGUN4);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- cap = pObj->RetResetCap();
- if ( cap == RESET_NONE ) continue;
-
- if ( cap == RESET_DELETE )
- {
- pTruck = pObj->RetTruck();
- if ( pTruck != 0 )
- {
- pTruck->SetFret(0);
- pObj->SetTruck(0);
- }
- pObj->DeleteObject();
- delete pObj;
- i --;
- continue;
- }
-
- pAuto = pObj->RetAuto();
- if ( pAuto != 0 )
- {
- pAuto->Abort();
- }
-
- if ( pObj->RetEnable() ) // object still active?
- {
- brain = pObj->RetBrain();
- if ( brain != 0 )
- {
- pos = pObj->RetResetPosition();
- angle = pObj->RetResetAngle();
-
- if ( pos == pObj->RetPosition(0) &&
- angle == pObj->RetAngle(0) ) continue;
- brain->StartTaskReset(pos, angle);
- continue;
- }
- }
-
- pObj->SetEnable(true); // active again
-
- pos = pObj->RetResetPosition();
- angle = pObj->RetResetAngle();
-
- if ( pos == pObj->RetPosition(0) &&
- angle == pObj->RetAngle(0) ) continue;
-
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_RESET, pObj);
-
- brain = pObj->RetBrain();
- if ( brain != 0 )
- {
- brain->RunProgram(pObj->RetResetRun());
- }
- }
-#else
- m_bResetCreate = true;
-#endif
-}
-
-// Resets all objects to their original position.
-
-void CRobotMain::ResetCreate()
-{
- CObject* pObj;
- CPyro* pyro;
- ResetCap cap;
- int i;
-
- SaveAllScript();
-
- // Removes all bullets in progress.
- m_particule->DeleteParticule(PARTIGUN1);
- m_particule->DeleteParticule(PARTIGUN2);
- m_particule->DeleteParticule(PARTIGUN3);
- m_particule->DeleteParticule(PARTIGUN4);
-
- DeselectAll(); // removes the control buttons
- DeleteAllObjects(); // removes all the current 3D Scene
-
- m_particule->FlushParticule();
- m_terrain->FlushBuildingLevel();
- m_iMan->Flush(CLASS_OBJECT);
- m_iMan->Flush(CLASS_PHYSICS);
- m_iMan->Flush(CLASS_BRAIN);
- m_iMan->Flush(CLASS_PYRO);
- m_camera->SetType(CAMERA_DIALOG);
-
- CreateScene(m_dialog->RetSceneSoluce(), false, true);
-
- if ( !RetNiceReset() ) return;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- cap = pObj->RetResetCap();
- if ( cap == RESET_NONE ) continue;
-
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_RESET, pObj);
- }
-}
-
-// Checks if the mission is over.
-
-Error CRobotMain::CheckEndMission(bool bFrame)
-{
- CObject* pObj;
- Math::Vector bPos, oPos;
- ObjectType type;
- int t, i, nb;
-
- for ( t=0 ; t<m_endTakeTotal ; t++ )
- {
- if ( m_endTake[t].message[0] != 0 ) continue;
-
- bPos = m_endTake[t].pos;
- bPos.y = 0.0f;
-
- nb = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- // Do not use RetActif () because an invisible worm (underground)
- // should be regarded as existing here!
- if ( pObj->RetLock() ) continue;
- if ( pObj->RetRuin() ) continue;
- if ( !pObj->RetEnable() ) continue;
-
- type = pObj->RetType();
- if ( type == OBJECT_SCRAP2 ||
- type == OBJECT_SCRAP3 ||
- type == OBJECT_SCRAP4 ||
- type == OBJECT_SCRAP5 ) // wastes?
- {
- type = OBJECT_SCRAP1;
- }
- if ( type != m_endTake[t].type ) continue;
-
- if ( pObj->RetTruck() == 0 )
- {
- oPos = pObj->RetPosition(0);
- }
- else
- {
- oPos = pObj->RetTruck()->RetPosition(0);
- }
- oPos.y = 0.0f;
- if ( Math::DistanceProjected(oPos, bPos) <= m_endTake[t].dist )
- {
- nb ++;
- }
- }
-
- if ( nb <= m_endTake[t].lost )
- {
- if ( m_endTake[t].type == OBJECT_HUMAN )
- {
- if ( m_lostDelay == 0.0f )
- {
- m_lostDelay = 0.1f; // lost immediately
- m_winDelay = 0.0f;
- }
- m_displayText->SetEnable(false);
- return INFO_LOSTq;
- }
- else
- {
- if ( m_lostDelay == 0.0f )
- {
- m_displayText->DisplayError(INFO_LOST, Math::Vector(0.0f,0.0f,0.0f));
- m_lostDelay = m_endTakeLostDelay; // lost in 6 seconds
- m_winDelay = 0.0f;
- }
- m_displayText->SetEnable(false);
- return INFO_LOST;
- }
- }
- if ( nb < m_endTake[t].min ||
- nb > m_endTake[t].max )
- {
- m_displayText->SetEnable(true);
- return ERR_MISSION_NOTERM;
- }
- if ( m_endTake[t].bImmediat )
- {
- if ( m_winDelay == 0.0f )
- {
- m_winDelay = m_endTakeWinDelay; // wins in x seconds
- m_lostDelay = 0.0f;
- }
- m_displayText->SetEnable(false);
- return ERR_OK; // mission ended
- }
- }
-
- if ( m_endTakeResearch != 0 )
- {
- if ( m_endTakeResearch != (m_endTakeResearch&g_researchDone) )
- {
- m_displayText->SetEnable(true);
- return ERR_MISSION_NOTERM;
- }
- }
-
- if ( m_endTakeWinDelay == -1.0f )
- {
- m_winDelay = 1.0f; // wins in one second
- m_lostDelay = 0.0f;
- m_displayText->SetEnable(false);
- return ERR_OK; // mission ended
- }
-
- if ( bFrame && m_bBase ) return ERR_MISSION_NOTERM;
-
- if ( m_winDelay == 0.0f )
- {
- m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f));
- m_winDelay = m_endTakeWinDelay; // wins in two seconds
- m_lostDelay = 0.0f;
- }
- m_displayText->SetEnable(false);
- return ERR_OK; // mission ended
-}
-
-// Checks if the mission is finished after displaying a message.
-
-void CRobotMain::CheckEndMessage(char *message)
-{
- int t;
-
- for ( t=0 ; t<m_endTakeTotal ; t++ )
- {
- if ( m_endTake[t].message[0] == 0 ) continue;
-
- if ( strcmp(m_endTake[t].message, message) == 0 )
- {
- m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f));
- m_winDelay = m_endTakeWinDelay; // wins in 2 seconds
- m_lostDelay = 0.0f;
- }
- }
-}
-
-
-// Returns the number of instructions required.
-
-int CRobotMain::RetObligatoryToken()
-{
- return m_obligatoryTotal;
-}
-
-// Returns the name of a required instruction.
-
-char* CRobotMain::RetObligatoryToken(int i)
-{
- return m_obligatoryToken[i];
-}
-
-// Checks if an instruction is part of the obligatory list.
-
-int CRobotMain::IsObligatoryToken(char *token)
-{
- int i;
-
- for ( i=0 ; i<m_obligatoryTotal ; i++ )
- {
- if ( strcmp(token, m_obligatoryToken[i]) == 0 )
- {
- return i;
- }
- }
- return -1;
-}
-
-// Checks if an instruction is not part of the banned list.
-
-bool CRobotMain::IsProhibitedToken(char *token)
-{
- int i;
-
- for ( i=0 ; i<m_prohibitedTotal ; i++ )
- {
- if ( strcmp(token, m_prohibitedToken[i]) == 0 )
- {
- return false;
- }
- }
- return true;
-}
-
-
-// Indicates whether it is possible to control a driving robot.
-
-bool CRobotMain::RetTrainerPilot()
-{
- return m_bTrainerPilot;
-}
-
-// Indicates whether the scene is fixed, without interaction.
-
-bool CRobotMain::RetFixScene()
-{
- return m_bFixScene;
-}
-
-
-char* CRobotMain::RetTitle()
-{
- return m_title;
-}
-
-char* CRobotMain::RetResume()
-{
- return m_resume;
-}
-
-char* CRobotMain::RetScriptName()
-{
- return m_scriptName;
-}
-
-char* CRobotMain::RetScriptFile()
-{
- return m_scriptFile;
-}
-
-
-bool CRobotMain::RetGlint()
-{
- return m_dialog->RetGlint();
-}
-
-bool CRobotMain::RetSoluce4()
-{
- return m_dialog->RetSoluce4();
-}
-
-bool CRobotMain::RetMovies()
-{
- return m_dialog->RetMovies();
-}
-
-bool CRobotMain::RetNiceReset()
-{
- return m_dialog->RetNiceReset();
-}
-
-bool CRobotMain::RetHimselfDamage()
-{
- return m_dialog->RetHimselfDamage();
-}
-
-bool CRobotMain::RetShowSoluce()
-{
- return m_bShowSoluce;
-}
-
-bool CRobotMain::RetSceneSoluce()
-{
- if ( m_infoFilename[SATCOM_SOLUCE][0] == 0 ) return false;
- return m_dialog->RetSceneSoluce();
-}
-
-bool CRobotMain::RetShowAll()
-{
- return m_bShowAll;
-}
-
-bool CRobotMain::RetCheatRadar()
-{
- return m_bCheatRadar;
-}
-
-char* CRobotMain::RetSavegameDir()
-{
- return m_dialog->RetSavegameDir();
-}
-
-char* CRobotMain::RetPublicDir()
-{
- return m_dialog->RetPublicDir();
-}
-
-char* CRobotMain::RetFilesDir()
-{
- return m_dialog->RetFilesDir();
-}
-
-
-// Change the player's name.
-
-void CRobotMain::SetGamerName(char *name)
-{
- strcpy(m_gamerName, name);
- SetGlobalGamerName(m_gamerName);
- ReadFreeParam();
-}
-
-// Gives the player's name.
-
-char* CRobotMain::RetGamerName()
-{
- return m_gamerName;
-}
-
-
-// Returns the representation to use for the player.
-
-int CRobotMain::RetGamerFace()
-{
- return m_dialog->RetGamerFace();
-}
-
-// Returns the representation to use for the player.
-
-int CRobotMain::RetGamerGlasses()
-{
- return m_dialog->RetGamerGlasses();
-}
-
-// Returns the mode with just the head.
-
-bool CRobotMain::RetGamerOnlyHead()
-{
- return m_dialog->RetGamerOnlyHead();
-}
-
-// Returns the angle of presentation.
-
-float CRobotMain::RetPersoAngle()
-{
- return m_dialog->RetPersoAngle();
-}
-
-
-// Changes on the pause mode.
-
-void CRobotMain::ChangePause(bool bPause)
-{
- m_bPause = bPause;
- m_engine->SetPause(m_bPause);
-
- m_sound->MuteAll(m_bPause);
- CreateShortcuts();
- if ( m_bPause ) HiliteClear();
-}
-
-
-// Changes game speed
-
-void CRobotMain::SetSpeed(float speed)
-{
- CButton* pb;
- char text[10];
-
- m_engine->SetSpeed(speed);
-
- pb = (CButton*)m_interface->SearchControl(EVENT_SPEED);
- if ( pb != 0 )
- {
- if ( speed == 1.0f )
- {
- pb->ClearState(STATE_VISIBLE);
- }
- else
- {
- sprintf(text, "x%.1f", speed);
- pb->SetName(text);
- pb->SetState(STATE_VISIBLE);
- }
- }
-}
-
-float CRobotMain::RetSpeed()
-{
- return m_engine->RetSpeed();
-}
-
-
-// Creates interface shortcuts to the units.
-
-bool CRobotMain::CreateShortcuts()
-{
- if ( m_phase != PHASE_SIMUL ) return false;
- if ( !m_bShortCut ) return false;
- return m_short->CreateShortcuts();
-}
-
-// Updates the map.
-
-void CRobotMain::UpdateMap()
-{
- m_map->UpdateMap();
-}
-
-// Indicates whether the mini-map is visible.
-
-bool CRobotMain::RetShowMap()
-{
- return m_map->RetShowMap() && m_bMapShow;
-}
-
-
-// Management of the lock mode for movies.
-
-void CRobotMain::SetMovieLock(bool bLock)
-{
- m_bMovieLock = bLock;
- m_engine->SetMovieLock(m_bMovieLock);
-
- CreateShortcuts();
- m_map->ShowMap(!m_bMovieLock && m_bMapShow);
- if ( m_bMovieLock ) HiliteClear();
- m_engine->SetMouseHide(m_bMovieLock);
-}
-
-bool CRobotMain::RetMovieLock()
-{
- return m_bMovieLock;
-}
-
-bool CRobotMain::RetInfoLock()
-{
- return ( m_displayInfo != 0 ); // info in progress?
-}
-
-// Management of the blocking of the call of SatCom.
-
-void CRobotMain::SetSatComLock(bool bLock)
-{
- m_bSatComLock = bLock;
-}
-
-bool CRobotMain::RetSatComLock()
-{
- return m_bSatComLock;
-}
-
-// Management of the lock mode for the edition.
-
-void CRobotMain::SetEditLock(bool bLock, bool bEdit)
-{
- m_bEditLock = bLock;
-
- CreateShortcuts();
-
- // Do not remove the card if it contains a still image.
- if ( !bLock || !m_map->RetFixImage() )
- {
- m_map->ShowMap(!m_bEditLock && m_bMapShow);
- }
-
- m_displayText->HideText(bLock);
- m_engine->FlushPressKey();
-
- if ( m_bEditLock )
- {
- HiliteClear();
- }
- else
- {
- m_bEditFull = false;
- }
-}
-
-bool CRobotMain::RetEditLock()
-{
- return m_bEditLock;
-}
-
-// Management of the fullscreen mode during editing.
-
-void CRobotMain::SetEditFull(bool bFull)
-{
- m_bEditFull = bFull;
-}
-
-bool CRobotMain::RetEditFull()
-{
- return m_bEditFull;
-}
-
-
-bool CRobotMain::RetFreePhoto()
-{
- return m_bFreePhoto;
-}
-
-
-// Indicates whether mouse is on an friend object, on which we should not shoot.
-
-void CRobotMain::SetFriendAim(bool bFriend)
-{
- m_bFriendAim = bFriend;
-}
-
-bool CRobotMain::RetFriendAim()
-{
- return m_bFriendAim;
-}
-
-
-// Management of the precision of drawing the ground.
-
-void CRobotMain::SetTracePrecision(float factor)
-{
- m_engine->SetTracePrecision(factor);
-}
-
-float CRobotMain::RetTracePrecision()
-{
- return m_engine->RetTracePrecision();
-}
-
-
-// Starts music with a mission.
-
-void CRobotMain::StartMusic()
-{
- if ( m_audioTrack != 0 )
- {
- m_sound->StopMusic();
- m_sound->PlayMusic(m_audioTrack, m_bAudioRepeat);
- }
-}
-
-// Removes hilite and tooltip.
-
-void CRobotMain::ClearInterface()
-{
- HiliteClear(); // removes setting evidence
- m_tooltipName[0] = 0; // really removes the tooltip
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// robotmain.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "CBot/CBotDll.h"
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "math/conv.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/language.h"
+#include "common/global.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/profile.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "old/math3d.h"
+#include "old/light.h"
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "old/cloud.h"
+#include "old/blitz.h"
+#include "old/planet.h"
+#include "object/object.h"
+#include "object/motion/motion.h"
+#include "object/motion/motiontoto.h"
+#include "object/motion/motionhuman.h"
+#include "physics/physics.h"
+#include "object/brain.h"
+#include "old/pyro.h"
+#include "old/modfile.h"
+#include "old/model.h"
+#include "old/camera.h"
+#include "object/task/task.h"
+#include "object/task/taskmanip.h"
+#include "object/task/taskbuild.h"
+#include "object/auto/auto.h"
+#include "object/auto/autobase.h"
+#include "ui/displayinfo.h"
+#include "ui/interface.h"
+#include "ui/shortcut.h"
+#include "ui/map.h"
+#include "ui/label.h"
+#include "ui/button.h"
+#include "ui/slider.h"
+#include "ui/window.h"
+#include "ui/edit.h"
+#include "ui/displaytext.h"
+#include "old/text.h"
+#include "old/sound.h"
+#include "script/cbottoken.h"
+#include "script/cmdtoken.h"
+#include "object/mainmovie.h"
+#include "ui/maindialog.h"
+#include "ui/mainshort.h"
+#include "ui/mainmap.h"
+#include "script/script.h"
+#include "object/robotmain.h"
+
+
+
+#define CBOT_STACK true // saves the stack of programs CBOT
+const float UNIT = 4.0f;
+
+
+
+// Global variables.
+
+long g_id; // unique identifier
+long g_build; // constructible buildings
+long g_researchDone; // research done
+long g_researchEnable; // research available
+float g_unit; // conversion factor
+
+
+
+#include "script/ClassFILE.cpp"
+
+
+
+// Compilation of class "point".
+
+CBotTypResult cPoint(CBotVar* pThis, CBotVar* &var)
+{
+ if ( !pThis->IsElemOfClass("point") ) return CBotTypResult(CBotErrBadNum);
+
+ if ( var == NULL ) return CBotTypResult(0); // ok if no parameter
+
+ // First parameter (x):
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ // Second parameter (y):
+ if ( var == NULL ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ // Third parameter (z):
+ if ( var == NULL ) // only 2 parameters?
+ {
+ return CBotTypResult(0); // this function returns void
+ }
+
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+ if ( var != NULL ) return CBotTypResult(CBotErrOverParam);
+
+ return CBotTypResult(0); // this function returns void
+}
+
+//Execution of the class "point".
+
+bool rPoint(CBotVar* pThis, CBotVar* var, CBotVar* pResult, int& Exception)
+{
+ CBotVar *pX, *pY, *pZ;
+
+ if ( var == NULL ) return true; // constructor with no parameters is ok
+
+ if ( var->GivType() > CBotTypDouble )
+ {
+ Exception = CBotErrBadNum; return false;
+ }
+
+ pX = pThis->GivItem("x");
+ if ( pX == NULL )
+ {
+ Exception = CBotErrUndefItem; return false;
+ }
+ pX->SetValFloat( var->GivValFloat() );
+ var = var->GivNext();
+
+ if ( var == NULL )
+ {
+ Exception = CBotErrLowParam; return false;
+ }
+
+ if ( var->GivType() > CBotTypDouble )
+ {
+ Exception = CBotErrBadNum; return false;
+ }
+
+ pY = pThis->GivItem("y");
+ if ( pY == NULL )
+ {
+ Exception = CBotErrUndefItem; return false;
+ }
+ pY->SetValFloat( var->GivValFloat() );
+ var = var->GivNext();
+
+ if ( var == NULL )
+ {
+ return true; // ok with only two parameters
+ }
+
+ pZ = pThis->GivItem("z");
+ if ( pZ == NULL )
+ {
+ Exception = CBotErrUndefItem; return false;
+ }
+ pZ->SetValFloat( var->GivValFloat() );
+ var = var->GivNext();
+
+ if ( var != NULL )
+ {
+ Exception = CBotErrOverParam; return false;
+ }
+
+ return true; // no interruption
+}
+
+
+
+
+// Constructor of robot application.
+
+CRobotMain::CRobotMain(CInstanceManager* iMan)
+{
+ ObjectType type;
+ float fValue;
+ int iValue, i;
+ char* token;
+
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_MAIN, this);
+
+ m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ m_cloud = (CCloud*)m_iMan->SearchInstance(CLASS_CLOUD);
+ m_blitz = (CBlitz*)m_iMan->SearchInstance(CLASS_BLITZ);
+ m_planet = (CPlanet*)m_iMan->SearchInstance(CLASS_PLANET);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+
+ m_interface = new CInterface(m_iMan);
+ m_terrain = new CTerrain(m_iMan);
+ m_model = new CModel(m_iMan);
+ m_camera = new CCamera(m_iMan);
+ m_displayText = new CDisplayText(m_iMan);
+ m_movie = new CMainMovie(m_iMan);
+ m_dialog = new CMainDialog(m_iMan);
+ m_short = new CMainShort(m_iMan);
+ m_map = new CMainMap(m_iMan);
+ m_displayInfo = 0;
+
+ m_engine->SetTerrain(m_terrain);
+ m_filesDir = m_dialog->RetFilesDir();
+
+ m_time = 0.0f;
+ m_gameTime = 0.0f;
+ m_checkEndTime = 0.0f;
+
+ m_phase = PHASE_NAME;
+ m_cameraRank = -1;
+ m_visitLast = EVENT_NULL;
+ m_visitObject = 0;
+ m_visitArrow = 0;
+ m_audioTrack = 0;
+ m_bAudioRepeat = true;
+ m_delayWriteMessage = 0;
+ m_selectObject = 0;
+ m_infoUsed = 0;
+
+ m_bBeginSatCom = false;
+ m_bMovieLock = false;
+ m_bSatComLock = false;
+ m_bEditLock = false;
+ m_bEditFull = false;
+ m_bPause = false;
+ m_bHilite = false;
+ m_bFreePhoto = false;
+ m_bShowPos = false;
+ m_bSelectInsect = false;
+ m_bShowSoluce = false;
+ m_bShowAll = false;
+ m_bCheatRadar = false;
+ m_bFixScene = false;
+ m_bTrainerPilot = false;
+ m_bSuspend = false;
+ m_bFriendAim = false;
+ m_bResetCreate = false;
+ m_bShortCut = true;
+
+ m_engine->SetMovieLock(m_bMovieLock);
+
+ m_movie->Flush();
+ m_movieInfoIndex = -1;
+
+ m_tooltipPos = Math::Point(0.0f, 0.0f);
+ m_tooltipName[0] = 0;
+ m_tooltipTime = 0.0f;
+
+ m_endingWinRank = 0;
+ m_endingLostRank = 0;
+ m_bWinTerminate = false;
+
+ FlushDisplayInfo();
+
+ m_fontSize = 9.0f;
+ m_windowPos = Math::Point(0.15f, 0.17f);
+ m_windowDim = Math::Point(0.70f, 0.66f);
+
+ if ( GetProfileFloat("Edit", "FontSize", fValue) ) m_fontSize = fValue;
+ if ( GetProfileFloat("Edit", "WindowPos.x", fValue) ) m_windowPos.x = fValue;
+ if ( GetProfileFloat("Edit", "WindowPos.y", fValue) ) m_windowPos.y = fValue;
+ if ( GetProfileFloat("Edit", "WindowDim.x", fValue) ) m_windowDim.x = fValue;
+ if ( GetProfileFloat("Edit", "WindowDim.y", fValue) ) m_windowDim.y = fValue;
+
+ m_IOPublic = false;
+ m_IODim = Math::Point(320.0f/640.0f, (121.0f+18.0f*8)/480.0f);
+ m_IOPos.x = (1.0f-m_IODim.x)/2.0f; // in the middle
+ m_IOPos.y = (1.0f-m_IODim.y)/2.0f;
+
+ if ( GetProfileInt ("Edit", "IOPublic", iValue) ) m_IOPublic = iValue;
+ if ( GetProfileFloat("Edit", "IOPos.x", fValue) ) m_IOPos.x = fValue;
+ if ( GetProfileFloat("Edit", "IOPos.y", fValue) ) m_IOPos.y = fValue;
+ if ( GetProfileFloat("Edit", "IODim.x", fValue) ) m_IODim.x = fValue;
+ if ( GetProfileFloat("Edit", "IODim.y", fValue) ) m_IODim.y = fValue;
+
+ m_short->FlushShortcuts();
+ InitEye();
+
+ m_engine->SetTracePrecision(1.0f);
+
+ m_cameraPan = 0.0f;
+ m_cameraZoom = 0.0f;
+
+ g_id = 0;
+ g_build = 0;
+ g_researchDone = 0; // no research done
+ g_researchEnable = 0;
+ g_unit = 4.0f;
+
+ m_gamerName[0] = 0;
+ GetProfileString("Gamer", "LastName", m_gamerName, 100);
+ SetGlobalGamerName(m_gamerName);
+ ReadFreeParam();
+ m_dialog->SetupRecall();
+
+ for ( i=0 ; i<MAXSHOWLIMIT ; i++ )
+ {
+ m_showLimit[i].bUsed = false;
+ m_showLimit[i].total = 0;
+ m_showLimit[i].link = 0;
+ }
+
+ CBotProgram::SetTimer(100);
+ CBotProgram::Init();
+
+ for ( i=0 ; i<OBJECT_MAX ; i++ )
+ {
+ type = (ObjectType)i;
+ token = RetObjectName(type);
+ if ( token[0] != 0 )
+ {
+ CBotProgram::DefineNum(token, type);
+ }
+ token = RetObjectAlias(type);
+ if ( token[0] != 0 )
+ {
+ CBotProgram::DefineNum(token, type);
+ }
+ }
+
+ CBotProgram::DefineNum("White", 0);
+ CBotProgram::DefineNum("Black", 1);
+ CBotProgram::DefineNum("Gray", 2);
+ CBotProgram::DefineNum("LightGray", 3);
+ CBotProgram::DefineNum("Red", 4);
+ CBotProgram::DefineNum("Pink", 5);
+ CBotProgram::DefineNum("Purple", 6);
+ CBotProgram::DefineNum("Orange", 7);
+ CBotProgram::DefineNum("Yellow", 8);
+ CBotProgram::DefineNum("Beige", 9);
+ CBotProgram::DefineNum("Brown", 10);
+ CBotProgram::DefineNum("Skin", 11);
+ CBotProgram::DefineNum("Green", 12);
+ CBotProgram::DefineNum("LightGreen", 13);
+ CBotProgram::DefineNum("Blue", 14);
+ CBotProgram::DefineNum("LightBlue", 15);
+ CBotProgram::DefineNum("BlackArrow", 16);
+ CBotProgram::DefineNum("RedArrow", 17);
+
+ CBotProgram::DefineNum("Metal", OM_METAL);
+ CBotProgram::DefineNum("Plastic", OM_PLASTIC);
+
+ CBotProgram::DefineNum("InFront", TMA_FFRONT);
+ CBotProgram::DefineNum("Behind", TMA_FBACK);
+ CBotProgram::DefineNum("EnergyCell", TMA_POWER);
+
+ CBotProgram::DefineNum("DisplayError", TT_ERROR);
+ CBotProgram::DefineNum("DisplayWarning", TT_WARNING);
+ CBotProgram::DefineNum("DisplayInfo", TT_INFO);
+ CBotProgram::DefineNum("DisplayMessage", TT_MESSAGE);
+
+ CBotProgram::DefineNum("FilterNone", FILTER_NONE);
+ CBotProgram::DefineNum("FilterOnlyLanding", FILTER_ONLYLANDING);
+ CBotProgram::DefineNum("FilterOnlyFliying", FILTER_ONLYFLYING);
+
+ // Add the class Point.
+ CBotClass* bc;
+ bc = new CBotClass("point", NULL, true); // intrinsic class
+ bc->AddItem("x", CBotTypFloat);
+ bc->AddItem("y", CBotTypFloat);
+ bc->AddItem("z", CBotTypFloat);
+ bc->AddFunction("point", rPoint, cPoint);
+
+ // Adds the class Object.
+ bc = new CBotClass("object", NULL);
+ bc->AddItem("category", CBotTypResult(CBotTypInt), PR_READ);
+ bc->AddItem("position", CBotTypResult(CBotTypClass, "point"), PR_READ);
+ bc->AddItem("orientation", CBotTypResult(CBotTypFloat), PR_READ);
+ bc->AddItem("pitch", CBotTypResult(CBotTypFloat), PR_READ);
+ bc->AddItem("roll", CBotTypResult(CBotTypFloat), PR_READ);
+ bc->AddItem("energyLevel", CBotTypResult(CBotTypFloat), PR_READ);
+ bc->AddItem("shieldLevel", CBotTypResult(CBotTypFloat), PR_READ);
+ bc->AddItem("temperature", CBotTypResult(CBotTypFloat), PR_READ);
+ bc->AddItem("altitude", CBotTypResult(CBotTypFloat), PR_READ);
+ bc->AddItem("lifeTime", CBotTypResult(CBotTypFloat), PR_READ);
+ bc->AddItem("material", CBotTypResult(CBotTypInt), PR_READ);
+ bc->AddItem("energyCell", CBotTypResult(CBotTypPointer, "object"), PR_READ);
+ bc->AddItem("load", CBotTypResult(CBotTypPointer, "object"), PR_READ);
+
+ // Initializes the class FILE.
+ InitClassFILE();
+
+ CScript::InitFonctions();
+}
+
+// Destructor of robot application.
+
+CRobotMain::~CRobotMain()
+{
+ delete m_movie;
+ delete m_dialog;
+ delete m_short;
+ delete m_map;
+ delete m_terrain;
+ delete m_model;
+}
+
+
+// Creates the file colobot.ini at the first time.
+
+void CRobotMain::CreateIni()
+{
+ int iValue;
+
+ // colobot.ini don't exist?
+ if ( !GetProfileInt("Setup", "TotoMode", iValue) )
+ {
+ m_dialog->SetupMemorize();
+ }
+}
+
+
+// Changes phase.
+
+void CRobotMain::ChangePhase(Phase phase)
+{
+ CEdit* pe;
+ CButton* pb;
+ D3DCOLORVALUE color;
+ Math::Point pos, dim, ddim;
+ float ox, oy, sx, sy;
+ char* read;
+ int rank, numTry;
+ bool bLoading;
+
+ if ( m_phase == PHASE_SIMUL ) // ends a simulation?
+ {
+ SaveAllScript();
+ m_sound->StopMusic();
+ m_camera->SetObject(0);
+
+#if _SCHOOL
+ if ( true )
+#else
+ if ( m_gameTime > 10.0f ) // did you play at least 10 seconds?
+#endif
+ {
+ rank = m_dialog->RetSceneRank();
+ numTry = m_dialog->RetGamerInfoTry(rank);
+ m_dialog->SetGamerInfoTry(rank, numTry+1);
+ m_dialog->WriteGamerInfo();
+ }
+ }
+
+ if ( phase == PHASE_WIN ) // wins a simulation?
+ {
+ rank = m_dialog->RetSceneRank();
+ m_dialog->SetGamerInfoPassed(rank, true);
+ m_dialog->NextMission(); // passes to the next mission
+ m_dialog->WriteGamerInfo();
+ }
+
+ DeleteAllObjects(); // removes all the current 3D Scene
+
+ m_phase = phase;
+ m_winDelay = 0.0f;
+ m_lostDelay = 0.0f;
+ m_bBeginSatCom = false;
+ m_bMovieLock = false;
+ m_bSatComLock = false;
+ m_bEditLock = false;
+ m_bFreePhoto = false;
+ m_bResetCreate = false;
+
+ m_engine->SetMovieLock(m_bMovieLock);
+ ChangePause(false);
+ FlushDisplayInfo();
+ m_engine->SetRankView(0);
+ m_engine->FlushObject();
+ color.r = color.g = color.b = color.a = 0.0f;
+ m_engine->SetWaterAddColor(color);
+ m_engine->SetBackground("");
+ m_engine->SetBackForce(false);
+ m_engine->SetFrontsizeName("");
+ m_engine->SetOverColor();
+ m_engine->GroundMarkDelete(0);
+ SetSpeed(1.0f);
+ m_terrain->SetWind(Math::Vector(0.0f, 0.0f, 0.0f));
+ m_terrain->FlushBuildingLevel();
+ m_terrain->FlushFlyingLimit();
+ m_light->FlushLight();
+ m_particule->FlushParticule();
+ m_water->Flush();
+ m_cloud->Flush();
+ m_blitz->Flush();
+ m_planet->Flush();
+ m_iMan->Flush(CLASS_OBJECT);
+ m_iMan->Flush(CLASS_PHYSICS);
+ m_iMan->Flush(CLASS_BRAIN);
+ m_iMan->Flush(CLASS_PYRO);
+ m_model->StopUserAction();
+ m_interface->Flush();
+ ClearInterface();
+ FlushNewScriptName();
+ m_sound->SetListener(Math::Vector(0.0f, 0.0f, 0.0f), Math::Vector(0.0f, 0.0f, 1.0f));
+ m_camera->SetType(CAMERA_DIALOG);
+ m_movie->Flush();
+ m_movieInfoIndex = -1;
+ m_cameraPan = 0.0f;
+ m_cameraZoom = 0.0f;
+ m_bShortCut = true;
+
+ // Creates and hide the command console.
+ dim.x = 200.0f/640.0f;
+ dim.y = 18.0f/480.0f;
+ pos.x = 50.0f/640.0f;
+ pos.y = 452.0f/480.0f;
+ pe = m_interface->CreateEdit(pos, dim, 0, EVENT_CMD);
+ if ( pe == 0 ) return;
+ pe->ClearState(STATE_VISIBLE);
+ m_bCmdEdit = false; // hidden for now
+
+ // Creates the speedometer.
+#if _TEEN
+ dim.x = 30.0f/640.0f;
+ dim.y = 20.0f/480.0f;
+ pos.x = 4.0f/640.0f;
+ pos.y = 454.0f/480.0f;
+#else
+ dim.x = 30.0f/640.0f;
+ dim.y = 20.0f/480.0f;
+ pos.x = 4.0f/640.0f;
+ pos.y = 426.0f/480.0f;
+#endif
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_SPEED);
+ if ( pb == 0 ) return;
+ pb->SetState(STATE_SIMPLY);
+ pb->ClearState(STATE_VISIBLE);
+
+ m_dialog->ChangePhase(m_phase);
+
+ dim.x = 32.0f/640.0f;
+ dim.y = 32.0f/480.0f;
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = (32.0f+2.0f)/640.0f;
+ sy = (32.0f+2.0f)/480.0f;
+
+ if ( m_phase != PHASE_PERSO )
+ {
+ m_engine->SetDrawWorld(true);
+ m_engine->SetDrawFront(false);
+ m_bFixScene = false;
+ }
+
+ if ( m_phase == PHASE_INIT )
+ {
+#if _NEWLOOK
+ m_engine->FreeTexture("generna.tga");
+ m_engine->FreeTexture("genernb.tga");
+ m_engine->FreeTexture("genernc.tga");
+ m_engine->FreeTexture("genernd.tga");
+#else
+#if _FRENCH
+#if _DEMO
+ m_engine->FreeTexture("genedfa.tga");
+ m_engine->FreeTexture("genedfb.tga");
+ m_engine->FreeTexture("genedfc.tga");
+ m_engine->FreeTexture("genedfd.tga");
+#else
+ m_engine->FreeTexture("generfa.tga");
+ m_engine->FreeTexture("generfb.tga");
+ m_engine->FreeTexture("generfc.tga");
+ m_engine->FreeTexture("generfd.tga");
+#endif
+#endif
+#if _ENGLISH
+#if _DEMO
+ m_engine->FreeTexture("genedea.tga");
+ m_engine->FreeTexture("genedeb.tga");
+ m_engine->FreeTexture("genedec.tga");
+ m_engine->FreeTexture("geneded.tga");
+#else
+ m_engine->FreeTexture("generea.tga");
+ m_engine->FreeTexture("genereb.tga");
+ m_engine->FreeTexture("generec.tga");
+ m_engine->FreeTexture("genered.tga");
+#endif
+#endif
+#if _GERMAN
+#if _DEMO
+ m_engine->FreeTexture("genedda.tga");
+ m_engine->FreeTexture("geneddb.tga");
+ m_engine->FreeTexture("geneddc.tga");
+ m_engine->FreeTexture("geneddd.tga");
+#else
+ m_engine->FreeTexture("generea.tga");
+ m_engine->FreeTexture("genereb.tga");
+ m_engine->FreeTexture("generec.tga");
+ m_engine->FreeTexture("genered.tga");
+#endif
+#endif
+#if _WG
+#if _DEMO
+ m_engine->FreeTexture("genedda.tga");
+ m_engine->FreeTexture("geneddb.tga");
+ m_engine->FreeTexture("geneddc.tga");
+ m_engine->FreeTexture("geneddd.tga");
+#else
+ m_engine->FreeTexture("generda.tga");
+ m_engine->FreeTexture("generdb.tga");
+ m_engine->FreeTexture("generdc.tga");
+ m_engine->FreeTexture("generdd.tga");
+#endif
+#endif
+#if _POLISH
+#if _DEMO
+ m_engine->FreeTexture("genedpa.tga");
+ m_engine->FreeTexture("genedpb.tga");
+ m_engine->FreeTexture("genedpc.tga");
+ m_engine->FreeTexture("genedpd.tga");
+#else
+ m_engine->FreeTexture("generpa.tga");
+ m_engine->FreeTexture("generpb.tga");
+ m_engine->FreeTexture("generpc.tga");
+ m_engine->FreeTexture("generpd.tga");
+#endif
+#endif
+#endif
+ }
+
+ if ( m_phase == PHASE_SIMUL )
+ {
+ m_engine->FreeTexture("inter01a.tga");
+ m_engine->FreeTexture("inter01b.tga");
+ m_engine->FreeTexture("inter01c.tga");
+ m_engine->FreeTexture("inter01d.tga");
+
+ read = m_dialog->RetSceneRead();
+ bLoading = (read[0] != 0);
+
+ m_map->CreateMap();
+ CreateScene(m_dialog->RetSceneSoluce(), false, false); // interactive scene
+ if ( m_bMapImage )
+ {
+ m_map->SetFixImage(m_mapFilename);
+ }
+
+ pos.x = 620.0f/640.0f;
+ pos.y = 460.0f/480.0f;
+ ddim.x = 20.0f/640.0f;
+ ddim.y = 20.0f/480.0f;
+ m_interface->CreateButton(pos, ddim, 11, EVENT_BUTTON_QUIT);
+
+ if ( m_bImmediatSatCom && !bLoading &&
+ m_infoFilename[SATCOM_HUSTON][0] != 0 )
+ {
+ StartDisplayInfo(SATCOM_HUSTON, false); // shows the instructions
+ }
+
+ m_sound->StopMusic();
+ if ( !m_bBase || bLoading ) StartMusic();
+ }
+
+ if ( m_phase == PHASE_WIN )
+ {
+ if ( m_endingWinRank == -1 )
+ {
+ ChangePhase(PHASE_TERM);
+ }
+ else
+ {
+#if _TEEN
+ m_bWinTerminate = (m_endingWinRank == 900);
+ m_dialog->SetSceneName("teenw");
+#else
+ m_bWinTerminate = (m_endingWinRank == 904);
+ m_dialog->SetSceneName("win");
+#endif
+ m_dialog->SetSceneRank(m_endingWinRank);
+ CreateScene(false, true, false); // sets scene
+
+ pos.x = ox+sx*1; pos.y = oy+sy*1;
+ ddim.x = dim.x*2; ddim.y = dim.y*2;
+ m_interface->CreateButton(pos, ddim, 16, EVENT_BUTTON_OK);
+
+ if ( m_bWinTerminate )
+ {
+#if _TEEN
+ pos.x = ox+sx*3; pos.y = oy+sy*1;
+ ddim.x = dim.x*15; ddim.y = dim.y*2;
+ pe = m_interface->CreateEdit(pos, ddim, 0, EVENT_EDIT0);
+ pe->SetFontType(FONT_COLOBOT);
+ pe->SetEditCap(false);
+ pe->SetHiliteCap(false);
+ pe->ReadText("help\\teenw.txt");
+#else
+ pos.x = ox+sx*3; pos.y = oy+sy*0.2f;
+ ddim.x = dim.x*15; ddim.y = dim.y*3.0f;
+ pe = m_interface->CreateEdit(pos, ddim, 0, EVENT_EDIT0);
+ pe->SetGenericMode(true);
+ pe->SetFontType(FONT_COLOBOT);
+ pe->SetEditCap(false);
+ pe->SetHiliteCap(false);
+ pe->ReadText("help\\win.txt");
+#endif
+ }
+ else
+ {
+ m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f), 15.0f, 60.0f, 1000.0f);
+ }
+ }
+ m_sound->StopAll();
+ StartMusic();
+ }
+
+ if ( m_phase == PHASE_LOST )
+ {
+ if ( m_endingLostRank == -1 )
+ {
+ ChangePhase(PHASE_TERM);
+ }
+ else
+ {
+ m_bWinTerminate = false;
+ m_dialog->SetSceneName("lost");
+ m_dialog->SetSceneRank(m_endingLostRank);
+ CreateScene(false, true, false); // sets scene
+
+ pos.x = ox+sx*1; pos.y = oy+sy*1;
+ ddim.x = dim.x*2; ddim.y = dim.y*2;
+ m_interface->CreateButton(pos, ddim, 16, EVENT_BUTTON_OK);
+ m_displayText->DisplayError(INFO_LOST, Math::Vector(0.0f,0.0f,0.0f), 15.0f, 60.0f, 1000.0f);
+ }
+ m_sound->StopAll();
+ StartMusic();
+ }
+
+ if ( m_phase == PHASE_MODEL )
+ {
+ pos.x = ox+sx*0; pos.y = oy+sy*0;
+ m_interface->CreateButton(pos, dim, 11, EVENT_BUTTON_CANCEL);
+
+ CreateModel();
+ }
+
+ if ( m_phase == PHASE_LOADING )
+ {
+ m_engine->SetMouseHide(true);
+ }
+ else
+ {
+ m_engine->SetMouseHide(false);
+ }
+
+ m_engine->LoadAllTexture();
+}
+
+
+// Processes an event.
+
+bool CRobotMain::EventProcess(const Event &event)
+{
+ CEdit* pe;
+ CObject* pObj;
+ Event newEvent;
+ MainMovieType type;
+ int i;
+
+ if ( event.event == EVENT_FRAME )
+ {
+ if ( !m_movie->EventProcess(event) ) // end of the movie?
+ {
+ type = m_movie->RetStopType();
+ if ( type == MM_SATCOMopen )
+ {
+ ChangePause(false);
+ SelectObject(m_infoObject, false); // hands over the command buttons
+ m_map->ShowMap(m_bMapShow);
+ m_displayText->HideText(false);
+ i = m_movieInfoIndex;
+ StartDisplayInfo(m_movieInfoIndex, false);
+ m_movieInfoIndex = i;
+ }
+ }
+
+ m_dialog->EventProcess(event);
+ m_displayText->EventProcess(event);
+ RemoteCamera(m_cameraPan, m_cameraZoom, event.rTime);
+
+ m_interface->EventProcess(event);
+ if ( m_displayInfo != 0 ) // current edition?
+ {
+ m_displayInfo->EventProcess(event);
+ }
+ return EventFrame(event);
+ }
+
+ // Management of the console.
+#if 0
+ if ( m_phase != PHASE_NAME &&
+ !m_movie->IsExist() &&
+ event.event == EVENT_KEYDOWN &&
+ event.param == VK_PAUSE &&
+ (event.keyState&KS_CONTROL) != 0 )
+#else
+ if ( m_phase != PHASE_NAME &&
+ !m_movie->IsExist() &&
+ event.event == EVENT_KEYDOWN &&
+ event.param == VK_CANCEL ) // Ctrl+Pause ?
+#endif
+ {
+ pe = (CEdit*)m_interface->SearchControl(EVENT_CMD);
+ if ( pe == 0 ) return false;
+ pe->SetState(STATE_VISIBLE);
+ pe->SetFocus(true);
+ if ( m_phase == PHASE_SIMUL ) ChangePause(true);
+ m_bCmdEdit = true;
+ return false;
+ }
+ if ( event.event == EVENT_KEYDOWN &&
+ event.param == VK_RETURN && m_bCmdEdit )
+ {
+ char cmd[50];
+ pe = (CEdit*)m_interface->SearchControl(EVENT_CMD);
+ if ( pe == 0 ) return false;
+ pe->GetText(cmd, 50);
+ pe->SetText("");
+ pe->ClearState(STATE_VISIBLE);
+ if ( m_phase == PHASE_SIMUL ) ChangePause(false);
+ ExecuteCmd(cmd);
+ m_bCmdEdit = false;
+ return false;
+ }
+
+ // Management of the speed change.
+ if ( event.event == EVENT_SPEED )
+ {
+ SetSpeed(1.0f);
+ }
+
+ if ( !m_dialog->EventProcess(event) )
+ {
+ if ( event.event == EVENT_MOUSEMOVE )
+ {
+ m_lastMousePos = event.pos;
+ HiliteObject(event.pos);
+ }
+ return false;
+ }
+
+ if ( !m_displayText->EventProcess(event) )
+ {
+ return false;
+ }
+
+ if ( event.event == EVENT_MOUSEMOVE )
+ {
+ m_lastMousePos = event.pos;
+ HiliteObject(event.pos);
+ }
+
+ if ( m_displayInfo != 0 ) // current info?
+ {
+ m_displayInfo->EventProcess(event);
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+ if ( event.param == m_engine->RetKey(KEYRANK_HELP, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_HELP, 1) ||
+ event.param == m_engine->RetKey(KEYRANK_PROG, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_PROG, 1) ||
+ event.param == VK_ESCAPE )
+ {
+ StopDisplayInfo();
+ }
+ }
+ if ( event.event == EVENT_OBJECT_INFOOK )
+ {
+ StopDisplayInfo();
+ }
+ return false;
+ }
+
+ // Simulation phase of the game
+ if ( m_phase == PHASE_SIMUL )
+ {
+ UpdateInfoText();
+
+ if ( !m_bEditFull )
+ {
+ m_camera->EventProcess(event);
+ }
+
+ switch( event.event )
+ {
+ case EVENT_KEYDOWN:
+ KeyCamera(event.event, event.param);
+ HiliteClear();
+ if ( event.param == VK_F11 )
+ {
+ m_particule->WriteWheelTrace("Savegame\\t.bmp", 256, 256, Math::Vector(16.0f, 0.0f, -368.0f), Math::Vector(140.0f, 0.0f, -248.0f));
+ return false;
+ }
+ if ( m_bEditLock ) // current edition?
+ {
+ if ( event.param == m_engine->RetKey(KEYRANK_HELP, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_HELP, 1) )
+ {
+ StartDisplayInfo(SATCOM_HUSTON, false);
+ return false;
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_PROG, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_PROG, 1) )
+ {
+ StartDisplayInfo(SATCOM_PROG, false);
+ return false;
+ }
+ break;
+ }
+ if ( m_bMovieLock ) // current movie?
+ {
+ if ( event.param == m_engine->RetKey(KEYRANK_QUIT, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_QUIT, 1) ||
+ event.param == VK_ESCAPE )
+ {
+ AbortMovie();
+ }
+ return false;
+ }
+ if ( m_camera->RetType() == CAMERA_VISIT )
+ {
+ if ( event.param == m_engine->RetKey(KEYRANK_VISIT, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_VISIT, 1) )
+ {
+ StartDisplayVisit(EVENT_NULL);
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_QUIT, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_QUIT, 1) ||
+ event.param == VK_ESCAPE )
+ {
+ StopDisplayVisit();
+ }
+ return false;
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_QUIT, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_QUIT, 1) )
+ {
+ if ( m_movie->IsExist() )
+ {
+ StartDisplayInfo(SATCOM_HUSTON, false);
+ }
+ else if ( m_winDelay > 0.0f )
+ {
+ ChangePhase(PHASE_WIN);
+ }
+ else if ( m_lostDelay > 0.0f )
+ {
+ ChangePhase(PHASE_LOST);
+ }
+ else
+ {
+ m_dialog->StartAbort(); // do you want to leave?
+ }
+ }
+ if ( event.param == VK_PAUSE )
+ {
+ if ( !m_bMovieLock && !m_bEditLock && !m_bCmdEdit &&
+ m_camera->RetType() != CAMERA_VISIT &&
+ !m_movie->IsExist() )
+ {
+ ChangePause(!m_engine->RetPause());
+ }
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_CAMERA, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_CAMERA, 1) )
+ {
+ ChangeCamera();
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_DESEL, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_DESEL, 1) )
+ {
+ if ( m_bShortCut )
+ {
+ DeselectObject();
+ }
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_HUMAN, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_HUMAN, 1) )
+ {
+ SelectHuman();
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_NEXT, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_NEXT, 1) )
+ {
+ if ( m_bShortCut )
+ {
+ m_short->SelectNext();
+ }
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_HELP, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_HELP, 1) )
+ {
+ StartDisplayInfo(SATCOM_HUSTON, true);
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_PROG, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_PROG, 1) )
+ {
+ StartDisplayInfo(SATCOM_PROG, true);
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_VISIT, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_VISIT, 1) )
+ {
+ StartDisplayVisit(EVENT_NULL);
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_SPEED10, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_SPEED10, 1) )
+ {
+ SetSpeed(1.0f);
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_SPEED15, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_SPEED15, 1) )
+ {
+ SetSpeed(1.5f);
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_SPEED20, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_SPEED20, 1) )
+ {
+ SetSpeed(2.0f);
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_SPEED30, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_SPEED30, 1) )
+ {
+ SetSpeed(3.0f);
+ }
+ break;
+
+ case EVENT_KEYUP:
+ KeyCamera(event.event, event.param);
+ break;
+
+ case EVENT_LBUTTONDOWN:
+ pObj = DetectObject(event.pos);
+ if ( !m_bShortCut ) pObj = 0;
+ if ( pObj != 0 && pObj->RetType() == OBJECT_TOTO )
+ {
+ if ( m_displayInfo != 0 ) // current info?
+ {
+ StopDisplayInfo();
+ }
+ else
+ {
+ if ( !m_bEditLock )
+ {
+ StartDisplayInfo(SATCOM_HUSTON, true);
+ }
+ }
+ }
+ else
+ {
+ SelectObject(pObj);
+ }
+ break;
+
+ case EVENT_LBUTTONUP:
+ m_cameraPan = 0.0f;
+ m_cameraZoom = 0.0f;
+ break;
+
+ case EVENT_BUTTON_QUIT:
+ if ( m_movie->IsExist() )
+ {
+ StartDisplayInfo(SATCOM_HUSTON, false);
+ }
+ else if ( m_winDelay > 0.0f )
+ {
+ ChangePhase(PHASE_WIN);
+ }
+ else if ( m_lostDelay > 0.0f )
+ {
+ ChangePhase(PHASE_LOST);
+ }
+ else
+ {
+ m_dialog->StartAbort(); // do you want to leave?
+ }
+ break;
+
+ case EVENT_OBJECT_LIMIT:
+ StartShowLimit();
+ break;
+
+ case EVENT_OBJECT_DESELECT:
+ if ( m_bShortCut )
+ {
+ DeselectObject();
+ }
+ break;
+
+ case EVENT_OBJECT_HELP:
+ HelpObject();
+ break;
+
+ case EVENT_OBJECT_CAMERA:
+ ChangeCamera();
+ break;
+
+ case EVENT_OBJECT_CAMERAleft:
+ m_cameraPan = -1.0f;
+ break;
+ case EVENT_OBJECT_CAMERAright:
+ m_cameraPan = 1.0f;
+ break;
+ case EVENT_OBJECT_CAMERAnear:
+ m_cameraZoom = -1.0f;
+ break;
+ case EVENT_OBJECT_CAMERAaway:
+ m_cameraZoom = 1.0f;
+ break;
+
+ case EVENT_OBJECT_DELETE:
+ m_dialog->StartDeleteObject(); // do you want to destroy it?
+ break;
+
+ case EVENT_OBJECT_BHELP:
+ StartDisplayInfo(SATCOM_HUSTON, true);
+ break;
+
+ case EVENT_OBJECT_SOLUCE:
+ StartDisplayInfo(SATCOM_SOLUCE, true);
+ break;
+
+ case EVENT_OBJECT_MAPZOOM:
+ m_map->ZoomMap();
+ break;
+
+ case EVENT_DT_VISIT0:
+ case EVENT_DT_VISIT1:
+ case EVENT_DT_VISIT2:
+ case EVENT_DT_VISIT3:
+ case EVENT_DT_VISIT4:
+ StartDisplayVisit(event.event);
+ break;
+
+ case EVENT_DT_END:
+ StopDisplayVisit();
+ break;
+
+ case EVENT_OBJECT_SHORTCUT00:
+ case EVENT_OBJECT_SHORTCUT01:
+ case EVENT_OBJECT_SHORTCUT02:
+ case EVENT_OBJECT_SHORTCUT03:
+ case EVENT_OBJECT_SHORTCUT04:
+ case EVENT_OBJECT_SHORTCUT05:
+ case EVENT_OBJECT_SHORTCUT06:
+ case EVENT_OBJECT_SHORTCUT07:
+ case EVENT_OBJECT_SHORTCUT08:
+ case EVENT_OBJECT_SHORTCUT09:
+ case EVENT_OBJECT_SHORTCUT10:
+ case EVENT_OBJECT_SHORTCUT11:
+ case EVENT_OBJECT_SHORTCUT12:
+ case EVENT_OBJECT_SHORTCUT13:
+ case EVENT_OBJECT_SHORTCUT14:
+ case EVENT_OBJECT_SHORTCUT15:
+ case EVENT_OBJECT_SHORTCUT16:
+ case EVENT_OBJECT_SHORTCUT17:
+ case EVENT_OBJECT_SHORTCUT18:
+ case EVENT_OBJECT_SHORTCUT19:
+ m_short->SelectShortcut(event.event);
+ break;
+
+ case EVENT_OBJECT_MOVIELOCK:
+ AbortMovie();
+ break;
+
+ case EVENT_WIN:
+ ChangePhase(PHASE_WIN);
+ break;
+
+ case EVENT_LOST:
+ ChangePhase(PHASE_LOST);
+ break;
+ }
+
+ EventObject(event);
+ return false;
+ }
+
+ if ( m_phase == PHASE_PERSO )
+ {
+ EventObject(event);
+ }
+
+ if ( m_phase == PHASE_WIN ||
+ m_phase == PHASE_LOST )
+ {
+ EventObject(event);
+
+ switch( event.event )
+ {
+ case EVENT_KEYDOWN:
+ if ( event.param == VK_ESCAPE ||
+ event.param == VK_RETURN )
+ {
+ if ( m_bWinTerminate )
+ {
+ ChangePhase(PHASE_INIT);
+ }
+ else
+ {
+ ChangePhase(PHASE_TERM);
+ }
+ }
+ break;
+
+ case EVENT_BUTTON_OK:
+ if ( m_bWinTerminate )
+ {
+ ChangePhase(PHASE_INIT);
+ }
+ else
+ {
+ ChangePhase(PHASE_TERM);
+ }
+ break;
+ }
+ }
+
+ if ( m_phase == PHASE_MODEL )
+ {
+ switch( event.event )
+ {
+ case EVENT_KEYDOWN:
+ if ( event.param == VK_ESCAPE )
+ {
+ ChangePhase(PHASE_INIT);
+ }
+ if ( event.param == VK_HOME )
+ {
+ InitEye();
+ }
+ break;
+
+ case EVENT_BUTTON_CANCEL:
+ ChangePhase(PHASE_INIT);
+ break;
+ }
+
+ m_model->EventProcess(event);
+ return false;
+ }
+
+ return true;
+}
+
+
+
+// Executes a command.
+
+void CRobotMain::ExecuteCmd(char *cmd)
+{
+ if ( cmd[0] == 0 ) return;
+
+ if ( m_phase == PHASE_SIMUL )
+ {
+ if ( strcmp(cmd, "winmission") == 0 )
+ {
+ Event newEvent;
+ m_event->MakeEvent(newEvent, EVENT_WIN);
+ m_event->AddEvent(newEvent);
+ }
+
+ if ( strcmp(cmd, "lostmission") == 0 )
+ {
+ Event newEvent;
+ m_event->MakeEvent(newEvent, EVENT_LOST);
+ m_event->AddEvent(newEvent);
+ }
+
+ if ( strcmp(cmd, "trainerpilot") == 0 )
+ {
+ m_bTrainerPilot = !m_bTrainerPilot;
+ return;
+ }
+
+ if ( strcmp(cmd, "fly") == 0 )
+ {
+ Event newEvent;
+
+ g_researchDone |= RESEARCH_FLY;
+
+ m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
+ m_event->AddEvent(newEvent);
+ return;
+ }
+
+ if ( strcmp(cmd, "allresearch") == 0 )
+ {
+ Event newEvent;
+
+ g_researchDone = -1; // all research are done
+
+ m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
+ m_event->AddEvent(newEvent);
+ return;
+ }
+
+ if ( strcmp(cmd, "nolimit") == 0 )
+ {
+ m_terrain->SetFlyingMaxHeight(280.0f);
+ return;
+ }
+
+ if ( strcmp(cmd, "photo1") == 0 )
+ {
+ m_bFreePhoto = !m_bFreePhoto;
+ if ( m_bFreePhoto )
+ {
+ m_camera->SetType(CAMERA_FREE);
+ ChangePause(true);
+ }
+ else
+ {
+ m_camera->SetType(CAMERA_BACK);
+ ChangePause(false);
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "photo2") == 0 )
+ {
+ m_bFreePhoto = !m_bFreePhoto;
+ if ( m_bFreePhoto )
+ {
+ m_camera->SetType(CAMERA_FREE);
+ ChangePause(true);
+ DeselectAll(); // removes the control buttons
+ m_map->ShowMap(false);
+ m_displayText->HideText(true);
+ }
+ else
+ {
+ m_camera->SetType(CAMERA_BACK);
+ ChangePause(false);
+ m_map->ShowMap(m_bMapShow);
+ m_displayText->HideText(false);
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "noclip") == 0 )
+ {
+ CObject* object;
+
+ object = RetSelect();
+ if ( object != 0 )
+ {
+ object->SetClip(false);
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "clip") == 0 )
+ {
+ CObject* object;
+
+ object = RetSelect();
+ if ( object != 0 )
+ {
+ object->SetClip(true);
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "addhusky") == 0 )
+ {
+ CObject* object;
+
+ object = RetSelect();
+ if ( object != 0 )
+ {
+ object->SetMagnifyDamage(object->RetMagnifyDamage()*0.1f);
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "addfreezer") == 0 )
+ {
+ CObject* object;
+
+ object = RetSelect();
+ if ( object != 0 )
+ {
+ object->SetRange(object->RetRange()*10.0f);
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "fullpower") == 0 )
+ {
+ CObject* object;
+ CObject* power;
+ CPhysics* physics;
+
+ object = RetSelect();
+ if ( object != 0 )
+ {
+ power = object->RetPower();
+ if ( power != 0 )
+ {
+ power->SetEnergy(1.0f);
+ }
+ object->SetShield(1.0f);
+ physics = object->RetPhysics();
+ if ( physics != 0 )
+ {
+ physics->SetReactorRange(1.0f);
+ }
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "fullenergy") == 0 )
+ {
+ CObject* object;
+ CObject* power;
+
+ object = RetSelect();
+ if ( object != 0 )
+ {
+ power = object->RetPower();
+ if ( power != 0 )
+ {
+ power->SetEnergy(1.0f);
+ }
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "fullshield") == 0 )
+ {
+ CObject* object;
+
+ object = RetSelect();
+ if ( object != 0 )
+ {
+ object->SetShield(1.0f);
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "fullrange") == 0 )
+ {
+ CObject* object;
+ CPhysics* physics;
+
+ object = RetSelect();
+ if ( object != 0 )
+ {
+ physics = object->RetPhysics();
+ if ( physics != 0 )
+ {
+ physics->SetReactorRange(1.0f);
+ }
+ }
+ return;
+ }
+ }
+
+ if ( strcmp(cmd, "debugmode") == 0 )
+ {
+ m_engine->SetDebugMode(!m_engine->RetDebugMode());
+ return;
+ }
+
+ if ( strcmp(cmd, "showstat") == 0 )
+ {
+ m_engine->SetShowStat(!m_engine->RetShowStat());
+ return;
+ }
+
+ if ( strcmp(cmd, "invshadow") == 0 )
+ {
+ m_engine->SetShadow(!m_engine->RetShadow());
+ return;
+ }
+
+ if ( strcmp(cmd, "invdirty") == 0 )
+ {
+ m_engine->SetDirty(!m_engine->RetDirty());
+ return;
+ }
+
+ if ( strcmp(cmd, "invfog") == 0 )
+ {
+ m_engine->SetFog(!m_engine->RetFog());
+ return;
+ }
+
+ if ( strcmp(cmd, "invlens") == 0 )
+ {
+ m_engine->SetLensMode(!m_engine->RetLensMode());
+ return;
+ }
+
+ if ( strcmp(cmd, "invwater") == 0 )
+ {
+ m_engine->SetWaterMode(!m_engine->RetWaterMode());
+ return;
+ }
+
+ if ( strcmp(cmd, "invsky") == 0 )
+ {
+ m_engine->SetSkyMode(!m_engine->RetSkyMode());
+ return;
+ }
+
+ if ( strcmp(cmd, "invplanet") == 0 )
+ {
+ m_engine->SetPlanetMode(!m_engine->RetPlanetMode());
+ return;
+ }
+
+ if ( strcmp(cmd, "showpos") == 0 )
+ {
+ m_bShowPos = !m_bShowPos;
+ return;
+ }
+
+ if ( strcmp(cmd, "selectinsect") == 0 )
+ {
+ m_bSelectInsect = !m_bSelectInsect;
+ return;
+ }
+
+ if ( strcmp(cmd, "showsoluce") == 0 )
+ {
+ m_bShowSoluce = !m_bShowSoluce;
+ m_dialog->ShowSoluceUpdate();
+ return;
+ }
+
+#if _TEEN
+ if ( strcmp(cmd, "allteens") == 0 )
+#else
+ if ( strcmp(cmd, "allmission") == 0 )
+#endif
+ {
+ m_bShowAll = !m_bShowAll;
+ m_dialog->AllMissionUpdate();
+ return;
+ }
+
+ if ( strcmp(cmd, "invradar") == 0 )
+ {
+ m_bCheatRadar = !m_bCheatRadar;
+ return;
+ }
+
+ if ( m_phase == PHASE_SIMUL )
+ {
+ m_displayText->DisplayError(ERR_CMD, Math::Vector(0.0f,0.0f,0.0f));
+ }
+}
+
+
+
+// Returns the type of current movie.
+
+MainMovieType CRobotMain::RetMainMovie()
+{
+ return m_movie->RetType();
+}
+
+
+// Clears the display of instructions.
+
+void CRobotMain::FlushDisplayInfo()
+{
+ int i;
+
+ for ( i=0 ; i<SATCOM_MAX ; i++ )
+ {
+ m_infoFilename[i][0] = 0;
+ m_infoPos[i] = 0;
+ }
+ strcpy(m_infoFilename[SATCOM_OBJECT], "help\\objects.txt");
+ m_infoIndex = 0;
+}
+
+// Beginning of the displaying of instructions.
+// index: SATCOM_*
+
+void CRobotMain::StartDisplayInfo(int index, bool bMovie)
+{
+ CObject* pObj;
+ CMotion* motion;
+ bool bHuman;
+
+ if ( m_bCmdEdit || m_bSatComLock ) return;
+
+ pObj = RetSelect();
+ bHuman = ( pObj != 0 && pObj->RetType() == OBJECT_HUMAN );
+
+ if ( !m_bEditLock && bMovie && !m_movie->IsExist() && bHuman )
+ {
+ motion = pObj->RetMotion();
+ if ( motion != 0 && motion->RetAction() == -1 )
+ {
+ m_movieInfoIndex = index;
+ m_movie->Start(MM_SATCOMopen, 2.5f);
+ ChangePause(true);
+//? m_map->ShowMap(false);
+ m_infoObject = DeselectAll(); // removes the control buttons
+ m_displayText->HideText(true);
+ return;
+ }
+ }
+
+ if ( m_movie->IsExist() )
+ {
+ m_movie->Stop();
+ ChangePause(false);
+ SelectObject(m_infoObject, false); // hands over the command buttons
+//? m_map->ShowMap(m_bMapShow);
+ m_displayText->HideText(false);
+ }
+
+ StartDisplayInfo(m_infoFilename[index], index);
+}
+
+// Beginning of the displaying of instructions.
+
+void CRobotMain::StartDisplayInfo(char *filename, int index)
+{
+ CButton* pb;
+ bool bSoluce;
+
+ if ( m_bCmdEdit ) return;
+
+ m_movieInfoIndex = -1;
+ ClearInterface(); // removes setting evidence and tooltip
+
+ if ( !m_bEditLock )
+ {
+//? m_map->ShowMap(false);
+ m_infoObject = DeselectAll(); // removes the control buttons
+ m_displayText->HideText(true);
+ m_sound->MuteAll(true);
+ }
+
+ pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
+ if ( pb != 0 )
+ {
+ pb->ClearState(STATE_VISIBLE);
+ }
+
+ bSoluce = m_dialog->RetSceneSoluce();
+
+ m_displayInfo = new CDisplayInfo(m_iMan);
+ m_displayInfo->StartDisplayInfo(filename, index, bSoluce);
+
+ m_infoIndex = index;
+ if ( index != -1 )
+ {
+ m_displayInfo->SetPosition(m_infoPos[index]);
+ }
+}
+
+// End of displaying of instructions.
+
+void CRobotMain::StopDisplayInfo()
+{
+ CButton* pb;
+
+ if ( m_movieInfoIndex != -1 ) // film to read the SatCom?
+ {
+ m_movie->Start(MM_SATCOMclose, 2.0f);
+ }
+
+ if ( m_infoIndex != -1 )
+ {
+ m_infoPos[m_infoIndex] = m_displayInfo->RetPosition();
+ }
+ m_displayInfo->StopDisplayInfo();
+
+ delete m_displayInfo;
+ m_displayInfo = 0;
+
+ if ( !m_bEditLock )
+ {
+ pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
+ if ( pb != 0 )
+ {
+ pb->SetState(STATE_VISIBLE);
+ }
+
+ SelectObject(m_infoObject, false); // gives the command buttons
+//? m_map->ShowMap(m_bMapShow);
+ m_displayText->HideText(false);
+
+ m_sound->MuteAll(false);
+ }
+
+ if ( m_infoUsed == 0 )
+ {
+ m_displayText->ClearText(); // removes message "see SatCom ..."
+ }
+ m_infoUsed ++;
+}
+
+// Returns the name of the text display.
+
+char* CRobotMain::RetDisplayInfoName(int index)
+{
+ return m_infoFilename[index];
+}
+
+// Returns the name of the text display.
+
+int CRobotMain::RetDisplayInfoPosition(int index)
+{
+ return m_infoPos[index];
+}
+
+// Returns the name of the text display.
+
+void CRobotMain::SetDisplayInfoPosition(int index, int pos)
+{
+ m_infoPos[index] = pos;
+}
+
+
+// Beginning of a dialogue during the game,
+
+void CRobotMain::StartSuspend()
+{
+ CButton* pb;
+
+ m_map->ShowMap(false);
+ m_infoObject = DeselectAll(); // removes the control buttons
+ m_displayText->HideText(true);
+
+ pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
+ if ( pb != 0 )
+ {
+ pb->ClearState(STATE_VISIBLE);
+ }
+
+ m_bSuspend = true;
+}
+
+// End of dialogue during the game,
+
+void CRobotMain::StopSuspend()
+{
+ CButton* pb;
+
+ pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
+ if ( pb != 0 )
+ {
+ pb->SetState(STATE_VISIBLE);
+ }
+
+ SelectObject(m_infoObject, false); // gives the command buttons
+ m_map->ShowMap(m_bMapShow);
+ m_displayText->HideText(false);
+
+ m_bSuspend = false;
+}
+
+
+// Returns the absolute time of the game
+
+float CRobotMain::RetGameTime()
+{
+ return m_gameTime;
+}
+
+
+
+// Managing the size of the default fonts.
+
+void CRobotMain::SetFontSize(float size)
+{
+ m_fontSize = size;
+ SetProfileFloat("Edit", "FontSize", m_fontSize);
+}
+
+float CRobotMain::RetFontSize()
+{
+ return m_fontSize;
+}
+
+// Managing the size of the default window.
+
+void CRobotMain::SetWindowPos(Math::Point pos)
+{
+ m_windowPos = pos;
+ SetProfileFloat("Edit", "WindowPos.x", m_windowPos.x);
+ SetProfileFloat("Edit", "WindowPos.y", m_windowPos.y);
+}
+
+Math::Point CRobotMain::RetWindowPos()
+{
+ return m_windowPos;
+}
+
+void CRobotMain::SetWindowDim(Math::Point dim)
+{
+ m_windowDim = dim;
+ SetProfileFloat("Edit", "WindowDim.x", m_windowDim.x);
+ SetProfileFloat("Edit", "WindowDim.y", m_windowDim.y);
+}
+
+Math::Point CRobotMain::RetWindowDim()
+{
+ return m_windowDim;
+}
+
+
+// Managing windows open/save.
+
+void CRobotMain::SetIOPublic(bool bMode)
+{
+ m_IOPublic = bMode;
+ SetProfileInt("Edit", "IOPublic", m_IOPublic);
+}
+
+bool CRobotMain::RetIOPublic()
+{
+ return m_IOPublic;
+}
+
+void CRobotMain::SetIOPos(Math::Point pos)
+{
+ m_IOPos = pos;
+ SetProfileFloat("Edit", "IOPos.x", m_IOPos.x);
+ SetProfileFloat("Edit", "IOPos.y", m_IOPos.y);
+}
+
+Math::Point CRobotMain::RetIOPos()
+{
+ return m_IOPos;
+}
+
+void CRobotMain::SetIODim(Math::Point dim)
+{
+ m_IODim = dim;
+ SetProfileFloat("Edit", "IODim.x", m_IODim.x);
+ SetProfileFloat("Edit", "IODim.y", m_IODim.y);
+}
+
+Math::Point CRobotMain::RetIODim()
+{
+ return m_IODim;
+}
+
+
+
+// Start of the visit instead of an error.
+
+void CRobotMain::StartDisplayVisit(EventMsg event)
+{
+ CWindow* pw;
+ CButton* button;
+ CGroup* group;
+ Math::Vector goal;
+ Math::Point pos, dim;
+ int i, j;
+
+ if ( m_bEditLock ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
+ if ( pw == 0 ) return;
+
+ if ( event == EVENT_NULL ) // visit by keyboard shortcut?
+ {
+ if ( m_visitLast != EVENT_NULL ) // already a current visit?
+ {
+ i = m_visitLast-EVENT_DT_VISIT0;
+ }
+ else
+ {
+ i = MAXDTLINE;
+ }
+
+ // Seeks the last.
+ for ( j=0 ; j<MAXDTLINE ; j++ )
+ {
+ i --;
+ if ( i < 0 ) i = MAXDTLINE-1;
+
+ button = (CButton*)pw->SearchControl(EventMsg(EVENT_DT_VISIT0+i));
+ if ( button == 0 || !button->TestState(STATE_ENABLE) ) continue;
+
+ group = (CGroup*)pw->SearchControl(EventMsg(EVENT_DT_GROUP0+i));
+ if ( group != 0 )
+ {
+ event = EventMsg(EVENT_DT_VISIT0+i);
+ break;
+ }
+ }
+ }
+ if ( event == EVENT_NULL )
+ {
+ m_sound->Play(SOUND_TZOING); // nothing to do!
+ return;
+ }
+
+ m_visitLast = event;
+
+ ClearInterface(); // removes setting evidence and tooltip
+
+ if ( m_camera->RetType() == CAMERA_VISIT ) // already a current visit?
+ {
+ m_camera->StopVisit();
+ m_displayText->ClearVisit();
+ }
+ else
+ {
+ m_visitObject = DeselectAll(); // removes the control buttons
+ }
+
+ // Creates the "continue" button.
+ if ( m_interface->SearchControl(EVENT_DT_END) == 0 )
+ {
+ pos.x = 10.0f/640.0f;
+ pos.y = 10.0f/480.0f;
+ dim.x = 50.0f/640.0f;
+ dim.y = 50.0f/480.0f;
+ m_interface->CreateButton(pos, dim, 16, EVENT_DT_END);
+ }
+
+ // Creates the arrow to show the place.
+ if ( m_visitArrow != 0 )
+ {
+ m_visitArrow->DeleteObject();
+ delete m_visitArrow;
+ m_visitArrow = 0;
+ }
+ goal = m_displayText->RetVisitGoal(event);
+ m_visitArrow = CreateObject(goal, 0.0f, 1.0f, 10.0f, OBJECT_SHOW, false, false, 0);
+
+ m_visitPos = m_visitArrow->RetPosition(0);
+ m_visitPosArrow = m_visitPos;
+ m_visitPosArrow.y += m_displayText->RetVisitHeight(event);
+ m_visitArrow->SetPosition(0, m_visitPosArrow);
+
+ m_visitTime = 0.0;
+ m_visitParticule = 0.0f;
+
+ m_particule->DeleteParticule(PARTISHOW);
+
+ m_camera->StartVisit(m_displayText->RetVisitGoal(event),
+ m_displayText->RetVisitDist(event));
+ m_displayText->SetVisit(event);
+ ChangePause(true);
+}
+
+// Move the arrow to visit.
+
+void CRobotMain::FrameVisit(float rTime)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float level;
+
+ if ( m_visitArrow == 0 ) return;
+
+ // Moves the arrow.
+ m_visitTime += rTime;
+
+ pos = m_visitPosArrow;
+ pos.y += 1.5f+sinf(m_visitTime*4.0f)*4.0f;
+ m_visitArrow->SetPosition(0, pos);
+ m_visitArrow->SetAngleY(0, m_visitTime*2.0f);
+
+ // Manages the particles "arrows".
+ m_visitParticule -= rTime;
+ if ( m_visitParticule <= 0.0f )
+ {
+ m_visitParticule = 1.5f;
+
+ pos = m_visitPos;
+ level = m_terrain->RetFloorLevel(pos)+2.0f;
+ if ( pos.y < level ) pos.y = level; // not below the ground
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 30.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISHOW, 2.0f);
+ }
+}
+
+// End of the visit instead of an error.
+
+void CRobotMain::StopDisplayVisit()
+{
+ m_visitLast = EVENT_NULL;
+
+ // Removes the button.
+ m_interface->DeleteControl(EVENT_DT_END);
+
+ // Removes the arrow.
+ if ( m_visitArrow != 0 )
+ {
+ m_visitArrow->DeleteObject();
+ delete m_visitArrow;
+ m_visitArrow = 0;
+ }
+
+ // Removes particles "arrows".
+ m_particule->DeleteParticule(PARTISHOW);
+
+ m_camera->StopVisit();
+ m_displayText->ClearVisit();
+ ChangePause(false);
+ if ( m_visitObject != 0 )
+ {
+ SelectObject(m_visitObject, false); // gives the command buttons
+ m_visitObject = 0;
+ }
+}
+
+
+
+// Updates all the shortcuts.
+
+void CRobotMain::UpdateShortcuts()
+{
+ m_short->UpdateShortcuts();
+}
+
+// Returns the object that default was select after the creation of a scene.
+
+CObject* CRobotMain::RetSelectObject()
+{
+ if ( m_selectObject != 0 ) return m_selectObject;
+ return SearchHuman();
+}
+
+// Deselects everything, and returns the object that was selected.
+
+CObject* CRobotMain::DeselectAll()
+{
+ CObject* pObj;
+ CObject* pPrev;
+ int i;
+
+ pPrev = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetSelect() ) pPrev = pObj;
+ pObj->SetSelect(false);
+ }
+ return pPrev;
+}
+
+// Selects an object, without attending to deselect the rest.
+
+void CRobotMain::SelectOneObject(CObject* pObj, bool bDisplayError)
+{
+ ObjectType type;
+ CObject* toto;
+ CMotionToto* mt;
+
+ pObj->SetSelect(true, bDisplayError);
+ m_camera->SetObject(pObj);
+
+ type = pObj->RetType();
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr ||
+ type == OBJECT_APOLLO2 )
+ {
+ m_camera->SetType(pObj->RetCameraType());
+ m_camera->SetDist(pObj->RetCameraDist());
+ }
+ else
+ {
+ m_camera->SetType(CAMERA_BACK);
+ }
+
+ toto = SearchToto();
+ if ( toto != 0 )
+ {
+ mt = (CMotionToto*)toto->RetMotion();
+ if ( mt != 0 )
+ {
+ mt->SetLinkType(type);
+ }
+ }
+}
+
+// Selects the object aimed by the mouse.
+
+bool CRobotMain::SelectObject(CObject* pObj, bool bDisplayError)
+{
+ CObject* pPrev;
+
+ if ( m_camera->RetType() == CAMERA_VISIT )
+ {
+ StopDisplayVisit();
+ }
+
+ if ( m_bMovieLock || m_bEditLock || m_bPause ) return false;
+ if ( m_movie->IsExist() ) return false;
+ if ( pObj == 0 || !IsSelectable(pObj) ) return false;
+
+ pPrev = DeselectAll();
+
+ if ( pPrev != 0 && pPrev != pObj )
+ {
+ pObj->AddDeselList(pPrev);
+ }
+
+ SelectOneObject(pObj, bDisplayError);
+ m_short->UpdateShortcuts();
+ return true;
+}
+
+// Deselects the selected object.
+
+bool CRobotMain::DeselectObject()
+{
+ CObject* pObj;
+ CObject* pPrev;
+
+ pPrev = DeselectAll();
+
+ if ( pPrev == 0 )
+ {
+ pObj = SearchHuman();
+ }
+ else
+ {
+ pObj = pPrev->SubDeselList();
+ }
+ if ( pObj == 0 )
+ {
+ pObj = SearchHuman();
+ }
+
+ if ( pObj != 0 )
+ {
+ SelectOneObject(pObj);
+ }
+ else
+ {
+ m_camera->SetType(CAMERA_FREE);
+ }
+
+ m_short->UpdateShortcuts();
+ return true;
+}
+
+// Quickly removes all objects.
+
+void CRobotMain::DeleteAllObjects()
+{
+ CPyro* pyro;
+ CObject* pObj;
+ int i;
+
+ // Removes all pyrotechnic effects in progress.
+ while ( true )
+ {
+ pyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, 0);
+ if ( pyro == 0 ) break;
+
+ pyro->DeleteObject();
+ delete pyro;
+ }
+
+ // Removes the arrow.
+ if ( m_visitArrow != 0 )
+ {
+ m_visitArrow->DeleteObject();
+ delete m_visitArrow;
+ m_visitArrow = 0;
+ }
+
+ for ( i=0 ; i<MAXSHOWLIMIT ; i++ )
+ {
+ FlushShowLimit(i);
+ }
+
+ while ( true )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, 0);
+ if ( pObj == 0 ) break;
+
+ pObj->DeleteObject(true); // destroys rapidly
+ delete pObj;
+ }
+}
+
+// Selects the human.
+
+void CRobotMain::SelectHuman()
+{
+ SelectObject(SearchHuman());
+}
+
+// Returns the object human.
+
+CObject* CRobotMain::SearchHuman()
+{
+ ObjectType type;
+ CObject* pObj;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_HUMAN )
+ {
+ return pObj;
+ }
+ }
+ return 0;
+}
+
+// Returns the object toto.
+
+CObject* CRobotMain::SearchToto()
+{
+ ObjectType type;
+ CObject* pObj;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_TOTO )
+ {
+ return pObj;
+ }
+ }
+ return 0;
+}
+
+// Returns the nearest selectable object from a given position.
+
+CObject* CRobotMain::SearchNearest(Math::Vector pos, CObject* pExclu)
+{
+ ObjectType type;
+ CObject *pObj, *pBest;
+ Math::Vector oPos;
+ float min, dist;
+ int i;
+
+ min = 100000.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == pExclu ) continue;
+ if ( !IsSelectable(pObj) ) continue;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_TOTO ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, pos);
+ if ( dist < min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+ return pBest;
+}
+
+// Returns the selected object.
+
+CObject* CRobotMain::RetSelect()
+{
+ CObject* pObj;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetSelect() )
+ {
+ return pObj;
+ }
+ }
+ return 0;
+}
+
+CObject* CRobotMain::SearchObject(ObjectType type)
+{
+ CObject* pObj;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetType() == type )
+ {
+ return pObj;
+ }
+ }
+ return 0;
+}
+
+// Detects the object aimed by the mouse.
+
+CObject* CRobotMain::DetectObject(Math::Point pos)
+{
+ ObjectType type;
+ CObject *pObj, *pTarget;
+ int objRank, i, j, rank;
+
+ objRank = m_engine->DetectObject(pos);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue;
+ if ( pObj->RetProxyActivate() ) continue;
+
+ pTarget = 0;
+ type = pObj->RetType();
+ if ( type == OBJECT_PORTICO ||
+ type == OBJECT_BASE ||
+ type == OBJECT_DERRICK ||
+ type == OBJECT_FACTORY ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_DESTROYER ||
+ type == OBJECT_STATION ||
+ type == OBJECT_CONVERT ||
+ type == OBJECT_TOWER ||
+ type == OBJECT_RESEARCH ||
+ type == OBJECT_RADAR ||
+ type == OBJECT_INFO ||
+ type == OBJECT_ENERGY ||
+ type == OBJECT_LABO ||
+ type == OBJECT_NUCLEAR ||
+ type == OBJECT_PARA ||
+ type == OBJECT_SAFE ||
+ type == OBJECT_HUSTON ||
+ type == OBJECT_TARGET1 ||
+ type == OBJECT_TARGET2 ||
+ type == OBJECT_START ||
+ type == OBJECT_END ||
+ type == OBJECT_STONE ||
+ type == OBJECT_URANIUM ||
+ type == OBJECT_BULLET ||
+ type == OBJECT_METAL ||
+ type == OBJECT_BBOX ||
+ type == OBJECT_KEYa ||
+ type == OBJECT_KEYb ||
+ type == OBJECT_KEYc ||
+ type == OBJECT_KEYd ||
+ type == OBJECT_TNT ||
+ type == OBJECT_SCRAP1 ||
+ type == OBJECT_SCRAP2 ||
+ type == OBJECT_SCRAP3 ||
+ type == OBJECT_SCRAP4 ||
+ type == OBJECT_SCRAP5 ||
+ type == OBJECT_BOMB ||
+ type == OBJECT_BAG ||
+ type == OBJECT_WAYPOINT ||
+ type == OBJECT_FLAGb ||
+ type == OBJECT_FLAGr ||
+ type == OBJECT_FLAGg ||
+ type == OBJECT_FLAGy ||
+ type == OBJECT_FLAGv ||
+ type == OBJECT_MARKPOWER ||
+ type == OBJECT_MARKSTONE ||
+ type == OBJECT_MARKURANIUM ||
+ type == OBJECT_MARKKEYa ||
+ type == OBJECT_MARKKEYb ||
+ type == OBJECT_MARKKEYc ||
+ type == OBJECT_MARKKEYd ||
+ type == OBJECT_HUMAN ||
+ type == OBJECT_TECH ||
+ type == OBJECT_TOTO ||
+ type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr ||
+ type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ||
+ type == OBJECT_EGG ||
+ type == OBJECT_RUINmobilew1 ||
+ type == OBJECT_RUINmobilew2 ||
+ type == OBJECT_RUINmobilet1 ||
+ type == OBJECT_RUINmobilet2 ||
+ type == OBJECT_RUINmobiler1 ||
+ type == OBJECT_RUINmobiler2 ||
+ type == OBJECT_RUINfactory ||
+ type == OBJECT_RUINdoor ||
+ type == OBJECT_RUINsupport ||
+ type == OBJECT_RUINradar ||
+ type == OBJECT_RUINconvert ||
+ type == OBJECT_RUINbase ||
+ type == OBJECT_RUINhead ||
+ type == OBJECT_APOLLO1 ||
+ type == OBJECT_APOLLO2 ||
+ type == OBJECT_APOLLO3 ||
+ type == OBJECT_APOLLO4 ||
+ type == OBJECT_APOLLO5 )
+ {
+ pTarget = pObj;
+ }
+ else if ( (type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC ) &&
+ pObj->RetTruck() != 0 ) // battery used?
+ {
+ pTarget = pObj->RetTruck();
+ }
+ else if ( type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC )
+ {
+ pTarget = pObj;
+ }
+
+ for ( j=0 ; j<OBJECTMAXPART ; j++ )
+ {
+ rank = pObj->RetObjectRank(j);
+ if ( rank == -1 ) continue;
+ if ( rank != objRank ) continue;
+ return pTarget;
+ }
+ }
+ return 0;
+}
+
+// Indicates whether an object is selectable.
+
+bool CRobotMain::IsSelectable(CObject* pObj)
+{
+ ObjectType type;
+
+ if ( !pObj->RetSelectable() ) return false;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TOTO ||
+ type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr ||
+ type == OBJECT_APOLLO2 ||
+ type == OBJECT_BASE ||
+ type == OBJECT_DERRICK ||
+ type == OBJECT_FACTORY ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_DESTROYER||
+ type == OBJECT_STATION ||
+ type == OBJECT_CONVERT ||
+ type == OBJECT_TOWER ||
+ type == OBJECT_RESEARCH ||
+ type == OBJECT_RADAR ||
+ type == OBJECT_INFO ||
+ type == OBJECT_ENERGY ||
+ type == OBJECT_LABO ||
+ type == OBJECT_NUCLEAR ||
+ type == OBJECT_PARA ||
+ type == OBJECT_SAFE ||
+ type == OBJECT_HUSTON )
+ {
+ return true;
+ }
+
+ if ( m_bSelectInsect )
+ {
+ if ( type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ||
+ type == OBJECT_MOBILEtg )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+// Deletes the selected object.
+
+bool CRobotMain::DeleteObject()
+{
+ CObject* pObj;
+ CPyro* pyro;
+
+ pObj = RetSelect();
+ if ( pObj == 0 ) return false;
+
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FRAGT, pObj);
+
+ pObj->SetSelect(false); // deselects the object
+ m_camera->SetType(CAMERA_EXPLO);
+ DeselectAll();
+ pObj->DeleteDeselList(pObj);
+
+ return true;
+}
+
+
+// Removes setting evidence of the object with the mouse hovers over.
+
+void CRobotMain::HiliteClear()
+{
+ CObject* pObj;
+ int i;
+
+ ClearTooltip();
+ m_tooltipName[0] = 0; // really removes the tooltip
+
+ if ( !m_bHilite ) return;
+
+ i = -1;
+ m_engine->SetHiliteRank(&i); // nothing more selected
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ pObj->SetHilite(false);
+ m_map->SetHilite(0);
+ m_short->SetHilite(0);
+ }
+
+ m_bHilite = false;
+}
+
+// Highlights the object with the mouse hovers over.
+
+void CRobotMain::HiliteObject(Math::Point pos)
+{
+ CObject* pObj;
+ char name[100];
+ bool bInMap;
+
+ if ( m_bFixScene && m_phase != PHASE_PERSO ) return;
+ if ( m_bMovieLock ) return;
+ if ( m_movie->IsExist() ) return;
+ if ( m_engine->RetMouseHide() ) return;
+
+ ClearInterface(); // removes setting evidence and tooltip
+
+ pObj = m_short->DetectShort(pos);
+
+ if ( m_dialog->RetTooltip() && m_interface->GetTooltip(pos, name) )
+ {
+ m_tooltipPos = pos;
+ strcpy(m_tooltipName, name);
+ m_tooltipTime = 0.0f;
+ if ( pObj == 0 ) return;
+ }
+
+ if ( m_bSuspend ) return;
+
+ if ( pObj == 0 )
+ {
+ pObj = m_map->DetectMap(pos, bInMap);
+ if ( pObj == 0 )
+ {
+ if ( bInMap ) return;
+
+ pObj = DetectObject(pos);
+
+ if ( m_camera->RetType() == CAMERA_ONBOARD &&
+ m_camera->RetObject() == pObj )
+ {
+ return;
+ }
+ }
+ }
+
+ if ( pObj != 0 )
+ {
+ if ( m_dialog->RetTooltip() && pObj->GetTooltipName(name) )
+ {
+ m_tooltipPos = pos;
+ strcpy(m_tooltipName, name);
+ m_tooltipTime = 0.0f;
+ }
+
+ if ( IsSelectable(pObj) )
+ {
+ pObj->SetHilite(true);
+ m_map->SetHilite(pObj);
+ m_short->SetHilite(pObj);
+ m_bHilite = true;
+ }
+ }
+}
+
+// Highlights the object with the mouse hovers over.
+
+void CRobotMain::HiliteFrame(float rTime)
+{
+ if ( m_bFixScene && m_phase != PHASE_PERSO ) return;
+ if ( m_bMovieLock ) return;
+ if ( m_movie->IsExist() ) return;
+
+ m_tooltipTime += rTime;
+
+ ClearTooltip();
+
+ if ( m_tooltipTime >= 0.2f &&
+ m_tooltipName[0] != 0 )
+ {
+ CreateTooltip(m_tooltipPos, m_tooltipName);
+ }
+}
+
+// Creates a tooltip.
+
+void CRobotMain::CreateTooltip(Math::Point pos, char* text)
+{
+ CWindow* pw;
+ Math::Point start, end, dim, offset, corner;
+
+ corner.x = pos.x+0.022f;
+ corner.y = pos.y-0.052f;
+
+ m_engine->RetText()->DimText(text, corner, 1,
+ SMALLFONT, NORMSTRETCH, FONT_COLOBOT,
+ start, end);
+ start.x -= 0.010f;
+ start.y -= 0.002f;
+ end.x += 0.010f;
+ end.y += 0.004f; // ch'tite (?) margin
+
+ pos.x = start.x;
+ pos.y = start.y;
+ dim.x = end.x-start.x;
+ dim.y = end.y-start.y;
+
+ offset.x = 0.0f;
+ offset.y = 0.0f;
+ if ( pos.x+dim.x > 1.0f ) offset.x = 1.0f-(pos.x+dim.x);
+ if ( pos.y < 0.0f ) offset.y = -pos.y;
+
+ corner.x += offset.x;
+ corner.y += offset.y;
+ pos.x += offset.x;
+ pos.y += offset.y;
+
+ m_interface->CreateWindows(pos, dim, 1, EVENT_TOOLTIP);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_TOOLTIP);
+ if ( pw != 0 )
+ {
+ pw->SetState(STATE_SHADOW);
+ pw->SetTrashEvent(false);
+
+ pos.y -= m_engine->RetText()->RetHeight(SMALLFONT, FONT_COLOBOT)/2.0f;
+ pw->CreateLabel(pos, dim, -1, EVENT_LABEL2, text);
+ }
+}
+
+// Clears the previous tooltip.
+
+void CRobotMain::ClearTooltip()
+{
+ m_interface->DeleteControl(EVENT_TOOLTIP);
+}
+
+
+// Displays help for an object.
+
+void CRobotMain::HelpObject()
+{
+ CObject* pObj;
+ char* filename;
+
+ pObj = RetSelect();
+ if ( pObj == 0 ) return;
+
+ filename = RetHelpFilename(pObj->RetType());
+ if ( filename[0] == 0 ) return;
+
+ StartDisplayInfo(filename, -1);
+}
+
+
+// Change the mode of the camera.
+
+void CRobotMain::ChangeCamera()
+{
+ CObject* pObj;
+ ObjectType oType;
+ CameraType type;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetSelect() )
+ {
+ if ( pObj->RetCameraLock() ) return;
+
+ oType = pObj->RetType();
+ type = pObj->RetCameraType();
+
+ if ( oType != OBJECT_MOBILEfa &&
+ oType != OBJECT_MOBILEta &&
+ oType != OBJECT_MOBILEwa &&
+ oType != OBJECT_MOBILEia &&
+ oType != OBJECT_MOBILEfc &&
+ oType != OBJECT_MOBILEtc &&
+ oType != OBJECT_MOBILEwc &&
+ oType != OBJECT_MOBILEic &&
+ oType != OBJECT_MOBILEfi &&
+ oType != OBJECT_MOBILEti &&
+ oType != OBJECT_MOBILEwi &&
+ oType != OBJECT_MOBILEii &&
+ oType != OBJECT_MOBILEfs &&
+ oType != OBJECT_MOBILEts &&
+ oType != OBJECT_MOBILEws &&
+ oType != OBJECT_MOBILEis &&
+ oType != OBJECT_MOBILErt &&
+ oType != OBJECT_MOBILErc &&
+ oType != OBJECT_MOBILErr &&
+ oType != OBJECT_MOBILErs &&
+ oType != OBJECT_MOBILEsa &&
+ oType != OBJECT_MOBILEtg &&
+ oType != OBJECT_MOBILEft &&
+ oType != OBJECT_MOBILEtt &&
+ oType != OBJECT_MOBILEwt &&
+ oType != OBJECT_MOBILEit &&
+ oType != OBJECT_MOBILEdr &&
+ oType != OBJECT_APOLLO2 ) return;
+
+ if ( oType == OBJECT_MOBILEdr ) // designer?
+ {
+ if ( type == CAMERA_PLANE ) type = CAMERA_BACK;
+ else if ( type == CAMERA_BACK ) type = CAMERA_PLANE;
+ }
+ else if ( pObj->RetTrainer() ) // trainer?
+ {
+ if ( type == CAMERA_ONBOARD ) type = CAMERA_FIX;
+ else if ( type == CAMERA_FIX ) type = CAMERA_PLANE;
+ else if ( type == CAMERA_PLANE ) type = CAMERA_BACK;
+ else if ( type == CAMERA_BACK ) type = CAMERA_ONBOARD;
+ }
+ else
+ {
+ if ( type == CAMERA_ONBOARD ) type = CAMERA_BACK;
+ else if ( type == CAMERA_BACK ) type = CAMERA_ONBOARD;
+ }
+
+ pObj->SetCameraType(type);
+ m_camera->SetType(type);
+ }
+ }
+}
+
+// Remote control the camera using the arrow keys.
+
+void CRobotMain::KeyCamera(EventMsg event, long param)
+{
+ CObject* pObj;
+
+ if ( event == EVENT_KEYUP )
+ {
+ if ( param == m_engine->RetKey(KEYRANK_LEFT, 0) ||
+ param == m_engine->RetKey(KEYRANK_LEFT, 1) )
+ {
+ m_cameraPan = 0.0f;
+ }
+
+ if ( param == m_engine->RetKey(KEYRANK_RIGHT, 0) ||
+ param == m_engine->RetKey(KEYRANK_RIGHT, 1) )
+ {
+ m_cameraPan = 0.0f;
+ }
+
+ if ( param == m_engine->RetKey(KEYRANK_UP, 0) ||
+ param == m_engine->RetKey(KEYRANK_UP, 1) )
+ {
+ m_cameraZoom = 0.0f;
+ }
+
+ if ( param == m_engine->RetKey(KEYRANK_DOWN, 0) ||
+ param == m_engine->RetKey(KEYRANK_DOWN, 1) )
+ {
+ m_cameraZoom = 0.0f;
+ }
+ }
+
+ if ( m_phase != PHASE_SIMUL ) return;
+ if ( m_bEditLock ) return; // current edition?
+ if ( m_bTrainerPilot ) return;
+
+ pObj = RetSelect();
+ if ( pObj == 0 ) return;
+ if ( !pObj->RetTrainer() ) return;
+
+ if ( event == EVENT_KEYDOWN )
+ {
+ if ( param == m_engine->RetKey(KEYRANK_LEFT, 0) ||
+ param == m_engine->RetKey(KEYRANK_LEFT, 1) )
+ {
+ m_cameraPan = -1.0f;
+ }
+
+ if ( param == m_engine->RetKey(KEYRANK_RIGHT, 0) ||
+ param == m_engine->RetKey(KEYRANK_RIGHT, 1) )
+ {
+ m_cameraPan = 1.0f;
+ }
+
+ if ( param == m_engine->RetKey(KEYRANK_UP, 0) ||
+ param == m_engine->RetKey(KEYRANK_UP, 1) )
+ {
+ m_cameraZoom = -1.0f;
+ }
+
+ if ( param == m_engine->RetKey(KEYRANK_DOWN, 0) ||
+ param == m_engine->RetKey(KEYRANK_DOWN, 1) )
+ {
+ m_cameraZoom = 1.0f;
+ }
+ }
+}
+
+// Panned with the camera if a button is pressed.
+
+void CRobotMain::RemoteCamera(float pan, float zoom, float rTime)
+{
+ float value;
+
+ if ( pan != 0.0f )
+ {
+ value = m_camera->RetRemotePan();
+ value += pan*rTime*1.5f;
+ m_camera->SetRemotePan(value);
+ }
+
+ if ( zoom != 0.0f )
+ {
+ value = m_camera->RetRemoteZoom();
+ value += zoom*rTime*0.3f;
+ m_camera->SetRemoteZoom(value);
+ }
+}
+
+
+
+// Cancels the current movie.
+
+void CRobotMain::AbortMovie()
+{
+ CObject* pObj;
+ CAuto* automat;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ automat = pObj->RetAuto();
+ if ( automat != 0 )
+ {
+ automat->Abort();
+ }
+ }
+
+ m_engine->SetMouseHide(false);
+}
+
+
+
+// Updates the text information.
+
+void CRobotMain::UpdateInfoText()
+{
+ CObject* pObj;
+ Math::Vector pos;
+ char info[100];
+
+ if ( m_bShowPos )
+ {
+ pObj = RetSelect();
+ if ( pObj != 0 )
+ {
+ pos = pObj->RetPosition(0);
+ sprintf(info, "Pos = %.2f ; %.2f", pos.x/g_unit, pos.z/g_unit);
+ m_engine->SetInfoText(4, info);
+ }
+ }
+}
+
+
+// Initializes the view.
+
+void CRobotMain::InitEye()
+{
+ if ( m_phase == PHASE_SIMUL )
+ {
+ m_camera->Init(Math::Vector( 0.0f, 10.0f, 0.0f),
+ Math::Vector(10.0f, 5.0f, 0.0f), 0.0f);
+ }
+
+ if ( m_phase == PHASE_MODEL )
+ {
+ m_model->InitView();
+ }
+}
+
+// Advances the entire scene.
+
+bool CRobotMain::EventFrame(const Event &event)
+{
+ ObjectType type;
+ CObject *pObj, *toto;
+ CPyro* pPyro;
+ CWindow* pw;
+ CMap* pm;
+ int i;
+
+ m_time += event.rTime;
+ if ( !m_bMovieLock ) m_gameTime += event.rTime;
+
+ if ( !m_bImmediatSatCom && !m_bBeginSatCom &&
+ m_gameTime > 0.1f && m_phase == PHASE_SIMUL )
+ {
+ m_displayText->DisplayError(INFO_BEGINSATCOM, Math::Vector(0.0f,0.0f,0.0f));
+ m_bBeginSatCom = true; // message appears
+ }
+
+ m_water->EventProcess(event);
+ m_cloud->EventProcess(event);
+ m_blitz->EventProcess(event);
+ m_planet->EventProcess(event);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw == 0 )
+ {
+ pm = 0;
+ }
+ else
+ {
+ pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
+ if ( pm != 0 ) pm->FlushObject();
+ }
+
+ toto = 0;
+ if ( !m_bFreePhoto )
+ {
+ // Advances all the robots, but not toto.
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pm != 0 ) pm->UpdateObject(pObj);
+ if ( pObj->RetTruck() != 0 ) continue;
+ type = pObj->RetType();
+ if ( type == OBJECT_TOTO )
+ {
+ toto = pObj;
+ }
+ else
+ {
+ pObj->EventProcess(event);
+ }
+ }
+ // Advances all objects transported by robots.
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pObj->RetTruck() == 0 ) continue;
+ pObj->EventProcess(event);
+ }
+
+ // Advances pyrotechnic effects.
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pPyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, i);
+ if ( pPyro == 0 ) break;
+
+ pPyro->EventProcess(event);
+ if ( pPyro->IsEnded() != ERR_CONTINUE )
+ {
+ pPyro->DeleteObject();
+ delete pPyro;
+ }
+ }
+ }
+
+ // The camera follows the object, because its position
+ // may depend on the selected object (CAMERA_ONBOARD or CAMERA_BACK).
+ if ( m_phase == PHASE_SIMUL && !m_bEditFull )
+ {
+ m_camera->EventProcess(event);
+
+ if ( m_engine->RetFog() )
+ {
+ m_camera->SetOverBaseColor(m_particule->RetFogColor(m_engine->RetEyePt()));
+ }
+ }
+ if ( m_phase == PHASE_PERSO ||
+ m_phase == PHASE_WIN ||
+ m_phase == PHASE_LOST )
+ {
+ m_camera->EventProcess(event);
+ }
+
+ // Advances toto following the camera, because its position depends on the camera.
+ if ( toto != 0 )
+ {
+ toto->EventProcess(event);
+ }
+
+ // Advances model.
+ if ( m_phase == PHASE_MODEL )
+ {
+ m_model->ViewMove(event, 2.0f);
+ m_model->UpdateView();
+ m_model->EventProcess(event);
+ }
+
+ HiliteFrame(event.rTime);
+
+ // Moves the film indicator.
+ if ( m_bMovieLock && !m_bEditLock ) // movie in progress?
+ {
+ CControl* pc;
+ Math::Point pos, dim;
+ float zoom;
+
+ pc = m_interface->SearchControl(EVENT_OBJECT_MOVIELOCK);
+ if ( pc != 0 )
+ {
+ dim.x = 32.0f/640.0f;
+ dim.y = 32.0f/480.0f;
+ pos.x = 20.0f/640.0f;
+ pos.y = (480.0f-24.0f)/480.0f;
+
+ zoom = 1.0f+sinf(m_time*6.0f)*0.1f; // 0.9 .. 1.1
+ dim.x *= zoom;
+ dim.y *= zoom;
+ pos.x -= dim.x/2.0f;
+ pos.y -= dim.y/2.0f;
+
+ pc->SetPos(pos);
+ pc->SetDim(dim);
+ }
+ }
+
+ // Moves edition indicator.
+ if ( m_bEditLock || m_bPause ) // edition in progress?
+ {
+ CControl* pc;
+ Math::Point pos, dim;
+ float zoom;
+
+ pc = m_interface->SearchControl(EVENT_OBJECT_EDITLOCK);
+ if ( pc != 0 )
+ {
+ if ( m_bEditFull || m_bEditLock )
+ {
+ dim.x = 10.0f/640.0f;
+ dim.y = 10.0f/480.0f;
+ pos.x = -20.0f/640.0f;
+ pos.y = -20.0f/480.0f; // invisible!
+ }
+ else
+ {
+ dim.x = 32.0f/640.0f;
+ dim.y = 32.0f/480.0f;
+ pos.x = 20.0f/640.0f;
+ pos.y = (480.0f-24.0f)/480.0f;
+
+ zoom = 1.0f+sinf(m_time*6.0f)*0.1f; // 0.9 .. 1.1
+ dim.x *= zoom;
+ dim.y *= zoom;
+ pos.x -= dim.x/2.0f;
+ pos.y -= dim.y/2.0f;
+ }
+ pc->SetPos(pos);
+ pc->SetDim(dim);
+ }
+ }
+
+ // Will move the arrow to visit.
+ if ( m_camera->RetType() == CAMERA_VISIT )
+ {
+ FrameVisit(event.rTime);
+ }
+
+ // Moves the boundaries.
+ FrameShowLimit(event.rTime);
+
+ if ( m_phase == PHASE_SIMUL )
+ {
+ if ( !m_bEditLock && m_checkEndTime+1.0f < m_time )
+ {
+ m_checkEndTime = m_time;
+ CheckEndMission(true);
+ }
+
+ if ( m_winDelay > 0.0f && !m_bEditLock )
+ {
+ m_winDelay -= event.rTime;
+ if ( m_winDelay <= 0.0f )
+ {
+ if ( m_bMovieLock )
+ {
+ m_winDelay = 1.0f;
+ }
+ else
+ {
+ Event newEvent;
+ m_event->MakeEvent(newEvent, EVENT_WIN);
+ m_event->AddEvent(newEvent);
+ }
+ }
+ }
+
+ if ( m_lostDelay > 0.0f && !m_bEditLock )
+ {
+ m_lostDelay -= event.rTime;
+ if ( m_lostDelay <= 0.0f )
+ {
+ if ( m_bMovieLock )
+ {
+ m_winDelay = 1.0f;
+ }
+ else
+ {
+ Event newEvent;
+ m_event->MakeEvent(newEvent, EVENT_LOST);
+ m_event->AddEvent(newEvent);
+ }
+ }
+ }
+ }
+
+ if ( m_delayWriteMessage > 0 )
+ {
+ m_delayWriteMessage --;
+ if ( m_delayWriteMessage == 0 )
+ {
+ m_displayText->DisplayError(INFO_WRITEOK, Math::Vector(0.0f,0.0f,0.0f));
+ }
+ }
+
+ return S_OK;
+}
+
+// Makes the event for all robots.
+
+bool CRobotMain::EventObject(const Event &event)
+{
+ CObject* pObj;
+ int i;
+
+ if ( m_bFreePhoto ) return S_OK;
+
+ m_bResetCreate = false;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ pObj->EventProcess(event);
+ }
+
+ if ( m_bResetCreate )
+ {
+ ResetCreate();
+ }
+
+ return S_OK;
+}
+
+
+// Calculates the point of arrival of the camera.
+
+Math::Vector CRobotMain::LookatPoint(Math::Vector eye, float angleH, float angleV,
+ float length)
+{
+ Math::Vector lookat;
+
+ lookat = eye;
+ lookat.z += length;
+
+ RotatePoint(eye, angleH, angleV, lookat);
+ return lookat;
+}
+
+
+
+char* SkipNum(char *p)
+{
+ while ( *p == ' ' || *p == '.' || *p == '-' || (*p >= '0' && *p <= '9') )
+ {
+ p++;
+ }
+ return p;
+}
+
+// Conversion of units.
+
+void CRobotMain::Convert()
+{
+ FILE* file = NULL;
+ FILE* fileNew = NULL;
+ char line[500];
+ char lineNew[500];
+ char s[200];
+ char* base;
+ char* p;
+ int rank;
+ Math::Vector pos;
+ float value;
+
+ base = m_dialog->RetSceneName();
+ rank = m_dialog->RetSceneRank();
+
+ m_dialog->BuildSceneName(line, base, rank);
+ file = fopen(line, "r");
+ if ( file == NULL ) return;
+
+ strcpy(line+strlen(line)-4, ".new");
+ fileNew = fopen(line, "w");
+ if ( fileNew == NULL ) return;
+
+ while ( fgets(line, 500, file) != NULL )
+ {
+ strcpy(lineNew, line);
+
+ if ( Cmd(line, "DeepView") )
+ {
+ p = strstr(line, "air=");
+ if ( p != 0 )
+ {
+ value = OpFloat(line, "air", 500.0f);
+ value /= g_unit;
+ p[0] = 0;
+ p = SkipNum(p+4);
+ strcpy(lineNew, line);
+ strcat(lineNew, "air=");
+ sprintf(s, "%.2f", value);
+ strcat(lineNew, s);
+ strcat(lineNew, " ");
+ strcat(lineNew, p);
+ }
+ strcpy(line, lineNew);
+
+ p = strstr(line, "water=");
+ if ( p != 0 )
+ {
+ value = OpFloat(line, "water", 100.0f);
+ value /= g_unit;
+ p[0] = 0;
+ p = SkipNum(p+6);
+ strcpy(lineNew, line);
+ strcat(lineNew, "water=");
+ sprintf(s, "%.2f", value);
+ strcat(lineNew, s);
+ strcat(lineNew, " ");
+ strcat(lineNew, p);
+ }
+ strcpy(line, lineNew);
+ }
+
+ if ( Cmd(line, "TerrainGenerate") )
+ {
+ p = strstr(line, "vision=");
+ if ( p != 0 )
+ {
+ value = OpFloat(line, "vision", 500.0f);
+ value /= g_unit;
+ p[0] = 0;
+ p = SkipNum(p+7);
+ strcpy(lineNew, line);
+ strcat(lineNew, "vision=");
+ sprintf(s, "%.2f", value);
+ strcat(lineNew, s);
+ strcat(lineNew, " ");
+ strcat(lineNew, p);
+ }
+ }
+
+ if ( Cmd(line, "CreateObject") ||
+ Cmd(line, "CreateSpot") )
+ {
+ p = strstr(line, "pos=");
+ if ( p != 0 )
+ {
+ pos = OpPos(line, "pos");
+ pos.x /= g_unit;
+ pos.y /= g_unit;
+ pos.z /= g_unit;
+ p[0] = 0;
+ p = SkipNum(p+4);
+ p = SkipNum(p+1);
+ strcpy(lineNew, line);
+ strcat(lineNew, "pos=");
+ sprintf(s, "%.2f", pos.x);
+ strcat(lineNew, s);
+ strcat(lineNew, ";");
+ sprintf(s, "%.2f", pos.z);
+ strcat(lineNew, s);
+ strcat(lineNew, " ");
+ strcat(lineNew, p);
+ }
+ }
+
+ if ( Cmd(line, "EndMissionTake") )
+ {
+ p = strstr(line, "pos=");
+ if ( p != 0 )
+ {
+ pos = OpPos(line, "pos");
+ pos.x /= g_unit;
+ pos.y /= g_unit;
+ pos.z /= g_unit;
+ p[0] = 0;
+ p = SkipNum(p+4);
+ p = SkipNum(p+1);
+ strcpy(lineNew, line);
+ strcat(lineNew, "pos=");
+ sprintf(s, "%.2f", pos.x);
+ strcat(lineNew, s);
+ strcat(lineNew, ";");
+ sprintf(s, "%.2f", pos.z);
+ strcat(lineNew, s);
+ strcat(lineNew, " ");
+ strcat(lineNew, p);
+ }
+ strcpy(line, lineNew);
+
+ p = strstr(line, "dist=");
+ if ( p != 0 )
+ {
+ value = OpFloat(line, "dist", 32.0f);
+ value /= g_unit;
+ p[0] = 0;
+ p = SkipNum(p+5);
+ strcpy(lineNew, line);
+ strcat(lineNew, "dist=");
+ sprintf(s, "%.2f", value);
+ strcat(lineNew, s);
+ strcat(lineNew, " ");
+ strcat(lineNew, p);
+ }
+ strcpy(line, lineNew);
+ }
+
+ if ( Cmd(line, "Camera") )
+ {
+ p = strstr(line, "pos=");
+ if ( p != 0 )
+ {
+ pos = OpPos(line, "pos");
+ pos.x /= g_unit;
+ pos.y /= g_unit;
+ pos.z /= g_unit;
+ p[0] = 0;
+ p = SkipNum(p+4);
+ p = SkipNum(p+1);
+ strcpy(lineNew, line);
+ strcat(lineNew, "pos=");
+ sprintf(s, "%.2f", pos.x);
+ strcat(lineNew, s);
+ strcat(lineNew, ";");
+ sprintf(s, "%.2f", pos.z);
+ strcat(lineNew, s);
+ strcat(lineNew, " ");
+ strcat(lineNew, p);
+ }
+ strcpy(line, lineNew);
+
+ p = strstr(line, "h=");
+ if ( p != 0 )
+ {
+ value = OpFloat(line, "h", 32.0f);
+ value /= g_unit;
+ p[0] = 0;
+ p = SkipNum(p+2);
+ strcpy(lineNew, line);
+ strcat(lineNew, "h=");
+ sprintf(s, "%.2f", value);
+ strcat(lineNew, s);
+ strcat(lineNew, " ");
+ strcat(lineNew, p);
+ }
+ strcpy(line, lineNew);
+ }
+
+ fputs(lineNew, fileNew);
+ }
+
+ fclose(fileNew);
+ fclose(file);
+}
+
+// Load the scene for the character.
+
+void CRobotMain::ScenePerso()
+{
+ CObject* pObj;
+
+ DeleteAllObjects(); // removes all the current 3D Scene
+ m_engine->FlushObject();
+ m_terrain->FlushRelief(); // all flat
+ m_terrain->FlushBuildingLevel();
+ m_terrain->FlushFlyingLimit();
+ m_light->FlushLight();
+ m_particule->FlushParticule();
+ m_iMan->Flush(CLASS_OBJECT);
+ m_iMan->Flush(CLASS_PHYSICS);
+ m_iMan->Flush(CLASS_BRAIN);
+ m_iMan->Flush(CLASS_PYRO);
+
+ m_dialog->SetSceneName("perso");
+ m_dialog->SetSceneRank(0);
+ CreateScene(false, true, false); // sets scene
+
+ m_engine->SetDrawWorld(false); // does not draw anything on the interface
+ m_engine->SetDrawFront(true); // draws on the human interface
+ pObj = SearchHuman();
+ if ( pObj != 0 )
+ {
+ CMotionHuman* mh;
+
+ pObj->SetDrawFront(true); // draws the interface
+
+ mh = (CMotionHuman*)pObj->RetMotion();
+ if ( mh != 0 )
+ {
+ mh->StartDisplayPerso();
+ }
+ }
+}
+
+// Creates the whole stage.
+
+void CRobotMain::CreateScene(bool bSoluce, bool bFixScene, bool bResetObject)
+{
+ CObject* pObj;
+ CObject* pSel;
+ CMotion* motion;
+ FILE* file = NULL;
+ char line[500];
+ char name[200];
+ char dir[100];
+ char op[100];
+ char* read;
+ char* stack;
+ char* base;
+ D3DCOLORVALUE color;
+ Math::Vector pos;
+ int rank, obj, i, rankObj, rankGadget;
+
+//? Convert();
+
+ base = m_dialog->RetSceneName();
+ rank = m_dialog->RetSceneRank();
+ read = m_dialog->RetSceneRead();
+ stack = m_dialog->RetStackRead();
+ m_dialog->SetUserDir(base, rank);
+
+ m_bFixScene = bFixScene;
+
+ g_id = 0;
+ m_bBase = false;
+
+ if ( !bResetObject )
+ {
+ g_build = 0;
+ g_researchDone = 0; // no research done
+ g_researchEnable = 0;
+
+ FlushDisplayInfo();
+ m_terrain->LevelFlush();
+ m_audioTrack = 0;
+ m_bAudioRepeat = true;
+ m_displayText->SetDelay(1.0f);
+ m_displayText->SetEnable(true);
+ m_bImmediatSatCom = false;
+ m_endingWinRank = 0;
+ m_endingLostRank = 0;
+ m_endTakeTotal = 0;
+ m_endTakeResearch = 0;
+ m_endTakeWinDelay = 2.0f;
+ m_endTakeLostDelay = 2.0f;
+ m_obligatoryTotal = 0;
+ m_prohibitedTotal = 0;
+ m_bMapShow = true;
+ m_bMapImage = false;
+ m_mapFilename[0] = 0;
+
+ m_colorRefBot.r = 10.0f/256.0f;
+ m_colorRefBot.g = 166.0f/256.0f;
+ m_colorRefBot.b = 254.0f/256.0f; // blue
+ m_colorRefBot.a = 0.0f;
+ m_colorNewBot = m_colorRefBot;
+
+ m_colorRefAlien.r = 135.0f/256.0f;
+ m_colorRefAlien.g = 170.0f/256.0f;
+ m_colorRefAlien.b = 13.0f/256.0f; // green
+ m_colorRefAlien.a = 0.0f;
+ m_colorNewAlien = m_colorRefAlien;
+
+ m_colorRefGreen.r = 135.0f/256.0f;
+ m_colorRefGreen.g = 170.0f/256.0f;
+ m_colorRefGreen.b = 13.0f/256.0f; // green
+ m_colorRefGreen.a = 0.0f;
+ m_colorNewGreen = m_colorRefGreen;
+
+ m_colorRefWater.r = 25.0f/256.0f;
+ m_colorRefWater.g = 255.0f/256.0f;
+ m_colorRefWater.b = 240.0f/256.0f; // cyan
+ m_colorRefWater.a = 0.0f;
+ m_colorNewWater = m_colorRefWater;
+
+ m_dialog->BuildResumeName(m_title, base, rank);
+ m_dialog->BuildResumeName(m_resume, base, rank);
+ GetResource(RES_TEXT, RT_SCRIPT_NEW, m_scriptName);
+ m_scriptFile[0] = 0;
+ }
+
+ m_dialog->BuildSceneName(line, base, rank);
+ file = fopen(line, "r");
+ if ( file == NULL ) return;
+
+ rankObj = 0;
+ rankGadget = 0;
+ pSel = 0;
+
+ while ( fgets(line, 500, file) != NULL )
+ {
+ for ( i=0 ; i<500 ; i++ )
+ {
+ if ( line[i] == '\t' ) line[i] = ' '; // replace tab by space
+ if ( line[i] == '/' && line[i+1] == '/' )
+ {
+ line[i] = 0;
+ break;
+ }
+ }
+
+ sprintf(op, "Title.%c", RetLanguageLetter());
+ if ( Cmd(line, op) && !bResetObject )
+ {
+ OpString(line, "text", m_title);
+ }
+
+ sprintf(op, "Resume.%c", RetLanguageLetter());
+ if ( Cmd(line, op) && !bResetObject )
+ {
+ OpString(line, "text", m_resume);
+ }
+
+ sprintf(op, "ScriptName.%c", RetLanguageLetter());
+ if ( Cmd(line, op) && !bResetObject )
+ {
+ OpString(line, "text", m_scriptName);
+ }
+
+ if ( Cmd(line, "ScriptFile") && !bResetObject )
+ {
+ OpString(line, "name", m_scriptFile);
+ }
+
+ if ( Cmd(line, "Instructions") && !bResetObject )
+ {
+ OpString(line, "name", name);
+//? sprintf(m_infoFilename[SATCOM_HUSTON], "help\\%s", name);
+ UserDir(m_infoFilename[SATCOM_HUSTON], name, "help");
+
+ m_bImmediatSatCom = OpInt(line, "immediat", 0);
+ }
+
+ if ( Cmd(line, "Satellite") && !bResetObject )
+ {
+ OpString(line, "name", name);
+//? sprintf(m_infoFilename[SATCOM_SAT], "help\\%s", name);
+ UserDir(m_infoFilename[SATCOM_SAT], name, "help");
+ }
+
+ if ( Cmd(line, "Loading") && !bResetObject )
+ {
+ OpString(line, "name", name);
+//? sprintf(m_infoFilename[SATCOM_LOADING], "help\\%s", name);
+ UserDir(m_infoFilename[SATCOM_LOADING], name, "help");
+ }
+
+ if ( Cmd(line, "HelpFile") && !bResetObject )
+ {
+ OpString(line, "name", name);
+//? sprintf(m_infoFilename[SATCOM_PROG], "help\\%s", name);
+ UserDir(m_infoFilename[SATCOM_PROG], name, "help");
+ }
+ if ( Cmd(line, "SoluceFile") && !bResetObject )
+ {
+ OpString(line, "name", name);
+//? sprintf(m_infoFilename[SATCOM_SOLUCE], "help\\%s", name);
+ UserDir(m_infoFilename[SATCOM_SOLUCE], name, "help");
+ }
+
+ if ( Cmd(line, "EndingFile") && !bResetObject )
+ {
+ m_endingWinRank = OpInt(line, "win", 0);
+ m_endingLostRank = OpInt(line, "lost", 0);
+ }
+
+ if ( Cmd(line, "MessageDelay") && !bResetObject )
+ {
+ m_displayText->SetDelay(OpFloat(line, "factor", 1.0f));
+ }
+
+ if ( Cmd(line, "Audio") && !bResetObject )
+ {
+ m_audioTrack = OpInt(line, "track", 0);
+ m_bAudioRepeat = OpInt(line, "repeat", 1);
+ }
+
+ if ( Cmd(line, "AmbiantColor") && !bResetObject )
+ {
+ m_engine->SetAmbiantColor(OpColor(line, "air", 0x88888888), 0);
+ m_engine->SetAmbiantColor(OpColor(line, "water", 0x88888888), 1);
+ }
+
+ if ( Cmd(line, "FogColor") && !bResetObject )
+ {
+ m_engine->SetFogColor(OpColor(line, "air", 0x88888888), 0);
+ m_engine->SetFogColor(OpColor(line, "water", 0x88888888), 1);
+ }
+
+ if ( Cmd(line, "VehicleColor") && !bResetObject )
+ {
+ m_colorNewBot = RetColor(OpColor(line, "color", 0x88888888));
+ }
+
+ if ( Cmd(line, "InsectColor") && !bResetObject )
+ {
+ m_colorNewAlien = RetColor(OpColor(line, "color", 0x88888888));
+ }
+
+ if ( Cmd(line, "GreeneryColor") && !bResetObject )
+ {
+ m_colorNewGreen = RetColor(OpColor(line, "color", 0x88888888));
+ }
+
+ if ( Cmd(line, "DeepView") && !bResetObject )
+ {
+ m_engine->SetDeepView(OpFloat(line, "air", 500.0f)*UNIT, 0, true);
+ m_engine->SetDeepView(OpFloat(line, "water", 100.0f)*UNIT, 1, true);
+ }
+
+ if ( Cmd(line, "FogStart") && !bResetObject )
+ {
+ m_engine->SetFogStart(OpFloat(line, "air", 0.5f), 0);
+ m_engine->SetFogStart(OpFloat(line, "water", 0.5f), 1);
+ }
+
+ if ( Cmd(line, "SecondTexture") && !bResetObject )
+ {
+ m_engine->SetSecondTexture(OpInt(line, "rank", 1));
+ }
+
+ if ( Cmd(line, "Background") && !bResetObject )
+ {
+ OpString(line, "image", name);
+ UserDir(dir, name, "");
+ m_engine->SetBackground(dir,
+ OpColor(line, "up", 0x00000000),
+ OpColor(line, "down", 0x00000000),
+ OpColor(line, "cloudUp", 0x00000000),
+ OpColor(line, "cloudDown", 0x00000000),
+ OpInt(line, "full", 0));
+ }
+
+ if ( Cmd(line, "Planet") && !bResetObject )
+ {
+ Math::Vector ppos, uv1, uv2;
+
+ ppos = OpPos(line, "pos");
+ uv1 = OpPos(line, "uv1");
+ uv2 = OpPos(line, "uv2");
+ OpString(line, "image", name);
+ UserDir(dir, name, "");
+ m_planet->Create(OpInt(line, "mode", 0),
+ Math::Point(ppos.x, ppos.z),
+ OpFloat(line, "dim", 0.2f),
+ OpFloat(line, "speed", 0.0f),
+ OpFloat(line, "dir", 0.0f),
+ dir,
+ Math::Point(uv1.x, uv1.z),
+ Math::Point(uv2.x, uv2.z));
+ }
+
+ if ( Cmd(line, "FrontsizeName") && !bResetObject )
+ {
+ OpString(line, "image", name);
+ UserDir(dir, name, "");
+ m_engine->SetFrontsizeName(dir);
+ }
+
+ if ( Cmd(line, "Global") && !bResetObject )
+ {
+ g_unit = OpFloat(line, "unitScale", 4.0f);
+ m_engine->SetTracePrecision(OpFloat(line, "traceQuality", 1.0f));
+ m_bShortCut = OpInt(line, "shortcut", 1);
+ }
+
+ if ( Cmd(line, "TerrainGenerate") && !bResetObject )
+ {
+ m_terrain->Generate(OpInt(line, "mosaic", 20),
+ OpInt(line, "brick", 3),
+ OpFloat(line, "size", 20.0f),
+ OpFloat(line, "vision", 500.0f)*UNIT,
+ OpInt(line, "depth", 2),
+ OpFloat(line, "hard", 0.5f));
+ }
+
+ if ( Cmd(line, "TerrainWind") && !bResetObject )
+ {
+ m_terrain->SetWind(OpPos(line, "speed"));
+ }
+
+ if ( Cmd(line, "TerrainRelief") && !bResetObject )
+ {
+ OpString(line, "image", name);
+ UserDir(dir, name, "textures");
+ m_terrain->ReliefFromBMP(dir, OpFloat(line, "factor", 1.0f), OpInt(line, "border", 1));
+ }
+
+ if ( Cmd(line, "TerrainReliefDXF") && !bResetObject )
+ {
+ OpString(line, "image", name);
+ UserDir(dir, name, "textures");
+ m_terrain->ReliefFromDXF(dir, OpFloat(line, "factor", 1.0f));
+ }
+
+ if ( Cmd(line, "TerrainResource") && !bResetObject )
+ {
+ OpString(line, "image", name);
+ UserDir(dir, name, "textures");
+ m_terrain->ResFromBMP(dir);
+ }
+
+ if ( Cmd(line, "TerrainWater") && !bResetObject )
+ {
+ OpString(line, "image", name);
+ UserDir(dir, name, "");
+ pos.x = OpFloat(line, "moveX", 0.0f);
+ pos.y = OpFloat(line, "moveY", 0.0f);
+ pos.z = pos.x;
+ m_water->Create(OpTypeWater(line, "air", WATER_TT),
+ OpTypeWater(line, "water", WATER_TT),
+ dir,
+ RetColor(OpColor(line, "diffuse", 0xffffffff)),
+ RetColor(OpColor(line, "ambiant", 0xffffffff)),
+ OpFloat(line, "level", 100.0f)*UNIT,
+ OpFloat(line, "glint", 1.0f),
+ pos);
+ m_colorNewWater = RetColor(OpColor(line, "color", RetColor(m_colorRefWater)));
+ m_colorShiftWater = OpFloat(line, "brightness", 0.0f);
+ }
+
+ if ( Cmd(line, "TerrainLava") && !bResetObject )
+ {
+ m_water->SetLava(OpInt(line, "mode", 0));
+ }
+
+ if ( Cmd(line, "TerrainCloud") && !bResetObject )
+ {
+ OpString(line, "image", name);
+ UserDir(dir, name, "");
+ m_cloud->Create(dir,
+ RetColor(OpColor(line, "diffuse", 0xffffffff)),
+ RetColor(OpColor(line, "ambiant", 0xffffffff)),
+ OpFloat(line, "level", 500.0f)*UNIT);
+ }
+
+ if ( Cmd(line, "TerrainBlitz") && !bResetObject )
+ {
+ m_blitz->Create(OpFloat(line, "sleep", 0.0f),
+ OpFloat(line, "delay", 3.0f),
+ OpFloat(line, "magnetic", 50.0f)*UNIT);
+ }
+
+ if ( Cmd(line, "TerrainInitTextures") && !bResetObject )
+ {
+ int dx, dy, tt[100];
+ char* op;
+
+ OpString(line, "image", name);
+ AddExt(name, ".tga");
+ dx = OpInt(line, "dx", 1);
+ dy = OpInt(line, "dy", 1);
+ op = SearchOp(line, "table");
+ for ( i=0 ; i<dx*dy ; i++ )
+ {
+ tt[i] = GetInt(op, i, 0);
+ }
+
+ if ( strstr(name, "%user%") != 0 )
+ {
+ CopyFileListToTemp(name, tt, dx*dy);
+ }
+
+ m_terrain->InitTextures(name, tt, dx, dy);
+ }
+
+ if ( Cmd(line, "TerrainInit") && !bResetObject )
+ {
+ m_terrain->LevelInit(OpInt(line, "id", 1));
+ }
+
+ if ( Cmd(line, "TerrainMaterial") && !bResetObject )
+ {
+ OpString(line, "image", name);
+ AddExt(name, ".tga");
+ if ( strstr(name, "%user%") != 0 )
+ {
+ CopyFileToTemp(name);
+ }
+
+ m_terrain->LevelMaterial(OpInt(line, "id", 0),
+ name,
+ OpFloat(line, "u", 0.0f),
+ OpFloat(line, "v", 0.0f),
+ OpInt(line, "up", 1),
+ OpInt(line, "right", 1),
+ OpInt(line, "down", 1),
+ OpInt(line, "left", 1),
+ OpFloat(line, "hard", 0.5f));
+ }
+
+ if ( Cmd(line, "TerrainLevel") && !bResetObject )
+ {
+ int id[50];
+ char* op;
+
+ op = SearchOp(line, "id");
+ i = 0;
+ while ( true )
+ {
+ id[i] = GetInt(op, i, 0);
+ if ( id[i++] == 0 ) break;
+ }
+
+ m_terrain->LevelGenerate(id,
+ OpFloat(line, "min", 0.0f)*UNIT,
+ OpFloat(line, "max", 100.0f)*UNIT,
+ OpFloat(line, "slope", 5.0f),
+ OpFloat(line, "freq", 100.0f),
+ OpPos(line, "center")*g_unit,
+ OpFloat(line, "radius", 0.0f)*g_unit);
+ }
+
+ if ( Cmd(line, "TerrainCreate") && !bResetObject )
+ {
+ m_terrain->CreateObjects(true);
+ }
+
+ if ( Cmd(line, "BeginObject") )
+ {
+ InitEye();
+ SetMovieLock(false);
+ if ( !m_bFixScene )
+ {
+//? CreateObject(Math::Vector(0.0f, 0.0f, 0.0f), 0.0f, 0.0f, OBJECT_TOTO);
+ }
+
+ if ( read[0] != 0 ) // loading file ?
+ {
+ pSel = IOReadScene(read, stack);
+ }
+ }
+
+ if ( Cmd(line, "CreateObject") && read[0] == 0 )
+ {
+ CObject* pObj;
+ CBrain* pBrain;
+ CAuto* pAuto;
+ CPyro* pyro;
+ ObjectType type;
+ PyroType pType;
+ CameraType cType;
+ Info info;
+ float dir;
+ char op[20];
+ char text[100];
+ char* p;
+ int run, gadget;
+
+ type = OpTypeObject(line, "type", OBJECT_NULL);
+
+ gadget = OpInt(line, "gadget", -1);
+ if ( gadget == -1 )
+ {
+ gadget = 0;
+ if ( type == OBJECT_TECH ||
+ (type >= OBJECT_PLANT0 &&
+ type <= OBJECT_PLANT19 ) ||
+ (type >= OBJECT_TREE0 &&
+ type <= OBJECT_TREE9 ) ||
+ (type >= OBJECT_TEEN0 &&
+ type <= OBJECT_TEEN49 ) ||
+ (type >= OBJECT_QUARTZ0 &&
+ type <= OBJECT_QUARTZ9 ) ||
+ (type >= OBJECT_ROOT0 &&
+ type <= OBJECT_ROOT4 ) ) // not ROOT5!
+ {
+ if ( type != OBJECT_TEEN11 && // lamp?
+ type != OBJECT_TEEN12 && // coke?
+ type != OBJECT_TEEN20 && // wall?
+ type != OBJECT_TEEN21 && // wall?
+ type != OBJECT_TEEN22 && // wall?
+ type != OBJECT_TEEN26 && // lamp?
+ type != OBJECT_TEEN28 && // bottle?
+ type != OBJECT_TEEN34 ) // stone?
+ {
+ gadget = 1;
+ }
+ }
+ }
+ if ( gadget != 0 ) // is this a gadget?
+ {
+ if ( !TestGadgetQuantity(rankGadget++) ) continue;
+ }
+
+ pos = OpPos(line, "pos")*g_unit;
+ dir = OpFloat(line, "dir", 0.0f)*Math::PI;
+ pObj = CreateObject(pos, dir,
+ OpFloat(line, "z", 1.0f),
+ OpFloat(line, "h", 0.0f),
+ type,
+ OpFloat(line, "power", 1.0f),
+ OpInt(line, "trainer", 0),
+ OpInt(line, "toy", 0),
+ OpInt(line, "option", 0));
+
+ if ( pObj != 0 )
+ {
+ pObj->SetDefRank(rankObj);
+
+ if ( type == OBJECT_BASE ) m_bBase = true;
+
+ cType = OpCamera(line, "camera");
+ if ( cType != CAMERA_NULL )
+ {
+ pObj->SetCameraType(cType);
+ }
+ pObj->SetCameraDist(OpFloat(line, "cameraDist", 50.0f));
+ pObj->SetCameraLock(OpInt(line, "cameraLock", 0));
+
+ pType = OpPyro(line, "pyro");
+ if ( pType != PT_NULL )
+ {
+ pyro = new CPyro(m_iMan);
+ pyro->Create(pType, pObj);
+ }
+
+ // Puts information in terminal (OBJECT_INFO).
+ for ( i=0 ; i<OBJECTMAXINFO ; i++ )
+ {
+ sprintf(op, "info%d", i+1);
+ OpString(line, op, text);
+ if ( text[0] == 0 ) break;
+ p = strchr(text, '=');
+ if ( p == 0 ) break;
+ *p = 0;
+ strcpy(info.name, text);
+ sscanf(p+1, "%f", &info.value);
+ pObj->SetInfo(i, info);
+ }
+
+ // Sets the parameters of the command line.
+ p = SearchOp(line, "cmdline");
+ for ( i=0 ; i<OBJECTMAXCMDLINE ; i++ )
+ {
+ float value;
+ value = GetFloat(p, i, NAN);
+ if ( value == NAN ) break;
+ pObj->SetCmdLine(i, value);
+ }
+
+ if ( OpInt(line, "select", 0) == 1 )
+ {
+ pSel = pObj;
+ }
+
+ pObj->SetSelectable(OpInt(line, "selectable", 1));
+ pObj->SetEnable(OpInt(line, "enable", 1));
+ pObj->SetProxyActivate(OpInt(line, "proxyActivate", 0));
+ pObj->SetProxyDistance(OpFloat(line, "proxyDistance", 15.0f)*g_unit);
+ pObj->SetRange(OpFloat(line, "range", 30.0f));
+ pObj->SetShield(OpFloat(line, "shield", 1.0f));
+ pObj->SetMagnifyDamage(OpFloat(line, "magnifyDamage", 1.0f));
+ pObj->SetClip(OpInt(line, "clip", 1));
+ pObj->SetCheckToken(OpInt(line, "checkToken", 1));
+ pObj->SetManual(OpInt(line, "manual", 0));
+
+ motion = pObj->RetMotion();
+ if ( motion != 0 )
+ {
+ p = SearchOp(line, "param");
+ for ( i=0 ; i<10 ; i++ )
+ {
+ float value;
+ value = GetFloat(p, i, NAN);
+ if ( value == NAN ) break;
+ motion->SetParam(i, value);
+ }
+ }
+
+ run = -1;
+ pBrain = pObj->RetBrain();
+ if ( pBrain != 0 )
+ {
+ for ( i=0 ; i<10 ; i++ )
+ {
+ sprintf(op, "script%d", i+1); // script1..script10
+ OpString(line, op, name);
+#if _SCHOOL
+ if ( !m_dialog->RetSoluce4() && i == 3 ) continue;
+#endif
+ if ( name[0] != 0 )
+ {
+ pBrain->SetScriptName(i, name);
+ }
+ }
+
+ i = OpInt(line, "run", 0);
+ if ( i != 0 )
+ {
+ run = i-1;
+ pBrain->SetScriptRun(run);
+ }
+ }
+ pAuto = pObj->RetAuto();
+ if ( pAuto != 0 )
+ {
+ type = OpTypeObject(line, "autoType", OBJECT_NULL);
+ pAuto->SetType(type);
+ for ( i=0 ; i<5 ; i++ )
+ {
+ sprintf(op, "autoValue%d", i+1); // autoValue1..autoValue5
+ pAuto->SetValue(i, OpFloat(line, op, 0.0f));
+ }
+ OpString(line, "autoString", name);
+ pAuto->SetString(name);
+
+ i = OpInt(line, "run", -1);
+ if ( i != -1 )
+ {
+ if ( i != PARAM_FIXSCENE &&
+ !m_dialog->RetMovies() ) i = 0;
+ pAuto->Start(i); // starts the film
+ }
+ }
+
+ OpString(line, "soluce", name);
+ if ( bSoluce && pBrain != 0 && name[0] != 0 )
+ {
+ pBrain->SetSoluceName(name);
+ }
+
+ pObj->SetResetPosition(pObj->RetPosition(0));
+ pObj->SetResetAngle(pObj->RetAngle(0));
+ pObj->SetResetRun(run);
+
+ if ( OpInt(line, "reset", 0) == 1 )
+ {
+ pObj->SetResetCap(RESET_MOVE);
+ }
+ }
+
+ rankObj ++;
+ }
+
+ if ( Cmd(line, "CreateFog") && !bResetObject )
+ {
+ ParticuleType type;
+ Math::Point dim;
+ float height, ddim, delay;
+
+ type = (ParticuleType)(PARTIFOG0+OpInt(line, "type", 0));
+ pos = OpPos(line, "pos")*g_unit;
+ height = OpFloat(line, "height", 1.0f)*g_unit;
+ ddim = OpFloat(line, "dim", 50.0f)*g_unit;
+ delay = OpFloat(line, "delay", 2.0f);
+ m_terrain->MoveOnFloor(pos);
+ pos.y += height;
+ dim.x = ddim;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), dim, type, delay, 0.0f, 0.0f);
+ }
+
+ if ( Cmd(line, "CreateLight") && !bResetObject )
+ {
+ D3DTypeObj type;
+
+ color.r = 0.5f;
+ color.g = 0.5f;
+ color.b = 0.5f;
+ color.a = 1.0f;
+ obj = CreateLight(OpDir(line, "dir"),
+ OpColorValue(line, "color", color));
+
+ type = OpTypeTerrain(line, "type", TYPENULL);
+ if ( type == TYPETERRAIN )
+ {
+ m_light->SetLightIncluType(obj, TYPETERRAIN);
+ }
+ if ( type == TYPEQUARTZ )
+ {
+ m_light->SetLightIncluType(obj, TYPEQUARTZ);
+ }
+ if ( type == TYPEMETAL )
+ {
+ m_light->SetLightIncluType(obj, TYPEMETAL);
+ }
+ if ( type == TYPEFIX )
+ {
+ m_light->SetLightExcluType(obj, TYPETERRAIN);
+ }
+ }
+ if ( Cmd(line, "CreateSpot") && !bResetObject )
+ {
+ D3DTypeObj type;
+
+ color.r = 0.5f;
+ color.g = 0.5f;
+ color.b = 0.5f;
+ color.a = 1.0f;
+ obj = CreateSpot(OpDir(line, "pos")*g_unit,
+ OpColorValue(line, "color", color));
+
+ type = OpTypeTerrain(line, "type", TYPENULL);
+ if ( type == TYPETERRAIN )
+ {
+ m_light->SetLightIncluType(obj, TYPETERRAIN);
+ }
+ if ( type == TYPEQUARTZ )
+ {
+ m_light->SetLightIncluType(obj, TYPEQUARTZ);
+ }
+ if ( type == TYPEMETAL )
+ {
+ m_light->SetLightIncluType(obj, TYPEMETAL);
+ }
+ if ( type == TYPEFIX )
+ {
+ m_light->SetLightExcluType(obj, TYPETERRAIN);
+ }
+ }
+
+ if ( Cmd(line, "GroundSpot") && !bResetObject )
+ {
+ rank = m_engine->GroundSpotCreate();
+ if ( rank != -1 )
+ {
+ m_engine->SetObjectGroundSpotPos(rank, OpPos(line, "pos")*g_unit);
+ m_engine->SetObjectGroundSpotRadius(rank, OpFloat(line, "radius", 10.0f)*g_unit);
+ m_engine->SetObjectGroundSpotColor(rank, RetColor(OpColor(line, "color", 0x88888888)));
+ m_engine->SetObjectGroundSpotSmooth(rank, OpFloat(line, "smooth", 1.0f));
+ m_engine->SetObjectGroundSpotMinMax(rank, OpFloat(line, "min", 0.0f)*g_unit,
+ OpFloat(line, "max", 0.0f)*g_unit);
+ }
+ }
+
+ if ( Cmd(line, "WaterColor") && !bResetObject )
+ {
+ color.r = 0.0f;
+ color.g = 0.0f;
+ color.b = 0.0f;
+ color.a = 1.0f;
+ m_engine->SetWaterAddColor(OpColorValue(line, "color", color));
+ }
+
+ if ( Cmd(line, "MapColor") && !bResetObject )
+ {
+ m_map->FloorColorMap(RetColor(OpColor(line, "floor", 0x88888888)),
+ RetColor(OpColor(line, "water", 0x88888888)));
+ m_bMapShow = OpInt(line, "show", 1);
+ m_map->ShowMap(m_bMapShow);
+ m_map->SetToy(OpInt(line, "toyIcon", 0));
+ m_bMapImage = OpInt(line, "image", 0);
+ if ( m_bMapImage )
+ {
+ Math::Vector offset;
+ OpString(line, "filename", m_mapFilename);
+ offset = OpPos(line, "offset");
+ m_map->SetFixParam(OpFloat(line, "zoom", 1.0f),
+ offset.x, offset.z,
+ OpFloat(line, "angle", 0.0f)*Math::PI/180.0f,
+ OpInt(line, "mode", 0),
+ OpInt(line, "debug", 0));
+ }
+ }
+ if ( Cmd(line, "MapZoom") && !bResetObject )
+ {
+ m_map->ZoomMap(OpFloat(line, "factor", 2.0f));
+ m_map->MapEnable(OpInt(line, "enable", 1));
+ }
+
+ if ( Cmd(line, "MaxFlyingHeight") && !bResetObject )
+ {
+ m_terrain->SetFlyingMaxHeight(OpFloat(line, "max", 280.0f)*g_unit);
+ }
+ if ( Cmd(line, "AddFlyingHeight") && !bResetObject )
+ {
+ m_terrain->AddFlyingLimit(OpPos(line, "center")*g_unit,
+ OpFloat(line, "extRadius", 20.0f)*g_unit,
+ OpFloat(line, "intRadius", 10.0f)*g_unit,
+ OpFloat(line, "maxHeight", 200.0f));
+ }
+
+ if ( Cmd(line, "Camera") )
+ {
+ m_camera->Init(OpDir(line, "eye")*g_unit,
+ OpDir(line, "lookat")*g_unit,
+ bResetObject?0.0f:OpFloat(line, "delay", 0.0f));
+
+ if ( OpInt(line, "fadeIn", 0) == 1 )
+ {
+ m_camera->StartOver(OE_FADEINw, Math::Vector(0.0f, 0.0f, 0.0f), 1.0f);
+ }
+ m_camera->SetFixDirection(OpFloat(line, "fixDirection", 0.25f)*Math::PI);
+ }
+
+ if ( Cmd(line, "EndMissionTake") && !bResetObject )
+ {
+ i = m_endTakeTotal;
+ if ( i < 10 )
+ {
+ m_endTake[i].pos = OpPos(line, "pos")*g_unit;
+ m_endTake[i].dist = OpFloat(line, "dist", 8.0f)*g_unit;
+ m_endTake[i].type = OpTypeObject(line, "type", OBJECT_NULL);
+ m_endTake[i].min = OpInt(line, "min", 1);
+ m_endTake[i].max = OpInt(line, "max", 9999);
+ m_endTake[i].lost = OpInt(line, "lost", -1);
+ m_endTake[i].bImmediat = OpInt(line, "immediat", 0);
+ OpString(line, "message", m_endTake[i].message);
+ m_endTakeTotal ++;
+ }
+ }
+ if ( Cmd(line, "EndMissionDelay") && !bResetObject )
+ {
+ m_endTakeWinDelay = OpFloat(line, "win", 2.0f);
+ m_endTakeLostDelay = OpFloat(line, "lost", 2.0f);
+ }
+ if ( Cmd(line, "EndMissionResearch") && !bResetObject )
+ {
+ m_endTakeResearch |= OpResearch(line, "type");
+ }
+
+ if ( Cmd(line, "ObligatoryToken") && !bResetObject )
+ {
+ i = m_obligatoryTotal;
+ if ( i < 100 )
+ {
+ OpString(line, "text", m_obligatoryToken[i]);
+ m_obligatoryTotal ++;
+ }
+ }
+
+ if ( Cmd(line, "ProhibitedToken") && !bResetObject )
+ {
+ i = m_prohibitedTotal;
+ if ( i < 100 )
+ {
+ OpString(line, "text", m_prohibitedToken[i]);
+ m_prohibitedTotal ++;
+ }
+ }
+
+ if ( Cmd(line, "EnableBuild") && !bResetObject )
+ {
+ g_build |= OpBuild(line, "type");
+ }
+
+ if ( Cmd(line, "EnableResearch") && !bResetObject )
+ {
+ g_researchEnable |= OpResearch(line, "type");
+ }
+ if ( Cmd(line, "DoneResearch") && read[0] == 0 && !bResetObject ) // not loading file?
+ {
+ g_researchDone |= OpResearch(line, "type");
+ }
+
+ if ( Cmd(line, "NewScript") && !bResetObject )
+ {
+ OpString(line, "name", name);
+ AddNewScriptName(OpTypeObject(line, "type", OBJECT_NULL), name);
+ }
+ }
+
+ fclose(file);
+
+ if ( read[0] == 0 )
+ {
+ CompileScript(bSoluce); // compiles all scripts
+ }
+
+ if ( strcmp(base, "scene") == 0 && !bResetObject ) // mission?
+ {
+ WriteFreeParam();
+ }
+ if ( strcmp(base, "free") == 0 && !bResetObject ) // free play?
+ {
+ g_researchDone = m_freeResearch;
+
+ g_build = m_freeBuild;
+ g_build &= ~BUILD_RESEARCH;
+ g_build &= ~BUILD_LABO;
+ g_build |= BUILD_FACTORY;
+ g_build |= BUILD_GFLAT;
+ g_build |= BUILD_FLAG;
+ }
+
+ if ( !bResetObject )
+ {
+ ChangeColor(); // changes the colors of texture
+ m_short->SetMode(false); // vehicles?
+ }
+
+ CreateShortcuts();
+ m_map->UpdateMap();
+ m_engine->TimeInit();
+ m_engine->FlushPressKey();
+ m_time = 0.0f;
+ m_gameTime = 0.0f;
+ m_checkEndTime = 0.0f;
+ m_infoUsed = 0;
+
+ m_selectObject = pSel;
+
+ if ( !m_bBase && // no main base?
+ !m_bFixScene ) // interractive scene?
+ {
+ if ( pSel == 0 )
+ {
+ pObj = SearchHuman();
+ }
+ else
+ {
+ pObj = pSel;
+ }
+ if ( pObj != 0 )
+ {
+ SelectObject(pObj);
+ m_camera->SetObject(pObj);
+//? m_camera->SetType(CAMERA_BACK);
+ m_camera->SetType(pObj->RetCameraType());
+ }
+ }
+ if ( m_bFixScene )
+ {
+ m_camera->SetType(CAMERA_SCRIPT);
+ }
+
+ if ( read[0] != 0 && pSel != 0 ) // loading file?
+ {
+ pos = pSel->RetPosition(0);
+ m_camera->Init(pos, pos, 0.0f);
+ m_camera->FixCamera();
+
+ SelectObject(pSel);
+ m_camera->SetObject(pSel);
+
+ m_bBeginSatCom = true; // message already displayed
+ }
+ m_dialog->SetSceneRead("");
+ m_dialog->SetStackRead("");
+}
+
+// Creates an object of decoration mobile or stationary.
+
+CObject* CRobotMain::CreateObject(Math::Vector pos, float angle, float zoom, float height,
+ ObjectType type, float power,
+ bool bTrainer, bool bToy,
+ int option)
+{
+ CObject* pObject = 0;
+ CAuto* automat;
+
+ if ( type == OBJECT_NULL ) return 0;
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH )
+ {
+ bTrainer = false; // necessarily
+ }
+
+ if ( type == OBJECT_PORTICO ||
+ type == OBJECT_BASE ||
+ type == OBJECT_DERRICK ||
+ type == OBJECT_FACTORY ||
+ type == OBJECT_STATION ||
+ type == OBJECT_CONVERT ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_DESTROYER||
+ type == OBJECT_TOWER ||
+ type == OBJECT_NEST ||
+ type == OBJECT_RESEARCH ||
+ type == OBJECT_RADAR ||
+ type == OBJECT_INFO ||
+ type == OBJECT_ENERGY ||
+ type == OBJECT_LABO ||
+ type == OBJECT_NUCLEAR ||
+ type == OBJECT_PARA ||
+ type == OBJECT_SAFE ||
+ type == OBJECT_HUSTON ||
+ type == OBJECT_TARGET1 ||
+ type == OBJECT_TARGET2 ||
+ type == OBJECT_START ||
+ type == OBJECT_END )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateBuilding(pos, angle, height, type, power);
+
+ automat = pObject->RetAuto();
+ if ( automat != 0 )
+ {
+ automat->Init();
+ }
+ }
+ else
+ if ( type == OBJECT_FRET ||
+ type == OBJECT_STONE ||
+ type == OBJECT_URANIUM ||
+ type == OBJECT_METAL ||
+ type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC ||
+ type == OBJECT_BULLET ||
+ type == OBJECT_BBOX ||
+ type == OBJECT_KEYa ||
+ type == OBJECT_KEYb ||
+ type == OBJECT_KEYc ||
+ type == OBJECT_KEYd ||
+ type == OBJECT_TNT ||
+ type == OBJECT_SCRAP1 ||
+ type == OBJECT_SCRAP2 ||
+ type == OBJECT_SCRAP3 ||
+ type == OBJECT_SCRAP4 ||
+ type == OBJECT_SCRAP5 ||
+ type == OBJECT_BOMB ||
+ type == OBJECT_WAYPOINT ||
+ type == OBJECT_SHOW ||
+ type == OBJECT_WINFIRE ||
+ type == OBJECT_BAG ||
+ type == OBJECT_MARKPOWER ||
+ type == OBJECT_MARKSTONE ||
+ type == OBJECT_MARKURANIUM ||
+ type == OBJECT_MARKKEYa ||
+ type == OBJECT_MARKKEYb ||
+ type == OBJECT_MARKKEYc ||
+ type == OBJECT_MARKKEYd ||
+ type == OBJECT_EGG )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateResource(pos, angle, type, power);
+ }
+ else
+ if ( type == OBJECT_FLAGb ||
+ type == OBJECT_FLAGr ||
+ type == OBJECT_FLAGg ||
+ type == OBJECT_FLAGy ||
+ type == OBJECT_FLAGv )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateFlag(pos, angle, type);
+ }
+ else
+ if ( type == OBJECT_BARRIER0 ||
+ type == OBJECT_BARRIER1 ||
+ type == OBJECT_BARRIER2 ||
+ type == OBJECT_BARRIER3 ||
+ type == OBJECT_BARRIER4 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateBarrier(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_PLANT0 ||
+ type == OBJECT_PLANT1 ||
+ type == OBJECT_PLANT2 ||
+ type == OBJECT_PLANT3 ||
+ type == OBJECT_PLANT4 ||
+ type == OBJECT_PLANT5 ||
+ type == OBJECT_PLANT6 ||
+ type == OBJECT_PLANT7 ||
+ type == OBJECT_PLANT8 ||
+ type == OBJECT_PLANT9 ||
+ type == OBJECT_PLANT10 ||
+ type == OBJECT_PLANT11 ||
+ type == OBJECT_PLANT12 ||
+ type == OBJECT_PLANT13 ||
+ type == OBJECT_PLANT14 ||
+ type == OBJECT_PLANT15 ||
+ type == OBJECT_PLANT16 ||
+ type == OBJECT_PLANT17 ||
+ type == OBJECT_PLANT18 ||
+ type == OBJECT_PLANT19 ||
+ type == OBJECT_TREE0 ||
+ type == OBJECT_TREE1 ||
+ type == OBJECT_TREE2 ||
+ type == OBJECT_TREE3 ||
+ type == OBJECT_TREE4 ||
+ type == OBJECT_TREE5 ||
+ type == OBJECT_TREE6 ||
+ type == OBJECT_TREE7 ||
+ type == OBJECT_TREE8 ||
+ type == OBJECT_TREE9 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreatePlant(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_MUSHROOM0 ||
+ type == OBJECT_MUSHROOM1 ||
+ type == OBJECT_MUSHROOM2 ||
+ type == OBJECT_MUSHROOM3 ||
+ type == OBJECT_MUSHROOM4 ||
+ type == OBJECT_MUSHROOM5 ||
+ type == OBJECT_MUSHROOM6 ||
+ type == OBJECT_MUSHROOM7 ||
+ type == OBJECT_MUSHROOM8 ||
+ type == OBJECT_MUSHROOM9 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateMushroom(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_TEEN0 ||
+ type == OBJECT_TEEN1 ||
+ type == OBJECT_TEEN2 ||
+ type == OBJECT_TEEN3 ||
+ type == OBJECT_TEEN4 ||
+ type == OBJECT_TEEN5 ||
+ type == OBJECT_TEEN6 ||
+ type == OBJECT_TEEN7 ||
+ type == OBJECT_TEEN8 ||
+ type == OBJECT_TEEN9 ||
+ type == OBJECT_TEEN10 ||
+ type == OBJECT_TEEN11 ||
+ type == OBJECT_TEEN12 ||
+ type == OBJECT_TEEN13 ||
+ type == OBJECT_TEEN14 ||
+ type == OBJECT_TEEN15 ||
+ type == OBJECT_TEEN16 ||
+ type == OBJECT_TEEN17 ||
+ type == OBJECT_TEEN18 ||
+ type == OBJECT_TEEN19 ||
+ type == OBJECT_TEEN20 ||
+ type == OBJECT_TEEN21 ||
+ type == OBJECT_TEEN22 ||
+ type == OBJECT_TEEN23 ||
+ type == OBJECT_TEEN24 ||
+ type == OBJECT_TEEN25 ||
+ type == OBJECT_TEEN26 ||
+ type == OBJECT_TEEN27 ||
+ type == OBJECT_TEEN28 ||
+ type == OBJECT_TEEN29 ||
+ type == OBJECT_TEEN30 ||
+ type == OBJECT_TEEN31 ||
+ type == OBJECT_TEEN32 ||
+ type == OBJECT_TEEN33 ||
+ type == OBJECT_TEEN34 ||
+ type == OBJECT_TEEN35 ||
+ type == OBJECT_TEEN36 ||
+ type == OBJECT_TEEN37 ||
+ type == OBJECT_TEEN38 ||
+ type == OBJECT_TEEN39 ||
+ type == OBJECT_TEEN40 ||
+ type == OBJECT_TEEN41 ||
+ type == OBJECT_TEEN42 ||
+ type == OBJECT_TEEN43 ||
+ type == OBJECT_TEEN44 ||
+ type == OBJECT_TEEN45 ||
+ type == OBJECT_TEEN46 ||
+ type == OBJECT_TEEN47 ||
+ type == OBJECT_TEEN48 ||
+ type == OBJECT_TEEN49 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->SetOption(option);
+ pObject->CreateTeen(pos, angle, zoom, height, type);
+ }
+ else
+ if ( type == OBJECT_QUARTZ0 ||
+ type == OBJECT_QUARTZ1 ||
+ type == OBJECT_QUARTZ2 ||
+ type == OBJECT_QUARTZ3 ||
+ type == OBJECT_QUARTZ4 ||
+ type == OBJECT_QUARTZ5 ||
+ type == OBJECT_QUARTZ6 ||
+ type == OBJECT_QUARTZ7 ||
+ type == OBJECT_QUARTZ8 ||
+ type == OBJECT_QUARTZ9 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateQuartz(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_ROOT0 ||
+ type == OBJECT_ROOT1 ||
+ type == OBJECT_ROOT2 ||
+ type == OBJECT_ROOT3 ||
+ type == OBJECT_ROOT4 ||
+ type == OBJECT_ROOT5 ||
+ type == OBJECT_ROOT6 ||
+ type == OBJECT_ROOT7 ||
+ type == OBJECT_ROOT8 ||
+ type == OBJECT_ROOT9 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateRoot(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_HOME1 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateHome(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_RUINmobilew1 ||
+ type == OBJECT_RUINmobilew2 ||
+ type == OBJECT_RUINmobilet1 ||
+ type == OBJECT_RUINmobilet2 ||
+ type == OBJECT_RUINmobiler1 ||
+ type == OBJECT_RUINmobiler2 ||
+ type == OBJECT_RUINfactory ||
+ type == OBJECT_RUINdoor ||
+ type == OBJECT_RUINsupport ||
+ type == OBJECT_RUINradar ||
+ type == OBJECT_RUINconvert ||
+ type == OBJECT_RUINbase ||
+ type == OBJECT_RUINhead )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateRuin(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_APOLLO1 ||
+ type == OBJECT_APOLLO3 ||
+ type == OBJECT_APOLLO4 ||
+ type == OBJECT_APOLLO5 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateApollo(pos, angle, type);
+ }
+ else
+ if ( type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateInsect(pos, angle, type); // no eggs
+ }
+ else
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH ||
+ type == OBJECT_TOTO ||
+ type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr ||
+ type == OBJECT_APOLLO2 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->SetOption(option);
+ pObject->CreateVehicle(pos, angle, type, power, bTrainer, bToy);
+ }
+
+ if ( m_bFixScene && type == OBJECT_HUMAN )
+ {
+ CMotion* motion;
+
+ motion = pObject->RetMotion();
+ if ( m_phase == PHASE_WIN ) motion->SetAction(MHS_WIN, 0.4f);
+ if ( m_phase == PHASE_LOST ) motion->SetAction(MHS_LOST, 0.5f);
+ }
+
+ return pObject;
+}
+
+
+// Creates the editable model.
+
+void CRobotMain::CreateModel()
+{
+ Math::Vector direction;
+ D3DCOLORVALUE color;
+
+ m_engine->SetAmbiantColor(0xC0C0C0C0); // gray
+ m_engine->SetBackground("", 0x80808080, 0x80808080, 0x80808080, 0x80808080);
+ m_engine->SetFogColor(0x80808080);
+ m_engine->SetDeepView(500.0f, 0);
+ m_engine->SetDeepView(100.0f, 1);
+ m_engine->SetFogStart(0.5f);
+
+ m_model->StartUserAction();
+
+ direction = Math::Vector(1.0f, -1.0f, 1.0f);
+ color.r = 0.7f;
+ color.g = 0.7f;
+ color.b = 0.7f; // white
+ CreateLight(direction, color);
+
+ direction = Math::Vector(-1.0f, -1.0f, 1.0f);
+ color.r = 0.7f;
+ color.g = 0.7f;
+ color.b = 0.7f; // white
+ CreateLight(direction, color);
+
+ direction = Math::Vector(1.0f, -1.0f, -1.0f);
+ color.r = 0.7f;
+ color.g = 0.7f;
+ color.b = 0.7f; // white
+ CreateLight(direction, color);
+
+ direction = Math::Vector(-1.0f, -1.0f, -1.0f);
+ color.r = 0.7f;
+ color.g = 0.7f;
+ color.b = 0.7f; // white
+ CreateLight(direction, color);
+
+ direction = Math::Vector(0.0f, 1.0f, 0.0f);
+ color.r = 0.7f;
+ color.g = 0.7f;
+ color.b = 0.7f; // white
+ CreateLight(direction, color);
+
+ InitEye();
+
+ m_engine->TimeInit();
+ m_time = 0.0f;
+ m_gameTime = 0.0f;
+ m_checkEndTime = 0.0f;
+}
+
+
+// Creates a directional light.
+
+int CRobotMain::CreateLight(Math::Vector direction, D3DCOLORVALUE color)
+{
+ D3DLIGHT7 light;
+ int obj;
+
+ if ( direction.x == 0.0f &&
+ direction.y == 0.0f &&
+ direction.z == 0.0f )
+ {
+ direction.y = -1.0f;
+ }
+
+ ZeroMemory(&light, sizeof(D3DLIGHT7));
+ light.dltType = D3DLIGHT_DIRECTIONAL;
+ light.dcvDiffuse.r = color.r;
+ light.dcvDiffuse.g = color.g;
+ light.dcvDiffuse.b = color.b;
+ light.dvDirection = VEC_TO_D3DVEC(direction);
+ obj = m_light->CreateLight();
+ m_light->SetLight(obj, light);
+
+ return obj;
+}
+
+// Creates a light spot.
+
+int CRobotMain::CreateSpot(Math::Vector pos, D3DCOLORVALUE color)
+{
+ D3DLIGHT7 light;
+ int obj;
+
+ if ( !m_engine->RetLightMode() ) return -1;
+
+ pos.y += m_terrain->RetFloorLevel(pos);
+
+ ZeroMemory(&light, sizeof(D3DLIGHT7));
+ light.dltType = D3DLIGHT_SPOT;
+ light.dcvDiffuse.r = color.r;
+ light.dcvDiffuse.g = color.g;
+ light.dcvDiffuse.b = color.b;
+ light.dvPosition = VEC_TO_D3DVEC(pos);
+ light.dvDirection = D3DVECTOR(0.0f, -1.0f, 0.0f);
+ light.dvRange = D3DLIGHT_RANGE_MAX;
+ light.dvFalloff = 1.0f;
+ light.dvTheta = 10.0f*Math::PI/180.0f;
+ light.dvPhi = 90.0f*Math::PI/180.0f;
+ light.dvAttenuation0 = 2.0f;
+ light.dvAttenuation1 = 0.0f;
+ light.dvAttenuation2 = 0.0f;
+ obj = m_light->CreateLight();
+ m_light->SetLight(obj, light);
+
+ return obj;
+}
+
+
+// Change the colors and textures.
+
+void CRobotMain::ChangeColor()
+{
+ D3DCOLORVALUE colorRef1, colorNew1, colorRef2, colorNew2;
+ Math::Point ts, ti;
+ Math::Point exclu[6];
+ char name[100];
+ int face;
+ float tolerance;
+
+ ts = Math::Point(0.0f, 0.0f);
+ ti = Math::Point(1.0f, 1.0f); // the entire image
+
+ colorRef1.a = 0.0f;
+ colorRef2.a = 0.0f;
+
+ colorRef1.r = 206.0f/256.0f;
+ colorRef1.g = 206.0f/256.0f;
+ colorRef1.b = 204.0f/256.0f; // ~white
+ colorNew1 = m_dialog->RetGamerColorCombi();
+ colorRef2.r = 255.0f/256.0f;
+ colorRef2.g = 132.0f/256.0f;
+ colorRef2.b = 1.0f/256.0f; // orange
+ colorNew2 = m_dialog->RetGamerColorBand();
+ exclu[0] = Math::Point(192.0f/256.0f, 0.0f/256.0f);
+ exclu[1] = Math::Point(256.0f/256.0f, 64.0f/256.0f); // crystals + cylinders
+ exclu[2] = Math::Point(208.0f/256.0f, 224.0f/256.0f);
+ exclu[3] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // SatCom screen
+ exclu[4] = Math::Point(0.0f, 0.0f);
+ exclu[5] = Math::Point(0.0f, 0.0f); // terminator
+ m_engine->ChangeColor("human.tga", colorRef1, colorNew1, colorRef2, colorNew2, 0.30f, 0.01f, ts, ti, exclu);
+
+ face = RetGamerFace();
+ if ( face == 0 ) // normal?
+ {
+ colorRef1.r = 90.0f/256.0f;
+ colorRef1.g = 95.0f/256.0f;
+ colorRef1.b = 85.0f/256.0f; // black
+ tolerance = 0.15f;
+ }
+ if ( face == 1 ) // bald?
+ {
+ colorRef1.r = 74.0f/256.0f;
+ colorRef1.g = 58.0f/256.0f;
+ colorRef1.b = 46.0f/256.0f; // brown
+ tolerance = 0.20f;
+ }
+ if ( face == 2 ) // carlos?
+ {
+ colorRef1.r = 70.0f/256.0f;
+ colorRef1.g = 40.0f/256.0f;
+ colorRef1.b = 8.0f/256.0f; // brown
+ tolerance = 0.30f;
+ }
+ if ( face == 3 ) // blonde?
+ {
+ colorRef1.r = 74.0f/256.0f;
+ colorRef1.g = 16.0f/256.0f;
+ colorRef1.b = 0.0f/256.0f; // yellow
+ tolerance = 0.20f;
+ }
+ colorNew1 = m_dialog->RetGamerColorHair();
+ colorRef2.r = 0.0f;
+ colorRef2.g = 0.0f;
+ colorRef2.b = 0.0f;
+ colorNew2.r = 0.0f;
+ colorNew2.g = 0.0f;
+ colorNew2.b = 0.0f;
+ sprintf(name, "face%.2d.tga", face+1);
+ exclu[0] = Math::Point(105.0f/256.0f, 47.0f/166.0f);
+ exclu[1] = Math::Point(153.0f/256.0f, 79.0f/166.0f); // blue canister
+ exclu[2] = Math::Point(0.0f, 0.0f);
+ exclu[3] = Math::Point(0.0f, 0.0f); // terminator
+ m_engine->ChangeColor(name, colorRef1, colorNew1, colorRef2, colorNew2, tolerance, 0.00f, ts, ti, exclu);
+
+ colorRef2.r = 0.0f;
+ colorRef2.g = 0.0f;
+ colorRef2.b = 0.0f;
+ colorNew2.r = 0.0f;
+ colorNew2.g = 0.0f;
+ colorNew2.b = 0.0f;
+
+ m_engine->ChangeColor("base1.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
+ m_engine->ChangeColor("convert.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
+ m_engine->ChangeColor("derrick.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
+ m_engine->ChangeColor("factory.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
+ m_engine->ChangeColor("lemt.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
+ m_engine->ChangeColor("roller.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
+ m_engine->ChangeColor("search.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
+
+ exclu[0] = Math::Point( 0.0f/256.0f, 160.0f/256.0f);
+ exclu[1] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // pencils
+ exclu[2] = Math::Point(0.0f, 0.0f);
+ exclu[3] = Math::Point(0.0f, 0.0f); // terminator
+ m_engine->ChangeColor("drawer.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true);
+
+ exclu[0] = Math::Point(237.0f/256.0f, 176.0f/256.0f);
+ exclu[1] = Math::Point(256.0f/256.0f, 220.0f/256.0f); // blue canister
+ exclu[2] = Math::Point(106.0f/256.0f, 150.0f/256.0f);
+ exclu[3] = Math::Point(130.0f/256.0f, 214.0f/256.0f); // safe location
+ exclu[4] = Math::Point(0.0f, 0.0f);
+ exclu[5] = Math::Point(0.0f, 0.0f); // terminator
+ m_engine->ChangeColor("subm.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true);
+
+ exclu[0] = Math::Point(128.0f/256.0f, 160.0f/256.0f);
+ exclu[1] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // SatCom
+ exclu[2] = Math::Point(0.0f, 0.0f);
+ exclu[3] = Math::Point(0.0f, 0.0f); // terminator
+ m_engine->ChangeColor("ant.tga", m_colorRefAlien, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti, exclu);
+ m_engine->ChangeColor("mother.tga", m_colorRefAlien, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti);
+
+ m_engine->ChangeColor("plant.tga", m_colorRefGreen, m_colorNewGreen, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti);
+
+ // PARTIPLOUF0 and PARTIDROP :
+ ts = Math::Point(0.500f, 0.500f);
+ ti = Math::Point(0.875f, 0.750f);
+ m_engine->ChangeColor("effect00.tga", m_colorRefWater, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, 0, m_colorShiftWater, true);
+
+ // PARTIFLIC :
+ ts = Math::Point(0.00f, 0.75f);
+ ti = Math::Point(0.25f, 1.00f);
+ m_engine->ChangeColor("effect02.tga", m_colorRefWater, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, 0, m_colorShiftWater, true);
+}
+
+// Updates the number of unnecessary objects.
+
+bool CRobotMain::TestGadgetQuantity(int rank)
+{
+ float percent;
+ int *table;
+
+ static int table10[10] = {0,1,0,0,0,0,0,0,0,0};
+ static int table20[10] = {0,1,0,0,0,1,0,0,0,0};
+ static int table30[10] = {0,1,0,1,0,1,0,0,0,0};
+ static int table40[10] = {0,1,0,1,0,1,0,1,0,0};
+ static int table50[10] = {0,1,0,1,0,1,0,1,0,1};
+ static int table60[10] = {0,1,0,1,1,1,0,1,0,1};
+ static int table70[10] = {0,1,0,1,1,1,0,1,1,1};
+ static int table80[10] = {0,1,1,1,1,1,0,1,1,1};
+ static int table90[10] = {0,1,1,1,1,1,1,1,1,1};
+
+ percent = m_engine->RetGadgetQuantity();
+ if ( percent == 0.0f ) return false;
+ if ( percent == 1.0f ) return true;
+
+ if ( percent <= 0.15f ) table = table10;
+ else if ( percent <= 0.25f ) table = table20;
+ else if ( percent <= 0.35f ) table = table30;
+ else if ( percent <= 0.45f ) table = table40;
+ else if ( percent <= 0.55f ) table = table50;
+ else if ( percent <= 0.65f ) table = table60;
+ else if ( percent <= 0.75f ) table = table70;
+ else if ( percent <= 0.85f ) table = table80;
+ else table = table90;
+
+ return table[rank%10];
+}
+
+
+
+// Calculates the distance to the nearest object.
+
+float CRobotMain::SearchNearestObject(Math::Vector center, CObject *exclu)
+{
+ CObject* pObj;
+ ObjectType type;
+ Math::Vector oPos;
+ float min, dist, oRadius;
+ int i, j;
+
+ min = 100000.0f;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue; // inactive?
+ if ( pObj->RetTruck() != 0 ) continue; // object carries?
+ if ( pObj == exclu ) continue;
+
+ type = pObj->RetType();
+
+ if ( type == OBJECT_BASE )
+ {
+ oPos = pObj->RetPosition(0);
+ if ( oPos.x != center.x ||
+ oPos.z != center.z )
+ {
+ dist = Math::Distance(center, oPos)-80.0f;
+ if ( dist < 0.0f ) dist = 0.0f;
+ min = Math::Min(min, dist);
+ continue;
+ }
+ }
+
+ if ( type == OBJECT_STATION ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_DESTROYER )
+ {
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(center, oPos)-8.0f;
+ if ( dist < 0.0f ) dist = 0.0f;
+ min = Math::Min(min, dist);
+ }
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ dist = Math::Distance(center, oPos)-oRadius;
+ if ( dist < 0.0f ) dist = 0.0f;
+ min = Math::Min(min, dist);
+ }
+ }
+ return min;
+}
+
+// Calculates a free space.
+
+bool CRobotMain::FreeSpace(Math::Vector &center, float minRadius, float maxRadius,
+ float space, CObject *exclu)
+{
+ Math::Vector pos;
+ Math::Point p;
+ float radius, ia, angle, dist, flat;
+
+ if ( minRadius < maxRadius ) // from internal to external?
+ {
+ for ( radius=minRadius ; radius<=maxRadius ; radius+=space )
+ {
+ ia = space/radius;
+ for ( angle=0.0f ; angle<Math::PI*2.0f ; angle+=ia )
+ {
+ p.x = center.x+radius;
+ p.y = center.z;
+ p = Math::RotatePoint(Math::Point(center.x, center.z), angle, p);
+ pos.x = p.x;
+ pos.z = p.y;
+ pos.y = 0.0f;
+ m_terrain->MoveOnFloor(pos, true);
+ dist = SearchNearestObject(pos, exclu);
+ if ( dist >= space )
+ {
+ flat = m_terrain->RetFlatZoneRadius(pos, dist/2.0f);
+ if ( flat >= dist/2.0f )
+ {
+ center = pos;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ else // from external to internal?
+ {
+ for ( radius=maxRadius ; radius>=minRadius ; radius-=space )
+ {
+ ia = space/radius;
+ for ( angle=0.0f ; angle<Math::PI*2.0f ; angle+=ia )
+ {
+ p.x = center.x+radius;
+ p.y = center.z;
+ p = Math::RotatePoint(Math::Point(center.x, center.z), angle, p);
+ pos.x = p.x;
+ pos.z = p.y;
+ pos.y = 0.0f;
+ m_terrain->MoveOnFloor(pos, true);
+ dist = SearchNearestObject(pos, exclu);
+ if ( dist >= space )
+ {
+ flat = m_terrain->RetFlatZoneRadius(pos, dist/2.0f);
+ if ( flat >= dist/2.0f )
+ {
+ center = pos;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+// Calculates the maximum radius of a free space.
+
+float CRobotMain::RetFlatZoneRadius(Math::Vector center, float maxRadius,
+ CObject *exclu)
+{
+ float dist;
+
+ dist = SearchNearestObject(center, exclu);
+ if ( dist == 0.0f ) return 0.0f;
+ if ( dist < maxRadius )
+ {
+ maxRadius = dist;
+ }
+ return m_terrain->RetFlatZoneRadius(center, maxRadius);
+}
+
+
+// Hides buildable area when a cube of metal is taken up.
+
+void CRobotMain::HideDropZone(CObject* metal)
+{
+ if ( m_showLimit[1].bUsed &&
+ m_showLimit[1].link == metal )
+ {
+ FlushShowLimit(1);
+ }
+
+ if ( m_showLimit[2].bUsed &&
+ m_showLimit[2].link == metal )
+ {
+ FlushShowLimit(2);
+ }
+}
+
+// Shows the buildable area when a cube of metal is deposited.
+
+void CRobotMain::ShowDropZone(CObject* metal, CObject* truck)
+{
+ CObject* pObj;
+ ObjectType type;
+ Math::Vector center, oPos;
+ float oMax, tMax, dist, oRadius, radius;
+ int i, j;
+
+ if ( metal == 0 ) return;
+
+ center = metal->RetPosition(0);
+
+ // Calculates the maximum radius possible depending on other items.
+ oMax = 30.0f; // radius to build the biggest building
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue; // inactive?
+ if ( pObj->RetTruck() != 0 ) continue; // object carried?
+ if ( pObj == metal ) continue;
+ if ( pObj == truck ) continue;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_BASE )
+ {
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(center, oPos)-80.0f;
+ oMax = Math::Min(oMax, dist);
+ }
+ else
+ {
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ dist = Math::Distance(center, oPos)-oRadius;
+ oMax = Math::Min(oMax, dist);
+ }
+ }
+
+ if ( type == OBJECT_DERRICK ||
+ type == OBJECT_FACTORY ||
+ type == OBJECT_STATION ||
+ type == OBJECT_CONVERT ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_DESTROYER||
+ type == OBJECT_TOWER ||
+ type == OBJECT_RESEARCH ||
+ type == OBJECT_RADAR ||
+ type == OBJECT_ENERGY ||
+ type == OBJECT_LABO ||
+ type == OBJECT_NUCLEAR ||
+ type == OBJECT_START ||
+ type == OBJECT_END ||
+ type == OBJECT_INFO ||
+ type == OBJECT_PARA ||
+ type == OBJECT_SAFE ||
+ type == OBJECT_HUSTON ) // building?
+ {
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ dist = Math::Distance(center, oPos)-oRadius-BUILDMARGIN;
+ oMax = Math::Min(oMax, dist);
+ }
+ }
+ }
+
+ // Calculates the maximum possible radius depending on terrain.
+ if ( oMax >= 2.0f )
+ {
+ tMax = m_terrain->RetFlatZoneRadius(center, 30.0f);
+ }
+ else
+ {
+ tMax = 0.0f;
+ }
+
+ radius = Math::Min(oMax, tMax);
+ if ( radius >= 2.0f )
+ {
+ SetShowLimit(1, PARTILIMIT2, metal, center, radius, 10.0f);
+ }
+}
+
+// Erases the boundaries shown.
+
+void CRobotMain::FlushShowLimit(int i)
+{
+ int j;
+
+ if ( m_showLimit[i].link != 0 )
+ {
+ m_showLimit[i].link->StopShowLimit();
+ }
+
+ for ( j=0 ; j<m_showLimit[i].total ; j++ )
+ {
+ if ( m_showLimit[i].parti[j] == 0 ) continue;
+
+ m_particule->DeleteParticule(m_showLimit[i].parti[j]);
+ m_showLimit[i].parti[j] = 0;
+ }
+
+ m_showLimit[i].total = 0;
+ m_showLimit[i].link = 0;
+ m_showLimit[i].bUsed = false;
+}
+
+// Specifies the boundaries to show.
+
+void CRobotMain::SetShowLimit(int i, ParticuleType parti, CObject *pObj,
+ Math::Vector pos, float radius, float duration)
+{
+ Math::Point dim;
+ float dist;
+ int j;
+
+ FlushShowLimit(i); // erases the current boundaries
+
+ if ( radius <= 0.0f ) return;
+
+ if ( radius <= 50.0f )
+ {
+ dim = Math::Point(0.3f, 0.3f);
+ dist = 2.5f;
+ }
+ else
+ {
+ dim = Math::Point(1.5f, 1.5f);
+ dist = 10.0f;
+ }
+
+ m_showLimit[i].bUsed = true;
+ m_showLimit[i].link = pObj;
+ m_showLimit[i].pos = pos;
+ m_showLimit[i].radius = radius;
+ m_showLimit[i].duration = duration;
+ m_showLimit[i].total = (int)((radius*2.0f*Math::PI)/dist);
+ if ( m_showLimit[i].total > MAXSHOWPARTI ) m_showLimit[i].total = MAXSHOWPARTI;
+ m_showLimit[i].time = 0.0f;
+
+ for ( j=0 ; j<m_showLimit[i].total ; j++ )
+ {
+ m_showLimit[i].parti[j] = m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), dim, parti, duration);
+ }
+}
+
+// Adjusts the boundaries to show.
+
+void CRobotMain::AdjustShowLimit(int i, Math::Vector pos)
+{
+ m_showLimit[i].pos = pos;
+}
+
+// Mount the boundaries of the selected object.
+
+void CRobotMain::StartShowLimit()
+{
+ CObject* pObj;
+
+ pObj = RetSelect();
+ if ( pObj == 0 ) return;
+
+ pObj->StartShowLimit();
+}
+
+// Advances the boundaries shown.
+
+void CRobotMain::FrameShowLimit(float rTime)
+{
+ Math::Vector pos;
+ Math::Point center, rotate;
+ float angle, factor, speed;
+ int i, j;
+
+ if ( m_engine->RetPause() ) return;
+
+ for ( i=0 ; i<MAXSHOWLIMIT ; i++ )
+ {
+ if ( !m_showLimit[i].bUsed ) continue;
+
+ m_showLimit[i].time += rTime;
+
+ if ( m_showLimit[i].time >= m_showLimit[i].duration )
+ {
+ FlushShowLimit(i);
+ continue;
+ }
+
+ if ( m_showLimit[i].time < 1.0f )
+ {
+ factor = m_showLimit[i].time;
+ }
+ else if ( m_showLimit[i].time > m_showLimit[i].duration-1.0f )
+ {
+ factor = m_showLimit[i].duration-m_showLimit[i].time;
+ }
+ else
+ {
+ factor = 1.0f;
+ }
+
+ speed = 0.4f-m_showLimit[i].radius*0.001f;
+ if ( speed < 0.1f ) speed = 0.1f;
+ angle = m_showLimit[i].time*speed;
+
+ for ( j=0 ; j<m_showLimit[i].total ; j++ )
+ {
+ if ( m_showLimit[i].parti[j] == 0 ) continue;
+
+ center.x = m_showLimit[i].pos.x;
+ center.y = m_showLimit[i].pos.z;
+ rotate.x = center.x+m_showLimit[i].radius*factor;
+ rotate.y = center.y;
+ rotate = Math::RotatePoint(center, angle, rotate);
+
+ pos.x = rotate.x;
+ pos.z = rotate.y;
+ pos.y = 0.0f;
+ m_terrain->MoveOnFloor(pos, true);
+ if ( m_showLimit[i].radius <= 50.0f ) pos.y += 0.5f;
+ else pos.y += 2.0f;
+ m_particule->SetPosition(m_showLimit[i].parti[j], pos);
+//? m_particule->SetAngle(m_showLimit[i].parti[j], angle-Math::PI/2.0f);
+
+ angle += (2.0f*Math::PI)/m_showLimit[i].total;
+ }
+ }
+}
+
+
+
+// Returns a pointer to the last backslash in a filename.
+
+char* SearchLastDir(char *filename)
+{
+ char* p = filename;
+
+ while ( *p++ != 0 );
+ p --; // ^on the zero terminator
+
+ while ( p != filename )
+ {
+ if ( *(--p) == '\\' ) return p;
+ }
+ return 0;
+}
+
+
+// Compiles all scripts of robots.
+
+void CRobotMain::CompileScript(bool bSoluce)
+{
+ CObject* pObj;
+ CBrain* brain;
+ int i, j, nbError, lastError, run;
+ char* name;
+
+ nbError = 0;
+ do
+ {
+ lastError = nbError;
+ nbError = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) continue;
+
+ for ( j=0 ; j<10 ; j++ )
+ {
+ if ( brain->RetCompile(j) ) continue;
+
+ name = brain->RetScriptName(j);
+ if ( name[0] != 0 )
+ {
+ brain->ReadProgram(j, name);
+ if ( !brain->RetCompile(j) ) nbError++;
+ }
+ }
+
+ LoadOneScript(pObj, nbError);
+ }
+ }
+ while ( nbError > 0 && nbError != lastError );
+
+ // Load all solutions.
+ if ( bSoluce )
+ {
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) continue;
+
+ name = brain->RetSoluceName();
+ if ( name[0] != 0 )
+ {
+ brain->ReadSoluce(name); // load solution
+ }
+ }
+ }
+
+ // Start all programs according to the command "run".
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) continue;
+
+ run = brain->RetScriptRun();
+ if ( run != -1 )
+ {
+ brain->RunProgram(run); // starts the program
+ }
+ }
+}
+
+// Load all programs of the robot.
+
+void CRobotMain::LoadOneScript(CObject *pObj, int &nbError)
+{
+ ObjectType type;
+ CBrain* brain;
+ char filename[_MAX_FNAME];
+ char* name;
+ int rank, i, objRank;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) return;
+
+ if ( !IsSelectable(pObj) ) return;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_HUMAN ) return;
+
+ objRank = pObj->RetDefRank();
+ if ( objRank == -1 ) return;
+
+ name = m_dialog->RetSceneName();
+ rank = m_dialog->RetSceneRank();
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ if ( brain->RetCompile(i) ) continue;
+//? if ( brain->ProgramExist(i) ) continue;
+
+ sprintf(filename, "%s\\%s\\%c%.3d%.3d%.1d.txt",
+ RetSavegameDir(), m_gamerName, name[0], rank, objRank, i);
+ brain->ReadProgram(i, filename);
+ if ( !brain->RetCompile(i) ) nbError++;
+ }
+}
+
+// Load all programs of the robot.
+
+void CRobotMain::LoadFileScript(CObject *pObj, char* filename, int objRank,
+ int &nbError)
+{
+ ObjectType type;
+ CBrain* brain;
+ char fn[_MAX_FNAME];
+ char* ldir;
+ char* name;
+ int rank, i;
+
+ if ( objRank == -1 ) return;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) return;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_HUMAN ) return;
+
+ name = m_dialog->RetSceneName();
+ rank = m_dialog->RetSceneRank();
+
+ strcpy(fn, filename);
+ ldir = SearchLastDir(fn);
+ if ( ldir == 0 ) return;
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ if ( brain->RetCompile(i) ) continue;
+//? if ( brain->ProgramExist(i) ) continue;
+
+ sprintf(ldir, "\\prog%.3d%.1d.txt", objRank, i);
+ brain->ReadProgram(i, fn);
+ if ( !brain->RetCompile(i) ) nbError++;
+ }
+}
+
+// Saves all programs of all the robots.
+
+void CRobotMain::SaveAllScript()
+{
+ CObject* pObj;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ SaveOneScript(pObj);
+ }
+}
+
+// Saves all programs of the robot.
+// If a program does not exist, the corresponding file is destroyed.
+
+void CRobotMain::SaveOneScript(CObject *pObj)
+{
+ ObjectType type;
+ CBrain* brain;
+ char filename[_MAX_FNAME];
+ char* name;
+ int rank, i, objRank;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) return;
+
+ if ( !IsSelectable(pObj) ) return;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_HUMAN ) return;
+
+ objRank = pObj->RetDefRank();
+ if ( objRank == -1 ) return;
+
+ name = m_dialog->RetSceneName();
+ rank = m_dialog->RetSceneRank();
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ sprintf(filename, "%s\\%s\\%c%.3d%.3d%.1d.txt",
+ RetSavegameDir(), m_gamerName, name[0], rank, objRank, i);
+ brain->WriteProgram(i, filename);
+ }
+}
+
+// Saves all programs of the robot.
+// If a program does not exist, the corresponding file is destroyed.
+
+void CRobotMain::SaveFileScript(CObject *pObj, char* filename, int objRank)
+{
+ ObjectType type;
+ CBrain* brain;
+ char fn[_MAX_FNAME];
+ char* ldir;
+ char* name;
+ int rank, i;
+
+ if ( objRank == -1 ) return;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) return;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_HUMAN ) return;
+
+ name = m_dialog->RetSceneName();
+ rank = m_dialog->RetSceneRank();
+
+ strcpy(fn, filename);
+ ldir = SearchLastDir(fn);
+ if ( ldir == 0 ) return;
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ sprintf(ldir, "\\prog%.3d%.1d.txt", objRank, i);
+ brain->WriteProgram(i, fn);
+ }
+}
+
+// Saves the stack of the program in execution of a robot.
+
+bool CRobotMain::SaveFileStack(CObject *pObj, FILE *file, int objRank)
+{
+ ObjectType type;
+ CBrain* brain;
+
+ if ( objRank == -1 ) return true;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) return true;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_HUMAN ) return true;
+
+ return brain->WriteStack(file);
+}
+
+// Resumes the execution stack of the program in a robot.
+
+bool CRobotMain::ReadFileStack(CObject *pObj, FILE *file, int objRank)
+{
+ ObjectType type;
+ CBrain* brain;
+
+ if ( objRank == -1 ) return true;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) return true;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_HUMAN ) return true;
+
+ return brain->ReadStack(file);
+}
+
+
+// Empty the list.
+
+bool CRobotMain::FlushNewScriptName()
+{
+ int i;
+
+ for ( i=0 ; i<MAXNEWSCRIPTNAME ; i++ )
+ {
+ m_newScriptName[i].bUsed = false;
+ }
+ return true;
+}
+
+// Adds a script name.
+
+bool CRobotMain::AddNewScriptName(ObjectType type, char *name)
+{
+ int i;
+
+ for ( i=0 ; i<MAXNEWSCRIPTNAME ; i++ )
+ {
+ if ( !m_newScriptName[i].bUsed )
+ {
+ m_newScriptName[i].bUsed = true;
+ m_newScriptName[i].type = type;
+ strcpy(m_newScriptName[i].name, name);
+ return true;
+ }
+ }
+ return false;
+}
+
+// Seeks a script name for a given type.
+
+char* CRobotMain::RetNewScriptName(ObjectType type, int rank)
+{
+ int i;
+
+ for ( i=0 ; i<MAXNEWSCRIPTNAME ; i++ )
+ {
+ if ( m_newScriptName[i].bUsed &&
+ (m_newScriptName[i].type == type ||
+ m_newScriptName[i].type == OBJECT_NULL ) )
+ {
+ if ( rank == 0 ) return m_newScriptName[i].name;
+ else rank --;
+ }
+ }
+
+ return 0;
+}
+
+
+// Seeks if an object occupies in a spot, to prevent a backup of the game.
+
+bool CRobotMain::IsBusy()
+{
+ CObject* pObj;
+ CBrain* pBrain;
+//? CAuto* pAuto;
+ int i;
+
+ if ( m_CompteurFileOpen > 0 ) return true;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ pBrain = pObj->RetBrain();
+ if ( pBrain != 0 )
+ {
+ if ( pBrain->IsBusy() ) return true;
+ }
+
+//? pAuto = pObj->RetAuto();
+//? if ( pAuto != 0 )
+//? {
+//? if ( pAuto->RetBusy() ) return true;
+//? }
+ }
+ return false;
+}
+
+// Writes an object into the backup file.
+
+void CRobotMain::IOWriteObject(FILE *file, CObject* pObj, char *cmd)
+{
+ Math::Vector pos;
+ CBrain* pBrain;
+ char line[3000];
+ char name[100];
+ int run, i;
+
+ if ( pObj->RetType() == OBJECT_FIX ) return;
+
+ strcpy(line, cmd);
+
+ sprintf(name, " type=%s", GetTypeObject(pObj->RetType()));
+ strcat(line, name);
+
+ sprintf(name, " id=%d", pObj->RetID());
+ strcat(line, name);
+
+ pos = pObj->RetPosition(0)/g_unit;
+ sprintf(name, " pos=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
+ strcat(line, name);
+
+ pos = pObj->RetAngle(0)/(Math::PI/180.0f);
+ sprintf(name, " angle=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
+ strcat(line, name);
+
+ pos = pObj->RetZoom(0);
+ sprintf(name, " zoom=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
+ strcat(line, name);
+
+ for ( i=1 ; i<OBJECTMAXPART ; i++ )
+ {
+ if ( pObj->RetObjectRank(i) == -1 ) continue;
+
+ pos = pObj->RetPosition(i);
+ if ( pos.x != 0.0f || pos.y != 0.0f || pos.z != 0.0f )
+ {
+ pos /= g_unit;
+ sprintf(name, " p%d=%.2f;%.2f;%.2f", i, pos.x, pos.y, pos.z);
+ strcat(line, name);
+ }
+
+ pos = pObj->RetAngle(i);
+ if ( pos.x != 0.0f || pos.y != 0.0f || pos.z != 0.0f )
+ {
+ pos /= (Math::PI/180.0f);
+ sprintf(name, " a%d=%.2f;%.2f;%.2f", i, pos.x, pos.y, pos.z);
+ strcat(line, name);
+ }
+
+ pos = pObj->RetZoom(i);
+ if ( pos.x != 1.0f || pos.y != 1.0f || pos.z != 1.0f )
+ {
+ sprintf(name, " z%d=%.2f;%.2f;%.2f", i, pos.x, pos.y, pos.z);
+ strcat(line, name);
+ }
+ }
+
+ sprintf(name, " trainer=%d", pObj->RetTrainer());
+ strcat(line, name);
+
+ sprintf(name, " option=%d", pObj->RetOption());
+ strcat(line, name);
+
+ if ( pObj == m_infoObject ) // selects object?
+ {
+ sprintf(name, " select=1");
+ strcat(line, name);
+ }
+
+ pObj->Write(line);
+
+ if ( pObj->RetType() == OBJECT_BASE )
+ {
+ sprintf(name, " run=3"); // stops and open (PARAM_FIXSCENE)
+ strcat(line, name);
+ }
+
+ pBrain = pObj->RetBrain();
+ if ( pBrain != 0 )
+ {
+ run = pBrain->RetProgram();
+ if ( run != -1 )
+ {
+ sprintf(name, " run=%d", run+1);
+ strcat(line, name);
+ }
+ }
+
+ strcat(line, "\n");
+ fputs(line, file);
+}
+
+// Saves the current game.
+
+bool CRobotMain::IOWriteScene(char *filename, char *filecbot, char *info)
+{
+ FILE* file;
+ char line[500];
+ char* name;
+ CObject *pObj, *pPower, *pFret;
+ float sleep, delay, magnetic, progress;
+ int i, objRank;
+ long version;
+
+ file = fopen(filename, "w");
+ if ( file == NULL ) return false;
+
+ sprintf(line, "Title text=\"%s\"\n", info);
+ fputs(line, file);
+
+ sprintf(line, "Version maj=%d min=%d\n", 0, 1);
+ fputs(line, file);
+
+ name = m_dialog->RetSceneName();
+ if ( strcmp(name, "user") == 0 )
+ {
+ sprintf(line, "Mission base=\"%s\" rank=%.3d dir=\"%s\"\n", name, m_dialog->RetSceneRank(), m_dialog->RetSceneDir());
+ }
+ else
+ {
+ sprintf(line, "Mission base=\"%s\" rank=%.3d\n", name, m_dialog->RetSceneRank());
+ }
+ fputs(line, file);
+
+ sprintf(line, "Map zoom=%.2f\n", m_map->RetZoomMap());
+ fputs(line, file);
+
+ sprintf(line, "DoneResearch bits=%d\n", g_researchDone);
+ fputs(line, file);
+
+ if ( m_blitz->GetStatus(sleep, delay, magnetic, progress) )
+ {
+ sprintf(line, "BlitzMode sleep=%.2f delay=%.2f magnetic=%.2f progress=%.2f\n", sleep, delay, magnetic/g_unit, progress);
+ fputs(line, file);
+ }
+
+ objRank = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetType() == OBJECT_TOTO ) continue;
+ if ( pObj->RetType() == OBJECT_FIX ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+ if ( pObj->RetBurn() ) continue;
+ if ( pObj->RetDead() ) continue;
+ if ( pObj->RetExplo() ) continue;
+
+ pPower = pObj->RetPower();
+ pFret = pObj->RetFret();
+
+ if ( pFret != 0 ) // object transported?
+ {
+ IOWriteObject(file, pFret, "CreateFret");
+ }
+
+ if ( pPower != 0 ) // battery transported?
+ {
+ IOWriteObject(file, pPower, "CreatePower");
+ }
+
+ IOWriteObject(file, pObj, "CreateObject");
+
+ SaveFileScript(pObj, filename, objRank++);
+ }
+ fclose(file);
+
+#if CBOT_STACK
+ // Writes the file of stacks of execution.
+ file = fOpen(filecbot, "wb");
+ if ( file == NULL ) return false;
+
+ version = 1;
+ fWrite(&version, sizeof(long), 1, file); // version of COLOBOT
+ version = CBotProgram::GivVersion();
+ fWrite(&version, sizeof(long), 1, file); // version of CBOT
+
+ objRank = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetType() == OBJECT_TOTO ) continue;
+ if ( pObj->RetType() == OBJECT_FIX ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+ if ( pObj->RetBurn() ) continue;
+ if ( pObj->RetDead() ) continue;
+
+ if ( !SaveFileStack(pObj, file, objRank++) ) break;
+ }
+ CBotClass::SaveStaticState(file);
+ fClose(file);
+#endif
+
+ m_delayWriteMessage = 4; // displays message in 3 frames
+ return true;
+}
+
+// Resumes the game.
+
+CObject* CRobotMain::IOReadObject(char *line, char* filename, int objRank)
+{
+ CObject* pObj;
+//? CBrain* pBrain;
+ CAuto* pAuto;
+ Math::Vector pos, dir, zoom;
+ ObjectType type;
+ int id, run, trainer, toy, option, i;
+ char op[10];
+
+ pos = OpDir(line, "pos")*g_unit;
+ dir = OpDir(line, "angle")*(Math::PI/180.0f);
+ zoom = OpDir(line, "zoom");
+ type = OpTypeObject(line, "type", OBJECT_NULL);
+ id = OpInt(line, "id", 0);
+ if ( type == OBJECT_NULL ) return 0;
+ trainer = OpInt(line, "trainer", 0);
+ toy = OpInt(line, "toy", 0);
+ option = OpInt(line, "option", 0);
+ pObj = CreateObject(pos, dir.y, 1.0f, 0.0f, type, 0.0f, trainer, toy, option);
+ pObj->SetDefRank(objRank);
+ pObj->SetPosition(0, pos);
+ pObj->SetAngle(0, dir);
+ pObj->SetID(id);
+ if ( g_id < id ) g_id = id;
+
+ if ( zoom.x != 0.0f || zoom.y != 0.0f || zoom.z != 0.0f )
+ {
+ pObj->SetZoom(0, zoom);
+ }
+
+ for ( i=1 ; i<OBJECTMAXPART ; i++ )
+ {
+ if ( pObj->RetObjectRank(i) == -1 ) continue;
+
+ sprintf(op, "p%d", i);
+ pos = OpDir(line, op);
+ if ( pos.x != 0.0f || pos.y != 0.0f || pos.z != 0.0f )
+ {
+ pObj->SetPosition(i, pos*g_unit);
+ }
+
+ sprintf(op, "a%d", i);
+ dir = OpDir(line, op);
+ if ( dir.x != 0.0f || dir.y != 0.0f || dir.z != 0.0f )
+ {
+ pObj->SetAngle(i, dir*(Math::PI/180.0f));
+ }
+
+ sprintf(op, "z%d", i);
+ zoom = OpDir(line, op);
+ if ( zoom.x != 0.0f || zoom.y != 0.0f || zoom.z != 0.0f )
+ {
+ pObj->SetZoom(i, zoom);
+ }
+ }
+
+ if ( type == OBJECT_BASE ) m_bBase = true;
+
+ pObj->Read(line);
+
+#if CBOT_STACK
+#else
+ LoadFileScript(pObj, filename, objRank, i);
+#endif
+
+ run = OpInt(line, "run", -1);
+ if ( run != -1 )
+ {
+#if CBOT_STACK
+#else
+ pBrain = pObj->RetBrain();
+ if ( pBrain != 0 )
+ {
+ pBrain->RunProgram(run-1); // starts the program
+ }
+#endif
+
+ pAuto = pObj->RetAuto();
+ if ( pAuto != 0 )
+ {
+ pAuto->Start(run); // starts the film
+ }
+ }
+
+ return pObj;
+}
+
+// Resumes some part of the game.
+
+CObject* CRobotMain::IOReadScene(char *filename, char *filecbot)
+{
+ FILE* file;
+ CObject *pObj, *pPower, *pFret, *pSel;
+ char line[3000];
+ float sleep, delay, progress, magnetic;
+ int i, objRank, nbError, lastError;
+ long version;
+
+ m_bBase = false;
+
+ file = fopen(filename, "r");
+ if ( file == NULL ) return 0;
+
+ pFret = 0;
+ pPower = 0;
+ pSel = 0;
+ objRank = 0;
+ while ( fgets(line, 3000, file) != NULL )
+ {
+ for ( i=0 ; i<3000 ; i++ )
+ {
+ if ( line[i] == '\t' ) line[i] = ' '; // replace tab by space
+ if ( line[i] == '/' && line[i+1] == '/' )
+ {
+ line[i] = 0;
+ break;
+ }
+ }
+
+ if ( Cmd(line, "Map") )
+ {
+ m_map->ZoomMap(OpFloat(line, "zoom", 1.0f));
+ }
+
+ if ( Cmd(line, "DoneResearch") )
+ {
+ g_researchDone = OpInt(line, "bits", 0);
+ }
+
+ if ( Cmd(line, "BlitzMode") )
+ {
+ sleep = OpFloat(line, "sleep", 0.0f);
+ delay = OpFloat(line, "delay", 3.0f);
+ magnetic = OpFloat(line, "magnetic", 50.0f)*g_unit;
+ progress = OpFloat(line, "progress", 0.0f);
+ m_blitz->SetStatus(sleep, delay, magnetic, progress);
+ }
+
+ if ( Cmd(line, "CreateFret") )
+ {
+ pFret = IOReadObject(line, filename, -1);
+ }
+
+ if ( Cmd(line, "CreatePower") )
+ {
+ pPower = IOReadObject(line, filename, -1);
+ }
+
+ if ( Cmd(line, "CreateObject") )
+ {
+ pObj = IOReadObject(line, filename, objRank++);
+
+ if ( OpInt(line, "select", 0) )
+ {
+ pSel = pObj;
+ }
+
+ if ( pFret != 0 )
+ {
+ CTaskManip* task;
+
+ pObj->SetFret(pFret);
+ task = new CTaskManip(m_iMan, pObj);
+ task->Start(TMO_AUTO, TMA_GRAB); // holds the object!
+ delete task;
+ }
+
+ if ( pPower != 0 )
+ {
+ pObj->SetPower(pPower);
+ pPower->SetTruck(pObj);
+ }
+
+ pFret = 0;
+ pPower = 0;
+ }
+ }
+ fclose(file);
+
+#if CBOT_STACK
+ // Compiles scripts.
+ nbError = 0;
+ do
+ {
+ lastError = nbError;
+ nbError = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ objRank = pObj->RetDefRank();
+ if ( objRank == -1 ) continue;
+
+ LoadFileScript(pObj, filename, objRank, nbError);
+ }
+ }
+ while ( nbError > 0 && nbError != lastError );
+
+ // Reads the file of stacks of execution.
+ file = fOpen(filecbot, "rb");
+ if ( file != NULL )
+ {
+ fRead(&version, sizeof(long), 1, file); // version of COLOBOT
+ if ( version == 1 )
+ {
+ fRead(&version, sizeof(long), 1, file); // version of CBOT
+ if ( version == CBotProgram::GivVersion() )
+ {
+ objRank = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetType() == OBJECT_TOTO ) continue;
+ if ( pObj->RetType() == OBJECT_FIX ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+ if ( pObj->RetBurn() ) continue;
+ if ( pObj->RetDead() ) continue;
+
+ if ( !ReadFileStack(pObj, file, objRank++) ) break;
+ }
+ }
+ }
+ CBotClass::RestoreStaticState(file);
+ fClose(file);
+ }
+#endif
+
+ return pSel;
+}
+
+
+// Writes the global parameters for free play.
+
+void CRobotMain::WriteFreeParam()
+{
+ FILE* file;
+ char filename[_MAX_FNAME];
+ char line[100];
+
+ m_freeResearch |= g_researchDone;
+ m_freeBuild |= g_build;
+
+ if ( m_gamerName[0] == 0 ) return;
+
+ sprintf(filename, "%s\\%s\\research.gam", RetSavegameDir(), m_gamerName);
+ file = fopen(filename, "w");
+ if ( file == NULL ) return;
+
+ sprintf(line, "research=%d build=%d\n", m_freeResearch, m_freeBuild);
+ fputs(line, file);
+ fclose(file);
+}
+
+// Reads the global parameters for free play.
+
+void CRobotMain::ReadFreeParam()
+{
+ FILE* file;
+ char filename[_MAX_FNAME];
+ char line[100];
+
+ m_freeResearch = 0;
+ m_freeBuild = 0;
+
+ if ( m_gamerName[0] == 0 ) return;
+
+ sprintf(filename, "%s\\%s\\research.gam", RetSavegameDir(), m_gamerName);
+ file = fopen(filename, "r");
+ if ( file == NULL ) return;
+
+ if ( fgets(line, 100, file) != NULL )
+ {
+ sscanf(line, "research=%d build=%d\n", &m_freeResearch, &m_freeBuild);
+ }
+
+ fclose(file);
+}
+
+
+// Resets all objects to their original position.
+
+void CRobotMain::ResetObject()
+{
+#if 0
+ CObject* pObj;
+ CObject* pTruck;
+ CAuto* pAuto;
+ CBrain* brain;
+ CPyro* pyro;
+ ResetCap cap;
+ Math::Vector pos, angle;
+ int i;
+
+ // Removes all pyrotechnic effects in progress.
+ while ( true )
+ {
+ pyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, 0);
+ if ( pyro == 0 ) break;
+
+ pyro->DeleteObject();
+ delete pyro;
+ }
+
+ // Removes all bullets in progress.
+ m_particule->DeleteParticule(PARTIGUN1);
+ m_particule->DeleteParticule(PARTIGUN2);
+ m_particule->DeleteParticule(PARTIGUN3);
+ m_particule->DeleteParticule(PARTIGUN4);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ cap = pObj->RetResetCap();
+ if ( cap == RESET_NONE ) continue;
+
+ if ( cap == RESET_DELETE )
+ {
+ pTruck = pObj->RetTruck();
+ if ( pTruck != 0 )
+ {
+ pTruck->SetFret(0);
+ pObj->SetTruck(0);
+ }
+ pObj->DeleteObject();
+ delete pObj;
+ i --;
+ continue;
+ }
+
+ pAuto = pObj->RetAuto();
+ if ( pAuto != 0 )
+ {
+ pAuto->Abort();
+ }
+
+ if ( pObj->RetEnable() ) // object still active?
+ {
+ brain = pObj->RetBrain();
+ if ( brain != 0 )
+ {
+ pos = pObj->RetResetPosition();
+ angle = pObj->RetResetAngle();
+
+ if ( pos == pObj->RetPosition(0) &&
+ angle == pObj->RetAngle(0) ) continue;
+ brain->StartTaskReset(pos, angle);
+ continue;
+ }
+ }
+
+ pObj->SetEnable(true); // active again
+
+ pos = pObj->RetResetPosition();
+ angle = pObj->RetResetAngle();
+
+ if ( pos == pObj->RetPosition(0) &&
+ angle == pObj->RetAngle(0) ) continue;
+
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_RESET, pObj);
+
+ brain = pObj->RetBrain();
+ if ( brain != 0 )
+ {
+ brain->RunProgram(pObj->RetResetRun());
+ }
+ }
+#else
+ m_bResetCreate = true;
+#endif
+}
+
+// Resets all objects to their original position.
+
+void CRobotMain::ResetCreate()
+{
+ CObject* pObj;
+ CPyro* pyro;
+ ResetCap cap;
+ int i;
+
+ SaveAllScript();
+
+ // Removes all bullets in progress.
+ m_particule->DeleteParticule(PARTIGUN1);
+ m_particule->DeleteParticule(PARTIGUN2);
+ m_particule->DeleteParticule(PARTIGUN3);
+ m_particule->DeleteParticule(PARTIGUN4);
+
+ DeselectAll(); // removes the control buttons
+ DeleteAllObjects(); // removes all the current 3D Scene
+
+ m_particule->FlushParticule();
+ m_terrain->FlushBuildingLevel();
+ m_iMan->Flush(CLASS_OBJECT);
+ m_iMan->Flush(CLASS_PHYSICS);
+ m_iMan->Flush(CLASS_BRAIN);
+ m_iMan->Flush(CLASS_PYRO);
+ m_camera->SetType(CAMERA_DIALOG);
+
+ CreateScene(m_dialog->RetSceneSoluce(), false, true);
+
+ if ( !RetNiceReset() ) return;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ cap = pObj->RetResetCap();
+ if ( cap == RESET_NONE ) continue;
+
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_RESET, pObj);
+ }
+}
+
+// Checks if the mission is over.
+
+Error CRobotMain::CheckEndMission(bool bFrame)
+{
+ CObject* pObj;
+ Math::Vector bPos, oPos;
+ ObjectType type;
+ int t, i, nb;
+
+ for ( t=0 ; t<m_endTakeTotal ; t++ )
+ {
+ if ( m_endTake[t].message[0] != 0 ) continue;
+
+ bPos = m_endTake[t].pos;
+ bPos.y = 0.0f;
+
+ nb = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ // Do not use RetActif () because an invisible worm (underground)
+ // should be regarded as existing here!
+ if ( pObj->RetLock() ) continue;
+ if ( pObj->RetRuin() ) continue;
+ if ( !pObj->RetEnable() ) continue;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_SCRAP2 ||
+ type == OBJECT_SCRAP3 ||
+ type == OBJECT_SCRAP4 ||
+ type == OBJECT_SCRAP5 ) // wastes?
+ {
+ type = OBJECT_SCRAP1;
+ }
+ if ( type != m_endTake[t].type ) continue;
+
+ if ( pObj->RetTruck() == 0 )
+ {
+ oPos = pObj->RetPosition(0);
+ }
+ else
+ {
+ oPos = pObj->RetTruck()->RetPosition(0);
+ }
+ oPos.y = 0.0f;
+ if ( Math::DistanceProjected(oPos, bPos) <= m_endTake[t].dist )
+ {
+ nb ++;
+ }
+ }
+
+ if ( nb <= m_endTake[t].lost )
+ {
+ if ( m_endTake[t].type == OBJECT_HUMAN )
+ {
+ if ( m_lostDelay == 0.0f )
+ {
+ m_lostDelay = 0.1f; // lost immediately
+ m_winDelay = 0.0f;
+ }
+ m_displayText->SetEnable(false);
+ return INFO_LOSTq;
+ }
+ else
+ {
+ if ( m_lostDelay == 0.0f )
+ {
+ m_displayText->DisplayError(INFO_LOST, Math::Vector(0.0f,0.0f,0.0f));
+ m_lostDelay = m_endTakeLostDelay; // lost in 6 seconds
+ m_winDelay = 0.0f;
+ }
+ m_displayText->SetEnable(false);
+ return INFO_LOST;
+ }
+ }
+ if ( nb < m_endTake[t].min ||
+ nb > m_endTake[t].max )
+ {
+ m_displayText->SetEnable(true);
+ return ERR_MISSION_NOTERM;
+ }
+ if ( m_endTake[t].bImmediat )
+ {
+ if ( m_winDelay == 0.0f )
+ {
+ m_winDelay = m_endTakeWinDelay; // wins in x seconds
+ m_lostDelay = 0.0f;
+ }
+ m_displayText->SetEnable(false);
+ return ERR_OK; // mission ended
+ }
+ }
+
+ if ( m_endTakeResearch != 0 )
+ {
+ if ( m_endTakeResearch != (m_endTakeResearch&g_researchDone) )
+ {
+ m_displayText->SetEnable(true);
+ return ERR_MISSION_NOTERM;
+ }
+ }
+
+ if ( m_endTakeWinDelay == -1.0f )
+ {
+ m_winDelay = 1.0f; // wins in one second
+ m_lostDelay = 0.0f;
+ m_displayText->SetEnable(false);
+ return ERR_OK; // mission ended
+ }
+
+ if ( bFrame && m_bBase ) return ERR_MISSION_NOTERM;
+
+ if ( m_winDelay == 0.0f )
+ {
+ m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f));
+ m_winDelay = m_endTakeWinDelay; // wins in two seconds
+ m_lostDelay = 0.0f;
+ }
+ m_displayText->SetEnable(false);
+ return ERR_OK; // mission ended
+}
+
+// Checks if the mission is finished after displaying a message.
+
+void CRobotMain::CheckEndMessage(char *message)
+{
+ int t;
+
+ for ( t=0 ; t<m_endTakeTotal ; t++ )
+ {
+ if ( m_endTake[t].message[0] == 0 ) continue;
+
+ if ( strcmp(m_endTake[t].message, message) == 0 )
+ {
+ m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f));
+ m_winDelay = m_endTakeWinDelay; // wins in 2 seconds
+ m_lostDelay = 0.0f;
+ }
+ }
+}
+
+
+// Returns the number of instructions required.
+
+int CRobotMain::RetObligatoryToken()
+{
+ return m_obligatoryTotal;
+}
+
+// Returns the name of a required instruction.
+
+char* CRobotMain::RetObligatoryToken(int i)
+{
+ return m_obligatoryToken[i];
+}
+
+// Checks if an instruction is part of the obligatory list.
+
+int CRobotMain::IsObligatoryToken(char *token)
+{
+ int i;
+
+ for ( i=0 ; i<m_obligatoryTotal ; i++ )
+ {
+ if ( strcmp(token, m_obligatoryToken[i]) == 0 )
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+// Checks if an instruction is not part of the banned list.
+
+bool CRobotMain::IsProhibitedToken(char *token)
+{
+ int i;
+
+ for ( i=0 ; i<m_prohibitedTotal ; i++ )
+ {
+ if ( strcmp(token, m_prohibitedToken[i]) == 0 )
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+// Indicates whether it is possible to control a driving robot.
+
+bool CRobotMain::RetTrainerPilot()
+{
+ return m_bTrainerPilot;
+}
+
+// Indicates whether the scene is fixed, without interaction.
+
+bool CRobotMain::RetFixScene()
+{
+ return m_bFixScene;
+}
+
+
+char* CRobotMain::RetTitle()
+{
+ return m_title;
+}
+
+char* CRobotMain::RetResume()
+{
+ return m_resume;
+}
+
+char* CRobotMain::RetScriptName()
+{
+ return m_scriptName;
+}
+
+char* CRobotMain::RetScriptFile()
+{
+ return m_scriptFile;
+}
+
+
+bool CRobotMain::RetGlint()
+{
+ return m_dialog->RetGlint();
+}
+
+bool CRobotMain::RetSoluce4()
+{
+ return m_dialog->RetSoluce4();
+}
+
+bool CRobotMain::RetMovies()
+{
+ return m_dialog->RetMovies();
+}
+
+bool CRobotMain::RetNiceReset()
+{
+ return m_dialog->RetNiceReset();
+}
+
+bool CRobotMain::RetHimselfDamage()
+{
+ return m_dialog->RetHimselfDamage();
+}
+
+bool CRobotMain::RetShowSoluce()
+{
+ return m_bShowSoluce;
+}
+
+bool CRobotMain::RetSceneSoluce()
+{
+ if ( m_infoFilename[SATCOM_SOLUCE][0] == 0 ) return false;
+ return m_dialog->RetSceneSoluce();
+}
+
+bool CRobotMain::RetShowAll()
+{
+ return m_bShowAll;
+}
+
+bool CRobotMain::RetCheatRadar()
+{
+ return m_bCheatRadar;
+}
+
+char* CRobotMain::RetSavegameDir()
+{
+ return m_dialog->RetSavegameDir();
+}
+
+char* CRobotMain::RetPublicDir()
+{
+ return m_dialog->RetPublicDir();
+}
+
+char* CRobotMain::RetFilesDir()
+{
+ return m_dialog->RetFilesDir();
+}
+
+
+// Change the player's name.
+
+void CRobotMain::SetGamerName(char *name)
+{
+ strcpy(m_gamerName, name);
+ SetGlobalGamerName(m_gamerName);
+ ReadFreeParam();
+}
+
+// Gives the player's name.
+
+char* CRobotMain::RetGamerName()
+{
+ return m_gamerName;
+}
+
+
+// Returns the representation to use for the player.
+
+int CRobotMain::RetGamerFace()
+{
+ return m_dialog->RetGamerFace();
+}
+
+// Returns the representation to use for the player.
+
+int CRobotMain::RetGamerGlasses()
+{
+ return m_dialog->RetGamerGlasses();
+}
+
+// Returns the mode with just the head.
+
+bool CRobotMain::RetGamerOnlyHead()
+{
+ return m_dialog->RetGamerOnlyHead();
+}
+
+// Returns the angle of presentation.
+
+float CRobotMain::RetPersoAngle()
+{
+ return m_dialog->RetPersoAngle();
+}
+
+
+// Changes on the pause mode.
+
+void CRobotMain::ChangePause(bool bPause)
+{
+ m_bPause = bPause;
+ m_engine->SetPause(m_bPause);
+
+ m_sound->MuteAll(m_bPause);
+ CreateShortcuts();
+ if ( m_bPause ) HiliteClear();
+}
+
+
+// Changes game speed
+
+void CRobotMain::SetSpeed(float speed)
+{
+ CButton* pb;
+ char text[10];
+
+ m_engine->SetSpeed(speed);
+
+ pb = (CButton*)m_interface->SearchControl(EVENT_SPEED);
+ if ( pb != 0 )
+ {
+ if ( speed == 1.0f )
+ {
+ pb->ClearState(STATE_VISIBLE);
+ }
+ else
+ {
+ sprintf(text, "x%.1f", speed);
+ pb->SetName(text);
+ pb->SetState(STATE_VISIBLE);
+ }
+ }
+}
+
+float CRobotMain::RetSpeed()
+{
+ return m_engine->RetSpeed();
+}
+
+
+// Creates interface shortcuts to the units.
+
+bool CRobotMain::CreateShortcuts()
+{
+ if ( m_phase != PHASE_SIMUL ) return false;
+ if ( !m_bShortCut ) return false;
+ return m_short->CreateShortcuts();
+}
+
+// Updates the map.
+
+void CRobotMain::UpdateMap()
+{
+ m_map->UpdateMap();
+}
+
+// Indicates whether the mini-map is visible.
+
+bool CRobotMain::RetShowMap()
+{
+ return m_map->RetShowMap() && m_bMapShow;
+}
+
+
+// Management of the lock mode for movies.
+
+void CRobotMain::SetMovieLock(bool bLock)
+{
+ m_bMovieLock = bLock;
+ m_engine->SetMovieLock(m_bMovieLock);
+
+ CreateShortcuts();
+ m_map->ShowMap(!m_bMovieLock && m_bMapShow);
+ if ( m_bMovieLock ) HiliteClear();
+ m_engine->SetMouseHide(m_bMovieLock);
+}
+
+bool CRobotMain::RetMovieLock()
+{
+ return m_bMovieLock;
+}
+
+bool CRobotMain::RetInfoLock()
+{
+ return ( m_displayInfo != 0 ); // info in progress?
+}
+
+// Management of the blocking of the call of SatCom.
+
+void CRobotMain::SetSatComLock(bool bLock)
+{
+ m_bSatComLock = bLock;
+}
+
+bool CRobotMain::RetSatComLock()
+{
+ return m_bSatComLock;
+}
+
+// Management of the lock mode for the edition.
+
+void CRobotMain::SetEditLock(bool bLock, bool bEdit)
+{
+ m_bEditLock = bLock;
+
+ CreateShortcuts();
+
+ // Do not remove the card if it contains a still image.
+ if ( !bLock || !m_map->RetFixImage() )
+ {
+ m_map->ShowMap(!m_bEditLock && m_bMapShow);
+ }
+
+ m_displayText->HideText(bLock);
+ m_engine->FlushPressKey();
+
+ if ( m_bEditLock )
+ {
+ HiliteClear();
+ }
+ else
+ {
+ m_bEditFull = false;
+ }
+}
+
+bool CRobotMain::RetEditLock()
+{
+ return m_bEditLock;
+}
+
+// Management of the fullscreen mode during editing.
+
+void CRobotMain::SetEditFull(bool bFull)
+{
+ m_bEditFull = bFull;
+}
+
+bool CRobotMain::RetEditFull()
+{
+ return m_bEditFull;
+}
+
+
+bool CRobotMain::RetFreePhoto()
+{
+ return m_bFreePhoto;
+}
+
+
+// Indicates whether mouse is on an friend object, on which we should not shoot.
+
+void CRobotMain::SetFriendAim(bool bFriend)
+{
+ m_bFriendAim = bFriend;
+}
+
+bool CRobotMain::RetFriendAim()
+{
+ return m_bFriendAim;
+}
+
+
+// Management of the precision of drawing the ground.
+
+void CRobotMain::SetTracePrecision(float factor)
+{
+ m_engine->SetTracePrecision(factor);
+}
+
+float CRobotMain::RetTracePrecision()
+{
+ return m_engine->RetTracePrecision();
+}
+
+
+// Starts music with a mission.
+
+void CRobotMain::StartMusic()
+{
+ if ( m_audioTrack != 0 )
+ {
+ m_sound->StopMusic();
+ m_sound->PlayMusic(m_audioTrack, m_bAudioRepeat);
+ }
+}
+
+// Removes hilite and tooltip.
+
+void CRobotMain::ClearInterface()
+{
+ HiliteClear(); // removes setting evidence
+ m_tooltipName[0] = 0; // really removes the tooltip
+}
+
+
diff --git a/src/object/robotmain.h b/src/object/robotmain.h
index a4b0489..559453b 100644
--- a/src/object/robotmain.h
+++ b/src/object/robotmain.h
@@ -1,459 +1,459 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// robotmain.h
-
-#pragma once
-
-
-#include <stdio.h>
-
-#include "common/misc.h"
-#include "old/d3dengine.h"
-#include "object/object.h"
-#include "object/mainmovie.h"
-#include "old/camera.h"
-#include "old/particule.h"
-
-
-enum Phase
-{
- PHASE_INIT,
- PHASE_TERM,
- PHASE_NAME,
- PHASE_PERSO,
- PHASE_TRAINER,
- PHASE_DEFI,
- PHASE_MISSION,
- PHASE_FREE,
- PHASE_TEEN,
- PHASE_USER,
- PHASE_PROTO,
- PHASE_LOADING,
- PHASE_SIMUL,
- PHASE_MODEL,
- PHASE_SETUPd,
- PHASE_SETUPg,
- PHASE_SETUPp,
- PHASE_SETUPc,
- PHASE_SETUPs,
- PHASE_SETUPds,
- PHASE_SETUPgs,
- PHASE_SETUPps,
- PHASE_SETUPcs,
- PHASE_SETUPss,
- PHASE_WRITE,
- PHASE_READ,
- PHASE_WRITEs,
- PHASE_READs,
- PHASE_WIN,
- PHASE_LOST,
- PHASE_WELCOME1,
- PHASE_WELCOME2,
- PHASE_WELCOME3,
- PHASE_GENERIC,
-};
-
-
-class CInstanceManager;
-class CMainDialog;
-class CMainShort;
-class CMainMap;
-class CEvent;
-class CD3DEngine;
-class CLight;
-class CWater;
-class CCloud;
-class CBlitz;
-class CPlanet;
-class CTerrain;
-class CModel;
-class CInterface;
-class CWindow;
-class CControl;
-class CDisplayText;
-class CDisplayInfo;
-class CSound;
-
-
-struct EndTake
-{
- Math::Vector pos;
- float dist;
- ObjectType type;
- int min; // wins if>
- int max; // wins if <
- int lost; // lost if <=
- bool bImmediat;
- char message[100];
-};
-
-
-const int MAXNEWSCRIPTNAME = 20;
-
-struct NewScriptName
-{
- bool bUsed;
- ObjectType type;
- char name[40];
-};
-
-
-const int MAXSHOWLIMIT = 5;
-const int MAXSHOWPARTI = 200;
-const float SHOWLIMITTIME = 20.0f;
-
-struct ShowLimit
-{
- bool bUsed;
- Math::Vector pos;
- float radius;
- int total;
- int parti[MAXSHOWPARTI];
- CObject* link;
- float duration;
- float time;
-};
-
-
-const int SATCOM_HUSTON = 0;
-const int SATCOM_SAT = 1;
-const int SATCOM_OBJECT = 2;
-const int SATCOM_LOADING = 3;
-const int SATCOM_PROG = 4;
-const int SATCOM_SOLUCE = 5;
-const int SATCOM_MAX = 6;
-
-
-
-class CRobotMain
-{
-public:
- CRobotMain(CInstanceManager* iMan);
- ~CRobotMain();
-
- void CreateIni();
-
- void ChangePhase(Phase phase);
- bool EventProcess(const Event &event);
-
- bool CreateShortcuts();
- void ScenePerso();
-
- void SetMovieLock(bool bLock);
- bool RetMovieLock();
- bool RetInfoLock();
- void SetSatComLock(bool bLock);
- bool RetSatComLock();
- void SetEditLock(bool bLock, bool bEdit);
- bool RetEditLock();
- void SetEditFull(bool bFull);
- bool RetEditFull();
- bool RetFreePhoto();
- void SetFriendAim(bool bFriend);
- bool RetFriendAim();
-
- void SetTracePrecision(float factor);
- float RetTracePrecision();
-
- void ChangePause(bool bPause);
-
- void SetSpeed(float speed);
- float RetSpeed();
-
- void UpdateShortcuts();
- void SelectHuman();
- CObject* SearchHuman();
- CObject* SearchToto();
- CObject* SearchNearest(Math::Vector pos, CObject* pExclu);
- bool SelectObject(CObject* pObj, bool bDisplayError=true);
- CObject* RetSelectObject();
- CObject* DeselectAll();
- bool DeleteObject();
-
- void ResetObject();
- void ResetCreate();
- Error CheckEndMission(bool bFrame);
- void CheckEndMessage(char *message);
- int RetObligatoryToken();
- char* RetObligatoryToken(int i);
- int IsObligatoryToken(char *token);
- bool IsProhibitedToken(char *token);
- void UpdateMap();
- bool RetShowMap();
-
- MainMovieType RetMainMovie();
-
- void FlushDisplayInfo();
- void StartDisplayInfo(int index, bool bMovie);
- void StartDisplayInfo(char *filename, int index);
- void StopDisplayInfo();
- char* RetDisplayInfoName(int index);
- int RetDisplayInfoPosition(int index);
- void SetDisplayInfoPosition(int index, int pos);
-
- void StartSuspend();
- void StopSuspend();
-
- float RetGameTime();
-
- void SetFontSize(float size);
- float RetFontSize();
- void SetWindowPos(Math::Point pos);
- Math::Point RetWindowPos();
- void SetWindowDim(Math::Point dim);
- Math::Point RetWindowDim();
-
- void SetIOPublic(bool bMode);
- bool RetIOPublic();
- void SetIOPos(Math::Point pos);
- Math::Point RetIOPos();
- void SetIODim(Math::Point dim);
- Math::Point RetIODim();
-
- char* RetTitle();
- char* RetResume();
- char* RetScriptName();
- char* RetScriptFile();
- bool RetTrainerPilot();
- bool RetFixScene();
- bool RetGlint();
- bool RetSoluce4();
- bool RetMovies();
- bool RetNiceReset();
- bool RetHimselfDamage();
- bool RetShowSoluce();
- bool RetSceneSoluce();
- bool RetShowAll();
- bool RetCheatRadar();
- char* RetSavegameDir();
- char* RetPublicDir();
- char* RetFilesDir();
-
- void SetGamerName(char *name);
- char* RetGamerName();
- int RetGamerFace();
- int RetGamerGlasses();
- bool RetGamerOnlyHead();
- float RetPersoAngle();
-
- void StartMusic();
- void ClearInterface();
- void ChangeColor();
-
- float SearchNearestObject(Math::Vector center, CObject *exclu);
- bool FreeSpace(Math::Vector &center, float minRadius, float maxRadius, float space, CObject *exclu);
- float RetFlatZoneRadius(Math::Vector center, float maxRadius, CObject *exclu);
- void HideDropZone(CObject* metal);
- void ShowDropZone(CObject* metal, CObject* truck);
- void FlushShowLimit(int i);
- void SetShowLimit(int i, ParticuleType parti, CObject *pObj, Math::Vector pos, float radius, float duration=SHOWLIMITTIME);
- void AdjustShowLimit(int i, Math::Vector pos);
- void StartShowLimit();
- void FrameShowLimit(float rTime);
-
- void CompileScript(bool bSoluce);
- void LoadOneScript(CObject *pObj, int &nbError);
- void LoadFileScript(CObject *pObj, char* filename, int objRank, int &nbError);
- void SaveAllScript();
- void SaveOneScript(CObject *pObj);
- void SaveFileScript(CObject *pObj, char* filename, int objRank);
- bool SaveFileStack(CObject *pObj, FILE *file, int objRank);
- bool ReadFileStack(CObject *pObj, FILE *file, int objRank);
-
- bool FlushNewScriptName();
- bool AddNewScriptName(ObjectType type, char *name);
- char* RetNewScriptName(ObjectType type, int rank);
-
- void WriteFreeParam();
- void ReadFreeParam();
-
- bool IsBusy();
- bool IOWriteScene(char *filename, char *filecbot, char *info);
- CObject* IOReadScene(char *filename, char *filecbot);
- void IOWriteObject(FILE *file, CObject* pObj, char *cmd);
- CObject* IOReadObject(char *line, char* filename, int objRank);
-
- int CreateSpot(Math::Vector pos, D3DCOLORVALUE color);
-
-protected:
- bool EventFrame(const Event &event);
- bool EventObject(const Event &event);
- void InitEye();
-
- void Convert();
- void CreateScene(bool bSoluce, bool bFixScene, bool bResetObject);
-
- void CreateModel();
- Math::Vector LookatPoint( Math::Vector eye, float angleH, float angleV, float length );
- CObject* CreateObject(Math::Vector pos, float angle, float zoom, float height, ObjectType type, float power=1.0f, bool bTrainer=false, bool bToy=false, int option=0);
- int CreateLight(Math::Vector direction, D3DCOLORVALUE color);
- void HiliteClear();
- void HiliteObject(Math::Point pos);
- void HiliteFrame(float rTime);
- void CreateTooltip(Math::Point pos, char* text);
- void ClearTooltip();
- CObject* DetectObject(Math::Point pos);
- void ChangeCamera();
- void RemoteCamera(float pan, float zoom, float rTime);
- void KeyCamera(EventMsg event, long param);
- void AbortMovie();
- bool IsSelectable(CObject* pObj);
- void SelectOneObject(CObject* pObj, bool bDisplayError=true);
- void HelpObject();
- bool DeselectObject();
- void DeleteAllObjects();
- void UpdateInfoText();
- CObject* SearchObject(ObjectType type);
- CObject* RetSelect();
- void StartDisplayVisit(EventMsg event);
- void FrameVisit(float rTime);
- void StopDisplayVisit();
- void ExecuteCmd(char *cmd);
- bool TestGadgetQuantity(int rank);
-
-protected:
- CInstanceManager* m_iMan;
- CMainMovie* m_movie;
- CMainDialog* m_dialog;
- CMainShort* m_short;
- CMainMap* m_map;
- CEvent* m_event;
- CD3DEngine* m_engine;
- CParticule* m_particule;
- CWater* m_water;
- CCloud* m_cloud;
- CBlitz* m_blitz;
- CPlanet* m_planet;
- CLight* m_light;
- CTerrain* m_terrain;
- CModel* m_model;
- CInterface* m_interface;
- CCamera* m_camera;
- CDisplayText* m_displayText;
- CDisplayInfo* m_displayInfo;
- CSound* m_sound;
-
- float m_time;
- float m_gameTime;
- float m_checkEndTime;
- float m_winDelay;
- float m_lostDelay;
- bool m_bFixScene; // scene fixed, no interraction
- bool m_bBase; // OBJECT_BASE exists in mission
- Math::Point m_lastMousePos;
- CObject* m_selectObject;
-
- Phase m_phase;
- int m_cameraRank;
- D3DCOLORVALUE m_color;
- bool m_bFreePhoto;
- bool m_bCmdEdit;
- bool m_bShowPos;
- bool m_bSelectInsect;
- bool m_bShowSoluce;
- bool m_bShowAll;
- bool m_bCheatRadar;
- bool m_bAudioRepeat;
- bool m_bShortCut;
- int m_audioTrack;
- int m_delayWriteMessage;
- int m_movieInfoIndex;
-
- bool m_bImmediatSatCom; // SatCom immediately?
- bool m_bBeginSatCom; // messages SatCom poster?
- bool m_bMovieLock; // movie in progress?
- bool m_bSatComLock; // call of SatCom is possible?
- bool m_bEditLock; // edition in progress?
- bool m_bEditFull; // edition in full screen?
- bool m_bPause; // simulation paused
- bool m_bHilite;
- bool m_bTrainerPilot; // remote trainer?
- bool m_bSuspend;
- bool m_bFriendAim;
- bool m_bResetCreate;
- bool m_bMapShow;
- bool m_bMapImage;
- char m_mapFilename[100];
-
- Math::Point m_tooltipPos;
- char m_tooltipName[100];
- float m_tooltipTime;
-
- char m_infoFilename[SATCOM_MAX][100]; // names of text files
- CObject* m_infoObject;
- int m_infoIndex;
- int m_infoPos[SATCOM_MAX];
- int m_infoUsed;
-
- char m_title[100];
- char m_resume[500];
- char m_scriptName[100];
- char m_scriptFile[100];
- int m_endingWinRank;
- int m_endingLostRank;
- bool m_bWinTerminate;
-
- float m_fontSize;
- Math::Point m_windowPos;
- Math::Point m_windowDim;
-
- bool m_IOPublic;
- Math::Point m_IOPos;
- Math::Point m_IODim;
-
- NewScriptName m_newScriptName[MAXNEWSCRIPTNAME];
-
- float m_cameraPan;
- float m_cameraZoom;
-
- EventMsg m_visitLast;
- CObject* m_visitObject;
- CObject* m_visitArrow;
- float m_visitTime;
- float m_visitParticule;
- Math::Vector m_visitPos;
- Math::Vector m_visitPosArrow;
-
- int m_endTakeTotal;
- EndTake m_endTake[10];
- long m_endTakeResearch;
- float m_endTakeWinDelay;
- float m_endTakeLostDelay;
-
- int m_obligatoryTotal;
- char m_obligatoryToken[100][20];
- int m_prohibitedTotal;
- char m_prohibitedToken[100][20];
-
- char m_gamerName[100];
-
- long m_freeBuild; // constructible buildings
- long m_freeResearch; // researches possible
-
- ShowLimit m_showLimit[MAXSHOWLIMIT];
-
- D3DCOLORVALUE m_colorRefBot;
- D3DCOLORVALUE m_colorNewBot;
- D3DCOLORVALUE m_colorRefAlien;
- D3DCOLORVALUE m_colorNewAlien;
- D3DCOLORVALUE m_colorRefGreen;
- D3DCOLORVALUE m_colorNewGreen;
- D3DCOLORVALUE m_colorRefWater;
- D3DCOLORVALUE m_colorNewWater;
- float m_colorShiftWater;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// robotmain.h
+
+#pragma once
+
+
+#include <stdio.h>
+
+#include "common/misc.h"
+#include "old/d3dengine.h"
+#include "object/object.h"
+#include "object/mainmovie.h"
+#include "old/camera.h"
+#include "old/particule.h"
+
+
+enum Phase
+{
+ PHASE_INIT,
+ PHASE_TERM,
+ PHASE_NAME,
+ PHASE_PERSO,
+ PHASE_TRAINER,
+ PHASE_DEFI,
+ PHASE_MISSION,
+ PHASE_FREE,
+ PHASE_TEEN,
+ PHASE_USER,
+ PHASE_PROTO,
+ PHASE_LOADING,
+ PHASE_SIMUL,
+ PHASE_MODEL,
+ PHASE_SETUPd,
+ PHASE_SETUPg,
+ PHASE_SETUPp,
+ PHASE_SETUPc,
+ PHASE_SETUPs,
+ PHASE_SETUPds,
+ PHASE_SETUPgs,
+ PHASE_SETUPps,
+ PHASE_SETUPcs,
+ PHASE_SETUPss,
+ PHASE_WRITE,
+ PHASE_READ,
+ PHASE_WRITEs,
+ PHASE_READs,
+ PHASE_WIN,
+ PHASE_LOST,
+ PHASE_WELCOME1,
+ PHASE_WELCOME2,
+ PHASE_WELCOME3,
+ PHASE_GENERIC,
+};
+
+
+class CInstanceManager;
+class CMainDialog;
+class CMainShort;
+class CMainMap;
+class CEvent;
+class CD3DEngine;
+class CLight;
+class CWater;
+class CCloud;
+class CBlitz;
+class CPlanet;
+class CTerrain;
+class CModel;
+class CInterface;
+class CWindow;
+class CControl;
+class CDisplayText;
+class CDisplayInfo;
+class CSound;
+
+
+struct EndTake
+{
+ Math::Vector pos;
+ float dist;
+ ObjectType type;
+ int min; // wins if>
+ int max; // wins if <
+ int lost; // lost if <=
+ bool bImmediat;
+ char message[100];
+};
+
+
+const int MAXNEWSCRIPTNAME = 20;
+
+struct NewScriptName
+{
+ bool bUsed;
+ ObjectType type;
+ char name[40];
+};
+
+
+const int MAXSHOWLIMIT = 5;
+const int MAXSHOWPARTI = 200;
+const float SHOWLIMITTIME = 20.0f;
+
+struct ShowLimit
+{
+ bool bUsed;
+ Math::Vector pos;
+ float radius;
+ int total;
+ int parti[MAXSHOWPARTI];
+ CObject* link;
+ float duration;
+ float time;
+};
+
+
+const int SATCOM_HUSTON = 0;
+const int SATCOM_SAT = 1;
+const int SATCOM_OBJECT = 2;
+const int SATCOM_LOADING = 3;
+const int SATCOM_PROG = 4;
+const int SATCOM_SOLUCE = 5;
+const int SATCOM_MAX = 6;
+
+
+
+class CRobotMain
+{
+public:
+ CRobotMain(CInstanceManager* iMan);
+ ~CRobotMain();
+
+ void CreateIni();
+
+ void ChangePhase(Phase phase);
+ bool EventProcess(const Event &event);
+
+ bool CreateShortcuts();
+ void ScenePerso();
+
+ void SetMovieLock(bool bLock);
+ bool RetMovieLock();
+ bool RetInfoLock();
+ void SetSatComLock(bool bLock);
+ bool RetSatComLock();
+ void SetEditLock(bool bLock, bool bEdit);
+ bool RetEditLock();
+ void SetEditFull(bool bFull);
+ bool RetEditFull();
+ bool RetFreePhoto();
+ void SetFriendAim(bool bFriend);
+ bool RetFriendAim();
+
+ void SetTracePrecision(float factor);
+ float RetTracePrecision();
+
+ void ChangePause(bool bPause);
+
+ void SetSpeed(float speed);
+ float RetSpeed();
+
+ void UpdateShortcuts();
+ void SelectHuman();
+ CObject* SearchHuman();
+ CObject* SearchToto();
+ CObject* SearchNearest(Math::Vector pos, CObject* pExclu);
+ bool SelectObject(CObject* pObj, bool bDisplayError=true);
+ CObject* RetSelectObject();
+ CObject* DeselectAll();
+ bool DeleteObject();
+
+ void ResetObject();
+ void ResetCreate();
+ Error CheckEndMission(bool bFrame);
+ void CheckEndMessage(char *message);
+ int RetObligatoryToken();
+ char* RetObligatoryToken(int i);
+ int IsObligatoryToken(char *token);
+ bool IsProhibitedToken(char *token);
+ void UpdateMap();
+ bool RetShowMap();
+
+ MainMovieType RetMainMovie();
+
+ void FlushDisplayInfo();
+ void StartDisplayInfo(int index, bool bMovie);
+ void StartDisplayInfo(char *filename, int index);
+ void StopDisplayInfo();
+ char* RetDisplayInfoName(int index);
+ int RetDisplayInfoPosition(int index);
+ void SetDisplayInfoPosition(int index, int pos);
+
+ void StartSuspend();
+ void StopSuspend();
+
+ float RetGameTime();
+
+ void SetFontSize(float size);
+ float RetFontSize();
+ void SetWindowPos(Math::Point pos);
+ Math::Point RetWindowPos();
+ void SetWindowDim(Math::Point dim);
+ Math::Point RetWindowDim();
+
+ void SetIOPublic(bool bMode);
+ bool RetIOPublic();
+ void SetIOPos(Math::Point pos);
+ Math::Point RetIOPos();
+ void SetIODim(Math::Point dim);
+ Math::Point RetIODim();
+
+ char* RetTitle();
+ char* RetResume();
+ char* RetScriptName();
+ char* RetScriptFile();
+ bool RetTrainerPilot();
+ bool RetFixScene();
+ bool RetGlint();
+ bool RetSoluce4();
+ bool RetMovies();
+ bool RetNiceReset();
+ bool RetHimselfDamage();
+ bool RetShowSoluce();
+ bool RetSceneSoluce();
+ bool RetShowAll();
+ bool RetCheatRadar();
+ char* RetSavegameDir();
+ char* RetPublicDir();
+ char* RetFilesDir();
+
+ void SetGamerName(char *name);
+ char* RetGamerName();
+ int RetGamerFace();
+ int RetGamerGlasses();
+ bool RetGamerOnlyHead();
+ float RetPersoAngle();
+
+ void StartMusic();
+ void ClearInterface();
+ void ChangeColor();
+
+ float SearchNearestObject(Math::Vector center, CObject *exclu);
+ bool FreeSpace(Math::Vector &center, float minRadius, float maxRadius, float space, CObject *exclu);
+ float RetFlatZoneRadius(Math::Vector center, float maxRadius, CObject *exclu);
+ void HideDropZone(CObject* metal);
+ void ShowDropZone(CObject* metal, CObject* truck);
+ void FlushShowLimit(int i);
+ void SetShowLimit(int i, ParticuleType parti, CObject *pObj, Math::Vector pos, float radius, float duration=SHOWLIMITTIME);
+ void AdjustShowLimit(int i, Math::Vector pos);
+ void StartShowLimit();
+ void FrameShowLimit(float rTime);
+
+ void CompileScript(bool bSoluce);
+ void LoadOneScript(CObject *pObj, int &nbError);
+ void LoadFileScript(CObject *pObj, char* filename, int objRank, int &nbError);
+ void SaveAllScript();
+ void SaveOneScript(CObject *pObj);
+ void SaveFileScript(CObject *pObj, char* filename, int objRank);
+ bool SaveFileStack(CObject *pObj, FILE *file, int objRank);
+ bool ReadFileStack(CObject *pObj, FILE *file, int objRank);
+
+ bool FlushNewScriptName();
+ bool AddNewScriptName(ObjectType type, char *name);
+ char* RetNewScriptName(ObjectType type, int rank);
+
+ void WriteFreeParam();
+ void ReadFreeParam();
+
+ bool IsBusy();
+ bool IOWriteScene(char *filename, char *filecbot, char *info);
+ CObject* IOReadScene(char *filename, char *filecbot);
+ void IOWriteObject(FILE *file, CObject* pObj, char *cmd);
+ CObject* IOReadObject(char *line, char* filename, int objRank);
+
+ int CreateSpot(Math::Vector pos, D3DCOLORVALUE color);
+
+protected:
+ bool EventFrame(const Event &event);
+ bool EventObject(const Event &event);
+ void InitEye();
+
+ void Convert();
+ void CreateScene(bool bSoluce, bool bFixScene, bool bResetObject);
+
+ void CreateModel();
+ Math::Vector LookatPoint( Math::Vector eye, float angleH, float angleV, float length );
+ CObject* CreateObject(Math::Vector pos, float angle, float zoom, float height, ObjectType type, float power=1.0f, bool bTrainer=false, bool bToy=false, int option=0);
+ int CreateLight(Math::Vector direction, D3DCOLORVALUE color);
+ void HiliteClear();
+ void HiliteObject(Math::Point pos);
+ void HiliteFrame(float rTime);
+ void CreateTooltip(Math::Point pos, char* text);
+ void ClearTooltip();
+ CObject* DetectObject(Math::Point pos);
+ void ChangeCamera();
+ void RemoteCamera(float pan, float zoom, float rTime);
+ void KeyCamera(EventMsg event, long param);
+ void AbortMovie();
+ bool IsSelectable(CObject* pObj);
+ void SelectOneObject(CObject* pObj, bool bDisplayError=true);
+ void HelpObject();
+ bool DeselectObject();
+ void DeleteAllObjects();
+ void UpdateInfoText();
+ CObject* SearchObject(ObjectType type);
+ CObject* RetSelect();
+ void StartDisplayVisit(EventMsg event);
+ void FrameVisit(float rTime);
+ void StopDisplayVisit();
+ void ExecuteCmd(char *cmd);
+ bool TestGadgetQuantity(int rank);
+
+protected:
+ CInstanceManager* m_iMan;
+ CMainMovie* m_movie;
+ CMainDialog* m_dialog;
+ CMainShort* m_short;
+ CMainMap* m_map;
+ CEvent* m_event;
+ CD3DEngine* m_engine;
+ CParticule* m_particule;
+ CWater* m_water;
+ CCloud* m_cloud;
+ CBlitz* m_blitz;
+ CPlanet* m_planet;
+ CLight* m_light;
+ CTerrain* m_terrain;
+ CModel* m_model;
+ CInterface* m_interface;
+ CCamera* m_camera;
+ CDisplayText* m_displayText;
+ CDisplayInfo* m_displayInfo;
+ CSound* m_sound;
+
+ float m_time;
+ float m_gameTime;
+ float m_checkEndTime;
+ float m_winDelay;
+ float m_lostDelay;
+ bool m_bFixScene; // scene fixed, no interraction
+ bool m_bBase; // OBJECT_BASE exists in mission
+ Math::Point m_lastMousePos;
+ CObject* m_selectObject;
+
+ Phase m_phase;
+ int m_cameraRank;
+ D3DCOLORVALUE m_color;
+ bool m_bFreePhoto;
+ bool m_bCmdEdit;
+ bool m_bShowPos;
+ bool m_bSelectInsect;
+ bool m_bShowSoluce;
+ bool m_bShowAll;
+ bool m_bCheatRadar;
+ bool m_bAudioRepeat;
+ bool m_bShortCut;
+ int m_audioTrack;
+ int m_delayWriteMessage;
+ int m_movieInfoIndex;
+
+ bool m_bImmediatSatCom; // SatCom immediately?
+ bool m_bBeginSatCom; // messages SatCom poster?
+ bool m_bMovieLock; // movie in progress?
+ bool m_bSatComLock; // call of SatCom is possible?
+ bool m_bEditLock; // edition in progress?
+ bool m_bEditFull; // edition in full screen?
+ bool m_bPause; // simulation paused
+ bool m_bHilite;
+ bool m_bTrainerPilot; // remote trainer?
+ bool m_bSuspend;
+ bool m_bFriendAim;
+ bool m_bResetCreate;
+ bool m_bMapShow;
+ bool m_bMapImage;
+ char m_mapFilename[100];
+
+ Math::Point m_tooltipPos;
+ char m_tooltipName[100];
+ float m_tooltipTime;
+
+ char m_infoFilename[SATCOM_MAX][100]; // names of text files
+ CObject* m_infoObject;
+ int m_infoIndex;
+ int m_infoPos[SATCOM_MAX];
+ int m_infoUsed;
+
+ char m_title[100];
+ char m_resume[500];
+ char m_scriptName[100];
+ char m_scriptFile[100];
+ int m_endingWinRank;
+ int m_endingLostRank;
+ bool m_bWinTerminate;
+
+ float m_fontSize;
+ Math::Point m_windowPos;
+ Math::Point m_windowDim;
+
+ bool m_IOPublic;
+ Math::Point m_IOPos;
+ Math::Point m_IODim;
+
+ NewScriptName m_newScriptName[MAXNEWSCRIPTNAME];
+
+ float m_cameraPan;
+ float m_cameraZoom;
+
+ EventMsg m_visitLast;
+ CObject* m_visitObject;
+ CObject* m_visitArrow;
+ float m_visitTime;
+ float m_visitParticule;
+ Math::Vector m_visitPos;
+ Math::Vector m_visitPosArrow;
+
+ int m_endTakeTotal;
+ EndTake m_endTake[10];
+ long m_endTakeResearch;
+ float m_endTakeWinDelay;
+ float m_endTakeLostDelay;
+
+ int m_obligatoryTotal;
+ char m_obligatoryToken[100][20];
+ int m_prohibitedTotal;
+ char m_prohibitedToken[100][20];
+
+ char m_gamerName[100];
+
+ long m_freeBuild; // constructible buildings
+ long m_freeResearch; // researches possible
+
+ ShowLimit m_showLimit[MAXSHOWLIMIT];
+
+ D3DCOLORVALUE m_colorRefBot;
+ D3DCOLORVALUE m_colorNewBot;
+ D3DCOLORVALUE m_colorRefAlien;
+ D3DCOLORVALUE m_colorNewAlien;
+ D3DCOLORVALUE m_colorRefGreen;
+ D3DCOLORVALUE m_colorNewGreen;
+ D3DCOLORVALUE m_colorRefWater;
+ D3DCOLORVALUE m_colorNewWater;
+ float m_colorShiftWater;
+};
+
diff --git a/src/object/task/task.cpp b/src/object/task/task.cpp
index 593d4e6..f910ea2 100644
--- a/src/object/task/task.cpp
+++ b/src/object/task/task.cpp
@@ -1,89 +1,89 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// task.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/task.h"
-
-#include "common/iman.h"
-#include "object/object.h"
-
-
-
-// Object's constructor.
-
-CTask::CTask(CInstanceManager* iMan, CObject* object)
-{
- m_iMan = iMan;
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
-
- m_object = object;
- m_physics = m_object->RetPhysics();
- m_brain = m_object->RetBrain();
- m_motion = m_object->RetMotion();
-}
-
-// Object's destructor.
-
-CTask::~CTask()
-{
-}
-
-
-// Management of an event.
-
-bool CTask::EventProcess(const Event &event)
-{
- return true;
-}
-
-
-// Indicates whether the action is finished.
-
-Error CTask::IsEnded()
-{
- return ERR_STOP;
-}
-
-
-// Indicates whether the action is pending.
-
-bool CTask::IsBusy()
-{
- return true;
-}
-
-
-// Suddenly ends the current action.
-
-bool CTask::Abort()
-{
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// task.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/task.h"
+
+#include "common/iman.h"
+#include "object/object.h"
+
+
+
+// Object's constructor.
+
+CTask::CTask(CInstanceManager* iMan, CObject* object)
+{
+ m_iMan = iMan;
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+
+ m_object = object;
+ m_physics = m_object->RetPhysics();
+ m_brain = m_object->RetBrain();
+ m_motion = m_object->RetMotion();
+}
+
+// Object's destructor.
+
+CTask::~CTask()
+{
+}
+
+
+// Management of an event.
+
+bool CTask::EventProcess(const Event &event)
+{
+ return true;
+}
+
+
+// Indicates whether the action is finished.
+
+Error CTask::IsEnded()
+{
+ return ERR_STOP;
+}
+
+
+// Indicates whether the action is pending.
+
+bool CTask::IsBusy()
+{
+ return true;
+}
+
+
+// Suddenly ends the current action.
+
+bool CTask::Abort()
+{
+ return true;
+}
+
+
diff --git a/src/object/task/task.h b/src/object/task/task.h
index 8a1255e..a3ec62c 100644
--- a/src/object/task/task.h
+++ b/src/object/task/task.h
@@ -1,86 +1,86 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// task.h
-
-#pragma once
-
-
-#include "common/misc.h"
-#include "math/const.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CLight;
-class CParticule;
-class CTerrain;
-class CWater;
-class CCamera;
-class CBrain;
-class CPhysics;
-class CMotion;
-class CObject;
-class CRobotMain;
-class CDisplayText;
-class CSound;
-
-
-const float TAKE_DIST = 6.0f; // distance to an object to pick it
-const float TAKE_DIST_OTHER = 1.5f; // additional distance if on friend
-
-//?const float ARM_NEUTRAL_ANGLE1 = 155.0f*Math::PI/180.0f;
-//?const float ARM_NEUTRAL_ANGLE2 = -125.0f*Math::PI/180.0f;
-//?const float ARM_NEUTRAL_ANGLE3 = -45.0f*Math::PI/180.0f;
-const float ARM_NEUTRAL_ANGLE1 = 110.0f*Math::PI/180.0f;
-const float ARM_NEUTRAL_ANGLE2 = -130.0f*Math::PI/180.0f;
-const float ARM_NEUTRAL_ANGLE3 = -50.0f*Math::PI/180.0f;
-
-const float ARM_STOCK_ANGLE1 = 110.0f*Math::PI/180.0f;
-const float ARM_STOCK_ANGLE2 = -100.0f*Math::PI/180.0f;
-const float ARM_STOCK_ANGLE3 = -70.0f*Math::PI/180.0f;
-
-
-class CTask
-{
-public:
- CTask(CInstanceManager* iMan, CObject* object);
- virtual ~CTask();
-
- virtual bool EventProcess(const Event &event);
- virtual Error IsEnded();
- virtual bool IsBusy();
- virtual bool Abort();
-
-protected:
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CLight* m_light;
- CParticule* m_particule;
- CTerrain* m_terrain;
- CWater* m_water;
- CCamera* m_camera;
- CMotion* m_motion;
- CBrain* m_brain;
- CPhysics* m_physics;
- CObject* m_object;
- CRobotMain* m_main;
- CDisplayText* m_displayText;
- CSound* m_sound;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// task.h
+
+#pragma once
+
+
+#include "common/misc.h"
+#include "math/const.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CLight;
+class CParticule;
+class CTerrain;
+class CWater;
+class CCamera;
+class CBrain;
+class CPhysics;
+class CMotion;
+class CObject;
+class CRobotMain;
+class CDisplayText;
+class CSound;
+
+
+const float TAKE_DIST = 6.0f; // distance to an object to pick it
+const float TAKE_DIST_OTHER = 1.5f; // additional distance if on friend
+
+//?const float ARM_NEUTRAL_ANGLE1 = 155.0f*Math::PI/180.0f;
+//?const float ARM_NEUTRAL_ANGLE2 = -125.0f*Math::PI/180.0f;
+//?const float ARM_NEUTRAL_ANGLE3 = -45.0f*Math::PI/180.0f;
+const float ARM_NEUTRAL_ANGLE1 = 110.0f*Math::PI/180.0f;
+const float ARM_NEUTRAL_ANGLE2 = -130.0f*Math::PI/180.0f;
+const float ARM_NEUTRAL_ANGLE3 = -50.0f*Math::PI/180.0f;
+
+const float ARM_STOCK_ANGLE1 = 110.0f*Math::PI/180.0f;
+const float ARM_STOCK_ANGLE2 = -100.0f*Math::PI/180.0f;
+const float ARM_STOCK_ANGLE3 = -70.0f*Math::PI/180.0f;
+
+
+class CTask
+{
+public:
+ CTask(CInstanceManager* iMan, CObject* object);
+ virtual ~CTask();
+
+ virtual bool EventProcess(const Event &event);
+ virtual Error IsEnded();
+ virtual bool IsBusy();
+ virtual bool Abort();
+
+protected:
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CLight* m_light;
+ CParticule* m_particule;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CCamera* m_camera;
+ CMotion* m_motion;
+ CBrain* m_brain;
+ CPhysics* m_physics;
+ CObject* m_object;
+ CRobotMain* m_main;
+ CDisplayText* m_displayText;
+ CSound* m_sound;
+};
+
diff --git a/src/object/task/taskadvance.cpp b/src/object/task/taskadvance.cpp
index c5a87d3..e50cb08 100644
--- a/src/object/task/taskadvance.cpp
+++ b/src/object/task/taskadvance.cpp
@@ -1,146 +1,146 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskadvance.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskadvance.h"
-
-#include "math/geometry.h"
-#include "physics/physics.h"
-
-
-
-
-// Object's constructor.
-
-CTaskAdvance::CTaskAdvance(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskAdvance::~CTaskAdvance()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskAdvance::EventProcess(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_fixTime += event.rTime;
-
- // Momentarily stationary object (ant on the back)?
- if ( m_object->RetFixed() )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_bError = true;
- return true;
- }
-
- m_timeLimit -= event.rTime;
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskAdvance::Start(float length)
-{
- m_direction = (length>=0.0f)?1.0f:-1.0f;
- m_totalLength = fabs(length);
- m_advanceLength = m_physics->RetLinLength(length);
- m_startPos = m_object->RetPosition(0);
- m_lastDist = 0.0f;
- m_fixTime = 0.0f;
-
- m_timeLimit = m_physics->RetLinTimeLength(m_totalLength, m_direction)*3.0f;
- if ( m_timeLimit < 2.0f ) m_timeLimit = 2.0f;
-
- m_physics->SetMotorSpeedX(m_direction*1.0f); // forward/backward
- m_physics->SetMotorSpeedY(0.0f);
- m_physics->SetMotorSpeedZ(0.0f);
-
- m_bError = false;
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskAdvance::IsEnded()
-{
- Math::Vector pos;
- float length;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
-
- if ( m_bError )
- {
- return ERR_STOP;
- }
-
- if ( m_timeLimit < 0.0f )
- {
- m_physics->SetMotorSpeedX(0.0f);
- return ERR_MOVE_IMPOSSIBLE;
- }
-
- pos = m_object->RetPosition(0);
- length = Math::DistanceProjected(pos, m_startPos);
-
- if ( length > m_lastDist ) // forward?
- {
- m_fixTime = 0.0f;
- }
- else // still stands?
- {
- if ( m_fixTime > 1.0f ) // for more than a second?
- {
- m_physics->SetMotorSpeedX(0.0f);
- return ERR_MOVE_IMPOSSIBLE;
- }
- }
- m_lastDist = length;
-
- if ( length >= m_totalLength )
- {
- m_physics->SetMotorSpeedX(0.0f);
- m_physics->SetLinMotionX(MO_CURSPEED, 0.0f);
-
- if ( length != 0.0f )
- {
- pos = m_startPos+((pos-m_startPos)*m_totalLength/length);
- m_object->SetPosition(0, pos);
- }
- return ERR_STOP;
- }
-
- if ( length >= m_advanceLength )
- {
- m_physics->SetMotorSpeedX(m_direction*0.1f);
- }
- return ERR_CONTINUE;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskadvance.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskadvance.h"
+
+#include "math/geometry.h"
+#include "physics/physics.h"
+
+
+
+
+// Object's constructor.
+
+CTaskAdvance::CTaskAdvance(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+}
+
+// Object's destructor.
+
+CTaskAdvance::~CTaskAdvance()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskAdvance::EventProcess(const Event &event)
+{
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_fixTime += event.rTime;
+
+ // Momentarily stationary object (ant on the back)?
+ if ( m_object->RetFixed() )
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ m_bError = true;
+ return true;
+ }
+
+ m_timeLimit -= event.rTime;
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskAdvance::Start(float length)
+{
+ m_direction = (length>=0.0f)?1.0f:-1.0f;
+ m_totalLength = fabs(length);
+ m_advanceLength = m_physics->RetLinLength(length);
+ m_startPos = m_object->RetPosition(0);
+ m_lastDist = 0.0f;
+ m_fixTime = 0.0f;
+
+ m_timeLimit = m_physics->RetLinTimeLength(m_totalLength, m_direction)*3.0f;
+ if ( m_timeLimit < 2.0f ) m_timeLimit = 2.0f;
+
+ m_physics->SetMotorSpeedX(m_direction*1.0f); // forward/backward
+ m_physics->SetMotorSpeedY(0.0f);
+ m_physics->SetMotorSpeedZ(0.0f);
+
+ m_bError = false;
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskAdvance::IsEnded()
+{
+ Math::Vector pos;
+ float length;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+
+ if ( m_bError )
+ {
+ return ERR_STOP;
+ }
+
+ if ( m_timeLimit < 0.0f )
+ {
+ m_physics->SetMotorSpeedX(0.0f);
+ return ERR_MOVE_IMPOSSIBLE;
+ }
+
+ pos = m_object->RetPosition(0);
+ length = Math::DistanceProjected(pos, m_startPos);
+
+ if ( length > m_lastDist ) // forward?
+ {
+ m_fixTime = 0.0f;
+ }
+ else // still stands?
+ {
+ if ( m_fixTime > 1.0f ) // for more than a second?
+ {
+ m_physics->SetMotorSpeedX(0.0f);
+ return ERR_MOVE_IMPOSSIBLE;
+ }
+ }
+ m_lastDist = length;
+
+ if ( length >= m_totalLength )
+ {
+ m_physics->SetMotorSpeedX(0.0f);
+ m_physics->SetLinMotionX(MO_CURSPEED, 0.0f);
+
+ if ( length != 0.0f )
+ {
+ pos = m_startPos+((pos-m_startPos)*m_totalLength/length);
+ m_object->SetPosition(0, pos);
+ }
+ return ERR_STOP;
+ }
+
+ if ( length >= m_advanceLength )
+ {
+ m_physics->SetMotorSpeedX(m_direction*0.1f);
+ }
+ return ERR_CONTINUE;
+}
+
+
diff --git a/src/object/task/taskadvance.h b/src/object/task/taskadvance.h
index b0f09b1..dbb80d9 100644
--- a/src/object/task/taskadvance.h
+++ b/src/object/task/taskadvance.h
@@ -1,50 +1,50 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskadvance.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-class CTaskAdvance : public CTask
-{
-public:
- CTaskAdvance(CInstanceManager* iMan, CObject* object);
- ~CTaskAdvance();
-
- bool EventProcess(const Event &event);
-
- Error Start(float length);
- Error IsEnded();
-
-protected:
-
-protected:
- float m_totalLength;
- float m_advanceLength;
- float m_direction;
- float m_timeLimit;
- Math::Vector m_startPos;
- float m_lastDist;
- float m_fixTime;
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskadvance.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "math/vector.h"
+
+
+
+class CTaskAdvance : public CTask
+{
+public:
+ CTaskAdvance(CInstanceManager* iMan, CObject* object);
+ ~CTaskAdvance();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(float length);
+ Error IsEnded();
+
+protected:
+
+protected:
+ float m_totalLength;
+ float m_advanceLength;
+ float m_direction;
+ float m_timeLimit;
+ Math::Vector m_startPos;
+ float m_lastDist;
+ float m_fixTime;
+ bool m_bError;
+};
+
diff --git a/src/object/task/taskbuild.cpp b/src/object/task/taskbuild.cpp
index f9d6c57..25936f9 100644
--- a/src/object/task/taskbuild.cpp
+++ b/src/object/task/taskbuild.cpp
@@ -1,806 +1,806 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskbuild.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskbuild.h"
-
-#include "common/iman.h"
-#include "old/light.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "math/geometry.h"
-#include "object/auto/auto.h"
-#include "object/motion/motionhuman.h"
-#include "object/robotmain.h"
-#include "physics/physics.h"
-#include "ui/displaytext.h"
-
-
-
-
-// Object's constructor.
-
-CTaskBuild::CTaskBuild(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- int i;
-
- m_type = OBJECT_DERRICK;
- m_time = 0.0f;
- m_soundChannel = -1;
-
- for ( i=0 ; i<TBMAXLIGHT ; i++ )
- {
- m_lightRank[i] = -1;
- }
-}
-
-// Object's destructor.
-
-CTaskBuild::~CTaskBuild()
-{
- int i;
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- for ( i=0 ; i<TBMAXLIGHT ; i++ )
- {
- if ( m_lightRank[i] == -1 ) continue;
- m_light->DeleteLight(m_lightRank[i]);
- }
-}
-
-
-// Creates a building.
-
-bool CTaskBuild::CreateBuilding(Math::Vector pos, float angle)
-{
- m_building = new CObject(m_iMan);
- if ( !m_building->CreateBuilding(pos, angle, 0.0f, m_type, 0.0f) )
- {
- delete m_building;
- m_building = 0;
- return false;
- }
- m_building->UpdateMapping();
- m_building->SetLock(true); // not yet usable
-
- if ( m_type == OBJECT_DERRICK ) m_buildingHeight = 35.0f;
- if ( m_type == OBJECT_FACTORY ) m_buildingHeight = 28.0f;
- if ( m_type == OBJECT_REPAIR ) m_buildingHeight = 30.0f;
- if ( m_type == OBJECT_STATION ) m_buildingHeight = 13.0f;
- if ( m_type == OBJECT_CONVERT ) m_buildingHeight = 20.0f;
- if ( m_type == OBJECT_TOWER ) m_buildingHeight = 30.0f;
- if ( m_type == OBJECT_RESEARCH ) m_buildingHeight = 22.0f;
- if ( m_type == OBJECT_RADAR ) m_buildingHeight = 19.0f;
- if ( m_type == OBJECT_ENERGY ) m_buildingHeight = 20.0f;
- if ( m_type == OBJECT_LABO ) m_buildingHeight = 16.0f;
- if ( m_type == OBJECT_NUCLEAR ) m_buildingHeight = 40.0f;
- if ( m_type == OBJECT_PARA ) m_buildingHeight = 68.0f;
- if ( m_type == OBJECT_INFO ) m_buildingHeight = 19.0f;
- m_buildingHeight *= 0.25f;
-
- m_buildingPos = m_building->RetPosition(0);
- m_buildingPos.y -= m_buildingHeight;
- m_building->SetPosition(0, m_buildingPos);
- return true;
-}
-
-// Creates lights for the effects.
-
-void CTaskBuild::CreateLight()
-{
- D3DLIGHT7 light;
- D3DCOLORVALUE color;
- Math::Vector center, pos, dir;
- Math::Point c, p;
- float angle;
- int i;
-
- if ( !m_engine->RetLightMode() ) return;
-
- center = m_metal->RetPosition(0);
-
- angle = 0;
- for ( i=0 ; i<TBMAXLIGHT ; i++ )
- {
- m_lightRank[i] = m_light->CreateLight();
- if ( m_lightRank[i] == -1 ) continue;
-
- c.x = center.x;
- c.y = center.z;
- p.x = center.x+40.0f;
- p.y = center.z;
- p = Math::RotatePoint(c, angle, p);
- pos.x = p.x;
- pos.z = p.y;
- pos.y = center.y+40.0f;
- dir = center-pos;
-
- ZeroMemory( &light, sizeof(light) );
- light.dltType = D3DLIGHT_SPOT;
- light.dcvDiffuse.r = 0.0f;
- light.dcvDiffuse.g = 0.0f;
- light.dcvDiffuse.b = 0.0f; // white (invisible)
- light.dvPosition.x = pos.x;
- light.dvPosition.y = pos.y;
- light.dvPosition.z = pos.z;
- light.dvDirection.x = dir.x;
- light.dvDirection.y = dir.y;
- light.dvDirection.z = dir.z;
- light.dvRange = D3DLIGHT_RANGE_MAX;
- light.dvFalloff = 1.0f;
- light.dvAttenuation0 = 1.0f;
- light.dvAttenuation1 = 0.0f;
- light.dvAttenuation2 = 0.0f;
- light.dvTheta = 0.0f;
- light.dvPhi = Math::PI/4.0f;
- m_light->SetLight(m_lightRank[i], light);
-
- color.r = -1.0f;
- color.g = -1.0f;
- color.b = -0.5f; // violet
- color.a = 0.0f;
- m_light->SetLightColor(m_lightRank[i], color);
- m_light->SetLightColorSpeed(m_lightRank[i], 1.0f/((1.0f/m_speed)*0.25f));
-
- angle += (Math::PI*2.0f)/TBMAXLIGHT;
- }
-
- m_bBlack = false;
-}
-
-// Switches the lights from black to white.
-
-void CTaskBuild::BlackLight()
-{
- D3DCOLORVALUE color;
- int i;
-
- for ( i=0 ; i<TBMAXLIGHT ; i++ )
- {
- if ( m_lightRank[i] == -1 ) continue;
-
- color.r = 0.0f;
- color.g = 0.0f;
- color.b = 0.0f; // white (invisible)
- color.a = 0.0f;
- m_light->SetLightColor(m_lightRank[i], color);
- m_light->SetLightColorSpeed(m_lightRank[i], 1.0f/((1.0f/m_speed)*0.75f));
- }
-
- m_bBlack = true;
-}
-
-// Management of an event.
-
-bool CTaskBuild::EventProcess(const Event &event)
-{
- Math::Matrix* mat;
- Math::Vector pos, dir, speed;
- Math::Point dim;
- float a, g, cirSpeed, dist, linSpeed;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_time += event.rTime;
-
- m_progress += event.rTime*m_speed; // other advance
-
- if ( m_phase == TBP_TURN ) // preliminary rotation?
- {
- a = m_object->RetAngleY(0);
- g = m_angleY;
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left/right
- return true;
- }
-
- if ( m_phase == TBP_MOVE ) // preliminary forward/backward?
- {
- dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0));
- linSpeed = 0.0f;
- if ( dist > 30.0f ) linSpeed = 1.0f;
- if ( dist < 30.0f ) linSpeed = -1.0f;
- m_physics->SetMotorSpeedX(linSpeed); // forward/backward
- return true;
- }
-
- if ( m_phase == TBP_RECEDE ) // terminal back?
- {
- m_physics->SetMotorSpeedX(-1.0f); // back
- return true;
- }
-
- if ( m_phase == TBP_TAKE ) // takes gun?
- {
- return true;
- }
-
- if ( m_phase == TBP_PREP ) // prepares?
- {
- return true;
- }
-
- if ( m_phase == TBP_TERM ) // ends?
- {
- return true;
- }
-
- if ( !m_bBuild ) // building to build?
- {
- m_bBuild = true;
-
- pos = m_metal->RetPosition(0);
- a = m_object->RetAngleY(0);
- if ( !CreateBuilding(pos, a+Math::PI) )
- {
- m_metal->SetLock(false); // usable again
- m_motion->SetAction(-1);
- m_object->SetObjectParent(14, 0);
- m_object->SetPosition(14, Math::Vector(-1.5f, 0.3f, -1.35f));
- m_object->SetAngleZ(14, Math::PI);
- m_camera->FlushEffect();
- Abort();
- m_bError = true;
- m_displayText->DisplayError(ERR_TOOMANY, m_object->RetPosition(0));
- return false;
- }
- CreateLight();
- }
-
- pos = m_buildingPos;
- pos.y += m_buildingHeight*m_progress;
- m_building->SetPosition(0, pos); // the building rises
-
- m_building->SetZoom(0, m_progress*0.75f+0.25f);
- m_metal->SetZoom(0, 1.0f-m_progress);
-
- a = (2.0f-2.0f*m_progress);
- if ( a > 1.0f ) a = 1.0f;
- dir.x = (Math::Rand()-0.5f)*a*0.1f;
- dir.z = (Math::Rand()-0.5f)*a*0.1f;
- dir.y = (Math::Rand()-0.5f)*a*0.1f;
- m_building->SetCirVibration(dir);
-
- if ( !m_bBlack && m_progress >= 0.25f )
- {
- BlackLight();
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_metal->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = Math::Rand()*10.0f;
- dim.x = Math::Rand()*6.0f+4.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFIRE);
-
- pos = Math::Vector(0.0f, 0.5f, 0.0f);
- mat = m_object->RetWorldMatrix(14);
- pos = Transform(*mat, pos);
- speed = m_metal->RetPosition(0);
- speed.x += (Math::Rand()-0.5f)*5.0f;
- speed.z += (Math::Rand()-0.5f)*5.0f;
- speed -= pos;
- dim.x = 2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ);
-
- if ( Math::Rand() < 0.3f )
- {
- m_sound->Play(SOUND_BUILD, m_object->RetPosition(0), 0.5f, 1.0f*Math::Rand()*1.5f);
- }
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskBuild::Start(ObjectType type)
-{
- Math::Vector pos, speed, pv, pm;
- Error err;
- float iAngle, oAngle;
-
- m_type = type;
- m_lastParticule = 0.0f;
- m_progress = 0.0f;
-
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
- oAngle = iAngle;
-
- m_bError = true; // operation impossible
-
- pos = m_object->RetPosition(0);
- if ( pos.y < m_water->RetLevel() ) return ERR_BUILD_WATER;
-
- if ( !m_physics->RetLand() ) return ERR_BUILD_FLY;
-
- speed = m_physics->RetMotorSpeed();
- if ( speed.x != 0.0f ||
- speed.z != 0.0f ) return ERR_BUILD_MOTOR;
-
- if ( m_object->RetFret() != 0 ) return ERR_MANIP_BUSY;
-
- m_metal = SearchMetalObject(oAngle, 2.0f, 100.0f, Math::PI*0.25f, err);
- if ( err == ERR_BUILD_METALNEAR && m_metal != 0 )
- {
- err = FlatFloor();
- if ( err != ERR_OK ) return err;
- return ERR_BUILD_METALNEAR;
- }
- if ( err != ERR_OK ) return err;
-
- err = FlatFloor();
- if ( err != ERR_OK ) return err;
-
- m_metal->SetLock(true); // not usable
- m_camera->StartCentering(m_object, Math::PI*0.15f, 99.9f, 0.0f, 1.0f);
-
- m_phase = TBP_TURN; // rotation necessary preliminary
- m_angleY = oAngle; // angle was reached
-
- pv = m_object->RetPosition(0);
- pv.y += 8.3f;
- pm = m_metal->RetPosition(0);
- m_angleZ = Math::RotateAngle(Math::DistanceProjected(pv, pm), fabs(pv.y-pm.y));
-
- m_physics->SetFreeze(true); // it does not move
-
- m_bBuild = false; // not yet built
- m_bError = false; // ok
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskBuild::IsEnded()
-{
- CAuto* automat;
- float angle, dist, time;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_phase == TBP_TURN ) // preliminary rotation?
- {
- angle = m_object->RetAngleY(0);
- angle = Math::NormAngle(angle); // 0..2*Math::PI
-
- if ( Math::TestAngle(angle, m_angleY-Math::PI*0.01f, m_angleY+Math::PI*0.01f) )
- {
- m_physics->SetMotorSpeedZ(0.0f);
-
- dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0));
- if ( dist > 30.0f )
- {
- time = m_physics->RetLinTimeLength(dist-30.0f, 1.0f);
- m_speed = 1.0f/time;
- }
- else
- {
- time = m_physics->RetLinTimeLength(30.0f-dist, -1.0f);
- m_speed = 1.0f/time;
- }
- m_phase = TBP_MOVE;
- m_progress = 0.0f;
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TBP_MOVE ) // preliminary forward/backward?
- {
- dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0));
-
- if ( dist >= 25.0f && dist <= 35.0f )
- {
- m_physics->SetMotorSpeedX(0.0f);
- m_motion->SetAction(MHS_GUN); // takes gun
-
- m_phase = TBP_TAKE;
- m_speed = 1.0f/1.0f;
- m_progress = 0.0f;
- }
- else
- {
- if ( m_progress > 1.0f ) // timeout?
- {
- m_metal->SetLock(false); // usable again
- if ( dist < 30.0f ) return ERR_BUILD_METALNEAR;
- else return ERR_BUILD_METALAWAY;
- }
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TBP_TAKE ) // takes gun
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_motion->SetAction(MHS_FIRE); // shooting position
- m_object->SetObjectParent(14, 4);
- m_object->SetPosition(14, Math::Vector(0.6f, 0.1f, 0.3f));
- m_object->SetAngleZ(14, 0.0f);
-
- m_phase = TBP_PREP;
- m_speed = 1.0f/1.0f;
- m_progress = 0.0f;
- }
-
- if ( m_phase == TBP_PREP ) // prepares?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_soundChannel = m_sound->Play(SOUND_TREMBLE, m_object->RetPosition(0), 0.0f, 1.0f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.7f, 1.0f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.7f, 1.5f, 7.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.5f, 2.0f, SOPER_STOP);
-
- m_camera->StartEffect(CE_VIBRATION, m_metal->RetPosition(0), 1.0f);
-
- m_phase = TBP_BUILD;
- m_speed = 1.0f/10.f; // duration of 10s
- m_progress = 0.0f;
- }
-
- if ( m_phase == TBP_BUILD ) // construction?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- DeleteMark(m_metal->RetPosition(0), 20.0f);
-
- m_metal->DeleteObject(); // removes the metal
- delete m_metal;
- m_metal = 0;
-
- m_building->SetZoom(0, 1.0f);
- m_building->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- m_building->SetLock(false); // building usable
- m_main->CreateShortcuts();
- m_displayText->DisplayError(INFO_BUILD, m_buildingPos, 10.0f, 50.0f);
-
- automat = m_building->RetAuto();
- if ( automat != 0 )
- {
- automat->Init();
- }
-
- m_motion->SetAction(MHS_GUN); // hands gun
- m_phase = TBP_TERM;
- m_speed = 1.0f/1.0f;
- m_progress = 0.0f;
- }
-
- if ( m_phase == TBP_TERM ) // rotation terminale ?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_motion->SetAction(-1);
- m_object->SetObjectParent(14, 0);
- m_object->SetPosition(14, Math::Vector(-1.5f, 0.3f, -1.35f));
- m_object->SetAngleZ(14, Math::PI);
-
- if ( m_type == OBJECT_FACTORY ||
- m_type == OBJECT_RESEARCH ||
- m_type == OBJECT_NUCLEAR )
- {
-
- m_phase = TBP_RECEDE;
- m_speed = 1.0f/1.5f;
- m_progress = 0.0f;
- }
- }
-
- if ( m_phase == TBP_RECEDE ) // back?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_physics->SetMotorSpeedX(0.0f);
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskBuild::Abort()
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- m_camera->StopCentering(m_object, 2.0f);
- m_physics->SetFreeze(false); // is moving again
- return true;
-}
-
-
-// Checks whether the terrain is fairly flat
-// and if there is not too close to another object.
-
-Error CTaskBuild::FlatFloor()
-{
- CObject *pObj;
- ObjectType type;
- Math::Vector center, pos, oPos, bPos;
- Math::Point c, p;
- float radius, max, oRadius, bRadius, angle, dist;
- int i, j;
- bool bLittleFlat, bBase;
-
- radius = 0.0f;
- if ( m_type == OBJECT_DERRICK ) radius = 5.0f;
- if ( m_type == OBJECT_FACTORY ) radius = 15.0f;
- if ( m_type == OBJECT_REPAIR ) radius = 12.0f;
- if ( m_type == OBJECT_STATION ) radius = 12.0f;
- if ( m_type == OBJECT_CONVERT ) radius = 12.0f;
- if ( m_type == OBJECT_TOWER ) radius = 7.0f;
- if ( m_type == OBJECT_RESEARCH ) radius = 10.0f;
- if ( m_type == OBJECT_RADAR ) radius = 5.0f;
- if ( m_type == OBJECT_ENERGY ) radius = 8.0f;
- if ( m_type == OBJECT_LABO ) radius = 12.0f;
- if ( m_type == OBJECT_NUCLEAR ) radius = 20.0f;
- if ( m_type == OBJECT_PARA ) radius = 20.0f;
- if ( m_type == OBJECT_INFO ) radius = 5.0f;
- if ( radius == 0.0f ) return ERR_GENERIC;
-
- center = m_metal->RetPosition(0);
- angle = m_terrain->RetFineSlope(center);
- bLittleFlat = ( angle < FLATLIMIT );
-
- max = m_terrain->RetFlatZoneRadius(center, radius);
- if ( max < radius ) // area too small?
- {
- if ( bLittleFlat )
- {
- m_main->SetShowLimit(1, PARTILIMIT3, m_metal, center, max, 10.0f);
- }
- return bLittleFlat?ERR_BUILD_FLATLIT:ERR_BUILD_FLAT;
- }
-
- max = 100000.0f;
- bBase = false;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj == m_metal ) continue;
- if ( pObj == m_object ) continue;
-
- type = pObj->RetType();
- if ( type == OBJECT_BASE )
- {
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(center, oPos)-80.0f;
- if ( dist < max )
- {
- max = dist;
- bPos = oPos;
- bRadius = oRadius;
- bBase = true;
- }
- }
- else
- {
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- dist = Math::Distance(center, oPos)-oRadius;
- if ( dist < max )
- {
- max = dist;
- bPos = oPos;
- bRadius = oRadius;
- bBase = false;
- }
- }
- }
- }
- if ( max < radius )
- {
- m_main->SetShowLimit(1, PARTILIMIT2, m_metal, center, max, 10.0f);
- if ( bRadius < 2.0f ) bRadius = 2.0f;
- m_main->SetShowLimit(2, PARTILIMIT3, m_metal, bPos, bRadius, 10.0f);
- return bBase?ERR_BUILD_BASE:ERR_BUILD_BUSY;
- }
-
- max = 100000.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj == m_metal ) continue;
- if ( pObj == m_object ) continue;
-
- type = pObj->RetType();
- if ( type == OBJECT_DERRICK ||
- type == OBJECT_FACTORY ||
- type == OBJECT_STATION ||
- type == OBJECT_CONVERT ||
- type == OBJECT_REPAIR ||
- type == OBJECT_TOWER ||
- type == OBJECT_RESEARCH ||
- type == OBJECT_RADAR ||
- type == OBJECT_ENERGY ||
- type == OBJECT_LABO ||
- type == OBJECT_NUCLEAR ||
- type == OBJECT_START ||
- type == OBJECT_END ||
- type == OBJECT_INFO ||
- type == OBJECT_PARA ||
- type == OBJECT_SAFE ||
- type == OBJECT_HUSTON ) // building?
- {
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- dist = Math::Distance(center, oPos)-oRadius;
- if ( dist < max )
- {
- max = dist;
- bPos = oPos;
- bRadius = oRadius;
- }
- }
- }
- }
- if ( max-BUILDMARGIN < radius )
- {
- m_main->SetShowLimit(1, PARTILIMIT2, m_metal, center, max-BUILDMARGIN, 10.0f);
- m_main->SetShowLimit(2, PARTILIMIT3, m_metal, bPos, bRadius+BUILDMARGIN, 10.0f);
- return bBase?ERR_BUILD_BASE:ERR_BUILD_NARROW;
- }
-
- return ERR_OK;
-}
-
-// Seeks the nearest metal object.
-
-CObject* CTaskBuild::SearchMetalObject(float &angle, float dMin, float dMax,
- float aLimit, Error &err)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float min, iAngle, a, aa, aBest, distance, magic;
- int i;
- bool bMetal;
-
- iPos = m_object->RetPosition(0);
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- min = 1000000.0f;
- pBest = 0;
- bMetal = false;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // objet inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- type = pObj->RetType();
- if ( type != OBJECT_METAL ) continue;
-
- bMetal = true; // metal exists
-
- oPos = pObj->RetPosition(0);
- distance = Math::Distance(oPos, iPos);
- a = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW!
-
- if ( distance > dMax ) continue;
- if ( !Math::TestAngle(a, iAngle-aLimit, iAngle+aLimit) ) continue;
-
- if ( distance < dMin )
- {
- err = ERR_BUILD_METALNEAR; // too close
- return pObj;
- }
-
- aa = fabs(a-iAngle);
- if ( aa > Math::PI ) aa = Math::PI*2.0f-aa;
- magic = distance*aa;
-
- if ( magic < min )
- {
- min = magic;
- aBest = a;
- pBest = pObj;
- }
- }
-
- if ( pBest == 0 )
- {
- if ( bMetal ) err = ERR_BUILD_METALAWAY; // too far
- else err = ERR_BUILD_METALINEX; // non-existent
- }
- else
- {
- angle = aBest;
- err = ERR_OK;
- }
- return pBest;
-}
-
-// Destroys all the close marks.
-
-void CTaskBuild::DeleteMark(Math::Vector pos, float radius)
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- float distance;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_MARKSTONE &&
- type != OBJECT_MARKURANIUM &&
- type != OBJECT_MARKKEYa &&
- type != OBJECT_MARKKEYb &&
- type != OBJECT_MARKKEYc &&
- type != OBJECT_MARKKEYd &&
- type != OBJECT_MARKPOWER ) continue;
-
- oPos = pObj->RetPosition(0);
- distance = Math::Distance(oPos, pos);
- if ( distance <= radius )
- {
- pObj->DeleteObject(); // removes the mark
- delete pObj;
- i --;
- }
- }
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskbuild.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskbuild.h"
+
+#include "common/iman.h"
+#include "old/light.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "math/geometry.h"
+#include "object/auto/auto.h"
+#include "object/motion/motionhuman.h"
+#include "object/robotmain.h"
+#include "physics/physics.h"
+#include "ui/displaytext.h"
+
+
+
+
+// Object's constructor.
+
+CTaskBuild::CTaskBuild(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ int i;
+
+ m_type = OBJECT_DERRICK;
+ m_time = 0.0f;
+ m_soundChannel = -1;
+
+ for ( i=0 ; i<TBMAXLIGHT ; i++ )
+ {
+ m_lightRank[i] = -1;
+ }
+}
+
+// Object's destructor.
+
+CTaskBuild::~CTaskBuild()
+{
+ int i;
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ for ( i=0 ; i<TBMAXLIGHT ; i++ )
+ {
+ if ( m_lightRank[i] == -1 ) continue;
+ m_light->DeleteLight(m_lightRank[i]);
+ }
+}
+
+
+// Creates a building.
+
+bool CTaskBuild::CreateBuilding(Math::Vector pos, float angle)
+{
+ m_building = new CObject(m_iMan);
+ if ( !m_building->CreateBuilding(pos, angle, 0.0f, m_type, 0.0f) )
+ {
+ delete m_building;
+ m_building = 0;
+ return false;
+ }
+ m_building->UpdateMapping();
+ m_building->SetLock(true); // not yet usable
+
+ if ( m_type == OBJECT_DERRICK ) m_buildingHeight = 35.0f;
+ if ( m_type == OBJECT_FACTORY ) m_buildingHeight = 28.0f;
+ if ( m_type == OBJECT_REPAIR ) m_buildingHeight = 30.0f;
+ if ( m_type == OBJECT_STATION ) m_buildingHeight = 13.0f;
+ if ( m_type == OBJECT_CONVERT ) m_buildingHeight = 20.0f;
+ if ( m_type == OBJECT_TOWER ) m_buildingHeight = 30.0f;
+ if ( m_type == OBJECT_RESEARCH ) m_buildingHeight = 22.0f;
+ if ( m_type == OBJECT_RADAR ) m_buildingHeight = 19.0f;
+ if ( m_type == OBJECT_ENERGY ) m_buildingHeight = 20.0f;
+ if ( m_type == OBJECT_LABO ) m_buildingHeight = 16.0f;
+ if ( m_type == OBJECT_NUCLEAR ) m_buildingHeight = 40.0f;
+ if ( m_type == OBJECT_PARA ) m_buildingHeight = 68.0f;
+ if ( m_type == OBJECT_INFO ) m_buildingHeight = 19.0f;
+ m_buildingHeight *= 0.25f;
+
+ m_buildingPos = m_building->RetPosition(0);
+ m_buildingPos.y -= m_buildingHeight;
+ m_building->SetPosition(0, m_buildingPos);
+ return true;
+}
+
+// Creates lights for the effects.
+
+void CTaskBuild::CreateLight()
+{
+ D3DLIGHT7 light;
+ D3DCOLORVALUE color;
+ Math::Vector center, pos, dir;
+ Math::Point c, p;
+ float angle;
+ int i;
+
+ if ( !m_engine->RetLightMode() ) return;
+
+ center = m_metal->RetPosition(0);
+
+ angle = 0;
+ for ( i=0 ; i<TBMAXLIGHT ; i++ )
+ {
+ m_lightRank[i] = m_light->CreateLight();
+ if ( m_lightRank[i] == -1 ) continue;
+
+ c.x = center.x;
+ c.y = center.z;
+ p.x = center.x+40.0f;
+ p.y = center.z;
+ p = Math::RotatePoint(c, angle, p);
+ pos.x = p.x;
+ pos.z = p.y;
+ pos.y = center.y+40.0f;
+ dir = center-pos;
+
+ ZeroMemory( &light, sizeof(light) );
+ light.dltType = D3DLIGHT_SPOT;
+ light.dcvDiffuse.r = 0.0f;
+ light.dcvDiffuse.g = 0.0f;
+ light.dcvDiffuse.b = 0.0f; // white (invisible)
+ light.dvPosition.x = pos.x;
+ light.dvPosition.y = pos.y;
+ light.dvPosition.z = pos.z;
+ light.dvDirection.x = dir.x;
+ light.dvDirection.y = dir.y;
+ light.dvDirection.z = dir.z;
+ light.dvRange = D3DLIGHT_RANGE_MAX;
+ light.dvFalloff = 1.0f;
+ light.dvAttenuation0 = 1.0f;
+ light.dvAttenuation1 = 0.0f;
+ light.dvAttenuation2 = 0.0f;
+ light.dvTheta = 0.0f;
+ light.dvPhi = Math::PI/4.0f;
+ m_light->SetLight(m_lightRank[i], light);
+
+ color.r = -1.0f;
+ color.g = -1.0f;
+ color.b = -0.5f; // violet
+ color.a = 0.0f;
+ m_light->SetLightColor(m_lightRank[i], color);
+ m_light->SetLightColorSpeed(m_lightRank[i], 1.0f/((1.0f/m_speed)*0.25f));
+
+ angle += (Math::PI*2.0f)/TBMAXLIGHT;
+ }
+
+ m_bBlack = false;
+}
+
+// Switches the lights from black to white.
+
+void CTaskBuild::BlackLight()
+{
+ D3DCOLORVALUE color;
+ int i;
+
+ for ( i=0 ; i<TBMAXLIGHT ; i++ )
+ {
+ if ( m_lightRank[i] == -1 ) continue;
+
+ color.r = 0.0f;
+ color.g = 0.0f;
+ color.b = 0.0f; // white (invisible)
+ color.a = 0.0f;
+ m_light->SetLightColor(m_lightRank[i], color);
+ m_light->SetLightColorSpeed(m_lightRank[i], 1.0f/((1.0f/m_speed)*0.75f));
+ }
+
+ m_bBlack = true;
+}
+
+// Management of an event.
+
+bool CTaskBuild::EventProcess(const Event &event)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, dir, speed;
+ Math::Point dim;
+ float a, g, cirSpeed, dist, linSpeed;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ m_time += event.rTime;
+
+ m_progress += event.rTime*m_speed; // other advance
+
+ if ( m_phase == TBP_TURN ) // preliminary rotation?
+ {
+ a = m_object->RetAngleY(0);
+ g = m_angleY;
+ cirSpeed = Math::Direction(a, g)*1.0f;
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left/right
+ return true;
+ }
+
+ if ( m_phase == TBP_MOVE ) // preliminary forward/backward?
+ {
+ dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0));
+ linSpeed = 0.0f;
+ if ( dist > 30.0f ) linSpeed = 1.0f;
+ if ( dist < 30.0f ) linSpeed = -1.0f;
+ m_physics->SetMotorSpeedX(linSpeed); // forward/backward
+ return true;
+ }
+
+ if ( m_phase == TBP_RECEDE ) // terminal back?
+ {
+ m_physics->SetMotorSpeedX(-1.0f); // back
+ return true;
+ }
+
+ if ( m_phase == TBP_TAKE ) // takes gun?
+ {
+ return true;
+ }
+
+ if ( m_phase == TBP_PREP ) // prepares?
+ {
+ return true;
+ }
+
+ if ( m_phase == TBP_TERM ) // ends?
+ {
+ return true;
+ }
+
+ if ( !m_bBuild ) // building to build?
+ {
+ m_bBuild = true;
+
+ pos = m_metal->RetPosition(0);
+ a = m_object->RetAngleY(0);
+ if ( !CreateBuilding(pos, a+Math::PI) )
+ {
+ m_metal->SetLock(false); // usable again
+ m_motion->SetAction(-1);
+ m_object->SetObjectParent(14, 0);
+ m_object->SetPosition(14, Math::Vector(-1.5f, 0.3f, -1.35f));
+ m_object->SetAngleZ(14, Math::PI);
+ m_camera->FlushEffect();
+ Abort();
+ m_bError = true;
+ m_displayText->DisplayError(ERR_TOOMANY, m_object->RetPosition(0));
+ return false;
+ }
+ CreateLight();
+ }
+
+ pos = m_buildingPos;
+ pos.y += m_buildingHeight*m_progress;
+ m_building->SetPosition(0, pos); // the building rises
+
+ m_building->SetZoom(0, m_progress*0.75f+0.25f);
+ m_metal->SetZoom(0, 1.0f-m_progress);
+
+ a = (2.0f-2.0f*m_progress);
+ if ( a > 1.0f ) a = 1.0f;
+ dir.x = (Math::Rand()-0.5f)*a*0.1f;
+ dir.z = (Math::Rand()-0.5f)*a*0.1f;
+ dir.y = (Math::Rand()-0.5f)*a*0.1f;
+ m_building->SetCirVibration(dir);
+
+ if ( !m_bBlack && m_progress >= 0.25f )
+ {
+ BlackLight();
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_metal->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ speed.y = Math::Rand()*10.0f;
+ dim.x = Math::Rand()*6.0f+4.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFIRE);
+
+ pos = Math::Vector(0.0f, 0.5f, 0.0f);
+ mat = m_object->RetWorldMatrix(14);
+ pos = Transform(*mat, pos);
+ speed = m_metal->RetPosition(0);
+ speed.x += (Math::Rand()-0.5f)*5.0f;
+ speed.z += (Math::Rand()-0.5f)*5.0f;
+ speed -= pos;
+ dim.x = 2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ);
+
+ if ( Math::Rand() < 0.3f )
+ {
+ m_sound->Play(SOUND_BUILD, m_object->RetPosition(0), 0.5f, 1.0f*Math::Rand()*1.5f);
+ }
+ }
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskBuild::Start(ObjectType type)
+{
+ Math::Vector pos, speed, pv, pm;
+ Error err;
+ float iAngle, oAngle;
+
+ m_type = type;
+ m_lastParticule = 0.0f;
+ m_progress = 0.0f;
+
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+ oAngle = iAngle;
+
+ m_bError = true; // operation impossible
+
+ pos = m_object->RetPosition(0);
+ if ( pos.y < m_water->RetLevel() ) return ERR_BUILD_WATER;
+
+ if ( !m_physics->RetLand() ) return ERR_BUILD_FLY;
+
+ speed = m_physics->RetMotorSpeed();
+ if ( speed.x != 0.0f ||
+ speed.z != 0.0f ) return ERR_BUILD_MOTOR;
+
+ if ( m_object->RetFret() != 0 ) return ERR_MANIP_BUSY;
+
+ m_metal = SearchMetalObject(oAngle, 2.0f, 100.0f, Math::PI*0.25f, err);
+ if ( err == ERR_BUILD_METALNEAR && m_metal != 0 )
+ {
+ err = FlatFloor();
+ if ( err != ERR_OK ) return err;
+ return ERR_BUILD_METALNEAR;
+ }
+ if ( err != ERR_OK ) return err;
+
+ err = FlatFloor();
+ if ( err != ERR_OK ) return err;
+
+ m_metal->SetLock(true); // not usable
+ m_camera->StartCentering(m_object, Math::PI*0.15f, 99.9f, 0.0f, 1.0f);
+
+ m_phase = TBP_TURN; // rotation necessary preliminary
+ m_angleY = oAngle; // angle was reached
+
+ pv = m_object->RetPosition(0);
+ pv.y += 8.3f;
+ pm = m_metal->RetPosition(0);
+ m_angleZ = Math::RotateAngle(Math::DistanceProjected(pv, pm), fabs(pv.y-pm.y));
+
+ m_physics->SetFreeze(true); // it does not move
+
+ m_bBuild = false; // not yet built
+ m_bError = false; // ok
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskBuild::IsEnded()
+{
+ CAuto* automat;
+ float angle, dist, time;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_phase == TBP_TURN ) // preliminary rotation?
+ {
+ angle = m_object->RetAngleY(0);
+ angle = Math::NormAngle(angle); // 0..2*Math::PI
+
+ if ( Math::TestAngle(angle, m_angleY-Math::PI*0.01f, m_angleY+Math::PI*0.01f) )
+ {
+ m_physics->SetMotorSpeedZ(0.0f);
+
+ dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0));
+ if ( dist > 30.0f )
+ {
+ time = m_physics->RetLinTimeLength(dist-30.0f, 1.0f);
+ m_speed = 1.0f/time;
+ }
+ else
+ {
+ time = m_physics->RetLinTimeLength(30.0f-dist, -1.0f);
+ m_speed = 1.0f/time;
+ }
+ m_phase = TBP_MOVE;
+ m_progress = 0.0f;
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TBP_MOVE ) // preliminary forward/backward?
+ {
+ dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0));
+
+ if ( dist >= 25.0f && dist <= 35.0f )
+ {
+ m_physics->SetMotorSpeedX(0.0f);
+ m_motion->SetAction(MHS_GUN); // takes gun
+
+ m_phase = TBP_TAKE;
+ m_speed = 1.0f/1.0f;
+ m_progress = 0.0f;
+ }
+ else
+ {
+ if ( m_progress > 1.0f ) // timeout?
+ {
+ m_metal->SetLock(false); // usable again
+ if ( dist < 30.0f ) return ERR_BUILD_METALNEAR;
+ else return ERR_BUILD_METALAWAY;
+ }
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TBP_TAKE ) // takes gun
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_motion->SetAction(MHS_FIRE); // shooting position
+ m_object->SetObjectParent(14, 4);
+ m_object->SetPosition(14, Math::Vector(0.6f, 0.1f, 0.3f));
+ m_object->SetAngleZ(14, 0.0f);
+
+ m_phase = TBP_PREP;
+ m_speed = 1.0f/1.0f;
+ m_progress = 0.0f;
+ }
+
+ if ( m_phase == TBP_PREP ) // prepares?
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_soundChannel = m_sound->Play(SOUND_TREMBLE, m_object->RetPosition(0), 0.0f, 1.0f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.7f, 1.0f, 1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.7f, 1.5f, 7.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.5f, 2.0f, SOPER_STOP);
+
+ m_camera->StartEffect(CE_VIBRATION, m_metal->RetPosition(0), 1.0f);
+
+ m_phase = TBP_BUILD;
+ m_speed = 1.0f/10.f; // duration of 10s
+ m_progress = 0.0f;
+ }
+
+ if ( m_phase == TBP_BUILD ) // construction?
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ DeleteMark(m_metal->RetPosition(0), 20.0f);
+
+ m_metal->DeleteObject(); // removes the metal
+ delete m_metal;
+ m_metal = 0;
+
+ m_building->SetZoom(0, 1.0f);
+ m_building->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ m_building->SetLock(false); // building usable
+ m_main->CreateShortcuts();
+ m_displayText->DisplayError(INFO_BUILD, m_buildingPos, 10.0f, 50.0f);
+
+ automat = m_building->RetAuto();
+ if ( automat != 0 )
+ {
+ automat->Init();
+ }
+
+ m_motion->SetAction(MHS_GUN); // hands gun
+ m_phase = TBP_TERM;
+ m_speed = 1.0f/1.0f;
+ m_progress = 0.0f;
+ }
+
+ if ( m_phase == TBP_TERM ) // rotation terminale ?
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_motion->SetAction(-1);
+ m_object->SetObjectParent(14, 0);
+ m_object->SetPosition(14, Math::Vector(-1.5f, 0.3f, -1.35f));
+ m_object->SetAngleZ(14, Math::PI);
+
+ if ( m_type == OBJECT_FACTORY ||
+ m_type == OBJECT_RESEARCH ||
+ m_type == OBJECT_NUCLEAR )
+ {
+
+ m_phase = TBP_RECEDE;
+ m_speed = 1.0f/1.5f;
+ m_progress = 0.0f;
+ }
+ }
+
+ if ( m_phase == TBP_RECEDE ) // back?
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_physics->SetMotorSpeedX(0.0f);
+ }
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskBuild::Abort()
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ m_camera->StopCentering(m_object, 2.0f);
+ m_physics->SetFreeze(false); // is moving again
+ return true;
+}
+
+
+// Checks whether the terrain is fairly flat
+// and if there is not too close to another object.
+
+Error CTaskBuild::FlatFloor()
+{
+ CObject *pObj;
+ ObjectType type;
+ Math::Vector center, pos, oPos, bPos;
+ Math::Point c, p;
+ float radius, max, oRadius, bRadius, angle, dist;
+ int i, j;
+ bool bLittleFlat, bBase;
+
+ radius = 0.0f;
+ if ( m_type == OBJECT_DERRICK ) radius = 5.0f;
+ if ( m_type == OBJECT_FACTORY ) radius = 15.0f;
+ if ( m_type == OBJECT_REPAIR ) radius = 12.0f;
+ if ( m_type == OBJECT_STATION ) radius = 12.0f;
+ if ( m_type == OBJECT_CONVERT ) radius = 12.0f;
+ if ( m_type == OBJECT_TOWER ) radius = 7.0f;
+ if ( m_type == OBJECT_RESEARCH ) radius = 10.0f;
+ if ( m_type == OBJECT_RADAR ) radius = 5.0f;
+ if ( m_type == OBJECT_ENERGY ) radius = 8.0f;
+ if ( m_type == OBJECT_LABO ) radius = 12.0f;
+ if ( m_type == OBJECT_NUCLEAR ) radius = 20.0f;
+ if ( m_type == OBJECT_PARA ) radius = 20.0f;
+ if ( m_type == OBJECT_INFO ) radius = 5.0f;
+ if ( radius == 0.0f ) return ERR_GENERIC;
+
+ center = m_metal->RetPosition(0);
+ angle = m_terrain->RetFineSlope(center);
+ bLittleFlat = ( angle < FLATLIMIT );
+
+ max = m_terrain->RetFlatZoneRadius(center, radius);
+ if ( max < radius ) // area too small?
+ {
+ if ( bLittleFlat )
+ {
+ m_main->SetShowLimit(1, PARTILIMIT3, m_metal, center, max, 10.0f);
+ }
+ return bLittleFlat?ERR_BUILD_FLATLIT:ERR_BUILD_FLAT;
+ }
+
+ max = 100000.0f;
+ bBase = false;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue; // inactive?
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( pObj == m_metal ) continue;
+ if ( pObj == m_object ) continue;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_BASE )
+ {
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(center, oPos)-80.0f;
+ if ( dist < max )
+ {
+ max = dist;
+ bPos = oPos;
+ bRadius = oRadius;
+ bBase = true;
+ }
+ }
+ else
+ {
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ dist = Math::Distance(center, oPos)-oRadius;
+ if ( dist < max )
+ {
+ max = dist;
+ bPos = oPos;
+ bRadius = oRadius;
+ bBase = false;
+ }
+ }
+ }
+ }
+ if ( max < radius )
+ {
+ m_main->SetShowLimit(1, PARTILIMIT2, m_metal, center, max, 10.0f);
+ if ( bRadius < 2.0f ) bRadius = 2.0f;
+ m_main->SetShowLimit(2, PARTILIMIT3, m_metal, bPos, bRadius, 10.0f);
+ return bBase?ERR_BUILD_BASE:ERR_BUILD_BUSY;
+ }
+
+ max = 100000.0f;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue; // inactive?
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( pObj == m_metal ) continue;
+ if ( pObj == m_object ) continue;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_DERRICK ||
+ type == OBJECT_FACTORY ||
+ type == OBJECT_STATION ||
+ type == OBJECT_CONVERT ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_TOWER ||
+ type == OBJECT_RESEARCH ||
+ type == OBJECT_RADAR ||
+ type == OBJECT_ENERGY ||
+ type == OBJECT_LABO ||
+ type == OBJECT_NUCLEAR ||
+ type == OBJECT_START ||
+ type == OBJECT_END ||
+ type == OBJECT_INFO ||
+ type == OBJECT_PARA ||
+ type == OBJECT_SAFE ||
+ type == OBJECT_HUSTON ) // building?
+ {
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ dist = Math::Distance(center, oPos)-oRadius;
+ if ( dist < max )
+ {
+ max = dist;
+ bPos = oPos;
+ bRadius = oRadius;
+ }
+ }
+ }
+ }
+ if ( max-BUILDMARGIN < radius )
+ {
+ m_main->SetShowLimit(1, PARTILIMIT2, m_metal, center, max-BUILDMARGIN, 10.0f);
+ m_main->SetShowLimit(2, PARTILIMIT3, m_metal, bPos, bRadius+BUILDMARGIN, 10.0f);
+ return bBase?ERR_BUILD_BASE:ERR_BUILD_NARROW;
+ }
+
+ return ERR_OK;
+}
+
+// Seeks the nearest metal object.
+
+CObject* CTaskBuild::SearchMetalObject(float &angle, float dMin, float dMax,
+ float aLimit, Error &err)
+{
+ CObject *pObj, *pBest;
+ Math::Vector iPos, oPos;
+ ObjectType type;
+ float min, iAngle, a, aa, aBest, distance, magic;
+ int i;
+ bool bMetal;
+
+ iPos = m_object->RetPosition(0);
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+
+ min = 1000000.0f;
+ pBest = 0;
+ bMetal = false;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue; // objet inactive?
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+
+ type = pObj->RetType();
+ if ( type != OBJECT_METAL ) continue;
+
+ bMetal = true; // metal exists
+
+ oPos = pObj->RetPosition(0);
+ distance = Math::Distance(oPos, iPos);
+ a = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW!
+
+ if ( distance > dMax ) continue;
+ if ( !Math::TestAngle(a, iAngle-aLimit, iAngle+aLimit) ) continue;
+
+ if ( distance < dMin )
+ {
+ err = ERR_BUILD_METALNEAR; // too close
+ return pObj;
+ }
+
+ aa = fabs(a-iAngle);
+ if ( aa > Math::PI ) aa = Math::PI*2.0f-aa;
+ magic = distance*aa;
+
+ if ( magic < min )
+ {
+ min = magic;
+ aBest = a;
+ pBest = pObj;
+ }
+ }
+
+ if ( pBest == 0 )
+ {
+ if ( bMetal ) err = ERR_BUILD_METALAWAY; // too far
+ else err = ERR_BUILD_METALINEX; // non-existent
+ }
+ else
+ {
+ angle = aBest;
+ err = ERR_OK;
+ }
+ return pBest;
+}
+
+// Destroys all the close marks.
+
+void CTaskBuild::DeleteMark(Math::Vector pos, float radius)
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ ObjectType type;
+ float distance;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_MARKSTONE &&
+ type != OBJECT_MARKURANIUM &&
+ type != OBJECT_MARKKEYa &&
+ type != OBJECT_MARKKEYb &&
+ type != OBJECT_MARKKEYc &&
+ type != OBJECT_MARKKEYd &&
+ type != OBJECT_MARKPOWER ) continue;
+
+ oPos = pObj->RetPosition(0);
+ distance = Math::Distance(oPos, pos);
+ if ( distance <= radius )
+ {
+ pObj->DeleteObject(); // removes the mark
+ delete pObj;
+ i --;
+ }
+ }
+}
+
diff --git a/src/object/task/taskbuild.h b/src/object/task/taskbuild.h
index 0ca7b9b..682086d 100644
--- a/src/object/task/taskbuild.h
+++ b/src/object/task/taskbuild.h
@@ -1,85 +1,85 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskbuild.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-#include "math/vector.h"
-
-
-
-const float BUILDMARGIN = 16.0f;
-const int TBMAXLIGHT = 4;
-
-
-enum TaskBuildPhase
-{
- TBP_TURN = 1, // turns
- TBP_MOVE = 2, // forward/backward
- TBP_TAKE = 3, // takes gun
- TBP_PREP = 4, // prepares
- TBP_BUILD = 5, // builds
- TBP_TERM = 6, // ends
- TBP_RECEDE = 7, // back terminal
-};
-
-
-
-class CTaskBuild : public CTask
-{
-public:
- CTaskBuild(CInstanceManager* iMan, CObject* object);
- ~CTaskBuild();
-
- bool EventProcess(const Event &event);
-
- Error Start(ObjectType type);
- Error IsEnded();
- bool Abort();
-
-protected:
- Error FlatFloor();
- bool CreateBuilding(Math::Vector pos, float angle);
- void CreateLight();
- void BlackLight();
- CObject* SearchMetalObject(float &angle, float dMin, float dMax, float aLimit, Error &err);
- void DeleteMark(Math::Vector pos, float radius);
-
-protected:
- ObjectType m_type; // type of construction
- CObject* m_metal; // transforms metal object
- CObject* m_power; // the vehicle battery
- CObject* m_building; // building built
- TaskBuildPhase m_phase; // phase of the operation
- bool m_bError; // true -> operation impossible
- bool m_bBuild; // true -> building built
- bool m_bBlack; // true -> lights black -> white
- float m_time; // absolute time
- float m_lastParticule; // time of generation last particle
- float m_progress; // progression (0..1)
- float m_speed; // speed of progression
- float m_angleY; // rotation angle of the vehicle
- float m_angleZ; // angle of rotation of the gun
- Math::Vector m_buildingPos; // initial position of the building
- float m_buildingHeight; // height of the building
- int m_lightRank[TBMAXLIGHT];// lights for the effects
- int m_soundChannel;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskbuild.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "object/object.h"
+#include "math/vector.h"
+
+
+
+const float BUILDMARGIN = 16.0f;
+const int TBMAXLIGHT = 4;
+
+
+enum TaskBuildPhase
+{
+ TBP_TURN = 1, // turns
+ TBP_MOVE = 2, // forward/backward
+ TBP_TAKE = 3, // takes gun
+ TBP_PREP = 4, // prepares
+ TBP_BUILD = 5, // builds
+ TBP_TERM = 6, // ends
+ TBP_RECEDE = 7, // back terminal
+};
+
+
+
+class CTaskBuild : public CTask
+{
+public:
+ CTaskBuild(CInstanceManager* iMan, CObject* object);
+ ~CTaskBuild();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(ObjectType type);
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ Error FlatFloor();
+ bool CreateBuilding(Math::Vector pos, float angle);
+ void CreateLight();
+ void BlackLight();
+ CObject* SearchMetalObject(float &angle, float dMin, float dMax, float aLimit, Error &err);
+ void DeleteMark(Math::Vector pos, float radius);
+
+protected:
+ ObjectType m_type; // type of construction
+ CObject* m_metal; // transforms metal object
+ CObject* m_power; // the vehicle battery
+ CObject* m_building; // building built
+ TaskBuildPhase m_phase; // phase of the operation
+ bool m_bError; // true -> operation impossible
+ bool m_bBuild; // true -> building built
+ bool m_bBlack; // true -> lights black -> white
+ float m_time; // absolute time
+ float m_lastParticule; // time of generation last particle
+ float m_progress; // progression (0..1)
+ float m_speed; // speed of progression
+ float m_angleY; // rotation angle of the vehicle
+ float m_angleZ; // angle of rotation of the gun
+ Math::Vector m_buildingPos; // initial position of the building
+ float m_buildingHeight; // height of the building
+ int m_lightRank[TBMAXLIGHT];// lights for the effects
+ int m_soundChannel;
+};
+
diff --git a/src/object/task/taskfire.cpp b/src/object/task/taskfire.cpp
index 4bab31e..8d300e6 100644
--- a/src/object/task/taskfire.cpp
+++ b/src/object/task/taskfire.cpp
@@ -1,384 +1,384 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskfire.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskfire.h"
-
-#include "old/particule.h"
-#include "math/geometry.h"
-#include "physics/physics.h"
-
-
-
-const float ENERGY_FIRE = (0.25f/2.5f); // energy consumed/shot
-const float ENERGY_FIREr = (0.25f/1.5f); // energy consumed/ray
-const float ENERGY_FIREi = (0.10f/2.5f); // energy consumed/organic
-
-
-// Object's constructor.
-
-CTaskFire::CTaskFire(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_soundChannel = -1;
-}
-
-// Object's destructor.
-
-CTaskFire::~CTaskFire()
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-}
-
-
-// Management of an event.
-
-bool CTaskFire::EventProcess(const Event &event)
-{
- CObject* power;
- CPhysics* physics;
- Math::Matrix* mat;
- Math::Vector pos, speed, dir, vib;
- ObjectType type;
- Math::Point dim;
- float energy, fire;
- int i, channel;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_time += event.rTime;
- m_lastSound -= event.rTime;
- m_progress += event.rTime*m_speed;
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- if ( m_bOrganic ) fire = ENERGY_FIREi;
- else if ( m_bRay ) fire = ENERGY_FIREr;
- else fire = ENERGY_FIRE;
- energy -= event.rTime*fire/power->RetCapacity();
- power->SetEnergy(energy);
- }
-
- if ( m_lastParticule+0.05f <= m_time )
- {
- m_lastParticule = m_time;
-
- if ( m_bOrganic )
- {
- mat = m_object->RetWorldMatrix(1); // insect-cannon
-
- for ( i=0 ; i<6 ; i++ )
- {
- pos = Math::Vector(0.0f, 2.5f, 0.0f);
- pos = Math::Transform(*mat, pos);
-
- speed = Math::Vector(200.0f, 0.0f, 0.0f);
-
- physics = m_object->RetPhysics();
- if ( physics != 0 )
- {
- speed += physics->RetLinMotion(MO_REASPEED);
- }
-
- speed.x += (Math::Rand()-0.5f)*10.0f;
- speed.y += (Math::Rand()-0.5f)*20.0f;
- speed.z += (Math::Rand()-0.5f)*30.0f;
- speed = Math::Transform(*mat, speed);
- speed -= pos;
-
- dim.x = Math::Rand()*0.5f+0.5f;
- dim.y = dim.x;
-
- channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN4, 0.8f, 0.0f, 0.0f);
- m_particule->SetObjectFather(channel, m_object);
- }
- }
- else if ( m_bRay )
- {
- mat = m_object->RetWorldMatrix(2); // cannon
-
- for ( i=0 ; i<4 ; i++ )
- {
- pos = Math::Vector(4.0f, 0.0f, 0.0f);
- pos.y += (rand()%3-1)*1.5f;
- pos.z += (rand()%3-1)*1.5f;
- pos = Math::Transform(*mat, pos);
-
- speed = Math::Vector(200.0f, 0.0f, 0.0f);
- speed.x += (Math::Rand()-0.5f)*6.0f;
- speed.y += (Math::Rand()-0.5f)*12.0f;
- speed.z += (Math::Rand()-0.5f)*12.0f;
- speed = Math::Transform(*mat, speed);
- speed -= pos;
-
- dim.x = 1.0f;
- dim.y = dim.x;
- channel = m_particule->CreateTrack(pos, speed, dim, PARTITRACK11,
- 2.0f, 200.0f, 0.5f, 1.0f);
- m_particule->SetObjectFather(channel, m_object);
-
- speed = Math::Vector(5.0f, 0.0f, 0.0f);
- speed.x += (Math::Rand()-0.5f)*1.0f;
- speed.y += (Math::Rand()-0.5f)*2.0f;
- speed.z += (Math::Rand()-0.5f)*2.0f;
- speed = Math::Transform(*mat, speed);
- speed -= pos;
- speed.y += 5.0f;
-
- dim.x = 2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE2, 2.0f, 0.0f, 0.5f);
- }
- }
- else
- {
- type = m_object->RetType();
-
- if ( type == OBJECT_MOBILErc )
- {
- mat = m_object->RetWorldMatrix(2); // cannon
- }
- else
- {
- mat = m_object->RetWorldMatrix(1); // cannon
- }
-
- for ( i=0 ; i<3 ; i++ )
- {
- if ( type == OBJECT_MOBILErc )
- {
- pos = Math::Vector(0.0f, 0.0f, 0.0f);
- }
- else
- {
- pos = Math::Vector(3.0f, 1.0f, 0.0f);
- }
- pos.y += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- pos = Math::Transform(*mat, pos);
-
- speed = Math::Vector(200.0f, 0.0f, 0.0f);
-
- physics = m_object->RetPhysics();
- if ( physics != 0 )
- {
- speed += physics->RetLinMotion(MO_REASPEED);
- }
-
- speed.x += (Math::Rand()-0.5f)*3.0f;
- speed.y += (Math::Rand()-0.5f)*6.0f;
- speed.z += (Math::Rand()-0.5f)*6.0f;
- speed = Math::Transform(*mat, speed);
- speed -= pos;
-
- dim.x = Math::Rand()*0.7f+0.7f;
- dim.y = dim.x;
-
- channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN1, 0.8f, 0.0f, 0.0f);
- m_particule->SetObjectFather(channel, m_object);
- }
-
- if ( type != OBJECT_MOBILErc &&
- m_progress > 0.3f )
- {
- pos = Math::Vector(-1.0f, 1.0f, 0.0f);
- pos.y += (Math::Rand()-0.5f)*0.4f;
- pos.z += (Math::Rand()-0.5f)*0.4f;
- pos = Math::Transform(*mat, pos);
-
- speed = Math::Vector(-4.0f, 0.0f, 0.0f);
- speed.x += (Math::Rand()-0.5f)*2.0f;
- speed.y += (Math::Rand()-0.2f)*4.0f;
- speed.z += (Math::Rand()-0.5f)*4.0f;
- speed = Math::Transform(*mat, speed);
- speed -= pos;
-
- dim.x = Math::Rand()*1.2f+1.2f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f);
-//? m_particule->CreateParticule(pos, speed, dim, PARTISMOKE2, 4.0f, 0.0f, 0.0f);
- }
- }
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- if ( m_progress < 0.1f )
- {
- dir.z = (Math::PI*0.04f)*(m_progress*10.0f);
- }
- else if ( m_progress < 0.9f )
- {
- dir.z = (Math::PI*0.04f);
- }
- else
- {
- dir.z = (Math::PI*0.04f)*(1.0f-(m_progress-0.9f)*10.0f);
- }
- m_object->SetInclinaison(dir);
-
- vib.x = (Math::Rand()-0.5f)*0.01f;
- vib.y = (Math::Rand()-0.5f)*0.02f;
- vib.z = (Math::Rand()-0.5f)*0.02f;
- m_object->SetCirVibration(vib);
-
- vib.x = (Math::Rand()-0.5f)*0.20f;
- vib.y = (Math::Rand()-0.5f)*0.05f;
- vib.z = (Math::Rand()-0.5f)*0.20f;
- m_object->SetLinVibration(vib);
- }
-
- if ( m_bRay && m_lastSound <= 0.0f )
- {
- m_lastSound = Math::Rand()*0.4f+0.4f;
- m_sound->Play(SOUND_FIREp, m_object->RetPosition(0));
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskFire::Start(float delay)
-{
- CObject* power;
- Math::Vector pos, goal, speed;
- float energy, fire;
- ObjectType type;
-
- m_bError = true; // operation impossible
-
- type = m_object->RetType();
- if ( type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILErc ) return ERR_FIRE_VEH;
-
-//? if ( !m_physics->RetLand() ) return ERR_FIRE_FLY;
-
- speed = m_physics->RetMotorSpeed();
-//? if ( speed.x != 0.0f ||
-//? speed.z != 0.0f ) return ERR_FIRE_MOTOR;
-
- m_bRay = (type == OBJECT_MOBILErc);
-
- m_bOrganic = false;
- if ( type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii )
- {
- m_bOrganic = true;
- }
-
- if ( delay == 0.0f )
- {
- if ( m_bRay ) delay = 1.2f;
- else delay = 2.0f;
- }
- m_delay = delay;
-
- power = m_object->RetPower();
- if ( power == 0 ) return ERR_FIRE_ENERGY;
- energy = power->RetEnergy();
- if ( m_bOrganic ) fire = m_delay*ENERGY_FIREi;
- else if ( m_bRay ) fire = m_delay*ENERGY_FIREr;
- else fire = m_delay*ENERGY_FIRE;
- if ( energy < fire/power->RetCapacity()+0.05f ) return ERR_FIRE_ENERGY;
-
- m_speed = 1.0f/m_delay;
- m_progress = 0.0f;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- m_lastSound = 0.0f;
- m_bError = false; // ok
-
-//? m_camera->StartCentering(m_object, Math::PI*0.15f, 99.9f, 0.0f, 1.0f);
-
- if ( m_bOrganic )
- {
- m_soundChannel = m_sound->Play(SOUND_FIREi, m_object->RetPosition(0), 1.0f, 1.0f, true);
- if ( m_soundChannel != -1 )
- {
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, m_delay, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.5f, SOPER_STOP);
- }
- }
- else if ( m_bRay )
- {
- }
- else
- {
- m_soundChannel = m_sound->Play(SOUND_FIRE, m_object->RetPosition(0), 1.0f, 1.0f, true);
- if ( m_soundChannel != -1 )
- {
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, m_delay, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.5f, SOPER_STOP);
- }
- }
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskFire::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskFire::Abort()
-{
- m_object->SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetLinVibration(Math::Vector(0.0f, 0.0f, 0.0f));
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
-//? m_camera->StopCentering(m_object, 1.0f);
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskfire.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskfire.h"
+
+#include "old/particule.h"
+#include "math/geometry.h"
+#include "physics/physics.h"
+
+
+
+const float ENERGY_FIRE = (0.25f/2.5f); // energy consumed/shot
+const float ENERGY_FIREr = (0.25f/1.5f); // energy consumed/ray
+const float ENERGY_FIREi = (0.10f/2.5f); // energy consumed/organic
+
+
+// Object's constructor.
+
+CTaskFire::CTaskFire(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_soundChannel = -1;
+}
+
+// Object's destructor.
+
+CTaskFire::~CTaskFire()
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+}
+
+
+// Management of an event.
+
+bool CTaskFire::EventProcess(const Event &event)
+{
+ CObject* power;
+ CPhysics* physics;
+ Math::Matrix* mat;
+ Math::Vector pos, speed, dir, vib;
+ ObjectType type;
+ Math::Point dim;
+ float energy, fire;
+ int i, channel;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ m_time += event.rTime;
+ m_lastSound -= event.rTime;
+ m_progress += event.rTime*m_speed;
+
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ if ( m_bOrganic ) fire = ENERGY_FIREi;
+ else if ( m_bRay ) fire = ENERGY_FIREr;
+ else fire = ENERGY_FIRE;
+ energy -= event.rTime*fire/power->RetCapacity();
+ power->SetEnergy(energy);
+ }
+
+ if ( m_lastParticule+0.05f <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ if ( m_bOrganic )
+ {
+ mat = m_object->RetWorldMatrix(1); // insect-cannon
+
+ for ( i=0 ; i<6 ; i++ )
+ {
+ pos = Math::Vector(0.0f, 2.5f, 0.0f);
+ pos = Math::Transform(*mat, pos);
+
+ speed = Math::Vector(200.0f, 0.0f, 0.0f);
+
+ physics = m_object->RetPhysics();
+ if ( physics != 0 )
+ {
+ speed += physics->RetLinMotion(MO_REASPEED);
+ }
+
+ speed.x += (Math::Rand()-0.5f)*10.0f;
+ speed.y += (Math::Rand()-0.5f)*20.0f;
+ speed.z += (Math::Rand()-0.5f)*30.0f;
+ speed = Math::Transform(*mat, speed);
+ speed -= pos;
+
+ dim.x = Math::Rand()*0.5f+0.5f;
+ dim.y = dim.x;
+
+ channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN4, 0.8f, 0.0f, 0.0f);
+ m_particule->SetObjectFather(channel, m_object);
+ }
+ }
+ else if ( m_bRay )
+ {
+ mat = m_object->RetWorldMatrix(2); // cannon
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ pos = Math::Vector(4.0f, 0.0f, 0.0f);
+ pos.y += (rand()%3-1)*1.5f;
+ pos.z += (rand()%3-1)*1.5f;
+ pos = Math::Transform(*mat, pos);
+
+ speed = Math::Vector(200.0f, 0.0f, 0.0f);
+ speed.x += (Math::Rand()-0.5f)*6.0f;
+ speed.y += (Math::Rand()-0.5f)*12.0f;
+ speed.z += (Math::Rand()-0.5f)*12.0f;
+ speed = Math::Transform(*mat, speed);
+ speed -= pos;
+
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ channel = m_particule->CreateTrack(pos, speed, dim, PARTITRACK11,
+ 2.0f, 200.0f, 0.5f, 1.0f);
+ m_particule->SetObjectFather(channel, m_object);
+
+ speed = Math::Vector(5.0f, 0.0f, 0.0f);
+ speed.x += (Math::Rand()-0.5f)*1.0f;
+ speed.y += (Math::Rand()-0.5f)*2.0f;
+ speed.z += (Math::Rand()-0.5f)*2.0f;
+ speed = Math::Transform(*mat, speed);
+ speed -= pos;
+ speed.y += 5.0f;
+
+ dim.x = 2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE2, 2.0f, 0.0f, 0.5f);
+ }
+ }
+ else
+ {
+ type = m_object->RetType();
+
+ if ( type == OBJECT_MOBILErc )
+ {
+ mat = m_object->RetWorldMatrix(2); // cannon
+ }
+ else
+ {
+ mat = m_object->RetWorldMatrix(1); // cannon
+ }
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ if ( type == OBJECT_MOBILErc )
+ {
+ pos = Math::Vector(0.0f, 0.0f, 0.0f);
+ }
+ else
+ {
+ pos = Math::Vector(3.0f, 1.0f, 0.0f);
+ }
+ pos.y += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ pos = Math::Transform(*mat, pos);
+
+ speed = Math::Vector(200.0f, 0.0f, 0.0f);
+
+ physics = m_object->RetPhysics();
+ if ( physics != 0 )
+ {
+ speed += physics->RetLinMotion(MO_REASPEED);
+ }
+
+ speed.x += (Math::Rand()-0.5f)*3.0f;
+ speed.y += (Math::Rand()-0.5f)*6.0f;
+ speed.z += (Math::Rand()-0.5f)*6.0f;
+ speed = Math::Transform(*mat, speed);
+ speed -= pos;
+
+ dim.x = Math::Rand()*0.7f+0.7f;
+ dim.y = dim.x;
+
+ channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN1, 0.8f, 0.0f, 0.0f);
+ m_particule->SetObjectFather(channel, m_object);
+ }
+
+ if ( type != OBJECT_MOBILErc &&
+ m_progress > 0.3f )
+ {
+ pos = Math::Vector(-1.0f, 1.0f, 0.0f);
+ pos.y += (Math::Rand()-0.5f)*0.4f;
+ pos.z += (Math::Rand()-0.5f)*0.4f;
+ pos = Math::Transform(*mat, pos);
+
+ speed = Math::Vector(-4.0f, 0.0f, 0.0f);
+ speed.x += (Math::Rand()-0.5f)*2.0f;
+ speed.y += (Math::Rand()-0.2f)*4.0f;
+ speed.z += (Math::Rand()-0.5f)*4.0f;
+ speed = Math::Transform(*mat, speed);
+ speed -= pos;
+
+ dim.x = Math::Rand()*1.2f+1.2f;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f);
+//? m_particule->CreateParticule(pos, speed, dim, PARTISMOKE2, 4.0f, 0.0f, 0.0f);
+ }
+ }
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ if ( m_progress < 0.1f )
+ {
+ dir.z = (Math::PI*0.04f)*(m_progress*10.0f);
+ }
+ else if ( m_progress < 0.9f )
+ {
+ dir.z = (Math::PI*0.04f);
+ }
+ else
+ {
+ dir.z = (Math::PI*0.04f)*(1.0f-(m_progress-0.9f)*10.0f);
+ }
+ m_object->SetInclinaison(dir);
+
+ vib.x = (Math::Rand()-0.5f)*0.01f;
+ vib.y = (Math::Rand()-0.5f)*0.02f;
+ vib.z = (Math::Rand()-0.5f)*0.02f;
+ m_object->SetCirVibration(vib);
+
+ vib.x = (Math::Rand()-0.5f)*0.20f;
+ vib.y = (Math::Rand()-0.5f)*0.05f;
+ vib.z = (Math::Rand()-0.5f)*0.20f;
+ m_object->SetLinVibration(vib);
+ }
+
+ if ( m_bRay && m_lastSound <= 0.0f )
+ {
+ m_lastSound = Math::Rand()*0.4f+0.4f;
+ m_sound->Play(SOUND_FIREp, m_object->RetPosition(0));
+ }
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskFire::Start(float delay)
+{
+ CObject* power;
+ Math::Vector pos, goal, speed;
+ float energy, fire;
+ ObjectType type;
+
+ m_bError = true; // operation impossible
+
+ type = m_object->RetType();
+ if ( type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILErc ) return ERR_FIRE_VEH;
+
+//? if ( !m_physics->RetLand() ) return ERR_FIRE_FLY;
+
+ speed = m_physics->RetMotorSpeed();
+//? if ( speed.x != 0.0f ||
+//? speed.z != 0.0f ) return ERR_FIRE_MOTOR;
+
+ m_bRay = (type == OBJECT_MOBILErc);
+
+ m_bOrganic = false;
+ if ( type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii )
+ {
+ m_bOrganic = true;
+ }
+
+ if ( delay == 0.0f )
+ {
+ if ( m_bRay ) delay = 1.2f;
+ else delay = 2.0f;
+ }
+ m_delay = delay;
+
+ power = m_object->RetPower();
+ if ( power == 0 ) return ERR_FIRE_ENERGY;
+ energy = power->RetEnergy();
+ if ( m_bOrganic ) fire = m_delay*ENERGY_FIREi;
+ else if ( m_bRay ) fire = m_delay*ENERGY_FIREr;
+ else fire = m_delay*ENERGY_FIRE;
+ if ( energy < fire/power->RetCapacity()+0.05f ) return ERR_FIRE_ENERGY;
+
+ m_speed = 1.0f/m_delay;
+ m_progress = 0.0f;
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+ m_lastSound = 0.0f;
+ m_bError = false; // ok
+
+//? m_camera->StartCentering(m_object, Math::PI*0.15f, 99.9f, 0.0f, 1.0f);
+
+ if ( m_bOrganic )
+ {
+ m_soundChannel = m_sound->Play(SOUND_FIREi, m_object->RetPosition(0), 1.0f, 1.0f, true);
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, m_delay, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.5f, SOPER_STOP);
+ }
+ }
+ else if ( m_bRay )
+ {
+ }
+ else
+ {
+ m_soundChannel = m_sound->Play(SOUND_FIRE, m_object->RetPosition(0), 1.0f, 1.0f, true);
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, m_delay, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.5f, SOPER_STOP);
+ }
+ }
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskFire::IsEnded()
+{
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskFire::Abort()
+{
+ m_object->SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
+ m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ m_object->SetLinVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+//? m_camera->StopCentering(m_object, 1.0f);
+ return true;
+}
+
diff --git a/src/object/task/taskfire.h b/src/object/task/taskfire.h
index 43f654e..f06b9f6 100644
--- a/src/object/task/taskfire.h
+++ b/src/object/task/taskfire.h
@@ -1,52 +1,52 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskfire.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskFire : public CTask
-{
-public:
- CTaskFire(CInstanceManager* iMan, CObject* object);
- ~CTaskFire();
-
- bool EventProcess(const Event &event);
-
- Error Start(float delay);
- Error IsEnded();
- bool Abort();
-
-protected:
-
-protected:
- float m_delay;
- float m_progress;
- bool m_bError;
- bool m_bRay;
- bool m_bOrganic;
- float m_time;
- float m_speed;
- float m_lastParticule;
- float m_lastSound;
- int m_soundChannel;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskfire.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+
+
+
+class CTaskFire : public CTask
+{
+public:
+ CTaskFire(CInstanceManager* iMan, CObject* object);
+ ~CTaskFire();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(float delay);
+ Error IsEnded();
+ bool Abort();
+
+protected:
+
+protected:
+ float m_delay;
+ float m_progress;
+ bool m_bError;
+ bool m_bRay;
+ bool m_bOrganic;
+ float m_time;
+ float m_speed;
+ float m_lastParticule;
+ float m_lastSound;
+ int m_soundChannel;
+};
+
diff --git a/src/object/task/taskfireant.cpp b/src/object/task/taskfireant.cpp
index d4a8a61..8eb2217 100644
--- a/src/object/task/taskfireant.cpp
+++ b/src/object/task/taskfireant.cpp
@@ -1,212 +1,212 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskfireant.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskfireant.h"
-
-#include "old/particule.h"
-#include "math/geometry.h"
-#include "object/motion/motionant.h"
-#include "physics/physics.h"
-
-
-
-
-// Object's constructor.
-
-CTaskFireAnt::CTaskFireAnt(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_phase = TFA_NULL;
-}
-
-// Object's destructor.
-
-CTaskFireAnt::~CTaskFireAnt()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskFireAnt::EventProcess(const Event &event)
-{
- Math::Vector dir, vib;
- float a, g, cirSpeed;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- if ( m_object->RetFixed() ) // insect on its back?
- {
- m_bError = true;
- return false;
- }
-
- m_time += event.rTime;
- m_progress += event.rTime*m_speed;
-
- if ( m_phase == TFA_TURN ) // preliminary rotation?
- {
- a = m_object->RetAngleY(0);
- g = m_angle;
- cirSpeed = Math::Direction(a, g)*2.0f;
- if ( cirSpeed > 2.0f ) cirSpeed = 2.0f;
- if ( cirSpeed < -2.0f ) cirSpeed = -2.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left/right
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskFireAnt::Start(Math::Vector impact)
-{
- Math::Vector pos;
- ObjectType type;
-
- m_impact = impact;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() ) return ERR_FIRE_VEH;
-
- type = m_object->RetType();
- if ( type != OBJECT_ANT ) return ERR_FIRE_VEH;
-
- // Insect on its back?
- if ( m_object->RetFixed() ) return ERR_FIRE_VEH;
-
- m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));
-
- pos = m_object->RetPosition(0);
- m_angle = Math::RotateAngle(m_impact.x-pos.x, pos.z-m_impact.z); // CW !
-
- m_phase = TFA_TURN;
- m_speed = 1.0f/1.0f;
- m_progress = 0.0f;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- m_bError = false; // ok
- m_bFire = false; // once!
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskFireAnt::IsEnded()
-{
- Math::Matrix* mat;
- Math::Vector pos, speed;
- Math::Point dim;
- float angle, dist;
- int i, channel;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
- if ( m_object->RetFixed() ) return ERR_STOP; // insect on its back?
-
- if ( m_phase == TFA_TURN ) // rotation ?
- {
- angle = m_object->RetAngleY(0);
- angle = Math::NormAngle(angle); // 0..2*Math::PI
- if ( !Math::TestAngle(angle, m_angle-Math::PI*0.05f, m_angle+Math::PI*0.05f) ) return ERR_CONTINUE;
-
- m_physics->SetMotorSpeedZ(0.0f); // rotation ended
-
- m_phase = TFA_PREPARE;
-//? m_speed = 1.0f/1.5f;
- m_speed = 1.0f/0.4f;
- m_progress = 0.0f;
-//? m_motion->SetAction(MAS_PREPARE, 1.5f);
- m_motion->SetAction(MAS_PREPARE, 0.4f);
- }
-
- if ( m_phase == TFA_PREPARE ) // preparation?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_phase = TFA_FIRE;
-//? m_speed = 1.0f/2.0f;
- m_speed = 1.0f/0.5f;
- m_progress = 0.0f;
-//? m_motion->SetAction(MAS_FIRE, 2.0f);
- m_motion->SetAction(MAS_FIRE, 0.5f);
- }
-
- if ( m_phase == TFA_FIRE ) // shooting?
- {
- if ( m_progress > 0.75f && !m_bFire )
- {
- m_bFire = true; // once
-
- for ( i=0 ; i<20 ; i++ )
- {
- pos = Math::Vector(-2.5f, -0.7f, 0.0f);
- mat = m_object->RetWorldMatrix(2);
- pos = Math::Transform(*mat, pos);
- dist = Math::Distance(pos, m_impact);
- speed = m_impact-pos;
- speed.x += (Math::Rand()-0.5f)*dist*1.2f;
- speed.y += (Math::Rand()-0.5f)*dist*0.4f+50.0f;
- speed.z += (Math::Rand()-0.5f)*dist*1.2f;
- dim.x = 1.0f;
- dim.y = dim.x;
- channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN2, 2.0f, 100.0f, 0.0f);
- m_particule->SetObjectFather(channel, m_object);
- }
- }
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_phase = TFA_TERMINATE;
-//? m_speed = 1.0f/0.9f;
- m_speed = 1.0f/0.4f;
- m_progress = 0.0f;
-//? m_motion->SetAction(MAS_TERMINATE, 0.9f);
- m_motion->SetAction(MAS_TERMINATE, 0.4f);
- }
-
- if ( m_phase == TFA_TERMINATE ) // ends?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_phase = TFA_NULL;
- m_speed = 1.0f/1.0f;
- m_progress = 0.0f;
- }
-
- Abort();
- return ERR_STOP;
-}
-
-
-// Suddenly ends the current action.
-
-bool CTaskFireAnt::Abort()
-{
- m_motion->SetAction(-1);
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskfireant.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskfireant.h"
+
+#include "old/particule.h"
+#include "math/geometry.h"
+#include "object/motion/motionant.h"
+#include "physics/physics.h"
+
+
+
+
+// Object's constructor.
+
+CTaskFireAnt::CTaskFireAnt(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_phase = TFA_NULL;
+}
+
+// Object's destructor.
+
+CTaskFireAnt::~CTaskFireAnt()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskFireAnt::EventProcess(const Event &event)
+{
+ Math::Vector dir, vib;
+ float a, g, cirSpeed;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ if ( m_object->RetFixed() ) // insect on its back?
+ {
+ m_bError = true;
+ return false;
+ }
+
+ m_time += event.rTime;
+ m_progress += event.rTime*m_speed;
+
+ if ( m_phase == TFA_TURN ) // preliminary rotation?
+ {
+ a = m_object->RetAngleY(0);
+ g = m_angle;
+ cirSpeed = Math::Direction(a, g)*2.0f;
+ if ( cirSpeed > 2.0f ) cirSpeed = 2.0f;
+ if ( cirSpeed < -2.0f ) cirSpeed = -2.0f;
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left/right
+ }
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskFireAnt::Start(Math::Vector impact)
+{
+ Math::Vector pos;
+ ObjectType type;
+
+ m_impact = impact;
+
+ m_bError = true; // operation impossible
+ if ( !m_physics->RetLand() ) return ERR_FIRE_VEH;
+
+ type = m_object->RetType();
+ if ( type != OBJECT_ANT ) return ERR_FIRE_VEH;
+
+ // Insect on its back?
+ if ( m_object->RetFixed() ) return ERR_FIRE_VEH;
+
+ m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));
+
+ pos = m_object->RetPosition(0);
+ m_angle = Math::RotateAngle(m_impact.x-pos.x, pos.z-m_impact.z); // CW !
+
+ m_phase = TFA_TURN;
+ m_speed = 1.0f/1.0f;
+ m_progress = 0.0f;
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+ m_bError = false; // ok
+ m_bFire = false; // once!
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskFireAnt::IsEnded()
+{
+ Math::Matrix* mat;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float angle, dist;
+ int i, channel;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+ if ( m_object->RetFixed() ) return ERR_STOP; // insect on its back?
+
+ if ( m_phase == TFA_TURN ) // rotation ?
+ {
+ angle = m_object->RetAngleY(0);
+ angle = Math::NormAngle(angle); // 0..2*Math::PI
+ if ( !Math::TestAngle(angle, m_angle-Math::PI*0.05f, m_angle+Math::PI*0.05f) ) return ERR_CONTINUE;
+
+ m_physics->SetMotorSpeedZ(0.0f); // rotation ended
+
+ m_phase = TFA_PREPARE;
+//? m_speed = 1.0f/1.5f;
+ m_speed = 1.0f/0.4f;
+ m_progress = 0.0f;
+//? m_motion->SetAction(MAS_PREPARE, 1.5f);
+ m_motion->SetAction(MAS_PREPARE, 0.4f);
+ }
+
+ if ( m_phase == TFA_PREPARE ) // preparation?
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_phase = TFA_FIRE;
+//? m_speed = 1.0f/2.0f;
+ m_speed = 1.0f/0.5f;
+ m_progress = 0.0f;
+//? m_motion->SetAction(MAS_FIRE, 2.0f);
+ m_motion->SetAction(MAS_FIRE, 0.5f);
+ }
+
+ if ( m_phase == TFA_FIRE ) // shooting?
+ {
+ if ( m_progress > 0.75f && !m_bFire )
+ {
+ m_bFire = true; // once
+
+ for ( i=0 ; i<20 ; i++ )
+ {
+ pos = Math::Vector(-2.5f, -0.7f, 0.0f);
+ mat = m_object->RetWorldMatrix(2);
+ pos = Math::Transform(*mat, pos);
+ dist = Math::Distance(pos, m_impact);
+ speed = m_impact-pos;
+ speed.x += (Math::Rand()-0.5f)*dist*1.2f;
+ speed.y += (Math::Rand()-0.5f)*dist*0.4f+50.0f;
+ speed.z += (Math::Rand()-0.5f)*dist*1.2f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN2, 2.0f, 100.0f, 0.0f);
+ m_particule->SetObjectFather(channel, m_object);
+ }
+ }
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_phase = TFA_TERMINATE;
+//? m_speed = 1.0f/0.9f;
+ m_speed = 1.0f/0.4f;
+ m_progress = 0.0f;
+//? m_motion->SetAction(MAS_TERMINATE, 0.9f);
+ m_motion->SetAction(MAS_TERMINATE, 0.4f);
+ }
+
+ if ( m_phase == TFA_TERMINATE ) // ends?
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_phase = TFA_NULL;
+ m_speed = 1.0f/1.0f;
+ m_progress = 0.0f;
+ }
+
+ Abort();
+ return ERR_STOP;
+}
+
+
+// Suddenly ends the current action.
+
+bool CTaskFireAnt::Abort()
+{
+ m_motion->SetAction(-1);
+ return true;
+}
+
diff --git a/src/object/task/taskfireant.h b/src/object/task/taskfireant.h
index 5b45775..1d8ef62 100644
--- a/src/object/task/taskfireant.h
+++ b/src/object/task/taskfireant.h
@@ -1,63 +1,63 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskfireant.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-enum TaskFireAnt
-{
- TFA_NULL = 0, // nothing to do
- TFA_TURN = 1, // turns
- TFA_PREPARE = 2, // prepares shooting position
- TFA_FIRE = 3, // shooting
- TFA_TERMINATE = 4, // ends shooting position
-};
-
-
-
-class CTaskFireAnt : public CTask
-{
-public:
- CTaskFireAnt(CInstanceManager* iMan, CObject* object);
- ~CTaskFireAnt();
-
- bool EventProcess(const Event &event);
-
- Error Start(Math::Vector impact);
- Error IsEnded();
- bool Abort();
-
-protected:
-
-protected:
- Math::Vector m_impact;
- TaskFireAnt m_phase;
- float m_progress;
- float m_speed;
- float m_angle;
- bool m_bError;
- bool m_bFire;
- float m_time;
- float m_lastParticule;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskfireant.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "math/vector.h"
+
+
+
+enum TaskFireAnt
+{
+ TFA_NULL = 0, // nothing to do
+ TFA_TURN = 1, // turns
+ TFA_PREPARE = 2, // prepares shooting position
+ TFA_FIRE = 3, // shooting
+ TFA_TERMINATE = 4, // ends shooting position
+};
+
+
+
+class CTaskFireAnt : public CTask
+{
+public:
+ CTaskFireAnt(CInstanceManager* iMan, CObject* object);
+ ~CTaskFireAnt();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(Math::Vector impact);
+ Error IsEnded();
+ bool Abort();
+
+protected:
+
+protected:
+ Math::Vector m_impact;
+ TaskFireAnt m_phase;
+ float m_progress;
+ float m_speed;
+ float m_angle;
+ bool m_bError;
+ bool m_bFire;
+ float m_time;
+ float m_lastParticule;
+};
+
diff --git a/src/object/task/taskflag.cpp b/src/object/task/taskflag.cpp
index f76fef6..7fba689 100644
--- a/src/object/task/taskflag.cpp
+++ b/src/object/task/taskflag.cpp
@@ -1,305 +1,305 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskflag.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskflag.h"
-
-#include "math/geometry.h"
-#include "common/iman.h"
-#include "old/water.h"
-#include "old/pyro.h"
-#include "physics/physics.h"
-#include "object/motion/motionhuman.h"
-
-
-
-
-
-// Object's constructor.
-
-CTaskFlag::CTaskFlag(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskFlag::~CTaskFlag()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskFlag::EventProcess(const Event &event)
-{
- if ( m_bError ) return true;
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_time += event.rTime;
-
- return true;
-}
-
-
-
-// Assigns the goal was achieved.
-
-Error CTaskFlag::Start(TaskFlagOrder order, int rank)
-{
- Math::Vector pos, speed;
- Error err;
-
- m_order = order;
- m_time = 0.0f;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() )
- {
- pos = m_object->RetPosition(0);
- if ( pos.y < m_water->RetLevel() ) return ERR_FLAG_WATER;
- return ERR_FLAG_FLY;
- }
-
- speed = m_physics->RetMotorSpeed();
- if ( speed.x != 0.0f ||
- speed.z != 0.0f ) return ERR_FLAG_MOTOR;
-
- if ( m_object->RetFret() != 0 ) return ERR_FLAG_BUSY;
-
- if ( order == TFL_CREATE )
- {
- err = CreateFlag(rank);
- if ( err != ERR_OK ) return err;
- }
-
- if ( order == TFL_DELETE )
- {
- err = DeleteFlag();
- if ( err != ERR_OK ) return err;
- }
-
- m_bError = false;
-
- m_motion->SetAction(MHS_FLAG); // sets/removes flag
- m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.5f);
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskFlag::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
-
- if ( m_bError ) return ERR_STOP;
- if ( m_time < 2.0f ) return ERR_CONTINUE;
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskFlag::Abort()
-{
- m_motion->SetAction(-1);
- m_camera->StopCentering(m_object, 2.0f);
- return true;
-}
-
-
-
-// Returns the closest object to a given position.
-
-CObject* CTaskFlag::SearchNearest(Math::Vector pos, ObjectType type)
-{
- ObjectType oType;
- CObject *pObj, *pBest;
- Math::Vector oPos;
- float min, dist;
- int i;
-
- min = 100000.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetEnable() ) continue;
-
- oType = pObj->RetType();
- if ( type == OBJECT_NULL )
- {
- if ( oType != OBJECT_FLAGb &&
- oType != OBJECT_FLAGr &&
- oType != OBJECT_FLAGg &&
- oType != OBJECT_FLAGy &&
- oType != OBJECT_FLAGv ) continue;
- }
- else
- {
- if ( oType != type ) continue;
- }
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, pos);
- if ( dist < min )
- {
- min = dist;
- pBest = pObj;
- }
- }
- return pBest;
-}
-
-// Counts the number of existing objects.
-
-int CTaskFlag::CountObject(ObjectType type)
-{
- ObjectType oType;
- CObject *pObj;
- Math::Vector oPos;
- int i, count;
-
- count = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetEnable() ) continue;
-
- oType = pObj->RetType();
- if ( type == OBJECT_NULL )
- {
- if ( oType != OBJECT_FLAGb &&
- oType != OBJECT_FLAGr &&
- oType != OBJECT_FLAGg &&
- oType != OBJECT_FLAGy &&
- oType != OBJECT_FLAGv ) continue;
- }
- else
- {
- if ( oType != type ) continue;
- }
-
- count ++;
- }
- return count;
-}
-
-// Creates a color indicator.
-
-Error CTaskFlag::CreateFlag(int rank)
-{
- CObject* pObj;
- CObject* pNew;
- CPyro* pyro;
- Math::Matrix* mat;
- Math::Vector pos;
- float dist;
- int i;
-
- ObjectType table[5] =
- {
- OBJECT_FLAGb,
- OBJECT_FLAGr,
- OBJECT_FLAGg,
- OBJECT_FLAGy,
- OBJECT_FLAGv,
- };
-
- mat = m_object->RetWorldMatrix(0);
- pos = Transform(*mat, Math::Vector(4.0f, 0.0f, 0.0f));
-
- pObj = SearchNearest(pos, OBJECT_NULL);
- if ( pObj != 0 )
- {
- dist = Math::Distance(pos, pObj->RetPosition(0));
- if ( dist < 10.0f )
- {
- return ERR_FLAG_PROXY;
- }
- }
-
- i = rank;
- if ( CountObject(table[i]) >= 5 )
- {
- return ERR_FLAG_CREATE;
- }
-
- pNew = new CObject(m_iMan);
- if ( !pNew->CreateFlag(pos, 0.0f, table[i]) )
- {
- delete pNew;
- return ERR_TOOMANY;
- }
- pNew->SetZoom(0, 0.0f);
-
- m_sound->Play(SOUND_WAYPOINT, pos);
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FLCREATE, pNew);
-
- return ERR_OK;
-}
-
-// Deletes a color indicator.
-
-Error CTaskFlag::DeleteFlag()
-{
- CObject* pObj;
- CPyro* pyro;
- Math::Vector iPos, oPos;
- float iAngle, angle, aLimit, dist;
-
- iPos = m_object->RetPosition(0);
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- pObj = SearchNearest(iPos, OBJECT_NULL);
- if ( pObj == 0 )
- {
- return ERR_FLAG_DELETE;
- }
- dist = Math::Distance(iPos, pObj->RetPosition(0));
- if ( dist > 10.0f )
- {
- return ERR_FLAG_DELETE;
- }
-
- oPos = pObj->RetPosition(0);
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- aLimit = 45.0f*Math::PI/180.0f;
- if ( !Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
- {
- return ERR_FLAG_DELETE;
- }
-
- m_sound->Play(SOUND_WAYPOINT, iPos);
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FLDELETE, pObj);
-
- return ERR_OK;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskflag.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskflag.h"
+
+#include "math/geometry.h"
+#include "common/iman.h"
+#include "old/water.h"
+#include "old/pyro.h"
+#include "physics/physics.h"
+#include "object/motion/motionhuman.h"
+
+
+
+
+
+// Object's constructor.
+
+CTaskFlag::CTaskFlag(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+}
+
+// Object's destructor.
+
+CTaskFlag::~CTaskFlag()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskFlag::EventProcess(const Event &event)
+{
+ if ( m_bError ) return true;
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_time += event.rTime;
+
+ return true;
+}
+
+
+
+// Assigns the goal was achieved.
+
+Error CTaskFlag::Start(TaskFlagOrder order, int rank)
+{
+ Math::Vector pos, speed;
+ Error err;
+
+ m_order = order;
+ m_time = 0.0f;
+
+ m_bError = true; // operation impossible
+ if ( !m_physics->RetLand() )
+ {
+ pos = m_object->RetPosition(0);
+ if ( pos.y < m_water->RetLevel() ) return ERR_FLAG_WATER;
+ return ERR_FLAG_FLY;
+ }
+
+ speed = m_physics->RetMotorSpeed();
+ if ( speed.x != 0.0f ||
+ speed.z != 0.0f ) return ERR_FLAG_MOTOR;
+
+ if ( m_object->RetFret() != 0 ) return ERR_FLAG_BUSY;
+
+ if ( order == TFL_CREATE )
+ {
+ err = CreateFlag(rank);
+ if ( err != ERR_OK ) return err;
+ }
+
+ if ( order == TFL_DELETE )
+ {
+ err = DeleteFlag();
+ if ( err != ERR_OK ) return err;
+ }
+
+ m_bError = false;
+
+ m_motion->SetAction(MHS_FLAG); // sets/removes flag
+ m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.5f);
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskFlag::IsEnded()
+{
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+
+ if ( m_bError ) return ERR_STOP;
+ if ( m_time < 2.0f ) return ERR_CONTINUE;
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskFlag::Abort()
+{
+ m_motion->SetAction(-1);
+ m_camera->StopCentering(m_object, 2.0f);
+ return true;
+}
+
+
+
+// Returns the closest object to a given position.
+
+CObject* CTaskFlag::SearchNearest(Math::Vector pos, ObjectType type)
+{
+ ObjectType oType;
+ CObject *pObj, *pBest;
+ Math::Vector oPos;
+ float min, dist;
+ int i;
+
+ min = 100000.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetEnable() ) continue;
+
+ oType = pObj->RetType();
+ if ( type == OBJECT_NULL )
+ {
+ if ( oType != OBJECT_FLAGb &&
+ oType != OBJECT_FLAGr &&
+ oType != OBJECT_FLAGg &&
+ oType != OBJECT_FLAGy &&
+ oType != OBJECT_FLAGv ) continue;
+ }
+ else
+ {
+ if ( oType != type ) continue;
+ }
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, pos);
+ if ( dist < min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+ return pBest;
+}
+
+// Counts the number of existing objects.
+
+int CTaskFlag::CountObject(ObjectType type)
+{
+ ObjectType oType;
+ CObject *pObj;
+ Math::Vector oPos;
+ int i, count;
+
+ count = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetEnable() ) continue;
+
+ oType = pObj->RetType();
+ if ( type == OBJECT_NULL )
+ {
+ if ( oType != OBJECT_FLAGb &&
+ oType != OBJECT_FLAGr &&
+ oType != OBJECT_FLAGg &&
+ oType != OBJECT_FLAGy &&
+ oType != OBJECT_FLAGv ) continue;
+ }
+ else
+ {
+ if ( oType != type ) continue;
+ }
+
+ count ++;
+ }
+ return count;
+}
+
+// Creates a color indicator.
+
+Error CTaskFlag::CreateFlag(int rank)
+{
+ CObject* pObj;
+ CObject* pNew;
+ CPyro* pyro;
+ Math::Matrix* mat;
+ Math::Vector pos;
+ float dist;
+ int i;
+
+ ObjectType table[5] =
+ {
+ OBJECT_FLAGb,
+ OBJECT_FLAGr,
+ OBJECT_FLAGg,
+ OBJECT_FLAGy,
+ OBJECT_FLAGv,
+ };
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, Math::Vector(4.0f, 0.0f, 0.0f));
+
+ pObj = SearchNearest(pos, OBJECT_NULL);
+ if ( pObj != 0 )
+ {
+ dist = Math::Distance(pos, pObj->RetPosition(0));
+ if ( dist < 10.0f )
+ {
+ return ERR_FLAG_PROXY;
+ }
+ }
+
+ i = rank;
+ if ( CountObject(table[i]) >= 5 )
+ {
+ return ERR_FLAG_CREATE;
+ }
+
+ pNew = new CObject(m_iMan);
+ if ( !pNew->CreateFlag(pos, 0.0f, table[i]) )
+ {
+ delete pNew;
+ return ERR_TOOMANY;
+ }
+ pNew->SetZoom(0, 0.0f);
+
+ m_sound->Play(SOUND_WAYPOINT, pos);
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FLCREATE, pNew);
+
+ return ERR_OK;
+}
+
+// Deletes a color indicator.
+
+Error CTaskFlag::DeleteFlag()
+{
+ CObject* pObj;
+ CPyro* pyro;
+ Math::Vector iPos, oPos;
+ float iAngle, angle, aLimit, dist;
+
+ iPos = m_object->RetPosition(0);
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+
+ pObj = SearchNearest(iPos, OBJECT_NULL);
+ if ( pObj == 0 )
+ {
+ return ERR_FLAG_DELETE;
+ }
+ dist = Math::Distance(iPos, pObj->RetPosition(0));
+ if ( dist > 10.0f )
+ {
+ return ERR_FLAG_DELETE;
+ }
+
+ oPos = pObj->RetPosition(0);
+ angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+ aLimit = 45.0f*Math::PI/180.0f;
+ if ( !Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
+ {
+ return ERR_FLAG_DELETE;
+ }
+
+ m_sound->Play(SOUND_WAYPOINT, iPos);
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FLDELETE, pObj);
+
+ return ERR_OK;
+}
+
diff --git a/src/object/task/taskflag.h b/src/object/task/taskflag.h
index 4a56357..5b0a058 100644
--- a/src/object/task/taskflag.h
+++ b/src/object/task/taskflag.h
@@ -1,58 +1,58 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-// taskflag.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-#include "math/vector.h"
-
-
-
-enum TaskFlagOrder
-{
- TFL_CREATE = 0, // sets
- TFL_DELETE = 1, // removes
-};
-
-
-
-class CTaskFlag : public CTask
-{
-public:
- CTaskFlag(CInstanceManager* iMan, CObject* object);
- ~CTaskFlag();
-
- bool EventProcess(const Event &event);
-
- Error Start(TaskFlagOrder order, int rank);
- Error IsEnded();
- bool Abort();
-
-protected:
- Error CreateFlag(int rank);
- Error DeleteFlag();
- CObject* SearchNearest(Math::Vector pos, ObjectType type);
- int CountObject(ObjectType type);
-
-protected:
- TaskFlagOrder m_order;
- float m_time;
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+// taskflag.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "object/object.h"
+#include "math/vector.h"
+
+
+
+enum TaskFlagOrder
+{
+ TFL_CREATE = 0, // sets
+ TFL_DELETE = 1, // removes
+};
+
+
+
+class CTaskFlag : public CTask
+{
+public:
+ CTaskFlag(CInstanceManager* iMan, CObject* object);
+ ~CTaskFlag();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(TaskFlagOrder order, int rank);
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ Error CreateFlag(int rank);
+ Error DeleteFlag();
+ CObject* SearchNearest(Math::Vector pos, ObjectType type);
+ int CountObject(ObjectType type);
+
+protected:
+ TaskFlagOrder m_order;
+ float m_time;
+ bool m_bError;
+};
+
diff --git a/src/object/task/taskgoto.cpp b/src/object/task/taskgoto.cpp
index 5ab248c..a3b1515 100644
--- a/src/object/task/taskgoto.cpp
+++ b/src/object/task/taskgoto.cpp
@@ -1,2341 +1,2341 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskgoto.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskgoto.h"
-
-#include "common/event.h"
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "math/geometry.h"
-#include "physics/physics.h"
-
-
-
-const float FLY_DIST_GROUND = 80.0f; // minimum distance to remain on the ground
-const float FLY_DEF_HEIGHT = 50.0f; // default flying height
-const float BM_DIM_STEP = 5.0f;
-
-
-
-
-// Object's constructor.
-
-CTaskGoto::CTaskGoto(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_bmArray = 0;
-}
-
-// Object's destructor.
-
-CTaskGoto::~CTaskGoto()
-{
- BitmapClose();
-}
-
-
-// Management of an event.
-
-bool CTaskGoto::EventProcess(const Event &event)
-{
- Math::Vector pos, goal;
- Math::Point rot, repulse;
- float a, g, dist, linSpeed, cirSpeed, h, hh, factor, dir;
- Error ret;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- // Momentarily stationary object (ant on the back)?
- if ( m_object->RetFixed() )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- return true;
- }
-
- if ( m_error != ERR_OK ) return false;
-
- if ( m_bWorm )
- {
- WormFrame(event.rTime);
- }
-
- if ( m_phase == TGP_BEAMLEAK ) // leak?
- {
- m_leakTime += event.rTime;
-
- pos = m_object->RetPosition(0);
-
- rot.x = m_leakPos.x-pos.x;
- rot.y = m_leakPos.z-pos.z;
- dist = Math::Point(rot.x, rot.y).Length();
- rot.x /= dist;
- rot.y /= dist;
-
- a = m_object->RetAngleY(0);
- g = Math::RotateAngle(rot.x, -rot.y); // CW !
- a = Math::Direction(a, g)*1.0f;
- cirSpeed = a;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- a = Math::NormAngle(a);
- if ( a > Math::PI*0.5f && a < Math::PI*1.5f )
- {
- linSpeed = 1.0f; // obstacle behind -> advance
- cirSpeed = -cirSpeed;
- }
- else
- {
- linSpeed = -1.0f; // obstacle in front -> back
- }
-
- if ( m_bLeakRecede )
- {
- linSpeed = -1.0f;
- cirSpeed = 0.0f;
- }
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- m_physics->SetMotorSpeedX(linSpeed); // advance
- return true;
- }
-
- if ( m_phase == TGP_BEAMSEARCH ) // search path?
- {
- if ( m_bmStep == 0 )
- {
- // Frees the area around the departure.
- BitmapClearCircle(m_object->RetPosition(0), BM_DIM_STEP*1.8f);
- }
-
- pos = m_object->RetPosition(0);
-
- if ( m_bmFretObject == 0 )
- {
- goal = m_goal;
- dist = 0.0f;
- }
- else
- {
- goal = m_goalObject;
- dist = TAKE_DIST+2.0f;
- if ( m_bmFretObject->RetType() == OBJECT_BASE ) dist = 12.0f;
- }
-
- ret = BeamSearch(pos, goal, dist);
- if ( ret == ERR_OK )
- {
-#if 0
- Math::Vector min, max;
- min = pos;
- max = m_goal;
- if ( min.x > max.x ) Math::Swap(min.x, max.x);
- if ( min.z > max.z ) Math::Swap(min.z, max.z);
- min.x -= 50.0f;
- min.z -= 50.0f;
- max.x += 50.0f;
- max.z += 50.0f;
- BitmapDebug(min, max, m_object->RetPosition(0), m_goal);
-#endif
- if ( m_physics->RetLand() ) m_phase = TGP_BEAMWCOLD;
- else m_phase = TGP_BEAMGOTO;
- m_bmIndex = 0;
- m_bmWatchDogPos = m_object->RetPosition(0);
- m_bmWatchDogTime = 0.0f;
- }
- if ( ret == ERR_GOTO_IMPOSSIBLE || ret == ERR_GOTO_ITER )
- {
-#if 0
- Math::Vector min, max;
- min = pos;
- max = m_goal;
- if ( min.x > max.x ) Math::Swap(min.x, max.x);
- if ( min.z > max.z ) Math::Swap(min.z, max.z);
- min.x -= 50.0f;
- min.z -= 50.0f;
- max.x += 50.0f;
- max.z += 50.0f;
- BitmapDebug(min, max, m_object->RetPosition(0), m_goal);
-#endif
- m_error = ret;
- return false;
- }
- return true;
- }
-
- if ( m_phase == TGP_BEAMWCOLD ) // expects cooled reactor?
- {
- return true;
- }
-
- if ( m_phase == TGP_BEAMUP ) // off?
- {
- m_physics->SetMotorSpeedY(1.0f); // up
- return true;
- }
-
- if ( m_phase == TGP_BEAMGOTO ) // goto dot list? (?)
- {
- if ( m_physics->RetCollision() ) // collision?
- {
- m_physics->SetCollision(false); // there's more
- }
-
- pos = m_object->RetPosition(0);
-
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude == 0.0f )
- {
- if ( m_physics->RetLand() )
- {
- m_physics->SetMotorSpeedY(0.0f);
- }
- else
- {
- m_physics->SetMotorSpeedY(-1.0f);
- }
- }
-
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
- {
- goal = m_bmPoints[m_bmIndex];
- goal.y = pos.y;
- h = m_terrain->RetFloorHeight(goal, true, true);
- dist = Math::DistanceProjected(pos, goal);
- if ( dist != 0.0f ) // anticipates?
- {
- linSpeed = m_physics->RetLinMotionX(MO_REASPEED);
- linSpeed /= m_physics->RetLinMotionX(MO_ADVSPEED);
- goal.x = pos.x + (goal.x-pos.x)*linSpeed*20.0f/dist;
- goal.z = pos.z + (goal.z-pos.z)*linSpeed*20.0f/dist;
- }
- goal.y = pos.y;
- hh = m_terrain->RetFloorHeight(goal, true, true);
- h = Math::Min(h, hh);
- linSpeed = 0.0f;
- if ( h < m_altitude-1.0f )
- {
- linSpeed = 0.2f+((m_altitude-1.0f)-h)*0.1f; // up
- if ( linSpeed > 1.0f ) linSpeed = 1.0f;
- }
- if ( h > m_altitude+1.0f )
- {
- linSpeed = -0.2f; // down
- }
- m_physics->SetMotorSpeedY(linSpeed);
- }
-
- rot.x = m_bmPoints[m_bmIndex].x-pos.x;
- rot.y = m_bmPoints[m_bmIndex].z-pos.z;
- dist = Math::Point(rot.x, rot.y).Length();
- rot.x /= dist;
- rot.y /= dist;
-
- a = m_object->RetAngleY(0);
- g = Math::RotateAngle(rot.x, -rot.y); // CW !
- cirSpeed = Math::Direction(a, g)*2.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
- if ( dist < 4.0f ) cirSpeed *= dist/4.0f; // so close -> turns less
-
- if ( m_bmIndex == m_bmTotal ) // last point?
- {
- linSpeed = dist/(m_physics->RetLinStopLength()*1.5f);
- if ( linSpeed > 1.0f ) linSpeed = 1.0f;
- }
- else
- {
- linSpeed = 1.0f; // dark without stopping
- }
-
- linSpeed *= 1.0f-(1.0f-0.3f)*fabs(cirSpeed);
-
-//? if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f )
- if ( fabs(cirSpeed) >= 0.2f )
- {
- linSpeed = 0.0f; // turns first, then advance
- }
-
- dist = Math::DistanceProjected(pos, m_bmWatchDogPos);
- if ( dist < 1.0f && linSpeed != 0.0f )
- {
- m_bmWatchDogTime += event.rTime;
- }
- else
- {
- m_bmWatchDogTime = 0.0f;
- m_bmWatchDogPos = pos;
- }
-
- if ( m_bmWatchDogTime >= 1.0f ) // immobile for a long time?
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- BeamStart(); // we start all
- return true;
- }
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- m_physics->SetMotorSpeedX(linSpeed); // advance
- return true;
- }
-
- if ( m_phase == TGP_BEAMDOWN ) // landed?
- {
- m_physics->SetMotorSpeedY(-0.5f); // tomb
- return true;
- }
-
- if ( m_phase == TGP_LAND ) // landed?
- {
- m_physics->SetMotorSpeedY(-0.5f); // tomb
- return true;
- }
-
- if ( m_goalMode == TGG_EXPRESS )
- {
- if ( m_crashMode == TGC_HALT )
- {
- if ( m_physics->RetCollision() ) // collision?
- {
- m_physics->SetCollision(false); // there's more
- m_error = ERR_STOP;
- return true;
- }
- }
-
- pos = m_object->RetPosition(0);
-
- if ( m_altitude > 0.0f )
- {
- h = m_terrain->RetFloorHeight(pos, true, true);
- linSpeed = 0.0f;
- if ( h < m_altitude )
- {
- linSpeed = 0.1f; // up
- }
- if ( h > m_altitude )
- {
- linSpeed = -0.2f; // down
- }
- m_physics->SetMotorSpeedY(linSpeed);
- }
-
- rot.x = m_goal.x-pos.x;
- rot.y = m_goal.z-pos.z;
- a = m_object->RetAngleY(0);
- g = Math::RotateAngle(rot.x, -rot.y); // CW !
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- m_physics->SetMotorSpeedX(1.0f); // advance
- return true;
- }
-
- if ( m_phase != TGP_TURN &&
- m_physics->RetType() == TYPE_FLYING &&
- m_altitude > 0.0f )
- {
- pos = m_object->RetPosition(0);
- dist = Math::DistanceProjected(m_goal, pos);
- factor = (dist-20.0f)/20.0f;
- if ( factor < 0.0f ) factor = 0.0f;
- if ( factor > 1.0f ) factor = 1.0f;
-
- h = m_terrain->RetFloorHeight(m_object->RetPosition(0), true, true);
- linSpeed = 0.0f;
- if ( h < (m_altitude-0.5f)*factor && factor == 1.0f )
- {
- linSpeed = 0.1f; // up
- }
- if ( h > m_altitude*factor )
- {
- linSpeed = -0.2f; // down
- }
- ComputeFlyingRepulse(dir);
- linSpeed += dir*0.2f;
-
- m_physics->SetMotorSpeedY(linSpeed);
- }
-
- if ( m_phase == TGP_ADVANCE ) // going towards the goal?
- {
- if ( m_physics->RetCollision() ) // collision?
- {
- m_physics->SetCollision(false); // there's more
- m_time = 0.0f;
- m_phase = TGP_CRWAIT;
- return true;
- }
-
-#if 0
- pos = m_object->RetPosition(0);
- a = m_object->RetAngleY(0);
- g = Math::RotateAngle(m_goal.x-pos.x, pos.z-m_goal.z); // CW !
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- dist = Math::DistanceProjected(m_goal, pos);
- linSpeed = dist/(m_physics->RetLinStopLength()*1.5f);
- if ( linSpeed > 1.0f ) linSpeed = 1.0f;
-
- if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f )
- {
- linSpeed = 0.0f; // turns first, then advance
- }
-#else
- pos = m_object->RetPosition(0);
-
- rot.x = m_goal.x-pos.x;
- rot.y = m_goal.z-pos.z;
- dist = Math::Point(rot.x, rot.y).Length();
- rot.x /= dist;
- rot.y /= dist;
-
- ComputeRepulse(repulse);
- rot.x += repulse.x*2.0f;
- rot.y += repulse.y*2.0f;
-
- a = m_object->RetAngleY(0);
- g = Math::RotateAngle(rot.x, -rot.y); // CW !
- cirSpeed = Math::Direction(a, g)*1.0f;
-//? if ( m_physics->RetType() == TYPE_FLYING &&
-//? m_physics->RetLand() ) // flying on the ground?
-//? {
-//? cirSpeed *= 4.0f; // more fishing
-//? }
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- dist = Math::DistanceProjected(m_goal, pos);
- linSpeed = dist/(m_physics->RetLinStopLength()*1.5f);
-//? if ( m_physics->RetType() == TYPE_FLYING &&
-//? m_physics->RetLand() ) // flying on the ground?
-//? {
-//? linSpeed *= 8.0f; // more fishing
-//? }
- if ( linSpeed > 1.0f ) linSpeed = 1.0f;
-
- linSpeed *= 1.0f-(1.0f-0.3f)*fabs(cirSpeed);
-
- if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f )
- {
- linSpeed = 0.0f; // turns first, then advance
- }
-#endif
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- m_physics->SetMotorSpeedX(linSpeed); // advance
- }
-
- if ( m_phase == TGP_TURN || // turns to the object?
- m_phase == TGP_CRTURN || // turns after collision?
- m_phase == TGP_CLTURN ) // turns after collision?
- {
- a = m_object->RetAngleY(0);
- g = m_angle;
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- }
-
- if ( m_phase == TGP_CRWAIT || // waits after collision?
- m_phase == TGP_CLWAIT ) // waits after collision?
- {
- m_time += event.rTime;
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- }
-
- if ( m_phase == TGP_CRADVANCE ) // advance after collision?
- {
- if ( m_physics->RetCollision() ) // collision?
- {
- m_physics->SetCollision(false); // there's more
- m_time = 0.0f;
- m_phase = TGP_CLWAIT;
- return true;
- }
- m_physics->SetMotorSpeedX(0.5f); // advance mollo
- }
-
- if ( m_phase == TGP_CLADVANCE ) // advance after collision?
- {
- if ( m_physics->RetCollision() ) // collision?
- {
- m_physics->SetCollision(false); // there's more
- m_time = 0.0f;
- m_phase = TGP_CRWAIT;
- return true;
- }
- m_physics->SetMotorSpeedX(0.5f); // advance mollo
- }
-
- if ( m_phase == TGP_MOVE ) // final advance?
- {
- m_bmTimeLimit -= event.rTime;
- m_physics->SetMotorSpeedX(1.0f);
- }
-
- return true;
-}
-
-
-// Sought a target for the worm.
-
-CObject* CTaskGoto::WormSearch(Math::Vector &impact)
-{
- CObject* pObj;
- CObject* pBest = 0;
- Math::Vector iPos, oPos;
- ObjectType oType;
- float distance, min, radius;
- int i;
-
- iPos = m_object->RetPosition(0);
- min = 1000000.0f;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( oType != OBJECT_MOBILEfa &&
- oType != OBJECT_MOBILEta &&
- oType != OBJECT_MOBILEwa &&
- oType != OBJECT_MOBILEia &&
- oType != OBJECT_MOBILEfc &&
- oType != OBJECT_MOBILEtc &&
- oType != OBJECT_MOBILEwc &&
- oType != OBJECT_MOBILEic &&
- oType != OBJECT_MOBILEfi &&
- oType != OBJECT_MOBILEti &&
- oType != OBJECT_MOBILEwi &&
- oType != OBJECT_MOBILEii &&
- oType != OBJECT_MOBILEfs &&
- oType != OBJECT_MOBILEts &&
- oType != OBJECT_MOBILEws &&
- oType != OBJECT_MOBILEis &&
- oType != OBJECT_MOBILErt &&
- oType != OBJECT_MOBILErc &&
- oType != OBJECT_MOBILErr &&
- oType != OBJECT_MOBILErs &&
- oType != OBJECT_MOBILEsa &&
- oType != OBJECT_MOBILEtg &&
- oType != OBJECT_MOBILEft &&
- oType != OBJECT_MOBILEtt &&
- oType != OBJECT_MOBILEwt &&
- oType != OBJECT_MOBILEit &&
- oType != OBJECT_MOBILEdr &&
- oType != OBJECT_DERRICK &&
- oType != OBJECT_STATION &&
- oType != OBJECT_FACTORY &&
- oType != OBJECT_REPAIR &&
- oType != OBJECT_DESTROYER &&
- oType != OBJECT_CONVERT &&
- oType != OBJECT_TOWER &&
- oType != OBJECT_RESEARCH &&
- oType != OBJECT_RADAR &&
- oType != OBJECT_INFO &&
- oType != OBJECT_ENERGY &&
- oType != OBJECT_LABO &&
- oType != OBJECT_NUCLEAR &&
- oType != OBJECT_PARA &&
- oType != OBJECT_SAFE &&
- oType != OBJECT_HUSTON ) continue;
-
- if ( pObj->RetVirusMode() ) continue; // object infected?
-
- if ( !pObj->GetCrashSphere(0, oPos, radius) ) continue;
- distance = Math::DistanceProjected(oPos, iPos);
- if ( distance < min )
- {
- min = distance;
- pBest = pObj;
- }
- }
- if ( pBest == 0 ) return 0;
-
- impact = pBest->RetPosition(0);
- return pBest;
-}
-
-// Contaminate objects near the worm.
-
-void CTaskGoto::WormFrame(float rTime)
-{
- CObject* pObj;
- Math::Vector impact, pos;
- float dist;
-
- m_wormLastTime += rTime;
-
- if ( m_wormLastTime >= 0.5f )
- {
- m_wormLastTime = 0.0f;
-
- pObj = WormSearch(impact);
- if ( pObj != 0 )
- {
- pos = m_object->RetPosition(0);
- dist = Math::Distance(pos, impact);
- if ( dist <= 15.0f )
- {
- pObj->SetVirusMode(true); // bam, infected!
- }
- }
- }
-}
-
-
-
-// Assigns the goal was achieved.
-// "dist" is the distance that needs to go far to make a deposit or object.
-
-Error CTaskGoto::Start(Math::Vector goal, float altitude,
- TaskGotoGoal goalMode, TaskGotoCrash crashMode)
-{
- Math::Vector pos;
- CObject* target;
- ObjectType type;
- float dist;
- int x, y;
-
- type = m_object->RetType();
-
- if ( goalMode == TGG_DEFAULT )
- {
- goalMode = TGG_STOP;
- if ( type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_WORM )
- {
- goalMode = TGG_EXPRESS;
- }
- }
-
- if ( crashMode == TGC_DEFAULT )
- {
-//? crashMode = TGC_RIGHTLEFT;
- crashMode = TGC_BEAM;
- if ( type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_WORM ||
- type == OBJECT_BEE )
- {
- crashMode = TGC_HALT;
- }
- }
-
- m_altitude = altitude;
- m_goalMode = goalMode;
- m_crashMode = crashMode;
- m_goalObject = goal;
- m_goal = goal;
-
- m_bTake = false;
- m_phase = TGP_ADVANCE;
- m_error = ERR_OK;
- m_try = 0;
- m_bmFretObject = 0;
- m_bmFinalMove = 0.0f;
-
- pos = m_object->RetPosition(0);
- dist = Math::DistanceProjected(pos, m_goal);
- if ( dist < 10.0f && m_crashMode == TGC_BEAM )
- {
- m_crashMode = TGC_RIGHTLEFT;
- }
-
- m_bWorm = false;
- if ( type == OBJECT_WORM )
- {
- m_bWorm = true;
- m_wormLastTime = 0.0f;
- }
-
- m_bApprox = false;
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH ||
- type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs )
- {
- m_bApprox = true;
- }
-
- if ( !m_bApprox && m_crashMode != TGC_BEAM )
- {
- target = SearchTarget(goal, 1.0f);
- if ( target != 0 )
- {
- m_goal = target->RetPosition(0);
- dist = 0.0f;
- if ( !AdjustBuilding(m_goal, 1.0f, dist) )
- {
- dist = 0.0f;
- AdjustTarget(target, m_goal, dist);
- }
- m_bTake = true; // object was taken on arrival (final rotation)
- }
- }
-
- m_lastDistance = 1000.0f;
- m_physics->SetCollision(false);
-
- if ( m_crashMode == TGC_BEAM ) // with the algorithm of rays?
- {
- target = SearchTarget(goal, 1.0f);
- if ( target != 0 )
- {
- m_goal = target->RetPosition(0);
- dist = 4.0f;
- if ( AdjustBuilding(m_goal, 1.0f, dist) )
- {
- m_bmFinalMove = dist;
- }
- else
- {
- dist = 4.0f;
- if ( AdjustTarget(target, m_goal, dist) )
- {
- m_bmFretObject = target; // cargo on the ground
- }
- else
- {
- m_bmFinalMove = dist;
- }
- }
- m_bTake = true; // object was taken on arrival (final rotation)
- }
-
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude == 0.0f )
- {
- pos = m_object->RetPosition(0);
- dist = Math::DistanceProjected(pos, m_goal);
- if ( dist > FLY_DIST_GROUND ) // over 20 meters?
- {
- m_altitude = FLY_DEF_HEIGHT; // default altitude
- }
- }
-
- BeamStart();
-
- if ( m_bmFretObject == 0 )
- {
- x = (int)((m_goal.x+1600.0f)/BM_DIM_STEP);
- y = (int)((m_goal.z+1600.0f)/BM_DIM_STEP);
- if ( BitmapTestDot(0, x, y) ) // arrival occupied?
- {
-#if 0
- Math::Vector min, max;
- min = m_object->RetPosition(0);
- max = m_goal;
- if ( min.x > max.x ) Math::Swap(min.x, max.x);
- if ( min.z > max.z ) Math::Swap(min.z, max.z);
- min.x -= 50.0f;
- min.z -= 50.0f;
- max.x += 50.0f;
- max.z += 50.0f;
- BitmapDebug(min, max, m_object->RetPosition(0), m_goal);
-#endif
- m_error = ERR_GOTO_BUSY;
- return m_error;
- }
- }
- }
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskGoto::IsEnded()
-{
- Math::Vector pos;
- float limit, angle, dist, h, level;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_error != ERR_OK ) return m_error;
-
- pos = m_object->RetPosition(0);
-
- if ( m_phase == TGP_BEAMLEAK ) // leak?
- {
- if ( m_leakTime >= m_leakDelay )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- BeamInit();
- m_phase = TGP_BEAMSEARCH; // will seek the path
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TGP_BEAMSEARCH ) // search path?
- {
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TGP_BEAMWCOLD ) // expects cool reactor?
- {
- if ( m_altitude != 0.0f &&
- m_physics->RetReactorRange() < 1.0f ) return ERR_CONTINUE;
- m_phase = TGP_BEAMUP;
- }
-
- if ( m_phase == TGP_BEAMUP ) // off?
- {
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
- {
- level = m_terrain->RetFloorLevel(pos, true, true);
- h = level+m_altitude-20.0f;
- limit = m_terrain->RetFlyingMaxHeight();
- if ( h > limit ) h = limit;
- if ( pos.y < h-1.0f ) return ERR_CONTINUE;
-
- m_physics->SetMotorSpeedY(0.0f); // stops the ascent
- }
- m_phase = TGP_BEAMGOTO;
- }
-
- if ( m_phase == TGP_BEAMGOTO ) // goto dot list ?
- {
- if ( m_altitude != 0.0f &&
- m_physics->RetReactorRange() < 0.1f ) // overheating?
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_physics->SetMotorSpeedY(-1.0f); // tomb
- m_phase = TGP_BEAMWCOLD;
- return ERR_CONTINUE;
- }
-
- if ( m_physics->RetLand() ) // on the ground?
- {
- limit = 1.0f;
- }
- else // in flight?
- {
- limit = 2.0f;
- if ( m_bmIndex < m_bmTotal ) limit *= 2.0f; // intermediate point
- }
- if ( m_bApprox ) limit = 2.0f;
-
- if ( fabs(pos.x - m_bmPoints[m_bmIndex].x) < limit &&
- fabs(pos.z - m_bmPoints[m_bmIndex].z) < limit )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
-
- m_bmIndex = BeamShortcut();
-
- if ( m_bmIndex > m_bmTotal )
- {
- m_phase = TGP_BEAMDOWN;
- }
- }
- }
-
- if ( m_phase == TGP_BEAMDOWN ) // landed?
- {
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
- {
- if ( !m_physics->RetLand() ) return ERR_CONTINUE;
- m_physics->SetMotorSpeedY(0.0f); // stops the descent
-
- m_altitude = 0.0f;
- m_phase = TGP_BEAMGOTO; // advance finely on the ground to finish
- m_bmIndex = m_bmTotal;
- return ERR_CONTINUE;
- }
-
- if ( m_bTake )
- {
- m_angle = Math::RotateAngle(m_goalObject.x-pos.x, pos.z-m_goalObject.z);
- m_phase = TGP_TURN;
- }
- else
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- return ERR_STOP;
- }
- }
-
- if ( m_goalMode == TGG_EXPRESS )
- {
- dist = Math::DistanceProjected(m_goal, pos);
- if ( dist < 10.0f && dist > m_lastDistance )
- {
- return ERR_STOP;
- }
- m_lastDistance = dist;
- }
-
- if ( m_phase == TGP_ADVANCE ) // going towards the goal?
- {
- if ( m_physics->RetLand() ) limit = 0.1f; // on the ground
- else limit = 1.0f; // flying
- if ( m_bApprox ) limit = 2.0f;
-
- if ( fabs(pos.x - m_goal.x) < limit &&
- fabs(pos.z - m_goal.z) < limit )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_phase = TGP_LAND;
- }
- }
-
- if ( m_phase == TGP_LAND ) // landed?
- {
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
- {
- if ( !m_physics->RetLand() ) return ERR_CONTINUE;
- m_physics->SetMotorSpeedY(0.0f);
- }
-
- if ( m_bTake )
- {
- m_angle = Math::RotateAngle(m_goalObject.x-pos.x, pos.z-m_goalObject.z);
- m_phase = TGP_TURN;
- }
- else
- {
- return ERR_STOP;
- }
- }
-
- if ( m_phase == TGP_TURN ) // turns to the object?
- {
- angle = Math::NormAngle(m_object->RetAngleY(0));
- limit = 0.02f;
- if ( m_bApprox ) limit = 0.10f;
- if ( fabs(angle-m_angle) < limit )
- {
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- if ( m_bmFinalMove == 0.0f ) return ERR_STOP;
-
- m_bmFinalPos = m_object->RetPosition(0);
- m_bmFinalDist = m_physics->RetLinLength(m_bmFinalMove);
- m_bmTimeLimit = m_physics->RetLinTimeLength(fabs(m_bmFinalMove))*1.5f;
- if ( m_bmTimeLimit < 0.5f ) m_bmTimeLimit = 0.5f;
- m_phase = TGP_MOVE;
- }
- }
-
- if ( m_phase == TGP_CRWAIT ) // waits after collision?
- {
- if ( m_crashMode == TGC_HALT )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_error = ERR_GENERIC;
- return m_error;
- }
- if ( m_time >= 1.0f )
- {
- if ( m_crashMode == TGC_RIGHTLEFT ||
- m_crashMode == TGC_RIGHT ) angle = Math::PI/2.0f; // 90 deegres to the right
- else angle = -Math::PI/2.0f; // 90 deegres to the left
- m_angle = Math::NormAngle(m_object->RetAngleY(0)+angle);
- m_phase = TGP_CRTURN;
-//? m_phase = TGP_ADVANCE;
- }
- }
-
- if ( m_phase == TGP_CRTURN ) // turns after collision?
- {
- angle = Math::NormAngle(m_object->RetAngleY(0));
- limit = 0.1f;
- if ( fabs(angle-m_angle) < limit )
- {
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_pos = pos;
- m_phase = TGP_CRADVANCE;
- }
- }
-
- if ( m_phase == TGP_CRADVANCE ) // advance after collision?
- {
- if ( Math::Distance(pos, m_pos) >= 5.0f )
- {
- m_phase = TGP_ADVANCE;
- }
- }
-
- if ( m_phase == TGP_CLWAIT ) // waits after collision?
- {
- if ( m_time >= 1.0f )
- {
- if ( m_crashMode == TGC_RIGHTLEFT ) angle = -Math::PI;
- if ( m_crashMode == TGC_LEFTRIGHT ) angle = Math::PI;
- if ( m_crashMode == TGC_RIGHT ) angle = Math::PI/2.0f;
- if ( m_crashMode == TGC_LEFT ) angle = -Math::PI/2.0f;
- m_angle = Math::NormAngle(m_object->RetAngleY(0)+angle);
- m_phase = TGP_CLTURN;
- }
- }
-
- if ( m_phase == TGP_CLTURN ) // turns after collision?
- {
- angle = Math::NormAngle(m_object->RetAngleY(0));
- limit = 0.1f;
- if ( fabs(angle-m_angle) < limit )
- {
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_pos = pos;
- m_phase = TGP_CLADVANCE;
- }
- }
-
- if ( m_phase == TGP_CLADVANCE ) // advance after collision?
- {
- if ( Math::Distance(pos, m_pos) >= 10.0f )
- {
- m_phase = TGP_ADVANCE;
- m_try ++;
- }
- }
-
- if ( m_phase == TGP_MOVE ) // final advance?
- {
- if ( m_bmTimeLimit <= 0.0f )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops
- Abort();
- return ERR_STOP;
- }
-
- dist = Math::Distance(m_bmFinalPos, m_object->RetPosition(0));
- if ( dist < m_bmFinalDist ) return ERR_CONTINUE;
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- return ERR_STOP;
- }
-
- return ERR_CONTINUE;
-}
-
-
-// Tries the object is the target position.
-
-CObject* CTaskGoto::SearchTarget(Math::Vector pos, float margin)
-{
- CObject *pObj, *pBest;
- Math::Vector oPos;
- float dist, min;
- int i;
-
- pBest = 0;
- min = 1000000.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue;
- if ( pObj->RetTruck() != 0 ) continue; // object transtorted?
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(pos, oPos);
-
- if ( dist <= margin && dist <= min )
- {
- min = dist;
- pBest = pObj;
- }
- }
-
- return pBest;
-}
-
-// Adjusts the target as a function of the object.
-// Returns true if it is cargo laying on the ground, which can be approached from any site.
-
-bool CTaskGoto::AdjustTarget(CObject* pObj, Math::Vector &pos, float &distance)
-{
- ObjectType type;
- Character* character;
- Math::Matrix* mat;
- Math::Vector goal;
- float dist, suppl;
-
- type = m_object->RetType();
- if ( type == OBJECT_BEE ||
- type == OBJECT_WORM )
- {
- pos = pObj->RetPosition(0);
- return false; // single approach
- }
-
- type = pObj->RetType();
-
- if ( type == OBJECT_FRET ||
- type == OBJECT_STONE ||
- type == OBJECT_URANIUM ||
- type == OBJECT_METAL ||
- type == OBJECT_POWER ||
- type == OBJECT_ATOMIC ||
- type == OBJECT_BULLET ||
- type == OBJECT_BBOX ||
- type == OBJECT_KEYa ||
- type == OBJECT_KEYb ||
- type == OBJECT_KEYc ||
- type == OBJECT_KEYd ||
- type == OBJECT_TNT ||
- type == OBJECT_SCRAP1 ||
- type == OBJECT_SCRAP2 ||
- type == OBJECT_SCRAP3 ||
- type == OBJECT_SCRAP4 ||
- type == OBJECT_SCRAP5 ||
- type == OBJECT_BOMB ||
- type == OBJECT_RUINmobilew1 ||
- type == OBJECT_RUINmobilew2 ||
- type == OBJECT_RUINmobilet1 ||
- type == OBJECT_RUINmobilet2 ||
- type == OBJECT_RUINmobiler1 ||
- type == OBJECT_RUINmobiler2 )
- {
- pos = m_object->RetPosition(0);
- goal = pObj->RetPosition(0);
- dist = Math::Distance(goal, pos);
- pos = (pos-goal)*(TAKE_DIST+distance)/dist + goal;
- return true; // approach from all sites
- }
-
- if ( type == OBJECT_BASE )
- {
- pos = m_object->RetPosition(0);
- goal = pObj->RetPosition(0);
- dist = Math::Distance(goal, pos);
- pos = (pos-goal)*(TAKE_DIST+distance)/dist + goal;
- return true; // approach from all sites
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr )
- {
- character = pObj->RetCharacter();
- pos = character->posPower;
- pos.x -= TAKE_DIST+TAKE_DIST_OTHER+distance;
- mat = pObj->RetWorldMatrix(0);
- pos = Transform(*mat, pos);
- return false; // single approach
- }
-
- if ( GetHotPoint(pObj, goal, true, distance, suppl) )
- {
- pos = goal;
- distance += suppl;
- return false; // single approach
- }
-
- pos = pObj->RetPosition(0);
- distance = 0.0f;
- return false; // single approach
-}
-
-// If you are on an object produced by a building (ore produced by derrick),
-// changes the position by report the building.
-
-bool CTaskGoto::AdjustBuilding(Math::Vector &pos, float margin, float &distance)
-{
- CObject* pObj;
- Math::Vector oPos;
- float dist, suppl;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue;
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- if ( !GetHotPoint(pObj, oPos, false, 0.0f, suppl) ) continue;
- dist = Math::DistanceProjected(pos, oPos);
- if ( dist <= margin )
- {
- GetHotPoint(pObj, pos, true, distance, suppl);
- distance += suppl;
- return true;
- }
- }
- return false;
-}
-
-// Returns the item or product or pose is something on a building.
-
-bool CTaskGoto::GetHotPoint(CObject *pObj, Math::Vector &pos,
- bool bTake, float distance, float &suppl)
-{
- ObjectType type;
- Math::Matrix* mat;
-
- pos = Math::Vector(0.0f, 0.0f, 0.0f);
- suppl = 0.0f;
- type = pObj->RetType();
-
- if ( type == OBJECT_DERRICK )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 8.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_CONVERT )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 0.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_RESEARCH )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 10.0f;
- if ( bTake && distance != 0.0f ) suppl = 2.5f;
- if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_ENERGY )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 6.0f;
- if ( bTake && distance != 0.0f ) suppl = 6.0f;
- if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_TOWER )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 5.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_LABO )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 6.0f;
- if ( bTake && distance != 0.0f ) suppl = 6.0f;
- if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_NUCLEAR )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 22.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_FACTORY )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 4.0f;
- if ( bTake && distance != 0.0f ) suppl = 6.0f;
- if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_STATION )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 4.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += distance;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_REPAIR )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 4.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += distance;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_DESTROYER )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 0.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_PARA && m_physics->RetType() == TYPE_FLYING )
- {
- mat = pObj->RetWorldMatrix(0);
- if ( bTake && distance != 0.0f ) suppl = 20.0f;
- if ( bTake ) pos.x += distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- suppl = 0.0f;
- return false;
-}
-
-
-// Seeks an object too close that he must flee.
-
-bool CTaskGoto::LeakSearch(Math::Vector &pos, float &delay)
-{
- CObject *pObj, *pObstacle;
- Math::Vector iPos, oPos, bPos;
- float iRadius, oRadius, bRadius, dist, min, dir;
- int i, j;
-
- if ( !m_physics->RetLand() ) return false; // in flight?
-
- m_object->GetCrashSphere(0, iPos, iRadius);
-
- min = 100000.0f;
- bRadius = 0.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( !pObj->RetActif() ) continue;
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- dist = Math::DistanceProjected(oPos, iPos);
- if ( dist < min )
- {
- min = dist;
- bPos = oPos;
- bRadius = oRadius;
- pObstacle = pObj;
- }
- }
- }
- if ( min > iRadius+bRadius+4.0f ) return false;
-
- m_bLeakRecede = false;
-
- dist = 4.0f;
- dir = 1.0f;
- if ( pObstacle->RetType() == OBJECT_FACTORY )
- {
- dist = 16.0f;
- dir = -1.0f;
- m_bLeakRecede = true; // simply recoils
- }
-
- pos = bPos;
- delay = m_physics->RetLinTimeLength(dist, dir);
- return true;
-}
-
-
-// Calculates the force of repulsion due to obstacles.
-// The vector length rendered is between 0 and 1.
-
-void CTaskGoto::ComputeRepulse(Math::Point &dir)
-{
-#if 0
- Math::Vector iPos, oPos;
- Math::Point repulse;
- CObject *pObj;
- float dist, iRadius, oRadius;
- int i;
-
- dir.x = 0.0f;
- dir.y = 0.0f;
-
- m_object->GetCrashSphere(0, iPos, iRadius);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, m_goalObject);
- if ( dist <= 1.0f ) continue;
-
- pObj->GetGlobalSphere(oPos, oRadius);
- oRadius += iRadius+m_physics->RetLinStopLength()*1.1f;
- dist = Math::DistanceProjected(oPos, iPos);
- if ( dist <= oRadius )
- {
- repulse.x = iPos.x-oPos.x;
- repulse.y = iPos.z-oPos.z;
-
-//? dist = 0.2f-(0.2f*dist/oRadius);
- dist = powf(dist/oRadius, 2.0f);
- dist = 0.2f-0.2f*dist;
- repulse.x *= dist;
- repulse.y *= dist;
-//? repulse.x /= dist;
-//? repulse.y /= dist;
-
- dir.x += repulse.x;
- dir.y += repulse.y;
- }
- }
-#else
- ObjectType iType, oType;
- Math::Vector iPos, oPos;
- Math::Point repulse;
- CObject *pObj;
- float gDist, add, addi, fac, dist, iRadius, oRadius;
- int i, j;
- bool bAlien;
-
- dir.x = 0.0f;
- dir.y = 0.0f;
-
- // The worm goes everywhere and through everything!
- iType = m_object->RetType();
- if ( iType == OBJECT_WORM ) return;
-
- m_object->GetCrashSphere(0, iPos, iRadius);
- gDist = Math::Distance(iPos, m_goal);
-
- add = m_physics->RetLinStopLength()*1.1f; // braking distance
- fac = 2.0f;
-
- if ( iType == OBJECT_MOBILEwa ||
- iType == OBJECT_MOBILEwc ||
- iType == OBJECT_MOBILEwi ||
- iType == OBJECT_MOBILEws ||
- iType == OBJECT_MOBILEwt ) // wheels?
- {
- add = 5.0f;
- fac = 1.5f;
- }
- if ( iType == OBJECT_MOBILEta ||
- iType == OBJECT_MOBILEtc ||
- iType == OBJECT_MOBILEti ||
- iType == OBJECT_MOBILEts ||
- iType == OBJECT_MOBILEtt ||
- iType == OBJECT_MOBILEdr ) // caterpillars?
- {
- add = 4.0f;
- fac = 1.5f;
- }
- if ( iType == OBJECT_MOBILEfa ||
- iType == OBJECT_MOBILEfc ||
- iType == OBJECT_MOBILEfi ||
- iType == OBJECT_MOBILEfs ||
- iType == OBJECT_MOBILEft ) // flying?
- {
- if ( m_physics->RetLand() )
- {
- add = 5.0f;
- fac = 1.5f;
- }
- else
- {
- add = 10.0f;
- fac = 1.5f;
- }
- }
- if ( iType == OBJECT_MOBILEia ||
- iType == OBJECT_MOBILEic ||
- iType == OBJECT_MOBILEii ||
- iType == OBJECT_MOBILEis ||
- iType == OBJECT_MOBILEit ) // legs?
- {
- add = 4.0f;
- fac = 1.5f;
- }
- if ( iType == OBJECT_BEE ) // wasp?
- {
- if ( m_physics->RetLand() )
- {
- add = 3.0f;
- fac = 1.5f;
- }
- else
- {
- add = 5.0f;
- fac = 1.5f;
- }
- }
-
- bAlien = false;
- if ( iType == OBJECT_MOTHER ||
- iType == OBJECT_ANT ||
- iType == OBJECT_SPIDER ||
- iType == OBJECT_BEE ||
- iType == OBJECT_WORM )
- {
- bAlien = true;
- }
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- oType = pObj->RetType();
-
- if ( oType == OBJECT_WORM ) continue;
-
- if ( bAlien )
- {
- if ( oType == OBJECT_STONE ||
- oType == OBJECT_URANIUM ||
- oType == OBJECT_METAL ||
- oType == OBJECT_POWER ||
- oType == OBJECT_ATOMIC ||
- oType == OBJECT_BULLET ||
- oType == OBJECT_BBOX ||
- oType == OBJECT_KEYa ||
- oType == OBJECT_KEYb ||
- oType == OBJECT_KEYc ||
- oType == OBJECT_KEYd ||
- oType == OBJECT_TNT ||
- oType == OBJECT_SCRAP1 ||
- oType == OBJECT_SCRAP2 ||
- oType == OBJECT_SCRAP3 ||
- oType == OBJECT_SCRAP4 ||
- oType == OBJECT_SCRAP5 ||
- oType == OBJECT_BOMB ||
- (oType >= OBJECT_PLANT0 &&
- oType <= OBJECT_PLANT19 ) ||
- (oType >= OBJECT_MUSHROOM0 &&
- oType <= OBJECT_MUSHROOM9 ) ) continue;
- }
-
- addi = add;
- if ( iType == OBJECT_BEE &&
- oType == OBJECT_BEE )
- {
- addi = 2.0f; // between wasps, do not annoy too much
- }
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- if ( oPos.y-oRadius > iPos.y+iRadius ) continue;
- if ( oPos.y+oRadius < iPos.y-iRadius ) continue;
-
- dist = Math::Distance(oPos, m_goal);
- if ( dist <= 1.0f ) continue; // on purpose?
-
- oRadius += iRadius+addi;
- dist = Math::DistanceProjected(oPos, iPos);
- if ( dist > gDist ) continue; // beyond the goal?
- if ( dist <= oRadius )
- {
- repulse.x = iPos.x-oPos.x;
- repulse.y = iPos.z-oPos.z;
-
- dist = powf(dist/oRadius, fac);
- dist = 0.2f-0.2f*dist;
- repulse.x *= dist;
- repulse.y *= dist;
-
- dir.x += repulse.x;
- dir.y += repulse.y;
- }
- }
- }
-#endif
-}
-
-// Calculates the force of vertical repulsion according to barriers.
-// The vector length is made​between -1 and 1.
-
-void CTaskGoto::ComputeFlyingRepulse(float &dir)
-{
- ObjectType oType;
- Math::Vector iPos, oPos;
- CObject *pObj;
- float add, fac, dist, iRadius, oRadius, repulse;
- int i, j;
-
- m_object->GetCrashSphere(0, iPos, iRadius);
-
- add = 0.0f;
- fac = 1.5f;
- dir = 0.0f;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- oType = pObj->RetType();
-
- if ( oType == OBJECT_WORM ) continue;
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- oRadius += iRadius+add;
- dist = Math::DistanceProjected(oPos, iPos);
- if ( dist <= oRadius )
- {
- repulse = iPos.y-oPos.y;
-
- dist = powf(dist/oRadius, fac);
- dist = 0.2f-0.2f*dist;
- repulse *= dist;
-
- dir += repulse;
- }
- }
- }
-
- if ( dir < -1.0f ) dir = -1.0f;
- if ( dir > 1.0f ) dir = 1.0f;
-}
-
-
-
-// Among all of the following, seek if there is one allowing to go directly to the crow flies.
-// If yes, skip all the unnecessary intermediate points.
-
-int CTaskGoto::BeamShortcut()
-{
- int i;
-
- for ( i=m_bmTotal ; i>=m_bmIndex+2 ; i-- ) // tries from the last
- {
- if ( BitmapTestLine(m_bmPoints[m_bmIndex], m_bmPoints[i], 0.0f, false) )
- {
- return i; // bingo, found
- }
- }
-
- return m_bmIndex+1; // simply goes to the next
-}
-
-// That's the big start.
-
-void CTaskGoto::BeamStart()
-{
- Math::Vector min, max;
-
- BitmapOpen();
- BitmapObject();
-
- min = m_object->RetPosition(0);
- max = m_goal;
- if ( min.x > max.x ) Math::Swap(min.x, max.x);
- if ( min.z > max.z ) Math::Swap(min.z, max.z);
- min.x -= 10.0f*BM_DIM_STEP;
- min.z -= 10.0f*BM_DIM_STEP;
- max.x += 10.0f*BM_DIM_STEP;
- max.z += 10.0f*BM_DIM_STEP;
- BitmapTerrain(min, max);
-
- if ( LeakSearch(m_leakPos, m_leakDelay) )
- {
- m_phase = TGP_BEAMLEAK; // must first leak
- m_leakTime = 0.0f;
- }
- else
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- BeamInit();
- m_phase = TGP_BEAMSEARCH; // will seek the path
- }
-}
-
-// Initialization before the first BeamSearch.
-
-void CTaskGoto::BeamInit()
-{
- int i;
-
- for ( i=0 ; i<MAXPOINTS ; i++ )
- {
- m_bmIter[i] = -1;
- }
- m_bmStep = 0;
-}
-
-// Calculates points and passes to go from start to goal.
-// Returns:
-// ERR_OK if it's good
-// ERR_GOTO_IMPOSSIBLE if impossible
-// ERR_GOTO_ITER if aborts because too many recursions
-// ERR_CONTINUE if not done yet
-// goalRadius: distance at which we must approach the goal
-
-Error CTaskGoto::BeamSearch(const Math::Vector &start, const Math::Vector &goal,
- float goalRadius)
-{
- float step, len;
- int nbIter;
-
- m_bmStep ++;
-
- len = Math::DistanceProjected(start, goal);
- step = len/5.0f;
- if ( step < BM_DIM_STEP*2.1f ) step = BM_DIM_STEP*2.1f;
- if ( step > 20.0f ) step = 20.0f;
- nbIter = 200; // in order not to lower the framerate
- m_bmIterCounter = 0;
- return BeamExplore(start, start, goal, goalRadius, 165.0f*Math::PI/180.0f, 22, step, 0, nbIter);
-}
-
-// prevPos: previous position
-// curPos: current position
-// goalPos: position that seeks to achieve
-// angle: angle to the goal we explores
-// nbDiv: number of subdivisions being done with angle
-// step length of a step
-// i number of recursions made
-// nbIter maximum number of iterations you have the right to make before temporarily interrupt
-
-Error CTaskGoto::BeamExplore(const Math::Vector &prevPos, const Math::Vector &curPos,
- const Math::Vector &goalPos, float goalRadius,
- float angle, int nbDiv, float step,
- int i, int nbIter)
-{
- Math::Vector newPos;
- Error ret;
- int iDiv, iClear, iLar;
-
- iLar = 0;
- if ( i >= MAXPOINTS ) return ERR_GOTO_ITER; // too many recursions
-
- if ( m_bmIter[i] == -1 )
- {
- m_bmIter[i] = 0;
-
- if ( i == 0 )
- {
- m_bmPoints[i] = curPos;
- }
- else
- {
- if ( !BitmapTestLine(prevPos, curPos, angle/nbDiv, true) ) return ERR_GOTO_IMPOSSIBLE;
-
- m_bmPoints[i] = curPos;
-
- if ( Math::DistanceProjected(curPos, goalPos)-goalRadius <= step )
- {
- if ( goalRadius == 0.0f )
- {
- newPos = goalPos;
- }
- else
- {
- newPos = BeamPoint(curPos, goalPos, 0, Math::DistanceProjected(curPos, goalPos)-goalRadius);
- }
- if ( BitmapTestLine(curPos, newPos, angle/nbDiv, false) )
- {
- m_bmPoints[i+1] = newPos;
- m_bmTotal = i+1;
- return ERR_OK;
- }
- }
- }
- }
-
- if ( iLar >= m_bmIter[i] )
- {
- newPos = BeamPoint(curPos, goalPos, 0, step);
- ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter);
- if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret;
- m_bmIter[i] = iLar+1;
- for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1;
- m_bmIterCounter ++;
- if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE;
- }
- iLar ++;
-
- for ( iDiv=1 ; iDiv<=nbDiv ; iDiv++ )
- {
- if ( iLar >= m_bmIter[i] )
- {
- newPos = BeamPoint(curPos, goalPos, angle*iDiv/nbDiv, step);
- ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter);
- if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret;
- m_bmIter[i] = iLar+1;
- for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1;
- m_bmIterCounter ++;
- if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE;
- }
- iLar ++;
-
- if ( iLar >= m_bmIter[i] )
- {
- newPos = BeamPoint(curPos, goalPos, -angle*iDiv/nbDiv, step);
- ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter);
- if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret;
- m_bmIter[i] = iLar+1;
- for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1;
- m_bmIterCounter ++;
- if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE;
- }
- iLar ++;
- }
-
- return ERR_GOTO_IMPOSSIBLE;
-}
-
-// Is a right "start-goal". Calculates the point located at the distance "step"
-// from the point "start" and an angle "angle" with the right.
-
-Math::Vector CTaskGoto::BeamPoint(const Math::Vector &startPoint,
- const Math::Vector &goalPoint,
- float angle, float step)
-{
- Math::Vector resPoint;
- float goalAngle;
-
- goalAngle = Math::RotateAngle(goalPoint.x-startPoint.x, goalPoint.z-startPoint.z);
-
- resPoint.x = startPoint.x + cosf(goalAngle+angle)*step;
- resPoint.z = startPoint.z + sinf(goalAngle+angle)*step;
- resPoint.y = 0.0f;
-
- return resPoint;
-}
-
-// Displays a bitmap part.
-
-void CTaskGoto::BitmapDebug(const Math::Vector &min, const Math::Vector &max,
- const Math::Vector &start, const Math::Vector &goal)
-{
- int minx, miny, maxx, maxy, x, y, i ,n;
- char s[2000];
-
- minx = (int)((min.x+1600.0f)/BM_DIM_STEP);
- miny = (int)((min.z+1600.0f)/BM_DIM_STEP);
- maxx = (int)((max.x+1600.0f)/BM_DIM_STEP);
- maxy = (int)((max.z+1600.0f)/BM_DIM_STEP);
-
- if ( minx > maxx ) Math::Swap(minx, maxx);
- if ( miny > maxy ) Math::Swap(miny, maxy);
-
- OutputDebugString("Bitmap :\n");
- for ( y=miny ; y<=maxy ; y++ )
- {
- s[0] = 0;
- for ( x=minx ; x<=maxx ; x++ )
- {
- n = -1;
- for ( i=0 ; i<=m_bmTotal ; i++ )
- {
- if ( x == (int)((m_bmPoints[i].x+1600.0f)/BM_DIM_STEP) &&
- y == (int)((m_bmPoints[i].z+1600.0f)/BM_DIM_STEP) )
- {
- n = i;
- break;
- }
- }
-
- if ( BitmapTestDot(0, x,y) )
- {
- strcat(s, "o");
- }
- else
- {
- if ( BitmapTestDot(1, x,y) )
- {
- strcat(s, "-");
- }
- else
- {
- strcat(s, ".");
- }
- }
-
- if ( x == (int)((start.x+1600.0f)/BM_DIM_STEP) &&
- y == (int)((start.z+1600.0f)/BM_DIM_STEP) )
- {
- strcat(s, "s");
- }
- else
- if ( x == (int)((goal.x+1600.0f)/BM_DIM_STEP) &&
- y == (int)((goal.z+1600.0f)/BM_DIM_STEP) )
- {
- strcat(s, "g");
- }
- else
- if ( n != -1 )
- {
- char ss[2];
- ss[0] = 'A'+n;
- ss[1] = 0;
- strcat(s, ss);
- }
- else
- {
- strcat(s, " ");
- }
- }
- strcat(s, "\n");
- OutputDebugString(s);
- }
-}
-
-// Tests if a path along a straight line is possible.
-
-bool CTaskGoto::BitmapTestLine(const Math::Vector &start, const Math::Vector &goal,
- float stepAngle, bool bSecond)
-{
- Math::Vector pos, inc;
- float dist, step;
- float distNoB2;
- int i, max, x, y;
-
- if ( m_bmArray == 0 ) return true;
-
- dist = Math::DistanceProjected(start, goal);
- if ( dist == 0.0f ) return true;
- step = BM_DIM_STEP*0.5f;
-
- inc.x = (goal.x-start.x)*step/dist;
- inc.z = (goal.z-start.z)*step/dist;
-
- pos = start;
-
- if ( bSecond )
- {
- x = (int)((pos.x+1600.0f)/BM_DIM_STEP);
- y = (int)((pos.z+1600.0f)/BM_DIM_STEP);
- BitmapSetDot(1, x, y); // puts the flag as the starting point
- }
-
- max = (int)(dist/step);
- if ( max == 0 ) max = 1;
- distNoB2 = BM_DIM_STEP*sqrtf(2.0f)/sinf(stepAngle);
- for ( i=0 ; i<max ; i++ )
- {
- if ( i == max-1 )
- {
- pos = goal; // tests the point of arrival
- }
- else
- {
- pos.x += inc.x;
- pos.z += inc.z;
- }
-
- x = (int)((pos.x+1600.0f)/BM_DIM_STEP);
- y = (int)((pos.z+1600.0f)/BM_DIM_STEP);
-
- if ( bSecond )
- {
- if ( i > 2 && BitmapTestDot(1, x, y) ) return false;
-
- if ( step*(i+1) > distNoB2 && i < max-2 )
- {
- BitmapSetDot(1, x, y);
- }
- }
-
- if ( BitmapTestDot(0, x, y) ) return false;
- }
- return true;
-}
-
-// Adds the objects in the bitmap.
-
-void CTaskGoto::BitmapObject()
-{
- CObject *pObj;
- ObjectType type;
- Math::Vector iPos, oPos;
- float iRadius, oRadius, h;
- int i, j;
-
- m_object->GetCrashSphere(0, iPos, iRadius);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
-
- if ( pObj == m_object ) continue;
- if ( pObj == m_bmFretObject ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- h = m_terrain->RetFloorLevel(pObj->RetPosition(0), false);
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
- {
- h += m_altitude;
- }
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f ) // flying?
- {
- if ( oPos.y-oRadius > h+8.0f ||
- oPos.y+oRadius < h-8.0f ) continue;
- }
- else // crawling?
- {
- if ( oPos.y-oRadius > h+8.0f ) continue;
- }
-
- if ( type == OBJECT_PARA ) oRadius -= 2.0f;
- BitmapSetCircle(oPos, oRadius+iRadius+4.0f);
- }
- }
-}
-
-// Adds a section of land in the bitmap.
-
-void CTaskGoto::BitmapTerrain(const Math::Vector &min, const Math::Vector &max)
-{
- int minx, miny, maxx, maxy;
-
- minx = (int)((min.x+1600.0f)/BM_DIM_STEP);
- miny = (int)((min.z+1600.0f)/BM_DIM_STEP);
- maxx = (int)((max.x+1600.0f)/BM_DIM_STEP);
- maxy = (int)((max.z+1600.0f)/BM_DIM_STEP);
-
- BitmapTerrain(minx, miny, maxx, maxy);
-}
-
-// Adds a section of land in the bitmap.
-
-void CTaskGoto::BitmapTerrain(int minx, int miny, int maxx, int maxy)
-{
- ObjectType type;
- Math::Vector p;
- float aLimit, angle, h;
- int x, y;
- bool bAcceptWater, bFly;
-
- if ( minx > maxx ) Math::Swap(minx, maxx);
- if ( miny > maxy ) Math::Swap(miny, maxy);
-
- if ( minx < 0 ) minx = 0;
- if ( miny < 0 ) miny = 0;
- if ( maxx > m_bmSize-1 ) maxx = m_bmSize-1;
- if ( maxy > m_bmSize-1 ) maxy = m_bmSize-1;
-
- if ( minx > m_bmMinX ) minx = m_bmMinX;
- if ( miny > m_bmMinY ) miny = m_bmMinY;
- if ( maxx < m_bmMaxX ) maxx = m_bmMaxX;
- if ( maxy < m_bmMaxY ) maxy = m_bmMaxY;
-
- if ( minx >= m_bmMinX && maxx <= m_bmMaxX &&
- miny >= m_bmMinY && maxy <= m_bmMaxY ) return;
-
- aLimit = 20.0f*Math::PI/180.0f;
- bAcceptWater = false;
- bFly = false;
-
- type = m_object->RetType();
-
- if ( type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEtg ) // wheels?
- {
- aLimit = 20.0f*Math::PI/180.0f;
- }
-
- if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts ) // caterpillars?
- {
- aLimit = 35.0f*Math::PI/180.0f;
- }
-
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ) // large caterpillars?
- {
- aLimit = 35.0f*Math::PI/180.0f;
- }
-
- if ( type == OBJECT_MOBILEsa ) // submarine caterpillars?
- {
- aLimit = 35.0f*Math::PI/180.0f;
- bAcceptWater = true;
- }
-
- if ( type == OBJECT_MOBILEdr ) // designer caterpillars?
- {
- aLimit = 35.0f*Math::PI/180.0f;
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEft ) // flying?
- {
- aLimit = 15.0f*Math::PI/180.0f;
- bFly = true;
- }
-
- if ( type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILEii ) // insect legs?
- {
- aLimit = 60.0f*Math::PI/180.0f;
- }
-
- for ( y=miny ; y<=maxy ; y++ )
- {
- for ( x=minx ; x<=maxx ; x++ )
- {
- if ( x >= m_bmMinX && x <= m_bmMaxX &&
- y >= m_bmMinY && y <= m_bmMaxY ) continue;
-
- p.x = x*BM_DIM_STEP-1600.0f;
- p.z = y*BM_DIM_STEP-1600.0f;
-
- if ( bFly ) // flying robot?
- {
- h = m_terrain->RetFloorLevel(p, true);
- if ( h >= m_terrain->RetFlyingMaxHeight()-5.0f )
- {
- BitmapSetDot(0, x, y);
- }
- continue;
- }
-
- if ( !bAcceptWater ) // not going underwater?
- {
- h = m_terrain->RetFloorLevel(p, true);
- if ( h < m_water->RetLevel()-2.0f ) // under water (*)?
- {
-//? BitmapSetDot(0, x, y);
- BitmapSetCircle(p, BM_DIM_STEP*1.0f);
- continue;
- }
- }
-
- angle = m_terrain->RetFineSlope(p);
- if ( angle > aLimit )
- {
- BitmapSetDot(0, x, y);
- }
- }
- }
-
- m_bmMinX = minx;
- m_bmMinY = miny;
- m_bmMaxX = maxx;
- m_bmMaxY = maxy; // expanded rectangular area
-}
-
-// (*) Accepts that a robot is 50cm under water, for example Tropica 3!
-
-// Opens an empty bitmap.
-
-bool CTaskGoto::BitmapOpen()
-{
- BitmapClose();
-
- m_bmSize = (int)(3200.0f/BM_DIM_STEP);
- m_bmArray = (unsigned char*)malloc(m_bmSize*m_bmSize/8*2);
- ZeroMemory(m_bmArray, m_bmSize*m_bmSize/8*2);
-
- m_bmOffset = m_bmSize/2;
- m_bmLine = m_bmSize/8;
-
- m_bmMinX = m_bmSize; // non-existent rectangular area
- m_bmMinY = m_bmSize;
- m_bmMaxX = 0;
- m_bmMaxY = 0;
-
- return true;
-}
-
-// Closes the bitmap.
-
-bool CTaskGoto::BitmapClose()
-{
- free(m_bmArray);
- m_bmArray = 0;
- return true;
-}
-
-// Puts a circle in the bitmap.
-
-void CTaskGoto::BitmapSetCircle(const Math::Vector &pos, float radius)
-{
- float d, r;
- int cx, cy, ix, iy;
-
- cx = (int)((pos.x+1600.0f)/BM_DIM_STEP);
- cy = (int)((pos.z+1600.0f)/BM_DIM_STEP);
- r = radius/BM_DIM_STEP;
-
- for ( iy=cy-(int)r ; iy<=cy+(int)r ; iy++ )
- {
- for ( ix=cx-(int)r ; ix<=cx+(int)r ; ix++ )
- {
- d = Math::Point((float)(ix-cx), (float)(iy-cy)).Length();
- if ( d > r ) continue;
- BitmapSetDot(0, ix, iy);
- }
- }
-}
-
-// Removes a circle in the bitmap.
-
-void CTaskGoto::BitmapClearCircle(const Math::Vector &pos, float radius)
-{
- float d, r;
- int cx, cy, ix, iy;
-
- cx = (int)((pos.x+1600.0f)/BM_DIM_STEP);
- cy = (int)((pos.z+1600.0f)/BM_DIM_STEP);
- r = radius/BM_DIM_STEP;
-
- for ( iy=cy-(int)r ; iy<=cy+(int)r ; iy++ )
- {
- for ( ix=cx-(int)r ; ix<=cx+(int)r ; ix++ )
- {
- d = Math::Point((float)(ix-cx), (float)(iy-cy)).Length();
- if ( d > r ) continue;
- BitmapClearDot(0, ix, iy);
- }
- }
-}
-
-// Makes a point in the bitmap.
-// x:y: 0..m_bmSize-1
-
-void CTaskGoto::BitmapSetDot(int rank, int x, int y)
-{
- if ( x < 0 || x >= m_bmSize ||
- y < 0 || y >= m_bmSize ) return;
-
- m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] |= (1<<x%8);
-}
-
-// Removes a point in the bitmap.
-// x:y: 0..m_bmSize-1
-
-void CTaskGoto::BitmapClearDot(int rank, int x, int y)
-{
- if ( x < 0 || x >= m_bmSize ||
- y < 0 || y >= m_bmSize ) return;
-
- m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] &= ~(1<<x%8);
-}
-
-// Tests a point in the bitmap.
-// x:y: 0..m_bmSize-1
-
-bool CTaskGoto::BitmapTestDot(int rank, int x, int y)
-{
- if ( x < 0 || x >= m_bmSize ||
- y < 0 || y >= m_bmSize ) return false;
-
- if ( x < m_bmMinX || x > m_bmMaxX ||
- y < m_bmMinY || y > m_bmMaxY )
- {
- BitmapTerrain(x-10,y-10, x+10,y+10); // remade a layer
- }
-
- return m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] & (1<<x%8);
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskgoto.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskgoto.h"
+
+#include "common/event.h"
+#include "common/iman.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "math/geometry.h"
+#include "physics/physics.h"
+
+
+
+const float FLY_DIST_GROUND = 80.0f; // minimum distance to remain on the ground
+const float FLY_DEF_HEIGHT = 50.0f; // default flying height
+const float BM_DIM_STEP = 5.0f;
+
+
+
+
+// Object's constructor.
+
+CTaskGoto::CTaskGoto(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_bmArray = 0;
+}
+
+// Object's destructor.
+
+CTaskGoto::~CTaskGoto()
+{
+ BitmapClose();
+}
+
+
+// Management of an event.
+
+bool CTaskGoto::EventProcess(const Event &event)
+{
+ Math::Vector pos, goal;
+ Math::Point rot, repulse;
+ float a, g, dist, linSpeed, cirSpeed, h, hh, factor, dir;
+ Error ret;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ // Momentarily stationary object (ant on the back)?
+ if ( m_object->RetFixed() )
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ return true;
+ }
+
+ if ( m_error != ERR_OK ) return false;
+
+ if ( m_bWorm )
+ {
+ WormFrame(event.rTime);
+ }
+
+ if ( m_phase == TGP_BEAMLEAK ) // leak?
+ {
+ m_leakTime += event.rTime;
+
+ pos = m_object->RetPosition(0);
+
+ rot.x = m_leakPos.x-pos.x;
+ rot.y = m_leakPos.z-pos.z;
+ dist = Math::Point(rot.x, rot.y).Length();
+ rot.x /= dist;
+ rot.y /= dist;
+
+ a = m_object->RetAngleY(0);
+ g = Math::RotateAngle(rot.x, -rot.y); // CW !
+ a = Math::Direction(a, g)*1.0f;
+ cirSpeed = a;
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ a = Math::NormAngle(a);
+ if ( a > Math::PI*0.5f && a < Math::PI*1.5f )
+ {
+ linSpeed = 1.0f; // obstacle behind -> advance
+ cirSpeed = -cirSpeed;
+ }
+ else
+ {
+ linSpeed = -1.0f; // obstacle in front -> back
+ }
+
+ if ( m_bLeakRecede )
+ {
+ linSpeed = -1.0f;
+ cirSpeed = 0.0f;
+ }
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
+ m_physics->SetMotorSpeedX(linSpeed); // advance
+ return true;
+ }
+
+ if ( m_phase == TGP_BEAMSEARCH ) // search path?
+ {
+ if ( m_bmStep == 0 )
+ {
+ // Frees the area around the departure.
+ BitmapClearCircle(m_object->RetPosition(0), BM_DIM_STEP*1.8f);
+ }
+
+ pos = m_object->RetPosition(0);
+
+ if ( m_bmFretObject == 0 )
+ {
+ goal = m_goal;
+ dist = 0.0f;
+ }
+ else
+ {
+ goal = m_goalObject;
+ dist = TAKE_DIST+2.0f;
+ if ( m_bmFretObject->RetType() == OBJECT_BASE ) dist = 12.0f;
+ }
+
+ ret = BeamSearch(pos, goal, dist);
+ if ( ret == ERR_OK )
+ {
+#if 0
+ Math::Vector min, max;
+ min = pos;
+ max = m_goal;
+ if ( min.x > max.x ) Math::Swap(min.x, max.x);
+ if ( min.z > max.z ) Math::Swap(min.z, max.z);
+ min.x -= 50.0f;
+ min.z -= 50.0f;
+ max.x += 50.0f;
+ max.z += 50.0f;
+ BitmapDebug(min, max, m_object->RetPosition(0), m_goal);
+#endif
+ if ( m_physics->RetLand() ) m_phase = TGP_BEAMWCOLD;
+ else m_phase = TGP_BEAMGOTO;
+ m_bmIndex = 0;
+ m_bmWatchDogPos = m_object->RetPosition(0);
+ m_bmWatchDogTime = 0.0f;
+ }
+ if ( ret == ERR_GOTO_IMPOSSIBLE || ret == ERR_GOTO_ITER )
+ {
+#if 0
+ Math::Vector min, max;
+ min = pos;
+ max = m_goal;
+ if ( min.x > max.x ) Math::Swap(min.x, max.x);
+ if ( min.z > max.z ) Math::Swap(min.z, max.z);
+ min.x -= 50.0f;
+ min.z -= 50.0f;
+ max.x += 50.0f;
+ max.z += 50.0f;
+ BitmapDebug(min, max, m_object->RetPosition(0), m_goal);
+#endif
+ m_error = ret;
+ return false;
+ }
+ return true;
+ }
+
+ if ( m_phase == TGP_BEAMWCOLD ) // expects cooled reactor?
+ {
+ return true;
+ }
+
+ if ( m_phase == TGP_BEAMUP ) // off?
+ {
+ m_physics->SetMotorSpeedY(1.0f); // up
+ return true;
+ }
+
+ if ( m_phase == TGP_BEAMGOTO ) // goto dot list? (?)
+ {
+ if ( m_physics->RetCollision() ) // collision?
+ {
+ m_physics->SetCollision(false); // there's more
+ }
+
+ pos = m_object->RetPosition(0);
+
+ if ( m_physics->RetType() == TYPE_FLYING && m_altitude == 0.0f )
+ {
+ if ( m_physics->RetLand() )
+ {
+ m_physics->SetMotorSpeedY(0.0f);
+ }
+ else
+ {
+ m_physics->SetMotorSpeedY(-1.0f);
+ }
+ }
+
+ if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
+ {
+ goal = m_bmPoints[m_bmIndex];
+ goal.y = pos.y;
+ h = m_terrain->RetFloorHeight(goal, true, true);
+ dist = Math::DistanceProjected(pos, goal);
+ if ( dist != 0.0f ) // anticipates?
+ {
+ linSpeed = m_physics->RetLinMotionX(MO_REASPEED);
+ linSpeed /= m_physics->RetLinMotionX(MO_ADVSPEED);
+ goal.x = pos.x + (goal.x-pos.x)*linSpeed*20.0f/dist;
+ goal.z = pos.z + (goal.z-pos.z)*linSpeed*20.0f/dist;
+ }
+ goal.y = pos.y;
+ hh = m_terrain->RetFloorHeight(goal, true, true);
+ h = Math::Min(h, hh);
+ linSpeed = 0.0f;
+ if ( h < m_altitude-1.0f )
+ {
+ linSpeed = 0.2f+((m_altitude-1.0f)-h)*0.1f; // up
+ if ( linSpeed > 1.0f ) linSpeed = 1.0f;
+ }
+ if ( h > m_altitude+1.0f )
+ {
+ linSpeed = -0.2f; // down
+ }
+ m_physics->SetMotorSpeedY(linSpeed);
+ }
+
+ rot.x = m_bmPoints[m_bmIndex].x-pos.x;
+ rot.y = m_bmPoints[m_bmIndex].z-pos.z;
+ dist = Math::Point(rot.x, rot.y).Length();
+ rot.x /= dist;
+ rot.y /= dist;
+
+ a = m_object->RetAngleY(0);
+ g = Math::RotateAngle(rot.x, -rot.y); // CW !
+ cirSpeed = Math::Direction(a, g)*2.0f;
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+ if ( dist < 4.0f ) cirSpeed *= dist/4.0f; // so close -> turns less
+
+ if ( m_bmIndex == m_bmTotal ) // last point?
+ {
+ linSpeed = dist/(m_physics->RetLinStopLength()*1.5f);
+ if ( linSpeed > 1.0f ) linSpeed = 1.0f;
+ }
+ else
+ {
+ linSpeed = 1.0f; // dark without stopping
+ }
+
+ linSpeed *= 1.0f-(1.0f-0.3f)*fabs(cirSpeed);
+
+//? if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f )
+ if ( fabs(cirSpeed) >= 0.2f )
+ {
+ linSpeed = 0.0f; // turns first, then advance
+ }
+
+ dist = Math::DistanceProjected(pos, m_bmWatchDogPos);
+ if ( dist < 1.0f && linSpeed != 0.0f )
+ {
+ m_bmWatchDogTime += event.rTime;
+ }
+ else
+ {
+ m_bmWatchDogTime = 0.0f;
+ m_bmWatchDogPos = pos;
+ }
+
+ if ( m_bmWatchDogTime >= 1.0f ) // immobile for a long time?
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ BeamStart(); // we start all
+ return true;
+ }
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
+ m_physics->SetMotorSpeedX(linSpeed); // advance
+ return true;
+ }
+
+ if ( m_phase == TGP_BEAMDOWN ) // landed?
+ {
+ m_physics->SetMotorSpeedY(-0.5f); // tomb
+ return true;
+ }
+
+ if ( m_phase == TGP_LAND ) // landed?
+ {
+ m_physics->SetMotorSpeedY(-0.5f); // tomb
+ return true;
+ }
+
+ if ( m_goalMode == TGG_EXPRESS )
+ {
+ if ( m_crashMode == TGC_HALT )
+ {
+ if ( m_physics->RetCollision() ) // collision?
+ {
+ m_physics->SetCollision(false); // there's more
+ m_error = ERR_STOP;
+ return true;
+ }
+ }
+
+ pos = m_object->RetPosition(0);
+
+ if ( m_altitude > 0.0f )
+ {
+ h = m_terrain->RetFloorHeight(pos, true, true);
+ linSpeed = 0.0f;
+ if ( h < m_altitude )
+ {
+ linSpeed = 0.1f; // up
+ }
+ if ( h > m_altitude )
+ {
+ linSpeed = -0.2f; // down
+ }
+ m_physics->SetMotorSpeedY(linSpeed);
+ }
+
+ rot.x = m_goal.x-pos.x;
+ rot.y = m_goal.z-pos.z;
+ a = m_object->RetAngleY(0);
+ g = Math::RotateAngle(rot.x, -rot.y); // CW !
+ cirSpeed = Math::Direction(a, g)*1.0f;
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
+ m_physics->SetMotorSpeedX(1.0f); // advance
+ return true;
+ }
+
+ if ( m_phase != TGP_TURN &&
+ m_physics->RetType() == TYPE_FLYING &&
+ m_altitude > 0.0f )
+ {
+ pos = m_object->RetPosition(0);
+ dist = Math::DistanceProjected(m_goal, pos);
+ factor = (dist-20.0f)/20.0f;
+ if ( factor < 0.0f ) factor = 0.0f;
+ if ( factor > 1.0f ) factor = 1.0f;
+
+ h = m_terrain->RetFloorHeight(m_object->RetPosition(0), true, true);
+ linSpeed = 0.0f;
+ if ( h < (m_altitude-0.5f)*factor && factor == 1.0f )
+ {
+ linSpeed = 0.1f; // up
+ }
+ if ( h > m_altitude*factor )
+ {
+ linSpeed = -0.2f; // down
+ }
+ ComputeFlyingRepulse(dir);
+ linSpeed += dir*0.2f;
+
+ m_physics->SetMotorSpeedY(linSpeed);
+ }
+
+ if ( m_phase == TGP_ADVANCE ) // going towards the goal?
+ {
+ if ( m_physics->RetCollision() ) // collision?
+ {
+ m_physics->SetCollision(false); // there's more
+ m_time = 0.0f;
+ m_phase = TGP_CRWAIT;
+ return true;
+ }
+
+#if 0
+ pos = m_object->RetPosition(0);
+ a = m_object->RetAngleY(0);
+ g = Math::RotateAngle(m_goal.x-pos.x, pos.z-m_goal.z); // CW !
+ cirSpeed = Math::Direction(a, g)*1.0f;
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ dist = Math::DistanceProjected(m_goal, pos);
+ linSpeed = dist/(m_physics->RetLinStopLength()*1.5f);
+ if ( linSpeed > 1.0f ) linSpeed = 1.0f;
+
+ if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f )
+ {
+ linSpeed = 0.0f; // turns first, then advance
+ }
+#else
+ pos = m_object->RetPosition(0);
+
+ rot.x = m_goal.x-pos.x;
+ rot.y = m_goal.z-pos.z;
+ dist = Math::Point(rot.x, rot.y).Length();
+ rot.x /= dist;
+ rot.y /= dist;
+
+ ComputeRepulse(repulse);
+ rot.x += repulse.x*2.0f;
+ rot.y += repulse.y*2.0f;
+
+ a = m_object->RetAngleY(0);
+ g = Math::RotateAngle(rot.x, -rot.y); // CW !
+ cirSpeed = Math::Direction(a, g)*1.0f;
+//? if ( m_physics->RetType() == TYPE_FLYING &&
+//? m_physics->RetLand() ) // flying on the ground?
+//? {
+//? cirSpeed *= 4.0f; // more fishing
+//? }
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ dist = Math::DistanceProjected(m_goal, pos);
+ linSpeed = dist/(m_physics->RetLinStopLength()*1.5f);
+//? if ( m_physics->RetType() == TYPE_FLYING &&
+//? m_physics->RetLand() ) // flying on the ground?
+//? {
+//? linSpeed *= 8.0f; // more fishing
+//? }
+ if ( linSpeed > 1.0f ) linSpeed = 1.0f;
+
+ linSpeed *= 1.0f-(1.0f-0.3f)*fabs(cirSpeed);
+
+ if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f )
+ {
+ linSpeed = 0.0f; // turns first, then advance
+ }
+#endif
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
+ m_physics->SetMotorSpeedX(linSpeed); // advance
+ }
+
+ if ( m_phase == TGP_TURN || // turns to the object?
+ m_phase == TGP_CRTURN || // turns after collision?
+ m_phase == TGP_CLTURN ) // turns after collision?
+ {
+ a = m_object->RetAngleY(0);
+ g = m_angle;
+ cirSpeed = Math::Direction(a, g)*1.0f;
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
+ }
+
+ if ( m_phase == TGP_CRWAIT || // waits after collision?
+ m_phase == TGP_CLWAIT ) // waits after collision?
+ {
+ m_time += event.rTime;
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ }
+
+ if ( m_phase == TGP_CRADVANCE ) // advance after collision?
+ {
+ if ( m_physics->RetCollision() ) // collision?
+ {
+ m_physics->SetCollision(false); // there's more
+ m_time = 0.0f;
+ m_phase = TGP_CLWAIT;
+ return true;
+ }
+ m_physics->SetMotorSpeedX(0.5f); // advance mollo
+ }
+
+ if ( m_phase == TGP_CLADVANCE ) // advance after collision?
+ {
+ if ( m_physics->RetCollision() ) // collision?
+ {
+ m_physics->SetCollision(false); // there's more
+ m_time = 0.0f;
+ m_phase = TGP_CRWAIT;
+ return true;
+ }
+ m_physics->SetMotorSpeedX(0.5f); // advance mollo
+ }
+
+ if ( m_phase == TGP_MOVE ) // final advance?
+ {
+ m_bmTimeLimit -= event.rTime;
+ m_physics->SetMotorSpeedX(1.0f);
+ }
+
+ return true;
+}
+
+
+// Sought a target for the worm.
+
+CObject* CTaskGoto::WormSearch(Math::Vector &impact)
+{
+ CObject* pObj;
+ CObject* pBest = 0;
+ Math::Vector iPos, oPos;
+ ObjectType oType;
+ float distance, min, radius;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+ min = 1000000.0f;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( oType != OBJECT_MOBILEfa &&
+ oType != OBJECT_MOBILEta &&
+ oType != OBJECT_MOBILEwa &&
+ oType != OBJECT_MOBILEia &&
+ oType != OBJECT_MOBILEfc &&
+ oType != OBJECT_MOBILEtc &&
+ oType != OBJECT_MOBILEwc &&
+ oType != OBJECT_MOBILEic &&
+ oType != OBJECT_MOBILEfi &&
+ oType != OBJECT_MOBILEti &&
+ oType != OBJECT_MOBILEwi &&
+ oType != OBJECT_MOBILEii &&
+ oType != OBJECT_MOBILEfs &&
+ oType != OBJECT_MOBILEts &&
+ oType != OBJECT_MOBILEws &&
+ oType != OBJECT_MOBILEis &&
+ oType != OBJECT_MOBILErt &&
+ oType != OBJECT_MOBILErc &&
+ oType != OBJECT_MOBILErr &&
+ oType != OBJECT_MOBILErs &&
+ oType != OBJECT_MOBILEsa &&
+ oType != OBJECT_MOBILEtg &&
+ oType != OBJECT_MOBILEft &&
+ oType != OBJECT_MOBILEtt &&
+ oType != OBJECT_MOBILEwt &&
+ oType != OBJECT_MOBILEit &&
+ oType != OBJECT_MOBILEdr &&
+ oType != OBJECT_DERRICK &&
+ oType != OBJECT_STATION &&
+ oType != OBJECT_FACTORY &&
+ oType != OBJECT_REPAIR &&
+ oType != OBJECT_DESTROYER &&
+ oType != OBJECT_CONVERT &&
+ oType != OBJECT_TOWER &&
+ oType != OBJECT_RESEARCH &&
+ oType != OBJECT_RADAR &&
+ oType != OBJECT_INFO &&
+ oType != OBJECT_ENERGY &&
+ oType != OBJECT_LABO &&
+ oType != OBJECT_NUCLEAR &&
+ oType != OBJECT_PARA &&
+ oType != OBJECT_SAFE &&
+ oType != OBJECT_HUSTON ) continue;
+
+ if ( pObj->RetVirusMode() ) continue; // object infected?
+
+ if ( !pObj->GetCrashSphere(0, oPos, radius) ) continue;
+ distance = Math::DistanceProjected(oPos, iPos);
+ if ( distance < min )
+ {
+ min = distance;
+ pBest = pObj;
+ }
+ }
+ if ( pBest == 0 ) return 0;
+
+ impact = pBest->RetPosition(0);
+ return pBest;
+}
+
+// Contaminate objects near the worm.
+
+void CTaskGoto::WormFrame(float rTime)
+{
+ CObject* pObj;
+ Math::Vector impact, pos;
+ float dist;
+
+ m_wormLastTime += rTime;
+
+ if ( m_wormLastTime >= 0.5f )
+ {
+ m_wormLastTime = 0.0f;
+
+ pObj = WormSearch(impact);
+ if ( pObj != 0 )
+ {
+ pos = m_object->RetPosition(0);
+ dist = Math::Distance(pos, impact);
+ if ( dist <= 15.0f )
+ {
+ pObj->SetVirusMode(true); // bam, infected!
+ }
+ }
+ }
+}
+
+
+
+// Assigns the goal was achieved.
+// "dist" is the distance that needs to go far to make a deposit or object.
+
+Error CTaskGoto::Start(Math::Vector goal, float altitude,
+ TaskGotoGoal goalMode, TaskGotoCrash crashMode)
+{
+ Math::Vector pos;
+ CObject* target;
+ ObjectType type;
+ float dist;
+ int x, y;
+
+ type = m_object->RetType();
+
+ if ( goalMode == TGG_DEFAULT )
+ {
+ goalMode = TGG_STOP;
+ if ( type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_WORM )
+ {
+ goalMode = TGG_EXPRESS;
+ }
+ }
+
+ if ( crashMode == TGC_DEFAULT )
+ {
+//? crashMode = TGC_RIGHTLEFT;
+ crashMode = TGC_BEAM;
+ if ( type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_WORM ||
+ type == OBJECT_BEE )
+ {
+ crashMode = TGC_HALT;
+ }
+ }
+
+ m_altitude = altitude;
+ m_goalMode = goalMode;
+ m_crashMode = crashMode;
+ m_goalObject = goal;
+ m_goal = goal;
+
+ m_bTake = false;
+ m_phase = TGP_ADVANCE;
+ m_error = ERR_OK;
+ m_try = 0;
+ m_bmFretObject = 0;
+ m_bmFinalMove = 0.0f;
+
+ pos = m_object->RetPosition(0);
+ dist = Math::DistanceProjected(pos, m_goal);
+ if ( dist < 10.0f && m_crashMode == TGC_BEAM )
+ {
+ m_crashMode = TGC_RIGHTLEFT;
+ }
+
+ m_bWorm = false;
+ if ( type == OBJECT_WORM )
+ {
+ m_bWorm = true;
+ m_wormLastTime = 0.0f;
+ }
+
+ m_bApprox = false;
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH ||
+ type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ m_bApprox = true;
+ }
+
+ if ( !m_bApprox && m_crashMode != TGC_BEAM )
+ {
+ target = SearchTarget(goal, 1.0f);
+ if ( target != 0 )
+ {
+ m_goal = target->RetPosition(0);
+ dist = 0.0f;
+ if ( !AdjustBuilding(m_goal, 1.0f, dist) )
+ {
+ dist = 0.0f;
+ AdjustTarget(target, m_goal, dist);
+ }
+ m_bTake = true; // object was taken on arrival (final rotation)
+ }
+ }
+
+ m_lastDistance = 1000.0f;
+ m_physics->SetCollision(false);
+
+ if ( m_crashMode == TGC_BEAM ) // with the algorithm of rays?
+ {
+ target = SearchTarget(goal, 1.0f);
+ if ( target != 0 )
+ {
+ m_goal = target->RetPosition(0);
+ dist = 4.0f;
+ if ( AdjustBuilding(m_goal, 1.0f, dist) )
+ {
+ m_bmFinalMove = dist;
+ }
+ else
+ {
+ dist = 4.0f;
+ if ( AdjustTarget(target, m_goal, dist) )
+ {
+ m_bmFretObject = target; // cargo on the ground
+ }
+ else
+ {
+ m_bmFinalMove = dist;
+ }
+ }
+ m_bTake = true; // object was taken on arrival (final rotation)
+ }
+
+ if ( m_physics->RetType() == TYPE_FLYING && m_altitude == 0.0f )
+ {
+ pos = m_object->RetPosition(0);
+ dist = Math::DistanceProjected(pos, m_goal);
+ if ( dist > FLY_DIST_GROUND ) // over 20 meters?
+ {
+ m_altitude = FLY_DEF_HEIGHT; // default altitude
+ }
+ }
+
+ BeamStart();
+
+ if ( m_bmFretObject == 0 )
+ {
+ x = (int)((m_goal.x+1600.0f)/BM_DIM_STEP);
+ y = (int)((m_goal.z+1600.0f)/BM_DIM_STEP);
+ if ( BitmapTestDot(0, x, y) ) // arrival occupied?
+ {
+#if 0
+ Math::Vector min, max;
+ min = m_object->RetPosition(0);
+ max = m_goal;
+ if ( min.x > max.x ) Math::Swap(min.x, max.x);
+ if ( min.z > max.z ) Math::Swap(min.z, max.z);
+ min.x -= 50.0f;
+ min.z -= 50.0f;
+ max.x += 50.0f;
+ max.z += 50.0f;
+ BitmapDebug(min, max, m_object->RetPosition(0), m_goal);
+#endif
+ m_error = ERR_GOTO_BUSY;
+ return m_error;
+ }
+ }
+ }
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskGoto::IsEnded()
+{
+ Math::Vector pos;
+ float limit, angle, dist, h, level;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_error != ERR_OK ) return m_error;
+
+ pos = m_object->RetPosition(0);
+
+ if ( m_phase == TGP_BEAMLEAK ) // leak?
+ {
+ if ( m_leakTime >= m_leakDelay )
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ BeamInit();
+ m_phase = TGP_BEAMSEARCH; // will seek the path
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TGP_BEAMSEARCH ) // search path?
+ {
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TGP_BEAMWCOLD ) // expects cool reactor?
+ {
+ if ( m_altitude != 0.0f &&
+ m_physics->RetReactorRange() < 1.0f ) return ERR_CONTINUE;
+ m_phase = TGP_BEAMUP;
+ }
+
+ if ( m_phase == TGP_BEAMUP ) // off?
+ {
+ if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
+ {
+ level = m_terrain->RetFloorLevel(pos, true, true);
+ h = level+m_altitude-20.0f;
+ limit = m_terrain->RetFlyingMaxHeight();
+ if ( h > limit ) h = limit;
+ if ( pos.y < h-1.0f ) return ERR_CONTINUE;
+
+ m_physics->SetMotorSpeedY(0.0f); // stops the ascent
+ }
+ m_phase = TGP_BEAMGOTO;
+ }
+
+ if ( m_phase == TGP_BEAMGOTO ) // goto dot list ?
+ {
+ if ( m_altitude != 0.0f &&
+ m_physics->RetReactorRange() < 0.1f ) // overheating?
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ m_physics->SetMotorSpeedY(-1.0f); // tomb
+ m_phase = TGP_BEAMWCOLD;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ limit = 1.0f;
+ }
+ else // in flight?
+ {
+ limit = 2.0f;
+ if ( m_bmIndex < m_bmTotal ) limit *= 2.0f; // intermediate point
+ }
+ if ( m_bApprox ) limit = 2.0f;
+
+ if ( fabs(pos.x - m_bmPoints[m_bmIndex].x) < limit &&
+ fabs(pos.z - m_bmPoints[m_bmIndex].z) < limit )
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+
+ m_bmIndex = BeamShortcut();
+
+ if ( m_bmIndex > m_bmTotal )
+ {
+ m_phase = TGP_BEAMDOWN;
+ }
+ }
+ }
+
+ if ( m_phase == TGP_BEAMDOWN ) // landed?
+ {
+ if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
+ {
+ if ( !m_physics->RetLand() ) return ERR_CONTINUE;
+ m_physics->SetMotorSpeedY(0.0f); // stops the descent
+
+ m_altitude = 0.0f;
+ m_phase = TGP_BEAMGOTO; // advance finely on the ground to finish
+ m_bmIndex = m_bmTotal;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_bTake )
+ {
+ m_angle = Math::RotateAngle(m_goalObject.x-pos.x, pos.z-m_goalObject.z);
+ m_phase = TGP_TURN;
+ }
+ else
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ return ERR_STOP;
+ }
+ }
+
+ if ( m_goalMode == TGG_EXPRESS )
+ {
+ dist = Math::DistanceProjected(m_goal, pos);
+ if ( dist < 10.0f && dist > m_lastDistance )
+ {
+ return ERR_STOP;
+ }
+ m_lastDistance = dist;
+ }
+
+ if ( m_phase == TGP_ADVANCE ) // going towards the goal?
+ {
+ if ( m_physics->RetLand() ) limit = 0.1f; // on the ground
+ else limit = 1.0f; // flying
+ if ( m_bApprox ) limit = 2.0f;
+
+ if ( fabs(pos.x - m_goal.x) < limit &&
+ fabs(pos.z - m_goal.z) < limit )
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ m_phase = TGP_LAND;
+ }
+ }
+
+ if ( m_phase == TGP_LAND ) // landed?
+ {
+ if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
+ {
+ if ( !m_physics->RetLand() ) return ERR_CONTINUE;
+ m_physics->SetMotorSpeedY(0.0f);
+ }
+
+ if ( m_bTake )
+ {
+ m_angle = Math::RotateAngle(m_goalObject.x-pos.x, pos.z-m_goalObject.z);
+ m_phase = TGP_TURN;
+ }
+ else
+ {
+ return ERR_STOP;
+ }
+ }
+
+ if ( m_phase == TGP_TURN ) // turns to the object?
+ {
+ angle = Math::NormAngle(m_object->RetAngleY(0));
+ limit = 0.02f;
+ if ( m_bApprox ) limit = 0.10f;
+ if ( fabs(angle-m_angle) < limit )
+ {
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ if ( m_bmFinalMove == 0.0f ) return ERR_STOP;
+
+ m_bmFinalPos = m_object->RetPosition(0);
+ m_bmFinalDist = m_physics->RetLinLength(m_bmFinalMove);
+ m_bmTimeLimit = m_physics->RetLinTimeLength(fabs(m_bmFinalMove))*1.5f;
+ if ( m_bmTimeLimit < 0.5f ) m_bmTimeLimit = 0.5f;
+ m_phase = TGP_MOVE;
+ }
+ }
+
+ if ( m_phase == TGP_CRWAIT ) // waits after collision?
+ {
+ if ( m_crashMode == TGC_HALT )
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ m_error = ERR_GENERIC;
+ return m_error;
+ }
+ if ( m_time >= 1.0f )
+ {
+ if ( m_crashMode == TGC_RIGHTLEFT ||
+ m_crashMode == TGC_RIGHT ) angle = Math::PI/2.0f; // 90 deegres to the right
+ else angle = -Math::PI/2.0f; // 90 deegres to the left
+ m_angle = Math::NormAngle(m_object->RetAngleY(0)+angle);
+ m_phase = TGP_CRTURN;
+//? m_phase = TGP_ADVANCE;
+ }
+ }
+
+ if ( m_phase == TGP_CRTURN ) // turns after collision?
+ {
+ angle = Math::NormAngle(m_object->RetAngleY(0));
+ limit = 0.1f;
+ if ( fabs(angle-m_angle) < limit )
+ {
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ m_pos = pos;
+ m_phase = TGP_CRADVANCE;
+ }
+ }
+
+ if ( m_phase == TGP_CRADVANCE ) // advance after collision?
+ {
+ if ( Math::Distance(pos, m_pos) >= 5.0f )
+ {
+ m_phase = TGP_ADVANCE;
+ }
+ }
+
+ if ( m_phase == TGP_CLWAIT ) // waits after collision?
+ {
+ if ( m_time >= 1.0f )
+ {
+ if ( m_crashMode == TGC_RIGHTLEFT ) angle = -Math::PI;
+ if ( m_crashMode == TGC_LEFTRIGHT ) angle = Math::PI;
+ if ( m_crashMode == TGC_RIGHT ) angle = Math::PI/2.0f;
+ if ( m_crashMode == TGC_LEFT ) angle = -Math::PI/2.0f;
+ m_angle = Math::NormAngle(m_object->RetAngleY(0)+angle);
+ m_phase = TGP_CLTURN;
+ }
+ }
+
+ if ( m_phase == TGP_CLTURN ) // turns after collision?
+ {
+ angle = Math::NormAngle(m_object->RetAngleY(0));
+ limit = 0.1f;
+ if ( fabs(angle-m_angle) < limit )
+ {
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ m_pos = pos;
+ m_phase = TGP_CLADVANCE;
+ }
+ }
+
+ if ( m_phase == TGP_CLADVANCE ) // advance after collision?
+ {
+ if ( Math::Distance(pos, m_pos) >= 10.0f )
+ {
+ m_phase = TGP_ADVANCE;
+ m_try ++;
+ }
+ }
+
+ if ( m_phase == TGP_MOVE ) // final advance?
+ {
+ if ( m_bmTimeLimit <= 0.0f )
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops
+ Abort();
+ return ERR_STOP;
+ }
+
+ dist = Math::Distance(m_bmFinalPos, m_object->RetPosition(0));
+ if ( dist < m_bmFinalDist ) return ERR_CONTINUE;
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ return ERR_STOP;
+ }
+
+ return ERR_CONTINUE;
+}
+
+
+// Tries the object is the target position.
+
+CObject* CTaskGoto::SearchTarget(Math::Vector pos, float margin)
+{
+ CObject *pObj, *pBest;
+ Math::Vector oPos;
+ float dist, min;
+ int i;
+
+ pBest = 0;
+ min = 1000000.0f;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue;
+ if ( pObj->RetTruck() != 0 ) continue; // object transtorted?
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(pos, oPos);
+
+ if ( dist <= margin && dist <= min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+
+ return pBest;
+}
+
+// Adjusts the target as a function of the object.
+// Returns true if it is cargo laying on the ground, which can be approached from any site.
+
+bool CTaskGoto::AdjustTarget(CObject* pObj, Math::Vector &pos, float &distance)
+{
+ ObjectType type;
+ Character* character;
+ Math::Matrix* mat;
+ Math::Vector goal;
+ float dist, suppl;
+
+ type = m_object->RetType();
+ if ( type == OBJECT_BEE ||
+ type == OBJECT_WORM )
+ {
+ pos = pObj->RetPosition(0);
+ return false; // single approach
+ }
+
+ type = pObj->RetType();
+
+ if ( type == OBJECT_FRET ||
+ type == OBJECT_STONE ||
+ type == OBJECT_URANIUM ||
+ type == OBJECT_METAL ||
+ type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC ||
+ type == OBJECT_BULLET ||
+ type == OBJECT_BBOX ||
+ type == OBJECT_KEYa ||
+ type == OBJECT_KEYb ||
+ type == OBJECT_KEYc ||
+ type == OBJECT_KEYd ||
+ type == OBJECT_TNT ||
+ type == OBJECT_SCRAP1 ||
+ type == OBJECT_SCRAP2 ||
+ type == OBJECT_SCRAP3 ||
+ type == OBJECT_SCRAP4 ||
+ type == OBJECT_SCRAP5 ||
+ type == OBJECT_BOMB ||
+ type == OBJECT_RUINmobilew1 ||
+ type == OBJECT_RUINmobilew2 ||
+ type == OBJECT_RUINmobilet1 ||
+ type == OBJECT_RUINmobilet2 ||
+ type == OBJECT_RUINmobiler1 ||
+ type == OBJECT_RUINmobiler2 )
+ {
+ pos = m_object->RetPosition(0);
+ goal = pObj->RetPosition(0);
+ dist = Math::Distance(goal, pos);
+ pos = (pos-goal)*(TAKE_DIST+distance)/dist + goal;
+ return true; // approach from all sites
+ }
+
+ if ( type == OBJECT_BASE )
+ {
+ pos = m_object->RetPosition(0);
+ goal = pObj->RetPosition(0);
+ dist = Math::Distance(goal, pos);
+ pos = (pos-goal)*(TAKE_DIST+distance)/dist + goal;
+ return true; // approach from all sites
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr )
+ {
+ character = pObj->RetCharacter();
+ pos = character->posPower;
+ pos.x -= TAKE_DIST+TAKE_DIST_OTHER+distance;
+ mat = pObj->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+ return false; // single approach
+ }
+
+ if ( GetHotPoint(pObj, goal, true, distance, suppl) )
+ {
+ pos = goal;
+ distance += suppl;
+ return false; // single approach
+ }
+
+ pos = pObj->RetPosition(0);
+ distance = 0.0f;
+ return false; // single approach
+}
+
+// If you are on an object produced by a building (ore produced by derrick),
+// changes the position by report the building.
+
+bool CTaskGoto::AdjustBuilding(Math::Vector &pos, float margin, float &distance)
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ float dist, suppl;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue;
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+
+ if ( !GetHotPoint(pObj, oPos, false, 0.0f, suppl) ) continue;
+ dist = Math::DistanceProjected(pos, oPos);
+ if ( dist <= margin )
+ {
+ GetHotPoint(pObj, pos, true, distance, suppl);
+ distance += suppl;
+ return true;
+ }
+ }
+ return false;
+}
+
+// Returns the item or product or pose is something on a building.
+
+bool CTaskGoto::GetHotPoint(CObject *pObj, Math::Vector &pos,
+ bool bTake, float distance, float &suppl)
+{
+ ObjectType type;
+ Math::Matrix* mat;
+
+ pos = Math::Vector(0.0f, 0.0f, 0.0f);
+ suppl = 0.0f;
+ type = pObj->RetType();
+
+ if ( type == OBJECT_DERRICK )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 8.0f;
+ if ( bTake && distance != 0.0f ) suppl = 4.0f;
+ if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_CONVERT )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 0.0f;
+ if ( bTake && distance != 0.0f ) suppl = 4.0f;
+ if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_RESEARCH )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 10.0f;
+ if ( bTake && distance != 0.0f ) suppl = 2.5f;
+ if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_ENERGY )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 6.0f;
+ if ( bTake && distance != 0.0f ) suppl = 6.0f;
+ if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_TOWER )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 5.0f;
+ if ( bTake && distance != 0.0f ) suppl = 4.0f;
+ if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_LABO )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 6.0f;
+ if ( bTake && distance != 0.0f ) suppl = 6.0f;
+ if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_NUCLEAR )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 22.0f;
+ if ( bTake && distance != 0.0f ) suppl = 4.0f;
+ if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_FACTORY )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 4.0f;
+ if ( bTake && distance != 0.0f ) suppl = 6.0f;
+ if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_STATION )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 4.0f;
+ if ( bTake && distance != 0.0f ) suppl = 4.0f;
+ if ( bTake ) pos.x += distance;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_REPAIR )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 4.0f;
+ if ( bTake && distance != 0.0f ) suppl = 4.0f;
+ if ( bTake ) pos.x += distance;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_DESTROYER )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 0.0f;
+ if ( bTake && distance != 0.0f ) suppl = 4.0f;
+ if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_PARA && m_physics->RetType() == TYPE_FLYING )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ if ( bTake && distance != 0.0f ) suppl = 20.0f;
+ if ( bTake ) pos.x += distance+suppl;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ suppl = 0.0f;
+ return false;
+}
+
+
+// Seeks an object too close that he must flee.
+
+bool CTaskGoto::LeakSearch(Math::Vector &pos, float &delay)
+{
+ CObject *pObj, *pObstacle;
+ Math::Vector iPos, oPos, bPos;
+ float iRadius, oRadius, bRadius, dist, min, dir;
+ int i, j;
+
+ if ( !m_physics->RetLand() ) return false; // in flight?
+
+ m_object->GetCrashSphere(0, iPos, iRadius);
+
+ min = 100000.0f;
+ bRadius = 0.0f;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue;
+ if ( !pObj->RetActif() ) continue;
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ dist = Math::DistanceProjected(oPos, iPos);
+ if ( dist < min )
+ {
+ min = dist;
+ bPos = oPos;
+ bRadius = oRadius;
+ pObstacle = pObj;
+ }
+ }
+ }
+ if ( min > iRadius+bRadius+4.0f ) return false;
+
+ m_bLeakRecede = false;
+
+ dist = 4.0f;
+ dir = 1.0f;
+ if ( pObstacle->RetType() == OBJECT_FACTORY )
+ {
+ dist = 16.0f;
+ dir = -1.0f;
+ m_bLeakRecede = true; // simply recoils
+ }
+
+ pos = bPos;
+ delay = m_physics->RetLinTimeLength(dist, dir);
+ return true;
+}
+
+
+// Calculates the force of repulsion due to obstacles.
+// The vector length rendered is between 0 and 1.
+
+void CTaskGoto::ComputeRepulse(Math::Point &dir)
+{
+#if 0
+ Math::Vector iPos, oPos;
+ Math::Point repulse;
+ CObject *pObj;
+ float dist, iRadius, oRadius;
+ int i;
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+
+ m_object->GetCrashSphere(0, iPos, iRadius);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, m_goalObject);
+ if ( dist <= 1.0f ) continue;
+
+ pObj->GetGlobalSphere(oPos, oRadius);
+ oRadius += iRadius+m_physics->RetLinStopLength()*1.1f;
+ dist = Math::DistanceProjected(oPos, iPos);
+ if ( dist <= oRadius )
+ {
+ repulse.x = iPos.x-oPos.x;
+ repulse.y = iPos.z-oPos.z;
+
+//? dist = 0.2f-(0.2f*dist/oRadius);
+ dist = powf(dist/oRadius, 2.0f);
+ dist = 0.2f-0.2f*dist;
+ repulse.x *= dist;
+ repulse.y *= dist;
+//? repulse.x /= dist;
+//? repulse.y /= dist;
+
+ dir.x += repulse.x;
+ dir.y += repulse.y;
+ }
+ }
+#else
+ ObjectType iType, oType;
+ Math::Vector iPos, oPos;
+ Math::Point repulse;
+ CObject *pObj;
+ float gDist, add, addi, fac, dist, iRadius, oRadius;
+ int i, j;
+ bool bAlien;
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+
+ // The worm goes everywhere and through everything!
+ iType = m_object->RetType();
+ if ( iType == OBJECT_WORM ) return;
+
+ m_object->GetCrashSphere(0, iPos, iRadius);
+ gDist = Math::Distance(iPos, m_goal);
+
+ add = m_physics->RetLinStopLength()*1.1f; // braking distance
+ fac = 2.0f;
+
+ if ( iType == OBJECT_MOBILEwa ||
+ iType == OBJECT_MOBILEwc ||
+ iType == OBJECT_MOBILEwi ||
+ iType == OBJECT_MOBILEws ||
+ iType == OBJECT_MOBILEwt ) // wheels?
+ {
+ add = 5.0f;
+ fac = 1.5f;
+ }
+ if ( iType == OBJECT_MOBILEta ||
+ iType == OBJECT_MOBILEtc ||
+ iType == OBJECT_MOBILEti ||
+ iType == OBJECT_MOBILEts ||
+ iType == OBJECT_MOBILEtt ||
+ iType == OBJECT_MOBILEdr ) // caterpillars?
+ {
+ add = 4.0f;
+ fac = 1.5f;
+ }
+ if ( iType == OBJECT_MOBILEfa ||
+ iType == OBJECT_MOBILEfc ||
+ iType == OBJECT_MOBILEfi ||
+ iType == OBJECT_MOBILEfs ||
+ iType == OBJECT_MOBILEft ) // flying?
+ {
+ if ( m_physics->RetLand() )
+ {
+ add = 5.0f;
+ fac = 1.5f;
+ }
+ else
+ {
+ add = 10.0f;
+ fac = 1.5f;
+ }
+ }
+ if ( iType == OBJECT_MOBILEia ||
+ iType == OBJECT_MOBILEic ||
+ iType == OBJECT_MOBILEii ||
+ iType == OBJECT_MOBILEis ||
+ iType == OBJECT_MOBILEit ) // legs?
+ {
+ add = 4.0f;
+ fac = 1.5f;
+ }
+ if ( iType == OBJECT_BEE ) // wasp?
+ {
+ if ( m_physics->RetLand() )
+ {
+ add = 3.0f;
+ fac = 1.5f;
+ }
+ else
+ {
+ add = 5.0f;
+ fac = 1.5f;
+ }
+ }
+
+ bAlien = false;
+ if ( iType == OBJECT_MOTHER ||
+ iType == OBJECT_ANT ||
+ iType == OBJECT_SPIDER ||
+ iType == OBJECT_BEE ||
+ iType == OBJECT_WORM )
+ {
+ bAlien = true;
+ }
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ oType = pObj->RetType();
+
+ if ( oType == OBJECT_WORM ) continue;
+
+ if ( bAlien )
+ {
+ if ( oType == OBJECT_STONE ||
+ oType == OBJECT_URANIUM ||
+ oType == OBJECT_METAL ||
+ oType == OBJECT_POWER ||
+ oType == OBJECT_ATOMIC ||
+ oType == OBJECT_BULLET ||
+ oType == OBJECT_BBOX ||
+ oType == OBJECT_KEYa ||
+ oType == OBJECT_KEYb ||
+ oType == OBJECT_KEYc ||
+ oType == OBJECT_KEYd ||
+ oType == OBJECT_TNT ||
+ oType == OBJECT_SCRAP1 ||
+ oType == OBJECT_SCRAP2 ||
+ oType == OBJECT_SCRAP3 ||
+ oType == OBJECT_SCRAP4 ||
+ oType == OBJECT_SCRAP5 ||
+ oType == OBJECT_BOMB ||
+ (oType >= OBJECT_PLANT0 &&
+ oType <= OBJECT_PLANT19 ) ||
+ (oType >= OBJECT_MUSHROOM0 &&
+ oType <= OBJECT_MUSHROOM9 ) ) continue;
+ }
+
+ addi = add;
+ if ( iType == OBJECT_BEE &&
+ oType == OBJECT_BEE )
+ {
+ addi = 2.0f; // between wasps, do not annoy too much
+ }
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ if ( oPos.y-oRadius > iPos.y+iRadius ) continue;
+ if ( oPos.y+oRadius < iPos.y-iRadius ) continue;
+
+ dist = Math::Distance(oPos, m_goal);
+ if ( dist <= 1.0f ) continue; // on purpose?
+
+ oRadius += iRadius+addi;
+ dist = Math::DistanceProjected(oPos, iPos);
+ if ( dist > gDist ) continue; // beyond the goal?
+ if ( dist <= oRadius )
+ {
+ repulse.x = iPos.x-oPos.x;
+ repulse.y = iPos.z-oPos.z;
+
+ dist = powf(dist/oRadius, fac);
+ dist = 0.2f-0.2f*dist;
+ repulse.x *= dist;
+ repulse.y *= dist;
+
+ dir.x += repulse.x;
+ dir.y += repulse.y;
+ }
+ }
+ }
+#endif
+}
+
+// Calculates the force of vertical repulsion according to barriers.
+// The vector length is made​between -1 and 1.
+
+void CTaskGoto::ComputeFlyingRepulse(float &dir)
+{
+ ObjectType oType;
+ Math::Vector iPos, oPos;
+ CObject *pObj;
+ float add, fac, dist, iRadius, oRadius, repulse;
+ int i, j;
+
+ m_object->GetCrashSphere(0, iPos, iRadius);
+
+ add = 0.0f;
+ fac = 1.5f;
+ dir = 0.0f;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ oType = pObj->RetType();
+
+ if ( oType == OBJECT_WORM ) continue;
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ oRadius += iRadius+add;
+ dist = Math::DistanceProjected(oPos, iPos);
+ if ( dist <= oRadius )
+ {
+ repulse = iPos.y-oPos.y;
+
+ dist = powf(dist/oRadius, fac);
+ dist = 0.2f-0.2f*dist;
+ repulse *= dist;
+
+ dir += repulse;
+ }
+ }
+ }
+
+ if ( dir < -1.0f ) dir = -1.0f;
+ if ( dir > 1.0f ) dir = 1.0f;
+}
+
+
+
+// Among all of the following, seek if there is one allowing to go directly to the crow flies.
+// If yes, skip all the unnecessary intermediate points.
+
+int CTaskGoto::BeamShortcut()
+{
+ int i;
+
+ for ( i=m_bmTotal ; i>=m_bmIndex+2 ; i-- ) // tries from the last
+ {
+ if ( BitmapTestLine(m_bmPoints[m_bmIndex], m_bmPoints[i], 0.0f, false) )
+ {
+ return i; // bingo, found
+ }
+ }
+
+ return m_bmIndex+1; // simply goes to the next
+}
+
+// That's the big start.
+
+void CTaskGoto::BeamStart()
+{
+ Math::Vector min, max;
+
+ BitmapOpen();
+ BitmapObject();
+
+ min = m_object->RetPosition(0);
+ max = m_goal;
+ if ( min.x > max.x ) Math::Swap(min.x, max.x);
+ if ( min.z > max.z ) Math::Swap(min.z, max.z);
+ min.x -= 10.0f*BM_DIM_STEP;
+ min.z -= 10.0f*BM_DIM_STEP;
+ max.x += 10.0f*BM_DIM_STEP;
+ max.z += 10.0f*BM_DIM_STEP;
+ BitmapTerrain(min, max);
+
+ if ( LeakSearch(m_leakPos, m_leakDelay) )
+ {
+ m_phase = TGP_BEAMLEAK; // must first leak
+ m_leakTime = 0.0f;
+ }
+ else
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ BeamInit();
+ m_phase = TGP_BEAMSEARCH; // will seek the path
+ }
+}
+
+// Initialization before the first BeamSearch.
+
+void CTaskGoto::BeamInit()
+{
+ int i;
+
+ for ( i=0 ; i<MAXPOINTS ; i++ )
+ {
+ m_bmIter[i] = -1;
+ }
+ m_bmStep = 0;
+}
+
+// Calculates points and passes to go from start to goal.
+// Returns:
+// ERR_OK if it's good
+// ERR_GOTO_IMPOSSIBLE if impossible
+// ERR_GOTO_ITER if aborts because too many recursions
+// ERR_CONTINUE if not done yet
+// goalRadius: distance at which we must approach the goal
+
+Error CTaskGoto::BeamSearch(const Math::Vector &start, const Math::Vector &goal,
+ float goalRadius)
+{
+ float step, len;
+ int nbIter;
+
+ m_bmStep ++;
+
+ len = Math::DistanceProjected(start, goal);
+ step = len/5.0f;
+ if ( step < BM_DIM_STEP*2.1f ) step = BM_DIM_STEP*2.1f;
+ if ( step > 20.0f ) step = 20.0f;
+ nbIter = 200; // in order not to lower the framerate
+ m_bmIterCounter = 0;
+ return BeamExplore(start, start, goal, goalRadius, 165.0f*Math::PI/180.0f, 22, step, 0, nbIter);
+}
+
+// prevPos: previous position
+// curPos: current position
+// goalPos: position that seeks to achieve
+// angle: angle to the goal we explores
+// nbDiv: number of subdivisions being done with angle
+// step length of a step
+// i number of recursions made
+// nbIter maximum number of iterations you have the right to make before temporarily interrupt
+
+Error CTaskGoto::BeamExplore(const Math::Vector &prevPos, const Math::Vector &curPos,
+ const Math::Vector &goalPos, float goalRadius,
+ float angle, int nbDiv, float step,
+ int i, int nbIter)
+{
+ Math::Vector newPos;
+ Error ret;
+ int iDiv, iClear, iLar;
+
+ iLar = 0;
+ if ( i >= MAXPOINTS ) return ERR_GOTO_ITER; // too many recursions
+
+ if ( m_bmIter[i] == -1 )
+ {
+ m_bmIter[i] = 0;
+
+ if ( i == 0 )
+ {
+ m_bmPoints[i] = curPos;
+ }
+ else
+ {
+ if ( !BitmapTestLine(prevPos, curPos, angle/nbDiv, true) ) return ERR_GOTO_IMPOSSIBLE;
+
+ m_bmPoints[i] = curPos;
+
+ if ( Math::DistanceProjected(curPos, goalPos)-goalRadius <= step )
+ {
+ if ( goalRadius == 0.0f )
+ {
+ newPos = goalPos;
+ }
+ else
+ {
+ newPos = BeamPoint(curPos, goalPos, 0, Math::DistanceProjected(curPos, goalPos)-goalRadius);
+ }
+ if ( BitmapTestLine(curPos, newPos, angle/nbDiv, false) )
+ {
+ m_bmPoints[i+1] = newPos;
+ m_bmTotal = i+1;
+ return ERR_OK;
+ }
+ }
+ }
+ }
+
+ if ( iLar >= m_bmIter[i] )
+ {
+ newPos = BeamPoint(curPos, goalPos, 0, step);
+ ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter);
+ if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret;
+ m_bmIter[i] = iLar+1;
+ for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1;
+ m_bmIterCounter ++;
+ if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE;
+ }
+ iLar ++;
+
+ for ( iDiv=1 ; iDiv<=nbDiv ; iDiv++ )
+ {
+ if ( iLar >= m_bmIter[i] )
+ {
+ newPos = BeamPoint(curPos, goalPos, angle*iDiv/nbDiv, step);
+ ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter);
+ if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret;
+ m_bmIter[i] = iLar+1;
+ for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1;
+ m_bmIterCounter ++;
+ if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE;
+ }
+ iLar ++;
+
+ if ( iLar >= m_bmIter[i] )
+ {
+ newPos = BeamPoint(curPos, goalPos, -angle*iDiv/nbDiv, step);
+ ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter);
+ if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret;
+ m_bmIter[i] = iLar+1;
+ for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1;
+ m_bmIterCounter ++;
+ if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE;
+ }
+ iLar ++;
+ }
+
+ return ERR_GOTO_IMPOSSIBLE;
+}
+
+// Is a right "start-goal". Calculates the point located at the distance "step"
+// from the point "start" and an angle "angle" with the right.
+
+Math::Vector CTaskGoto::BeamPoint(const Math::Vector &startPoint,
+ const Math::Vector &goalPoint,
+ float angle, float step)
+{
+ Math::Vector resPoint;
+ float goalAngle;
+
+ goalAngle = Math::RotateAngle(goalPoint.x-startPoint.x, goalPoint.z-startPoint.z);
+
+ resPoint.x = startPoint.x + cosf(goalAngle+angle)*step;
+ resPoint.z = startPoint.z + sinf(goalAngle+angle)*step;
+ resPoint.y = 0.0f;
+
+ return resPoint;
+}
+
+// Displays a bitmap part.
+
+void CTaskGoto::BitmapDebug(const Math::Vector &min, const Math::Vector &max,
+ const Math::Vector &start, const Math::Vector &goal)
+{
+ int minx, miny, maxx, maxy, x, y, i ,n;
+ char s[2000];
+
+ minx = (int)((min.x+1600.0f)/BM_DIM_STEP);
+ miny = (int)((min.z+1600.0f)/BM_DIM_STEP);
+ maxx = (int)((max.x+1600.0f)/BM_DIM_STEP);
+ maxy = (int)((max.z+1600.0f)/BM_DIM_STEP);
+
+ if ( minx > maxx ) Math::Swap(minx, maxx);
+ if ( miny > maxy ) Math::Swap(miny, maxy);
+
+ OutputDebugString("Bitmap :\n");
+ for ( y=miny ; y<=maxy ; y++ )
+ {
+ s[0] = 0;
+ for ( x=minx ; x<=maxx ; x++ )
+ {
+ n = -1;
+ for ( i=0 ; i<=m_bmTotal ; i++ )
+ {
+ if ( x == (int)((m_bmPoints[i].x+1600.0f)/BM_DIM_STEP) &&
+ y == (int)((m_bmPoints[i].z+1600.0f)/BM_DIM_STEP) )
+ {
+ n = i;
+ break;
+ }
+ }
+
+ if ( BitmapTestDot(0, x,y) )
+ {
+ strcat(s, "o");
+ }
+ else
+ {
+ if ( BitmapTestDot(1, x,y) )
+ {
+ strcat(s, "-");
+ }
+ else
+ {
+ strcat(s, ".");
+ }
+ }
+
+ if ( x == (int)((start.x+1600.0f)/BM_DIM_STEP) &&
+ y == (int)((start.z+1600.0f)/BM_DIM_STEP) )
+ {
+ strcat(s, "s");
+ }
+ else
+ if ( x == (int)((goal.x+1600.0f)/BM_DIM_STEP) &&
+ y == (int)((goal.z+1600.0f)/BM_DIM_STEP) )
+ {
+ strcat(s, "g");
+ }
+ else
+ if ( n != -1 )
+ {
+ char ss[2];
+ ss[0] = 'A'+n;
+ ss[1] = 0;
+ strcat(s, ss);
+ }
+ else
+ {
+ strcat(s, " ");
+ }
+ }
+ strcat(s, "\n");
+ OutputDebugString(s);
+ }
+}
+
+// Tests if a path along a straight line is possible.
+
+bool CTaskGoto::BitmapTestLine(const Math::Vector &start, const Math::Vector &goal,
+ float stepAngle, bool bSecond)
+{
+ Math::Vector pos, inc;
+ float dist, step;
+ float distNoB2;
+ int i, max, x, y;
+
+ if ( m_bmArray == 0 ) return true;
+
+ dist = Math::DistanceProjected(start, goal);
+ if ( dist == 0.0f ) return true;
+ step = BM_DIM_STEP*0.5f;
+
+ inc.x = (goal.x-start.x)*step/dist;
+ inc.z = (goal.z-start.z)*step/dist;
+
+ pos = start;
+
+ if ( bSecond )
+ {
+ x = (int)((pos.x+1600.0f)/BM_DIM_STEP);
+ y = (int)((pos.z+1600.0f)/BM_DIM_STEP);
+ BitmapSetDot(1, x, y); // puts the flag as the starting point
+ }
+
+ max = (int)(dist/step);
+ if ( max == 0 ) max = 1;
+ distNoB2 = BM_DIM_STEP*sqrtf(2.0f)/sinf(stepAngle);
+ for ( i=0 ; i<max ; i++ )
+ {
+ if ( i == max-1 )
+ {
+ pos = goal; // tests the point of arrival
+ }
+ else
+ {
+ pos.x += inc.x;
+ pos.z += inc.z;
+ }
+
+ x = (int)((pos.x+1600.0f)/BM_DIM_STEP);
+ y = (int)((pos.z+1600.0f)/BM_DIM_STEP);
+
+ if ( bSecond )
+ {
+ if ( i > 2 && BitmapTestDot(1, x, y) ) return false;
+
+ if ( step*(i+1) > distNoB2 && i < max-2 )
+ {
+ BitmapSetDot(1, x, y);
+ }
+ }
+
+ if ( BitmapTestDot(0, x, y) ) return false;
+ }
+ return true;
+}
+
+// Adds the objects in the bitmap.
+
+void CTaskGoto::BitmapObject()
+{
+ CObject *pObj;
+ ObjectType type;
+ Math::Vector iPos, oPos;
+ float iRadius, oRadius, h;
+ int i, j;
+
+ m_object->GetCrashSphere(0, iPos, iRadius);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+
+ if ( pObj == m_object ) continue;
+ if ( pObj == m_bmFretObject ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ h = m_terrain->RetFloorLevel(pObj->RetPosition(0), false);
+ if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
+ {
+ h += m_altitude;
+ }
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f ) // flying?
+ {
+ if ( oPos.y-oRadius > h+8.0f ||
+ oPos.y+oRadius < h-8.0f ) continue;
+ }
+ else // crawling?
+ {
+ if ( oPos.y-oRadius > h+8.0f ) continue;
+ }
+
+ if ( type == OBJECT_PARA ) oRadius -= 2.0f;
+ BitmapSetCircle(oPos, oRadius+iRadius+4.0f);
+ }
+ }
+}
+
+// Adds a section of land in the bitmap.
+
+void CTaskGoto::BitmapTerrain(const Math::Vector &min, const Math::Vector &max)
+{
+ int minx, miny, maxx, maxy;
+
+ minx = (int)((min.x+1600.0f)/BM_DIM_STEP);
+ miny = (int)((min.z+1600.0f)/BM_DIM_STEP);
+ maxx = (int)((max.x+1600.0f)/BM_DIM_STEP);
+ maxy = (int)((max.z+1600.0f)/BM_DIM_STEP);
+
+ BitmapTerrain(minx, miny, maxx, maxy);
+}
+
+// Adds a section of land in the bitmap.
+
+void CTaskGoto::BitmapTerrain(int minx, int miny, int maxx, int maxy)
+{
+ ObjectType type;
+ Math::Vector p;
+ float aLimit, angle, h;
+ int x, y;
+ bool bAcceptWater, bFly;
+
+ if ( minx > maxx ) Math::Swap(minx, maxx);
+ if ( miny > maxy ) Math::Swap(miny, maxy);
+
+ if ( minx < 0 ) minx = 0;
+ if ( miny < 0 ) miny = 0;
+ if ( maxx > m_bmSize-1 ) maxx = m_bmSize-1;
+ if ( maxy > m_bmSize-1 ) maxy = m_bmSize-1;
+
+ if ( minx > m_bmMinX ) minx = m_bmMinX;
+ if ( miny > m_bmMinY ) miny = m_bmMinY;
+ if ( maxx < m_bmMaxX ) maxx = m_bmMaxX;
+ if ( maxy < m_bmMaxY ) maxy = m_bmMaxY;
+
+ if ( minx >= m_bmMinX && maxx <= m_bmMaxX &&
+ miny >= m_bmMinY && maxy <= m_bmMaxY ) return;
+
+ aLimit = 20.0f*Math::PI/180.0f;
+ bAcceptWater = false;
+ bFly = false;
+
+ type = m_object->RetType();
+
+ if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEtg ) // wheels?
+ {
+ aLimit = 20.0f*Math::PI/180.0f;
+ }
+
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts ) // caterpillars?
+ {
+ aLimit = 35.0f*Math::PI/180.0f;
+ }
+
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ) // large caterpillars?
+ {
+ aLimit = 35.0f*Math::PI/180.0f;
+ }
+
+ if ( type == OBJECT_MOBILEsa ) // submarine caterpillars?
+ {
+ aLimit = 35.0f*Math::PI/180.0f;
+ bAcceptWater = true;
+ }
+
+ if ( type == OBJECT_MOBILEdr ) // designer caterpillars?
+ {
+ aLimit = 35.0f*Math::PI/180.0f;
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEft ) // flying?
+ {
+ aLimit = 15.0f*Math::PI/180.0f;
+ bFly = true;
+ }
+
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILEii ) // insect legs?
+ {
+ aLimit = 60.0f*Math::PI/180.0f;
+ }
+
+ for ( y=miny ; y<=maxy ; y++ )
+ {
+ for ( x=minx ; x<=maxx ; x++ )
+ {
+ if ( x >= m_bmMinX && x <= m_bmMaxX &&
+ y >= m_bmMinY && y <= m_bmMaxY ) continue;
+
+ p.x = x*BM_DIM_STEP-1600.0f;
+ p.z = y*BM_DIM_STEP-1600.0f;
+
+ if ( bFly ) // flying robot?
+ {
+ h = m_terrain->RetFloorLevel(p, true);
+ if ( h >= m_terrain->RetFlyingMaxHeight()-5.0f )
+ {
+ BitmapSetDot(0, x, y);
+ }
+ continue;
+ }
+
+ if ( !bAcceptWater ) // not going underwater?
+ {
+ h = m_terrain->RetFloorLevel(p, true);
+ if ( h < m_water->RetLevel()-2.0f ) // under water (*)?
+ {
+//? BitmapSetDot(0, x, y);
+ BitmapSetCircle(p, BM_DIM_STEP*1.0f);
+ continue;
+ }
+ }
+
+ angle = m_terrain->RetFineSlope(p);
+ if ( angle > aLimit )
+ {
+ BitmapSetDot(0, x, y);
+ }
+ }
+ }
+
+ m_bmMinX = minx;
+ m_bmMinY = miny;
+ m_bmMaxX = maxx;
+ m_bmMaxY = maxy; // expanded rectangular area
+}
+
+// (*) Accepts that a robot is 50cm under water, for example Tropica 3!
+
+// Opens an empty bitmap.
+
+bool CTaskGoto::BitmapOpen()
+{
+ BitmapClose();
+
+ m_bmSize = (int)(3200.0f/BM_DIM_STEP);
+ m_bmArray = (unsigned char*)malloc(m_bmSize*m_bmSize/8*2);
+ ZeroMemory(m_bmArray, m_bmSize*m_bmSize/8*2);
+
+ m_bmOffset = m_bmSize/2;
+ m_bmLine = m_bmSize/8;
+
+ m_bmMinX = m_bmSize; // non-existent rectangular area
+ m_bmMinY = m_bmSize;
+ m_bmMaxX = 0;
+ m_bmMaxY = 0;
+
+ return true;
+}
+
+// Closes the bitmap.
+
+bool CTaskGoto::BitmapClose()
+{
+ free(m_bmArray);
+ m_bmArray = 0;
+ return true;
+}
+
+// Puts a circle in the bitmap.
+
+void CTaskGoto::BitmapSetCircle(const Math::Vector &pos, float radius)
+{
+ float d, r;
+ int cx, cy, ix, iy;
+
+ cx = (int)((pos.x+1600.0f)/BM_DIM_STEP);
+ cy = (int)((pos.z+1600.0f)/BM_DIM_STEP);
+ r = radius/BM_DIM_STEP;
+
+ for ( iy=cy-(int)r ; iy<=cy+(int)r ; iy++ )
+ {
+ for ( ix=cx-(int)r ; ix<=cx+(int)r ; ix++ )
+ {
+ d = Math::Point((float)(ix-cx), (float)(iy-cy)).Length();
+ if ( d > r ) continue;
+ BitmapSetDot(0, ix, iy);
+ }
+ }
+}
+
+// Removes a circle in the bitmap.
+
+void CTaskGoto::BitmapClearCircle(const Math::Vector &pos, float radius)
+{
+ float d, r;
+ int cx, cy, ix, iy;
+
+ cx = (int)((pos.x+1600.0f)/BM_DIM_STEP);
+ cy = (int)((pos.z+1600.0f)/BM_DIM_STEP);
+ r = radius/BM_DIM_STEP;
+
+ for ( iy=cy-(int)r ; iy<=cy+(int)r ; iy++ )
+ {
+ for ( ix=cx-(int)r ; ix<=cx+(int)r ; ix++ )
+ {
+ d = Math::Point((float)(ix-cx), (float)(iy-cy)).Length();
+ if ( d > r ) continue;
+ BitmapClearDot(0, ix, iy);
+ }
+ }
+}
+
+// Makes a point in the bitmap.
+// x:y: 0..m_bmSize-1
+
+void CTaskGoto::BitmapSetDot(int rank, int x, int y)
+{
+ if ( x < 0 || x >= m_bmSize ||
+ y < 0 || y >= m_bmSize ) return;
+
+ m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] |= (1<<x%8);
+}
+
+// Removes a point in the bitmap.
+// x:y: 0..m_bmSize-1
+
+void CTaskGoto::BitmapClearDot(int rank, int x, int y)
+{
+ if ( x < 0 || x >= m_bmSize ||
+ y < 0 || y >= m_bmSize ) return;
+
+ m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] &= ~(1<<x%8);
+}
+
+// Tests a point in the bitmap.
+// x:y: 0..m_bmSize-1
+
+bool CTaskGoto::BitmapTestDot(int rank, int x, int y)
+{
+ if ( x < 0 || x >= m_bmSize ||
+ y < 0 || y >= m_bmSize ) return false;
+
+ if ( x < m_bmMinX || x > m_bmMaxX ||
+ y < m_bmMinY || y > m_bmMaxY )
+ {
+ BitmapTerrain(x-10,y-10, x+10,y+10); // remade a layer
+ }
+
+ return m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] & (1<<x%8);
+}
+
+
diff --git a/src/object/task/taskgoto.h b/src/object/task/taskgoto.h
index ae83459..1382d4c 100644
--- a/src/object/task/taskgoto.h
+++ b/src/object/task/taskgoto.h
@@ -1,157 +1,157 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskgoto.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-const int MAXPOINTS = 500;
-
-
-
-enum TaskGotoGoal
-{
- TGG_DEFAULT = -1, // default mode
- TGG_STOP = 0, // goes to destination pausing with precision
- TGG_EXPRESS = 1, // goes to destination without stopping
-};
-
-enum TaskGotoCrash
-{
- TGC_DEFAULT = -1, // default mode
- TGC_HALT = 0, // stops if collision
- TGC_RIGHTLEFT = 1, // right-left
- TGC_LEFTRIGHT = 2, // left-right
- TGC_LEFT = 3, // left
- TGC_RIGHT = 4, // right
- TGC_BEAM = 5, // algorithm "sunlight"
-};
-
-
-enum TaskGotoPhase
-{
- TGP_ADVANCE = 1, // advance
- TGP_LAND = 2, // landed
- TGP_TURN = 3, // turns to finish
- TGP_MOVE = 4, // advance to finish
- TGP_CRWAIT = 5, // waits after collision
- TGP_CRTURN = 6, // turns right after collision
- TGP_CRADVANCE = 7, // advance to the right after collision
- TGP_CLWAIT = 8, // waits after collision
- TGP_CLTURN = 9, // turns left after collision
- TGP_CLADVANCE = 10, // advance to the left after collision
- TGP_BEAMLEAK = 11, // beam: leak (leaking)
- TGP_BEAMSEARCH = 12, // beam: search
- TGP_BEAMWCOLD = 13, // beam: expects cool reactor
- TGP_BEAMUP = 14, // beam: off
- TGP_BEAMGOTO = 15, // beam: goto dot list
- TGP_BEAMDOWN = 16, // beam: landed
-};
-
-
-
-class CTaskGoto : public CTask
-{
-public:
- CTaskGoto(CInstanceManager* iMan, CObject* object);
- ~CTaskGoto();
-
- bool EventProcess(const Event &event);
-
- Error Start(Math::Vector goal, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode);
- Error IsEnded();
-
-protected:
- CObject* WormSearch(Math::Vector &impact);
- void WormFrame(float rTime);
- CObject* SearchTarget(Math::Vector pos, float margin);
- bool AdjustTarget(CObject* pObj, Math::Vector &pos, float &distance);
- bool AdjustBuilding(Math::Vector &pos, float margin, float &distance);
- bool GetHotPoint(CObject *pObj, Math::Vector &pos, bool bTake, float distance, float &suppl);
- bool LeakSearch(Math::Vector &pos, float &delay);
- void ComputeRepulse(Math::Point &dir);
- void ComputeFlyingRepulse(float &dir);
-
- int BeamShortcut();
- void BeamStart();
- void BeamInit();
- Error BeamSearch(const Math::Vector &start, const Math::Vector &goal, float goalRadius);
- Error BeamExplore(const Math::Vector &prevPos, const Math::Vector &curPos, const Math::Vector &goalPos, float goalRadius, float angle, int nbDiv, float step, int i, int nbIter);
- Math::Vector BeamPoint(const Math::Vector &startPoint, const Math::Vector &goalPoint, float angle, float step);
-
- void BitmapDebug(const Math::Vector &min, const Math::Vector &max, const Math::Vector &start, const Math::Vector &goal);
- bool BitmapTestLine(const Math::Vector &start, const Math::Vector &goal, float stepAngle, bool bSecond);
- void BitmapObject();
- void BitmapTerrain(const Math::Vector &min, const Math::Vector &max);
- void BitmapTerrain(int minx, int miny, int maxx, int maxy);
- bool BitmapOpen();
- bool BitmapClose();
- void BitmapSetCircle(const Math::Vector &pos, float radius);
- void BitmapClearCircle(const Math::Vector &pos, float radius);
- void BitmapSetDot(int rank, int x, int y);
- void BitmapClearDot(int rank, int x, int y);
- bool BitmapTestDot(int rank, int x, int y);
-
-protected:
- Math::Vector m_goal;
- Math::Vector m_goalObject;
- float m_angle;
- float m_altitude;
- TaskGotoCrash m_crashMode;
- TaskGotoGoal m_goalMode;
- TaskGotoPhase m_phase;
- int m_try;
- Error m_error;
- bool m_bTake;
- float m_stopLength; // braking distance
- float m_time;
- Math::Vector m_pos;
- bool m_bWorm;
- bool m_bApprox;
- float m_wormLastTime;
- float m_lastDistance;
-
- int m_bmSize; // width or height of the table
- int m_bmOffset; // m_bmSize/2
- int m_bmLine; // increment line m_bmSize/8
- unsigned char* m_bmArray; // bit table
- int m_bmMinX, m_bmMinY;
- int m_bmMaxX, m_bmMaxY;
- int m_bmTotal; // number of points in m_bmPoints
- int m_bmIndex; // index in m_bmPoints
- Math::Vector m_bmPoints[MAXPOINTS+2];
- char m_bmIter[MAXPOINTS+2];
- int m_bmIterCounter;
- CObject* m_bmFretObject;
- float m_bmFinalMove; // final advance distance
- float m_bmFinalDist; // effective distance to advance
- Math::Vector m_bmFinalPos; // initial position before advance
- float m_bmTimeLimit;
- int m_bmStep;
- Math::Vector m_bmWatchDogPos;
- float m_bmWatchDogTime;
- Math::Vector m_leakPos; // initial position leak
- float m_leakDelay;
- float m_leakTime;
- bool m_bLeakRecede;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskgoto.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "math/vector.h"
+
+
+
+const int MAXPOINTS = 500;
+
+
+
+enum TaskGotoGoal
+{
+ TGG_DEFAULT = -1, // default mode
+ TGG_STOP = 0, // goes to destination pausing with precision
+ TGG_EXPRESS = 1, // goes to destination without stopping
+};
+
+enum TaskGotoCrash
+{
+ TGC_DEFAULT = -1, // default mode
+ TGC_HALT = 0, // stops if collision
+ TGC_RIGHTLEFT = 1, // right-left
+ TGC_LEFTRIGHT = 2, // left-right
+ TGC_LEFT = 3, // left
+ TGC_RIGHT = 4, // right
+ TGC_BEAM = 5, // algorithm "sunlight"
+};
+
+
+enum TaskGotoPhase
+{
+ TGP_ADVANCE = 1, // advance
+ TGP_LAND = 2, // landed
+ TGP_TURN = 3, // turns to finish
+ TGP_MOVE = 4, // advance to finish
+ TGP_CRWAIT = 5, // waits after collision
+ TGP_CRTURN = 6, // turns right after collision
+ TGP_CRADVANCE = 7, // advance to the right after collision
+ TGP_CLWAIT = 8, // waits after collision
+ TGP_CLTURN = 9, // turns left after collision
+ TGP_CLADVANCE = 10, // advance to the left after collision
+ TGP_BEAMLEAK = 11, // beam: leak (leaking)
+ TGP_BEAMSEARCH = 12, // beam: search
+ TGP_BEAMWCOLD = 13, // beam: expects cool reactor
+ TGP_BEAMUP = 14, // beam: off
+ TGP_BEAMGOTO = 15, // beam: goto dot list
+ TGP_BEAMDOWN = 16, // beam: landed
+};
+
+
+
+class CTaskGoto : public CTask
+{
+public:
+ CTaskGoto(CInstanceManager* iMan, CObject* object);
+ ~CTaskGoto();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(Math::Vector goal, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode);
+ Error IsEnded();
+
+protected:
+ CObject* WormSearch(Math::Vector &impact);
+ void WormFrame(float rTime);
+ CObject* SearchTarget(Math::Vector pos, float margin);
+ bool AdjustTarget(CObject* pObj, Math::Vector &pos, float &distance);
+ bool AdjustBuilding(Math::Vector &pos, float margin, float &distance);
+ bool GetHotPoint(CObject *pObj, Math::Vector &pos, bool bTake, float distance, float &suppl);
+ bool LeakSearch(Math::Vector &pos, float &delay);
+ void ComputeRepulse(Math::Point &dir);
+ void ComputeFlyingRepulse(float &dir);
+
+ int BeamShortcut();
+ void BeamStart();
+ void BeamInit();
+ Error BeamSearch(const Math::Vector &start, const Math::Vector &goal, float goalRadius);
+ Error BeamExplore(const Math::Vector &prevPos, const Math::Vector &curPos, const Math::Vector &goalPos, float goalRadius, float angle, int nbDiv, float step, int i, int nbIter);
+ Math::Vector BeamPoint(const Math::Vector &startPoint, const Math::Vector &goalPoint, float angle, float step);
+
+ void BitmapDebug(const Math::Vector &min, const Math::Vector &max, const Math::Vector &start, const Math::Vector &goal);
+ bool BitmapTestLine(const Math::Vector &start, const Math::Vector &goal, float stepAngle, bool bSecond);
+ void BitmapObject();
+ void BitmapTerrain(const Math::Vector &min, const Math::Vector &max);
+ void BitmapTerrain(int minx, int miny, int maxx, int maxy);
+ bool BitmapOpen();
+ bool BitmapClose();
+ void BitmapSetCircle(const Math::Vector &pos, float radius);
+ void BitmapClearCircle(const Math::Vector &pos, float radius);
+ void BitmapSetDot(int rank, int x, int y);
+ void BitmapClearDot(int rank, int x, int y);
+ bool BitmapTestDot(int rank, int x, int y);
+
+protected:
+ Math::Vector m_goal;
+ Math::Vector m_goalObject;
+ float m_angle;
+ float m_altitude;
+ TaskGotoCrash m_crashMode;
+ TaskGotoGoal m_goalMode;
+ TaskGotoPhase m_phase;
+ int m_try;
+ Error m_error;
+ bool m_bTake;
+ float m_stopLength; // braking distance
+ float m_time;
+ Math::Vector m_pos;
+ bool m_bWorm;
+ bool m_bApprox;
+ float m_wormLastTime;
+ float m_lastDistance;
+
+ int m_bmSize; // width or height of the table
+ int m_bmOffset; // m_bmSize/2
+ int m_bmLine; // increment line m_bmSize/8
+ unsigned char* m_bmArray; // bit table
+ int m_bmMinX, m_bmMinY;
+ int m_bmMaxX, m_bmMaxY;
+ int m_bmTotal; // number of points in m_bmPoints
+ int m_bmIndex; // index in m_bmPoints
+ Math::Vector m_bmPoints[MAXPOINTS+2];
+ char m_bmIter[MAXPOINTS+2];
+ int m_bmIterCounter;
+ CObject* m_bmFretObject;
+ float m_bmFinalMove; // final advance distance
+ float m_bmFinalDist; // effective distance to advance
+ Math::Vector m_bmFinalPos; // initial position before advance
+ float m_bmTimeLimit;
+ int m_bmStep;
+ Math::Vector m_bmWatchDogPos;
+ float m_bmWatchDogTime;
+ Math::Vector m_leakPos; // initial position leak
+ float m_leakDelay;
+ float m_leakTime;
+ bool m_bLeakRecede;
+};
+
diff --git a/src/object/task/taskgungoal.cpp b/src/object/task/taskgungoal.cpp
index 0635b97..e259ca8 100644
--- a/src/object/task/taskgungoal.cpp
+++ b/src/object/task/taskgungoal.cpp
@@ -1,149 +1,149 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskgungoal.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskgungoal.h"
-
-#include "object/object.h"
-
-
-
-
-// Object's constructor.
-
-CTaskGunGoal::CTaskGunGoal(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskGunGoal::~CTaskGunGoal()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskGunGoal::EventProcess(const Event &event)
-{
- float dir;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
-
- if ( m_progress < 1.0f )
- {
- dir = m_initialDirV + (m_finalDirV-m_initialDirV)*m_progress;
- }
- else
- {
- dir = m_finalDirV;
- }
- m_object->SetGunGoalV(dir);
-
- if ( m_progress < 1.0f )
- {
- dir = m_initialDirH + (m_finalDirH-m_initialDirH)*m_progress;
- }
- else
- {
- dir = m_finalDirH;
- }
- m_object->SetGunGoalH(dir);
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskGunGoal::Start(float dirV, float dirH)
-{
- float speedV, speedH;
- int i;
-
- m_initialDirV = m_object->RetGunGoalV();
- m_object->SetGunGoalV(dirV);
- m_finalDirV = m_object->RetGunGoalV(); // possible direction
- m_object->SetGunGoalV(m_initialDirV); // gives initial direction
-
- if ( m_finalDirV == m_initialDirV )
- {
- speedV = 100.0f;
- }
- else
- {
- speedV = 1.0f/(fabs(m_finalDirV-m_initialDirV)*1.0f);
- }
-
- m_initialDirH = m_object->RetGunGoalH();
- m_object->SetGunGoalH(dirH);
- m_finalDirH = m_object->RetGunGoalH(); // possible direction
- m_object->SetGunGoalH(m_initialDirH); // gives initial direction
-
- if ( m_finalDirH == m_initialDirH )
- {
- speedH = 100.0f;
- }
- else
- {
- speedH = 1.0f/(fabs(m_finalDirH-m_initialDirH)*1.0f);
- }
-
- m_speed = Math::Min(speedV, speedH);
-
- if ( m_finalDirV != m_initialDirV ||
- m_finalDirH != m_initialDirH )
- {
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.3f, 1.5f, true);
- m_sound->AddEnvelope(i, 0.3f, 1.5f, 1.0f/m_speed, SOPER_STOP);
- }
-
- m_progress = 0.0f;
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskGunGoal::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
-
- if ( m_initialDirV == m_finalDirV &&
- m_initialDirH == m_finalDirH ) return ERR_STOP;
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_object->SetGunGoalV(m_finalDirV);
- m_object->SetGunGoalH(m_finalDirH);
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskGunGoal::Abort()
-{
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskgungoal.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskgungoal.h"
+
+#include "object/object.h"
+
+
+
+
+// Object's constructor.
+
+CTaskGunGoal::CTaskGunGoal(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+}
+
+// Object's destructor.
+
+CTaskGunGoal::~CTaskGunGoal()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskGunGoal::EventProcess(const Event &event)
+{
+ float dir;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+
+ if ( m_progress < 1.0f )
+ {
+ dir = m_initialDirV + (m_finalDirV-m_initialDirV)*m_progress;
+ }
+ else
+ {
+ dir = m_finalDirV;
+ }
+ m_object->SetGunGoalV(dir);
+
+ if ( m_progress < 1.0f )
+ {
+ dir = m_initialDirH + (m_finalDirH-m_initialDirH)*m_progress;
+ }
+ else
+ {
+ dir = m_finalDirH;
+ }
+ m_object->SetGunGoalH(dir);
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskGunGoal::Start(float dirV, float dirH)
+{
+ float speedV, speedH;
+ int i;
+
+ m_initialDirV = m_object->RetGunGoalV();
+ m_object->SetGunGoalV(dirV);
+ m_finalDirV = m_object->RetGunGoalV(); // possible direction
+ m_object->SetGunGoalV(m_initialDirV); // gives initial direction
+
+ if ( m_finalDirV == m_initialDirV )
+ {
+ speedV = 100.0f;
+ }
+ else
+ {
+ speedV = 1.0f/(fabs(m_finalDirV-m_initialDirV)*1.0f);
+ }
+
+ m_initialDirH = m_object->RetGunGoalH();
+ m_object->SetGunGoalH(dirH);
+ m_finalDirH = m_object->RetGunGoalH(); // possible direction
+ m_object->SetGunGoalH(m_initialDirH); // gives initial direction
+
+ if ( m_finalDirH == m_initialDirH )
+ {
+ speedH = 100.0f;
+ }
+ else
+ {
+ speedH = 1.0f/(fabs(m_finalDirH-m_initialDirH)*1.0f);
+ }
+
+ m_speed = Math::Min(speedV, speedH);
+
+ if ( m_finalDirV != m_initialDirV ||
+ m_finalDirH != m_initialDirH )
+ {
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.3f, 1.5f, true);
+ m_sound->AddEnvelope(i, 0.3f, 1.5f, 1.0f/m_speed, SOPER_STOP);
+ }
+
+ m_progress = 0.0f;
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskGunGoal::IsEnded()
+{
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+
+ if ( m_initialDirV == m_finalDirV &&
+ m_initialDirH == m_finalDirH ) return ERR_STOP;
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_object->SetGunGoalV(m_finalDirV);
+ m_object->SetGunGoalH(m_finalDirH);
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskGunGoal::Abort()
+{
+ return true;
+}
+
diff --git a/src/object/task/taskgungoal.h b/src/object/task/taskgungoal.h
index 4759cbc..0c063d1 100644
--- a/src/object/task/taskgungoal.h
+++ b/src/object/task/taskgungoal.h
@@ -1,48 +1,48 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskgungoal.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskGunGoal : public CTask
-{
-public:
- CTaskGunGoal(CInstanceManager* iMan, CObject* object);
- ~CTaskGunGoal();
-
- bool EventProcess(const Event &event);
-
- Error Start(float dirV, float dirH);
- Error IsEnded();
- bool Abort();
-
-protected:
-
-protected:
- float m_progress;
- float m_speed;
- float m_initialDirV; // initial direction
- float m_finalDirV; // direction to reach
- float m_initialDirH; // initial direction
- float m_finalDirH; // direction to reach
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskgungoal.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+
+
+
+class CTaskGunGoal : public CTask
+{
+public:
+ CTaskGunGoal(CInstanceManager* iMan, CObject* object);
+ ~CTaskGunGoal();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(float dirV, float dirH);
+ Error IsEnded();
+ bool Abort();
+
+protected:
+
+protected:
+ float m_progress;
+ float m_speed;
+ float m_initialDirV; // initial direction
+ float m_finalDirV; // direction to reach
+ float m_initialDirH; // initial direction
+ float m_finalDirH; // direction to reach
+};
+
diff --git a/src/object/task/taskinfo.cpp b/src/object/task/taskinfo.cpp
index cfcbe93..6d1f486 100644
--- a/src/object/task/taskinfo.cpp
+++ b/src/object/task/taskinfo.cpp
@@ -1,219 +1,219 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskinfo.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskinfo.h"
-
-#include "common/iman.h"
-#include "old/particule.h"
-#include "object/auto/autoinfo.h"
-
-
-
-
-
-// Object's constructor.
-
-CTaskInfo::CTaskInfo(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskInfo::~CTaskInfo()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskInfo::EventProcess(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_progress += event.rTime*m_speed; // other advance
- m_time += event.rTime;
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskInfo::Start(char *name, float value, float power, bool bSend)
-{
- CObject* pInfo;
- CAutoInfo* pAuto;
- Math::Vector pos, goal;
- Info info;
- int i, total, op;
-
- m_bError = true;
- m_object->SetInfoReturn(NAN);
-
- pInfo = SearchInfo(power); // seeks terminal
- if ( pInfo == 0 )
- {
- return ERR_INFO_NULL;
- }
-
- pAuto = (CAutoInfo*)pInfo->RetAuto();
- if ( pAuto == 0 )
- {
- return ERR_INFO_NULL;
- }
-
- op = 1; // transmission impossible
- if ( bSend ) // send?
- {
- total = pInfo->RetInfoTotal();
- for ( i=0 ; i<total ; i++ )
- {
- info = pInfo->RetInfo(i);
- if ( strcmp(info.name, name) == 0 )
- {
- info.value = value;
- pInfo->SetInfo(i, info);
- break;
- }
- }
- if ( i == total )
- {
- if ( total < OBJECTMAXINFO )
- {
- strcpy(info.name, name);
- info.value = value;
- pInfo->SetInfo(total, info);
- op = 2; // start of reception (for terminal)
- }
- }
- else
- {
- op = 2; // start of reception (for terminal)
- }
- }
- else // receive?
- {
- total = pInfo->RetInfoTotal();
- for ( i=0 ; i<total ; i++ )
- {
- info = pInfo->RetInfo(i);
- if ( strcmp(info.name, name) == 0 )
- {
- m_object->SetInfoReturn(info.value);
- break;
- }
- }
- if ( i < total )
- {
- op = 0; // beginning of transmission (for terminal)
- }
- }
-
- pAuto->Start(op);
-
- if ( op == 0 ) // transmission?
- {
- pos = pInfo->RetPosition(0);
- pos.y += 9.5f;
- goal = m_object->RetPosition(0);
- goal.y += 4.0f;
- m_particule->CreateRay(pos, goal, PARTIRAY3, Math::Point(2.0f, 2.0f), 1.0f);
- }
- if ( op == 2 ) // reception?
- {
- goal = pInfo->RetPosition(0);
- goal.y += 9.5f;
- pos = m_object->RetPosition(0);
- pos.y += 4.0f;
- m_particule->CreateRay(pos, goal, PARTIRAY3, Math::Point(2.0f, 2.0f), 1.0f);
- }
-
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- m_time = 0.0f;
-
- m_bError = false; // ok
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskInfo::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskInfo::Abort()
-{
- return true;
-}
-
-
-// Seeks the nearest information terminal.
-
-CObject* CTaskInfo::SearchInfo(float power)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float dist, min;
- int i;
-
- iPos = m_object->RetPosition(0);
-
- min = 100000.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_INFO ) continue;
-
- if ( !pObj->RetActif() ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, iPos);
- if ( dist > power ) continue; // too far?
- if ( dist < min )
- {
- min = dist;
- pBest = pObj;
- }
- }
-
- return pBest;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskinfo.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskinfo.h"
+
+#include "common/iman.h"
+#include "old/particule.h"
+#include "object/auto/autoinfo.h"
+
+
+
+
+
+// Object's constructor.
+
+CTaskInfo::CTaskInfo(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+}
+
+// Object's destructor.
+
+CTaskInfo::~CTaskInfo()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskInfo::EventProcess(const Event &event)
+{
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ m_progress += event.rTime*m_speed; // other advance
+ m_time += event.rTime;
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskInfo::Start(char *name, float value, float power, bool bSend)
+{
+ CObject* pInfo;
+ CAutoInfo* pAuto;
+ Math::Vector pos, goal;
+ Info info;
+ int i, total, op;
+
+ m_bError = true;
+ m_object->SetInfoReturn(NAN);
+
+ pInfo = SearchInfo(power); // seeks terminal
+ if ( pInfo == 0 )
+ {
+ return ERR_INFO_NULL;
+ }
+
+ pAuto = (CAutoInfo*)pInfo->RetAuto();
+ if ( pAuto == 0 )
+ {
+ return ERR_INFO_NULL;
+ }
+
+ op = 1; // transmission impossible
+ if ( bSend ) // send?
+ {
+ total = pInfo->RetInfoTotal();
+ for ( i=0 ; i<total ; i++ )
+ {
+ info = pInfo->RetInfo(i);
+ if ( strcmp(info.name, name) == 0 )
+ {
+ info.value = value;
+ pInfo->SetInfo(i, info);
+ break;
+ }
+ }
+ if ( i == total )
+ {
+ if ( total < OBJECTMAXINFO )
+ {
+ strcpy(info.name, name);
+ info.value = value;
+ pInfo->SetInfo(total, info);
+ op = 2; // start of reception (for terminal)
+ }
+ }
+ else
+ {
+ op = 2; // start of reception (for terminal)
+ }
+ }
+ else // receive?
+ {
+ total = pInfo->RetInfoTotal();
+ for ( i=0 ; i<total ; i++ )
+ {
+ info = pInfo->RetInfo(i);
+ if ( strcmp(info.name, name) == 0 )
+ {
+ m_object->SetInfoReturn(info.value);
+ break;
+ }
+ }
+ if ( i < total )
+ {
+ op = 0; // beginning of transmission (for terminal)
+ }
+ }
+
+ pAuto->Start(op);
+
+ if ( op == 0 ) // transmission?
+ {
+ pos = pInfo->RetPosition(0);
+ pos.y += 9.5f;
+ goal = m_object->RetPosition(0);
+ goal.y += 4.0f;
+ m_particule->CreateRay(pos, goal, PARTIRAY3, Math::Point(2.0f, 2.0f), 1.0f);
+ }
+ if ( op == 2 ) // reception?
+ {
+ goal = pInfo->RetPosition(0);
+ goal.y += 9.5f;
+ pos = m_object->RetPosition(0);
+ pos.y += 4.0f;
+ m_particule->CreateRay(pos, goal, PARTIRAY3, Math::Point(2.0f, 2.0f), 1.0f);
+ }
+
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ m_time = 0.0f;
+
+ m_bError = false; // ok
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskInfo::IsEnded()
+{
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+ m_progress = 0.0f;
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskInfo::Abort()
+{
+ return true;
+}
+
+
+// Seeks the nearest information terminal.
+
+CObject* CTaskInfo::SearchInfo(float power)
+{
+ CObject *pObj, *pBest;
+ Math::Vector iPos, oPos;
+ ObjectType type;
+ float dist, min;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+
+ min = 100000.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_INFO ) continue;
+
+ if ( !pObj->RetActif() ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, iPos);
+ if ( dist > power ) continue; // too far?
+ if ( dist < min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+
+ return pBest;
+}
+
diff --git a/src/object/task/taskinfo.h b/src/object/task/taskinfo.h
index 8f6e4f2..21a4392 100644
--- a/src/object/task/taskinfo.h
+++ b/src/object/task/taskinfo.h
@@ -1,47 +1,47 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskinfo.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskInfo : public CTask
-{
-public:
- CTaskInfo(CInstanceManager* iMan, CObject* object);
- ~CTaskInfo();
-
- bool EventProcess(const Event &event);
-
- Error Start(char *name, float value, float power, bool bSend);
- Error IsEnded();
- bool Abort();
-
-protected:
- CObject* SearchInfo(float power);
-
-protected:
- float m_progress;
- float m_speed;
- float m_time;
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskinfo.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+
+
+
+class CTaskInfo : public CTask
+{
+public:
+ CTaskInfo(CInstanceManager* iMan, CObject* object);
+ ~CTaskInfo();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(char *name, float value, float power, bool bSend);
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ CObject* SearchInfo(float power);
+
+protected:
+ float m_progress;
+ float m_speed;
+ float m_time;
+ bool m_bError;
+};
+
diff --git a/src/object/task/taskmanager.cpp b/src/object/task/taskmanager.cpp
index f6f8b97..d81fb5b 100644
--- a/src/object/task/taskmanager.cpp
+++ b/src/object/task/taskmanager.cpp
@@ -1,278 +1,278 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskmanager.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskmanager.h"
-
-#include "common/iman.h"
-#include "object/task/taskwait.h"
-#include "object/task/taskadvance.h"
-#include "object/task/taskturn.h"
-#include "object/task/tasktake.h"
-#include "object/task/taskbuild.h"
-#include "object/task/tasksearch.h"
-#include "object/task/taskterraform.h"
-#include "object/task/taskpen.h"
-#include "object/task/taskrecover.h"
-#include "object/task/taskinfo.h"
-#include "object/task/taskfire.h"
-#include "object/task/taskfireant.h"
-#include "object/task/taskgungoal.h"
-#include "object/task/taskspiderexplo.h"
-#include "object/task/taskreset.h"
-
-
-
-
-// Object's constructor.
-
-CTaskManager::CTaskManager(CInstanceManager* iMan, CObject* object)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_TASKMANAGER, this, 100);
-
- m_task = 0;
- m_object = object;
- m_bPilot = false;
-}
-
-// Object's destructor.
-
-CTaskManager::~CTaskManager()
-{
- delete m_task;
-}
-
-
-
-// Waits for a while.
-
-Error CTaskManager::StartTaskWait(float time)
-{
- m_task = new CTaskWait(m_iMan, m_object);
- return ((CTaskWait*)m_task)->Start(time);
-}
-
-// Advance straight ahead a certain distance.
-
-Error CTaskManager::StartTaskAdvance(float length)
-{
- m_task = new CTaskAdvance(m_iMan, m_object);
- return ((CTaskAdvance*)m_task)->Start(length);
-}
-
-// Turns through an certain angle.
-
-Error CTaskManager::StartTaskTurn(float angle)
-{
- m_task = new CTaskTurn(m_iMan, m_object);
- return ((CTaskTurn*)m_task)->Start(angle);
-}
-
-// Reaches a given position.
-
-Error CTaskManager::StartTaskGoto(Math::Vector pos, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode)
-{
- m_task = new CTaskGoto(m_iMan, m_object);
- return ((CTaskGoto*)m_task)->Start(pos, altitude, goalMode, crashMode);
-}
-
-// Move the manipulator arm.
-
-Error CTaskManager::StartTaskTake()
-{
- m_task = new CTaskTake(m_iMan, m_object);
- return ((CTaskTake*)m_task)->Start();
-}
-
-// Move the manipulator arm.
-
-Error CTaskManager::StartTaskManip(TaskManipOrder order, TaskManipArm arm)
-{
- m_task = new CTaskManip(m_iMan, m_object);
- return ((CTaskManip*)m_task)->Start(order, arm);
-}
-
-// Puts or removes a flag.
-
-Error CTaskManager::StartTaskFlag(TaskFlagOrder order, int rank)
-{
- m_task = new CTaskFlag(m_iMan, m_object);
- return ((CTaskFlag*)m_task)->Start(order, rank);
-}
-
-// Builds a building.
-
-Error CTaskManager::StartTaskBuild(ObjectType type)
-{
- m_task = new CTaskBuild(m_iMan, m_object);
- return ((CTaskBuild*)m_task)->Start(type);
-}
-
-// Probe the ground.
-
-Error CTaskManager::StartTaskSearch()
-{
- m_task = new CTaskSearch(m_iMan, m_object);
- return ((CTaskSearch*)m_task)->Start();
-}
-
-// Reads an information terminal.
-
-Error CTaskManager::StartTaskInfo(char *name, float value, float power, bool bSend)
-{
- m_task = new CTaskInfo(m_iMan, m_object);
- return ((CTaskInfo*)m_task)->Start(name, value, power, bSend);
-}
-
-// Terraforms the ground.
-
-Error CTaskManager::StartTaskTerraform()
-{
- m_task = new CTaskTerraform(m_iMan, m_object);
- return ((CTaskTerraform*)m_task)->Start();
-}
-
-// Changes the pencil.
-
-Error CTaskManager::StartTaskPen(bool bDown, int color)
-{
- m_task = new CTaskPen(m_iMan, m_object);
- return ((CTaskPen*)m_task)->Start(bDown, color);
-}
-
-// Recovers a ruin.
-
-Error CTaskManager::StartTaskRecover()
-{
- m_task = new CTaskRecover(m_iMan, m_object);
- return ((CTaskRecover*)m_task)->Start();
-}
-
-// Deploys the shield.
-
-Error CTaskManager::StartTaskShield(TaskShieldMode mode, float delay)
-{
- if ( mode == TSM_UP )
- {
- m_task = new CTaskShield(m_iMan, m_object);
- return ((CTaskShield*)m_task)->Start(mode, delay);
- }
- if ( mode == TSM_DOWN && m_task != 0 )
- {
- return ((CTaskShield*)m_task)->Start(mode, delay);
- }
- if ( mode == TSM_UPDATE && m_task != 0 )
- {
- return ((CTaskShield*)m_task)->Start(mode, delay);
- }
- return ERR_GENERIC;
-}
-
-// Shoots.
-
-Error CTaskManager::StartTaskFire(float delay)
-{
- m_bPilot = true;
- m_task = new CTaskFire(m_iMan, m_object);
- return ((CTaskFire*)m_task)->Start(delay);
-}
-
-// Shoots with the ant.
-
-Error CTaskManager::StartTaskFireAnt(Math::Vector impact)
-{
- m_task = new CTaskFireAnt(m_iMan, m_object);
- return ((CTaskFireAnt*)m_task)->Start(impact);
-}
-
-// Adjusts higher.
-
-Error CTaskManager::StartTaskGunGoal(float dirV, float dirH)
-{
- m_task = new CTaskGunGoal(m_iMan, m_object);
- return ((CTaskGunGoal*)m_task)->Start(dirV, dirH);
-}
-
-// Suicide of the spider.
-
-Error CTaskManager::StartTaskSpiderExplo()
-{
- m_task = new CTaskSpiderExplo(m_iMan, m_object);
- return ((CTaskSpiderExplo*)m_task)->Start();
-}
-
-// Reset.
-
-Error CTaskManager::StartTaskReset(Math::Vector goal, Math::Vector angle)
-{
- m_task = new CTaskReset(m_iMan, m_object);
- return ((CTaskReset*)m_task)->Start(goal, angle);
-}
-
-
-
-
-
-// Management of an event.
-
-bool CTaskManager::EventProcess(const Event &event)
-{
- if ( m_task == 0 ) return false;
- return m_task->EventProcess(event);
-}
-
-
-// Indicates whether the action is finished.
-
-Error CTaskManager::IsEnded()
-{
- if ( m_task == 0 ) return ERR_GENERIC;
- return m_task->IsEnded();
-}
-
-
-// Indicates whether the action is pending.
-
-bool CTaskManager::IsBusy()
-{
- if ( m_task == 0 ) return false;
- return m_task->IsBusy();
-}
-
-
-// Indicates whether it is possible to control the robot
-// during the execution of the current task.
-
-bool CTaskManager::IsPilot()
-{
- return m_bPilot;
-}
-
-
-// Suddenly ends the current action.
-
-bool CTaskManager::Abort()
-{
- if ( m_task == 0 ) return false;
- return m_task->Abort();
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskmanager.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskmanager.h"
+
+#include "common/iman.h"
+#include "object/task/taskwait.h"
+#include "object/task/taskadvance.h"
+#include "object/task/taskturn.h"
+#include "object/task/tasktake.h"
+#include "object/task/taskbuild.h"
+#include "object/task/tasksearch.h"
+#include "object/task/taskterraform.h"
+#include "object/task/taskpen.h"
+#include "object/task/taskrecover.h"
+#include "object/task/taskinfo.h"
+#include "object/task/taskfire.h"
+#include "object/task/taskfireant.h"
+#include "object/task/taskgungoal.h"
+#include "object/task/taskspiderexplo.h"
+#include "object/task/taskreset.h"
+
+
+
+
+// Object's constructor.
+
+CTaskManager::CTaskManager(CInstanceManager* iMan, CObject* object)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_TASKMANAGER, this, 100);
+
+ m_task = 0;
+ m_object = object;
+ m_bPilot = false;
+}
+
+// Object's destructor.
+
+CTaskManager::~CTaskManager()
+{
+ delete m_task;
+}
+
+
+
+// Waits for a while.
+
+Error CTaskManager::StartTaskWait(float time)
+{
+ m_task = new CTaskWait(m_iMan, m_object);
+ return ((CTaskWait*)m_task)->Start(time);
+}
+
+// Advance straight ahead a certain distance.
+
+Error CTaskManager::StartTaskAdvance(float length)
+{
+ m_task = new CTaskAdvance(m_iMan, m_object);
+ return ((CTaskAdvance*)m_task)->Start(length);
+}
+
+// Turns through an certain angle.
+
+Error CTaskManager::StartTaskTurn(float angle)
+{
+ m_task = new CTaskTurn(m_iMan, m_object);
+ return ((CTaskTurn*)m_task)->Start(angle);
+}
+
+// Reaches a given position.
+
+Error CTaskManager::StartTaskGoto(Math::Vector pos, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode)
+{
+ m_task = new CTaskGoto(m_iMan, m_object);
+ return ((CTaskGoto*)m_task)->Start(pos, altitude, goalMode, crashMode);
+}
+
+// Move the manipulator arm.
+
+Error CTaskManager::StartTaskTake()
+{
+ m_task = new CTaskTake(m_iMan, m_object);
+ return ((CTaskTake*)m_task)->Start();
+}
+
+// Move the manipulator arm.
+
+Error CTaskManager::StartTaskManip(TaskManipOrder order, TaskManipArm arm)
+{
+ m_task = new CTaskManip(m_iMan, m_object);
+ return ((CTaskManip*)m_task)->Start(order, arm);
+}
+
+// Puts or removes a flag.
+
+Error CTaskManager::StartTaskFlag(TaskFlagOrder order, int rank)
+{
+ m_task = new CTaskFlag(m_iMan, m_object);
+ return ((CTaskFlag*)m_task)->Start(order, rank);
+}
+
+// Builds a building.
+
+Error CTaskManager::StartTaskBuild(ObjectType type)
+{
+ m_task = new CTaskBuild(m_iMan, m_object);
+ return ((CTaskBuild*)m_task)->Start(type);
+}
+
+// Probe the ground.
+
+Error CTaskManager::StartTaskSearch()
+{
+ m_task = new CTaskSearch(m_iMan, m_object);
+ return ((CTaskSearch*)m_task)->Start();
+}
+
+// Reads an information terminal.
+
+Error CTaskManager::StartTaskInfo(char *name, float value, float power, bool bSend)
+{
+ m_task = new CTaskInfo(m_iMan, m_object);
+ return ((CTaskInfo*)m_task)->Start(name, value, power, bSend);
+}
+
+// Terraforms the ground.
+
+Error CTaskManager::StartTaskTerraform()
+{
+ m_task = new CTaskTerraform(m_iMan, m_object);
+ return ((CTaskTerraform*)m_task)->Start();
+}
+
+// Changes the pencil.
+
+Error CTaskManager::StartTaskPen(bool bDown, int color)
+{
+ m_task = new CTaskPen(m_iMan, m_object);
+ return ((CTaskPen*)m_task)->Start(bDown, color);
+}
+
+// Recovers a ruin.
+
+Error CTaskManager::StartTaskRecover()
+{
+ m_task = new CTaskRecover(m_iMan, m_object);
+ return ((CTaskRecover*)m_task)->Start();
+}
+
+// Deploys the shield.
+
+Error CTaskManager::StartTaskShield(TaskShieldMode mode, float delay)
+{
+ if ( mode == TSM_UP )
+ {
+ m_task = new CTaskShield(m_iMan, m_object);
+ return ((CTaskShield*)m_task)->Start(mode, delay);
+ }
+ if ( mode == TSM_DOWN && m_task != 0 )
+ {
+ return ((CTaskShield*)m_task)->Start(mode, delay);
+ }
+ if ( mode == TSM_UPDATE && m_task != 0 )
+ {
+ return ((CTaskShield*)m_task)->Start(mode, delay);
+ }
+ return ERR_GENERIC;
+}
+
+// Shoots.
+
+Error CTaskManager::StartTaskFire(float delay)
+{
+ m_bPilot = true;
+ m_task = new CTaskFire(m_iMan, m_object);
+ return ((CTaskFire*)m_task)->Start(delay);
+}
+
+// Shoots with the ant.
+
+Error CTaskManager::StartTaskFireAnt(Math::Vector impact)
+{
+ m_task = new CTaskFireAnt(m_iMan, m_object);
+ return ((CTaskFireAnt*)m_task)->Start(impact);
+}
+
+// Adjusts higher.
+
+Error CTaskManager::StartTaskGunGoal(float dirV, float dirH)
+{
+ m_task = new CTaskGunGoal(m_iMan, m_object);
+ return ((CTaskGunGoal*)m_task)->Start(dirV, dirH);
+}
+
+// Suicide of the spider.
+
+Error CTaskManager::StartTaskSpiderExplo()
+{
+ m_task = new CTaskSpiderExplo(m_iMan, m_object);
+ return ((CTaskSpiderExplo*)m_task)->Start();
+}
+
+// Reset.
+
+Error CTaskManager::StartTaskReset(Math::Vector goal, Math::Vector angle)
+{
+ m_task = new CTaskReset(m_iMan, m_object);
+ return ((CTaskReset*)m_task)->Start(goal, angle);
+}
+
+
+
+
+
+// Management of an event.
+
+bool CTaskManager::EventProcess(const Event &event)
+{
+ if ( m_task == 0 ) return false;
+ return m_task->EventProcess(event);
+}
+
+
+// Indicates whether the action is finished.
+
+Error CTaskManager::IsEnded()
+{
+ if ( m_task == 0 ) return ERR_GENERIC;
+ return m_task->IsEnded();
+}
+
+
+// Indicates whether the action is pending.
+
+bool CTaskManager::IsBusy()
+{
+ if ( m_task == 0 ) return false;
+ return m_task->IsBusy();
+}
+
+
+// Indicates whether it is possible to control the robot
+// during the execution of the current task.
+
+bool CTaskManager::IsPilot()
+{
+ return m_bPilot;
+}
+
+
+// Suddenly ends the current action.
+
+bool CTaskManager::Abort()
+{
+ if ( m_task == 0 ) return false;
+ return m_task->Abort();
+}
+
+
diff --git a/src/object/task/taskmanager.h b/src/object/task/taskmanager.h
index 30b6c81..14fc276 100644
--- a/src/object/task/taskmanager.h
+++ b/src/object/task/taskmanager.h
@@ -1,71 +1,71 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskmanager.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-#include "object/task/taskmanip.h"
-#include "object/task/taskgoto.h"
-#include "object/task/taskshield.h"
-#include "object/task/taskflag.h"
-
-
-
-class CTaskManager
-{
-public:
- CTaskManager(CInstanceManager* iMan, CObject* object);
- ~CTaskManager();
-
- Error StartTaskWait(float time);
- Error StartTaskAdvance(float length);
- Error StartTaskTurn(float angle);
- Error StartTaskGoto(Math::Vector pos, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode);
- Error StartTaskTake();
- Error StartTaskManip(TaskManipOrder order, TaskManipArm arm);
- Error StartTaskFlag(TaskFlagOrder order, int rank);
- Error StartTaskBuild(ObjectType type);
- Error StartTaskSearch();
- Error StartTaskInfo(char *name, float value, float power, bool bSend);
- Error StartTaskTerraform();
- Error StartTaskPen(bool bDown, int color);
- Error StartTaskRecover();
- Error StartTaskShield(TaskShieldMode mode, float delay);
- Error StartTaskFire(float delay);
- Error StartTaskFireAnt(Math::Vector impact);
- Error StartTaskGunGoal(float dirV, float dirH);
- Error StartTaskSpiderExplo();
- Error StartTaskReset(Math::Vector goal, Math::Vector angle);
-
- bool EventProcess(const Event &event);
- Error IsEnded();
- bool IsBusy();
- bool IsPilot();
- bool Abort();
-
-protected:
-
-protected:
- CInstanceManager* m_iMan;
- CTask* m_task;
- CObject* m_object;
- bool m_bPilot;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskmanager.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "object/object.h"
+#include "object/task/taskmanip.h"
+#include "object/task/taskgoto.h"
+#include "object/task/taskshield.h"
+#include "object/task/taskflag.h"
+
+
+
+class CTaskManager
+{
+public:
+ CTaskManager(CInstanceManager* iMan, CObject* object);
+ ~CTaskManager();
+
+ Error StartTaskWait(float time);
+ Error StartTaskAdvance(float length);
+ Error StartTaskTurn(float angle);
+ Error StartTaskGoto(Math::Vector pos, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode);
+ Error StartTaskTake();
+ Error StartTaskManip(TaskManipOrder order, TaskManipArm arm);
+ Error StartTaskFlag(TaskFlagOrder order, int rank);
+ Error StartTaskBuild(ObjectType type);
+ Error StartTaskSearch();
+ Error StartTaskInfo(char *name, float value, float power, bool bSend);
+ Error StartTaskTerraform();
+ Error StartTaskPen(bool bDown, int color);
+ Error StartTaskRecover();
+ Error StartTaskShield(TaskShieldMode mode, float delay);
+ Error StartTaskFire(float delay);
+ Error StartTaskFireAnt(Math::Vector impact);
+ Error StartTaskGunGoal(float dirV, float dirH);
+ Error StartTaskSpiderExplo();
+ Error StartTaskReset(Math::Vector goal, Math::Vector angle);
+
+ bool EventProcess(const Event &event);
+ Error IsEnded();
+ bool IsBusy();
+ bool IsPilot();
+ bool Abort();
+
+protected:
+
+protected:
+ CInstanceManager* m_iMan;
+ CTask* m_task;
+ CObject* m_object;
+ bool m_bPilot;
+};
+
diff --git a/src/object/task/taskmanip.cpp b/src/object/task/taskmanip.cpp
index 636031b..456f274 100644
--- a/src/object/task/taskmanip.cpp
+++ b/src/object/task/taskmanip.cpp
@@ -1,1383 +1,1383 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskmanip.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskmanip.h"
-
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "old/pyro.h"
-#include "math/geometry.h"
-#include "object/robotmain.h"
-#include "physics/physics.h"
-
-
-//?const float MARGIN_FRONT = 2.0f;
-//?const float MARGIN_BACK = 2.0f;
-//?const float MARGIN_FRIEND = 2.0f;
-//?const float MARGIN_BEE = 5.0f;
-const float MARGIN_FRONT = 4.0f; //OK 1.9
-const float MARGIN_BACK = 4.0f; //OK 1.9
-const float MARGIN_FRIEND = 4.0f; //OK 1.9
-const float MARGIN_BEE = 5.0f; //OK 1.9
-
-
-
-
-// Object's constructor.
-
-CTaskManip::CTaskManip(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_arm = TMA_NEUTRAL;
- m_hand = TMH_OPEN;
-}
-
-// Object's destructor.
-
-CTaskManip::~CTaskManip()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskManip::EventProcess(const Event &event)
-{
- Math::Vector pos;
- float angle, a, g, cirSpeed, progress;
- int i;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- if ( m_bBee ) // bee?
- {
- return true;
- }
-
- if ( m_bTurn ) // preliminary rotation?
- {
- a = m_object->RetAngleY(0);
- g = m_angle;
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( m_physics->RetType() == TYPE_FLYING ) // flying on the ground?
- {
- cirSpeed *= 4.0f; // more fishing
- }
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- return true;
- }
-
- if ( m_move != 0 ) // preliminary advance?
- {
- m_timeLimit -= event.rTime;
- m_physics->SetMotorSpeedX(m_move); // forward/backward
- return true;
- }
-
- m_progress += event.rTime*m_speed; // others advance
- progress = m_progress;
- if ( progress > 1.0f ) progress = 1.0f;
-
- if ( m_bSubm ) // submarine?
- {
- if ( m_order == TMO_GRAB )
- {
- if ( m_step == 0 ) // fall?
- {
- pos = m_object->RetPosition(1);
- pos.y = 3.0f-progress*2.0f;
- m_object->SetPosition(1, pos);
- }
- if ( m_step == 1 ) // farm?
- {
- pos = m_object->RetPosition(2);
- pos.z = -1.5f+progress*0.5f;
- m_object->SetPosition(2, pos);
-
- pos = m_object->RetPosition(3);
- pos.z = 1.5f-progress*0.5f;
- m_object->SetPosition(3, pos);
- }
- if ( m_step == 2 ) // up?
- {
- pos = m_object->RetPosition(1);
- pos.y = 3.0f-(1.0f-progress)*2.0f;
- m_object->SetPosition(1, pos);
- }
- }
- else
- {
- if ( m_step == 0 ) // fall?
- {
- pos = m_object->RetPosition(1);
- pos.y = 3.0f-progress*2.0f;
- m_object->SetPosition(1, pos);
- }
- if ( m_step == 1 ) // farm?
- {
- pos = m_object->RetPosition(2);
- pos.z = -1.5f+(1.0f-progress)*0.5f;
- m_object->SetPosition(2, pos);
-
- pos = m_object->RetPosition(3);
- pos.z = 1.5f-(1.0f-progress)*0.5f;
- m_object->SetPosition(3, pos);
- }
- if ( m_step == 2 ) // up?
- {
- pos = m_object->RetPosition(1);
- pos.y = 3.0f-(1.0f-progress)*2.0f;
- m_object->SetPosition(1, pos);
- }
- }
- }
- else
- {
- for ( i=0 ; i<5 ; i++ )
- {
- angle = (m_finalAngle[i]-m_initialAngle[i])*progress;
- angle += m_initialAngle[i];
- m_object->SetAngleZ(i+1, angle);
- }
- }
-
- return true;
-}
-
-
-// Initializes the initial and final angles.
-
-void CTaskManip::InitAngle()
-{
- CObject* power;
- float max, energy;
- int i;
-
- if ( m_bSubm || m_bBee ) return;
-
- if ( m_arm == TMA_NEUTRAL ||
- m_arm == TMA_GRAB )
- {
- m_finalAngle[0] = ARM_NEUTRAL_ANGLE1; // arm
- m_finalAngle[1] = ARM_NEUTRAL_ANGLE2; // forearm
- m_finalAngle[2] = ARM_NEUTRAL_ANGLE3; // hand
- }
- if ( m_arm == TMA_STOCK )
- {
- m_finalAngle[0] = ARM_STOCK_ANGLE1; // arm
- m_finalAngle[1] = ARM_STOCK_ANGLE2; // forearm
- m_finalAngle[2] = ARM_STOCK_ANGLE3; // hand
- }
- if ( m_arm == TMA_FFRONT )
- {
- m_finalAngle[0] = 35.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = -95.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = -27.0f*Math::PI/180.0f; // hand
- }
- if ( m_arm == TMA_FBACK )
- {
- m_finalAngle[0] = 145.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = 95.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = 27.0f*Math::PI/180.0f; // hand
- }
- if ( m_arm == TMA_POWER )
- {
- m_finalAngle[0] = 95.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = 125.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = 50.0f*Math::PI/180.0f; // hand
- }
- if ( m_arm == TMA_OTHER )
- {
- if ( m_height <= 3.0f )
- {
- m_finalAngle[0] = 55.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = -90.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = -35.0f*Math::PI/180.0f; // hand
- }
- else
- {
- m_finalAngle[0] = 70.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = -90.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = -50.0f*Math::PI/180.0f; // hand
- }
- }
-
- if ( m_hand == TMH_OPEN ) // open clamp?
- {
- m_finalAngle[3] = -Math::PI*0.10f; // clamp close
- m_finalAngle[4] = Math::PI*0.10f; // clamp remote
- }
- if ( m_hand == TMH_CLOSE ) // clamp closed?
- {
- m_finalAngle[3] = Math::PI*0.05f; // clamp close
- m_finalAngle[4] = -Math::PI*0.05f; // clamp remote
- }
-
- for ( i=0 ; i<5 ; i++ )
- {
- m_initialAngle[i] = m_object->RetAngleZ(i+1);
- }
-
- max = 0.0f;
- for ( i=0 ; i<5 ; i++ )
- {
- max = Math::Max(max, fabs(m_initialAngle[i] - m_finalAngle[i]));
- }
- m_speed = (Math::PI*1.0f)/max;
- if ( m_speed > 3.0f ) m_speed = 3.0f; // piano, ma non troppo (?)
-
- energy = 0.0f;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- }
-
- if ( energy == 0.0f )
- {
- m_speed *= 0.7f; // slower if more energy!
- }
-}
-
-
-// Tests whether an object is compatible with the operation TMA_OTHER.
-
-bool TestFriend(ObjectType oType, ObjectType fType)
-{
- if ( oType == OBJECT_ENERGY )
- {
- return ( fType == OBJECT_METAL );
- }
- if ( oType == OBJECT_LABO )
- {
- return ( fType == OBJECT_BULLET );
- }
- if ( oType == OBJECT_NUCLEAR )
- {
- return ( fType == OBJECT_URANIUM );
- }
-
- return ( fType == OBJECT_POWER ||
- fType == OBJECT_ATOMIC );
-}
-
-// Assigns the goal was achieved.
-
-Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm)
-{
- ObjectType type;
- CObject *front, *other, *power;
- CPyro *pyro;
- float iAngle, dist, len;
- float fDist, fAngle, oDist, oAngle, oHeight;
- Math::Vector pos, fPos, oPos;
-
- m_arm = arm;
- m_height = 0.0f;
- m_step = 0;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
-
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
- oAngle = iAngle;
-
- m_bError = true; // operation impossible
-
- if ( m_arm != TMA_FFRONT &&
- m_arm != TMA_FBACK &&
- m_arm != TMA_POWER &&
- m_arm != TMA_GRAB ) return ERR_MANIP_VEH;
-
- m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));
-
- type = m_object->RetType();
- if ( type == OBJECT_BEE ) // bee?
- {
- if ( m_object->RetFret() == 0 )
- {
- if ( !m_physics->RetLand() ) return ERR_MANIP_FLY;
-
- other = SearchTakeUnderObject(m_targetPos, MARGIN_BEE);
- if ( other == 0 ) return ERR_MANIP_NIL;
- m_object->SetFret(other); // takes the ball
- other->SetTruck(m_object);
- other->SetTruckPart(0); // taken with the base
- other->SetPosition(0, Math::Vector(0.0f, -3.0f, 0.0f));
- }
- else
- {
- other = m_object->RetFret(); // other = ball
- m_object->SetFret(0); // lick the ball
- other->SetTruck(0);
- pos = m_object->RetPosition(0);
- pos.y -= 3.0f;
- other->SetPosition(0, pos);
-
- pos = m_object->RetPosition(0);
- pos.y += 2.0f;
- m_object->SetPosition(0, pos); // against the top of jump
-
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FALL, other); // the ball falls
- }
-
- m_bBee = true;
- m_bError = false; // ok
- return ERR_OK;
- }
- m_bBee = false;
-
- m_bSubm = ( type == OBJECT_MOBILEsa ); // submarine?
-
- if ( m_arm == TMA_GRAB ) // takes immediately?
- {
- TruckTakeObject();
- Abort();
- return ERR_OK;
- }
-
- m_energy = 0.0f;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- m_energy = power->RetEnergy();
- }
-
- if ( !m_physics->RetLand() ) return ERR_MANIP_FLY;
-
- if ( type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEsa ) return ERR_MANIP_VEH;
-
- if ( m_bSubm ) // submarine?
- {
- m_arm = TMA_FFRONT; // only possible in front!
- }
-
- m_move = 0.0f; // advance not necessary
- m_angle = iAngle;
-
- if ( order == TMO_AUTO )
- {
- if ( m_object->RetFret() == 0 )
- {
- m_order = TMO_GRAB;
- }
- else
- {
- m_order = TMO_DROP;
- }
- }
- else
- {
- m_order = order;
- }
-
- if ( m_order == TMO_GRAB && m_object->RetFret() != 0 )
- {
- return ERR_MANIP_BUSY;
- }
- if ( m_order == TMO_DROP && m_object->RetFret() == 0 )
- {
- return ERR_MANIP_EMPTY;
- }
-
-//? speed = m_physics->RetMotorSpeed();
-//? if ( speed.x != 0.0f ||
-//? speed.z != 0.0f ) return ERR_MANIP_MOTOR;
-
- if ( m_order == TMO_GRAB )
- {
- if ( m_arm == TMA_FFRONT )
- {
- front = SearchTakeFrontObject(true, fPos, fDist, fAngle);
- other = SearchOtherObject(true, oPos, oDist, oAngle, oHeight);
-
- if ( front != 0 && fDist < oDist )
- {
- m_targetPos = fPos;
- m_angle = fAngle;
- m_move = 1.0f; // advance required
- }
- else if ( other != 0 && oDist < fDist )
- {
- if ( other->RetPower() == 0 ) return ERR_MANIP_NIL;
- m_targetPos = oPos;
- m_angle = oAngle;
- m_height = oHeight;
- m_move = 1.0f; // advance required
- m_arm = TMA_OTHER;
- }
- else
- {
- return ERR_MANIP_NIL;
- }
- m_main->HideDropZone(front); // hides buildable area
- }
- if ( m_arm == TMA_FBACK )
- {
- if ( SearchTakeBackObject(true, m_targetPos, fDist, m_angle) == 0 )
- {
- return ERR_MANIP_NIL;
- }
- m_angle += Math::PI;
- m_move = -1.0f; // back necessary
- }
- if ( m_arm == TMA_POWER )
- {
- if ( m_object->RetPower() == 0 ) return ERR_MANIP_NIL;
- }
- }
-
- if ( m_order == TMO_DROP )
- {
- if ( m_arm == TMA_FFRONT )
- {
- other = SearchOtherObject(true, oPos, oDist, oAngle, oHeight);
- if ( other != 0 && other->RetPower() == 0 )
- {
- m_targetPos = oPos;
- m_angle = oAngle;
- m_height = oHeight;
- m_move = 1.0f; // advance required
- m_arm = TMA_OTHER;
- }
- else
- {
- if ( !IsFreeDeposeObject(Math::Vector(TAKE_DIST, 0.0f, 0.0f)) ) return ERR_MANIP_OCC;
- }
- }
- if ( m_arm == TMA_FBACK )
- {
- if ( !IsFreeDeposeObject(Math::Vector(-TAKE_DIST, 0.0f, 0.0f)) ) return ERR_MANIP_OCC;
- }
- if ( m_arm == TMA_POWER )
- {
- if ( m_object->RetPower() != 0 ) return ERR_MANIP_OCC;
- }
- }
-
- dist = Math::Distance(m_object->RetPosition(0), m_targetPos);
- len = dist-TAKE_DIST;
- if ( m_arm == TMA_OTHER ) len -= TAKE_DIST_OTHER;
- if ( len < 0.0f ) len = 0.0f;
- if ( m_arm == TMA_FBACK ) len = -len;
- m_advanceLength = dist-m_physics->RetLinLength(len);
- if ( dist <= m_advanceLength+0.2f ) m_move = 0.0f; // not necessary to advance
-
- if ( m_energy == 0.0f ) m_move = 0.0f;
-
- if ( m_move != 0.0f ) // forward or backward?
- {
- m_timeLimit = m_physics->RetLinTimeLength(fabs(len))*1.5f;
- if ( m_timeLimit < 0.5f ) m_timeLimit = 0.5f;
- }
-
- if ( m_object->RetFret() == 0 ) // not carrying anything?
- {
- m_hand = TMH_OPEN; // open clamp
- }
- else
- {
- m_hand = TMH_CLOSE; // closed clamp
- }
-
- InitAngle();
-
- if ( iAngle == m_angle || m_energy == 0.0f )
- {
- m_bTurn = false; // preliminary rotation unnecessary
- SoundManip(1.0f/m_speed);
- }
- else
- {
- m_bTurn = true; // preliminary rotation necessary
- }
-
- if ( m_bSubm )
- {
- m_camera->StartCentering(m_object, Math::PI*0.8f, 99.9f, 0.0f, 0.5f);
- }
-
- m_physics->SetFreeze(true); // it does not move
-
- m_bError = false; // ok
- return ERR_OK;
-}
-
-// Indicates whether the action is complete.
-
-Error CTaskManip::IsEnded()
-{
- CObject* fret;
- Math::Vector pos;
- float angle, dist;
- int i;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_bBee ) // bee?
- {
- return ERR_STOP;
- }
-
- if ( m_bTurn ) // preliminary rotation?
- {
- angle = m_object->RetAngleY(0);
- angle = Math::NormAngle(angle); // 0..2*Math::PI
-
- if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) )
- {
- m_bTurn = false; // rotation ended
- m_physics->SetMotorSpeedZ(0.0f);
- if ( m_move == 0.0f )
- {
- SoundManip(1.0f/m_speed);
- }
- }
- return ERR_CONTINUE;
- }
-
- if ( m_move != 0.0f ) // preliminary advance?
- {
- if ( m_timeLimit <= 0.0f )
- {
-//OK 1.9
- dist = Math::Distance(m_object->RetPosition(0), m_targetPos);
- if ( dist <= m_advanceLength + 2.0f )
- {
- m_move = 0.0f; // advance ended
- m_physics->SetMotorSpeedX(0.0f);
- SoundManip(1.0f/m_speed);
- return ERR_CONTINUE;
- }
- else
- {
-//EOK 1.9
- m_move = 0.0f; // advance ended
- m_physics->SetMotorSpeedX(0.0f); // stops
- Abort();
- return ERR_STOP;
- }
- }
-
- dist = Math::Distance(m_object->RetPosition(0), m_targetPos);
- if ( dist <= m_advanceLength )
- {
- m_move = 0.0f; // advance ended
- m_physics->SetMotorSpeedX(0.0f);
- SoundManip(1.0f/m_speed);
- }
- return ERR_CONTINUE;
- }
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( !m_bSubm )
- {
- for ( i=0 ; i<5 ; i++ )
- {
- m_object->SetAngleZ(i+1, m_finalAngle[i]);
- }
- }
- m_step ++;
-
- if ( m_order == TMO_GRAB )
- {
- if ( m_step == 1 )
- {
- if ( m_bSubm ) m_speed = 1.0f/0.7f;
- m_hand = TMH_CLOSE; // closes the clamp to take
- InitAngle();
- SoundManip(1.0f/m_speed, 0.8f, 1.5f);
- return ERR_CONTINUE;
- }
- if ( m_step == 2 )
- {
- if ( m_bSubm ) m_speed = 1.0f/1.5f;
- if ( !TruckTakeObject() &&
- m_object->RetFret() == 0 )
- {
- m_hand = TMH_OPEN; // reopens the clamp
- m_arm = TMA_NEUTRAL;
- InitAngle();
- SoundManip(1.0f/m_speed, 0.8f, 1.5f);
- }
- else
- {
- if ( (m_arm == TMA_OTHER ||
- m_arm == TMA_POWER ) &&
- (m_fretType == OBJECT_POWER ||
- m_fretType == OBJECT_ATOMIC ) )
- {
- m_sound->Play(SOUND_POWEROFF, m_object->RetPosition(0));
- }
- m_arm = TMA_STOCK;
- InitAngle();
- SoundManip(1.0f/m_speed);
- }
- return ERR_CONTINUE;
- }
- }
-
- if ( m_order == TMO_DROP )
- {
- if ( m_step == 1 )
- {
- if ( m_bSubm ) m_speed = 1.0f/0.7f;
- fret = m_object->RetFret();
- if ( TruckDeposeObject() )
- {
- if ( (m_arm == TMA_OTHER ||
- m_arm == TMA_POWER ) &&
- (m_fretType == OBJECT_POWER ||
- m_fretType == OBJECT_ATOMIC ) )
- {
- m_sound->Play(SOUND_POWERON, m_object->RetPosition(0));
- }
- if ( fret != 0 && m_fretType == OBJECT_METAL && m_arm == TMA_FFRONT )
- {
- m_main->ShowDropZone(fret, m_object); // shows buildable area
- }
- m_hand = TMH_OPEN; // opens the clamp to deposit
- SoundManip(1.0f/m_speed, 0.8f, 1.5f);
- }
- InitAngle();
- return ERR_CONTINUE;
- }
- if ( m_step == 2 )
- {
- if ( m_bSubm ) m_speed = 1.0f/1.5f;
- m_arm = TMA_NEUTRAL;
- InitAngle();
- SoundManip(1.0f/m_speed);
- return ERR_CONTINUE;
- }
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskManip::Abort()
-{
- int i;
-
- if ( m_object->RetFret() == 0 ) // not carrying anything?
- {
- m_hand = TMH_OPEN; // open clamp
- m_arm = TMA_NEUTRAL;
- }
- else
- {
- m_hand = TMH_CLOSE; // closed clamp
- m_arm = TMA_STOCK;
- }
- InitAngle();
-
- if ( !m_bSubm )
- {
- for ( i=0 ; i<5 ; i++ )
- {
- m_object->SetAngleZ(i+1, m_finalAngle[i]);
- }
- }
-
- m_camera->StopCentering(m_object, 2.0f);
- m_physics->SetFreeze(false); // is moving again
- return true;
-}
-
-
-// Seeks the object below to take (for bees).
-
-CObject* CTaskManip::SearchTakeUnderObject(Math::Vector &pos, float dLimit)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float min, distance;
- int i;
-
- iPos = m_object->RetPosition(0);
-
- min = 1000000.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
-
- if ( type != OBJECT_FRET &&
- type != OBJECT_STONE &&
- type != OBJECT_URANIUM &&
- type != OBJECT_BULLET &&
- type != OBJECT_METAL &&
- type != OBJECT_POWER &&
- type != OBJECT_ATOMIC &&
- type != OBJECT_BBOX &&
- type != OBJECT_KEYa &&
- type != OBJECT_KEYb &&
- type != OBJECT_KEYc &&
- type != OBJECT_KEYd &&
- type != OBJECT_TNT ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj->RetLock() ) continue;
- if ( pObj->RetZoomY(0) != 1.0f ) continue;
-
- oPos = pObj->RetPosition(0);
- distance = Math::Distance(oPos, iPos);
- if ( distance <= dLimit &&
- distance < min )
- {
- min = distance;
- pBest = pObj;
- }
- }
- if ( pBest != 0 )
- {
- pos = pBest->RetPosition(0);
- }
- return pBest;
-}
-
-// Seeks the object in front to take.
-
-CObject* CTaskManip::SearchTakeFrontObject(bool bAdvance, Math::Vector &pos,
- float &distance, float &angle)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float min, iAngle, bAngle, aLimit, dLimit, f;
- int i;
-
- iPos = m_object->RetPosition(0);
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- if ( bAdvance && m_energy > 0.0f )
- {
- aLimit = 60.0f*Math::PI/180.0f;
- dLimit = MARGIN_FRONT+10.0f;
- }
- else
- {
-//? aLimit = 7.0f*Math::PI/180.0f;
- aLimit = 15.0f*Math::PI/180.0f; //OK 1.9
- dLimit = MARGIN_FRONT;
- }
-
- min = 1000000.0f;
- pBest = 0;
- bAngle = 0.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
-
- if ( type != OBJECT_FRET &&
- type != OBJECT_STONE &&
- type != OBJECT_URANIUM &&
- type != OBJECT_BULLET &&
- type != OBJECT_METAL &&
- type != OBJECT_POWER &&
- type != OBJECT_ATOMIC &&
- type != OBJECT_BBOX &&
- type != OBJECT_KEYa &&
- type != OBJECT_KEYb &&
- type != OBJECT_KEYc &&
- type != OBJECT_KEYd &&
- type != OBJECT_TNT &&
- type != OBJECT_SCRAP1 &&
- type != OBJECT_SCRAP2 &&
- type != OBJECT_SCRAP3 &&
- type != OBJECT_SCRAP4 &&
- type != OBJECT_SCRAP5 ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj->RetLock() ) continue;
- if ( pObj->RetZoomY(0) != 1.0f ) continue;
-
- oPos = pObj->RetPosition(0);
- distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST);
- f = 1.0f-distance/50.0f;
- if ( f < 0.5f ) f = 0.5f;
-
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( !Math::TestAngle(angle, iAngle-aLimit*f, iAngle+aLimit*f) ) continue;
-
- if ( distance < -dLimit ||
- distance > dLimit ) continue;
-
- if ( distance < min )
- {
- min = distance;
- pBest = pObj;
- bAngle = angle;
- }
- }
- if ( pBest == 0 )
- {
- distance = 1000000.0f;
- angle = 0.0f;
- }
- else
- {
- pos = pBest->RetPosition(0);
- distance = min;
- angle = bAngle;
- }
- return pBest;
-}
-
-// Seeks the object back to take.
-
-CObject* CTaskManip::SearchTakeBackObject(bool bAdvance, Math::Vector &pos,
- float &distance, float &angle)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float min, iAngle, bAngle, aLimit, dLimit, f;
- int i;
-
- iPos = m_object->RetPosition(0);
- iAngle = m_object->RetAngleY(0)+Math::PI;
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- if ( bAdvance && m_energy > 0.0f )
- {
- aLimit = 60.0f*Math::PI/180.0f;
- dLimit = MARGIN_BACK+5.0f;
- }
- else
- {
- aLimit = 7.0f*Math::PI/180.0f;
- dLimit = MARGIN_BACK;
- }
-
- min = 1000000.0f;
- pBest = 0;
- bAngle = 0.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
-
- if ( type != OBJECT_FRET &&
- type != OBJECT_STONE &&
- type != OBJECT_URANIUM &&
- type != OBJECT_BULLET &&
- type != OBJECT_METAL &&
- type != OBJECT_POWER &&
- type != OBJECT_ATOMIC &&
- type != OBJECT_BBOX &&
- type != OBJECT_KEYa &&
- type != OBJECT_KEYb &&
- type != OBJECT_KEYc &&
- type != OBJECT_KEYd &&
- type != OBJECT_TNT &&
- type != OBJECT_SCRAP1 &&
- type != OBJECT_SCRAP2 &&
- type != OBJECT_SCRAP3 &&
- type != OBJECT_SCRAP4 &&
- type != OBJECT_SCRAP5 ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj->RetLock() ) continue;
- if ( pObj->RetZoomY(0) != 1.0f ) continue;
-
- oPos = pObj->RetPosition(0);
- distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST);
- f = 1.0f-distance/50.0f;
- if ( f < 0.5f ) f = 0.5f;
-
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( !Math::TestAngle(angle, iAngle-aLimit*f, iAngle+aLimit*f) ) continue;
-
- if ( distance < -dLimit ||
- distance > dLimit ) continue;
-
- if ( distance < min )
- {
- min = distance;
- pBest = pObj;
- bAngle = angle;
- }
- }
- if ( pBest == 0 )
- {
- distance = 1000000.0f;
- angle = 0.0f;
- }
- else
- {
- pos = pBest->RetPosition(0);
- distance = min;
- angle = bAngle;
- }
- return pBest;
-}
-
-// Seeks the robot or building on which it wants to put a battery or or other object.
-
-CObject* CTaskManip::SearchOtherObject(bool bAdvance, Math::Vector &pos,
- float &distance, float &angle,
- float &height)
-{
- Character* character;
- CObject* pObj;
- CObject* pPower;
- Math::Matrix* mat;
- Math::Vector iPos, oPos;
- ObjectType type, powerType;
- float iAngle, iRad, oAngle, oLimit, aLimit, dLimit;
- int i;
-
- distance = 1000000.0f;
- angle = 0.0f;
-
- if ( m_bSubm ) return 0; // impossible with the submarine
-
- if ( !m_object->GetCrashSphere(0, iPos, iRad) ) return 0;
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- if ( bAdvance && m_energy > 0.0f )
- {
- aLimit = 60.0f*Math::PI/180.0f;
- dLimit = MARGIN_FRIEND+10.0f;
- }
- else
- {
- aLimit = 7.0f*Math::PI/180.0f;
- dLimit = MARGIN_FRIEND;
- }
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue; // yourself?
-
- type = pObj->RetType();
- if ( type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_TOWER &&
- type != OBJECT_RESEARCH &&
- type != OBJECT_ENERGY &&
- type != OBJECT_LABO &&
- type != OBJECT_NUCLEAR ) continue;
-
- pPower = pObj->RetPower();
- if ( pPower != 0 )
- {
- if ( pPower->RetLock() ) continue;
- if ( pPower->RetZoomY(0) != 1.0f ) continue;
-
- powerType = pPower->RetType();
- if ( powerType == OBJECT_NULL ||
- powerType == OBJECT_FIX ) continue;
- }
-
- mat = pObj->RetWorldMatrix(0);
- character = pObj->RetCharacter();
- oPos = Transform(*mat, character->posPower);
-
- oAngle = pObj->RetAngleY(0);
- if ( type == OBJECT_TOWER ||
- type == OBJECT_RESEARCH )
- {
- oLimit = 45.0f*Math::PI/180.0f;
- }
- else if ( type == OBJECT_ENERGY )
- {
- oLimit = 90.0f*Math::PI/180.0f;
- }
- else if ( type == OBJECT_LABO )
- {
- oLimit = 120.0f*Math::PI/180.0f;
- }
- else if ( type == OBJECT_NUCLEAR )
- {
- oLimit = 45.0f*Math::PI/180.0f;
- }
- else
- {
- oLimit = 45.0f*Math::PI/180.0f;
- oAngle += Math::PI; // is behind
- }
- oAngle = Math::NormAngle(oAngle); // 0..2*Math::PI
- angle = Math::RotateAngle(iPos.x-oPos.x, oPos.z-iPos.z); // CW !
- if ( !Math::TestAngle(angle, oAngle-oLimit, oAngle+oLimit) ) continue;
-
- distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST);
- if ( distance <= dLimit )
- {
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
- {
- character = pObj->RetCharacter();
- height = character->posPower.y;
- pos = oPos;
- return pObj;
- }
- }
- }
-
- distance = 1000000.0f;
- angle = 0.0f;
- return 0;
-}
-
-// Takes the object placed in front.
-
-bool CTaskManip::TruckTakeObject()
-{
- CObject* fret;
- CObject* other;
- Math::Matrix matRotate;
- Math::Vector pos;
- float angle, dist;
-
- if ( m_arm == TMA_GRAB ) // takes immediately?
- {
- fret = m_object->RetFret();
- if ( fret == 0 ) return false; // nothing to take?
- m_fretType = fret->RetType();
-
- if ( m_object->RetType() == OBJECT_HUMAN ||
- m_object->RetType() == OBJECT_TECH )
- {
- fret->SetTruck(m_object);
- fret->SetTruckPart(4); // takes with the hand
-
- fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f));
- fret->SetAngleY(0, 0.1f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.8f);
- }
- else if ( m_bSubm )
- {
- fret->SetTruck(m_object);
- fret->SetTruckPart(2); // takes with the right claw
-
- pos = Math::Vector(1.1f, -1.0f, 1.0f); // relative
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleY(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- }
- else
- {
- fret->SetTruck(m_object);
- fret->SetTruckPart(3); // takes with the hand
-
- pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, Math::PI/2.0f);
- fret->SetAngleY(0, 0.0f);
- }
-
- m_object->SetFret(fret); // takes
- }
-
- if ( m_arm == TMA_FFRONT ) // takes on the ground in front?
- {
- fret = SearchTakeFrontObject(false, pos, dist, angle);
- if ( fret == 0 ) return false; // nothing to take?
- m_fretType = fret->RetType();
-
- if ( m_bSubm )
- {
- fret->SetTruck(m_object);
- fret->SetTruckPart(2); // takes with the right claw
-
- pos = Math::Vector(1.1f, -1.0f, 1.0f); // relative
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleY(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- }
- else
- {
- fret->SetTruck(m_object);
- fret->SetTruckPart(3); // takes with the hand
-
- pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, Math::PI/2.0f);
- fret->SetAngleY(0, 0.0f);
- }
-
- m_object->SetFret(fret); // takes
- }
-
- if ( m_arm == TMA_FBACK ) // takes on the ground behind?
- {
- fret = SearchTakeBackObject(false, pos, dist, angle);
- if ( fret == 0 ) return false; // nothing to take?
- m_fretType = fret->RetType();
-
- fret->SetTruck(m_object);
- fret->SetTruckPart(3); // takes with the hand
-
- pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, Math::PI/2.0f);
- fret->SetAngleY(0, 0.0f);
-
- m_object->SetFret(fret); // takes
- }
-
- if ( m_arm == TMA_POWER ) // takes battery in the back?
- {
- fret = m_object->RetPower();
- if ( fret == 0 ) return false; // no battery?
- m_fretType = fret->RetType();
-
- pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, Math::PI/2.0f);
- fret->SetAngleY(0, 0.0f);
- fret->SetTruckPart(3); // takes with the hand
-
- m_object->SetPower(0);
- m_object->SetFret(fret); // takes
- }
-
- if ( m_arm == TMA_OTHER ) // battery takes from friend?
- {
- other = SearchOtherObject(false, pos, dist, angle, m_height);
- if ( other == 0 ) return false;
-
- fret = other->RetPower();
- if ( fret == 0 ) return false; // the other does not have a battery?
- m_fretType = fret->RetType();
-
- other->SetPower(0);
- fret->SetTruck(m_object);
- fret->SetTruckPart(3); // takes with the hand
-
- pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, Math::PI/2.0f);
- fret->SetAngleY(0, 0.0f);
-
- m_object->SetFret(fret); // takes
- }
-
- return true;
-}
-
-// Deposes the object taken.
-
-bool CTaskManip::TruckDeposeObject()
-{
- Character* character;
- CObject* fret;
- CObject* other;
- Math::Matrix* mat;
- Math::Vector pos;
- float angle, dist;
-
- if ( m_arm == TMA_FFRONT ) // deposits on the ground in front?
- {
- fret = m_object->RetFret();
- if ( fret == 0 ) return false; // nothing transported?
- m_fretType = fret->RetType();
-
- mat = fret->RetWorldMatrix(0);
- pos = Transform(*mat, Math::Vector(0.0f, 1.0f, 0.0f));
- m_terrain->MoveOnFloor(pos);
- fret->SetPosition(0, pos);
- fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- fret->FloorAdjust(); // plate well on the ground
-
- fret->SetTruck(0);
- m_object->SetFret(0); // deposit
- }
-
- if ( m_arm == TMA_FBACK ) // deposited on the ground behind?
- {
- fret = m_object->RetFret();
- if ( fret == 0 ) return false; // nothing transported?
- m_fretType = fret->RetType();
-
- mat = fret->RetWorldMatrix(0);
- pos = Transform(*mat, Math::Vector(0.0f, 1.0f, 0.0f));
- m_terrain->MoveOnFloor(pos);
- fret->SetPosition(0, pos);
- fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
-
- fret->SetTruck(0);
- m_object->SetFret(0); // deposit
- }
-
- if ( m_arm == TMA_POWER ) // deposits battery in the back?
- {
- fret = m_object->RetFret();
- if ( fret == 0 ) return false; // nothing transported?
- m_fretType = fret->RetType();
-
- if ( m_object->RetPower() != 0 ) return false;
-
- fret->SetTruck(m_object);
- fret->SetTruckPart(0); // carried by the base
-
- character = m_object->RetCharacter();
- fret->SetPosition(0, character->posPower);
- fret->SetAngleY(0, 0.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
-
- m_object->SetPower(fret); // uses
- m_object->SetFret(0);
- }
-
- if ( m_arm == TMA_OTHER ) // deposits battery on friend?
- {
- other = SearchOtherObject(false, pos, dist, angle, m_height);
- if ( other == 0 ) return false;
-
- fret = other->RetPower();
- if ( fret != 0 ) return false; // the other already has a battery?
-
- fret = m_object->RetFret();
- if ( fret == 0 ) return false;
- m_fretType = fret->RetType();
-
- other->SetPower(fret);
- fret->SetTruck(other);
-
- character = other->RetCharacter();
- fret->SetPosition(0, character->posPower);
- fret->SetAngleY(0, 0.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- fret->SetTruckPart(0); // carried by the base
-
- m_object->SetFret(0); // deposit
- }
-
- return true;
-}
-
-// Seeks if a location allows to deposit an object.
-
-bool CTaskManip::IsFreeDeposeObject(Math::Vector pos)
-{
- CObject* pObj;
- Math::Matrix* mat;
- Math::Vector iPos, oPos;
- float oRadius;
- int i, j;
-
- mat = m_object->RetWorldMatrix(0);
- iPos = Transform(*mat, pos);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- if ( Math::Distance(iPos, oPos)-(oRadius+1.0f) < 2.0f )
- {
- return false; // location occupied
- }
- }
- }
- return true; // location free
-}
-
-// Plays the sound of the manipulator arm.
-
-void CTaskManip::SoundManip(float time, float amplitude, float frequency)
-{
- int i;
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskmanip.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskmanip.h"
+
+#include "common/iman.h"
+#include "old/terrain.h"
+#include "old/pyro.h"
+#include "math/geometry.h"
+#include "object/robotmain.h"
+#include "physics/physics.h"
+
+
+//?const float MARGIN_FRONT = 2.0f;
+//?const float MARGIN_BACK = 2.0f;
+//?const float MARGIN_FRIEND = 2.0f;
+//?const float MARGIN_BEE = 5.0f;
+const float MARGIN_FRONT = 4.0f; //OK 1.9
+const float MARGIN_BACK = 4.0f; //OK 1.9
+const float MARGIN_FRIEND = 4.0f; //OK 1.9
+const float MARGIN_BEE = 5.0f; //OK 1.9
+
+
+
+
+// Object's constructor.
+
+CTaskManip::CTaskManip(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_arm = TMA_NEUTRAL;
+ m_hand = TMH_OPEN;
+}
+
+// Object's destructor.
+
+CTaskManip::~CTaskManip()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskManip::EventProcess(const Event &event)
+{
+ Math::Vector pos;
+ float angle, a, g, cirSpeed, progress;
+ int i;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ if ( m_bBee ) // bee?
+ {
+ return true;
+ }
+
+ if ( m_bTurn ) // preliminary rotation?
+ {
+ a = m_object->RetAngleY(0);
+ g = m_angle;
+ cirSpeed = Math::Direction(a, g)*1.0f;
+ if ( m_physics->RetType() == TYPE_FLYING ) // flying on the ground?
+ {
+ cirSpeed *= 4.0f; // more fishing
+ }
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
+ return true;
+ }
+
+ if ( m_move != 0 ) // preliminary advance?
+ {
+ m_timeLimit -= event.rTime;
+ m_physics->SetMotorSpeedX(m_move); // forward/backward
+ return true;
+ }
+
+ m_progress += event.rTime*m_speed; // others advance
+ progress = m_progress;
+ if ( progress > 1.0f ) progress = 1.0f;
+
+ if ( m_bSubm ) // submarine?
+ {
+ if ( m_order == TMO_GRAB )
+ {
+ if ( m_step == 0 ) // fall?
+ {
+ pos = m_object->RetPosition(1);
+ pos.y = 3.0f-progress*2.0f;
+ m_object->SetPosition(1, pos);
+ }
+ if ( m_step == 1 ) // farm?
+ {
+ pos = m_object->RetPosition(2);
+ pos.z = -1.5f+progress*0.5f;
+ m_object->SetPosition(2, pos);
+
+ pos = m_object->RetPosition(3);
+ pos.z = 1.5f-progress*0.5f;
+ m_object->SetPosition(3, pos);
+ }
+ if ( m_step == 2 ) // up?
+ {
+ pos = m_object->RetPosition(1);
+ pos.y = 3.0f-(1.0f-progress)*2.0f;
+ m_object->SetPosition(1, pos);
+ }
+ }
+ else
+ {
+ if ( m_step == 0 ) // fall?
+ {
+ pos = m_object->RetPosition(1);
+ pos.y = 3.0f-progress*2.0f;
+ m_object->SetPosition(1, pos);
+ }
+ if ( m_step == 1 ) // farm?
+ {
+ pos = m_object->RetPosition(2);
+ pos.z = -1.5f+(1.0f-progress)*0.5f;
+ m_object->SetPosition(2, pos);
+
+ pos = m_object->RetPosition(3);
+ pos.z = 1.5f-(1.0f-progress)*0.5f;
+ m_object->SetPosition(3, pos);
+ }
+ if ( m_step == 2 ) // up?
+ {
+ pos = m_object->RetPosition(1);
+ pos.y = 3.0f-(1.0f-progress)*2.0f;
+ m_object->SetPosition(1, pos);
+ }
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<5 ; i++ )
+ {
+ angle = (m_finalAngle[i]-m_initialAngle[i])*progress;
+ angle += m_initialAngle[i];
+ m_object->SetAngleZ(i+1, angle);
+ }
+ }
+
+ return true;
+}
+
+
+// Initializes the initial and final angles.
+
+void CTaskManip::InitAngle()
+{
+ CObject* power;
+ float max, energy;
+ int i;
+
+ if ( m_bSubm || m_bBee ) return;
+
+ if ( m_arm == TMA_NEUTRAL ||
+ m_arm == TMA_GRAB )
+ {
+ m_finalAngle[0] = ARM_NEUTRAL_ANGLE1; // arm
+ m_finalAngle[1] = ARM_NEUTRAL_ANGLE2; // forearm
+ m_finalAngle[2] = ARM_NEUTRAL_ANGLE3; // hand
+ }
+ if ( m_arm == TMA_STOCK )
+ {
+ m_finalAngle[0] = ARM_STOCK_ANGLE1; // arm
+ m_finalAngle[1] = ARM_STOCK_ANGLE2; // forearm
+ m_finalAngle[2] = ARM_STOCK_ANGLE3; // hand
+ }
+ if ( m_arm == TMA_FFRONT )
+ {
+ m_finalAngle[0] = 35.0f*Math::PI/180.0f; // arm
+ m_finalAngle[1] = -95.0f*Math::PI/180.0f; // forearm
+ m_finalAngle[2] = -27.0f*Math::PI/180.0f; // hand
+ }
+ if ( m_arm == TMA_FBACK )
+ {
+ m_finalAngle[0] = 145.0f*Math::PI/180.0f; // arm
+ m_finalAngle[1] = 95.0f*Math::PI/180.0f; // forearm
+ m_finalAngle[2] = 27.0f*Math::PI/180.0f; // hand
+ }
+ if ( m_arm == TMA_POWER )
+ {
+ m_finalAngle[0] = 95.0f*Math::PI/180.0f; // arm
+ m_finalAngle[1] = 125.0f*Math::PI/180.0f; // forearm
+ m_finalAngle[2] = 50.0f*Math::PI/180.0f; // hand
+ }
+ if ( m_arm == TMA_OTHER )
+ {
+ if ( m_height <= 3.0f )
+ {
+ m_finalAngle[0] = 55.0f*Math::PI/180.0f; // arm
+ m_finalAngle[1] = -90.0f*Math::PI/180.0f; // forearm
+ m_finalAngle[2] = -35.0f*Math::PI/180.0f; // hand
+ }
+ else
+ {
+ m_finalAngle[0] = 70.0f*Math::PI/180.0f; // arm
+ m_finalAngle[1] = -90.0f*Math::PI/180.0f; // forearm
+ m_finalAngle[2] = -50.0f*Math::PI/180.0f; // hand
+ }
+ }
+
+ if ( m_hand == TMH_OPEN ) // open clamp?
+ {
+ m_finalAngle[3] = -Math::PI*0.10f; // clamp close
+ m_finalAngle[4] = Math::PI*0.10f; // clamp remote
+ }
+ if ( m_hand == TMH_CLOSE ) // clamp closed?
+ {
+ m_finalAngle[3] = Math::PI*0.05f; // clamp close
+ m_finalAngle[4] = -Math::PI*0.05f; // clamp remote
+ }
+
+ for ( i=0 ; i<5 ; i++ )
+ {
+ m_initialAngle[i] = m_object->RetAngleZ(i+1);
+ }
+
+ max = 0.0f;
+ for ( i=0 ; i<5 ; i++ )
+ {
+ max = Math::Max(max, fabs(m_initialAngle[i] - m_finalAngle[i]));
+ }
+ m_speed = (Math::PI*1.0f)/max;
+ if ( m_speed > 3.0f ) m_speed = 3.0f; // piano, ma non troppo (?)
+
+ energy = 0.0f;
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ }
+
+ if ( energy == 0.0f )
+ {
+ m_speed *= 0.7f; // slower if more energy!
+ }
+}
+
+
+// Tests whether an object is compatible with the operation TMA_OTHER.
+
+bool TestFriend(ObjectType oType, ObjectType fType)
+{
+ if ( oType == OBJECT_ENERGY )
+ {
+ return ( fType == OBJECT_METAL );
+ }
+ if ( oType == OBJECT_LABO )
+ {
+ return ( fType == OBJECT_BULLET );
+ }
+ if ( oType == OBJECT_NUCLEAR )
+ {
+ return ( fType == OBJECT_URANIUM );
+ }
+
+ return ( fType == OBJECT_POWER ||
+ fType == OBJECT_ATOMIC );
+}
+
+// Assigns the goal was achieved.
+
+Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm)
+{
+ ObjectType type;
+ CObject *front, *other, *power;
+ CPyro *pyro;
+ float iAngle, dist, len;
+ float fDist, fAngle, oDist, oAngle, oHeight;
+ Math::Vector pos, fPos, oPos;
+
+ m_arm = arm;
+ m_height = 0.0f;
+ m_step = 0;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+ oAngle = iAngle;
+
+ m_bError = true; // operation impossible
+
+ if ( m_arm != TMA_FFRONT &&
+ m_arm != TMA_FBACK &&
+ m_arm != TMA_POWER &&
+ m_arm != TMA_GRAB ) return ERR_MANIP_VEH;
+
+ m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));
+
+ type = m_object->RetType();
+ if ( type == OBJECT_BEE ) // bee?
+ {
+ if ( m_object->RetFret() == 0 )
+ {
+ if ( !m_physics->RetLand() ) return ERR_MANIP_FLY;
+
+ other = SearchTakeUnderObject(m_targetPos, MARGIN_BEE);
+ if ( other == 0 ) return ERR_MANIP_NIL;
+ m_object->SetFret(other); // takes the ball
+ other->SetTruck(m_object);
+ other->SetTruckPart(0); // taken with the base
+ other->SetPosition(0, Math::Vector(0.0f, -3.0f, 0.0f));
+ }
+ else
+ {
+ other = m_object->RetFret(); // other = ball
+ m_object->SetFret(0); // lick the ball
+ other->SetTruck(0);
+ pos = m_object->RetPosition(0);
+ pos.y -= 3.0f;
+ other->SetPosition(0, pos);
+
+ pos = m_object->RetPosition(0);
+ pos.y += 2.0f;
+ m_object->SetPosition(0, pos); // against the top of jump
+
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FALL, other); // the ball falls
+ }
+
+ m_bBee = true;
+ m_bError = false; // ok
+ return ERR_OK;
+ }
+ m_bBee = false;
+
+ m_bSubm = ( type == OBJECT_MOBILEsa ); // submarine?
+
+ if ( m_arm == TMA_GRAB ) // takes immediately?
+ {
+ TruckTakeObject();
+ Abort();
+ return ERR_OK;
+ }
+
+ m_energy = 0.0f;
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ m_energy = power->RetEnergy();
+ }
+
+ if ( !m_physics->RetLand() ) return ERR_MANIP_FLY;
+
+ if ( type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEsa ) return ERR_MANIP_VEH;
+
+ if ( m_bSubm ) // submarine?
+ {
+ m_arm = TMA_FFRONT; // only possible in front!
+ }
+
+ m_move = 0.0f; // advance not necessary
+ m_angle = iAngle;
+
+ if ( order == TMO_AUTO )
+ {
+ if ( m_object->RetFret() == 0 )
+ {
+ m_order = TMO_GRAB;
+ }
+ else
+ {
+ m_order = TMO_DROP;
+ }
+ }
+ else
+ {
+ m_order = order;
+ }
+
+ if ( m_order == TMO_GRAB && m_object->RetFret() != 0 )
+ {
+ return ERR_MANIP_BUSY;
+ }
+ if ( m_order == TMO_DROP && m_object->RetFret() == 0 )
+ {
+ return ERR_MANIP_EMPTY;
+ }
+
+//? speed = m_physics->RetMotorSpeed();
+//? if ( speed.x != 0.0f ||
+//? speed.z != 0.0f ) return ERR_MANIP_MOTOR;
+
+ if ( m_order == TMO_GRAB )
+ {
+ if ( m_arm == TMA_FFRONT )
+ {
+ front = SearchTakeFrontObject(true, fPos, fDist, fAngle);
+ other = SearchOtherObject(true, oPos, oDist, oAngle, oHeight);
+
+ if ( front != 0 && fDist < oDist )
+ {
+ m_targetPos = fPos;
+ m_angle = fAngle;
+ m_move = 1.0f; // advance required
+ }
+ else if ( other != 0 && oDist < fDist )
+ {
+ if ( other->RetPower() == 0 ) return ERR_MANIP_NIL;
+ m_targetPos = oPos;
+ m_angle = oAngle;
+ m_height = oHeight;
+ m_move = 1.0f; // advance required
+ m_arm = TMA_OTHER;
+ }
+ else
+ {
+ return ERR_MANIP_NIL;
+ }
+ m_main->HideDropZone(front); // hides buildable area
+ }
+ if ( m_arm == TMA_FBACK )
+ {
+ if ( SearchTakeBackObject(true, m_targetPos, fDist, m_angle) == 0 )
+ {
+ return ERR_MANIP_NIL;
+ }
+ m_angle += Math::PI;
+ m_move = -1.0f; // back necessary
+ }
+ if ( m_arm == TMA_POWER )
+ {
+ if ( m_object->RetPower() == 0 ) return ERR_MANIP_NIL;
+ }
+ }
+
+ if ( m_order == TMO_DROP )
+ {
+ if ( m_arm == TMA_FFRONT )
+ {
+ other = SearchOtherObject(true, oPos, oDist, oAngle, oHeight);
+ if ( other != 0 && other->RetPower() == 0 )
+ {
+ m_targetPos = oPos;
+ m_angle = oAngle;
+ m_height = oHeight;
+ m_move = 1.0f; // advance required
+ m_arm = TMA_OTHER;
+ }
+ else
+ {
+ if ( !IsFreeDeposeObject(Math::Vector(TAKE_DIST, 0.0f, 0.0f)) ) return ERR_MANIP_OCC;
+ }
+ }
+ if ( m_arm == TMA_FBACK )
+ {
+ if ( !IsFreeDeposeObject(Math::Vector(-TAKE_DIST, 0.0f, 0.0f)) ) return ERR_MANIP_OCC;
+ }
+ if ( m_arm == TMA_POWER )
+ {
+ if ( m_object->RetPower() != 0 ) return ERR_MANIP_OCC;
+ }
+ }
+
+ dist = Math::Distance(m_object->RetPosition(0), m_targetPos);
+ len = dist-TAKE_DIST;
+ if ( m_arm == TMA_OTHER ) len -= TAKE_DIST_OTHER;
+ if ( len < 0.0f ) len = 0.0f;
+ if ( m_arm == TMA_FBACK ) len = -len;
+ m_advanceLength = dist-m_physics->RetLinLength(len);
+ if ( dist <= m_advanceLength+0.2f ) m_move = 0.0f; // not necessary to advance
+
+ if ( m_energy == 0.0f ) m_move = 0.0f;
+
+ if ( m_move != 0.0f ) // forward or backward?
+ {
+ m_timeLimit = m_physics->RetLinTimeLength(fabs(len))*1.5f;
+ if ( m_timeLimit < 0.5f ) m_timeLimit = 0.5f;
+ }
+
+ if ( m_object->RetFret() == 0 ) // not carrying anything?
+ {
+ m_hand = TMH_OPEN; // open clamp
+ }
+ else
+ {
+ m_hand = TMH_CLOSE; // closed clamp
+ }
+
+ InitAngle();
+
+ if ( iAngle == m_angle || m_energy == 0.0f )
+ {
+ m_bTurn = false; // preliminary rotation unnecessary
+ SoundManip(1.0f/m_speed);
+ }
+ else
+ {
+ m_bTurn = true; // preliminary rotation necessary
+ }
+
+ if ( m_bSubm )
+ {
+ m_camera->StartCentering(m_object, Math::PI*0.8f, 99.9f, 0.0f, 0.5f);
+ }
+
+ m_physics->SetFreeze(true); // it does not move
+
+ m_bError = false; // ok
+ return ERR_OK;
+}
+
+// Indicates whether the action is complete.
+
+Error CTaskManip::IsEnded()
+{
+ CObject* fret;
+ Math::Vector pos;
+ float angle, dist;
+ int i;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_bBee ) // bee?
+ {
+ return ERR_STOP;
+ }
+
+ if ( m_bTurn ) // preliminary rotation?
+ {
+ angle = m_object->RetAngleY(0);
+ angle = Math::NormAngle(angle); // 0..2*Math::PI
+
+ if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) )
+ {
+ m_bTurn = false; // rotation ended
+ m_physics->SetMotorSpeedZ(0.0f);
+ if ( m_move == 0.0f )
+ {
+ SoundManip(1.0f/m_speed);
+ }
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_move != 0.0f ) // preliminary advance?
+ {
+ if ( m_timeLimit <= 0.0f )
+ {
+//OK 1.9
+ dist = Math::Distance(m_object->RetPosition(0), m_targetPos);
+ if ( dist <= m_advanceLength + 2.0f )
+ {
+ m_move = 0.0f; // advance ended
+ m_physics->SetMotorSpeedX(0.0f);
+ SoundManip(1.0f/m_speed);
+ return ERR_CONTINUE;
+ }
+ else
+ {
+//EOK 1.9
+ m_move = 0.0f; // advance ended
+ m_physics->SetMotorSpeedX(0.0f); // stops
+ Abort();
+ return ERR_STOP;
+ }
+ }
+
+ dist = Math::Distance(m_object->RetPosition(0), m_targetPos);
+ if ( dist <= m_advanceLength )
+ {
+ m_move = 0.0f; // advance ended
+ m_physics->SetMotorSpeedX(0.0f);
+ SoundManip(1.0f/m_speed);
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+ m_progress = 0.0f;
+
+ if ( !m_bSubm )
+ {
+ for ( i=0 ; i<5 ; i++ )
+ {
+ m_object->SetAngleZ(i+1, m_finalAngle[i]);
+ }
+ }
+ m_step ++;
+
+ if ( m_order == TMO_GRAB )
+ {
+ if ( m_step == 1 )
+ {
+ if ( m_bSubm ) m_speed = 1.0f/0.7f;
+ m_hand = TMH_CLOSE; // closes the clamp to take
+ InitAngle();
+ SoundManip(1.0f/m_speed, 0.8f, 1.5f);
+ return ERR_CONTINUE;
+ }
+ if ( m_step == 2 )
+ {
+ if ( m_bSubm ) m_speed = 1.0f/1.5f;
+ if ( !TruckTakeObject() &&
+ m_object->RetFret() == 0 )
+ {
+ m_hand = TMH_OPEN; // reopens the clamp
+ m_arm = TMA_NEUTRAL;
+ InitAngle();
+ SoundManip(1.0f/m_speed, 0.8f, 1.5f);
+ }
+ else
+ {
+ if ( (m_arm == TMA_OTHER ||
+ m_arm == TMA_POWER ) &&
+ (m_fretType == OBJECT_POWER ||
+ m_fretType == OBJECT_ATOMIC ) )
+ {
+ m_sound->Play(SOUND_POWEROFF, m_object->RetPosition(0));
+ }
+ m_arm = TMA_STOCK;
+ InitAngle();
+ SoundManip(1.0f/m_speed);
+ }
+ return ERR_CONTINUE;
+ }
+ }
+
+ if ( m_order == TMO_DROP )
+ {
+ if ( m_step == 1 )
+ {
+ if ( m_bSubm ) m_speed = 1.0f/0.7f;
+ fret = m_object->RetFret();
+ if ( TruckDeposeObject() )
+ {
+ if ( (m_arm == TMA_OTHER ||
+ m_arm == TMA_POWER ) &&
+ (m_fretType == OBJECT_POWER ||
+ m_fretType == OBJECT_ATOMIC ) )
+ {
+ m_sound->Play(SOUND_POWERON, m_object->RetPosition(0));
+ }
+ if ( fret != 0 && m_fretType == OBJECT_METAL && m_arm == TMA_FFRONT )
+ {
+ m_main->ShowDropZone(fret, m_object); // shows buildable area
+ }
+ m_hand = TMH_OPEN; // opens the clamp to deposit
+ SoundManip(1.0f/m_speed, 0.8f, 1.5f);
+ }
+ InitAngle();
+ return ERR_CONTINUE;
+ }
+ if ( m_step == 2 )
+ {
+ if ( m_bSubm ) m_speed = 1.0f/1.5f;
+ m_arm = TMA_NEUTRAL;
+ InitAngle();
+ SoundManip(1.0f/m_speed);
+ return ERR_CONTINUE;
+ }
+ }
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskManip::Abort()
+{
+ int i;
+
+ if ( m_object->RetFret() == 0 ) // not carrying anything?
+ {
+ m_hand = TMH_OPEN; // open clamp
+ m_arm = TMA_NEUTRAL;
+ }
+ else
+ {
+ m_hand = TMH_CLOSE; // closed clamp
+ m_arm = TMA_STOCK;
+ }
+ InitAngle();
+
+ if ( !m_bSubm )
+ {
+ for ( i=0 ; i<5 ; i++ )
+ {
+ m_object->SetAngleZ(i+1, m_finalAngle[i]);
+ }
+ }
+
+ m_camera->StopCentering(m_object, 2.0f);
+ m_physics->SetFreeze(false); // is moving again
+ return true;
+}
+
+
+// Seeks the object below to take (for bees).
+
+CObject* CTaskManip::SearchTakeUnderObject(Math::Vector &pos, float dLimit)
+{
+ CObject *pObj, *pBest;
+ Math::Vector iPos, oPos;
+ ObjectType type;
+ float min, distance;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+
+ min = 1000000.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+
+ if ( type != OBJECT_FRET &&
+ type != OBJECT_STONE &&
+ type != OBJECT_URANIUM &&
+ type != OBJECT_BULLET &&
+ type != OBJECT_METAL &&
+ type != OBJECT_POWER &&
+ type != OBJECT_ATOMIC &&
+ type != OBJECT_BBOX &&
+ type != OBJECT_KEYa &&
+ type != OBJECT_KEYb &&
+ type != OBJECT_KEYc &&
+ type != OBJECT_KEYd &&
+ type != OBJECT_TNT ) continue;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( pObj->RetLock() ) continue;
+ if ( pObj->RetZoomY(0) != 1.0f ) continue;
+
+ oPos = pObj->RetPosition(0);
+ distance = Math::Distance(oPos, iPos);
+ if ( distance <= dLimit &&
+ distance < min )
+ {
+ min = distance;
+ pBest = pObj;
+ }
+ }
+ if ( pBest != 0 )
+ {
+ pos = pBest->RetPosition(0);
+ }
+ return pBest;
+}
+
+// Seeks the object in front to take.
+
+CObject* CTaskManip::SearchTakeFrontObject(bool bAdvance, Math::Vector &pos,
+ float &distance, float &angle)
+{
+ CObject *pObj, *pBest;
+ Math::Vector iPos, oPos;
+ ObjectType type;
+ float min, iAngle, bAngle, aLimit, dLimit, f;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+
+ if ( bAdvance && m_energy > 0.0f )
+ {
+ aLimit = 60.0f*Math::PI/180.0f;
+ dLimit = MARGIN_FRONT+10.0f;
+ }
+ else
+ {
+//? aLimit = 7.0f*Math::PI/180.0f;
+ aLimit = 15.0f*Math::PI/180.0f; //OK 1.9
+ dLimit = MARGIN_FRONT;
+ }
+
+ min = 1000000.0f;
+ pBest = 0;
+ bAngle = 0.0f;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+
+ if ( type != OBJECT_FRET &&
+ type != OBJECT_STONE &&
+ type != OBJECT_URANIUM &&
+ type != OBJECT_BULLET &&
+ type != OBJECT_METAL &&
+ type != OBJECT_POWER &&
+ type != OBJECT_ATOMIC &&
+ type != OBJECT_BBOX &&
+ type != OBJECT_KEYa &&
+ type != OBJECT_KEYb &&
+ type != OBJECT_KEYc &&
+ type != OBJECT_KEYd &&
+ type != OBJECT_TNT &&
+ type != OBJECT_SCRAP1 &&
+ type != OBJECT_SCRAP2 &&
+ type != OBJECT_SCRAP3 &&
+ type != OBJECT_SCRAP4 &&
+ type != OBJECT_SCRAP5 ) continue;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( pObj->RetLock() ) continue;
+ if ( pObj->RetZoomY(0) != 1.0f ) continue;
+
+ oPos = pObj->RetPosition(0);
+ distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST);
+ f = 1.0f-distance/50.0f;
+ if ( f < 0.5f ) f = 0.5f;
+
+ angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+ if ( !Math::TestAngle(angle, iAngle-aLimit*f, iAngle+aLimit*f) ) continue;
+
+ if ( distance < -dLimit ||
+ distance > dLimit ) continue;
+
+ if ( distance < min )
+ {
+ min = distance;
+ pBest = pObj;
+ bAngle = angle;
+ }
+ }
+ if ( pBest == 0 )
+ {
+ distance = 1000000.0f;
+ angle = 0.0f;
+ }
+ else
+ {
+ pos = pBest->RetPosition(0);
+ distance = min;
+ angle = bAngle;
+ }
+ return pBest;
+}
+
+// Seeks the object back to take.
+
+CObject* CTaskManip::SearchTakeBackObject(bool bAdvance, Math::Vector &pos,
+ float &distance, float &angle)
+{
+ CObject *pObj, *pBest;
+ Math::Vector iPos, oPos;
+ ObjectType type;
+ float min, iAngle, bAngle, aLimit, dLimit, f;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+ iAngle = m_object->RetAngleY(0)+Math::PI;
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+
+ if ( bAdvance && m_energy > 0.0f )
+ {
+ aLimit = 60.0f*Math::PI/180.0f;
+ dLimit = MARGIN_BACK+5.0f;
+ }
+ else
+ {
+ aLimit = 7.0f*Math::PI/180.0f;
+ dLimit = MARGIN_BACK;
+ }
+
+ min = 1000000.0f;
+ pBest = 0;
+ bAngle = 0.0f;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+
+ if ( type != OBJECT_FRET &&
+ type != OBJECT_STONE &&
+ type != OBJECT_URANIUM &&
+ type != OBJECT_BULLET &&
+ type != OBJECT_METAL &&
+ type != OBJECT_POWER &&
+ type != OBJECT_ATOMIC &&
+ type != OBJECT_BBOX &&
+ type != OBJECT_KEYa &&
+ type != OBJECT_KEYb &&
+ type != OBJECT_KEYc &&
+ type != OBJECT_KEYd &&
+ type != OBJECT_TNT &&
+ type != OBJECT_SCRAP1 &&
+ type != OBJECT_SCRAP2 &&
+ type != OBJECT_SCRAP3 &&
+ type != OBJECT_SCRAP4 &&
+ type != OBJECT_SCRAP5 ) continue;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( pObj->RetLock() ) continue;
+ if ( pObj->RetZoomY(0) != 1.0f ) continue;
+
+ oPos = pObj->RetPosition(0);
+ distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST);
+ f = 1.0f-distance/50.0f;
+ if ( f < 0.5f ) f = 0.5f;
+
+ angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+ if ( !Math::TestAngle(angle, iAngle-aLimit*f, iAngle+aLimit*f) ) continue;
+
+ if ( distance < -dLimit ||
+ distance > dLimit ) continue;
+
+ if ( distance < min )
+ {
+ min = distance;
+ pBest = pObj;
+ bAngle = angle;
+ }
+ }
+ if ( pBest == 0 )
+ {
+ distance = 1000000.0f;
+ angle = 0.0f;
+ }
+ else
+ {
+ pos = pBest->RetPosition(0);
+ distance = min;
+ angle = bAngle;
+ }
+ return pBest;
+}
+
+// Seeks the robot or building on which it wants to put a battery or or other object.
+
+CObject* CTaskManip::SearchOtherObject(bool bAdvance, Math::Vector &pos,
+ float &distance, float &angle,
+ float &height)
+{
+ Character* character;
+ CObject* pObj;
+ CObject* pPower;
+ Math::Matrix* mat;
+ Math::Vector iPos, oPos;
+ ObjectType type, powerType;
+ float iAngle, iRad, oAngle, oLimit, aLimit, dLimit;
+ int i;
+
+ distance = 1000000.0f;
+ angle = 0.0f;
+
+ if ( m_bSubm ) return 0; // impossible with the submarine
+
+ if ( !m_object->GetCrashSphere(0, iPos, iRad) ) return 0;
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+
+ if ( bAdvance && m_energy > 0.0f )
+ {
+ aLimit = 60.0f*Math::PI/180.0f;
+ dLimit = MARGIN_FRIEND+10.0f;
+ }
+ else
+ {
+ aLimit = 7.0f*Math::PI/180.0f;
+ dLimit = MARGIN_FRIEND;
+ }
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue; // yourself?
+
+ type = pObj->RetType();
+ if ( type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis &&
+ type != OBJECT_MOBILErt &&
+ type != OBJECT_MOBILErc &&
+ type != OBJECT_MOBILErr &&
+ type != OBJECT_MOBILErs &&
+ type != OBJECT_MOBILEsa &&
+ type != OBJECT_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_TOWER &&
+ type != OBJECT_RESEARCH &&
+ type != OBJECT_ENERGY &&
+ type != OBJECT_LABO &&
+ type != OBJECT_NUCLEAR ) continue;
+
+ pPower = pObj->RetPower();
+ if ( pPower != 0 )
+ {
+ if ( pPower->RetLock() ) continue;
+ if ( pPower->RetZoomY(0) != 1.0f ) continue;
+
+ powerType = pPower->RetType();
+ if ( powerType == OBJECT_NULL ||
+ powerType == OBJECT_FIX ) continue;
+ }
+
+ mat = pObj->RetWorldMatrix(0);
+ character = pObj->RetCharacter();
+ oPos = Transform(*mat, character->posPower);
+
+ oAngle = pObj->RetAngleY(0);
+ if ( type == OBJECT_TOWER ||
+ type == OBJECT_RESEARCH )
+ {
+ oLimit = 45.0f*Math::PI/180.0f;
+ }
+ else if ( type == OBJECT_ENERGY )
+ {
+ oLimit = 90.0f*Math::PI/180.0f;
+ }
+ else if ( type == OBJECT_LABO )
+ {
+ oLimit = 120.0f*Math::PI/180.0f;
+ }
+ else if ( type == OBJECT_NUCLEAR )
+ {
+ oLimit = 45.0f*Math::PI/180.0f;
+ }
+ else
+ {
+ oLimit = 45.0f*Math::PI/180.0f;
+ oAngle += Math::PI; // is behind
+ }
+ oAngle = Math::NormAngle(oAngle); // 0..2*Math::PI
+ angle = Math::RotateAngle(iPos.x-oPos.x, oPos.z-iPos.z); // CW !
+ if ( !Math::TestAngle(angle, oAngle-oLimit, oAngle+oLimit) ) continue;
+
+ distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST);
+ if ( distance <= dLimit )
+ {
+ angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+ if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
+ {
+ character = pObj->RetCharacter();
+ height = character->posPower.y;
+ pos = oPos;
+ return pObj;
+ }
+ }
+ }
+
+ distance = 1000000.0f;
+ angle = 0.0f;
+ return 0;
+}
+
+// Takes the object placed in front.
+
+bool CTaskManip::TruckTakeObject()
+{
+ CObject* fret;
+ CObject* other;
+ Math::Matrix matRotate;
+ Math::Vector pos;
+ float angle, dist;
+
+ if ( m_arm == TMA_GRAB ) // takes immediately?
+ {
+ fret = m_object->RetFret();
+ if ( fret == 0 ) return false; // nothing to take?
+ m_fretType = fret->RetType();
+
+ if ( m_object->RetType() == OBJECT_HUMAN ||
+ m_object->RetType() == OBJECT_TECH )
+ {
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(4); // takes with the hand
+
+ fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f));
+ fret->SetAngleY(0, 0.1f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.8f);
+ }
+ else if ( m_bSubm )
+ {
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(2); // takes with the right claw
+
+ pos = Math::Vector(1.1f, -1.0f, 1.0f); // relative
+ fret->SetPosition(0, pos);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleY(0, 0.0f);
+ fret->SetAngleZ(0, 0.0f);
+ }
+ else
+ {
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(3); // takes with the hand
+
+ pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
+ fret->SetPosition(0, pos);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, Math::PI/2.0f);
+ fret->SetAngleY(0, 0.0f);
+ }
+
+ m_object->SetFret(fret); // takes
+ }
+
+ if ( m_arm == TMA_FFRONT ) // takes on the ground in front?
+ {
+ fret = SearchTakeFrontObject(false, pos, dist, angle);
+ if ( fret == 0 ) return false; // nothing to take?
+ m_fretType = fret->RetType();
+
+ if ( m_bSubm )
+ {
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(2); // takes with the right claw
+
+ pos = Math::Vector(1.1f, -1.0f, 1.0f); // relative
+ fret->SetPosition(0, pos);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleY(0, 0.0f);
+ fret->SetAngleZ(0, 0.0f);
+ }
+ else
+ {
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(3); // takes with the hand
+
+ pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
+ fret->SetPosition(0, pos);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, Math::PI/2.0f);
+ fret->SetAngleY(0, 0.0f);
+ }
+
+ m_object->SetFret(fret); // takes
+ }
+
+ if ( m_arm == TMA_FBACK ) // takes on the ground behind?
+ {
+ fret = SearchTakeBackObject(false, pos, dist, angle);
+ if ( fret == 0 ) return false; // nothing to take?
+ m_fretType = fret->RetType();
+
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(3); // takes with the hand
+
+ pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
+ fret->SetPosition(0, pos);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, Math::PI/2.0f);
+ fret->SetAngleY(0, 0.0f);
+
+ m_object->SetFret(fret); // takes
+ }
+
+ if ( m_arm == TMA_POWER ) // takes battery in the back?
+ {
+ fret = m_object->RetPower();
+ if ( fret == 0 ) return false; // no battery?
+ m_fretType = fret->RetType();
+
+ pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
+ fret->SetPosition(0, pos);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, Math::PI/2.0f);
+ fret->SetAngleY(0, 0.0f);
+ fret->SetTruckPart(3); // takes with the hand
+
+ m_object->SetPower(0);
+ m_object->SetFret(fret); // takes
+ }
+
+ if ( m_arm == TMA_OTHER ) // battery takes from friend?
+ {
+ other = SearchOtherObject(false, pos, dist, angle, m_height);
+ if ( other == 0 ) return false;
+
+ fret = other->RetPower();
+ if ( fret == 0 ) return false; // the other does not have a battery?
+ m_fretType = fret->RetType();
+
+ other->SetPower(0);
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(3); // takes with the hand
+
+ pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
+ fret->SetPosition(0, pos);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, Math::PI/2.0f);
+ fret->SetAngleY(0, 0.0f);
+
+ m_object->SetFret(fret); // takes
+ }
+
+ return true;
+}
+
+// Deposes the object taken.
+
+bool CTaskManip::TruckDeposeObject()
+{
+ Character* character;
+ CObject* fret;
+ CObject* other;
+ Math::Matrix* mat;
+ Math::Vector pos;
+ float angle, dist;
+
+ if ( m_arm == TMA_FFRONT ) // deposits on the ground in front?
+ {
+ fret = m_object->RetFret();
+ if ( fret == 0 ) return false; // nothing transported?
+ m_fretType = fret->RetType();
+
+ mat = fret->RetWorldMatrix(0);
+ pos = Transform(*mat, Math::Vector(0.0f, 1.0f, 0.0f));
+ m_terrain->MoveOnFloor(pos);
+ fret->SetPosition(0, pos);
+ fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.0f);
+ fret->FloorAdjust(); // plate well on the ground
+
+ fret->SetTruck(0);
+ m_object->SetFret(0); // deposit
+ }
+
+ if ( m_arm == TMA_FBACK ) // deposited on the ground behind?
+ {
+ fret = m_object->RetFret();
+ if ( fret == 0 ) return false; // nothing transported?
+ m_fretType = fret->RetType();
+
+ mat = fret->RetWorldMatrix(0);
+ pos = Transform(*mat, Math::Vector(0.0f, 1.0f, 0.0f));
+ m_terrain->MoveOnFloor(pos);
+ fret->SetPosition(0, pos);
+ fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.0f);
+
+ fret->SetTruck(0);
+ m_object->SetFret(0); // deposit
+ }
+
+ if ( m_arm == TMA_POWER ) // deposits battery in the back?
+ {
+ fret = m_object->RetFret();
+ if ( fret == 0 ) return false; // nothing transported?
+ m_fretType = fret->RetType();
+
+ if ( m_object->RetPower() != 0 ) return false;
+
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(0); // carried by the base
+
+ character = m_object->RetCharacter();
+ fret->SetPosition(0, character->posPower);
+ fret->SetAngleY(0, 0.0f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.0f);
+
+ m_object->SetPower(fret); // uses
+ m_object->SetFret(0);
+ }
+
+ if ( m_arm == TMA_OTHER ) // deposits battery on friend?
+ {
+ other = SearchOtherObject(false, pos, dist, angle, m_height);
+ if ( other == 0 ) return false;
+
+ fret = other->RetPower();
+ if ( fret != 0 ) return false; // the other already has a battery?
+
+ fret = m_object->RetFret();
+ if ( fret == 0 ) return false;
+ m_fretType = fret->RetType();
+
+ other->SetPower(fret);
+ fret->SetTruck(other);
+
+ character = other->RetCharacter();
+ fret->SetPosition(0, character->posPower);
+ fret->SetAngleY(0, 0.0f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.0f);
+ fret->SetTruckPart(0); // carried by the base
+
+ m_object->SetFret(0); // deposit
+ }
+
+ return true;
+}
+
+// Seeks if a location allows to deposit an object.
+
+bool CTaskManip::IsFreeDeposeObject(Math::Vector pos)
+{
+ CObject* pObj;
+ Math::Matrix* mat;
+ Math::Vector iPos, oPos;
+ float oRadius;
+ int i, j;
+
+ mat = m_object->RetWorldMatrix(0);
+ iPos = Transform(*mat, pos);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue;
+ if ( !pObj->RetActif() ) continue; // inactive?
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ if ( Math::Distance(iPos, oPos)-(oRadius+1.0f) < 2.0f )
+ {
+ return false; // location occupied
+ }
+ }
+ }
+ return true; // location free
+}
+
+// Plays the sound of the manipulator arm.
+
+void CTaskManip::SoundManip(float time, float amplitude, float frequency)
+{
+ int i;
+
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
+ m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
+}
+
diff --git a/src/object/task/taskmanip.h b/src/object/task/taskmanip.h
index d915558..79d9ad5 100644
--- a/src/object/task/taskmanip.h
+++ b/src/object/task/taskmanip.h
@@ -1,99 +1,99 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskmanip.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-#include "math/vector.h"
-
-
-
-enum TaskManipOrder
-{
- TMO_AUTO = 0, // deposits or takes automatically
- TMO_GRAB = 1, // takes an object
- TMO_DROP = 2, // deposits the object
-};
-
-enum TaskManipArm
-{
- TMA_NEUTRAL = 1, // empty arm at rest
- TMA_STOCK = 2, // right arm resting
- TMA_FFRONT = 3, // arm on the ground
- TMA_FBACK = 4, // arm behind the robot
- TMA_POWER = 5, // arm behind the robot
- TMA_OTHER = 6, // arm behind a friend robot
- TMA_GRAB = 7, // takes immediately
-};
-
-enum TaskManipHand
-{
- TMH_OPEN = 1, // open clamp
- TMH_CLOSE = 2, // closed clamp
-};
-
-
-
-class CTaskManip : public CTask
-{
-public:
- CTaskManip(CInstanceManager* iMan, CObject* object);
- ~CTaskManip();
-
- bool EventProcess(const Event &event);
-
- Error Start(TaskManipOrder order, TaskManipArm arm);
- Error IsEnded();
- bool Abort();
-
-protected:
- void InitAngle();
- CObject* SearchTakeUnderObject(Math::Vector &pos, float dLimit);
- CObject* SearchTakeFrontObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle);
- CObject* SearchTakeBackObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle);
- CObject* SearchOtherObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle, float &height);
- bool TruckTakeObject();
- bool TruckDeposeObject();
- bool IsFreeDeposeObject(Math::Vector pos);
- void SoundManip(float time, float amplitude=1.0f, float frequency=1.0f);
-
-protected:
- TaskManipOrder m_order;
- TaskManipArm m_arm;
- TaskManipHand m_hand;
- int m_step;
- float m_speed;
- float m_progress;
- float m_initialAngle[5];
- float m_finalAngle[5];
- float m_height;
- float m_advanceLength;
- float m_energy;
- bool m_bError;
- bool m_bTurn;
- bool m_bSubm;
- bool m_bBee;
- float m_angle;
- float m_move;
- Math::Vector m_targetPos;
- float m_timeLimit;
- ObjectType m_fretType;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskmanip.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "object/object.h"
+#include "math/vector.h"
+
+
+
+enum TaskManipOrder
+{
+ TMO_AUTO = 0, // deposits or takes automatically
+ TMO_GRAB = 1, // takes an object
+ TMO_DROP = 2, // deposits the object
+};
+
+enum TaskManipArm
+{
+ TMA_NEUTRAL = 1, // empty arm at rest
+ TMA_STOCK = 2, // right arm resting
+ TMA_FFRONT = 3, // arm on the ground
+ TMA_FBACK = 4, // arm behind the robot
+ TMA_POWER = 5, // arm behind the robot
+ TMA_OTHER = 6, // arm behind a friend robot
+ TMA_GRAB = 7, // takes immediately
+};
+
+enum TaskManipHand
+{
+ TMH_OPEN = 1, // open clamp
+ TMH_CLOSE = 2, // closed clamp
+};
+
+
+
+class CTaskManip : public CTask
+{
+public:
+ CTaskManip(CInstanceManager* iMan, CObject* object);
+ ~CTaskManip();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(TaskManipOrder order, TaskManipArm arm);
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ void InitAngle();
+ CObject* SearchTakeUnderObject(Math::Vector &pos, float dLimit);
+ CObject* SearchTakeFrontObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle);
+ CObject* SearchTakeBackObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle);
+ CObject* SearchOtherObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle, float &height);
+ bool TruckTakeObject();
+ bool TruckDeposeObject();
+ bool IsFreeDeposeObject(Math::Vector pos);
+ void SoundManip(float time, float amplitude=1.0f, float frequency=1.0f);
+
+protected:
+ TaskManipOrder m_order;
+ TaskManipArm m_arm;
+ TaskManipHand m_hand;
+ int m_step;
+ float m_speed;
+ float m_progress;
+ float m_initialAngle[5];
+ float m_finalAngle[5];
+ float m_height;
+ float m_advanceLength;
+ float m_energy;
+ bool m_bError;
+ bool m_bTurn;
+ bool m_bSubm;
+ bool m_bBee;
+ float m_angle;
+ float m_move;
+ Math::Vector m_targetPos;
+ float m_timeLimit;
+ ObjectType m_fretType;
+};
+
diff --git a/src/object/task/taskpen.cpp b/src/object/task/taskpen.cpp
index ff2f4e0..c3a9aef 100644
--- a/src/object/task/taskpen.cpp
+++ b/src/object/task/taskpen.cpp
@@ -1,287 +1,287 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskpen.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskpen.h"
-
-#include "old/particule.h"
-#include "math/geometry.h"
-#include "object/object.h"
-
-
-
-// Object's constructor.
-
-CTaskPen::CTaskPen(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskPen::~CTaskPen()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskPen::EventProcess(const Event &event)
-{
- Math::Vector pos, speed;
- Math::Point dim;
- int i;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- if ( m_delay == 0.0f )
- {
- m_progress = 1.0f;
- }
- else
- {
- m_progress += event.rTime*(1.0f/m_delay); // others advance
- if ( m_progress > 1.0f ) m_progress = 1.0f;
- }
-
- m_time += event.rTime;
-
- if ( m_phase == TPP_UP ) // back the pencil
- {
- i = AngleToRank(m_object->RetAngleY(1));
- pos = m_object->RetPosition(10+i);
- pos.y = -3.2f*(1.0f-m_progress);
- m_object->SetPosition(10+i, pos);
- }
-
- if ( m_phase == TPP_TURN ) // turns the carousel?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_supportPos;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = (Math::Rand()-0.5f)*3.0f;
- speed.z = (Math::Rand()-0.5f)*3.0f;
- speed.y = Math::Rand()*2.0f;
- dim.x = Math::Rand()*1.5f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
- }
-
- m_object->SetAngleY(1, m_oldAngle+(m_newAngle-m_oldAngle)*m_progress);
- }
-
- if ( m_phase == TPP_DOWN ) // down the pencil?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_supportPos;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = (Math::Rand()-0.5f)*3.0f;
- speed.z = (Math::Rand()-0.5f)*3.0f;
- speed.y = Math::Rand()*5.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIVAPOR, 4.0f);
- }
-
- i = AngleToRank(m_object->RetAngleY(1));
- pos = m_object->RetPosition(10+i);
- if ( m_timeDown == 0.0f )
- {
- pos.y = 0.0f;
- }
- else
- {
- pos.y = -3.2f*Math::Bounce(Math::Min(m_progress*1.8f, 1.0f));
- }
- m_object->SetPosition(10+i, pos);
- }
-
- return true;
-}
-
-
-// Assigns the goal has achieved.
-
-Error CTaskPen::Start(bool bDown, int color)
-{
- Math::Vector pos;
- Math::Matrix* mat;
- ObjectType type;
- int i;
-
- m_bError = true; // operation impossible
-
- type = m_object->RetType();
- if ( type != OBJECT_MOBILEdr ) return ERR_FIRE_VEH;
-
- m_bError = false; // ok
-
- m_oldAngle = m_object->RetAngleY(1);
- m_newAngle = ColorToAngle(color);
-
- i = AngleToRank(m_oldAngle);
- pos = m_object->RetPosition(10+i);
-
- if ( pos.y == 0.0f ) // pencil at the top?
- {
- m_timeUp = 0.0f;
- }
- else // pencil on the bottom?
- {
- m_timeUp = 1.0f; // must rise up
- }
-
- if ( bDown ) // must go down ?
- {
- m_timeDown = 0.7f;
- }
- else
- {
- m_timeDown = 0.0f;
- }
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(-3.0f, 7.0f, 0.0f);
- pos = Math::Transform(*mat, pos); // position of carousel
- m_supportPos = pos;
-
- m_phase = TPP_UP;
- m_progress = 0.0f;
- m_delay = m_timeUp;
- m_time = 0.0f;
-
- if ( m_timeUp > 0.0f )
- {
- SoundManip(m_timeUp, 1.0f, 0.5f);
- }
-
- m_lastParticule = 0.0f;
-
-//? m_camera->StartCentering(m_object, Math::PI*0.60f, 99.9f, 5.0f, 0.5f);
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskPen::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( m_phase == TPP_UP )
- {
- m_phase = TPP_TURN;
- m_progress = 0.0f;
- m_delay = fabs(m_oldAngle-m_newAngle)/Math::PI;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- if ( m_delay > 0.0f )
- {
- SoundManip(m_delay, 1.0f, 1.0f);
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TPP_TURN )
- {
- m_sound->Play(SOUND_PSHHH2, m_supportPos, 1.0f, 1.4f);
- m_phase = TPP_DOWN;
- m_progress = 0.0f;
- m_delay = m_timeDown;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- return ERR_CONTINUE;
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskPen::Abort()
-{
-//? m_camera->StopCentering(m_object, 0.5f);
- return true;
-}
-
-
-// Plays the sound of the manipulator arm.
-
-void CTaskPen::SoundManip(float time, float amplitude, float frequency)
-{
- int i;
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
-}
-
-
-// Converting a angle to number of pencil.
-
-int CTaskPen::AngleToRank(float angle)
-{
-//? return (int)(angle/(-45.0f*Math::PI/180.0f));
- angle = -angle;
- angle += (45.0f*Math::PI/180.0f)/2.0f;
- return (int)(angle/(45.0f*Math::PI/180.0f));
-}
-
-// Converting a color to the angle of carousel of pencils.
-
-float CTaskPen::ColorToAngle(int color)
-{
- return -45.0f*Math::PI/180.0f*ColorToRank(color);
-}
-
-// Converting a color number to the pencil (0 .. 7).
-
-int CTaskPen::ColorToRank(int color)
-{
- if ( color == 8 ) return 1; // yellow
- if ( color == 7 ) return 2; // orange
- if ( color == 5 ) return 2; // pink
- if ( color == 4 ) return 3; // red
- if ( color == 6 ) return 4; // purple
- if ( color == 14 ) return 5; // blue
- if ( color == 15 ) return 5; // light blue
- if ( color == 12 ) return 6; // green
- if ( color == 13 ) return 6; // light green
- if ( color == 10 ) return 7; // brown
- if ( color == 9 ) return 7; // beige
- return 0; // black
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskpen.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskpen.h"
+
+#include "old/particule.h"
+#include "math/geometry.h"
+#include "object/object.h"
+
+
+
+// Object's constructor.
+
+CTaskPen::CTaskPen(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+}
+
+// Object's destructor.
+
+CTaskPen::~CTaskPen()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskPen::EventProcess(const Event &event)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+ int i;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ if ( m_delay == 0.0f )
+ {
+ m_progress = 1.0f;
+ }
+ else
+ {
+ m_progress += event.rTime*(1.0f/m_delay); // others advance
+ if ( m_progress > 1.0f ) m_progress = 1.0f;
+ }
+
+ m_time += event.rTime;
+
+ if ( m_phase == TPP_UP ) // back the pencil
+ {
+ i = AngleToRank(m_object->RetAngleY(1));
+ pos = m_object->RetPosition(10+i);
+ pos.y = -3.2f*(1.0f-m_progress);
+ m_object->SetPosition(10+i, pos);
+ }
+
+ if ( m_phase == TPP_TURN ) // turns the carousel?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_supportPos;
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ speed.x = (Math::Rand()-0.5f)*3.0f;
+ speed.z = (Math::Rand()-0.5f)*3.0f;
+ speed.y = Math::Rand()*2.0f;
+ dim.x = Math::Rand()*1.5f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
+ }
+
+ m_object->SetAngleY(1, m_oldAngle+(m_newAngle-m_oldAngle)*m_progress);
+ }
+
+ if ( m_phase == TPP_DOWN ) // down the pencil?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_supportPos;
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ speed.x = (Math::Rand()-0.5f)*3.0f;
+ speed.z = (Math::Rand()-0.5f)*3.0f;
+ speed.y = Math::Rand()*5.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIVAPOR, 4.0f);
+ }
+
+ i = AngleToRank(m_object->RetAngleY(1));
+ pos = m_object->RetPosition(10+i);
+ if ( m_timeDown == 0.0f )
+ {
+ pos.y = 0.0f;
+ }
+ else
+ {
+ pos.y = -3.2f*Math::Bounce(Math::Min(m_progress*1.8f, 1.0f));
+ }
+ m_object->SetPosition(10+i, pos);
+ }
+
+ return true;
+}
+
+
+// Assigns the goal has achieved.
+
+Error CTaskPen::Start(bool bDown, int color)
+{
+ Math::Vector pos;
+ Math::Matrix* mat;
+ ObjectType type;
+ int i;
+
+ m_bError = true; // operation impossible
+
+ type = m_object->RetType();
+ if ( type != OBJECT_MOBILEdr ) return ERR_FIRE_VEH;
+
+ m_bError = false; // ok
+
+ m_oldAngle = m_object->RetAngleY(1);
+ m_newAngle = ColorToAngle(color);
+
+ i = AngleToRank(m_oldAngle);
+ pos = m_object->RetPosition(10+i);
+
+ if ( pos.y == 0.0f ) // pencil at the top?
+ {
+ m_timeUp = 0.0f;
+ }
+ else // pencil on the bottom?
+ {
+ m_timeUp = 1.0f; // must rise up
+ }
+
+ if ( bDown ) // must go down ?
+ {
+ m_timeDown = 0.7f;
+ }
+ else
+ {
+ m_timeDown = 0.0f;
+ }
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(-3.0f, 7.0f, 0.0f);
+ pos = Math::Transform(*mat, pos); // position of carousel
+ m_supportPos = pos;
+
+ m_phase = TPP_UP;
+ m_progress = 0.0f;
+ m_delay = m_timeUp;
+ m_time = 0.0f;
+
+ if ( m_timeUp > 0.0f )
+ {
+ SoundManip(m_timeUp, 1.0f, 0.5f);
+ }
+
+ m_lastParticule = 0.0f;
+
+//? m_camera->StartCentering(m_object, Math::PI*0.60f, 99.9f, 5.0f, 0.5f);
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskPen::IsEnded()
+{
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+ m_progress = 0.0f;
+
+ if ( m_phase == TPP_UP )
+ {
+ m_phase = TPP_TURN;
+ m_progress = 0.0f;
+ m_delay = fabs(m_oldAngle-m_newAngle)/Math::PI;
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+ if ( m_delay > 0.0f )
+ {
+ SoundManip(m_delay, 1.0f, 1.0f);
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TPP_TURN )
+ {
+ m_sound->Play(SOUND_PSHHH2, m_supportPos, 1.0f, 1.4f);
+ m_phase = TPP_DOWN;
+ m_progress = 0.0f;
+ m_delay = m_timeDown;
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+ return ERR_CONTINUE;
+ }
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskPen::Abort()
+{
+//? m_camera->StopCentering(m_object, 0.5f);
+ return true;
+}
+
+
+// Plays the sound of the manipulator arm.
+
+void CTaskPen::SoundManip(float time, float amplitude, float frequency)
+{
+ int i;
+
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
+ m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
+}
+
+
+// Converting a angle to number of pencil.
+
+int CTaskPen::AngleToRank(float angle)
+{
+//? return (int)(angle/(-45.0f*Math::PI/180.0f));
+ angle = -angle;
+ angle += (45.0f*Math::PI/180.0f)/2.0f;
+ return (int)(angle/(45.0f*Math::PI/180.0f));
+}
+
+// Converting a color to the angle of carousel of pencils.
+
+float CTaskPen::ColorToAngle(int color)
+{
+ return -45.0f*Math::PI/180.0f*ColorToRank(color);
+}
+
+// Converting a color number to the pencil (0 .. 7).
+
+int CTaskPen::ColorToRank(int color)
+{
+ if ( color == 8 ) return 1; // yellow
+ if ( color == 7 ) return 2; // orange
+ if ( color == 5 ) return 2; // pink
+ if ( color == 4 ) return 3; // red
+ if ( color == 6 ) return 4; // purple
+ if ( color == 14 ) return 5; // blue
+ if ( color == 15 ) return 5; // light blue
+ if ( color == 12 ) return 6; // green
+ if ( color == 13 ) return 6; // light green
+ if ( color == 10 ) return 7; // brown
+ if ( color == 9 ) return 7; // beige
+ return 0; // black
+}
+
diff --git a/src/object/task/taskpen.h b/src/object/task/taskpen.h
index 3c65d2e..b41c513 100644
--- a/src/object/task/taskpen.h
+++ b/src/object/task/taskpen.h
@@ -1,68 +1,68 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskpen.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-enum TaskPenPhase
-{
- TPP_UP = 1, // rises the pencil
- TPP_TURN = 2, // turns the carousel
- TPP_DOWN = 3, // descends the pencil
-};
-
-
-
-class CTaskPen : public CTask
-{
-public:
- CTaskPen(CInstanceManager* iMan, CObject* object);
- ~CTaskPen();
-
- bool EventProcess(const Event &event);
-
- Error Start(bool bDown, int color);
- Error IsEnded();
- bool Abort();
-
-protected:
- void SoundManip(float time, float amplitude, float frequency);
- int AngleToRank(float angle);
- float ColorToAngle(int color);
- int ColorToRank(int color);
-
-protected:
- bool m_bError;
- TaskPenPhase m_phase;
- float m_progress;
- float m_delay;
- float m_time;
- float m_lastParticule;
- Math::Vector m_supportPos;
-
- float m_timeUp;
- float m_oldAngle;
- float m_newAngle;
- float m_timeDown;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskpen.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "math/vector.h"
+
+
+
+enum TaskPenPhase
+{
+ TPP_UP = 1, // rises the pencil
+ TPP_TURN = 2, // turns the carousel
+ TPP_DOWN = 3, // descends the pencil
+};
+
+
+
+class CTaskPen : public CTask
+{
+public:
+ CTaskPen(CInstanceManager* iMan, CObject* object);
+ ~CTaskPen();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(bool bDown, int color);
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ void SoundManip(float time, float amplitude, float frequency);
+ int AngleToRank(float angle);
+ float ColorToAngle(int color);
+ int ColorToRank(int color);
+
+protected:
+ bool m_bError;
+ TaskPenPhase m_phase;
+ float m_progress;
+ float m_delay;
+ float m_time;
+ float m_lastParticule;
+ Math::Vector m_supportPos;
+
+ float m_timeUp;
+ float m_oldAngle;
+ float m_newAngle;
+ float m_timeDown;
+};
+
diff --git a/src/object/task/taskrecover.cpp b/src/object/task/taskrecover.cpp
index d91c45d..8f603f7 100644
--- a/src/object/task/taskrecover.cpp
+++ b/src/object/task/taskrecover.cpp
@@ -1,417 +1,417 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskrecover.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskrecover.h"
-
-#include "math/geometry.h"
-#include "common/iman.h"
-#include "old/particule.h"
-#include "physics/physics.h"
-#include "ui/displaytext.h"
-
-
-const float ENERGY_RECOVER = 0.25f; // energy consumed by recovery
-const float RECOVER_DIST = 11.8f;
-
-
-
-// Object's constructor.
-
-CTaskRecover::CTaskRecover(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_ruin = 0;
- m_soundChannel = -1;
-}
-
-// Object's constructor.
-
-CTaskRecover::~CTaskRecover()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskRecover::EventProcess(const Event &event)
-{
- CObject* power;
- Math::Vector pos, speed;
- Math::Point dim;
- float a, g, cirSpeed, angle, energy, dist, linSpeed;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- if ( m_phase == TRP_TURN ) // preliminary rotation?
- {
- a = m_object->RetAngleY(0);
- g = m_angle;
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- return true;
- }
-
- m_progress += event.rTime*m_speed; // others advance
- m_time += event.rTime;
-
- if ( m_phase == TRP_DOWN )
- {
- angle = Math::PropAngle(126, -10, m_progress);
- m_object->SetAngleZ(2, angle);
- m_object->SetAngleZ(4, angle);
-
- angle = Math::PropAngle(-144, 0, m_progress);
- m_object->SetAngleZ(3, angle);
- m_object->SetAngleZ(5, angle);
- }
-
- if ( m_phase == TRP_MOVE ) // preliminary forward/backward?
- {
- dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0));
- linSpeed = 0.0f;
- if ( dist > RECOVER_DIST ) linSpeed = 1.0f;
- if ( dist < RECOVER_DIST ) linSpeed = -1.0f;
- m_physics->SetMotorSpeedX(linSpeed); // forward/backward
- return true;
- }
-
- if ( m_phase == TRP_OPER )
- {
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- power->SetEnergy(energy-ENERGY_RECOVER*event.rTime*m_speed);
- }
-
- speed.x = (Math::Rand()-0.5f)*0.1f*m_progress;
- speed.y = (Math::Rand()-0.5f)*0.1f*m_progress;
- speed.z = (Math::Rand()-0.5f)*0.1f*m_progress;
- m_ruin->SetCirVibration(speed);
-
- if ( m_progress >= 0.75f )
- {
- m_ruin->SetZoom(0, 1.0f-(m_progress-0.75f)/0.25f);
- }
-
- if ( m_progress > 0.5f && m_progress < 0.8f )
- {
- m_metal->SetZoom(0, (m_progress-0.5f)/0.3f);
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.02f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_recoverPos;
- pos.x += (Math::Rand()-0.5f)*8.0f*(1.0f-m_progress);
- pos.z += (Math::Rand()-0.5f)*8.0f*(1.0f-m_progress);
- pos.y -= 4.0f;
- speed.x = (Math::Rand()-0.5f)*0.0f;
- speed.z = (Math::Rand()-0.5f)*0.0f;
- speed.y = Math::Rand()*15.0f;
- dim.x = Math::Rand()*2.0f+1.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIRECOVER, 1.0f, 0.0f, 0.0f);
- }
- }
-
- if ( m_phase == TRP_UP )
- {
- angle = Math::PropAngle(-10, 126, m_progress);
- m_object->SetAngleZ(2, angle);
- m_object->SetAngleZ(4, angle);
-
- angle = Math::PropAngle(0, -144, m_progress);
- m_object->SetAngleZ(3, angle);
- m_object->SetAngleZ(5, angle);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.02f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_recoverPos;
- pos.y -= 4.0f;
- speed.x = (Math::Rand()-0.5f)*0.0f;
- speed.z = (Math::Rand()-0.5f)*0.0f;
- speed.y = Math::Rand()*15.0f;
- dim.x = Math::Rand()*2.0f+1.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIRECOVER, 1.0f, 0.0f, 0.0f);
- }
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskRecover::Start()
-{
- CObject* power;
- Math::Matrix* mat;
- Math::Vector pos, iPos, oPos;
- float energy;
-
- ObjectType type;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() ) return ERR_RECOVER_VEH;
-
- type = m_object->RetType();
- if ( type != OBJECT_MOBILErr ) return ERR_RECOVER_VEH;
-
- power = m_object->RetPower();
- if ( power == 0 ) return ERR_RECOVER_ENERGY;
- energy = power->RetEnergy();
- if ( energy < ENERGY_RECOVER/power->RetCapacity()+0.05f ) return ERR_RECOVER_ENERGY;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(RECOVER_DIST, 3.3f, 0.0f);
- pos = Transform(*mat, pos); // position in front
- m_recoverPos = pos;
-
- m_ruin = SearchRuin();
- if ( m_ruin == 0 ) return ERR_RECOVER_NULL;
- m_ruin->SetLock(true); // ruin no longer usable
-
- iPos = m_object->RetPosition(0);
- oPos = m_ruin->RetPosition(0);
- m_angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
-
- m_metal = 0;
-
- m_phase = TRP_TURN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
-
- m_bError = false; // ok
-
- m_camera->StartCentering(m_object, Math::PI*0.85f, 99.9f, 10.0f, 3.0f);
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskRecover::IsEnded()
-{
- Math::Matrix* mat;
- Math::Vector pos, speed, goal;
- Math::Point dim;
- float angle, dist, time;
- int i;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_phase == TRP_TURN ) // preliminary rotation?
- {
- angle = m_object->RetAngleY(0);
- angle = Math::NormAngle(angle); // 0..2*Math::PI
-
- if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) )
- {
- m_physics->SetMotorSpeedZ(0.0f);
-
- dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0));
- if ( dist > RECOVER_DIST )
- {
- time = m_physics->RetLinTimeLength(dist-RECOVER_DIST, 1.0f);
- m_speed = 1.0f/time;
- }
- else
- {
- time = m_physics->RetLinTimeLength(RECOVER_DIST-dist, -1.0f);
- m_speed = 1.0f/time;
- }
- m_phase = TRP_MOVE;
- m_progress = 0.0f;
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TRP_MOVE ) // preliminary advance?
- {
- dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0));
-
- if ( dist >= RECOVER_DIST-1.0f &&
- dist <= RECOVER_DIST+1.0f )
- {
- m_physics->SetMotorSpeedX(0.0f);
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(RECOVER_DIST, 3.3f, 0.0f);
- pos = Transform(*mat, pos); // position in front
- m_recoverPos = pos;
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.9f, true);
- m_sound->AddEnvelope(i, 1.0f, 1.5f, 0.3f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 1.0f, 1.5f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.9f, 0.3f, SOPER_STOP);
-
- m_phase = TRP_DOWN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- m_time = 0.0f;
- }
- else
- {
- if ( m_progress > 1.0f ) // timeout?
- {
- m_ruin->SetLock(false); // usable again
- m_camera->StopCentering(m_object, 2.0f);
- return ERR_RECOVER_NULL;
- }
- }
- return ERR_CONTINUE;
- }
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( m_phase == TRP_DOWN )
- {
- m_metal = new CObject(m_iMan);
- if ( !m_metal->CreateResource(m_recoverPos, 0.0f, OBJECT_METAL) )
- {
- delete m_metal;
- m_metal = 0;
- Abort();
- m_bError = true;
- m_displayText->DisplayError(ERR_TOOMANY, m_object);
- return ERR_STOP;
- }
- m_metal->SetLock(true); // metal not yet usable
- m_metal->SetZoom(0, 0.0f);
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(RECOVER_DIST, 3.1f, 3.9f);
- pos = Transform(*mat, pos);
- goal = Math::Vector(RECOVER_DIST, 3.1f, -3.9f);
- goal = Transform(*mat, goal);
- m_particule->CreateRay(pos, goal, PARTIRAY2,
- Math::Point(2.0f, 2.0f), 8.0f);
-
- m_soundChannel = m_sound->Play(SOUND_RECOVER, m_ruin->RetPosition(0), 0.0f, 1.0f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.6f, 1.0f, 2.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.6f, 1.0f, 4.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.7f, 2.0f, SOPER_STOP);
-
- m_phase = TRP_OPER;
- m_speed = 1.0f/8.0f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TRP_OPER )
- {
- m_metal->SetZoom(0, 1.0f);
-
- m_ruin->DeleteObject(); // destroys the ruin
- delete m_ruin;
- m_ruin = 0;
-
- m_soundChannel = -1;
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.9f, true);
- m_sound->AddEnvelope(i, 1.0f, 1.5f, 0.3f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 1.0f, 1.5f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.9f, 0.3f, SOPER_STOP);
-
- m_phase = TRP_UP;
- m_speed = 1.0f/1.5f;
- return ERR_CONTINUE;
- }
-
- m_metal->SetLock(false); // metal usable
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskRecover::Abort()
-{
- m_object->SetAngleZ(2, 126.0f*Math::PI/180.0f);
- m_object->SetAngleZ(4, 126.0f*Math::PI/180.0f);
- m_object->SetAngleZ(3, -144.0f*Math::PI/180.0f);
- m_object->SetAngleZ(5, -144.0f*Math::PI/180.0f); // rest
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- m_camera->StopCentering(m_object, 2.0f);
- return true;
-}
-
-
-// Seeks if a ruin is in front of the vehicle.
-
-CObject* CTaskRecover::SearchRuin()
-{
- CObject *pObj, *pBest;
- Math::Vector oPos;
- ObjectType type;
- float dist, min;
- int i;
-
- pBest = 0;
- min = 100000.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_RUINmobilew1 ||
- type == OBJECT_RUINmobilew2 ||
- type == OBJECT_RUINmobilet1 ||
- type == OBJECT_RUINmobilet2 ||
- type == OBJECT_RUINmobiler1 ||
- type == OBJECT_RUINmobiler2 ) // vehicle in ruin?
- {
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, m_recoverPos);
- if ( dist > 40.0f ) continue;
-
- if ( dist < min )
- {
- min = dist;
- pBest = pObj;
- }
- }
-
- }
- return pBest;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskrecover.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskrecover.h"
+
+#include "math/geometry.h"
+#include "common/iman.h"
+#include "old/particule.h"
+#include "physics/physics.h"
+#include "ui/displaytext.h"
+
+
+const float ENERGY_RECOVER = 0.25f; // energy consumed by recovery
+const float RECOVER_DIST = 11.8f;
+
+
+
+// Object's constructor.
+
+CTaskRecover::CTaskRecover(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_ruin = 0;
+ m_soundChannel = -1;
+}
+
+// Object's constructor.
+
+CTaskRecover::~CTaskRecover()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskRecover::EventProcess(const Event &event)
+{
+ CObject* power;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float a, g, cirSpeed, angle, energy, dist, linSpeed;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ if ( m_phase == TRP_TURN ) // preliminary rotation?
+ {
+ a = m_object->RetAngleY(0);
+ g = m_angle;
+ cirSpeed = Math::Direction(a, g)*1.0f;
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
+ return true;
+ }
+
+ m_progress += event.rTime*m_speed; // others advance
+ m_time += event.rTime;
+
+ if ( m_phase == TRP_DOWN )
+ {
+ angle = Math::PropAngle(126, -10, m_progress);
+ m_object->SetAngleZ(2, angle);
+ m_object->SetAngleZ(4, angle);
+
+ angle = Math::PropAngle(-144, 0, m_progress);
+ m_object->SetAngleZ(3, angle);
+ m_object->SetAngleZ(5, angle);
+ }
+
+ if ( m_phase == TRP_MOVE ) // preliminary forward/backward?
+ {
+ dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0));
+ linSpeed = 0.0f;
+ if ( dist > RECOVER_DIST ) linSpeed = 1.0f;
+ if ( dist < RECOVER_DIST ) linSpeed = -1.0f;
+ m_physics->SetMotorSpeedX(linSpeed); // forward/backward
+ return true;
+ }
+
+ if ( m_phase == TRP_OPER )
+ {
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ power->SetEnergy(energy-ENERGY_RECOVER*event.rTime*m_speed);
+ }
+
+ speed.x = (Math::Rand()-0.5f)*0.1f*m_progress;
+ speed.y = (Math::Rand()-0.5f)*0.1f*m_progress;
+ speed.z = (Math::Rand()-0.5f)*0.1f*m_progress;
+ m_ruin->SetCirVibration(speed);
+
+ if ( m_progress >= 0.75f )
+ {
+ m_ruin->SetZoom(0, 1.0f-(m_progress-0.75f)/0.25f);
+ }
+
+ if ( m_progress > 0.5f && m_progress < 0.8f )
+ {
+ m_metal->SetZoom(0, (m_progress-0.5f)/0.3f);
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.02f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_recoverPos;
+ pos.x += (Math::Rand()-0.5f)*8.0f*(1.0f-m_progress);
+ pos.z += (Math::Rand()-0.5f)*8.0f*(1.0f-m_progress);
+ pos.y -= 4.0f;
+ speed.x = (Math::Rand()-0.5f)*0.0f;
+ speed.z = (Math::Rand()-0.5f)*0.0f;
+ speed.y = Math::Rand()*15.0f;
+ dim.x = Math::Rand()*2.0f+1.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIRECOVER, 1.0f, 0.0f, 0.0f);
+ }
+ }
+
+ if ( m_phase == TRP_UP )
+ {
+ angle = Math::PropAngle(-10, 126, m_progress);
+ m_object->SetAngleZ(2, angle);
+ m_object->SetAngleZ(4, angle);
+
+ angle = Math::PropAngle(0, -144, m_progress);
+ m_object->SetAngleZ(3, angle);
+ m_object->SetAngleZ(5, angle);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.02f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_recoverPos;
+ pos.y -= 4.0f;
+ speed.x = (Math::Rand()-0.5f)*0.0f;
+ speed.z = (Math::Rand()-0.5f)*0.0f;
+ speed.y = Math::Rand()*15.0f;
+ dim.x = Math::Rand()*2.0f+1.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIRECOVER, 1.0f, 0.0f, 0.0f);
+ }
+ }
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskRecover::Start()
+{
+ CObject* power;
+ Math::Matrix* mat;
+ Math::Vector pos, iPos, oPos;
+ float energy;
+
+ ObjectType type;
+
+ m_bError = true; // operation impossible
+ if ( !m_physics->RetLand() ) return ERR_RECOVER_VEH;
+
+ type = m_object->RetType();
+ if ( type != OBJECT_MOBILErr ) return ERR_RECOVER_VEH;
+
+ power = m_object->RetPower();
+ if ( power == 0 ) return ERR_RECOVER_ENERGY;
+ energy = power->RetEnergy();
+ if ( energy < ENERGY_RECOVER/power->RetCapacity()+0.05f ) return ERR_RECOVER_ENERGY;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(RECOVER_DIST, 3.3f, 0.0f);
+ pos = Transform(*mat, pos); // position in front
+ m_recoverPos = pos;
+
+ m_ruin = SearchRuin();
+ if ( m_ruin == 0 ) return ERR_RECOVER_NULL;
+ m_ruin->SetLock(true); // ruin no longer usable
+
+ iPos = m_object->RetPosition(0);
+ oPos = m_ruin->RetPosition(0);
+ m_angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+
+ m_metal = 0;
+
+ m_phase = TRP_TURN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+
+ m_bError = false; // ok
+
+ m_camera->StartCentering(m_object, Math::PI*0.85f, 99.9f, 10.0f, 3.0f);
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskRecover::IsEnded()
+{
+ Math::Matrix* mat;
+ Math::Vector pos, speed, goal;
+ Math::Point dim;
+ float angle, dist, time;
+ int i;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_phase == TRP_TURN ) // preliminary rotation?
+ {
+ angle = m_object->RetAngleY(0);
+ angle = Math::NormAngle(angle); // 0..2*Math::PI
+
+ if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) )
+ {
+ m_physics->SetMotorSpeedZ(0.0f);
+
+ dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0));
+ if ( dist > RECOVER_DIST )
+ {
+ time = m_physics->RetLinTimeLength(dist-RECOVER_DIST, 1.0f);
+ m_speed = 1.0f/time;
+ }
+ else
+ {
+ time = m_physics->RetLinTimeLength(RECOVER_DIST-dist, -1.0f);
+ m_speed = 1.0f/time;
+ }
+ m_phase = TRP_MOVE;
+ m_progress = 0.0f;
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TRP_MOVE ) // preliminary advance?
+ {
+ dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0));
+
+ if ( dist >= RECOVER_DIST-1.0f &&
+ dist <= RECOVER_DIST+1.0f )
+ {
+ m_physics->SetMotorSpeedX(0.0f);
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(RECOVER_DIST, 3.3f, 0.0f);
+ pos = Transform(*mat, pos); // position in front
+ m_recoverPos = pos;
+
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.9f, true);
+ m_sound->AddEnvelope(i, 1.0f, 1.5f, 0.3f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 1.0f, 1.5f, 1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.0f, 0.9f, 0.3f, SOPER_STOP);
+
+ m_phase = TRP_DOWN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ m_time = 0.0f;
+ }
+ else
+ {
+ if ( m_progress > 1.0f ) // timeout?
+ {
+ m_ruin->SetLock(false); // usable again
+ m_camera->StopCentering(m_object, 2.0f);
+ return ERR_RECOVER_NULL;
+ }
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+ m_progress = 0.0f;
+
+ if ( m_phase == TRP_DOWN )
+ {
+ m_metal = new CObject(m_iMan);
+ if ( !m_metal->CreateResource(m_recoverPos, 0.0f, OBJECT_METAL) )
+ {
+ delete m_metal;
+ m_metal = 0;
+ Abort();
+ m_bError = true;
+ m_displayText->DisplayError(ERR_TOOMANY, m_object);
+ return ERR_STOP;
+ }
+ m_metal->SetLock(true); // metal not yet usable
+ m_metal->SetZoom(0, 0.0f);
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(RECOVER_DIST, 3.1f, 3.9f);
+ pos = Transform(*mat, pos);
+ goal = Math::Vector(RECOVER_DIST, 3.1f, -3.9f);
+ goal = Transform(*mat, goal);
+ m_particule->CreateRay(pos, goal, PARTIRAY2,
+ Math::Point(2.0f, 2.0f), 8.0f);
+
+ m_soundChannel = m_sound->Play(SOUND_RECOVER, m_ruin->RetPosition(0), 0.0f, 1.0f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.6f, 1.0f, 2.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.6f, 1.0f, 4.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.7f, 2.0f, SOPER_STOP);
+
+ m_phase = TRP_OPER;
+ m_speed = 1.0f/8.0f;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TRP_OPER )
+ {
+ m_metal->SetZoom(0, 1.0f);
+
+ m_ruin->DeleteObject(); // destroys the ruin
+ delete m_ruin;
+ m_ruin = 0;
+
+ m_soundChannel = -1;
+
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.9f, true);
+ m_sound->AddEnvelope(i, 1.0f, 1.5f, 0.3f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 1.0f, 1.5f, 1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.0f, 0.9f, 0.3f, SOPER_STOP);
+
+ m_phase = TRP_UP;
+ m_speed = 1.0f/1.5f;
+ return ERR_CONTINUE;
+ }
+
+ m_metal->SetLock(false); // metal usable
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskRecover::Abort()
+{
+ m_object->SetAngleZ(2, 126.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(4, 126.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(3, -144.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(5, -144.0f*Math::PI/180.0f); // rest
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ m_camera->StopCentering(m_object, 2.0f);
+ return true;
+}
+
+
+// Seeks if a ruin is in front of the vehicle.
+
+CObject* CTaskRecover::SearchRuin()
+{
+ CObject *pObj, *pBest;
+ Math::Vector oPos;
+ ObjectType type;
+ float dist, min;
+ int i;
+
+ pBest = 0;
+ min = 100000.0f;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_RUINmobilew1 ||
+ type == OBJECT_RUINmobilew2 ||
+ type == OBJECT_RUINmobilet1 ||
+ type == OBJECT_RUINmobilet2 ||
+ type == OBJECT_RUINmobiler1 ||
+ type == OBJECT_RUINmobiler2 ) // vehicle in ruin?
+ {
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, m_recoverPos);
+ if ( dist > 40.0f ) continue;
+
+ if ( dist < min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+
+ }
+ return pBest;
+}
+
diff --git a/src/object/task/taskrecover.h b/src/object/task/taskrecover.h
index 5ee696a..8af6353 100644
--- a/src/object/task/taskrecover.h
+++ b/src/object/task/taskrecover.h
@@ -1,66 +1,66 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskrecover.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-enum TaskRecoverPhase
-{
- TRP_TURN = 1, // turns
- TRP_MOVE = 2, // advance
- TRP_DOWN = 3, // descends
- TRP_OPER = 4, // operates
- TRP_UP = 5, // back
-};
-
-
-
-class CTaskRecover : public CTask
-{
-public:
- CTaskRecover(CInstanceManager* iMan, CObject* object);
- ~CTaskRecover();
-
- bool EventProcess(const Event &event);
-
- Error Start();
- Error IsEnded();
- bool Abort();
-
-protected:
- CObject* SearchRuin();
-
-protected:
- TaskRecoverPhase m_phase;
- float m_progress;
- float m_speed;
- float m_time;
- float m_angle;
- float m_lastParticule;
- bool m_bError;
- CObject* m_ruin;
- CObject* m_metal;
- Math::Vector m_recoverPos;
- int m_soundChannel;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskrecover.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "math/vector.h"
+
+
+
+enum TaskRecoverPhase
+{
+ TRP_TURN = 1, // turns
+ TRP_MOVE = 2, // advance
+ TRP_DOWN = 3, // descends
+ TRP_OPER = 4, // operates
+ TRP_UP = 5, // back
+};
+
+
+
+class CTaskRecover : public CTask
+{
+public:
+ CTaskRecover(CInstanceManager* iMan, CObject* object);
+ ~CTaskRecover();
+
+ bool EventProcess(const Event &event);
+
+ Error Start();
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ CObject* SearchRuin();
+
+protected:
+ TaskRecoverPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_time;
+ float m_angle;
+ float m_lastParticule;
+ bool m_bError;
+ CObject* m_ruin;
+ CObject* m_metal;
+ Math::Vector m_recoverPos;
+ int m_soundChannel;
+};
+
diff --git a/src/object/task/taskreset.cpp b/src/object/task/taskreset.cpp
index ab41076..2366fea 100644
--- a/src/object/task/taskreset.cpp
+++ b/src/object/task/taskreset.cpp
@@ -1,330 +1,330 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskreset.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskreset.h"
-
-#include "common/iman.h"
-#include "object/brain.h"
-#include "object/robotmain.h"
-
-
-
-const float RESET_DELAY_ZOOM = 0.7f;
-const float RESET_DELAY_MOVE = 0.7f;
-
-
-
-
-// Object's constructor.
-
-CTaskReset::CTaskReset(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskReset::~CTaskReset()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskReset::EventProcess(const Event &event)
-{
- Math::Vector pos, speed;
- Math::Point dim;
- float angle, duration;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_time += event.rTime;
- m_progress += event.rTime*m_speed;
-
- if ( m_phase == TRSP_ZOUT )
- {
- angle = m_iAngle;
- angle += powf(m_progress*5.0f, 2.0f); // accelerates
- m_object->SetAngleY(0, angle);
- m_object->SetZoom(0, 1.0f-m_progress);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_begin;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 5.0f+Math::Rand()*5.0f;
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
-
- pos = m_begin;
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = Math::Rand()*10.0f;
- speed *= 1.0f-m_progress*0.5f;
- pos += speed*1.5f;
- speed = -speed;
- dim.x = 0.6f;
- dim.y = dim.x;
- pos.y += dim.y;
- duration = Math::Rand()*1.5f+1.5f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
- duration, 0.0f,
- duration*0.9f, 0.7f);
- }
- }
-
- if ( m_phase == TRSP_MOVE )
- {
- pos = m_begin+(m_goal-m_begin)*m_progress;
- m_object->SetPosition(0, pos);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 2.0f+Math::Rand()*2.0f;
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
- }
- }
-
- if ( m_phase == TRSP_ZIN )
- {
- angle = m_angle.y;
- angle += -powf((1.0f-m_progress)*5.0f, 2.0f); // slows
- m_object->SetAngleY(0, angle);
- m_object->SetZoom(0, m_progress);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_goal;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 5.0f+Math::Rand()*5.0f;
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
-
- pos = m_goal;
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = Math::Rand()*10.0f;
- speed *= 0.5f+m_progress*0.5f;
- dim.x = 0.6f;
- dim.y = dim.x;
- pos.y += dim.y;
- duration = Math::Rand()*1.5f+1.5f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
- duration, 0.0f,
- duration*0.9f, 0.7f);
- }
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-// A positive angle makes a turn right.
-
-Error CTaskReset::Start(Math::Vector goal, Math::Vector angle)
-{
- CObject* fret;
- int i;
-
- fret = m_object->RetFret();
- if ( fret != 0 && fret->RetResetCap() == RESET_MOVE )
- {
- fret->SetTruck(0);
- m_object->SetFret(0); // does nothing
- }
-
- if ( !m_main->RetNiceReset() ) // quick return?
- {
- m_object->SetPosition(0, goal);
- m_object->SetAngle(0, angle);
- m_brain->RunProgram(m_object->RetResetRun());
-
- m_bError = false;
- return ERR_OK;
- }
-
- m_begin = m_object->RetPosition(0);
- m_goal = goal;
- m_angle = angle;
-
- if ( SearchVehicle() ) // starting location occupied?
- {
- m_bError = true;
- return ERR_RESET_NEAR;
- }
-
- m_iAngle = m_object->RetAngleY(0);
- m_time = 0.0f;
- m_phase = TRSP_ZOUT;
- m_speed = 1.0f/RESET_DELAY_ZOOM;
- m_progress = 0.0f;
- m_lastParticule = 0.0f;
-
- m_object->SetResetBusy(true);
-
- i = m_sound->Play(SOUND_GGG, m_begin, 1.0f, 2.0f, true);
- m_sound->AddEnvelope(i, 0.0f, 0.5f, RESET_DELAY_ZOOM, SOPER_STOP);
-
- m_bError = false;
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskReset::IsEnded()
-{
- CObject* power;
- float dist;
- int i;
-
- if ( !m_main->RetNiceReset() ) // quick return?
- {
- return ERR_STOP;
- }
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- if ( m_phase == TRSP_ZOUT )
- {
- dist = Math::Distance(m_begin, m_goal);
- m_phase = TRSP_MOVE;
- m_speed = 1.0f/(dist*RESET_DELAY_MOVE/100.0f);
- m_progress = 0.0f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TRSP_MOVE )
- {
- m_object->SetPosition(0, m_goal);
- m_object->SetAngle(0, m_angle);
-
- i = m_sound->Play(SOUND_GGG, m_goal, 1.0f, 0.5f, true);
- m_sound->AddEnvelope(i, 0.0f, 2.0f, RESET_DELAY_ZOOM, SOPER_STOP);
-
- m_phase = TRSP_ZIN;
- m_speed = 1.0f/RESET_DELAY_ZOOM;
- m_progress = 0.0f;
- return ERR_CONTINUE;
- }
-
- m_object->SetAngle(0, m_angle);
- m_object->SetZoom(0, 1.0f);
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- power->SetEnergy(power->RetCapacity()); // refueling
- }
-
- m_brain->RunProgram(m_object->RetResetRun());
- m_object->SetResetBusy(false);
- return ERR_STOP;
-}
-
-
-// Seeks if a vehicle is too close.
-
-bool CTaskReset::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- float oRadius, dist;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
-
- type = pObj->RetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_TECH &&
- type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr &&
- type != OBJECT_MOTHER &&
- type != OBJECT_ANT &&
- type != OBJECT_SPIDER &&
- type != OBJECT_BEE &&
- type != OBJECT_WORM ) continue;
-
- if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
- dist = Math::Distance(oPos, m_goal)-oRadius;
-
- if ( dist < 5.0f ) return true;
- }
-
- return false;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskreset.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskreset.h"
+
+#include "common/iman.h"
+#include "object/brain.h"
+#include "object/robotmain.h"
+
+
+
+const float RESET_DELAY_ZOOM = 0.7f;
+const float RESET_DELAY_MOVE = 0.7f;
+
+
+
+
+// Object's constructor.
+
+CTaskReset::CTaskReset(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+}
+
+// Object's destructor.
+
+CTaskReset::~CTaskReset()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskReset::EventProcess(const Event &event)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float angle, duration;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ m_time += event.rTime;
+ m_progress += event.rTime*m_speed;
+
+ if ( m_phase == TRSP_ZOUT )
+ {
+ angle = m_iAngle;
+ angle += powf(m_progress*5.0f, 2.0f); // accelerates
+ m_object->SetAngleY(0, angle);
+ m_object->SetZoom(0, 1.0f-m_progress);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_begin;
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 5.0f+Math::Rand()*5.0f;
+ dim.x = Math::Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
+
+ pos = m_begin;
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ speed.y = Math::Rand()*10.0f;
+ speed *= 1.0f-m_progress*0.5f;
+ pos += speed*1.5f;
+ speed = -speed;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ pos.y += dim.y;
+ duration = Math::Rand()*1.5f+1.5f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
+ duration, 0.0f,
+ duration*0.9f, 0.7f);
+ }
+ }
+
+ if ( m_phase == TRSP_MOVE )
+ {
+ pos = m_begin+(m_goal-m_begin)*m_progress;
+ m_object->SetPosition(0, pos);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 2.0f+Math::Rand()*2.0f;
+ dim.x = Math::Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
+ }
+ }
+
+ if ( m_phase == TRSP_ZIN )
+ {
+ angle = m_angle.y;
+ angle += -powf((1.0f-m_progress)*5.0f, 2.0f); // slows
+ m_object->SetAngleY(0, angle);
+ m_object->SetZoom(0, m_progress);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_goal;
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 5.0f+Math::Rand()*5.0f;
+ dim.x = Math::Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
+
+ pos = m_goal;
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ speed.y = Math::Rand()*10.0f;
+ speed *= 0.5f+m_progress*0.5f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ pos.y += dim.y;
+ duration = Math::Rand()*1.5f+1.5f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
+ duration, 0.0f,
+ duration*0.9f, 0.7f);
+ }
+ }
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+// A positive angle makes a turn right.
+
+Error CTaskReset::Start(Math::Vector goal, Math::Vector angle)
+{
+ CObject* fret;
+ int i;
+
+ fret = m_object->RetFret();
+ if ( fret != 0 && fret->RetResetCap() == RESET_MOVE )
+ {
+ fret->SetTruck(0);
+ m_object->SetFret(0); // does nothing
+ }
+
+ if ( !m_main->RetNiceReset() ) // quick return?
+ {
+ m_object->SetPosition(0, goal);
+ m_object->SetAngle(0, angle);
+ m_brain->RunProgram(m_object->RetResetRun());
+
+ m_bError = false;
+ return ERR_OK;
+ }
+
+ m_begin = m_object->RetPosition(0);
+ m_goal = goal;
+ m_angle = angle;
+
+ if ( SearchVehicle() ) // starting location occupied?
+ {
+ m_bError = true;
+ return ERR_RESET_NEAR;
+ }
+
+ m_iAngle = m_object->RetAngleY(0);
+ m_time = 0.0f;
+ m_phase = TRSP_ZOUT;
+ m_speed = 1.0f/RESET_DELAY_ZOOM;
+ m_progress = 0.0f;
+ m_lastParticule = 0.0f;
+
+ m_object->SetResetBusy(true);
+
+ i = m_sound->Play(SOUND_GGG, m_begin, 1.0f, 2.0f, true);
+ m_sound->AddEnvelope(i, 0.0f, 0.5f, RESET_DELAY_ZOOM, SOPER_STOP);
+
+ m_bError = false;
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskReset::IsEnded()
+{
+ CObject* power;
+ float dist;
+ int i;
+
+ if ( !m_main->RetNiceReset() ) // quick return?
+ {
+ return ERR_STOP;
+ }
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ if ( m_phase == TRSP_ZOUT )
+ {
+ dist = Math::Distance(m_begin, m_goal);
+ m_phase = TRSP_MOVE;
+ m_speed = 1.0f/(dist*RESET_DELAY_MOVE/100.0f);
+ m_progress = 0.0f;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TRSP_MOVE )
+ {
+ m_object->SetPosition(0, m_goal);
+ m_object->SetAngle(0, m_angle);
+
+ i = m_sound->Play(SOUND_GGG, m_goal, 1.0f, 0.5f, true);
+ m_sound->AddEnvelope(i, 0.0f, 2.0f, RESET_DELAY_ZOOM, SOPER_STOP);
+
+ m_phase = TRSP_ZIN;
+ m_speed = 1.0f/RESET_DELAY_ZOOM;
+ m_progress = 0.0f;
+ return ERR_CONTINUE;
+ }
+
+ m_object->SetAngle(0, m_angle);
+ m_object->SetZoom(0, 1.0f);
+
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ power->SetEnergy(power->RetCapacity()); // refueling
+ }
+
+ m_brain->RunProgram(m_object->RetResetRun());
+ m_object->SetResetBusy(false);
+ return ERR_STOP;
+}
+
+
+// Seeks if a vehicle is too close.
+
+bool CTaskReset::SearchVehicle()
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ ObjectType type;
+ float oRadius, dist;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_HUMAN &&
+ type != OBJECT_TECH &&
+ type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis &&
+ type != OBJECT_MOBILErt &&
+ type != OBJECT_MOBILErc &&
+ type != OBJECT_MOBILErr &&
+ type != OBJECT_MOBILErs &&
+ type != OBJECT_MOBILEsa &&
+ type != OBJECT_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_MOBILEdr &&
+ type != OBJECT_MOTHER &&
+ type != OBJECT_ANT &&
+ type != OBJECT_SPIDER &&
+ type != OBJECT_BEE &&
+ type != OBJECT_WORM ) continue;
+
+ if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
+ dist = Math::Distance(oPos, m_goal)-oRadius;
+
+ if ( dist < 5.0f ) return true;
+ }
+
+ return false;
+}
+
diff --git a/src/object/task/taskreset.h b/src/object/task/taskreset.h
index 2c885f9..17a4441 100644
--- a/src/object/task/taskreset.h
+++ b/src/object/task/taskreset.h
@@ -1,63 +1,63 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskreset.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-enum TaskResetPhase
-{
- TRSP_ZOUT = 1, // disappears
- TRSP_MOVE = 2, // moves
- TRSP_ZIN = 3, // reappears
-};
-
-
-
-class CTaskReset : public CTask
-{
-public:
- CTaskReset(CInstanceManager* iMan, CObject* object);
- ~CTaskReset();
-
- bool EventProcess(const Event &event);
-
- Error Start(Math::Vector goal, Math::Vector angle);
- Error IsEnded();
-
-protected:
- bool SearchVehicle();
-
-protected:
- Math::Vector m_begin;
- Math::Vector m_goal;
- Math::Vector m_angle;
-
- TaskResetPhase m_phase;
- bool m_bError;
- float m_time;
- float m_speed;
- float m_progress;
- float m_lastParticule; // time of generation last particle
- float m_iAngle;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskreset.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "math/vector.h"
+
+
+
+enum TaskResetPhase
+{
+ TRSP_ZOUT = 1, // disappears
+ TRSP_MOVE = 2, // moves
+ TRSP_ZIN = 3, // reappears
+};
+
+
+
+class CTaskReset : public CTask
+{
+public:
+ CTaskReset(CInstanceManager* iMan, CObject* object);
+ ~CTaskReset();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(Math::Vector goal, Math::Vector angle);
+ Error IsEnded();
+
+protected:
+ bool SearchVehicle();
+
+protected:
+ Math::Vector m_begin;
+ Math::Vector m_goal;
+ Math::Vector m_angle;
+
+ TaskResetPhase m_phase;
+ bool m_bError;
+ float m_time;
+ float m_speed;
+ float m_progress;
+ float m_lastParticule; // time of generation last particle
+ float m_iAngle;
+};
+
diff --git a/src/object/task/tasksearch.cpp b/src/object/task/tasksearch.cpp
index cf038aa..8c083dd 100644
--- a/src/object/task/tasksearch.cpp
+++ b/src/object/task/tasksearch.cpp
@@ -1,321 +1,321 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// tasksearch.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/tasksearch.h"
-
-#include "math/geometry.h"
-#include "common/iman.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "physics/physics.h"
-#include "ui/displaytext.h"
-
-
-
-
-// Object's constructor.
-
-CTaskSearch::CTaskSearch(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_hand = TSH_UP;
-}
-
-// Object's destructor.
-
-CTaskSearch::~CTaskSearch()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskSearch::EventProcess(const Event &event)
-{
- Math::Matrix* mat;
- Math::Vector pos, speed;
- Math::Point dim;
- float angle;
- int i;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_progress += event.rTime*m_speed; // others advance
- m_time += event.rTime;
-
- if ( m_phase == TSP_DOWN ||
- m_phase == TSP_UP )
- {
- for ( i=0 ; i<3 ; i++ )
- {
- angle = (m_finalAngle[i]-m_initialAngle[i])*m_progress;
- angle += m_initialAngle[i];
- m_object->SetAngleZ(i+1, angle);
- }
- }
-
- if ( m_phase == TSP_SEARCH &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(6.5f, 0.2f, 0.0f);
- pos = Math::Transform(*mat, pos); // sensor position
-
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = 0.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS);
- }
-
- return true;
-}
-
-
-// Initializes the initial and final angles.
-
-void CTaskSearch::InitAngle()
-{
- int i;
-
- if ( m_hand == TSH_UP )
- {
- m_finalAngle[0] = 110.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = -110.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = -65.0f*Math::PI/180.0f; // sensor
- }
- if ( m_hand == TSH_DOWN )
- {
- m_finalAngle[0] = 25.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = -70.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = -45.0f*Math::PI/180.0f; // sensor
- }
-
- for ( i=0 ; i<3 ; i++ )
- {
- m_initialAngle[i] = m_object->RetAngleZ(i+1);
- }
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskSearch::Start()
-{
- ObjectType type;
- Math::Vector speed;
- int i;
-
- m_bError = true;
- if ( !m_physics->RetLand() ) return ERR_SEARCH_FLY;
-
- speed = m_physics->RetMotorSpeed();
- if ( speed.x != 0.0f ||
- speed.z != 0.0f ) return ERR_SEARCH_MOTOR;
-
- type = m_object->RetType();
- if ( type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis ) return ERR_SEARCH_VEH;
-
- m_hand = TSH_DOWN;
- m_phase = TSP_DOWN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
-
- InitAngle();
- m_bError = false; // ok
-
- m_camera->StartCentering(m_object, Math::PI*0.50f, 99.9f, 0.0f, 1.0f);
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, true);
- m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.9f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.3f, 0.1f, SOPER_STOP);
-
- m_physics->SetFreeze(true); // it does not move
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskSearch::IsEnded()
-{
- int i;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( m_phase == TSP_DOWN ||
- m_phase == TSP_UP )
- {
- for ( i=0 ; i<3 ; i++ )
- {
- m_object->SetAngleZ(i+1, m_finalAngle[i]);
- }
- }
-
- if ( m_phase == TSP_DOWN )
- {
- m_sound->Play(SOUND_REPAIR, m_object->RetPosition(0));
-
- m_phase = TSP_SEARCH;
- m_speed = 1.0f/4.0f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TSP_SEARCH )
- {
- CreateMark();
-
- m_hand = TSH_UP;
- InitAngle();
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, true);
- m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.9f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.3f, 0.1f, SOPER_STOP);
-
- m_phase = TSP_UP;
- m_speed = 1.0f/1.0f;
- return ERR_CONTINUE;
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskSearch::Abort()
-{
- m_camera->StopCentering(m_object, 2.0f);
- m_physics->SetFreeze(false); // is moving again
- return true;
-}
-
-
-// Creates a mark if possible.
-
-bool CTaskSearch::CreateMark()
-{
- CObject* fret;
- ObjectType type;
- Math::Matrix* mat;
- Math::Vector pos;
- TerrainRes res;
- Error info;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(7.5f, 0.0f, 0.0f);
- pos = Math::Transform(*mat, pos); // sensor position
-
- res = m_terrain->RetResource(pos);
- if ( res == TR_NULL ) return false;
-
- type = OBJECT_NULL;
- if ( res == TR_STONE )
- {
- type = OBJECT_MARKSTONE;
- info = INFO_MARKSTONE;
- }
- if ( res == TR_URANIUM )
- {
- type = OBJECT_MARKURANIUM;
- info = INFO_MARKURANIUM;
- }
- if ( res == TR_POWER )
- {
- type = OBJECT_MARKPOWER;
- info = INFO_MARKPOWER;
- }
- if ( res == TR_KEYa )
- {
- type = OBJECT_MARKKEYa;
- info = INFO_MARKKEYa;
- }
- if ( res == TR_KEYb )
- {
- type = OBJECT_MARKKEYb;
- info = INFO_MARKKEYb;
- }
- if ( res == TR_KEYc )
- {
- type = OBJECT_MARKKEYc;
- info = INFO_MARKKEYc;
- }
- if ( res == TR_KEYd )
- {
- type = OBJECT_MARKKEYd;
- info = INFO_MARKKEYd;
- }
- if ( type == OBJECT_NULL ) return false;
-
-//? DeleteMark(type);
-
- fret = new CObject(m_iMan);
- if ( !fret->CreateResource(pos, 0.0f, type) )
- {
- delete fret;
- m_displayText->DisplayError(ERR_TOOMANY, m_object);
- return false;
- }
-
- m_displayText->DisplayError(info, pos, 5.0f, 50.0f); // displays the message
-
- return true;
-}
-
-// Destroys the marks of a given type.
-
-void CTaskSearch::DeleteMark(ObjectType type)
-{
- CObject* pObj;
- Math::Vector oPos;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( type == pObj->RetType() )
- {
- pObj->DeleteObject(); // removes the mark
- delete pObj;
- break;
- }
- }
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// tasksearch.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/tasksearch.h"
+
+#include "math/geometry.h"
+#include "common/iman.h"
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "physics/physics.h"
+#include "ui/displaytext.h"
+
+
+
+
+// Object's constructor.
+
+CTaskSearch::CTaskSearch(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_hand = TSH_UP;
+}
+
+// Object's destructor.
+
+CTaskSearch::~CTaskSearch()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskSearch::EventProcess(const Event &event)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float angle;
+ int i;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ m_progress += event.rTime*m_speed; // others advance
+ m_time += event.rTime;
+
+ if ( m_phase == TSP_DOWN ||
+ m_phase == TSP_UP )
+ {
+ for ( i=0 ; i<3 ; i++ )
+ {
+ angle = (m_finalAngle[i]-m_initialAngle[i])*m_progress;
+ angle += m_initialAngle[i];
+ m_object->SetAngleZ(i+1, angle);
+ }
+ }
+
+ if ( m_phase == TSP_SEARCH &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(6.5f, 0.2f, 0.0f);
+ pos = Math::Transform(*mat, pos); // sensor position
+
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ speed.y = 0.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS);
+ }
+
+ return true;
+}
+
+
+// Initializes the initial and final angles.
+
+void CTaskSearch::InitAngle()
+{
+ int i;
+
+ if ( m_hand == TSH_UP )
+ {
+ m_finalAngle[0] = 110.0f*Math::PI/180.0f; // arm
+ m_finalAngle[1] = -110.0f*Math::PI/180.0f; // forearm
+ m_finalAngle[2] = -65.0f*Math::PI/180.0f; // sensor
+ }
+ if ( m_hand == TSH_DOWN )
+ {
+ m_finalAngle[0] = 25.0f*Math::PI/180.0f; // arm
+ m_finalAngle[1] = -70.0f*Math::PI/180.0f; // forearm
+ m_finalAngle[2] = -45.0f*Math::PI/180.0f; // sensor
+ }
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ m_initialAngle[i] = m_object->RetAngleZ(i+1);
+ }
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskSearch::Start()
+{
+ ObjectType type;
+ Math::Vector speed;
+ int i;
+
+ m_bError = true;
+ if ( !m_physics->RetLand() ) return ERR_SEARCH_FLY;
+
+ speed = m_physics->RetMotorSpeed();
+ if ( speed.x != 0.0f ||
+ speed.z != 0.0f ) return ERR_SEARCH_MOTOR;
+
+ type = m_object->RetType();
+ if ( type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis ) return ERR_SEARCH_VEH;
+
+ m_hand = TSH_DOWN;
+ m_phase = TSP_DOWN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+
+ InitAngle();
+ m_bError = false; // ok
+
+ m_camera->StartCentering(m_object, Math::PI*0.50f, 99.9f, 0.0f, 1.0f);
+
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, true);
+ m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.9f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.0f, 0.3f, 0.1f, SOPER_STOP);
+
+ m_physics->SetFreeze(true); // it does not move
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskSearch::IsEnded()
+{
+ int i;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+ m_progress = 0.0f;
+
+ if ( m_phase == TSP_DOWN ||
+ m_phase == TSP_UP )
+ {
+ for ( i=0 ; i<3 ; i++ )
+ {
+ m_object->SetAngleZ(i+1, m_finalAngle[i]);
+ }
+ }
+
+ if ( m_phase == TSP_DOWN )
+ {
+ m_sound->Play(SOUND_REPAIR, m_object->RetPosition(0));
+
+ m_phase = TSP_SEARCH;
+ m_speed = 1.0f/4.0f;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TSP_SEARCH )
+ {
+ CreateMark();
+
+ m_hand = TSH_UP;
+ InitAngle();
+
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, true);
+ m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.9f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.0f, 0.3f, 0.1f, SOPER_STOP);
+
+ m_phase = TSP_UP;
+ m_speed = 1.0f/1.0f;
+ return ERR_CONTINUE;
+ }
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskSearch::Abort()
+{
+ m_camera->StopCentering(m_object, 2.0f);
+ m_physics->SetFreeze(false); // is moving again
+ return true;
+}
+
+
+// Creates a mark if possible.
+
+bool CTaskSearch::CreateMark()
+{
+ CObject* fret;
+ ObjectType type;
+ Math::Matrix* mat;
+ Math::Vector pos;
+ TerrainRes res;
+ Error info;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(7.5f, 0.0f, 0.0f);
+ pos = Math::Transform(*mat, pos); // sensor position
+
+ res = m_terrain->RetResource(pos);
+ if ( res == TR_NULL ) return false;
+
+ type = OBJECT_NULL;
+ if ( res == TR_STONE )
+ {
+ type = OBJECT_MARKSTONE;
+ info = INFO_MARKSTONE;
+ }
+ if ( res == TR_URANIUM )
+ {
+ type = OBJECT_MARKURANIUM;
+ info = INFO_MARKURANIUM;
+ }
+ if ( res == TR_POWER )
+ {
+ type = OBJECT_MARKPOWER;
+ info = INFO_MARKPOWER;
+ }
+ if ( res == TR_KEYa )
+ {
+ type = OBJECT_MARKKEYa;
+ info = INFO_MARKKEYa;
+ }
+ if ( res == TR_KEYb )
+ {
+ type = OBJECT_MARKKEYb;
+ info = INFO_MARKKEYb;
+ }
+ if ( res == TR_KEYc )
+ {
+ type = OBJECT_MARKKEYc;
+ info = INFO_MARKKEYc;
+ }
+ if ( res == TR_KEYd )
+ {
+ type = OBJECT_MARKKEYd;
+ info = INFO_MARKKEYd;
+ }
+ if ( type == OBJECT_NULL ) return false;
+
+//? DeleteMark(type);
+
+ fret = new CObject(m_iMan);
+ if ( !fret->CreateResource(pos, 0.0f, type) )
+ {
+ delete fret;
+ m_displayText->DisplayError(ERR_TOOMANY, m_object);
+ return false;
+ }
+
+ m_displayText->DisplayError(info, pos, 5.0f, 50.0f); // displays the message
+
+ return true;
+}
+
+// Destroys the marks of a given type.
+
+void CTaskSearch::DeleteMark(ObjectType type)
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( type == pObj->RetType() )
+ {
+ pObj->DeleteObject(); // removes the mark
+ delete pObj;
+ break;
+ }
+ }
+}
+
+
diff --git a/src/object/task/tasksearch.h b/src/object/task/tasksearch.h
index 040c606..304473d 100644
--- a/src/object/task/tasksearch.h
+++ b/src/object/task/tasksearch.h
@@ -1,70 +1,70 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// tasksearch.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-
-
-
-enum TaskSearchHand
-{
- TSH_UP = 1, // sensor at the top
- TSH_DOWN = 2, // sensor at the bottom
-};
-
-enum TaskSearchPhase
-{
- TSP_DOWN = 1, // descends
- TSP_SEARCH = 2, // seeks
- TSP_UP = 3, // rises
-};
-
-
-
-class CTaskSearch : public CTask
-{
-public:
- CTaskSearch(CInstanceManager* iMan, CObject* object);
- ~CTaskSearch();
-
- bool EventProcess(const Event &event);
-
- Error Start();
- Error IsEnded();
- bool Abort();
-
-protected:
- void InitAngle();
- bool CreateMark();
- void DeleteMark(ObjectType type);
-
-protected:
- TaskSearchHand m_hand;
- TaskSearchPhase m_phase;
- float m_progress;
- float m_speed;
- float m_time;
- float m_lastParticule;
- float m_initialAngle[3];
- float m_finalAngle[3];
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// tasksearch.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "object/object.h"
+
+
+
+enum TaskSearchHand
+{
+ TSH_UP = 1, // sensor at the top
+ TSH_DOWN = 2, // sensor at the bottom
+};
+
+enum TaskSearchPhase
+{
+ TSP_DOWN = 1, // descends
+ TSP_SEARCH = 2, // seeks
+ TSP_UP = 3, // rises
+};
+
+
+
+class CTaskSearch : public CTask
+{
+public:
+ CTaskSearch(CInstanceManager* iMan, CObject* object);
+ ~CTaskSearch();
+
+ bool EventProcess(const Event &event);
+
+ Error Start();
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ void InitAngle();
+ bool CreateMark();
+ void DeleteMark(ObjectType type);
+
+protected:
+ TaskSearchHand m_hand;
+ TaskSearchPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_time;
+ float m_lastParticule;
+ float m_initialAngle[3];
+ float m_finalAngle[3];
+ bool m_bError;
+};
+
diff --git a/src/object/task/taskshield.cpp b/src/object/task/taskshield.cpp
index 7ceb03b..d5265a2 100644
--- a/src/object/task/taskshield.cpp
+++ b/src/object/task/taskshield.cpp
@@ -1,560 +1,560 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskshield.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskshield.h"
-
-#include "common/iman.h"
-#include "old/light.h"
-#include "old/particule.h"
-#include "math/geometry.h"
-#include "object/brain.h"
-#include "physics/physics.h"
-
-
-const float ENERGY_TIME = 20.0f; // maximum duration if full battery
-
-
-
-// Object's constructor.
-
-CTaskShield::CTaskShield(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_rankSphere = -1;
- m_soundChannel = -1;
- m_effectLight = -1;
-}
-
-// Object's destructor.
-
-CTaskShield::~CTaskShield()
-{
- Abort();
-}
-
-
-// Management of an event.
-
-bool CTaskShield::EventProcess(const Event &event)
-{
- CObject* power;
- Math::Matrix* mat;
- Math::Matrix matrix;
- Math::Vector pos, speed, goal, angle;
- D3DCOLORVALUE color;
- Math::Point dim;
- float energy;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_progress += event.rTime*m_speed; // others advance
- m_time += event.rTime;
- m_delay -= event.rTime;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(7.0f, 15.0f, 0.0f);
- pos = Math::Transform(*mat, pos); // sphere position
- m_shieldPos = pos;
-
- if ( m_rankSphere != -1 )
- {
- m_particule->SetPosition(m_rankSphere, m_shieldPos);
- dim.x = RetRadius();
- dim.y = dim.x;
- m_particule->SetDimension(m_rankSphere, dim);
- }
-
- if ( m_phase == TS_UP1 )
- {
- pos.x = 7.0f;
- pos.y = 4.5f+Math::Bounce(m_progress)*3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
- }
-
- if ( m_phase == TS_UP2 )
- {
- pos.x = 0.0f;
- pos.y = 1.0f+Math::Bounce(m_progress)*3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(3, pos);
- }
-
- if ( m_phase == TS_SHIELD )
- {
- energy = (1.0f/ENERGY_TIME)*event.rTime;
- energy *= RetRadius()/RADIUS_SHIELD_MAX;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- power->SetEnergy(power->RetEnergy()-energy/power->RetCapacity());
- }
- m_energyUsed += energy;
-
- if ( m_soundChannel == -1 )
- {
- m_soundChannel = m_sound->Play(SOUND_SHIELD, m_shieldPos, 0.5f, 0.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_LOOP);
- }
- else
- {
- m_sound->Position(m_soundChannel, m_shieldPos);
- }
-
- pos = m_shieldPos;
- pos.y += RetRadius()*(2.0f+sinf(m_time*9.0f)*0.2f);
- if ( m_effectLight == -1 )
- {
- CreateLight(pos);
- }
- else
- {
- m_light->SetLightPos(m_effectLight, pos);
-
- color.r = 0.0f+sinf(m_time*33.2f)*0.2f;
- color.g = 0.5f+sinf(m_time*20.0f)*0.5f;
- color.b = 0.5f+sinf(m_time*21.3f)*1.0f;
- color.a = 0.0f;
- m_light->SetLightColor(m_effectLight, color);
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_shieldPos;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = (Math::Rand()-0.5f)*0.0f;
- speed.z = (Math::Rand()-0.5f)*0.0f;
- speed.y = Math::Rand()*15.0f;
- dim.x = Math::Rand()*6.0f+4.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
- }
-
- if ( m_lastRay+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastRay = m_time;
-
- pos = m_shieldPos;
- dim.x = RetRadius()/20.0f;
- dim.y = dim.x;
- angle.x = (Math::Rand()-0.5f)*Math::PI*1.2f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*Math::PI*1.2f;
- Math::LoadRotationXZYMatrix(matrix, angle);
- goal = Math::Transform(matrix, Math::Vector(0.0f, RetRadius()-dim.x, 0.0f));
- goal += pos;
- m_particule->CreateRay(pos, goal, PARTIRAY2, dim, 0.3f);
- }
-
- if ( m_lastIncrease+0.2f <= m_time )
- {
- m_lastIncrease = m_time;
- IncreaseShield();
- }
- }
-
- if ( m_phase == TS_SMOKE )
- {
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.5f, 2.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_shieldPos;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = (Math::Rand()-0.5f)*3.0f;
- speed.z = (Math::Rand()-0.5f)*3.0f;
- speed.y = (Math::Rand()-0.5f)*3.0f;
- dim.x = Math::Rand()*1.5f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
- }
- }
-
- if ( m_phase == TS_DOWN1 )
- {
- pos.x = 0.0f;
- pos.y = 1.0f+(1.0f-Math::Bounce(m_progress))*3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(3, pos);
- }
-
- if ( m_phase == TS_DOWN2 )
- {
- pos.x = 7.0f;
- pos.y = 4.5f+(1.0f-Math::Bounce(m_progress))*3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
- }
-
- return true;
-}
-
-
-// Deploys the shield.
-// The period is only useful with TSM_UP!
-
-Error CTaskShield::Start(TaskShieldMode mode, float delay)
-{
- CObject* power;
- Math::Matrix* mat;
- Math::Vector pos, iPos, oPos, speed;
- ObjectType type;
- float energy;
-
- if ( mode == TSM_DOWN )
- {
- return Stop();
- }
-
- if ( mode == TSM_UPDATE )
- {
- if ( m_object->RetSelect() )
- {
- m_brain->UpdateInterface();
- }
- return ERR_OK;
- }
-
- type = m_object->RetType();
- if ( type != OBJECT_MOBILErs ) return ERR_SHIELD_VEH;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() ) return ERR_SHIELD_VEH;
-
- power = m_object->RetPower();
- if ( power == 0 ) return ERR_SHIELD_ENERGY;
- energy = power->RetEnergy();
- if ( energy == 0.0f ) return ERR_SHIELD_ENERGY;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(7.0f, 15.0f, 0.0f);
- pos = Transform(*mat, pos); // sphere position
- m_shieldPos = pos;
-
- m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 0.7f);
-
- m_phase = TS_UP1;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- m_time = 0.0f;
- m_delay = delay;
- m_lastParticule = 0.0f;
- m_lastRay = 0.0f;
- m_lastIncrease = 0.0f;
- m_energyUsed = 0.0f;
-
- m_bError = false; // ok
-
- if ( m_object->RetSelect() )
- {
- m_brain->UpdateInterface();
- }
-//? m_camera->StartCentering(m_object, Math::PI*0.85f, -Math::PI*0.15f, RetRadius()+40.0f, 3.0f);
- return ERR_OK;
-}
-
-// Returns the shield.
-
-Error CTaskShield::Stop()
-{
- float time;
-
- if ( m_phase == TS_SHIELD )
- {
- m_object->SetShieldRadius(0.0f);
-
- if ( m_rankSphere != -1 )
- {
- m_particule->SetPhase(m_rankSphere, PARPHEND, 3.0f);
- m_rankSphere = -1;
- }
-
- if ( m_effectLight != -1 )
- {
- m_light->DeleteLight(m_effectLight);
- m_effectLight = -1;
- }
-
- time = m_energyUsed*4.0f;
- if ( time < 1.0f ) time = 1.0f;
- if ( time > 4.0f ) time = 4.0f;
-
- m_phase = TS_SMOKE;
- m_speed = 1.0f/time;
-
- m_camera->StopCentering(m_object, 4.0f);
-
- if ( m_object->RetSelect() )
- {
- m_brain->UpdateInterface();
- }
- return ERR_CONTINUE;
- }
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskShield::IsEnded()
-{
- CObject* power;
- Math::Vector pos, speed;
- Math::Point dim;
- float energy;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_phase == TS_SHIELD )
- {
- m_object->SetShieldRadius(RetRadius());
-
- power = m_object->RetPower();
- if ( power == 0 )
- {
- energy = 0.0f;
- }
- else
- {
- energy = power->RetEnergy();
- }
-
- if ( energy == 0.0f || m_delay <= 0.0f )
- {
- Stop();
- }
- return ERR_CONTINUE;
- }
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( m_phase == TS_UP1 )
- {
- pos.x = 7.0f;
- pos.y = 4.5f+3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
-
- m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 1.0f);
-
- m_phase = TS_UP2;
- m_speed = 1.0f/0.8f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TS_UP2 )
- {
- pos.x = 0.0f;
- pos.y = 1.0f+3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(3, pos);
-
- m_object->SetShieldRadius(RetRadius());
-
- pos = m_shieldPos;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = RetRadius();
- dim.y = dim.x;
- m_rankSphere = m_particule->CreateParticule(pos, speed, dim, PARTISPHERE3, 2.0f, 0.0f, 0.0f);
-
- m_phase = TS_SHIELD;
- m_speed = 1.0f/999.9f;
-
- if ( m_object->RetSelect() )
- {
- m_brain->UpdateInterface();
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TS_SMOKE )
- {
- m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 1.0f);
-
- m_phase = TS_DOWN1;
- m_speed = 1.0f/0.8f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TS_DOWN1 )
- {
- m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 0.7f);
-
- m_phase = TS_DOWN2;
- m_speed = 1.0f/1.0f;
- return ERR_CONTINUE;
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Indicates whether the action is pending.
-
-bool CTaskShield::IsBusy()
-{
- if ( m_phase == TS_SHIELD )
- {
- return false;
- }
-
- return true;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskShield::Abort()
-{
- Math::Vector pos;
-
- m_object->SetShieldRadius(0.0f);
-
- pos.x = 7.0f;
- pos.y = 4.5f;
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
-
- pos.x = 0.0f;
- pos.y = 1.0f;
- pos.z = 0.0f;
- m_object->SetPosition(3, pos);
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.5f, 2.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- if ( m_rankSphere != -1 )
- {
- m_particule->SetPhase(m_rankSphere, PARPHEND, 3.0f);
- m_rankSphere = -1;
- }
-
- if ( m_effectLight != -1 )
- {
- m_light->DeleteLight(m_effectLight);
- m_effectLight = -1;
- }
-
- m_camera->StopCentering(m_object, 2.0f);
- return true;
-}
-
-
-// Creates the light to accompany a pyrotechnic effect.
-
-bool CTaskShield::CreateLight(Math::Vector pos)
-{
- D3DLIGHT7 light;
-
- if ( !m_engine->RetLightMode() ) return true;
-
- ZeroMemory( &light, sizeof(light) );
- light.dltType = D3DLIGHT_SPOT;
- light.dcvDiffuse.r = 0.0f;
- light.dcvDiffuse.g = 1.0f;
- light.dcvDiffuse.b = 2.0f;
- light.dvPosition.x = pos.x;
- light.dvPosition.y = pos.y;
- light.dvPosition.z = pos.z;
- light.dvDirection.x = 0.0f;
- light.dvDirection.y = -1.0f; // against the bottom
- light.dvDirection.z = 0.0f;
- light.dvRange = D3DLIGHT_RANGE_MAX;
- light.dvFalloff = 1.0f;
- light.dvAttenuation0 = 1.0f;
- light.dvAttenuation1 = 0.0f;
- light.dvAttenuation2 = 0.0f;
- light.dvTheta = 0.0f;
- light.dvPhi = Math::PI/4.0f;
-
- m_effectLight = m_light->CreateLight();
- if ( m_effectLight == -1 ) return false;
-
- m_light->SetLight(m_effectLight, light);
- m_light->SetLightIntensity(m_effectLight, 1.0f);
-
- return true;
-}
-
-
-// Repaired the shielded objects within the sphere of the shield.
-
-void CTaskShield::IncreaseShield()
-{
- ObjectType type;
- CObject* pObj;
- Math::Vector oPos;
- float dist, shield;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, m_shieldPos);
- if ( dist <= RetRadius()+10.0f )
- {
- shield = pObj->RetShield();
- shield += 0.1f;
- if ( shield > 1.0f ) shield = 1.0f;
- pObj->SetShield(shield);
- }
- }
-}
-
-
-// Returns the radius of the shield.
-
-float CTaskShield::RetRadius()
-{
- return RADIUS_SHIELD_MIN + (RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)*m_object->RetParam();
-}
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskshield.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskshield.h"
+
+#include "common/iman.h"
+#include "old/light.h"
+#include "old/particule.h"
+#include "math/geometry.h"
+#include "object/brain.h"
+#include "physics/physics.h"
+
+
+const float ENERGY_TIME = 20.0f; // maximum duration if full battery
+
+
+
+// Object's constructor.
+
+CTaskShield::CTaskShield(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_rankSphere = -1;
+ m_soundChannel = -1;
+ m_effectLight = -1;
+}
+
+// Object's destructor.
+
+CTaskShield::~CTaskShield()
+{
+ Abort();
+}
+
+
+// Management of an event.
+
+bool CTaskShield::EventProcess(const Event &event)
+{
+ CObject* power;
+ Math::Matrix* mat;
+ Math::Matrix matrix;
+ Math::Vector pos, speed, goal, angle;
+ D3DCOLORVALUE color;
+ Math::Point dim;
+ float energy;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ m_progress += event.rTime*m_speed; // others advance
+ m_time += event.rTime;
+ m_delay -= event.rTime;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(7.0f, 15.0f, 0.0f);
+ pos = Math::Transform(*mat, pos); // sphere position
+ m_shieldPos = pos;
+
+ if ( m_rankSphere != -1 )
+ {
+ m_particule->SetPosition(m_rankSphere, m_shieldPos);
+ dim.x = RetRadius();
+ dim.y = dim.x;
+ m_particule->SetDimension(m_rankSphere, dim);
+ }
+
+ if ( m_phase == TS_UP1 )
+ {
+ pos.x = 7.0f;
+ pos.y = 4.5f+Math::Bounce(m_progress)*3.0f;
+ pos.z = 0.0f;
+ m_object->SetPosition(2, pos);
+ }
+
+ if ( m_phase == TS_UP2 )
+ {
+ pos.x = 0.0f;
+ pos.y = 1.0f+Math::Bounce(m_progress)*3.0f;
+ pos.z = 0.0f;
+ m_object->SetPosition(3, pos);
+ }
+
+ if ( m_phase == TS_SHIELD )
+ {
+ energy = (1.0f/ENERGY_TIME)*event.rTime;
+ energy *= RetRadius()/RADIUS_SHIELD_MAX;
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ power->SetEnergy(power->RetEnergy()-energy/power->RetCapacity());
+ }
+ m_energyUsed += energy;
+
+ if ( m_soundChannel == -1 )
+ {
+ m_soundChannel = m_sound->Play(SOUND_SHIELD, m_shieldPos, 0.5f, 0.5f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_LOOP);
+ }
+ else
+ {
+ m_sound->Position(m_soundChannel, m_shieldPos);
+ }
+
+ pos = m_shieldPos;
+ pos.y += RetRadius()*(2.0f+sinf(m_time*9.0f)*0.2f);
+ if ( m_effectLight == -1 )
+ {
+ CreateLight(pos);
+ }
+ else
+ {
+ m_light->SetLightPos(m_effectLight, pos);
+
+ color.r = 0.0f+sinf(m_time*33.2f)*0.2f;
+ color.g = 0.5f+sinf(m_time*20.0f)*0.5f;
+ color.b = 0.5f+sinf(m_time*21.3f)*1.0f;
+ color.a = 0.0f;
+ m_light->SetLightColor(m_effectLight, color);
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_shieldPos;
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ speed.x = (Math::Rand()-0.5f)*0.0f;
+ speed.z = (Math::Rand()-0.5f)*0.0f;
+ speed.y = Math::Rand()*15.0f;
+ dim.x = Math::Rand()*6.0f+4.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
+ }
+
+ if ( m_lastRay+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastRay = m_time;
+
+ pos = m_shieldPos;
+ dim.x = RetRadius()/20.0f;
+ dim.y = dim.x;
+ angle.x = (Math::Rand()-0.5f)*Math::PI*1.2f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*Math::PI*1.2f;
+ Math::LoadRotationXZYMatrix(matrix, angle);
+ goal = Math::Transform(matrix, Math::Vector(0.0f, RetRadius()-dim.x, 0.0f));
+ goal += pos;
+ m_particule->CreateRay(pos, goal, PARTIRAY2, dim, 0.3f);
+ }
+
+ if ( m_lastIncrease+0.2f <= m_time )
+ {
+ m_lastIncrease = m_time;
+ IncreaseShield();
+ }
+ }
+
+ if ( m_phase == TS_SMOKE )
+ {
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.5f, 2.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_shieldPos;
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ speed.x = (Math::Rand()-0.5f)*3.0f;
+ speed.z = (Math::Rand()-0.5f)*3.0f;
+ speed.y = (Math::Rand()-0.5f)*3.0f;
+ dim.x = Math::Rand()*1.5f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
+ }
+ }
+
+ if ( m_phase == TS_DOWN1 )
+ {
+ pos.x = 0.0f;
+ pos.y = 1.0f+(1.0f-Math::Bounce(m_progress))*3.0f;
+ pos.z = 0.0f;
+ m_object->SetPosition(3, pos);
+ }
+
+ if ( m_phase == TS_DOWN2 )
+ {
+ pos.x = 7.0f;
+ pos.y = 4.5f+(1.0f-Math::Bounce(m_progress))*3.0f;
+ pos.z = 0.0f;
+ m_object->SetPosition(2, pos);
+ }
+
+ return true;
+}
+
+
+// Deploys the shield.
+// The period is only useful with TSM_UP!
+
+Error CTaskShield::Start(TaskShieldMode mode, float delay)
+{
+ CObject* power;
+ Math::Matrix* mat;
+ Math::Vector pos, iPos, oPos, speed;
+ ObjectType type;
+ float energy;
+
+ if ( mode == TSM_DOWN )
+ {
+ return Stop();
+ }
+
+ if ( mode == TSM_UPDATE )
+ {
+ if ( m_object->RetSelect() )
+ {
+ m_brain->UpdateInterface();
+ }
+ return ERR_OK;
+ }
+
+ type = m_object->RetType();
+ if ( type != OBJECT_MOBILErs ) return ERR_SHIELD_VEH;
+
+ m_bError = true; // operation impossible
+ if ( !m_physics->RetLand() ) return ERR_SHIELD_VEH;
+
+ power = m_object->RetPower();
+ if ( power == 0 ) return ERR_SHIELD_ENERGY;
+ energy = power->RetEnergy();
+ if ( energy == 0.0f ) return ERR_SHIELD_ENERGY;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(7.0f, 15.0f, 0.0f);
+ pos = Transform(*mat, pos); // sphere position
+ m_shieldPos = pos;
+
+ m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 0.7f);
+
+ m_phase = TS_UP1;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ m_time = 0.0f;
+ m_delay = delay;
+ m_lastParticule = 0.0f;
+ m_lastRay = 0.0f;
+ m_lastIncrease = 0.0f;
+ m_energyUsed = 0.0f;
+
+ m_bError = false; // ok
+
+ if ( m_object->RetSelect() )
+ {
+ m_brain->UpdateInterface();
+ }
+//? m_camera->StartCentering(m_object, Math::PI*0.85f, -Math::PI*0.15f, RetRadius()+40.0f, 3.0f);
+ return ERR_OK;
+}
+
+// Returns the shield.
+
+Error CTaskShield::Stop()
+{
+ float time;
+
+ if ( m_phase == TS_SHIELD )
+ {
+ m_object->SetShieldRadius(0.0f);
+
+ if ( m_rankSphere != -1 )
+ {
+ m_particule->SetPhase(m_rankSphere, PARPHEND, 3.0f);
+ m_rankSphere = -1;
+ }
+
+ if ( m_effectLight != -1 )
+ {
+ m_light->DeleteLight(m_effectLight);
+ m_effectLight = -1;
+ }
+
+ time = m_energyUsed*4.0f;
+ if ( time < 1.0f ) time = 1.0f;
+ if ( time > 4.0f ) time = 4.0f;
+
+ m_phase = TS_SMOKE;
+ m_speed = 1.0f/time;
+
+ m_camera->StopCentering(m_object, 4.0f);
+
+ if ( m_object->RetSelect() )
+ {
+ m_brain->UpdateInterface();
+ }
+ return ERR_CONTINUE;
+ }
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskShield::IsEnded()
+{
+ CObject* power;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float energy;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_phase == TS_SHIELD )
+ {
+ m_object->SetShieldRadius(RetRadius());
+
+ power = m_object->RetPower();
+ if ( power == 0 )
+ {
+ energy = 0.0f;
+ }
+ else
+ {
+ energy = power->RetEnergy();
+ }
+
+ if ( energy == 0.0f || m_delay <= 0.0f )
+ {
+ Stop();
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+ m_progress = 0.0f;
+
+ if ( m_phase == TS_UP1 )
+ {
+ pos.x = 7.0f;
+ pos.y = 4.5f+3.0f;
+ pos.z = 0.0f;
+ m_object->SetPosition(2, pos);
+
+ m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 1.0f);
+
+ m_phase = TS_UP2;
+ m_speed = 1.0f/0.8f;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TS_UP2 )
+ {
+ pos.x = 0.0f;
+ pos.y = 1.0f+3.0f;
+ pos.z = 0.0f;
+ m_object->SetPosition(3, pos);
+
+ m_object->SetShieldRadius(RetRadius());
+
+ pos = m_shieldPos;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = RetRadius();
+ dim.y = dim.x;
+ m_rankSphere = m_particule->CreateParticule(pos, speed, dim, PARTISPHERE3, 2.0f, 0.0f, 0.0f);
+
+ m_phase = TS_SHIELD;
+ m_speed = 1.0f/999.9f;
+
+ if ( m_object->RetSelect() )
+ {
+ m_brain->UpdateInterface();
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TS_SMOKE )
+ {
+ m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 1.0f);
+
+ m_phase = TS_DOWN1;
+ m_speed = 1.0f/0.8f;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TS_DOWN1 )
+ {
+ m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 0.7f);
+
+ m_phase = TS_DOWN2;
+ m_speed = 1.0f/1.0f;
+ return ERR_CONTINUE;
+ }
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Indicates whether the action is pending.
+
+bool CTaskShield::IsBusy()
+{
+ if ( m_phase == TS_SHIELD )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskShield::Abort()
+{
+ Math::Vector pos;
+
+ m_object->SetShieldRadius(0.0f);
+
+ pos.x = 7.0f;
+ pos.y = 4.5f;
+ pos.z = 0.0f;
+ m_object->SetPosition(2, pos);
+
+ pos.x = 0.0f;
+ pos.y = 1.0f;
+ pos.z = 0.0f;
+ m_object->SetPosition(3, pos);
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.5f, 2.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ if ( m_rankSphere != -1 )
+ {
+ m_particule->SetPhase(m_rankSphere, PARPHEND, 3.0f);
+ m_rankSphere = -1;
+ }
+
+ if ( m_effectLight != -1 )
+ {
+ m_light->DeleteLight(m_effectLight);
+ m_effectLight = -1;
+ }
+
+ m_camera->StopCentering(m_object, 2.0f);
+ return true;
+}
+
+
+// Creates the light to accompany a pyrotechnic effect.
+
+bool CTaskShield::CreateLight(Math::Vector pos)
+{
+ D3DLIGHT7 light;
+
+ if ( !m_engine->RetLightMode() ) return true;
+
+ ZeroMemory( &light, sizeof(light) );
+ light.dltType = D3DLIGHT_SPOT;
+ light.dcvDiffuse.r = 0.0f;
+ light.dcvDiffuse.g = 1.0f;
+ light.dcvDiffuse.b = 2.0f;
+ light.dvPosition.x = pos.x;
+ light.dvPosition.y = pos.y;
+ light.dvPosition.z = pos.z;
+ light.dvDirection.x = 0.0f;
+ light.dvDirection.y = -1.0f; // against the bottom
+ light.dvDirection.z = 0.0f;
+ light.dvRange = D3DLIGHT_RANGE_MAX;
+ light.dvFalloff = 1.0f;
+ light.dvAttenuation0 = 1.0f;
+ light.dvAttenuation1 = 0.0f;
+ light.dvAttenuation2 = 0.0f;
+ light.dvTheta = 0.0f;
+ light.dvPhi = Math::PI/4.0f;
+
+ m_effectLight = m_light->CreateLight();
+ if ( m_effectLight == -1 ) return false;
+
+ m_light->SetLight(m_effectLight, light);
+ m_light->SetLightIntensity(m_effectLight, 1.0f);
+
+ return true;
+}
+
+
+// Repaired the shielded objects within the sphere of the shield.
+
+void CTaskShield::IncreaseShield()
+{
+ ObjectType type;
+ CObject* pObj;
+ Math::Vector oPos;
+ float dist, shield;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, m_shieldPos);
+ if ( dist <= RetRadius()+10.0f )
+ {
+ shield = pObj->RetShield();
+ shield += 0.1f;
+ if ( shield > 1.0f ) shield = 1.0f;
+ pObj->SetShield(shield);
+ }
+ }
+}
+
+
+// Returns the radius of the shield.
+
+float CTaskShield::RetRadius()
+{
+ return RADIUS_SHIELD_MIN + (RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)*m_object->RetParam();
+}
+
+
+
diff --git a/src/object/task/taskshield.h b/src/object/task/taskshield.h
index 7749f52..5842ae0 100644
--- a/src/object/task/taskshield.h
+++ b/src/object/task/taskshield.h
@@ -1,84 +1,84 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskshield.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-const float RADIUS_SHIELD_MIN = 40.0f; // minimum radius of the protected zone
-const float RADIUS_SHIELD_MAX = 100.0f; // maximum radius of the protected zone
-
-
-enum TaskShieldPhase
-{
- TS_UP1 = 1, // up
- TS_UP2 = 2, // up
- TS_SHIELD = 3, // shield deployed
- TS_SMOKE = 4, // smoke
- TS_DOWN1 = 5, // down
- TS_DOWN2 = 6, // down
-};
-
-enum TaskShieldMode
-{
- TSM_UP = 1, // deploys shield
- TSM_DOWN = 2, // returns the shield
- TSM_UPDATE = 3, // radius change
-};
-
-
-
-class CTaskShield : public CTask
-{
-public:
- CTaskShield(CInstanceManager* iMan, CObject* object);
- ~CTaskShield();
-
- bool EventProcess(const Event &event);
-
- Error Start(TaskShieldMode mode, float delay);
- Error IsEnded();
- bool IsBusy();
- bool Abort();
-
-protected:
- Error Stop();
- bool CreateLight(Math::Vector pos);
- void IncreaseShield();
- float RetRadius();
-
-protected:
- TaskShieldPhase m_phase;
- float m_progress;
- float m_speed;
- float m_time;
- float m_delay;
- float m_lastParticule;
- float m_lastRay;
- float m_lastIncrease;
- float m_energyUsed;
- bool m_bError;
- Math::Vector m_shieldPos;
- int m_rankSphere;
- int m_soundChannel;
- int m_effectLight;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskshield.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "math/vector.h"
+
+
+const float RADIUS_SHIELD_MIN = 40.0f; // minimum radius of the protected zone
+const float RADIUS_SHIELD_MAX = 100.0f; // maximum radius of the protected zone
+
+
+enum TaskShieldPhase
+{
+ TS_UP1 = 1, // up
+ TS_UP2 = 2, // up
+ TS_SHIELD = 3, // shield deployed
+ TS_SMOKE = 4, // smoke
+ TS_DOWN1 = 5, // down
+ TS_DOWN2 = 6, // down
+};
+
+enum TaskShieldMode
+{
+ TSM_UP = 1, // deploys shield
+ TSM_DOWN = 2, // returns the shield
+ TSM_UPDATE = 3, // radius change
+};
+
+
+
+class CTaskShield : public CTask
+{
+public:
+ CTaskShield(CInstanceManager* iMan, CObject* object);
+ ~CTaskShield();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(TaskShieldMode mode, float delay);
+ Error IsEnded();
+ bool IsBusy();
+ bool Abort();
+
+protected:
+ Error Stop();
+ bool CreateLight(Math::Vector pos);
+ void IncreaseShield();
+ float RetRadius();
+
+protected:
+ TaskShieldPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_time;
+ float m_delay;
+ float m_lastParticule;
+ float m_lastRay;
+ float m_lastIncrease;
+ float m_energyUsed;
+ bool m_bError;
+ Math::Vector m_shieldPos;
+ int m_rankSphere;
+ int m_soundChannel;
+ int m_effectLight;
+};
+
diff --git a/src/object/task/taskspiderexplo.cpp b/src/object/task/taskspiderexplo.cpp
index 2d6c846..fa505b1 100644
--- a/src/object/task/taskspiderexplo.cpp
+++ b/src/object/task/taskspiderexplo.cpp
@@ -1,110 +1,110 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskspiderexplo.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskspiderexplo.h"
-
-#include "old/pyro.h"
-#include "object/motion/motionspider.h"
-#include "physics/physics.h"
-
-
-
-
-// Object's constructor.
-
-CTaskSpiderExplo::CTaskSpiderExplo(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_time = 0.0f;
- m_bError = false;
-}
-
-// Object's destructor.
-
-CTaskSpiderExplo::~CTaskSpiderExplo()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskSpiderExplo::EventProcess(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- // Momentarily stationary object (ant on the back)?
- if ( m_object->RetFixed() )
- {
- m_bError = true;
- return true;
- }
-
- m_time += event.rTime;
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskSpiderExplo::Start()
-{
- m_motion->SetAction(MSS_EXPLO, 1.0f); // swells abdominal
- m_time = 0.0f;
-
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
-
- m_bError = false;
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskSpiderExplo::IsEnded()
-{
- CPyro* pyro;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
-
- if ( m_bError )
- {
- Abort();
- return ERR_STOP;
- }
-
- if ( m_time < 1.0f ) return ERR_CONTINUE;
-
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_SPIDER, m_object); // the spider explodes (suicide)
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskSpiderExplo::Abort()
-{
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskspiderexplo.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskspiderexplo.h"
+
+#include "old/pyro.h"
+#include "object/motion/motionspider.h"
+#include "physics/physics.h"
+
+
+
+
+// Object's constructor.
+
+CTaskSpiderExplo::CTaskSpiderExplo(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_time = 0.0f;
+ m_bError = false;
+}
+
+// Object's destructor.
+
+CTaskSpiderExplo::~CTaskSpiderExplo()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskSpiderExplo::EventProcess(const Event &event)
+{
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ // Momentarily stationary object (ant on the back)?
+ if ( m_object->RetFixed() )
+ {
+ m_bError = true;
+ return true;
+ }
+
+ m_time += event.rTime;
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskSpiderExplo::Start()
+{
+ m_motion->SetAction(MSS_EXPLO, 1.0f); // swells abdominal
+ m_time = 0.0f;
+
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+
+ m_bError = false;
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskSpiderExplo::IsEnded()
+{
+ CPyro* pyro;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+
+ if ( m_bError )
+ {
+ Abort();
+ return ERR_STOP;
+ }
+
+ if ( m_time < 1.0f ) return ERR_CONTINUE;
+
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_SPIDER, m_object); // the spider explodes (suicide)
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskSpiderExplo::Abort()
+{
+ return true;
+}
+
diff --git a/src/object/task/taskspiderexplo.h b/src/object/task/taskspiderexplo.h
index df77b62..50f3ad2 100644
--- a/src/object/task/taskspiderexplo.h
+++ b/src/object/task/taskspiderexplo.h
@@ -1,44 +1,44 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskspiderexplo.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskSpiderExplo : public CTask
-{
-public:
- CTaskSpiderExplo(CInstanceManager* iMan, CObject* object);
- ~CTaskSpiderExplo();
-
- bool EventProcess(const Event &event);
-
- Error Start();
- Error IsEnded();
- bool Abort();
-
-protected:
-
-protected:
- float m_time;
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskspiderexplo.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+
+
+
+class CTaskSpiderExplo : public CTask
+{
+public:
+ CTaskSpiderExplo(CInstanceManager* iMan, CObject* object);
+ ~CTaskSpiderExplo();
+
+ bool EventProcess(const Event &event);
+
+ Error Start();
+ Error IsEnded();
+ bool Abort();
+
+protected:
+
+protected:
+ float m_time;
+ bool m_bError;
+};
+
diff --git a/src/object/task/tasktake.cpp b/src/object/task/tasktake.cpp
index b6d9e0e..1a50f06 100644
--- a/src/object/task/tasktake.cpp
+++ b/src/object/task/tasktake.cpp
@@ -1,596 +1,596 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// tasktake.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/tasktake.h"
-
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "math/geometry.h"
-#include "object/motion/motionhuman.h"
-#include "object/robotmain.h"
-#include "physics/physics.h"
-
-
-
-
-// Object's constructor.
-
-CTaskTake::CTaskTake(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
-
- m_arm = TTA_NEUTRAL;
-}
-
-// Object's destructor.
-
-CTaskTake::~CTaskTake()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskTake::EventProcess(const Event &event)
-{
- float a, g, cirSpeed;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- if ( m_bTurn ) // preliminary rotation?
- {
- a = m_object->RetAngleY(0);
- g = m_angle;
- cirSpeed = Math::Direction(a, g)*2.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- return true;
- }
-
- m_progress += event.rTime*m_speed; // others advance
-
- m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f)); // immobile!
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskTake::Start()
-{
- ObjectType type;
- CObject* other;
- float iAngle, oAngle, h;
- Math::Vector pos;
-
- m_height = 0.0f;
- m_step = 0;
- m_progress = 0.0f;
-
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
- oAngle = iAngle;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() )
- {
- pos = m_object->RetPosition(0);
- h = m_water->RetLevel(m_object);
- if ( pos.y < h ) return ERR_MANIP_WATER; // impossible under water
- return ERR_MANIP_FLY;
- }
-
- type = m_object->RetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_TECH ) return ERR_MANIP_VEH;
-
- m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));
-
- if ( m_object->RetFret() == 0 )
- {
- m_order = TTO_TAKE;
- }
- else
- {
- m_order = TTO_DEPOSE;
- }
-
- if ( m_order == TTO_TAKE )
- {
- pos = m_object->RetPosition(0);
- h = m_water->RetLevel(m_object);
- if ( pos.y < h ) return ERR_MANIP_WATER; // impossible under water
-
- other = SearchFriendObject(oAngle, 1.5f, Math::PI*0.50f);
- if ( other != 0 && other->RetPower() != 0 )
- {
- type = other->RetPower()->RetType();
- if ( type == OBJECT_URANIUM ) return ERR_MANIP_RADIO;
- if ( type != OBJECT_FRET &&
- type != OBJECT_STONE &&
- type != OBJECT_BULLET &&
- type != OBJECT_METAL &&
- type != OBJECT_POWER &&
- type != OBJECT_ATOMIC &&
- type != OBJECT_BBOX &&
- type != OBJECT_KEYa &&
- type != OBJECT_KEYb &&
- type != OBJECT_KEYc &&
- type != OBJECT_KEYd &&
- type != OBJECT_TNT ) return ERR_MANIP_FRIEND;
-//? m_camera->StartCentering(m_object, Math::PI*0.3f, -Math::PI*0.1f, 0.0f, 0.8f);
- m_arm = TTA_FRIEND;
- }
- else
- {
- other = SearchTakeObject(oAngle, 1.5f, Math::PI*0.45f);
- if ( other == 0 ) return ERR_MANIP_NIL;
- type = other->RetType();
- if ( type == OBJECT_URANIUM ) return ERR_MANIP_RADIO;
-//? m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.8f);
- m_arm = TTA_FFRONT;
- m_main->HideDropZone(other); // hides buildable area
- }
- }
-
- if ( m_order == TTO_DEPOSE )
- {
-//? speed = m_physics->RetMotorSpeed();
-//? if ( speed.x != 0.0f ||
-//? speed.z != 0.0f ) return ERR_MANIP_MOTOR;
-
- other = SearchFriendObject(oAngle, 1.5f, Math::PI*0.50f);
- if ( other != 0 && other->RetPower() == 0 )
- {
-//? m_camera->StartCentering(m_object, Math::PI*0.3f, -Math::PI*0.1f, 0.0f, 0.8f);
- m_arm = TTA_FRIEND;
- }
- else
- {
- if ( !IsFreeDeposeObject(Math::Vector(2.5f, 0.0f, 0.0f)) ) return ERR_MANIP_OCC;
-//? m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.8f);
- m_arm = TTA_FFRONT;
- }
- }
-
- m_bTurn = true; // preliminary rotation necessary
- m_angle = oAngle; // angle was reached
-
- m_physics->SetFreeze(true); // it does not move
-
- m_bError = false; // ok
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskTake::IsEnded()
-{
- CObject* fret;
- float angle;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_bTurn ) // preliminary rotation?
- {
- angle = m_object->RetAngleY(0);
- angle = Math::NormAngle(angle); // 0..2*Math::PI
-
- if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) )
- {
- m_bTurn = false; // rotation ended
- m_physics->SetMotorSpeedZ(0.0f);
-
- if ( m_arm == TTA_FFRONT )
- {
- m_motion->SetAction(MHS_TAKE, 0.2f); // will decrease
- }
- if ( m_arm == TTA_FRIEND )
- {
- if ( m_height <= 3.0f )
- {
- m_motion->SetAction(MHS_TAKEOTHER, 0.2f); // will decrease
- }
- else
- {
- m_motion->SetAction(MHS_TAKEHIGH, 0.2f); // will decrease
- }
- }
- m_progress = 0.0f;
- m_speed = 1.0f/0.6f;
- }
- return ERR_CONTINUE;
- }
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- m_step ++;
-
- if ( m_order == TTO_TAKE )
- {
- if ( m_step == 1 )
- {
- if ( TruckTakeObject() )
- {
- if ( m_arm == TTA_FRIEND &&
- (m_fretType == OBJECT_POWER ||
- m_fretType == OBJECT_ATOMIC ) )
- {
- m_sound->Play(SOUND_POWEROFF, m_object->RetPosition(0));
- }
- }
- m_motion->SetAction(MHS_UPRIGHT, 0.4f); // gets up
- m_progress = 0.0f;
- m_speed = 1.0f/0.8f;
- m_camera->StopCentering(m_object, 0.8f);
- return ERR_CONTINUE;
- }
- }
-
- if ( m_order == TTO_DEPOSE )
- {
- if ( m_step == 1 )
- {
- fret = m_object->RetFret();
- TruckDeposeObject();
- if ( m_arm == TTA_FRIEND &&
- (m_fretType == OBJECT_POWER ||
- m_fretType == OBJECT_ATOMIC ) )
- {
- m_sound->Play(SOUND_POWERON, m_object->RetPosition(0));
- }
- if ( fret != 0 && m_fretType == OBJECT_METAL && m_arm == TTA_FFRONT )
- {
- m_main->ShowDropZone(fret, m_object); // shows buildable area
- }
- m_motion->SetAction(-1); // gets up
- m_progress = 0.0f;
- m_speed = 1.0f/0.4f;
- m_camera->StopCentering(m_object, 0.8f);
- return ERR_CONTINUE;
- }
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskTake::Abort()
-{
- m_motion->SetAction(-1);
- m_camera->StopCentering(m_object, 0.8f);
- m_physics->SetFreeze(false); // is moving again
- return true;
-}
-
-
-// Seeks the object to take in front.
-
-CObject* CTaskTake::SearchTakeObject(float &angle,
- float dLimit, float aLimit)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float min, iAngle, bAngle, a, distance;
- int i;
-
- iPos = m_object->RetPosition(0);
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- min = 1000000.0f;
- pBest = 0;
- bAngle = 0.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
-
- if ( type != OBJECT_FRET &&
- type != OBJECT_STONE &&
- type != OBJECT_URANIUM &&
- type != OBJECT_BULLET &&
- type != OBJECT_METAL &&
- type != OBJECT_POWER &&
- type != OBJECT_ATOMIC &&
- type != OBJECT_BBOX &&
- type != OBJECT_KEYa &&
- type != OBJECT_KEYb &&
- type != OBJECT_KEYc &&
- type != OBJECT_KEYd &&
- type != OBJECT_TNT ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj->RetLock() ) continue;
- if ( pObj->RetZoomY(0) != 1.0f ) continue;
-
- oPos = pObj->RetPosition(0);
- distance = Math::Distance(oPos, iPos);
- if ( distance >= 4.0f-dLimit &&
- distance <= 4.0f+dLimit )
- {
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
- {
- a = fabs(angle-iAngle);
- if ( a > Math::PI ) a = Math::PI*2.0f-a;
- if ( a < min )
- {
- min = a;
- pBest = pObj;
- bAngle = angle;
- }
- }
- }
- }
- angle = bAngle;
- return pBest;
-}
-
-// Seeks the robot on which you want take or put a battery.
-
-CObject* CTaskTake::SearchFriendObject(float &angle,
- float dLimit, float aLimit)
-{
- Character* character;
- CObject* pObj;
- CObject* pPower;
- Math::Matrix* mat;
- Math::Vector iPos, oPos;
- ObjectType type, powerType;
- float iAngle, iRad, distance;
- int i;
-
- if ( !m_object->GetCrashSphere(0, iPos, iRad) ) return 0;
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue; // yourself?
-
- type = pObj->RetType();
- if ( type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_TOWER &&
- type != OBJECT_RESEARCH &&
- type != OBJECT_ENERGY &&
- type != OBJECT_LABO &&
- type != OBJECT_NUCLEAR ) continue;
-
- pPower = pObj->RetPower();
- if ( pPower != 0 )
- {
- if ( pPower->RetLock() ) continue;
- if ( pPower->RetZoomY(0) != 1.0f ) continue;
-
- powerType = pPower->RetType();
- if ( powerType == OBJECT_NULL ||
- powerType == OBJECT_FIX ) continue;
- }
-
- mat = pObj->RetWorldMatrix(0);
- character = pObj->RetCharacter();
- oPos = Transform(*mat, character->posPower);
-
- distance = fabs(Math::Distance(oPos, iPos) - (iRad+1.0f));
- if ( distance <= dLimit )
- {
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
- {
- character = pObj->RetCharacter();
- m_height = character->posPower.y;
- return pObj;
- }
- }
- }
-
- return 0;
-}
-
-// Takes the object in front.
-
-bool CTaskTake::TruckTakeObject()
-{
- CObject* fret;
- CObject* other;
- Math::Matrix matRotate;
- float angle;
-
- if ( m_arm == TTA_FFRONT ) // takes on the ground in front?
- {
-//? fret = SearchTakeObject(angle, 1.5f, Math::PI*0.04f);
- fret = SearchTakeObject(angle, 1.5f, Math::PI*0.15f); //OK 1.9
- if ( fret == 0 ) return false; // rien � prendre ?
- m_fretType = fret->RetType();
-
- fret->SetTruck(m_object);
- fret->SetTruckPart(4); // takes with the hand
-
-//? fret->SetPosition(0, Math::Vector(2.2f, -1.0f, 1.1f));
- fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f));
- fret->SetAngleY(0, 0.1f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.8f);
-
- m_object->SetFret(fret); // takes
- }
-
- if ( m_arm == TTA_FRIEND ) // takes friend's battery?
- {
- other = SearchFriendObject(angle, 1.5f, Math::PI*0.04f);
- if ( other == 0 ) return false;
-
- fret = other->RetPower();
- if ( fret == 0 ) return false; // the other does not have a battery?
- m_fretType = fret->RetType();
-
- other->SetPower(0);
- fret->SetTruck(m_object);
- fret->SetTruckPart(4); // takes with the hand
-
-//? fret->SetPosition(0, Math::Vector(2.2f, -1.0f, 1.1f));
- fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f));
- fret->SetAngleY(0, 0.1f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.8f);
-
- m_object->SetFret(fret); // takes
- }
-
- return true;
-}
-
-// Deposes the object taken.
-
-bool CTaskTake::TruckDeposeObject()
-{
- Character* character;
- CObject* fret;
- CObject* other;
- Math::Matrix* mat;
- Math::Vector pos;
- float angle;
-
- if ( m_arm == TTA_FFRONT ) // deposes on the ground in front?
- {
- fret = m_object->RetFret();
- if ( fret == 0 ) return false; // does nothing?
- m_fretType = fret->RetType();
-
- mat = fret->RetWorldMatrix(0);
- pos = Transform(*mat, Math::Vector(-0.5f, 1.0f, 0.0f));
- m_terrain->MoveOnFloor(pos);
- fret->SetPosition(0, pos);
- fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- fret->FloorAdjust(); // plate well on the ground
-
- fret->SetTruck(0);
- m_object->SetFret(0); // deposit
- }
-
- if ( m_arm == TTA_FRIEND ) // deposes battery on friends?
- {
- other = SearchFriendObject(angle, 1.5f, Math::PI*0.04f);
- if ( other == 0 ) return false;
-
- fret = other->RetPower();
- if ( fret != 0 ) return false; // the other already has a battery?
-
- fret = m_object->RetFret();
- if ( fret == 0 ) return false;
- m_fretType = fret->RetType();
-
- other->SetPower(fret);
- fret->SetTruck(other);
-
- character = other->RetCharacter();
- fret->SetPosition(0, character->posPower);
- fret->SetAngleY(0, 0.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- fret->SetTruckPart(0); // carried by the base
-
- m_object->SetFret(0); // deposit
- }
-
- return true;
-}
-
-// Seeks if a location allows to deposit an object.
-
-bool CTaskTake::IsFreeDeposeObject(Math::Vector pos)
-{
- CObject* pObj;
- Math::Matrix* mat;
- Math::Vector iPos, oPos;
- float oRadius;
- int i, j;
-
- mat = m_object->RetWorldMatrix(0);
- iPos = Transform(*mat, pos);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- if ( Math::Distance(iPos, oPos)-(oRadius+1.0f) < 1.0f )
- {
- return false; // location occupied
- }
- }
- }
- return true; // location free
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// tasktake.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/tasktake.h"
+
+#include "common/iman.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "math/geometry.h"
+#include "object/motion/motionhuman.h"
+#include "object/robotmain.h"
+#include "physics/physics.h"
+
+
+
+
+// Object's constructor.
+
+CTaskTake::CTaskTake(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+
+ m_arm = TTA_NEUTRAL;
+}
+
+// Object's destructor.
+
+CTaskTake::~CTaskTake()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskTake::EventProcess(const Event &event)
+{
+ float a, g, cirSpeed;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ if ( m_bTurn ) // preliminary rotation?
+ {
+ a = m_object->RetAngleY(0);
+ g = m_angle;
+ cirSpeed = Math::Direction(a, g)*2.0f;
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
+ return true;
+ }
+
+ m_progress += event.rTime*m_speed; // others advance
+
+ m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f)); // immobile!
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskTake::Start()
+{
+ ObjectType type;
+ CObject* other;
+ float iAngle, oAngle, h;
+ Math::Vector pos;
+
+ m_height = 0.0f;
+ m_step = 0;
+ m_progress = 0.0f;
+
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+ oAngle = iAngle;
+
+ m_bError = true; // operation impossible
+ if ( !m_physics->RetLand() )
+ {
+ pos = m_object->RetPosition(0);
+ h = m_water->RetLevel(m_object);
+ if ( pos.y < h ) return ERR_MANIP_WATER; // impossible under water
+ return ERR_MANIP_FLY;
+ }
+
+ type = m_object->RetType();
+ if ( type != OBJECT_HUMAN &&
+ type != OBJECT_TECH ) return ERR_MANIP_VEH;
+
+ m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));
+
+ if ( m_object->RetFret() == 0 )
+ {
+ m_order = TTO_TAKE;
+ }
+ else
+ {
+ m_order = TTO_DEPOSE;
+ }
+
+ if ( m_order == TTO_TAKE )
+ {
+ pos = m_object->RetPosition(0);
+ h = m_water->RetLevel(m_object);
+ if ( pos.y < h ) return ERR_MANIP_WATER; // impossible under water
+
+ other = SearchFriendObject(oAngle, 1.5f, Math::PI*0.50f);
+ if ( other != 0 && other->RetPower() != 0 )
+ {
+ type = other->RetPower()->RetType();
+ if ( type == OBJECT_URANIUM ) return ERR_MANIP_RADIO;
+ if ( type != OBJECT_FRET &&
+ type != OBJECT_STONE &&
+ type != OBJECT_BULLET &&
+ type != OBJECT_METAL &&
+ type != OBJECT_POWER &&
+ type != OBJECT_ATOMIC &&
+ type != OBJECT_BBOX &&
+ type != OBJECT_KEYa &&
+ type != OBJECT_KEYb &&
+ type != OBJECT_KEYc &&
+ type != OBJECT_KEYd &&
+ type != OBJECT_TNT ) return ERR_MANIP_FRIEND;
+//? m_camera->StartCentering(m_object, Math::PI*0.3f, -Math::PI*0.1f, 0.0f, 0.8f);
+ m_arm = TTA_FRIEND;
+ }
+ else
+ {
+ other = SearchTakeObject(oAngle, 1.5f, Math::PI*0.45f);
+ if ( other == 0 ) return ERR_MANIP_NIL;
+ type = other->RetType();
+ if ( type == OBJECT_URANIUM ) return ERR_MANIP_RADIO;
+//? m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.8f);
+ m_arm = TTA_FFRONT;
+ m_main->HideDropZone(other); // hides buildable area
+ }
+ }
+
+ if ( m_order == TTO_DEPOSE )
+ {
+//? speed = m_physics->RetMotorSpeed();
+//? if ( speed.x != 0.0f ||
+//? speed.z != 0.0f ) return ERR_MANIP_MOTOR;
+
+ other = SearchFriendObject(oAngle, 1.5f, Math::PI*0.50f);
+ if ( other != 0 && other->RetPower() == 0 )
+ {
+//? m_camera->StartCentering(m_object, Math::PI*0.3f, -Math::PI*0.1f, 0.0f, 0.8f);
+ m_arm = TTA_FRIEND;
+ }
+ else
+ {
+ if ( !IsFreeDeposeObject(Math::Vector(2.5f, 0.0f, 0.0f)) ) return ERR_MANIP_OCC;
+//? m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.8f);
+ m_arm = TTA_FFRONT;
+ }
+ }
+
+ m_bTurn = true; // preliminary rotation necessary
+ m_angle = oAngle; // angle was reached
+
+ m_physics->SetFreeze(true); // it does not move
+
+ m_bError = false; // ok
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskTake::IsEnded()
+{
+ CObject* fret;
+ float angle;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_bTurn ) // preliminary rotation?
+ {
+ angle = m_object->RetAngleY(0);
+ angle = Math::NormAngle(angle); // 0..2*Math::PI
+
+ if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) )
+ {
+ m_bTurn = false; // rotation ended
+ m_physics->SetMotorSpeedZ(0.0f);
+
+ if ( m_arm == TTA_FFRONT )
+ {
+ m_motion->SetAction(MHS_TAKE, 0.2f); // will decrease
+ }
+ if ( m_arm == TTA_FRIEND )
+ {
+ if ( m_height <= 3.0f )
+ {
+ m_motion->SetAction(MHS_TAKEOTHER, 0.2f); // will decrease
+ }
+ else
+ {
+ m_motion->SetAction(MHS_TAKEHIGH, 0.2f); // will decrease
+ }
+ }
+ m_progress = 0.0f;
+ m_speed = 1.0f/0.6f;
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+ m_progress = 0.0f;
+
+ m_step ++;
+
+ if ( m_order == TTO_TAKE )
+ {
+ if ( m_step == 1 )
+ {
+ if ( TruckTakeObject() )
+ {
+ if ( m_arm == TTA_FRIEND &&
+ (m_fretType == OBJECT_POWER ||
+ m_fretType == OBJECT_ATOMIC ) )
+ {
+ m_sound->Play(SOUND_POWEROFF, m_object->RetPosition(0));
+ }
+ }
+ m_motion->SetAction(MHS_UPRIGHT, 0.4f); // gets up
+ m_progress = 0.0f;
+ m_speed = 1.0f/0.8f;
+ m_camera->StopCentering(m_object, 0.8f);
+ return ERR_CONTINUE;
+ }
+ }
+
+ if ( m_order == TTO_DEPOSE )
+ {
+ if ( m_step == 1 )
+ {
+ fret = m_object->RetFret();
+ TruckDeposeObject();
+ if ( m_arm == TTA_FRIEND &&
+ (m_fretType == OBJECT_POWER ||
+ m_fretType == OBJECT_ATOMIC ) )
+ {
+ m_sound->Play(SOUND_POWERON, m_object->RetPosition(0));
+ }
+ if ( fret != 0 && m_fretType == OBJECT_METAL && m_arm == TTA_FFRONT )
+ {
+ m_main->ShowDropZone(fret, m_object); // shows buildable area
+ }
+ m_motion->SetAction(-1); // gets up
+ m_progress = 0.0f;
+ m_speed = 1.0f/0.4f;
+ m_camera->StopCentering(m_object, 0.8f);
+ return ERR_CONTINUE;
+ }
+ }
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskTake::Abort()
+{
+ m_motion->SetAction(-1);
+ m_camera->StopCentering(m_object, 0.8f);
+ m_physics->SetFreeze(false); // is moving again
+ return true;
+}
+
+
+// Seeks the object to take in front.
+
+CObject* CTaskTake::SearchTakeObject(float &angle,
+ float dLimit, float aLimit)
+{
+ CObject *pObj, *pBest;
+ Math::Vector iPos, oPos;
+ ObjectType type;
+ float min, iAngle, bAngle, a, distance;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+
+ min = 1000000.0f;
+ pBest = 0;
+ bAngle = 0.0f;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+
+ if ( type != OBJECT_FRET &&
+ type != OBJECT_STONE &&
+ type != OBJECT_URANIUM &&
+ type != OBJECT_BULLET &&
+ type != OBJECT_METAL &&
+ type != OBJECT_POWER &&
+ type != OBJECT_ATOMIC &&
+ type != OBJECT_BBOX &&
+ type != OBJECT_KEYa &&
+ type != OBJECT_KEYb &&
+ type != OBJECT_KEYc &&
+ type != OBJECT_KEYd &&
+ type != OBJECT_TNT ) continue;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( pObj->RetLock() ) continue;
+ if ( pObj->RetZoomY(0) != 1.0f ) continue;
+
+ oPos = pObj->RetPosition(0);
+ distance = Math::Distance(oPos, iPos);
+ if ( distance >= 4.0f-dLimit &&
+ distance <= 4.0f+dLimit )
+ {
+ angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+ if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
+ {
+ a = fabs(angle-iAngle);
+ if ( a > Math::PI ) a = Math::PI*2.0f-a;
+ if ( a < min )
+ {
+ min = a;
+ pBest = pObj;
+ bAngle = angle;
+ }
+ }
+ }
+ }
+ angle = bAngle;
+ return pBest;
+}
+
+// Seeks the robot on which you want take or put a battery.
+
+CObject* CTaskTake::SearchFriendObject(float &angle,
+ float dLimit, float aLimit)
+{
+ Character* character;
+ CObject* pObj;
+ CObject* pPower;
+ Math::Matrix* mat;
+ Math::Vector iPos, oPos;
+ ObjectType type, powerType;
+ float iAngle, iRad, distance;
+ int i;
+
+ if ( !m_object->GetCrashSphere(0, iPos, iRad) ) return 0;
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue; // yourself?
+
+ type = pObj->RetType();
+ if ( type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis &&
+ type != OBJECT_MOBILErt &&
+ type != OBJECT_MOBILErc &&
+ type != OBJECT_MOBILErr &&
+ type != OBJECT_MOBILErs &&
+ type != OBJECT_MOBILEsa &&
+ type != OBJECT_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_TOWER &&
+ type != OBJECT_RESEARCH &&
+ type != OBJECT_ENERGY &&
+ type != OBJECT_LABO &&
+ type != OBJECT_NUCLEAR ) continue;
+
+ pPower = pObj->RetPower();
+ if ( pPower != 0 )
+ {
+ if ( pPower->RetLock() ) continue;
+ if ( pPower->RetZoomY(0) != 1.0f ) continue;
+
+ powerType = pPower->RetType();
+ if ( powerType == OBJECT_NULL ||
+ powerType == OBJECT_FIX ) continue;
+ }
+
+ mat = pObj->RetWorldMatrix(0);
+ character = pObj->RetCharacter();
+ oPos = Transform(*mat, character->posPower);
+
+ distance = fabs(Math::Distance(oPos, iPos) - (iRad+1.0f));
+ if ( distance <= dLimit )
+ {
+ angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+ if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
+ {
+ character = pObj->RetCharacter();
+ m_height = character->posPower.y;
+ return pObj;
+ }
+ }
+ }
+
+ return 0;
+}
+
+// Takes the object in front.
+
+bool CTaskTake::TruckTakeObject()
+{
+ CObject* fret;
+ CObject* other;
+ Math::Matrix matRotate;
+ float angle;
+
+ if ( m_arm == TTA_FFRONT ) // takes on the ground in front?
+ {
+//? fret = SearchTakeObject(angle, 1.5f, Math::PI*0.04f);
+ fret = SearchTakeObject(angle, 1.5f, Math::PI*0.15f); //OK 1.9
+ if ( fret == 0 ) return false; // rien � prendre ?
+ m_fretType = fret->RetType();
+
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(4); // takes with the hand
+
+//? fret->SetPosition(0, Math::Vector(2.2f, -1.0f, 1.1f));
+ fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f));
+ fret->SetAngleY(0, 0.1f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.8f);
+
+ m_object->SetFret(fret); // takes
+ }
+
+ if ( m_arm == TTA_FRIEND ) // takes friend's battery?
+ {
+ other = SearchFriendObject(angle, 1.5f, Math::PI*0.04f);
+ if ( other == 0 ) return false;
+
+ fret = other->RetPower();
+ if ( fret == 0 ) return false; // the other does not have a battery?
+ m_fretType = fret->RetType();
+
+ other->SetPower(0);
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(4); // takes with the hand
+
+//? fret->SetPosition(0, Math::Vector(2.2f, -1.0f, 1.1f));
+ fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f));
+ fret->SetAngleY(0, 0.1f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.8f);
+
+ m_object->SetFret(fret); // takes
+ }
+
+ return true;
+}
+
+// Deposes the object taken.
+
+bool CTaskTake::TruckDeposeObject()
+{
+ Character* character;
+ CObject* fret;
+ CObject* other;
+ Math::Matrix* mat;
+ Math::Vector pos;
+ float angle;
+
+ if ( m_arm == TTA_FFRONT ) // deposes on the ground in front?
+ {
+ fret = m_object->RetFret();
+ if ( fret == 0 ) return false; // does nothing?
+ m_fretType = fret->RetType();
+
+ mat = fret->RetWorldMatrix(0);
+ pos = Transform(*mat, Math::Vector(-0.5f, 1.0f, 0.0f));
+ m_terrain->MoveOnFloor(pos);
+ fret->SetPosition(0, pos);
+ fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.0f);
+ fret->FloorAdjust(); // plate well on the ground
+
+ fret->SetTruck(0);
+ m_object->SetFret(0); // deposit
+ }
+
+ if ( m_arm == TTA_FRIEND ) // deposes battery on friends?
+ {
+ other = SearchFriendObject(angle, 1.5f, Math::PI*0.04f);
+ if ( other == 0 ) return false;
+
+ fret = other->RetPower();
+ if ( fret != 0 ) return false; // the other already has a battery?
+
+ fret = m_object->RetFret();
+ if ( fret == 0 ) return false;
+ m_fretType = fret->RetType();
+
+ other->SetPower(fret);
+ fret->SetTruck(other);
+
+ character = other->RetCharacter();
+ fret->SetPosition(0, character->posPower);
+ fret->SetAngleY(0, 0.0f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.0f);
+ fret->SetTruckPart(0); // carried by the base
+
+ m_object->SetFret(0); // deposit
+ }
+
+ return true;
+}
+
+// Seeks if a location allows to deposit an object.
+
+bool CTaskTake::IsFreeDeposeObject(Math::Vector pos)
+{
+ CObject* pObj;
+ Math::Matrix* mat;
+ Math::Vector iPos, oPos;
+ float oRadius;
+ int i, j;
+
+ mat = m_object->RetWorldMatrix(0);
+ iPos = Transform(*mat, pos);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue;
+ if ( !pObj->RetActif() ) continue; // inactive?
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ if ( Math::Distance(iPos, oPos)-(oRadius+1.0f) < 1.0f )
+ {
+ return false; // location occupied
+ }
+ }
+ }
+ return true; // location free
+}
+
+
diff --git a/src/object/task/tasktake.h b/src/object/task/tasktake.h
index b8203a8..b0553a0 100644
--- a/src/object/task/tasktake.h
+++ b/src/object/task/tasktake.h
@@ -1,75 +1,75 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// tasktake.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-
-
-
-enum TaskTakeOrder
-{
- TTO_TAKE = 1, // takes an object
- TTO_DEPOSE = 2, // deposes the object
-};
-
-enum TaskTakeArm
-{
- TTA_NEUTRAL = 1, // empty arm at rest
- TTA_FFRONT = 2, // arm on the ground
- TTA_FRIEND = 3, // arm behind a friend robot
-};
-
-
-
-class CTaskTake : public CTask
-{
-public:
- CTaskTake(CInstanceManager* iMan, CObject* object);
- ~CTaskTake();
-
- bool EventProcess(const Event &event);
-
- Error Start();
- Error IsEnded();
- bool Abort();
-
-protected:
- CObject* SearchTakeObject(float &angle, float dLimit, float aLimit);
- CObject* SearchFriendObject(float &angle, float dLimit, float aLimit);
- bool TruckTakeObject();
- bool TruckDeposeObject();
- bool IsFreeDeposeObject(Math::Vector pos);
-
-protected:
- CTerrain* m_terrain;
-
- TaskTakeOrder m_order;
- TaskTakeArm m_arm;
- int m_step;
- float m_speed;
- float m_progress;
- float m_height;
- bool m_bError;
- bool m_bTurn;
- float m_angle;
- ObjectType m_fretType;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// tasktake.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "object/object.h"
+
+
+
+enum TaskTakeOrder
+{
+ TTO_TAKE = 1, // takes an object
+ TTO_DEPOSE = 2, // deposes the object
+};
+
+enum TaskTakeArm
+{
+ TTA_NEUTRAL = 1, // empty arm at rest
+ TTA_FFRONT = 2, // arm on the ground
+ TTA_FRIEND = 3, // arm behind a friend robot
+};
+
+
+
+class CTaskTake : public CTask
+{
+public:
+ CTaskTake(CInstanceManager* iMan, CObject* object);
+ ~CTaskTake();
+
+ bool EventProcess(const Event &event);
+
+ Error Start();
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ CObject* SearchTakeObject(float &angle, float dLimit, float aLimit);
+ CObject* SearchFriendObject(float &angle, float dLimit, float aLimit);
+ bool TruckTakeObject();
+ bool TruckDeposeObject();
+ bool IsFreeDeposeObject(Math::Vector pos);
+
+protected:
+ CTerrain* m_terrain;
+
+ TaskTakeOrder m_order;
+ TaskTakeArm m_arm;
+ int m_step;
+ float m_speed;
+ float m_progress;
+ float m_height;
+ bool m_bError;
+ bool m_bTurn;
+ float m_angle;
+ ObjectType m_fretType;
+};
+
diff --git a/src/object/task/taskterraform.cpp b/src/object/task/taskterraform.cpp
index 58cf347..94e3b75 100644
--- a/src/object/task/taskterraform.cpp
+++ b/src/object/task/taskterraform.cpp
@@ -1,416 +1,416 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskterraform.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskterraform.h"
-
-#include "math/geometry.h"
-#include "common/iman.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "physics/physics.h"
-#include "old/pyro.h"
-#include "object/brain.h"
-#include "object/motion/motionant.h"
-#include "object/motion/motionspider.h"
-
-
-const float ENERGY_TERRA = 0.40f; // energy consumed by blow
-const float ACTION_RADIUS = 400.0f;
-
-
-
-// Object's constructor.
-
-CTaskTerraform::CTaskTerraform(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_lastParticule = 0.0f;
- m_soundChannel = -1;
-}
-
-// Object's destructor.
-
-CTaskTerraform::~CTaskTerraform()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskTerraform::EventProcess(const Event &event)
-{
- CObject* power;
- Math::Matrix* mat;
- Math::Vector pos, dir, speed;
- Math::Point dim;
- float energy;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_progress += event.rTime*m_speed; // others advance
- m_time += event.rTime;
-
- if ( m_phase == TTP_CHARGE )
- {
- if ( m_soundChannel == -1 )
- {
-#if _TEEN
- m_soundChannel = m_sound->Play(SOUND_GGG, m_object->RetPosition(0), 1.0f, 0.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.0f, 1.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP);
-#else
- m_soundChannel = m_sound->Play(SOUND_GGG, m_object->RetPosition(0), 1.0f, 0.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.0f, 4.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP);
-#endif
- }
-
- dir.x = 0.0f;
- dir.y = (Math::Rand()-0.5f)*0.2f*m_progress;
- dir.z = 0.0f;
- m_object->SetCirVibration(dir);
-
- m_object->SetZoom(0, 1.0f+m_progress*0.2f);
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- power->SetZoom(0, 1.0f+m_progress*1.0f);
-
- energy = power->RetEnergy();
- energy -= event.rTime*ENERGY_TERRA/power->RetCapacity()/4.0f;
- if ( energy < 0.0f ) energy = 0.0f;
- power->SetEnergy(energy);
- }
- }
-
- if ( m_phase == TTP_DOWN )
- {
- pos.x = 9.0f;
-#if _TEEN
- pos.y = 4.0f-m_progress*4.0f;
-#else
- pos.y = 4.0f-m_progress*5.8f;
-#endif
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
- }
-
- if ( m_phase == TTP_UP )
- {
- pos.x = 9.0f;
-#if _TEEN
- pos.y = 4.0f-(1.0f-m_progress)*4.0f;
-#else
- pos.y = 4.0f-(1.0f-m_progress)*5.8f;
-#endif
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
- }
-
- dir.x = 0.0f;
- dir.y = 0.0f;
- dir.z = 0.0f;
- pos = m_object->RetPosition(2);
- if ( pos.y < 0.0f )
- {
- dir.z = -atanf((pos.y/2.0f)/9.0f);
- }
- m_object->SetInclinaison(dir);
-
- if ( m_time-m_lastParticule >= m_engine->ParticuleAdapt(0.05f) )
- {
- m_lastParticule = m_time;
-
- mat = m_object->RetWorldMatrix(0);
-
- if ( m_phase == TTP_CHARGE )
- {
- // Battery.
- pos = Math::Vector(-6.0f, 5.5f+2.0f*m_progress, 0.0f);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- pos = Math::Transform(*mat, pos);
- speed.x = (Math::Rand()-0.5f)*6.0f*(1.0f+m_progress*4.0f);
- speed.z = (Math::Rand()-0.5f)*6.0f*(1.0f+m_progress*4.0f);
- speed.y = 6.0f+Math::Rand()*4.0f*(1.0f+m_progress*2.0f);
- dim.x = 0.5f+1.5f*m_progress;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 2.0f, 20.0f);
- }
-
- if ( m_phase != TTP_CHARGE )
- {
- // Left grid.
- pos = Math::Vector(-1.0f, 5.8f, 3.5f);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- pos = Math::Transform(*mat, pos);
- speed.x = Math::Rand()*4.0f;
- speed.z = Math::Rand()*2.0f;
- speed.y = 2.5f+Math::Rand()*1.0f;
- speed = Math::Transform(*mat, speed);
- speed -= m_object->RetPosition(0);
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
-
- // Right grid.
- pos = Math::Vector(-1.0f, 5.8f, -3.5f);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- pos = Math::Transform(*mat, pos);
- speed.x = Math::Rand()*4.0f;
- speed.z = -Math::Rand()*2.0f;
- speed.y = 2.5f+Math::Rand()*1.0f;
- speed = Math::Transform(*mat, speed);
- speed -= m_object->RetPosition(0);
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
- }
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskTerraform::Start()
-{
- CObject* power;
- Math::Matrix* mat;
- Math::Vector pos, speed;
- float energy;
-
- ObjectType type;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() ) return ERR_TERRA_VEH;
-
- type = m_object->RetType();
- if ( type != OBJECT_MOBILErt ) return ERR_TERRA_VEH;
-
- power = m_object->RetPower();
- if ( power == 0 ) return ERR_TERRA_ENERGY;
- energy = power->RetEnergy();
- if ( energy < ENERGY_TERRA/power->RetCapacity()+0.05f ) return ERR_TERRA_ENERGY;
-
- speed = m_physics->RetMotorSpeed();
- if ( speed.x != 0.0f ||
- speed.z != 0.0f ) return ERR_MANIP_MOTOR;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(9.0f, 0.0f, 0.0f);
- pos = Math::Transform(*mat, pos); // battery position
- m_terraPos = pos;
-
- m_phase = TTP_CHARGE;
- m_progress = 0.0f;
-#if _TEEN
- m_speed = 1.0f/1.5f;
-#else
- m_speed = 1.0f/4.0f;
-#endif
- m_time = 0.0f;
-
- m_bError = false; // ok
-
- m_camera->StartCentering(m_object, Math::PI*0.35f, 99.9f, 20.0f, 2.0f);
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskTerraform::IsEnded()
-{
- CObject* power;
- Math::Vector pos, speed;
- Math::Point dim;
- float dist, duration;
- int i, max;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( m_phase == TTP_CHARGE )
- {
-#if _TEEN
- Terraform(); // changes the terrain.
-#endif
-
- m_phase = TTP_DOWN;
- m_speed = 1.0f/0.2f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TTP_DOWN )
- {
-#if !_TEEN
- Terraform(); // changes the terrain.
-#endif
-
- m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetZoom(0, 1.0f);
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- power->SetZoom(0, 1.0f);
- }
-
- max= (int)(50.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<max ; i++ )
- {
- pos.x = m_terraPos.x+(Math::Rand()-0.5f)*80.0f;
- pos.z = m_terraPos.z+(Math::Rand()-0.5f)*80.0f;
- pos.y = m_terraPos.y;
- m_terrain->MoveOnFloor(pos);
- dist = Math::Distance(pos, m_terraPos);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 2.0f+(40.0f-dist)/(1.0f+Math::Rand()*4.0f);
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
-
- pos = m_terraPos;
- speed.x = (Math::Rand()-0.5f)*40.0f;
- speed.z = (Math::Rand()-0.5f)*40.0f;
- speed.y = Math::Rand()*15.0f+15.0f;
- dim.x = 0.6f;
- dim.y = dim.x;
- pos.y += dim.y;
- duration = Math::Rand()*3.0f+3.0f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK5,
- duration, Math::Rand()*10.0f+15.0f,
- duration*0.2f, 1.0f);
- }
-
- m_phase = TTP_TERRA;
- m_speed = 1.0f/2.0f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TTP_TERRA )
- {
- m_phase = TTP_UP;
- m_speed = 1.0f/1.0f;
- return ERR_CONTINUE;
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskTerraform::Abort()
-{
- CObject* power;
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.3f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- m_object->SetPosition(2, Math::Vector(9.0f, 4.0f, 0.0f));
- m_object->SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetZoom(0, 1.0f);
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- power->SetZoom(0, 1.0f);
- }
-
- m_camera->StopCentering(m_object, 2.0f);
- return true;
-}
-
-
-// Returns all the close ants and spiders.
-
-bool CTaskTerraform::Terraform()
-{
- CObject* pObj;
- CBrain* brain;
- CMotion* motion;
- CPyro* pyro;
- ObjectType type;
- float dist;
- int i;
-
- m_camera->StartEffect(CE_TERRAFORM, m_terraPos, 1.0f);
-
- m_sound->Play(SOUND_THUMP, m_terraPos);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_NULL ) continue;
-
- if ( type == OBJECT_TEEN34 ) // stone?
- {
- dist = Math::Distance(m_terraPos, pObj->RetPosition(0));
- if ( dist > 20.0f ) continue;
-
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FRAGT, pObj);
- }
- else
- {
- motion = pObj->RetMotion();
- if ( motion == 0 ) continue;
-
- dist = Math::Distance(m_terraPos, pObj->RetPosition(0));
- if ( dist > ACTION_RADIUS ) continue;
-
- if ( type == OBJECT_ANT )
- {
- brain = pObj->RetBrain();
- if ( brain != 0 ) brain->StopTask();
- motion->SetAction(MAS_BACK1, 0.8f+Math::Rand()*0.3f);
- pObj->SetFixed(true); // not moving
- }
- if ( type == OBJECT_SPIDER )
- {
- brain = pObj->RetBrain();
- if ( brain != 0 ) brain->StopTask();
- motion->SetAction(MSS_BACK1, 0.8f+Math::Rand()*0.3f);
- pObj->SetFixed(true); // not moving
- }
- }
- }
-
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskterraform.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskterraform.h"
+
+#include "math/geometry.h"
+#include "common/iman.h"
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "physics/physics.h"
+#include "old/pyro.h"
+#include "object/brain.h"
+#include "object/motion/motionant.h"
+#include "object/motion/motionspider.h"
+
+
+const float ENERGY_TERRA = 0.40f; // energy consumed by blow
+const float ACTION_RADIUS = 400.0f;
+
+
+
+// Object's constructor.
+
+CTaskTerraform::CTaskTerraform(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_lastParticule = 0.0f;
+ m_soundChannel = -1;
+}
+
+// Object's destructor.
+
+CTaskTerraform::~CTaskTerraform()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskTerraform::EventProcess(const Event &event)
+{
+ CObject* power;
+ Math::Matrix* mat;
+ Math::Vector pos, dir, speed;
+ Math::Point dim;
+ float energy;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ m_progress += event.rTime*m_speed; // others advance
+ m_time += event.rTime;
+
+ if ( m_phase == TTP_CHARGE )
+ {
+ if ( m_soundChannel == -1 )
+ {
+#if _TEEN
+ m_soundChannel = m_sound->Play(SOUND_GGG, m_object->RetPosition(0), 1.0f, 0.5f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.0f, 1.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP);
+#else
+ m_soundChannel = m_sound->Play(SOUND_GGG, m_object->RetPosition(0), 1.0f, 0.5f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.0f, 4.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP);
+#endif
+ }
+
+ dir.x = 0.0f;
+ dir.y = (Math::Rand()-0.5f)*0.2f*m_progress;
+ dir.z = 0.0f;
+ m_object->SetCirVibration(dir);
+
+ m_object->SetZoom(0, 1.0f+m_progress*0.2f);
+
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ power->SetZoom(0, 1.0f+m_progress*1.0f);
+
+ energy = power->RetEnergy();
+ energy -= event.rTime*ENERGY_TERRA/power->RetCapacity()/4.0f;
+ if ( energy < 0.0f ) energy = 0.0f;
+ power->SetEnergy(energy);
+ }
+ }
+
+ if ( m_phase == TTP_DOWN )
+ {
+ pos.x = 9.0f;
+#if _TEEN
+ pos.y = 4.0f-m_progress*4.0f;
+#else
+ pos.y = 4.0f-m_progress*5.8f;
+#endif
+ pos.z = 0.0f;
+ m_object->SetPosition(2, pos);
+ }
+
+ if ( m_phase == TTP_UP )
+ {
+ pos.x = 9.0f;
+#if _TEEN
+ pos.y = 4.0f-(1.0f-m_progress)*4.0f;
+#else
+ pos.y = 4.0f-(1.0f-m_progress)*5.8f;
+#endif
+ pos.z = 0.0f;
+ m_object->SetPosition(2, pos);
+ }
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = 0.0f;
+ pos = m_object->RetPosition(2);
+ if ( pos.y < 0.0f )
+ {
+ dir.z = -atanf((pos.y/2.0f)/9.0f);
+ }
+ m_object->SetInclinaison(dir);
+
+ if ( m_time-m_lastParticule >= m_engine->ParticuleAdapt(0.05f) )
+ {
+ m_lastParticule = m_time;
+
+ mat = m_object->RetWorldMatrix(0);
+
+ if ( m_phase == TTP_CHARGE )
+ {
+ // Battery.
+ pos = Math::Vector(-6.0f, 5.5f+2.0f*m_progress, 0.0f);
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ pos = Math::Transform(*mat, pos);
+ speed.x = (Math::Rand()-0.5f)*6.0f*(1.0f+m_progress*4.0f);
+ speed.z = (Math::Rand()-0.5f)*6.0f*(1.0f+m_progress*4.0f);
+ speed.y = 6.0f+Math::Rand()*4.0f*(1.0f+m_progress*2.0f);
+ dim.x = 0.5f+1.5f*m_progress;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 2.0f, 20.0f);
+ }
+
+ if ( m_phase != TTP_CHARGE )
+ {
+ // Left grid.
+ pos = Math::Vector(-1.0f, 5.8f, 3.5f);
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ pos = Math::Transform(*mat, pos);
+ speed.x = Math::Rand()*4.0f;
+ speed.z = Math::Rand()*2.0f;
+ speed.y = 2.5f+Math::Rand()*1.0f;
+ speed = Math::Transform(*mat, speed);
+ speed -= m_object->RetPosition(0);
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
+
+ // Right grid.
+ pos = Math::Vector(-1.0f, 5.8f, -3.5f);
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ pos = Math::Transform(*mat, pos);
+ speed.x = Math::Rand()*4.0f;
+ speed.z = -Math::Rand()*2.0f;
+ speed.y = 2.5f+Math::Rand()*1.0f;
+ speed = Math::Transform(*mat, speed);
+ speed -= m_object->RetPosition(0);
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
+ }
+ }
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskTerraform::Start()
+{
+ CObject* power;
+ Math::Matrix* mat;
+ Math::Vector pos, speed;
+ float energy;
+
+ ObjectType type;
+
+ m_bError = true; // operation impossible
+ if ( !m_physics->RetLand() ) return ERR_TERRA_VEH;
+
+ type = m_object->RetType();
+ if ( type != OBJECT_MOBILErt ) return ERR_TERRA_VEH;
+
+ power = m_object->RetPower();
+ if ( power == 0 ) return ERR_TERRA_ENERGY;
+ energy = power->RetEnergy();
+ if ( energy < ENERGY_TERRA/power->RetCapacity()+0.05f ) return ERR_TERRA_ENERGY;
+
+ speed = m_physics->RetMotorSpeed();
+ if ( speed.x != 0.0f ||
+ speed.z != 0.0f ) return ERR_MANIP_MOTOR;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(9.0f, 0.0f, 0.0f);
+ pos = Math::Transform(*mat, pos); // battery position
+ m_terraPos = pos;
+
+ m_phase = TTP_CHARGE;
+ m_progress = 0.0f;
+#if _TEEN
+ m_speed = 1.0f/1.5f;
+#else
+ m_speed = 1.0f/4.0f;
+#endif
+ m_time = 0.0f;
+
+ m_bError = false; // ok
+
+ m_camera->StartCentering(m_object, Math::PI*0.35f, 99.9f, 20.0f, 2.0f);
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskTerraform::IsEnded()
+{
+ CObject* power;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float dist, duration;
+ int i, max;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+ m_progress = 0.0f;
+
+ if ( m_phase == TTP_CHARGE )
+ {
+#if _TEEN
+ Terraform(); // changes the terrain.
+#endif
+
+ m_phase = TTP_DOWN;
+ m_speed = 1.0f/0.2f;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TTP_DOWN )
+ {
+#if !_TEEN
+ Terraform(); // changes the terrain.
+#endif
+
+ m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ m_object->SetZoom(0, 1.0f);
+
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ power->SetZoom(0, 1.0f);
+ }
+
+ max= (int)(50.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<max ; i++ )
+ {
+ pos.x = m_terraPos.x+(Math::Rand()-0.5f)*80.0f;
+ pos.z = m_terraPos.z+(Math::Rand()-0.5f)*80.0f;
+ pos.y = m_terraPos.y;
+ m_terrain->MoveOnFloor(pos);
+ dist = Math::Distance(pos, m_terraPos);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 2.0f+(40.0f-dist)/(1.0f+Math::Rand()*4.0f);
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+
+ pos = m_terraPos;
+ speed.x = (Math::Rand()-0.5f)*40.0f;
+ speed.z = (Math::Rand()-0.5f)*40.0f;
+ speed.y = Math::Rand()*15.0f+15.0f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ pos.y += dim.y;
+ duration = Math::Rand()*3.0f+3.0f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK5,
+ duration, Math::Rand()*10.0f+15.0f,
+ duration*0.2f, 1.0f);
+ }
+
+ m_phase = TTP_TERRA;
+ m_speed = 1.0f/2.0f;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TTP_TERRA )
+ {
+ m_phase = TTP_UP;
+ m_speed = 1.0f/1.0f;
+ return ERR_CONTINUE;
+ }
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskTerraform::Abort()
+{
+ CObject* power;
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.3f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ m_object->SetPosition(2, Math::Vector(9.0f, 4.0f, 0.0f));
+ m_object->SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
+ m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ m_object->SetZoom(0, 1.0f);
+
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ power->SetZoom(0, 1.0f);
+ }
+
+ m_camera->StopCentering(m_object, 2.0f);
+ return true;
+}
+
+
+// Returns all the close ants and spiders.
+
+bool CTaskTerraform::Terraform()
+{
+ CObject* pObj;
+ CBrain* brain;
+ CMotion* motion;
+ CPyro* pyro;
+ ObjectType type;
+ float dist;
+ int i;
+
+ m_camera->StartEffect(CE_TERRAFORM, m_terraPos, 1.0f);
+
+ m_sound->Play(SOUND_THUMP, m_terraPos);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_NULL ) continue;
+
+ if ( type == OBJECT_TEEN34 ) // stone?
+ {
+ dist = Math::Distance(m_terraPos, pObj->RetPosition(0));
+ if ( dist > 20.0f ) continue;
+
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FRAGT, pObj);
+ }
+ else
+ {
+ motion = pObj->RetMotion();
+ if ( motion == 0 ) continue;
+
+ dist = Math::Distance(m_terraPos, pObj->RetPosition(0));
+ if ( dist > ACTION_RADIUS ) continue;
+
+ if ( type == OBJECT_ANT )
+ {
+ brain = pObj->RetBrain();
+ if ( brain != 0 ) brain->StopTask();
+ motion->SetAction(MAS_BACK1, 0.8f+Math::Rand()*0.3f);
+ pObj->SetFixed(true); // not moving
+ }
+ if ( type == OBJECT_SPIDER )
+ {
+ brain = pObj->RetBrain();
+ if ( brain != 0 ) brain->StopTask();
+ motion->SetAction(MSS_BACK1, 0.8f+Math::Rand()*0.3f);
+ pObj->SetFixed(true); // not moving
+ }
+ }
+ }
+
+ return true;
+}
+
diff --git a/src/object/task/taskterraform.h b/src/object/task/taskterraform.h
index d4798e6..5c9c114 100644
--- a/src/object/task/taskterraform.h
+++ b/src/object/task/taskterraform.h
@@ -1,62 +1,62 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskterraform.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-enum TaskTerraPhase
-{
- TTP_CHARGE = 1, // charge of energy
- TTP_DOWN = 2, // down
- TTP_TERRA = 3, // strike
- TTP_UP = 4, // up
-};
-
-
-
-class CTaskTerraform : public CTask
-{
-public:
- CTaskTerraform(CInstanceManager* iMan, CObject* object);
- ~CTaskTerraform();
-
- bool EventProcess(const Event &event);
-
- Error Start();
- Error IsEnded();
- bool Abort();
-
-protected:
- bool Terraform();
-
-protected:
- TaskTerraPhase m_phase;
- float m_progress;
- float m_speed;
- float m_time;
- float m_lastParticule;
- int m_soundChannel;
- bool m_bError;
- Math::Vector m_terraPos;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskterraform.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "math/vector.h"
+
+
+
+enum TaskTerraPhase
+{
+ TTP_CHARGE = 1, // charge of energy
+ TTP_DOWN = 2, // down
+ TTP_TERRA = 3, // strike
+ TTP_UP = 4, // up
+};
+
+
+
+class CTaskTerraform : public CTask
+{
+public:
+ CTaskTerraform(CInstanceManager* iMan, CObject* object);
+ ~CTaskTerraform();
+
+ bool EventProcess(const Event &event);
+
+ Error Start();
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ bool Terraform();
+
+protected:
+ TaskTerraPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_time;
+ float m_lastParticule;
+ int m_soundChannel;
+ bool m_bError;
+ Math::Vector m_terraPos;
+};
+
diff --git a/src/object/task/taskturn.cpp b/src/object/task/taskturn.cpp
index d29cdaa..f8bf26c 100644
--- a/src/object/task/taskturn.cpp
+++ b/src/object/task/taskturn.cpp
@@ -1,134 +1,134 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskturn.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskturn.h"
-
-#include "old/terrain.h"
-#include "physics/physics.h"
-
-
-
-
-// Object's constructor.
-
-CTaskTurn::CTaskTurn(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskTurn::~CTaskTurn()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskTurn::EventProcess(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- // Momentarily stationary object (ant on the back)?
- if ( m_object->RetFixed() )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_bError = true;
- return true;
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-// A positive angle is turning right.
-
-Error CTaskTurn::Start(float angle)
-{
- m_startAngle = m_object->RetAngleY(0);
- m_finalAngle = m_startAngle+angle;
-
- if ( angle < 0.0f )
- {
- m_angle = angle+m_physics->RetCirStopLength();
- m_physics->SetMotorSpeedZ(-1.0f); // turns left
- m_bLeft = true;
- }
- else
- {
- m_angle = angle-m_physics->RetCirStopLength();
- m_physics->SetMotorSpeedZ(1.0f); // turns right
- m_bLeft = false;
- }
- m_physics->SetMotorSpeedX(0.0f);
- m_physics->SetMotorSpeedY(0.0f);
-
- m_bError = false;
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskTurn::IsEnded()
-{
- float angle;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
-
- if ( m_bError )
- {
- return ERR_STOP;
- }
-
- angle = m_object->RetAngleY(0);
-
- if ( m_bLeft )
- {
- if ( angle <= m_startAngle+m_angle )
- {
- m_physics->SetMotorSpeedZ(0.0f);
-//? m_physics->SetCirMotionY(MO_MOTSPEED, 0.0f);
- m_physics->SetCirMotionY(MO_CURSPEED, 0.0f);
-//? m_physics->SetCirMotionY(MO_REASPEED, 0.0f);
- m_object->SetAngleY(0, m_finalAngle);
- return ERR_STOP;
- }
- }
- else
- {
- if ( angle >= m_startAngle+m_angle )
- {
- m_physics->SetMotorSpeedZ(0.0f);
-//? m_physics->SetCirMotionY(MO_MOTSPEED, 0.0f);
- m_physics->SetCirMotionY(MO_CURSPEED, 0.0f);
-//? m_physics->SetCirMotionY(MO_REASPEED, 0.0f);
- m_object->SetAngleY(0, m_finalAngle);
- return ERR_STOP;
- }
- }
-
- return ERR_CONTINUE;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskturn.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskturn.h"
+
+#include "old/terrain.h"
+#include "physics/physics.h"
+
+
+
+
+// Object's constructor.
+
+CTaskTurn::CTaskTurn(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+}
+
+// Object's destructor.
+
+CTaskTurn::~CTaskTurn()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskTurn::EventProcess(const Event &event)
+{
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ // Momentarily stationary object (ant on the back)?
+ if ( m_object->RetFixed() )
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ m_bError = true;
+ return true;
+ }
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+// A positive angle is turning right.
+
+Error CTaskTurn::Start(float angle)
+{
+ m_startAngle = m_object->RetAngleY(0);
+ m_finalAngle = m_startAngle+angle;
+
+ if ( angle < 0.0f )
+ {
+ m_angle = angle+m_physics->RetCirStopLength();
+ m_physics->SetMotorSpeedZ(-1.0f); // turns left
+ m_bLeft = true;
+ }
+ else
+ {
+ m_angle = angle-m_physics->RetCirStopLength();
+ m_physics->SetMotorSpeedZ(1.0f); // turns right
+ m_bLeft = false;
+ }
+ m_physics->SetMotorSpeedX(0.0f);
+ m_physics->SetMotorSpeedY(0.0f);
+
+ m_bError = false;
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskTurn::IsEnded()
+{
+ float angle;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+
+ if ( m_bError )
+ {
+ return ERR_STOP;
+ }
+
+ angle = m_object->RetAngleY(0);
+
+ if ( m_bLeft )
+ {
+ if ( angle <= m_startAngle+m_angle )
+ {
+ m_physics->SetMotorSpeedZ(0.0f);
+//? m_physics->SetCirMotionY(MO_MOTSPEED, 0.0f);
+ m_physics->SetCirMotionY(MO_CURSPEED, 0.0f);
+//? m_physics->SetCirMotionY(MO_REASPEED, 0.0f);
+ m_object->SetAngleY(0, m_finalAngle);
+ return ERR_STOP;
+ }
+ }
+ else
+ {
+ if ( angle >= m_startAngle+m_angle )
+ {
+ m_physics->SetMotorSpeedZ(0.0f);
+//? m_physics->SetCirMotionY(MO_MOTSPEED, 0.0f);
+ m_physics->SetCirMotionY(MO_CURSPEED, 0.0f);
+//? m_physics->SetCirMotionY(MO_REASPEED, 0.0f);
+ m_object->SetAngleY(0, m_finalAngle);
+ return ERR_STOP;
+ }
+ }
+
+ return ERR_CONTINUE;
+}
+
+
diff --git a/src/object/task/taskturn.h b/src/object/task/taskturn.h
index bfbd064..1ee40d9 100644
--- a/src/object/task/taskturn.h
+++ b/src/object/task/taskturn.h
@@ -1,46 +1,46 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskturn.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskTurn : public CTask
-{
-public:
- CTaskTurn(CInstanceManager* iMan, CObject* object);
- ~CTaskTurn();
-
- bool EventProcess(const Event &event);
-
- Error Start(float angle);
- Error IsEnded();
-
-protected:
-
-protected:
- float m_angle;
- float m_startAngle;
- float m_finalAngle;
- bool m_bLeft;
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskturn.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+
+
+
+class CTaskTurn : public CTask
+{
+public:
+ CTaskTurn(CInstanceManager* iMan, CObject* object);
+ ~CTaskTurn();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(float angle);
+ Error IsEnded();
+
+protected:
+
+protected:
+ float m_angle;
+ float m_startAngle;
+ float m_finalAngle;
+ bool m_bLeft;
+ bool m_bError;
+};
+
diff --git a/src/object/task/taskwait.cpp b/src/object/task/taskwait.cpp
index f501405..03bddcb 100644
--- a/src/object/task/taskwait.cpp
+++ b/src/object/task/taskwait.cpp
@@ -1,74 +1,74 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskwait.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskwait.h"
-
-#include "old/d3dengine.h"
-
-
-
-// Object's constructor.
-
-CTaskWait::CTaskWait(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskWait::~CTaskWait()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskWait::EventProcess(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_passTime += event.rTime;
- m_bEnded = (m_passTime >= m_waitTime);
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskWait::Start(float time)
-{
- m_waitTime = time; // duration to wait
- m_passTime = 0.0f; // time elapsed
- m_bEnded = false;
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskWait::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bEnded ) return ERR_STOP;
- return ERR_CONTINUE;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskwait.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskwait.h"
+
+#include "old/d3dengine.h"
+
+
+
+// Object's constructor.
+
+CTaskWait::CTaskWait(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+}
+
+// Object's destructor.
+
+CTaskWait::~CTaskWait()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskWait::EventProcess(const Event &event)
+{
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_passTime += event.rTime;
+ m_bEnded = (m_passTime >= m_waitTime);
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskWait::Start(float time)
+{
+ m_waitTime = time; // duration to wait
+ m_passTime = 0.0f; // time elapsed
+ m_bEnded = false;
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskWait::IsEnded()
+{
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bEnded ) return ERR_STOP;
+ return ERR_CONTINUE;
+}
+
+
diff --git a/src/object/task/taskwait.h b/src/object/task/taskwait.h
index 3439bc8..3434c36 100644
--- a/src/object/task/taskwait.h
+++ b/src/object/task/taskwait.h
@@ -1,44 +1,44 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskwait.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskWait : public CTask
-{
-public:
- CTaskWait(CInstanceManager* iMan, CObject* object);
- ~CTaskWait();
-
- bool EventProcess(const Event &event);
-
- Error Start(float time);
- Error IsEnded();
-
-protected:
-
-protected:
- float m_waitTime;
- float m_passTime;
- bool m_bEnded;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskwait.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+
+
+
+class CTaskWait : public CTask
+{
+public:
+ CTaskWait(CInstanceManager* iMan, CObject* object);
+ ~CTaskWait();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(float time);
+ Error IsEnded();
+
+protected:
+
+protected:
+ float m_waitTime;
+ float m_passTime;
+ bool m_bEnded;
+};
+