1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-12-07 23:33:15 +02:00

Merge branch 'develop' into feature/nullkiller2

This commit is contained in:
Mircea TheHonestCTO
2025-11-15 17:15:46 +01:00
151 changed files with 17411 additions and 9818 deletions

View File

@@ -20,7 +20,8 @@
VCMI_LIB_NAMESPACE_BEGIN
const std::vector<CDrawLinesOperation::LinePattern> CDrawLinesOperation::patterns =
template <typename T>
const std::vector<typename CDrawLinesOperation<T>::LinePattern> CDrawLinesOperation<T>::patterns =
{
//single tile. fall-back pattern
{
@@ -156,34 +157,47 @@ static bool ruleIsAny(const std::string & rule)
#endif
///CDrawLinesOperation
CDrawLinesOperation::CDrawLinesOperation(CMap * map, CTerrainSelection terrainSel, vstd::RNG * gen):
template <typename T>
CDrawLinesOperation<T>::CDrawLinesOperation(CMap * map, CTerrainSelection terrainSel, T lineType, vstd::RNG * gen):
CMapOperation(map),
terrainSel(std::move(terrainSel)),
lineType(lineType),
gen(gen)
{
}
///CDrawRoadsOperation
CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, RoadId roadType, vstd::RNG * gen):
CDrawLinesOperation(map, terrainSel,gen),
roadType(roadType)
{
}
CDrawLinesOperation(map, terrainSel,roadType, gen)
{}
///CDrawRiversOperation
CDrawRiversOperation::CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, RiverId riverType, vstd::RNG * gen):
CDrawLinesOperation(map, terrainSel, gen),
riverType(riverType)
CDrawLinesOperation(map, terrainSel, riverType, gen)
{}
template <typename T>
void CDrawLinesOperation<T>::execute()
{
for(const auto & pos : terrainSel.getSelectedItems())
{
auto identifier = getIdentifier(map->getTile(pos));
if (formerState.find(identifier) == formerState.end())
formerState.insert({identifier, CTerrainSelection(terrainSel.getMap())});
formerState.at(identifier).select(pos);
}
drawLines(terrainSel, lineType);
}
void CDrawLinesOperation::execute()
template <typename T>
void CDrawLinesOperation<T>::drawLines(CTerrainSelection selection, T type)
{
std::set<int3> invalidated;
for(const auto & pos : terrainSel.getSelectedItems())
for(const auto & pos : selection.getSelectedItems())
{
executeTile(map->getTile(pos));
executeTile(map->getTile(pos), type);
auto rect = extendTileAroundSafely(pos);
rect.forEach([&invalidated](const int3 & pos)
@@ -195,17 +209,23 @@ void CDrawLinesOperation::execute()
updateTiles(invalidated);
}
void CDrawLinesOperation::undo()
template <typename T>
void CDrawLinesOperation<T>::undo()
{
//TODO
for (auto const& typeToSelection : formerState)
{
drawLines(typeToSelection.second, typeToSelection.first);
}
}
void CDrawLinesOperation::redo()
template <typename T>
void CDrawLinesOperation<T>::redo()
{
//TODO
drawLines(terrainSel, lineType);
}
void CDrawLinesOperation::flipPattern(LinePattern& pattern, int flip) const
template <typename T>
void CDrawLinesOperation<T>::flipPattern(LinePattern& pattern, int flip) const
{
//todo: use cashing here and also in terrain patterns
@@ -233,7 +253,8 @@ void CDrawLinesOperation::flipPattern(LinePattern& pattern, int flip) const
}
}
void CDrawLinesOperation::updateTiles(std::set<int3> & invalidated)
template <typename T>
void CDrawLinesOperation<T>::updateTiles(std::set<int3> & invalidated)
{
for(const int3 & coord : invalidated)
{
@@ -264,7 +285,8 @@ void CDrawLinesOperation::updateTiles(std::set<int3> & invalidated)
}
}
CDrawLinesOperation::ValidationResult CDrawLinesOperation::validateTile(const LinePattern & pattern, const int3 & pos)
template <typename T>
typename CDrawLinesOperation<T>::ValidationResult CDrawLinesOperation<T>::validateTile(const LinePattern & pattern, const int3 & pos)
{
ValidationResult result(false);
@@ -342,14 +364,14 @@ std::string CDrawRiversOperation::getLabel() const
return "Draw Rivers";
}
void CDrawRoadsOperation::executeTile(TerrainTile & tile)
void CDrawRoadsOperation::executeTile(TerrainTile & tile, RoadId type)
{
tile.roadType = roadType;
tile.roadType = type;
}
void CDrawRiversOperation::executeTile(TerrainTile & tile)
void CDrawRiversOperation::executeTile(TerrainTile & tile, RiverId type)
{
tile.riverType = riverType;
tile.riverType = type;
}
bool CDrawRoadsOperation::canApplyPattern(const LinePattern & pattern) const
@@ -398,4 +420,14 @@ void CDrawRiversOperation::updateTile(TerrainTile & tile, const LinePattern & pa
tile.extTileFlags = (tile.extTileFlags & 0b00111111) | (flip << 2);
}
RiverId CDrawRiversOperation::getIdentifier(TerrainTile & tile) const
{
return tile.riverType;
}
RoadId CDrawRoadsOperation::getIdentifier(TerrainTile & tile) const
{
return tile.roadType;
}
VCMI_LIB_NAMESPACE_END

View File

@@ -16,7 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN
struct TerrainTile;
class CDrawLinesOperation : public CMapOperation
template <typename T> class CDrawLinesOperation : public CMapOperation
{
public:
void execute() override;
@@ -41,14 +41,15 @@ protected:
int flip;
};
CDrawLinesOperation(CMap * map, CTerrainSelection terrainSel, vstd::RNG * gen);
CDrawLinesOperation(CMap * map, CTerrainSelection terrainSel, T lineType, vstd::RNG * gen);
virtual void executeTile(TerrainTile & tile) = 0;
virtual bool canApplyPattern(const CDrawLinesOperation::LinePattern & pattern) const = 0;
virtual void executeTile(TerrainTile & tile, T type) = 0;
virtual bool canApplyPattern(const LinePattern & pattern) const = 0;
virtual bool needUpdateTile(const TerrainTile & tile) const = 0;
virtual bool tileHasSomething(const int3 & pos) const = 0;
virtual void updateTile(TerrainTile & tile, const CDrawLinesOperation::LinePattern & pattern, const int flip) = 0;
virtual void updateTile(TerrainTile & tile, const LinePattern & pattern, const int flip) = 0;
virtual T getIdentifier(TerrainTile & tile) const = 0;
static const std::vector<LinePattern> patterns;
void flipPattern(LinePattern & pattern, int flip) const;
@@ -58,38 +59,45 @@ protected:
ValidationResult validateTile(const LinePattern & pattern, const int3 & pos);
CTerrainSelection terrainSel;
T lineType;
vstd::RNG * gen;
std::map<T, CTerrainSelection> formerState;
private:
void drawLines(CTerrainSelection selection, T type);
};
class CDrawRoadsOperation : public CDrawLinesOperation
class CDrawRoadsOperation : public CDrawLinesOperation<RoadId>
{
public:
CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, RoadId roadType, vstd::RNG * gen);
std::string getLabel() const override;
protected:
void executeTile(TerrainTile & tile) override;
bool canApplyPattern(const CDrawLinesOperation::LinePattern & pattern) const override;
void executeTile(TerrainTile & tile, RoadId type) override;
bool canApplyPattern(const LinePattern & pattern) const override;
bool needUpdateTile(const TerrainTile & tile) const override;
bool tileHasSomething(const int3 & pos) const override;
void updateTile(TerrainTile & tile, const CDrawLinesOperation::LinePattern & pattern, const int flip) override;
void updateTile(TerrainTile & tile, const LinePattern & pattern, const int flip) override;
RoadId getIdentifier(TerrainTile & tile) const override;
private:
RoadId roadType;
};
class CDrawRiversOperation : public CDrawLinesOperation
class CDrawRiversOperation : public CDrawLinesOperation<RiverId>
{
public:
CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, RiverId roadType, vstd::RNG * gen);
std::string getLabel() const override;
protected:
void executeTile(TerrainTile & tile) override;
bool canApplyPattern(const CDrawLinesOperation::LinePattern & pattern) const override;
void executeTile(TerrainTile & tile, RiverId type) override;
bool canApplyPattern(const LinePattern & pattern) const override;
bool needUpdateTile(const TerrainTile & tile) const override;
bool tileHasSomething(const int3 & pos) const override;
void updateTile(TerrainTile & tile, const CDrawLinesOperation::LinePattern & pattern, const int flip) override;
void updateTile(TerrainTile & tile, const LinePattern & pattern, const int flip) override;
RiverId getIdentifier(TerrainTile & tile) const override;
private:
RiverId riverType;

