diff --git a/binaries/data/mods/public/simulation/ai/petra/mapModule.js b/binaries/data/mods/public/simulation/ai/petra/mapModule.js index aa580e7c8e..d729faab9b 100644 --- a/binaries/data/mods/public/simulation/ai/petra/mapModule.js +++ b/binaries/data/mods/public/simulation/ai/petra/mapModule.js @@ -90,9 +90,10 @@ PETRA.createObstructionMap = function(gameState, accessIndex, template) { let obstructionRadius = template.obstructionRadius(); if (obstructionRadius) - minDist += obstructionRadius.max; + minDist -= obstructionRadius.min; let fromClass = distance.FromClass; let cellSize = passabilityMap.cellSize; + let cellDist = 1 + minDist / cellSize; let structures = gameState.getOwnStructures().filter(API3.Filters.byClass(fromClass)); for (let ent of structures.values()) { @@ -101,9 +102,7 @@ PETRA.createObstructionMap = function(gameState, accessIndex, template) let pos = ent.position(); let x = Math.round(pos[0] / cellSize); let z = Math.round(pos[1] / cellSize); - let entRadius = ent.obstructionRadius(); - let dist = 1 + (minDist + (entRadius ? entRadius.max : 0)) / cellSize; - map.addInfluence(x, z, dist, -255, "constant"); + map.addInfluence(x, z, cellDist, -255, "constant"); } } } diff --git a/binaries/data/mods/public/simulation/components/AlertRaiser.js b/binaries/data/mods/public/simulation/components/AlertRaiser.js index 1734e736a0..c433e3f8ab 100644 --- a/binaries/data/mods/public/simulation/components/AlertRaiser.js +++ b/binaries/data/mods/public/simulation/components/AlertRaiser.js @@ -44,12 +44,12 @@ AlertRaiser.prototype.RaiseAlert = function() // Store the number of available garrison spots so that units don't try to garrison in buildings that will be full let reserved = new Map(); - let units = cmpRangeManager.ExecuteQuery(this.entity, 0, +this.template.RaiseAlertRange, [owner], IID_UnitAI).filter(ent => this.UnitFilter(ent)); + let units = cmpRangeManager.ExecuteQuery(this.entity, 0, +this.template.RaiseAlertRange, [owner], IID_UnitAI, true).filter(ent => this.UnitFilter(ent)); for (let unit of units) { let cmpUnitAI = Engine.QueryInterface(unit, IID_UnitAI); - let holder = cmpRangeManager.ExecuteQuery(unit, 0, +this.template.SearchRange, mutualAllies, IID_GarrisonHolder).find(ent => { + let holder = cmpRangeManager.ExecuteQuery(unit, 0, +this.template.SearchRange, mutualAllies, IID_GarrisonHolder, true).find(ent => { // Ignore moving garrison holders if (Engine.QueryInterface(ent, IID_UnitAI)) return false; @@ -98,7 +98,7 @@ AlertRaiser.prototype.EndOfAlert = function() let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); // Units that are not garrisoned should go back to work - let units = cmpRangeManager.ExecuteQuery(this.entity, 0, +this.template.EndOfAlertRange, [owner], IID_UnitAI).filter(ent => this.UnitFilter(ent)); + let units = cmpRangeManager.ExecuteQuery(this.entity, 0, +this.template.EndOfAlertRange, [owner], IID_UnitAI, true).filter(ent => this.UnitFilter(ent)); for (let unit of units) { let cmpUnitAI = Engine.QueryInterface(unit, IID_UnitAI); @@ -110,7 +110,7 @@ AlertRaiser.prototype.EndOfAlert = function() } // Units that are garrisoned should ungarrison and go back to work - let holders = cmpRangeManager.ExecuteQuery(this.entity, 0, +this.template.EndOfAlertRange, mutualAllies, IID_GarrisonHolder); + let holders = cmpRangeManager.ExecuteQuery(this.entity, 0, +this.template.EndOfAlertRange, mutualAllies, IID_GarrisonHolder, true); if (Engine.QueryInterface(this.entity, IID_GarrisonHolder)) holders.push(this.entity); diff --git a/binaries/data/mods/public/simulation/components/Auras.js b/binaries/data/mods/public/simulation/components/Auras.js index b8b8072421..c30f297ec6 100644 --- a/binaries/data/mods/public/simulation/components/Auras.js +++ b/binaries/data/mods/public/simulation/components/Auras.js @@ -267,13 +267,17 @@ Auras.prototype.Clean = function() if (this[name].isApplied && (this.IsRangeAura(name) || this.IsGlobalAura(name) && !!this.GetOverlayIcon(name))) { + // Do not account for entity sizes: structures can have various sizes + // and we currently prefer auras to not depend on the source size + // (this is generally irrelevant for units). this[name].rangeQuery = cmpRangeManager.CreateActiveQuery( this.entity, 0, this.GetRange(name), affectedPlayers, IID_Identity, - cmpRangeManager.GetEntityFlagMask("normal") + cmpRangeManager.GetEntityFlagMask("normal"), + false ); cmpRangeManager.EnableActiveQuery(this[name].rangeQuery); } diff --git a/binaries/data/mods/public/simulation/components/BuildRestrictions.js b/binaries/data/mods/public/simulation/components/BuildRestrictions.js index cf4eab0cfa..3b81b12e43 100644 --- a/binaries/data/mods/public/simulation/components/BuildRestrictions.js +++ b/binaries/data/mods/public/simulation/components/BuildRestrictions.js @@ -256,7 +256,7 @@ BuildRestrictions.prototype.CheckPlacement = function() if (this.template.Distance.MinDistance !== undefined) { let minDistance = ApplyValueModificationsToTemplate("BuildRestrictions/Distance/MinDistance", +this.template.Distance.MinDistance, cmpPlayer.GetPlayerID(), template); - if (cmpRangeManager.ExecuteQuery(this.entity, 0, minDistance, [cmpPlayer.GetPlayerID()], IID_BuildRestrictions).some(filter)) + if (cmpRangeManager.ExecuteQuery(this.entity, 0, minDistance, [cmpPlayer.GetPlayerID()], IID_BuildRestrictions, false).some(filter)) { let result = markForPluralTranslation( "%(name)s too close to a %(category)s, must be at least %(distance)s meter away", @@ -277,7 +277,7 @@ BuildRestrictions.prototype.CheckPlacement = function() if (this.template.Distance.MaxDistance !== undefined) { let maxDistance = ApplyValueModificationsToTemplate("BuildRestrictions/Distance/MaxDistance", +this.template.Distance.MaxDistance, cmpPlayer.GetPlayerID(), template); - if (!cmpRangeManager.ExecuteQuery(this.entity, 0, maxDistance, [cmpPlayer.GetPlayerID()], IID_BuildRestrictions).some(filter)) + if (!cmpRangeManager.ExecuteQuery(this.entity, 0, maxDistance, [cmpPlayer.GetPlayerID()], IID_BuildRestrictions, false).some(filter)) { let result = markForPluralTranslation( "%(name)s too far from a %(category)s, must be within %(distance)s meter", diff --git a/binaries/data/mods/public/simulation/components/BuildingAI.js b/binaries/data/mods/public/simulation/components/BuildingAI.js index 145953f9a5..908dda58c0 100644 --- a/binaries/data/mods/public/simulation/components/BuildingAI.js +++ b/binaries/data/mods/public/simulation/components/BuildingAI.js @@ -139,6 +139,7 @@ BuildingAI.prototype.SetupRangeQuery = function() return; var range = cmpAttack.GetRange(attackType); + // This takes entity sizes into accounts, so no need to compensate for structure size. this.enemyUnitsQuery = cmpRangeManager.CreateActiveParabolicQuery( this.entity, range.min, range.max, range.elevationBonus, enemies, IID_Resistance, cmpRangeManager.GetEntityFlagMask("normal")); @@ -168,6 +169,7 @@ BuildingAI.prototype.SetupGaiaRangeQuery = function() var range = cmpAttack.GetRange(attackType); // This query is only interested in Gaia entities that can attack. + // This takes entity sizes into accounts, so no need to compensate for structure size. this.gaiaUnitsQuery = cmpRangeManager.CreateActiveParabolicQuery( this.entity, range.min, range.max, range.elevationBonus, [0], IID_Attack, cmpRangeManager.GetEntityFlagMask("normal")); diff --git a/binaries/data/mods/public/simulation/components/Gate.js b/binaries/data/mods/public/simulation/components/Gate.js index 75e43cd115..2338b3393a 100644 --- a/binaries/data/mods/public/simulation/components/Gate.js +++ b/binaries/data/mods/public/simulation/components/Gate.js @@ -78,7 +78,7 @@ Gate.prototype.SetupRangeQuery = function(owner) if (range > 0) { // Only find entities with IID_UnitAI interface - this.unitsQuery = cmpRangeManager.CreateActiveQuery(this.entity, 0, range, players, IID_UnitAI, cmpRangeManager.GetEntityFlagMask("normal")); + this.unitsQuery = cmpRangeManager.CreateActiveQuery(this.entity, 0, range, players, IID_UnitAI, cmpRangeManager.GetEntityFlagMask("normal"), true); cmpRangeManager.EnableActiveQuery(this.unitsQuery); } }; diff --git a/binaries/data/mods/public/simulation/components/RangeOverlayManager.js b/binaries/data/mods/public/simulation/components/RangeOverlayManager.js index 21ce7482b0..5e0a561692 100644 --- a/binaries/data/mods/public/simulation/components/RangeOverlayManager.js +++ b/binaries/data/mods/public/simulation/components/RangeOverlayManager.js @@ -48,15 +48,12 @@ RangeOverlayManager.prototype.RegenerateRangeOverlays = function(forceUpdate) if (!this.enabled && !forceUpdate) return; - let cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction); - let rangeBonus = cmpObstruction ? cmpObstruction.GetSize() : 0; - // Only render individual range types that have been enabled for (let rangeOverlayType of this.rangeVisualizations.keys()) if (this.enabledRangeTypes[rangeOverlayType]) for (let rangeOverlay of this.rangeVisualizations.get(rangeOverlayType)) cmpRangeOverlayRenderer.AddRangeOverlay( - rangeOverlay.radius + rangeBonus, + rangeOverlay.radius, rangeOverlay.texture, rangeOverlay.textureMask, rangeOverlay.thickness); diff --git a/binaries/data/mods/public/simulation/components/TriggerPoint.js b/binaries/data/mods/public/simulation/components/TriggerPoint.js index a1874b99df..0799d64dc3 100644 --- a/binaries/data/mods/public/simulation/components/TriggerPoint.js +++ b/binaries/data/mods/public/simulation/components/TriggerPoint.js @@ -45,7 +45,7 @@ TriggerPoint.prototype.RegisterRangeTrigger = function(action, data) var cid = data.requiredComponent || -1; var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); - var tag = cmpRangeManager.CreateActiveQuery(this.entity, minRange, maxRange, players, cid, cmpRangeManager.GetEntityFlagMask("normal")); + var tag = cmpRangeManager.CreateActiveQuery(this.entity, minRange, maxRange, players, cid, cmpRangeManager.GetEntityFlagMask("normal"), true); this.currentCollections[tag] = []; this.actions[tag] = action; diff --git a/binaries/data/mods/public/simulation/components/UnitAI.js b/binaries/data/mods/public/simulation/components/UnitAI.js index 26ae0d75d4..9859dfd295 100644 --- a/binaries/data/mods/public/simulation/components/UnitAI.js +++ b/binaries/data/mods/public/simulation/components/UnitAI.js @@ -3791,7 +3791,10 @@ UnitAI.prototype.SetupLOSRangeQuery = function(enable = true) return; let range = this.GetQueryRange(IID_Vision); - this.losRangeQuery = cmpRangeManager.CreateActiveQuery(this.entity, range.min, range.max, players, IID_Identity, cmpRangeManager.GetEntityFlagMask("normal")); + // Do not compensate for entity sizes: LOS doesn't, and UnitAI relies on that. + this.losRangeQuery = cmpRangeManager.CreateActiveQuery(this.entity, + range.min, range.max, players, IID_Identity, + cmpRangeManager.GetEntityFlagMask("normal"), false); if (enable) cmpRangeManager.EnableActiveQuery(this.losRangeQuery); @@ -3820,7 +3823,10 @@ UnitAI.prototype.SetupHealRangeQuery = function(enable = true) let players = cmpPlayer.GetAllies(); let range = this.GetQueryRange(IID_Heal); - this.losHealRangeQuery = cmpRangeManager.CreateActiveQuery(this.entity, range.min, range.max, players, IID_Health, cmpRangeManager.GetEntityFlagMask("injured")); + // Do not compensate for entity sizes: LOS doesn't, and UnitAI relies on that. + this.losHealRangeQuery = cmpRangeManager.CreateActiveQuery(this.entity, + range.min, range.max, players, IID_Health, + cmpRangeManager.GetEntityFlagMask("injured"), false); if (enable) cmpRangeManager.EnableActiveQuery(this.losHealRangeQuery); @@ -3852,7 +3858,10 @@ UnitAI.prototype.SetupAttackRangeQuery = function(enable = true) return; let range = this.GetQueryRange(IID_Attack); - this.losAttackRangeQuery = cmpRangeManager.CreateActiveQuery(this.entity, range.min, range.max, players, IID_Resistance, cmpRangeManager.GetEntityFlagMask("normal")); + // Do not compensate for entity sizes: LOS doesn't, and UnitAI relies on that. + this.losAttackRangeQuery = cmpRangeManager.CreateActiveQuery(this.entity, + range.min, range.max, players, IID_Resistance, + cmpRangeManager.GetEntityFlagMask("normal"), false); if (enable) cmpRangeManager.EnableActiveQuery(this.losAttackRangeQuery); @@ -4437,7 +4446,8 @@ UnitAI.prototype.FindNearbyResource = function(position, filter) let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); - let nearby = cmpRangeManager.ExecuteQueryAroundPos(position, 0, range, players, IID_ResourceSupply); + // Don't account for entity size, we need to match LOS visibility. + let nearby = cmpRangeManager.ExecuteQueryAroundPos(position, 0, range, players, IID_ResourceSupply, false); return nearby.find(ent => { if (!this.CanGather(ent) || !this.CheckTargetVisible(ent)) return false; @@ -4476,7 +4486,7 @@ UnitAI.prototype.FindNearestDropsite = function(genericType) let owner = cmpOwnership.GetOwner(); let cmpPlayer = QueryOwnerInterface(this.entity); let players = cmpPlayer && cmpPlayer.HasSharedDropsites() ? cmpPlayer.GetMutualAllies() : [owner]; - let nearestDropsites = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager).ExecuteQuery(this.entity, 0, -1, players, IID_ResourceDropsite); + let nearestDropsites = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager).ExecuteQuery(this.entity, 0, -1, players, IID_ResourceDropsite, false); let isShip = Engine.QueryInterface(this.entity, IID_Identity).HasClass("Ship"); let cmpObstructionManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ObstructionManager); @@ -4526,7 +4536,8 @@ UnitAI.prototype.FindNearbyFoundation = function(position) let range = 64; // TODO: what's a sensible number? let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); - let nearby = cmpRangeManager.ExecuteQueryAroundPos(position, 0, range, players, IID_Foundation); + // Don't account for entity size, we need to match LOS visibility. + let nearby = cmpRangeManager.ExecuteQueryAroundPos(position, 0, range, players, IID_Foundation, false); // Skip foundations that are already complete. (This matters since // we process the ConstructionFinished message before the foundation @@ -6556,7 +6567,7 @@ UnitAI.prototype.CallPlayerOwnedEntitiesFunctionInRange = function(funcname, arg if (owner == INVALID_PLAYER) return; let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); - let nearby = cmpRangeManager.ExecuteQuery(this.entity, 0, range, [owner], IID_UnitAI); + let nearby = cmpRangeManager.ExecuteQuery(this.entity, 0, range, [owner], IID_UnitAI, true); for (let i = 0; i < nearby.length; ++i) { let cmpUnitAI = Engine.QueryInterface(nearby[i], IID_UnitAI); diff --git a/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js b/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js index e75b704f70..7ff5d41770 100644 --- a/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js +++ b/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js @@ -122,7 +122,7 @@ function TestFormationExiting(mode) }); AddMock(SYSTEM_ENTITY, IID_RangeManager, { - CreateActiveQuery: function(ent, minRange, maxRange, players, iid, flags) { + CreateActiveQuery: function(ent, minRange, maxRange, players, iid, flags, accountForSize) { return 1; }, EnableActiveQuery: function(id) { }, @@ -293,7 +293,7 @@ function TestMoveIntoFormationWhileAttacking() AddMock(SYSTEM_ENTITY, IID_RangeManager, { - CreateActiveQuery: function(ent, minRange, maxRange, players, iid, flags) { + CreateActiveQuery: function(ent, minRange, maxRange, players, iid, flags, accountForSize) { return 1; }, EnableActiveQuery: function(id) { }, diff --git a/binaries/data/mods/public/simulation/data/auras/structures/iber_monument.json b/binaries/data/mods/public/simulation/data/auras/structures/iber_monument.json index 98e471864c..44e07c8071 100644 --- a/binaries/data/mods/public/simulation/data/auras/structures/iber_monument.json +++ b/binaries/data/mods/public/simulation/data/auras/structures/iber_monument.json @@ -1,6 +1,6 @@ { "type": "range", - "radius": 45, + "radius": 50, "affects": ["Soldier"], "modifications": [ { "value": "Attack/Melee/Damage/Hack", "multiply": 1.2 }, diff --git a/binaries/data/mods/public/simulation/data/auras/structures/kush_pyramids_economic.json b/binaries/data/mods/public/simulation/data/auras/structures/kush_pyramids_economic.json index a306ac94f2..2c841743bc 100644 --- a/binaries/data/mods/public/simulation/data/auras/structures/kush_pyramids_economic.json +++ b/binaries/data/mods/public/simulation/data/auras/structures/kush_pyramids_economic.json @@ -1,6 +1,6 @@ { "type": "range", - "radius": 50, + "radius": 60, "affects": ["Worker"], "modifications": [ { "value": "ResourceGatherer/BaseSpeed", "multiply": 1.15 } diff --git a/binaries/data/mods/public/simulation/data/auras/structures/kush_pyramids_military.json b/binaries/data/mods/public/simulation/data/auras/structures/kush_pyramids_military.json index cfc1050e5e..16a6434c41 100644 --- a/binaries/data/mods/public/simulation/data/auras/structures/kush_pyramids_military.json +++ b/binaries/data/mods/public/simulation/data/auras/structures/kush_pyramids_military.json @@ -1,6 +1,6 @@ { "type": "range", - "radius": 55, + "radius": 70, "affects": ["Soldier"], "modifications": [ { "value": "Attack/Melee/Damage/Hack", "multiply": 1.1 }, diff --git a/binaries/data/mods/public/simulation/data/auras/structures/loyalty_regen.json b/binaries/data/mods/public/simulation/data/auras/structures/loyalty_regen.json index 63bb9fdbab..1093c05bab 100644 --- a/binaries/data/mods/public/simulation/data/auras/structures/loyalty_regen.json +++ b/binaries/data/mods/public/simulation/data/auras/structures/loyalty_regen.json @@ -1,6 +1,6 @@ { "type": "range", - "radius": 60, + "radius": 75, "affects": ["Structure"], "modifications": [ { "value": "Capturable/GarrisonRegenRate", "multiply": 1.5 } diff --git a/binaries/data/mods/public/simulation/data/auras/structures/maur_pillar.json b/binaries/data/mods/public/simulation/data/auras/structures/maur_pillar.json index 533ca35b46..7b279eea68 100644 --- a/binaries/data/mods/public/simulation/data/auras/structures/maur_pillar.json +++ b/binaries/data/mods/public/simulation/data/auras/structures/maur_pillar.json @@ -1,6 +1,6 @@ { "type": "range", - "radius": 70, + "radius": 75, "affects": ["Trader"], "modifications": [ { "value": "UnitMotion/WalkSpeed", "multiply": 1.2 } diff --git a/binaries/data/mods/public/simulation/data/auras/structures/rotary_mill.json b/binaries/data/mods/public/simulation/data/auras/structures/rotary_mill.json index efe38106d3..375f259385 100644 --- a/binaries/data/mods/public/simulation/data/auras/structures/rotary_mill.json +++ b/binaries/data/mods/public/simulation/data/auras/structures/rotary_mill.json @@ -1,6 +1,6 @@ { "type": "range", - "radius": 50, + "radius": 60, "affects": ["Worker"], "modifications": [ { "value": "ResourceGatherer/Rates/food.grain", "multiply": 1.25 } diff --git a/binaries/data/mods/public/simulation/data/auras/structures/temple_heal.json b/binaries/data/mods/public/simulation/data/auras/structures/temple_heal.json index c08c5a63a6..c09c3b3452 100644 --- a/binaries/data/mods/public/simulation/data/auras/structures/temple_heal.json +++ b/binaries/data/mods/public/simulation/data/auras/structures/temple_heal.json @@ -1,6 +1,6 @@ { "type": "range", - "radius": 20, + "radius": 40, "affects": ["Human"], "modifications": [ { "value": "Health/RegenRate", "add": 1 } diff --git a/binaries/data/mods/public/simulation/helpers/Position.js b/binaries/data/mods/public/simulation/helpers/Position.js index 60e3c79f9e..a5fe7a3449 100644 --- a/binaries/data/mods/public/simulation/helpers/Position.js +++ b/binaries/data/mods/public/simulation/helpers/Position.js @@ -34,7 +34,7 @@ PositionHelper.prototype.EntitiesNearPoint = function(origin, radius, players, i return []; let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); - return cmpRangeManager.ExecuteQueryAroundPos(origin, 0, radius, players, iid); + return cmpRangeManager.ExecuteQueryAroundPos(origin, 0, radius, players, iid, true); }; /** diff --git a/binaries/data/mods/public/simulation/templates/structures/iber/monument.xml b/binaries/data/mods/public/simulation/templates/structures/iber/monument.xml index c6266d7f91..6fb0243990 100644 --- a/binaries/data/mods/public/simulation/templates/structures/iber/monument.xml +++ b/binaries/data/mods/public/simulation/templates/structures/iber/monument.xml @@ -7,7 +7,7 @@ Monument Monument - 145 + 150 diff --git a/binaries/data/mods/public/simulation/templates/structures/maur/pillar_ashoka.xml b/binaries/data/mods/public/simulation/templates/structures/maur/pillar_ashoka.xml index 9a00fe2abd..61a12bfd56 100644 --- a/binaries/data/mods/public/simulation/templates/structures/maur/pillar_ashoka.xml +++ b/binaries/data/mods/public/simulation/templates/structures/maur/pillar_ashoka.xml @@ -7,7 +7,7 @@ Pillar Pillar - 70 + 75 diff --git a/binaries/data/mods/public/simulation/templates/structures/merc_camp_egyptian.xml b/binaries/data/mods/public/simulation/templates/structures/merc_camp_egyptian.xml index 00bf821b02..4afedef66c 100644 --- a/binaries/data/mods/public/simulation/templates/structures/merc_camp_egyptian.xml +++ b/binaries/data/mods/public/simulation/templates/structures/merc_camp_egyptian.xml @@ -4,7 +4,7 @@ own neutral MercenaryCamp - 70 + 100 diff --git a/binaries/data/mods/public/simulation/templates/structures/ptol/mercenary_camp.xml b/binaries/data/mods/public/simulation/templates/structures/ptol/mercenary_camp.xml index 27fe9a28ef..edc550b7be 100644 --- a/binaries/data/mods/public/simulation/templates/structures/ptol/mercenary_camp.xml +++ b/binaries/data/mods/public/simulation/templates/structures/ptol/mercenary_camp.xml @@ -4,7 +4,7 @@ own neutral MercenaryCamp - 70 + 100 diff --git a/binaries/data/mods/public/simulation/templates/structures/rome/army_camp.xml b/binaries/data/mods/public/simulation/templates/structures/rome/army_camp.xml index 51d49d2a30..f42e68df2d 100644 --- a/binaries/data/mods/public/simulation/templates/structures/rome/army_camp.xml +++ b/binaries/data/mods/public/simulation/templates/structures/rome/army_camp.xml @@ -38,7 +38,7 @@ ArmyCamp ArmyCamp - 45 + 80 diff --git a/binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml b/binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml index a9dbf4ab23..952530408a 100644 --- a/binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml +++ b/binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml @@ -2,8 +2,8 @@ FemaleCitizen - 140 - 190 + 120 + 180 100 @@ -44,7 +44,7 @@ CivilCentre CivilCentre - 160 + 200 diff --git a/binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre_military_colony.xml b/binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre_military_colony.xml index 465739d787..c4edb5dfb4 100644 --- a/binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre_military_colony.xml +++ b/binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre_military_colony.xml @@ -8,7 +8,7 @@ Colony CivilCentre - 80 + 120 diff --git a/binaries/data/mods/public/simulation/templates/template_structure_defensive_outpost.xml b/binaries/data/mods/public/simulation/templates/template_structure_defensive_outpost.xml index 607f7f3a23..3bff2e1f1c 100644 --- a/binaries/data/mods/public/simulation/templates/template_structure_defensive_outpost.xml +++ b/binaries/data/mods/public/simulation/templates/template_structure_defensive_outpost.xml @@ -7,7 +7,7 @@ own neutral Outpost - 45 + 50 diff --git a/binaries/data/mods/public/simulation/templates/template_structure_defensive_tower.xml b/binaries/data/mods/public/simulation/templates/template_structure_defensive_tower.xml index 9d95538b8e..0eb66f3455 100644 --- a/binaries/data/mods/public/simulation/templates/template_structure_defensive_tower.xml +++ b/binaries/data/mods/public/simulation/templates/template_structure_defensive_tower.xml @@ -37,7 +37,7 @@ Tower Tower - 55 + 60 diff --git a/binaries/data/mods/public/simulation/templates/template_structure_economic_farmstead.xml b/binaries/data/mods/public/simulation/templates/template_structure_economic_farmstead.xml index 0e1032fe08..0bd663f8ff 100644 --- a/binaries/data/mods/public/simulation/templates/template_structure_economic_farmstead.xml +++ b/binaries/data/mods/public/simulation/templates/template_structure_economic_farmstead.xml @@ -2,7 +2,7 @@ FemaleCitizen - 60 + 50 100 100 diff --git a/binaries/data/mods/public/simulation/templates/template_structure_economic_storehouse.xml b/binaries/data/mods/public/simulation/templates/template_structure_economic_storehouse.xml index b832c850f1..aac21a1d0c 100644 --- a/binaries/data/mods/public/simulation/templates/template_structure_economic_storehouse.xml +++ b/binaries/data/mods/public/simulation/templates/template_structure_economic_storehouse.xml @@ -2,7 +2,7 @@ FemaleCitizen - 60 + 50 100 100 diff --git a/binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml b/binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml index 3ec44a59f4..6cc676939b 100644 --- a/binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml +++ b/binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml @@ -37,7 +37,7 @@ Fortress Fortress - 55 + 80 diff --git a/source/simulation2/components/CCmpRangeManager.cpp b/source/simulation2/components/CCmpRangeManager.cpp index 1272cab74c..0a1af40900 100644 --- a/source/simulation2/components/CCmpRangeManager.cpp +++ b/source/simulation2/components/CCmpRangeManager.cpp @@ -153,6 +153,7 @@ struct Query u8 flagsMask; bool enabled; bool parabolic; + bool accountForSize; // If true, the query accounts for unit sizes, otherwise it treats all entities as points. }; /** @@ -244,8 +245,6 @@ struct SerializeHelper template void Common(S& serialize, const char* UNUSED(name), Serialize::qualify value) { - serialize.Bool("enabled", value.enabled); - serialize.Bool("parabolic",value.parabolic); serialize.NumberFixed_Unbounded("min range", value.minRange); serialize.NumberFixed_Unbounded("max range", value.maxRange); serialize.NumberFixed_Unbounded("elevation bonus", value.elevationBonus); @@ -253,6 +252,9 @@ struct SerializeHelper serialize.NumberI32_Unbounded("interface", value.interface); Serializer(serialize, "last match", value.lastMatch); serialize.NumberU8_Unbounded("flagsMask", value.flagsMask); + serialize.Bool("enabled", value.enabled); + serialize.Bool("parabolic",value.parabolic); + serialize.Bool("account for size",value.accountForSize); } void operator()(ISerializer& serialize, const char* name, Query& value, const CSimContext& UNUSED(context)) @@ -907,10 +909,10 @@ public: virtual tag_t CreateActiveQuery(entity_id_t source, entity_pos_t minRange, entity_pos_t maxRange, - const std::vector& owners, int requiredInterface, u8 flags) + const std::vector& owners, int requiredInterface, u8 flags, bool accountForSize) { tag_t id = m_QueryNext++; - m_Queries[id] = ConstructQuery(source, minRange, maxRange, owners, requiredInterface, flags); + m_Queries[id] = ConstructQuery(source, minRange, maxRange, owners, requiredInterface, flags, accountForSize); return id; } @@ -920,7 +922,7 @@ public: const std::vector& owners, int requiredInterface, u8 flags) { tag_t id = m_QueryNext++; - m_Queries[id] = ConstructParabolicQuery(source, minRange, maxRange, elevationBonus, owners, requiredInterface, flags); + m_Queries[id] = ConstructParabolicQuery(source, minRange, maxRange, elevationBonus, owners, requiredInterface, flags, true); return id; } @@ -977,9 +979,9 @@ public: virtual std::vector ExecuteQueryAroundPos(const CFixedVector2D& pos, entity_pos_t minRange, entity_pos_t maxRange, - const std::vector& owners, int requiredInterface) + const std::vector& owners, int requiredInterface, bool accountForSize) { - Query q = ConstructQuery(INVALID_ENTITY, minRange, maxRange, owners, requiredInterface, GetEntityFlagMask("normal")); + Query q = ConstructQuery(INVALID_ENTITY, minRange, maxRange, owners, requiredInterface, GetEntityFlagMask("normal"), accountForSize); std::vector r; PerformQuery(q, r, pos); @@ -991,11 +993,11 @@ public: virtual std::vector ExecuteQuery(entity_id_t source, entity_pos_t minRange, entity_pos_t maxRange, - const std::vector& owners, int requiredInterface) + const std::vector& owners, int requiredInterface, bool accountForSize) { PROFILE("ExecuteQuery"); - Query q = ConstructQuery(source, minRange, maxRange, owners, requiredInterface, GetEntityFlagMask("normal")); + Query q = ConstructQuery(source, minRange, maxRange, owners, requiredInterface, GetEntityFlagMask("normal"), accountForSize); std::vector r; @@ -1221,8 +1223,8 @@ public: // they have an intersection after which the former grows slower, and then use that to prove the above. // Note that this is only true because we do not account for vertical size here, // if we did, we would also need to artificially 'raise' the source over the target. - if (!InParabolicRange(CFixedVector3D(it->second.x, secondPosition.Y, it->second.z) - pos3d, - q.maxRange + fixed::FromInt(it->second.size))) + entity_pos_t range = q.maxRange + (q.accountForSize ? fixed::FromInt(it->second.size) : fixed::Zero()); + if (!InParabolicRange(CFixedVector3D(it->second.x, secondPosition.Y, it->second.z) - pos3d, range)) continue; if (!q.minRange.IsZero()) @@ -1249,7 +1251,8 @@ public: continue; // Restrict based on approximate circle-circle distance. - if ((CFixedVector2D(it->second.x, it->second.z) - pos).CompareLength(q.maxRange + fixed::FromInt(it->second.size)) > 0) + entity_pos_t range = q.maxRange + (q.accountForSize ? fixed::FromInt(it->second.size) : fixed::Zero()); + if ((CFixedVector2D(it->second.x, it->second.z) - pos).CompareLength(range) > 0) continue; if (!q.minRange.IsZero()) @@ -1364,7 +1367,7 @@ public: Query ConstructQuery(entity_id_t source, entity_pos_t minRange, entity_pos_t maxRange, - const std::vector& owners, int requiredInterface, u8 flagsMask) const + const std::vector& owners, int requiredInterface, u8 flagsMask, bool accountForSize) const { // Min range must be non-negative if (minRange < entity_pos_t::Zero()) @@ -1381,8 +1384,9 @@ public: q.minRange = minRange; q.maxRange = maxRange; q.elevationBonus = entity_pos_t::Zero(); + q.accountForSize = accountForSize; - if (q.source.GetId() != INVALID_ENTITY && q.maxRange != entity_pos_t::FromInt(-1)) + if (q.accountForSize && q.source.GetId() != INVALID_ENTITY && q.maxRange != entity_pos_t::FromInt(-1)) { u32 size = 0; if (ENTITY_IS_LOCAL(q.source.GetId())) @@ -1418,9 +1422,9 @@ public: Query ConstructParabolicQuery(entity_id_t source, entity_pos_t minRange, entity_pos_t maxRange, entity_pos_t elevationBonus, - const std::vector& owners, int requiredInterface, u8 flagsMask) const + const std::vector& owners, int requiredInterface, u8 flagsMask, bool accountForSize) const { - Query q = ConstructQuery(source,minRange,maxRange,owners,requiredInterface,flagsMask); + Query q = ConstructQuery(source, minRange, maxRange, owners, requiredInterface, flagsMask, accountForSize); q.parabolic = true; q.elevationBonus = elevationBonus; return q; diff --git a/source/simulation2/components/ICmpRangeManager.cpp b/source/simulation2/components/ICmpRangeManager.cpp index 0ebc994dd3..3a739100e3 100644 --- a/source/simulation2/components/ICmpRangeManager.cpp +++ b/source/simulation2/components/ICmpRangeManager.cpp @@ -45,9 +45,9 @@ std::string ICmpRangeManager::GetLosVisibilityPosition_wrapper(entity_pos_t x, e } BEGIN_INTERFACE_WRAPPER(RangeManager) -DEFINE_INTERFACE_METHOD_5("ExecuteQuery", std::vector, ICmpRangeManager, ExecuteQuery, entity_id_t, entity_pos_t, entity_pos_t, std::vector, int) -DEFINE_INTERFACE_METHOD_5("ExecuteQueryAroundPos", std::vector, ICmpRangeManager, ExecuteQueryAroundPos, CFixedVector2D, entity_pos_t, entity_pos_t, std::vector, int) -DEFINE_INTERFACE_METHOD_6("CreateActiveQuery", ICmpRangeManager::tag_t, ICmpRangeManager, CreateActiveQuery, entity_id_t, entity_pos_t, entity_pos_t, std::vector, int, u8) +DEFINE_INTERFACE_METHOD_6("ExecuteQuery", std::vector, ICmpRangeManager, ExecuteQuery, entity_id_t, entity_pos_t, entity_pos_t, std::vector, int, bool) +DEFINE_INTERFACE_METHOD_6("ExecuteQueryAroundPos", std::vector, ICmpRangeManager, ExecuteQueryAroundPos, CFixedVector2D, entity_pos_t, entity_pos_t, std::vector, int, bool) +DEFINE_INTERFACE_METHOD_7("CreateActiveQuery", ICmpRangeManager::tag_t, ICmpRangeManager, CreateActiveQuery, entity_id_t, entity_pos_t, entity_pos_t, std::vector, int, u8, bool) DEFINE_INTERFACE_METHOD_7("CreateActiveParabolicQuery", ICmpRangeManager::tag_t, ICmpRangeManager, CreateActiveParabolicQuery, entity_id_t, entity_pos_t, entity_pos_t, entity_pos_t, std::vector, int, u8) DEFINE_INTERFACE_METHOD_1("DestroyActiveQuery", void, ICmpRangeManager, DestroyActiveQuery, ICmpRangeManager::tag_t) DEFINE_INTERFACE_METHOD_1("EnableActiveQuery", void, ICmpRangeManager, EnableActiveQuery, ICmpRangeManager::tag_t) diff --git a/source/simulation2/components/ICmpRangeManager.h b/source/simulation2/components/ICmpRangeManager.h index ca0bcf8da1..4e71e2e49f 100644 --- a/source/simulation2/components/ICmpRangeManager.h +++ b/source/simulation2/components/ICmpRangeManager.h @@ -73,7 +73,8 @@ class CLosQuerier; * * In most cases the users are event-based and want notifications when something * has entered or left the range, and the query can be set up once and rarely changed. - * These queries have to be fast. Entities are approximated as circles. + * These queries have to be fast. Entities are approximated as points or circles + * (queries can be set up to ignore sizes because LOS currently ignores it, and mismatches are problematic). * * Current design: * @@ -116,10 +117,11 @@ public: * @param maxRange non-negative maximum distance in metres (inclusive); or -1.0 to ignore distance. * @param owners list of player IDs that matching entities may have; -1 matches entities with no owner. * @param requiredInterface if non-zero, an interface ID that matching entities must implement. + * @param accountForSize if true, compensate for source/target entity sizes. * @return list of entities matching the query, ordered by increasing distance from the source entity. */ - virtual std::vector ExecuteQuery(entity_id_t source, - entity_pos_t minRange, entity_pos_t maxRange, const std::vector& owners, int requiredInterface) = 0; + virtual std::vector ExecuteQuery(entity_id_t source, entity_pos_t minRange, entity_pos_t maxRange, + const std::vector& owners, int requiredInterface, bool accountForSize) = 0; /** * Execute a passive query. @@ -128,10 +130,11 @@ public: * @param maxRange non-negative maximum distance in metres (inclusive); or -1.0 to ignore distance. * @param owners list of player IDs that matching entities may have; -1 matches entities with no owner. * @param requiredInterface if non-zero, an interface ID that matching entities must implement. + * @param accountForSize if true, compensate for source/target entity sizes. * @return list of entities matching the query, ordered by increasing distance from the source entity. */ - virtual std::vector ExecuteQueryAroundPos(const CFixedVector2D& pos, - entity_pos_t minRange, entity_pos_t maxRange, const std::vector& owners, int requiredInterface) = 0; + virtual std::vector ExecuteQueryAroundPos(const CFixedVector2D& pos, entity_pos_t minRange, entity_pos_t maxRange, + const std::vector& owners, int requiredInterface, bool accountForSize) = 0; /** * Construct an active query. The query will be disabled by default. @@ -141,10 +144,11 @@ public: * @param owners list of player IDs that matching entities may have; -1 matches entities with no owner. * @param requiredInterface if non-zero, an interface ID that matching entities must implement. * @param flags if a entity in range has one of the flags set it will show up. + * @param accountForSize if true, compensate for source/target entity sizes. * @return unique non-zero identifier of query. */ - virtual tag_t CreateActiveQuery(entity_id_t source, - entity_pos_t minRange, entity_pos_t maxRange, const std::vector& owners, int requiredInterface, u8 flags) = 0; + virtual tag_t CreateActiveQuery(entity_id_t source, entity_pos_t minRange, entity_pos_t maxRange, + const std::vector& owners, int requiredInterface, u8 flags, bool accountForSize) = 0; /** * Construct an active query of a paraboloic form around the unit. @@ -158,10 +162,11 @@ public: * @param owners list of player IDs that matching entities may have; -1 matches entities with no owner. * @param requiredInterface if non-zero, an interface ID that matching entities must implement. * @param flags if a entity in range has one of the flags set it will show up. + * NB: this one has no accountForSize parameter (assumed true), because we currently can only have 7 arguments for JS functions. * @return unique non-zero identifier of query. */ - virtual tag_t CreateActiveParabolicQuery(entity_id_t source, - entity_pos_t minRange, entity_pos_t maxRange, entity_pos_t elevationBonus, const std::vector& owners, int requiredInterface, u8 flags) = 0; + virtual tag_t CreateActiveParabolicQuery(entity_id_t source, entity_pos_t minRange, entity_pos_t maxRange, entity_pos_t elevationBonus, + const std::vector& owners, int requiredInterface, u8 flags) = 0; /** diff --git a/source/simulation2/components/tests/test_RangeManager.h b/source/simulation2/components/tests/test_RangeManager.h index 5bd3fc9a7a..db17c4b71d 100644 --- a/source/simulation2/components/tests/test_RangeManager.h +++ b/source/simulation2/components/tests/test_RangeManager.h @@ -230,41 +230,41 @@ public: move(100, position, fixed::FromInt(10), fixed::FromInt(10)); move(101, position2, fixed::FromInt(10), fixed::FromInt(20)); - std::vector nearby = cmp->ExecuteQuery(100, fixed::FromInt(0), fixed::FromInt(4), {1}, 0); + std::vector nearby = cmp->ExecuteQuery(100, fixed::FromInt(0), fixed::FromInt(4), {1}, 0, true); TS_ASSERT_EQUALS(nearby, std::vector{}); - nearby = cmp->ExecuteQuery(100, fixed::FromInt(4), fixed::FromInt(50), {1}, 0); + nearby = cmp->ExecuteQuery(100, fixed::FromInt(4), fixed::FromInt(50), {1}, 0, true); TS_ASSERT_EQUALS(nearby, std::vector{101}); move(101, position2, fixed::FromInt(10), fixed::FromInt(10)); - nearby = cmp->ExecuteQuery(100, fixed::FromInt(0), fixed::FromInt(4), {1}, 0); + nearby = cmp->ExecuteQuery(100, fixed::FromInt(0), fixed::FromInt(4), {1}, 0, true); TS_ASSERT_EQUALS(nearby, std::vector{101}); - nearby = cmp->ExecuteQuery(100, fixed::FromInt(4), fixed::FromInt(50), {1}, 0); + nearby = cmp->ExecuteQuery(100, fixed::FromInt(4), fixed::FromInt(50), {1}, 0, true); TS_ASSERT_EQUALS(nearby, std::vector{}); move(101, position2, fixed::FromInt(10), fixed::FromInt(13)); - nearby = cmp->ExecuteQuery(100, fixed::FromInt(0), fixed::FromInt(4), {1}, 0); + nearby = cmp->ExecuteQuery(100, fixed::FromInt(0), fixed::FromInt(4), {1}, 0, true); TS_ASSERT_EQUALS(nearby, std::vector{101}); - nearby = cmp->ExecuteQuery(100, fixed::FromInt(4), fixed::FromInt(50), {1}, 0); + nearby = cmp->ExecuteQuery(100, fixed::FromInt(4), fixed::FromInt(50), {1}, 0, true); TS_ASSERT_EQUALS(nearby, std::vector{}); move(101, position2, fixed::FromInt(10), fixed::FromInt(15)); // In range thanks to self obstruction size. - nearby = cmp->ExecuteQuery(100, fixed::FromInt(0), fixed::FromInt(4), {1}, 0); + nearby = cmp->ExecuteQuery(100, fixed::FromInt(0), fixed::FromInt(4), {1}, 0, true); TS_ASSERT_EQUALS(nearby, std::vector{101}); // In range thanks to target obstruction size. - nearby = cmp->ExecuteQuery(101, fixed::FromInt(0), fixed::FromInt(4), {1}, 0); + nearby = cmp->ExecuteQuery(101, fixed::FromInt(0), fixed::FromInt(4), {1}, 0, true); TS_ASSERT_EQUALS(nearby, std::vector{100}); // Trickier: min-range is closest-to-closest, but rotation may change the real distance. - nearby = cmp->ExecuteQuery(100, fixed::FromInt(2), fixed::FromInt(50), {1}, 0); + nearby = cmp->ExecuteQuery(100, fixed::FromInt(2), fixed::FromInt(50), {1}, 0, true); TS_ASSERT_EQUALS(nearby, std::vector{101}); - nearby = cmp->ExecuteQuery(100, fixed::FromInt(5), fixed::FromInt(50), {1}, 0); + nearby = cmp->ExecuteQuery(100, fixed::FromInt(5), fixed::FromInt(50), {1}, 0, true); TS_ASSERT_EQUALS(nearby, std::vector{101}); - nearby = cmp->ExecuteQuery(100, fixed::FromInt(6), fixed::FromInt(50), {1}, 0); + nearby = cmp->ExecuteQuery(100, fixed::FromInt(6), fixed::FromInt(50), {1}, 0, true); TS_ASSERT_EQUALS(nearby, std::vector{}); - nearby = cmp->ExecuteQuery(101, fixed::FromInt(5), fixed::FromInt(50), {1}, 0); + nearby = cmp->ExecuteQuery(101, fixed::FromInt(5), fixed::FromInt(50), {1}, 0, true); TS_ASSERT_EQUALS(nearby, std::vector{100}); - nearby = cmp->ExecuteQuery(101, fixed::FromInt(6), fixed::FromInt(50), {1}, 0); + nearby = cmp->ExecuteQuery(101, fixed::FromInt(6), fixed::FromInt(50), {1}, 0, true); TS_ASSERT_EQUALS(nearby, std::vector{}); }