mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-22 22:13:35 +02:00
Merge remote-tracking branch 'vcmi/develop' into lobby
This commit is contained in:
commit
322c5faf63
14
.github/workflows/github.yml
vendored
14
.github/workflows/github.yml
vendored
@ -268,18 +268,26 @@ jobs:
|
||||
run: |
|
||||
ctest --preset ${{matrix.preset}}
|
||||
|
||||
- name: Kill XProtect to work around CPack issue on macOS
|
||||
if: ${{ startsWith(matrix.platform, 'mac') }}
|
||||
run: |
|
||||
# Cf. https://github.com/actions/runner-images/issues/7522#issuecomment-1556766641
|
||||
echo Killing...; sudo pkill -9 XProtect >/dev/null || true;
|
||||
echo "Waiting..."; counter=0; while pgrep XProtect && ((counter < 20)); do sleep 3; ((counter++)); done
|
||||
pgrep XProtect || true
|
||||
|
||||
- name: Pack
|
||||
id: cpack
|
||||
if: ${{ matrix.pack == 1 }}
|
||||
run: |
|
||||
cd '${{github.workspace}}/out/build/${{matrix.preset}}'
|
||||
CPACK_PATH=`which -a cpack | grep -m1 -v -i chocolatey`
|
||||
"$CPACK_PATH" -C ${{matrix.pack_type}} ${{ matrix.cpack_args }}
|
||||
counter=0; until "$CPACK_PATH" -C ${{matrix.pack_type}} ${{ matrix.cpack_args }} || ((counter > 20)); do sleep 3; ((counter++)); done
|
||||
test -f '${{github.workspace}}/CI/${{matrix.platform}}/post_pack.sh' \
|
||||
&& '${{github.workspace}}/CI/${{matrix.platform}}/post_pack.sh' '${{github.workspace}}' "$(ls '${{ env.VCMI_PACKAGE_FILE_NAME }}'.*)"
|
||||
rm -rf _CPack_Packages
|
||||
|
||||
- name: Create android package
|
||||
- name: Create Android package
|
||||
if: ${{ startsWith(matrix.platform, 'android') }}
|
||||
run: |
|
||||
cd android
|
||||
@ -414,7 +422,7 @@ jobs:
|
||||
name: Android JNI android-64
|
||||
path: ${{ github.workspace }}/android/vcmi-app/src/main/jniLibs/
|
||||
|
||||
- name: Create android package
|
||||
- name: Create Android package
|
||||
run: |
|
||||
cd android
|
||||
./gradlew bundleRelease --info
|
||||
|
@ -14,11 +14,11 @@
|
||||
#include "../../lib/CStack.h"
|
||||
#include "../../lib/battle/BattleAction.h"
|
||||
|
||||
void CEmptyAI::saveGame(BinarySerializer & h, const int version)
|
||||
void CEmptyAI::saveGame(BinarySerializer & h)
|
||||
{
|
||||
}
|
||||
|
||||
void CEmptyAI::loadGame(BinaryDeserializer & h, const int version)
|
||||
void CEmptyAI::loadGame(BinaryDeserializer & h)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,8 @@ class CEmptyAI : public CGlobalAI
|
||||
std::shared_ptr<CCallback> cb;
|
||||
|
||||
public:
|
||||
virtual void saveGame(BinarySerializer & h, const int version) override;
|
||||
virtual void loadGame(BinaryDeserializer & h, const int version) override;
|
||||
virtual void saveGame(BinarySerializer & h) override;
|
||||
virtual void loadGame(BinaryDeserializer & h) override;
|
||||
|
||||
void initGameInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB) override;
|
||||
void yourTurn(QueryID queryID) override;
|
||||
|
@ -586,11 +586,18 @@ void AIGateway::heroGotLevel(const CGHeroInstance * hero, PrimarySkill pskill, s
|
||||
|
||||
requestActionASAP([=]()
|
||||
{
|
||||
int sel = 0;
|
||||
|
||||
if(hPtr.validAndSet())
|
||||
{
|
||||
std::unique_lock<std::mutex> lockGuard(nullkiller->aiStateMutex);
|
||||
|
||||
nullkiller->heroManager->update();
|
||||
answerQuery(queryID, nullkiller->heroManager->selectBestSkill(hPtr, skills));
|
||||
|
||||
sel = nullkiller->heroManager->selectBestSkill(hPtr, skills);
|
||||
}
|
||||
|
||||
answerQuery(queryID, sel);
|
||||
});
|
||||
}
|
||||
|
||||
@ -661,14 +668,18 @@ void AIGateway::showBlockingDialog(const std::string & text, const std::vector<C
|
||||
if(selection) //select from multiple components -> take the last one (they're indexed [1-size])
|
||||
sel = components.size();
|
||||
|
||||
// TODO: Find better way to understand it is Chest of Treasures
|
||||
if(hero.validAndSet()
|
||||
&& components.size() == 2
|
||||
&& components.front().type == ComponentType::RESOURCE
|
||||
&& (nullkiller->heroManager->getHeroRole(hero) != HeroRole::MAIN
|
||||
|| nullkiller->buildAnalyzer->getGoldPreasure() > MAX_GOLD_PEASURE))
|
||||
{
|
||||
sel = 1; // for now lets pick gold from a chest.
|
||||
std::unique_lock<std::mutex> mxLock(nullkiller->aiStateMutex);
|
||||
|
||||
// TODO: Find better way to understand it is Chest of Treasures
|
||||
if(hero.validAndSet()
|
||||
&& components.size() == 2
|
||||
&& components.front().type == ComponentType::RESOURCE
|
||||
&& (nullkiller->heroManager->getHeroRole(hero) != HeroRole::MAIN
|
||||
|| nullkiller->buildAnalyzer->getGoldPreasure() > MAX_GOLD_PEASURE))
|
||||
{
|
||||
sel = 1; // for now lets pick gold from a chest.
|
||||
}
|
||||
}
|
||||
|
||||
answerQuery(askID, sel);
|
||||
@ -747,27 +758,25 @@ void AIGateway::showMapObjectSelectDialog(QueryID askID, const Component & icon,
|
||||
requestActionASAP([=](){ answerQuery(askID, selectedObject.getNum()); });
|
||||
}
|
||||
|
||||
void AIGateway::saveGame(BinarySerializer & h, const int version)
|
||||
void AIGateway::saveGame(BinarySerializer & h)
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "version '%i'", version);
|
||||
NET_EVENT_HANDLER;
|
||||
nullkiller->memory->removeInvisibleObjects(myCb.get());
|
||||
|
||||
CAdventureAI::saveGame(h, version);
|
||||
serializeInternal(h, version);
|
||||
CAdventureAI::saveGame(h);
|
||||
serializeInternal(h);
|
||||
}
|
||||
|
||||
void AIGateway::loadGame(BinaryDeserializer & h, const int version)
|
||||
void AIGateway::loadGame(BinaryDeserializer & h)
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "version '%i'", version);
|
||||
//NET_EVENT_HANDLER;
|
||||
|
||||
#if 0
|
||||
//disabled due to issue 2890
|
||||
registerGoals(h);
|
||||
#endif // 0
|
||||
CAdventureAI::loadGame(h, version);
|
||||
serializeInternal(h, version);
|
||||
CAdventureAI::loadGame(h);
|
||||
serializeInternal(h);
|
||||
}
|
||||
|
||||
bool AIGateway::makePossibleUpgrades(const CArmedInstance * obj)
|
||||
@ -859,6 +868,8 @@ void AIGateway::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h
|
||||
{
|
||||
makePossibleUpgrades(h.get());
|
||||
|
||||
std::unique_lock<std::mutex> lockGuard(nullkiller->aiStateMutex);
|
||||
|
||||
if(!h->visitedTown->garrisonHero || !nullkiller->isHeroLocked(h->visitedTown->garrisonHero))
|
||||
moveCreaturesToHero(h->visitedTown);
|
||||
|
||||
|
@ -62,7 +62,7 @@ public:
|
||||
void heroVisit(const CGObjectInstance * obj, bool started);
|
||||
|
||||
|
||||
template<typename Handler> void serialize(Handler & h, const int version)
|
||||
template<typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & battle;
|
||||
h & remainingQueries;
|
||||
@ -119,8 +119,8 @@ public:
|
||||
void showGarrisonDialog(const CArmedInstance * up, const CGHeroInstance * down, bool removableUnits, QueryID queryID) override; //all stacks operations between these objects become allowed, interface has to call onEnd when done
|
||||
void showTeleportDialog(const CGHeroInstance * hero, TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
|
||||
void showMapObjectSelectDialog(QueryID askID, const Component & icon, const MetaString & title, const MetaString & description, const std::vector<ObjectInstanceID> & objects) override;
|
||||
void saveGame(BinarySerializer & h, const int version) override; //saving
|
||||
void loadGame(BinaryDeserializer & h, const int version) override; //loading
|
||||
void saveGame(BinarySerializer & h) override; //saving
|
||||
void loadGame(BinaryDeserializer & h) override; //loading
|
||||
void finish() override;
|
||||
|
||||
void availableCreaturesChanged(const CGDwelling * town) override;
|
||||
@ -203,7 +203,7 @@ public:
|
||||
//special function that can be called ONLY from game events handling thread and will send request ASAP
|
||||
void requestActionASAP(std::function<void()> whatToDo);
|
||||
|
||||
template<typename Handler> void serializeInternal(Handler & h, const int version)
|
||||
template<typename Handler> void serializeInternal(Handler & h)
|
||||
{
|
||||
h & nullkiller->memory->knownTeleportChannels;
|
||||
h & nullkiller->memory->knownSubterraneanGates;
|
||||
|
@ -115,7 +115,7 @@ public:
|
||||
bool validAndSet() const;
|
||||
|
||||
|
||||
template<typename Handler> void serialize(Handler & h, const int version)
|
||||
template<typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & this->h;
|
||||
h & hid;
|
||||
@ -147,7 +147,7 @@ struct ObjectIdRef
|
||||
bool operator<(const ObjectIdRef & rhs) const;
|
||||
|
||||
|
||||
template<typename Handler> void serialize(Handler & h, const int version)
|
||||
template<typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & id;
|
||||
}
|
||||
|
@ -115,6 +115,8 @@ Goals::TTask Nullkiller::choseBestTask(Goals::TSubgoal behavior, int decompositi
|
||||
|
||||
void Nullkiller::resetAiState()
|
||||
{
|
||||
std::unique_lock<std::mutex> lockGuard(aiStateMutex);
|
||||
|
||||
lockedResources = TResources();
|
||||
scanDepth = ScanDepth::MAIN_FULL;
|
||||
playerID = ai->playerID;
|
||||
@ -127,6 +129,8 @@ void Nullkiller::updateAiState(int pass, bool fast)
|
||||
{
|
||||
boost::this_thread::interruption_point();
|
||||
|
||||
std::unique_lock<std::mutex> lockGuard(aiStateMutex);
|
||||
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
activeHero = nullptr;
|
||||
|
@ -73,6 +73,7 @@ public:
|
||||
std::unique_ptr<ArmyFormation> armyFormation;
|
||||
PlayerColor playerID;
|
||||
std::shared_ptr<CCallback> cb;
|
||||
std::mutex aiStateMutex;
|
||||
|
||||
Nullkiller();
|
||||
void init(std::shared_ptr<CCallback> cb, PlayerColor playerID);
|
||||
|
@ -137,6 +137,18 @@ TResources getCreatureBankResources(const CGObjectInstance * target, const CGHer
|
||||
return sum > 1 ? result / sum : result;
|
||||
}
|
||||
|
||||
uint64_t getResourcesGoldReward(const TResources & res)
|
||||
{
|
||||
int nonGoldResources = res[EGameResID::GEMS]
|
||||
+ res[EGameResID::SULFUR]
|
||||
+ res[EGameResID::WOOD]
|
||||
+ res[EGameResID::ORE]
|
||||
+ res[EGameResID::CRYSTAL]
|
||||
+ res[EGameResID::MERCURY];
|
||||
|
||||
return res[EGameResID::GOLD] + 100 * nonGoldResources;
|
||||
}
|
||||
|
||||
uint64_t getCreatureBankArmyReward(const CGObjectInstance * target, const CGHeroInstance * hero)
|
||||
{
|
||||
auto objectInfo = target->getObjectHandler()->getObjectInfo(target->appearance);
|
||||
@ -491,7 +503,7 @@ float RewardEvaluator::getStrategicalValue(const CGObjectInstance * target) cons
|
||||
//Evaluate resources used for construction. Gold is evaluated separately.
|
||||
if (it->resType != EGameResID::GOLD)
|
||||
{
|
||||
sum += 0.1f * getResourceRequirementStrength(it->resType);
|
||||
sum += 0.1f * it->resVal * getResourceRequirementStrength(it->resType);
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
@ -529,6 +541,9 @@ float RewardEvaluator::getStrategicalValue(const CGObjectInstance * target) cons
|
||||
? getEnemyHeroStrategicalValue(dynamic_cast<const CGHeroInstance *>(target))
|
||||
: 0;
|
||||
|
||||
case Obj::KEYMASTER:
|
||||
return 0.6f;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -588,6 +603,8 @@ float RewardEvaluator::getSkillReward(const CGObjectInstance * target, const CGH
|
||||
case Obj::PANDORAS_BOX:
|
||||
//Can contains experience, spells, or skills (only on custom maps)
|
||||
return 2.5f;
|
||||
case Obj::PYRAMID:
|
||||
return 3.0f;
|
||||
case Obj::HERO:
|
||||
return ai->cb->getPlayerRelations(target->tempOwner, ai->playerID) == PlayerRelations::ENEMIES
|
||||
? enemyHeroEliminationSkillRewardRatio * dynamic_cast<const CGHeroInstance *>(target)->level
|
||||
@ -660,7 +677,7 @@ int32_t RewardEvaluator::getGoldReward(const CGObjectInstance * target, const CG
|
||||
case Obj::WAGON:
|
||||
return 100;
|
||||
case Obj::CREATURE_BANK:
|
||||
return getCreatureBankResources(target, hero)[EGameResID::GOLD];
|
||||
return getResourcesGoldReward(getCreatureBankResources(target, hero));
|
||||
case Obj::CRYPT:
|
||||
case Obj::DERELICT_SHIP:
|
||||
return 3000;
|
||||
|
@ -37,7 +37,7 @@ namespace Goals
|
||||
{
|
||||
return new T(static_cast<T const &>(*this)); //casting enforces template instantiation
|
||||
}
|
||||
template<typename Handler> void serialize(Handler & h, const int version)
|
||||
template<typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & static_cast<AbstractGoal &>(*this);
|
||||
//h & goalType & isElementar & isAbstract & priority;
|
||||
|
@ -35,6 +35,8 @@ const uint64_t MIN_ARMY_STRENGTH_FOR_CHAIN = 5000;
|
||||
const uint64_t MIN_ARMY_STRENGTH_FOR_NEXT_ACTOR = 1000;
|
||||
const uint64_t CHAIN_MAX_DEPTH = 4;
|
||||
|
||||
const bool DO_NOT_SAVE_TO_COMMITED_TILES = false;
|
||||
|
||||
AISharedStorage::AISharedStorage(int3 sizes)
|
||||
{
|
||||
if(!shared){
|
||||
@ -234,6 +236,7 @@ void AINodeStorage::resetTile(const int3 & coord, EPathfindingLayer layer, EPath
|
||||
heroNode.specialAction.reset();
|
||||
heroNode.armyLoss = 0;
|
||||
heroNode.chainOther = nullptr;
|
||||
heroNode.dayFlags = DayFlags::NONE;
|
||||
heroNode.update(coord, layer, accessibility);
|
||||
}
|
||||
}
|
||||
@ -265,7 +268,8 @@ void AINodeStorage::commit(
|
||||
EPathNodeAction action,
|
||||
int turn,
|
||||
int movementLeft,
|
||||
float cost) const
|
||||
float cost,
|
||||
bool saveToCommited) const
|
||||
{
|
||||
destination->action = action;
|
||||
destination->setCost(cost);
|
||||
@ -291,10 +295,15 @@ void AINodeStorage::commit(
|
||||
destination->actor->armyValue);
|
||||
#endif
|
||||
|
||||
if(destination->turns <= heroChainTurn)
|
||||
if(saveToCommited && destination->turns <= heroChainTurn)
|
||||
{
|
||||
commitedTiles.insert(destination->coord);
|
||||
}
|
||||
|
||||
if(destination->turns == source->turns)
|
||||
{
|
||||
destination->dayFlags = source->dayFlags;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<CGPathNode *> AINodeStorage::calculateNeighbours(
|
||||
@ -778,7 +787,14 @@ void HeroChainCalculationTask::addHeroChain(const std::vector<ExchangeCandidate>
|
||||
continue;
|
||||
}
|
||||
|
||||
storage.commit(exchangeNode, carrier, carrier->action, chainInfo.turns, chainInfo.moveRemains, chainInfo.getCost());
|
||||
storage.commit(
|
||||
exchangeNode,
|
||||
carrier,
|
||||
carrier->action,
|
||||
chainInfo.turns,
|
||||
chainInfo.moveRemains,
|
||||
chainInfo.getCost(),
|
||||
DO_NOT_SAVE_TO_COMMITED_TILES);
|
||||
|
||||
if(carrier->specialAction || carrier->chainOther)
|
||||
{
|
||||
@ -1070,7 +1086,8 @@ struct TowmPortalFinder
|
||||
EPathNodeAction::TELEPORT_NORMAL,
|
||||
bestNode->turns,
|
||||
bestNode->moveRemains - movementNeeded,
|
||||
movementCost);
|
||||
movementCost,
|
||||
DO_NOT_SAVE_TO_COMMITED_TILES);
|
||||
|
||||
node->theNodeBefore = bestNode;
|
||||
node->addSpecialAction(std::make_shared<AIPathfinding::TownPortalAction>(targetTown));
|
||||
|
@ -41,11 +41,19 @@ namespace AIPathfinding
|
||||
const int CHAIN_MAX_DEPTH = 4;
|
||||
}
|
||||
|
||||
enum DayFlags : ui8
|
||||
{
|
||||
NONE = 0,
|
||||
FLY_CAST = 1,
|
||||
WATER_WALK_CAST = 2
|
||||
};
|
||||
|
||||
struct AIPathNode : public CGPathNode
|
||||
{
|
||||
uint64_t danger;
|
||||
uint64_t armyLoss;
|
||||
int32_t manaCost;
|
||||
int16_t manaCost;
|
||||
DayFlags dayFlags;
|
||||
const AIPathNode * chainOther;
|
||||
std::shared_ptr<const SpecialAction> specialAction;
|
||||
const ChainActor * actor;
|
||||
@ -200,7 +208,8 @@ public:
|
||||
EPathNodeAction action,
|
||||
int turn,
|
||||
int movementLeft,
|
||||
float cost) const;
|
||||
float cost,
|
||||
bool saveToCommited = true) const;
|
||||
|
||||
inline const AIPathNode * getAINode(const CGPathNode * node) const
|
||||
{
|
||||
|
@ -22,18 +22,18 @@ namespace NKAI
|
||||
|
||||
namespace AIPathfinding
|
||||
{
|
||||
AdventureCastAction::AdventureCastAction(SpellID spellToCast, const CGHeroInstance * hero)
|
||||
:spellToCast(spellToCast), hero(hero)
|
||||
AdventureCastAction::AdventureCastAction(SpellID spellToCast, const CGHeroInstance * hero, DayFlags flagsToAdd)
|
||||
:spellToCast(spellToCast), hero(hero), flagsToAdd(flagsToAdd)
|
||||
{
|
||||
manaCost = hero->getSpellCost(spellToCast.toSpell());
|
||||
}
|
||||
|
||||
WaterWalkingAction::WaterWalkingAction(const CGHeroInstance * hero)
|
||||
:AdventureCastAction(SpellID::WATER_WALK, hero)
|
||||
:AdventureCastAction(SpellID::WATER_WALK, hero, DayFlags::WATER_WALK_CAST)
|
||||
{ }
|
||||
|
||||
AirWalkingAction::AirWalkingAction(const CGHeroInstance * hero)
|
||||
: AdventureCastAction(SpellID::FLY, hero)
|
||||
: AdventureCastAction(SpellID::FLY, hero, DayFlags::FLY_CAST)
|
||||
{
|
||||
}
|
||||
|
||||
@ -41,11 +41,12 @@ namespace AIPathfinding
|
||||
const CGHeroInstance * hero,
|
||||
CDestinationNodeInfo & destination,
|
||||
const PathNodeInfo & source,
|
||||
AIPathNode * dstMode,
|
||||
AIPathNode * dstNode,
|
||||
const AIPathNode * srcNode) const
|
||||
{
|
||||
dstMode->manaCost = srcNode->manaCost + manaCost;
|
||||
dstMode->theNodeBefore = source.node;
|
||||
dstNode->manaCost = srcNode->manaCost + manaCost;
|
||||
dstNode->theNodeBefore = source.node;
|
||||
dstNode->dayFlags = static_cast<DayFlags>(dstNode->dayFlags | flagsToAdd);
|
||||
}
|
||||
|
||||
void AdventureCastAction::execute(const CGHeroInstance * hero) const
|
||||
|
@ -24,9 +24,10 @@ namespace AIPathfinding
|
||||
SpellID spellToCast;
|
||||
const CGHeroInstance * hero;
|
||||
int manaCost;
|
||||
DayFlags flagsToAdd;
|
||||
|
||||
public:
|
||||
AdventureCastAction(SpellID spellToCast, const CGHeroInstance * hero);
|
||||
AdventureCastAction(SpellID spellToCast, const CGHeroInstance * hero, DayFlags flagsToAdd = DayFlags::NONE);
|
||||
|
||||
virtual void execute(const CGHeroInstance * hero) const override;
|
||||
|
||||
|
@ -61,6 +61,12 @@ namespace AIPathfinding
|
||||
|
||||
if(source.node->layer == EPathfindingLayer::LAND && destination.node->layer == EPathfindingLayer::WATER)
|
||||
{
|
||||
if(nodeStorage->getAINode(source.node)->dayFlags & DayFlags::WATER_WALK_CAST)
|
||||
{
|
||||
destination.blocked = false;
|
||||
return;
|
||||
}
|
||||
|
||||
auto action = waterWalkingActions.find(nodeStorage->getHero(source.node));
|
||||
|
||||
if(action != waterWalkingActions.end() && tryUseSpecialAction(destination, source, action->second, EPathNodeAction::NORMAL))
|
||||
@ -73,6 +79,12 @@ namespace AIPathfinding
|
||||
|
||||
if(source.node->layer == EPathfindingLayer::LAND && destination.node->layer == EPathfindingLayer::AIR)
|
||||
{
|
||||
if(nodeStorage->getAINode(source.node)->dayFlags & DayFlags::FLY_CAST)
|
||||
{
|
||||
destination.blocked = false;
|
||||
return;
|
||||
}
|
||||
|
||||
auto action = airWalkingActions.find(nodeStorage->getHero(source.node));
|
||||
|
||||
if(action != airWalkingActions.end() && tryUseSpecialAction(destination, source, action->second, EPathNodeAction::NORMAL))
|
||||
|
@ -16,8 +16,6 @@
|
||||
#include "../../lib/battle/BattleAction.h"
|
||||
#include "../../lib/battle/BattleInfo.h"
|
||||
|
||||
static std::shared_ptr<CBattleCallback> cbc;
|
||||
|
||||
CStupidAI::CStupidAI()
|
||||
: side(-1)
|
||||
, wasWaitingForRealize(false)
|
||||
@ -41,7 +39,7 @@ void CStupidAI::initBattleInterface(std::shared_ptr<Environment> ENV, std::share
|
||||
{
|
||||
print("init called, saving ptr to IBattleCallback");
|
||||
env = ENV;
|
||||
cbc = cb = CB;
|
||||
cb = CB;
|
||||
|
||||
wasWaitingForRealize = CB->waitTillRealize;
|
||||
wasUnlockingGs = CB->unlockGsWhenWaiting;
|
||||
@ -73,11 +71,11 @@ public:
|
||||
std::vector<BattleHex> attackFrom; //for melee fight
|
||||
EnemyInfo(const CStack * _s) : s(_s), adi(0), adr(0)
|
||||
{}
|
||||
void calcDmg(const BattleID & battleID, const CStack * ourStack)
|
||||
void calcDmg(std::shared_ptr<CBattleCallback> cb, const BattleID & battleID, const CStack * ourStack)
|
||||
{
|
||||
// FIXME: provide distance info for Jousting bonus
|
||||
DamageEstimation retal;
|
||||
DamageEstimation dmg = cbc->getBattle(battleID)->battleEstimateDamage(ourStack, s, 0, &retal);
|
||||
DamageEstimation dmg = cb->getBattle(battleID)->battleEstimateDamage(ourStack, s, 0, &retal);
|
||||
adi = static_cast<int>((dmg.damage.min + dmg.damage.max) / 2);
|
||||
adr = static_cast<int>((retal.damage.min + retal.damage.max) / 2);
|
||||
}
|
||||
@ -93,14 +91,14 @@ bool isMoreProfitable(const EnemyInfo &ei1, const EnemyInfo& ei2)
|
||||
return (ei1.adi-ei1.adr) < (ei2.adi - ei2.adr);
|
||||
}
|
||||
|
||||
static bool willSecondHexBlockMoreEnemyShooters(const BattleID & battleID, const BattleHex &h1, const BattleHex &h2)
|
||||
static bool willSecondHexBlockMoreEnemyShooters(std::shared_ptr<CBattleCallback> cb, const BattleID & battleID, const BattleHex &h1, const BattleHex &h2)
|
||||
{
|
||||
int shooters[2] = {0}; //count of shooters on hexes
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
for (auto & neighbour : (i ? h2 : h1).neighbouringTiles())
|
||||
if(const auto * s = cbc->getBattle(battleID)->battleGetUnitByPos(neighbour))
|
||||
if(const auto * s = cb->getBattle(battleID)->battleGetUnitByPos(neighbour))
|
||||
if(s->isShooter())
|
||||
shooters[i]++;
|
||||
}
|
||||
@ -172,10 +170,10 @@ void CStupidAI::activeStack(const BattleID & battleID, const CStack * stack)
|
||||
}
|
||||
|
||||
for ( auto & enemy : enemiesReachable )
|
||||
enemy.calcDmg(battleID, stack);
|
||||
enemy.calcDmg(cb, battleID, stack);
|
||||
|
||||
for ( auto & enemy : enemiesShootable )
|
||||
enemy.calcDmg(battleID, stack);
|
||||
enemy.calcDmg(cb, battleID, stack);
|
||||
|
||||
if(enemiesShootable.size())
|
||||
{
|
||||
@ -186,7 +184,7 @@ void CStupidAI::activeStack(const BattleID & battleID, const CStack * stack)
|
||||
else if(enemiesReachable.size())
|
||||
{
|
||||
const EnemyInfo &ei= *std::max_element(enemiesReachable.begin(), enemiesReachable.end(), &isMoreProfitable);
|
||||
BattleHex targetHex = *std::max_element(ei.attackFrom.begin(), ei.attackFrom.end(), [&](auto a, auto b) { return willSecondHexBlockMoreEnemyShooters(battleID, a, b);});
|
||||
BattleHex targetHex = *std::max_element(ei.attackFrom.begin(), ei.attackFrom.end(), [&](auto a, auto b) { return willSecondHexBlockMoreEnemyShooters(cb, battleID, a, b);});
|
||||
|
||||
cb->battleMakeUnitAction(battleID, BattleAction::makeMeleeAttack(stack, ei.s->getPosition(), targetHex));
|
||||
return;
|
||||
|
@ -70,7 +70,7 @@ public:
|
||||
bool validAndSet() const;
|
||||
|
||||
|
||||
template<typename Handler> void serialize(Handler & h, const int version)
|
||||
template<typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & this->h;
|
||||
h & hid;
|
||||
@ -102,7 +102,7 @@ struct ObjectIdRef
|
||||
bool operator<(const ObjectIdRef & rhs) const;
|
||||
|
||||
|
||||
template<typename Handler> void serialize(Handler & h, const int version)
|
||||
template<typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & id;
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ namespace Goals
|
||||
return !(*this == g);
|
||||
}
|
||||
|
||||
template<typename Handler> void serialize(Handler & h, const int version)
|
||||
template<typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & goalType;
|
||||
h & isElementar;
|
||||
|
@ -69,7 +69,7 @@ namespace Goals
|
||||
|
||||
return ptr;
|
||||
}
|
||||
template<typename Handler> void serialize(Handler & h, const int version)
|
||||
template<typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & static_cast<AbstractGoal &>(*this);
|
||||
//h & goalType & isElementar & isAbstract & priority;
|
||||
|
@ -28,7 +28,7 @@ struct DLL_EXPORT ResourceObjective
|
||||
Goals::TSubgoal goal; //what for (build, gather army etc...)
|
||||
|
||||
//TODO: register?
|
||||
template<typename Handler> void serializeInternal(Handler & h, const int version)
|
||||
template<typename Handler> void serializeInternal(Handler & h)
|
||||
{
|
||||
h & resources;
|
||||
//h & goal; //FIXME: goal serialization is broken
|
||||
@ -105,7 +105,7 @@ private:
|
||||
void dumpToLog() const;
|
||||
|
||||
//TODO: register?
|
||||
template<typename Handler> void serializeInternal(Handler & h, const int version)
|
||||
template<typename Handler> void serializeInternal(Handler & h)
|
||||
{
|
||||
h & saving;
|
||||
h & queue;
|
||||
|
@ -746,9 +746,8 @@ void VCAI::showMapObjectSelectDialog(QueryID askID, const Component & icon, cons
|
||||
requestActionASAP([=](){ answerQuery(askID, selectedObject.getNum()); });
|
||||
}
|
||||
|
||||
void VCAI::saveGame(BinarySerializer & h, const int version)
|
||||
void VCAI::saveGame(BinarySerializer & h)
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "version '%i'", version);
|
||||
NET_EVENT_HANDLER;
|
||||
validateVisitableObjs();
|
||||
|
||||
@ -756,21 +755,20 @@ void VCAI::saveGame(BinarySerializer & h, const int version)
|
||||
//disabled due to issue 2890
|
||||
registerGoals(h);
|
||||
#endif // 0
|
||||
CAdventureAI::saveGame(h, version);
|
||||
serializeInternal(h, version);
|
||||
CAdventureAI::saveGame(h);
|
||||
serializeInternal(h);
|
||||
}
|
||||
|
||||
void VCAI::loadGame(BinaryDeserializer & h, const int version)
|
||||
void VCAI::loadGame(BinaryDeserializer & h)
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "version '%i'", version);
|
||||
//NET_EVENT_HANDLER;
|
||||
|
||||
#if 0
|
||||
//disabled due to issue 2890
|
||||
registerGoals(h);
|
||||
#endif // 0
|
||||
CAdventureAI::loadGame(h, version);
|
||||
serializeInternal(h, version);
|
||||
CAdventureAI::loadGame(h);
|
||||
serializeInternal(h);
|
||||
}
|
||||
|
||||
void makePossibleUpgrades(const CArmedInstance * obj)
|
||||
|
@ -68,7 +68,7 @@ public:
|
||||
void heroVisit(const CGObjectInstance * obj, bool started);
|
||||
|
||||
|
||||
template<typename Handler> void serialize(Handler & h, const int version)
|
||||
template<typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & battle;
|
||||
h & remainingQueries;
|
||||
@ -152,8 +152,8 @@ public:
|
||||
void showGarrisonDialog(const CArmedInstance * up, const CGHeroInstance * down, bool removableUnits, QueryID queryID) override; //all stacks operations between these objects become allowed, interface has to call onEnd when done
|
||||
void showTeleportDialog(const CGHeroInstance * hero, TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
|
||||
void showMapObjectSelectDialog(QueryID askID, const Component & icon, const MetaString & title, const MetaString & description, const std::vector<ObjectInstanceID> & objects) override;
|
||||
void saveGame(BinarySerializer & h, const int version) override; //saving
|
||||
void loadGame(BinaryDeserializer & h, const int version) override; //loading
|
||||
void saveGame(BinarySerializer & h) override; //saving
|
||||
void loadGame(BinaryDeserializer & h) override; //loading
|
||||
void finish() override;
|
||||
|
||||
void availableCreaturesChanged(const CGDwelling * town) override;
|
||||
@ -301,7 +301,7 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename Handler> void serializeInternal(Handler & h, const int version)
|
||||
template<typename Handler> void serializeInternal(Handler & h)
|
||||
{
|
||||
h & knownTeleportChannels;
|
||||
h & knownSubterraneanGates;
|
||||
@ -341,7 +341,7 @@ public:
|
||||
//we have to explicitly ignore invalid goal class type id
|
||||
h & typeId;
|
||||
Goals::AbstractGoal ignored2;
|
||||
ignored2.serialize(h, version);
|
||||
ignored2.serialize(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -261,12 +261,12 @@ void CCallback::setFormation(const CGHeroInstance * hero, EArmyFormation mode)
|
||||
sendRequest(&pack);
|
||||
}
|
||||
|
||||
void CCallback::recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero)
|
||||
void CCallback::recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero, const HeroTypeID & nextHero)
|
||||
{
|
||||
assert(townOrTavern);
|
||||
assert(hero);
|
||||
|
||||
HireHero pack(hero->getHeroType(), townOrTavern->id);
|
||||
HireHero pack(hero->getHeroType(), townOrTavern->id, nextHero);
|
||||
pack.player = *player;
|
||||
sendRequest(&pack);
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ public:
|
||||
virtual void castSpell(const CGHeroInstance *hero, SpellID spellID, const int3 &pos = int3(-1, -1, -1))=0; //cast adventure map spell
|
||||
|
||||
//town
|
||||
virtual void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero)=0;
|
||||
virtual void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero, const HeroTypeID & nextHero=HeroTypeID::NONE)=0;
|
||||
virtual bool buildBuilding(const CGTownInstance *town, BuildingID buildingID)=0;
|
||||
virtual void recruitCreatures(const CGDwelling *obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1)=0;
|
||||
virtual bool upgradeCreature(const CArmedInstance *obj, SlotID stackPos, CreatureID newID=CreatureID::NONE)=0; //if newID==-1 then best possible upgrade will be made
|
||||
@ -185,7 +185,7 @@ public:
|
||||
void trade(const IMarket * market, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero = nullptr) override;
|
||||
void trade(const IMarket * market, EMarketMode mode, const std::vector<TradeItemSell> & id1, const std::vector<TradeItemBuy> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero = nullptr) override;
|
||||
void setFormation(const CGHeroInstance * hero, EArmyFormation mode) override;
|
||||
void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero) override;
|
||||
void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero, const HeroTypeID & nextHero=HeroTypeID::NONE) override;
|
||||
void save(const std::string &fname) override;
|
||||
void sendMessage(const std::string &mess, const CGObjectInstance * currentObject = nullptr) override;
|
||||
void gamePause(bool pause) override;
|
||||
|
27
ChangeLog.md
27
ChangeLog.md
@ -1,4 +1,4 @@
|
||||
# 1.4.3 -> 1.5.0
|
||||
# 1.4.5 -> 1.5.0
|
||||
|
||||
### General
|
||||
* Added Chinese translation to map editor
|
||||
@ -10,6 +10,31 @@
|
||||
* Added status bar to the backpack window
|
||||
* Quick backpack window is now only available when enabled Interface enhancements
|
||||
|
||||
# 1.4.4 -> 1.4.5
|
||||
|
||||
### Stability
|
||||
* Fixed crash on creature spellcasting
|
||||
* Fixed crash on unit entering magical obstacles such as quicksands
|
||||
* Fixed freeze on map loading on some systems
|
||||
* Fixed crash on attempt to start campaign with unsupported map
|
||||
* Fixed crash on opening creature information window with invalid SPELL_IMMUNITY bonus
|
||||
|
||||
### Random Maps Generator
|
||||
* Fixed placement of guards sometimes resulting into open connection into third zone
|
||||
* Fixed rare crash on multithreaded access during placement of artifacts or wandering monsters
|
||||
|
||||
### Map Editor
|
||||
* Fixed inspector using wrong editor for some values
|
||||
|
||||
### AI
|
||||
* Fixed bug leading to AI not attacking wandering monsters in some cases
|
||||
* Fixed crash on using StupidAI for autocombat or for enemy players
|
||||
|
||||
# 1.4.3 -> 1.4.4
|
||||
|
||||
### General
|
||||
* Fixed crash on generation of random maps
|
||||
|
||||
# 1.4.2 -> 1.4.3
|
||||
|
||||
### General
|
||||
|
@ -91,6 +91,7 @@
|
||||
"vcmi.lobby.room.type" : "Room Type",
|
||||
"vcmi.lobby.room.mode" : "Game Mode",
|
||||
|
||||
"vcmi.client.errors.invalidMap" : "{Invalid map or campaign}\n\nFailed to start game! Selected map or campaign might be invalid or corrupted. Reason:\n%s",
|
||||
"vcmi.client.errors.missingCampaigns" : "{Missing data files}\n\nCampaigns data files were not found! You may be using incomplete or corrupted Heroes 3 data files. Please reinstall game data.",
|
||||
"vcmi.server.errors.existingProcess" : "Another VCMI server process is running. Please terminate it before starting a new game.",
|
||||
"vcmi.server.errors.modsToEnable" : "{Following mods are required}",
|
||||
@ -251,6 +252,8 @@
|
||||
"vcmi.heroWindow.openBackpack.hover" : "Open artifact backpack window",
|
||||
"vcmi.heroWindow.openBackpack.help" : "Opens window that allows easier artifact backpack management.",
|
||||
|
||||
"vcmi.tavernWindow.inviteHero" : "Invite hero",
|
||||
|
||||
"vcmi.commanderWindow.artifactMessage" : "Do you want to return this artifact to the hero?",
|
||||
|
||||
"vcmi.creatureWindow.showBonuses.hover" : "Switch to bonuses view",
|
||||
|
@ -232,6 +232,8 @@
|
||||
"vcmi.heroWindow.openBackpack.hover" : "Artefakt-Rucksack-Fenster öffnen",
|
||||
"vcmi.heroWindow.openBackpack.help" : "Öffnet ein Fenster, das die Verwaltung des Artefakt-Rucksacks erleichtert",
|
||||
|
||||
"vcmi.tavernWindow.inviteHero" : "Helden einladen",
|
||||
|
||||
"vcmi.commanderWindow.artifactMessage" : "Möchtet Ihr diesen Artefakt dem Helden zurückgeben?",
|
||||
|
||||
"vcmi.creatureWindow.showBonuses.hover" : "Wechsle zur Bonus-Ansicht",
|
||||
|
@ -412,9 +412,9 @@ static void mainLoop()
|
||||
{
|
||||
if(CSH->client)
|
||||
CSH->endGameplay();
|
||||
}
|
||||
|
||||
GH.windows().clear();
|
||||
GH.windows().clear();
|
||||
}
|
||||
|
||||
CMM.reset();
|
||||
|
||||
@ -474,25 +474,24 @@ void handleQuit(bool ask)
|
||||
// FIXME: avoids crash if player attempts to close game while opening is still playing
|
||||
// use cursor handler as indicator that loading is not done yet
|
||||
// proper solution would be to abort init thread (or wait for it to finish)
|
||||
if(!ask)
|
||||
{
|
||||
quitApplication();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CCS->curh)
|
||||
{
|
||||
quitRequestedDuringOpeningPlayback = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if(ask)
|
||||
{
|
||||
CCS->curh->set(Cursor::Map::POINTER);
|
||||
CCS->curh->set(Cursor::Map::POINTER);
|
||||
|
||||
if (LOCPLINT)
|
||||
LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[69], quitApplication, nullptr);
|
||||
else
|
||||
CInfoWindow::showYesNoDialog(CGI->generaltexth->allTexts[69], {}, quitApplication, {}, PlayerColor(1));
|
||||
}
|
||||
if (LOCPLINT)
|
||||
LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[69], quitApplication, nullptr);
|
||||
else
|
||||
{
|
||||
quitApplication();
|
||||
}
|
||||
CInfoWindow::showYesNoDialog(CGI->generaltexth->allTexts[69], {}, quitApplication, {}, PlayerColor(1));
|
||||
}
|
||||
|
||||
void handleFatalError(const std::string & message, bool terminate)
|
||||
|
@ -1150,16 +1150,16 @@ void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const Bonus
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerInterface::saveGame( BinarySerializer & h, const int version )
|
||||
void CPlayerInterface::saveGame( BinarySerializer & h )
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
localState->serialize(h, version);
|
||||
localState->serialize(h);
|
||||
}
|
||||
|
||||
void CPlayerInterface::loadGame( BinaryDeserializer & h, const int version )
|
||||
void CPlayerInterface::loadGame( BinaryDeserializer & h )
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
localState->serialize(h, version);
|
||||
localState->serialize(h);
|
||||
firstCall = -1;
|
||||
}
|
||||
|
||||
|
@ -145,8 +145,8 @@ protected: // Call-ins from server, should not be called directly, but only via
|
||||
void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) override;
|
||||
void playerStartsTurn(PlayerColor player) override; //called before yourTurn on active itnerface
|
||||
void playerEndsTurn(PlayerColor player) override;
|
||||
void saveGame(BinarySerializer & h, const int version) override; //saving
|
||||
void loadGame(BinaryDeserializer & h, const int version) override; //loading
|
||||
void saveGame(BinarySerializer & h) override; //saving
|
||||
void loadGame(BinaryDeserializer & h) override; //loading
|
||||
void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override;
|
||||
|
||||
//for battles
|
||||
|
@ -610,7 +610,9 @@ bool CServerHandler::validateGameStart(bool allowOnlyAI) const
|
||||
void CServerHandler::sendStartGame(bool allowOnlyAI) const
|
||||
{
|
||||
verifyStateBeforeStart(allowOnlyAI ? true : settings["session"]["onlyai"].Bool());
|
||||
GH.windows().createAndPushWindow<CLoadingScreen>();
|
||||
|
||||
if(!settings["session"]["headless"].Bool())
|
||||
GH.windows().createAndPushWindow<CLoadingScreen>();
|
||||
|
||||
LobbyStartGame lsg;
|
||||
if(client)
|
||||
|
@ -226,7 +226,7 @@ void CClient::loadGame(CGameState * initializedGameState)
|
||||
throw std::runtime_error("Cannot open client part of " + CSH->si->mapname);
|
||||
|
||||
std::unique_ptr<CLoadFile> loader (new CLoadFile(clientSaveName));
|
||||
serialize(loader->serializer, loader->serializer.fileVersion);
|
||||
serialize(loader->serializer, loader->serializer.version);
|
||||
|
||||
logNetwork->info("Client data loaded.");
|
||||
}
|
||||
@ -239,7 +239,7 @@ void CClient::loadGame(CGameState * initializedGameState)
|
||||
initPlayerInterfaces();
|
||||
}
|
||||
|
||||
void CClient::serialize(BinarySerializer & h, const int version)
|
||||
void CClient::serialize(BinarySerializer & h)
|
||||
{
|
||||
assert(h.saving);
|
||||
ui8 players = static_cast<ui8>(playerint.size());
|
||||
@ -252,20 +252,17 @@ void CClient::serialize(BinarySerializer & h, const int version)
|
||||
h & i->first;
|
||||
h & i->second->dllName;
|
||||
h & i->second->human;
|
||||
i->second->saveGame(h, version);
|
||||
i->second->saveGame(h);
|
||||
}
|
||||
|
||||
#if SCRIPTING_ENABLED
|
||||
if(version >= 800)
|
||||
{
|
||||
JsonNode scriptsState;
|
||||
clientScripts->serializeState(h.saving, scriptsState);
|
||||
h & scriptsState;
|
||||
}
|
||||
JsonNode scriptsState;
|
||||
clientScripts->serializeState(h.saving, scriptsState);
|
||||
h & scriptsState;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CClient::serialize(BinaryDeserializer & h, const int version)
|
||||
void CClient::serialize(BinaryDeserializer & h)
|
||||
{
|
||||
assert(!h.saving);
|
||||
ui8 players = 0;
|
||||
@ -321,7 +318,7 @@ void CClient::serialize(BinaryDeserializer & h, const int version)
|
||||
|
||||
// loadGame needs to be called after initGameInterface to load paths correctly
|
||||
// initGameInterface is called in installNewPlayerInterface
|
||||
nInt->loadGame(h, version);
|
||||
nInt->loadGame(h);
|
||||
|
||||
if (shouldResetInterface)
|
||||
{
|
||||
@ -412,7 +409,7 @@ void CClient::initPlayerEnvironments()
|
||||
hasHumanPlayer = true;
|
||||
}
|
||||
|
||||
if(!hasHumanPlayer)
|
||||
if(!hasHumanPlayer && !settings["session"]["headless"].Bool())
|
||||
{
|
||||
Settings session = settings.write["session"];
|
||||
session["spectate"].Bool() = true;
|
||||
@ -437,7 +434,7 @@ void CClient::initPlayerInterfaces()
|
||||
if(!vstd::contains(playerint, color))
|
||||
{
|
||||
logNetwork->info("Preparing interface for player %s", color.toString());
|
||||
if(playerInfo.second.isControlledByAI())
|
||||
if(playerInfo.second.isControlledByAI() || settings["session"]["onlyai"].Bool())
|
||||
{
|
||||
bool alliedToHuman = false;
|
||||
for(auto & allyInfo : gs->scenarioOps->playerInfos)
|
||||
|
@ -131,8 +131,8 @@ public:
|
||||
|
||||
void newGame(CGameState * gameState);
|
||||
void loadGame(CGameState * gameState);
|
||||
void serialize(BinarySerializer & h, const int version);
|
||||
void serialize(BinaryDeserializer & h, const int version);
|
||||
void serialize(BinarySerializer & h);
|
||||
void serialize(BinaryDeserializer & h);
|
||||
|
||||
void save(const std::string & fname);
|
||||
void endGame();
|
||||
|
@ -157,6 +157,9 @@ void ApplyClientNetPackVisitor::visitSetMana(SetMana & pack)
|
||||
const CGHeroInstance *h = cl.getHero(pack.hid);
|
||||
callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroManaPointsChanged, h);
|
||||
|
||||
if(settings["session"]["headless"].Bool())
|
||||
return;
|
||||
|
||||
for (auto window : GH.windows().findWindows<BattleWindow>())
|
||||
window->heroManaPointsChanged(h);
|
||||
}
|
||||
@ -467,7 +470,8 @@ void ApplyFirstClientNetPackVisitor::visitRemoveObject(RemoveObject & pack)
|
||||
i->second->objectRemoved(o, pack.initiator);
|
||||
}
|
||||
|
||||
CGI->mh->waitForOngoingAnimations();
|
||||
if(CGI->mh)
|
||||
CGI->mh->waitForOngoingAnimations();
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitRemoveObject(RemoveObject & pack)
|
||||
@ -553,9 +557,11 @@ void ApplyClientNetPackVisitor::visitNewStructures(NewStructures & pack)
|
||||
}
|
||||
|
||||
// invalidate section of map view with our object and force an update
|
||||
CGI->mh->onObjectInstantRemove(town, town->getOwner());
|
||||
CGI->mh->onObjectInstantAdd(town, town->getOwner());
|
||||
|
||||
if(CGI->mh)
|
||||
{
|
||||
CGI->mh->onObjectInstantRemove(town, town->getOwner());
|
||||
CGI->mh->onObjectInstantAdd(town, town->getOwner());
|
||||
}
|
||||
}
|
||||
void ApplyClientNetPackVisitor::visitRazeStructures(RazeStructures & pack)
|
||||
{
|
||||
@ -566,8 +572,11 @@ void ApplyClientNetPackVisitor::visitRazeStructures(RazeStructures & pack)
|
||||
}
|
||||
|
||||
// invalidate section of map view with our object and force an update
|
||||
CGI->mh->onObjectInstantRemove(town, town->getOwner());
|
||||
CGI->mh->onObjectInstantAdd(town, town->getOwner());
|
||||
if(CGI->mh)
|
||||
{
|
||||
CGI->mh->onObjectInstantRemove(town, town->getOwner());
|
||||
CGI->mh->onObjectInstantAdd(town, town->getOwner());
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitSetAvailableCreatures(SetAvailableCreatures & pack)
|
||||
@ -651,7 +660,7 @@ void ApplyFirstClientNetPackVisitor::visitSetObjectProperty(SetObjectProperty &
|
||||
}
|
||||
|
||||
// invalidate section of map view with our object and force an update with new flag color
|
||||
if (pack.what == ObjProperty::OWNER)
|
||||
if (pack.what == ObjProperty::OWNER && CGI->mh)
|
||||
{
|
||||
auto object = gs.getObjInstance(pack.id);
|
||||
CGI->mh->onObjectInstantRemove(object, object->getOwner());
|
||||
@ -668,7 +677,7 @@ void ApplyClientNetPackVisitor::visitSetObjectProperty(SetObjectProperty & pack)
|
||||
}
|
||||
|
||||
// invalidate section of map view with our object and force an update with new flag color
|
||||
if (pack.what == ObjProperty::OWNER)
|
||||
if (pack.what == ObjProperty::OWNER && CGI->mh)
|
||||
{
|
||||
auto object = gs.getObjInstance(pack.id);
|
||||
CGI->mh->onObjectInstantAdd(object, object->getOwner());
|
||||
@ -1023,7 +1032,9 @@ void ApplyClientNetPackVisitor::visitNewObject(NewObject & pack)
|
||||
if(gs.isVisible(obj, i->first))
|
||||
i->second->newObject(obj);
|
||||
}
|
||||
CGI->mh->waitForOngoingAnimations();
|
||||
|
||||
if(CGI->mh)
|
||||
CGI->mh->waitForOngoingAnimations();
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitSetAvailableArtifacts(SetAvailableArtifacts & pack)
|
||||
|
@ -47,7 +47,7 @@ public:
|
||||
int spellbookLastTabAdvmap = 4;
|
||||
|
||||
template<typename Handler>
|
||||
void serialize(Handler & h, const int version)
|
||||
void serialize(Handler & h)
|
||||
{
|
||||
h & spellbookLastPageBattle;
|
||||
h & spellbookLastPageAdvmap;
|
||||
@ -94,7 +94,7 @@ public:
|
||||
void setSelection(const CArmedInstance *sel);
|
||||
|
||||
template<typename Handler>
|
||||
void serialize(Handler & h, int version)
|
||||
void serialize(Handler & h)
|
||||
{
|
||||
//WARNING: this code is broken and not used. See CClient::loadGame
|
||||
std::map<const CGHeroInstance *, int3> pathsMap; //hero -> dest
|
||||
|
@ -750,7 +750,7 @@ void BattleActionsController::actionRealize(PossiblePlayerBattleAction action, B
|
||||
|
||||
if (!spellcastingModeActive())
|
||||
{
|
||||
if (action.spell().toSpell())
|
||||
if (action.spell().hasValue())
|
||||
{
|
||||
owner.giveCommand(EActionType::MONSTER_SPELL, targetHex, action.spell());
|
||||
}
|
||||
@ -887,17 +887,17 @@ void BattleActionsController::tryActivateStackSpellcasting(const CStack *casterS
|
||||
{
|
||||
// faerie dragon can cast only one, randomly selected spell until their next move
|
||||
//TODO: faerie dragon type spell should be selected by server
|
||||
const auto * spellToCast = owner.getBattle()->getRandomCastedSpell(CRandomGenerator::getDefault(), casterStack).toSpell();
|
||||
const auto spellToCast = owner.getBattle()->getRandomCastedSpell(CRandomGenerator::getDefault(), casterStack);
|
||||
|
||||
if (spellToCast)
|
||||
creatureSpells.push_back(spellToCast);
|
||||
if (spellToCast.hasValue())
|
||||
creatureSpells.push_back(spellToCast.toSpell());
|
||||
}
|
||||
|
||||
TConstBonusListPtr bl = casterStack->getBonuses(Selector::type()(BonusType::SPELLCASTER));
|
||||
|
||||
for(const auto & bonus : *bl)
|
||||
{
|
||||
if (bonus->additionalInfo[0] <= 0)
|
||||
if (bonus->additionalInfo[0] <= 0 && bonus->subtype.as<SpellID>().hasValue())
|
||||
creatureSpells.push_back(bonus->subtype.as<SpellID>().toSpell());
|
||||
}
|
||||
}
|
||||
|
@ -352,13 +352,13 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
|
||||
CCS->curh->set(Cursor::Combat::BLOCKED);
|
||||
|
||||
const SpellID spellID = sc->spellID;
|
||||
|
||||
if(!spellID.hasValue())
|
||||
return;
|
||||
|
||||
const CSpell * spell = spellID.toSpell();
|
||||
auto targetedTile = sc->tile;
|
||||
|
||||
assert(spell);
|
||||
if(!spell)
|
||||
return;
|
||||
|
||||
const AudioPath & castSoundPath = spell->getCastSound();
|
||||
|
||||
if (!castSoundPath.empty())
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "../render/Colors.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
#include "../render/Graphics.h"
|
||||
#include "../render/IFont.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/spells/ISpellMechanics.h"
|
||||
@ -327,10 +329,10 @@ void BattleStacksController::showStackAmountBox(Canvas & canvas, const CStack *
|
||||
boxPosition = owner.fieldController->hexPositionLocal(frontPos).center() + Point(-8, -14);
|
||||
}
|
||||
|
||||
Point textPosition = amountBG->dimensions()/2 + boxPosition + Point(0, 1);
|
||||
Point textPosition = Point(amountBG->dimensions().x/2 + boxPosition.x, boxPosition.y + graphics->fonts[EFonts::FONT_TINY]->getLineHeight() - 6);
|
||||
|
||||
canvas.draw(amountBG, boxPosition);
|
||||
canvas.drawText(textPosition, EFonts::FONT_TINY, Colors::WHITE, ETextAlignment::CENTER, TextOperations::formatMetric(stack->getCount(), 4));
|
||||
canvas.drawText(textPosition, EFonts::FONT_TINY, Colors::WHITE, ETextAlignment::TOPCENTER, TextOperations::formatMetric(stack->getCount(), 4));
|
||||
}
|
||||
|
||||
void BattleStacksController::showStack(Canvas & canvas, const CStack * stack)
|
||||
|
@ -21,10 +21,6 @@
|
||||
|
||||
#include <SDL_events.h>
|
||||
|
||||
#ifdef VCMI_APPLE
|
||||
# include <dispatch/dispatch.h>
|
||||
#endif
|
||||
|
||||
void InputSourceText::handleEventTextInput(const SDL_TextInputEvent & text)
|
||||
{
|
||||
GH.events().dispatchTextInput(text.text);
|
||||
@ -37,38 +33,27 @@ void InputSourceText::handleEventTextEditing(const SDL_TextEditingEvent & text)
|
||||
|
||||
void InputSourceText::startTextInput(const Rect & whereInput)
|
||||
{
|
||||
|
||||
#ifdef VCMI_APPLE
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
#endif
|
||||
|
||||
Rect rectInScreenCoordinates = GH.screenHandler().convertLogicalPointsToWindow(whereInput);
|
||||
SDL_Rect textInputRect = CSDL_Ext::toSDL(rectInScreenCoordinates);
|
||||
|
||||
SDL_SetTextInputRect(&textInputRect);
|
||||
|
||||
if (SDL_IsTextInputActive() == SDL_FALSE)
|
||||
GH.dispatchMainThread([whereInput]()
|
||||
{
|
||||
SDL_StartTextInput();
|
||||
}
|
||||
Rect rectInScreenCoordinates = GH.screenHandler().convertLogicalPointsToWindow(whereInput);
|
||||
SDL_Rect textInputRect = CSDL_Ext::toSDL(rectInScreenCoordinates);
|
||||
|
||||
#ifdef VCMI_APPLE
|
||||
SDL_SetTextInputRect(&textInputRect);
|
||||
|
||||
if (SDL_IsTextInputActive() == SDL_FALSE)
|
||||
{
|
||||
SDL_StartTextInput();
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputSourceText::stopTextInput()
|
||||
{
|
||||
#ifdef VCMI_APPLE
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
#endif
|
||||
|
||||
if (SDL_IsTextInputActive() == SDL_TRUE)
|
||||
GH.dispatchMainThread([]()
|
||||
{
|
||||
SDL_StopTextInput();
|
||||
}
|
||||
|
||||
#ifdef VCMI_APPLE
|
||||
if (SDL_IsTextInputActive() == SDL_TRUE)
|
||||
{
|
||||
SDL_StopTextInput();
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ CBonusSelection::CBonusSelection()
|
||||
|
||||
buttonStart = std::make_shared<CButton>(Point(475, 536), AnimationPath::builtin("CBBEGIB.DEF"), CButton::tooltip(), std::bind(&CBonusSelection::startMap, this), EShortcut::GLOBAL_ACCEPT);
|
||||
buttonRestart = std::make_shared<CButton>(Point(475, 536), AnimationPath::builtin("CBRESTB.DEF"), CButton::tooltip(), std::bind(&CBonusSelection::restartMap, this), EShortcut::GLOBAL_ACCEPT);
|
||||
buttonVideo = std::make_shared<CButton>(Point(705, 214), AnimationPath::builtin("CBVIDEB.DEF"), CButton::tooltip(), [this](){ GH.windows().createAndPushWindow<CPrologEpilogVideo>(getCampaign()->scenario(CSH->campaignMap).prolog, [this](){ redraw(); }); });
|
||||
buttonBack = std::make_shared<CButton>(Point(624, 536), AnimationPath::builtin("CBCANCB.DEF"), CButton::tooltip(), std::bind(&CBonusSelection::goBack, this), EShortcut::GLOBAL_CANCEL);
|
||||
|
||||
campaignName = std::make_shared<CLabel>(481, 28, FONT_BIG, ETextAlignment::TOPLEFT, Colors::YELLOW, CSH->si->getCampaignName());
|
||||
@ -309,6 +310,7 @@ void CBonusSelection::updateAfterStateChange()
|
||||
if(CSH->state != EClientState::GAMEPLAY)
|
||||
{
|
||||
buttonRestart->disable();
|
||||
buttonVideo->disable();
|
||||
buttonStart->enable();
|
||||
if(!getCampaign()->conqueredScenarios().empty())
|
||||
buttonBack->block(true);
|
||||
@ -319,6 +321,7 @@ void CBonusSelection::updateAfterStateChange()
|
||||
{
|
||||
buttonStart->disable();
|
||||
buttonRestart->enable();
|
||||
buttonVideo->enable();
|
||||
buttonBack->block(false);
|
||||
if(buttonDifficultyLeft)
|
||||
buttonDifficultyLeft->disable();
|
||||
@ -401,6 +404,7 @@ void CBonusSelection::startMap()
|
||||
//block buttons immediately
|
||||
buttonStart->block(true);
|
||||
buttonRestart->block(true);
|
||||
buttonVideo->block(true);
|
||||
buttonBack->block(true);
|
||||
|
||||
if(LOCPLINT) // we're currently ingame, so ask for starting new map and end game
|
||||
|
@ -65,6 +65,7 @@ public:
|
||||
std::shared_ptr<CButton> buttonStart;
|
||||
std::shared_ptr<CButton> buttonRestart;
|
||||
std::shared_ptr<CButton> buttonBack;
|
||||
std::shared_ptr<CButton> buttonVideo;
|
||||
std::shared_ptr<CLabel> campaignName;
|
||||
std::shared_ptr<CLabel> labelCampaignDescription;
|
||||
std::shared_ptr<CTextBox> campaignDescription;
|
||||
|
@ -135,11 +135,23 @@ void CLobbyScreen::toggleTab(std::shared_ptr<CIntObject> tab)
|
||||
|
||||
void CLobbyScreen::startCampaign()
|
||||
{
|
||||
if(CSH->mi)
|
||||
{
|
||||
if(!CSH->mi)
|
||||
return;
|
||||
|
||||
try {
|
||||
auto ourCampaign = CampaignHandler::getCampaign(CSH->mi->fileURI);
|
||||
CSH->setCampaignState(ourCampaign);
|
||||
}
|
||||
catch (const std::runtime_error &e)
|
||||
{
|
||||
// handle possible exception on map loading. For example campaign that contains map in unsupported format
|
||||
// for example, wog campaigns or hota campaigns without hota map support mod
|
||||
MetaString message;
|
||||
message.appendTextID("vcmi.client.errors.invalidMap");
|
||||
message.replaceRawString(e.what());
|
||||
|
||||
CInfoWindow::showInfoDialog(message.toString(), {});
|
||||
}
|
||||
}
|
||||
|
||||
void CLobbyScreen::startScenario(bool allowOnlyAI)
|
||||
|
@ -407,8 +407,14 @@ void OptionsTabBase::recreate()
|
||||
}
|
||||
|
||||
if(auto buttonCheatAllowed = widget<CToggleButton>("buttonCheatAllowed"))
|
||||
{
|
||||
buttonCheatAllowed->setSelectedSilent(SEL->getStartInfo()->extraOptionsInfo.cheatsAllowed);
|
||||
buttonCheatAllowed->block(SEL->screenType == ESelectionScreen::loadGame);
|
||||
}
|
||||
|
||||
if(auto buttonUnlimitedReplay = widget<CToggleButton>("buttonUnlimitedReplay"))
|
||||
{
|
||||
buttonUnlimitedReplay->setSelectedSilent(SEL->getStartInfo()->extraOptionsInfo.unlimitedReplay);
|
||||
buttonUnlimitedReplay->block(SEL->screenType == ESelectionScreen::loadGame);
|
||||
}
|
||||
}
|
||||
|
@ -64,5 +64,6 @@ void CPrologEpilogVideo::clickPressed(const Point & cursorPosition)
|
||||
close();
|
||||
CCS->soundh->stopSound(voiceSoundHandle);
|
||||
CCS->soundh->stopSound(videoSoundHandle);
|
||||
exitCb();
|
||||
if(exitCb)
|
||||
exitCb();
|
||||
}
|
||||
|
@ -205,6 +205,8 @@ void SDLImage::exportBitmap(const boost::filesystem::path& path) const
|
||||
|
||||
void SDLImage::playerColored(PlayerColor player)
|
||||
{
|
||||
if (!surf)
|
||||
return;
|
||||
graphics->blueToPlayersAdv(surf, player);
|
||||
}
|
||||
|
||||
|
@ -553,8 +553,7 @@ Point CGStatusBar::getBorderSize()
|
||||
|
||||
CTextInput::CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(const std::string &)> & CB, ETextAlignment alignment, bool giveFocusToInput)
|
||||
: CLabel(Pos.x, Pos.y, font, alignment),
|
||||
cb(CB),
|
||||
CFocusable(std::make_shared<CKeyboardFocusListener>(this))
|
||||
cb(CB)
|
||||
{
|
||||
setRedrawParent(true);
|
||||
pos.h = Pos.h;
|
||||
@ -570,7 +569,7 @@ CTextInput::CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(c
|
||||
}
|
||||
|
||||
CTextInput::CTextInput(const Rect & Pos, const Point & bgOffset, const ImagePath & bgName, const CFunctionList<void(const std::string &)> & CB)
|
||||
:cb(CB), CFocusable(std::make_shared<CKeyboardFocusListener>(this))
|
||||
:cb(CB)
|
||||
{
|
||||
pos += Pos.topLeft();
|
||||
pos.h = Pos.h;
|
||||
@ -587,7 +586,6 @@ CTextInput::CTextInput(const Rect & Pos, const Point & bgOffset, const ImagePath
|
||||
}
|
||||
|
||||
CTextInput::CTextInput(const Rect & Pos, std::shared_ptr<IImage> srf)
|
||||
:CFocusable(std::make_shared<CKeyboardFocusListener>(this))
|
||||
{
|
||||
pos += Pos.topLeft();
|
||||
OBJ_CONSTRUCTION;
|
||||
@ -603,20 +601,15 @@ CTextInput::CTextInput(const Rect & Pos, std::shared_ptr<IImage> srf)
|
||||
#endif
|
||||
}
|
||||
|
||||
std::atomic<int> CKeyboardFocusListener::usageIndex(0);
|
||||
std::atomic<int> CFocusable::usageIndex(0);
|
||||
|
||||
CKeyboardFocusListener::CKeyboardFocusListener(CTextInput * textInput)
|
||||
:textInput(textInput)
|
||||
void CFocusable::focusGot()
|
||||
{
|
||||
}
|
||||
|
||||
void CKeyboardFocusListener::focusGot()
|
||||
{
|
||||
GH.startTextInput(textInput->pos);
|
||||
GH.startTextInput(pos);
|
||||
usageIndex++;
|
||||
}
|
||||
|
||||
void CKeyboardFocusListener::focusLost()
|
||||
void CFocusable::focusLost()
|
||||
{
|
||||
if(0 == --usageIndex)
|
||||
{
|
||||
@ -769,12 +762,6 @@ void CTextInput::numberFilter(std::string & text, const std::string & oldText, i
|
||||
}
|
||||
|
||||
CFocusable::CFocusable()
|
||||
:CFocusable(std::make_shared<IFocusListener>())
|
||||
{
|
||||
}
|
||||
|
||||
CFocusable::CFocusable(std::shared_ptr<IFocusListener> focusListener)
|
||||
: focusListener(focusListener)
|
||||
{
|
||||
focus = false;
|
||||
focusables.push_back(this);
|
||||
@ -785,7 +772,7 @@ CFocusable::~CFocusable()
|
||||
if(hasFocus())
|
||||
{
|
||||
inputWithFocus = nullptr;
|
||||
focusListener->focusLost();
|
||||
focusLost();
|
||||
}
|
||||
|
||||
focusables -= this;
|
||||
@ -799,13 +786,13 @@ bool CFocusable::hasFocus() const
|
||||
void CFocusable::giveFocus()
|
||||
{
|
||||
focus = true;
|
||||
focusListener->focusGot();
|
||||
focusGot();
|
||||
redraw();
|
||||
|
||||
if(inputWithFocus)
|
||||
{
|
||||
inputWithFocus->focus = false;
|
||||
inputWithFocus->focusListener->focusLost();
|
||||
inputWithFocus->focusLost();
|
||||
inputWithFocus->redraw();
|
||||
}
|
||||
|
||||
@ -837,7 +824,7 @@ void CFocusable::removeFocus()
|
||||
if(this == inputWithFocus)
|
||||
{
|
||||
focus = false;
|
||||
focusListener->focusLost();
|
||||
focusLost();
|
||||
redraw();
|
||||
|
||||
inputWithFocus = nullptr;
|
||||
|
@ -163,25 +163,12 @@ public:
|
||||
void clear() override;
|
||||
void setEnteringMode(bool on) override;
|
||||
void setEnteredText(const std::string & text) override;
|
||||
|
||||
};
|
||||
|
||||
class CFocusable;
|
||||
|
||||
class IFocusListener
|
||||
{
|
||||
public:
|
||||
virtual void focusGot() {};
|
||||
virtual void focusLost() {};
|
||||
virtual ~IFocusListener() = default;
|
||||
};
|
||||
|
||||
/// UIElement which can get input focus
|
||||
class CFocusable : public virtual CIntObject
|
||||
{
|
||||
private:
|
||||
std::shared_ptr<IFocusListener> focusListener;
|
||||
|
||||
static std::atomic<int> usageIndex;
|
||||
public:
|
||||
bool focus; //only one focusable control can have focus at one moment
|
||||
|
||||
@ -190,38 +177,27 @@ public:
|
||||
void removeFocus(); //remove focus
|
||||
bool hasFocus() const;
|
||||
|
||||
void focusGot();
|
||||
void focusLost();
|
||||
|
||||
static std::list<CFocusable *> focusables; //all existing objs
|
||||
static CFocusable * inputWithFocus; //who has focus now
|
||||
|
||||
CFocusable();
|
||||
CFocusable(std::shared_ptr<IFocusListener> focusListener);
|
||||
~CFocusable();
|
||||
};
|
||||
|
||||
class CTextInput;
|
||||
class CKeyboardFocusListener : public IFocusListener
|
||||
{
|
||||
private:
|
||||
static std::atomic<int> usageIndex;
|
||||
CTextInput * textInput;
|
||||
|
||||
public:
|
||||
CKeyboardFocusListener(CTextInput * textInput);
|
||||
void focusGot() override;
|
||||
void focusLost() override;
|
||||
};
|
||||
|
||||
/// Text input box where players can enter text
|
||||
class CTextInput : public CLabel, public CFocusable
|
||||
{
|
||||
std::string newText;
|
||||
std::string helpBox; //for right-click help
|
||||
|
||||
|
||||
protected:
|
||||
std::string visibleText() override;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
CFunctionList<void(const std::string &)> cb;
|
||||
CFunctionList<void(std::string &, const std::string &)> filters;
|
||||
void setText(const std::string & nText) override;
|
||||
|
@ -161,7 +161,7 @@ CMapOverviewWidget::CMapOverviewWidget(CMapOverview& parent):
|
||||
std::unique_ptr<CMap> campaignMap = nullptr;
|
||||
if(p.tabType != ESelectionScreen::newGame && config["variables"]["mapPreviewForSaves"].Bool())
|
||||
{
|
||||
CLoadFile lf(*CResourceHandler::get()->getResourceName(ResourcePath(p.resource.getName(), EResType::SAVEGAME)), MINIMAL_SERIALIZATION_VERSION);
|
||||
CLoadFile lf(*CResourceHandler::get()->getResourceName(ResourcePath(p.resource.getName(), EResType::SAVEGAME)), ESerializationVersion::MINIMAL);
|
||||
lf.checkMagicBytes(SAVEGAME_MAGIC);
|
||||
|
||||
auto mapHeader = std::make_unique<CMapHeader>();
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include "InfoWindows.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CServerHandler.h"
|
||||
#include "../Client.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CVideoHandler.h"
|
||||
@ -48,6 +50,7 @@
|
||||
#include "../lib/mapObjects/ObjectTemplate.h"
|
||||
#include "../lib/gameState/CGameState.h"
|
||||
#include "../lib/gameState/SThievesGuildInfo.h"
|
||||
#include "../lib/gameState/TavernHeroesPool.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/GameSettings.h"
|
||||
@ -443,7 +446,8 @@ CLevelWindow::~CLevelWindow()
|
||||
CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj, const std::function<void()> & onWindowClosed)
|
||||
: CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("TPTAVERN")),
|
||||
onWindowClosed(onWindowClosed),
|
||||
tavernObj(TavernObj)
|
||||
tavernObj(TavernObj),
|
||||
heroToInvite(nullptr)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
|
||||
@ -459,8 +463,8 @@ CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj, const std::func
|
||||
|
||||
oldSelected = -1;
|
||||
|
||||
h1 = std::make_shared<HeroPortrait>(selected, 0, 72, 299, h[0]);
|
||||
h2 = std::make_shared<HeroPortrait>(selected, 1, 162, 299, h[1]);
|
||||
h1 = std::make_shared<HeroPortrait>(selected, 0, 72, 299, h[0], [this]() { if(!recruit->isBlocked()) recruitb(); });
|
||||
h2 = std::make_shared<HeroPortrait>(selected, 1, 162, 299, h[1], [this]() { if(!recruit->isBlocked()) recruitb(); });
|
||||
|
||||
title = std::make_shared<CLabel>(197, 32, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[37]);
|
||||
cost = std::make_shared<CLabel>(320, 328, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, std::to_string(GameConstants::HERO_GOLD_COST));
|
||||
@ -507,6 +511,34 @@ CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj, const std::func
|
||||
CCS->videoh->open(townObj->town->clientInfo.tavernVideo);
|
||||
else
|
||||
CCS->videoh->open(VideoPath::builtin("TAVERN.BIK"));
|
||||
|
||||
addInvite();
|
||||
}
|
||||
|
||||
void CTavernWindow::addInvite()
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
|
||||
if(!VLC->settings()->getBoolean(EGameSettings::HEROES_TAVERN_INVITE))
|
||||
return;
|
||||
|
||||
const auto & heroesPool = CSH->client->gameState()->heroesPool;
|
||||
for(auto & elem : heroesPool->unusedHeroesFromPool())
|
||||
{
|
||||
bool heroAvailable = heroesPool->isHeroAvailableFor(elem.first, tavernObj->getOwner());
|
||||
if(heroAvailable)
|
||||
inviteableHeroes[elem.first] = elem.second;
|
||||
}
|
||||
|
||||
if(!inviteableHeroes.empty())
|
||||
{
|
||||
if(!heroToInvite)
|
||||
heroToInvite = (*RandomGeneratorUtil::nextItem(inviteableHeroes, CRandomGenerator::getDefault())).second;
|
||||
|
||||
inviteHero = std::make_shared<CLabel>(170, 444, EFonts::FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->translate("vcmi.tavernWindow.inviteHero"));
|
||||
inviteHeroImage = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsSmall"), (*CGI->heroh)[heroToInvite->getHeroType()]->imageIndex, 0, 245, 428);
|
||||
inviteHeroImageArea = std::make_shared<LRClickableArea>(Rect(245, 428, 48, 32), [this](){ GH.windows().createAndPushWindow<HeroSelector>(inviteableHeroes, [this](CGHeroInstance* h){ heroToInvite = h; addInvite(); }); }, [this](){ GH.windows().createAndPushWindow<CRClickPopupInt>(std::make_shared<CHeroWindow>(heroToInvite)); });
|
||||
}
|
||||
}
|
||||
|
||||
void CTavernWindow::recruitb()
|
||||
@ -514,7 +546,7 @@ void CTavernWindow::recruitb()
|
||||
const CGHeroInstance *toBuy = (selected ? h2 : h1)->h;
|
||||
const CGObjectInstance *obj = tavernObj;
|
||||
|
||||
LOCPLINT->cb->recruitHero(obj, toBuy);
|
||||
LOCPLINT->cb->recruitHero(obj, toBuy, heroToInvite ? heroToInvite->getHeroType() : HeroTypeID::NONE);
|
||||
close();
|
||||
}
|
||||
|
||||
@ -569,15 +601,23 @@ void CTavernWindow::HeroPortrait::clickPressed(const Point & cursorPosition)
|
||||
*_sel = _id;
|
||||
}
|
||||
|
||||
void CTavernWindow::HeroPortrait::clickDouble(const Point & cursorPosition)
|
||||
{
|
||||
clickPressed(cursorPosition);
|
||||
|
||||
if(onChoose)
|
||||
onChoose();
|
||||
}
|
||||
|
||||
void CTavernWindow::HeroPortrait::showPopupWindow(const Point & cursorPosition)
|
||||
{
|
||||
if(h)
|
||||
GH.windows().createAndPushWindow<CRClickPopupInt>(std::make_shared<CHeroWindow>(h));
|
||||
}
|
||||
|
||||
CTavernWindow::HeroPortrait::HeroPortrait(int & sel, int id, int x, int y, const CGHeroInstance * H)
|
||||
: CIntObject(LCLICK | SHOW_POPUP | HOVER),
|
||||
h(H), _sel(&sel), _id(id)
|
||||
CTavernWindow::HeroPortrait::HeroPortrait(int & sel, int id, int x, int y, const CGHeroInstance * H, std::function<void()> OnChoose)
|
||||
: CIntObject(LCLICK | DOUBLECLICK | SHOW_POPUP | HOVER),
|
||||
h(H), _sel(&sel), _id(id), onChoose(OnChoose)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
h = H;
|
||||
@ -615,6 +655,33 @@ void CTavernWindow::HeroPortrait::hover(bool on)
|
||||
GH.statusbar()->clear();
|
||||
}
|
||||
|
||||
CTavernWindow::HeroSelector::HeroSelector(std::map<HeroTypeID, CGHeroInstance*> InviteableHeroes, std::function<void(CGHeroInstance*)> OnChoose)
|
||||
: CWindowObject(BORDERED), inviteableHeroes(InviteableHeroes), onChoose(OnChoose)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
|
||||
pos = Rect(0, 0, 16 * 48, (inviteableHeroes.size() / 16 + (inviteableHeroes.size() % 16 != 0)) * 32);
|
||||
background = std::make_shared<CFilledTexture>(ImagePath::builtin("DIBOXBCK"), Rect(0, 0, pos.w, pos.h));
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
for(auto & h : inviteableHeroes)
|
||||
{
|
||||
portraits.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsSmall"), (*CGI->heroh)[h.first]->imageIndex, 0, x * 48, y * 32));
|
||||
portraitAreas.push_back(std::make_shared<LRClickableArea>(Rect(x * 48, y * 32, 48, 32), [this, h](){ close(); onChoose(inviteableHeroes[h.first]); }, [this, h](){ GH.windows().createAndPushWindow<CRClickPopupInt>(std::make_shared<CHeroWindow>(inviteableHeroes[h.first])); }));
|
||||
|
||||
if(x > 0 && x % 15 == 0)
|
||||
{
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
else
|
||||
x++;
|
||||
}
|
||||
|
||||
center();
|
||||
}
|
||||
|
||||
static const std::string QUICK_EXCHANGE_MOD_PREFIX = "quick-exchange";
|
||||
static const std::string QUICK_EXCHANGE_BG = QUICK_EXCHANGE_MOD_PREFIX + "/TRADEQE";
|
||||
|
||||
|
@ -36,6 +36,8 @@ class CTextBox;
|
||||
class CGarrisonInt;
|
||||
class CGarrisonSlot;
|
||||
class CHeroArea;
|
||||
class CAnimImage;
|
||||
class CFilledTexture;
|
||||
|
||||
enum class EUserEvent;
|
||||
|
||||
@ -206,10 +208,13 @@ public:
|
||||
std::string description; // "XXX is a level Y ZZZ with N artifacts"
|
||||
const CGHeroInstance * h;
|
||||
|
||||
std::function<void()> onChoose;
|
||||
|
||||
void clickPressed(const Point & cursorPosition) override;
|
||||
void clickDouble(const Point & cursorPosition) override;
|
||||
void showPopupWindow(const Point & cursorPosition) override;
|
||||
void hover (bool on) override;
|
||||
HeroPortrait(int & sel, int id, int x, int y, const CGHeroInstance * H);
|
||||
HeroPortrait(int & sel, int id, int x, int y, const CGHeroInstance * H, std::function<void()> OnChoose = nullptr);
|
||||
|
||||
private:
|
||||
int *_sel;
|
||||
@ -218,6 +223,21 @@ public:
|
||||
std::shared_ptr<CAnimImage> portrait;
|
||||
};
|
||||
|
||||
class HeroSelector : public CWindowObject
|
||||
{
|
||||
public:
|
||||
std::shared_ptr<CFilledTexture> background;
|
||||
|
||||
HeroSelector(std::map<HeroTypeID, CGHeroInstance*> InviteableHeroes, std::function<void(CGHeroInstance*)> OnChoose);
|
||||
|
||||
private:
|
||||
std::map<HeroTypeID, CGHeroInstance*> inviteableHeroes;
|
||||
std::function<void(CGHeroInstance*)> onChoose;
|
||||
|
||||
std::vector<std::shared_ptr<CAnimImage>> portraits;
|
||||
std::vector<std::shared_ptr<LRClickableArea>> portraitAreas;
|
||||
};
|
||||
|
||||
//recruitable heroes
|
||||
std::shared_ptr<HeroPortrait> h1;
|
||||
std::shared_ptr<HeroPortrait> h2; //recruitable heroes
|
||||
@ -237,6 +257,13 @@ public:
|
||||
std::shared_ptr<CTextBox> heroDescription;
|
||||
|
||||
std::shared_ptr<CTextBox> rumor;
|
||||
|
||||
std::shared_ptr<CLabel> inviteHero;
|
||||
std::shared_ptr<CAnimImage> inviteHeroImage;
|
||||
std::shared_ptr<LRClickableArea> inviteHeroImageArea;
|
||||
std::map<HeroTypeID, CGHeroInstance*> inviteableHeroes;
|
||||
CGHeroInstance* heroToInvite;
|
||||
void addInvite();
|
||||
|
||||
CTavernWindow(const CGObjectInstance * TavernObj, const std::function<void()> & onWindowClosed);
|
||||
~CTavernWindow();
|
||||
|
@ -2,7 +2,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
||||
if(NOT DEFINED MAIN_LIB_DIR)
|
||||
set(MAIN_LIB_DIR "${CMAKE_SOURCE_DIR}/lib")
|
||||
endif()
|
||||
|
||||
|
||||
set(lib_SRCS
|
||||
${MAIN_LIB_DIR}/StdInc.cpp
|
||||
|
||||
@ -268,13 +268,13 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
||||
${MAIN_LIB_DIR}/VCMI_Lib.cpp
|
||||
)
|
||||
|
||||
# Version.cpp is a generated file
|
||||
# Version.cpp is a generated file
|
||||
if(ENABLE_GITVERSION)
|
||||
list(APPEND lib_SRCS ${CMAKE_BINARY_DIR}/Version.cpp)
|
||||
set_source_files_properties(${CMAKE_BINARY_DIR}/Version.cpp
|
||||
PROPERTIES GENERATED TRUE
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(lib_HEADERS
|
||||
${MAIN_LIB_DIR}/../include/vstd/CLoggerBase.h
|
||||
@ -567,6 +567,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
||||
${MAIN_LIB_DIR}/serializer/JsonSerializer.h
|
||||
${MAIN_LIB_DIR}/serializer/JsonUpdater.h
|
||||
${MAIN_LIB_DIR}/serializer/Cast.h
|
||||
${MAIN_LIB_DIR}/serializer/ESerializationVersion.h
|
||||
|
||||
${MAIN_LIB_DIR}/spells/AbilityCaster.h
|
||||
${MAIN_LIB_DIR}/spells/AdventureSpellMechanics.h
|
||||
@ -628,6 +629,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
||||
${MAIN_LIB_DIR}/CStopWatch.h
|
||||
${MAIN_LIB_DIR}/CThreadHelper.h
|
||||
${MAIN_LIB_DIR}/CTownHandler.h
|
||||
${MAIN_LIB_DIR}/ExtraOptionsInfo.h
|
||||
${MAIN_LIB_DIR}/FunctionList.h
|
||||
${MAIN_LIB_DIR}/GameCallbackHolder.h
|
||||
${MAIN_LIB_DIR}/GameConstants.h
|
||||
@ -663,7 +665,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
||||
${MAIN_LIB_DIR}/VCMI_Lib.h
|
||||
)
|
||||
|
||||
assign_source_group(${lib_SRCS} ${lib_HEADERS})
|
||||
assign_source_group(${lib_SRCS} ${lib_HEADERS})
|
||||
|
||||
add_library(${TARGET_NAME} ${LIBRARY_TYPE} ${lib_SRCS} ${lib_HEADERS})
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES COMPILE_DEFINITIONS "VCMI_DLL=1")
|
||||
@ -671,7 +673,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
||||
minizip::minizip ZLIB::ZLIB
|
||||
${SYSTEM_LIBS} Boost::boost Boost::thread Boost::filesystem Boost::program_options Boost::locale Boost::date_time
|
||||
)
|
||||
if(APPLE_IOS)
|
||||
if(APPLE_IOS)
|
||||
target_link_libraries(${TARGET_NAME} PUBLIC iOS_utils)
|
||||
endif()
|
||||
|
||||
@ -682,13 +684,13 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
||||
PUBLIC ${MAIN_LIB_DIR}
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
if(WIN32)
|
||||
set_target_properties(${TARGET_NAME}
|
||||
PROPERTIES
|
||||
OUTPUT_NAME "VCMI_lib"
|
||||
OUTPUT_NAME "VCMI_lib"
|
||||
PROJECT_LABEL "VCMI_lib"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
vcmi_set_output_dir(${TARGET_NAME} "")
|
||||
|
||||
@ -702,7 +704,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake_modules/create_link.cmake ${MAIN_LIB_DIR}/../config ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/config
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake_modules/create_link.cmake ${MAIN_LIB_DIR}/../Mods ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/Mods
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Update version before vcmi compiling
|
||||
if(TARGET update_version)
|
||||
|
@ -149,7 +149,7 @@
|
||||
{
|
||||
"graphics":
|
||||
{
|
||||
"icon": "zvs/Lib1.res/E_RDEF"
|
||||
"icon": "zvs/Lib1.res/E_RATT"
|
||||
}
|
||||
},
|
||||
|
||||
@ -197,7 +197,7 @@
|
||||
{
|
||||
"graphics":
|
||||
{
|
||||
"icon": ""
|
||||
"icon": "zvs/Lib1.res/Ferocity"
|
||||
}
|
||||
},
|
||||
|
||||
@ -448,7 +448,7 @@
|
||||
{
|
||||
"graphics":
|
||||
{
|
||||
"icon": ""
|
||||
"icon": "zvs/Lib1.res/Revenge"
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
},
|
||||
"king":
|
||||
{
|
||||
"resources": { "wood" : 0, "mercury": 0, "ore": 0 , "sulfur": 0, "crystal": 0, "gems": 0, "gold": 0, "mithril": 0 },
|
||||
"resources": { "wood" : 0, "mercury": 0, "ore": 0, "sulfur": 0, "crystal": 0, "gems": 0, "gold": 0, "mithril": 0 },
|
||||
"globalBonuses": [],
|
||||
"battleBonuses": []
|
||||
}
|
||||
|
@ -289,7 +289,9 @@
|
||||
// Chances for a hero with default army to receive corresponding stack out of his predefined starting troops
|
||||
"startingStackChances": [ 100, 88, 25],
|
||||
// number of artifacts that can fit in a backpack. -1 is unlimited.
|
||||
"backpackSize" : -1
|
||||
"backpackSize" : -1,
|
||||
// if heroes are invitable in tavern
|
||||
"tavernInvite" : false
|
||||
},
|
||||
|
||||
"towns":
|
||||
|
@ -64,12 +64,14 @@
|
||||
"name": "buttonCheatAllowed",
|
||||
"image": "lobby/checkbox",
|
||||
"callback" : "setCheatAllowed",
|
||||
"help" : "vcmi.optionsTab.cheatAllowed",
|
||||
"selected" : true
|
||||
},
|
||||
{
|
||||
"name": "buttonUnlimitedReplay",
|
||||
"image": "lobby/checkbox",
|
||||
"callback" : "setUnlimitedReplay",
|
||||
"help" : "vcmi.optionsTab.unlimitedReplay",
|
||||
"selected" : true
|
||||
}
|
||||
]
|
||||
|
6
debian/changelog
vendored
6
debian/changelog
vendored
@ -4,6 +4,12 @@ vcmi (1.5.0) jammy; urgency=medium
|
||||
|
||||
-- Ivan Savenko <saven.ivan@gmail.com> Fri, 1 Mar 2024 12:00:00 +0200
|
||||
|
||||
vcmi (1.4.5) jammy; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
|
||||
-- Ivan Savenko <saven.ivan@gmail.com> Tue, 23 Jan 2024 12:00:00 +0200
|
||||
|
||||
vcmi (1.4.4) jammy; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
|
@ -2,7 +2,7 @@
|
||||
[![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/1.4.0/total)](https://github.com/vcmi/vcmi/releases/tag/1.4.0)
|
||||
[![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/1.4.1/total)](https://github.com/vcmi/vcmi/releases/tag/1.4.1)
|
||||
[![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/1.4.2/total)](https://github.com/vcmi/vcmi/releases/tag/1.4.2)
|
||||
[![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/1.4.3/total)](https://github.com/vcmi/vcmi/releases/tag/1.4.3)
|
||||
[![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/1.4.4/total)](https://github.com/vcmi/vcmi/releases/tag/1.4.4)
|
||||
[![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/total)](https://github.com/vcmi/vcmi/releases)
|
||||
|
||||
# VCMI Project
|
||||
|
@ -77,6 +77,7 @@
|
||||
</screenshots>
|
||||
<releases>
|
||||
<release version="1.5.0" date="2024-03-01" type="development"/>
|
||||
<release version="1.4.5" date="2024-01-23" type="stable"/>
|
||||
<release version="1.4.4" date="2024-01-20" type="stable"/>
|
||||
<release version="1.4.3" date="2024-01-19" type="stable"/>
|
||||
<release version="1.4.2" date="2023-12-25" type="stable"/>
|
||||
|
@ -38,6 +38,9 @@ bool CModEntry::isEnabled() const
|
||||
if(!isInstalled())
|
||||
return false;
|
||||
|
||||
if (!isVisible())
|
||||
return false;
|
||||
|
||||
return modSettings["active"].toBool();
|
||||
}
|
||||
|
||||
|
@ -521,7 +521,7 @@ QStringList CModListView::findDependentMods(QString mod, bool excludeDisabled)
|
||||
{
|
||||
auto current = modModel->getMod(modName);
|
||||
|
||||
if(!current.isInstalled())
|
||||
if(!current.isInstalled() || !current.isVisible())
|
||||
continue;
|
||||
|
||||
if(current.getDependencies().contains(mod, Qt::CaseInsensitive))
|
||||
|
@ -6,84 +6,84 @@
|
||||
<message>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="22"/>
|
||||
<source>VCMI on Discord</source>
|
||||
<translation type="unfinished">VCMI en Discord</translation>
|
||||
<translation>VCMI en Discord</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="29"/>
|
||||
<source>Have a question? Found a bug? Want to help? Join us!</source>
|
||||
<translation type="unfinished">¿Tienes alguna pregunta? ¿Encontraste algún error? ¿Quieres ayudar? ¡Únete a nosotros!</translation>
|
||||
<translation>¿Tienes alguna pregunta? ¿Encontraste algún error? ¿Quieres ayudar? ¡Únete a nosotros!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="36"/>
|
||||
<source>VCMI on Github</source>
|
||||
<translation type="unfinished">VCMI en Github</translation>
|
||||
<translation>VCMI en Github</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="55"/>
|
||||
<source>Our Community</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Nuestra comunidad</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="62"/>
|
||||
<source>VCMI on Slack</source>
|
||||
<translation type="unfinished">VCMI en Slack</translation>
|
||||
<translation>VCMI en Slack</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="98"/>
|
||||
<source>Build Information</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Información de la versión</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="115"/>
|
||||
<source>User data directory</source>
|
||||
<translation type="unfinished">Directorio de datos del usuario</translation>
|
||||
<translation>Directorio de datos del usuario</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="122"/>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="129"/>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="193"/>
|
||||
<source>Open</source>
|
||||
<translation type="unfinished">Abrir</translation>
|
||||
<translation>Abrir</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="136"/>
|
||||
<source>Check for updates</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Comprobar actualizaciones</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="156"/>
|
||||
<source>Game version</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Versión del juego</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="163"/>
|
||||
<source>Log files directory</source>
|
||||
<translation type="unfinished">Directorio de archivos de registro</translation>
|
||||
<translation>Directorio de archivos de registro</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="176"/>
|
||||
<source>Data Directories</source>
|
||||
<translation type="unfinished">Directorios de datos</translation>
|
||||
<translation>Directorios de datos</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="213"/>
|
||||
<source>Game data directory</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Directorio de los datos del juego</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="220"/>
|
||||
<source>Operating System</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Sistema operativo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="273"/>
|
||||
<source>Project homepage</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Página web del proyecto</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../aboutProject/aboutproject_moc.ui" line="286"/>
|
||||
<source>Report a bug</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Informar de un error</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -121,7 +121,7 @@
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistmodel_moc.cpp" line="48"/>
|
||||
<source>Maps</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Mapas</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistmodel_moc.cpp" line="49"/>
|
||||
@ -180,7 +180,7 @@
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistmodel_moc.cpp" line="62"/>
|
||||
<source>Compatibility</source>
|
||||
<translation type="unfinished">Compatibilidad</translation>
|
||||
<translation>Compatibilidad</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistmodel_moc.cpp" line="63"/>
|
||||
@ -319,7 +319,7 @@
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="292"/>
|
||||
<source>Size</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Tamaño</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="294"/>
|
||||
@ -410,12 +410,12 @@
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="638"/>
|
||||
<source>Downloading %s%. %p% (%v MB out of %m MB) finished</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Descargando %s%. %p% (%v MB de %m MB) completado</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="665"/>
|
||||
<source>Download failed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Descarga fallida</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="666"/>
|
||||
@ -424,30 +424,37 @@
|
||||
Encountered errors:
|
||||
|
||||
</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>No se han podido descargar todos los ficheros.
|
||||
|
||||
Errores encontrados:
|
||||
|
||||
</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="667"/>
|
||||
<source>
|
||||
|
||||
Install successfully downloaded?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>
|
||||
|
||||
Instalar lo correctamente descargado?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="812"/>
|
||||
<source>Installing mod %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Instalando mod %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="874"/>
|
||||
<source>Operation failed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Operación fallida</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="875"/>
|
||||
<source>Encountered errors:
|
||||
</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Errores encontrados:
|
||||
</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="910"/>
|
||||
@ -482,94 +489,94 @@ Install successfully downloaded?</source>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="230"/>
|
||||
<source>Interface Scaling</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Escala de la interfaz</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="394"/>
|
||||
<source>Neutral AI in battles</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>IA neutral en batallas</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="169"/>
|
||||
<source>Enemy AI in battles</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>IA enemiga en batallas</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="176"/>
|
||||
<source>Additional repository</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Repositorio adicional</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="210"/>
|
||||
<source>Adventure Map Allies</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Aliados en el Mapa de aventuras</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="552"/>
|
||||
<source>Adventure Map Enemies</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Enemigos en el Mapa de aventuras</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="428"/>
|
||||
<source>Windowed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Ventana</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="433"/>
|
||||
<source>Borderless fullscreen</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Ventana completa sin bordes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="438"/>
|
||||
<source>Exclusive fullscreen</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Pantalla completa</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="593"/>
|
||||
<source>Autosave limit (0 = off)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Límite de autosaves (0 = sin límite)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="401"/>
|
||||
<source>Friendly AI in battles</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>IA amistosa en batallas</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="370"/>
|
||||
<source>Framerate Limit</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Límite de fotogramas</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="460"/>
|
||||
<source>Autosave prefix</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Prefijo autoguardado</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="484"/>
|
||||
<source>empty = map name prefix</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Vacio = prefijo del mapa</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="607"/>
|
||||
<source>Refresh now</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Actualizar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="614"/>
|
||||
<source>Default repository</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Repositorio por defecto</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="624"/>
|
||||
<source>Renderer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Render</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="246"/>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="476"/>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="544"/>
|
||||
<source>On</source>
|
||||
<translation>Encendido</translation>
|
||||
<translation>Activado</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="115"/>
|
||||
@ -584,7 +591,7 @@ Install successfully downloaded?</source>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="349"/>
|
||||
<source>Reserved screen area</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Área de pantalla reservada</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="155"/>
|
||||
@ -614,7 +621,7 @@ Install successfully downloaded?</source>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="562"/>
|
||||
<source>VSync</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Sincronización vertical</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="135"/>
|
||||
@ -640,7 +647,13 @@ Windowed - game will run inside a window that covers part of your screen
|
||||
Borderless Windowed Mode - game will run in a window that covers entirely of your screen, using same resolution as your screen.
|
||||
|
||||
Fullscreen Exclusive Mode - game will cover entirety of your screen and will use selected resolution.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Selecciona el modo de visualización del juego
|
||||
|
||||
En ventana - el juego se ejecutará dentro de una ventana que forma parte de tu pantalla.
|
||||
|
||||
Ventana sin bordes - el juego se ejecutará en una ventana que cubre completamente tu pantalla, usando la misma resolución.
|
||||
|
||||
Pantalla completa - el juego cubrirá la totalidad de la pantalla y utilizará la resolución seleccionada.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="522"/>
|
||||
@ -764,12 +777,12 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.ui" line="702"/>
|
||||
<source>Interface Improvements</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Mejora de la interfaz</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.ui" line="772"/>
|
||||
<source>Install mod that provides various interface improvements, such as better interface for random maps and selectable actions in battles</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Instalar mod que proporciona varias mejoras en la interfaz, como mejor interacción en los mapas aleatorios y más opciones en las batallas</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.ui" line="127"/>
|
||||
@ -882,12 +895,12 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.cpp" line="143"/>
|
||||
<source>Heroes III installation found!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Instalación de Heroes III encontrada!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.cpp" line="143"/>
|
||||
<source>Copy data to VCMI folder?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Copiar datos a la carpeta VCMI?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -903,7 +916,7 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi
|
||||
<message>
|
||||
<location filename="../languages.cpp" line="23"/>
|
||||
<source>Czech</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Czech (Checo)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../languages.cpp" line="24"/>
|
||||
@ -918,7 +931,7 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi
|
||||
<message>
|
||||
<location filename="../languages.cpp" line="26"/>
|
||||
<source>Finnish</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Finnish (Finlandés)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../languages.cpp" line="27"/>
|
||||
@ -933,12 +946,12 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi
|
||||
<message>
|
||||
<location filename="../languages.cpp" line="29"/>
|
||||
<source>Hungarian</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Hungarian (Húngaro)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../languages.cpp" line="30"/>
|
||||
<source>Italian</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Italian (Italiano)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../languages.cpp" line="31"/>
|
||||
@ -953,7 +966,7 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi
|
||||
<message>
|
||||
<location filename="../languages.cpp" line="33"/>
|
||||
<source>Portuguese</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Portuguese (Portugués)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../languages.cpp" line="34"/>
|
||||
@ -968,12 +981,12 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi
|
||||
<message>
|
||||
<location filename="../languages.cpp" line="36"/>
|
||||
<source>Swedish</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Swedish (Sueco)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../languages.cpp" line="37"/>
|
||||
<source>Turkish</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Turkish (Turco)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../languages.cpp" line="38"/>
|
||||
@ -983,7 +996,7 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi
|
||||
<message>
|
||||
<location filename="../languages.cpp" line="39"/>
|
||||
<source>Vietnamese</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Vietnamese (Vietnamita)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../languages.cpp" line="40"/>
|
||||
@ -993,12 +1006,12 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi
|
||||
<message>
|
||||
<location filename="../languages.cpp" line="41"/>
|
||||
<source>Other (Cyrillic Script)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Otro (Escritura cirílica)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../languages.cpp" line="42"/>
|
||||
<source>Other (West European)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Otro (Europa del Este)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../languages.cpp" line="64"/>
|
||||
@ -1021,7 +1034,7 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi
|
||||
<message>
|
||||
<location filename="../mainwindow_moc.ui" line="157"/>
|
||||
<source>Help</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Ayuda</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow_moc.ui" line="226"/>
|
||||
|
@ -179,7 +179,7 @@ struct DLL_LINKAGE ArtSlotInfo
|
||||
ArtSlotInfo() : locked(false) {}
|
||||
const CArtifactInstance * getArt() const;
|
||||
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & artifact;
|
||||
h & locked;
|
||||
@ -223,7 +223,7 @@ public:
|
||||
virtual void removeArtifact(ArtifactPosition slot);
|
||||
virtual ~CArtifactSet();
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & artifactsInBackpack;
|
||||
h & artifactsWorn;
|
||||
|
@ -27,7 +27,7 @@ public:
|
||||
{
|
||||
ConstTransitivePtr<CArtifactInstance> art;
|
||||
ArtifactPosition slot;
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & art;
|
||||
h & slot;
|
||||
@ -41,7 +41,7 @@ public:
|
||||
const std::vector<PartInfo> & getPartsInfo() const;
|
||||
void addPlacementMap(CArtifactSet::ArtPlacementMap & placementMap);
|
||||
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & partsInfo;
|
||||
}
|
||||
@ -93,7 +93,7 @@ public:
|
||||
void move(CArtifactSet & srcSet, const ArtifactPosition srcSlot, CArtifactSet & dstSet, const ArtifactPosition dstSlot);
|
||||
|
||||
void deserializationFix();
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & static_cast<CBonusSystemNode&>(*this);
|
||||
h & static_cast<CCombinedArtifactInstance&>(*this);
|
||||
|
@ -76,10 +76,10 @@ std::string CBonusTypeHandler::bonusToString(const std::shared_ptr<Bonus> & bonu
|
||||
if (text.find("${val}") != std::string::npos)
|
||||
boost::algorithm::replace_all(text, "${val}", std::to_string(bearer->valOfBonuses(Selector::typeSubtype(bonus->type, bonus->subtype))));
|
||||
|
||||
if (text.find("${subtype.creature}") != std::string::npos && bonus->subtype.as<CreatureID>() != CreatureID::NONE)
|
||||
if (text.find("${subtype.creature}") != std::string::npos && bonus->subtype.as<CreatureID>().hasValue())
|
||||
boost::algorithm::replace_all(text, "${subtype.creature}", bonus->subtype.as<CreatureID>().toCreature()->getNamePluralTranslated());
|
||||
|
||||
if (text.find("${subtype.spell}") != std::string::npos && bonus->subtype.as<SpellID>() != SpellID::NONE)
|
||||
if (text.find("${subtype.spell}") != std::string::npos && bonus->subtype.as<SpellID>().hasValue())
|
||||
boost::algorithm::replace_all(text, "${subtype.spell}", bonus->subtype.as<SpellID>().toSpell()->getNameTranslated());
|
||||
|
||||
return text;
|
||||
@ -95,8 +95,11 @@ ImagePath CBonusTypeHandler::bonusToGraphics(const std::shared_ptr<Bonus> & bonu
|
||||
case BonusType::SPELL_IMMUNITY:
|
||||
{
|
||||
fullPath = true;
|
||||
const CSpell * sp = bonus->subtype.as<SpellID>().toSpell();
|
||||
fileName = sp->getIconImmune();
|
||||
if (bonus->subtype.as<SpellID>().hasValue())
|
||||
{
|
||||
const CSpell * sp = bonus->subtype.as<SpellID>().toSpell();
|
||||
fileName = sp->getIconImmune();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BonusType::SPELL_DAMAGE_REDUCTION: //Spell damage reduction for all schools
|
||||
|
@ -27,7 +27,7 @@ public:
|
||||
std::string getNameTextID() const;
|
||||
std::string getDescriptionTextID() const;
|
||||
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & icon;
|
||||
h & identifier;
|
||||
@ -53,7 +53,7 @@ public:
|
||||
std::string bonusToString(const std::shared_ptr<Bonus> & bonus, const IBonusBearer * bearer, bool description) const override;
|
||||
ImagePath bonusToGraphics(const std::shared_ptr<Bonus> & bonus) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
//for now always use up to date configuration
|
||||
//once modded bonus type will be implemented, serialize only them
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
|
||||
friend bool operator== (const CStackBasicDescriptor & l, const CStackBasicDescriptor & r);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
if(h.saving)
|
||||
{
|
||||
@ -85,7 +85,7 @@ public:
|
||||
const CArmedInstance * const & armyObj; //stack must be part of some army, army must be part of some object
|
||||
TExpType experience;//commander needs same amount of exp as hero
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & static_cast<CBonusSystemNode&>(*this);
|
||||
h & static_cast<CStackBasicDescriptor&>(*this);
|
||||
@ -157,7 +157,7 @@ public:
|
||||
int getLevel() const override;
|
||||
ArtBearer::ArtBearer bearerType() const override; //from CArtifactSet
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & static_cast<CStackInstance&>(*this);
|
||||
h & alive;
|
||||
@ -197,7 +197,7 @@ public:
|
||||
bool setCreature(SlotID slot, CreatureID cre, TQuantity count) override;
|
||||
operator bool() const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & army;
|
||||
}
|
||||
@ -280,7 +280,7 @@ public:
|
||||
bool contains(const CStackInstance *stack) const;
|
||||
bool canBeMergedWith(const CCreatureSet &cs, bool allowMergingStacks = true) const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & stacks;
|
||||
h & formation;
|
||||
|
@ -243,9 +243,8 @@ void CAdventureAI::yourTacticPhase(const BattleID & battleID, int distance)
|
||||
battleAI->yourTacticPhase(battleID, distance);
|
||||
}
|
||||
|
||||
void CAdventureAI::saveGame(BinarySerializer & h, const int version) /*saving */
|
||||
void CAdventureAI::saveGame(BinarySerializer & h) /*saving */
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "version '%i'", version);
|
||||
bool hasBattleAI = static_cast<bool>(battleAI);
|
||||
h & hasBattleAI;
|
||||
if(hasBattleAI)
|
||||
@ -254,9 +253,8 @@ void CAdventureAI::saveGame(BinarySerializer & h, const int version) /*saving */
|
||||
}
|
||||
}
|
||||
|
||||
void CAdventureAI::loadGame(BinaryDeserializer & h, const int version) /*loading */
|
||||
void CAdventureAI::loadGame(BinaryDeserializer & h) /*loading */
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "version '%i'", version);
|
||||
bool hasBattleAI = false;
|
||||
h & hasBattleAI;
|
||||
if(hasBattleAI)
|
||||
|
@ -111,8 +111,8 @@ public:
|
||||
|
||||
virtual std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState) = 0;
|
||||
|
||||
virtual void saveGame(BinarySerializer & h, const int version) = 0;
|
||||
virtual void loadGame(BinaryDeserializer & h, const int version) = 0;
|
||||
virtual void saveGame(BinarySerializer & h) = 0;
|
||||
virtual void loadGame(BinaryDeserializer & h) = 0;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CDynLibHandler
|
||||
@ -162,8 +162,8 @@ public:
|
||||
virtual void battleEnd(const BattleID & battleID, const BattleResult *br, QueryID queryID) override;
|
||||
virtual void battleUnitsChanged(const BattleID & battleID, const std::vector<UnitChanges> & units) override;
|
||||
|
||||
virtual void saveGame(BinarySerializer & h, const int version) override;
|
||||
virtual void loadGame(BinaryDeserializer & h, const int version) override;
|
||||
virtual void saveGame(BinarySerializer & h) override;
|
||||
virtual void loadGame(BinaryDeserializer & h) override;
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -135,7 +135,7 @@ protected:
|
||||
std::string modContext;
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler & h, const int Version)
|
||||
void serialize(Handler & h)
|
||||
{
|
||||
h & baseValue;
|
||||
h & baseLanguage;
|
||||
@ -193,7 +193,7 @@ public:
|
||||
void jsonSerialize(JsonNode & dest) const;
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler & h, const int Version)
|
||||
void serialize(Handler & h)
|
||||
{
|
||||
std::string key;
|
||||
auto sz = stringsLocalizations.size();
|
||||
|
@ -40,10 +40,10 @@ struct DLL_LINKAGE PlayerState : public CBonusSystemNode, public Player
|
||||
return subID < other.subID;
|
||||
}
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & id;
|
||||
subID.serializeIdentifier(h, id, version);
|
||||
subID.serializeIdentifier(h, id);
|
||||
}
|
||||
};
|
||||
|
||||
@ -89,7 +89,7 @@ public:
|
||||
return heroes.empty() && towns.empty();
|
||||
}
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & color;
|
||||
h & human;
|
||||
@ -123,7 +123,7 @@ public:
|
||||
|
||||
TeamState();
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & id;
|
||||
h & players;
|
||||
|
@ -87,7 +87,7 @@ private:
|
||||
|
||||
public:
|
||||
template <typename Handler>
|
||||
void serialize(Handler & h, const int version)
|
||||
void serialize(Handler & h)
|
||||
{
|
||||
if(h.saving)
|
||||
{
|
||||
|
@ -93,7 +93,7 @@ public:
|
||||
return this->owner;
|
||||
}
|
||||
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
//this assumes that stack objects is newly created
|
||||
//stackState is not serialized here
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
{}
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler &h, const int version)
|
||||
void serialize(Handler &h)
|
||||
{
|
||||
h & r;
|
||||
h & g;
|
||||
|
@ -69,7 +69,7 @@ public:
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & ptr;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ struct DLL_LINKAGE ExtraOptionsInfo
|
||||
bool operator == (const ExtraOptionsInfo & other) const;
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler &h, const int version)
|
||||
void serialize(Handler &h)
|
||||
{
|
||||
h & cheatsAllowed;
|
||||
h & unlimitedReplay;
|
||||
|
@ -74,6 +74,7 @@ void GameSettings::load(const JsonNode & input)
|
||||
{EGameSettings::HEROES_RETREAT_ON_WIN_WITHOUT_TROOPS, "heroes", "retreatOnWinWithoutTroops" },
|
||||
{EGameSettings::HEROES_STARTING_STACKS_CHANCES, "heroes", "startingStackChances" },
|
||||
{EGameSettings::HEROES_BACKPACK_CAP, "heroes", "backpackSize" },
|
||||
{EGameSettings::HEROES_TAVERN_INVITE, "heroes", "tavernInvite" },
|
||||
{EGameSettings::MAP_FORMAT_RESTORATION_OF_ERATHIA, "mapFormat", "restorationOfErathia" },
|
||||
{EGameSettings::MAP_FORMAT_ARMAGEDDONS_BLADE, "mapFormat", "armageddonsBlade" },
|
||||
{EGameSettings::MAP_FORMAT_SHADOW_OF_DEATH, "mapFormat", "shadowOfDeath" },
|
||||
|
@ -38,6 +38,7 @@ enum class EGameSettings
|
||||
HEROES_RETREAT_ON_WIN_WITHOUT_TROOPS,
|
||||
HEROES_STARTING_STACKS_CHANCES,
|
||||
HEROES_BACKPACK_CAP,
|
||||
HEROES_TAVERN_INVITE,
|
||||
MARKETS_BLACK_MARKET_RESTOCK_PERIOD,
|
||||
BANKS_SHOW_GUARDS_COMPOSITION,
|
||||
MODULE_COMMANDERS,
|
||||
@ -96,7 +97,7 @@ public:
|
||||
const JsonNode & getValue(EGameSettings option) const override;
|
||||
|
||||
template<typename Handler>
|
||||
void serialize(Handler & h, const int version)
|
||||
void serialize(Handler & h)
|
||||
{
|
||||
h & gameSettings;
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ public:
|
||||
|
||||
std::string toJson(bool compact = false) const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & meta;
|
||||
h & flags;
|
||||
|
@ -80,7 +80,7 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
IdentifierType JsonRandom::decodeKey(const std::string & modScope, const std::string & value, const Variables & variables)
|
||||
{
|
||||
if (value.empty() || value[0] != '@')
|
||||
return IdentifierType(*VLC->identifiers()->getIdentifier(modScope, IdentifierType::entityType(), value));
|
||||
return IdentifierType(VLC->identifiers()->getIdentifier(modScope, IdentifierType::entityType(), value).value_or(-1));
|
||||
else
|
||||
return loadVariable(IdentifierType::entityType(), value, variables, IdentifierType::NONE);
|
||||
}
|
||||
@ -89,7 +89,7 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
IdentifierType JsonRandom::decodeKey(const JsonNode & value, const Variables & variables)
|
||||
{
|
||||
if (value.String().empty() || value.String()[0] != '@')
|
||||
return IdentifierType(*VLC->identifiers()->getIdentifier(IdentifierType::entityType(), value));
|
||||
return IdentifierType(VLC->identifiers()->getIdentifier(IdentifierType::entityType(), value).value_or(-1));
|
||||
else
|
||||
return loadVariable(IdentifierType::entityType(), value.String(), variables, IdentifierType::NONE);
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ namespace LogicalExpressionDetail
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler & h, const int version)
|
||||
void serialize(Handler & h)
|
||||
{
|
||||
h & expressions;
|
||||
}
|
||||
@ -614,7 +614,7 @@ public:
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler & h, const int version)
|
||||
void serialize(Handler & h)
|
||||
{
|
||||
h & data;
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ public:
|
||||
|
||||
void serializeJson(JsonSerializeFormat & handler);
|
||||
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & exactStrings;
|
||||
h & localStrings;
|
||||
|
@ -122,7 +122,7 @@ public:
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler &h, const int version)
|
||||
void serialize(Handler &h)
|
||||
{
|
||||
h & x;
|
||||
h & y;
|
||||
|
@ -163,7 +163,7 @@ public:
|
||||
DLL_LINKAGE Rect include(const Rect & other) const;
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler &h, const int version)
|
||||
void serialize(Handler &h)
|
||||
{
|
||||
h & x;
|
||||
h & y;
|
||||
|
@ -180,7 +180,7 @@ public:
|
||||
// return true;
|
||||
// }
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & container;
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ public:
|
||||
|
||||
void run(std::shared_ptr<Pool> pool) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
JsonNode state;
|
||||
if(h.saving)
|
||||
|
@ -41,7 +41,7 @@ struct DLL_LINKAGE SimturnsInfo
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler &h, const int version)
|
||||
void serialize(Handler &h)
|
||||
{
|
||||
h & requiredTurns;
|
||||
h & optionalTurns;
|
||||
@ -76,7 +76,7 @@ struct DLL_LINKAGE PlayerSettings
|
||||
std::set<ui8> connectedPlayerIDs; //Empty - AI, or connectrd player ids
|
||||
bool compOnly; //true if this player is a computer only player; required for RMG
|
||||
template <typename Handler>
|
||||
void serialize(Handler &h, const int version)
|
||||
void serialize(Handler &h)
|
||||
{
|
||||
h & castle;
|
||||
h & hero;
|
||||
@ -137,7 +137,7 @@ struct DLL_LINKAGE StartInfo
|
||||
std::string getCampaignName() const;
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler &h, const int version)
|
||||
void serialize(Handler &h)
|
||||
{
|
||||
h & mode;
|
||||
h & difficulty;
|
||||
@ -149,7 +149,7 @@ struct DLL_LINKAGE StartInfo
|
||||
h & fileURI;
|
||||
h & simturnsInfo;
|
||||
h & turnTimerInfo;
|
||||
if(version >= 832)
|
||||
if(h.version >= Handler::Version::HAS_EXTRA_OPTIONS)
|
||||
h & extraOptionsInfo;
|
||||
else
|
||||
extraOptionsInfo = ExtraOptionsInfo();
|
||||
@ -170,7 +170,7 @@ struct ClientPlayer
|
||||
int connection;
|
||||
std::string name;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & connection;
|
||||
h & name;
|
||||
@ -190,7 +190,7 @@ struct DLL_LINKAGE LobbyState
|
||||
|
||||
LobbyState() : si(new StartInfo()), hostClientId(-1), campaignMap(CampaignScenarioID::NONE), campaignBonus(-1) {}
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & si;
|
||||
h & mi;
|
||||
|
@ -26,7 +26,7 @@ struct DLL_LINKAGE TerrainPaletteAnimation
|
||||
/// total numbers of colors to cycle
|
||||
int32_t length;
|
||||
|
||||
template <typename Handler> void serialize(Handler& h, const int version)
|
||||
template <typename Handler> void serialize(Handler& h)
|
||||
{
|
||||
h & start;
|
||||
h & length;
|
||||
|
@ -34,7 +34,7 @@ struct DLL_LINKAGE TurnTimerInfo
|
||||
bool operator == (const TurnTimerInfo & other) const;
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler &h, const int version)
|
||||
void serialize(Handler &h)
|
||||
{
|
||||
h & turnTimer;
|
||||
h & baseTimer;
|
||||
|
@ -55,7 +55,7 @@ public:
|
||||
battle::Target getTarget(const CBattleInfoCallback * cb) const;
|
||||
void setTarget(const battle::Target & target_);
|
||||
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & side;
|
||||
h & stackNumber;
|
||||
@ -70,7 +70,7 @@ private:
|
||||
int32_t unitValue;
|
||||
BattleHex hexValue;
|
||||
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & unitValue;
|
||||
h & hexValue;
|
||||
|
@ -105,7 +105,7 @@ struct DLL_LINKAGE BattleHex //TODO: decide if this should be changed to class f
|
||||
static BattleHex getClosestTile(ui8 side, BattleHex initialPos, std::set<BattleHex> & possibilities); //TODO: vector or set? copying one to another is bad
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler &h, const int version)
|
||||
void serialize(Handler &h)
|
||||
{
|
||||
h & hex;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
ui8 tacticsSide; //which side is requested to play tactics phase
|
||||
ui8 tacticDistance; //how many hexes we can go forward (1 = only hexes adjacent to margin line)
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & battleID;
|
||||
h & sides;
|
||||
@ -66,10 +66,7 @@ public:
|
||||
h & tacticsSide;
|
||||
h & tacticDistance;
|
||||
h & static_cast<CBonusSystemNode&>(*this);
|
||||
if (version > 824)
|
||||
h & replayAllowed;
|
||||
else
|
||||
replayAllowed = false;
|
||||
h & replayAllowed;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -867,9 +867,10 @@ bool CBattleInfoCallback::handleObstacleTriggersForUnit(SpellCastEnvironment & s
|
||||
auto shouldReveal = !spellObstacle->hidden || !battleIsObstacleVisibleForSide(*obstacle, (BattlePerspective::BattlePerspective)side);
|
||||
const auto * hero = battleGetFightingHero(spellObstacle->casterSide);
|
||||
auto caster = spells::ObstacleCasterProxy(getBattle()->getSidePlayer(spellObstacle->casterSide), hero, *spellObstacle);
|
||||
const auto * sp = obstacle->getTrigger().toSpell();
|
||||
if(obstacle->triggersEffects() && sp)
|
||||
|
||||
if(obstacle->triggersEffects() && obstacle->getTrigger().hasValue())
|
||||
{
|
||||
const auto * sp = obstacle->getTrigger().toSpell();
|
||||
auto cast = spells::BattleCast(this, &caster, spells::Mode::PASSIVE, sp);
|
||||
spells::detail::ProblemImpl ignored;
|
||||
auto target = spells::Target(1, spells::Destination(&unit));
|
||||
|
@ -36,7 +36,7 @@ struct DLL_LINKAGE AttackableTiles
|
||||
{
|
||||
std::set<BattleHex> hostileCreaturePositions;
|
||||
std::set<BattleHex> friendlyCreaturePositions; //for Dragon Breath
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & hostileCreaturePositions;
|
||||
h & friendlyCreaturePositions;
|
||||
|
@ -63,7 +63,7 @@ struct DLL_LINKAGE CObstacleInstance
|
||||
|
||||
virtual void serializeJson(JsonSerializeFormat & handler);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & ID;
|
||||
h & pos;
|
||||
@ -118,7 +118,7 @@ struct DLL_LINKAGE SpellCreatedObstacle : CObstacleInstance
|
||||
|
||||
void serializeJson(JsonSerializeFormat & handler) override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & static_cast<CObstacleInstance&>(*this);
|
||||
h & turnsRemaining;
|
||||
|
@ -28,7 +28,7 @@ struct DLL_LINKAGE SideInBattle
|
||||
void init(const CGHeroInstance * Hero, const CArmedInstance * Army);
|
||||
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & color;
|
||||
h & hero;
|
||||
|
@ -23,7 +23,7 @@ struct DLL_LINKAGE SiegeInfo
|
||||
// return EWallState decreased by value of damage points
|
||||
static EWallState applyDamage(EWallState state, unsigned int value);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & wallState;
|
||||
h & gateState;
|
||||
|
@ -86,7 +86,7 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>
|
||||
Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID, BonusSubtypeID subtype, BonusValueType ValType);
|
||||
Bonus() = default;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & duration;
|
||||
h & type;
|
||||
|
@ -91,7 +91,7 @@ public:
|
||||
void insert(TInternalContainer::iterator position, TInternalContainer::size_type n, const std::shared_ptr<Bonus> & x);
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler &h, const int version)
|
||||
void serialize(Handler &h)
|
||||
{
|
||||
h & static_cast<TInternalContainer&>(bonuses);
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ public:
|
||||
return PlayerColor::NEUTRAL;
|
||||
}
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & nodeType;
|
||||
h & exportedBonuses;
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
virtual std::string toString() const;
|
||||
virtual JsonNode toJsonNode() const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -53,7 +53,7 @@ public:
|
||||
void add(const TLimiterPtr & limiter);
|
||||
JsonNode toJsonNode() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & static_cast<ILimiter&>(*this);
|
||||
h & limiters;
|
||||
@ -104,7 +104,7 @@ public:
|
||||
std::string toString() const override;
|
||||
JsonNode toJsonNode() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & static_cast<ILimiter&>(*this);
|
||||
h & creature;
|
||||
@ -132,7 +132,7 @@ public:
|
||||
std::string toString() const override;
|
||||
JsonNode toJsonNode() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & static_cast<ILimiter&>(*this);
|
||||
h & type;
|
||||
@ -156,7 +156,7 @@ public:
|
||||
std::string toString() const override;
|
||||
JsonNode toJsonNode() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & static_cast<ILimiter&>(*this);
|
||||
h & terrainType;
|
||||
@ -175,7 +175,7 @@ public:
|
||||
std::string toString() const override;
|
||||
JsonNode toJsonNode() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & static_cast<ILimiter&>(*this);
|
||||
h & minLevel;
|
||||
@ -193,7 +193,7 @@ public:
|
||||
std::string toString() const override;
|
||||
JsonNode toJsonNode() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & static_cast<ILimiter&>(*this);
|
||||
h & faction;
|
||||
@ -210,7 +210,7 @@ public:
|
||||
std::string toString() const override;
|
||||
JsonNode toJsonNode() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & static_cast<ILimiter&>(*this);
|
||||
h & alignment;
|
||||
@ -225,7 +225,7 @@ public:
|
||||
|
||||
EDecision limit(const BonusLimitationContext &context) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & static_cast<ILimiter&>(*this);
|
||||
h & owner;
|
||||
@ -242,7 +242,7 @@ public:
|
||||
RankRangeLimiter(ui8 Min, ui8 Max = 255);
|
||||
EDecision limit(const BonusLimitationContext &context) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & static_cast<ILimiter&>(*this);
|
||||
h & minRank;
|
||||
@ -259,7 +259,7 @@ public:
|
||||
EDecision limit(const BonusLimitationContext &context) const override;
|
||||
JsonNode toJsonNode() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & static_cast<ILimiter&>(*this);
|
||||
h & applicableHexes;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user