To follow other maps name syntax (`<name> (<number of players>)`), "players" is
removed from the name on the Watering Holes map to keep only the number.
sortEntitiesForEngagement projects both attackers and targets from
the same origin (avgAttackers) onto the same vector,
so reversing the target array was incorrect.
We need to track models to update in a single place. SceneRenderer in
that case. It allows us to make ModelVertexRenderer implementations more
straightforward.
The last node needs to have distance "0" to next node. Do the inverse of
when adding nodes.
Also add some basic tests covering this bug.
Fixes: #4659
Signed-off-by: Ralph Sennhauser <ralph.sennhauser@gmail.com>
cmpPosition was declared but never read anywhere in the function,
likely left over from an earlier refactor — each unit's own position
is already fetched correctly inside the loop via unitPos. CmpPtr
construction is a pure lookup with no side effects, so removing the
unused instance doesn't change behaviour.
In `CCmpPathfinder::CheckBuildingPlacement`, the boundary check for the
vertical grid dimension (`j > m_TerrainOnlyGrid->m_H`) allowed `j` to equal
`m_TerrainOnlyGrid->m_H`. Since grid indices are 0-based (valid row indices
range from `0` to `m_H - 1`), this boundary condition allowed the loop to
execute with an out-of-bounds row index, leading to an invalid memory
read (`m_TerrainOnlyGrid->get(i, j)`) and potential segfaults.
This patch changes the comparison operator to `j >= m_TerrainOnlyGrid->m_H`,
ensuring that spans extending to or past the grid height bound are properly
flagged as out-of-bounds.
Follows db23584fc3 - the caller of GetEffectiveAttackRange's didn't
really use the NEVER_IN_RANGE result properly.
The C++ engine does not handle Infinity (treated as 0).
This also changes MoveToTargetAttackRange to explicitly try to get
closer if the parabolic range is not in range, but it seems like a flat
range could - on the assumption that once we get closer, the terrain
height difference is lower.
range.GetInternalValue() is an i32; multiplying it by 2 before the cast
to i64 could overflow instead of widening, corrupting the divisor. Cast
to i64 first.
Since 38b33b0484, the range check happened in CanAttack, however the
check there is too permissive.
This meant it was possible for towers to attack certain targets outside
their actual range, depending on the query results and unit AI focus
fire.
Following 38b33b0484, units on aggressive stance no longer chase beyond
their own vision, including on player-forced orders. This fixes that
regression.
(Note that approaching and chasing are a bit inconsistent).
38b33b0484 partly rewrote GetQueryRange but ended up with two
bugs/regressions:
- in standGround, melee units used an effective max-range of 0 instead
of their melee attack max range
- units that have a min-range did not see units within their min-range
(even though they can move).
This fixes these issues and rewrite the function in a simpler fashion
for readability.
38b33b0484 added a visibility filter to TestEntityQuery, active whenever
a query sets preferMirages - which UnitAI's attack range query does.
However, those filters do not work for Gaia, and so the query never
returned anything.
It was only a wrapper around `std::string::substr`. The interface
matches the usecase more. In some places it's better to use
`std::string::ends_with`.