Ticket #1847: attack-move-v4.diff
File attack-move-v4.diff, 8.2 KB (added by , 11 years ago) |
---|
-
binaries/data/mods/public/simulation/components/UnitAI.js
288 288 return; 289 289 } 290 290 291 this. SetHeldPosition(this.order.data.x, this.order.data.z);291 this.ResetHeldPosition(); 292 292 this.MoveToPoint(this.order.data.x, this.order.data.z); 293 293 if (this.IsAnimal()) 294 294 this.SetNextState("ANIMAL.WALKING"); // WalkAndFight not applicable for animals … … 660 660 661 661 "Order.WalkAndFight": function(msg) { 662 662 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); 663 cmpFormation.CallMemberFunction(" SetHeldPosition", [msg.data.x, msg.data.z]);663 cmpFormation.CallMemberFunction("ResetHeldPosition", []); 664 664 665 665 this.MoveToPoint(this.order.data.x, this.order.data.z); 666 666 this.SetNextState("WALKINGANDFIGHTING"); … … 924 924 925 925 "WALKINGANDFIGHTING": { 926 926 "enter": function(msg) { 927 this.StartTimer(0, 1000); 927 this.StartTimer(1000, 1000); 928 this.FormationFindNewTargets(); 928 929 }, 929 930 930 931 "Timer": function(msg) { 931 // check if there are no enemies 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 } 932 // check if there are no ennemies to attack 933 this.FormationFindNewTargets(); 947 934 }, 948 935 949 936 "leave": function(msg) { … … 1017 1004 1018 1005 // Have all members finished the task? 1019 1006 if (!cmpFormation.TestAllMemberFunction("HasFinishedOrder", [])) 1007 { 1008 // If in WalkAndFight and some units are not fighting, send them back to fight 1009 if (this.IsInWalkAndFight()) 1010 cmpFormation.CallMemberFunction("SendBackToFight", []); 1020 1011 return; 1012 } 1021 1013 1022 1014 cmpFormation.CallMemberFunction("ResetFinishOrder", []); 1023 1015 1016 // If in WalkAndFight, no more units fighting, will resume the walk 1017 // but we must first duplicate the order, because FinishOrder will remove it 1018 if (this.IsInWalkAndFight()) 1019 this.PushOrderFront(this.orderQueue[0].type, this.orderQueue[0].data); 1020 1024 1021 // Execute the next order 1025 1022 if (this.FinishOrder()) 1026 {1027 // if WalkAndFight order, look for new target before moving again1028 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 }1045 1023 return; 1046 }1047 1024 1048 1025 // No more order left. 1049 1026 cmpFormation.Disband(); … … 1253 1230 1254 1231 "WALKINGANDFIGHTING": { 1255 1232 "enter": function () { 1256 this.StartTimer( 0, 1000);1233 this.StartTimer(1000, 1000); 1257 1234 this.SelectAnimation("move"); 1235 this.FindNewTargets(); 1258 1236 }, 1259 1237 1260 1238 "Timer": function(msg) { … … 1459 1437 } 1460 1438 1461 1439 // Can't reach it, no longer owned by enemy, or it doesn't exist any more - give up 1440 1462 1441 // Except if in WalkAndFight mode where we look for more ennemies around before moving again 1463 if (this.FinishOrder()) 1442 // but we should take care that the new target is in order 0 while the old target was order 1 1443 // so we must exchange them before FinishOrder 1444 1445 if (this.IsInWalkAndFight()) 1464 1446 { 1465 if (this.orderQueue.length > 0 && this.orderQueue[0].type == "WalkAndFight") 1466 this.FindNewTargets(); 1467 return; 1447 if (this.FindNewTargets()) 1448 this.orderQueue[1].data = this.orderQueue[0].data; 1449 else if(this.GetTargetFromFormation()) 1450 this.orderQueue[1].data = this.orderQueue[0].data; 1468 1451 } 1469 1452 1453 if (this.FinishOrder()) 1454 return; 1455 1470 1456 // See if we can switch to a new nearby enemy 1471 1457 if (this.FindNewTargets()) 1472 1458 { … … 2712 2698 // if there are still queued formation orders left 2713 2699 if (cmpUnitAI.GetOrders().length > 1) 2714 2700 return true; 2701 // length = 1 for WalkAndFight, but we still want to return true 2702 if (cmpUnitAI.IsInWalkAndFight()) 2703 return true; 2715 2704 } 2716 2705 } 2717 2706 … … 3485 3474 return false; 3486 3475 }; 3487 3476 3477 /** 3478 * Returns true if we are in WalkAndFight mode (which induces some change in Attack orders). 3479 */ 3480 UnitAI.prototype.IsInWalkAndFight = function() 3481 { 3482 if (this.IsFormationMember()) 3483 { 3484 var cmpUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI); 3485 if (cmpUnitAI && cmpUnitAI.orderQueue[0] && cmpUnitAI.orderQueue[0].type == "WalkAndFight") 3486 return true; 3487 } 3488 else 3489 { 3490 if (this.orderQueue[0] && this.orderQueue[0].type == "WalkAndFight") 3491 return true; 3492 if (this.orderQueue[1] && this.orderQueue[1].type == "WalkAndFight" && this.orderQueue[0].type == "Attack") 3493 return true; 3494 } 3495 return false; 3496 }; 3497 3488 3498 //// External interface functions //// 3489 3499 3490 3500 UnitAI.prototype.SetFormationController = function(ent) … … 4078 4088 this.heldPosition = {"x": x, "z": z}; 4079 4089 }; 4080 4090 4091 UnitAI.prototype.ResetHeldPosition = function(x, z) 4092 { 4093 this.heldPosition = undefined; 4094 }; 4095 4081 4096 UnitAI.prototype.GetHeldPosition = function(pos) 4082 4097 { 4083 4098 return this.heldPosition; … … 4323 4338 return (cmpPack && cmpPack.IsPacking()); 4324 4339 }; 4325 4340 4341 UnitAI.prototype.GetTargetFromFormation = function() 4342 { 4343 if (!this.IsFormationMember()) 4344 return false; 4345 var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); 4346 if (!cmpAttack) 4347 return false; 4348 var targetlist = []; 4349 var cmpUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI); 4350 var cmpFormation = Engine.QueryInterface(cmpUnitAI.entity, IID_Formation); 4351 for each (var ent in cmpFormation.members) 4352 { 4353 var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); 4354 var targetfound = undefined; 4355 var order = cmpUnitAI.orderQueue[0]; 4356 if(order && order.type == "Attack") 4357 targetfound = order.data.target; 4358 if (targetfound && this.TargetIsAlive(targetfound) && targetlist.indexOf(targetfound) == -1) 4359 targetlist.push(targetfound); 4360 } 4361 if (targetlist.length == 0) 4362 return false; 4363 var ents = targetlist.filter(function (v, i, a) { return cmpAttack.CanAttack(v); }) 4364 .sort(function (a, b) { return cmpAttack.CompareEntitiesByPreference(a, b); }) 4365 if (this.AttackVisibleEntity(ents, true)) 4366 return true; 4367 return false; 4368 }; 4369 4370 UnitAI.prototype.SendBackToFight = function() 4371 { 4372 if (!this.HasFinishedOrder()) 4373 return; 4374 if (this.GetTargetFromFormation()) 4375 this.finishedOrder = false; 4376 }; 4377 4378 UnitAI.prototype.FormationFindNewTargets = function() 4379 { 4380 var targetlist = []; 4381 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); 4382 for each (var ent in cmpFormation.members) 4383 { 4384 var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); 4385 var targetfound = undefined; 4386 if (cmpUnitAI.FindNewTargets()) 4387 targetfound = cmpUnitAI.orderQueue[0].data.target; 4388 if (targetfound && targetlist.indexOf(targetfound) == -1) 4389 targetlist.push(targetfound); 4390 } 4391 if (targetlist.length > 0) 4392 { 4393 // Reaffect units which have not already found a target 4394 for each (var ent in cmpFormation.members) 4395 { 4396 var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); 4397 if (!cmpUnitAI.orderQueue[0] || cmpUnitAI.orderQueue[0].type != "Attack") 4398 cmpUnitAI.AttackVisibleEntity(targetlist, true); 4399 } 4400 // We don't want to rearrange the formation if the individual units are attacking 4401 cmpFormation.SetRearrange(false); 4402 this.SetNextStateAlwaysEntering("MEMBER"); 4403 } 4404 return (targetlist.length > 0); 4405 }; 4406 4326 4407 //// Animal specific functions //// 4327 4408 4328 4409 UnitAI.prototype.MoveRandomly = function(distance)