mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-08 22:26:51 +02:00
Merge pull request #5344 from IvanSavenko/hotfix
[1.6.4] Fixes for reported issues
This commit is contained in:
@ -371,7 +371,8 @@ BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, const Battl
|
||||
|
||||
if (siegeDefense)
|
||||
{
|
||||
vstd::erase_if(avHexes, [&](const BattleHex & hex) {
|
||||
avHexes.eraseIf([&](const BattleHex & hex)
|
||||
{
|
||||
return !cb->getBattle(battleID)->battleIsInsideWalls(hex);
|
||||
});
|
||||
}
|
||||
@ -383,7 +384,7 @@ BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, const Battl
|
||||
|
||||
BattleHexArray targetHexes = hexes;
|
||||
|
||||
std::sort(targetHexes.begin(), targetHexes.end(), [&](const BattleHex & h1, const BattleHex & h2) -> bool
|
||||
targetHexes.sort([&](const BattleHex & h1, const BattleHex & h2) -> bool
|
||||
{
|
||||
return reachability.distances[h1.toInt()] < reachability.distances[h2.toInt()];
|
||||
});
|
||||
|
@ -289,7 +289,7 @@ BattleAction CStupidAI::goTowards(const BattleID & battleID, const CStack * stac
|
||||
return BattleAction::makeDefend(stack);
|
||||
}
|
||||
|
||||
std::sort(hexes.begin(), hexes.end(), [&](const BattleHex & h1, const BattleHex & h2) -> bool
|
||||
hexes.sort([&](const BattleHex & h1, const BattleHex & h2) -> bool
|
||||
{
|
||||
return reachability.distances[h1.toInt()] < reachability.distances[h2.toInt()];
|
||||
});
|
||||
|
@ -379,7 +379,12 @@ static void detectOverlappingBuildings(RenderHandler * renderHandler, const Fact
|
||||
continue; // only a<->b comparison is needed, not a<->a or b<->a
|
||||
|
||||
if (left->building && right->building && left->building->getBase() == right->building->getBase())
|
||||
{
|
||||
if (left->pos.z != right->pos.z)
|
||||
logMod->warn("Town %s: Upgrades of same building have different z-index: '%s' and '%s'", faction->getJsonKey(), left->identifier, right->identifier);
|
||||
|
||||
continue; // upgrades of the same buildings are expected to overlap
|
||||
}
|
||||
|
||||
if (left->pos.z != right->pos.z)
|
||||
continue; // buildings already have different z-index and have well-defined overlap logic
|
||||
|
@ -92,7 +92,7 @@
|
||||
"villageHall": { "animation" : "TBDNHALL.def", "x" : 0, "y" : 234, "border" : "TODHALL1.bmp", "area" : "TZDHALL1.bmp" },
|
||||
"townHall": { "animation" : "TBDNHAL2.def", "x" : 0, "y" : 223, "border" : "TODHALL2.bmp", "area" : "TZDHALL2.bmp" },
|
||||
"cityHall": { "animation" : "TBDNHAL3.def", "x" : 0, "y" : 223, "border" : "TODHALL3.bmp", "area" : "TZDHALL3.bmp" },
|
||||
"capitol": { "animation" : "TBDNHAL4.def", "x" : 0, "y" : 203, "z" : -1, "border" : "TODHALL4.bmp", "area" : "TZDHALL4.bmp" },
|
||||
"capitol": { "animation" : "TBDNHAL4.def", "x" : 0, "y" : 203, "border" : "TODHALL4.bmp", "area" : "TZDHALL4.bmp" },
|
||||
"marketplace": { "animation" : "TBDNMARK.def", "x" : 590, "y" : 318, "z" : -2, "border" : "TODMARK.bmp", "area" : "TZDMARK.bmp" },
|
||||
"resourceSilo": { "animation" : "TBDNSILO.def", "x" : 624, "y" : 335, "z" : 1, "border" : "TODSILO.bmp", "area" : "TZDSILO.bmp" },
|
||||
"blacksmith": { "animation" : "TBDNBLAK.def", "x" : 544, "y" : 248, "z" : -3, "border" : "TODSMITH.bmp", "area" : "TZDSMITH.bmp" },
|
||||
|
@ -84,7 +84,7 @@
|
||||
"mageGuild2": { "animation" : "TBFRMAG2.def", "x" : 0, "y" : 177, "z" : -1, "border" : "TOFMAG2A.bmp", "area" : "TZFMAG2A.bmp" },
|
||||
"mageGuild3": { "animation" : "TBFRMAG3.def", "x" : 0, "y" : 135, "z" : -1, "border" : "TOFMAG3A.bmp", "area" : "TZFMAG3A.bmp" },
|
||||
"tavern": { "animation" : "TBFRTVRN.def", "x" : 634, "y" : 219, "z" : 3, "border" : "TOFTAVA.bmp", "area" : "TZFTAVA.bmp" },
|
||||
"shipyard": { "animation" : "TBFRDOCK.def", "x" : 197, "y" : 294, "border" : "TOFDCK2.bmp", "area" : "TZFDCK2.bmp" },
|
||||
"shipyard": { "animation" : "TBFRDOCK.def", "x" : 197, "y" : 294, "z" : 1, "border" : "TOFDCK2.bmp", "area" : "TZFDCK2.bmp" },
|
||||
"fort": { "animation" : "TBFRCSTL.def", "x" : 368, "y" : 118, "z" : -2, "border" : "TOFCAS1.bmp", "area" : "TZFCAS1.bmp" },
|
||||
"citadel": { "animation" : "TBFRCAS2.def", "x" : 368, "y" : 98, "z" : -2, "border" : "TOFCAS2.bmp", "area" : "TZFCAS2.bmp" },
|
||||
"castle": { "animation" : "TBFRCAS3.def", "x" : 368, "y" : 55, "z" : -2, "border" : "TOFCAS3.bmp", "area" : "TZFCAS3.bmp" },
|
||||
|
@ -97,8 +97,8 @@
|
||||
"resourceSilo": { "animation" : "TBRMSILO.def", "x" : 245, "y" : 324, "z" : 4, "border" : "TORMRK2.bmp", "area" : "TZRMRK2.bmp" },
|
||||
"blacksmith": { "animation" : "TBRMBLAK.def", "x" : 558, "y" : 105, "z" : -3, "border" : "TORAID.bmp", "area" : "TZRAID.bmp" },
|
||||
"special1": { "animation" : "TBRMSPEC.def", "x" : 555, "y" : 297, "z" : 2, "border" : "TORGAR1A.bmp", "area" : "TZRGAR1A.bmp" },
|
||||
"horde1": { "animation" : "TBRMHRD1.def", "x" : 0, "y" : 154, "border" : "TORDWF1H.bmp", "area" : "TZRDWF1H.bmp", "hidden" : true },
|
||||
"horde1Upgr": { "animation" : "TBRMHRD2.def", "x" : 0, "y" : 143, "border" : "TORDWF2H.bmp", "area" : "TZRDWF2H.bmp", "hidden" : true, "builds" : "horde1" },
|
||||
"horde1": { "animation" : "TBRMHRD1.def", "x" : 0, "y" : 154, "z" : -2, "border" : "TORDWF1H.bmp", "area" : "TZRDWF1H.bmp", "hidden" : true },
|
||||
"horde1Upgr": { "animation" : "TBRMHRD2.def", "x" : 0, "y" : 143, "z" : -2, "border" : "TORDWF2H.bmp", "area" : "TZRDWF2H.bmp", "hidden" : true, "builds" : "horde1" },
|
||||
"special2": { "animation" : "TBRMEXT0.def", "x" : 555, "y" : 297, "z" : 2, "border" : "TORGAR2A.bmp", "area" : "TZRGAR2A.bmp" },
|
||||
"special3": { "animation" : "TBRMEXT1.def", "x" : 0, "y" : 181, "z" : 1, "border" : "TORDWFT.bmp", "area" : "TZRDWFT.bmp" },
|
||||
"horde2": { "animation" : "TBRMHRD3.def", "x" : 47, "y" : 142, "z" : -1, "border" : "TORTRE1H.bmp", "area" : "TZRTRE1H.bmp", "hidden" : true },
|
||||
@ -108,14 +108,14 @@
|
||||
"extraCityHall": { "animation" : "TBRMEXT4.def", "x" : 295, "y" : 191, "z" : 0 },
|
||||
"extraCapitol": { "animation" : "TBRMEXT5.def", "x" : 260, "y" : 171, "z" : 3 },
|
||||
"dwellingLvl1": { "animation" : "TBRMDW_0.def", "x" : 0, "y" : 236, "z" : 2, "border" : "TORCEN1A.bmp", "area" : "TZRCEN1A.bmp" },
|
||||
"dwellingLvl2": { "animation" : "TBRMDW_1.def", "x" : 0, "y" : 154, "border" : "TORDWF1.bmp", "area" : "TZRDWF1.bmp" },
|
||||
"dwellingLvl2": { "animation" : "TBRMDW_1.def", "x" : 0, "y" : 154, "z" : -2, "border" : "TORDWF1.bmp", "area" : "TZRDWF1.bmp" },
|
||||
"dwellingLvl3": { "animation" : "TBRMDW_2.def", "x" : 668, "y" : 101, "z" : -1, "border" : "TORELF1.bmp", "area" : "TZRELF1.bmp" },
|
||||
"dwellingLvl4": { "animation" : "TBRMDW_3.def", "x" : 287, "y" : 73, "z" : -1, "border" : "TORPEG1A.bmp", "area" : "TZRPEG1A.bmp" },
|
||||
"dwellingLvl5": { "animation" : "TBRMDW_4.def", "x" : 68, "y" : 146, "z" : -1, "border" : "TORTRE1.bmp", "area" : "TZRTRE1.bmp" },
|
||||
"dwellingLvl6": { "animation" : "TBRMDW_5.def", "x" : 362, "y" : 90, "z" : -2, "border" : "TORUNI1.bmp", "area" : "TZRUNI1.bmp" },
|
||||
"dwellingLvl7": { "animation" : "TBRMDW_6.def", "x" : 502, "y" : 27, "z" : -5, "border" : "TORDR1AA.bmp", "area" : "TZRDR1AA.bmp" },
|
||||
"dwellingUpLvl1": { "animation" : "TBRMUP_0.def", "x" : 0, "y" : 236, "z" : 2, "border" : "TORCEN2A.bmp", "area" : "TZRCEN2A.bmp" },
|
||||
"dwellingUpLvl2": { "animation" : "TBRMUP_1.def", "x" : 0, "y" : 143, "border" : "TORDWF2.bmp", "area" : "TZRDWF2.bmp" },
|
||||
"dwellingUpLvl2": { "animation" : "TBRMUP_1.def", "x" : 0, "y" : 143, "z" : -2, "border" : "TORDWF2.bmp", "area" : "TZRDWF2.bmp" },
|
||||
"dwellingUpLvl3": { "animation" : "TBRMUP_2.def", "x" : 665, "y" : 101, "z" : -1, "border" : "TORELF2.bmp", "area" : "TZRELF2.bmp" },
|
||||
"dwellingUpLvl4": { "animation" : "TBRMUP_3.def", "x" : 287, "y" : 28, "z" : -1, "border" : "TORPEG2A.bmp", "area" : "TZRPEG2A.bmp" },
|
||||
"dwellingUpLvl5": { "animation" : "TBRMUP_4.def", "x" : 63, "y" : 146, "z" : -1, "border" : "TORTRE2.bmp", "area" : "TZRTRE2.bmp" },
|
||||
|
@ -30,16 +30,6 @@ void BattleHexArray::insert(const BattleHexArray & other) noexcept
|
||||
}
|
||||
}
|
||||
|
||||
void BattleHexArray::erase(iterator first, iterator last) noexcept
|
||||
{
|
||||
for(auto it = first; it != last && it != internalStorage.end(); ++it)
|
||||
{
|
||||
presenceFlags[it->toInt()] = false;
|
||||
}
|
||||
|
||||
internalStorage.erase(first, last);
|
||||
}
|
||||
|
||||
void BattleHexArray::clear() noexcept
|
||||
{
|
||||
for(const auto & hex : internalStorage)
|
||||
@ -129,4 +119,4 @@ const std::map<BattleSide, BattleHexArray::ArrayOfBattleHexArrays> BattleHexArra
|
||||
{ BattleSide::DEFENDER, precalculateNeighbouringTilesDoubleWide(BattleSide::DEFENDER) }
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "BattleHex.h"
|
||||
#include <boost/container/small_vector.hpp>
|
||||
#include <vstd/RNG.h>
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@ -41,9 +42,7 @@ public:
|
||||
using pointer = value_type *;
|
||||
using const_pointer = const value_type *;
|
||||
using difference_type = typename StorageType::difference_type;
|
||||
using iterator = typename StorageType::iterator;
|
||||
using const_iterator = typename StorageType::const_iterator;
|
||||
using reverse_iterator = typename StorageType::reverse_iterator;
|
||||
using const_reverse_iterator = typename StorageType::const_reverse_iterator;
|
||||
|
||||
BattleHexArray() = default;
|
||||
@ -71,7 +70,7 @@ public:
|
||||
{
|
||||
if(tile.isAvailable() && !contains(tile))
|
||||
{
|
||||
presenceFlags[tile.toInt()] = true;
|
||||
presenceFlags.set(tile.toInt());
|
||||
internalStorage.emplace_back(tile);
|
||||
}
|
||||
}
|
||||
@ -81,7 +80,7 @@ public:
|
||||
if(contains(hex))
|
||||
return;
|
||||
|
||||
presenceFlags[hex.toInt()] = true;
|
||||
presenceFlags.set(hex.toInt());
|
||||
internalStorage.emplace_back(hex);
|
||||
}
|
||||
|
||||
@ -98,19 +97,10 @@ public:
|
||||
if(contains(hex))
|
||||
return;
|
||||
|
||||
presenceFlags[hex.toInt()] = true;
|
||||
presenceFlags.set(hex.toInt());
|
||||
internalStorage[index] = hex;
|
||||
}
|
||||
|
||||
iterator insert(iterator pos, const BattleHex & hex) noexcept
|
||||
{
|
||||
if(contains(hex))
|
||||
return pos;
|
||||
|
||||
presenceFlags[hex.toInt()] = true;
|
||||
return internalStorage.insert(pos, hex);
|
||||
}
|
||||
|
||||
void insert(const BattleHexArray & other) noexcept;
|
||||
|
||||
template <typename Container, typename = std::enable_if_t<
|
||||
@ -123,17 +113,44 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Predicate>
|
||||
void sort(Predicate pred)
|
||||
{
|
||||
std::sort(internalStorage.begin(), internalStorage.end(), pred);
|
||||
}
|
||||
|
||||
template<typename Predicate>
|
||||
void eraseIf(Predicate pred)
|
||||
{
|
||||
vstd::erase_if(internalStorage, pred);
|
||||
// reinit presence flags
|
||||
presenceFlags = {};
|
||||
for(const auto & hex : internalStorage)
|
||||
presenceFlags.set(hex.toInt()) = true;
|
||||
}
|
||||
|
||||
void shuffle(vstd::RNG & rand)
|
||||
{
|
||||
int64_t n = internalStorage.size();
|
||||
|
||||
for(int64_t i = n - 1; i > 0; --i)
|
||||
{
|
||||
auto randIndex = rand.nextInt64(0, i);
|
||||
std::swap(internalStorage[i], internalStorage[randIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
void clear() noexcept;
|
||||
inline void erase(const BattleHex & target) noexcept
|
||||
{
|
||||
assert(contains(target));
|
||||
vstd::erase(internalStorage, target);
|
||||
presenceFlags[target.toInt()] = false;
|
||||
presenceFlags.reset(target.toInt());
|
||||
}
|
||||
void erase(iterator first, iterator last) noexcept;
|
||||
|
||||
inline void pop_back() noexcept
|
||||
{
|
||||
presenceFlags[internalStorage.back().toInt()] = false;
|
||||
presenceFlags.reset(internalStorage.back().toInt());
|
||||
internalStorage.pop_back();
|
||||
}
|
||||
|
||||
@ -156,12 +173,6 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Predicate>
|
||||
iterator findIf(Predicate predicate) noexcept
|
||||
{
|
||||
return std::find_if(begin(), end(), predicate);
|
||||
}
|
||||
|
||||
template <typename Predicate>
|
||||
const_iterator findIf(Predicate predicate) const noexcept
|
||||
{
|
||||
@ -216,7 +227,7 @@ public:
|
||||
[[nodiscard]] inline bool contains(const BattleHex & hex) const noexcept
|
||||
{
|
||||
if(hex.isValid())
|
||||
return presenceFlags[hex.toInt()];
|
||||
return presenceFlags.test(hex.toInt());
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -228,7 +239,7 @@ public:
|
||||
if(!s.saving)
|
||||
{
|
||||
for(const auto & hex : internalStorage)
|
||||
presenceFlags[hex.toInt()] = true;
|
||||
presenceFlags.set(hex.toInt()) = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,11 +268,6 @@ public:
|
||||
return internalStorage.size();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline iterator begin() noexcept
|
||||
{
|
||||
return internalStorage.begin();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline const_iterator begin() const noexcept
|
||||
{
|
||||
return internalStorage.begin();
|
||||
@ -272,31 +278,16 @@ public:
|
||||
return internalStorage.empty();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline iterator end() noexcept
|
||||
{
|
||||
return internalStorage.end();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline const_iterator end() const noexcept
|
||||
{
|
||||
return internalStorage.end();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline reverse_iterator rbegin() noexcept
|
||||
{
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
[[nodiscard]] inline const_reverse_iterator rbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
[[nodiscard]] inline reverse_iterator rend() noexcept
|
||||
{
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
[[nodiscard]] inline const_reverse_iterator rend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
|
@ -49,11 +49,6 @@ static bool sameSideOfWall(const BattleHex & pos1, const BattleHex & pos2)
|
||||
return stackLeft == destLeft;
|
||||
}
|
||||
|
||||
static bool isInsideWalls(const BattleHex & pos)
|
||||
{
|
||||
return lineToWallHex(pos.getY()) <= pos;
|
||||
}
|
||||
|
||||
// parts of wall
|
||||
static const std::pair<int, EWallPart> wallParts[] =
|
||||
{
|
||||
@ -167,7 +162,20 @@ std::pair< BattleHexArray, int > CBattleInfoCallback::getPath(const BattleHex &
|
||||
|
||||
bool CBattleInfoCallback::battleIsInsideWalls(const BattleHex & from) const
|
||||
{
|
||||
return isInsideWalls(from);
|
||||
BattleHex wallPos = lineToWallHex(from.getY());
|
||||
|
||||
if (from < wallPos)
|
||||
return false;
|
||||
|
||||
if (wallPos < from)
|
||||
return true;
|
||||
|
||||
// edge case - this is the wall. (or drawbridge)
|
||||
// since this method is used exclusively to determine behavior of defenders,
|
||||
// consider it inside walls, unless this is intact drawbridge - to prevent defenders standing on it and opening the gates
|
||||
if (from == BattleHex::GATE_INNER)
|
||||
return battleGetGateState() == EGateState::DESTROYED;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBattleInfoCallback::battleHasPenaltyOnLine(const BattleHex & from, const BattleHex & dest, bool checkWall, bool checkMoat) const
|
||||
|
@ -79,7 +79,7 @@ uint32_t ReachabilityInfo::distToNearestNeighbour(
|
||||
}
|
||||
}
|
||||
|
||||
vstd::erase_if(attackableHexes, [defender](const BattleHex & h) -> bool
|
||||
attackableHexes.eraseIf([defender](const BattleHex & h) -> bool
|
||||
{
|
||||
return h.getY() != defender->getPosition().getY() || !h.isAvailable();
|
||||
});
|
||||
|
@ -194,7 +194,7 @@ void Obstacle::apply(ServerCallback * server, const Mechanics * m, const EffectT
|
||||
for(const auto & destination : target)
|
||||
insertAvailable(destination.hexValue, availableTiles);
|
||||
|
||||
RandomGeneratorUtil::randomShuffle(availableTiles, *server->getRNG());
|
||||
availableTiles.shuffle(*server->getRNG());
|
||||
const int patchesToPut = std::min(patchCount, static_cast<int>(availableTiles.size()));
|
||||
EffectTarget randomTarget;
|
||||
randomTarget.reserve(patchesToPut);
|
||||
|
Reference in New Issue
Block a user