@@ -1007,7 +1007,7 @@ function HumanBehaviors.WeaponSearch(AI, Owner, Abort)
1007
1007
end
1008
1008
searchesRemaining = searchesRemaining - 1 ;
1009
1009
end ,
1010
- Owner .Pos , device .Pos , false , Owner .DigStrength , Owner .Team
1010
+ Owner .Pos , device .Pos , Owner . JumpHeight , Owner .DigStrength , Owner .Team
1011
1011
);
1012
1012
end
1013
1013
end
@@ -1123,7 +1123,7 @@ function HumanBehaviors.ToolSearch(AI, Owner, Abort)
1123
1123
end
1124
1124
searchesRemaining = searchesRemaining - 1 ;
1125
1125
end ,
1126
- Owner .Pos , device .Pos , false , Owner .DigStrength , Owner .Team
1126
+ Owner .Pos , device .Pos , Owner . JumpHeight , Owner .DigStrength , Owner .Team
1127
1127
);
1128
1128
end
1129
1129
end
@@ -1353,142 +1353,78 @@ function HumanBehaviors.GoToWpt(AI, Owner, Abort)
1353
1353
if WptList then
1354
1354
local NextWptPos = WptList [1 ].Pos ;
1355
1355
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
1367
1358
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
1390
-
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
1359
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
1418
1372
else
1419
1373
digState = AHuman .NOTDIGGING ;
1420
1374
obstacleState = Actor .PROCEEDING ;
1421
- StuckTimer :SetSimTimeLimitMS (1000 );
1422
1375
end
1423
- end
1424
1376
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
1428
1385
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 );
1434
1389
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 );
1439
1395
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 );
1446
1400
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 ;
1449
1404
else
1450
1405
AI .proneState = AHuman .NOTPRONE ;
1451
1406
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 ;
1452
1412
end
1453
1413
end
1414
+ end
1454
1415
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
1458
1418
end
1459
1419
1460
1420
if not Waypoint .Type then
1461
1421
ArrivedTimer :SetSimTimeLimitMS (100 );
1462
1422
elseif Waypoint .Type == " last" then
1463
- ArrivedTimer :SetSimTimeLimitMS (600 );
1423
+ ArrivedTimer :SetSimTimeLimitMS (300 );
1464
1424
else -- air or corner wpt
1465
1425
ArrivedTimer :SetSimTimeLimitMS (0 );
1466
1426
end
1467
1427
end
1468
- elseif WptList [2 ] then -- check if some other waypoint is closer
1469
- local test = math.random (1 , math.min (10 , # WptList ));
1470
- local RandomWpt = WptList [test ];
1471
- if RandomWpt then
1472
- Dist = SceneMan :ShortestDistance (Owner .Pos , RandomWpt .Pos , false );
1473
- if Dist :MagnitudeIsLessThan (50 ) and Dist :MagnitudeIsLessThan (SceneMan :ShortestDistance (Owner .Pos , Waypoint .Pos , false ).Magnitude * 0.33 ) then
1474
- -- this waypoint is closer, check LOS
1475
- if - 1 == SceneMan :CastObstacleRay (Owner .Pos , Dist , Vector (), Vector (), Owner .ID , Owner .IgnoresWhichTeam , rte .grassID , 4 ) then
1476
- Waypoint = RandomWpt ; -- go here instead
1477
- if WptList [test - 1 ] then
1478
- PrevWptPos = Vector (WptList [test - 1 ].Pos .X , WptList [test - 1 ].Pos .Y );
1479
- else
1480
- PrevWptPos = Vector (Owner .Pos .X , Owner .Pos .Y );
1481
- end
1482
-
1483
- for _ = 1 , test do -- delete the earlier waypoints
1484
- table.remove (WptList , 1 );
1485
- if WptList [1 ] then
1486
- Owner :RemoveMovePathBeginning ();
1487
- end
1488
- end
1489
- end
1490
- end
1491
- end
1492
1428
end
1493
1429
1494
1430
if Waypoint then
@@ -1743,7 +1679,7 @@ function HumanBehaviors.GoToWpt(AI, Owner, Abort)
1743
1679
if Owner .Jetpack and Owner .Head and Owner .Head :IsAttached () then
1744
1680
if Owner .Jetpack .JetTimeLeft < AI .minBurstTime then
1745
1681
AI .jump = false ; -- not enough fuel left, no point in jumping yet
1746
- if not AI .flying or Owner .Vel .Y > 1 then
1682
+ if not AI .flying or Owner .Vel .Y > 4 then
1747
1683
AI .refuel = true ;
1748
1684
end
1749
1685
else
@@ -1958,24 +1894,23 @@ function HumanBehaviors.GoToWpt(AI, Owner, Abort)
1958
1894
local TmpWpts = {};
1959
1895
table.insert (TmpWpts , {Pos = Owner .Pos });
1960
1896
1961
- local Origin ;
1962
1897
local LastPos = PathDump [1 ];
1963
1898
local index = 1 ;
1964
1899
for _ , WptPos in pairs (PathDump ) do
1965
- Origin = TmpWpts [index ].Pos ;
1966
- local Dist = SceneMan :ShortestDistance (Origin , WptPos , false );
1967
- if math.abs (Dist .Y ) > 30 or Dist :MagnitudeIsGreaterThan (80 ) or -- skip any waypoint too close to the previous one
1968
- SceneMan :CastStrengthSumRay (Origin , WptPos , 3 , rte .grassID ) > 5
1969
- then
1900
+ -- Origin = TmpWpts[index].Pos;
1901
+ -- local Dist = SceneMan:ShortestDistance(Origin, WptPos, false);
1902
+ -- if math.abs(Dist.Y) > 30 or Dist:MagnitudeIsGreaterThan(80) or -- skip any waypoint too close to the previous one
1903
+ -- SceneMan:CastStrengthSumRay(Origin, WptPos, 3, rte.grassID) > 5
1904
+ -- then
1970
1905
table.insert (TmpWpts , {Pos = LastPos });
1971
1906
index = index + 1 ;
1972
- end
1907
+ -- end
1973
1908
1974
1909
LastPos = WptPos ;
1975
1910
end
1976
1911
1977
1912
-- No path
1978
- if # PathDump == 0 then
1913
+ if # TmpWpts == 0 then
1979
1914
break ;
1980
1915
end
1981
1916
@@ -1986,50 +1921,6 @@ function HumanBehaviors.GoToWpt(AI, Owner, Abort)
1986
1921
while TmpWpts [1 ] do
1987
1922
local NextWpt = table.remove (TmpWpts , 1 );
1988
1923
1989
- if Lower (NextWpt , StartWpt , 30 ) then -- scan for sharp drops
1990
- local Dist = SceneMan :ShortestDistance (StartWpt .Pos , NextWpt .Pos , false );
1991
- if math.abs (Dist .X ) < Dist .Y then -- check the slope
1992
- if SceneMan :CastObstacleRay (StartWpt .Pos , Dist , Vector (), Vector (), Owner .ID , Owner .IgnoresWhichTeam , rte .grassID , 4 ) < 0 then
1993
- NextWpt .Type = " drop" ; -- LOS from StartWpt to NextWpt
1994
- end
1995
-
1996
- local GapList = {};
1997
- for j , JumpWpt in pairs (TmpWpts ) do -- look for the other side
1998
- local Gap = SceneMan :ShortestDistance (StartWpt .Pos , JumpWpt .Pos , false );
1999
- if Gap :MagnitudeIsGreaterThan (400 - Gap .Y ) then -- TODO: use actor properties here
2000
- break ; -- too far
2001
- end
2002
-
2003
- if Gap .Y > - 40 then -- no more than 2m above
2004
- table.insert (GapList , {Wpt = JumpWpt , score = math.abs (Gap .X / Gap .Y ), index = j });
2005
- end
2006
- end
2007
-
2008
- table.sort (GapList , function (A , B ) return A .score > B .score end ); -- sort largest first
2009
-
2010
- for _ , LZ in pairs (GapList ) do
2011
- -- check if we can jump
2012
- local Trace = SceneMan :ShortestDistance (StartWpt .Pos , LZ .Wpt .Pos , false );
2013
- if SceneMan :CastObstacleRay (StartWpt .Pos , Trace , Vector (), Vector (), Owner .ID , Owner .IgnoresWhichTeam , rte .grassID , 4 ) < 0 then
2014
- -- find a point mid-air
2015
- local TestPos = StartWpt .Pos + Trace * 0.6 ;
2016
- local Free = Vector ();
2017
- if 0 ~= SceneMan :CastObstacleRay (TestPos , Vector (0 , - math.abs (Trace .X )/ 2 ), Vector (), Free , Owner .ID , Owner .IgnoresWhichTeam , rte .grassID , 2 ) then -- TODO: check LOS? what if 0?
2018
- table.insert (WptList , {Pos = Free + Vector (0 ,Owner .Height / 3 ), Type = " air" }); -- guide point in the air
2019
- NextWpt = LZ .Wpt ;
2020
-
2021
- -- delete any waypoints between StartWpt and the LZ
2022
- for i = LZ .index , 1 , - 1 do
2023
- table.remove (TmpWpts , i );
2024
- end
2025
-
2026
- break ;
2027
- end
2028
- end
2029
- end
2030
- end
2031
- end
2032
-
2033
1924
table.insert (WptList , NextWpt );
2034
1925
StartWpt = NextWpt ;
2035
1926
end
0 commit comments