2012-06-26 20:23:05 +00:00
|
|
|
|
// * This file is part of the COLOBOT source code
|
|
|
|
|
// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
|
|
|
|
|
// *
|
|
|
|
|
// * This program is free software: you can redistribute it and/or modify
|
|
|
|
|
// * it under the terms of the GNU General Public License as published by
|
|
|
|
|
// * the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
// * (at your option) any later version.
|
|
|
|
|
// *
|
|
|
|
|
// * This program is distributed in the hope that it will be useful,
|
|
|
|
|
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
// * GNU General Public License for more details.
|
|
|
|
|
// *
|
|
|
|
|
// * You should have received a copy of the GNU General Public License
|
|
|
|
|
// * along with this program. If not, see http://www.gnu.org/licenses/.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
#include "object/task/taskgoto.h"
|
|
|
|
|
|
|
|
|
|
#include "common/event.h"
|
|
|
|
|
#include "common/iman.h"
|
2013-02-16 21:37:43 +00:00
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
#include "graphics/engine/terrain.h"
|
|
|
|
|
#include "graphics/engine/water.h"
|
2013-02-16 21:37:43 +00:00
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
|
#include "math/geometry.h"
|
2013-02-16 21:37:43 +00:00
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
|
#include "physics/physics.h"
|
|
|
|
|
|
2012-09-15 16:50:51 +00:00
|
|
|
|
#include <string.h>
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
2013-02-16 21:37:43 +00:00
|
|
|
|
CTaskGoto::CTaskGoto(CObject* object) : CTask(object)
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
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;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
float a, g, dist, linSpeed, cirSpeed, h, hh, factor, dir;
|
|
|
|
|
Error ret;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_engine->GetPause() ) return true;
|
|
|
|
|
if ( event.type != EVENT_FRAME ) return true;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
// Momentarily stationary object (ant on the back)?
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_object->GetFixed() )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
pos = m_object->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
rot.x = m_leakPos.x-pos.x;
|
|
|
|
|
rot.y = m_leakPos.z-pos.z;
|
|
|
|
|
dist = Math::Point(rot.x, rot.y).Length();
|
2013-04-26 14:51:17 +00:00
|
|
|
|
if (dist != 0) {
|
|
|
|
|
rot.x /= dist;
|
|
|
|
|
rot.y /= dist;
|
|
|
|
|
}
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
a = m_object->GetAngleY(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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.
|
2012-09-11 21:11:34 +00:00
|
|
|
|
BitmapClearCircle(m_object->GetPosition(0), BM_DIM_STEP*1.8f);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
pos = m_object->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
if ( m_bmFretObject == 0 )
|
|
|
|
|
{
|
|
|
|
|
goal = m_goal;
|
|
|
|
|
dist = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
goal = m_goalObject;
|
|
|
|
|
dist = TAKE_DIST+2.0f;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_bmFretObject->GetType() == OBJECT_BASE ) dist = 12.0f;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = BeamSearch(pos, goal, dist);
|
|
|
|
|
if ( ret == ERR_OK )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetLand() ) m_phase = TGP_BEAMWCOLD;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
else m_phase = TGP_BEAMGOTO;
|
|
|
|
|
m_bmIndex = 0;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
m_bmWatchDogPos = m_object->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
m_bmWatchDogTime = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
if ( ret == ERR_GOTO_IMPOSSIBLE || ret == ERR_GOTO_ITER )
|
|
|
|
|
{
|
|
|
|
|
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? (?)
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetCollision() ) // collision?
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
m_physics->SetCollision(false); // there's more
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
pos = m_object->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetType() == TYPE_FLYING && m_altitude == 0.0f )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetLand() )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
m_physics->SetMotorSpeedY(0.0f);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_physics->SetMotorSpeedY(-1.0f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetType() == TYPE_FLYING && m_altitude > 0.0f )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
goal = m_bmPoints[m_bmIndex];
|
|
|
|
|
goal.y = pos.y;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
h = m_terrain->GetHeightToFloor(goal, true, true);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
dist = Math::DistanceProjected(pos, goal);
|
|
|
|
|
if ( dist != 0.0f ) // anticipates?
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
linSpeed = m_physics->GetLinMotionX(MO_REASPEED);
|
|
|
|
|
linSpeed /= m_physics->GetLinMotionX(MO_ADVSPEED);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
hh = m_terrain->GetHeightToFloor(goal, true, true);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
a = m_object->GetAngleY(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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?
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
linSpeed = dist/(m_physics->GetLinStopLength()*1.5f);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetCollision() ) // collision?
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
m_physics->SetCollision(false); // there's more
|
|
|
|
|
m_error = ERR_STOP;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
pos = m_object->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
if ( m_altitude > 0.0f )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
h = m_terrain->GetHeightToFloor(pos, true, true);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
a = m_object->GetAngleY(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 &&
|
2012-09-11 21:11:34 +00:00
|
|
|
|
m_physics->GetType() == TYPE_FLYING &&
|
2012-06-26 20:23:05 +00:00
|
|
|
|
m_altitude > 0.0f )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
pos = m_object->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
h = m_terrain->GetHeightToFloor(m_object->GetPosition(0), true, true);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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?
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetCollision() ) // collision?
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
m_physics->SetCollision(false); // there's more
|
|
|
|
|
m_time = 0.0f;
|
|
|
|
|
m_phase = TGP_CRWAIT;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 0
|
2012-09-11 21:11:34 +00:00
|
|
|
|
pos = m_object->GetPosition(0);
|
|
|
|
|
a = m_object->GetAngleY(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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);
|
2012-09-11 21:11:34 +00:00
|
|
|
|
linSpeed = dist/(m_physics->GetLinStopLength()*1.5f);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( linSpeed > 1.0f ) linSpeed = 1.0f;
|
|
|
|
|
|
|
|
|
|
if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f )
|
|
|
|
|
{
|
|
|
|
|
linSpeed = 0.0f; // turns first, then advance
|
|
|
|
|
}
|
|
|
|
|
#else
|
2012-09-11 21:11:34 +00:00
|
|
|
|
pos = m_object->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
a = m_object->GetAngleY(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
g = Math::RotateAngle(rot.x, -rot.y); // CW !
|
|
|
|
|
cirSpeed = Math::Direction(a, g)*1.0f;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
//? if ( m_physics->GetType() == TYPE_FLYING &&
|
|
|
|
|
//? m_physics->GetLand() ) // flying on the ground?
|
2012-06-26 20:23:05 +00:00
|
|
|
|
//? {
|
|
|
|
|
//? 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);
|
2012-09-11 21:11:34 +00:00
|
|
|
|
linSpeed = dist/(m_physics->GetLinStopLength()*1.5f);
|
|
|
|
|
//? if ( m_physics->GetType() == TYPE_FLYING &&
|
|
|
|
|
//? m_physics->GetLand() ) // flying on the ground?
|
2012-06-26 20:23:05 +00:00
|
|
|
|
//? {
|
|
|
|
|
//? 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?
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
a = m_object->GetAngleY(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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?
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetCollision() ) // collision?
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
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?
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetCollision() ) // collision?
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
|
2013-02-16 21:37:43 +00:00
|
|
|
|
CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
iPos = m_object->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
min = 1000000.0f;
|
|
|
|
|
|
|
|
|
|
for ( i=0 ; i<1000000 ; i++ )
|
|
|
|
|
{
|
2013-02-16 21:37:43 +00:00
|
|
|
|
pObj = static_cast<CObject*>(iMan->SearchInstance(CLASS_OBJECT, i));
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( pObj == 0 ) break;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
oType = pObj->GetType();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( pObj->GetVirusMode() ) continue; // object infected?
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
if ( !pObj->GetCrashSphere(0, oPos, radius) ) continue;
|
|
|
|
|
distance = Math::DistanceProjected(oPos, iPos);
|
|
|
|
|
if ( distance < min )
|
|
|
|
|
{
|
|
|
|
|
min = distance;
|
|
|
|
|
pBest = pObj;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( pBest == 0 ) return 0;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
impact = pBest->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
pos = m_object->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
type = m_object->GetType();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
pos = m_object->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
m_goal = target->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
m_goal = target->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetType() == TYPE_FLYING && m_altitude == 0.0f )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
pos = m_object->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
x = static_cast<int>((m_goal.x+1600.0f)/BM_DIM_STEP);
|
|
|
|
|
y = static_cast<int>((m_goal.z+1600.0f)/BM_DIM_STEP);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( BitmapTestDot(0, x, y) ) // arrival occupied?
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_engine->GetPause() ) return ERR_CONTINUE;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( m_error != ERR_OK ) return m_error;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
pos = m_object->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
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 &&
|
2012-09-11 21:11:34 +00:00
|
|
|
|
m_physics->GetReactorRange() < 1.0f ) return ERR_CONTINUE;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
m_phase = TGP_BEAMUP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( m_phase == TGP_BEAMUP ) // off?
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetType() == TYPE_FLYING && m_altitude > 0.0f )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
level = m_terrain->GetFloorLevel(pos, true, true);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
h = level+m_altitude-20.0f;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
limit = m_terrain->GetFlyingMaxHeight();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 &&
|
2012-09-11 21:11:34 +00:00
|
|
|
|
m_physics->GetReactorRange() < 0.1f ) // overheating?
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetLand() ) // on the ground?
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
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?
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetType() == TYPE_FLYING && m_altitude > 0.0f )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( !m_physics->GetLand() ) return ERR_CONTINUE;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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?
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetLand() ) limit = 0.1f; // on the ground
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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?
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetType() == TYPE_FLYING && m_altitude > 0.0f )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( !m_physics->GetLand() ) return ERR_CONTINUE;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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?
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
angle = Math::NormAngle(m_object->GetAngleY(0));
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
m_bmFinalPos = m_object->GetPosition(0);
|
|
|
|
|
m_bmFinalDist = m_physics->GetLinLength(m_bmFinalMove);
|
|
|
|
|
m_bmTimeLimit = m_physics->GetLinTimeLength(fabs(m_bmFinalMove))*1.5f;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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
|
2012-09-11 21:11:34 +00:00
|
|
|
|
m_angle = Math::NormAngle(m_object->GetAngleY(0)+angle);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
m_phase = TGP_CRTURN;
|
|
|
|
|
//? m_phase = TGP_ADVANCE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( m_phase == TGP_CRTURN ) // turns after collision?
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
angle = Math::NormAngle(m_object->GetAngleY(0));
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
m_angle = Math::NormAngle(m_object->GetAngleY(0)+angle);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
m_phase = TGP_CLTURN;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( m_phase == TGP_CLTURN ) // turns after collision?
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
angle = Math::NormAngle(m_object->GetAngleY(0));
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
dist = Math::Distance(m_bmFinalPos, m_object->GetPosition(0));
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2013-02-16 21:37:43 +00:00
|
|
|
|
CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
|
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
|
pBest = 0;
|
|
|
|
|
min = 1000000.0f;
|
|
|
|
|
for ( i=0 ; i<1000000 ; i++ )
|
|
|
|
|
{
|
2013-02-16 21:37:43 +00:00
|
|
|
|
pObj = static_cast<CObject*>(iMan->SearchInstance(CLASS_OBJECT, i));
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( pObj == 0 ) break;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( !pObj->GetActif() ) continue;
|
|
|
|
|
if ( pObj->GetTruck() != 0 ) continue; // object transtorted?
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
oPos = pObj->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
type = m_object->GetType();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( type == OBJECT_BEE ||
|
|
|
|
|
type == OBJECT_WORM )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
pos = pObj->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
return false; // single approach
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
type = pObj->GetType();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
pos = m_object->GetPosition(0);
|
|
|
|
|
goal = pObj->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
dist = Math::Distance(goal, pos);
|
|
|
|
|
pos = (pos-goal)*(TAKE_DIST+distance)/dist + goal;
|
|
|
|
|
return true; // approach from all sites
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( type == OBJECT_BASE )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
pos = m_object->GetPosition(0);
|
|
|
|
|
goal = pObj->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
character = pObj->GetCharacter();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
pos = character->posPower;
|
|
|
|
|
pos.x -= TAKE_DIST+TAKE_DIST_OTHER+distance;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
mat = pObj->GetWorldMatrix(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
pos = Transform(*mat, pos);
|
|
|
|
|
return false; // single approach
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( GetHotPoint(pObj, goal, true, distance, suppl) )
|
|
|
|
|
{
|
|
|
|
|
pos = goal;
|
|
|
|
|
distance += suppl;
|
|
|
|
|
return false; // single approach
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
pos = pObj->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2013-02-16 21:37:43 +00:00
|
|
|
|
CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
|
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
|
for ( i=0 ; i<1000000 ; i++ )
|
|
|
|
|
{
|
2013-02-16 21:37:43 +00:00
|
|
|
|
pObj = static_cast<CObject*>(iMan->SearchInstance(CLASS_OBJECT, i));
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( pObj == 0 ) break;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( !pObj->GetActif() ) continue;
|
|
|
|
|
if ( pObj->GetTruck() != 0 ) continue; // object transported?
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
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;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
type = pObj->GetType();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
if ( type == OBJECT_DERRICK )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
mat = pObj->GetWorldMatrix(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
mat = pObj->GetWorldMatrix(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
mat = pObj->GetWorldMatrix(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
mat = pObj->GetWorldMatrix(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
mat = pObj->GetWorldMatrix(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
mat = pObj->GetWorldMatrix(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
mat = pObj->GetWorldMatrix(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
mat = pObj->GetWorldMatrix(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
mat = pObj->GetWorldMatrix(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
mat = pObj->GetWorldMatrix(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
mat = pObj->GetWorldMatrix(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( type == OBJECT_PARA && m_physics->GetType() == TYPE_FLYING )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
mat = pObj->GetWorldMatrix(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( !m_physics->GetLand() ) return false; // in flight?
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
m_object->GetCrashSphere(0, iPos, iRadius);
|
|
|
|
|
|
2013-02-16 21:37:43 +00:00
|
|
|
|
CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
|
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
|
min = 100000.0f;
|
|
|
|
|
bRadius = 0.0f;
|
|
|
|
|
for ( i=0 ; i<1000000 ; i++ )
|
|
|
|
|
{
|
2013-02-16 21:37:43 +00:00
|
|
|
|
pObj = static_cast<CObject*>(iMan->SearchInstance(CLASS_OBJECT, i));
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( pObj == 0 ) break;
|
|
|
|
|
|
|
|
|
|
if ( pObj == m_object ) continue;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( !pObj->GetActif() ) continue;
|
|
|
|
|
if ( pObj->GetTruck() != 0 ) continue; // object transported?
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
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;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( pObstacle->GetType() == OBJECT_FACTORY )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
dist = 16.0f;
|
|
|
|
|
dir = -1.0f;
|
|
|
|
|
m_bLeakRecede = true; // simply recoils
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pos = bPos;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
delay = m_physics->GetLinTimeLength(dist, dir);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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++ )
|
|
|
|
|
{
|
2013-02-16 21:37:43 +00:00
|
|
|
|
pObj = static_cast<CObject*>(iMan->SearchInstance(CLASS_OBJECT, i));
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( pObj == 0 ) break;
|
|
|
|
|
|
|
|
|
|
if ( pObj == m_object ) continue;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( pObj->GetTruck() != 0 ) continue;
|
2012-06-26 21:01:17 +00:00
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
oPos = pObj->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
dist = Math::Distance(oPos, m_goalObject);
|
|
|
|
|
if ( dist <= 1.0f ) continue;
|
|
|
|
|
|
|
|
|
|
pObj->GetGlobalSphere(oPos, oRadius);
|
2012-09-11 21:11:34 +00:00
|
|
|
|
oRadius += iRadius+m_physics->GetLinStopLength()*1.1f;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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!
|
2012-09-11 21:11:34 +00:00
|
|
|
|
iType = m_object->GetType();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( iType == OBJECT_WORM ) return;
|
|
|
|
|
|
|
|
|
|
m_object->GetCrashSphere(0, iPos, iRadius);
|
|
|
|
|
gDist = Math::Distance(iPos, m_goal);
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
add = m_physics->GetLinStopLength()*1.1f; // braking distance
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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?
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetLand() )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
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?
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetLand() )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-16 21:37:43 +00:00
|
|
|
|
CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
|
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
|
for ( i=0 ; i<1000000 ; i++ )
|
|
|
|
|
{
|
2013-02-16 21:37:43 +00:00
|
|
|
|
pObj = static_cast<CObject*>(iMan->SearchInstance(CLASS_OBJECT, i));
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( pObj == 0 ) break;
|
|
|
|
|
|
|
|
|
|
if ( pObj == m_object ) continue;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( pObj->GetTruck() != 0 ) continue;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
oType = pObj->GetType();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
2012-06-26 21:01:17 +00:00
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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 madebetween -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;
|
|
|
|
|
|
2013-02-16 21:37:43 +00:00
|
|
|
|
CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
|
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
|
for ( i=0 ; i<1000000 ; i++ )
|
|
|
|
|
{
|
2013-02-16 21:37:43 +00:00
|
|
|
|
pObj = static_cast<CObject*>(iMan->SearchInstance(CLASS_OBJECT, i));
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( pObj == 0 ) break;
|
|
|
|
|
|
|
|
|
|
if ( pObj == m_object ) continue;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( pObj->GetTruck() != 0 ) continue;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
oType = pObj->GetType();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
min = m_object->GetPosition(0);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
2012-06-26 21:01:17 +00:00
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
|
iLar = 0;
|
|
|
|
|
if ( i >= MAXPOINTS ) return ERR_GOTO_ITER; // too many recursions
|
2012-06-26 21:01:17 +00:00
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-06-26 21:01:17 +00:00
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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 )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
x = static_cast<int>((pos.x+1600.0f)/BM_DIM_STEP);
|
|
|
|
|
y = static_cast<int>((pos.z+1600.0f)/BM_DIM_STEP);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
BitmapSetDot(1, x, y); // puts the flag as the starting point
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
max = static_cast<int>(dist/step);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
x = static_cast<int>((pos.x+1600.0f)/BM_DIM_STEP);
|
|
|
|
|
y = static_cast<int>((pos.z+1600.0f)/BM_DIM_STEP);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2013-02-16 21:37:43 +00:00
|
|
|
|
CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
|
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
|
for ( i=0 ; i<1000000 ; i++ )
|
|
|
|
|
{
|
2013-02-16 21:37:43 +00:00
|
|
|
|
pObj = static_cast<CObject*>(iMan->SearchInstance(CLASS_OBJECT, i));
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( pObj == 0 ) break;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
type = pObj->GetType();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
if ( pObj == m_object ) continue;
|
|
|
|
|
if ( pObj == m_bmFretObject ) continue;
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( pObj->GetTruck() != 0 ) continue;
|
2012-06-26 21:01:17 +00:00
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
h = m_terrain->GetFloorLevel(pObj->GetPosition(0), false);
|
|
|
|
|
if ( m_physics->GetType() == TYPE_FLYING && m_altitude > 0.0f )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
h += m_altitude;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
j = 0;
|
|
|
|
|
while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
if ( m_physics->GetType() == TYPE_FLYING && m_altitude > 0.0f ) // flying?
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
minx = static_cast<int>((min.x+1600.0f)/BM_DIM_STEP);
|
|
|
|
|
miny = static_cast<int>((min.z+1600.0f)/BM_DIM_STEP);
|
|
|
|
|
maxx = static_cast<int>((max.x+1600.0f)/BM_DIM_STEP);
|
|
|
|
|
maxy = static_cast<int>((max.z+1600.0f)/BM_DIM_STEP);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
type = m_object->GetType();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2012-06-26 21:01:17 +00:00
|
|
|
|
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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?
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
h = m_terrain->GetFloorLevel(p, true);
|
|
|
|
|
if ( h >= m_terrain->GetFlyingMaxHeight()-5.0f )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
BitmapSetDot(0, x, y);
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( !bAcceptWater ) // not going underwater?
|
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
h = m_terrain->GetFloorLevel(p, true);
|
|
|
|
|
if ( h < m_water->GetLevel()-2.0f ) // under water (*)?
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
|
|
|
|
//? BitmapSetDot(0, x, y);
|
|
|
|
|
BitmapSetCircle(p, BM_DIM_STEP*1.0f);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
angle = m_terrain->GetFineSlope(p);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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();
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
m_bmSize = static_cast<int>(3200.0f/BM_DIM_STEP);
|
2012-12-28 12:37:08 +00:00
|
|
|
|
m_bmArray = new unsigned char[m_bmSize*m_bmSize/8*2];
|
2012-09-11 21:11:34 +00:00
|
|
|
|
memset(m_bmArray, 0, m_bmSize*m_bmSize/8*2);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
{
|
2012-12-28 12:37:08 +00:00
|
|
|
|
delete[] m_bmArray;
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
cx = static_cast<int>((pos.x+1600.0f)/BM_DIM_STEP);
|
|
|
|
|
cy = static_cast<int>((pos.z+1600.0f)/BM_DIM_STEP);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
r = radius/BM_DIM_STEP;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
for ( iy=cy-static_cast<int>(r) ; iy<=cy+static_cast<int>(r) ; iy++ )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
for ( ix=cx-static_cast<int>(r) ; ix<=cx+static_cast<int>(r) ; ix++ )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
d = Math::Point(static_cast<float>(ix-cx), static_cast<float>(iy-cy)).Length();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
if ( d > r ) continue;
|
|
|
|
|
BitmapSetDot(0, ix, iy);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Removes a circle in the bitmap.
|
2012-09-11 21:11:34 +00:00
|
|
|
|
//TODO this method is almost same as above one
|
2012-06-26 20:23:05 +00:00
|
|
|
|
void CTaskGoto::BitmapClearCircle(const Math::Vector &pos, float radius)
|
|
|
|
|
{
|
|
|
|
|
float d, r;
|
|
|
|
|
int cx, cy, ix, iy;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
cx = static_cast<int>((pos.x+1600.0f)/BM_DIM_STEP);
|
|
|
|
|
cy = static_cast<int>((pos.z+1600.0f)/BM_DIM_STEP);
|
2012-06-26 20:23:05 +00:00
|
|
|
|
r = radius/BM_DIM_STEP;
|
|
|
|
|
|
2012-09-11 21:11:34 +00:00
|
|
|
|
for ( iy=cy-static_cast<int>(r) ; iy<=cy+static_cast<int>(r) ; iy++ )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
for ( ix=cx-static_cast<int>(r) ; ix<=cx+static_cast<int>(r) ; ix++ )
|
2012-06-26 20:23:05 +00:00
|
|
|
|
{
|
2012-09-11 21:11:34 +00:00
|
|
|
|
d = Math::Point(static_cast<float>(ix-cx), static_cast<float>(iy-cy)).Length();
|
2012-06-26 20:23:05 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|