1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-18 17:40:48 +02:00

Merge remote-tracking branch 'upstream/features/new-terrains' into cpp-map-editor

# Conflicts:
#	config/randomMap.json
#	config/terrains.json
#	lib/rmg/CMapGenerator.cpp
#	lib/rmg/CMapGenerator.h
#	lib/rmg/ObjectManager.cpp
#	lib/rmg/ObjectManager.h
#	lib/rmg/ObstaclePlacer.cpp
#	lib/rmg/ObstaclePlacer.h
#	lib/rmg/RmgArea.h
#	lib/rmg/RmgMap.cpp
#	lib/rmg/RmgMap.h
#	lib/rmg/RoadPlacer.cpp
#	lib/rmg/RoadPlacer.h
#	lib/rmg/Zone.cpp
#	lib/rmg/Zone.h
This commit is contained in:
nordsoft 2022-09-04 15:54:37 +04:00
commit 149790ad2d
16 changed files with 171 additions and 29 deletions

View File

@ -80,4 +80,4 @@ Dmitry Orlov, <shubus.corporation@gmail.com>
* special buildings support in fan towns, new features and bug fixes * special buildings support in fan towns, new features and bug fixes
Andrey Cherkas aka nordsoft, <nordsoft@yahoo.com> Andrey Cherkas aka nordsoft, <nordsoft@yahoo.com>
* random map generator features and bug fixes * new terrain support, random map generator features and various bug fixes

View File

@ -37,8 +37,8 @@ if(NOT CMAKE_BUILD_TYPE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo)
endif() endif()
set(VCMI_VERSION_MAJOR 0) set(VCMI_VERSION_MAJOR 1)
set(VCMI_VERSION_MINOR 99) set(VCMI_VERSION_MINOR 0)
set(VCMI_VERSION_PATCH 0) set(VCMI_VERSION_PATCH 0)
option(ENABLE_ERM "Enable compilation of ERM scripting module" ON) option(ENABLE_ERM "Enable compilation of ERM scripting module" ON)

View File

@ -1,9 +1,12 @@
0.99 -> 1.00 0.99 -> 1.0
GENERAL: GENERAL:
* Spectator mode was implemented through command-line options * Spectator mode was implemented through command-line options
* Some main menu settings get saved after returning to main menu - last selected map, save etc. * Some main menu settings get saved after returning to main menu - last selected map, save etc.
* Restart scenario button should work correctly now * Restart scenario button should work correctly now
* Skyship Grail works now immediately after capturing without battle
* Lodestar Grail implemented
* Fixed Gargoyles immunity
* New bonuses: * New bonuses:
- SOUL_STEAL - "WoG ghost" ability, should work somewhat same as in H3 - SOUL_STEAL - "WoG ghost" ability, should work somewhat same as in H3
- TRANSMUTATION - "WoG werewolf"-like ability - TRANSMUTATION - "WoG werewolf"-like ability
@ -35,6 +38,15 @@ MODS:
* Added bonus updaters for hero specialties * Added bonus updaters for hero specialties
* Added allOf, anyOf and noneOf qualifiers for bonus limiters * Added allOf, anyOf and noneOf qualifiers for bonus limiters
* Added bonus limiters: alignment, faction and terrain * Added bonus limiters: alignment, faction and terrain
* Supported new terrains, new battlefields, custom water and rock terrains
* Following special buildings becomes available in the fan towns:
- attackVisitingBonus
- defenceVisitingBonus
- spellPowerVisitingBonus
- knowledgeVisitingBonus
- experienceVisitingBonus
- lighthouse
- treasury
SOUND: SOUND:
* Fixed many mising or wrong pickup and visit sounds for map objects * Fixed many mising or wrong pickup and visit sounds for map objects
@ -46,6 +58,33 @@ RANDOM MAP GENERATOR:
* Added parameter for template allowedWaterContent * Added parameter for template allowedWaterContent
* Extra resource packs appear nearby mines * Extra resource packs appear nearby mines
* Underground can be player starting place for factions allowed to be placed underground * Underground can be player starting place for factions allowed to be placed underground
* Improved obstacles placement aesthetics
* Rivers are generated on the random maps
* RMG works more stable, various crashes have been fixed
* Treasures requiring guards are guaranteed to be protected
VCAI:
* Reworked goal decomposition engine, fixing many loopholes. AI will now pick correct goals faster.
* AI will now use universal pathfinding globally
* AI can use Summon Boat and Town Portal
* AI can gather and save resources on purpose
* AI will only buy army on demand instead of every turn
* AI can distinguish the value of all map objects
* General speed optimizations
BATTLES:
* Towers should block ranged retaliation
* AI can bypass broken wall with moat instead of standing and waiting until gate is destroyed
* Towers do not attack war machines automatically
* Draw is possible now as battle outcome in case the battle ends with only summoned creatures (both sides loose)
ADVENTURE MAP:
* Added buttons and keyboard shortcuts to quickly exchange army and artifacts between heroes
* Fix: Captured town should not be duplicated on the UI
LAUNCHER:
* Implemented notifications about updates
* Supported redirection links for downloading mods
0.98 -> 0.99 0.98 -> 0.99

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

