Ticket #1720: patrol_V3.2.patch
File patrol_V3.2.patch, 10.2 KB (added by , 8 years ago) |
---|
-
binaries/data/config/default.cfg
280 280 garrison = Ctrl ; Modifier to garrison when clicking on building 281 281 autorallypoint = Ctrl ; Modifier to set the rally point on the building itself 282 282 guard = "G" ; Modifier to escort/guard when clicking on unit/building 283 patrol = "Y" ; Modifier to patrol a unit 283 284 queue = Shift ; Modifier to queue unit orders instead of replacing 284 285 batchtrain = Shift ; Modifier to train units in batches 285 286 massbarter = Shift ; Modifier to barter bunch of resources -
binaries/data/mods/public/gui/session/input.js
16 16 const ACTION_GARRISON = 1; 17 17 const ACTION_REPAIR = 2; 18 18 const ACTION_GUARD = 3; 19 const ACTION_PATROL = 4; 19 20 var preSelectedAction = ACTION_NONE; 20 21 21 22 const INPUT_NORMAL = 0; … … 208 209 return { "possible": true, "data": data, "cursor": cursor }; 209 210 } 210 211 212 if (action == "patrol") 213 { 214 // dirty hack 215 return { "possible": true }; 216 } 217 211 218 return { "possible": (action == "move" || action == "attack-move" || action == "remove-guard") }; 212 219 } 213 220 … … 1160 1167 // of running it immediately 1161 1168 var queued = Engine.HotkeyIsPressed("session.queue"); 1162 1169 var target = Engine.GetTerrainAtScreenPoint(ev.x, ev.y); 1163 1170 1164 1171 if (unitActions[action.type] && unitActions[action.type].execute) 1165 1172 return unitActions[action.type].execute(target, action, selection, queued); 1166 1173 error("Invalid action.type "+action.type); -
binaries/data/mods/public/gui/session/unit_actions.js
139 139 "specificness": 10, 140 140 }, 141 141 142 "patrol": 143 { 144 "execute": function(target, action, selection, queued) 145 { 146 var targetClasses = { "attack": ["Unit"] }; // patrol should only attack units - if a new strucure is build near to the patrol, the patrol will recognize the units 147 Engine.PostNetworkCommand({ "type": "patrol", "entities": selection, "x": target.x, "z": target.z, "target": action.target, "targetClasses": targetClasses, "queued": queued, "allowCapture": false }); 148 Engine.GuiInterfaceCall("PlaySound", { "name": "order_patrol", "entity": selection[0] }); 149 return true; 150 }, 151 "getActionInfo": function(entState, targetState) 152 { 153 return { "possible": true }; 154 }, 155 "hotkeyActionCheck": function(target) 156 { 157 if (Engine.HotkeyIsPressed("session.patrol") && getActionInfo("patrol", target).possible) 158 return { "type": "patrol", "cursor": "action-patrol", "target": target }; 159 return false; 160 }, 161 "preSelectedActionCheck" : function(target) 162 { 163 if (preSelectedAction != ACTION_PATROL) 164 return false; 165 if (getActionInfo("patrol", target).possible) 166 return { "type": "patrol", "cursor": "action-patrol", "target": target }; 167 return false; 168 }, 169 "specificness": 37, 170 171 }, 172 142 173 "heal": 143 174 { 144 175 "execute": function(target, action, selection, queued) … … 894 925 toggleTrade(); 895 926 }, 896 927 }, 928 // Patrol 929 "patrol": { 930 "getInfo": function(entState) 931 { 932 if (!entState.unitAI) 933 return false; 934 return { 935 "tooltip": translate("Patrol"), 936 "icon": "patrol.png" 937 }; 938 }, 939 "execute": function(entState) 940 { 941 inputState = INPUT_PRESELECTEDACTION; 942 preSelectedAction = ACTION_PATROL; 943 }, 944 }, 897 945 // Dropsite sharing 898 946 "share-dropsite": { 899 947 "getInfo": function(entState) -
binaries/data/mods/public/simulation/components/UnitAI.js
510 510 this.FinishOrder(); 511 511 }, 512 512 513 "Order.Patrol": function(msg) { 514 // Let players move captured domestic animals around 515 if (this.IsAnimal() || this.IsTurret()) 516 { 517 this.FinishOrder(); 518 return; 519 } 520 521 // For packable units: 522 // 1. If packed, we can move. 523 // 2. If unpacked, we first need to pack, then follow case 1. 524 if (this.CanPack()) 525 { 526 // Case 2: pack 527 this.PushOrderFront("Pack", { "force": true }); 528 return; 529 } 530 531 this.MoveToPoint(this.order.data.x, this.order.data.z); 532 this.SetNextState("INDIVIDUAL.PATROL"); 533 }, 534 513 535 "Order.Heal": function(msg) { 514 536 // Check the target is alive 515 537 if (!this.TargetIsAlive(this.order.data.target)) … … 825 847 this.FinishOrder(); 826 848 }, 827 849 850 "Order.Patrol": function(msg) { 851 this.CallMemberFunction("SetHeldPosition", [msg.data.x, msg.data.z]); 852 853 this.MoveToPoint(this.order.data.x, this.order.data.z); 854 this.SetNextState("PATROL"); 855 }, 856 828 857 "Order.Guard": function(msg) { 829 858 this.CallMemberFunction("Guard", [msg.data.target, false]); 830 859 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); … … 1074 1103 }, 1075 1104 }, 1076 1105 1106 "PATROL": { 1107 "enter": function(msg) { 1108 this.StartTimer(0, 1000); 1109 1110 // memorize the origin position in case that we want to go back 1111 let cntPosition = Engine.QueryInterface(this.entity, IID_Position); 1112 if (!cntPosition || !cntPosition.IsInWorld()) 1113 { 1114 this.FinishOrder(); 1115 return; 1116 } 1117 this.patrolStartPos = cntPosition.GetPosition(); 1118 }, 1119 1120 "Timer": function(msg) { 1121 // check if there are no enemies to attack 1122 this.FindWalkAndFightTargets(); 1123 }, 1124 1125 "leave": function(msg) { 1126 this.StopTimer(); 1127 }, 1128 1129 "MoveStarted": function(msg) { 1130 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); 1131 cmpFormation.SetRearrange(true); 1132 cmpFormation.MoveMembersIntoFormation(true, true); 1133 }, 1134 1135 "MoveCompleted": function() { 1136 // A-B-A-B-..: 1137 // if the user only commands one patrol order, the patrol will be between 1138 // the last position and the defined waypoint 1139 // A-B-C-..-A-B-..: 1140 // otherwise, the patrol is only between the given patrol commands and the 1141 // last position is not included (last position = the position where the unit 1142 // is located at the time of the first patrol order) 1143 if (this.orderQueue.length == 1) 1144 { 1145 this.orderQueue.push({ "type": "Patrol", "data": this.patrolStartPos }); 1146 } 1147 1148 this.orderQueue.push(this.order); 1149 this.FinishOrder(); 1150 }, 1151 }, 1152 1077 1153 "GARRISON":{ 1078 1154 "enter": function() { 1079 1155 // If the garrisonholder should pickup, warn it so it can take needed action … … 1551 1627 }, 1552 1628 }, 1553 1629 1630 "PATROL": { 1631 "enter": function () { 1632 this.StartTimer(0, 1000); 1633 this.SelectAnimation("move"); 1634 1635 // memorize the origin position in case that we want to go back 1636 let cntPosition = Engine.QueryInterface(this.entity, IID_Position); 1637 if (!cntPosition || !cntPosition.IsInWorld()) 1638 { 1639 this.FinishOrder(); 1640 return; 1641 } 1642 this.patrolStartPos = cntPosition.GetPosition(); 1643 }, 1644 1645 "leave": function() { 1646 this.StopTimer(); 1647 }, 1648 1649 "Timer": function(msg) { 1650 this.FindWalkAndFightTargets(); 1651 }, 1652 1653 "MoveCompleted": function() { 1654 if (this.orderQueue.length == 1) 1655 { 1656 this.orderQueue.push({"type": "Patrol", "data": this.patrolStartPos}); 1657 } 1658 1659 this.orderQueue.push(this.order); 1660 this.FinishOrder(); 1661 }, 1662 }, 1663 1554 1664 "GUARD": { 1555 1665 "RemoveGuard": function() { 1556 1666 this.StopMoving(); … … 1795 1905 } 1796 1906 // Check the target is still alive and attackable 1797 1907 if (this.TargetIsAlive(target) && 1798 1799 1908 this.CanAttack(target, this.order.data.forceResponse || null) && 1909 !this.CheckTargetAttackRange(target, this.order.data.attackType)) 1800 1910 { 1801 1911 // Can't reach it - try to chase after it 1802 1912 if (this.ShouldChaseTargetedEntity(target, this.order.data.force)) … … 2037 2147 var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); 2038 2148 var cmpMirage = Engine.QueryInterface(this.gatheringTarget, IID_Mirage); 2039 2149 if ((!cmpMirage || !cmpMirage.Mirages(IID_ResourceSupply)) && 2040 2150 (!cmpSupply || !cmpSupply.AddGatherer(cmpOwnership.GetOwner(), this.entity))) 2041 2151 { 2042 2152 // Save the current order's data in case we need it later 2043 2153 var oldType = this.order.data.type; … … 3560 3670 error("FinishOrder called for entity " + this.entity + " (" + template + ") when order queue is empty\n" + stack); 3561 3671 } 3562 3672 3673 // next order 3563 3674 this.orderQueue.shift(); 3564 3675 this.order = this.orderQueue[0]; 3565 3676 … … 4771 4882 case "WalkToPointRange": 4772 4883 case "MoveIntoFormation": 4773 4884 case "GatherNearPosition": 4885 case "Patrol": 4774 4886 targetPositions.push(new Vector2D(order.data.x, order.data.z)); 4775 4887 break; // and continue the loop 4776 4888 … … 4983 5095 this.AddOrder("WalkAndFight", { "x": x, "z": z, "targetClasses": targetClasses, "force": true }, queued); 4984 5096 }; 4985 5097 5098 UnitAI.prototype.Patrol = function(x, z, targetClasses, queued) 5099 { 5100 this.AddOrder("Patrol", { "x": x, "z": z, "targetClasses": targetClasses, "force": true }, queued); 5101 }; 5102 4986 5103 /** 4987 5104 * Adds leave foundation order to queue, treated as forced. 4988 5105 */ -
binaries/data/mods/public/simulation/helpers/Commands.js
174 174 }); 175 175 }, 176 176 177 "patrol": function(player, cmd, data) 178 { 179 GetFormationUnitAIs(data.entities, player).forEach(cmpUnitAI => { 180 cmpUnitAI.Patrol(cmd.x, cmd.z, cmd.targetClasses, cmd.queued); 181 }); 182 }, 183 177 184 "heal": function(player, cmd, data) 178 185 { 179 186 if (g_DebugCommands && !(IsOwnedByPlayer(player, cmd.target) || IsOwnedByAllyOfPlayer(player, cmd.target)))