Ticket #4098: 4098.3.diff
File 4098.3.diff, 20.5 KB (added by , 7 years ago) |
---|
-
binaries/data/mods/public/simulation/components/UnitAI.js
356 356 // Check if we need to move TODO implement a better way to know if we are on the shoreline 357 357 var needToMove = true; 358 358 var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); 359 if (this.lastShorelinePosition && cmpPosition && (this.lastShorelinePosition.x == cmpPosition.GetPosition().x) 360 && (this.lastShorelinePosition.z == cmpPosition.GetPosition().z)) 359 if (this.lastShorelinePosition && cmpPosition && 360 this.lastShorelinePosition.x == cmpPosition.GetPosition().x && 361 this.lastShorelinePosition.z == cmpPosition.GetPosition().z) 361 362 { 362 363 // we were already on the shoreline, and have not moved since 363 364 if (DistanceBetweenEntities(this.entity, this.order.data.target) < 50) … … 1454 1455 1455 1456 "GuardedAttacked": function(msg) { 1456 1457 // do nothing if we have a forced order in queue before the guard order 1457 for (var i = 0; i < this.orderQueue.length; ++i)1458 for(let order of this.orderQueue) 1458 1459 { 1459 if ( this.orderQueue[i].type == "Guard")1460 if (order.type == "Guard") 1460 1461 break; 1461 if ( this.orderQueue[i].data && this.orderQueue[i].data.force)1462 if (order.data && order.data.force) 1462 1463 return; 1463 1464 } 1464 1465 // if we already are targeting another unit still alive, finish with it first … … 1946 1947 var animationName = "attack_" + this.order.data.attackType.toLowerCase(); 1947 1948 if (this.IsFormationMember()) 1948 1949 { 1949 varcmpFormation = Engine.QueryInterface(this.formationController, IID_Formation);1950 let cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); 1950 1951 if (cmpFormation) 1951 1952 animationName = cmpFormation.GetFormationAnimation(this.entity, animationName); 1952 1953 } … … 2169 2170 2170 2171 // Try to find another nearby target of the same specific type 2171 2172 // Also don't switch to a different type of huntable animal 2172 var nearby = this.FindNearbyResource(function (ent, type, template) { 2173 return ( 2174 ent != oldTarget 2175 && ((type.generic == "treasure" && oldType.generic == "treasure") 2176 || (type.specific == oldType.specific 2177 && (type.specific != "meat" || oldTemplate == template))) 2178 ); 2179 }, oldTarget); 2173 let nearby = this.FindNearbyResource((ent, type, template) => 2174 ent != oldTarget && 2175 (type.generic == "treasure" && oldType.generic == "treasure" || 2176 (type.specific == oldType.specific && 2177 (type.specific != "meat" || oldTemplate == template))), 2178 oldTarget); 2180 2179 if (nearby) 2181 2180 { 2182 2181 this.PerformGather(nearby, false, false); … … 2197 2196 else 2198 2197 { 2199 2198 // we're kind of stuck here. Return resource. 2200 varnearby = this.FindNearestDropsite(oldType.generic);2199 nearby = this.FindNearestDropsite(oldType.generic); 2201 2200 if (nearby) 2202 2201 { 2203 2202 this.PushOrderFront("ReturnResource", { "target": nearby, "force": false }); … … 2234 2233 2235 2234 // Try to find another nearby target of the same specific type 2236 2235 // Also don't switch to a different type of huntable animal 2237 var nearby = this.FindNearbyResource(function (ent, type, template) { 2238 return ( 2239 ent != oldTarget 2240 && ((type.generic == "treasure" && oldType.generic == "treasure") 2241 || (type.specific == oldType.specific 2242 && (type.specific != "meat" || oldTemplate == template))) 2243 ); 2244 }); 2236 let nearby = this.FindNearbyResource((ent, type, template) => 2237 ent != oldTarget && 2238 (type.generic == "treasure" && oldType.generic == "treasure" || 2239 (type.specific == oldType.specific && 2240 (type.specific != "meat" || oldTemplate == template)))); 2245 2241 if (nearby) 2246 2242 { 2247 2243 this.PerformGather(nearby, false, false); … … 2280 2276 2281 2277 // Try to find another nearby target of the same specific type 2282 2278 // Also don't switch to a different type of huntable animal 2283 var nearby = this.FindNearbyResource(function (ent, type, template) { 2284 return ( 2285 (type.generic == "treasure" && resourceType.generic == "treasure") 2286 || (type.specific == resourceType.specific 2287 && (type.specific != "meat" || resourceTemplate == template)) 2288 ); 2289 }); 2279 let nearby = this.FindNearbyResource((ent, type, template) => 2280 (type.generic == "treasure" && resourceType.generic == "treasure") || 2281 (type.specific == resourceType.specific && 2282 (type.specific != "meat" || resourceTemplate == template))); 2290 2283 2291 2284 // If there is a nearby resource start gathering 2292 2285 if (nearby) … … 2300 2293 return; 2301 2294 2302 2295 // Nothing better to do: go back to dropsite 2303 varnearby = this.FindNearestDropsite(resourceType.generic);2296 nearby = this.FindNearestDropsite(resourceType.generic); 2304 2297 if (nearby) 2305 2298 { 2306 2299 this.PushOrderFront("ReturnResource", { "target": nearby, "force": false }); … … 2403 2396 if (this.CheckTargetRange(this.gatheringTarget, IID_ResourceGatherer) && this.CanGather(this.gatheringTarget)) 2404 2397 { 2405 2398 // Gather the resources: 2399 let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); 2406 2400 2407 var cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);2408 2409 2401 // Try to gather treasure 2410 2402 if (cmpResourceGatherer.TryInstantGather(this.gatheringTarget)) 2411 2403 return; … … 2422 2414 // return to the nearest dropsite 2423 2415 if (status.filled) 2424 2416 { 2425 varnearby = this.FindNearestDropsite(resourceType.generic);2417 let nearby = this.FindNearestDropsite(resourceType.generic); 2426 2418 if (nearby) 2427 2419 { 2428 2420 // (Keep this Gather order on the stack so we'll … … 2472 2464 2473 2465 // Give up on this order and try our next queued order 2474 2466 // but first check what is our next order and, if needed, insert a returnResource order 2475 varcmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);2467 let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); 2476 2468 if (cmpResourceGatherer.IsCarrying(resourceType.generic) && 2477 2469 this.orderQueue.length > 1 && this.orderQueue[1] !== "ReturnResource" && 2478 2470 (this.orderQueue[1].type !== "Gather" || this.orderQueue[1].data.type.generic !== resourceType.generic)) … … 2488 2480 2489 2481 // Try to find a new resource of the same specific type near our current position: 2490 2482 // Also don't switch to a different type of huntable animal 2491 var nearby = this.FindNearbyResource(function (ent, type, template) { 2492 return ( 2493 (type.generic == "treasure" && resourceType.generic == "treasure") 2494 || (type.specific == resourceType.specific 2495 && (type.specific != "meat" || resourceTemplate == template)) 2496 ); 2497 }); 2483 let nearby = this.FindNearbyResource((ent, type, template) => 2484 (type.generic == "treasure" && resourceType.generic == "treasure") || 2485 (type.specific == resourceType.specific && 2486 (type.specific != "meat" || resourceTemplate == template))); 2498 2487 if (nearby) 2499 2488 { 2500 2489 this.PerformGather(nearby, false, false); … … 2512 2501 // drop it off, and if not then we might as well head to the dropsite 2513 2502 // anyway because that's a nice enough place to congregate and idle 2514 2503 2515 varnearby = this.FindNearestDropsite(resourceType.generic);2504 nearby = this.FindNearestDropsite(resourceType.generic); 2516 2505 if (nearby) 2517 2506 { 2518 2507 this.PushOrderFront("ReturnResource", { "target": nearby, "force": false }); … … 2680 2669 // Dump any resources we can 2681 2670 var dropsiteTypes = cmpResourceDropsite.GetTypes(); 2682 2671 2683 varcmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);2672 let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); 2684 2673 cmpResourceGatherer.CommitResources(dropsiteTypes); 2685 2674 2686 2675 // Stop showing the carried resource animation. … … 2696 2685 // The dropsite was destroyed, or we couldn't reach it, or ownership changed 2697 2686 // Look for a new one. 2698 2687 2699 varcmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);2688 let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); 2700 2689 var genericType = cmpResourceGatherer.GetMainCarryingType(); 2701 2690 var nearby = this.FindNearestDropsite(genericType); 2702 2691 if (nearby) … … 2891 2880 // the build command should look for nearby resources to gather 2892 2881 if ((oldData.force || oldData.autoharvest) && this.CanReturnResource(msg.data.newentity, false)) 2893 2882 { 2894 varcmpResourceDropsite = Engine.QueryInterface(msg.data.newentity, IID_ResourceDropsite);2895 vartypes = cmpResourceDropsite.GetTypes();2883 cmpResourceDropsite = Engine.QueryInterface(msg.data.newentity, IID_ResourceDropsite); 2884 let types = cmpResourceDropsite.GetTypes(); 2896 2885 // TODO: Slightly undefined behavior here, we don't know what type of resource will be collected, 2897 2886 // may cause problems for AIs (especially hunting fast animals), but avoid ugly hacks to fix that! 2898 var nearby = this.FindNearbyResource(function (ent, type, template) { 2899 return (types.indexOf(type.generic) != -1); 2900 }); 2887 let nearby = this.FindNearbyResource((ent, type, template) => types.indexOf(type.generic) != -1); 2901 2888 if (nearby) 2902 2889 { 2903 2890 this.PerformGather(nearby, true, false); … … 2976 2963 "GARRISONED": { 2977 2964 "enter": function() { 2978 2965 // Target is not handled the same way with Alert and direct garrisoning 2979 if (this.order.data.target) 2980 var target = this.order.data.target; 2981 else 2966 let target = this.order.data.target; 2967 if (!target) 2982 2968 { 2983 2969 if (!this.alertGarrisoningTarget) 2984 2970 { … … 2986 2972 this.FinishOrder(); 2987 2973 return true; 2988 2974 } 2989 vartarget = this.alertGarrisoningTarget;2975 target = this.alertGarrisoningTarget; 2990 2976 } 2991 2977 2992 2978 // Check that we can garrison here … … 3358 3344 3359 3345 UnitAI.prototype.IsUnderAlert = function() 3360 3346 { 3361 return this.alertRaiser != undefined;3347 return this.alertRaiser !== undefined; 3362 3348 }; 3363 3349 3364 3350 UnitAI.prototype.ResetAlert = function() … … 3488 3474 { 3489 3475 // Switch to a virgin state to let states execute their leave handlers. 3490 3476 // except if garrisoned or cheering or (un)packing, in which case we only clear the order queue 3491 if (this.isGarrisoned || (this.orderQueue[0] && (this.orderQueue[0].type == "Cheering" 3492 ||this.orderQueue[0].type == "Pack" || this.orderQueue[0].type == "Unpack")))3477 if (this.isGarrisoned || (this.orderQueue[0] && (this.orderQueue[0].type == "Cheering" || 3478 this.orderQueue[0].type == "Pack" || this.orderQueue[0].type == "Unpack"))) 3493 3479 { 3494 3480 this.orderQueue.length = Math.min(this.orderQueue.length, 1); 3495 3481 Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); … … 3553 3539 { 3554 3540 if (this.orderQueue[i].type != "PickupUnit" || this.orderQueue[i].data.target != msg.entity) 3555 3541 continue; 3556 if (i == 0)3542 if (i === 0) 3557 3543 this.UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg}); 3558 3544 else 3559 3545 this.orderQueue.splice(i, 1); … … 3838 3824 // TODO: maybe a better way of doing this would be to use priority levels 3839 3825 if (this.order && this.order.type == "Cheering") 3840 3826 { 3841 varorder = { "type": type, "data": data };3827 let order = { "type": type, "data": data }; 3842 3828 var cheeringOrder = this.orderQueue.shift(); 3843 3829 this.orderQueue = [cheeringOrder, order]; 3844 3830 } 3845 3831 else if (this.IsPacking() && type != "CancelPack" && type != "CancelUnpack") 3846 3832 { 3847 varorder = { "type": type, "data": data };3833 let order = { "type": type, "data": data }; 3848 3834 var packingOrder = this.orderQueue.shift(); 3849 3835 this.orderQueue = [packingOrder, order]; 3850 3836 } … … 3901 3887 var cmpUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI); 3902 3888 if (cmpUnitAI) 3903 3889 { 3904 for ( vari = 0; i < cmpUnitAI.orderQueue.length; ++i)3890 for (let i = 0; i < cmpUnitAI.orderQueue.length; ++i) 3905 3891 { 3906 3892 if (isWorkType(cmpUnitAI.orderQueue[i].type)) 3907 3893 { … … 3913 3899 } 3914 3900 3915 3901 // If nothing found, take the unit orders 3916 for ( vari = 0; i < this.orderQueue.length; ++i)3902 for (let i = 0; i < this.orderQueue.length; ++i) 3917 3903 { 3918 3904 if (isWorkType(this.orderQueue[i].type)) 3919 3905 { … … 3925 3911 3926 3912 UnitAI.prototype.BackToWork = function() 3927 3913 { 3928 if ( this.workOrders.length == 0)3914 if (!this.workOrders.length) 3929 3915 return false; 3930 3916 3931 3917 // Clear the order queue considering special orders not to avoid … … 4104 4090 return true; 4105 4091 4106 4092 var cmpHealth = QueryMiragedInterface(ent, IID_Health); 4107 return cmpHealth && cmpHealth.GetHitpoints() != 0;4093 return cmpHealth && cmpHealth.GetHitpoints() !== 0; 4108 4094 }; 4109 4095 4110 4096 /** … … 4437 4423 var t = targetCmpPosition.GetPosition(); 4438 4424 // h is positive when I'm higher than the target 4439 4425 var h = s.y-t.y+range.elevationBonus; 4440 4426 let parabolicMaxRange = 0; 4441 4427 // No negative roots please 4442 if (h>-range.max/2) 4443 var parabolicMaxRange = Math.sqrt(range.max*range.max+2*range.max*h); 4444 else 4445 // return false? Or hope you come close enough? 4446 var parabolicMaxRange = 0; 4447 //return false; 4428 if (h > -range.max / 2) 4429 parabolicMaxRange = Math.sqrt(range.max * range.max + 2 * range.max * h); 4448 4430 4449 4431 // the parabole changes while walking, take something in the middle 4450 var guessedMaxRange = (range.max + parabolicMaxRange) /2;4432 var guessedMaxRange = (range.max + parabolicMaxRange) / 2; 4451 4433 4452 4434 var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); 4453 4435 if (cmpUnitMotion.MoveToTargetRange(target, range.min, guessedMaxRange)) … … 4509 4491 if (this.IsFormationMember()) 4510 4492 { 4511 4493 var cmpFormationUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI); 4512 if (cmpFormationUnitAI && cmpFormationUnitAI.IsAttackingAsFormation() 4513 &&cmpFormationUnitAI.order.data.target == target)4494 if (cmpFormationUnitAI && cmpFormationUnitAI.IsAttackingAsFormation() && 4495 cmpFormationUnitAI.order.data.target == target) 4514 4496 return true; 4515 4497 } 4516 4498 … … 4689 4671 UnitAI.prototype.AttackEntityInZone = function(ents, forceResponse) 4690 4672 { 4691 4673 var target = ents.find(target => 4692 this.CanAttack(target, forceResponse) 4693 && this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true))4694 &&(this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target))4674 this.CanAttack(target, forceResponse) && 4675 this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true)) && 4676 (this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target)) 4695 4677 ); 4696 4678 if (!target) 4697 4679 return false; … … 5204 5186 5205 5187 // Remember the position of our target, if any, in case it disappears 5206 5188 // later and we want to head to its last known position 5207 var lastPos = undefined;5189 var lastPos; 5208 5190 var cmpPosition = Engine.QueryInterface(target, IID_Position); 5209 5191 if (cmpPosition && cmpPosition.IsInWorld()) 5210 5192 lastPos = cmpPosition.GetPosition(); … … 5527 5509 { 5528 5510 var cmpUnitAI; 5529 5511 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); 5530 for each (var ent incmpFormation.members)5512 for (let ent of cmpFormation.members) 5531 5513 { 5532 5514 if (!(cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI))) 5533 5515 continue; 5534 vartargets = cmpUnitAI.GetTargetsFromUnit();5535 for ( var targof targets)5516 let targets = cmpUnitAI.GetTargetsFromUnit(); 5517 for (let target of targets) 5536 5518 { 5537 if (!cmpUnitAI.CanAttack(targ ))5519 if (!cmpUnitAI.CanAttack(target)) 5538 5520 continue; 5539 5521 if (this.order.data.targetClasses) 5540 5522 { 5541 var cmpIdentity = Engine.QueryInterface(targ, IID_Identity); 5542 var targetClasses = this.order.data.targetClasses; 5543 if (targetClasses.attack && cmpIdentity 5544 && !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack)) 5523 let cmpIdentity = Engine.QueryInterface(target, IID_Identity); 5524 let targetClasses = this.order.data.targetClasses; 5525 if (targetClasses.attack && cmpIdentity && !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack)) 5545 5526 continue; 5546 if (targetClasses.avoid && cmpIdentity 5547 && MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid)) 5527 if (targetClasses.avoid && cmpIdentity && MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid)) 5548 5528 continue; 5549 5529 // Only used by the AIs to prevent some choices of targets 5550 if (targetClasses.vetoEntities && targetClasses.vetoEntities[targ ])5530 if (targetClasses.vetoEntities && targetClasses.vetoEntities[target]) 5551 5531 continue; 5552 5532 } 5553 this.PushOrderFront("Attack", { "target": targ , "force": true, "allowCapture": true });5533 this.PushOrderFront("Attack", { "target": target, "force": true, "allowCapture": true }); 5554 5534 return true; 5555 5535 } 5556 5536 } … … 5558 5538 } 5559 5539 5560 5540 var targets = this.GetTargetsFromUnit(); 5561 for ( var targof targets)5541 for (let target of targets) 5562 5542 { 5563 if (!this.CanAttack(targ ))5543 if (!this.CanAttack(target)) 5564 5544 continue; 5565 5545 if (this.order.data.targetClasses) 5566 5546 { 5567 var cmpIdentity = Engine.QueryInterface(targ, IID_Identity); 5568 var targetClasses = this.order.data.targetClasses; 5569 if (cmpIdentity && targetClasses.attack 5570 && !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack)) 5547 let cmpIdentity = Engine.QueryInterface(target, IID_Identity); 5548 let targetClasses = this.order.data.targetClasses; 5549 if (cmpIdentity && targetClasses.attack && !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack)) 5571 5550 continue; 5572 if (cmpIdentity && targetClasses.avoid 5573 && MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid)) 5551 if (cmpIdentity && targetClasses.avoid && MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid)) 5574 5552 continue; 5575 5553 // Only used by the AIs to prevent some choices of targets 5576 if (targetClasses.vetoEntities && targetClasses.vetoEntities[targ ])5554 if (targetClasses.vetoEntities && targetClasses.vetoEntities[target]) 5577 5555 continue; 5578 5556 } 5579 this.PushOrderFront("Attack", { "target": targ , "force": true, "allowCapture": true });5557 this.PushOrderFront("Attack", { "target": target, "force": true, "allowCapture": true }); 5580 5558 return true; 5581 5559 } 5582 5560 … … 5633 5611 var ret = { "min": 0, "max": 0 }; 5634 5612 if (this.GetStance().respondStandGround) 5635 5613 { 5636 varcmpRanged = Engine.QueryInterface(this.entity, iid);5614 let cmpRanged = Engine.QueryInterface(this.entity, iid); 5637 5615 if (!cmpRanged) 5638 5616 return ret; 5639 varrange = iid !== IID_Attack ? cmpRanged.GetRange() : cmpRanged.GetFullAttackRange();5617 let range = iid !== IID_Attack ? cmpRanged.GetRange() : cmpRanged.GetFullAttackRange(); 5640 5618 ret.min = range.min; 5641 5619 ret.max = range.max; 5642 5620 } 5643 5621 else if (this.GetStance().respondChase) 5644 5622 { 5645 varcmpVision = Engine.QueryInterface(this.entity, IID_Vision);5623 let cmpVision = Engine.QueryInterface(this.entity, IID_Vision); 5646 5624 if (!cmpVision) 5647 5625 return ret; 5648 var range = cmpVision.GetRange(); 5649 ret.max = range; 5626 ret.max = cmpVision.GetRange(); 5650 5627 } 5651 5628 else if (this.GetStance().respondHoldGround) 5652 5629 { 5653 varcmpRanged = Engine.QueryInterface(this.entity, iid);5630 let cmpRanged = Engine.QueryInterface(this.entity, iid); 5654 5631 if (!cmpRanged) 5655 5632 return ret; 5656 varrange = iid !== IID_Attack ? cmpRanged.GetRange() : cmpRanged.GetFullAttackRange();5657 varcmpVision = Engine.QueryInterface(this.entity, IID_Vision);5633 let range = iid !== IID_Attack ? cmpRanged.GetRange() : cmpRanged.GetFullAttackRange(); 5634 let cmpVision = Engine.QueryInterface(this.entity, IID_Vision); 5658 5635 if (!cmpVision) 5659 5636 return ret; 5660 5637 var halfvision = cmpVision.GetRange() / 2; … … 5664 5641 // but as it is the default for healers we need to set it to something sane. 5665 5642 else if (iid === IID_Heal) 5666 5643 { 5667 varcmpVision = Engine.QueryInterface(this.entity, IID_Vision);5644 let cmpVision = Engine.QueryInterface(this.entity, IID_Vision); 5668 5645 if (!cmpVision) 5669 5646 return ret; 5670 var range = cmpVision.GetRange();5671 ret.max = range;5647 5648 ret.max = cmpVision.GetRange(); 5672 5649 } 5673 5650 return ret; 5674 5651 }; … … 5965 5942 UnitAI.prototype.IsAttackingAsFormation = function() 5966 5943 { 5967 5944 var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); 5968 return cmpAttack && cmpAttack.CanAttackAsFormation() 5945 return cmpAttack && cmpAttack.CanAttackAsFormation() 5969 5946 && this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING"; 5970 5947 }; 5971 5948