mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-15 08:34:40 +00:00
add a calibrateable mHeightTolerance
for players this defaults to 0.001, for wheeledvehicles, 2.0, and for flyingvehicles, 200 fix naveditor cript not looking up the object.datablock.aicontrollerdata fix AIWheeledVehicleControllerData not binding the relevant ::resolvespeed also the relevant ::resolvespeed now lowers the throttle post-turning add AIFlyingVehicleControllerData
This commit is contained in:
parent
fdb64b15a8
commit
6200a6f1fb
4 changed files with 205 additions and 55 deletions
|
|
@ -24,6 +24,7 @@
|
||||||
#include "T3D/player.h"
|
#include "T3D/player.h"
|
||||||
#include "T3D/rigidShape.h"
|
#include "T3D/rigidShape.h"
|
||||||
#include "T3D/vehicles/wheeledVehicle.h"
|
#include "T3D/vehicles/wheeledVehicle.h"
|
||||||
|
#include "T3D/vehicles/flyingVehicle.h"
|
||||||
|
|
||||||
|
|
||||||
IMPLEMENT_CONOBJECT(AIController);
|
IMPLEMENT_CONOBJECT(AIController);
|
||||||
|
|
@ -164,16 +165,13 @@ bool AIController::getAIMove(Move* movePtr)
|
||||||
{
|
{
|
||||||
if (getGoal()->getDist() > mControllerData->mFollowTolerance)
|
if (getGoal()->getDist() > mControllerData->mFollowTolerance)
|
||||||
{
|
{
|
||||||
F32 raylength = 2.0; //for vehicles
|
|
||||||
SceneObject* obj = getAIInfo()->mObj->getObjectMount();
|
SceneObject* obj = getAIInfo()->mObj->getObjectMount();
|
||||||
if (!obj)
|
if (!obj)
|
||||||
{
|
{
|
||||||
obj = getAIInfo()->mObj;
|
obj = getAIInfo()->mObj;
|
||||||
raylength = 0.001f; //for jumping
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RayInfo info;
|
RayInfo info;
|
||||||
if (obj->getContainer()->castRay(obj->getPosition(), obj->getPosition() - Point3F(0, 0, raylength), StaticShapeObjectType, &info))
|
if (obj->getContainer()->castRay(obj->getPosition(), obj->getPosition() - Point3F(0, 0, mControllerData->mHeightTolerance), StaticShapeObjectType, &info))
|
||||||
{
|
{
|
||||||
getNav()->repath();
|
getNav()->repath();
|
||||||
}
|
}
|
||||||
|
|
@ -399,9 +397,11 @@ void AIControllerData::resolveSpeed(AIController* obj, Point3F location, Move* m
|
||||||
if (mIsZero(xDiff))
|
if (mIsZero(xDiff))
|
||||||
movePtr->y = (location.y > obj->getNav()->getMoveDestination().y) ? -1.0f : 1.0f;
|
movePtr->y = (location.y > obj->getNav()->getMoveDestination().y) ? -1.0f : 1.0f;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
if (mIsZero(yDiff))
|
if (mIsZero(yDiff))
|
||||||
movePtr->x = (location.x > obj->getNav()->getMoveDestination().x) ? -1.0f : 1.0f;
|
movePtr->x = (location.x > obj->getNav()->getMoveDestination().x) ? -1.0f : 1.0f;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
if (mFabs(xDiff) > mFabs(yDiff))
|
if (mFabs(xDiff) > mFabs(yDiff))
|
||||||
{
|
{
|
||||||
F32 value = mFabs(yDiff / xDiff);
|
F32 value = mFabs(yDiff / xDiff);
|
||||||
|
|
@ -414,7 +414,8 @@ void AIControllerData::resolveSpeed(AIController* obj, Point3F location, Move* m
|
||||||
movePtr->x = (location.x > obj->getNav()->getMoveDestination().x) ? -value : value;
|
movePtr->x = (location.x > obj->getNav()->getMoveDestination().x) ? -value : value;
|
||||||
movePtr->y = (location.y > obj->getNav()->getMoveDestination().y) ? -1.0f : 1.0f;
|
movePtr->y = (location.y > obj->getNav()->getMoveDestination().y) ? -1.0f : 1.0f;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// Rotate the move into object space (this really only needs
|
// Rotate the move into object space (this really only needs
|
||||||
// a 2D matrix)
|
// a 2D matrix)
|
||||||
Point3F newMove;
|
Point3F newMove;
|
||||||
|
|
@ -484,13 +485,14 @@ void AIControllerData::resolveStuck(AIController* obj)
|
||||||
|
|
||||||
AIControllerData::AIControllerData()
|
AIControllerData::AIControllerData()
|
||||||
{
|
{
|
||||||
mMoveTolerance = 0.25;
|
mMoveTolerance = 0.25f;
|
||||||
mFollowTolerance = 1.0;
|
mFollowTolerance = 1.0f;
|
||||||
mAttackRadius = 2.0;
|
mAttackRadius = 2.0f;
|
||||||
mMoveStuckTolerance = 0.01f;
|
mMoveStuckTolerance = 0.01f;
|
||||||
mMoveStuckTestDelay = 30;
|
mMoveStuckTestDelay = 30;
|
||||||
mLinkTypes = LinkData(AllFlags);
|
mLinkTypes = LinkData(AllFlags);
|
||||||
mNavSize = AINavigation::Regular;
|
mNavSize = AINavigation::Regular;
|
||||||
|
mHeightTolerance = 0.001f;
|
||||||
|
|
||||||
mFlocking.mChance = 90;
|
mFlocking.mChance = 90;
|
||||||
mFlocking.mMin = 1.0f;
|
mFlocking.mMin = 1.0f;
|
||||||
|
|
@ -638,6 +640,8 @@ void AIPlayerControllerData::resolveTriggerState(AIController* obj, Move* movePt
|
||||||
#endif // TORQUE_NAVIGATION_ENABLED
|
#endif // TORQUE_NAVIGATION_ENABLED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
IMPLEMENT_CO_DATABLOCK_V1(AIWheeledVehicleControllerData);
|
IMPLEMENT_CO_DATABLOCK_V1(AIWheeledVehicleControllerData);
|
||||||
// Build a Triangle .. calculate angle of rotation required to meet target..
|
// Build a Triangle .. calculate angle of rotation required to meet target..
|
||||||
// man there has to be a better way! >:)
|
// man there has to be a better way! >:)
|
||||||
|
|
@ -772,57 +776,172 @@ void AIWheeledVehicleControllerData::resolveYaw(AIController* obj, Point3F locat
|
||||||
|
|
||||||
void AIWheeledVehicleControllerData::resolveSpeed(AIController* obj, Point3F location, Move* movePtr)
|
void AIWheeledVehicleControllerData::resolveSpeed(AIController* obj, Point3F location, Move* movePtr)
|
||||||
{
|
{
|
||||||
F32 xDiff = obj->getNav()->getMoveDestination().x - location.x;
|
WheeledVehicle* wvo = dynamic_cast<WheeledVehicle*>(obj->getAIInfo()->mObj.getPointer());
|
||||||
F32 yDiff = obj->getNav()->getMoveDestination().y - location.y;
|
if (!wvo)
|
||||||
Point3F rotation = obj->getAIInfo()->mObj->getTransform().toEuler();
|
|
||||||
|
|
||||||
Point2F movTarg;
|
|
||||||
|
|
||||||
// Build move direction in world space
|
|
||||||
if (mIsZero(xDiff))
|
|
||||||
movTarg.y = (location.y > obj->getNav()->getMoveDestination().y) ? -1.0f : 1.0f;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if (mIsZero(yDiff))
|
//cover the case of a connection controling an object in turn controlling another
|
||||||
movTarg.x = (location.x > obj->getNav()->getMoveDestination().x) ? -1.0f : 1.0f;
|
if (obj->getAIInfo()->mObj->getObjectMount())
|
||||||
|
wvo = dynamic_cast<WheeledVehicle*>(obj->getAIInfo()->mObj->getObjectMount());
|
||||||
|
}
|
||||||
|
if (!wvo) return;//not a WheeledVehicle
|
||||||
|
|
||||||
|
Parent::resolveSpeed(obj, location, movePtr);
|
||||||
|
|
||||||
|
VehicleData* db = static_cast<VehicleData *>(wvo->getDataBlock());
|
||||||
|
movePtr->x = 0;// 1.1 - wvo->getSteering().x / db->maxSteeringAngle;
|
||||||
|
movePtr->y *= 1.1 - wvo->getSteering().y / db->maxSteeringAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
IMPLEMENT_CO_DATABLOCK_V1(AIFlyingVehicleControllerData);
|
||||||
|
// Build a Triangle .. calculate angle of rotation required to meet target..
|
||||||
|
// man there has to be a better way! >:)
|
||||||
|
F32 AIFlyingVehicleControllerData::getSteeringAngle(AIController* obj, Point3F location)
|
||||||
|
{
|
||||||
|
FlyingVehicle* wvo = dynamic_cast<FlyingVehicle*>(obj->getAIInfo()->mObj.getPointer());
|
||||||
|
if (!wvo)
|
||||||
|
{
|
||||||
|
//cover the case of a connection controling an object in turn controlling another
|
||||||
|
if (obj->getAIInfo()->mObj->getObjectMount())
|
||||||
|
wvo = dynamic_cast<FlyingVehicle*>(obj->getAIInfo()->mObj->getObjectMount());
|
||||||
|
}
|
||||||
|
if (!wvo) return 0;//not a FlyingVehicle
|
||||||
|
|
||||||
|
DrivingState steerState = SteerNull;
|
||||||
|
|
||||||
|
// What is our target
|
||||||
|
Point3F desired;
|
||||||
|
desired = obj->getNav()->getMoveDestination();
|
||||||
|
|
||||||
|
MatrixF mat = wvo->getTransform();
|
||||||
|
Point3F center, front;
|
||||||
|
Point3F wFront;
|
||||||
|
Box3F box = wvo->getObjBox();
|
||||||
|
|
||||||
|
box.getCenter(¢er);
|
||||||
|
front = center;
|
||||||
|
front.y = box.maxExtents.y; // should be true for all these objects
|
||||||
|
|
||||||
|
obj->getAIInfo()->mObj->getWorldBox().getCenter(¢er);
|
||||||
|
front = center + front;
|
||||||
|
|
||||||
|
Point3F objFront = front;
|
||||||
|
Point3F offset = front - center;
|
||||||
|
EulerF rot;
|
||||||
|
rot = mat.toEuler();
|
||||||
|
MatrixF transform(rot);
|
||||||
|
transform.mulV(offset, &wFront);
|
||||||
|
front = wFront + center;
|
||||||
|
|
||||||
|
Point3F ftoc;
|
||||||
|
ftoc.x = mFabs(front.x - center.x);
|
||||||
|
ftoc.y = mFabs(front.y - center.y);
|
||||||
|
ftoc.z = mFabs(front.z - center.z);
|
||||||
|
F32 fToc = mSqrt((ftoc.x * ftoc.x) + (ftoc.y * ftoc.y));
|
||||||
|
|
||||||
|
Point3F ltoc;
|
||||||
|
ltoc.x = mFabs(desired.x - center.x);
|
||||||
|
ltoc.y = mFabs(desired.y - center.y);
|
||||||
|
ltoc.z = mFabs(desired.z - center.z);
|
||||||
|
F32 lToc = mSqrt((ltoc.x * ltoc.x) + (ltoc.y * ltoc.y));
|
||||||
|
|
||||||
|
Point3F ftol;
|
||||||
|
ftol.x = mFabs(front.x - desired.x);
|
||||||
|
ftol.y = mFabs(front.y - desired.y);
|
||||||
|
ftol.z = mFabs(front.z - desired.z);
|
||||||
|
F32 fTol = mSqrt((ftol.x * ftol.x) + (ftol.y * ftol.y));
|
||||||
|
|
||||||
|
F32 myAngle = mAcos(((lToc * lToc) + (fToc * fToc) - (fTol * fTol)) / (2 * lToc * fToc));
|
||||||
|
|
||||||
|
F32 finalYaw = mRadToDeg(myAngle);
|
||||||
|
|
||||||
|
F32 maxSteeringAngle = 0;
|
||||||
|
|
||||||
|
VehicleData* vd = (VehicleData*)(wvo->getDataBlock());
|
||||||
|
maxSteeringAngle = vd->maxSteeringAngle;
|
||||||
|
|
||||||
|
Point2F steering = wvo->getSteering();
|
||||||
|
if (finalYaw < 5 && steering.x != 0.0f)
|
||||||
|
steerState = Straight;
|
||||||
|
else if (finalYaw < 5)
|
||||||
|
steerState = SteerNull;
|
||||||
|
else
|
||||||
|
{// Quickly Hack out left or right turn info
|
||||||
|
Point3F rotData = objFront - desired;
|
||||||
|
MatrixF leftM(-rot);
|
||||||
|
Point3F leftP;
|
||||||
|
leftM.mulV(rotData, &leftP);
|
||||||
|
leftP = leftP + desired;
|
||||||
|
|
||||||
|
if (leftP.x < desired.x)
|
||||||
|
steerState = Right;
|
||||||
else
|
else
|
||||||
{
|
steerState = Left;
|
||||||
if (mFabs(xDiff) > mFabs(yDiff))
|
|
||||||
{
|
|
||||||
F32 value = mFabs(yDiff / xDiff);
|
|
||||||
movTarg.y = (location.y > obj->getNav()->getMoveDestination().y) ? -value : value;
|
|
||||||
movTarg.x = (location.x > obj->getNav()->getMoveDestination().x) ? -1.0f : 1.0f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
F32 value = mFabs(xDiff / yDiff);
|
|
||||||
movTarg.x = (location.x > obj->getNav()->getMoveDestination().x) ? -value : value;
|
|
||||||
movTarg.y = (location.y > obj->getNav()->getMoveDestination().y) ? -1.0f : 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Rotate the move into object space (this really only needs
|
|
||||||
// a 2D matrix)
|
|
||||||
Point3F newMove;
|
|
||||||
MatrixF moveMatrix;
|
|
||||||
moveMatrix.set(EulerF(0.0f, 0.0f, -(rotation.z + movePtr->yaw)));
|
|
||||||
moveMatrix.mulV(Point3F(movTarg.x, movTarg.y, 0.0f), &newMove);
|
|
||||||
movTarg.y = newMove.y;
|
|
||||||
|
|
||||||
// Set Throttle. We'll slow down once we get close
|
F32 throttle = wvo->getThrottle();
|
||||||
// to try and stop on the spot...
|
if (throttle < 0.0f && steerState != Straight)
|
||||||
if (obj->mMovement.mMoveSlowdown)
|
|
||||||
{
|
{
|
||||||
F32 throttle = obj->mMovement.mMoveSpeed;
|
F32 reverseReduction = 0.25;
|
||||||
F32 dist = mSqrt(xDiff * xDiff + yDiff * yDiff);
|
steering.x = steering.x * reverseReduction * throttle;
|
||||||
F32 maxDist = mMoveTolerance * 2;
|
|
||||||
if (dist < maxDist)
|
|
||||||
throttle *= dist / maxDist;
|
|
||||||
movePtr->y *= throttle;
|
|
||||||
}
|
}
|
||||||
else
|
F32 turnAdjust = myAngle - steering.x;
|
||||||
|
|
||||||
|
F32 steer = 0;
|
||||||
|
switch (steerState)
|
||||||
{
|
{
|
||||||
movePtr->y *= obj->mMovement.mMoveSpeed;
|
case Left:
|
||||||
|
steer = myAngle < maxSteeringAngle ? -turnAdjust : -maxSteeringAngle - steering.x;
|
||||||
|
break;
|
||||||
|
case Right:
|
||||||
|
steer = myAngle < maxSteeringAngle ? turnAdjust : maxSteeringAngle - steering.x;
|
||||||
|
break;
|
||||||
|
case Straight:
|
||||||
|
steer = -steering.x;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Con::printf("AI Steering : %f", steer);
|
||||||
|
return steer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AIFlyingVehicleControllerData::resolveYaw(AIController* obj, Point3F location, Move* movePtr)
|
||||||
|
{
|
||||||
|
FlyingVehicle* wvo = dynamic_cast<FlyingVehicle*>(obj->getAIInfo()->mObj.getPointer());
|
||||||
|
if (!wvo)
|
||||||
|
{
|
||||||
|
//cover the case of a connection controling an object in turn controlling another
|
||||||
|
if (obj->getAIInfo()->mObj->getObjectMount())
|
||||||
|
wvo = dynamic_cast<FlyingVehicle*>(obj->getAIInfo()->mObj->getObjectMount());
|
||||||
}
|
}
|
||||||
|
if (!wvo) return;//not a FlyingVehicle
|
||||||
|
|
||||||
|
// Orient towards our destination.
|
||||||
|
if (obj->mMovement.mMoveState == AIController::ModeMove || obj->mMovement.mMoveState == AIController::ModeReverse) {
|
||||||
|
movePtr->yaw = getSteeringAngle(obj, location);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void AIFlyingVehicleControllerData::resolveSpeed(AIController* obj, Point3F location, Move* movePtr)
|
||||||
|
{
|
||||||
|
FlyingVehicle* wvo = dynamic_cast<FlyingVehicle*>(obj->getAIInfo()->mObj.getPointer());
|
||||||
|
if (!wvo)
|
||||||
|
{
|
||||||
|
//cover the case of a connection controling an object in turn controlling another
|
||||||
|
if (obj->getAIInfo()->mObj->getObjectMount())
|
||||||
|
wvo = dynamic_cast<FlyingVehicle*>(obj->getAIInfo()->mObj->getObjectMount());
|
||||||
|
}
|
||||||
|
if (!wvo) return;//not a FlyingVehicle
|
||||||
|
|
||||||
|
Parent::resolveSpeed(obj, location, movePtr);
|
||||||
|
|
||||||
|
VehicleData* db = static_cast<VehicleData*>(wvo->getDataBlock());
|
||||||
|
movePtr->x = 0;// 1.1 - wvo->getSteering().x / db->maxSteeringAngle;
|
||||||
|
movePtr->y *= 1.1 - wvo->getSteering().y / db->maxSteeringAngle;
|
||||||
}
|
}
|
||||||
#endif //_AICONTROLLER_H_
|
#endif //_AICONTROLLER_H_
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ public:
|
||||||
F32 mAttackRadius; // Distance to trigger weaponry calcs
|
F32 mAttackRadius; // Distance to trigger weaponry calcs
|
||||||
F32 mMoveStuckTolerance; // Distance tolerance on stuck check
|
F32 mMoveStuckTolerance; // Distance tolerance on stuck check
|
||||||
S32 mMoveStuckTestDelay; // The number of ticks to wait before checking if the AI is stuck
|
S32 mMoveStuckTestDelay; // The number of ticks to wait before checking if the AI is stuck
|
||||||
|
F32 mHeightTolerance; // how high above the navmesh are we before we stop trying to repath
|
||||||
struct Flocking {
|
struct Flocking {
|
||||||
U32 mChance; // chance of flocking
|
U32 mChance; // chance of flocking
|
||||||
F32 mMin; // min flocking separation distance
|
F32 mMin; // min flocking separation distance
|
||||||
|
|
@ -217,12 +217,37 @@ public:
|
||||||
AIWheeledVehicleControllerData()
|
AIWheeledVehicleControllerData()
|
||||||
{
|
{
|
||||||
resolveYawPtr.bind(this, &AIWheeledVehicleControllerData::resolveYaw);
|
resolveYawPtr.bind(this, &AIWheeledVehicleControllerData::resolveYaw);
|
||||||
resolveSpeedPtr.bind(this, &AIControllerData::resolveSpeed);
|
resolveSpeedPtr.bind(this, &AIWheeledVehicleControllerData::resolveSpeed);
|
||||||
|
mHeightTolerance = 2.0f;
|
||||||
}
|
}
|
||||||
F32 getSteeringAngle(AIController* obj, Point3F location);
|
F32 getSteeringAngle(AIController* obj, Point3F location);
|
||||||
void resolveYaw(AIController* obj, Point3F location, Move* movePtr);
|
void resolveYaw(AIController* obj, Point3F location, Move* movePtr);
|
||||||
void resolveSpeed(AIController* obj, Point3F location, Move* movePtr);
|
void resolveSpeed(AIController* obj, Point3F location, Move* movePtr);
|
||||||
DECLARE_CONOBJECT(AIWheeledVehicleControllerData);
|
DECLARE_CONOBJECT(AIWheeledVehicleControllerData);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AIFlyingVehicleControllerData : public AIControllerData
|
||||||
|
{
|
||||||
|
typedef AIControllerData Parent;
|
||||||
|
|
||||||
|
enum DrivingState {
|
||||||
|
SteerNull,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Straight
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
AIFlyingVehicleControllerData()
|
||||||
|
{
|
||||||
|
resolveYawPtr.bind(this, &AIFlyingVehicleControllerData::resolveYaw);
|
||||||
|
resolveSpeedPtr.bind(this, &AIFlyingVehicleControllerData::resolveSpeed);
|
||||||
|
mHeightTolerance = 200.0f;
|
||||||
|
}
|
||||||
|
F32 getSteeringAngle(AIController* obj, Point3F location);
|
||||||
|
void resolveYaw(AIController* obj, Point3F location, Move* movePtr);
|
||||||
|
void resolveSpeed(AIController* obj, Point3F location, Move* movePtr);
|
||||||
|
DECLARE_CONOBJECT(AIFlyingVehicleControllerData);
|
||||||
|
};
|
||||||
#endif // TORQUE_NAVIGATION_ENABLED
|
#endif // TORQUE_NAVIGATION_ENABLED
|
||||||
#endif //_AICONTROLLER_H_
|
#endif //_AICONTROLLER_H_
|
||||||
|
|
|
||||||
|
|
@ -179,3 +179,9 @@ datablock AIWheeledVehicleControllerData( aiCarControl )
|
||||||
{
|
{
|
||||||
moveTolerance = 1.0; followTolerance = 2.0; mAttackRadius = 5.0;
|
moveTolerance = 1.0; followTolerance = 2.0; mAttackRadius = 5.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
datablock AIFlyingVehicleControllerData( aiPlaneControl )
|
||||||
|
{
|
||||||
|
moveTolerance = 2.0; followTolerance = 5.0; mAttackRadius = 10.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -461,7 +461,7 @@ function NavEditorGui::onPlayerSelected(%this, %flags)
|
||||||
{
|
{
|
||||||
if (!isObject(%this.getPlayer().aiController) && (!(%this.getPlayer().isMemberOfClass("AIPlayer"))))
|
if (!isObject(%this.getPlayer().aiController) && (!(%this.getPlayer().isMemberOfClass("AIPlayer"))))
|
||||||
{
|
{
|
||||||
%this.getPlayer().aiController = new AIController(){ ControllerData = aiPlayerControl; };
|
%this.getPlayer().aiController = new AIController(){ ControllerData = %this.getPlayer().getDatablock().aiControllerData; };
|
||||||
%this.getPlayer().setAIController(%this.getPlayer().aiController);
|
%this.getPlayer().setAIController(%this.getPlayer().aiController);
|
||||||
}
|
}
|
||||||
NavMeshIgnore(%this.getPlayer(), true);
|
NavMeshIgnore(%this.getPlayer(), true);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue