Ticket #3488: 3488.16.diff
File 3488.16.diff, 14.6 KB (added by , 7 years ago) |
---|
-
binaries/data/mods/public/simulation/components/BuildingAI.js
37 37 for (let ent of msg.added) 38 38 { 39 39 let cmpIdentity = Engine.QueryInterface(ent, IID_Identity); 40 if ( !cmpIdentity)40 if (msg.visible[ent] || !cmpIdentity) 41 41 continue; 42 42 if (MatchesClassList(cmpIdentity.GetClassesList(), classes)) 43 43 ++this.archersGarrisoned; … … 46 46 for (let ent of msg.removed) 47 47 { 48 48 let cmpIdentity = Engine.QueryInterface(ent, IID_Identity); 49 if ( !cmpIdentity)49 if (msg.visible[ent] || !cmpIdentity) 50 50 continue; 51 51 if (MatchesClassList(cmpIdentity.GetClassesList(), classes)) 52 52 --this.archersGarrisoned; -
binaries/data/mods/public/simulation/components/GarrisonHolder.js
1 /** 2 * @class Defines an entity's ability to garrison units. 3 */ 1 4 function GarrisonHolder() {} 2 5 3 6 GarrisonHolder.prototype.Schema = … … 45 48 "<element name='Z'>" + 46 49 "<data type='decimal'/>" + 47 50 "</element>" + 51 "<element name='VisibleGarrisonAllowedClasses'>" + 52 "<attribute name='datatype'>" + 53 "<value>tokens</value>" + 54 "</attribute>" + 55 "<text/>" + 56 "</element>" + 48 57 "</interleave>" + 49 58 "</element>" + 50 59 "</zeroOrMore>" + … … 72 81 o.x = +offset.X; 73 82 o.y = +offset.Y; 74 83 o.z = +offset.Z; 75 this.visibleGarrisonPoints.push({ "offset":o, "entity": null});84 this.visibleGarrisonPoints.push({ "offset": o, "entity": null, "allowedClass": offset.VisibleGarrisonAllowedClasses }); 76 85 } 77 86 } 78 87 }; … … 100 109 return IsOwnedByPlayer(player, ent); 101 110 }; 102 111 103 104 112 /** 105 113 * Return the list of entities garrisoned inside 106 114 */ … … 204 212 }; 205 213 206 214 /** 215 * Returns true if the unit is allowed be visible on that garrison point, false otherwise. 216 */ 217 GarrisonHolder.prototype.AllowedToVisibleGarrisoning = function(visibleGarrisonPoint, entity) 218 { 219 return MatchesClassList(Engine.QueryInterface(entity, IID_Identity).GetClassesList(), visibleGarrisonPoint.allowedClass._string); 220 }; 221 222 /** 207 223 * Garrison a unit inside. 208 224 * Returns true if successful, false if not 209 225 * The timer for AutoHeal is started here … … 225 241 { 226 242 if (vgp.entity) 227 243 continue; 228 visibleGarrisonPoint = vgp; 229 break; 244 if (this.AllowedToVisibleGarrisoning(vgp, entity)) 245 { 246 visibleGarrisonPoint = vgp; 247 break; 248 } 230 249 } 231 250 } 232 233 if (visibleGarrisonPoint) 251 if (visibleGarrisonPoint && this.AllowedToVisibleGarrisoning(visibleGarrisonPoint, entity)) 234 252 { 235 253 visibleGarrisonPoint.entity = entity; 236 254 cmpPosition.SetTurretParent(this.entity, visibleGarrisonPoint.offset); … … 241 259 else 242 260 cmpPosition.MoveOutOfWorld(); 243 261 262 let visible = {}; 263 visible[entity] = this.IsVisiblyGarrisoned(entity); 264 // Should only be called after the garrison has been performed else the visible Garrison Points are not updated yet. 265 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { 266 "added": [entity], 267 "removed": [], 268 "visible": visible 269 }); 244 270 return true; 245 271 }; 246 272 273 /** 274 * Garrison units inside the entity 275 * @return true if successful, false if not 276 */ 247 277 GarrisonHolder.prototype.PerformGarrison = function(entity) 248 278 { 249 279 if (!this.HasEnoughHealth()) … … 250 280 return false; 251 281 252 282 // Check if the unit is allowed to be garrisoned inside the building 253 if (!this.AllowedToGarrison(entity))283 if (!this.AllowedToGarrison(entity)) 254 284 return false; 255 285 256 // check the capacity286 // Check the capacity 257 287 var extraCount = 0; 258 288 var cmpGarrisonHolder = Engine.QueryInterface(entity, IID_GarrisonHolder); 259 289 if (cmpGarrisonHolder) … … 278 308 if (cmpAura && cmpAura.HasGarrisonAura()) 279 309 cmpAura.ApplyGarrisonBonus(this.entity); 280 310 281 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [entity], "removed": [] });282 283 311 var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI); 284 312 if (cmpUnitAI && cmpUnitAI.IsUnderAlert()) 285 313 Engine.PostMessage(cmpUnitAI.GetAlertRaiser(), MT_UnitGarrisonedAfterAlert, {"holder": this.entity, "unit": entity}); … … 326 354 327 355 var cmpNewPosition = Engine.QueryInterface(entity, IID_Position); 328 356 this.entities.splice(entityIndex, 1); 329 357 358 let visible = {}; 359 visible[entity] = this.IsVisiblyGarrisoned(entity); 360 // Should only be called before the ejection has been performed else the visible Garrison Points will be empty. 361 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { 362 "added": [], 363 "removed": [entity], 364 "visible": visible 365 }); 330 366 for (var vgp of this.visibleGarrisonPoints) 331 367 { 332 368 if (vgp.entity != entity) … … 356 392 cmpNewPosition.SetHeightOffset(0); 357 393 // TODO: what direction should they face in? 358 394 359 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [entity] });360 395 361 396 return true; 362 397 }; … … 454 489 */ 455 490 GarrisonHolder.prototype.UnloadTemplate = function(extendedTemplate, all, forced) 456 491 { 457 varindex = extendedTemplate.indexOf("&");492 let index = extendedTemplate.indexOf("&"); 458 493 if (index == -1) 459 494 return false; 460 495 461 var owner = +extendedTemplate.slice(1,index); 462 var template = extendedTemplate.slice(index+1); 496 let entities = []; 497 let visibleEntities = []; 498 let entitiesMatching = []; 499 let entitiesNotOwned = []; 500 let entitiesNotMatchingName = []; 501 let owner = +extendedTemplate.slice(1, index); 502 let template = extendedTemplate.slice(index + 1); 503 let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); 463 504 464 var entities = []; 465 var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); 466 for each (var entity in this.entities) 467 { 468 var cmpIdentity = Engine.QueryInterface(entity, IID_Identity); 505 entitiesNotOwned= this.entities.filter(e => Engine.QueryInterface(e, IID_Ownership).GetOwner() != owner); 506 entitiesNotMatchingName = this.entities.filter(e => (Engine.QueryInterface(e, IID_Identity).GetSelectionGroupName() || cmpTemplateManager.GetCurrentTemplateName(e)) != template); 469 507 470 // Units with multiple ranks are grouped together.471 var name = cmpIdentity.GetSelectionGroupName()472 || cmpTemplateManager.GetCurrentTemplateName(entity);508 for (let entity of this.entities) 509 if(!entitiesNotOwned.some(e=> e == entity) && ! entitiesNotMatchingName.some(e=> e == entity)) 510 entitiesMatching.push(entity); 473 511 474 if (name != template) 475 continue; 476 if (owner != Engine.QueryInterface(entity, IID_Ownership).GetOwner()) 477 continue; 512 for (let entity of entitiesMatching) 513 { 514 if (this.IsVisiblyGarrisoned(entity)) 515 visibleEntities.push(entity); 516 else 517 entities.push(entity); 478 518 479 entities.push(entity); 519 // If 'all' is false, only ungarrison the first matched unit and if possible, one that 's not visible. 520 if (!all) 521 { 522 if (!entities.length) 523 { 524 if (entitiesMatching.length !== visibleEntities.length) 525 continue; 480 526 481 // If 'all' is false, only ungarrison the first matched unit. 482 if (!all) 527 if (visibleEntities.length) 528 entities.push(visibleEntities[0]); 529 } 483 530 break; 531 } 484 532 } 485 533 if (all) 534 entities.push.apply(entities,visibleEntities); 486 535 return this.PerformEject(entities, forced); 487 536 }; 488 537 … … 607 656 } 608 657 609 658 // or on some of its garrisoned units 610 varentityIndex = this.entities.indexOf(msg.entity);659 let entityIndex = this.entities.indexOf(msg.entity); 611 660 if (entityIndex != -1) 612 661 { 613 662 // If the entity is dead, remove it directly instead of ejecting the corpse 614 varcmpHealth = Engine.QueryInterface(msg.entity, IID_Health);663 let cmpHealth = Engine.QueryInterface(msg.entity, IID_Health); 615 664 if (cmpHealth && cmpHealth.GetHitpoints() == 0) 616 665 { 617 666 this.entities.splice(entityIndex, 1); 618 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [msg.entity] }); 667 let visible = {}; 668 visible[msg.entity] = this.IsVisiblyGarrisoned(msg.entity); 669 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { 670 "added": [], 671 "removed": [msg.entity], 672 "visible": visible 673 }); 619 674 this.UpdateGarrisonFlag(); 620 675 621 676 for (var pt of this.visibleGarrisonPoints) … … 629 684 630 685 /** 631 686 * Update list of garrisoned entities if one gets renamed (e.g. by promotion) 687 * vgpEntity is only defined in some peculiar case where we want to reuse the same visibleGarrisonPoint, 688 * in case of promotion for example, and thus should always be allowed. 632 689 */ 633 690 GarrisonHolder.prototype.OnGlobalEntityRenamed = function(msg) 634 691 { … … 665 722 } 666 723 }; 667 724 668 669 725 /** 670 726 * Eject all foreign garrisoned entities which are no more allied 671 727 */ … … 682 738 GarrisonHolder.prototype.EjectOrKill = function(entities) 683 739 { 684 740 var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); 685 // Eject the units which can be ejected (if not in world, it generallymeans this holder741 // Eject the units which can be ejected (if not in world, it often means this holder 686 742 // is inside a holder which kills its entities, so do not eject) 687 743 if (cmpPosition.IsInWorld()) 688 744 { … … 705 761 this.entities.splice(entityIndex, 1); 706 762 killedEntities.push(entity); 707 763 } 708 709 764 if (killedEntities.length > 0) 710 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed" : killedEntities }); 765 { 766 let visibleEntitiesIds = {}; 767 for (let ent of killedEntities) 768 visibleEntitiesIds[ent] = this.IsVisiblyGarrisoned(ent); 769 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { 770 "added": [], 771 "removed": killedEntities, 772 "visible": visibleEntitiesIds 773 }); 774 } 711 775 this.UpdateGarrisonFlag(); 712 776 }; 713 777 714 778 /** 779 * Gives insight about the unit type of garrisoning. 780 * @return{bool} returns true if the unit is visible on the structure 781 * @param {int} the entity's id 782 */ 783 GarrisonHolder.prototype.IsVisiblyGarrisoned = function(entity) 784 { 785 return this.visibleGarrisonPoints.some(point => point.entity == entity); 786 }; 787 788 /** 715 789 * Checks if an entity is ejectable on destroy if possible 716 790 */ 717 791 GarrisonHolder.prototype.IsEjectable = function(entity) -
binaries/data/mods/public/simulation/templates/structures/maur_fortress.xml
5 5 <SpecificName>Durg</SpecificName> 6 6 <Tooltip>Train heroes and champion units.</Tooltip> 7 7 </Identity> 8 <GarrisonHolder> 9 <Max>150</Max> 10 <List datatype="tokens"> 11 Ranged 12 Infantry 13 Cavalry 14 Elephant 15 Ranged 16 Catapult 17 </List> 18 <EjectHealth>0.1</EjectHealth> 19 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 20 <BuffHeal>0</BuffHeal> 21 <LoadingRange>2</LoadingRange> 22 <VisibleGarrisonPoints> 23 <Archer1> 24 <X>10.5</X><Y>13.75</Y><Z>-9.5</Z> 25 <VisibleGarrisonAllowedClasses datatype="tokens"> 26 Infantry+Ranged 27 </VisibleGarrisonAllowedClasses> 28 </Archer1> 29 <Archer2> 30 <X>-10.5</X><Y>13.75</Y><Z>9.5</Z> 31 <VisibleGarrisonAllowedClasses datatype="tokens"> 32 Infantry+Ranged 33 </VisibleGarrisonAllowedClasses> 34 </Archer2> 35 <Archer3> 36 <X>-10.5</X><Y>13.75</Y><Z>-9.5</Z> 37 <VisibleGarrisonAllowedClasses datatype="tokens"> 38 Infantry+Ranged 39 </VisibleGarrisonAllowedClasses> 40 </Archer3> 41 <Archer4> 42 <X>10.5</X><Y>13.75</Y><Z>9.5</Z> 43 <VisibleGarrisonAllowedClasses datatype="tokens"> 44 Ranged+Catapult 45 </VisibleGarrisonAllowedClasses> 46 </Archer4> 47 </VisibleGarrisonPoints> 48 </GarrisonHolder> 8 49 <ProductionQueue> 9 50 <Entities datatype="tokens"> 10 51 units/{civ}_hero_chanakya -
binaries/data/mods/public/simulation/templates/template_structure_defense_wall_long.xml
17 17 <VisibleGarrisonPoints> 18 18 <Archer1> 19 19 <X>0</X><Y>11.5</Y><Z>0</Z> 20 <VisibleGarrisonAllowedClasses datatype="tokens"> 21 Infantry+Ranged 22 </VisibleGarrisonAllowedClasses> 20 23 </Archer1> 21 24 <Archer2> 22 25 <X>8</X><Y>11.5</Y><Z>0</Z> 26 <VisibleGarrisonAllowedClasses datatype="tokens"> 27 Infantry+Ranged 28 </VisibleGarrisonAllowedClasses> 23 29 </Archer2> 24 30 <Archer3> 25 31 <X>-8</X><Y>11.5</Y><Z>0</Z> 32 <VisibleGarrisonAllowedClasses datatype="tokens"> 33 Infantry+Ranged 34 </VisibleGarrisonAllowedClasses> 26 35 </Archer3> 27 36 <Archer4> 28 37 <X>4</X><Y>11.5</Y><Z>0</Z> 38 <VisibleGarrisonAllowedClasses datatype="tokens"> 39 Infantry+Ranged 40 </VisibleGarrisonAllowedClasses> 29 41 </Archer4> 30 42 <Archer5> 31 43 <X>-4</X><Y>11.5</Y><Z>0</Z> 44 <VisibleGarrisonAllowedClasses datatype="tokens"> 45 Infantry+Ranged 46 </VisibleGarrisonAllowedClasses> 32 47 </Archer5> 33 48 </VisibleGarrisonPoints> 34 49 </GarrisonHolder> -
binaries/data/mods/public/simulation/templates/template_structure_defense_wall_medium.xml
17 17 <VisibleGarrisonPoints> 18 18 <Archer1> 19 19 <X>0</X><Y>11.5</Y><Z>0</Z> 20 <VisibleGarrisonAllowedClasses datatype="tokens"> 21 Infantry+Ranged 22 </VisibleGarrisonAllowedClasses> 20 23 </Archer1> 21 24 <Archer2> 22 25 <X>4</X><Y>11.5</Y><Z>0</Z> 26 <VisibleGarrisonAllowedClasses datatype="tokens"> 27 Infantry+Ranged 28 </VisibleGarrisonAllowedClasses> 23 29 </Archer2> 24 30 <Archer3> 25 31 <X>-4</X><Y>11.5</Y><Z>0</Z> 32 <VisibleGarrisonAllowedClasses datatype="tokens"> 33 Infantry+Ranged 34 </VisibleGarrisonAllowedClasses> 26 35 </Archer3> 27 36 </VisibleGarrisonPoints> 28 37 </GarrisonHolder>