diff --git a/binaries/data/mods/public/maps/random/survivalofthefittest_triggers.js b/binaries/data/mods/public/maps/random/survivalofthefittest_triggers.js index 40d5a018a1..b074fc4f5b 100644 --- a/binaries/data/mods/public/maps/random/survivalofthefittest_triggers.js +++ b/binaries/data/mods/public/maps/random/survivalofthefittest_triggers.js @@ -211,7 +211,11 @@ Trigger.prototype.StartAnEnemyWave = function() } // Don't spawn attackers for defeated players and players that lost their cc after win - let playerID = QueryOwnerInterface(point, IID_Player).GetPlayerID(); + let cmpPlayer = QueryOwnerInterface(point, IID_Player); + if (!cmpPlayer) + continue; + + let playerID = cmpPlayer.GetPlayerID(); let civicCentre = this.playerCivicCenter[playerID]; if (!civicCentre) continue; diff --git a/binaries/data/mods/public/maps/scripts/CaptureTheRelic.js b/binaries/data/mods/public/maps/scripts/CaptureTheRelic.js index c8b3ce0251..a91a0f95e9 100644 --- a/binaries/data/mods/public/maps/scripts/CaptureTheRelic.js +++ b/binaries/data/mods/public/maps/scripts/CaptureTheRelic.js @@ -38,7 +38,7 @@ Trigger.prototype.CheckCaptureTheRelicVictory = function(data) if (data.to == -1) { - warn("Relic entity " + data.entity + " has been destroyed"); + warn("Relic entity " + data.entity + " has been destroyed."); this.relics.splice(this.relics.indexOf(data.entity), 1); } else @@ -130,6 +130,14 @@ Trigger.prototype.StartCaptureTheRelicCountdown = function(winningPlayers) } let cmpPlayer = QueryOwnerInterface(this.relics[0], IID_Player); + if (!cmpPlayer) + { + warn("Relic entity " + this.relics[0] + " has no owner."); + this.relics.splice(0, 1); + + this.CheckCaptureTheRelicCountdown(); + return; + } let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager); let captureTheRelicDuration = cmpEndGameManager.GetGameSettings().relicDuration; diff --git a/binaries/data/mods/public/simulation/components/BuildRestrictions.js b/binaries/data/mods/public/simulation/components/BuildRestrictions.js index def8631b0e..686975af51 100644 --- a/binaries/data/mods/public/simulation/components/BuildRestrictions.js +++ b/binaries/data/mods/public/simulation/components/BuildRestrictions.js @@ -92,8 +92,11 @@ BuildRestrictions.prototype.CheckPlacement = function() "translateParameters": ["name"], }; - // TODO: AI has no visibility info var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); + if (!cmpPlayer) + return result; // Fail + + // TODO: AI has no visibility info if (!cmpPlayer.IsAI()) { // Check whether it's in a visible or fogged region @@ -164,9 +167,8 @@ BuildRestrictions.prototype.CheckPlacement = function() // Check territory restrictions var cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager); - var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); - if (!(cmpTerritoryManager && cmpPlayer && cmpPosition && cmpPosition.IsInWorld())) + if (!cmpTerritoryManager || !cmpPosition || !cmpPosition.IsInWorld()) return result; // Fail var pos = cmpPosition.GetPosition2D(); @@ -239,7 +241,6 @@ BuildRestrictions.prototype.CheckPlacement = function() if (this.template.Distance) { var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); - var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); var cat = this.template.Distance.FromClass; var filter = function(id) diff --git a/binaries/data/mods/public/simulation/components/Looter.js b/binaries/data/mods/public/simulation/components/Looter.js index 6877dde192..b994a58a38 100644 --- a/binaries/data/mods/public/simulation/components/Looter.js +++ b/binaries/data/mods/public/simulation/components/Looter.js @@ -34,7 +34,8 @@ Looter.prototype.Collect = function(targetEntity) // Transfer resources var cmpPlayer = QueryOwnerInterface(this.entity); - cmpPlayer.AddResources(resources); + if (cmpPlayer) + cmpPlayer.AddResources(resources); // Update statistics var cmpStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker); diff --git a/binaries/data/mods/public/simulation/components/ProductionQueue.js b/binaries/data/mods/public/simulation/components/ProductionQueue.js index f2bdb8a017..872e8ab2b7 100644 --- a/binaries/data/mods/public/simulation/components/ProductionQueue.js +++ b/binaries/data/mods/public/simulation/components/ProductionQueue.js @@ -303,6 +303,8 @@ ProductionQueue.prototype.IsTechnologyResearchedOrInProgress = function(tech) return false; let cmpTechnologyManager = QueryOwnerInterface(this.entity, IID_TechnologyManager); + if (!cmpTechnologyManager) + return false; let template = TechnologyTemplates.Get(tech); if (template.top) @@ -323,6 +325,8 @@ ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat // TODO: there should be a way for the GUI to determine whether it's going // to be possible to add a batch (based on resource costs and length limits). let cmpPlayer = QueryOwnerInterface(this.entity); + if (!cmpPlayer) + return; if (this.queue.length < this.MaxQueueSize) { @@ -376,7 +380,8 @@ ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat { let unitCategory = template.TrainingRestrictions.Category; let cmpPlayerEntityLimits = QueryOwnerInterface(this.entity, IID_EntityLimits); - cmpPlayerEntityLimits.ChangeCount(unitCategory, count); + if (cmpPlayerEntityLimits) + cmpPlayerEntityLimits.ChangeCount(unitCategory, count); } let buildTime = ApplyValueModificationsToTemplate( @@ -718,13 +723,12 @@ ProductionQueue.prototype.SpawnUnits = function(templateName, count, metadata) // since it will be increased by EntityLimits.OnGlobalOwnershipChanged function, // i.e. we replace a 'trained' entity by 'alive' one. // Must be done after spawn check so EntityLimits decrements only if unit spawns. - let cmpTrainingRestrictions = Engine.QueryInterface(ent, IID_TrainingRestrictions); - if (cmpTrainingRestrictions) + if (cmpPlayerEntityLimits) { - let unitCategory = cmpTrainingRestrictions.GetCategory(); - cmpPlayerEntityLimits.ChangeCount(unitCategory, -1); + let cmpTrainingRestrictions = Engine.QueryInterface(ent, IID_TrainingRestrictions); + if (cmpTrainingRestrictions) + cmpPlayerEntityLimits.ChangeCount(cmpTrainingRestrictions.GetCategory(), -1); } - cmpNewOwnership.SetOwner(cmpOwnership.GetOwner()); if (cmpPlayerStatisticsTracker) @@ -773,11 +777,15 @@ ProductionQueue.prototype.ProgressTimeout = function(data) // Check if the production is paused (eg the entity is garrisoned) if (this.paused) return; + + let cmpPlayer = QueryOwnerInterface(this.entity); + if (!cmpPlayer) + return; + // Allocate available time to as many queue items as it takes // until we've used up all the time (so that we work accurately // with items that take fractions of a second). let time = this.ProgressInterval; - let cmpPlayer = QueryOwnerInterface(this.entity); let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); while (time > 0 && this.queue.length) @@ -815,7 +823,11 @@ ProductionQueue.prototype.ProgressTimeout = function(data) { // Mark the research as started. let cmpTechnologyManager = QueryOwnerInterface(this.entity, IID_TechnologyManager); - cmpTechnologyManager.StartedResearch(item.technologyTemplate, true); + if (cmpTechnologyManager) + cmpTechnologyManager.StartedResearch(item.technologyTemplate, true); + else + warn("Failed to start researching " + item.technologyTemplate + ": No TechnologyManager available."); + this.SetAnimation("researching"); } @@ -877,13 +889,16 @@ ProductionQueue.prototype.ProgressTimeout = function(data) else if (item.technologyTemplate) { let cmpTechnologyManager = QueryOwnerInterface(this.entity, IID_TechnologyManager); - cmpTechnologyManager.ResearchTechnology(item.technologyTemplate); + if (cmpTechnologyManager) + cmpTechnologyManager.ResearchTechnology(item.technologyTemplate); + else + warn("Failed to stop researching " + item.technologyTemplate + ": No TechnologyManager available."); + this.SetAnimation("idle"); let template = TechnologyTemplates.Get(item.technologyTemplate); if (template && template.soundComplete) { let cmpSoundManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_SoundManager); - if (cmpSoundManager) cmpSoundManager.PlaySoundGroup(template.soundComplete, this.entity); } diff --git a/binaries/data/mods/public/simulation/components/Promotion.js b/binaries/data/mods/public/simulation/components/Promotion.js index 79b1c78de9..4f30622e31 100644 --- a/binaries/data/mods/public/simulation/components/Promotion.js +++ b/binaries/data/mods/public/simulation/components/Promotion.js @@ -60,19 +60,23 @@ Promotion.prototype.IncreaseXp = function(amount) return; } - this.currentXp += +(amount); - var requiredXp = this.GetRequiredXp(); + this.currentXp += +amount; + let requiredXp = this.GetRequiredXp(); if (this.currentXp >= requiredXp) { - var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); - var playerID = QueryOwnerInterface(this.entity, IID_Player).GetPlayerID(); + let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); + let cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); + if (!cmpPlayer) + return; + + let playerID = cmpPlayer.GetPlayerID(); this.currentXp -= requiredXp; - var promotedTemplateName = this.GetPromotedTemplateName(); + let promotedTemplateName = this.GetPromotedTemplateName(); // check if we can upgrade a second time (or even more) while (true) { - var template = cmpTemplateManager.GetTemplate(promotedTemplateName); + let template = cmpTemplateManager.GetTemplate(promotedTemplateName); if (!template.Promotion) break; requiredXp = ApplyValueModificationsToTemplate("Promotion/RequiredXp", +template.Promotion.RequiredXp, playerID, template); diff --git a/binaries/data/mods/public/simulation/components/ResourceGatherer.js b/binaries/data/mods/public/simulation/components/ResourceGatherer.js index 11737758b6..bd9ac82604 100644 --- a/binaries/data/mods/public/simulation/components/ResourceGatherer.js +++ b/binaries/data/mods/public/simulation/components/ResourceGatherer.js @@ -358,7 +358,8 @@ ResourceGatherer.prototype.OnGlobalInitGame = function(msg) ResourceGatherer.prototype.OnMultiplierChanged = function(msg) { - if (msg.player == QueryOwnerInterface(this.entity, IID_Player).GetPlayerID()) + let cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); + if (cmpPlayer && msg.player == cmpPlayer.GetPlayerID()) this.RecalculateGatherRatesAndCapacities(); }; diff --git a/binaries/data/mods/public/simulation/components/SkirmishReplacer.js b/binaries/data/mods/public/simulation/components/SkirmishReplacer.js index c475e8f2ca..30e5140e3e 100644 --- a/binaries/data/mods/public/simulation/components/SkirmishReplacer.js +++ b/binaries/data/mods/public/simulation/components/SkirmishReplacer.js @@ -29,6 +29,9 @@ SkirmishReplacer.prototype.OnOwnershipChanged = function(msg) SkirmishReplacer.prototype.ReplaceEntities = function() { var cmpPlayer = QueryOwnerInterface(this.entity); + if (!cmpPlayer) + return; + var civ = cmpPlayer.GetCiv(); var replacementEntities = getReplacementEntities(civ); diff --git a/binaries/data/mods/public/simulation/components/Trader.js b/binaries/data/mods/public/simulation/components/Trader.js index ece60f8f45..3334e564bc 100644 --- a/binaries/data/mods/public/simulation/components/Trader.js +++ b/binaries/data/mods/public/simulation/components/Trader.js @@ -81,7 +81,7 @@ Trader.prototype.RemoveTargetMarket = function(target) this.index = -1; this.markets = []; return true; -} +}; // Set target as target market. // Return true if at least one of markets was changed. @@ -184,7 +184,7 @@ Trader.prototype.CanTrade = function(target) let cmpTraderPlayer = QueryOwnerInterface(this.entity, IID_Player); let cmpTargetPlayer = QueryOwnerInterface(target, IID_Player); - return !cmpTraderPlayer.IsEnemy(cmpTargetPlayer.GetPlayerID()); + return cmpTraderPlayer && cmpTargetPlayer && !cmpTraderPlayer.IsEnemy(cmpTargetPlayer.GetPlayerID()); }; Trader.prototype.AddResources = function(ent, gain) diff --git a/binaries/data/mods/public/simulation/components/Upgrade.js b/binaries/data/mods/public/simulation/components/Upgrade.js index 081a45dbaf..6b722dbd8e 100644 --- a/binaries/data/mods/public/simulation/components/Upgrade.js +++ b/binaries/data/mods/public/simulation/components/Upgrade.js @@ -230,7 +230,7 @@ Upgrade.prototype.Upgrade = function(template) let cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); this.expendedResources = this.GetResourceCosts(template); - if (!cmpPlayer.TrySubtractResources(this.expendedResources)) + if (!cmpPlayer || !cmpPlayer.TrySubtractResources(this.expendedResources)) { this.expendedResources = {}; return false; diff --git a/binaries/data/mods/public/simulation/helpers/Commands.js b/binaries/data/mods/public/simulation/helpers/Commands.js index 17d55fce85..d810df58c9 100644 --- a/binaries/data/mods/public/simulation/helpers/Commands.js +++ b/binaries/data/mods/public/simulation/helpers/Commands.js @@ -296,7 +296,7 @@ var g_Commands = { if (unitCategory) { var cmpPlayerEntityLimits = QueryOwnerInterface(ent, IID_EntityLimits); - if (!cmpPlayerEntityLimits.AllowedToTrain(unitCategory, cmd.count)) + if (cmpPlayerEntityLimits && !cmpPlayerEntityLimits.AllowedToTrain(unitCategory, cmd.count)) { if (g_DebugCommands) warn(unitCategory + " train limit is reached: " + uneval(cmd)); @@ -305,7 +305,7 @@ var g_Commands = { } var cmpTechnologyManager = QueryOwnerInterface(ent, IID_TechnologyManager); - if (!cmpTechnologyManager.CanProduce(cmd.template)) + if (cmpTechnologyManager && !cmpTechnologyManager.CanProduce(cmd.template)) { if (g_DebugCommands) warn("Invalid command: training requires unresearched technology: " + uneval(cmd)); @@ -348,7 +348,7 @@ var g_Commands = { } var cmpTechnologyManager = QueryOwnerInterface(cmd.entity, IID_TechnologyManager); - if (!cmpTechnologyManager.CanResearch(cmd.template)) + if (cmpTechnologyManager && !cmpTechnologyManager.CanResearch(cmd.template)) { if (g_DebugCommands) warn("Invalid command: Requirements to research technology are not met: " + uneval(cmd));