mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-04 09:42:40 +02:00
Fix typos using https://github.com/crate-ci/typos
Changes were reviewed manually
This commit is contained in:
parent
820b1b446e
commit
02e429e973
@ -176,7 +176,7 @@ void CBattleAI::activeStack(const BattleID & battleID, const CStack * stack )
|
|||||||
movesSkippedByDefense = 0;
|
movesSkippedByDefense = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
logAi->trace("BattleAI decission made in %lld", timeElapsed(start));
|
logAi->trace("BattleAI decision made in %lld", timeElapsed(start));
|
||||||
|
|
||||||
cb->battleMakeUnitAction(battleID, result);
|
cb->battleMakeUnitAction(battleID, result);
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ struct CurrentOffensivePotential
|
|||||||
return ourPotential - enemyPotential;
|
return ourPotential - enemyPotential;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
*/ // These lines may be usefull but they are't used in the code.
|
*/ // These lines may be useful but they are't used in the code.
|
||||||
|
|
||||||
class CBattleAI : public CBattleGameInterface
|
class CBattleAI : public CBattleGameInterface
|
||||||
{
|
{
|
||||||
|
@ -196,7 +196,7 @@ BattleAction BattleEvaluator::selectStackAction(const CStack * stack)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//ThreatMap threatsToUs(stack); // These lines may be usefull but they are't used in the code.
|
//ThreatMap threatsToUs(stack); // These lines may be useful but they are't used in the code.
|
||||||
if(moveTarget.scorePerTurn > score)
|
if(moveTarget.scorePerTurn > score)
|
||||||
{
|
{
|
||||||
score = moveTarget.score;
|
score = moveTarget.score;
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
AttackerValue::AttackerValue()
|
AttackerValue::AttackerValue()
|
||||||
: value(0),
|
: value(0),
|
||||||
isRetalitated(false)
|
isRetaliated(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,14 +57,14 @@ float BattleExchangeVariant::trackAttack(
|
|||||||
|
|
||||||
attackValue -= attackerDamageReduce;
|
attackValue -= attackerDamageReduce;
|
||||||
dpsScore.ourDamageReduce += attackerDamageReduce;
|
dpsScore.ourDamageReduce += attackerDamageReduce;
|
||||||
attackerValue[unitToUpdate->unitId()].isRetalitated = true;
|
attackerValue[unitToUpdate->unitId()].isRetaliated = true;
|
||||||
|
|
||||||
unitToUpdate->damage(retaliationDamage);
|
unitToUpdate->damage(retaliationDamage);
|
||||||
defender->afterAttack(false, true);
|
defender->afterAttack(false, true);
|
||||||
|
|
||||||
#if BATTLE_TRACE_LEVEL>=1
|
#if BATTLE_TRACE_LEVEL>=1
|
||||||
logAi->trace(
|
logAi->trace(
|
||||||
"%s -> %s, ap retalitation, %s, dps: %2f, score: %2f",
|
"%s -> %s, ap retaliation, %s, dps: %2f, score: %2f",
|
||||||
defender->getDescription(),
|
defender->getDescription(),
|
||||||
unitToUpdate->getDescription(),
|
unitToUpdate->getDescription(),
|
||||||
ap.attack.shooting ? "shot" : "mellee",
|
ap.attack.shooting ? "shot" : "mellee",
|
||||||
@ -185,7 +185,7 @@ float BattleExchangeVariant::trackAttack(
|
|||||||
if(isOurAttack)
|
if(isOurAttack)
|
||||||
{
|
{
|
||||||
dpsScore.ourDamageReduce += attackerDamageReduce;
|
dpsScore.ourDamageReduce += attackerDamageReduce;
|
||||||
attackerValue[attacker->unitId()].isRetalitated = true;
|
attackerValue[attacker->unitId()].isRetaliated = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -45,7 +45,7 @@ struct BattleScore
|
|||||||
struct AttackerValue
|
struct AttackerValue
|
||||||
{
|
{
|
||||||
float value;
|
float value;
|
||||||
bool isRetalitated;
|
bool isRetaliated;
|
||||||
BattleHex position;
|
BattleHex position;
|
||||||
|
|
||||||
AttackerValue();
|
AttackerValue();
|
||||||
|
@ -70,4 +70,4 @@ ThreatMap::ThreatMap(const CStack *Endangered) : endangered(Endangered)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/ // These lines may be usefull but they are't used in the code.
|
*/ // These lines may be useful but they are't used in the code.
|
||||||
|
@ -22,4 +22,4 @@ public:
|
|||||||
std::array<int, GameConstants::BFIELD_SIZE> sufferedDamage;
|
std::array<int, GameConstants::BFIELD_SIZE> sufferedDamage;
|
||||||
|
|
||||||
ThreatMap(const CStack *Endangered);
|
ThreatMap(const CStack *Endangered);
|
||||||
};*/ // These lines may be usefull but they are't used in the code.
|
};*/ // These lines may be useful but they are't used in the code.
|
||||||
|
@ -500,7 +500,7 @@ void AIGateway::objectPropertyChanged(const SetObjectProperty * sop)
|
|||||||
if(relations == PlayerRelations::ENEMIES)
|
if(relations == PlayerRelations::ENEMIES)
|
||||||
{
|
{
|
||||||
//we want to visit objects owned by oppponents
|
//we want to visit objects owned by oppponents
|
||||||
//addVisitableObj(obj); // TODO: Remove once save compatability broken. In past owned objects were removed from this set
|
//addVisitableObj(obj); // TODO: Remove once save compatibility broken. In past owned objects were removed from this set
|
||||||
nullkiller->memory->markObjectUnvisited(obj);
|
nullkiller->memory->markObjectUnvisited(obj);
|
||||||
}
|
}
|
||||||
else if(relations == PlayerRelations::SAME_PLAYER && obj->ID == Obj::TOWN)
|
else if(relations == PlayerRelations::SAME_PLAYER && obj->ID == Obj::TOWN)
|
||||||
@ -705,7 +705,7 @@ void AIGateway::showTeleportDialog(const CGHeroInstance * hero, TeleportChannelI
|
|||||||
NET_EVENT_HANDLER;
|
NET_EVENT_HANDLER;
|
||||||
status.addQuery(askID, boost::str(boost::format("Teleport dialog query with %d exits") % exits.size()));
|
status.addQuery(askID, boost::str(boost::format("Teleport dialog query with %d exits") % exits.size()));
|
||||||
|
|
||||||
int choosenExit = -1;
|
int chosenExit = -1;
|
||||||
if(impassable)
|
if(impassable)
|
||||||
{
|
{
|
||||||
nullkiller->memory->knownTeleportChannels[channel]->passability = TeleportChannel::IMPASSABLE;
|
nullkiller->memory->knownTeleportChannels[channel]->passability = TeleportChannel::IMPASSABLE;
|
||||||
@ -714,14 +714,14 @@ void AIGateway::showTeleportDialog(const CGHeroInstance * hero, TeleportChannelI
|
|||||||
{
|
{
|
||||||
auto neededExit = std::make_pair(destinationTeleport, destinationTeleportPos);
|
auto neededExit = std::make_pair(destinationTeleport, destinationTeleportPos);
|
||||||
if(destinationTeleport != ObjectInstanceID() && vstd::contains(exits, neededExit))
|
if(destinationTeleport != ObjectInstanceID() && vstd::contains(exits, neededExit))
|
||||||
choosenExit = vstd::find_pos(exits, neededExit);
|
chosenExit = vstd::find_pos(exits, neededExit);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto exit : exits)
|
for(auto exit : exits)
|
||||||
{
|
{
|
||||||
if(status.channelProbing() && exit.first == destinationTeleport)
|
if(status.channelProbing() && exit.first == destinationTeleport)
|
||||||
{
|
{
|
||||||
choosenExit = vstd::find_pos(exits, exit);
|
chosenExit = vstd::find_pos(exits, exit);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -739,7 +739,7 @@ void AIGateway::showTeleportDialog(const CGHeroInstance * hero, TeleportChannelI
|
|||||||
|
|
||||||
requestActionASAP([=]()
|
requestActionASAP([=]()
|
||||||
{
|
{
|
||||||
answerQuery(askID, choosenExit);
|
answerQuery(askID, chosenExit);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1452,7 +1452,7 @@ void AIGateway::tryRealize(Goals::Trade & g) //trade
|
|||||||
if(cb->getResourceAmount(GameResID(g.resID)) >= g.value) //goal is already fulfilled. Why we need this check, anyway?
|
if(cb->getResourceAmount(GameResID(g.resID)) >= g.value) //goal is already fulfilled. Why we need this check, anyway?
|
||||||
throw goalFulfilledException(sptr(g));
|
throw goalFulfilledException(sptr(g));
|
||||||
|
|
||||||
int accquiredResources = 0;
|
int acquiredResources = 0;
|
||||||
if(const CGObjectInstance * obj = cb->getObj(ObjectInstanceID(g.objid), false))
|
if(const CGObjectInstance * obj = cb->getObj(ObjectInstanceID(g.objid), false))
|
||||||
{
|
{
|
||||||
if(const auto * m = dynamic_cast<const IMarket*>(obj))
|
if(const auto * m = dynamic_cast<const IMarket*>(obj))
|
||||||
@ -1472,8 +1472,8 @@ void AIGateway::tryRealize(Goals::Trade & g) //trade
|
|||||||
if (toGive) //don't try to sell 0 resources
|
if (toGive) //don't try to sell 0 resources
|
||||||
{
|
{
|
||||||
cb->trade(m, EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
|
cb->trade(m, EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
|
||||||
accquiredResources = static_cast<int>(toGet * (it->resVal / toGive));
|
acquiredResources = static_cast<int>(toGet * (it->resVal / toGive));
|
||||||
logAi->debug("Traded %d of %s for %d of %s at %s", toGive, res, accquiredResources, g.resID, obj->getObjectName());
|
logAi->debug("Traded %d of %s for %d of %s at %s", toGive, res, acquiredResources, g.resID, obj->getObjectName());
|
||||||
}
|
}
|
||||||
if (cb->getResourceAmount(GameResID(g.resID)))
|
if (cb->getResourceAmount(GameResID(g.resID)))
|
||||||
throw goalFulfilledException(sptr(g)); //we traded all we needed
|
throw goalFulfilledException(sptr(g)); //we traded all we needed
|
||||||
|
@ -95,7 +95,7 @@ public:
|
|||||||
AIGateway();
|
AIGateway();
|
||||||
virtual ~AIGateway();
|
virtual ~AIGateway();
|
||||||
|
|
||||||
//TODO: extract to apropriate goals
|
//TODO: extract to appropriate goals
|
||||||
void tryRealize(Goals::DigAtTile & g);
|
void tryRealize(Goals::DigAtTile & g);
|
||||||
void tryRealize(Goals::Trade & g);
|
void tryRealize(Goals::Trade & g);
|
||||||
|
|
||||||
|
@ -434,9 +434,9 @@ bool townHasFreeTavern(const CGTownInstance * town)
|
|||||||
if(!town->hasBuilt(BuildingID::TAVERN)) return false;
|
if(!town->hasBuilt(BuildingID::TAVERN)) return false;
|
||||||
if(!town->visitingHero) return true;
|
if(!town->visitingHero) return true;
|
||||||
|
|
||||||
bool canMoveVisitingHeroToGarnison = !town->getUpperArmy()->stacksCount();
|
bool canMoveVisitingHeroToGarrison = !town->getUpperArmy()->stacksCount();
|
||||||
|
|
||||||
return canMoveVisitingHeroToGarnison;
|
return canMoveVisitingHeroToGarrison;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t getHeroArmyStrengthWithCommander(const CGHeroInstance * hero, const CCreatureSet * heroArmy)
|
uint64_t getHeroArmyStrengthWithCommander(const CGHeroInstance * hero, const CCreatureSet * heroArmy)
|
||||||
|
@ -267,7 +267,7 @@ BuildingInfo BuildAnalyzer::getBuildingOrPrerequisite(
|
|||||||
|
|
||||||
BuildingInfo prerequisite = getBuildingOrPrerequisite(town, missingBuildings[0], excludeDwellingDependencies);
|
BuildingInfo prerequisite = getBuildingOrPrerequisite(town, missingBuildings[0], excludeDwellingDependencies);
|
||||||
|
|
||||||
prerequisite.buildCostWithPrerequisits += info.buildCost;
|
prerequisite.buildCostWithPrerequisites += info.buildCost;
|
||||||
prerequisite.creatureCost = info.creatureCost;
|
prerequisite.creatureCost = info.creatureCost;
|
||||||
prerequisite.creatureGrows = info.creatureGrows;
|
prerequisite.creatureGrows = info.creatureGrows;
|
||||||
prerequisite.creatureLevel = info.creatureLevel;
|
prerequisite.creatureLevel = info.creatureLevel;
|
||||||
@ -340,7 +340,7 @@ void TownDevelopmentInfo::addExistingDwelling(const BuildingInfo & existingDwell
|
|||||||
|
|
||||||
void TownDevelopmentInfo::addBuildingToBuild(const BuildingInfo & nextToBuild)
|
void TownDevelopmentInfo::addBuildingToBuild(const BuildingInfo & nextToBuild)
|
||||||
{
|
{
|
||||||
townDevelopmentCost += nextToBuild.buildCostWithPrerequisits;
|
townDevelopmentCost += nextToBuild.buildCostWithPrerequisites;
|
||||||
|
|
||||||
if(nextToBuild.canBuild)
|
if(nextToBuild.canBuild)
|
||||||
{
|
{
|
||||||
@ -361,7 +361,7 @@ BuildingInfo::BuildingInfo()
|
|||||||
creatureGrows = 0;
|
creatureGrows = 0;
|
||||||
creatureID = CreatureID::NONE;
|
creatureID = CreatureID::NONE;
|
||||||
buildCost = 0;
|
buildCost = 0;
|
||||||
buildCostWithPrerequisits = 0;
|
buildCostWithPrerequisites = 0;
|
||||||
prerequisitesCount = 0;
|
prerequisitesCount = 0;
|
||||||
name.clear();
|
name.clear();
|
||||||
armyStrength = 0;
|
armyStrength = 0;
|
||||||
@ -376,7 +376,7 @@ BuildingInfo::BuildingInfo(
|
|||||||
{
|
{
|
||||||
id = building->bid;
|
id = building->bid;
|
||||||
buildCost = building->resources;
|
buildCost = building->resources;
|
||||||
buildCostWithPrerequisits = building->resources;
|
buildCostWithPrerequisites = building->resources;
|
||||||
dailyIncome = building->produce;
|
dailyIncome = building->produce;
|
||||||
exists = town->hasBuilt(id);
|
exists = town->hasBuilt(id);
|
||||||
prerequisitesCount = 1;
|
prerequisitesCount = 1;
|
||||||
|
@ -22,7 +22,7 @@ class DLL_EXPORT BuildingInfo
|
|||||||
public:
|
public:
|
||||||
BuildingID id;
|
BuildingID id;
|
||||||
TResources buildCost;
|
TResources buildCost;
|
||||||
TResources buildCostWithPrerequisits;
|
TResources buildCostWithPrerequisites;
|
||||||
int creatureGrows;
|
int creatureGrows;
|
||||||
uint8_t creatureLevel;
|
uint8_t creatureLevel;
|
||||||
TResources creatureCost;
|
TResources creatureCost;
|
||||||
|
@ -240,7 +240,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
|
|||||||
if(path.turn() <= threat.turn - 2)
|
if(path.turn() <= threat.turn - 2)
|
||||||
{
|
{
|
||||||
#if NKAI_TRACE_LEVEL >= 1
|
#if NKAI_TRACE_LEVEL >= 1
|
||||||
logAi->trace("Defer defence of %s by %s because he has enough time to reach the town next trun",
|
logAi->trace("Defer defence of %s by %s because he has enough time to reach the town next turn",
|
||||||
town->getObjectName(),
|
town->getObjectName(),
|
||||||
path.targetHero->getObjectName());
|
path.targetHero->getObjectName());
|
||||||
#endif
|
#endif
|
||||||
|
@ -399,7 +399,7 @@ void Nullkiller::makeTurn()
|
|||||||
|
|
||||||
auto selectedTasks = buildPlan(bestTasks);
|
auto selectedTasks = buildPlan(bestTasks);
|
||||||
|
|
||||||
logAi->debug("Decission madel in %ld", timeElapsed(start));
|
logAi->debug("Decision madel in %ld", timeElapsed(start));
|
||||||
|
|
||||||
if(selectedTasks.empty())
|
if(selectedTasks.empty())
|
||||||
{
|
{
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
namespace NKAI
|
namespace NKAI
|
||||||
{
|
{
|
||||||
|
|
||||||
#define MIN_AI_STRENGHT (0.5f) //lower when combat AI gets smarter
|
#define MIN_AI_STRENGTH (0.5f) //lower when combat AI gets smarter
|
||||||
#define UNGUARDED_OBJECT (100.0f) //we consider unguarded objects 100 times weaker than us
|
#define UNGUARDED_OBJECT (100.0f) //we consider unguarded objects 100 times weaker than us
|
||||||
const float MIN_CRITICAL_VALUE = 2.0f;
|
const float MIN_CRITICAL_VALUE = 2.0f;
|
||||||
|
|
||||||
@ -1000,7 +1000,7 @@ public:
|
|||||||
evaluationContext.goldReward += 7 * bi.dailyIncome[EGameResID::GOLD] / 2; // 7 day income but half we already have
|
evaluationContext.goldReward += 7 * bi.dailyIncome[EGameResID::GOLD] / 2; // 7 day income but half we already have
|
||||||
evaluationContext.heroRole = HeroRole::MAIN;
|
evaluationContext.heroRole = HeroRole::MAIN;
|
||||||
evaluationContext.movementCostByRole[evaluationContext.heroRole] += bi.prerequisitesCount;
|
evaluationContext.movementCostByRole[evaluationContext.heroRole] += bi.prerequisitesCount;
|
||||||
evaluationContext.goldCost += bi.buildCostWithPrerequisits[EGameResID::GOLD];
|
evaluationContext.goldCost += bi.buildCostWithPrerequisites[EGameResID::GOLD];
|
||||||
evaluationContext.closestWayRatio = 1;
|
evaluationContext.closestWayRatio = 1;
|
||||||
|
|
||||||
if(bi.creatureID != CreatureID::NONE)
|
if(bi.creatureID != CreatureID::NONE)
|
||||||
|
@ -34,13 +34,13 @@ void BuyArmy::accept(AIGateway * ai)
|
|||||||
ui64 valueBought = 0;
|
ui64 valueBought = 0;
|
||||||
//buy the stacks with largest AI value
|
//buy the stacks with largest AI value
|
||||||
|
|
||||||
auto upgradeSuccessfull = ai->makePossibleUpgrades(town);
|
auto upgradeSuccessful = ai->makePossibleUpgrades(town);
|
||||||
|
|
||||||
auto armyToBuy = ai->nullkiller->armyManager->getArmyAvailableToBuy(town->getUpperArmy(), town);
|
auto armyToBuy = ai->nullkiller->armyManager->getArmyAvailableToBuy(town->getUpperArmy(), town);
|
||||||
|
|
||||||
if(armyToBuy.empty())
|
if(armyToBuy.empty())
|
||||||
{
|
{
|
||||||
if(upgradeSuccessfull)
|
if(upgradeSuccessful)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
throw cannotFulfillGoalException("No creatures to buy.");
|
throw cannotFulfillGoalException("No creatures to buy.");
|
||||||
|
@ -234,7 +234,7 @@ void ExecuteHeroChain::accept(AIGateway * ai)
|
|||||||
if(node->turns == 0)
|
if(node->turns == 0)
|
||||||
{
|
{
|
||||||
logAi->error(
|
logAi->error(
|
||||||
"Unable to complete chain. Expected hero %s to arive to %s but he is at %s",
|
"Unable to complete chain. Expected hero %s to arrive to %s but he is at %s",
|
||||||
hero->getNameTranslated(),
|
hero->getNameTranslated(),
|
||||||
node->coord.toString(),
|
node->coord.toString(),
|
||||||
hero->visitablePos().toString());
|
hero->visitablePos().toString());
|
||||||
|
@ -27,8 +27,8 @@ namespace NKAI
|
|||||||
std::shared_ptr<boost::multi_array<AIPathNode, 4>> AISharedStorage::shared;
|
std::shared_ptr<boost::multi_array<AIPathNode, 4>> AISharedStorage::shared;
|
||||||
uint64_t AISharedStorage::version = 0;
|
uint64_t AISharedStorage::version = 0;
|
||||||
boost::mutex AISharedStorage::locker;
|
boost::mutex AISharedStorage::locker;
|
||||||
std::set<int3> commitedTiles;
|
std::set<int3> committedTiles;
|
||||||
std::set<int3> commitedTilesInitial;
|
std::set<int3> committedTilesInitial;
|
||||||
|
|
||||||
|
|
||||||
const uint64_t FirstActorMask = 1;
|
const uint64_t FirstActorMask = 1;
|
||||||
@ -36,7 +36,7 @@ const uint64_t MIN_ARMY_STRENGTH_FOR_CHAIN = 5000;
|
|||||||
const uint64_t MIN_ARMY_STRENGTH_FOR_NEXT_ACTOR = 1000;
|
const uint64_t MIN_ARMY_STRENGTH_FOR_NEXT_ACTOR = 1000;
|
||||||
const uint64_t CHAIN_MAX_DEPTH = 4;
|
const uint64_t CHAIN_MAX_DEPTH = 4;
|
||||||
|
|
||||||
const bool DO_NOT_SAVE_TO_COMMITED_TILES = false;
|
const bool DO_NOT_SAVE_TO_COMMITTED_TILES = false;
|
||||||
|
|
||||||
AISharedStorage::AISharedStorage(int3 sizes)
|
AISharedStorage::AISharedStorage(int3 sizes)
|
||||||
{
|
{
|
||||||
@ -94,7 +94,7 @@ void AIPathNode::addSpecialAction(std::shared_ptr<const SpecialAction> action)
|
|||||||
AINodeStorage::AINodeStorage(const Nullkiller * ai, const int3 & Sizes)
|
AINodeStorage::AINodeStorage(const Nullkiller * ai, const int3 & Sizes)
|
||||||
: sizes(Sizes), ai(ai), cb(ai->cb.get()), nodes(Sizes)
|
: sizes(Sizes), ai(ai), cb(ai->cb.get()), nodes(Sizes)
|
||||||
{
|
{
|
||||||
accesibility = std::make_unique<boost::multi_array<EPathAccessibility, 4>>(
|
accessibility = std::make_unique<boost::multi_array<EPathAccessibility, 4>>(
|
||||||
boost::extents[sizes.z][sizes.x][sizes.y][EPathfindingLayer::NUM_LAYERS]);
|
boost::extents[sizes.z][sizes.x][sizes.y][EPathfindingLayer::NUM_LAYERS]);
|
||||||
|
|
||||||
dangerEvaluator.reset(new FuzzyHelper(ai));
|
dangerEvaluator.reset(new FuzzyHelper(ai));
|
||||||
@ -157,7 +157,7 @@ void AINodeStorage::initialize(const PathfinderOptions & options, const CGameSta
|
|||||||
void AINodeStorage::clear()
|
void AINodeStorage::clear()
|
||||||
{
|
{
|
||||||
actors.clear();
|
actors.clear();
|
||||||
commitedTiles.clear();
|
committedTiles.clear();
|
||||||
heroChainPass = EHeroChainPass::INITIAL;
|
heroChainPass = EHeroChainPass::INITIAL;
|
||||||
heroChainTurn = 0;
|
heroChainTurn = 0;
|
||||||
heroChainMaxTurns = 1;
|
heroChainMaxTurns = 1;
|
||||||
@ -276,7 +276,7 @@ void AINodeStorage::commit(
|
|||||||
int turn,
|
int turn,
|
||||||
int movementLeft,
|
int movementLeft,
|
||||||
float cost,
|
float cost,
|
||||||
bool saveToCommited) const
|
bool saveToCommitted) const
|
||||||
{
|
{
|
||||||
destination->action = action;
|
destination->action = action;
|
||||||
destination->setCost(cost);
|
destination->setCost(cost);
|
||||||
@ -290,7 +290,7 @@ void AINodeStorage::commit(
|
|||||||
|
|
||||||
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
|
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
|
||||||
logAi->trace(
|
logAi->trace(
|
||||||
"Commited %s -> %s, layer: %d, cost: %f, turn: %s, mp: %d, hero: %s, mask: %x, army: %lld",
|
"Committed %s -> %s, layer: %d, cost: %f, turn: %s, mp: %d, hero: %s, mask: %x, army: %lld",
|
||||||
source->coord.toString(),
|
source->coord.toString(),
|
||||||
destination->coord.toString(),
|
destination->coord.toString(),
|
||||||
destination->layer,
|
destination->layer,
|
||||||
@ -302,9 +302,9 @@ void AINodeStorage::commit(
|
|||||||
destination->actor->armyValue);
|
destination->actor->armyValue);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(saveToCommited && destination->turns <= heroChainTurn)
|
if(saveToCommitted && destination->turns <= heroChainTurn)
|
||||||
{
|
{
|
||||||
commitedTiles.insert(destination->coord);
|
committedTiles.insert(destination->coord);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(destination->turns == source->turns)
|
if(destination->turns == source->turns)
|
||||||
@ -376,7 +376,7 @@ bool AINodeStorage::increaseHeroChainTurnLimit()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
heroChainTurn++;
|
heroChainTurn++;
|
||||||
commitedTiles.clear();
|
committedTiles.clear();
|
||||||
|
|
||||||
for(auto layer : phisycalLayers)
|
for(auto layer : phisycalLayers)
|
||||||
{
|
{
|
||||||
@ -386,7 +386,7 @@ bool AINodeStorage::increaseHeroChainTurnLimit()
|
|||||||
{
|
{
|
||||||
if(node.turns <= heroChainTurn && node.action != EPathNodeAction::UNKNOWN)
|
if(node.turns <= heroChainTurn && node.action != EPathNodeAction::UNKNOWN)
|
||||||
{
|
{
|
||||||
commitedTiles.insert(pos);
|
committedTiles.insert(pos);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,7 +547,7 @@ bool AINodeStorage::calculateHeroChain()
|
|||||||
heroChainPass = EHeroChainPass::CHAIN;
|
heroChainPass = EHeroChainPass::CHAIN;
|
||||||
heroChain.clear();
|
heroChain.clear();
|
||||||
|
|
||||||
std::vector<int3> data(commitedTiles.begin(), commitedTiles.end());
|
std::vector<int3> data(committedTiles.begin(), committedTiles.end());
|
||||||
|
|
||||||
if(data.size() > 100)
|
if(data.size() > 100)
|
||||||
{
|
{
|
||||||
@ -578,7 +578,7 @@ bool AINodeStorage::calculateHeroChain()
|
|||||||
task.flushResult(heroChain);
|
task.flushResult(heroChain);
|
||||||
}
|
}
|
||||||
|
|
||||||
commitedTiles.clear();
|
committedTiles.clear();
|
||||||
|
|
||||||
return !heroChain.empty();
|
return !heroChain.empty();
|
||||||
}
|
}
|
||||||
@ -594,7 +594,7 @@ bool AINodeStorage::selectFirstActor()
|
|||||||
});
|
});
|
||||||
|
|
||||||
chainMask = strongest->chainMask;
|
chainMask = strongest->chainMask;
|
||||||
commitedTilesInitial = commitedTiles;
|
committedTilesInitial = committedTiles;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -629,7 +629,7 @@ bool AINodeStorage::selectNextActor()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
chainMask = nextActor->get()->chainMask;
|
chainMask = nextActor->get()->chainMask;
|
||||||
commitedTiles = commitedTilesInitial;
|
committedTiles = committedTilesInitial;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -656,7 +656,7 @@ void HeroChainCalculationTask::cleanupInefectiveChains(std::vector<ExchangeCandi
|
|||||||
if(isNotEffective)
|
if(isNotEffective)
|
||||||
{
|
{
|
||||||
logAi->trace(
|
logAi->trace(
|
||||||
"Skip exchange %s[%x] -> %s[%x] at %s is ineficient",
|
"Skip exchange %s[%x] -> %s[%x] at %s is inefficient",
|
||||||
chainInfo.otherParent->actor->toString(),
|
chainInfo.otherParent->actor->toString(),
|
||||||
chainInfo.otherParent->actor->chainMask,
|
chainInfo.otherParent->actor->chainMask,
|
||||||
chainInfo.carrierParent->actor->toString(),
|
chainInfo.carrierParent->actor->toString(),
|
||||||
@ -756,7 +756,7 @@ void HeroChainCalculationTask::calculateHeroChain(
|
|||||||
if(hasLessMp && hasLessExperience)
|
if(hasLessMp && hasLessExperience)
|
||||||
{
|
{
|
||||||
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
|
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
|
||||||
logAi->trace("Exchange at %s is ineficient. Blocked.", carrier->coord.toString());
|
logAi->trace("Exchange at %s is inefficient. Blocked.", carrier->coord.toString());
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -825,7 +825,7 @@ void HeroChainCalculationTask::addHeroChain(const std::vector<ExchangeCandidate>
|
|||||||
chainInfo.turns,
|
chainInfo.turns,
|
||||||
chainInfo.moveRemains,
|
chainInfo.moveRemains,
|
||||||
chainInfo.getCost(),
|
chainInfo.getCost(),
|
||||||
DO_NOT_SAVE_TO_COMMITED_TILES);
|
DO_NOT_SAVE_TO_COMMITTED_TILES);
|
||||||
|
|
||||||
if(carrier->specialAction || carrier->chainOther)
|
if(carrier->specialAction || carrier->chainOther)
|
||||||
{
|
{
|
||||||
@ -1119,7 +1119,7 @@ struct TownPortalFinder
|
|||||||
bestNode->turns,
|
bestNode->turns,
|
||||||
bestNode->moveRemains - movementNeeded,
|
bestNode->moveRemains - movementNeeded,
|
||||||
movementCost,
|
movementCost,
|
||||||
DO_NOT_SAVE_TO_COMMITED_TILES);
|
DO_NOT_SAVE_TO_COMMITTED_TILES);
|
||||||
|
|
||||||
node->theNodeBefore = bestNode;
|
node->theNodeBefore = bestNode;
|
||||||
node->addSpecialAction(std::make_shared<AIPathfinding::TownPortalAction>(targetTown));
|
node->addSpecialAction(std::make_shared<AIPathfinding::TownPortalAction>(targetTown));
|
||||||
@ -1281,7 +1281,7 @@ bool AINodeStorage::isOtherChainBetter(
|
|||||||
{
|
{
|
||||||
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
|
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
|
||||||
logAi->trace(
|
logAi->trace(
|
||||||
"Block ineficient battle move %s->%s, hero: %s[%X], army %lld, mp diff: %i",
|
"Block inefficient battle move %s->%s, hero: %s[%X], army %lld, mp diff: %i",
|
||||||
source->coord.toString(),
|
source->coord.toString(),
|
||||||
candidateNode.coord.toString(),
|
candidateNode.coord.toString(),
|
||||||
candidateNode.actor->hero->getNameTranslated(),
|
candidateNode.actor->hero->getNameTranslated(),
|
||||||
@ -1305,7 +1305,7 @@ bool AINodeStorage::isOtherChainBetter(
|
|||||||
{
|
{
|
||||||
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
|
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
|
||||||
logAi->trace(
|
logAi->trace(
|
||||||
"Block ineficient move because of stronger army %s->%s, hero: %s[%X], army %lld, mp diff: %i",
|
"Block inefficient move because of stronger army %s->%s, hero: %s[%X], army %lld, mp diff: %i",
|
||||||
source->coord.toString(),
|
source->coord.toString(),
|
||||||
candidateNode.coord.toString(),
|
candidateNode.coord.toString(),
|
||||||
candidateNode.actor->hero->getNameTranslated(),
|
candidateNode.actor->hero->getNameTranslated(),
|
||||||
@ -1331,7 +1331,7 @@ bool AINodeStorage::isOtherChainBetter(
|
|||||||
|
|
||||||
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
|
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
|
||||||
logAi->trace(
|
logAi->trace(
|
||||||
"Block ineficient move because of stronger hero %s->%s, hero: %s[%X], army %lld, mp diff: %i",
|
"Block inefficient move because of stronger hero %s->%s, hero: %s[%X], army %lld, mp diff: %i",
|
||||||
source->coord.toString(),
|
source->coord.toString(),
|
||||||
candidateNode.coord.toString(),
|
candidateNode.coord.toString(),
|
||||||
candidateNode.actor->hero->getNameTranslated(),
|
candidateNode.actor->hero->getNameTranslated(),
|
||||||
|
@ -165,7 +165,7 @@ class AINodeStorage : public INodeStorage
|
|||||||
private:
|
private:
|
||||||
int3 sizes;
|
int3 sizes;
|
||||||
|
|
||||||
std::unique_ptr<boost::multi_array<EPathAccessibility, 4>> accesibility;
|
std::unique_ptr<boost::multi_array<EPathAccessibility, 4>> accessibility;
|
||||||
|
|
||||||
const CPlayerSpecificInfoCallback * cb;
|
const CPlayerSpecificInfoCallback * cb;
|
||||||
const Nullkiller * ai;
|
const Nullkiller * ai;
|
||||||
@ -214,7 +214,7 @@ public:
|
|||||||
int turn,
|
int turn,
|
||||||
int movementLeft,
|
int movementLeft,
|
||||||
float cost,
|
float cost,
|
||||||
bool saveToCommited = true) const;
|
bool saveToCommitted = true) const;
|
||||||
|
|
||||||
inline const AIPathNode * getAINode(const CGPathNode * node) const
|
inline const AIPathNode * getAINode(const CGPathNode * node) const
|
||||||
{
|
{
|
||||||
@ -257,7 +257,7 @@ public:
|
|||||||
const AIPathNode & candidateNode,
|
const AIPathNode & candidateNode,
|
||||||
const AIPathNode & other) const;
|
const AIPathNode & other) const;
|
||||||
|
|
||||||
bool isMovementIneficient(const PathNodeInfo & source, CDestinationNodeInfo & destination) const
|
bool isMovementInefficient(const PathNodeInfo & source, CDestinationNodeInfo & destination) const
|
||||||
{
|
{
|
||||||
return hasBetterChain(source, destination);
|
return hasBetterChain(source, destination);
|
||||||
}
|
}
|
||||||
@ -287,12 +287,12 @@ public:
|
|||||||
|
|
||||||
inline EPathAccessibility getAccessibility(const int3 & tile, EPathfindingLayer layer) const
|
inline EPathAccessibility getAccessibility(const int3 & tile, EPathfindingLayer layer) const
|
||||||
{
|
{
|
||||||
return (*this->accesibility)[tile.z][tile.x][tile.y][layer];
|
return (*this->accessibility)[tile.z][tile.x][tile.y][layer];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void resetTile(const int3 & tile, EPathfindingLayer layer, EPathAccessibility tileAccessibility)
|
inline void resetTile(const int3 & tile, EPathfindingLayer layer, EPathAccessibility tileAccessibility)
|
||||||
{
|
{
|
||||||
(*this->accesibility)[tile.z][tile.x][tile.y][layer] = tileAccessibility;
|
(*this->accessibility)[tile.z][tile.x][tile.y][layer] = tileAccessibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int getBucket(const ChainActor * actor) const
|
inline int getBucket(const ChainActor * actor) const
|
||||||
|
@ -164,7 +164,7 @@ namespace AIPathfinding
|
|||||||
if(hero->canCastThisSpell(summonBoatSpell)
|
if(hero->canCastThisSpell(summonBoatSpell)
|
||||||
&& hero->getSpellSchoolLevel(summonBoatSpell) >= MasteryLevel::ADVANCED)
|
&& hero->getSpellSchoolLevel(summonBoatSpell) >= MasteryLevel::ADVANCED)
|
||||||
{
|
{
|
||||||
// TODO: For lower school level we might need to check the existance of some boat
|
// TODO: For lower school level we might need to check the existence of some boat
|
||||||
summonableVirtualBoats[hero] = std::make_shared<SummonBoatAction>();
|
summonableVirtualBoats[hero] = std::make_shared<SummonBoatAction>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ namespace AIPathfinding
|
|||||||
const PathfinderConfig * pathfinderConfig,
|
const PathfinderConfig * pathfinderConfig,
|
||||||
CPathfinderHelper * pathfinderHelper) const
|
CPathfinderHelper * pathfinderHelper) const
|
||||||
{
|
{
|
||||||
if(nodeStorage->isMovementIneficient(source, destination))
|
if(nodeStorage->isMovementInefficient(source, destination))
|
||||||
{
|
{
|
||||||
destination.node->locked = true;
|
destination.node->locked = true;
|
||||||
destination.blocked = true;
|
destination.blocked = true;
|
||||||
|
@ -41,7 +41,7 @@ TSubgoal BuildThis::whatToDoToAchieve()
|
|||||||
{
|
{
|
||||||
case EBuildingState::ALLOWED:
|
case EBuildingState::ALLOWED:
|
||||||
town = candidateTown;
|
town = candidateTown;
|
||||||
break; //TODO: look for prerequisites? this is not our reponsibility
|
break; //TODO: look for prerequisites? this is not our responsibility
|
||||||
default:
|
default:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ TGoalVec ClearWayTo::getAllPossibleSubgoals()
|
|||||||
if(ret.empty())
|
if(ret.empty())
|
||||||
{
|
{
|
||||||
logAi->warn("There is no known way to clear the way to tile %s", tile.toString());
|
logAi->warn("There is no known way to clear the way to tile %s", tile.toString());
|
||||||
throw goalFulfilledException(sptr(ClearWayTo(tile))); //make sure asigned hero gets unlocked
|
throw goalFulfilledException(sptr(ClearWayTo(tile))); //make sure assigned hero gets unlocked
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -53,7 +53,7 @@ TSubgoal VisitHero::whatToDoToAchieve()
|
|||||||
|
|
||||||
bool VisitHero::fulfillsMe(TSubgoal goal)
|
bool VisitHero::fulfillsMe(TSubgoal goal)
|
||||||
{
|
{
|
||||||
//TODO: VisitObj shoudl not be used for heroes, but...
|
//TODO: VisitObj should not be used for heroes, but...
|
||||||
if(goal->goalType == VISIT_TILE)
|
if(goal->goalType == VISIT_TILE)
|
||||||
{
|
{
|
||||||
auto obj = cb->getObj(ObjectInstanceID(objid));
|
auto obj = cb->getObj(ObjectInstanceID(objid));
|
||||||
|
@ -74,7 +74,7 @@ TSubgoal Win::whatToDoToAchieve()
|
|||||||
case EventCondition::HAVE_BUILDING:
|
case EventCondition::HAVE_BUILDING:
|
||||||
{
|
{
|
||||||
// TODO build other buildings apart from Grail
|
// TODO build other buildings apart from Grail
|
||||||
// goal.objectType = buidingID to build
|
// goal.objectType = buildingID to build
|
||||||
// goal.object = optional, town in which building should be built
|
// goal.object = optional, town in which building should be built
|
||||||
// Represents "Improve town" condition from H3 (but unlike H3 it consists from 2 separate conditions)
|
// Represents "Improve town" condition from H3 (but unlike H3 it consists from 2 separate conditions)
|
||||||
|
|
||||||
|
@ -309,7 +309,7 @@ bool AINodeStorage::hasBetterChain(const PathNodeInfo & source, CDestinationNode
|
|||||||
{
|
{
|
||||||
#ifdef VCMI_TRACE_PATHFINDER
|
#ifdef VCMI_TRACE_PATHFINDER
|
||||||
logAi->trace(
|
logAi->trace(
|
||||||
"Block ineficient move %s:->%s, mask=%i, mp diff: %i",
|
"Block inefficient move %s:->%s, mask=%i, mp diff: %i",
|
||||||
source.coord.toString(),
|
source.coord.toString(),
|
||||||
destination.coord.toString(),
|
destination.coord.toString(),
|
||||||
destinationNode->chainMask,
|
destinationNode->chainMask,
|
||||||
|
@ -79,7 +79,7 @@ namespace AIPathfinding
|
|||||||
if(hero->canCastThisSpell(summonBoatSpell)
|
if(hero->canCastThisSpell(summonBoatSpell)
|
||||||
&& hero->getSpellSchoolLevel(summonBoatSpell) >= MasteryLevel::ADVANCED)
|
&& hero->getSpellSchoolLevel(summonBoatSpell) >= MasteryLevel::ADVANCED)
|
||||||
{
|
{
|
||||||
// TODO: For lower school level we might need to check the existance of some boat
|
// TODO: For lower school level we might need to check the existence of some boat
|
||||||
summonableVirtualBoat.reset(new SummonBoatAction());
|
summonableVirtualBoat.reset(new SummonBoatAction());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ TResources ResourceManager::estimateIncome() const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceManager::reserveResoures(const TResources & res, Goals::TSubgoal goal)
|
void ResourceManager::reserveResources(const TResources & res, Goals::TSubgoal goal)
|
||||||
{
|
{
|
||||||
if (!goal->invalid())
|
if (!goal->invalid())
|
||||||
tryPush(ResourceObjective(res, goal));
|
tryPush(ResourceObjective(res, goal));
|
||||||
@ -315,7 +315,7 @@ bool ResourceManager::removeOutdatedObjectives(std::function<bool(const Goals::T
|
|||||||
TResources ResourceManager::reservedResources() const
|
TResources ResourceManager::reservedResources() const
|
||||||
{
|
{
|
||||||
TResources res;
|
TResources res;
|
||||||
for (auto it : queue) //substract the value of reserved goals
|
for (auto it : queue) //subtract the value of reserved goals
|
||||||
res += it.resources;
|
res += it.resources;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -323,7 +323,7 @@ TResources ResourceManager::reservedResources() const
|
|||||||
TResources ResourceManager::freeResources() const
|
TResources ResourceManager::freeResources() const
|
||||||
{
|
{
|
||||||
TResources myRes = cb->getResourceAmount();
|
TResources myRes = cb->getResourceAmount();
|
||||||
myRes -= reservedResources(); //substract the value of reserved goals
|
myRes -= reservedResources(); //subtract the value of reserved goals
|
||||||
|
|
||||||
for (auto & val : myRes)
|
for (auto & val : myRes)
|
||||||
vstd::amax(val, 0); //never negative
|
vstd::amax(val, 0); //never negative
|
||||||
|
@ -24,7 +24,7 @@ struct DLL_EXPORT ResourceObjective
|
|||||||
ResourceObjective(const TResources &res, Goals::TSubgoal goal);
|
ResourceObjective(const TResources &res, Goals::TSubgoal goal);
|
||||||
bool operator < (const ResourceObjective &ro) const;
|
bool operator < (const ResourceObjective &ro) const;
|
||||||
|
|
||||||
TResources resources; //how many resoures do we need
|
TResources resources; //how many resources do we need
|
||||||
Goals::TSubgoal goal; //what for (build, gather army etc...)
|
Goals::TSubgoal goal; //what for (build, gather army etc...)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ public:
|
|||||||
bool notifyGoalCompleted(Goals::TSubgoal goal) override;
|
bool notifyGoalCompleted(Goals::TSubgoal goal) override;
|
||||||
|
|
||||||
protected: //not-const actions only for AI
|
protected: //not-const actions only for AI
|
||||||
virtual void reserveResoures(const TResources & res, Goals::TSubgoal goal = Goals::TSubgoal());
|
virtual void reserveResources(const TResources & res, Goals::TSubgoal goal = Goals::TSubgoal());
|
||||||
virtual bool updateGoal(Goals::TSubgoal goal); //new goal must have same properties but different priority
|
virtual bool updateGoal(Goals::TSubgoal goal); //new goal must have same properties but different priority
|
||||||
virtual bool tryPush(const ResourceObjective &o);
|
virtual bool tryPush(const ResourceObjective &o);
|
||||||
|
|
||||||
|
@ -571,7 +571,7 @@ void VCAI::objectPropertyChanged(const SetObjectProperty * sop)
|
|||||||
auto obj = myCb->getObj(sop->id, false);
|
auto obj = myCb->getObj(sop->id, false);
|
||||||
if(obj)
|
if(obj)
|
||||||
{
|
{
|
||||||
addVisitableObj(obj); // TODO: Remove once save compatability broken. In past owned objects were removed from this set
|
addVisitableObj(obj); // TODO: Remove once save compatibility broken. In past owned objects were removed from this set
|
||||||
vstd::erase_if_present(alreadyVisited, obj);
|
vstd::erase_if_present(alreadyVisited, obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -682,7 +682,7 @@ void VCAI::showTeleportDialog(const CGHeroInstance * hero, TeleportChannelID cha
|
|||||||
status.addQuery(askID, boost::str(boost::format("Teleport dialog query with %d exits")
|
status.addQuery(askID, boost::str(boost::format("Teleport dialog query with %d exits")
|
||||||
% exits.size()));
|
% exits.size()));
|
||||||
|
|
||||||
int choosenExit = -1;
|
int chosenExit = -1;
|
||||||
if(impassable)
|
if(impassable)
|
||||||
{
|
{
|
||||||
knownTeleportChannels[channel]->passability = TeleportChannel::IMPASSABLE;
|
knownTeleportChannels[channel]->passability = TeleportChannel::IMPASSABLE;
|
||||||
@ -691,14 +691,14 @@ void VCAI::showTeleportDialog(const CGHeroInstance * hero, TeleportChannelID cha
|
|||||||
{
|
{
|
||||||
auto neededExit = std::make_pair(destinationTeleport, destinationTeleportPos);
|
auto neededExit = std::make_pair(destinationTeleport, destinationTeleportPos);
|
||||||
if(destinationTeleport != ObjectInstanceID() && vstd::contains(exits, neededExit))
|
if(destinationTeleport != ObjectInstanceID() && vstd::contains(exits, neededExit))
|
||||||
choosenExit = vstd::find_pos(exits, neededExit);
|
chosenExit = vstd::find_pos(exits, neededExit);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto exit : exits)
|
for(auto exit : exits)
|
||||||
{
|
{
|
||||||
if(status.channelProbing() && exit.first == destinationTeleport)
|
if(status.channelProbing() && exit.first == destinationTeleport)
|
||||||
{
|
{
|
||||||
choosenExit = vstd::find_pos(exits, exit);
|
chosenExit = vstd::find_pos(exits, exit);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -716,7 +716,7 @@ void VCAI::showTeleportDialog(const CGHeroInstance * hero, TeleportChannelID cha
|
|||||||
|
|
||||||
requestActionASAP([=]()
|
requestActionASAP([=]()
|
||||||
{
|
{
|
||||||
answerQuery(askID, choosenExit);
|
answerQuery(askID, chosenExit);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -942,7 +942,7 @@ void VCAI::mainLoop()
|
|||||||
while (possibleGoals.size())
|
while (possibleGoals.size())
|
||||||
{
|
{
|
||||||
//allow assign goals to heroes with 0 movement, but don't realize them
|
//allow assign goals to heroes with 0 movement, but don't realize them
|
||||||
//maybe there are beter ones left
|
//maybe there are better ones left
|
||||||
|
|
||||||
auto bestGoal = fh->chooseSolution(possibleGoals);
|
auto bestGoal = fh->chooseSolution(possibleGoals);
|
||||||
if (bestGoal->hero) //lock this hero to fulfill goal
|
if (bestGoal->hero) //lock this hero to fulfill goal
|
||||||
@ -1543,7 +1543,7 @@ void VCAI::completeGoal(Goals::TSubgoal goal)
|
|||||||
auto it = lockedHeroes.find(h);
|
auto it = lockedHeroes.find(h);
|
||||||
if(it != lockedHeroes.end())
|
if(it != lockedHeroes.end())
|
||||||
{
|
{
|
||||||
if(it->second == goal || it->second->fulfillsMe(goal)) //FIXME this is overspecified, fulfillsMe shoudl be complete
|
if(it->second == goal || it->second->fulfillsMe(goal)) //FIXME this is overspecified, fulfillsMe should be complete
|
||||||
{
|
{
|
||||||
logAi->debug(goal->completeMessage());
|
logAi->debug(goal->completeMessage());
|
||||||
lockedHeroes.erase(it); //goal fulfilled, free hero
|
lockedHeroes.erase(it); //goal fulfilled, free hero
|
||||||
@ -1735,7 +1735,7 @@ const CGObjectInstance * VCAI::lookForArt(ArtifactID aid) const
|
|||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
//TODO what if more than one artifact is available? return them all or some slection criteria
|
//TODO what if more than one artifact is available? return them all or some selection criteria
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VCAI::isAccessible(const int3 & pos) const
|
bool VCAI::isAccessible(const int3 & pos) const
|
||||||
@ -2110,7 +2110,7 @@ void VCAI::tryRealize(Goals::Trade & g) //trade
|
|||||||
if(ah->freeResources()[g.resID] >= g.value) //goal is already fulfilled. Why we need this check, anyway?
|
if(ah->freeResources()[g.resID] >= g.value) //goal is already fulfilled. Why we need this check, anyway?
|
||||||
throw goalFulfilledException(sptr(g));
|
throw goalFulfilledException(sptr(g));
|
||||||
|
|
||||||
int accquiredResources = 0;
|
int acquiredResources = 0;
|
||||||
if(const CGObjectInstance * obj = cb->getObj(ObjectInstanceID(g.objid), false))
|
if(const CGObjectInstance * obj = cb->getObj(ObjectInstanceID(g.objid), false))
|
||||||
{
|
{
|
||||||
if(const auto * m = dynamic_cast<const IMarket*>(obj))
|
if(const auto * m = dynamic_cast<const IMarket*>(obj))
|
||||||
@ -2130,8 +2130,8 @@ void VCAI::tryRealize(Goals::Trade & g) //trade
|
|||||||
if (toGive) //don't try to sell 0 resources
|
if (toGive) //don't try to sell 0 resources
|
||||||
{
|
{
|
||||||
cb->trade(m, EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
|
cb->trade(m, EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
|
||||||
accquiredResources = static_cast<int>(toGet * (it->resVal / toGive));
|
acquiredResources = static_cast<int>(toGet * (it->resVal / toGive));
|
||||||
logAi->debug("Traded %d of %s for %d of %s at %s", toGive, res, accquiredResources, g.resID, obj->getObjectName());
|
logAi->debug("Traded %d of %s for %d of %s at %s", toGive, res, acquiredResources, g.resID, obj->getObjectName());
|
||||||
}
|
}
|
||||||
if (ah->freeResources()[g.resID] >= g.value)
|
if (ah->freeResources()[g.resID] >= g.value)
|
||||||
throw goalFulfilledException(sptr(g)); //we traded all we needed
|
throw goalFulfilledException(sptr(g)); //we traded all we needed
|
||||||
|
@ -83,7 +83,7 @@ public:
|
|||||||
//std::vector<const CGObjectInstance *> visitedThisWeek; //only OPWs
|
//std::vector<const CGObjectInstance *> visitedThisWeek; //only OPWs
|
||||||
std::map<HeroPtr, std::set<const CGTownInstance *>> townVisitsThisWeek;
|
std::map<HeroPtr, std::set<const CGTownInstance *>> townVisitsThisWeek;
|
||||||
|
|
||||||
//part of mainLoop, but accessible from outisde
|
//part of mainLoop, but accessible from outside
|
||||||
std::vector<Goals::TSubgoal> basicGoals;
|
std::vector<Goals::TSubgoal> basicGoals;
|
||||||
Goals::TGoalVec goalsToRemove;
|
Goals::TGoalVec goalsToRemove;
|
||||||
Goals::TGoalVec goalsToAdd;
|
Goals::TGoalVec goalsToAdd;
|
||||||
|
@ -69,7 +69,7 @@ public:
|
|||||||
//hero
|
//hero
|
||||||
virtual void moveHero(const CGHeroInstance *h, const std::vector<int3> & path, bool transit) =0; //moves hero alongside provided path
|
virtual void moveHero(const CGHeroInstance *h, const std::vector<int3> & path, bool transit) =0; //moves hero alongside provided path
|
||||||
virtual void moveHero(const CGHeroInstance *h, const int3 & destination, bool transit) =0; //moves hero alongside provided path
|
virtual void moveHero(const CGHeroInstance *h, const int3 & destination, bool transit) =0; //moves hero alongside provided path
|
||||||
virtual bool dismissHero(const CGHeroInstance * hero)=0; //dismisses given hero; true - successfuly, false - not successfuly
|
virtual bool dismissHero(const CGHeroInstance * hero)=0; //dismisses given hero; true - successfully, false - not successfully
|
||||||
virtual void dig(const CGObjectInstance *hero)=0;
|
virtual void dig(const CGObjectInstance *hero)=0;
|
||||||
virtual void castSpell(const CGHeroInstance *hero, SpellID spellID, const int3 &pos = int3(-1, -1, -1))=0; //cast adventure map spell
|
virtual void castSpell(const CGHeroInstance *hero, SpellID spellID, const int3 &pos = int3(-1, -1, -1))=0; //cast adventure map spell
|
||||||
|
|
||||||
|
@ -486,15 +486,15 @@ Done:
|
|||||||
Exch $R1
|
Exch $R1
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
|
|
||||||
Function ConditionalAddToRegisty
|
Function ConditionalAddToRegistry
|
||||||
Pop $0
|
Pop $0
|
||||||
Pop $1
|
Pop $1
|
||||||
StrCmp "$0" "" ConditionalAddToRegisty_EmptyString
|
StrCmp "$0" "" ConditionalAddToRegistry_EmptyString
|
||||||
WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" \
|
WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" \
|
||||||
"$1" "$0"
|
"$1" "$0"
|
||||||
;MessageBox MB_OK "Set Registry: '$1' to '$0'"
|
;MessageBox MB_OK "Set Registry: '$1' to '$0'"
|
||||||
DetailPrint "Set install registry entry: '$1' to '$0'"
|
DetailPrint "Set install registry entry: '$1' to '$0'"
|
||||||
ConditionalAddToRegisty_EmptyString:
|
ConditionalAddToRegistry_EmptyString:
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
|
|
||||||
;--------------------------------
|
;--------------------------------
|
||||||
@ -646,44 +646,44 @@ Section "-Core installation"
|
|||||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||||
Push "DisplayName"
|
Push "DisplayName"
|
||||||
Push "@CPACK_NSIS_DISPLAY_NAME@"
|
Push "@CPACK_NSIS_DISPLAY_NAME@"
|
||||||
Call ConditionalAddToRegisty
|
Call ConditionalAddToRegistry
|
||||||
Push "DisplayVersion"
|
Push "DisplayVersion"
|
||||||
Push "@CPACK_PACKAGE_VERSION@"
|
Push "@CPACK_PACKAGE_VERSION@"
|
||||||
Call ConditionalAddToRegisty
|
Call ConditionalAddToRegistry
|
||||||
Push "Publisher"
|
Push "Publisher"
|
||||||
Push "@CPACK_PACKAGE_VENDOR@"
|
Push "@CPACK_PACKAGE_VENDOR@"
|
||||||
Call ConditionalAddToRegisty
|
Call ConditionalAddToRegistry
|
||||||
Push "UninstallString"
|
Push "UninstallString"
|
||||||
Push "$INSTDIR\Uninstall.exe"
|
Push "$INSTDIR\Uninstall.exe"
|
||||||
Call ConditionalAddToRegisty
|
Call ConditionalAddToRegistry
|
||||||
Push "NoRepair"
|
Push "NoRepair"
|
||||||
Push "1"
|
Push "1"
|
||||||
Call ConditionalAddToRegisty
|
Call ConditionalAddToRegistry
|
||||||
|
|
||||||
!ifdef CPACK_NSIS_ADD_REMOVE
|
!ifdef CPACK_NSIS_ADD_REMOVE
|
||||||
;Create add/remove functionality
|
;Create add/remove functionality
|
||||||
Push "ModifyPath"
|
Push "ModifyPath"
|
||||||
Push "$INSTDIR\AddRemove.exe"
|
Push "$INSTDIR\AddRemove.exe"
|
||||||
Call ConditionalAddToRegisty
|
Call ConditionalAddToRegistry
|
||||||
!else
|
!else
|
||||||
Push "NoModify"
|
Push "NoModify"
|
||||||
Push "1"
|
Push "1"
|
||||||
Call ConditionalAddToRegisty
|
Call ConditionalAddToRegistry
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
; Optional registration
|
; Optional registration
|
||||||
Push "DisplayIcon"
|
Push "DisplayIcon"
|
||||||
Push "$INSTDIR\@CPACK_NSIS_INSTALLED_ICON_NAME@"
|
Push "$INSTDIR\@CPACK_NSIS_INSTALLED_ICON_NAME@"
|
||||||
Call ConditionalAddToRegisty
|
Call ConditionalAddToRegistry
|
||||||
Push "HelpLink"
|
Push "HelpLink"
|
||||||
Push "@CPACK_NSIS_HELP_LINK@"
|
Push "@CPACK_NSIS_HELP_LINK@"
|
||||||
Call ConditionalAddToRegisty
|
Call ConditionalAddToRegistry
|
||||||
Push "URLInfoAbout"
|
Push "URLInfoAbout"
|
||||||
Push "@CPACK_NSIS_URL_INFO_ABOUT@"
|
Push "@CPACK_NSIS_URL_INFO_ABOUT@"
|
||||||
Call ConditionalAddToRegisty
|
Call ConditionalAddToRegistry
|
||||||
Push "Contact"
|
Push "Contact"
|
||||||
Push "@CPACK_NSIS_CONTACT@"
|
Push "@CPACK_NSIS_CONTACT@"
|
||||||
Call ConditionalAddToRegisty
|
Call ConditionalAddToRegistry
|
||||||
!insertmacro MUI_INSTALLOPTIONS_READ $INSTALL_DESKTOP "NSIS.InstallOptions.ini" "Field 5" "State"
|
!insertmacro MUI_INSTALLOPTIONS_READ $INSTALL_DESKTOP "NSIS.InstallOptions.ini" "Field 5" "State"
|
||||||
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
|
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
|
||||||
|
|
||||||
@ -701,19 +701,19 @@ Section "-Core installation"
|
|||||||
; Write special uninstall registry entries
|
; Write special uninstall registry entries
|
||||||
Push "StartMenu"
|
Push "StartMenu"
|
||||||
Push "$STARTMENU_FOLDER"
|
Push "$STARTMENU_FOLDER"
|
||||||
Call ConditionalAddToRegisty
|
Call ConditionalAddToRegistry
|
||||||
Push "DoNotAddToPath"
|
Push "DoNotAddToPath"
|
||||||
Push "$DO_NOT_ADD_TO_PATH"
|
Push "$DO_NOT_ADD_TO_PATH"
|
||||||
Call ConditionalAddToRegisty
|
Call ConditionalAddToRegistry
|
||||||
Push "AddToPathAllUsers"
|
Push "AddToPathAllUsers"
|
||||||
Push "$ADD_TO_PATH_ALL_USERS"
|
Push "$ADD_TO_PATH_ALL_USERS"
|
||||||
Call ConditionalAddToRegisty
|
Call ConditionalAddToRegistry
|
||||||
Push "AddToPathCurrentUser"
|
Push "AddToPathCurrentUser"
|
||||||
Push "$ADD_TO_PATH_CURRENT_USER"
|
Push "$ADD_TO_PATH_CURRENT_USER"
|
||||||
Call ConditionalAddToRegisty
|
Call ConditionalAddToRegistry
|
||||||
Push "InstallToDesktop"
|
Push "InstallToDesktop"
|
||||||
Push "$INSTALL_DESKTOP"
|
Push "$INSTALL_DESKTOP"
|
||||||
Call ConditionalAddToRegisty
|
Call ConditionalAddToRegistry
|
||||||
|
|
||||||
!insertmacro MUI_STARTMENU_WRITE_END
|
!insertmacro MUI_STARTMENU_WRITE_END
|
||||||
|
|
||||||
@ -848,7 +848,7 @@ Section "Uninstall"
|
|||||||
@CPACK_NSIS_DELETE_ICONS@
|
@CPACK_NSIS_DELETE_ICONS@
|
||||||
@CPACK_NSIS_DELETE_ICONS_EXTRA@
|
@CPACK_NSIS_DELETE_ICONS_EXTRA@
|
||||||
|
|
||||||
;Delete empty start menu parent diretories
|
;Delete empty start menu parent directories
|
||||||
StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"
|
StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"
|
||||||
|
|
||||||
startMenuDeleteLoop:
|
startMenuDeleteLoop:
|
||||||
@ -867,7 +867,7 @@ Section "Uninstall"
|
|||||||
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
|
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
|
||||||
@CPACK_NSIS_DELETE_ICONS_EXTRA@
|
@CPACK_NSIS_DELETE_ICONS_EXTRA@
|
||||||
|
|
||||||
;Delete empty start menu parent diretories
|
;Delete empty start menu parent directories
|
||||||
StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"
|
StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"
|
||||||
|
|
||||||
secondStartMenuDeleteLoop:
|
secondStartMenuDeleteLoop:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Minimum required version greatly affect CMake behavior
|
# Minimum required version greatly affect CMake behavior
|
||||||
# So cmake_minimum_required must be called before the project()
|
# So cmake_minimum_required must be called before the project()
|
||||||
# 3.16.0 is used since it's used by our currently oldest suppored system: Ubuntu-20.04
|
# 3.16.0 is used since it's used by our currently oldest supported system: Ubuntu-20.04
|
||||||
cmake_minimum_required(VERSION 3.16.0)
|
cmake_minimum_required(VERSION 3.16.0)
|
||||||
|
|
||||||
project(VCMI)
|
project(VCMI)
|
||||||
|
44
ChangeLog.md
44
ChangeLog.md
@ -40,7 +40,7 @@
|
|||||||
* Fixed wrong order of activating mods in chain when installing multiple mods at once
|
* Fixed wrong order of activating mods in chain when installing multiple mods at once
|
||||||
* Mod list no longer shows mod version column. Version is now only shown in the mod description.
|
* Mod list no longer shows mod version column. Version is now only shown in the mod description.
|
||||||
* Launcher will now skip the Heroes 3 data import step if data has been found automatically
|
* Launcher will now skip the Heroes 3 data import step if data has been found automatically
|
||||||
* Fixed inport of existing data files on iOS. This option now requires iOS 13 or later
|
* Fixed import of existing data files on iOS. This option now requires iOS 13 or later
|
||||||
* Fixed import using offline installer on iOS.
|
* Fixed import using offline installer on iOS.
|
||||||
* Buttons to open data directories in the Help tab are now hidden on mobile systems if they can't be opened with file browser
|
* Buttons to open data directories in the Help tab are now hidden on mobile systems if they can't be opened with file browser
|
||||||
* Added the configuration files directory to the Help tab as it is located separately on Linux systems
|
* Added the configuration files directory to the Help tab as it is located separately on Linux systems
|
||||||
@ -321,7 +321,7 @@
|
|||||||
|
|
||||||
### Battles
|
### Battles
|
||||||
* Added option to enable unlimited combat replays during game setup
|
* Added option to enable unlimited combat replays during game setup
|
||||||
* Added option to instantly end battle using quick combat (shotcut: 'e')
|
* Added option to instantly end battle using quick combat (shortcut: 'e')
|
||||||
* Added option to replace auto-combat button action with instant end using quick combat
|
* Added option to replace auto-combat button action with instant end using quick combat
|
||||||
* Battles against AI players can now be done using quick combat
|
* Battles against AI players can now be done using quick combat
|
||||||
* Disabling battle queue will now correctly reposition hero statistics preview popup
|
* Disabling battle queue will now correctly reposition hero statistics preview popup
|
||||||
@ -885,7 +885,7 @@
|
|||||||
### GENERAL:
|
### GENERAL:
|
||||||
* Fixed framerate drops on hero movement with active hota mod
|
* Fixed framerate drops on hero movement with active hota mod
|
||||||
* Fade-out animations will now be skipped when instant hero movement speed is used
|
* Fade-out animations will now be skipped when instant hero movement speed is used
|
||||||
* Restarting loaded campaing scenario will now correctly reapply starting bonus
|
* Restarting loaded campaign scenario will now correctly reapply starting bonus
|
||||||
* Reverted FPS limit on mobile systems back to 60 fps
|
* Reverted FPS limit on mobile systems back to 60 fps
|
||||||
* Fixed loading of translations for maps and campaigns
|
* Fixed loading of translations for maps and campaigns
|
||||||
* Fixed loading of preconfigured starting army for heroes with preconfigured spells
|
* Fixed loading of preconfigured starting army for heroes with preconfigured spells
|
||||||
@ -1051,7 +1051,7 @@
|
|||||||
* Battle opening sound can now be skipped with mouse click
|
* Battle opening sound can now be skipped with mouse click
|
||||||
* Fixed movement through moat of double-hexed units
|
* Fixed movement through moat of double-hexed units
|
||||||
* Fixed removal of Land Mines and Fire Walls
|
* Fixed removal of Land Mines and Fire Walls
|
||||||
* Obstacles will now corectly show up either below or above unit
|
* Obstacles will now correctly show up either below or above unit
|
||||||
* It is now possible to teleport a unit through destroyed walls
|
* It is now possible to teleport a unit through destroyed walls
|
||||||
* Added distinct overlay image for showing movement range of highlighted unit
|
* Added distinct overlay image for showing movement range of highlighted unit
|
||||||
* Added overlay for displaying shooting range penalties of units
|
* Added overlay for displaying shooting range penalties of units
|
||||||
@ -1171,7 +1171,7 @@
|
|||||||
* RMG will no longer place shipyards or boats at very small lakes
|
* RMG will no longer place shipyards or boats at very small lakes
|
||||||
* Fixed placement of shipyards in invalid locations
|
* Fixed placement of shipyards in invalid locations
|
||||||
* Fixed potential game hang on generation of random map
|
* Fixed potential game hang on generation of random map
|
||||||
* RMG will now generate addditional monolith pairs to create required number of zone connections
|
* RMG will now generate additional monolith pairs to create required number of zone connections
|
||||||
* RMG will try to place Subterranean Gates as far away from other objects (including each other) as possible
|
* RMG will try to place Subterranean Gates as far away from other objects (including each other) as possible
|
||||||
* RMG will now try to place objects as far as possible in both zones sharing a guard, not only the first one.
|
* RMG will now try to place objects as far as possible in both zones sharing a guard, not only the first one.
|
||||||
* Use only one template for an object in zone
|
* Use only one template for an object in zone
|
||||||
@ -1195,7 +1195,7 @@
|
|||||||
* Added option to show amount of creatures as numeric range rather than adjective
|
* Added option to show amount of creatures as numeric range rather than adjective
|
||||||
* Added option to show map grid
|
* Added option to show map grid
|
||||||
* Map swipe is no longer exclusive for phones and can be enabled on desktop platforms
|
* Map swipe is no longer exclusive for phones and can be enabled on desktop platforms
|
||||||
* Added more graduated settigns for hero movement speed
|
* Added more graduated settings for hero movement speed
|
||||||
* Map scrolling is now more graduated and scrolls with pixel-level precision
|
* Map scrolling is now more graduated and scrolls with pixel-level precision
|
||||||
* Hero movement speed now matches H3
|
* Hero movement speed now matches H3
|
||||||
* Improved performance of adventure map rendering
|
* Improved performance of adventure map rendering
|
||||||
@ -1214,7 +1214,7 @@
|
|||||||
* Fixed white status bar on server connection screen
|
* Fixed white status bar on server connection screen
|
||||||
* Buttons in battle window now correctly show tooltip in status bar
|
* Buttons in battle window now correctly show tooltip in status bar
|
||||||
* Fixed cursor image during enemy turn in combat
|
* Fixed cursor image during enemy turn in combat
|
||||||
* Game will no longer promt to assemble artifacts if they fall into backpack
|
* Game will no longer prompt to assemble artifacts if they fall into backpack
|
||||||
* It is now possible to use in-game console for vcmi commands
|
* It is now possible to use in-game console for vcmi commands
|
||||||
* Stacks sized 1000-9999 units will not be displayed as "1k"
|
* Stacks sized 1000-9999 units will not be displayed as "1k"
|
||||||
* It is now possible to select destination town for Town Portal via double-click
|
* It is now possible to select destination town for Town Portal via double-click
|
||||||
@ -1300,7 +1300,7 @@
|
|||||||
* Dragon Breath attack now correctly uses different attack animation if multiple targets are hit
|
* Dragon Breath attack now correctly uses different attack animation if multiple targets are hit
|
||||||
* Petrification: implemented visual effect
|
* Petrification: implemented visual effect
|
||||||
* Paralyze: added visual effect
|
* Paralyze: added visual effect
|
||||||
* Blind: Stacks will no longer retailate on attack that blinds them
|
* Blind: Stacks will no longer retaliate on attack that blinds them
|
||||||
* Demon Summon: Added animation effect for summoning
|
* Demon Summon: Added animation effect for summoning
|
||||||
* Fire shield will no longer trigger on non-adjacent attacks, e.g. from Dragon Breath
|
* Fire shield will no longer trigger on non-adjacent attacks, e.g. from Dragon Breath
|
||||||
* Weakness now has correct visual effect
|
* Weakness now has correct visual effect
|
||||||
@ -1479,7 +1479,7 @@
|
|||||||
* treasury
|
* treasury
|
||||||
|
|
||||||
### SOUND:
|
### SOUND:
|
||||||
* Fixed many mising or wrong pickup and visit sounds for map objects
|
* Fixed many missing or wrong pickup and visit sounds for map objects
|
||||||
* All map objects now have ambient sounds identical to OH3
|
* All map objects now have ambient sounds identical to OH3
|
||||||
|
|
||||||
### RANDOM MAP GENERATOR:
|
### RANDOM MAP GENERATOR:
|
||||||
@ -1532,7 +1532,7 @@
|
|||||||
* New console commands:
|
* New console commands:
|
||||||
* gosolo - AI take control over human players and vice versa
|
* gosolo - AI take control over human players and vice versa
|
||||||
* controlai - give control of one or all AIs to player
|
* controlai - give control of one or all AIs to player
|
||||||
* set hideSystemMessages on/off - supress server messages in chat
|
* set hideSystemMessages on/off - suppress server messages in chat
|
||||||
|
|
||||||
### BATTLES:
|
### BATTLES:
|
||||||
* Drawbridge mechanics implemented (animation still missing)
|
* Drawbridge mechanics implemented (animation still missing)
|
||||||
@ -1574,7 +1574,7 @@
|
|||||||
* View Earth
|
* View Earth
|
||||||
* Visions
|
* Visions
|
||||||
* Disguise
|
* Disguise
|
||||||
* Implemented CURE spell negative dispell effect
|
* Implemented CURE spell negative dispel effect
|
||||||
* Added LOCATION target for spells castable on any hex with new target modifiers
|
* Added LOCATION target for spells castable on any hex with new target modifiers
|
||||||
|
|
||||||
### BATTLES:
|
### BATTLES:
|
||||||
@ -1597,7 +1597,7 @@
|
|||||||
* VCMI can now be compiled with SDL2
|
* VCMI can now be compiled with SDL2
|
||||||
* Movies will use ffmpeg library
|
* Movies will use ffmpeg library
|
||||||
* change boost::bind to std::bind
|
* change boost::bind to std::bind
|
||||||
* removed boost::asign
|
* removed boost::assign
|
||||||
* Updated FuzzyLite to 5.0
|
* Updated FuzzyLite to 5.0
|
||||||
* Multiplayer load support was implemented through command-line options
|
* Multiplayer load support was implemented through command-line options
|
||||||
|
|
||||||
@ -1646,7 +1646,7 @@
|
|||||||
* Zone placement
|
* Zone placement
|
||||||
* Zone borders and connections, fractalized paths inside zones
|
* Zone borders and connections, fractalized paths inside zones
|
||||||
* Guard generation
|
* Guard generation
|
||||||
* Treasue piles generation (so far only few removable objects)
|
* Treasure piles generation (so far only few removable objects)
|
||||||
|
|
||||||
### MODS:
|
### MODS:
|
||||||
* Support for submods - mod may have their own "submods" located in <modname>/Mods directory
|
* Support for submods - mod may have their own "submods" located in <modname>/Mods directory
|
||||||
@ -1753,7 +1753,7 @@
|
|||||||
* Improved json validation. Now it support most of features from latest json schema draft.
|
* Improved json validation. Now it support most of features from latest json schema draft.
|
||||||
* Icons use path to icon instead of image indexes.
|
* Icons use path to icon instead of image indexes.
|
||||||
* It is possible to edit data of another mod or H3 data via mods.
|
* It is possible to edit data of another mod or H3 data via mods.
|
||||||
* Mods can access only ID's from dependenies, virtual "core" mod and itself (optional for some mods compatibility)
|
* Mods can access only ID's from dependencies, virtual "core" mod and itself (optional for some mods compatibility)
|
||||||
* Removed no longer needed field "projectile spins"
|
* Removed no longer needed field "projectile spins"
|
||||||
* Heroes: split heroes.json in manner similar to creatures\factions; string ID's for H3 heroes; h3 hero classes and artifacts can be modified via json.
|
* Heroes: split heroes.json in manner similar to creatures\factions; string ID's for H3 heroes; h3 hero classes and artifacts can be modified via json.
|
||||||
|
|
||||||
@ -1870,7 +1870,7 @@
|
|||||||
* Fixed a possible freeze when exchanging resources at marketplace
|
* Fixed a possible freeze when exchanging resources at marketplace
|
||||||
|
|
||||||
### BATTLE AI:
|
### BATTLE AI:
|
||||||
* It is possible to select a battle AI module used by VCMI by typing into the console "setBattleAI <name>". The names of avaialble modules are "StupidAI" and "BattleAI". BattleAI may be a little smarter but less stable. By the default, StupidAI will be used, as in previous releases.
|
* It is possible to select a battle AI module used by VCMI by typing into the console "setBattleAI <name>". The names of available modules are "StupidAI" and "BattleAI". BattleAI may be a little smarter but less stable. By the default, StupidAI will be used, as in previous releases.
|
||||||
* New battle AI module: "BattleAI" that is smarter and capable of casting some offensive and enchantment spells
|
* New battle AI module: "BattleAI" that is smarter and capable of casting some offensive and enchantment spells
|
||||||
|
|
||||||
# 0.88 -> 0.89 (Jun 01 2012)
|
# 0.88 -> 0.89 (Jun 01 2012)
|
||||||
@ -1963,7 +1963,7 @@
|
|||||||
* No wall penalty
|
* No wall penalty
|
||||||
* Enchanter
|
* Enchanter
|
||||||
* Bind
|
* Bind
|
||||||
* Dispell helpful spells
|
* Dispel helpful spells
|
||||||
|
|
||||||
# 0.85 -> 0.86 (Sep 01 2011)
|
# 0.85 -> 0.86 (Sep 01 2011)
|
||||||
|
|
||||||
@ -2085,7 +2085,7 @@
|
|||||||
* Spell damage specialities (Deemer), fixed bonus (Ciele)
|
* Spell damage specialities (Deemer), fixed bonus (Ciele)
|
||||||
* Secondary skill bonuses
|
* Secondary skill bonuses
|
||||||
* Creature Upgrades (Gelu)
|
* Creature Upgrades (Gelu)
|
||||||
* Resorce generation
|
* Resource generation
|
||||||
* Starting Skill (Adrienne)
|
* Starting Skill (Adrienne)
|
||||||
|
|
||||||
### TOWNS:
|
### TOWNS:
|
||||||
@ -2224,7 +2224,7 @@ http://bugs.vcmi.eu/changelog_page.php?version_id=14
|
|||||||
* Clicking on the border no longer opens an empty info windows
|
* Clicking on the border no longer opens an empty info windows
|
||||||
|
|
||||||
### HERO WINDOW:
|
### HERO WINDOW:
|
||||||
* Improved artifact moving. Available slots are higlighted. Moved artifact is bound to mouse cursor.
|
* Improved artifact moving. Available slots are highlighted. Moved artifact is bound to mouse cursor.
|
||||||
|
|
||||||
### TOWNS:
|
### TOWNS:
|
||||||
* new special town structures supported:
|
* new special town structures supported:
|
||||||
@ -2237,7 +2237,7 @@ http://bugs.vcmi.eu/changelog_page.php?version_id=14
|
|||||||
### OBJECTS:
|
### OBJECTS:
|
||||||
* External dwellings increase town growth
|
* External dwellings increase town growth
|
||||||
* Right-click info window for castles and garrisons you do not own shows a rough amount of creatures instead of none
|
* Right-click info window for castles and garrisons you do not own shows a rough amount of creatures instead of none
|
||||||
* Scholar won't give unavaliable spells anymore.
|
* Scholar won't give unavailable spells anymore.
|
||||||
|
|
||||||
A lot of of various bugfixes and improvements:
|
A lot of of various bugfixes and improvements:
|
||||||
http://bugs.vcmi.eu/changelog_page.php?version_id=2
|
http://bugs.vcmi.eu/changelog_page.php?version_id=2
|
||||||
@ -2257,7 +2257,7 @@ http://bugs.vcmi.eu/changelog_page.php?version_id=2
|
|||||||
* a few fixes for shipyard window
|
* a few fixes for shipyard window
|
||||||
|
|
||||||
### ADVENTURE INTERFACE:
|
### ADVENTURE INTERFACE:
|
||||||
* Cursor shows if tile is accesible and how many turns away
|
* Cursor shows if tile is accessible and how many turns away
|
||||||
* moving hero with arrow keys / numpad
|
* moving hero with arrow keys / numpad
|
||||||
* fixed Next Hero button behaviour
|
* fixed Next Hero button behaviour
|
||||||
* fixed Surface/Underground switch button in higher resolutions
|
* fixed Surface/Underground switch button in higher resolutions
|
||||||
@ -2426,7 +2426,7 @@ http://bugs.vcmi.eu/changelog_page.php?version_id=2
|
|||||||
* Diplomacy secondary skill support
|
* Diplomacy secondary skill support
|
||||||
* timed events won't cause resources amount to be negative
|
* timed events won't cause resources amount to be negative
|
||||||
* support for sorcery secondary skill
|
* support for sorcery secondary skill
|
||||||
* reduntant quotation marks from artifact descriptions are removed
|
* redundant quotation marks from artifact descriptions are removed
|
||||||
* no income at the first day
|
* no income at the first day
|
||||||
|
|
||||||
### ADVENTURE INTERFACE:
|
### ADVENTURE INTERFACE:
|
||||||
@ -2954,7 +2954,7 @@ And a lot of minor fixes
|
|||||||
* [feature] picked artifacts are added to hero's backpack
|
* [feature] picked artifacts are added to hero's backpack
|
||||||
* [feature] possibility of choosing player to play
|
* [feature] possibility of choosing player to play
|
||||||
* [bugfix] ZELP.TXT file *should* be handled correctly even it is non-english
|
* [bugfix] ZELP.TXT file *should* be handled correctly even it is non-english
|
||||||
* [bugfix] fixed crashbug in reading defs with negativ left/right margins
|
* [bugfix] fixed crashbug in reading defs with negative left/right margins
|
||||||
* [bugfix] improved randomization
|
* [bugfix] improved randomization
|
||||||
* [bugfix] pathfinder can't be cheated (what caused errors)
|
* [bugfix] pathfinder can't be cheated (what caused errors)
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
|||||||
| InputDevice.SOURCE_CLASS_POSITION
|
| InputDevice.SOURCE_CLASS_POSITION
|
||||||
| InputDevice.SOURCE_CLASS_TRACKBALL);
|
| InputDevice.SOURCE_CLASS_TRACKBALL);
|
||||||
|
|
||||||
if (s2 != 0) cls += "Some_Unkown";
|
if (s2 != 0) cls += "Some_Unknown";
|
||||||
|
|
||||||
s2 = s_copy & InputDevice.SOURCE_ANY; // keep source only, no class;
|
s2 = s_copy & InputDevice.SOURCE_ANY; // keep source only, no class;
|
||||||
|
|
||||||
@ -163,7 +163,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
|||||||
if (s == FLAG_TAINTED) src += " FLAG_TAINTED";
|
if (s == FLAG_TAINTED) src += " FLAG_TAINTED";
|
||||||
s2 &= ~FLAG_TAINTED;
|
s2 &= ~FLAG_TAINTED;
|
||||||
|
|
||||||
if (s2 != 0) src += " Some_Unkown";
|
if (s2 != 0) src += " Some_Unknown";
|
||||||
|
|
||||||
Log.v(TAG, prefix + "int=" + s_copy + " CLASS={" + cls + " } source(s):" + src);
|
Log.v(TAG, prefix + "int=" + s_copy + " CLASS={" + cls + " } source(s):" + src);
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ public:
|
|||||||
extern CClientState * CCS;
|
extern CClientState * CCS;
|
||||||
|
|
||||||
/// CGameInfo class
|
/// CGameInfo class
|
||||||
/// for allowing different functions for accessing game informations
|
/// for allowing different functions for accessing game information
|
||||||
class CGameInfo final : public Services
|
class CGameInfo final : public Services
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -282,7 +282,7 @@ int main(int argc, char * argv[])
|
|||||||
GH.init();
|
GH.init();
|
||||||
|
|
||||||
CCS = new CClientState();
|
CCS = new CClientState();
|
||||||
CGI = new CGameInfo(); //contains all global informations about game (texts, lodHandlers, map handler etc.)
|
CGI = new CGameInfo(); //contains all global information about game (texts, lodHandlers, map handler etc.)
|
||||||
CSH = new CServerHandler();
|
CSH = new CServerHandler();
|
||||||
|
|
||||||
// Initialize video
|
// Initialize video
|
||||||
@ -525,7 +525,7 @@ void handleQuit(bool ask)
|
|||||||
|
|
||||||
void handleFatalError(const std::string & message, bool terminate)
|
void handleFatalError(const std::string & message, bool terminate)
|
||||||
{
|
{
|
||||||
logGlobal->error("FATAL ERROR ENCOUTERED, VCMI WILL NOW TERMINATE");
|
logGlobal->error("FATAL ERROR ENCOUNTERED, VCMI WILL NOW TERMINATE");
|
||||||
logGlobal->error("Reason: %s", message);
|
logGlobal->error("Reason: %s", message);
|
||||||
|
|
||||||
std::string messageToShow = "Fatal error! " + message;
|
std::string messageToShow = "Fatal error! " + message;
|
||||||
|
@ -22,6 +22,6 @@ extern SDL_Surface *screenBuf; // points to screen (if only advmapint is present
|
|||||||
|
|
||||||
void handleQuit(bool ask = true);
|
void handleQuit(bool ask = true);
|
||||||
|
|
||||||
/// Notify user about encoutered fatal error and terminate the game
|
/// Notify user about encountered fatal error and terminate the game
|
||||||
/// TODO: decide on better location for this method
|
/// TODO: decide on better location for this method
|
||||||
[[noreturn]] void handleFatalError(const std::string & message, bool terminate);
|
[[noreturn]] void handleFatalError(const std::string & message, bool terminate);
|
||||||
|
@ -142,7 +142,7 @@ protected: // Call-ins from server, should not be called directly, but only via
|
|||||||
void objectRemovedAfter() override;
|
void objectRemovedAfter() override;
|
||||||
void playerBlocked(int reason, bool start) override;
|
void playerBlocked(int reason, bool start) override;
|
||||||
void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) override;
|
void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) override;
|
||||||
void playerStartsTurn(PlayerColor player) override; //called before yourTurn on active itnerface
|
void playerStartsTurn(PlayerColor player) override; //called before yourTurn on active interface
|
||||||
void playerEndsTurn(PlayerColor player) override;
|
void playerEndsTurn(PlayerColor player) override;
|
||||||
void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override;
|
void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override;
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ class ClientCommandManager //take mantis #2292 issue about account if thinking a
|
|||||||
// Export file into Extracted directory
|
// Export file into Extracted directory
|
||||||
void handleExtractCommand(std::istringstream& singleWordBuffer);
|
void handleExtractCommand(std::istringstream& singleWordBuffer);
|
||||||
|
|
||||||
// Print in console the current bonuses for curent army
|
// Print in console the current bonuses for current army
|
||||||
void handleBonusesCommand(std::istringstream & singleWordBuffer);
|
void handleBonusesCommand(std::istringstream & singleWordBuffer);
|
||||||
|
|
||||||
// Get what artifact is present on artifact slot with specified ID for hero with specified ID
|
// Get what artifact is present on artifact slot with specified ID for hero with specified ID
|
||||||
|
@ -118,7 +118,7 @@ void callBattleInterfaceIfPresentForBothSides(CClient & cl, const BattleID & bat
|
|||||||
|
|
||||||
void ApplyClientNetPackVisitor::visitSetResources(SetResources & pack)
|
void ApplyClientNetPackVisitor::visitSetResources(SetResources & pack)
|
||||||
{
|
{
|
||||||
//todo: inform on actual resource set transfered
|
//todo: inform on actual resource set transferred
|
||||||
callInterfaceIfPresent(cl, pack.player, &IGameEventsReceiver::receivedResource);
|
callInterfaceIfPresent(cl, pack.player, &IGameEventsReceiver::receivedResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -844,7 +844,7 @@ void ApplyFirstClientNetPackVisitor::visitBattleAttack(BattleAttack & pack)
|
|||||||
{
|
{
|
||||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleAttack, pack.battleID, &pack);
|
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleAttack, pack.battleID, &pack);
|
||||||
|
|
||||||
// battleStacksAttacked should be excuted before BattleAttack.applyGs() to play animation before damaging unit
|
// battleStacksAttacked should be executed before BattleAttack.applyGs() to play animation before damaging unit
|
||||||
// so this has to be here instead of ApplyClientNetPackVisitor::visitBattleAttack()
|
// so this has to be here instead of ApplyClientNetPackVisitor::visitBattleAttack()
|
||||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleStacksAttacked, pack.battleID, pack.bsa, pack.shot());
|
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleStacksAttacked, pack.battleID, pack.bsa, pack.shot());
|
||||||
}
|
}
|
||||||
|
@ -221,7 +221,7 @@ void CInGameConsole::keyPressed (EShortcut key)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInGameConsole::textInputed(const std::string & inputtedText)
|
void CInGameConsole::textInputted(const std::string & inputtedText)
|
||||||
{
|
{
|
||||||
if (LOCPLINT->cingconsole != this)
|
if (LOCPLINT->cingconsole != this)
|
||||||
return;
|
return;
|
||||||
|
@ -50,7 +50,7 @@ public:
|
|||||||
void show(Canvas & to) override;
|
void show(Canvas & to) override;
|
||||||
void showAll(Canvas & to) override;
|
void showAll(Canvas & to) override;
|
||||||
void keyPressed(EShortcut key) override;
|
void keyPressed(EShortcut key) override;
|
||||||
void textInputed(const std::string & enteredText) override;
|
void textInputted(const std::string & enteredText) override;
|
||||||
void textEdited(const std::string & enteredText) override;
|
void textEdited(const std::string & enteredText) override;
|
||||||
bool captureThisKey(EShortcut key) override;
|
bool captureThisKey(EShortcut key) override;
|
||||||
|
|
||||||
|
@ -380,7 +380,7 @@ std::shared_ptr<CIntObject> CTownList::CTownItem::genSelection()
|
|||||||
|
|
||||||
void CTownList::CTownItem::update()
|
void CTownList::CTownItem::update()
|
||||||
{
|
{
|
||||||
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
|
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->built >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
|
||||||
|
|
||||||
picture->setFrame(iconIndex + 2);
|
picture->setFrame(iconIndex + 2);
|
||||||
redraw();
|
redraw();
|
||||||
|
@ -92,9 +92,9 @@ CMinimap::CMinimap(const Rect & position)
|
|||||||
{
|
{
|
||||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||||
|
|
||||||
double maxSideLenghtSrc = std::max(LOCPLINT->cb->getMapSize().x, LOCPLINT->cb->getMapSize().y);
|
double maxSideLengthSrc = std::max(LOCPLINT->cb->getMapSize().x, LOCPLINT->cb->getMapSize().y);
|
||||||
double maxSideLenghtDst = std::max(position.w, position.h);
|
double maxSideLengthDst = std::max(position.w, position.h);
|
||||||
double resize = maxSideLenghtSrc / maxSideLenghtDst;
|
double resize = maxSideLengthSrc / maxSideLengthDst;
|
||||||
Point newMinimapSize = Point(LOCPLINT->cb->getMapSize().x/ resize, LOCPLINT->cb->getMapSize().y / resize);
|
Point newMinimapSize = Point(LOCPLINT->cb->getMapSize().x/ resize, LOCPLINT->cb->getMapSize().y / resize);
|
||||||
Point offset = Point((std::max(newMinimapSize.x, newMinimapSize.y) - newMinimapSize.x) / 2, (std::max(newMinimapSize.x, newMinimapSize.y) - newMinimapSize.y) / 2);
|
Point offset = Point((std::max(newMinimapSize.x, newMinimapSize.y) - newMinimapSize.x) / 2, (std::max(newMinimapSize.x, newMinimapSize.y) - newMinimapSize.y) / 2);
|
||||||
|
|
||||||
|
@ -120,6 +120,6 @@ public:
|
|||||||
const std::vector<PossiblePlayerBattleAction> & getPossibleActions() const;
|
const std::vector<PossiblePlayerBattleAction> & getPossibleActions() const;
|
||||||
void removePossibleAction(PossiblePlayerBattleAction);
|
void removePossibleAction(PossiblePlayerBattleAction);
|
||||||
|
|
||||||
/// inserts possible action in the beggining in order to prioritize it
|
/// inserts possible action in the beginning in order to prioritize it
|
||||||
void pushFrontPossibleAction(PossiblePlayerBattleAction);
|
void pushFrontPossibleAction(PossiblePlayerBattleAction);
|
||||||
};
|
};
|
||||||
|
@ -355,9 +355,9 @@ bool MovementAnimation::init()
|
|||||||
myAnim->setType(ECreatureAnimType::MOVING);
|
myAnim->setType(ECreatureAnimType::MOVING);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moveSoundHander == -1)
|
if (moveSoundHandler == -1)
|
||||||
{
|
{
|
||||||
moveSoundHander = CCS->soundh->playSound(stack->unitType()->sounds.move, -1);
|
moveSoundHandler = CCS->soundh->playSound(stack->unitType()->sounds.move, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Point begPosition = owner.stacksController->getStackPositionAtHex(prevHex, stack);
|
Point begPosition = owner.stacksController->getStackPositionAtHex(prevHex, stack);
|
||||||
@ -398,12 +398,12 @@ void MovementAnimation::tick(uint32_t msPassed)
|
|||||||
myAnim->pos.moveTo(coords);
|
myAnim->pos.moveTo(coords);
|
||||||
|
|
||||||
// true if creature haven't reached the final destination hex
|
// true if creature haven't reached the final destination hex
|
||||||
if ((curentMoveIndex + 1) < destTiles.size())
|
if ((currentMoveIndex + 1) < destTiles.size())
|
||||||
{
|
{
|
||||||
// update the next hex field which has to be reached by the stack
|
// update the next hex field which has to be reached by the stack
|
||||||
curentMoveIndex++;
|
currentMoveIndex++;
|
||||||
prevHex = nextHex;
|
prevHex = nextHex;
|
||||||
nextHex = destTiles[curentMoveIndex];
|
nextHex = destTiles[currentMoveIndex];
|
||||||
|
|
||||||
// request re-initialization
|
// request re-initialization
|
||||||
initialized = false;
|
initialized = false;
|
||||||
@ -417,18 +417,18 @@ MovementAnimation::~MovementAnimation()
|
|||||||
{
|
{
|
||||||
assert(stack);
|
assert(stack);
|
||||||
|
|
||||||
if(moveSoundHander != -1)
|
if(moveSoundHandler != -1)
|
||||||
CCS->soundh->stopSound(moveSoundHander);
|
CCS->soundh->stopSound(moveSoundHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
MovementAnimation::MovementAnimation(BattleInterface & owner, const CStack *stack, std::vector<BattleHex> _destTiles, int _distance)
|
MovementAnimation::MovementAnimation(BattleInterface & owner, const CStack *stack, std::vector<BattleHex> _destTiles, int _distance)
|
||||||
: StackMoveAnimation(owner, stack, stack->getPosition(), _destTiles.front()),
|
: StackMoveAnimation(owner, stack, stack->getPosition(), _destTiles.front()),
|
||||||
destTiles(_destTiles),
|
destTiles(_destTiles),
|
||||||
curentMoveIndex(0),
|
currentMoveIndex(0),
|
||||||
begX(0), begY(0),
|
begX(0), begY(0),
|
||||||
distanceX(0), distanceY(0),
|
distanceX(0), distanceY(0),
|
||||||
progressPerSecond(0.0),
|
progressPerSecond(0.0),
|
||||||
moveSoundHander(-1),
|
moveSoundHandler(-1),
|
||||||
progress(0.0)
|
progress(0.0)
|
||||||
{
|
{
|
||||||
logAnim->debug("Created MovementAnimation for %s", stack->getName());
|
logAnim->debug("Created MovementAnimation for %s", stack->getName());
|
||||||
@ -649,7 +649,7 @@ void RangedAttackAnimation::setAnimationGroup()
|
|||||||
Point shooterPos = stackAnimation(attackingStack)->pos.topLeft();
|
Point shooterPos = stackAnimation(attackingStack)->pos.topLeft();
|
||||||
Point shotTarget = owner.stacksController->getStackPositionAtHex(dest, defendingStack);
|
Point shotTarget = owner.stacksController->getStackPositionAtHex(dest, defendingStack);
|
||||||
|
|
||||||
//maximal angle in radians between straight horizontal line and shooting line for which shot is considered to be straight (absoulte value)
|
//maximal angle in radians between straight horizontal line and shooting line for which shot is considered to be straight (absolute value)
|
||||||
static const double straightAngle = 0.2;
|
static const double straightAngle = 0.2;
|
||||||
|
|
||||||
double projectileAngle = -atan2(shotTarget.y - shooterPos.y, std::abs(shotTarget.x - shooterPos.x));
|
double projectileAngle = -atan2(shotTarget.y - shooterPos.y, std::abs(shotTarget.x - shooterPos.x));
|
||||||
@ -672,18 +672,18 @@ void RangedAttackAnimation::initializeProjectile()
|
|||||||
|
|
||||||
if (getGroup() == getUpwardsGroup())
|
if (getGroup() == getUpwardsGroup())
|
||||||
{
|
{
|
||||||
shotOrigin.x += ( -25 + shooterInfo->animation.upperRightMissleOffsetX ) * multiplier;
|
shotOrigin.x += ( -25 + shooterInfo->animation.upperRightMissileOffsetX ) * multiplier;
|
||||||
shotOrigin.y += shooterInfo->animation.upperRightMissleOffsetY;
|
shotOrigin.y += shooterInfo->animation.upperRightMissileOffsetY;
|
||||||
}
|
}
|
||||||
else if (getGroup() == getDownwardsGroup())
|
else if (getGroup() == getDownwardsGroup())
|
||||||
{
|
{
|
||||||
shotOrigin.x += ( -25 + shooterInfo->animation.lowerRightMissleOffsetX ) * multiplier;
|
shotOrigin.x += ( -25 + shooterInfo->animation.lowerRightMissileOffsetX ) * multiplier;
|
||||||
shotOrigin.y += shooterInfo->animation.lowerRightMissleOffsetY;
|
shotOrigin.y += shooterInfo->animation.lowerRightMissileOffsetY;
|
||||||
}
|
}
|
||||||
else if (getGroup() == getForwardGroup())
|
else if (getGroup() == getForwardGroup())
|
||||||
{
|
{
|
||||||
shotOrigin.x += ( -25 + shooterInfo->animation.rightMissleOffsetX ) * multiplier;
|
shotOrigin.x += ( -25 + shooterInfo->animation.rightMissileOffsetX ) * multiplier;
|
||||||
shotOrigin.y += shooterInfo->animation.rightMissleOffsetY;
|
shotOrigin.y += shooterInfo->animation.rightMissileOffsetY;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -141,10 +141,10 @@ protected:
|
|||||||
class MovementAnimation : public StackMoveAnimation
|
class MovementAnimation : public StackMoveAnimation
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int moveSoundHander; // sound handler used when moving a unit
|
int moveSoundHandler; // sound handler used when moving a unit
|
||||||
|
|
||||||
std::vector<BattleHex> destTiles; //full path, includes already passed hexes
|
std::vector<BattleHex> destTiles; //full path, includes already passed hexes
|
||||||
ui32 curentMoveIndex; // index of nextHex in destTiles
|
ui32 currentMoveIndex; // index of nextHex in destTiles
|
||||||
|
|
||||||
double begX, begY; // starting position
|
double begX, begY; // starting position
|
||||||
double distanceX, distanceY; // full movement distance, may be negative if creture moves topleft
|
double distanceX, distanceY; // full movement distance, may be negative if creture moves topleft
|
||||||
|
@ -84,7 +84,7 @@ namespace HexMasks
|
|||||||
|
|
||||||
std::map<int, int> hexEdgeMaskToFrameIndex;
|
std::map<int, int> hexEdgeMaskToFrameIndex;
|
||||||
|
|
||||||
// Maps HexEdgesMask to "Frame" indexes for range highligt images
|
// Maps HexEdgesMask to "Frame" indexes for range highlight images
|
||||||
void initializeHexEdgeMaskToFrameIndex()
|
void initializeHexEdgeMaskToFrameIndex()
|
||||||
{
|
{
|
||||||
hexEdgeMaskToFrameIndex[HexMasks::empty] = 0;
|
hexEdgeMaskToFrameIndex[HexMasks::empty] = 0;
|
||||||
@ -548,12 +548,12 @@ std::vector<std::shared_ptr<IImage>> BattleFieldController::calculateRangeLimitH
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleFieldController::calculateRangeLimitAndHighlightImages(uint8_t distance, std::shared_ptr<CAnimation> rangeLimitImages, std::vector<BattleHex> & rangeLimitHexes, std::vector<std::shared_ptr<IImage>> & rangeLimitHexesHighligts)
|
void BattleFieldController::calculateRangeLimitAndHighlightImages(uint8_t distance, std::shared_ptr<CAnimation> rangeLimitImages, std::vector<BattleHex> & rangeLimitHexes, std::vector<std::shared_ptr<IImage>> & rangeLimitHexesHighlights)
|
||||||
{
|
{
|
||||||
std::vector<BattleHex> rangeHexes = getRangeHexes(hoveredHex, distance);
|
std::vector<BattleHex> rangeHexes = getRangeHexes(hoveredHex, distance);
|
||||||
rangeLimitHexes = getRangeLimitHexes(hoveredHex, rangeHexes, distance);
|
rangeLimitHexes = getRangeLimitHexes(hoveredHex, rangeHexes, distance);
|
||||||
std::vector<std::vector<BattleHex::EDir>> rangeLimitNeighbourDirections = getOutsideNeighbourDirectionsForLimitHexes(rangeHexes, rangeLimitHexes);
|
std::vector<std::vector<BattleHex::EDir>> rangeLimitNeighbourDirections = getOutsideNeighbourDirectionsForLimitHexes(rangeHexes, rangeLimitHexes);
|
||||||
rangeLimitHexesHighligts = calculateRangeLimitHighlightImages(rangeLimitNeighbourDirections, rangeLimitImages);
|
rangeLimitHexesHighlights = calculateRangeLimitHighlightImages(rangeLimitNeighbourDirections, rangeLimitImages);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleFieldController::flipRangeLimitImagesIntoPositions(std::shared_ptr<CAnimation> images)
|
void BattleFieldController::flipRangeLimitImagesIntoPositions(std::shared_ptr<CAnimation> images)
|
||||||
@ -581,8 +581,8 @@ void BattleFieldController::showHighlightedHexes(Canvas & canvas)
|
|||||||
std::vector<BattleHex> rangedFullDamageLimitHexes;
|
std::vector<BattleHex> rangedFullDamageLimitHexes;
|
||||||
std::vector<BattleHex> shootingRangeLimitHexes;
|
std::vector<BattleHex> shootingRangeLimitHexes;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<IImage>> rangedFullDamageLimitHexesHighligts;
|
std::vector<std::shared_ptr<IImage>> rangedFullDamageLimitHexesHighlights;
|
||||||
std::vector<std::shared_ptr<IImage>> shootingRangeLimitHexesHighligts;
|
std::vector<std::shared_ptr<IImage>> shootingRangeLimitHexesHighlights;
|
||||||
|
|
||||||
std::set<BattleHex> hoveredStackMovementRangeHexes = getMovementRangeForHoveredStack();
|
std::set<BattleHex> hoveredStackMovementRangeHexes = getMovementRangeForHoveredStack();
|
||||||
std::set<BattleHex> hoveredSpellHexes = getHighlightedHexesForSpellRange();
|
std::set<BattleHex> hoveredSpellHexes = getHighlightedHexesForSpellRange();
|
||||||
@ -598,11 +598,11 @@ void BattleFieldController::showHighlightedHexes(Canvas & canvas)
|
|||||||
{
|
{
|
||||||
// calculate array with highlight images for ranged full damage limit
|
// calculate array with highlight images for ranged full damage limit
|
||||||
auto rangedFullDamageDistance = hoveredStack->getRangedFullDamageDistance();
|
auto rangedFullDamageDistance = hoveredStack->getRangedFullDamageDistance();
|
||||||
calculateRangeLimitAndHighlightImages(rangedFullDamageDistance, rangedFullDamageLimitImages, rangedFullDamageLimitHexes, rangedFullDamageLimitHexesHighligts);
|
calculateRangeLimitAndHighlightImages(rangedFullDamageDistance, rangedFullDamageLimitImages, rangedFullDamageLimitHexes, rangedFullDamageLimitHexesHighlights);
|
||||||
|
|
||||||
// calculate array with highlight images for shooting range limit
|
// calculate array with highlight images for shooting range limit
|
||||||
auto shootingRangeDistance = hoveredStack->getShootingRangeDistance();
|
auto shootingRangeDistance = hoveredStack->getShootingRangeDistance();
|
||||||
calculateRangeLimitAndHighlightImages(shootingRangeDistance, shootingRangeLimitImages, shootingRangeLimitHexes, shootingRangeLimitHexesHighligts);
|
calculateRangeLimitAndHighlightImages(shootingRangeDistance, shootingRangeLimitImages, shootingRangeLimitHexes, shootingRangeLimitHexesHighlights);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const & hoveredMouseHexes = hoveredHex != BattleHex::INVALID && owner.actionsController->currentActionSpellcasting(getHoveredHex()) ? hoveredSpellHexes : hoveredMoveHexes;
|
auto const & hoveredMouseHexes = hoveredHex != BattleHex::INVALID && owner.actionsController->currentActionSpellcasting(getHoveredHex()) ? hoveredSpellHexes : hoveredMoveHexes;
|
||||||
@ -635,11 +635,11 @@ void BattleFieldController::showHighlightedHexes(Canvas & canvas)
|
|||||||
}
|
}
|
||||||
if(hexInRangedFullDamageLimit)
|
if(hexInRangedFullDamageLimit)
|
||||||
{
|
{
|
||||||
showHighlightedHex(canvas, rangedFullDamageLimitHexesHighligts[hexIndexInRangedFullDamageLimit], hex, false);
|
showHighlightedHex(canvas, rangedFullDamageLimitHexesHighlights[hexIndexInRangedFullDamageLimit], hex, false);
|
||||||
}
|
}
|
||||||
if(hexInShootingRangeLimit)
|
if(hexInShootingRangeLimit)
|
||||||
{
|
{
|
||||||
showHighlightedHex(canvas, shootingRangeLimitHexesHighligts[hexIndexInShootingRangeLimit], hex, false);
|
showHighlightedHex(canvas, shootingRangeLimitHexesHighlights[hexIndexInShootingRangeLimit], hex, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -865,7 +865,7 @@ bool BattleFieldController::isTileAttackable(const BattleHex & number) const
|
|||||||
|
|
||||||
void BattleFieldController::updateAccessibleHexes()
|
void BattleFieldController::updateAccessibleHexes()
|
||||||
{
|
{
|
||||||
auto accessibility = owner.getBattle()->getAccesibility();
|
auto accessibility = owner.getBattle()->getAccessibility();
|
||||||
|
|
||||||
for(int i = 0; i < accessibility.size(); i++)
|
for(int i = 0; i < accessibility.size(); i++)
|
||||||
stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE || (accessibility[i] == EAccessibility::SIDE_COLUMN));
|
stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE || (accessibility[i] == EAccessibility::SIDE_COLUMN));
|
||||||
|
@ -73,7 +73,7 @@ class BattleFieldController : public CIntObject
|
|||||||
/// calculate if a hex is in range limit and return its index in range
|
/// calculate if a hex is in range limit and return its index in range
|
||||||
bool IsHexInRangeLimit(BattleHex hex, std::vector<BattleHex> & rangeLimitHexes, int * hexIndexInRangeLimit);
|
bool IsHexInRangeLimit(BattleHex hex, std::vector<BattleHex> & rangeLimitHexes, int * hexIndexInRangeLimit);
|
||||||
|
|
||||||
/// get an array that has for each hex in range, an aray with all directions where an ouside neighbour hex exists
|
/// get an array that has for each hex in range, an array with all directions where an outside neighbour hex exists
|
||||||
std::vector<std::vector<BattleHex::EDir>> getOutsideNeighbourDirectionsForLimitHexes(std::vector<BattleHex> rangeHexes, std::vector<BattleHex> rangeLimitHexes);
|
std::vector<std::vector<BattleHex::EDir>> getOutsideNeighbourDirectionsForLimitHexes(std::vector<BattleHex> rangeHexes, std::vector<BattleHex> rangeLimitHexes);
|
||||||
|
|
||||||
/// calculates what image to use as range limit, depending on the direction of neighbors
|
/// calculates what image to use as range limit, depending on the direction of neighbors
|
||||||
@ -82,7 +82,7 @@ class BattleFieldController : public CIntObject
|
|||||||
std::vector<std::shared_ptr<IImage>> calculateRangeLimitHighlightImages(std::vector<std::vector<BattleHex::EDir>> hexesNeighbourDirections, std::shared_ptr<CAnimation> limitImages);
|
std::vector<std::shared_ptr<IImage>> calculateRangeLimitHighlightImages(std::vector<std::vector<BattleHex::EDir>> hexesNeighbourDirections, std::shared_ptr<CAnimation> limitImages);
|
||||||
|
|
||||||
/// calculates all hexes for a range limit and what images to be shown as highlight for each of the hexes
|
/// calculates all hexes for a range limit and what images to be shown as highlight for each of the hexes
|
||||||
void calculateRangeLimitAndHighlightImages(uint8_t distance, std::shared_ptr<CAnimation> rangeLimitImages, std::vector<BattleHex> & rangeLimitHexes, std::vector<std::shared_ptr<IImage>> & rangeLimitHexesHighligts);
|
void calculateRangeLimitAndHighlightImages(uint8_t distance, std::shared_ptr<CAnimation> rangeLimitImages, std::vector<BattleHex> & rangeLimitHexes, std::vector<std::shared_ptr<IImage>> & rangeLimitHexesHighlights);
|
||||||
|
|
||||||
/// to reduce the number of source images used, some images will be used as flipped versions of preloaded ones
|
/// to reduce the number of source images used, some images will be used as flipped versions of preloaded ones
|
||||||
void flipRangeLimitImagesIntoPositions(std::shared_ptr<CAnimation> images);
|
void flipRangeLimitImagesIntoPositions(std::shared_ptr<CAnimation> images);
|
||||||
|
@ -206,7 +206,7 @@ public:
|
|||||||
void stacksAreAttacked(std::vector<StackAttackedInfo> attackedInfos); //called when a certain amount of stacks has been attacked
|
void stacksAreAttacked(std::vector<StackAttackedInfo> attackedInfos); //called when a certain amount of stacks has been attacked
|
||||||
void stackAttacking(const StackAttackInfo & attackInfo); //called when stack with id ID is attacking something on hex dest
|
void stackAttacking(const StackAttackInfo & attackInfo); //called when stack with id ID is attacking something on hex dest
|
||||||
void newRoundFirst();
|
void newRoundFirst();
|
||||||
void newRound(); //caled when round is ended;
|
void newRound(); //called when round is ended;
|
||||||
void stackIsCatapulting(const CatapultAttack & ca); //called when a stack is attacking walls
|
void stackIsCatapulting(const CatapultAttack & ca); //called when a stack is attacking walls
|
||||||
void battleFinished(const BattleResult& br, QueryID queryID); //called when battle is finished - battleresult window should be printed
|
void battleFinished(const BattleResult& br, QueryID queryID); //called when battle is finished - battleresult window should be printed
|
||||||
void spellCast(const BattleSpellCast *sc); //called when a hero casts a spell
|
void spellCast(const BattleSpellCast *sc); //called when a hero casts a spell
|
||||||
|
@ -161,7 +161,7 @@ const CCreature & BattleProjectileController::getShooter(const CStack * stack) c
|
|||||||
if(creature->getId() == CreatureID::ARROW_TOWERS)
|
if(creature->getId() == CreatureID::ARROW_TOWERS)
|
||||||
creature = owner.siegeController->getTurretCreature();
|
creature = owner.siegeController->getTurretCreature();
|
||||||
|
|
||||||
if(creature->animation.missleFrameAngles.empty())
|
if(creature->animation.missileFrameAngles.empty())
|
||||||
{
|
{
|
||||||
logAnim->error("Mod error: Creature '%s' on the Archer's tower is not a shooter. Mod should be fixed. Trying to use archer's data instead...", creature->getNameSingularTranslated());
|
logAnim->error("Mod error: Creature '%s' on the Archer's tower is not a shooter. Mod should be fixed. Trying to use archer's data instead...", creature->getNameSingularTranslated());
|
||||||
creature = CreatureID(CreatureID::ARCHER).toCreature();
|
creature = CreatureID(CreatureID::ARCHER).toCreature();
|
||||||
@ -277,7 +277,7 @@ int BattleProjectileController::computeProjectileFrameID( Point from, Point dest
|
|||||||
{
|
{
|
||||||
const CCreature & creature = getShooter(stack);
|
const CCreature & creature = getShooter(stack);
|
||||||
|
|
||||||
auto & angles = creature.animation.missleFrameAngles;
|
auto & angles = creature.animation.missileFrameAngles;
|
||||||
auto animation = getProjectileImage(stack);
|
auto animation = getProjectileImage(stack);
|
||||||
|
|
||||||
// only frames below maxFrame are usable: anything higher is either no present or we don't know when it should be used
|
// only frames below maxFrame are usable: anything higher is either no present or we don't know when it should be used
|
||||||
|
@ -126,7 +126,7 @@ ImagePath BattleSiegeController::getBattleBackgroundName() const
|
|||||||
return ImagePath::builtinTODO(prefix + "BACK.BMP");
|
return ImagePath::builtinTODO(prefix + "BACK.BMP");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BattleSiegeController::getWallPieceExistance(EWallVisual::EWallVisual what) const
|
bool BattleSiegeController::getWallPieceExistence(EWallVisual::EWallVisual what) const
|
||||||
{
|
{
|
||||||
//FIXME: use this instead of buildings test?
|
//FIXME: use this instead of buildings test?
|
||||||
//ui8 siegeLevel = owner.curInt->cb->battleGetSiegeLevel();
|
//ui8 siegeLevel = owner.curInt->cb->battleGetSiegeLevel();
|
||||||
@ -179,7 +179,7 @@ BattleSiegeController::BattleSiegeController(BattleInterface & owner, const CGTo
|
|||||||
if ( g == EWallVisual::GATE ) // gate is initially closed and has no image to display in this state
|
if ( g == EWallVisual::GATE ) // gate is initially closed and has no image to display in this state
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( !getWallPieceExistance(EWallVisual::EWallVisual(g)) )
|
if ( !getWallPieceExistence(EWallVisual::EWallVisual(g)) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
wallPieceImages[g] = GH.renderHandler().loadImage(getWallPieceImageName(EWallVisual::EWallVisual(g), EWallState::REINFORCED));
|
wallPieceImages[g] = GH.renderHandler().loadImage(getWallPieceImageName(EWallVisual::EWallVisual(g), EWallState::REINFORCED));
|
||||||
@ -256,10 +256,10 @@ void BattleSiegeController::gateStateChanged(const EGateState state)
|
|||||||
|
|
||||||
void BattleSiegeController::showAbsoluteObstacles(Canvas & canvas)
|
void BattleSiegeController::showAbsoluteObstacles(Canvas & canvas)
|
||||||
{
|
{
|
||||||
if (getWallPieceExistance(EWallVisual::MOAT))
|
if (getWallPieceExistence(EWallVisual::MOAT))
|
||||||
showWallPiece(canvas, EWallVisual::MOAT);
|
showWallPiece(canvas, EWallVisual::MOAT);
|
||||||
|
|
||||||
if (getWallPieceExistance(EWallVisual::MOAT_BANK))
|
if (getWallPieceExistence(EWallVisual::MOAT_BANK))
|
||||||
showWallPiece(canvas, EWallVisual::MOAT_BANK);
|
showWallPiece(canvas, EWallVisual::MOAT_BANK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,7 +292,7 @@ void BattleSiegeController::collectRenderableObjects(BattleRenderer & renderer)
|
|||||||
{
|
{
|
||||||
auto wallPiece = EWallVisual::EWallVisual(i);
|
auto wallPiece = EWallVisual::EWallVisual(i);
|
||||||
|
|
||||||
if ( !getWallPieceExistance(wallPiece))
|
if ( !getWallPieceExistence(wallPiece))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( getWallPiecePosition(wallPiece) == BattleHex::INVALID)
|
if ( getWallPiecePosition(wallPiece) == BattleHex::INVALID)
|
||||||
|
@ -83,7 +83,7 @@ class BattleSiegeController
|
|||||||
BattleHex getWallPiecePosition(EWallVisual::EWallVisual what) const;
|
BattleHex getWallPiecePosition(EWallVisual::EWallVisual what) const;
|
||||||
|
|
||||||
/// returns true if chosen wall piece should be present in current battle
|
/// returns true if chosen wall piece should be present in current battle
|
||||||
bool getWallPieceExistance(EWallVisual::EWallVisual what) const;
|
bool getWallPieceExistence(EWallVisual::EWallVisual what) const;
|
||||||
|
|
||||||
void showWallPiece(Canvas & canvas, EWallVisual::EWallVisual what);
|
void showWallPiece(Canvas & canvas, EWallVisual::EWallVisual what);
|
||||||
|
|
||||||
|
@ -438,7 +438,7 @@ void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> at
|
|||||||
// defender need to face in direction opposited to out attacker
|
// defender need to face in direction opposited to out attacker
|
||||||
bool needsReverse = shouldAttackFacingRight(attackedInfo.attacker, attackedInfo.defender) == facingRight(attackedInfo.defender);
|
bool needsReverse = shouldAttackFacingRight(attackedInfo.attacker, attackedInfo.defender) == facingRight(attackedInfo.defender);
|
||||||
|
|
||||||
// FIXME: this check is better, however not usable since stacksAreAttacked is called after net pack is applyed - petrification is already removed
|
// FIXME: this check is better, however not usable since stacksAreAttacked is called after net pack is applied - petrification is already removed
|
||||||
// if (needsReverse && !attackedInfo.defender->isFrozen())
|
// if (needsReverse && !attackedInfo.defender->isFrozen())
|
||||||
if (needsReverse && stackAnimation[attackedInfo.defender->unitId()]->getType() != ECreatureAnimType::FROZEN)
|
if (needsReverse && stackAnimation[attackedInfo.defender->unitId()]->getType() != ECreatureAnimType::FROZEN)
|
||||||
{
|
{
|
||||||
|
@ -372,7 +372,7 @@ void CreatureAnimation::nextFrame(Canvas & canvas, const ColorFilter & shifter,
|
|||||||
IImage::SpecialPalette SpecialPalette;
|
IImage::SpecialPalette SpecialPalette;
|
||||||
genSpecialPalette(SpecialPalette);
|
genSpecialPalette(SpecialPalette);
|
||||||
|
|
||||||
image->setSpecialPallete(SpecialPalette, IImage::SPECIAL_PALETTE_MASK_CREATURES);
|
image->setSpecialPalette(SpecialPalette, IImage::SPECIAL_PALETTE_MASK_CREATURES);
|
||||||
image->adjustPalette(shifter, IImage::SPECIAL_PALETTE_MASK_CREATURES);
|
image->adjustPalette(shifter, IImage::SPECIAL_PALETTE_MASK_CREATURES);
|
||||||
|
|
||||||
canvas.draw(image, pos.topLeft(), Rect(0, 0, pos.w, pos.h));
|
canvas.draw(image, pos.topLeft(), Rect(0, 0, pos.w, pos.h));
|
||||||
|
@ -39,7 +39,7 @@ InputSourceGameController::InputSourceGameController():
|
|||||||
scrollAxisValueY(0),
|
scrollAxisValueY(0),
|
||||||
scrollPlanDisX(0.0),
|
scrollPlanDisX(0.0),
|
||||||
scrollPlanDisY(0.0),
|
scrollPlanDisY(0.0),
|
||||||
configTriggerTreshold(settings["input"]["controllerTriggerTreshold"].Float()),
|
configTriggerThreshold(settings["input"]["controllerTriggerThreshold"].Float()),
|
||||||
configAxisDeadZone(settings["input"]["controllerAxisDeadZone"].Float()),
|
configAxisDeadZone(settings["input"]["controllerAxisDeadZone"].Float()),
|
||||||
configAxisFullZone(settings["input"]["controllerAxisFullZone"].Float()),
|
configAxisFullZone(settings["input"]["controllerAxisFullZone"].Float()),
|
||||||
configAxisSpeed(settings["input"]["controllerAxisSpeed"].Float()),
|
configAxisSpeed(settings["input"]["controllerAxisSpeed"].Float()),
|
||||||
@ -142,7 +142,7 @@ double InputSourceGameController::getRealAxisValue(int value) const
|
|||||||
|
|
||||||
void InputSourceGameController::dispatchAxisShortcuts(const std::vector<EShortcut> & shortcutsVector, SDL_GameControllerAxis axisID, int axisValue)
|
void InputSourceGameController::dispatchAxisShortcuts(const std::vector<EShortcut> & shortcutsVector, SDL_GameControllerAxis axisID, int axisValue)
|
||||||
{
|
{
|
||||||
if(getRealAxisValue(axisValue) > configTriggerTreshold)
|
if(getRealAxisValue(axisValue) > configTriggerThreshold)
|
||||||
{
|
{
|
||||||
if(!pressedAxes.count(axisID))
|
if(!pressedAxes.count(axisID))
|
||||||
{
|
{
|
||||||
|
@ -39,7 +39,7 @@ class InputSourceGameController
|
|||||||
double scrollPlanDisX;
|
double scrollPlanDisX;
|
||||||
double scrollPlanDisY;
|
double scrollPlanDisY;
|
||||||
|
|
||||||
const double configTriggerTreshold;
|
const double configTriggerThreshold;
|
||||||
const double configAxisDeadZone;
|
const double configAxisDeadZone;
|
||||||
const double configAxisFullZone;
|
const double configAxisFullZone;
|
||||||
const double configAxisSpeed;
|
const double configAxisSpeed;
|
||||||
|
@ -65,7 +65,7 @@ GlobalLobbyLoginWindow::GlobalLobbyLoginWindow()
|
|||||||
{
|
{
|
||||||
buttonLogin->block(true);
|
buttonLogin->block(true);
|
||||||
toggleMode->setSelected(0);
|
toggleMode->setSelected(0);
|
||||||
onLoginModeChanged(0); // call it manually to disable widgets - toggleMode will not emit this call if this is currenly selected option
|
onLoginModeChanged(0); // call it manually to disable widgets - toggleMode will not emit this call if this is currently selected option
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
toggleMode->setSelected(1);
|
toggleMode->setSelected(1);
|
||||||
|
@ -79,7 +79,7 @@ public:
|
|||||||
|
|
||||||
/// deactivates if needed, blocks all automatic activity, allows only disposal
|
/// deactivates if needed, blocks all automatic activity, allows only disposal
|
||||||
void disable();
|
void disable();
|
||||||
/// activates if needed, all activity enabled (Warning: may not be symetric with disable if recActions was limited!)
|
/// activates if needed, all activity enabled (Warning: may not be symmetric with disable if recActions was limited!)
|
||||||
void enable();
|
void enable();
|
||||||
/// deactivates or activates UI element based on flag
|
/// deactivates or activates UI element based on flag
|
||||||
void setEnabled(bool on);
|
void setEnabled(bool on);
|
||||||
|
@ -304,7 +304,7 @@ void EventDispatcher::dispatchTextInput(const std::string & text)
|
|||||||
{
|
{
|
||||||
for(auto it : textInterested)
|
for(auto it : textInterested)
|
||||||
{
|
{
|
||||||
it->textInputed(text);
|
it->textInputted(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ public:
|
|||||||
/// Called when UI element gesture status changes
|
/// Called when UI element gesture status changes
|
||||||
virtual void gesture(bool on, const Point & initialPosition, const Point & finalPosition) {}
|
virtual void gesture(bool on, const Point & initialPosition, const Point & finalPosition) {}
|
||||||
|
|
||||||
virtual void textInputed(const std::string & enteredText) {}
|
virtual void textInputted(const std::string & enteredText) {}
|
||||||
virtual void textEdited(const std::string & enteredText) {}
|
virtual void textEdited(const std::string & enteredText) {}
|
||||||
|
|
||||||
virtual void keyPressed(EShortcut key) {}
|
virtual void keyPressed(EShortcut key) {}
|
||||||
|
@ -22,7 +22,7 @@ class FramerateManager
|
|||||||
Duration targetFrameTime;
|
Duration targetFrameTime;
|
||||||
TimePoint lastTimePoint;
|
TimePoint lastTimePoint;
|
||||||
|
|
||||||
/// index of last measured frome in lastFrameTimes array
|
/// index of last measured from in lastFrameTimes array
|
||||||
ui32 lastFrameIndex;
|
ui32 lastFrameIndex;
|
||||||
|
|
||||||
bool vsyncEnabled;
|
bool vsyncEnabled;
|
||||||
|
@ -41,7 +41,7 @@ public:
|
|||||||
InterfaceObjectConfigurable(const JsonNode & config, int used=0, Point offset=Point());
|
InterfaceObjectConfigurable(const JsonNode & config, int used=0, Point offset=Point());
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Set blocked status for all buttons assotiated with provided shortcut
|
/// Set blocked status for all buttons associated with provided shortcut
|
||||||
void setShortcutBlocked(EShortcut shortcut, bool isBlocked);
|
void setShortcutBlocked(EShortcut shortcut, bool isBlocked);
|
||||||
|
|
||||||
/// Registers provided callback to be called whenever specified shortcut is triggered
|
/// Registers provided callback to be called whenever specified shortcut is triggered
|
||||||
|
@ -559,7 +559,7 @@ TeamAlignmentsWidget::TeamAlignmentsWidget(RandomMapTab & randomMapTab):
|
|||||||
players.back()->addToggle(teamId, std::dynamic_pointer_cast<CToggleBase>(button));
|
players.back()->addToggle(teamId, std::dynamic_pointer_cast<CToggleBase>(button));
|
||||||
}
|
}
|
||||||
|
|
||||||
// plId is not neccessarily player color, just an index
|
// plId is not necessarily player color, just an index
|
||||||
auto team = settingsVec.at(plId).getTeam();
|
auto team = settingsVec.at(plId).getTeam();
|
||||||
if(team == TeamID::NO_TEAM)
|
if(team == TeamID::NO_TEAM)
|
||||||
{
|
{
|
||||||
@ -577,9 +577,9 @@ TeamAlignmentsWidget::TeamAlignmentsWidget(RandomMapTab & randomMapTab):
|
|||||||
void RandomMapTab::saveOptions(const CMapGenOptions & options)
|
void RandomMapTab::saveOptions(const CMapGenOptions & options)
|
||||||
{
|
{
|
||||||
JsonNode data;
|
JsonNode data;
|
||||||
JsonSerializer ser(nullptr, data);
|
JsonSerializer set(nullptr, data);
|
||||||
|
|
||||||
ser.serializeStruct("lastSettings", const_cast<CMapGenOptions & >(options));
|
set.serializeStruct("lastSettings", const_cast<CMapGenOptions & >(options));
|
||||||
|
|
||||||
// FIXME: Do not nest fields
|
// FIXME: Do not nest fields
|
||||||
Settings rmgSettings = persistentStorage.write["rmg"];
|
Settings rmgSettings = persistentStorage.write["rmg"];
|
||||||
|
@ -136,7 +136,7 @@ size_t CMenuScreen::getActiveTab() const
|
|||||||
return tabs->getActive();
|
return tabs->getActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
//funciton for std::string -> std::function conversion for main menu
|
//function for std::string -> std::function conversion for main menu
|
||||||
static std::function<void()> genCommand(CMenuScreen * menu, std::vector<std::string> menuType, const std::string & string)
|
static std::function<void()> genCommand(CMenuScreen * menu, std::vector<std::string> menuType, const std::string & string)
|
||||||
{
|
{
|
||||||
static const std::vector<std::string> commandType = {"to", "campaigns", "start", "load", "exit", "highscores"};
|
static const std::vector<std::string> commandType = {"to", "campaigns", "start", "load", "exit", "highscores"};
|
||||||
|
@ -187,7 +187,7 @@ void MapView::postSwipe(uint32_t msPassed)
|
|||||||
std::pair<uint32_t, Point> firstAccepted;
|
std::pair<uint32_t, Point> firstAccepted;
|
||||||
uint32_t now = GH.input().getTicks();
|
uint32_t now = GH.input().getTicks();
|
||||||
for (auto & x : swipeHistory) {
|
for (auto & x : swipeHistory) {
|
||||||
if(now - x.first < postSwipeCatchIntervalMs) { // only the last x ms are catched
|
if(now - x.first < postSwipeCatchIntervalMs) { // only the last x ms are caught
|
||||||
if(firstAccepted.first == 0)
|
if(firstAccepted.first == 0)
|
||||||
firstAccepted = x;
|
firstAccepted = x;
|
||||||
diff += x.second;
|
diff += x.second;
|
||||||
|
@ -289,7 +289,7 @@ bool MusicEntry::play()
|
|||||||
|
|
||||||
// erase stored position:
|
// erase stored position:
|
||||||
// if music track will be interrupted again - new position will be written in stop() method
|
// if music track will be interrupted again - new position will be written in stop() method
|
||||||
// if music track is not interrupted and will finish by timeout/end of file - it will restart from begginning as it should
|
// if music track is not interrupted and will finish by timeout/end of file - it will restart from beginning as it should
|
||||||
owner->trackPositions.erase(owner->trackPositions.find(currentName));
|
owner->trackPositions.erase(owner->trackPositions.find(currentName));
|
||||||
|
|
||||||
if(Mix_FadeInMusicPos(music, 1, 1000, timeToStart) == -1)
|
if(Mix_FadeInMusicPos(music, 1, 1000, timeToStart) == -1)
|
||||||
|
@ -147,7 +147,7 @@ uint32_t CSoundHandler::getSoundDurationMilliseconds(const AudioPath & sound)
|
|||||||
SDL_AudioSpec spec;
|
SDL_AudioSpec spec;
|
||||||
uint32_t audioLen;
|
uint32_t audioLen;
|
||||||
uint8_t * audioBuf;
|
uint8_t * audioBuf;
|
||||||
uint32_t miliseconds = 0;
|
uint32_t milliseconds = 0;
|
||||||
|
|
||||||
if(SDL_LoadWAV_RW(SDL_RWFromMem(data.first.get(), data.second), 1, &spec, &audioBuf, &audioLen) != nullptr)
|
if(SDL_LoadWAV_RW(SDL_RWFromMem(data.first.get(), data.second), 1, &spec, &audioBuf, &audioLen) != nullptr)
|
||||||
{
|
{
|
||||||
@ -155,10 +155,10 @@ uint32_t CSoundHandler::getSoundDurationMilliseconds(const AudioPath & sound)
|
|||||||
uint32_t sampleSize = SDL_AUDIO_BITSIZE(spec.format) / 8;
|
uint32_t sampleSize = SDL_AUDIO_BITSIZE(spec.format) / 8;
|
||||||
uint32_t sampleCount = audioLen / sampleSize;
|
uint32_t sampleCount = audioLen / sampleSize;
|
||||||
uint32_t sampleLen = sampleCount / spec.channels;
|
uint32_t sampleLen = sampleCount / spec.channels;
|
||||||
miliseconds = 1000 * sampleLen / spec.freq;
|
milliseconds = 1000 * sampleLen / spec.freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
return miliseconds;
|
return milliseconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plays a sound, and return its channel so we can fade it out later
|
// Plays a sound, and return its channel so we can fade it out later
|
||||||
@ -292,7 +292,7 @@ void CSoundHandler::soundFinishedCallback(int channel)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// store callbacks from container locally - SDL might reuse this channel for another sound
|
// store callbacks from container locally - SDL might reuse this channel for another sound
|
||||||
// but do actualy execution in separate thread, to avoid potential deadlocks in case if callback requires locks of its own
|
// but do actually execution in separate thread, to avoid potential deadlocks in case if callback requires locks of its own
|
||||||
auto callback = callbacks.at(channel);
|
auto callback = callbacks.at(channel);
|
||||||
callbacks.erase(channel);
|
callbacks.erase(channel);
|
||||||
|
|
||||||
|
@ -29,14 +29,14 @@ class Canvas
|
|||||||
/// constructs canvas using existing surface. Caller maintains ownership on the surface
|
/// constructs canvas using existing surface. Caller maintains ownership on the surface
|
||||||
explicit Canvas(SDL_Surface * surface);
|
explicit Canvas(SDL_Surface * surface);
|
||||||
|
|
||||||
/// copy contructor
|
/// copy constructor
|
||||||
Canvas(const Canvas & other);
|
Canvas(const Canvas & other);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Canvas & operator = (const Canvas & other) = delete;
|
Canvas & operator = (const Canvas & other) = delete;
|
||||||
Canvas & operator = (Canvas && other) = delete;
|
Canvas & operator = (Canvas && other) = delete;
|
||||||
|
|
||||||
/// move contructor
|
/// move constructor
|
||||||
Canvas(Canvas && other);
|
Canvas(Canvas && other);
|
||||||
|
|
||||||
/// creates canvas that only covers specified subsection of a surface
|
/// creates canvas that only covers specified subsection of a surface
|
||||||
|
@ -76,7 +76,7 @@ public:
|
|||||||
virtual void setBlitMode(EImageBlitMode mode) = 0;
|
virtual void setBlitMode(EImageBlitMode mode) = 0;
|
||||||
|
|
||||||
//only indexed bitmaps with 7 special colors
|
//only indexed bitmaps with 7 special colors
|
||||||
virtual void setSpecialPallete(const SpecialPalette & SpecialPalette, uint32_t colorsToSkipMask) = 0;
|
virtual void setSpecialPalette(const SpecialPalette & SpecialPalette, uint32_t colorsToSkipMask) = 0;
|
||||||
|
|
||||||
virtual void horizontalFlip() = 0;
|
virtual void horizontalFlip() = 0;
|
||||||
virtual void verticalFlip() = 0;
|
virtual void verticalFlip() = 0;
|
||||||
|
@ -321,7 +321,7 @@ void SDLImage::resetPalette()
|
|||||||
if(originalPalette == nullptr)
|
if(originalPalette == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Always keept the original palette not changed, copy a new palette to assign to surface
|
// Always keep the original palette not changed, copy a new palette to assign to surface
|
||||||
SDL_SetPaletteColors(surf->format->palette, originalPalette->colors, 0, originalPalette->ncolors);
|
SDL_SetPaletteColors(surf->format->palette, originalPalette->colors, 0, originalPalette->ncolors);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,11 +330,11 @@ void SDLImage::resetPalette( int colorID )
|
|||||||
if(originalPalette == nullptr)
|
if(originalPalette == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Always keept the original palette not changed, copy a new palette to assign to surface
|
// Always keep the original palette not changed, copy a new palette to assign to surface
|
||||||
SDL_SetPaletteColors(surf->format->palette, originalPalette->colors + colorID, colorID, 1);
|
SDL_SetPaletteColors(surf->format->palette, originalPalette->colors + colorID, colorID, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDLImage::setSpecialPallete(const IImage::SpecialPalette & specialPalette, uint32_t colorsToSkipMask)
|
void SDLImage::setSpecialPalette(const IImage::SpecialPalette & specialPalette, uint32_t colorsToSkipMask)
|
||||||
{
|
{
|
||||||
if(surf->format->palette)
|
if(surf->format->palette)
|
||||||
{
|
{
|
||||||
|
@ -74,7 +74,7 @@ public:
|
|||||||
void setAlpha(uint8_t value) override;
|
void setAlpha(uint8_t value) override;
|
||||||
void setBlitMode(EImageBlitMode mode) override;
|
void setBlitMode(EImageBlitMode mode) override;
|
||||||
|
|
||||||
void setSpecialPallete(const SpecialPalette & SpecialPalette, uint32_t colorsToSkipMask) override;
|
void setSpecialPalette(const SpecialPalette & SpecialPalette, uint32_t colorsToSkipMask) override;
|
||||||
|
|
||||||
friend class SDLImageLoader;
|
friend class SDLImageLoader;
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ public:
|
|||||||
|
|
||||||
void addCallback(const std::function<void(bool)> & callback);
|
void addCallback(const std::function<void(bool)> & callback);
|
||||||
|
|
||||||
/// Set whether the toggle is currently enabled for user to use, this is only inplemented in ToggleButton, not for other toggles yet.
|
/// Set whether the toggle is currently enabled for user to use, this is only implemented in ToggleButton, not for other toggles yet.
|
||||||
virtual void setEnabled(bool enabled);
|
virtual void setEnabled(bool enabled);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ void CTextInput::updateLabel()
|
|||||||
label->setText(visibleText);
|
label->setText(visibleText);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTextInput::textInputed(const std::string & enteredText)
|
void CTextInput::textInputted(const std::string & enteredText)
|
||||||
{
|
{
|
||||||
if(!hasFocus())
|
if(!hasFocus())
|
||||||
return;
|
return;
|
||||||
|
@ -70,7 +70,7 @@ class CTextInput final : public CFocusable
|
|||||||
void updateLabel();
|
void updateLabel();
|
||||||
|
|
||||||
void clickPressed(const Point & cursorPosition) final;
|
void clickPressed(const Point & cursorPosition) final;
|
||||||
void textInputed(const std::string & enteredText) final;
|
void textInputted(const std::string & enteredText) final;
|
||||||
void textEdited(const std::string & enteredText) final;
|
void textEdited(const std::string & enteredText) final;
|
||||||
void onFocusGot() final;
|
void onFocusGot() final;
|
||||||
void onFocusLost() final;
|
void onFocusLost() final;
|
||||||
|
@ -31,7 +31,7 @@ public:
|
|||||||
/// if set, only specified section of internal image will be rendered
|
/// if set, only specified section of internal image will be rendered
|
||||||
std::optional<Rect> srcRect;
|
std::optional<Rect> srcRect;
|
||||||
|
|
||||||
/// If set to true, iamge will be redrawn on each frame
|
/// If set to true, image will be redrawn on each frame
|
||||||
bool needRefresh;
|
bool needRefresh;
|
||||||
|
|
||||||
std::shared_ptr<IImage> getSurface()
|
std::shared_ptr<IImage> getSurface()
|
||||||
|
@ -77,7 +77,7 @@ public:
|
|||||||
//ItemOffset - distance between items in the list
|
//ItemOffset - distance between items in the list
|
||||||
//VisibleSize - maximal number of displayable at once items
|
//VisibleSize - maximal number of displayable at once items
|
||||||
//TotalSize
|
//TotalSize
|
||||||
//Slider - slider style, bit field: 1 = present(disabled), 2=horisontal(vertical), 4=blue(brown)
|
//Slider - slider style, bit field: 1 = present(disabled), 2=horizontal(vertical), 4=blue(brown)
|
||||||
//SliderPos - position of slider, if present
|
//SliderPos - position of slider, if present
|
||||||
CListBox(CreateFunc create, Point Pos, Point ItemOffset, size_t VisibleSize,
|
CListBox(CreateFunc create, Point Pos, Point ItemOffset, size_t VisibleSize,
|
||||||
size_t TotalSize, size_t InitialPos=0, int Slider=0, Rect SliderPos=Rect() );
|
size_t TotalSize, size_t InitialPos=0, int Slider=0, Rect SliderPos=Rect() );
|
||||||
|
@ -173,13 +173,13 @@ void CTextContainer::blitLine(Canvas & to, Rect destRect, std::string what)
|
|||||||
{
|
{
|
||||||
const auto f = graphics->fonts[font];
|
const auto f = graphics->fonts[font];
|
||||||
Point where = destRect.topLeft();
|
Point where = destRect.topLeft();
|
||||||
const std::string delimeters = "{}";
|
const std::string delimiters = "{}";
|
||||||
auto delimitersCount = std::count_if(what.cbegin(), what.cend(), [&delimeters](char c)
|
auto delimitersCount = std::count_if(what.cbegin(), what.cend(), [&delimiters](char c)
|
||||||
{
|
{
|
||||||
return delimeters.find(c) != std::string::npos;
|
return delimiters.find(c) != std::string::npos;
|
||||||
});
|
});
|
||||||
//We should count delimiters length from string to correct centering later.
|
//We should count delimiters length from string to correct centering later.
|
||||||
delimitersCount *= f->getStringWidth(delimeters)/2;
|
delimitersCount *= f->getStringWidth(delimiters)/2;
|
||||||
|
|
||||||
std::smatch match;
|
std::smatch match;
|
||||||
std::regex expr("\\{(.*?)\\|");
|
std::regex expr("\\{(.*?)\\|");
|
||||||
@ -214,16 +214,16 @@ void CTextContainer::blitLine(Canvas & to, Rect destRect, std::string what)
|
|||||||
where.y += getBorderSize().y + destRect.h - static_cast<int>(f->getLineHeight());
|
where.y += getBorderSize().y + destRect.h - static_cast<int>(f->getLineHeight());
|
||||||
|
|
||||||
size_t begin = 0;
|
size_t begin = 0;
|
||||||
size_t currDelimeter = 0;
|
size_t currDelimiter = 0;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
size_t end = what.find_first_of(delimeters[currDelimeter % 2], begin);
|
size_t end = what.find_first_of(delimiters[currDelimiter % 2], begin);
|
||||||
if(begin != end)
|
if(begin != end)
|
||||||
{
|
{
|
||||||
std::string toPrint = what.substr(begin, end - begin);
|
std::string toPrint = what.substr(begin, end - begin);
|
||||||
|
|
||||||
if(currDelimeter % 2) // Enclosed in {} text - set to yellow or defined color
|
if(currDelimiter % 2) // Enclosed in {} text - set to yellow or defined color
|
||||||
{
|
{
|
||||||
std::smatch match;
|
std::smatch match;
|
||||||
std::regex expr("^(.*?)\\|");
|
std::regex expr("^(.*?)\\|");
|
||||||
@ -249,7 +249,7 @@ void CTextContainer::blitLine(Canvas & to, Rect destRect, std::string what)
|
|||||||
|
|
||||||
where.x += (int)f->getStringWidth(toPrint);
|
where.x += (int)f->getStringWidth(toPrint);
|
||||||
}
|
}
|
||||||
currDelimeter++;
|
currDelimiter++;
|
||||||
} while(begin++ != std::string::npos);
|
} while(begin++ != std::string::npos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,7 +234,7 @@ std::string CBuildingRect::getSubtitle()//hover text for building
|
|||||||
|
|
||||||
int bid = getBuilding()->bid;
|
int bid = getBuilding()->bid;
|
||||||
|
|
||||||
if (bid<30)//non-dwellings - only buiding name
|
if (bid<30)//non-dwellings - only building name
|
||||||
return town->town->buildings.at(getBuilding()->bid)->getNameTranslated();
|
return town->town->buildings.at(getBuilding()->bid)->getNameTranslated();
|
||||||
else//dwellings - recruit %creature%
|
else//dwellings - recruit %creature%
|
||||||
{
|
{
|
||||||
@ -476,7 +476,7 @@ void CHeroGSlot::setHighlight(bool on)
|
|||||||
|
|
||||||
if(owner->garrisonedHero->hero && owner->visitingHero->hero) //two heroes in town
|
if(owner->garrisonedHero->hero && owner->visitingHero->hero) //two heroes in town
|
||||||
{
|
{
|
||||||
for(auto & elem : owner->garr->splitButtons) //splitting enabled when slot higlighted
|
for(auto & elem : owner->garr->splitButtons) //splitting enabled when slot highlighted
|
||||||
elem->block(!on);
|
elem->block(!on);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1364,7 +1364,7 @@ void CCastleInterface::removeBuilding(BuildingID bid)
|
|||||||
void CCastleInterface::recreateIcons()
|
void CCastleInterface::recreateIcons()
|
||||||
{
|
{
|
||||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||||
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
|
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->built >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
|
||||||
|
|
||||||
icon->setFrame(iconIndex);
|
icon->setFrame(iconIndex);
|
||||||
TResources townIncome = town->dailyIncome();
|
TResources townIncome = town->dailyIncome();
|
||||||
|
@ -59,7 +59,7 @@ public:
|
|||||||
std::function<void(CreatureID)> callback;
|
std::function<void(CreatureID)> callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
// pointers to permament objects in game state
|
// pointers to permanent objects in game state
|
||||||
const CCreature * creature;
|
const CCreature * creature;
|
||||||
const CCommanderInstance * commander;
|
const CCommanderInstance * commander;
|
||||||
const CStackInstance * stackNode;
|
const CStackInstance * stackNode;
|
||||||
@ -144,10 +144,10 @@ void CCommanderSkillIcon::show(Canvas &to)
|
|||||||
|
|
||||||
static ImagePath skillToFile(int skill, int level, bool selected)
|
static ImagePath skillToFile(int skill, int level, bool selected)
|
||||||
{
|
{
|
||||||
// FIXME: is this a correct hadling?
|
// FIXME: is this a correct handling?
|
||||||
// level 0 = skill not present, use image with "no" suffix
|
// level 0 = skill not present, use image with "no" suffix
|
||||||
// level 1-5 = skill available, mapped to images indexed as 0-4
|
// level 1-5 = skill available, mapped to images indexed as 0-4
|
||||||
// selecting skill means that it will appear one level higher (as if alredy upgraded)
|
// selecting skill means that it will appear one level higher (as if already upgraded)
|
||||||
std::string file = "zvs/Lib1.res/_";
|
std::string file = "zvs/Lib1.res/_";
|
||||||
switch (skill)
|
switch (skill)
|
||||||
{
|
{
|
||||||
@ -170,17 +170,17 @@ static ImagePath skillToFile(int skill, int level, bool selected)
|
|||||||
file += "MP";
|
file += "MP";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
std::string sufix;
|
std::string suffix;
|
||||||
if (selected)
|
if (selected)
|
||||||
level++; // UI will display resulting level
|
level++; // UI will display resulting level
|
||||||
if (level == 0)
|
if (level == 0)
|
||||||
sufix = "no"; //not avaliable - no number
|
suffix = "no"; //not available - no number
|
||||||
else
|
else
|
||||||
sufix = std::to_string(level-1);
|
suffix = std::to_string(level-1);
|
||||||
if (selected)
|
if (selected)
|
||||||
sufix += "="; //level-up highlight
|
suffix += "="; //level-up highlight
|
||||||
|
|
||||||
return ImagePath::builtin(file + sufix + ".bmp");
|
return ImagePath::builtin(file + suffix + ".bmp");
|
||||||
}
|
}
|
||||||
|
|
||||||
CStackWindow::CWindowSection::CWindowSection(CStackWindow * parent, const ImagePath & backgroundPath, int yOffset)
|
CStackWindow::CWindowSection::CWindowSection(CStackWindow * parent, const ImagePath & backgroundPath, int yOffset)
|
||||||
@ -343,7 +343,7 @@ CStackWindow::ButtonsSection::ButtonsSection(CStackWindow * owner, int yOffset)
|
|||||||
|
|
||||||
upgradeBtn->setOverlay(std::make_shared<CAnimImage>(AnimationPath::builtin("CPRSMALL"), VLC->creh->objects[upgradeInfo.info.newID[buttonIndex]]->getIconIndex()));
|
upgradeBtn->setOverlay(std::make_shared<CAnimImage>(AnimationPath::builtin("CPRSMALL"), VLC->creh->objects[upgradeInfo.info.newID[buttonIndex]]->getIconIndex()));
|
||||||
|
|
||||||
if(buttonsToCreate == 1) // single upgrade avaialbe
|
if(buttonsToCreate == 1) // single upgrade available
|
||||||
upgradeBtn->assignedKey = EShortcut::RECRUITMENT_UPGRADE;
|
upgradeBtn->assignedKey = EShortcut::RECRUITMENT_UPGRADE;
|
||||||
|
|
||||||
upgrade[buttonIndex] = upgradeBtn;
|
upgrade[buttonIndex] = upgradeBtn;
|
||||||
|
@ -35,7 +35,7 @@ class CCommanderSkillIcon : public LRClickableAreaWText //TODO: maybe bring comm
|
|||||||
{
|
{
|
||||||
std::shared_ptr<CIntObject> object; // passive object that will be used to determine clickable area
|
std::shared_ptr<CIntObject> object; // passive object that will be used to determine clickable area
|
||||||
bool isMasterAbility; // refers to WoG abilities obtainable via combining master skills (for example attack + speed unlocks shoot)
|
bool isMasterAbility; // refers to WoG abilities obtainable via combining master skills (for example attack + speed unlocks shoot)
|
||||||
bool isSelected; // used only for programatically created border around selected "master abilities"
|
bool isSelected; // used only for programmatically created border around selected "master abilities"
|
||||||
public:
|
public:
|
||||||
CCommanderSkillIcon(std::shared_ptr<CIntObject> object_, bool isMasterAbility_, std::function<void()> callback);
|
CCommanderSkillIcon(std::shared_ptr<CIntObject> object_, bool isMasterAbility_, std::function<void()> callback);
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ public:
|
|||||||
|
|
||||||
void update() override;
|
void update() override;
|
||||||
|
|
||||||
void dismissCurrent(); //dissmissed currently displayed hero (curHero)
|
void dismissCurrent(); //dismissed currently displayed hero (curHero)
|
||||||
void commanderWindow();
|
void commanderWindow();
|
||||||
void switchHero(); //changes displayed hero
|
void switchHero(); //changes displayed hero
|
||||||
void updateGarrisons() override;
|
void updateGarrisons() override;
|
||||||
|
@ -801,7 +801,7 @@ CTownItem::CTownItem(const CGTownInstance * Town)
|
|||||||
garr = std::make_shared<CGarrisonInt>(Point(313, 3), 4, Point(232,0), town->getUpperArmy(), town->visitingHero, true, true, CGarrisonInt::ESlotsLayout::TWO_ROWS);
|
garr = std::make_shared<CGarrisonInt>(Point(313, 3), 4, Point(232,0), town->getUpperArmy(), town->visitingHero, true, true, CGarrisonInt::ESlotsLayout::TWO_ROWS);
|
||||||
heroes = std::make_shared<HeroSlots>(town, Point(244,6), Point(475,6), garr, false);
|
heroes = std::make_shared<HeroSlots>(town, Point(244,6), Point(475,6), garr, false);
|
||||||
|
|
||||||
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
|
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->built >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
|
||||||
|
|
||||||
picture = std::make_shared<CAnimImage>(AnimationPath::builtin("ITPT"), iconIndex, 0, 5, 6);
|
picture = std::make_shared<CAnimImage>(AnimationPath::builtin("ITPT"), iconIndex, 0, 5, 6);
|
||||||
openTown = std::make_shared<LRClickableAreaOpenTown>(Rect(5, 6, 58, 64), town);
|
openTown = std::make_shared<LRClickableAreaOpenTown>(Rect(5, 6, 58, 64), town);
|
||||||
|
@ -136,9 +136,9 @@ std::shared_ptr<CPicture> CMapOverviewWidget::buildDrawMinimap(const JsonNode &
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
Rect minimapRect = minimaps[id].getRenderArea();
|
Rect minimapRect = minimaps[id].getRenderArea();
|
||||||
double maxSideLenghtSrc = std::max(minimapRect.w, minimapRect.h);
|
double maxSideLengthSrc = std::max(minimapRect.w, minimapRect.h);
|
||||||
double maxSideLenghtDst = std::max(rect.w, rect.h);
|
double maxSideLengthDst = std::max(rect.w, rect.h);
|
||||||
double resize = maxSideLenghtSrc / maxSideLenghtDst;
|
double resize = maxSideLengthSrc / maxSideLengthDst;
|
||||||
Point newMinimapSize = Point(minimapRect.w / resize, minimapRect.h / resize);
|
Point newMinimapSize = Point(minimapRect.w / resize, minimapRect.h / resize);
|
||||||
|
|
||||||
Canvas canvasScaled = Canvas(Point(rect.w, rect.h));
|
Canvas canvasScaled = Canvas(Point(rect.w, rect.h));
|
||||||
|
@ -176,9 +176,9 @@ std::vector<std::string> CMessage::breakText(std::string text, size_t maxLineWid
|
|||||||
std::string CMessage::guessHeader(const std::string & msg)
|
std::string CMessage::guessHeader(const std::string & msg)
|
||||||
{
|
{
|
||||||
size_t begin = 0;
|
size_t begin = 0;
|
||||||
std::string delimeters = "{}";
|
std::string delimiters = "{}";
|
||||||
size_t start = msg.find_first_of(delimeters[0], begin);
|
size_t start = msg.find_first_of(delimiters[0], begin);
|
||||||
size_t end = msg.find_first_of(delimeters[1], start);
|
size_t end = msg.find_first_of(delimiters[1], start);
|
||||||
if(start > msg.size() || end > msg.size())
|
if(start > msg.size() || end > msg.size())
|
||||||
return "";
|
return "";
|
||||||
return msg.substr(begin, end);
|
return msg.substr(begin, end);
|
||||||
|
@ -129,7 +129,7 @@ CQuestLog::CQuestLog (const std::vector<QuestInfo> & Quests)
|
|||||||
// TextBox have it's own 4 pixel padding from top at least for English. To achieve 10px from both left and top only add 6px margin
|
// TextBox have it's own 4 pixel padding from top at least for English. To achieve 10px from both left and top only add 6px margin
|
||||||
description = std::make_shared<CTextBox>("", Rect(205, 18, 385, DESCRIPTION_HEIGHT_MAX), CSlider::BROWN, FONT_MEDIUM, ETextAlignment::TOPLEFT, Colors::WHITE);
|
description = std::make_shared<CTextBox>("", Rect(205, 18, 385, DESCRIPTION_HEIGHT_MAX), CSlider::BROWN, FONT_MEDIUM, ETextAlignment::TOPLEFT, Colors::WHITE);
|
||||||
ok = std::make_shared<CButton>(Point(539, 398), AnimationPath::builtin("IOKAY.DEF"), CGI->generaltexth->zelp[445], std::bind(&CQuestLog::close, this), EShortcut::GLOBAL_RETURN);
|
ok = std::make_shared<CButton>(Point(539, 398), AnimationPath::builtin("IOKAY.DEF"), CGI->generaltexth->zelp[445], std::bind(&CQuestLog::close, this), EShortcut::GLOBAL_RETURN);
|
||||||
// Both button and lable are shifted to -2px by x and y to not make them actually look like they're on same line with quests list and ok button
|
// Both button and label are shifted to -2px by x and y to not make them actually look like they're on same line with quests list and ok button
|
||||||
hideCompleteButton = std::make_shared<CToggleButton>(Point(10, 396), AnimationPath::builtin("sysopchk.def"), CButton::tooltipLocalized("vcmi.questLog.hideComplete"), std::bind(&CQuestLog::toggleComplete, this, _1));
|
hideCompleteButton = std::make_shared<CToggleButton>(Point(10, 396), AnimationPath::builtin("sysopchk.def"), CButton::tooltipLocalized("vcmi.questLog.hideComplete"), std::bind(&CQuestLog::toggleComplete, this, _1));
|
||||||
hideCompleteLabel = std::make_shared<CLabel>(46, 398, FONT_MEDIUM, ETextAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->translate("vcmi.questLog.hideComplete.hover"));
|
hideCompleteLabel = std::make_shared<CLabel>(46, 398, FONT_MEDIUM, ETextAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->translate("vcmi.questLog.hideComplete.hover"));
|
||||||
slider = std::make_shared<CSlider>(Point(166, 195), 191, std::bind(&CQuestLog::sliderMoved, this, _1), QUEST_COUNT, 0, 0, Orientation::VERTICAL, CSlider::BROWN);
|
slider = std::make_shared<CSlider>(Point(166, 195), 191, std::bind(&CQuestLog::sliderMoved, this, _1), QUEST_COUNT, 0, 0, Orientation::VERTICAL, CSlider::BROWN);
|
||||||
|
@ -42,7 +42,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* options - EOpions enum
|
* options - EOptions enum
|
||||||
* imageName - name for background image, can be empty
|
* imageName - name for background image, can be empty
|
||||||
* centerAt - position of window center. Default - center of the screen
|
* centerAt - position of window center. Default - center of the screen
|
||||||
*/
|
*/
|
||||||
|
@ -44,7 +44,7 @@ private:
|
|||||||
void initCostBox();
|
void initCostBox();
|
||||||
|
|
||||||
// This just wraps a clickeable area. There's a weird layout scheme in the file and
|
// This just wraps a clickeable area. There's a weird layout scheme in the file and
|
||||||
// it's easier to just add a separate invisble box on top
|
// it's easier to just add a separate invisible box on top
|
||||||
class CCreatureClickArea : public CIntObject
|
class CCreatureClickArea : public CIntObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -153,7 +153,7 @@ void CRecruitmentWindow::buy()
|
|||||||
std::pair<SlotID, SlotID> toMerge;
|
std::pair<SlotID, SlotID> toMerge;
|
||||||
bool allowMerge = CGI->settings()->getBoolean(EGameSettings::DWELLINGS_ACCUMULATE_WHEN_OWNED);
|
bool allowMerge = CGI->settings()->getBoolean(EGameSettings::DWELLINGS_ACCUMULATE_WHEN_OWNED);
|
||||||
|
|
||||||
if (allowMerge && dst->mergableStacks(toMerge))
|
if (allowMerge && dst->mergeableStacks(toMerge))
|
||||||
{
|
{
|
||||||
LOCPLINT->cb->mergeStacks( dst, dst, toMerge.first, toMerge.second);
|
LOCPLINT->cb->mergeStacks( dst, dst, toMerge.first, toMerge.second);
|
||||||
}
|
}
|
||||||
|
@ -82,11 +82,11 @@ This module responds to the following cache variables:
|
|||||||
SDL2_LIBRARY
|
SDL2_LIBRARY
|
||||||
SDL2 Library (.dll, .so, .a, etc) path.
|
SDL2 Library (.dll, .so, .a, etc) path.
|
||||||
|
|
||||||
SDL2MAIN_LIBRAY
|
SDL2MAIN_LIBRARY
|
||||||
SDL2main Library (.a) path.
|
SDL2main Library (.a) path.
|
||||||
|
|
||||||
SDL2_BUILDING_LIBRARY
|
SDL2_BUILDING_LIBRARY
|
||||||
This flag is useful only when linking to SDL2_LIBRARIES insead of
|
This flag is useful only when linking to SDL2_LIBRARIES instead of
|
||||||
SDL2::SDL2main. It is required only when building a library that links to
|
SDL2::SDL2main. It is required only when building a library that links to
|
||||||
SDL2_LIBRARIES, because only applications need main() (No need to also
|
SDL2_LIBRARIES, because only applications need main() (No need to also
|
||||||
link to SDL2main).
|
link to SDL2main).
|
||||||
|
@ -10,7 +10,7 @@ We have 3 battle AIs so far:
|
|||||||
|
|
||||||
Each battle AI consist of a few classes, but the main class, kind of entry point usually has the same name as the package itself. In BattleAI it is the BattleAI class. It implements some battle specific interface, do not remember. Main method there is activeStack(battle::Unit* stack). It is invoked by the system when it's time to move your stack. The thing you use to interact with the game and receive the gamestate is usually referenced in the code as cb. CPlayerSpecificCallback it should be. It has a lot of methods and can do anything. For instance it has battleGetUnitsIf(), which returns all units on the battlefield matching some lambda condition.
|
Each battle AI consist of a few classes, but the main class, kind of entry point usually has the same name as the package itself. In BattleAI it is the BattleAI class. It implements some battle specific interface, do not remember. Main method there is activeStack(battle::Unit* stack). It is invoked by the system when it's time to move your stack. The thing you use to interact with the game and receive the gamestate is usually referenced in the code as cb. CPlayerSpecificCallback it should be. It has a lot of methods and can do anything. For instance it has battleGetUnitsIf(), which returns all units on the battlefield matching some lambda condition.
|
||||||
Each side in a battle is represented by an CArmedInstance object. CHeroInstance and CGDwelling, CGMonster and more are subclasses of CArmedInstance. CArmedInstance contains a set of stacks. When the battle starts, these stacks are converted to battle stacks. Usually Battle AIs reference them using the interface battle::Unit *.
|
Each side in a battle is represented by an CArmedInstance object. CHeroInstance and CGDwelling, CGMonster and more are subclasses of CArmedInstance. CArmedInstance contains a set of stacks. When the battle starts, these stacks are converted to battle stacks. Usually Battle AIs reference them using the interface battle::Unit *.
|
||||||
Units have bonuses. Nearly everything aspect of a unit is configured in the form of bonuses. Attack, defense, health, retalitation, shooter or not, initial count of shots and so on.
|
Units have bonuses. Nearly everything aspect of a unit is configured in the form of bonuses. Attack, defense, health, retaliation, shooter or not, initial count of shots and so on.
|
||||||
When you call unit->getAttack() it summarizes all these bonuses and returns the resulting value.
|
When you call unit->getAttack() it summarizes all these bonuses and returns the resulting value.
|
||||||
|
|
||||||
One important class is HypotheticBattle. It is used to evaluate the effects of an action without changing the actual gamestate. It is a wrapper around CPlayerSpecificCallback or another HypotheticBattle so it can provide you data, Internally it has a set of modified unit states and intercepts some calls to underlying callback and returns these internal states instead. These states in turn are wrappers around original units and contain modified bonuses (CStackWithBonuses). So if you need to emulate an attack you can call hypotheticbattle.getforupdate() and it will return the CStackWithBonuses which you can safely change.
|
One important class is HypotheticBattle. It is used to evaluate the effects of an action without changing the actual gamestate. It is a wrapper around CPlayerSpecificCallback or another HypotheticBattle so it can provide you data, Internally it has a set of modified unit states and intercepts some calls to underlying callback and returns these internal states instead. These states in turn are wrappers around original units and contain modified bonuses (CStackWithBonuses). So if you need to emulate an attack you can call hypotheticbattle.getforupdate() and it will return the CStackWithBonuses which you can safely change.
|
||||||
|
@ -45,7 +45,7 @@ If you want to speed up the recompilation, add `-D ENABLE_CCACHE=ON`
|
|||||||
|
|
||||||
### Building for device
|
### Building for device
|
||||||
|
|
||||||
To be able to build for iOS device, you must also specify codesigning settings. If you don't know your development team ID, open the generated Xcode project, open project settings (click **VCMI** with blue icon on the very top in the left panel with files), select **vcmiclient** target, open **Signing & Capabilities** tab and select yout team. Now you can copy the value from **Build Settings** tab - `DEVELOPMENT_TEAM` variable (paste it in the Filter field on the right) - click the greenish value - Other... - copy. Now you can pass it in `CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM` variable when configuring the project to avoid selecting the team manually every time CMake re-generates the project.
|
To be able to build for iOS device, you must also specify codesigning settings. If you don't know your development team ID, open the generated Xcode project, open project settings (click **VCMI** with blue icon on the very top in the left panel with files), select **vcmiclient** target, open **Signing & Capabilities** tab and select your team. Now you can copy the value from **Build Settings** tab - `DEVELOPMENT_TEAM` variable (paste it in the Filter field on the right) - click the greenish value - Other... - copy. Now you can pass it in `CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM` variable when configuring the project to avoid selecting the team manually every time CMake re-generates the project.
|
||||||
|
|
||||||
Advanced users who know exact private key and provisioning profile to sign with, can use `CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY` and `CMAKE_XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER` variables instead. In this case you must also pass `-D CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_STYLE=Manual`.
|
Advanced users who know exact private key and provisioning profile to sign with, can use `CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY` and `CMAKE_XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER` variables instead. In this case you must also pass `-D CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_STYLE=Manual`.
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ Client is responsible for:
|
|||||||
|
|
||||||
## Rendering of graphics
|
## Rendering of graphics
|
||||||
|
|
||||||
Rendering of graphics relies heavily on SDL. Currently we do not have any wrapper for SDL internal structures and most of rendering is about blitting surfaces using SDL_BlitSurface. We have a few function that make rendering easier or make specific parts of rendering (like printing text). They are places in client/SDL_Extensions and client/SDL_Framerate (the second one contains code responsible for keeping appropriate framerate, it should work more smart than just SDL_Delay(miliseconds)).
|
Rendering of graphics relies heavily on SDL. Currently we do not have any wrapper for SDL internal structures and most of rendering is about blitting surfaces using SDL_BlitSurface. We have a few function that make rendering easier or make specific parts of rendering (like printing text). They are places in client/SDL_Extensions and client/SDL_Framerate (the second one contains code responsible for keeping appropriate framerate, it should work more smart than just SDL_Delay(milliseconds)).
|
||||||
In rendering, Interface object system is quite helpful. Its base is CIntObject class that is basically a base class for our library of GUI components and other objects.
|
In rendering, Interface object system is quite helpful. Its base is CIntObject class that is basically a base class for our library of GUI components and other objects.
|
||||||
|
|
||||||
# Server
|
# Server
|
||||||
@ -111,7 +111,7 @@ VCAI module is currently developed agent-based system driven by goals and heroes
|
|||||||
|
|
||||||
## Fuzzy logic
|
## Fuzzy logic
|
||||||
|
|
||||||
VCMI includes [FuzzyLite](http://code.google.com/p/fuzzy-lite/) library to make use of fuzzy rule-based algorithms. They are useful to handle uncertanity and resemble human behaviour who takes decisions based on rough observations. FuzzyLite is linked as separate static library in AI/FuzzyLite.lib file.
|
VCMI includes [FuzzyLite](http://code.google.com/p/fuzzy-lite/) library to make use of fuzzy rule-based algorithms. They are useful to handle uncertainty and resemble human behaviour who takes decisions based on rough observations. FuzzyLite is linked as separate static library in AI/FuzzyLite.lib file.
|
||||||
|
|
||||||
# Utilities
|
# Utilities
|
||||||
|
|
||||||
|
@ -759,7 +759,7 @@ The line length for c++ source code is 120 columns. If your function declaration
|
|||||||
|
|
||||||
### Warnings
|
### Warnings
|
||||||
|
|
||||||
Avoid use of #pragma to disable warnings. Compile at warning level 3. Avoid commiting code with new warnings.
|
Avoid use of #pragma to disable warnings. Compile at warning level 3. Avoid committing code with new warnings.
|
||||||
|
|
||||||
### File/directory naming
|
### File/directory naming
|
||||||
|
|
||||||
@ -789,9 +789,9 @@ The name of the type should be logged first, e.g. {TYPE_NAME: members...}. The m
|
|||||||
|
|
||||||
Avoid code duplication or don't repeat yourself(DRY) is the most important aspect in programming. Code duplication of any kind can lead to inconsistency and is much harder to maintain. If one part of the system gets changed you have to change the code in several places. This process is error-prone and leads often to problems. Here you can read more about the DRY principle: [<http://en.wikipedia.org/wiki/Don%27t_repeat_yourself>](http://en.wikipedia.org/wiki/Don%27t_repeat_yourself)
|
Avoid code duplication or don't repeat yourself(DRY) is the most important aspect in programming. Code duplication of any kind can lead to inconsistency and is much harder to maintain. If one part of the system gets changed you have to change the code in several places. This process is error-prone and leads often to problems. Here you can read more about the DRY principle: [<http://en.wikipedia.org/wiki/Don%27t_repeat_yourself>](http://en.wikipedia.org/wiki/Don%27t_repeat_yourself)
|
||||||
|
|
||||||
### Do not use uncommon abbrevations
|
### Do not use uncommon abbreviations
|
||||||
|
|
||||||
Do not use uncommon abbrevations for class, method, parameter and global object names.
|
Do not use uncommon abbreviations for class, method, parameter and global object names.
|
||||||
|
|
||||||
Bad:
|
Bad:
|
||||||
|
|
||||||
|
@ -158,4 +158,4 @@ global, level=debug
|
|||||||
ai, level=not set, effective level=debug
|
ai, level=not set, effective level=debug
|
||||||
ai.battle, level=trace, effective level=trace
|
ai.battle, level=trace, effective level=trace
|
||||||
|
|
||||||
The same technique is applied to the console colors. If you want to have another debug color for the domain ai, you can explicitely set a color for that domain and level.
|
The same technique is applied to the console colors. If you want to have another debug color for the domain ai, you can explicitly set a color for that domain and level.
|
||||||
|
@ -78,7 +78,7 @@ To make the user-defined type serializable, it has to provide a template method
|
|||||||
|
|
||||||
Serializer provides an operator& that is internally expanded to `<<` when serialziing or `>>` when deserializing.
|
Serializer provides an operator& that is internally expanded to `<<` when serialziing or `>>` when deserializing.
|
||||||
|
|
||||||
Serializer provides a public bool field `saving`that set to true during serialziation and to false for deserialziation.
|
Serializer provides a public bool field `saving`that set to true during serialization and to false for deserialization.
|
||||||
|
|
||||||
Typically, serializing class involves serializing all its members (given that they are serializable). Sample:
|
Typically, serializing class involves serializing all its members (given that they are serializable). Sample:
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
The bonuses were grouped according to their original purpose. The bonus system allows them to propagate freely betwen the nodes, however they may not be recognized properly beyond the scope of original use.
|
The bonuses were grouped according to their original purpose. The bonus system allows them to propagate freely between the nodes, however they may not be recognized properly beyond the scope of original use.
|
||||||
|
|
||||||
## General-purpose bonuses
|
## General-purpose bonuses
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ Bonus that does not account for propagation and gives specific amount of extra r
|
|||||||
Bonus that does not account for propagation and gives extra resources per day with amount multiplied by number of owned towns
|
Bonus that does not account for propagation and gives extra resources per day with amount multiplied by number of owned towns
|
||||||
|
|
||||||
- subtype: resource identifier
|
- subtype: resource identifier
|
||||||
- val: - base resource amount to be multipled times number of owned towns
|
- val: - base resource amount to be multiplied times number of owned towns
|
||||||
|
|
||||||
## Hero bonuses
|
## Hero bonuses
|
||||||
|
|
||||||
@ -351,7 +351,7 @@ Negates all natural immunities for affected stacks. (Orb of Vulnerability)
|
|||||||
|
|
||||||
In battle, army affected by this bonus will cast spell at the very start of the battle. Spell is always cast at expert level.
|
In battle, army affected by this bonus will cast spell at the very start of the battle. Spell is always cast at expert level.
|
||||||
|
|
||||||
- subtype: spell identifer
|
- subtype: spell identifier
|
||||||
- val: duration of the spell, in rounds
|
- val: duration of the spell, in rounds
|
||||||
|
|
||||||
### FREE_SHIP_BOARDING
|
### FREE_SHIP_BOARDING
|
||||||
@ -876,7 +876,7 @@ Affected unit receives decreased damage from spells of specific school (Golems)
|
|||||||
Affected unit receives increased damage from specific spell
|
Affected unit receives increased damage from specific spell
|
||||||
|
|
||||||
- val: increase to damage, percentage
|
- val: increase to damage, percentage
|
||||||
- subtype: spell identifer
|
- subtype: spell identifier
|
||||||
|
|
||||||
### MIND_IMMUNITY
|
### MIND_IMMUNITY
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ Difficulty configuration is located in [config/difficulty.json](../config/diffic
|
|||||||
{
|
{
|
||||||
//starting resources
|
//starting resources
|
||||||
"resources": { "wood" : 30, "mercury": 15, "ore": 30, "sulfur": 15, "crystal": 15, "gems": 15, "gold": 30000, "mithril": 0 },
|
"resources": { "wood" : 30, "mercury": 15, "ore": 30, "sulfur": 15, "crystal": 15, "gems": 15, "gold": 30000, "mithril": 0 },
|
||||||
//bonuses will be given to player globaly
|
//bonuses will be given to player globally
|
||||||
"globalBonuses": [],
|
"globalBonuses": [],
|
||||||
//bonuses will be given to player every battle
|
//bonuses will be given to player every battle
|
||||||
"battleBonuses": []
|
"battleBonuses": []
|
||||||
@ -38,9 +38,9 @@ Difficulty configuration is located in [config/difficulty.json](../config/diffic
|
|||||||
|
|
||||||
It's possible to specify bonuses of two types: `globalBonuses` and `battleBonuses`.
|
It's possible to specify bonuses of two types: `globalBonuses` and `battleBonuses`.
|
||||||
|
|
||||||
Both are arrays containing any amount of bonuses, each can be described as usual bonus. See details in [bonus documenation](Bonus_Format.md).
|
Both are arrays containing any amount of bonuses, each can be described as usual bonus. See details in [bonus documentation](Bonus_Format.md).
|
||||||
|
|
||||||
`globalBonuses` are given to player on the begining and depending on bonus configuration, it can behave diffierently.
|
`globalBonuses` are given to player on the beginning and depending on bonus configuration, it can behave diffierently.
|
||||||
|
|
||||||
`battleBonuses` are given to player during the battles, but *only for battles with neutral forces*. So it won't be provided to player for PvP battles and battles versus AI heroes/castles/garrisons. To avoid cumulative effects or unexpected behavior it's recommended to specify bonus `duration` as `ONE_BATTLE`.
|
`battleBonuses` are given to player during the battles, but *only for battles with neutral forces*. So it won't be provided to player for PvP battles and battles versus AI heroes/castles/garrisons. To avoid cumulative effects or unexpected behavior it's recommended to specify bonus `duration` as `ONE_BATTLE`.
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user