Ticket #3488: 3488.13.diff
File 3488.13.diff, 8.8 KB (added by , 8 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 "<optional>" + 52 "<element name='VisibleGarrisonAllowedClasses'>" + 53 "<attribute name='datatype'>" + 54 "<value>tokens</value>" + 55 "</attribute>" + 56 "<text/>" + 57 "</element>" + 58 "</optional>" + 48 59 "</interleave>" + 49 60 "</element>" + 50 61 "</zeroOrMore>" + … … 72 83 o.x = +offset.X; 73 84 o.y = +offset.Y; 74 85 o.z = +offset.Z; 75 this.visibleGarrisonPoints.push({ "offset":o, "entity": null});86 this.visibleGarrisonPoints.push({ "offset": o, "entity": null, "allowedClass": offset.VisibleGarrisonAllowedClasses }); 76 87 } 77 88 } 78 89 }; … … 100 111 return IsOwnedByPlayer(player, ent); 101 112 }; 102 113 103 104 114 /** 105 115 * Return the list of entities garrisoned inside 106 116 */ … … 204 214 }; 205 215 206 216 /** 217 * Returns true if the unit is allowed be visible on that garrison point, false otherwise. 218 */ 219 GarrisonHolder.prototype.AllowedToVisibleGarrisoning = function(visibleGarrisonPoint, entity) 220 { 221 let allowedClassesList = visibleGarrisonPoint.allowedClass._string; 222 // If classlist is empty, everybody can garrison. 223 if (!allowedClassesList) 224 return true; 225 226 return MatchesClassList(Engine.QueryInterface(entity, IID_Identity).GetClassesList(), allowedClassesList); 227 }; 228 229 /** 207 230 * Garrison a unit inside. 208 231 * Returns true if successful, false if not 209 232 * The timer for AutoHeal is started here … … 225 248 { 226 249 if (vgp.entity) 227 250 continue; 228 visibleGarrisonPoint = vgp; 229 break; 251 if (this.AllowedToVisibleGarrisoning(vgp, entity)) 252 { 253 visibleGarrisonPoint = vgp; 254 break; 255 } 230 256 } 231 257 } 232 233 if (visibleGarrisonPoint) 258 if (visibleGarrisonPoint && this.AllowedToVisibleGarrisoning(visibleGarrisonPoint, entity)) 234 259 { 235 260 visibleGarrisonPoint.entity = entity; 236 261 cmpPosition.SetTurretParent(this.entity, visibleGarrisonPoint.offset); … … 241 266 else 242 267 cmpPosition.MoveOutOfWorld(); 243 268 269 let visible = {}; 270 let key = "" + entity; 271 visible[key] = this.IsVisiblyGarrisoned(entity); 272 // Should only be called after the garrison has been performed else the visible Garrison Points are not updated yet. 273 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { 274 "added": [entity], 275 "removed": [], 276 "visible": visible 277 }); 244 278 return true; 245 279 }; 246 280 281 /** 282 * Garrison units inside the entity 283 * @return true if successful, false if not 284 */ 247 285 GarrisonHolder.prototype.PerformGarrison = function(entity) 248 286 { 249 287 if (!this.HasEnoughHealth()) … … 250 288 return false; 251 289 252 290 // Check if the unit is allowed to be garrisoned inside the building 253 if (!this.AllowedToGarrison(entity))291 if (!this.AllowedToGarrison(entity)) 254 292 return false; 255 293 256 // check the capacity294 // Check the capacity 257 295 var extraCount = 0; 258 296 var cmpGarrisonHolder = Engine.QueryInterface(entity, IID_GarrisonHolder); 259 297 if (cmpGarrisonHolder) … … 278 316 if (cmpAura && cmpAura.HasGarrisonAura()) 279 317 cmpAura.ApplyGarrisonBonus(this.entity); 280 318 281 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [entity], "removed": [] });282 283 319 var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI); 284 320 if (cmpUnitAI && cmpUnitAI.IsUnderAlert()) 285 321 Engine.PostMessage(cmpUnitAI.GetAlertRaiser(), MT_UnitGarrisonedAfterAlert, {"holder": this.entity, "unit": entity}); … … 326 362 327 363 var cmpNewPosition = Engine.QueryInterface(entity, IID_Position); 328 364 this.entities.splice(entityIndex, 1); 329 365 366 let visible = {}; 367 let key = "" + entity; 368 visible[key] = this.IsVisiblyGarrisoned(entity); 369 // Should only be called before the ejection has been performed else the visible Garrison Points will be empty. 370 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { 371 "added": [], 372 "removed": [entity], 373 "visible": visible 374 }); 330 375 for (var vgp of this.visibleGarrisonPoints) 331 376 { 332 377 if (vgp.entity != entity) … … 356 401 cmpNewPosition.SetHeightOffset(0); 357 402 // TODO: what direction should they face in? 358 403 359 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [entity] });360 404 361 405 return true; 362 406 }; … … 597 641 */ 598 642 GarrisonHolder.prototype.OnGlobalOwnershipChanged = function(msg) 599 643 { 644 let msgEntity = msg.entity; 600 645 // the ownership change may be on the garrisonholder 601 if (this.entity == msg .entity)646 if (this.entity == msgEntity) 602 647 { 603 648 var entities = []; 604 649 for each (var entity in this.entities) … … 612 657 } 613 658 614 659 // or on some of its garrisoned units 615 var entityIndex = this.entities.indexOf(msg .entity);660 var entityIndex = this.entities.indexOf(msgEntity); 616 661 if (entityIndex != -1) 617 662 { 618 663 // If the entity is dead, remove it directly instead of ejecting the corpse 619 var cmpHealth = Engine.QueryInterface(msg .entity, IID_Health);664 var cmpHealth = Engine.QueryInterface(msgEntity, IID_Health); 620 665 if (cmpHealth && cmpHealth.GetHitpoints() == 0) 621 666 { 622 667 this.entities.splice(entityIndex, 1); 623 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [msg.entity] }); 668 let visible = {}; 669 let key = "" + msgEntity; 670 visible[key] = this.IsVisiblyGarrisoned(msgEntity); 671 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { 672 "added": [], 673 "removed": [msgEntity], 674 "visible": visible 675 }); 624 676 this.UpdateGarrisonFlag(); 625 677 626 678 for (var pt of this.visibleGarrisonPoints) 627 if (pt.entity == msg .entity)679 if (pt.entity == msgEntity) 628 680 pt.entity = null; 629 681 } 630 else if (msg.to == -1 || !IsOwnedByMutualAllyOfEntity(this.entity, msg .entity))631 this.EjectOrKill([msg .entity]);682 else if (msg.to == -1 || !IsOwnedByMutualAllyOfEntity(this.entity, msgEntity)) 683 this.EjectOrKill([msgEntity]); 632 684 } 633 685 }; 634 686 635 687 /** 636 688 * Update list of garrisoned entities if one gets renamed (e.g. by promotion) 689 * vgpEntity is only defined in some peculiar case where we want to reuse the same visibleGarrisonPoint, 690 * in case of promotion for example, and thus should always be allowed. 637 691 */ 638 692 GarrisonHolder.prototype.OnGlobalEntityRenamed = function(msg) 639 693 { … … 670 724 } 671 725 }; 672 726 673 674 727 /** 675 728 * Eject all foreign garrisoned entities which are no more allied 676 729 */ … … 687 740 GarrisonHolder.prototype.EjectOrKill = function(entities) 688 741 { 689 742 var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); 690 // Eject the units which can be ejected (if not in world, it generallymeans this holder743 // Eject the units which can be ejected (if not in world, it often means this holder 691 744 // is inside a holder which kills its entities, so do not eject) 692 745 if (cmpPosition.IsInWorld()) 693 746 { … … 710 763 this.entities.splice(entityIndex, 1); 711 764 killedEntities.push(entity); 712 765 } 713 714 766 if (killedEntities.length > 0) 715 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed" : killedEntities }); 767 { 768 let visibleEntitiesIds = {}; 769 for (let ent of killedEntities) 770 visibleEntitiesIds[ent] = this.IsVisiblyGarrisoned(ent); 771 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { 772 "added": [], 773 "removed": killedEntities, 774 "visible": visibleEntitiesIds 775 }); 776 } 716 777 this.UpdateGarrisonFlag(); 717 778 }; 718 779 719 780 /** 781 * Gives insight about the unit type of garrisoning. 782 * @return{bool} returns true if the unit is visible on the structure 783 * @param {int} the entity's id 784 */ 785 GarrisonHolder.prototype.IsVisiblyGarrisoned = function(entity) 786 { 787 return this.visibleGarrisonPoints.some(point => point.entity == entity); 788 }; 789 790 /** 720 791 * Checks if an entity is ejectable on destroy if possible 721 792 */ 722 793 GarrisonHolder.prototype.IsEjectable = function(entity)