Ticket #2242: swimmer-v2.diff
File swimmer-v2.diff, 29.6 KB (added by , 10 years ago) |
---|
-
binaries/data/mods/public/simulation/components/GarrisonHolder.js
13 13 "<element name='EjectHealth' a:help='Percentage of maximum health below which this holder no longer allows garrisoning'>" + 14 14 "<ref name='nonNegativeDecimal'/>" + 15 15 "</element>" + 16 "<element name='EjectEntitiesOnDestroy' a:help='Whether the entity should eject or kill all garrisoned entities on destroy'>" + 17 "<data type='boolean'/>" + 16 "<element name='EjectClassesOnDestroy' a:help='Classes of entities to be ejected on destroy. Others are killed'>" + 17 "<attribute name='datatype'>" + 18 "<value>tokens</value>" + 19 "</attribute>" + 20 "<text/>" + 18 21 "</element>" + 19 22 "<element name='BuffHeal' a:help='Number of hit points that will be restored to this holder's garrisoned units each second'>" + 20 23 "<ref name='nonNegativeDecimal'/>" + … … 105 108 return ApplyValueModificationsToEntity("GarrisonHolder/BuffHeal", +this.template.BuffHeal, this.entity); 106 109 }; 107 110 108 GarrisonHolder.prototype.EjectEntitiesOnDestroy = function()109 {110 return this.template.EjectEntitiesOnDestroy == "true";111 };112 113 111 /** 114 112 * Set this entity to allow or disallow garrisoning in 115 113 * Every component calling this function should do it with its own ID, and as long as one … … 270 268 271 269 // Find spawning location 272 270 var cmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint); 273 var pos = cmpFootprint.PickSpawnPoint(entity); 271 var cmpHealth = Engine.QueryInterface(this.entity, IID_Health); 272 var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity); 273 // If the garrisonHolder is a sinking ship, restrict the location to the intersection of both passabilities 274 // TODO: should use passability classes to be more generic 275 if ((!cmpHealth || cmpHealth.GetHitpoints() == 0) && cmpIdentity && cmpIdentity.HasClass("Ship")) 276 var pos = cmpFootprint.PickSpawnPointBothPass(entity); 277 else 278 var pos = cmpFootprint.PickSpawnPoint(entity); 279 274 280 if (pos.y < 0) 275 281 { 276 282 // Error: couldn't find space satisfying the unit's passability criteria … … 602 608 var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); 603 609 // Eject the units which can be ejected (if not in world, it generally means this holder 604 610 // is inside a holder which kills its entities, so do not eject) 605 if (cmpPosition.IsInWorld() && this.EjectEntitiesOnDestroy()) 606 this.PerformEject(entities, true); 611 if (cmpPosition.IsInWorld()) 612 { 613 var cmpGarrisonHolder = this; 614 var ejectables = entities.filter(function(ent) { return cmpGarrisonHolder.IsEjectable(ent) }); 615 if (ejectables.length) 616 this.PerformEject(ejectables, false); 617 } 607 618 608 619 // And destroy all remaining entities 609 620 for each (var entity in entities) … … 621 632 this.UpdateGarrisonFlag(); 622 633 }; 623 634 635 /** 636 * Checks if an entity is ejectable on destroy if possible 637 */ 638 GarrisonHolder.prototype.IsEjectable = function(entity) 639 { 640 var ejectableClasses = this.template.EjectClassesOnDestroy._string; 641 ejectableClasses = ejectableClasses ? ejectableClasses.split(/\s+/) : []; 642 var entityClasses = (Engine.QueryInterface(entity, IID_Identity)).GetClassesList(); 643 for each (var ejectableClass in ejectableClasses) 644 if (entityClasses.indexOf(ejectableClass) != -1) 645 return true; 646 647 return false; 648 }; 649 624 650 Engine.RegisterComponentType(IID_GarrisonHolder, "GarrisonHolder", GarrisonHolder); 625 651 -
binaries/data/mods/public/simulation/templates/other/plane.xml
24 24 <List datatype="tokens">Support Infantry</List> 25 25 <BuffHeal>1</BuffHeal> 26 26 <LoadingRange>5</LoadingRange> 27 <Eject EntitiesOnDestroy>false</EjectEntitiesOnDestroy>27 <EjectClassesOnDestroy datatype="tokens" /> 28 28 </GarrisonHolder> 29 29 <Decay> 30 30 <Inactive/> -
binaries/data/mods/public/simulation/templates/structures/athen_wonder.xml
7 7 <GarrisonHolder> 8 8 <Max>30</Max> 9 9 <EjectHealth>0.1</EjectHealth> 10 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>10 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 11 11 <List datatype="tokens">Support Infantry Cavalry</List> 12 12 <BuffHeal>3</BuffHeal> 13 13 <LoadingRange>2</LoadingRange> -
binaries/data/mods/public/simulation/templates/structures/cart_wonder.xml
7 7 <GarrisonHolder> 8 8 <Max>30</Max> 9 9 <EjectHealth>0.1</EjectHealth> 10 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>10 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 11 11 <List datatype="tokens">Support Infantry Cavalry</List> 12 12 <BuffHeal>3</BuffHeal> 13 13 <LoadingRange>2</LoadingRange> -
binaries/data/mods/public/simulation/templates/structures/hele_wonder.xml
7 7 <GarrisonHolder> 8 8 <Max>30</Max> 9 9 <EjectHealth>0.1</EjectHealth> 10 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>10 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 11 11 <List datatype="tokens">Support Infantry Cavalry</List> 12 12 <BuffHeal>3</BuffHeal> 13 13 <LoadingRange>2</LoadingRange> -
binaries/data/mods/public/simulation/templates/structures/mace_wonder.xml
7 7 <GarrisonHolder> 8 8 <Max>30</Max> 9 9 <EjectHealth>0.1</EjectHealth> 10 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>10 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 11 11 <List datatype="tokens">Support Infantry Cavalry</List> 12 12 <BuffHeal>3</BuffHeal> 13 13 <LoadingRange>2</LoadingRange> -
binaries/data/mods/public/simulation/templates/structures/ptol_wonder.xml
7 7 <GarrisonHolder> 8 8 <Max>30</Max> 9 9 <EjectHealth>0.1</EjectHealth> 10 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>10 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 11 11 <List datatype="tokens">Support Infantry Cavalry</List> 12 12 <BuffHeal>3</BuffHeal> 13 13 <LoadingRange>2</LoadingRange> -
binaries/data/mods/public/simulation/templates/structures/rome_tent.xml
16 16 <GarrisonHolder> 17 17 <Max>5</Max> 18 18 <EjectHealth>0.1</EjectHealth> 19 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>19 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 20 20 <List datatype="tokens">Support Infantry</List> 21 21 <BuffHeal>0</BuffHeal> 22 22 <LoadingRange>2</LoadingRange> -
binaries/data/mods/public/simulation/templates/structures/rome_wonder.xml
7 7 <GarrisonHolder> 8 8 <Max>30</Max> 9 9 <EjectHealth>0.1</EjectHealth> 10 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>10 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 11 11 <List datatype="tokens">Support Infantry Cavalry</List> 12 12 <BuffHeal>3</BuffHeal> 13 13 <LoadingRange>2</LoadingRange> -
binaries/data/mods/public/simulation/templates/structures/spart_wonder.xml
7 7 <GarrisonHolder> 8 8 <Max>30</Max> 9 9 <EjectHealth>0.1</EjectHealth> 10 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>10 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 11 11 <List datatype="tokens">Support Infantry Cavalry</List> 12 12 <BuffHeal>3</BuffHeal> 13 13 <LoadingRange>2</LoadingRange> -
binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml
49 49 <GarrisonHolder> 50 50 <Max>20</Max> 51 51 <EjectHealth>0.1</EjectHealth> 52 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>52 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 53 53 <List datatype="tokens">Support Infantry Cavalry</List> 54 54 <BuffHeal>1</BuffHeal> 55 55 <LoadingRange>1</LoadingRange> -
binaries/data/mods/public/simulation/templates/template_structure_civic_house.xml
18 18 <Max>3</Max> 19 19 <BuffHeal>0</BuffHeal> 20 20 <EjectHealth>0.1</EjectHealth> 21 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>21 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 22 22 <List datatype="tokens">Support</List> 23 23 <LoadingRange>1</LoadingRange> 24 24 </GarrisonHolder> -
binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml
23 23 <GarrisonHolder> 24 24 <Max>20</Max> 25 25 <EjectHealth>0.1</EjectHealth> 26 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>26 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 27 27 <List datatype="tokens">Support Infantry Cavalry</List> 28 28 <BuffHeal>3</BuffHeal> 29 29 <LoadingRange>2</LoadingRange> -
binaries/data/mods/public/simulation/templates/template_structure_defense_defense_tower.xml
46 46 <GarrisonHolder> 47 47 <Max>5</Max> 48 48 <EjectHealth>0.1</EjectHealth> 49 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>49 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 50 50 <List datatype="tokens">Support Infantry</List> 51 51 <BuffHeal>0</BuffHeal> 52 52 <LoadingRange>2</LoadingRange> -
binaries/data/mods/public/simulation/templates/template_structure_defense_outpost.xml
44 44 <GarrisonHolder> 45 45 <Max>1</Max> 46 46 <EjectHealth>0.1</EjectHealth> 47 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>47 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 48 48 <List datatype="tokens">Support Infantry</List> 49 49 <BuffHeal>0</BuffHeal> 50 50 <LoadingRange>2</LoadingRange> -
binaries/data/mods/public/simulation/templates/template_structure_defense_wall_tower.xml
41 41 <GarrisonHolder> 42 42 <Max>5</Max> 43 43 <EjectHealth>0.1</EjectHealth> 44 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>44 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 45 45 <List datatype="tokens">Support Infantry</List> 46 46 <BuffHeal>0</BuffHeal> 47 47 <LoadingRange>2</LoadingRange> -
binaries/data/mods/public/simulation/templates/template_structure_military_barracks.xml
16 16 <GarrisonHolder> 17 17 <Max>10</Max> 18 18 <EjectHealth>0.1</EjectHealth> 19 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>19 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 20 20 <List datatype="tokens">Infantry Cavalry</List> 21 21 <BuffHeal>0</BuffHeal> 22 22 <LoadingRange>2</LoadingRange> -
binaries/data/mods/public/simulation/templates/template_structure_military_blacksmith.xml
16 16 <GarrisonHolder> 17 17 <Max>1</Max> 18 18 <EjectHealth>0.1</EjectHealth> 19 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>19 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 20 20 <List datatype="tokens">Infantry</List> 21 21 <BuffHeal>0</BuffHeal> 22 22 <LoadingRange>2</LoadingRange> -
binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml
46 46 <GarrisonHolder> 47 47 <Max>20</Max> 48 48 <EjectHealth>0.075</EjectHealth> 49 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>49 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 50 50 <List datatype="tokens">Support Infantry Cavalry Siege</List> 51 51 <BuffHeal>0</BuffHeal> 52 52 <LoadingRange>6</LoadingRange> -
binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml
13 13 <GarrisonHolder> 14 14 <Max>10</Max> 15 15 <EjectHealth>0.1</EjectHealth> 16 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>16 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 17 17 <List datatype="tokens">Animal</List> 18 18 <BuffHeal>1</BuffHeal> 19 19 <LoadingRange>2</LoadingRange> -
binaries/data/mods/public/simulation/templates/template_structure_special.xml
29 29 <GarrisonHolder> 30 30 <Max>5</Max> 31 31 <EjectHealth>0.1</EjectHealth> 32 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>32 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 33 33 <List datatype="tokens">Support Infantry Cavalry</List> 34 34 <BuffHeal>1</BuffHeal> 35 35 <LoadingRange>2</LoadingRange> -
binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_bireme.xml
33 33 <GarrisonHolder> 34 34 <Max>20</Max> 35 35 <EjectHealth>0</EjectHealth> 36 <Eject EntitiesOnDestroy>false</EjectEntitiesOnDestroy>36 <EjectClassesOnDestroy datatype="tokens">Female Infantry</EjectClassesOnDestroy> 37 37 <List datatype="tokens">Support Infantry Cavalry</List> 38 38 <BuffHeal>1</BuffHeal> 39 39 <LoadingRange>10</LoadingRange> -
binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_fishing.xml
22 22 <GarrisonHolder> 23 23 <Max>1</Max> 24 24 <EjectHealth>0</EjectHealth> 25 <Eject EntitiesOnDestroy>false</EjectEntitiesOnDestroy>25 <EjectClassesOnDestroy datatype="tokens">Female Infantry</EjectClassesOnDestroy> 26 26 <List datatype="tokens">Support Infantry</List> 27 27 <BuffHeal>1</BuffHeal> 28 28 <LoadingRange>10</LoadingRange> -
binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_merchant.xml
14 14 <GarrisonHolder> 15 15 <Max>15</Max> 16 16 <EjectHealth>0</EjectHealth> 17 <Eject EntitiesOnDestroy>false</EjectEntitiesOnDestroy>17 <EjectClassesOnDestroy datatype="tokens">Female Infantry</EjectClassesOnDestroy> 18 18 <List datatype="tokens">Support Infantry Cavalry</List> 19 19 <BuffHeal>1</BuffHeal> 20 20 <LoadingRange>10</LoadingRange> -
binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_quinquereme.xml
41 41 <GarrisonHolder> 42 42 <Max>50</Max> 43 43 <EjectHealth>0</EjectHealth> 44 <Eject EntitiesOnDestroy>false</EjectEntitiesOnDestroy>44 <EjectClassesOnDestroy datatype="tokens">Female Infantry</EjectClassesOnDestroy> 45 45 <List datatype="tokens">Support Infantry Cavalry Siege</List> 46 46 <BuffHeal>1</BuffHeal> 47 47 <LoadingRange>10</LoadingRange> -
binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_trireme.xml
33 33 <GarrisonHolder> 34 34 <Max>30</Max> 35 35 <EjectHealth>0</EjectHealth> 36 <Eject EntitiesOnDestroy>false</EjectEntitiesOnDestroy>36 <EjectClassesOnDestroy datatype="tokens">Female Infantry</EjectClassesOnDestroy> 37 37 <List datatype="tokens">Support Infantry Cavalry Siege</List> 38 38 <BuffHeal>1</BuffHeal> 39 39 <LoadingRange>10</LoadingRange> -
binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_ram.xml
48 48 <GarrisonHolder> 49 49 <Max>5</Max> 50 50 <EjectHealth>0.1</EjectHealth> 51 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>51 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 52 52 <List datatype="tokens">Support Infantry</List> 53 53 <BuffHeal>1</BuffHeal> 54 54 <LoadingRange>2</LoadingRange> -
binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_tower.xml
46 46 <GarrisonHolder> 47 47 <Max>20</Max> 48 48 <EjectHealth>0.1</EjectHealth> 49 <Eject EntitiesOnDestroy>true</EjectEntitiesOnDestroy>49 <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy> 50 50 <List datatype="tokens">Support Infantry</List> 51 51 <BuffHeal>0</BuffHeal> 52 52 <LoadingRange>2</LoadingRange> -
source/simulation2/components/CCmpFootprint.cpp
158 158 CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity()); 159 159 if (!cmpPathfinder) 160 160 return error; 161 161 162 162 CFixedVector2D initialPos = cmpPosition->GetPosition2D(); 163 163 entity_angle_t initialAngle = cmpPosition->GetRotation().Y; 164 164 … … 250 250 251 251 return error; 252 252 } 253 254 virtual CFixedVector3D PickSpawnPointBothPass(entity_id_t spawned) 255 { 256 // Try to find a free space inside and around this footprint 257 // at the intersection between the footprint passability and the unit passability. 258 // (useful for example for destroyed ships where the spawning point should be in the intersection 259 // of the unit and ship passabilities). 260 // As the overlap between these passabilities regions may be narrow, we need a small step (1 meter) 261 262 const CFixedVector3D error(fixed::FromInt(-1), fixed::FromInt(-1), fixed::FromInt(-1)); 263 264 CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); 265 if (!cmpPosition || !cmpPosition->IsInWorld()) 266 return error; 267 268 CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity()); 269 if (!cmpObstructionManager) 270 return error; 271 272 entity_pos_t spawnedRadius; 273 ICmpObstructionManager::tag_t spawnedTag; 274 275 CmpPtr<ICmpObstruction> cmpSpawnedObstruction(GetSimContext(), spawned); 276 if (cmpSpawnedObstruction) 277 { 278 spawnedRadius = cmpSpawnedObstruction->GetUnitRadius(); 279 spawnedTag = cmpSpawnedObstruction->GetObstruction(); 280 } 281 // else use zero radius 282 283 // Get passability class from UnitMotion 284 CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), spawned); 285 if (!cmpUnitMotion) 286 return error; 287 288 ICmpPathfinder::pass_class_t spawnedPass = cmpUnitMotion->GetPassabilityClass(); 289 CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity()); 290 if (!cmpPathfinder) 291 return error; 292 293 // Get the Footprint entity passability 294 CmpPtr<ICmpUnitMotion> cmpEntityMotion(GetEntityHandle()); 295 if (!cmpEntityMotion) 296 return error; 297 ICmpPathfinder::pass_class_t entityPass = cmpEntityMotion->GetPassabilityClass(); 298 299 CFixedVector2D initialPos = cmpPosition->GetPosition2D(); 300 entity_angle_t initialAngle = cmpPosition->GetRotation().Y; 301 302 // Max spawning distance + 1 (in meters) 303 const i32 maxSpawningDistance = 13; 304 305 if (m_Shape == CIRCLE) 306 { 307 // Expand outwards from foundation with a fixed step of 1 meter 308 for (i32 dist = 0; dist <= maxSpawningDistance; ++dist) 309 { 310 // The spawn point should be far enough from this footprint to fit the unit, plus a little gap 311 entity_pos_t clearance = spawnedRadius + entity_pos_t::FromInt(1+dist); 312 entity_pos_t radius = m_Size0 + clearance; 313 314 // Try equally-spaced points around the circle in alternating directions, starting from the front 315 const i32 numPoints = 31 + 2*dist; 316 for (i32 i = 0; i < (numPoints+1)/2; i = (i > 0 ? -i : 1-i)) // [0, +1, -1, +2, -2, ... (np-1)/2, -(np-1)/2] 317 { 318 entity_angle_t angle = initialAngle + (entity_angle_t::Pi()*2).Multiply(entity_angle_t::FromInt(i)/(int)numPoints); 319 320 fixed s, c; 321 sincos_approx(angle, s, c); 322 323 CFixedVector3D pos (initialPos.X + s.Multiply(radius), fixed::Zero(), initialPos.Y + c.Multiply(radius)); 324 325 SkipTagObstructionFilter filter(spawnedTag); // ignore collisions with the spawned entity 326 if (cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Z, spawnedRadius, spawnedPass) == ICmpObstruction::FOUNDATION_CHECK_SUCCESS && 327 cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Z, spawnedRadius, entityPass) == ICmpObstruction::FOUNDATION_CHECK_SUCCESS) 328 return pos; // this position is okay, so return it 329 } 330 } 331 } 332 else 333 { 334 fixed s, c; 335 sincos_approx(initialAngle, s, c); 336 337 // Expand outwards from foundation with a fixed step of 1 meter 338 for (i32 dist = 0; dist <= maxSpawningDistance; ++dist) 339 { 340 // The spawn point should be far enough from this footprint to fit the unit, plus a little gap 341 entity_pos_t clearance = spawnedRadius + entity_pos_t::FromInt(1+dist); 342 343 for (i32 edge = 0; edge < 4; ++edge) 344 { 345 // Compute the direction and length of the current edge 346 CFixedVector2D dir; 347 fixed sx, sy; 348 switch (edge) 349 { 350 case 0: 351 dir = CFixedVector2D(c, -s); 352 sx = m_Size0; 353 sy = m_Size1; 354 break; 355 case 1: 356 dir = CFixedVector2D(-s, -c); 357 sx = m_Size1; 358 sy = m_Size0; 359 break; 360 case 2: 361 dir = CFixedVector2D(s, c); 362 sx = m_Size1; 363 sy = m_Size0; 364 break; 365 case 3: 366 dir = CFixedVector2D(-c, s); 367 sx = m_Size0; 368 sy = m_Size1; 369 break; 370 } 371 sx = sx/2 + clearance; 372 sy = sy/2 + clearance; 373 // Try equally-spaced (1 meter) points along the edge in alternating directions, starting from the middle 374 i32 numPoints = 1 + 2*sx.ToInt_RoundToNearest(); 375 CFixedVector2D center = initialPos - dir.Perpendicular().Multiply(sy); 376 for (i32 i = 0; i < (numPoints+1)/2; i = (i > 0 ? -i : 1-i)) // [0, +1, -1, +2, -2, ... (np-1)/2, -(np-1)/2] 377 { 378 CFixedVector2D pos (center + dir*i); 379 380 SkipTagObstructionFilter filter(spawnedTag); // ignore collisions with the spawned entity 381 if (cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Y, spawnedRadius, spawnedPass) == ICmpObstruction::FOUNDATION_CHECK_SUCCESS && 382 cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Y, spawnedRadius, entityPass) == ICmpObstruction::FOUNDATION_CHECK_SUCCESS) 383 return CFixedVector3D(pos.X, fixed::Zero(), pos.Y); // this position is okay, so return it 384 } 385 } 386 } 387 } 388 389 return error; 390 } 253 391 }; 254 392 255 393 REGISTER_COMPONENT_TYPE(Footprint) -
source/simulation2/components/ICmpFootprint.cpp
62 62 63 63 BEGIN_INTERFACE_WRAPPER(Footprint) 64 64 DEFINE_INTERFACE_METHOD_1("PickSpawnPoint", CFixedVector3D, ICmpFootprint, PickSpawnPoint, entity_id_t) 65 DEFINE_INTERFACE_METHOD_1("PickSpawnPointBothPass", CFixedVector3D, ICmpFootprint, PickSpawnPointBothPass, entity_id_t) 65 66 DEFINE_INTERFACE_METHOD_0("GetShape", CScriptVal, ICmpFootprint, GetShape_wrapper) 66 67 END_INTERFACE_WRAPPER(Footprint) -
source/simulation2/components/ICmpFootprint.h
64 64 */ 65 65 virtual CFixedVector3D PickSpawnPoint(entity_id_t spawned) = 0; 66 66 67 /** 68 * Pick a sensible position to place a newly-spawned entity near this footprint, 69 * at the intersection between the footprint passability and the entity one. 70 * @return the X and Z coordinates of the spawn point, with Y = 0; or the special value (-1, -1, -1) if there's no space 71 */ 72 virtual CFixedVector3D PickSpawnPointBothPass(entity_id_t spawned) = 0; 73 67 74 DECLARE_INTERFACE_TYPE(Footprint) 68 75 }; 69 76