Skip to content

Commit dd39107

Browse files
committed
Attempts to improve navigation
1 parent fdfaf70 commit dd39107

File tree

2 files changed

+50
-90
lines changed

2 files changed

+50
-90
lines changed

Data/Base.rte/AI/HumanBehaviors.lua

Lines changed: 47 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,114 +1353,74 @@ function HumanBehaviors.GoToWpt(AI, Owner, Abort)
13531353
if WptList then
13541354
local NextWptPos = WptList[1].Pos;
13551355
Dist = SceneMan:ShortestDistance(Owner.Pos, NextWptPos, false);
1356-
if Dist.Y < -25 and math.abs(Dist.X) < 30 then -- avoid any corners if the next waypoint is above us
1357-
local cornerType;
1358-
local CornerPos = Vector(NextWptPos.X, NextWptPos.Y);
1359-
if Owner.Pos.X > CornerPos.X then
1360-
CornerPos = CornerPos + Vector(25, -40);
1361-
cornerType = "right";
1362-
else
1363-
CornerPos = CornerPos + Vector(-25, -40);
1364-
cornerType = "left";
1365-
end
1366-
1356+
Waypoint = table.remove(WptList, 1);
1357+
if Waypoint.Type ~= "air" then
13671358
local Free = Vector();
1368-
Dist = SceneMan:ShortestDistance(NextWptPos, CornerPos, false);
1369-
-- make sure the corner waypoint is not inside terrain
1370-
local pixels = SceneMan:CastObstacleRay(NextWptPos, Dist, Vector(), Free, Owner.ID, Owner.IgnoresWhichTeam, rte.grassID, 3);
1371-
if pixels == 0 then
1372-
break; -- the waypoint is inside terrain, plot a new path
1373-
elseif pixels > 0 then
1374-
CornerPos = (NextWptPos + Free) / 2; -- compensate for obstacles
1375-
end
1376-
1377-
-- check if we have LOS
1378-
Dist = SceneMan:ShortestDistance(Owner.Pos, CornerPos, false);
1379-
if 0 <= SceneMan:CastObstacleRay(Owner.Pos, Dist, Vector(), Vector(), Owner.ID, Owner.IgnoresWhichTeam, rte.grassID, 2) then
1380-
-- CornerPos is blocked
1381-
CornerPos.X = Owner.Pos.X; -- move CornerPos straight above us
1382-
cornerType = "air";
1383-
end
1384-
1385-
Waypoint = {Pos=CornerPos, Type=cornerType};
1386-
if WptList[2] and not WptList[1].Type then -- remove the waypoint after the corner if possible
1387-
table.remove(WptList, 1);
1388-
Owner:RemoveMovePathBeginning(); -- clean up the graphical representation of the path
1389-
end
13901359

