@@ -914,27 +914,38 @@ end
914
914
915
915
-- find a weapon to pick up
916
916
function HumanBehaviors .WeaponSearch (AI , Owner , Abort )
917
- local minDist ;
918
917
local pickupDiggers = not Owner :HasObjectInGroup (" Tools - Diggers" );
919
918
919
+ local maxSearchDistance ;
920
920
if AI .isPlayerOwned then
921
- minDist = 100 ; -- don't move player actors too far
921
+ maxSearchDistance = 100 ; -- don't move player actors too far
922
922
else
923
- minDist = FrameMan .PlayerScreenWidth * 0.45 ;
923
+ maxSearchDistance = FrameMan .PlayerScreenWidth * 0.45 ;
924
924
end
925
925
926
926
if Owner .AIMode == Actor .AIMODE_SENTRY then
927
- minDist = minDist * 0.6 ;
927
+ maxSearchDistance = maxSearchDistance * 0.6 ;
928
928
end
929
929
930
930
local devices = {};
931
931
local mosSearched = 0 ;
932
- for movableObject in MovableMan :GetMOsInRadius (Owner .Pos , minDist , - 1 , true ) do
932
+ for movableObject in MovableMan :GetMOsInRadius (Owner .Pos , maxSearchDistance , - 1 , true ) do
933
933
mosSearched = mosSearched + 1 ;
934
- if IsHeldDevice (movableObject ) then
934
+ if mosSearched % 30 == 0 then
935
+ local _ai , _ownr , _abrt = coroutine.yield ();
936
+ if _abrt then return true end
937
+ end
938
+
939
+ if IsHeldDevice (movableObject ) and MovableMan :ValidMO (movableObject ) then
935
940
local device = ToHeldDevice (movableObject );
936
941
if device :IsPickupableBy (Owner ) and not device :IsActivated () and device .Vel .Largest < 3 and not SceneMan :IsUnseen (device .Pos .X , device .Pos .Y , Owner .Team ) then
937
- table.insert (devices , { device = device , distance = SceneMan :ShortestDistance (Owner .Pos , device .Pos , SceneMan .SceneWrapsX or SceneMan .SceneWrapsY ) });
942
+ local distanceToDevice = SceneMan :ShortestDistance (Owner .Pos , device .Pos , SceneMan .SceneWrapsX or SceneMan .SceneWrapsY );
943
+ if distanceToDevice :MagnitudeIsGreaterThan (Owner .Radius * 0.75 ) then
944
+ table.insert (devices , { device = device , distance = distanceToDevice });
945
+ else
946
+ devices = {{ device = device , distance = distanceToDevice }};
947
+ break ;
948
+ end
938
949
end
939
950
end
940
951
end
@@ -944,21 +955,24 @@ function HumanBehaviors.WeaponSearch(AI, Owner, Abort)
944
955
local _ai , _ownr , _abrt = coroutine.yield ();
945
956
if _abrt then return true end
946
957
947
- local waypointDistance = 36 ;
958
+ local maxWaypointDistance = 36 ;
948
959
if AI .isPlayerOwned then
949
- waypointDistance = 10 ;
960
+ maxWaypointDistance = 10 ;
950
961
end
951
962
952
- local waypoints , score ;
953
963
local devicesToPickUp = {};
954
964
for _ , deviceEntry in pairs (devices ) do
955
965
local device = deviceEntry .device ;
956
966
if MovableMan :ValidMO (device ) then
957
- local pathToItemIsObstructed = SceneMan :CastStrengthRay (Owner .Pos , deviceEntry .distance , 5 , Vector (), 4 , rte .grassID , true ); -- TODO if still laggy, just use this entirely and don't bother calcuating a path. Maybe only calculate path on smaller maps (< 10,000,000 square px)
967
+ local pathToItemIsObstructed = false ;
968
+ if AI .useExpensiveToolAndWeaponSearch then
969
+ pathToItemIsObstructed = SceneMan :CastStrengthRay (Owner .Pos , deviceEntry .distance , 5 , Vector (), 4 , rte .grassID , true );
970
+ end
958
971
local pathfinderNodeSize = 20 ; -- TODO this should be read from cpp
959
972
960
- local distanceToTarget = pathToItemIsObstructed and SceneMan .Scene :CalculatePath (Owner .Pos , device .Pos , false , 1 , Owner .Team ) or deviceEntry .distance .Magnitude / pathfinderNodeSize ;
961
- if distanceToTarget < waypointDistance and distanceToTarget > - 1 then
973
+ local distanceToTarget = pathToItemIsObstructed and SceneMan .Scene :CalculatePath (Owner .Pos , device .Pos , false , 1 , Owner .Team ) or (deviceEntry .distance .Magnitude / pathfinderNodeSize );
974
+ if distanceToTarget < maxWaypointDistance and distanceToTarget > - 1 then
975
+ local score = distanceToTarget
962
976
if device :HasObjectInGroup (" Weapons - Primary" ) or device :HasObjectInGroup (" Weapons - Heavy" ) then
963
977
score = distanceToTarget * 0.4 ; -- prioritize primary or heavy weapons
964
978
elseif device .ClassName == " TDExplosive" then
@@ -967,14 +981,17 @@ function HumanBehaviors.WeaponSearch(AI, Owner, Abort)
967
981
if pickupDiggers and device :HasObjectInGroup (" Tools - Diggers" ) then
968
982
score = distanceToTarget * 1.8 ; -- avoid diggers if there are other weapons
969
983
else
970
- distanceToTarget = waypointDistance ;
984
+ distanceToTarget = maxWaypointDistance ;
971
985
end
972
- else
973
- score = distanceToTarget ;
974
986
end
975
987
976
- if distanceToTarget < waypointDistance then
988
+ if distanceToTarget < maxWaypointDistance then
977
989
table.insert (devicesToPickUp , {device = device , score = score });
990
+ if not pathToItemIsObstructed or score < 1 then
991
+ local _ai , _ownr , _abrt = coroutine.yield ();
992
+ if _abrt then return true end
993
+ break ;
994
+ end
978
995
end
979
996
for i = 1 , 2 do
980
997
local _ai , _ownr , _abrt = coroutine.yield ();
@@ -984,9 +1001,10 @@ function HumanBehaviors.WeaponSearch(AI, Owner, Abort)
984
1001
end
985
1002
end
986
1003
1004
+
987
1005
AI .PickupHD = nil ;
988
- table.sort (devicesToPickUp , function (A ,B ) return A .score < B .score end ); -- sort the items in order of discounted distance
989
- for _ , deviceToPickupEntry in pairs (devicesToPickUp ) do
1006
+ table.sort (devicesToPickUp , function (A ,B ) return A .score < B .score end );
1007
+ for _ , deviceToPickupEntry in ipairs (devicesToPickUp ) do
990
1008
if MovableMan :ValidMO (deviceToPickupEntry .device ) and deviceToPickupEntry .device :IsDevice () then
991
1009
AI .PickupHD = deviceToPickupEntry .device ;
992
1010
break ;
@@ -1026,25 +1044,38 @@ end
1026
1044
1027
1045
-- find a tool to pick up
1028
1046
function HumanBehaviors .ToolSearch (AI , Owner , Abort )
1029
- local minDist ;
1047
+ local maxSearchDistance ;
1030
1048
if Owner .AIMode == Actor .AIMODE_GOLDDIG then
1031
- minDist = FrameMan .PlayerScreenWidth * 0.5 ; -- move up to half a screen when digging
1049
+ maxSearchDistance = FrameMan .PlayerScreenWidth * 0.5 ; -- move up to half a screen when digging
1032
1050
elseif AI .isPlayerOwned then
1033
- minDist = 60 ; -- don't move player actors too far
1051
+ maxSearchDistance = 60 ; -- don't move player actors too far
1034
1052
else
1035
- minDist = FrameMan .PlayerScreenWidth * 0.3 ;
1053
+ maxSearchDistance = FrameMan .PlayerScreenWidth * 0.3 ;
1036
1054
end
1037
1055
1038
1056
if Owner .AIMode == Actor .AIMODE_SENTRY then
1039
- minDist = minDist * 0.6 ;
1057
+ maxSearchDistance = maxSearchDistance * 0.6 ;
1040
1058
end
1041
1059
1042
1060
local devices = {};
1043
- for movableObject in MovableMan :GetMOsInRadius (Owner .Pos , minDist , - 1 , true ) do
1044
- if IsHeldDevice (movableObject ) then
1061
+ local mosSearched = 0 ;
1062
+ for movableObject in MovableMan :GetMOsInRadius (Owner .Pos , maxSearchDistance , - 1 , true ) do
1063
+ mosSearched = mosSearched + 1 ;
1064
+ if mosSearched % 30 == 0 then
1065
+ local _ai , _ownr , _abrt = coroutine.yield ();
1066
+ if _abrt then return true end
1067
+ end
1068
+
1069
+ if IsHeldDevice (movableObject ) and MovableMan :ValidMO (movableObject ) then
1045
1070
local device = ToHeldDevice (movableObject );
1046
1071
if device :IsPickupableBy (Owner ) and not device :IsActivated () and device .Vel .Largest < 3 and not SceneMan :IsUnseen (device .Pos .X , device .Pos .Y , Owner .Team ) and device :HasObjectInGroup (" Tools - Diggers" ) then
1047
- table.insert (devices , { device = device , distance = SceneMan :ShortestDistance (Owner .Pos , device .Pos , SceneMan .SceneWrapsX or SceneMan .SceneWrapsY ) });
1072
+ local distanceToDevice = SceneMan :ShortestDistance (Owner .Pos , device .Pos , SceneMan .SceneWrapsX or SceneMan .SceneWrapsY );
1073
+ if distanceToDevice :MagnitudeIsGreaterThan (20 ) then
1074
+ table.insert (devices , { device = device , distance = distanceToDevice });
1075
+ else
1076
+ devices = {{ device = device , distance = distanceToDevice }};
1077
+ break ;
1078
+ end
1048
1079
end
1049
1080
end
1050
1081
end
@@ -1054,25 +1085,31 @@ function HumanBehaviors.ToolSearch(AI, Owner, Abort)
1054
1085
local _ai , _ownr , _abrt = coroutine.yield ();
1055
1086
if _abrt then return true end
1056
1087
1057
- local waypointDistance = 16 ;
1088
+ local maxWaypointDistance = 16 ;
1058
1089
if Owner .AIMode == Actor .AIMODE_GOLDDIG then
1059
- waypointDistance = 30 ;
1090
+ maxWaypointDistance = 30 ;
1060
1091
elseif AI .isPlayerOwned then
1061
- waypointDistance = 5 ;
1092
+ maxWaypointDistance = 5 ;
1062
1093
end
1063
1094
1064
- local waypoints , score ;
1065
1095
local devicesToPickUp = {};
1066
1096
for _ , deviceEntry in pairs (devices ) do
1067
1097
local device = deviceEntry .device ;
1068
1098
if MovableMan :ValidMO (device ) then
1069
- local pathToItemIsObstructed = SceneMan :CastStrengthRay (Owner .Pos , deviceEntry .distance , 5 , Vector (), 4 , rte .grassID , true );
1099
+ local pathToItemIsObstructed = false ;
1100
+ if AI .useExpensiveToolAndWeaponSearch then
1101
+ pathToItemIsObstructed = SceneMan :CastStrengthRay (Owner .Pos , deviceEntry .distance , 5 , Vector (), 4 , rte .grassID , true );
1102
+ end
1070
1103
local pathfinderNodeSize = 20 ; -- TODO this should be read from cpp
1071
1104
1072
- local distanceToTarget = pathToItemIsObstructed and SceneMan .Scene :CalculatePath (Owner .Pos , device .Pos , false , 1 , Owner .Team ) or deviceEntry .distance .Magnitude / pathfinderNodeSize ;
1073
- if distanceToTarget < waypointDistance and distanceToTarget > - 1 then
1105
+ local distanceToTarget = pathToItemIsObstructed and SceneMan .Scene :CalculatePath (Owner .Pos , device .Pos , false , 1 , Owner .Team ) or ( deviceEntry .distance .Magnitude / pathfinderNodeSize ) ;
1106
+ if distanceToTarget < maxWaypointDistance and distanceToTarget > - 1 then
1074
1107
table.insert (devicesToPickUp , {device = device , score = distanceToTarget });
1075
1108
1109
+ if not pathToItemIsObstructed or distanceToTarget < 1 then
1110
+ break ;
1111
+ end
1112
+
1076
1113
for i = 1 , 2 do
1077
1114
local _ai , _ownr , _abrt = coroutine.yield ();
1078
1115
if _abrt then return true end
@@ -1083,7 +1120,7 @@ function HumanBehaviors.ToolSearch(AI, Owner, Abort)
1083
1120
1084
1121
AI .PickupHD = nil ;
1085
1122
table.sort (devicesToPickUp , function (A ,B ) return A .score < B .score end ); -- sort the items in order of discounted distance
1086
- for _ , deviceToPickupEntry in pairs (devicesToPickUp ) do
1123
+ for _ , deviceToPickupEntry in ipairs (devicesToPickUp ) do
1087
1124
if MovableMan :ValidMO (deviceToPickupEntry .device ) and deviceToPickupEntry .device :IsDevice () then
1088
1125
AI .PickupHD = deviceToPickupEntry .device ;
1089
1126
break ;
0 commit comments