diff --git a/client/mapView/MapRenderer.cpp b/client/mapView/MapRenderer.cpp index ef8d0d8e4..cd2f8a746 100644 --- a/client/mapView/MapRenderer.cpp +++ b/client/mapView/MapRenderer.cpp @@ -145,16 +145,8 @@ void MapRendererTerrain::renderTile(IMapRendererContext & context, Canvas & targ const auto & image = storage.find(terrainIndex, rotationIndex, imageIndex); - if(mapTile.terType->getId() == ETerrainId::LAVA) - { - image->shiftPalette(246, 9, context.terrainImageIndex(9)); - } - - if(mapTile.terType->getId() == ETerrainId::WATER) - { - image->shiftPalette(229, 12, context.terrainImageIndex(12)); - image->shiftPalette(242, 14, context.terrainImageIndex(14)); - } + for( auto const & element : mapTile.terType->paletteAnimation) + image->shiftPalette(element.start, element.length, context.terrainImageIndex(element.length)); target.draw(image, Point(0, 0)); } @@ -163,7 +155,7 @@ uint8_t MapRendererTerrain::checksum(IMapRendererContext & context, const int3 & { const TerrainTile & mapTile = context.getMapTile(coordinates); - if(mapTile.terType->getId() == ETerrainId::LAVA || mapTile.terType->getId() == ETerrainId::WATER) + if(!mapTile.terType->paletteAnimation.empty()) return context.terrainImageIndex(250); return 0xff - 1; } @@ -188,23 +180,8 @@ void MapRendererRiver::renderTile(IMapRendererContext & context, Canvas & target const auto & image = storage.find(terrainIndex, rotationIndex, imageIndex); - if(mapTile.riverType->getId() == River::WATER_RIVER) - { - image->shiftPalette(183, 12, context.terrainImageIndex(12)); - image->shiftPalette(195, 6, context.terrainImageIndex(6)); - } - - if(mapTile.riverType->getId() == River::MUD_RIVER) - { - image->shiftPalette(228, 12, context.terrainImageIndex(12)); - image->shiftPalette(183, 6, context.terrainImageIndex(6)); - image->shiftPalette(240, 6, context.terrainImageIndex(6)); - } - - if(mapTile.riverType->getId() == River::LAVA_RIVER) - { - image->shiftPalette(240, 9, context.terrainImageIndex(9)); - } + for( auto const & element : mapTile.riverType->paletteAnimation) + image->shiftPalette(element.start, element.length, context.terrainImageIndex(element.length)); target.draw(image, Point(0, 0)); } @@ -213,9 +190,7 @@ uint8_t MapRendererRiver::checksum(IMapRendererContext & context, const int3 & c { const TerrainTile & mapTile = context.getMapTile(coordinates); - if(mapTile.riverType->getId() == River::WATER_RIVER || - mapTile.riverType->getId() == River::MUD_RIVER || - mapTile.riverType->getId() == River::LAVA_RIVER) + if(!mapTile.riverType->paletteAnimation.empty()) return context.terrainImageIndex(250); return 0xff-1; } diff --git a/config/rivers.json b/config/rivers.json index b9cc138dd..8e05091e4 100644 --- a/config/rivers.json +++ b/config/rivers.json @@ -1,34 +1,46 @@ { - "waterRiver": - { - "index": 1, - "text" : "Water river", - "shortIdentifier": "rw", //must be 2 characters - "tilesFilename": "clrrvr", - "delta": "clrdelt" - }, - "iceRiver": - { - "index": 2, - "text" : "Ice river", - "shortIdentifier": "ri", - "tilesFilename": "icyrvr", - "delta": "icedelt" - }, - "mudRiver": - { - "index": 3, - "text" : "Mud river", - "shortIdentifier": "rm", - "tilesFilename": "mudrvr", - "delta": "muddelt" - }, - "lavaRiver": - { - "index": 4, - "text" : "Lava river", - "shortIdentifier": "rl", - "tilesFilename": "lavrvr", - "delta": "lavdelt" - } + "waterRiver": + { + "index": 1, + "text" : "Water river", + "shortIdentifier": "rw", //must be 2 characters + "tilesFilename": "clrrvr", + "delta": "clrdelt", + "paletteAnimation" : [ + { "start" : 183, "length" : 12 }, + { "start" : 195, "length" : 6 } + ] + }, + "iceRiver": + { + "index": 2, + "text" : "Ice river", + "shortIdentifier": "ri", + "tilesFilename": "icyrvr", + "delta": "icedelt" + }, + "mudRiver": + { + "index": 3, + "text" : "Mud river", + "shortIdentifier": "rm", + "tilesFilename": "mudrvr", + "delta": "muddelt", + "paletteAnimation" : [ + { "start" : 228, "length" : 12 }, + { "start" : 183, "length" : 6 }, + { "start" : 240, "length" : 6 } + ] + }, + "lavaRiver": + { + "index": 4, + "text" : "Lava river", + "shortIdentifier": "rl", + "tilesFilename": "lavrvr", + "delta": "lavdelt", + "paletteAnimation" : [ + { "start" : 240, "length" : 9 } + ] + } } diff --git a/config/schemas/river.json b/config/schemas/river.json index 56d8dccd5..38e0d780e 100644 --- a/config/schemas/river.json +++ b/config/schemas/river.json @@ -27,6 +27,23 @@ "type" : "string", "description" : "Name of file with river delta graphics" }, + "paletteAnimation" : { + "type" : "array", + "description" : "If defined, terrain will be animated using palette color cycling effect", + "items" : + { + "type" : "object", + "additionalProperties" : false, + "properties" : { + "start" : { + "type" : "number" + }, + "length" : { + "type" : "number" + } + } + } + }, "index" : { "type" : "number", diff --git a/config/schemas/terrain.json b/config/schemas/terrain.json index febe11346..e9e5f2b91 100644 --- a/config/schemas/terrain.json +++ b/config/schemas/terrain.json @@ -47,6 +47,23 @@ "type" : "string", "description" : "River type which should be used for that terrain" }, + "paletteAnimation" : { + "type" : "array", + "description" : "If defined, terrain will be animated using palette color cycling effect", + "items" : + { + "type" : "object", + "additionalProperties" : false, + "properties" : { + "start" : { + "type" : "number" + }, + "length" : { + "type" : "number" + } + } + } + }, "battleFields" : { "type" : "array", diff --git a/config/terrains.json b/config/terrains.json index 6cddc2f84..e649fcdb2 100644 --- a/config/terrains.json +++ b/config/terrains.json @@ -122,7 +122,10 @@ "battleFields" : ["lava"], "rockTerrain" : "rock", "horseSound" : "horse07", - "horseSoundPenalty" : "horse27" + "horseSoundPenalty" : "horse27", + "paletteAnimation" : [ + { "start" : 246, "length" : 9 } + ] }, "water" : { @@ -139,6 +142,10 @@ "terrainViewPatterns" : "water", "horseSound" : "horse08", "horseSoundPenalty" : "horse08", + "paletteAnimation" : [ + { "start" : 229, "length" : 12 }, + { "start" : 242, "length" : 12 } + ], "sounds": { "ambient": ["LOOPOCEA"] } diff --git a/lib/RiverHandler.cpp b/lib/RiverHandler.cpp index 6710f46a2..ba7344dd0 100644 --- a/lib/RiverHandler.cpp +++ b/lib/RiverHandler.cpp @@ -40,6 +40,15 @@ RiverType * RiverTypeHandler::loadFromJson( info->shortIdentifier = json["shortIdentifier"].String(); info->deltaName = json["delta"].String(); + for(const auto & t : json["paletteAnimation"].Vector()) + { + RiverPaletteAnimation element{ + static_cast(t["start"].Integer()), + static_cast(t["length"].Integer()) + }; + info->paletteAnimation.push_back(element); + } + VLC->generaltexth->registerString(scope, info->getNameTextID(), json["text"].String()); return info; diff --git a/lib/RiverHandler.h b/lib/RiverHandler.h index 13444add2..22fad8660 100644 --- a/lib/RiverHandler.h +++ b/lib/RiverHandler.h @@ -17,6 +17,20 @@ VCMI_LIB_NAMESPACE_BEGIN +struct DLL_LINKAGE RiverPaletteAnimation +{ + /// index of first color to cycle + int32_t start; + /// total numbers of colors to cycle + int32_t length; + + template void serialize(Handler& h, const int version) + { + h & start; + h & length; + } +}; + class DLL_LINKAGE RiverType : public EntityT { friend class RiverTypeHandler; @@ -39,6 +53,8 @@ public: std::string shortIdentifier; std::string deltaName; + std::vector paletteAnimation; + RiverType(); template void serialize(Handler& h, const int version) @@ -48,6 +64,7 @@ public: h & modScope; h & deltaName; h & id; + h & paletteAnimation; } }; diff --git a/lib/TerrainHandler.cpp b/lib/TerrainHandler.cpp index ec3b0c4c3..fbdcc48df 100644 --- a/lib/TerrainHandler.cpp +++ b/lib/TerrainHandler.cpp @@ -73,6 +73,15 @@ TerrainType * TerrainTypeHandler::loadFromJson( const std::string & scope, const }); } + for(const auto & t : json["paletteAnimation"].Vector()) + { + TerrainPaletteAnimation element{ + static_cast(t["start"].Integer()), + static_cast(t["length"].Integer()) + }; + info->paletteAnimation.push_back(element); + } + info->shortIdentifier = json["shortIdentifier"].String(); assert(info->shortIdentifier.length() == 2); diff --git a/lib/TerrainHandler.h b/lib/TerrainHandler.h index 6d23c59fa..5a10f1afa 100644 --- a/lib/TerrainHandler.h +++ b/lib/TerrainHandler.h @@ -18,6 +18,21 @@ VCMI_LIB_NAMESPACE_BEGIN +struct DLL_LINKAGE TerrainPaletteAnimation +{ + /// index of first color to cycle + int32_t start; + /// total numbers of colors to cycle + int32_t length; + + template void serialize(Handler& h, const int version) + { + h & start; + h & length; + } +}; + + class DLL_LINKAGE TerrainType : public EntityT { friend class TerrainTypeHandler; @@ -57,6 +72,8 @@ public: std::string horseSound; std::string horseSoundPenalty; + std::vector paletteAnimation; + TerrainId rockTerrain; RiverId river; int moveCost; @@ -87,6 +104,7 @@ public: h & terrainViewPatterns; h & rockTerrain; h & river; + h & paletteAnimation; h & id; h & moveCost; diff --git a/lib/serializer/CSerializer.h b/lib/serializer/CSerializer.h index 52c556a6a..62e76c9a2 100644 --- a/lib/serializer/CSerializer.h +++ b/lib/serializer/CSerializer.h @@ -14,8 +14,8 @@ VCMI_LIB_NAMESPACE_BEGIN -const ui32 SERIALIZATION_VERSION = 823; -const ui32 MINIMAL_SERIALIZATION_VERSION = 823; +const ui32 SERIALIZATION_VERSION = 824; +const ui32 MINIMAL_SERIALIZATION_VERSION = 824; const std::string SAVEGAME_MAGIC = "VCMISVG"; class CHero;