mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-25 22:42:04 +02:00
Reworked & fixed DARKNESS bonuses and lookout tower / skyship logic
This commit is contained in:
@@ -171,7 +171,12 @@
|
|||||||
"special1": { "requires" : [ "marketplace" ], "marketModes" : ["resource-artifact", "artifact-resource"] },
|
"special1": { "requires" : [ "marketplace" ], "marketModes" : ["resource-artifact", "artifact-resource"] },
|
||||||
"horde1": { "id" : 18, "upgrades" : "dwellingLvl2" },
|
"horde1": { "id" : 18, "upgrades" : "dwellingLvl2" },
|
||||||
"horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl2", "requires" : [ "horde1" ], "mode" : "auto" },
|
"horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl2", "requires" : [ "horde1" ], "mode" : "auto" },
|
||||||
"special2": { "height" : "high", "requires" : [ "fort" ] },
|
"special2": {
|
||||||
|
"requires" : [ "fort" ],
|
||||||
|
"bonuses": [
|
||||||
|
{ "type": "SIGHT_RADIUS", "val": 15 }, // 5 base + 15 bonus = 20 tiles range
|
||||||
|
]
|
||||||
|
},
|
||||||
"special3": { "type" : "library", "requires" : [ "mageGuild1" ] },
|
"special3": { "type" : "library", "requires" : [ "mageGuild1" ] },
|
||||||
"special4": {
|
"special4": {
|
||||||
"requires" : [ "mageGuild1" ],
|
"requires" : [ "mageGuild1" ],
|
||||||
@@ -185,7 +190,13 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grail": { "height" : "skyship", "produce" : { "gold": 5000 }, "bonuses": [ { "type": "PRIMARY_SKILL", "subtype": "primarySkill.knowledge", "val": 15 } ] },
|
"grail": {
|
||||||
|
"produce" : { "gold": 5000 },
|
||||||
|
"bonuses": [
|
||||||
|
{ "type": "PRIMARY_SKILL", "subtype": "primarySkill.knowledge", "val": 15 },
|
||||||
|
{ "type": "FULL_MAP_SCOUTING" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
"dwellingLvl1": { "id" : 30, "requires" : [ "fort" ] },
|
"dwellingLvl1": { "id" : 30, "requires" : [ "fort" ] },
|
||||||
"dwellingLvl2": { "id" : 31, "requires" : [ "dwellingLvl1" ] },
|
"dwellingLvl2": { "id" : 31, "requires" : [ "dwellingLvl1" ] },
|
||||||
|
|||||||
@@ -314,6 +314,9 @@
|
|||||||
"movementPointsLand" : [ 1500, 1500, 1500, 1500, 1560, 1630, 1700, 1760, 1830, 1900, 1960, 2000 ],
|
"movementPointsLand" : [ 1500, 1500, 1500, 1500, 1560, 1630, 1700, 1760, 1830, 1900, 1960, 2000 ],
|
||||||
/// movement points hero can get on start of the turn when on sea, depending on speed of slowest creature (0-based list)
|
/// movement points hero can get on start of the turn when on sea, depending on speed of slowest creature (0-based list)
|
||||||
"movementPointsSea" : [ 1500 ]
|
"movementPointsSea" : [ 1500 ]
|
||||||
|
|
||||||
|
/// Base scouting range for hero without any range modifiers
|
||||||
|
"baseScoutingRange" : 5,
|
||||||
},
|
},
|
||||||
|
|
||||||
"towns":
|
"towns":
|
||||||
@@ -335,7 +338,10 @@
|
|||||||
// How much researchs/skips per day are possible? (array index is spell tier)
|
// How much researchs/skips per day are possible? (array index is spell tier)
|
||||||
"spellResearchPerDay": [ 2, 2, 2, 2, 1 ],
|
"spellResearchPerDay": [ 2, 2, 2, 2, 1 ],
|
||||||
// Exponent for increasing cost for each research (factor 1 disables this; array index is spell tier)
|
// Exponent for increasing cost for each research (factor 1 disables this; array index is spell tier)
|
||||||
"spellResearchCostExponentPerResearch": [ 1.25, 1.25, 1.25, 1.25, 1.25 ]
|
"spellResearchCostExponentPerResearch": [ 1.25, 1.25, 1.25, 1.25, 1.25 ],
|
||||||
|
|
||||||
|
// Base scouting range for town without any range modifiers
|
||||||
|
"baseScoutingRange" : 5,
|
||||||
},
|
},
|
||||||
|
|
||||||
"combat":
|
"combat":
|
||||||
@@ -581,12 +587,6 @@
|
|||||||
"val" : 1,
|
"val" : 1,
|
||||||
"valueType" : "BASE_NUMBER"
|
"valueType" : "BASE_NUMBER"
|
||||||
},
|
},
|
||||||
"sightRadius" :
|
|
||||||
{
|
|
||||||
"type" : "SIGHT_RADIUS", //default sight radius
|
|
||||||
"val" : 5,
|
|
||||||
"valueType" : "BASE_NUMBER"
|
|
||||||
},
|
|
||||||
"experienceGain" :
|
"experienceGain" :
|
||||||
{
|
{
|
||||||
"type" : "HERO_EXPERIENCE_GAIN_PERCENT", //default hero xp
|
"type" : "HERO_EXPERIENCE_GAIN_PERCENT", //default hero xp
|
||||||
|
|||||||
@@ -44,11 +44,6 @@
|
|||||||
"enum" : [ "normal", "auto", "special", "grail" ],
|
"enum" : [ "normal", "auto", "special", "grail" ],
|
||||||
"description" : "Mode in which this building will be built"
|
"description" : "Mode in which this building will be built"
|
||||||
},
|
},
|
||||||
"height" : {
|
|
||||||
"type" : "string",
|
|
||||||
"enum" : [ "skyship", "high", "average", "low"],
|
|
||||||
"description" : "Height for lookout towers and some grails"
|
|
||||||
},
|
|
||||||
"requires" : {
|
"requires" : {
|
||||||
"$ref" : "#/definitions/buildingRequirement",
|
"$ref" : "#/definitions/buildingRequirement",
|
||||||
"description" : "List of town buildings that must be built before this one"
|
"description" : "List of town buildings that must be built before this one"
|
||||||
|
|||||||
@@ -27,12 +27,6 @@ Changes mastery level of spells of affected heroes and units. Examples are magic
|
|||||||
- subtype: school of magic
|
- subtype: school of magic
|
||||||
- val: level
|
- val: level
|
||||||
|
|
||||||
### DARKNESS
|
|
||||||
|
|
||||||
On each turn, hides area in fog of war around affected town for all players other than town owner. Currently does not work for any entities other than towns.
|
|
||||||
|
|
||||||
- val: radius in tiles
|
|
||||||
|
|
||||||
## Player bonuses
|
## Player bonuses
|
||||||
|
|
||||||
Intended to be setup as global effect, AI cheat etc.
|
Intended to be setup as global effect, AI cheat etc.
|
||||||
@@ -99,6 +93,27 @@ Reveal area of fog of war around affected heroes when hero is recruited or moves
|
|||||||
|
|
||||||
- val: radius in tiles
|
- val: radius in tiles
|
||||||
|
|
||||||
|
### DARKNESS
|
||||||
|
|
||||||
|
On each turn, hides area in fog of war around affected objects for all players other than town owner. Areas within scouting range of owned objects are not affected
|
||||||
|
|
||||||
|
NOTE: when used by heroes, effect would still activate only on new turn, and not on every hero movement
|
||||||
|
|
||||||
|
- val: radius in tiles
|
||||||
|
- addInfo: optional, activation period (e.g. 7 = weekly, 28 = monthly)
|
||||||
|
|
||||||
|
### FULL_MAP_SCOUTING
|
||||||
|
|
||||||
|
On each turn, reveals entire map for owner of the bonus
|
||||||
|
|
||||||
|
- addInfo: optional, activation period (e.g. 7 = weekly, 28 = monthly)
|
||||||
|
|
||||||
|
### FULL_MAP_DARKNESS
|
||||||
|
|
||||||
|
On each turn, hides entire map in fog of war for all players other than town owner. Areas within scouting range of owned objects are not affected
|
||||||
|
|
||||||
|
- addInfo: optional, activation period (e.g. 7 = weekly, 28 = monthly)
|
||||||
|
|
||||||
### MANA_REGENERATION
|
### MANA_REGENERATION
|
||||||
|
|
||||||
Restores specific amount of mana points for affected heroes on new turn
|
Restores specific amount of mana points for affected heroes on new turn
|
||||||
|
|||||||
@@ -150,16 +150,7 @@ These are just a couple of examples of what can be done in VCMI. See vcmi config
|
|||||||
// Generally only needs to be specified for "special" buildings
|
// Generally only needs to be specified for "special" buildings
|
||||||
// See 'List of unique town buildings' section below for detailed description of this field
|
// See 'List of unique town buildings' section below for detailed description of this field
|
||||||
"type" : "",
|
"type" : "",
|
||||||
|
|
||||||
// If set, building will have Lookout Tower logic - extend sight radius of a town.
|
|
||||||
// Possible values:
|
|
||||||
// low - increases town sight radius by 5 tiles
|
|
||||||
// average - sight radius extended by 15 tiles
|
|
||||||
// high - sight radius extended by 20 tiles
|
|
||||||
// skyship - entire map will be revealed
|
|
||||||
// If not set, building will not affect sight radius of a town
|
|
||||||
"height" : "average"
|
|
||||||
|
|
||||||
// Resources produced each day by this building
|
// Resources produced each day by this building
|
||||||
"produce" : {
|
"produce" : {
|
||||||
"sulfur" : 1,
|
"sulfur" : 1,
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ const std::vector<GameSettings::SettingOption> GameSettings::settingProperties =
|
|||||||
{EGameSettings::DWELLINGS_ACCUMULATE_WHEN_OWNED, "dwellings", "accumulateWhenOwned" },
|
{EGameSettings::DWELLINGS_ACCUMULATE_WHEN_OWNED, "dwellings", "accumulateWhenOwned" },
|
||||||
{EGameSettings::DWELLINGS_MERGE_ON_RECRUIT, "dwellings", "mergeOnRecruit" },
|
{EGameSettings::DWELLINGS_MERGE_ON_RECRUIT, "dwellings", "mergeOnRecruit" },
|
||||||
{EGameSettings::HEROES_BACKPACK_CAP, "heroes", "backpackSize" },
|
{EGameSettings::HEROES_BACKPACK_CAP, "heroes", "backpackSize" },
|
||||||
|
{EGameSettings::HEROES_BASE_SCOUNTING_RANGE, "heroes", "baseScoutingRange" },
|
||||||
{EGameSettings::HEROES_MINIMAL_PRIMARY_SKILLS, "heroes", "minimalPrimarySkills" },
|
{EGameSettings::HEROES_MINIMAL_PRIMARY_SKILLS, "heroes", "minimalPrimarySkills" },
|
||||||
{EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP, "heroes", "perPlayerOnMapCap" },
|
{EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP, "heroes", "perPlayerOnMapCap" },
|
||||||
{EGameSettings::HEROES_PER_PLAYER_TOTAL_CAP, "heroes", "perPlayerTotalCap" },
|
{EGameSettings::HEROES_PER_PLAYER_TOTAL_CAP, "heroes", "perPlayerTotalCap" },
|
||||||
@@ -116,6 +117,7 @@ const std::vector<GameSettings::SettingOption> GameSettings::settingProperties =
|
|||||||
{EGameSettings::TEXTS_ROAD, "textData", "road" },
|
{EGameSettings::TEXTS_ROAD, "textData", "road" },
|
||||||
{EGameSettings::TEXTS_SPELL, "textData", "spell" },
|
{EGameSettings::TEXTS_SPELL, "textData", "spell" },
|
||||||
{EGameSettings::TEXTS_TERRAIN, "textData", "terrain" },
|
{EGameSettings::TEXTS_TERRAIN, "textData", "terrain" },
|
||||||
|
{EGameSettings::TOWNS_BASE_SCOUNTING_RANGE, "towns", "baseScoutingRange" },
|
||||||
{EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP, "towns", "buildingsPerTurnCap" },
|
{EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP, "towns", "buildingsPerTurnCap" },
|
||||||
{EGameSettings::TOWNS_STARTING_DWELLING_CHANCES, "towns", "startingDwellingChances" },
|
{EGameSettings::TOWNS_STARTING_DWELLING_CHANCES, "towns", "startingDwellingChances" },
|
||||||
{EGameSettings::TOWNS_SPELL_RESEARCH, "towns", "spellResearch" },
|
{EGameSettings::TOWNS_SPELL_RESEARCH, "towns", "spellResearch" },
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ enum class EGameSettings
|
|||||||
DWELLINGS_ACCUMULATE_WHEN_OWNED,
|
DWELLINGS_ACCUMULATE_WHEN_OWNED,
|
||||||
DWELLINGS_MERGE_ON_RECRUIT,
|
DWELLINGS_MERGE_ON_RECRUIT,
|
||||||
HEROES_BACKPACK_CAP,
|
HEROES_BACKPACK_CAP,
|
||||||
|
HEROES_BASE_SCOUNTING_RANGE,
|
||||||
HEROES_MINIMAL_PRIMARY_SKILLS,
|
HEROES_MINIMAL_PRIMARY_SKILLS,
|
||||||
HEROES_PER_PLAYER_ON_MAP_CAP,
|
HEROES_PER_PLAYER_ON_MAP_CAP,
|
||||||
HEROES_PER_PLAYER_TOTAL_CAP,
|
HEROES_PER_PLAYER_TOTAL_CAP,
|
||||||
@@ -59,6 +60,7 @@ enum class EGameSettings
|
|||||||
HEROES_MOVEMENT_COST_BASE,
|
HEROES_MOVEMENT_COST_BASE,
|
||||||
HEROES_MOVEMENT_POINTS_LAND,
|
HEROES_MOVEMENT_POINTS_LAND,
|
||||||
HEROES_MOVEMENT_POINTS_SEA,
|
HEROES_MOVEMENT_POINTS_SEA,
|
||||||
|
INTERFACE_PLAYER_COLORED_BACKGROUND,
|
||||||
MAP_FORMAT_ARMAGEDDONS_BLADE,
|
MAP_FORMAT_ARMAGEDDONS_BLADE,
|
||||||
MAP_FORMAT_CHRONICLES,
|
MAP_FORMAT_CHRONICLES,
|
||||||
MAP_FORMAT_HORN_OF_THE_ABYSS,
|
MAP_FORMAT_HORN_OF_THE_ABYSS,
|
||||||
@@ -91,14 +93,13 @@ enum class EGameSettings
|
|||||||
TEXTS_TERRAIN,
|
TEXTS_TERRAIN,
|
||||||
TOWNS_BUILDINGS_PER_TURN_CAP,
|
TOWNS_BUILDINGS_PER_TURN_CAP,
|
||||||
TOWNS_STARTING_DWELLING_CHANCES,
|
TOWNS_STARTING_DWELLING_CHANCES,
|
||||||
INTERFACE_PLAYER_COLORED_BACKGROUND,
|
TOWNS_BASE_SCOUNTING_RANGE,
|
||||||
TOWNS_SPELL_RESEARCH,
|
TOWNS_SPELL_RESEARCH,
|
||||||
TOWNS_SPELL_RESEARCH_COST,
|
TOWNS_SPELL_RESEARCH_COST,
|
||||||
TOWNS_SPELL_RESEARCH_PER_DAY,
|
TOWNS_SPELL_RESEARCH_PER_DAY,
|
||||||
TOWNS_SPELL_RESEARCH_COST_EXPONENT_PER_RESEARCH,
|
TOWNS_SPELL_RESEARCH_COST_EXPONENT_PER_RESEARCH,
|
||||||
|
|
||||||
OPTIONS_COUNT,
|
OPTIONS_COUNT
|
||||||
OPTIONS_BEGIN = BONUSES_GLOBAL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE IGameSettings
|
class DLL_LINKAGE IGameSettings
|
||||||
|
|||||||
@@ -190,6 +190,8 @@ class JsonNode;
|
|||||||
BONUS_NAME(MULTIHEX_ANIMATION) /*eg. dragons*/ \
|
BONUS_NAME(MULTIHEX_ANIMATION) /*eg. dragons*/ \
|
||||||
BONUS_NAME(STACK_EXPERIENCE_GAIN_PERCENT) /*modifies all stack experience gains*/\
|
BONUS_NAME(STACK_EXPERIENCE_GAIN_PERCENT) /*modifies all stack experience gains*/\
|
||||||
BONUS_NAME(VULNERABLE_FROM_BACK) /*bonus damage for attacks from behind*/\
|
BONUS_NAME(VULNERABLE_FROM_BACK) /*bonus damage for attacks from behind*/\
|
||||||
|
BONUS_NAME(FULL_MAP_SCOUTING) /*Skyship*/\
|
||||||
|
BONUS_NAME(FULL_MAP_DARKNESS) /*opposite to Skyship*/\
|
||||||
/* end of list */
|
/* end of list */
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,10 +15,10 @@
|
|||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
int IBonusBearer::valOfBonuses(const CSelector &selector, const std::string &cachingStr) const
|
int IBonusBearer::valOfBonuses(const CSelector &selector, const std::string &cachingStr, int baseValue) const
|
||||||
{
|
{
|
||||||
TConstBonusListPtr hlp = getAllBonuses(selector, nullptr, cachingStr);
|
TConstBonusListPtr hlp = getAllBonuses(selector, nullptr, cachingStr);
|
||||||
return hlp->totalValue();
|
return hlp->totalValue(baseValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IBonusBearer::hasBonus(const CSelector &selector, const std::string &cachingStr) const
|
bool IBonusBearer::hasBonus(const CSelector &selector, const std::string &cachingStr) const
|
||||||
@@ -63,14 +63,17 @@ TConstBonusListPtr IBonusBearer::getBonusesOfType(BonusType type, BonusSubtypeID
|
|||||||
return getBonuses(s, cachingStr);
|
return getBonuses(s, cachingStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int IBonusBearer::valOfBonuses(BonusType type) const
|
int IBonusBearer::applyBonuses(BonusType type, int baseValue) const
|
||||||
{
|
{
|
||||||
//This part is performance-critical
|
//This part is performance-critical
|
||||||
std::string cachingStr = "type_" + std::to_string(static_cast<int>(type));
|
std::string cachingStr = "type_" + std::to_string(static_cast<int>(type));
|
||||||
|
|
||||||
CSelector s = Selector::type()(type);
|
CSelector s = Selector::type()(type);
|
||||||
|
return valOfBonuses(s, cachingStr, baseValue);
|
||||||
|
}
|
||||||
|
|
||||||
return valOfBonuses(s, cachingStr);
|
int IBonusBearer::valOfBonuses(BonusType type) const
|
||||||
|
{
|
||||||
|
return applyBonuses(type, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IBonusBearer::hasBonusOfType(BonusType type) const
|
bool IBonusBearer::hasBonusOfType(BonusType type) const
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public:
|
|||||||
IBonusBearer() = default;
|
IBonusBearer() = default;
|
||||||
virtual ~IBonusBearer() = default;
|
virtual ~IBonusBearer() = default;
|
||||||
virtual TConstBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr = {}) const = 0;
|
virtual TConstBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr = {}) const = 0;
|
||||||
int valOfBonuses(const CSelector &selector, const std::string &cachingStr = {}) const;
|
int valOfBonuses(const CSelector &selector, const std::string &cachingStr = {}, int baseValue = 0) const;
|
||||||
bool hasBonus(const CSelector &selector, const std::string &cachingStr = {}) const;
|
bool hasBonus(const CSelector &selector, const std::string &cachingStr = {}) const;
|
||||||
bool hasBonus(const CSelector &selector, const CSelector &limit, const std::string &cachingStr = {}) const;
|
bool hasBonus(const CSelector &selector, const CSelector &limit, const std::string &cachingStr = {}) const;
|
||||||
TConstBonusListPtr getBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr = {}) const;
|
TConstBonusListPtr getBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr = {}) const;
|
||||||
@@ -30,6 +30,7 @@ public:
|
|||||||
std::shared_ptr<const Bonus> getBonus(const CSelector &selector) const; //returns any bonus visible on node that matches (or nullptr if none matches)
|
std::shared_ptr<const Bonus> getBonus(const CSelector &selector) const; //returns any bonus visible on node that matches (or nullptr if none matches)
|
||||||
|
|
||||||
//Optimized interface (with auto-caching)
|
//Optimized interface (with auto-caching)
|
||||||
|
int applyBonuses(BonusType type, int baseValue) const; //subtype -> subtype of bonus;
|
||||||
int valOfBonuses(BonusType type) const; //subtype -> subtype of bonus;
|
int valOfBonuses(BonusType type) const; //subtype -> subtype of bonus;
|
||||||
bool hasBonusOfType(BonusType type) const;//determines if hero has a bonus of given type (and optionally subtype)
|
bool hasBonusOfType(BonusType type) const;//determines if hero has a bonus of given type (and optionally subtype)
|
||||||
int valOfBonuses(BonusType type, BonusSubtypeID subtype) const; //subtype -> subtype of bonus;
|
int valOfBonuses(BonusType type, BonusSubtypeID subtype) const; //subtype -> subtype of bonus;
|
||||||
|
|||||||
@@ -903,7 +903,7 @@ void CGameInfoCallback::getTilesInRange(std::unordered_set<int3> & tiles,
|
|||||||
logGlobal->error("Illegal call to getTilesInRange!");
|
logGlobal->error("Illegal call to getTilesInRange!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(radious == CBuilding::HEIGHT_SKYSHIP) //reveal entire map
|
if(radious == GameConstants::FULL_MAP_RANGE)
|
||||||
getAllTiles (tiles, player, -1, [](auto * tile){return true;});
|
getAllTiles (tiles, player, -1, [](auto * tile){return true;});
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ namespace GameConstants
|
|||||||
constexpr int TOURNAMENT_RULES_DD_MAP_TILES_THRESHOLD = 144*144*2; //map tiles count threshold for 2 dimension door casts with tournament rules
|
constexpr int TOURNAMENT_RULES_DD_MAP_TILES_THRESHOLD = 144*144*2; //map tiles count threshold for 2 dimension door casts with tournament rules
|
||||||
constexpr int KINGDOM_WINDOW_HEROES_SLOTS = 4;
|
constexpr int KINGDOM_WINDOW_HEROES_SLOTS = 4;
|
||||||
constexpr int INFO_WINDOW_ARTIFACTS_MAX_ITEMS = 14;
|
constexpr int INFO_WINDOW_ARTIFACTS_MAX_ITEMS = 14;
|
||||||
|
|
||||||
|
constexpr int FULL_MAP_RANGE = std::numeric_limits<int>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|||||||
@@ -25,14 +25,6 @@ const std::map<std::string, CBuilding::EBuildMode> CBuilding::MODES =
|
|||||||
{ "grail", CBuilding::BUILD_GRAIL }
|
{ "grail", CBuilding::BUILD_GRAIL }
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::map<std::string, CBuilding::ETowerHeight> CBuilding::TOWER_TYPES =
|
|
||||||
{
|
|
||||||
{ "low", CBuilding::HEIGHT_LOW },
|
|
||||||
{ "average", CBuilding::HEIGHT_AVERAGE },
|
|
||||||
{ "high", CBuilding::HEIGHT_HIGH },
|
|
||||||
{ "skyship", CBuilding::HEIGHT_SKYSHIP }
|
|
||||||
};
|
|
||||||
|
|
||||||
BuildingTypeUniqueID CBuilding::getUniqueTypeID() const
|
BuildingTypeUniqueID CBuilding::getUniqueTypeID() const
|
||||||
{
|
{
|
||||||
return BuildingTypeUniqueID(town->faction->getId(), bid);
|
return BuildingTypeUniqueID(town->faction->getId(), bid);
|
||||||
|
|||||||
@@ -60,17 +60,7 @@ public:
|
|||||||
BUILD_GRAIL // 3 - grail - building requires grail to be built
|
BUILD_GRAIL // 3 - grail - building requires grail to be built
|
||||||
} mode;
|
} mode;
|
||||||
|
|
||||||
enum ETowerHeight // for lookup towers and some grails
|
|
||||||
{
|
|
||||||
HEIGHT_NO_TOWER = 5, // building has not 'lookout tower' ability
|
|
||||||
HEIGHT_LOW = 10, // low lookout tower, but castle without lookout tower gives radius 5
|
|
||||||
HEIGHT_AVERAGE = 15,
|
|
||||||
HEIGHT_HIGH = 20, // such tower is in the Tower town
|
|
||||||
HEIGHT_SKYSHIP = std::numeric_limits<int>::max() // grail, open entire map
|
|
||||||
} height;
|
|
||||||
|
|
||||||
static const std::map<std::string, CBuilding::EBuildMode> MODES;
|
static const std::map<std::string, CBuilding::EBuildMode> MODES;
|
||||||
static const std::map<std::string, CBuilding::ETowerHeight> TOWER_TYPES;
|
|
||||||
|
|
||||||
CBuilding() : town(nullptr), mode(BUILD_NORMAL) {};
|
CBuilding() : town(nullptr), mode(BUILD_NORMAL) {};
|
||||||
|
|
||||||
|
|||||||
@@ -283,8 +283,6 @@ void CTownHandler::loadBuilding(CTown * town, const std::string & stringID, cons
|
|||||||
? CBuilding::BUILD_GRAIL
|
? CBuilding::BUILD_GRAIL
|
||||||
: vstd::find_or(CBuilding::MODES, source["mode"].String(), CBuilding::BUILD_NORMAL);
|
: vstd::find_or(CBuilding::MODES, source["mode"].String(), CBuilding::BUILD_NORMAL);
|
||||||
|
|
||||||
ret->height = vstd::find_or(CBuilding::TOWER_TYPES, source["height"].String(), CBuilding::HEIGHT_NO_TOWER);
|
|
||||||
|
|
||||||
ret->identifier = stringID;
|
ret->identifier = stringID;
|
||||||
ret->modScope = source.getModScope();
|
ret->modScope = source.getModScope();
|
||||||
ret->town = town;
|
ret->town = town;
|
||||||
|
|||||||
@@ -220,6 +220,9 @@ static void loadBonusAddInfo(CAddInfo & var, BonusType type, const JsonNode & no
|
|||||||
case BonusType::PRIMARY_SKILL:
|
case BonusType::PRIMARY_SKILL:
|
||||||
case BonusType::ENCHANTER:
|
case BonusType::ENCHANTER:
|
||||||
case BonusType::SPECIAL_PECULIAR_ENCHANT:
|
case BonusType::SPECIAL_PECULIAR_ENCHANT:
|
||||||
|
case BonusType::DARKNESS:
|
||||||
|
case BonusType::FULL_MAP_SCOUTING:
|
||||||
|
case BonusType::FULL_MAP_DARKNESS:
|
||||||
// 1 number
|
// 1 number
|
||||||
var = getFirstValue(value).Integer();
|
var = getFirstValue(value).Integer();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1062,7 +1062,8 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b
|
|||||||
|
|
||||||
int CGHeroInstance::getSightRadius() const
|
int CGHeroInstance::getSightRadius() const
|
||||||
{
|
{
|
||||||
return valOfBonuses(BonusType::SIGHT_RADIUS); // scouting gives SIGHT_RADIUS bonus
|
int baseValue = LIBRARY->engineSettings()->getInteger(EGameSettings::HEROES_BASE_SCOUNTING_RANGE);
|
||||||
|
return applyBonuses(BonusType::SIGHT_RADIUS, baseValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
si32 CGHeroInstance::manaRegain() const
|
si32 CGHeroInstance::manaRegain() const
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "CGTownInstance.h"
|
#include "CGTownInstance.h"
|
||||||
|
|
||||||
|
#include "IGameSettings.h"
|
||||||
#include "TownBuildingInstance.h"
|
#include "TownBuildingInstance.h"
|
||||||
#include "../spells/CSpellHandler.h"
|
#include "../spells/CSpellHandler.h"
|
||||||
#include "../bonuses/Bonus.h"
|
#include "../bonuses/Bonus.h"
|
||||||
@@ -42,17 +43,10 @@
|
|||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
int CGTownInstance::getSightRadius() const //returns sight distance
|
int CGTownInstance::getSightRadius() const
|
||||||
{
|
{
|
||||||
auto ret = CBuilding::HEIGHT_NO_TOWER;
|
int baseValue = LIBRARY->engineSettings()->getInteger(EGameSettings::TOWNS_BASE_SCOUNTING_RANGE);
|
||||||
|
return applyBonuses(BonusType::SIGHT_RADIUS, baseValue);
|
||||||
for(const auto & bid : builtBuildings)
|
|
||||||
{
|
|
||||||
auto height = getTown()->buildings.at(bid)->height;
|
|
||||||
if(ret < height)
|
|
||||||
ret = height;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGTownInstance::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
|
void CGTownInstance::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
|
||||||
|
|||||||
@@ -654,6 +654,19 @@ void CGameHandler::onNewTurn()
|
|||||||
addStatistics(*statistics); // write at end of turn
|
addStatistics(*statistics); // write at end of turn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto & currentDaySelector = [day = gameState().day+1](const Bonus * bonus)
|
||||||
|
{
|
||||||
|
if (bonus->additionalInfo[0] <= 0)
|
||||||
|
return true;
|
||||||
|
if ((day % bonus->additionalInfo[0]) == 0)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto & fullMapScoutingSelector = Selector::type()(BonusType::FULL_MAP_SCOUTING).And(currentDaySelector);
|
||||||
|
const auto & fullMapDarknessSelector = Selector::type()(BonusType::FULL_MAP_DARKNESS).And(currentDaySelector);
|
||||||
|
const auto & darknessSelector = Selector::type()(BonusType::DARKNESS).And(currentDaySelector);
|
||||||
|
|
||||||
for (const auto & townID : gameState().getMap().getAllTowns())
|
for (const auto & townID : gameState().getMap().getAllTowns())
|
||||||
{
|
{
|
||||||
const auto * t = gameState().getTown(townID);
|
const auto * t = gameState().getTown(townID);
|
||||||
@@ -661,25 +674,27 @@ void CGameHandler::onNewTurn()
|
|||||||
|
|
||||||
// Skyship, probably easier to handle same as Veil of darkness
|
// Skyship, probably easier to handle same as Veil of darkness
|
||||||
// do it every new day before veils
|
// do it every new day before veils
|
||||||
if(t->hasBuilt(BuildingID::GRAIL)
|
if(t->hasBonus(fullMapScoutingSelector) && player.isValidPlayer())
|
||||||
&& player.isValidPlayer()
|
changeFogOfWar(t->getSightCenter(), GameConstants::FULL_MAP_RANGE, player, ETileVisibility::REVEALED);
|
||||||
&& t->getTown()->buildings.at(BuildingID::GRAIL)->height == CBuilding::HEIGHT_SKYSHIP)
|
|
||||||
{
|
|
||||||
changeFogOfWar(t->getSightCenter(), t->getSightRadius(), player, ETileVisibility::REVEALED);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto & townID : gameState().getMap().getAllTowns())
|
for (const auto & object : gameState().getMap().getObjects<CArmedInstance>())
|
||||||
{
|
{
|
||||||
const auto * t = gameState().getTown(townID);
|
if(!object->hasBonus(darknessSelector) && !object->hasBonus(fullMapDarknessSelector))
|
||||||
if(t->hasBonusOfType(BonusType::DARKNESS))
|
continue;
|
||||||
|
|
||||||
|
for(const auto & player : gameState().players)
|
||||||
{
|
{
|
||||||
for(const auto & player : gameState().players)
|
if (gameInfo().getPlayerStatus(player.first) != EPlayerStatus::INGAME)
|
||||||
{
|
continue;
|
||||||
if (gameInfo().getPlayerStatus(player.first) == EPlayerStatus::INGAME &&
|
|
||||||
gameInfo().getPlayerRelations(player.first, t->tempOwner) == PlayerRelations::ENEMIES)
|
if (gameInfo().getPlayerRelations(player.first, object->getOwner()) != PlayerRelations::ENEMIES)
|
||||||
changeFogOfWar(t->getSightCenter(), t->valOfBonuses(BonusType::DARKNESS), player.first, ETileVisibility::HIDDEN);
|
continue;
|
||||||
}
|
|
||||||
|
if (object->hasBonus(fullMapDarknessSelector))
|
||||||
|
changeFogOfWar(object->getSightCenter(), GameConstants::FULL_MAP_RANGE, player.first, ETileVisibility::HIDDEN);
|
||||||
|
else
|
||||||
|
changeFogOfWar(object->getSightCenter(), object->valOfBonuses(darknessSelector), player.first, ETileVisibility::HIDDEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4146,7 +4161,6 @@ void CGameHandler::changeFogOfWar(const std::unordered_set<int3> &tiles, PlayerC
|
|||||||
if (mode == ETileVisibility::HIDDEN)
|
if (mode == ETileVisibility::HIDDEN)
|
||||||
{
|
{
|
||||||
// do not hide tiles observed by owned objects. May lead to disastrous AI problems
|
// do not hide tiles observed by owned objects. May lead to disastrous AI problems
|
||||||
// FIXME: this leads to a bug - shroud of darkness from Necropolis does can not override Skyship from Tower
|
|
||||||
std::unordered_set<int3> observedTiles;
|
std::unordered_set<int3> observedTiles;
|
||||||
const auto * p = gameInfo().getPlayerState(player);
|
const auto * p = gameInfo().getPlayerState(player);
|
||||||
for (const auto * obj : p->getOwnedObjects())
|
for (const auto * obj : p->getOwnedObjects())
|
||||||
|
|||||||
Reference in New Issue
Block a user