Ticket #1001: attack-move-v3.diff
File attack-move-v3.diff, 10.2 KB (added by , 11 years ago) |
---|
-
binaries/data/mods/public/gui/session/input.js
187 187 { 188 188 if (action == "set-rallypoint" && haveRallyPoints) 189 189 return {"possible": true}; 190 else if (action == "move" )190 else if (action == "move" || action == "attack-move") 191 191 return {"possible": true}; 192 192 else 193 193 return {"possible": false}; … … 404 404 break; 405 405 } 406 406 } 407 if (action == "move" )407 if (action == "move" || action == "attack-move") 408 408 return {"possible": true}; 409 409 else 410 410 return {"possible": false}; … … 480 480 { 481 481 return {"type": "attack", "cursor": "action-attack", "target": target}; 482 482 } 483 else if (Engine.HotkeyIsPressed("session.attackmove") && getActionInfo("attack-move", target).possible) 484 { 485 return {"type": "attack-move", "cursor": "action-attack"}; 486 } 483 487 else if (Engine.HotkeyIsPressed("session.garrison")) 484 488 { 485 489 if (getActionInfo("garrison", target).possible) … … 1320 1324 Engine.GuiInterfaceCall("PlaySound", { "name": "order_walk", "entity": selection[0] }); 1321 1325 return true; 1322 1326 1327 case "attack-move": 1328 var target = Engine.GetTerrainAtScreenPoint(ev.x, ev.y); 1329 Engine.PostNetworkCommand({"type": "attack-walk", "entities": selection, "x": target.x, "z": target.z, "queued": queued}); 1330 Engine.GuiInterfaceCall("PlaySound", { "name": "order_walk", "entity": selection[0] }); 1331 return true; 1332 1323 1333 case "attack": 1324 1334 Engine.PostNetworkCommand({"type": "attack", "entities": selection, "target": action.target, "queued": queued}); 1325 1335 Engine.GuiInterfaceCall("PlaySound", { "name": "order_attack", "entity": selection[0] }); … … 1419 1429 Engine.GuiInterfaceCall("PlaySound", { "name": "order_walk", "entity": selection[0] }); 1420 1430 return true; 1421 1431 1432 case "attack-move": 1433 Engine.PostNetworkCommand({"type": "attack-walk", "entities": selection, "x": target.x, "z": target.z, "queued": queued}); 1434 Engine.GuiInterfaceCall("PlaySound", { "name": "order_walk", "entity": selection[0] }); 1435 return true; 1436 1422 1437 case "set-rallypoint": 1423 1438 Engine.PostNetworkCommand({"type": "set-rallypoint", "entities": selection, "x": target.x, "z": target.z}); 1424 1439 // Display rally point at the new coordinates, to avoid display lag -
binaries/data/mods/public/simulation/helpers/Commands.js
88 88 }); 89 89 break; 90 90 91 case "attack-walk": 92 var entities = FilterEntityList(cmd.entities, player, controlAllUnits); 93 GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) { 94 cmpUnitAI.WalkAndFight(cmd.x, cmd.z, cmd.queued); 95 }); 96 break; 97 91 98 case "attack": 92 99 if (g_DebugCommands && !(IsOwnedByEnemyOfPlayer(player, cmd.target) || IsOwnedByNeutralOfPlayer(player, cmd.target))) 93 100 { -
binaries/data/mods/public/simulation/components/UnitAI.js
270 270 this.SetNextState("INDIVIDUAL.WALKING"); 271 271 }, 272 272 273 "Order.WalkAndFight": function(msg) { 274 // Let players move captured domestic animals around 275 if (this.IsAnimal() && !this.IsDomestic()) 276 { 277 this.FinishOrder(); 278 return; 279 } 280 281 // For packable units: 282 // 1. If packed, we can move. 283 // 2. If unpacked, we first need to pack, then follow case 1. 284 if (this.CanPack()) 285 { 286 // Case 2: pack 287 this.PushOrderFront("Pack", { "force": true }); 288 return; 289 } 290 291 this.SetHeldPosition(this.order.data.x, this.order.data.z); 292 this.MoveToPoint(this.order.data.x, this.order.data.z); 293 if (this.IsAnimal()) 294 this.SetNextState("ANIMAL.WALKING"); // WalkAndFight not applicable for animals 295 else 296 this.SetNextState("INDIVIDUAL.WALKINGANDFIGHTING"); 297 }, 298 299 273 300 "Order.WalkToTarget": function(msg) { 274 301 // Let players move captured domestic animals around 275 302 if (this.IsAnimal() && !this.IsDomestic()) … … 353 380 if (this.CanUnpack()) 354 381 { 355 382 // Ignore unforced attacks 383 // this would prevent attacks from AttackVisibleEntity or AttackEntityInZone ? 384 // so we accept attacks against targets for which we have a bonus 356 385 // TODO: use special stances instead? 357 if (!this.order.data.force )386 if (!this.order.data.force && this.GetAttackBonus(type, this.order.data.target) < 1.5) 358 387 { 359 388 this.FinishOrder(); 360 389 return; … … 628 657 this.MoveToPoint(this.order.data.x, this.order.data.z); 629 658 this.SetNextState("WALKING"); 630 659 }, 660 661 "Order.WalkAndFight": function(msg) { 662 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); 663 cmpFormation.CallMemberFunction("SetHeldPosition", [msg.data.x, msg.data.z]); 664 665 this.MoveToPoint(this.order.data.x, this.order.data.z); 666 this.SetNextState("WALKINGANDFIGHTING"); 667 }, 631 668 632 669 "Order.MoveIntoFormation": function(msg) { 633 670 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); … … 885 922 }, 886 923 }, 887 924 925 "WALKINGANDFIGHTING": { 926 "enter": function(msg) { 927 this.StartTimer(0, 1000); 928 }, 929 930 "Timer": function(msg) { 931 // check if there are no ennemies to attack 932 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); 933 for each (var ent in cmpFormation.members) 934 { 935 var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); 936 if (cmpUnitAI.FindNewTargets()) 937 { 938 if (cmpUnitAI.orderQueue[0] && cmpUnitAI.orderQueue[0].type == "Attack") 939 { 940 var data = cmpUnitAI.orderQueue[0].data; 941 cmpUnitAI.FinishOrder(); 942 this.PushOrderFront("Attack", { "target": data.target, "force": false, "forceResponse": data.forceResponse }); 943 break; 944 } 945 } 946 } 947 }, 948 949 "leave": function(msg) { 950 this.StopTimer(); 951 }, 952 953 "MoveStarted": function(msg) { 954 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); 955 cmpFormation.SetRearrange(true); 956 cmpFormation.MoveMembersIntoFormation(true, true); 957 }, 958 959 "MoveCompleted": function(msg) { 960 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); 961 962 if (this.FinishOrder()) 963 { 964 cmpFormation.CallMemberFunction("ResetFinishOrder", []); 965 return; 966 } 967 968 // No more orders left. 969 cmpFormation.Disband(); 970 }, 971 }, 972 888 973 "FORMING": { 889 974 "MoveStarted": function(msg) { 890 975 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); … … 938 1023 939 1024 // Execute the next order 940 1025 if (this.FinishOrder()) 1026 { 1027 // if WalkAndFight order, look for new target before moving again 1028 if (this.orderQueue.length > 0 && this.orderQueue[0].type == "WalkAndFight") 1029 { 1030 for each (var ent in cmpFormation.members) 1031 { 1032 var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); 1033 if (cmpUnitAI.FindNewTargets()) 1034 { 1035 if (cmpUnitAI.orderQueue[0] && cmpUnitAI.orderQueue[0].type == "Attack") 1036 { 1037 var data = cmpUnitAI.orderQueue[0].data; 1038 cmpUnitAI.FinishOrder(); 1039 this.PushOrderFront("Attack", { "target": data.target, "force": false, "forceResponse": data.forceResponse }); 1040 break; 1041 } 1042 } 1043 } 1044 } 941 1045 return; 1046 } 942 1047 943 1048 // No more order left. 944 1049 cmpFormation.Disband(); … … 1146 1251 }, 1147 1252 }, 1148 1253 1254 "WALKINGANDFIGHTING": { 1255 "enter": function () { 1256 this.StartTimer(0, 1000); 1257 this.SelectAnimation("move"); 1258 }, 1259 1260 "Timer": function(msg) { 1261 this.FindNewTargets(); 1262 }, 1263 1264 "leave": function(msg) { 1265 this.StopTimer(); 1266 }, 1267 1268 "MoveCompleted": function() { 1269 this.FinishOrder(); 1270 }, 1271 }, 1272 1149 1273 "FLEEING": { 1150 1274 "enter": function() { 1151 1275 this.PlaySound("panic"); … … 1335 1459 } 1336 1460 1337 1461 // Can't reach it, no longer owned by enemy, or it doesn't exist any more - give up 1462 // Except if in WalkAndFight mode where we look for more ennemies around before moving again 1338 1463 if (this.FinishOrder()) 1464 { 1465 if (this.orderQueue.length > 0 && this.orderQueue[0].type == "WalkAndFight") 1466 this.FindNewTargets(); 1339 1467 return; 1468 } 1340 1469 1341 1470 // See if we can switch to a new nearby enemy 1342 1471 if (this.FindNewTargets()) … … 3213 3342 return cmpAttack.GetBestAttackAgainst(target); 3214 3343 }; 3215 3344 3345 UnitAI.prototype.GetAttackBonus = function(type, target) 3346 { 3347 var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); 3348 if (!cmpAttack) 3349 return 1; 3350 return cmpAttack.GetAttackBonus(type, target); 3351 }; 3352 3216 3353 /** 3217 3354 * Try to find one of the given entities which can be attacked, 3218 3355 * and start attacking it. … … 3425 3562 switch (order.type) 3426 3563 { 3427 3564 case "Walk": 3565 case "WalkAndFight": 3428 3566 case "WalkToPointRange": 3429 3567 case "MoveIntoFormation": 3430 3568 case "GatherNearPosition": … … 3511 3649 }; 3512 3650 3513 3651 /** 3652 * Adds walk-and-fight order to queue, this only occurs in response 3653 * to a player order, and so is forced. 3654 */ 3655 UnitAI.prototype.WalkAndFight = function(x, z, queued) 3656 { 3657 this.AddOrder("WalkAndFight", { "x": x, "z": z, "force": true }, queued); 3658 }; 3659 3660 /** 3514 3661 * Adds leave foundation order to queue, treated as forced. 3515 3662 */ 3516 3663 UnitAI.prototype.LeaveFoundation = function(target) -
binaries/data/config/default.cfg
245 245 hotkey.session.kill = Delete ; Destroy selected units 246 246 hotkey.session.attack = Ctrl ; Modifier to force attack instead of another action 247 247 hotkey.session.garrison = Ctrl ; Modifier to garrison when clicking on building 248 hotkey.session.attackmove = AltGr ; Modifier to attackmove when clicking on a point 248 249 hotkey.session.queue = Shift ; Modifier to queue unit orders instead of replacing 249 250 hotkey.session.batchtrain = Shift ; Modifier to train units in batches 250 251 hotkey.session.massbarter = Shift ; Modifier to barter bunch of resources