2015-09-20 20:03:13 +02:00
|
|
|
/*
|
|
|
|
|
Copyright (C) 2014 Erik Ogenvik
|
|
|
|
|
|
|
|
|
|
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 2 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, write to the Free Software
|
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "Steering.h"
|
|
|
|
|
#include "Awareness.h"
|
|
|
|
|
|
|
|
|
|
#include "rulesets/MemEntity.h"
|
|
|
|
|
|
2015-09-26 20:37:31 +02:00
|
|
|
#include "common/debug.h"
|
|
|
|
|
|
2015-09-20 20:03:13 +02:00
|
|
|
#include <wfmath/point.h>
|
|
|
|
|
#include <wfmath/vector.h>
|
|
|
|
|
#include <wfmath/rotbox.h>
|
|
|
|
|
#include <wfmath/segment.h>
|
|
|
|
|
|
2015-09-26 20:37:31 +02:00
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
|
|
static const bool debug_flag = true;
|
|
|
|
|
|
2015-09-25 21:25:04 +02:00
|
|
|
Steering::Steering(MemEntity& avatar) :
|
2018-02-09 12:50:01 +01:00
|
|
|
mAwareness(nullptr),
|
|
|
|
|
mAvatar(avatar),
|
|
|
|
|
mDestinationEntityId(-1),
|
|
|
|
|
mDestinationRadius(1.0),
|
|
|
|
|
mSteeringEnabled(false),
|
|
|
|
|
mUpdateNeeded(false),
|
|
|
|
|
mPadding(16),
|
2018-02-11 23:22:20 +01:00
|
|
|
mMaxSpeed(5),
|
|
|
|
|
mDesiredSpeed(0.5),
|
2018-02-09 12:50:01 +01:00
|
|
|
mExpectingServerMovement(false),
|
|
|
|
|
mPathResult(0),
|
|
|
|
|
mAvatarHorizRadius(0.4)
|
2015-09-20 20:03:13 +02:00
|
|
|
{
|
2018-02-11 23:22:20 +01:00
|
|
|
auto speedGroundProp = avatar.getPropertyType<double>("speed-ground");
|
|
|
|
|
if (speedGroundProp) {
|
|
|
|
|
mMaxSpeed = speedGroundProp->data();
|
|
|
|
|
}
|
2016-03-20 18:25:17 +01:00
|
|
|
|
2015-09-20 20:03:13 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-25 21:25:04 +02:00
|
|
|
void Steering::setAwareness(Awareness* awareness)
|
2015-09-20 20:03:13 +02:00
|
|
|
{
|
2018-02-09 12:50:01 +01:00
|
|
|
auto& bbox = mAvatar.m_location.bBox();
|
2016-03-20 18:25:17 +01:00
|
|
|
if (bbox.isValid()) {
|
|
|
|
|
WFMath::CoordType squareHorizRadius = std::max(square(bbox.lowCorner().x()) +
|
2018-02-09 12:50:01 +01:00
|
|
|
square(bbox.lowCorner().z()),
|
2016-03-20 18:25:17 +01:00
|
|
|
square(bbox.highCorner().x()) +
|
2018-02-09 12:50:01 +01:00
|
|
|
square(bbox.highCorner().z()));
|
2016-03-20 18:25:17 +01:00
|
|
|
mAvatarHorizRadius = std::sqrt(squareHorizRadius);
|
|
|
|
|
}
|
2015-09-25 21:25:04 +02:00
|
|
|
mAwareness = awareness;
|
|
|
|
|
mTileListenerConnection.disconnect();
|
|
|
|
|
if (mAwareness) {
|
|
|
|
|
mTileListenerConnection = mAwareness->EventTileUpdated.connect(sigc::mem_fun(*this, &Steering::Awareness_TileUpdated));
|
2015-09-26 20:37:31 +02:00
|
|
|
setAwarenessArea();
|
2015-09-25 21:25:04 +02:00
|
|
|
}
|
2015-09-20 20:03:13 +02:00
|
|
|
}
|
|
|
|
|
|
2016-04-03 21:25:39 +02:00
|
|
|
void Steering::setDestination(int entityId, const WFMath::Point<3>& entityRelativePosition, float radius, double currentServerTimestamp)
|
2015-09-20 20:03:13 +02:00
|
|
|
{
|
2016-03-08 23:28:05 +01:00
|
|
|
if (mAwareness) {
|
2016-04-03 21:25:39 +02:00
|
|
|
mDestinationEntityId = entityId;
|
|
|
|
|
mEntityRelativeDestination = entityRelativePosition;
|
|
|
|
|
|
2016-03-08 23:28:05 +01:00
|
|
|
auto currentAvatarPos = getCurrentAvatarPosition(currentServerTimestamp);
|
2016-03-13 23:24:01 +01:00
|
|
|
|
2016-04-03 21:25:39 +02:00
|
|
|
WFMath::Point<3> finalPosition = entityRelativePosition;
|
|
|
|
|
updateDestination(currentServerTimestamp, entityId, finalPosition);
|
|
|
|
|
|
|
|
|
|
float distanceAvatarDestination = WFMath::Distance(currentAvatarPos, finalPosition);
|
2016-03-13 23:24:01 +01:00
|
|
|
|
|
|
|
|
float finalRadius = radius;
|
|
|
|
|
|
|
|
|
|
//Check if the destination is too far away. If so we should adjust it closer, and increase the radius.
|
|
|
|
|
//This depends on the AI updating the destination at regular intervals.
|
|
|
|
|
if (distanceAvatarDestination > (mAwareness->getTileSizeInMeters() * 10)) {
|
2016-04-03 21:25:39 +02:00
|
|
|
WFMath::Vector<3> vector = finalPosition - currentAvatarPos;
|
2016-03-13 23:24:01 +01:00
|
|
|
|
|
|
|
|
finalPosition = currentAvatarPos + (vector.normalize() * mAwareness->getTileSizeInMeters() * 10);
|
|
|
|
|
finalRadius = (radius * 10.f);
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-15 23:14:36 +01:00
|
|
|
//Only update if destination or radius has changed, or if the current tile of the avatar isn't known.
|
2016-03-13 23:24:01 +01:00
|
|
|
if (mViewDestination != finalPosition || mDestinationRadius != finalRadius
|
2018-02-09 12:50:01 +01:00
|
|
|
|| !mAwareness->isPositionAware(currentAvatarPos.x(), currentAvatarPos.z())) {
|
2016-03-13 23:24:01 +01:00
|
|
|
mViewDestination = finalPosition;
|
|
|
|
|
mDestinationRadius = finalRadius;
|
2016-03-08 23:28:05 +01:00
|
|
|
mUpdateNeeded = true;
|
|
|
|
|
|
|
|
|
|
setAwarenessArea();
|
|
|
|
|
mAvatarPositionLastUpdate = currentAvatarPos;
|
|
|
|
|
}
|
2015-09-26 20:37:31 +02:00
|
|
|
}
|
2015-09-25 21:25:04 +02:00
|
|
|
}
|
2015-09-20 20:03:13 +02:00
|
|
|
|
2015-09-25 21:25:04 +02:00
|
|
|
void Steering::setAwarenessArea()
|
|
|
|
|
{
|
|
|
|
|
if (mAwareness) {
|
2015-09-26 20:37:31 +02:00
|
|
|
if (mViewDestination.isValid()) {
|
2018-02-09 12:50:01 +01:00
|
|
|
WFMath::Point<2> destination2d(mViewDestination.x(), mViewDestination.z());
|
|
|
|
|
WFMath::Point<2> entityPosition2d(mAvatar.m_location.m_pos.x(), mAvatar.m_location.m_pos.z());
|
2015-09-20 20:03:13 +02:00
|
|
|
|
2015-09-26 20:37:31 +02:00
|
|
|
WFMath::Vector<2> direction(destination2d - entityPosition2d);
|
2018-02-09 12:50:01 +01:00
|
|
|
auto theta = std::atan2(direction.y(), direction.x()); // rotation about Y
|
2015-09-26 20:37:31 +02:00
|
|
|
WFMath::RotMatrix<2> rm;
|
|
|
|
|
rm.rotation(theta);
|
2015-09-20 20:03:13 +02:00
|
|
|
|
2015-09-26 20:37:31 +02:00
|
|
|
WFMath::Point<2> start = entityPosition2d;
|
|
|
|
|
start -= WFMath::Vector<2>(mPadding, mPadding);
|
2015-09-20 20:03:13 +02:00
|
|
|
|
2015-09-26 20:37:31 +02:00
|
|
|
WFMath::Vector<2> size(direction.mag() + (mPadding * 2), mPadding * 2);
|
2015-09-20 20:03:13 +02:00
|
|
|
|
2015-09-26 20:37:31 +02:00
|
|
|
WFMath::RotBox<2> area;
|
|
|
|
|
area.size() = size;
|
|
|
|
|
area.corner0() = start;
|
|
|
|
|
area.orientation() = WFMath::RotMatrix<2>().identity();
|
|
|
|
|
area.rotatePoint(rm, entityPosition2d);
|
2015-09-25 21:25:04 +02:00
|
|
|
|
2016-03-13 14:03:13 +01:00
|
|
|
mAwareness->setAwarenessArea(mAvatar.getId(), area, WFMath::Segment<2>(entityPosition2d, destination2d));
|
2015-09-26 20:37:31 +02:00
|
|
|
}
|
2015-09-25 21:25:04 +02:00
|
|
|
}
|
2015-09-20 20:03:13 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-13 14:03:13 +01:00
|
|
|
size_t Steering::unawareAreaCount() const {
|
|
|
|
|
if (mAwareness) {
|
|
|
|
|
return mAwareness->unawareTilesInArea(mAvatar.getId());
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2018-02-11 23:22:20 +01:00
|
|
|
void Steering::setDesiredSpeed(float desiredSpeed)
|
2015-09-20 20:03:13 +02:00
|
|
|
{
|
2018-02-11 23:22:20 +01:00
|
|
|
mDesiredSpeed = desiredSpeed;
|
2015-09-20 20:03:13 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-13 23:24:01 +01:00
|
|
|
int Steering::getPathResult() const
|
|
|
|
|
{
|
|
|
|
|
return mPathResult;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-03 21:25:39 +02:00
|
|
|
void Steering::updateDestination(double currentServerTimestamp, int entityId, WFMath::Point<3>& pos) {
|
2016-05-22 21:55:09 +02:00
|
|
|
if (mAwareness && mAvatar.m_location.m_loc) {
|
2016-04-03 21:25:39 +02:00
|
|
|
if (entityId != mAvatar.m_location.m_loc->getIntId()) {
|
|
|
|
|
mAwareness->projectPosition(mDestinationEntityId, pos, currentServerTimestamp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-13 23:24:01 +01:00
|
|
|
|
2016-03-08 23:28:05 +01:00
|
|
|
int Steering::updatePath(const WFMath::Point<3>& currentAvatarPosition)
|
2015-09-20 20:03:13 +02:00
|
|
|
{
|
2015-09-25 21:25:04 +02:00
|
|
|
mPath.clear();
|
|
|
|
|
if (!mAwareness) {
|
2016-03-13 23:24:01 +01:00
|
|
|
mPathResult = -7;
|
|
|
|
|
return mPathResult;
|
|
|
|
|
}
|
|
|
|
|
if (!mViewDestination.isValid()) {
|
|
|
|
|
mPathResult = -8;
|
|
|
|
|
return mPathResult;
|
2015-09-25 21:25:04 +02:00
|
|
|
}
|
2016-03-13 23:24:01 +01:00
|
|
|
mPathResult = mAwareness->findPath(currentAvatarPosition, mViewDestination, mDestinationRadius, mPath);
|
2016-03-08 23:28:05 +01:00
|
|
|
//debug_print("Updating path, size of new path: " << result << ". Pos: " << currentAvatarPosition);
|
2015-09-25 21:25:04 +02:00
|
|
|
EventPathUpdated();
|
|
|
|
|
mUpdateNeeded = false;
|
2016-03-13 23:24:01 +01:00
|
|
|
return mPathResult;
|
2016-03-08 23:28:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Steering::updatePath(double currentTimestamp)
|
|
|
|
|
{
|
|
|
|
|
if (!mAwareness) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
auto currentEntityPos = mAvatar.m_location.m_pos;
|
|
|
|
|
if (mAvatar.m_location.m_velocity.isValid()) {
|
|
|
|
|
currentEntityPos += (mAvatar.m_location.m_velocity * (currentTimestamp - mAvatar.m_location.timeStamp()));
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-03 21:25:39 +02:00
|
|
|
updateDestination(currentTimestamp, mDestinationEntityId, mViewDestination);
|
|
|
|
|
|
2016-03-08 23:28:05 +01:00
|
|
|
return updatePath(currentEntityPos);
|
2015-09-20 20:03:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Steering::requestUpdate()
|
|
|
|
|
{
|
2015-09-25 21:25:04 +02:00
|
|
|
mUpdateNeeded = true;
|
2015-09-20 20:03:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Steering::startSteering()
|
|
|
|
|
{
|
2015-09-25 21:25:04 +02:00
|
|
|
mSteeringEnabled = true;
|
|
|
|
|
mExpectingServerMovement = false;
|
2015-09-20 20:03:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Steering::stopSteering()
|
|
|
|
|
{
|
2015-09-25 21:25:04 +02:00
|
|
|
if (!mSteeringEnabled) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
mSteeringEnabled = false;
|
|
|
|
|
mExpectingServerMovement = false;
|
|
|
|
|
mLastSentVelocity = WFMath::Vector<2>();
|
2015-09-20 20:03:13 +02:00
|
|
|
|
2015-09-25 21:25:04 +02:00
|
|
|
//reset path
|
|
|
|
|
mPath = std::list<WFMath::Point<3>>();
|
2016-06-07 22:51:53 +02:00
|
|
|
mPathResult = 0;
|
2015-09-25 21:25:04 +02:00
|
|
|
EventPathUpdated();
|
2015-09-20 20:03:13 +02:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Steering::isEnabled() const
|
|
|
|
|
{
|
2015-09-25 21:25:04 +02:00
|
|
|
return mSteeringEnabled;
|
2015-09-20 20:03:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::list<WFMath::Point<3>>& Steering::getPath() const
|
|
|
|
|
{
|
2015-09-25 21:25:04 +02:00
|
|
|
return mPath;
|
2015-09-20 20:03:13 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-08 23:28:05 +01:00
|
|
|
WFMath::Point<3> Steering::getCurrentAvatarPosition(double currentTimestamp)
|
|
|
|
|
{
|
|
|
|
|
auto currentEntityPos = mAvatar.m_location.m_pos;
|
|
|
|
|
if (mAvatar.m_location.m_velocity.isValid()) {
|
|
|
|
|
currentEntityPos += (mAvatar.m_location.m_velocity * (currentTimestamp - mAvatar.m_location.timeStamp()));
|
|
|
|
|
}
|
|
|
|
|
return currentEntityPos;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-20 20:03:13 +02:00
|
|
|
SteeringResult Steering::update(double currentTimestamp)
|
|
|
|
|
{
|
2018-02-09 12:50:01 +01:00
|
|
|
SteeringResult result{};
|
2015-09-25 21:25:04 +02:00
|
|
|
if (mSteeringEnabled && mAwareness) {
|
2015-09-27 22:41:40 +02:00
|
|
|
|
2016-03-08 23:28:05 +01:00
|
|
|
auto currentEntityPos = getCurrentAvatarPosition(currentTimestamp);
|
2015-09-26 20:37:31 +02:00
|
|
|
|
2016-03-20 20:20:26 +01:00
|
|
|
//if (mUpdateNeeded) {
|
2016-04-03 21:25:39 +02:00
|
|
|
updateDestination(currentTimestamp, mDestinationEntityId, mViewDestination);
|
2015-09-26 20:37:31 +02:00
|
|
|
updatePath(currentEntityPos);
|
2016-03-20 20:20:26 +01:00
|
|
|
//}
|
2015-09-25 21:25:04 +02:00
|
|
|
if (!mPath.empty()) {
|
|
|
|
|
const auto& finalDestination = mPath.back();
|
2015-09-26 20:37:31 +02:00
|
|
|
|
2018-02-09 12:50:01 +01:00
|
|
|
const WFMath::Point<2> entityPosition(currentEntityPos.x(), currentEntityPos.z());
|
2015-09-25 21:25:04 +02:00
|
|
|
//First check if we've arrived at our actual destination.
|
2018-02-09 12:50:01 +01:00
|
|
|
if (WFMath::Distance(WFMath::Point<2>(finalDestination.x(), finalDestination.z()), entityPosition) < mAvatarHorizRadius) {
|
2015-09-25 21:25:04 +02:00
|
|
|
//We've arrived at our destination. If we're moving we should stop.
|
|
|
|
|
if (mLastSentVelocity != WFMath::Vector<2>::ZERO()) {
|
|
|
|
|
result.direction = WFMath::Vector<3>::ZERO();
|
2015-09-20 20:03:13 +02:00
|
|
|
mLastSentVelocity = WFMath::Vector<2>::ZERO();
|
|
|
|
|
mExpectingServerMovement = true;
|
2015-09-25 21:25:04 +02:00
|
|
|
}
|
|
|
|
|
stopSteering();
|
|
|
|
|
} else {
|
|
|
|
|
//We should send a move op if we're either not moving, or we've reached a waypoint, or we need to divert a lot.
|
|
|
|
|
|
2018-01-10 15:11:20 +01:00
|
|
|
WFMath::Point<2> nextWaypoint(mPath.front().x(), mPath.front().z());
|
2016-03-20 18:25:17 +01:00
|
|
|
while (WFMath::Distance(nextWaypoint, entityPosition) < mAvatarHorizRadius && mPath.size() > 1) {
|
2015-09-25 21:25:04 +02:00
|
|
|
mPath.pop_front();
|
2018-01-10 15:11:20 +01:00
|
|
|
nextWaypoint = WFMath::Point<2>(mPath.front().x(), mPath.front().z());
|
2015-09-25 21:25:04 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-27 22:41:40 +02:00
|
|
|
WFMath::Vector<2> distance = nextWaypoint - entityPosition;
|
|
|
|
|
WFMath::Vector<2> velocity = distance;
|
2015-09-25 21:25:04 +02:00
|
|
|
WFMath::Point<2> destination;
|
2018-02-11 23:22:20 +01:00
|
|
|
velocity = velocity.normalize() * mDesiredSpeed;
|
2015-09-25 21:25:04 +02:00
|
|
|
|
2018-02-11 23:22:20 +01:00
|
|
|
result.timeToNextWaypoint = distance.mag() / mMaxSpeed;
|
2015-09-27 22:41:40 +02:00
|
|
|
|
|
|
|
|
if (mPath.size() == 1) {
|
2015-09-25 21:25:04 +02:00
|
|
|
//if the next waypoint is the destination we should send a "move to position" update to the server, to make sure that we stop when we've arrived.
|
|
|
|
|
//otherwise, if there's too much lag, we might end up overshooting our destination and will have to double back
|
|
|
|
|
destination = nextWaypoint;
|
2015-09-27 22:41:40 +02:00
|
|
|
}
|
2015-09-25 21:25:04 +02:00
|
|
|
|
|
|
|
|
//Check if we need to divert in order to avoid colliding.
|
|
|
|
|
WFMath::Vector<2> newVelocity;
|
2018-02-11 23:22:20 +01:00
|
|
|
bool avoiding = mAwareness->avoidObstacles(mAvatar.getIntId(), entityPosition, velocity * mMaxSpeed, newVelocity, currentTimestamp);
|
2015-09-25 21:25:04 +02:00
|
|
|
if (avoiding) {
|
2018-02-11 23:22:20 +01:00
|
|
|
auto newMag = newVelocity.mag();
|
|
|
|
|
auto relativeMag = mMaxSpeed / newMag;
|
|
|
|
|
|
2015-09-25 21:25:04 +02:00
|
|
|
velocity = newVelocity;
|
|
|
|
|
velocity.normalize();
|
2018-02-11 23:22:20 +01:00
|
|
|
velocity *= relativeMag;
|
|
|
|
|
|
2016-03-11 23:12:26 +01:00
|
|
|
//Schedule a new steering op very soon
|
2016-03-12 23:38:45 +01:00
|
|
|
result.timeToNextWaypoint = 0.2f;
|
2015-09-25 21:25:04 +02:00
|
|
|
mUpdateNeeded = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool shouldSend = false;
|
|
|
|
|
if (velocity.isValid()) {
|
|
|
|
|
if (mLastSentVelocity.isValid()) {
|
|
|
|
|
//If the entity has stopped, and we're not waiting for confirmation to a movement request we've made, we need to start moving.
|
2015-09-26 20:37:31 +02:00
|
|
|
if (mAvatar.m_location.velocity() == WFMath::Vector<3>::ZERO() && !mExpectingServerMovement) {
|
2015-09-25 21:25:04 +02:00
|
|
|
shouldSend = true;
|
|
|
|
|
} else {
|
2018-02-09 12:50:01 +01:00
|
|
|
auto currentTheta = std::atan2(mLastSentVelocity.y(), mLastSentVelocity.x());
|
|
|
|
|
auto newTheta = std::atan2(velocity.y(), velocity.x());
|
2015-09-25 21:25:04 +02:00
|
|
|
|
|
|
|
|
//If we divert too much from where we need to go we must adjust.
|
|
|
|
|
if (std::abs(currentTheta - newTheta) > WFMath::numeric_constants<double>::pi() / 20) {
|
|
|
|
|
shouldSend = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
//If we've never sent a movement update before we should do that now.
|
|
|
|
|
shouldSend = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (shouldSend) {
|
|
|
|
|
//If we're moving to a certain destination and aren't avoiding anything we should tell the server to move to the destination.
|
|
|
|
|
if (destination.isValid() && !avoiding) {
|
2018-01-10 15:11:20 +01:00
|
|
|
result.destination = WFMath::Point<3>(destination.x(), mAvatar.m_location.m_pos.y(), destination.y());
|
2015-09-25 21:25:04 +02:00
|
|
|
}
|
2018-01-10 15:11:20 +01:00
|
|
|
result.direction = WFMath::Vector<3>(velocity.x(), 0, velocity.y());
|
2015-09-25 21:25:04 +02:00
|
|
|
mLastSentVelocity = velocity;
|
|
|
|
|
mExpectingServerMovement = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
//We are steering, but the path is empty, which means we can't find any path. If we're moving we should stop movement.
|
|
|
|
|
//But we won't stop steering; perhaps we'll find a path later.
|
|
|
|
|
if (mLastSentVelocity != WFMath::Vector<2>::ZERO()) {
|
|
|
|
|
result.direction = WFMath::Vector<3>::ZERO();
|
|
|
|
|
mLastSentVelocity = WFMath::Vector<2>::ZERO();
|
|
|
|
|
mExpectingServerMovement = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
2015-09-20 20:03:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Steering::Awareness_TileUpdated(int tx, int ty)
|
|
|
|
|
{
|
2015-09-25 21:25:04 +02:00
|
|
|
mUpdateNeeded = true;
|
2015-09-20 20:03:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Steering::getIsExpectingServerMovement() const
|
|
|
|
|
{
|
2015-09-25 21:25:04 +02:00
|
|
|
return mExpectingServerMovement;
|
2015-09-20 20:03:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Steering::setIsExpectingServerMovement(bool expected)
|
|
|
|
|
{
|
2015-09-25 21:25:04 +02:00
|
|
|
mExpectingServerMovement = expected;
|
2015-09-20 20:03:13 +02:00
|
|
|
}
|
|
|
|
|
|