summaryrefslogtreecommitdiffstats
path: root/src/object/motion
diff options
context:
space:
mode:
Diffstat (limited to 'src/object/motion')
-rw-r--r--src/object/motion/motion.cpp257
-rw-r--r--src/object/motion/motion.h94
-rw-r--r--src/object/motion/motionant.cpp901
-rw-r--r--src/object/motion/motionant.h80
-rw-r--r--src/object/motion/motionbee.cpp663
-rw-r--r--src/object/motion/motionbee.h73
-rw-r--r--src/object/motion/motionhuman.cpp1799
-rw-r--r--src/object/motion/motionhuman.h102
-rw-r--r--src/object/motion/motionmother.cpp543
-rw-r--r--src/object/motion/motionmother.h67
-rw-r--r--src/object/motion/motionspider.cpp789
-rw-r--r--src/object/motion/motionspider.h78
-rw-r--r--src/object/motion/motiontoto.cpp886
-rw-r--r--src/object/motion/motiontoto.h81
-rw-r--r--src/object/motion/motionvehicle.cpp2091
-rw-r--r--src/object/motion/motionvehicle.h82
-rw-r--r--src/object/motion/motionworm.cpp380
-rw-r--r--src/object/motion/motionworm.h75
18 files changed, 9041 insertions, 0 deletions
diff --git a/src/object/motion/motion.cpp b/src/object/motion/motion.cpp
new file mode 100644
index 0000000..642108b
--- /dev/null
+++ b/src/object/motion/motion.cpp
@@ -0,0 +1,257 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motion.cpp
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "math3d.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "light.h"
+#include "particule.h"
+#include "terrain.h"
+#include "water.h"
+#include "object.h"
+#include "physics.h"
+#include "brain.h"
+#include "camera.h"
+#include "robotmain.h"
+#include "sound.h"
+#include "cmdtoken.h"
+#include "motion.h"
+
+
+
+
+// Object's constructor.
+
+CMotion::CMotion(CInstanceManager* iMan, CObject* object)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_MOTION, this, 100);
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+
+ m_object = object;
+ m_physics = 0;
+ m_brain = 0;
+
+ m_actionType = -1;
+ m_actionTime = 0.0f;
+ m_progress = 0.0f;
+
+ m_linVibration = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ m_cirVibration = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ m_inclinaison = D3DVECTOR(0.0f, 0.0f, 0.0f);
+}
+
+// Object's destructor.
+
+CMotion::~CMotion()
+{
+ m_iMan->DeleteInstance(CLASS_MOTION, this);
+}
+
+// Deletes the object.
+
+void CMotion::DeleteObject(BOOL bAll)
+{
+}
+
+
+void CMotion::SetPhysics(CPhysics* physics)
+{
+ m_physics = physics;
+}
+
+void CMotion::SetBrain(CBrain* brain)
+{
+ m_brain = brain;
+}
+
+
+// Creates.
+
+BOOL CMotion::Create(D3DVECTOR pos, float angle, ObjectType type, float power)
+{
+ return TRUE;
+}
+
+// Management of an event.
+
+BOOL CMotion::EventProcess(const Event &event)
+{
+ D3DVECTOR pos, dir;
+ float time;
+
+ if ( m_object->RetType() != OBJECT_TOTO &&
+ m_engine->RetPause() ) return TRUE;
+
+ if ( event.event != EVENT_FRAME ) return TRUE;
+
+ m_progress += event.rTime*m_actionTime;
+ if ( m_progress > 1.0f ) m_progress = 1.0f; // (*)
+
+ pos = m_object->RetPosition(0);
+ if ( pos.y < m_water->RetLevel(m_object) ) // underwater?
+ {
+ time = event.rTime*3.0f; // everything is slower
+ }
+ else
+ {
+ time = event.rTime*10.0f;
+ }
+
+ dir = m_object->RetLinVibration();
+ dir.x = Smooth(dir.x, m_linVibration.x, time);
+ dir.y = Smooth(dir.y, m_linVibration.y, time);
+ dir.z = Smooth(dir.z, m_linVibration.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir = m_object->RetCirVibration();
+ dir.x = Smooth(dir.x, m_cirVibration.x, time);
+ dir.y = Smooth(dir.y, m_cirVibration.y, time);
+ dir.z = Smooth(dir.z, m_cirVibration.z, time);
+ m_object->SetCirVibration(dir);
+
+ dir = m_object->RetInclinaison();
+ dir.x = Smooth(dir.x, m_inclinaison.x, time);
+ dir.y = Smooth(dir.y, m_inclinaison.y, time);
+ dir.z = Smooth(dir.z, m_inclinaison.z, time);
+ m_object->SetInclinaison(dir);
+
+ return TRUE;
+}
+
+// (*) Avoids the bug of ants returned by the thumper and
+// whose abdomen grown to infinity!
+
+
+// Start an action.
+
+Error CMotion::SetAction(int action, float time)
+{
+ m_actionType = action;
+ m_actionTime = 1.0f/time;
+ m_progress = 0.0f;
+ return ERR_OK;
+}
+
+// Returns the current action.
+
+int CMotion::RetAction()
+{
+ return m_actionType;
+}
+
+
+// Specifies a special parameter.
+
+BOOL CMotion::SetParam(int rank, float value)
+{
+ return FALSE;
+}
+
+float CMotion::RetParam(int rank)
+{
+ return 0.0f;
+}
+
+
+// Saves all parameters of the object.
+
+BOOL CMotion::Write(char *line)
+{
+ char name[100];
+
+ if ( m_actionType == -1 ) return FALSE;
+
+ sprintf(name, " mType=%d", m_actionType);
+ strcat(line, name);
+
+ sprintf(name, " mTime=%.2f", m_actionTime);
+ strcat(line, name);
+
+ sprintf(name, " mProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ return FALSE;
+}
+
+// Restores all parameters of the object.
+
+BOOL CMotion::Read(char *line)
+{
+ m_actionType = OpInt(line, "mType", -1);
+ m_actionTime = OpFloat(line, "mTime", 0.0f);
+ m_progress = OpFloat(line, "mProgress", 0.0f);
+
+ return FALSE;
+}
+
+
+// Gives the linear vibration.
+
+void CMotion::SetLinVibration(D3DVECTOR dir)
+{
+ m_linVibration = dir;
+}
+
+D3DVECTOR CMotion::RetLinVibration()
+{
+ return m_linVibration;
+}
+
+// Gives the circular vibration.
+
+void CMotion::SetCirVibration(D3DVECTOR dir)
+{
+ m_cirVibration = dir;
+}
+
+D3DVECTOR CMotion::RetCirVibration()
+{
+ return m_cirVibration;
+}
+
+// Gives the tilt.
+
+void CMotion::SetInclinaison(D3DVECTOR dir)
+{
+ m_inclinaison = dir;
+}
+
+D3DVECTOR CMotion::RetInclinaison()
+{
+ return m_inclinaison;
+}
+
diff --git a/src/object/motion/motion.h b/src/object/motion/motion.h
new file mode 100644
index 0000000..5aa0afb
--- /dev/null
+++ b/src/object/motion/motion.h
@@ -0,0 +1,94 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motion.h
+
+#ifndef _MOTION_H_
+#define _MOTION_H_
+
+
+#include "d3dengine.h"
+
+
+class CInstanceManager;
+class CEngine;
+class CLight;
+class CParticule;
+class CTerrain;
+class CWater;
+class CCamera;
+class CBrain;
+class CPhysics;
+class CObject;
+class CRobotMain;
+class CSound;
+
+
+class CMotion
+{
+public:
+ CMotion(CInstanceManager* iMan, CObject* object);
+ virtual ~CMotion();
+
+ void SetPhysics(CPhysics* physics);
+ void SetBrain(CBrain* brain);
+
+ virtual void DeleteObject(BOOL bAll=FALSE);
+ virtual BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power);
+ virtual BOOL EventProcess(const Event &event);
+ virtual Error SetAction(int action, float time=0.2f);
+ virtual int RetAction();
+
+ virtual BOOL SetParam(int rank, float value);
+ virtual float RetParam(int rank);
+
+ virtual BOOL Write(char *line);
+ virtual BOOL Read(char *line);
+
+ virtual void SetLinVibration(D3DVECTOR dir);
+ virtual D3DVECTOR RetLinVibration();
+ virtual void SetCirVibration(D3DVECTOR dir);
+ virtual D3DVECTOR RetCirVibration();
+ virtual void SetInclinaison(D3DVECTOR dir);
+ virtual D3DVECTOR RetInclinaison();
+
+protected:
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CLight* m_light;
+ CParticule* m_particule;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CCamera* m_camera;
+ CObject* m_object;
+ CBrain* m_brain;
+ CPhysics* m_physics;
+ CRobotMain* m_main;
+ CSound* m_sound;
+
+ int m_actionType;
+ float m_actionTime;
+ float m_progress;
+
+ D3DVECTOR m_linVibration; // linear vibration
+ D3DVECTOR m_cirVibration; // circular vibration
+ D3DVECTOR m_inclinaison; // tilt
+};
+
+
+#endif //_MOTION_H_
diff --git a/src/object/motion/motionant.cpp b/src/object/motion/motionant.cpp
new file mode 100644
index 0000000..3790f7e
--- /dev/null
+++ b/src/object/motion/motionant.cpp
@@ -0,0 +1,901 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionant.cpp
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "math3d.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "light.h"
+#include "particule.h"
+#include "terrain.h"
+#include "object.h"
+#include "physics.h"
+#include "brain.h"
+#include "camera.h"
+#include "modfile.h"
+#include "sound.h"
+#include "motion.h"
+#include "motionant.h"
+
+
+
+#define ADJUST_ANGLE FALSE // TRUE -> adjusts the angles of the members
+#define START_TIME 1000.0f // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionAnt::CMotionAnt(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ CMotion::CMotion(iMan, object);
+
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeMarch = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLastAction = -1;
+ m_bArmStop = FALSE;
+ m_lastParticule = 0.0f;
+}
+
+// Object's destructor.
+
+CMotionAnt::~CMotionAnt()
+{
+}
+
+
+// Removes an object.
+
+void CMotionAnt::DeleteObject(BOOL bAll)
+{
+}
+
+
+// Creates a vehicle poses some rolling on the floor.
+
+BOOL CMotionAnt::Create(D3DVECTOR pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 3+18 ) return FALSE;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates the main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+
+ pModFile->ReadModel("objects\\ant1.mod");
+ pModFile->CreateEngineObject(rank);
+
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have necessarily a collision
+ //with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(D3DVECTOR(0.0f, -2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
+ m_object->SetGlobalSphere(D3DVECTOR(-0.5f, 1.0f, 0.0f), 4.0f);
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\ant2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, D3DVECTOR(2.0f, 0.0f, 0.0f));
+
+ // Creates the tail.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\ant3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, D3DVECTOR(-1.0f, 0.0f, 0.0f));
+
+ // Creates a right-back thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, D3DVECTOR(-0.4f, -0.1f, -0.3f));
+
+ // Creates a right-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 3);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, D3DVECTOR(0.0f, 0.0f, -1.0f));
+
+ // Creates a right-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 4);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, D3DVECTOR(0.0f, 0.0f, -2.0f));
+
+ // Creates two middle-right thighs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, D3DVECTOR(0.1f, -0.1f, -0.4f));
+
+ // Creates two middle-right legs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 6);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, D3DVECTOR(0.0f, 0.0f, -1.0f));
+
+ // Creates two middle-right foots.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 7);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, D3DVECTOR(0.0f, 0.0f, -2.0f));
+
+ // Creates the right front thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, D3DVECTOR(1.4f, -0.1f, -0.6f));
+
+ // Creates the right front leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10, rank);
+ m_object->SetObjectParent(10, 9);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10, D3DVECTOR(0.0f, 0.0f, -1.0f));
+
+ // Creates the right front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(11, rank);
+ m_object->SetObjectParent(11, 10);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(11, D3DVECTOR(0.0f, 0.0f, -2.0f));
+
+ // Creates a left-back thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(12, rank);
+ m_object->SetObjectParent(12, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(12, D3DVECTOR(-0.4f, -0.1f, 0.3f));
+
+ // Creates a left-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(13, rank);
+ m_object->SetObjectParent(13, 12);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(13, D3DVECTOR(0.0f, 0.0f, 1.0f));
+
+ // Creates a left-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(14, rank);
+ m_object->SetObjectParent(14, 13);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(14, D3DVECTOR(0.0f, 0.0f, 2.0f));
+
+ // Creates two middle-left thighs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(15, rank);
+ m_object->SetObjectParent(15, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(15, D3DVECTOR(0.1f, -0.1f, 0.4f));
+
+ // Creates two middle-left legs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(16, rank);
+ m_object->SetObjectParent(16, 15);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(16, D3DVECTOR(0.0f, 0.0f, 1.0f));
+
+ // Creates two middle-left foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(17, rank);
+ m_object->SetObjectParent(17, 16);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(17, D3DVECTOR(0.0f, 0.0f, 2.0f));
+
+ // Creates the left front thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(18, rank);
+ m_object->SetObjectParent(18, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(18, D3DVECTOR(1.4f, -0.1f, 0.6f));
+
+ // Creates the left front leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(19, rank);
+ m_object->SetObjectParent(19, 18);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(19, D3DVECTOR(0.0f, 0.0f, 1.0f));
+
+ // Creates the left front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(20, rank);
+ m_object->SetObjectParent(20, 19);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(20, D3DVECTOR(0.0f, 0.0f, 2.0f));
+
+ m_object->CreateShadowCircle(4.0f, 0.5f);
+
+ CreatePhysics();
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return TRUE;
+}
+
+// Creates the physics of the object.
+
+void CMotionAnt::CreatePhysics()
+{
+ Character* character;
+ int i;
+
+ int member_march[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 0,45,0, 0,45,0, 0,50,0, // t0: thighs 1..3
+ 30,-70,0, 20,-105,20, 25,-100,0, // t0: legs 1..3
+ -70,75,0, -30,80,0, -80,80,0, // t0: feet 1..3
+ // on the ground:
+ 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3
+ -15,-50,0, -20,-60,0, -10,-75,0, // t1: legs 1..3
+ -40,50,0, -25,15,0, -50,35,0, // t1: feet 1..3
+ // on the ground back:
+ 0,35,0, 0,30,0, 0,20,0, // t2: thighs 1..3
+ -20,-15,0, -30,-55,0, -25,-70,15, // t2: legs 1..3
+ -25,25,0, -20,60,0, -30,95,0, // t2: feet 1..3
+ };
+
+ int member_stop[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 0,30,0, 0,20,0, 0,15,0, // t0: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // t0: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // t0: feet 1..3
+ // on the ground:
+ 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // t1: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // t1: feet 1..3
+ // on the ground back:
+ 0,30,0, 0,20,0, 0,15,0, // t2: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // t2: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // t2: feet 1..3
+ };
+
+ int member_spec[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // prepares the fire:
+ 0,20,0, 0,10,0, 0,50,0, // s0: thighs 1..3
+ -50,-30,0, -20,-15,0, 35,-65,0, // s0: legs 1..3
+ -5,-40,0, 20,-70,0, -10,-40,0, // s0: feet 1..3
+ // shot:
+ 0,20,0, 0,10,0, 0,50,0, // s1: thighs 1..3
+ -50,-30,0, -20,-15,0, 35,-65,0, // s1: legs 1..3
+ -5,-40,0, 20,-70,0, -10,-40,0, // s1: feet 1..3
+ // ends the fire:
+ 0,30,0, 0,20,0, 0,15,0, // s2: thighs 1..3
+ -15,-50,0, -20,-60,0, -10,-75,0, // s2: legs 1..3
+ -40,50,0, -25,15,0, -50,35,0, // s2: feet 1..3
+ // burning:
+ 0,30,0, 0,20,0, 0,15,0, // s3: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // s3: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // s3: feet 1..3
+ // destroyed:
+ 0,30,0, 0,20,0, 0,15,0, // s4: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // s4: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // s4: feet 1..3
+ // back1 :
+ 0,30,0, 0,20,0, 0,15,0, // s5: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // s5: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // s5: feet 1..3
+ // back2 :
+ 0,45,0, 0,45,0, 0,50,0, // s6: thighs 1..3
+ -35,-70,0, -20,-85,-25, -25,-100,0, // s6: legs 1..3
+ -110,75,-15, -130,80,-25, -125,40,0, // s6: feet 1..3
+ // back3 :
+ 0,30,0, 0,20,0, 0,15,0, // s7: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // s7: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // s7: feet 1..3
+ };
+
+ m_physics->SetType(TYPE_ROLLING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 3.0f;
+ character->wheelBack = 3.0f;
+ character->wheelLeft = 5.0f;
+ character->wheelRight = 5.0f;
+ character->height = 1.2f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 12.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 12.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 15.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 10.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 40.0f);
+
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MA_MARCH+i] = member_march[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MA_STOP+i] = member_stop[i];
+ }
+ for ( i=0 ; i<3*3*3*8 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MA_SPEC+i] = member_spec[i];
+ }
+}
+
+
+// Management of an event.
+
+BOOL CMotionAnt::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if ADJUST_ANGLE
+ int i;
+
+ if ( event.param == 'A' ) m_armTimeIndex++;
+ if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
+
+ if ( event.param == 'Q' ) m_armPartIndex++;
+ if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
+
+ if ( event.param == 'W' ) m_armMemberIndex++;
+ if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
+
+ i = m_armMemberIndex*3;
+ i += m_armPartIndex*3*3;
+ i += m_armTimeIndex*3*3*3;
+//? i += 3*3*3*3;
+
+ if ( event.param == 'E' ) m_armAngles[i+0] += 5;
+ if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
+ if ( event.param == 'R' ) m_armAngles[i+1] += 5;
+ if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
+ if ( event.param == 'T' ) m_armAngles[i+2] += 5;
+ if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
+
+ if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
+#endif
+ }
+
+ return TRUE;
+}
+
+// Calculates a value (radians) proportional between a and b (degrees).
+
+inline float Propf(float a, float b, float p)
+{
+ float aa, bb;
+
+ aa = a*PI/180.0f;
+ bb = b*PI/180.0f;
+
+ return aa+p*(bb-aa);
+}
+
+// Management of an event.
+
+BOOL CMotionAnt::EventFrame(const Event &event)
+{
+ D3DVECTOR dir, pos, speed;
+ FPOINT dim;
+ float s, a, prog, time;
+ float tSt[9], tNd[9];
+ int i, ii, st, nd, action;
+ BOOL bStop;
+
+ if ( m_engine->RetPause() ) return TRUE;
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return TRUE;
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
+ a = Abs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f);
+
+ if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armTimeMarch += (s)*event.rTime*0.15f;
+ m_armMember += (s+a)*event.rTime*0.15f;
+
+ bStop = ( a == 0.0f && s == 0.0f ); // stopped?
+
+ action = MA_MARCH; // walking
+ if ( s == 0.0f && a == 0.0f )
+ {
+ action = MA_STOP; // stop
+ }
+
+ if ( bStop )
+ {
+ prog = Mod(m_armTimeAbs, 2.0f)/10.0f;
+ a = Mod(m_armMember, 1.0f);
+ a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly
+ m_armMember += a;
+ }
+
+ if ( m_object->RetRuin() ) // destroyed?
+ {
+ m_actionType = MAS_RUIN;
+ }
+ if ( m_object->RetBurn() ) // burning?
+ {
+ if ( m_object->RetFixed() )
+ {
+ m_actionType = MAS_BURN;
+ }
+ else
+ {
+ m_actionType = -1;
+ }
+ }
+
+ for ( i=0 ; i<6 ; i++ ) // the six legs
+ {
+ if ( m_actionType != -1 ) // special action in progress?
+ {
+ st = 3*3*3*3*MA_SPEC + 3*3*3*m_actionType + (i%3)*3;
+ nd = st;
+ time = event.rTime*m_actionTime;
+ m_armTimeAction = 0.0f;
+ }
+ else
+ {
+ if ( i < 3 ) prog = Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
+ else prog = Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
+ if ( m_bArmStop )
+ {
+ prog = (float)m_armTimeIndex/3.0f;
+ }
+ if ( prog < 0.33f ) // t0..t1 ?
+ {
+ prog = prog/0.33f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.67f ) // t1..t2 ?
+ {
+ prog = (prog-0.33f)/0.33f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.67f)/0.33f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ st = 3*3*3*3*action + st*3*3*3 + (i%3)*3;
+ nd = 3*3*3*3*action + nd*3*3*3 + (i%3)*3;
+
+ // More and more soft ...
+ time = event.rTime*(10.0f+Min(m_armTimeAction*100.0f, 200.0f));
+ }
+
+ tSt[0] = m_armAngles[st+ 0]; // x
+ tSt[1] = m_armAngles[st+ 1]; // y
+ tSt[2] = m_armAngles[st+ 2]; // z
+ tSt[3] = m_armAngles[st+ 9]; // x
+ tSt[4] = m_armAngles[st+10]; // y
+ tSt[5] = m_armAngles[st+11]; // z
+ tSt[6] = m_armAngles[st+18]; // x
+ tSt[7] = m_armAngles[st+19]; // y
+ tSt[8] = m_armAngles[st+20]; // z
+
+ tNd[0] = m_armAngles[nd+ 0]; // x
+ tNd[1] = m_armAngles[nd+ 1]; // y
+ tNd[2] = m_armAngles[nd+ 2]; // z
+ tNd[3] = m_armAngles[nd+ 9]; // x
+ tNd[4] = m_armAngles[nd+10]; // y
+ tNd[5] = m_armAngles[nd+11]; // z
+ tNd[6] = m_armAngles[nd+18]; // x
+ tNd[7] = m_armAngles[nd+19]; // y
+ tNd[8] = m_armAngles[nd+20]; // z
+
+ if ( m_actionType == MAS_BACK2 ) // on the back?
+ {
+ for ( ii=0 ; ii<9 ; ii++ )
+ {
+ tSt[ii] += Rand()*50.0f;
+ tNd[ii] = tSt[ii];
+ }
+//? time = 100.0f;
+ time = event.rTime*10.0f;
+ }
+
+ if ( i < 3 ) // right leg (1..3) ?
+ {
+ m_object->SetAngleX(3+3*i+0, Smooth(m_object->RetAngleX(3+3*i+0), Propf(tSt[0], tNd[0], prog), time));
+ m_object->SetAngleY(3+3*i+0, Smooth(m_object->RetAngleY(3+3*i+0), Propf(tSt[1], tNd[1], prog), time));
+ m_object->SetAngleZ(3+3*i+0, Smooth(m_object->RetAngleZ(3+3*i+0), Propf(tSt[2], tNd[2], prog), time));
+ m_object->SetAngleX(3+3*i+1, Smooth(m_object->RetAngleX(3+3*i+1), Propf(tSt[3], tNd[3], prog), time));
+ m_object->SetAngleY(3+3*i+1, Smooth(m_object->RetAngleY(3+3*i+1), Propf(tSt[4], tNd[4], prog), time));
+ m_object->SetAngleZ(3+3*i+1, Smooth(m_object->RetAngleZ(3+3*i+1), Propf(tSt[5], tNd[5], prog), time));
+ m_object->SetAngleX(3+3*i+2, Smooth(m_object->RetAngleX(3+3*i+2), Propf(tSt[6], tNd[6], prog), time));
+ m_object->SetAngleY(3+3*i+2, Smooth(m_object->RetAngleY(3+3*i+2), Propf(tSt[7], tNd[7], prog), time));
+ m_object->SetAngleZ(3+3*i+2, Smooth(m_object->RetAngleZ(3+3*i+2), Propf(tSt[8], tNd[8], prog), time));
+ }
+ else // left leg (4..6) ?
+ {
+ m_object->SetAngleX(3+3*i+0, Smooth(m_object->RetAngleX(3+3*i+0), Propf(-tSt[0], -tNd[0], prog), time));
+ m_object->SetAngleY(3+3*i+0, Smooth(m_object->RetAngleY(3+3*i+0), Propf(-tSt[1], -tNd[1], prog), time));
+ m_object->SetAngleZ(3+3*i+0, Smooth(m_object->RetAngleZ(3+3*i+0), Propf( tSt[2], tNd[2], prog), time));
+ m_object->SetAngleX(3+3*i+1, Smooth(m_object->RetAngleX(3+3*i+1), Propf(-tSt[3], -tNd[3], prog), time));
+ m_object->SetAngleY(3+3*i+1, Smooth(m_object->RetAngleY(3+3*i+1), Propf(-tSt[4], -tNd[4], prog), time));
+ m_object->SetAngleZ(3+3*i+1, Smooth(m_object->RetAngleZ(3+3*i+1), Propf( tSt[5], tNd[5], prog), time));
+ m_object->SetAngleX(3+3*i+2, Smooth(m_object->RetAngleX(3+3*i+2), Propf(-tSt[6], -tNd[6], prog), time));
+ m_object->SetAngleY(3+3*i+2, Smooth(m_object->RetAngleY(3+3*i+2), Propf(-tSt[7], -tNd[7], prog), time));
+ m_object->SetAngleZ(3+3*i+2, Smooth(m_object->RetAngleZ(3+3*i+2), Propf( tSt[8], tNd[8], prog), time));
+ }
+ }
+
+#if ADJUST_ANGLE
+ if ( m_object->RetSelect() )
+ {
+ char s[100];
+ sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
+ m_engine->SetInfoText(4, s);
+ }
+#endif
+
+ if ( m_actionType == MAS_PREPARE ) // prepares the shooting?
+ {
+ prog = m_progress;
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = Prop(0, -50, prog);
+ SetInclinaison(dir);
+ m_object->SetAngleZ(1, Prop(0, 65, prog)); // head
+ m_object->SetAngleZ(2, Prop(0, -95, prog)); // tail
+ }
+ else if ( m_actionType == MAS_FIRE ) // shooting?
+ {
+ if ( m_progress < 0.75f ) a = m_progress/0.75f;
+ else a = (1.0f-m_progress)/0.25f;
+ m_object->SetZoom(2, (a*0.5f)+1.0f); // tail
+ m_object->SetAngleX(2, (Rand()-0.5f)*0.3f*a);
+ m_object->SetAngleY(2, (Rand()-0.5f)*0.3f*a);
+
+ dir.x = (Rand()-0.5f)*0.02f*a;
+ dir.y = (Rand()-0.5f)*0.05f*a;
+ dir.z = (Rand()-0.5f)*0.03f*a;
+ SetCirVibration(dir);
+ }
+ else if ( m_actionType == MAS_TERMINATE ) // ends the shooting?
+ {
+ prog = 1.0f-m_progress;
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = Prop(0, -50, prog);
+ SetInclinaison(dir);
+ m_object->SetAngleZ(1, Prop(0, 65, prog)); // head
+ m_object->SetAngleZ(2, Prop(0, -95, prog)); // tail
+ }
+ else if ( m_actionType == MAS_BURN ) // burning?
+ {
+ dir = D3DVECTOR(PI, 0.0f, 0.0f);
+ SetCirVibration(dir);
+ dir = D3DVECTOR(0.0f, -1.5f, 0.0f);
+ SetLinVibration(dir);
+ dir = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ time = event.rTime*1.0f;
+ m_object->SetAngleZ(1, Smooth(m_object->RetAngleZ(1), 0.0f, time)); // head
+ m_object->SetAngleZ(2, Smooth(m_object->RetAngleZ(2), 0.0f, time)); // tail
+ }
+ else if ( m_actionType == MAS_RUIN ) // destroyed?
+ {
+ dir = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ SetCirVibration(dir);
+ SetInclinaison(dir);
+ }
+ else if ( m_actionType == MAS_BACK1 ) // starts on the back?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (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 < 0.5f )
+ {
+ dir.x = 0.0f;
+ dir.y = powf(m_progress/0.5f, 2.0f)*12.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*12.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ dir.x = m_progress*PI;
+ dir.y = 0.0f;
+ dir.z = 0.0f;
+ SetCirVibration(dir);
+
+ dir = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(MAS_BACK2, 55.0f+Rand()*10.0f);
+ }
+ }
+ else if ( m_actionType == MAS_BACK2 ) // moves on the back?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ if ( rand()%10 == 0 )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += (Rand()-0.5f)*5.0f;
+ pos.z += (Rand()-0.5f)*5.0f;
+ pos.y -= 1.0f;
+ speed.x = (Rand()-0.5f)*2.0f;
+ speed.z = (Rand()-0.5f)*2.0f;
+ speed.y = Rand()*2.0f;
+ dim.x = Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+ }
+
+ dir = D3DVECTOR(0.0f, -1.0f, 0.0f);
+ SetLinVibration(dir);
+ dir.x = sinf(m_armTimeAbs* 4.0f)*0.10f+
+ sinf(m_armTimeAbs* 7.0f)*0.20f+
+ sinf(m_armTimeAbs*10.0f)*0.40f+
+ sinf(m_armTimeAbs*21.0f)*0.50f+PI;
+ dir.y = sinf(m_armTimeAbs* 3.0f)*0.01f+
+ sinf(m_armTimeAbs* 6.0f)*0.02f+
+ sinf(m_armTimeAbs*11.0f)*0.04f+
+ sinf(m_armTimeAbs*20.0f)*0.02f;
+ dir.z = sinf(m_armTimeAbs* 5.0f)*0.01f+
+ sinf(m_armTimeAbs* 8.0f)*0.02f+
+ sinf(m_armTimeAbs* 9.0f)*0.04f+
+ sinf(m_armTimeAbs*23.0f)*0.03f;
+ SetCirVibration(dir);
+ dir = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*8.0f)*0.7f); // head
+ m_object->SetAngleY(2, cosf(m_armTimeAbs*8.0f)*0.7f); // tail
+ m_object->SetAngleZ(1, 0.0f); // head
+ m_object->SetAngleZ(2, 0.0f); // tail
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(MAS_BACK3, 0.4f);
+ }
+ }
+ else if ( m_actionType == MAS_BACK3 ) // goes back on the legs?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (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 < 0.5f )
+ {
+ dir.x = 0.0f;
+ dir.y = powf(m_progress/0.5f, 2.0f)*5.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*5.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ dir.x = (1.0f-m_progress)*PI;
+ dir.y = 0.0f;
+ dir.z = 0.0f;
+ SetCirVibration(dir);
+
+ dir = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(-1);
+ m_object->SetFixed(FALSE); // moving again
+ }
+ }
+ else
+ {
+ m_object->SetZoom(2, 1.0f); // tail
+ m_object->SetAngleX(2, 0.0f);
+ m_object->SetAngleY(2, 0.0f);
+
+ if ( bStop )
+ {
+ m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.7f)*0.15f); // tail
+
+ dir = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ SetInclinaison(dir);
+ }
+ else
+ {
+ a = Mod(m_armTimeMarch, 1.0f);
+ if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
+ else a = 3.0f-4.0f*a; // 1..-1
+ dir.x = sinf(a)*0.05f;
+
+ s = Mod(m_armTimeMarch/2.0f, 1.0f);
+ if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
+ else s = 3.0f-4.0f*s; // 1..-1
+ dir.z = sinf(s)*0.1f;
+
+ dir.y = 0.0f;
+ SetInclinaison(dir);
+
+ m_object->SetAngleZ(2, -sinf(a)*0.3f); // tail
+
+ a = Mod(m_armMember-0.1f, 1.0f);
+ if ( a < 0.33f )
+ {
+ dir.y = -(1.0f-(a/0.33f))*0.3f;
+ }
+ else if ( a < 0.67f )
+ {
+ dir.y = 0.0f;
+ }
+ else
+ {
+ dir.y = -(a-0.67f)/0.33f*0.3f;
+ }
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+
+ dir = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ SetCirVibration(dir);
+
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.4f)*0.20f); // head
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.9f)*0.10f); // head
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*2.1f)*0.50f); // head
+ }
+
+ return TRUE;
+}
+
+
diff --git a/src/object/motion/motionant.h b/src/object/motion/motionant.h
new file mode 100644
index 0000000..e8d79c6
--- /dev/null
+++ b/src/object/motion/motionant.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/.
+
+// motionant.h
+
+#ifndef _MOTIONANT_H_
+#define _MOTIONANT_H_
+
+
+#include "motion.h"
+
+
+class CInstanceManager;
+class CEngine;
+class CLight;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CBrain;
+class CPhysics;
+class CObject;
+
+
+#define MA_MARCH 0
+#define MA_STOP 1
+#define MA_SPEC 2
+
+#define MAS_PREPARE 0
+#define MAS_FIRE 1
+#define MAS_TERMINATE 2
+#define MAS_BURN 3
+#define MAS_RUIN 4
+#define MAS_BACK1 5
+#define MAS_BACK2 6
+#define MAS_BACK3 7
+
+
+class CMotionAnt : public CMotion
+{
+public:
+ CMotionAnt(CInstanceManager* iMan, CObject* object);
+ ~CMotionAnt();
+
+ void DeleteObject(BOOL bAll=FALSE);
+ BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power);
+ BOOL EventProcess(const Event &event);
+
+protected:
+ void CreatePhysics();
+ BOOL EventFrame(const Event &event);
+
+protected:
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeMarch;
+ float m_armTimeAction;
+ short m_armAngles[3*3*3*3*3 + 3*3*3*8];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ BOOL m_bArmStop;
+ float m_lastParticule;
+};
+
+
+#endif //_MOTIONANT_H_
diff --git a/src/object/motion/motionbee.cpp b/src/object/motion/motionbee.cpp
new file mode 100644
index 0000000..65ebeb7
--- /dev/null
+++ b/src/object/motion/motionbee.cpp
@@ -0,0 +1,663 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionbee.cpp
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "math3d.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "light.h"
+#include "particule.h"
+#include "terrain.h"
+#include "object.h"
+#include "physics.h"
+#include "brain.h"
+#include "camera.h"
+#include "modfile.h"
+#include "sound.h"
+#include "motion.h"
+#include "motionbee.h"
+
+
+
+#define ADJUST_ANGLE FALSE // TRUE -> adjusts the angles of the members
+#define START_TIME 1000.0f // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionBee::CMotionBee(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ CMotion::CMotion(iMan, object);
+
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeMarch = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLastAction = -1;
+ m_bArmStop = FALSE;
+}
+
+// Object's destructor.
+
+CMotionBee::~CMotionBee()
+{
+}
+
+
+// Removes an object.
+
+void CMotionBee::DeleteObject(BOOL bAll)
+{
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+BOOL CMotionBee::Create(D3DVECTOR pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 3+18+2 ) return FALSE;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+
+ pModFile->ReadModel("objects\\bee1.mod");
+ pModFile->CreateEngineObject(rank);
+
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have an obligatory collision
+ // with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
+ m_object->SetGlobalSphere(D3DVECTOR(-1.0f, 1.0f, 0.0f), 5.0f);
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\bee2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, D3DVECTOR(1.6f, 0.3f, 0.0f));
+
+ // Creates the tail.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\bee3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, D3DVECTOR(-0.8f, 0.0f, 0.0f));
+
+ // Creates a right-back thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, D3DVECTOR(-0.3f, -0.1f, -0.2f));
+
+ // Creates a right-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 3);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, D3DVECTOR(0.0f, 0.0f, -1.0f));
+
+ // Creates a right-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 4);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, D3DVECTOR(0.0f, 0.0f, -2.0f));
+
+ // Creates two middle-right thighs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, D3DVECTOR(0.3f, -0.1f, -0.4f));
+
+ // Creates two middle-right legs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 6);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, D3DVECTOR(0.0f, 0.0f, -1.0f));
+
+ // Creates two middle-right feet.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 7);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, D3DVECTOR(0.0f, 0.0f, -2.0f));
+
+ // Creates the right front thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, D3DVECTOR(1.0f, -0.1f, -0.7f));
+
+ // Creates the right front leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10, rank);
+ m_object->SetObjectParent(10, 9);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10, D3DVECTOR(0.0f, 0.0f, -1.0f));
+
+ // Creates the right front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(11, rank);
+ m_object->SetObjectParent(11, 10);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(11, D3DVECTOR(0.0f, 0.0f, -2.0f));
+
+ // Creates a left-back thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(12, rank);
+ m_object->SetObjectParent(12, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(12, D3DVECTOR(-0.3f, -0.1f, 0.2f));
+ m_object->SetAngleY(12, PI);
+
+ // Creates a left-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(13, rank);
+ m_object->SetObjectParent(13, 12);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(13, D3DVECTOR(0.0f, 0.0f, -1.0f));
+
+ // Creates a left-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(14, rank);
+ m_object->SetObjectParent(14, 13);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(14, D3DVECTOR(0.0f, 0.0f, -2.0f));
+
+ // Creates two middle-left thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(15, rank);
+ m_object->SetObjectParent(15, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(15, D3DVECTOR(0.3f, -0.1f, 0.4f));
+ m_object->SetAngleY(15, PI);
+
+ // Creates two middle-left legs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(16, rank);
+ m_object->SetObjectParent(16, 15);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(16, D3DVECTOR(0.0f, 0.0f, -1.0f));
+
+ // Creates two middle-left feet.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(17, rank);
+ m_object->SetObjectParent(17, 16);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(17, D3DVECTOR(0.0f, 0.0f, -2.0f));
+
+ // Creates front-left thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(18, rank);
+ m_object->SetObjectParent(18, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(18, D3DVECTOR(1.0f, -0.1f, 0.7f));
+ m_object->SetAngleY(18, PI);
+
+ // Creates front-left leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(19, rank);
+ m_object->SetObjectParent(19, 18);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(19, D3DVECTOR(0.0f, 0.0f, -1.0f));
+
+ // Creates front-left foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(20, rank);
+ m_object->SetObjectParent(20, 19);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(20, D3DVECTOR(0.0f, 0.0f, -2.0f));
+
+ // Creates the right wing.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(21, rank);
+ m_object->SetObjectParent(21, 0);
+ pModFile->ReadModel("objects\\bee7.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(21, D3DVECTOR(0.8f, 0.4f, -0.5f));
+
+ // Creates the left wing.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(22, rank);
+ m_object->SetObjectParent(22, 0);
+ pModFile->ReadModel("objects\\bee7.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(22, D3DVECTOR(0.8f, 0.4f, 0.5f));
+
+ m_object->CreateShadowCircle(6.0f, 0.5f);
+
+ CreatePhysics();
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return TRUE;
+}
+
+// Creates the physical object.
+
+void CMotionBee::CreatePhysics()
+{
+ Character* character;
+ int i;
+
+ int member_march[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 0,45,0, 0,45,0, 0,50,0, // t0: thighs 1..3
+ 30,-70,0, 20,-105,20, 25,-100,0, // t0: legs 1..3
+ -70,75,0, -30,80,0, -80,80,0, // t0: feet 1..3
+ // on the ground:
+ 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3
+ -15,-50,0, -20,-60,0, -10,-75,0, // t1: legs 1..3
+ -40,50,0, -25,15,0, -50,35,0, // t1: feet 1..3
+ // on the ground back:
+ 0,35,0, 0,30,0, 0,20,0, // t2: thighs 1..3
+ -20,-15,0, -30,-55,0, -25,-70,15, // t2: legs 1..3
+ -25,25,0, -20,60,0, -30,95,0, // t2: feet 1..3
+ };
+
+ int member_spec[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // ball carrier:
+ 0,45,0, 0,45,0, 0,50,0, // s0: thighs 1..3
+ -35,-70,0, -20,-85,-25, -25,-100,0, // s0: legs 1..3
+ -110,75,-15, -130,80,-25, -125,40,0, // s0: feet 1..3
+ // burning:
+ 0,45,0, 0,45,0, 0,50,0, // s1: thighs 1..3
+ -35,-70,0, -20,-85,-25, -25,-100,0, // s1: legs 1..3
+ -110,75,-15, -130,80,-25, -125,40,0, // s1: feet 1..3
+ // destroyed:
+ 0,45,0, 0,45,0, 0,50,0, // s2: thighs 1..3
+ -35,-70,0, -20,-85,-25, -25,-100,0, // s2: legs 1..3
+ -110,75,-15, -130,80,-25, -125,40,0, // s2: feet 1..3
+ };
+
+ m_physics->SetType(TYPE_FLYING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 3.0f;
+ character->wheelBack = 3.0f;
+ character->wheelLeft = 5.0f;
+ character->wheelRight = 5.0f;
+ character->height = 2.5f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 50.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+ m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
+ m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 40.0f);
+
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MB_MARCH+i] = member_march[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MB_SPEC+i] = member_spec[i];
+ }
+}
+
+
+// Management of an event.
+
+BOOL CMotionBee::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if ADJUST_ANGLE
+ int i;
+
+ if ( event.param == 'A' ) m_armTimeIndex++;
+ if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
+
+ if ( event.param == 'Q' ) m_armPartIndex++;
+ if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
+
+ if ( event.param == 'W' ) m_armMemberIndex++;
+ if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
+
+ i = m_armMemberIndex*3;
+ i += m_armPartIndex*3*3;
+ i += m_armTimeIndex*3*3*3;
+//? i += 3*3*3*3;
+
+ if ( event.param == 'E' ) m_armAngles[i+0] += 5;
+ if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
+ if ( event.param == 'R' ) m_armAngles[i+1] += 5;
+ if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
+ if ( event.param == 'T' ) m_armAngles[i+2] += 5;
+ if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
+
+ if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
+#endif
+ }
+
+ return TRUE;
+}
+
+// Management of an event.
+
+BOOL CMotionBee::EventFrame(const Event &event)
+{
+ D3DVECTOR dir;
+ float s, a, prog;
+ int action, i, st, nd;
+ BOOL bStop;
+
+ if ( m_engine->RetPause() ) return TRUE;
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return TRUE;
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.30f;
+ a = Abs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.00f);
+
+ if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armTimeMarch += (s)*event.rTime*0.15f;
+ m_armMember += (s+a)*event.rTime*0.15f;
+
+ bStop = ( a == 0.0f && s == 0.0f ); // stopped?
+ if ( !m_physics->RetLand() ) bStop = TRUE;
+
+ if ( bStop )
+ {
+ prog = Mod(m_armTimeAbs, 2.0f)/10.0f;
+ a = Mod(m_armMember, 1.0f);
+ a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly
+ m_armMember += a;
+ }
+
+ action = MB_MARCH; // flying
+
+ m_actionType = -1;
+ if ( m_object->RetFret() != 0 ) m_actionType = MBS_HOLD; // carries the ball
+
+ if ( m_object->RetRuin() ) // destroyed?
+ {
+ m_actionType = MBS_RUIN;
+ }
+ if ( m_object->RetBurn() ) // burning?
+ {
+ m_actionType = MBS_BURN;
+ }
+
+ for ( i=0 ; i<6 ; i++ ) // the six legs
+ {
+ if ( m_actionType != -1 ) // special action in progress?
+ {
+ st = 3*3*3*3*MB_SPEC + 3*3*3*m_actionType + (i%3)*3;
+ nd = st;
+ }
+ else
+ {
+ if ( i < 3 ) prog = Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
+ else prog = Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
+ if ( m_bArmStop )
+ {
+ prog = (float)m_armTimeIndex/3.0f;
+ }
+ if ( prog < 0.33f ) // t0..t1 ?
+ {
+ prog = prog/0.33f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.67f ) // t1..t2 ?
+ {
+ prog = (prog-0.33f)/0.33f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.67f)/0.33f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ st = 3*3*3*3*action + st*3*3*3 + (i%3)*3;
+ nd = 3*3*3*3*action + nd*3*3*3 + (i%3)*3;
+ }
+
+ if ( i < 3 ) // right leg (1..3) ?
+ {
+ m_object->SetAngleX(3+3*i+0, Prop(m_armAngles[st+ 0], m_armAngles[nd+ 0], prog));
+ m_object->SetAngleY(3+3*i+0, Prop(m_armAngles[st+ 1], m_armAngles[nd+ 1], prog));
+ m_object->SetAngleZ(3+3*i+0, Prop(m_armAngles[st+ 2], m_armAngles[nd+ 2], prog));
+ m_object->SetAngleX(3+3*i+1, Prop(m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
+ m_object->SetAngleY(3+3*i+1, Prop(m_armAngles[st+10], m_armAngles[nd+10], prog));
+ m_object->SetAngleZ(3+3*i+1, Prop(m_armAngles[st+11], m_armAngles[nd+11], prog));
+ m_object->SetAngleX(3+3*i+2, Prop(m_armAngles[st+18], m_armAngles[nd+18], prog));
+ m_object->SetAngleY(3+3*i+2, Prop(m_armAngles[st+19], m_armAngles[nd+19], prog));
+ m_object->SetAngleZ(3+3*i+2, Prop(m_armAngles[st+20], m_armAngles[nd+20], prog));
+ }
+ else // left leg(4..6) ?
+ {
+ m_object->SetAngleX(3+3*i+0, Prop( -m_armAngles[st+ 0], -m_armAngles[nd+ 0], prog));
+ m_object->SetAngleY(3+3*i+0, Prop(180-m_armAngles[st+ 1], 180-m_armAngles[nd+ 1], prog));
+ m_object->SetAngleZ(3+3*i+0, Prop( -m_armAngles[st+ 2], -m_armAngles[nd+ 2], prog));
+ m_object->SetAngleX(3+3*i+1, Prop( m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
+ m_object->SetAngleY(3+3*i+1, Prop( -m_armAngles[st+10], -m_armAngles[nd+10], prog));
+ m_object->SetAngleZ(3+3*i+1, Prop( -m_armAngles[st+11], -m_armAngles[nd+11], prog));
+ m_object->SetAngleX(3+3*i+2, Prop( m_armAngles[st+18], m_armAngles[nd+18], prog));
+ m_object->SetAngleY(3+3*i+2, Prop( -m_armAngles[st+19], -m_armAngles[nd+19], prog));
+ m_object->SetAngleZ(3+3*i+2, Prop( -m_armAngles[st+20], -m_armAngles[nd+20], prog));
+ }
+ }
+
+#if ADJUST_ANGLE
+ if ( m_object->RetSelect() )
+ {
+ char s[100];
+ sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
+ m_engine->SetInfoText(4, s);
+ }
+#endif
+
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ if ( m_object->RetRuin() )
+ {
+ }
+ else if ( bStop || m_object->RetBurn() )
+ {
+ m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.7f)*0.15f+0.35f); // tail
+ }
+ else
+ {
+ a = Mod(m_armTimeMarch, 1.0f);
+ if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
+ else a = 3.0f-4.0f*a; // 1..-1
+ dir.x = sinf(a)*0.05f;
+
+ s = Mod(m_armTimeMarch/2.0f, 1.0f);
+ if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
+ else s = 3.0f-4.0f*s; // 1..-1
+ dir.z = sinf(s)*0.1f;
+
+ dir.y = 0.0f;
+ m_object->SetInclinaison(dir);
+
+ m_object->SetAngleZ(2, -sinf(a)*0.3f); // tail
+
+ a = Mod(m_armMember-0.1f, 1.0f);
+ if ( a < 0.33f )
+ {
+ dir.y = -(1.0f-(a/0.33f))*0.3f;
+ }
+ else if ( a < 0.67f )
+ {
+ dir.y = 0.0f;
+ }
+ else
+ {
+ dir.y = -(a-0.67f)/0.33f*0.3f;
+ }
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ m_object->SetLinVibration(dir);
+ }
+ }
+
+ if ( m_physics->RetLand() )
+ {
+ if ( bStop ) prog = 0.05f;
+ else prog = 0.15f;
+ }
+ else
+ {
+ prog = 1.00f;
+ }
+
+#if 0
+ a = Rand()*PI/2.0f*prog;
+ m_object->SetAngleX(21, a); // right wing
+ a = -Rand()*PI/4.0f*prog;
+ m_object->SetAngleY(21, a);
+
+ a = -Rand()*PI/2.0f*prog;
+ m_object->SetAngleX(22, a); // left wing
+ a = Rand()*PI/4.0f*prog;
+ m_object->SetAngleY(22, a);
+#else
+ m_object->SetAngleX(21, (sinf(m_armTimeAbs*30.0f)+1.0f)*(PI/4.0f)*prog);
+ m_object->SetAngleY(21, -Rand()*PI/6.0f*prog);
+
+ m_object->SetAngleX(22, -(sinf(m_armTimeAbs*30.0f)+1.0f)*(PI/4.0f)*prog);
+ m_object->SetAngleY(22, Rand()*PI/6.0f*prog);
+#endif
+
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.4f)*0.20f); // head
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.9f)*0.10f); // head
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*2.1f)*0.50f); // head
+
+#if 0
+ h = m_terrain->RetFloorHeight(RetPosition(0));
+ radius = 4.0f+h/4.0f;
+ color.r = 0.3f+h/80.0f;
+ color.g = color.r;
+ color.b = color.r;
+ color.a = color.r;
+ m_engine->SetObjectShadowRadius(m_objectPart[0].object, radius);
+ m_engine->SetObjectShadowColor(m_objectPart[0].object, color);
+#endif
+
+ return TRUE;
+}
+
+
diff --git a/src/object/motion/motionbee.h b/src/object/motion/motionbee.h
new file mode 100644
index 0000000..facf650
--- /dev/null
+++ b/src/object/motion/motionbee.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/.
+
+// motionbee.h
+
+#ifndef _MOTIONBEE_H_
+#define _MOTIONBEE_H_
+
+
+#include "motion.h"
+
+
+class CInstanceManager;
+class CEngine;
+class CLight;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CBrain;
+class CPhysics;
+class CObject;
+
+
+#define MB_MARCH 0
+#define MB_SPEC 1
+
+#define MBS_HOLD 0
+#define MBS_BURN 1
+#define MBS_RUIN 2
+
+
+class CMotionBee : public CMotion
+{
+public:
+ CMotionBee(CInstanceManager* iMan, CObject* object);
+ ~CMotionBee();
+
+ void DeleteObject(BOOL bAll=FALSE);
+ BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power);
+ BOOL EventProcess(const Event &event);
+
+protected:
+ void CreatePhysics();
+ BOOL EventFrame(const Event &event);
+
+protected:
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeMarch;
+ float m_armTimeAction;
+ short m_armAngles[3*3*3*3*2];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ BOOL m_bArmStop;
+};
+
+
+#endif //_MOTIONBEE_H_
diff --git a/src/object/motion/motionhuman.cpp b/src/object/motion/motionhuman.cpp
new file mode 100644
index 0000000..78750fa
--- /dev/null
+++ b/src/object/motion/motionhuman.cpp
@@ -0,0 +1,1799 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionhuman.cpp
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "math3d.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "light.h"
+#include "particule.h"
+#include "terrain.h"
+#include "water.h"
+#include "object.h"
+#include "physics.h"
+#include "brain.h"
+#include "camera.h"
+#include "modfile.h"
+#include "robotmain.h"
+#include "sound.h"
+#include "motion.h"
+#include "motionhuman.h"
+
+
+
+#define ADJUST_ANGLE FALSE // TRUE -> adjusts the angles of the members
+#define ADJUST_ACTION (3*3*3*3*MH_SPEC+3*3*3*MHS_SATCOM)
+
+#define START_TIME 1000.0f // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionHuman::CMotionHuman(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ CMotion::CMotion(iMan, object);
+
+ m_partiReactor = -1;
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeSwim = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLastAction = -1;
+ m_bArmStop = FALSE;
+ m_lastSoundMarch = 0.0f;
+ m_lastSoundHhh = 0.0f;
+ m_time = 0.0f;
+ m_tired = 0.0f;
+ m_bDisplayPerso = FALSE;
+}
+
+// Object's constructor.
+
+CMotionHuman::~CMotionHuman()
+{
+}
+
+
+// Removes an object.
+
+void CMotionHuman::DeleteObject(BOOL bAll)
+{
+ if ( m_partiReactor != -1 )
+ {
+ m_particule->DeleteParticule(m_partiReactor);
+ m_partiReactor = -1;
+ }
+}
+
+
+// Starts an action.
+
+Error CMotionHuman::SetAction(int action, float time)
+{
+ CMotion::SetAction(action, time);
+ m_time = 0.0f;
+ return ERR_OK;
+}
+
+
+// Creates cosmonaut on the ground.
+
+BOOL CMotionHuman::Create(D3DVECTOR pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ char filename[100];
+ int rank, option, face, glasses;
+
+ if ( m_engine->RetRestCreate() < 16 ) return FALSE;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+ option = m_object->RetOption();
+
+ if ( m_main->RetGamerOnlyHead() )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+ face = m_main->RetGamerFace();
+ sprintf(filename, "objects\\human2h%d.mod", face+1);
+ pModFile->ReadModel(filename);
+ pModFile->CreateEngineObject(rank);
+
+ glasses = m_main->RetGamerGlasses();
+ if ( glasses != 0 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ sprintf(filename, "objects\\human2g%d.mod", glasses);
+ pModFile->ReadModel(filename);
+ pModFile->CreateEngineObject(rank);
+ }
+
+ CreatePhysics(type);
+ m_object->SetFloorHeight(0.0f);
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return TRUE;
+ }
+
+ // Creates the main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+
+ if ( option == 0 ) // head in helmet?
+ {
+ pModFile->ReadModel("objects\\human1c.mod");
+ }
+ if ( option == 1 ) // head without helmet?
+ {
+ pModFile->ReadModel("objects\\human1h.mod");
+ }
+ if ( option == 2 ) // without a backpack?
+ {
+ pModFile->ReadModel("objects\\human1v.mod");
+ }
+ pModFile->CreateEngineObject(rank);
+
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have an obligatory collision with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 2.0f, SOUND_AIE, 0.20f);
+ m_object->SetGlobalSphere(D3DVECTOR(0.0f, 1.0f, 0.0f), 4.0f);
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+
+ if ( type == OBJECT_HUMAN )
+ {
+ if ( option == 0 ) // head in helmet?
+ {
+ face = m_main->RetGamerFace();
+ sprintf(filename, "objects\\human2c%d.mod", face+1);
+ pModFile->ReadModel(filename);
+ }
+ if ( option == 1 || // head without helmet?
+ option == 2 ) // without a backpack?
+ {
+ face = m_main->RetGamerFace();
+ sprintf(filename, "objects\\human2h%d.mod", face+1);
+ pModFile->ReadModel(filename);
+ }
+ }
+ if ( type == OBJECT_TECH )
+ {
+ pModFile->ReadModel("objects\\human2t.mod");
+ }
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, D3DVECTOR(0.0f, 2.7f, 0.0f));
+ if ( option == 1 || // head without helmet?
+ option == 2 ) // without a backpack?
+ {
+ m_object->SetZoom(1, D3DVECTOR(1.0f, 1.05f, 1.0f));
+ }
+
+ // Creates the glasses.
+ glasses = m_main->RetGamerGlasses();
+ if ( glasses != 0 && type == OBJECT_HUMAN )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(15, rank);
+ m_object->SetObjectParent(15, 1);
+ sprintf(filename, "objects\\human2g%d.mod", glasses);
+ pModFile->ReadModel(filename);
+ pModFile->CreateEngineObject(rank);
+ }
+
+ // Creates the right arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\human3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, D3DVECTOR(0.0f, 2.3f, -1.2f));
+ m_object->SetAngle(2, D3DVECTOR(90.0f*PI/180.0f, 90.0f*PI/180.0f, -50.0f*PI/180.0f));
+
+ // Creates the right forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\human4r.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, D3DVECTOR(1.3f, 0.0f, 0.0f));
+ m_object->SetAngle(3, D3DVECTOR(0.0f*PI/180.0f, -20.0f*PI/180.0f, 0.0f*PI/180.0f));
+
+ // Creates right hand.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 3);
+ pModFile->ReadModel("objects\\human5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, D3DVECTOR(1.2f, 0.0f, 0.0f));
+
+ // Creates the right thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 0);
+ pModFile->ReadModel("objects\\human6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, D3DVECTOR(0.0f, 0.0f, -0.7f));
+ m_object->SetAngle(5, D3DVECTOR(10.0f*PI/180.0f, 0.0f*PI/180.0f, 5.0f*PI/180.0f));
+
+ // Creates the right leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 5);
+ pModFile->ReadModel("objects\\human7.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, D3DVECTOR(0.0f, -1.5f, 0.0f));
+ m_object->SetAngle(6, D3DVECTOR(0.0f*PI/180.0f, 0.0f*PI/180.0f, -10.0f*PI/180.0f));
+
+ // Creates the right foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 6);
+ pModFile->ReadModel("objects\\human8.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, D3DVECTOR(0.0f, -1.5f, 0.0f));
+ m_object->SetAngle(7, D3DVECTOR(-10.0f*PI/180.0f, 5.0f*PI/180.0f, 5.0f*PI/180.0f));
+
+ // Creates the left arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\human3.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, D3DVECTOR(0.0f, 2.3f, 1.2f));
+ m_object->SetAngle(8, D3DVECTOR(-90.0f*PI/180.0f, -90.0f*PI/180.0f, -50.0f*PI/180.0f));
+
+ // Creates the left forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 8);
+ pModFile->ReadModel("objects\\human4l.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, D3DVECTOR(1.3f, 0.0f, 0.0f));
+ m_object->SetAngle(9, D3DVECTOR(0.0f*PI/180.0f, 20.0f*PI/180.0f, 0.0f*PI/180.0f));
+
+ // Creates left hand.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10, rank);
+ m_object->SetObjectParent(10, 9);
+ pModFile->ReadModel("objects\\human5.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10, D3DVECTOR(1.2f, 0.0f, 0.0f));
+
+ // Creates the left thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(11, rank);
+ m_object->SetObjectParent(11, 0);
+ pModFile->ReadModel("objects\\human6.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(11, D3DVECTOR(0.0f, 0.0f, 0.7f));
+ m_object->SetAngle(11, D3DVECTOR(-10.0f*PI/180.0f, 0.0f*PI/180.0f, 5.0f*PI/180.0f));
+
+ // Creates the left leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(12, rank);
+ m_object->SetObjectParent(12, 11);
+ pModFile->ReadModel("objects\\human7.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(12, D3DVECTOR(0.0f, -1.5f, 0.0f));
+ m_object->SetAngle(12, D3DVECTOR(0.0f*PI/180.0f, 0.0f*PI/180.0f, -10.0f*PI/180.0f));
+
+ // Creates the left foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(13, rank);
+ m_object->SetObjectParent(13, 12);
+ pModFile->ReadModel("objects\\human8.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(13, D3DVECTOR(0.0f, -1.5f, 0.0f));
+ m_object->SetAngle(13, D3DVECTOR(10.0f*PI/180.0f, -5.0f*PI/180.0f, 5.0f*PI/180.0f));
+
+ // Creates the neutron gun.
+ if ( option != 2 ) // with backpack?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(14, rank);
+ m_object->SetObjectParent(14, 0);
+ pModFile->ReadModel("objects\\human9.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(14, D3DVECTOR(-1.5f, 0.3f, -1.35f));
+ m_object->SetAngleZ(14, PI);
+ }
+
+ m_object->CreateShadowCircle(2.0f, 0.8f);
+
+ CreatePhysics(type);
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return TRUE;
+}
+
+// Creates the physical object.
+
+void CMotionHuman::CreatePhysics(ObjectType type)
+{
+ Character* character;
+ int i;
+
+ int member_march[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 90,90,-50, 10,0,55, 0,0,0, // t0: arms/thighs/-
+ 0,-20,0, -5,0,-110, 0,0,0, // t0: forearm/legs/-
+ 0,0,0, -5,0,40, 0,0,0, // t0: hands/feet/-
+ // on the ground:
+ 125,115,-45, 10,0,50, 0,0,0, // t1: arms/thighs/-
+ 0,-20,0, -5,0,-15, 0,0,0, // t1: forearm/legs/-
+ 0,0,0, -5,0,0, 0,0,0, // t1: hands/feet/-
+ // on the ground back:
+ 25,55,-40, 10,0,-15, 0,0,0, // t2: arms/thighs/-
+ 30,-50,40, -5,0,-55, 0,0,0, // t2: forearm/legs/-
+ 0,0,0, -5,0,25, 0,0,0, // t2: hands/feet/-
+ };
+
+ int member_march_take[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 15,50,-50, 10,0,55, 0,0,0, // t0: arms/thighs/-
+ 45,-70,10, -5,0,-110, 0,0,0, // t0: forearm/legs/-
+ -10,25,0, -5,0,40, 0,0,0, // t0: hands/feet/-
+ // on the ground:
+ 15,50,-55, 10,0,50, 0,0,0, // t1: arms/thighs/-
+ 45,-70,10, -5,0,-15, 0,0,0, // t1: forearm/legs/-
+ -10,25,0, -5,0,0, 0,0,0, // t1: hands/feet/-
+ // on the ground back:
+ 15,50,-45, 10,0,-15, 0,0,0, // t2: arms/thighs/-
+ 45,-70,10, -5,0,-55, 0,0,0, // t2: forearm/legs/-
+ -10,25,0, -5,0,45, 0,0,0, // t2: hands/feet/-
+ };
+
+ int member_turn[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 90,90,-50, 10,0,30, 0,0,0, // t0: arms/thighs/-
+ 0,-20,0, -5,0,-60, 0,0,0, // t0: forearm/legs/-
+ 0,0,0, -5,0,30, 0,0,0, // t0: hands/feet/-
+ // on the ground:
+ 90,110,-45, 10,0,0, 0,0,0, // t1: arms/thighs/-
+ 0,-20,0, -5,5,0, 0,0,0, // t1: forearm/legs/-
+ 0,0,0, -5,10,0, 0,0,0, // t1: hands/feet/-
+ // on the ground back:
+ 90,70,-45, 10,0,0, 0,0,0, // t2: arms/thighs/-
+ 0,-20,10, -5,-5,0, 0,0,0, // t2: forearm/legs/-
+ 0,0,0, -5,-10,0, 0,0,0, // t2: hands/feet/-
+ };
+
+ int member_stop[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3,
+ 90,90,-50, 10,0,5, 0,0,0, // arms/thighs/-
+ 0,-20,0, 0,0,-10, 0,0,0, // forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // hands/feet/-
+ //
+ 90,90,-55, 10,0,5, 0,0,0, // arms/thighs/-
+ 0,-15,0, 0,0,-10, 0,0,0, // forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // hands/feet/-
+ //
+ 90,90,-60, 10,0,5, 0,0,0, // arms/thighs/-
+ 0,-10,0, 0,0,-10, 0,0,0, // forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // hands/feet/-
+ };
+
+ int member_fly[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3,
+ -5,90,-60, 20,5,-25, 0,0,0, // arms/thighs/-
+ 85,-40,-25, 10,0,-30, 0,0,0, // forearm/legs/-
+ 40,10,25, 0,15,0, 0,0,0, // hands/feet/-
+ //
+ -15,90,-40, 20,5,-35, 0,0,0, // arms/thighs/-
+ 85,-40,-25, 10,0,-40, 0,0,0, // forearm/legs/-
+ 45,5,20, 0,15,0, 0,0,0, // hands/feet/-
+ //
+ -25,90,-50, 20,5,-20, 0,0,0, // arms/thighs/-
+ 85,-40,-25, 10,0,-10, 0,0,0, // forearm/legs/-
+ 30,15,25, 0,15,0, 0,0,0, // hands/feet/-
+ };
+
+ int member_swim[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3,
+#if 1
+ 130,-70,200, 10,20,55, 0,0,0, // arms/thighs/-
+ 115,-125,0, -5,0,-110, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,10,-5, 0,0,0, // hands/feet/-
+ //
+ 130,-95,115,55,5,5, 0,0,0, // arms/thighs/-
+ 75,-50,25, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,5,-30, 0,0,0, // hands/feet/-
+ //
+ 130,-100,220,5,0,0, 0,0,0, // arms/thighs/-
+ 150,5,0, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,30,-20, 0,0,0, // hands/feet/-
+#endif
+#if 0
+ 130,-70,200,5,0,0, 0,0,0, // arms/thighs/-
+ 115,-125,0, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,30,-20, 0,0,0, // hands/feet/-
+ //
+ 130,-95,115, 10,20,55, 0,0,0, // arms/thighs/-
+ 75,-50,25, -5,0,-110, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,10,-5, 0,0,0, // hands/feet/-
+ //
+ 130,-100,220, 55,5,5, 0,0,0, // arms/thighs/-
+ 150,5,0, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,5,-30, 0,0,0, // hands/feet/-
+#endif
+#if 0
+ 130,-70,200, 55,5,5, 0,0,0, // arms/thighs/-
+ 115,-125,0, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,5,-30, 0,0,0, // hands/feet/-
+ //
+ 130,-95,115, 5,0,0, 0,0,0, // arms/thighs/-
+ 75,-50,25, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,30,-20, 0,0,0, // hands/feet/-
+ //
+ 130,-100,220, 10,20,55, 0,0,0, // arms/thighs/-
+ 150,5,0, -5,0,-110, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,10,-5, 0,0,0, // hands/feet/-
+#endif
+ };
+
+ int member_spec[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // shooting:
+ 65,5,-20, 10,0,40, 0,0,0, // s0: arms/thighs/-
+ -50,-30,50, 0,0,-70, 0,0,0, // s0: forearm/legs/-
+ 0,50,0, -10,0,35, 0,0,0, // s0: hands/feet/-
+ // takes weapon:
+ 160,135,-20,10,0,5, 0,0,0, // s1: arms/thighs/-
+ 10,-60,40, 0,0,-10, 0,0,0, // s1: forearm/legs/-
+ 0,-5,-25, -10,5,5, 0,0,0, // s1: hands/feet/-
+ // carries earth:
+ 25,40,-40, 10,0,60, 0,0,0, // s2: arms/thighs/-
+ 0,-45,0, 0,0,-120, 0,0,0, // s2: forearm/legs/-
+ 0,15,5, -10,0,70, 0,0,0, // s2: hands/feet/-
+ // carries in front:
+ 25,20,5, 10,0,55, 0,0,0, // s3: arms/thighs/-
+ -15,-30,10, 0,0,-110, 0,0,0, // s3: forearm/legs/-
+ 0,0,0, -10,0,65, 0,0,0, // s3: hands/feet/-
+ // carries vertically:
+ -30,15,-5, 10,0,15, 0,0,0, // s4: arms/thighs/-
+ 0,-15,15, 0,0,-30, 0,0,0, // s4: forearm/legs/-
+ 35,0,-15, -10,0,25, 0,0,0, // s4: hands/feet/-
+ // rises:
+ 15,50,-50, 10,0,5, 0,0,0, // s5: arms/thighs/-
+ 45,-70,10, 0,0,-10, 0,0,0, // s5: forearm/legs/-
+ -10,25,0, -10,5,5, 0,0,0, // s5: hands/feet/-
+ // wins:
+ 90,90,-30, 20,0,5, 0,0,0, // s6: arms/thighs/-
+ 0,-90,0, -10,0,-10, 0,0,0, // s6: forearm/legs/-
+ 0,25,0, -10,5,5, 0,0,0, // s6: hands/feet/-
+ // lose:
+ -70,45,35, 10,0,40, 0,0,0, // s7: arms/thighs/-
+ 15,-95,-5, 0,0,-70, 0,0,0, // s7: forearm/legs/-
+ 0,0,0, -10,0,35, 0,0,0, // s7: hands/feet/-
+ // shooting death (falls):
+ 90,90,-50, 10,0,5, 0,0,0, // s8: arms/thighs/-
+ 0,-20,0, 0,0,-10, 0,0,0, // s8: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s8: hands/feet/-
+ // shooting death (knees):
+ 110,105,-5, 10,0,25, 0,0,0, // s9: arms/thighs/-
+ 0,-40,20, 0,0,-120, 0,0,0, // s9: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s9: hands/feet/-
+ // shooting death (knees):
+ 110,120,-25, 10,0,25, 0,0,0, // s10: arms/thighs/-
+ 0,-40,20, 0,0,-120, 0,0,0, // s10: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s10: hands/feet/-
+ // shooting death (face down):
+ 110,100,-25, 25,0,10, 0,0,0, // s11: arms/thighs/-
+ 0,-40,20, 0,0,-25, 0,0,0, // s11: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s11: hands/feet/-
+ // shooting death (face down):
+ 110,100,-25, 25,0,10, 0,0,0, // s12: arms/thighs/-
+ 0,-40,20, 0,0,-25, 0,0,0, // s12: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s12: hands/feet/-
+ // drowned:
+ 110,100,-25, 25,0,10, 0,0,0, // s13: arms/thighs/-
+ 0,-40,20, 0,0,-25, 0,0,0, // s13: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s13: hands/feet/-
+ // puts / removes flag:
+ 85,45,-50, 10,0,60, 0,0,0, // s14: arms/thighs/-
+ -60,15,65, 0,0,-105, 0,0,0, // s14: forearm/legs/-
+ 0,10,0, -10,0,60, 0,0,0, // s14: hands/feet/-
+ // reads SatCom:
+ 70,30,-20, 10,0,5, 0,0,0, // s15: arms/thighs/-
+ 115,-65,60, 0,0,-10, 0,0,0, // s15: forearm/legs/-
+ 0,20,0, -10,5,5, 0,0,0, // s15: hands/feet/-
+ };
+
+ m_physics->SetType(TYPE_FLYING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.0f;
+ character->wheelRight = 4.0f;
+ character->height = 3.5f;
+
+ if ( type == OBJECT_HUMAN )
+ {
+ m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 35.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 70.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 40.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+ m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
+ m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 6.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 6.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 4.0f);
+ }
+ else
+ {
+ m_physics->SetLinMotionX(MO_ADVSPEED, 40.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 8.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 8.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 8.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+ m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
+ m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.6f*PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.6f*PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 4.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 4.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 3.0f);
+ }
+
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_MARCH+i] = member_march[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_MARCHTAKE+i] = member_march_take[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_TURN+i] = member_turn[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_STOP+i] = member_stop[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_FLY+i] = member_fly[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_SWIM+i] = member_swim[i];
+ }
+ for ( i=0 ; i<3*3*3*16 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_SPEC+i] = member_spec[i];
+ }
+}
+
+
+// Management of an event.
+
+BOOL CMotionHuman::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if ADJUST_ANGLE
+ int i;
+
+ if ( event.param == 'A' ) m_armTimeIndex++;
+ if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
+
+ if ( event.param == 'Q' ) m_armPartIndex++;
+ if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
+
+ if ( event.param == 'W' ) m_armMemberIndex++;
+ if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
+
+ i = m_armMemberIndex*3;
+ i += m_armPartIndex*3*3;
+ i += m_armTimeIndex*3*3*3;
+ i += ADJUST_ACTION;
+
+ if ( event.param == 'E' ) m_armAngles[i+0] += 5;
+ if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
+ if ( event.param == 'R' ) m_armAngles[i+1] += 5;
+ if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
+ if ( event.param == 'T' ) m_armAngles[i+2] += 5;
+ if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
+
+ if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
+
+ if ( event.param == 'Y' )
+ {
+ char s[100];
+ sprintf(s, "index dans table = %d %d %d\n", i, i+9, i+18);
+ OutputDebugString(s);
+ }
+#endif
+ }
+
+ return TRUE;
+}
+
+// Calculates a value (radians) proportional between a and b (degrees).
+
+inline float Propf(float a, float b, float p)
+{
+ float aa, bb;
+
+ aa = a*PI/180.0f;
+ bb = b*PI/180.0f;
+
+ return aa+p*(bb-aa);
+}
+
+// Management of an event.
+
+BOOL CMotionHuman::EventFrame(const Event &event)
+{
+ D3DMATRIX* mat;
+ D3DVECTOR dir, actual, pos, speed, pf;
+ FPOINT center, dim, p2;
+ float s, a, prog, rTime[2], lTime[2], time, rot, hr, hl;
+ float al, ar, af;
+ float tSt[9], tNd[9];
+ float aa, bb, shield, deadFactor, level;
+ int i, ii, st, nd, action, legAction, armAction;
+ BOOL bOnBoard, bSwim, bStop;
+
+ if ( m_engine->RetPause() )
+ {
+ if ( m_actionType == MHS_SATCOM )
+ {
+ m_progress += event.rTime*m_actionTime;
+ }
+ else
+ {
+ return TRUE;
+ }
+ }
+
+ bOnBoard = FALSE;
+ if ( m_object->RetSelect() &&
+ m_camera->RetType() == CAMERA_ONBOARD )
+ {
+ bOnBoard = TRUE;
+ }
+
+ if ( m_bDisplayPerso && m_main->RetGamerOnlyHead() )
+ {
+ m_time += event.rTime;
+ m_object->SetLinVibration(D3DVECTOR(0.0f, -0.55f, 0.0f));
+ m_object->SetCirVibration(D3DVECTOR(0.0f, m_main->RetPersoAngle(), 0.0f));
+ return TRUE;
+ }
+ if ( m_bDisplayPerso )
+ {
+ m_object->SetCirVibration(D3DVECTOR(0.0f, m_main->RetPersoAngle()+0.2f, 0.0f));
+ }
+
+ shield = m_object->RetShield();
+ shield += event.rTime*(1.0f/120.0f); // regeneration in 120 seconds
+ if ( shield > 1.0f ) shield = 1.0f;
+ m_object->SetShield(shield);
+
+ bSwim = m_physics->RetSwim();
+
+#if 0
+ rot = m_physics->RetCirMotionY(MO_MOTSPEED);
+ s = m_physics->RetLinMotionX(MO_REASPEED)*2.0f;
+ a = m_physics->RetLinMotionX(MO_TERSPEED);
+ if ( a < 0.0f ) // rises?
+ {
+ if ( s > 0.0f && s < 20.0f ) s = 20.0f; // moving slowly?
+//? if ( s < 0.0f && s > -10.0f ) s = 0.0f; // falling slowly?
+ }
+ if ( a > 0.0f && !bSwim ) // falls?
+ {
+ if ( s > 0.0f && s < 10.0f ) s = 0.0f; // moving slowly?
+//? if ( s < 0.0f && s > -5.0f ) s = -5.0f; // falling slowly?
+ }
+ a = Abs(rot*12.0f);
+
+ if ( !m_physics->RetLand() && !bSwim ) // in flight?
+ {
+ s = 0.0f;
+ }
+
+ if ( m_object->RetFret() != 0 ) // carries something?
+ {
+ s *= 1.3f;
+ }
+#else
+ rot = m_physics->RetCirMotionY(MO_MOTSPEED);
+#if 0
+ s = m_physics->RetLinMotionX(MO_REASPEED);
+#else
+ a = m_physics->RetLinMotionX(MO_REASPEED);
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.2f;
+ if ( Abs(a) > Abs(s) ) s = a; // the highest value
+#endif
+ a = m_physics->RetLinMotionX(MO_TERSPEED);
+ if ( a < 0.0f ) // rises?
+ {
+ a += m_physics->RetLinMotionX(MO_TERSLIDE);
+ if ( a < 0.0f ) s -= a;
+ }
+ if ( a > 0.0f ) // falls?
+ {
+ a -= m_physics->RetLinMotionX(MO_TERSLIDE);
+ if ( a > 0.0f ) s -= a;
+ }
+ s *= 2.0f;
+ a = Abs(rot*12.0f);
+
+ if ( !m_physics->RetLand() && !bSwim ) // in flight?
+ {
+ s = 0.0f;
+ }
+
+ if ( m_object->RetFret() != 0 ) // carries something?
+ {
+ s *= 1.3f;
+ }
+#endif
+
+ m_time += event.rTime;
+ m_armTimeAbs += event.rTime;
+ m_armTimeAction += event.rTime;
+ m_armMember += s*event.rTime*0.05f;
+
+ // Fatigue management when short.
+ if ( m_physics->RetLand() && s != 0.0f ) // on the ground?
+ {
+ m_tired += event.rTime*0.1f;
+ if ( m_tired > 1.0f )
+ {
+ m_tired = 1.0f;
+ if ( m_lastSoundHhh > 3.0f ) m_lastSoundHhh = 0.5f;
+ }
+ }
+ else
+ {
+ m_tired -= event.rTime*0.2f;
+ if ( m_tired < 0.0f ) m_tired = 0.0f;
+ }
+
+ if ( bSwim ) // swims?
+ {
+ s += Abs(m_physics->RetLinMotionY(MO_REASPEED)*2.0f);
+ a *= 2.0f;
+ m_armTimeSwim += Min(Max(s,a,3.0f),15.0f)*event.rTime*0.05f;
+ }
+
+ bStop = ( s == 0.0f ); // stop?
+ prog = 0.0f;
+
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ if ( s == 0.0f && a == 0.0f )
+ {
+ action = MH_STOP; // stop
+ rTime[0] = rTime[1] = m_armTimeAbs*0.21f;
+ lTime[0] = lTime[1] = m_armTimeAbs*0.25f;
+ m_armMember = START_TIME;
+ }
+ else
+ {
+ if ( s == 0.0f )
+ {
+ action = MH_TURN; // turn
+ rTime[0] = rTime[1] = m_armTimeAbs;
+ lTime[0] = lTime[1] = m_armTimeAbs+0.5f;
+ if ( rot < 0.0f )
+ {
+ rTime[1] = 1000000.0f-rTime[1];
+ }
+ else
+ {
+ lTime[1] = 1000000.0f-lTime[1];
+ }
+ m_armMember = START_TIME;
+ }
+ else
+ {
+ action = MH_MARCH; // walking
+ if ( m_object->RetFret() != 0 ) action = MH_MARCHTAKE; // take walking
+ rTime[0] = rTime[1] = m_armMember;
+ lTime[0] = lTime[1] = m_armMember+0.5f;
+ }
+ }
+ if ( bSwim )
+ {
+ rTime[0] *= 0.6f;
+ rTime[1] *= 0.6f;
+ lTime[0] = rTime[0]+0.5f;
+ lTime[1] = rTime[1]+0.5f;
+ }
+ }
+ else
+ {
+ if ( bSwim )
+ {
+ action = MH_SWIM; // swim
+ rTime[0] = rTime[1] = m_armTimeSwim;
+ lTime[0] = lTime[1] = m_armTimeSwim;
+ }
+ else
+ {
+ action = MH_FLY; // fly
+ rTime[0] = rTime[1] = m_armTimeAbs*0.30f;
+ lTime[0] = lTime[1] = m_armTimeAbs*0.31f;
+ m_armMember = START_TIME;
+ }
+ }
+
+ if ( action != m_armLastAction )
+ {
+ m_armLastAction = action;
+ m_armTimeAction = 0.0f;
+ }
+
+ armAction = action;
+ legAction = action;
+
+ if ( m_object->RetFret() != 0 ) // carries something?
+ {
+ armAction = MH_MARCHTAKE; // take walking
+ }
+
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ a = m_object->RetAngleY(0);
+ pos = m_object->RetPosition(0);
+ m_terrain->MoveOnFloor(pos);
+
+ pf.x = pos.x+cosf(a+PI*1.5f)*0.7f;
+ pf.y = pos.y;
+ pf.z = pos.z-sinf(a+PI*1.5f)*0.7f;
+ m_terrain->MoveOnFloor(pf);
+ al = atanf((pf.y-pos.y)/0.7f); // angle for left leg
+
+ pf = pos;
+ pf.x = pos.x+cosf(a+PI*0.5f)*0.7f;
+ pf.y = pos.y;
+ pf.z = pos.z-sinf(a+PI*0.5f)*0.7f;
+ m_terrain->MoveOnFloor(pf);
+ ar = atanf((pf.y-pos.y)/0.7f); // angle to right leg
+
+ pf.x = pos.x+cosf(a+PI)*0.3f;
+ pf.y = pos.y;
+ pf.z = pos.z-sinf(a+PI)*0.3f;
+ m_terrain->MoveOnFloor(pf);
+ af = atanf((pf.y-pos.y)/0.3f); // angle for feet
+ }
+ else
+ {
+ al = 0.0f;
+ ar = 0.0f;
+ af = 0.0f;
+ }
+
+ for ( i=0 ; i<4 ; i++ ) // 4 members
+ {
+ if ( m_bArmStop ) // focus?
+ {
+ st = ADJUST_ACTION + (i%2)*3;
+ nd = st;
+ time = 100.0f;
+ m_armTimeAction = 0.0f;
+ }
+ else if ( m_actionType != -1 ) // special action in progress?
+ {
+ st = 3*3*3*3*MH_SPEC + 3*3*3*m_actionType + (i%2)*3;
+ nd = st;
+ time = event.rTime*m_actionTime;
+ m_armTimeAction = 0.0f;
+ }
+ else
+ {
+ if ( i < 2 ) prog = Mod(rTime[i%2], 1.0f);
+ else prog = Mod(lTime[i%2], 1.0f);
+ if ( prog < 0.25f ) // t0..t1 ?
+ {
+ prog = prog/0.25f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.75f ) // t1..t2 ?
+ {
+ prog = (prog-0.25f)/0.50f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.75f)/0.25f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ if ( i%2 == 0 ) // arm?
+ {
+ st = 3*3*3*3*armAction + st*3*3*3 + (i%2)*3;
+ nd = 3*3*3*3*armAction + nd*3*3*3 + (i%2)*3;
+ }
+ else // leg?
+ {
+ st = 3*3*3*3*legAction + st*3*3*3 + (i%2)*3;
+ nd = 3*3*3*3*legAction + nd*3*3*3 + (i%2)*3;
+ }
+
+ // Less soft ...
+ time = event.rTime*(5.0f+Min(m_armTimeAction*50.0f, 100.0f));
+ if ( bSwim ) time *= 0.25f;
+ }
+
+ tSt[0] = m_armAngles[st+ 0]; // x
+ tSt[1] = m_armAngles[st+ 1]; // y
+ tSt[2] = m_armAngles[st+ 2]; // z
+ tSt[3] = m_armAngles[st+ 9]; // x
+ tSt[4] = m_armAngles[st+10]; // y
+ tSt[5] = m_armAngles[st+11]; // z
+ tSt[6] = m_armAngles[st+18]; // x
+ tSt[7] = m_armAngles[st+19]; // y
+ tSt[8] = m_armAngles[st+20]; // z
+
+ tNd[0] = m_armAngles[nd+ 0]; // x
+ tNd[1] = m_armAngles[nd+ 1]; // y
+ tNd[2] = m_armAngles[nd+ 2]; // z
+ tNd[3] = m_armAngles[nd+ 9]; // x
+ tNd[4] = m_armAngles[nd+10]; // y
+ tNd[5] = m_armAngles[nd+11]; // z
+ tNd[6] = m_armAngles[nd+18]; // x
+ tNd[7] = m_armAngles[nd+19]; // y
+ tNd[8] = m_armAngles[nd+20]; // z
+
+ aa = 0.5f;
+ if ( i%2 == 0 ) // arm?
+ {
+ if ( m_object->RetFret() == 0 ) // does nothing?
+ {
+ aa = 2.0f; // moves a lot
+ }
+ else
+ {
+ aa = 0.0f; // immobile
+ }
+ }
+
+ if ( i < 2 ) // left?
+ {
+ bb = sinf(m_time*1.1f)*aa; tSt[0] += bb; tNd[0] += bb;
+ bb = sinf(m_time*1.0f)*aa; tSt[1] += bb; tNd[1] += bb;
+ bb = sinf(m_time*1.2f)*aa; tSt[2] += bb; tNd[2] += bb;
+ bb = sinf(m_time*2.5f)*aa; tSt[3] += bb; tNd[3] += bb;
+ bb = sinf(m_time*2.0f)*aa; tSt[4] += bb; tNd[4] += bb;
+ bb = sinf(m_time*3.8f)*aa; tSt[5] += bb; tNd[5] += bb;
+ bb = sinf(m_time*3.0f)*aa; tSt[6] += bb; tNd[6] += bb;
+ bb = sinf(m_time*2.3f)*aa; tSt[7] += bb; tNd[7] += bb;
+ bb = sinf(m_time*4.0f)*aa; tSt[8] += bb; tNd[8] += bb;
+ }
+ else // right?
+ {
+ bb = sinf(m_time*0.9f)*aa; tSt[0] += bb; tNd[0] += bb;
+ bb = sinf(m_time*1.2f)*aa; tSt[1] += bb; tNd[1] += bb;
+ bb = sinf(m_time*1.4f)*aa; tSt[2] += bb; tNd[2] += bb;
+ bb = sinf(m_time*2.9f)*aa; tSt[3] += bb; tNd[3] += bb;
+ bb = sinf(m_time*1.4f)*aa; tSt[4] += bb; tNd[4] += bb;
+ bb = sinf(m_time*3.1f)*aa; tSt[5] += bb; tNd[5] += bb;
+ bb = sinf(m_time*3.7f)*aa; tSt[6] += bb; tNd[6] += bb;
+ bb = sinf(m_time*2.0f)*aa; tSt[7] += bb; tNd[7] += bb;
+ bb = sinf(m_time*3.1f)*aa; tSt[8] += bb; tNd[8] += bb;
+ }
+
+#if 1
+ if ( i%2 == 1 && // leg?
+ m_actionType == -1 ) // no special action?
+ {
+ if ( i == 1 ) // right leg?
+ {
+ ii = 5;
+ a = ar*0.25f;
+ }
+ else
+ {
+ ii = 11;
+ a = al*0.25f;
+ }
+ if ( a < -0.2f ) a = -0.2f;
+ if ( a > 0.2f ) a = 0.2f;
+
+ pos = m_object->RetPosition(ii+0);
+ pos.y = 0.0f+a;
+ m_object->SetPosition(ii+0, pos); // lengthens / shortcuts thigh
+
+ pos = m_object->RetPosition(ii+1);
+ pos.y = -1.5f+a;
+ m_object->SetPosition(ii+1, pos); // lengthens / shortcuts leg
+
+ pos = m_object->RetPosition(ii+2);
+ pos.y = -1.5f+a;
+ m_object->SetPosition(ii+2, pos); // lengthens / shortcuts foot
+
+ if ( i == 1 ) // right leg?
+ {
+ aa = (ar*180.0f/PI*0.5f);
+ }
+ else // left leg?
+ {
+ aa = (al*180.0f/PI*0.5f);
+ }
+ tSt[6] += aa;
+ tNd[6] += aa; // increases the angle X of the foot
+
+ if ( i == 1 ) // right leg?
+ {
+ aa = (ar*180.0f/PI);
+ }
+ else // left leg?
+ {
+ aa = (al*180.0f/PI);
+ }
+ if ( aa < 0.0f ) aa = 0.0f;
+ if ( aa > 30.0f ) aa = 30.0f;
+
+ tSt[2] += aa;
+ tNd[2] += aa; // increases the angle Z of the thigh
+ tSt[5] -= aa*2;
+ tNd[5] -= aa*2; // increases the angle Z of the leg
+ tSt[8] += aa;
+ tNd[8] += aa; // increases the angle Z of the foot
+
+ aa = (af*180.0f/PI)*0.7f;
+ if ( aa < -30.0f ) aa = -30.0f;
+ if ( aa > 30.0f ) aa = 30.0f;
+
+ tSt[8] -= aa;
+ tNd[8] -= aa; // increases the angle Z of the foot
+ }
+#endif
+
+ if ( m_actionType == MHS_DEADw ) // drowned?
+ {
+ if ( m_progress < 0.5f )
+ {
+ deadFactor = m_progress/0.5f;
+ }
+ else
+ {
+ deadFactor = 1.0f-(m_progress-0.5f)/0.5f;
+ }
+ if ( deadFactor < 0.0f ) deadFactor = 0.0f;
+ if ( deadFactor > 1.0f ) deadFactor = 1.0f;
+
+ for ( ii=0 ; ii<9 ; ii++ )
+ {
+ tSt[ii] += Rand()*20.0f*deadFactor;
+ tNd[ii] = tSt[ii];
+ }
+ time = 100.0f;
+ }
+
+ if ( i < 2 ) // right member (0..1) ?
+ {
+ m_object->SetAngleX(2+3*i+0, Smooth(m_object->RetAngleX(2+3*i+0), Propf(tSt[0], tNd[0], prog), time));
+ m_object->SetAngleY(2+3*i+0, Smooth(m_object->RetAngleY(2+3*i+0), Propf(tSt[1], tNd[1], prog), time));
+ m_object->SetAngleZ(2+3*i+0, Smooth(m_object->RetAngleZ(2+3*i+0), Propf(tSt[2], tNd[2], prog), time));
+ m_object->SetAngleX(2+3*i+1, Smooth(m_object->RetAngleX(2+3*i+1), Propf(tSt[3], tNd[3], prog), time));
+ m_object->SetAngleY(2+3*i+1, Smooth(m_object->RetAngleY(2+3*i+1), Propf(tSt[4], tNd[4], prog), time));
+ m_object->SetAngleZ(2+3*i+1, Smooth(m_object->RetAngleZ(2+3*i+1), Propf(tSt[5], tNd[5], prog), time));
+ m_object->SetAngleX(2+3*i+2, Smooth(m_object->RetAngleX(2+3*i+2), Propf(tSt[6], tNd[6], prog), time));
+ m_object->SetAngleY(2+3*i+2, Smooth(m_object->RetAngleY(2+3*i+2), Propf(tSt[7], tNd[7], prog), time));
+ m_object->SetAngleZ(2+3*i+2, Smooth(m_object->RetAngleZ(2+3*i+2), Propf(tSt[8], tNd[8], prog), time));
+ }
+ else // left member (2..3) ?
+ {
+ m_object->SetAngleX(2+3*i+0, Smooth(m_object->RetAngleX(2+3*i+0), Propf(-tSt[0], -tNd[0], prog), time));
+ m_object->SetAngleY(2+3*i+0, Smooth(m_object->RetAngleY(2+3*i+0), Propf(-tSt[1], -tNd[1], prog), time));
+ m_object->SetAngleZ(2+3*i+0, Smooth(m_object->RetAngleZ(2+3*i+0), Propf( tSt[2], tNd[2], prog), time));
+ m_object->SetAngleX(2+3*i+1, Smooth(m_object->RetAngleX(2+3*i+1), Propf(-tSt[3], -tNd[3], prog), time));
+ m_object->SetAngleY(2+3*i+1, Smooth(m_object->RetAngleY(2+3*i+1), Propf(-tSt[4], -tNd[4], prog), time));
+ m_object->SetAngleZ(2+3*i+1, Smooth(m_object->RetAngleZ(2+3*i+1), Propf( tSt[5], tNd[5], prog), time));
+ m_object->SetAngleX(2+3*i+2, Smooth(m_object->RetAngleX(2+3*i+2), Propf(-tSt[6], -tNd[6], prog), time));
+ m_object->SetAngleY(2+3*i+2, Smooth(m_object->RetAngleY(2+3*i+2), Propf(-tSt[7], -tNd[7], prog), time));
+ m_object->SetAngleZ(2+3*i+2, Smooth(m_object->RetAngleZ(2+3*i+2), Propf( tSt[8], tNd[8], prog), time));
+ }
+ }
+
+#if ADJUST_ANGLE
+ if ( m_object->RetSelect() )
+ {
+ char s[100];
+ sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
+ m_engine->SetInfoText(4, s);
+ }
+#endif
+
+ // calculates the height lowering as a function
+ // of the position of the legs.
+ hr = 1.5f*(1.0f-cosf(m_object->RetAngleZ(5))) +
+ 1.5f*(1.0f-cosf(m_object->RetAngleZ(5)+m_object->RetAngleZ(6)));
+ a = 1.0f*sinf(m_object->RetAngleZ(5)+m_object->RetAngleZ(6)+m_object->RetAngleZ(7));
+ if ( a < 0.0f ) hr += a;
+
+ hl = 1.5f*(1.0f-cosf(m_object->RetAngleZ(11))) +
+ 1.5f*(1.0f-cosf(m_object->RetAngleZ(11)+m_object->RetAngleZ(12)));
+ a = 1.0f*sinf(m_object->RetAngleZ(11)+m_object->RetAngleZ(12)+m_object->RetAngleZ(13));
+ if ( a < 0.0f ) hl += a;
+
+ hr = Min(hr, hl);
+
+ if ( m_actionType == MHS_FIRE ) // shooting?
+ {
+ time = event.rTime*m_actionTime;
+
+ dir.x = (Rand()-0.5f)/8.0f;
+ dir.z = (Rand()-0.5f)/8.0f;
+ dir.y = -0.5f; // slightly lower
+ actual = m_object->RetLinVibration();
+ dir.x = Smooth(actual.x, dir.x, time);
+//? dir.y = Smooth(actual.y, dir.y, time);
+ dir.y = -hr;
+ dir.z = Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = (Rand()-0.5f)/3.0f;
+ dir.z = -0.1f; // slightly leaning forward
+ actual = m_object->RetInclinaison();
+ dir.x = Smooth(actual.x, dir.x, time);
+ dir.y = Smooth(actual.y, dir.y, time);
+ dir.z = Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_TAKE || // carrying?
+ m_actionType == MHS_TAKEOTHER ) // flag?
+ {
+ time = event.rTime*m_actionTime*2.0f;
+
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = -1.5f; // slightly lower
+ actual = m_object->RetLinVibration();
+ dir.x = Smooth(actual.x, dir.x, time);
+//? dir.y = Smooth(actual.y, dir.y, time);
+ dir.y = -hr;
+ dir.z = Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = -0.2f;
+ actual = m_object->RetInclinaison();
+ dir.x = Smooth(actual.x, dir.x, time);
+ dir.y = Smooth(actual.y, dir.y, time);
+ dir.z = Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_TAKEHIGH ) // carrying?
+ {
+ time = event.rTime*m_actionTime*2.0f;
+
+ dir.x = 0.4f; // slightly forward
+ dir.z = 0.0f;
+ dir.y = 0.0f;
+ actual = m_object->RetLinVibration();
+ dir.x = Smooth(actual.x, dir.x, time);
+//? dir.y = Smooth(actual.y, dir.y, time);
+ dir.y = -hr;
+ dir.z = Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = -0.2f;
+ actual = m_object->RetInclinaison();
+ dir.x = Smooth(actual.x, dir.x, time);
+ dir.y = Smooth(actual.y, dir.y, time);
+ dir.z = Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_FLAG ) // flag?
+ {
+ time = event.rTime*m_actionTime*2.0f;
+
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = -2.0f; // slightly lower
+ actual = m_object->RetLinVibration();
+ dir.x = Smooth(actual.x, dir.x, time);
+//? dir.y = Smooth(actual.y, dir.y, time);
+ dir.y = -hr;
+ dir.z = Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = -0.4f;
+ actual = m_object->RetInclinaison();
+ dir.x = Smooth(actual.x, dir.x, time);
+ dir.y = Smooth(actual.y, dir.y, time);
+ dir.z = Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_DEADg ) // shooting death (falls)?
+ {
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ SetAction(MHS_DEADg1, 0.5f); // knees
+ }
+ }
+ else if ( m_actionType == MHS_DEADg1 ) // shooting death (knees)?
+ {
+ prog = m_progress;
+ if ( prog >= 1.0f )
+ {
+ prog = 1.0f;
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += (Rand()-0.5f)*4.0f;
+ pos.z += (Rand()-0.5f)*4.0f;
+ m_terrain->MoveOnFloor(pos);
+ speed = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ dim.x = 1.2f+Rand()*1.2f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f);
+ }
+ m_sound->Play(SOUND_BOUMv, m_object->RetPosition(0));
+
+ SetAction(MHS_DEADg2, 1.0f); // expects knees
+ }
+
+ time = 100.0f;
+
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = -1.5f*prog;
+ actual = m_object->RetLinVibration();
+ dir.x = Smooth(actual.x, dir.x, time);
+ dir.y = Smooth(actual.y, dir.y, time);
+ dir.z = Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = -(20.0f*PI/180.0f)*prog;
+ actual = m_object->RetInclinaison();
+ dir.x = Smooth(actual.x, dir.x, time);
+ dir.y = Smooth(actual.y, dir.y, time);
+ dir.z = Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_DEADg2 ) // shooting death (knees)?
+ {
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(MHS_DEADg3, 1.0f); // face down
+ }
+
+ time = 100.0f;
+
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = -1.5f;
+ actual = m_object->RetLinVibration();
+ dir.x = Smooth(actual.x, dir.x, time);
+ dir.y = Smooth(actual.y, dir.y, time);
+ dir.z = Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = -(20.0f*PI/180.0f);
+ actual = m_object->RetInclinaison();
+ dir.x = Smooth(actual.x, dir.x, time);
+ dir.y = Smooth(actual.y, dir.y, time);
+ dir.z = Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_DEADg3 ) // shooting death (face down)?
+ {
+ prog = m_progress;
+ if ( prog >= 1.0f )
+ {
+ prog = 1.0f;
+
+ for ( i=0 ; i<20 ; i++ )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += (Rand()-0.5f)*8.0f;
+ pos.z += (Rand()-0.5f)*8.0f;
+ m_terrain->MoveOnFloor(pos);
+ speed = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ dim.x = 2.0f+Rand()*1.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f);
+ }
+ m_sound->Play(SOUND_BOUMv, m_object->RetPosition(0));
+
+ SetAction(MHS_DEADg4, 3.0f); // expects face down
+ }
+
+ time = 100.0f;
+ prog = powf(prog, 3.0f);
+
+ dir.y = -(1.5f+1.5f*prog);
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ actual = m_object->RetLinVibration();
+ dir.x = Smooth(actual.x, dir.x, time);
+ dir.y = Smooth(actual.y, dir.y, time);
+ dir.z = Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.z = -((20.0f*PI/180.0f)+(70.0f*PI/180.0f)*prog);
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ actual = m_object->RetInclinaison();
+ dir.x = Smooth(actual.x, dir.x, time);
+ dir.y = Smooth(actual.y, dir.y, time);
+ dir.z = Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_DEADg4 ) // shooting death (face down)?
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_object->SetEnable(FALSE);
+ }
+
+ time = 100.0f;
+
+ dir.y = -(1.5f+1.5f);
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ actual = m_object->RetLinVibration();
+ dir.x = Smooth(actual.x, dir.x, time);
+ dir.y = Smooth(actual.y, dir.y, time);
+ dir.z = Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.z = -((20.0f*PI/180.0f)+(70.0f*PI/180.0f));
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ actual = m_object->RetInclinaison();
+ dir.x = Smooth(actual.x, dir.x, time);
+ dir.y = Smooth(actual.y, dir.y, time);
+ dir.z = Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_DEADw ) // drowned?
+ {
+ pos = m_object->RetPosition(0);
+ level = m_water->RetLevel()-0.5f;
+ if ( pos.y < level )
+ {
+ pos.y += 4.0f*event.rTime; // back to the surface
+ if ( pos.y > level ) pos.y = level;
+ m_object->SetPosition(0, pos);
+ }
+ if ( pos.y > level )
+ {
+ pos.y -= 10.0f*event.rTime; // down quickly
+ if ( pos.y < level ) pos.y = level;
+ m_object->SetPosition(0, pos);
+ }
+
+ prog = m_progress;
+ if ( prog >= 1.0f )
+ {
+ prog = 1.0f;
+ if ( pos.y >= level ) m_object->SetEnable(FALSE);
+ }
+
+ prog *= 2.0f;
+ if ( prog > 1.0f ) prog = 1.0f;
+
+ time = 100.0f;
+
+ dir.z = -(90.0f*PI/180.0f)*prog;
+ dir.x = Rand()*0.3f*deadFactor;
+ dir.y = Rand()*0.3f*deadFactor;
+ actual = m_object->RetInclinaison();
+ dir.x = Smooth(actual.x, dir.x, time);
+ dir.y = Smooth(actual.y, dir.y, time);
+ dir.z = Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+
+ m_object->SetCirVibration(D3DVECTOR(0.0f, 0.0f, 0.0f));
+ }
+ else if ( m_actionType == MHS_LOST ) // lost?
+ {
+ time = m_time;
+ if ( time < 10.0f ) time *= time/10.0f; // starts slowly
+
+ dir.x = time*2.0f;
+ dir.y = sinf(m_time*0.8f)*0.8f;
+ dir.z = sinf(m_time*0.6f)*0.5f;
+ m_object->SetInclinaison(dir);
+ SetInclinaison(dir);
+
+//? dir.x = -(sinf(time*0.05f+PI*1.5f)+1.0f)*100.0f;
+ // original code: Min(time/30.0f) (?) changed to time/30.0f
+ dir.x = -(powf(time/30.0f, 4.0f))*1000.0f; // from the distance
+ dir.y = 0.0f;
+ dir.z = 0.0f;
+ m_object->SetLinVibration(dir);
+ SetLinVibration(dir);
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = D3DVECTOR(0.5f, 3.7f, 0.0f);
+ pos.x += (Rand()-0.5f)*1.0f;
+ pos.y += (Rand()-0.5f)*1.0f;
+ pos.z += (Rand()-0.5f)*1.0f;
+ pos = Transform(*mat, pos);
+ speed.x = (Rand()-0.5f)*0.5f;
+ speed.y = (Rand()-0.5f)*0.5f;
+ speed.z = (Rand()-0.5f)*0.5f;
+ dim.x = 0.5f+Rand()*0.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTILENS1, 5.0f, 0.0f, 0.0f);
+ }
+ else if ( m_actionType == MHS_SATCOM ) // look at the SatCom?
+ {
+ SetCirVibration(D3DVECTOR(0.0f, 0.0f, 0.0f));
+ SetLinVibration(D3DVECTOR(0.0f, 0.0f, 0.0f));
+ SetInclinaison(D3DVECTOR(0.0f, 0.0f, 0.0f));
+ }
+ else
+ {
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ time = event.rTime*8.0f;
+ if ( bSwim ) time *= 0.25f;
+
+ if ( action == MH_MARCH ) // walking?
+ {
+ dir.x = sinf(Mod(rTime[0]+0.5f, 1.0f)*PI*2.0f)*0.10f;
+ dir.y = sinf(Mod(rTime[0]+0.6f, 1.0f)*PI*2.0f)*0.20f;
+ s = m_physics->RetLinMotionX(MO_REASPEED)*0.03f;
+ }
+ else if ( action == MH_MARCHTAKE ) // takes walking?
+ {
+ dir.x = sinf(Mod(rTime[0]+0.5f, 1.0f)*PI*2.0f)*0.10f;
+ dir.y = sinf(Mod(rTime[0]+0.6f, 1.0f)*PI*2.0f)*0.15f;
+ s = m_physics->RetLinMotionX(MO_REASPEED)*0.02f;
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ s = m_physics->RetLinMotionX(MO_REASPEED)*0.03f;
+ }
+
+ if ( s < 0.0f ) s *= 0.5f;
+ dir.z = -s*0.7f;
+
+ actual = m_object->RetInclinaison();
+ dir.x = Smooth(actual.x, dir.x, time);
+ dir.y = Smooth(actual.y, dir.y, time);
+ dir.z = Smooth(actual.z, dir.z, time);
+ if ( bOnBoard ) dir *= 0.3f;
+ m_object->SetInclinaison(dir);
+ SetInclinaison(dir);
+
+ if ( action == MH_MARCH ) // walking?
+ {
+ p2.x = 0.0f;
+ p2.y = sinf(Mod(rTime[0]+0.5f, 1.0f)*PI*2.0f)*0.5f;
+ p2 = RotatePoint(-m_object->RetAngleY(0), p2);
+ dir.x = p2.x;
+ dir.z = p2.y;
+ dir.y = sinf(Mod(rTime[0]*2.0f, 1.0f)*PI*2.0f)*0.3f;
+ }
+ else if ( action == MH_MARCHTAKE ) // takes walking?
+ {
+ p2.x = 0.0f;
+ p2.y = sinf(Mod(rTime[0]+0.5f, 1.0f)*PI*2.0f)*0.25f;
+ p2 = RotatePoint(-m_object->RetAngleY(0), p2);
+ dir.x = p2.x;
+ dir.z = p2.y;
+ dir.y = sinf(Mod(rTime[0]*2.0f, 1.0f)*PI*2.0f)*0.05f-0.3f;
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = 0.0f;
+ }
+
+ actual = m_object->RetLinVibration();
+ dir.x = Smooth(actual.x, dir.x, time);
+ if ( action == MH_MARCHTAKE ) // takes walking?
+ {
+ dir.y = -hr;
+ }
+ else
+ {
+ s = Min(m_armTimeAction, 1.0f);
+ dir.y = Smooth(actual.y, dir.y, time)*s;
+ dir.y += -hr*(1.0f-s);
+ }
+ dir.z = Smooth(actual.z, dir.z, time);
+ if ( bOnBoard ) dir *= 0.3f;
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = 0.0f;
+ SetCirVibration(dir);
+ }
+ }
+
+ // Management of the head.
+ if ( m_actionType == MHS_TAKE || // takes?
+ m_actionType == MHS_FLAG ) // takes?
+ {
+ m_object->SetAngleZ(1, Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f-0.6f, event.rTime*5.0f));
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f);
+ m_object->SetAngleY(1, Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f));
+ }
+ else if ( m_actionType == MHS_TAKEOTHER || // takes?
+ m_actionType == MHS_TAKEHIGH ) // takes?
+ {
+ m_object->SetAngleZ(1, Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f-0.3f, event.rTime*5.0f));
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f);
+ m_object->SetAngleY(1, Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f));
+ }
+ else if ( m_actionType == MHS_WIN ) // win
+ {
+ float factor = 0.6f+(sinf(m_armTimeAbs*0.5f)*0.40f);
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*5.0f)*0.20f*factor);
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*0.6f)*0.10f);
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*1.5f)*0.15f);
+ }
+ else if ( m_actionType == MHS_LOST ) // lost?
+ {
+ float factor = 0.6f+(sinf(m_armTimeAbs*0.5f)*0.40f);
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*0.6f)*0.10f);
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*0.7f)*0.10f);
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*3.0f)*0.30f*factor);
+ }
+ else if ( m_object->RetDead() ) // dead?
+ {
+ }
+ else
+ {
+ m_object->SetAngleZ(1, Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f, event.rTime*5.0f));
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f);
+ m_object->SetAngleY(1, Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f));
+ }
+
+ if ( bOnBoard )
+ {
+ m_object->SetAngleZ(1, 0.0f);
+ m_object->SetAngleX(1, 0.0f);
+ m_object->SetAngleY(1, 0.0f);
+ }
+
+ // Steps sound effects.
+ if ( legAction == MH_MARCH ||
+ legAction == MH_MARCHTAKE )
+ {
+ Sound sound[2];
+ float speed, synchro, volume[2], freq[2], hard, level;
+
+ speed = m_physics->RetLinMotionX(MO_REASPEED);
+
+ if ( m_object->RetFret() == 0 )
+ {
+ if ( speed > 0.0f ) synchro = 0.21f; // synchro forward
+ else synchro = 0.29f; // synchro backward
+ }
+ else
+ {
+ if ( speed > 0.0f ) synchro = 0.15f; // synchro forward
+ else synchro = 0.35f; // synchro backward
+ }
+ time = rTime[1]+synchro;
+
+ if ( Abs(m_lastSoundMarch-time) > 0.4f &&
+ Mod(time, 0.5f) < 0.1f )
+ {
+ volume[0] = 0.5f;
+ freq[0] = 1.0f;
+ if ( m_object->RetFret() != 0 )
+ {
+//? volume[0] *= 2.0f;
+ freq[0] = 0.7f;
+ }
+ volume[1] = volume[0];
+ freq[1] = freq[0];
+ sound[0] = SOUND_CLICK;
+ sound[1] = SOUND_CLICK;
+
+ pos = m_object->RetPosition(0);
+
+ level = m_water->RetLevel();
+ if ( pos.y <= level+3.0f ) // underwater?
+ {
+ sound[0] = SOUND_STEPw;
+ }
+ else
+ {
+ hard = m_terrain->RetHardness(pos);
+
+ if ( hard >= 0.875 )
+ {
+ sound[0] = SOUND_STEPm; // metal
+ }
+ else
+ {
+ hard /= 0.875;
+ sound[0] = SOUND_STEPs; // smooth
+ sound[1] = SOUND_STEPh; // hard
+
+ volume[0] *= 1.0f-hard;
+ volume[1] *= hard;
+ if ( hard < 0.5f )
+ {
+ volume[0] *= 1.0f+hard*2.0f;
+ volume[1] *= 1.0f+hard*2.0f;
+ }
+ else
+ {
+ volume[0] *= 3.0f-hard*2.0f;
+ volume[1] *= 3.0f-hard*2.0f;
+ }
+ freq[0] *= 1.0f+hard;
+ freq[1] *= 0.5f+hard;
+ }
+ }
+
+ if ( sound[0] != SOUND_CLICK )
+ {
+ m_sound->Play(sound[0], pos, volume[0], freq[0]);
+ }
+ if ( sound[1] != SOUND_CLICK )
+ {
+ m_sound->Play(sound[1], pos, volume[1], freq[1]);
+ }
+ m_lastSoundMarch = time;
+ }
+ }
+
+ if ( legAction == MH_SWIM )
+ {
+ time = rTime[0]+0.5f;
+
+ if ( Abs(m_lastSoundMarch-time) > 0.9f &&
+ Mod(time, 1.0f) < 0.1f )
+ {
+ m_sound->Play(SOUND_SWIM, m_object->RetPosition(0), 0.5f);
+ m_lastSoundMarch = time;
+ }
+ }
+
+ m_lastSoundHhh -= event.rTime;
+ if ( m_lastSoundHhh <= 0.0f &&
+ m_object->RetSelect() &&
+ m_object->RetOption() == 0 ) // helmet?
+ {
+ m_sound->Play(SOUND_HUMAN1, m_object->RetPosition(0), (0.5f+m_tired*0.2f));
+ m_lastSoundHhh = (4.0f-m_tired*2.5f)+(4.0f-m_tired*2.5f)*Rand();
+ }
+
+ return TRUE;
+}
+
+
+// Management of the display mode when customizing the personal.
+
+void CMotionHuman::StartDisplayPerso()
+{
+ m_bDisplayPerso = TRUE;
+}
+
+void CMotionHuman::StopDisplayPerso()
+{
+ m_bDisplayPerso = FALSE;
+}
+
+
diff --git a/src/object/motion/motionhuman.h b/src/object/motion/motionhuman.h
new file mode 100644
index 0000000..44a0c4c
--- /dev/null
+++ b/src/object/motion/motionhuman.h
@@ -0,0 +1,102 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionhuman.h
+
+#ifndef _MOTIONHUMAN_H_
+#define _MOTIONHUMAN_H_
+
+
+#include "motion.h"
+#include "misc.h"
+
+
+class CInstanceManager;
+class CEngine;
+class CLight;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CBrain;
+class CPhysics;
+class CObject;
+
+
+#define MH_MARCH 0
+#define MH_MARCHTAKE 1
+#define MH_TURN 2
+#define MH_STOP 3
+#define MH_FLY 4
+#define MH_SWIM 5
+#define MH_SPEC 6
+
+#define MHS_FIRE 0
+#define MHS_GUN 1
+#define MHS_TAKE 2
+#define MHS_TAKEOTHER 3
+#define MHS_TAKEHIGH 4
+#define MHS_UPRIGHT 5
+#define MHS_WIN 6
+#define MHS_LOST 7
+#define MHS_DEADg 8
+#define MHS_DEADg1 9
+#define MHS_DEADg2 10
+#define MHS_DEADg3 11
+#define MHS_DEADg4 12
+#define MHS_DEADw 13
+#define MHS_FLAG 14
+#define MHS_SATCOM 15
+
+
+class CMotionHuman : public CMotion
+{
+public:
+ CMotionHuman(CInstanceManager* iMan, CObject* object);
+ ~CMotionHuman();
+
+ void DeleteObject(BOOL bAll=FALSE);
+ BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power);
+ BOOL EventProcess(const Event &event);
+ Error SetAction(int action, float time=0.2f);
+
+ void StartDisplayPerso();
+ void StopDisplayPerso();
+
+protected:
+ void CreatePhysics(ObjectType type);
+ BOOL EventFrame(const Event &event);
+
+protected:
+ int m_partiReactor;
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeAction;
+ float m_armTimeSwim;
+ short m_armAngles[3*3*3*3*7 + 3*3*3*16];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ BOOL m_bArmStop;
+ float m_lastSoundMarch;
+ float m_lastSoundHhh;
+ float m_time;
+ float m_tired;
+ BOOL m_bDisplayPerso;
+};
+
+
+#endif //_MOTIONHUMAN_H_
diff --git a/src/object/motion/motionmother.cpp b/src/object/motion/motionmother.cpp
new file mode 100644
index 0000000..872ef76
--- /dev/null
+++ b/src/object/motion/motionmother.cpp
@@ -0,0 +1,543 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionmother.cpp
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "math3d.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "light.h"
+#include "particule.h"
+#include "terrain.h"
+#include "object.h"
+#include "physics.h"
+#include "brain.h"
+#include "camera.h"
+#include "modfile.h"
+#include "sound.h"
+#include "motion.h"
+#include "motionmother.h"
+
+
+
+#define ADJUST_ANGLE FALSE // TRUE -> adjusts the angles of the members
+#define START_TIME 1000.0f // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionMother::CMotionMother(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ CMotion::CMotion(iMan, object);
+
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeMarch = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLastAction = -1;
+ m_specAction = -1;
+ m_bArmStop = FALSE;
+}
+
+// Object's destructor.
+
+CMotionMother::~CMotionMother()
+{
+}
+
+
+// Removes an object.
+
+void CMotionMother::DeleteObject(BOOL bAll)
+{
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+BOOL CMotionMother::Create(D3DVECTOR pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 2+12+6 ) return FALSE;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+
+ pModFile->ReadModel("objects\\mother1.mod");
+ pModFile->CreateEngineObject(rank);
+
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have a obligatory collision
+ //with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 20.0f, SOUND_BOUM, 0.20f);
+ m_object->SetGlobalSphere(D3DVECTOR(-2.0f, 10.0f, 0.0f), 25.0f);
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\mother2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, D3DVECTOR(16.0f, 3.0f, 0.0f));
+
+ // Creates a right-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, D3DVECTOR(-5.0f, -1.0f, -12.0f));
+
+ // Creates a right-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, D3DVECTOR(0.0f, 0.0f, -8.5f));
+
+ // Creates a middle-right leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, D3DVECTOR(3.5f, -1.0f, -12.0f));
+
+ // Creates a middle-right foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 4);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, D3DVECTOR(0.0f, 0.0f, -8.5f));
+
+ // Creates a right-front leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, D3DVECTOR(10.0f, -1.0f, -10.0f));
+
+ // Creates a right-front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 6);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, D3DVECTOR(0.0f, 0.0f, -8.5f));
+
+ // Creates a left-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, D3DVECTOR(-5.0f, -1.0f, 12.0f));
+ m_object->SetAngleY(8, PI);
+
+ // Creates a left-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 8);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, D3DVECTOR(0.0f, 0.0f, -8.5f));
+
+ // Creates a middle-left leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10, rank);
+ m_object->SetObjectParent(10, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10, D3DVECTOR(3.5f, -1.0f, 12.0f));
+ m_object->SetAngleY(10, PI);
+
+ // Creates a middle-left foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(11, rank);
+ m_object->SetObjectParent(11, 10);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(11, D3DVECTOR(0.0f, 0.0f, -8.5f));
+
+ // Creates a left-front leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(12, rank);
+ m_object->SetObjectParent(12, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(12, D3DVECTOR(10.0f, -1.0f, 10.0f));
+ m_object->SetAngleY(12, PI);
+
+ // Creates a left-front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(13, rank);
+ m_object->SetObjectParent(13, 12);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(13, D3DVECTOR(0.0f, 0.0f, -8.5f));
+
+ // Creates the right antenna.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(14, rank);
+ m_object->SetObjectParent(14, 1);
+ pModFile->ReadModel("objects\\mother5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(14, D3DVECTOR(6.0f, 1.0f, -2.5f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(15, rank);
+ m_object->SetObjectParent(15, 14);
+ pModFile->ReadModel("objects\\mother6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(15, D3DVECTOR(8.0f, 0.0f, 0.0f));
+
+ // Creates the left antenna.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(16, rank);
+ m_object->SetObjectParent(16, 1);
+ pModFile->ReadModel("objects\\mother5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(16, D3DVECTOR(6.0f, 1.0f, 2.5f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(17, rank);
+ m_object->SetObjectParent(17, 16);
+ pModFile->ReadModel("objects\\mother6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(17, D3DVECTOR(8.0f, 0.0f, 0.0f));
+
+ // Creates the right claw.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(18, rank);
+ m_object->SetObjectParent(18, 1);
+ pModFile->ReadModel("objects\\mother7.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(18, D3DVECTOR(-4.0f, -3.5f, -8.0f));
+ m_object->SetZoomX(18, 1.2f);
+
+ // Creates the left claw.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(19, rank);
+ m_object->SetObjectParent(19, 1);
+ pModFile->ReadModel("objects\\mother7.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(19, D3DVECTOR(-4.0f, -3.5f, 8.0f));
+ m_object->SetZoomX(19, 1.2f);
+
+ m_object->CreateShadowCircle(18.0f, 0.8f);
+
+ CreatePhysics();
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return TRUE;
+}
+
+// Creates the physics of the object.
+
+void CMotionMother::CreatePhysics()
+{
+ Character* character;
+ int i;
+
+ int member[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 30,30,10, 35,-15,10, 35,-35,10, // t0: legs 1..3
+ -80,-45,-35, -115,-40,-35, -90,10,-55, // t0: feet 1..3
+ 0,0,0, 0,0,0, 0,0,0, // t0: unused
+ // on the ground:
+ 15,-5,10, 10,-30,10, 5,-50,10, // t1: legs 1..3
+ -90,-15,-15, -110,-55,-35, -75,-75,-30, // t1: feet 1..3
+ 0,0,0, 0,0,0, 0,0,0, // t1: unused
+ // on the ground back:
+ 0,40,10, 5,5,10, 0,-15,10, // t2: legs 1..3
+ -45,0,-55, -65,10,-50, -125,-85,-45, // t2: feet 1..3
+ 0,0,0, 0,0,0, 0,0,0, // t2: unused
+ };
+
+ m_physics->SetType(TYPE_ROLLING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 10.0f;
+ character->wheelBack = 10.0f;
+ character->wheelLeft = 20.0f;
+ character->wheelRight = 20.0f;
+ character->height = 3.0f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 8.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 8.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 30.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.1f*PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.1f*PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 20.0f);
+
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[i] = member[i];
+ }
+}
+
+
+// Management of an event.
+
+BOOL CMotionMother::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if ADJUST_ANGLE
+ int i;
+
+ if ( event.param == 'A' ) m_armTimeIndex++;
+ if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
+
+ if ( event.param == 'Q' ) m_armPartIndex++;
+ if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
+
+ if ( event.param == 'W' ) m_armMemberIndex++;
+ if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
+
+ i = m_armMemberIndex*3;
+ i += m_armPartIndex*3*3;
+ i += m_armTimeIndex*3*3*3;
+//? i += 3*3*3*3;
+
+ if ( event.param == 'E' ) m_armAngles[i+0] += 5;
+ if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
+ if ( event.param == 'R' ) m_armAngles[i+1] += 5;
+ if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
+ if ( event.param == 'T' ) m_armAngles[i+2] += 5;
+ if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
+
+ if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
+#endif
+ }
+
+ return TRUE;
+}
+
+// Management of an event.
+
+BOOL CMotionMother::EventFrame(const Event &event)
+{
+ D3DVECTOR dir;
+ float s, a, prog;
+ int i, st, nd;
+ BOOL bStop;
+
+ if ( m_engine->RetPause() ) return TRUE;
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return TRUE;
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
+ a = Abs(m_physics->RetCirMotionY(MO_MOTSPEED)*26.0f);
+
+ if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armTimeMarch += (s)*event.rTime*0.05f;
+ m_armMember += (s+a)*event.rTime*0.05f;
+
+ bStop = ( a == 0.0f && s == 0.0f ); // stop?
+
+ if ( bStop )
+ {
+ prog = Mod(m_armTimeAbs, 2.0f)/10.0f;
+ a = Mod(m_armMember, 1.0f);
+ a = (prog-a)*event.rTime*1.0f; // stop position just pleasantly
+ m_armMember += a;
+ }
+
+ for ( i=0 ; i<6 ; i++ ) // the six legs
+ {
+ if ( i < 3 ) prog = Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
+ else prog = Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
+ if ( m_bArmStop )
+ {
+ prog = (float)m_armTimeIndex/3.0f;
+ }
+ if ( prog < 0.33f ) // t0..t1 ?
+ {
+ prog = prog/0.33f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.67f ) // t1..t2 ?
+ {
+ prog = (prog-0.33f)/0.33f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.67f)/0.33f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ st = st*27+(i%3)*3;
+ nd = nd*27+(i%3)*3;
+ if ( i < 3 ) // right leg (1..3) ?
+ {
+ m_object->SetAngleX(2+2*i+0, Prop(m_armAngles[st+ 0], m_armAngles[nd+ 0], prog));
+ m_object->SetAngleY(2+2*i+0, Prop(m_armAngles[st+ 1], m_armAngles[nd+ 1], prog));
+ m_object->SetAngleZ(2+2*i+0, Prop(m_armAngles[st+ 2], m_armAngles[nd+ 2], prog));
+ m_object->SetAngleX(2+2*i+1, Prop(m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
+ m_object->SetAngleY(2+2*i+1, Prop(m_armAngles[st+10], m_armAngles[nd+10], prog));
+ m_object->SetAngleZ(2+2*i+1, Prop(m_armAngles[st+11], m_armAngles[nd+11], prog));
+ }
+ else // left leg (4..6) ?
+ {
+ m_object->SetAngleX(2+2*i+0, Prop( m_armAngles[st+ 0], m_armAngles[nd+ 0], prog));
+ m_object->SetAngleY(2+2*i+0, Prop(180-m_armAngles[st+ 1], 180-m_armAngles[nd+ 1], prog));
+ m_object->SetAngleZ(2+2*i+0, Prop( -m_armAngles[st+ 2], -m_armAngles[nd+ 2], prog));
+ m_object->SetAngleX(2+2*i+1, Prop( m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
+ m_object->SetAngleY(2+2*i+1, Prop( -m_armAngles[st+10], -m_armAngles[nd+10], prog));
+ m_object->SetAngleZ(2+2*i+1, Prop( -m_armAngles[st+11], -m_armAngles[nd+11], prog));
+ }
+ }
+
+#if ADJUST_ANGLE
+ if ( m_object->RetSelect() )
+ {
+ char s[100];
+ sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
+ m_engine->SetInfoText(4, s);
+ }
+#endif
+
+ if ( !bStop && !m_object->RetRuin() )
+ {
+ a = Mod(m_armTimeMarch, 1.0f);
+ if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
+ else a = 3.0f-4.0f*a; // 1..-1
+ dir.x = sinf(a)*0.03f;
+
+ s = Mod(m_armTimeMarch/2.0f, 1.0f);
+ if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
+ else s = 3.0f-4.0f*s; // 1..-1
+ dir.z = sinf(s)*0.05f;
+
+ dir.y = 0.0f;
+ m_object->SetInclinaison(dir);
+
+ a = Mod(m_armMember-0.1f, 1.0f);
+ if ( a < 0.33f )
+ {
+ dir.y = -(1.0f-(a/0.33f))*0.3f;
+ }
+ else if ( a < 0.67f )
+ {
+ dir.y = 0.0f;
+ }
+ else
+ {
+ dir.y = -(a-0.67f)/0.33f*0.3f;
+ }
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ m_object->SetLinVibration(dir);
+ }
+
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*0.5f)*0.20f); // head
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*0.6f)*0.10f); // head
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*0.7f)*0.20f); // head
+
+ m_object->SetAngleZ(14, 0.50f);
+ m_object->SetAngleZ(16, 0.50f);
+ m_object->SetAngleY(14, 0.80f+sinf(m_armTimeAbs*1.1f)*0.53f); // right antenna
+ m_object->SetAngleY(15, 0.70f-sinf(m_armTimeAbs*1.7f)*0.43f);
+ m_object->SetAngleY(16, -0.80f+sinf(m_armTimeAbs*0.9f)*0.53f); // left antenna
+ m_object->SetAngleY(17, -0.70f-sinf(m_armTimeAbs*1.3f)*0.43f);
+
+ m_object->SetAngleY(18, sinf(m_armTimeAbs*1.1f)*0.20f); // right claw
+ m_object->SetAngleZ(18, -0.20f);
+ m_object->SetAngleY(19, sinf(m_armTimeAbs*0.9f)*0.20f); // left claw
+ m_object->SetAngleZ(19, -0.20f);
+
+ return TRUE;
+}
+
+
diff --git a/src/object/motion/motionmother.h b/src/object/motion/motionmother.h
new file mode 100644
index 0000000..6e8eb32
--- /dev/null
+++ b/src/object/motion/motionmother.h
@@ -0,0 +1,67 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionmother.h
+
+#ifndef _MOTIONMOTHER_H_
+#define _MOTIONMOTHER_H_
+
+
+#include "motion.h"
+
+
+class CInstanceManager;
+class CEngine;
+class CLight;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CBrain;
+class CPhysics;
+class CObject;
+
+
+class CMotionMother : public CMotion
+{
+public:
+ CMotionMother(CInstanceManager* iMan, CObject* object);
+ ~CMotionMother();
+
+ void DeleteObject(BOOL bAll=FALSE);
+ BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power);
+ BOOL EventProcess(const Event &event);
+
+protected:
+ void CreatePhysics();
+ BOOL EventFrame(const Event &event);
+
+protected:
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeMarch;
+ float m_armTimeAction;
+ short m_armAngles[3*3*3*3*10];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ int m_specAction;
+ float m_specTime;
+ BOOL m_bArmStop;
+};
+
+
+#endif //_MOTIONMOTHER_H_
diff --git a/src/object/motion/motionspider.cpp b/src/object/motion/motionspider.cpp
new file mode 100644
index 0000000..99c3d06
--- /dev/null
+++ b/src/object/motion/motionspider.cpp
@@ -0,0 +1,789 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionspider.cpp
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "math3d.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "light.h"
+#include "particule.h"
+#include "terrain.h"
+#include "object.h"
+#include "physics.h"
+#include "brain.h"
+#include "camera.h"
+#include "modfile.h"
+#include "sound.h"
+#include "motion.h"
+#include "motionspider.h"
+
+
+
+#define ADJUST_ANGLE FALSE // TRUE -> adjusts the angles of the members
+#define START_TIME 1000.0f // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionSpider::CMotionSpider(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ CMotion::CMotion(iMan, object);
+
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeMarch = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLastAction = -1;
+ m_bArmStop = FALSE;
+ m_lastParticule = 0.0f;
+}
+
+// Object's destructor.
+
+CMotionSpider::~CMotionSpider()
+{
+}
+
+
+// Removes an object.
+
+void CMotionSpider::DeleteObject(BOOL bAll)
+{
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+BOOL CMotionSpider::Create(D3DVECTOR pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank, i, j, parent;
+ char name[50];
+
+ float table[] =
+ {
+ // x y z
+ 0.6f, 0.0f, 0.0f, // back leg
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+
+ 0.8f, 0.0f, -0.2f, // middle-back leg
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+
+ 1.0f, 0.0f, -0.2f, // middle-front leg
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+
+ 1.2f, 0.0f, 0.0f, // front leg
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+ };
+
+ if ( m_engine->RetRestCreate() < 3+32+2 ) return FALSE;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates the main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\spider0.mod"); // doesn't exist
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have a obligatory collision
+ // with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(D3DVECTOR(0.0f, -2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
+ m_object->SetGlobalSphere(D3DVECTOR(-0.5f, 1.0f, 0.0f), 4.0f);
+
+ // Creates the abdomen.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\spider1.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, D3DVECTOR(1.0f, 0.0f, 0.0f));
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\spider2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, D3DVECTOR(1.0f, 0.0f, 0.0f));
+
+ // Creates legs.
+ for ( i=0 ; i<4 ; i++ )
+ {
+ for ( j=0 ; j<4 ; j++ )
+ {
+ sprintf(name, "objects\\spider%d.mod", j+3); // 3..6
+
+ // Creates the right leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3+i*4+j, rank);
+ if ( j == 0 ) parent = 0;
+ else parent = 3+i*4+j-1;
+ m_object->SetObjectParent(3+i*4+j, parent);
+ pModFile->ReadModel(name);
+ pModFile->CreateEngineObject(rank);
+ pos.x = table[i*12+j*3+0];
+ pos.y = table[i*12+j*3+1];
+ pos.z = table[i*12+j*3+2];
+ m_object->SetPosition(3+i*4+j, pos);
+
+ // Creates the left leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(19+i*4+j, rank);
+ if ( j == 0 ) parent = 0;
+ else parent = 19+i*4+j-1;
+ m_object->SetObjectParent(19+i*4+j, parent);
+ pModFile->ReadModel(name);
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ pos.x = table[i*12+j*3+0];
+ pos.y = table[i*12+j*3+1];
+ pos.z = -table[i*12+j*3+2];
+ m_object->SetPosition(19+i*4+j, pos);
+ }
+ }
+
+ // Creates the right mandible.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(35, rank);
+ m_object->SetObjectParent(35, 1);
+ pModFile->ReadModel("objects\\spider7.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(35, D3DVECTOR(0.0f, 0.0f, -0.3f));
+
+ // Creates the left mandible.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(36, rank);
+ m_object->SetObjectParent(36, 1);
+ pModFile->ReadModel("objects\\spider7.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(36, D3DVECTOR(0.0f, 0.0f, 0.3f));
+
+ m_object->CreateShadowCircle(4.0f, 0.5f);
+
+ CreatePhysics();
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return TRUE;
+}
+
+// Creates the physics of the object.
+
+void CMotionSpider::CreatePhysics()
+{
+ Character* character;
+ int i;
+
+ int member_march[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // in the air:
+ 60,25,0, 60,0,0, 60,-25,0, 60,-50,0, // t0: thighs 1..4
+ -35,40,0, -35,0,0, -35,0,0, -35,-40,0, // t0: legs 1..4
+ -65,0,-30, -65,0,0, -65,0,0, -65,0,30, // t0: feet 1..4
+ 25,0,0, 25,0,0, 25,0,0, 25,0,0, // t0: fingers 1..4
+ // on the ground:
+ 30,15,0, 30,-10,0, 30,-35,0, 30,-60,0, // t1: thighs 1..4
+ -10,40,0, -45,0,0, -45,0,0, -45,-40,0, // t1: legs 1..4
+ -90,0,0, -20,0,0, -20,0,0, -20,0,0, // t1: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t1: fingers 1..4
+ // on the ground back:
+ 35,35,0, 40,10,0, 40,-15,0, 40,-40,0, // t2: thighs 1..4
+ -35,40,0, -35,0,0, -35,0,0, -25,-40,0, // t2: legs 1..4
+ -50,-25,-30, -65,0,0, -65,0,0, -90,0,30, // t2: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t2: fingers 1..4
+ };
+
+ int member_stop[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // in the air:
+ 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t0: thighs 1..4
+ -35,40,0, -45,0,0, -45,0,0, -45,-40,0, // t0: legs 1..4
+ -50,-25,-30, -20,0,0, -20,0,0, -20,0,30, // t0: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t0: fingers 1..4
+ // on the ground:
+ 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t1: thighs 1..4
+ -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // t1: legs 1..4
+ -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // t1: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t1: fingers 1..4
+ // on the ground back:
+ 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t2: thighs 1..4
+ -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // t2: legs 1..4
+ -50,-25,-30, -20,0,0, -20,0,0, -20,0,30, // t2: feet 1..4
+ -10,0,0, -10,0,0, -10,0,0, -10,0,0, // t2: fingers 1..4
+ };
+
+ int member_spec[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // burning:
+ 30,25,0, 30,0,0, 30,-25,0, 30,-50,0, // s0: thighs 1..4
+ -45,0,0, -45,0,0, -45,0,0, -45,0,0, // s0: legs 1..4
+ -20,0,0, -20,0,0, -20,0,0, -20,0,0, // s0: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s0: fingers 1..4
+ // destroyed:
+ 30,25,0, 30,0,0, 30,-25,0, 30,-50,0, // s1: thighs 1..4
+ -45,0,0, -45,0,0, -45,0,0, -45,0,0, // s1: legs 1..4
+ -20,0,0, -20,0,0, -20,0,0, -20,0,0, // s1: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s1: fingers 1..4
+ // explodes:
+ 40,25,0, 40,0,0, 40,-25,0, 40,-50,0, // s2: thighs 1..4
+ -55,0,0, -55,0,0, -55,0,0, -55,0,0, // s2: legs 1..4
+ -30,0,0, -30,0,0, -30,0,0, -30,0,0, // s2: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s2: fingers 1..4
+ // back1 :
+ 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // s3: thighs 1..4
+ -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // s3: legs 1..4
+ -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // s3: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s3: fingers 1..4
+ // back2 :
+ 15,35,0, 15,0,0, 15,-25,0, 15,-50,0, // s4: thighs 1..4
+ -60,40,0, -60,0,0, -60,0,0, -60,-40,0, // s4: legs 1..4
+ -65,-25,-30, -65,0,0, -65,0,0, -65,0,0, // s4: feet 1..4
+ -15,0,0, -15,0,0, -15,0,0, -15,0,0, // s4: fingers 1..4
+ // back3 :
+ 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // s5: thighs 1..4
+ -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // s5: legs 1..4
+ -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // s5: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s5: fingers 1..4
+ };
+
+ m_physics->SetType(TYPE_ROLLING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 6.0f;
+ character->wheelRight = 6.0f;
+ character->height = 0.6f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 12.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 12.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 15.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 10.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 40.0f);
+
+ for ( i=0 ; i<3*4*4*3 ; i++ )
+ {
+ m_armAngles[3*4*4*3*MS_MARCH+i] = member_march[i];
+ }
+ for ( i=0 ; i<3*4*4*3 ; i++ )
+ {
+ m_armAngles[3*4*4*3*MS_STOP+i] = member_stop[i];
+ }
+ for ( i=0 ; i<3*4*4*6 ; i++ )
+ {
+ m_armAngles[3*4*4*3*MS_SPEC+i] = member_spec[i];
+ }
+}
+
+
+// Management of an event.
+
+BOOL CMotionSpider::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if ADJUST_ANGLE
+ int i;
+
+ if ( event.param == 'A' ) m_armTimeIndex++;
+ if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
+
+ if ( event.param == 'Q' ) m_armPartIndex++;
+ if ( m_armPartIndex >= 4 ) m_armPartIndex = 0;
+
+ if ( event.param == 'W' ) m_armMemberIndex++;
+ if ( m_armMemberIndex >= 4 ) m_armMemberIndex = 0;
+
+ i = m_armMemberIndex*3;
+ i += m_armPartIndex*3*4;
+ i += m_armTimeIndex*3*4*4;
+
+ if ( event.param == 'E' ) m_armAngles[i+0] += 5;
+ if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
+ if ( event.param == 'R' ) m_armAngles[i+1] += 5;
+ if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
+ if ( event.param == 'T' ) m_armAngles[i+2] += 5;
+ if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
+ if ( event.param == 'Z' ) m_armAngles[i+3] += 5;
+ if ( event.param == 'H' ) m_armAngles[i+3] -= 5;
+
+ if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
+#endif
+ }
+
+ return TRUE;
+}
+
+// Calculates a value (radians) proportional between a and b (degrees).
+
+inline float Propf(float a, float b, float p)
+{
+ float aa, bb;
+
+ aa = a*PI/180.0f;
+ bb = b*PI/180.0f;
+
+ return aa+p*(bb-aa);
+}
+
+// Management of an event.
+
+BOOL CMotionSpider::EventFrame(const Event &event)
+{
+ D3DVECTOR dir, pos, speed;
+ FPOINT dim;
+ float s, a, prog, time;
+ float tSt[12], tNd[12];
+ int i, ii, st, nd, action;
+ BOOL bStop;
+
+ if ( m_engine->RetPause() ) return TRUE;
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return TRUE;
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
+ a = Abs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f);
+
+ if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armTimeAction += event.rTime;
+ m_armTimeMarch += (s)*event.rTime*0.15f;
+ m_armMember += (s+a)*event.rTime*0.15f;
+
+ bStop = ( a == 0.0f && s == 0.0f ); // stop?
+
+ action = MS_MARCH; // waslking
+ if ( s == 0.0f && a == 0.0f )
+ {
+ action = MS_STOP; // stop
+ }
+
+ if ( bStop )
+ {
+ prog = Mod(m_armTimeAbs, 2.0f)/10.0f;
+ a = Mod(m_armMember, 1.0f);
+ a = (prog-a)*event.rTime*2.0f; // stop position just pleasantly
+ m_armMember += a;
+ }
+
+ if ( m_object->RetRuin() ) // destroyed?
+ {
+ m_actionType = MSS_RUIN;
+ }
+ if ( m_object->RetBurn() ) // burning?
+ {
+ if ( m_object->RetFixed() )
+ {
+ m_actionType = MSS_BURN;
+ }
+ else
+ {
+ m_actionType = -1;
+ }
+ }
+
+ for ( i=0 ; i<8 ; i++ ) // the 8 legs
+ {
+ if ( m_actionType != -1 ) // special action in progress?
+ {
+ st = 3*4*4*3*MS_SPEC + 3*4*4*m_actionType + (i%4)*3;
+ nd = st;
+ time = event.rTime*m_actionTime;
+ m_armTimeAction = 0.0f;
+ }
+ else
+ {
+//? if ( i < 4 ) prog = Mod(m_armMember+(2.0f-(i%4))*0.25f+0.0f, 1.0f);
+//? else prog = Mod(m_armMember+(2.0f-(i%4))*0.25f+0.3f, 1.0f);
+ if ( i < 4 ) prog = Mod(m_armMember+(2.0f-(i%4))*0.25f+0.0f, 1.0f);
+ else prog = Mod(m_armMember+(2.0f-(i%4))*0.25f+0.5f, 1.0f);
+ if ( m_bArmStop )
+ {
+ prog = (float)m_armTimeIndex/3.0f;
+ action = MS_MARCH;
+ }
+ if ( prog < 0.33f ) // t0..t1 ?
+ {
+ prog = prog/0.33f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.67f ) // t1..t2 ?
+ {
+ prog = (prog-0.33f)/0.33f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.67f)/0.33f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ st = 3*4*4*3*action + st*3*4*4 + (i%4)*3;
+ nd = 3*4*4*3*action + nd*3*4*4 + (i%4)*3;
+
+ // Less and less soft ...
+//? time = event.rTime*(2.0f+Min(m_armTimeAction*20.0f, 40.0f));
+ time = event.rTime*10.0f;
+ }
+
+ tSt[ 0] = m_armAngles[st+ 0]; // x
+ tSt[ 1] = m_armAngles[st+ 1]; // y
+ tSt[ 2] = m_armAngles[st+ 2]; // z
+ tSt[ 3] = m_armAngles[st+12]; // x
+ tSt[ 4] = m_armAngles[st+13]; // y
+ tSt[ 5] = m_armAngles[st+14]; // z
+ tSt[ 6] = m_armAngles[st+24]; // x
+ tSt[ 7] = m_armAngles[st+25]; // y
+ tSt[ 8] = m_armAngles[st+26]; // z
+ tSt[ 9] = m_armAngles[st+36]; // x
+ tSt[10] = m_armAngles[st+37]; // y
+ tSt[11] = m_armAngles[st+38]; // z
+
+ tNd[ 0] = m_armAngles[nd+ 0]; // x
+ tNd[ 1] = m_armAngles[nd+ 1]; // y
+ tNd[ 2] = m_armAngles[nd+ 2]; // z
+ tNd[ 3] = m_armAngles[nd+12]; // x
+ tNd[ 4] = m_armAngles[nd+13]; // y
+ tNd[ 5] = m_armAngles[nd+14]; // z
+ tNd[ 6] = m_armAngles[nd+24]; // x
+ tNd[ 7] = m_armAngles[nd+25]; // y
+ tNd[ 8] = m_armAngles[nd+26]; // z
+ tNd[ 9] = m_armAngles[nd+36]; // z
+ tNd[10] = m_armAngles[nd+37]; // z
+ tNd[11] = m_armAngles[nd+38]; // z
+
+ if ( m_actionType == MSS_BACK2 ) // on the back?
+ {
+ for ( ii=0 ; ii<12 ; ii++ )
+ {
+ tSt[ii] += Rand()*20.0f;
+ tNd[ii] = tSt[ii];
+ }
+//? time = 100.0f;
+ time = event.rTime*10.0f;
+ }
+
+ if ( i < 4 ) // right leg (1..4) ?
+ {
+ m_object->SetAngleX(3+4*i+0, Smooth(m_object->RetAngleX(3+4*i+0), Propf(tSt[ 0], tNd[ 0], prog), time));
+ m_object->SetAngleY(3+4*i+0, Smooth(m_object->RetAngleY(3+4*i+0), Propf(tSt[ 1], tNd[ 1], prog), time));
+ m_object->SetAngleZ(3+4*i+0, Smooth(m_object->RetAngleZ(3+4*i+0), Propf(tSt[ 2], tNd[ 2], prog), time));
+ m_object->SetAngleX(3+4*i+1, Smooth(m_object->RetAngleX(3+4*i+1), Propf(tSt[ 3], tNd[ 3], prog), time));
+ m_object->SetAngleY(3+4*i+1, Smooth(m_object->RetAngleY(3+4*i+1), Propf(tSt[ 4], tNd[ 4], prog), time));
+ m_object->SetAngleZ(3+4*i+1, Smooth(m_object->RetAngleZ(3+4*i+1), Propf(tSt[ 5], tNd[ 5], prog), time));
+ m_object->SetAngleX(3+4*i+2, Smooth(m_object->RetAngleX(3+4*i+2), Propf(tSt[ 6], tNd[ 6], prog), time));
+ m_object->SetAngleY(3+4*i+2, Smooth(m_object->RetAngleY(3+4*i+2), Propf(tSt[ 7], tNd[ 7], prog), time));
+ m_object->SetAngleZ(3+4*i+2, Smooth(m_object->RetAngleZ(3+4*i+2), Propf(tSt[ 8], tNd[ 8], prog), time));
+ m_object->SetAngleX(3+4*i+3, Smooth(m_object->RetAngleX(3+4*i+3), Propf(tSt[ 9], tNd[ 9], prog), time));
+ m_object->SetAngleY(3+4*i+3, Smooth(m_object->RetAngleY(3+4*i+3), Propf(tSt[10], tNd[10], prog), time));
+ m_object->SetAngleZ(3+4*i+3, Smooth(m_object->RetAngleZ(3+4*i+3), Propf(tSt[11], tNd[11], prog), time));
+ }
+ else // left leg (5..8) ?
+ {
+ m_object->SetAngleX(3+4*i+0, Smooth(m_object->RetAngleX(3+4*i+0), Propf(-tSt[ 0], -tNd[ 0], prog), time));
+ m_object->SetAngleY(3+4*i+0, Smooth(m_object->RetAngleY(3+4*i+0), Propf(-tSt[ 1], -tNd[ 1], prog), time));
+ m_object->SetAngleZ(3+4*i+0, Smooth(m_object->RetAngleZ(3+4*i+0), Propf( tSt[ 2], tNd[ 2], prog), time));
+ m_object->SetAngleX(3+4*i+1, Smooth(m_object->RetAngleX(3+4*i+1), Propf(-tSt[ 3], -tNd[ 3], prog), time));
+ m_object->SetAngleY(3+4*i+1, Smooth(m_object->RetAngleY(3+4*i+1), Propf(-tSt[ 4], -tNd[ 4], prog), time));
+ m_object->SetAngleZ(3+4*i+1, Smooth(m_object->RetAngleZ(3+4*i+1), Propf( tSt[ 5], tNd[ 5], prog), time));
+ m_object->SetAngleX(3+4*i+2, Smooth(m_object->RetAngleX(3+4*i+2), Propf(-tSt[ 6], -tNd[ 6], prog), time));
+ m_object->SetAngleY(3+4*i+2, Smooth(m_object->RetAngleY(3+4*i+2), Propf(-tSt[ 7], -tNd[ 7], prog), time));
+ m_object->SetAngleZ(3+4*i+2, Smooth(m_object->RetAngleZ(3+4*i+2), Propf( tSt[ 8], tNd[ 8], prog), time));
+ m_object->SetAngleX(3+4*i+3, Smooth(m_object->RetAngleX(3+4*i+3), Propf(-tSt[ 9], -tNd[ 9], prog), time));
+ m_object->SetAngleY(3+4*i+3, Smooth(m_object->RetAngleY(3+4*i+3), Propf(-tSt[10], -tNd[10], prog), time));
+ m_object->SetAngleZ(3+4*i+3, Smooth(m_object->RetAngleZ(3+4*i+3), Propf( tSt[11], tNd[11], prog), time));
+ }
+ }
+
+#if ADJUST_ANGLE
+ if ( m_object->RetSelect() )
+ {
+ char s[100];
+ sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
+ m_engine->SetInfoText(4, s);
+ }
+#endif
+
+ if ( m_actionType == MSS_BURN ) // burning?
+ {
+ dir = D3DVECTOR(PI, 0.0f, 0.0f);
+ SetCirVibration(dir);
+ dir = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ SetInclinaison(dir);
+
+ time = event.rTime*1.0f;
+ m_object->SetAngleZ(1, Smooth(m_object->RetAngleZ(1), 0.0f, time)); // head
+ }
+ else if ( m_actionType == MSS_RUIN ) // destroyed?
+ {
+ dir = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ SetCirVibration(dir);
+ SetInclinaison(dir);
+ }
+ else if ( m_actionType == MSS_EXPLO ) // exploded?
+ {
+ m_object->SetZoomY(1, 1.0f+m_progress);
+ m_object->SetZoomZ(1, 1.0f+m_progress);
+ m_object->SetZoomX(1, 1.0f+m_progress/2.0f);
+
+ dir.x = (Rand()-0.5f)*0.1f*m_progress;
+ dir.y = (Rand()-0.5f)*0.1f*m_progress;
+ dir.z = (Rand()-0.5f)*0.1f*m_progress;
+ m_object->SetCirVibration(dir);
+ }
+ else if ( m_actionType == MSS_BACK1 ) // turns on the back?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (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 < 0.5f )
+ {
+ dir.x = 0.0f;
+ dir.y = powf(m_progress/0.5f, 2.0f)*12.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*12.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ dir.x = m_progress*PI;
+ dir.y = 0.0f;
+ dir.z = 0.0f;
+ SetCirVibration(dir);
+
+ dir = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(MSS_BACK2, 55.0f+Rand()*10.0f);
+ }
+ }
+ else if ( m_actionType == MSS_BACK2 ) // moves on the back?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ if ( rand()%10 == 0 )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += (Rand()-0.5f)*8.0f;
+ pos.z += (Rand()-0.5f)*8.0f;
+ pos.y -= 1.0f;
+ speed.x = (Rand()-0.5f)*2.0f;
+ speed.z = (Rand()-0.5f)*2.0f;
+ speed.y = Rand()*2.0f;
+ dim.x = Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+ }
+
+ dir = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ dir.x = sinf(m_armTimeAbs* 3.0f)*0.20f+
+ sinf(m_armTimeAbs* 6.0f)*0.20f+
+ sinf(m_armTimeAbs*10.0f)*0.20f+
+ sinf(m_armTimeAbs*17.0f)*0.30f+PI;
+ dir.y = sinf(m_armTimeAbs* 4.0f)*0.02f+
+ sinf(m_armTimeAbs* 5.0f)*0.02f+
+ sinf(m_armTimeAbs*11.0f)*0.02f+
+ sinf(m_armTimeAbs*18.0f)*0.03f;
+ dir.z = sinf(m_armTimeAbs* 2.0f)*0.02f+
+ sinf(m_armTimeAbs* 7.0f)*0.02f+
+ sinf(m_armTimeAbs*13.0f)*0.02f+
+ sinf(m_armTimeAbs*15.0f)*0.03f;
+ SetCirVibration(dir);
+ dir = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*5.0f)*0.05f); // tail
+ m_object->SetAngleY(2, cosf(m_armTimeAbs*5.0f)*0.20f); // head
+ m_object->SetAngleZ(1, 0.4f); // tail
+ m_object->SetAngleZ(2, 0.0f); // head
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(MSS_BACK3, 0.4f);
+ }
+ }
+ else if ( m_actionType == MSS_BACK3 ) // recovers on the legs?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (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 < 0.5f )
+ {
+ dir.x = 0.0f;
+ dir.y = powf(m_progress/0.5f, 2.0f)*5.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*5.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ dir.x = (1.0f-m_progress)*PI;
+ dir.y = 0.0f;
+ dir.z = 0.0f;
+ SetCirVibration(dir);
+
+ dir = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(-1);
+ m_object->SetFixed(FALSE); // moving again
+ }
+ }
+ else
+ {
+ if ( bStop )
+ {
+ dir = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+ }
+ else
+ {
+ a = Mod(m_armMember, 1.0f);
+ if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
+ else a = 3.0f-4.0f*a; // 1..-1
+ dir.x = sinf(a)*0.05f;
+
+ s = Mod(m_armMember/2.0f, 1.0f);
+ if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
+ else s = 3.0f-4.0f*s; // 1..-1
+ dir.z = sinf(s)*0.1f;
+
+ dir.y = 0.0f;
+ SetInclinaison(dir);
+ }
+
+ dir = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ SetCirVibration(dir);
+
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.7f)*0.02f); // tail
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.3f)*0.05f);
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*2.4f)*0.10f);
+ m_object->SetZoom(1, 1.0f+sinf(m_armTimeAbs*3.3f)*0.05f);
+
+ m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.4f)*0.20f); // head
+ m_object->SetAngleX(2, sinf(m_armTimeAbs*1.9f)*0.10f);
+ m_object->SetAngleY(2, sinf(m_armTimeAbs*2.1f)*0.10f);
+
+ m_object->SetAngleY(35, sinf(m_armTimeAbs*3.1f)*0.20f); // mandible
+ m_object->SetAngleY(36, -sinf(m_armTimeAbs*3.1f)*0.20f); // mandible
+ }
+
+ return TRUE;
+}
+
+
diff --git a/src/object/motion/motionspider.h b/src/object/motion/motionspider.h
new file mode 100644
index 0000000..294daf3
--- /dev/null
+++ b/src/object/motion/motionspider.h
@@ -0,0 +1,78 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionspider.h
+
+#ifndef _MOTIONSPIDER_H_
+#define _MOTIONSPIDER_H_
+
+
+#include "motion.h"
+
+
+class CInstanceManager;
+class CEngine;
+class CLight;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CBrain;
+class CPhysics;
+class CObject;
+
+
+#define MS_MARCH 0
+#define MS_STOP 1
+#define MS_SPEC 2
+
+#define MSS_BURN 0
+#define MSS_RUIN 1
+#define MSS_EXPLO 2
+#define MSS_BACK1 3
+#define MSS_BACK2 4
+#define MSS_BACK3 5
+
+
+class CMotionSpider : public CMotion
+{
+public:
+ CMotionSpider(CInstanceManager* iMan, CObject* object);
+ ~CMotionSpider();
+
+ void DeleteObject(BOOL bAll=FALSE);
+ BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power);
+ BOOL EventProcess(const Event &event);
+
+protected:
+ void CreatePhysics();
+ BOOL EventFrame(const Event &event);
+
+protected:
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeMarch;
+ float m_armTimeAction;
+ short m_armAngles[3*4*4*3*3 + 3*4*4*6];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ BOOL m_bArmStop;
+ float m_lastParticule;
+};
+
+
+#endif //_MOTIONSPIDER_H_
diff --git a/src/object/motion/motiontoto.cpp b/src/object/motion/motiontoto.cpp
new file mode 100644
index 0000000..afd5779
--- /dev/null
+++ b/src/object/motion/motiontoto.cpp
@@ -0,0 +1,886 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motiontoto.cpp
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "math3d.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "light.h"
+#include "particule.h"
+#include "terrain.h"
+#include "water.h"
+#include "object.h"
+#include "physics.h"
+#include "brain.h"
+#include "modfile.h"
+#include "robotmain.h"
+#include "sound.h"
+#include "motion.h"
+#include "motiontoto.h"
+
+
+
+#define START_TIME 1000.0f // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionToto::CMotionToto(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ CMotion::CMotion(iMan, object);
+
+ m_time = 0.0f;
+ m_bDisplayInfo = FALSE;
+ m_bQuickPos = FALSE;
+ m_bStartAction = FALSE;
+ m_speedAction = 20.0f;
+ m_soundChannel = -1;
+ m_clownRadius = 0.0f;
+ m_clownDelay = 0.0f;
+ m_clownTime = 0.0f;
+ m_blinkTime = 0.0f;
+ m_blinkProgress = -1.0f;
+ m_lastMotorParticule = 0.0f;
+ m_type = OBJECT_NULL;
+ m_mousePos = FPOINT(0.0f, 0.0f);
+}
+
+// Object's destructor.
+
+CMotionToto::~CMotionToto()
+{
+}
+
+
+// Removes an object.
+
+void CMotionToto::DeleteObject(BOOL bAll)
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->Stop(m_soundChannel);
+ m_soundChannel = -1;
+ }
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+BOOL CMotionToto::Create(D3DVECTOR pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 10 ) return FALSE;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\toto1.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // Creates mouth.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\toto2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, D3DVECTOR(1.00f, 0.17f, 0.00f));
+
+ // Creates the left eye.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\toto3.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, D3DVECTOR(0.85f, 1.04f, 0.25f));
+ m_object->SetAngleY(2, -20.0f*PI/180.0f);
+
+ // Creates the right eye.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 0);
+ pModFile->ReadModel("objects\\toto3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, D3DVECTOR(0.85f, 1.04f, -0.25f));
+ m_object->SetAngleY(3, 20.0f*PI/180.0f);
+
+ // Creates left antenna.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 0);
+ pModFile->ReadModel("objects\\toto4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, D3DVECTOR(0.0f, 1.9f, 0.3f));
+ m_object->SetAngleX(4, 30.0f*PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 4);
+ pModFile->ReadModel("objects\\toto4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, D3DVECTOR(0.0f, 0.67f, 0.0f));
+ m_object->SetAngleX(5, 30.0f*PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 5);
+ pModFile->ReadModel("objects\\toto5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, D3DVECTOR(0.0f, 0.70f, 0.0f));
+ m_object->SetAngleX(6, 30.0f*PI/180.0f);
+
+ // Creates right antenna.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\toto4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, D3DVECTOR(0.0f, 1.9f, -0.3f));
+ m_object->SetAngleX(7, -30.0f*PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 7);
+ pModFile->ReadModel("objects\\toto4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, D3DVECTOR(0.0f, 0.67f, 0.0f));
+ m_object->SetAngleX(8, -30.0f*PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 8);
+ pModFile->ReadModel("objects\\toto5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, D3DVECTOR(0.0f, 0.70f, 0.0f));
+ m_object->SetAngleX(9, -30.0f*PI/180.0f);
+
+ m_object->SetZoom(0, 0.5f); // is little
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return TRUE;
+}
+
+
+// Beginning of the display of informations, with foo in the left margin.
+
+void CMotionToto::StartDisplayInfo()
+{
+return;
+//?
+ m_bDisplayInfo = TRUE;
+
+ m_actionType = -1;
+ m_actionTime = 0.0f;
+ m_progress = 0.0f;
+
+ m_object->SetAngleY(0, 0.0f);
+ m_mousePos = FPOINT(0.5f, 0.5f);
+}
+
+// End of the display of informations.
+
+void CMotionToto::StopDisplayInfo()
+{
+ m_bDisplayInfo = FALSE;
+ m_bQuickPos = TRUE;
+}
+
+// Gives the position of the mouse.
+
+void CMotionToto::SetMousePos(FPOINT pos)
+{
+ m_mousePos = pos;
+}
+
+
+// Management of an event.
+
+BOOL CMotionToto::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ return TRUE;
+}
+
+// Management of an event.
+
+BOOL CMotionToto::EventFrame(const Event &event)
+{
+ D3DMATRIX* mat;
+ D3DVECTOR eye, lookat, dir, perp, nPos, aPos, pos, speed;
+ D3DVECTOR vibLin, vibCir, dirSpeed, aAntenna;
+ FPOINT dim;
+ POINT wDim;
+ ParticuleType type;
+ float progress, focus, distance, shift, verti, level, zoom;
+ float aAngle, nAngle, mAngle, angle, linSpeed, cirSpeed;
+ int sheet, i, r;
+ BOOL bHidden;
+
+ if ( m_engine->RetPause() &&
+ !m_main->RetInfoLock() ) return TRUE;
+
+ if ( m_bDisplayInfo ) // "looks" mouse?
+ {
+ bHidden = FALSE;
+ }
+ else
+ {
+ bHidden = FALSE;
+
+ if ( m_main->RetMovieLock() ) // current movie?
+ {
+ bHidden = TRUE;
+ }
+ if ( !m_engine->RetTotoMode() )
+ {
+ if ( !m_main->RetEditLock() ) // current edition?
+ {
+ bHidden = TRUE;
+ }
+ }
+ }
+
+ if ( bHidden )
+ {
+ nPos = m_object->RetPosition(0);
+ m_terrain->MoveOnFloor(nPos, TRUE);
+ nPos.y -= 100.0f; // hidden under the ground!
+ m_object->SetPosition(0, nPos);
+ return TRUE;
+ }
+
+ m_time += event.rTime;
+ m_blinkTime -= event.rTime;
+
+ progress = 0.0f;
+ if ( m_actionType != -1 ) // current action?
+ {
+ if ( m_progress < 0.15f )
+ {
+ progress = m_progress/0.15f;
+ }
+ else if ( m_progress < 0.85f )
+ {
+ progress = 1.0f;
+ }
+ else
+ {
+ progress = (1.0f-m_progress)/0.15f;
+ }
+ }
+
+ if ( m_progress >= 1.0f )
+ {
+ m_actionType = -1; // action ended
+ m_actionTime = 0.0f;
+ m_progress = 0.0f;
+
+ m_clownTime = 0.0f;
+ m_clownDelay = 0.0f;
+ }
+
+ focus = m_engine->RetFocus();
+ eye = m_engine->RetEyePt();
+ lookat = m_engine->RetLookatPt();
+
+ vibLin = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ vibCir = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ aAntenna = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ aAntenna.x += 30.0f*PI/180.0f;
+
+ // Calculates the new position.
+ if ( m_bDisplayInfo )
+ {
+ wDim = m_engine->RetDim();
+ nPos.x = -4.0f*((float)wDim.x/(float)wDim.y)/(640.0f/480.0f);
+ nPos.y = -0.5f;
+ nPos.z = 7.0f; // in the left margin
+
+ linSpeed = 0.0f;
+ }
+ else
+ {
+#if 0
+ distance = 30.0f-progress*24.5f; // remoteness
+ shift = 18.0f-progress*15.4f; // shift is left
+ verti = 10.0f-progress* 9.6f; // shift at the top
+#else
+ distance = 30.0f-progress*18.0f; // remoteness
+ shift = 18.0f-progress*11.0f; // shift is left
+ verti = 10.0f-progress* 8.0f; // shift at the top
+#endif
+
+ if ( m_actionType == -1 &&
+ (m_type == OBJECT_HUMAN ||
+ m_type == OBJECT_TECH ||
+ m_type == OBJECT_MOBILEwa ||
+ m_type == OBJECT_MOBILEta ||
+ m_type == OBJECT_MOBILEfa ||
+ m_type == OBJECT_MOBILEia ||
+ m_type == OBJECT_MOBILEwc ||
+ m_type == OBJECT_MOBILEtc ||
+ m_type == OBJECT_MOBILEfc ||
+ m_type == OBJECT_MOBILEic ||
+ m_type == OBJECT_MOBILEwi ||
+ m_type == OBJECT_MOBILEti ||
+ m_type == OBJECT_MOBILEfi ||
+ m_type == OBJECT_MOBILEii ||
+ m_type == OBJECT_MOBILEws ||
+ m_type == OBJECT_MOBILEts ||
+ m_type == OBJECT_MOBILEfs ||
+ m_type == OBJECT_MOBILEis ||
+ m_type == OBJECT_MOBILErt ||
+ m_type == OBJECT_MOBILErc ||
+ m_type == OBJECT_MOBILErr ||
+ m_type == OBJECT_MOBILErs ||
+ m_type == OBJECT_MOBILEsa ||
+ m_type == OBJECT_MOBILEwt ||
+ m_type == OBJECT_MOBILEtt ||
+ m_type == OBJECT_MOBILEft ||
+ m_type == OBJECT_MOBILEit ||
+ m_type == OBJECT_MOBILEdr ) ) // vehicle?
+ {
+ m_clownTime += event.rTime;
+ if ( m_clownTime >= m_clownDelay )
+ {
+ if ( rand()%10 < 2 )
+ {
+ m_clownRadius = 2.0f+Rand()*10.0f;
+//? m_clownDelay = m_clownRadius/(2.0f+Rand()*2.0f);
+ m_clownDelay = 1.5f+Rand()*1.0f;
+ }
+ else
+ {
+ m_clownRadius = 0.0f;
+ m_clownDelay = 2.0f+Rand()*2.0f;
+ }
+ pos = m_object->RetPosition(0);
+ if ( pos.y < m_water->RetLevel() ) // underwater?
+ {
+ m_clownRadius /= 1.5f;
+ m_clownDelay *= 2.0f;
+ }
+ m_clownTime = 0.0f;
+ }
+ else
+ {
+ distance -= m_clownRadius*sinf(m_clownTime*PI*2.0f/m_clownDelay);
+ shift -= m_clownRadius-m_clownRadius*cosf(m_clownTime*PI*2.0f/m_clownDelay);
+ }
+
+ verti += (18.0f-shift)*0.2f;
+ }
+
+ distance /= focus;
+//? shift *= focus;
+ verti /= focus;
+
+ dir = Normalize(lookat-eye);
+ nPos = eye + dir*distance;
+
+ perp.x = -dir.z;
+ perp.y = dir.y;
+ perp.z = dir.x;
+ nPos = nPos + perp*shift;
+
+ nPos.y += verti;
+
+ if ( m_bQuickPos ) // immediately in place?
+ {
+ m_bQuickPos = FALSE;
+ linSpeed = 0.0f;
+ }
+ else
+ {
+ aPos = m_object->RetPosition(0);
+ if ( m_actionType == -1 )
+ {
+ level = 4.0f;
+ }
+ else
+ {
+ if ( m_bStartAction )
+ {
+ m_bStartAction = FALSE;
+ m_speedAction = Length(nPos, aPos)/15.0f;
+ if ( m_speedAction < 20.0f ) m_speedAction = 20.0f;
+ }
+ level = m_speedAction;
+ }
+ if ( level > 1.0f/event.rTime ) level = 1.0f/event.rTime;
+ nPos = aPos + (nPos-aPos)*event.rTime*level; // progression aPos -> nPos
+
+ linSpeed = Length2d(nPos, aPos)/event.rTime;
+ dirSpeed = (nPos-aPos)/event.rTime;
+ nPos.y -= linSpeed*0.015f*(1.0f-progress); // at ground level if moving fast
+ }
+ }
+
+ // Calculate the new angle.
+ nAngle = NormAngle(RotateAngle(eye.x-lookat.x, lookat.z-eye.z)-0.9f);
+ if ( linSpeed == 0.0f || m_actionType != -1 )
+ {
+ mAngle = nAngle;
+ }
+ else
+ {
+ mAngle = NormAngle(RotateAngle(dirSpeed.x, -dirSpeed.z));
+ }
+ level = Min(linSpeed*0.1f, 1.0f);
+ nAngle = nAngle*(1.0f-level) + mAngle*level;
+ aAngle = NormAngle(m_object->RetAngleY(0));
+
+ if ( nAngle < aAngle )
+ {
+ if ( nAngle+PI*2.0f-aAngle < aAngle-nAngle ) nAngle += PI*2.0f;
+ }
+ else
+ {
+ if ( aAngle+PI*2.0f-nAngle < nAngle-aAngle ) aAngle += PI*2.0f;
+ }
+ nAngle = aAngle + (nAngle-aAngle)*event.rTime*4.0f;
+
+ // Leans quotes if running.
+ cirSpeed = (aAngle-nAngle)/event.rTime;
+ angle = cirSpeed*0.3f*(1.0f-progress);
+ if ( angle > 0.7f ) angle = 0.7f;
+ if ( angle < -0.7f ) angle = -0.7f;
+ vibCir.x += angle*1.5f;
+ aAntenna.x += Abs(angle)*0.8f; // deviates
+
+ // Leans forward so quickly advance.
+ angle = linSpeed*0.10f*(1.0f-progress);
+ if ( angle > 1.0f ) angle = 1.0f;
+ vibCir.z -= angle/2.0f; // leans forward
+ aAntenna.z -= angle; // leans forward
+
+ // Calculates the residual motion.
+#if 1
+ vibLin.y += (sinf(m_time*2.00f)*0.5f+
+ sinf(m_time*2.11f)*0.2f)*(1.0f-progress);
+
+ vibCir.z += sinf(m_time*PI* 2.01f)*(PI/ 75.0f)+
+ sinf(m_time*PI* 2.51f)*(PI/100.0f)+
+ sinf(m_time*PI*19.01f)*(PI/200.0f);
+
+ vibCir.x += sinf(m_time*PI* 2.03f)*(PI/ 75.0f)+
+ sinf(m_time*PI* 2.52f)*(PI/100.0f)+
+ sinf(m_time*PI*19.53f)*(PI/200.0f);
+
+ vibCir.y += (sinf(m_time*PI* 1.07f)*(PI/ 10.0f)+
+ sinf(m_time*PI* 1.19f)*(PI/ 17.0f)+
+ sinf(m_time*PI* 1.57f)*(PI/ 31.0f))*(1.0f-progress);
+#endif
+
+ // Calculates the animations in action.
+ if ( m_actionType == MT_ERROR ) // no-no?
+ {
+ vibCir.y += progress*sinf(m_progress*PI*11.0f)*1.0f;
+ vibCir.z -= progress*0.5f; // leans forward
+
+ aAntenna.x -= progress*0.4f; // narrows
+ aAntenna.z += progress*1.0f; // leaning back
+ }
+
+ if ( m_actionType == MT_WARNING ) // warning?
+ {
+ vibCir.x += progress*sinf(m_progress*PI*17.0f)*0.5f;
+
+ aAntenna.x += progress*sinf(m_progress*PI*17.0f)*0.5f; // deviates
+ aAntenna.z += progress*cosf(m_progress*PI*17.0f)*0.5f; // turns
+ }
+
+ if ( m_actionType == MT_INFO ) // yes-yes?
+ {
+ vibCir.z += progress*sinf(m_progress*PI*19.0f)*0.7f;
+
+ aAntenna.x -= progress*0.2f; // narrows
+ aAntenna.z -= progress*cosf(m_progress*PI*19.0f)*0.9f; // turns
+ }
+
+ if ( m_actionType == MT_MESSAGE ) // message?
+ {
+ vibCir.x += progress*sinf(m_progress*PI*15.0f)*0.3f;
+ vibCir.z += progress*cosf(m_progress*PI*15.0f)*0.3f;
+
+ aAntenna.x -= progress*0.4f; // narrows
+ aAntenna.z -= progress*cosf(m_progress*PI*19.0f)*0.8f;
+ }
+
+ // Initialize the object.
+ if ( m_bDisplayInfo ) // "looks" mouse?
+ {
+ if ( m_mousePos.x < 0.15f )
+ {
+ progress = 1.0f-m_mousePos.x/0.15f;
+ vibCir.y += progress*PI/2.0f;
+ }
+ else
+ {
+ progress = (m_mousePos.x-0.15f)/0.85f;
+ vibCir.y -= progress*PI/3.0f;
+ }
+
+ angle = RotateAngle(m_mousePos.x-0.1f, m_mousePos.y-0.5f-vibLin.y*0.2f);
+ if ( angle < PI )
+ {
+ if ( angle > PI*0.5f ) angle = PI-angle;
+ if ( angle > PI*0.3f ) angle = PI*0.3f;
+ vibCir.z += angle;
+ }
+ else
+ {
+ angle = PI*2.0f-angle;
+ if ( angle > PI*0.5f ) angle = PI-angle;
+ if ( angle > PI*0.3f ) angle = PI*0.3f;
+ vibCir.z -= angle;
+ }
+ }
+ else
+ {
+ nPos.y += vibLin.y;
+ level = m_terrain->RetFloorLevel(nPos);
+ if ( nPos.y < level+2.0f )
+ {
+ nPos.y = level+2.0f; // just above the ground
+ }
+ nPos.y -= vibLin.y;
+ }
+ m_object->SetPosition(0, nPos);
+ m_object->SetAngleY(0, nAngle);
+
+ SetLinVibration(vibLin);
+ SetCirVibration(vibCir);
+
+ // Calculates the residual movement of the antennas.
+ pos = aAntenna*0.40f;
+ pos.x += sinf(m_time*PI*2.07f)*(PI/50.0f)+
+ sinf(m_time*PI*2.59f)*(PI/70.0f)+
+ sinf(m_time*PI*2.67f)*(PI/90.0f);
+
+ pos.y += sinf(m_time*PI*2.22f)*(PI/50.0f)+
+ sinf(m_time*PI*2.36f)*(PI/70.0f)+
+ sinf(m_time*PI*3.01f)*(PI/90.0f);
+
+ pos.z += sinf(m_time*PI*2.11f)*(PI/50.0f)+
+ sinf(m_time*PI*2.83f)*(PI/70.0f)+
+ sinf(m_time*PI*3.09f)*(PI/90.0f);
+
+ m_object->SetAngle(4, pos); // left antenna
+ m_object->SetAngle(5, pos); // left antenna
+ m_object->SetAngle(6, pos); // left antenna
+
+ pos = aAntenna*0.40f;
+ pos.x = -pos.x;
+ pos.x += sinf(m_time*PI*2.33f)*(PI/50.0f)+
+ sinf(m_time*PI*2.19f)*(PI/70.0f)+
+ sinf(m_time*PI*2.07f)*(PI/90.0f);
+
+ pos.y += sinf(m_time*PI*2.44f)*(PI/50.0f)+
+ sinf(m_time*PI*2.77f)*(PI/70.0f)+
+ sinf(m_time*PI*3.22f)*(PI/90.0f);
+
+ pos.z += sinf(m_time*PI*2.05f)*(PI/50.0f)+
+ sinf(m_time*PI*2.38f)*(PI/70.0f)+
+ sinf(m_time*PI*2.79f)*(PI/90.0f);
+
+ m_object->SetAngle(7, pos); // right antenna
+ m_object->SetAngle(8, pos); // right antenna
+ m_object->SetAngle(9, pos); // right antenna
+
+ // Movement of the mouth.
+ if ( m_actionType == MT_ERROR ) // no-no?
+ {
+ m_object->SetAngleX(1, 0.0f);
+ m_object->SetAngleZ(1, 0.2f+sinf(m_time*10.0f)*0.2f);
+ m_object->SetZoomY(1, 2.0f+sinf(m_time*10.0f));
+ m_object->SetZoomZ(1, 1.0f);
+ }
+ else if ( m_actionType == MT_WARNING ) // warning?
+ {
+ m_object->SetAngleX(1, 15.0f*PI/180.0f);
+ m_object->SetAngleZ(1, 0.0f);
+ m_object->SetZoomY(1, 1.0f);
+ m_object->SetZoomZ(1, 1.0f);
+ }
+ else if ( m_actionType == MT_INFO ) // yes-yes?
+ {
+ m_object->SetAngleX(1, 0.0f);
+ m_object->SetAngleZ(1, 0.0f);
+ m_object->SetZoomY(1, 1.0f);
+ m_object->SetZoomZ(1, 0.7f+sinf(m_time*10.0f)*0.3f);
+ }
+ else if ( m_actionType == MT_MESSAGE ) // message?
+ {
+ m_object->SetAngleX(1, 0.0f);
+ m_object->SetAngleZ(1, 0.0f);
+ m_object->SetZoomY(1, 1.0f);
+ m_object->SetZoomZ(1, 0.8f+sinf(m_time*7.0f)*0.2f);
+ }
+ else
+ {
+ m_object->SetAngleX(1, 0.0f);
+ m_object->SetAngleZ(1, 0.0f);
+ m_object->SetZoomY(1, 1.0f);
+ m_object->SetZoomZ(1, 1.0f);
+ }
+
+ // Eye blinking management.
+ if ( m_blinkTime <= 0.0f && m_blinkProgress == -1.0f )
+ {
+ m_blinkProgress = 0.0f;
+ }
+
+ if ( m_blinkProgress >= 0.0f )
+ {
+ m_blinkProgress += event.rTime*3.2f;
+
+ if ( m_blinkProgress < 1.0f )
+ {
+ if ( m_blinkProgress < 0.5f ) zoom = m_blinkProgress/0.5f;
+ else zoom = 2.0f-m_blinkProgress/0.5f;
+ m_object->SetZoomY(2, 1.0f-zoom*0.9f);
+ m_object->SetZoomY(3, 1.0f-zoom*0.9f);
+ }
+ else
+ {
+ m_blinkProgress = -1.0f;
+ m_blinkTime = 0.1f+Rand()*4.0f;
+ m_object->SetZoomY(2, 1.0f);
+ m_object->SetZoomY(3, 1.0f);
+ }
+ }
+
+ if ( m_actionType == MT_ERROR ) // no-no?
+ {
+ m_object->SetAngleX(2, -30.0f*PI/180.0f);
+ m_object->SetAngleX(3, 30.0f*PI/180.0f);
+ }
+ else if ( m_actionType == MT_WARNING ) // warning?
+ {
+ m_object->SetAngleX(2, -15.0f*PI/180.0f);
+ m_object->SetAngleX(3, 15.0f*PI/180.0f);
+ }
+ else if ( m_actionType == MT_INFO ) // yes-yes?
+ {
+ m_object->SetAngleX(2, 40.0f*PI/180.0f);
+ m_object->SetAngleX(3, -40.0f*PI/180.0f);
+ }
+ else if ( m_actionType == MT_MESSAGE ) // message?
+ {
+ m_object->SetAngleX(2, 20.0f*PI/180.0f);
+ m_object->SetAngleX(3, -20.0f*PI/180.0f);
+ }
+ else
+ {
+ m_object->SetAngleX(2, 0.0f);
+ m_object->SetAngleX(3, 0.0f);
+ }
+
+ mat = m_object->RetWorldMatrix(0); // must be done every time!
+
+ // Generates particles.
+ if ( m_time-m_lastMotorParticule >= m_engine->ParticuleAdapt(0.05f) )
+ {
+ m_lastMotorParticule = m_time;
+
+ if ( m_bDisplayInfo ) sheet = SH_FRONT;
+ else sheet = SH_WORLD;
+
+ pos = m_object->RetPosition(0);
+ if ( !m_bDisplayInfo &&
+ pos.y < m_water->RetLevel() ) // underwater?
+ {
+ float t = Mod(m_time, 3.5f);
+ if ( t >= 2.2f || ( t >= 1.2f && t <= 1.4f ) ) // breathe?
+ {
+ pos = D3DVECTOR(1.0f, 0.2f, 0.0f);
+ pos.z += (Rand()-0.5f)*0.5f;
+
+ speed = pos;
+ speed.y += 5.0f+Rand()*5.0f;
+ speed.x += Rand()*2.0f;
+ speed.z += (Rand()-0.5f)*2.0f;
+
+ pos = Transform(*mat, pos);
+ speed = Transform(*mat, speed)-pos;
+
+ dim.x = 0.12f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBUBBLE, 3.0f, 0.0f, 0.0f);
+ }
+ }
+ else // out of water?
+ {
+ pos = D3DVECTOR(0.0f, -0.5f, 0.0f);
+ pos.z += (Rand()-0.5f)*0.5f;
+
+ speed = pos;
+ speed.y -= (1.5f+Rand()*1.5f) + vibLin.y;
+ speed.x += (Rand()-0.5f)*2.0f;
+ speed.z += (Rand()-0.5f)*2.0f;
+
+// mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+ speed = Transform(*mat, speed)-pos;
+
+ dim.x = (Rand()*0.4f+0.4f)*(1.0f+Min(linSpeed*0.1f, 5.0f));
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTITOTO, 1.0f+Rand()*1.0f, 0.0f, 1.0f, sheet);
+ }
+
+ if ( m_actionType != -1 && // current action?
+ m_progress <= 0.85f )
+ {
+ pos.x = (Rand()-0.5f)*1.0f;
+ pos.y = (Rand()-0.5f)*1.0f+3.5f;
+ pos.z = (Rand()-0.5f)*1.0f;
+ pos = Transform(*mat, pos);
+ speed = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ dim.x = (Rand()*0.3f+0.3f);
+ dim.y = dim.x;
+ if ( m_actionType == MT_ERROR ) type = PARTIERROR;
+ if ( m_actionType == MT_WARNING ) type = PARTIWARNING;
+ if ( m_actionType == MT_INFO ) type = PARTIINFO;
+ if ( m_actionType == MT_MESSAGE ) type = PARTIWARNING;
+ m_particule->CreateParticule(pos, speed, dim, type, 0.5f+Rand()*0.5f, 0.0f, 1.0f, sheet);
+
+ pos.x = 0.50f+(Rand()-0.5f)*0.80f;
+ pos.y = 0.86f+(Rand()-0.5f)*0.08f;
+ pos.z = 0.00f;
+ dim.x = (Rand()*0.04f+0.04f);
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim, type, 0.5f+Rand()*0.5f, 0.0f, 1.0f, SH_INTERFACE);
+ }
+
+//? if ( m_bDisplayInfo && m_main->RetGlint() )
+ if ( FALSE )
+ {
+ pos.x = (Rand()-0.5f)*1.4f;
+ pos.y = (Rand()-0.5f)*1.4f+3.5f;
+ pos.z = (Rand()-0.5f)*1.4f;
+ pos = Transform(*mat, pos);
+ speed = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ dim.x = (Rand()*0.5f+0.5f);
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 0.5f+Rand()*0.5f, 0.0f, 1.0f, sheet);
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ pos.x = 0.60f+(Rand()-0.5f)*0.76f;
+ pos.y = 0.47f+(Rand()-0.5f)*0.90f;
+ pos.z = 0.00f;
+ r = rand()%4;
+ if ( r == 0 ) pos.x = 0.21f; // the left edge
+ else if ( r == 1 ) pos.x = 0.98f; // the right edge
+ else if ( r == 2 ) pos.y = 0.02f; // on the lower edge
+ else pos.y = 0.92f; // on the upper edge
+ dim.x = (Rand()*0.02f+0.02f);
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 0.5f+Rand()*0.5f, 0.0f, 1.0f, SH_INTERFACE);
+ }
+ }
+ }
+
+ // Move the sound.
+ if ( m_soundChannel != -1 )
+ {
+ if ( !m_sound->Position(m_soundChannel, m_object->RetPosition(0)) )
+ {
+ m_soundChannel = -1;
+ }
+ }
+
+ return TRUE;
+}
+
+
+// Starts an action.
+
+Error CMotionToto::SetAction(int action, float time)
+{
+ Sound sound;
+
+ CMotion::SetAction(action, time);
+
+ m_bStartAction = TRUE;
+
+ sound = SOUND_CLICK;
+ if ( action == MT_ERROR ) sound = SOUND_ERROR;
+ if ( action == MT_WARNING ) sound = SOUND_WARNING;
+ if ( action == MT_INFO ) sound = SOUND_INFO;
+ if ( action == MT_MESSAGE ) sound = SOUND_MESSAGE;
+
+ if ( sound != SOUND_CLICK )
+ {
+ m_soundChannel = m_sound->Play(sound, m_object->RetPosition(0));
+ }
+
+ return ERR_OK;
+}
+
+// Specifies the type of the object is attached to toto.
+
+void CMotionToto::SetLinkType(ObjectType type)
+{
+ m_type = type;
+}
+
+
diff --git a/src/object/motion/motiontoto.h b/src/object/motion/motiontoto.h
new file mode 100644
index 0000000..22955bb
--- /dev/null
+++ b/src/object/motion/motiontoto.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/.
+
+// motiontoto.h
+
+#ifndef _MOTIONTOTO_H_
+#define _MOTIONTOTO_H_
+
+
+#include "struct.h"
+#include "object.h"
+#include "motion.h"
+
+
+class CInstanceManager;
+class CEngine;
+class CLight;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CBrain;
+class CPhysics;
+
+
+#define MT_ERROR 0
+#define MT_WARNING 1
+#define MT_INFO 2
+#define MT_MESSAGE 3
+
+
+class CMotionToto : public CMotion
+{
+public:
+ CMotionToto(CInstanceManager* iMan, CObject* object);
+ ~CMotionToto();
+
+ void DeleteObject(BOOL bAll=FALSE);
+ BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power);
+ BOOL EventProcess(const Event &event);
+ Error SetAction(int action, float time=0.2f);
+ void SetLinkType(ObjectType type);
+
+ void StartDisplayInfo();
+ void StopDisplayInfo();
+ void SetMousePos(FPOINT pos);
+
+protected:
+ BOOL EventFrame(const Event &event);
+
+protected:
+ float m_time;
+ float m_lastMotorParticule;
+ BOOL m_bDisplayInfo;
+ BOOL m_bQuickPos;
+ BOOL m_bStartAction;
+ float m_speedAction;
+ float m_clownRadius;
+ float m_clownDelay;
+ float m_clownTime;
+ float m_blinkTime;
+ float m_blinkProgress;
+ int m_soundChannel;
+ ObjectType m_type;
+ FPOINT m_mousePos;
+};
+
+
+#endif //_MOTIONTOTO_H_
diff --git a/src/object/motion/motionvehicle.cpp b/src/object/motion/motionvehicle.cpp
new file mode 100644
index 0000000..73dae74
--- /dev/null
+++ b/src/object/motion/motionvehicle.cpp
@@ -0,0 +1,2091 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionvehicle.cpp
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "math3d.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "light.h"
+#include "particule.h"
+#include "terrain.h"
+#include "object.h"
+#include "physics.h"
+#include "brain.h"
+#include "camera.h"
+#include "modfile.h"
+#include "sound.h"
+#include "motion.h"
+#include "motionvehicle.h"
+
+
+
+#define ARM_NEUTRAL_ANGLE1 110.0f*PI/180.0f
+#define ARM_NEUTRAL_ANGLE2 -130.0f*PI/180.0f
+#define ARM_NEUTRAL_ANGLE3 -50.0f*PI/180.0f
+
+
+
+// Object's constructor.
+
+CMotionVehicle::CMotionVehicle(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ int i;
+
+ CMotion::CMotion(iMan, object);
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ m_wheelTurn[i] = 0.0f;
+ }
+ for ( i=0 ; i<3 ; i++ )
+ {
+ m_flyPaw[i] = 0.0f;
+ }
+ m_posTrackLeft = 0.0f;
+ m_posTrackRight = 0.0f;
+ m_partiReactor = -1;
+ m_armTimeAbs = 1000.0f;
+ m_armMember = 1000.0f;
+ m_canonTime = 0.0f;
+ m_lastTimeCanon = 0.0f;
+ m_wheelLastPos = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ m_wheelLastAngle = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ m_posKey = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ m_bFlyFix = FALSE;
+
+ m_bTraceDown = FALSE;
+ m_traceColor = 1; // black
+ m_traceWidth = 0.5f;
+}
+
+// Object's destructor.
+
+CMotionVehicle::~CMotionVehicle()
+{
+}
+
+
+// Removes an object.
+
+void CMotionVehicle::DeleteObject(BOOL bAll)
+{
+ if ( m_partiReactor != -1 )
+ {
+ m_particule->DeleteParticule(m_partiReactor);
+ m_partiReactor = -1;
+ }
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+BOOL CMotionVehicle::Create(D3DVECTOR pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ CObject* pPower;
+ int rank, i, j, parent;
+ D3DCOLORVALUE color;
+ char name[50];
+
+ if ( m_engine->RetRestCreate() < 1+5+18+1 ) return FALSE;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates the main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs )
+ {
+ pModFile->ReadModel("objects\\lem1f.mod");
+ }
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts )
+ {
+ pModFile->ReadModel("objects\\lem1t.mod");
+ }
+ if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEws )
+ {
+ if ( m_object->RetTrainer() )
+ {
+ pModFile->ReadModel("objects\\lem1wt.mod");
+ }
+ else
+ {
+ pModFile->ReadModel("objects\\lem1w.mod");
+ }
+ }
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEis )
+ {
+ pModFile->ReadModel("objects\\lem1i.mod");
+ }
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ pModFile->ReadModel("objects\\roller1.mod");
+ }
+ if ( type == OBJECT_MOBILEsa )
+ {
+ pModFile->ReadModel("objects\\subm1.mod");
+ }
+ if ( type == OBJECT_MOBILEtg )
+ {
+ pModFile->ReadModel("objects\\target.mod");
+ }
+ if ( type == OBJECT_MOBILEwt )
+ {
+ pModFile->ReadModel("objects\\trainerw.mod");
+ }
+ if ( type == OBJECT_MOBILEft )
+ {
+ pModFile->ReadModel("objects\\trainerf.mod");
+ }
+ if ( type == OBJECT_MOBILEtt )
+ {
+ pModFile->ReadModel("objects\\trainert.mod");
+ }
+ if ( type == OBJECT_MOBILEit )
+ {
+ pModFile->ReadModel("objects\\traineri.mod");
+ }
+ if ( type == OBJECT_MOBILEdr )
+ {
+ pModFile->ReadModel("objects\\drawer1.mod");
+ }
+ if ( type == OBJECT_APOLLO2 )
+ {
+ pModFile->ReadModel("objects\\apolloj1.mod");
+ }
+ pModFile->CreateEngineObject(rank);
+
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have a obligatory collision
+ // with a sphere of center (0, y, 0) (see GetCrashSphere).
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ m_object->CreateCrashSphere(D3DVECTOR(0.0f, 4.0f, 0.0f), 6.5f, SOUND_BOUMm, 0.45f);
+ m_object->SetGlobalSphere(D3DVECTOR(0.0f, 3.0f, 0.0f), 7.0f);
+ }
+ else if ( type == OBJECT_MOBILEsa )
+ {
+ m_object->CreateCrashSphere(D3DVECTOR(0.0f, 3.0f, 0.0f), 4.5f, SOUND_BOUMm, 0.45f);
+ m_object->SetGlobalSphere(D3DVECTOR(0.0f, 3.0f, 0.0f), 6.0f);
+ }
+ else if ( type == OBJECT_MOBILEdr )
+ {
+ m_object->CreateCrashSphere(D3DVECTOR(0.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ m_object->SetGlobalSphere(D3DVECTOR(0.0f, 3.0f, 0.0f), 7.0f);
+ }
+ else if ( type == OBJECT_APOLLO2 )
+ {
+ m_object->CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ }
+ else
+ {
+ m_object->CreateCrashSphere(D3DVECTOR(0.0f, 3.0f, 0.0f), 4.5f, SOUND_BOUMm, 0.45f);
+ m_object->SetGlobalSphere(D3DVECTOR(0.0f, 4.0f, 0.0f), 6.0f);
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia )
+ {
+ // Creates the arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\lem2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, D3DVECTOR(0.0f, 5.3f, 0.0f));
+ m_object->SetAngleZ(1, ARM_NEUTRAL_ANGLE1);
+
+ // Creates the forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\lem3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, D3DVECTOR(5.0f, 0.0f, 0.0f));
+ m_object->SetAngleZ(2, ARM_NEUTRAL_ANGLE2);
+
+ // Creates the hand.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\lem4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, D3DVECTOR(3.5f, 0.0f, 0.0f));
+ m_object->SetAngleZ(3, ARM_NEUTRAL_ANGLE3);
+ m_object->SetAngleX(3, PI/2.0f);
+
+ // Creates the close clamp.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 3);
+ pModFile->ReadModel("objects\\lem5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, D3DVECTOR(1.5f, 0.0f, 0.0f));
+ m_object->SetAngleZ(4, -PI*0.10f);
+
+ // Creates the remote clamp.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 3);
+ pModFile->ReadModel("objects\\lem6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, D3DVECTOR(1.5f, 0.0f, 0.0f));
+ m_object->SetAngleZ(5, PI*0.10f);
+ }
+
+ if ( type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis )
+ {
+ // Creates the arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\lem2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, D3DVECTOR(0.0f, 5.3f, 0.0f));
+ m_object->SetAngleZ(1, 110.0f*PI/180.0f);
+
+ // Creates the forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\lem3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, D3DVECTOR(5.0f, 0.0f, 0.0f));
+ m_object->SetAngleZ(2, -110.0f*PI/180.0f);
+
+ // Creates the sensor.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\lem4s.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, D3DVECTOR(3.5f, 0.0f, 0.0f));
+ m_object->SetAngleZ(3, -65.0f*PI/180.0f);
+ }
+
+ if ( type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic )
+ {
+ // Creates the cannon.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\canon.mod");
+ pModFile->CreateEngineObject(rank);
+//? m_object->SetPosition(1, D3DVECTOR(0.0f, 5.3f, 0.0f));
+ m_object->SetPosition(1, D3DVECTOR(0.0f, 5.3f, 0.0f));
+ m_object->SetAngleZ(1, 0.0f);
+ }
+
+ if ( type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii )
+ {
+ // Creates the insect cannon.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\canoni1.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, D3DVECTOR(0.0f, 5.3f, 0.0f));
+ m_object->SetAngleZ(1, 0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\canoni2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, D3DVECTOR(0.0f, 2.5f, 0.0f));
+ m_object->SetAngleZ(2, 0.0f);
+ }
+
+ if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEwt )
+ {
+ // Creates the right-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, D3DVECTOR(-3.0f, 1.0f, -3.0f));
+
+ // Creates the left-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, D3DVECTOR(-3.0f, 1.0f, 3.0f));
+ m_object->SetAngleY(7, PI);
+
+ // Creates the right-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, D3DVECTOR(2.0f, 1.0f, -3.0f));
+
+ // Creates the left-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, D3DVECTOR(2.0f, 1.0f, 3.0f));
+ m_object->SetAngleY(9, PI);
+ }
+
+ if ( type == OBJECT_MOBILEtg )
+ {
+ // Creates the right-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, D3DVECTOR(-2.0f, 1.0f, -3.0f));
+
+ // Creates the left-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, D3DVECTOR(-2.0f, 1.0f, 3.0f));
+ m_object->SetAngleY(7, PI);
+
+ // Creates the right-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, D3DVECTOR(3.0f, 1.0f, -3.0f));
+
+ // Creates the left-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, D3DVECTOR(3.0f, 1.0f, 3.0f));
+ m_object->SetAngleY(9, PI);
+ }
+
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts ) // caterpillars?
+ {
+ // Creates the right caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\lem2t.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, D3DVECTOR(0.0f, 2.0f, -3.0f));
+
+ // Creates the left caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\lem3t.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, D3DVECTOR(0.0f, 2.0f, 3.0f));
+ }
+
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ) // large caterpillars?
+ {
+ // Creates the right caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\roller2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, D3DVECTOR(0.0f, 2.0f, -3.0f));
+
+ // Creates the left caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\roller3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, D3DVECTOR(0.0f, 2.0f, 3.0f));
+ }
+
+ if ( type == OBJECT_MOBILEsa ) // underwater caterpillars?
+ {
+ // Creates the right caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\subm4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, D3DVECTOR(0.0f, 1.0f, -3.0f));
+
+ // Creates the left caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\subm5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, D3DVECTOR(0.0f, 1.0f, 3.0f));
+ }
+
+ if ( type == OBJECT_MOBILEdr ) // caterpillars?
+ {
+ // Creates the right caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\drawer2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, D3DVECTOR(0.0f, 1.0f, -3.0f));
+
+ // Creates the left caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\drawer3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, D3DVECTOR(0.0f, 1.0f, 3.0f));
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEft ) // flying?
+ {
+ // Creates the front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\lem2f.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, D3DVECTOR(1.7f, 3.0f, 0.0f));
+
+ // Creates the right-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\lem2f.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, D3DVECTOR(-1.8f, 3.0f, -1.5f));
+ m_object->SetAngleY(7, 120.0f*PI/180.0f);
+
+ // Creates the left-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\lem2f.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, D3DVECTOR(-1.8f, 3.0f, 1.5f));
+ m_object->SetAngleY(8, -120.0f*PI/180.0f);
+ }
+
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILEii ) // insect legs?
+ {
+ float table[] =
+ {
+ // x y z
+ -1.5f, 1.2f, -0.7f, // back leg
+ 0.0f, 0.0f, -1.0f,
+ 0.0f, 0.0f, -2.0f,
+
+ 0.0f, 1.2f, -0.9f, // middle leg
+ 0.0f, 0.0f, -1.0f,
+ 0.0f, 0.0f, -2.0f,
+
+ 1.5f, 1.2f, -0.7f, // front leg
+ 0.0f, 0.0f, -1.0f,
+ 0.0f, 0.0f, -2.0f,
+ };
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ for ( j=0 ; j<3 ; j++ )
+ {
+ sprintf(name, "objects\\ant%d.mod", j+4); // 4..6
+
+ // Creates the right leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6+i*3+j, rank);
+ if ( j == 0 ) parent = 0;
+ else parent = 6+i*3+j-1;
+ m_object->SetObjectParent(6+i*3+j, parent);
+ pModFile->ReadModel(name);
+ pModFile->CreateEngineObject(rank);
+ pos.x = table[i*9+j*3+0];
+ pos.y = table[i*9+j*3+1];
+ pos.z = table[i*9+j*3+2];
+ m_object->SetPosition(6+i*3+j, pos);
+
+ // Creates the left leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(15+i*3+j, rank);
+ if ( j == 0 ) parent = 0;
+ else parent = 15+i*3+j-1;
+ m_object->SetObjectParent(15+i*3+j, parent);
+ pModFile->ReadModel(name);
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ pos.x = table[i*9+j*3+0];
+ pos.y = table[i*9+j*3+1];
+ pos.z = -table[i*9+j*3+2];
+ m_object->SetPosition(15+i*3+j, pos);
+ }
+ }
+ }
+
+ if ( type == OBJECT_MOBILErt )
+ {
+ // Creates the holder.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\roller2t.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, D3DVECTOR(0.0f, 0.0f, 0.0f));
+ m_object->SetAngleZ(1, 0.0f);
+
+ // Creates the pestle.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\roller3t.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, D3DVECTOR(9.0f, 4.0f, 0.0f));
+ m_object->SetAngleZ(2, 0.0f);
+ }
+
+ if ( type == OBJECT_MOBILErc )
+ {
+ // Creates the holder.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\roller2c.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, D3DVECTOR(3.0f, 4.6f, 0.0f));
+ m_object->SetAngleZ(1, PI/8.0f);
+
+ // Creates the cannon.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\roller3p.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, D3DVECTOR(7.0f, 6.5f, 0.0f));
+ m_object->SetAngleZ(2, 0.0f);
+ }
+
+ if ( type == OBJECT_MOBILErr )
+ {
+ // Creates the holder.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\recover1.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, D3DVECTOR(2.0f, 5.0f, 0.0f));
+
+ // Creates the right arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\recover2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, D3DVECTOR(0.1f, 0.0f, -5.0f));
+ m_object->SetAngleZ(2, 126.0f*PI/180.0f);
+
+ // Creates the right forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\recover3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, D3DVECTOR(5.0f, 0.0f, -0.5f));
+ m_object->SetAngleZ(3, -144.0f*PI/180.0f);
+
+ // Creates the left arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 1);
+ pModFile->ReadModel("objects\\recover2.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, D3DVECTOR(0.1f, 0.0f, 5.0f));
+ m_object->SetAngleZ(4, 126.0f*PI/180.0f);
+
+ // Creates the left forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 4);
+ pModFile->ReadModel("objects\\recover3.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, D3DVECTOR(5.0f, 0.0f, 0.5f));
+ m_object->SetAngleZ(5, -144.0f*PI/180.0f);
+ }
+
+ if ( type == OBJECT_MOBILErs )
+ {
+ // Creates the holder.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\roller2s.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, D3DVECTOR(0.0f, 0.0f, 0.0f));
+ m_object->SetAngleZ(1, 0.0f);
+
+ // Creates the intermediate piston.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\roller3s.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, D3DVECTOR(7.0f, 4.5f, 0.0f));
+ m_object->SetAngleZ(2, 0.0f);
+
+ // Creates the piston with the sphere.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\roller4s.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, D3DVECTOR(0.0f, 1.0f, 0.0f));
+ m_object->SetAngleZ(3, 0.0f);
+ }
+
+ if ( type == OBJECT_MOBILEsa )
+ {
+ // Creates the holder.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\subm2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, D3DVECTOR(4.2f, 3.0f, 0.0f));
+
+ // Creates the right tong.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\subm3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, D3DVECTOR(0.5f, 0.0f, -1.5f));
+
+ // Creates the left tong.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 1);
+ pModFile->ReadModel("objects\\subm3.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, D3DVECTOR(0.5f, 0.0f, 1.5f));
+ }
+
+ if ( type == OBJECT_MOBILEdr )
+ {
+ // Creates the carousel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\drawer4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, D3DVECTOR(-3.0f, 3.0f, 0.0f));
+
+ // Creates the key.
+ if ( m_object->RetToy() )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\drawer5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_posKey = D3DVECTOR(3.0f, 5.7f, 0.0f);
+ m_object->SetPosition(2, m_posKey);
+ m_object->SetAngleY(2, 90.0f*PI/180.0f);
+ }
+
+ // Creates pencils.
+ for ( i=0 ; i<8 ; i++ )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10+i, rank);
+ m_object->SetObjectParent(10+i, 1);
+ sprintf(name, "objects\\drawer%d.mod", 10+i);
+ pModFile->ReadModel(name);
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10+i, D3DVECTOR(0.0f, 0.0f, 0.0f));
+ m_object->SetAngleY(10+i, 45.0f*PI/180.0f*i);
+ }
+ }
+
+ if ( type == OBJECT_MOBILEwt )
+ {
+ // Creates the key.
+ if ( m_object->RetToy() )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\drawer5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_posKey = D3DVECTOR(0.2f, 4.1f, 0.0f);
+ m_object->SetPosition(2, m_posKey);
+ m_object->SetAngleY(2, 90.0f*PI/180.0f);
+ }
+ }
+
+ if ( type == OBJECT_APOLLO2 )
+ {
+ // Creates the accessories.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\apolloj2.mod"); // antenna
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, D3DVECTOR(5.5f, 8.8f, 2.0f));
+ m_object->SetAngleY(1, -120.0f*PI/180.0f);
+ m_object->SetAngleZ(1, 45.0f*PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\apolloj3.mod"); // camera
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, D3DVECTOR(5.5f, 2.8f, -2.0f));
+ m_object->SetAngleY(2, 30.0f*PI/180.0f);
+
+ // Creates the wheels.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, D3DVECTOR(-5.75f, 1.65f, -5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, D3DVECTOR(-5.75f, 1.65f, 5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, D3DVECTOR(5.75f, 1.65f, -5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, D3DVECTOR(5.75f, 1.65f, 5.00f));
+
+ // Creates mud guards.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10, rank);
+ m_object->SetObjectParent(10, 0);
+ pModFile->ReadModel("objects\\apolloj6.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10, D3DVECTOR(-5.75f, 1.65f, -5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(11, rank);
+ m_object->SetObjectParent(11, 0);
+ pModFile->ReadModel("objects\\apolloj6.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(11, D3DVECTOR(-5.75f, 1.65f, 5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(12, rank);
+ m_object->SetObjectParent(12, 0);
+ pModFile->ReadModel("objects\\apolloj5.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(12, D3DVECTOR(5.75f, 1.65f, -5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(13, rank);
+ m_object->SetObjectParent(13, 0);
+ pModFile->ReadModel("objects\\apolloj5.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(13, D3DVECTOR(5.75f, 1.65f, 5.00f));
+ }
+
+#if 1
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ m_object->CreateShadowCircle(6.0f, 1.0f);
+ }
+ else if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEsa )
+ {
+ m_object->CreateShadowCircle(5.0f, 1.0f);
+ }
+ else if ( type == OBJECT_MOBILEdr )
+ {
+ m_object->CreateShadowCircle(4.5f, 1.0f);
+ }
+ else if ( type == OBJECT_APOLLO2 )
+ {
+ m_object->CreateShadowCircle(7.0f, 0.8f);
+ }
+ else
+ {
+ m_object->CreateShadowCircle(4.0f, 1.0f);
+ }
+#else
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ m_object->CreateShadowCircle(6.0f, 1.0f, D3DSHADOWTANK);
+ }
+ else if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts )
+ {
+ m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWTANK);
+ }
+ else if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs )
+ {
+ m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWFLY);
+ }
+ else if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEws )
+ {
+ m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWWHEEL);
+ }
+ else if ( type == OBJECT_APOLLO2 )
+ {
+ m_object->CreateShadowCircle(6.0f, 0.8f);
+ }
+ else
+ {
+ m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWNORM);
+ }
+#endif
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEft ) // flying?
+ {
+//? color.r = 0.5f-1.0f;
+//? color.g = 0.2f-1.0f;
+//? color.b = 0.0f-1.0f; // orange
+//? color.r = 0.8f;
+//? color.g = 0.6f;
+//? color.b = 0.0f; // yellow-orange
+ color.r = 0.0f;
+ color.g = 0.4f;
+ color.b = 0.8f; // blue
+ color.a = 0.0f;
+ m_object->CreateShadowLight(50.0f, color);
+ }
+
+ CreatePhysics(type);
+ m_object->SetFloorHeight(0.0f);
+
+ if ( power > 0.0f &&
+ type != OBJECT_MOBILEdr &&
+ type != OBJECT_APOLLO2 )
+ {
+ color.r = 1.0f;
+ color.g = 1.0f;
+ color.b = 0.0f; // yellow
+ color.a = 0.0f;
+ m_object->CreateEffectLight(20.0f, color);
+
+ // Creates the battery.
+ pPower = new CObject(m_iMan);
+ pPower->SetType(power<=1.0f?OBJECT_POWER:OBJECT_ATOMIC);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ pPower->SetObjectRank(0, rank);
+
+ if ( power <= 1.0f ) pModFile->ReadModel("objects\\power.mod");
+ else pModFile->ReadModel("objects\\atomic.mod");
+ pModFile->CreateEngineObject(rank);
+
+ pPower->SetPosition(0, m_object->RetCharacter()->posPower);
+ pPower->CreateCrashSphere(D3DVECTOR(0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ pPower->SetGlobalSphere(D3DVECTOR(0.0f, 1.0f, 0.0f), 1.5f);
+
+ pPower->SetTruck(m_object);
+ m_object->SetPower(pPower);
+
+ if ( power <= 1.0f ) pPower->SetEnergy(power);
+ else pPower->SetEnergy(power/100.0f);
+ }
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); //to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return TRUE;
+}
+
+// Creates the physics of the object.
+
+void CMotionVehicle::CreatePhysics(ObjectType type)
+{
+ Character* character;
+
+ character = m_object->RetCharacter();
+
+ if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEwt ) // wheels?
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 3.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.0f;
+ character->wheelRight = 4.0f;
+ character->posPower = D3DVECTOR(-3.2f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 20.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 30.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 8.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 8.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 12.0f);
+ }
+
+ if ( type == OBJECT_MOBILEtg )
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 4.0f;
+ character->wheelBack = 3.0f;
+ character->wheelLeft = 4.0f;
+ character->wheelRight = 4.0f;
+ character->posPower = D3DVECTOR(-3.2f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 20.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 15.0f);
+ }
+
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts ) // caterpillars?
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.8f;
+ character->wheelRight = 4.8f;
+ character->posPower = D3DVECTOR(-3.2f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 8.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 8.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 6.0f);
+ }
+
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEis ) // legs?
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 5.0f;
+ character->wheelRight = 5.0f;
+ character->posPower = D3DVECTOR(-3.2f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 8.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 10.0f);
+//? m_physics->SetLinMotionX(MO_TERFORCE, 15.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 15.0f);
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEft ) // flying?
+ {
+ m_physics->SetType(TYPE_FLYING);
+
+ character->wheelFront = 5.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.5f;
+ character->wheelRight = 4.5f;
+ character->posPower = D3DVECTOR(-3.2f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 50.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+ m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
+ m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.4f*PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.4f*PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 2.0f);
+ }
+
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ) // large caterpillars?
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 5.0f;
+ character->wheelBack = 5.0f;
+ character->wheelLeft = 6.0f;
+ character->wheelRight = 6.0f;
+ character->posPower = D3DVECTOR(-5.8f, 4.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 5.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 5.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.3f*PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.3f*PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 4.0f);
+ }
+
+ if ( type == OBJECT_MOBILEsa )
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.0f;
+ character->wheelRight = 4.0f;
+ character->posPower = D3DVECTOR(-5.0f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 5.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 5.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 10.0f);
+ }
+
+ if ( type == OBJECT_MOBILEdr )
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.0f;
+ character->wheelRight = 4.0f;
+ character->posPower = D3DVECTOR(-5.0f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 5.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 5.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 10.0f);
+ }
+
+ if ( type == OBJECT_APOLLO2 ) // jeep?
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 6.0f;
+ character->wheelBack = 6.0f;
+ character->wheelLeft = 5.0f;
+ character->wheelRight = 5.0f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 2.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 2.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 30.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.4f*PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.4f*PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 4.0f);
+ }
+}
+
+
+// Management of an event.
+
+BOOL CMotionVehicle::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+ }
+
+ return TRUE;
+}
+
+// Management of an event.
+
+BOOL CMotionVehicle::EventFrame(const Event &event)
+{
+ D3DMATRIX* mat;
+ Character* character;
+ D3DVECTOR pos, angle, floor;
+ ObjectType type;
+ float s, a, speedBL, speedBR, speedFL, speedFR, h, a1, a2;
+ float back, front, dist, radius, limit[2];
+
+ if ( m_engine->RetPause() ) return TRUE;
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return TRUE;
+
+ type = m_object->RetType();
+
+ if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_APOLLO2 ) // wheels?
+ {
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.0f;
+ a = m_physics->RetCirMotionY(MO_MOTSPEED)*3.0f;
+
+ if ( type == OBJECT_APOLLO2 ) s *= 0.5f;
+
+ speedBR = -s+a;
+ speedBL = s+a;
+ speedFR = -s+a;
+ speedFL = s+a;
+
+ m_object->SetAngleZ(6, m_object->RetAngleZ(6)+event.rTime*speedBR); // turning the wheels
+ m_object->SetAngleZ(7, m_object->RetAngleZ(7)+event.rTime*speedBL);
+ m_object->SetAngleZ(8, m_object->RetAngleZ(8)+event.rTime*speedFR);
+ m_object->SetAngleZ(9, m_object->RetAngleZ(9)+event.rTime*speedFL);
+
+ if ( s > 0.0f )
+ {
+ m_wheelTurn[0] = -a*0.05f;
+ m_wheelTurn[1] = -a*0.05f+PI;
+ m_wheelTurn[2] = a*0.05f;
+ m_wheelTurn[3] = a*0.05f+PI;
+ }
+ else if ( s < 0.0f )
+ {
+ m_wheelTurn[0] = a*0.05f;
+ m_wheelTurn[1] = a*0.05f+PI;
+ m_wheelTurn[2] = -a*0.05f;
+ m_wheelTurn[3] = -a*0.05f+PI;
+ }
+ else
+ {
+ m_wheelTurn[0] = Abs(a)*0.05f;
+ m_wheelTurn[1] = -Abs(a)*0.05f+PI;
+ m_wheelTurn[2] = -Abs(a)*0.05f;
+ m_wheelTurn[3] = Abs(a)*0.05f+PI;
+ }
+ m_object->SetAngleY(6, m_object->RetAngleY(6)+(m_wheelTurn[0]-m_object->RetAngleY(6))*event.rTime*8.0f);
+ m_object->SetAngleY(7, m_object->RetAngleY(7)+(m_wheelTurn[1]-m_object->RetAngleY(7))*event.rTime*8.0f);
+ m_object->SetAngleY(8, m_object->RetAngleY(8)+(m_wheelTurn[2]-m_object->RetAngleY(8))*event.rTime*8.0f);
+ m_object->SetAngleY(9, m_object->RetAngleY(9)+(m_wheelTurn[3]-m_object->RetAngleY(9))*event.rTime*8.0f);
+
+ if ( type == OBJECT_APOLLO2 )
+ {
+ m_object->SetAngleY(10, m_object->RetAngleY(6)+(m_wheelTurn[0]-m_object->RetAngleY(6))*event.rTime*8.0f);
+ m_object->SetAngleY(11, m_object->RetAngleY(7)+(m_wheelTurn[1]-m_object->RetAngleY(7))*event.rTime*8.0f+PI);
+ m_object->SetAngleY(12, m_object->RetAngleY(8)+(m_wheelTurn[2]-m_object->RetAngleY(8))*event.rTime*8.0f);
+ m_object->SetAngleY(13, m_object->RetAngleY(9)+(m_wheelTurn[3]-m_object->RetAngleY(9))*event.rTime*8.0f+PI);
+ }
+
+ pos = m_object->RetPosition(0);
+ angle = m_object->RetAngle(0);
+ if ( pos.x != m_wheelLastPos.x ||
+ pos.y != m_wheelLastPos.y ||
+ pos.z != m_wheelLastPos.z ||
+ angle.x != m_wheelLastAngle.x ||
+ angle.y != m_wheelLastAngle.y ||
+ angle.z != m_wheelLastAngle.z )
+ {
+ m_wheelLastPos = pos;
+ m_wheelLastAngle = angle;
+
+ if ( type == OBJECT_MOBILEtg )
+ {
+ back = -2.0f; // back wheels position
+ front = 3.0f; // front wheels position
+ dist = 3.0f; // distancing wheels Z
+ radius = 1.0f;
+ }
+ else if ( type == OBJECT_APOLLO2 )
+ {
+ back = -5.75f; // back wheels position
+ front = 5.75f; // front wheels position
+ dist = 5.00f; // distancing wheels Z
+ radius = 1.65f;
+ }
+ else
+ {
+ back = -3.0f; // back wheels position
+ front = 2.0f; // front wheels position
+ dist = 3.0f; // distancing wheels Z
+ radius = 1.0f;
+ }
+
+ if ( Length(pos, m_engine->RetEyePt()) < 50.0f ) // suspension?
+ {
+ character = m_object->RetCharacter();
+ mat = m_object->RetWorldMatrix(0);
+
+ pos.x = -character->wheelBack; // right back wheel
+ pos.z = -character->wheelRight;
+ pos.y = 0.0f;
+ pos = Transform(*mat, pos);
+ h = m_terrain->RetFloorHeight(pos);
+ if ( h > 0.5f ) h = 0.5f;
+ if ( h < -0.5f ) h = -0.5f;
+ pos.x = back;
+ pos.y = radius-h;
+ pos.z = -dist;
+ m_object->SetPosition(6, pos);
+ if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(10, pos);
+
+ pos.x = -character->wheelBack; // left back wheel
+ pos.z = character->wheelLeft;
+ pos.y = 0.0f;
+ pos = Transform(*mat, pos);
+ h = m_terrain->RetFloorHeight(pos);
+ if ( h > 0.5f ) h = 0.5f;
+ if ( h < -0.5f ) h = -0.5f;
+ pos.x = back;
+ pos.y = radius-h;
+ pos.z = dist;
+ m_object->SetPosition(7, pos);
+ if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(11, pos);
+
+ pos.x = character->wheelFront; // right front wheel
+ pos.z = -character->wheelRight;
+ pos.y = 0.0f;
+ pos = Transform(*mat, pos);
+ h = m_terrain->RetFloorHeight(pos);
+ if ( h > 0.5f ) h = 0.5f;
+ if ( h < -0.5f ) h = -0.5f;
+ pos.x = front;
+ pos.y = radius-h;
+ pos.z = -dist;
+ m_object->SetPosition(8, pos);
+ if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(12, pos);
+
+ pos.x = character->wheelFront; // left front wheel
+ pos.z = character->wheelLeft;
+ pos.y = 0.0f;
+ pos = Transform(*mat, pos);
+ h = m_terrain->RetFloorHeight(pos);
+ if ( h > 0.5f ) h = 0.5f;
+ if ( h < -0.5f ) h = -0.5f;
+ pos.x = front;
+ pos.y = radius-h;
+ pos.z = dist;
+ m_object->SetPosition(9, pos);
+ if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(13, pos);
+ }
+ else
+ {
+ m_object->SetPosition(6, D3DVECTOR(back, radius, -dist));
+ m_object->SetPosition(7, D3DVECTOR(back, radius, dist));
+ m_object->SetPosition(8, D3DVECTOR(front, radius, -dist));
+ m_object->SetPosition(9, D3DVECTOR(front, radius, dist));
+
+ if ( type == OBJECT_APOLLO2 )
+ {
+ m_object->SetPosition(10, D3DVECTOR(back, radius, -dist));
+ m_object->SetPosition(11, D3DVECTOR(back, radius, dist));
+ m_object->SetPosition(12, D3DVECTOR(front, radius, -dist));
+ m_object->SetPosition(13, D3DVECTOR(front, radius, dist));
+ }
+ }
+ }
+ }
+
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEdr ) // caterpillars?
+ {
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.7f;
+ a = m_physics->RetCirMotionY(MO_MOTSPEED)*2.5f;
+
+ m_posTrackLeft += event.rTime*(s+a);
+ m_posTrackRight += event.rTime*(s-a);
+
+ UpdateTrackMapping(m_posTrackLeft, m_posTrackRight, type);
+
+ pos = m_object->RetPosition(0);
+ angle = m_object->RetAngle(0);
+ if ( pos.x != m_wheelLastPos.x ||
+ pos.y != m_wheelLastPos.y ||
+ pos.z != m_wheelLastPos.z ||
+ angle.x != m_wheelLastAngle.x ||
+ angle.y != m_wheelLastAngle.y ||
+ angle.z != m_wheelLastAngle.z )
+ {
+ m_wheelLastPos = pos;
+ m_wheelLastAngle = angle;
+
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts )
+ {
+ limit[0] = 8.0f*PI/180.0f;
+ limit[1] = -12.0f*PI/180.0f;
+ }
+ else if ( type == OBJECT_MOBILEsa )
+ {
+ limit[0] = 15.0f*PI/180.0f;
+ limit[1] = -15.0f*PI/180.0f;
+ }
+ else if ( type == OBJECT_MOBILEdr )
+ {
+ limit[0] = 10.0f*PI/180.0f;
+ limit[1] = -10.0f*PI/180.0f;
+ }
+ else
+ {
+ limit[0] = 15.0f*PI/180.0f;
+ limit[1] = -10.0f*PI/180.0f;
+ }
+
+ if ( Length(pos, m_engine->RetEyePt()) < 50.0f ) // suspension?
+ {
+ character = m_object->RetCharacter();
+ mat = m_object->RetWorldMatrix(0);
+
+ pos.x = character->wheelFront; // right front wheel
+ pos.z = -character->wheelRight;
+ pos.y = 0.0f;
+ pos = Transform(*mat, pos);
+ a1 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelFront);
+
+ pos.x = -character->wheelBack; // right back wheel
+ pos.z = -character->wheelRight;
+ pos.y = 0.0f;
+ pos = Transform(*mat, pos);
+ a2 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelBack);
+
+ a = (a2-a1)/2.0f;
+ if ( a > limit[0] ) a = limit[0];
+ if ( a < limit[1] ) a = limit[1];
+ m_object->SetAngleZ(6, a);
+
+ pos.x = character->wheelFront; // left front wheel
+ pos.z = character->wheelLeft;
+ pos.y = 0.0f;
+ pos = Transform(*mat, pos);
+ a1 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelFront);
+
+ pos.x = -character->wheelBack; // left back wheel
+ pos.z = character->wheelLeft;
+ pos.y = 0.0f;
+ pos = Transform(*mat, pos);
+ a2 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelBack);
+
+ a = (a2-a1)/2.0f;
+ if ( a > limit[0] ) a = limit[0];
+ if ( a < limit[1] ) a = limit[1];
+ m_object->SetAngleZ(7, a);
+ }
+ else
+ {
+ m_object->SetAngleZ(6, 0.0f);
+ m_object->SetAngleZ(7, 0.0f);
+ }
+ }
+ }
+
+ if ( type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEdr ) // toy is key?
+ {
+ pos = m_posKey;
+ if ( m_object->RetSelect() &&
+ m_camera->RetType() == CAMERA_ONBOARD )
+ {
+ pos.y += 10.0f; // out of sight!
+ }
+ m_object->SetPosition(2, pos);
+
+ s = -Abs(m_physics->RetLinMotionX(MO_MOTSPEED)*0.1f);
+ s += -Abs(m_physics->RetCirMotionY(MO_MOTSPEED)*1.5f);
+ m_object->SetAngleY(2, m_object->RetAngleY(2)+event.rTime*s); // turns the key
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEft ) // flying?
+ {
+ EventFrameFly(event);
+ }
+
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEis ) // legs?
+ {
+ EventFrameInsect(event);
+ }
+
+ if ( type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEii ) // insect cannon?
+ {
+ EventFrameCanoni(event);
+ }
+
+ return TRUE;
+}
+
+// Managing an event for a flying robot.
+
+BOOL CMotionVehicle::EventFrameFly(const Event &event)
+{
+ D3DMATRIX* mat;
+ D3DVECTOR pos, angle, paw[3];
+ float hope[3], actual, final, h, a;
+ int i;
+
+ pos = m_object->RetPosition(0);
+ angle = m_object->RetAngle(0);
+ if ( m_bFlyFix &&
+ pos.x == m_wheelLastPos.x &&
+ pos.y == m_wheelLastPos.y &&
+ pos.z == m_wheelLastPos.z &&
+ angle.x == m_wheelLastAngle.x &&
+ angle.y == m_wheelLastAngle.y &&
+ angle.z == m_wheelLastAngle.z ) return TRUE;
+
+ m_wheelLastPos = pos;
+ m_wheelLastAngle = angle;
+
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ mat = m_object->RetWorldMatrix(0);
+ paw[0] = Transform(*mat, D3DVECTOR( 4.2f, 0.0f, 0.0f)); // front
+ paw[1] = Transform(*mat, D3DVECTOR(-3.0f, 0.0f, -3.7f)); // right back
+ paw[2] = Transform(*mat, D3DVECTOR(-3.0f, 0.0f, 3.7f)); // left back
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ h = m_terrain->RetFloorHeight(paw[i]);
+ a = -atanf(h*0.5f);
+ if ( a > PI*0.2f ) a = PI*0.2f;
+ if ( a < -PI*0.2f ) a = -PI*0.2f;
+ hope[i] = a;
+ }
+ }
+ else // in flight?
+ {
+ hope[0] = 0.0f; // front
+ hope[1] = 0.0f; // right back
+ hope[2] = 0.0f; // left back
+ }
+
+ m_bFlyFix = TRUE;
+ for ( i=0 ; i<3 ; i++ )
+ {
+ actual = m_object->RetAngleZ(6+i);
+ final = Smooth(actual, hope[i], event.rTime*5.0f);
+ if ( final != actual )
+ {
+ m_bFlyFix = FALSE; // it is moving
+ m_object->SetAngleZ(6+i, final);
+ }
+ }
+
+ return TRUE;
+}
+
+// Event management for insect legs.
+
+BOOL CMotionVehicle::EventFrameInsect(const Event &event)
+{
+ D3DVECTOR dir;
+ float s, a, prog, time;
+ int i, st, nd, action;
+ BOOL bStop, bOnBoard;
+
+ static int table[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 60,25,0, 60,0,0, 60,-25,0, // t0: thighs 1..4
+ -35,0,0, -35,0,0, -35,0,0, // t0: legs 1..4
+ -65,0,0, -65,0,0, -65,0,0, // t0: feet 1..4
+ // on the ground:
+ 30,10,0, 30,-15,0, 30,-40,0, // t1: thighs 1..4
+ -45,0,0, -45,0,0, -45,0,0, // t1: legs 1..4
+ -20,0,0, -20,0,0, -20,0,0, // t1: feet 1..4
+ // on the ground back:
+ 35,40,0, 40,15,0, 40,-10,0, // t2: thighs 1..4
+ -35,0,0, -35,0,0, -35,0,0, // t2: legs 1..4
+ -50,0,0, -65,0,0, -65,0,0, // t2: feet 1..4
+ // stop:
+ 35,35,0, 40,10,0, 40,-15,0, // s0: thighs 1..4
+ -35,0,0, -35,0,0, -35,0,0, // s0: legs 1..4
+ -50,0,0, -65,0,0, -65,0,0, // s0: feet 1..4
+ };
+
+ bOnBoard = FALSE;
+ if ( m_object->RetSelect() &&
+ m_camera->RetType() == CAMERA_ONBOARD )
+ {
+ bOnBoard = TRUE;
+ }
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
+ a = Abs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f);
+
+ if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armMember += (s+a)*event.rTime*0.15f;
+
+ bStop = ( a == 0.0f && s == 0.0f ); // stop?
+
+ action = 0; // walking
+ if ( s == 0.0f && a == 0.0f )
+ {
+ action = 3; // stop
+ }
+
+ if ( bStop )
+ {
+ prog = Mod(m_armTimeAbs, 2.0f)/10.0f;
+ a = Mod(m_armMember, 1.0f);
+ a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly
+ m_armMember += a;
+ }
+
+ if ( m_object->RetRuin() ) // burn or explode?
+ {
+ action = 3;
+ }
+
+ for ( i=0 ; i<6 ; i++ ) // the six legs
+ {
+ if ( action != 0 ) // special action in progress?
+ {
+ st = 3*3*3*action + (i%3)*3;
+ nd = st;
+ time = event.rTime*5.0f;
+ }
+ else
+ {
+ if ( i < 3 ) prog = Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
+ else prog = Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
+ if ( prog < 0.33f ) // t0..t1 ?
+ {
+ prog = prog/0.33f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.67f ) // t1..t2 ?
+ {
+ prog = (prog-0.33f)/0.33f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.67f)/0.33f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ st = 3*3*3*action + st*3*3*3 + (i%3)*3;
+ nd = 3*3*3*action + nd*3*3*3 + (i%3)*3;
+
+ // Less and less soft ...
+ time = event.rTime*20.0f;
+ }
+
+ if ( i < 3 ) // right leg (1..3) ?
+ {
+ m_object->SetAngleX(6+3*i+0, Smooth(m_object->RetAngleX(6+3*i+0), Prop(table[st+ 0], table[nd+ 0], prog), time));
+ m_object->SetAngleY(6+3*i+0, Smooth(m_object->RetAngleY(6+3*i+0), Prop(table[st+ 1], table[nd+ 1], prog), time));
+ m_object->SetAngleZ(6+3*i+0, Smooth(m_object->RetAngleZ(6+3*i+0), Prop(table[st+ 2], table[nd+ 2], prog), time));
+ m_object->SetAngleX(6+3*i+1, Smooth(m_object->RetAngleX(6+3*i+1), Prop(table[st+ 9], table[nd+ 9], prog), time));
+ m_object->SetAngleY(6+3*i+1, Smooth(m_object->RetAngleY(6+3*i+1), Prop(table[st+10], table[nd+10], prog), time));
+ m_object->SetAngleZ(6+3*i+1, Smooth(m_object->RetAngleZ(6+3*i+1), Prop(table[st+11], table[nd+11], prog), time));
+ m_object->SetAngleX(6+3*i+2, Smooth(m_object->RetAngleX(6+3*i+2), Prop(table[st+18], table[nd+18], prog), time));
+ m_object->SetAngleY(6+3*i+2, Smooth(m_object->RetAngleY(6+3*i+2), Prop(table[st+19], table[nd+19], prog), time));
+ m_object->SetAngleZ(6+3*i+2, Smooth(m_object->RetAngleZ(6+3*i+2), Prop(table[st+20], table[nd+20], prog), time));
+ }
+ else // left leg (4..6) ?
+ {
+ m_object->SetAngleX(6+3*i+0, Smooth(m_object->RetAngleX(6+3*i+0), Prop(-table[st+ 0], -table[nd+ 0], prog), time));
+ m_object->SetAngleY(6+3*i+0, Smooth(m_object->RetAngleY(6+3*i+0), Prop(-table[st+ 1], -table[nd+ 1], prog), time));
+ m_object->SetAngleZ(6+3*i+0, Smooth(m_object->RetAngleZ(6+3*i+0), Prop( table[st+ 2], table[nd+ 2], prog), time));
+ m_object->SetAngleX(6+3*i+1, Smooth(m_object->RetAngleX(6+3*i+1), Prop(-table[st+ 9], -table[nd+ 9], prog), time));
+ m_object->SetAngleY(6+3*i+1, Smooth(m_object->RetAngleY(6+3*i+1), Prop(-table[st+10], -table[nd+10], prog), time));
+ m_object->SetAngleZ(6+3*i+1, Smooth(m_object->RetAngleZ(6+3*i+1), Prop( table[st+11], table[nd+11], prog), time));
+ m_object->SetAngleX(6+3*i+2, Smooth(m_object->RetAngleX(6+3*i+2), Prop(-table[st+18], -table[nd+18], prog), time));
+ m_object->SetAngleY(6+3*i+2, Smooth(m_object->RetAngleY(6+3*i+2), Prop(-table[st+19], -table[nd+19], prog), time));
+ m_object->SetAngleZ(6+3*i+2, Smooth(m_object->RetAngleZ(6+3*i+2), Prop( table[st+20], table[nd+20], prog), time));
+ }
+ }
+
+ if ( bStop )
+ {
+ }
+ else
+ {
+ a = Mod(m_armMember, 1.0f);
+ if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
+ else a = 3.0f-4.0f*a; // 1..-1
+ dir.x = sinf(a)*0.05f;
+
+ s = Mod(m_armMember/2.0f, 1.0f);
+ if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
+ else s = 3.0f-4.0f*s; // 1..-1
+ dir.z = sinf(s)*0.1f;
+
+ dir.y = 0.0f;
+
+ if ( bOnBoard ) dir *= 0.6f;
+ SetInclinaison(dir);
+ }
+
+ return TRUE;
+}
+
+// Event management for a insect cannon.
+
+BOOL CMotionVehicle::EventFrameCanoni(const Event &event)
+{
+ CObject* power;
+ D3DVECTOR pos, speed;
+ FPOINT dim;
+ float zoom, angle, energy, factor;
+ BOOL bOnBoard = FALSE;
+
+ m_canonTime += event.rTime;
+
+ if ( m_object->RetSelect() &&
+ m_camera->RetType() == CAMERA_ONBOARD )
+ {
+ bOnBoard = TRUE;
+ }
+
+ power = m_object->RetPower();
+ if ( power == 0 )
+ {
+ energy = 0.0f;
+ }
+ else
+ {
+ energy = power->RetEnergy();
+ }
+ if ( energy == 0.0f ) return TRUE;
+
+ factor = 0.5f+energy*0.5f;
+ if ( bOnBoard ) factor *= 0.8f;
+
+ zoom = 1.3f+
+ sinf(m_canonTime*PI*0.31f)*0.10f+
+ sinf(m_canonTime*PI*0.52f)*0.08f+
+ sinf(m_canonTime*PI*1.53f)*0.05f;
+ zoom *= factor;
+ m_object->SetZoomY(2, zoom);
+
+ zoom = 1.0f+
+ sinf(m_canonTime*PI*0.27f)*0.07f+
+ sinf(m_canonTime*PI*0.62f)*0.06f+
+ sinf(m_canonTime*PI*1.73f)*0.03f;
+ zoom *= factor;
+ m_object->SetZoomZ(2, zoom);
+
+ angle = sinf(m_canonTime*1.0f)*0.10f+
+ sinf(m_canonTime*1.3f)*0.15f+
+ sinf(m_canonTime*2.7f)*0.05f;
+ m_object->SetAngleX(2, angle);
+
+#if 0
+ m_lastTimeCanon -= event.rTime;
+ if ( m_lastTimeCanon <= 0.0f )
+ {
+ m_lastTimeCanon = m_engine->ParticuleAdapt(0.5f+Rand()*0.5f);
+
+ pos = m_object->RetPosition(0);
+ pos.y += 8.0f;
+ speed.y = 7.0f+Rand()*3.0f;
+ speed.x = (Rand()-0.5f)*2.0f;
+ speed.z = 2.0f+Rand()*2.0f;
+ if ( Rand() < 0.5f ) speed.z = -speed.z;
+ mat = m_object->RetRotateMatrix(0);
+ speed = Transform(*mat, speed);
+ dim.x = Rand()*0.1f+0.1f;
+ if ( bOnBoard ) dim.x *= 0.4f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIORGANIC2, 2.0f, 10.0f);
+ }
+#endif
+
+ return TRUE;
+}
+
+
+// Updates the mapping of the texture of the caterpillars.
+
+void CMotionVehicle::UpdateTrackMapping(float left, float right, ObjectType type)
+{
+ D3DMATERIAL7 mat;
+ float limit[4];
+ int rRank, lRank, i;
+
+ ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
+ mat.diffuse.r = 1.0f;
+ mat.diffuse.g = 1.0f;
+ mat.diffuse.b = 1.0f; // white
+ mat.ambient.r = 0.5f;
+ mat.ambient.g = 0.5f;
+ mat.ambient.b = 0.5f;
+
+ rRank = m_object->RetObjectRank(6);
+ lRank = m_object->RetObjectRank(7);
+
+
+ if ( type == OBJECT_MOBILEdr )
+ {
+ limit[0] = 0.0f;
+ limit[1] = 1000000.0f;
+ limit[2] = limit[1];
+ limit[3] = m_engine->RetLimitLOD(1);
+
+ m_engine->TrackTextureMapping(rRank, mat, D3DSTATEPART1, "drawer.tga", "",
+ limit[0], limit[1], D3DMAPPINGX,
+ right, 1.0f, 8.0f, 192.0f, 256.0f);
+
+ m_engine->TrackTextureMapping(lRank, mat, D3DSTATEPART2, "drawer.tga", "",
+ limit[0], limit[1], D3DMAPPINGX,
+ left, 1.0f, 8.0f, 192.0f, 256.0f);
+ }
+ else
+ {
+ limit[0] = 0.0f;
+ limit[1] = m_engine->RetLimitLOD(0);
+ limit[2] = limit[1];
+ limit[3] = m_engine->RetLimitLOD(1);
+
+ for ( i=0 ; i<2 ; i++ )
+ {
+ m_engine->TrackTextureMapping(rRank, mat, D3DSTATEPART1, "lemt.tga", "",
+ limit[i*2+0], limit[i*2+1], D3DMAPPINGX,
+ right, 1.0f, 8.0f, 192.0f, 256.0f);
+
+ m_engine->TrackTextureMapping(lRank, mat, D3DSTATEPART2, "lemt.tga", "",
+ limit[i*2+0], limit[i*2+1], D3DMAPPINGX,
+ left, 1.0f, 8.0f, 192.0f, 256.0f);
+ }
+ }
+
+}
+
+
+
+// State management of the pencil drawing robot.
+
+BOOL CMotionVehicle::RetTraceDown()
+{
+ return m_bTraceDown;
+}
+
+void CMotionVehicle::SetTraceDown(BOOL bDown)
+{
+ m_bTraceDown = bDown;
+}
+
+int CMotionVehicle::RetTraceColor()
+{
+ return m_traceColor;
+}
+
+void CMotionVehicle::SetTraceColor(int color)
+{
+ m_traceColor = color;
+}
+
+float CMotionVehicle::RetTraceWidth()
+{
+ return m_traceWidth;
+}
+
+void CMotionVehicle::SetTraceWidth(float width)
+{
+ m_traceWidth = width;
+}
+
+
diff --git a/src/object/motion/motionvehicle.h b/src/object/motion/motionvehicle.h
new file mode 100644
index 0000000..1b351c4
--- /dev/null
+++ b/src/object/motion/motionvehicle.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/.
+
+// motionvehicle.h
+
+#ifndef _MOTIONVEHICLE_H_
+#define _MOTIONVEHICLE_H_
+
+
+#include "motion.h"
+
+
+class CInstanceManager;
+class CEngine;
+class CLight;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CBrain;
+class CPhysics;
+class CObject;
+
+
+class CMotionVehicle : public CMotion
+{
+public:
+ CMotionVehicle(CInstanceManager* iMan, CObject* object);
+ ~CMotionVehicle();
+
+ void DeleteObject(BOOL bAll=FALSE);
+ BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power);
+ BOOL EventProcess(const Event &event);
+
+ BOOL RetTraceDown();
+ void SetTraceDown(BOOL bDown);
+ int RetTraceColor();
+ void SetTraceColor(int color);
+ float RetTraceWidth();
+ void SetTraceWidth(float width);
+
+protected:
+ void CreatePhysics(ObjectType type);
+ BOOL EventFrame(const Event &event);
+ BOOL EventFrameFly(const Event &event);
+ BOOL EventFrameInsect(const Event &event);
+ BOOL EventFrameCanoni(const Event &event);
+ void UpdateTrackMapping(float left, float right, ObjectType type);
+
+protected:
+ float m_wheelTurn[4];
+ float m_flyPaw[3];
+ float m_posTrackLeft;
+ float m_posTrackRight;
+ int m_partiReactor;
+ float m_armTimeAbs;
+ float m_armMember;
+ float m_canonTime;
+ float m_lastTimeCanon;
+ D3DVECTOR m_wheelLastPos;
+ D3DVECTOR m_wheelLastAngle;
+ D3DVECTOR m_posKey;
+ BOOL m_bFlyFix;
+ BOOL m_bTraceDown;
+ int m_traceColor;
+ float m_traceWidth;
+};
+
+
+#endif //_MOTIONVEHICLE_H_
diff --git a/src/object/motion/motionworm.cpp b/src/object/motion/motionworm.cpp
new file mode 100644
index 0000000..eb32b44
--- /dev/null
+++ b/src/object/motion/motionworm.cpp
@@ -0,0 +1,380 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionworm.cpp
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "d3dengine.h"
+#include "math3d.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "light.h"
+#include "particule.h"
+#include "terrain.h"
+#include "object.h"
+#include "physics.h"
+#include "brain.h"
+#include "camera.h"
+#include "modfile.h"
+#include "sound.h"
+#include "motion.h"
+#include "motionworm.h"
+
+
+
+#define START_TIME 1000.0f // beginning of the relative time
+#define TIME_UPDOWN 2.0f // time for up / down
+#define DOWN_ALTITUDE 3.0f // underground distance
+#define WORM_PART 7 // number of parts of a worm
+
+
+
+// Object's constructor.
+
+CMotionWorm::CMotionWorm(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ CMotion::CMotion(iMan, object);
+
+ m_timeUp = 18.0f;
+ m_timeDown = 18.0f;
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeMarch = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLinSpeed = 0.0f;
+ m_armCirSpeed = 0.0f;
+ m_armLastAction = -1;
+ m_specAction = -1;
+ m_lastParticule = 0.0f;
+ m_bArmStop = FALSE;
+}
+
+// Object's destructor.
+
+CMotionWorm::~CMotionWorm()
+{
+}
+
+
+// Removes an object.
+
+void CMotionWorm::DeleteObject(BOOL bAll)
+{
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+BOOL CMotionWorm::Create(D3DVECTOR pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank, i;
+ float px;
+
+ if ( m_engine->RetRestCreate() < 2+WORM_PART+1 ) return FALSE;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates the main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\worm0.mod"); // there is no purpose!
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have a obligatory collision with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
+ m_object->SetGlobalSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 5.0f);
+
+ px = 1.0f+WORM_PART/2;
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\worm1.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, D3DVECTOR(px, 0.0f, 0.0f));
+ px -= 1.0f;
+
+ // Creates the body.
+ for ( i=0 ; i<WORM_PART ; i++ )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2+i, rank);
+ m_object->SetObjectParent(2+i, 0);
+ pModFile->ReadModel("objects\\worm2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2+i, D3DVECTOR(px, 0.0f, 0.0f));
+ px -= 1.0f;
+ }
+
+ // Creates the tail.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2+WORM_PART, rank);
+ m_object->SetObjectParent(2+WORM_PART, 0);
+ pModFile->ReadModel("objects\\worm3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2+WORM_PART, D3DVECTOR(px, 0.0f, 0.0f));
+
+ m_object->CreateShadowCircle(0.0f, 1.0f, D3DSHADOWWORM);
+
+ CreatePhysics();
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return TRUE;
+}
+
+// Creates the physics of the object.
+
+void CMotionWorm::CreatePhysics()
+{
+ Character* character;
+
+ m_physics->SetType(TYPE_ROLLING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 10.0f;
+ character->wheelBack = 10.0f;
+ character->wheelLeft = 2.0f;
+ character->wheelRight = 2.0f;
+ character->height = -0.2f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 3.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 3.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.2f*PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.2f*PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 20.0f);
+}
+
+
+
+// Specifies a special parameter.
+
+BOOL CMotionWorm::SetParam(int rank, float value)
+{
+ if ( rank == 0 )
+ {
+ m_timeDown = value;
+ return TRUE;
+ }
+
+ if ( rank == 1 )
+ {
+ m_timeUp = value;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+float CMotionWorm::RetParam(int rank)
+{
+ if ( rank == 0 ) return m_timeDown;
+ if ( rank == 1 ) return m_timeUp;
+ return 0.0f;
+}
+
+
+
+// Management of an event.
+
+BOOL CMotionWorm::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+ }
+
+ return TRUE;
+}
+
+// Management of an event.
+
+BOOL CMotionWorm::EventFrame(const Event &event)
+{
+ D3DMATRIX* mat;
+ D3DVECTOR pos, p, angle, speed;
+ FPOINT center, pp, dim;
+ float height[WORM_PART+2];
+ float floor, a, s, px, curve, phase, h, zoom, radius;
+ int i, under;
+
+ if ( m_engine->RetPause() ) return TRUE;
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)/m_physics->RetLinMotionX(MO_ADVSPEED);
+ a = m_physics->RetCirMotionY(MO_MOTSPEED)/m_physics->RetCirMotionY(MO_ADVSPEED);
+
+ if ( s == 0.0f && a != 0.0f ) s = a;
+
+ m_armLinSpeed += (s-m_armLinSpeed)*event.rTime*3.0f;
+ m_armCirSpeed += (a-m_armCirSpeed)*event.rTime*1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armTimeMarch += event.rTime*m_armLinSpeed;
+
+ under = 0; // no piece under the ground
+ for ( i=0 ; i<WORM_PART+2 ; i++ )
+ {
+ phase = Mod(m_armTimeMarch-START_TIME-i*0.3f, TIME_UPDOWN+m_timeDown+TIME_UPDOWN+m_timeUp);
+ if ( phase < TIME_UPDOWN ) // descends?
+ {
+ h = -(phase/TIME_UPDOWN)*DOWN_ALTITUDE;
+ }
+ else if ( phase < TIME_UPDOWN+m_timeDown ) // advance underground?
+ {
+ h = -DOWN_ALTITUDE;
+ under ++; // the most of a piece entirely under ground
+ }
+ else if ( phase < TIME_UPDOWN+m_timeDown+TIME_UPDOWN ) // up?
+ {
+ h = -(1.0f-(phase-TIME_UPDOWN-m_timeDown)/TIME_UPDOWN)*DOWN_ALTITUDE;
+ }
+ else // advance on earth?
+ {
+ h = 0.0f;
+ }
+ if ( m_object->RetBurn() ) // is burning?
+ {
+ h = 0.0f; // remains on earth
+ }
+ h += 0.3f;
+ height[i] = h;
+ }
+ m_object->SetVisible(under!=WORM_PART+2);
+
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return TRUE;
+
+ pos = m_object->RetPosition(0);
+ floor = m_terrain->RetFloorLevel(pos, TRUE);
+
+ mat = m_object->RetWorldMatrix(0);
+
+ px = 1.0f+WORM_PART/2;
+ for ( i=0 ; i<WORM_PART+2 ; i++ )
+ {
+ radius = 1.0f+(height[i]-0.3f)/DOWN_ALTITUDE; // 0 = underground, 1 = surface
+ radius = radius*1.3f-0.3f;
+ if ( radius < 0.0f ) radius = 0.0f;
+ radius *= 5.0f;
+ m_engine->SetObjectShadowRadius(m_object->RetObjectRank(0), radius);
+
+ pos.x = px+ sinf(m_armTimeMarch*4.0f+0.5f*i)*0.6f;
+ pos.y = height[i]+sinf(m_armTimeMarch*4.0f+0.5f*i)*0.2f*m_armLinSpeed;
+ pos.y += sinf(m_armTimeAbs *1.3f+0.2f*i)*0.1f;
+ pos.z = sinf(m_armTimeAbs *2.0f+0.7f*i)*0.2f;
+
+ curve = ((float)i-(WORM_PART+2)/2)*m_armCirSpeed*0.1f;
+ center.x = 0.0f;
+ center.y = 0.0f;
+ pp.x = pos.x;
+ pp.y = pos.z;
+ pp = RotatePoint(center, curve, pp);
+ pos.x = pp.x;
+ pos.z = pp.y;
+
+ p = Transform(*mat, pos);
+ pos.y += m_terrain->RetFloorLevel(p, TRUE)-floor;
+ m_object->SetPosition(i+1, pos);
+
+ zoom = Mod(m_armTimeAbs*0.5f+100.0f-i*0.1f, 2.0f);
+ if ( zoom > 1.0f ) zoom = 2.0f-zoom;
+ zoom *= 1.6f;
+ if ( zoom < 1.0f ) zoom = 1.0f;
+ m_object->SetZoomY(i+1, 0.2f+zoom*0.8f);
+ m_object->SetZoomZ(i+1, zoom);
+
+ if ( height[i] >= -1.0f && height[i] < -0.2f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.2f) <= m_armTimeMarch )
+ {
+ m_lastParticule = m_armTimeMarch;
+
+ pos = p;
+ pos.y += -height[i];
+ pos.x += (Rand()-0.5f)*4.0f;
+ pos.z += (Rand()-0.5f)*4.0f;
+ speed = D3DVECTOR(0.0f, 0.0f, 0.0f);
+ dim.x = Rand()*2.0f+1.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+
+ px -= 1.0f;
+ }
+
+ for ( i=0 ; i<WORM_PART+1 ; i++ )
+ {
+ pos = m_object->RetPosition(i+2);
+ pos -= m_object->RetPosition(i+1);
+
+ angle.z = -RotateAngle(Length(pos.x, pos.z), pos.y);
+ angle.y = PI-RotateAngle(pos.x, pos.z);
+ angle.x = 0.0f;
+ m_object->SetAngle(i+1, angle);
+
+ if ( i == WORM_PART )
+ {
+ m_object->SetAngle(i+2, angle);
+ }
+ }
+
+ return TRUE;
+}
+
+
diff --git a/src/object/motion/motionworm.h b/src/object/motion/motionworm.h
new file mode 100644
index 0000000..cabb2ba
--- /dev/null
+++ b/src/object/motion/motionworm.h
@@ -0,0 +1,75 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionworm.h
+
+#ifndef _MOTIONWORM_H_
+#define _MOTIONWORM_H_
+
+
+#include "motion.h"
+
+
+class CInstanceManager;
+class CEngine;
+class CLight;
+class CParticule;
+class CTerrain;
+class CCamera;
+class CBrain;
+class CPhysics;
+class CObject;
+
+
+class CMotionWorm : public CMotion
+{
+public:
+ CMotionWorm(CInstanceManager* iMan, CObject* object);
+ ~CMotionWorm();
+
+ void DeleteObject(BOOL bAll=FALSE);
+ BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power);
+ BOOL EventProcess(const Event &event);
+
+ BOOL SetParam(int rank, float value);
+ float RetParam(int rank);
+
+protected:
+ void CreatePhysics();
+ BOOL EventFrame(const Event &event);
+
+protected:
+ float m_timeUp;
+ float m_timeDown;
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeMarch;
+ float m_armTimeAction;
+ short m_armAngles[3*3*3*3*10];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ float m_armLinSpeed;
+ float m_armCirSpeed;
+ int m_specAction;
+ float m_specTime;
+ BOOL m_bArmStop;
+ float m_lastParticule;
+};
+
+
+#endif //_MOTIONWORM_H_