Ticket #4102: garrison-4102.patch
File garrison-4102.patch, 18.0 KB (added by , 8 years ago) |
---|
-
binaries/data/mods/public/simulation/components/GarrisonHolder.js
65 65 this.allowGarrisoning = {}; 66 66 this.visibleGarrisonPoints = []; 67 67 if (this.template.VisibleGarrisonPoints) 68 { 69 for each (var offset in this.template.VisibleGarrisonPoints) 70 { 71 var o = {}; 72 o.x = +offset.X; 73 o.y = +offset.Y; 74 o.z = +offset.Z; 75 this.visibleGarrisonPoints.push({"offset":o, "entity": null}); 76 } 77 } 68 for (let name in this.template.VisibleGarrisonPoints) 69 this.visibleGarrisonPoints.push({ 70 "offset": { 71 "x": +this.template.VisibleGarrisonPoints[name].X, 72 "y": +this.template.VisibleGarrisonPoints[name].Y, 73 "z": +this.template.VisibleGarrisonPoints[name].Z 74 }, "entity": null }); 78 75 }; 79 76 80 77 /** … … 82 79 */ 83 80 GarrisonHolder.prototype.GetLoadingRange = function() 84 81 { 85 var max = +this.template.LoadingRange; 86 return { "max": max, "min": 0 }; 82 return { "max": +this.template.LoadingRange, "min": 0 }; 87 83 }; 88 84 89 85 /** … … 93 89 { 94 90 if (!this.template.Pickup || this.IsFull()) 95 91 return false; 96 varcmpOwner = Engine.QueryInterface(this.entity, IID_Ownership);92 let cmpOwner = Engine.QueryInterface(this.entity, IID_Ownership); 97 93 if (!cmpOwner) 98 94 return false; 99 var player = cmpOwner.GetOwner(); 100 return IsOwnedByPlayer(player, ent); 95 return IsOwnedByPlayer(cmpOwner.GetOwner(), ent); 101 96 }; 102 97 103 98 … … 163 158 */ 164 159 GarrisonHolder.prototype.IsGarrisoningAllowed = function() 165 160 { 166 for each (var allow in this.allowGarrisoning) 167 { 168 if (!allow) 161 for (let allow in this.allowGarrisoning) 162 if (!this.allowGarrisoning[allow]) 169 163 return false; 170 } 164 171 165 return true; 172 166 }; 173 167 … … 176 170 */ 177 171 GarrisonHolder.prototype.GetGarrisonedEntitiesCount = function() 178 172 { 179 varcount = 0;180 for each (var ent inthis.entities)173 let count = 0; 174 for (let ent of this.entities) 181 175 { 182 count++;183 varcmpGarrisonHolder = Engine.QueryInterface(ent, IID_GarrisonHolder);176 ++count; 177 let cmpGarrisonHolder = Engine.QueryInterface(ent, IID_GarrisonHolder); 184 178 if (cmpGarrisonHolder) 185 179 count += cmpGarrisonHolder.GetGarrisonedEntitiesCount(); 186 180 } … … 196 190 if (!this.IsGarrisoningAllowed()) 197 191 return false; 198 192 199 varcmpIdentity = Engine.QueryInterface(entity, IID_Identity);193 let cmpIdentity = Engine.QueryInterface(entity, IID_Identity); 200 194 if (!cmpIdentity) 201 195 return false; 202 var entityClasses = cmpIdentity.GetClassesList(); 203 return MatchesClassList(entityClasses, this.template.List._string); 196 return MatchesClassList(cmpIdentity.GetClassesList(), this.template.List._string); 204 197 }; 205 198 206 199 /** … … 211 204 */ 212 205 GarrisonHolder.prototype.Garrison = function(entity, vgpEntity) 213 206 { 214 varcmpPosition = Engine.QueryInterface(entity, IID_Position);207 let cmpPosition = Engine.QueryInterface(entity, IID_Position); 215 208 if (!cmpPosition) 216 209 return false; 217 210 … … 254 247 return false; 255 248 256 249 // check the capacity 257 varextraCount = 0;258 varcmpGarrisonHolder = Engine.QueryInterface(entity, IID_GarrisonHolder);250 let extraCount = 0; 251 let cmpGarrisonHolder = Engine.QueryInterface(entity, IID_GarrisonHolder); 259 252 if (cmpGarrisonHolder) 260 253 extraCount += cmpGarrisonHolder.GetGarrisonedEntitiesCount(); 261 254 if (this.GetGarrisonedEntitiesCount() + extraCount >= this.GetCapacity()) … … 263 256 264 257 if (!this.timer && this.GetHealRate() > 0) 265 258 { 266 varcmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);259 let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 267 260 this.timer = cmpTimer.SetTimeout(this.entity, IID_GarrisonHolder, "HealTimeout", 1000, {}); 268 261 } 269 262 … … 270 263 // Actual garrisoning happens here 271 264 this.entities.push(entity); 272 265 this.UpdateGarrisonFlag(); 273 varcmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue);266 let cmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue); 274 267 if (cmpProductionQueue) 275 268 cmpProductionQueue.PauseProduction(); 276 269 277 varcmpAura = Engine.QueryInterface(entity, IID_Auras);270 let cmpAura = Engine.QueryInterface(entity, IID_Auras); 278 271 if (cmpAura && cmpAura.HasGarrisonAura()) 279 272 cmpAura.ApplyGarrisonBonus(this.entity); 280 273 281 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" 274 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added": [entity], "removed": [] }); 282 275 283 varcmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);276 let cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI); 284 277 if (cmpUnitAI && cmpUnitAI.IsUnderAlert()) 285 Engine.PostMessage(cmpUnitAI.GetAlertRaiser(), MT_UnitGarrisonedAfterAlert, { "holder": this.entity, "unit": entity});278 Engine.PostMessage(cmpUnitAI.GetAlertRaiser(), MT_UnitGarrisonedAfterAlert, { "holder": this.entity, "unit": entity }); 286 279 287 280 return true; 288 281 }; … … 294 287 */ 295 288 GarrisonHolder.prototype.Eject = function(entity, forced) 296 289 { 297 varentityIndex = this.entities.indexOf(entity);290 let entityIndex = this.entities.indexOf(entity); 298 291 // Error: invalid entity ID, usually it's already been ejected 299 292 if (entityIndex == -1) 300 293 return false; // Fail 301 294 302 295 // Find spawning location 303 varcmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint);304 varcmpHealth = Engine.QueryInterface(this.entity, IID_Health);305 varcmpIdentity = Engine.QueryInterface(this.entity, IID_Identity);296 let cmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint); 297 let cmpHealth = Engine.QueryInterface(this.entity, IID_Health); 298 let cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity); 306 299 // If the garrisonHolder is a sinking ship, restrict the location to the intersection of both passabilities 307 300 // TODO: should use passability classes to be more generic 308 if ((!cmpHealth || cmpHealth.GetHitpoints() == 0) && cmpIdentity && cmpIdentity.HasClass("Ship")) 309 var pos = cmpFootprint.PickSpawnPointBothPass(entity); 310 else 311 var pos = cmpFootprint.PickSpawnPoint(entity); 301 let pos = (!cmpHealth || cmpHealth.GetHitpoints() === 0) && cmpIdentity && cmpIdentity.HasClass("Ship") ? 302 cmpFootprint.PickSpawnPointBothPass(entity) : 303 cmpFootprint.PickSpawnPoint(entity); 312 304 313 305 if (pos.y < 0) 314 306 { … … 315 307 // Error: couldn't find space satisfying the unit's passability criteria 316 308 if (forced) 317 309 { // If ejection is forced, we need to continue, so use center of the building 318 varcmpPosition = Engine.QueryInterface(this.entity, IID_Position);310 let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); 319 311 pos = cmpPosition.GetPosition(); 320 312 } 321 313 else … … 324 316 } 325 317 } 326 318 327 varcmpNewPosition = Engine.QueryInterface(entity, IID_Position);319 let cmpNewPosition = Engine.QueryInterface(entity, IID_Position); 328 320 this.entities.splice(entityIndex, 1); 329 321 330 for (var vgp of this.visibleGarrisonPoints) 322 let cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI); 323 for (let vgp of this.visibleGarrisonPoints) 331 324 { 332 325 if (vgp.entity != entity) 333 326 continue; 334 327 cmpNewPosition.SetTurretParent(INVALID_ENTITY, new Vector3D()); 335 var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);336 328 if (cmpUnitAI) 337 329 cmpUnitAI.ResetTurretStance(); 338 330 vgp.entity = null; … … 339 331 break; 340 332 } 341 333 342 var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);343 334 if (cmpUnitAI) 344 335 cmpUnitAI.Ungarrison(); 345 336 346 varcmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue);337 let cmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue); 347 338 if (cmpProductionQueue) 348 339 cmpProductionQueue.UnpauseProduction(); 349 340 350 varcmpAura = Engine.QueryInterface(entity, IID_Auras);341 let cmpAura = Engine.QueryInterface(entity, IID_Auras); 351 342 if (cmpAura && cmpAura.HasGarrisonAura()) 352 343 cmpAura.RemoveGarrisonBonus(this.entity); 353 344 … … 366 357 */ 367 358 GarrisonHolder.prototype.OrderWalkToRallyPoint = function(entities) 368 359 { 369 varcmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);370 varcmpRallyPoint = Engine.QueryInterface(this.entity, IID_RallyPoint);360 let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 361 let cmpRallyPoint = Engine.QueryInterface(this.entity, IID_RallyPoint); 371 362 if (cmpRallyPoint) 372 363 { 373 varrallyPos = cmpRallyPoint.GetPositions()[0];364 let rallyPos = cmpRallyPoint.GetPositions()[0]; 374 365 if (rallyPos) 375 366 { 376 varcommands = GetRallyPointCommands(cmpRallyPoint, entities);367 let commands = GetRallyPointCommands(cmpRallyPoint, entities); 377 368 // ignore the rally point if it is autogarrison 378 369 if (commands[0].type == "garrison" && commands[0].target == this.entity) 379 370 return; 380 for each (var com in commands) 381 { 382 ProcessCommand(cmpOwnership.GetOwner(), com); 383 } 371 for (let command of commands) 372 ProcessCommand(cmpOwnership.GetOwner(), command); 384 373 } 385 374 } 386 375 }; … … 396 385 if (!this.IsGarrisoningAllowed() && !forced) 397 386 return false; 398 387 399 varejectedEntities = [];400 varsuccess = true;401 varfailedRadius;402 for ( varentity of entities)388 let ejectedEntities = []; 389 let success = true; 390 let failedRadius; 391 for (let entity of entities) 403 392 { 404 393 if (failedRadius !== undefined) 405 394 { 406 varcmpObstruction = Engine.QueryInterface(entity, IID_Obstruction);407 varradius = cmpObstruction ? cmpObstruction.GetUnitRadius() : 0;395 let cmpObstruction = Engine.QueryInterface(entity, IID_Obstruction); 396 let radius = cmpObstruction ? cmpObstruction.GetUnitRadius() : 0; 408 397 if (radius >= failedRadius) 409 398 continue; 410 399 } … … 411 400 412 401 if (this.Eject(entity, forced)) 413 402 { 414 varcmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);415 varcmpEntOwnership = Engine.QueryInterface(entity, IID_Ownership);403 let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 404 let cmpEntOwnership = Engine.QueryInterface(entity, IID_Ownership); 416 405 if (cmpOwnership && cmpEntOwnership && cmpOwnership.GetOwner() == cmpEntOwnership.GetOwner()) 417 406 ejectedEntities.push(entity); 418 407 } … … 423 412 failedRadius = Math.min(failedRadius, radius); 424 413 else 425 414 { 426 varcmpObstruction = Engine.QueryInterface(entity, IID_Obstruction);415 let cmpObstruction = Engine.QueryInterface(entity, IID_Obstruction); 427 416 failedRadius = cmpObstruction ? cmpObstruction.GetUnitRadius() : 0; 428 417 } 429 418 } … … 454 443 */ 455 444 GarrisonHolder.prototype.UnloadTemplate = function(extendedTemplate, all, forced) 456 445 { 457 varindex = extendedTemplate.indexOf("&");446 let index = extendedTemplate.indexOf("&"); 458 447 if (index == -1) 459 448 return false; 460 449 461 varowner = +extendedTemplate.slice(1,index);462 vartemplate = extendedTemplate.slice(index+1);450 let owner = +extendedTemplate.slice(1,index); 451 let template = extendedTemplate.slice(index+1); 463 452 464 varentities = [];465 varcmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);466 for each (var entity inthis.entities)453 let entities = []; 454 let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); 455 for (let entity of this.entities) 467 456 { 468 varcmpIdentity = Engine.QueryInterface(entity, IID_Identity);457 let cmpIdentity = Engine.QueryInterface(entity, IID_Identity); 469 458 470 459 // Units with multiple ranks are grouped together. 471 var name = cmpIdentity.GetSelectionGroupName() 472 || cmpTemplateManager.GetCurrentTemplateName(entity); 460 let name = cmpIdentity.GetSelectionGroupName() || cmpTemplateManager.GetCurrentTemplateName(entity); 473 461 474 462 if (name != template) 475 463 continue; … … 493 481 */ 494 482 GarrisonHolder.prototype.UnloadAllByOwner = function(owner, forced) 495 483 { 496 varentities = this.entities.filter(ent => {497 varcmpOwnership = Engine.QueryInterface(ent, IID_Ownership);484 let entities = this.entities.filter(ent => { 485 let cmpOwnership = Engine.QueryInterface(ent, IID_Ownership); 498 486 return cmpOwnership && cmpOwnership.GetOwner() == owner; 499 487 }); 500 488 return this.PerformEject(entities, forced); … … 507 495 */ 508 496 GarrisonHolder.prototype.UnloadAll = function(forced) 509 497 { 510 var entities = this.entities.slice(); 511 return this.PerformEject(entities, forced); 498 return this.PerformEject(this.entities.slice(), forced); 512 499 }; 513 500 514 501 /** … … 518 505 GarrisonHolder.prototype.OnHealthChanged = function(msg) 519 506 { 520 507 if (!this.HasEnoughHealth() && this.entities.length) 521 { 522 var entities = this.entities.slice(); 523 this.EjectOrKill(entities); 524 } 508 this.EjectOrKill(this.entities.slice()); 525 509 }; 526 510 527 511 /** … … 529 513 */ 530 514 GarrisonHolder.prototype.HasEnoughHealth = function() 531 515 { 532 varcmpHealth = Engine.QueryInterface(this.entity, IID_Health);533 varhitpoints = cmpHealth.GetHitpoints();534 varmaxHitpoints = cmpHealth.GetMaxHitpoints();535 varejectHitpoints = Math.floor((+this.template.EjectHealth) * maxHitpoints);516 let cmpHealth = Engine.QueryInterface(this.entity, IID_Health); 517 let hitpoints = cmpHealth.GetHitpoints(); 518 let maxHitpoints = cmpHealth.GetMaxHitpoints(); 519 let ejectHitpoints = Math.floor((+this.template.EjectHealth) * maxHitpoints); 536 520 return hitpoints > ejectHitpoints; 537 521 }; 538 522 … … 541 525 */ 542 526 GarrisonHolder.prototype.HealTimeout = function(data) 543 527 { 544 if (this.entities.length == 0) 528 let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 529 if (!this.entities.length) 545 530 { 546 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);547 531 cmpTimer.CancelTimer(this.timer); 548 532 this.timer = undefined; 533 return; 549 534 } 550 else 535 536 for (let entity of this.entities) 551 537 { 552 for each (var entity in this.entities) 538 let cmpHealth = Engine.QueryInterface(entity, IID_Health); 539 if (cmpHealth) 553 540 { 554 var cmpHealth = Engine.QueryInterface(entity, IID_Health); 555 if (cmpHealth) 556 { 557 // We do not want to heal unhealable units 558 if (!cmpHealth.IsUnhealable()) 559 cmpHealth.Increase(this.GetHealRate()); 560 } 541 // We do not want to heal unhealable units 542 if (!cmpHealth.IsUnhealable()) 543 cmpHealth.Increase(this.GetHealRate()); 561 544 } 562 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);563 this.timer = cmpTimer.SetTimeout(this.entity, IID_GarrisonHolder, "HealTimeout", 1000, {});564 545 } 546 this.timer = cmpTimer.SetTimeout(this.entity, IID_GarrisonHolder, "HealTimeout", 1000, {}); 565 547 }; 566 548 567 549 GarrisonHolder.prototype.UpdateGarrisonFlag = function() … … 580 562 { 581 563 if (this.timer) 582 564 { 583 varcmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);565 let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 584 566 cmpTimer.CancelTimer(this.timer); 585 567 } 586 568 }; … … 595 577 // the ownership change may be on the garrisonholder 596 578 if (this.entity == msg.entity) 597 579 { 598 varentities = [];599 for each (var entity inthis.entities)580 let entities = []; 581 for (let entity of this.entities) 600 582 { 601 583 if (msg.to == -1 || !IsOwnedByMutualAllyOfEntity(this.entity, entity)) 602 584 entities.push(entity); … … 607 589 } 608 590 609 591 // or on some of its garrisoned units 610 varentityIndex = this.entities.indexOf(msg.entity);592 let entityIndex = this.entities.indexOf(msg.entity); 611 593 if (entityIndex != -1) 612 594 { 613 595 // If the entity is dead, remove it directly instead of ejecting the corpse 614 varcmpHealth = Engine.QueryInterface(msg.entity, IID_Health);615 if (cmpHealth && cmpHealth.GetHitpoints() == 0)596 let cmpHealth = Engine.QueryInterface(msg.entity, IID_Health); 597 if (cmpHealth && cmpHealth.GetHitpoints() === 0) 616 598 { 617 599 this.entities.splice(entityIndex, 1); 618 600 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [msg.entity] }); 619 601 this.UpdateGarrisonFlag(); 620 602 621 for ( varpt of this.visibleGarrisonPoints)603 for (let pt of this.visibleGarrisonPoints) 622 604 if (pt.entity == msg.entity) 623 605 pt.entity = null; 624 606 } … … 632 614 */ 633 615 GarrisonHolder.prototype.OnGlobalEntityRenamed = function(msg) 634 616 { 635 varentityIndex = this.entities.indexOf(msg.entity);617 let entityIndex = this.entities.indexOf(msg.entity); 636 618 if (entityIndex != -1) 637 619 { 638 620 let vgpRenamed; … … 671 653 */ 672 654 GarrisonHolder.prototype.OnDiplomacyChanged = function() 673 655 { 674 varentities = this.entities.filter(ent => !IsOwnedByMutualAllyOfEntity(this.entity, ent));656 let entities = this.entities.filter(ent => !IsOwnedByMutualAllyOfEntity(this.entity, ent)); 675 657 this.EjectOrKill(entities); 676 658 }; 677 659 … … 686 668 // is inside a holder which kills its entities, so do not eject) 687 669 if (cmpPosition.IsInWorld()) 688 670 { 689 var cmpGarrisonHolder = this; 690 var ejectables = entities.filter(function(ent) { return cmpGarrisonHolder.IsEjectable(ent); }); 671 let ejectables = entities.filter(ent => this.IsEjectable(ent), this); 691 672 if (ejectables.length) 692 673 this.PerformEject(ejectables, false); 693 674 } 694 675 695 676 // And destroy all remaining entities 696 varkilledEntities = [];697 for each (var entity inentities)677 let killedEntities = []; 678 for (let entity of entities) 698 679 { 699 varentityIndex = this.entities.indexOf(entity);680 let entityIndex = this.entities.indexOf(entity); 700 681 if (entityIndex == -1) 701 682 continue; 702 varcmpHealth = Engine.QueryInterface(entity, IID_Health);683 let cmpHealth = Engine.QueryInterface(entity, IID_Health); 703 684 if (cmpHealth) 704 685 cmpHealth.Kill(); 705 686 this.entities.splice(entityIndex, 1); … … 707 688 } 708 689 709 690 if (killedEntities.length > 0) 710 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": killedEntities });691 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added": [], "removed": killedEntities }); 711 692 this.UpdateGarrisonFlag(); 712 693 }; 713 694 … … 716 697 */ 717 698 GarrisonHolder.prototype.IsEjectable = function(entity) 718 699 { 719 varejectableClasses = this.template.EjectClassesOnDestroy._string;700 let ejectableClasses = this.template.EjectClassesOnDestroy._string; 720 701 ejectableClasses = ejectableClasses ? ejectableClasses.split(/\s+/) : []; 721 var entityClasses = (Engine.QueryInterface(entity, IID_Identity)).GetClassesList(); 722 for each (var ejectableClass in ejectableClasses) 723 if (entityClasses.indexOf(ejectableClass) != -1) 724 return true; 725 726 return false; 702 let entityClasses = (Engine.QueryInterface(entity, IID_Identity)).GetClassesList(); 703 return ejectableClasses.some(ejectableClass => entityClasses.indexOf(ejectableClass) != -1); 727 704 }; 728 705 729 706 /** … … 744 721 }; 745 722 746 723 Engine.RegisterComponentType(IID_GarrisonHolder, "GarrisonHolder", GarrisonHolder); 747