diff options
Diffstat (limited to 'src/object/task')
42 files changed, 10995 insertions, 10995 deletions
diff --git a/src/object/task/task.cpp b/src/object/task/task.cpp index 593d4e6..f910ea2 100644 --- a/src/object/task/task.cpp +++ b/src/object/task/task.cpp @@ -1,89 +1,89 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// task.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/task.h"
-
-#include "common/iman.h"
-#include "object/object.h"
-
-
-
-// Object's constructor.
-
-CTask::CTask(CInstanceManager* iMan, CObject* object)
-{
- m_iMan = iMan;
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
-
- m_object = object;
- m_physics = m_object->RetPhysics();
- m_brain = m_object->RetBrain();
- m_motion = m_object->RetMotion();
-}
-
-// Object's destructor.
-
-CTask::~CTask()
-{
-}
-
-
-// Management of an event.
-
-bool CTask::EventProcess(const Event &event)
-{
- return true;
-}
-
-
-// Indicates whether the action is finished.
-
-Error CTask::IsEnded()
-{
- return ERR_STOP;
-}
-
-
-// Indicates whether the action is pending.
-
-bool CTask::IsBusy()
-{
- return true;
-}
-
-
-// Suddenly ends the current action.
-
-bool CTask::Abort()
-{
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// task.cpp + + +#include <stdio.h> + +#include "object/task/task.h" + +#include "common/iman.h" +#include "object/object.h" + + + +// Object's constructor. + +CTask::CTask(CInstanceManager* iMan, CObject* object) +{ + m_iMan = iMan; + + m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE); + m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT); + m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE); + m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN); + m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER); + m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA); + m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN); + m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT); + m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND); + + m_object = object; + m_physics = m_object->RetPhysics(); + m_brain = m_object->RetBrain(); + m_motion = m_object->RetMotion(); +} + +// Object's destructor. + +CTask::~CTask() +{ +} + + +// Management of an event. + +bool CTask::EventProcess(const Event &event) +{ + return true; +} + + +// Indicates whether the action is finished. + +Error CTask::IsEnded() +{ + return ERR_STOP; +} + + +// Indicates whether the action is pending. + +bool CTask::IsBusy() +{ + return true; +} + + +// Suddenly ends the current action. + +bool CTask::Abort() +{ + return true; +} + + diff --git a/src/object/task/task.h b/src/object/task/task.h index 8a1255e..a3ec62c 100644 --- a/src/object/task/task.h +++ b/src/object/task/task.h @@ -1,86 +1,86 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// task.h
-
-#pragma once
-
-
-#include "common/misc.h"
-#include "math/const.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CLight;
-class CParticule;
-class CTerrain;
-class CWater;
-class CCamera;
-class CBrain;
-class CPhysics;
-class CMotion;
-class CObject;
-class CRobotMain;
-class CDisplayText;
-class CSound;
-
-
-const float TAKE_DIST = 6.0f; // distance to an object to pick it
-const float TAKE_DIST_OTHER = 1.5f; // additional distance if on friend
-
-//?const float ARM_NEUTRAL_ANGLE1 = 155.0f*Math::PI/180.0f;
-//?const float ARM_NEUTRAL_ANGLE2 = -125.0f*Math::PI/180.0f;
-//?const float ARM_NEUTRAL_ANGLE3 = -45.0f*Math::PI/180.0f;
-const float ARM_NEUTRAL_ANGLE1 = 110.0f*Math::PI/180.0f;
-const float ARM_NEUTRAL_ANGLE2 = -130.0f*Math::PI/180.0f;
-const float ARM_NEUTRAL_ANGLE3 = -50.0f*Math::PI/180.0f;
-
-const float ARM_STOCK_ANGLE1 = 110.0f*Math::PI/180.0f;
-const float ARM_STOCK_ANGLE2 = -100.0f*Math::PI/180.0f;
-const float ARM_STOCK_ANGLE3 = -70.0f*Math::PI/180.0f;
-
-
-class CTask
-{
-public:
- CTask(CInstanceManager* iMan, CObject* object);
- virtual ~CTask();
-
- virtual bool EventProcess(const Event &event);
- virtual Error IsEnded();
- virtual bool IsBusy();
- virtual bool Abort();
-
-protected:
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CLight* m_light;
- CParticule* m_particule;
- CTerrain* m_terrain;
- CWater* m_water;
- CCamera* m_camera;
- CMotion* m_motion;
- CBrain* m_brain;
- CPhysics* m_physics;
- CObject* m_object;
- CRobotMain* m_main;
- CDisplayText* m_displayText;
- CSound* m_sound;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// task.h + +#pragma once + + +#include "common/misc.h" +#include "math/const.h" + + +class CInstanceManager; +class CD3DEngine; +class CLight; +class CParticule; +class CTerrain; +class CWater; +class CCamera; +class CBrain; +class CPhysics; +class CMotion; +class CObject; +class CRobotMain; +class CDisplayText; +class CSound; + + +const float TAKE_DIST = 6.0f; // distance to an object to pick it +const float TAKE_DIST_OTHER = 1.5f; // additional distance if on friend + +//?const float ARM_NEUTRAL_ANGLE1 = 155.0f*Math::PI/180.0f; +//?const float ARM_NEUTRAL_ANGLE2 = -125.0f*Math::PI/180.0f; +//?const float ARM_NEUTRAL_ANGLE3 = -45.0f*Math::PI/180.0f; +const float ARM_NEUTRAL_ANGLE1 = 110.0f*Math::PI/180.0f; +const float ARM_NEUTRAL_ANGLE2 = -130.0f*Math::PI/180.0f; +const float ARM_NEUTRAL_ANGLE3 = -50.0f*Math::PI/180.0f; + +const float ARM_STOCK_ANGLE1 = 110.0f*Math::PI/180.0f; +const float ARM_STOCK_ANGLE2 = -100.0f*Math::PI/180.0f; +const float ARM_STOCK_ANGLE3 = -70.0f*Math::PI/180.0f; + + +class CTask +{ +public: + CTask(CInstanceManager* iMan, CObject* object); + virtual ~CTask(); + + virtual bool EventProcess(const Event &event); + virtual Error IsEnded(); + virtual bool IsBusy(); + virtual bool Abort(); + +protected: + +protected: + CInstanceManager* m_iMan; + CD3DEngine* m_engine; + CLight* m_light; + CParticule* m_particule; + CTerrain* m_terrain; + CWater* m_water; + CCamera* m_camera; + CMotion* m_motion; + CBrain* m_brain; + CPhysics* m_physics; + CObject* m_object; + CRobotMain* m_main; + CDisplayText* m_displayText; + CSound* m_sound; +}; + diff --git a/src/object/task/taskadvance.cpp b/src/object/task/taskadvance.cpp index c5a87d3..e50cb08 100644 --- a/src/object/task/taskadvance.cpp +++ b/src/object/task/taskadvance.cpp @@ -1,146 +1,146 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskadvance.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskadvance.h"
-
-#include "math/geometry.h"
-#include "physics/physics.h"
-
-
-
-
-// Object's constructor.
-
-CTaskAdvance::CTaskAdvance(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskAdvance::~CTaskAdvance()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskAdvance::EventProcess(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_fixTime += event.rTime;
-
- // Momentarily stationary object (ant on the back)?
- if ( m_object->RetFixed() )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_bError = true;
- return true;
- }
-
- m_timeLimit -= event.rTime;
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskAdvance::Start(float length)
-{
- m_direction = (length>=0.0f)?1.0f:-1.0f;
- m_totalLength = fabs(length);
- m_advanceLength = m_physics->RetLinLength(length);
- m_startPos = m_object->RetPosition(0);
- m_lastDist = 0.0f;
- m_fixTime = 0.0f;
-
- m_timeLimit = m_physics->RetLinTimeLength(m_totalLength, m_direction)*3.0f;
- if ( m_timeLimit < 2.0f ) m_timeLimit = 2.0f;
-
- m_physics->SetMotorSpeedX(m_direction*1.0f); // forward/backward
- m_physics->SetMotorSpeedY(0.0f);
- m_physics->SetMotorSpeedZ(0.0f);
-
- m_bError = false;
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskAdvance::IsEnded()
-{
- Math::Vector pos;
- float length;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
-
- if ( m_bError )
- {
- return ERR_STOP;
- }
-
- if ( m_timeLimit < 0.0f )
- {
- m_physics->SetMotorSpeedX(0.0f);
- return ERR_MOVE_IMPOSSIBLE;
- }
-
- pos = m_object->RetPosition(0);
- length = Math::DistanceProjected(pos, m_startPos);
-
- if ( length > m_lastDist ) // forward?
- {
- m_fixTime = 0.0f;
- }
- else // still stands?
- {
- if ( m_fixTime > 1.0f ) // for more than a second?
- {
- m_physics->SetMotorSpeedX(0.0f);
- return ERR_MOVE_IMPOSSIBLE;
- }
- }
- m_lastDist = length;
-
- if ( length >= m_totalLength )
- {
- m_physics->SetMotorSpeedX(0.0f);
- m_physics->SetLinMotionX(MO_CURSPEED, 0.0f);
-
- if ( length != 0.0f )
- {
- pos = m_startPos+((pos-m_startPos)*m_totalLength/length);
- m_object->SetPosition(0, pos);
- }
- return ERR_STOP;
- }
-
- if ( length >= m_advanceLength )
- {
- m_physics->SetMotorSpeedX(m_direction*0.1f);
- }
- return ERR_CONTINUE;
-}
-
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskadvance.cpp + + +#include <stdio.h> + +#include "object/task/taskadvance.h" + +#include "math/geometry.h" +#include "physics/physics.h" + + + + +// Object's constructor. + +CTaskAdvance::CTaskAdvance(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ +} + +// Object's destructor. + +CTaskAdvance::~CTaskAdvance() +{ +} + + +// Management of an event. + +bool CTaskAdvance::EventProcess(const Event &event) +{ + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + + m_fixTime += event.rTime; + + // Momentarily stationary object (ant on the back)? + if ( m_object->RetFixed() ) + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + m_bError = true; + return true; + } + + m_timeLimit -= event.rTime; + return true; +} + + +// Assigns the goal was achieved. + +Error CTaskAdvance::Start(float length) +{ + m_direction = (length>=0.0f)?1.0f:-1.0f; + m_totalLength = fabs(length); + m_advanceLength = m_physics->RetLinLength(length); + m_startPos = m_object->RetPosition(0); + m_lastDist = 0.0f; + m_fixTime = 0.0f; + + m_timeLimit = m_physics->RetLinTimeLength(m_totalLength, m_direction)*3.0f; + if ( m_timeLimit < 2.0f ) m_timeLimit = 2.0f; + + m_physics->SetMotorSpeedX(m_direction*1.0f); // forward/backward + m_physics->SetMotorSpeedY(0.0f); + m_physics->SetMotorSpeedZ(0.0f); + + m_bError = false; + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskAdvance::IsEnded() +{ + Math::Vector pos; + float length; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + + if ( m_bError ) + { + return ERR_STOP; + } + + if ( m_timeLimit < 0.0f ) + { + m_physics->SetMotorSpeedX(0.0f); + return ERR_MOVE_IMPOSSIBLE; + } + + pos = m_object->RetPosition(0); + length = Math::DistanceProjected(pos, m_startPos); + + if ( length > m_lastDist ) // forward? + { + m_fixTime = 0.0f; + } + else // still stands? + { + if ( m_fixTime > 1.0f ) // for more than a second? + { + m_physics->SetMotorSpeedX(0.0f); + return ERR_MOVE_IMPOSSIBLE; + } + } + m_lastDist = length; + + if ( length >= m_totalLength ) + { + m_physics->SetMotorSpeedX(0.0f); + m_physics->SetLinMotionX(MO_CURSPEED, 0.0f); + + if ( length != 0.0f ) + { + pos = m_startPos+((pos-m_startPos)*m_totalLength/length); + m_object->SetPosition(0, pos); + } + return ERR_STOP; + } + + if ( length >= m_advanceLength ) + { + m_physics->SetMotorSpeedX(m_direction*0.1f); + } + return ERR_CONTINUE; +} + + diff --git a/src/object/task/taskadvance.h b/src/object/task/taskadvance.h index b0f09b1..dbb80d9 100644 --- a/src/object/task/taskadvance.h +++ b/src/object/task/taskadvance.h @@ -1,50 +1,50 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskadvance.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-class CTaskAdvance : public CTask
-{
-public:
- CTaskAdvance(CInstanceManager* iMan, CObject* object);
- ~CTaskAdvance();
-
- bool EventProcess(const Event &event);
-
- Error Start(float length);
- Error IsEnded();
-
-protected:
-
-protected:
- float m_totalLength;
- float m_advanceLength;
- float m_direction;
- float m_timeLimit;
- Math::Vector m_startPos;
- float m_lastDist;
- float m_fixTime;
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskadvance.h + +#pragma once + + +#include "object/task/task.h" +#include "math/vector.h" + + + +class CTaskAdvance : public CTask +{ +public: + CTaskAdvance(CInstanceManager* iMan, CObject* object); + ~CTaskAdvance(); + + bool EventProcess(const Event &event); + + Error Start(float length); + Error IsEnded(); + +protected: + +protected: + float m_totalLength; + float m_advanceLength; + float m_direction; + float m_timeLimit; + Math::Vector m_startPos; + float m_lastDist; + float m_fixTime; + bool m_bError; +}; + diff --git a/src/object/task/taskbuild.cpp b/src/object/task/taskbuild.cpp index f9d6c57..25936f9 100644 --- a/src/object/task/taskbuild.cpp +++ b/src/object/task/taskbuild.cpp @@ -1,806 +1,806 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskbuild.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskbuild.h"
-
-#include "common/iman.h"
-#include "old/light.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "math/geometry.h"
-#include "object/auto/auto.h"
-#include "object/motion/motionhuman.h"
-#include "object/robotmain.h"
-#include "physics/physics.h"
-#include "ui/displaytext.h"
-
-
-
-
-// Object's constructor.
-
-CTaskBuild::CTaskBuild(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- int i;
-
- m_type = OBJECT_DERRICK;
- m_time = 0.0f;
- m_soundChannel = -1;
-
- for ( i=0 ; i<TBMAXLIGHT ; i++ )
- {
- m_lightRank[i] = -1;
- }
-}
-
-// Object's destructor.
-
-CTaskBuild::~CTaskBuild()
-{
- int i;
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- for ( i=0 ; i<TBMAXLIGHT ; i++ )
- {
- if ( m_lightRank[i] == -1 ) continue;
- m_light->DeleteLight(m_lightRank[i]);
- }
-}
-
-
-// Creates a building.
-
-bool CTaskBuild::CreateBuilding(Math::Vector pos, float angle)
-{
- m_building = new CObject(m_iMan);
- if ( !m_building->CreateBuilding(pos, angle, 0.0f, m_type, 0.0f) )
- {
- delete m_building;
- m_building = 0;
- return false;
- }
- m_building->UpdateMapping();
- m_building->SetLock(true); // not yet usable
-
- if ( m_type == OBJECT_DERRICK ) m_buildingHeight = 35.0f;
- if ( m_type == OBJECT_FACTORY ) m_buildingHeight = 28.0f;
- if ( m_type == OBJECT_REPAIR ) m_buildingHeight = 30.0f;
- if ( m_type == OBJECT_STATION ) m_buildingHeight = 13.0f;
- if ( m_type == OBJECT_CONVERT ) m_buildingHeight = 20.0f;
- if ( m_type == OBJECT_TOWER ) m_buildingHeight = 30.0f;
- if ( m_type == OBJECT_RESEARCH ) m_buildingHeight = 22.0f;
- if ( m_type == OBJECT_RADAR ) m_buildingHeight = 19.0f;
- if ( m_type == OBJECT_ENERGY ) m_buildingHeight = 20.0f;
- if ( m_type == OBJECT_LABO ) m_buildingHeight = 16.0f;
- if ( m_type == OBJECT_NUCLEAR ) m_buildingHeight = 40.0f;
- if ( m_type == OBJECT_PARA ) m_buildingHeight = 68.0f;
- if ( m_type == OBJECT_INFO ) m_buildingHeight = 19.0f;
- m_buildingHeight *= 0.25f;
-
- m_buildingPos = m_building->RetPosition(0);
- m_buildingPos.y -= m_buildingHeight;
- m_building->SetPosition(0, m_buildingPos);
- return true;
-}
-
-// Creates lights for the effects.
-
-void CTaskBuild::CreateLight()
-{
- D3DLIGHT7 light;
- D3DCOLORVALUE color;
- Math::Vector center, pos, dir;
- Math::Point c, p;
- float angle;
- int i;
-
- if ( !m_engine->RetLightMode() ) return;
-
- center = m_metal->RetPosition(0);
-
- angle = 0;
- for ( i=0 ; i<TBMAXLIGHT ; i++ )
- {
- m_lightRank[i] = m_light->CreateLight();
- if ( m_lightRank[i] == -1 ) continue;
-
- c.x = center.x;
- c.y = center.z;
- p.x = center.x+40.0f;
- p.y = center.z;
- p = Math::RotatePoint(c, angle, p);
- pos.x = p.x;
- pos.z = p.y;
- pos.y = center.y+40.0f;
- dir = center-pos;
-
- ZeroMemory( &light, sizeof(light) );
- light.dltType = D3DLIGHT_SPOT;
- light.dcvDiffuse.r = 0.0f;
- light.dcvDiffuse.g = 0.0f;
- light.dcvDiffuse.b = 0.0f; // white (invisible)
- light.dvPosition.x = pos.x;
- light.dvPosition.y = pos.y;
- light.dvPosition.z = pos.z;
- light.dvDirection.x = dir.x;
- light.dvDirection.y = dir.y;
- light.dvDirection.z = dir.z;
- light.dvRange = D3DLIGHT_RANGE_MAX;
- light.dvFalloff = 1.0f;
- light.dvAttenuation0 = 1.0f;
- light.dvAttenuation1 = 0.0f;
- light.dvAttenuation2 = 0.0f;
- light.dvTheta = 0.0f;
- light.dvPhi = Math::PI/4.0f;
- m_light->SetLight(m_lightRank[i], light);
-
- color.r = -1.0f;
- color.g = -1.0f;
- color.b = -0.5f; // violet
- color.a = 0.0f;
- m_light->SetLightColor(m_lightRank[i], color);
- m_light->SetLightColorSpeed(m_lightRank[i], 1.0f/((1.0f/m_speed)*0.25f));
-
- angle += (Math::PI*2.0f)/TBMAXLIGHT;
- }
-
- m_bBlack = false;
-}
-
-// Switches the lights from black to white.
-
-void CTaskBuild::BlackLight()
-{
- D3DCOLORVALUE color;
- int i;
-
- for ( i=0 ; i<TBMAXLIGHT ; i++ )
- {
- if ( m_lightRank[i] == -1 ) continue;
-
- color.r = 0.0f;
- color.g = 0.0f;
- color.b = 0.0f; // white (invisible)
- color.a = 0.0f;
- m_light->SetLightColor(m_lightRank[i], color);
- m_light->SetLightColorSpeed(m_lightRank[i], 1.0f/((1.0f/m_speed)*0.75f));
- }
-
- m_bBlack = true;
-}
-
-// Management of an event.
-
-bool CTaskBuild::EventProcess(const Event &event)
-{
- Math::Matrix* mat;
- Math::Vector pos, dir, speed;
- Math::Point dim;
- float a, g, cirSpeed, dist, linSpeed;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_time += event.rTime;
-
- m_progress += event.rTime*m_speed; // other advance
-
- if ( m_phase == TBP_TURN ) // preliminary rotation?
- {
- a = m_object->RetAngleY(0);
- g = m_angleY;
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left/right
- return true;
- }
-
- if ( m_phase == TBP_MOVE ) // preliminary forward/backward?
- {
- dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0));
- linSpeed = 0.0f;
- if ( dist > 30.0f ) linSpeed = 1.0f;
- if ( dist < 30.0f ) linSpeed = -1.0f;
- m_physics->SetMotorSpeedX(linSpeed); // forward/backward
- return true;
- }
-
- if ( m_phase == TBP_RECEDE ) // terminal back?
- {
- m_physics->SetMotorSpeedX(-1.0f); // back
- return true;
- }
-
- if ( m_phase == TBP_TAKE ) // takes gun?
- {
- return true;
- }
-
- if ( m_phase == TBP_PREP ) // prepares?
- {
- return true;
- }
-
- if ( m_phase == TBP_TERM ) // ends?
- {
- return true;
- }
-
- if ( !m_bBuild ) // building to build?
- {
- m_bBuild = true;
-
- pos = m_metal->RetPosition(0);
- a = m_object->RetAngleY(0);
- if ( !CreateBuilding(pos, a+Math::PI) )
- {
- m_metal->SetLock(false); // usable again
- m_motion->SetAction(-1);
- m_object->SetObjectParent(14, 0);
- m_object->SetPosition(14, Math::Vector(-1.5f, 0.3f, -1.35f));
- m_object->SetAngleZ(14, Math::PI);
- m_camera->FlushEffect();
- Abort();
- m_bError = true;
- m_displayText->DisplayError(ERR_TOOMANY, m_object->RetPosition(0));
- return false;
- }
- CreateLight();
- }
-
- pos = m_buildingPos;
- pos.y += m_buildingHeight*m_progress;
- m_building->SetPosition(0, pos); // the building rises
-
- m_building->SetZoom(0, m_progress*0.75f+0.25f);
- m_metal->SetZoom(0, 1.0f-m_progress);
-
- a = (2.0f-2.0f*m_progress);
- if ( a > 1.0f ) a = 1.0f;
- dir.x = (Math::Rand()-0.5f)*a*0.1f;
- dir.z = (Math::Rand()-0.5f)*a*0.1f;
- dir.y = (Math::Rand()-0.5f)*a*0.1f;
- m_building->SetCirVibration(dir);
-
- if ( !m_bBlack && m_progress >= 0.25f )
- {
- BlackLight();
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_metal->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = Math::Rand()*10.0f;
- dim.x = Math::Rand()*6.0f+4.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFIRE);
-
- pos = Math::Vector(0.0f, 0.5f, 0.0f);
- mat = m_object->RetWorldMatrix(14);
- pos = Transform(*mat, pos);
- speed = m_metal->RetPosition(0);
- speed.x += (Math::Rand()-0.5f)*5.0f;
- speed.z += (Math::Rand()-0.5f)*5.0f;
- speed -= pos;
- dim.x = 2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ);
-
- if ( Math::Rand() < 0.3f )
- {
- m_sound->Play(SOUND_BUILD, m_object->RetPosition(0), 0.5f, 1.0f*Math::Rand()*1.5f);
- }
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskBuild::Start(ObjectType type)
-{
- Math::Vector pos, speed, pv, pm;
- Error err;
- float iAngle, oAngle;
-
- m_type = type;
- m_lastParticule = 0.0f;
- m_progress = 0.0f;
-
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
- oAngle = iAngle;
-
- m_bError = true; // operation impossible
-
- pos = m_object->RetPosition(0);
- if ( pos.y < m_water->RetLevel() ) return ERR_BUILD_WATER;
-
- if ( !m_physics->RetLand() ) return ERR_BUILD_FLY;
-
- speed = m_physics->RetMotorSpeed();
- if ( speed.x != 0.0f ||
- speed.z != 0.0f ) return ERR_BUILD_MOTOR;
-
- if ( m_object->RetFret() != 0 ) return ERR_MANIP_BUSY;
-
- m_metal = SearchMetalObject(oAngle, 2.0f, 100.0f, Math::PI*0.25f, err);
- if ( err == ERR_BUILD_METALNEAR && m_metal != 0 )
- {
- err = FlatFloor();
- if ( err != ERR_OK ) return err;
- return ERR_BUILD_METALNEAR;
- }
- if ( err != ERR_OK ) return err;
-
- err = FlatFloor();
- if ( err != ERR_OK ) return err;
-
- m_metal->SetLock(true); // not usable
- m_camera->StartCentering(m_object, Math::PI*0.15f, 99.9f, 0.0f, 1.0f);
-
- m_phase = TBP_TURN; // rotation necessary preliminary
- m_angleY = oAngle; // angle was reached
-
- pv = m_object->RetPosition(0);
- pv.y += 8.3f;
- pm = m_metal->RetPosition(0);
- m_angleZ = Math::RotateAngle(Math::DistanceProjected(pv, pm), fabs(pv.y-pm.y));
-
- m_physics->SetFreeze(true); // it does not move
-
- m_bBuild = false; // not yet built
- m_bError = false; // ok
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskBuild::IsEnded()
-{
- CAuto* automat;
- float angle, dist, time;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_phase == TBP_TURN ) // preliminary rotation?
- {
- angle = m_object->RetAngleY(0);
- angle = Math::NormAngle(angle); // 0..2*Math::PI
-
- if ( Math::TestAngle(angle, m_angleY-Math::PI*0.01f, m_angleY+Math::PI*0.01f) )
- {
- m_physics->SetMotorSpeedZ(0.0f);
-
- dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0));
- if ( dist > 30.0f )
- {
- time = m_physics->RetLinTimeLength(dist-30.0f, 1.0f);
- m_speed = 1.0f/time;
- }
- else
- {
- time = m_physics->RetLinTimeLength(30.0f-dist, -1.0f);
- m_speed = 1.0f/time;
- }
- m_phase = TBP_MOVE;
- m_progress = 0.0f;
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TBP_MOVE ) // preliminary forward/backward?
- {
- dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0));
-
- if ( dist >= 25.0f && dist <= 35.0f )
- {
- m_physics->SetMotorSpeedX(0.0f);
- m_motion->SetAction(MHS_GUN); // takes gun
-
- m_phase = TBP_TAKE;
- m_speed = 1.0f/1.0f;
- m_progress = 0.0f;
- }
- else
- {
- if ( m_progress > 1.0f ) // timeout?
- {
- m_metal->SetLock(false); // usable again
- if ( dist < 30.0f ) return ERR_BUILD_METALNEAR;
- else return ERR_BUILD_METALAWAY;
- }
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TBP_TAKE ) // takes gun
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_motion->SetAction(MHS_FIRE); // shooting position
- m_object->SetObjectParent(14, 4);
- m_object->SetPosition(14, Math::Vector(0.6f, 0.1f, 0.3f));
- m_object->SetAngleZ(14, 0.0f);
-
- m_phase = TBP_PREP;
- m_speed = 1.0f/1.0f;
- m_progress = 0.0f;
- }
-
- if ( m_phase == TBP_PREP ) // prepares?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_soundChannel = m_sound->Play(SOUND_TREMBLE, m_object->RetPosition(0), 0.0f, 1.0f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.7f, 1.0f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.7f, 1.5f, 7.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.5f, 2.0f, SOPER_STOP);
-
- m_camera->StartEffect(CE_VIBRATION, m_metal->RetPosition(0), 1.0f);
-
- m_phase = TBP_BUILD;
- m_speed = 1.0f/10.f; // duration of 10s
- m_progress = 0.0f;
- }
-
- if ( m_phase == TBP_BUILD ) // construction?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- DeleteMark(m_metal->RetPosition(0), 20.0f);
-
- m_metal->DeleteObject(); // removes the metal
- delete m_metal;
- m_metal = 0;
-
- m_building->SetZoom(0, 1.0f);
- m_building->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- m_building->SetLock(false); // building usable
- m_main->CreateShortcuts();
- m_displayText->DisplayError(INFO_BUILD, m_buildingPos, 10.0f, 50.0f);
-
- automat = m_building->RetAuto();
- if ( automat != 0 )
- {
- automat->Init();
- }
-
- m_motion->SetAction(MHS_GUN); // hands gun
- m_phase = TBP_TERM;
- m_speed = 1.0f/1.0f;
- m_progress = 0.0f;
- }
-
- if ( m_phase == TBP_TERM ) // rotation terminale ?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_motion->SetAction(-1);
- m_object->SetObjectParent(14, 0);
- m_object->SetPosition(14, Math::Vector(-1.5f, 0.3f, -1.35f));
- m_object->SetAngleZ(14, Math::PI);
-
- if ( m_type == OBJECT_FACTORY ||
- m_type == OBJECT_RESEARCH ||
- m_type == OBJECT_NUCLEAR )
- {
-
- m_phase = TBP_RECEDE;
- m_speed = 1.0f/1.5f;
- m_progress = 0.0f;
- }
- }
-
- if ( m_phase == TBP_RECEDE ) // back?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_physics->SetMotorSpeedX(0.0f);
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskBuild::Abort()
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- m_camera->StopCentering(m_object, 2.0f);
- m_physics->SetFreeze(false); // is moving again
- return true;
-}
-
-
-// Checks whether the terrain is fairly flat
-// and if there is not too close to another object.
-
-Error CTaskBuild::FlatFloor()
-{
- CObject *pObj;
- ObjectType type;
- Math::Vector center, pos, oPos, bPos;
- Math::Point c, p;
- float radius, max, oRadius, bRadius, angle, dist;
- int i, j;
- bool bLittleFlat, bBase;
-
- radius = 0.0f;
- if ( m_type == OBJECT_DERRICK ) radius = 5.0f;
- if ( m_type == OBJECT_FACTORY ) radius = 15.0f;
- if ( m_type == OBJECT_REPAIR ) radius = 12.0f;
- if ( m_type == OBJECT_STATION ) radius = 12.0f;
- if ( m_type == OBJECT_CONVERT ) radius = 12.0f;
- if ( m_type == OBJECT_TOWER ) radius = 7.0f;
- if ( m_type == OBJECT_RESEARCH ) radius = 10.0f;
- if ( m_type == OBJECT_RADAR ) radius = 5.0f;
- if ( m_type == OBJECT_ENERGY ) radius = 8.0f;
- if ( m_type == OBJECT_LABO ) radius = 12.0f;
- if ( m_type == OBJECT_NUCLEAR ) radius = 20.0f;
- if ( m_type == OBJECT_PARA ) radius = 20.0f;
- if ( m_type == OBJECT_INFO ) radius = 5.0f;
- if ( radius == 0.0f ) return ERR_GENERIC;
-
- center = m_metal->RetPosition(0);
- angle = m_terrain->RetFineSlope(center);
- bLittleFlat = ( angle < FLATLIMIT );
-
- max = m_terrain->RetFlatZoneRadius(center, radius);
- if ( max < radius ) // area too small?
- {
- if ( bLittleFlat )
- {
- m_main->SetShowLimit(1, PARTILIMIT3, m_metal, center, max, 10.0f);
- }
- return bLittleFlat?ERR_BUILD_FLATLIT:ERR_BUILD_FLAT;
- }
-
- max = 100000.0f;
- bBase = false;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj == m_metal ) continue;
- if ( pObj == m_object ) continue;
-
- type = pObj->RetType();
- if ( type == OBJECT_BASE )
- {
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(center, oPos)-80.0f;
- if ( dist < max )
- {
- max = dist;
- bPos = oPos;
- bRadius = oRadius;
- bBase = true;
- }
- }
- else
- {
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- dist = Math::Distance(center, oPos)-oRadius;
- if ( dist < max )
- {
- max = dist;
- bPos = oPos;
- bRadius = oRadius;
- bBase = false;
- }
- }
- }
- }
- if ( max < radius )
- {
- m_main->SetShowLimit(1, PARTILIMIT2, m_metal, center, max, 10.0f);
- if ( bRadius < 2.0f ) bRadius = 2.0f;
- m_main->SetShowLimit(2, PARTILIMIT3, m_metal, bPos, bRadius, 10.0f);
- return bBase?ERR_BUILD_BASE:ERR_BUILD_BUSY;
- }
-
- max = 100000.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj == m_metal ) continue;
- if ( pObj == m_object ) continue;
-
- type = pObj->RetType();
- if ( type == OBJECT_DERRICK ||
- type == OBJECT_FACTORY ||
- type == OBJECT_STATION ||
- type == OBJECT_CONVERT ||
- type == OBJECT_REPAIR ||
- type == OBJECT_TOWER ||
- type == OBJECT_RESEARCH ||
- type == OBJECT_RADAR ||
- type == OBJECT_ENERGY ||
- type == OBJECT_LABO ||
- type == OBJECT_NUCLEAR ||
- type == OBJECT_START ||
- type == OBJECT_END ||
- type == OBJECT_INFO ||
- type == OBJECT_PARA ||
- type == OBJECT_SAFE ||
- type == OBJECT_HUSTON ) // building?
- {
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- dist = Math::Distance(center, oPos)-oRadius;
- if ( dist < max )
- {
- max = dist;
- bPos = oPos;
- bRadius = oRadius;
- }
- }
- }
- }
- if ( max-BUILDMARGIN < radius )
- {
- m_main->SetShowLimit(1, PARTILIMIT2, m_metal, center, max-BUILDMARGIN, 10.0f);
- m_main->SetShowLimit(2, PARTILIMIT3, m_metal, bPos, bRadius+BUILDMARGIN, 10.0f);
- return bBase?ERR_BUILD_BASE:ERR_BUILD_NARROW;
- }
-
- return ERR_OK;
-}
-
-// Seeks the nearest metal object.
-
-CObject* CTaskBuild::SearchMetalObject(float &angle, float dMin, float dMax,
- float aLimit, Error &err)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float min, iAngle, a, aa, aBest, distance, magic;
- int i;
- bool bMetal;
-
- iPos = m_object->RetPosition(0);
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- min = 1000000.0f;
- pBest = 0;
- bMetal = false;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // objet inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- type = pObj->RetType();
- if ( type != OBJECT_METAL ) continue;
-
- bMetal = true; // metal exists
-
- oPos = pObj->RetPosition(0);
- distance = Math::Distance(oPos, iPos);
- a = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW!
-
- if ( distance > dMax ) continue;
- if ( !Math::TestAngle(a, iAngle-aLimit, iAngle+aLimit) ) continue;
-
- if ( distance < dMin )
- {
- err = ERR_BUILD_METALNEAR; // too close
- return pObj;
- }
-
- aa = fabs(a-iAngle);
- if ( aa > Math::PI ) aa = Math::PI*2.0f-aa;
- magic = distance*aa;
-
- if ( magic < min )
- {
- min = magic;
- aBest = a;
- pBest = pObj;
- }
- }
-
- if ( pBest == 0 )
- {
- if ( bMetal ) err = ERR_BUILD_METALAWAY; // too far
- else err = ERR_BUILD_METALINEX; // non-existent
- }
- else
- {
- angle = aBest;
- err = ERR_OK;
- }
- return pBest;
-}
-
-// Destroys all the close marks.
-
-void CTaskBuild::DeleteMark(Math::Vector pos, float radius)
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- float distance;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_MARKSTONE &&
- type != OBJECT_MARKURANIUM &&
- type != OBJECT_MARKKEYa &&
- type != OBJECT_MARKKEYb &&
- type != OBJECT_MARKKEYc &&
- type != OBJECT_MARKKEYd &&
- type != OBJECT_MARKPOWER ) continue;
-
- oPos = pObj->RetPosition(0);
- distance = Math::Distance(oPos, pos);
- if ( distance <= radius )
- {
- pObj->DeleteObject(); // removes the mark
- delete pObj;
- i --;
- }
- }
-}
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskbuild.cpp + + +#include <stdio.h> + +#include "object/task/taskbuild.h" + +#include "common/iman.h" +#include "old/light.h" +#include "old/terrain.h" +#include "old/water.h" +#include "math/geometry.h" +#include "object/auto/auto.h" +#include "object/motion/motionhuman.h" +#include "object/robotmain.h" +#include "physics/physics.h" +#include "ui/displaytext.h" + + + + +// Object's constructor. + +CTaskBuild::CTaskBuild(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + int i; + + m_type = OBJECT_DERRICK; + m_time = 0.0f; + m_soundChannel = -1; + + for ( i=0 ; i<TBMAXLIGHT ; i++ ) + { + m_lightRank[i] = -1; + } +} + +// Object's destructor. + +CTaskBuild::~CTaskBuild() +{ + int i; + + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + + for ( i=0 ; i<TBMAXLIGHT ; i++ ) + { + if ( m_lightRank[i] == -1 ) continue; + m_light->DeleteLight(m_lightRank[i]); + } +} + + +// Creates a building. + +bool CTaskBuild::CreateBuilding(Math::Vector pos, float angle) +{ + m_building = new CObject(m_iMan); + if ( !m_building->CreateBuilding(pos, angle, 0.0f, m_type, 0.0f) ) + { + delete m_building; + m_building = 0; + return false; + } + m_building->UpdateMapping(); + m_building->SetLock(true); // not yet usable + + if ( m_type == OBJECT_DERRICK ) m_buildingHeight = 35.0f; + if ( m_type == OBJECT_FACTORY ) m_buildingHeight = 28.0f; + if ( m_type == OBJECT_REPAIR ) m_buildingHeight = 30.0f; + if ( m_type == OBJECT_STATION ) m_buildingHeight = 13.0f; + if ( m_type == OBJECT_CONVERT ) m_buildingHeight = 20.0f; + if ( m_type == OBJECT_TOWER ) m_buildingHeight = 30.0f; + if ( m_type == OBJECT_RESEARCH ) m_buildingHeight = 22.0f; + if ( m_type == OBJECT_RADAR ) m_buildingHeight = 19.0f; + if ( m_type == OBJECT_ENERGY ) m_buildingHeight = 20.0f; + if ( m_type == OBJECT_LABO ) m_buildingHeight = 16.0f; + if ( m_type == OBJECT_NUCLEAR ) m_buildingHeight = 40.0f; + if ( m_type == OBJECT_PARA ) m_buildingHeight = 68.0f; + if ( m_type == OBJECT_INFO ) m_buildingHeight = 19.0f; + m_buildingHeight *= 0.25f; + + m_buildingPos = m_building->RetPosition(0); + m_buildingPos.y -= m_buildingHeight; + m_building->SetPosition(0, m_buildingPos); + return true; +} + +// Creates lights for the effects. + +void CTaskBuild::CreateLight() +{ + D3DLIGHT7 light; + D3DCOLORVALUE color; + Math::Vector center, pos, dir; + Math::Point c, p; + float angle; + int i; + + if ( !m_engine->RetLightMode() ) return; + + center = m_metal->RetPosition(0); + + angle = 0; + for ( i=0 ; i<TBMAXLIGHT ; i++ ) + { + m_lightRank[i] = m_light->CreateLight(); + if ( m_lightRank[i] == -1 ) continue; + + c.x = center.x; + c.y = center.z; + p.x = center.x+40.0f; + p.y = center.z; + p = Math::RotatePoint(c, angle, p); + pos.x = p.x; + pos.z = p.y; + pos.y = center.y+40.0f; + dir = center-pos; + + ZeroMemory( &light, sizeof(light) ); + light.dltType = D3DLIGHT_SPOT; + light.dcvDiffuse.r = 0.0f; + light.dcvDiffuse.g = 0.0f; + light.dcvDiffuse.b = 0.0f; // white (invisible) + light.dvPosition.x = pos.x; + light.dvPosition.y = pos.y; + light.dvPosition.z = pos.z; + light.dvDirection.x = dir.x; + light.dvDirection.y = dir.y; + light.dvDirection.z = dir.z; + light.dvRange = D3DLIGHT_RANGE_MAX; + light.dvFalloff = 1.0f; + light.dvAttenuation0 = 1.0f; + light.dvAttenuation1 = 0.0f; + light.dvAttenuation2 = 0.0f; + light.dvTheta = 0.0f; + light.dvPhi = Math::PI/4.0f; + m_light->SetLight(m_lightRank[i], light); + + color.r = -1.0f; + color.g = -1.0f; + color.b = -0.5f; // violet + color.a = 0.0f; + m_light->SetLightColor(m_lightRank[i], color); + m_light->SetLightColorSpeed(m_lightRank[i], 1.0f/((1.0f/m_speed)*0.25f)); + + angle += (Math::PI*2.0f)/TBMAXLIGHT; + } + + m_bBlack = false; +} + +// Switches the lights from black to white. + +void CTaskBuild::BlackLight() +{ + D3DCOLORVALUE color; + int i; + + for ( i=0 ; i<TBMAXLIGHT ; i++ ) + { + if ( m_lightRank[i] == -1 ) continue; + + color.r = 0.0f; + color.g = 0.0f; + color.b = 0.0f; // white (invisible) + color.a = 0.0f; + m_light->SetLightColor(m_lightRank[i], color); + m_light->SetLightColorSpeed(m_lightRank[i], 1.0f/((1.0f/m_speed)*0.75f)); + } + + m_bBlack = true; +} + +// Management of an event. + +bool CTaskBuild::EventProcess(const Event &event) +{ + Math::Matrix* mat; + Math::Vector pos, dir, speed; + Math::Point dim; + float a, g, cirSpeed, dist, linSpeed; + + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + if ( m_bError ) return false; + + m_time += event.rTime; + + m_progress += event.rTime*m_speed; // other advance + + if ( m_phase == TBP_TURN ) // preliminary rotation? + { + a = m_object->RetAngleY(0); + g = m_angleY; + cirSpeed = Math::Direction(a, g)*1.0f; + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left/right + return true; + } + + if ( m_phase == TBP_MOVE ) // preliminary forward/backward? + { + dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0)); + linSpeed = 0.0f; + if ( dist > 30.0f ) linSpeed = 1.0f; + if ( dist < 30.0f ) linSpeed = -1.0f; + m_physics->SetMotorSpeedX(linSpeed); // forward/backward + return true; + } + + if ( m_phase == TBP_RECEDE ) // terminal back? + { + m_physics->SetMotorSpeedX(-1.0f); // back + return true; + } + + if ( m_phase == TBP_TAKE ) // takes gun? + { + return true; + } + + if ( m_phase == TBP_PREP ) // prepares? + { + return true; + } + + if ( m_phase == TBP_TERM ) // ends? + { + return true; + } + + if ( !m_bBuild ) // building to build? + { + m_bBuild = true; + + pos = m_metal->RetPosition(0); + a = m_object->RetAngleY(0); + if ( !CreateBuilding(pos, a+Math::PI) ) + { + m_metal->SetLock(false); // usable again + m_motion->SetAction(-1); + m_object->SetObjectParent(14, 0); + m_object->SetPosition(14, Math::Vector(-1.5f, 0.3f, -1.35f)); + m_object->SetAngleZ(14, Math::PI); + m_camera->FlushEffect(); + Abort(); + m_bError = true; + m_displayText->DisplayError(ERR_TOOMANY, m_object->RetPosition(0)); + return false; + } + CreateLight(); + } + + pos = m_buildingPos; + pos.y += m_buildingHeight*m_progress; + m_building->SetPosition(0, pos); // the building rises + + m_building->SetZoom(0, m_progress*0.75f+0.25f); + m_metal->SetZoom(0, 1.0f-m_progress); + + a = (2.0f-2.0f*m_progress); + if ( a > 1.0f ) a = 1.0f; + dir.x = (Math::Rand()-0.5f)*a*0.1f; + dir.z = (Math::Rand()-0.5f)*a*0.1f; + dir.y = (Math::Rand()-0.5f)*a*0.1f; + m_building->SetCirVibration(dir); + + if ( !m_bBlack && m_progress >= 0.25f ) + { + BlackLight(); + } + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_metal->RetPosition(0); + speed.x = (Math::Rand()-0.5f)*20.0f; + speed.z = (Math::Rand()-0.5f)*20.0f; + speed.y = Math::Rand()*10.0f; + dim.x = Math::Rand()*6.0f+4.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIFIRE); + + pos = Math::Vector(0.0f, 0.5f, 0.0f); + mat = m_object->RetWorldMatrix(14); + pos = Transform(*mat, pos); + speed = m_metal->RetPosition(0); + speed.x += (Math::Rand()-0.5f)*5.0f; + speed.z += (Math::Rand()-0.5f)*5.0f; + speed -= pos; + dim.x = 2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ); + + if ( Math::Rand() < 0.3f ) + { + m_sound->Play(SOUND_BUILD, m_object->RetPosition(0), 0.5f, 1.0f*Math::Rand()*1.5f); + } + } + + return true; +} + + +// Assigns the goal was achieved. + +Error CTaskBuild::Start(ObjectType type) +{ + Math::Vector pos, speed, pv, pm; + Error err; + float iAngle, oAngle; + + m_type = type; + m_lastParticule = 0.0f; + m_progress = 0.0f; + + iAngle = m_object->RetAngleY(0); + iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI + oAngle = iAngle; + + m_bError = true; // operation impossible + + pos = m_object->RetPosition(0); + if ( pos.y < m_water->RetLevel() ) return ERR_BUILD_WATER; + + if ( !m_physics->RetLand() ) return ERR_BUILD_FLY; + + speed = m_physics->RetMotorSpeed(); + if ( speed.x != 0.0f || + speed.z != 0.0f ) return ERR_BUILD_MOTOR; + + if ( m_object->RetFret() != 0 ) return ERR_MANIP_BUSY; + + m_metal = SearchMetalObject(oAngle, 2.0f, 100.0f, Math::PI*0.25f, err); + if ( err == ERR_BUILD_METALNEAR && m_metal != 0 ) + { + err = FlatFloor(); + if ( err != ERR_OK ) return err; + return ERR_BUILD_METALNEAR; + } + if ( err != ERR_OK ) return err; + + err = FlatFloor(); + if ( err != ERR_OK ) return err; + + m_metal->SetLock(true); // not usable + m_camera->StartCentering(m_object, Math::PI*0.15f, 99.9f, 0.0f, 1.0f); + + m_phase = TBP_TURN; // rotation necessary preliminary + m_angleY = oAngle; // angle was reached + + pv = m_object->RetPosition(0); + pv.y += 8.3f; + pm = m_metal->RetPosition(0); + m_angleZ = Math::RotateAngle(Math::DistanceProjected(pv, pm), fabs(pv.y-pm.y)); + + m_physics->SetFreeze(true); // it does not move + + m_bBuild = false; // not yet built + m_bError = false; // ok + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskBuild::IsEnded() +{ + CAuto* automat; + float angle, dist, time; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_phase == TBP_TURN ) // preliminary rotation? + { + angle = m_object->RetAngleY(0); + angle = Math::NormAngle(angle); // 0..2*Math::PI + + if ( Math::TestAngle(angle, m_angleY-Math::PI*0.01f, m_angleY+Math::PI*0.01f) ) + { + m_physics->SetMotorSpeedZ(0.0f); + + dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0)); + if ( dist > 30.0f ) + { + time = m_physics->RetLinTimeLength(dist-30.0f, 1.0f); + m_speed = 1.0f/time; + } + else + { + time = m_physics->RetLinTimeLength(30.0f-dist, -1.0f); + m_speed = 1.0f/time; + } + m_phase = TBP_MOVE; + m_progress = 0.0f; + } + return ERR_CONTINUE; + } + + if ( m_phase == TBP_MOVE ) // preliminary forward/backward? + { + dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0)); + + if ( dist >= 25.0f && dist <= 35.0f ) + { + m_physics->SetMotorSpeedX(0.0f); + m_motion->SetAction(MHS_GUN); // takes gun + + m_phase = TBP_TAKE; + m_speed = 1.0f/1.0f; + m_progress = 0.0f; + } + else + { + if ( m_progress > 1.0f ) // timeout? + { + m_metal->SetLock(false); // usable again + if ( dist < 30.0f ) return ERR_BUILD_METALNEAR; + else return ERR_BUILD_METALAWAY; + } + } + return ERR_CONTINUE; + } + + if ( m_phase == TBP_TAKE ) // takes gun + { + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + m_motion->SetAction(MHS_FIRE); // shooting position + m_object->SetObjectParent(14, 4); + m_object->SetPosition(14, Math::Vector(0.6f, 0.1f, 0.3f)); + m_object->SetAngleZ(14, 0.0f); + + m_phase = TBP_PREP; + m_speed = 1.0f/1.0f; + m_progress = 0.0f; + } + + if ( m_phase == TBP_PREP ) // prepares? + { + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + m_soundChannel = m_sound->Play(SOUND_TREMBLE, m_object->RetPosition(0), 0.0f, 1.0f, true); + m_sound->AddEnvelope(m_soundChannel, 0.7f, 1.0f, 1.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.7f, 1.5f, 7.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.5f, 2.0f, SOPER_STOP); + + m_camera->StartEffect(CE_VIBRATION, m_metal->RetPosition(0), 1.0f); + + m_phase = TBP_BUILD; + m_speed = 1.0f/10.f; // duration of 10s + m_progress = 0.0f; + } + + if ( m_phase == TBP_BUILD ) // construction? + { + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + DeleteMark(m_metal->RetPosition(0), 20.0f); + + m_metal->DeleteObject(); // removes the metal + delete m_metal; + m_metal = 0; + + m_building->SetZoom(0, 1.0f); + m_building->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f)); + m_building->SetLock(false); // building usable + m_main->CreateShortcuts(); + m_displayText->DisplayError(INFO_BUILD, m_buildingPos, 10.0f, 50.0f); + + automat = m_building->RetAuto(); + if ( automat != 0 ) + { + automat->Init(); + } + + m_motion->SetAction(MHS_GUN); // hands gun + m_phase = TBP_TERM; + m_speed = 1.0f/1.0f; + m_progress = 0.0f; + } + + if ( m_phase == TBP_TERM ) // rotation terminale ? + { + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + m_motion->SetAction(-1); + m_object->SetObjectParent(14, 0); + m_object->SetPosition(14, Math::Vector(-1.5f, 0.3f, -1.35f)); + m_object->SetAngleZ(14, Math::PI); + + if ( m_type == OBJECT_FACTORY || + m_type == OBJECT_RESEARCH || + m_type == OBJECT_NUCLEAR ) + { + + m_phase = TBP_RECEDE; + m_speed = 1.0f/1.5f; + m_progress = 0.0f; + } + } + + if ( m_phase == TBP_RECEDE ) // back? + { + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + m_physics->SetMotorSpeedX(0.0f); + } + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +bool CTaskBuild::Abort() +{ + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + + m_camera->StopCentering(m_object, 2.0f); + m_physics->SetFreeze(false); // is moving again + return true; +} + + +// Checks whether the terrain is fairly flat +// and if there is not too close to another object. + +Error CTaskBuild::FlatFloor() +{ + CObject *pObj; + ObjectType type; + Math::Vector center, pos, oPos, bPos; + Math::Point c, p; + float radius, max, oRadius, bRadius, angle, dist; + int i, j; + bool bLittleFlat, bBase; + + radius = 0.0f; + if ( m_type == OBJECT_DERRICK ) radius = 5.0f; + if ( m_type == OBJECT_FACTORY ) radius = 15.0f; + if ( m_type == OBJECT_REPAIR ) radius = 12.0f; + if ( m_type == OBJECT_STATION ) radius = 12.0f; + if ( m_type == OBJECT_CONVERT ) radius = 12.0f; + if ( m_type == OBJECT_TOWER ) radius = 7.0f; + if ( m_type == OBJECT_RESEARCH ) radius = 10.0f; + if ( m_type == OBJECT_RADAR ) radius = 5.0f; + if ( m_type == OBJECT_ENERGY ) radius = 8.0f; + if ( m_type == OBJECT_LABO ) radius = 12.0f; + if ( m_type == OBJECT_NUCLEAR ) radius = 20.0f; + if ( m_type == OBJECT_PARA ) radius = 20.0f; + if ( m_type == OBJECT_INFO ) radius = 5.0f; + if ( radius == 0.0f ) return ERR_GENERIC; + + center = m_metal->RetPosition(0); + angle = m_terrain->RetFineSlope(center); + bLittleFlat = ( angle < FLATLIMIT ); + + max = m_terrain->RetFlatZoneRadius(center, radius); + if ( max < radius ) // area too small? + { + if ( bLittleFlat ) + { + m_main->SetShowLimit(1, PARTILIMIT3, m_metal, center, max, 10.0f); + } + return bLittleFlat?ERR_BUILD_FLATLIT:ERR_BUILD_FLAT; + } + + max = 100000.0f; + bBase = false; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetActif() ) continue; // inactive? + if ( pObj->RetTruck() != 0 ) continue; // object transported? + if ( pObj == m_metal ) continue; + if ( pObj == m_object ) continue; + + type = pObj->RetType(); + if ( type == OBJECT_BASE ) + { + oPos = pObj->RetPosition(0); + dist = Math::Distance(center, oPos)-80.0f; + if ( dist < max ) + { + max = dist; + bPos = oPos; + bRadius = oRadius; + bBase = true; + } + } + else + { + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) + { + dist = Math::Distance(center, oPos)-oRadius; + if ( dist < max ) + { + max = dist; + bPos = oPos; + bRadius = oRadius; + bBase = false; + } + } + } + } + if ( max < radius ) + { + m_main->SetShowLimit(1, PARTILIMIT2, m_metal, center, max, 10.0f); + if ( bRadius < 2.0f ) bRadius = 2.0f; + m_main->SetShowLimit(2, PARTILIMIT3, m_metal, bPos, bRadius, 10.0f); + return bBase?ERR_BUILD_BASE:ERR_BUILD_BUSY; + } + + max = 100000.0f; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetActif() ) continue; // inactive? + if ( pObj->RetTruck() != 0 ) continue; // object transported? + if ( pObj == m_metal ) continue; + if ( pObj == m_object ) continue; + + type = pObj->RetType(); + if ( type == OBJECT_DERRICK || + type == OBJECT_FACTORY || + type == OBJECT_STATION || + type == OBJECT_CONVERT || + type == OBJECT_REPAIR || + type == OBJECT_TOWER || + type == OBJECT_RESEARCH || + type == OBJECT_RADAR || + type == OBJECT_ENERGY || + type == OBJECT_LABO || + type == OBJECT_NUCLEAR || + type == OBJECT_START || + type == OBJECT_END || + type == OBJECT_INFO || + type == OBJECT_PARA || + type == OBJECT_SAFE || + type == OBJECT_HUSTON ) // building? + { + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) + { + dist = Math::Distance(center, oPos)-oRadius; + if ( dist < max ) + { + max = dist; + bPos = oPos; + bRadius = oRadius; + } + } + } + } + if ( max-BUILDMARGIN < radius ) + { + m_main->SetShowLimit(1, PARTILIMIT2, m_metal, center, max-BUILDMARGIN, 10.0f); + m_main->SetShowLimit(2, PARTILIMIT3, m_metal, bPos, bRadius+BUILDMARGIN, 10.0f); + return bBase?ERR_BUILD_BASE:ERR_BUILD_NARROW; + } + + return ERR_OK; +} + +// Seeks the nearest metal object. + +CObject* CTaskBuild::SearchMetalObject(float &angle, float dMin, float dMax, + float aLimit, Error &err) +{ + CObject *pObj, *pBest; + Math::Vector iPos, oPos; + ObjectType type; + float min, iAngle, a, aa, aBest, distance, magic; + int i; + bool bMetal; + + iPos = m_object->RetPosition(0); + iAngle = m_object->RetAngleY(0); + iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI + + min = 1000000.0f; + pBest = 0; + bMetal = false; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetActif() ) continue; // objet inactive? + if ( pObj->RetTruck() != 0 ) continue; // object transported? + + type = pObj->RetType(); + if ( type != OBJECT_METAL ) continue; + + bMetal = true; // metal exists + + oPos = pObj->RetPosition(0); + distance = Math::Distance(oPos, iPos); + a = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW! + + if ( distance > dMax ) continue; + if ( !Math::TestAngle(a, iAngle-aLimit, iAngle+aLimit) ) continue; + + if ( distance < dMin ) + { + err = ERR_BUILD_METALNEAR; // too close + return pObj; + } + + aa = fabs(a-iAngle); + if ( aa > Math::PI ) aa = Math::PI*2.0f-aa; + magic = distance*aa; + + if ( magic < min ) + { + min = magic; + aBest = a; + pBest = pObj; + } + } + + if ( pBest == 0 ) + { + if ( bMetal ) err = ERR_BUILD_METALAWAY; // too far + else err = ERR_BUILD_METALINEX; // non-existent + } + else + { + angle = aBest; + err = ERR_OK; + } + return pBest; +} + +// Destroys all the close marks. + +void CTaskBuild::DeleteMark(Math::Vector pos, float radius) +{ + CObject* pObj; + Math::Vector oPos; + ObjectType type; + float distance; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type != OBJECT_MARKSTONE && + type != OBJECT_MARKURANIUM && + type != OBJECT_MARKKEYa && + type != OBJECT_MARKKEYb && + type != OBJECT_MARKKEYc && + type != OBJECT_MARKKEYd && + type != OBJECT_MARKPOWER ) continue; + + oPos = pObj->RetPosition(0); + distance = Math::Distance(oPos, pos); + if ( distance <= radius ) + { + pObj->DeleteObject(); // removes the mark + delete pObj; + i --; + } + } +} + diff --git a/src/object/task/taskbuild.h b/src/object/task/taskbuild.h index 0ca7b9b..682086d 100644 --- a/src/object/task/taskbuild.h +++ b/src/object/task/taskbuild.h @@ -1,85 +1,85 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskbuild.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-#include "math/vector.h"
-
-
-
-const float BUILDMARGIN = 16.0f;
-const int TBMAXLIGHT = 4;
-
-
-enum TaskBuildPhase
-{
- TBP_TURN = 1, // turns
- TBP_MOVE = 2, // forward/backward
- TBP_TAKE = 3, // takes gun
- TBP_PREP = 4, // prepares
- TBP_BUILD = 5, // builds
- TBP_TERM = 6, // ends
- TBP_RECEDE = 7, // back terminal
-};
-
-
-
-class CTaskBuild : public CTask
-{
-public:
- CTaskBuild(CInstanceManager* iMan, CObject* object);
- ~CTaskBuild();
-
- bool EventProcess(const Event &event);
-
- Error Start(ObjectType type);
- Error IsEnded();
- bool Abort();
-
-protected:
- Error FlatFloor();
- bool CreateBuilding(Math::Vector pos, float angle);
- void CreateLight();
- void BlackLight();
- CObject* SearchMetalObject(float &angle, float dMin, float dMax, float aLimit, Error &err);
- void DeleteMark(Math::Vector pos, float radius);
-
-protected:
- ObjectType m_type; // type of construction
- CObject* m_metal; // transforms metal object
- CObject* m_power; // the vehicle battery
- CObject* m_building; // building built
- TaskBuildPhase m_phase; // phase of the operation
- bool m_bError; // true -> operation impossible
- bool m_bBuild; // true -> building built
- bool m_bBlack; // true -> lights black -> white
- float m_time; // absolute time
- float m_lastParticule; // time of generation last particle
- float m_progress; // progression (0..1)
- float m_speed; // speed of progression
- float m_angleY; // rotation angle of the vehicle
- float m_angleZ; // angle of rotation of the gun
- Math::Vector m_buildingPos; // initial position of the building
- float m_buildingHeight; // height of the building
- int m_lightRank[TBMAXLIGHT];// lights for the effects
- int m_soundChannel;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskbuild.h + +#pragma once + + +#include "object/task/task.h" +#include "object/object.h" +#include "math/vector.h" + + + +const float BUILDMARGIN = 16.0f; +const int TBMAXLIGHT = 4; + + +enum TaskBuildPhase +{ + TBP_TURN = 1, // turns + TBP_MOVE = 2, // forward/backward + TBP_TAKE = 3, // takes gun + TBP_PREP = 4, // prepares + TBP_BUILD = 5, // builds + TBP_TERM = 6, // ends + TBP_RECEDE = 7, // back terminal +}; + + + +class CTaskBuild : public CTask +{ +public: + CTaskBuild(CInstanceManager* iMan, CObject* object); + ~CTaskBuild(); + + bool EventProcess(const Event &event); + + Error Start(ObjectType type); + Error IsEnded(); + bool Abort(); + +protected: + Error FlatFloor(); + bool CreateBuilding(Math::Vector pos, float angle); + void CreateLight(); + void BlackLight(); + CObject* SearchMetalObject(float &angle, float dMin, float dMax, float aLimit, Error &err); + void DeleteMark(Math::Vector pos, float radius); + +protected: + ObjectType m_type; // type of construction + CObject* m_metal; // transforms metal object + CObject* m_power; // the vehicle battery + CObject* m_building; // building built + TaskBuildPhase m_phase; // phase of the operation + bool m_bError; // true -> operation impossible + bool m_bBuild; // true -> building built + bool m_bBlack; // true -> lights black -> white + float m_time; // absolute time + float m_lastParticule; // time of generation last particle + float m_progress; // progression (0..1) + float m_speed; // speed of progression + float m_angleY; // rotation angle of the vehicle + float m_angleZ; // angle of rotation of the gun + Math::Vector m_buildingPos; // initial position of the building + float m_buildingHeight; // height of the building + int m_lightRank[TBMAXLIGHT];// lights for the effects + int m_soundChannel; +}; + diff --git a/src/object/task/taskfire.cpp b/src/object/task/taskfire.cpp index 4bab31e..8d300e6 100644 --- a/src/object/task/taskfire.cpp +++ b/src/object/task/taskfire.cpp @@ -1,384 +1,384 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskfire.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskfire.h"
-
-#include "old/particule.h"
-#include "math/geometry.h"
-#include "physics/physics.h"
-
-
-
-const float ENERGY_FIRE = (0.25f/2.5f); // energy consumed/shot
-const float ENERGY_FIREr = (0.25f/1.5f); // energy consumed/ray
-const float ENERGY_FIREi = (0.10f/2.5f); // energy consumed/organic
-
-
-// Object's constructor.
-
-CTaskFire::CTaskFire(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_soundChannel = -1;
-}
-
-// Object's destructor.
-
-CTaskFire::~CTaskFire()
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-}
-
-
-// Management of an event.
-
-bool CTaskFire::EventProcess(const Event &event)
-{
- CObject* power;
- CPhysics* physics;
- Math::Matrix* mat;
- Math::Vector pos, speed, dir, vib;
- ObjectType type;
- Math::Point dim;
- float energy, fire;
- int i, channel;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_time += event.rTime;
- m_lastSound -= event.rTime;
- m_progress += event.rTime*m_speed;
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- if ( m_bOrganic ) fire = ENERGY_FIREi;
- else if ( m_bRay ) fire = ENERGY_FIREr;
- else fire = ENERGY_FIRE;
- energy -= event.rTime*fire/power->RetCapacity();
- power->SetEnergy(energy);
- }
-
- if ( m_lastParticule+0.05f <= m_time )
- {
- m_lastParticule = m_time;
-
- if ( m_bOrganic )
- {
- mat = m_object->RetWorldMatrix(1); // insect-cannon
-
- for ( i=0 ; i<6 ; i++ )
- {
- pos = Math::Vector(0.0f, 2.5f, 0.0f);
- pos = Math::Transform(*mat, pos);
-
- speed = Math::Vector(200.0f, 0.0f, 0.0f);
-
- physics = m_object->RetPhysics();
- if ( physics != 0 )
- {
- speed += physics->RetLinMotion(MO_REASPEED);
- }
-
- speed.x += (Math::Rand()-0.5f)*10.0f;
- speed.y += (Math::Rand()-0.5f)*20.0f;
- speed.z += (Math::Rand()-0.5f)*30.0f;
- speed = Math::Transform(*mat, speed);
- speed -= pos;
-
- dim.x = Math::Rand()*0.5f+0.5f;
- dim.y = dim.x;
-
- channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN4, 0.8f, 0.0f, 0.0f);
- m_particule->SetObjectFather(channel, m_object);
- }
- }
- else if ( m_bRay )
- {
- mat = m_object->RetWorldMatrix(2); // cannon
-
- for ( i=0 ; i<4 ; i++ )
- {
- pos = Math::Vector(4.0f, 0.0f, 0.0f);
- pos.y += (rand()%3-1)*1.5f;
- pos.z += (rand()%3-1)*1.5f;
- pos = Math::Transform(*mat, pos);
-
- speed = Math::Vector(200.0f, 0.0f, 0.0f);
- speed.x += (Math::Rand()-0.5f)*6.0f;
- speed.y += (Math::Rand()-0.5f)*12.0f;
- speed.z += (Math::Rand()-0.5f)*12.0f;
- speed = Math::Transform(*mat, speed);
- speed -= pos;
-
- dim.x = 1.0f;
- dim.y = dim.x;
- channel = m_particule->CreateTrack(pos, speed, dim, PARTITRACK11,
- 2.0f, 200.0f, 0.5f, 1.0f);
- m_particule->SetObjectFather(channel, m_object);
-
- speed = Math::Vector(5.0f, 0.0f, 0.0f);
- speed.x += (Math::Rand()-0.5f)*1.0f;
- speed.y += (Math::Rand()-0.5f)*2.0f;
- speed.z += (Math::Rand()-0.5f)*2.0f;
- speed = Math::Transform(*mat, speed);
- speed -= pos;
- speed.y += 5.0f;
-
- dim.x = 2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE2, 2.0f, 0.0f, 0.5f);
- }
- }
- else
- {
- type = m_object->RetType();
-
- if ( type == OBJECT_MOBILErc )
- {
- mat = m_object->RetWorldMatrix(2); // cannon
- }
- else
- {
- mat = m_object->RetWorldMatrix(1); // cannon
- }
-
- for ( i=0 ; i<3 ; i++ )
- {
- if ( type == OBJECT_MOBILErc )
- {
- pos = Math::Vector(0.0f, 0.0f, 0.0f);
- }
- else
- {
- pos = Math::Vector(3.0f, 1.0f, 0.0f);
- }
- pos.y += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- pos = Math::Transform(*mat, pos);
-
- speed = Math::Vector(200.0f, 0.0f, 0.0f);
-
- physics = m_object->RetPhysics();
- if ( physics != 0 )
- {
- speed += physics->RetLinMotion(MO_REASPEED);
- }
-
- speed.x += (Math::Rand()-0.5f)*3.0f;
- speed.y += (Math::Rand()-0.5f)*6.0f;
- speed.z += (Math::Rand()-0.5f)*6.0f;
- speed = Math::Transform(*mat, speed);
- speed -= pos;
-
- dim.x = Math::Rand()*0.7f+0.7f;
- dim.y = dim.x;
-
- channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN1, 0.8f, 0.0f, 0.0f);
- m_particule->SetObjectFather(channel, m_object);
- }
-
- if ( type != OBJECT_MOBILErc &&
- m_progress > 0.3f )
- {
- pos = Math::Vector(-1.0f, 1.0f, 0.0f);
- pos.y += (Math::Rand()-0.5f)*0.4f;
- pos.z += (Math::Rand()-0.5f)*0.4f;
- pos = Math::Transform(*mat, pos);
-
- speed = Math::Vector(-4.0f, 0.0f, 0.0f);
- speed.x += (Math::Rand()-0.5f)*2.0f;
- speed.y += (Math::Rand()-0.2f)*4.0f;
- speed.z += (Math::Rand()-0.5f)*4.0f;
- speed = Math::Transform(*mat, speed);
- speed -= pos;
-
- dim.x = Math::Rand()*1.2f+1.2f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f);
-//? m_particule->CreateParticule(pos, speed, dim, PARTISMOKE2, 4.0f, 0.0f, 0.0f);
- }
- }
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- if ( m_progress < 0.1f )
- {
- dir.z = (Math::PI*0.04f)*(m_progress*10.0f);
- }
- else if ( m_progress < 0.9f )
- {
- dir.z = (Math::PI*0.04f);
- }
- else
- {
- dir.z = (Math::PI*0.04f)*(1.0f-(m_progress-0.9f)*10.0f);
- }
- m_object->SetInclinaison(dir);
-
- vib.x = (Math::Rand()-0.5f)*0.01f;
- vib.y = (Math::Rand()-0.5f)*0.02f;
- vib.z = (Math::Rand()-0.5f)*0.02f;
- m_object->SetCirVibration(vib);
-
- vib.x = (Math::Rand()-0.5f)*0.20f;
- vib.y = (Math::Rand()-0.5f)*0.05f;
- vib.z = (Math::Rand()-0.5f)*0.20f;
- m_object->SetLinVibration(vib);
- }
-
- if ( m_bRay && m_lastSound <= 0.0f )
- {
- m_lastSound = Math::Rand()*0.4f+0.4f;
- m_sound->Play(SOUND_FIREp, m_object->RetPosition(0));
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskFire::Start(float delay)
-{
- CObject* power;
- Math::Vector pos, goal, speed;
- float energy, fire;
- ObjectType type;
-
- m_bError = true; // operation impossible
-
- type = m_object->RetType();
- if ( type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILErc ) return ERR_FIRE_VEH;
-
-//? if ( !m_physics->RetLand() ) return ERR_FIRE_FLY;
-
- speed = m_physics->RetMotorSpeed();
-//? if ( speed.x != 0.0f ||
-//? speed.z != 0.0f ) return ERR_FIRE_MOTOR;
-
- m_bRay = (type == OBJECT_MOBILErc);
-
- m_bOrganic = false;
- if ( type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii )
- {
- m_bOrganic = true;
- }
-
- if ( delay == 0.0f )
- {
- if ( m_bRay ) delay = 1.2f;
- else delay = 2.0f;
- }
- m_delay = delay;
-
- power = m_object->RetPower();
- if ( power == 0 ) return ERR_FIRE_ENERGY;
- energy = power->RetEnergy();
- if ( m_bOrganic ) fire = m_delay*ENERGY_FIREi;
- else if ( m_bRay ) fire = m_delay*ENERGY_FIREr;
- else fire = m_delay*ENERGY_FIRE;
- if ( energy < fire/power->RetCapacity()+0.05f ) return ERR_FIRE_ENERGY;
-
- m_speed = 1.0f/m_delay;
- m_progress = 0.0f;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- m_lastSound = 0.0f;
- m_bError = false; // ok
-
-//? m_camera->StartCentering(m_object, Math::PI*0.15f, 99.9f, 0.0f, 1.0f);
-
- if ( m_bOrganic )
- {
- m_soundChannel = m_sound->Play(SOUND_FIREi, m_object->RetPosition(0), 1.0f, 1.0f, true);
- if ( m_soundChannel != -1 )
- {
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, m_delay, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.5f, SOPER_STOP);
- }
- }
- else if ( m_bRay )
- {
- }
- else
- {
- m_soundChannel = m_sound->Play(SOUND_FIRE, m_object->RetPosition(0), 1.0f, 1.0f, true);
- if ( m_soundChannel != -1 )
- {
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, m_delay, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.5f, SOPER_STOP);
- }
- }
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskFire::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskFire::Abort()
-{
- m_object->SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetLinVibration(Math::Vector(0.0f, 0.0f, 0.0f));
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
-//? m_camera->StopCentering(m_object, 1.0f);
- return true;
-}
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskfire.cpp + + +#include <stdio.h> + +#include "object/task/taskfire.h" + +#include "old/particule.h" +#include "math/geometry.h" +#include "physics/physics.h" + + + +const float ENERGY_FIRE = (0.25f/2.5f); // energy consumed/shot +const float ENERGY_FIREr = (0.25f/1.5f); // energy consumed/ray +const float ENERGY_FIREi = (0.10f/2.5f); // energy consumed/organic + + +// Object's constructor. + +CTaskFire::CTaskFire(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + m_soundChannel = -1; +} + +// Object's destructor. + +CTaskFire::~CTaskFire() +{ + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } +} + + +// Management of an event. + +bool CTaskFire::EventProcess(const Event &event) +{ + CObject* power; + CPhysics* physics; + Math::Matrix* mat; + Math::Vector pos, speed, dir, vib; + ObjectType type; + Math::Point dim; + float energy, fire; + int i, channel; + + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + if ( m_bError ) return false; + + m_time += event.rTime; + m_lastSound -= event.rTime; + m_progress += event.rTime*m_speed; + + power = m_object->RetPower(); + if ( power != 0 ) + { + energy = power->RetEnergy(); + if ( m_bOrganic ) fire = ENERGY_FIREi; + else if ( m_bRay ) fire = ENERGY_FIREr; + else fire = ENERGY_FIRE; + energy -= event.rTime*fire/power->RetCapacity(); + power->SetEnergy(energy); + } + + if ( m_lastParticule+0.05f <= m_time ) + { + m_lastParticule = m_time; + + if ( m_bOrganic ) + { + mat = m_object->RetWorldMatrix(1); // insect-cannon + + for ( i=0 ; i<6 ; i++ ) + { + pos = Math::Vector(0.0f, 2.5f, 0.0f); + pos = Math::Transform(*mat, pos); + + speed = Math::Vector(200.0f, 0.0f, 0.0f); + + physics = m_object->RetPhysics(); + if ( physics != 0 ) + { + speed += physics->RetLinMotion(MO_REASPEED); + } + + speed.x += (Math::Rand()-0.5f)*10.0f; + speed.y += (Math::Rand()-0.5f)*20.0f; + speed.z += (Math::Rand()-0.5f)*30.0f; + speed = Math::Transform(*mat, speed); + speed -= pos; + + dim.x = Math::Rand()*0.5f+0.5f; + dim.y = dim.x; + + channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN4, 0.8f, 0.0f, 0.0f); + m_particule->SetObjectFather(channel, m_object); + } + } + else if ( m_bRay ) + { + mat = m_object->RetWorldMatrix(2); // cannon + + for ( i=0 ; i<4 ; i++ ) + { + pos = Math::Vector(4.0f, 0.0f, 0.0f); + pos.y += (rand()%3-1)*1.5f; + pos.z += (rand()%3-1)*1.5f; + pos = Math::Transform(*mat, pos); + + speed = Math::Vector(200.0f, 0.0f, 0.0f); + speed.x += (Math::Rand()-0.5f)*6.0f; + speed.y += (Math::Rand()-0.5f)*12.0f; + speed.z += (Math::Rand()-0.5f)*12.0f; + speed = Math::Transform(*mat, speed); + speed -= pos; + + dim.x = 1.0f; + dim.y = dim.x; + channel = m_particule->CreateTrack(pos, speed, dim, PARTITRACK11, + 2.0f, 200.0f, 0.5f, 1.0f); + m_particule->SetObjectFather(channel, m_object); + + speed = Math::Vector(5.0f, 0.0f, 0.0f); + speed.x += (Math::Rand()-0.5f)*1.0f; + speed.y += (Math::Rand()-0.5f)*2.0f; + speed.z += (Math::Rand()-0.5f)*2.0f; + speed = Math::Transform(*mat, speed); + speed -= pos; + speed.y += 5.0f; + + dim.x = 2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE2, 2.0f, 0.0f, 0.5f); + } + } + else + { + type = m_object->RetType(); + + if ( type == OBJECT_MOBILErc ) + { + mat = m_object->RetWorldMatrix(2); // cannon + } + else + { + mat = m_object->RetWorldMatrix(1); // cannon + } + + for ( i=0 ; i<3 ; i++ ) + { + if ( type == OBJECT_MOBILErc ) + { + pos = Math::Vector(0.0f, 0.0f, 0.0f); + } + else + { + pos = Math::Vector(3.0f, 1.0f, 0.0f); + } + pos.y += (Math::Rand()-0.5f)*1.0f; + pos.z += (Math::Rand()-0.5f)*1.0f; + pos = Math::Transform(*mat, pos); + + speed = Math::Vector(200.0f, 0.0f, 0.0f); + + physics = m_object->RetPhysics(); + if ( physics != 0 ) + { + speed += physics->RetLinMotion(MO_REASPEED); + } + + speed.x += (Math::Rand()-0.5f)*3.0f; + speed.y += (Math::Rand()-0.5f)*6.0f; + speed.z += (Math::Rand()-0.5f)*6.0f; + speed = Math::Transform(*mat, speed); + speed -= pos; + + dim.x = Math::Rand()*0.7f+0.7f; + dim.y = dim.x; + + channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN1, 0.8f, 0.0f, 0.0f); + m_particule->SetObjectFather(channel, m_object); + } + + if ( type != OBJECT_MOBILErc && + m_progress > 0.3f ) + { + pos = Math::Vector(-1.0f, 1.0f, 0.0f); + pos.y += (Math::Rand()-0.5f)*0.4f; + pos.z += (Math::Rand()-0.5f)*0.4f; + pos = Math::Transform(*mat, pos); + + speed = Math::Vector(-4.0f, 0.0f, 0.0f); + speed.x += (Math::Rand()-0.5f)*2.0f; + speed.y += (Math::Rand()-0.2f)*4.0f; + speed.z += (Math::Rand()-0.5f)*4.0f; + speed = Math::Transform(*mat, speed); + speed -= pos; + + dim.x = Math::Rand()*1.2f+1.2f; + dim.y = dim.x; + + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f); +//? m_particule->CreateParticule(pos, speed, dim, PARTISMOKE2, 4.0f, 0.0f, 0.0f); + } + } + + dir = Math::Vector(0.0f, 0.0f, 0.0f); + if ( m_progress < 0.1f ) + { + dir.z = (Math::PI*0.04f)*(m_progress*10.0f); + } + else if ( m_progress < 0.9f ) + { + dir.z = (Math::PI*0.04f); + } + else + { + dir.z = (Math::PI*0.04f)*(1.0f-(m_progress-0.9f)*10.0f); + } + m_object->SetInclinaison(dir); + + vib.x = (Math::Rand()-0.5f)*0.01f; + vib.y = (Math::Rand()-0.5f)*0.02f; + vib.z = (Math::Rand()-0.5f)*0.02f; + m_object->SetCirVibration(vib); + + vib.x = (Math::Rand()-0.5f)*0.20f; + vib.y = (Math::Rand()-0.5f)*0.05f; + vib.z = (Math::Rand()-0.5f)*0.20f; + m_object->SetLinVibration(vib); + } + + if ( m_bRay && m_lastSound <= 0.0f ) + { + m_lastSound = Math::Rand()*0.4f+0.4f; + m_sound->Play(SOUND_FIREp, m_object->RetPosition(0)); + } + + return true; +} + + +// Assigns the goal was achieved. + +Error CTaskFire::Start(float delay) +{ + CObject* power; + Math::Vector pos, goal, speed; + float energy, fire; + ObjectType type; + + m_bError = true; // operation impossible + + type = m_object->RetType(); + if ( type != OBJECT_MOBILEfc && + type != OBJECT_MOBILEtc && + type != OBJECT_MOBILEwc && + type != OBJECT_MOBILEic && + type != OBJECT_MOBILEfi && + type != OBJECT_MOBILEti && + type != OBJECT_MOBILEwi && + type != OBJECT_MOBILEii && + type != OBJECT_MOBILErc ) return ERR_FIRE_VEH; + +//? if ( !m_physics->RetLand() ) return ERR_FIRE_FLY; + + speed = m_physics->RetMotorSpeed(); +//? if ( speed.x != 0.0f || +//? speed.z != 0.0f ) return ERR_FIRE_MOTOR; + + m_bRay = (type == OBJECT_MOBILErc); + + m_bOrganic = false; + if ( type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEii ) + { + m_bOrganic = true; + } + + if ( delay == 0.0f ) + { + if ( m_bRay ) delay = 1.2f; + else delay = 2.0f; + } + m_delay = delay; + + power = m_object->RetPower(); + if ( power == 0 ) return ERR_FIRE_ENERGY; + energy = power->RetEnergy(); + if ( m_bOrganic ) fire = m_delay*ENERGY_FIREi; + else if ( m_bRay ) fire = m_delay*ENERGY_FIREr; + else fire = m_delay*ENERGY_FIRE; + if ( energy < fire/power->RetCapacity()+0.05f ) return ERR_FIRE_ENERGY; + + m_speed = 1.0f/m_delay; + m_progress = 0.0f; + m_time = 0.0f; + m_lastParticule = 0.0f; + m_lastSound = 0.0f; + m_bError = false; // ok + +//? m_camera->StartCentering(m_object, Math::PI*0.15f, 99.9f, 0.0f, 1.0f); + + if ( m_bOrganic ) + { + m_soundChannel = m_sound->Play(SOUND_FIREi, m_object->RetPosition(0), 1.0f, 1.0f, true); + if ( m_soundChannel != -1 ) + { + m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, m_delay, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.5f, SOPER_STOP); + } + } + else if ( m_bRay ) + { + } + else + { + m_soundChannel = m_sound->Play(SOUND_FIRE, m_object->RetPosition(0), 1.0f, 1.0f, true); + if ( m_soundChannel != -1 ) + { + m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, m_delay, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.5f, SOPER_STOP); + } + } + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskFire::IsEnded() +{ + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +bool CTaskFire::Abort() +{ + m_object->SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f)); + m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f)); + m_object->SetLinVibration(Math::Vector(0.0f, 0.0f, 0.0f)); + + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + +//? m_camera->StopCentering(m_object, 1.0f); + return true; +} + diff --git a/src/object/task/taskfire.h b/src/object/task/taskfire.h index 43f654e..f06b9f6 100644 --- a/src/object/task/taskfire.h +++ b/src/object/task/taskfire.h @@ -1,52 +1,52 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskfire.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskFire : public CTask
-{
-public:
- CTaskFire(CInstanceManager* iMan, CObject* object);
- ~CTaskFire();
-
- bool EventProcess(const Event &event);
-
- Error Start(float delay);
- Error IsEnded();
- bool Abort();
-
-protected:
-
-protected:
- float m_delay;
- float m_progress;
- bool m_bError;
- bool m_bRay;
- bool m_bOrganic;
- float m_time;
- float m_speed;
- float m_lastParticule;
- float m_lastSound;
- int m_soundChannel;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskfire.h + +#pragma once + + +#include "object/task/task.h" + + + +class CTaskFire : public CTask +{ +public: + CTaskFire(CInstanceManager* iMan, CObject* object); + ~CTaskFire(); + + bool EventProcess(const Event &event); + + Error Start(float delay); + Error IsEnded(); + bool Abort(); + +protected: + +protected: + float m_delay; + float m_progress; + bool m_bError; + bool m_bRay; + bool m_bOrganic; + float m_time; + float m_speed; + float m_lastParticule; + float m_lastSound; + int m_soundChannel; +}; + diff --git a/src/object/task/taskfireant.cpp b/src/object/task/taskfireant.cpp index d4a8a61..8eb2217 100644 --- a/src/object/task/taskfireant.cpp +++ b/src/object/task/taskfireant.cpp @@ -1,212 +1,212 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskfireant.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskfireant.h"
-
-#include "old/particule.h"
-#include "math/geometry.h"
-#include "object/motion/motionant.h"
-#include "physics/physics.h"
-
-
-
-
-// Object's constructor.
-
-CTaskFireAnt::CTaskFireAnt(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_phase = TFA_NULL;
-}
-
-// Object's destructor.
-
-CTaskFireAnt::~CTaskFireAnt()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskFireAnt::EventProcess(const Event &event)
-{
- Math::Vector dir, vib;
- float a, g, cirSpeed;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- if ( m_object->RetFixed() ) // insect on its back?
- {
- m_bError = true;
- return false;
- }
-
- m_time += event.rTime;
- m_progress += event.rTime*m_speed;
-
- if ( m_phase == TFA_TURN ) // preliminary rotation?
- {
- a = m_object->RetAngleY(0);
- g = m_angle;
- cirSpeed = Math::Direction(a, g)*2.0f;
- if ( cirSpeed > 2.0f ) cirSpeed = 2.0f;
- if ( cirSpeed < -2.0f ) cirSpeed = -2.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left/right
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskFireAnt::Start(Math::Vector impact)
-{
- Math::Vector pos;
- ObjectType type;
-
- m_impact = impact;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() ) return ERR_FIRE_VEH;
-
- type = m_object->RetType();
- if ( type != OBJECT_ANT ) return ERR_FIRE_VEH;
-
- // Insect on its back?
- if ( m_object->RetFixed() ) return ERR_FIRE_VEH;
-
- m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));
-
- pos = m_object->RetPosition(0);
- m_angle = Math::RotateAngle(m_impact.x-pos.x, pos.z-m_impact.z); // CW !
-
- m_phase = TFA_TURN;
- m_speed = 1.0f/1.0f;
- m_progress = 0.0f;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- m_bError = false; // ok
- m_bFire = false; // once!
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskFireAnt::IsEnded()
-{
- Math::Matrix* mat;
- Math::Vector pos, speed;
- Math::Point dim;
- float angle, dist;
- int i, channel;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
- if ( m_object->RetFixed() ) return ERR_STOP; // insect on its back?
-
- if ( m_phase == TFA_TURN ) // rotation ?
- {
- angle = m_object->RetAngleY(0);
- angle = Math::NormAngle(angle); // 0..2*Math::PI
- if ( !Math::TestAngle(angle, m_angle-Math::PI*0.05f, m_angle+Math::PI*0.05f) ) return ERR_CONTINUE;
-
- m_physics->SetMotorSpeedZ(0.0f); // rotation ended
-
- m_phase = TFA_PREPARE;
-//? m_speed = 1.0f/1.5f;
- m_speed = 1.0f/0.4f;
- m_progress = 0.0f;
-//? m_motion->SetAction(MAS_PREPARE, 1.5f);
- m_motion->SetAction(MAS_PREPARE, 0.4f);
- }
-
- if ( m_phase == TFA_PREPARE ) // preparation?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_phase = TFA_FIRE;
-//? m_speed = 1.0f/2.0f;
- m_speed = 1.0f/0.5f;
- m_progress = 0.0f;
-//? m_motion->SetAction(MAS_FIRE, 2.0f);
- m_motion->SetAction(MAS_FIRE, 0.5f);
- }
-
- if ( m_phase == TFA_FIRE ) // shooting?
- {
- if ( m_progress > 0.75f && !m_bFire )
- {
- m_bFire = true; // once
-
- for ( i=0 ; i<20 ; i++ )
- {
- pos = Math::Vector(-2.5f, -0.7f, 0.0f);
- mat = m_object->RetWorldMatrix(2);
- pos = Math::Transform(*mat, pos);
- dist = Math::Distance(pos, m_impact);
- speed = m_impact-pos;
- speed.x += (Math::Rand()-0.5f)*dist*1.2f;
- speed.y += (Math::Rand()-0.5f)*dist*0.4f+50.0f;
- speed.z += (Math::Rand()-0.5f)*dist*1.2f;
- dim.x = 1.0f;
- dim.y = dim.x;
- channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN2, 2.0f, 100.0f, 0.0f);
- m_particule->SetObjectFather(channel, m_object);
- }
- }
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_phase = TFA_TERMINATE;
-//? m_speed = 1.0f/0.9f;
- m_speed = 1.0f/0.4f;
- m_progress = 0.0f;
-//? m_motion->SetAction(MAS_TERMINATE, 0.9f);
- m_motion->SetAction(MAS_TERMINATE, 0.4f);
- }
-
- if ( m_phase == TFA_TERMINATE ) // ends?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_phase = TFA_NULL;
- m_speed = 1.0f/1.0f;
- m_progress = 0.0f;
- }
-
- Abort();
- return ERR_STOP;
-}
-
-
-// Suddenly ends the current action.
-
-bool CTaskFireAnt::Abort()
-{
- m_motion->SetAction(-1);
- return true;
-}
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskfireant.cpp + + +#include <stdio.h> + +#include "object/task/taskfireant.h" + +#include "old/particule.h" +#include "math/geometry.h" +#include "object/motion/motionant.h" +#include "physics/physics.h" + + + + +// Object's constructor. + +CTaskFireAnt::CTaskFireAnt(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + m_phase = TFA_NULL; +} + +// Object's destructor. + +CTaskFireAnt::~CTaskFireAnt() +{ +} + + +// Management of an event. + +bool CTaskFireAnt::EventProcess(const Event &event) +{ + Math::Vector dir, vib; + float a, g, cirSpeed; + + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + if ( m_bError ) return false; + + if ( m_object->RetFixed() ) // insect on its back? + { + m_bError = true; + return false; + } + + m_time += event.rTime; + m_progress += event.rTime*m_speed; + + if ( m_phase == TFA_TURN ) // preliminary rotation? + { + a = m_object->RetAngleY(0); + g = m_angle; + cirSpeed = Math::Direction(a, g)*2.0f; + if ( cirSpeed > 2.0f ) cirSpeed = 2.0f; + if ( cirSpeed < -2.0f ) cirSpeed = -2.0f; + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left/right + } + + return true; +} + + +// Assigns the goal was achieved. + +Error CTaskFireAnt::Start(Math::Vector impact) +{ + Math::Vector pos; + ObjectType type; + + m_impact = impact; + + m_bError = true; // operation impossible + if ( !m_physics->RetLand() ) return ERR_FIRE_VEH; + + type = m_object->RetType(); + if ( type != OBJECT_ANT ) return ERR_FIRE_VEH; + + // Insect on its back? + if ( m_object->RetFixed() ) return ERR_FIRE_VEH; + + m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f)); + + pos = m_object->RetPosition(0); + m_angle = Math::RotateAngle(m_impact.x-pos.x, pos.z-m_impact.z); // CW ! + + m_phase = TFA_TURN; + m_speed = 1.0f/1.0f; + m_progress = 0.0f; + m_time = 0.0f; + m_lastParticule = 0.0f; + m_bError = false; // ok + m_bFire = false; // once! + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskFireAnt::IsEnded() +{ + Math::Matrix* mat; + Math::Vector pos, speed; + Math::Point dim; + float angle, dist; + int i, channel; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + if ( m_object->RetFixed() ) return ERR_STOP; // insect on its back? + + if ( m_phase == TFA_TURN ) // rotation ? + { + angle = m_object->RetAngleY(0); + angle = Math::NormAngle(angle); // 0..2*Math::PI + if ( !Math::TestAngle(angle, m_angle-Math::PI*0.05f, m_angle+Math::PI*0.05f) ) return ERR_CONTINUE; + + m_physics->SetMotorSpeedZ(0.0f); // rotation ended + + m_phase = TFA_PREPARE; +//? m_speed = 1.0f/1.5f; + m_speed = 1.0f/0.4f; + m_progress = 0.0f; +//? m_motion->SetAction(MAS_PREPARE, 1.5f); + m_motion->SetAction(MAS_PREPARE, 0.4f); + } + + if ( m_phase == TFA_PREPARE ) // preparation? + { + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + m_phase = TFA_FIRE; +//? m_speed = 1.0f/2.0f; + m_speed = 1.0f/0.5f; + m_progress = 0.0f; +//? m_motion->SetAction(MAS_FIRE, 2.0f); + m_motion->SetAction(MAS_FIRE, 0.5f); + } + + if ( m_phase == TFA_FIRE ) // shooting? + { + if ( m_progress > 0.75f && !m_bFire ) + { + m_bFire = true; // once + + for ( i=0 ; i<20 ; i++ ) + { + pos = Math::Vector(-2.5f, -0.7f, 0.0f); + mat = m_object->RetWorldMatrix(2); + pos = Math::Transform(*mat, pos); + dist = Math::Distance(pos, m_impact); + speed = m_impact-pos; + speed.x += (Math::Rand()-0.5f)*dist*1.2f; + speed.y += (Math::Rand()-0.5f)*dist*0.4f+50.0f; + speed.z += (Math::Rand()-0.5f)*dist*1.2f; + dim.x = 1.0f; + dim.y = dim.x; + channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN2, 2.0f, 100.0f, 0.0f); + m_particule->SetObjectFather(channel, m_object); + } + } + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + m_phase = TFA_TERMINATE; +//? m_speed = 1.0f/0.9f; + m_speed = 1.0f/0.4f; + m_progress = 0.0f; +//? m_motion->SetAction(MAS_TERMINATE, 0.9f); + m_motion->SetAction(MAS_TERMINATE, 0.4f); + } + + if ( m_phase == TFA_TERMINATE ) // ends? + { + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + m_phase = TFA_NULL; + m_speed = 1.0f/1.0f; + m_progress = 0.0f; + } + + Abort(); + return ERR_STOP; +} + + +// Suddenly ends the current action. + +bool CTaskFireAnt::Abort() +{ + m_motion->SetAction(-1); + return true; +} + diff --git a/src/object/task/taskfireant.h b/src/object/task/taskfireant.h index 5b45775..1d8ef62 100644 --- a/src/object/task/taskfireant.h +++ b/src/object/task/taskfireant.h @@ -1,63 +1,63 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskfireant.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-enum TaskFireAnt
-{
- TFA_NULL = 0, // nothing to do
- TFA_TURN = 1, // turns
- TFA_PREPARE = 2, // prepares shooting position
- TFA_FIRE = 3, // shooting
- TFA_TERMINATE = 4, // ends shooting position
-};
-
-
-
-class CTaskFireAnt : public CTask
-{
-public:
- CTaskFireAnt(CInstanceManager* iMan, CObject* object);
- ~CTaskFireAnt();
-
- bool EventProcess(const Event &event);
-
- Error Start(Math::Vector impact);
- Error IsEnded();
- bool Abort();
-
-protected:
-
-protected:
- Math::Vector m_impact;
- TaskFireAnt m_phase;
- float m_progress;
- float m_speed;
- float m_angle;
- bool m_bError;
- bool m_bFire;
- float m_time;
- float m_lastParticule;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskfireant.h + +#pragma once + + +#include "object/task/task.h" +#include "math/vector.h" + + + +enum TaskFireAnt +{ + TFA_NULL = 0, // nothing to do + TFA_TURN = 1, // turns + TFA_PREPARE = 2, // prepares shooting position + TFA_FIRE = 3, // shooting + TFA_TERMINATE = 4, // ends shooting position +}; + + + +class CTaskFireAnt : public CTask +{ +public: + CTaskFireAnt(CInstanceManager* iMan, CObject* object); + ~CTaskFireAnt(); + + bool EventProcess(const Event &event); + + Error Start(Math::Vector impact); + Error IsEnded(); + bool Abort(); + +protected: + +protected: + Math::Vector m_impact; + TaskFireAnt m_phase; + float m_progress; + float m_speed; + float m_angle; + bool m_bError; + bool m_bFire; + float m_time; + float m_lastParticule; +}; + diff --git a/src/object/task/taskflag.cpp b/src/object/task/taskflag.cpp index f76fef6..7fba689 100644 --- a/src/object/task/taskflag.cpp +++ b/src/object/task/taskflag.cpp @@ -1,305 +1,305 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskflag.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskflag.h"
-
-#include "math/geometry.h"
-#include "common/iman.h"
-#include "old/water.h"
-#include "old/pyro.h"
-#include "physics/physics.h"
-#include "object/motion/motionhuman.h"
-
-
-
-
-
-// Object's constructor.
-
-CTaskFlag::CTaskFlag(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskFlag::~CTaskFlag()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskFlag::EventProcess(const Event &event)
-{
- if ( m_bError ) return true;
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_time += event.rTime;
-
- return true;
-}
-
-
-
-// Assigns the goal was achieved.
-
-Error CTaskFlag::Start(TaskFlagOrder order, int rank)
-{
- Math::Vector pos, speed;
- Error err;
-
- m_order = order;
- m_time = 0.0f;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() )
- {
- pos = m_object->RetPosition(0);
- if ( pos.y < m_water->RetLevel() ) return ERR_FLAG_WATER;
- return ERR_FLAG_FLY;
- }
-
- speed = m_physics->RetMotorSpeed();
- if ( speed.x != 0.0f ||
- speed.z != 0.0f ) return ERR_FLAG_MOTOR;
-
- if ( m_object->RetFret() != 0 ) return ERR_FLAG_BUSY;
-
- if ( order == TFL_CREATE )
- {
- err = CreateFlag(rank);
- if ( err != ERR_OK ) return err;
- }
-
- if ( order == TFL_DELETE )
- {
- err = DeleteFlag();
- if ( err != ERR_OK ) return err;
- }
-
- m_bError = false;
-
- m_motion->SetAction(MHS_FLAG); // sets/removes flag
- m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.5f);
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskFlag::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
-
- if ( m_bError ) return ERR_STOP;
- if ( m_time < 2.0f ) return ERR_CONTINUE;
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskFlag::Abort()
-{
- m_motion->SetAction(-1);
- m_camera->StopCentering(m_object, 2.0f);
- return true;
-}
-
-
-
-// Returns the closest object to a given position.
-
-CObject* CTaskFlag::SearchNearest(Math::Vector pos, ObjectType type)
-{
- ObjectType oType;
- CObject *pObj, *pBest;
- Math::Vector oPos;
- float min, dist;
- int i;
-
- min = 100000.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetEnable() ) continue;
-
- oType = pObj->RetType();
- if ( type == OBJECT_NULL )
- {
- if ( oType != OBJECT_FLAGb &&
- oType != OBJECT_FLAGr &&
- oType != OBJECT_FLAGg &&
- oType != OBJECT_FLAGy &&
- oType != OBJECT_FLAGv ) continue;
- }
- else
- {
- if ( oType != type ) continue;
- }
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, pos);
- if ( dist < min )
- {
- min = dist;
- pBest = pObj;
- }
- }
- return pBest;
-}
-
-// Counts the number of existing objects.
-
-int CTaskFlag::CountObject(ObjectType type)
-{
- ObjectType oType;
- CObject *pObj;
- Math::Vector oPos;
- int i, count;
-
- count = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetEnable() ) continue;
-
- oType = pObj->RetType();
- if ( type == OBJECT_NULL )
- {
- if ( oType != OBJECT_FLAGb &&
- oType != OBJECT_FLAGr &&
- oType != OBJECT_FLAGg &&
- oType != OBJECT_FLAGy &&
- oType != OBJECT_FLAGv ) continue;
- }
- else
- {
- if ( oType != type ) continue;
- }
-
- count ++;
- }
- return count;
-}
-
-// Creates a color indicator.
-
-Error CTaskFlag::CreateFlag(int rank)
-{
- CObject* pObj;
- CObject* pNew;
- CPyro* pyro;
- Math::Matrix* mat;
- Math::Vector pos;
- float dist;
- int i;
-
- ObjectType table[5] =
- {
- OBJECT_FLAGb,
- OBJECT_FLAGr,
- OBJECT_FLAGg,
- OBJECT_FLAGy,
- OBJECT_FLAGv,
- };
-
- mat = m_object->RetWorldMatrix(0);
- pos = Transform(*mat, Math::Vector(4.0f, 0.0f, 0.0f));
-
- pObj = SearchNearest(pos, OBJECT_NULL);
- if ( pObj != 0 )
- {
- dist = Math::Distance(pos, pObj->RetPosition(0));
- if ( dist < 10.0f )
- {
- return ERR_FLAG_PROXY;
- }
- }
-
- i = rank;
- if ( CountObject(table[i]) >= 5 )
- {
- return ERR_FLAG_CREATE;
- }
-
- pNew = new CObject(m_iMan);
- if ( !pNew->CreateFlag(pos, 0.0f, table[i]) )
- {
- delete pNew;
- return ERR_TOOMANY;
- }
- pNew->SetZoom(0, 0.0f);
-
- m_sound->Play(SOUND_WAYPOINT, pos);
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FLCREATE, pNew);
-
- return ERR_OK;
-}
-
-// Deletes a color indicator.
-
-Error CTaskFlag::DeleteFlag()
-{
- CObject* pObj;
- CPyro* pyro;
- Math::Vector iPos, oPos;
- float iAngle, angle, aLimit, dist;
-
- iPos = m_object->RetPosition(0);
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- pObj = SearchNearest(iPos, OBJECT_NULL);
- if ( pObj == 0 )
- {
- return ERR_FLAG_DELETE;
- }
- dist = Math::Distance(iPos, pObj->RetPosition(0));
- if ( dist > 10.0f )
- {
- return ERR_FLAG_DELETE;
- }
-
- oPos = pObj->RetPosition(0);
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- aLimit = 45.0f*Math::PI/180.0f;
- if ( !Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
- {
- return ERR_FLAG_DELETE;
- }
-
- m_sound->Play(SOUND_WAYPOINT, iPos);
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FLDELETE, pObj);
-
- return ERR_OK;
-}
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskflag.cpp + + +#include <stdio.h> + +#include "object/task/taskflag.h" + +#include "math/geometry.h" +#include "common/iman.h" +#include "old/water.h" +#include "old/pyro.h" +#include "physics/physics.h" +#include "object/motion/motionhuman.h" + + + + + +// Object's constructor. + +CTaskFlag::CTaskFlag(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ +} + +// Object's destructor. + +CTaskFlag::~CTaskFlag() +{ +} + + +// Management of an event. + +bool CTaskFlag::EventProcess(const Event &event) +{ + if ( m_bError ) return true; + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + + m_time += event.rTime; + + return true; +} + + + +// Assigns the goal was achieved. + +Error CTaskFlag::Start(TaskFlagOrder order, int rank) +{ + Math::Vector pos, speed; + Error err; + + m_order = order; + m_time = 0.0f; + + m_bError = true; // operation impossible + if ( !m_physics->RetLand() ) + { + pos = m_object->RetPosition(0); + if ( pos.y < m_water->RetLevel() ) return ERR_FLAG_WATER; + return ERR_FLAG_FLY; + } + + speed = m_physics->RetMotorSpeed(); + if ( speed.x != 0.0f || + speed.z != 0.0f ) return ERR_FLAG_MOTOR; + + if ( m_object->RetFret() != 0 ) return ERR_FLAG_BUSY; + + if ( order == TFL_CREATE ) + { + err = CreateFlag(rank); + if ( err != ERR_OK ) return err; + } + + if ( order == TFL_DELETE ) + { + err = DeleteFlag(); + if ( err != ERR_OK ) return err; + } + + m_bError = false; + + m_motion->SetAction(MHS_FLAG); // sets/removes flag + m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.5f); + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskFlag::IsEnded() +{ + if ( m_engine->RetPause() ) return ERR_CONTINUE; + + if ( m_bError ) return ERR_STOP; + if ( m_time < 2.0f ) return ERR_CONTINUE; + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +bool CTaskFlag::Abort() +{ + m_motion->SetAction(-1); + m_camera->StopCentering(m_object, 2.0f); + return true; +} + + + +// Returns the closest object to a given position. + +CObject* CTaskFlag::SearchNearest(Math::Vector pos, ObjectType type) +{ + ObjectType oType; + CObject *pObj, *pBest; + Math::Vector oPos; + float min, dist; + int i; + + min = 100000.0f; + pBest = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetEnable() ) continue; + + oType = pObj->RetType(); + if ( type == OBJECT_NULL ) + { + if ( oType != OBJECT_FLAGb && + oType != OBJECT_FLAGr && + oType != OBJECT_FLAGg && + oType != OBJECT_FLAGy && + oType != OBJECT_FLAGv ) continue; + } + else + { + if ( oType != type ) continue; + } + + oPos = pObj->RetPosition(0); + dist = Math::DistanceProjected(oPos, pos); + if ( dist < min ) + { + min = dist; + pBest = pObj; + } + } + return pBest; +} + +// Counts the number of existing objects. + +int CTaskFlag::CountObject(ObjectType type) +{ + ObjectType oType; + CObject *pObj; + Math::Vector oPos; + int i, count; + + count = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetEnable() ) continue; + + oType = pObj->RetType(); + if ( type == OBJECT_NULL ) + { + if ( oType != OBJECT_FLAGb && + oType != OBJECT_FLAGr && + oType != OBJECT_FLAGg && + oType != OBJECT_FLAGy && + oType != OBJECT_FLAGv ) continue; + } + else + { + if ( oType != type ) continue; + } + + count ++; + } + return count; +} + +// Creates a color indicator. + +Error CTaskFlag::CreateFlag(int rank) +{ + CObject* pObj; + CObject* pNew; + CPyro* pyro; + Math::Matrix* mat; + Math::Vector pos; + float dist; + int i; + + ObjectType table[5] = + { + OBJECT_FLAGb, + OBJECT_FLAGr, + OBJECT_FLAGg, + OBJECT_FLAGy, + OBJECT_FLAGv, + }; + + mat = m_object->RetWorldMatrix(0); + pos = Transform(*mat, Math::Vector(4.0f, 0.0f, 0.0f)); + + pObj = SearchNearest(pos, OBJECT_NULL); + if ( pObj != 0 ) + { + dist = Math::Distance(pos, pObj->RetPosition(0)); + if ( dist < 10.0f ) + { + return ERR_FLAG_PROXY; + } + } + + i = rank; + if ( CountObject(table[i]) >= 5 ) + { + return ERR_FLAG_CREATE; + } + + pNew = new CObject(m_iMan); + if ( !pNew->CreateFlag(pos, 0.0f, table[i]) ) + { + delete pNew; + return ERR_TOOMANY; + } + pNew->SetZoom(0, 0.0f); + + m_sound->Play(SOUND_WAYPOINT, pos); + pyro = new CPyro(m_iMan); + pyro->Create(PT_FLCREATE, pNew); + + return ERR_OK; +} + +// Deletes a color indicator. + +Error CTaskFlag::DeleteFlag() +{ + CObject* pObj; + CPyro* pyro; + Math::Vector iPos, oPos; + float iAngle, angle, aLimit, dist; + + iPos = m_object->RetPosition(0); + iAngle = m_object->RetAngleY(0); + iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI + + pObj = SearchNearest(iPos, OBJECT_NULL); + if ( pObj == 0 ) + { + return ERR_FLAG_DELETE; + } + dist = Math::Distance(iPos, pObj->RetPosition(0)); + if ( dist > 10.0f ) + { + return ERR_FLAG_DELETE; + } + + oPos = pObj->RetPosition(0); + angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + aLimit = 45.0f*Math::PI/180.0f; + if ( !Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) ) + { + return ERR_FLAG_DELETE; + } + + m_sound->Play(SOUND_WAYPOINT, iPos); + pyro = new CPyro(m_iMan); + pyro->Create(PT_FLDELETE, pObj); + + return ERR_OK; +} + diff --git a/src/object/task/taskflag.h b/src/object/task/taskflag.h index 4a56357..5b0a058 100644 --- a/src/object/task/taskflag.h +++ b/src/object/task/taskflag.h @@ -1,58 +1,58 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-// taskflag.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-#include "math/vector.h"
-
-
-
-enum TaskFlagOrder
-{
- TFL_CREATE = 0, // sets
- TFL_DELETE = 1, // removes
-};
-
-
-
-class CTaskFlag : public CTask
-{
-public:
- CTaskFlag(CInstanceManager* iMan, CObject* object);
- ~CTaskFlag();
-
- bool EventProcess(const Event &event);
-
- Error Start(TaskFlagOrder order, int rank);
- Error IsEnded();
- bool Abort();
-
-protected:
- Error CreateFlag(int rank);
- Error DeleteFlag();
- CObject* SearchNearest(Math::Vector pos, ObjectType type);
- int CountObject(ObjectType type);
-
-protected:
- TaskFlagOrder m_order;
- float m_time;
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. +// taskflag.h + +#pragma once + + +#include "object/task/task.h" +#include "object/object.h" +#include "math/vector.h" + + + +enum TaskFlagOrder +{ + TFL_CREATE = 0, // sets + TFL_DELETE = 1, // removes +}; + + + +class CTaskFlag : public CTask +{ +public: + CTaskFlag(CInstanceManager* iMan, CObject* object); + ~CTaskFlag(); + + bool EventProcess(const Event &event); + + Error Start(TaskFlagOrder order, int rank); + Error IsEnded(); + bool Abort(); + +protected: + Error CreateFlag(int rank); + Error DeleteFlag(); + CObject* SearchNearest(Math::Vector pos, ObjectType type); + int CountObject(ObjectType type); + +protected: + TaskFlagOrder m_order; + float m_time; + bool m_bError; +}; + diff --git a/src/object/task/taskgoto.cpp b/src/object/task/taskgoto.cpp index 5ab248c..a3b1515 100644 --- a/src/object/task/taskgoto.cpp +++ b/src/object/task/taskgoto.cpp @@ -1,2341 +1,2341 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskgoto.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskgoto.h"
-
-#include "common/event.h"
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "math/geometry.h"
-#include "physics/physics.h"
-
-
-
-const float FLY_DIST_GROUND = 80.0f; // minimum distance to remain on the ground
-const float FLY_DEF_HEIGHT = 50.0f; // default flying height
-const float BM_DIM_STEP = 5.0f;
-
-
-
-
-// Object's constructor.
-
-CTaskGoto::CTaskGoto(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_bmArray = 0;
-}
-
-// Object's destructor.
-
-CTaskGoto::~CTaskGoto()
-{
- BitmapClose();
-}
-
-
-// Management of an event.
-
-bool CTaskGoto::EventProcess(const Event &event)
-{
- Math::Vector pos, goal;
- Math::Point rot, repulse;
- float a, g, dist, linSpeed, cirSpeed, h, hh, factor, dir;
- Error ret;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- // Momentarily stationary object (ant on the back)?
- if ( m_object->RetFixed() )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- return true;
- }
-
- if ( m_error != ERR_OK ) return false;
-
- if ( m_bWorm )
- {
- WormFrame(event.rTime);
- }
-
- if ( m_phase == TGP_BEAMLEAK ) // leak?
- {
- m_leakTime += event.rTime;
-
- pos = m_object->RetPosition(0);
-
- rot.x = m_leakPos.x-pos.x;
- rot.y = m_leakPos.z-pos.z;
- dist = Math::Point(rot.x, rot.y).Length();
- rot.x /= dist;
- rot.y /= dist;
-
- a = m_object->RetAngleY(0);
- g = Math::RotateAngle(rot.x, -rot.y); // CW !
- a = Math::Direction(a, g)*1.0f;
- cirSpeed = a;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- a = Math::NormAngle(a);
- if ( a > Math::PI*0.5f && a < Math::PI*1.5f )
- {
- linSpeed = 1.0f; // obstacle behind -> advance
- cirSpeed = -cirSpeed;
- }
- else
- {
- linSpeed = -1.0f; // obstacle in front -> back
- }
-
- if ( m_bLeakRecede )
- {
- linSpeed = -1.0f;
- cirSpeed = 0.0f;
- }
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- m_physics->SetMotorSpeedX(linSpeed); // advance
- return true;
- }
-
- if ( m_phase == TGP_BEAMSEARCH ) // search path?
- {
- if ( m_bmStep == 0 )
- {
- // Frees the area around the departure.
- BitmapClearCircle(m_object->RetPosition(0), BM_DIM_STEP*1.8f);
- }
-
- pos = m_object->RetPosition(0);
-
- if ( m_bmFretObject == 0 )
- {
- goal = m_goal;
- dist = 0.0f;
- }
- else
- {
- goal = m_goalObject;
- dist = TAKE_DIST+2.0f;
- if ( m_bmFretObject->RetType() == OBJECT_BASE ) dist = 12.0f;
- }
-
- ret = BeamSearch(pos, goal, dist);
- if ( ret == ERR_OK )
- {
-#if 0
- Math::Vector min, max;
- min = pos;
- max = m_goal;
- if ( min.x > max.x ) Math::Swap(min.x, max.x);
- if ( min.z > max.z ) Math::Swap(min.z, max.z);
- min.x -= 50.0f;
- min.z -= 50.0f;
- max.x += 50.0f;
- max.z += 50.0f;
- BitmapDebug(min, max, m_object->RetPosition(0), m_goal);
-#endif
- if ( m_physics->RetLand() ) m_phase = TGP_BEAMWCOLD;
- else m_phase = TGP_BEAMGOTO;
- m_bmIndex = 0;
- m_bmWatchDogPos = m_object->RetPosition(0);
- m_bmWatchDogTime = 0.0f;
- }
- if ( ret == ERR_GOTO_IMPOSSIBLE || ret == ERR_GOTO_ITER )
- {
-#if 0
- Math::Vector min, max;
- min = pos;
- max = m_goal;
- if ( min.x > max.x ) Math::Swap(min.x, max.x);
- if ( min.z > max.z ) Math::Swap(min.z, max.z);
- min.x -= 50.0f;
- min.z -= 50.0f;
- max.x += 50.0f;
- max.z += 50.0f;
- BitmapDebug(min, max, m_object->RetPosition(0), m_goal);
-#endif
- m_error = ret;
- return false;
- }
- return true;
- }
-
- if ( m_phase == TGP_BEAMWCOLD ) // expects cooled reactor?
- {
- return true;
- }
-
- if ( m_phase == TGP_BEAMUP ) // off?
- {
- m_physics->SetMotorSpeedY(1.0f); // up
- return true;
- }
-
- if ( m_phase == TGP_BEAMGOTO ) // goto dot list? (?)
- {
- if ( m_physics->RetCollision() ) // collision?
- {
- m_physics->SetCollision(false); // there's more
- }
-
- pos = m_object->RetPosition(0);
-
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude == 0.0f )
- {
- if ( m_physics->RetLand() )
- {
- m_physics->SetMotorSpeedY(0.0f);
- }
- else
- {
- m_physics->SetMotorSpeedY(-1.0f);
- }
- }
-
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
- {
- goal = m_bmPoints[m_bmIndex];
- goal.y = pos.y;
- h = m_terrain->RetFloorHeight(goal, true, true);
- dist = Math::DistanceProjected(pos, goal);
- if ( dist != 0.0f ) // anticipates?
- {
- linSpeed = m_physics->RetLinMotionX(MO_REASPEED);
- linSpeed /= m_physics->RetLinMotionX(MO_ADVSPEED);
- goal.x = pos.x + (goal.x-pos.x)*linSpeed*20.0f/dist;
- goal.z = pos.z + (goal.z-pos.z)*linSpeed*20.0f/dist;
- }
- goal.y = pos.y;
- hh = m_terrain->RetFloorHeight(goal, true, true);
- h = Math::Min(h, hh);
- linSpeed = 0.0f;
- if ( h < m_altitude-1.0f )
- {
- linSpeed = 0.2f+((m_altitude-1.0f)-h)*0.1f; // up
- if ( linSpeed > 1.0f ) linSpeed = 1.0f;
- }
- if ( h > m_altitude+1.0f )
- {
- linSpeed = -0.2f; // down
- }
- m_physics->SetMotorSpeedY(linSpeed);
- }
-
- rot.x = m_bmPoints[m_bmIndex].x-pos.x;
- rot.y = m_bmPoints[m_bmIndex].z-pos.z;
- dist = Math::Point(rot.x, rot.y).Length();
- rot.x /= dist;
- rot.y /= dist;
-
- a = m_object->RetAngleY(0);
- g = Math::RotateAngle(rot.x, -rot.y); // CW !
- cirSpeed = Math::Direction(a, g)*2.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
- if ( dist < 4.0f ) cirSpeed *= dist/4.0f; // so close -> turns less
-
- if ( m_bmIndex == m_bmTotal ) // last point?
- {
- linSpeed = dist/(m_physics->RetLinStopLength()*1.5f);
- if ( linSpeed > 1.0f ) linSpeed = 1.0f;
- }
- else
- {
- linSpeed = 1.0f; // dark without stopping
- }
-
- linSpeed *= 1.0f-(1.0f-0.3f)*fabs(cirSpeed);
-
-//? if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f )
- if ( fabs(cirSpeed) >= 0.2f )
- {
- linSpeed = 0.0f; // turns first, then advance
- }
-
- dist = Math::DistanceProjected(pos, m_bmWatchDogPos);
- if ( dist < 1.0f && linSpeed != 0.0f )
- {
- m_bmWatchDogTime += event.rTime;
- }
- else
- {
- m_bmWatchDogTime = 0.0f;
- m_bmWatchDogPos = pos;
- }
-
- if ( m_bmWatchDogTime >= 1.0f ) // immobile for a long time?
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- BeamStart(); // we start all
- return true;
- }
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- m_physics->SetMotorSpeedX(linSpeed); // advance
- return true;
- }
-
- if ( m_phase == TGP_BEAMDOWN ) // landed?
- {
- m_physics->SetMotorSpeedY(-0.5f); // tomb
- return true;
- }
-
- if ( m_phase == TGP_LAND ) // landed?
- {
- m_physics->SetMotorSpeedY(-0.5f); // tomb
- return true;
- }
-
- if ( m_goalMode == TGG_EXPRESS )
- {
- if ( m_crashMode == TGC_HALT )
- {
- if ( m_physics->RetCollision() ) // collision?
- {
- m_physics->SetCollision(false); // there's more
- m_error = ERR_STOP;
- return true;
- }
- }
-
- pos = m_object->RetPosition(0);
-
- if ( m_altitude > 0.0f )
- {
- h = m_terrain->RetFloorHeight(pos, true, true);
- linSpeed = 0.0f;
- if ( h < m_altitude )
- {
- linSpeed = 0.1f; // up
- }
- if ( h > m_altitude )
- {
- linSpeed = -0.2f; // down
- }
- m_physics->SetMotorSpeedY(linSpeed);
- }
-
- rot.x = m_goal.x-pos.x;
- rot.y = m_goal.z-pos.z;
- a = m_object->RetAngleY(0);
- g = Math::RotateAngle(rot.x, -rot.y); // CW !
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- m_physics->SetMotorSpeedX(1.0f); // advance
- return true;
- }
-
- if ( m_phase != TGP_TURN &&
- m_physics->RetType() == TYPE_FLYING &&
- m_altitude > 0.0f )
- {
- pos = m_object->RetPosition(0);
- dist = Math::DistanceProjected(m_goal, pos);
- factor = (dist-20.0f)/20.0f;
- if ( factor < 0.0f ) factor = 0.0f;
- if ( factor > 1.0f ) factor = 1.0f;
-
- h = m_terrain->RetFloorHeight(m_object->RetPosition(0), true, true);
- linSpeed = 0.0f;
- if ( h < (m_altitude-0.5f)*factor && factor == 1.0f )
- {
- linSpeed = 0.1f; // up
- }
- if ( h > m_altitude*factor )
- {
- linSpeed = -0.2f; // down
- }
- ComputeFlyingRepulse(dir);
- linSpeed += dir*0.2f;
-
- m_physics->SetMotorSpeedY(linSpeed);
- }
-
- if ( m_phase == TGP_ADVANCE ) // going towards the goal?
- {
- if ( m_physics->RetCollision() ) // collision?
- {
- m_physics->SetCollision(false); // there's more
- m_time = 0.0f;
- m_phase = TGP_CRWAIT;
- return true;
- }
-
-#if 0
- pos = m_object->RetPosition(0);
- a = m_object->RetAngleY(0);
- g = Math::RotateAngle(m_goal.x-pos.x, pos.z-m_goal.z); // CW !
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- dist = Math::DistanceProjected(m_goal, pos);
- linSpeed = dist/(m_physics->RetLinStopLength()*1.5f);
- if ( linSpeed > 1.0f ) linSpeed = 1.0f;
-
- if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f )
- {
- linSpeed = 0.0f; // turns first, then advance
- }
-#else
- pos = m_object->RetPosition(0);
-
- rot.x = m_goal.x-pos.x;
- rot.y = m_goal.z-pos.z;
- dist = Math::Point(rot.x, rot.y).Length();
- rot.x /= dist;
- rot.y /= dist;
-
- ComputeRepulse(repulse);
- rot.x += repulse.x*2.0f;
- rot.y += repulse.y*2.0f;
-
- a = m_object->RetAngleY(0);
- g = Math::RotateAngle(rot.x, -rot.y); // CW !
- cirSpeed = Math::Direction(a, g)*1.0f;
-//? if ( m_physics->RetType() == TYPE_FLYING &&
-//? m_physics->RetLand() ) // flying on the ground?
-//? {
-//? cirSpeed *= 4.0f; // more fishing
-//? }
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- dist = Math::DistanceProjected(m_goal, pos);
- linSpeed = dist/(m_physics->RetLinStopLength()*1.5f);
-//? if ( m_physics->RetType() == TYPE_FLYING &&
-//? m_physics->RetLand() ) // flying on the ground?
-//? {
-//? linSpeed *= 8.0f; // more fishing
-//? }
- if ( linSpeed > 1.0f ) linSpeed = 1.0f;
-
- linSpeed *= 1.0f-(1.0f-0.3f)*fabs(cirSpeed);
-
- if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f )
- {
- linSpeed = 0.0f; // turns first, then advance
- }
-#endif
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- m_physics->SetMotorSpeedX(linSpeed); // advance
- }
-
- if ( m_phase == TGP_TURN || // turns to the object?
- m_phase == TGP_CRTURN || // turns after collision?
- m_phase == TGP_CLTURN ) // turns after collision?
- {
- a = m_object->RetAngleY(0);
- g = m_angle;
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- }
-
- if ( m_phase == TGP_CRWAIT || // waits after collision?
- m_phase == TGP_CLWAIT ) // waits after collision?
- {
- m_time += event.rTime;
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- }
-
- if ( m_phase == TGP_CRADVANCE ) // advance after collision?
- {
- if ( m_physics->RetCollision() ) // collision?
- {
- m_physics->SetCollision(false); // there's more
- m_time = 0.0f;
- m_phase = TGP_CLWAIT;
- return true;
- }
- m_physics->SetMotorSpeedX(0.5f); // advance mollo
- }
-
- if ( m_phase == TGP_CLADVANCE ) // advance after collision?
- {
- if ( m_physics->RetCollision() ) // collision?
- {
- m_physics->SetCollision(false); // there's more
- m_time = 0.0f;
- m_phase = TGP_CRWAIT;
- return true;
- }
- m_physics->SetMotorSpeedX(0.5f); // advance mollo
- }
-
- if ( m_phase == TGP_MOVE ) // final advance?
- {
- m_bmTimeLimit -= event.rTime;
- m_physics->SetMotorSpeedX(1.0f);
- }
-
- return true;
-}
-
-
-// Sought a target for the worm.
-
-CObject* CTaskGoto::WormSearch(Math::Vector &impact)
-{
- CObject* pObj;
- CObject* pBest = 0;
- Math::Vector iPos, oPos;
- ObjectType oType;
- float distance, min, radius;
- int i;
-
- iPos = m_object->RetPosition(0);
- min = 1000000.0f;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( oType != OBJECT_MOBILEfa &&
- oType != OBJECT_MOBILEta &&
- oType != OBJECT_MOBILEwa &&
- oType != OBJECT_MOBILEia &&
- oType != OBJECT_MOBILEfc &&
- oType != OBJECT_MOBILEtc &&
- oType != OBJECT_MOBILEwc &&
- oType != OBJECT_MOBILEic &&
- oType != OBJECT_MOBILEfi &&
- oType != OBJECT_MOBILEti &&
- oType != OBJECT_MOBILEwi &&
- oType != OBJECT_MOBILEii &&
- oType != OBJECT_MOBILEfs &&
- oType != OBJECT_MOBILEts &&
- oType != OBJECT_MOBILEws &&
- oType != OBJECT_MOBILEis &&
- oType != OBJECT_MOBILErt &&
- oType != OBJECT_MOBILErc &&
- oType != OBJECT_MOBILErr &&
- oType != OBJECT_MOBILErs &&
- oType != OBJECT_MOBILEsa &&
- oType != OBJECT_MOBILEtg &&
- oType != OBJECT_MOBILEft &&
- oType != OBJECT_MOBILEtt &&
- oType != OBJECT_MOBILEwt &&
- oType != OBJECT_MOBILEit &&
- oType != OBJECT_MOBILEdr &&
- oType != OBJECT_DERRICK &&
- oType != OBJECT_STATION &&
- oType != OBJECT_FACTORY &&
- oType != OBJECT_REPAIR &&
- oType != OBJECT_DESTROYER &&
- oType != OBJECT_CONVERT &&
- oType != OBJECT_TOWER &&
- oType != OBJECT_RESEARCH &&
- oType != OBJECT_RADAR &&
- oType != OBJECT_INFO &&
- oType != OBJECT_ENERGY &&
- oType != OBJECT_LABO &&
- oType != OBJECT_NUCLEAR &&
- oType != OBJECT_PARA &&
- oType != OBJECT_SAFE &&
- oType != OBJECT_HUSTON ) continue;
-
- if ( pObj->RetVirusMode() ) continue; // object infected?
-
- if ( !pObj->GetCrashSphere(0, oPos, radius) ) continue;
- distance = Math::DistanceProjected(oPos, iPos);
- if ( distance < min )
- {
- min = distance;
- pBest = pObj;
- }
- }
- if ( pBest == 0 ) return 0;
-
- impact = pBest->RetPosition(0);
- return pBest;
-}
-
-// Contaminate objects near the worm.
-
-void CTaskGoto::WormFrame(float rTime)
-{
- CObject* pObj;
- Math::Vector impact, pos;
- float dist;
-
- m_wormLastTime += rTime;
-
- if ( m_wormLastTime >= 0.5f )
- {
- m_wormLastTime = 0.0f;
-
- pObj = WormSearch(impact);
- if ( pObj != 0 )
- {
- pos = m_object->RetPosition(0);
- dist = Math::Distance(pos, impact);
- if ( dist <= 15.0f )
- {
- pObj->SetVirusMode(true); // bam, infected!
- }
- }
- }
-}
-
-
-
-// Assigns the goal was achieved.
-// "dist" is the distance that needs to go far to make a deposit or object.
-
-Error CTaskGoto::Start(Math::Vector goal, float altitude,
- TaskGotoGoal goalMode, TaskGotoCrash crashMode)
-{
- Math::Vector pos;
- CObject* target;
- ObjectType type;
- float dist;
- int x, y;
-
- type = m_object->RetType();
-
- if ( goalMode == TGG_DEFAULT )
- {
- goalMode = TGG_STOP;
- if ( type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_WORM )
- {
- goalMode = TGG_EXPRESS;
- }
- }
-
- if ( crashMode == TGC_DEFAULT )
- {
-//? crashMode = TGC_RIGHTLEFT;
- crashMode = TGC_BEAM;
- if ( type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_WORM ||
- type == OBJECT_BEE )
- {
- crashMode = TGC_HALT;
- }
- }
-
- m_altitude = altitude;
- m_goalMode = goalMode;
- m_crashMode = crashMode;
- m_goalObject = goal;
- m_goal = goal;
-
- m_bTake = false;
- m_phase = TGP_ADVANCE;
- m_error = ERR_OK;
- m_try = 0;
- m_bmFretObject = 0;
- m_bmFinalMove = 0.0f;
-
- pos = m_object->RetPosition(0);
- dist = Math::DistanceProjected(pos, m_goal);
- if ( dist < 10.0f && m_crashMode == TGC_BEAM )
- {
- m_crashMode = TGC_RIGHTLEFT;
- }
-
- m_bWorm = false;
- if ( type == OBJECT_WORM )
- {
- m_bWorm = true;
- m_wormLastTime = 0.0f;
- }
-
- m_bApprox = false;
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH ||
- type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs )
- {
- m_bApprox = true;
- }
-
- if ( !m_bApprox && m_crashMode != TGC_BEAM )
- {
- target = SearchTarget(goal, 1.0f);
- if ( target != 0 )
- {
- m_goal = target->RetPosition(0);
- dist = 0.0f;
- if ( !AdjustBuilding(m_goal, 1.0f, dist) )
- {
- dist = 0.0f;
- AdjustTarget(target, m_goal, dist);
- }
- m_bTake = true; // object was taken on arrival (final rotation)
- }
- }
-
- m_lastDistance = 1000.0f;
- m_physics->SetCollision(false);
-
- if ( m_crashMode == TGC_BEAM ) // with the algorithm of rays?
- {
- target = SearchTarget(goal, 1.0f);
- if ( target != 0 )
- {
- m_goal = target->RetPosition(0);
- dist = 4.0f;
- if ( AdjustBuilding(m_goal, 1.0f, dist) )
- {
- m_bmFinalMove = dist;
- }
- else
- {
- dist = 4.0f;
- if ( AdjustTarget(target, m_goal, dist) )
- {
- m_bmFretObject = target; // cargo on the ground
- }
- else
- {
- m_bmFinalMove = dist;
- }
- }
- m_bTake = true; // object was taken on arrival (final rotation)
- }
-
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude == 0.0f )
- {
- pos = m_object->RetPosition(0);
- dist = Math::DistanceProjected(pos, m_goal);
- if ( dist > FLY_DIST_GROUND ) // over 20 meters?
- {
- m_altitude = FLY_DEF_HEIGHT; // default altitude
- }
- }
-
- BeamStart();
-
- if ( m_bmFretObject == 0 )
- {
- x = (int)((m_goal.x+1600.0f)/BM_DIM_STEP);
- y = (int)((m_goal.z+1600.0f)/BM_DIM_STEP);
- if ( BitmapTestDot(0, x, y) ) // arrival occupied?
- {
-#if 0
- Math::Vector min, max;
- min = m_object->RetPosition(0);
- max = m_goal;
- if ( min.x > max.x ) Math::Swap(min.x, max.x);
- if ( min.z > max.z ) Math::Swap(min.z, max.z);
- min.x -= 50.0f;
- min.z -= 50.0f;
- max.x += 50.0f;
- max.z += 50.0f;
- BitmapDebug(min, max, m_object->RetPosition(0), m_goal);
-#endif
- m_error = ERR_GOTO_BUSY;
- return m_error;
- }
- }
- }
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskGoto::IsEnded()
-{
- Math::Vector pos;
- float limit, angle, dist, h, level;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_error != ERR_OK ) return m_error;
-
- pos = m_object->RetPosition(0);
-
- if ( m_phase == TGP_BEAMLEAK ) // leak?
- {
- if ( m_leakTime >= m_leakDelay )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- BeamInit();
- m_phase = TGP_BEAMSEARCH; // will seek the path
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TGP_BEAMSEARCH ) // search path?
- {
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TGP_BEAMWCOLD ) // expects cool reactor?
- {
- if ( m_altitude != 0.0f &&
- m_physics->RetReactorRange() < 1.0f ) return ERR_CONTINUE;
- m_phase = TGP_BEAMUP;
- }
-
- if ( m_phase == TGP_BEAMUP ) // off?
- {
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
- {
- level = m_terrain->RetFloorLevel(pos, true, true);
- h = level+m_altitude-20.0f;
- limit = m_terrain->RetFlyingMaxHeight();
- if ( h > limit ) h = limit;
- if ( pos.y < h-1.0f ) return ERR_CONTINUE;
-
- m_physics->SetMotorSpeedY(0.0f); // stops the ascent
- }
- m_phase = TGP_BEAMGOTO;
- }
-
- if ( m_phase == TGP_BEAMGOTO ) // goto dot list ?
- {
- if ( m_altitude != 0.0f &&
- m_physics->RetReactorRange() < 0.1f ) // overheating?
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_physics->SetMotorSpeedY(-1.0f); // tomb
- m_phase = TGP_BEAMWCOLD;
- return ERR_CONTINUE;
- }
-
- if ( m_physics->RetLand() ) // on the ground?
- {
- limit = 1.0f;
- }
- else // in flight?
- {
- limit = 2.0f;
- if ( m_bmIndex < m_bmTotal ) limit *= 2.0f; // intermediate point
- }
- if ( m_bApprox ) limit = 2.0f;
-
- if ( fabs(pos.x - m_bmPoints[m_bmIndex].x) < limit &&
- fabs(pos.z - m_bmPoints[m_bmIndex].z) < limit )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
-
- m_bmIndex = BeamShortcut();
-
- if ( m_bmIndex > m_bmTotal )
- {
- m_phase = TGP_BEAMDOWN;
- }
- }
- }
-
- if ( m_phase == TGP_BEAMDOWN ) // landed?
- {
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
- {
- if ( !m_physics->RetLand() ) return ERR_CONTINUE;
- m_physics->SetMotorSpeedY(0.0f); // stops the descent
-
- m_altitude = 0.0f;
- m_phase = TGP_BEAMGOTO; // advance finely on the ground to finish
- m_bmIndex = m_bmTotal;
- return ERR_CONTINUE;
- }
-
- if ( m_bTake )
- {
- m_angle = Math::RotateAngle(m_goalObject.x-pos.x, pos.z-m_goalObject.z);
- m_phase = TGP_TURN;
- }
- else
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- return ERR_STOP;
- }
- }
-
- if ( m_goalMode == TGG_EXPRESS )
- {
- dist = Math::DistanceProjected(m_goal, pos);
- if ( dist < 10.0f && dist > m_lastDistance )
- {
- return ERR_STOP;
- }
- m_lastDistance = dist;
- }
-
- if ( m_phase == TGP_ADVANCE ) // going towards the goal?
- {
- if ( m_physics->RetLand() ) limit = 0.1f; // on the ground
- else limit = 1.0f; // flying
- if ( m_bApprox ) limit = 2.0f;
-
- if ( fabs(pos.x - m_goal.x) < limit &&
- fabs(pos.z - m_goal.z) < limit )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_phase = TGP_LAND;
- }
- }
-
- if ( m_phase == TGP_LAND ) // landed?
- {
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
- {
- if ( !m_physics->RetLand() ) return ERR_CONTINUE;
- m_physics->SetMotorSpeedY(0.0f);
- }
-
- if ( m_bTake )
- {
- m_angle = Math::RotateAngle(m_goalObject.x-pos.x, pos.z-m_goalObject.z);
- m_phase = TGP_TURN;
- }
- else
- {
- return ERR_STOP;
- }
- }
-
- if ( m_phase == TGP_TURN ) // turns to the object?
- {
- angle = Math::NormAngle(m_object->RetAngleY(0));
- limit = 0.02f;
- if ( m_bApprox ) limit = 0.10f;
- if ( fabs(angle-m_angle) < limit )
- {
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- if ( m_bmFinalMove == 0.0f ) return ERR_STOP;
-
- m_bmFinalPos = m_object->RetPosition(0);
- m_bmFinalDist = m_physics->RetLinLength(m_bmFinalMove);
- m_bmTimeLimit = m_physics->RetLinTimeLength(fabs(m_bmFinalMove))*1.5f;
- if ( m_bmTimeLimit < 0.5f ) m_bmTimeLimit = 0.5f;
- m_phase = TGP_MOVE;
- }
- }
-
- if ( m_phase == TGP_CRWAIT ) // waits after collision?
- {
- if ( m_crashMode == TGC_HALT )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_error = ERR_GENERIC;
- return m_error;
- }
- if ( m_time >= 1.0f )
- {
- if ( m_crashMode == TGC_RIGHTLEFT ||
- m_crashMode == TGC_RIGHT ) angle = Math::PI/2.0f; // 90 deegres to the right
- else angle = -Math::PI/2.0f; // 90 deegres to the left
- m_angle = Math::NormAngle(m_object->RetAngleY(0)+angle);
- m_phase = TGP_CRTURN;
-//? m_phase = TGP_ADVANCE;
- }
- }
-
- if ( m_phase == TGP_CRTURN ) // turns after collision?
- {
- angle = Math::NormAngle(m_object->RetAngleY(0));
- limit = 0.1f;
- if ( fabs(angle-m_angle) < limit )
- {
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_pos = pos;
- m_phase = TGP_CRADVANCE;
- }
- }
-
- if ( m_phase == TGP_CRADVANCE ) // advance after collision?
- {
- if ( Math::Distance(pos, m_pos) >= 5.0f )
- {
- m_phase = TGP_ADVANCE;
- }
- }
-
- if ( m_phase == TGP_CLWAIT ) // waits after collision?
- {
- if ( m_time >= 1.0f )
- {
- if ( m_crashMode == TGC_RIGHTLEFT ) angle = -Math::PI;
- if ( m_crashMode == TGC_LEFTRIGHT ) angle = Math::PI;
- if ( m_crashMode == TGC_RIGHT ) angle = Math::PI/2.0f;
- if ( m_crashMode == TGC_LEFT ) angle = -Math::PI/2.0f;
- m_angle = Math::NormAngle(m_object->RetAngleY(0)+angle);
- m_phase = TGP_CLTURN;
- }
- }
-
- if ( m_phase == TGP_CLTURN ) // turns after collision?
- {
- angle = Math::NormAngle(m_object->RetAngleY(0));
- limit = 0.1f;
- if ( fabs(angle-m_angle) < limit )
- {
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_pos = pos;
- m_phase = TGP_CLADVANCE;
- }
- }
-
- if ( m_phase == TGP_CLADVANCE ) // advance after collision?
- {
- if ( Math::Distance(pos, m_pos) >= 10.0f )
- {
- m_phase = TGP_ADVANCE;
- m_try ++;
- }
- }
-
- if ( m_phase == TGP_MOVE ) // final advance?
- {
- if ( m_bmTimeLimit <= 0.0f )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops
- Abort();
- return ERR_STOP;
- }
-
- dist = Math::Distance(m_bmFinalPos, m_object->RetPosition(0));
- if ( dist < m_bmFinalDist ) return ERR_CONTINUE;
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- return ERR_STOP;
- }
-
- return ERR_CONTINUE;
-}
-
-
-// Tries the object is the target position.
-
-CObject* CTaskGoto::SearchTarget(Math::Vector pos, float margin)
-{
- CObject *pObj, *pBest;
- Math::Vector oPos;
- float dist, min;
- int i;
-
- pBest = 0;
- min = 1000000.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue;
- if ( pObj->RetTruck() != 0 ) continue; // object transtorted?
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(pos, oPos);
-
- if ( dist <= margin && dist <= min )
- {
- min = dist;
- pBest = pObj;
- }
- }
-
- return pBest;
-}
-
-// Adjusts the target as a function of the object.
-// Returns true if it is cargo laying on the ground, which can be approached from any site.
-
-bool CTaskGoto::AdjustTarget(CObject* pObj, Math::Vector &pos, float &distance)
-{
- ObjectType type;
- Character* character;
- Math::Matrix* mat;
- Math::Vector goal;
- float dist, suppl;
-
- type = m_object->RetType();
- if ( type == OBJECT_BEE ||
- type == OBJECT_WORM )
- {
- pos = pObj->RetPosition(0);
- return false; // single approach
- }
-
- type = pObj->RetType();
-
- if ( type == OBJECT_FRET ||
- type == OBJECT_STONE ||
- type == OBJECT_URANIUM ||
- type == OBJECT_METAL ||
- type == OBJECT_POWER ||
- type == OBJECT_ATOMIC ||
- type == OBJECT_BULLET ||
- type == OBJECT_BBOX ||
- type == OBJECT_KEYa ||
- type == OBJECT_KEYb ||
- type == OBJECT_KEYc ||
- type == OBJECT_KEYd ||
- type == OBJECT_TNT ||
- type == OBJECT_SCRAP1 ||
- type == OBJECT_SCRAP2 ||
- type == OBJECT_SCRAP3 ||
- type == OBJECT_SCRAP4 ||
- type == OBJECT_SCRAP5 ||
- type == OBJECT_BOMB ||
- type == OBJECT_RUINmobilew1 ||
- type == OBJECT_RUINmobilew2 ||
- type == OBJECT_RUINmobilet1 ||
- type == OBJECT_RUINmobilet2 ||
- type == OBJECT_RUINmobiler1 ||
- type == OBJECT_RUINmobiler2 )
- {
- pos = m_object->RetPosition(0);
- goal = pObj->RetPosition(0);
- dist = Math::Distance(goal, pos);
- pos = (pos-goal)*(TAKE_DIST+distance)/dist + goal;
- return true; // approach from all sites
- }
-
- if ( type == OBJECT_BASE )
- {
- pos = m_object->RetPosition(0);
- goal = pObj->RetPosition(0);
- dist = Math::Distance(goal, pos);
- pos = (pos-goal)*(TAKE_DIST+distance)/dist + goal;
- return true; // approach from all sites
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr )
- {
- character = pObj->RetCharacter();
- pos = character->posPower;
- pos.x -= TAKE_DIST+TAKE_DIST_OTHER+distance;
- mat = pObj->RetWorldMatrix(0);
- pos = Transform(*mat, pos);
- return false; // single approach
- }
-
- if ( GetHotPoint(pObj, goal, true, distance, suppl) )
- {
- pos = goal;
- distance += suppl;
- return false; // single approach
- }
-
- pos = pObj->RetPosition(0);
- distance = 0.0f;
- return false; // single approach
-}
-
-// If you are on an object produced by a building (ore produced by derrick),
-// changes the position by report the building.
-
-bool CTaskGoto::AdjustBuilding(Math::Vector &pos, float margin, float &distance)
-{
- CObject* pObj;
- Math::Vector oPos;
- float dist, suppl;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue;
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- if ( !GetHotPoint(pObj, oPos, false, 0.0f, suppl) ) continue;
- dist = Math::DistanceProjected(pos, oPos);
- if ( dist <= margin )
- {
- GetHotPoint(pObj, pos, true, distance, suppl);
- distance += suppl;
- return true;
- }
- }
- return false;
-}
-
-// Returns the item or product or pose is something on a building.
-
-bool CTaskGoto::GetHotPoint(CObject *pObj, Math::Vector &pos,
- bool bTake, float distance, float &suppl)
-{
- ObjectType type;
- Math::Matrix* mat;
-
- pos = Math::Vector(0.0f, 0.0f, 0.0f);
- suppl = 0.0f;
- type = pObj->RetType();
-
- if ( type == OBJECT_DERRICK )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 8.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_CONVERT )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 0.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_RESEARCH )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 10.0f;
- if ( bTake && distance != 0.0f ) suppl = 2.5f;
- if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_ENERGY )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 6.0f;
- if ( bTake && distance != 0.0f ) suppl = 6.0f;
- if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_TOWER )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 5.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_LABO )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 6.0f;
- if ( bTake && distance != 0.0f ) suppl = 6.0f;
- if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_NUCLEAR )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 22.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_FACTORY )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 4.0f;
- if ( bTake && distance != 0.0f ) suppl = 6.0f;
- if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_STATION )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 4.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += distance;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_REPAIR )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 4.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += distance;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_DESTROYER )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 0.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_PARA && m_physics->RetType() == TYPE_FLYING )
- {
- mat = pObj->RetWorldMatrix(0);
- if ( bTake && distance != 0.0f ) suppl = 20.0f;
- if ( bTake ) pos.x += distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- suppl = 0.0f;
- return false;
-}
-
-
-// Seeks an object too close that he must flee.
-
-bool CTaskGoto::LeakSearch(Math::Vector &pos, float &delay)
-{
- CObject *pObj, *pObstacle;
- Math::Vector iPos, oPos, bPos;
- float iRadius, oRadius, bRadius, dist, min, dir;
- int i, j;
-
- if ( !m_physics->RetLand() ) return false; // in flight?
-
- m_object->GetCrashSphere(0, iPos, iRadius);
-
- min = 100000.0f;
- bRadius = 0.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( !pObj->RetActif() ) continue;
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- dist = Math::DistanceProjected(oPos, iPos);
- if ( dist < min )
- {
- min = dist;
- bPos = oPos;
- bRadius = oRadius;
- pObstacle = pObj;
- }
- }
- }
- if ( min > iRadius+bRadius+4.0f ) return false;
-
- m_bLeakRecede = false;
-
- dist = 4.0f;
- dir = 1.0f;
- if ( pObstacle->RetType() == OBJECT_FACTORY )
- {
- dist = 16.0f;
- dir = -1.0f;
- m_bLeakRecede = true; // simply recoils
- }
-
- pos = bPos;
- delay = m_physics->RetLinTimeLength(dist, dir);
- return true;
-}
-
-
-// Calculates the force of repulsion due to obstacles.
-// The vector length rendered is between 0 and 1.
-
-void CTaskGoto::ComputeRepulse(Math::Point &dir)
-{
-#if 0
- Math::Vector iPos, oPos;
- Math::Point repulse;
- CObject *pObj;
- float dist, iRadius, oRadius;
- int i;
-
- dir.x = 0.0f;
- dir.y = 0.0f;
-
- m_object->GetCrashSphere(0, iPos, iRadius);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, m_goalObject);
- if ( dist <= 1.0f ) continue;
-
- pObj->GetGlobalSphere(oPos, oRadius);
- oRadius += iRadius+m_physics->RetLinStopLength()*1.1f;
- dist = Math::DistanceProjected(oPos, iPos);
- if ( dist <= oRadius )
- {
- repulse.x = iPos.x-oPos.x;
- repulse.y = iPos.z-oPos.z;
-
-//? dist = 0.2f-(0.2f*dist/oRadius);
- dist = powf(dist/oRadius, 2.0f);
- dist = 0.2f-0.2f*dist;
- repulse.x *= dist;
- repulse.y *= dist;
-//? repulse.x /= dist;
-//? repulse.y /= dist;
-
- dir.x += repulse.x;
- dir.y += repulse.y;
- }
- }
-#else
- ObjectType iType, oType;
- Math::Vector iPos, oPos;
- Math::Point repulse;
- CObject *pObj;
- float gDist, add, addi, fac, dist, iRadius, oRadius;
- int i, j;
- bool bAlien;
-
- dir.x = 0.0f;
- dir.y = 0.0f;
-
- // The worm goes everywhere and through everything!
- iType = m_object->RetType();
- if ( iType == OBJECT_WORM ) return;
-
- m_object->GetCrashSphere(0, iPos, iRadius);
- gDist = Math::Distance(iPos, m_goal);
-
- add = m_physics->RetLinStopLength()*1.1f; // braking distance
- fac = 2.0f;
-
- if ( iType == OBJECT_MOBILEwa ||
- iType == OBJECT_MOBILEwc ||
- iType == OBJECT_MOBILEwi ||
- iType == OBJECT_MOBILEws ||
- iType == OBJECT_MOBILEwt ) // wheels?
- {
- add = 5.0f;
- fac = 1.5f;
- }
- if ( iType == OBJECT_MOBILEta ||
- iType == OBJECT_MOBILEtc ||
- iType == OBJECT_MOBILEti ||
- iType == OBJECT_MOBILEts ||
- iType == OBJECT_MOBILEtt ||
- iType == OBJECT_MOBILEdr ) // caterpillars?
- {
- add = 4.0f;
- fac = 1.5f;
- }
- if ( iType == OBJECT_MOBILEfa ||
- iType == OBJECT_MOBILEfc ||
- iType == OBJECT_MOBILEfi ||
- iType == OBJECT_MOBILEfs ||
- iType == OBJECT_MOBILEft ) // flying?
- {
- if ( m_physics->RetLand() )
- {
- add = 5.0f;
- fac = 1.5f;
- }
- else
- {
- add = 10.0f;
- fac = 1.5f;
- }
- }
- if ( iType == OBJECT_MOBILEia ||
- iType == OBJECT_MOBILEic ||
- iType == OBJECT_MOBILEii ||
- iType == OBJECT_MOBILEis ||
- iType == OBJECT_MOBILEit ) // legs?
- {
- add = 4.0f;
- fac = 1.5f;
- }
- if ( iType == OBJECT_BEE ) // wasp?
- {
- if ( m_physics->RetLand() )
- {
- add = 3.0f;
- fac = 1.5f;
- }
- else
- {
- add = 5.0f;
- fac = 1.5f;
- }
- }
-
- bAlien = false;
- if ( iType == OBJECT_MOTHER ||
- iType == OBJECT_ANT ||
- iType == OBJECT_SPIDER ||
- iType == OBJECT_BEE ||
- iType == OBJECT_WORM )
- {
- bAlien = true;
- }
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- oType = pObj->RetType();
-
- if ( oType == OBJECT_WORM ) continue;
-
- if ( bAlien )
- {
- if ( oType == OBJECT_STONE ||
- oType == OBJECT_URANIUM ||
- oType == OBJECT_METAL ||
- oType == OBJECT_POWER ||
- oType == OBJECT_ATOMIC ||
- oType == OBJECT_BULLET ||
- oType == OBJECT_BBOX ||
- oType == OBJECT_KEYa ||
- oType == OBJECT_KEYb ||
- oType == OBJECT_KEYc ||
- oType == OBJECT_KEYd ||
- oType == OBJECT_TNT ||
- oType == OBJECT_SCRAP1 ||
- oType == OBJECT_SCRAP2 ||
- oType == OBJECT_SCRAP3 ||
- oType == OBJECT_SCRAP4 ||
- oType == OBJECT_SCRAP5 ||
- oType == OBJECT_BOMB ||
- (oType >= OBJECT_PLANT0 &&
- oType <= OBJECT_PLANT19 ) ||
- (oType >= OBJECT_MUSHROOM0 &&
- oType <= OBJECT_MUSHROOM9 ) ) continue;
- }
-
- addi = add;
- if ( iType == OBJECT_BEE &&
- oType == OBJECT_BEE )
- {
- addi = 2.0f; // between wasps, do not annoy too much
- }
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- if ( oPos.y-oRadius > iPos.y+iRadius ) continue;
- if ( oPos.y+oRadius < iPos.y-iRadius ) continue;
-
- dist = Math::Distance(oPos, m_goal);
- if ( dist <= 1.0f ) continue; // on purpose?
-
- oRadius += iRadius+addi;
- dist = Math::DistanceProjected(oPos, iPos);
- if ( dist > gDist ) continue; // beyond the goal?
- if ( dist <= oRadius )
- {
- repulse.x = iPos.x-oPos.x;
- repulse.y = iPos.z-oPos.z;
-
- dist = powf(dist/oRadius, fac);
- dist = 0.2f-0.2f*dist;
- repulse.x *= dist;
- repulse.y *= dist;
-
- dir.x += repulse.x;
- dir.y += repulse.y;
- }
- }
- }
-#endif
-}
-
-// Calculates the force of vertical repulsion according to barriers.
-// The vector length is made​between -1 and 1.
-
-void CTaskGoto::ComputeFlyingRepulse(float &dir)
-{
- ObjectType oType;
- Math::Vector iPos, oPos;
- CObject *pObj;
- float add, fac, dist, iRadius, oRadius, repulse;
- int i, j;
-
- m_object->GetCrashSphere(0, iPos, iRadius);
-
- add = 0.0f;
- fac = 1.5f;
- dir = 0.0f;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- oType = pObj->RetType();
-
- if ( oType == OBJECT_WORM ) continue;
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- oRadius += iRadius+add;
- dist = Math::DistanceProjected(oPos, iPos);
- if ( dist <= oRadius )
- {
- repulse = iPos.y-oPos.y;
-
- dist = powf(dist/oRadius, fac);
- dist = 0.2f-0.2f*dist;
- repulse *= dist;
-
- dir += repulse;
- }
- }
- }
-
- if ( dir < -1.0f ) dir = -1.0f;
- if ( dir > 1.0f ) dir = 1.0f;
-}
-
-
-
-// Among all of the following, seek if there is one allowing to go directly to the crow flies.
-// If yes, skip all the unnecessary intermediate points.
-
-int CTaskGoto::BeamShortcut()
-{
- int i;
-
- for ( i=m_bmTotal ; i>=m_bmIndex+2 ; i-- ) // tries from the last
- {
- if ( BitmapTestLine(m_bmPoints[m_bmIndex], m_bmPoints[i], 0.0f, false) )
- {
- return i; // bingo, found
- }
- }
-
- return m_bmIndex+1; // simply goes to the next
-}
-
-// That's the big start.
-
-void CTaskGoto::BeamStart()
-{
- Math::Vector min, max;
-
- BitmapOpen();
- BitmapObject();
-
- min = m_object->RetPosition(0);
- max = m_goal;
- if ( min.x > max.x ) Math::Swap(min.x, max.x);
- if ( min.z > max.z ) Math::Swap(min.z, max.z);
- min.x -= 10.0f*BM_DIM_STEP;
- min.z -= 10.0f*BM_DIM_STEP;
- max.x += 10.0f*BM_DIM_STEP;
- max.z += 10.0f*BM_DIM_STEP;
- BitmapTerrain(min, max);
-
- if ( LeakSearch(m_leakPos, m_leakDelay) )
- {
- m_phase = TGP_BEAMLEAK; // must first leak
- m_leakTime = 0.0f;
- }
- else
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- BeamInit();
- m_phase = TGP_BEAMSEARCH; // will seek the path
- }
-}
-
-// Initialization before the first BeamSearch.
-
-void CTaskGoto::BeamInit()
-{
- int i;
-
- for ( i=0 ; i<MAXPOINTS ; i++ )
- {
- m_bmIter[i] = -1;
- }
- m_bmStep = 0;
-}
-
-// Calculates points and passes to go from start to goal.
-// Returns:
-// ERR_OK if it's good
-// ERR_GOTO_IMPOSSIBLE if impossible
-// ERR_GOTO_ITER if aborts because too many recursions
-// ERR_CONTINUE if not done yet
-// goalRadius: distance at which we must approach the goal
-
-Error CTaskGoto::BeamSearch(const Math::Vector &start, const Math::Vector &goal,
- float goalRadius)
-{
- float step, len;
- int nbIter;
-
- m_bmStep ++;
-
- len = Math::DistanceProjected(start, goal);
- step = len/5.0f;
- if ( step < BM_DIM_STEP*2.1f ) step = BM_DIM_STEP*2.1f;
- if ( step > 20.0f ) step = 20.0f;
- nbIter = 200; // in order not to lower the framerate
- m_bmIterCounter = 0;
- return BeamExplore(start, start, goal, goalRadius, 165.0f*Math::PI/180.0f, 22, step, 0, nbIter);
-}
-
-// prevPos: previous position
-// curPos: current position
-// goalPos: position that seeks to achieve
-// angle: angle to the goal we explores
-// nbDiv: number of subdivisions being done with angle
-// step length of a step
-// i number of recursions made
-// nbIter maximum number of iterations you have the right to make before temporarily interrupt
-
-Error CTaskGoto::BeamExplore(const Math::Vector &prevPos, const Math::Vector &curPos,
- const Math::Vector &goalPos, float goalRadius,
- float angle, int nbDiv, float step,
- int i, int nbIter)
-{
- Math::Vector newPos;
- Error ret;
- int iDiv, iClear, iLar;
-
- iLar = 0;
- if ( i >= MAXPOINTS ) return ERR_GOTO_ITER; // too many recursions
-
- if ( m_bmIter[i] == -1 )
- {
- m_bmIter[i] = 0;
-
- if ( i == 0 )
- {
- m_bmPoints[i] = curPos;
- }
- else
- {
- if ( !BitmapTestLine(prevPos, curPos, angle/nbDiv, true) ) return ERR_GOTO_IMPOSSIBLE;
-
- m_bmPoints[i] = curPos;
-
- if ( Math::DistanceProjected(curPos, goalPos)-goalRadius <= step )
- {
- if ( goalRadius == 0.0f )
- {
- newPos = goalPos;
- }
- else
- {
- newPos = BeamPoint(curPos, goalPos, 0, Math::DistanceProjected(curPos, goalPos)-goalRadius);
- }
- if ( BitmapTestLine(curPos, newPos, angle/nbDiv, false) )
- {
- m_bmPoints[i+1] = newPos;
- m_bmTotal = i+1;
- return ERR_OK;
- }
- }
- }
- }
-
- if ( iLar >= m_bmIter[i] )
- {
- newPos = BeamPoint(curPos, goalPos, 0, step);
- ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter);
- if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret;
- m_bmIter[i] = iLar+1;
- for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1;
- m_bmIterCounter ++;
- if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE;
- }
- iLar ++;
-
- for ( iDiv=1 ; iDiv<=nbDiv ; iDiv++ )
- {
- if ( iLar >= m_bmIter[i] )
- {
- newPos = BeamPoint(curPos, goalPos, angle*iDiv/nbDiv, step);
- ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter);
- if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret;
- m_bmIter[i] = iLar+1;
- for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1;
- m_bmIterCounter ++;
- if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE;
- }
- iLar ++;
-
- if ( iLar >= m_bmIter[i] )
- {
- newPos = BeamPoint(curPos, goalPos, -angle*iDiv/nbDiv, step);
- ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter);
- if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret;
- m_bmIter[i] = iLar+1;
- for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1;
- m_bmIterCounter ++;
- if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE;
- }
- iLar ++;
- }
-
- return ERR_GOTO_IMPOSSIBLE;
-}
-
-// Is a right "start-goal". Calculates the point located at the distance "step"
-// from the point "start" and an angle "angle" with the right.
-
-Math::Vector CTaskGoto::BeamPoint(const Math::Vector &startPoint,
- const Math::Vector &goalPoint,
- float angle, float step)
-{
- Math::Vector resPoint;
- float goalAngle;
-
- goalAngle = Math::RotateAngle(goalPoint.x-startPoint.x, goalPoint.z-startPoint.z);
-
- resPoint.x = startPoint.x + cosf(goalAngle+angle)*step;
- resPoint.z = startPoint.z + sinf(goalAngle+angle)*step;
- resPoint.y = 0.0f;
-
- return resPoint;
-}
-
-// Displays a bitmap part.
-
-void CTaskGoto::BitmapDebug(const Math::Vector &min, const Math::Vector &max,
- const Math::Vector &start, const Math::Vector &goal)
-{
- int minx, miny, maxx, maxy, x, y, i ,n;
- char s[2000];
-
- minx = (int)((min.x+1600.0f)/BM_DIM_STEP);
- miny = (int)((min.z+1600.0f)/BM_DIM_STEP);
- maxx = (int)((max.x+1600.0f)/BM_DIM_STEP);
- maxy = (int)((max.z+1600.0f)/BM_DIM_STEP);
-
- if ( minx > maxx ) Math::Swap(minx, maxx);
- if ( miny > maxy ) Math::Swap(miny, maxy);
-
- OutputDebugString("Bitmap :\n");
- for ( y=miny ; y<=maxy ; y++ )
- {
- s[0] = 0;
- for ( x=minx ; x<=maxx ; x++ )
- {
- n = -1;
- for ( i=0 ; i<=m_bmTotal ; i++ )
- {
- if ( x == (int)((m_bmPoints[i].x+1600.0f)/BM_DIM_STEP) &&
- y == (int)((m_bmPoints[i].z+1600.0f)/BM_DIM_STEP) )
- {
- n = i;
- break;
- }
- }
-
- if ( BitmapTestDot(0, x,y) )
- {
- strcat(s, "o");
- }
- else
- {
- if ( BitmapTestDot(1, x,y) )
- {
- strcat(s, "-");
- }
- else
- {
- strcat(s, ".");
- }
- }
-
- if ( x == (int)((start.x+1600.0f)/BM_DIM_STEP) &&
- y == (int)((start.z+1600.0f)/BM_DIM_STEP) )
- {
- strcat(s, "s");
- }
- else
- if ( x == (int)((goal.x+1600.0f)/BM_DIM_STEP) &&
- y == (int)((goal.z+1600.0f)/BM_DIM_STEP) )
- {
- strcat(s, "g");
- }
- else
- if ( n != -1 )
- {
- char ss[2];
- ss[0] = 'A'+n;
- ss[1] = 0;
- strcat(s, ss);
- }
- else
- {
- strcat(s, " ");
- }
- }
- strcat(s, "\n");
- OutputDebugString(s);
- }
-}
-
-// Tests if a path along a straight line is possible.
-
-bool CTaskGoto::BitmapTestLine(const Math::Vector &start, const Math::Vector &goal,
- float stepAngle, bool bSecond)
-{
- Math::Vector pos, inc;
- float dist, step;
- float distNoB2;
- int i, max, x, y;
-
- if ( m_bmArray == 0 ) return true;
-
- dist = Math::DistanceProjected(start, goal);
- if ( dist == 0.0f ) return true;
- step = BM_DIM_STEP*0.5f;
-
- inc.x = (goal.x-start.x)*step/dist;
- inc.z = (goal.z-start.z)*step/dist;
-
- pos = start;
-
- if ( bSecond )
- {
- x = (int)((pos.x+1600.0f)/BM_DIM_STEP);
- y = (int)((pos.z+1600.0f)/BM_DIM_STEP);
- BitmapSetDot(1, x, y); // puts the flag as the starting point
- }
-
- max = (int)(dist/step);
- if ( max == 0 ) max = 1;
- distNoB2 = BM_DIM_STEP*sqrtf(2.0f)/sinf(stepAngle);
- for ( i=0 ; i<max ; i++ )
- {
- if ( i == max-1 )
- {
- pos = goal; // tests the point of arrival
- }
- else
- {
- pos.x += inc.x;
- pos.z += inc.z;
- }
-
- x = (int)((pos.x+1600.0f)/BM_DIM_STEP);
- y = (int)((pos.z+1600.0f)/BM_DIM_STEP);
-
- if ( bSecond )
- {
- if ( i > 2 && BitmapTestDot(1, x, y) ) return false;
-
- if ( step*(i+1) > distNoB2 && i < max-2 )
- {
- BitmapSetDot(1, x, y);
- }
- }
-
- if ( BitmapTestDot(0, x, y) ) return false;
- }
- return true;
-}
-
-// Adds the objects in the bitmap.
-
-void CTaskGoto::BitmapObject()
-{
- CObject *pObj;
- ObjectType type;
- Math::Vector iPos, oPos;
- float iRadius, oRadius, h;
- int i, j;
-
- m_object->GetCrashSphere(0, iPos, iRadius);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
-
- if ( pObj == m_object ) continue;
- if ( pObj == m_bmFretObject ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- h = m_terrain->RetFloorLevel(pObj->RetPosition(0), false);
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
- {
- h += m_altitude;
- }
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f ) // flying?
- {
- if ( oPos.y-oRadius > h+8.0f ||
- oPos.y+oRadius < h-8.0f ) continue;
- }
- else // crawling?
- {
- if ( oPos.y-oRadius > h+8.0f ) continue;
- }
-
- if ( type == OBJECT_PARA ) oRadius -= 2.0f;
- BitmapSetCircle(oPos, oRadius+iRadius+4.0f);
- }
- }
-}
-
-// Adds a section of land in the bitmap.
-
-void CTaskGoto::BitmapTerrain(const Math::Vector &min, const Math::Vector &max)
-{
- int minx, miny, maxx, maxy;
-
- minx = (int)((min.x+1600.0f)/BM_DIM_STEP);
- miny = (int)((min.z+1600.0f)/BM_DIM_STEP);
- maxx = (int)((max.x+1600.0f)/BM_DIM_STEP);
- maxy = (int)((max.z+1600.0f)/BM_DIM_STEP);
-
- BitmapTerrain(minx, miny, maxx, maxy);
-}
-
-// Adds a section of land in the bitmap.
-
-void CTaskGoto::BitmapTerrain(int minx, int miny, int maxx, int maxy)
-{
- ObjectType type;
- Math::Vector p;
- float aLimit, angle, h;
- int x, y;
- bool bAcceptWater, bFly;
-
- if ( minx > maxx ) Math::Swap(minx, maxx);
- if ( miny > maxy ) Math::Swap(miny, maxy);
-
- if ( minx < 0 ) minx = 0;
- if ( miny < 0 ) miny = 0;
- if ( maxx > m_bmSize-1 ) maxx = m_bmSize-1;
- if ( maxy > m_bmSize-1 ) maxy = m_bmSize-1;
-
- if ( minx > m_bmMinX ) minx = m_bmMinX;
- if ( miny > m_bmMinY ) miny = m_bmMinY;
- if ( maxx < m_bmMaxX ) maxx = m_bmMaxX;
- if ( maxy < m_bmMaxY ) maxy = m_bmMaxY;
-
- if ( minx >= m_bmMinX && maxx <= m_bmMaxX &&
- miny >= m_bmMinY && maxy <= m_bmMaxY ) return;
-
- aLimit = 20.0f*Math::PI/180.0f;
- bAcceptWater = false;
- bFly = false;
-
- type = m_object->RetType();
-
- if ( type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEtg ) // wheels?
- {
- aLimit = 20.0f*Math::PI/180.0f;
- }
-
- if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts ) // caterpillars?
- {
- aLimit = 35.0f*Math::PI/180.0f;
- }
-
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ) // large caterpillars?
- {
- aLimit = 35.0f*Math::PI/180.0f;
- }
-
- if ( type == OBJECT_MOBILEsa ) // submarine caterpillars?
- {
- aLimit = 35.0f*Math::PI/180.0f;
- bAcceptWater = true;
- }
-
- if ( type == OBJECT_MOBILEdr ) // designer caterpillars?
- {
- aLimit = 35.0f*Math::PI/180.0f;
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEft ) // flying?
- {
- aLimit = 15.0f*Math::PI/180.0f;
- bFly = true;
- }
-
- if ( type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILEii ) // insect legs?
- {
- aLimit = 60.0f*Math::PI/180.0f;
- }
-
- for ( y=miny ; y<=maxy ; y++ )
- {
- for ( x=minx ; x<=maxx ; x++ )
- {
- if ( x >= m_bmMinX && x <= m_bmMaxX &&
- y >= m_bmMinY && y <= m_bmMaxY ) continue;
-
- p.x = x*BM_DIM_STEP-1600.0f;
- p.z = y*BM_DIM_STEP-1600.0f;
-
- if ( bFly ) // flying robot?
- {
- h = m_terrain->RetFloorLevel(p, true);
- if ( h >= m_terrain->RetFlyingMaxHeight()-5.0f )
- {
- BitmapSetDot(0, x, y);
- }
- continue;
- }
-
- if ( !bAcceptWater ) // not going underwater?
- {
- h = m_terrain->RetFloorLevel(p, true);
- if ( h < m_water->RetLevel()-2.0f ) // under water (*)?
- {
-//? BitmapSetDot(0, x, y);
- BitmapSetCircle(p, BM_DIM_STEP*1.0f);
- continue;
- }
- }
-
- angle = m_terrain->RetFineSlope(p);
- if ( angle > aLimit )
- {
- BitmapSetDot(0, x, y);
- }
- }
- }
-
- m_bmMinX = minx;
- m_bmMinY = miny;
- m_bmMaxX = maxx;
- m_bmMaxY = maxy; // expanded rectangular area
-}
-
-// (*) Accepts that a robot is 50cm under water, for example Tropica 3!
-
-// Opens an empty bitmap.
-
-bool CTaskGoto::BitmapOpen()
-{
- BitmapClose();
-
- m_bmSize = (int)(3200.0f/BM_DIM_STEP);
- m_bmArray = (unsigned char*)malloc(m_bmSize*m_bmSize/8*2);
- ZeroMemory(m_bmArray, m_bmSize*m_bmSize/8*2);
-
- m_bmOffset = m_bmSize/2;
- m_bmLine = m_bmSize/8;
-
- m_bmMinX = m_bmSize; // non-existent rectangular area
- m_bmMinY = m_bmSize;
- m_bmMaxX = 0;
- m_bmMaxY = 0;
-
- return true;
-}
-
-// Closes the bitmap.
-
-bool CTaskGoto::BitmapClose()
-{
- free(m_bmArray);
- m_bmArray = 0;
- return true;
-}
-
-// Puts a circle in the bitmap.
-
-void CTaskGoto::BitmapSetCircle(const Math::Vector &pos, float radius)
-{
- float d, r;
- int cx, cy, ix, iy;
-
- cx = (int)((pos.x+1600.0f)/BM_DIM_STEP);
- cy = (int)((pos.z+1600.0f)/BM_DIM_STEP);
- r = radius/BM_DIM_STEP;
-
- for ( iy=cy-(int)r ; iy<=cy+(int)r ; iy++ )
- {
- for ( ix=cx-(int)r ; ix<=cx+(int)r ; ix++ )
- {
- d = Math::Point((float)(ix-cx), (float)(iy-cy)).Length();
- if ( d > r ) continue;
- BitmapSetDot(0, ix, iy);
- }
- }
-}
-
-// Removes a circle in the bitmap.
-
-void CTaskGoto::BitmapClearCircle(const Math::Vector &pos, float radius)
-{
- float d, r;
- int cx, cy, ix, iy;
-
- cx = (int)((pos.x+1600.0f)/BM_DIM_STEP);
- cy = (int)((pos.z+1600.0f)/BM_DIM_STEP);
- r = radius/BM_DIM_STEP;
-
- for ( iy=cy-(int)r ; iy<=cy+(int)r ; iy++ )
- {
- for ( ix=cx-(int)r ; ix<=cx+(int)r ; ix++ )
- {
- d = Math::Point((float)(ix-cx), (float)(iy-cy)).Length();
- if ( d > r ) continue;
- BitmapClearDot(0, ix, iy);
- }
- }
-}
-
-// Makes a point in the bitmap.
-// x:y: 0..m_bmSize-1
-
-void CTaskGoto::BitmapSetDot(int rank, int x, int y)
-{
- if ( x < 0 || x >= m_bmSize ||
- y < 0 || y >= m_bmSize ) return;
-
- m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] |= (1<<x%8);
-}
-
-// Removes a point in the bitmap.
-// x:y: 0..m_bmSize-1
-
-void CTaskGoto::BitmapClearDot(int rank, int x, int y)
-{
- if ( x < 0 || x >= m_bmSize ||
- y < 0 || y >= m_bmSize ) return;
-
- m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] &= ~(1<<x%8);
-}
-
-// Tests a point in the bitmap.
-// x:y: 0..m_bmSize-1
-
-bool CTaskGoto::BitmapTestDot(int rank, int x, int y)
-{
- if ( x < 0 || x >= m_bmSize ||
- y < 0 || y >= m_bmSize ) return false;
-
- if ( x < m_bmMinX || x > m_bmMaxX ||
- y < m_bmMinY || y > m_bmMaxY )
- {
- BitmapTerrain(x-10,y-10, x+10,y+10); // remade a layer
- }
-
- return m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] & (1<<x%8);
-}
-
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskgoto.cpp + + +#include <stdio.h> + +#include "object/task/taskgoto.h" + +#include "common/event.h" +#include "common/iman.h" +#include "old/terrain.h" +#include "old/water.h" +#include "math/geometry.h" +#include "physics/physics.h" + + + +const float FLY_DIST_GROUND = 80.0f; // minimum distance to remain on the ground +const float FLY_DEF_HEIGHT = 50.0f; // default flying height +const float BM_DIM_STEP = 5.0f; + + + + +// Object's constructor. + +CTaskGoto::CTaskGoto(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + m_bmArray = 0; +} + +// Object's destructor. + +CTaskGoto::~CTaskGoto() +{ + BitmapClose(); +} + + +// Management of an event. + +bool CTaskGoto::EventProcess(const Event &event) +{ + Math::Vector pos, goal; + Math::Point rot, repulse; + float a, g, dist, linSpeed, cirSpeed, h, hh, factor, dir; + Error ret; + + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + + // Momentarily stationary object (ant on the back)? + if ( m_object->RetFixed() ) + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + return true; + } + + if ( m_error != ERR_OK ) return false; + + if ( m_bWorm ) + { + WormFrame(event.rTime); + } + + if ( m_phase == TGP_BEAMLEAK ) // leak? + { + m_leakTime += event.rTime; + + pos = m_object->RetPosition(0); + + rot.x = m_leakPos.x-pos.x; + rot.y = m_leakPos.z-pos.z; + dist = Math::Point(rot.x, rot.y).Length(); + rot.x /= dist; + rot.y /= dist; + + a = m_object->RetAngleY(0); + g = Math::RotateAngle(rot.x, -rot.y); // CW ! + a = Math::Direction(a, g)*1.0f; + cirSpeed = a; + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + a = Math::NormAngle(a); + if ( a > Math::PI*0.5f && a < Math::PI*1.5f ) + { + linSpeed = 1.0f; // obstacle behind -> advance + cirSpeed = -cirSpeed; + } + else + { + linSpeed = -1.0f; // obstacle in front -> back + } + + if ( m_bLeakRecede ) + { + linSpeed = -1.0f; + cirSpeed = 0.0f; + } + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right + m_physics->SetMotorSpeedX(linSpeed); // advance + return true; + } + + if ( m_phase == TGP_BEAMSEARCH ) // search path? + { + if ( m_bmStep == 0 ) + { + // Frees the area around the departure. + BitmapClearCircle(m_object->RetPosition(0), BM_DIM_STEP*1.8f); + } + + pos = m_object->RetPosition(0); + + if ( m_bmFretObject == 0 ) + { + goal = m_goal; + dist = 0.0f; + } + else + { + goal = m_goalObject; + dist = TAKE_DIST+2.0f; + if ( m_bmFretObject->RetType() == OBJECT_BASE ) dist = 12.0f; + } + + ret = BeamSearch(pos, goal, dist); + if ( ret == ERR_OK ) + { +#if 0 + Math::Vector min, max; + min = pos; + max = m_goal; + if ( min.x > max.x ) Math::Swap(min.x, max.x); + if ( min.z > max.z ) Math::Swap(min.z, max.z); + min.x -= 50.0f; + min.z -= 50.0f; + max.x += 50.0f; + max.z += 50.0f; + BitmapDebug(min, max, m_object->RetPosition(0), m_goal); +#endif + if ( m_physics->RetLand() ) m_phase = TGP_BEAMWCOLD; + else m_phase = TGP_BEAMGOTO; + m_bmIndex = 0; + m_bmWatchDogPos = m_object->RetPosition(0); + m_bmWatchDogTime = 0.0f; + } + if ( ret == ERR_GOTO_IMPOSSIBLE || ret == ERR_GOTO_ITER ) + { +#if 0 + Math::Vector min, max; + min = pos; + max = m_goal; + if ( min.x > max.x ) Math::Swap(min.x, max.x); + if ( min.z > max.z ) Math::Swap(min.z, max.z); + min.x -= 50.0f; + min.z -= 50.0f; + max.x += 50.0f; + max.z += 50.0f; + BitmapDebug(min, max, m_object->RetPosition(0), m_goal); +#endif + m_error = ret; + return false; + } + return true; + } + + if ( m_phase == TGP_BEAMWCOLD ) // expects cooled reactor? + { + return true; + } + + if ( m_phase == TGP_BEAMUP ) // off? + { + m_physics->SetMotorSpeedY(1.0f); // up + return true; + } + + if ( m_phase == TGP_BEAMGOTO ) // goto dot list? (?) + { + if ( m_physics->RetCollision() ) // collision? + { + m_physics->SetCollision(false); // there's more + } + + pos = m_object->RetPosition(0); + + if ( m_physics->RetType() == TYPE_FLYING && m_altitude == 0.0f ) + { + if ( m_physics->RetLand() ) + { + m_physics->SetMotorSpeedY(0.0f); + } + else + { + m_physics->SetMotorSpeedY(-1.0f); + } + } + + if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f ) + { + goal = m_bmPoints[m_bmIndex]; + goal.y = pos.y; + h = m_terrain->RetFloorHeight(goal, true, true); + dist = Math::DistanceProjected(pos, goal); + if ( dist != 0.0f ) // anticipates? + { + linSpeed = m_physics->RetLinMotionX(MO_REASPEED); + linSpeed /= m_physics->RetLinMotionX(MO_ADVSPEED); + goal.x = pos.x + (goal.x-pos.x)*linSpeed*20.0f/dist; + goal.z = pos.z + (goal.z-pos.z)*linSpeed*20.0f/dist; + } + goal.y = pos.y; + hh = m_terrain->RetFloorHeight(goal, true, true); + h = Math::Min(h, hh); + linSpeed = 0.0f; + if ( h < m_altitude-1.0f ) + { + linSpeed = 0.2f+((m_altitude-1.0f)-h)*0.1f; // up + if ( linSpeed > 1.0f ) linSpeed = 1.0f; + } + if ( h > m_altitude+1.0f ) + { + linSpeed = -0.2f; // down + } + m_physics->SetMotorSpeedY(linSpeed); + } + + rot.x = m_bmPoints[m_bmIndex].x-pos.x; + rot.y = m_bmPoints[m_bmIndex].z-pos.z; + dist = Math::Point(rot.x, rot.y).Length(); + rot.x /= dist; + rot.y /= dist; + + a = m_object->RetAngleY(0); + g = Math::RotateAngle(rot.x, -rot.y); // CW ! + cirSpeed = Math::Direction(a, g)*2.0f; + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + if ( dist < 4.0f ) cirSpeed *= dist/4.0f; // so close -> turns less + + if ( m_bmIndex == m_bmTotal ) // last point? + { + linSpeed = dist/(m_physics->RetLinStopLength()*1.5f); + if ( linSpeed > 1.0f ) linSpeed = 1.0f; + } + else + { + linSpeed = 1.0f; // dark without stopping + } + + linSpeed *= 1.0f-(1.0f-0.3f)*fabs(cirSpeed); + +//? if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f ) + if ( fabs(cirSpeed) >= 0.2f ) + { + linSpeed = 0.0f; // turns first, then advance + } + + dist = Math::DistanceProjected(pos, m_bmWatchDogPos); + if ( dist < 1.0f && linSpeed != 0.0f ) + { + m_bmWatchDogTime += event.rTime; + } + else + { + m_bmWatchDogTime = 0.0f; + m_bmWatchDogPos = pos; + } + + if ( m_bmWatchDogTime >= 1.0f ) // immobile for a long time? + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + BeamStart(); // we start all + return true; + } + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right + m_physics->SetMotorSpeedX(linSpeed); // advance + return true; + } + + if ( m_phase == TGP_BEAMDOWN ) // landed? + { + m_physics->SetMotorSpeedY(-0.5f); // tomb + return true; + } + + if ( m_phase == TGP_LAND ) // landed? + { + m_physics->SetMotorSpeedY(-0.5f); // tomb + return true; + } + + if ( m_goalMode == TGG_EXPRESS ) + { + if ( m_crashMode == TGC_HALT ) + { + if ( m_physics->RetCollision() ) // collision? + { + m_physics->SetCollision(false); // there's more + m_error = ERR_STOP; + return true; + } + } + + pos = m_object->RetPosition(0); + + if ( m_altitude > 0.0f ) + { + h = m_terrain->RetFloorHeight(pos, true, true); + linSpeed = 0.0f; + if ( h < m_altitude ) + { + linSpeed = 0.1f; // up + } + if ( h > m_altitude ) + { + linSpeed = -0.2f; // down + } + m_physics->SetMotorSpeedY(linSpeed); + } + + rot.x = m_goal.x-pos.x; + rot.y = m_goal.z-pos.z; + a = m_object->RetAngleY(0); + g = Math::RotateAngle(rot.x, -rot.y); // CW ! + cirSpeed = Math::Direction(a, g)*1.0f; + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right + m_physics->SetMotorSpeedX(1.0f); // advance + return true; + } + + if ( m_phase != TGP_TURN && + m_physics->RetType() == TYPE_FLYING && + m_altitude > 0.0f ) + { + pos = m_object->RetPosition(0); + dist = Math::DistanceProjected(m_goal, pos); + factor = (dist-20.0f)/20.0f; + if ( factor < 0.0f ) factor = 0.0f; + if ( factor > 1.0f ) factor = 1.0f; + + h = m_terrain->RetFloorHeight(m_object->RetPosition(0), true, true); + linSpeed = 0.0f; + if ( h < (m_altitude-0.5f)*factor && factor == 1.0f ) + { + linSpeed = 0.1f; // up + } + if ( h > m_altitude*factor ) + { + linSpeed = -0.2f; // down + } + ComputeFlyingRepulse(dir); + linSpeed += dir*0.2f; + + m_physics->SetMotorSpeedY(linSpeed); + } + + if ( m_phase == TGP_ADVANCE ) // going towards the goal? + { + if ( m_physics->RetCollision() ) // collision? + { + m_physics->SetCollision(false); // there's more + m_time = 0.0f; + m_phase = TGP_CRWAIT; + return true; + } + +#if 0 + pos = m_object->RetPosition(0); + a = m_object->RetAngleY(0); + g = Math::RotateAngle(m_goal.x-pos.x, pos.z-m_goal.z); // CW ! + cirSpeed = Math::Direction(a, g)*1.0f; + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + dist = Math::DistanceProjected(m_goal, pos); + linSpeed = dist/(m_physics->RetLinStopLength()*1.5f); + if ( linSpeed > 1.0f ) linSpeed = 1.0f; + + if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f ) + { + linSpeed = 0.0f; // turns first, then advance + } +#else + pos = m_object->RetPosition(0); + + rot.x = m_goal.x-pos.x; + rot.y = m_goal.z-pos.z; + dist = Math::Point(rot.x, rot.y).Length(); + rot.x /= dist; + rot.y /= dist; + + ComputeRepulse(repulse); + rot.x += repulse.x*2.0f; + rot.y += repulse.y*2.0f; + + a = m_object->RetAngleY(0); + g = Math::RotateAngle(rot.x, -rot.y); // CW ! + cirSpeed = Math::Direction(a, g)*1.0f; +//? if ( m_physics->RetType() == TYPE_FLYING && +//? m_physics->RetLand() ) // flying on the ground? +//? { +//? cirSpeed *= 4.0f; // more fishing +//? } + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + dist = Math::DistanceProjected(m_goal, pos); + linSpeed = dist/(m_physics->RetLinStopLength()*1.5f); +//? if ( m_physics->RetType() == TYPE_FLYING && +//? m_physics->RetLand() ) // flying on the ground? +//? { +//? linSpeed *= 8.0f; // more fishing +//? } + if ( linSpeed > 1.0f ) linSpeed = 1.0f; + + linSpeed *= 1.0f-(1.0f-0.3f)*fabs(cirSpeed); + + if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f ) + { + linSpeed = 0.0f; // turns first, then advance + } +#endif + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right + m_physics->SetMotorSpeedX(linSpeed); // advance + } + + if ( m_phase == TGP_TURN || // turns to the object? + m_phase == TGP_CRTURN || // turns after collision? + m_phase == TGP_CLTURN ) // turns after collision? + { + a = m_object->RetAngleY(0); + g = m_angle; + cirSpeed = Math::Direction(a, g)*1.0f; + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right + } + + if ( m_phase == TGP_CRWAIT || // waits after collision? + m_phase == TGP_CLWAIT ) // waits after collision? + { + m_time += event.rTime; + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + } + + if ( m_phase == TGP_CRADVANCE ) // advance after collision? + { + if ( m_physics->RetCollision() ) // collision? + { + m_physics->SetCollision(false); // there's more + m_time = 0.0f; + m_phase = TGP_CLWAIT; + return true; + } + m_physics->SetMotorSpeedX(0.5f); // advance mollo + } + + if ( m_phase == TGP_CLADVANCE ) // advance after collision? + { + if ( m_physics->RetCollision() ) // collision? + { + m_physics->SetCollision(false); // there's more + m_time = 0.0f; + m_phase = TGP_CRWAIT; + return true; + } + m_physics->SetMotorSpeedX(0.5f); // advance mollo + } + + if ( m_phase == TGP_MOVE ) // final advance? + { + m_bmTimeLimit -= event.rTime; + m_physics->SetMotorSpeedX(1.0f); + } + + return true; +} + + +// Sought a target for the worm. + +CObject* CTaskGoto::WormSearch(Math::Vector &impact) +{ + CObject* pObj; + CObject* pBest = 0; + Math::Vector iPos, oPos; + ObjectType oType; + float distance, min, radius; + int i; + + iPos = m_object->RetPosition(0); + min = 1000000.0f; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + oType = pObj->RetType(); + if ( oType != OBJECT_MOBILEfa && + oType != OBJECT_MOBILEta && + oType != OBJECT_MOBILEwa && + oType != OBJECT_MOBILEia && + oType != OBJECT_MOBILEfc && + oType != OBJECT_MOBILEtc && + oType != OBJECT_MOBILEwc && + oType != OBJECT_MOBILEic && + oType != OBJECT_MOBILEfi && + oType != OBJECT_MOBILEti && + oType != OBJECT_MOBILEwi && + oType != OBJECT_MOBILEii && + oType != OBJECT_MOBILEfs && + oType != OBJECT_MOBILEts && + oType != OBJECT_MOBILEws && + oType != OBJECT_MOBILEis && + oType != OBJECT_MOBILErt && + oType != OBJECT_MOBILErc && + oType != OBJECT_MOBILErr && + oType != OBJECT_MOBILErs && + oType != OBJECT_MOBILEsa && + oType != OBJECT_MOBILEtg && + oType != OBJECT_MOBILEft && + oType != OBJECT_MOBILEtt && + oType != OBJECT_MOBILEwt && + oType != OBJECT_MOBILEit && + oType != OBJECT_MOBILEdr && + oType != OBJECT_DERRICK && + oType != OBJECT_STATION && + oType != OBJECT_FACTORY && + oType != OBJECT_REPAIR && + oType != OBJECT_DESTROYER && + oType != OBJECT_CONVERT && + oType != OBJECT_TOWER && + oType != OBJECT_RESEARCH && + oType != OBJECT_RADAR && + oType != OBJECT_INFO && + oType != OBJECT_ENERGY && + oType != OBJECT_LABO && + oType != OBJECT_NUCLEAR && + oType != OBJECT_PARA && + oType != OBJECT_SAFE && + oType != OBJECT_HUSTON ) continue; + + if ( pObj->RetVirusMode() ) continue; // object infected? + + if ( !pObj->GetCrashSphere(0, oPos, radius) ) continue; + distance = Math::DistanceProjected(oPos, iPos); + if ( distance < min ) + { + min = distance; + pBest = pObj; + } + } + if ( pBest == 0 ) return 0; + + impact = pBest->RetPosition(0); + return pBest; +} + +// Contaminate objects near the worm. + +void CTaskGoto::WormFrame(float rTime) +{ + CObject* pObj; + Math::Vector impact, pos; + float dist; + + m_wormLastTime += rTime; + + if ( m_wormLastTime >= 0.5f ) + { + m_wormLastTime = 0.0f; + + pObj = WormSearch(impact); + if ( pObj != 0 ) + { + pos = m_object->RetPosition(0); + dist = Math::Distance(pos, impact); + if ( dist <= 15.0f ) + { + pObj->SetVirusMode(true); // bam, infected! + } + } + } +} + + + +// Assigns the goal was achieved. +// "dist" is the distance that needs to go far to make a deposit or object. + +Error CTaskGoto::Start(Math::Vector goal, float altitude, + TaskGotoGoal goalMode, TaskGotoCrash crashMode) +{ + Math::Vector pos; + CObject* target; + ObjectType type; + float dist; + int x, y; + + type = m_object->RetType(); + + if ( goalMode == TGG_DEFAULT ) + { + goalMode = TGG_STOP; + if ( type == OBJECT_MOTHER || + type == OBJECT_ANT || + type == OBJECT_SPIDER || + type == OBJECT_WORM ) + { + goalMode = TGG_EXPRESS; + } + } + + if ( crashMode == TGC_DEFAULT ) + { +//? crashMode = TGC_RIGHTLEFT; + crashMode = TGC_BEAM; + if ( type == OBJECT_MOTHER || + type == OBJECT_ANT || + type == OBJECT_SPIDER || + type == OBJECT_WORM || + type == OBJECT_BEE ) + { + crashMode = TGC_HALT; + } + } + + m_altitude = altitude; + m_goalMode = goalMode; + m_crashMode = crashMode; + m_goalObject = goal; + m_goal = goal; + + m_bTake = false; + m_phase = TGP_ADVANCE; + m_error = ERR_OK; + m_try = 0; + m_bmFretObject = 0; + m_bmFinalMove = 0.0f; + + pos = m_object->RetPosition(0); + dist = Math::DistanceProjected(pos, m_goal); + if ( dist < 10.0f && m_crashMode == TGC_BEAM ) + { + m_crashMode = TGC_RIGHTLEFT; + } + + m_bWorm = false; + if ( type == OBJECT_WORM ) + { + m_bWorm = true; + m_wormLastTime = 0.0f; + } + + m_bApprox = false; + if ( type == OBJECT_HUMAN || + type == OBJECT_TECH || + type == OBJECT_MOTHER || + type == OBJECT_ANT || + type == OBJECT_SPIDER || + type == OBJECT_BEE || + type == OBJECT_WORM || + type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs ) + { + m_bApprox = true; + } + + if ( !m_bApprox && m_crashMode != TGC_BEAM ) + { + target = SearchTarget(goal, 1.0f); + if ( target != 0 ) + { + m_goal = target->RetPosition(0); + dist = 0.0f; + if ( !AdjustBuilding(m_goal, 1.0f, dist) ) + { + dist = 0.0f; + AdjustTarget(target, m_goal, dist); + } + m_bTake = true; // object was taken on arrival (final rotation) + } + } + + m_lastDistance = 1000.0f; + m_physics->SetCollision(false); + + if ( m_crashMode == TGC_BEAM ) // with the algorithm of rays? + { + target = SearchTarget(goal, 1.0f); + if ( target != 0 ) + { + m_goal = target->RetPosition(0); + dist = 4.0f; + if ( AdjustBuilding(m_goal, 1.0f, dist) ) + { + m_bmFinalMove = dist; + } + else + { + dist = 4.0f; + if ( AdjustTarget(target, m_goal, dist) ) + { + m_bmFretObject = target; // cargo on the ground + } + else + { + m_bmFinalMove = dist; + } + } + m_bTake = true; // object was taken on arrival (final rotation) + } + + if ( m_physics->RetType() == TYPE_FLYING && m_altitude == 0.0f ) + { + pos = m_object->RetPosition(0); + dist = Math::DistanceProjected(pos, m_goal); + if ( dist > FLY_DIST_GROUND ) // over 20 meters? + { + m_altitude = FLY_DEF_HEIGHT; // default altitude + } + } + + BeamStart(); + + if ( m_bmFretObject == 0 ) + { + x = (int)((m_goal.x+1600.0f)/BM_DIM_STEP); + y = (int)((m_goal.z+1600.0f)/BM_DIM_STEP); + if ( BitmapTestDot(0, x, y) ) // arrival occupied? + { +#if 0 + Math::Vector min, max; + min = m_object->RetPosition(0); + max = m_goal; + if ( min.x > max.x ) Math::Swap(min.x, max.x); + if ( min.z > max.z ) Math::Swap(min.z, max.z); + min.x -= 50.0f; + min.z -= 50.0f; + max.x += 50.0f; + max.z += 50.0f; + BitmapDebug(min, max, m_object->RetPosition(0), m_goal); +#endif + m_error = ERR_GOTO_BUSY; + return m_error; + } + } + } + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskGoto::IsEnded() +{ + Math::Vector pos; + float limit, angle, dist, h, level; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_error != ERR_OK ) return m_error; + + pos = m_object->RetPosition(0); + + if ( m_phase == TGP_BEAMLEAK ) // leak? + { + if ( m_leakTime >= m_leakDelay ) + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + BeamInit(); + m_phase = TGP_BEAMSEARCH; // will seek the path + } + return ERR_CONTINUE; + } + + if ( m_phase == TGP_BEAMSEARCH ) // search path? + { + return ERR_CONTINUE; + } + + if ( m_phase == TGP_BEAMWCOLD ) // expects cool reactor? + { + if ( m_altitude != 0.0f && + m_physics->RetReactorRange() < 1.0f ) return ERR_CONTINUE; + m_phase = TGP_BEAMUP; + } + + if ( m_phase == TGP_BEAMUP ) // off? + { + if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f ) + { + level = m_terrain->RetFloorLevel(pos, true, true); + h = level+m_altitude-20.0f; + limit = m_terrain->RetFlyingMaxHeight(); + if ( h > limit ) h = limit; + if ( pos.y < h-1.0f ) return ERR_CONTINUE; + + m_physics->SetMotorSpeedY(0.0f); // stops the ascent + } + m_phase = TGP_BEAMGOTO; + } + + if ( m_phase == TGP_BEAMGOTO ) // goto dot list ? + { + if ( m_altitude != 0.0f && + m_physics->RetReactorRange() < 0.1f ) // overheating? + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + m_physics->SetMotorSpeedY(-1.0f); // tomb + m_phase = TGP_BEAMWCOLD; + return ERR_CONTINUE; + } + + if ( m_physics->RetLand() ) // on the ground? + { + limit = 1.0f; + } + else // in flight? + { + limit = 2.0f; + if ( m_bmIndex < m_bmTotal ) limit *= 2.0f; // intermediate point + } + if ( m_bApprox ) limit = 2.0f; + + if ( fabs(pos.x - m_bmPoints[m_bmIndex].x) < limit && + fabs(pos.z - m_bmPoints[m_bmIndex].z) < limit ) + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + + m_bmIndex = BeamShortcut(); + + if ( m_bmIndex > m_bmTotal ) + { + m_phase = TGP_BEAMDOWN; + } + } + } + + if ( m_phase == TGP_BEAMDOWN ) // landed? + { + if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f ) + { + if ( !m_physics->RetLand() ) return ERR_CONTINUE; + m_physics->SetMotorSpeedY(0.0f); // stops the descent + + m_altitude = 0.0f; + m_phase = TGP_BEAMGOTO; // advance finely on the ground to finish + m_bmIndex = m_bmTotal; + return ERR_CONTINUE; + } + + if ( m_bTake ) + { + m_angle = Math::RotateAngle(m_goalObject.x-pos.x, pos.z-m_goalObject.z); + m_phase = TGP_TURN; + } + else + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + return ERR_STOP; + } + } + + if ( m_goalMode == TGG_EXPRESS ) + { + dist = Math::DistanceProjected(m_goal, pos); + if ( dist < 10.0f && dist > m_lastDistance ) + { + return ERR_STOP; + } + m_lastDistance = dist; + } + + if ( m_phase == TGP_ADVANCE ) // going towards the goal? + { + if ( m_physics->RetLand() ) limit = 0.1f; // on the ground + else limit = 1.0f; // flying + if ( m_bApprox ) limit = 2.0f; + + if ( fabs(pos.x - m_goal.x) < limit && + fabs(pos.z - m_goal.z) < limit ) + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + m_phase = TGP_LAND; + } + } + + if ( m_phase == TGP_LAND ) // landed? + { + if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f ) + { + if ( !m_physics->RetLand() ) return ERR_CONTINUE; + m_physics->SetMotorSpeedY(0.0f); + } + + if ( m_bTake ) + { + m_angle = Math::RotateAngle(m_goalObject.x-pos.x, pos.z-m_goalObject.z); + m_phase = TGP_TURN; + } + else + { + return ERR_STOP; + } + } + + if ( m_phase == TGP_TURN ) // turns to the object? + { + angle = Math::NormAngle(m_object->RetAngleY(0)); + limit = 0.02f; + if ( m_bApprox ) limit = 0.10f; + if ( fabs(angle-m_angle) < limit ) + { + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + if ( m_bmFinalMove == 0.0f ) return ERR_STOP; + + m_bmFinalPos = m_object->RetPosition(0); + m_bmFinalDist = m_physics->RetLinLength(m_bmFinalMove); + m_bmTimeLimit = m_physics->RetLinTimeLength(fabs(m_bmFinalMove))*1.5f; + if ( m_bmTimeLimit < 0.5f ) m_bmTimeLimit = 0.5f; + m_phase = TGP_MOVE; + } + } + + if ( m_phase == TGP_CRWAIT ) // waits after collision? + { + if ( m_crashMode == TGC_HALT ) + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + m_error = ERR_GENERIC; + return m_error; + } + if ( m_time >= 1.0f ) + { + if ( m_crashMode == TGC_RIGHTLEFT || + m_crashMode == TGC_RIGHT ) angle = Math::PI/2.0f; // 90 deegres to the right + else angle = -Math::PI/2.0f; // 90 deegres to the left + m_angle = Math::NormAngle(m_object->RetAngleY(0)+angle); + m_phase = TGP_CRTURN; +//? m_phase = TGP_ADVANCE; + } + } + + if ( m_phase == TGP_CRTURN ) // turns after collision? + { + angle = Math::NormAngle(m_object->RetAngleY(0)); + limit = 0.1f; + if ( fabs(angle-m_angle) < limit ) + { + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + m_pos = pos; + m_phase = TGP_CRADVANCE; + } + } + + if ( m_phase == TGP_CRADVANCE ) // advance after collision? + { + if ( Math::Distance(pos, m_pos) >= 5.0f ) + { + m_phase = TGP_ADVANCE; + } + } + + if ( m_phase == TGP_CLWAIT ) // waits after collision? + { + if ( m_time >= 1.0f ) + { + if ( m_crashMode == TGC_RIGHTLEFT ) angle = -Math::PI; + if ( m_crashMode == TGC_LEFTRIGHT ) angle = Math::PI; + if ( m_crashMode == TGC_RIGHT ) angle = Math::PI/2.0f; + if ( m_crashMode == TGC_LEFT ) angle = -Math::PI/2.0f; + m_angle = Math::NormAngle(m_object->RetAngleY(0)+angle); + m_phase = TGP_CLTURN; + } + } + + if ( m_phase == TGP_CLTURN ) // turns after collision? + { + angle = Math::NormAngle(m_object->RetAngleY(0)); + limit = 0.1f; + if ( fabs(angle-m_angle) < limit ) + { + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + m_pos = pos; + m_phase = TGP_CLADVANCE; + } + } + + if ( m_phase == TGP_CLADVANCE ) // advance after collision? + { + if ( Math::Distance(pos, m_pos) >= 10.0f ) + { + m_phase = TGP_ADVANCE; + m_try ++; + } + } + + if ( m_phase == TGP_MOVE ) // final advance? + { + if ( m_bmTimeLimit <= 0.0f ) + { + m_physics->SetMotorSpeedX(0.0f); // stops + Abort(); + return ERR_STOP; + } + + dist = Math::Distance(m_bmFinalPos, m_object->RetPosition(0)); + if ( dist < m_bmFinalDist ) return ERR_CONTINUE; + m_physics->SetMotorSpeedX(0.0f); // stops the advance + return ERR_STOP; + } + + return ERR_CONTINUE; +} + + +// Tries the object is the target position. + +CObject* CTaskGoto::SearchTarget(Math::Vector pos, float margin) +{ + CObject *pObj, *pBest; + Math::Vector oPos; + float dist, min; + int i; + + pBest = 0; + min = 1000000.0f; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetActif() ) continue; + if ( pObj->RetTruck() != 0 ) continue; // object transtorted? + + oPos = pObj->RetPosition(0); + dist = Math::DistanceProjected(pos, oPos); + + if ( dist <= margin && dist <= min ) + { + min = dist; + pBest = pObj; + } + } + + return pBest; +} + +// Adjusts the target as a function of the object. +// Returns true if it is cargo laying on the ground, which can be approached from any site. + +bool CTaskGoto::AdjustTarget(CObject* pObj, Math::Vector &pos, float &distance) +{ + ObjectType type; + Character* character; + Math::Matrix* mat; + Math::Vector goal; + float dist, suppl; + + type = m_object->RetType(); + if ( type == OBJECT_BEE || + type == OBJECT_WORM ) + { + pos = pObj->RetPosition(0); + return false; // single approach + } + + type = pObj->RetType(); + + if ( type == OBJECT_FRET || + type == OBJECT_STONE || + type == OBJECT_URANIUM || + type == OBJECT_METAL || + type == OBJECT_POWER || + type == OBJECT_ATOMIC || + type == OBJECT_BULLET || + type == OBJECT_BBOX || + type == OBJECT_KEYa || + type == OBJECT_KEYb || + type == OBJECT_KEYc || + type == OBJECT_KEYd || + type == OBJECT_TNT || + type == OBJECT_SCRAP1 || + type == OBJECT_SCRAP2 || + type == OBJECT_SCRAP3 || + type == OBJECT_SCRAP4 || + type == OBJECT_SCRAP5 || + type == OBJECT_BOMB || + type == OBJECT_RUINmobilew1 || + type == OBJECT_RUINmobilew2 || + type == OBJECT_RUINmobilet1 || + type == OBJECT_RUINmobilet2 || + type == OBJECT_RUINmobiler1 || + type == OBJECT_RUINmobiler2 ) + { + pos = m_object->RetPosition(0); + goal = pObj->RetPosition(0); + dist = Math::Distance(goal, pos); + pos = (pos-goal)*(TAKE_DIST+distance)/dist + goal; + return true; // approach from all sites + } + + if ( type == OBJECT_BASE ) + { + pos = m_object->RetPosition(0); + goal = pObj->RetPosition(0); + dist = Math::Distance(goal, pos); + pos = (pos-goal)*(TAKE_DIST+distance)/dist + goal; + return true; // approach from all sites + } + + if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEta || + type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEis || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEii || + type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs || + type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEtg || + type == OBJECT_MOBILEft || + type == OBJECT_MOBILEtt || + type == OBJECT_MOBILEwt || + type == OBJECT_MOBILEit || + type == OBJECT_MOBILEdr ) + { + character = pObj->RetCharacter(); + pos = character->posPower; + pos.x -= TAKE_DIST+TAKE_DIST_OTHER+distance; + mat = pObj->RetWorldMatrix(0); + pos = Transform(*mat, pos); + return false; // single approach + } + + if ( GetHotPoint(pObj, goal, true, distance, suppl) ) + { + pos = goal; + distance += suppl; + return false; // single approach + } + + pos = pObj->RetPosition(0); + distance = 0.0f; + return false; // single approach +} + +// If you are on an object produced by a building (ore produced by derrick), +// changes the position by report the building. + +bool CTaskGoto::AdjustBuilding(Math::Vector &pos, float margin, float &distance) +{ + CObject* pObj; + Math::Vector oPos; + float dist, suppl; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetActif() ) continue; + if ( pObj->RetTruck() != 0 ) continue; // object transported? + + if ( !GetHotPoint(pObj, oPos, false, 0.0f, suppl) ) continue; + dist = Math::DistanceProjected(pos, oPos); + if ( dist <= margin ) + { + GetHotPoint(pObj, pos, true, distance, suppl); + distance += suppl; + return true; + } + } + return false; +} + +// Returns the item or product or pose is something on a building. + +bool CTaskGoto::GetHotPoint(CObject *pObj, Math::Vector &pos, + bool bTake, float distance, float &suppl) +{ + ObjectType type; + Math::Matrix* mat; + + pos = Math::Vector(0.0f, 0.0f, 0.0f); + suppl = 0.0f; + type = pObj->RetType(); + + if ( type == OBJECT_DERRICK ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 8.0f; + if ( bTake && distance != 0.0f ) suppl = 4.0f; + if ( bTake ) pos.x += TAKE_DIST+distance+suppl; + pos = Transform(*mat, pos); + return true; + } + + if ( type == OBJECT_CONVERT ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 0.0f; + if ( bTake && distance != 0.0f ) suppl = 4.0f; + if ( bTake ) pos.x += TAKE_DIST+distance+suppl; + pos = Transform(*mat, pos); + return true; + } + + if ( type == OBJECT_RESEARCH ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 10.0f; + if ( bTake && distance != 0.0f ) suppl = 2.5f; + if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl; + pos = Transform(*mat, pos); + return true; + } + + if ( type == OBJECT_ENERGY ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 6.0f; + if ( bTake && distance != 0.0f ) suppl = 6.0f; + if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance; + pos = Transform(*mat, pos); + return true; + } + + if ( type == OBJECT_TOWER ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 5.0f; + if ( bTake && distance != 0.0f ) suppl = 4.0f; + if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl; + pos = Transform(*mat, pos); + return true; + } + + if ( type == OBJECT_LABO ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 6.0f; + if ( bTake && distance != 0.0f ) suppl = 6.0f; + if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance; + pos = Transform(*mat, pos); + return true; + } + + if ( type == OBJECT_NUCLEAR ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 22.0f; + if ( bTake && distance != 0.0f ) suppl = 4.0f; + if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl; + pos = Transform(*mat, pos); + return true; + } + + if ( type == OBJECT_FACTORY ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 4.0f; + if ( bTake && distance != 0.0f ) suppl = 6.0f; + if ( bTake ) pos.x += TAKE_DIST+distance+suppl; + pos = Transform(*mat, pos); + return true; + } + + if ( type == OBJECT_STATION ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 4.0f; + if ( bTake && distance != 0.0f ) suppl = 4.0f; + if ( bTake ) pos.x += distance; + pos = Transform(*mat, pos); + return true; + } + + if ( type == OBJECT_REPAIR ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 4.0f; + if ( bTake && distance != 0.0f ) suppl = 4.0f; + if ( bTake ) pos.x += distance; + pos = Transform(*mat, pos); + return true; + } + + if ( type == OBJECT_DESTROYER ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 0.0f; + if ( bTake && distance != 0.0f ) suppl = 4.0f; + if ( bTake ) pos.x += TAKE_DIST+distance+suppl; + pos = Transform(*mat, pos); + return true; + } + + if ( type == OBJECT_PARA && m_physics->RetType() == TYPE_FLYING ) + { + mat = pObj->RetWorldMatrix(0); + if ( bTake && distance != 0.0f ) suppl = 20.0f; + if ( bTake ) pos.x += distance+suppl; + pos = Transform(*mat, pos); + return true; + } + + suppl = 0.0f; + return false; +} + + +// Seeks an object too close that he must flee. + +bool CTaskGoto::LeakSearch(Math::Vector &pos, float &delay) +{ + CObject *pObj, *pObstacle; + Math::Vector iPos, oPos, bPos; + float iRadius, oRadius, bRadius, dist, min, dir; + int i, j; + + if ( !m_physics->RetLand() ) return false; // in flight? + + m_object->GetCrashSphere(0, iPos, iRadius); + + min = 100000.0f; + bRadius = 0.0f; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; + if ( !pObj->RetActif() ) continue; + if ( pObj->RetTruck() != 0 ) continue; // object transported? + + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) + { + dist = Math::DistanceProjected(oPos, iPos); + if ( dist < min ) + { + min = dist; + bPos = oPos; + bRadius = oRadius; + pObstacle = pObj; + } + } + } + if ( min > iRadius+bRadius+4.0f ) return false; + + m_bLeakRecede = false; + + dist = 4.0f; + dir = 1.0f; + if ( pObstacle->RetType() == OBJECT_FACTORY ) + { + dist = 16.0f; + dir = -1.0f; + m_bLeakRecede = true; // simply recoils + } + + pos = bPos; + delay = m_physics->RetLinTimeLength(dist, dir); + return true; +} + + +// Calculates the force of repulsion due to obstacles. +// The vector length rendered is between 0 and 1. + +void CTaskGoto::ComputeRepulse(Math::Point &dir) +{ +#if 0 + Math::Vector iPos, oPos; + Math::Point repulse; + CObject *pObj; + float dist, iRadius, oRadius; + int i; + + dir.x = 0.0f; + dir.y = 0.0f; + + m_object->GetCrashSphere(0, iPos, iRadius); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; + if ( pObj->RetTruck() != 0 ) continue; + + oPos = pObj->RetPosition(0); + dist = Math::Distance(oPos, m_goalObject); + if ( dist <= 1.0f ) continue; + + pObj->GetGlobalSphere(oPos, oRadius); + oRadius += iRadius+m_physics->RetLinStopLength()*1.1f; + dist = Math::DistanceProjected(oPos, iPos); + if ( dist <= oRadius ) + { + repulse.x = iPos.x-oPos.x; + repulse.y = iPos.z-oPos.z; + +//? dist = 0.2f-(0.2f*dist/oRadius); + dist = powf(dist/oRadius, 2.0f); + dist = 0.2f-0.2f*dist; + repulse.x *= dist; + repulse.y *= dist; +//? repulse.x /= dist; +//? repulse.y /= dist; + + dir.x += repulse.x; + dir.y += repulse.y; + } + } +#else + ObjectType iType, oType; + Math::Vector iPos, oPos; + Math::Point repulse; + CObject *pObj; + float gDist, add, addi, fac, dist, iRadius, oRadius; + int i, j; + bool bAlien; + + dir.x = 0.0f; + dir.y = 0.0f; + + // The worm goes everywhere and through everything! + iType = m_object->RetType(); + if ( iType == OBJECT_WORM ) return; + + m_object->GetCrashSphere(0, iPos, iRadius); + gDist = Math::Distance(iPos, m_goal); + + add = m_physics->RetLinStopLength()*1.1f; // braking distance + fac = 2.0f; + + if ( iType == OBJECT_MOBILEwa || + iType == OBJECT_MOBILEwc || + iType == OBJECT_MOBILEwi || + iType == OBJECT_MOBILEws || + iType == OBJECT_MOBILEwt ) // wheels? + { + add = 5.0f; + fac = 1.5f; + } + if ( iType == OBJECT_MOBILEta || + iType == OBJECT_MOBILEtc || + iType == OBJECT_MOBILEti || + iType == OBJECT_MOBILEts || + iType == OBJECT_MOBILEtt || + iType == OBJECT_MOBILEdr ) // caterpillars? + { + add = 4.0f; + fac = 1.5f; + } + if ( iType == OBJECT_MOBILEfa || + iType == OBJECT_MOBILEfc || + iType == OBJECT_MOBILEfi || + iType == OBJECT_MOBILEfs || + iType == OBJECT_MOBILEft ) // flying? + { + if ( m_physics->RetLand() ) + { + add = 5.0f; + fac = 1.5f; + } + else + { + add = 10.0f; + fac = 1.5f; + } + } + if ( iType == OBJECT_MOBILEia || + iType == OBJECT_MOBILEic || + iType == OBJECT_MOBILEii || + iType == OBJECT_MOBILEis || + iType == OBJECT_MOBILEit ) // legs? + { + add = 4.0f; + fac = 1.5f; + } + if ( iType == OBJECT_BEE ) // wasp? + { + if ( m_physics->RetLand() ) + { + add = 3.0f; + fac = 1.5f; + } + else + { + add = 5.0f; + fac = 1.5f; + } + } + + bAlien = false; + if ( iType == OBJECT_MOTHER || + iType == OBJECT_ANT || + iType == OBJECT_SPIDER || + iType == OBJECT_BEE || + iType == OBJECT_WORM ) + { + bAlien = true; + } + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; + if ( pObj->RetTruck() != 0 ) continue; + + oType = pObj->RetType(); + + if ( oType == OBJECT_WORM ) continue; + + if ( bAlien ) + { + if ( oType == OBJECT_STONE || + oType == OBJECT_URANIUM || + oType == OBJECT_METAL || + oType == OBJECT_POWER || + oType == OBJECT_ATOMIC || + oType == OBJECT_BULLET || + oType == OBJECT_BBOX || + oType == OBJECT_KEYa || + oType == OBJECT_KEYb || + oType == OBJECT_KEYc || + oType == OBJECT_KEYd || + oType == OBJECT_TNT || + oType == OBJECT_SCRAP1 || + oType == OBJECT_SCRAP2 || + oType == OBJECT_SCRAP3 || + oType == OBJECT_SCRAP4 || + oType == OBJECT_SCRAP5 || + oType == OBJECT_BOMB || + (oType >= OBJECT_PLANT0 && + oType <= OBJECT_PLANT19 ) || + (oType >= OBJECT_MUSHROOM0 && + oType <= OBJECT_MUSHROOM9 ) ) continue; + } + + addi = add; + if ( iType == OBJECT_BEE && + oType == OBJECT_BEE ) + { + addi = 2.0f; // between wasps, do not annoy too much + } + + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) + { + if ( oPos.y-oRadius > iPos.y+iRadius ) continue; + if ( oPos.y+oRadius < iPos.y-iRadius ) continue; + + dist = Math::Distance(oPos, m_goal); + if ( dist <= 1.0f ) continue; // on purpose? + + oRadius += iRadius+addi; + dist = Math::DistanceProjected(oPos, iPos); + if ( dist > gDist ) continue; // beyond the goal? + if ( dist <= oRadius ) + { + repulse.x = iPos.x-oPos.x; + repulse.y = iPos.z-oPos.z; + + dist = powf(dist/oRadius, fac); + dist = 0.2f-0.2f*dist; + repulse.x *= dist; + repulse.y *= dist; + + dir.x += repulse.x; + dir.y += repulse.y; + } + } + } +#endif +} + +// Calculates the force of vertical repulsion according to barriers. +// The vector length is made​between -1 and 1. + +void CTaskGoto::ComputeFlyingRepulse(float &dir) +{ + ObjectType oType; + Math::Vector iPos, oPos; + CObject *pObj; + float add, fac, dist, iRadius, oRadius, repulse; + int i, j; + + m_object->GetCrashSphere(0, iPos, iRadius); + + add = 0.0f; + fac = 1.5f; + dir = 0.0f; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; + if ( pObj->RetTruck() != 0 ) continue; + + oType = pObj->RetType(); + + if ( oType == OBJECT_WORM ) continue; + + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) + { + oRadius += iRadius+add; + dist = Math::DistanceProjected(oPos, iPos); + if ( dist <= oRadius ) + { + repulse = iPos.y-oPos.y; + + dist = powf(dist/oRadius, fac); + dist = 0.2f-0.2f*dist; + repulse *= dist; + + dir += repulse; + } + } + } + + if ( dir < -1.0f ) dir = -1.0f; + if ( dir > 1.0f ) dir = 1.0f; +} + + + +// Among all of the following, seek if there is one allowing to go directly to the crow flies. +// If yes, skip all the unnecessary intermediate points. + +int CTaskGoto::BeamShortcut() +{ + int i; + + for ( i=m_bmTotal ; i>=m_bmIndex+2 ; i-- ) // tries from the last + { + if ( BitmapTestLine(m_bmPoints[m_bmIndex], m_bmPoints[i], 0.0f, false) ) + { + return i; // bingo, found + } + } + + return m_bmIndex+1; // simply goes to the next +} + +// That's the big start. + +void CTaskGoto::BeamStart() +{ + Math::Vector min, max; + + BitmapOpen(); + BitmapObject(); + + min = m_object->RetPosition(0); + max = m_goal; + if ( min.x > max.x ) Math::Swap(min.x, max.x); + if ( min.z > max.z ) Math::Swap(min.z, max.z); + min.x -= 10.0f*BM_DIM_STEP; + min.z -= 10.0f*BM_DIM_STEP; + max.x += 10.0f*BM_DIM_STEP; + max.z += 10.0f*BM_DIM_STEP; + BitmapTerrain(min, max); + + if ( LeakSearch(m_leakPos, m_leakDelay) ) + { + m_phase = TGP_BEAMLEAK; // must first leak + m_leakTime = 0.0f; + } + else + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + BeamInit(); + m_phase = TGP_BEAMSEARCH; // will seek the path + } +} + +// Initialization before the first BeamSearch. + +void CTaskGoto::BeamInit() +{ + int i; + + for ( i=0 ; i<MAXPOINTS ; i++ ) + { + m_bmIter[i] = -1; + } + m_bmStep = 0; +} + +// Calculates points and passes to go from start to goal. +// Returns: +// ERR_OK if it's good +// ERR_GOTO_IMPOSSIBLE if impossible +// ERR_GOTO_ITER if aborts because too many recursions +// ERR_CONTINUE if not done yet +// goalRadius: distance at which we must approach the goal + +Error CTaskGoto::BeamSearch(const Math::Vector &start, const Math::Vector &goal, + float goalRadius) +{ + float step, len; + int nbIter; + + m_bmStep ++; + + len = Math::DistanceProjected(start, goal); + step = len/5.0f; + if ( step < BM_DIM_STEP*2.1f ) step = BM_DIM_STEP*2.1f; + if ( step > 20.0f ) step = 20.0f; + nbIter = 200; // in order not to lower the framerate + m_bmIterCounter = 0; + return BeamExplore(start, start, goal, goalRadius, 165.0f*Math::PI/180.0f, 22, step, 0, nbIter); +} + +// prevPos: previous position +// curPos: current position +// goalPos: position that seeks to achieve +// angle: angle to the goal we explores +// nbDiv: number of subdivisions being done with angle +// step length of a step +// i number of recursions made +// nbIter maximum number of iterations you have the right to make before temporarily interrupt + +Error CTaskGoto::BeamExplore(const Math::Vector &prevPos, const Math::Vector &curPos, + const Math::Vector &goalPos, float goalRadius, + float angle, int nbDiv, float step, + int i, int nbIter) +{ + Math::Vector newPos; + Error ret; + int iDiv, iClear, iLar; + + iLar = 0; + if ( i >= MAXPOINTS ) return ERR_GOTO_ITER; // too many recursions + + if ( m_bmIter[i] == -1 ) + { + m_bmIter[i] = 0; + + if ( i == 0 ) + { + m_bmPoints[i] = curPos; + } + else + { + if ( !BitmapTestLine(prevPos, curPos, angle/nbDiv, true) ) return ERR_GOTO_IMPOSSIBLE; + + m_bmPoints[i] = curPos; + + if ( Math::DistanceProjected(curPos, goalPos)-goalRadius <= step ) + { + if ( goalRadius == 0.0f ) + { + newPos = goalPos; + } + else + { + newPos = BeamPoint(curPos, goalPos, 0, Math::DistanceProjected(curPos, goalPos)-goalRadius); + } + if ( BitmapTestLine(curPos, newPos, angle/nbDiv, false) ) + { + m_bmPoints[i+1] = newPos; + m_bmTotal = i+1; + return ERR_OK; + } + } + } + } + + if ( iLar >= m_bmIter[i] ) + { + newPos = BeamPoint(curPos, goalPos, 0, step); + ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter); + if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret; + m_bmIter[i] = iLar+1; + for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1; + m_bmIterCounter ++; + if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE; + } + iLar ++; + + for ( iDiv=1 ; iDiv<=nbDiv ; iDiv++ ) + { + if ( iLar >= m_bmIter[i] ) + { + newPos = BeamPoint(curPos, goalPos, angle*iDiv/nbDiv, step); + ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter); + if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret; + m_bmIter[i] = iLar+1; + for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1; + m_bmIterCounter ++; + if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE; + } + iLar ++; + + if ( iLar >= m_bmIter[i] ) + { + newPos = BeamPoint(curPos, goalPos, -angle*iDiv/nbDiv, step); + ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter); + if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret; + m_bmIter[i] = iLar+1; + for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1; + m_bmIterCounter ++; + if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE; + } + iLar ++; + } + + return ERR_GOTO_IMPOSSIBLE; +} + +// Is a right "start-goal". Calculates the point located at the distance "step" +// from the point "start" and an angle "angle" with the right. + +Math::Vector CTaskGoto::BeamPoint(const Math::Vector &startPoint, + const Math::Vector &goalPoint, + float angle, float step) +{ + Math::Vector resPoint; + float goalAngle; + + goalAngle = Math::RotateAngle(goalPoint.x-startPoint.x, goalPoint.z-startPoint.z); + + resPoint.x = startPoint.x + cosf(goalAngle+angle)*step; + resPoint.z = startPoint.z + sinf(goalAngle+angle)*step; + resPoint.y = 0.0f; + + return resPoint; +} + +// Displays a bitmap part. + +void CTaskGoto::BitmapDebug(const Math::Vector &min, const Math::Vector &max, + const Math::Vector &start, const Math::Vector &goal) +{ + int minx, miny, maxx, maxy, x, y, i ,n; + char s[2000]; + + minx = (int)((min.x+1600.0f)/BM_DIM_STEP); + miny = (int)((min.z+1600.0f)/BM_DIM_STEP); + maxx = (int)((max.x+1600.0f)/BM_DIM_STEP); + maxy = (int)((max.z+1600.0f)/BM_DIM_STEP); + + if ( minx > maxx ) Math::Swap(minx, maxx); + if ( miny > maxy ) Math::Swap(miny, maxy); + + OutputDebugString("Bitmap :\n"); + for ( y=miny ; y<=maxy ; y++ ) + { + s[0] = 0; + for ( x=minx ; x<=maxx ; x++ ) + { + n = -1; + for ( i=0 ; i<=m_bmTotal ; i++ ) + { + if ( x == (int)((m_bmPoints[i].x+1600.0f)/BM_DIM_STEP) && + y == (int)((m_bmPoints[i].z+1600.0f)/BM_DIM_STEP) ) + { + n = i; + break; + } + } + + if ( BitmapTestDot(0, x,y) ) + { + strcat(s, "o"); + } + else + { + if ( BitmapTestDot(1, x,y) ) + { + strcat(s, "-"); + } + else + { + strcat(s, "."); + } + } + + if ( x == (int)((start.x+1600.0f)/BM_DIM_STEP) && + y == (int)((start.z+1600.0f)/BM_DIM_STEP) ) + { + strcat(s, "s"); + } + else + if ( x == (int)((goal.x+1600.0f)/BM_DIM_STEP) && + y == (int)((goal.z+1600.0f)/BM_DIM_STEP) ) + { + strcat(s, "g"); + } + else + if ( n != -1 ) + { + char ss[2]; + ss[0] = 'A'+n; + ss[1] = 0; + strcat(s, ss); + } + else + { + strcat(s, " "); + } + } + strcat(s, "\n"); + OutputDebugString(s); + } +} + +// Tests if a path along a straight line is possible. + +bool CTaskGoto::BitmapTestLine(const Math::Vector &start, const Math::Vector &goal, + float stepAngle, bool bSecond) +{ + Math::Vector pos, inc; + float dist, step; + float distNoB2; + int i, max, x, y; + + if ( m_bmArray == 0 ) return true; + + dist = Math::DistanceProjected(start, goal); + if ( dist == 0.0f ) return true; + step = BM_DIM_STEP*0.5f; + + inc.x = (goal.x-start.x)*step/dist; + inc.z = (goal.z-start.z)*step/dist; + + pos = start; + + if ( bSecond ) + { + x = (int)((pos.x+1600.0f)/BM_DIM_STEP); + y = (int)((pos.z+1600.0f)/BM_DIM_STEP); + BitmapSetDot(1, x, y); // puts the flag as the starting point + } + + max = (int)(dist/step); + if ( max == 0 ) max = 1; + distNoB2 = BM_DIM_STEP*sqrtf(2.0f)/sinf(stepAngle); + for ( i=0 ; i<max ; i++ ) + { + if ( i == max-1 ) + { + pos = goal; // tests the point of arrival + } + else + { + pos.x += inc.x; + pos.z += inc.z; + } + + x = (int)((pos.x+1600.0f)/BM_DIM_STEP); + y = (int)((pos.z+1600.0f)/BM_DIM_STEP); + + if ( bSecond ) + { + if ( i > 2 && BitmapTestDot(1, x, y) ) return false; + + if ( step*(i+1) > distNoB2 && i < max-2 ) + { + BitmapSetDot(1, x, y); + } + } + + if ( BitmapTestDot(0, x, y) ) return false; + } + return true; +} + +// Adds the objects in the bitmap. + +void CTaskGoto::BitmapObject() +{ + CObject *pObj; + ObjectType type; + Math::Vector iPos, oPos; + float iRadius, oRadius, h; + int i, j; + + m_object->GetCrashSphere(0, iPos, iRadius); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + + if ( pObj == m_object ) continue; + if ( pObj == m_bmFretObject ) continue; + if ( pObj->RetTruck() != 0 ) continue; + + h = m_terrain->RetFloorLevel(pObj->RetPosition(0), false); + if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f ) + { + h += m_altitude; + } + + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) + { + if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f ) // flying? + { + if ( oPos.y-oRadius > h+8.0f || + oPos.y+oRadius < h-8.0f ) continue; + } + else // crawling? + { + if ( oPos.y-oRadius > h+8.0f ) continue; + } + + if ( type == OBJECT_PARA ) oRadius -= 2.0f; + BitmapSetCircle(oPos, oRadius+iRadius+4.0f); + } + } +} + +// Adds a section of land in the bitmap. + +void CTaskGoto::BitmapTerrain(const Math::Vector &min, const Math::Vector &max) +{ + int minx, miny, maxx, maxy; + + minx = (int)((min.x+1600.0f)/BM_DIM_STEP); + miny = (int)((min.z+1600.0f)/BM_DIM_STEP); + maxx = (int)((max.x+1600.0f)/BM_DIM_STEP); + maxy = (int)((max.z+1600.0f)/BM_DIM_STEP); + + BitmapTerrain(minx, miny, maxx, maxy); +} + +// Adds a section of land in the bitmap. + +void CTaskGoto::BitmapTerrain(int minx, int miny, int maxx, int maxy) +{ + ObjectType type; + Math::Vector p; + float aLimit, angle, h; + int x, y; + bool bAcceptWater, bFly; + + if ( minx > maxx ) Math::Swap(minx, maxx); + if ( miny > maxy ) Math::Swap(miny, maxy); + + if ( minx < 0 ) minx = 0; + if ( miny < 0 ) miny = 0; + if ( maxx > m_bmSize-1 ) maxx = m_bmSize-1; + if ( maxy > m_bmSize-1 ) maxy = m_bmSize-1; + + if ( minx > m_bmMinX ) minx = m_bmMinX; + if ( miny > m_bmMinY ) miny = m_bmMinY; + if ( maxx < m_bmMaxX ) maxx = m_bmMaxX; + if ( maxy < m_bmMaxY ) maxy = m_bmMaxY; + + if ( minx >= m_bmMinX && maxx <= m_bmMaxX && + miny >= m_bmMinY && maxy <= m_bmMaxY ) return; + + aLimit = 20.0f*Math::PI/180.0f; + bAcceptWater = false; + bFly = false; + + type = m_object->RetType(); + + if ( type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEwt || + type == OBJECT_MOBILEtg ) // wheels? + { + aLimit = 20.0f*Math::PI/180.0f; + } + + if ( type == OBJECT_MOBILEta || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEts ) // caterpillars? + { + aLimit = 35.0f*Math::PI/180.0f; + } + + if ( type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs ) // large caterpillars? + { + aLimit = 35.0f*Math::PI/180.0f; + } + + if ( type == OBJECT_MOBILEsa ) // submarine caterpillars? + { + aLimit = 35.0f*Math::PI/180.0f; + bAcceptWater = true; + } + + if ( type == OBJECT_MOBILEdr ) // designer caterpillars? + { + aLimit = 35.0f*Math::PI/180.0f; + } + + if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEft ) // flying? + { + aLimit = 15.0f*Math::PI/180.0f; + bFly = true; + } + + if ( type == OBJECT_MOBILEia || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEis || + type == OBJECT_MOBILEii ) // insect legs? + { + aLimit = 60.0f*Math::PI/180.0f; + } + + for ( y=miny ; y<=maxy ; y++ ) + { + for ( x=minx ; x<=maxx ; x++ ) + { + if ( x >= m_bmMinX && x <= m_bmMaxX && + y >= m_bmMinY && y <= m_bmMaxY ) continue; + + p.x = x*BM_DIM_STEP-1600.0f; + p.z = y*BM_DIM_STEP-1600.0f; + + if ( bFly ) // flying robot? + { + h = m_terrain->RetFloorLevel(p, true); + if ( h >= m_terrain->RetFlyingMaxHeight()-5.0f ) + { + BitmapSetDot(0, x, y); + } + continue; + } + + if ( !bAcceptWater ) // not going underwater? + { + h = m_terrain->RetFloorLevel(p, true); + if ( h < m_water->RetLevel()-2.0f ) // under water (*)? + { +//? BitmapSetDot(0, x, y); + BitmapSetCircle(p, BM_DIM_STEP*1.0f); + continue; + } + } + + angle = m_terrain->RetFineSlope(p); + if ( angle > aLimit ) + { + BitmapSetDot(0, x, y); + } + } + } + + m_bmMinX = minx; + m_bmMinY = miny; + m_bmMaxX = maxx; + m_bmMaxY = maxy; // expanded rectangular area +} + +// (*) Accepts that a robot is 50cm under water, for example Tropica 3! + +// Opens an empty bitmap. + +bool CTaskGoto::BitmapOpen() +{ + BitmapClose(); + + m_bmSize = (int)(3200.0f/BM_DIM_STEP); + m_bmArray = (unsigned char*)malloc(m_bmSize*m_bmSize/8*2); + ZeroMemory(m_bmArray, m_bmSize*m_bmSize/8*2); + + m_bmOffset = m_bmSize/2; + m_bmLine = m_bmSize/8; + + m_bmMinX = m_bmSize; // non-existent rectangular area + m_bmMinY = m_bmSize; + m_bmMaxX = 0; + m_bmMaxY = 0; + + return true; +} + +// Closes the bitmap. + +bool CTaskGoto::BitmapClose() +{ + free(m_bmArray); + m_bmArray = 0; + return true; +} + +// Puts a circle in the bitmap. + +void CTaskGoto::BitmapSetCircle(const Math::Vector &pos, float radius) +{ + float d, r; + int cx, cy, ix, iy; + + cx = (int)((pos.x+1600.0f)/BM_DIM_STEP); + cy = (int)((pos.z+1600.0f)/BM_DIM_STEP); + r = radius/BM_DIM_STEP; + + for ( iy=cy-(int)r ; iy<=cy+(int)r ; iy++ ) + { + for ( ix=cx-(int)r ; ix<=cx+(int)r ; ix++ ) + { + d = Math::Point((float)(ix-cx), (float)(iy-cy)).Length(); + if ( d > r ) continue; + BitmapSetDot(0, ix, iy); + } + } +} + +// Removes a circle in the bitmap. + +void CTaskGoto::BitmapClearCircle(const Math::Vector &pos, float radius) +{ + float d, r; + int cx, cy, ix, iy; + + cx = (int)((pos.x+1600.0f)/BM_DIM_STEP); + cy = (int)((pos.z+1600.0f)/BM_DIM_STEP); + r = radius/BM_DIM_STEP; + + for ( iy=cy-(int)r ; iy<=cy+(int)r ; iy++ ) + { + for ( ix=cx-(int)r ; ix<=cx+(int)r ; ix++ ) + { + d = Math::Point((float)(ix-cx), (float)(iy-cy)).Length(); + if ( d > r ) continue; + BitmapClearDot(0, ix, iy); + } + } +} + +// Makes a point in the bitmap. +// x:y: 0..m_bmSize-1 + +void CTaskGoto::BitmapSetDot(int rank, int x, int y) +{ + if ( x < 0 || x >= m_bmSize || + y < 0 || y >= m_bmSize ) return; + + m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] |= (1<<x%8); +} + +// Removes a point in the bitmap. +// x:y: 0..m_bmSize-1 + +void CTaskGoto::BitmapClearDot(int rank, int x, int y) +{ + if ( x < 0 || x >= m_bmSize || + y < 0 || y >= m_bmSize ) return; + + m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] &= ~(1<<x%8); +} + +// Tests a point in the bitmap. +// x:y: 0..m_bmSize-1 + +bool CTaskGoto::BitmapTestDot(int rank, int x, int y) +{ + if ( x < 0 || x >= m_bmSize || + y < 0 || y >= m_bmSize ) return false; + + if ( x < m_bmMinX || x > m_bmMaxX || + y < m_bmMinY || y > m_bmMaxY ) + { + BitmapTerrain(x-10,y-10, x+10,y+10); // remade a layer + } + + return m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] & (1<<x%8); +} + + diff --git a/src/object/task/taskgoto.h b/src/object/task/taskgoto.h index ae83459..1382d4c 100644 --- a/src/object/task/taskgoto.h +++ b/src/object/task/taskgoto.h @@ -1,157 +1,157 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskgoto.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-const int MAXPOINTS = 500;
-
-
-
-enum TaskGotoGoal
-{
- TGG_DEFAULT = -1, // default mode
- TGG_STOP = 0, // goes to destination pausing with precision
- TGG_EXPRESS = 1, // goes to destination without stopping
-};
-
-enum TaskGotoCrash
-{
- TGC_DEFAULT = -1, // default mode
- TGC_HALT = 0, // stops if collision
- TGC_RIGHTLEFT = 1, // right-left
- TGC_LEFTRIGHT = 2, // left-right
- TGC_LEFT = 3, // left
- TGC_RIGHT = 4, // right
- TGC_BEAM = 5, // algorithm "sunlight"
-};
-
-
-enum TaskGotoPhase
-{
- TGP_ADVANCE = 1, // advance
- TGP_LAND = 2, // landed
- TGP_TURN = 3, // turns to finish
- TGP_MOVE = 4, // advance to finish
- TGP_CRWAIT = 5, // waits after collision
- TGP_CRTURN = 6, // turns right after collision
- TGP_CRADVANCE = 7, // advance to the right after collision
- TGP_CLWAIT = 8, // waits after collision
- TGP_CLTURN = 9, // turns left after collision
- TGP_CLADVANCE = 10, // advance to the left after collision
- TGP_BEAMLEAK = 11, // beam: leak (leaking)
- TGP_BEAMSEARCH = 12, // beam: search
- TGP_BEAMWCOLD = 13, // beam: expects cool reactor
- TGP_BEAMUP = 14, // beam: off
- TGP_BEAMGOTO = 15, // beam: goto dot list
- TGP_BEAMDOWN = 16, // beam: landed
-};
-
-
-
-class CTaskGoto : public CTask
-{
-public:
- CTaskGoto(CInstanceManager* iMan, CObject* object);
- ~CTaskGoto();
-
- bool EventProcess(const Event &event);
-
- Error Start(Math::Vector goal, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode);
- Error IsEnded();
-
-protected:
- CObject* WormSearch(Math::Vector &impact);
- void WormFrame(float rTime);
- CObject* SearchTarget(Math::Vector pos, float margin);
- bool AdjustTarget(CObject* pObj, Math::Vector &pos, float &distance);
- bool AdjustBuilding(Math::Vector &pos, float margin, float &distance);
- bool GetHotPoint(CObject *pObj, Math::Vector &pos, bool bTake, float distance, float &suppl);
- bool LeakSearch(Math::Vector &pos, float &delay);
- void ComputeRepulse(Math::Point &dir);
- void ComputeFlyingRepulse(float &dir);
-
- int BeamShortcut();
- void BeamStart();
- void BeamInit();
- Error BeamSearch(const Math::Vector &start, const Math::Vector &goal, float goalRadius);
- Error BeamExplore(const Math::Vector &prevPos, const Math::Vector &curPos, const Math::Vector &goalPos, float goalRadius, float angle, int nbDiv, float step, int i, int nbIter);
- Math::Vector BeamPoint(const Math::Vector &startPoint, const Math::Vector &goalPoint, float angle, float step);
-
- void BitmapDebug(const Math::Vector &min, const Math::Vector &max, const Math::Vector &start, const Math::Vector &goal);
- bool BitmapTestLine(const Math::Vector &start, const Math::Vector &goal, float stepAngle, bool bSecond);
- void BitmapObject();
- void BitmapTerrain(const Math::Vector &min, const Math::Vector &max);
- void BitmapTerrain(int minx, int miny, int maxx, int maxy);
- bool BitmapOpen();
- bool BitmapClose();
- void BitmapSetCircle(const Math::Vector &pos, float radius);
- void BitmapClearCircle(const Math::Vector &pos, float radius);
- void BitmapSetDot(int rank, int x, int y);
- void BitmapClearDot(int rank, int x, int y);
- bool BitmapTestDot(int rank, int x, int y);
-
-protected:
- Math::Vector m_goal;
- Math::Vector m_goalObject;
- float m_angle;
- float m_altitude;
- TaskGotoCrash m_crashMode;
- TaskGotoGoal m_goalMode;
- TaskGotoPhase m_phase;
- int m_try;
- Error m_error;
- bool m_bTake;
- float m_stopLength; // braking distance
- float m_time;
- Math::Vector m_pos;
- bool m_bWorm;
- bool m_bApprox;
- float m_wormLastTime;
- float m_lastDistance;
-
- int m_bmSize; // width or height of the table
- int m_bmOffset; // m_bmSize/2
- int m_bmLine; // increment line m_bmSize/8
- unsigned char* m_bmArray; // bit table
- int m_bmMinX, m_bmMinY;
- int m_bmMaxX, m_bmMaxY;
- int m_bmTotal; // number of points in m_bmPoints
- int m_bmIndex; // index in m_bmPoints
- Math::Vector m_bmPoints[MAXPOINTS+2];
- char m_bmIter[MAXPOINTS+2];
- int m_bmIterCounter;
- CObject* m_bmFretObject;
- float m_bmFinalMove; // final advance distance
- float m_bmFinalDist; // effective distance to advance
- Math::Vector m_bmFinalPos; // initial position before advance
- float m_bmTimeLimit;
- int m_bmStep;
- Math::Vector m_bmWatchDogPos;
- float m_bmWatchDogTime;
- Math::Vector m_leakPos; // initial position leak
- float m_leakDelay;
- float m_leakTime;
- bool m_bLeakRecede;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskgoto.h + +#pragma once + + +#include "object/task/task.h" +#include "math/vector.h" + + + +const int MAXPOINTS = 500; + + + +enum TaskGotoGoal +{ + TGG_DEFAULT = -1, // default mode + TGG_STOP = 0, // goes to destination pausing with precision + TGG_EXPRESS = 1, // goes to destination without stopping +}; + +enum TaskGotoCrash +{ + TGC_DEFAULT = -1, // default mode + TGC_HALT = 0, // stops if collision + TGC_RIGHTLEFT = 1, // right-left + TGC_LEFTRIGHT = 2, // left-right + TGC_LEFT = 3, // left + TGC_RIGHT = 4, // right + TGC_BEAM = 5, // algorithm "sunlight" +}; + + +enum TaskGotoPhase +{ + TGP_ADVANCE = 1, // advance + TGP_LAND = 2, // landed + TGP_TURN = 3, // turns to finish + TGP_MOVE = 4, // advance to finish + TGP_CRWAIT = 5, // waits after collision + TGP_CRTURN = 6, // turns right after collision + TGP_CRADVANCE = 7, // advance to the right after collision + TGP_CLWAIT = 8, // waits after collision + TGP_CLTURN = 9, // turns left after collision + TGP_CLADVANCE = 10, // advance to the left after collision + TGP_BEAMLEAK = 11, // beam: leak (leaking) + TGP_BEAMSEARCH = 12, // beam: search + TGP_BEAMWCOLD = 13, // beam: expects cool reactor + TGP_BEAMUP = 14, // beam: off + TGP_BEAMGOTO = 15, // beam: goto dot list + TGP_BEAMDOWN = 16, // beam: landed +}; + + + +class CTaskGoto : public CTask +{ +public: + CTaskGoto(CInstanceManager* iMan, CObject* object); + ~CTaskGoto(); + + bool EventProcess(const Event &event); + + Error Start(Math::Vector goal, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode); + Error IsEnded(); + +protected: + CObject* WormSearch(Math::Vector &impact); + void WormFrame(float rTime); + CObject* SearchTarget(Math::Vector pos, float margin); + bool AdjustTarget(CObject* pObj, Math::Vector &pos, float &distance); + bool AdjustBuilding(Math::Vector &pos, float margin, float &distance); + bool GetHotPoint(CObject *pObj, Math::Vector &pos, bool bTake, float distance, float &suppl); + bool LeakSearch(Math::Vector &pos, float &delay); + void ComputeRepulse(Math::Point &dir); + void ComputeFlyingRepulse(float &dir); + + int BeamShortcut(); + void BeamStart(); + void BeamInit(); + Error BeamSearch(const Math::Vector &start, const Math::Vector &goal, float goalRadius); + Error BeamExplore(const Math::Vector &prevPos, const Math::Vector &curPos, const Math::Vector &goalPos, float goalRadius, float angle, int nbDiv, float step, int i, int nbIter); + Math::Vector BeamPoint(const Math::Vector &startPoint, const Math::Vector &goalPoint, float angle, float step); + + void BitmapDebug(const Math::Vector &min, const Math::Vector &max, const Math::Vector &start, const Math::Vector &goal); + bool BitmapTestLine(const Math::Vector &start, const Math::Vector &goal, float stepAngle, bool bSecond); + void BitmapObject(); + void BitmapTerrain(const Math::Vector &min, const Math::Vector &max); + void BitmapTerrain(int minx, int miny, int maxx, int maxy); + bool BitmapOpen(); + bool BitmapClose(); + void BitmapSetCircle(const Math::Vector &pos, float radius); + void BitmapClearCircle(const Math::Vector &pos, float radius); + void BitmapSetDot(int rank, int x, int y); + void BitmapClearDot(int rank, int x, int y); + bool BitmapTestDot(int rank, int x, int y); + +protected: + Math::Vector m_goal; + Math::Vector m_goalObject; + float m_angle; + float m_altitude; + TaskGotoCrash m_crashMode; + TaskGotoGoal m_goalMode; + TaskGotoPhase m_phase; + int m_try; + Error m_error; + bool m_bTake; + float m_stopLength; // braking distance + float m_time; + Math::Vector m_pos; + bool m_bWorm; + bool m_bApprox; + float m_wormLastTime; + float m_lastDistance; + + int m_bmSize; // width or height of the table + int m_bmOffset; // m_bmSize/2 + int m_bmLine; // increment line m_bmSize/8 + unsigned char* m_bmArray; // bit table + int m_bmMinX, m_bmMinY; + int m_bmMaxX, m_bmMaxY; + int m_bmTotal; // number of points in m_bmPoints + int m_bmIndex; // index in m_bmPoints + Math::Vector m_bmPoints[MAXPOINTS+2]; + char m_bmIter[MAXPOINTS+2]; + int m_bmIterCounter; + CObject* m_bmFretObject; + float m_bmFinalMove; // final advance distance + float m_bmFinalDist; // effective distance to advance + Math::Vector m_bmFinalPos; // initial position before advance + float m_bmTimeLimit; + int m_bmStep; + Math::Vector m_bmWatchDogPos; + float m_bmWatchDogTime; + Math::Vector m_leakPos; // initial position leak + float m_leakDelay; + float m_leakTime; + bool m_bLeakRecede; +}; + diff --git a/src/object/task/taskgungoal.cpp b/src/object/task/taskgungoal.cpp index 0635b97..e259ca8 100644 --- a/src/object/task/taskgungoal.cpp +++ b/src/object/task/taskgungoal.cpp @@ -1,149 +1,149 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskgungoal.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskgungoal.h"
-
-#include "object/object.h"
-
-
-
-
-// Object's constructor.
-
-CTaskGunGoal::CTaskGunGoal(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskGunGoal::~CTaskGunGoal()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskGunGoal::EventProcess(const Event &event)
-{
- float dir;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
-
- if ( m_progress < 1.0f )
- {
- dir = m_initialDirV + (m_finalDirV-m_initialDirV)*m_progress;
- }
- else
- {
- dir = m_finalDirV;
- }
- m_object->SetGunGoalV(dir);
-
- if ( m_progress < 1.0f )
- {
- dir = m_initialDirH + (m_finalDirH-m_initialDirH)*m_progress;
- }
- else
- {
- dir = m_finalDirH;
- }
- m_object->SetGunGoalH(dir);
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskGunGoal::Start(float dirV, float dirH)
-{
- float speedV, speedH;
- int i;
-
- m_initialDirV = m_object->RetGunGoalV();
- m_object->SetGunGoalV(dirV);
- m_finalDirV = m_object->RetGunGoalV(); // possible direction
- m_object->SetGunGoalV(m_initialDirV); // gives initial direction
-
- if ( m_finalDirV == m_initialDirV )
- {
- speedV = 100.0f;
- }
- else
- {
- speedV = 1.0f/(fabs(m_finalDirV-m_initialDirV)*1.0f);
- }
-
- m_initialDirH = m_object->RetGunGoalH();
- m_object->SetGunGoalH(dirH);
- m_finalDirH = m_object->RetGunGoalH(); // possible direction
- m_object->SetGunGoalH(m_initialDirH); // gives initial direction
-
- if ( m_finalDirH == m_initialDirH )
- {
- speedH = 100.0f;
- }
- else
- {
- speedH = 1.0f/(fabs(m_finalDirH-m_initialDirH)*1.0f);
- }
-
- m_speed = Math::Min(speedV, speedH);
-
- if ( m_finalDirV != m_initialDirV ||
- m_finalDirH != m_initialDirH )
- {
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.3f, 1.5f, true);
- m_sound->AddEnvelope(i, 0.3f, 1.5f, 1.0f/m_speed, SOPER_STOP);
- }
-
- m_progress = 0.0f;
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskGunGoal::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
-
- if ( m_initialDirV == m_finalDirV &&
- m_initialDirH == m_finalDirH ) return ERR_STOP;
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_object->SetGunGoalV(m_finalDirV);
- m_object->SetGunGoalH(m_finalDirH);
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskGunGoal::Abort()
-{
- return true;
-}
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskgungoal.cpp + + +#include <stdio.h> + +#include "object/task/taskgungoal.h" + +#include "object/object.h" + + + + +// Object's constructor. + +CTaskGunGoal::CTaskGunGoal(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ +} + +// Object's destructor. + +CTaskGunGoal::~CTaskGunGoal() +{ +} + + +// Management of an event. + +bool CTaskGunGoal::EventProcess(const Event &event) +{ + float dir; + + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + + m_progress += event.rTime*m_speed; + + if ( m_progress < 1.0f ) + { + dir = m_initialDirV + (m_finalDirV-m_initialDirV)*m_progress; + } + else + { + dir = m_finalDirV; + } + m_object->SetGunGoalV(dir); + + if ( m_progress < 1.0f ) + { + dir = m_initialDirH + (m_finalDirH-m_initialDirH)*m_progress; + } + else + { + dir = m_finalDirH; + } + m_object->SetGunGoalH(dir); + + return true; +} + + +// Assigns the goal was achieved. + +Error CTaskGunGoal::Start(float dirV, float dirH) +{ + float speedV, speedH; + int i; + + m_initialDirV = m_object->RetGunGoalV(); + m_object->SetGunGoalV(dirV); + m_finalDirV = m_object->RetGunGoalV(); // possible direction + m_object->SetGunGoalV(m_initialDirV); // gives initial direction + + if ( m_finalDirV == m_initialDirV ) + { + speedV = 100.0f; + } + else + { + speedV = 1.0f/(fabs(m_finalDirV-m_initialDirV)*1.0f); + } + + m_initialDirH = m_object->RetGunGoalH(); + m_object->SetGunGoalH(dirH); + m_finalDirH = m_object->RetGunGoalH(); // possible direction + m_object->SetGunGoalH(m_initialDirH); // gives initial direction + + if ( m_finalDirH == m_initialDirH ) + { + speedH = 100.0f; + } + else + { + speedH = 1.0f/(fabs(m_finalDirH-m_initialDirH)*1.0f); + } + + m_speed = Math::Min(speedV, speedH); + + if ( m_finalDirV != m_initialDirV || + m_finalDirH != m_initialDirH ) + { + i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.3f, 1.5f, true); + m_sound->AddEnvelope(i, 0.3f, 1.5f, 1.0f/m_speed, SOPER_STOP); + } + + m_progress = 0.0f; + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskGunGoal::IsEnded() +{ + if ( m_engine->RetPause() ) return ERR_CONTINUE; + + if ( m_initialDirV == m_finalDirV && + m_initialDirH == m_finalDirH ) return ERR_STOP; + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + m_object->SetGunGoalV(m_finalDirV); + m_object->SetGunGoalH(m_finalDirH); + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +bool CTaskGunGoal::Abort() +{ + return true; +} + diff --git a/src/object/task/taskgungoal.h b/src/object/task/taskgungoal.h index 4759cbc..0c063d1 100644 --- a/src/object/task/taskgungoal.h +++ b/src/object/task/taskgungoal.h @@ -1,48 +1,48 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskgungoal.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskGunGoal : public CTask
-{
-public:
- CTaskGunGoal(CInstanceManager* iMan, CObject* object);
- ~CTaskGunGoal();
-
- bool EventProcess(const Event &event);
-
- Error Start(float dirV, float dirH);
- Error IsEnded();
- bool Abort();
-
-protected:
-
-protected:
- float m_progress;
- float m_speed;
- float m_initialDirV; // initial direction
- float m_finalDirV; // direction to reach
- float m_initialDirH; // initial direction
- float m_finalDirH; // direction to reach
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskgungoal.h + +#pragma once + + +#include "object/task/task.h" + + + +class CTaskGunGoal : public CTask +{ +public: + CTaskGunGoal(CInstanceManager* iMan, CObject* object); + ~CTaskGunGoal(); + + bool EventProcess(const Event &event); + + Error Start(float dirV, float dirH); + Error IsEnded(); + bool Abort(); + +protected: + +protected: + float m_progress; + float m_speed; + float m_initialDirV; // initial direction + float m_finalDirV; // direction to reach + float m_initialDirH; // initial direction + float m_finalDirH; // direction to reach +}; + diff --git a/src/object/task/taskinfo.cpp b/src/object/task/taskinfo.cpp index cfcbe93..6d1f486 100644 --- a/src/object/task/taskinfo.cpp +++ b/src/object/task/taskinfo.cpp @@ -1,219 +1,219 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskinfo.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskinfo.h"
-
-#include "common/iman.h"
-#include "old/particule.h"
-#include "object/auto/autoinfo.h"
-
-
-
-
-
-// Object's constructor.
-
-CTaskInfo::CTaskInfo(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskInfo::~CTaskInfo()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskInfo::EventProcess(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_progress += event.rTime*m_speed; // other advance
- m_time += event.rTime;
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskInfo::Start(char *name, float value, float power, bool bSend)
-{
- CObject* pInfo;
- CAutoInfo* pAuto;
- Math::Vector pos, goal;
- Info info;
- int i, total, op;
-
- m_bError = true;
- m_object->SetInfoReturn(NAN);
-
- pInfo = SearchInfo(power); // seeks terminal
- if ( pInfo == 0 )
- {
- return ERR_INFO_NULL;
- }
-
- pAuto = (CAutoInfo*)pInfo->RetAuto();
- if ( pAuto == 0 )
- {
- return ERR_INFO_NULL;
- }
-
- op = 1; // transmission impossible
- if ( bSend ) // send?
- {
- total = pInfo->RetInfoTotal();
- for ( i=0 ; i<total ; i++ )
- {
- info = pInfo->RetInfo(i);
- if ( strcmp(info.name, name) == 0 )
- {
- info.value = value;
- pInfo->SetInfo(i, info);
- break;
- }
- }
- if ( i == total )
- {
- if ( total < OBJECTMAXINFO )
- {
- strcpy(info.name, name);
- info.value = value;
- pInfo->SetInfo(total, info);
- op = 2; // start of reception (for terminal)
- }
- }
- else
- {
- op = 2; // start of reception (for terminal)
- }
- }
- else // receive?
- {
- total = pInfo->RetInfoTotal();
- for ( i=0 ; i<total ; i++ )
- {
- info = pInfo->RetInfo(i);
- if ( strcmp(info.name, name) == 0 )
- {
- m_object->SetInfoReturn(info.value);
- break;
- }
- }
- if ( i < total )
- {
- op = 0; // beginning of transmission (for terminal)
- }
- }
-
- pAuto->Start(op);
-
- if ( op == 0 ) // transmission?
- {
- pos = pInfo->RetPosition(0);
- pos.y += 9.5f;
- goal = m_object->RetPosition(0);
- goal.y += 4.0f;
- m_particule->CreateRay(pos, goal, PARTIRAY3, Math::Point(2.0f, 2.0f), 1.0f);
- }
- if ( op == 2 ) // reception?
- {
- goal = pInfo->RetPosition(0);
- goal.y += 9.5f;
- pos = m_object->RetPosition(0);
- pos.y += 4.0f;
- m_particule->CreateRay(pos, goal, PARTIRAY3, Math::Point(2.0f, 2.0f), 1.0f);
- }
-
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- m_time = 0.0f;
-
- m_bError = false; // ok
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskInfo::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskInfo::Abort()
-{
- return true;
-}
-
-
-// Seeks the nearest information terminal.
-
-CObject* CTaskInfo::SearchInfo(float power)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float dist, min;
- int i;
-
- iPos = m_object->RetPosition(0);
-
- min = 100000.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_INFO ) continue;
-
- if ( !pObj->RetActif() ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, iPos);
- if ( dist > power ) continue; // too far?
- if ( dist < min )
- {
- min = dist;
- pBest = pObj;
- }
- }
-
- return pBest;
-}
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskinfo.cpp + + +#include <stdio.h> + +#include "object/task/taskinfo.h" + +#include "common/iman.h" +#include "old/particule.h" +#include "object/auto/autoinfo.h" + + + + + +// Object's constructor. + +CTaskInfo::CTaskInfo(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ +} + +// Object's destructor. + +CTaskInfo::~CTaskInfo() +{ +} + + +// Management of an event. + +bool CTaskInfo::EventProcess(const Event &event) +{ + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + if ( m_bError ) return false; + + m_progress += event.rTime*m_speed; // other advance + m_time += event.rTime; + + return true; +} + + +// Assigns the goal was achieved. + +Error CTaskInfo::Start(char *name, float value, float power, bool bSend) +{ + CObject* pInfo; + CAutoInfo* pAuto; + Math::Vector pos, goal; + Info info; + int i, total, op; + + m_bError = true; + m_object->SetInfoReturn(NAN); + + pInfo = SearchInfo(power); // seeks terminal + if ( pInfo == 0 ) + { + return ERR_INFO_NULL; + } + + pAuto = (CAutoInfo*)pInfo->RetAuto(); + if ( pAuto == 0 ) + { + return ERR_INFO_NULL; + } + + op = 1; // transmission impossible + if ( bSend ) // send? + { + total = pInfo->RetInfoTotal(); + for ( i=0 ; i<total ; i++ ) + { + info = pInfo->RetInfo(i); + if ( strcmp(info.name, name) == 0 ) + { + info.value = value; + pInfo->SetInfo(i, info); + break; + } + } + if ( i == total ) + { + if ( total < OBJECTMAXINFO ) + { + strcpy(info.name, name); + info.value = value; + pInfo->SetInfo(total, info); + op = 2; // start of reception (for terminal) + } + } + else + { + op = 2; // start of reception (for terminal) + } + } + else // receive? + { + total = pInfo->RetInfoTotal(); + for ( i=0 ; i<total ; i++ ) + { + info = pInfo->RetInfo(i); + if ( strcmp(info.name, name) == 0 ) + { + m_object->SetInfoReturn(info.value); + break; + } + } + if ( i < total ) + { + op = 0; // beginning of transmission (for terminal) + } + } + + pAuto->Start(op); + + if ( op == 0 ) // transmission? + { + pos = pInfo->RetPosition(0); + pos.y += 9.5f; + goal = m_object->RetPosition(0); + goal.y += 4.0f; + m_particule->CreateRay(pos, goal, PARTIRAY3, Math::Point(2.0f, 2.0f), 1.0f); + } + if ( op == 2 ) // reception? + { + goal = pInfo->RetPosition(0); + goal.y += 9.5f; + pos = m_object->RetPosition(0); + pos.y += 4.0f; + m_particule->CreateRay(pos, goal, PARTIRAY3, Math::Point(2.0f, 2.0f), 1.0f); + } + + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + m_time = 0.0f; + + m_bError = false; // ok + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskInfo::IsEnded() +{ + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + m_progress = 0.0f; + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +bool CTaskInfo::Abort() +{ + return true; +} + + +// Seeks the nearest information terminal. + +CObject* CTaskInfo::SearchInfo(float power) +{ + CObject *pObj, *pBest; + Math::Vector iPos, oPos; + ObjectType type; + float dist, min; + int i; + + iPos = m_object->RetPosition(0); + + min = 100000.0f; + pBest = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type != OBJECT_INFO ) continue; + + if ( !pObj->RetActif() ) continue; + + oPos = pObj->RetPosition(0); + dist = Math::Distance(oPos, iPos); + if ( dist > power ) continue; // too far? + if ( dist < min ) + { + min = dist; + pBest = pObj; + } + } + + return pBest; +} + diff --git a/src/object/task/taskinfo.h b/src/object/task/taskinfo.h index 8f6e4f2..21a4392 100644 --- a/src/object/task/taskinfo.h +++ b/src/object/task/taskinfo.h @@ -1,47 +1,47 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskinfo.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskInfo : public CTask
-{
-public:
- CTaskInfo(CInstanceManager* iMan, CObject* object);
- ~CTaskInfo();
-
- bool EventProcess(const Event &event);
-
- Error Start(char *name, float value, float power, bool bSend);
- Error IsEnded();
- bool Abort();
-
-protected:
- CObject* SearchInfo(float power);
-
-protected:
- float m_progress;
- float m_speed;
- float m_time;
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskinfo.h + +#pragma once + + +#include "object/task/task.h" + + + +class CTaskInfo : public CTask +{ +public: + CTaskInfo(CInstanceManager* iMan, CObject* object); + ~CTaskInfo(); + + bool EventProcess(const Event &event); + + Error Start(char *name, float value, float power, bool bSend); + Error IsEnded(); + bool Abort(); + +protected: + CObject* SearchInfo(float power); + +protected: + float m_progress; + float m_speed; + float m_time; + bool m_bError; +}; + diff --git a/src/object/task/taskmanager.cpp b/src/object/task/taskmanager.cpp index f6f8b97..d81fb5b 100644 --- a/src/object/task/taskmanager.cpp +++ b/src/object/task/taskmanager.cpp @@ -1,278 +1,278 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskmanager.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskmanager.h"
-
-#include "common/iman.h"
-#include "object/task/taskwait.h"
-#include "object/task/taskadvance.h"
-#include "object/task/taskturn.h"
-#include "object/task/tasktake.h"
-#include "object/task/taskbuild.h"
-#include "object/task/tasksearch.h"
-#include "object/task/taskterraform.h"
-#include "object/task/taskpen.h"
-#include "object/task/taskrecover.h"
-#include "object/task/taskinfo.h"
-#include "object/task/taskfire.h"
-#include "object/task/taskfireant.h"
-#include "object/task/taskgungoal.h"
-#include "object/task/taskspiderexplo.h"
-#include "object/task/taskreset.h"
-
-
-
-
-// Object's constructor.
-
-CTaskManager::CTaskManager(CInstanceManager* iMan, CObject* object)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_TASKMANAGER, this, 100);
-
- m_task = 0;
- m_object = object;
- m_bPilot = false;
-}
-
-// Object's destructor.
-
-CTaskManager::~CTaskManager()
-{
- delete m_task;
-}
-
-
-
-// Waits for a while.
-
-Error CTaskManager::StartTaskWait(float time)
-{
- m_task = new CTaskWait(m_iMan, m_object);
- return ((CTaskWait*)m_task)->Start(time);
-}
-
-// Advance straight ahead a certain distance.
-
-Error CTaskManager::StartTaskAdvance(float length)
-{
- m_task = new CTaskAdvance(m_iMan, m_object);
- return ((CTaskAdvance*)m_task)->Start(length);
-}
-
-// Turns through an certain angle.
-
-Error CTaskManager::StartTaskTurn(float angle)
-{
- m_task = new CTaskTurn(m_iMan, m_object);
- return ((CTaskTurn*)m_task)->Start(angle);
-}
-
-// Reaches a given position.
-
-Error CTaskManager::StartTaskGoto(Math::Vector pos, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode)
-{
- m_task = new CTaskGoto(m_iMan, m_object);
- return ((CTaskGoto*)m_task)->Start(pos, altitude, goalMode, crashMode);
-}
-
-// Move the manipulator arm.
-
-Error CTaskManager::StartTaskTake()
-{
- m_task = new CTaskTake(m_iMan, m_object);
- return ((CTaskTake*)m_task)->Start();
-}
-
-// Move the manipulator arm.
-
-Error CTaskManager::StartTaskManip(TaskManipOrder order, TaskManipArm arm)
-{
- m_task = new CTaskManip(m_iMan, m_object);
- return ((CTaskManip*)m_task)->Start(order, arm);
-}
-
-// Puts or removes a flag.
-
-Error CTaskManager::StartTaskFlag(TaskFlagOrder order, int rank)
-{
- m_task = new CTaskFlag(m_iMan, m_object);
- return ((CTaskFlag*)m_task)->Start(order, rank);
-}
-
-// Builds a building.
-
-Error CTaskManager::StartTaskBuild(ObjectType type)
-{
- m_task = new CTaskBuild(m_iMan, m_object);
- return ((CTaskBuild*)m_task)->Start(type);
-}
-
-// Probe the ground.
-
-Error CTaskManager::StartTaskSearch()
-{
- m_task = new CTaskSearch(m_iMan, m_object);
- return ((CTaskSearch*)m_task)->Start();
-}
-
-// Reads an information terminal.
-
-Error CTaskManager::StartTaskInfo(char *name, float value, float power, bool bSend)
-{
- m_task = new CTaskInfo(m_iMan, m_object);
- return ((CTaskInfo*)m_task)->Start(name, value, power, bSend);
-}
-
-// Terraforms the ground.
-
-Error CTaskManager::StartTaskTerraform()
-{
- m_task = new CTaskTerraform(m_iMan, m_object);
- return ((CTaskTerraform*)m_task)->Start();
-}
-
-// Changes the pencil.
-
-Error CTaskManager::StartTaskPen(bool bDown, int color)
-{
- m_task = new CTaskPen(m_iMan, m_object);
- return ((CTaskPen*)m_task)->Start(bDown, color);
-}
-
-// Recovers a ruin.
-
-Error CTaskManager::StartTaskRecover()
-{
- m_task = new CTaskRecover(m_iMan, m_object);
- return ((CTaskRecover*)m_task)->Start();
-}
-
-// Deploys the shield.
-
-Error CTaskManager::StartTaskShield(TaskShieldMode mode, float delay)
-{
- if ( mode == TSM_UP )
- {
- m_task = new CTaskShield(m_iMan, m_object);
- return ((CTaskShield*)m_task)->Start(mode, delay);
- }
- if ( mode == TSM_DOWN && m_task != 0 )
- {
- return ((CTaskShield*)m_task)->Start(mode, delay);
- }
- if ( mode == TSM_UPDATE && m_task != 0 )
- {
- return ((CTaskShield*)m_task)->Start(mode, delay);
- }
- return ERR_GENERIC;
-}
-
-// Shoots.
-
-Error CTaskManager::StartTaskFire(float delay)
-{
- m_bPilot = true;
- m_task = new CTaskFire(m_iMan, m_object);
- return ((CTaskFire*)m_task)->Start(delay);
-}
-
-// Shoots with the ant.
-
-Error CTaskManager::StartTaskFireAnt(Math::Vector impact)
-{
- m_task = new CTaskFireAnt(m_iMan, m_object);
- return ((CTaskFireAnt*)m_task)->Start(impact);
-}
-
-// Adjusts higher.
-
-Error CTaskManager::StartTaskGunGoal(float dirV, float dirH)
-{
- m_task = new CTaskGunGoal(m_iMan, m_object);
- return ((CTaskGunGoal*)m_task)->Start(dirV, dirH);
-}
-
-// Suicide of the spider.
-
-Error CTaskManager::StartTaskSpiderExplo()
-{
- m_task = new CTaskSpiderExplo(m_iMan, m_object);
- return ((CTaskSpiderExplo*)m_task)->Start();
-}
-
-// Reset.
-
-Error CTaskManager::StartTaskReset(Math::Vector goal, Math::Vector angle)
-{
- m_task = new CTaskReset(m_iMan, m_object);
- return ((CTaskReset*)m_task)->Start(goal, angle);
-}
-
-
-
-
-
-// Management of an event.
-
-bool CTaskManager::EventProcess(const Event &event)
-{
- if ( m_task == 0 ) return false;
- return m_task->EventProcess(event);
-}
-
-
-// Indicates whether the action is finished.
-
-Error CTaskManager::IsEnded()
-{
- if ( m_task == 0 ) return ERR_GENERIC;
- return m_task->IsEnded();
-}
-
-
-// Indicates whether the action is pending.
-
-bool CTaskManager::IsBusy()
-{
- if ( m_task == 0 ) return false;
- return m_task->IsBusy();
-}
-
-
-// Indicates whether it is possible to control the robot
-// during the execution of the current task.
-
-bool CTaskManager::IsPilot()
-{
- return m_bPilot;
-}
-
-
-// Suddenly ends the current action.
-
-bool CTaskManager::Abort()
-{
- if ( m_task == 0 ) return false;
- return m_task->Abort();
-}
-
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskmanager.cpp + + +#include <stdio.h> + +#include "object/task/taskmanager.h" + +#include "common/iman.h" +#include "object/task/taskwait.h" +#include "object/task/taskadvance.h" +#include "object/task/taskturn.h" +#include "object/task/tasktake.h" +#include "object/task/taskbuild.h" +#include "object/task/tasksearch.h" +#include "object/task/taskterraform.h" +#include "object/task/taskpen.h" +#include "object/task/taskrecover.h" +#include "object/task/taskinfo.h" +#include "object/task/taskfire.h" +#include "object/task/taskfireant.h" +#include "object/task/taskgungoal.h" +#include "object/task/taskspiderexplo.h" +#include "object/task/taskreset.h" + + + + +// Object's constructor. + +CTaskManager::CTaskManager(CInstanceManager* iMan, CObject* object) +{ + m_iMan = iMan; + m_iMan->AddInstance(CLASS_TASKMANAGER, this, 100); + + m_task = 0; + m_object = object; + m_bPilot = false; +} + +// Object's destructor. + +CTaskManager::~CTaskManager() +{ + delete m_task; +} + + + +// Waits for a while. + +Error CTaskManager::StartTaskWait(float time) +{ + m_task = new CTaskWait(m_iMan, m_object); + return ((CTaskWait*)m_task)->Start(time); +} + +// Advance straight ahead a certain distance. + +Error CTaskManager::StartTaskAdvance(float length) +{ + m_task = new CTaskAdvance(m_iMan, m_object); + return ((CTaskAdvance*)m_task)->Start(length); +} + +// Turns through an certain angle. + +Error CTaskManager::StartTaskTurn(float angle) +{ + m_task = new CTaskTurn(m_iMan, m_object); + return ((CTaskTurn*)m_task)->Start(angle); +} + +// Reaches a given position. + +Error CTaskManager::StartTaskGoto(Math::Vector pos, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode) +{ + m_task = new CTaskGoto(m_iMan, m_object); + return ((CTaskGoto*)m_task)->Start(pos, altitude, goalMode, crashMode); +} + +// Move the manipulator arm. + +Error CTaskManager::StartTaskTake() +{ + m_task = new CTaskTake(m_iMan, m_object); + return ((CTaskTake*)m_task)->Start(); +} + +// Move the manipulator arm. + +Error CTaskManager::StartTaskManip(TaskManipOrder order, TaskManipArm arm) +{ + m_task = new CTaskManip(m_iMan, m_object); + return ((CTaskManip*)m_task)->Start(order, arm); +} + +// Puts or removes a flag. + +Error CTaskManager::StartTaskFlag(TaskFlagOrder order, int rank) +{ + m_task = new CTaskFlag(m_iMan, m_object); + return ((CTaskFlag*)m_task)->Start(order, rank); +} + +// Builds a building. + +Error CTaskManager::StartTaskBuild(ObjectType type) +{ + m_task = new CTaskBuild(m_iMan, m_object); + return ((CTaskBuild*)m_task)->Start(type); +} + +// Probe the ground. + +Error CTaskManager::StartTaskSearch() +{ + m_task = new CTaskSearch(m_iMan, m_object); + return ((CTaskSearch*)m_task)->Start(); +} + +// Reads an information terminal. + +Error CTaskManager::StartTaskInfo(char *name, float value, float power, bool bSend) +{ + m_task = new CTaskInfo(m_iMan, m_object); + return ((CTaskInfo*)m_task)->Start(name, value, power, bSend); +} + +// Terraforms the ground. + +Error CTaskManager::StartTaskTerraform() +{ + m_task = new CTaskTerraform(m_iMan, m_object); + return ((CTaskTerraform*)m_task)->Start(); +} + +// Changes the pencil. + +Error CTaskManager::StartTaskPen(bool bDown, int color) +{ + m_task = new CTaskPen(m_iMan, m_object); + return ((CTaskPen*)m_task)->Start(bDown, color); +} + +// Recovers a ruin. + +Error CTaskManager::StartTaskRecover() +{ + m_task = new CTaskRecover(m_iMan, m_object); + return ((CTaskRecover*)m_task)->Start(); +} + +// Deploys the shield. + +Error CTaskManager::StartTaskShield(TaskShieldMode mode, float delay) +{ + if ( mode == TSM_UP ) + { + m_task = new CTaskShield(m_iMan, m_object); + return ((CTaskShield*)m_task)->Start(mode, delay); + } + if ( mode == TSM_DOWN && m_task != 0 ) + { + return ((CTaskShield*)m_task)->Start(mode, delay); + } + if ( mode == TSM_UPDATE && m_task != 0 ) + { + return ((CTaskShield*)m_task)->Start(mode, delay); + } + return ERR_GENERIC; +} + +// Shoots. + +Error CTaskManager::StartTaskFire(float delay) +{ + m_bPilot = true; + m_task = new CTaskFire(m_iMan, m_object); + return ((CTaskFire*)m_task)->Start(delay); +} + +// Shoots with the ant. + +Error CTaskManager::StartTaskFireAnt(Math::Vector impact) +{ + m_task = new CTaskFireAnt(m_iMan, m_object); + return ((CTaskFireAnt*)m_task)->Start(impact); +} + +// Adjusts higher. + +Error CTaskManager::StartTaskGunGoal(float dirV, float dirH) +{ + m_task = new CTaskGunGoal(m_iMan, m_object); + return ((CTaskGunGoal*)m_task)->Start(dirV, dirH); +} + +// Suicide of the spider. + +Error CTaskManager::StartTaskSpiderExplo() +{ + m_task = new CTaskSpiderExplo(m_iMan, m_object); + return ((CTaskSpiderExplo*)m_task)->Start(); +} + +// Reset. + +Error CTaskManager::StartTaskReset(Math::Vector goal, Math::Vector angle) +{ + m_task = new CTaskReset(m_iMan, m_object); + return ((CTaskReset*)m_task)->Start(goal, angle); +} + + + + + +// Management of an event. + +bool CTaskManager::EventProcess(const Event &event) +{ + if ( m_task == 0 ) return false; + return m_task->EventProcess(event); +} + + +// Indicates whether the action is finished. + +Error CTaskManager::IsEnded() +{ + if ( m_task == 0 ) return ERR_GENERIC; + return m_task->IsEnded(); +} + + +// Indicates whether the action is pending. + +bool CTaskManager::IsBusy() +{ + if ( m_task == 0 ) return false; + return m_task->IsBusy(); +} + + +// Indicates whether it is possible to control the robot +// during the execution of the current task. + +bool CTaskManager::IsPilot() +{ + return m_bPilot; +} + + +// Suddenly ends the current action. + +bool CTaskManager::Abort() +{ + if ( m_task == 0 ) return false; + return m_task->Abort(); +} + + diff --git a/src/object/task/taskmanager.h b/src/object/task/taskmanager.h index 30b6c81..14fc276 100644 --- a/src/object/task/taskmanager.h +++ b/src/object/task/taskmanager.h @@ -1,71 +1,71 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskmanager.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-#include "object/task/taskmanip.h"
-#include "object/task/taskgoto.h"
-#include "object/task/taskshield.h"
-#include "object/task/taskflag.h"
-
-
-
-class CTaskManager
-{
-public:
- CTaskManager(CInstanceManager* iMan, CObject* object);
- ~CTaskManager();
-
- Error StartTaskWait(float time);
- Error StartTaskAdvance(float length);
- Error StartTaskTurn(float angle);
- Error StartTaskGoto(Math::Vector pos, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode);
- Error StartTaskTake();
- Error StartTaskManip(TaskManipOrder order, TaskManipArm arm);
- Error StartTaskFlag(TaskFlagOrder order, int rank);
- Error StartTaskBuild(ObjectType type);
- Error StartTaskSearch();
- Error StartTaskInfo(char *name, float value, float power, bool bSend);
- Error StartTaskTerraform();
- Error StartTaskPen(bool bDown, int color);
- Error StartTaskRecover();
- Error StartTaskShield(TaskShieldMode mode, float delay);
- Error StartTaskFire(float delay);
- Error StartTaskFireAnt(Math::Vector impact);
- Error StartTaskGunGoal(float dirV, float dirH);
- Error StartTaskSpiderExplo();
- Error StartTaskReset(Math::Vector goal, Math::Vector angle);
-
- bool EventProcess(const Event &event);
- Error IsEnded();
- bool IsBusy();
- bool IsPilot();
- bool Abort();
-
-protected:
-
-protected:
- CInstanceManager* m_iMan;
- CTask* m_task;
- CObject* m_object;
- bool m_bPilot;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskmanager.h + +#pragma once + + +#include "object/task/task.h" +#include "object/object.h" +#include "object/task/taskmanip.h" +#include "object/task/taskgoto.h" +#include "object/task/taskshield.h" +#include "object/task/taskflag.h" + + + +class CTaskManager +{ +public: + CTaskManager(CInstanceManager* iMan, CObject* object); + ~CTaskManager(); + + Error StartTaskWait(float time); + Error StartTaskAdvance(float length); + Error StartTaskTurn(float angle); + Error StartTaskGoto(Math::Vector pos, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode); + Error StartTaskTake(); + Error StartTaskManip(TaskManipOrder order, TaskManipArm arm); + Error StartTaskFlag(TaskFlagOrder order, int rank); + Error StartTaskBuild(ObjectType type); + Error StartTaskSearch(); + Error StartTaskInfo(char *name, float value, float power, bool bSend); + Error StartTaskTerraform(); + Error StartTaskPen(bool bDown, int color); + Error StartTaskRecover(); + Error StartTaskShield(TaskShieldMode mode, float delay); + Error StartTaskFire(float delay); + Error StartTaskFireAnt(Math::Vector impact); + Error StartTaskGunGoal(float dirV, float dirH); + Error StartTaskSpiderExplo(); + Error StartTaskReset(Math::Vector goal, Math::Vector angle); + + bool EventProcess(const Event &event); + Error IsEnded(); + bool IsBusy(); + bool IsPilot(); + bool Abort(); + +protected: + +protected: + CInstanceManager* m_iMan; + CTask* m_task; + CObject* m_object; + bool m_bPilot; +}; + diff --git a/src/object/task/taskmanip.cpp b/src/object/task/taskmanip.cpp index 636031b..456f274 100644 --- a/src/object/task/taskmanip.cpp +++ b/src/object/task/taskmanip.cpp @@ -1,1383 +1,1383 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskmanip.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskmanip.h"
-
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "old/pyro.h"
-#include "math/geometry.h"
-#include "object/robotmain.h"
-#include "physics/physics.h"
-
-
-//?const float MARGIN_FRONT = 2.0f;
-//?const float MARGIN_BACK = 2.0f;
-//?const float MARGIN_FRIEND = 2.0f;
-//?const float MARGIN_BEE = 5.0f;
-const float MARGIN_FRONT = 4.0f; //OK 1.9
-const float MARGIN_BACK = 4.0f; //OK 1.9
-const float MARGIN_FRIEND = 4.0f; //OK 1.9
-const float MARGIN_BEE = 5.0f; //OK 1.9
-
-
-
-
-// Object's constructor.
-
-CTaskManip::CTaskManip(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_arm = TMA_NEUTRAL;
- m_hand = TMH_OPEN;
-}
-
-// Object's destructor.
-
-CTaskManip::~CTaskManip()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskManip::EventProcess(const Event &event)
-{
- Math::Vector pos;
- float angle, a, g, cirSpeed, progress;
- int i;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- if ( m_bBee ) // bee?
- {
- return true;
- }
-
- if ( m_bTurn ) // preliminary rotation?
- {
- a = m_object->RetAngleY(0);
- g = m_angle;
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( m_physics->RetType() == TYPE_FLYING ) // flying on the ground?
- {
- cirSpeed *= 4.0f; // more fishing
- }
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- return true;
- }
-
- if ( m_move != 0 ) // preliminary advance?
- {
- m_timeLimit -= event.rTime;
- m_physics->SetMotorSpeedX(m_move); // forward/backward
- return true;
- }
-
- m_progress += event.rTime*m_speed; // others advance
- progress = m_progress;
- if ( progress > 1.0f ) progress = 1.0f;
-
- if ( m_bSubm ) // submarine?
- {
- if ( m_order == TMO_GRAB )
- {
- if ( m_step == 0 ) // fall?
- {
- pos = m_object->RetPosition(1);
- pos.y = 3.0f-progress*2.0f;
- m_object->SetPosition(1, pos);
- }
- if ( m_step == 1 ) // farm?
- {
- pos = m_object->RetPosition(2);
- pos.z = -1.5f+progress*0.5f;
- m_object->SetPosition(2, pos);
-
- pos = m_object->RetPosition(3);
- pos.z = 1.5f-progress*0.5f;
- m_object->SetPosition(3, pos);
- }
- if ( m_step == 2 ) // up?
- {
- pos = m_object->RetPosition(1);
- pos.y = 3.0f-(1.0f-progress)*2.0f;
- m_object->SetPosition(1, pos);
- }
- }
- else
- {
- if ( m_step == 0 ) // fall?
- {
- pos = m_object->RetPosition(1);
- pos.y = 3.0f-progress*2.0f;
- m_object->SetPosition(1, pos);
- }
- if ( m_step == 1 ) // farm?
- {
- pos = m_object->RetPosition(2);
- pos.z = -1.5f+(1.0f-progress)*0.5f;
- m_object->SetPosition(2, pos);
-
- pos = m_object->RetPosition(3);
- pos.z = 1.5f-(1.0f-progress)*0.5f;
- m_object->SetPosition(3, pos);
- }
- if ( m_step == 2 ) // up?
- {
- pos = m_object->RetPosition(1);
- pos.y = 3.0f-(1.0f-progress)*2.0f;
- m_object->SetPosition(1, pos);
- }
- }
- }
- else
- {
- for ( i=0 ; i<5 ; i++ )
- {
- angle = (m_finalAngle[i]-m_initialAngle[i])*progress;
- angle += m_initialAngle[i];
- m_object->SetAngleZ(i+1, angle);
- }
- }
-
- return true;
-}
-
-
-// Initializes the initial and final angles.
-
-void CTaskManip::InitAngle()
-{
- CObject* power;
- float max, energy;
- int i;
-
- if ( m_bSubm || m_bBee ) return;
-
- if ( m_arm == TMA_NEUTRAL ||
- m_arm == TMA_GRAB )
- {
- m_finalAngle[0] = ARM_NEUTRAL_ANGLE1; // arm
- m_finalAngle[1] = ARM_NEUTRAL_ANGLE2; // forearm
- m_finalAngle[2] = ARM_NEUTRAL_ANGLE3; // hand
- }
- if ( m_arm == TMA_STOCK )
- {
- m_finalAngle[0] = ARM_STOCK_ANGLE1; // arm
- m_finalAngle[1] = ARM_STOCK_ANGLE2; // forearm
- m_finalAngle[2] = ARM_STOCK_ANGLE3; // hand
- }
- if ( m_arm == TMA_FFRONT )
- {
- m_finalAngle[0] = 35.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = -95.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = -27.0f*Math::PI/180.0f; // hand
- }
- if ( m_arm == TMA_FBACK )
- {
- m_finalAngle[0] = 145.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = 95.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = 27.0f*Math::PI/180.0f; // hand
- }
- if ( m_arm == TMA_POWER )
- {
- m_finalAngle[0] = 95.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = 125.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = 50.0f*Math::PI/180.0f; // hand
- }
- if ( m_arm == TMA_OTHER )
- {
- if ( m_height <= 3.0f )
- {
- m_finalAngle[0] = 55.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = -90.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = -35.0f*Math::PI/180.0f; // hand
- }
- else
- {
- m_finalAngle[0] = 70.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = -90.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = -50.0f*Math::PI/180.0f; // hand
- }
- }
-
- if ( m_hand == TMH_OPEN ) // open clamp?
- {
- m_finalAngle[3] = -Math::PI*0.10f; // clamp close
- m_finalAngle[4] = Math::PI*0.10f; // clamp remote
- }
- if ( m_hand == TMH_CLOSE ) // clamp closed?
- {
- m_finalAngle[3] = Math::PI*0.05f; // clamp close
- m_finalAngle[4] = -Math::PI*0.05f; // clamp remote
- }
-
- for ( i=0 ; i<5 ; i++ )
- {
- m_initialAngle[i] = m_object->RetAngleZ(i+1);
- }
-
- max = 0.0f;
- for ( i=0 ; i<5 ; i++ )
- {
- max = Math::Max(max, fabs(m_initialAngle[i] - m_finalAngle[i]));
- }
- m_speed = (Math::PI*1.0f)/max;
- if ( m_speed > 3.0f ) m_speed = 3.0f; // piano, ma non troppo (?)
-
- energy = 0.0f;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- }
-
- if ( energy == 0.0f )
- {
- m_speed *= 0.7f; // slower if more energy!
- }
-}
-
-
-// Tests whether an object is compatible with the operation TMA_OTHER.
-
-bool TestFriend(ObjectType oType, ObjectType fType)
-{
- if ( oType == OBJECT_ENERGY )
- {
- return ( fType == OBJECT_METAL );
- }
- if ( oType == OBJECT_LABO )
- {
- return ( fType == OBJECT_BULLET );
- }
- if ( oType == OBJECT_NUCLEAR )
- {
- return ( fType == OBJECT_URANIUM );
- }
-
- return ( fType == OBJECT_POWER ||
- fType == OBJECT_ATOMIC );
-}
-
-// Assigns the goal was achieved.
-
-Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm)
-{
- ObjectType type;
- CObject *front, *other, *power;
- CPyro *pyro;
- float iAngle, dist, len;
- float fDist, fAngle, oDist, oAngle, oHeight;
- Math::Vector pos, fPos, oPos;
-
- m_arm = arm;
- m_height = 0.0f;
- m_step = 0;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
-
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
- oAngle = iAngle;
-
- m_bError = true; // operation impossible
-
- if ( m_arm != TMA_FFRONT &&
- m_arm != TMA_FBACK &&
- m_arm != TMA_POWER &&
- m_arm != TMA_GRAB ) return ERR_MANIP_VEH;
-
- m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));
-
- type = m_object->RetType();
- if ( type == OBJECT_BEE ) // bee?
- {
- if ( m_object->RetFret() == 0 )
- {
- if ( !m_physics->RetLand() ) return ERR_MANIP_FLY;
-
- other = SearchTakeUnderObject(m_targetPos, MARGIN_BEE);
- if ( other == 0 ) return ERR_MANIP_NIL;
- m_object->SetFret(other); // takes the ball
- other->SetTruck(m_object);
- other->SetTruckPart(0); // taken with the base
- other->SetPosition(0, Math::Vector(0.0f, -3.0f, 0.0f));
- }
- else
- {
- other = m_object->RetFret(); // other = ball
- m_object->SetFret(0); // lick the ball
- other->SetTruck(0);
- pos = m_object->RetPosition(0);
- pos.y -= 3.0f;
- other->SetPosition(0, pos);
-
- pos = m_object->RetPosition(0);
- pos.y += 2.0f;
- m_object->SetPosition(0, pos); // against the top of jump
-
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FALL, other); // the ball falls
- }
-
- m_bBee = true;
- m_bError = false; // ok
- return ERR_OK;
- }
- m_bBee = false;
-
- m_bSubm = ( type == OBJECT_MOBILEsa ); // submarine?
-
- if ( m_arm == TMA_GRAB ) // takes immediately?
- {
- TruckTakeObject();
- Abort();
- return ERR_OK;
- }
-
- m_energy = 0.0f;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- m_energy = power->RetEnergy();
- }
-
- if ( !m_physics->RetLand() ) return ERR_MANIP_FLY;
-
- if ( type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEsa ) return ERR_MANIP_VEH;
-
- if ( m_bSubm ) // submarine?
- {
- m_arm = TMA_FFRONT; // only possible in front!
- }
-
- m_move = 0.0f; // advance not necessary
- m_angle = iAngle;
-
- if ( order == TMO_AUTO )
- {
- if ( m_object->RetFret() == 0 )
- {
- m_order = TMO_GRAB;
- }
- else
- {
- m_order = TMO_DROP;
- }
- }
- else
- {
- m_order = order;
- }
-
- if ( m_order == TMO_GRAB && m_object->RetFret() != 0 )
- {
- return ERR_MANIP_BUSY;
- }
- if ( m_order == TMO_DROP && m_object->RetFret() == 0 )
- {
- return ERR_MANIP_EMPTY;
- }
-
-//? speed = m_physics->RetMotorSpeed();
-//? if ( speed.x != 0.0f ||
-//? speed.z != 0.0f ) return ERR_MANIP_MOTOR;
-
- if ( m_order == TMO_GRAB )
- {
- if ( m_arm == TMA_FFRONT )
- {
- front = SearchTakeFrontObject(true, fPos, fDist, fAngle);
- other = SearchOtherObject(true, oPos, oDist, oAngle, oHeight);
-
- if ( front != 0 && fDist < oDist )
- {
- m_targetPos = fPos;
- m_angle = fAngle;
- m_move = 1.0f; // advance required
- }
- else if ( other != 0 && oDist < fDist )
- {
- if ( other->RetPower() == 0 ) return ERR_MANIP_NIL;
- m_targetPos = oPos;
- m_angle = oAngle;
- m_height = oHeight;
- m_move = 1.0f; // advance required
- m_arm = TMA_OTHER;
- }
- else
- {
- return ERR_MANIP_NIL;
- }
- m_main->HideDropZone(front); // hides buildable area
- }
- if ( m_arm == TMA_FBACK )
- {
- if ( SearchTakeBackObject(true, m_targetPos, fDist, m_angle) == 0 )
- {
- return ERR_MANIP_NIL;
- }
- m_angle += Math::PI;
- m_move = -1.0f; // back necessary
- }
- if ( m_arm == TMA_POWER )
- {
- if ( m_object->RetPower() == 0 ) return ERR_MANIP_NIL;
- }
- }
-
- if ( m_order == TMO_DROP )
- {
- if ( m_arm == TMA_FFRONT )
- {
- other = SearchOtherObject(true, oPos, oDist, oAngle, oHeight);
- if ( other != 0 && other->RetPower() == 0 )
- {
- m_targetPos = oPos;
- m_angle = oAngle;
- m_height = oHeight;
- m_move = 1.0f; // advance required
- m_arm = TMA_OTHER;
- }
- else
- {
- if ( !IsFreeDeposeObject(Math::Vector(TAKE_DIST, 0.0f, 0.0f)) ) return ERR_MANIP_OCC;
- }
- }
- if ( m_arm == TMA_FBACK )
- {
- if ( !IsFreeDeposeObject(Math::Vector(-TAKE_DIST, 0.0f, 0.0f)) ) return ERR_MANIP_OCC;
- }
- if ( m_arm == TMA_POWER )
- {
- if ( m_object->RetPower() != 0 ) return ERR_MANIP_OCC;
- }
- }
-
- dist = Math::Distance(m_object->RetPosition(0), m_targetPos);
- len = dist-TAKE_DIST;
- if ( m_arm == TMA_OTHER ) len -= TAKE_DIST_OTHER;
- if ( len < 0.0f ) len = 0.0f;
- if ( m_arm == TMA_FBACK ) len = -len;
- m_advanceLength = dist-m_physics->RetLinLength(len);
- if ( dist <= m_advanceLength+0.2f ) m_move = 0.0f; // not necessary to advance
-
- if ( m_energy == 0.0f ) m_move = 0.0f;
-
- if ( m_move != 0.0f ) // forward or backward?
- {
- m_timeLimit = m_physics->RetLinTimeLength(fabs(len))*1.5f;
- if ( m_timeLimit < 0.5f ) m_timeLimit = 0.5f;
- }
-
- if ( m_object->RetFret() == 0 ) // not carrying anything?
- {
- m_hand = TMH_OPEN; // open clamp
- }
- else
- {
- m_hand = TMH_CLOSE; // closed clamp
- }
-
- InitAngle();
-
- if ( iAngle == m_angle || m_energy == 0.0f )
- {
- m_bTurn = false; // preliminary rotation unnecessary
- SoundManip(1.0f/m_speed);
- }
- else
- {
- m_bTurn = true; // preliminary rotation necessary
- }
-
- if ( m_bSubm )
- {
- m_camera->StartCentering(m_object, Math::PI*0.8f, 99.9f, 0.0f, 0.5f);
- }
-
- m_physics->SetFreeze(true); // it does not move
-
- m_bError = false; // ok
- return ERR_OK;
-}
-
-// Indicates whether the action is complete.
-
-Error CTaskManip::IsEnded()
-{
- CObject* fret;
- Math::Vector pos;
- float angle, dist;
- int i;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_bBee ) // bee?
- {
- return ERR_STOP;
- }
-
- if ( m_bTurn ) // preliminary rotation?
- {
- angle = m_object->RetAngleY(0);
- angle = Math::NormAngle(angle); // 0..2*Math::PI
-
- if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) )
- {
- m_bTurn = false; // rotation ended
- m_physics->SetMotorSpeedZ(0.0f);
- if ( m_move == 0.0f )
- {
- SoundManip(1.0f/m_speed);
- }
- }
- return ERR_CONTINUE;
- }
-
- if ( m_move != 0.0f ) // preliminary advance?
- {
- if ( m_timeLimit <= 0.0f )
- {
-//OK 1.9
- dist = Math::Distance(m_object->RetPosition(0), m_targetPos);
- if ( dist <= m_advanceLength + 2.0f )
- {
- m_move = 0.0f; // advance ended
- m_physics->SetMotorSpeedX(0.0f);
- SoundManip(1.0f/m_speed);
- return ERR_CONTINUE;
- }
- else
- {
-//EOK 1.9
- m_move = 0.0f; // advance ended
- m_physics->SetMotorSpeedX(0.0f); // stops
- Abort();
- return ERR_STOP;
- }
- }
-
- dist = Math::Distance(m_object->RetPosition(0), m_targetPos);
- if ( dist <= m_advanceLength )
- {
- m_move = 0.0f; // advance ended
- m_physics->SetMotorSpeedX(0.0f);
- SoundManip(1.0f/m_speed);
- }
- return ERR_CONTINUE;
- }
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( !m_bSubm )
- {
- for ( i=0 ; i<5 ; i++ )
- {
- m_object->SetAngleZ(i+1, m_finalAngle[i]);
- }
- }
- m_step ++;
-
- if ( m_order == TMO_GRAB )
- {
- if ( m_step == 1 )
- {
- if ( m_bSubm ) m_speed = 1.0f/0.7f;
- m_hand = TMH_CLOSE; // closes the clamp to take
- InitAngle();
- SoundManip(1.0f/m_speed, 0.8f, 1.5f);
- return ERR_CONTINUE;
- }
- if ( m_step == 2 )
- {
- if ( m_bSubm ) m_speed = 1.0f/1.5f;
- if ( !TruckTakeObject() &&
- m_object->RetFret() == 0 )
- {
- m_hand = TMH_OPEN; // reopens the clamp
- m_arm = TMA_NEUTRAL;
- InitAngle();
- SoundManip(1.0f/m_speed, 0.8f, 1.5f);
- }
- else
- {
- if ( (m_arm == TMA_OTHER ||
- m_arm == TMA_POWER ) &&
- (m_fretType == OBJECT_POWER ||
- m_fretType == OBJECT_ATOMIC ) )
- {
- m_sound->Play(SOUND_POWEROFF, m_object->RetPosition(0));
- }
- m_arm = TMA_STOCK;
- InitAngle();
- SoundManip(1.0f/m_speed);
- }
- return ERR_CONTINUE;
- }
- }
-
- if ( m_order == TMO_DROP )
- {
- if ( m_step == 1 )
- {
- if ( m_bSubm ) m_speed = 1.0f/0.7f;
- fret = m_object->RetFret();
- if ( TruckDeposeObject() )
- {
- if ( (m_arm == TMA_OTHER ||
- m_arm == TMA_POWER ) &&
- (m_fretType == OBJECT_POWER ||
- m_fretType == OBJECT_ATOMIC ) )
- {
- m_sound->Play(SOUND_POWERON, m_object->RetPosition(0));
- }
- if ( fret != 0 && m_fretType == OBJECT_METAL && m_arm == TMA_FFRONT )
- {
- m_main->ShowDropZone(fret, m_object); // shows buildable area
- }
- m_hand = TMH_OPEN; // opens the clamp to deposit
- SoundManip(1.0f/m_speed, 0.8f, 1.5f);
- }
- InitAngle();
- return ERR_CONTINUE;
- }
- if ( m_step == 2 )
- {
- if ( m_bSubm ) m_speed = 1.0f/1.5f;
- m_arm = TMA_NEUTRAL;
- InitAngle();
- SoundManip(1.0f/m_speed);
- return ERR_CONTINUE;
- }
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskManip::Abort()
-{
- int i;
-
- if ( m_object->RetFret() == 0 ) // not carrying anything?
- {
- m_hand = TMH_OPEN; // open clamp
- m_arm = TMA_NEUTRAL;
- }
- else
- {
- m_hand = TMH_CLOSE; // closed clamp
- m_arm = TMA_STOCK;
- }
- InitAngle();
-
- if ( !m_bSubm )
- {
- for ( i=0 ; i<5 ; i++ )
- {
- m_object->SetAngleZ(i+1, m_finalAngle[i]);
- }
- }
-
- m_camera->StopCentering(m_object, 2.0f);
- m_physics->SetFreeze(false); // is moving again
- return true;
-}
-
-
-// Seeks the object below to take (for bees).
-
-CObject* CTaskManip::SearchTakeUnderObject(Math::Vector &pos, float dLimit)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float min, distance;
- int i;
-
- iPos = m_object->RetPosition(0);
-
- min = 1000000.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
-
- if ( type != OBJECT_FRET &&
- type != OBJECT_STONE &&
- type != OBJECT_URANIUM &&
- type != OBJECT_BULLET &&
- type != OBJECT_METAL &&
- type != OBJECT_POWER &&
- type != OBJECT_ATOMIC &&
- type != OBJECT_BBOX &&
- type != OBJECT_KEYa &&
- type != OBJECT_KEYb &&
- type != OBJECT_KEYc &&
- type != OBJECT_KEYd &&
- type != OBJECT_TNT ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj->RetLock() ) continue;
- if ( pObj->RetZoomY(0) != 1.0f ) continue;
-
- oPos = pObj->RetPosition(0);
- distance = Math::Distance(oPos, iPos);
- if ( distance <= dLimit &&
- distance < min )
- {
- min = distance;
- pBest = pObj;
- }
- }
- if ( pBest != 0 )
- {
- pos = pBest->RetPosition(0);
- }
- return pBest;
-}
-
-// Seeks the object in front to take.
-
-CObject* CTaskManip::SearchTakeFrontObject(bool bAdvance, Math::Vector &pos,
- float &distance, float &angle)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float min, iAngle, bAngle, aLimit, dLimit, f;
- int i;
-
- iPos = m_object->RetPosition(0);
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- if ( bAdvance && m_energy > 0.0f )
- {
- aLimit = 60.0f*Math::PI/180.0f;
- dLimit = MARGIN_FRONT+10.0f;
- }
- else
- {
-//? aLimit = 7.0f*Math::PI/180.0f;
- aLimit = 15.0f*Math::PI/180.0f; //OK 1.9
- dLimit = MARGIN_FRONT;
- }
-
- min = 1000000.0f;
- pBest = 0;
- bAngle = 0.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
-
- if ( type != OBJECT_FRET &&
- type != OBJECT_STONE &&
- type != OBJECT_URANIUM &&
- type != OBJECT_BULLET &&
- type != OBJECT_METAL &&
- type != OBJECT_POWER &&
- type != OBJECT_ATOMIC &&
- type != OBJECT_BBOX &&
- type != OBJECT_KEYa &&
- type != OBJECT_KEYb &&
- type != OBJECT_KEYc &&
- type != OBJECT_KEYd &&
- type != OBJECT_TNT &&
- type != OBJECT_SCRAP1 &&
- type != OBJECT_SCRAP2 &&
- type != OBJECT_SCRAP3 &&
- type != OBJECT_SCRAP4 &&
- type != OBJECT_SCRAP5 ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj->RetLock() ) continue;
- if ( pObj->RetZoomY(0) != 1.0f ) continue;
-
- oPos = pObj->RetPosition(0);
- distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST);
- f = 1.0f-distance/50.0f;
- if ( f < 0.5f ) f = 0.5f;
-
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( !Math::TestAngle(angle, iAngle-aLimit*f, iAngle+aLimit*f) ) continue;
-
- if ( distance < -dLimit ||
- distance > dLimit ) continue;
-
- if ( distance < min )
- {
- min = distance;
- pBest = pObj;
- bAngle = angle;
- }
- }
- if ( pBest == 0 )
- {
- distance = 1000000.0f;
- angle = 0.0f;
- }
- else
- {
- pos = pBest->RetPosition(0);
- distance = min;
- angle = bAngle;
- }
- return pBest;
-}
-
-// Seeks the object back to take.
-
-CObject* CTaskManip::SearchTakeBackObject(bool bAdvance, Math::Vector &pos,
- float &distance, float &angle)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float min, iAngle, bAngle, aLimit, dLimit, f;
- int i;
-
- iPos = m_object->RetPosition(0);
- iAngle = m_object->RetAngleY(0)+Math::PI;
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- if ( bAdvance && m_energy > 0.0f )
- {
- aLimit = 60.0f*Math::PI/180.0f;
- dLimit = MARGIN_BACK+5.0f;
- }
- else
- {
- aLimit = 7.0f*Math::PI/180.0f;
- dLimit = MARGIN_BACK;
- }
-
- min = 1000000.0f;
- pBest = 0;
- bAngle = 0.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
-
- if ( type != OBJECT_FRET &&
- type != OBJECT_STONE &&
- type != OBJECT_URANIUM &&
- type != OBJECT_BULLET &&
- type != OBJECT_METAL &&
- type != OBJECT_POWER &&
- type != OBJECT_ATOMIC &&
- type != OBJECT_BBOX &&
- type != OBJECT_KEYa &&
- type != OBJECT_KEYb &&
- type != OBJECT_KEYc &&
- type != OBJECT_KEYd &&
- type != OBJECT_TNT &&
- type != OBJECT_SCRAP1 &&
- type != OBJECT_SCRAP2 &&
- type != OBJECT_SCRAP3 &&
- type != OBJECT_SCRAP4 &&
- type != OBJECT_SCRAP5 ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj->RetLock() ) continue;
- if ( pObj->RetZoomY(0) != 1.0f ) continue;
-
- oPos = pObj->RetPosition(0);
- distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST);
- f = 1.0f-distance/50.0f;
- if ( f < 0.5f ) f = 0.5f;
-
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( !Math::TestAngle(angle, iAngle-aLimit*f, iAngle+aLimit*f) ) continue;
-
- if ( distance < -dLimit ||
- distance > dLimit ) continue;
-
- if ( distance < min )
- {
- min = distance;
- pBest = pObj;
- bAngle = angle;
- }
- }
- if ( pBest == 0 )
- {
- distance = 1000000.0f;
- angle = 0.0f;
- }
- else
- {
- pos = pBest->RetPosition(0);
- distance = min;
- angle = bAngle;
- }
- return pBest;
-}
-
-// Seeks the robot or building on which it wants to put a battery or or other object.
-
-CObject* CTaskManip::SearchOtherObject(bool bAdvance, Math::Vector &pos,
- float &distance, float &angle,
- float &height)
-{
- Character* character;
- CObject* pObj;
- CObject* pPower;
- Math::Matrix* mat;
- Math::Vector iPos, oPos;
- ObjectType type, powerType;
- float iAngle, iRad, oAngle, oLimit, aLimit, dLimit;
- int i;
-
- distance = 1000000.0f;
- angle = 0.0f;
-
- if ( m_bSubm ) return 0; // impossible with the submarine
-
- if ( !m_object->GetCrashSphere(0, iPos, iRad) ) return 0;
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- if ( bAdvance && m_energy > 0.0f )
- {
- aLimit = 60.0f*Math::PI/180.0f;
- dLimit = MARGIN_FRIEND+10.0f;
- }
- else
- {
- aLimit = 7.0f*Math::PI/180.0f;
- dLimit = MARGIN_FRIEND;
- }
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue; // yourself?
-
- type = pObj->RetType();
- if ( type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_TOWER &&
- type != OBJECT_RESEARCH &&
- type != OBJECT_ENERGY &&
- type != OBJECT_LABO &&
- type != OBJECT_NUCLEAR ) continue;
-
- pPower = pObj->RetPower();
- if ( pPower != 0 )
- {
- if ( pPower->RetLock() ) continue;
- if ( pPower->RetZoomY(0) != 1.0f ) continue;
-
- powerType = pPower->RetType();
- if ( powerType == OBJECT_NULL ||
- powerType == OBJECT_FIX ) continue;
- }
-
- mat = pObj->RetWorldMatrix(0);
- character = pObj->RetCharacter();
- oPos = Transform(*mat, character->posPower);
-
- oAngle = pObj->RetAngleY(0);
- if ( type == OBJECT_TOWER ||
- type == OBJECT_RESEARCH )
- {
- oLimit = 45.0f*Math::PI/180.0f;
- }
- else if ( type == OBJECT_ENERGY )
- {
- oLimit = 90.0f*Math::PI/180.0f;
- }
- else if ( type == OBJECT_LABO )
- {
- oLimit = 120.0f*Math::PI/180.0f;
- }
- else if ( type == OBJECT_NUCLEAR )
- {
- oLimit = 45.0f*Math::PI/180.0f;
- }
- else
- {
- oLimit = 45.0f*Math::PI/180.0f;
- oAngle += Math::PI; // is behind
- }
- oAngle = Math::NormAngle(oAngle); // 0..2*Math::PI
- angle = Math::RotateAngle(iPos.x-oPos.x, oPos.z-iPos.z); // CW !
- if ( !Math::TestAngle(angle, oAngle-oLimit, oAngle+oLimit) ) continue;
-
- distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST);
- if ( distance <= dLimit )
- {
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
- {
- character = pObj->RetCharacter();
- height = character->posPower.y;
- pos = oPos;
- return pObj;
- }
- }
- }
-
- distance = 1000000.0f;
- angle = 0.0f;
- return 0;
-}
-
-// Takes the object placed in front.
-
-bool CTaskManip::TruckTakeObject()
-{
- CObject* fret;
- CObject* other;
- Math::Matrix matRotate;
- Math::Vector pos;
- float angle, dist;
-
- if ( m_arm == TMA_GRAB ) // takes immediately?
- {
- fret = m_object->RetFret();
- if ( fret == 0 ) return false; // nothing to take?
- m_fretType = fret->RetType();
-
- if ( m_object->RetType() == OBJECT_HUMAN ||
- m_object->RetType() == OBJECT_TECH )
- {
- fret->SetTruck(m_object);
- fret->SetTruckPart(4); // takes with the hand
-
- fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f));
- fret->SetAngleY(0, 0.1f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.8f);
- }
- else if ( m_bSubm )
- {
- fret->SetTruck(m_object);
- fret->SetTruckPart(2); // takes with the right claw
-
- pos = Math::Vector(1.1f, -1.0f, 1.0f); // relative
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleY(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- }
- else
- {
- fret->SetTruck(m_object);
- fret->SetTruckPart(3); // takes with the hand
-
- pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, Math::PI/2.0f);
- fret->SetAngleY(0, 0.0f);
- }
-
- m_object->SetFret(fret); // takes
- }
-
- if ( m_arm == TMA_FFRONT ) // takes on the ground in front?
- {
- fret = SearchTakeFrontObject(false, pos, dist, angle);
- if ( fret == 0 ) return false; // nothing to take?
- m_fretType = fret->RetType();
-
- if ( m_bSubm )
- {
- fret->SetTruck(m_object);
- fret->SetTruckPart(2); // takes with the right claw
-
- pos = Math::Vector(1.1f, -1.0f, 1.0f); // relative
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleY(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- }
- else
- {
- fret->SetTruck(m_object);
- fret->SetTruckPart(3); // takes with the hand
-
- pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, Math::PI/2.0f);
- fret->SetAngleY(0, 0.0f);
- }
-
- m_object->SetFret(fret); // takes
- }
-
- if ( m_arm == TMA_FBACK ) // takes on the ground behind?
- {
- fret = SearchTakeBackObject(false, pos, dist, angle);
- if ( fret == 0 ) return false; // nothing to take?
- m_fretType = fret->RetType();
-
- fret->SetTruck(m_object);
- fret->SetTruckPart(3); // takes with the hand
-
- pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, Math::PI/2.0f);
- fret->SetAngleY(0, 0.0f);
-
- m_object->SetFret(fret); // takes
- }
-
- if ( m_arm == TMA_POWER ) // takes battery in the back?
- {
- fret = m_object->RetPower();
- if ( fret == 0 ) return false; // no battery?
- m_fretType = fret->RetType();
-
- pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, Math::PI/2.0f);
- fret->SetAngleY(0, 0.0f);
- fret->SetTruckPart(3); // takes with the hand
-
- m_object->SetPower(0);
- m_object->SetFret(fret); // takes
- }
-
- if ( m_arm == TMA_OTHER ) // battery takes from friend?
- {
- other = SearchOtherObject(false, pos, dist, angle, m_height);
- if ( other == 0 ) return false;
-
- fret = other->RetPower();
- if ( fret == 0 ) return false; // the other does not have a battery?
- m_fretType = fret->RetType();
-
- other->SetPower(0);
- fret->SetTruck(m_object);
- fret->SetTruckPart(3); // takes with the hand
-
- pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, Math::PI/2.0f);
- fret->SetAngleY(0, 0.0f);
-
- m_object->SetFret(fret); // takes
- }
-
- return true;
-}
-
-// Deposes the object taken.
-
-bool CTaskManip::TruckDeposeObject()
-{
- Character* character;
- CObject* fret;
- CObject* other;
- Math::Matrix* mat;
- Math::Vector pos;
- float angle, dist;
-
- if ( m_arm == TMA_FFRONT ) // deposits on the ground in front?
- {
- fret = m_object->RetFret();
- if ( fret == 0 ) return false; // nothing transported?
- m_fretType = fret->RetType();
-
- mat = fret->RetWorldMatrix(0);
- pos = Transform(*mat, Math::Vector(0.0f, 1.0f, 0.0f));
- m_terrain->MoveOnFloor(pos);
- fret->SetPosition(0, pos);
- fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- fret->FloorAdjust(); // plate well on the ground
-
- fret->SetTruck(0);
- m_object->SetFret(0); // deposit
- }
-
- if ( m_arm == TMA_FBACK ) // deposited on the ground behind?
- {
- fret = m_object->RetFret();
- if ( fret == 0 ) return false; // nothing transported?
- m_fretType = fret->RetType();
-
- mat = fret->RetWorldMatrix(0);
- pos = Transform(*mat, Math::Vector(0.0f, 1.0f, 0.0f));
- m_terrain->MoveOnFloor(pos);
- fret->SetPosition(0, pos);
- fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
-
- fret->SetTruck(0);
- m_object->SetFret(0); // deposit
- }
-
- if ( m_arm == TMA_POWER ) // deposits battery in the back?
- {
- fret = m_object->RetFret();
- if ( fret == 0 ) return false; // nothing transported?
- m_fretType = fret->RetType();
-
- if ( m_object->RetPower() != 0 ) return false;
-
- fret->SetTruck(m_object);
- fret->SetTruckPart(0); // carried by the base
-
- character = m_object->RetCharacter();
- fret->SetPosition(0, character->posPower);
- fret->SetAngleY(0, 0.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
-
- m_object->SetPower(fret); // uses
- m_object->SetFret(0);
- }
-
- if ( m_arm == TMA_OTHER ) // deposits battery on friend?
- {
- other = SearchOtherObject(false, pos, dist, angle, m_height);
- if ( other == 0 ) return false;
-
- fret = other->RetPower();
- if ( fret != 0 ) return false; // the other already has a battery?
-
- fret = m_object->RetFret();
- if ( fret == 0 ) return false;
- m_fretType = fret->RetType();
-
- other->SetPower(fret);
- fret->SetTruck(other);
-
- character = other->RetCharacter();
- fret->SetPosition(0, character->posPower);
- fret->SetAngleY(0, 0.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- fret->SetTruckPart(0); // carried by the base
-
- m_object->SetFret(0); // deposit
- }
-
- return true;
-}
-
-// Seeks if a location allows to deposit an object.
-
-bool CTaskManip::IsFreeDeposeObject(Math::Vector pos)
-{
- CObject* pObj;
- Math::Matrix* mat;
- Math::Vector iPos, oPos;
- float oRadius;
- int i, j;
-
- mat = m_object->RetWorldMatrix(0);
- iPos = Transform(*mat, pos);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- if ( Math::Distance(iPos, oPos)-(oRadius+1.0f) < 2.0f )
- {
- return false; // location occupied
- }
- }
- }
- return true; // location free
-}
-
-// Plays the sound of the manipulator arm.
-
-void CTaskManip::SoundManip(float time, float amplitude, float frequency)
-{
- int i;
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
-}
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskmanip.cpp + + +#include <stdio.h> + +#include "object/task/taskmanip.h" + +#include "common/iman.h" +#include "old/terrain.h" +#include "old/pyro.h" +#include "math/geometry.h" +#include "object/robotmain.h" +#include "physics/physics.h" + + +//?const float MARGIN_FRONT = 2.0f; +//?const float MARGIN_BACK = 2.0f; +//?const float MARGIN_FRIEND = 2.0f; +//?const float MARGIN_BEE = 5.0f; +const float MARGIN_FRONT = 4.0f; //OK 1.9 +const float MARGIN_BACK = 4.0f; //OK 1.9 +const float MARGIN_FRIEND = 4.0f; //OK 1.9 +const float MARGIN_BEE = 5.0f; //OK 1.9 + + + + +// Object's constructor. + +CTaskManip::CTaskManip(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + m_arm = TMA_NEUTRAL; + m_hand = TMH_OPEN; +} + +// Object's destructor. + +CTaskManip::~CTaskManip() +{ +} + + +// Management of an event. + +bool CTaskManip::EventProcess(const Event &event) +{ + Math::Vector pos; + float angle, a, g, cirSpeed, progress; + int i; + + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + if ( m_bError ) return false; + + if ( m_bBee ) // bee? + { + return true; + } + + if ( m_bTurn ) // preliminary rotation? + { + a = m_object->RetAngleY(0); + g = m_angle; + cirSpeed = Math::Direction(a, g)*1.0f; + if ( m_physics->RetType() == TYPE_FLYING ) // flying on the ground? + { + cirSpeed *= 4.0f; // more fishing + } + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right + return true; + } + + if ( m_move != 0 ) // preliminary advance? + { + m_timeLimit -= event.rTime; + m_physics->SetMotorSpeedX(m_move); // forward/backward + return true; + } + + m_progress += event.rTime*m_speed; // others advance + progress = m_progress; + if ( progress > 1.0f ) progress = 1.0f; + + if ( m_bSubm ) // submarine? + { + if ( m_order == TMO_GRAB ) + { + if ( m_step == 0 ) // fall? + { + pos = m_object->RetPosition(1); + pos.y = 3.0f-progress*2.0f; + m_object->SetPosition(1, pos); + } + if ( m_step == 1 ) // farm? + { + pos = m_object->RetPosition(2); + pos.z = -1.5f+progress*0.5f; + m_object->SetPosition(2, pos); + + pos = m_object->RetPosition(3); + pos.z = 1.5f-progress*0.5f; + m_object->SetPosition(3, pos); + } + if ( m_step == 2 ) // up? + { + pos = m_object->RetPosition(1); + pos.y = 3.0f-(1.0f-progress)*2.0f; + m_object->SetPosition(1, pos); + } + } + else + { + if ( m_step == 0 ) // fall? + { + pos = m_object->RetPosition(1); + pos.y = 3.0f-progress*2.0f; + m_object->SetPosition(1, pos); + } + if ( m_step == 1 ) // farm? + { + pos = m_object->RetPosition(2); + pos.z = -1.5f+(1.0f-progress)*0.5f; + m_object->SetPosition(2, pos); + + pos = m_object->RetPosition(3); + pos.z = 1.5f-(1.0f-progress)*0.5f; + m_object->SetPosition(3, pos); + } + if ( m_step == 2 ) // up? + { + pos = m_object->RetPosition(1); + pos.y = 3.0f-(1.0f-progress)*2.0f; + m_object->SetPosition(1, pos); + } + } + } + else + { + for ( i=0 ; i<5 ; i++ ) + { + angle = (m_finalAngle[i]-m_initialAngle[i])*progress; + angle += m_initialAngle[i]; + m_object->SetAngleZ(i+1, angle); + } + } + + return true; +} + + +// Initializes the initial and final angles. + +void CTaskManip::InitAngle() +{ + CObject* power; + float max, energy; + int i; + + if ( m_bSubm || m_bBee ) return; + + if ( m_arm == TMA_NEUTRAL || + m_arm == TMA_GRAB ) + { + m_finalAngle[0] = ARM_NEUTRAL_ANGLE1; // arm + m_finalAngle[1] = ARM_NEUTRAL_ANGLE2; // forearm + m_finalAngle[2] = ARM_NEUTRAL_ANGLE3; // hand + } + if ( m_arm == TMA_STOCK ) + { + m_finalAngle[0] = ARM_STOCK_ANGLE1; // arm + m_finalAngle[1] = ARM_STOCK_ANGLE2; // forearm + m_finalAngle[2] = ARM_STOCK_ANGLE3; // hand + } + if ( m_arm == TMA_FFRONT ) + { + m_finalAngle[0] = 35.0f*Math::PI/180.0f; // arm + m_finalAngle[1] = -95.0f*Math::PI/180.0f; // forearm + m_finalAngle[2] = -27.0f*Math::PI/180.0f; // hand + } + if ( m_arm == TMA_FBACK ) + { + m_finalAngle[0] = 145.0f*Math::PI/180.0f; // arm + m_finalAngle[1] = 95.0f*Math::PI/180.0f; // forearm + m_finalAngle[2] = 27.0f*Math::PI/180.0f; // hand + } + if ( m_arm == TMA_POWER ) + { + m_finalAngle[0] = 95.0f*Math::PI/180.0f; // arm + m_finalAngle[1] = 125.0f*Math::PI/180.0f; // forearm + m_finalAngle[2] = 50.0f*Math::PI/180.0f; // hand + } + if ( m_arm == TMA_OTHER ) + { + if ( m_height <= 3.0f ) + { + m_finalAngle[0] = 55.0f*Math::PI/180.0f; // arm + m_finalAngle[1] = -90.0f*Math::PI/180.0f; // forearm + m_finalAngle[2] = -35.0f*Math::PI/180.0f; // hand + } + else + { + m_finalAngle[0] = 70.0f*Math::PI/180.0f; // arm + m_finalAngle[1] = -90.0f*Math::PI/180.0f; // forearm + m_finalAngle[2] = -50.0f*Math::PI/180.0f; // hand + } + } + + if ( m_hand == TMH_OPEN ) // open clamp? + { + m_finalAngle[3] = -Math::PI*0.10f; // clamp close + m_finalAngle[4] = Math::PI*0.10f; // clamp remote + } + if ( m_hand == TMH_CLOSE ) // clamp closed? + { + m_finalAngle[3] = Math::PI*0.05f; // clamp close + m_finalAngle[4] = -Math::PI*0.05f; // clamp remote + } + + for ( i=0 ; i<5 ; i++ ) + { + m_initialAngle[i] = m_object->RetAngleZ(i+1); + } + + max = 0.0f; + for ( i=0 ; i<5 ; i++ ) + { + max = Math::Max(max, fabs(m_initialAngle[i] - m_finalAngle[i])); + } + m_speed = (Math::PI*1.0f)/max; + if ( m_speed > 3.0f ) m_speed = 3.0f; // piano, ma non troppo (?) + + energy = 0.0f; + power = m_object->RetPower(); + if ( power != 0 ) + { + energy = power->RetEnergy(); + } + + if ( energy == 0.0f ) + { + m_speed *= 0.7f; // slower if more energy! + } +} + + +// Tests whether an object is compatible with the operation TMA_OTHER. + +bool TestFriend(ObjectType oType, ObjectType fType) +{ + if ( oType == OBJECT_ENERGY ) + { + return ( fType == OBJECT_METAL ); + } + if ( oType == OBJECT_LABO ) + { + return ( fType == OBJECT_BULLET ); + } + if ( oType == OBJECT_NUCLEAR ) + { + return ( fType == OBJECT_URANIUM ); + } + + return ( fType == OBJECT_POWER || + fType == OBJECT_ATOMIC ); +} + +// Assigns the goal was achieved. + +Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm) +{ + ObjectType type; + CObject *front, *other, *power; + CPyro *pyro; + float iAngle, dist, len; + float fDist, fAngle, oDist, oAngle, oHeight; + Math::Vector pos, fPos, oPos; + + m_arm = arm; + m_height = 0.0f; + m_step = 0; + m_progress = 0.0f; + m_speed = 1.0f/1.5f; + + iAngle = m_object->RetAngleY(0); + iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI + oAngle = iAngle; + + m_bError = true; // operation impossible + + if ( m_arm != TMA_FFRONT && + m_arm != TMA_FBACK && + m_arm != TMA_POWER && + m_arm != TMA_GRAB ) return ERR_MANIP_VEH; + + m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f)); + + type = m_object->RetType(); + if ( type == OBJECT_BEE ) // bee? + { + if ( m_object->RetFret() == 0 ) + { + if ( !m_physics->RetLand() ) return ERR_MANIP_FLY; + + other = SearchTakeUnderObject(m_targetPos, MARGIN_BEE); + if ( other == 0 ) return ERR_MANIP_NIL; + m_object->SetFret(other); // takes the ball + other->SetTruck(m_object); + other->SetTruckPart(0); // taken with the base + other->SetPosition(0, Math::Vector(0.0f, -3.0f, 0.0f)); + } + else + { + other = m_object->RetFret(); // other = ball + m_object->SetFret(0); // lick the ball + other->SetTruck(0); + pos = m_object->RetPosition(0); + pos.y -= 3.0f; + other->SetPosition(0, pos); + + pos = m_object->RetPosition(0); + pos.y += 2.0f; + m_object->SetPosition(0, pos); // against the top of jump + + pyro = new CPyro(m_iMan); + pyro->Create(PT_FALL, other); // the ball falls + } + + m_bBee = true; + m_bError = false; // ok + return ERR_OK; + } + m_bBee = false; + + m_bSubm = ( type == OBJECT_MOBILEsa ); // submarine? + + if ( m_arm == TMA_GRAB ) // takes immediately? + { + TruckTakeObject(); + Abort(); + return ERR_OK; + } + + m_energy = 0.0f; + power = m_object->RetPower(); + if ( power != 0 ) + { + m_energy = power->RetEnergy(); + } + + if ( !m_physics->RetLand() ) return ERR_MANIP_FLY; + + if ( type != OBJECT_MOBILEfa && + type != OBJECT_MOBILEta && + type != OBJECT_MOBILEwa && + type != OBJECT_MOBILEia && + type != OBJECT_MOBILEsa ) return ERR_MANIP_VEH; + + if ( m_bSubm ) // submarine? + { + m_arm = TMA_FFRONT; // only possible in front! + } + + m_move = 0.0f; // advance not necessary + m_angle = iAngle; + + if ( order == TMO_AUTO ) + { + if ( m_object->RetFret() == 0 ) + { + m_order = TMO_GRAB; + } + else + { + m_order = TMO_DROP; + } + } + else + { + m_order = order; + } + + if ( m_order == TMO_GRAB && m_object->RetFret() != 0 ) + { + return ERR_MANIP_BUSY; + } + if ( m_order == TMO_DROP && m_object->RetFret() == 0 ) + { + return ERR_MANIP_EMPTY; + } + +//? speed = m_physics->RetMotorSpeed(); +//? if ( speed.x != 0.0f || +//? speed.z != 0.0f ) return ERR_MANIP_MOTOR; + + if ( m_order == TMO_GRAB ) + { + if ( m_arm == TMA_FFRONT ) + { + front = SearchTakeFrontObject(true, fPos, fDist, fAngle); + other = SearchOtherObject(true, oPos, oDist, oAngle, oHeight); + + if ( front != 0 && fDist < oDist ) + { + m_targetPos = fPos; + m_angle = fAngle; + m_move = 1.0f; // advance required + } + else if ( other != 0 && oDist < fDist ) + { + if ( other->RetPower() == 0 ) return ERR_MANIP_NIL; + m_targetPos = oPos; + m_angle = oAngle; + m_height = oHeight; + m_move = 1.0f; // advance required + m_arm = TMA_OTHER; + } + else + { + return ERR_MANIP_NIL; + } + m_main->HideDropZone(front); // hides buildable area + } + if ( m_arm == TMA_FBACK ) + { + if ( SearchTakeBackObject(true, m_targetPos, fDist, m_angle) == 0 ) + { + return ERR_MANIP_NIL; + } + m_angle += Math::PI; + m_move = -1.0f; // back necessary + } + if ( m_arm == TMA_POWER ) + { + if ( m_object->RetPower() == 0 ) return ERR_MANIP_NIL; + } + } + + if ( m_order == TMO_DROP ) + { + if ( m_arm == TMA_FFRONT ) + { + other = SearchOtherObject(true, oPos, oDist, oAngle, oHeight); + if ( other != 0 && other->RetPower() == 0 ) + { + m_targetPos = oPos; + m_angle = oAngle; + m_height = oHeight; + m_move = 1.0f; // advance required + m_arm = TMA_OTHER; + } + else + { + if ( !IsFreeDeposeObject(Math::Vector(TAKE_DIST, 0.0f, 0.0f)) ) return ERR_MANIP_OCC; + } + } + if ( m_arm == TMA_FBACK ) + { + if ( !IsFreeDeposeObject(Math::Vector(-TAKE_DIST, 0.0f, 0.0f)) ) return ERR_MANIP_OCC; + } + if ( m_arm == TMA_POWER ) + { + if ( m_object->RetPower() != 0 ) return ERR_MANIP_OCC; + } + } + + dist = Math::Distance(m_object->RetPosition(0), m_targetPos); + len = dist-TAKE_DIST; + if ( m_arm == TMA_OTHER ) len -= TAKE_DIST_OTHER; + if ( len < 0.0f ) len = 0.0f; + if ( m_arm == TMA_FBACK ) len = -len; + m_advanceLength = dist-m_physics->RetLinLength(len); + if ( dist <= m_advanceLength+0.2f ) m_move = 0.0f; // not necessary to advance + + if ( m_energy == 0.0f ) m_move = 0.0f; + + if ( m_move != 0.0f ) // forward or backward? + { + m_timeLimit = m_physics->RetLinTimeLength(fabs(len))*1.5f; + if ( m_timeLimit < 0.5f ) m_timeLimit = 0.5f; + } + + if ( m_object->RetFret() == 0 ) // not carrying anything? + { + m_hand = TMH_OPEN; // open clamp + } + else + { + m_hand = TMH_CLOSE; // closed clamp + } + + InitAngle(); + + if ( iAngle == m_angle || m_energy == 0.0f ) + { + m_bTurn = false; // preliminary rotation unnecessary + SoundManip(1.0f/m_speed); + } + else + { + m_bTurn = true; // preliminary rotation necessary + } + + if ( m_bSubm ) + { + m_camera->StartCentering(m_object, Math::PI*0.8f, 99.9f, 0.0f, 0.5f); + } + + m_physics->SetFreeze(true); // it does not move + + m_bError = false; // ok + return ERR_OK; +} + +// Indicates whether the action is complete. + +Error CTaskManip::IsEnded() +{ + CObject* fret; + Math::Vector pos; + float angle, dist; + int i; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_bBee ) // bee? + { + return ERR_STOP; + } + + if ( m_bTurn ) // preliminary rotation? + { + angle = m_object->RetAngleY(0); + angle = Math::NormAngle(angle); // 0..2*Math::PI + + if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) ) + { + m_bTurn = false; // rotation ended + m_physics->SetMotorSpeedZ(0.0f); + if ( m_move == 0.0f ) + { + SoundManip(1.0f/m_speed); + } + } + return ERR_CONTINUE; + } + + if ( m_move != 0.0f ) // preliminary advance? + { + if ( m_timeLimit <= 0.0f ) + { +//OK 1.9 + dist = Math::Distance(m_object->RetPosition(0), m_targetPos); + if ( dist <= m_advanceLength + 2.0f ) + { + m_move = 0.0f; // advance ended + m_physics->SetMotorSpeedX(0.0f); + SoundManip(1.0f/m_speed); + return ERR_CONTINUE; + } + else + { +//EOK 1.9 + m_move = 0.0f; // advance ended + m_physics->SetMotorSpeedX(0.0f); // stops + Abort(); + return ERR_STOP; + } + } + + dist = Math::Distance(m_object->RetPosition(0), m_targetPos); + if ( dist <= m_advanceLength ) + { + m_move = 0.0f; // advance ended + m_physics->SetMotorSpeedX(0.0f); + SoundManip(1.0f/m_speed); + } + return ERR_CONTINUE; + } + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + m_progress = 0.0f; + + if ( !m_bSubm ) + { + for ( i=0 ; i<5 ; i++ ) + { + m_object->SetAngleZ(i+1, m_finalAngle[i]); + } + } + m_step ++; + + if ( m_order == TMO_GRAB ) + { + if ( m_step == 1 ) + { + if ( m_bSubm ) m_speed = 1.0f/0.7f; + m_hand = TMH_CLOSE; // closes the clamp to take + InitAngle(); + SoundManip(1.0f/m_speed, 0.8f, 1.5f); + return ERR_CONTINUE; + } + if ( m_step == 2 ) + { + if ( m_bSubm ) m_speed = 1.0f/1.5f; + if ( !TruckTakeObject() && + m_object->RetFret() == 0 ) + { + m_hand = TMH_OPEN; // reopens the clamp + m_arm = TMA_NEUTRAL; + InitAngle(); + SoundManip(1.0f/m_speed, 0.8f, 1.5f); + } + else + { + if ( (m_arm == TMA_OTHER || + m_arm == TMA_POWER ) && + (m_fretType == OBJECT_POWER || + m_fretType == OBJECT_ATOMIC ) ) + { + m_sound->Play(SOUND_POWEROFF, m_object->RetPosition(0)); + } + m_arm = TMA_STOCK; + InitAngle(); + SoundManip(1.0f/m_speed); + } + return ERR_CONTINUE; + } + } + + if ( m_order == TMO_DROP ) + { + if ( m_step == 1 ) + { + if ( m_bSubm ) m_speed = 1.0f/0.7f; + fret = m_object->RetFret(); + if ( TruckDeposeObject() ) + { + if ( (m_arm == TMA_OTHER || + m_arm == TMA_POWER ) && + (m_fretType == OBJECT_POWER || + m_fretType == OBJECT_ATOMIC ) ) + { + m_sound->Play(SOUND_POWERON, m_object->RetPosition(0)); + } + if ( fret != 0 && m_fretType == OBJECT_METAL && m_arm == TMA_FFRONT ) + { + m_main->ShowDropZone(fret, m_object); // shows buildable area + } + m_hand = TMH_OPEN; // opens the clamp to deposit + SoundManip(1.0f/m_speed, 0.8f, 1.5f); + } + InitAngle(); + return ERR_CONTINUE; + } + if ( m_step == 2 ) + { + if ( m_bSubm ) m_speed = 1.0f/1.5f; + m_arm = TMA_NEUTRAL; + InitAngle(); + SoundManip(1.0f/m_speed); + return ERR_CONTINUE; + } + } + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +bool CTaskManip::Abort() +{ + int i; + + if ( m_object->RetFret() == 0 ) // not carrying anything? + { + m_hand = TMH_OPEN; // open clamp + m_arm = TMA_NEUTRAL; + } + else + { + m_hand = TMH_CLOSE; // closed clamp + m_arm = TMA_STOCK; + } + InitAngle(); + + if ( !m_bSubm ) + { + for ( i=0 ; i<5 ; i++ ) + { + m_object->SetAngleZ(i+1, m_finalAngle[i]); + } + } + + m_camera->StopCentering(m_object, 2.0f); + m_physics->SetFreeze(false); // is moving again + return true; +} + + +// Seeks the object below to take (for bees). + +CObject* CTaskManip::SearchTakeUnderObject(Math::Vector &pos, float dLimit) +{ + CObject *pObj, *pBest; + Math::Vector iPos, oPos; + ObjectType type; + float min, distance; + int i; + + iPos = m_object->RetPosition(0); + + min = 1000000.0f; + pBest = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + + if ( type != OBJECT_FRET && + type != OBJECT_STONE && + type != OBJECT_URANIUM && + type != OBJECT_BULLET && + type != OBJECT_METAL && + type != OBJECT_POWER && + type != OBJECT_ATOMIC && + type != OBJECT_BBOX && + type != OBJECT_KEYa && + type != OBJECT_KEYb && + type != OBJECT_KEYc && + type != OBJECT_KEYd && + type != OBJECT_TNT ) continue; + + if ( pObj->RetTruck() != 0 ) continue; // object transported? + if ( pObj->RetLock() ) continue; + if ( pObj->RetZoomY(0) != 1.0f ) continue; + + oPos = pObj->RetPosition(0); + distance = Math::Distance(oPos, iPos); + if ( distance <= dLimit && + distance < min ) + { + min = distance; + pBest = pObj; + } + } + if ( pBest != 0 ) + { + pos = pBest->RetPosition(0); + } + return pBest; +} + +// Seeks the object in front to take. + +CObject* CTaskManip::SearchTakeFrontObject(bool bAdvance, Math::Vector &pos, + float &distance, float &angle) +{ + CObject *pObj, *pBest; + Math::Vector iPos, oPos; + ObjectType type; + float min, iAngle, bAngle, aLimit, dLimit, f; + int i; + + iPos = m_object->RetPosition(0); + iAngle = m_object->RetAngleY(0); + iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI + + if ( bAdvance && m_energy > 0.0f ) + { + aLimit = 60.0f*Math::PI/180.0f; + dLimit = MARGIN_FRONT+10.0f; + } + else + { +//? aLimit = 7.0f*Math::PI/180.0f; + aLimit = 15.0f*Math::PI/180.0f; //OK 1.9 + dLimit = MARGIN_FRONT; + } + + min = 1000000.0f; + pBest = 0; + bAngle = 0.0f; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + + if ( type != OBJECT_FRET && + type != OBJECT_STONE && + type != OBJECT_URANIUM && + type != OBJECT_BULLET && + type != OBJECT_METAL && + type != OBJECT_POWER && + type != OBJECT_ATOMIC && + type != OBJECT_BBOX && + type != OBJECT_KEYa && + type != OBJECT_KEYb && + type != OBJECT_KEYc && + type != OBJECT_KEYd && + type != OBJECT_TNT && + type != OBJECT_SCRAP1 && + type != OBJECT_SCRAP2 && + type != OBJECT_SCRAP3 && + type != OBJECT_SCRAP4 && + type != OBJECT_SCRAP5 ) continue; + + if ( pObj->RetTruck() != 0 ) continue; // object transported? + if ( pObj->RetLock() ) continue; + if ( pObj->RetZoomY(0) != 1.0f ) continue; + + oPos = pObj->RetPosition(0); + distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST); + f = 1.0f-distance/50.0f; + if ( f < 0.5f ) f = 0.5f; + + angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + if ( !Math::TestAngle(angle, iAngle-aLimit*f, iAngle+aLimit*f) ) continue; + + if ( distance < -dLimit || + distance > dLimit ) continue; + + if ( distance < min ) + { + min = distance; + pBest = pObj; + bAngle = angle; + } + } + if ( pBest == 0 ) + { + distance = 1000000.0f; + angle = 0.0f; + } + else + { + pos = pBest->RetPosition(0); + distance = min; + angle = bAngle; + } + return pBest; +} + +// Seeks the object back to take. + +CObject* CTaskManip::SearchTakeBackObject(bool bAdvance, Math::Vector &pos, + float &distance, float &angle) +{ + CObject *pObj, *pBest; + Math::Vector iPos, oPos; + ObjectType type; + float min, iAngle, bAngle, aLimit, dLimit, f; + int i; + + iPos = m_object->RetPosition(0); + iAngle = m_object->RetAngleY(0)+Math::PI; + iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI + + if ( bAdvance && m_energy > 0.0f ) + { + aLimit = 60.0f*Math::PI/180.0f; + dLimit = MARGIN_BACK+5.0f; + } + else + { + aLimit = 7.0f*Math::PI/180.0f; + dLimit = MARGIN_BACK; + } + + min = 1000000.0f; + pBest = 0; + bAngle = 0.0f; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + + if ( type != OBJECT_FRET && + type != OBJECT_STONE && + type != OBJECT_URANIUM && + type != OBJECT_BULLET && + type != OBJECT_METAL && + type != OBJECT_POWER && + type != OBJECT_ATOMIC && + type != OBJECT_BBOX && + type != OBJECT_KEYa && + type != OBJECT_KEYb && + type != OBJECT_KEYc && + type != OBJECT_KEYd && + type != OBJECT_TNT && + type != OBJECT_SCRAP1 && + type != OBJECT_SCRAP2 && + type != OBJECT_SCRAP3 && + type != OBJECT_SCRAP4 && + type != OBJECT_SCRAP5 ) continue; + + if ( pObj->RetTruck() != 0 ) continue; // object transported? + if ( pObj->RetLock() ) continue; + if ( pObj->RetZoomY(0) != 1.0f ) continue; + + oPos = pObj->RetPosition(0); + distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST); + f = 1.0f-distance/50.0f; + if ( f < 0.5f ) f = 0.5f; + + angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + if ( !Math::TestAngle(angle, iAngle-aLimit*f, iAngle+aLimit*f) ) continue; + + if ( distance < -dLimit || + distance > dLimit ) continue; + + if ( distance < min ) + { + min = distance; + pBest = pObj; + bAngle = angle; + } + } + if ( pBest == 0 ) + { + distance = 1000000.0f; + angle = 0.0f; + } + else + { + pos = pBest->RetPosition(0); + distance = min; + angle = bAngle; + } + return pBest; +} + +// Seeks the robot or building on which it wants to put a battery or or other object. + +CObject* CTaskManip::SearchOtherObject(bool bAdvance, Math::Vector &pos, + float &distance, float &angle, + float &height) +{ + Character* character; + CObject* pObj; + CObject* pPower; + Math::Matrix* mat; + Math::Vector iPos, oPos; + ObjectType type, powerType; + float iAngle, iRad, oAngle, oLimit, aLimit, dLimit; + int i; + + distance = 1000000.0f; + angle = 0.0f; + + if ( m_bSubm ) return 0; // impossible with the submarine + + if ( !m_object->GetCrashSphere(0, iPos, iRad) ) return 0; + iAngle = m_object->RetAngleY(0); + iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI + + if ( bAdvance && m_energy > 0.0f ) + { + aLimit = 60.0f*Math::PI/180.0f; + dLimit = MARGIN_FRIEND+10.0f; + } + else + { + aLimit = 7.0f*Math::PI/180.0f; + dLimit = MARGIN_FRIEND; + } + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; // yourself? + + type = pObj->RetType(); + if ( type != OBJECT_MOBILEfa && + type != OBJECT_MOBILEta && + type != OBJECT_MOBILEwa && + type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfc && + type != OBJECT_MOBILEtc && + type != OBJECT_MOBILEwc && + type != OBJECT_MOBILEic && + type != OBJECT_MOBILEfi && + type != OBJECT_MOBILEti && + type != OBJECT_MOBILEwi && + type != OBJECT_MOBILEii && + type != OBJECT_MOBILEfs && + type != OBJECT_MOBILEts && + type != OBJECT_MOBILEws && + type != OBJECT_MOBILEis && + type != OBJECT_MOBILErt && + type != OBJECT_MOBILErc && + type != OBJECT_MOBILErr && + type != OBJECT_MOBILErs && + type != OBJECT_MOBILEsa && + type != OBJECT_MOBILEtg && + type != OBJECT_MOBILEft && + type != OBJECT_MOBILEtt && + type != OBJECT_MOBILEwt && + type != OBJECT_MOBILEit && + type != OBJECT_TOWER && + type != OBJECT_RESEARCH && + type != OBJECT_ENERGY && + type != OBJECT_LABO && + type != OBJECT_NUCLEAR ) continue; + + pPower = pObj->RetPower(); + if ( pPower != 0 ) + { + if ( pPower->RetLock() ) continue; + if ( pPower->RetZoomY(0) != 1.0f ) continue; + + powerType = pPower->RetType(); + if ( powerType == OBJECT_NULL || + powerType == OBJECT_FIX ) continue; + } + + mat = pObj->RetWorldMatrix(0); + character = pObj->RetCharacter(); + oPos = Transform(*mat, character->posPower); + + oAngle = pObj->RetAngleY(0); + if ( type == OBJECT_TOWER || + type == OBJECT_RESEARCH ) + { + oLimit = 45.0f*Math::PI/180.0f; + } + else if ( type == OBJECT_ENERGY ) + { + oLimit = 90.0f*Math::PI/180.0f; + } + else if ( type == OBJECT_LABO ) + { + oLimit = 120.0f*Math::PI/180.0f; + } + else if ( type == OBJECT_NUCLEAR ) + { + oLimit = 45.0f*Math::PI/180.0f; + } + else + { + oLimit = 45.0f*Math::PI/180.0f; + oAngle += Math::PI; // is behind + } + oAngle = Math::NormAngle(oAngle); // 0..2*Math::PI + angle = Math::RotateAngle(iPos.x-oPos.x, oPos.z-iPos.z); // CW ! + if ( !Math::TestAngle(angle, oAngle-oLimit, oAngle+oLimit) ) continue; + + distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST); + if ( distance <= dLimit ) + { + angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) ) + { + character = pObj->RetCharacter(); + height = character->posPower.y; + pos = oPos; + return pObj; + } + } + } + + distance = 1000000.0f; + angle = 0.0f; + return 0; +} + +// Takes the object placed in front. + +bool CTaskManip::TruckTakeObject() +{ + CObject* fret; + CObject* other; + Math::Matrix matRotate; + Math::Vector pos; + float angle, dist; + + if ( m_arm == TMA_GRAB ) // takes immediately? + { + fret = m_object->RetFret(); + if ( fret == 0 ) return false; // nothing to take? + m_fretType = fret->RetType(); + + if ( m_object->RetType() == OBJECT_HUMAN || + m_object->RetType() == OBJECT_TECH ) + { + fret->SetTruck(m_object); + fret->SetTruckPart(4); // takes with the hand + + fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f)); + fret->SetAngleY(0, 0.1f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.8f); + } + else if ( m_bSubm ) + { + fret->SetTruck(m_object); + fret->SetTruckPart(2); // takes with the right claw + + pos = Math::Vector(1.1f, -1.0f, 1.0f); // relative + fret->SetPosition(0, pos); + fret->SetAngleX(0, 0.0f); + fret->SetAngleY(0, 0.0f); + fret->SetAngleZ(0, 0.0f); + } + else + { + fret->SetTruck(m_object); + fret->SetTruckPart(3); // takes with the hand + + pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4) + fret->SetPosition(0, pos); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, Math::PI/2.0f); + fret->SetAngleY(0, 0.0f); + } + + m_object->SetFret(fret); // takes + } + + if ( m_arm == TMA_FFRONT ) // takes on the ground in front? + { + fret = SearchTakeFrontObject(false, pos, dist, angle); + if ( fret == 0 ) return false; // nothing to take? + m_fretType = fret->RetType(); + + if ( m_bSubm ) + { + fret->SetTruck(m_object); + fret->SetTruckPart(2); // takes with the right claw + + pos = Math::Vector(1.1f, -1.0f, 1.0f); // relative + fret->SetPosition(0, pos); + fret->SetAngleX(0, 0.0f); + fret->SetAngleY(0, 0.0f); + fret->SetAngleZ(0, 0.0f); + } + else + { + fret->SetTruck(m_object); + fret->SetTruckPart(3); // takes with the hand + + pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4) + fret->SetPosition(0, pos); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, Math::PI/2.0f); + fret->SetAngleY(0, 0.0f); + } + + m_object->SetFret(fret); // takes + } + + if ( m_arm == TMA_FBACK ) // takes on the ground behind? + { + fret = SearchTakeBackObject(false, pos, dist, angle); + if ( fret == 0 ) return false; // nothing to take? + m_fretType = fret->RetType(); + + fret->SetTruck(m_object); + fret->SetTruckPart(3); // takes with the hand + + pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4) + fret->SetPosition(0, pos); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, Math::PI/2.0f); + fret->SetAngleY(0, 0.0f); + + m_object->SetFret(fret); // takes + } + + if ( m_arm == TMA_POWER ) // takes battery in the back? + { + fret = m_object->RetPower(); + if ( fret == 0 ) return false; // no battery? + m_fretType = fret->RetType(); + + pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4) + fret->SetPosition(0, pos); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, Math::PI/2.0f); + fret->SetAngleY(0, 0.0f); + fret->SetTruckPart(3); // takes with the hand + + m_object->SetPower(0); + m_object->SetFret(fret); // takes + } + + if ( m_arm == TMA_OTHER ) // battery takes from friend? + { + other = SearchOtherObject(false, pos, dist, angle, m_height); + if ( other == 0 ) return false; + + fret = other->RetPower(); + if ( fret == 0 ) return false; // the other does not have a battery? + m_fretType = fret->RetType(); + + other->SetPower(0); + fret->SetTruck(m_object); + fret->SetTruckPart(3); // takes with the hand + + pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4) + fret->SetPosition(0, pos); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, Math::PI/2.0f); + fret->SetAngleY(0, 0.0f); + + m_object->SetFret(fret); // takes + } + + return true; +} + +// Deposes the object taken. + +bool CTaskManip::TruckDeposeObject() +{ + Character* character; + CObject* fret; + CObject* other; + Math::Matrix* mat; + Math::Vector pos; + float angle, dist; + + if ( m_arm == TMA_FFRONT ) // deposits on the ground in front? + { + fret = m_object->RetFret(); + if ( fret == 0 ) return false; // nothing transported? + m_fretType = fret->RetType(); + + mat = fret->RetWorldMatrix(0); + pos = Transform(*mat, Math::Vector(0.0f, 1.0f, 0.0f)); + m_terrain->MoveOnFloor(pos); + fret->SetPosition(0, pos); + fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.0f); + fret->FloorAdjust(); // plate well on the ground + + fret->SetTruck(0); + m_object->SetFret(0); // deposit + } + + if ( m_arm == TMA_FBACK ) // deposited on the ground behind? + { + fret = m_object->RetFret(); + if ( fret == 0 ) return false; // nothing transported? + m_fretType = fret->RetType(); + + mat = fret->RetWorldMatrix(0); + pos = Transform(*mat, Math::Vector(0.0f, 1.0f, 0.0f)); + m_terrain->MoveOnFloor(pos); + fret->SetPosition(0, pos); + fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.0f); + + fret->SetTruck(0); + m_object->SetFret(0); // deposit + } + + if ( m_arm == TMA_POWER ) // deposits battery in the back? + { + fret = m_object->RetFret(); + if ( fret == 0 ) return false; // nothing transported? + m_fretType = fret->RetType(); + + if ( m_object->RetPower() != 0 ) return false; + + fret->SetTruck(m_object); + fret->SetTruckPart(0); // carried by the base + + character = m_object->RetCharacter(); + fret->SetPosition(0, character->posPower); + fret->SetAngleY(0, 0.0f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.0f); + + m_object->SetPower(fret); // uses + m_object->SetFret(0); + } + + if ( m_arm == TMA_OTHER ) // deposits battery on friend? + { + other = SearchOtherObject(false, pos, dist, angle, m_height); + if ( other == 0 ) return false; + + fret = other->RetPower(); + if ( fret != 0 ) return false; // the other already has a battery? + + fret = m_object->RetFret(); + if ( fret == 0 ) return false; + m_fretType = fret->RetType(); + + other->SetPower(fret); + fret->SetTruck(other); + + character = other->RetCharacter(); + fret->SetPosition(0, character->posPower); + fret->SetAngleY(0, 0.0f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.0f); + fret->SetTruckPart(0); // carried by the base + + m_object->SetFret(0); // deposit + } + + return true; +} + +// Seeks if a location allows to deposit an object. + +bool CTaskManip::IsFreeDeposeObject(Math::Vector pos) +{ + CObject* pObj; + Math::Matrix* mat; + Math::Vector iPos, oPos; + float oRadius; + int i, j; + + mat = m_object->RetWorldMatrix(0); + iPos = Transform(*mat, pos); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; + if ( !pObj->RetActif() ) continue; // inactive? + if ( pObj->RetTruck() != 0 ) continue; // object transported? + + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) + { + if ( Math::Distance(iPos, oPos)-(oRadius+1.0f) < 2.0f ) + { + return false; // location occupied + } + } + } + return true; // location free +} + +// Plays the sound of the manipulator arm. + +void CTaskManip::SoundManip(float time, float amplitude, float frequency) +{ + int i; + + i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true); + m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP); +} + diff --git a/src/object/task/taskmanip.h b/src/object/task/taskmanip.h index d915558..79d9ad5 100644 --- a/src/object/task/taskmanip.h +++ b/src/object/task/taskmanip.h @@ -1,99 +1,99 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskmanip.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-#include "math/vector.h"
-
-
-
-enum TaskManipOrder
-{
- TMO_AUTO = 0, // deposits or takes automatically
- TMO_GRAB = 1, // takes an object
- TMO_DROP = 2, // deposits the object
-};
-
-enum TaskManipArm
-{
- TMA_NEUTRAL = 1, // empty arm at rest
- TMA_STOCK = 2, // right arm resting
- TMA_FFRONT = 3, // arm on the ground
- TMA_FBACK = 4, // arm behind the robot
- TMA_POWER = 5, // arm behind the robot
- TMA_OTHER = 6, // arm behind a friend robot
- TMA_GRAB = 7, // takes immediately
-};
-
-enum TaskManipHand
-{
- TMH_OPEN = 1, // open clamp
- TMH_CLOSE = 2, // closed clamp
-};
-
-
-
-class CTaskManip : public CTask
-{
-public:
- CTaskManip(CInstanceManager* iMan, CObject* object);
- ~CTaskManip();
-
- bool EventProcess(const Event &event);
-
- Error Start(TaskManipOrder order, TaskManipArm arm);
- Error IsEnded();
- bool Abort();
-
-protected:
- void InitAngle();
- CObject* SearchTakeUnderObject(Math::Vector &pos, float dLimit);
- CObject* SearchTakeFrontObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle);
- CObject* SearchTakeBackObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle);
- CObject* SearchOtherObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle, float &height);
- bool TruckTakeObject();
- bool TruckDeposeObject();
- bool IsFreeDeposeObject(Math::Vector pos);
- void SoundManip(float time, float amplitude=1.0f, float frequency=1.0f);
-
-protected:
- TaskManipOrder m_order;
- TaskManipArm m_arm;
- TaskManipHand m_hand;
- int m_step;
- float m_speed;
- float m_progress;
- float m_initialAngle[5];
- float m_finalAngle[5];
- float m_height;
- float m_advanceLength;
- float m_energy;
- bool m_bError;
- bool m_bTurn;
- bool m_bSubm;
- bool m_bBee;
- float m_angle;
- float m_move;
- Math::Vector m_targetPos;
- float m_timeLimit;
- ObjectType m_fretType;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskmanip.h + +#pragma once + + +#include "object/task/task.h" +#include "object/object.h" +#include "math/vector.h" + + + +enum TaskManipOrder +{ + TMO_AUTO = 0, // deposits or takes automatically + TMO_GRAB = 1, // takes an object + TMO_DROP = 2, // deposits the object +}; + +enum TaskManipArm +{ + TMA_NEUTRAL = 1, // empty arm at rest + TMA_STOCK = 2, // right arm resting + TMA_FFRONT = 3, // arm on the ground + TMA_FBACK = 4, // arm behind the robot + TMA_POWER = 5, // arm behind the robot + TMA_OTHER = 6, // arm behind a friend robot + TMA_GRAB = 7, // takes immediately +}; + +enum TaskManipHand +{ + TMH_OPEN = 1, // open clamp + TMH_CLOSE = 2, // closed clamp +}; + + + +class CTaskManip : public CTask +{ +public: + CTaskManip(CInstanceManager* iMan, CObject* object); + ~CTaskManip(); + + bool EventProcess(const Event &event); + + Error Start(TaskManipOrder order, TaskManipArm arm); + Error IsEnded(); + bool Abort(); + +protected: + void InitAngle(); + CObject* SearchTakeUnderObject(Math::Vector &pos, float dLimit); + CObject* SearchTakeFrontObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle); + CObject* SearchTakeBackObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle); + CObject* SearchOtherObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle, float &height); + bool TruckTakeObject(); + bool TruckDeposeObject(); + bool IsFreeDeposeObject(Math::Vector pos); + void SoundManip(float time, float amplitude=1.0f, float frequency=1.0f); + +protected: + TaskManipOrder m_order; + TaskManipArm m_arm; + TaskManipHand m_hand; + int m_step; + float m_speed; + float m_progress; + float m_initialAngle[5]; + float m_finalAngle[5]; + float m_height; + float m_advanceLength; + float m_energy; + bool m_bError; + bool m_bTurn; + bool m_bSubm; + bool m_bBee; + float m_angle; + float m_move; + Math::Vector m_targetPos; + float m_timeLimit; + ObjectType m_fretType; +}; + diff --git a/src/object/task/taskpen.cpp b/src/object/task/taskpen.cpp index ff2f4e0..c3a9aef 100644 --- a/src/object/task/taskpen.cpp +++ b/src/object/task/taskpen.cpp @@ -1,287 +1,287 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskpen.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskpen.h"
-
-#include "old/particule.h"
-#include "math/geometry.h"
-#include "object/object.h"
-
-
-
-// Object's constructor.
-
-CTaskPen::CTaskPen(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskPen::~CTaskPen()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskPen::EventProcess(const Event &event)
-{
- Math::Vector pos, speed;
- Math::Point dim;
- int i;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- if ( m_delay == 0.0f )
- {
- m_progress = 1.0f;
- }
- else
- {
- m_progress += event.rTime*(1.0f/m_delay); // others advance
- if ( m_progress > 1.0f ) m_progress = 1.0f;
- }
-
- m_time += event.rTime;
-
- if ( m_phase == TPP_UP ) // back the pencil
- {
- i = AngleToRank(m_object->RetAngleY(1));
- pos = m_object->RetPosition(10+i);
- pos.y = -3.2f*(1.0f-m_progress);
- m_object->SetPosition(10+i, pos);
- }
-
- if ( m_phase == TPP_TURN ) // turns the carousel?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_supportPos;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = (Math::Rand()-0.5f)*3.0f;
- speed.z = (Math::Rand()-0.5f)*3.0f;
- speed.y = Math::Rand()*2.0f;
- dim.x = Math::Rand()*1.5f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
- }
-
- m_object->SetAngleY(1, m_oldAngle+(m_newAngle-m_oldAngle)*m_progress);
- }
-
- if ( m_phase == TPP_DOWN ) // down the pencil?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_supportPos;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = (Math::Rand()-0.5f)*3.0f;
- speed.z = (Math::Rand()-0.5f)*3.0f;
- speed.y = Math::Rand()*5.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIVAPOR, 4.0f);
- }
-
- i = AngleToRank(m_object->RetAngleY(1));
- pos = m_object->RetPosition(10+i);
- if ( m_timeDown == 0.0f )
- {
- pos.y = 0.0f;
- }
- else
- {
- pos.y = -3.2f*Math::Bounce(Math::Min(m_progress*1.8f, 1.0f));
- }
- m_object->SetPosition(10+i, pos);
- }
-
- return true;
-}
-
-
-// Assigns the goal has achieved.
-
-Error CTaskPen::Start(bool bDown, int color)
-{
- Math::Vector pos;
- Math::Matrix* mat;
- ObjectType type;
- int i;
-
- m_bError = true; // operation impossible
-
- type = m_object->RetType();
- if ( type != OBJECT_MOBILEdr ) return ERR_FIRE_VEH;
-
- m_bError = false; // ok
-
- m_oldAngle = m_object->RetAngleY(1);
- m_newAngle = ColorToAngle(color);
-
- i = AngleToRank(m_oldAngle);
- pos = m_object->RetPosition(10+i);
-
- if ( pos.y == 0.0f ) // pencil at the top?
- {
- m_timeUp = 0.0f;
- }
- else // pencil on the bottom?
- {
- m_timeUp = 1.0f; // must rise up
- }
-
- if ( bDown ) // must go down ?
- {
- m_timeDown = 0.7f;
- }
- else
- {
- m_timeDown = 0.0f;
- }
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(-3.0f, 7.0f, 0.0f);
- pos = Math::Transform(*mat, pos); // position of carousel
- m_supportPos = pos;
-
- m_phase = TPP_UP;
- m_progress = 0.0f;
- m_delay = m_timeUp;
- m_time = 0.0f;
-
- if ( m_timeUp > 0.0f )
- {
- SoundManip(m_timeUp, 1.0f, 0.5f);
- }
-
- m_lastParticule = 0.0f;
-
-//? m_camera->StartCentering(m_object, Math::PI*0.60f, 99.9f, 5.0f, 0.5f);
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskPen::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( m_phase == TPP_UP )
- {
- m_phase = TPP_TURN;
- m_progress = 0.0f;
- m_delay = fabs(m_oldAngle-m_newAngle)/Math::PI;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- if ( m_delay > 0.0f )
- {
- SoundManip(m_delay, 1.0f, 1.0f);
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TPP_TURN )
- {
- m_sound->Play(SOUND_PSHHH2, m_supportPos, 1.0f, 1.4f);
- m_phase = TPP_DOWN;
- m_progress = 0.0f;
- m_delay = m_timeDown;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- return ERR_CONTINUE;
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskPen::Abort()
-{
-//? m_camera->StopCentering(m_object, 0.5f);
- return true;
-}
-
-
-// Plays the sound of the manipulator arm.
-
-void CTaskPen::SoundManip(float time, float amplitude, float frequency)
-{
- int i;
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
-}
-
-
-// Converting a angle to number of pencil.
-
-int CTaskPen::AngleToRank(float angle)
-{
-//? return (int)(angle/(-45.0f*Math::PI/180.0f));
- angle = -angle;
- angle += (45.0f*Math::PI/180.0f)/2.0f;
- return (int)(angle/(45.0f*Math::PI/180.0f));
-}
-
-// Converting a color to the angle of carousel of pencils.
-
-float CTaskPen::ColorToAngle(int color)
-{
- return -45.0f*Math::PI/180.0f*ColorToRank(color);
-}
-
-// Converting a color number to the pencil (0 .. 7).
-
-int CTaskPen::ColorToRank(int color)
-{
- if ( color == 8 ) return 1; // yellow
- if ( color == 7 ) return 2; // orange
- if ( color == 5 ) return 2; // pink
- if ( color == 4 ) return 3; // red
- if ( color == 6 ) return 4; // purple
- if ( color == 14 ) return 5; // blue
- if ( color == 15 ) return 5; // light blue
- if ( color == 12 ) return 6; // green
- if ( color == 13 ) return 6; // light green
- if ( color == 10 ) return 7; // brown
- if ( color == 9 ) return 7; // beige
- return 0; // black
-}
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskpen.cpp + + +#include <stdio.h> + +#include "object/task/taskpen.h" + +#include "old/particule.h" +#include "math/geometry.h" +#include "object/object.h" + + + +// Object's constructor. + +CTaskPen::CTaskPen(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ +} + +// Object's destructor. + +CTaskPen::~CTaskPen() +{ +} + + +// Management of an event. + +bool CTaskPen::EventProcess(const Event &event) +{ + Math::Vector pos, speed; + Math::Point dim; + int i; + + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + if ( m_bError ) return false; + + if ( m_delay == 0.0f ) + { + m_progress = 1.0f; + } + else + { + m_progress += event.rTime*(1.0f/m_delay); // others advance + if ( m_progress > 1.0f ) m_progress = 1.0f; + } + + m_time += event.rTime; + + if ( m_phase == TPP_UP ) // back the pencil + { + i = AngleToRank(m_object->RetAngleY(1)); + pos = m_object->RetPosition(10+i); + pos.y = -3.2f*(1.0f-m_progress); + m_object->SetPosition(10+i, pos); + } + + if ( m_phase == TPP_TURN ) // turns the carousel? + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_supportPos; + pos.x += (Math::Rand()-0.5f)*5.0f; + pos.z += (Math::Rand()-0.5f)*5.0f; + speed.x = (Math::Rand()-0.5f)*3.0f; + speed.z = (Math::Rand()-0.5f)*3.0f; + speed.y = Math::Rand()*2.0f; + dim.x = Math::Rand()*1.5f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f); + } + + m_object->SetAngleY(1, m_oldAngle+(m_newAngle-m_oldAngle)*m_progress); + } + + if ( m_phase == TPP_DOWN ) // down the pencil? + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_supportPos; + pos.x += (Math::Rand()-0.5f)*5.0f; + pos.z += (Math::Rand()-0.5f)*5.0f; + speed.x = (Math::Rand()-0.5f)*3.0f; + speed.z = (Math::Rand()-0.5f)*3.0f; + speed.y = Math::Rand()*5.0f; + dim.x = Math::Rand()*1.0f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIVAPOR, 4.0f); + } + + i = AngleToRank(m_object->RetAngleY(1)); + pos = m_object->RetPosition(10+i); + if ( m_timeDown == 0.0f ) + { + pos.y = 0.0f; + } + else + { + pos.y = -3.2f*Math::Bounce(Math::Min(m_progress*1.8f, 1.0f)); + } + m_object->SetPosition(10+i, pos); + } + + return true; +} + + +// Assigns the goal has achieved. + +Error CTaskPen::Start(bool bDown, int color) +{ + Math::Vector pos; + Math::Matrix* mat; + ObjectType type; + int i; + + m_bError = true; // operation impossible + + type = m_object->RetType(); + if ( type != OBJECT_MOBILEdr ) return ERR_FIRE_VEH; + + m_bError = false; // ok + + m_oldAngle = m_object->RetAngleY(1); + m_newAngle = ColorToAngle(color); + + i = AngleToRank(m_oldAngle); + pos = m_object->RetPosition(10+i); + + if ( pos.y == 0.0f ) // pencil at the top? + { + m_timeUp = 0.0f; + } + else // pencil on the bottom? + { + m_timeUp = 1.0f; // must rise up + } + + if ( bDown ) // must go down ? + { + m_timeDown = 0.7f; + } + else + { + m_timeDown = 0.0f; + } + + mat = m_object->RetWorldMatrix(0); + pos = Math::Vector(-3.0f, 7.0f, 0.0f); + pos = Math::Transform(*mat, pos); // position of carousel + m_supportPos = pos; + + m_phase = TPP_UP; + m_progress = 0.0f; + m_delay = m_timeUp; + m_time = 0.0f; + + if ( m_timeUp > 0.0f ) + { + SoundManip(m_timeUp, 1.0f, 0.5f); + } + + m_lastParticule = 0.0f; + +//? m_camera->StartCentering(m_object, Math::PI*0.60f, 99.9f, 5.0f, 0.5f); + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskPen::IsEnded() +{ + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + m_progress = 0.0f; + + if ( m_phase == TPP_UP ) + { + m_phase = TPP_TURN; + m_progress = 0.0f; + m_delay = fabs(m_oldAngle-m_newAngle)/Math::PI; + m_time = 0.0f; + m_lastParticule = 0.0f; + if ( m_delay > 0.0f ) + { + SoundManip(m_delay, 1.0f, 1.0f); + } + return ERR_CONTINUE; + } + + if ( m_phase == TPP_TURN ) + { + m_sound->Play(SOUND_PSHHH2, m_supportPos, 1.0f, 1.4f); + m_phase = TPP_DOWN; + m_progress = 0.0f; + m_delay = m_timeDown; + m_time = 0.0f; + m_lastParticule = 0.0f; + return ERR_CONTINUE; + } + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +bool CTaskPen::Abort() +{ +//? m_camera->StopCentering(m_object, 0.5f); + return true; +} + + +// Plays the sound of the manipulator arm. + +void CTaskPen::SoundManip(float time, float amplitude, float frequency) +{ + int i; + + i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true); + m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP); +} + + +// Converting a angle to number of pencil. + +int CTaskPen::AngleToRank(float angle) +{ +//? return (int)(angle/(-45.0f*Math::PI/180.0f)); + angle = -angle; + angle += (45.0f*Math::PI/180.0f)/2.0f; + return (int)(angle/(45.0f*Math::PI/180.0f)); +} + +// Converting a color to the angle of carousel of pencils. + +float CTaskPen::ColorToAngle(int color) +{ + return -45.0f*Math::PI/180.0f*ColorToRank(color); +} + +// Converting a color number to the pencil (0 .. 7). + +int CTaskPen::ColorToRank(int color) +{ + if ( color == 8 ) return 1; // yellow + if ( color == 7 ) return 2; // orange + if ( color == 5 ) return 2; // pink + if ( color == 4 ) return 3; // red + if ( color == 6 ) return 4; // purple + if ( color == 14 ) return 5; // blue + if ( color == 15 ) return 5; // light blue + if ( color == 12 ) return 6; // green + if ( color == 13 ) return 6; // light green + if ( color == 10 ) return 7; // brown + if ( color == 9 ) return 7; // beige + return 0; // black +} + diff --git a/src/object/task/taskpen.h b/src/object/task/taskpen.h index 3c65d2e..b41c513 100644 --- a/src/object/task/taskpen.h +++ b/src/object/task/taskpen.h @@ -1,68 +1,68 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskpen.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-enum TaskPenPhase
-{
- TPP_UP = 1, // rises the pencil
- TPP_TURN = 2, // turns the carousel
- TPP_DOWN = 3, // descends the pencil
-};
-
-
-
-class CTaskPen : public CTask
-{
-public:
- CTaskPen(CInstanceManager* iMan, CObject* object);
- ~CTaskPen();
-
- bool EventProcess(const Event &event);
-
- Error Start(bool bDown, int color);
- Error IsEnded();
- bool Abort();
-
-protected:
- void SoundManip(float time, float amplitude, float frequency);
- int AngleToRank(float angle);
- float ColorToAngle(int color);
- int ColorToRank(int color);
-
-protected:
- bool m_bError;
- TaskPenPhase m_phase;
- float m_progress;
- float m_delay;
- float m_time;
- float m_lastParticule;
- Math::Vector m_supportPos;
-
- float m_timeUp;
- float m_oldAngle;
- float m_newAngle;
- float m_timeDown;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskpen.h + +#pragma once + + +#include "object/task/task.h" +#include "math/vector.h" + + + +enum TaskPenPhase +{ + TPP_UP = 1, // rises the pencil + TPP_TURN = 2, // turns the carousel + TPP_DOWN = 3, // descends the pencil +}; + + + +class CTaskPen : public CTask +{ +public: + CTaskPen(CInstanceManager* iMan, CObject* object); + ~CTaskPen(); + + bool EventProcess(const Event &event); + + Error Start(bool bDown, int color); + Error IsEnded(); + bool Abort(); + +protected: + void SoundManip(float time, float amplitude, float frequency); + int AngleToRank(float angle); + float ColorToAngle(int color); + int ColorToRank(int color); + +protected: + bool m_bError; + TaskPenPhase m_phase; + float m_progress; + float m_delay; + float m_time; + float m_lastParticule; + Math::Vector m_supportPos; + + float m_timeUp; + float m_oldAngle; + float m_newAngle; + float m_timeDown; +}; + diff --git a/src/object/task/taskrecover.cpp b/src/object/task/taskrecover.cpp index d91c45d..8f603f7 100644 --- a/src/object/task/taskrecover.cpp +++ b/src/object/task/taskrecover.cpp @@ -1,417 +1,417 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskrecover.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskrecover.h"
-
-#include "math/geometry.h"
-#include "common/iman.h"
-#include "old/particule.h"
-#include "physics/physics.h"
-#include "ui/displaytext.h"
-
-
-const float ENERGY_RECOVER = 0.25f; // energy consumed by recovery
-const float RECOVER_DIST = 11.8f;
-
-
-
-// Object's constructor.
-
-CTaskRecover::CTaskRecover(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_ruin = 0;
- m_soundChannel = -1;
-}
-
-// Object's constructor.
-
-CTaskRecover::~CTaskRecover()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskRecover::EventProcess(const Event &event)
-{
- CObject* power;
- Math::Vector pos, speed;
- Math::Point dim;
- float a, g, cirSpeed, angle, energy, dist, linSpeed;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- if ( m_phase == TRP_TURN ) // preliminary rotation?
- {
- a = m_object->RetAngleY(0);
- g = m_angle;
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- return true;
- }
-
- m_progress += event.rTime*m_speed; // others advance
- m_time += event.rTime;
-
- if ( m_phase == TRP_DOWN )
- {
- angle = Math::PropAngle(126, -10, m_progress);
- m_object->SetAngleZ(2, angle);
- m_object->SetAngleZ(4, angle);
-
- angle = Math::PropAngle(-144, 0, m_progress);
- m_object->SetAngleZ(3, angle);
- m_object->SetAngleZ(5, angle);
- }
-
- if ( m_phase == TRP_MOVE ) // preliminary forward/backward?
- {
- dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0));
- linSpeed = 0.0f;
- if ( dist > RECOVER_DIST ) linSpeed = 1.0f;
- if ( dist < RECOVER_DIST ) linSpeed = -1.0f;
- m_physics->SetMotorSpeedX(linSpeed); // forward/backward
- return true;
- }
-
- if ( m_phase == TRP_OPER )
- {
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- power->SetEnergy(energy-ENERGY_RECOVER*event.rTime*m_speed);
- }
-
- speed.x = (Math::Rand()-0.5f)*0.1f*m_progress;
- speed.y = (Math::Rand()-0.5f)*0.1f*m_progress;
- speed.z = (Math::Rand()-0.5f)*0.1f*m_progress;
- m_ruin->SetCirVibration(speed);
-
- if ( m_progress >= 0.75f )
- {
- m_ruin->SetZoom(0, 1.0f-(m_progress-0.75f)/0.25f);
- }
-
- if ( m_progress > 0.5f && m_progress < 0.8f )
- {
- m_metal->SetZoom(0, (m_progress-0.5f)/0.3f);
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.02f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_recoverPos;
- pos.x += (Math::Rand()-0.5f)*8.0f*(1.0f-m_progress);
- pos.z += (Math::Rand()-0.5f)*8.0f*(1.0f-m_progress);
- pos.y -= 4.0f;
- speed.x = (Math::Rand()-0.5f)*0.0f;
- speed.z = (Math::Rand()-0.5f)*0.0f;
- speed.y = Math::Rand()*15.0f;
- dim.x = Math::Rand()*2.0f+1.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIRECOVER, 1.0f, 0.0f, 0.0f);
- }
- }
-
- if ( m_phase == TRP_UP )
- {
- angle = Math::PropAngle(-10, 126, m_progress);
- m_object->SetAngleZ(2, angle);
- m_object->SetAngleZ(4, angle);
-
- angle = Math::PropAngle(0, -144, m_progress);
- m_object->SetAngleZ(3, angle);
- m_object->SetAngleZ(5, angle);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.02f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_recoverPos;
- pos.y -= 4.0f;
- speed.x = (Math::Rand()-0.5f)*0.0f;
- speed.z = (Math::Rand()-0.5f)*0.0f;
- speed.y = Math::Rand()*15.0f;
- dim.x = Math::Rand()*2.0f+1.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIRECOVER, 1.0f, 0.0f, 0.0f);
- }
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskRecover::Start()
-{
- CObject* power;
- Math::Matrix* mat;
- Math::Vector pos, iPos, oPos;
- float energy;
-
- ObjectType type;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() ) return ERR_RECOVER_VEH;
-
- type = m_object->RetType();
- if ( type != OBJECT_MOBILErr ) return ERR_RECOVER_VEH;
-
- power = m_object->RetPower();
- if ( power == 0 ) return ERR_RECOVER_ENERGY;
- energy = power->RetEnergy();
- if ( energy < ENERGY_RECOVER/power->RetCapacity()+0.05f ) return ERR_RECOVER_ENERGY;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(RECOVER_DIST, 3.3f, 0.0f);
- pos = Transform(*mat, pos); // position in front
- m_recoverPos = pos;
-
- m_ruin = SearchRuin();
- if ( m_ruin == 0 ) return ERR_RECOVER_NULL;
- m_ruin->SetLock(true); // ruin no longer usable
-
- iPos = m_object->RetPosition(0);
- oPos = m_ruin->RetPosition(0);
- m_angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
-
- m_metal = 0;
-
- m_phase = TRP_TURN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
-
- m_bError = false; // ok
-
- m_camera->StartCentering(m_object, Math::PI*0.85f, 99.9f, 10.0f, 3.0f);
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskRecover::IsEnded()
-{
- Math::Matrix* mat;
- Math::Vector pos, speed, goal;
- Math::Point dim;
- float angle, dist, time;
- int i;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_phase == TRP_TURN ) // preliminary rotation?
- {
- angle = m_object->RetAngleY(0);
- angle = Math::NormAngle(angle); // 0..2*Math::PI
-
- if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) )
- {
- m_physics->SetMotorSpeedZ(0.0f);
-
- dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0));
- if ( dist > RECOVER_DIST )
- {
- time = m_physics->RetLinTimeLength(dist-RECOVER_DIST, 1.0f);
- m_speed = 1.0f/time;
- }
- else
- {
- time = m_physics->RetLinTimeLength(RECOVER_DIST-dist, -1.0f);
- m_speed = 1.0f/time;
- }
- m_phase = TRP_MOVE;
- m_progress = 0.0f;
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TRP_MOVE ) // preliminary advance?
- {
- dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0));
-
- if ( dist >= RECOVER_DIST-1.0f &&
- dist <= RECOVER_DIST+1.0f )
- {
- m_physics->SetMotorSpeedX(0.0f);
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(RECOVER_DIST, 3.3f, 0.0f);
- pos = Transform(*mat, pos); // position in front
- m_recoverPos = pos;
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.9f, true);
- m_sound->AddEnvelope(i, 1.0f, 1.5f, 0.3f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 1.0f, 1.5f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.9f, 0.3f, SOPER_STOP);
-
- m_phase = TRP_DOWN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- m_time = 0.0f;
- }
- else
- {
- if ( m_progress > 1.0f ) // timeout?
- {
- m_ruin->SetLock(false); // usable again
- m_camera->StopCentering(m_object, 2.0f);
- return ERR_RECOVER_NULL;
- }
- }
- return ERR_CONTINUE;
- }
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( m_phase == TRP_DOWN )
- {
- m_metal = new CObject(m_iMan);
- if ( !m_metal->CreateResource(m_recoverPos, 0.0f, OBJECT_METAL) )
- {
- delete m_metal;
- m_metal = 0;
- Abort();
- m_bError = true;
- m_displayText->DisplayError(ERR_TOOMANY, m_object);
- return ERR_STOP;
- }
- m_metal->SetLock(true); // metal not yet usable
- m_metal->SetZoom(0, 0.0f);
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(RECOVER_DIST, 3.1f, 3.9f);
- pos = Transform(*mat, pos);
- goal = Math::Vector(RECOVER_DIST, 3.1f, -3.9f);
- goal = Transform(*mat, goal);
- m_particule->CreateRay(pos, goal, PARTIRAY2,
- Math::Point(2.0f, 2.0f), 8.0f);
-
- m_soundChannel = m_sound->Play(SOUND_RECOVER, m_ruin->RetPosition(0), 0.0f, 1.0f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.6f, 1.0f, 2.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.6f, 1.0f, 4.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.7f, 2.0f, SOPER_STOP);
-
- m_phase = TRP_OPER;
- m_speed = 1.0f/8.0f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TRP_OPER )
- {
- m_metal->SetZoom(0, 1.0f);
-
- m_ruin->DeleteObject(); // destroys the ruin
- delete m_ruin;
- m_ruin = 0;
-
- m_soundChannel = -1;
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.9f, true);
- m_sound->AddEnvelope(i, 1.0f, 1.5f, 0.3f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 1.0f, 1.5f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.9f, 0.3f, SOPER_STOP);
-
- m_phase = TRP_UP;
- m_speed = 1.0f/1.5f;
- return ERR_CONTINUE;
- }
-
- m_metal->SetLock(false); // metal usable
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskRecover::Abort()
-{
- m_object->SetAngleZ(2, 126.0f*Math::PI/180.0f);
- m_object->SetAngleZ(4, 126.0f*Math::PI/180.0f);
- m_object->SetAngleZ(3, -144.0f*Math::PI/180.0f);
- m_object->SetAngleZ(5, -144.0f*Math::PI/180.0f); // rest
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- m_camera->StopCentering(m_object, 2.0f);
- return true;
-}
-
-
-// Seeks if a ruin is in front of the vehicle.
-
-CObject* CTaskRecover::SearchRuin()
-{
- CObject *pObj, *pBest;
- Math::Vector oPos;
- ObjectType type;
- float dist, min;
- int i;
-
- pBest = 0;
- min = 100000.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_RUINmobilew1 ||
- type == OBJECT_RUINmobilew2 ||
- type == OBJECT_RUINmobilet1 ||
- type == OBJECT_RUINmobilet2 ||
- type == OBJECT_RUINmobiler1 ||
- type == OBJECT_RUINmobiler2 ) // vehicle in ruin?
- {
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, m_recoverPos);
- if ( dist > 40.0f ) continue;
-
- if ( dist < min )
- {
- min = dist;
- pBest = pObj;
- }
- }
-
- }
- return pBest;
-}
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskrecover.cpp + + +#include <stdio.h> + +#include "object/task/taskrecover.h" + +#include "math/geometry.h" +#include "common/iman.h" +#include "old/particule.h" +#include "physics/physics.h" +#include "ui/displaytext.h" + + +const float ENERGY_RECOVER = 0.25f; // energy consumed by recovery +const float RECOVER_DIST = 11.8f; + + + +// Object's constructor. + +CTaskRecover::CTaskRecover(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + m_ruin = 0; + m_soundChannel = -1; +} + +// Object's constructor. + +CTaskRecover::~CTaskRecover() +{ +} + + +// Management of an event. + +bool CTaskRecover::EventProcess(const Event &event) +{ + CObject* power; + Math::Vector pos, speed; + Math::Point dim; + float a, g, cirSpeed, angle, energy, dist, linSpeed; + + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + if ( m_bError ) return false; + + if ( m_phase == TRP_TURN ) // preliminary rotation? + { + a = m_object->RetAngleY(0); + g = m_angle; + cirSpeed = Math::Direction(a, g)*1.0f; + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right + return true; + } + + m_progress += event.rTime*m_speed; // others advance + m_time += event.rTime; + + if ( m_phase == TRP_DOWN ) + { + angle = Math::PropAngle(126, -10, m_progress); + m_object->SetAngleZ(2, angle); + m_object->SetAngleZ(4, angle); + + angle = Math::PropAngle(-144, 0, m_progress); + m_object->SetAngleZ(3, angle); + m_object->SetAngleZ(5, angle); + } + + if ( m_phase == TRP_MOVE ) // preliminary forward/backward? + { + dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0)); + linSpeed = 0.0f; + if ( dist > RECOVER_DIST ) linSpeed = 1.0f; + if ( dist < RECOVER_DIST ) linSpeed = -1.0f; + m_physics->SetMotorSpeedX(linSpeed); // forward/backward + return true; + } + + if ( m_phase == TRP_OPER ) + { + power = m_object->RetPower(); + if ( power != 0 ) + { + energy = power->RetEnergy(); + power->SetEnergy(energy-ENERGY_RECOVER*event.rTime*m_speed); + } + + speed.x = (Math::Rand()-0.5f)*0.1f*m_progress; + speed.y = (Math::Rand()-0.5f)*0.1f*m_progress; + speed.z = (Math::Rand()-0.5f)*0.1f*m_progress; + m_ruin->SetCirVibration(speed); + + if ( m_progress >= 0.75f ) + { + m_ruin->SetZoom(0, 1.0f-(m_progress-0.75f)/0.25f); + } + + if ( m_progress > 0.5f && m_progress < 0.8f ) + { + m_metal->SetZoom(0, (m_progress-0.5f)/0.3f); + } + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.02f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_recoverPos; + pos.x += (Math::Rand()-0.5f)*8.0f*(1.0f-m_progress); + pos.z += (Math::Rand()-0.5f)*8.0f*(1.0f-m_progress); + pos.y -= 4.0f; + speed.x = (Math::Rand()-0.5f)*0.0f; + speed.z = (Math::Rand()-0.5f)*0.0f; + speed.y = Math::Rand()*15.0f; + dim.x = Math::Rand()*2.0f+1.5f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIRECOVER, 1.0f, 0.0f, 0.0f); + } + } + + if ( m_phase == TRP_UP ) + { + angle = Math::PropAngle(-10, 126, m_progress); + m_object->SetAngleZ(2, angle); + m_object->SetAngleZ(4, angle); + + angle = Math::PropAngle(0, -144, m_progress); + m_object->SetAngleZ(3, angle); + m_object->SetAngleZ(5, angle); + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.02f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_recoverPos; + pos.y -= 4.0f; + speed.x = (Math::Rand()-0.5f)*0.0f; + speed.z = (Math::Rand()-0.5f)*0.0f; + speed.y = Math::Rand()*15.0f; + dim.x = Math::Rand()*2.0f+1.5f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIRECOVER, 1.0f, 0.0f, 0.0f); + } + } + + return true; +} + + +// Assigns the goal was achieved. + +Error CTaskRecover::Start() +{ + CObject* power; + Math::Matrix* mat; + Math::Vector pos, iPos, oPos; + float energy; + + ObjectType type; + + m_bError = true; // operation impossible + if ( !m_physics->RetLand() ) return ERR_RECOVER_VEH; + + type = m_object->RetType(); + if ( type != OBJECT_MOBILErr ) return ERR_RECOVER_VEH; + + power = m_object->RetPower(); + if ( power == 0 ) return ERR_RECOVER_ENERGY; + energy = power->RetEnergy(); + if ( energy < ENERGY_RECOVER/power->RetCapacity()+0.05f ) return ERR_RECOVER_ENERGY; + + mat = m_object->RetWorldMatrix(0); + pos = Math::Vector(RECOVER_DIST, 3.3f, 0.0f); + pos = Transform(*mat, pos); // position in front + m_recoverPos = pos; + + m_ruin = SearchRuin(); + if ( m_ruin == 0 ) return ERR_RECOVER_NULL; + m_ruin->SetLock(true); // ruin no longer usable + + iPos = m_object->RetPosition(0); + oPos = m_ruin->RetPosition(0); + m_angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + + m_metal = 0; + + m_phase = TRP_TURN; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + m_time = 0.0f; + m_lastParticule = 0.0f; + + m_bError = false; // ok + + m_camera->StartCentering(m_object, Math::PI*0.85f, 99.9f, 10.0f, 3.0f); + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskRecover::IsEnded() +{ + Math::Matrix* mat; + Math::Vector pos, speed, goal; + Math::Point dim; + float angle, dist, time; + int i; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_phase == TRP_TURN ) // preliminary rotation? + { + angle = m_object->RetAngleY(0); + angle = Math::NormAngle(angle); // 0..2*Math::PI + + if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) ) + { + m_physics->SetMotorSpeedZ(0.0f); + + dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0)); + if ( dist > RECOVER_DIST ) + { + time = m_physics->RetLinTimeLength(dist-RECOVER_DIST, 1.0f); + m_speed = 1.0f/time; + } + else + { + time = m_physics->RetLinTimeLength(RECOVER_DIST-dist, -1.0f); + m_speed = 1.0f/time; + } + m_phase = TRP_MOVE; + m_progress = 0.0f; + } + return ERR_CONTINUE; + } + + if ( m_phase == TRP_MOVE ) // preliminary advance? + { + dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0)); + + if ( dist >= RECOVER_DIST-1.0f && + dist <= RECOVER_DIST+1.0f ) + { + m_physics->SetMotorSpeedX(0.0f); + + mat = m_object->RetWorldMatrix(0); + pos = Math::Vector(RECOVER_DIST, 3.3f, 0.0f); + pos = Transform(*mat, pos); // position in front + m_recoverPos = pos; + + i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.9f, true); + m_sound->AddEnvelope(i, 1.0f, 1.5f, 0.3f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 1.0f, 1.5f, 1.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.0f, 0.9f, 0.3f, SOPER_STOP); + + m_phase = TRP_DOWN; + m_progress = 0.0f; + m_speed = 1.0f/1.5f; + m_time = 0.0f; + } + else + { + if ( m_progress > 1.0f ) // timeout? + { + m_ruin->SetLock(false); // usable again + m_camera->StopCentering(m_object, 2.0f); + return ERR_RECOVER_NULL; + } + } + return ERR_CONTINUE; + } + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + m_progress = 0.0f; + + if ( m_phase == TRP_DOWN ) + { + m_metal = new CObject(m_iMan); + if ( !m_metal->CreateResource(m_recoverPos, 0.0f, OBJECT_METAL) ) + { + delete m_metal; + m_metal = 0; + Abort(); + m_bError = true; + m_displayText->DisplayError(ERR_TOOMANY, m_object); + return ERR_STOP; + } + m_metal->SetLock(true); // metal not yet usable + m_metal->SetZoom(0, 0.0f); + + mat = m_object->RetWorldMatrix(0); + pos = Math::Vector(RECOVER_DIST, 3.1f, 3.9f); + pos = Transform(*mat, pos); + goal = Math::Vector(RECOVER_DIST, 3.1f, -3.9f); + goal = Transform(*mat, goal); + m_particule->CreateRay(pos, goal, PARTIRAY2, + Math::Point(2.0f, 2.0f), 8.0f); + + m_soundChannel = m_sound->Play(SOUND_RECOVER, m_ruin->RetPosition(0), 0.0f, 1.0f, true); + m_sound->AddEnvelope(m_soundChannel, 0.6f, 1.0f, 2.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.6f, 1.0f, 4.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.7f, 2.0f, SOPER_STOP); + + m_phase = TRP_OPER; + m_speed = 1.0f/8.0f; + return ERR_CONTINUE; + } + + if ( m_phase == TRP_OPER ) + { + m_metal->SetZoom(0, 1.0f); + + m_ruin->DeleteObject(); // destroys the ruin + delete m_ruin; + m_ruin = 0; + + m_soundChannel = -1; + + i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.9f, true); + m_sound->AddEnvelope(i, 1.0f, 1.5f, 0.3f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 1.0f, 1.5f, 1.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.0f, 0.9f, 0.3f, SOPER_STOP); + + m_phase = TRP_UP; + m_speed = 1.0f/1.5f; + return ERR_CONTINUE; + } + + m_metal->SetLock(false); // metal usable + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +bool CTaskRecover::Abort() +{ + m_object->SetAngleZ(2, 126.0f*Math::PI/180.0f); + m_object->SetAngleZ(4, 126.0f*Math::PI/180.0f); + m_object->SetAngleZ(3, -144.0f*Math::PI/180.0f); + m_object->SetAngleZ(5, -144.0f*Math::PI/180.0f); // rest + + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + + m_camera->StopCentering(m_object, 2.0f); + return true; +} + + +// Seeks if a ruin is in front of the vehicle. + +CObject* CTaskRecover::SearchRuin() +{ + CObject *pObj, *pBest; + Math::Vector oPos; + ObjectType type; + float dist, min; + int i; + + pBest = 0; + min = 100000.0f; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type == OBJECT_RUINmobilew1 || + type == OBJECT_RUINmobilew2 || + type == OBJECT_RUINmobilet1 || + type == OBJECT_RUINmobilet2 || + type == OBJECT_RUINmobiler1 || + type == OBJECT_RUINmobiler2 ) // vehicle in ruin? + { + oPos = pObj->RetPosition(0); + dist = Math::Distance(oPos, m_recoverPos); + if ( dist > 40.0f ) continue; + + if ( dist < min ) + { + min = dist; + pBest = pObj; + } + } + + } + return pBest; +} + diff --git a/src/object/task/taskrecover.h b/src/object/task/taskrecover.h index 5ee696a..8af6353 100644 --- a/src/object/task/taskrecover.h +++ b/src/object/task/taskrecover.h @@ -1,66 +1,66 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskrecover.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-enum TaskRecoverPhase
-{
- TRP_TURN = 1, // turns
- TRP_MOVE = 2, // advance
- TRP_DOWN = 3, // descends
- TRP_OPER = 4, // operates
- TRP_UP = 5, // back
-};
-
-
-
-class CTaskRecover : public CTask
-{
-public:
- CTaskRecover(CInstanceManager* iMan, CObject* object);
- ~CTaskRecover();
-
- bool EventProcess(const Event &event);
-
- Error Start();
- Error IsEnded();
- bool Abort();
-
-protected:
- CObject* SearchRuin();
-
-protected:
- TaskRecoverPhase m_phase;
- float m_progress;
- float m_speed;
- float m_time;
- float m_angle;
- float m_lastParticule;
- bool m_bError;
- CObject* m_ruin;
- CObject* m_metal;
- Math::Vector m_recoverPos;
- int m_soundChannel;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskrecover.h + +#pragma once + + +#include "object/task/task.h" +#include "math/vector.h" + + + +enum TaskRecoverPhase +{ + TRP_TURN = 1, // turns + TRP_MOVE = 2, // advance + TRP_DOWN = 3, // descends + TRP_OPER = 4, // operates + TRP_UP = 5, // back +}; + + + +class CTaskRecover : public CTask +{ +public: + CTaskRecover(CInstanceManager* iMan, CObject* object); + ~CTaskRecover(); + + bool EventProcess(const Event &event); + + Error Start(); + Error IsEnded(); + bool Abort(); + +protected: + CObject* SearchRuin(); + +protected: + TaskRecoverPhase m_phase; + float m_progress; + float m_speed; + float m_time; + float m_angle; + float m_lastParticule; + bool m_bError; + CObject* m_ruin; + CObject* m_metal; + Math::Vector m_recoverPos; + int m_soundChannel; +}; + diff --git a/src/object/task/taskreset.cpp b/src/object/task/taskreset.cpp index ab41076..2366fea 100644 --- a/src/object/task/taskreset.cpp +++ b/src/object/task/taskreset.cpp @@ -1,330 +1,330 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskreset.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskreset.h"
-
-#include "common/iman.h"
-#include "object/brain.h"
-#include "object/robotmain.h"
-
-
-
-const float RESET_DELAY_ZOOM = 0.7f;
-const float RESET_DELAY_MOVE = 0.7f;
-
-
-
-
-// Object's constructor.
-
-CTaskReset::CTaskReset(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskReset::~CTaskReset()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskReset::EventProcess(const Event &event)
-{
- Math::Vector pos, speed;
- Math::Point dim;
- float angle, duration;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_time += event.rTime;
- m_progress += event.rTime*m_speed;
-
- if ( m_phase == TRSP_ZOUT )
- {
- angle = m_iAngle;
- angle += powf(m_progress*5.0f, 2.0f); // accelerates
- m_object->SetAngleY(0, angle);
- m_object->SetZoom(0, 1.0f-m_progress);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_begin;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 5.0f+Math::Rand()*5.0f;
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
-
- pos = m_begin;
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = Math::Rand()*10.0f;
- speed *= 1.0f-m_progress*0.5f;
- pos += speed*1.5f;
- speed = -speed;
- dim.x = 0.6f;
- dim.y = dim.x;
- pos.y += dim.y;
- duration = Math::Rand()*1.5f+1.5f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
- duration, 0.0f,
- duration*0.9f, 0.7f);
- }
- }
-
- if ( m_phase == TRSP_MOVE )
- {
- pos = m_begin+(m_goal-m_begin)*m_progress;
- m_object->SetPosition(0, pos);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 2.0f+Math::Rand()*2.0f;
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
- }
- }
-
- if ( m_phase == TRSP_ZIN )
- {
- angle = m_angle.y;
- angle += -powf((1.0f-m_progress)*5.0f, 2.0f); // slows
- m_object->SetAngleY(0, angle);
- m_object->SetZoom(0, m_progress);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_goal;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 5.0f+Math::Rand()*5.0f;
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
-
- pos = m_goal;
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = Math::Rand()*10.0f;
- speed *= 0.5f+m_progress*0.5f;
- dim.x = 0.6f;
- dim.y = dim.x;
- pos.y += dim.y;
- duration = Math::Rand()*1.5f+1.5f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
- duration, 0.0f,
- duration*0.9f, 0.7f);
- }
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-// A positive angle makes a turn right.
-
-Error CTaskReset::Start(Math::Vector goal, Math::Vector angle)
-{
- CObject* fret;
- int i;
-
- fret = m_object->RetFret();
- if ( fret != 0 && fret->RetResetCap() == RESET_MOVE )
- {
- fret->SetTruck(0);
- m_object->SetFret(0); // does nothing
- }
-
- if ( !m_main->RetNiceReset() ) // quick return?
- {
- m_object->SetPosition(0, goal);
- m_object->SetAngle(0, angle);
- m_brain->RunProgram(m_object->RetResetRun());
-
- m_bError = false;
- return ERR_OK;
- }
-
- m_begin = m_object->RetPosition(0);
- m_goal = goal;
- m_angle = angle;
-
- if ( SearchVehicle() ) // starting location occupied?
- {
- m_bError = true;
- return ERR_RESET_NEAR;
- }
-
- m_iAngle = m_object->RetAngleY(0);
- m_time = 0.0f;
- m_phase = TRSP_ZOUT;
- m_speed = 1.0f/RESET_DELAY_ZOOM;
- m_progress = 0.0f;
- m_lastParticule = 0.0f;
-
- m_object->SetResetBusy(true);
-
- i = m_sound->Play(SOUND_GGG, m_begin, 1.0f, 2.0f, true);
- m_sound->AddEnvelope(i, 0.0f, 0.5f, RESET_DELAY_ZOOM, SOPER_STOP);
-
- m_bError = false;
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskReset::IsEnded()
-{
- CObject* power;
- float dist;
- int i;
-
- if ( !m_main->RetNiceReset() ) // quick return?
- {
- return ERR_STOP;
- }
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- if ( m_phase == TRSP_ZOUT )
- {
- dist = Math::Distance(m_begin, m_goal);
- m_phase = TRSP_MOVE;
- m_speed = 1.0f/(dist*RESET_DELAY_MOVE/100.0f);
- m_progress = 0.0f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TRSP_MOVE )
- {
- m_object->SetPosition(0, m_goal);
- m_object->SetAngle(0, m_angle);
-
- i = m_sound->Play(SOUND_GGG, m_goal, 1.0f, 0.5f, true);
- m_sound->AddEnvelope(i, 0.0f, 2.0f, RESET_DELAY_ZOOM, SOPER_STOP);
-
- m_phase = TRSP_ZIN;
- m_speed = 1.0f/RESET_DELAY_ZOOM;
- m_progress = 0.0f;
- return ERR_CONTINUE;
- }
-
- m_object->SetAngle(0, m_angle);
- m_object->SetZoom(0, 1.0f);
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- power->SetEnergy(power->RetCapacity()); // refueling
- }
-
- m_brain->RunProgram(m_object->RetResetRun());
- m_object->SetResetBusy(false);
- return ERR_STOP;
-}
-
-
-// Seeks if a vehicle is too close.
-
-bool CTaskReset::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- float oRadius, dist;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
-
- type = pObj->RetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_TECH &&
- type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr &&
- type != OBJECT_MOTHER &&
- type != OBJECT_ANT &&
- type != OBJECT_SPIDER &&
- type != OBJECT_BEE &&
- type != OBJECT_WORM ) continue;
-
- if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
- dist = Math::Distance(oPos, m_goal)-oRadius;
-
- if ( dist < 5.0f ) return true;
- }
-
- return false;
-}
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskreset.cpp + + +#include <stdio.h> + +#include "object/task/taskreset.h" + +#include "common/iman.h" +#include "object/brain.h" +#include "object/robotmain.h" + + + +const float RESET_DELAY_ZOOM = 0.7f; +const float RESET_DELAY_MOVE = 0.7f; + + + + +// Object's constructor. + +CTaskReset::CTaskReset(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ +} + +// Object's destructor. + +CTaskReset::~CTaskReset() +{ +} + + +// Management of an event. + +bool CTaskReset::EventProcess(const Event &event) +{ + Math::Vector pos, speed; + Math::Point dim; + float angle, duration; + + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + if ( m_bError ) return false; + + m_time += event.rTime; + m_progress += event.rTime*m_speed; + + if ( m_phase == TRSP_ZOUT ) + { + angle = m_iAngle; + angle += powf(m_progress*5.0f, 2.0f); // accelerates + m_object->SetAngleY(0, angle); + m_object->SetZoom(0, 1.0f-m_progress); + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_begin; + pos.x += (Math::Rand()-0.5f)*5.0f; + pos.z += (Math::Rand()-0.5f)*5.0f; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 5.0f+Math::Rand()*5.0f; + dim.x = Math::Rand()*2.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f); + + pos = m_begin; + speed.x = (Math::Rand()-0.5f)*20.0f; + speed.z = (Math::Rand()-0.5f)*20.0f; + speed.y = Math::Rand()*10.0f; + speed *= 1.0f-m_progress*0.5f; + pos += speed*1.5f; + speed = -speed; + dim.x = 0.6f; + dim.y = dim.x; + pos.y += dim.y; + duration = Math::Rand()*1.5f+1.5f; + m_particule->CreateTrack(pos, speed, dim, PARTITRACK6, + duration, 0.0f, + duration*0.9f, 0.7f); + } + } + + if ( m_phase == TRSP_MOVE ) + { + pos = m_begin+(m_goal-m_begin)*m_progress; + m_object->SetPosition(0, pos); + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos.x += (Math::Rand()-0.5f)*5.0f; + pos.z += (Math::Rand()-0.5f)*5.0f; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 2.0f+Math::Rand()*2.0f; + dim.x = Math::Rand()*2.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f); + } + } + + if ( m_phase == TRSP_ZIN ) + { + angle = m_angle.y; + angle += -powf((1.0f-m_progress)*5.0f, 2.0f); // slows + m_object->SetAngleY(0, angle); + m_object->SetZoom(0, m_progress); + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_goal; + pos.x += (Math::Rand()-0.5f)*5.0f; + pos.z += (Math::Rand()-0.5f)*5.0f; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 5.0f+Math::Rand()*5.0f; + dim.x = Math::Rand()*2.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f); + + pos = m_goal; + speed.x = (Math::Rand()-0.5f)*20.0f; + speed.z = (Math::Rand()-0.5f)*20.0f; + speed.y = Math::Rand()*10.0f; + speed *= 0.5f+m_progress*0.5f; + dim.x = 0.6f; + dim.y = dim.x; + pos.y += dim.y; + duration = Math::Rand()*1.5f+1.5f; + m_particule->CreateTrack(pos, speed, dim, PARTITRACK6, + duration, 0.0f, + duration*0.9f, 0.7f); + } + } + + return true; +} + + +// Assigns the goal was achieved. +// A positive angle makes a turn right. + +Error CTaskReset::Start(Math::Vector goal, Math::Vector angle) +{ + CObject* fret; + int i; + + fret = m_object->RetFret(); + if ( fret != 0 && fret->RetResetCap() == RESET_MOVE ) + { + fret->SetTruck(0); + m_object->SetFret(0); // does nothing + } + + if ( !m_main->RetNiceReset() ) // quick return? + { + m_object->SetPosition(0, goal); + m_object->SetAngle(0, angle); + m_brain->RunProgram(m_object->RetResetRun()); + + m_bError = false; + return ERR_OK; + } + + m_begin = m_object->RetPosition(0); + m_goal = goal; + m_angle = angle; + + if ( SearchVehicle() ) // starting location occupied? + { + m_bError = true; + return ERR_RESET_NEAR; + } + + m_iAngle = m_object->RetAngleY(0); + m_time = 0.0f; + m_phase = TRSP_ZOUT; + m_speed = 1.0f/RESET_DELAY_ZOOM; + m_progress = 0.0f; + m_lastParticule = 0.0f; + + m_object->SetResetBusy(true); + + i = m_sound->Play(SOUND_GGG, m_begin, 1.0f, 2.0f, true); + m_sound->AddEnvelope(i, 0.0f, 0.5f, RESET_DELAY_ZOOM, SOPER_STOP); + + m_bError = false; + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskReset::IsEnded() +{ + CObject* power; + float dist; + int i; + + if ( !m_main->RetNiceReset() ) // quick return? + { + return ERR_STOP; + } + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + if ( m_phase == TRSP_ZOUT ) + { + dist = Math::Distance(m_begin, m_goal); + m_phase = TRSP_MOVE; + m_speed = 1.0f/(dist*RESET_DELAY_MOVE/100.0f); + m_progress = 0.0f; + return ERR_CONTINUE; + } + + if ( m_phase == TRSP_MOVE ) + { + m_object->SetPosition(0, m_goal); + m_object->SetAngle(0, m_angle); + + i = m_sound->Play(SOUND_GGG, m_goal, 1.0f, 0.5f, true); + m_sound->AddEnvelope(i, 0.0f, 2.0f, RESET_DELAY_ZOOM, SOPER_STOP); + + m_phase = TRSP_ZIN; + m_speed = 1.0f/RESET_DELAY_ZOOM; + m_progress = 0.0f; + return ERR_CONTINUE; + } + + m_object->SetAngle(0, m_angle); + m_object->SetZoom(0, 1.0f); + + power = m_object->RetPower(); + if ( power != 0 ) + { + power->SetEnergy(power->RetCapacity()); // refueling + } + + m_brain->RunProgram(m_object->RetResetRun()); + m_object->SetResetBusy(false); + return ERR_STOP; +} + + +// Seeks if a vehicle is too close. + +bool CTaskReset::SearchVehicle() +{ + CObject* pObj; + Math::Vector oPos; + ObjectType type; + float oRadius, dist; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; + + type = pObj->RetType(); + if ( type != OBJECT_HUMAN && + type != OBJECT_TECH && + type != OBJECT_MOBILEfa && + type != OBJECT_MOBILEta && + type != OBJECT_MOBILEwa && + type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfc && + type != OBJECT_MOBILEtc && + type != OBJECT_MOBILEwc && + type != OBJECT_MOBILEic && + type != OBJECT_MOBILEfi && + type != OBJECT_MOBILEti && + type != OBJECT_MOBILEwi && + type != OBJECT_MOBILEii && + type != OBJECT_MOBILEfs && + type != OBJECT_MOBILEts && + type != OBJECT_MOBILEws && + type != OBJECT_MOBILEis && + type != OBJECT_MOBILErt && + type != OBJECT_MOBILErc && + type != OBJECT_MOBILErr && + type != OBJECT_MOBILErs && + type != OBJECT_MOBILEsa && + type != OBJECT_MOBILEtg && + type != OBJECT_MOBILEft && + type != OBJECT_MOBILEtt && + type != OBJECT_MOBILEwt && + type != OBJECT_MOBILEit && + type != OBJECT_MOBILEdr && + type != OBJECT_MOTHER && + type != OBJECT_ANT && + type != OBJECT_SPIDER && + type != OBJECT_BEE && + type != OBJECT_WORM ) continue; + + if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue; + dist = Math::Distance(oPos, m_goal)-oRadius; + + if ( dist < 5.0f ) return true; + } + + return false; +} + diff --git a/src/object/task/taskreset.h b/src/object/task/taskreset.h index 2c885f9..17a4441 100644 --- a/src/object/task/taskreset.h +++ b/src/object/task/taskreset.h @@ -1,63 +1,63 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskreset.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-enum TaskResetPhase
-{
- TRSP_ZOUT = 1, // disappears
- TRSP_MOVE = 2, // moves
- TRSP_ZIN = 3, // reappears
-};
-
-
-
-class CTaskReset : public CTask
-{
-public:
- CTaskReset(CInstanceManager* iMan, CObject* object);
- ~CTaskReset();
-
- bool EventProcess(const Event &event);
-
- Error Start(Math::Vector goal, Math::Vector angle);
- Error IsEnded();
-
-protected:
- bool SearchVehicle();
-
-protected:
- Math::Vector m_begin;
- Math::Vector m_goal;
- Math::Vector m_angle;
-
- TaskResetPhase m_phase;
- bool m_bError;
- float m_time;
- float m_speed;
- float m_progress;
- float m_lastParticule; // time of generation last particle
- float m_iAngle;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskreset.h + +#pragma once + + +#include "object/task/task.h" +#include "math/vector.h" + + + +enum TaskResetPhase +{ + TRSP_ZOUT = 1, // disappears + TRSP_MOVE = 2, // moves + TRSP_ZIN = 3, // reappears +}; + + + +class CTaskReset : public CTask +{ +public: + CTaskReset(CInstanceManager* iMan, CObject* object); + ~CTaskReset(); + + bool EventProcess(const Event &event); + + Error Start(Math::Vector goal, Math::Vector angle); + Error IsEnded(); + +protected: + bool SearchVehicle(); + +protected: + Math::Vector m_begin; + Math::Vector m_goal; + Math::Vector m_angle; + + TaskResetPhase m_phase; + bool m_bError; + float m_time; + float m_speed; + float m_progress; + float m_lastParticule; // time of generation last particle + float m_iAngle; +}; + diff --git a/src/object/task/tasksearch.cpp b/src/object/task/tasksearch.cpp index cf038aa..8c083dd 100644 --- a/src/object/task/tasksearch.cpp +++ b/src/object/task/tasksearch.cpp @@ -1,321 +1,321 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// tasksearch.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/tasksearch.h"
-
-#include "math/geometry.h"
-#include "common/iman.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "physics/physics.h"
-#include "ui/displaytext.h"
-
-
-
-
-// Object's constructor.
-
-CTaskSearch::CTaskSearch(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_hand = TSH_UP;
-}
-
-// Object's destructor.
-
-CTaskSearch::~CTaskSearch()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskSearch::EventProcess(const Event &event)
-{
- Math::Matrix* mat;
- Math::Vector pos, speed;
- Math::Point dim;
- float angle;
- int i;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_progress += event.rTime*m_speed; // others advance
- m_time += event.rTime;
-
- if ( m_phase == TSP_DOWN ||
- m_phase == TSP_UP )
- {
- for ( i=0 ; i<3 ; i++ )
- {
- angle = (m_finalAngle[i]-m_initialAngle[i])*m_progress;
- angle += m_initialAngle[i];
- m_object->SetAngleZ(i+1, angle);
- }
- }
-
- if ( m_phase == TSP_SEARCH &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(6.5f, 0.2f, 0.0f);
- pos = Math::Transform(*mat, pos); // sensor position
-
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = 0.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS);
- }
-
- return true;
-}
-
-
-// Initializes the initial and final angles.
-
-void CTaskSearch::InitAngle()
-{
- int i;
-
- if ( m_hand == TSH_UP )
- {
- m_finalAngle[0] = 110.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = -110.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = -65.0f*Math::PI/180.0f; // sensor
- }
- if ( m_hand == TSH_DOWN )
- {
- m_finalAngle[0] = 25.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = -70.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = -45.0f*Math::PI/180.0f; // sensor
- }
-
- for ( i=0 ; i<3 ; i++ )
- {
- m_initialAngle[i] = m_object->RetAngleZ(i+1);
- }
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskSearch::Start()
-{
- ObjectType type;
- Math::Vector speed;
- int i;
-
- m_bError = true;
- if ( !m_physics->RetLand() ) return ERR_SEARCH_FLY;
-
- speed = m_physics->RetMotorSpeed();
- if ( speed.x != 0.0f ||
- speed.z != 0.0f ) return ERR_SEARCH_MOTOR;
-
- type = m_object->RetType();
- if ( type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis ) return ERR_SEARCH_VEH;
-
- m_hand = TSH_DOWN;
- m_phase = TSP_DOWN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
-
- InitAngle();
- m_bError = false; // ok
-
- m_camera->StartCentering(m_object, Math::PI*0.50f, 99.9f, 0.0f, 1.0f);
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, true);
- m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.9f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.3f, 0.1f, SOPER_STOP);
-
- m_physics->SetFreeze(true); // it does not move
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskSearch::IsEnded()
-{
- int i;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( m_phase == TSP_DOWN ||
- m_phase == TSP_UP )
- {
- for ( i=0 ; i<3 ; i++ )
- {
- m_object->SetAngleZ(i+1, m_finalAngle[i]);
- }
- }
-
- if ( m_phase == TSP_DOWN )
- {
- m_sound->Play(SOUND_REPAIR, m_object->RetPosition(0));
-
- m_phase = TSP_SEARCH;
- m_speed = 1.0f/4.0f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TSP_SEARCH )
- {
- CreateMark();
-
- m_hand = TSH_UP;
- InitAngle();
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, true);
- m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.9f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.3f, 0.1f, SOPER_STOP);
-
- m_phase = TSP_UP;
- m_speed = 1.0f/1.0f;
- return ERR_CONTINUE;
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskSearch::Abort()
-{
- m_camera->StopCentering(m_object, 2.0f);
- m_physics->SetFreeze(false); // is moving again
- return true;
-}
-
-
-// Creates a mark if possible.
-
-bool CTaskSearch::CreateMark()
-{
- CObject* fret;
- ObjectType type;
- Math::Matrix* mat;
- Math::Vector pos;
- TerrainRes res;
- Error info;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(7.5f, 0.0f, 0.0f);
- pos = Math::Transform(*mat, pos); // sensor position
-
- res = m_terrain->RetResource(pos);
- if ( res == TR_NULL ) return false;
-
- type = OBJECT_NULL;
- if ( res == TR_STONE )
- {
- type = OBJECT_MARKSTONE;
- info = INFO_MARKSTONE;
- }
- if ( res == TR_URANIUM )
- {
- type = OBJECT_MARKURANIUM;
- info = INFO_MARKURANIUM;
- }
- if ( res == TR_POWER )
- {
- type = OBJECT_MARKPOWER;
- info = INFO_MARKPOWER;
- }
- if ( res == TR_KEYa )
- {
- type = OBJECT_MARKKEYa;
- info = INFO_MARKKEYa;
- }
- if ( res == TR_KEYb )
- {
- type = OBJECT_MARKKEYb;
- info = INFO_MARKKEYb;
- }
- if ( res == TR_KEYc )
- {
- type = OBJECT_MARKKEYc;
- info = INFO_MARKKEYc;
- }
- if ( res == TR_KEYd )
- {
- type = OBJECT_MARKKEYd;
- info = INFO_MARKKEYd;
- }
- if ( type == OBJECT_NULL ) return false;
-
-//? DeleteMark(type);
-
- fret = new CObject(m_iMan);
- if ( !fret->CreateResource(pos, 0.0f, type) )
- {
- delete fret;
- m_displayText->DisplayError(ERR_TOOMANY, m_object);
- return false;
- }
-
- m_displayText->DisplayError(info, pos, 5.0f, 50.0f); // displays the message
-
- return true;
-}
-
-// Destroys the marks of a given type.
-
-void CTaskSearch::DeleteMark(ObjectType type)
-{
- CObject* pObj;
- Math::Vector oPos;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( type == pObj->RetType() )
- {
- pObj->DeleteObject(); // removes the mark
- delete pObj;
- break;
- }
- }
-}
-
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// tasksearch.cpp + + +#include <stdio.h> + +#include "object/task/tasksearch.h" + +#include "math/geometry.h" +#include "common/iman.h" +#include "old/particule.h" +#include "old/terrain.h" +#include "physics/physics.h" +#include "ui/displaytext.h" + + + + +// Object's constructor. + +CTaskSearch::CTaskSearch(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + m_hand = TSH_UP; +} + +// Object's destructor. + +CTaskSearch::~CTaskSearch() +{ +} + + +// Management of an event. + +bool CTaskSearch::EventProcess(const Event &event) +{ + Math::Matrix* mat; + Math::Vector pos, speed; + Math::Point dim; + float angle; + int i; + + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + if ( m_bError ) return false; + + m_progress += event.rTime*m_speed; // others advance + m_time += event.rTime; + + if ( m_phase == TSP_DOWN || + m_phase == TSP_UP ) + { + for ( i=0 ; i<3 ; i++ ) + { + angle = (m_finalAngle[i]-m_initialAngle[i])*m_progress; + angle += m_initialAngle[i]; + m_object->SetAngleZ(i+1, angle); + } + } + + if ( m_phase == TSP_SEARCH && + m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + mat = m_object->RetWorldMatrix(0); + pos = Math::Vector(6.5f, 0.2f, 0.0f); + pos = Math::Transform(*mat, pos); // sensor position + + speed.x = (Math::Rand()-0.5f)*20.0f; + speed.z = (Math::Rand()-0.5f)*20.0f; + speed.y = 0.0f; + dim.x = Math::Rand()*1.0f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGAS); + } + + return true; +} + + +// Initializes the initial and final angles. + +void CTaskSearch::InitAngle() +{ + int i; + + if ( m_hand == TSH_UP ) + { + m_finalAngle[0] = 110.0f*Math::PI/180.0f; // arm + m_finalAngle[1] = -110.0f*Math::PI/180.0f; // forearm + m_finalAngle[2] = -65.0f*Math::PI/180.0f; // sensor + } + if ( m_hand == TSH_DOWN ) + { + m_finalAngle[0] = 25.0f*Math::PI/180.0f; // arm + m_finalAngle[1] = -70.0f*Math::PI/180.0f; // forearm + m_finalAngle[2] = -45.0f*Math::PI/180.0f; // sensor + } + + for ( i=0 ; i<3 ; i++ ) + { + m_initialAngle[i] = m_object->RetAngleZ(i+1); + } +} + + +// Assigns the goal was achieved. + +Error CTaskSearch::Start() +{ + ObjectType type; + Math::Vector speed; + int i; + + m_bError = true; + if ( !m_physics->RetLand() ) return ERR_SEARCH_FLY; + + speed = m_physics->RetMotorSpeed(); + if ( speed.x != 0.0f || + speed.z != 0.0f ) return ERR_SEARCH_MOTOR; + + type = m_object->RetType(); + if ( type != OBJECT_MOBILEfs && + type != OBJECT_MOBILEts && + type != OBJECT_MOBILEws && + type != OBJECT_MOBILEis ) return ERR_SEARCH_VEH; + + m_hand = TSH_DOWN; + m_phase = TSP_DOWN; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + m_time = 0.0f; + m_lastParticule = 0.0f; + + InitAngle(); + m_bError = false; // ok + + m_camera->StartCentering(m_object, Math::PI*0.50f, 99.9f, 0.0f, 1.0f); + + i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, true); + m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.9f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.0f, 0.3f, 0.1f, SOPER_STOP); + + m_physics->SetFreeze(true); // it does not move + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskSearch::IsEnded() +{ + int i; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + m_progress = 0.0f; + + if ( m_phase == TSP_DOWN || + m_phase == TSP_UP ) + { + for ( i=0 ; i<3 ; i++ ) + { + m_object->SetAngleZ(i+1, m_finalAngle[i]); + } + } + + if ( m_phase == TSP_DOWN ) + { + m_sound->Play(SOUND_REPAIR, m_object->RetPosition(0)); + + m_phase = TSP_SEARCH; + m_speed = 1.0f/4.0f; + return ERR_CONTINUE; + } + + if ( m_phase == TSP_SEARCH ) + { + CreateMark(); + + m_hand = TSH_UP; + InitAngle(); + + i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, true); + m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.9f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.0f, 0.3f, 0.1f, SOPER_STOP); + + m_phase = TSP_UP; + m_speed = 1.0f/1.0f; + return ERR_CONTINUE; + } + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +bool CTaskSearch::Abort() +{ + m_camera->StopCentering(m_object, 2.0f); + m_physics->SetFreeze(false); // is moving again + return true; +} + + +// Creates a mark if possible. + +bool CTaskSearch::CreateMark() +{ + CObject* fret; + ObjectType type; + Math::Matrix* mat; + Math::Vector pos; + TerrainRes res; + Error info; + + mat = m_object->RetWorldMatrix(0); + pos = Math::Vector(7.5f, 0.0f, 0.0f); + pos = Math::Transform(*mat, pos); // sensor position + + res = m_terrain->RetResource(pos); + if ( res == TR_NULL ) return false; + + type = OBJECT_NULL; + if ( res == TR_STONE ) + { + type = OBJECT_MARKSTONE; + info = INFO_MARKSTONE; + } + if ( res == TR_URANIUM ) + { + type = OBJECT_MARKURANIUM; + info = INFO_MARKURANIUM; + } + if ( res == TR_POWER ) + { + type = OBJECT_MARKPOWER; + info = INFO_MARKPOWER; + } + if ( res == TR_KEYa ) + { + type = OBJECT_MARKKEYa; + info = INFO_MARKKEYa; + } + if ( res == TR_KEYb ) + { + type = OBJECT_MARKKEYb; + info = INFO_MARKKEYb; + } + if ( res == TR_KEYc ) + { + type = OBJECT_MARKKEYc; + info = INFO_MARKKEYc; + } + if ( res == TR_KEYd ) + { + type = OBJECT_MARKKEYd; + info = INFO_MARKKEYd; + } + if ( type == OBJECT_NULL ) return false; + +//? DeleteMark(type); + + fret = new CObject(m_iMan); + if ( !fret->CreateResource(pos, 0.0f, type) ) + { + delete fret; + m_displayText->DisplayError(ERR_TOOMANY, m_object); + return false; + } + + m_displayText->DisplayError(info, pos, 5.0f, 50.0f); // displays the message + + return true; +} + +// Destroys the marks of a given type. + +void CTaskSearch::DeleteMark(ObjectType type) +{ + CObject* pObj; + Math::Vector oPos; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( type == pObj->RetType() ) + { + pObj->DeleteObject(); // removes the mark + delete pObj; + break; + } + } +} + + diff --git a/src/object/task/tasksearch.h b/src/object/task/tasksearch.h index 040c606..304473d 100644 --- a/src/object/task/tasksearch.h +++ b/src/object/task/tasksearch.h @@ -1,70 +1,70 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// tasksearch.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-
-
-
-enum TaskSearchHand
-{
- TSH_UP = 1, // sensor at the top
- TSH_DOWN = 2, // sensor at the bottom
-};
-
-enum TaskSearchPhase
-{
- TSP_DOWN = 1, // descends
- TSP_SEARCH = 2, // seeks
- TSP_UP = 3, // rises
-};
-
-
-
-class CTaskSearch : public CTask
-{
-public:
- CTaskSearch(CInstanceManager* iMan, CObject* object);
- ~CTaskSearch();
-
- bool EventProcess(const Event &event);
-
- Error Start();
- Error IsEnded();
- bool Abort();
-
-protected:
- void InitAngle();
- bool CreateMark();
- void DeleteMark(ObjectType type);
-
-protected:
- TaskSearchHand m_hand;
- TaskSearchPhase m_phase;
- float m_progress;
- float m_speed;
- float m_time;
- float m_lastParticule;
- float m_initialAngle[3];
- float m_finalAngle[3];
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// tasksearch.h + +#pragma once + + +#include "object/task/task.h" +#include "object/object.h" + + + +enum TaskSearchHand +{ + TSH_UP = 1, // sensor at the top + TSH_DOWN = 2, // sensor at the bottom +}; + +enum TaskSearchPhase +{ + TSP_DOWN = 1, // descends + TSP_SEARCH = 2, // seeks + TSP_UP = 3, // rises +}; + + + +class CTaskSearch : public CTask +{ +public: + CTaskSearch(CInstanceManager* iMan, CObject* object); + ~CTaskSearch(); + + bool EventProcess(const Event &event); + + Error Start(); + Error IsEnded(); + bool Abort(); + +protected: + void InitAngle(); + bool CreateMark(); + void DeleteMark(ObjectType type); + +protected: + TaskSearchHand m_hand; + TaskSearchPhase m_phase; + float m_progress; + float m_speed; + float m_time; + float m_lastParticule; + float m_initialAngle[3]; + float m_finalAngle[3]; + bool m_bError; +}; + diff --git a/src/object/task/taskshield.cpp b/src/object/task/taskshield.cpp index 7ceb03b..d5265a2 100644 --- a/src/object/task/taskshield.cpp +++ b/src/object/task/taskshield.cpp @@ -1,560 +1,560 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskshield.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskshield.h"
-
-#include "common/iman.h"
-#include "old/light.h"
-#include "old/particule.h"
-#include "math/geometry.h"
-#include "object/brain.h"
-#include "physics/physics.h"
-
-
-const float ENERGY_TIME = 20.0f; // maximum duration if full battery
-
-
-
-// Object's constructor.
-
-CTaskShield::CTaskShield(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_rankSphere = -1;
- m_soundChannel = -1;
- m_effectLight = -1;
-}
-
-// Object's destructor.
-
-CTaskShield::~CTaskShield()
-{
- Abort();
-}
-
-
-// Management of an event.
-
-bool CTaskShield::EventProcess(const Event &event)
-{
- CObject* power;
- Math::Matrix* mat;
- Math::Matrix matrix;
- Math::Vector pos, speed, goal, angle;
- D3DCOLORVALUE color;
- Math::Point dim;
- float energy;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_progress += event.rTime*m_speed; // others advance
- m_time += event.rTime;
- m_delay -= event.rTime;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(7.0f, 15.0f, 0.0f);
- pos = Math::Transform(*mat, pos); // sphere position
- m_shieldPos = pos;
-
- if ( m_rankSphere != -1 )
- {
- m_particule->SetPosition(m_rankSphere, m_shieldPos);
- dim.x = RetRadius();
- dim.y = dim.x;
- m_particule->SetDimension(m_rankSphere, dim);
- }
-
- if ( m_phase == TS_UP1 )
- {
- pos.x = 7.0f;
- pos.y = 4.5f+Math::Bounce(m_progress)*3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
- }
-
- if ( m_phase == TS_UP2 )
- {
- pos.x = 0.0f;
- pos.y = 1.0f+Math::Bounce(m_progress)*3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(3, pos);
- }
-
- if ( m_phase == TS_SHIELD )
- {
- energy = (1.0f/ENERGY_TIME)*event.rTime;
- energy *= RetRadius()/RADIUS_SHIELD_MAX;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- power->SetEnergy(power->RetEnergy()-energy/power->RetCapacity());
- }
- m_energyUsed += energy;
-
- if ( m_soundChannel == -1 )
- {
- m_soundChannel = m_sound->Play(SOUND_SHIELD, m_shieldPos, 0.5f, 0.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_LOOP);
- }
- else
- {
- m_sound->Position(m_soundChannel, m_shieldPos);
- }
-
- pos = m_shieldPos;
- pos.y += RetRadius()*(2.0f+sinf(m_time*9.0f)*0.2f);
- if ( m_effectLight == -1 )
- {
- CreateLight(pos);
- }
- else
- {
- m_light->SetLightPos(m_effectLight, pos);
-
- color.r = 0.0f+sinf(m_time*33.2f)*0.2f;
- color.g = 0.5f+sinf(m_time*20.0f)*0.5f;
- color.b = 0.5f+sinf(m_time*21.3f)*1.0f;
- color.a = 0.0f;
- m_light->SetLightColor(m_effectLight, color);
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_shieldPos;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = (Math::Rand()-0.5f)*0.0f;
- speed.z = (Math::Rand()-0.5f)*0.0f;
- speed.y = Math::Rand()*15.0f;
- dim.x = Math::Rand()*6.0f+4.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
- }
-
- if ( m_lastRay+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastRay = m_time;
-
- pos = m_shieldPos;
- dim.x = RetRadius()/20.0f;
- dim.y = dim.x;
- angle.x = (Math::Rand()-0.5f)*Math::PI*1.2f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*Math::PI*1.2f;
- Math::LoadRotationXZYMatrix(matrix, angle);
- goal = Math::Transform(matrix, Math::Vector(0.0f, RetRadius()-dim.x, 0.0f));
- goal += pos;
- m_particule->CreateRay(pos, goal, PARTIRAY2, dim, 0.3f);
- }
-
- if ( m_lastIncrease+0.2f <= m_time )
- {
- m_lastIncrease = m_time;
- IncreaseShield();
- }
- }
-
- if ( m_phase == TS_SMOKE )
- {
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.5f, 2.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_shieldPos;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = (Math::Rand()-0.5f)*3.0f;
- speed.z = (Math::Rand()-0.5f)*3.0f;
- speed.y = (Math::Rand()-0.5f)*3.0f;
- dim.x = Math::Rand()*1.5f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
- }
- }
-
- if ( m_phase == TS_DOWN1 )
- {
- pos.x = 0.0f;
- pos.y = 1.0f+(1.0f-Math::Bounce(m_progress))*3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(3, pos);
- }
-
- if ( m_phase == TS_DOWN2 )
- {
- pos.x = 7.0f;
- pos.y = 4.5f+(1.0f-Math::Bounce(m_progress))*3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
- }
-
- return true;
-}
-
-
-// Deploys the shield.
-// The period is only useful with TSM_UP!
-
-Error CTaskShield::Start(TaskShieldMode mode, float delay)
-{
- CObject* power;
- Math::Matrix* mat;
- Math::Vector pos, iPos, oPos, speed;
- ObjectType type;
- float energy;
-
- if ( mode == TSM_DOWN )
- {
- return Stop();
- }
-
- if ( mode == TSM_UPDATE )
- {
- if ( m_object->RetSelect() )
- {
- m_brain->UpdateInterface();
- }
- return ERR_OK;
- }
-
- type = m_object->RetType();
- if ( type != OBJECT_MOBILErs ) return ERR_SHIELD_VEH;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() ) return ERR_SHIELD_VEH;
-
- power = m_object->RetPower();
- if ( power == 0 ) return ERR_SHIELD_ENERGY;
- energy = power->RetEnergy();
- if ( energy == 0.0f ) return ERR_SHIELD_ENERGY;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(7.0f, 15.0f, 0.0f);
- pos = Transform(*mat, pos); // sphere position
- m_shieldPos = pos;
-
- m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 0.7f);
-
- m_phase = TS_UP1;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- m_time = 0.0f;
- m_delay = delay;
- m_lastParticule = 0.0f;
- m_lastRay = 0.0f;
- m_lastIncrease = 0.0f;
- m_energyUsed = 0.0f;
-
- m_bError = false; // ok
-
- if ( m_object->RetSelect() )
- {
- m_brain->UpdateInterface();
- }
-//? m_camera->StartCentering(m_object, Math::PI*0.85f, -Math::PI*0.15f, RetRadius()+40.0f, 3.0f);
- return ERR_OK;
-}
-
-// Returns the shield.
-
-Error CTaskShield::Stop()
-{
- float time;
-
- if ( m_phase == TS_SHIELD )
- {
- m_object->SetShieldRadius(0.0f);
-
- if ( m_rankSphere != -1 )
- {
- m_particule->SetPhase(m_rankSphere, PARPHEND, 3.0f);
- m_rankSphere = -1;
- }
-
- if ( m_effectLight != -1 )
- {
- m_light->DeleteLight(m_effectLight);
- m_effectLight = -1;
- }
-
- time = m_energyUsed*4.0f;
- if ( time < 1.0f ) time = 1.0f;
- if ( time > 4.0f ) time = 4.0f;
-
- m_phase = TS_SMOKE;
- m_speed = 1.0f/time;
-
- m_camera->StopCentering(m_object, 4.0f);
-
- if ( m_object->RetSelect() )
- {
- m_brain->UpdateInterface();
- }
- return ERR_CONTINUE;
- }
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskShield::IsEnded()
-{
- CObject* power;
- Math::Vector pos, speed;
- Math::Point dim;
- float energy;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_phase == TS_SHIELD )
- {
- m_object->SetShieldRadius(RetRadius());
-
- power = m_object->RetPower();
- if ( power == 0 )
- {
- energy = 0.0f;
- }
- else
- {
- energy = power->RetEnergy();
- }
-
- if ( energy == 0.0f || m_delay <= 0.0f )
- {
- Stop();
- }
- return ERR_CONTINUE;
- }
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( m_phase == TS_UP1 )
- {
- pos.x = 7.0f;
- pos.y = 4.5f+3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
-
- m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 1.0f);
-
- m_phase = TS_UP2;
- m_speed = 1.0f/0.8f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TS_UP2 )
- {
- pos.x = 0.0f;
- pos.y = 1.0f+3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(3, pos);
-
- m_object->SetShieldRadius(RetRadius());
-
- pos = m_shieldPos;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = RetRadius();
- dim.y = dim.x;
- m_rankSphere = m_particule->CreateParticule(pos, speed, dim, PARTISPHERE3, 2.0f, 0.0f, 0.0f);
-
- m_phase = TS_SHIELD;
- m_speed = 1.0f/999.9f;
-
- if ( m_object->RetSelect() )
- {
- m_brain->UpdateInterface();
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TS_SMOKE )
- {
- m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 1.0f);
-
- m_phase = TS_DOWN1;
- m_speed = 1.0f/0.8f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TS_DOWN1 )
- {
- m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 0.7f);
-
- m_phase = TS_DOWN2;
- m_speed = 1.0f/1.0f;
- return ERR_CONTINUE;
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Indicates whether the action is pending.
-
-bool CTaskShield::IsBusy()
-{
- if ( m_phase == TS_SHIELD )
- {
- return false;
- }
-
- return true;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskShield::Abort()
-{
- Math::Vector pos;
-
- m_object->SetShieldRadius(0.0f);
-
- pos.x = 7.0f;
- pos.y = 4.5f;
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
-
- pos.x = 0.0f;
- pos.y = 1.0f;
- pos.z = 0.0f;
- m_object->SetPosition(3, pos);
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.5f, 2.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- if ( m_rankSphere != -1 )
- {
- m_particule->SetPhase(m_rankSphere, PARPHEND, 3.0f);
- m_rankSphere = -1;
- }
-
- if ( m_effectLight != -1 )
- {
- m_light->DeleteLight(m_effectLight);
- m_effectLight = -1;
- }
-
- m_camera->StopCentering(m_object, 2.0f);
- return true;
-}
-
-
-// Creates the light to accompany a pyrotechnic effect.
-
-bool CTaskShield::CreateLight(Math::Vector pos)
-{
- D3DLIGHT7 light;
-
- if ( !m_engine->RetLightMode() ) return true;
-
- ZeroMemory( &light, sizeof(light) );
- light.dltType = D3DLIGHT_SPOT;
- light.dcvDiffuse.r = 0.0f;
- light.dcvDiffuse.g = 1.0f;
- light.dcvDiffuse.b = 2.0f;
- light.dvPosition.x = pos.x;
- light.dvPosition.y = pos.y;
- light.dvPosition.z = pos.z;
- light.dvDirection.x = 0.0f;
- light.dvDirection.y = -1.0f; // against the bottom
- light.dvDirection.z = 0.0f;
- light.dvRange = D3DLIGHT_RANGE_MAX;
- light.dvFalloff = 1.0f;
- light.dvAttenuation0 = 1.0f;
- light.dvAttenuation1 = 0.0f;
- light.dvAttenuation2 = 0.0f;
- light.dvTheta = 0.0f;
- light.dvPhi = Math::PI/4.0f;
-
- m_effectLight = m_light->CreateLight();
- if ( m_effectLight == -1 ) return false;
-
- m_light->SetLight(m_effectLight, light);
- m_light->SetLightIntensity(m_effectLight, 1.0f);
-
- return true;
-}
-
-
-// Repaired the shielded objects within the sphere of the shield.
-
-void CTaskShield::IncreaseShield()
-{
- ObjectType type;
- CObject* pObj;
- Math::Vector oPos;
- float dist, shield;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, m_shieldPos);
- if ( dist <= RetRadius()+10.0f )
- {
- shield = pObj->RetShield();
- shield += 0.1f;
- if ( shield > 1.0f ) shield = 1.0f;
- pObj->SetShield(shield);
- }
- }
-}
-
-
-// Returns the radius of the shield.
-
-float CTaskShield::RetRadius()
-{
- return RADIUS_SHIELD_MIN + (RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)*m_object->RetParam();
-}
-
-
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskshield.cpp + + +#include <stdio.h> + +#include "object/task/taskshield.h" + +#include "common/iman.h" +#include "old/light.h" +#include "old/particule.h" +#include "math/geometry.h" +#include "object/brain.h" +#include "physics/physics.h" + + +const float ENERGY_TIME = 20.0f; // maximum duration if full battery + + + +// Object's constructor. + +CTaskShield::CTaskShield(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + m_rankSphere = -1; + m_soundChannel = -1; + m_effectLight = -1; +} + +// Object's destructor. + +CTaskShield::~CTaskShield() +{ + Abort(); +} + + +// Management of an event. + +bool CTaskShield::EventProcess(const Event &event) +{ + CObject* power; + Math::Matrix* mat; + Math::Matrix matrix; + Math::Vector pos, speed, goal, angle; + D3DCOLORVALUE color; + Math::Point dim; + float energy; + + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + if ( m_bError ) return false; + + m_progress += event.rTime*m_speed; // others advance + m_time += event.rTime; + m_delay -= event.rTime; + + mat = m_object->RetWorldMatrix(0); + pos = Math::Vector(7.0f, 15.0f, 0.0f); + pos = Math::Transform(*mat, pos); // sphere position + m_shieldPos = pos; + + if ( m_rankSphere != -1 ) + { + m_particule->SetPosition(m_rankSphere, m_shieldPos); + dim.x = RetRadius(); + dim.y = dim.x; + m_particule->SetDimension(m_rankSphere, dim); + } + + if ( m_phase == TS_UP1 ) + { + pos.x = 7.0f; + pos.y = 4.5f+Math::Bounce(m_progress)*3.0f; + pos.z = 0.0f; + m_object->SetPosition(2, pos); + } + + if ( m_phase == TS_UP2 ) + { + pos.x = 0.0f; + pos.y = 1.0f+Math::Bounce(m_progress)*3.0f; + pos.z = 0.0f; + m_object->SetPosition(3, pos); + } + + if ( m_phase == TS_SHIELD ) + { + energy = (1.0f/ENERGY_TIME)*event.rTime; + energy *= RetRadius()/RADIUS_SHIELD_MAX; + power = m_object->RetPower(); + if ( power != 0 ) + { + power->SetEnergy(power->RetEnergy()-energy/power->RetCapacity()); + } + m_energyUsed += energy; + + if ( m_soundChannel == -1 ) + { + m_soundChannel = m_sound->Play(SOUND_SHIELD, m_shieldPos, 0.5f, 0.5f, true); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_LOOP); + } + else + { + m_sound->Position(m_soundChannel, m_shieldPos); + } + + pos = m_shieldPos; + pos.y += RetRadius()*(2.0f+sinf(m_time*9.0f)*0.2f); + if ( m_effectLight == -1 ) + { + CreateLight(pos); + } + else + { + m_light->SetLightPos(m_effectLight, pos); + + color.r = 0.0f+sinf(m_time*33.2f)*0.2f; + color.g = 0.5f+sinf(m_time*20.0f)*0.5f; + color.b = 0.5f+sinf(m_time*21.3f)*1.0f; + color.a = 0.0f; + m_light->SetLightColor(m_effectLight, color); + } + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_shieldPos; + pos.x += (Math::Rand()-0.5f)*5.0f; + pos.z += (Math::Rand()-0.5f)*5.0f; + speed.x = (Math::Rand()-0.5f)*0.0f; + speed.z = (Math::Rand()-0.5f)*0.0f; + speed.y = Math::Rand()*15.0f; + dim.x = Math::Rand()*6.0f+4.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f); + } + + if ( m_lastRay+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastRay = m_time; + + pos = m_shieldPos; + dim.x = RetRadius()/20.0f; + dim.y = dim.x; + angle.x = (Math::Rand()-0.5f)*Math::PI*1.2f; + angle.y = 0.0f; + angle.z = (Math::Rand()-0.5f)*Math::PI*1.2f; + Math::LoadRotationXZYMatrix(matrix, angle); + goal = Math::Transform(matrix, Math::Vector(0.0f, RetRadius()-dim.x, 0.0f)); + goal += pos; + m_particule->CreateRay(pos, goal, PARTIRAY2, dim, 0.3f); + } + + if ( m_lastIncrease+0.2f <= m_time ) + { + m_lastIncrease = m_time; + IncreaseShield(); + } + } + + if ( m_phase == TS_SMOKE ) + { + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.5f, 2.0f, SOPER_STOP); + m_soundChannel = -1; + } + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_shieldPos; + pos.x += (Math::Rand()-0.5f)*5.0f; + pos.z += (Math::Rand()-0.5f)*5.0f; + speed.x = (Math::Rand()-0.5f)*3.0f; + speed.z = (Math::Rand()-0.5f)*3.0f; + speed.y = (Math::Rand()-0.5f)*3.0f; + dim.x = Math::Rand()*1.5f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f); + } + } + + if ( m_phase == TS_DOWN1 ) + { + pos.x = 0.0f; + pos.y = 1.0f+(1.0f-Math::Bounce(m_progress))*3.0f; + pos.z = 0.0f; + m_object->SetPosition(3, pos); + } + + if ( m_phase == TS_DOWN2 ) + { + pos.x = 7.0f; + pos.y = 4.5f+(1.0f-Math::Bounce(m_progress))*3.0f; + pos.z = 0.0f; + m_object->SetPosition(2, pos); + } + + return true; +} + + +// Deploys the shield. +// The period is only useful with TSM_UP! + +Error CTaskShield::Start(TaskShieldMode mode, float delay) +{ + CObject* power; + Math::Matrix* mat; + Math::Vector pos, iPos, oPos, speed; + ObjectType type; + float energy; + + if ( mode == TSM_DOWN ) + { + return Stop(); + } + + if ( mode == TSM_UPDATE ) + { + if ( m_object->RetSelect() ) + { + m_brain->UpdateInterface(); + } + return ERR_OK; + } + + type = m_object->RetType(); + if ( type != OBJECT_MOBILErs ) return ERR_SHIELD_VEH; + + m_bError = true; // operation impossible + if ( !m_physics->RetLand() ) return ERR_SHIELD_VEH; + + power = m_object->RetPower(); + if ( power == 0 ) return ERR_SHIELD_ENERGY; + energy = power->RetEnergy(); + if ( energy == 0.0f ) return ERR_SHIELD_ENERGY; + + mat = m_object->RetWorldMatrix(0); + pos = Math::Vector(7.0f, 15.0f, 0.0f); + pos = Transform(*mat, pos); // sphere position + m_shieldPos = pos; + + m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 0.7f); + + m_phase = TS_UP1; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + m_time = 0.0f; + m_delay = delay; + m_lastParticule = 0.0f; + m_lastRay = 0.0f; + m_lastIncrease = 0.0f; + m_energyUsed = 0.0f; + + m_bError = false; // ok + + if ( m_object->RetSelect() ) + { + m_brain->UpdateInterface(); + } +//? m_camera->StartCentering(m_object, Math::PI*0.85f, -Math::PI*0.15f, RetRadius()+40.0f, 3.0f); + return ERR_OK; +} + +// Returns the shield. + +Error CTaskShield::Stop() +{ + float time; + + if ( m_phase == TS_SHIELD ) + { + m_object->SetShieldRadius(0.0f); + + if ( m_rankSphere != -1 ) + { + m_particule->SetPhase(m_rankSphere, PARPHEND, 3.0f); + m_rankSphere = -1; + } + + if ( m_effectLight != -1 ) + { + m_light->DeleteLight(m_effectLight); + m_effectLight = -1; + } + + time = m_energyUsed*4.0f; + if ( time < 1.0f ) time = 1.0f; + if ( time > 4.0f ) time = 4.0f; + + m_phase = TS_SMOKE; + m_speed = 1.0f/time; + + m_camera->StopCentering(m_object, 4.0f); + + if ( m_object->RetSelect() ) + { + m_brain->UpdateInterface(); + } + return ERR_CONTINUE; + } + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskShield::IsEnded() +{ + CObject* power; + Math::Vector pos, speed; + Math::Point dim; + float energy; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_phase == TS_SHIELD ) + { + m_object->SetShieldRadius(RetRadius()); + + power = m_object->RetPower(); + if ( power == 0 ) + { + energy = 0.0f; + } + else + { + energy = power->RetEnergy(); + } + + if ( energy == 0.0f || m_delay <= 0.0f ) + { + Stop(); + } + return ERR_CONTINUE; + } + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + m_progress = 0.0f; + + if ( m_phase == TS_UP1 ) + { + pos.x = 7.0f; + pos.y = 4.5f+3.0f; + pos.z = 0.0f; + m_object->SetPosition(2, pos); + + m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 1.0f); + + m_phase = TS_UP2; + m_speed = 1.0f/0.8f; + return ERR_CONTINUE; + } + + if ( m_phase == TS_UP2 ) + { + pos.x = 0.0f; + pos.y = 1.0f+3.0f; + pos.z = 0.0f; + m_object->SetPosition(3, pos); + + m_object->SetShieldRadius(RetRadius()); + + pos = m_shieldPos; + speed = Math::Vector(0.0f, 0.0f, 0.0f); + dim.x = RetRadius(); + dim.y = dim.x; + m_rankSphere = m_particule->CreateParticule(pos, speed, dim, PARTISPHERE3, 2.0f, 0.0f, 0.0f); + + m_phase = TS_SHIELD; + m_speed = 1.0f/999.9f; + + if ( m_object->RetSelect() ) + { + m_brain->UpdateInterface(); + } + return ERR_CONTINUE; + } + + if ( m_phase == TS_SMOKE ) + { + m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 1.0f); + + m_phase = TS_DOWN1; + m_speed = 1.0f/0.8f; + return ERR_CONTINUE; + } + + if ( m_phase == TS_DOWN1 ) + { + m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 0.7f); + + m_phase = TS_DOWN2; + m_speed = 1.0f/1.0f; + return ERR_CONTINUE; + } + + Abort(); + return ERR_STOP; +} + +// Indicates whether the action is pending. + +bool CTaskShield::IsBusy() +{ + if ( m_phase == TS_SHIELD ) + { + return false; + } + + return true; +} + +// Suddenly ends the current action. + +bool CTaskShield::Abort() +{ + Math::Vector pos; + + m_object->SetShieldRadius(0.0f); + + pos.x = 7.0f; + pos.y = 4.5f; + pos.z = 0.0f; + m_object->SetPosition(2, pos); + + pos.x = 0.0f; + pos.y = 1.0f; + pos.z = 0.0f; + m_object->SetPosition(3, pos); + + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.5f, 2.0f, SOPER_STOP); + m_soundChannel = -1; + } + + if ( m_rankSphere != -1 ) + { + m_particule->SetPhase(m_rankSphere, PARPHEND, 3.0f); + m_rankSphere = -1; + } + + if ( m_effectLight != -1 ) + { + m_light->DeleteLight(m_effectLight); + m_effectLight = -1; + } + + m_camera->StopCentering(m_object, 2.0f); + return true; +} + + +// Creates the light to accompany a pyrotechnic effect. + +bool CTaskShield::CreateLight(Math::Vector pos) +{ + D3DLIGHT7 light; + + if ( !m_engine->RetLightMode() ) return true; + + ZeroMemory( &light, sizeof(light) ); + light.dltType = D3DLIGHT_SPOT; + light.dcvDiffuse.r = 0.0f; + light.dcvDiffuse.g = 1.0f; + light.dcvDiffuse.b = 2.0f; + light.dvPosition.x = pos.x; + light.dvPosition.y = pos.y; + light.dvPosition.z = pos.z; + light.dvDirection.x = 0.0f; + light.dvDirection.y = -1.0f; // against the bottom + light.dvDirection.z = 0.0f; + light.dvRange = D3DLIGHT_RANGE_MAX; + light.dvFalloff = 1.0f; + light.dvAttenuation0 = 1.0f; + light.dvAttenuation1 = 0.0f; + light.dvAttenuation2 = 0.0f; + light.dvTheta = 0.0f; + light.dvPhi = Math::PI/4.0f; + + m_effectLight = m_light->CreateLight(); + if ( m_effectLight == -1 ) return false; + + m_light->SetLight(m_effectLight, light); + m_light->SetLightIntensity(m_effectLight, 1.0f); + + return true; +} + + +// Repaired the shielded objects within the sphere of the shield. + +void CTaskShield::IncreaseShield() +{ + ObjectType type; + CObject* pObj; + Math::Vector oPos; + float dist, shield; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type == OBJECT_MOTHER || + type == OBJECT_ANT || + type == OBJECT_SPIDER || + type == OBJECT_BEE || + type == OBJECT_WORM ) continue; + + oPos = pObj->RetPosition(0); + dist = Math::Distance(oPos, m_shieldPos); + if ( dist <= RetRadius()+10.0f ) + { + shield = pObj->RetShield(); + shield += 0.1f; + if ( shield > 1.0f ) shield = 1.0f; + pObj->SetShield(shield); + } + } +} + + +// Returns the radius of the shield. + +float CTaskShield::RetRadius() +{ + return RADIUS_SHIELD_MIN + (RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)*m_object->RetParam(); +} + + + diff --git a/src/object/task/taskshield.h b/src/object/task/taskshield.h index 7749f52..5842ae0 100644 --- a/src/object/task/taskshield.h +++ b/src/object/task/taskshield.h @@ -1,84 +1,84 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskshield.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-const float RADIUS_SHIELD_MIN = 40.0f; // minimum radius of the protected zone
-const float RADIUS_SHIELD_MAX = 100.0f; // maximum radius of the protected zone
-
-
-enum TaskShieldPhase
-{
- TS_UP1 = 1, // up
- TS_UP2 = 2, // up
- TS_SHIELD = 3, // shield deployed
- TS_SMOKE = 4, // smoke
- TS_DOWN1 = 5, // down
- TS_DOWN2 = 6, // down
-};
-
-enum TaskShieldMode
-{
- TSM_UP = 1, // deploys shield
- TSM_DOWN = 2, // returns the shield
- TSM_UPDATE = 3, // radius change
-};
-
-
-
-class CTaskShield : public CTask
-{
-public:
- CTaskShield(CInstanceManager* iMan, CObject* object);
- ~CTaskShield();
-
- bool EventProcess(const Event &event);
-
- Error Start(TaskShieldMode mode, float delay);
- Error IsEnded();
- bool IsBusy();
- bool Abort();
-
-protected:
- Error Stop();
- bool CreateLight(Math::Vector pos);
- void IncreaseShield();
- float RetRadius();
-
-protected:
- TaskShieldPhase m_phase;
- float m_progress;
- float m_speed;
- float m_time;
- float m_delay;
- float m_lastParticule;
- float m_lastRay;
- float m_lastIncrease;
- float m_energyUsed;
- bool m_bError;
- Math::Vector m_shieldPos;
- int m_rankSphere;
- int m_soundChannel;
- int m_effectLight;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskshield.h + +#pragma once + + +#include "object/task/task.h" +#include "math/vector.h" + + +const float RADIUS_SHIELD_MIN = 40.0f; // minimum radius of the protected zone +const float RADIUS_SHIELD_MAX = 100.0f; // maximum radius of the protected zone + + +enum TaskShieldPhase +{ + TS_UP1 = 1, // up + TS_UP2 = 2, // up + TS_SHIELD = 3, // shield deployed + TS_SMOKE = 4, // smoke + TS_DOWN1 = 5, // down + TS_DOWN2 = 6, // down +}; + +enum TaskShieldMode +{ + TSM_UP = 1, // deploys shield + TSM_DOWN = 2, // returns the shield + TSM_UPDATE = 3, // radius change +}; + + + +class CTaskShield : public CTask +{ +public: + CTaskShield(CInstanceManager* iMan, CObject* object); + ~CTaskShield(); + + bool EventProcess(const Event &event); + + Error Start(TaskShieldMode mode, float delay); + Error IsEnded(); + bool IsBusy(); + bool Abort(); + +protected: + Error Stop(); + bool CreateLight(Math::Vector pos); + void IncreaseShield(); + float RetRadius(); + +protected: + TaskShieldPhase m_phase; + float m_progress; + float m_speed; + float m_time; + float m_delay; + float m_lastParticule; + float m_lastRay; + float m_lastIncrease; + float m_energyUsed; + bool m_bError; + Math::Vector m_shieldPos; + int m_rankSphere; + int m_soundChannel; + int m_effectLight; +}; + diff --git a/src/object/task/taskspiderexplo.cpp b/src/object/task/taskspiderexplo.cpp index 2d6c846..fa505b1 100644 --- a/src/object/task/taskspiderexplo.cpp +++ b/src/object/task/taskspiderexplo.cpp @@ -1,110 +1,110 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskspiderexplo.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskspiderexplo.h"
-
-#include "old/pyro.h"
-#include "object/motion/motionspider.h"
-#include "physics/physics.h"
-
-
-
-
-// Object's constructor.
-
-CTaskSpiderExplo::CTaskSpiderExplo(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_time = 0.0f;
- m_bError = false;
-}
-
-// Object's destructor.
-
-CTaskSpiderExplo::~CTaskSpiderExplo()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskSpiderExplo::EventProcess(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- // Momentarily stationary object (ant on the back)?
- if ( m_object->RetFixed() )
- {
- m_bError = true;
- return true;
- }
-
- m_time += event.rTime;
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskSpiderExplo::Start()
-{
- m_motion->SetAction(MSS_EXPLO, 1.0f); // swells abdominal
- m_time = 0.0f;
-
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
-
- m_bError = false;
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskSpiderExplo::IsEnded()
-{
- CPyro* pyro;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
-
- if ( m_bError )
- {
- Abort();
- return ERR_STOP;
- }
-
- if ( m_time < 1.0f ) return ERR_CONTINUE;
-
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_SPIDER, m_object); // the spider explodes (suicide)
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskSpiderExplo::Abort()
-{
- return true;
-}
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskspiderexplo.cpp + + +#include <stdio.h> + +#include "object/task/taskspiderexplo.h" + +#include "old/pyro.h" +#include "object/motion/motionspider.h" +#include "physics/physics.h" + + + + +// Object's constructor. + +CTaskSpiderExplo::CTaskSpiderExplo(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + m_time = 0.0f; + m_bError = false; +} + +// Object's destructor. + +CTaskSpiderExplo::~CTaskSpiderExplo() +{ +} + + +// Management of an event. + +bool CTaskSpiderExplo::EventProcess(const Event &event) +{ + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + + // Momentarily stationary object (ant on the back)? + if ( m_object->RetFixed() ) + { + m_bError = true; + return true; + } + + m_time += event.rTime; + + return true; +} + + +// Assigns the goal was achieved. + +Error CTaskSpiderExplo::Start() +{ + m_motion->SetAction(MSS_EXPLO, 1.0f); // swells abdominal + m_time = 0.0f; + + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + + m_bError = false; + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskSpiderExplo::IsEnded() +{ + CPyro* pyro; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + + if ( m_bError ) + { + Abort(); + return ERR_STOP; + } + + if ( m_time < 1.0f ) return ERR_CONTINUE; + + pyro = new CPyro(m_iMan); + pyro->Create(PT_SPIDER, m_object); // the spider explodes (suicide) + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +bool CTaskSpiderExplo::Abort() +{ + return true; +} + diff --git a/src/object/task/taskspiderexplo.h b/src/object/task/taskspiderexplo.h index df77b62..50f3ad2 100644 --- a/src/object/task/taskspiderexplo.h +++ b/src/object/task/taskspiderexplo.h @@ -1,44 +1,44 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskspiderexplo.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskSpiderExplo : public CTask
-{
-public:
- CTaskSpiderExplo(CInstanceManager* iMan, CObject* object);
- ~CTaskSpiderExplo();
-
- bool EventProcess(const Event &event);
-
- Error Start();
- Error IsEnded();
- bool Abort();
-
-protected:
-
-protected:
- float m_time;
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskspiderexplo.h + +#pragma once + + +#include "object/task/task.h" + + + +class CTaskSpiderExplo : public CTask +{ +public: + CTaskSpiderExplo(CInstanceManager* iMan, CObject* object); + ~CTaskSpiderExplo(); + + bool EventProcess(const Event &event); + + Error Start(); + Error IsEnded(); + bool Abort(); + +protected: + +protected: + float m_time; + bool m_bError; +}; + diff --git a/src/object/task/tasktake.cpp b/src/object/task/tasktake.cpp index b6d9e0e..1a50f06 100644 --- a/src/object/task/tasktake.cpp +++ b/src/object/task/tasktake.cpp @@ -1,596 +1,596 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// tasktake.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/tasktake.h"
-
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "math/geometry.h"
-#include "object/motion/motionhuman.h"
-#include "object/robotmain.h"
-#include "physics/physics.h"
-
-
-
-
-// Object's constructor.
-
-CTaskTake::CTaskTake(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
-
- m_arm = TTA_NEUTRAL;
-}
-
-// Object's destructor.
-
-CTaskTake::~CTaskTake()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskTake::EventProcess(const Event &event)
-{
- float a, g, cirSpeed;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- if ( m_bTurn ) // preliminary rotation?
- {
- a = m_object->RetAngleY(0);
- g = m_angle;
- cirSpeed = Math::Direction(a, g)*2.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- return true;
- }
-
- m_progress += event.rTime*m_speed; // others advance
-
- m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f)); // immobile!
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskTake::Start()
-{
- ObjectType type;
- CObject* other;
- float iAngle, oAngle, h;
- Math::Vector pos;
-
- m_height = 0.0f;
- m_step = 0;
- m_progress = 0.0f;
-
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
- oAngle = iAngle;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() )
- {
- pos = m_object->RetPosition(0);
- h = m_water->RetLevel(m_object);
- if ( pos.y < h ) return ERR_MANIP_WATER; // impossible under water
- return ERR_MANIP_FLY;
- }
-
- type = m_object->RetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_TECH ) return ERR_MANIP_VEH;
-
- m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));
-
- if ( m_object->RetFret() == 0 )
- {
- m_order = TTO_TAKE;
- }
- else
- {
- m_order = TTO_DEPOSE;
- }
-
- if ( m_order == TTO_TAKE )
- {
- pos = m_object->RetPosition(0);
- h = m_water->RetLevel(m_object);
- if ( pos.y < h ) return ERR_MANIP_WATER; // impossible under water
-
- other = SearchFriendObject(oAngle, 1.5f, Math::PI*0.50f);
- if ( other != 0 && other->RetPower() != 0 )
- {
- type = other->RetPower()->RetType();
- if ( type == OBJECT_URANIUM ) return ERR_MANIP_RADIO;
- if ( type != OBJECT_FRET &&
- type != OBJECT_STONE &&
- type != OBJECT_BULLET &&
- type != OBJECT_METAL &&
- type != OBJECT_POWER &&
- type != OBJECT_ATOMIC &&
- type != OBJECT_BBOX &&
- type != OBJECT_KEYa &&
- type != OBJECT_KEYb &&
- type != OBJECT_KEYc &&
- type != OBJECT_KEYd &&
- type != OBJECT_TNT ) return ERR_MANIP_FRIEND;
-//? m_camera->StartCentering(m_object, Math::PI*0.3f, -Math::PI*0.1f, 0.0f, 0.8f);
- m_arm = TTA_FRIEND;
- }
- else
- {
- other = SearchTakeObject(oAngle, 1.5f, Math::PI*0.45f);
- if ( other == 0 ) return ERR_MANIP_NIL;
- type = other->RetType();
- if ( type == OBJECT_URANIUM ) return ERR_MANIP_RADIO;
-//? m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.8f);
- m_arm = TTA_FFRONT;
- m_main->HideDropZone(other); // hides buildable area
- }
- }
-
- if ( m_order == TTO_DEPOSE )
- {
-//? speed = m_physics->RetMotorSpeed();
-//? if ( speed.x != 0.0f ||
-//? speed.z != 0.0f ) return ERR_MANIP_MOTOR;
-
- other = SearchFriendObject(oAngle, 1.5f, Math::PI*0.50f);
- if ( other != 0 && other->RetPower() == 0 )
- {
-//? m_camera->StartCentering(m_object, Math::PI*0.3f, -Math::PI*0.1f, 0.0f, 0.8f);
- m_arm = TTA_FRIEND;
- }
- else
- {
- if ( !IsFreeDeposeObject(Math::Vector(2.5f, 0.0f, 0.0f)) ) return ERR_MANIP_OCC;
-//? m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.8f);
- m_arm = TTA_FFRONT;
- }
- }
-
- m_bTurn = true; // preliminary rotation necessary
- m_angle = oAngle; // angle was reached
-
- m_physics->SetFreeze(true); // it does not move
-
- m_bError = false; // ok
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskTake::IsEnded()
-{
- CObject* fret;
- float angle;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_bTurn ) // preliminary rotation?
- {
- angle = m_object->RetAngleY(0);
- angle = Math::NormAngle(angle); // 0..2*Math::PI
-
- if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) )
- {
- m_bTurn = false; // rotation ended
- m_physics->SetMotorSpeedZ(0.0f);
-
- if ( m_arm == TTA_FFRONT )
- {
- m_motion->SetAction(MHS_TAKE, 0.2f); // will decrease
- }
- if ( m_arm == TTA_FRIEND )
- {
- if ( m_height <= 3.0f )
- {
- m_motion->SetAction(MHS_TAKEOTHER, 0.2f); // will decrease
- }
- else
- {
- m_motion->SetAction(MHS_TAKEHIGH, 0.2f); // will decrease
- }
- }
- m_progress = 0.0f;
- m_speed = 1.0f/0.6f;
- }
- return ERR_CONTINUE;
- }
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- m_step ++;
-
- if ( m_order == TTO_TAKE )
- {
- if ( m_step == 1 )
- {
- if ( TruckTakeObject() )
- {
- if ( m_arm == TTA_FRIEND &&
- (m_fretType == OBJECT_POWER ||
- m_fretType == OBJECT_ATOMIC ) )
- {
- m_sound->Play(SOUND_POWEROFF, m_object->RetPosition(0));
- }
- }
- m_motion->SetAction(MHS_UPRIGHT, 0.4f); // gets up
- m_progress = 0.0f;
- m_speed = 1.0f/0.8f;
- m_camera->StopCentering(m_object, 0.8f);
- return ERR_CONTINUE;
- }
- }
-
- if ( m_order == TTO_DEPOSE )
- {
- if ( m_step == 1 )
- {
- fret = m_object->RetFret();
- TruckDeposeObject();
- if ( m_arm == TTA_FRIEND &&
- (m_fretType == OBJECT_POWER ||
- m_fretType == OBJECT_ATOMIC ) )
- {
- m_sound->Play(SOUND_POWERON, m_object->RetPosition(0));
- }
- if ( fret != 0 && m_fretType == OBJECT_METAL && m_arm == TTA_FFRONT )
- {
- m_main->ShowDropZone(fret, m_object); // shows buildable area
- }
- m_motion->SetAction(-1); // gets up
- m_progress = 0.0f;
- m_speed = 1.0f/0.4f;
- m_camera->StopCentering(m_object, 0.8f);
- return ERR_CONTINUE;
- }
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskTake::Abort()
-{
- m_motion->SetAction(-1);
- m_camera->StopCentering(m_object, 0.8f);
- m_physics->SetFreeze(false); // is moving again
- return true;
-}
-
-
-// Seeks the object to take in front.
-
-CObject* CTaskTake::SearchTakeObject(float &angle,
- float dLimit, float aLimit)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float min, iAngle, bAngle, a, distance;
- int i;
-
- iPos = m_object->RetPosition(0);
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- min = 1000000.0f;
- pBest = 0;
- bAngle = 0.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
-
- if ( type != OBJECT_FRET &&
- type != OBJECT_STONE &&
- type != OBJECT_URANIUM &&
- type != OBJECT_BULLET &&
- type != OBJECT_METAL &&
- type != OBJECT_POWER &&
- type != OBJECT_ATOMIC &&
- type != OBJECT_BBOX &&
- type != OBJECT_KEYa &&
- type != OBJECT_KEYb &&
- type != OBJECT_KEYc &&
- type != OBJECT_KEYd &&
- type != OBJECT_TNT ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj->RetLock() ) continue;
- if ( pObj->RetZoomY(0) != 1.0f ) continue;
-
- oPos = pObj->RetPosition(0);
- distance = Math::Distance(oPos, iPos);
- if ( distance >= 4.0f-dLimit &&
- distance <= 4.0f+dLimit )
- {
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
- {
- a = fabs(angle-iAngle);
- if ( a > Math::PI ) a = Math::PI*2.0f-a;
- if ( a < min )
- {
- min = a;
- pBest = pObj;
- bAngle = angle;
- }
- }
- }
- }
- angle = bAngle;
- return pBest;
-}
-
-// Seeks the robot on which you want take or put a battery.
-
-CObject* CTaskTake::SearchFriendObject(float &angle,
- float dLimit, float aLimit)
-{
- Character* character;
- CObject* pObj;
- CObject* pPower;
- Math::Matrix* mat;
- Math::Vector iPos, oPos;
- ObjectType type, powerType;
- float iAngle, iRad, distance;
- int i;
-
- if ( !m_object->GetCrashSphere(0, iPos, iRad) ) return 0;
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue; // yourself?
-
- type = pObj->RetType();
- if ( type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_TOWER &&
- type != OBJECT_RESEARCH &&
- type != OBJECT_ENERGY &&
- type != OBJECT_LABO &&
- type != OBJECT_NUCLEAR ) continue;
-
- pPower = pObj->RetPower();
- if ( pPower != 0 )
- {
- if ( pPower->RetLock() ) continue;
- if ( pPower->RetZoomY(0) != 1.0f ) continue;
-
- powerType = pPower->RetType();
- if ( powerType == OBJECT_NULL ||
- powerType == OBJECT_FIX ) continue;
- }
-
- mat = pObj->RetWorldMatrix(0);
- character = pObj->RetCharacter();
- oPos = Transform(*mat, character->posPower);
-
- distance = fabs(Math::Distance(oPos, iPos) - (iRad+1.0f));
- if ( distance <= dLimit )
- {
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
- {
- character = pObj->RetCharacter();
- m_height = character->posPower.y;
- return pObj;
- }
- }
- }
-
- return 0;
-}
-
-// Takes the object in front.
-
-bool CTaskTake::TruckTakeObject()
-{
- CObject* fret;
- CObject* other;
- Math::Matrix matRotate;
- float angle;
-
- if ( m_arm == TTA_FFRONT ) // takes on the ground in front?
- {
-//? fret = SearchTakeObject(angle, 1.5f, Math::PI*0.04f);
- fret = SearchTakeObject(angle, 1.5f, Math::PI*0.15f); //OK 1.9
- if ( fret == 0 ) return false; // rien � prendre ?
- m_fretType = fret->RetType();
-
- fret->SetTruck(m_object);
- fret->SetTruckPart(4); // takes with the hand
-
-//? fret->SetPosition(0, Math::Vector(2.2f, -1.0f, 1.1f));
- fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f));
- fret->SetAngleY(0, 0.1f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.8f);
-
- m_object->SetFret(fret); // takes
- }
-
- if ( m_arm == TTA_FRIEND ) // takes friend's battery?
- {
- other = SearchFriendObject(angle, 1.5f, Math::PI*0.04f);
- if ( other == 0 ) return false;
-
- fret = other->RetPower();
- if ( fret == 0 ) return false; // the other does not have a battery?
- m_fretType = fret->RetType();
-
- other->SetPower(0);
- fret->SetTruck(m_object);
- fret->SetTruckPart(4); // takes with the hand
-
-//? fret->SetPosition(0, Math::Vector(2.2f, -1.0f, 1.1f));
- fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f));
- fret->SetAngleY(0, 0.1f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.8f);
-
- m_object->SetFret(fret); // takes
- }
-
- return true;
-}
-
-// Deposes the object taken.
-
-bool CTaskTake::TruckDeposeObject()
-{
- Character* character;
- CObject* fret;
- CObject* other;
- Math::Matrix* mat;
- Math::Vector pos;
- float angle;
-
- if ( m_arm == TTA_FFRONT ) // deposes on the ground in front?
- {
- fret = m_object->RetFret();
- if ( fret == 0 ) return false; // does nothing?
- m_fretType = fret->RetType();
-
- mat = fret->RetWorldMatrix(0);
- pos = Transform(*mat, Math::Vector(-0.5f, 1.0f, 0.0f));
- m_terrain->MoveOnFloor(pos);
- fret->SetPosition(0, pos);
- fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- fret->FloorAdjust(); // plate well on the ground
-
- fret->SetTruck(0);
- m_object->SetFret(0); // deposit
- }
-
- if ( m_arm == TTA_FRIEND ) // deposes battery on friends?
- {
- other = SearchFriendObject(angle, 1.5f, Math::PI*0.04f);
- if ( other == 0 ) return false;
-
- fret = other->RetPower();
- if ( fret != 0 ) return false; // the other already has a battery?
-
- fret = m_object->RetFret();
- if ( fret == 0 ) return false;
- m_fretType = fret->RetType();
-
- other->SetPower(fret);
- fret->SetTruck(other);
-
- character = other->RetCharacter();
- fret->SetPosition(0, character->posPower);
- fret->SetAngleY(0, 0.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- fret->SetTruckPart(0); // carried by the base
-
- m_object->SetFret(0); // deposit
- }
-
- return true;
-}
-
-// Seeks if a location allows to deposit an object.
-
-bool CTaskTake::IsFreeDeposeObject(Math::Vector pos)
-{
- CObject* pObj;
- Math::Matrix* mat;
- Math::Vector iPos, oPos;
- float oRadius;
- int i, j;
-
- mat = m_object->RetWorldMatrix(0);
- iPos = Transform(*mat, pos);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- if ( Math::Distance(iPos, oPos)-(oRadius+1.0f) < 1.0f )
- {
- return false; // location occupied
- }
- }
- }
- return true; // location free
-}
-
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// tasktake.cpp + + +#include <stdio.h> + +#include "object/task/tasktake.h" + +#include "common/iman.h" +#include "old/terrain.h" +#include "old/water.h" +#include "math/geometry.h" +#include "object/motion/motionhuman.h" +#include "object/robotmain.h" +#include "physics/physics.h" + + + + +// Object's constructor. + +CTaskTake::CTaskTake(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN); + + m_arm = TTA_NEUTRAL; +} + +// Object's destructor. + +CTaskTake::~CTaskTake() +{ +} + + +// Management of an event. + +bool CTaskTake::EventProcess(const Event &event) +{ + float a, g, cirSpeed; + + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + if ( m_bError ) return false; + + if ( m_bTurn ) // preliminary rotation? + { + a = m_object->RetAngleY(0); + g = m_angle; + cirSpeed = Math::Direction(a, g)*2.0f; + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right + return true; + } + + m_progress += event.rTime*m_speed; // others advance + + m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f)); // immobile! + + return true; +} + + +// Assigns the goal was achieved. + +Error CTaskTake::Start() +{ + ObjectType type; + CObject* other; + float iAngle, oAngle, h; + Math::Vector pos; + + m_height = 0.0f; + m_step = 0; + m_progress = 0.0f; + + iAngle = m_object->RetAngleY(0); + iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI + oAngle = iAngle; + + m_bError = true; // operation impossible + if ( !m_physics->RetLand() ) + { + pos = m_object->RetPosition(0); + h = m_water->RetLevel(m_object); + if ( pos.y < h ) return ERR_MANIP_WATER; // impossible under water + return ERR_MANIP_FLY; + } + + type = m_object->RetType(); + if ( type != OBJECT_HUMAN && + type != OBJECT_TECH ) return ERR_MANIP_VEH; + + m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f)); + + if ( m_object->RetFret() == 0 ) + { + m_order = TTO_TAKE; + } + else + { + m_order = TTO_DEPOSE; + } + + if ( m_order == TTO_TAKE ) + { + pos = m_object->RetPosition(0); + h = m_water->RetLevel(m_object); + if ( pos.y < h ) return ERR_MANIP_WATER; // impossible under water + + other = SearchFriendObject(oAngle, 1.5f, Math::PI*0.50f); + if ( other != 0 && other->RetPower() != 0 ) + { + type = other->RetPower()->RetType(); + if ( type == OBJECT_URANIUM ) return ERR_MANIP_RADIO; + if ( type != OBJECT_FRET && + type != OBJECT_STONE && + type != OBJECT_BULLET && + type != OBJECT_METAL && + type != OBJECT_POWER && + type != OBJECT_ATOMIC && + type != OBJECT_BBOX && + type != OBJECT_KEYa && + type != OBJECT_KEYb && + type != OBJECT_KEYc && + type != OBJECT_KEYd && + type != OBJECT_TNT ) return ERR_MANIP_FRIEND; +//? m_camera->StartCentering(m_object, Math::PI*0.3f, -Math::PI*0.1f, 0.0f, 0.8f); + m_arm = TTA_FRIEND; + } + else + { + other = SearchTakeObject(oAngle, 1.5f, Math::PI*0.45f); + if ( other == 0 ) return ERR_MANIP_NIL; + type = other->RetType(); + if ( type == OBJECT_URANIUM ) return ERR_MANIP_RADIO; +//? m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.8f); + m_arm = TTA_FFRONT; + m_main->HideDropZone(other); // hides buildable area + } + } + + if ( m_order == TTO_DEPOSE ) + { +//? speed = m_physics->RetMotorSpeed(); +//? if ( speed.x != 0.0f || +//? speed.z != 0.0f ) return ERR_MANIP_MOTOR; + + other = SearchFriendObject(oAngle, 1.5f, Math::PI*0.50f); + if ( other != 0 && other->RetPower() == 0 ) + { +//? m_camera->StartCentering(m_object, Math::PI*0.3f, -Math::PI*0.1f, 0.0f, 0.8f); + m_arm = TTA_FRIEND; + } + else + { + if ( !IsFreeDeposeObject(Math::Vector(2.5f, 0.0f, 0.0f)) ) return ERR_MANIP_OCC; +//? m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.8f); + m_arm = TTA_FFRONT; + } + } + + m_bTurn = true; // preliminary rotation necessary + m_angle = oAngle; // angle was reached + + m_physics->SetFreeze(true); // it does not move + + m_bError = false; // ok + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskTake::IsEnded() +{ + CObject* fret; + float angle; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_bTurn ) // preliminary rotation? + { + angle = m_object->RetAngleY(0); + angle = Math::NormAngle(angle); // 0..2*Math::PI + + if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) ) + { + m_bTurn = false; // rotation ended + m_physics->SetMotorSpeedZ(0.0f); + + if ( m_arm == TTA_FFRONT ) + { + m_motion->SetAction(MHS_TAKE, 0.2f); // will decrease + } + if ( m_arm == TTA_FRIEND ) + { + if ( m_height <= 3.0f ) + { + m_motion->SetAction(MHS_TAKEOTHER, 0.2f); // will decrease + } + else + { + m_motion->SetAction(MHS_TAKEHIGH, 0.2f); // will decrease + } + } + m_progress = 0.0f; + m_speed = 1.0f/0.6f; + } + return ERR_CONTINUE; + } + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + m_progress = 0.0f; + + m_step ++; + + if ( m_order == TTO_TAKE ) + { + if ( m_step == 1 ) + { + if ( TruckTakeObject() ) + { + if ( m_arm == TTA_FRIEND && + (m_fretType == OBJECT_POWER || + m_fretType == OBJECT_ATOMIC ) ) + { + m_sound->Play(SOUND_POWEROFF, m_object->RetPosition(0)); + } + } + m_motion->SetAction(MHS_UPRIGHT, 0.4f); // gets up + m_progress = 0.0f; + m_speed = 1.0f/0.8f; + m_camera->StopCentering(m_object, 0.8f); + return ERR_CONTINUE; + } + } + + if ( m_order == TTO_DEPOSE ) + { + if ( m_step == 1 ) + { + fret = m_object->RetFret(); + TruckDeposeObject(); + if ( m_arm == TTA_FRIEND && + (m_fretType == OBJECT_POWER || + m_fretType == OBJECT_ATOMIC ) ) + { + m_sound->Play(SOUND_POWERON, m_object->RetPosition(0)); + } + if ( fret != 0 && m_fretType == OBJECT_METAL && m_arm == TTA_FFRONT ) + { + m_main->ShowDropZone(fret, m_object); // shows buildable area + } + m_motion->SetAction(-1); // gets up + m_progress = 0.0f; + m_speed = 1.0f/0.4f; + m_camera->StopCentering(m_object, 0.8f); + return ERR_CONTINUE; + } + } + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +bool CTaskTake::Abort() +{ + m_motion->SetAction(-1); + m_camera->StopCentering(m_object, 0.8f); + m_physics->SetFreeze(false); // is moving again + return true; +} + + +// Seeks the object to take in front. + +CObject* CTaskTake::SearchTakeObject(float &angle, + float dLimit, float aLimit) +{ + CObject *pObj, *pBest; + Math::Vector iPos, oPos; + ObjectType type; + float min, iAngle, bAngle, a, distance; + int i; + + iPos = m_object->RetPosition(0); + iAngle = m_object->RetAngleY(0); + iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI + + min = 1000000.0f; + pBest = 0; + bAngle = 0.0f; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + + if ( type != OBJECT_FRET && + type != OBJECT_STONE && + type != OBJECT_URANIUM && + type != OBJECT_BULLET && + type != OBJECT_METAL && + type != OBJECT_POWER && + type != OBJECT_ATOMIC && + type != OBJECT_BBOX && + type != OBJECT_KEYa && + type != OBJECT_KEYb && + type != OBJECT_KEYc && + type != OBJECT_KEYd && + type != OBJECT_TNT ) continue; + + if ( pObj->RetTruck() != 0 ) continue; // object transported? + if ( pObj->RetLock() ) continue; + if ( pObj->RetZoomY(0) != 1.0f ) continue; + + oPos = pObj->RetPosition(0); + distance = Math::Distance(oPos, iPos); + if ( distance >= 4.0f-dLimit && + distance <= 4.0f+dLimit ) + { + angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) ) + { + a = fabs(angle-iAngle); + if ( a > Math::PI ) a = Math::PI*2.0f-a; + if ( a < min ) + { + min = a; + pBest = pObj; + bAngle = angle; + } + } + } + } + angle = bAngle; + return pBest; +} + +// Seeks the robot on which you want take or put a battery. + +CObject* CTaskTake::SearchFriendObject(float &angle, + float dLimit, float aLimit) +{ + Character* character; + CObject* pObj; + CObject* pPower; + Math::Matrix* mat; + Math::Vector iPos, oPos; + ObjectType type, powerType; + float iAngle, iRad, distance; + int i; + + if ( !m_object->GetCrashSphere(0, iPos, iRad) ) return 0; + iAngle = m_object->RetAngleY(0); + iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; // yourself? + + type = pObj->RetType(); + if ( type != OBJECT_MOBILEfa && + type != OBJECT_MOBILEta && + type != OBJECT_MOBILEwa && + type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfc && + type != OBJECT_MOBILEtc && + type != OBJECT_MOBILEwc && + type != OBJECT_MOBILEic && + type != OBJECT_MOBILEfi && + type != OBJECT_MOBILEti && + type != OBJECT_MOBILEwi && + type != OBJECT_MOBILEii && + type != OBJECT_MOBILEfs && + type != OBJECT_MOBILEts && + type != OBJECT_MOBILEws && + type != OBJECT_MOBILEis && + type != OBJECT_MOBILErt && + type != OBJECT_MOBILErc && + type != OBJECT_MOBILErr && + type != OBJECT_MOBILErs && + type != OBJECT_MOBILEsa && + type != OBJECT_MOBILEtg && + type != OBJECT_MOBILEft && + type != OBJECT_MOBILEtt && + type != OBJECT_MOBILEwt && + type != OBJECT_MOBILEit && + type != OBJECT_TOWER && + type != OBJECT_RESEARCH && + type != OBJECT_ENERGY && + type != OBJECT_LABO && + type != OBJECT_NUCLEAR ) continue; + + pPower = pObj->RetPower(); + if ( pPower != 0 ) + { + if ( pPower->RetLock() ) continue; + if ( pPower->RetZoomY(0) != 1.0f ) continue; + + powerType = pPower->RetType(); + if ( powerType == OBJECT_NULL || + powerType == OBJECT_FIX ) continue; + } + + mat = pObj->RetWorldMatrix(0); + character = pObj->RetCharacter(); + oPos = Transform(*mat, character->posPower); + + distance = fabs(Math::Distance(oPos, iPos) - (iRad+1.0f)); + if ( distance <= dLimit ) + { + angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) ) + { + character = pObj->RetCharacter(); + m_height = character->posPower.y; + return pObj; + } + } + } + + return 0; +} + +// Takes the object in front. + +bool CTaskTake::TruckTakeObject() +{ + CObject* fret; + CObject* other; + Math::Matrix matRotate; + float angle; + + if ( m_arm == TTA_FFRONT ) // takes on the ground in front? + { +//? fret = SearchTakeObject(angle, 1.5f, Math::PI*0.04f); + fret = SearchTakeObject(angle, 1.5f, Math::PI*0.15f); //OK 1.9 + if ( fret == 0 ) return false; // rien � prendre ? + m_fretType = fret->RetType(); + + fret->SetTruck(m_object); + fret->SetTruckPart(4); // takes with the hand + +//? fret->SetPosition(0, Math::Vector(2.2f, -1.0f, 1.1f)); + fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f)); + fret->SetAngleY(0, 0.1f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.8f); + + m_object->SetFret(fret); // takes + } + + if ( m_arm == TTA_FRIEND ) // takes friend's battery? + { + other = SearchFriendObject(angle, 1.5f, Math::PI*0.04f); + if ( other == 0 ) return false; + + fret = other->RetPower(); + if ( fret == 0 ) return false; // the other does not have a battery? + m_fretType = fret->RetType(); + + other->SetPower(0); + fret->SetTruck(m_object); + fret->SetTruckPart(4); // takes with the hand + +//? fret->SetPosition(0, Math::Vector(2.2f, -1.0f, 1.1f)); + fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f)); + fret->SetAngleY(0, 0.1f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.8f); + + m_object->SetFret(fret); // takes + } + + return true; +} + +// Deposes the object taken. + +bool CTaskTake::TruckDeposeObject() +{ + Character* character; + CObject* fret; + CObject* other; + Math::Matrix* mat; + Math::Vector pos; + float angle; + + if ( m_arm == TTA_FFRONT ) // deposes on the ground in front? + { + fret = m_object->RetFret(); + if ( fret == 0 ) return false; // does nothing? + m_fretType = fret->RetType(); + + mat = fret->RetWorldMatrix(0); + pos = Transform(*mat, Math::Vector(-0.5f, 1.0f, 0.0f)); + m_terrain->MoveOnFloor(pos); + fret->SetPosition(0, pos); + fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.0f); + fret->FloorAdjust(); // plate well on the ground + + fret->SetTruck(0); + m_object->SetFret(0); // deposit + } + + if ( m_arm == TTA_FRIEND ) // deposes battery on friends? + { + other = SearchFriendObject(angle, 1.5f, Math::PI*0.04f); + if ( other == 0 ) return false; + + fret = other->RetPower(); + if ( fret != 0 ) return false; // the other already has a battery? + + fret = m_object->RetFret(); + if ( fret == 0 ) return false; + m_fretType = fret->RetType(); + + other->SetPower(fret); + fret->SetTruck(other); + + character = other->RetCharacter(); + fret->SetPosition(0, character->posPower); + fret->SetAngleY(0, 0.0f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.0f); + fret->SetTruckPart(0); // carried by the base + + m_object->SetFret(0); // deposit + } + + return true; +} + +// Seeks if a location allows to deposit an object. + +bool CTaskTake::IsFreeDeposeObject(Math::Vector pos) +{ + CObject* pObj; + Math::Matrix* mat; + Math::Vector iPos, oPos; + float oRadius; + int i, j; + + mat = m_object->RetWorldMatrix(0); + iPos = Transform(*mat, pos); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; + if ( !pObj->RetActif() ) continue; // inactive? + if ( pObj->RetTruck() != 0 ) continue; // object transported? + + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) + { + if ( Math::Distance(iPos, oPos)-(oRadius+1.0f) < 1.0f ) + { + return false; // location occupied + } + } + } + return true; // location free +} + + diff --git a/src/object/task/tasktake.h b/src/object/task/tasktake.h index b8203a8..b0553a0 100644 --- a/src/object/task/tasktake.h +++ b/src/object/task/tasktake.h @@ -1,75 +1,75 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// tasktake.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-
-
-
-enum TaskTakeOrder
-{
- TTO_TAKE = 1, // takes an object
- TTO_DEPOSE = 2, // deposes the object
-};
-
-enum TaskTakeArm
-{
- TTA_NEUTRAL = 1, // empty arm at rest
- TTA_FFRONT = 2, // arm on the ground
- TTA_FRIEND = 3, // arm behind a friend robot
-};
-
-
-
-class CTaskTake : public CTask
-{
-public:
- CTaskTake(CInstanceManager* iMan, CObject* object);
- ~CTaskTake();
-
- bool EventProcess(const Event &event);
-
- Error Start();
- Error IsEnded();
- bool Abort();
-
-protected:
- CObject* SearchTakeObject(float &angle, float dLimit, float aLimit);
- CObject* SearchFriendObject(float &angle, float dLimit, float aLimit);
- bool TruckTakeObject();
- bool TruckDeposeObject();
- bool IsFreeDeposeObject(Math::Vector pos);
-
-protected:
- CTerrain* m_terrain;
-
- TaskTakeOrder m_order;
- TaskTakeArm m_arm;
- int m_step;
- float m_speed;
- float m_progress;
- float m_height;
- bool m_bError;
- bool m_bTurn;
- float m_angle;
- ObjectType m_fretType;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// tasktake.h + +#pragma once + + +#include "object/task/task.h" +#include "object/object.h" + + + +enum TaskTakeOrder +{ + TTO_TAKE = 1, // takes an object + TTO_DEPOSE = 2, // deposes the object +}; + +enum TaskTakeArm +{ + TTA_NEUTRAL = 1, // empty arm at rest + TTA_FFRONT = 2, // arm on the ground + TTA_FRIEND = 3, // arm behind a friend robot +}; + + + +class CTaskTake : public CTask +{ +public: + CTaskTake(CInstanceManager* iMan, CObject* object); + ~CTaskTake(); + + bool EventProcess(const Event &event); + + Error Start(); + Error IsEnded(); + bool Abort(); + +protected: + CObject* SearchTakeObject(float &angle, float dLimit, float aLimit); + CObject* SearchFriendObject(float &angle, float dLimit, float aLimit); + bool TruckTakeObject(); + bool TruckDeposeObject(); + bool IsFreeDeposeObject(Math::Vector pos); + +protected: + CTerrain* m_terrain; + + TaskTakeOrder m_order; + TaskTakeArm m_arm; + int m_step; + float m_speed; + float m_progress; + float m_height; + bool m_bError; + bool m_bTurn; + float m_angle; + ObjectType m_fretType; +}; + diff --git a/src/object/task/taskterraform.cpp b/src/object/task/taskterraform.cpp index 58cf347..94e3b75 100644 --- a/src/object/task/taskterraform.cpp +++ b/src/object/task/taskterraform.cpp @@ -1,416 +1,416 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskterraform.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskterraform.h"
-
-#include "math/geometry.h"
-#include "common/iman.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "physics/physics.h"
-#include "old/pyro.h"
-#include "object/brain.h"
-#include "object/motion/motionant.h"
-#include "object/motion/motionspider.h"
-
-
-const float ENERGY_TERRA = 0.40f; // energy consumed by blow
-const float ACTION_RADIUS = 400.0f;
-
-
-
-// Object's constructor.
-
-CTaskTerraform::CTaskTerraform(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_lastParticule = 0.0f;
- m_soundChannel = -1;
-}
-
-// Object's destructor.
-
-CTaskTerraform::~CTaskTerraform()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskTerraform::EventProcess(const Event &event)
-{
- CObject* power;
- Math::Matrix* mat;
- Math::Vector pos, dir, speed;
- Math::Point dim;
- float energy;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_progress += event.rTime*m_speed; // others advance
- m_time += event.rTime;
-
- if ( m_phase == TTP_CHARGE )
- {
- if ( m_soundChannel == -1 )
- {
-#if _TEEN
- m_soundChannel = m_sound->Play(SOUND_GGG, m_object->RetPosition(0), 1.0f, 0.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.0f, 1.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP);
-#else
- m_soundChannel = m_sound->Play(SOUND_GGG, m_object->RetPosition(0), 1.0f, 0.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.0f, 4.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP);
-#endif
- }
-
- dir.x = 0.0f;
- dir.y = (Math::Rand()-0.5f)*0.2f*m_progress;
- dir.z = 0.0f;
- m_object->SetCirVibration(dir);
-
- m_object->SetZoom(0, 1.0f+m_progress*0.2f);
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- power->SetZoom(0, 1.0f+m_progress*1.0f);
-
- energy = power->RetEnergy();
- energy -= event.rTime*ENERGY_TERRA/power->RetCapacity()/4.0f;
- if ( energy < 0.0f ) energy = 0.0f;
- power->SetEnergy(energy);
- }
- }
-
- if ( m_phase == TTP_DOWN )
- {
- pos.x = 9.0f;
-#if _TEEN
- pos.y = 4.0f-m_progress*4.0f;
-#else
- pos.y = 4.0f-m_progress*5.8f;
-#endif
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
- }
-
- if ( m_phase == TTP_UP )
- {
- pos.x = 9.0f;
-#if _TEEN
- pos.y = 4.0f-(1.0f-m_progress)*4.0f;
-#else
- pos.y = 4.0f-(1.0f-m_progress)*5.8f;
-#endif
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
- }
-
- dir.x = 0.0f;
- dir.y = 0.0f;
- dir.z = 0.0f;
- pos = m_object->RetPosition(2);
- if ( pos.y < 0.0f )
- {
- dir.z = -atanf((pos.y/2.0f)/9.0f);
- }
- m_object->SetInclinaison(dir);
-
- if ( m_time-m_lastParticule >= m_engine->ParticuleAdapt(0.05f) )
- {
- m_lastParticule = m_time;
-
- mat = m_object->RetWorldMatrix(0);
-
- if ( m_phase == TTP_CHARGE )
- {
- // Battery.
- pos = Math::Vector(-6.0f, 5.5f+2.0f*m_progress, 0.0f);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- pos = Math::Transform(*mat, pos);
- speed.x = (Math::Rand()-0.5f)*6.0f*(1.0f+m_progress*4.0f);
- speed.z = (Math::Rand()-0.5f)*6.0f*(1.0f+m_progress*4.0f);
- speed.y = 6.0f+Math::Rand()*4.0f*(1.0f+m_progress*2.0f);
- dim.x = 0.5f+1.5f*m_progress;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 2.0f, 20.0f);
- }
-
- if ( m_phase != TTP_CHARGE )
- {
- // Left grid.
- pos = Math::Vector(-1.0f, 5.8f, 3.5f);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- pos = Math::Transform(*mat, pos);
- speed.x = Math::Rand()*4.0f;
- speed.z = Math::Rand()*2.0f;
- speed.y = 2.5f+Math::Rand()*1.0f;
- speed = Math::Transform(*mat, speed);
- speed -= m_object->RetPosition(0);
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
-
- // Right grid.
- pos = Math::Vector(-1.0f, 5.8f, -3.5f);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- pos = Math::Transform(*mat, pos);
- speed.x = Math::Rand()*4.0f;
- speed.z = -Math::Rand()*2.0f;
- speed.y = 2.5f+Math::Rand()*1.0f;
- speed = Math::Transform(*mat, speed);
- speed -= m_object->RetPosition(0);
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
- }
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskTerraform::Start()
-{
- CObject* power;
- Math::Matrix* mat;
- Math::Vector pos, speed;
- float energy;
-
- ObjectType type;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() ) return ERR_TERRA_VEH;
-
- type = m_object->RetType();
- if ( type != OBJECT_MOBILErt ) return ERR_TERRA_VEH;
-
- power = m_object->RetPower();
- if ( power == 0 ) return ERR_TERRA_ENERGY;
- energy = power->RetEnergy();
- if ( energy < ENERGY_TERRA/power->RetCapacity()+0.05f ) return ERR_TERRA_ENERGY;
-
- speed = m_physics->RetMotorSpeed();
- if ( speed.x != 0.0f ||
- speed.z != 0.0f ) return ERR_MANIP_MOTOR;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(9.0f, 0.0f, 0.0f);
- pos = Math::Transform(*mat, pos); // battery position
- m_terraPos = pos;
-
- m_phase = TTP_CHARGE;
- m_progress = 0.0f;
-#if _TEEN
- m_speed = 1.0f/1.5f;
-#else
- m_speed = 1.0f/4.0f;
-#endif
- m_time = 0.0f;
-
- m_bError = false; // ok
-
- m_camera->StartCentering(m_object, Math::PI*0.35f, 99.9f, 20.0f, 2.0f);
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskTerraform::IsEnded()
-{
- CObject* power;
- Math::Vector pos, speed;
- Math::Point dim;
- float dist, duration;
- int i, max;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( m_phase == TTP_CHARGE )
- {
-#if _TEEN
- Terraform(); // changes the terrain.
-#endif
-
- m_phase = TTP_DOWN;
- m_speed = 1.0f/0.2f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TTP_DOWN )
- {
-#if !_TEEN
- Terraform(); // changes the terrain.
-#endif
-
- m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetZoom(0, 1.0f);
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- power->SetZoom(0, 1.0f);
- }
-
- max= (int)(50.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<max ; i++ )
- {
- pos.x = m_terraPos.x+(Math::Rand()-0.5f)*80.0f;
- pos.z = m_terraPos.z+(Math::Rand()-0.5f)*80.0f;
- pos.y = m_terraPos.y;
- m_terrain->MoveOnFloor(pos);
- dist = Math::Distance(pos, m_terraPos);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 2.0f+(40.0f-dist)/(1.0f+Math::Rand()*4.0f);
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
-
- pos = m_terraPos;
- speed.x = (Math::Rand()-0.5f)*40.0f;
- speed.z = (Math::Rand()-0.5f)*40.0f;
- speed.y = Math::Rand()*15.0f+15.0f;
- dim.x = 0.6f;
- dim.y = dim.x;
- pos.y += dim.y;
- duration = Math::Rand()*3.0f+3.0f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK5,
- duration, Math::Rand()*10.0f+15.0f,
- duration*0.2f, 1.0f);
- }
-
- m_phase = TTP_TERRA;
- m_speed = 1.0f/2.0f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TTP_TERRA )
- {
- m_phase = TTP_UP;
- m_speed = 1.0f/1.0f;
- return ERR_CONTINUE;
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskTerraform::Abort()
-{
- CObject* power;
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.3f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- m_object->SetPosition(2, Math::Vector(9.0f, 4.0f, 0.0f));
- m_object->SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetZoom(0, 1.0f);
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- power->SetZoom(0, 1.0f);
- }
-
- m_camera->StopCentering(m_object, 2.0f);
- return true;
-}
-
-
-// Returns all the close ants and spiders.
-
-bool CTaskTerraform::Terraform()
-{
- CObject* pObj;
- CBrain* brain;
- CMotion* motion;
- CPyro* pyro;
- ObjectType type;
- float dist;
- int i;
-
- m_camera->StartEffect(CE_TERRAFORM, m_terraPos, 1.0f);
-
- m_sound->Play(SOUND_THUMP, m_terraPos);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_NULL ) continue;
-
- if ( type == OBJECT_TEEN34 ) // stone?
- {
- dist = Math::Distance(m_terraPos, pObj->RetPosition(0));
- if ( dist > 20.0f ) continue;
-
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FRAGT, pObj);
- }
- else
- {
- motion = pObj->RetMotion();
- if ( motion == 0 ) continue;
-
- dist = Math::Distance(m_terraPos, pObj->RetPosition(0));
- if ( dist > ACTION_RADIUS ) continue;
-
- if ( type == OBJECT_ANT )
- {
- brain = pObj->RetBrain();
- if ( brain != 0 ) brain->StopTask();
- motion->SetAction(MAS_BACK1, 0.8f+Math::Rand()*0.3f);
- pObj->SetFixed(true); // not moving
- }
- if ( type == OBJECT_SPIDER )
- {
- brain = pObj->RetBrain();
- if ( brain != 0 ) brain->StopTask();
- motion->SetAction(MSS_BACK1, 0.8f+Math::Rand()*0.3f);
- pObj->SetFixed(true); // not moving
- }
- }
- }
-
- return true;
-}
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskterraform.cpp + + +#include <stdio.h> + +#include "object/task/taskterraform.h" + +#include "math/geometry.h" +#include "common/iman.h" +#include "old/particule.h" +#include "old/terrain.h" +#include "physics/physics.h" +#include "old/pyro.h" +#include "object/brain.h" +#include "object/motion/motionant.h" +#include "object/motion/motionspider.h" + + +const float ENERGY_TERRA = 0.40f; // energy consumed by blow +const float ACTION_RADIUS = 400.0f; + + + +// Object's constructor. + +CTaskTerraform::CTaskTerraform(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + m_lastParticule = 0.0f; + m_soundChannel = -1; +} + +// Object's destructor. + +CTaskTerraform::~CTaskTerraform() +{ +} + + +// Management of an event. + +bool CTaskTerraform::EventProcess(const Event &event) +{ + CObject* power; + Math::Matrix* mat; + Math::Vector pos, dir, speed; + Math::Point dim; + float energy; + + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + if ( m_bError ) return false; + + m_progress += event.rTime*m_speed; // others advance + m_time += event.rTime; + + if ( m_phase == TTP_CHARGE ) + { + if ( m_soundChannel == -1 ) + { +#if _TEEN + m_soundChannel = m_sound->Play(SOUND_GGG, m_object->RetPosition(0), 1.0f, 0.5f, true); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.0f, 1.5f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP); +#else + m_soundChannel = m_sound->Play(SOUND_GGG, m_object->RetPosition(0), 1.0f, 0.5f, true); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.0f, 4.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP); +#endif + } + + dir.x = 0.0f; + dir.y = (Math::Rand()-0.5f)*0.2f*m_progress; + dir.z = 0.0f; + m_object->SetCirVibration(dir); + + m_object->SetZoom(0, 1.0f+m_progress*0.2f); + + power = m_object->RetPower(); + if ( power != 0 ) + { + power->SetZoom(0, 1.0f+m_progress*1.0f); + + energy = power->RetEnergy(); + energy -= event.rTime*ENERGY_TERRA/power->RetCapacity()/4.0f; + if ( energy < 0.0f ) energy = 0.0f; + power->SetEnergy(energy); + } + } + + if ( m_phase == TTP_DOWN ) + { + pos.x = 9.0f; +#if _TEEN + pos.y = 4.0f-m_progress*4.0f; +#else + pos.y = 4.0f-m_progress*5.8f; +#endif + pos.z = 0.0f; + m_object->SetPosition(2, pos); + } + + if ( m_phase == TTP_UP ) + { + pos.x = 9.0f; +#if _TEEN + pos.y = 4.0f-(1.0f-m_progress)*4.0f; +#else + pos.y = 4.0f-(1.0f-m_progress)*5.8f; +#endif + pos.z = 0.0f; + m_object->SetPosition(2, pos); + } + + dir.x = 0.0f; + dir.y = 0.0f; + dir.z = 0.0f; + pos = m_object->RetPosition(2); + if ( pos.y < 0.0f ) + { + dir.z = -atanf((pos.y/2.0f)/9.0f); + } + m_object->SetInclinaison(dir); + + if ( m_time-m_lastParticule >= m_engine->ParticuleAdapt(0.05f) ) + { + m_lastParticule = m_time; + + mat = m_object->RetWorldMatrix(0); + + if ( m_phase == TTP_CHARGE ) + { + // Battery. + pos = Math::Vector(-6.0f, 5.5f+2.0f*m_progress, 0.0f); + pos.x += (Math::Rand()-0.5f)*1.0f; + pos.z += (Math::Rand()-0.5f)*1.0f; + pos = Math::Transform(*mat, pos); + speed.x = (Math::Rand()-0.5f)*6.0f*(1.0f+m_progress*4.0f); + speed.z = (Math::Rand()-0.5f)*6.0f*(1.0f+m_progress*4.0f); + speed.y = 6.0f+Math::Rand()*4.0f*(1.0f+m_progress*2.0f); + dim.x = 0.5f+1.5f*m_progress; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 2.0f, 20.0f); + } + + if ( m_phase != TTP_CHARGE ) + { + // Left grid. + pos = Math::Vector(-1.0f, 5.8f, 3.5f); + pos.x += (Math::Rand()-0.5f)*1.0f; + pos.z += (Math::Rand()-0.5f)*1.0f; + pos = Math::Transform(*mat, pos); + speed.x = Math::Rand()*4.0f; + speed.z = Math::Rand()*2.0f; + speed.y = 2.5f+Math::Rand()*1.0f; + speed = Math::Transform(*mat, speed); + speed -= m_object->RetPosition(0); + dim.x = Math::Rand()*1.0f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f); + + // Right grid. + pos = Math::Vector(-1.0f, 5.8f, -3.5f); + pos.x += (Math::Rand()-0.5f)*1.0f; + pos.z += (Math::Rand()-0.5f)*1.0f; + pos = Math::Transform(*mat, pos); + speed.x = Math::Rand()*4.0f; + speed.z = -Math::Rand()*2.0f; + speed.y = 2.5f+Math::Rand()*1.0f; + speed = Math::Transform(*mat, speed); + speed -= m_object->RetPosition(0); + dim.x = Math::Rand()*1.0f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f); + } + } + + return true; +} + + +// Assigns the goal was achieved. + +Error CTaskTerraform::Start() +{ + CObject* power; + Math::Matrix* mat; + Math::Vector pos, speed; + float energy; + + ObjectType type; + + m_bError = true; // operation impossible + if ( !m_physics->RetLand() ) return ERR_TERRA_VEH; + + type = m_object->RetType(); + if ( type != OBJECT_MOBILErt ) return ERR_TERRA_VEH; + + power = m_object->RetPower(); + if ( power == 0 ) return ERR_TERRA_ENERGY; + energy = power->RetEnergy(); + if ( energy < ENERGY_TERRA/power->RetCapacity()+0.05f ) return ERR_TERRA_ENERGY; + + speed = m_physics->RetMotorSpeed(); + if ( speed.x != 0.0f || + speed.z != 0.0f ) return ERR_MANIP_MOTOR; + + mat = m_object->RetWorldMatrix(0); + pos = Math::Vector(9.0f, 0.0f, 0.0f); + pos = Math::Transform(*mat, pos); // battery position + m_terraPos = pos; + + m_phase = TTP_CHARGE; + m_progress = 0.0f; +#if _TEEN + m_speed = 1.0f/1.5f; +#else + m_speed = 1.0f/4.0f; +#endif + m_time = 0.0f; + + m_bError = false; // ok + + m_camera->StartCentering(m_object, Math::PI*0.35f, 99.9f, 20.0f, 2.0f); + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskTerraform::IsEnded() +{ + CObject* power; + Math::Vector pos, speed; + Math::Point dim; + float dist, duration; + int i, max; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + m_progress = 0.0f; + + if ( m_phase == TTP_CHARGE ) + { +#if _TEEN + Terraform(); // changes the terrain. +#endif + + m_phase = TTP_DOWN; + m_speed = 1.0f/0.2f; + return ERR_CONTINUE; + } + + if ( m_phase == TTP_DOWN ) + { +#if !_TEEN + Terraform(); // changes the terrain. +#endif + + m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f)); + m_object->SetZoom(0, 1.0f); + + power = m_object->RetPower(); + if ( power != 0 ) + { + power->SetZoom(0, 1.0f); + } + + max= (int)(50.0f*m_engine->RetParticuleDensity()); + for ( i=0 ; i<max ; i++ ) + { + pos.x = m_terraPos.x+(Math::Rand()-0.5f)*80.0f; + pos.z = m_terraPos.z+(Math::Rand()-0.5f)*80.0f; + pos.y = m_terraPos.y; + m_terrain->MoveOnFloor(pos); + dist = Math::Distance(pos, m_terraPos); + speed = Math::Vector(0.0f, 0.0f, 0.0f); + dim.x = 2.0f+(40.0f-dist)/(1.0f+Math::Rand()*4.0f); + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f); + + pos = m_terraPos; + speed.x = (Math::Rand()-0.5f)*40.0f; + speed.z = (Math::Rand()-0.5f)*40.0f; + speed.y = Math::Rand()*15.0f+15.0f; + dim.x = 0.6f; + dim.y = dim.x; + pos.y += dim.y; + duration = Math::Rand()*3.0f+3.0f; + m_particule->CreateTrack(pos, speed, dim, PARTITRACK5, + duration, Math::Rand()*10.0f+15.0f, + duration*0.2f, 1.0f); + } + + m_phase = TTP_TERRA; + m_speed = 1.0f/2.0f; + return ERR_CONTINUE; + } + + if ( m_phase == TTP_TERRA ) + { + m_phase = TTP_UP; + m_speed = 1.0f/1.0f; + return ERR_CONTINUE; + } + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +bool CTaskTerraform::Abort() +{ + CObject* power; + + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.3f, SOPER_STOP); + m_soundChannel = -1; + } + + m_object->SetPosition(2, Math::Vector(9.0f, 4.0f, 0.0f)); + m_object->SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f)); + m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f)); + m_object->SetZoom(0, 1.0f); + + power = m_object->RetPower(); + if ( power != 0 ) + { + power->SetZoom(0, 1.0f); + } + + m_camera->StopCentering(m_object, 2.0f); + return true; +} + + +// Returns all the close ants and spiders. + +bool CTaskTerraform::Terraform() +{ + CObject* pObj; + CBrain* brain; + CMotion* motion; + CPyro* pyro; + ObjectType type; + float dist; + int i; + + m_camera->StartEffect(CE_TERRAFORM, m_terraPos, 1.0f); + + m_sound->Play(SOUND_THUMP, m_terraPos); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type == OBJECT_NULL ) continue; + + if ( type == OBJECT_TEEN34 ) // stone? + { + dist = Math::Distance(m_terraPos, pObj->RetPosition(0)); + if ( dist > 20.0f ) continue; + + pyro = new CPyro(m_iMan); + pyro->Create(PT_FRAGT, pObj); + } + else + { + motion = pObj->RetMotion(); + if ( motion == 0 ) continue; + + dist = Math::Distance(m_terraPos, pObj->RetPosition(0)); + if ( dist > ACTION_RADIUS ) continue; + + if ( type == OBJECT_ANT ) + { + brain = pObj->RetBrain(); + if ( brain != 0 ) brain->StopTask(); + motion->SetAction(MAS_BACK1, 0.8f+Math::Rand()*0.3f); + pObj->SetFixed(true); // not moving + } + if ( type == OBJECT_SPIDER ) + { + brain = pObj->RetBrain(); + if ( brain != 0 ) brain->StopTask(); + motion->SetAction(MSS_BACK1, 0.8f+Math::Rand()*0.3f); + pObj->SetFixed(true); // not moving + } + } + } + + return true; +} + diff --git a/src/object/task/taskterraform.h b/src/object/task/taskterraform.h index d4798e6..5c9c114 100644 --- a/src/object/task/taskterraform.h +++ b/src/object/task/taskterraform.h @@ -1,62 +1,62 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskterraform.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-enum TaskTerraPhase
-{
- TTP_CHARGE = 1, // charge of energy
- TTP_DOWN = 2, // down
- TTP_TERRA = 3, // strike
- TTP_UP = 4, // up
-};
-
-
-
-class CTaskTerraform : public CTask
-{
-public:
- CTaskTerraform(CInstanceManager* iMan, CObject* object);
- ~CTaskTerraform();
-
- bool EventProcess(const Event &event);
-
- Error Start();
- Error IsEnded();
- bool Abort();
-
-protected:
- bool Terraform();
-
-protected:
- TaskTerraPhase m_phase;
- float m_progress;
- float m_speed;
- float m_time;
- float m_lastParticule;
- int m_soundChannel;
- bool m_bError;
- Math::Vector m_terraPos;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskterraform.h + +#pragma once + + +#include "object/task/task.h" +#include "math/vector.h" + + + +enum TaskTerraPhase +{ + TTP_CHARGE = 1, // charge of energy + TTP_DOWN = 2, // down + TTP_TERRA = 3, // strike + TTP_UP = 4, // up +}; + + + +class CTaskTerraform : public CTask +{ +public: + CTaskTerraform(CInstanceManager* iMan, CObject* object); + ~CTaskTerraform(); + + bool EventProcess(const Event &event); + + Error Start(); + Error IsEnded(); + bool Abort(); + +protected: + bool Terraform(); + +protected: + TaskTerraPhase m_phase; + float m_progress; + float m_speed; + float m_time; + float m_lastParticule; + int m_soundChannel; + bool m_bError; + Math::Vector m_terraPos; +}; + diff --git a/src/object/task/taskturn.cpp b/src/object/task/taskturn.cpp index d29cdaa..f8bf26c 100644 --- a/src/object/task/taskturn.cpp +++ b/src/object/task/taskturn.cpp @@ -1,134 +1,134 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskturn.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskturn.h"
-
-#include "old/terrain.h"
-#include "physics/physics.h"
-
-
-
-
-// Object's constructor.
-
-CTaskTurn::CTaskTurn(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskTurn::~CTaskTurn()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskTurn::EventProcess(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- // Momentarily stationary object (ant on the back)?
- if ( m_object->RetFixed() )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_bError = true;
- return true;
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-// A positive angle is turning right.
-
-Error CTaskTurn::Start(float angle)
-{
- m_startAngle = m_object->RetAngleY(0);
- m_finalAngle = m_startAngle+angle;
-
- if ( angle < 0.0f )
- {
- m_angle = angle+m_physics->RetCirStopLength();
- m_physics->SetMotorSpeedZ(-1.0f); // turns left
- m_bLeft = true;
- }
- else
- {
- m_angle = angle-m_physics->RetCirStopLength();
- m_physics->SetMotorSpeedZ(1.0f); // turns right
- m_bLeft = false;
- }
- m_physics->SetMotorSpeedX(0.0f);
- m_physics->SetMotorSpeedY(0.0f);
-
- m_bError = false;
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskTurn::IsEnded()
-{
- float angle;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
-
- if ( m_bError )
- {
- return ERR_STOP;
- }
-
- angle = m_object->RetAngleY(0);
-
- if ( m_bLeft )
- {
- if ( angle <= m_startAngle+m_angle )
- {
- m_physics->SetMotorSpeedZ(0.0f);
-//? m_physics->SetCirMotionY(MO_MOTSPEED, 0.0f);
- m_physics->SetCirMotionY(MO_CURSPEED, 0.0f);
-//? m_physics->SetCirMotionY(MO_REASPEED, 0.0f);
- m_object->SetAngleY(0, m_finalAngle);
- return ERR_STOP;
- }
- }
- else
- {
- if ( angle >= m_startAngle+m_angle )
- {
- m_physics->SetMotorSpeedZ(0.0f);
-//? m_physics->SetCirMotionY(MO_MOTSPEED, 0.0f);
- m_physics->SetCirMotionY(MO_CURSPEED, 0.0f);
-//? m_physics->SetCirMotionY(MO_REASPEED, 0.0f);
- m_object->SetAngleY(0, m_finalAngle);
- return ERR_STOP;
- }
- }
-
- return ERR_CONTINUE;
-}
-
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskturn.cpp + + +#include <stdio.h> + +#include "object/task/taskturn.h" + +#include "old/terrain.h" +#include "physics/physics.h" + + + + +// Object's constructor. + +CTaskTurn::CTaskTurn(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ +} + +// Object's destructor. + +CTaskTurn::~CTaskTurn() +{ +} + + +// Management of an event. + +bool CTaskTurn::EventProcess(const Event &event) +{ + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + + // Momentarily stationary object (ant on the back)? + if ( m_object->RetFixed() ) + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + m_bError = true; + return true; + } + + return true; +} + + +// Assigns the goal was achieved. +// A positive angle is turning right. + +Error CTaskTurn::Start(float angle) +{ + m_startAngle = m_object->RetAngleY(0); + m_finalAngle = m_startAngle+angle; + + if ( angle < 0.0f ) + { + m_angle = angle+m_physics->RetCirStopLength(); + m_physics->SetMotorSpeedZ(-1.0f); // turns left + m_bLeft = true; + } + else + { + m_angle = angle-m_physics->RetCirStopLength(); + m_physics->SetMotorSpeedZ(1.0f); // turns right + m_bLeft = false; + } + m_physics->SetMotorSpeedX(0.0f); + m_physics->SetMotorSpeedY(0.0f); + + m_bError = false; + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskTurn::IsEnded() +{ + float angle; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + + if ( m_bError ) + { + return ERR_STOP; + } + + angle = m_object->RetAngleY(0); + + if ( m_bLeft ) + { + if ( angle <= m_startAngle+m_angle ) + { + m_physics->SetMotorSpeedZ(0.0f); +//? m_physics->SetCirMotionY(MO_MOTSPEED, 0.0f); + m_physics->SetCirMotionY(MO_CURSPEED, 0.0f); +//? m_physics->SetCirMotionY(MO_REASPEED, 0.0f); + m_object->SetAngleY(0, m_finalAngle); + return ERR_STOP; + } + } + else + { + if ( angle >= m_startAngle+m_angle ) + { + m_physics->SetMotorSpeedZ(0.0f); +//? m_physics->SetCirMotionY(MO_MOTSPEED, 0.0f); + m_physics->SetCirMotionY(MO_CURSPEED, 0.0f); +//? m_physics->SetCirMotionY(MO_REASPEED, 0.0f); + m_object->SetAngleY(0, m_finalAngle); + return ERR_STOP; + } + } + + return ERR_CONTINUE; +} + + diff --git a/src/object/task/taskturn.h b/src/object/task/taskturn.h index bfbd064..1ee40d9 100644 --- a/src/object/task/taskturn.h +++ b/src/object/task/taskturn.h @@ -1,46 +1,46 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskturn.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskTurn : public CTask
-{
-public:
- CTaskTurn(CInstanceManager* iMan, CObject* object);
- ~CTaskTurn();
-
- bool EventProcess(const Event &event);
-
- Error Start(float angle);
- Error IsEnded();
-
-protected:
-
-protected:
- float m_angle;
- float m_startAngle;
- float m_finalAngle;
- bool m_bLeft;
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskturn.h + +#pragma once + + +#include "object/task/task.h" + + + +class CTaskTurn : public CTask +{ +public: + CTaskTurn(CInstanceManager* iMan, CObject* object); + ~CTaskTurn(); + + bool EventProcess(const Event &event); + + Error Start(float angle); + Error IsEnded(); + +protected: + +protected: + float m_angle; + float m_startAngle; + float m_finalAngle; + bool m_bLeft; + bool m_bError; +}; + diff --git a/src/object/task/taskwait.cpp b/src/object/task/taskwait.cpp index f501405..03bddcb 100644 --- a/src/object/task/taskwait.cpp +++ b/src/object/task/taskwait.cpp @@ -1,74 +1,74 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskwait.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskwait.h"
-
-#include "old/d3dengine.h"
-
-
-
-// Object's constructor.
-
-CTaskWait::CTaskWait(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskWait::~CTaskWait()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskWait::EventProcess(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_passTime += event.rTime;
- m_bEnded = (m_passTime >= m_waitTime);
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskWait::Start(float time)
-{
- m_waitTime = time; // duration to wait
- m_passTime = 0.0f; // time elapsed
- m_bEnded = false;
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskWait::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bEnded ) return ERR_STOP;
- return ERR_CONTINUE;
-}
-
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskwait.cpp + + +#include <stdio.h> + +#include "object/task/taskwait.h" + +#include "old/d3dengine.h" + + + +// Object's constructor. + +CTaskWait::CTaskWait(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ +} + +// Object's destructor. + +CTaskWait::~CTaskWait() +{ +} + + +// Management of an event. + +bool CTaskWait::EventProcess(const Event &event) +{ + if ( m_engine->RetPause() ) return true; + if ( event.event != EVENT_FRAME ) return true; + + m_passTime += event.rTime; + m_bEnded = (m_passTime >= m_waitTime); + return true; +} + + +// Assigns the goal was achieved. + +Error CTaskWait::Start(float time) +{ + m_waitTime = time; // duration to wait + m_passTime = 0.0f; // time elapsed + m_bEnded = false; + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskWait::IsEnded() +{ + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bEnded ) return ERR_STOP; + return ERR_CONTINUE; +} + + diff --git a/src/object/task/taskwait.h b/src/object/task/taskwait.h index 3439bc8..3434c36 100644 --- a/src/object/task/taskwait.h +++ b/src/object/task/taskwait.h @@ -1,44 +1,44 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskwait.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskWait : public CTask
-{
-public:
- CTaskWait(CInstanceManager* iMan, CObject* object);
- ~CTaskWait();
-
- bool EventProcess(const Event &event);
-
- Error Start(float time);
- Error IsEnded();
-
-protected:
-
-protected:
- float m_waitTime;
- float m_passTime;
- bool m_bEnded;
-};
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// taskwait.h + +#pragma once + + +#include "object/task/task.h" + + + +class CTaskWait : public CTask +{ +public: + CTaskWait(CInstanceManager* iMan, CObject* object); + ~CTaskWait(); + + bool EventProcess(const Event &event); + + Error Start(float time); + Error IsEnded(); + +protected: + +protected: + float m_waitTime; + float m_passTime; + bool m_bEnded; +}; + |