summaryrefslogtreecommitdiffstats
path: root/src/taskflag.cpp
diff options
context:
space:
mode:
authoradiblol <adiblol@1tbps.org>2012-03-08 19:32:05 +0100
committeradiblol <adiblol@1tbps.org>2012-03-08 19:32:05 +0100
commita4c804b49ec872b71bd5a0167c3ad45704a3cc30 (patch)
tree8c931235247d662ca46a99695beb328fdfc8e8a8 /src/taskflag.cpp
downloadcolobot-a4c804b49ec872b71bd5a0167c3ad45704a3cc30.tar.gz
colobot-a4c804b49ec872b71bd5a0167c3ad45704a3cc30.tar.bz2
colobot-a4c804b49ec872b71bd5a0167c3ad45704a3cc30.zip
Initial commit, Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
Diffstat (limited to 'src/taskflag.cpp')
-rw-r--r--src/taskflag.cpp305
1 files changed, 305 insertions, 0 deletions
diff --git a/src/taskflag.cpp b/src/taskflag.cpp
new file mode 100644
index 0000000..a475e67
--- /dev/null
+++ b/src/taskflag.cpp
@@ -0,0 +1,305 @@
+// taskflag.cpp
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "struct.h"
+#include "D3DEngine.h"
+#include "D3DMath.h"
+#include "math3d.h"
+#include "event.h"
+#include "misc.h"
+#include "iman.h"
+#include "terrain.h"
+#include "water.h"
+#include "object.h"
+#include "pyro.h"
+#include "physics.h"
+#include "brain.h"
+#include "camera.h"
+#include "motion.h"
+#include "motionhuman.h"
+#include "sound.h"
+#include "task.h"
+#include "taskflag.h"
+
+
+
+
+
+// Constructeur de l'objet.
+
+CTaskFlag::CTaskFlag(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ CTask::CTask(iMan, object);
+}
+
+// Destructeur de l'objet.
+
+CTaskFlag::~CTaskFlag()
+{
+}
+
+
+// Gestion d'un événement.
+
+BOOL CTaskFlag::EventProcess(const Event &event)
+{
+ if ( m_bError ) return TRUE;
+ if ( m_engine->RetPause() ) return TRUE;
+ if ( event.event != EVENT_FRAME ) return TRUE;
+
+ m_time += event.rTime;
+
+ return TRUE;
+}
+
+
+
+// Assigne le but à atteindre.
+
+Error CTaskFlag::Start(TaskFlagOrder order, int rank)
+{
+ D3DVECTOR pos, speed;
+ Error err;
+
+ m_order = order;
+ m_time = 0.0f;
+
+ m_bError = TRUE; // opération impossible
+ if ( !m_physics->RetLand() )
+ {
+ pos = m_object->RetPosition(0);
+ if ( pos.y < m_water->RetLevel() ) return ERR_FLAG_WATER;
+ return ERR_FLAG_FLY;
+ }
+
+ speed = m_physics->RetMotorSpeed();
+ if ( speed.x != 0.0f ||
+ speed.z != 0.0f ) return ERR_FLAG_MOTOR;
+
+ if ( m_object->RetFret() != 0 ) return ERR_FLAG_BUSY;
+
+ if ( order == TFL_CREATE )
+ {
+ err = CreateFlag(rank);
+ if ( err != ERR_OK ) return err;
+ }
+
+ if ( order == TFL_DELETE )
+ {
+ err = DeleteFlag();
+ if ( err != ERR_OK ) return err;
+ }
+
+ m_bError = FALSE;
+
+ m_motion->SetAction(MHS_FLAG); // met/enlève drapeau
+ m_camera->StartCentering(m_object, PI*0.3f, 99.9f, 0.0f, 0.5f);
+
+ return ERR_OK;
+}
+
+// Indique si l'action est terminée.
+
+Error CTaskFlag::IsEnded()
+{
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+
+ if ( m_bError ) return ERR_STOP;
+ if ( m_time < 2.0f ) return ERR_CONTINUE;
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Termine brutalement l'action en cours.
+
+BOOL CTaskFlag::Abort()
+{
+ m_motion->SetAction(-1);
+ m_camera->StopCentering(m_object, 2.0f);
+ return TRUE;
+}
+
+
+
+// Retourne l'objet le plus proche d'une position donnée.
+
+CObject* CTaskFlag::SearchNearest(D3DVECTOR pos, ObjectType type)
+{
+ ObjectType oType;
+ CObject *pObj, *pBest;
+ D3DVECTOR oPos;
+ float min, dist;
+ int i;
+
+ min = 100000.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetEnable() ) continue;
+
+ oType = pObj->RetType();
+ if ( type == OBJECT_NULL )
+ {
+ if ( oType != OBJECT_FLAGb &&
+ oType != OBJECT_FLAGr &&
+ oType != OBJECT_FLAGg &&
+ oType != OBJECT_FLAGy &&
+ oType != OBJECT_FLAGv ) continue;
+ }
+ else
+ {
+ if ( oType != type ) continue;
+ }
+
+ oPos = pObj->RetPosition(0);
+ dist = Length2d(oPos, pos);
+ if ( dist < min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+ return pBest;
+}
+
+// Compte le nombre d'objets existants.
+
+int CTaskFlag::CountObject(ObjectType type)
+{
+ ObjectType oType;
+ CObject *pObj;
+ D3DVECTOR oPos;
+ int i, count;
+
+ count = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetEnable() ) continue;
+
+ oType = pObj->RetType();
+ if ( type == OBJECT_NULL )
+ {
+ if ( oType != OBJECT_FLAGb &&
+ oType != OBJECT_FLAGr &&
+ oType != OBJECT_FLAGg &&
+ oType != OBJECT_FLAGy &&
+ oType != OBJECT_FLAGv ) continue;
+ }
+ else
+ {
+ if ( oType != type ) continue;
+ }
+
+ count ++;
+ }
+ return count;
+}
+
+// Crée un indicateur de couleur.
+
+Error CTaskFlag::CreateFlag(int rank)
+{
+ CObject* pObj;
+ CObject* pNew;
+ CPyro* pyro;
+ D3DMATRIX* mat;
+ D3DVECTOR pos;
+ float dist;
+ int i;
+
+ ObjectType table[5] =
+ {
+ OBJECT_FLAGb,
+ OBJECT_FLAGr,
+ OBJECT_FLAGg,
+ OBJECT_FLAGy,
+ OBJECT_FLAGv,
+ };
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, D3DVECTOR(4.0f, 0.0f, 0.0f));
+
+ pObj = SearchNearest(pos, OBJECT_NULL);
+ if ( pObj != 0 )
+ {
+ dist = Length(pos, pObj->RetPosition(0));
+ if ( dist < 10.0f )
+ {
+ return ERR_FLAG_PROXY;
+ }
+ }
+
+ i = rank;
+ if ( CountObject(table[i]) >= 5 )
+ {
+ return ERR_FLAG_CREATE;
+ }
+
+ pNew = new CObject(m_iMan);
+ if ( !pNew->CreateFlag(pos, 0.0f, table[i]) )
+ {
+ delete pNew;
+ return ERR_TOOMANY;
+ }
+ pNew->SetZoom(0, 0.0f);
+
+ m_sound->Play(SOUND_WAYPOINT, pos);
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FLCREATE, pNew);
+
+ return ERR_OK;
+}
+
+// Supprime un indicateur de couleur.
+
+Error CTaskFlag::DeleteFlag()
+{
+ CObject* pObj;
+ CPyro* pyro;
+ D3DVECTOR iPos, oPos;
+ float iAngle, angle, aLimit, dist;
+
+ iPos = m_object->RetPosition(0);
+ iAngle = m_object->RetAngleY(0);
+ iAngle = NormAngle(iAngle); // 0..2*PI
+
+ pObj = SearchNearest(iPos, OBJECT_NULL);
+ if ( pObj == 0 )
+ {
+ return ERR_FLAG_DELETE;
+ }
+ dist = Length(iPos, pObj->RetPosition(0));
+ if ( dist > 10.0f )
+ {
+ return ERR_FLAG_DELETE;
+ }
+
+ oPos = pObj->RetPosition(0);
+ angle = RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+ aLimit = 45.0f*PI/180.0f;
+ if ( !TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
+ {
+ return ERR_FLAG_DELETE;
+ }
+
+ m_sound->Play(SOUND_WAYPOINT, iPos);
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FLDELETE, pObj);
+
+ return ERR_OK;
+}
+