1391-
if not Owner.MOMoveTarget then
1392-
Owner:AddToMovePathBeginning(Waypoint.Pos);
1393-
end
1394-
else
1395-
Waypoint = table.remove(WptList, 1);
1396-
if Waypoint.Type ~= "air" then
1397-
local Free = Vector();
1398-
1399-
-- only if we have a digging tool
1400-
if Waypoint.Type ~= "drop" and Owner:HasObjectInGroup("Tools - Diggers") then
1401-
local PathSegRay = SceneMan:ShortestDistance(PrevWptPos, Waypoint.Pos, false); -- detect material blocking the path and start digging through it
1402-
if AI.teamBlockState ~= Actor.BLOCKED and SceneMan:CastStrengthRay(PrevWptPos, PathSegRay, 4, Free, 2, rte.doorID, true) then
1403-
if SceneMan:ShortestDistance(Owner.Pos, Free, false):MagnitudeIsLessThan(Owner.Height*0.4) then -- check that we're close enough to start digging
1404-
digState = AHuman.STARTDIG;
1405-
AI.deviceState = AHuman.DIGGING;
1406-
obstacleState = Actor.DIGPAUSING;
1407-
nextLatMove = Actor.LAT_STILL;
1408-
sweepRange = math.min(math.pi*0.2, Owner.AimRange);
1409-
StuckTimer:SetSimTimeLimitMS(6000);
1410-
AI.Ctrl.AnalogAim = SceneMan:ShortestDistance(Owner.Pos, Waypoint.Pos, false).Normalized; -- aim in the direction of the next waypoint
1411-
else
1412-
digState = AHuman.NOTDIGGING;
1413-
obstacleState = Actor.PROCEEDING;
1414-
end
1415-
1416-
local _ai, _ownr, _abrt = coroutine.yield(); -- wait until next frame
1417-
if _abrt then return true end
1360+
-- only if we have a digging tool
1361+
if Waypoint.Type ~= "drop" and Owner:HasObjectInGroup("Tools - Diggers") then
1362+
local PathSegRay = SceneMan:ShortestDistance(PrevWptPos, Waypoint.Pos, false); -- detect material blocking the path and start digging through it
1363+
if AI.teamBlockState ~= Actor.BLOCKED and SceneMan:CastStrengthRay(PrevWptPos, PathSegRay, 4, Free, 2, rte.doorID, true) then
1364+
if SceneMan:ShortestDistance(Owner.Pos, Free, false):MagnitudeIsLessThan(Owner.Height*0.4) then -- check that we're close enough to start digging
1365+
digState = AHuman.STARTDIG;
1366+
AI.deviceState = AHuman.DIGGING;
1367+
obstacleState = Actor.DIGPAUSING;
1368+
nextLatMove = Actor.LAT_STILL;
1369+
sweepRange = math.min(math.pi*0.2, Owner.AimRange);
1370+
StuckTimer:SetSimTimeLimitMS(6000);
1371+
AI.Ctrl.AnalogAim = SceneMan:ShortestDistance(Owner.Pos, Waypoint.Pos, false).Normalized; -- aim in the direction of the next waypoint
14181372
else
14191373
digState = AHuman.NOTDIGGING;
14201374
obstacleState = Actor.PROCEEDING;
1421-
StuckTimer:SetSimTimeLimitMS(1000);
14221375
end
1423-
end
14241376

1425-
if digState == AHuman.NOTDIGGING and AI.deviceState ~= AHuman.DIGGING then
1426-
-- if our path isn't blocked enough to dig, but the headroom is too little, start crawling to get through
1427-
local heading = SceneMan:ShortestDistance(Owner.Pos, Waypoint.Pos, false):SetMagnitude(Owner.Height*0.5);
1377+
local _ai, _ownr, _abrt = coroutine.yield(); -- wait until next frame
1378+
if _abrt then return true end
1379+
else
1380+
digState = AHuman.NOTDIGGING;
1381+
obstacleState = Actor.PROCEEDING;
1382+
StuckTimer:SetSimTimeLimitMS(1000);
1383+
end
1384+
end
14281385

1429-
-- This gets the angle of the heading vector relative to flat (i.e, straight along the X axis)
1430-
-- This gives a range of [0, 90]
1431-
-- 0 is pointing straight left/right, and 90 is pointing straight up/down.
1432-
local angleRadians = math.abs(math.atan2(-(heading.X * heading.Y), heading.X * heading.X));
1433-
local angleDegrees = angleRadians * (180 / math.pi);
1386+
if digState == AHuman.NOTDIGGING and AI.deviceState ~= AHuman.DIGGING then
1387+
-- if our path isn't blocked enough to dig, but the headroom is too little, start crawling to get through
1388+
local heading = SceneMan:ShortestDistance(Owner.Pos, Waypoint.Pos, false):SetMagnitude(Owner.Height*0.5);
14341389

1435-
-- We only crawl it it's quite flat, otherwise climb
1436-
local crawlThresholdDegrees = 30;
1437-
if angleDegrees <= crawlThresholdDegrees and Owner.Head and Owner.Head:IsAttached() then
1438-
local topHeadPos = Owner.Head.Pos - Vector(0, Owner.Head.Radius*0.7);
1390+
-- This gets the angle of the heading vector relative to flat (i.e, straight along the X axis)
1391+
-- This gives a range of [0, 90]
1392+
-- 0 is pointing straight left/right, and 90 is pointing straight up/down.
1393+
local angleRadians = math.abs(math.atan2(-(heading.X * heading.Y), heading.X * heading.X));
1394+
local angleDegrees = angleRadians * (180 / math.pi);
14391395

