mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
commit
8444f7b330
@ -176,7 +176,7 @@ void CBattleAI::activeStack(const BattleID & battleID, const CStack * stack )
|
||||
movesSkippedByDefense = 0;
|
||||
}
|
||||
|
||||
logAi->trace("BattleAI decission made in %lld", timeElapsed(start));
|
||||
logAi->trace("BattleAI decision made in %lld", timeElapsed(start));
|
||||
|
||||
cb->battleMakeUnitAction(battleID, result);
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ struct CurrentOffensivePotential
|
||||
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
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
score = moveTarget.score;
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
AttackerValue::AttackerValue()
|
||||
: value(0),
|
||||
isRetalitated(false)
|
||||
isRetaliated(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -57,14 +57,14 @@ float BattleExchangeVariant::trackAttack(
|
||||
|
||||
attackValue -= attackerDamageReduce;
|
||||
dpsScore.ourDamageReduce += attackerDamageReduce;
|
||||
attackerValue[unitToUpdate->unitId()].isRetalitated = true;
|
||||
attackerValue[unitToUpdate->unitId()].isRetaliated = true;
|
||||
|
||||
unitToUpdate->damage(retaliationDamage);
|
||||
defender->afterAttack(false, true);
|
||||
|
||||
#if BATTLE_TRACE_LEVEL>=1
|
||||
logAi->trace(
|
||||
"%s -> %s, ap retalitation, %s, dps: %2f, score: %2f",
|
||||
"%s -> %s, ap retaliation, %s, dps: %2f, score: %2f",
|
||||
defender->getDescription(),
|
||||
unitToUpdate->getDescription(),
|
||||
ap.attack.shooting ? "shot" : "mellee",
|
||||
@ -185,7 +185,7 @@ float BattleExchangeVariant::trackAttack(
|
||||
if(isOurAttack)
|
||||
{
|
||||
dpsScore.ourDamageReduce += attackerDamageReduce;
|
||||
attackerValue[attacker->unitId()].isRetalitated = true;
|
||||
attackerValue[attacker->unitId()].isRetaliated = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -45,7 +45,7 @@ struct BattleScore
|
||||
struct AttackerValue
|
||||
{
|
||||
float value;
|
||||
bool isRetalitated;
|
||||
bool isRetaliated;
|
||||
BattleHex position;
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
//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);
|
||||
}
|
||||
else if(relations == PlayerRelations::SAME_PLAYER && obj->ID == Obj::TOWN)
|
||||
@ -705,7 +705,7 @@ void AIGateway::showTeleportDialog(const CGHeroInstance * hero, TeleportChannelI
|
||||
NET_EVENT_HANDLER;
|
||||
status.addQuery(askID, boost::str(boost::format("Teleport dialog query with %d exits") % exits.size()));
|
||||
|
||||
int choosenExit = -1;
|
||||
int chosenExit = -1;
|
||||
if(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);
|
||||
if(destinationTeleport != ObjectInstanceID() && vstd::contains(exits, neededExit))
|
||||
choosenExit = vstd::find_pos(exits, neededExit);
|
||||
chosenExit = vstd::find_pos(exits, neededExit);
|
||||
}
|
||||
|
||||
for(auto exit : exits)
|
||||
{
|
||||
if(status.channelProbing() && exit.first == destinationTeleport)
|
||||
{
|
||||
choosenExit = vstd::find_pos(exits, exit);
|
||||
chosenExit = vstd::find_pos(exits, exit);
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -739,7 +739,7 @@ void AIGateway::showTeleportDialog(const CGHeroInstance * hero, TeleportChannelI
|
||||
|
||||
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?
|
||||
throw goalFulfilledException(sptr(g));
|
||||
|
||||
int accquiredResources = 0;
|
||||
int acquiredResources = 0;
|
||||
if(const CGObjectInstance * obj = cb->getObj(ObjectInstanceID(g.objid), false))
|
||||
{
|
||||
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
|
||||
{
|
||||
cb->trade(m, EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
|
||||
accquiredResources = 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());
|
||||
acquiredResources = static_cast<int>(toGet * (it->resVal / toGive));
|
||||
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)))
|
||||
throw goalFulfilledException(sptr(g)); //we traded all we needed
|
||||
|
@ -95,7 +95,7 @@ public:
|
||||
AIGateway();
|
||||
virtual ~AIGateway();
|
||||
|
||||
//TODO: extract to apropriate goals
|
||||
//TODO: extract to appropriate goals
|
||||
void tryRealize(Goals::DigAtTile & g);
|
||||
void tryRealize(Goals::Trade & g);
|
||||
|
||||
|
@ -434,9 +434,9 @@ bool townHasFreeTavern(const CGTownInstance * town)
|
||||
if(!town->hasBuilt(BuildingID::TAVERN)) return false;
|
||||
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)
|
||||
|
@ -267,7 +267,7 @@ BuildingInfo BuildAnalyzer::getBuildingOrPrerequisite(
|
||||
|
||||
BuildingInfo prerequisite = getBuildingOrPrerequisite(town, missingBuildings[0], excludeDwellingDependencies);
|
||||
|
||||
prerequisite.buildCostWithPrerequisits += info.buildCost;
|
||||
prerequisite.buildCostWithPrerequisites += info.buildCost;
|
||||
prerequisite.creatureCost = info.creatureCost;
|
||||
prerequisite.creatureGrows = info.creatureGrows;
|
||||
prerequisite.creatureLevel = info.creatureLevel;
|
||||
@ -340,7 +340,7 @@ void TownDevelopmentInfo::addExistingDwelling(const BuildingInfo & existingDwell
|
||||
|
||||
void TownDevelopmentInfo::addBuildingToBuild(const BuildingInfo & nextToBuild)
|
||||
{
|
||||
townDevelopmentCost += nextToBuild.buildCostWithPrerequisits;
|
||||
townDevelopmentCost += nextToBuild.buildCostWithPrerequisites;
|
||||
|
||||
if(nextToBuild.canBuild)
|
||||
{
|
||||
@ -361,7 +361,7 @@ BuildingInfo::BuildingInfo()
|
||||
creatureGrows = 0;
|
||||
creatureID = CreatureID::NONE;
|
||||
buildCost = 0;
|
||||
buildCostWithPrerequisits = 0;
|
||||
buildCostWithPrerequisites = 0;
|
||||
prerequisitesCount = 0;
|
||||
name.clear();
|
||||
armyStrength = 0;
|
||||
@ -376,7 +376,7 @@ BuildingInfo::BuildingInfo(
|
||||
{
|
||||
id = building->bid;
|
||||
buildCost = building->resources;
|
||||
buildCostWithPrerequisits = building->resources;
|
||||
buildCostWithPrerequisites = building->resources;
|
||||
dailyIncome = building->produce;
|
||||
exists = town->hasBuilt(id);
|
||||
prerequisitesCount = 1;
|
||||
|
@ -22,7 +22,7 @@ class DLL_EXPORT BuildingInfo
|
||||
public:
|
||||
BuildingID id;
|
||||
TResources buildCost;
|
||||
TResources buildCostWithPrerequisits;
|
||||
TResources buildCostWithPrerequisites;
|
||||
int creatureGrows;
|
||||
uint8_t creatureLevel;
|
||||
TResources creatureCost;
|
||||
|
@ -240,7 +240,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
|
||||
if(path.turn() <= threat.turn - 2)
|
||||
{
|
||||
#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(),
|
||||
path.targetHero->getObjectName());
|
||||
#endif
|
||||
|
@ -399,7 +399,7 @@ void Nullkiller::makeTurn()
|
||||
|
||||
auto selectedTasks = buildPlan(bestTasks);
|
||||
|
||||
logAi->debug("Decission madel in %ld", timeElapsed(start));
|
||||
logAi->debug("Decision madel in %ld", timeElapsed(start));
|
||||
|
||||
if(selectedTasks.empty())
|
||||
{
|
||||
|
@ -33,7 +33,7 @@
|
||||
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
|
||||
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.heroRole = HeroRole::MAIN;
|
||||
evaluationContext.movementCostByRole[evaluationContext.heroRole] += bi.prerequisitesCount;
|
||||
evaluationContext.goldCost += bi.buildCostWithPrerequisits[EGameResID::GOLD];
|
||||
evaluationContext.goldCost += bi.buildCostWithPrerequisites[EGameResID::GOLD];
|
||||
evaluationContext.closestWayRatio = 1;
|
||||
|
||||
if(bi.creatureID != CreatureID::NONE)
|
||||
|
@ -34,13 +34,13 @@ void BuyArmy::accept(AIGateway * ai)
|
||||
ui64 valueBought = 0;
|
||||
//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);
|
||||
|
||||
if(armyToBuy.empty())
|
||||
{
|
||||
if(upgradeSuccessfull)
|
||||
if(upgradeSuccessful)
|
||||
return;
|
||||
|
||||
throw cannotFulfillGoalException("No creatures to buy.");
|
||||
|
@ -234,7 +234,7 @@ void ExecuteHeroChain::accept(AIGateway * ai)
|
||||
if(node->turns == 0)
|
||||
{
|
||||
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(),
|
||||
node->coord.toString(),
|
||||
hero->visitablePos().toString());
|
||||
|
@ -27,8 +27,8 @@ namespace NKAI
|
||||
std::shared_ptr<boost::multi_array<AIPathNode, 4>> AISharedStorage::shared;
|
||||
uint64_t AISharedStorage::version = 0;
|
||||
boost::mutex AISharedStorage::locker;
|
||||
std::set<int3> commitedTiles;
|
||||
std::set<int3> commitedTilesInitial;
|
||||
std::set<int3> committedTiles;
|
||||
std::set<int3> committedTilesInitial;
|
||||
|
||||
|
||||
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 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)
|
||||
{
|
||||
@ -94,7 +94,7 @@ void AIPathNode::addSpecialAction(std::shared_ptr<const SpecialAction> action)
|
||||
AINodeStorage::AINodeStorage(const Nullkiller * ai, const int3 & 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]);
|
||||
|
||||
dangerEvaluator.reset(new FuzzyHelper(ai));
|
||||
@ -157,7 +157,7 @@ void AINodeStorage::initialize(const PathfinderOptions & options, const CGameSta
|
||||
void AINodeStorage::clear()
|
||||
{
|
||||
actors.clear();
|
||||
commitedTiles.clear();
|
||||
committedTiles.clear();
|
||||
heroChainPass = EHeroChainPass::INITIAL;
|
||||
heroChainTurn = 0;
|
||||
heroChainMaxTurns = 1;
|
||||
@ -276,7 +276,7 @@ void AINodeStorage::commit(
|
||||
int turn,
|
||||
int movementLeft,
|
||||
float cost,
|
||||
bool saveToCommited) const
|
||||
bool saveToCommitted) const
|
||||
{
|
||||
destination->action = action;
|
||||
destination->setCost(cost);
|
||||
@ -290,7 +290,7 @@ void AINodeStorage::commit(
|
||||
|
||||
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
|
||||
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(),
|
||||
destination->coord.toString(),
|
||||
destination->layer,
|
||||
@ -302,9 +302,9 @@ void AINodeStorage::commit(
|
||||
destination->actor->armyValue);
|
||||
#endif
|
||||
|
||||
if(saveToCommited && destination->turns <= heroChainTurn)
|
||||
if(saveToCommitted && destination->turns <= heroChainTurn)
|
||||
{
|
||||
commitedTiles.insert(destination->coord);
|
||||
committedTiles.insert(destination->coord);
|
||||
}
|
||||
|
||||
if(destination->turns == source->turns)
|
||||
@ -376,7 +376,7 @@ bool AINodeStorage::increaseHeroChainTurnLimit()
|
||||
return false;
|
||||
|
||||
heroChainTurn++;
|
||||
commitedTiles.clear();
|
||||
committedTiles.clear();
|
||||
|
||||
for(auto layer : phisycalLayers)
|
||||
{
|
||||
@ -386,7 +386,7 @@ bool AINodeStorage::increaseHeroChainTurnLimit()
|
||||
{
|
||||
if(node.turns <= heroChainTurn && node.action != EPathNodeAction::UNKNOWN)
|
||||
{
|
||||
commitedTiles.insert(pos);
|
||||
committedTiles.insert(pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -547,7 +547,7 @@ bool AINodeStorage::calculateHeroChain()
|
||||
heroChainPass = EHeroChainPass::CHAIN;
|
||||
heroChain.clear();
|
||||
|
||||
std::vector<int3> data(commitedTiles.begin(), commitedTiles.end());
|
||||
std::vector<int3> data(committedTiles.begin(), committedTiles.end());
|
||||
|
||||
if(data.size() > 100)
|
||||
{
|
||||
@ -578,7 +578,7 @@ bool AINodeStorage::calculateHeroChain()
|
||||
task.flushResult(heroChain);
|
||||
}
|
||||
|
||||
commitedTiles.clear();
|
||||
committedTiles.clear();
|
||||
|
||||
return !heroChain.empty();
|
||||
}
|
||||
@ -594,7 +594,7 @@ bool AINodeStorage::selectFirstActor()
|
||||
});
|
||||
|
||||
chainMask = strongest->chainMask;
|
||||
commitedTilesInitial = commitedTiles;
|
||||
committedTilesInitial = committedTiles;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -629,7 +629,7 @@ bool AINodeStorage::selectNextActor()
|
||||
return false;
|
||||
|
||||
chainMask = nextActor->get()->chainMask;
|
||||
commitedTiles = commitedTilesInitial;
|
||||
committedTiles = committedTilesInitial;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -656,7 +656,7 @@ void HeroChainCalculationTask::cleanupInefectiveChains(std::vector<ExchangeCandi
|
||||
if(isNotEffective)
|
||||
{
|
||||
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->chainMask,
|
||||
chainInfo.carrierParent->actor->toString(),
|
||||
@ -756,7 +756,7 @@ void HeroChainCalculationTask::calculateHeroChain(
|
||||
if(hasLessMp && hasLessExperience)
|
||||
{
|
||||
#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
|
||||
return;
|
||||
}
|
||||
@ -825,7 +825,7 @@ void HeroChainCalculationTask::addHeroChain(const std::vector<ExchangeCandidate>
|
||||
chainInfo.turns,
|
||||
chainInfo.moveRemains,
|
||||
chainInfo.getCost(),
|
||||
DO_NOT_SAVE_TO_COMMITED_TILES);
|
||||
DO_NOT_SAVE_TO_COMMITTED_TILES);
|
||||
|
||||
if(carrier->specialAction || carrier->chainOther)
|
||||
{
|
||||
@ -1029,7 +1029,7 @@ std::vector<CGPathNode *> AINodeStorage::calculateTeleportations(
|
||||
return neighbours;
|
||||
}
|
||||
|
||||
struct TowmPortalFinder
|
||||
struct TownPortalFinder
|
||||
{
|
||||
const std::vector<CGPathNode *> & initialNodes;
|
||||
MasteryLevel::Type townPortalSkillLevel;
|
||||
@ -1042,7 +1042,7 @@ struct TowmPortalFinder
|
||||
SpellID spellID;
|
||||
const CSpell * townPortal;
|
||||
|
||||
TowmPortalFinder(
|
||||
TownPortalFinder(
|
||||
const ChainActor * actor,
|
||||
const std::vector<CGPathNode *> & initialNodes,
|
||||
std::vector<const CGTownInstance *> targetTowns,
|
||||
@ -1119,7 +1119,7 @@ struct TowmPortalFinder
|
||||
bestNode->turns,
|
||||
bestNode->moveRemains - movementNeeded,
|
||||
movementCost,
|
||||
DO_NOT_SAVE_TO_COMMITED_TILES);
|
||||
DO_NOT_SAVE_TO_COMMITTED_TILES);
|
||||
|
||||
node->theNodeBefore = bestNode;
|
||||
node->addSpecialAction(std::make_shared<AIPathfinding::TownPortalAction>(targetTown));
|
||||
@ -1148,7 +1148,7 @@ void AINodeStorage::calculateTownPortal(
|
||||
return; // no towns no need to run loop further
|
||||
}
|
||||
|
||||
TowmPortalFinder townPortalFinder(actor, initialNodes, towns, this);
|
||||
TownPortalFinder townPortalFinder(actor, initialNodes, towns, this);
|
||||
|
||||
if(townPortalFinder.actorCanCastTownPortal())
|
||||
{
|
||||
@ -1281,7 +1281,7 @@ bool AINodeStorage::isOtherChainBetter(
|
||||
{
|
||||
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
|
||||
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(),
|
||||
candidateNode.coord.toString(),
|
||||
candidateNode.actor->hero->getNameTranslated(),
|
||||
@ -1305,7 +1305,7 @@ bool AINodeStorage::isOtherChainBetter(
|
||||
{
|
||||
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
|
||||
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(),
|
||||
candidateNode.coord.toString(),
|
||||
candidateNode.actor->hero->getNameTranslated(),
|
||||
@ -1331,7 +1331,7 @@ bool AINodeStorage::isOtherChainBetter(
|
||||
|
||||
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
|
||||
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(),
|
||||
candidateNode.coord.toString(),
|
||||
candidateNode.actor->hero->getNameTranslated(),
|
||||
|
@ -165,7 +165,7 @@ class AINodeStorage : public INodeStorage
|
||||
private:
|
||||
int3 sizes;
|
||||
|
||||
std::unique_ptr<boost::multi_array<EPathAccessibility, 4>> accesibility;
|
||||
std::unique_ptr<boost::multi_array<EPathAccessibility, 4>> accessibility;
|
||||
|
||||
const CPlayerSpecificInfoCallback * cb;
|
||||
const Nullkiller * ai;
|
||||
@ -214,7 +214,7 @@ public:
|
||||
int turn,
|
||||
int movementLeft,
|
||||
float cost,
|
||||
bool saveToCommited = true) const;
|
||||
bool saveToCommitted = true) const;
|
||||
|
||||
inline const AIPathNode * getAINode(const CGPathNode * node) const
|
||||
{
|
||||
@ -257,7 +257,7 @@ public:
|
||||
const AIPathNode & candidateNode,
|
||||
const AIPathNode & other) const;
|
||||
|
||||
bool isMovementIneficient(const PathNodeInfo & source, CDestinationNodeInfo & destination) const
|
||||
bool isMovementInefficient(const PathNodeInfo & source, CDestinationNodeInfo & destination) const
|
||||
{
|
||||
return hasBetterChain(source, destination);
|
||||
}
|
||||
@ -287,12 +287,12 @@ public:
|
||||
|
||||
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)
|
||||
{
|
||||
(*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
|
||||
|
@ -164,7 +164,7 @@ namespace AIPathfinding
|
||||
if(hero->canCastThisSpell(summonBoatSpell)
|
||||
&& 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>();
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ namespace AIPathfinding
|
||||
const PathfinderConfig * pathfinderConfig,
|
||||
CPathfinderHelper * pathfinderHelper) const
|
||||
{
|
||||
if(nodeStorage->isMovementIneficient(source, destination))
|
||||
if(nodeStorage->isMovementInefficient(source, destination))
|
||||
{
|
||||
destination.node->locked = true;
|
||||
destination.blocked = true;
|
||||
|
@ -41,7 +41,7 @@ TSubgoal BuildThis::whatToDoToAchieve()
|
||||
{
|
||||
case EBuildingState::ALLOWED:
|
||||
town = candidateTown;
|
||||
break; //TODO: look for prerequisites? this is not our reponsibility
|
||||
break; //TODO: look for prerequisites? this is not our responsibility
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ TGoalVec ClearWayTo::getAllPossibleSubgoals()
|
||||
if(ret.empty())
|
||||
{
|
||||
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;
|
||||
|
@ -53,7 +53,7 @@ TSubgoal VisitHero::whatToDoToAchieve()
|
||||
|
||||
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)
|
||||
{
|
||||
auto obj = cb->getObj(ObjectInstanceID(objid));
|
||||
|
@ -74,7 +74,7 @@ TSubgoal Win::whatToDoToAchieve()
|
||||
case EventCondition::HAVE_BUILDING:
|
||||
{
|
||||
// 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
|
||||
// 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
|
||||
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(),
|
||||
destination.coord.toString(),
|
||||
destinationNode->chainMask,
|
||||
|
@ -79,7 +79,7 @@ namespace AIPathfinding
|
||||
if(hero->canCastThisSpell(summonBoatSpell)
|
||||
&& 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());
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ TResources ResourceManager::estimateIncome() const
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ResourceManager::reserveResoures(const TResources & res, Goals::TSubgoal goal)
|
||||
void ResourceManager::reserveResources(const TResources & res, Goals::TSubgoal goal)
|
||||
{
|
||||
if (!goal->invalid())
|
||||
tryPush(ResourceObjective(res, goal));
|
||||
@ -315,7 +315,7 @@ bool ResourceManager::removeOutdatedObjectives(std::function<bool(const Goals::T
|
||||
TResources ResourceManager::reservedResources() const
|
||||
{
|
||||
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;
|
||||
return res;
|
||||
}
|
||||
@ -323,7 +323,7 @@ TResources ResourceManager::reservedResources() const
|
||||
TResources ResourceManager::freeResources() const
|
||||
{
|
||||
TResources myRes = cb->getResourceAmount();
|
||||
myRes -= reservedResources(); //substract the value of reserved goals
|
||||
myRes -= reservedResources(); //subtract the value of reserved goals
|
||||
|
||||
for (auto & val : myRes)
|
||||
vstd::amax(val, 0); //never negative
|
||||
|
@ -24,7 +24,7 @@ struct DLL_EXPORT ResourceObjective
|
||||
ResourceObjective(const TResources &res, Goals::TSubgoal goal);
|
||||
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...)
|
||||
};
|
||||
|
||||
@ -79,7 +79,7 @@ public:
|
||||
bool notifyGoalCompleted(Goals::TSubgoal goal) override;
|
||||
|
||||
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 tryPush(const ResourceObjective &o);
|
||||
|
||||
|
@ -571,7 +571,7 @@ void VCAI::objectPropertyChanged(const SetObjectProperty * sop)
|
||||
auto obj = myCb->getObj(sop->id, false);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -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")
|
||||
% exits.size()));
|
||||
|
||||
int choosenExit = -1;
|
||||
int chosenExit = -1;
|
||||
if(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);
|
||||
if(destinationTeleport != ObjectInstanceID() && vstd::contains(exits, neededExit))
|
||||
choosenExit = vstd::find_pos(exits, neededExit);
|
||||
chosenExit = vstd::find_pos(exits, neededExit);
|
||||
}
|
||||
|
||||
for(auto exit : exits)
|
||||
{
|
||||
if(status.channelProbing() && exit.first == destinationTeleport)
|
||||
{
|
||||
choosenExit = vstd::find_pos(exits, exit);
|
||||
chosenExit = vstd::find_pos(exits, exit);
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -716,7 +716,7 @@ void VCAI::showTeleportDialog(const CGHeroInstance * hero, TeleportChannelID cha
|
||||
|
||||
requestActionASAP([=]()
|
||||
{
|
||||
answerQuery(askID, choosenExit);
|
||||
answerQuery(askID, chosenExit);
|
||||
});
|
||||
}
|
||||
|
||||
@ -942,7 +942,7 @@ void VCAI::mainLoop()
|
||||
while (possibleGoals.size())
|
||||
{
|
||||
//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);
|
||||
if (bestGoal->hero) //lock this hero to fulfill goal
|
||||
@ -1543,7 +1543,7 @@ void VCAI::completeGoal(Goals::TSubgoal goal)
|
||||
auto it = lockedHeroes.find(h);
|
||||
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());
|
||||
lockedHeroes.erase(it); //goal fulfilled, free hero
|
||||
@ -1735,7 +1735,7 @@ const CGObjectInstance * VCAI::lookForArt(ArtifactID aid) const
|
||||
|
||||
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
|
||||
@ -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?
|
||||
throw goalFulfilledException(sptr(g));
|
||||
|
||||
int accquiredResources = 0;
|
||||
int acquiredResources = 0;
|
||||
if(const CGObjectInstance * obj = cb->getObj(ObjectInstanceID(g.objid), false))
|
||||
{
|
||||
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
|
||||
{
|
||||
cb->trade(m, EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
|
||||
accquiredResources = 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());
|
||||
acquiredResources = static_cast<int>(toGet * (it->resVal / toGive));
|
||||
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)
|
||||
throw goalFulfilledException(sptr(g)); //we traded all we needed
|
||||
|
@ -83,7 +83,7 @@ public:
|
||||
//std::vector<const CGObjectInstance *> visitedThisWeek; //only OPWs
|
||||
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;
|
||||
Goals::TGoalVec goalsToRemove;
|
||||
Goals::TGoalVec goalsToAdd;
|
||||
|
@ -69,7 +69,7 @@ public:
|
||||
//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 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 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
|
||||
FunctionEnd
|
||||
|
||||
Function ConditionalAddToRegisty
|
||||
Function ConditionalAddToRegistry
|
||||
Pop $0
|
||||
Pop $1
|
||||
StrCmp "$0" "" ConditionalAddToRegisty_EmptyString
|
||||
StrCmp "$0" "" ConditionalAddToRegistry_EmptyString
|
||||
WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" \
|
||||
"$1" "$0"
|
||||
;MessageBox MB_OK "Set Registry: '$1' to '$0'"
|
||||
DetailPrint "Set install registry entry: '$1' to '$0'"
|
||||
ConditionalAddToRegisty_EmptyString:
|
||||
ConditionalAddToRegistry_EmptyString:
|
||||
FunctionEnd
|
||||
|
||||
;--------------------------------
|
||||
@ -646,44 +646,44 @@ Section "-Core installation"
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
Push "DisplayName"
|
||||
Push "@CPACK_NSIS_DISPLAY_NAME@"
|
||||
Call ConditionalAddToRegisty
|
||||
Call ConditionalAddToRegistry
|
||||
Push "DisplayVersion"
|
||||
Push "@CPACK_PACKAGE_VERSION@"
|
||||
Call ConditionalAddToRegisty
|
||||
Call ConditionalAddToRegistry
|
||||
Push "Publisher"
|
||||
Push "@CPACK_PACKAGE_VENDOR@"
|
||||
Call ConditionalAddToRegisty
|
||||
Call ConditionalAddToRegistry
|
||||
Push "UninstallString"
|
||||
Push "$INSTDIR\Uninstall.exe"
|
||||
Call ConditionalAddToRegisty
|
||||
Call ConditionalAddToRegistry
|
||||
Push "NoRepair"
|
||||
Push "1"
|
||||
Call ConditionalAddToRegisty
|
||||
Call ConditionalAddToRegistry
|
||||
|
||||
!ifdef CPACK_NSIS_ADD_REMOVE
|
||||
;Create add/remove functionality
|
||||
Push "ModifyPath"
|
||||
Push "$INSTDIR\AddRemove.exe"
|
||||
Call ConditionalAddToRegisty
|
||||
Call ConditionalAddToRegistry
|
||||
!else
|
||||
Push "NoModify"
|
||||
Push "1"
|
||||
Call ConditionalAddToRegisty
|
||||
Call ConditionalAddToRegistry
|
||||
!endif
|
||||
|
||||
; Optional registration
|
||||
Push "DisplayIcon"
|
||||
Push "$INSTDIR\@CPACK_NSIS_INSTALLED_ICON_NAME@"
|
||||
Call ConditionalAddToRegisty
|
||||
Call ConditionalAddToRegistry
|
||||
Push "HelpLink"
|
||||
Push "@CPACK_NSIS_HELP_LINK@"
|
||||
Call ConditionalAddToRegisty
|
||||
Call ConditionalAddToRegistry
|
||||
Push "URLInfoAbout"
|
||||
Push "@CPACK_NSIS_URL_INFO_ABOUT@"
|
||||
Call ConditionalAddToRegisty
|
||||
Call ConditionalAddToRegistry
|
||||
Push "Contact"
|
||||
Push "@CPACK_NSIS_CONTACT@"
|
||||
Call ConditionalAddToRegisty
|
||||
Call ConditionalAddToRegistry
|
||||
!insertmacro MUI_INSTALLOPTIONS_READ $INSTALL_DESKTOP "NSIS.InstallOptions.ini" "Field 5" "State"
|
||||
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
|
||||
|
||||
@ -701,19 +701,19 @@ Section "-Core installation"
|
||||
; Write special uninstall registry entries
|
||||
Push "StartMenu"
|
||||
Push "$STARTMENU_FOLDER"
|
||||
Call ConditionalAddToRegisty
|
||||
Call ConditionalAddToRegistry
|
||||
Push "DoNotAddToPath"
|
||||
Push "$DO_NOT_ADD_TO_PATH"
|
||||
Call ConditionalAddToRegisty
|
||||
Call ConditionalAddToRegistry
|
||||
Push "AddToPathAllUsers"
|
||||
Push "$ADD_TO_PATH_ALL_USERS"
|
||||
Call ConditionalAddToRegisty
|
||||
Call ConditionalAddToRegistry
|
||||
Push "AddToPathCurrentUser"
|
||||
Push "$ADD_TO_PATH_CURRENT_USER"
|
||||
Call ConditionalAddToRegisty
|
||||
Call ConditionalAddToRegistry
|
||||
Push "InstallToDesktop"
|
||||
Push "$INSTALL_DESKTOP"
|
||||
Call ConditionalAddToRegisty
|
||||
Call ConditionalAddToRegistry
|
||||
|
||||
!insertmacro MUI_STARTMENU_WRITE_END
|
||||
|
||||
@ -848,7 +848,7 @@ Section "Uninstall"
|
||||
@CPACK_NSIS_DELETE_ICONS@
|
||||
@CPACK_NSIS_DELETE_ICONS_EXTRA@
|
||||
|
||||
;Delete empty start menu parent diretories
|
||||
;Delete empty start menu parent directories
|
||||
StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"
|
||||
|
||||
startMenuDeleteLoop:
|
||||
@ -867,7 +867,7 @@ Section "Uninstall"
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
|
||||
@CPACK_NSIS_DELETE_ICONS_EXTRA@
|
||||
|
||||
;Delete empty start menu parent diretories
|
||||
;Delete empty start menu parent directories
|
||||
StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"
|
||||
|
||||
secondStartMenuDeleteLoop:
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Minimum required version greatly affect CMake behavior
|
||||
# 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)
|
||||
|
||||
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
|
||||
* 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
|
||||
* 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.
|
||||
* 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
|
||||
@ -321,7 +321,7 @@
|
||||
|
||||
### Battles
|
||||
* 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
|
||||
* Battles against AI players can now be done using quick combat
|
||||
* Disabling battle queue will now correctly reposition hero statistics preview popup
|
||||
@ -885,7 +885,7 @@
|
||||
### GENERAL:
|
||||
* Fixed framerate drops on hero movement with active hota mod
|
||||
* 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
|
||||
* Fixed loading of translations for maps and campaigns
|
||||
* 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
|
||||
* Fixed movement through moat of double-hexed units
|
||||
* 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
|
||||
* Added distinct overlay image for showing movement range of highlighted unit
|
||||
* 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
|
||||
* Fixed placement of shipyards in invalid locations
|
||||
* 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 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
|
||||
@ -1195,7 +1195,7 @@
|
||||
* Added option to show amount of creatures as numeric range rather than adjective
|
||||
* Added option to show map grid
|
||||
* 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
|
||||
* Hero movement speed now matches H3
|
||||
* Improved performance of adventure map rendering
|
||||
@ -1214,7 +1214,7 @@
|
||||
* Fixed white status bar on server connection screen
|
||||
* Buttons in battle window now correctly show tooltip in status bar
|
||||
* 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
|
||||
* 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
|
||||
@ -1300,7 +1300,7 @@
|
||||
* Dragon Breath attack now correctly uses different attack animation if multiple targets are hit
|
||||
* Petrification: implemented 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
|
||||
* Fire shield will no longer trigger on non-adjacent attacks, e.g. from Dragon Breath
|
||||
* Weakness now has correct visual effect
|
||||
@ -1479,7 +1479,7 @@
|
||||
* treasury
|
||||
|
||||
### 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
|
||||
|
||||
### RANDOM MAP GENERATOR:
|
||||
@ -1532,7 +1532,7 @@
|
||||
* New console commands:
|
||||
* gosolo - AI take control over human players and vice versa
|
||||
* 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:
|
||||
* Drawbridge mechanics implemented (animation still missing)
|
||||
@ -1574,7 +1574,7 @@
|
||||
* View Earth
|
||||
* Visions
|
||||
* 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
|
||||
|
||||
### BATTLES:
|
||||
@ -1597,7 +1597,7 @@
|
||||
* VCMI can now be compiled with SDL2
|
||||
* Movies will use ffmpeg library
|
||||
* change boost::bind to std::bind
|
||||
* removed boost::asign
|
||||
* removed boost::assign
|
||||
* Updated FuzzyLite to 5.0
|
||||
* Multiplayer load support was implemented through command-line options
|
||||
|
||||
@ -1646,7 +1646,7 @@
|
||||
* Zone placement
|
||||
* Zone borders and connections, fractalized paths inside zones
|
||||
* Guard generation
|
||||
* Treasue piles generation (so far only few removable objects)
|
||||
* Treasure piles generation (so far only few removable objects)
|
||||
|
||||
### MODS:
|
||||
* 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.
|
||||
* Icons use path to icon instead of image indexes.
|
||||
* 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"
|
||||
* 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
|
||||
|
||||
### 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
|
||||
|
||||
# 0.88 -> 0.89 (Jun 01 2012)
|
||||
@ -1963,7 +1963,7 @@
|
||||
* No wall penalty
|
||||
* Enchanter
|
||||
* Bind
|
||||
* Dispell helpful spells
|
||||
* Dispel helpful spells
|
||||
|
||||
# 0.85 -> 0.86 (Sep 01 2011)
|
||||
|
||||
@ -2085,7 +2085,7 @@
|
||||
* Spell damage specialities (Deemer), fixed bonus (Ciele)
|
||||
* Secondary skill bonuses
|
||||
* Creature Upgrades (Gelu)
|
||||
* Resorce generation
|
||||
* Resource generation
|
||||
* Starting Skill (Adrienne)
|
||||
|
||||
### 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
|
||||
|
||||
### 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:
|
||||
* new special town structures supported:
|
||||
@ -2237,7 +2237,7 @@ http://bugs.vcmi.eu/changelog_page.php?version_id=14
|
||||
### OBJECTS:
|
||||
* 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
|
||||
* Scholar won't give unavaliable spells anymore.
|
||||
* Scholar won't give unavailable spells anymore.
|
||||
|
||||
A lot of of various bugfixes and improvements:
|
||||
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
|
||||
|
||||
### 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
|
||||
* fixed Next Hero button behaviour
|
||||
* 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
|
||||
* timed events won't cause resources amount to be negative
|
||||
* 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
|
||||
|
||||
### ADVENTURE INTERFACE:
|
||||
@ -2954,7 +2954,7 @@ And a lot of minor fixes
|
||||
* [feature] picked artifacts are added to hero's backpack
|
||||
* [feature] possibility of choosing player to play
|
||||
* [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] 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_TRACKBALL);
|
||||
|
||||
if (s2 != 0) cls += "Some_Unkown";
|
||||
if (s2 != 0) cls += "Some_Unknown";
|
||||
|
||||
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";
|
||||
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);
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ public:
|
||||
extern CClientState * CCS;
|
||||
|
||||
/// CGameInfo class
|
||||
/// for allowing different functions for accessing game informations
|
||||
/// for allowing different functions for accessing game information
|
||||
class CGameInfo final : public Services
|
||||
{
|
||||
public:
|
||||
|
@ -282,7 +282,7 @@ int main(int argc, char * argv[])
|
||||
GH.init();
|
||||
|
||||
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();
|
||||
|
||||
// Initialize video
|
||||
@ -525,7 +525,7 @@ void handleQuit(bool ask)
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
/// 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
|
||||
[[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 playerBlocked(int reason, bool start) 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 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
|
||||
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);
|
||||
|
||||
// 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)
|
||||
{
|
||||
//todo: inform on actual resource set transfered
|
||||
//todo: inform on actual resource set transferred
|
||||
callInterfaceIfPresent(cl, pack.player, &IGameEventsReceiver::receivedResource);
|
||||
}
|
||||
|
||||
@ -844,7 +844,7 @@ void ApplyFirstClientNetPackVisitor::visitBattleAttack(BattleAttack & 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()
|
||||
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)
|
||||
return;
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
void show(Canvas & to) override;
|
||||
void showAll(Canvas & to) 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;
|
||||
bool captureThisKey(EShortcut key) override;
|
||||
|
||||
|
@ -380,7 +380,7 @@ std::shared_ptr<CIntObject> CTownList::CTownItem::genSelection()
|
||||
|
||||
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);
|
||||
redraw();
|
||||
|
@ -92,9 +92,9 @@ CMinimap::CMinimap(const Rect & position)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
|
||||
double maxSideLenghtSrc = std::max(LOCPLINT->cb->getMapSize().x, LOCPLINT->cb->getMapSize().y);
|
||||
double maxSideLenghtDst = std::max(position.w, position.h);
|
||||
double resize = maxSideLenghtSrc / maxSideLenghtDst;
|
||||
double maxSideLengthSrc = std::max(LOCPLINT->cb->getMapSize().x, LOCPLINT->cb->getMapSize().y);
|
||||
double maxSideLengthDst = std::max(position.w, position.h);
|
||||
double resize = maxSideLengthSrc / maxSideLengthDst;
|
||||
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);
|
||||
|
||||
|
@ -120,6 +120,6 @@ public:
|
||||
const std::vector<PossiblePlayerBattleAction> & getPossibleActions() const;
|
||||
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);
|
||||
};
|
||||
|
@ -355,9 +355,9 @@ bool MovementAnimation::init()
|
||||
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);
|
||||
@ -398,12 +398,12 @@ void MovementAnimation::tick(uint32_t msPassed)
|
||||
myAnim->pos.moveTo(coords);
|
||||
|
||||
// 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
|
||||
curentMoveIndex++;
|
||||
currentMoveIndex++;
|
||||
prevHex = nextHex;
|
||||
nextHex = destTiles[curentMoveIndex];
|
||||
nextHex = destTiles[currentMoveIndex];
|
||||
|
||||
// request re-initialization
|
||||
initialized = false;
|
||||
@ -417,18 +417,18 @@ MovementAnimation::~MovementAnimation()
|
||||
{
|
||||
assert(stack);
|
||||
|
||||
if(moveSoundHander != -1)
|
||||
CCS->soundh->stopSound(moveSoundHander);
|
||||
if(moveSoundHandler != -1)
|
||||
CCS->soundh->stopSound(moveSoundHandler);
|
||||
}
|
||||
|
||||
MovementAnimation::MovementAnimation(BattleInterface & owner, const CStack *stack, std::vector<BattleHex> _destTiles, int _distance)
|
||||
: StackMoveAnimation(owner, stack, stack->getPosition(), _destTiles.front()),
|
||||
destTiles(_destTiles),
|
||||
curentMoveIndex(0),
|
||||
currentMoveIndex(0),
|
||||
begX(0), begY(0),
|
||||
distanceX(0), distanceY(0),
|
||||
progressPerSecond(0.0),
|
||||
moveSoundHander(-1),
|
||||
moveSoundHandler(-1),
|
||||
progress(0.0)
|
||||
{
|
||||
logAnim->debug("Created MovementAnimation for %s", stack->getName());
|
||||
@ -649,7 +649,7 @@ void RangedAttackAnimation::setAnimationGroup()
|
||||
Point shooterPos = stackAnimation(attackingStack)->pos.topLeft();
|
||||
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;
|
||||
|
||||
double projectileAngle = -atan2(shotTarget.y - shooterPos.y, std::abs(shotTarget.x - shooterPos.x));
|
||||
@ -672,18 +672,18 @@ void RangedAttackAnimation::initializeProjectile()
|
||||
|
||||
if (getGroup() == getUpwardsGroup())
|
||||
{
|
||||
shotOrigin.x += ( -25 + shooterInfo->animation.upperRightMissleOffsetX ) * multiplier;
|
||||
shotOrigin.y += shooterInfo->animation.upperRightMissleOffsetY;
|
||||
shotOrigin.x += ( -25 + shooterInfo->animation.upperRightMissileOffsetX ) * multiplier;
|
||||
shotOrigin.y += shooterInfo->animation.upperRightMissileOffsetY;
|
||||
}
|
||||
else if (getGroup() == getDownwardsGroup())
|
||||
{
|
||||
shotOrigin.x += ( -25 + shooterInfo->animation.lowerRightMissleOffsetX ) * multiplier;
|
||||
shotOrigin.y += shooterInfo->animation.lowerRightMissleOffsetY;
|
||||
shotOrigin.x += ( -25 + shooterInfo->animation.lowerRightMissileOffsetX ) * multiplier;
|
||||
shotOrigin.y += shooterInfo->animation.lowerRightMissileOffsetY;
|
||||
}
|
||||
else if (getGroup() == getForwardGroup())
|
||||
{
|
||||
shotOrigin.x += ( -25 + shooterInfo->animation.rightMissleOffsetX ) * multiplier;
|
||||
shotOrigin.y += shooterInfo->animation.rightMissleOffsetY;
|
||||
shotOrigin.x += ( -25 + shooterInfo->animation.rightMissileOffsetX ) * multiplier;
|
||||
shotOrigin.y += shooterInfo->animation.rightMissileOffsetY;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -141,10 +141,10 @@ protected:
|
||||
class MovementAnimation : public StackMoveAnimation
|
||||
{
|
||||
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
|
||||
ui32 curentMoveIndex; // index of nextHex in destTiles
|
||||
ui32 currentMoveIndex; // index of nextHex in destTiles
|
||||
|
||||
double begX, begY; // starting position
|
||||
double distanceX, distanceY; // full movement distance, may be negative if creture moves topleft
|
||||
|
@ -84,7 +84,7 @@ namespace HexMasks
|
||||
|
||||
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()
|
||||
{
|
||||
hexEdgeMaskToFrameIndex[HexMasks::empty] = 0;
|
||||
@ -548,12 +548,12 @@ std::vector<std::shared_ptr<IImage>> BattleFieldController::calculateRangeLimitH
|
||||
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);
|
||||
rangeLimitHexes = getRangeLimitHexes(hoveredHex, rangeHexes, distance);
|
||||
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)
|
||||
@ -581,8 +581,8 @@ void BattleFieldController::showHighlightedHexes(Canvas & canvas)
|
||||
std::vector<BattleHex> rangedFullDamageLimitHexes;
|
||||
std::vector<BattleHex> shootingRangeLimitHexes;
|
||||
|
||||
std::vector<std::shared_ptr<IImage>> rangedFullDamageLimitHexesHighligts;
|
||||
std::vector<std::shared_ptr<IImage>> shootingRangeLimitHexesHighligts;
|
||||
std::vector<std::shared_ptr<IImage>> rangedFullDamageLimitHexesHighlights;
|
||||
std::vector<std::shared_ptr<IImage>> shootingRangeLimitHexesHighlights;
|
||||
|
||||
std::set<BattleHex> hoveredStackMovementRangeHexes = getMovementRangeForHoveredStack();
|
||||
std::set<BattleHex> hoveredSpellHexes = getHighlightedHexesForSpellRange();
|
||||
@ -598,11 +598,11 @@ void BattleFieldController::showHighlightedHexes(Canvas & canvas)
|
||||
{
|
||||
// calculate array with highlight images for ranged full damage limit
|
||||
auto rangedFullDamageDistance = hoveredStack->getRangedFullDamageDistance();
|
||||
calculateRangeLimitAndHighlightImages(rangedFullDamageDistance, rangedFullDamageLimitImages, rangedFullDamageLimitHexes, rangedFullDamageLimitHexesHighligts);
|
||||
calculateRangeLimitAndHighlightImages(rangedFullDamageDistance, rangedFullDamageLimitImages, rangedFullDamageLimitHexes, rangedFullDamageLimitHexesHighlights);
|
||||
|
||||
// calculate array with highlight images for shooting range limit
|
||||
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;
|
||||
@ -635,11 +635,11 @@ void BattleFieldController::showHighlightedHexes(Canvas & canvas)
|
||||
}
|
||||
if(hexInRangedFullDamageLimit)
|
||||
{
|
||||
showHighlightedHex(canvas, rangedFullDamageLimitHexesHighligts[hexIndexInRangedFullDamageLimit], hex, false);
|
||||
showHighlightedHex(canvas, rangedFullDamageLimitHexesHighlights[hexIndexInRangedFullDamageLimit], hex, false);
|
||||
}
|
||||
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()
|
||||
{
|
||||
auto accessibility = owner.getBattle()->getAccesibility();
|
||||
auto accessibility = owner.getBattle()->getAccessibility();
|
||||
|
||||
for(int i = 0; i < accessibility.size(); i++)
|
||||
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
|
||||
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);
|
||||
|
||||
/// 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);
|
||||
|
||||
/// 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
|
||||
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 stackAttacking(const StackAttackInfo & attackInfo); //called when stack with id ID is attacking something on hex dest
|
||||
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 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
|
||||
|
@ -161,7 +161,7 @@ const CCreature & BattleProjectileController::getShooter(const CStack * stack) c
|
||||
if(creature->getId() == CreatureID::ARROW_TOWERS)
|
||||
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());
|
||||
creature = CreatureID(CreatureID::ARCHER).toCreature();
|
||||
@ -277,7 +277,7 @@ int BattleProjectileController::computeProjectileFrameID( Point from, Point dest
|
||||
{
|
||||
const CCreature & creature = getShooter(stack);
|
||||
|
||||
auto & angles = creature.animation.missleFrameAngles;
|
||||
auto & angles = creature.animation.missileFrameAngles;
|
||||
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
|
||||
|
@ -126,7 +126,7 @@ ImagePath BattleSiegeController::getBattleBackgroundName() const
|
||||
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?
|
||||
//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
|
||||
continue;
|
||||
|
||||
if ( !getWallPieceExistance(EWallVisual::EWallVisual(g)) )
|
||||
if ( !getWallPieceExistence(EWallVisual::EWallVisual(g)) )
|
||||
continue;
|
||||
|
||||
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)
|
||||
{
|
||||
if (getWallPieceExistance(EWallVisual::MOAT))
|
||||
if (getWallPieceExistence(EWallVisual::MOAT))
|
||||
showWallPiece(canvas, EWallVisual::MOAT);
|
||||
|
||||
if (getWallPieceExistance(EWallVisual::MOAT_BANK))
|
||||
if (getWallPieceExistence(EWallVisual::MOAT_BANK))
|
||||
showWallPiece(canvas, EWallVisual::MOAT_BANK);
|
||||
}
|
||||
|
||||
@ -292,7 +292,7 @@ void BattleSiegeController::collectRenderableObjects(BattleRenderer & renderer)
|
||||
{
|
||||
auto wallPiece = EWallVisual::EWallVisual(i);
|
||||
|
||||
if ( !getWallPieceExistance(wallPiece))
|
||||
if ( !getWallPieceExistence(wallPiece))
|
||||
continue;
|
||||
|
||||
if ( getWallPiecePosition(wallPiece) == BattleHex::INVALID)
|
||||
|
@ -83,7 +83,7 @@ class BattleSiegeController
|
||||
BattleHex getWallPiecePosition(EWallVisual::EWallVisual what) const;
|
||||
|
||||
/// 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);
|
||||
|
||||
|
@ -438,7 +438,7 @@ void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> at
|
||||
// defender need to face in direction opposited to out attacker
|
||||
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 && stackAnimation[attackedInfo.defender->unitId()]->getType() != ECreatureAnimType::FROZEN)
|
||||
{
|
||||
|
@ -372,7 +372,7 @@ void CreatureAnimation::nextFrame(Canvas & canvas, const ColorFilter & shifter,
|
||||
IImage::SpecialPalette 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);
|
||||
|
||||
canvas.draw(image, pos.topLeft(), Rect(0, 0, pos.w, pos.h));
|
||||
|
@ -39,7 +39,7 @@ InputSourceGameController::InputSourceGameController():
|
||||
scrollAxisValueY(0),
|
||||
scrollPlanDisX(0.0),
|
||||
scrollPlanDisY(0.0),
|
||||
configTriggerTreshold(settings["input"]["controllerTriggerTreshold"].Float()),
|
||||
configTriggerThreshold(settings["input"]["controllerTriggerThreshold"].Float()),
|
||||
configAxisDeadZone(settings["input"]["controllerAxisDeadZone"].Float()),
|
||||
configAxisFullZone(settings["input"]["controllerAxisFullZone"].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)
|
||||
{
|
||||
if(getRealAxisValue(axisValue) > configTriggerTreshold)
|
||||
if(getRealAxisValue(axisValue) > configTriggerThreshold)
|
||||
{
|
||||
if(!pressedAxes.count(axisID))
|
||||
{
|
||||
|
@ -39,7 +39,7 @@ class InputSourceGameController
|
||||
double scrollPlanDisX;
|
||||
double scrollPlanDisY;
|
||||
|
||||
const double configTriggerTreshold;
|
||||
const double configTriggerThreshold;
|
||||
const double configAxisDeadZone;
|
||||
const double configAxisFullZone;
|
||||
const double configAxisSpeed;
|
||||
|
@ -65,7 +65,7 @@ GlobalLobbyLoginWindow::GlobalLobbyLoginWindow()
|
||||
{
|
||||
buttonLogin->block(true);
|
||||
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
|
||||
toggleMode->setSelected(1);
|
||||
|
@ -79,7 +79,7 @@ public:
|
||||
|
||||
/// deactivates if needed, blocks all automatic activity, allows only disposal
|
||||
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();
|
||||
/// deactivates or activates UI element based on flag
|
||||
void setEnabled(bool on);
|
||||
|
@ -304,7 +304,7 @@ void EventDispatcher::dispatchTextInput(const std::string & text)
|
||||
{
|
||||
for(auto it : textInterested)
|
||||
{
|
||||
it->textInputed(text);
|
||||
it->textInputted(text);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ public:
|
||||
/// Called when UI element gesture status changes
|
||||
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 keyPressed(EShortcut key) {}
|
||||
|
@ -22,7 +22,7 @@ class FramerateManager
|
||||
Duration targetFrameTime;
|
||||
TimePoint lastTimePoint;
|
||||
|
||||
/// index of last measured frome in lastFrameTimes array
|
||||
/// index of last measured from in lastFrameTimes array
|
||||
ui32 lastFrameIndex;
|
||||
|
||||
bool vsyncEnabled;
|
||||
|
@ -41,7 +41,7 @@ public:
|
||||
InterfaceObjectConfigurable(const JsonNode & config, int used=0, Point offset=Point());
|
||||
|
||||
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);
|
||||
|
||||
/// 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));
|
||||
}
|
||||
|
||||
// plId is not neccessarily player color, just an index
|
||||
// plId is not necessarily player color, just an index
|
||||
auto team = settingsVec.at(plId).getTeam();
|
||||
if(team == TeamID::NO_TEAM)
|
||||
{
|
||||
@ -577,9 +577,9 @@ TeamAlignmentsWidget::TeamAlignmentsWidget(RandomMapTab & randomMapTab):
|
||||
void RandomMapTab::saveOptions(const CMapGenOptions & options)
|
||||
{
|
||||
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
|
||||
Settings rmgSettings = persistentStorage.write["rmg"];
|
||||
|
@ -136,7 +136,7 @@ size_t CMenuScreen::getActiveTab() const
|
||||
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 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;
|
||||
uint32_t now = GH.input().getTicks();
|
||||
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)
|
||||
firstAccepted = x;
|
||||
diff += x.second;
|
||||
|
@ -289,7 +289,7 @@ bool MusicEntry::play()
|
||||
|
||||
// erase stored position:
|
||||
// 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));
|
||||
|
||||
if(Mix_FadeInMusicPos(music, 1, 1000, timeToStart) == -1)
|
||||
|
@ -147,7 +147,7 @@ uint32_t CSoundHandler::getSoundDurationMilliseconds(const AudioPath & sound)
|
||||
SDL_AudioSpec spec;
|
||||
uint32_t audioLen;
|
||||
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)
|
||||
{
|
||||
@ -155,10 +155,10 @@ uint32_t CSoundHandler::getSoundDurationMilliseconds(const AudioPath & sound)
|
||||
uint32_t sampleSize = SDL_AUDIO_BITSIZE(spec.format) / 8;
|
||||
uint32_t sampleCount = audioLen / sampleSize;
|
||||
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
|
||||
@ -292,7 +292,7 @@ void CSoundHandler::soundFinishedCallback(int channel)
|
||||
return;
|
||||
|
||||
// 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);
|
||||
callbacks.erase(channel);
|
||||
|
||||
|
@ -29,14 +29,14 @@ class Canvas
|
||||
/// constructs canvas using existing surface. Caller maintains ownership on the surface
|
||||
explicit Canvas(SDL_Surface * surface);
|
||||
|
||||
/// copy contructor
|
||||
/// copy constructor
|
||||
Canvas(const Canvas & other);
|
||||
|
||||
public:
|
||||
Canvas & operator = (const Canvas & other) = delete;
|
||||
Canvas & operator = (Canvas && other) = delete;
|
||||
|
||||
/// move contructor
|
||||
/// move constructor
|
||||
Canvas(Canvas && other);
|
||||
|
||||
/// creates canvas that only covers specified subsection of a surface
|
||||
|
@ -76,7 +76,7 @@ public:
|
||||
virtual void setBlitMode(EImageBlitMode mode) = 0;
|
||||
|
||||
//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 verticalFlip() = 0;
|
||||
|
@ -321,7 +321,7 @@ void SDLImage::resetPalette()
|
||||
if(originalPalette == nullptr)
|
||||
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);
|
||||
}
|
||||
|
||||
@ -330,11 +330,11 @@ void SDLImage::resetPalette( int colorID )
|
||||
if(originalPalette == nullptr)
|
||||
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);
|
||||
}
|
||||
|
||||
void SDLImage::setSpecialPallete(const IImage::SpecialPalette & specialPalette, uint32_t colorsToSkipMask)
|
||||
void SDLImage::setSpecialPalette(const IImage::SpecialPalette & specialPalette, uint32_t colorsToSkipMask)
|
||||
{
|
||||
if(surf->format->palette)
|
||||
{
|
||||
|
@ -74,7 +74,7 @@ public:
|
||||
void setAlpha(uint8_t value) 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;
|
||||
|
||||
|
@ -154,7 +154,7 @@ public:
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
|
@ -189,7 +189,7 @@ void CTextInput::updateLabel()
|
||||
label->setText(visibleText);
|
||||
}
|
||||
|
||||
void CTextInput::textInputed(const std::string & enteredText)
|
||||
void CTextInput::textInputted(const std::string & enteredText)
|
||||
{
|
||||
if(!hasFocus())
|
||||
return;
|
||||
|
@ -70,7 +70,7 @@ class CTextInput final : public CFocusable
|
||||
void updateLabel();
|
||||
|
||||
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 onFocusGot() final;
|
||||
void onFocusLost() final;
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
/// if set, only specified section of internal image will be rendered
|
||||
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;
|
||||
|
||||
std::shared_ptr<IImage> getSurface()
|
||||
|
@ -77,7 +77,7 @@ public:
|
||||
//ItemOffset - distance between items in the list
|
||||
//VisibleSize - maximal number of displayable at once items
|
||||
//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
|
||||
CListBox(CreateFunc create, Point Pos, Point ItemOffset, size_t VisibleSize,
|
||||
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];
|
||||
Point where = destRect.topLeft();
|
||||
const std::string delimeters = "{}";
|
||||
auto delimitersCount = std::count_if(what.cbegin(), what.cend(), [&delimeters](char c)
|
||||
const std::string delimiters = "{}";
|
||||
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.
|
||||
delimitersCount *= f->getStringWidth(delimeters)/2;
|
||||
delimitersCount *= f->getStringWidth(delimiters)/2;
|
||||
|
||||
std::smatch match;
|
||||
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());
|
||||
|
||||
size_t begin = 0;
|
||||
size_t currDelimeter = 0;
|
||||
size_t currDelimiter = 0;
|
||||
|
||||
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)
|
||||
{
|
||||
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::regex expr("^(.*?)\\|");
|
||||
@ -249,7 +249,7 @@ void CTextContainer::blitLine(Canvas & to, Rect destRect, std::string what)
|
||||
|
||||
where.x += (int)f->getStringWidth(toPrint);
|
||||
}
|
||||
currDelimeter++;
|
||||
currDelimiter++;
|
||||
} while(begin++ != std::string::npos);
|
||||
}
|
||||
|
||||
|
@ -234,7 +234,7 @@ std::string CBuildingRect::getSubtitle()//hover text for building
|
||||
|
||||
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();
|
||||
else//dwellings - recruit %creature%
|
||||
{
|
||||
@ -476,7 +476,7 @@ void CHeroGSlot::setHighlight(bool on)
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -1364,7 +1364,7 @@ void CCastleInterface::removeBuilding(BuildingID bid)
|
||||
void CCastleInterface::recreateIcons()
|
||||
{
|
||||
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);
|
||||
TResources townIncome = town->dailyIncome();
|
||||
|
@ -59,7 +59,7 @@ public:
|
||||
std::function<void(CreatureID)> callback;
|
||||
};
|
||||
|
||||
// pointers to permament objects in game state
|
||||
// pointers to permanent objects in game state
|
||||
const CCreature * creature;
|
||||
const CCommanderInstance * commander;
|
||||
const CStackInstance * stackNode;
|
||||
@ -144,10 +144,10 @@ void CCommanderSkillIcon::show(Canvas &to)
|
||||
|
||||
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 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/_";
|
||||
switch (skill)
|
||||
{
|
||||
@ -170,17 +170,17 @@ static ImagePath skillToFile(int skill, int level, bool selected)
|
||||
file += "MP";
|
||||
break;
|
||||
}
|
||||
std::string sufix;
|
||||
std::string suffix;
|
||||
if (selected)
|
||||
level++; // UI will display resulting level
|
||||
if (level == 0)
|
||||
sufix = "no"; //not avaliable - no number
|
||||
suffix = "no"; //not available - no number
|
||||
else
|
||||
sufix = std::to_string(level-1);
|
||||
suffix = std::to_string(level-1);
|
||||
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)
|
||||
@ -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()));
|
||||
|
||||
if(buttonsToCreate == 1) // single upgrade avaialbe
|
||||
if(buttonsToCreate == 1) // single upgrade available
|
||||
upgradeBtn->assignedKey = EShortcut::RECRUITMENT_UPGRADE;
|
||||
|
||||
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
|
||||
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:
|
||||
CCommanderSkillIcon(std::shared_ptr<CIntObject> object_, bool isMasterAbility_, std::function<void()> callback);
|
||||
|
||||
|
@ -102,7 +102,7 @@ public:
|
||||
|
||||
void update() override;
|
||||
|
||||
void dismissCurrent(); //dissmissed currently displayed hero (curHero)
|
||||
void dismissCurrent(); //dismissed currently displayed hero (curHero)
|
||||
void commanderWindow();
|
||||
void switchHero(); //changes displayed hero
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
|
||||
Rect minimapRect = minimaps[id].getRenderArea();
|
||||
double maxSideLenghtSrc = std::max(minimapRect.w, minimapRect.h);
|
||||
double maxSideLenghtDst = std::max(rect.w, rect.h);
|
||||
double resize = maxSideLenghtSrc / maxSideLenghtDst;
|
||||
double maxSideLengthSrc = std::max(minimapRect.w, minimapRect.h);
|
||||
double maxSideLengthDst = std::max(rect.w, rect.h);
|
||||
double resize = maxSideLengthSrc / maxSideLengthDst;
|
||||
Point newMinimapSize = Point(minimapRect.w / resize, minimapRect.h / resize);
|
||||
|
||||
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)
|
||||
{
|
||||
size_t begin = 0;
|
||||
std::string delimeters = "{}";
|
||||
size_t start = msg.find_first_of(delimeters[0], begin);
|
||||
size_t end = msg.find_first_of(delimeters[1], start);
|
||||
std::string delimiters = "{}";
|
||||
size_t start = msg.find_first_of(delimiters[0], begin);
|
||||
size_t end = msg.find_first_of(delimiters[1], start);
|
||||
if(start > msg.size() || end > msg.size())
|
||||
return "";
|
||||
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
|
||||
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);
|
||||
// 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));
|
||||
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);
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
};
|
||||
|
||||
/*
|
||||
* options - EOpions enum
|
||||
* options - EOptions enum
|
||||
* imageName - name for background image, can be empty
|
||||
* centerAt - position of window center. Default - center of the screen
|
||||
*/
|
||||
|
@ -44,7 +44,7 @@ private:
|
||||
void initCostBox();
|
||||
|
||||
// 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
|
||||
{
|
||||
public:
|
||||
|
@ -153,7 +153,7 @@ void CRecruitmentWindow::buy()
|
||||
std::pair<SlotID, SlotID> toMerge;
|
||||
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);
|
||||
}
|
||||
|
@ -82,11 +82,11 @@ This module responds to the following cache variables:
|
||||
SDL2_LIBRARY
|
||||
SDL2 Library (.dll, .so, .a, etc) path.
|
||||
|
||||
SDL2MAIN_LIBRAY
|
||||
SDL2MAIN_LIBRARY
|
||||
SDL2main Library (.a) path.
|
||||
|
||||
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_LIBRARIES, because only applications need main() (No need to also
|
||||
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 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.
|
||||
|
||||
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
|
||||
|
||||
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`.
|
||||
|
||||
|
@ -33,7 +33,7 @@ Client is responsible for:
|
||||
|
||||
## 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.
|
||||
|
||||
# Server
|
||||
@ -111,7 +111,7 @@ VCAI module is currently developed agent-based system driven by goals and heroes
|
||||
|
||||
## 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
|
||||
|
||||
|
@ -759,7 +759,7 @@ The line length for c++ source code is 120 columns. If your function declaration
|
||||
|
||||
### 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
|
||||
|
||||
@ -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)
|
||||
|
||||
### 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:
|
||||
|
||||
|
@ -158,4 +158,4 @@ global, level=debug
|
||||
ai, level=not set, effective level=debug
|
||||
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 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:
|
||||
|
||||
|
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
- 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
|
||||
|
||||
@ -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.
|
||||
|
||||
- subtype: spell identifer
|
||||
- subtype: spell identifier
|
||||
- val: duration of the spell, in rounds
|
||||
|
||||
### 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
|
||||
|
||||
- val: increase to damage, percentage
|
||||
- subtype: spell identifer
|
||||
- subtype: spell identifier
|
||||
|
||||
### MIND_IMMUNITY
|
||||
|
||||
|
@ -13,7 +13,7 @@ Difficulty configuration is located in [config/difficulty.json](../config/diffic
|
||||
{
|
||||
//starting resources
|
||||
"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": [],
|
||||
//bonuses will be given to player every battle
|
||||
"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`.
|
||||
|
||||
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`.
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user