Ticket #4098: 4098.diff
File 4098.diff, 19.9 KB (added by , 8 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) … … 1376 1377 1377 1378 "GuardedAttacked": function(msg) { 1378 1379 // do nothing if we have a forced order in queue before the guard order 1379 for ( vari = 0; i < this.orderQueue.length; ++i)1380 for (let i = 0; i < this.orderQueue.length; ++i) 1380 1381 { 1381 1382 if (this.orderQueue[i].type == "Guard") 1382 1383 break; … … 1831 1832 var animationName = "attack_" + this.order.data.attackType.toLowerCase(); 1832 1833 if (this.IsFormationMember()) 1833 1834 { 1834 varcmpFormation = Engine.QueryInterface(this.formationController, IID_Formation);1835 let cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); 1835 1836 if (cmpFormation) 1836 1837 animationName = cmpFormation.GetFormationAnimation(this.entity, animationName); 1837 1838 } … … 2054 2055 2055 2056 // Try to find another nearby target of the same specific type 2056 2057 // Also don't switch to a different type of huntable animal 2057 var nearby = this.FindNearbyResource(function (ent, type, template) { 2058 return ( 2059 ent != oldTarget 2060 && ((type.generic == "treasure" && oldType.generic == "treasure") 2061 || (type.specific == oldType.specific 2062 && (type.specific != "meat" || oldTemplate == template))) 2058 let nearby = this.FindNearbyResource((ent, type, template) => 2059 (ent != oldTarget && 2060 (type.generic == "treasure" && oldType.generic == "treasure" || 2061 (type.specific == oldType.specific && 2062 (type.specific != "meat" || oldTemplate == template))) 2063 2063 ); 2064 2064 }, oldTarget); 2065 2065 if (nearby) … … 2082 2082 else 2083 2083 { 2084 2084 // we're kind of stuck here. Return resource. 2085 varnearby = this.FindNearestDropsite(oldType.generic);2085 nearby = this.FindNearestDropsite(oldType.generic); 2086 2086 if (nearby) 2087 2087 { 2088 2088 this.PushOrderFront("ReturnResource", { "target": nearby, "force": false }); … … 2119 2119 2120 2120 // Try to find another nearby target of the same specific type 2121 2121 // Also don't switch to a different type of huntable animal 2122 var nearby = this.FindNearbyResource(function (ent, type, template) { 2123 return ( 2124 ent != oldTarget 2125 && ((type.generic == "treasure" && oldType.generic == "treasure") 2126 || (type.specific == oldType.specific 2127 && (type.specific != "meat" || oldTemplate == template))) 2122 let nearby = this.FindNearbyResource(function (ent, type, template) { 2123 return (ent != oldTarget && 2124 (type.generic == "treasure" && oldType.generic == "treasure" || 2125 (type.specific == oldType.specific && 2126 (type.specific != "meat" || oldTemplate == template))) 2128 2127 ); 2129 2128 }); 2130 2129 if (nearby) … … 2165 2164 2166 2165 // Try to find another nearby target of the same specific type 2167 2166 // Also don't switch to a different type of huntable animal 2168 varnearby = this.FindNearbyResource(function (ent, type, template) {2167 let nearby = this.FindNearbyResource(function (ent, type, template) { 2169 2168 return ( 2170 (type.generic == "treasure" && resourceType.generic == "treasure") 2171 || (type.specific == resourceType.specific2172 &&(type.specific != "meat" || resourceTemplate == template))2169 (type.generic == "treasure" && resourceType.generic == "treasure") || 2170 (type.specific == resourceType.specific && 2171 (type.specific != "meat" || resourceTemplate == template)) 2173 2172 ); 2174 2173 }); 2175 2174 … … 2185 2184 return; 2186 2185 2187 2186 // Nothing better to do: go back to dropsite 2188 varnearby = this.FindNearestDropsite(resourceType.generic);2187 nearby = this.FindNearestDropsite(resourceType.generic); 2189 2188 if (nearby) 2190 2189 { 2191 2190 this.PushOrderFront("ReturnResource", { "target": nearby, "force": false }); … … 2289 2288 { 2290 2289 // Gather the resources: 2291 2290 2292 varcmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);2291 let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); 2293 2292 2294 2293 // Try to gather treasure 2295 2294 if (cmpResourceGatherer.TryInstantGather(this.gatheringTarget)) … … 2307 2306 // return to the nearest dropsite 2308 2307 if (status.filled) 2309 2308 { 2310 varnearby = this.FindNearestDropsite(resourceType.generic);2309 let nearby = this.FindNearestDropsite(resourceType.generic); 2311 2310 if (nearby) 2312 2311 { 2313 2312 // (Keep this Gather order on the stack so we'll … … 2357 2356 2358 2357 // Give up on this order and try our next queued order 2359 2358 // but first check what is our next order and, if needed, insert a returnResource order 2360 varcmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);2359 let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); 2361 2360 if (cmpResourceGatherer.IsCarrying(resourceType.generic) && 2362 2361 this.orderQueue.length > 1 && this.orderQueue[1] !== "ReturnResource" && 2363 2362 (this.orderQueue[1].type !== "Gather" || this.orderQueue[1].data.type.generic !== resourceType.generic)) … … 2373 2372 2374 2373 // Try to find a new resource of the same specific type near our current position: 2375 2374 // Also don't switch to a different type of huntable animal 2376 varnearby = this.FindNearbyResource(function (ent, type, template) {2377 return ( 2378 (type.generic == "treasure" && resourceType.generic == "treasure")2379 || (type.specific == resourceType.specific2380 &&(type.specific != "meat" || resourceTemplate == template))2375 let nearby = this.FindNearbyResource(function (ent, type, template) { 2376 return ((type.generic == "treasure" && 2377 resourceType.generic == "treasure") || 2378 (type.specific == resourceType.specific && 2379 (type.specific != "meat" || resourceTemplate == template)) 2381 2380 ); 2382 2381 }); 2383 2382 if (nearby) … … 2397 2396 // drop it off, and if not then we might as well head to the dropsite 2398 2397 // anyway because that's a nice enough place to congregate and idle 2399 2398 2400 varnearby = this.FindNearestDropsite(resourceType.generic);2399 nearby = this.FindNearestDropsite(resourceType.generic); 2401 2400 if (nearby) 2402 2401 { 2403 2402 this.PushOrderFront("ReturnResource", { "target": nearby, "force": false }); … … 2565 2564 // Dump any resources we can 2566 2565 var dropsiteTypes = cmpResourceDropsite.GetTypes(); 2567 2566 2568 varcmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);2567 let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); 2569 2568 cmpResourceGatherer.CommitResources(dropsiteTypes); 2570 2569 2571 2570 // Stop showing the carried resource animation. … … 2581 2580 // The dropsite was destroyed, or we couldn't reach it, or ownership changed 2582 2581 // Look for a new one. 2583 2582 2584 varcmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);2583 let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); 2585 2584 var genericType = cmpResourceGatherer.GetMainCarryingType(); 2586 2585 var nearby = this.FindNearestDropsite(genericType); 2587 2586 if (nearby) … … 2776 2775 // the build command should look for nearby resources to gather 2777 2776 if ((oldData.force || oldData.autoharvest) && this.CanReturnResource(msg.data.newentity, false)) 2778 2777 { 2779 varcmpResourceDropsite = Engine.QueryInterface(msg.data.newentity, IID_ResourceDropsite);2778 cmpResourceDropsite = Engine.QueryInterface(msg.data.newentity, IID_ResourceDropsite); 2780 2779 var types = cmpResourceDropsite.GetTypes(); 2781 2780 // TODO: Slightly undefined behavior here, we don't know what type of resource will be collected, 2782 2781 // may cause problems for AIs (especially hunting fast animals), but avoid ugly hacks to fix that! … … 2861 2860 "GARRISONED": { 2862 2861 "enter": function() { 2863 2862 // Target is not handled the same way with Alert and direct garrisoning 2864 if (this.order.data.target) 2865 var target = this.order.data.target; 2866 else 2863 var target = this.order.data.target; 2864 if (!target) 2867 2865 { 2868 2866 if (!this.alertGarrisoningTarget) 2869 2867 { … … 2871 2869 this.FinishOrder(); 2872 2870 return true; 2873 2871 } 2874 vartarget = this.alertGarrisoningTarget;2872 target = this.alertGarrisoningTarget; 2875 2873 } 2876 2874 2877 2875 // Check that we can garrison here … … 3243 3241 3244 3242 UnitAI.prototype.IsUnderAlert = function() 3245 3243 { 3246 return this.alertRaiser != undefined;3244 return this.alertRaiser !== undefined; 3247 3245 }; 3248 3246 3249 3247 UnitAI.prototype.ResetAlert = function() … … 3367 3365 { 3368 3366 // Switch to a virgin state to let states execute their leave handlers. 3369 3367 // except if garrisoned or cheering or (un)packing, in which case we only clear the order queue 3370 if (this.isGarrisoned || (this.orderQueue[0] && (this.orderQueue[0].type == "Cheering" 3371 ||this.orderQueue[0].type == "Pack" || this.orderQueue[0].type == "Unpack")))3368 if (this.isGarrisoned || (this.orderQueue[0] && (this.orderQueue[0].type == "Cheering" || 3369 this.orderQueue[0].type == "Pack" || this.orderQueue[0].type == "Unpack"))) 3372 3370 { 3373 3371 this.orderQueue.length = Math.min(this.orderQueue.length, 1); 3374 3372 Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); … … 3427 3425 { 3428 3426 if (this.orderQueue[i].type != "PickupUnit" || this.orderQueue[i].data.target != msg.entity) 3429 3427 continue; 3430 if (i == 0)3428 if (i === 0) 3431 3429 this.UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg}); 3432 3430 else 3433 3431 this.orderQueue.splice(i, 1); … … 3729 3727 // TODO: maybe a better way of doing this would be to use priority levels 3730 3728 if (this.order && this.order.type == "Cheering") 3731 3729 { 3732 varorder = { "type": type, "data": data };3730 let order = { "type": type, "data": data }; 3733 3731 var cheeringOrder = this.orderQueue.shift(); 3734 3732 this.orderQueue = [cheeringOrder, order]; 3735 3733 } 3736 3734 else if (this.IsPacking() && type != "CancelPack" && type != "CancelUnpack") 3737 3735 { 3738 varorder = { "type": type, "data": data };3736 let order = { "type": type, "data": data }; 3739 3737 var packingOrder = this.orderQueue.shift(); 3740 3738 this.orderQueue = [packingOrder, order]; 3741 3739 } … … 3792 3790 var cmpUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI); 3793 3791 if (cmpUnitAI) 3794 3792 { 3795 for ( vari = 0; i < cmpUnitAI.orderQueue.length; ++i)3793 for (let i = 0; i < cmpUnitAI.orderQueue.length; ++i) 3796 3794 { 3797 3795 if (isWorkType(cmpUnitAI.orderQueue[i].type)) 3798 3796 { … … 3804 3802 } 3805 3803 3806 3804 // If nothing found, take the unit orders 3807 for ( vari = 0; i < this.orderQueue.length; ++i)3805 for (let i = 0; i < this.orderQueue.length; ++i) 3808 3806 { 3809 3807 if (isWorkType(this.orderQueue[i].type)) 3810 3808 { … … 3816 3814 3817 3815 UnitAI.prototype.BackToWork = function() 3818 3816 { 3819 if ( this.workOrders.length == 0)3817 if (!this.workOrders.length) 3820 3818 return false; 3821 3819 3822 3820 // Clear the order queue considering special orders not to avoid … … 3998 3996 return true; 3999 3997 4000 3998 var cmpHealth = QueryMiragedInterface(ent, IID_Health); 4001 return cmpHealth && cmpHealth.GetHitpoints() != 0;3999 return cmpHealth && cmpHealth.GetHitpoints() !== 0; 4002 4000 }; 4003 4001 4004 4002 /** … … 4336 4334 var t = targetCmpPosition.GetPosition(); 4337 4335 // h is positive when I'm higher than the target 4338 4336 var h = s.y-t.y+range.elevationBonus; 4339 4337 let parabolicMaxRange = 0; 4340 4338 // No negative roots please 4341 if (h>-range.max/2) 4342 var parabolicMaxRange = Math.sqrt(range.max*range.max+2*range.max*h); 4343 else 4344 // return false? Or hope you come close enough? 4345 var parabolicMaxRange = 0; 4346 //return false; 4339 if (h > - range.max / 2) 4340 parabolicMaxRange = Math.sqrt(range.max*range.max+2*range.max*h); 4347 4341 4348 4342 // the parabole changes while walking, take something in the middle 4349 4343 var guessedMaxRange = (range.max + parabolicMaxRange)/2; … … 4408 4402 if (this.IsFormationMember()) 4409 4403 { 4410 4404 var cmpFormationUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI); 4411 if (cmpFormationUnitAI && cmpFormationUnitAI.IsAttackingAsFormation() 4412 && cmpFormationUnitAI.order.data.target == target) 4405 if (cmpFormationUnitAI && cmpFormationUnitAI.IsAttackingAsFormation() && cmpFormationUnitAI.order.data.target == target) 4413 4406 return true; 4414 4407 } 4415 4408 … … 4588 4581 UnitAI.prototype.AttackEntityInZone = function(ents, forceResponse) 4589 4582 { 4590 4583 var target = ents.find(target => 4591 this.CanAttack(target, forceResponse) 4592 && this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true))4593 &&(this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target))4584 this.CanAttack(target, forceResponse) && 4585 this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true)) && 4586 (this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target)) 4594 4587 ); 4595 4588 if (!target) 4596 4589 return false; … … 5098 5091 5099 5092 // Remember the position of our target, if any, in case it disappears 5100 5093 // later and we want to head to its last known position 5101 var lastPos = undefined;5094 var lastPos; 5102 5095 var cmpPosition = Engine.QueryInterface(target, IID_Position); 5103 5096 if (cmpPosition && cmpPosition.IsInWorld()) 5104 5097 lastPos = cmpPosition.GetPosition(); … … 5223 5216 this.order.data.target = newMarket; 5224 5217 }; 5225 5218 5226 UnitAI.prototype.MoveToMarket = function(targetMarket) 5227 { 5228 if (this.waypoints && this.waypoints.length > 1) 5229 { 5230 var point = this.waypoints.pop(); 5231 var ok = this.MoveToPoint(point.x, point.z); 5232 if (!ok) 5233 ok = this.MoveToMarket(targetMarket); 5234 } 5235 else 5236 { 5237 this.waypoints = undefined; 5238 var ok = this.MoveToTarget(targetMarket); 5239 } 5219 e 5240 5220 5241 return ok;5242 };5243 5244 5221 UnitAI.prototype.PerformTradeAndMoveToNextMarket = function(currentMarket) 5245 5222 { 5246 5223 if (!this.CanTrade(currentMarket)) … … 5427 5404 { 5428 5405 var cmpUnitAI; 5429 5406 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); 5430 for each (var ent incmpFormation.members)5407 for (let ent of cmpFormation.members) 5431 5408 { 5432 5409 if (!(cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI))) 5433 5410 continue; 5434 vartargets = cmpUnitAI.GetTargetsFromUnit();5435 for ( var targof targets)5411 let targets = cmpUnitAI.GetTargetsFromUnit(); 5412 for (let target of targets) 5436 5413 { 5437 if (!cmpUnitAI.CanAttack(targ ))5414 if (!cmpUnitAI.CanAttack(target)) 5438 5415 continue; 5439 5416 if (this.order.data.targetClasses) 5440 5417 { 5441 var cmpIdentity = Engine.QueryInterface(targ, IID_Identity); 5442 var targetClasses = this.order.data.targetClasses; 5443 if (targetClasses.attack && cmpIdentity 5444 && !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack)) 5418 var cmpIdentity = Engine.QueryInterface(target, IID_Identity); 5419 let targetClasses = this.order.data.targetClasses; 5420 if (targetClasses.attack && cmpIdentity && !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack)) 5445 5421 continue; 5446 if (targetClasses.avoid && cmpIdentity 5447 && MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid)) 5422 if (targetClasses.avoid && cmpIdentity && MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid)) 5448 5423 continue; 5449 5424 // Only used by the AIs to prevent some choices of targets 5450 if (targetClasses.vetoEntities && targetClasses.vetoEntities[targ ])5425 if (targetClasses.vetoEntities && targetClasses.vetoEntities[target]) 5451 5426 continue; 5452 5427 } 5453 this.PushOrderFront("Attack", { "target": targ , "force": true, "allowCapture": true });5428 this.PushOrderFront("Attack", { "target": target, "force": true, "allowCapture": true }); 5454 5429 return true; 5455 5430 } 5456 5431 } … … 5458 5433 } 5459 5434 5460 5435 var targets = this.GetTargetsFromUnit(); 5461 for ( var targof targets)5436 for (let target of targets) 5462 5437 { 5463 if (!this.CanAttack(targ ))5438 if (!this.CanAttack(target)) 5464 5439 continue; 5465 5440 if (this.order.data.targetClasses) 5466 5441 { 5467 var cmpIdentity = Engine.QueryInterface(targ, IID_Identity); 5468 var targetClasses = this.order.data.targetClasses; 5469 if (cmpIdentity && targetClasses.attack 5470 && !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack)) 5442 let cmpIdentity = Engine.QueryInterface(target, IID_Identity); 5443 let targetClasses = this.order.data.targetClasses; 5444 if (cmpIdentity && targetClasses.attack && !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack)) 5471 5445 continue; 5472 if (cmpIdentity && targetClasses.avoid 5473 && MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid)) 5446 if (cmpIdentity && targetClasses.avoid && MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid)) 5474 5447 continue; 5475 5448 // Only used by the AIs to prevent some choices of targets 5476 if (targetClasses.vetoEntities && targetClasses.vetoEntities[targ ])5449 if (targetClasses.vetoEntities && targetClasses.vetoEntities[target]) 5477 5450 continue; 5478 5451 } 5479 this.PushOrderFront("Attack", { "target": targ , "force": true, "allowCapture": true });5452 this.PushOrderFront("Attack", { "target": target, "force": true, "allowCapture": true }); 5480 5453 return true; 5481 5454 } 5482 5455 … … 5533 5506 var ret = { "min": 0, "max": 0 }; 5534 5507 if (this.GetStance().respondStandGround) 5535 5508 { 5536 varcmpRanged = Engine.QueryInterface(this.entity, iid);5509 let cmpRanged = Engine.QueryInterface(this.entity, iid); 5537 5510 if (!cmpRanged) 5538 5511 return ret; 5539 varrange = iid !== IID_Attack ? cmpRanged.GetRange() : cmpRanged.GetFullAttackRange();5512 let range = iid !== IID_Attack ? cmpRanged.GetRange() : cmpRanged.GetFullAttackRange(); 5540 5513 ret.min = range.min; 5541 5514 ret.max = range.max; 5542 5515 } 5543 5516 else if (this.GetStance().respondChase) 5544 5517 { 5545 varcmpVision = Engine.QueryInterface(this.entity, IID_Vision);5518 let cmpVision = Engine.QueryInterface(this.entity, IID_Vision); 5546 5519 if (!cmpVision) 5547 5520 return ret; 5548 varrange = cmpVision.GetRange();5521 let range = cmpVision.GetRange(); 5549 5522 ret.max = range; 5550 5523 } 5551 5524 else if (this.GetStance().respondHoldGround) 5552 5525 { 5553 varcmpRanged = Engine.QueryInterface(this.entity, iid);5526 let cmpRanged = Engine.QueryInterface(this.entity, iid); 5554 5527 if (!cmpRanged) 5555 5528 return ret; 5556 varrange = iid !== IID_Attack ? cmpRanged.GetRange() : cmpRanged.GetFullAttackRange();5557 varcmpVision = Engine.QueryInterface(this.entity, IID_Vision);5529 let range = iid !== IID_Attack ? cmpRanged.GetRange() : cmpRanged.GetFullAttackRange(); 5530 let cmpVision = Engine.QueryInterface(this.entity, IID_Vision); 5558 5531 if (!cmpVision) 5559 5532 return ret; 5560 5533 var halfvision = cmpVision.GetRange() / 2; … … 5564 5537 // but as it is the default for healers we need to set it to something sane. 5565 5538 else if (iid === IID_Heal) 5566 5539 { 5567 varcmpVision = Engine.QueryInterface(this.entity, IID_Vision);5540 let cmpVision = Engine.QueryInterface(this.entity, IID_Vision); 5568 5541 if (!cmpVision) 5569 5542 return ret; 5570 var range = cmpVision.GetRange();5571 ret.max = range;5543 5544 ret.max = cmpVision.GetRange(); 5572 5545 } 5573 5546 return ret; 5574 5547 }; … … 5865 5838 UnitAI.prototype.IsAttackingAsFormation = function() 5866 5839 { 5867 5840 var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); 5868 return cmpAttack && cmpAttack.CanAttackAsFormation() 5869 && this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING"; 5841 return cmpAttack && cmpAttack.CanAttackAsFormation() && this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING"; 5870 5842 }; 5871 5843 5872 5844 //// Animal specific functions ////