1440-
-- first check up to the top of the head, and then from there forward
1441-
if SceneMan:CastStrengthRay(Owner.Pos, topHeadPos - Owner.Pos, 5, Free, 4, rte.doorID, true) or SceneMan:CastStrengthRay(topHeadPos, heading, 5, Free, 4, rte.doorID, true) then
1442-
AI.proneState = AHuman.PRONE;
1443-
else
1444-
AI.proneState = AHuman.NOTPRONE;
1445-
end
1396+
-- We only crawl it it's quite flat, otherwise climb
1397+
local crawlThresholdDegrees = 30;
1398+
if angleDegrees <= crawlThresholdDegrees and Owner.Head and Owner.Head:IsAttached() then
1399+
local topHeadPos = Owner.Head.Pos - Vector(0, Owner.Head.Radius*0.7);
14461400

1447-
local _ai, _ownr, _abrt = coroutine.yield(); -- wait until next frame
1448-
if _abrt then return true end
1401+
-- first check up to the top of the head, and then from there forward
1402+
if SceneMan:CastStrengthRay(Owner.Pos, topHeadPos - Owner.Pos, 5, Free, 4, rte.doorID, true) or SceneMan:CastStrengthRay(topHeadPos, heading, 5, Free, 4, rte.doorID, true) then
1403+
AI.proneState = AHuman.PRONE;
14491404
else
14501405
AI.proneState = AHuman.NOTPRONE;
14511406
end
1407+
1408+
local _ai, _ownr, _abrt = coroutine.yield(); -- wait until next frame
1409+
if _abrt then return true end
1410+
else
1411+
AI.proneState = AHuman.NOTPRONE;
14521412
end
14531413
end
1414+
end
14541415

1455-
if not WptList[1] then
1456-
WptList = nil; -- update the path
1457-
end
1416+
if not WptList[1] then
1417+
WptList = nil; -- update the path
14581418
end
14591419

14601420
if not Waypoint.Type then
14611421
ArrivedTimer:SetSimTimeLimitMS(100);
14621422
elseif Waypoint.Type == "last" then
1463-
ArrivedTimer:SetSimTimeLimitMS(600);
1423+
ArrivedTimer:SetSimTimeLimitMS(300);
14641424
else -- air or corner wpt
14651425
ArrivedTimer:SetSimTimeLimitMS(0);
14661426
end
@@ -1743,7 +1703,7 @@ function HumanBehaviors.GoToWpt(AI, Owner, Abort)
17431703
if Owner.Jetpack and Owner.Head and Owner.Head:IsAttached() then
17441704
if Owner.Jetpack.JetTimeLeft < AI.minBurstTime then
17451705
AI.jump = false; -- not enough fuel left, no point in jumping yet
1746-
if not AI.flying or Owner.Vel.Y > 1 then
1706+
if not AI.flying or Owner.Vel.Y > 4 then
17471707
AI.refuel = true;
17481708
end
17491709
else

Source/Entities/AHuman.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,9 @@ float AHuman::EstimateJumpHeight() const {
956956
}
957957
} while (currentVelocity.GetY() < 0.0F);
958958

959-
return totalHeight * -1.0F * c_MPP;
959+
float finalCalculatedHeight = totalHeight * -1.0F * c_MPP;
960+
float finalHeightMultipler = 0.8f; // Make us think we can do a little less because AI path following is shit
961+
return finalCalculatedHeight * finalHeightMultipler;
960962
}
961963

962964
bool AHuman::EquipShield() {
@@ -2545,7 +2547,6 @@ void AHuman::DrawHUD(BITMAP* pTargetBitmap, const Vector& targetPos, int whichSc
25452547
return;
25462548
}
25472549

2548-
#ifdef DEBUG_BUILD
25492550
// Limbpath debug drawing
25502551
m_Paths[FGROUND][WALK].Draw(pTargetBitmap, targetPos, 122);
25512552
m_Paths[FGROUND][CRAWL].Draw(pTargetBitmap, targetPos, 122);
@@ -2575,7 +2576,6 @@ void AHuman::DrawHUD(BITMAP* pTargetBitmap, const Vector& targetPos, int whichSc
25752576
// Radius
25762577
// waypoint = m_Pos - targetPos;
25772578
// circle(pTargetBitmap, waypoint.m_X, waypoint.m_Y, m_MoveProximityLimit, g_RedColor);
2578-
#endif
25792579

25802580
// Player AI drawing
25812581

0 commit comments

Comments
 (0)