Delete sheep corpses when starting to build a foundation,

so that units don't try to gather forever while not being able to reach
it and
so that the sheep corpse can't be selected and seen anymore.

Differential Revision: https://code.wildfiregames.com/D21
Fixes #4268
Based On Patch By: wraitii
Reviewed By: temple
Previously Reviewed By: Itms
This was SVN commit r21597.
This commit is contained in:
elexis 2018-03-21 01:44:15 +00:00
parent adfd2cfae1
commit 29492badb7
8 changed files with 78 additions and 12 deletions

View file

@ -196,7 +196,9 @@ Foundation.prototype.Build = function(builderEnt, work)
var cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction);
if (cmpObstruction && cmpObstruction.GetBlockMovementFlag())
{
var collisions = cmpObstruction.GetUnitCollisions();
// Remove all obstructions at the new entity, especially animal corpses
let collisions = cmpObstruction.GetEntityCollisions();
if (collisions.length)
{
var cmpFoundationOwnership = Engine.QueryInterface(this.entity, IID_Ownership);

View file

@ -62,7 +62,7 @@ function testFoundation(...mocks)
AddMock(foundationEnt, IID_Obstruction, {
"GetBlockMovementFlag": () => true,
"GetUnitCollisions": () => [],
"GetEntityCollisions": () => [],
"SetDisableBlockMovementPathfinding": () => {},
});

View file

@ -190,8 +190,7 @@ function ObstructionsBlockingTemplateChange(ent, templateArg)
var cmpNewObstruction = Engine.QueryInterface(previewEntity, IID_Obstruction);
if (cmpNewObstruction && cmpNewObstruction.GetBlockMovementFlag())
{
// Check for units
var collisions = cmpNewObstruction.GetUnitCollisions();
let collisions = cmpNewObstruction.GetEntityCollisions();
if (collisions.length)
return DeleteEntityAndReturn(previewEntity, cmpPosition, pos, angle, cmpNewPosition, true);
}

View file

@ -624,7 +624,7 @@ public:
return ret; // error
// There are four 'block' flags: construction, foundation, movement,
// and pathfinding. Structures have all of these flags, while units
// and pathfinding. Structures have all of these flags, while most units
// block only movement and construction.
flags_t flags = ICmpObstructionManager::FLAG_BLOCK_CONSTRUCTION;
@ -642,6 +642,27 @@ public:
return ret;
}
virtual std::vector<entity_id_t> GetEntityCollisions() const
{
std::vector<entity_id_t> ret;
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (!cmpObstructionManager)
return ret; // error
// Ignore collisions within the same control group.
SkipControlGroupsRequireFlagObstructionFilter filter(true, m_ControlGroup, m_ControlGroup2, 0);
ICmpObstructionManager::ObstructionSquare square;
if (!GetObstructionSquare(square))
return ret; // error
cmpObstructionManager->GetUnitsOnObstruction(square, ret, filter, false);
cmpObstructionManager->GetStaticObstructionsOnObstruction(square, ret, filter);
return ret;
}
virtual void SetMovingFlag(bool enabled)
{
m_Moving = enabled;

View file

@ -476,6 +476,7 @@ public:
virtual void GetUnitObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector<ObstructionSquare>& squares) const;
virtual void GetStaticObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector<ObstructionSquare>& squares) const;
virtual void GetUnitsOnObstruction(const ObstructionSquare& square, std::vector<entity_id_t>& out, const IObstructionTestFilter& filter, bool strict = false) const;
virtual void GetStaticObstructionsOnObstruction(const ObstructionSquare& square, std::vector<entity_id_t>& out, const IObstructionTestFilter& filter) const;
virtual void SetPassabilityCircular(bool enabled)
{
@ -890,7 +891,7 @@ void CCmpObstructionManager::Rasterize(Grid<NavcellData>& grid, const std::vecto
{
case PathfinderPassability::PATHFINDING:
{
auto it = pathfindingMasks.find(passability.m_Clearance);
std::map<entity_pos_t, u16>::iterator it = pathfindingMasks.find(passability.m_Clearance);
if (it == pathfindingMasks.end())
pathfindingMasks[passability.m_Clearance] = passability.m_Mask;
else
@ -979,7 +980,7 @@ void CCmpObstructionManager::GetUnitObstructionsInRange(const IObstructionTestFi
m_UnitSubdivision.GetInRange(unitShapes, CFixedVector2D(x0, z0), CFixedVector2D(x1, z1));
for (entity_id_t& unitShape : unitShapes)
{
auto it = m_UnitShapes.find(unitShape);
std::map<u32, UnitShape>::const_iterator it = m_UnitShapes.find(unitShape);
ENSURE(it != m_UnitShapes.end());
if (!filter.TestShape(UNIT_INDEX_TO_TAG(it->first), it->second.flags, it->second.group, INVALID_ENTITY))
@ -1007,7 +1008,7 @@ void CCmpObstructionManager::GetStaticObstructionsInRange(const IObstructionTest
m_StaticSubdivision.GetInRange(staticShapes, CFixedVector2D(x0, z0), CFixedVector2D(x1, z1));
for (entity_id_t& staticShape : staticShapes)
{
auto it = m_StaticShapes.find(staticShape);
std::map<u32, StaticShape>::const_iterator it = m_StaticShapes.find(staticShape);
ENSURE(it != m_StaticShapes.end());
if (!filter.TestShape(STATIC_INDEX_TO_TAG(it->first), it->second.flags, it->second.group, it->second.group2))
@ -1030,7 +1031,7 @@ void CCmpObstructionManager::GetUnitsOnObstruction(const ObstructionSquare& squa
PROFILE("GetUnitsOnObstruction");
// In order to avoid getting units on impassable cells, we want to find all
// units s.t. the RasterizeRectWithClearance of the building's shape with the
// units subject to the RasterizeRectWithClearance of the building's shape with the
// unit's clearance covers the navcell the unit is on.
std::vector<entity_id_t> unitShapes;
@ -1044,7 +1045,7 @@ void CCmpObstructionManager::GetUnitsOnObstruction(const ObstructionSquare& squa
for (const u32& unitShape : unitShapes)
{
auto it = m_UnitShapes.find(unitShape);
std::map<u32, UnitShape>::const_iterator it = m_UnitShapes.find(unitShape);
ENSURE(it != m_UnitShapes.end());
const UnitShape& shape = it->second;
@ -1086,6 +1087,40 @@ void CCmpObstructionManager::GetUnitsOnObstruction(const ObstructionSquare& squa
}
}
void CCmpObstructionManager::GetStaticObstructionsOnObstruction(const ObstructionSquare& square, std::vector<entity_id_t>& out, const IObstructionTestFilter& filter) const
{
PROFILE("GetStaticObstructionsOnObstruction");
std::vector<entity_id_t> staticShapes;
CFixedVector2D center(square.x, square.z);
CFixedVector2D expandedBox = Geometry::GetHalfBoundingBox(square.u, square.v, CFixedVector2D(square.hw, square.hh));
m_StaticSubdivision.GetInRange(staticShapes, center - expandedBox, center + expandedBox);
for (const u32& staticShape : staticShapes)
{
std::map<u32, StaticShape>::const_iterator it = m_StaticShapes.find(staticShape);
ENSURE(it != m_StaticShapes.end());
const StaticShape& shape = it->second;
if (!filter.TestShape(STATIC_INDEX_TO_TAG(staticShape), shape.flags, shape.group, shape.group2))
continue;
if (Geometry::TestSquareSquare(
center,
square.u,
square.v,
CFixedVector2D(square.hw, square.hh),
CFixedVector2D(shape.x, shape.z),
shape.u,
shape.v,
CFixedVector2D(shape.hw, shape.hh)))
{
out.push_back(shape.entity);
}
}
}
void CCmpObstructionManager::RenderSubmit(SceneCollector& collector)
{
if (!m_DebugOverlayEnabled)

View file

@ -51,6 +51,7 @@ DEFINE_INTERFACE_METHOD_CONST_0("CheckShorePlacement", bool, ICmpObstruction, Ch
DEFINE_INTERFACE_METHOD_CONST_2("CheckFoundation", std::string, ICmpObstruction, CheckFoundation_wrapper, std::string, bool)
DEFINE_INTERFACE_METHOD_CONST_0("CheckDuplicateFoundation", bool, ICmpObstruction, CheckDuplicateFoundation)
DEFINE_INTERFACE_METHOD_CONST_0("GetUnitCollisions", std::vector<entity_id_t>, ICmpObstruction, GetUnitCollisions)
DEFINE_INTERFACE_METHOD_CONST_0("GetEntityCollisions", std::vector<entity_id_t>, ICmpObstruction, GetEntityCollisions)
DEFINE_INTERFACE_METHOD_1("SetActive", void, ICmpObstruction, SetActive, bool)
DEFINE_INTERFACE_METHOD_3("SetDisableBlockMovementPathfinding", void, ICmpObstruction, SetDisableBlockMovementPathfinding, bool, bool, int32_t)
DEFINE_INTERFACE_METHOD_CONST_0("GetBlockMovementFlag", bool, ICmpObstruction, GetBlockMovementFlag)

View file

@ -89,11 +89,18 @@ public:
virtual bool CheckDuplicateFoundation() const = 0;
/**
* Returns a list of units that are colliding with this entity,
* Returns a list of units that are colliding with this entity.
* @return vector of blocking units
*/
virtual std::vector<entity_id_t> GetUnitCollisions() const = 0;
/**
* Returns a list of entities that are colliding with this entity (excluding self).
* This can be used to retrieve units with static obstructions, such as animal corpses.
* @return vector of blocking units
*/
virtual std::vector<entity_id_t> GetEntityCollisions() const = 0;
/**
* Detects collisions between foundation-blocking entities and
* tries to fix them by setting control groups, if appropriate.

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2017 Wildfire Games.
/* Copyright (C) 2018 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -245,6 +245,7 @@ public:
virtual void GetObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector<ObstructionSquare>& squares) const = 0;
virtual void GetStaticObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector<ObstructionSquare>& squares) const = 0;
virtual void GetUnitObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector<ObstructionSquare>& squares) const = 0;
virtual void GetStaticObstructionsOnObstruction(const ObstructionSquare& square, std::vector<entity_id_t>& out, const IObstructionTestFilter& filter) const = 0;
/**
* Returns the entity IDs of all unit shapes that intersect the given