View File

@@ -129,6 +129,7 @@ CMapHeader::CMapHeader()
, defeatIconIndex(0)
, howManyTeams(0)
, areAnyPlayers(false)
, battleOnly(false)
{
setupEvents();
allowedHeroes = LIBRARY->heroh->getDefaultAllowed();

View File

@@ -272,6 +272,8 @@ public:
bool areAnyPlayers; /// Unused. True if there are any playable players on the map.
bool battleOnly; /// Battle only mode
/// "main quests" of the map that describe victory and loss conditions
std::vector<TriggeredEvent> triggeredEvents;
@@ -316,6 +318,8 @@ public:
h & levelLimit;
h & areAnyPlayers;
if (h.version >= Handler::Version::BATTLE_ONLY)
h & battleOnly;
h & players;
h & howManyTeams;
h & allowedHeroes;

View File

@@ -103,22 +103,38 @@ void CDrawTerrainOperation::execute()
for(const auto & pos : terrainSel.getSelectedItems())
{
auto & tile = map->getTile(pos);
tile.terrainType = terType;
if (formerState.find(tile.terrainType) == formerState.end())
formerState.insert({tile.terrainType, CTerrainSelection(terrainSel.getMap())});
formerState.at(tile.terrainType).select(pos);
}
drawTerrain(terType, terrainSel);
}
void CDrawTerrainOperation::drawTerrain(TerrainId terrainType, CTerrainSelection selection)
{
for(const auto & pos : selection.getSelectedItems())
{
auto & tile = map->getTile(pos);
tile.terrainType = terrainType;
invalidateTerrainViews(pos);
}
updateTerrainTypes();
updateTerrainTypes(selection);
updateTerrainViews();
invalidatedTerViews.clear();
}
void CDrawTerrainOperation::undo()
{
//TODO
for (auto const& typeToSelection : formerState)
{
drawTerrain(typeToSelection.first, typeToSelection.second);
}
}
void CDrawTerrainOperation::redo()
{
//TODO
drawTerrain(terType, terrainSel);
}
std::string CDrawTerrainOperation::getLabel() const
@@ -126,9 +142,9 @@ std::string CDrawTerrainOperation::getLabel() const
return "Draw Terrain";
}
void CDrawTerrainOperation::updateTerrainTypes()
void CDrawTerrainOperation::updateTerrainTypes(CTerrainSelection selection)
{
auto positions = terrainSel.getSelectedItems();
auto positions = selection.getSelectedItems();
while(!positions.empty())
{
const auto & centerPos = *(positions.begin());
@@ -405,9 +421,9 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi
{
if(recDepth == 0 && map->isInTheMap(currentPos))
{
if(terType->getId() == centerTerType->getId())
if(centerTerType->getId() == terType->getId() || (centerTerType->getId() == ETerrainId::DIRT && !terType->isTransitionRequired()))
{
const auto patternForRule = LIBRARY->terviewh->getTerrainViewPatternsById(centerTerType->getId(), rule.name);
const auto patternForRule = LIBRARY->terviewh->getTerrainViewPatternsById(terType->getId(), rule.name);
if(auto p = patternForRule)
{
auto rslt = validateTerrainView(currentPos, &(p->get()), 1);

View File

@@ -94,7 +94,8 @@ private:
InvalidTiles() : centerPosValid(false) { }
};
void updateTerrainTypes();
void drawTerrain(TerrainId terrain, CTerrainSelection selection);
void updateTerrainTypes(CTerrainSelection selection);
void invalidateTerrainViews(const int3 & centerPos);
InvalidTiles getInvalidTiles(const int3 & centerPos) const;
@@ -106,6 +107,7 @@ private:
CTerrainSelection terrainSel;
TerrainId terType;
std::map<TerrainId, CTerrainSelection> formerState;
int decorationsPercentage;
vstd::RNG* gen;
std::set<int3> invalidatedTerViews;

View File

@@ -120,14 +120,14 @@ void CTerrainSelection::setSelection(const std::vector<int3> & vec)
void CTerrainSelection::selectAll()
{
selectRange(MapRect(int3(0, 0, 0), getMap()->width, getMap()->height));
selectRange(MapRect(int3(0, 0, 1), getMap()->width, getMap()->height));
for(int i = 0; i < getMap()->mapLevels; i++)
selectRange(MapRect(int3(0, 0, i), getMap()->width, getMap()->height));
}
void CTerrainSelection::clearSelection()
{
deselectRange(MapRect(int3(0, 0, 0), getMap()->width, getMap()->height));
deselectRange(MapRect(int3(0, 0, 1), getMap()->width, getMap()->height));
for(int i = 0; i < getMap()->mapLevels; i++)
deselectRange(MapRect(int3(0, 0, i), getMap()->width, getMap()->height));
}
CObjectSelection::CObjectSelection(CMap * map) : CMapSelection(map)

View File

@@ -870,6 +870,8 @@ void CMapLoaderJson::readHeader(const bool complete)
readTeams(handler);
//TODO: check mods
mapHeader->battleOnly = header["battleOnly"].Bool();
if(complete)
readOptions(handler);
@@ -1225,6 +1227,8 @@ void CMapSaverJson::writeHeader()
writeTeams(handler);
header["battleOnly"].Bool() = mapHeader->battleOnly;
writeOptions(handler);
writeTranslations();