diff --git a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp index 71f6950d8..c3e3d1043 100644 --- a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp +++ b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp @@ -1061,27 +1061,27 @@ std::vector AINodeStorage::calculateTeleportations( struct TownPortalFinder { const std::vector & initialNodes; - MasteryLevel::Type townPortalSkillLevel; - uint64_t movementNeeded; const ChainActor * actor; const CGHeroInstance * hero; std::vector targetTowns; AINodeStorage * nodeStorage; - - SpellID spellID; const CSpell * townPortal; + uint64_t movementNeeded; + SpellID spellID; + bool townSelectionAllowed; - TownPortalFinder(const ChainActor * actor, const std::vector & initialNodes, std::vector targetTowns, AINodeStorage * nodeStorage, SpellID spellID) - : actor(actor) - , initialNodes(initialNodes) + TownPortalFinder(const ChainActor * actor, const std::vector & initialNodes, const std::vector & targetTowns, AINodeStorage * nodeStorage, SpellID spellID) + : initialNodes(initialNodes) + , actor(actor) , hero(actor->hero) , targetTowns(targetTowns) , nodeStorage(nodeStorage) - , spellID(spellID) , townPortal(spellID.toSpell()) + , spellID(spellID) { auto townPortalEffect = townPortal->getAdventureMechanics().getEffectAs(hero); movementNeeded = townPortalEffect->getMovementPointsRequired(); + townSelectionAllowed = townPortalEffect->townSelectionAllowed(); } bool actorCanCastTownPortal() @@ -1102,7 +1102,7 @@ struct TownPortalFinder continue; } - if(townPortalSkillLevel < MasteryLevel::ADVANCED) + if(!townSelectionAllowed) { const CGTownInstance * nearestTown = *vstd::minElementByFun(targetTowns, [&](const CGTownInstance * t) -> int { diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 32bec952a..d87151d2e 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -1236,7 +1236,7 @@ void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const Bonus adventureInt->onHeroChanged(hero); //recalculate paths because hero has lost or gained bonus influencing pathfinding - if ((bonus.type == BonusType::FLYING_MOVEMENT || bonus.type == BonusType::WATER_WALKING || bonus.type == BonusType::ROUGH_TERRAIN_DISCOUNT || bonus.type == BonusType::NO_TERRAIN_PENALTY)) + if (bonus.type == BonusType::FLYING_MOVEMENT || bonus.type == BonusType::WATER_WALKING || bonus.type == BonusType::ROUGH_TERRAIN_DISCOUNT || bonus.type == BonusType::NO_TERRAIN_PENALTY) localState->verifyPath(hero); } diff --git a/client/gui/CursorHandler.cpp b/client/gui/CursorHandler.cpp index 33c166de8..8856e9f94 100644 --- a/client/gui/CursorHandler.cpp +++ b/client/gui/CursorHandler.cpp @@ -68,8 +68,6 @@ void CursorHandler::init() cursors.push_back(parameters); } - // TODO: Preload? - set(Cursor::Map::POINTER); } diff --git a/docs/modders/Entities_Format/Spell_Format.md b/docs/modders/Entities_Format/Spell_Format.md index 943dbb7ce..74b43269f 100644 --- a/docs/modders/Entities_Format/Spell_Format.md +++ b/docs/modders/Entities_Format/Spell_Format.md @@ -679,6 +679,7 @@ Value of all bonuses can be affected by following bonuses: ## Configurable adventure map effects Currently, VCMI does not allow completely new spell effects for adventure maps. However, it is possible to: + - modify the parameters of all H3 spells. - create spells with similar effects to H3 spells - create a spell that gives bonuses to the hero who cast the spell. @@ -686,9 +687,11 @@ Currently, VCMI does not allow completely new spell effects for adventure maps. Unlike combat effects, adventure map spells can only have one special effect, such as the Dimension Door or Town Portal effect. The number of bonuses granted by an adventure map spell is unlimited. The AI has a limited understanding of adventure map spells and may use the following spells: -- Spells that give WATER_WALKING or FLYING_MOVEMENT bonuses + +- Spells that give `WATER_WALKING` or `FLYING_MOVEMENT` bonuses - Spells with the Summon Boat effect, provided the spell can create new boats with a 100% success chance. - Any spells with the Town Portal effect. + ### Common format All properties in this section can be used for all non-generic adventure map spell effects. @@ -696,7 +699,7 @@ All properties in this section can be used for all non-generic adventure map spe Parameters: - `type` - the type of spell effect used for this spell, or `generic` if a custom mechanic is not used. -- `castsPerDay` - Optional. Defines how many times a hero can cast this spell per day; set to zero or omitted for unlimited use. +- `castsPerDay` - Optional. Defines how many times a hero can cast this spell per day; set to zero or omit for unlimited use. - `castsPerDayXL` - Optional. An alternative cast-per-day limit that is only active on maps that are at least XL+U in size. If this value is not set or is set to zero, the game will use the value of the `castsPerDay` variable. - `bonuses` - A list of bonuses that will be given to the hero when this spell is cast successfully. When used with effects that can fail (e.g. Summon Boat), the bonuses will only apply to a successful cast. @@ -724,9 +727,6 @@ The effect instantly teleports the hero to the selected location. Parameters: -The effect instantly teleports the hero to the selected location. - - - `movementPointsRequired` - The amount of movement points the hero must have to cast this spell. - `movementPointsTaken` - The amount of movement points that will be taken if the spell is cast successfully. If the hero does not have enough movement points, they will be reduced to zero after casting. - `waterLandFailureTakesPoints` - If set to true, mana and movement points will be spent on an attempt to teleport to an inaccessible location (e.g. teleporting to land while in a boat). @@ -757,7 +757,7 @@ Example: ### Remove Object -The effect completely removes the targeted object from the map. The Scuttle Boat spell is an example of this effect. +The effect completely removes the targeted object from the map. The Scuttle Boat spell is an example of this effect. The success chance is defined as [spell effect power](#spell-power). Parameters: @@ -792,8 +792,8 @@ Parameters: - `useExistingBoat` - If this is set to true, the spell can move existing boats to the hero's location. - `createdBoat` - Optional identifier of the boat type that can be created by this spell. If this is not set, the spell cannot create new boats. - Note that if the spell can both create new boats and use existing ones, it would prefer to move existing boats and only create new ones if there are no suitable ones to move. + Example: ```json @@ -842,6 +842,7 @@ Example: ```json "adventureEffect" : { + "type" : "viewWorld", "objects" : { "resource" : true, "mine" : true, diff --git a/lib/callback/CGameInfoCallback.h b/lib/callback/CGameInfoCallback.h index b214cdc8b..6ab6893ad 100644 --- a/lib/callback/CGameInfoCallback.h +++ b/lib/callback/CGameInfoCallback.h @@ -72,7 +72,7 @@ public: //map int3 guardingCreaturePosition (int3 pos) const override; std::vector getGuardingCreatures (int3 pos) const override; - bool isTileGuardedUnchecked(int3 tile) const; + bool isTileGuardedUnchecked(int3 tile) const override; const TerrainTile * getTile(int3 tile, bool verbose = true) const override; const TerrainTile * getTileUnchecked(int3 tile) const override; void getVisibleTilesInRange(std::unordered_set &tiles, int3 pos, int radious, int3::EDistanceFormula distanceFormula = int3::DIST_2D) const; diff --git a/lib/constants/EntityIdentifiers.h b/lib/constants/EntityIdentifiers.h index 6b6d5832e..2294055da 100644 --- a/lib/constants/EntityIdentifiers.h +++ b/lib/constants/EntityIdentifiers.h @@ -856,16 +856,16 @@ public: NONE = -1, // Adventure map spells - SUMMON_BOAT [[deprecated]] = 0, - SCUTTLE_BOAT [[deprecated]] = 1, - VISIONS [[deprecated]] = 2, - VIEW_EARTH [[deprecated]] = 3, - DISGUISE [[deprecated]] = 4, - VIEW_AIR [[deprecated]] = 5, - FLY [[deprecated]] = 6, - WATER_WALK [[deprecated]] = 7, - DIMENSION_DOOR [[deprecated]] = 8, - TOWN_PORTAL [[deprecated]] = 9, + SUMMON_BOAT [[deprecated("check for spell mechanics instead of spell ID")]] = 0, + SCUTTLE_BOAT [[deprecated("check for spell mechanics instead of spell ID")]] = 1, + VISIONS [[deprecated("check for spell mechanics instead of spell ID")]] = 2, + VIEW_EARTH [[deprecated("check for spell mechanics instead of spell ID")]] = 3, + DISGUISE [[deprecated("check for spell mechanics instead of spell ID")]] = 4, + VIEW_AIR [[deprecated("check for spell mechanics instead of spell ID")]] = 5, + FLY [[deprecated("check for spell mechanics instead of spell ID")]] = 6, + WATER_WALK [[deprecated("check for spell mechanics instead of spell ID")]] = 7, + DIMENSION_DOOR [[deprecated("check for spell mechanics instead of spell ID")]] = 8, + TOWN_PORTAL [[deprecated("check for spell mechanics instead of spell ID")]] = 9, // Combat spells QUICKSAND = 10, diff --git a/lib/spells/adventure/AdventureSpellMechanics.cpp b/lib/spells/adventure/AdventureSpellMechanics.cpp index e0aca591a..cb51c356e 100644 --- a/lib/spells/adventure/AdventureSpellMechanics.cpp +++ b/lib/spells/adventure/AdventureSpellMechanics.cpp @@ -28,7 +28,7 @@ VCMI_LIB_NAMESPACE_BEGIN -static std::unique_ptr createAdventureEffect(const CSpell * s, const JsonNode & node) +std::unique_ptr AdventureSpellMechanics::createAdventureEffect(const CSpell * s, const JsonNode & node) { const std::string & typeID = node["type"].String(); diff --git a/lib/spells/adventure/AdventureSpellMechanics.h b/lib/spells/adventure/AdventureSpellMechanics.h index b6ea56515..5508f9f2f 100644 --- a/lib/spells/adventure/AdventureSpellMechanics.h +++ b/lib/spells/adventure/AdventureSpellMechanics.h @@ -30,17 +30,20 @@ class AdventureSpellMechanics final : public IAdventureSpellMechanics, boost::no const LevelOptions & getLevel(const spells::Caster * caster) const; void giveBonuses(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const; + std::unique_ptr createAdventureEffect(const CSpell * s, const JsonNode & node); public: AdventureSpellMechanics(const CSpell * s); ~AdventureSpellMechanics(); + void performCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const; + +private: bool canBeCast(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const final; bool canBeCastAt(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const final; bool adventureCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const final; const IAdventureSpellEffect * getEffect(const spells::Caster * caster) const final; bool givesBonus(const spells::Caster * caster, BonusType which) const final; - void performCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const; }; VCMI_LIB_NAMESPACE_END diff --git a/lib/spells/adventure/DimensionDoorEffect.h b/lib/spells/adventure/DimensionDoorEffect.h index c82870401..16f2111ad 100644 --- a/lib/spells/adventure/DimensionDoorEffect.h +++ b/lib/spells/adventure/DimensionDoorEffect.h @@ -26,10 +26,9 @@ class DimensionDoorEffect final : public AdventureSpellRangedEffect public: DimensionDoorEffect(const CSpell * s, const JsonNode & config); -protected: +private: bool canBeCastImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const final; bool canBeCastAtImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const final; - ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const final; void endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const final; std::string getCursorForTarget(const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const final; diff --git a/lib/spells/adventure/RemoveObjectEffect.h b/lib/spells/adventure/RemoveObjectEffect.h index bb355789f..4141d166b 100644 --- a/lib/spells/adventure/RemoveObjectEffect.h +++ b/lib/spells/adventure/RemoveObjectEffect.h @@ -24,6 +24,7 @@ class RemoveObjectEffect final : public AdventureSpellRangedEffect public: RemoveObjectEffect(const CSpell * s, const JsonNode & config); +private: bool canBeCastAtImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const final; ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const final; std::string getCursorForTarget(const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const final; diff --git a/lib/spells/adventure/SummonBoatEffect.h b/lib/spells/adventure/SummonBoatEffect.h index 00651c639..7dd1307ad 100644 --- a/lib/spells/adventure/SummonBoatEffect.h +++ b/lib/spells/adventure/SummonBoatEffect.h @@ -26,9 +26,8 @@ public: bool canCreateNewBoat() const; int getSuccessChance(const spells::Caster * caster) const; -protected: +private: bool canBeCastImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const final; - ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const final; }; diff --git a/lib/spells/adventure/TownPortalEffect.h b/lib/spells/adventure/TownPortalEffect.h index ec6c3b7ec..5011b26f0 100644 --- a/lib/spells/adventure/TownPortalEffect.h +++ b/lib/spells/adventure/TownPortalEffect.h @@ -16,7 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN class CGTownInstance; -class TownPortalEffect final : public IAdventureSpellEffect +class DLL_LINKAGE TownPortalEffect final : public IAdventureSpellEffect { const CSpell * owner; int movementPointsRequired; @@ -27,15 +27,13 @@ class TownPortalEffect final : public IAdventureSpellEffect public: TownPortalEffect(const CSpell * s, const JsonNode & config); - bool getMovementPointsRequired() const { return movementPointsRequired; } + int getMovementPointsRequired() const { return movementPointsRequired; } bool townSelectionAllowed() const { return allowTownSelection; } -protected: +private: ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override; ESpellCastResult beginCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters, const AdventureSpellMechanics & mechanics) const override; void endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override; - -private: const CGTownInstance * findNearestTown(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters, const std::vector & pool) const; std::vector getPossibleTowns(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const; };