summaryrefslogtreecommitdiffstats
path: root/src/object/auto
diff options
context:
space:
mode:
Diffstat (limited to 'src/object/auto')
-rw-r--r--src/object/auto/auto.cpp461
-rw-r--r--src/object/auto/auto.h114
-rw-r--r--src/object/auto/autobase.cpp1459
-rw-r--r--src/object/auto/autobase.h122
-rw-r--r--src/object/auto/autoconvert.cpp546
-rw-r--r--src/object/auto/autoconvert.h82
-rw-r--r--src/object/auto/autoderrick.cpp605
-rw-r--r--src/object/auto/autoderrick.h84
-rw-r--r--src/object/auto/autodestroyer.cpp397
-rw-r--r--src/object/auto/autodestroyer.h76
-rw-r--r--src/object/auto/autoegg.cpp375
-rw-r--r--src/object/auto/autoegg.h83
-rw-r--r--src/object/auto/autoenergy.cpp665
-rw-r--r--src/object/auto/autoenergy.h83
-rw-r--r--src/object/auto/autofactory.cpp961
-rw-r--r--src/object/auto/autofactory.h85
-rw-r--r--src/object/auto/autoflag.cpp178
-rw-r--r--src/object/auto/autoflag.h58
-rw-r--r--src/object/auto/autohuston.cpp315
-rw-r--r--src/object/auto/autohuston.h77
-rw-r--r--src/object/auto/autoinfo.cpp537
-rw-r--r--src/object/auto/autoinfo.h80
-rw-r--r--src/object/auto/autojostle.cpp167
-rw-r--r--src/object/auto/autojostle.h60
-rw-r--r--src/object/auto/autokid.cpp222
-rw-r--r--src/object/auto/autokid.h59
-rw-r--r--src/object/auto/autolabo.cpp629
-rw-r--r--src/object/auto/autolabo.h87
-rw-r--r--src/object/auto/automush.cpp362
-rw-r--r--src/object/auto/automush.h73
-rw-r--r--src/object/auto/autonest.cpp291
-rw-r--r--src/object/auto/autonest.h73
-rw-r--r--src/object/auto/autonuclear.cpp504
-rw-r--r--src/object/auto/autonuclear.h80
-rw-r--r--src/object/auto/autopara.cpp347
-rw-r--r--src/object/auto/autopara.h77
-rw-r--r--src/object/auto/autoportico.cpp446
-rw-r--r--src/object/auto/autoportico.h81
-rw-r--r--src/object/auto/autoradar.cpp326
-rw-r--r--src/object/auto/autoradar.h76
-rw-r--r--src/object/auto/autorepair.cpp362
-rw-r--r--src/object/auto/autorepair.h76
-rw-r--r--src/object/auto/autoresearch.cpp627
-rw-r--r--src/object/auto/autoresearch.h82
-rw-r--r--src/object/auto/autoroot.cpp135
-rw-r--r--src/object/auto/autoroot.h56
-rw-r--r--src/object/auto/autosafe.cpp636
-rw-r--r--src/object/auto/autosafe.h86
-rw-r--r--src/object/auto/autostation.cpp387
-rw-r--r--src/object/auto/autostation.h68
-rw-r--r--src/object/auto/autotower.cpp561
-rw-r--r--src/object/auto/autotower.h86
52 files changed, 14565 insertions, 0 deletions
diff --git a/src/object/auto/auto.cpp b/src/object/auto/auto.cpp
new file mode 100644
index 0000000..9711423
--- /dev/null
+++ b/src/object/auto/auto.cpp
@@ -0,0 +1,461 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "light.h"
+#include "terrain.h"
+#include "water.h"
+#include "cloud.h"
+#include "planet.h"
+#include "blitz.h"
+#include "camera.h"
+#include "object.h"
+#include "modfile.h"
+#include "interface.h"
+#include "button.h"
+#include "list.h"
+#include "label.h"
+#include "gauge.h"
+#include "window.h"
+#include "robotmain.h"
+#include "displaytext.h"
+#include "sound.h"
+#include "cmdtoken.h"
+#include "auto.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;
+ FPOINT 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
new file mode 100644
index 0000000..4cc9389
--- /dev/null
+++ b/src/object/auto/auto.h
@@ -0,0 +1,114 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// auto.h
+
+#ifndef _AUTO_H_
+#define _AUTO_H_
+
+
+#include "object.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CLight;
+class CTerrain;
+class CWater;
+class CCloud;
+class CPlanet;
+class CBlitz;
+class CCamera;
+class CObject;
+class CInterface;
+class CRobotMain;
+class CDisplayText;
+class CWindow;
+class CSound;
+
+
+
+
+class CAuto
+{
+public:
+ CAuto(CInstanceManager* iMan, CObject* object);
+ ~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;
+};
+
+
+#endif //_AUTO_H_
diff --git a/src/object/auto/autobase.cpp b/src/object/auto/autobase.cpp
new file mode 100644
index 0000000..fada8d5
--- /dev/null
+++ b/src/object/auto/autobase.cpp
@@ -0,0 +1,1459 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "language.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "terrain.h"
+#include "cloud.h"
+#include "planet.h"
+#include "blitz.h"
+#include "camera.h"
+#include "object.h"
+#include "physics.h"
+#include "interface.h"
+#include "button.h"
+#include "window.h"
+#include "displaytext.h"
+#include "robotmain.h"
+#include "sound.h"
+#include "auto.h"
+#include "autobase.h"
+
+
+
+#define BASE_LAND_TIME 7.5f // hard landing
+#define BASE_TAKO_TIME 10.0f // hard landing
+#define BASE_DOOR_TIME 6.0f // time opening / closing
+#define BASE_DOOR_TIME2 2.0f // time opening / closing suppl.
+#define BASE_PORTICO_TIME_MOVE 16.0f // gate advance time
+#define BASE_PORTICO_TIME_DOWN 4.0f // gate length down
+#define BASE_PORTICO_TIME_OPEN 4.0f // gate opening duration
+#define BASE_TRANSIT_TIME 15.0f // transit duration
+
+
+
+
+// Object's constructor.
+
+CAutoBase::CAutoBase(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::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()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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)
+{
+ D3DMATRIX* mat;
+ Event newEvent;
+ CObject* pObj;
+ D3DVECTOR pos, speed, vibCir, iPos;
+ FPOINT 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, PI/2.0f-124.0f*PI/180.0f);
+ m_object->SetAngleX(10+i, -10.0f*PI/180.0f);
+ m_object->SetAngleX(18+i, 10.0f*PI/180.0f);
+ m_object->SetPosition(10+i, D3DVECTOR(23.5f, 0.0f, -11.5f));
+ m_object->SetPosition(18+i, D3DVECTOR(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, PI/2.0f-124.0f*PI/180.0f);
+ m_object->SetAngleX(10+i, -10.0f*PI/180.0f);
+ m_object->SetAngleX(18+i, 10.0f*PI/180.0f);
+ m_object->SetPosition(10+i, D3DVECTOR(23.5f, 0.0f, -11.5f));
+ m_object->SetPosition(18+i, D3DVECTOR(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, -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 = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ dim.x = 10.0f;
+ dim.y = dim.x;
+ pos = D3DVECTOR(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 = D3DVECTOR(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 = D3DVECTOR(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 = D3DVECTOR(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 = D3DVECTOR(-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 = D3DVECTOR(-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 = D3DVECTOR(-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 = D3DVECTOR(-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*PI* 2.01f)*(PI/150.0f)+
+ sinf(m_time*PI* 2.51f)*(PI/200.0f)+
+ sinf(m_time*PI*19.01f)*(PI/400.0f);
+ vibCir.x = sinf(m_time*PI* 2.03f)*(PI/150.0f)+
+ sinf(m_time*PI* 2.52f)*(PI/200.0f)+
+ sinf(m_time*PI*19.53f)*(PI/400.0f);
+ vibCir.y = 0.0f;
+ vibCir *= 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 += (Rand()-0.5f)*10.0f;
+ pos.z += (Rand()-0.5f)*10.0f;
+ angle = Rand()*(PI*2.0f);
+ dist = m_progress*50.0f;
+ p = RotatePoint(angle, dist);
+ speed.x = p.x;
+ speed.z = p.y;
+ speed.y = 0.0f;
+ dim.x = (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 = (Rand()-0.5f)*(80.0f-50.0f*h);
+ speed.z = (Rand()-0.5f)*(80.0f-50.0f*h);
+ speed.y = -(Rand()*(h+1.0f)*40.0f+(h+1.0f)*40.0f);
+ dim.x = 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 += (Rand()-0.5f)*8.0f;
+ pos.z += (Rand()-0.5f)*8.0f;
+ pos.y += 3.0f;
+ speed.x = (Rand()-0.5f)*8.0f;
+ speed.z = (Rand()-0.5f)*8.0f;
+ speed.y = 0.0f;
+ dim.x = 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(D3DVECTOR(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 = Rand()*(PI*2.0f);
+ p = RotatePoint(angle, 46.0f);
+ pos = m_pos;
+ pos.x += p.x;
+ pos.z += p.y;
+ speed = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ dim.x = Rand()*10.0f+10.0f;
+ dim.y = dim.x;
+ time = 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 += (Rand()-0.5f)*8.0f;
+ pos.z += (Rand()-0.5f)*8.0f;
+ pos.y += 3.0f;
+ speed.x = (Rand()-0.5f)*8.0f;
+ speed.z = (Rand()-0.5f)*8.0f;
+ speed.y = 0.0f;
+ dim.x = 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*PI/180.0f;
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, PI/2.0f+angle);
+ }
+
+ if ( m_param != PARAM_PORTICO )
+ {
+ angle = m_progress*PI*2.0f;
+ p = 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, PI/2.0f-124.0f*PI/180.0f);
+ }
+
+ // Clash the doors with the ground.
+ max = (int)(20.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<max ; i++ )
+ {
+ angle = Rand()*(20.0f*PI/180.0f)-(10.0f*PI/180.0f);
+ angle += (PI/4.0f)*(rand()%8);
+ p = RotatePoint(angle, 74.0f);
+ pos = m_pos;
+ pos.x += p.x;
+ pos.z += p.y;
+ speed = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ dim.x = Rand()*8.0f+8.0f;
+ dim.y = dim.x;
+ time = 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, D3DVECTOR(23.5f, 0.0f, len));
+ m_object->SetPosition(18+i, D3DVECTOR(23.5f, 0.0f, -len));
+ m_object->SetAngleX(10+i, -10.0f*PI/180.0f*m_progress);
+ m_object->SetAngleX(18+i, 10.0f*PI/180.0f*m_progress);
+ }
+
+ if ( m_param != PARAM_PORTICO )
+ {
+ angle = m_progress*PI/2.0f;
+ p = 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, D3DVECTOR(23.5f, 0.0f, -11.5f));
+ m_object->SetPosition(18+i, D3DVECTOR(23.5f, 0.0f, 11.5f));
+ m_object->SetAngleX(10+i, -10.0f*PI/180.0f);
+ m_object->SetAngleX(18+i, 10.0f*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, D3DVECTOR(23.5f, 0.0f, len));
+ m_object->SetPosition(18+i, D3DVECTOR(23.5f, 0.0f, -len));
+ m_object->SetAngleX(10+i, -10.0f*PI/180.0f*(1.0f-m_progress));
+ m_object->SetAngleX(18+i, 10.0f*PI/180.0f*(1.0f-m_progress));
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetPosition(10+i, D3DVECTOR(23.5f, 0.0f, 7.0f));
+ m_object->SetPosition(18+i, D3DVECTOR(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*PI/180.0f;
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, PI/2.0f+angle);
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, 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 = Rand()*PI*2.0f;
+ p = RotatePoint(angle, 32.0f);
+ pos = m_pos;
+ pos.x += p.x;
+ pos.z += p.y;
+ pos.y += 85.0f;
+ speed = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ dim.x = Rand()*3.0f+3.0f;
+ dim.y = dim.x;
+ time = 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*PI*19.01f)*(PI/400.0f);
+ vibCir.x = sinf(m_time*PI*19.53f)*(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 = (Rand()-0.5f)*160.0f;
+ speed.z = (Rand()-0.5f)*160.0f;
+ speed.y = -(Rand()*10.0f+10.0f);
+ dim.x = 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*PI*19.01f)*(PI/400.0f);
+ vibCir.x = sinf(m_time*PI*19.53f)*(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 += (Rand()-0.5f)*10.0f;
+ pos.z += (Rand()-0.5f)*10.0f;
+ angle = Rand()*(PI*2.0f);
+ dist = (1.0f-m_progress)*50.0f;
+ p = RotatePoint(angle, dist);
+ speed.x = p.x;
+ speed.z = p.y;
+ speed.y = 0.0f;
+ dim.x = (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 = (Rand()-0.5f)*40.0f;
+ speed.z = (Rand()-0.5f)*40.0f;
+ time = 5.0f+150.0f*m_progress;
+ speed.y = -(Rand()*time+time);
+ time = 2.0f+m_progress*12.0f;
+ dim.x = 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 = (Rand()-0.5f)*10.0f*(4.0f-m_progress*3.0f);
+ speed.z = (Rand()-0.5f)*10.0f*(4.0f-m_progress*3.0f);
+ speed.y = 0.0f;
+ dim.x = 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 = Rand()*(PI*2.0f);
+ p = RotatePoint(angle, 46.0f);
+ pos = m_pos;
+ pos.x += p.x;
+ pos.z += p.y;
+ speed = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ dim.x = Rand()*10.0f+10.0f;
+ dim.y = dim.x;
+ time = 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 = D3DVECTOR(0.0f, 6.0f, 0.0f);
+ speed.x = (Rand()-0.5f)*4.0f;
+ speed.z = (Rand()-0.5f)*4.0f;
+ speed.y = vSpeed*0.8f-(8.0f+Rand()*6.0f);
+ speed += pos;
+ pos = Transform(*mat, pos);
+ speed = Transform(*mat, speed);
+ speed -= pos;
+
+ dim.x = 4.0f+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 = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ dim.x = 12.0f;
+ dim.y = dim.x;
+ pos = D3DVECTOR(0.0f, 7.0f, 0.0f);
+ pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 1.0f, 0.0f, 0.0f);
+
+ speed = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ dim.x = 4.0f;
+ dim.y = dim.x;
+ pos = D3DVECTOR(42.0f, 0.0f, 17.0f);
+ pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = D3DVECTOR(17.0f, 0.0f, 42.0f);
+ pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = D3DVECTOR(42.0f, 0.0f, -17.0f);
+ pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = D3DVECTOR(17.0f, 0.0f, -42.0f);
+ pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = D3DVECTOR(-42.0f, 0.0f, 17.0f);
+ pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = D3DVECTOR(-17.0f, 0.0f, 42.0f);
+ pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = D3DVECTOR(-42.0f, 0.0f, -17.0f);
+ pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = D3DVECTOR(-17.0f, 0.0f, -42.0f);
+ pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+
+ pos = D3DVECTOR(42.0f, -2.0f, 17.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[0], pos);
+ pos = D3DVECTOR(17.0f, -2.0f, 42.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[1], pos);
+ pos = D3DVECTOR(42.0f, -2.0f, -17.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[2], pos);
+ pos = D3DVECTOR(17.0f, -2.0f, -42.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[3], pos);
+ pos = D3DVECTOR(-42.0f, -2.0f, 17.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[4], pos);
+ pos = D3DVECTOR(-17.0f, -2.0f, 42.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[5], pos);
+ pos = D3DVECTOR(-42.0f, -2.0f, -17.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[6], pos);
+ pos = D3DVECTOR(-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, PI/2.0f-124.0f*PI/180.0f);
+ m_object->SetAngleX(10+i, -10.0f*PI/180.0f);
+ m_object->SetAngleX(18+i, 10.0f*PI/180.0f);
+ m_object->SetPosition(10+i, D3DVECTOR(23.5f, 0.0f, -11.5f));
+ m_object->SetPosition(18+i, D3DVECTOR(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(D3DVECTOR(0.0f, 0.0f, 0.0f));
+ MoveCargo(); // all cargo moves
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, PI/2.0f-124.0f*PI/180.0f);
+ m_object->SetAngleX(10+i, -10.0f*PI/180.0f);
+ m_object->SetAngleX(18+i, 10.0f*PI/180.0f);
+ m_object->SetPosition(10+i, D3DVECTOR(23.5f, 0.0f, -11.5f));
+ m_object->SetPosition(18+i, D3DVECTOR(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;
+ FPOINT 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;
+ D3DVECTOR 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 = Length2d(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;
+ D3DVECTOR 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;
+ D3DVECTOR 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 = Length2d(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
new file mode 100644
index 0000000..7e0093a
--- /dev/null
+++ b/src/object/auto/autobase.h
@@ -0,0 +1,122 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * 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
+
+#ifndef _AUTOBASE_H_
+#define _AUTOBASE_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+#define PARAM_STOP 0 // run=0 -> stops and open
+#define PARAM_LANDING 1 // run=1 -> landing
+#define PARAM_PORTICO 2 // run=2 -> gate on the ground
+#define PARAM_FIXSCENE 3 // run=3 -> open and stops to win / lost
+#define PARAM_TRANSIT1 11 // run=11 -> transit in space
+#define PARAM_TRANSIT2 12 // run=12 -> transit in space
+#define 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;
+ D3DVECTOR m_pos;
+ D3DVECTOR m_posSound;
+ D3DVECTOR m_finalPos;
+ D3DVECTOR 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;
+};
+
+
+#endif //_AUTOBASE_H_
diff --git a/src/object/auto/autoconvert.cpp b/src/object/auto/autoconvert.cpp
new file mode 100644
index 0000000..ae213e3
--- /dev/null
+++ b/src/object/auto/autoconvert.cpp
@@ -0,0 +1,546 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "light.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "interface.h"
+#include "button.h"
+#include "window.h"
+#include "sound.h"
+#include "displaytext.h"
+#include "cmdtoken.h"
+#include "auto.h"
+#include "autoconvert.h"
+
+
+
+
+// Object's constructor.
+
+CAutoConvert::CAutoConvert(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::CAuto(iMan, object);
+
+ Init();
+ m_phase = ACP_STOP;
+ m_bResetDelete = FALSE;
+ m_soundChannel = -1;
+}
+
+// Object's destructor.
+
+CAutoConvert::~CAutoConvert()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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;
+ D3DVECTOR pos, speed;
+ FPOINT 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+Rand()*0.3f;
+
+ angle = (Rand()-0.5f)*0.3f;
+ m_object->SetAngleY(1, angle);
+ m_object->SetAngleY(2, angle);
+ m_object->SetAngleY(3, angle+PI);
+
+ m_object->SetAngleX(2, -PI*0.35f*(0.8f+Rand()*0.2f));
+ m_object->SetAngleX(3, -PI*0.35f*(0.8f+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 = -PI*0.35f*(1.0f-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+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 = RotatePoint(c, Rand()*PI*2.0f, p);
+ pos.x = p.x;
+ pos.z = p.y;
+ pos.y += 1.0f;
+ speed = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ dim.x = 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, 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 = -PI*0.35f*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 += (Rand()-0.5f)*6.0f;
+ pos.z += (Rand()-0.5f)*6.0f;
+ pos.y += Rand()*4.0f;
+ speed = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ dim.x = 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, -PI*0.35f);
+ m_object->SetAngleX(3, -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, PI);
+ m_object->SetAngleX(2, -PI*0.35f);
+ m_object->SetAngleX(3, -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;
+ FPOINT 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;
+ D3DVECTOR 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 = Length(oPos, cPos);
+
+ if ( dist <= 5.0f ) return pObj;
+ }
+
+ return 0;
+}
+
+// Search if a vehicle is too close.
+
+BOOL CAutoConvert::SearchVehicle()
+{
+ CObject* pObj;
+ D3DVECTOR 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 = Length(oPos, cPos)-oRadius;
+
+ if ( dist < 8.0f ) return TRUE;
+ }
+
+ return FALSE;
+}
+
+// Creates an object metal.
+
+void CAutoConvert::CreateMetal()
+{
+ D3DVECTOR 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
new file mode 100644
index 0000000..2e35e24
--- /dev/null
+++ b/src/object/auto/autoconvert.h
@@ -0,0 +1,82 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * 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
+
+#ifndef _AUTOCONVERT_H_
+#define _AUTOCONVERT_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+};
+
+
+#endif //_AUTOCONVERT_H_
diff --git a/src/object/auto/autoderrick.cpp b/src/object/auto/autoderrick.cpp
new file mode 100644
index 0000000..d2541c5
--- /dev/null
+++ b/src/object/auto/autoderrick.cpp
@@ -0,0 +1,605 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "interface.h"
+#include "button.h"
+#include "window.h"
+#include "sound.h"
+#include "displaytext.h"
+#include "cmdtoken.h"
+#include "auto.h"
+#include "autoderrick.h"
+
+
+
+#define DERRICK_DELAY 10.0f // duration of the extraction
+#define DERRICK_DELAYu 30.0f // same, but for uranium
+
+
+
+
+// Object's constructor.
+
+CAutoDerrick::CAutoDerrick(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::CAuto(iMan, object);
+
+ Init();
+ m_phase = ADP_WAIT; // paused until the first Init ()
+ m_soundChannel = -1;
+}
+
+// Object's destructor.
+
+CAutoDerrick::~CAutoDerrick()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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()
+{
+ D3DMATRIX* mat;
+ D3DVECTOR 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 = D3DVECTOR(7.0f, 0.0f, 0.0f);
+ mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+ m_terrain->MoveOnFloor(pos);
+ m_fretPos = pos;
+}
+
+
+// Management of an event.
+
+BOOL CAutoDerrick::EventProcess(const Event &event)
+{
+ CObject* fret;
+ D3DVECTOR pos, speed;
+ FPOINT 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+Rand()*0.3f;
+
+ pos.x = 0.0f;
+ pos.z = 0.0f;
+ pos.y = -2.0f*Rand();
+ m_object->SetPosition(1, pos); // up / down the drill
+
+ m_object->SetAngleY(1, 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 = (Rand()-0.5f)*10.0f;
+ speed.z = (Rand()-0.5f)*10.0f;
+ speed.y = Rand()*5.0f;
+ dim.x = 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 = (Rand()-0.5f)*12.0f;
+ speed.z = (Rand()-0.5f)*12.0f;
+ speed.y = Rand()*10.0f+10.0f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ pos.y += dim.y;
+ duration = Rand()*2.0f+2.0f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK5,
+ duration, 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 = (Rand()-0.5f)*10.0f;
+ speed.z = (Rand()-0.5f)*10.0f;
+ speed.y = Rand()*5.0f;
+ dim.x = 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 = (Rand()-0.5f)*12.0f;
+ speed.z = (Rand()-0.5f)*12.0f;
+ speed.y = Rand()*10.0f+10.0f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ pos.y += dim.y;
+ duration = Rand()*2.0f+2.0f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK5,
+ duration, 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 += (Rand()-0.5f)*5.0f;
+ pos.z += (Rand()-0.5f)*5.0f;
+ pos.y += (Rand()-0.5f)*5.0f;
+ speed = D3DVECTOR(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 += (Rand()-0.5f)*5.0f;
+ pos.z += (Rand()-0.5f)*5.0f;
+ pos.y += Rand()*2.5f;
+ speed = D3DVECTOR(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;
+ FPOINT 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;
+ D3DVECTOR 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(D3DVECTOR pos)
+{
+ CObject* pObj;
+ D3DVECTOR 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 = Length(sPos, pos);
+ distance -= sRadius;
+ if ( distance < 2.0f ) return FALSE; // location occupied
+ }
+ }
+
+ return TRUE; // location free
+}
+
+// Create a transportable object.
+
+void CAutoDerrick::CreateFret(D3DVECTOR 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
new file mode 100644
index 0000000..6c9293d
--- /dev/null
+++ b/src/object/auto/autoderrick.h
@@ -0,0 +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/.
+
+// autoderrick.h
+
+#ifndef _AUTODERRICK_H_
+#define _AUTODERRICK_H_
+
+
+#include "object.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+
+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(D3DVECTOR pos);
+ void CreateFret(D3DVECTOR 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;
+ D3DVECTOR m_fretPos;
+ int m_soundChannel;
+ BOOL m_bSoundFall;
+};
+
+
+#endif //_AUTODERRICK_H_
diff --git a/src/object/auto/autodestroyer.cpp b/src/object/auto/autodestroyer.cpp
new file mode 100644
index 0000000..11dc0ba
--- /dev/null
+++ b/src/object/auto/autodestroyer.cpp
@@ -0,0 +1,397 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "light.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "physics.h"
+#include "pyro.h"
+#include "sound.h"
+#include "interface.h"
+#include "button.h"
+#include "window.h"
+#include "robotmain.h"
+#include "cmdtoken.h"
+#include "auto.h"
+#include "autodestroyer.h"
+
+
+
+
+// Object's constructor.
+
+CAutoDestroyer::CAutoDestroyer(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::CAuto(iMan, object);
+
+ Init();
+ m_phase = ADEP_WAIT; // paused until the first Init ()
+}
+
+// Destructive of the object.
+
+CAutoDestroyer::~CAutoDestroyer()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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;
+ D3DVECTOR pos, speed;
+ FPOINT 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+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 = D3DVECTOR(0.0f, -10.0f, 0.0f);
+ pos.y = -Bounce(m_progress, 0.3f)*10.0f;
+ m_object->SetPosition(1, pos);
+ }
+ else
+ {
+ m_object->SetPosition(1, D3DVECTOR(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 = D3DVECTOR(0.0f, -10.0f, 0.0f);
+ pos.y = -(1.0f-m_progress)*10.0f;
+ m_object->SetPosition(1, pos);
+ }
+ else
+ {
+ m_object->SetPosition(1, D3DVECTOR(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;
+ FPOINT 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;
+ D3DVECTOR 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 = Length(oPos, sPos);
+ if ( dist <= 5.0f ) return pObj;
+ }
+
+ return 0;
+}
+
+// Seeks if one vehicle is too close.
+
+BOOL CAutoDestroyer::SearchVehicle()
+{
+ CObject* pObj;
+ D3DVECTOR 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 = Length(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
new file mode 100644
index 0000000..a69f832
--- /dev/null
+++ b/src/object/auto/autodestroyer.h
@@ -0,0 +1,76 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autodestroyer.h
+
+#ifndef _AUTODESTROYER_H_
+#define _AUTODESTROYER_H_
+
+
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+};
+
+
+#endif //_AUTODESTROYER_H_
diff --git a/src/object/auto/autoegg.cpp b/src/object/auto/autoegg.cpp
new file mode 100644
index 0000000..6e57fcc
--- /dev/null
+++ b/src/object/auto/autoegg.cpp
@@ -0,0 +1,375 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "pyro.h"
+#include "cmdtoken.h"
+#include "auto.h"
+#include "autoegg.h"
+
+
+
+// Object's constructor.
+
+CAutoEgg::CAutoEgg(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::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()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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;
+ D3DVECTOR 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 = Length2d(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
new file mode 100644
index 0000000..4340a9b
--- /dev/null
+++ b/src/object/auto/autoegg.h
@@ -0,0 +1,83 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoegg.h
+
+#ifndef _AUTOEGG_H_
+#define _AUTOEGG_H_
+
+
+#include "object.h"
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+};
+
+
+#endif //_AUTOEGG_H_
diff --git a/src/object/auto/autoenergy.cpp b/src/object/auto/autoenergy.cpp
new file mode 100644
index 0000000..023a185
--- /dev/null
+++ b/src/object/auto/autoenergy.cpp
@@ -0,0 +1,665 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "light.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "interface.h"
+#include "button.h"
+#include "gauge.h"
+#include "window.h"
+#include "displaytext.h"
+#include "sound.h"
+#include "cmdtoken.h"
+#include "auto.h"
+#include "autoenergy.h"
+
+
+
+#define ENERGY_POWER 0.4f // Necessary energy for a battery
+#define ENERGY_DELAY 12.0f // processing time
+
+
+
+
+// Object's constructor.
+
+CAutoEnergy::CAutoEnergy(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::CAuto(iMan, object);
+
+ m_partiSphere = -1;
+ Init();
+}
+
+// Object's destructor.
+
+CAutoEnergy::~CAutoEnergy()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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;
+ D3DVECTOR pos, ppos, speed;
+ FPOINT 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+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 = (Rand()-0.5f)*10.0f;
+ speed.z = (Rand()-0.5f)*10.0f;
+ speed.y = -7.0f;
+ dim.x = 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 = D3DVECTOR(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/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 = (Rand()-0.5f)*1.0f;
+ speed.z = (Rand()-0.5f)*1.0f;
+ speed.y = -7.0f;
+ dim.x = 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 = RotatePoint(c, Rand()*PI*2.0f, p);
+ pos.x = p.x;
+ pos.z = p.y;
+ pos.y += 2.5f+Rand()*3.0f;
+ speed = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ dim.x = 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 = (Rand()-0.5f)*30.0f;
+ speed.z = (Rand()-0.5f)*30.0f;
+ speed.y = Rand()*20.0f+10.0f;
+ dim.x = 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 = (Rand()-0.5f)*1.5f;
+ speed.z = (Rand()-0.5f)*1.5f;
+ speed.y = -6.0f;
+ dim.x = 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+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, D3DVECTOR(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 += (Rand()-0.5f)*3.0f;
+ pos.z += (Rand()-0.5f)*3.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 6.0f+Rand()*6.0f;
+ dim.x = 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;
+ D3DVECTOR 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 = Length(oPos, cPos)-oRadius;
+
+ if ( dist < 10.0f ) return TRUE;
+ }
+
+ return FALSE;
+}
+
+// Create a cell.
+
+void CAutoEnergy::CreatePower()
+{
+ CObject* power;
+ D3DVECTOR 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;
+ D3DVECTOR 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;
+ FPOINT 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
new file mode 100644
index 0000000..dd920fb
--- /dev/null
+++ b/src/object/auto/autoenergy.h
@@ -0,0 +1,83 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoenergy.h
+
+#ifndef _AUTOENERGY_H_
+#define _AUTOENERGY_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+};
+
+
+#endif //_AUTOENERGY_H_
diff --git a/src/object/auto/autofactory.cpp b/src/object/auto/autofactory.cpp
new file mode 100644
index 0000000..7fab2fb
--- /dev/null
+++ b/src/object/auto/autofactory.cpp
@@ -0,0 +1,961 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "restext.h"
+#include "global.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "light.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "physics.h"
+#include "brain.h"
+#include "interface.h"
+#include "button.h"
+#include "window.h"
+#include "displaytext.h"
+#include "robotmain.h"
+#include "sound.h"
+#include "cmdtoken.h"
+#include "auto.h"
+#include "autofactory.h"
+
+
+
+
+// Object's constructor.
+
+CAutoFactory::CAutoFactory(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::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()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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;
+ D3DMATRIX* mat;
+ CPhysics* physics;
+ D3DVECTOR pos, speed;
+ FPOINT 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*(PI/2.0f)+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+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 += (Rand()-0.5f)*20.0f;
+ pos.z += (Rand()-0.5f)*20.0f;
+ pos.y += 1.0f;
+ speed.x = (Rand()-0.5f)*12.0f;
+ speed.z = (Rand()-0.5f)*12.0f;
+ speed.y = Rand()*12.0f;
+ dim.x = 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 = D3DVECTOR(-12.0f, 20.0f, -4.0f); // position of chimney
+ pos = Transform(*mat, pos);
+ pos.y += 2.0f;
+ pos.x += (Rand()-0.5f)*2.0f;
+ pos.z += (Rand()-0.5f)*2.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 6.0f+Rand()*6.0f;
+ dim.x = 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)+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)*(PI/2.0f)+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 += (Rand()-0.5f)*10.0f;
+ pos.z += (Rand()-0.5f)*10.0f;
+ pos.y += Rand()*10.0f;
+ speed = D3DVECTOR(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, PI/2.0f);
+ m_object->SetAngleZ(10+i, -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 += (Rand()-0.5f)*10.0f;
+ pos.z += (Rand()-0.5f)*10.0f;
+ pos.y += Rand()*10.0f;
+ speed = D3DVECTOR(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;
+ D3DVECTOR 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 = Length(oPos, m_fretPos);
+
+ if ( dist < 8.0f ) return pObj;
+ }
+
+ return 0;
+}
+
+// Search if a vehicle is too close.
+
+BOOL CAutoFactory::NearestVehicle()
+{
+ CObject* pObj;
+ D3DVECTOR 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 = Length(oPos, cPos)-oRadius;
+
+ if ( dist < 10.0f ) return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+// Creates a vehicle.
+
+BOOL CAutoFactory::CreateVehicle()
+{
+ CObject* vehicle;
+ D3DMATRIX* mat;
+ CPhysics* physics;
+ D3DVECTOR 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 = D3DVECTOR(2.0f, 0.0f, 0.0f);
+ }
+ else
+ {
+ pos = D3DVECTOR(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;
+ D3DVECTOR 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 = Length(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;
+ FPOINT 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
new file mode 100644
index 0000000..bcfc43e
--- /dev/null
+++ b/src/object/auto/autofactory.h
@@ -0,0 +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/.
+
+// autofactory.h
+
+#ifndef _AUTOFACTORY_H_
+#define _AUTOFACTORY_H_
+
+
+#include "auto.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+ D3DVECTOR m_fretPos;
+ int m_channelSound;
+};
+
+
+#endif //_AUTOFACTORY_H_
diff --git a/src/object/auto/autoflag.cpp b/src/object/auto/autoflag.cpp
new file mode 100644
index 0000000..5cd4bf2
--- /dev/null
+++ b/src/object/auto/autoflag.cpp
@@ -0,0 +1,178 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "auto.h"
+#include "autoflag.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)
+{
+ CAuto::CAuto(iMan, object);
+
+ Init();
+}
+
+// Object's destructor.
+
+CAutoFlag::~CAutoFlag()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// Destroys the object.
+
+void CAutoFlag::DeleteObject(BOOL bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoFlag::Init()
+{
+ D3DVECTOR wind;
+ float angle;
+
+ m_time = 0.0f;
+ m_param = 0;
+ m_progress = 0.0f;
+
+ wind = m_terrain->RetWind();
+ angle = RotateAngle(wind.x, -wind.z);
+ m_object->SetAngleY(0, angle); // directs the flag in the wind
+
+ m_strong = Length(wind);
+}
+
+
+// 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*PI*8.0f)*0.3f*(1.0f-m_progress);
+ m_object->SetAngleX(0, angle);
+ angle = sinf(m_progress*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
new file mode 100644
index 0000000..4ef0fe4
--- /dev/null
+++ b/src/object/auto/autoflag.h
@@ -0,0 +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/.
+
+// autoflag.h
+
+#ifndef _AUTOFLAG_H_
+#define _AUTOFLAG_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+};
+
+
+#endif //_AUTOFLAG_H_
diff --git a/src/object/auto/autohuston.cpp b/src/object/auto/autohuston.cpp
new file mode 100644
index 0000000..ad66702
--- /dev/null
+++ b/src/object/auto/autohuston.cpp
@@ -0,0 +1,315 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "interface.h"
+#include "button.h"
+#include "window.h"
+#include "auto.h"
+#include "autohuston.h"
+
+
+
+
+// Object's constructor.
+
+CAutoHuston::CAutoHuston(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ D3DVECTOR pos;
+ int i;
+
+ CAuto::CAuto(iMan, object);
+
+ 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+D3DVECTOR(0.0f+13.0f, 34.0f, 30.0f );
+ m_lens[1].pos = pos+D3DVECTOR(0.0f-13.0f, 34.0f, 30.0f );
+ m_lens[2].pos = pos+D3DVECTOR(0.0f , 34.0f, 30.0f+13.0f);
+ m_lens[3].pos = pos+D3DVECTOR(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+D3DVECTOR(-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+D3DVECTOR(-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+D3DVECTOR(-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+D3DVECTOR(-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+D3DVECTOR(-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+D3DVECTOR(-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+D3DVECTOR(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+D3DVECTOR(-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+D3DVECTOR(-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+D3DVECTOR(-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+D3DVECTOR(-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+D3DVECTOR(-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+D3DVECTOR(-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+D3DVECTOR(-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+D3DVECTOR(-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()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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)
+{
+ D3DVECTOR speed;
+ FPOINT 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 = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ for ( i=0 ; i<m_lensTotal ; i++ )
+ {
+ if ( m_lens[i].total != 0.0f &&
+ 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;
+ FPOINT 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
new file mode 100644
index 0000000..0611eb2
--- /dev/null
+++ b/src/object/auto/autohuston.h
@@ -0,0 +1,77 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * 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
+
+#ifndef _AUTOHUSTON_H_
+#define _AUTOHUSTON_H_
+
+
+#include "auto.h"
+#include "particule.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+typedef struct
+{
+ int parti;
+ ParticuleType type;
+ D3DVECTOR pos;
+ float dim;
+ float total;
+ float off;
+}
+HustonLens;
+
+
+#define 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;
+};
+
+
+#endif //_AUTOHUSTON_H_
diff --git a/src/object/auto/autoinfo.cpp b/src/object/auto/autoinfo.cpp
new file mode 100644
index 0000000..e9708e0
--- /dev/null
+++ b/src/object/auto/autoinfo.cpp
@@ -0,0 +1,537 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "light.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "interface.h"
+#include "button.h"
+#include "list.h"
+#include "window.h"
+#include "sound.h"
+#include "cmdtoken.h"
+#include "auto.h"
+#include "autoinfo.h"
+
+
+
+
+// Object's constructor.
+
+CAutoInfo::CAutoInfo(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::CAuto(iMan, object);
+
+ Init();
+}
+
+// Object's destructor.
+
+CAutoInfo::~CAutoInfo()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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)
+{
+ D3DVECTOR pos, speed;
+ FPOINT 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 = D3DVECTOR(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 = D3DVECTOR(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)
+{
+ D3DVECTOR pos, speed;
+ FPOINT 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+Rand()*0.3f;
+
+ angle = m_object->RetAngleY(1);
+ angle += Rand()*0.3f;
+ m_object->SetAngleY(1, angle);
+
+ m_object->SetAngleX(2, (Rand()-0.5f)*0.3f);
+ m_object->SetAngleX(4, (Rand()-0.5f)*0.3f);
+ m_object->SetAngleX(6, (Rand()-0.5f)*0.3f);
+
+ m_object->SetAngleZ(2, (Rand()-0.5f)*0.3f);
+ m_object->SetAngleZ(4, (Rand()-0.5f)*0.3f);
+ m_object->SetAngleZ(6, (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 = (Rand()-0.5f)*50.0f;
+ speed.z = (Rand()-0.5f)*50.0f;
+ speed.y = (Rand()-0.5f)*50.0f;
+ speed *= 0.5f+m_progress*0.5f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ duration = 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*PI);
+ m_object->SetAngleZ(4, m_progress*2.0f*PI);
+ m_object->SetAngleZ(6, m_progress*2.0f*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 += (Rand()-0.5f)*40.0f;
+ pos.y += (Rand()-0.5f)*40.0f;
+ pos.z += (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 = 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*PI);
+ m_object->SetAngleZ(4, m_progress*2.0f*PI);
+ m_object->SetAngleZ(6, m_progress*2.0f*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 = (Rand()-0.5f)*5.0f;
+ speed.z = (Rand()-0.5f)*5.0f;
+ speed.y = 5.0f+Rand()*5.0f;
+ dim.x = 5.0f+Rand()*5.0f;
+ dim.y = dim.x;
+ duration = 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, (Rand()-0.5f)*0.2f);
+ m_object->SetAngleZ(4, (Rand()-0.5f)*0.2f);
+ m_object->SetAngleZ(6, (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+PI*0.0f/3.0f)*0.3f);
+ m_object->SetAngleX(5, sinf(m_time*6.0f+PI*2.0f/3.0f)*0.3f);
+ m_object->SetAngleX(7, sinf(m_time*6.0f+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;
+ FPOINT 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+Rand()*10.0f);
+ for ( j=0 ; j<max ; j++ )
+ {
+ do
+ {
+ text[j] = ' '+(int)(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
new file mode 100644
index 0000000..28fc9ab
--- /dev/null
+++ b/src/object/auto/autoinfo.h
@@ -0,0 +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/.
+
+// autoinfo.h
+
+#ifndef _AUTOINFO_H_
+#define _AUTOINFO_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+ D3DVECTOR m_goal;
+ BOOL m_bLastVirus;
+};
+
+
+#endif //_AUTOINFO_H_
diff --git a/src/object/auto/autojostle.cpp b/src/object/auto/autojostle.cpp
new file mode 100644
index 0000000..1bcd11e
--- /dev/null
+++ b/src/object/auto/autojostle.cpp
@@ -0,0 +1,167 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "light.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "interface.h"
+#include "button.h"
+#include "list.h"
+#include "window.h"
+#include "sound.h"
+#include "auto.h"
+#include "autojostle.h"
+
+
+
+
+// Object's constructor.
+
+CAutoJostle::CAutoJostle(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::CAuto(iMan, object);
+
+ Init();
+}
+
+// Object's destructor.
+
+CAutoJostle::~CAutoJostle()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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)
+{
+ D3DVECTOR 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*PI*4.0f);
+ dir.z = cosf(m_progress*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, D3DVECTOR(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
new file mode 100644
index 0000000..18027a0
--- /dev/null
+++ b/src/object/auto/autojostle.h
@@ -0,0 +1,60 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * 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
+
+#ifndef _AUTOJOSTLE_H_
+#define _AUTOJOSTLE_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+};
+
+
+#endif //_AUTOJOSTLE_H_
diff --git a/src/object/auto/autokid.cpp b/src/object/auto/autokid.cpp
new file mode 100644
index 0000000..98c0f45
--- /dev/null
+++ b/src/object/auto/autokid.cpp
@@ -0,0 +1,222 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "terrain.h"
+#include "water.h"
+#include "camera.h"
+#include "object.h"
+#include "sound.h"
+#include "cmdtoken.h"
+#include "auto.h"
+#include "autokid.h"
+
+
+
+
+// Object's constructor.
+
+CAutoKid::CAutoKid(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::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;
+ }
+
+ this->CAuto::~CAuto();
+}
+
+
+// Destroys the object.
+
+void CAutoKid::DeleteObject(BOOL bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoKid::Init()
+{
+ D3DVECTOR 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+(Mod(pos.x/10.0f-0.5f, 1.0f)*0.2f));
+ m_progress = Mod(pos.x/10.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_TEEN37 ) // boat?
+ {
+ pos = m_object->RetPosition(0);
+ m_speed = 1.0f/(1.0f+(Mod(pos.x/10.0f-0.5f, 1.0f)*0.2f))*2.5f;
+ m_progress = 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)
+{
+ D3DVECTOR vib, pos, speed;
+ FPOINT 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 += (Rand()-0.5f)*50.0f;
+ pos.z += (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 += (Rand()-0.5f)*20.0f;
+ pos.z += (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
new file mode 100644
index 0000000..dc5305b
--- /dev/null
+++ b/src/object/auto/autokid.h
@@ -0,0 +1,59 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * 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
+
+#ifndef _AUTOKID_H_
+#define _AUTOKID_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+};
+
+
+#endif //_AUTOKID_H_
diff --git a/src/object/auto/autolabo.cpp b/src/object/auto/autolabo.cpp
new file mode 100644
index 0000000..ce6214c
--- /dev/null
+++ b/src/object/auto/autolabo.cpp
@@ -0,0 +1,629 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "global.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "light.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "interface.h"
+#include "button.h"
+#include "window.h"
+#include "displaytext.h"
+#include "sound.h"
+#include "robotmain.h"
+#include "cmdtoken.h"
+#include "auto.h"
+#include "autolabo.h"
+
+
+
+#define LABO_DELAY 20.0f // duration of the analysis
+
+
+
+
+// Object's constructor.
+
+CAutoLabo::CAutoLabo(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ int i;
+
+ CAuto::CAuto(iMan, object);
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ m_partiRank[i] = -1;
+ }
+ m_partiSphere = -1;
+
+ m_soundChannel = -1;
+ Init();
+}
+
+// Object's destructor.
+
+CAutoLabo::~CAutoLabo()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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;
+ D3DVECTOR pos, goal, speed;
+ FPOINT 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+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*PI/180.0f);
+ m_object->SetAngleZ(4, angle*PI/180.0f);
+ m_object->SetAngleZ(5, angle*PI/180.0f);
+ }
+ else
+ {
+ m_object->SetAngleZ(3, 45.0f*PI/180.0f);
+ m_object->SetAngleZ(4, 45.0f*PI/180.0f);
+ m_object->SetAngleZ(5, 45.0f*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, D3DVECTOR(-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)*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,
+ FPOINT(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 = D3DVECTOR(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 = 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 += 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 += (Rand()-0.5f)*2.0f;
+ pos.z += (Rand()-0.5f)*2.0f;
+ speed.y = Rand()*5.0f+5.0f;
+ speed.x = (Rand()-0.5f)*10.0f;
+ speed.z = (Rand()-0.5f)*10.0f;
+ dim.x = 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*PI/2.0f;
+ m_object->SetAngleZ(1, angle);
+ }
+ else
+ {
+ m_object->SetAngleZ(1, 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, D3DVECTOR(-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*PI/180.0f);
+ m_object->SetAngleZ(4, angle*PI/180.0f);
+ m_object->SetAngleZ(5, angle*PI/180.0f);
+ }
+ else
+ {
+ m_object->SetAngleZ(3, 80.0f*PI/180.0f);
+ m_object->SetAngleZ(4, 80.0f*PI/180.0f);
+ m_object->SetAngleZ(5, 80.0f*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;
+ FPOINT 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)
+{
+ D3DVECTOR 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)
+{
+ D3DVECTOR 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
new file mode 100644
index 0000000..997bc55
--- /dev/null
+++ b/src/object/auto/autolabo.h
@@ -0,0 +1,87 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * 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
+
+#ifndef _AUTOLABO_H_
+#define _AUTOLABO_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+};
+
+
+#endif //_AUTOLABO_H_
diff --git a/src/object/auto/automush.cpp b/src/object/auto/automush.cpp
new file mode 100644
index 0000000..d1107ed
--- /dev/null
+++ b/src/object/auto/automush.cpp
@@ -0,0 +1,362 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "cmdtoken.h"
+#include "sound.h"
+#include "auto.h"
+#include "automush.h"
+
+
+
+
+// Object's constructor.
+
+CAutoMush::CAutoMush(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::CAuto(iMan, object);
+
+ Init();
+}
+
+// Object's destructor.
+
+CAutoMush::~CAutoMush()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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)
+{
+ D3DVECTOR pos, speed, dir;
+ FPOINT 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+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 = (Rand()-0.5f)*200.0f;
+ speed.z = (Rand()-0.5f)*200.0f;
+ speed.y = -(20.0f+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 = (Rand()-0.5f)*4.0f;
+ speed.z = (Rand()-0.5f)*4.0f;
+ speed.y = -(0.5f+Rand()*0.5f);
+ dim.x = 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+Rand()*2.0f);
+ }
+ }
+
+ if ( factor != 0.0f || size != 1.0f )
+ {
+ dir.x = sinf(m_time*PI*4.0f);
+ dir.z = cosf(m_time*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, D3DVECTOR(1.0f, 1.0f, 1.0f));
+ }
+
+ return TRUE;
+}
+
+
+// Seeking a nearby target.
+
+BOOL CAutoMush::SearchTarget()
+{
+ CObject* pObj;
+ D3DVECTOR 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 = Length(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)
+{
+ D3DVECTOR 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)
+{
+ D3DVECTOR 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
new file mode 100644
index 0000000..81314ee
--- /dev/null
+++ b/src/object/auto/automush.h
@@ -0,0 +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/.
+
+// automush.h
+
+#ifndef _AUTOMUSH_H_
+#define _AUTOMUSH_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+};
+
+
+#endif //_AUTOMUSH_H_
diff --git a/src/object/auto/autonest.cpp b/src/object/auto/autonest.cpp
new file mode 100644
index 0000000..a86e7b8
--- /dev/null
+++ b/src/object/auto/autonest.cpp
@@ -0,0 +1,291 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "cmdtoken.h"
+#include "auto.h"
+#include "autonest.h"
+
+
+
+
+// Object's constructor.
+
+CAutoNest::CAutoNest(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::CAuto(iMan, object);
+
+ Init();
+}
+
+// Object's destructor.
+
+CAutoNest::~CAutoNest()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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()
+{
+ D3DVECTOR 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(D3DVECTOR pos)
+{
+ CObject* pObj;
+ D3DVECTOR 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 = Length(sPos, pos);
+ distance -= sRadius;
+ if ( distance < 2.0f ) return FALSE; // location occupied
+ }
+ }
+
+ return TRUE; // free location
+}
+
+// Create a transportable object.
+
+void CAutoNest::CreateFret(D3DVECTOR 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;
+ D3DVECTOR 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)
+{
+ D3DVECTOR 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)
+{
+ D3DVECTOR 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
new file mode 100644
index 0000000..0c6febc
--- /dev/null
+++ b/src/object/auto/autonest.h
@@ -0,0 +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/.
+
+// autonest.h
+
+#ifndef _AUTONEST_H_
+#define _AUTONEST_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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(D3DVECTOR pos);
+ void CreateFret(D3DVECTOR pos, float angle, ObjectType type);
+ CObject* SearchFret();
+
+protected:
+ AutoNestPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_lastParticule;
+ D3DVECTOR m_fretPos;
+};
+
+
+#endif //_AUTONEST_H_
diff --git a/src/object/auto/autonuclear.cpp b/src/object/auto/autonuclear.cpp
new file mode 100644
index 0000000..824bfca
--- /dev/null
+++ b/src/object/auto/autonuclear.cpp
@@ -0,0 +1,504 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "global.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "light.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "interface.h"
+#include "button.h"
+#include "window.h"
+#include "sound.h"
+#include "displaytext.h"
+#include "cmdtoken.h"
+#include "auto.h"
+#include "autonuclear.h"
+
+
+
+#define NUCLEAR_DELAY 30.0f // duration of the generation
+
+
+
+
+// Object's constructor.
+
+CAutoNuclear::CAutoNuclear(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::CAuto(iMan, object);
+
+ m_channelSound = -1;
+ Init();
+}
+
+// Object's destructor.
+
+CAutoNuclear::~CAutoNuclear()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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()
+{
+ D3DMATRIX* mat;
+
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+
+ mat = m_object->RetWorldMatrix(0);
+ m_pos = Transform(*mat, D3DVECTOR(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;
+ D3DMATRIX* mat;
+ D3DVECTOR pos, goal, speed;
+ FPOINT 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+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*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 = (Rand()-0.5f)*8.0f;
+ pos = Transform(*mat, pos);
+ speed.y = 0.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ dim.x = 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 += (Rand()-0.5f)*6.0f;
+ pos.z += (Rand()-0.5f)*6.0f;
+ speed.y = Rand()*15.0f+15.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ dim.x = Rand()*8.0f+8.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH);
+
+ pos = m_pos;
+ speed.x = (Rand()-0.5f)*20.0f;
+ speed.y = (Rand()-0.5f)*20.0f;
+ speed.z = (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 += (Rand()-0.5f)*3.0f;
+ pos.y += (Rand()-0.5f)*3.0f;
+ pos.z += (Rand()-0.5f)*3.0f;
+ speed.y = 0.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ dim.x = Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 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*PI/180.0f);
+ m_object->SetAngleZ(1, angle);
+ }
+ else
+ {
+ m_object->SetAngleZ(1, 135.0f*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;
+ FPOINT 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;
+ D3DVECTOR 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 = Length(oPos, m_pos)-oRadius;
+
+ if ( dist < 10.0f ) return TRUE;
+ }
+
+ return FALSE;
+}
+
+// Creates an object stack.
+
+void CAutoNuclear::CreatePower()
+{
+ CObject* power;
+ D3DVECTOR 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, D3DVECTOR(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
new file mode 100644
index 0000000..e62282a
--- /dev/null
+++ b/src/object/auto/autonuclear.h
@@ -0,0 +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/.
+
+// autonuclear.h
+
+#ifndef _AUTONUCLEAR_H_
+#define _AUTONUCLEAR_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+ D3DVECTOR m_pos;
+ int m_channelSound;
+};
+
+
+#endif //_AUTONUCLEAR_H_
diff --git a/src/object/auto/autopara.cpp b/src/object/auto/autopara.cpp
new file mode 100644
index 0000000..cb42e6d
--- /dev/null
+++ b/src/object/auto/autopara.cpp
@@ -0,0 +1,347 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "global.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "light.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "interface.h"
+#include "button.h"
+#include "window.h"
+#include "sound.h"
+#include "displaytext.h"
+#include "cmdtoken.h"
+#include "auto.h"
+#include "autopara.h"
+
+
+
+
+// Object's constructor.
+
+CAutoPara::CAutoPara(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::CAuto(iMan, object);
+
+ m_channelSound = -1;
+ Init();
+}
+
+// Object's destructor.
+
+CAutoPara::~CAutoPara()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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()
+{
+ D3DMATRIX* mat;
+
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+
+ mat = m_object->RetWorldMatrix(0);
+ m_pos = Transform(*mat, D3DVECTOR(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)
+{
+ D3DVECTOR pos, speed;
+ FPOINT 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+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 += (Rand()-0.5f)*m_progress*40.0f;
+ pos.z += (Rand()-0.5f)*m_progress*40.0f;
+ pos.y += 50.0f-m_progress*50.0f;
+ speed.x = (Rand()-0.5f)*20.0f;
+ speed.z = (Rand()-0.5f)*20.0f;
+ speed.y = 5.0f+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 = (Rand()-0.5f)*10.0f;
+ speed.z = (Rand()-0.5f)*10.0f;
+ speed.y = -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;
+ FPOINT 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;
+ D3DVECTOR 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 = Length(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
new file mode 100644
index 0000000..9a7c0c4
--- /dev/null
+++ b/src/object/auto/autopara.h
@@ -0,0 +1,77 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * 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
+
+#ifndef _AUTOPARA_H_
+#define _AUTOPARA_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+ D3DVECTOR m_pos;
+ int m_channelSound;
+};
+
+
+#endif //_AUTOPARA_H_
diff --git a/src/object/auto/autoportico.cpp b/src/object/auto/autoportico.cpp
new file mode 100644
index 0000000..c02348d
--- /dev/null
+++ b/src/object/auto/autoportico.cpp
@@ -0,0 +1,446 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "interface.h"
+#include "button.h"
+#include "window.h"
+#include "displaytext.h"
+#include "robotmain.h"
+#include "sound.h"
+#include "auto.h"
+#include "autoportico.h"
+
+
+
+#define PARAM_DEPOSE 2 // run=2 -> deposits the spaceship
+
+#define PORTICO_POSa 75.0f
+#define PORTICO_POSb 65.0f
+#define PORTICO_ANGLE1a ( 25.0f*PI/180.0f)
+#define PORTICO_ANGLE1b ( 70.0f*PI/180.0f)
+#define PORTICO_ANGLE2a (-37.5f*PI/180.0f)
+#define PORTICO_ANGLE2b (-62.5f*PI/180.0f)
+#define PORTICO_ANGLE3a (-77.5f*PI/180.0f)
+#define PORTICO_ANGLE3b (-30.0f*PI/180.0f)
+
+#define PORTICO_TIME_MOVE 16.0f
+#define PORTICO_TIME_DOWN 4.0f
+#define 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)
+{
+ CAuto::CAuto(iMan, object);
+
+ Init();
+ m_phase = APOP_WAIT;
+ m_soundChannel = -1;
+}
+
+// Object's destructor.
+
+CAutoPortico::~CAutoPortico()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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)
+{
+ D3DVECTOR 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, D3DVECTOR(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;
+ D3DVECTOR 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+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, D3DVECTOR(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
new file mode 100644
index 0000000..7ed2e70
--- /dev/null
+++ b/src/object/auto/autoportico.h
@@ -0,0 +1,81 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoportico.h
+
+#ifndef _AUTOPORTICO_H_
+#define _AUTOPORTICO_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+ D3DVECTOR m_finalPos;
+ D3DVECTOR m_startPos;
+ float m_posTrack;
+ int m_param;
+ int m_soundChannel;
+};
+
+
+#endif //_AUTOPORTICO_H_
diff --git a/src/object/auto/autoradar.cpp b/src/object/auto/autoradar.cpp
new file mode 100644
index 0000000..2353149
--- /dev/null
+++ b/src/object/auto/autoradar.cpp
@@ -0,0 +1,326 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "interface.h"
+#include "button.h"
+#include "window.h"
+#include "gauge.h"
+#include "sound.h"
+#include "auto.h"
+#include "autoradar.h"
+
+
+
+
+// Object's constructor.
+
+CAutoRadar::CAutoRadar(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::CAuto(iMan, object);
+
+ Init();
+ m_phase = ARAP_WAIT;
+ m_totalDetect = 0;
+}
+
+// Object's destructor.
+
+CAutoRadar::~CAutoRadar()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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)
+{
+ D3DVECTOR 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+Rand()*0.3f;
+
+ angle = m_object->RetAngleY(1);
+ angle += (Rand()-0.2f)*0.5f;
+ m_object->SetAngleY(1, angle);
+
+ angle = m_object->RetAngleY(2);
+ angle += (Rand()-0.8f)*1.0f;
+ m_object->SetAngleY(2, angle);
+
+ m_object->SetAngleX(3, (Rand()-0.5f)*0.3f);
+
+ m_totalDetect = (int)(Rand()*10.0f);
+ UpdateInterface();
+ }
+ return TRUE;
+ }
+
+ if ( m_phase == ARAP_SEARCH )
+ {
+ if ( m_progress < 1.0f )
+ {
+ speed = 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-NormAngle(m_start)+PI*2.0f;
+ m_angle += RotateAngle(pos.x-ePos.x, ePos.z-pos.z);
+ m_angle += PI-m_object->RetAngleY(0);
+
+ m_phase = ARAP_SHOW;
+ m_progress = 0.0f;
+ m_speed = 1.0f/(Abs(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 = 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;
+ FPOINT 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(D3DVECTOR &pos)
+{
+ CObject* pObj;
+ CObject* pBest = 0;
+ D3DVECTOR 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 = Length(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
new file mode 100644
index 0000000..298d011
--- /dev/null
+++ b/src/object/auto/autoradar.h
@@ -0,0 +1,76 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoradar.h
+
+#ifndef _AUTORADAR_H_
+#define _AUTORADAR_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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(D3DVECTOR &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;
+};
+
+
+#endif //_AUTORADAR_H_
diff --git a/src/object/auto/autorepair.cpp b/src/object/auto/autorepair.cpp
new file mode 100644
index 0000000..6994842
--- /dev/null
+++ b/src/object/auto/autorepair.cpp
@@ -0,0 +1,362 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "light.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "physics.h"
+#include "sound.h"
+#include "interface.h"
+#include "button.h"
+#include "window.h"
+#include "robotmain.h"
+#include "cmdtoken.h"
+#include "auto.h"
+#include "autorepair.h"
+
+
+
+
+// Object's constructor.
+
+CAutoRepair::CAutoRepair(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::CAuto(iMan, object);
+
+ Init();
+ m_phase = ARP_WAIT; // paused until the first Init ()
+}
+
+// Object's destructor.
+
+CAutoRepair::~CAutoRepair()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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;
+ D3DVECTOR pos, speed;
+ FPOINT 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+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*(PI/2.0f)+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 += (Rand()-0.5f)*5.0f;
+ pos.z += (Rand()-0.5f)*5.0f;
+ pos.y += 1.0f;
+ speed.x = (Rand()-0.5f)*12.0f;
+ speed.z = (Rand()-0.5f)*12.0f;
+ speed.y = Rand()*15.0f;
+ dim.x = 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)*(PI/2.0f)+PI/2.0f;
+ m_object->SetAngleZ(1, angle);
+ }
+ else
+ {
+ m_object->SetAngleZ(1, 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;
+ FPOINT 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;
+ D3DVECTOR 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 = Length(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
new file mode 100644
index 0000000..1383fc7
--- /dev/null
+++ b/src/object/auto/autorepair.h
@@ -0,0 +1,76 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autorepair.h
+
+#ifndef _AUTOREPAIR_H_
+#define _AUTOREPAIR_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+};
+
+
+#endif //_AUTOREPAIR_H_
diff --git a/src/object/auto/autoresearch.cpp b/src/object/auto/autoresearch.cpp
new file mode 100644
index 0000000..b15a9b8
--- /dev/null
+++ b/src/object/auto/autoresearch.cpp
@@ -0,0 +1,627 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "global.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "interface.h"
+#include "button.h"
+#include "gauge.h"
+#include "window.h"
+#include "displaytext.h"
+#include "sound.h"
+#include "robotmain.h"
+#include "cmdtoken.h"
+#include "auto.h"
+#include "autoresearch.h"
+
+
+
+#define SEARCH_TIME 30.0f // duration of a research
+
+
+
+// Object's constructor.
+
+CAutoResearch::CAutoResearch(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ int i;
+
+ CAuto::CAuto(iMan, object);
+
+ for ( i=0 ; i<6 ; i++ )
+ {
+ m_partiStop[i] = -1;
+ }
+ m_channelSound = -1;
+
+ Init();
+}
+
+// Object's destructor.
+
+CAutoResearch::~CAutoResearch()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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;
+ D3DVECTOR pos, speed;
+ Error message;
+ FPOINT 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+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)*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 += (Rand()-0.5f)*6.0f;
+ pos.z += (Rand()-0.5f)*6.0f;
+ pos.y += 11.0f;
+ speed.x = (Rand()-0.5f)*2.0f;
+ speed.z = (Rand()-0.5f)*2.0f;
+ speed.y = Rand()*20.0f;
+ dim.x = 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;
+ FPOINT 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)
+{
+ D3DMATRIX* mat;
+ D3DVECTOR pos, speed;
+ FPOINT 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 = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ dim.x = 2.0f;
+ dim.y = dim.x;
+
+ for ( i=0 ; i<6 ; i++ )
+ {
+ if ( 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 = 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
new file mode 100644
index 0000000..f773084
--- /dev/null
+++ b/src/object/auto/autoresearch.h
@@ -0,0 +1,82 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * 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
+
+#ifndef _AUTORESEARCH_H_
+#define _AUTORESEARCH_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+};
+
+
+#endif //_AUTORESEARCH_H_
diff --git a/src/object/auto/autoroot.cpp b/src/object/auto/autoroot.cpp
new file mode 100644
index 0000000..5f1afad
--- /dev/null
+++ b/src/object/auto/autoroot.cpp
@@ -0,0 +1,135 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "auto.h"
+#include "autoroot.h"
+
+
+
+
+// Object's constructor.
+
+CAutoRoot::CAutoRoot(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::CAuto(iMan, object);
+
+ Init();
+}
+
+// Object's destructor.
+
+CAutoRoot::~CAutoRoot()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// Destroys the object.
+
+void CAutoRoot::DeleteObject(BOOL bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoRoot::Init()
+{
+ D3DMATRIX* mat;
+ D3DVECTOR pos, speed;
+ FPOINT dim;
+
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = D3DVECTOR(-5.0f, 28.0f, -4.0f); // peak position
+ pos = Transform(*mat, pos);
+ m_center = pos;
+
+ speed = D3DVECTOR(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)
+{
+ D3DVECTOR pos, speed;
+ FPOINT 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 += (Rand()-0.5f)*8.0f;
+ pos.z += (Rand()-0.5f)*8.0f;
+ pos.y += 0.0f;
+ speed.x = (Rand()-0.5f)*12.0f;
+ speed.z = (Rand()-0.5f)*12.0f;
+ speed.y = Rand()*12.0f;
+ dim.x = 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
new file mode 100644
index 0000000..85bdb69
--- /dev/null
+++ b/src/object/auto/autoroot.h
@@ -0,0 +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/.
+
+// autoroot.h
+
+#ifndef _AUTOROOT_H_
+#define _AUTOROOT_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+ D3DVECTOR m_center;
+};
+
+
+#endif //_AUTOROOT_H_
diff --git a/src/object/auto/autosafe.cpp b/src/object/auto/autosafe.cpp
new file mode 100644
index 0000000..bdc6d32
--- /dev/null
+++ b/src/object/auto/autosafe.cpp
@@ -0,0 +1,636 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "global.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "light.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "interface.h"
+#include "button.h"
+#include "robotmain.h"
+#include "window.h"
+#include "sound.h"
+#include "displaytext.h"
+#include "cmdtoken.h"
+#include "auto.h"
+#include "autosafe.h"
+
+
+
+#define OPEN_DELAY 8.0f // duration of opening
+
+
+
+
+// Object's constructor.
+
+CAutoSafe::CAutoSafe(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ int i;
+
+ CAuto::CAuto(iMan, object);
+
+ 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()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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;
+ D3DVECTOR pos, speed;
+ FPOINT 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+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*PI/180.0f;
+ if ( count == 1 ) m_finalAngle = 5.0f*PI/180.0f;
+ if ( count == 2 ) m_finalAngle = 10.0f*PI/180.0f;
+ if ( count == 3 ) m_finalAngle = 15.0f*PI/180.0f;
+ if ( count == 4 ) m_finalAngle = 120.0f*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 += (Rand()-0.5f)*10.0f;
+ pos.z += (Rand()-0.5f)*10.0f;
+ speed.x = (Rand()-0.5f)*4.0f;
+ speed.z = (Rand()-0.5f)*4.0f;
+ speed.y = Rand()*15.0f;
+ dim.x = 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 += (Rand()-0.5f)*10.0f;
+ pos.z += (Rand()-0.5f)*10.0f;
+ speed.x = (Rand()-0.5f)*4.0f;
+ speed.z = (Rand()-0.5f)*4.0f;
+ speed.y = Rand()*10.0f;
+ dim.x = 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 = (Rand()-0.5f)*2.0f;
+ speed.z = (Rand()-0.5f)*2.0f;
+ speed.y = 1.0f+Rand()*1.0f;
+ dim.x = 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(D3DVECTOR(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*PI/180.0f)*event.rTime/OPEN_DELAY;
+ if ( m_actualAngle > m_finalAngle ) m_actualAngle = m_finalAngle;
+ }
+ else
+ {
+ m_actualAngle -= (105.0f*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 = D3DVECTOR(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] || 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;
+ FPOINT 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;
+ D3DVECTOR cPos, oPos;
+ FPOINT 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 = Length2d(oPos, cPos);
+ if ( dist > 20.0f ) continue;
+
+ if ( oType == OBJECT_KEYa )
+ {
+ limit = PI*1.0f;
+ oAngle = PI*0.0f;
+ index = 0;
+ }
+ if ( oType == OBJECT_KEYb )
+ {
+ limit = PI*0.0f;
+ oAngle = PI*1.0f;
+ index = 1;
+ }
+ if ( oType == OBJECT_KEYc )
+ {
+ limit = PI*1.5f;
+ oAngle = PI*0.5f;
+ index = 2;
+ }
+ if ( oType == OBJECT_KEYd )
+ {
+ limit = PI*0.5f;
+ oAngle = PI*0.0f;
+ index = 3;
+ }
+
+ angle = RotateAngle(oPos.x-cPos.x, oPos.z-cPos.z)+cAngle;
+ if ( !TestAngle(angle, limit-8.0f*PI/180.0f, limit+8.0f*PI/180.0f) ) continue;
+
+ // Key changes the shape of the base.
+ rot = RotatePoint(FPOINT(cPos.x, cPos.z), limit-cAngle, FPOINT(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;
+ D3DVECTOR 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 = Length2d(oPos, cPos);
+ if ( dist > 20.0f ) continue;
+
+ pObj->SetLock(TRUE);
+ }
+}
+
+// Sent down all the keys.
+
+void CAutoSafe::DownKeys(float progress)
+{
+ CObject* pObj;
+ D3DVECTOR 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 = Length2d(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;
+ D3DVECTOR 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 = Length2d(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;
+ D3DVECTOR 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 = Length2d(oPos, cPos);
+ if ( dist <= 4.0f ) return pObj;
+ }
+ return 0;
+}
+
+
+
diff --git a/src/object/auto/autosafe.h b/src/object/auto/autosafe.h
new file mode 100644
index 0000000..b60472d
--- /dev/null
+++ b/src/object/auto/autosafe.h
@@ -0,0 +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/.
+
+// autosafe.h
+
+#ifndef _AUTOSAFE_H_
+#define _AUTOSAFE_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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];
+ D3DVECTOR m_keyPos[4];
+ int m_keyParti[4];
+};
+
+
+#endif //_AUTOSAFE_H_
diff --git a/src/object/auto/autostation.cpp b/src/object/auto/autostation.cpp
new file mode 100644
index 0000000..1e23e1d
--- /dev/null
+++ b/src/object/auto/autostation.cpp
@@ -0,0 +1,387 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "light.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "interface.h"
+#include "button.h"
+#include "gauge.h"
+#include "window.h"
+#include "sound.h"
+#include "auto.h"
+#include "autostation.h"
+
+
+
+
+// Object's constructor.
+
+CAutoStation::CAutoStation(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ CAuto::CAuto(iMan, object);
+
+ Init();
+}
+
+// Object's destructor.
+
+CAutoStation::~CAutoStation()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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)
+{
+ D3DMATRIX* mat;
+ D3DVECTOR pos, ppos, speed;
+ FPOINT 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+Rand()*0.3f;
+
+ m_object->SetEnergy(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 = D3DVECTOR(-15.0f, 7.0f, 0.0f); // battery position
+ pos = Transform(*mat, pos);
+ speed.x = (Rand()-0.5f)*20.0f;
+ speed.y = (Rand()-0.5f)*20.0f;
+ speed.z = (Rand()-0.5f)*20.0f;
+ ppos.x = pos.x;
+ ppos.y = pos.y+(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 += (Rand()-0.5f)*3.0f;
+ ppos.z += (Rand()-0.5f)*3.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 2.5f+Rand()*6.0f;
+ dim.x = 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 += (Rand()-0.5f)*3.0f;
+ ppos.z += (Rand()-0.5f)*3.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 2.5f+Rand()*5.0f;
+ dim.x = 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;
+ D3DVECTOR 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 = Length(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;
+ FPOINT 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
new file mode 100644
index 0000000..d783cc9
--- /dev/null
+++ b/src/object/auto/autostation.h
@@ -0,0 +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/.
+
+// autostation.h
+
+#ifndef _AUTOSTATION_H_
+#define _AUTOSTATION_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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;
+ D3DVECTOR m_fretPos;
+ BOOL m_bLastVirus;
+ float m_energyVirus;
+};
+
+
+#endif //_AUTOSTATION_H_
diff --git a/src/object/auto/autotower.cpp b/src/object/auto/autotower.cpp
new file mode 100644
index 0000000..7dcdb05
--- /dev/null
+++ b/src/object/auto/autotower.cpp
@@ -0,0 +1,561 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "d3dmath.h"
+#include "global.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "math3d.h"
+#include "particule.h"
+#include "terrain.h"
+#include "camera.h"
+#include "object.h"
+#include "physics.h"
+#include "interface.h"
+#include "button.h"
+#include "gauge.h"
+#include "window.h"
+#include "sound.h"
+#include "displaytext.h"
+#include "cmdtoken.h"
+#include "auto.h"
+#include "autotower.h"
+
+
+
+#define TOWER_SCOPE 200.0f // range of beam
+#define ENERGY_FIRE 0.125f // energy consumed by fire
+
+
+// Object's constructor.
+
+CAutoTower::CAutoTower(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ int i;
+
+ CAuto::CAuto(iMan, object);
+
+ 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()
+{
+ this->CAuto::~CAuto();
+}
+
+
+// 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;
+ D3DVECTOR 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+Rand()*0.3f;
+
+ angle = m_object->RetAngleY(1);
+ angle += Rand()*0.5f;
+ m_object->SetAngleY(1, angle);
+
+ m_object->SetAngleZ(2, 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 = RotateAngle(m_targetPos.x-pos.x, pos.z-m_targetPos.z); // CW !
+ m_angleYfinal += PI*2.0f;
+ m_angleYfinal -= m_object->RetAngleY(0);
+ m_angleYactual = NormAngle(m_object->RetAngleY(1));
+
+ m_angleZfinal = -PI/2.0f;
+ m_angleZfinal -= RotateAngle(Length2d(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,
+ FPOINT(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(D3DVECTOR &impact)
+{
+ CObject* pObj;
+ CObject* pBest = 0;
+ CPhysics* physics;
+ D3DVECTOR 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 = Abs(physics->RetLinMotionX(MO_REASPEED));
+ if ( speed > 20.0f ) continue; // moving too fast?
+ }
+ }
+
+ if ( !pObj->GetCrashSphere(0, oPos, radius) ) continue;
+ distance = Length(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)
+{
+ D3DMATRIX* mat;
+ D3DVECTOR pos, speed;
+ FPOINT 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 = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ dim.x = 2.0f;
+ dim.y = dim.x;
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ if ( 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;
+ FPOINT 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
new file mode 100644
index 0000000..fa7e6cb
--- /dev/null
+++ b/src/object/auto/autotower.h
@@ -0,0 +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/.
+
+// autotower.h
+
+#ifndef _AUTOTOWER_H_
+#define _AUTOTOWER_H_
+
+
+#include "auto.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CObject;
+
+
+
+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(D3DVECTOR &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;
+ D3DVECTOR m_targetPos;
+ float m_angleYactual;
+ float m_angleZactual;
+ float m_angleYfinal;
+ float m_angleZfinal;
+ int m_partiStop[4];
+};
+
+
+#endif //_AUTOTOWER_H_