40
Mods/vcmi/Data/s/std.verm Executable file
View File

@ -0,0 +1,40 @@
VERM
; standard verm file, global engine things should be put here
!?PI;
; example 1 --- Hello World
![print ^Hello world!^]
; example 2 --- simple arithmetics
![defun add [x y] [+ x y]]
![print [add 2 3]]
; example 3 --- semantic macros
![defmacro do-n-times [times body]
`[progn
[setq do-counter 0]
[setq do-max ,times]
[do [< do-counter do-max]
[progn
[setq do-counter [+ do-counter 1]]
,body
]
]
]
]
![do-n-times 4 [print ^tekst\n^]]
; example 4 --- conditional expression
![if [> 2 1] [print ^Wieksze^] [print ^Mniejsze^]]
; example 5 --- lambda expressions
![[lambda [x y] [if [> x y] [print ^wieksze^] [print ^mniejsze^]]] 2 3]
; example 6 --- resursion
![defun factorial [n]
[if [= n 0] 1
[* n [factorial [- n 1]]]
]
]
![print [factorial 8]]

14
Mods/vcmi/Data/s/testy.erm Executable file
View File

@ -0,0 +1,14 @@
ZVSE
!?PI;
!!VRv2777:S4;
!!DO1/0/5/1&v2777<>1:P0;
!?FU1;
!!VRv2778:Sx16%2;
!!IF&x16>3:M^Hello world number %X16! To duza liczba^;
!!IF&v2778==0&x16<=3:M^Hello world number %X16! To mala parzysta liczba^;
!!IF&v2778==1&x16<=3:M^Hello world number %X16! To mala nieparzysta liczba^;
!?PI;
!!VRz10:S^Composed hello ^;
!!IF:M^%Z10%%world%%, v2777=%V2777, v2778=%V2778!^;

Binary file not shown.

View File

@ -22,6 +22,7 @@
}, },
"minGuardStrength" : 2000, "minGuardStrength" : 2000,
"defaultRoadType" : "pc", //pd - dirt, pg - gravel, pc - cobblestone "defaultRoadType" : "pc", //pd - dirt, pg - gravel, pc - cobblestone
"secondaryRoadType": "pd",
"treasureValueLimit" : 20000, //generate pandora with gold for treasure above this limit "treasureValueLimit" : 20000, //generate pandora with gold for treasure above this limit
"prisons" : "prisons" :
{ {

View File

@ -9,7 +9,8 @@
"code" : "dt", "code" : "dt",
"river" : "rm", "river" : "rm",
"battleFields" : ["dirt_birches", "dirt_hills", "dirt_pines"], "battleFields" : ["dirt_birches", "dirt_hills", "dirt_pines"],
"terrainViewPatterns" : "dirt" "terrainViewPatterns" : "dirt",
"horseSoundId" : 0
}, },
"sand" : "sand" :
{ {
@ -22,7 +23,8 @@
"river" : "rm", "river" : "rm",
"battleFields" : ["sand_mesas"], "battleFields" : ["sand_mesas"],
"transitionRequired" : true, "transitionRequired" : true,
"terrainViewPatterns" : "sand" "terrainViewPatterns" : "sand",
"horseSoundId" : 1
}, },
"grass" : "grass" :
{ {
@ -33,7 +35,8 @@
"tiles" : "GRASTL", "tiles" : "GRASTL",
"code" : "gr", "code" : "gr",
"river" : "rw", "river" : "rw",
"battleFields" : ["grass_hills", "grass_pines"] "battleFields" : ["grass_hills", "grass_pines"],
"horseSoundId" : 2
}, },
"snow" : "snow" :
{ {
@ -44,7 +47,8 @@
"tiles" : "SNOWTL", "tiles" : "SNOWTL",
"code" : "sn", "code" : "sn",
"river" : "ri", "river" : "ri",
"battleFields" : ["snow_mountains", "snow_trees"] "battleFields" : ["snow_mountains", "snow_trees"],
"horseSoundId" : 3
}, },
"swamp" : "swamp" :
{ {
@ -55,7 +59,8 @@
"tiles" : "SWMPTL", "tiles" : "SWMPTL",
"code" : "sw", "code" : "sw",
"river" : "rw", "river" : "rw",
"battleFields" : ["swamp_trees"] "battleFields" : ["swamp_trees"],
"horseSoundId" : 4
}, },
"rough" : "rough" :
{ {
@ -66,7 +71,8 @@
"tiles" : "ROUGTL", "tiles" : "ROUGTL",
"code" : "rg", "code" : "rg",
"river" : "rm", "river" : "rm",
"battleFields" : ["rough"] "battleFields" : ["rough"],
"horseSoundId" : 5
}, },
"subterra" : "subterra" :
{ {
@ -79,7 +85,8 @@
"code" : "sb", "code" : "sb",
"river" : "rw", "river" : "rw",
"battleFields" : ["subterranean"], "battleFields" : ["subterranean"],
"rockTerrain" : "rock" "rockTerrain" : "rock",
"horseSoundId" : 6
}, },
"lava" : "lava" :
{ {
@ -91,7 +98,8 @@
"code" : "lv", "code" : "lv",
"river" : "rl", "river" : "rl",
"battleFields" : ["lava"], "battleFields" : ["lava"],
"rockTerrain" : "rock" "rockTerrain" : "rock",
"horseSoundId" : 7
}, },
"water" : "water" :
{ {
@ -104,7 +112,8 @@
"code" : "wt", "code" : "wt",
"battleFields" : ["ship"], "battleFields" : ["ship"],
"transitionRequired" : true, "transitionRequired" : true,
"terrainViewPatterns" : "water" "terrainViewPatterns" : "water",
"horseSoundId" : 8
}, },
"rock" : "rock" :
{ {
@ -117,6 +126,7 @@
"code" : "rc", "code" : "rc",
"battleFields" : ["rocklands"], "battleFields" : ["rocklands"],
"transitionRequired" : true, "transitionRequired" : true,
"terrainViewPatterns" : "rock" "terrainViewPatterns" : "rock",
"horseSoundId" : 9
} }
} }

View File

@ -51,9 +51,9 @@ const TeamID TeamID::NO_TEAM = TeamID(255);
namespace GameConstants namespace GameConstants
{ {
#ifdef VCMI_NO_EXTRA_VERSION #ifdef VCMI_NO_EXTRA_VERSION
const std::string VCMI_VERSION = std::string("VCMI 0.99"); const std::string VCMI_VERSION = std::string("VCMI 1.0.0");
#else #else
const std::string VCMI_VERSION = std::string("VCMI 0.99 ") + GIT_SHA1; const std::string VCMI_VERSION = std::string("VCMI 1.0.0.") + GIT_SHA1;
#endif #endif
} }

View File

@ -69,6 +69,7 @@ void CMapGenerator::loadConfig()
config.mineExtraResources = randomMapJson["mines"]["extraResourcesLimit"].Integer(); config.mineExtraResources = randomMapJson["mines"]["extraResourcesLimit"].Integer();
config.minGuardStrength = randomMapJson["minGuardStrength"].Integer(); config.minGuardStrength = randomMapJson["minGuardStrength"].Integer();
config.defaultRoadType = randomMapJson["defaultRoadType"].String(); config.defaultRoadType = randomMapJson["defaultRoadType"].String();
config.secondaryRoadType = randomMapJson["secondaryRoadType"].String();
config.treasureValueLimit = randomMapJson["treasureValueLimit"].Integer(); config.treasureValueLimit = randomMapJson["treasureValueLimit"].Integer();
for(auto & i : randomMapJson["prisons"]["experience"].Vector()) for(auto & i : randomMapJson["prisons"]["experience"].Vector())
config.prisonExperience.push_back(i.Integer()); config.prisonExperience.push_back(i.Integer());

View File

@ -39,6 +39,7 @@ public:
int mineExtraResources; int mineExtraResources;
int minGuardStrength; int minGuardStrength;
std::string defaultRoadType; std::string defaultRoadType;
std::string secondaryRoadType;
int treasureValueLimit; int treasureValueLimit;
std::vector<int> prisonExperience, prisonValues; std::vector<int> prisonExperience, prisonValues;
std::vector<int> scrollValues; std::vector<int> scrollValues;

View File

@ -27,7 +27,7 @@
void ObjectManager::process() void ObjectManager::process()
{ {
zone.fractalize(); zone.fractalize();
createRequiredObjects(); createRequiredObjects();
} }
void ObjectManager::init() void ObjectManager::init()
@ -77,6 +77,21 @@ const rmg::Area & ObjectManager::getVisitableArea() const
return objectsVisitableArea; return objectsVisitableArea;
} }
std::vector<CGObjectInstance*> ObjectManager::getMines() const
{
std::vector<CGObjectInstance*> mines;
for (auto object : objects)
{
if (object->ID == Obj::MINE)
{
mines.push_back(object);
}
}
return mines;
}
int3 ObjectManager::findPlaceForObject(const rmg::Area & searchArea, rmg::Object & obj, std::function<float(const int3)> weightFunction, OptimizeType optimizer) const int3 ObjectManager::findPlaceForObject(const rmg::Area & searchArea, rmg::Object & obj, std::function<float(const int3)> weightFunction, OptimizeType optimizer) const
{ {
float bestWeight = 0.f; float bestWeight = 0.f;
@ -220,6 +235,7 @@ bool ObjectManager::createRequiredObjects()
{ {
logGlobal->trace("Creating required objects"); logGlobal->trace("Creating required objects");
RandomGeneratorUtil::randomShuffle(requiredObjects, generator.rand);
for(const auto & object : requiredObjects) for(const auto & object : requiredObjects)
{ {
auto * obj = object.first; auto * obj = object.first;

View File

@ -64,6 +64,8 @@ public:
const rmg::Area & getVisitableArea() const; const rmg::Area & getVisitableArea() const;
std::vector<CGObjectInstance*> getMines() const;
protected: protected:
//content info //content info
std::vector<std::pair<CGObjectInstance*, ui32>> requiredObjects; std::vector<std::pair<CGObjectInstance*, ui32>> requiredObjects;

View File

@ -10,6 +10,7 @@
#include "StdInc.h" #include "StdInc.h"
#include "RoadPlacer.h" #include "RoadPlacer.h"
#include "ObjectManager.h"
#include "Functions.h" #include "Functions.h"
#include "CMapGenerator.h" #include "CMapGenerator.h"
#include "RmgMap.h" #include "RmgMap.h"
@ -63,12 +64,13 @@ bool RoadPlacer::createRoad(const int3 & dst)
} }
void RoadPlacer::drawRoads() void RoadPlacer::drawRoads(bool secondary)
{ {
zone.areaPossible().subtract(roads); zone.areaPossible().subtract(roads);
zone.freePaths().unite(roads); zone.freePaths().unite(roads);
map.getEditManager()->getTerrainSelection().setSelection(roads.getTilesVector()); map.getEditManager()->getTerrainSelection().setSelection(roads.getTilesVector());
map.getEditManager()->drawRoad(generator.getConfig().defaultRoadType, &generator.rand); std::string roadType = (secondary ? generator.getConfig().secondaryRoadType : generator.getConfig().defaultRoadType);
map.getEditManager()->drawRoad(roadType, &generator.rand);
} }
void RoadPlacer::addRoadNode(const int3& node) void RoadPlacer::addRoadNode(const int3& node)
@ -78,7 +80,22 @@ void RoadPlacer::addRoadNode(const int3& node)
void RoadPlacer::connectRoads() void RoadPlacer::connectRoads()
{ {
if(roadNodes.empty()) bool noRoadNodes = false;
//Assumes objects are already placed
if (roadNodes.size() < 2)
{
//If there are no nodes, draw roads to mines
noRoadNodes = true;
if (auto* m = zone.getModificator<ObjectManager>())
{
for (auto object : m->getMines())
{
addRoadNode(object->visitablePos());
}
}
}
if(roadNodes.size() < 2)
return; return;
//take any tile from road nodes as destination zone for all other road nodes //take any tile from road nodes as destination zone for all other road nodes
@ -90,7 +107,8 @@ void RoadPlacer::connectRoads()
createRoad(node); createRoad(node);
} }
drawRoads(); //Draw dirt roads if there are only mines
drawRoads(noRoadNodes);
} }
char RoadPlacer::dump(const int3 & t) char RoadPlacer::dump(const int3 & t)

View File

@ -28,7 +28,7 @@ public:
protected: protected:
bool createRoad(const int3 & dst); bool createRoad(const int3 & dst);
void drawRoads(); //actually updates tiles void drawRoads(bool secondary = false); //actually updates tiles
protected: protected:
rmg::Tileset roadNodes; //tiles to be connected with roads rmg::Tileset roadNodes; //tiles to be connected with roads