mirror of
https://github.com/Ragora/T2-DXAI.git
synced 2026-01-19 18:14:45 +00:00
Mathematical optimizations.
This commit is contained in:
parent
3058d538f8
commit
274d858679
|
|
@ -4,7 +4,7 @@
|
|||
// https://github.com/Ragora/T2-DXAI.git
|
||||
//
|
||||
// Copyright (c) 2015 Robert MacGregor
|
||||
// This software is licensed under the MIT license.
|
||||
// This software is licensed under the MIT license.
|
||||
// Refer to LICENSE.txt for more information.
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -12,10 +12,10 @@ function sameSide(%p1, %p2, %a, %b)
|
|||
{
|
||||
%cp1 = vectorCross(vectorSub(%b, %a), vectorSub(%p1, %a));
|
||||
%cp2 = vectorCross(vectorSub(%b, %a), vectorSub(%p2, %a));
|
||||
|
||||
|
||||
if (vectorDot(%cp1, %cp2) >= 0)
|
||||
return true;
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -26,17 +26,23 @@ function sameSide(%p1, %p2, %a, %b)
|
|||
// Param %a: One point of the triangle.
|
||||
// Param %b: One point of the triangle.
|
||||
// Param %c: One point of the triangle.
|
||||
// Return: A boolean representing whether or not the given point resides inside of the
|
||||
// Return: A boolean representing whether or not the given point resides inside of the
|
||||
// triangle.
|
||||
//------------------------------------------------------------------------------------------
|
||||
function pointInTriangle(%point, %a, %b, %c)
|
||||
{
|
||||
if (sameSide(%point, %a, %b, %c) && sameSide(%point, %b, %a, %c) && sameSide(%point, %c, %a, %b))
|
||||
return true;
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function Player::getXFacing(%this)
|
||||
{
|
||||
%forward = %this.getForwardVector();
|
||||
return mAtan(getWord(%forward, 1), getWord(%forward, 0));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
// Description: Calculates all the points of the given client's view cone given a maximum
|
||||
// view distance and returns them in a long string.
|
||||
|
|
@ -48,60 +54,30 @@ function pointInTriangle(%point, %a, %b, %c)
|
|||
// TODO: Return in a faster-to-read format: Could try as static GVar names
|
||||
// as the game's scripting environment for the gameplay is single threaded
|
||||
// and it probably does a hash to store the values.
|
||||
// FIXME: Mathematical optimizations, right now it's a hack because of no
|
||||
// reliable way of getting a player's X facing? Also, the horizontal view cones may
|
||||
// be all that's necessary. A player height check could be used to help alleviate
|
||||
// computational complexity.
|
||||
// FIXME: The horizontal view cones may be all that's necessary. A player
|
||||
// height check could be used to help alleviate computational complexity.
|
||||
//------------------------------------------------------------------------------------------
|
||||
function GameConnection::calculateViewCone(%this, %distance)
|
||||
{
|
||||
if (!isObject(%this.player) || %this.player.getState() !$= "Move")
|
||||
return -1;
|
||||
|
||||
//%xFacing = %this.player.getXFacing();
|
||||
%halfView = %this.fieldOfView / 2;
|
||||
|
||||
%xFacing = %this.player.getXFacing();
|
||||
%coneOrigin = %this.player.getMuzzlePoint($WeaponSlot);
|
||||
|
||||
%forwardVector = %this.player.getForwardVector();
|
||||
%sideVector = vectorCross("0 0 1", %forwardVector);
|
||||
|
||||
// Clockwise
|
||||
//%viewConeClockwise = %xFacing - %halfView;
|
||||
|
||||
// %viewConeClockwisePoint = mCos(%viewConeClockwise) SPC mSin(%viewConeClockwise) SPC "0";
|
||||
%viewConeClockwisePoint = mCos(-%halfView) SPC mSin(-%halfView) SPC "0";
|
||||
%viewConeClockwisePoint = vectorScale(%viewConeClockwisePoint, %this.viewDistance);
|
||||
//%viewConeClockwisePoint = vectorAdd(%viewConeClockwisePoint, %coneOrigin);
|
||||
|
||||
// Counter Clockwise
|
||||
//%viewConeCounterClockwise = %xFacing + %halfView;
|
||||
|
||||
//%viewConeCounterClockwisePoint = mCos(%viewConeCounterClockwise) SPC mSin(%viewConeCounterClockwise) SPC "0";
|
||||
%viewConeCounterClockwisePoint = mCos(%halfView) SPC mSin(%halfView) SPC "0";
|
||||
%viewConeCounterClockwisePoint = vectorScale(%viewConeCounterClockwisePoint, %this.viewDistance);
|
||||
//%viewConeCounterClockwisePoint = vectorAdd(%viewConeCounterClockwisePoint, %coneOrigin);
|
||||
|
||||
// Offsets
|
||||
%halfDistance = vectorDist(%viewConeCounterClockwisePoint, %viewConeClockwisePoint) / 2;
|
||||
|
||||
%viewConeCounterClockwisePoint = vectorScale(%sideVector, %halfDistance);
|
||||
%viewConeCounterClockwisePoint = vectorAdd(%coneOrigin, %viewConeCounterClockwisePoint);
|
||||
|
||||
%viewConeClockwisePoint = vectorScale(vectorScale(%sideVector, -1), %halfDistance);
|
||||
%viewConeClockwisePoint = vectorAdd(%coneOrigin, %viewConeClockwisePoint);
|
||||
|
||||
|
||||
%halfView = %this.fieldOfView / 2;
|
||||
%cos = mCos(%halfView);
|
||||
%sin = mSin(%halfView);
|
||||
|
||||
// Translate the horizontal points
|
||||
%viewConeClockwisePoint = vectorAdd(%coneOrigin, vectorScale(%cos SPC -%sin SPC "0", %this.viewDistance));
|
||||
%viewConeCounterClockwisePoint = vectorAdd(%coneOrigin, vectorScale(%cos SPC -%sin SPC "0", %this.viewDistance));
|
||||
|
||||
// Translate the upper and lower points
|
||||
%viewForwardPoint = vectorScale(%forwardVector, %this.viewDistance);
|
||||
|
||||
%viewConeUpperPoint = vectorAdd(vectorScale("0 0 1", %halfDistance), %viewForwardPoint);
|
||||
%viewConeUpperPoint = vectorAdd(%coneOrigin, %viewConeUpperPoint);
|
||||
|
||||
%viewConeLowerPoint = vectorAdd(vectorScale("0 0 -1", %halfDistance), %viewForwardPoint);
|
||||
%viewConeLowerPoint = vectorAdd(%coneOrigin, %viewConeLowerPoint);
|
||||
|
||||
// Now cast them forward
|
||||
%viewConeClockwisePoint = vectorAdd(%viewConeClockwisePoint, vectorScale(%this.player.getForwardVector(), %this.viewDistance));
|
||||
%viewConeCounterClockwisePoint = vectorAdd(%viewConeCounterClockwisePoint, vectorScale(%this.player.getForwardVector(), %this.viewDistance));
|
||||
%halfDistance = vectorDist(%viewConeCounterClockwisePoint, %viewConeClockwisePoint) / 2;
|
||||
|
||||
%viewConeUpperPoint = vectorAdd(%coneOrigin, "0 0" SPC %halfDistance);
|
||||
%viewConeLowerPoint = vectorAdd(%coneOrigin, "0 0" SPC -%halfDistance);
|
||||
|
||||
return %coneOrigin SPC %viewConeClockwisePoint SPC %viewConeCounterClockwisePoint SPC %viewConeUpperPoint SPC %viewConeLowerPoint;
|
||||
}
|
||||
|
|
@ -116,17 +92,17 @@ function SimSet::recurse(%this, %result)
|
|||
{
|
||||
if (!isObject(%result))
|
||||
%result = new SimSet();
|
||||
|
||||
|
||||
for (%iteration = 0; %iteration < %this.getCount(); %iteration++)
|
||||
{
|
||||
%current = %this.getObject(%iteration);
|
||||
|
||||
|
||||
if (%current.getClassName() $= "SimGroup" || %current.getClassName() $= "SimSet")
|
||||
%current.recurse(%result);
|
||||
else
|
||||
%result.add(%current);
|
||||
}
|
||||
|
||||
|
||||
return %result;
|
||||
}
|
||||
|
||||
|
|
@ -142,23 +118,23 @@ function GameConnection::getClosestInventory(%this)
|
|||
{
|
||||
if (!isObject(%this.player))
|
||||
return -1;
|
||||
|
||||
|
||||
%group = nameToID("Team" @ %this.team);
|
||||
if (!isObject(%group))
|
||||
return -1;
|
||||
|
||||
|
||||
%teamObjects = %group.recurse();
|
||||
|
||||
|
||||
%closestInventory = -1;
|
||||
%closestInventoryDistance = 9999;
|
||||
for (%iteration = 0; %iteration < %teamObjects.getCount(); %iteration++)
|
||||
{
|
||||
%current = %teamObjects.getObject(%iteration);
|
||||
|
||||
|
||||
if (%current.getClassName() $= "StaticShape" && %current.getDatablock().getName() $= "StationInventory")
|
||||
{
|
||||
%inventoryDistance = vectorDist(%current.getPosition(), %this.player.getPosition());
|
||||
|
||||
|
||||
if (%inventoryDistance < %closestInventoryDistance)
|
||||
{
|
||||
%closestInventoryDistance = %inventoryDistance;
|
||||
|
|
@ -166,9 +142,9 @@ function GameConnection::getClosestInventory(%this)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
%teamObjects.delete();
|
||||
|
||||
|
||||
return %closestInventory;
|
||||
}
|
||||
|
||||
|
|
@ -190,27 +166,27 @@ function GameConnection::getObjectsInViewcone(%this, %typeMask, %distance, %perf
|
|||
%this.fieldOfView = $DXAPI::Bot::DefaultFieldOfView;
|
||||
error("DXAI: Bad field of view value! (" @ %this @ ".fieldOfView > 3.14 || " @ %this @ ".fieldOfView < 0)");
|
||||
}
|
||||
|
||||
|
||||
if (%this.viewDistance <= 0)
|
||||
{
|
||||
%this.viewDistance = $DXAPI::Bot::DefaultViewDistance;
|
||||
error("DXAI: Bad view distance value! (" @ %this @ ".viewDistance <= 0)");
|
||||
}
|
||||
|
||||
|
||||
if (%distance $= "")
|
||||
%distance = %this.viewDistance;
|
||||
|
||||
|
||||
%viewCone = %this.calculateViewCone(%distance);
|
||||
|
||||
|
||||
// Extract the results: See TODO above ::calculateViewCone implementation
|
||||
%coneOrigin = getWords(%viewCone, 0, 2);
|
||||
%viewConeClockwiseVector = getWords(%viewCone, 3, 5);
|
||||
%viewConeCounterClockwiseVector = getWords(%viewCone, 6, 8);
|
||||
%viewConeUpperVector = getWords(%viewCone, 9, 11);
|
||||
%viewConeLowerVector = getWords(%viewCone, 12, 14);
|
||||
|
||||
|
||||
%result = new SimSet();
|
||||
|
||||
|
||||
// Doing a radius search should hopefully be faster than iterating over all objects in MissionCleanup.
|
||||
// Even if the game did that internally it's definitely faster than doing it in TS
|
||||
InitContainerRadiusSearch(%coneOrigin, %distance, %typeMask);
|
||||
|
|
@ -227,9 +203,9 @@ function GameConnection::getObjectsInViewcone(%this, %typeMask, %distance, %perf
|
|||
else
|
||||
{
|
||||
%rayCast = containerRayCast(%coneOrigin, %currentObject.getWorldBoxCenter(), $TypeMasks::AllObjectType, %this.player);
|
||||
|
||||
|
||||
%hitObject = getWord(%raycast, 0);
|
||||
|
||||
|
||||
// Since the engine doesn't do raycasts against projectiles & items correctly, we just check if the bot
|
||||
// hit -nothing- when doing the raycast rather than checking for a hit against the object
|
||||
%workaroundTypes = $TypeMasks::ProjectileObjectType | $TypeMasks::ItemObjectType;
|
||||
|
|
@ -238,14 +214,14 @@ function GameConnection::getObjectsInViewcone(%this, %typeMask, %distance, %perf
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return %result;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
// Description: Gets a random position somewhere within %distance of the given position.
|
||||
// Param %position: The position to generate a new position around.
|
||||
// Param %distance: The maximum distance the new position may be
|
||||
// Param %distance: The maximum distance the new position may be
|
||||
// Param %raycast: A boolean representing whether or not a raycast should be made from
|
||||
// %position to the randomly chosen location to stop on objects that may be in the way.
|
||||
// This is useful for grabbing positions indoors.
|
||||
|
|
@ -254,16 +230,16 @@ function getRandomPosition(%position, %distance, %raycast)
|
|||
{
|
||||
// First, we determine a random direction vector
|
||||
%direction = vectorNormalize(getRandom(0, 10000) SPC getRandom(0, 10000) SPC getRandom(0, 10000));
|
||||
|
||||
|
||||
// Return the scaled result
|
||||
%result = vectorAdd(%position, vectorScale(%direction, getRandom(0, %distance)));
|
||||
|
||||
|
||||
if (!%raycast)
|
||||
return %result;
|
||||
|
||||
|
||||
%rayCast = containerRayCast(%position, %result, $TypeMasks::AllObjectType, 0);
|
||||
%result = getWords(%raycast, 1, 3);
|
||||
|
||||
|
||||
return %result;
|
||||
}
|
||||
|
||||
|
|
@ -273,7 +249,7 @@ function getRandomPosition(%position, %distance, %raycast)
|
|||
// getRandomPosition with the raycast setting if all that is necessary is generating a
|
||||
// position relative to the terrain object.
|
||||
// Param %position: The position to generate a new position around.
|
||||
// Param %distance: The maximum distance the new position may be
|
||||
// Param %distance: The maximum distance the new position may be
|
||||
//------------------------------------------------------------------------------------------
|
||||
function getRandomPositionOnTerrain(%position, %distance)
|
||||
{
|
||||
|
|
@ -289,8 +265,8 @@ function getRandomPositionOnTerrain(%position, %distance)
|
|||
//------------------------------------------------------------------------------------------
|
||||
function vectorMult(%vec1, %vec2)
|
||||
{
|
||||
return (getWord(%vec1, 0) * getWord(%vec2, 0)) SPC
|
||||
(getWord(%vec1, 1) * getWord(%vec2, 1)) SPC
|
||||
return (getWord(%vec1, 0) * getWord(%vec2, 0)) SPC
|
||||
(getWord(%vec1, 1) * getWord(%vec2, 1)) SPC
|
||||
(getWord(%vec1, 2) * getWord(%vec2, 2));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue