@@ -320,8 +320,12 @@ function HumanBehaviors.Sentry(AI, Owner, Abort)
320
320
Owner :ClearMovePath ();
321
321
Owner :AddAISceneWaypoint (Vector (Owner .Pos .X , 0 ));
322
322
Owner :UpdateMovePath ();
323
- local _ai , _ownr , _abrt = coroutine.yield (); -- wait until next frame
324
- if _abrt then return true end
323
+
324
+ -- wait until movepath is updated
325
+ while Owner .IsWaitingOnNewMovePath do
326
+ local _ai , _ownr , _abrt = coroutine.yield ();
327
+ if _abrt then return true end
328
+ end
325
329
326
330
-- face the direction of the first waypoint
327
331
for WptPos in Owner .MovePath do
@@ -528,12 +532,14 @@ function HumanBehaviors.Patrol(AI, Owner, Abort)
528
532
529
533
if Dist :MagnitudeIsGreaterThan (20 ) then
530
534
Owner :ClearAIWaypoints ();
531
- Owner :AddAISceneWaypoint (Free );
532
- local _ai , _ownr , _abrt = coroutine.yield (); -- wait until next frame
533
- if _abrt then return true end
535
+ Owner :AddAISceneWaypoint (Free );
534
536
Owner :UpdateMovePath ();
535
- local _ai , _ownr , _abrt = coroutine.yield (); -- wait until next frame
536
- if _abrt then return true end
537
+
538
+ -- wait until movepath is updated
539
+ while Owner .IsWaitingOnNewMovePath do
540
+ local _ai , _ownr , _abrt = coroutine.yield ();
541
+ if _abrt then return true end
542
+ end
537
543
538
544
local PrevPos = Vector (Owner .Pos .X , Owner .Pos .Y );
539
545
for WptPos in Owner .MovePath do
@@ -553,11 +559,13 @@ function HumanBehaviors.Patrol(AI, Owner, Abort)
553
559
if Dist :MagnitudeIsGreaterThan (20 ) then
554
560
Owner :ClearAIWaypoints ();
555
561
Owner :AddAISceneWaypoint (Free );
556
- local _ai , _ownr , _abrt = coroutine.yield (); -- wait until next frame
557
- if _abrt then return true end
558
562
Owner :UpdateMovePath ();
559
- local _ai , _ownr , _abrt = coroutine.yield (); -- wait until next frame
560
- if _abrt then return true end
563
+
564
+ -- wait until movepath is updated
565
+ while Owner .IsWaitingOnNewMovePath do
566
+ local _ai , _ownr , _abrt = coroutine.yield ();
567
+ if _abrt then return true end
568
+ end
561
569
562
570
local PrevPos = Vector (Owner .Pos .X , Owner .Pos .Y );
563
571
for WptPos in Owner .MovePath do
@@ -843,6 +851,12 @@ function HumanBehaviors.BrainSearch(AI, Owner, Abort)
843
851
Owner :AddAISceneWaypoint (Act .Pos );
844
852
Owner :UpdateMovePath ();
845
853
854
+ -- wait until movepath is updated
855
+ while Owner .IsWaitingOnNewMovePath do
856
+ local _ai , _ownr , _abrt = coroutine.yield ();
857
+ if _abrt then return true end
858
+ end
859
+
846
860
local OldWpt , deltaY ;
847
861
local index = 0 ;
848
862
local height = 0 ;
@@ -951,55 +965,46 @@ function HumanBehaviors.WeaponSearch(AI, Owner, Abort)
951
965
table.sort (devices , function (device , otherDevice ) return device .distance .SqrMagnitude < otherDevice .distance .SqrMagnitude end );
952
966
953
967
if # devices > 0 then
954
- local _ai , _ownr , _abrt = coroutine.yield ();
955
- if _abrt then return true end
956
-
957
- local maxWaypointDistance = 36 ;
968
+ local maxPathLength = 36 ; -- TODO when this gets turned into a part of pathing calc, use it that way instead
958
969
if AI .isPlayerOwned then
959
- maxWaypointDistance = 10 ;
970
+ maxPathLength = 10 ;
960
971
end
961
-
972
+
973
+ local searchesRemaining = # devices ;
962
974
local devicesToPickUp = {};
963
975
for _ , deviceEntry in pairs (devices ) do
964
976
local device = deviceEntry .device ;
965
977
if MovableMan :ValidMO (device ) then
966
- local pathToItemIsObstructed = false ;
967
- if AI .useExpensiveToolAndWeaponSearch then
968
- pathToItemIsObstructed = SceneMan :CastStrengthRay (Owner .Pos , deviceEntry .distance , 5 , Vector (), 4 , rte .grassID , true );
969
- end
970
- local pathfinderNodeSize = 20 ; -- TODO this should be read from cpp
971
-
972
- local distanceToTarget = pathToItemIsObstructed and SceneMan .Scene :CalculatePath (Owner .Pos , device .Pos , false , 1 , Owner .Team ) or (deviceEntry .distance .Magnitude / pathfinderNodeSize );
973
- if distanceToTarget < maxWaypointDistance and distanceToTarget > - 1 then
974
- local score = distanceToTarget
975
- if device :HasObjectInGroup (" Weapons - Primary" ) or device :HasObjectInGroup (" Weapons - Heavy" ) then
976
- score = distanceToTarget * 0.4 ; -- prioritize primary or heavy weapons
977
- elseif device .ClassName == " TDExplosive" then
978
- score = distanceToTarget * 1.4 ; -- avoid grenades if there are other weapons
979
- elseif device :IsTool () then
980
- if pickupDiggers and device :HasObjectInGroup (" Tools - Diggers" ) then
981
- score = distanceToTarget * 1.8 ; -- avoid diggers if there are other weapons
982
- else
983
- distanceToTarget = maxWaypointDistance ;
984
- end
985
- end
986
-
987
- if distanceToTarget < maxWaypointDistance then
988
- table.insert (devicesToPickUp , {device = device , score = score });
989
- if not pathToItemIsObstructed or score < 1 then
990
- local _ai , _ownr , _abrt = coroutine.yield ();
991
- if _abrt then return true end
992
- break ;
978
+ SceneMan .Scene :CalculatePathAsync (
979
+ function (pathRequest )
980
+ local pathLength = pathRequest .PathLength ;
981
+ if pathRequest .Status ~= PathRequest .NoSolution and pathLength < maxPathLength then
982
+ local score = pathLength ;
983
+ if device :HasObjectInGroup (" Weapons - Primary" ) or device :HasObjectInGroup (" Weapons - Heavy" ) then
984
+ score = pathLength * 0.4 ; -- prioritize primary or heavy weapons
985
+ elseif device .ClassName == " TDExplosive" then
986
+ score = pathLength * 1.4 ; -- avoid grenades if there are other weapons
987
+ elseif device :IsTool () then
988
+ if pickupDiggers and device :HasObjectInGroup (" Tools - Diggers" ) then
989
+ score = pathLength * 1.8 ; -- avoid diggers if there are other weapons
990
+ else
991
+ pathLength = maxPathLength ;
992
+ end
993
+ end
994
+ if pathLength < maxPathLength then
995
+ table.insert (devicesToPickUp , {device = device , score = score });
996
+ end
993
997
end
998
+ searchesRemaining = searchesRemaining - 1 ;
994
999
end
995
- for i = 1 , 2 do
996
- local _ai , _ownr , _abrt = coroutine.yield ();
997
- if _abrt then return true end
998
- end
999
- end
1000
+ , Owner .Pos , device .Pos , false , Owner .DigStrength , Owner .Team );
1000
1001
end
1001
1002
end
1002
-
1003
+
1004
+ while searchesRemaining > 0 do
1005
+ local _ai , _ownr , _abrt = coroutine.yield ();
1006
+ if _abrt then return true end
1007
+ end
1003
1008
1004
1009
AI .PickupHD = nil ;
1005
1010
table.sort (devicesToPickUp , function (A ,B ) return A .score < B .score end );
@@ -1033,6 +1038,13 @@ function HumanBehaviors.WeaponSearch(AI, Owner, Abort)
1033
1038
end
1034
1039
1035
1040
Owner :UpdateMovePath ();
1041
+
1042
+ -- wait until movepath is updated
1043
+ while Owner .IsWaitingOnNewMovePath do
1044
+ local _ai , _ownr , _abrt = coroutine.yield ();
1045
+ if _abrt then return true end
1046
+ end
1047
+
1036
1048
AI :CreateGoToBehavior (Owner );
1037
1049
end
1038
1050
end
@@ -1081,41 +1093,34 @@ function HumanBehaviors.ToolSearch(AI, Owner, Abort)
1081
1093
table.sort (devices , function (device , otherDevice ) return device .distance .SqrMagnitude < otherDevice .distance .SqrMagnitude end );
1082
1094
1083
1095
if # devices > 0 then
1084
- local _ai , _ownr , _abrt = coroutine.yield ();
1085
- if _abrt then return true end
1086
-
1087
- local maxWaypointDistance = 16 ;
1096
+ local maxPathLength = 16 ;
1088
1097
if Owner .AIMode == Actor .AIMODE_GOLDDIG then
1089
- maxWaypointDistance = 30 ;
1098
+ maxPathLength = 30 ;
1090
1099
elseif AI .isPlayerOwned then
1091
- maxWaypointDistance = 5 ;
1100
+ maxPathLength = 5 ;
1092
1101
end
1093
-
1102
+
1103
+ local searchesRemaining = # devices ;
1094
1104
local devicesToPickUp = {};
1095
1105
for _ , deviceEntry in pairs (devices ) do
1096
1106
local device = deviceEntry .device ;
1097
1107
if MovableMan :ValidMO (device ) then
1098
- local pathToItemIsObstructed = false ;
1099
- if AI .useExpensiveToolAndWeaponSearch then
1100
- pathToItemIsObstructed = SceneMan :CastStrengthRay (Owner .Pos , deviceEntry .distance , 5 , Vector (), 4 , rte .grassID , true );
1101
- end
1102
- local pathfinderNodeSize = 20 ; -- TODO this should be read from cpp
1103
-
1104
- local distanceToTarget = pathToItemIsObstructed and SceneMan .Scene :CalculatePath (Owner .Pos , device .Pos , false , 1 , Owner .Team ) or (deviceEntry .distance .Magnitude / pathfinderNodeSize );
1105
- if distanceToTarget < maxWaypointDistance and distanceToTarget > - 1 then
1106
- table.insert (devicesToPickUp , {device = device , score = distanceToTarget });
1107
-
1108
- if not pathToItemIsObstructed or distanceToTarget < 1 then
1109
- break ;
1110
- end
1111
-
1112
- for i = 1 , 2 do
1113
- local _ai , _ownr , _abrt = coroutine.yield ();
1114
- if _abrt then return true end
1108
+ SceneMan .Scene :CalculatePathAsync (
1109
+ function (pathRequest )
1110
+ local pathLength = pathRequest .PathLength ;
1111
+ if pathRequest .Status ~= PathRequest .NoSolution and pathLength < maxPathLength then
1112
+ table.insert (devicesToPickUp , {device = device , score = pathLength });
1113
+ end
1114
+ searchesRemaining = searchesRemaining - 1 ;
1115
1115
end
1116
- end
1116
+ , Owner . Pos , device . Pos , false , Owner . DigStrength , Owner . Team );
1117
1117
end
1118
1118
end
1119
+
1120
+ while searchesRemaining > 0 do
1121
+ local _ai , _ownr , _abrt = coroutine.yield ();
1122
+ if _abrt then return true end
1123
+ end
1119
1124
1120
1125
AI .PickupHD = nil ;
1121
1126
table.sort (devicesToPickUp , function (A ,B ) return A .score < B .score end ); -- sort the items in order of discounted distance
@@ -1151,6 +1156,13 @@ function HumanBehaviors.ToolSearch(AI, Owner, Abort)
1151
1156
end
1152
1157
1153
1158
Owner :UpdateMovePath ();
1159
+
1160
+ -- wait until movepath is updated
1161
+ while Owner .IsWaitingOnNewMovePath do
1162
+ local _ai , _ownr , _abrt = coroutine.yield ();
1163
+ if _abrt then return true end
1164
+ end
1165
+
1154
1166
AI :CreateGoToBehavior (Owner );
1155
1167
end
1156
1168
end
@@ -1909,6 +1921,12 @@ function HumanBehaviors.GoToWpt(AI, Owner, Abort)
1909
1921
else
1910
1922
Owner :UpdateMovePath ();
1911
1923
1924
+ -- wait until movepath is updated
1925
+ while Owner .IsWaitingOnNewMovePath do
1926
+ local _ai , _ownr , _abrt = coroutine.yield ();
1927
+ if _abrt then return true end
1928
+ end
1929
+
1912
1930
-- have we arrived?
1913
1931
if not Owner .MOMoveTarget then
1914
1932
local ProxyWpt = SceneMan :MovePointToGround (Owner :GetLastAIWaypoint (), Owner .Height * 0.2 , 5 );
@@ -1927,7 +1945,7 @@ function HumanBehaviors.GoToWpt(AI, Owner, Abort)
1927
1945
end
1928
1946
end
1929
1947
1930
- -- no waypoint list, create one in several small steps to reduce lag
1948
+ -- no waypoint list, create one
1931
1949
local PathDump = {};
1932
1950
if Owner .MOMoveTarget and MovableMan :ValidMO (Owner .MOMoveTarget ) then
1933
1951
Owner :DrawWaypoints (false );
@@ -1941,18 +1959,12 @@ function HumanBehaviors.GoToWpt(AI, Owner, Abort)
1941
1959
Owner :ClearMovePath ();
1942
1960
Owner :AddToMovePathEnd (Owner .MOMoveTarget .Pos );
1943
1961
else
1944
- local _ai , _ownr , _abrt = coroutine.yield (); -- wait until next frame
1945
- if _abrt then return true end
1946
-
1947
1962
-- copy the MovePath to a temporary table so we can yield safely while working on the path
1948
1963
for WptPos in Owner .MovePath do
1949
1964
table.insert (PathDump , WptPos );
1950
1965
end
1951
1966
end
1952
1967
1953
- local _ai , _ownr , _abrt = coroutine.yield (); -- wait until next frame
1954
- if _abrt then return true end
1955
-
1956
1968
-- copy useful waypoints to a temporary path
1957
1969
local TmpWpts = {};
1958
1970
table.insert (TmpWpts , {Pos = Owner .Pos });
@@ -1971,8 +1983,6 @@ function HumanBehaviors.GoToWpt(AI, Owner, Abort)
1971
1983
end
1972
1984
1973
1985
LastPos = WptPos ;
1974
- local _ai , _ownr , _abrt = coroutine.yield (); -- wait until next frame
1975
- if _abrt then return true end
1976
1986
end
1977
1987
1978
1988
-- No path
@@ -2006,9 +2016,6 @@ function HumanBehaviors.GoToWpt(AI, Owner, Abort)
2006
2016
end
2007
2017
end
2008
2018
2009
- local _ai , _ownr , _abrt = coroutine.yield (); -- wait until next frame
2010
- if _abrt then return true end
2011
-
2012
2019
table.sort (GapList , function (A , B ) return A .score > B .score end ); -- sort largest first
2013
2020
2014
2021
for _ , LZ in pairs (GapList ) do
@@ -2030,9 +2037,6 @@ function HumanBehaviors.GoToWpt(AI, Owner, Abort)
2030
2037
break ;
2031
2038
end
2032
2039
end
2033
-
2034
- local _ai , _ownr , _abrt = coroutine.yield (); -- wait until next frame
2035
- if _abrt then return true end
2036
2040
end
2037
2041
end
2038
2042
end
0 commit comments