mirror of
https://github.com/vcmi/vcmi.git
synced 2025-02-03 13:01:33 +02:00
Merge remote-tracking branch 'upstream/develop' into editor-improvements-1.4
# Conflicts: # lib/mapObjects/CGObjectInstance.cpp
This commit is contained in:
commit
0148662847
@ -52,7 +52,7 @@ void CBattleAI::initBattleInterface(std::shared_ptr<Environment> ENV, std::share
|
||||
setCbc(CB);
|
||||
env = ENV;
|
||||
cb = CB;
|
||||
playerID = *CB->getPlayerID(); //TODO should be sth in callback
|
||||
playerID = *CB->getPlayerID();
|
||||
wasWaitingForRealize = CB->waitTillRealize;
|
||||
wasUnlockingGs = CB->unlockGsWhenWaiting;
|
||||
CB->waitTillRealize = false;
|
||||
@ -66,9 +66,9 @@ void CBattleAI::initBattleInterface(std::shared_ptr<Environment> ENV, std::share
|
||||
autobattlePreferences = autocombatPreferences;
|
||||
}
|
||||
|
||||
BattleAction CBattleAI::useHealingTent(const CStack *stack)
|
||||
BattleAction CBattleAI::useHealingTent(const BattleID & battleID, const CStack *stack)
|
||||
{
|
||||
auto healingTargets = cb->battleGetStacks(CBattleInfoEssentials::ONLY_MINE);
|
||||
auto healingTargets = cb->getBattle(battleID)->battleGetStacks(CBattleInfoEssentials::ONLY_MINE);
|
||||
std::map<int, const CStack*> woundHpToStack;
|
||||
for(const auto * stack : healingTargets)
|
||||
{
|
||||
@ -82,12 +82,12 @@ BattleAction CBattleAI::useHealingTent(const CStack *stack)
|
||||
return BattleAction::makeHeal(stack, woundHpToStack.rbegin()->second); //last element of the woundHpToStack is the most wounded stack
|
||||
}
|
||||
|
||||
void CBattleAI::yourTacticPhase(int distance)
|
||||
void CBattleAI::yourTacticPhase(const BattleID & battleID, int distance)
|
||||
{
|
||||
cb->battleMakeTacticAction(BattleAction::makeEndOFTacticPhase(cb->battleGetTacticsSide()));
|
||||
cb->battleMakeTacticAction(battleID, BattleAction::makeEndOFTacticPhase(cb->getBattle(battleID)->battleGetTacticsSide()));
|
||||
}
|
||||
|
||||
float getStrengthRatio(std::shared_ptr<CBattleCallback> cb, int side)
|
||||
static float getStrengthRatio(std::shared_ptr<CBattleInfoCallback> cb, int side)
|
||||
{
|
||||
auto stacks = cb->battleGetAllStacks();
|
||||
auto our = 0, enemy = 0;
|
||||
@ -108,7 +108,7 @@ float getStrengthRatio(std::shared_ptr<CBattleCallback> cb, int side)
|
||||
return enemy == 0 ? 1.0f : static_cast<float>(our) / enemy;
|
||||
}
|
||||
|
||||
void CBattleAI::activeStack(const CStack * stack )
|
||||
void CBattleAI::activeStack(const BattleID & battleID, const CStack * stack )
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "stack: %s", stack->nodeName());
|
||||
|
||||
@ -128,12 +128,12 @@ void CBattleAI::activeStack(const CStack * stack )
|
||||
{
|
||||
if(stack->creatureId() == CreatureID::CATAPULT)
|
||||
{
|
||||
cb->battleMakeUnitAction(useCatapult(stack));
|
||||
cb->battleMakeUnitAction(battleID, useCatapult(battleID, stack));
|
||||
return;
|
||||
}
|
||||
if(stack->hasBonusOfType(BonusType::SIEGE_WEAPON) && stack->hasBonusOfType(BonusType::HEALER))
|
||||
{
|
||||
cb->battleMakeUnitAction(useHealingTent(stack));
|
||||
cb->battleMakeUnitAction(battleID, useHealingTent(battleID, stack));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -141,7 +141,7 @@ void CBattleAI::activeStack(const CStack * stack )
|
||||
logAi->trace("Build evaluator and targets");
|
||||
#endif
|
||||
|
||||
BattleEvaluator evaluator(env, cb, stack, playerID, side, getStrengthRatio(cb, side));
|
||||
BattleEvaluator evaluator(env, cb, stack, playerID, battleID, side, getStrengthRatio(cb->getBattle(battleID), side));
|
||||
|
||||
result = evaluator.selectStackAction(stack);
|
||||
|
||||
@ -157,9 +157,9 @@ void CBattleAI::activeStack(const CStack * stack )
|
||||
|
||||
logAi->trace("Spellcast attempt completed in %lld", timeElapsed(start));
|
||||
|
||||
if(auto action = considerFleeingOrSurrendering())
|
||||
if(auto action = considerFleeingOrSurrendering(battleID))
|
||||
{
|
||||
cb->battleMakeUnitAction(*action);
|
||||
cb->battleMakeUnitAction(battleID, *action);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -183,17 +183,17 @@ void CBattleAI::activeStack(const CStack * stack )
|
||||
|
||||
logAi->trace("BattleAI decission made in %lld", timeElapsed(start));
|
||||
|
||||
cb->battleMakeUnitAction(result);
|
||||
cb->battleMakeUnitAction(battleID, result);
|
||||
}
|
||||
|
||||
BattleAction CBattleAI::useCatapult(const CStack * stack)
|
||||
BattleAction CBattleAI::useCatapult(const BattleID & battleID, const CStack * stack)
|
||||
{
|
||||
BattleAction attack;
|
||||
BattleHex targetHex = BattleHex::INVALID;
|
||||
|
||||
if(cb->battleGetGateState() == EGateState::CLOSED)
|
||||
if(cb->getBattle(battleID)->battleGetGateState() == EGateState::CLOSED)
|
||||
{
|
||||
targetHex = cb->wallPartToBattleHex(EWallPart::GATE);
|
||||
targetHex = cb->getBattle(battleID)->wallPartToBattleHex(EWallPart::GATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -209,11 +209,11 @@ BattleAction CBattleAI::useCatapult(const CStack * stack)
|
||||
|
||||
for(auto wallPart : wallParts)
|
||||
{
|
||||
auto wallState = cb->battleGetWallState(wallPart);
|
||||
auto wallState = cb->getBattle(battleID)->battleGetWallState(wallPart);
|
||||
|
||||
if(wallState == EWallState::REINFORCED || wallState == EWallState::INTACT || wallState == EWallState::DAMAGED)
|
||||
{
|
||||
targetHex = cb->wallPartToBattleHex(wallPart);
|
||||
targetHex = cb->getBattle(battleID)->wallPartToBattleHex(wallPart);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -234,7 +234,7 @@ BattleAction CBattleAI::useCatapult(const CStack * stack)
|
||||
return attack;
|
||||
}
|
||||
|
||||
void CBattleAI::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool Side, bool replayAllowed)
|
||||
void CBattleAI::battleStart(const BattleID & battleID, const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool Side, bool replayAllowed)
|
||||
{
|
||||
LOG_TRACE(logAi);
|
||||
side = Side;
|
||||
@ -244,20 +244,20 @@ void CBattleAI::battleStart(const CCreatureSet *army1, const CCreatureSet *army2
|
||||
|
||||
void CBattleAI::print(const std::string &text) const
|
||||
{
|
||||
logAi->trace("%s Battle AI[%p]: %s", playerID.getStr(), this, text);
|
||||
logAi->trace("%s Battle AI[%p]: %s", playerID.toString(), this, text);
|
||||
}
|
||||
|
||||
std::optional<BattleAction> CBattleAI::considerFleeingOrSurrendering()
|
||||
std::optional<BattleAction> CBattleAI::considerFleeingOrSurrendering(const BattleID & battleID)
|
||||
{
|
||||
BattleStateInfoForRetreat bs;
|
||||
|
||||
bs.canFlee = cb->battleCanFlee();
|
||||
bs.canSurrender = cb->battleCanSurrender(playerID);
|
||||
bs.ourSide = cb->battleGetMySide();
|
||||
bs.ourHero = cb->battleGetMyHero();
|
||||
bs.canFlee = cb->getBattle(battleID)->battleCanFlee();
|
||||
bs.canSurrender = cb->getBattle(battleID)->battleCanSurrender(playerID);
|
||||
bs.ourSide = cb->getBattle(battleID)->battleGetMySide();
|
||||
bs.ourHero = cb->getBattle(battleID)->battleGetMyHero();
|
||||
bs.enemyHero = nullptr;
|
||||
|
||||
for(auto stack : cb->battleGetAllStacks(false))
|
||||
for(auto stack : cb->getBattle(battleID)->battleGetAllStacks(false))
|
||||
{
|
||||
if(stack->alive())
|
||||
{
|
||||
@ -266,7 +266,7 @@ std::optional<BattleAction> CBattleAI::considerFleeingOrSurrendering()
|
||||
else
|
||||
{
|
||||
bs.enemyStacks.push_back(stack);
|
||||
bs.enemyHero = cb->battleGetOwnerHero(stack);
|
||||
bs.enemyHero = cb->getBattle(battleID)->battleGetOwnerHero(stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -278,7 +278,7 @@ std::optional<BattleAction> CBattleAI::considerFleeingOrSurrendering()
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto result = cb->makeSurrenderRetreatDecision(bs);
|
||||
auto result = cb->makeSurrenderRetreatDecision(battleID, bs);
|
||||
|
||||
if(!result && bs.canFlee && bs.turnsSkippedByDefense > 30)
|
||||
{
|
||||
|
@ -71,16 +71,16 @@ public:
|
||||
void initBattleInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CBattleCallback> CB) override;
|
||||
void initBattleInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CBattleCallback> CB, AutocombatPreferences autocombatPreferences) override;
|
||||
|
||||
void activeStack(const CStack * stack) override; //called when it's turn of that stack
|
||||
void yourTacticPhase(int distance) override;
|
||||
void activeStack(const BattleID & battleID, const CStack * stack) override; //called when it's turn of that stack
|
||||
void yourTacticPhase(const BattleID & battleID, int distance) override;
|
||||
|
||||
std::optional<BattleAction> considerFleeingOrSurrendering();
|
||||
std::optional<BattleAction> considerFleeingOrSurrendering(const BattleID & battleID);
|
||||
|
||||
void print(const std::string &text) const;
|
||||
BattleAction useCatapult(const CStack *stack);
|
||||
BattleAction useHealingTent(const CStack *stack);
|
||||
BattleAction useCatapult(const BattleID & battleID, const CStack *stack);
|
||||
BattleAction useHealingTent(const BattleID & battleID, const CStack *stack);
|
||||
|
||||
void battleStart(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool Side, bool replayAllowed) override;
|
||||
void battleStart(const BattleID & battleID, const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool Side, bool replayAllowed) override;
|
||||
//void actionFinished(const BattleAction &action) override;//occurs AFTER every action taken by any stack or by the hero
|
||||
//void actionStarted(const BattleAction &action) override;//occurs BEFORE every action taken by any stack or by the hero
|
||||
//void battleAttack(const BattleAttack *ba) override; //called when stack is performing attack
|
||||
|
@ -53,12 +53,12 @@ std::vector<BattleHex> BattleEvaluator::getBrokenWallMoatHexes() const
|
||||
|
||||
for(EWallPart wallPart : { EWallPart::BOTTOM_WALL, EWallPart::BELOW_GATE, EWallPart::OVER_GATE, EWallPart::UPPER_WALL })
|
||||
{
|
||||
auto state = cb->battleGetWallState(wallPart);
|
||||
auto state = cb->getBattle(battleID)->battleGetWallState(wallPart);
|
||||
|
||||
if(state != EWallState::DESTROYED)
|
||||
continue;
|
||||
|
||||
auto wallHex = cb->wallPartToBattleHex((EWallPart)wallPart);
|
||||
auto wallHex = cb->getBattle(battleID)->wallPartToBattleHex((EWallPart)wallPart);
|
||||
auto moatHex = wallHex.cloneInDirection(BattleHex::LEFT);
|
||||
|
||||
result.push_back(moatHex);
|
||||
@ -70,15 +70,15 @@ std::vector<BattleHex> BattleEvaluator::getBrokenWallMoatHexes() const
|
||||
std::optional<PossibleSpellcast> BattleEvaluator::findBestCreatureSpell(const CStack *stack)
|
||||
{
|
||||
//TODO: faerie dragon type spell should be selected by server
|
||||
SpellID creatureSpellToCast = cb->battleGetRandomStackSpell(CRandomGenerator::getDefault(), stack, CBattleInfoCallback::RANDOM_AIMED);
|
||||
SpellID creatureSpellToCast = cb->getBattle(battleID)->battleGetRandomStackSpell(CRandomGenerator::getDefault(), stack, CBattleInfoCallback::RANDOM_AIMED);
|
||||
if(stack->hasBonusOfType(BonusType::SPELLCASTER) && stack->canCast() && creatureSpellToCast != SpellID::NONE)
|
||||
{
|
||||
const CSpell * spell = creatureSpellToCast.toSpell();
|
||||
|
||||
if(spell->canBeCast(getCbc().get(), spells::Mode::CREATURE_ACTIVE, stack))
|
||||
if(spell->canBeCast(cb->getBattle(battleID).get(), spells::Mode::CREATURE_ACTIVE, stack))
|
||||
{
|
||||
std::vector<PossibleSpellcast> possibleCasts;
|
||||
spells::BattleCast temp(getCbc().get(), stack, spells::Mode::CREATURE_ACTIVE, spell);
|
||||
spells::BattleCast temp(cb->getBattle(battleID).get(), stack, spells::Mode::CREATURE_ACTIVE, spell);
|
||||
for(auto & target : temp.findPotentialTargets())
|
||||
{
|
||||
PossibleSpellcast ps;
|
||||
@ -201,7 +201,7 @@ BattleAction BattleEvaluator::selectStackAction(const CStack * stack)
|
||||
if(score <= EvaluationResult::INEFFECTIVE_SCORE
|
||||
&& !stack->hasBonusOfType(BonusType::FLYING)
|
||||
&& stack->unitSide() == BattleSide::ATTACKER
|
||||
&& cb->battleGetSiegeLevel() >= CGTownInstance::CITADEL)
|
||||
&& cb->getBattle(battleID)->battleGetSiegeLevel() >= CGTownInstance::CITADEL)
|
||||
{
|
||||
auto brokenWallMoat = getBrokenWallMoatHexes();
|
||||
|
||||
@ -228,8 +228,8 @@ uint64_t timeElapsed(std::chrono::time_point<std::chrono::high_resolution_clock>
|
||||
|
||||
BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, std::vector<BattleHex> hexes)
|
||||
{
|
||||
auto reachability = cb->getReachability(stack);
|
||||
auto avHexes = cb->battleGetAvailableHexes(reachability, stack, false);
|
||||
auto reachability = cb->getBattle(battleID)->getReachability(stack);
|
||||
auto avHexes = cb->getBattle(battleID)->battleGetAvailableHexes(reachability, stack, false);
|
||||
|
||||
if(!avHexes.size() || !hexes.size()) //we are blocked or dest is blocked
|
||||
{
|
||||
@ -325,16 +325,16 @@ BattleAction BattleEvaluator::goTowardsNearest(const CStack * stack, std::vector
|
||||
|
||||
bool BattleEvaluator::canCastSpell()
|
||||
{
|
||||
auto hero = cb->battleGetMyHero();
|
||||
auto hero = cb->getBattle(battleID)->battleGetMyHero();
|
||||
if(!hero)
|
||||
return false;
|
||||
|
||||
return cb->battleCanCastSpell(hero, spells::Mode::HERO) == ESpellCastProblem::OK;
|
||||
return cb->getBattle(battleID)->battleCanCastSpell(hero, spells::Mode::HERO) == ESpellCastProblem::OK;
|
||||
}
|
||||
|
||||
bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
|
||||
{
|
||||
auto hero = cb->battleGetMyHero();
|
||||
auto hero = cb->getBattle(battleID)->battleGetMyHero();
|
||||
if(!hero)
|
||||
return false;
|
||||
|
||||
@ -343,7 +343,7 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
|
||||
std::vector<const CSpell*> possibleSpells;
|
||||
vstd::copy_if(VLC->spellh->objects, std::back_inserter(possibleSpells), [hero, this](const CSpell *s) -> bool
|
||||
{
|
||||
return s->canBeCast(cb.get(), spells::Mode::HERO, hero);
|
||||
return s->canBeCast(cb->getBattle(battleID).get(), spells::Mode::HERO, hero);
|
||||
});
|
||||
LOGFL("I can cast %d spells.", possibleSpells.size());
|
||||
|
||||
@ -358,7 +358,7 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
|
||||
std::vector<PossibleSpellcast> possibleCasts;
|
||||
for(auto spell : possibleSpells)
|
||||
{
|
||||
spells::BattleCast temp(cb.get(), hero, spells::Mode::HERO, spell);
|
||||
spells::BattleCast temp(cb->getBattle(battleID).get(), hero, spells::Mode::HERO, spell);
|
||||
|
||||
if(spell->getTargetType() == spells::AimType::LOCATION)
|
||||
continue;
|
||||
@ -390,7 +390,7 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
|
||||
for(auto & round : queue)
|
||||
{
|
||||
if(!firstRound)
|
||||
state->nextRound(0);//todo: set actual value?
|
||||
state->nextRound();
|
||||
for(auto unit : round)
|
||||
{
|
||||
if(!vstd::contains(values, unit->unitId()))
|
||||
@ -468,7 +468,7 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
|
||||
ValueMap valueOfStack;
|
||||
ValueMap healthOfStack;
|
||||
|
||||
TStacks all = cb->battleGetAllStacks(false);
|
||||
TStacks all = cb->getBattle(battleID)->battleGetAllStacks(false);
|
||||
|
||||
size_t ourRemainingTurns = 0;
|
||||
|
||||
@ -477,7 +477,7 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
|
||||
healthOfStack[unit->unitId()] = unit->getAvailableHealth();
|
||||
valueOfStack[unit->unitId()] = 0;
|
||||
|
||||
if(cb->battleGetOwner(unit) == playerID && unit->canMove() && !unit->moved())
|
||||
if(cb->getBattle(battleID)->battleGetOwner(unit) == playerID && unit->canMove() && !unit->moved())
|
||||
ourRemainingTurns++;
|
||||
}
|
||||
|
||||
@ -494,12 +494,12 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
|
||||
|
||||
std::vector<battle::Units> turnOrder;
|
||||
|
||||
cb->battleGetTurnOrder(turnOrder, amount, 2); //no more than 1 turn after current, each unit at least once
|
||||
cb->getBattle(battleID)->battleGetTurnOrder(turnOrder, amount, 2); //no more than 1 turn after current, each unit at least once
|
||||
|
||||
{
|
||||
bool enemyHadTurn = false;
|
||||
|
||||
auto state = std::make_shared<HypotheticBattle>(env.get(), cb);
|
||||
auto state = std::make_shared<HypotheticBattle>(env.get(), cb->getBattle(battleID));
|
||||
|
||||
evaluateQueue(valueOfStack, turnOrder, state, 0, &enemyHadTurn);
|
||||
|
||||
@ -531,7 +531,7 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
|
||||
logAi->trace("Evaluating %s", ps.spell->getNameTranslated());
|
||||
#endif
|
||||
|
||||
auto state = std::make_shared<HypotheticBattle>(env.get(), cb);
|
||||
auto state = std::make_shared<HypotheticBattle>(env.get(), cb->getBattle(battleID));
|
||||
|
||||
spells::BattleCast cast(state.get(), hero, spells::Mode::HERO, ps.spell);
|
||||
cast.castEval(state->getServerCallback(), ps.dest);
|
||||
@ -540,7 +540,7 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
|
||||
|
||||
auto needFullEval = vstd::contains_if(allUnits, [&](const battle::Unit * u) -> bool
|
||||
{
|
||||
auto original = cb->battleGetUnitByID(u->unitId());
|
||||
auto original = cb->getBattle(battleID)->battleGetUnitByID(u->unitId());
|
||||
return !original || u->speed() != original->speed();
|
||||
});
|
||||
|
||||
@ -583,7 +583,7 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
|
||||
if(oldHealth != newHealth)
|
||||
{
|
||||
auto damage = std::abs(oldHealth - newHealth);
|
||||
auto originalDefender = cb->battleGetUnitByID(unit->unitId());
|
||||
auto originalDefender = cb->getBattle(battleID)->battleGetUnitByID(unit->unitId());
|
||||
|
||||
auto dpsReduce = AttackPossibility::calculateDamageReduce(
|
||||
nullptr,
|
||||
@ -639,7 +639,7 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
|
||||
spellcast.setTarget(castToPerform.dest);
|
||||
spellcast.side = side;
|
||||
spellcast.stackNumber = (!side) ? -1 : -2;
|
||||
cb->battleMakeSpellAction(spellcast);
|
||||
cb->battleMakeSpellAction(battleID, spellcast);
|
||||
activeActionMade = true;
|
||||
|
||||
return true;
|
||||
@ -656,8 +656,8 @@ void BattleEvaluator::evaluateCreatureSpellcast(const CStack * stack, PossibleSp
|
||||
using ValueMap = PossibleSpellcast::ValueMap;
|
||||
|
||||
RNGStub rngStub;
|
||||
HypotheticBattle state(env.get(), cb);
|
||||
TStacks all = cb->battleGetAllStacks(false);
|
||||
HypotheticBattle state(env.get(), cb->getBattle(battleID));
|
||||
TStacks all = cb->getBattle(battleID)->battleGetAllStacks(false);
|
||||
|
||||
ValueMap healthOfStack;
|
||||
ValueMap newHealthOfStack;
|
||||
@ -686,7 +686,7 @@ void BattleEvaluator::evaluateCreatureSpellcast(const CStack * stack, PossibleSp
|
||||
|
||||
auto healthDiff = newHealthOfStack[unitId] - healthOfStack[unitId];
|
||||
|
||||
if(localUnit->unitOwner() != getCbc()->getPlayerID())
|
||||
if(localUnit->unitOwner() != cb->getBattle(battleID)->getPlayerID())
|
||||
healthDiff = -healthDiff;
|
||||
|
||||
if(healthDiff < 0)
|
||||
@ -703,7 +703,7 @@ void BattleEvaluator::evaluateCreatureSpellcast(const CStack * stack, PossibleSp
|
||||
|
||||
void BattleEvaluator::print(const std::string & text) const
|
||||
{
|
||||
logAi->trace("%s Battle AI[%p]: %s", playerID.getStr(), this, text);
|
||||
logAi->trace("%s Battle AI[%p]: %s", playerID.toString(), this, text);
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,6 +32,7 @@ class BattleEvaluator
|
||||
bool activeActionMade = false;
|
||||
std::optional<AttackPossibility> cachedAttack;
|
||||
PlayerColor playerID;
|
||||
BattleID battleID;
|
||||
int side;
|
||||
float cachedScore;
|
||||
DamageCache damageCache;
|
||||
@ -52,11 +53,12 @@ public:
|
||||
std::shared_ptr<CBattleCallback> cb,
|
||||
const battle::Unit * activeStack,
|
||||
PlayerColor playerID,
|
||||
BattleID battleID,
|
||||
int side,
|
||||
float strengthRatio)
|
||||
:scoreEvaluator(cb, env, strengthRatio), cachedAttack(), playerID(playerID), side(side), env(env), cb(cb), strengthRatio(strengthRatio)
|
||||
:scoreEvaluator(cb->getBattle(battleID), env, strengthRatio), cachedAttack(), playerID(playerID), side(side), env(env), cb(cb), strengthRatio(strengthRatio), battleID(battleID)
|
||||
{
|
||||
hb = std::make_shared<HypotheticBattle>(env.get(), cb);
|
||||
hb = std::make_shared<HypotheticBattle>(env.get(), cb->getBattle(battleID));
|
||||
damageCache.buildDamageCache(hb, side);
|
||||
|
||||
targets = std::make_unique<PotentialTargets>(activeStack, damageCache, hb);
|
||||
@ -70,9 +72,10 @@ public:
|
||||
DamageCache & damageCache,
|
||||
const battle::Unit * activeStack,
|
||||
PlayerColor playerID,
|
||||
BattleID battleID,
|
||||
int side,
|
||||
float strengthRatio)
|
||||
:scoreEvaluator(cb, env, strengthRatio), cachedAttack(), playerID(playerID), side(side), env(env), cb(cb), hb(hb), damageCache(damageCache), strengthRatio(strengthRatio)
|
||||
:scoreEvaluator(cb->getBattle(battleID), env, strengthRatio), cachedAttack(), playerID(playerID), side(side), env(env), cb(cb), hb(hb), damageCache(damageCache), strengthRatio(strengthRatio), battleID(battleID)
|
||||
{
|
||||
targets = std::make_unique<PotentialTargets>(activeStack, damageCache, hb);
|
||||
cachedScore = EvaluationResult::INEFFECTIVE_SCORE;
|
||||
|
@ -133,4 +133,4 @@ public:
|
||||
|
||||
float getPositiveEffectMultiplier() { return 1; }
|
||||
float getNegativeEffectMultiplier() { return negativeEffectMultiplier; }
|
||||
};
|
||||
};
|
||||
|
@ -231,7 +231,7 @@ void StackWithBonuses::removeUnitBonus(const CSelector & selector)
|
||||
std::string StackWithBonuses::getDescription() const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << unitOwner().getStr();
|
||||
oss << unitOwner().toString();
|
||||
oss << " battle stack [" << unitId() << "]: " << getCount() << " of ";
|
||||
if(type)
|
||||
oss << type->getJsonKey();
|
||||
@ -320,12 +320,17 @@ battle::Units HypotheticBattle::getUnitsIf(battle::UnitFilter predicate) const
|
||||
return ret;
|
||||
}
|
||||
|
||||
BattleID HypotheticBattle::getBattleID() const
|
||||
{
|
||||
return subject->getBattle()->getBattleID();
|
||||
}
|
||||
|
||||
int32_t HypotheticBattle::getActiveStackID() const
|
||||
{
|
||||
return activeUnitId;
|
||||
}
|
||||
|
||||
void HypotheticBattle::nextRound(int32_t roundNr)
|
||||
void HypotheticBattle::nextRound()
|
||||
{
|
||||
//TODO:HypotheticBattle::nextRound
|
||||
for(auto unit : battleAliveUnits())
|
||||
@ -462,6 +467,24 @@ int64_t HypotheticBattle::getActualDamage(const DamageRange & damage, int32_t at
|
||||
return (damage.min + damage.max) / 2;
|
||||
}
|
||||
|
||||
std::vector<SpellID> HypotheticBattle::getUsedSpells(ui8 side) const
|
||||
{
|
||||
// TODO
|
||||
return {};
|
||||
}
|
||||
|
||||
int3 HypotheticBattle::getLocation() const
|
||||
{
|
||||
// TODO
|
||||
return int3(-1, -1, -1);
|
||||
}
|
||||
|
||||
bool HypotheticBattle::isCreatureBank() const
|
||||
{
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t HypotheticBattle::getTreeVersion() const
|
||||
{
|
||||
return getBonusBearer()->getTreeVersion() + bonusTreeVersion;
|
||||
@ -552,8 +575,9 @@ const Services * HypotheticBattle::HypotheticEnvironment::services() const
|
||||
return env->services();
|
||||
}
|
||||
|
||||
const Environment::BattleCb * HypotheticBattle::HypotheticEnvironment::battle() const
|
||||
const Environment::BattleCb * HypotheticBattle::HypotheticEnvironment::battle(const BattleID & battleID) const
|
||||
{
|
||||
assert(battleID == owner->getBattleID());
|
||||
return owner;
|
||||
}
|
||||
|
||||
|
@ -110,11 +110,13 @@ public:
|
||||
|
||||
std::shared_ptr<StackWithBonuses> getForUpdate(uint32_t id);
|
||||
|
||||
BattleID getBattleID() const override;
|
||||
|
||||
int32_t getActiveStackID() const override;
|
||||
|
||||
battle::Units getUnitsIf(battle::UnitFilter predicate) const override;
|
||||
|
||||
void nextRound(int32_t roundNr) override;
|
||||
void nextRound() override;
|
||||
void nextTurn(uint32_t unitId) override;
|
||||
|
||||
void addUnit(uint32_t id, const JsonNode & data) override;
|
||||
@ -136,6 +138,9 @@ public:
|
||||
uint32_t nextUnitId() const override;
|
||||
|
||||
int64_t getActualDamage(const DamageRange & damage, int32_t attackerCount, vstd::RNG & rng) const override;
|
||||
std::vector<SpellID> getUsedSpells(ui8 side) const override;
|
||||
int3 getLocation() const override;
|
||||
bool isCreatureBank() const override;
|
||||
|
||||
int64_t getTreeVersion() const;
|
||||
|
||||
@ -177,7 +182,7 @@ private:
|
||||
HypotheticEnvironment(HypotheticBattle * owner_, const Environment * upperEnvironment);
|
||||
|
||||
const Services * services() const override;
|
||||
const BattleCb * battle() const override;
|
||||
const BattleCb * battle(const BattleID & battleID) const override;
|
||||
const GameCb * game() const override;
|
||||
vstd::CLoggerBase * logger() const override;
|
||||
events::EventBus * eventBus() const override;
|
||||
|
@ -27,7 +27,7 @@ void CEmptyAI::initGameInterface(std::shared_ptr<Environment> ENV, std::shared_p
|
||||
cb = CB;
|
||||
env = ENV;
|
||||
human=false;
|
||||
playerID = *cb->getMyColor();
|
||||
playerID = *cb->getPlayerID();
|
||||
}
|
||||
|
||||
void CEmptyAI::yourTurn(QueryID queryID)
|
||||
@ -36,14 +36,14 @@ void CEmptyAI::yourTurn(QueryID queryID)
|
||||
cb->endTurn();
|
||||
}
|
||||
|
||||
void CEmptyAI::activeStack(const CStack * stack)
|
||||
void CEmptyAI::activeStack(const BattleID & battleID, const CStack * stack)
|
||||
{
|
||||
cb->battleMakeUnitAction(BattleAction::makeDefend(stack));
|
||||
cb->battleMakeUnitAction(battleID, BattleAction::makeDefend(stack));
|
||||
}
|
||||
|
||||
void CEmptyAI::yourTacticPhase(int distance)
|
||||
void CEmptyAI::yourTacticPhase(const BattleID & battleID, int distance)
|
||||
{
|
||||
cb->battleMakeTacticAction(BattleAction::makeEndOFTacticPhase(cb->battleGetTacticsSide()));
|
||||
cb->battleMakeTacticAction(battleID, BattleAction::makeEndOFTacticPhase(cb->getBattle(battleID)->battleGetTacticsSide()));
|
||||
}
|
||||
|
||||
void CEmptyAI::heroGotLevel(const CGHeroInstance *hero, PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID)
|
||||
@ -76,7 +76,7 @@ void CEmptyAI::showMapObjectSelectDialog(QueryID askID, const Component & icon,
|
||||
cb->selectionMade(0, askID);
|
||||
}
|
||||
|
||||
std::optional<BattleAction> CEmptyAI::makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState)
|
||||
std::optional<BattleAction> CEmptyAI::makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
@ -24,15 +24,15 @@ public:
|
||||
|
||||
void initGameInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB) override;
|
||||
void yourTurn(QueryID queryID) override;
|
||||
void yourTacticPhase(int distance) override;
|
||||
void activeStack(const CStack * stack) override;
|
||||
void yourTacticPhase(const BattleID & battleID, int distance) override;
|
||||
void activeStack(const BattleID & battleID, const CStack * stack) override;
|
||||
void heroGotLevel(const CGHeroInstance *hero, PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override;
|
||||
void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override;
|
||||
void showBlockingDialog(const std::string &text, const std::vector<Component> &components, QueryID askID, const int soundID, bool selection, bool cancel) override;
|
||||
void showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
|
||||
void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override;
|
||||
void showMapObjectSelectDialog(QueryID askID, const Component & icon, const MetaString & title, const MetaString & description, const std::vector<ObjectInstanceID> & objects) override;
|
||||
std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState) override;
|
||||
std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState) override;
|
||||
};
|
||||
|
||||
#define NAME "EmptyAI 0.1"
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "../../lib/serializer/BinarySerializer.h"
|
||||
#include "../../lib/serializer/BinaryDeserializer.h"
|
||||
#include "../../lib/battle/BattleStateInfoForRetreat.h"
|
||||
#include "../../lib/battle/BattleInfo.h"
|
||||
|
||||
#include "AIGateway.h"
|
||||
#include "Goals/Goals.h"
|
||||
@ -192,7 +193,7 @@ void AIGateway::gameOver(PlayerColor player, const EVictoryLossCheckResult & vic
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "victoryLossCheckResult '%s'", victoryLossCheckResult.messageToSelf.toString());
|
||||
NET_EVENT_HANDLER;
|
||||
logAi->debug("Player %d (%s): I heard that player %d (%s) %s.", playerID, playerID.getStr(), player, player.getStr(), (victoryLossCheckResult.victory() ? "won" : "lost"));
|
||||
logAi->debug("Player %d (%s): I heard that player %d (%s) %s.", playerID, playerID.toString(), player, player.toString(), (victoryLossCheckResult.victory() ? "won" : "lost"));
|
||||
|
||||
// some whitespace to flush stream
|
||||
logAi->debug(std::string(200, ' '));
|
||||
@ -201,12 +202,12 @@ void AIGateway::gameOver(PlayerColor player, const EVictoryLossCheckResult & vic
|
||||
{
|
||||
if(victoryLossCheckResult.victory())
|
||||
{
|
||||
logAi->debug("AIGateway: Player %d (%s) won. I won! Incredible!", player, player.getStr());
|
||||
logAi->debug("AIGateway: Player %d (%s) won. I won! Incredible!", player, player.toString());
|
||||
logAi->debug("Turn nr %d", myCb->getDate());
|
||||
}
|
||||
else
|
||||
{
|
||||
logAi->debug("AIGateway: Player %d (%s) lost. It's me. What a disappointment! :(", player, player.getStr());
|
||||
logAi->debug("AIGateway: Player %d (%s) lost. It's me. What a disappointment! :(", player, player.toString());
|
||||
}
|
||||
|
||||
// some whitespace to flush stream
|
||||
@ -387,7 +388,7 @@ void AIGateway::heroCreated(const CGHeroInstance * h)
|
||||
NET_EVENT_HANDLER;
|
||||
}
|
||||
|
||||
void AIGateway::advmapSpellCast(const CGHeroInstance * caster, int spellID)
|
||||
void AIGateway::advmapSpellCast(const CGHeroInstance * caster, SpellID spellID)
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "spellID '%i", spellID);
|
||||
NET_EVENT_HANDLER;
|
||||
@ -510,7 +511,7 @@ void AIGateway::showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositio
|
||||
NET_EVENT_HANDLER;
|
||||
}
|
||||
|
||||
std::optional<BattleAction> AIGateway::makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState)
|
||||
std::optional<BattleAction> AIGateway::makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState)
|
||||
{
|
||||
LOG_TRACE(logAi);
|
||||
NET_EVENT_HANDLER;
|
||||
@ -535,7 +536,7 @@ void AIGateway::initGameInterface(std::shared_ptr<Environment> env, std::shared_
|
||||
cbc = CB;
|
||||
|
||||
NET_EVENT_HANDLER;
|
||||
playerID = *myCb->getMyColor();
|
||||
playerID = *myCb->getPlayerID();
|
||||
myCb->waitTillRealize = true;
|
||||
myCb->unlockGsWhenWaiting = true;
|
||||
|
||||
@ -776,7 +777,7 @@ void AIGateway::makeTurn()
|
||||
MAKING_TURN;
|
||||
|
||||
auto day = cb->getDate(Date::DAY);
|
||||
logAi->info("Player %d (%s) starting turn, day %d", playerID, playerID.getStr(), day);
|
||||
logAi->info("Player %d (%s) starting turn, day %d", playerID, playerID.toString(), day);
|
||||
|
||||
boost::shared_lock<boost::shared_mutex> gsLock(CGameState::mutex);
|
||||
setThreadName("AIGateway::makeTurn");
|
||||
@ -1080,23 +1081,23 @@ void AIGateway::recruitCreatures(const CGDwelling * d, const CArmedInstance * re
|
||||
}
|
||||
}
|
||||
|
||||
void AIGateway::battleStart(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side, bool replayAllowed)
|
||||
void AIGateway::battleStart(const BattleID & battleID, const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side, bool replayAllowed)
|
||||
{
|
||||
NET_EVENT_HANDLER;
|
||||
assert(!playerID.isValidPlayer() || status.getBattle() == UPCOMING_BATTLE);
|
||||
status.setBattle(ONGOING_BATTLE);
|
||||
const CGObjectInstance * presumedEnemy = vstd::backOrNull(cb->getVisitableObjs(tile)); //may be nullptr in some very are cases -> eg. visited monolith and fighting with an enemy at the FoW covered exit
|
||||
battlename = boost::str(boost::format("Starting battle of %s attacking %s at %s") % (hero1 ? hero1->getNameTranslated() : "a army") % (presumedEnemy ? presumedEnemy->getObjectName() : "unknown enemy") % tile.toString());
|
||||
CAdventureAI::battleStart(army1, army2, tile, hero1, hero2, side, replayAllowed);
|
||||
CAdventureAI::battleStart(battleID, army1, army2, tile, hero1, hero2, side, replayAllowed);
|
||||
}
|
||||
|
||||
void AIGateway::battleEnd(const BattleResult * br, QueryID queryID)
|
||||
void AIGateway::battleEnd(const BattleID & battleID, const BattleResult * br, QueryID queryID)
|
||||
{
|
||||
NET_EVENT_HANDLER;
|
||||
assert(status.getBattle() == ONGOING_BATTLE);
|
||||
status.setBattle(ENDING_BATTLE);
|
||||
bool won = br->winner == myCb->battleGetMySide();
|
||||
logAi->debug("Player %d (%s): I %s the %s!", playerID, playerID.getStr(), (won ? "won" : "lost"), battlename);
|
||||
bool won = br->winner == myCb->getBattle(battleID)->battleGetMySide();
|
||||
logAi->debug("Player %d (%s): I %s the %s!", playerID, playerID.toString(), (won ? "won" : "lost"), battlename);
|
||||
battlename.clear();
|
||||
|
||||
if (queryID != QueryID::NONE)
|
||||
@ -1108,7 +1109,7 @@ void AIGateway::battleEnd(const BattleResult * br, QueryID queryID)
|
||||
answerQuery(queryID, confirmAction);
|
||||
});
|
||||
}
|
||||
CAdventureAI::battleEnd(br, queryID);
|
||||
CAdventureAI::battleEnd(battleID, br, queryID);
|
||||
}
|
||||
|
||||
void AIGateway::waitTillFree()
|
||||
@ -1421,7 +1422,7 @@ void AIGateway::tryRealize(Goals::Trade & g) //trade
|
||||
|
||||
void AIGateway::endTurn()
|
||||
{
|
||||
logAi->info("Player %d (%s) ends turn", playerID, playerID.getStr());
|
||||
logAi->info("Player %d (%s) ends turn", playerID, playerID.toString());
|
||||
if(!status.haveTurn())
|
||||
{
|
||||
logAi->error("Not having turn at the end of turn???");
|
||||
@ -1441,7 +1442,7 @@ void AIGateway::endTurn()
|
||||
}
|
||||
while(status.haveTurn()); //for some reasons, our request may fail -> stop requesting end of turn only after we've received a confirmation that it's over
|
||||
|
||||
logGlobal->info("Player %d (%s) ended turn", playerID, playerID.getStr());
|
||||
logGlobal->info("Player %d (%s) ended turn", playerID, playerID.toString());
|
||||
}
|
||||
|
||||
void AIGateway::buildArmyIn(const CGTownInstance * t)
|
||||
|
@ -152,7 +152,7 @@ public:
|
||||
void showHillFortWindow(const CGObjectInstance * object, const CGHeroInstance * visitor) override;
|
||||
void playerBonusChanged(const Bonus & bonus, bool gain) override;
|
||||
void heroCreated(const CGHeroInstance *) override;
|
||||
void advmapSpellCast(const CGHeroInstance * caster, int spellID) override;
|
||||
void advmapSpellCast(const CGHeroInstance * caster, SpellID spellID) override;
|
||||
void showInfoDialog(EInfoWindowMode type, const std::string & text, const std::vector<Component> & components, int soundID) override;
|
||||
void requestRealized(PackageApplied * pa) override;
|
||||
void receivedResource() override;
|
||||
@ -167,10 +167,10 @@ public:
|
||||
void heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) override;
|
||||
void showMarketWindow(const IMarket * market, const CGHeroInstance * visitor) override;
|
||||
void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override;
|
||||
std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState) override;
|
||||
std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState) override;
|
||||
|
||||
void battleStart(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side, bool replayAllowed) override;
|
||||
void battleEnd(const BattleResult * br, QueryID queryID) override;
|
||||
void battleStart(const BattleID & battleID, const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side, bool replayAllowed) override;
|
||||
void battleEnd(const BattleID & battleID, const BattleResult * br, QueryID queryID) override;
|
||||
|
||||
void makeTurn();
|
||||
|
||||
|
@ -68,7 +68,7 @@ PriorityEvaluator::~PriorityEvaluator()
|
||||
|
||||
void PriorityEvaluator::initVisitTile()
|
||||
{
|
||||
auto file = CResourceHandler::get()->load(ResourceID("config/ai/object-priorities.txt"))->readAll();
|
||||
auto file = CResourceHandler::get()->load(ResourcePath("config/ai/object-priorities.txt"))->readAll();
|
||||
std::string str = std::string((char *)file.first.get(), file.second);
|
||||
engine = fl::FllImporter().fromString(str);
|
||||
armyLossPersentageVariable = engine->getInputVariable("armyLoss");
|
||||
|
@ -1208,7 +1208,7 @@ bool AINodeStorage::hasBetterChain(
|
||||
"Block ineficient battle move %s->%s, hero: %s[%X], army %lld, mp diff: %i",
|
||||
source->coord.toString(),
|
||||
candidateNode->coord.toString(),
|
||||
candidateNode->actor->hero->name,
|
||||
candidateNode->actor->hero->getNameTranslated(),
|
||||
candidateNode->actor->chainMask,
|
||||
candidateNode->actor->armyValue,
|
||||
node.moveRemains - candidateNode->moveRemains);
|
||||
@ -1232,7 +1232,7 @@ bool AINodeStorage::hasBetterChain(
|
||||
"Block ineficient move because of stronger army %s->%s, hero: %s[%X], army %lld, mp diff: %i",
|
||||
source->coord.toString(),
|
||||
candidateNode->coord.toString(),
|
||||
candidateNode->actor->hero->name,
|
||||
candidateNode->actor->hero->getNameTranslated(),
|
||||
candidateNode->actor->chainMask,
|
||||
candidateNode->actor->armyValue,
|
||||
node.moveRemains - candidateNode->moveRemains);
|
||||
@ -1258,7 +1258,7 @@ bool AINodeStorage::hasBetterChain(
|
||||
"Block ineficient move because of stronger hero %s->%s, hero: %s[%X], army %lld, mp diff: %i",
|
||||
source->coord.toString(),
|
||||
candidateNode->coord.toString(),
|
||||
candidateNode->actor->hero->name,
|
||||
candidateNode->actor->hero->getNameTranslated(),
|
||||
candidateNode->actor->chainMask,
|
||||
candidateNode->actor->armyValue,
|
||||
node.moveRemains - candidateNode->moveRemains);
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/battle/BattleAction.h"
|
||||
#include "../../lib/battle/BattleInfo.h"
|
||||
|
||||
static std::shared_ptr<CBattleCallback> cbc;
|
||||
|
||||
@ -53,12 +54,12 @@ void CStupidAI::initBattleInterface(std::shared_ptr<Environment> ENV, std::share
|
||||
initBattleInterface(ENV, CB);
|
||||
}
|
||||
|
||||
void CStupidAI::actionFinished(const BattleAction &action)
|
||||
void CStupidAI::actionFinished(const BattleID & battleID, const BattleAction &action)
|
||||
{
|
||||
print("actionFinished called");
|
||||
}
|
||||
|
||||
void CStupidAI::actionStarted(const BattleAction &action)
|
||||
void CStupidAI::actionStarted(const BattleID & battleID, const BattleAction &action)
|
||||
{
|
||||
print("actionStarted called");
|
||||
}
|
||||
@ -71,11 +72,11 @@ public:
|
||||
std::vector<BattleHex> attackFrom; //for melee fight
|
||||
EnemyInfo(const CStack * _s) : s(_s), adi(0), adr(0)
|
||||
{}
|
||||
void calcDmg(const CStack * ourStack)
|
||||
void calcDmg(const BattleID & battleID, const CStack * ourStack)
|
||||
{
|
||||
// FIXME: provide distance info for Jousting bonus
|
||||
DamageEstimation retal;
|
||||
DamageEstimation dmg = cbc->battleEstimateDamage(ourStack, s, 0, &retal);
|
||||
DamageEstimation dmg = cbc->getBattle(battleID)->battleEstimateDamage(ourStack, s, 0, &retal);
|
||||
adi = static_cast<int>((dmg.damage.min + dmg.damage.max) / 2);
|
||||
adr = static_cast<int>((retal.damage.min + retal.damage.max) / 2);
|
||||
}
|
||||
@ -91,14 +92,14 @@ bool isMoreProfitable(const EnemyInfo &ei1, const EnemyInfo& ei2)
|
||||
return (ei1.adi-ei1.adr) < (ei2.adi - ei2.adr);
|
||||
}
|
||||
|
||||
static bool willSecondHexBlockMoreEnemyShooters(const BattleHex &h1, const BattleHex &h2)
|
||||
static bool willSecondHexBlockMoreEnemyShooters(const BattleID & battleID, const BattleHex &h1, const BattleHex &h2)
|
||||
{
|
||||
int shooters[2] = {0}; //count of shooters on hexes
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
for (auto & neighbour : (i ? h2 : h1).neighbouringTiles())
|
||||
if(const auto * s = cbc->battleGetUnitByPos(neighbour))
|
||||
if(const auto * s = cbc->getBattle(battleID)->battleGetUnitByPos(neighbour))
|
||||
if(s->isShooter())
|
||||
shooters[i]++;
|
||||
}
|
||||
@ -106,16 +107,16 @@ static bool willSecondHexBlockMoreEnemyShooters(const BattleHex &h1, const Battl
|
||||
return shooters[0] < shooters[1];
|
||||
}
|
||||
|
||||
void CStupidAI::yourTacticPhase(int distance)
|
||||
void CStupidAI::yourTacticPhase(const BattleID & battleID, int distance)
|
||||
{
|
||||
cb->battleMakeTacticAction(BattleAction::makeEndOFTacticPhase(cb->battleGetTacticsSide()));
|
||||
cb->battleMakeTacticAction(battleID, BattleAction::makeEndOFTacticPhase(cb->getBattle(battleID)->battleGetTacticsSide()));
|
||||
}
|
||||
|
||||
void CStupidAI::activeStack( const CStack * stack )
|
||||
void CStupidAI::activeStack(const BattleID & battleID, const CStack * stack)
|
||||
{
|
||||
//boost::this_thread::sleep_for(boost::chrono::seconds(2));
|
||||
print("activeStack called for " + stack->nodeName());
|
||||
ReachabilityInfo dists = cb->getReachability(stack);
|
||||
ReachabilityInfo dists = cb->getBattle(battleID)->getReachability(stack);
|
||||
std::vector<EnemyInfo> enemiesShootable, enemiesReachable, enemiesUnreachable;
|
||||
|
||||
if(stack->creatureId() == CreatureID::CATAPULT)
|
||||
@ -128,24 +129,24 @@ void CStupidAI::activeStack( const CStack * stack )
|
||||
attack.side = side;
|
||||
attack.stackNumber = stack->unitId();
|
||||
|
||||
cb->battleMakeUnitAction(attack);
|
||||
cb->battleMakeUnitAction(battleID, attack);
|
||||
return;
|
||||
}
|
||||
else if(stack->hasBonusOfType(BonusType::SIEGE_WEAPON))
|
||||
{
|
||||
cb->battleMakeUnitAction(BattleAction::makeDefend(stack));
|
||||
cb->battleMakeUnitAction(battleID, BattleAction::makeDefend(stack));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const CStack *s : cb->battleGetStacks(CBattleCallback::ONLY_ENEMY))
|
||||
for (const CStack *s : cb->getBattle(battleID)->battleGetStacks(CBattleInfoEssentials::ONLY_ENEMY))
|
||||
{
|
||||
if(cb->battleCanShoot(stack, s->getPosition()))
|
||||
if(cb->getBattle(battleID)->battleCanShoot(stack, s->getPosition()))
|
||||
{
|
||||
enemiesShootable.push_back(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<BattleHex> avHexes = cb->battleGetAvailableHexes(stack, false);
|
||||
std::vector<BattleHex> avHexes = cb->getBattle(battleID)->battleGetAvailableHexes(stack, false);
|
||||
|
||||
for (BattleHex hex : avHexes)
|
||||
{
|
||||
@ -168,21 +169,23 @@ void CStupidAI::activeStack( const CStack * stack )
|
||||
}
|
||||
|
||||
for ( auto & enemy : enemiesReachable )
|
||||
enemy.calcDmg( stack );
|
||||
enemy.calcDmg(battleID, stack);
|
||||
|
||||
for ( auto & enemy : enemiesShootable )
|
||||
enemy.calcDmg( stack );
|
||||
enemy.calcDmg(battleID, stack);
|
||||
|
||||
if(enemiesShootable.size())
|
||||
{
|
||||
const EnemyInfo &ei= *std::max_element(enemiesShootable.begin(), enemiesShootable.end(), isMoreProfitable);
|
||||
cb->battleMakeUnitAction(BattleAction::makeShotAttack(stack, ei.s));
|
||||
cb->battleMakeUnitAction(battleID, BattleAction::makeShotAttack(stack, ei.s));
|
||||
return;
|
||||
}
|
||||
else if(enemiesReachable.size())
|
||||
{
|
||||
const EnemyInfo &ei= *std::max_element(enemiesReachable.begin(), enemiesReachable.end(), &isMoreProfitable);
|
||||
cb->battleMakeUnitAction(BattleAction::makeMeleeAttack(stack, ei.s->getPosition(), *std::max_element(ei.attackFrom.begin(), ei.attackFrom.end(), &willSecondHexBlockMoreEnemyShooters)));
|
||||
BattleHex targetHex = *std::max_element(ei.attackFrom.begin(), ei.attackFrom.end(), [&](auto a, auto b) { return willSecondHexBlockMoreEnemyShooters(battleID, a, b);});
|
||||
|
||||
cb->battleMakeUnitAction(battleID, BattleAction::makeMeleeAttack(stack, ei.s->getPosition(), targetHex));
|
||||
return;
|
||||
}
|
||||
else if(enemiesUnreachable.size()) //due to #955 - a buggy battle may occur when there are no enemies
|
||||
@ -194,26 +197,26 @@ void CStupidAI::activeStack( const CStack * stack )
|
||||
|
||||
if(dists.distToNearestNeighbour(stack, closestEnemy->s) < GameConstants::BFIELD_SIZE)
|
||||
{
|
||||
cb->battleMakeUnitAction(goTowards(stack, closestEnemy->s->getAttackableHexes(stack)));
|
||||
cb->battleMakeUnitAction(battleID, goTowards(battleID, stack, closestEnemy->s->getAttackableHexes(stack)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cb->battleMakeUnitAction(BattleAction::makeDefend(stack));
|
||||
cb->battleMakeUnitAction(battleID, BattleAction::makeDefend(stack));
|
||||
return;
|
||||
}
|
||||
|
||||
void CStupidAI::battleAttack(const BattleAttack *ba)
|
||||
void CStupidAI::battleAttack(const BattleID & battleID, const BattleAttack *ba)
|
||||
{
|
||||
print("battleAttack called");
|
||||
}
|
||||
|
||||
void CStupidAI::battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa, bool ranged)
|
||||
void CStupidAI::battleStacksAttacked(const BattleID & battleID, const std::vector<BattleStackAttacked> & bsa, bool ranged)
|
||||
{
|
||||
print("battleStacksAttacked called");
|
||||
}
|
||||
|
||||
void CStupidAI::battleEnd(const BattleResult *br, QueryID queryID)
|
||||
void CStupidAI::battleEnd(const BattleID & battleID, const BattleResult *br, QueryID queryID)
|
||||
{
|
||||
print("battleEnd called");
|
||||
}
|
||||
@ -223,38 +226,38 @@ void CStupidAI::battleEnd(const BattleResult *br, QueryID queryID)
|
||||
// print("battleResultsApplied called");
|
||||
// }
|
||||
|
||||
void CStupidAI::battleNewRoundFirst(int round)
|
||||
void CStupidAI::battleNewRoundFirst(const BattleID & battleID)
|
||||
{
|
||||
print("battleNewRoundFirst called");
|
||||
}
|
||||
|
||||
void CStupidAI::battleNewRound(int round)
|
||||
void CStupidAI::battleNewRound(const BattleID & battleID)
|
||||
{
|
||||
print("battleNewRound called");
|
||||
}
|
||||
|
||||
void CStupidAI::battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance, bool teleport)
|
||||
void CStupidAI::battleStackMoved(const BattleID & battleID, const CStack * stack, std::vector<BattleHex> dest, int distance, bool teleport)
|
||||
{
|
||||
print("battleStackMoved called");
|
||||
}
|
||||
|
||||
void CStupidAI::battleSpellCast(const BattleSpellCast *sc)
|
||||
void CStupidAI::battleSpellCast(const BattleID & battleID, const BattleSpellCast *sc)
|
||||
{
|
||||
print("battleSpellCast called");
|
||||
}
|
||||
|
||||
void CStupidAI::battleStacksEffectsSet(const SetStackEffect & sse)
|
||||
void CStupidAI::battleStacksEffectsSet(const BattleID & battleID, const SetStackEffect & sse)
|
||||
{
|
||||
print("battleStacksEffectsSet called");
|
||||
}
|
||||
|
||||
void CStupidAI::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool Side, bool replayAllowed)
|
||||
void CStupidAI::battleStart(const BattleID & battleID, const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool Side, bool replayAllowed)
|
||||
{
|
||||
print("battleStart called");
|
||||
side = Side;
|
||||
}
|
||||
|
||||
void CStupidAI::battleCatapultAttacked(const CatapultAttack & ca)
|
||||
void CStupidAI::battleCatapultAttacked(const BattleID & battleID, const CatapultAttack & ca)
|
||||
{
|
||||
print("battleCatapultAttacked called");
|
||||
}
|
||||
@ -264,10 +267,10 @@ void CStupidAI::print(const std::string &text) const
|
||||
logAi->trace("CStupidAI [%p]: %s", this, text);
|
||||
}
|
||||
|
||||
BattleAction CStupidAI::goTowards(const CStack * stack, std::vector<BattleHex> hexes) const
|
||||
BattleAction CStupidAI::goTowards(const BattleID & battleID, const CStack * stack, std::vector<BattleHex> hexes) const
|
||||
{
|
||||
auto reachability = cb->getReachability(stack);
|
||||
auto avHexes = cb->battleGetAvailableHexes(reachability, stack, false);
|
||||
auto reachability = cb->getBattle(battleID)->getReachability(stack);
|
||||
auto avHexes = cb->getBattle(battleID)->battleGetAvailableHexes(reachability, stack, false);
|
||||
|
||||
if(!avHexes.size() || !hexes.size()) //we are blocked or dest is blocked
|
||||
{
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "../../lib/battle/BattleHex.h"
|
||||
#include "../../lib/battle/ReachabilityInfo.h"
|
||||
#include "../../lib/CGameInterface.h"
|
||||
|
||||
class EnemyInfo;
|
||||
|
||||
@ -30,25 +31,26 @@ public:
|
||||
|
||||
void initBattleInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CBattleCallback> CB) override;
|
||||
void initBattleInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CBattleCallback> CB, AutocombatPreferences autocombatPreferences) override;
|
||||
void actionFinished(const BattleAction &action) override;//occurs AFTER every action taken by any stack or by the hero
|
||||
void actionStarted(const BattleAction &action) override;//occurs BEFORE every action taken by any stack or by the hero
|
||||
void activeStack(const CStack * stack) override; //called when it's turn of that stack
|
||||
void yourTacticPhase(int distance) override;
|
||||
|
||||
void battleAttack(const BattleAttack *ba) override; //called when stack is performing attack
|
||||
void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa, bool ranged) override; //called when stack receives damage (after battleAttack())
|
||||
void battleEnd(const BattleResult *br, QueryID queryID) override;
|
||||
void actionFinished(const BattleID & battleID, const BattleAction &action) override;//occurs AFTER every action taken by any stack or by the hero
|
||||
void actionStarted(const BattleID & battleID, const BattleAction &action) override;//occurs BEFORE every action taken by any stack or by the hero
|
||||
void activeStack(const BattleID & battleID, const CStack * stack) override; //called when it's turn of that stack
|
||||
void yourTacticPhase(const BattleID & battleID, int distance) override;
|
||||
|
||||
void battleAttack(const BattleID & battleID, const BattleAttack *ba) override; //called when stack is performing attack
|
||||
void battleStacksAttacked(const BattleID & battleID, const std::vector<BattleStackAttacked> & bsa, bool ranged) override; //called when stack receives damage (after battleAttack())
|
||||
void battleEnd(const BattleID & battleID, const BattleResult *br, QueryID queryID) override;
|
||||
//void battleResultsApplied() override; //called when all effects of last battle are applied
|
||||
void battleNewRoundFirst(int round) override; //called at the beginning of each turn before changes are applied;
|
||||
void battleNewRound(int round) override; //called at the beginning of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
|
||||
void battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance, bool teleport) override;
|
||||
void battleSpellCast(const BattleSpellCast *sc) override;
|
||||
void battleStacksEffectsSet(const SetStackEffect & sse) override;//called when a specific effect is set to stacks
|
||||
void battleNewRoundFirst(const BattleID & battleID) override; //called at the beginning of each turn before changes are applied;
|
||||
void battleNewRound(const BattleID & battleID) override; //called at the beginning of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
|
||||
void battleStackMoved(const BattleID & battleID, const CStack * stack, std::vector<BattleHex> dest, int distance, bool teleport) override;
|
||||
void battleSpellCast(const BattleID & battleID, const BattleSpellCast *sc) override;
|
||||
void battleStacksEffectsSet(const BattleID & battleID, const SetStackEffect & sse) override;//called when a specific effect is set to stacks
|
||||
//void battleTriggerEffect(const BattleTriggerEffect & bte) override;
|
||||
void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side, bool replayAllowed) override; //called by engine when battle starts; side=0 - left, side=1 - right
|
||||
void battleCatapultAttacked(const CatapultAttack & ca) override; //called when catapult makes an attack
|
||||
void battleStart(const BattleID & battleID, const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side, bool replayAllowed) override; //called by engine when battle starts; side=0 - left, side=1 - right
|
||||
void battleCatapultAttacked(const BattleID & battleID, const CatapultAttack & ca) override; //called when catapult makes an attack
|
||||
|
||||
private:
|
||||
BattleAction goTowards(const CStack * stack, std::vector<BattleHex> hexes) const;
|
||||
BattleAction goTowards(const BattleID & battleID, const CStack * stack, std::vector<BattleHex> hexes) const;
|
||||
};
|
||||
|
||||
|
@ -204,7 +204,7 @@ void VCAI::gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryL
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "victoryLossCheckResult '%s'", victoryLossCheckResult.messageToSelf.toString());
|
||||
NET_EVENT_HANDLER;
|
||||
logAi->debug("Player %d (%s): I heard that player %d (%s) %s.", playerID, playerID.getStr(), player, player.getStr(), (victoryLossCheckResult.victory() ? "won" : "lost"));
|
||||
logAi->debug("Player %d (%s): I heard that player %d (%s) %s.", playerID, playerID.toString(), player, player.toString(), (victoryLossCheckResult.victory() ? "won" : "lost"));
|
||||
if(player == playerID)
|
||||
{
|
||||
if(victoryLossCheckResult.victory())
|
||||
@ -214,7 +214,7 @@ void VCAI::gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryL
|
||||
}
|
||||
else
|
||||
{
|
||||
logAi->debug("VCAI: Player %d (%s) lost. It's me. What a disappointment! :(", player, player.getStr());
|
||||
logAi->debug("VCAI: Player %d (%s) lost. It's me. What a disappointment! :(", player, player.toString());
|
||||
}
|
||||
|
||||
finish();
|
||||
@ -475,7 +475,7 @@ void VCAI::heroCreated(const CGHeroInstance * h)
|
||||
NET_EVENT_HANDLER;
|
||||
}
|
||||
|
||||
void VCAI::advmapSpellCast(const CGHeroInstance * caster, int spellID)
|
||||
void VCAI::advmapSpellCast(const CGHeroInstance * caster, SpellID spellID)
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "spellID '%i", spellID);
|
||||
NET_EVENT_HANDLER;
|
||||
@ -600,7 +600,7 @@ void VCAI::initGameInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<C
|
||||
ah->init(CB.get());
|
||||
|
||||
NET_EVENT_HANDLER; //sets ah->rm->cb
|
||||
playerID = *myCb->getMyColor();
|
||||
playerID = *myCb->getPlayerID();
|
||||
myCb->waitTillRealize = true;
|
||||
myCb->unlockGsWhenWaiting = true;
|
||||
|
||||
@ -779,7 +779,7 @@ void VCAI::makeTurn()
|
||||
MAKING_TURN;
|
||||
|
||||
auto day = cb->getDate(Date::DAY);
|
||||
logAi->info("Player %d (%s) starting turn, day %d", playerID, playerID.getStr(), day);
|
||||
logAi->info("Player %d (%s) starting turn, day %d", playerID, playerID.toString(), day);
|
||||
|
||||
boost::shared_lock<boost::shared_mutex> gsLock(CGameState::mutex);
|
||||
setThreadName("VCAI::makeTurn");
|
||||
@ -1577,23 +1577,23 @@ void VCAI::completeGoal(Goals::TSubgoal goal)
|
||||
|
||||
}
|
||||
|
||||
void VCAI::battleStart(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side, bool replayAllowed)
|
||||
void VCAI::battleStart(const BattleID & battleID, const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side, bool replayAllowed)
|
||||
{
|
||||
NET_EVENT_HANDLER;
|
||||
assert(!playerID.isValidPlayer() || status.getBattle() == UPCOMING_BATTLE);
|
||||
status.setBattle(ONGOING_BATTLE);
|
||||
const CGObjectInstance * presumedEnemy = vstd::backOrNull(cb->getVisitableObjs(tile)); //may be nullptr in some very are cases -> eg. visited monolith and fighting with an enemy at the FoW covered exit
|
||||
battlename = boost::str(boost::format("Starting battle of %s attacking %s at %s") % (hero1 ? hero1->getNameTranslated() : "a army") % (presumedEnemy ? presumedEnemy->getObjectName() : "unknown enemy") % tile.toString());
|
||||
CAdventureAI::battleStart(army1, army2, tile, hero1, hero2, side, replayAllowed);
|
||||
CAdventureAI::battleStart(battleID, army1, army2, tile, hero1, hero2, side, replayAllowed);
|
||||
}
|
||||
|
||||
void VCAI::battleEnd(const BattleResult * br, QueryID queryID)
|
||||
void VCAI::battleEnd(const BattleID & battleID, const BattleResult * br, QueryID queryID)
|
||||
{
|
||||
NET_EVENT_HANDLER;
|
||||
assert(status.getBattle() == ONGOING_BATTLE);
|
||||
status.setBattle(ENDING_BATTLE);
|
||||
bool won = br->winner == myCb->battleGetMySide();
|
||||
logAi->debug("Player %d (%s): I %s the %s!", playerID, playerID.getStr(), (won ? "won" : "lost"), battlename);
|
||||
bool won = br->winner == myCb->getBattle(battleID)->battleGetMySide();
|
||||
logAi->debug("Player %d (%s): I %s the %s!", playerID, playerID.toString(), (won ? "won" : "lost"), battlename);
|
||||
battlename.clear();
|
||||
|
||||
if (queryID != QueryID::NONE)
|
||||
@ -1605,7 +1605,7 @@ void VCAI::battleEnd(const BattleResult * br, QueryID queryID)
|
||||
answerQuery(queryID, confirmAction);
|
||||
});
|
||||
}
|
||||
CAdventureAI::battleEnd(br, queryID);
|
||||
CAdventureAI::battleEnd(battleID, br, queryID);
|
||||
}
|
||||
|
||||
void VCAI::waitTillFree()
|
||||
@ -2288,7 +2288,7 @@ HeroPtr VCAI::primaryHero() const
|
||||
|
||||
void VCAI::endTurn()
|
||||
{
|
||||
logAi->info("Player %d (%s) ends turn", playerID, playerID.getStr());
|
||||
logAi->info("Player %d (%s) ends turn", playerID, playerID.toString());
|
||||
if(!status.haveTurn())
|
||||
{
|
||||
logAi->error("Not having turn at the end of turn???");
|
||||
@ -2300,7 +2300,7 @@ void VCAI::endTurn()
|
||||
}
|
||||
while(status.haveTurn()); //for some reasons, our request may fail -> stop requesting end of turn only after we've received a confirmation that it's over
|
||||
|
||||
logGlobal->info("Player %d (%s) ended turn", playerID, playerID.getStr());
|
||||
logGlobal->info("Player %d (%s) ended turn", playerID, playerID.toString());
|
||||
}
|
||||
|
||||
void VCAI::striveToGoal(Goals::TSubgoal basicGoal)
|
||||
@ -2894,7 +2894,7 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<BattleAction> VCAI::makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState)
|
||||
std::optional<BattleAction> VCAI::makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ public:
|
||||
void showHillFortWindow(const CGObjectInstance * object, const CGHeroInstance * visitor) override;
|
||||
void playerBonusChanged(const Bonus & bonus, bool gain) override;
|
||||
void heroCreated(const CGHeroInstance *) override;
|
||||
void advmapSpellCast(const CGHeroInstance * caster, int spellID) override;
|
||||
void advmapSpellCast(const CGHeroInstance * caster, SpellID spellID) override;
|
||||
void showInfoDialog(EInfoWindowMode type, const std::string & text, const std::vector<Component> & components, int soundID) override;
|
||||
void requestRealized(PackageApplied * pa) override;
|
||||
void receivedResource() override;
|
||||
@ -201,9 +201,9 @@ public:
|
||||
void showMarketWindow(const IMarket * market, const CGHeroInstance * visitor) override;
|
||||
void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override;
|
||||
|
||||
void battleStart(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side, bool replayAllowed) override;
|
||||
void battleEnd(const BattleResult * br, QueryID queryID) override;
|
||||
std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState) override;
|
||||
void battleStart(const BattleID & battleID, const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side, bool replayAllowed) override;
|
||||
void battleEnd(const BattleID & battleID, const BattleResult * br, QueryID queryID) override;
|
||||
std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState) override;
|
||||
|
||||
void makeTurn();
|
||||
void mainLoop();
|
||||
|
@ -168,14 +168,10 @@ bool CCallback::swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation
|
||||
* @param assembleTo If assemble is true, this represents the artifact ID of the combination
|
||||
* artifact to assemble to. Otherwise it's not used.
|
||||
*/
|
||||
bool CCallback::assembleArtifacts (const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)
|
||||
void CCallback::assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)
|
||||
{
|
||||
if (player != hero->tempOwner)
|
||||
return false;
|
||||
|
||||
AssembleArtifacts aa(hero->id, artifactSlot, assemble, assembleTo);
|
||||
sendRequest(&aa);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCallback::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap)
|
||||
@ -203,16 +199,17 @@ bool CCallback::buildBuilding(const CGTownInstance *town, BuildingID buildingID)
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBattleCallback::battleMakeSpellAction(const BattleAction & action)
|
||||
void CBattleCallback::battleMakeSpellAction(const BattleID & battleID, const BattleAction & action)
|
||||
{
|
||||
assert(action.actionType == EActionType::HERO_SPELL);
|
||||
MakeAction mca(action);
|
||||
mca.battleID = battleID;
|
||||
sendRequest(&mca);
|
||||
}
|
||||
|
||||
int CBattleCallback::sendRequest(const CPackForServer * request)
|
||||
{
|
||||
int requestID = cl->sendRequest(request, *player);
|
||||
int requestID = cl->sendRequest(request, *getPlayerID());
|
||||
if(waitTillRealize)
|
||||
{
|
||||
logGlobal->trace("We'll wait till request %d is answered.\n", requestID);
|
||||
@ -226,8 +223,7 @@ int CBattleCallback::sendRequest(const CPackForServer * request)
|
||||
|
||||
void CCallback::swapGarrisonHero( const CGTownInstance *town )
|
||||
{
|
||||
if(town->tempOwner == *player
|
||||
|| (town->garrisonHero && town->garrisonHero->tempOwner == *player ))
|
||||
if(town->tempOwner == *player || (town->garrisonHero && town->garrisonHero->tempOwner == *player ))
|
||||
{
|
||||
GarrisonHeroSwap pack(town->id);
|
||||
sendRequest(&pack);
|
||||
@ -236,7 +232,7 @@ void CCallback::swapGarrisonHero( const CGTownInstance *town )
|
||||
|
||||
void CCallback::buyArtifact(const CGHeroInstance *hero, ArtifactID aid)
|
||||
{
|
||||
if(hero->tempOwner != player) return;
|
||||
if(hero->tempOwner != *player) return;
|
||||
|
||||
BuyArtifact pack(hero->id,aid);
|
||||
sendRequest(&pack);
|
||||
@ -297,8 +293,8 @@ void CCallback::buildBoat( const IShipyard *obj )
|
||||
sendRequest(&bb);
|
||||
}
|
||||
|
||||
CCallback::CCallback(CGameState * GS, std::optional<PlayerColor> Player, CClient * C):
|
||||
CBattleCallback(Player, C)
|
||||
CCallback::CCallback(CGameState * GS, std::optional<PlayerColor> Player, CClient * C)
|
||||
: CBattleCallback(Player, C)
|
||||
{
|
||||
gs = GS;
|
||||
|
||||
@ -306,10 +302,7 @@ CCallback::CCallback(CGameState * GS, std::optional<PlayerColor> Player, CClient
|
||||
unlockGsWhenWaiting = false;
|
||||
}
|
||||
|
||||
CCallback::~CCallback()
|
||||
{
|
||||
//trivial, but required. Don`t remove.
|
||||
}
|
||||
CCallback::~CCallback() = default;
|
||||
|
||||
bool CCallback::canMoveBetween(const int3 &a, const int3 &b)
|
||||
{
|
||||
@ -322,6 +315,11 @@ std::shared_ptr<const CPathsInfo> CCallback::getPathsInfo(const CGHeroInstance *
|
||||
return cl->getPathsInfo(h);
|
||||
}
|
||||
|
||||
std::optional<PlayerColor> CCallback::getPlayerID() const
|
||||
{
|
||||
return CBattleCallback::getPlayerID();
|
||||
}
|
||||
|
||||
int3 CCallback::getGuardingCreaturePosition(int3 tile)
|
||||
{
|
||||
if (!gs->map->isInTheMap(tile))
|
||||
@ -364,36 +362,51 @@ void CCallback::unregisterBattleInterface(std::shared_ptr<IBattleEventsReceiver>
|
||||
cl->additionalBattleInts[*player] -= battleEvents;
|
||||
}
|
||||
|
||||
#if SCRIPTING_ENABLED
|
||||
scripting::Pool * CBattleCallback::getContextPool() const
|
||||
CBattleCallback::CBattleCallback(std::optional<PlayerColor> player, CClient * C):
|
||||
cl(C),
|
||||
player(player)
|
||||
{
|
||||
return cl->getGlobalContextPool();
|
||||
}
|
||||
#endif
|
||||
|
||||
CBattleCallback::CBattleCallback(std::optional<PlayerColor> Player, CClient * C)
|
||||
{
|
||||
player = Player;
|
||||
cl = C;
|
||||
}
|
||||
|
||||
void CBattleCallback::battleMakeUnitAction(const BattleAction & action)
|
||||
void CBattleCallback::battleMakeUnitAction(const BattleID & battleID, const BattleAction & action)
|
||||
{
|
||||
assert(!cl->gs->curB->tacticDistance);
|
||||
assert(!cl->gs->getBattle(battleID)->tacticDistance);
|
||||
MakeAction ma;
|
||||
ma.ba = action;
|
||||
ma.battleID = battleID;
|
||||
sendRequest(&ma);
|
||||
}
|
||||
|
||||
void CBattleCallback::battleMakeTacticAction( const BattleAction & action )
|
||||
void CBattleCallback::battleMakeTacticAction(const BattleID & battleID, const BattleAction & action )
|
||||
{
|
||||
assert(cl->gs->curB->tacticDistance);
|
||||
assert(cl->gs->getBattle(battleID)->tacticDistance);
|
||||
MakeAction ma;
|
||||
ma.ba = action;
|
||||
ma.battleID = battleID;
|
||||
sendRequest(&ma);
|
||||
}
|
||||
|
||||
std::optional<BattleAction> CBattleCallback::makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState)
|
||||
std::optional<BattleAction> CBattleCallback::makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState)
|
||||
{
|
||||
return cl->playerint[getPlayerID().value()]->makeSurrenderRetreatDecision(battleState);
|
||||
return cl->playerint[getPlayerID().value()]->makeSurrenderRetreatDecision(battleID, battleState);
|
||||
}
|
||||
|
||||
std::shared_ptr<CPlayerBattleCallback> CBattleCallback::getBattle(const BattleID & battleID)
|
||||
{
|
||||
return activeBattles.at(battleID);
|
||||
}
|
||||
|
||||
std::optional<PlayerColor> CBattleCallback::getPlayerID() const
|
||||
{
|
||||
return player;
|
||||
}
|
||||
|
||||
void CBattleCallback::onBattleStarted(const IBattleInfo * info)
|
||||
{
|
||||
activeBattles[info->getBattleID()] = std::make_shared<CPlayerBattleCallback>(info, *getPlayerID());
|
||||
}
|
||||
|
||||
void CBattleCallback::onBattleEnded(const BattleID & battleID)
|
||||
{
|
||||
activeBattles.erase(battleID);
|
||||
}
|
||||
|
45
CCallback.h
45
CCallback.h
@ -53,10 +53,13 @@ public:
|
||||
bool waitTillRealize = false; //if true, request functions will return after they are realized by server
|
||||
bool unlockGsWhenWaiting = false;//if true after sending each request, gs mutex will be unlocked so the changes can be applied; NOTICE caller must have gs mx locked prior to any call to actiob callback!
|
||||
//battle
|
||||
virtual void battleMakeSpellAction(const BattleAction & action) = 0;
|
||||
virtual void battleMakeUnitAction(const BattleAction & action) = 0;
|
||||
virtual void battleMakeTacticAction(const BattleAction & action) = 0;
|
||||
virtual std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState) = 0;
|
||||
virtual void battleMakeSpellAction(const BattleID & battleID, const BattleAction & action) = 0;
|
||||
virtual void battleMakeUnitAction(const BattleID & battleID, const BattleAction & action) = 0;
|
||||
virtual void battleMakeTacticAction(const BattleID & battleID, const BattleAction & action) = 0;
|
||||
virtual std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState) = 0;
|
||||
|
||||
virtual std::shared_ptr<CPlayerBattleCallback> getBattle(const BattleID & battleID) = 0;
|
||||
virtual std::optional<PlayerColor> getPlayerID() const = 0;
|
||||
};
|
||||
|
||||
class IGameActionCallback
|
||||
@ -86,7 +89,7 @@ public:
|
||||
virtual int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2, int val)=0;//split creatures from the first stack
|
||||
//virtual bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2)=0; //swaps artifacts between two given heroes
|
||||
virtual bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2)=0;
|
||||
virtual bool assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)=0;
|
||||
virtual void assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)=0;
|
||||
virtual void eraseArtifactByClient(const ArtifactLocation & al)=0;
|
||||
virtual bool dismissCreature(const CArmedInstance *obj, SlotID stackPos)=0;
|
||||
virtual void endTurn()=0;
|
||||
@ -108,30 +111,34 @@ public:
|
||||
virtual void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) = 0;
|
||||
};
|
||||
|
||||
class CBattleCallback : public IBattleCallback, public CPlayerBattleCallback
|
||||
class CBattleCallback : public IBattleCallback
|
||||
{
|
||||
std::map<BattleID, std::shared_ptr<CPlayerBattleCallback>> activeBattles;
|
||||
|
||||
std::optional<PlayerColor> player;
|
||||
|
||||
protected:
|
||||
int sendRequest(const CPackForServer * request); //returns requestID (that'll be matched to requestID in PackageApplied)
|
||||
CClient *cl;
|
||||
|
||||
public:
|
||||
CBattleCallback(std::optional<PlayerColor> Player, CClient * C);
|
||||
void battleMakeSpellAction(const BattleAction & action) override;//for casting spells by hero - DO NOT use it for moving active stack
|
||||
void battleMakeUnitAction(const BattleAction & action) override;
|
||||
void battleMakeTacticAction(const BattleAction & action) override; // performs tactic phase actions
|
||||
std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState) override;
|
||||
CBattleCallback(std::optional<PlayerColor> player, CClient * C);
|
||||
void battleMakeSpellAction(const BattleID & battleID, const BattleAction & action) override;//for casting spells by hero - DO NOT use it for moving active stack
|
||||
void battleMakeUnitAction(const BattleID & battleID, const BattleAction & action) override;
|
||||
void battleMakeTacticAction(const BattleID & battleID, const BattleAction & action) override; // performs tactic phase actions
|
||||
std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState) override;
|
||||
|
||||
#if SCRIPTING_ENABLED
|
||||
scripting::Pool * getContextPool() const override;
|
||||
#endif
|
||||
std::shared_ptr<CPlayerBattleCallback> getBattle(const BattleID & battleID) override;
|
||||
std::optional<PlayerColor> getPlayerID() const override;
|
||||
|
||||
void onBattleStarted(const IBattleInfo * info);
|
||||
void onBattleEnded(const BattleID & battleID);
|
||||
|
||||
friend class CCallback;
|
||||
friend class CClient;
|
||||
};
|
||||
|
||||
class CCallback : public CPlayerSpecificInfoCallback,
|
||||
public IGameActionCallback,
|
||||
public CBattleCallback
|
||||
class CCallback : public CPlayerSpecificInfoCallback, public CBattleCallback, public IGameActionCallback
|
||||
{
|
||||
public:
|
||||
CCallback(CGameState * GS, std::optional<PlayerColor> Player, CClient * C);
|
||||
@ -142,6 +149,8 @@ public:
|
||||
virtual int3 getGuardingCreaturePosition(int3 tile);
|
||||
virtual std::shared_ptr<const CPathsInfo> getPathsInfo(const CGHeroInstance * h);
|
||||
|
||||
std::optional<PlayerColor> getPlayerID() const override;
|
||||
|
||||
//Set of metrhods that allows adding more interfaces for this player that'll receive game event call-ins.
|
||||
void registerBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents);
|
||||
void unregisterBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents);
|
||||
@ -161,7 +170,7 @@ public:
|
||||
int bulkMergeStacks(ObjectInstanceID armyId, SlotID srcSlot) override;
|
||||
bool dismissHero(const CGHeroInstance * hero) override;
|
||||
bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2) override;
|
||||
bool assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) override;
|
||||
void assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) override;
|
||||
void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) override;
|
||||
void eraseArtifactByClient(const ArtifactLocation & al) override;
|
||||
bool buildBuilding(const CGTownInstance *town, BuildingID buildingID) override;
|
||||
|
@ -251,7 +251,7 @@ int main(int argc, char * argv[])
|
||||
// Some basic data validation to produce better error messages in cases of incorrect install
|
||||
auto testFile = [](std::string filename, std::string message)
|
||||
{
|
||||
if (!CResourceHandler::get()->existsResource(ResourceID(filename)))
|
||||
if (!CResourceHandler::get()->existsResource(ResourcePath(filename)))
|
||||
handleFatalError(message, false);
|
||||
};
|
||||
|
||||
@ -423,10 +423,10 @@ int main(int argc, char * argv[])
|
||||
//plays intro, ends when intro is over or button has been pressed (handles events)
|
||||
void playIntro()
|
||||
{
|
||||
if(CCS->videoh->openAndPlayVideo("3DOLOGO.SMK", 0, 1, true, true))
|
||||
if(CCS->videoh->openAndPlayVideo(VideoPath::builtin("3DOLOGO.SMK"), 0, 1, true, true))
|
||||
{
|
||||
if (CCS->videoh->openAndPlayVideo("NWCLOGO.SMK", 0, 1, true, true))
|
||||
CCS->videoh->openAndPlayVideo("H3INTRO.SMK", 0, 1, true, true);
|
||||
if (CCS->videoh->openAndPlayVideo(VideoPath::builtin("NWCLOGO.SMK"), 0, 1, true, true))
|
||||
CCS->videoh->openAndPlayVideo(VideoPath::builtin("H3INTRO.SMK"), 0, 1, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,6 +84,7 @@ set(client_SRCS
|
||||
renderSDL/CTrueTypeFont.cpp
|
||||
renderSDL/CursorHardware.cpp
|
||||
renderSDL/CursorSoftware.cpp
|
||||
renderSDL/RenderHandler.cpp
|
||||
renderSDL/SDLImage.cpp
|
||||
renderSDL/SDLImageLoader.cpp
|
||||
renderSDL/SDLRWwrapper.cpp
|
||||
@ -235,6 +236,7 @@ set(client_HEADERS
|
||||
render/IFont.h
|
||||
render/IImage.h
|
||||
render/IImageLoader.h
|
||||
render/IRenderHandler.h
|
||||
render/IScreenHandler.h
|
||||
|
||||
renderSDL/CBitmapFont.h
|
||||
@ -242,6 +244,7 @@ set(client_HEADERS
|
||||
renderSDL/CTrueTypeFont.h
|
||||
renderSDL/CursorHardware.h
|
||||
renderSDL/CursorSoftware.h
|
||||
renderSDL/RenderHandler.h
|
||||
renderSDL/SDLImage.h
|
||||
renderSDL/SDLImageLoader.h
|
||||
renderSDL/SDLRWwrapper.h
|
||||
|
@ -75,7 +75,7 @@ void CSoundHandler::onVolumeChange(const JsonNode &volumeNode)
|
||||
|
||||
CSoundHandler::CSoundHandler():
|
||||
listener(settings.listen["general"]["sound"]),
|
||||
ambientConfig(JsonNode(ResourceID("config/ambientSounds.json")))
|
||||
ambientConfig(JsonPath::builtin("config/ambientSounds.json"))
|
||||
{
|
||||
listener(std::bind(&CSoundHandler::onVolumeChange, this, _1));
|
||||
|
||||
@ -119,25 +119,25 @@ void CSoundHandler::release()
|
||||
}
|
||||
|
||||
// Allocate an SDL chunk and cache it.
|
||||
Mix_Chunk *CSoundHandler::GetSoundChunk(std::string &sound, bool cache)
|
||||
Mix_Chunk *CSoundHandler::GetSoundChunk(const AudioPath & sound, bool cache)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (cache && soundChunks.find(sound) != soundChunks.end())
|
||||
return soundChunks[sound].first;
|
||||
|
||||
auto data = CResourceHandler::get()->load(ResourceID(std::string("SOUNDS/") + sound, EResType::SOUND))->readAll();
|
||||
auto data = CResourceHandler::get()->load(sound.addPrefix("SOUNDS/"))->readAll();
|
||||
SDL_RWops *ops = SDL_RWFromMem(data.first.get(), (int)data.second);
|
||||
Mix_Chunk *chunk = Mix_LoadWAV_RW(ops, 1); // will free ops
|
||||
|
||||
if (cache)
|
||||
soundChunks.insert(std::pair<std::string, CachedChunk>(sound, std::make_pair (chunk, std::move (data.first))));
|
||||
soundChunks.insert({sound, std::make_pair (chunk, std::move (data.first))});
|
||||
|
||||
return chunk;
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
logGlobal->warn("Cannot get sound %s chunk: %s", sound, e.what());
|
||||
logGlobal->warn("Cannot get sound %s chunk: %s", sound.getOriginalName(), e.what());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@ -153,7 +153,7 @@ int CSoundHandler::ambientDistToVolume(int distance) const
|
||||
return volume * (int)ambientConfig["volume"].Integer() / 100;
|
||||
}
|
||||
|
||||
void CSoundHandler::ambientStopSound(std::string soundId)
|
||||
void CSoundHandler::ambientStopSound(const AudioPath & soundId)
|
||||
{
|
||||
stopSound(ambientChannels[soundId]);
|
||||
setChannelVolume(ambientChannels[soundId], volume);
|
||||
@ -163,13 +163,13 @@ void CSoundHandler::ambientStopSound(std::string soundId)
|
||||
int CSoundHandler::playSound(soundBase::soundID soundID, int repeats)
|
||||
{
|
||||
assert(soundID < soundBase::sound_after_last);
|
||||
auto sound = sounds[soundID];
|
||||
logGlobal->trace("Attempt to play sound %d with file name %s with cache", soundID, sound);
|
||||
auto sound = AudioPath::builtin(sounds[soundID]);
|
||||
logGlobal->trace("Attempt to play sound %d with file name %s with cache", soundID, sound.getOriginalName());
|
||||
|
||||
return playSound(sound, repeats, true);
|
||||
}
|
||||
|
||||
int CSoundHandler::playSound(std::string sound, int repeats, bool cache)
|
||||
int CSoundHandler::playSound(const AudioPath & sound, int repeats, bool cache)
|
||||
{
|
||||
if (!initialized || sound.empty())
|
||||
return -1;
|
||||
@ -182,7 +182,7 @@ int CSoundHandler::playSound(std::string sound, int repeats, bool cache)
|
||||
channel = Mix_PlayChannel(-1, chunk, repeats);
|
||||
if (channel == -1)
|
||||
{
|
||||
logGlobal->error("Unable to play sound file %s , error %s", sound, Mix_GetError());
|
||||
logGlobal->error("Unable to play sound file %s , error %s", sound.getOriginalName(), Mix_GetError());
|
||||
if (!cache)
|
||||
Mix_FreeChunk(chunk);
|
||||
}
|
||||
@ -290,14 +290,14 @@ int CSoundHandler::ambientGetRange() const
|
||||
return static_cast<int>(ambientConfig["range"].Integer());
|
||||
}
|
||||
|
||||
void CSoundHandler::ambientUpdateChannels(std::map<std::string, int> soundsArg)
|
||||
void CSoundHandler::ambientUpdateChannels(std::map<AudioPath, int> soundsArg)
|
||||
{
|
||||
boost::mutex::scoped_lock guard(mutex);
|
||||
|
||||
std::vector<std::string> stoppedSounds;
|
||||
std::vector<AudioPath> stoppedSounds;
|
||||
for(auto & pair : ambientChannels)
|
||||
{
|
||||
const std::string & soundId = pair.first;
|
||||
const auto & soundId = pair.first;
|
||||
const int channel = pair.second;
|
||||
|
||||
if(!vstd::contains(soundsArg, soundId))
|
||||
@ -320,7 +320,7 @@ void CSoundHandler::ambientUpdateChannels(std::map<std::string, int> soundsArg)
|
||||
|
||||
for(auto & pair : soundsArg)
|
||||
{
|
||||
const std::string & soundId = pair.first;
|
||||
const auto & soundId = pair.first;
|
||||
const int distance = pair.second;
|
||||
|
||||
if(!vstd::contains(ambientChannels, soundId))
|
||||
@ -357,7 +357,7 @@ CMusicHandler::CMusicHandler():
|
||||
{
|
||||
listener(std::bind(&CMusicHandler::onVolumeChange, this, _1));
|
||||
|
||||
auto mp3files = CResourceHandler::get()->getFilteredFiles([](const ResourceID & id) -> bool
|
||||
auto mp3files = CResourceHandler::get()->getFilteredFiles([](const ResourcePath & id) -> bool
|
||||
{
|
||||
if(id.getType() != EResType::SOUND)
|
||||
return false;
|
||||
@ -369,12 +369,12 @@ CMusicHandler::CMusicHandler():
|
||||
return true;
|
||||
});
|
||||
|
||||
for(const ResourceID & file : mp3files)
|
||||
for(const ResourcePath & file : mp3files)
|
||||
{
|
||||
if(boost::algorithm::istarts_with(file.getName(), "MUSIC/Combat"))
|
||||
addEntryToSet("battle", file.getName());
|
||||
addEntryToSet("battle", AudioPath::fromResource(file));
|
||||
else if(boost::algorithm::istarts_with(file.getName(), "MUSIC/AITheme"))
|
||||
addEntryToSet("enemy-turn", file.getName());
|
||||
addEntryToSet("enemy-turn", AudioPath::fromResource(file));
|
||||
}
|
||||
|
||||
}
|
||||
@ -383,11 +383,11 @@ void CMusicHandler::loadTerrainMusicThemes()
|
||||
{
|
||||
for (const auto & terrain : CGI->terrainTypeHandler->objects)
|
||||
{
|
||||
addEntryToSet("terrain_" + terrain->getJsonKey(), "Music/" + terrain->musicFilename);
|
||||
addEntryToSet("terrain_" + terrain->getJsonKey(), terrain->musicFilename);
|
||||
}
|
||||
}
|
||||
|
||||
void CMusicHandler::addEntryToSet(const std::string & set, const std::string & musicURI)
|
||||
void CMusicHandler::addEntryToSet(const std::string & set, const AudioPath & musicURI)
|
||||
{
|
||||
musicsSet[set].push_back(musicURI);
|
||||
}
|
||||
@ -421,7 +421,7 @@ void CMusicHandler::release()
|
||||
CAudioBase::release();
|
||||
}
|
||||
|
||||
void CMusicHandler::playMusic(const std::string & musicURI, bool loop, bool fromStart)
|
||||
void CMusicHandler::playMusic(const AudioPath & musicURI, bool loop, bool fromStart)
|
||||
{
|
||||
boost::mutex::scoped_lock guard(mutex);
|
||||
|
||||
@ -451,7 +451,7 @@ void CMusicHandler::playMusicFromSet(const std::string & whichSet, bool loop, bo
|
||||
return;
|
||||
|
||||
// in this mode - play random track from set
|
||||
queueNext(this, whichSet, "", loop, fromStart);
|
||||
queueNext(this, whichSet, AudioPath(), loop, fromStart);
|
||||
}
|
||||
|
||||
void CMusicHandler::queueNext(std::unique_ptr<MusicEntry> queued)
|
||||
@ -468,7 +468,7 @@ void CMusicHandler::queueNext(std::unique_ptr<MusicEntry> queued)
|
||||
}
|
||||
}
|
||||
|
||||
void CMusicHandler::queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped, bool fromStart)
|
||||
void CMusicHandler::queueNext(CMusicHandler *owner, const std::string & setName, const AudioPath & musicURI, bool looped, bool fromStart)
|
||||
{
|
||||
queueNext(std::make_unique<MusicEntry>(owner, setName, musicURI, looped, fromStart));
|
||||
}
|
||||
@ -523,7 +523,7 @@ void CMusicHandler::musicFinishedCallback()
|
||||
});
|
||||
}
|
||||
|
||||
MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped, bool fromStart):
|
||||
MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, const AudioPath & musicURI, bool looped, bool fromStart):
|
||||
owner(owner),
|
||||
music(nullptr),
|
||||
playing(false),
|
||||
@ -552,39 +552,43 @@ MusicEntry::~MusicEntry()
|
||||
Mix_HaltMusic();
|
||||
}
|
||||
|
||||
logGlobal->trace("Del-ing music file %s", currentName);
|
||||
logGlobal->trace("Del-ing music file %s", currentName.getOriginalName());
|
||||
if (music)
|
||||
Mix_FreeMusic(music);
|
||||
}
|
||||
|
||||
void MusicEntry::load(std::string musicURI)
|
||||
void MusicEntry::load(const AudioPath & musicURI)
|
||||
{
|
||||
if (music)
|
||||
{
|
||||
logGlobal->trace("Del-ing music file %s", currentName);
|
||||
logGlobal->trace("Del-ing music file %s", currentName.getOriginalName());
|
||||
Mix_FreeMusic(music);
|
||||
music = nullptr;
|
||||
}
|
||||
|
||||
currentName = musicURI;
|
||||
if (CResourceHandler::get()->existsResource(musicURI))
|
||||
currentName = musicURI;
|
||||
else
|
||||
currentName = musicURI.addPrefix("MUSIC/");
|
||||
|
||||
music = nullptr;
|
||||
|
||||
logGlobal->trace("Loading music file %s", musicURI);
|
||||
logGlobal->trace("Loading music file %s", currentName.getOriginalName());
|
||||
|
||||
try
|
||||
{
|
||||
auto musicFile = MakeSDLRWops(CResourceHandler::get()->load(ResourceID(std::move(musicURI), EResType::SOUND)));
|
||||
auto musicFile = MakeSDLRWops(CResourceHandler::get()->load(currentName));
|
||||
music = Mix_LoadMUS_RW(musicFile, SDL_TRUE);
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
logGlobal->error("Failed to load music. setName=%s\tmusicURI=%s", setName, musicURI);
|
||||
logGlobal->error("Failed to load music. setName=%s\tmusicURI=%s", setName, currentName.getOriginalName());
|
||||
logGlobal->error("Exception: %s", e.what());
|
||||
}
|
||||
|
||||
if(!music)
|
||||
{
|
||||
logGlobal->warn("Warning: Cannot open %s: %s", currentName, Mix_GetError());
|
||||
logGlobal->warn("Warning: Cannot open %s: %s", currentName.getOriginalName(), Mix_GetError());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -601,7 +605,7 @@ bool MusicEntry::play()
|
||||
load(*iter);
|
||||
}
|
||||
|
||||
logGlobal->trace("Playing music file %s", currentName);
|
||||
logGlobal->trace("Playing music file %s", currentName.getOriginalName());
|
||||
|
||||
if (!fromStart && owner->trackPositions.count(currentName) > 0 && owner->trackPositions[currentName] > 0)
|
||||
{
|
||||
@ -646,7 +650,7 @@ bool MusicEntry::stop(int fade_ms)
|
||||
assert(startTime != uint32_t(-1));
|
||||
float playDuration = (endTime - startTime + startPosition) / 1000.f;
|
||||
owner->trackPositions[currentName] = playDuration;
|
||||
logGlobal->trace("Stopping music file %s at %f", currentName, playDuration);
|
||||
logGlobal->trace("Stopping music file %s at %f", currentName.getOriginalName(), playDuration);
|
||||
|
||||
Mix_FadeOutMusic(fade_ms);
|
||||
return true;
|
||||
@ -664,7 +668,7 @@ bool MusicEntry::isSet(std::string set)
|
||||
return !setName.empty() && set == setName;
|
||||
}
|
||||
|
||||
bool MusicEntry::isTrack(std::string track)
|
||||
bool MusicEntry::isTrack(const AudioPath & track)
|
||||
{
|
||||
return setName.empty() && track == currentName;
|
||||
}
|
||||
|
@ -35,15 +35,14 @@ public:
|
||||
class CSoundHandler: public CAudioBase
|
||||
{
|
||||
private:
|
||||
//soundBase::soundID getSoundID(const std::string &fileName);
|
||||
//update volume on configuration change
|
||||
SettingsListener listener;
|
||||
void onVolumeChange(const JsonNode &volumeNode);
|
||||
|
||||
using CachedChunk = std::pair<Mix_Chunk *, std::unique_ptr<ui8[]>>;
|
||||
std::map<std::string, CachedChunk> soundChunks;
|
||||
std::map<AudioPath, CachedChunk> soundChunks;
|
||||
|
||||
Mix_Chunk *GetSoundChunk(std::string &sound, bool cache);
|
||||
Mix_Chunk *GetSoundChunk(const AudioPath & sound, bool cache);
|
||||
|
||||
/// have entry for every currently active channel
|
||||
/// vector will be empty if callback was not set
|
||||
@ -54,12 +53,12 @@ private:
|
||||
boost::mutex mutexCallbacks;
|
||||
|
||||
int ambientDistToVolume(int distance) const;
|
||||
void ambientStopSound(std::string soundId);
|
||||
void ambientStopSound(const AudioPath & soundId);
|
||||
void updateChannelVolume(int channel);
|
||||
|
||||
const JsonNode ambientConfig;
|
||||
|
||||
std::map<std::string, int> ambientChannels;
|
||||
std::map<AudioPath, int> ambientChannels;
|
||||
std::map<int, int> channelVolumes;
|
||||
|
||||
void initCallback(int channel, const std::function<void()> & function);
|
||||
@ -76,7 +75,7 @@ public:
|
||||
|
||||
// Sounds
|
||||
int playSound(soundBase::soundID soundID, int repeats=0);
|
||||
int playSound(std::string sound, int repeats=0, bool cache=false);
|
||||
int playSound(const AudioPath & sound, int repeats=0, bool cache=false);
|
||||
int playSoundFromSet(std::vector<soundBase::soundID> &sound_vec);
|
||||
void stopSound(int handler);
|
||||
|
||||
@ -84,16 +83,13 @@ public:
|
||||
void soundFinishedCallback(int channel);
|
||||
|
||||
int ambientGetRange() const;
|
||||
void ambientUpdateChannels(std::map<std::string, int> currentSounds);
|
||||
void ambientUpdateChannels(std::map<AudioPath, int> currentSounds);
|
||||
void ambientStopAllChannels();
|
||||
|
||||
// Sets
|
||||
std::vector<soundBase::soundID> battleIntroSounds;
|
||||
};
|
||||
|
||||
// Helper //now it looks somewhat useless
|
||||
#define battle_sound(creature,what_sound) creature->sounds.what_sound
|
||||
|
||||
class CMusicHandler;
|
||||
|
||||
//Class for handling one music file
|
||||
@ -109,16 +105,16 @@ class MusicEntry
|
||||
uint32_t startPosition;
|
||||
//if not null - set from which music will be randomly selected
|
||||
std::string setName;
|
||||
std::string currentName;
|
||||
AudioPath currentName;
|
||||
|
||||
void load(std::string musicURI);
|
||||
void load(const AudioPath & musicURI);
|
||||
|
||||
public:
|
||||
MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped, bool fromStart);
|
||||
MusicEntry(CMusicHandler *owner, std::string setName, const AudioPath & musicURI, bool looped, bool fromStart);
|
||||
~MusicEntry();
|
||||
|
||||
bool isSet(std::string setName);
|
||||
bool isTrack(std::string trackName);
|
||||
bool isTrack(const AudioPath & trackName);
|
||||
bool isPlaying();
|
||||
|
||||
bool play();
|
||||
@ -135,20 +131,20 @@ private:
|
||||
std::unique_ptr<MusicEntry> current;
|
||||
std::unique_ptr<MusicEntry> next;
|
||||
|
||||
void queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped, bool fromStart);
|
||||
void queueNext(CMusicHandler *owner, const std::string & setName, const AudioPath & musicURI, bool looped, bool fromStart);
|
||||
void queueNext(std::unique_ptr<MusicEntry> queued);
|
||||
void musicFinishedCallback();
|
||||
|
||||
/// map <set name> -> <list of URI's to tracks belonging to the said set>
|
||||
std::map<std::string, std::vector<std::string>> musicsSet;
|
||||
std::map<std::string, std::vector<AudioPath>> musicsSet;
|
||||
/// stored position, in seconds at which music player should resume playing this track
|
||||
std::map<std::string, float> trackPositions;
|
||||
std::map<AudioPath, float> trackPositions;
|
||||
|
||||
public:
|
||||
CMusicHandler();
|
||||
|
||||
/// add entry with URI musicURI in set. Track will have ID musicID
|
||||
void addEntryToSet(const std::string & set, const std::string & musicURI);
|
||||
void addEntryToSet(const std::string & set, const AudioPath & musicURI);
|
||||
|
||||
void init() override;
|
||||
void loadTerrainMusicThemes();
|
||||
@ -156,7 +152,7 @@ public:
|
||||
void setVolume(ui32 percent) override;
|
||||
|
||||
/// play track by URI, if loop = true music will be looped
|
||||
void playMusic(const std::string & musicURI, bool loop, bool fromStart);
|
||||
void playMusic(const AudioPath & musicURI, bool loop, bool fromStart);
|
||||
/// play random track from this set
|
||||
void playMusicFromSet(const std::string & musicSet, bool loop, bool fromStart);
|
||||
/// play random track from set (musicSet, entryID)
|
||||
|
@ -125,7 +125,7 @@ struct HeroObjectRetriever
|
||||
CPlayerInterface::CPlayerInterface(PlayerColor Player):
|
||||
localState(std::make_unique<PlayerLocalState>(*this))
|
||||
{
|
||||
logGlobal->trace("\tHuman player interface for player %s being constructed", Player.getStr());
|
||||
logGlobal->trace("\tHuman player interface for player %s being constructed", Player.toString());
|
||||
destinationTeleport = ObjectInstanceID();
|
||||
destinationTeleportPos = int3(-1);
|
||||
GH.defActionsDef = 0;
|
||||
@ -147,7 +147,7 @@ CPlayerInterface::CPlayerInterface(PlayerColor Player):
|
||||
|
||||
CPlayerInterface::~CPlayerInterface()
|
||||
{
|
||||
logGlobal->trace("\tHuman player interface for player %s being destructed", playerID.getStr());
|
||||
logGlobal->trace("\tHuman player interface for player %s being destructed", playerID.toString());
|
||||
delete showingDialog;
|
||||
delete cingconsole;
|
||||
if (LOCPLINT == this)
|
||||
@ -658,7 +658,7 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, BuildingID build
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleStartBefore(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2)
|
||||
void CPlayerInterface::battleStartBefore(const BattleID & battleID, const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2)
|
||||
{
|
||||
// when battle starts, game will send battleStart pack *before* movement confirmation
|
||||
// and since network thread wait for battle intro to play, movement confirmation will only happen after intro
|
||||
@ -670,7 +670,7 @@ void CPlayerInterface::battleStartBefore(const CCreatureSet *army1, const CCreat
|
||||
waitForAllDialogs();
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side, bool replayAllowed)
|
||||
void CPlayerInterface::battleStart(const BattleID & battleID, const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side, bool replayAllowed)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
|
||||
@ -685,7 +685,7 @@ void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet
|
||||
autocombatPreferences.enableSpellsUsage = settings["battle"]["enableAutocombatSpells"].Bool();
|
||||
|
||||
autofightingAI->initBattleInterface(env, cb, autocombatPreferences);
|
||||
autofightingAI->battleStart(army1, army2, tile, hero1, hero2, side, false);
|
||||
autofightingAI->battleStart(battleID, army1, army2, tile, hero1, hero2, side, false);
|
||||
isAutoFightOn = true;
|
||||
cb->registerBattleInterface(autofightingAI);
|
||||
}
|
||||
@ -697,7 +697,7 @@ void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleUnitsChanged(const std::vector<UnitChanges> & units)
|
||||
void CPlayerInterface::battleUnitsChanged(const BattleID & battleID, const std::vector<UnitChanges> & units)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
@ -708,7 +708,7 @@ void CPlayerInterface::battleUnitsChanged(const std::vector<UnitChanges> & units
|
||||
{
|
||||
case UnitChanges::EOperation::RESET_STATE:
|
||||
{
|
||||
const CStack * stack = cb->battleGetStackByID(info.id );
|
||||
const CStack * stack = cb->getBattle(battleID)->battleGetStackByID(info.id );
|
||||
|
||||
if(!stack)
|
||||
{
|
||||
@ -723,7 +723,7 @@ void CPlayerInterface::battleUnitsChanged(const std::vector<UnitChanges> & units
|
||||
break;
|
||||
case UnitChanges::EOperation::ADD:
|
||||
{
|
||||
const CStack * unit = cb->battleGetStackByID(info.id);
|
||||
const CStack * unit = cb->getBattle(battleID)->battleGetStackByID(info.id);
|
||||
if(!unit)
|
||||
{
|
||||
logGlobal->error("Invalid unit ID %d", info.id);
|
||||
@ -739,7 +739,7 @@ void CPlayerInterface::battleUnitsChanged(const std::vector<UnitChanges> & units
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleObstaclesChanged(const std::vector<ObstacleChanges> & obstacles)
|
||||
void CPlayerInterface::battleObstaclesChanged(const BattleID & battleID, const std::vector<ObstacleChanges> & obstacles)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
@ -751,7 +751,7 @@ void CPlayerInterface::battleObstaclesChanged(const std::vector<ObstacleChanges>
|
||||
{
|
||||
if(change.operation == BattleChanges::EOperation::ADD)
|
||||
{
|
||||
auto instance = cb->battleGetObstacleByID(change.id);
|
||||
auto instance = cb->getBattle(battleID)->battleGetObstacleByID(change.id);
|
||||
if(instance)
|
||||
newObstacles.push_back(instance);
|
||||
else
|
||||
@ -770,7 +770,7 @@ void CPlayerInterface::battleObstaclesChanged(const std::vector<ObstacleChanges>
|
||||
battleInt->fieldController->redrawBackgroundWithHexes();
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleCatapultAttacked(const CatapultAttack & ca)
|
||||
void CPlayerInterface::battleCatapultAttacked(const BattleID & battleID, const CatapultAttack & ca)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
@ -778,15 +778,15 @@ void CPlayerInterface::battleCatapultAttacked(const CatapultAttack & ca)
|
||||
battleInt->stackIsCatapulting(ca);
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleNewRound(int round) //called at the beginning of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
|
||||
void CPlayerInterface::battleNewRound(const BattleID & battleID) //called at the beginning of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
|
||||
battleInt->newRound(round);
|
||||
battleInt->newRound();
|
||||
}
|
||||
|
||||
void CPlayerInterface::actionStarted(const BattleAction &action)
|
||||
void CPlayerInterface::actionStarted(const BattleID & battleID, const BattleAction &action)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
@ -794,7 +794,7 @@ void CPlayerInterface::actionStarted(const BattleAction &action)
|
||||
battleInt->startAction(action);
|
||||
}
|
||||
|
||||
void CPlayerInterface::actionFinished(const BattleAction &action)
|
||||
void CPlayerInterface::actionFinished(const BattleID & battleID, const BattleAction &action)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
@ -802,17 +802,17 @@ void CPlayerInterface::actionFinished(const BattleAction &action)
|
||||
battleInt->endAction(action);
|
||||
}
|
||||
|
||||
void CPlayerInterface::activeStack(const CStack * stack) //called when it's turn of that stack
|
||||
void CPlayerInterface::activeStack(const BattleID & battleID, const CStack * stack) //called when it's turn of that stack
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
logGlobal->trace("Awaiting command for %s", stack->nodeName());
|
||||
|
||||
assert(!cb->battleIsFinished());
|
||||
if (cb->battleIsFinished())
|
||||
assert(!cb->getBattle(battleID)->battleIsFinished());
|
||||
if (cb->getBattle(battleID)->battleIsFinished())
|
||||
{
|
||||
logGlobal->error("Received CPlayerInterface::activeStack after battle is finished!");
|
||||
|
||||
cb->battleMakeUnitAction(BattleAction::makeDefend(stack));
|
||||
cb->battleMakeUnitAction(battleID, BattleAction::makeDefend(stack));
|
||||
return ;
|
||||
}
|
||||
|
||||
@ -823,7 +823,7 @@ void CPlayerInterface::activeStack(const CStack * stack) //called when it's turn
|
||||
//FIXME: we want client rendering to proceed while AI is making actions
|
||||
// so unlock mutex while AI is busy since this might take quite a while, especially if hero has many spells
|
||||
auto unlockPim = vstd::makeUnlockGuard(*pim);
|
||||
autofightingAI->activeStack(stack);
|
||||
autofightingAI->activeStack(battleID, stack);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -835,7 +835,7 @@ void CPlayerInterface::activeStack(const CStack * stack) //called when it's turn
|
||||
if(!battleInt)
|
||||
{
|
||||
// probably battle is finished already
|
||||
cb->battleMakeUnitAction(BattleAction::makeDefend(stack));
|
||||
cb->battleMakeUnitAction(battleID, BattleAction::makeDefend(stack));
|
||||
}
|
||||
|
||||
{
|
||||
@ -845,7 +845,7 @@ void CPlayerInterface::activeStack(const CStack * stack) //called when it's turn
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleEnd(const BattleResult *br, QueryID queryID)
|
||||
void CPlayerInterface::battleEnd(const BattleID & battleID, const BattleResult *br, QueryID queryID)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
if(isAutoFightOn || autofightingAI)
|
||||
@ -880,7 +880,7 @@ void CPlayerInterface::battleEnd(const BattleResult *br, QueryID queryID)
|
||||
battleInt->battleFinished(*br, queryID);
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleLogMessage(const std::vector<MetaString> & lines)
|
||||
void CPlayerInterface::battleLogMessage(const BattleID & battleID, const std::vector<MetaString> & lines)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
@ -888,28 +888,28 @@ void CPlayerInterface::battleLogMessage(const std::vector<MetaString> & lines)
|
||||
battleInt->displayBattleLog(lines);
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance, bool teleport)
|
||||
void CPlayerInterface::battleStackMoved(const BattleID & battleID, const CStack * stack, std::vector<BattleHex> dest, int distance, bool teleport)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
|
||||
battleInt->stackMoved(stack, dest, distance, teleport);
|
||||
}
|
||||
void CPlayerInterface::battleSpellCast( const BattleSpellCast *sc )
|
||||
void CPlayerInterface::battleSpellCast(const BattleID & battleID, const BattleSpellCast * sc)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
|
||||
battleInt->spellCast(sc);
|
||||
}
|
||||
void CPlayerInterface::battleStacksEffectsSet( const SetStackEffect & sse )
|
||||
void CPlayerInterface::battleStacksEffectsSet(const BattleID & battleID, const SetStackEffect & sse)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
|
||||
battleInt->battleStacksEffectsSet(sse);
|
||||
}
|
||||
void CPlayerInterface::battleTriggerEffect (const BattleTriggerEffect & bte)
|
||||
void CPlayerInterface::battleTriggerEffect(const BattleID & battleID, const BattleTriggerEffect & bte)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
@ -923,7 +923,7 @@ void CPlayerInterface::battleTriggerEffect (const BattleTriggerEffect & bte)
|
||||
battleInt->windowObject->heroManaPointsChanged(manaDrainedHero);
|
||||
}
|
||||
}
|
||||
void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa, bool ranged)
|
||||
void CPlayerInterface::battleStacksAttacked(const BattleID & battleID, const std::vector<BattleStackAttacked> & bsa, bool ranged)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
@ -931,8 +931,8 @@ void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacke
|
||||
std::vector<StackAttackedInfo> arg;
|
||||
for(auto & elem : bsa)
|
||||
{
|
||||
const CStack * defender = cb->battleGetStackByID(elem.stackAttacked, false);
|
||||
const CStack * attacker = cb->battleGetStackByID(elem.attackerID, false);
|
||||
const CStack * defender = cb->getBattle(battleID)->battleGetStackByID(elem.stackAttacked, false);
|
||||
const CStack * attacker = cb->getBattle(battleID)->battleGetStackByID(elem.attackerID, false);
|
||||
|
||||
assert(defender);
|
||||
|
||||
@ -955,13 +955,13 @@ void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacke
|
||||
}
|
||||
battleInt->stacksAreAttacked(arg);
|
||||
}
|
||||
void CPlayerInterface::battleAttack(const BattleAttack * ba)
|
||||
void CPlayerInterface::battleAttack(const BattleID & battleID, const BattleAttack * ba)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
|
||||
StackAttackInfo info;
|
||||
info.attacker = cb->battleGetStackByID(ba->stackAttacking);
|
||||
info.attacker = cb->getBattle(battleID)->battleGetStackByID(ba->stackAttacking);
|
||||
info.defender = nullptr;
|
||||
info.indirectAttack = ba->shot();
|
||||
info.lucky = ba->lucky();
|
||||
@ -979,11 +979,11 @@ void CPlayerInterface::battleAttack(const BattleAttack * ba)
|
||||
if(!elem.isSecondary())
|
||||
{
|
||||
assert(info.defender == nullptr);
|
||||
info.defender = cb->battleGetStackByID(elem.stackAttacked);
|
||||
info.defender = cb->getBattle(battleID)->battleGetStackByID(elem.stackAttacked);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.secondaryDefender.push_back(cb->battleGetStackByID(elem.stackAttacked));
|
||||
info.secondaryDefender.push_back(cb->getBattle(battleID)->battleGetStackByID(elem.stackAttacked));
|
||||
}
|
||||
}
|
||||
assert(info.defender != nullptr);
|
||||
@ -992,7 +992,7 @@ void CPlayerInterface::battleAttack(const BattleAttack * ba)
|
||||
battleInt->stackAttacking(info);
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleGateStateChanged(const EGateState state)
|
||||
void CPlayerInterface::battleGateStateChanged(const BattleID & battleID, const EGateState state)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
@ -1000,7 +1000,7 @@ void CPlayerInterface::battleGateStateChanged(const EGateState state)
|
||||
battleInt->gateStateChanged(state);
|
||||
}
|
||||
|
||||
void CPlayerInterface::yourTacticPhase(int distance)
|
||||
void CPlayerInterface::yourTacticPhase(const BattleID & battleID, int distance)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
}
|
||||
@ -1112,11 +1112,11 @@ void CPlayerInterface::showBlockingDialog( const std::string &text, const std::v
|
||||
for (auto & component : components)
|
||||
intComps.push_back(std::make_shared<CSelectableComponent>(component)); //will be deleted by CSelWindow::close
|
||||
|
||||
std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
|
||||
pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0));
|
||||
std::vector<std::pair<AnimationPath,CFunctionList<void()> > > pom;
|
||||
pom.push_back({ AnimationPath::builtin("IOKAY.DEF"),0});
|
||||
if (cancel)
|
||||
{
|
||||
pom.push_back(std::pair<std::string,CFunctionList<void()> >("ICANCEL.DEF",0));
|
||||
pom.push_back({AnimationPath::builtin("ICANCEL.DEF"),0});
|
||||
}
|
||||
|
||||
int charperline = 35;
|
||||
@ -1288,7 +1288,7 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer
|
||||
* into a combinational one on an artifact screen. Does not require the combination of
|
||||
* artifacts to be legal.
|
||||
*/
|
||||
void CPlayerInterface::showArtifactAssemblyDialog(const Artifact * artifact, const Artifact * assembledArtifact, CFunctionList<bool()> onYes)
|
||||
void CPlayerInterface::showArtifactAssemblyDialog(const Artifact * artifact, const Artifact * assembledArtifact, CFunctionList<void()> onYes)
|
||||
{
|
||||
std::string text = artifact->getDescriptionTranslated();
|
||||
text += "\n\n";
|
||||
@ -1657,7 +1657,7 @@ void CPlayerInterface::viewWorldMap()
|
||||
adventureInt->openWorldView();
|
||||
}
|
||||
|
||||
void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellID)
|
||||
void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, SpellID spellID)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
|
||||
@ -1667,8 +1667,7 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellI
|
||||
if(spellID == SpellID::FLY || spellID == SpellID::WATER_WALK)
|
||||
localState->erasePath(caster);
|
||||
|
||||
const spells::Spell * spell = CGI->spells()->getByIndex(spellID);
|
||||
auto castSoundPath = spell->getCastSound();
|
||||
auto castSoundPath = spellID.toSpell()->getCastSound();
|
||||
if(!castSoundPath.empty())
|
||||
CCS->soundh->playSound(castSoundPath);
|
||||
}
|
||||
@ -1705,12 +1704,12 @@ void CPlayerInterface::tryDigging(const CGHeroInstance * h)
|
||||
showInfoDialog(CGI->generaltexth->allTexts[msgToShow]);
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleNewRoundFirst( int round )
|
||||
void CPlayerInterface::battleNewRoundFirst(const BattleID & battleID)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
|
||||
battleInt->newRoundFirst(round);
|
||||
battleInt->newRoundFirst();
|
||||
}
|
||||
|
||||
void CPlayerInterface::stopMovement()
|
||||
@ -1992,22 +1991,22 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
|
||||
elem.coord = h->convertFromVisitablePos(elem.coord);
|
||||
|
||||
int soundChannel = -1;
|
||||
std::string soundName;
|
||||
AudioPath soundName;
|
||||
|
||||
auto getMovementSoundFor = [&](const CGHeroInstance * hero, int3 posPrev, int3 posNext, EPathNodeAction moveType) -> std::string
|
||||
auto getMovementSoundFor = [&](const CGHeroInstance * hero, int3 posPrev, int3 posNext, EPathNodeAction moveType) -> AudioPath
|
||||
{
|
||||
if (moveType == EPathNodeAction::TELEPORT_BATTLE || moveType == EPathNodeAction::TELEPORT_BLOCKING_VISIT || moveType == EPathNodeAction::TELEPORT_NORMAL)
|
||||
return "";
|
||||
return {};
|
||||
|
||||
if (moveType == EPathNodeAction::EMBARK || moveType == EPathNodeAction::DISEMBARK)
|
||||
return "";
|
||||
return {};
|
||||
|
||||
if (moveType == EPathNodeAction::BLOCKING_VISIT)
|
||||
return "";
|
||||
return {};
|
||||
|
||||
// flying movement sound
|
||||
if (hero->hasBonusOfType(BonusType::FLYING_MOVEMENT))
|
||||
return "HORSE10.wav";
|
||||
return AudioPath::builtin("HORSE10.wav");
|
||||
|
||||
auto prevTile = cb->getTile(h->convertToVisitablePos(posPrev));
|
||||
auto nextTile = cb->getTile(h->convertToVisitablePos(posNext));
|
||||
@ -2073,7 +2072,7 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
|
||||
|
||||
{
|
||||
// Start a new sound for the hero movement or let the existing one carry on.
|
||||
std::string newSoundName = getMovementSoundFor(h, prevCoord, nextCoord, path.nodes[i-1].action);
|
||||
AudioPath newSoundName = getMovementSoundFor(h, prevCoord, nextCoord, path.nodes[i-1].action);
|
||||
|
||||
if(newSoundName != soundName)
|
||||
{
|
||||
@ -2126,7 +2125,7 @@ void CPlayerInterface::showWorldViewEx(const std::vector<ObjectPosInfo>& objectP
|
||||
adventureInt->openWorldView(objectPositions, showTerrain );
|
||||
}
|
||||
|
||||
std::optional<BattleAction> CPlayerInterface::makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState)
|
||||
std::optional<BattleAction> CPlayerInterface::makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ protected: // Call-ins from server, should not be called directly, but only via
|
||||
void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor) override;
|
||||
void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor) override;
|
||||
void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) override;
|
||||
void advmapSpellCast(const CGHeroInstance * caster, int spellID) override; //called when a hero casts a spell
|
||||
void advmapSpellCast(const CGHeroInstance * caster, SpellID spellID) override; //called when a hero casts a spell
|
||||
void tileHidden(const std::unordered_set<int3> &pos) override; //called when given tiles become hidden under fog of war
|
||||
void tileRevealed(const std::unordered_set<int3> &pos) override; //called when fog of war disappears from given tiles
|
||||
void newObject(const CGObjectInstance * obj) override;
|
||||
@ -152,27 +152,27 @@ protected: // Call-ins from server, should not be called directly, but only via
|
||||
void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override;
|
||||
|
||||
//for battles
|
||||
void actionFinished(const BattleAction& action) override;//occurs AFTER action taken by active stack or by the hero
|
||||
void actionStarted(const BattleAction& action) override;//occurs BEFORE action taken by active stack or by the hero
|
||||
void activeStack(const CStack * stack) override; //called when it's turn of that stack
|
||||
void battleAttack(const BattleAttack *ba) override; //stack performs attack
|
||||
void battleEnd(const BattleResult *br, QueryID queryID) override; //end of battle
|
||||
void battleNewRoundFirst(int round) override; //called at the beginning of each turn before changes are applied; used for HP regen handling
|
||||
void battleNewRound(int round) override; //called at the beginning of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
|
||||
void battleLogMessage(const std::vector<MetaString> & lines) override;
|
||||
void battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance, bool teleport) override;
|
||||
void battleSpellCast(const BattleSpellCast *sc) override;
|
||||
void battleStacksEffectsSet(const SetStackEffect & sse) override; //called when a specific effect is set to stacks
|
||||
void battleTriggerEffect(const BattleTriggerEffect & bte) override; //various one-shot effect
|
||||
void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa, bool ranged) override;
|
||||
void battleStartBefore(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2) override; //called by engine just before battle starts; side=0 - left, side=1 - right
|
||||
void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side, bool replayAllowed) override; //called by engine when battle starts; side=0 - left, side=1 - right
|
||||
void battleUnitsChanged(const std::vector<UnitChanges> & units) override;
|
||||
void battleObstaclesChanged(const std::vector<ObstacleChanges> & obstacles) override;
|
||||
void battleCatapultAttacked(const CatapultAttack & ca) override; //called when catapult makes an attack
|
||||
void battleGateStateChanged(const EGateState state) override;
|
||||
void yourTacticPhase(int distance) override;
|
||||
std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState) override;
|
||||
void actionFinished(const BattleID & battleID, const BattleAction& action) override;//occurs AFTER action taken by active stack or by the hero
|
||||
void actionStarted(const BattleID & battleID, const BattleAction& action) override;//occurs BEFORE action taken by active stack or by the hero
|
||||
void activeStack(const BattleID & battleID, const CStack * stack) override; //called when it's turn of that stack
|
||||
void battleAttack(const BattleID & battleID, const BattleAttack *ba) override; //stack performs attack
|
||||
void battleEnd(const BattleID & battleID, const BattleResult *br, QueryID queryID) override; //end of battle
|
||||
void battleNewRoundFirst(const BattleID & battleID) override; //called at the beginning of each turn before changes are applied; used for HP regen handling
|
||||
void battleNewRound(const BattleID & battleID) override; //called at the beginning of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
|
||||
void battleLogMessage(const BattleID & battleID, const std::vector<MetaString> & lines) override;
|
||||
void battleStackMoved(const BattleID & battleID, const CStack * stack, std::vector<BattleHex> dest, int distance, bool teleport) override;
|
||||
void battleSpellCast(const BattleID & battleID, const BattleSpellCast *sc) override;
|
||||
void battleStacksEffectsSet(const BattleID & battleID, const SetStackEffect & sse) override; //called when a specific effect is set to stacks
|
||||
void battleTriggerEffect(const BattleID & battleID, const BattleTriggerEffect & bte) override; //various one-shot effect
|
||||
void battleStacksAttacked(const BattleID & battleID, const std::vector<BattleStackAttacked> & bsa, bool ranged) override;
|
||||
void battleStartBefore(const BattleID & battleID, const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2) override; //called by engine just before battle starts; side=0 - left, side=1 - right
|
||||
void battleStart(const BattleID & battleID, const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side, bool replayAllowed) override; //called by engine when battle starts; side=0 - left, side=1 - right
|
||||
void battleUnitsChanged(const BattleID & battleID, const std::vector<UnitChanges> & units) override;
|
||||
void battleObstaclesChanged(const BattleID & battleID, const std::vector<ObstacleChanges> & obstacles) override;
|
||||
void battleCatapultAttacked(const BattleID & battleID, const CatapultAttack & ca) override; //called when catapult makes an attack
|
||||
void battleGateStateChanged(const BattleID & battleID, const EGateState state) override;
|
||||
void yourTacticPhase(const BattleID & battleID, int distance) override;
|
||||
std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState) override;
|
||||
|
||||
public: // public interface for use by client via LOCPLINT access
|
||||
|
||||
@ -185,7 +185,7 @@ public: // public interface for use by client via LOCPLINT access
|
||||
void showShipyardDialog(const IShipyard *obj) override; //obj may be town or shipyard;
|
||||
|
||||
void showHeroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2);
|
||||
void showArtifactAssemblyDialog(const Artifact * artifact, const Artifact * assembledArtifact, CFunctionList<bool()> onYes);
|
||||
void showArtifactAssemblyDialog(const Artifact * artifact, const Artifact * assembledArtifact, CFunctionList<void()> onYes);
|
||||
void waitWhileDialog(bool unlockPim = true);
|
||||
void waitForAllDialogs(bool unlockPim = true);
|
||||
void openTownWindow(const CGTownInstance * town); //shows townscreen
|
||||
|
@ -748,7 +748,7 @@ void CServerHandler::debugStartTest(std::string filename, bool save)
|
||||
if(save)
|
||||
{
|
||||
resetStateForLobby(StartInfo::LOAD_GAME);
|
||||
mapInfo->saveInit(ResourceID(filename, EResType::SAVEGAME));
|
||||
mapInfo->saveInit(ResourcePath(filename, EResType::SAVEGAME));
|
||||
screenType = ESelectionScreen::loadGame;
|
||||
}
|
||||
else
|
||||
|
@ -70,30 +70,32 @@ CVideoPlayer::CVideoPlayer()
|
||||
, doLoop(false)
|
||||
{}
|
||||
|
||||
bool CVideoPlayer::open(std::string fname, bool scale)
|
||||
bool CVideoPlayer::open(const VideoPath & fname, bool scale)
|
||||
{
|
||||
return open(fname, true, false);
|
||||
}
|
||||
|
||||
// loop = to loop through the video
|
||||
// useOverlay = directly write to the screen.
|
||||
bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scale)
|
||||
bool CVideoPlayer::open(const VideoPath & videoToOpen, bool loop, bool useOverlay, bool scale)
|
||||
{
|
||||
close();
|
||||
|
||||
this->fname = fname;
|
||||
doLoop = loop;
|
||||
frameTime = 0;
|
||||
|
||||
ResourceID resource(std::string("Video/") + fname, EResType::VIDEO);
|
||||
if (CResourceHandler::get()->existsResource(videoToOpen))
|
||||
fname = videoToOpen;
|
||||
else
|
||||
fname = videoToOpen.addPrefix("VIDEO/");
|
||||
|
||||
if (!CResourceHandler::get()->existsResource(resource))
|
||||
if (!CResourceHandler::get()->existsResource(fname))
|
||||
{
|
||||
logGlobal->error("Error: video %s was not found", resource.getName());
|
||||
logGlobal->error("Error: video %s was not found", fname.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
data = CResourceHandler::get()->load(resource);
|
||||
data = CResourceHandler::get()->load(fname);
|
||||
|
||||
static const int BUFFER_SIZE = 4096;
|
||||
|
||||
@ -382,7 +384,8 @@ void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, boo
|
||||
|
||||
void CVideoPlayer::close()
|
||||
{
|
||||
fname.clear();
|
||||
fname = VideoPath();
|
||||
|
||||
if (sws)
|
||||
{
|
||||
sws_freeContext(sws);
|
||||
@ -467,7 +470,7 @@ bool CVideoPlayer::playVideo(int x, int y, bool stopOnKey)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CVideoPlayer::openAndPlayVideo(std::string name, int x, int y, bool stopOnKey, bool scale)
|
||||
bool CVideoPlayer::openAndPlayVideo(const VideoPath & name, int x, int y, bool stopOnKey, bool scale)
|
||||
{
|
||||
open(name, false, true, scale);
|
||||
bool ret = playVideo(x, y, stopOnKey);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../lib/Rect.h"
|
||||
#include "../lib/filesystem/ResourcePath.h"
|
||||
|
||||
struct SDL_Surface;
|
||||
struct SDL_Texture;
|
||||
@ -17,7 +18,7 @@ struct SDL_Texture;
|
||||
class IVideoPlayer
|
||||
{
|
||||
public:
|
||||
virtual bool open(std::string name, bool scale = false)=0; //true - succes
|
||||
virtual bool open(const VideoPath & name, bool scale = false)=0; //true - succes
|
||||
virtual void close()=0;
|
||||
virtual bool nextFrame()=0;
|
||||
virtual void show(int x, int y, SDL_Surface *dst, bool update = true)=0;
|
||||
@ -30,10 +31,10 @@ public:
|
||||
class IMainVideoPlayer : public IVideoPlayer
|
||||
{
|
||||
public:
|
||||
std::string fname; //name of current video file (empty if idle)
|
||||
VideoPath fname; //name of current video file (empty if idle)
|
||||
|
||||
virtual void update(int x, int y, SDL_Surface *dst, bool forceRedraw, bool update = true){}
|
||||
virtual bool openAndPlayVideo(std::string name, int x, int y, bool stopOnKey = false, bool scale = false)
|
||||
virtual bool openAndPlayVideo(const VideoPath & name, int x, int y, bool stopOnKey = false, bool scale = false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -49,7 +50,7 @@ public:
|
||||
bool nextFrame() override {return false;};
|
||||
void close() override {};
|
||||
bool wait() override {return false;};
|
||||
bool open(std::string name, bool scale = false) override {return false;};
|
||||
bool open(const VideoPath & name, bool scale = false) override {return false;};
|
||||
};
|
||||
|
||||
#ifndef DISABLE_VIDEO
|
||||
@ -85,14 +86,14 @@ class CVideoPlayer : public IMainVideoPlayer
|
||||
bool doLoop; // loop through video
|
||||
|
||||
bool playVideo(int x, int y, bool stopOnKey);
|
||||
bool open(std::string fname, bool loop, bool useOverlay = false, bool scale = false);
|
||||
bool open(const VideoPath & fname, bool loop, bool useOverlay = false, bool scale = false);
|
||||
|
||||
public:
|
||||
CVideoPlayer();
|
||||
~CVideoPlayer();
|
||||
|
||||
bool init();
|
||||
bool open(std::string fname, bool scale = false) override;
|
||||
bool open(const VideoPath & fname, bool scale = false) override;
|
||||
void close() override;
|
||||
bool nextFrame() override; // display next frame
|
||||
|
||||
@ -101,7 +102,7 @@ public:
|
||||
void update(int x, int y, SDL_Surface *dst, bool forceRedraw, bool update = true) override; //moves to next frame if appropriate, and blits it or blits only if redraw parameter is set true
|
||||
|
||||
// Opens video, calls playVideo, closes video; returns playVideo result (if whole video has been played)
|
||||
bool openAndPlayVideo(std::string name, int x, int y, bool stopOnKey = false, bool scale = false) override;
|
||||
bool openAndPlayVideo(const VideoPath & name, int x, int y, bool stopOnKey = false, bool scale = false) override;
|
||||
|
||||
//TODO:
|
||||
bool wait() override {return false;};
|
||||
|
@ -122,9 +122,9 @@ events::EventBus * CPlayerEnvironment::eventBus() const
|
||||
return cl->eventBus();//always get actual value
|
||||
}
|
||||
|
||||
const CPlayerEnvironment::BattleCb * CPlayerEnvironment::battle() const
|
||||
const CPlayerEnvironment::BattleCb * CPlayerEnvironment::battle(const BattleID & battleID) const
|
||||
{
|
||||
return mainCallback.get();
|
||||
return mainCallback->getBattle(battleID).get();
|
||||
}
|
||||
|
||||
const CPlayerEnvironment::GameCb * CPlayerEnvironment::game() const
|
||||
@ -153,9 +153,9 @@ const Services * CClient::services() const
|
||||
return VLC; //todo: this should be CGI
|
||||
}
|
||||
|
||||
const CClient::BattleCb * CClient::battle() const
|
||||
const CClient::BattleCb * CClient::battle(const BattleID & battleID) const
|
||||
{
|
||||
return this;
|
||||
return nullptr; //todo?
|
||||
}
|
||||
|
||||
const CClient::GameCb * CClient::game() const
|
||||
@ -222,7 +222,7 @@ void CClient::loadGame(CGameState * initializedGameState)
|
||||
// try to deserialize client data including sleepingHeroes
|
||||
try
|
||||
{
|
||||
boost::filesystem::path clientSaveName = *CResourceHandler::get()->getResourceName(ResourceID(CSH->si->mapname, EResType::CLIENT_SAVEGAME));
|
||||
boost::filesystem::path clientSaveName = *CResourceHandler::get()->getResourceName(ResourcePath(CSH->si->mapname, EResType::CLIENT_SAVEGAME));
|
||||
|
||||
if(clientSaveName.empty())
|
||||
throw std::runtime_error("Cannot open client part of " + CSH->si->mapname);
|
||||
@ -345,7 +345,7 @@ void CClient::serialize(BinaryDeserializer & h, const int version)
|
||||
|
||||
void CClient::save(const std::string & fname)
|
||||
{
|
||||
if(gs->curB)
|
||||
if(!gs->currentBattles.empty())
|
||||
{
|
||||
logNetwork->error("Game cannot be saved during battle!");
|
||||
return;
|
||||
@ -408,7 +408,7 @@ void CClient::initPlayerEnvironments()
|
||||
bool hasHumanPlayer = false;
|
||||
for(auto & color : allPlayers)
|
||||
{
|
||||
logNetwork->info("Preparing environment for player %s", color.getStr());
|
||||
logNetwork->info("Preparing environment for player %s", color.toString());
|
||||
playerEnvironments[color] = std::make_shared<CPlayerEnvironment>(color, this, std::make_shared<CCallback>(gs, color, this));
|
||||
|
||||
if(!hasHumanPlayer && gs->players[color].isHuman())
|
||||
@ -439,7 +439,7 @@ void CClient::initPlayerInterfaces()
|
||||
|
||||
if(!vstd::contains(playerint, color))
|
||||
{
|
||||
logNetwork->info("Preparing interface for player %s", color.getStr());
|
||||
logNetwork->info("Preparing interface for player %s", color.toString());
|
||||
if(playerInfo.second.isControlledByAI())
|
||||
{
|
||||
bool alliedToHuman = false;
|
||||
@ -448,12 +448,12 @@ void CClient::initPlayerInterfaces()
|
||||
alliedToHuman = true;
|
||||
|
||||
auto AiToGive = aiNameForPlayer(playerInfo.second, false, alliedToHuman);
|
||||
logNetwork->info("Player %s will be lead by %s", color.getStr(), AiToGive);
|
||||
logNetwork->info("Player %s will be lead by %s", color.toString(), AiToGive);
|
||||
installNewPlayerInterface(CDynLibHandler::getNewAI(AiToGive), color);
|
||||
}
|
||||
else
|
||||
{
|
||||
logNetwork->info("Player %s will be lead by human", color.getStr());
|
||||
logNetwork->info("Player %s will be lead by human", color.toString());
|
||||
installNewPlayerInterface(std::make_shared<CPlayerInterface>(color), color);
|
||||
}
|
||||
}
|
||||
@ -503,7 +503,7 @@ void CClient::installNewPlayerInterface(std::shared_ptr<CGameInterface> gameInte
|
||||
|
||||
playerint[color] = gameInterface;
|
||||
|
||||
logGlobal->trace("\tInitializing the interface for player %s", color.getStr());
|
||||
logGlobal->trace("\tInitializing the interface for player %s", color.toString());
|
||||
auto cb = std::make_shared<CCallback>(gs, color, this);
|
||||
battleCallbacks[color] = cb;
|
||||
gameInterface->initGameInterface(playerEnvironments.at(color), cb);
|
||||
@ -519,7 +519,7 @@ void CClient::installNewBattleInterface(std::shared_ptr<CBattleGameInterface> ba
|
||||
|
||||
if(needCallback)
|
||||
{
|
||||
logGlobal->trace("\tInitializing the battle interface for player %s", color.getStr());
|
||||
logGlobal->trace("\tInitializing the battle interface for player %s", color.toString());
|
||||
auto cbc = std::make_shared<CBattleCallback>(color, this);
|
||||
battleCallbacks[color] = cbc;
|
||||
battleInterface->initBattleInterface(playerEnvironments.at(color), cbc);
|
||||
@ -565,14 +565,12 @@ int CClient::sendRequest(const CPackForServer * request, PlayerColor player)
|
||||
|
||||
void CClient::battleStarted(const BattleInfo * info)
|
||||
{
|
||||
setBattle(info);
|
||||
|
||||
for(auto & battleCb : battleCallbacks)
|
||||
{
|
||||
if(vstd::contains_if(info->sides, [&](const SideInBattle& side) {return side.color == battleCb.first; })
|
||||
|| !battleCb.first.isValidPlayer())
|
||||
{
|
||||
battleCb.second->setBattle(info);
|
||||
battleCb.second->onBattleStarted(info);
|
||||
}
|
||||
}
|
||||
|
||||
@ -583,7 +581,7 @@ void CClient::battleStarted(const BattleInfo * info)
|
||||
auto callBattleStart = [&](PlayerColor color, ui8 side)
|
||||
{
|
||||
if(vstd::contains(battleints, color))
|
||||
battleints[color]->battleStart(leftSide.armyObject, rightSide.armyObject, info->tile, leftSide.hero, rightSide.hero, side, info->replayAllowed);
|
||||
battleints[color]->battleStart(info->battleID, leftSide.armyObject, rightSide.armyObject, info->tile, leftSide.hero, rightSide.hero, side, info->replayAllowed);
|
||||
};
|
||||
|
||||
callBattleStart(leftSide.color, 0);
|
||||
@ -601,11 +599,11 @@ void CClient::battleStarted(const BattleInfo * info)
|
||||
//Remove player interfaces for auto battle (quickCombat option)
|
||||
if(att && att->isAutoFightOn)
|
||||
{
|
||||
if (att->cb->battleGetTacticDist())
|
||||
if (att->cb->getBattle(info->battleID)->battleGetTacticDist())
|
||||
{
|
||||
auto side = att->cb->playerToSide(att->playerID);
|
||||
auto side = att->cb->getBattle(info->battleID)->playerToSide(att->playerID);
|
||||
auto action = BattleAction::makeEndOFTacticPhase(*side);
|
||||
att->cb->battleMakeTacticAction(action);
|
||||
att->cb->battleMakeTacticAction(info->battleID, action);
|
||||
}
|
||||
|
||||
att.reset();
|
||||
@ -617,15 +615,15 @@ void CClient::battleStarted(const BattleInfo * info)
|
||||
if(att || def)
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> un(*CPlayerInterface::pim);
|
||||
CPlayerInterface::battleInt = std::make_shared<BattleInterface>(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, att, def);
|
||||
CPlayerInterface::battleInt = std::make_shared<BattleInterface>(info->getBattleID(), leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, att, def);
|
||||
}
|
||||
else if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool())
|
||||
{
|
||||
//TODO: This certainly need improvement
|
||||
auto spectratorInt = std::dynamic_pointer_cast<CPlayerInterface>(playerint[PlayerColor::SPECTATOR]);
|
||||
spectratorInt->cb->setBattle(info);
|
||||
spectratorInt->cb->onBattleStarted(info);
|
||||
boost::unique_lock<boost::recursive_mutex> un(*CPlayerInterface::pim);
|
||||
CPlayerInterface::battleInt = std::make_shared<BattleInterface>(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, att, def, spectratorInt);
|
||||
CPlayerInterface::battleInt = std::make_shared<BattleInterface>(info->getBattleID(), leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, att, def, spectratorInt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -634,24 +632,21 @@ void CClient::battleStarted(const BattleInfo * info)
|
||||
auto tacticianColor = info->sides[info->tacticsSide].color;
|
||||
|
||||
if (vstd::contains(battleints, tacticianColor))
|
||||
battleints[tacticianColor]->yourTacticPhase(info->tacticDistance);
|
||||
battleints[tacticianColor]->yourTacticPhase(info->battleID, info->tacticDistance);
|
||||
}
|
||||
}
|
||||
|
||||
void CClient::battleFinished()
|
||||
void CClient::battleFinished(const BattleID & battleID)
|
||||
{
|
||||
for(auto & side : gs->curB->sides)
|
||||
for(auto & side : gs->getBattle(battleID)->sides)
|
||||
if(battleCallbacks.count(side.color))
|
||||
battleCallbacks[side.color]->setBattle(nullptr);
|
||||
battleCallbacks[side.color]->onBattleEnded(battleID);
|
||||
|
||||
if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool())
|
||||
battleCallbacks[PlayerColor::SPECTATOR]->setBattle(nullptr);
|
||||
|
||||
setBattle(nullptr);
|
||||
gs->curB.dellNull();
|
||||
battleCallbacks[PlayerColor::SPECTATOR]->onBattleEnded(battleID);
|
||||
}
|
||||
|
||||
void CClient::startPlayerBattleAction(PlayerColor color)
|
||||
void CClient::startPlayerBattleAction(const BattleID & battleID, PlayerColor color)
|
||||
{
|
||||
assert(vstd::contains(battleints, color));
|
||||
|
||||
@ -661,7 +656,7 @@ void CClient::startPlayerBattleAction(PlayerColor color)
|
||||
auto unlock = vstd::makeUnlockGuardIf(*CPlayerInterface::pim, !battleints[color]->human);
|
||||
|
||||
assert(vstd::contains(battleints, color));
|
||||
battleints[color]->activeStack(gs->curB->battleGetStackByID(gs->curB->activeStack, false));
|
||||
battleints[color]->activeStack(battleID, gs->getBattle(battleID)->battleGetStackByID(gs->getBattle(battleID)->activeStack, false));
|
||||
}
|
||||
}
|
||||
|
||||
@ -698,11 +693,6 @@ scripting::Pool * CClient::getGlobalContextPool() const
|
||||
{
|
||||
return clientScripts.get();
|
||||
}
|
||||
|
||||
scripting::Pool * CClient::getContextPool() const
|
||||
{
|
||||
return clientScripts.get();
|
||||
}
|
||||
#endif
|
||||
|
||||
void CClient::reinitScripting()
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <vcmi/Environment.h>
|
||||
|
||||
#include "../lib/IGameCallback.h"
|
||||
#include "../lib/battle/CBattleInfoCallback.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@ -25,6 +24,7 @@ class CGameInterface;
|
||||
class BinaryDeserializer;
|
||||
class BinarySerializer;
|
||||
class BattleAction;
|
||||
class BattleInfo;
|
||||
|
||||
template<typename T> class CApplier;
|
||||
|
||||
@ -105,12 +105,12 @@ public:
|
||||
const Services * services() const override;
|
||||
vstd::CLoggerBase * logger() const override;
|
||||
events::EventBus * eventBus() const override;
|
||||
const BattleCb * battle() const override;
|
||||
const BattleCb * battle(const BattleID & battle) const override;
|
||||
const GameCb * game() const override;
|
||||
};
|
||||
|
||||
/// Class which handles client - server logic
|
||||
class CClient : public IGameCallback, public CBattleInfoCallback, public Environment
|
||||
class CClient : public IGameCallback, public Environment
|
||||
{
|
||||
public:
|
||||
std::map<PlayerColor, std::shared_ptr<CGameInterface>> playerint;
|
||||
@ -124,7 +124,7 @@ public:
|
||||
~CClient();
|
||||
|
||||
const Services * services() const override;
|
||||
const BattleCb * battle() const override;
|
||||
const BattleCb * battle(const BattleID & battle) const override;
|
||||
const GameCb * game() const override;
|
||||
vstd::CLoggerBase * logger() const override;
|
||||
events::EventBus * eventBus() const override;
|
||||
@ -151,8 +151,8 @@ public:
|
||||
int sendRequest(const CPackForServer * request, PlayerColor player); //returns ID given to that request
|
||||
|
||||
void battleStarted(const BattleInfo * info);
|
||||
void battleFinished();
|
||||
void startPlayerBattleAction(PlayerColor color);
|
||||
void battleFinished(const BattleID & battleID);
|
||||
void startPlayerBattleAction(const BattleID & battleID, PlayerColor color);
|
||||
|
||||
void invalidatePaths();
|
||||
std::shared_ptr<const CPathsInfo> getPathsInfo(const CGHeroInstance * h);
|
||||
@ -220,7 +220,6 @@ public:
|
||||
|
||||
#if SCRIPTING_ENABLED
|
||||
scripting::Pool * getGlobalContextPool() const override;
|
||||
scripting::Pool * getContextPool() const override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "CServerHandler.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "gui/WindowHandler.h"
|
||||
#include "render/IRenderHandler.h"
|
||||
#include "../lib/NetPacks.h"
|
||||
#include "ClientNetPackVisitors.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
@ -97,7 +98,7 @@ void ClientCommandManager::handleGoSoloCommand()
|
||||
if(elem.second.human)
|
||||
{
|
||||
auto AiToGive = CSH->client->aiNameForPlayer(*CSH->client->getPlayerSettings(elem.first), false, false);
|
||||
printCommandMessage("Player " + elem.first.getStr() + " will be lead by " + AiToGive, ELogLevel::INFO);
|
||||
printCommandMessage("Player " + elem.first.toString() + " will be lead by " + AiToGive, ELogLevel::INFO);
|
||||
CSH->client->installNewPlayerInterface(CDynLibHandler::getNewAI(AiToGive), elem.first);
|
||||
}
|
||||
}
|
||||
@ -182,12 +183,12 @@ void ClientCommandManager::handleNotDialogCommand()
|
||||
void ClientCommandManager::handleConvertTextCommand()
|
||||
{
|
||||
logGlobal->info("Searching for available maps");
|
||||
std::unordered_set<ResourceID> mapList = CResourceHandler::get()->getFilteredFiles([&](const ResourceID & ident)
|
||||
std::unordered_set<ResourcePath> mapList = CResourceHandler::get()->getFilteredFiles([&](const ResourcePath & ident)
|
||||
{
|
||||
return ident.getType() == EResType::MAP;
|
||||
});
|
||||
|
||||
std::unordered_set<ResourceID> campaignList = CResourceHandler::get()->getFilteredFiles([&](const ResourceID & ident)
|
||||
std::unordered_set<ResourcePath> campaignList = CResourceHandler::get()->getFilteredFiles([&](const ResourcePath & ident)
|
||||
{
|
||||
return ident.getType() == EResType::CAMPAIGN;
|
||||
});
|
||||
@ -292,7 +293,7 @@ void ClientCommandManager::handleGetTextCommand()
|
||||
VCMIDirs::get().userExtractedPath();
|
||||
|
||||
auto list =
|
||||
CResourceHandler::get()->getFilteredFiles([](const ResourceID & ident)
|
||||
CResourceHandler::get()->getFilteredFiles([](const ResourcePath & ident)
|
||||
{
|
||||
return ident.getType() == EResType::TEXT && boost::algorithm::starts_with(ident.getName(), "DATA/");
|
||||
});
|
||||
@ -317,7 +318,7 @@ void ClientCommandManager::handleDef2bmpCommand(std::istringstream& singleWordBu
|
||||
{
|
||||
std::string URI;
|
||||
singleWordBuffer >> URI;
|
||||
std::unique_ptr<CAnimation> anim = std::make_unique<CAnimation>(URI);
|
||||
auto anim = GH.renderHandler().loadAnimation(AnimationPath::builtin(URI));
|
||||
anim->preload();
|
||||
anim->exportBitmaps(VCMIDirs::get().userExtractedPath());
|
||||
}
|
||||
@ -327,11 +328,11 @@ void ClientCommandManager::handleExtractCommand(std::istringstream& singleWordBu
|
||||
std::string URI;
|
||||
singleWordBuffer >> URI;
|
||||
|
||||
if(CResourceHandler::get()->existsResource(ResourceID(URI)))
|
||||
if(CResourceHandler::get()->existsResource(ResourcePath(URI)))
|
||||
{
|
||||
const boost::filesystem::path outPath = VCMIDirs::get().userExtractedPath() / URI;
|
||||
|
||||
auto data = CResourceHandler::get()->load(ResourceID(URI))->readAll();
|
||||
auto data = CResourceHandler::get()->load(ResourcePath(URI))->readAll();
|
||||
|
||||
boost::filesystem::create_directories(outPath.parent_path());
|
||||
std::ofstream outFile(outPath.c_str(), std::ofstream::binary);
|
||||
|
@ -95,18 +95,18 @@ void callAllInterfaces(CClient & cl, void (T::*ptr)(Args...), Args2 && ...args)
|
||||
|
||||
//calls all normal interfaces and privileged ones, playerints may be updated when iterating over it, so we need a copy
|
||||
template<typename T, typename ... Args, typename ... Args2>
|
||||
void callBattleInterfaceIfPresentForBothSides(CClient & cl, void (T::*ptr)(Args...), Args2 && ...args)
|
||||
void callBattleInterfaceIfPresentForBothSides(CClient & cl, const BattleID & battleID, void (T::*ptr)(Args...), Args2 && ...args)
|
||||
{
|
||||
assert(cl.gameState()->curB);
|
||||
assert(cl.gameState()->getBattle(battleID));
|
||||
|
||||
if (!cl.gameState()->curB)
|
||||
if (!cl.gameState()->getBattle(battleID))
|
||||
{
|
||||
logGlobal->error("Attempt to call battle interface without ongoing battle!");
|
||||
return;
|
||||
}
|
||||
|
||||
callOnlyThatBattleInterface(cl, cl.gameState()->curB->sides[0].color, ptr, std::forward<Args2>(args)...);
|
||||
callOnlyThatBattleInterface(cl, cl.gameState()->curB->sides[1].color, ptr, std::forward<Args2>(args)...);
|
||||
callOnlyThatBattleInterface(cl, cl.gameState()->getBattle(battleID)->sides[0].color, ptr, std::forward<Args2>(args)...);
|
||||
callOnlyThatBattleInterface(cl, cl.gameState()->getBattle(battleID)->sides[1].color, ptr, std::forward<Args2>(args)...);
|
||||
if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool() && LOCPLINT->battleInt)
|
||||
{
|
||||
callOnlyThatBattleInterface(cl, PlayerColor::SPECTATOR, ptr, std::forward<Args2>(args)...);
|
||||
@ -714,11 +714,11 @@ void ApplyClientNetPackVisitor::visitMapObjectSelectDialog(MapObjectSelectDialog
|
||||
void ApplyFirstClientNetPackVisitor::visitBattleStart(BattleStart & pack)
|
||||
{
|
||||
// Cannot use the usual code because curB is not set yet
|
||||
callOnlyThatBattleInterface(cl, pack.info->sides[0].color, &IBattleEventsReceiver::battleStartBefore, pack.info->sides[0].armyObject, pack.info->sides[1].armyObject,
|
||||
callOnlyThatBattleInterface(cl, pack.info->sides[0].color, &IBattleEventsReceiver::battleStartBefore, pack.battleID, pack.info->sides[0].armyObject, pack.info->sides[1].armyObject,
|
||||
pack.info->tile, pack.info->sides[0].hero, pack.info->sides[1].hero);
|
||||
callOnlyThatBattleInterface(cl, pack.info->sides[1].color, &IBattleEventsReceiver::battleStartBefore, pack.info->sides[0].armyObject, pack.info->sides[1].armyObject,
|
||||
callOnlyThatBattleInterface(cl, pack.info->sides[1].color, &IBattleEventsReceiver::battleStartBefore, pack.battleID, pack.info->sides[0].armyObject, pack.info->sides[1].armyObject,
|
||||
pack.info->tile, pack.info->sides[0].hero, pack.info->sides[1].hero);
|
||||
callOnlyThatBattleInterface(cl, PlayerColor::SPECTATOR, &IBattleEventsReceiver::battleStartBefore, pack.info->sides[0].armyObject, pack.info->sides[1].armyObject,
|
||||
callOnlyThatBattleInterface(cl, PlayerColor::SPECTATOR, &IBattleEventsReceiver::battleStartBefore, pack.battleID, pack.info->sides[0].armyObject, pack.info->sides[1].armyObject,
|
||||
pack.info->tile, pack.info->sides[0].hero, pack.info->sides[1].hero);
|
||||
}
|
||||
|
||||
@ -729,12 +729,12 @@ void ApplyClientNetPackVisitor::visitBattleStart(BattleStart & pack)
|
||||
|
||||
void ApplyFirstClientNetPackVisitor::visitBattleNextRound(BattleNextRound & pack)
|
||||
{
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleNewRoundFirst, pack.round);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleNewRoundFirst, pack.battleID);
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitBattleNextRound(BattleNextRound & pack)
|
||||
{
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleNewRound, pack.round);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleNewRound, pack.battleID);
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitBattleSetActiveStack(BattleSetActiveStack & pack)
|
||||
@ -742,56 +742,56 @@ void ApplyClientNetPackVisitor::visitBattleSetActiveStack(BattleSetActiveStack &
|
||||
if(!pack.askPlayerInterface)
|
||||
return;
|
||||
|
||||
const CStack *activated = gs.curB->battleGetStackByID(pack.stack);
|
||||
const CStack *activated = gs.getBattle(pack.battleID)->battleGetStackByID(pack.stack);
|
||||
PlayerColor playerToCall; //pack.player that will move activated stack
|
||||
if (activated->hasBonusOfType(BonusType::HYPNOTIZED))
|
||||
{
|
||||
playerToCall = (gs.curB->sides[0].color == activated->unitOwner()
|
||||
? gs.curB->sides[1].color
|
||||
: gs.curB->sides[0].color);
|
||||
playerToCall = (gs.getBattle(pack.battleID)->sides[0].color == activated->unitOwner()
|
||||
? gs.getBattle(pack.battleID)->sides[1].color
|
||||
: gs.getBattle(pack.battleID)->sides[0].color);
|
||||
}
|
||||
else
|
||||
{
|
||||
playerToCall = activated->unitOwner();
|
||||
}
|
||||
|
||||
cl.startPlayerBattleAction(playerToCall);
|
||||
cl.startPlayerBattleAction(pack.battleID, playerToCall);
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitBattleLogMessage(BattleLogMessage & pack)
|
||||
{
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleLogMessage, pack.lines);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleLogMessage, pack.battleID, pack.lines);
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitBattleTriggerEffect(BattleTriggerEffect & pack)
|
||||
{
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleTriggerEffect, pack);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleTriggerEffect, pack.battleID, pack);
|
||||
}
|
||||
|
||||
void ApplyFirstClientNetPackVisitor::visitBattleUpdateGateState(BattleUpdateGateState & pack)
|
||||
{
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleGateStateChanged, pack.state);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleGateStateChanged, pack.battleID, pack.state);
|
||||
}
|
||||
|
||||
void ApplyFirstClientNetPackVisitor::visitBattleResult(BattleResult & pack)
|
||||
{
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleEnd, &pack, pack.queryID);
|
||||
cl.battleFinished();
|
||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleEnd, pack.battleID, &pack, pack.queryID);
|
||||
cl.battleFinished(pack.battleID);
|
||||
}
|
||||
|
||||
void ApplyFirstClientNetPackVisitor::visitBattleStackMoved(BattleStackMoved & pack)
|
||||
{
|
||||
const CStack * movedStack = gs.curB->battleGetStackByID(pack.stack);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStackMoved, movedStack, pack.tilesToMove, pack.distance, pack.teleporting);
|
||||
const CStack * movedStack = gs.getBattle(pack.battleID)->battleGetStackByID(pack.stack);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleStackMoved, pack.battleID, movedStack, pack.tilesToMove, pack.distance, pack.teleporting);
|
||||
}
|
||||
|
||||
void ApplyFirstClientNetPackVisitor::visitBattleAttack(BattleAttack & pack)
|
||||
{
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleAttack, &pack);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleAttack, pack.battleID, &pack);
|
||||
|
||||
// battleStacksAttacked should be excuted before BattleAttack.applyGs() to play animation before damaging unit
|
||||
// so this has to be here instead of ApplyClientNetPackVisitor::visitBattleAttack()
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStacksAttacked, pack.bsa, pack.shot());
|
||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleStacksAttacked, pack.battleID, pack.bsa, pack.shot());
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitBattleAttack(BattleAttack & pack)
|
||||
@ -801,23 +801,23 @@ void ApplyClientNetPackVisitor::visitBattleAttack(BattleAttack & pack)
|
||||
void ApplyFirstClientNetPackVisitor::visitStartAction(StartAction & pack)
|
||||
{
|
||||
cl.currentBattleAction = std::make_unique<BattleAction>(pack.ba);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::actionStarted, pack.ba);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::actionStarted, pack.battleID, pack.ba);
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitBattleSpellCast(BattleSpellCast & pack)
|
||||
{
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleSpellCast, &pack);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleSpellCast, pack.battleID, &pack);
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitSetStackEffect(SetStackEffect & pack)
|
||||
{
|
||||
//informing about effects
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStacksEffectsSet, pack);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleStacksEffectsSet, pack.battleID, pack);
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitStacksInjured(StacksInjured & pack)
|
||||
{
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStacksAttacked, pack.stacks, false);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleStacksAttacked, pack.battleID, pack.stacks, false);
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitBattleResultsApplied(BattleResultsApplied & pack)
|
||||
@ -829,24 +829,24 @@ void ApplyClientNetPackVisitor::visitBattleResultsApplied(BattleResultsApplied &
|
||||
|
||||
void ApplyClientNetPackVisitor::visitBattleUnitsChanged(BattleUnitsChanged & pack)
|
||||
{
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleUnitsChanged, pack.changedStacks);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleUnitsChanged, pack.battleID, pack.changedStacks);
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitBattleObstaclesChanged(BattleObstaclesChanged & pack)
|
||||
{
|
||||
//inform interfaces about removed obstacles
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleObstaclesChanged, pack.changes);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleObstaclesChanged, pack.battleID, pack.changes);
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitCatapultAttack(CatapultAttack & pack)
|
||||
{
|
||||
//inform interfaces about catapult attack
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleCatapultAttacked, pack);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::battleCatapultAttacked, pack.battleID, pack);
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitEndAction(EndAction & pack)
|
||||
{
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::actionFinished, *cl.currentBattleAction);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, pack.battleID, &IBattleEventsReceiver::actionFinished, pack.battleID, *cl.currentBattleAction);
|
||||
cl.currentBattleAction.reset();
|
||||
}
|
||||
|
||||
@ -874,7 +874,7 @@ void ApplyClientNetPackVisitor::visitPlayerBlocked(PlayerBlocked & pack)
|
||||
|
||||
void ApplyClientNetPackVisitor::visitYourTurn(YourTurn & pack)
|
||||
{
|
||||
logNetwork->debug("Server gives turn to %s", pack.player.getStr());
|
||||
logNetwork->debug("Server gives turn to %s", pack.player.toString());
|
||||
|
||||
callAllInterfaces(cl, &IGameEventsReceiver::playerStartsTurn, pack.player);
|
||||
callOnlyThatInterface(cl, pack.player, &CGameInterface::yourTurn, pack.queryID);
|
||||
@ -882,12 +882,12 @@ void ApplyClientNetPackVisitor::visitYourTurn(YourTurn & pack)
|
||||
|
||||
void ApplyClientNetPackVisitor::visitTurnTimeUpdate(TurnTimeUpdate & pack)
|
||||
{
|
||||
logNetwork->debug("Server sets turn timer {turn: %d, base: %d, battle: %d, creature: %d} for %s", pack.turnTimer.turnTimer, pack.turnTimer.baseTimer, pack.turnTimer.battleTimer, pack.turnTimer.creatureTimer, pack.player.getStr());
|
||||
logNetwork->debug("Server sets turn timer {turn: %d, base: %d, battle: %d, creature: %d} for %s", pack.turnTimer.turnTimer, pack.turnTimer.baseTimer, pack.turnTimer.battleTimer, pack.turnTimer.creatureTimer, pack.player.toString());
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitPlayerMessageClient(PlayerMessageClient & pack)
|
||||
{
|
||||
logNetwork->debug("pack.player %s sends a message: %s", pack.player.getStr(), pack.text);
|
||||
logNetwork->debug("pack.player %s sends a message: %s", pack.player.toString(), pack.text);
|
||||
|
||||
std::ostringstream str;
|
||||
if(pack.player.isSpectator())
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "../mapView/MapView.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../widgets/Images.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
@ -30,7 +31,7 @@
|
||||
#include "../PlayerLocalState.h"
|
||||
|
||||
#include "../../lib/constants/StringConstants.h"
|
||||
#include "../../lib/filesystem/ResourceID.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
|
||||
AdventureMapWidget::AdventureMapWidget( std::shared_ptr<AdventureMapShortcuts> shortcuts )
|
||||
: shortcuts(shortcuts)
|
||||
@ -56,13 +57,10 @@ AdventureMapWidget::AdventureMapWidget( std::shared_ptr<AdventureMapShortcuts> s
|
||||
for (const auto & entry : shortcuts->getShortcuts())
|
||||
addShortcut(entry.shortcut, entry.callback);
|
||||
|
||||
const JsonNode config(ResourceID("config/widgets/adventureMap.json"));
|
||||
const JsonNode config(JsonPath::builtin("config/widgets/adventureMap.json"));
|
||||
|
||||
for(const auto & entry : config["options"]["imagesPlayerColored"].Vector())
|
||||
{
|
||||
ResourceID resourceName(entry.String(), EResType::IMAGE);
|
||||
playerColorerImages.push_back(resourceName.getName());
|
||||
}
|
||||
playerColorerImages.push_back(ImagePath::fromJson(entry));
|
||||
|
||||
build(config);
|
||||
addUsedEvents(KEYBOARD);
|
||||
@ -127,24 +125,24 @@ Rect AdventureMapWidget::readArea(const JsonNode & source, const Rect & bounding
|
||||
return Rect(topLeft + boundingBox.topLeft(), dimensions);
|
||||
}
|
||||
|
||||
std::shared_ptr<IImage> AdventureMapWidget::loadImage(const std::string & name)
|
||||
std::shared_ptr<IImage> AdventureMapWidget::loadImage(const JsonNode & name)
|
||||
{
|
||||
ResourceID resource(name, EResType::IMAGE);
|
||||
ImagePath resource = ImagePath::fromJson(name);
|
||||
|
||||
if(images.count(resource.getName()) == 0)
|
||||
images[resource.getName()] = IImage::createFromFile(resource.getName());
|
||||
if(images.count(resource) == 0)
|
||||
images[resource] = GH.renderHandler().loadImage(resource);
|
||||
|
||||
return images[resource.getName()];
|
||||
return images[resource];
|
||||
}
|
||||
|
||||
std::shared_ptr<CAnimation> AdventureMapWidget::loadAnimation(const std::string & name)
|
||||
std::shared_ptr<CAnimation> AdventureMapWidget::loadAnimation(const JsonNode & name)
|
||||
{
|
||||
ResourceID resource(name, EResType::ANIMATION);
|
||||
AnimationPath resource = AnimationPath::fromJson(name);
|
||||
|
||||
if(animations.count(resource.getName()) == 0)
|
||||
animations[resource.getName()] = std::make_shared<CAnimation>(resource.getName());
|
||||
if(animations.count(resource) == 0)
|
||||
animations[resource] = GH.renderHandler().loadAnimation(resource);
|
||||
|
||||
return animations[resource.getName()];
|
||||
return animations[resource];
|
||||
}
|
||||
|
||||
std::shared_ptr<CIntObject> AdventureMapWidget::buildInfobox(const JsonNode & input)
|
||||
@ -158,15 +156,14 @@ std::shared_ptr<CIntObject> AdventureMapWidget::buildMapImage(const JsonNode & i
|
||||
{
|
||||
Rect targetArea = readTargetArea(input["area"]);
|
||||
Rect sourceArea = readSourceArea(input["sourceArea"], input["area"]);
|
||||
std::string image = input["image"].String();
|
||||
|
||||
return std::make_shared<CFilledTexture>(loadImage(image), targetArea, sourceArea);
|
||||
return std::make_shared<CFilledTexture>(loadImage(input["image"]), targetArea, sourceArea);
|
||||
}
|
||||
|
||||
std::shared_ptr<CIntObject> AdventureMapWidget::buildMapButton(const JsonNode & input)
|
||||
{
|
||||
auto position = readTargetArea(input["area"]);
|
||||
auto image = input["image"].String();
|
||||
auto image = AnimationPath::fromJson(input["image"]);
|
||||
auto help = readHintText(input["help"]);
|
||||
bool playerColored = input["playerColored"].Bool();
|
||||
|
||||
@ -259,9 +256,8 @@ std::shared_ptr<CIntObject> AdventureMapWidget::buildMapIcon(const JsonNode & in
|
||||
Rect area = readTargetArea(input["area"]);
|
||||
size_t index = input["index"].Integer();
|
||||
size_t perPlayer = input["perPlayer"].Integer();
|
||||
std::string image = input["image"].String();
|
||||
|
||||
return std::make_shared<CAdventureMapIcon>(area.topLeft(), loadAnimation(image), index, perPlayer);
|
||||
return std::make_shared<CAdventureMapIcon>(area.topLeft(), loadAnimation(input["image"]), index, perPlayer);
|
||||
}
|
||||
|
||||
std::shared_ptr<CIntObject> AdventureMapWidget::buildMapTownList(const JsonNode & input)
|
||||
@ -298,7 +294,7 @@ std::shared_ptr<CIntObject> AdventureMapWidget::buildMinimap(const JsonNode & in
|
||||
std::shared_ptr<CIntObject> AdventureMapWidget::buildResourceDateBar(const JsonNode & input)
|
||||
{
|
||||
Rect area = readTargetArea(input["area"]);
|
||||
std::string image = input["image"].String();
|
||||
auto image = ImagePath::fromJson(input["image"]);
|
||||
|
||||
auto result = std::make_shared<CResDataBar>(image, area.topLeft());
|
||||
|
||||
@ -320,7 +316,7 @@ std::shared_ptr<CIntObject> AdventureMapWidget::buildResourceDateBar(const JsonN
|
||||
std::shared_ptr<CIntObject> AdventureMapWidget::buildStatusBar(const JsonNode & input)
|
||||
{
|
||||
Rect area = readTargetArea(input["area"]);
|
||||
std::string image = input["image"].String();
|
||||
auto image = ImagePath::fromJson(input["image"]);
|
||||
|
||||
auto background = std::make_shared<CFilledTexture>(image, area);
|
||||
|
||||
@ -330,7 +326,7 @@ std::shared_ptr<CIntObject> AdventureMapWidget::buildStatusBar(const JsonNode &
|
||||
std::shared_ptr<CIntObject> AdventureMapWidget::buildTexturePlayerColored(const JsonNode & input)
|
||||
{
|
||||
logGlobal->debug("Building widget CFilledTexture");
|
||||
auto image = input["image"].String();
|
||||
auto image = ImagePath::fromJson(input["image"]);
|
||||
Rect area = readTargetArea(input["area"]);
|
||||
return std::make_shared<FilledTexturePlayerColored>(image, area);
|
||||
}
|
||||
|
@ -29,11 +29,11 @@ class AdventureMapWidget : public InterfaceObjectConfigurable
|
||||
std::vector<Rect> subwidgetSizes;
|
||||
|
||||
/// list of images on which player-colored palette will be applied
|
||||
std::vector<std::string> playerColorerImages;
|
||||
std::vector<ImagePath> playerColorerImages;
|
||||
|
||||
/// list of named images shared between widgets
|
||||
std::map<std::string, std::shared_ptr<IImage>> images;
|
||||
std::map<std::string, std::shared_ptr<CAnimation>> animations;
|
||||
std::map<ImagePath, std::shared_ptr<IImage>> images;
|
||||
std::map<AnimationPath, std::shared_ptr<CAnimation>> animations;
|
||||
|
||||
/// Widgets that require access from adventure map
|
||||
std::shared_ptr<CHeroList> heroList;
|
||||
@ -48,8 +48,8 @@ class AdventureMapWidget : public InterfaceObjectConfigurable
|
||||
Rect readSourceArea(const JsonNode & source, const JsonNode & sourceCommon);
|
||||
Rect readArea(const JsonNode & source, const Rect & boundingBox);
|
||||
|
||||
std::shared_ptr<IImage> loadImage(const std::string & name);
|
||||
std::shared_ptr<CAnimation> loadAnimation(const std::string & name);
|
||||
std::shared_ptr<IImage> loadImage(const JsonNode & name);
|
||||
std::shared_ptr<CAnimation> loadAnimation(const JsonNode & name);
|
||||
|
||||
std::shared_ptr<CIntObject> buildInfobox(const JsonNode & input);
|
||||
std::shared_ptr<CIntObject> buildMapImage(const JsonNode & input);
|
||||
|
@ -25,22 +25,22 @@
|
||||
#include "../../lib/StartInfo.h"
|
||||
|
||||
AdventureOptions::AdventureOptions()
|
||||
: CWindowObject(PLAYER_COLORED, "ADVOPTS")
|
||||
: CWindowObject(PLAYER_COLORED, ImagePath::builtin("ADVOPTS"))
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
|
||||
viewWorld = std::make_shared<CButton>(Point(24, 23), "ADVVIEW.DEF", CButton::tooltip(), [&](){ close(); }, EShortcut::ADVENTURE_VIEW_WORLD);
|
||||
viewWorld = std::make_shared<CButton>(Point(24, 23), AnimationPath::builtin("ADVVIEW.DEF"), CButton::tooltip(), [&](){ close(); }, EShortcut::ADVENTURE_VIEW_WORLD);
|
||||
viewWorld->addCallback( [] { LOCPLINT->viewWorldMap(); });
|
||||
|
||||
exit = std::make_shared<CButton>(Point(204, 313), "IOK6432.DEF", CButton::tooltip(), std::bind(&AdventureOptions::close, this), EShortcut::GLOBAL_RETURN);
|
||||
exit = std::make_shared<CButton>(Point(204, 313), AnimationPath::builtin("IOK6432.DEF"), CButton::tooltip(), std::bind(&AdventureOptions::close, this), EShortcut::GLOBAL_RETURN);
|
||||
|
||||
scenInfo = std::make_shared<CButton>(Point(24, 198), "ADVINFO.DEF", CButton::tooltip(), [&](){ close(); }, EShortcut::ADVENTURE_VIEW_SCENARIO);
|
||||
scenInfo = std::make_shared<CButton>(Point(24, 198), AnimationPath::builtin("ADVINFO.DEF"), CButton::tooltip(), [&](){ close(); }, EShortcut::ADVENTURE_VIEW_SCENARIO);
|
||||
scenInfo->addCallback(AdventureOptions::showScenarioInfo);
|
||||
|
||||
puzzle = std::make_shared<CButton>(Point(24, 81), "ADVPUZ.DEF", CButton::tooltip(), [&](){ close(); }, EShortcut::ADVENTURE_VIEW_PUZZLE);
|
||||
puzzle = std::make_shared<CButton>(Point(24, 81), AnimationPath::builtin("ADVPUZ.DEF"), CButton::tooltip(), [&](){ close(); }, EShortcut::ADVENTURE_VIEW_PUZZLE);
|
||||
puzzle->addCallback(std::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT));
|
||||
|
||||
dig = std::make_shared<CButton>(Point(24, 139), "ADVDIG.DEF", CButton::tooltip(), [&](){ close(); }, EShortcut::ADVENTURE_DIG_GRAIL);
|
||||
dig = std::make_shared<CButton>(Point(24, 139), AnimationPath::builtin("ADVDIG.DEF"), CButton::tooltip(), [&](){ close(); }, EShortcut::ADVENTURE_DIG_GRAIL);
|
||||
if(const CGHeroInstance *h = LOCPLINT->localState->getCurrentHero())
|
||||
dig->addCallback(std::bind(&CPlayerInterface::tryDigging, LOCPLINT, h));
|
||||
else
|
||||
|
@ -105,7 +105,7 @@ void CInGameConsole::print(const std::string & txt)
|
||||
}
|
||||
|
||||
GH.windows().totalRedraw(); // FIXME: ingame console has no parent widget set
|
||||
CCS->soundh->playSound("CHAT");
|
||||
CCS->soundh->playSound(AudioPath::builtin("CHAT"));
|
||||
}
|
||||
|
||||
bool CInGameConsole::captureThisKey(EShortcut key)
|
||||
|
@ -51,7 +51,7 @@ CInfoBar::EmptyVisibleInfo::EmptyVisibleInfo()
|
||||
CInfoBar::VisibleHeroInfo::VisibleHeroInfo(const CGHeroInstance * hero)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
background = std::make_shared<CPicture>("ADSTATHR");
|
||||
background = std::make_shared<CPicture>(ImagePath::builtin("ADSTATHR"));
|
||||
|
||||
if(settings["gameTweaks"]["infoBarCreatureManagement"].Bool())
|
||||
heroTooltip = std::make_shared<CInteractableHeroTooltip>(Point(0,0), hero);
|
||||
@ -62,7 +62,7 @@ CInfoBar::VisibleHeroInfo::VisibleHeroInfo(const CGHeroInstance * hero)
|
||||
CInfoBar::VisibleTownInfo::VisibleTownInfo(const CGTownInstance * town)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
background = std::make_shared<CPicture>("ADSTATCS");
|
||||
background = std::make_shared<CPicture>(ImagePath::builtin("ADSTATCS"));
|
||||
|
||||
if(settings["gameTweaks"]["infoBarCreatureManagement"].Bool())
|
||||
townTooltip = std::make_shared<CInteractableTownTooltip>(Point(0,0), town);
|
||||
@ -88,36 +88,36 @@ CInfoBar::VisibleDateInfo::VisibleDateInfo()
|
||||
forceRefresh.push_back(label);
|
||||
}
|
||||
|
||||
std::string CInfoBar::VisibleDateInfo::getNewDayName()
|
||||
AnimationPath CInfoBar::VisibleDateInfo::getNewDayName()
|
||||
{
|
||||
if(LOCPLINT->cb->getDate(Date::DAY) == 1)
|
||||
return "NEWDAY";
|
||||
return AnimationPath::builtin("NEWDAY");
|
||||
|
||||
if(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK) != 1)
|
||||
return "NEWDAY";
|
||||
return AnimationPath::builtin("NEWDAY");
|
||||
|
||||
switch(LOCPLINT->cb->getDate(Date::WEEK))
|
||||
{
|
||||
case 1:
|
||||
return "NEWWEEK1";
|
||||
return AnimationPath::builtin("NEWWEEK1");
|
||||
case 2:
|
||||
return "NEWWEEK2";
|
||||
return AnimationPath::builtin("NEWWEEK2");
|
||||
case 3:
|
||||
return "NEWWEEK3";
|
||||
return AnimationPath::builtin("NEWWEEK3");
|
||||
case 4:
|
||||
return "NEWWEEK4";
|
||||
return AnimationPath::builtin("NEWWEEK4");
|
||||
default:
|
||||
return "";
|
||||
return AnimationPath();
|
||||
}
|
||||
}
|
||||
|
||||
CInfoBar::VisibleEnemyTurnInfo::VisibleEnemyTurnInfo(PlayerColor player)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
background = std::make_shared<CPicture>("ADSTATNX");
|
||||
banner = std::make_shared<CAnimImage>("CREST58", player.getNum(), 0, 20, 51);
|
||||
sand = std::make_shared<CShowableAnim>(99, 51, "HOURSAND", 0, 100); // H3 uses around 100 ms per frame
|
||||
glass = std::make_shared<CShowableAnim>(99, 51, "HOURGLAS", CShowableAnim::PLAY_ONCE, 1000); // H3 scales this nicely for AI turn duration, don't have anything like that in vcmi
|
||||
background = std::make_shared<CPicture>(ImagePath::builtin("ADSTATNX"));
|
||||
banner = std::make_shared<CAnimImage>(AnimationPath::builtin("CREST58"), player.getNum(), 0, 20, 51);
|
||||
sand = std::make_shared<CShowableAnim>(99, 51, AnimationPath::builtin("HOURSAND"), 0, 100); // H3 uses around 100 ms per frame
|
||||
glass = std::make_shared<CShowableAnim>(99, 51, AnimationPath::builtin("HOURGLAS"), CShowableAnim::PLAY_ONCE, 1000); // H3 scales this nicely for AI turn duration, don't have anything like that in vcmi
|
||||
}
|
||||
|
||||
CInfoBar::VisibleGameStatusInfo::VisibleGameStatusInfo()
|
||||
@ -148,14 +148,14 @@ CInfoBar::VisibleGameStatusInfo::VisibleGameStatusInfo()
|
||||
}
|
||||
|
||||
//generate widgets
|
||||
background = std::make_shared<CPicture>("ADSTATIN");
|
||||
background = std::make_shared<CPicture>(ImagePath::builtin("ADSTATIN"));
|
||||
allyLabel = std::make_shared<CLabel>(10, 106, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[390] + ":");
|
||||
enemyLabel = std::make_shared<CLabel>(10, 136, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[391] + ":");
|
||||
|
||||
int posx = allyLabel->pos.w + allyLabel->pos.x - pos.x + 4;
|
||||
for(PlayerColor & player : allies)
|
||||
{
|
||||
auto image = std::make_shared<CAnimImage>("ITGFLAGS", player.getNum(), 0, posx, 102);
|
||||
auto image = std::make_shared<CAnimImage>(AnimationPath::builtin("ITGFLAGS"), player.getNum(), 0, posx, 102);
|
||||
posx += image->pos.w;
|
||||
flags.push_back(image);
|
||||
}
|
||||
@ -163,14 +163,14 @@ CInfoBar::VisibleGameStatusInfo::VisibleGameStatusInfo()
|
||||
posx = enemyLabel->pos.w + enemyLabel->pos.x - pos.x + 4;
|
||||
for(PlayerColor & player : enemies)
|
||||
{
|
||||
auto image = std::make_shared<CAnimImage>("ITGFLAGS", player.getNum(), 0, posx, 132);
|
||||
auto image = std::make_shared<CAnimImage>(AnimationPath::builtin("ITGFLAGS"), player.getNum(), 0, posx, 132);
|
||||
posx += image->pos.w;
|
||||
flags.push_back(image);
|
||||
}
|
||||
|
||||
for(size_t i=0; i<halls.size(); i++)
|
||||
{
|
||||
hallIcons.push_back(std::make_shared<CAnimImage>("itmtl", i, 0, 6 + 42 * (int)i , 11));
|
||||
hallIcons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("itmtl"), i, 0, 6 + 42 * (int)i , 11));
|
||||
if(halls[i])
|
||||
hallLabels.push_back(std::make_shared<CLabel>( 26 + 42 * (int)i, 64, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, std::to_string(halls[i])));
|
||||
}
|
||||
@ -180,7 +180,7 @@ CInfoBar::VisibleComponentInfo::VisibleComponentInfo(const std::vector<Component
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
|
||||
background = std::make_shared<CPicture>("ADSTATOT", 1, 0);
|
||||
background = std::make_shared<CPicture>(ImagePath::builtin("ADSTATOT"), 1, 0);
|
||||
auto fullRect = Rect(CInfoBar::offset, CInfoBar::offset, data_width - 2 * CInfoBar::offset, data_height - 2 * CInfoBar::offset);
|
||||
auto textRect = fullRect;
|
||||
auto imageRect = fullRect;
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
#include "CConfigHandler.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@ -86,7 +87,7 @@ private:
|
||||
std::shared_ptr<CShowableAnim> animation;
|
||||
std::shared_ptr<CLabel> label;
|
||||
|
||||
std::string getNewDayName();
|
||||
AnimationPath getNewDayName();
|
||||
public:
|
||||
VisibleDateInfo();
|
||||
};
|
||||
|
@ -206,9 +206,9 @@ void CList::selectPrev()
|
||||
CHeroList::CEmptyHeroItem::CEmptyHeroItem()
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
movement = std::make_shared<CAnimImage>("IMOBIL", 0, 0, 0, 1);
|
||||
portrait = std::make_shared<CPicture>("HPSXXX", movement->pos.w + 1, 0);
|
||||
mana = std::make_shared<CAnimImage>("IMANA", 0, 0, movement->pos.w + portrait->pos.w + 2, 1 );
|
||||
movement = std::make_shared<CAnimImage>(AnimationPath::builtin("IMOBIL"), 0, 0, 0, 1);
|
||||
portrait = std::make_shared<CPicture>(ImagePath::builtin("HPSXXX"), movement->pos.w + 1, 0);
|
||||
mana = std::make_shared<CAnimImage>(AnimationPath::builtin("IMANA"), 0, 0, movement->pos.w + portrait->pos.w + 2, 1 );
|
||||
|
||||
pos.w = mana->pos.w + mana->pos.x - pos.x;
|
||||
pos.h = std::max(std::max<int>(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
|
||||
@ -219,9 +219,9 @@ CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero)
|
||||
hero(Hero)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
movement = std::make_shared<CAnimImage>("IMOBIL", 0, 0, 0, 1);
|
||||
portrait = std::make_shared<CAnimImage>("PortraitsSmall", hero->portrait, 0, movement->pos.w + 1);
|
||||
mana = std::make_shared<CAnimImage>("IMANA", 0, 0, movement->pos.w + portrait->pos.w + 2, 1);
|
||||
movement = std::make_shared<CAnimImage>(AnimationPath::builtin("IMOBIL"), 0, 0, 0, 1);
|
||||
portrait = std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsSmall"), hero->portrait, 0, movement->pos.w + 1);
|
||||
mana = std::make_shared<CAnimImage>(AnimationPath::builtin("IMANA"), 0, 0, movement->pos.w + portrait->pos.w + 2, 1);
|
||||
|
||||
pos.w = mana->pos.w + mana->pos.x - pos.x;
|
||||
pos.h = std::max(std::max<int>(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
|
||||
@ -238,7 +238,7 @@ void CHeroList::CHeroItem::update()
|
||||
|
||||
std::shared_ptr<CIntObject> CHeroList::CHeroItem::genSelection()
|
||||
{
|
||||
return std::make_shared<CPicture>("HPSYYY", movement->pos.w + 1, 0);
|
||||
return std::make_shared<CPicture>(ImagePath::builtin("HPSYYY"), movement->pos.w + 1, 0);
|
||||
}
|
||||
|
||||
void CHeroList::CHeroItem::select(bool on)
|
||||
@ -319,7 +319,7 @@ std::shared_ptr<CIntObject> CTownList::createItem(size_t index)
|
||||
{
|
||||
if (LOCPLINT->localState->getOwnedTowns().size() > index)
|
||||
return std::make_shared<CTownItem>(this, LOCPLINT->localState->getOwnedTown(index));
|
||||
return std::make_shared<CAnimImage>("ITPA", 0);
|
||||
return std::make_shared<CAnimImage>(AnimationPath::builtin("ITPA"), 0);
|
||||
}
|
||||
|
||||
CTownList::CTownItem::CTownItem(CTownList *parent, const CGTownInstance *Town):
|
||||
@ -327,14 +327,14 @@ CTownList::CTownItem::CTownItem(CTownList *parent, const CGTownInstance *Town):
|
||||
town(Town)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
picture = std::make_shared<CAnimImage>("ITPA", 0);
|
||||
picture = std::make_shared<CAnimImage>(AnimationPath::builtin("ITPA"), 0);
|
||||
pos = picture->pos;
|
||||
update();
|
||||
}
|
||||
|
||||
std::shared_ptr<CIntObject> CTownList::CTownItem::genSelection()
|
||||
{
|
||||
return std::make_shared<CAnimImage>("ITPA", 1);
|
||||
return std::make_shared<CAnimImage>(AnimationPath::builtin("ITPA"), 1);
|
||||
}
|
||||
|
||||
void CTownList::CTownItem::update()
|
||||
|
@ -94,7 +94,7 @@ CMinimap::CMinimap(const Rect & position)
|
||||
pos.w = position.w;
|
||||
pos.h = position.h;
|
||||
|
||||
aiShield = std::make_shared<CPicture>("AIShield");
|
||||
aiShield = std::make_shared<CPicture>(ImagePath::builtin("AIShield"));
|
||||
aiShield->disable();
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/ResourceSet.h"
|
||||
|
||||
CResDataBar::CResDataBar(const std::string & imageName, const Point & position)
|
||||
CResDataBar::CResDataBar(const ImagePath & imageName, const Point & position)
|
||||
{
|
||||
pos.x += position.x;
|
||||
pos.y += position.y;
|
||||
@ -37,7 +37,7 @@ CResDataBar::CResDataBar(const std::string & imageName, const Point & position)
|
||||
pos.h = background->pos.h;
|
||||
}
|
||||
|
||||
CResDataBar::CResDataBar(const std::string & defname, int x, int y, int offx, int offy, int resdist, int datedist):
|
||||
CResDataBar::CResDataBar(const ImagePath & defname, int x, int y, int offx, int offy, int resdist, int datedist):
|
||||
CResDataBar(defname, Point(x,y))
|
||||
{
|
||||
for (int i = 0; i < 7 ; i++)
|
||||
|
@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
|
||||
/// Resources bar which shows information about how many gold, crystals,... you have
|
||||
/// Current date is displayed too
|
||||
@ -25,10 +26,10 @@ class CResDataBar : public CIntObject
|
||||
public:
|
||||
|
||||
/// For dynamically-sized UI windows, e.g. adventure map interface
|
||||
CResDataBar(const std::string & imageName, const Point & position);
|
||||
CResDataBar(const ImagePath & imageName, const Point & position);
|
||||
|
||||
/// For fixed-size UI windows, e.g. CastleInterface
|
||||
CResDataBar(const std::string &defname, int x, int y, int offx, int offy, int resdist, int datedist);
|
||||
CResDataBar(const ImagePath & defname, int x, int y, int offx, int offy, int resdist, int datedist);
|
||||
|
||||
void setDatePosition(const Point & position);
|
||||
void setResourcePosition(const GameResID & resource, const Point & position);
|
||||
|
@ -123,9 +123,9 @@ void MapAudioPlayer::removeObject(const CGObjectInstance * obj)
|
||||
vstd::erase(objects[z][x][y], obj->id);
|
||||
}
|
||||
|
||||
std::vector<std::string> MapAudioPlayer::getAmbientSounds(const int3 & tile)
|
||||
std::vector<AudioPath> MapAudioPlayer::getAmbientSounds(const int3 & tile)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
std::vector<AudioPath> result;
|
||||
|
||||
for(auto & objectID : objects[tile.z][tile.x][tile.y])
|
||||
{
|
||||
@ -140,15 +140,15 @@ std::vector<std::string> MapAudioPlayer::getAmbientSounds(const int3 & tile)
|
||||
}
|
||||
|
||||
if(CGI->mh->getMap()->isCoastalTile(tile))
|
||||
result.emplace_back("LOOPOCEA");
|
||||
result.emplace_back(AudioPath::builtin("LOOPOCEA"));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void MapAudioPlayer::updateAmbientSounds()
|
||||
{
|
||||
std::map<std::string, int> currentSounds;
|
||||
auto updateSounds = [&](const std::string& soundId, int distance) -> void
|
||||
std::map<AudioPath, int> currentSounds;
|
||||
auto updateSounds = [&](const AudioPath& soundId, int distance) -> void
|
||||
{
|
||||
if(vstd::contains(currentSounds, soundId))
|
||||
currentSounds[soundId] = std::min(currentSounds[soundId], distance);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../mapView/IMapRendererObserver.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class ObjectInstanceID;
|
||||
@ -29,7 +30,7 @@ class MapAudioPlayer : public IMapObjectObserver
|
||||
void addObject(const CGObjectInstance * obj);
|
||||
void removeObject(const CGObjectInstance * obj);
|
||||
|
||||
std::vector<std::string> getAmbientSounds(const int3 & tile);
|
||||
std::vector<AudioPath> getAmbientSounds(const int3 & tile);
|
||||
void updateAmbientSounds();
|
||||
void updateMusic();
|
||||
void update();
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CStack.h"
|
||||
#include "../../lib/CPlayerState.h"
|
||||
#include "../../lib/filesystem/ResourceID.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
|
||||
TurnTimerWidget::DrawRect::DrawRect(const Rect & r, const ColorRGBA & c):
|
||||
CIntObject(), rect(r), color(c)
|
||||
@ -47,7 +47,7 @@ TurnTimerWidget::TurnTimerWidget():
|
||||
|
||||
recActions &= ~DEACTIVATE;
|
||||
|
||||
const JsonNode config(ResourceID("config/widgets/turnTimer.json"));
|
||||
const JsonNode config(JsonPath::builtin("config/widgets/turnTimer.json"));
|
||||
|
||||
build(config);
|
||||
|
||||
@ -77,7 +77,7 @@ void TurnTimerWidget::setTime(PlayerColor player, int time)
|
||||
&& newTime != turnTime
|
||||
&& notifications.count(newTime))
|
||||
{
|
||||
CCS->soundh->playSound(variables["notificationSound"].String());
|
||||
CCS->soundh->playSound(AudioPath::fromJson(variables["notificationSound"]));
|
||||
}
|
||||
|
||||
turnTime = newTime;
|
||||
|
@ -171,7 +171,7 @@ void BattleActionsController::enterCreatureCastingMode()
|
||||
spells::Target target;
|
||||
target.emplace_back();
|
||||
|
||||
spells::BattleCast cast(owner.curInt->cb.get(), caster, spells::Mode::CREATURE_ACTIVE, spell);
|
||||
spells::BattleCast cast(owner.getBattle().get(), caster, spells::Mode::CREATURE_ACTIVE, spell);
|
||||
|
||||
auto m = spell->battleMechanics(&cast);
|
||||
spells::detail::ProblemImpl ignored;
|
||||
@ -207,7 +207,7 @@ std::vector<PossiblePlayerBattleAction> BattleActionsController::getPossibleActi
|
||||
data.creatureSpellsToCast.push_back(spell->id);
|
||||
|
||||
data.tacticsMode = owner.tacticsMode;
|
||||
auto allActions = owner.curInt->cb->getClientActionsForStack(stack, data);
|
||||
auto allActions = owner.getBattle()->getClientActionsForStack(stack, data);
|
||||
|
||||
allActions.push_back(PossiblePlayerBattleAction::HERO_INFO);
|
||||
allActions.push_back(PossiblePlayerBattleAction::CREATURE_INFO);
|
||||
@ -231,7 +231,7 @@ void BattleActionsController::reorderPossibleActionsPriority(const CStack * stac
|
||||
case PossiblePlayerBattleAction::OBSTACLE:
|
||||
if(!stack->hasBonusOfType(BonusType::NO_SPELLCAST_BY_DEFAULT) && targetStack != nullptr)
|
||||
{
|
||||
PlayerColor stackOwner = owner.curInt->cb->battleGetOwner(targetStack);
|
||||
PlayerColor stackOwner = owner.getBattle()->battleGetOwner(targetStack);
|
||||
bool enemyTargetingPositiveSpellcast = item.spell().toSpell()->isPositive() && stackOwner != LOCPLINT->playerID;
|
||||
bool friendTargetingNegativeSpellcast = item.spell().toSpell()->isNegative() && stackOwner == LOCPLINT->playerID;
|
||||
|
||||
@ -300,12 +300,12 @@ void BattleActionsController::castThisSpell(SpellID spellID)
|
||||
//choosing possible targets
|
||||
const CGHeroInstance *castingHero = (owner.attackingHeroInstance->tempOwner == owner.curInt->playerID) ? owner.attackingHeroInstance : owner.defendingHeroInstance;
|
||||
assert(castingHero); // code below assumes non-null hero
|
||||
PossiblePlayerBattleAction spellSelMode = owner.curInt->cb->getCasterAction(spellID.toSpell(), castingHero, spells::Mode::HERO);
|
||||
PossiblePlayerBattleAction spellSelMode = owner.getBattle()->getCasterAction(spellID.toSpell(), castingHero, spells::Mode::HERO);
|
||||
|
||||
if (spellSelMode.get() == PossiblePlayerBattleAction::NO_LOCATION) //user does not have to select location
|
||||
{
|
||||
heroSpellToCast->aimToHex(BattleHex::INVALID);
|
||||
owner.curInt->cb->battleMakeSpellAction(*heroSpellToCast);
|
||||
owner.curInt->cb->battleMakeSpellAction(owner.getBattleID(), *heroSpellToCast);
|
||||
endCastingSpell();
|
||||
}
|
||||
else
|
||||
@ -353,10 +353,10 @@ const CSpell * BattleActionsController::getCurrentSpell(BattleHex hoveredHex)
|
||||
|
||||
const CStack * BattleActionsController::getStackForHex(BattleHex hoveredHex)
|
||||
{
|
||||
const CStack * shere = owner.curInt->cb->battleGetStackByPos(hoveredHex, true);
|
||||
const CStack * shere = owner.getBattle()->battleGetStackByPos(hoveredHex, true);
|
||||
if(shere)
|
||||
return shere;
|
||||
return owner.curInt->cb->battleGetStackByPos(hoveredHex, false);
|
||||
return owner.getBattle()->battleGetStackByPos(hoveredHex, false);
|
||||
}
|
||||
|
||||
void BattleActionsController::actionSetCursor(PossiblePlayerBattleAction action, BattleHex targetHex)
|
||||
@ -400,7 +400,7 @@ void BattleActionsController::actionSetCursor(PossiblePlayerBattleAction action,
|
||||
}
|
||||
|
||||
case PossiblePlayerBattleAction::SHOOT:
|
||||
if (owner.curInt->cb->battleHasShootingPenalty(owner.stacksController->getActiveStack(), targetHex))
|
||||
if (owner.getBattle()->battleHasShootingPenalty(owner.stacksController->getActiveStack(), targetHex))
|
||||
CCS->curh->set(Cursor::Combat::SHOOT_PENALTY);
|
||||
else
|
||||
CCS->curh->set(Cursor::Combat::SHOOT);
|
||||
@ -482,7 +482,7 @@ std::string BattleActionsController::actionGetStatusMessage(PossiblePlayerBattle
|
||||
case PossiblePlayerBattleAction::ATTACK_AND_RETURN: //TODO: allow to disable return
|
||||
{
|
||||
BattleHex attackFromHex = owner.fieldController->fromWhichHexAttack(targetHex);
|
||||
DamageEstimation estimation = owner.curInt->cb->battleEstimateDamage(owner.stacksController->getActiveStack(), targetStack, attackFromHex);
|
||||
DamageEstimation estimation = owner.getBattle()->battleEstimateDamage(owner.stacksController->getActiveStack(), targetStack, attackFromHex);
|
||||
estimation.kills.max = std::min<int64_t>(estimation.kills.max, targetStack->getCount());
|
||||
estimation.kills.min = std::min<int64_t>(estimation.kills.min, targetStack->getCount());
|
||||
|
||||
@ -493,7 +493,7 @@ std::string BattleActionsController::actionGetStatusMessage(PossiblePlayerBattle
|
||||
{
|
||||
const auto * shooter = owner.stacksController->getActiveStack();
|
||||
|
||||
DamageEstimation estimation = owner.curInt->cb->battleEstimateDamage(shooter, targetStack, shooter->getPosition());
|
||||
DamageEstimation estimation = owner.getBattle()->battleEstimateDamage(shooter, targetStack, shooter->getPosition());
|
||||
estimation.kills.max = std::min<int64_t>(estimation.kills.max, targetStack->getCount());
|
||||
estimation.kills.min = std::min<int64_t>(estimation.kills.min, targetStack->getCount());
|
||||
|
||||
@ -593,7 +593,7 @@ bool BattleActionsController::actionIsLegal(PossiblePlayerBattleAction action, B
|
||||
case PossiblePlayerBattleAction::ATTACK:
|
||||
case PossiblePlayerBattleAction::WALK_AND_ATTACK:
|
||||
case PossiblePlayerBattleAction::ATTACK_AND_RETURN:
|
||||
if(owner.curInt->cb->battleCanAttack(owner.stacksController->getActiveStack(), targetStack, targetHex))
|
||||
if(owner.getBattle()->battleCanAttack(owner.stacksController->getActiveStack(), targetStack, targetHex))
|
||||
{
|
||||
if (owner.fieldController->isTileAttackable(targetHex)) // move isTileAttackable to be part of battleCanAttack?
|
||||
return true;
|
||||
@ -601,7 +601,7 @@ bool BattleActionsController::actionIsLegal(PossiblePlayerBattleAction action, B
|
||||
return false;
|
||||
|
||||
case PossiblePlayerBattleAction::SHOOT:
|
||||
return owner.curInt->cb->battleCanShoot(owner.stacksController->getActiveStack(), targetHex);
|
||||
return owner.getBattle()->battleCanShoot(owner.stacksController->getActiveStack(), targetHex);
|
||||
|
||||
case PossiblePlayerBattleAction::NO_LOCATION:
|
||||
return false;
|
||||
@ -615,7 +615,7 @@ bool BattleActionsController::actionIsLegal(PossiblePlayerBattleAction action, B
|
||||
case PossiblePlayerBattleAction::RANDOM_GENIE_SPELL:
|
||||
if(targetStack && targetStackOwned && targetStack != owner.stacksController->getActiveStack() && targetStack->alive()) //only positive spells for other allied creatures
|
||||
{
|
||||
int spellID = owner.curInt->cb->battleGetRandomStackSpell(CRandomGenerator::getDefault(), targetStack, CBattleInfoCallback::RANDOM_GENIE);
|
||||
int spellID = owner.getBattle()->battleGetRandomStackSpell(CRandomGenerator::getDefault(), targetStack, CBattleInfoCallback::RANDOM_GENIE);
|
||||
return spellID > -1;
|
||||
}
|
||||
return false;
|
||||
@ -658,7 +658,7 @@ void BattleActionsController::actionRealize(PossiblePlayerBattleAction action, B
|
||||
{
|
||||
if(owner.stacksController->getActiveStack()->doubleWide())
|
||||
{
|
||||
std::vector<BattleHex> acc = owner.curInt->cb->battleGetAvailableHexes(owner.stacksController->getActiveStack(), false);
|
||||
std::vector<BattleHex> acc = owner.getBattle()->battleGetAvailableHexes(owner.stacksController->getActiveStack(), false);
|
||||
BattleHex shiftedDest = targetHex.cloneInDirection(owner.stacksController->getActiveStack()->destShiftDir(), false);
|
||||
if(vstd::contains(acc, targetHex))
|
||||
owner.giveCommand(EActionType::WALK, targetHex);
|
||||
@ -770,7 +770,7 @@ void BattleActionsController::actionRealize(PossiblePlayerBattleAction action, B
|
||||
heroSpellToCast->aimToHex(targetHex);
|
||||
break;
|
||||
}
|
||||
owner.curInt->cb->battleMakeSpellAction(*heroSpellToCast);
|
||||
owner.curInt->cb->battleMakeSpellAction(owner.getBattleID(), *heroSpellToCast);
|
||||
endCastingSpell();
|
||||
}
|
||||
selectedStack = nullptr;
|
||||
@ -886,7 +886,7 @@ void BattleActionsController::tryActivateStackSpellcasting(const CStack *casterS
|
||||
{
|
||||
// faerie dragon can cast only one, randomly selected spell until their next move
|
||||
//TODO: faerie dragon type spell should be selected by server
|
||||
const auto * spellToCast = owner.curInt->cb->battleGetRandomStackSpell(CRandomGenerator::getDefault(), casterStack, CBattleInfoCallback::RANDOM_AIMED).toSpell();
|
||||
const auto * spellToCast = owner.getBattle()->battleGetRandomStackSpell(CRandomGenerator::getDefault(), casterStack, CBattleInfoCallback::RANDOM_AIMED).toSpell();
|
||||
|
||||
if (spellToCast)
|
||||
creatureSpells.push_back(spellToCast);
|
||||
@ -933,7 +933,7 @@ bool BattleActionsController::isCastingPossibleHere(const CSpell * currentSpell,
|
||||
target.emplace_back(targetStack);
|
||||
target.emplace_back(targetHex);
|
||||
|
||||
spells::BattleCast cast(owner.curInt->cb.get(), caster, mode, currentSpell);
|
||||
spells::BattleCast cast(owner.getBattle().get(), caster, mode, currentSpell);
|
||||
|
||||
auto m = currentSpell->battleMechanics(&cast);
|
||||
spells::detail::ProblemImpl problem; //todo: display problem in status bar
|
||||
@ -943,7 +943,7 @@ bool BattleActionsController::isCastingPossibleHere(const CSpell * currentSpell,
|
||||
|
||||
bool BattleActionsController::canStackMoveHere(const CStack * stackToMove, BattleHex myNumber) const
|
||||
{
|
||||
std::vector<BattleHex> acc = owner.curInt->cb->battleGetAvailableHexes(stackToMove, false);
|
||||
std::vector<BattleHex> acc = owner.getBattle()->battleGetAvailableHexes(stackToMove, false);
|
||||
BattleHex shiftedDest = myNumber.cloneInDirection(stackToMove->destShiftDir(), false);
|
||||
|
||||
if (vstd::contains(acc, myNumber))
|
||||
@ -1006,7 +1006,7 @@ void BattleActionsController::onHexRightClicked(BattleHex clickedHex)
|
||||
return;
|
||||
}
|
||||
|
||||
auto selectedStack = owner.curInt->cb->battleGetStackByPos(clickedHex, true);
|
||||
auto selectedStack = owner.getBattle()->battleGetStackByPos(clickedHex, true);
|
||||
|
||||
if (selectedStack != nullptr)
|
||||
GH.windows().createAndPushWindow<CStackWindow>(selectedStack, true);
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../gui/CursorHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CStack.h"
|
||||
@ -114,7 +115,7 @@ void StackActionAnimation::setGroup( ECreatureAnimType group )
|
||||
currGroup = group;
|
||||
}
|
||||
|
||||
void StackActionAnimation::setSound( std::string sound )
|
||||
void StackActionAnimation::setSound( const AudioPath & sound )
|
||||
{
|
||||
this->sound = sound;
|
||||
}
|
||||
@ -179,7 +180,7 @@ HittedAnimation::HittedAnimation(BattleInterface & owner, const CStack * stack)
|
||||
: StackActionAnimation(owner, stack)
|
||||
{
|
||||
setGroup(ECreatureAnimType::HITTED);
|
||||
setSound(battle_sound(stack->unitType(), wince));
|
||||
setSound(stack->unitType()->sounds.wince);
|
||||
logAnim->debug("Created HittedAnimation for %s", stack->getName());
|
||||
}
|
||||
|
||||
@ -187,14 +188,14 @@ DefenceAnimation::DefenceAnimation(BattleInterface & owner, const CStack * stack
|
||||
: StackActionAnimation(owner, stack)
|
||||
{
|
||||
setGroup(ECreatureAnimType::DEFENCE);
|
||||
setSound(battle_sound(stack->unitType(), defend));
|
||||
setSound(stack->unitType()->sounds.defend);
|
||||
logAnim->debug("Created DefenceAnimation for %s", stack->getName());
|
||||
}
|
||||
|
||||
DeathAnimation::DeathAnimation(BattleInterface & owner, const CStack * stack, bool ranged):
|
||||
StackActionAnimation(owner, stack)
|
||||
{
|
||||
setSound(battle_sound(stack->unitType(), killed));
|
||||
setSound(stack->unitType()->sounds.killed);
|
||||
|
||||
if(ranged && myAnim->framesInGroup(ECreatureAnimType::DEATH_RANGED) > 0)
|
||||
setGroup(ECreatureAnimType::DEATH_RANGED);
|
||||
@ -315,7 +316,7 @@ MeleeAttackAnimation::MeleeAttackAnimation(BattleInterface & owner, const CStack
|
||||
: AttackAnimation(owner, attacker, _dest, _attacked)
|
||||
{
|
||||
logAnim->debug("Created MeleeAttackAnimation for %s", attacker->getName());
|
||||
setSound(battle_sound(getCreature(), attack));
|
||||
setSound(getCreature()->sounds.attack);
|
||||
setGroup(selectGroup(multiAttack));
|
||||
}
|
||||
|
||||
@ -356,7 +357,7 @@ bool MovementAnimation::init()
|
||||
|
||||
if (moveSoundHander == -1)
|
||||
{
|
||||
moveSoundHander = CCS->soundh->playSound(battle_sound(stack->unitType(), move), -1);
|
||||
moveSoundHander = CCS->soundh->playSound(stack->unitType()->sounds.move, -1);
|
||||
}
|
||||
|
||||
Point begPosition = owner.stacksController->getStackPositionAtHex(prevHex, stack);
|
||||
@ -453,7 +454,7 @@ bool MovementEndAnimation::init()
|
||||
logAnim->debug("CMovementEndAnimation::init: stack %s", stack->getName());
|
||||
myAnim->pos.moveTo(owner.stacksController->getStackPositionAtHex(nextHex, stack));
|
||||
|
||||
CCS->soundh->playSound(battle_sound(stack->unitType(), endMoving));
|
||||
CCS->soundh->playSound(stack->unitType()->sounds.endMoving);
|
||||
|
||||
if(!myAnim->framesInGroup(ECreatureAnimType::MOVE_END))
|
||||
{
|
||||
@ -494,7 +495,7 @@ bool MovementStartAnimation::init()
|
||||
}
|
||||
|
||||
logAnim->debug("CMovementStartAnimation::init: stack %s", stack->getName());
|
||||
CCS->soundh->playSound(battle_sound(stack->unitType(), startMoving));
|
||||
CCS->soundh->playSound(stack->unitType()->sounds.startMoving);
|
||||
|
||||
if(!myAnim->framesInGroup(ECreatureAnimType::MOVE_START))
|
||||
{
|
||||
@ -632,7 +633,7 @@ RangedAttackAnimation::RangedAttackAnimation(BattleInterface & owner_, const CSt
|
||||
: AttackAnimation(owner_, attacker, dest_, defender),
|
||||
projectileEmitted(false)
|
||||
{
|
||||
setSound(battle_sound(getCreature(), shoot));
|
||||
setSound(getCreature()->sounds.shoot);
|
||||
}
|
||||
|
||||
bool RangedAttackAnimation::init()
|
||||
@ -806,8 +807,8 @@ void CatapultAnimation::tick(uint32_t msPassed)
|
||||
explosionEmitted = true;
|
||||
Point shotTarget = owner.stacksController->getStackPositionAtHex(dest, defendingStack) + Point(225, 225) - Point(126, 105);
|
||||
|
||||
std::string soundFilename = (catapultDamage > 0) ? "WALLHIT" : "WALLMISS";
|
||||
std::string effectFilename = (catapultDamage > 0) ? "SGEXPL" : "CSGRCK";
|
||||
auto soundFilename = AudioPath::builtin((catapultDamage > 0) ? "WALLHIT" : "WALLMISS");
|
||||
AnimationPath effectFilename = AnimationPath::builtin((catapultDamage > 0) ? "SGEXPL" : "CSGRCK");
|
||||
|
||||
CCS->soundh->playSound( soundFilename );
|
||||
owner.stacksController->addNewAnim( new EffectAnimation(owner, effectFilename, shotTarget));
|
||||
@ -879,42 +880,42 @@ uint32_t CastAnimation::getAttackClimaxFrame() const
|
||||
return maxFrames / 2;
|
||||
}
|
||||
|
||||
EffectAnimation::EffectAnimation(BattleInterface & owner, std::string animationName, int effects, bool reversed):
|
||||
EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, int effects, bool reversed):
|
||||
BattleAnimation(owner),
|
||||
animation(std::make_shared<CAnimation>(animationName)),
|
||||
animation(GH.renderHandler().loadAnimation(animationName)),
|
||||
effectFlags(effects),
|
||||
effectFinished(false),
|
||||
reversed(reversed)
|
||||
{
|
||||
logAnim->debug("CPointEffectAnimation::init: effect %s", animationName);
|
||||
logAnim->debug("CPointEffectAnimation::init: effect %s", animationName.getName());
|
||||
}
|
||||
|
||||
EffectAnimation::EffectAnimation(BattleInterface & owner, std::string animationName, std::vector<BattleHex> hex, int effects, bool reversed):
|
||||
EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, std::vector<BattleHex> hex, int effects, bool reversed):
|
||||
EffectAnimation(owner, animationName, effects, reversed)
|
||||
{
|
||||
battlehexes = hex;
|
||||
}
|
||||
|
||||
EffectAnimation::EffectAnimation(BattleInterface & owner, std::string animationName, BattleHex hex, int effects, bool reversed):
|
||||
EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, BattleHex hex, int effects, bool reversed):
|
||||
EffectAnimation(owner, animationName, effects, reversed)
|
||||
{
|
||||
assert(hex.isValid());
|
||||
battlehexes.push_back(hex);
|
||||
}
|
||||
|
||||
EffectAnimation::EffectAnimation(BattleInterface & owner, std::string animationName, std::vector<Point> pos, int effects, bool reversed):
|
||||
EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, std::vector<Point> pos, int effects, bool reversed):
|
||||
EffectAnimation(owner, animationName, effects, reversed)
|
||||
{
|
||||
positions = pos;
|
||||
}
|
||||
|
||||
EffectAnimation::EffectAnimation(BattleInterface & owner, std::string animationName, Point pos, int effects, bool reversed):
|
||||
EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, Point pos, int effects, bool reversed):
|
||||
EffectAnimation(owner, animationName, effects, reversed)
|
||||
{
|
||||
positions.push_back(pos);
|
||||
}
|
||||
|
||||
EffectAnimation::EffectAnimation(BattleInterface & owner, std::string animationName, Point pos, BattleHex hex, int effects, bool reversed):
|
||||
EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, Point pos, BattleHex hex, int effects, bool reversed):
|
||||
EffectAnimation(owner, animationName, effects, reversed)
|
||||
{
|
||||
assert(hex.isValid());
|
||||
@ -970,7 +971,7 @@ bool EffectAnimation::init()
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto * destStack = owner.getCurrentPlayerInterface()->cb->battleGetUnitByPos(battlehexes[i], false);
|
||||
const auto * destStack = owner.getBattle()->battleGetUnitByPos(battlehexes[i], false);
|
||||
Rect tilePos = owner.fieldController->hexPositionLocal(battlehexes[i]);
|
||||
|
||||
be.pos.x = tilePos.x + tilePos.w/2 - first->width()/2;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/battle/BattleHex.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
#include "BattleConstants.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
@ -68,11 +69,11 @@ class StackActionAnimation : public BattleStackAnimation
|
||||
{
|
||||
ECreatureAnimType nextGroup;
|
||||
ECreatureAnimType currGroup;
|
||||
std::string sound;
|
||||
AudioPath sound;
|
||||
public:
|
||||
void setNextGroup( ECreatureAnimType group );
|
||||
void setGroup( ECreatureAnimType group );
|
||||
void setSound( std::string sound );
|
||||
void setSound( const AudioPath & sound );
|
||||
|
||||
ECreatureAnimType getGroup() const;
|
||||
|
||||
@ -334,17 +335,17 @@ public:
|
||||
};
|
||||
|
||||
/// Create animation with screen-wide effect
|
||||
EffectAnimation(BattleInterface & owner, std::string animationName, int effects = 0, bool reversed = false);
|
||||
EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, int effects = 0, bool reversed = false);
|
||||
|
||||
/// Create animation positioned at point(s). Note that positions must be are absolute, including battleint position offset
|
||||
EffectAnimation(BattleInterface & owner, std::string animationName, Point pos , int effects = 0, bool reversed = false);
|
||||
EffectAnimation(BattleInterface & owner, std::string animationName, std::vector<Point> pos , int effects = 0, bool reversed = false);
|
||||
EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, Point pos , int effects = 0, bool reversed = false);
|
||||
EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, std::vector<Point> pos , int effects = 0, bool reversed = false);
|
||||
|
||||
/// Create animation positioned at certain hex(es)
|
||||
EffectAnimation(BattleInterface & owner, std::string animationName, BattleHex hex , int effects = 0, bool reversed = false);
|
||||
EffectAnimation(BattleInterface & owner, std::string animationName, std::vector<BattleHex> hex, int effects = 0, bool reversed = false);
|
||||
EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, BattleHex hex , int effects = 0, bool reversed = false);
|
||||
EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, std::vector<BattleHex> hex, int effects = 0, bool reversed = false);
|
||||
|
||||
EffectAnimation(BattleInterface & owner, std::string animationName, Point pos, BattleHex hex, int effects = 0, bool reversed = false);
|
||||
EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, Point pos, BattleHex hex, int effects = 0, bool reversed = false);
|
||||
~EffectAnimation();
|
||||
|
||||
bool init() override;
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/battle/BattleAction.h"
|
||||
#include "../../lib/filesystem/ResourceID.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
#include "../../lib/NetPacks.h"
|
||||
#include "../../lib/CStack.h"
|
||||
#include "../../lib/IGameEventsReceiver.h"
|
||||
@ -41,14 +41,14 @@ BattleEffectsController::BattleEffectsController(BattleInterface & owner):
|
||||
|
||||
void BattleEffectsController::displayEffect(EBattleEffect effect, const BattleHex & destTile)
|
||||
{
|
||||
displayEffect(effect, "", destTile);
|
||||
displayEffect(effect, AudioPath(), destTile);
|
||||
}
|
||||
|
||||
void BattleEffectsController::displayEffect(EBattleEffect effect, std::string soundFile, const BattleHex & destTile)
|
||||
void BattleEffectsController::displayEffect(EBattleEffect effect, const AudioPath & soundFile, const BattleHex & destTile)
|
||||
{
|
||||
size_t effectID = static_cast<size_t>(effect);
|
||||
|
||||
std::string customAnim = graphics->battleACToDef[effectID][0];
|
||||
AnimationPath customAnim = AnimationPath::builtinTODO(graphics->battleACToDef[effectID][0]);
|
||||
|
||||
CCS->soundh->playSound( soundFile );
|
||||
|
||||
@ -59,7 +59,7 @@ void BattleEffectsController::battleTriggerEffect(const BattleTriggerEffect & bt
|
||||
{
|
||||
owner.checkForAnimations();
|
||||
|
||||
const CStack * stack = owner.curInt->cb->battleGetStackByID(bte.stackID);
|
||||
const CStack * stack = owner.getBattle()->battleGetStackByID(bte.stackID);
|
||||
if(!stack)
|
||||
{
|
||||
logGlobal->error("Invalid stack ID %d", bte.stackID);
|
||||
@ -69,22 +69,22 @@ void BattleEffectsController::battleTriggerEffect(const BattleTriggerEffect & bt
|
||||
switch(static_cast<BonusType>(bte.effect))
|
||||
{
|
||||
case BonusType::HP_REGENERATION:
|
||||
displayEffect(EBattleEffect::REGENERATION, "REGENER", stack->getPosition());
|
||||
displayEffect(EBattleEffect::REGENERATION, AudioPath::builtin("REGENER"), stack->getPosition());
|
||||
break;
|
||||
case BonusType::MANA_DRAIN:
|
||||
displayEffect(EBattleEffect::MANA_DRAIN, "MANADRAI", stack->getPosition());
|
||||
displayEffect(EBattleEffect::MANA_DRAIN, AudioPath::builtin("MANADRAI"), stack->getPosition());
|
||||
break;
|
||||
case BonusType::POISON:
|
||||
displayEffect(EBattleEffect::POISON, "POISON", stack->getPosition());
|
||||
displayEffect(EBattleEffect::POISON, AudioPath::builtin("POISON"), stack->getPosition());
|
||||
break;
|
||||
case BonusType::FEAR:
|
||||
displayEffect(EBattleEffect::FEAR, "FEAR", stack->getPosition());
|
||||
displayEffect(EBattleEffect::FEAR, AudioPath::builtin("FEAR"), stack->getPosition());
|
||||
break;
|
||||
case BonusType::MORALE:
|
||||
{
|
||||
std::string hlp = CGI->generaltexth->allTexts[33];
|
||||
boost::algorithm::replace_first(hlp,"%s",(stack->getName()));
|
||||
displayEffect(EBattleEffect::GOOD_MORALE, "GOODMRLE", stack->getPosition());
|
||||
displayEffect(EBattleEffect::GOOD_MORALE, AudioPath::builtin("GOODMRLE"), stack->getPosition());
|
||||
owner.appendBattleLog(hlp);
|
||||
break;
|
||||
}
|
||||
@ -98,7 +98,7 @@ void BattleEffectsController::startAction(const BattleAction & action)
|
||||
{
|
||||
owner.checkForAnimations();
|
||||
|
||||
const CStack *stack = owner.curInt->cb->battleGetStackByID(action.stackNumber);
|
||||
const CStack *stack = owner.getBattle()->battleGetStackByID(action.stackNumber);
|
||||
|
||||
switch(action.actionType)
|
||||
{
|
||||
@ -107,7 +107,7 @@ void BattleEffectsController::startAction(const BattleAction & action)
|
||||
break;
|
||||
case EActionType::BAD_MORALE:
|
||||
owner.appendBattleLog(stack->formatGeneralMessage(-34));
|
||||
displayEffect(EBattleEffect::BAD_MORALE, "BADMRLE", stack->getPosition());
|
||||
displayEffect(EBattleEffect::BAD_MORALE, AudioPath::builtin("BADMRLE"), stack->getPosition());
|
||||
break;
|
||||
}
|
||||
|
||||
@ -132,7 +132,7 @@ void BattleEffectsController::collectRenderableObjects(BattleRenderer & renderer
|
||||
|
||||
void BattleEffectsController::loadColorMuxers()
|
||||
{
|
||||
const JsonNode config(ResourceID("config/battleEffects.json"));
|
||||
const JsonNode config(JsonPath::builtin("config/battleEffects.json"));
|
||||
|
||||
for(auto & muxer : config["colorMuxers"].Struct())
|
||||
{
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "../../lib/battle/BattleHex.h"
|
||||
#include "../../lib/Point.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
#include "BattleConstants.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
@ -64,7 +65,7 @@ public:
|
||||
|
||||
//displays custom effect on the battlefield
|
||||
void displayEffect(EBattleEffect effect, const BattleHex & destTile);
|
||||
void displayEffect(EBattleEffect effect, std::string soundFile, const BattleHex & destTile);
|
||||
void displayEffect(EBattleEffect effect, const AudioPath & soundFile, const BattleHex & destTile);
|
||||
|
||||
void battleTriggerEffect(const BattleTriggerEffect & bte);
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/CursorHandler.h"
|
||||
#include "../adventureMap/CInGameConsole.h"
|
||||
@ -120,20 +121,20 @@ BattleFieldController::BattleFieldController(BattleInterface & owner):
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
|
||||
//preparing cells and hexes
|
||||
cellBorder = IImage::createFromFile("CCELLGRD.BMP", EImageBlitMode::COLORKEY);
|
||||
cellShade = IImage::createFromFile("CCELLSHD.BMP");
|
||||
cellUnitMovementHighlight = IImage::createFromFile("UnitMovementHighlight.PNG", EImageBlitMode::COLORKEY);
|
||||
cellUnitMaxMovementHighlight = IImage::createFromFile("UnitMaxMovementHighlight.PNG", EImageBlitMode::COLORKEY);
|
||||
cellBorder = GH.renderHandler().loadImage(ImagePath::builtin("CCELLGRD.BMP"), EImageBlitMode::COLORKEY);
|
||||
cellShade = GH.renderHandler().loadImage(ImagePath::builtin("CCELLSHD.BMP"));
|
||||
cellUnitMovementHighlight = GH.renderHandler().loadImage(ImagePath::builtin("UnitMovementHighlight.PNG"), EImageBlitMode::COLORKEY);
|
||||
cellUnitMaxMovementHighlight = GH.renderHandler().loadImage(ImagePath::builtin("UnitMaxMovementHighlight.PNG"), EImageBlitMode::COLORKEY);
|
||||
|
||||
attackCursors = std::make_shared<CAnimation>("CRCOMBAT");
|
||||
attackCursors = GH.renderHandler().loadAnimation(AnimationPath::builtin("CRCOMBAT"));
|
||||
attackCursors->preload();
|
||||
|
||||
initializeHexEdgeMaskToFrameIndex();
|
||||
|
||||
rangedFullDamageLimitImages = std::make_shared<CAnimation>("battle/rangeHighlights/rangeHighlightsGreen.json");
|
||||
rangedFullDamageLimitImages = GH.renderHandler().loadAnimation(AnimationPath::builtin("battle/rangeHighlights/rangeHighlightsGreen.json"));
|
||||
rangedFullDamageLimitImages->preload();
|
||||
|
||||
shootingRangeLimitImages = std::make_shared<CAnimation>("battle/rangeHighlights/rangeHighlightsRed.json");
|
||||
shootingRangeLimitImages = GH.renderHandler().loadAnimation(AnimationPath::builtin("battle/rangeHighlights/rangeHighlightsRed.json"));
|
||||
shootingRangeLimitImages->preload();
|
||||
|
||||
flipRangeLimitImagesIntoPositions(rangedFullDamageLimitImages);
|
||||
@ -141,17 +142,17 @@ BattleFieldController::BattleFieldController(BattleInterface & owner):
|
||||
|
||||
if(!owner.siegeController)
|
||||
{
|
||||
auto bfieldType = owner.curInt->cb->battleGetBattlefieldType();
|
||||
auto bfieldType = owner.getBattle()->battleGetBattlefieldType();
|
||||
|
||||
if(bfieldType == BattleField::NONE)
|
||||
logGlobal->error("Invalid battlefield returned for current battle");
|
||||
else
|
||||
background = IImage::createFromFile(bfieldType.getInfo()->graphics, EImageBlitMode::OPAQUE);
|
||||
background = GH.renderHandler().loadImage(bfieldType.getInfo()->graphics, EImageBlitMode::OPAQUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string backgroundName = owner.siegeController->getBattleBackgroundName();
|
||||
background = IImage::createFromFile(backgroundName, EImageBlitMode::OPAQUE);
|
||||
auto backgroundName = owner.siegeController->getBattleBackgroundName();
|
||||
background = GH.renderHandler().loadImage(backgroundName, EImageBlitMode::OPAQUE);
|
||||
}
|
||||
|
||||
pos.w = background->width();
|
||||
@ -284,7 +285,7 @@ void BattleFieldController::redrawBackgroundWithHexes()
|
||||
const CStack *activeStack = owner.stacksController->getActiveStack();
|
||||
std::vector<BattleHex> attackableHexes;
|
||||
if(activeStack)
|
||||
occupiableHexes = owner.curInt->cb->battleGetAvailableHexes(activeStack, false, true, &attackableHexes);
|
||||
occupiableHexes = owner.getBattle()->battleGetAvailableHexes(activeStack, false, true, &attackableHexes);
|
||||
|
||||
// prepare background graphic with hexes and shaded hexes
|
||||
backgroundWithHexes->draw(background, Point(0,0));
|
||||
@ -339,7 +340,7 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesForActiveStack()
|
||||
|
||||
auto hoveredHex = getHoveredHex();
|
||||
|
||||
std::set<BattleHex> set = owner.curInt->cb->battleGetAttackedHexes(owner.stacksController->getActiveStack(), hoveredHex);
|
||||
std::set<BattleHex> set = owner.getBattle()->battleGetAttackedHexes(owner.stacksController->getActiveStack(), hoveredHex);
|
||||
for(BattleHex hex : set)
|
||||
result.insert(hex);
|
||||
|
||||
@ -359,10 +360,10 @@ std::set<BattleHex> BattleFieldController::getMovementRangeForHoveredStack()
|
||||
auto hoveredHex = getHoveredHex();
|
||||
|
||||
// add possible movement hexes for stack under mouse
|
||||
const CStack * const hoveredStack = owner.curInt->cb->battleGetStackByPos(hoveredHex, true);
|
||||
const CStack * const hoveredStack = owner.getBattle()->battleGetStackByPos(hoveredHex, true);
|
||||
if(hoveredStack)
|
||||
{
|
||||
std::vector<BattleHex> v = owner.curInt->cb->battleGetAvailableHexes(hoveredStack, true, true, nullptr);
|
||||
std::vector<BattleHex> v = owner.getBattle()->battleGetAvailableHexes(hoveredStack, true, true, nullptr);
|
||||
for(BattleHex hex : v)
|
||||
result.insert(hex);
|
||||
}
|
||||
@ -387,7 +388,7 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesForSpellRange()
|
||||
if(caster && spell) //when casting spell
|
||||
{
|
||||
// printing shaded hex(es)
|
||||
spells::BattleCast event(owner.curInt->cb.get(), caster, mode, spell);
|
||||
spells::BattleCast event(owner.getBattle().get(), caster, mode, spell);
|
||||
auto shadedHexes = spell->battleMechanics(&event)->rangeInHexes(hoveredHex);
|
||||
|
||||
for(BattleHex shadedHex : shadedHexes)
|
||||
@ -407,10 +408,10 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesForMovementTarget(
|
||||
if(!stack)
|
||||
return {};
|
||||
|
||||
std::vector<BattleHex> availableHexes = owner.curInt->cb->battleGetAvailableHexes(stack, false, false, nullptr);
|
||||
std::vector<BattleHex> availableHexes = owner.getBattle()->battleGetAvailableHexes(stack, false, false, nullptr);
|
||||
|
||||
auto hoveredStack = owner.curInt->cb->battleGetStackByPos(hoveredHex, true);
|
||||
if(owner.curInt->cb->battleCanAttack(stack, hoveredStack, hoveredHex))
|
||||
auto hoveredStack = owner.getBattle()->battleGetStackByPos(hoveredHex, true);
|
||||
if(owner.getBattle()->battleCanAttack(stack, hoveredStack, hoveredHex))
|
||||
{
|
||||
if(isTileAttackable(hoveredHex))
|
||||
{
|
||||
@ -670,7 +671,7 @@ BattleHex BattleFieldController::getHoveredHex()
|
||||
const CStack* BattleFieldController::getHoveredStack()
|
||||
{
|
||||
auto hoveredHex = getHoveredHex();
|
||||
const CStack* hoveredStack = owner.curInt->cb->battleGetStackByPos(hoveredHex, true);
|
||||
const CStack* hoveredStack = owner.getBattle()->battleGetStackByPos(hoveredHex, true);
|
||||
|
||||
return hoveredStack;
|
||||
}
|
||||
@ -856,7 +857,7 @@ bool BattleFieldController::isTileAttackable(const BattleHex & number) const
|
||||
|
||||
void BattleFieldController::updateAccessibleHexes()
|
||||
{
|
||||
auto accessibility = owner.curInt->cb->getAccesibility();
|
||||
auto accessibility = owner.getBattle()->getAccesibility();
|
||||
|
||||
for(int i = 0; i < accessibility.size(); i++)
|
||||
stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE || (accessibility[i] == EAccessibility::SIDE_COLUMN));
|
||||
|
@ -45,7 +45,7 @@
|
||||
#include "../../lib/TerrainHandler.h"
|
||||
#include "../../lib/CThreadHelper.h"
|
||||
|
||||
BattleInterface::BattleInterface(const CCreatureSet *army1, const CCreatureSet *army2,
|
||||
BattleInterface::BattleInterface(const BattleID & battleID, const CCreatureSet *army1, const CCreatureSet *army2,
|
||||
const CGHeroInstance *hero1, const CGHeroInstance *hero2,
|
||||
std::shared_ptr<CPlayerInterface> att,
|
||||
std::shared_ptr<CPlayerInterface> defen,
|
||||
@ -55,6 +55,7 @@ BattleInterface::BattleInterface(const CCreatureSet *army1, const CCreatureSet *
|
||||
, attackerInt(att)
|
||||
, defenderInt(defen)
|
||||
, curInt(att)
|
||||
, battleID(battleID)
|
||||
, battleOpeningDelayActive(true)
|
||||
{
|
||||
if(spectatorInt)
|
||||
@ -68,9 +69,9 @@ BattleInterface::BattleInterface(const CCreatureSet *army1, const CCreatureSet *
|
||||
}
|
||||
|
||||
//hot-seat -> check tactics for both players (defender may be local human)
|
||||
if(attackerInt && attackerInt->cb->battleGetTacticDist())
|
||||
if(attackerInt && attackerInt->cb->getBattle(getBattleID())->battleGetTacticDist())
|
||||
tacticianInterface = attackerInt;
|
||||
else if(defenderInt && defenderInt->cb->battleGetTacticDist())
|
||||
else if(defenderInt && defenderInt->cb->getBattle(getBattleID())->battleGetTacticDist())
|
||||
tacticianInterface = defenderInt;
|
||||
|
||||
//if we found interface of player with tactics, then enter tactics mode
|
||||
@ -80,7 +81,7 @@ BattleInterface::BattleInterface(const CCreatureSet *army1, const CCreatureSet *
|
||||
this->army1 = army1;
|
||||
this->army2 = army2;
|
||||
|
||||
const CGTownInstance *town = curInt->cb->battleGetDefendedTown();
|
||||
const CGTownInstance *town = getBattle()->battleGetDefendedTown();
|
||||
if(town && town->hasFort())
|
||||
siegeController.reset(new BattleSiegeController(*this, town));
|
||||
|
||||
@ -223,12 +224,12 @@ void BattleInterface::stackAttacking( const StackAttackInfo & attackInfo )
|
||||
stacksController->stackAttacking(attackInfo);
|
||||
}
|
||||
|
||||
void BattleInterface::newRoundFirst( int round )
|
||||
void BattleInterface::newRoundFirst()
|
||||
{
|
||||
waitForAnimations();
|
||||
}
|
||||
|
||||
void BattleInterface::newRound(int number)
|
||||
void BattleInterface::newRound()
|
||||
{
|
||||
console->addText(CGI->generaltexth->allTexts[412]);
|
||||
}
|
||||
@ -241,10 +242,10 @@ void BattleInterface::giveCommand(EActionType action, BattleHex tile, SpellID sp
|
||||
actor = stacksController->getActiveStack();
|
||||
}
|
||||
|
||||
auto side = curInt->cb->playerToSide(curInt->playerID);
|
||||
auto side = getBattle()->playerToSide(curInt->playerID);
|
||||
if(!side)
|
||||
{
|
||||
logGlobal->error("Player %s is not in battle", curInt->playerID.getStr());
|
||||
logGlobal->error("Player %s is not in battle", curInt->playerID.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -265,11 +266,11 @@ void BattleInterface::sendCommand(BattleAction command, const CStack * actor)
|
||||
{
|
||||
logGlobal->trace("Setting command for %s", (actor ? actor->nodeName() : "hero"));
|
||||
stacksController->setActiveStack(nullptr);
|
||||
curInt->cb->battleMakeUnitAction(command);
|
||||
curInt->cb->battleMakeUnitAction(battleID, command);
|
||||
}
|
||||
else
|
||||
{
|
||||
curInt->cb->battleMakeTacticAction(command);
|
||||
curInt->cb->battleMakeTacticAction(battleID, command);
|
||||
stacksController->setActiveStack(nullptr);
|
||||
//next stack will be activated when action ends
|
||||
}
|
||||
@ -353,7 +354,7 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
|
||||
if(!spell)
|
||||
return;
|
||||
|
||||
const std::string & castSoundPath = spell->getCastSound();
|
||||
const AudioPath & castSoundPath = spell->getCastSound();
|
||||
|
||||
if (!castSoundPath.empty())
|
||||
{
|
||||
@ -368,13 +369,13 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
|
||||
|
||||
if ( sc->activeCast )
|
||||
{
|
||||
const CStack * casterStack = curInt->cb->battleGetStackByID(sc->casterStack);
|
||||
const CStack * casterStack = getBattle()->battleGetStackByID(sc->casterStack);
|
||||
|
||||
if(casterStack != nullptr )
|
||||
{
|
||||
addToAnimationStage(EAnimationEvents::BEFORE_HIT, [=]()
|
||||
{
|
||||
stacksController->addNewAnim(new CastAnimation(*this, casterStack, targetedTile, curInt->cb->battleGetStackByPos(targetedTile), spell));
|
||||
stacksController->addNewAnim(new CastAnimation(*this, casterStack, targetedTile, getBattle()->battleGetStackByPos(targetedTile), spell));
|
||||
displaySpellCast(spell, casterStack->getPosition());
|
||||
});
|
||||
}
|
||||
@ -385,7 +386,7 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
|
||||
|
||||
addToAnimationStage(EAnimationEvents::BEFORE_HIT, [=]()
|
||||
{
|
||||
stacksController->addNewAnim(new HeroCastAnimation(*this, hero, targetedTile, curInt->cb->battleGetStackByPos(targetedTile), spell));
|
||||
stacksController->addNewAnim(new HeroCastAnimation(*this, hero, targetedTile, getBattle()->battleGetStackByPos(targetedTile), spell));
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -397,7 +398,7 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
|
||||
//queuing affect animation
|
||||
for(auto & elem : sc->affectedCres)
|
||||
{
|
||||
auto stack = curInt->cb->battleGetStackByID(elem, false);
|
||||
auto stack = getBattle()->battleGetStackByID(elem, false);
|
||||
assert(stack);
|
||||
if(stack)
|
||||
{
|
||||
@ -409,7 +410,7 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
|
||||
|
||||
for(auto & elem : sc->reflectedCres)
|
||||
{
|
||||
auto stack = curInt->cb->battleGetStackByID(elem, false);
|
||||
auto stack = getBattle()->battleGetStackByID(elem, false);
|
||||
assert(stack);
|
||||
addToAnimationStage(EAnimationEvents::HIT, [=](){
|
||||
effectsController->displayEffect(EBattleEffect::MAGIC_MIRROR, stack->getPosition());
|
||||
@ -419,13 +420,13 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
|
||||
if (!sc->resistedCres.empty())
|
||||
{
|
||||
addToAnimationStage(EAnimationEvents::HIT, [=](){
|
||||
CCS->soundh->playSound("MAGICRES");
|
||||
CCS->soundh->playSound(AudioPath::builtin("MAGICRES"));
|
||||
});
|
||||
}
|
||||
|
||||
for(auto & elem : sc->resistedCres)
|
||||
{
|
||||
auto stack = curInt->cb->battleGetStackByID(elem, false);
|
||||
auto stack = getBattle()->battleGetStackByID(elem, false);
|
||||
assert(stack);
|
||||
addToAnimationStage(EAnimationEvents::HIT, [=](){
|
||||
effectsController->displayEffect(EBattleEffect::RESISTANCE, stack->getPosition());
|
||||
@ -440,8 +441,8 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
|
||||
bool side = sc->side;
|
||||
|
||||
addToAnimationStage(EAnimationEvents::AFTER_HIT, [=](){
|
||||
stacksController->addNewAnim(new EffectAnimation(*this, side ? "SP07_A.DEF" : "SP07_B.DEF", leftHero));
|
||||
stacksController->addNewAnim(new EffectAnimation(*this, side ? "SP07_B.DEF" : "SP07_A.DEF", rightHero));
|
||||
stacksController->addNewAnim(new EffectAnimation(*this, AnimationPath::builtin(side ? "SP07_A.DEF" : "SP07_B.DEF"), leftHero));
|
||||
stacksController->addNewAnim(new EffectAnimation(*this, AnimationPath::builtin(side ? "SP07_B.DEF" : "SP07_A.DEF"), rightHero));
|
||||
});
|
||||
}
|
||||
|
||||
@ -487,7 +488,7 @@ void BattleInterface::displaySpellAnimationQueue(const CSpell * spell, const CSp
|
||||
|
||||
if (!animation.effectName.empty())
|
||||
{
|
||||
const CStack * destStack = getCurrentPlayerInterface()->cb->battleGetStackByPos(destinationTile, false);
|
||||
const CStack * destStack = getBattle()->battleGetStackByPos(destinationTile, false);
|
||||
|
||||
if (destStack)
|
||||
stacksController->addNewAnim(new ColorTransformAnimation(*this, destStack, animation.effectName, spell ));
|
||||
@ -566,12 +567,22 @@ bool BattleInterface::makingTurn() const
|
||||
return stacksController->getActiveStack() != nullptr;
|
||||
}
|
||||
|
||||
BattleID BattleInterface::getBattleID() const
|
||||
{
|
||||
return battleID;
|
||||
}
|
||||
|
||||
std::shared_ptr<CPlayerBattleCallback> BattleInterface::getBattle() const
|
||||
{
|
||||
return curInt->cb->getBattle(battleID);
|
||||
}
|
||||
|
||||
void BattleInterface::endAction(const BattleAction &action)
|
||||
{
|
||||
// it is possible that tactics mode ended while opening music is still playing
|
||||
waitForAnimations();
|
||||
|
||||
const CStack *stack = curInt->cb->battleGetStackByID(action.stackNumber);
|
||||
const CStack *stack = getBattle()->battleGetStackByID(action.stackNumber);
|
||||
|
||||
// Activate stack from stackToActivate because this might have been temporary disabled, e.g., during spell cast
|
||||
activateStack();
|
||||
@ -606,7 +617,7 @@ void BattleInterface::startAction(const BattleAction & action)
|
||||
if (!action.isUnitAction())
|
||||
return;
|
||||
|
||||
assert(curInt->cb->battleGetStackByID(action.stackNumber));
|
||||
assert(getBattle()->battleGetStackByID(action.stackNumber));
|
||||
windowObject->updateQueue();
|
||||
effectsController->startAction(action);
|
||||
}
|
||||
@ -616,10 +627,10 @@ void BattleInterface::tacticPhaseEnd()
|
||||
stacksController->setActiveStack(nullptr);
|
||||
tacticsMode = false;
|
||||
|
||||
auto side = tacticianInterface->cb->playerToSide(tacticianInterface->playerID);
|
||||
auto side = tacticianInterface->cb->getBattle(battleID)->playerToSide(tacticianInterface->playerID);
|
||||
auto action = BattleAction::makeEndOFTacticPhase(*side);
|
||||
|
||||
tacticianInterface->cb->battleMakeTacticAction(action);
|
||||
tacticianInterface->cb->battleMakeTacticAction(battleID, action);
|
||||
}
|
||||
|
||||
static bool immobile(const CStack *s)
|
||||
@ -635,7 +646,7 @@ void BattleInterface::tacticNextStack(const CStack * current)
|
||||
//no switching stacks when the current one is moving
|
||||
checkForAnimations();
|
||||
|
||||
TStacks stacksOfMine = tacticianInterface->cb->battleGetStacks(CBattleCallback::ONLY_MINE);
|
||||
TStacks stacksOfMine = tacticianInterface->cb->getBattle(battleID)->battleGetStacks(CPlayerBattleCallback::ONLY_MINE);
|
||||
vstd::erase_if (stacksOfMine, &immobile);
|
||||
if (stacksOfMine.empty())
|
||||
{
|
||||
@ -687,7 +698,7 @@ void BattleInterface::requestAutofightingAIToTakeAction()
|
||||
{
|
||||
assert(curInt->isAutoFightOn);
|
||||
|
||||
if(curInt->cb->battleIsFinished())
|
||||
if(getBattle()->battleIsFinished())
|
||||
{
|
||||
return; // battle finished with spellcast
|
||||
}
|
||||
@ -716,7 +727,7 @@ void BattleInterface::requestAutofightingAIToTakeAction()
|
||||
boost::thread aiThread([this, activeStack]()
|
||||
{
|
||||
setThreadName("autofightingAI");
|
||||
curInt->autofightingAI->activeStack(activeStack);
|
||||
curInt->autofightingAI->activeStack(battleID, activeStack);
|
||||
});
|
||||
aiThread.detach();
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ struct BattleTriggerEffect;
|
||||
struct BattleHex;
|
||||
struct InfoAboutHero;
|
||||
class ObstacleChanges;
|
||||
class CPlayerBattleCallback;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
@ -115,6 +116,9 @@ class BattleInterface
|
||||
/// if set to true, battle is still starting and waiting for intro sound to end / key press from player
|
||||
bool battleOpeningDelayActive;
|
||||
|
||||
/// ID of ongoing battle
|
||||
BattleID battleID;
|
||||
|
||||
void playIntroSoundAndUnlockInterface();
|
||||
void onIntroSoundPlayed();
|
||||
public:
|
||||
@ -149,7 +153,10 @@ public:
|
||||
|
||||
bool makingTurn() const;
|
||||
|
||||
BattleInterface(const CCreatureSet *army1, const CCreatureSet *army2, const CGHeroInstance *hero1, const CGHeroInstance *hero2, std::shared_ptr<CPlayerInterface> att, std::shared_ptr<CPlayerInterface> defen, std::shared_ptr<CPlayerInterface> spectatorInt = nullptr);
|
||||
BattleID getBattleID() const;
|
||||
std::shared_ptr<CPlayerBattleCallback> getBattle() const;
|
||||
|
||||
BattleInterface(const BattleID & battleID, const CCreatureSet *army1, const CCreatureSet *army2, const CGHeroInstance *hero1, const CGHeroInstance *hero2, std::shared_ptr<CPlayerInterface> att, std::shared_ptr<CPlayerInterface> defen, std::shared_ptr<CPlayerInterface> spectatorInt = nullptr);
|
||||
~BattleInterface();
|
||||
|
||||
void trySetActivePlayer( PlayerColor player ); // if in hotseat, will activate interface of chosen player
|
||||
@ -196,8 +203,8 @@ public:
|
||||
void stackMoved(const CStack *stack, std::vector<BattleHex> destHex, int distance, bool teleport); //stack with id number moved to destHex
|
||||
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( int round );
|
||||
void newRound(int number); //caled when round is ended; number is the number of round
|
||||
void newRoundFirst();
|
||||
void newRound(); //caled 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
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "../windows/CMessage.h"
|
||||
#include "../windows/CSpellWindow.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
#include "../adventureMap/CInGameConsole.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
@ -289,7 +290,7 @@ void BattleHero::heroLeftClicked()
|
||||
if(!hero || !owner.makingTurn())
|
||||
return;
|
||||
|
||||
if(owner.getCurrentPlayerInterface()->cb->battleCanCastSpell(hero, spells::Mode::HERO) == ESpellCastProblem::OK) //check conditions
|
||||
if(owner.getBattle()->battleCanCastSpell(hero, spells::Mode::HERO) == ESpellCastProblem::OK) //check conditions
|
||||
{
|
||||
CCS->curh->set(Cursor::Map::POINTER);
|
||||
GH.windows().createAndPushWindow<CSpellWindow>(hero, owner.getCurrentPlayerInterface());
|
||||
@ -342,7 +343,7 @@ BattleHero::BattleHero(const BattleInterface & owner, const CGHeroInstance * her
|
||||
currentFrame(0.f),
|
||||
flagCurrentFrame(0.f)
|
||||
{
|
||||
std::string animationPath;
|
||||
AnimationPath animationPath;
|
||||
|
||||
if(!hero->type->battleImage.empty())
|
||||
animationPath = hero->type->battleImage;
|
||||
@ -352,7 +353,7 @@ BattleHero::BattleHero(const BattleInterface & owner, const CGHeroInstance * her
|
||||
else
|
||||
animationPath = hero->type->heroClass->imageBattleMale;
|
||||
|
||||
animation = std::make_shared<CAnimation>(animationPath);
|
||||
animation = GH.renderHandler().loadAnimation(animationPath);
|
||||
animation->preload();
|
||||
|
||||
pos.w = 64;
|
||||
@ -364,9 +365,9 @@ BattleHero::BattleHero(const BattleInterface & owner, const CGHeroInstance * her
|
||||
animation->verticalFlip();
|
||||
|
||||
if(defender)
|
||||
flagAnimation = std::make_shared<CAnimation>("CMFLAGR");
|
||||
flagAnimation = GH.renderHandler().loadAnimation(AnimationPath::builtin("CMFLAGR"));
|
||||
else
|
||||
flagAnimation = std::make_shared<CAnimation>("CMFLAGL");
|
||||
flagAnimation = GH.renderHandler().loadAnimation(AnimationPath::builtin("CMFLAGL"));
|
||||
|
||||
flagAnimation->preload();
|
||||
flagAnimation->playerColored(hero->tempOwner);
|
||||
@ -386,7 +387,7 @@ HeroInfoBasicPanel::HeroInfoBasicPanel(const InfoAboutHero & hero, Point * posit
|
||||
|
||||
if(initializeBackground)
|
||||
{
|
||||
background = std::make_shared<CPicture>("CHRPOP");
|
||||
background = std::make_shared<CPicture>(ImagePath::builtin("CHRPOP"));
|
||||
background->getSurface()->setBlitMode(EImageBlitMode::OPAQUE);
|
||||
background->colorize(hero.owner);
|
||||
}
|
||||
@ -406,7 +407,7 @@ void HeroInfoBasicPanel::initializeData(const InfoAboutHero & hero)
|
||||
auto currentSpellPoints = hero.details->mana;
|
||||
auto maxSpellPoints = hero.details->manaLimit;
|
||||
|
||||
icons.push_back(std::make_shared<CAnimImage>("PortraitsLarge", hero.portrait, 0, 10, 6));
|
||||
icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), hero.portrait, 0, 10, 6));
|
||||
|
||||
//primary stats
|
||||
labels.push_back(std::make_shared<CLabel>(9, 75, EFonts::FONT_TINY, ETextAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[380] + ":"));
|
||||
@ -423,8 +424,8 @@ void HeroInfoBasicPanel::initializeData(const InfoAboutHero & hero)
|
||||
labels.push_back(std::make_shared<CLabel>(9, 131, EFonts::FONT_TINY, ETextAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[384] + ":"));
|
||||
labels.push_back(std::make_shared<CLabel>(9, 143, EFonts::FONT_TINY, ETextAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[385] + ":"));
|
||||
|
||||
icons.push_back(std::make_shared<CAnimImage>("IMRL22", morale + 3, 0, 47, 131));
|
||||
icons.push_back(std::make_shared<CAnimImage>("ILCK22", luck + 3, 0, 47, 143));
|
||||
icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("IMRL22"), morale + 3, 0, 47, 131));
|
||||
icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("ILCK22"), luck + 3, 0, 47, 143));
|
||||
|
||||
//spell points
|
||||
labels.push_back(std::make_shared<CLabel>(39, 174, EFonts::FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->allTexts[387]));
|
||||
@ -446,7 +447,7 @@ void HeroInfoBasicPanel::show(Canvas & to)
|
||||
}
|
||||
|
||||
HeroInfoWindow::HeroInfoWindow(const InfoAboutHero & hero, Point * position)
|
||||
: CWindowObject(RCLICK_POPUP | SHADOW_DISABLED, "CHRPOP")
|
||||
: CWindowObject(RCLICK_POPUP | SHADOW_DISABLED, ImagePath::builtin("CHRPOP"))
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
if (position != nullptr)
|
||||
@ -462,16 +463,16 @@ BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
|
||||
background = std::make_shared<CPicture>("CPRESULT");
|
||||
background = std::make_shared<CPicture>(ImagePath::builtin("CPRESULT"));
|
||||
background->colorize(owner.playerID);
|
||||
pos = center(background->pos);
|
||||
|
||||
exit = std::make_shared<CButton>(Point(384, 505), "iok6432.def", std::make_pair("", ""), [&](){ bExitf();}, EShortcut::GLOBAL_ACCEPT);
|
||||
exit = std::make_shared<CButton>(Point(384, 505), AnimationPath::builtin("iok6432.def"), std::make_pair("", ""), [&](){ bExitf();}, EShortcut::GLOBAL_ACCEPT);
|
||||
exit->setBorderColor(Colors::METALLIC_GOLD);
|
||||
|
||||
if(allowReplay)
|
||||
{
|
||||
repeat = std::make_shared<CButton>(Point(24, 505), "icn6432.def", std::make_pair("", ""), [&](){ bRepeatf();}, EShortcut::GLOBAL_CANCEL);
|
||||
repeat = std::make_shared<CButton>(Point(24, 505), AnimationPath::builtin("icn6432.def"), std::make_pair("", ""), [&](){ bRepeatf();}, EShortcut::GLOBAL_CANCEL);
|
||||
repeat->setBorderColor(Colors::METALLIC_GOLD);
|
||||
labels.push_back(std::make_shared<CLabel>(232, 520, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->translate("vcmi.battleResultsWindow.applyResultsLabel")));
|
||||
}
|
||||
@ -502,17 +503,17 @@ BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
auto heroInfo = owner.cb->battleGetHeroInfo(i);
|
||||
auto heroInfo = owner.cb->getBattle(br.battleID)->battleGetHeroInfo(i);
|
||||
const int xs[] = {21, 392};
|
||||
|
||||
if(heroInfo.portrait >= 0) //attacking hero
|
||||
{
|
||||
icons.push_back(std::make_shared<CAnimImage>("PortraitsLarge", heroInfo.portrait, 0, xs[i], 38));
|
||||
icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsLarge"), heroInfo.portrait, 0, xs[i], 38));
|
||||
sideNames[i] = heroInfo.name;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto stacks = owner.cb->battleGetAllStacks();
|
||||
auto stacks = owner.cb->getBattle(br.battleID)->battleGetAllStacks();
|
||||
vstd::erase_if(stacks, [i](const CStack * stack) //erase stack of other side and not coming from garrison
|
||||
{
|
||||
return stack->unitSide() != i || !stack->base;
|
||||
@ -525,7 +526,7 @@ BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface
|
||||
|
||||
if(best != stacks.end()) //should be always but to be safe...
|
||||
{
|
||||
icons.push_back(std::make_shared<CAnimImage>("TWCRPORT", (*best)->unitType()->getIconIndex(), 0, xs[i], 38));
|
||||
icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("TWCRPORT"), (*best)->unitType()->getIconIndex(), 0, xs[i], 38));
|
||||
sideNames[i] = (*best)->unitType()->getNamePluralTranslated();
|
||||
}
|
||||
}
|
||||
@ -552,7 +553,7 @@ BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface
|
||||
if (creature->getId() == CreatureID::ARROW_TOWERS )
|
||||
continue; // do not show destroyed towers in battle results
|
||||
|
||||
icons.push_back(std::make_shared<CAnimImage>("CPRSMALL", creature->getIconIndex(), 0, xPos, yPos));
|
||||
icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("CPRSMALL"), creature->getIconIndex(), 0, xPos, yPos));
|
||||
std::ostringstream amount;
|
||||
amount<<elem.second;
|
||||
labels.push_back(std::make_shared<CLabel>(xPos + 16, yPos + 42, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, amount.str()));
|
||||
@ -561,7 +562,7 @@ BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface
|
||||
}
|
||||
}
|
||||
//printing result description
|
||||
bool weAreAttacker = !(owner.cb->battleGetMySide());
|
||||
bool weAreAttacker = !(owner.cb->getBattle(br.battleID)->battleGetMySide());
|
||||
if((br.winner == 0 && weAreAttacker) || (br.winner == 1 && !weAreAttacker)) //we've won
|
||||
{
|
||||
int text = 304;
|
||||
@ -580,11 +581,11 @@ BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface
|
||||
break;
|
||||
}
|
||||
|
||||
CCS->musich->playMusic("Music/Win Battle", false, true);
|
||||
CCS->videoh->open("WIN3.BIK");
|
||||
CCS->musich->playMusic(AudioPath::builtin("Music/Win Battle"), false, true);
|
||||
CCS->videoh->open(VideoPath::builtin("WIN3.BIK"));
|
||||
std::string str = CGI->generaltexth->allTexts[text];
|
||||
|
||||
const CGHeroInstance * ourHero = owner.cb->battleGetMyHero();
|
||||
const CGHeroInstance * ourHero = owner.cb->getBattle(br.battleID)->battleGetMyHero();
|
||||
if (ourHero)
|
||||
{
|
||||
str += CGI->generaltexth->allTexts[305];
|
||||
@ -597,20 +598,20 @@ BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface
|
||||
else // we lose
|
||||
{
|
||||
int text = 311;
|
||||
std::string musicName = "Music/LoseCombat";
|
||||
std::string videoName = "LBSTART.BIK";
|
||||
AudioPath musicName = AudioPath::builtin("Music/LoseCombat");
|
||||
VideoPath videoName = VideoPath::builtin("LBSTART.BIK");
|
||||
switch(br.result)
|
||||
{
|
||||
case EBattleResult::NORMAL:
|
||||
break;
|
||||
case EBattleResult::ESCAPE:
|
||||
musicName = "Music/Retreat Battle";
|
||||
videoName = "RTSTART.BIK";
|
||||
musicName = AudioPath::builtin("Music/Retreat Battle");
|
||||
videoName = VideoPath::builtin("RTSTART.BIK");
|
||||
text = 310;
|
||||
break;
|
||||
case EBattleResult::SURRENDER:
|
||||
musicName = "Music/Surrender Battle";
|
||||
videoName = "SURRENDER.BIK";
|
||||
musicName = AudioPath::builtin("Music/Surrender Battle");
|
||||
videoName = VideoPath::builtin("SURRENDER.BIK");
|
||||
text = 309;
|
||||
break;
|
||||
default:
|
||||
@ -676,8 +677,8 @@ StackQueue::StackQueue(bool Embedded, BattleInterface & owner)
|
||||
pos.x += parent->pos.w/2 - pos.w/2;
|
||||
pos.y += 10;
|
||||
|
||||
icons = std::make_shared<CAnimation>("CPRSMALL");
|
||||
stateIcons = std::make_shared<CAnimation>("VCMI/BATTLEQUEUE/STATESSMALL");
|
||||
icons = GH.renderHandler().loadAnimation(AnimationPath::builtin("CPRSMALL"));
|
||||
stateIcons = GH.renderHandler().loadAnimation(AnimationPath::builtin("VCMI/BATTLEQUEUE/STATESSMALL"));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -686,12 +687,12 @@ StackQueue::StackQueue(bool Embedded, BattleInterface & owner)
|
||||
pos.x += 0;
|
||||
pos.y -= pos.h;
|
||||
|
||||
background = std::make_shared<CFilledTexture>("DIBOXBCK", Rect(0, 0, pos.w, pos.h));
|
||||
background = std::make_shared<CFilledTexture>(ImagePath::builtin("DIBOXBCK"), Rect(0, 0, pos.w, pos.h));
|
||||
|
||||
icons = std::make_shared<CAnimation>("TWCRPORT");
|
||||
stateIcons = std::make_shared<CAnimation>("VCMI/BATTLEQUEUE/STATESSMALL");
|
||||
icons = GH.renderHandler().loadAnimation(AnimationPath::builtin("TWCRPORT"));
|
||||
stateIcons = GH.renderHandler().loadAnimation(AnimationPath::builtin("VCMI/BATTLEQUEUE/STATESSMALL"));
|
||||
//TODO: where use big icons?
|
||||
//stateIcons = std::make_shared<CAnimation>("VCMI/BATTLEQUEUE/STATESBIG");
|
||||
//stateIcons = GH.renderHandler().loadAnimation("VCMI/BATTLEQUEUE/STATESBIG");
|
||||
}
|
||||
stateIcons->preload();
|
||||
|
||||
@ -714,7 +715,7 @@ void StackQueue::update()
|
||||
{
|
||||
std::vector<battle::Units> queueData;
|
||||
|
||||
owner.getCurrentPlayerInterface()->cb->battleGetTurnOrder(queueData, stackBoxes.size(), 0);
|
||||
owner.getBattle()->battleGetTurnOrder(queueData, stackBoxes.size(), 0);
|
||||
|
||||
size_t boxIndex = 0;
|
||||
|
||||
@ -750,7 +751,7 @@ StackQueue::StackBox::StackBox(StackQueue * owner):
|
||||
CIntObject(SHOW_POPUP | HOVER), owner(owner)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
background = std::make_shared<CPicture>(owner->embedded ? "StackQueueSmall" : "StackQueueLarge");
|
||||
background = std::make_shared<CPicture>(ImagePath::builtin(owner->embedded ? "StackQueueSmall" : "StackQueueLarge"));
|
||||
|
||||
pos.w = background->pos.w;
|
||||
pos.h = background->pos.h;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/battle/CObstacleInstance.h"
|
||||
@ -31,7 +32,7 @@ BattleObstacleController::BattleObstacleController(BattleInterface & owner):
|
||||
owner(owner),
|
||||
timePassed(0.f)
|
||||
{
|
||||
auto obst = owner.curInt->cb->battleGetAllObstacles();
|
||||
auto obst = owner.getBattle()->battleGetAllObstacles();
|
||||
for(auto & elem : obst)
|
||||
{
|
||||
if ( elem->obstacleType == CObstacleInstance::MOAT )
|
||||
@ -42,21 +43,21 @@ BattleObstacleController::BattleObstacleController(BattleInterface & owner):
|
||||
|
||||
void BattleObstacleController::loadObstacleImage(const CObstacleInstance & oi)
|
||||
{
|
||||
std::string animationName = oi.getAnimation();
|
||||
AnimationPath animationName = oi.getAnimation();
|
||||
|
||||
if (animationsCache.count(animationName) == 0)
|
||||
{
|
||||
if (oi.obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
|
||||
{
|
||||
// obstacle uses single bitmap image for animations
|
||||
auto animation = std::make_shared<CAnimation>();
|
||||
animation->setCustom(animationName, 0, 0);
|
||||
auto animation = GH.renderHandler().createAnimation();
|
||||
animation->setCustom(animationName.getName(), 0, 0);
|
||||
animationsCache[animationName] = animation;
|
||||
animation->preload();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto animation = std::make_shared<CAnimation>(animationName);
|
||||
auto animation = GH.renderHandler().loadAnimation(animationName);
|
||||
animationsCache[animationName] = animation;
|
||||
animation->preload();
|
||||
}
|
||||
@ -76,7 +77,7 @@ void BattleObstacleController::obstacleRemoved(const std::vector<ObstacleChanges
|
||||
continue;
|
||||
}
|
||||
|
||||
auto animation = std::make_shared<CAnimation>(obstacle["appearAnimation"].String());
|
||||
auto animation = GH.renderHandler().loadAnimation(AnimationPath::fromJson(obstacle["appearAnimation"]));
|
||||
animation->preload();
|
||||
|
||||
auto first = animation->getImage(0, 0);
|
||||
@ -87,7 +88,7 @@ void BattleObstacleController::obstacleRemoved(const std::vector<ObstacleChanges
|
||||
// -> if we know how to blit obstacle, let's blit the effect in the same place
|
||||
Point whereTo = getObstaclePosition(first, obstacle);
|
||||
//AFAIK, in H3 there is no sound of obstacle removal
|
||||
owner.stacksController->addNewAnim(new EffectAnimation(owner, obstacle["appearAnimation"].String(), whereTo, obstacle["position"].Integer(), 0, true));
|
||||
owner.stacksController->addNewAnim(new EffectAnimation(owner, AnimationPath::fromJson(obstacle["appearAnimation"]), whereTo, obstacle["position"].Integer(), 0, true));
|
||||
|
||||
obstacleAnimations.erase(oi.id);
|
||||
//so when multiple obstacles are removed, they show up one after another
|
||||
@ -99,12 +100,12 @@ void BattleObstacleController::obstaclePlaced(const std::vector<std::shared_ptr<
|
||||
{
|
||||
for(const auto & oi : obstacles)
|
||||
{
|
||||
auto side = owner.curInt->cb->playerToSide(owner.curInt->playerID);
|
||||
auto side = owner.getBattle()->playerToSide(owner.curInt->playerID);
|
||||
|
||||
if(!oi->visibleForSide(side.value(), owner.curInt->cb->battleHasNativeStack(side.value())))
|
||||
if(!oi->visibleForSide(side.value(), owner.getBattle()->battleHasNativeStack(side.value())))
|
||||
continue;
|
||||
|
||||
auto animation = std::make_shared<CAnimation>(oi->getAppearAnimation());
|
||||
auto animation = GH.renderHandler().loadAnimation(oi->getAppearAnimation());
|
||||
animation->preload();
|
||||
|
||||
auto first = animation->getImage(0, 0);
|
||||
@ -127,7 +128,7 @@ void BattleObstacleController::obstaclePlaced(const std::vector<std::shared_ptr<
|
||||
void BattleObstacleController::showAbsoluteObstacles(Canvas & canvas)
|
||||
{
|
||||
//Blit absolute obstacles
|
||||
for(auto & obstacle : owner.curInt->cb->battleGetAllObstacles())
|
||||
for(auto & obstacle : owner.getBattle()->battleGetAllObstacles())
|
||||
{
|
||||
if(obstacle->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
|
||||
{
|
||||
@ -153,7 +154,7 @@ void BattleObstacleController::showAbsoluteObstacles(Canvas & canvas)
|
||||
|
||||
void BattleObstacleController::collectRenderableObjects(BattleRenderer & renderer)
|
||||
{
|
||||
for (auto obstacle : owner.curInt->cb->battleGetAllObstacles())
|
||||
for (auto obstacle : owner.getBattle()->battleGetAllObstacles())
|
||||
{
|
||||
if (obstacle->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
|
||||
continue;
|
||||
|
@ -9,6 +9,8 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
struct BattleHex;
|
||||
@ -35,7 +37,7 @@ class BattleObstacleController
|
||||
float timePassed;
|
||||
|
||||
/// cached animations of all obstacles in current battle
|
||||
std::map<std::string, std::shared_ptr<CAnimation>> animationsCache;
|
||||
std::map<AnimationPath, std::shared_ptr<CAnimation>> animationsCache;
|
||||
|
||||
/// list of all obstacles that are currently being rendered
|
||||
std::map<si32, std::shared_ptr<CAnimation>> obstacleAnimations;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "CreatureAnimation.h"
|
||||
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../CGameInfo.h"
|
||||
|
||||
@ -188,9 +189,9 @@ void BattleProjectileController::initStackProjectile(const CStack * stack)
|
||||
projectilesCache[creature.animation.projectileImageName] = createProjectileImage(creature.animation.projectileImageName);
|
||||
}
|
||||
|
||||
std::shared_ptr<CAnimation> BattleProjectileController::createProjectileImage(const std::string & path )
|
||||
std::shared_ptr<CAnimation> BattleProjectileController::createProjectileImage(const AnimationPath & path )
|
||||
{
|
||||
std::shared_ptr<CAnimation> projectile = std::make_shared<CAnimation>(path);
|
||||
std::shared_ptr<CAnimation> projectile = GH.renderHandler().loadAnimation(path);
|
||||
projectile->preload();
|
||||
|
||||
if(projectile->size(1) != 0)
|
||||
@ -204,7 +205,7 @@ std::shared_ptr<CAnimation> BattleProjectileController::createProjectileImage(co
|
||||
std::shared_ptr<CAnimation> BattleProjectileController::getProjectileImage(const CStack * stack)
|
||||
{
|
||||
const CCreature & creature = getShooter(stack);
|
||||
std::string imageName = creature.animation.projectileImageName;
|
||||
AnimationPath imageName = creature.animation.projectileImageName;
|
||||
|
||||
if (!projectilesCache.count(imageName))
|
||||
initStackProjectile(stack);
|
||||
@ -361,7 +362,7 @@ void BattleProjectileController::createProjectile(const CStack * shooter, Point
|
||||
void BattleProjectileController::createSpellProjectile(const CStack * shooter, Point from, Point dest, const CSpell * spell)
|
||||
{
|
||||
double projectileAngle = std::abs(atan2(dest.x - from.x, dest.y - from.y));
|
||||
std::string animToDisplay = spell->animationInfo.selectProjectile(projectileAngle);
|
||||
AnimationPath animToDisplay = spell->animationInfo.selectProjectile(projectileAngle);
|
||||
|
||||
assert(!animToDisplay.empty());
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/Point.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@ -83,13 +84,13 @@ class BattleProjectileController
|
||||
BattleInterface & owner;
|
||||
|
||||
/// all projectiles loaded during current battle
|
||||
std::map<std::string, std::shared_ptr<CAnimation>> projectilesCache;
|
||||
std::map<AnimationPath, std::shared_ptr<CAnimation>> projectilesCache;
|
||||
|
||||
/// projectiles currently flying on battlefield
|
||||
std::vector<std::shared_ptr<ProjectileBase>> projectiles;
|
||||
|
||||
std::shared_ptr<CAnimation> getProjectileImage(const CStack * stack);
|
||||
std::shared_ptr<CAnimation> createProjectileImage(const std::string & path );
|
||||
std::shared_ptr<CAnimation> createProjectileImage(const AnimationPath & path );
|
||||
void initStackProjectile(const CStack * stack);
|
||||
|
||||
bool stackUsesRayProjectile(const CStack * stack) const;
|
||||
|
@ -20,15 +20,17 @@
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/NetPacks.h"
|
||||
#include "../../lib/CStack.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
|
||||
std::string BattleSiegeController::getWallPieceImageName(EWallVisual::EWallVisual what, EWallState state) const
|
||||
ImagePath BattleSiegeController::getWallPieceImageName(EWallVisual::EWallVisual what, EWallState state) const
|
||||
{
|
||||
auto getImageIndex = [&]() -> int
|
||||
{
|
||||
@ -68,44 +70,44 @@ std::string BattleSiegeController::getWallPieceImageName(EWallVisual::EWallVisua
|
||||
auto faction = town->town->faction->getIndex();
|
||||
|
||||
if (faction == ETownType::RAMPART || faction == ETownType::NECROPOLIS || faction == ETownType::DUNGEON || faction == ETownType::STRONGHOLD)
|
||||
return prefix + "TPW1.BMP";
|
||||
return ImagePath::builtinTODO(prefix + "TPW1.BMP");
|
||||
else
|
||||
return prefix + "TPWL.BMP";
|
||||
return ImagePath::builtinTODO(prefix + "TPWL.BMP");
|
||||
}
|
||||
case EWallVisual::KEEP:
|
||||
return prefix + "MAN" + addit + ".BMP";
|
||||
return ImagePath::builtinTODO(prefix + "MAN" + addit + ".BMP");
|
||||
case EWallVisual::BOTTOM_TOWER:
|
||||
return prefix + "TW1" + addit + ".BMP";
|
||||
return ImagePath::builtinTODO(prefix + "TW1" + addit + ".BMP");
|
||||
case EWallVisual::BOTTOM_WALL:
|
||||
return prefix + "WA1" + addit + ".BMP";
|
||||
return ImagePath::builtinTODO(prefix + "WA1" + addit + ".BMP");
|
||||
case EWallVisual::WALL_BELLOW_GATE:
|
||||
return prefix + "WA3" + addit + ".BMP";
|
||||
return ImagePath::builtinTODO(prefix + "WA3" + addit + ".BMP");
|
||||
case EWallVisual::WALL_OVER_GATE:
|
||||
return prefix + "WA4" + addit + ".BMP";
|
||||
return ImagePath::builtinTODO(prefix + "WA4" + addit + ".BMP");
|
||||
case EWallVisual::UPPER_WALL:
|
||||
return prefix + "WA6" + addit + ".BMP";
|
||||
return ImagePath::builtinTODO(prefix + "WA6" + addit + ".BMP");
|
||||
case EWallVisual::UPPER_TOWER:
|
||||
return prefix + "TW2" + addit + ".BMP";
|
||||
return ImagePath::builtinTODO(prefix + "TW2" + addit + ".BMP");
|
||||
case EWallVisual::GATE:
|
||||
return prefix + "DRW" + addit + ".BMP";
|
||||
return ImagePath::builtinTODO(prefix + "DRW" + addit + ".BMP");
|
||||
case EWallVisual::GATE_ARCH:
|
||||
return prefix + "ARCH.BMP";
|
||||
return ImagePath::builtinTODO(prefix + "ARCH.BMP");
|
||||
case EWallVisual::BOTTOM_STATIC_WALL:
|
||||
return prefix + "WA2.BMP";
|
||||
return ImagePath::builtinTODO(prefix + "WA2.BMP");
|
||||
case EWallVisual::UPPER_STATIC_WALL:
|
||||
return prefix + "WA5.BMP";
|
||||
return ImagePath::builtinTODO(prefix + "WA5.BMP");
|
||||
case EWallVisual::MOAT:
|
||||
return prefix + "MOAT.BMP";
|
||||
return ImagePath::builtinTODO(prefix + "MOAT.BMP");
|
||||
case EWallVisual::MOAT_BANK:
|
||||
return prefix + "MLIP.BMP";
|
||||
return ImagePath::builtinTODO(prefix + "MLIP.BMP");
|
||||
case EWallVisual::KEEP_BATTLEMENT:
|
||||
return prefix + "MANC.BMP";
|
||||
return ImagePath::builtinTODO(prefix + "MANC.BMP");
|
||||
case EWallVisual::BOTTOM_BATTLEMENT:
|
||||
return prefix + "TW1C.BMP";
|
||||
return ImagePath::builtinTODO(prefix + "TW1C.BMP");
|
||||
case EWallVisual::UPPER_BATTLEMENT:
|
||||
return prefix + "TW2C.BMP";
|
||||
return ImagePath::builtinTODO(prefix + "TW2C.BMP");
|
||||
default:
|
||||
return "";
|
||||
return ImagePath();
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,10 +120,10 @@ void BattleSiegeController::showWallPiece(Canvas & canvas, EWallVisual::EWallVis
|
||||
canvas.draw(wallPieceImages[what], Point(pos.x, pos.y));
|
||||
}
|
||||
|
||||
std::string BattleSiegeController::getBattleBackgroundName() const
|
||||
ImagePath BattleSiegeController::getBattleBackgroundName() const
|
||||
{
|
||||
const std::string & prefix = town->town->clientInfo.siegePrefix;
|
||||
return prefix + "BACK.BMP";
|
||||
return ImagePath::builtinTODO(prefix + "BACK.BMP");
|
||||
}
|
||||
|
||||
bool BattleSiegeController::getWallPieceExistance(EWallVisual::EWallVisual what) const
|
||||
@ -133,9 +135,9 @@ bool BattleSiegeController::getWallPieceExistance(EWallVisual::EWallVisual what)
|
||||
{
|
||||
case EWallVisual::MOAT: return town->hasBuilt(BuildingID::CITADEL) && town->town->clientInfo.siegePositions.at(EWallVisual::MOAT).isValid();
|
||||
case EWallVisual::MOAT_BANK: return town->hasBuilt(BuildingID::CITADEL) && town->town->clientInfo.siegePositions.at(EWallVisual::MOAT_BANK).isValid();
|
||||
case EWallVisual::KEEP_BATTLEMENT: return town->hasBuilt(BuildingID::CITADEL) && owner.curInt->cb->battleGetWallState(EWallPart::KEEP) != EWallState::DESTROYED;
|
||||
case EWallVisual::UPPER_BATTLEMENT: return town->hasBuilt(BuildingID::CASTLE) && owner.curInt->cb->battleGetWallState(EWallPart::UPPER_TOWER) != EWallState::DESTROYED;
|
||||
case EWallVisual::BOTTOM_BATTLEMENT: return town->hasBuilt(BuildingID::CASTLE) && owner.curInt->cb->battleGetWallState(EWallPart::BOTTOM_TOWER) != EWallState::DESTROYED;
|
||||
case EWallVisual::KEEP_BATTLEMENT: return town->hasBuilt(BuildingID::CITADEL) && owner.getBattle()->battleGetWallState(EWallPart::KEEP) != EWallState::DESTROYED;
|
||||
case EWallVisual::UPPER_BATTLEMENT: return town->hasBuilt(BuildingID::CASTLE) && owner.getBattle()->battleGetWallState(EWallPart::UPPER_TOWER) != EWallState::DESTROYED;
|
||||
case EWallVisual::BOTTOM_BATTLEMENT: return town->hasBuilt(BuildingID::CASTLE) && owner.getBattle()->battleGetWallState(EWallPart::BOTTOM_TOWER) != EWallState::DESTROYED;
|
||||
default: return true;
|
||||
}
|
||||
}
|
||||
@ -180,7 +182,7 @@ BattleSiegeController::BattleSiegeController(BattleInterface & owner, const CGTo
|
||||
if ( !getWallPieceExistance(EWallVisual::EWallVisual(g)) )
|
||||
continue;
|
||||
|
||||
wallPieceImages[g] = IImage::createFromFile(getWallPieceImageName(EWallVisual::EWallVisual(g), EWallState::REINFORCED));
|
||||
wallPieceImages[g] = GH.renderHandler().loadImage(getWallPieceImageName(EWallVisual::EWallVisual(g), EWallState::REINFORCED));
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,7 +222,7 @@ Point BattleSiegeController::getTurretCreaturePosition( BattleHex position ) con
|
||||
|
||||
void BattleSiegeController::gateStateChanged(const EGateState state)
|
||||
{
|
||||
auto oldState = owner.curInt->cb->battleGetGateState();
|
||||
auto oldState = owner.getBattle()->battleGetGateState();
|
||||
bool playSound = false;
|
||||
auto stateId = EWallState::NONE;
|
||||
switch(state)
|
||||
@ -246,7 +248,7 @@ void BattleSiegeController::gateStateChanged(const EGateState state)
|
||||
wallPieceImages[EWallVisual::GATE] = nullptr;
|
||||
|
||||
if (stateId != EWallState::NONE)
|
||||
wallPieceImages[EWallVisual::GATE] = IImage::createFromFile(getWallPieceImageName(EWallVisual::GATE, stateId));
|
||||
wallPieceImages[EWallVisual::GATE] = GH.renderHandler().loadImage(getWallPieceImageName(EWallVisual::GATE, stateId));
|
||||
|
||||
if (playSound)
|
||||
CCS->soundh->playSound(soundBase::DRAWBRG);
|
||||
@ -275,7 +277,7 @@ BattleHex BattleSiegeController::getTurretBattleHex(EWallVisual::EWallVisual wal
|
||||
|
||||
const CStack * BattleSiegeController::getTurretStack(EWallVisual::EWallVisual wallPiece) const
|
||||
{
|
||||
for (auto & stack : owner.curInt->cb->battleGetAllStacks(true))
|
||||
for (auto & stack : owner.getBattle()->battleGetAllStacks(true))
|
||||
{
|
||||
if ( stack->initialPosition == getTurretBattleHex(wallPiece))
|
||||
return stack;
|
||||
@ -318,15 +320,15 @@ bool BattleSiegeController::isAttackableByCatapult(BattleHex hex) const
|
||||
if (owner.tacticsMode)
|
||||
return false;
|
||||
|
||||
auto wallPart = owner.curInt->cb->battleHexToWallPart(hex);
|
||||
return owner.curInt->cb->isWallPartAttackable(wallPart);
|
||||
auto wallPart = owner.getBattle()->battleHexToWallPart(hex);
|
||||
return owner.getBattle()->isWallPartAttackable(wallPart);
|
||||
}
|
||||
|
||||
void BattleSiegeController::stackIsCatapulting(const CatapultAttack & ca)
|
||||
{
|
||||
if (ca.attacker != -1)
|
||||
{
|
||||
const CStack *stack = owner.curInt->cb->battleGetStackByID(ca.attacker);
|
||||
const CStack *stack = owner.getBattle()->battleGetStackByID(ca.attacker);
|
||||
for (auto attackInfo : ca.attackedParts)
|
||||
{
|
||||
owner.stacksController->addNewAnim(new CatapultAnimation(owner, stack, attackInfo.destinationTile, nullptr, attackInfo.damageDealt));
|
||||
@ -340,8 +342,8 @@ void BattleSiegeController::stackIsCatapulting(const CatapultAttack & ca)
|
||||
for (auto attackInfo : ca.attackedParts)
|
||||
positions.push_back(owner.stacksController->getStackPositionAtHex(attackInfo.destinationTile, nullptr) + Point(99, 120));
|
||||
|
||||
CCS->soundh->playSound( "WALLHIT" );
|
||||
owner.stacksController->addNewAnim(new EffectAnimation(owner, "SGEXPL.DEF", positions));
|
||||
CCS->soundh->playSound( AudioPath::builtin("WALLHIT") );
|
||||
owner.stacksController->addNewAnim(new EffectAnimation(owner, AnimationPath::builtin("SGEXPL.DEF"), positions));
|
||||
}
|
||||
|
||||
owner.waitForAnimations();
|
||||
@ -353,9 +355,9 @@ void BattleSiegeController::stackIsCatapulting(const CatapultAttack & ca)
|
||||
if (wallId == EWallVisual::GATE)
|
||||
continue;
|
||||
|
||||
auto wallState = EWallState(owner.curInt->cb->battleGetWallState(attackInfo.attackedPart));
|
||||
auto wallState = EWallState(owner.getBattle()->battleGetWallState(attackInfo.attackedPart));
|
||||
|
||||
wallPieceImages[wallId] = IImage::createFromFile(getWallPieceImageName(EWallVisual::EWallVisual(wallId), wallState));
|
||||
wallPieceImages[wallId] = GH.renderHandler().loadImage(getWallPieceImageName(EWallVisual::EWallVisual(wallId), wallState));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "../../lib/GameConstants.h"
|
||||
#include "../../lib/battle/BattleHex.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@ -76,7 +77,7 @@ class BattleSiegeController
|
||||
std::array<std::shared_ptr<IImage>, EWallVisual::WALL_LAST + 1> wallPieceImages;
|
||||
|
||||
/// return URI for image for a wall piece
|
||||
std::string getWallPieceImageName(EWallVisual::EWallVisual what, EWallState state) const;
|
||||
ImagePath getWallPieceImageName(EWallVisual::EWallVisual what, EWallState state) const;
|
||||
|
||||
/// returns BattleHex to which chosen wall piece is bound
|
||||
BattleHex getWallPiecePosition(EWallVisual::EWallVisual what) const;
|
||||
@ -102,7 +103,7 @@ public:
|
||||
|
||||
/// queries from other battle controllers
|
||||
bool isAttackableByCatapult(BattleHex hex) const;
|
||||
std::string getBattleBackgroundName() const;
|
||||
ImagePath getBattleBackgroundName() const;
|
||||
const CCreature *getTurretCreature() const;
|
||||
Point getTurretCreaturePosition( BattleHex position ) const;
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../render/Colors.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/spells/ISpellMechanics.h"
|
||||
@ -76,10 +77,10 @@ BattleStacksController::BattleStacksController(BattleInterface & owner):
|
||||
animIDhelper(0)
|
||||
{
|
||||
//preparing graphics for displaying amounts of creatures
|
||||
amountNormal = IImage::createFromFile("CMNUMWIN.BMP", EImageBlitMode::COLORKEY);
|
||||
amountPositive = IImage::createFromFile("CMNUMWIN.BMP", EImageBlitMode::COLORKEY);
|
||||
amountNegative = IImage::createFromFile("CMNUMWIN.BMP", EImageBlitMode::COLORKEY);
|
||||
amountEffNeutral = IImage::createFromFile("CMNUMWIN.BMP", EImageBlitMode::COLORKEY);
|
||||
amountNormal = GH.renderHandler().loadImage(ImagePath::builtin("CMNUMWIN.BMP"), EImageBlitMode::COLORKEY);
|
||||
amountPositive = GH.renderHandler().loadImage(ImagePath::builtin("CMNUMWIN.BMP"), EImageBlitMode::COLORKEY);
|
||||
amountNegative = GH.renderHandler().loadImage(ImagePath::builtin("CMNUMWIN.BMP"), EImageBlitMode::COLORKEY);
|
||||
amountEffNeutral = GH.renderHandler().loadImage(ImagePath::builtin("CMNUMWIN.BMP"), EImageBlitMode::COLORKEY);
|
||||
|
||||
static const auto shifterNormal = ColorFilter::genRangeShifter( 0.f, 0.f, 0.f, 0.6f, 0.2f, 1.0f );
|
||||
static const auto shifterPositive = ColorFilter::genRangeShifter( 0.f, 0.f, 0.f, 0.2f, 1.0f, 0.2f );
|
||||
@ -94,7 +95,7 @@ BattleStacksController::BattleStacksController(BattleInterface & owner):
|
||||
amountNegative->adjustPalette(shifterNegative, ignoredMask);
|
||||
amountEffNeutral->adjustPalette(shifterNeutral, ignoredMask);
|
||||
|
||||
std::vector<const CStack*> stacks = owner.curInt->cb->battleGetAllStacks(true);
|
||||
std::vector<const CStack*> stacks = owner.getBattle()->battleGetAllStacks(true);
|
||||
for(const CStack * s : stacks)
|
||||
{
|
||||
stackAdded(s, true);
|
||||
@ -126,7 +127,7 @@ BattleHex BattleStacksController::getStackCurrentPosition(const CStack * stack)
|
||||
|
||||
void BattleStacksController::collectRenderableObjects(BattleRenderer & renderer)
|
||||
{
|
||||
auto stacks = owner.curInt->cb->battleGetAllStacks(false);
|
||||
auto stacks = owner.getBattle()->battleGetAllStacks(false);
|
||||
|
||||
for (auto stack : stacks)
|
||||
{
|
||||
@ -359,7 +360,7 @@ void BattleStacksController::initializeBattleAnimations()
|
||||
|
||||
void BattleStacksController::tickFrameBattleAnimations(uint32_t msPassed)
|
||||
{
|
||||
for (auto stack : owner.curInt->cb->battleGetAllStacks(true))
|
||||
for (auto stack : owner.getBattle()->battleGetAllStacks(true))
|
||||
{
|
||||
if (stackAnimation.find(stack->unitId()) == stackAnimation.end()) //e.g. for summoned but not yet handled stacks
|
||||
continue;
|
||||
@ -462,7 +463,7 @@ void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> at
|
||||
addNewAnim(new HittedAnimation(owner, attackedInfo.defender));
|
||||
|
||||
if (attackedInfo.fireShield)
|
||||
owner.effectsController->displayEffect(EBattleEffect::FIRE_SHIELD, "FIRESHIE", attackedInfo.attacker->getPosition());
|
||||
owner.effectsController->displayEffect(EBattleEffect::FIRE_SHIELD, AudioPath::builtin("FIRESHIE"), attackedInfo.attacker->getPosition());
|
||||
|
||||
if (attackedInfo.spellEffect != SpellID::NONE)
|
||||
{
|
||||
@ -481,7 +482,7 @@ void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> at
|
||||
if (attackedInfo.rebirth)
|
||||
{
|
||||
owner.addToAnimationStage(EAnimationEvents::AFTER_HIT, [=](){
|
||||
owner.effectsController->displayEffect(EBattleEffect::RESURRECT, "RESURECT", attackedInfo.defender->getPosition());
|
||||
owner.effectsController->displayEffect(EBattleEffect::RESURRECT, AudioPath::builtin("RESURECT"), attackedInfo.defender->getPosition());
|
||||
addNewAnim(new ResurrectionAnimation(owner, attackedInfo.defender));
|
||||
});
|
||||
}
|
||||
@ -552,9 +553,7 @@ void BattleStacksController::stackMoved(const CStack *stack, std::vector<BattleH
|
||||
|
||||
bool BattleStacksController::shouldAttackFacingRight(const CStack * attacker, const CStack * defender)
|
||||
{
|
||||
bool mustReverse = owner.curInt->cb->isToReverse(
|
||||
attacker,
|
||||
defender);
|
||||
bool mustReverse = owner.getBattle()->isToReverse(attacker, defender);
|
||||
|
||||
if (attacker->unitSide() == BattleSide::ATTACKER)
|
||||
return !mustReverse;
|
||||
@ -594,7 +593,7 @@ void BattleStacksController::stackAttacking( const StackAttackInfo & info )
|
||||
{
|
||||
owner.addToAnimationStage(EAnimationEvents::BEFORE_HIT, [=]() {
|
||||
owner.appendBattleLog(info.attacker->formatGeneralMessage(-45));
|
||||
owner.effectsController->displayEffect(EBattleEffect::GOOD_LUCK, "GOODLUCK", attacker->getPosition());
|
||||
owner.effectsController->displayEffect(EBattleEffect::GOOD_LUCK, AudioPath::builtin("GOODLUCK"), attacker->getPosition());
|
||||
});
|
||||
}
|
||||
|
||||
@ -602,7 +601,7 @@ void BattleStacksController::stackAttacking( const StackAttackInfo & info )
|
||||
{
|
||||
owner.addToAnimationStage(EAnimationEvents::BEFORE_HIT, [=]() {
|
||||
owner.appendBattleLog(info.attacker->formatGeneralMessage(-44));
|
||||
owner.effectsController->displayEffect(EBattleEffect::BAD_LUCK, "BADLUCK", attacker->getPosition());
|
||||
owner.effectsController->displayEffect(EBattleEffect::BAD_LUCK, AudioPath::builtin("BADLUCK"), attacker->getPosition());
|
||||
});
|
||||
}
|
||||
|
||||
@ -610,7 +609,7 @@ void BattleStacksController::stackAttacking( const StackAttackInfo & info )
|
||||
{
|
||||
owner.addToAnimationStage(EAnimationEvents::BEFORE_HIT, [=]() {
|
||||
owner.appendBattleLog(info.attacker->formatGeneralMessage(365));
|
||||
owner.effectsController->displayEffect(EBattleEffect::DEATH_BLOW, "DEATHBLO", defender->getPosition());
|
||||
owner.effectsController->displayEffect(EBattleEffect::DEATH_BLOW, AudioPath::builtin("DEATHBLO"), defender->getPosition());
|
||||
});
|
||||
|
||||
for(auto elem : info.secondaryDefender)
|
||||
@ -645,7 +644,7 @@ void BattleStacksController::stackAttacking( const StackAttackInfo & info )
|
||||
{
|
||||
owner.addToAnimationStage(EAnimationEvents::AFTER_HIT, [=]()
|
||||
{
|
||||
owner.effectsController->displayEffect(EBattleEffect::DRAIN_LIFE, "DRAINLIF", attacker->getPosition());
|
||||
owner.effectsController->displayEffect(EBattleEffect::DRAIN_LIFE, AudioPath::builtin("DRAINLIF"), attacker->getPosition());
|
||||
});
|
||||
}
|
||||
|
||||
@ -670,7 +669,7 @@ void BattleStacksController::endAction(const BattleAction & action)
|
||||
owner.checkForAnimations();
|
||||
|
||||
//check if we should reverse stacks
|
||||
TStacks stacks = owner.curInt->cb->battleGetStacks(CBattleCallback::MINE_AND_ENEMY);
|
||||
TStacks stacks = owner.getBattle()->battleGetStacks(CPlayerBattleCallback::MINE_AND_ENEMY);
|
||||
|
||||
for (const CStack *s : stacks)
|
||||
{
|
||||
@ -847,7 +846,7 @@ std::vector<const CStack *> BattleStacksController::selectHoveredStacks()
|
||||
auto hoveredQueueUnitId = owner.windowObject->getQueueHoveredUnitId();
|
||||
if(hoveredQueueUnitId.has_value())
|
||||
{
|
||||
return { owner.curInt->cb->battleGetStackByID(hoveredQueueUnitId.value(), true) };
|
||||
return { owner.getBattle()->battleGetStackByID(hoveredQueueUnitId.value(), true) };
|
||||
}
|
||||
|
||||
auto hoveredHex = owner.fieldController->getHoveredHex();
|
||||
@ -867,14 +866,14 @@ std::vector<const CStack *> BattleStacksController::selectHoveredStacks()
|
||||
spells::Target target;
|
||||
target.emplace_back(hoveredHex);
|
||||
|
||||
spells::BattleCast event(owner.curInt->cb.get(), caster, mode, spell);
|
||||
spells::BattleCast event(owner.getBattle().get(), caster, mode, spell);
|
||||
auto mechanics = spell->battleMechanics(&event);
|
||||
return mechanics->getAffectedStacks(target);
|
||||
}
|
||||
|
||||
if(hoveredHex.isValid())
|
||||
{
|
||||
const CStack * const stack = owner.curInt->cb->battleGetStackByPos(hoveredHex, true);
|
||||
const CStack * const stack = owner.getBattle()->battleGetStackByPos(hoveredHex, true);
|
||||
|
||||
if (stack)
|
||||
return {stack};
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "../windows/CMessage.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
#include "../adventureMap/CInGameConsole.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
@ -37,7 +38,7 @@
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../lib/CStack.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/filesystem/ResourceID.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
#include "../windows/settings/SettingsMainWindow.h"
|
||||
|
||||
BattleWindow::BattleWindow(BattleInterface & owner):
|
||||
@ -51,7 +52,7 @@ BattleWindow::BattleWindow(BattleInterface & owner):
|
||||
|
||||
REGISTER_BUILDER("battleConsole", &BattleWindow::buildBattleConsole);
|
||||
|
||||
const JsonNode config(ResourceID("config/widgets/BattleWindow2.json"));
|
||||
const JsonNode config(JsonPath::builtin("config/widgets/BattleWindow2.json"));
|
||||
|
||||
addShortcut(EShortcut::GLOBAL_OPTIONS, std::bind(&BattleWindow::bOptionsf, this));
|
||||
addShortcut(EShortcut::BATTLE_SURRENDER, std::bind(&BattleWindow::bSurrenderf, this));
|
||||
@ -367,10 +368,10 @@ void BattleWindow::bSurrenderf()
|
||||
if (owner.actionsController->spellcastingModeActive())
|
||||
return;
|
||||
|
||||
int cost = owner.curInt->cb->battleGetSurrenderCost();
|
||||
int cost = owner.getBattle()->battleGetSurrenderCost();
|
||||
if(cost >= 0)
|
||||
{
|
||||
std::string enemyHeroName = owner.curInt->cb->battleGetEnemyHero().name;
|
||||
std::string enemyHeroName = owner.getBattle()->battleGetEnemyHero().name;
|
||||
if(enemyHeroName.empty())
|
||||
{
|
||||
logGlobal->warn("Surrender performed without enemy hero, should not happen!");
|
||||
@ -387,7 +388,7 @@ void BattleWindow::bFleef()
|
||||
if (owner.actionsController->spellcastingModeActive())
|
||||
return;
|
||||
|
||||
if ( owner.curInt->cb->battleCanFlee() )
|
||||
if ( owner.getBattle()->battleCanFlee() )
|
||||
{
|
||||
CFunctionList<void()> ony = std::bind(&BattleWindow::reallyFlee,this);
|
||||
owner.curInt->showYesNoDialog(CGI->generaltexth->allTexts[28], ony, nullptr); //Are you sure you want to retreat?
|
||||
@ -398,10 +399,10 @@ void BattleWindow::bFleef()
|
||||
std::string heroName;
|
||||
//calculating fleeing hero's name
|
||||
if (owner.attackingHeroInstance)
|
||||
if (owner.attackingHeroInstance->tempOwner == owner.curInt->cb->getMyColor())
|
||||
if (owner.attackingHeroInstance->tempOwner == owner.curInt->cb->getPlayerID())
|
||||
heroName = owner.attackingHeroInstance->getNameTranslated();
|
||||
if (owner.defendingHeroInstance)
|
||||
if (owner.defendingHeroInstance->tempOwner == owner.curInt->cb->getMyColor())
|
||||
if (owner.defendingHeroInstance->tempOwner == owner.curInt->cb->getPlayerID())
|
||||
heroName = owner.defendingHeroInstance->getNameTranslated();
|
||||
//calculating text
|
||||
auto txt = boost::format(CGI->generaltexth->allTexts[340]) % heroName; //The Shackles of War are present. %s can not retreat!
|
||||
@ -419,7 +420,7 @@ void BattleWindow::reallyFlee()
|
||||
|
||||
void BattleWindow::reallySurrender()
|
||||
{
|
||||
if (owner.curInt->cb->getResourceAmount(EGameResID::GOLD) < owner.curInt->cb->battleGetSurrenderCost())
|
||||
if (owner.curInt->cb->getResourceAmount(EGameResID::GOLD) < owner.getBattle()->battleGetSurrenderCost())
|
||||
{
|
||||
owner.curInt->showInfoDialog(CGI->generaltexth->allTexts[29]); //You don't have enough gold!
|
||||
}
|
||||
@ -436,23 +437,23 @@ void BattleWindow::showAlternativeActionIcon(PossiblePlayerBattleAction action)
|
||||
if(!w)
|
||||
return;
|
||||
|
||||
std::string iconName = variables["actionIconDefault"].String();
|
||||
AnimationPath iconName = AnimationPath::fromJson(variables["actionIconDefault"]);
|
||||
switch(action.get())
|
||||
{
|
||||
case PossiblePlayerBattleAction::ATTACK:
|
||||
iconName = variables["actionIconAttack"].String();
|
||||
iconName = AnimationPath::fromJson(variables["actionIconAttack"]);
|
||||
break;
|
||||
|
||||
case PossiblePlayerBattleAction::SHOOT:
|
||||
iconName = variables["actionIconShoot"].String();
|
||||
iconName = AnimationPath::fromJson(variables["actionIconShoot"]);
|
||||
break;
|
||||
|
||||
case PossiblePlayerBattleAction::AIMED_SPELL_CREATURE:
|
||||
iconName = variables["actionIconSpell"].String();
|
||||
iconName = AnimationPath::fromJson(variables["actionIconSpell"]);
|
||||
break;
|
||||
|
||||
case PossiblePlayerBattleAction::ANY_LOCATION:
|
||||
iconName = variables["actionIconSpell"].String();
|
||||
iconName = AnimationPath::fromJson(variables["actionIconSpell"]);
|
||||
break;
|
||||
|
||||
//TODO: figure out purpose of this icon
|
||||
@ -461,15 +462,15 @@ void BattleWindow::showAlternativeActionIcon(PossiblePlayerBattleAction action)
|
||||
//break;
|
||||
|
||||
case PossiblePlayerBattleAction::ATTACK_AND_RETURN:
|
||||
iconName = variables["actionIconReturn"].String();
|
||||
iconName = AnimationPath::fromJson(variables["actionIconReturn"]);
|
||||
break;
|
||||
|
||||
case PossiblePlayerBattleAction::WALK_AND_ATTACK:
|
||||
iconName = variables["actionIconNoReturn"].String();
|
||||
iconName = AnimationPath::fromJson(variables["actionIconNoReturn"]);
|
||||
break;
|
||||
}
|
||||
|
||||
auto anim = std::make_shared<CAnimation>(iconName);
|
||||
auto anim = GH.renderHandler().loadAnimation(iconName);
|
||||
w->setImage(anim);
|
||||
w->redraw();
|
||||
}
|
||||
@ -509,7 +510,7 @@ void BattleWindow::bAutofightf()
|
||||
autocombatPreferences.enableSpellsUsage = settings["battle"]["enableAutocombatSpells"].Bool();
|
||||
|
||||
ai->initBattleInterface(owner.curInt->env, owner.curInt->cb, autocombatPreferences);
|
||||
ai->battleStart(owner.army1, owner.army2, int3(0,0,0), owner.attackingHeroInstance, owner.defendingHeroInstance, owner.curInt->cb->battleGetMySide(), false);
|
||||
ai->battleStart(owner.getBattleID(), owner.army1, owner.army2, int3(0,0,0), owner.attackingHeroInstance, owner.defendingHeroInstance, owner.getBattle()->battleGetMySide(), false);
|
||||
owner.curInt->autofightingAI = ai;
|
||||
owner.curInt->cb->registerBattleInterface(ai);
|
||||
|
||||
@ -531,7 +532,7 @@ void BattleWindow::bSpellf()
|
||||
|
||||
CCS->curh->set(Cursor::Map::POINTER);
|
||||
|
||||
ESpellCastProblem spellCastProblem = owner.curInt->cb->battleCanCastSpell(myHero, spells::Mode::HERO);
|
||||
ESpellCastProblem spellCastProblem = owner.getBattle()->battleCanCastSpell(myHero, spells::Mode::HERO);
|
||||
|
||||
if(spellCastProblem == ESpellCastProblem::OK)
|
||||
{
|
||||
@ -633,11 +634,11 @@ void BattleWindow::bTacticPhaseEnd()
|
||||
void BattleWindow::blockUI(bool on)
|
||||
{
|
||||
bool canCastSpells = false;
|
||||
auto hero = owner.curInt->cb->battleGetMyHero();
|
||||
auto hero = owner.getBattle()->battleGetMyHero();
|
||||
|
||||
if(hero)
|
||||
{
|
||||
ESpellCastProblem spellcastingProblem = owner.curInt->cb->battleCanCastSpell(hero, spells::Mode::HERO);
|
||||
ESpellCastProblem spellcastingProblem = owner.getBattle()->battleCanCastSpell(hero, spells::Mode::HERO);
|
||||
|
||||
//if magic is blocked, we leave button active, so the message can be displayed after button click
|
||||
canCastSpells = spellcastingProblem == ESpellCastProblem::OK || spellcastingProblem == ESpellCastProblem::MAGIC_IS_BLOCKED;
|
||||
@ -646,8 +647,8 @@ void BattleWindow::blockUI(bool on)
|
||||
bool canWait = owner.stacksController->getActiveStack() ? !owner.stacksController->getActiveStack()->waitedThisTurn : false;
|
||||
|
||||
setShortcutBlocked(EShortcut::GLOBAL_OPTIONS, on);
|
||||
setShortcutBlocked(EShortcut::BATTLE_RETREAT, on || !owner.curInt->cb->battleCanFlee());
|
||||
setShortcutBlocked(EShortcut::BATTLE_SURRENDER, on || owner.curInt->cb->battleGetSurrenderCost() < 0);
|
||||
setShortcutBlocked(EShortcut::BATTLE_RETREAT, on || !owner.getBattle()->battleCanFlee());
|
||||
setShortcutBlocked(EShortcut::BATTLE_SURRENDER, on || owner.getBattle()->battleGetSurrenderCost() < 0);
|
||||
setShortcutBlocked(EShortcut::BATTLE_CAST_SPELL, on || owner.tacticsMode || !canCastSpells);
|
||||
setShortcutBlocked(EShortcut::BATTLE_WAIT, on || owner.tacticsMode || !canWait);
|
||||
setShortcutBlocked(EShortcut::BATTLE_DEFEND, on || owner.tacticsMode);
|
||||
|
@ -13,8 +13,10 @@
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/ColorFilter.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
|
||||
static const ColorRGBA creatureBlueBorder = { 0, 255, 255, 255 };
|
||||
static const ColorRGBA creatureGoldBorder = { 255, 255, 0, 255 };
|
||||
@ -185,7 +187,7 @@ void CreatureAnimation::setType(ECreatureAnimType type)
|
||||
speed = speedController(this, type);
|
||||
}
|
||||
|
||||
CreatureAnimation::CreatureAnimation(const std::string & name_, TSpeedController controller)
|
||||
CreatureAnimation::CreatureAnimation(const AnimationPath & name_, TSpeedController controller)
|
||||
: name(name_),
|
||||
speed(0.1f),
|
||||
shadowAlpha(128),
|
||||
@ -196,8 +198,8 @@ CreatureAnimation::CreatureAnimation(const std::string & name_, TSpeedController
|
||||
speedController(controller),
|
||||
once(false)
|
||||
{
|
||||
forward = std::make_shared<CAnimation>(name_);
|
||||
reverse = std::make_shared<CAnimation>(name_);
|
||||
forward = GH.renderHandler().loadAnimation(name_);
|
||||
reverse = GH.renderHandler().loadAnimation(name_);
|
||||
|
||||
//todo: optimize
|
||||
forward->preload();
|
||||
|
@ -70,7 +70,7 @@ public:
|
||||
using TSpeedController = std::function<float(CreatureAnimation *, ECreatureAnimType)>;
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
AnimationPath name;
|
||||
|
||||
/// animation for rendering stack in default orientation - facing right
|
||||
std::shared_ptr<CAnimation> forward;
|
||||
@ -122,7 +122,7 @@ public:
|
||||
/// name - path to .def file, relative to SPRITES/ directory
|
||||
/// controller - function that will return for how long *each* frame
|
||||
/// in specified group of animation should be played, measured in seconds
|
||||
CreatureAnimation(const std::string & name_, TSpeedController speedController);
|
||||
CreatureAnimation(const AnimationPath & name_, TSpeedController speedController);
|
||||
|
||||
/// sets type of animation and resets framecount
|
||||
void setType(ECreatureAnimType type);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "../render/IFont.h"
|
||||
#include "../render/EFont.h"
|
||||
#include "../renderSDL/ScreenHandler.h"
|
||||
#include "../renderSDL/RenderHandler.h"
|
||||
#include "../CMT.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../battle/BattleInterface.h"
|
||||
@ -75,6 +76,7 @@ void CGuiHandler::init()
|
||||
eventDispatcherInstance = std::make_unique<EventDispatcher>();
|
||||
windowHandlerInstance = std::make_unique<WindowHandler>();
|
||||
screenHandlerInstance = std::make_unique<ScreenHandler>();
|
||||
renderHandlerInstance = std::make_unique<RenderHandler>();
|
||||
shortcutsHandlerInstance = std::make_unique<ShortcutHandler>();
|
||||
framerateManagerInstance = std::make_unique<FramerateManager>(settings["video"]["targetfps"].Integer());
|
||||
}
|
||||
@ -206,6 +208,11 @@ IScreenHandler & CGuiHandler::screenHandler()
|
||||
return *screenHandlerInstance;
|
||||
}
|
||||
|
||||
IRenderHandler & CGuiHandler::renderHandler()
|
||||
{
|
||||
return *renderHandlerInstance;
|
||||
}
|
||||
|
||||
EventDispatcher & CGuiHandler::events()
|
||||
{
|
||||
return *eventDispatcherInstance;
|
||||
|
@ -22,6 +22,7 @@ class IStatusBar;
|
||||
class CIntObject;
|
||||
class IUpdateable;
|
||||
class IShowActivatable;
|
||||
class IRenderHandler;
|
||||
class IScreenHandler;
|
||||
class WindowHandler;
|
||||
class EventDispatcher;
|
||||
@ -41,6 +42,7 @@ private:
|
||||
std::unique_ptr<WindowHandler> windowHandlerInstance;
|
||||
|
||||
std::unique_ptr<IScreenHandler> screenHandlerInstance;
|
||||
std::unique_ptr<IRenderHandler> renderHandlerInstance;
|
||||
std::unique_ptr<FramerateManager> framerateManagerInstance;
|
||||
std::unique_ptr<EventDispatcher> eventDispatcherInstance;
|
||||
std::unique_ptr<InputHandler> inputHandlerInstance;
|
||||
@ -67,7 +69,7 @@ public:
|
||||
void stopTextInput();
|
||||
|
||||
IScreenHandler & screenHandler();
|
||||
|
||||
IRenderHandler & renderHandler();
|
||||
WindowHandler & windows();
|
||||
|
||||
/// Returns currently active status bar. Guaranteed to be non-null
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "../renderSDL/CursorHardware.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
|
||||
@ -46,10 +47,10 @@ CursorHandler::CursorHandler()
|
||||
|
||||
cursors =
|
||||
{
|
||||
std::make_unique<CAnimation>("CRADVNTR"),
|
||||
std::make_unique<CAnimation>("CRCOMBAT"),
|
||||
std::make_unique<CAnimation>("CRDEFLT"),
|
||||
std::make_unique<CAnimation>("CRSPELL")
|
||||
GH.renderHandler().loadAnimation(AnimationPath::builtin("CRADVNTR")),
|
||||
GH.renderHandler().loadAnimation(AnimationPath::builtin("CRCOMBAT")),
|
||||
GH.renderHandler().loadAnimation(AnimationPath::builtin("CRDEFLT")),
|
||||
GH.renderHandler().loadAnimation(AnimationPath::builtin("CRSPELL"))
|
||||
};
|
||||
|
||||
for (auto & cursor : cursors)
|
||||
@ -100,11 +101,11 @@ void CursorHandler::dragAndDropCursor(std::shared_ptr<IImage> image)
|
||||
cursor->setImage(getCurrentImage(), getPivotOffset());
|
||||
}
|
||||
|
||||
void CursorHandler::dragAndDropCursor (std::string path, size_t index)
|
||||
void CursorHandler::dragAndDropCursor (const AnimationPath & path, size_t index)
|
||||
{
|
||||
CAnimation anim(path);
|
||||
anim.load(index);
|
||||
dragAndDropCursor(anim.getImage(index));
|
||||
auto anim = GH.renderHandler().loadAnimation(path);
|
||||
anim->load(index);
|
||||
dragAndDropCursor(anim->getImage(index));
|
||||
}
|
||||
|
||||
void CursorHandler::cursorMove(const int & x, const int & y)
|
||||
|
@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/Point.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
|
||||
class ICursor;
|
||||
class IImage;
|
||||
@ -113,7 +114,7 @@ class CursorHandler final
|
||||
{
|
||||
std::shared_ptr<IImage> dndObject; //if set, overrides currentCursor
|
||||
|
||||
std::array<std::unique_ptr<CAnimation>, 4> cursors;
|
||||
std::array<std::shared_ptr<CAnimation>, 4> cursors;
|
||||
|
||||
bool showing;
|
||||
|
||||
@ -143,7 +144,7 @@ public:
|
||||
/// @param image Image to replace cursor with or nullptr to use the normal cursor.
|
||||
void dragAndDropCursor(std::shared_ptr<IImage> image);
|
||||
|
||||
void dragAndDropCursor(std::string path, size_t index);
|
||||
void dragAndDropCursor(const AnimationPath & path, size_t index);
|
||||
|
||||
/// Changes cursor to specified index
|
||||
void set(Cursor::Default index);
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
#include "../../lib//constants/StringConstants.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/filesystem/ResourceID.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
|
||||
InterfaceObjectConfigurable::InterfaceObjectConfigurable(const JsonNode & config, int used, Point offset):
|
||||
InterfaceObjectConfigurable(used, offset)
|
||||
@ -110,7 +110,7 @@ void InterfaceObjectConfigurable::build(const JsonNode &config)
|
||||
{
|
||||
if (!config["library"].isNull())
|
||||
{
|
||||
const JsonNode library(ResourceID(config["library"].String()));
|
||||
const JsonNode library(JsonPath::fromJson(config["library"]));
|
||||
loadCustomBuilders(library);
|
||||
}
|
||||
|
||||
@ -238,7 +238,7 @@ PlayerColor InterfaceObjectConfigurable::readPlayerColor(const JsonNode & config
|
||||
{
|
||||
logGlobal->debug("Reading PlayerColor");
|
||||
if(!config.isNull() && config.isString())
|
||||
return PlayerColor(vstd::find_pos(GameConstants::PLAYER_COLOR_NAMES, config.String()));
|
||||
return PlayerColor::decode(config.String());
|
||||
|
||||
logGlobal->debug("Unknown PlayerColor attribute");
|
||||
return PlayerColor::CANNOT_DETERMINE;
|
||||
@ -305,7 +305,7 @@ EShortcut InterfaceObjectConfigurable::readHotkey(const JsonNode & config) const
|
||||
std::shared_ptr<CPicture> InterfaceObjectConfigurable::buildPicture(const JsonNode & config) const
|
||||
{
|
||||
logGlobal->debug("Building widget CPicture");
|
||||
auto image = config["image"].String();
|
||||
auto image = ImagePath::fromJson(config["image"]);
|
||||
auto position = readPosition(config["position"]);
|
||||
auto pic = std::make_shared<CPicture>(image, position.x, position.y);
|
||||
if(!config["visible"].isNull())
|
||||
@ -369,7 +369,7 @@ std::shared_ptr<CToggleButton> InterfaceObjectConfigurable::buildToggleButton(co
|
||||
{
|
||||
logGlobal->debug("Building widget CToggleButton");
|
||||
auto position = readPosition(config["position"]);
|
||||
auto image = config["image"].String();
|
||||
auto image = AnimationPath::fromJson(config["image"]);
|
||||
auto help = readHintText(config["help"]);
|
||||
auto button = std::make_shared<CToggleButton>(position, image, help);
|
||||
if(!config["items"].isNull())
|
||||
@ -395,7 +395,7 @@ std::shared_ptr<CButton> InterfaceObjectConfigurable::buildButton(const JsonNode
|
||||
{
|
||||
logGlobal->debug("Building widget CButton");
|
||||
auto position = readPosition(config["position"]);
|
||||
auto image = config["image"].String();
|
||||
auto image = AnimationPath::fromJson(config["image"]);
|
||||
auto help = readHintText(config["help"]);
|
||||
auto button = std::make_shared<CButton>(position, image, help);
|
||||
if(!config["items"].isNull())
|
||||
@ -522,7 +522,7 @@ std::shared_ptr<CAnimImage> InterfaceObjectConfigurable::buildImage(const JsonNo
|
||||
{
|
||||
logGlobal->debug("Building widget CAnimImage");
|
||||
auto position = readPosition(config["position"]);
|
||||
auto image = config["image"].String();
|
||||
auto image = AnimationPath::fromJson(config["image"]);
|
||||
int group = config["group"].isNull() ? 0 : config["group"].Integer();
|
||||
int frame = config["frame"].isNull() ? 0 : config["frame"].Integer();
|
||||
return std::make_shared<CAnimImage>(image, frame, group, position.x, position.y);
|
||||
@ -531,7 +531,7 @@ std::shared_ptr<CAnimImage> InterfaceObjectConfigurable::buildImage(const JsonNo
|
||||
std::shared_ptr<CFilledTexture> InterfaceObjectConfigurable::buildTexture(const JsonNode & config) const
|
||||
{
|
||||
logGlobal->debug("Building widget CFilledTexture");
|
||||
auto image = config["image"].String();
|
||||
auto image = ImagePath::fromJson(config["image"]);
|
||||
auto rect = readRect(config["rect"]);
|
||||
auto playerColor = readPlayerColor(config["color"]);
|
||||
if(playerColor.isValidPlayer())
|
||||
@ -546,7 +546,7 @@ std::shared_ptr<ComboBox> InterfaceObjectConfigurable::buildComboBox(const JsonN
|
||||
{
|
||||
logGlobal->debug("Building widget ComboBox");
|
||||
auto position = readPosition(config["position"]);
|
||||
auto image = config["image"].String();
|
||||
auto image = AnimationPath::fromJson(config["image"]);
|
||||
auto help = readHintText(config["help"]);
|
||||
auto result = std::make_shared<ComboBox>(position, image, help, config["dropDown"]);
|
||||
if(!config["items"].isNull())
|
||||
@ -573,7 +573,7 @@ std::shared_ptr<CTextInput> InterfaceObjectConfigurable::buildTextInput(const Js
|
||||
logGlobal->debug("Building widget CTextInput");
|
||||
auto rect = readRect(config["rect"]);
|
||||
auto offset = readPosition(config["backgroundOffset"]);
|
||||
auto bgName = config["background"].String();
|
||||
auto bgName = ImagePath::fromJson(config["background"]);
|
||||
auto result = std::make_shared<CTextInput>(rect, offset, bgName, 0);
|
||||
if(!config["alignment"].isNull())
|
||||
result->alignment = readTextAlignment(config["alignment"]);
|
||||
@ -664,7 +664,7 @@ std::shared_ptr<CShowableAnim> InterfaceObjectConfigurable::buildAnimation(const
|
||||
{
|
||||
logGlobal->debug("Building widget CShowableAnim");
|
||||
auto position = readPosition(config["position"]);
|
||||
auto image = config["image"].String();
|
||||
auto image = AnimationPath::fromJson(config["image"]);
|
||||
ui8 flags = 0;
|
||||
if(!config["repeat"].Bool())
|
||||
flags |= CShowableAnim::EFlags::PLAY_ONCE;
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "../windows/GUIClasses.h"
|
||||
#include "../windows/InfoWindows.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/Graphics.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
@ -65,18 +66,17 @@ CBonusSelection::CBonusSelection()
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
|
||||
std::string bgName = getCampaign()->getRegions().getBackgroundName();
|
||||
setBackground(bgName);
|
||||
setBackground(getCampaign()->getRegions().getBackgroundName());
|
||||
|
||||
panelBackground = std::make_shared<CPicture>("CAMPBRF.BMP", 456, 6);
|
||||
panelBackground = std::make_shared<CPicture>(ImagePath::builtin("CAMPBRF.BMP"), 456, 6);
|
||||
|
||||
buttonStart = std::make_shared<CButton>(Point(475, 536), "CBBEGIB.DEF", CButton::tooltip(), std::bind(&CBonusSelection::startMap, this), EShortcut::GLOBAL_ACCEPT);
|
||||
buttonRestart = std::make_shared<CButton>(Point(475, 536), "CBRESTB.DEF", CButton::tooltip(), std::bind(&CBonusSelection::restartMap, this), EShortcut::GLOBAL_ACCEPT);
|
||||
buttonBack = std::make_shared<CButton>(Point(624, 536), "CBCANCB.DEF", CButton::tooltip(), std::bind(&CBonusSelection::goBack, this), EShortcut::GLOBAL_CANCEL);
|
||||
buttonStart = std::make_shared<CButton>(Point(475, 536), AnimationPath::builtin("CBBEGIB.DEF"), CButton::tooltip(), std::bind(&CBonusSelection::startMap, this), EShortcut::GLOBAL_ACCEPT);
|
||||
buttonRestart = std::make_shared<CButton>(Point(475, 536), AnimationPath::builtin("CBRESTB.DEF"), CButton::tooltip(), std::bind(&CBonusSelection::restartMap, this), EShortcut::GLOBAL_ACCEPT);
|
||||
buttonBack = std::make_shared<CButton>(Point(624, 536), AnimationPath::builtin("CBCANCB.DEF"), CButton::tooltip(), std::bind(&CBonusSelection::goBack, this), EShortcut::GLOBAL_CANCEL);
|
||||
|
||||
campaignName = std::make_shared<CLabel>(481, 28, FONT_BIG, ETextAlignment::TOPLEFT, Colors::YELLOW, CSH->si->getCampaignName());
|
||||
|
||||
iconsMapSizes = std::make_shared<CAnimImage>("SCNRMPSZ", 4, 0, 735, 26);
|
||||
iconsMapSizes = std::make_shared<CAnimImage>(AnimationPath::builtin("SCNRMPSZ"), 4, 0, 735, 26);
|
||||
|
||||
labelCampaignDescription = std::make_shared<CLabel>(481, 63, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::YELLOW, CGI->generaltexth->allTexts[38]);
|
||||
campaignDescription = std::make_shared<CTextBox>(getCampaign()->getDescription(), Rect(480, 86, 286, 117), 1);
|
||||
@ -97,13 +97,13 @@ CBonusSelection::CBonusSelection()
|
||||
|
||||
for(size_t b = 0; b < difficultyIcons.size(); ++b)
|
||||
{
|
||||
difficultyIcons[b] = std::make_shared<CAnimImage>("GSPBUT" + std::to_string(b + 3) + ".DEF", 0, 0, 709, 455);
|
||||
difficultyIcons[b] = std::make_shared<CAnimImage>(AnimationPath::builtinTODO("GSPBUT" + std::to_string(b + 3) + ".DEF"), 0, 0, 709, 455);
|
||||
}
|
||||
|
||||
if(getCampaign()->playerSelectedDifficulty())
|
||||
{
|
||||
buttonDifficultyLeft = std::make_shared<CButton>(Point(694, 508), "SCNRBLF.DEF", CButton::tooltip(), std::bind(&CBonusSelection::decreaseDifficulty, this));
|
||||
buttonDifficultyRight = std::make_shared<CButton>(Point(738, 508), "SCNRBRT.DEF", CButton::tooltip(), std::bind(&CBonusSelection::increaseDifficulty, this));
|
||||
buttonDifficultyLeft = std::make_shared<CButton>(Point(694, 508), AnimationPath::builtin("SCNRBLF.DEF"), CButton::tooltip(), std::bind(&CBonusSelection::decreaseDifficulty, this));
|
||||
buttonDifficultyRight = std::make_shared<CButton>(Point(738, 508), AnimationPath::builtin("SCNRBRT.DEF"), CButton::tooltip(), std::bind(&CBonusSelection::increaseDifficulty, this));
|
||||
}
|
||||
|
||||
for(auto scenarioID : getCampaign()->allScenarios())
|
||||
@ -115,7 +115,7 @@ CBonusSelection::CBonusSelection()
|
||||
}
|
||||
|
||||
if (!getCampaign()->getMusic().empty())
|
||||
CCS->musich->playMusic( "Music/" + getCampaign()->getMusic(), true, false);
|
||||
CCS->musich->playMusic( getCampaign()->getMusic(), true, false);
|
||||
}
|
||||
|
||||
void CBonusSelection::createBonusesIcons()
|
||||
@ -302,12 +302,12 @@ void CBonusSelection::createBonusesIcons()
|
||||
break;
|
||||
}
|
||||
|
||||
std::shared_ptr<CToggleButton> bonusButton = std::make_shared<CToggleButton>(Point(475 + i * 68, 455), "", CButton::tooltip(desc, desc));
|
||||
std::shared_ptr<CToggleButton> bonusButton = std::make_shared<CToggleButton>(Point(475 + i * 68, 455), AnimationPath(), CButton::tooltip(desc, desc));
|
||||
|
||||
if(picNumber != -1)
|
||||
picName += ":" + std::to_string(picNumber);
|
||||
|
||||
auto anim = std::make_shared<CAnimation>();
|
||||
auto anim = GH.renderHandler().createAnimation();
|
||||
anim->setCustom(picName, 0);
|
||||
bonusButton->setImage(anim);
|
||||
if(CSH->campaignBonus == i)
|
||||
|
@ -43,17 +43,17 @@ CLobbyScreen::CLobbyScreen(ESelectionScreen screenType)
|
||||
{
|
||||
tabSel->callOnSelect = std::bind(&IServerAPI::setMapInfo, CSH, _1, nullptr);
|
||||
|
||||
buttonSelect = std::make_shared<CButton>(Point(411, 80), "GSPBUTT.DEF", CGI->generaltexth->zelp[45], 0, EShortcut::LOBBY_SELECT_SCENARIO);
|
||||
buttonSelect = std::make_shared<CButton>(Point(411, 80), AnimationPath::builtin("GSPBUTT.DEF"), CGI->generaltexth->zelp[45], 0, EShortcut::LOBBY_SELECT_SCENARIO);
|
||||
buttonSelect->addCallback([&]()
|
||||
{
|
||||
toggleTab(tabSel);
|
||||
CSH->setMapInfo(tabSel->getSelectedMapInfo());
|
||||
});
|
||||
|
||||
buttonOptions = std::make_shared<CButton>(Point(411, 510), "GSPBUTT.DEF", CGI->generaltexth->zelp[46], std::bind(&CLobbyScreen::toggleTab, this, tabOpt), EShortcut::LOBBY_ADDITIONAL_OPTIONS);
|
||||
buttonOptions = std::make_shared<CButton>(Point(411, 510), AnimationPath::builtin("GSPBUTT.DEF"), CGI->generaltexth->zelp[46], std::bind(&CLobbyScreen::toggleTab, this, tabOpt), EShortcut::LOBBY_ADDITIONAL_OPTIONS);
|
||||
};
|
||||
|
||||
buttonChat = std::make_shared<CButton>(Point(619, 80), "GSPBUT2.DEF", CGI->generaltexth->zelp[48], std::bind(&CLobbyScreen::toggleChat, this), EShortcut::LOBBY_HIDE_CHAT);
|
||||
buttonChat = std::make_shared<CButton>(Point(619, 80), AnimationPath::builtin("GSPBUT2.DEF"), CGI->generaltexth->zelp[48], std::bind(&CLobbyScreen::toggleChat, this), EShortcut::LOBBY_HIDE_CHAT);
|
||||
buttonChat->addTextOverlay(CGI->generaltexth->allTexts[532], FONT_SMALL, Colors::WHITE);
|
||||
|
||||
switch(screenType)
|
||||
@ -63,7 +63,7 @@ CLobbyScreen::CLobbyScreen(ESelectionScreen screenType)
|
||||
tabOpt = std::make_shared<OptionsTab>();
|
||||
tabRand = std::make_shared<RandomMapTab>();
|
||||
tabRand->mapInfoChanged += std::bind(&IServerAPI::setMapInfo, CSH, _1, _2);
|
||||
buttonRMG = std::make_shared<CButton>(Point(411, 105), "GSPBUTT.DEF", CGI->generaltexth->zelp[47], 0, EShortcut::LOBBY_RANDOM_MAP);
|
||||
buttonRMG = std::make_shared<CButton>(Point(411, 105), AnimationPath::builtin("GSPBUTT.DEF"), CGI->generaltexth->zelp[47], 0, EShortcut::LOBBY_RANDOM_MAP);
|
||||
buttonRMG->addCallback([&]()
|
||||
{
|
||||
toggleTab(tabRand);
|
||||
@ -72,24 +72,24 @@ CLobbyScreen::CLobbyScreen(ESelectionScreen screenType)
|
||||
|
||||
card->iconDifficulty->addCallback(std::bind(&IServerAPI::setDifficulty, CSH, _1));
|
||||
|
||||
buttonStart = std::make_shared<CButton>(Point(411, 535), "SCNRBEG.DEF", CGI->generaltexth->zelp[103], std::bind(&CLobbyScreen::startScenario, this, true), EShortcut::LOBBY_BEGIN_GAME);
|
||||
buttonStart = std::make_shared<CButton>(Point(411, 535), AnimationPath::builtin("SCNRBEG.DEF"), CGI->generaltexth->zelp[103], std::bind(&CLobbyScreen::startScenario, this, true), EShortcut::LOBBY_BEGIN_GAME);
|
||||
initLobby();
|
||||
break;
|
||||
}
|
||||
case ESelectionScreen::loadGame:
|
||||
{
|
||||
tabOpt = std::make_shared<OptionsTab>();
|
||||
buttonStart = std::make_shared<CButton>(Point(411, 535), "SCNRLOD.DEF", CGI->generaltexth->zelp[103], std::bind(&CLobbyScreen::startScenario, this, true), EShortcut::LOBBY_LOAD_GAME);
|
||||
buttonStart = std::make_shared<CButton>(Point(411, 535), AnimationPath::builtin("SCNRLOD.DEF"), CGI->generaltexth->zelp[103], std::bind(&CLobbyScreen::startScenario, this, true), EShortcut::LOBBY_LOAD_GAME);
|
||||
initLobby();
|
||||
break;
|
||||
}
|
||||
case ESelectionScreen::campaignList:
|
||||
tabSel->callOnSelect = std::bind(&IServerAPI::setMapInfo, CSH, _1, nullptr);
|
||||
buttonStart = std::make_shared<CButton>(Point(411, 535), "SCNRLOD.DEF", CButton::tooltip(), std::bind(&CLobbyScreen::startCampaign, this), EShortcut::LOBBY_BEGIN_GAME);
|
||||
buttonStart = std::make_shared<CButton>(Point(411, 535), AnimationPath::builtin("SCNRLOD.DEF"), CButton::tooltip(), std::bind(&CLobbyScreen::startCampaign, this), EShortcut::LOBBY_BEGIN_GAME);
|
||||
break;
|
||||
}
|
||||
|
||||
buttonBack = std::make_shared<CButton>(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [&]()
|
||||
buttonBack = std::make_shared<CButton>(Point(581, 535), AnimationPath::builtin("SCNRBACK.DEF"), CGI->generaltexth->zelp[105], [&]()
|
||||
{
|
||||
CSH->sendClientDisconnecting();
|
||||
close();
|
||||
|
@ -40,7 +40,7 @@ CSavingScreen::CSavingScreen()
|
||||
tabSel->toggleMode();
|
||||
curTab = tabSel;
|
||||
|
||||
buttonStart = std::make_shared<CButton>(Point(411, 535), "SCNRSAV.DEF", CGI->generaltexth->zelp[103], std::bind(&CSavingScreen::saveGame, this), EShortcut::LOBBY_SAVE_GAME);
|
||||
buttonStart = std::make_shared<CButton>(Point(411, 535), AnimationPath::builtin("SCNRSAV.DEF"), CGI->generaltexth->zelp[103], std::bind(&CSavingScreen::saveGame, this), EShortcut::LOBBY_SAVE_GAME);
|
||||
}
|
||||
|
||||
const CMapInfo * CSavingScreen::getMapInfo()
|
||||
@ -80,7 +80,7 @@ void CSavingScreen::saveGame()
|
||||
close();
|
||||
};
|
||||
|
||||
if(CResourceHandler::get("local")->existsResource(ResourceID(path, EResType::SAVEGAME)))
|
||||
if(CResourceHandler::get("local")->existsResource(ResourcePath(path, EResType::SAVEGAME)))
|
||||
{
|
||||
std::string hlp = CGI->generaltexth->allTexts[493]; //%s exists. Overwrite?
|
||||
boost::algorithm::replace_first(hlp, "%s", tabSel->inputName->getText());
|
||||
|
@ -45,7 +45,7 @@ CScenarioInfoScreen::CScenarioInfoScreen()
|
||||
card->changeSelection();
|
||||
|
||||
card->iconDifficulty->setSelected(getCurrentDifficulty());
|
||||
buttonBack = std::make_shared<CButton>(Point(584, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [=](){ close();}, EShortcut::GLOBAL_CANCEL);
|
||||
buttonBack = std::make_shared<CButton>(Point(584, 535), AnimationPath::builtin("SCNRBACK.DEF"), CGI->generaltexth->zelp[105], [=](){ close();}, EShortcut::GLOBAL_CANCEL);
|
||||
}
|
||||
|
||||
CScenarioInfoScreen::~CScenarioInfoScreen()
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/Graphics.h"
|
||||
#include "../render/IFont.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
|
||||
#include "../../lib/NetPacksLobby.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
@ -80,16 +81,16 @@ CSelectionBase::CSelectionBase(ESelectionScreen type)
|
||||
pos.h = 584;
|
||||
if(screenType == ESelectionScreen::campaignList)
|
||||
{
|
||||
setBackground("CamCust.bmp");
|
||||
setBackground(ImagePath::builtin("CamCust.bmp"));
|
||||
}
|
||||
else
|
||||
{
|
||||
const JsonVector & bgNames = CMainMenuConfig::get().getConfig()["game-select"].Vector();
|
||||
setBackground(RandomGeneratorUtil::nextItem(bgNames, CRandomGenerator::getDefault())->String());
|
||||
setBackground(ImagePath::fromJson(*RandomGeneratorUtil::nextItem(bgNames, CRandomGenerator::getDefault())));
|
||||
}
|
||||
pos = background->center();
|
||||
card = std::make_shared<InfoCard>();
|
||||
buttonBack = std::make_shared<CButton>(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], [=](){ close();}, EShortcut::GLOBAL_CANCEL);
|
||||
buttonBack = std::make_shared<CButton>(Point(581, 535), AnimationPath::builtin("SCNRBACK.DEF"), CGI->generaltexth->zelp[105], [=](){ close();}, EShortcut::GLOBAL_CANCEL);
|
||||
}
|
||||
|
||||
void CSelectionBase::toggleTab(std::shared_ptr<CIntObject> tab)
|
||||
@ -125,7 +126,7 @@ InfoCard::InfoCard()
|
||||
mapName = std::make_shared<CLabel>(26, 39, FONT_BIG, ETextAlignment::TOPLEFT, Colors::YELLOW);
|
||||
Rect descriptionRect(26, 149, 320, 115);
|
||||
mapDescription = std::make_shared<CTextBox>("", descriptionRect, 1);
|
||||
playerListBg = std::make_shared<CPicture>("CHATPLUG.bmp", 16, 276);
|
||||
playerListBg = std::make_shared<CPicture>(ImagePath::builtin("CHATPLUG.bmp"), 16, 276);
|
||||
chat = std::make_shared<CChatBox>(Rect(26, 132, 340, 132));
|
||||
|
||||
if(SEL->screenType == ESelectionScreen::campaignList)
|
||||
@ -134,14 +135,14 @@ InfoCard::InfoCard()
|
||||
}
|
||||
else
|
||||
{
|
||||
background = std::make_shared<CPicture>("GSELPOP1.bmp", 0, 0);
|
||||
background = std::make_shared<CPicture>(ImagePath::builtin("GSELPOP1.bmp"), 0, 0);
|
||||
parent->addChild(background.get());
|
||||
auto it = vstd::find(parent->children, this); //our position among parent children
|
||||
parent->children.insert(it, background.get()); //put BG before us
|
||||
parent->children.pop_back();
|
||||
pos.w = background->pos.w;
|
||||
pos.h = background->pos.h;
|
||||
iconsMapSizes = std::make_shared<CAnimImage>("SCNRMPSZ", 4, 0, 318, 22); //let it be custom size (frame 4) by default
|
||||
iconsMapSizes = std::make_shared<CAnimImage>(AnimationPath::builtin("SCNRMPSZ"), 4, 0, 318, 22); //let it be custom size (frame 4) by default
|
||||
|
||||
iconDifficulty = std::make_shared<CToggleGroup>(0);
|
||||
{
|
||||
@ -149,7 +150,7 @@ InfoCard::InfoCard()
|
||||
|
||||
for(int i = 0; i < 5; i++)
|
||||
{
|
||||
auto button = std::make_shared<CToggleButton>(Point(110 + i * 32, 450), difButns[i], CGI->generaltexth->zelp[24 + i]);
|
||||
auto button = std::make_shared<CToggleButton>(Point(110 + i * 32, 450), AnimationPath::builtin(difButns[i]), CGI->generaltexth->zelp[24 + i]);
|
||||
|
||||
iconDifficulty->addToggle(i, button);
|
||||
if(SEL->screenType != ESelectionScreen::newGame)
|
||||
@ -165,8 +166,8 @@ InfoCard::InfoCard()
|
||||
labelScenarioDescription = std::make_shared<CLabel>(26, 132, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::YELLOW, CGI->generaltexth->allTexts[496]);
|
||||
labelVictoryCondition = std::make_shared<CLabel>(26, 283, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::YELLOW, CGI->generaltexth->allTexts[497]);
|
||||
labelLossCondition = std::make_shared<CLabel>(26, 339, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::YELLOW, CGI->generaltexth->allTexts[498]);
|
||||
iconsVictoryCondition = std::make_shared<CAnimImage>("SCNRVICT", 0, 0, 24, 302);
|
||||
iconsLossCondition = std::make_shared<CAnimImage>("SCNRLOSS", 0, 0, 24, 359);
|
||||
iconsVictoryCondition = std::make_shared<CAnimImage>(AnimationPath::builtin("SCNRVICT"), 0, 0, 24, 302);
|
||||
iconsLossCondition = std::make_shared<CAnimImage>(AnimationPath::builtin("SCNRLOSS"), 0, 0, 24, 359);
|
||||
|
||||
labelVictoryConditionText = std::make_shared<CLabel>(60, 307, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE);
|
||||
labelLossConditionText = std::make_shared<CLabel>(60, 366, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE);
|
||||
@ -240,7 +241,7 @@ void InfoCard::changeSelection()
|
||||
int pid = p.first;
|
||||
if(pset)
|
||||
{
|
||||
auto name = boost::str(boost::format("%s (%d-%d %s)") % p.second.name % p.second.connection % pid % pset->color.getStr());
|
||||
auto name = boost::str(boost::format("%s (%d-%d %s)") % p.second.name % p.second.connection % pid % pset->color.toString());
|
||||
labelGroupPlayersAssigned->add(24, 285 + (int)labelGroupPlayersAssigned->currentSize()*(int)graphics->fonts[FONT_SMALL]->getLineHeight(), name);
|
||||
}
|
||||
else
|
||||
@ -339,7 +340,7 @@ void CChatBox::keyPressed(EShortcut key)
|
||||
|
||||
void CChatBox::addNewMessage(const std::string & text)
|
||||
{
|
||||
CCS->soundh->playSound("CHAT");
|
||||
CCS->soundh->playSound(AudioPath::builtin("CHAT"));
|
||||
chatHistory->setText(chatHistory->label->getText() + text + "\n");
|
||||
if(chatHistory->slider)
|
||||
chatHistory->slider->scrollToMax();
|
||||
@ -356,7 +357,7 @@ CFlagBox::CFlagBox(const Rect & rect)
|
||||
labelAllies = std::make_shared<CLabel>(0, 0, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[390] + ":");
|
||||
labelEnemies = std::make_shared<CLabel>(133, 0, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[391] + ":");
|
||||
|
||||
iconsTeamFlags = std::make_shared<CAnimation>("ITGFLAGS.DEF");
|
||||
iconsTeamFlags = GH.renderHandler().loadAnimation(AnimationPath::builtin("ITGFLAGS.DEF"));
|
||||
iconsTeamFlags->preload();
|
||||
}
|
||||
|
||||
@ -390,7 +391,7 @@ void CFlagBox::showPopupWindow(const Point & cursorPosition)
|
||||
}
|
||||
|
||||
CFlagBox::CFlagBoxTooltipBox::CFlagBoxTooltipBox(std::shared_ptr<CAnimation> icons)
|
||||
: CWindowObject(BORDERED | RCLICK_POPUP | SHADOW_DISABLED, "DIBOXBCK")
|
||||
: CWindowObject(BORDERED | RCLICK_POPUP | SHADOW_DISABLED, ImagePath::builtin("DIBOXBCK"))
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
|
||||
|
@ -137,7 +137,7 @@ OptionsTab::OptionsTab() : humanPlayers(0)
|
||||
}
|
||||
});
|
||||
|
||||
const JsonNode config(ResourceID("config/widgets/optionsTab.json"));
|
||||
const JsonNode config(JsonPath::builtin("config/widgets/optionsTab.json"));
|
||||
build(config);
|
||||
|
||||
//set timers combo box callbacks
|
||||
@ -343,18 +343,18 @@ size_t OptionsTab::CPlayerSettingsHelper::getImageIndex(bool big)
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string OptionsTab::CPlayerSettingsHelper::getImageName(bool big)
|
||||
AnimationPath OptionsTab::CPlayerSettingsHelper::getImageName(bool big)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case OptionsTab::TOWN:
|
||||
return big ? "ITPt": "ITPA";
|
||||
return AnimationPath::builtin(big ? "ITPt": "ITPA");
|
||||
case OptionsTab::HERO:
|
||||
return big ? "PortraitsLarge": "PortraitsSmall";
|
||||
return AnimationPath::builtin(big ? "PortraitsLarge": "PortraitsSmall");
|
||||
case OptionsTab::BONUS:
|
||||
return "SCNRSTAR";
|
||||
return AnimationPath::builtin("SCNRSTAR");
|
||||
}
|
||||
return "";
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string OptionsTab::CPlayerSettingsHelper::getName()
|
||||
@ -553,7 +553,7 @@ OptionsTab::CPlayerOptionTooltipBox::CPlayerOptionTooltipBox(CPlayerSettingsHelp
|
||||
|
||||
void OptionsTab::CPlayerOptionTooltipBox::genHeader()
|
||||
{
|
||||
backgroundTexture = std::make_shared<CFilledTexture>("DIBOXBCK", pos);
|
||||
backgroundTexture = std::make_shared<CFilledTexture>(ImagePath::builtin("DIBOXBCK"), pos);
|
||||
updateShadow();
|
||||
|
||||
labelTitle = std::make_shared<CLabel>(pos.w / 2 + 8, 21, FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW, getTitle());
|
||||
@ -585,7 +585,7 @@ void OptionsTab::CPlayerOptionTooltipBox::genHeroWindow()
|
||||
labelHeroSpeciality = std::make_shared<CLabel>(pos.w / 2 + 4, 117, FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[78]);
|
||||
auto heroIndex = settings.hero.getNum() >= CGI->heroh->size() ? 0 : settings.hero.getNum();
|
||||
|
||||
imageSpeciality = std::make_shared<CAnimImage>("UN44", (*CGI->heroh)[heroIndex]->imageIndex, 0, pos.w / 2 - 22, 134);
|
||||
imageSpeciality = std::make_shared<CAnimImage>(AnimationPath::builtin("UN44"), (*CGI->heroh)[heroIndex]->imageIndex, 0, pos.w / 2 - 22, 134);
|
||||
labelSpecialityName = std::make_shared<CLabel>(pos.w / 2, 188, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, (*CGI->heroh)[heroIndex]->getSpecialtyNameTranslated());
|
||||
}
|
||||
|
||||
@ -717,7 +717,7 @@ void OptionsTab::SelectionWindow::recreate()
|
||||
|
||||
pos = Rect(0, 0, x, y);
|
||||
|
||||
backgroundTexture = std::make_shared<FilledTexturePlayerColored>("DiBoxBck", pos);
|
||||
backgroundTexture = std::make_shared<FilledTexturePlayerColored>(ImagePath::builtin("DiBoxBck"), pos);
|
||||
backgroundTexture->playerColored(PlayerColor(1));
|
||||
updateShadow();
|
||||
|
||||
@ -747,7 +747,7 @@ void OptionsTab::SelectionWindow::genContentGrid(int lines)
|
||||
{
|
||||
for(int x = 0; x < elementsPerLine; x++)
|
||||
{
|
||||
components.push_back(std::make_shared<CPicture>("lobby/townBorderBig", x * (ICON_BIG_WIDTH-1), y * (ICON_BIG_HEIGHT-1)));
|
||||
components.push_back(std::make_shared<CPicture>(ImagePath::builtin("lobby/townBorderBig"), x * (ICON_BIG_WIDTH-1), y * (ICON_BIG_HEIGHT-1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -763,7 +763,7 @@ void OptionsTab::SelectionWindow::genContentFactions()
|
||||
components.push_back(std::make_shared<CAnimImage>(helper.getImageName(), helper.getImageIndex(), 0, 6, (ICON_SMALL_HEIGHT/2)));
|
||||
drawOutlinedText(TEXT_POS_X, TEXT_POS_Y, (selectedFaction.getNum() == PlayerSettings::RANDOM) ? Colors::YELLOW : Colors::WHITE, helper.getName());
|
||||
if(selectedFaction.getNum() == PlayerSettings::RANDOM)
|
||||
components.push_back(std::make_shared<CPicture>("lobby/townBorderSmallActivated", 6, (ICON_SMALL_HEIGHT/2)));
|
||||
components.push_back(std::make_shared<CPicture>(ImagePath::builtin("lobby/townBorderSmallActivated"), 6, (ICON_SMALL_HEIGHT/2)));
|
||||
|
||||
for(auto & elem : allowedFactions)
|
||||
{
|
||||
@ -776,7 +776,7 @@ void OptionsTab::SelectionWindow::genContentFactions()
|
||||
CPlayerSettingsHelper helper = CPlayerSettingsHelper(set, SelType::TOWN);
|
||||
|
||||
components.push_back(std::make_shared<CAnimImage>(helper.getImageName(true), helper.getImageIndex(true), 0, x * (ICON_BIG_WIDTH-1), y * (ICON_BIG_HEIGHT-1)));
|
||||
components.push_back(std::make_shared<CPicture>(selectedFaction == elem ? "lobby/townBorderBigActivated" : "lobby/townBorderBig", x * (ICON_BIG_WIDTH-1), y * (ICON_BIG_HEIGHT-1)));
|
||||
components.push_back(std::make_shared<CPicture>(ImagePath::builtin(selectedFaction == elem ? "lobby/townBorderBigActivated" : "lobby/townBorderBig"), x * (ICON_BIG_WIDTH-1), y * (ICON_BIG_HEIGHT-1)));
|
||||
drawOutlinedText(x * (ICON_BIG_WIDTH-1) + TEXT_POS_X, y * (ICON_BIG_HEIGHT-1) + TEXT_POS_Y, (selectedFaction == elem) ? Colors::YELLOW : Colors::WHITE, helper.getName());
|
||||
factions.push_back(elem);
|
||||
|
||||
@ -795,7 +795,7 @@ void OptionsTab::SelectionWindow::genContentHeroes()
|
||||
components.push_back(std::make_shared<CAnimImage>(helper.getImageName(), helper.getImageIndex(), 0, 6, (ICON_SMALL_HEIGHT/2)));
|
||||
drawOutlinedText(TEXT_POS_X, TEXT_POS_Y, (selectedHero.getNum() == PlayerSettings::RANDOM) ? Colors::YELLOW : Colors::WHITE, helper.getName());
|
||||
if(selectedHero.getNum() == PlayerSettings::RANDOM)
|
||||
components.push_back(std::make_shared<CPicture>("lobby/townBorderSmallActivated", 6, (ICON_SMALL_HEIGHT/2)));
|
||||
components.push_back(std::make_shared<CPicture>(ImagePath::builtin("lobby/townBorderSmallActivated"), 6, (ICON_SMALL_HEIGHT/2)));
|
||||
|
||||
for(auto & elem : allowedHeroes)
|
||||
{
|
||||
@ -814,11 +814,11 @@ void OptionsTab::SelectionWindow::genContentHeroes()
|
||||
|
||||
components.push_back(std::make_shared<CAnimImage>(helper.getImageName(true), helper.getImageIndex(true), 0, x * (ICON_BIG_WIDTH-1), y * (ICON_BIG_HEIGHT-1)));
|
||||
drawOutlinedText(x * (ICON_BIG_WIDTH-1) + TEXT_POS_X, y * (ICON_BIG_HEIGHT-1) + TEXT_POS_Y, (selectedHero == elem) ? Colors::YELLOW : Colors::WHITE, helper.getName());
|
||||
std::string image = "lobby/townBorderBig";
|
||||
ImagePath image = ImagePath::builtin("lobby/townBorderBig");
|
||||
if(selectedHero == elem)
|
||||
image = "lobby/townBorderBigActivated";
|
||||
image = ImagePath::builtin("lobby/townBorderBigActivated");
|
||||
if(unusableHeroes.count(elem))
|
||||
image = "lobby/townBorderBigGrayedOut";
|
||||
image = ImagePath::builtin("lobby/townBorderBigGrayedOut");
|
||||
components.push_back(std::make_shared<CPicture>(image, x * (ICON_BIG_WIDTH-1), y * (ICON_BIG_HEIGHT-1)));
|
||||
heroes.push_back(elem);
|
||||
|
||||
@ -843,7 +843,7 @@ void OptionsTab::SelectionWindow::genContentBonus()
|
||||
drawOutlinedText(x * (ICON_BIG_WIDTH-1) + TEXT_POS_X, y * (ICON_BIG_HEIGHT-1) + TEXT_POS_Y, Colors::WHITE , helper.getName());
|
||||
if(selectedBonus == elem)
|
||||
{
|
||||
components.push_back(std::make_shared<CPicture>("lobby/townBorderSmallActivated", x * (ICON_BIG_WIDTH-1) + 6, y * (ICON_BIG_HEIGHT-1) + (ICON_SMALL_HEIGHT/2)));
|
||||
components.push_back(std::make_shared<CPicture>(ImagePath::builtin("lobby/townBorderSmallActivated"), x * (ICON_BIG_WIDTH-1) + 6, y * (ICON_BIG_HEIGHT-1) + (ICON_SMALL_HEIGHT/2)));
|
||||
drawOutlinedText(x * (ICON_BIG_WIDTH-1) + TEXT_POS_X, y * (ICON_BIG_HEIGHT-1) + TEXT_POS_Y, Colors::YELLOW , helper.getName());
|
||||
}
|
||||
|
||||
@ -1075,18 +1075,18 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S, con
|
||||
"ADOPOPNL.bmp", "ADOPPPNL.bmp", "ADOPTPNL.bmp", "ADOPSPNL.bmp"
|
||||
}};
|
||||
|
||||
background = std::make_shared<CPicture>(bgs[s->color.getNum()], 0, 0);
|
||||
background = std::make_shared<CPicture>(ImagePath::builtin(bgs[s->color.getNum()]), 0, 0);
|
||||
labelPlayerName = std::make_shared<CLabel>(55, 10, EFonts::FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, s->name);
|
||||
labelWhoCanPlay = std::make_shared<CMultiLineLabel>(Rect(6, 23, 45, (int)graphics->fonts[EFonts::FONT_TINY]->getLineHeight()*2), EFonts::FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->arraytxt[206 + whoCanPlay]);
|
||||
|
||||
if(SEL->screenType == ESelectionScreen::newGame)
|
||||
{
|
||||
buttonTownLeft = std::make_shared<CButton>(Point(107, 5), "ADOPLFA.DEF", CGI->generaltexth->zelp[132], std::bind(&IServerAPI::setPlayerOption, CSH, LobbyChangePlayerOption::TOWN, -1, s->color));
|
||||
buttonTownRight = std::make_shared<CButton>(Point(168, 5), "ADOPRTA.DEF", CGI->generaltexth->zelp[133], std::bind(&IServerAPI::setPlayerOption, CSH, LobbyChangePlayerOption::TOWN, +1, s->color));
|
||||
buttonHeroLeft = std::make_shared<CButton>(Point(183, 5), "ADOPLFA.DEF", CGI->generaltexth->zelp[148], std::bind(&IServerAPI::setPlayerOption, CSH, LobbyChangePlayerOption::HERO, -1, s->color));
|
||||
buttonHeroRight = std::make_shared<CButton>(Point(244, 5), "ADOPRTA.DEF", CGI->generaltexth->zelp[149], std::bind(&IServerAPI::setPlayerOption, CSH, LobbyChangePlayerOption::HERO, +1, s->color));
|
||||
buttonBonusLeft = std::make_shared<CButton>(Point(259, 5), "ADOPLFA.DEF", CGI->generaltexth->zelp[164], std::bind(&IServerAPI::setPlayerOption, CSH, LobbyChangePlayerOption::BONUS, -1, s->color));
|
||||
buttonBonusRight = std::make_shared<CButton>(Point(320, 5), "ADOPRTA.DEF", CGI->generaltexth->zelp[165], std::bind(&IServerAPI::setPlayerOption, CSH, LobbyChangePlayerOption::BONUS, +1, s->color));
|
||||
buttonTownLeft = std::make_shared<CButton>(Point(107, 5), AnimationPath::builtin("ADOPLFA.DEF"), CGI->generaltexth->zelp[132], std::bind(&IServerAPI::setPlayerOption, CSH, LobbyChangePlayerOption::TOWN, -1, s->color));
|
||||
buttonTownRight = std::make_shared<CButton>(Point(168, 5), AnimationPath::builtin("ADOPRTA.DEF"), CGI->generaltexth->zelp[133], std::bind(&IServerAPI::setPlayerOption, CSH, LobbyChangePlayerOption::TOWN, +1, s->color));
|
||||
buttonHeroLeft = std::make_shared<CButton>(Point(183, 5), AnimationPath::builtin("ADOPLFA.DEF"), CGI->generaltexth->zelp[148], std::bind(&IServerAPI::setPlayerOption, CSH, LobbyChangePlayerOption::HERO, -1, s->color));
|
||||
buttonHeroRight = std::make_shared<CButton>(Point(244, 5), AnimationPath::builtin("ADOPRTA.DEF"), CGI->generaltexth->zelp[149], std::bind(&IServerAPI::setPlayerOption, CSH, LobbyChangePlayerOption::HERO, +1, s->color));
|
||||
buttonBonusLeft = std::make_shared<CButton>(Point(259, 5), AnimationPath::builtin("ADOPLFA.DEF"), CGI->generaltexth->zelp[164], std::bind(&IServerAPI::setPlayerOption, CSH, LobbyChangePlayerOption::BONUS, -1, s->color));
|
||||
buttonBonusRight = std::make_shared<CButton>(Point(320, 5), AnimationPath::builtin("ADOPRTA.DEF"), CGI->generaltexth->zelp[165], std::bind(&IServerAPI::setPlayerOption, CSH, LobbyChangePlayerOption::BONUS, +1, s->color));
|
||||
}
|
||||
|
||||
hideUnavailableButtons();
|
||||
@ -1095,7 +1095,7 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S, con
|
||||
{
|
||||
flag = std::make_shared<CButton>(
|
||||
Point(-43, 2),
|
||||
flags[s->color.getNum()],
|
||||
AnimationPath::builtin(flags[s->color.getNum()]),
|
||||
CGI->generaltexth->zelp[180],
|
||||
std::bind(&OptionsTab::onSetPlayerClicked, &parentTab, *s)
|
||||
);
|
||||
|
@ -62,7 +62,7 @@ private:
|
||||
|
||||
/// visible image settings
|
||||
size_t getImageIndex(bool big = false);
|
||||
std::string getImageName(bool big = false);
|
||||
AnimationPath getImageName(bool big = false);
|
||||
|
||||
std::string getName(); /// name visible in options dialog
|
||||
std::string getTitle(); /// title in popup box
|
||||
|
@ -118,7 +118,7 @@ RandomMapTab::RandomMapTab():
|
||||
});
|
||||
}
|
||||
|
||||
const JsonNode config(ResourceID("config/widgets/randomMapTab.json"));
|
||||
const JsonNode config(JsonPath::builtin("config/widgets/randomMapTab.json"));
|
||||
build(config);
|
||||
|
||||
//set combo box callbacks
|
||||
@ -388,7 +388,7 @@ std::vector<int> RandomMapTab::getPossibleMapSizes()
|
||||
TeamAlignmentsWidget::TeamAlignmentsWidget(RandomMapTab & randomMapTab):
|
||||
InterfaceObjectConfigurable()
|
||||
{
|
||||
const JsonNode config(ResourceID("config/widgets/randomMapTeamsWidget.json"));
|
||||
const JsonNode config(JsonPath::builtin("config/widgets/randomMapTeamsWidget.json"));
|
||||
variables = config["variables"];
|
||||
|
||||
int humanPlayers = randomMapTab.obtainMapGenOptions().getPlayerCount();
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
#include "../render/Graphics.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
@ -158,16 +159,16 @@ SelectionTab::SelectionTab(ESelectionScreen Type)
|
||||
if(tabType != ESelectionScreen::campaignList)
|
||||
{
|
||||
sortingBy = _format;
|
||||
background = std::make_shared<CPicture>("SCSELBCK.bmp", 0, 6);
|
||||
background = std::make_shared<CPicture>(ImagePath::builtin("SCSELBCK.bmp"), 0, 6);
|
||||
pos = background->pos;
|
||||
inputName = std::make_shared<CTextInput>(inputNameRect, Point(-32, -25), "GSSTRIP.bmp", 0);
|
||||
inputName = std::make_shared<CTextInput>(inputNameRect, Point(-32, -25), ImagePath::builtin("GSSTRIP.bmp"), 0);
|
||||
inputName->filters += CTextInput::filenameFilter;
|
||||
labelMapSizes = std::make_shared<CLabel>(87, 62, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[510]);
|
||||
|
||||
int sizes[] = {36, 72, 108, 144, 0};
|
||||
const char * filterIconNmes[] = {"SCSMBUT.DEF", "SCMDBUT.DEF", "SCLGBUT.DEF", "SCXLBUT.DEF", "SCALBUT.DEF"};
|
||||
for(int i = 0; i < 5; i++)
|
||||
buttonsSortBy.push_back(std::make_shared<CButton>(Point(158 + 47 * i, 46), filterIconNmes[i], CGI->generaltexth->zelp[54 + i], std::bind(&SelectionTab::filter, this, sizes[i], true)));
|
||||
buttonsSortBy.push_back(std::make_shared<CButton>(Point(158 + 47 * i, 46), AnimationPath::builtin(filterIconNmes[i]), CGI->generaltexth->zelp[54 + i], std::bind(&SelectionTab::filter, this, sizes[i], true)));
|
||||
|
||||
int xpos[] = {23, 55, 88, 121, 306, 339};
|
||||
const char * sortIconNames[] = {"SCBUTT1.DEF", "SCBUTT2.DEF", "SCBUTCP.DEF", "SCBUTT3.DEF", "SCBUTT4.DEF", "SCBUTT5.DEF"};
|
||||
@ -177,7 +178,7 @@ SelectionTab::SelectionTab(ESelectionScreen Type)
|
||||
if(criteria == _name)
|
||||
criteria = generalSortingBy;
|
||||
|
||||
buttonsSortBy.push_back(std::make_shared<CButton>(Point(xpos[i], 86), sortIconNames[i], CGI->generaltexth->zelp[107 + i], std::bind(&SelectionTab::sortBy, this, criteria)));
|
||||
buttonsSortBy.push_back(std::make_shared<CButton>(Point(xpos[i], 86), AnimationPath::builtin(sortIconNames[i]), CGI->generaltexth->zelp[107 + i], std::bind(&SelectionTab::sortBy, this, criteria)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,17 +204,17 @@ SelectionTab::SelectionTab(ESelectionScreen Type)
|
||||
pos.x += 3;
|
||||
pos.y += 6;
|
||||
|
||||
buttonsSortBy.push_back(std::make_shared<CButton>(Point(23, 86), "CamCusM.DEF", CButton::tooltip(), std::bind(&SelectionTab::sortBy, this, _numOfMaps)));
|
||||
buttonsSortBy.push_back(std::make_shared<CButton>(Point(55, 86), "CamCusL.DEF", CButton::tooltip(), std::bind(&SelectionTab::sortBy, this, _name)));
|
||||
buttonsSortBy.push_back(std::make_shared<CButton>(Point(23, 86), AnimationPath::builtin("CamCusM.DEF"), CButton::tooltip(), std::bind(&SelectionTab::sortBy, this, _numOfMaps)));
|
||||
buttonsSortBy.push_back(std::make_shared<CButton>(Point(55, 86), AnimationPath::builtin("CamCusL.DEF"), CButton::tooltip(), std::bind(&SelectionTab::sortBy, this, _name)));
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
iconsMapFormats = std::make_shared<CAnimation>("SCSELC.DEF");
|
||||
iconsVictoryCondition = std::make_shared<CAnimation>("SCNRVICT.DEF");
|
||||
iconsLossCondition = std::make_shared<CAnimation>("SCNRLOSS.DEF");
|
||||
iconsMapFormats = GH.renderHandler().loadAnimation(AnimationPath::builtin("SCSELC.DEF"));
|
||||
iconsVictoryCondition = GH.renderHandler().loadAnimation(AnimationPath::builtin("SCNRVICT.DEF"));
|
||||
iconsLossCondition = GH.renderHandler().loadAnimation(AnimationPath::builtin("SCNRLOSS.DEF"));
|
||||
for(int i = 0; i < positionsToShow; i++)
|
||||
listItems.push_back(std::make_shared<ListItem>(Point(30, 129 + i * 25), iconsMapFormats, iconsVictoryCondition, iconsLossCondition));
|
||||
|
||||
@ -244,7 +245,7 @@ void SelectionTab::toggleMode()
|
||||
{
|
||||
inputName->disable();
|
||||
auto files = getFiles("Maps/", EResType::MAP);
|
||||
files.erase(ResourceID("Maps/Tutorial.tut", EResType::MAP));
|
||||
files.erase(ResourcePath("Maps/Tutorial.tut", EResType::MAP));
|
||||
parseMaps(files);
|
||||
break;
|
||||
}
|
||||
@ -367,7 +368,7 @@ void SelectionTab::showPopupWindow(const Point & cursorPosition)
|
||||
if(curItems[py]->date != "")
|
||||
text += boost::str(boost::format("\r\n\r\n%1%:\r\n%2%") % CGI->generaltexth->translate("vcmi.lobby.creationDate") % curItems[py]->date);
|
||||
|
||||
GH.windows().createAndPushWindow<CMapInfoTooltipBox>(text, ResourceID(curItems[py]->fileURI), tabType);
|
||||
GH.windows().createAndPushWindow<CMapInfoTooltipBox>(text, ResourcePath(curItems[py]->fileURI), tabType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -556,7 +557,7 @@ void SelectionTab::select(int position)
|
||||
|
||||
if(inputName && inputName->isActive())
|
||||
{
|
||||
auto filename = *CResourceHandler::get()->getResourceName(ResourceID(curItems[py]->fileURI, EResType::SAVEGAME));
|
||||
auto filename = *CResourceHandler::get()->getResourceName(ResourcePath(curItems[py]->fileURI, EResType::SAVEGAME));
|
||||
inputName->setText(filename.stem().string());
|
||||
}
|
||||
|
||||
@ -723,7 +724,7 @@ bool SelectionTab::isMapSupported(const CMapInfo & info)
|
||||
return false;
|
||||
}
|
||||
|
||||
void SelectionTab::parseMaps(const std::unordered_set<ResourceID> & files)
|
||||
void SelectionTab::parseMaps(const std::unordered_set<ResourcePath> & files)
|
||||
{
|
||||
logGlobal->debug("Parsing %d maps", files.size());
|
||||
allItems.clear();
|
||||
@ -744,7 +745,7 @@ void SelectionTab::parseMaps(const std::unordered_set<ResourceID> & files)
|
||||
}
|
||||
}
|
||||
|
||||
void SelectionTab::parseSaves(const std::unordered_set<ResourceID> & files)
|
||||
void SelectionTab::parseSaves(const std::unordered_set<ResourcePath> & files)
|
||||
{
|
||||
for(auto & file : files)
|
||||
{
|
||||
@ -786,7 +787,7 @@ void SelectionTab::parseSaves(const std::unordered_set<ResourceID> & files)
|
||||
}
|
||||
}
|
||||
|
||||
void SelectionTab::parseCampaigns(const std::unordered_set<ResourceID> & files)
|
||||
void SelectionTab::parseCampaigns(const std::unordered_set<ResourcePath> & files)
|
||||
{
|
||||
allItems.reserve(files.size());
|
||||
for(auto & file : files)
|
||||
@ -800,7 +801,7 @@ void SelectionTab::parseCampaigns(const std::unordered_set<ResourceID> & files)
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_set<ResourceID> SelectionTab::getFiles(std::string dirURI, int resType)
|
||||
std::unordered_set<ResourcePath> SelectionTab::getFiles(std::string dirURI, EResType resType)
|
||||
{
|
||||
boost::to_upper(dirURI);
|
||||
CResourceHandler::get()->updateFilteredFiles([&](const std::string & mount)
|
||||
@ -808,7 +809,7 @@ std::unordered_set<ResourceID> SelectionTab::getFiles(std::string dirURI, int re
|
||||
return boost::algorithm::starts_with(mount, dirURI);
|
||||
});
|
||||
|
||||
std::unordered_set<ResourceID> ret = CResourceHandler::get()->getFilteredFiles([&](const ResourceID & ident)
|
||||
std::unordered_set<ResourcePath> ret = CResourceHandler::get()->getFilteredFiles([&](const ResourcePath & ident)
|
||||
{
|
||||
return ident.getType() == resType && boost::algorithm::starts_with(ident.getName(), dirURI);
|
||||
});
|
||||
@ -816,7 +817,7 @@ std::unordered_set<ResourceID> SelectionTab::getFiles(std::string dirURI, int re
|
||||
return ret;
|
||||
}
|
||||
|
||||
SelectionTab::CMapInfoTooltipBox::CMapInfoTooltipBox(std::string text, ResourceID resource, ESelectionScreen tabType)
|
||||
SelectionTab::CMapInfoTooltipBox::CMapInfoTooltipBox(std::string text, ResourcePath resource, ESelectionScreen tabType)
|
||||
: CWindowObject(BORDERED | RCLICK_POPUP)
|
||||
{
|
||||
drawPlayerElements = tabType == ESelectionScreen::newGame;
|
||||
@ -826,7 +827,7 @@ SelectionTab::CMapInfoTooltipBox::CMapInfoTooltipBox(std::string text, ResourceI
|
||||
|
||||
std::vector<std::shared_ptr<IImage>> mapLayerImages;
|
||||
if(renderImage)
|
||||
mapLayerImages = createMinimaps(ResourceID(resource.getName(), EResType::MAP), IMAGE_SIZE);
|
||||
mapLayerImages = createMinimaps(ResourcePath(resource.getName(), EResType::MAP), IMAGE_SIZE);
|
||||
|
||||
if(mapLayerImages.size() == 0)
|
||||
renderImage = false;
|
||||
@ -844,7 +845,7 @@ SelectionTab::CMapInfoTooltipBox::CMapInfoTooltipBox(std::string text, ResourceI
|
||||
pos.h = BORDER + textHeight + BORDER;
|
||||
if(renderImage)
|
||||
pos.h += IMAGE_SIZE + BORDER;
|
||||
backgroundTexture = std::make_shared<CFilledTexture>("DIBOXBCK", pos);
|
||||
backgroundTexture = std::make_shared<CFilledTexture>(ImagePath::builtin("DIBOXBCK"), pos);
|
||||
updateShadow();
|
||||
|
||||
drawLabel();
|
||||
@ -903,7 +904,7 @@ Canvas SelectionTab::CMapInfoTooltipBox::createMinimapForLayer(std::unique_ptr<C
|
||||
return canvas;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<IImage>> SelectionTab::CMapInfoTooltipBox::createMinimaps(ResourceID resource, int size)
|
||||
std::vector<std::shared_ptr<IImage>> SelectionTab::CMapInfoTooltipBox::createMinimaps(ResourcePath resource, int size)
|
||||
{
|
||||
std::vector<std::shared_ptr<IImage>> ret = std::vector<std::shared_ptr<IImage>>();
|
||||
|
||||
@ -923,7 +924,7 @@ std::vector<std::shared_ptr<IImage>> SelectionTab::CMapInfoTooltipBox::createMin
|
||||
Canvas canvas = createMinimapForLayer(map, i);
|
||||
Canvas canvasScaled = Canvas(Point(size, size));
|
||||
canvasScaled.drawScaled(canvas, Point(0, 0), Point(size, size));
|
||||
std::shared_ptr<IImage> img = IImage::createFromSurface(canvasScaled.getInternalSurface());
|
||||
std::shared_ptr<IImage> img = GH.renderHandler().createImage(canvasScaled.getInternalSurface());
|
||||
|
||||
ret.push_back(img);
|
||||
}
|
||||
@ -935,7 +936,7 @@ SelectionTab::ListItem::ListItem(Point position, std::shared_ptr<CAnimation> ico
|
||||
: CIntObject(LCLICK, position)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
pictureEmptyLine = std::make_shared<CPicture>(IImage::createFromFile("camcust"), Rect(25, 121, 349, 26), -8, -14);
|
||||
pictureEmptyLine = std::make_shared<CPicture>(GH.renderHandler().loadImage(ImagePath::builtin("camcust")), Rect(25, 121, 349, 26), -8, -14);
|
||||
labelName = std::make_shared<CLabel>(184, 0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
|
||||
labelName->setAutoRedraw(false);
|
||||
labelAmountOfPlayers = std::make_shared<CLabel>(8, 0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
|
||||
@ -945,7 +946,7 @@ SelectionTab::ListItem::ListItem(Point position, std::shared_ptr<CAnimation> ico
|
||||
labelMapSizeLetter = std::make_shared<CLabel>(41, 0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
|
||||
labelMapSizeLetter->setAutoRedraw(false);
|
||||
// FIXME: This -12 should not be needed, but for some reason CAnimImage displaced otherwise
|
||||
iconFolder = std::make_shared<CPicture>("lobby/iconFolder.png", -8, -12);
|
||||
iconFolder = std::make_shared<CPicture>(ImagePath::builtin("lobby/iconFolder.png"), -8, -12);
|
||||
iconFormat = std::make_shared<CAnimImage>(iconsFormats, 0, 0, 59, -12);
|
||||
iconVictoryCondition = std::make_shared<CAnimImage>(iconsVictory, 0, 0, 277, -12);
|
||||
iconLossCondition = std::make_shared<CAnimImage>(iconsLoss, 0, 0, 310, -12);
|
||||
|
@ -14,6 +14,7 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
class CMap;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
#include "../../lib/mapping/CMapInfo.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
|
||||
class CSlider;
|
||||
class CLabel;
|
||||
@ -81,9 +82,9 @@ class SelectionTab : public CIntObject
|
||||
std::shared_ptr<CPicture> image2;
|
||||
|
||||
Canvas createMinimapForLayer(std::unique_ptr<CMap> & map, int layer);
|
||||
std::vector<std::shared_ptr<IImage>> createMinimaps(ResourceID resource, int size);
|
||||
std::vector<std::shared_ptr<IImage>> createMinimaps(ResourcePath resource, int size);
|
||||
public:
|
||||
CMapInfoTooltipBox(std::string text, ResourceID resource, ESelectionScreen tabType);
|
||||
CMapInfoTooltipBox(std::string text, ResourcePath resource, ESelectionScreen tabType);
|
||||
};
|
||||
public:
|
||||
std::vector<std::shared_ptr<ElementInfo>> allItems;
|
||||
@ -134,8 +135,8 @@ private:
|
||||
auto checkSubfolder(std::string path);
|
||||
|
||||
bool isMapSupported(const CMapInfo & info);
|
||||
void parseMaps(const std::unordered_set<ResourceID> & files);
|
||||
void parseSaves(const std::unordered_set<ResourceID> & files);
|
||||
void parseCampaigns(const std::unordered_set<ResourceID> & files);
|
||||
std::unordered_set<ResourceID> getFiles(std::string dirURI, int resType);
|
||||
void parseMaps(const std::unordered_set<ResourcePath> & files);
|
||||
void parseSaves(const std::unordered_set<ResourcePath> & files);
|
||||
void parseCampaigns(const std::unordered_set<ResourcePath> & files);
|
||||
std::unordered_set<ResourcePath> getFiles(std::string dirURI, EResType resType);
|
||||
};
|
||||
|
@ -75,7 +75,7 @@ CCampaignScreen::CCampaignScreen(const JsonNode & config)
|
||||
|
||||
void CCampaignScreen::activate()
|
||||
{
|
||||
CCS->musich->playMusic("Music/MainMenu", true, false);
|
||||
CCS->musich->playMusic(AudioPath::builtin("Music/MainMenu"), true, false);
|
||||
|
||||
CWindowObject::activate();
|
||||
}
|
||||
@ -86,7 +86,7 @@ std::shared_ptr<CButton> CCampaignScreen::createExitButton(const JsonNode & butt
|
||||
if(!button["help"].isNull() && button["help"].Float() > 0)
|
||||
help = CGI->generaltexth->zelp[(size_t)button["help"].Float()];
|
||||
|
||||
return std::make_shared<CButton>(Point((int)button["x"].Float(), (int)button["y"].Float()), button["name"].String(), help, [=](){ close();}, EShortcut::GLOBAL_CANCEL);
|
||||
return std::make_shared<CButton>(Point((int)button["x"].Float(), (int)button["y"].Float()), AnimationPath::fromJson(button["name"]), help, [=](){ close();}, EShortcut::GLOBAL_CANCEL);
|
||||
}
|
||||
|
||||
CCampaignScreen::CCampaignButton::CCampaignButton(const JsonNode & config)
|
||||
@ -99,7 +99,7 @@ CCampaignScreen::CCampaignButton::CCampaignButton(const JsonNode & config)
|
||||
pos.h = 116;
|
||||
|
||||
campFile = config["file"].String();
|
||||
video = config["video"].String();
|
||||
video = VideoPath::fromJson(config["video"]);
|
||||
|
||||
status = config["open"].Bool() ? CCampaignScreen::ENABLED : CCampaignScreen::DISABLED;
|
||||
|
||||
@ -109,14 +109,14 @@ CCampaignScreen::CCampaignButton::CCampaignButton(const JsonNode & config)
|
||||
if(status != CCampaignScreen::DISABLED)
|
||||
{
|
||||
addUsedEvents(LCLICK | HOVER);
|
||||
graphicsImage = std::make_shared<CPicture>(config["image"].String());
|
||||
graphicsImage = std::make_shared<CPicture>(ImagePath::fromJson(config["image"]));
|
||||
|
||||
hoverLabel = std::make_shared<CLabel>(pos.w / 2, pos.h + 20, FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW, "");
|
||||
parent->addChild(hoverLabel.get());
|
||||
}
|
||||
|
||||
if(status == CCampaignScreen::COMPLETED)
|
||||
graphicsCompleted = std::make_shared<CPicture>("CAMPCHK");
|
||||
graphicsCompleted = std::make_shared<CPicture>(ImagePath::builtin("CAMPCHK"));
|
||||
}
|
||||
|
||||
void CCampaignScreen::CCampaignButton::show(Canvas & to)
|
||||
@ -128,17 +128,7 @@ void CCampaignScreen::CCampaignButton::show(Canvas & to)
|
||||
|
||||
// Play the campaign button video when the mouse cursor is placed over the button
|
||||
if(isHovered())
|
||||
{
|
||||
if(CCS->videoh->fname != video)
|
||||
CCS->videoh->open(video);
|
||||
|
||||
CCS->videoh->update(pos.x, pos.y, to.getInternalSurface(), true, false); // plays sequentially frame by frame, starts at the beginning when the video is over
|
||||
}
|
||||
else if(CCS->videoh->fname == video) // When you got out of the bounds of the button then close the video
|
||||
{
|
||||
CCS->videoh->close();
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
|
||||
void CCampaignScreen::CCampaignButton::clickReleased(const Point & cursorPosition)
|
||||
@ -149,6 +139,11 @@ void CCampaignScreen::CCampaignButton::clickReleased(const Point & cursorPositio
|
||||
|
||||
void CCampaignScreen::CCampaignButton::hover(bool on)
|
||||
{
|
||||
if (on)
|
||||
CCS->videoh->open(video);
|
||||
else
|
||||
CCS->videoh->close();
|
||||
|
||||
if(hoverLabel)
|
||||
{
|
||||
if(on)
|
||||
|
@ -37,7 +37,7 @@ private:
|
||||
CampaignStatus status;
|
||||
|
||||
std::string campFile; // the filename/resourcename of the campaign
|
||||
std::string video; // the resource name of the video
|
||||
VideoPath video; // the resource name of the video
|
||||
std::string hoverText;
|
||||
|
||||
void clickReleased(const Point & cursorPosition) override;
|
||||
|
@ -78,7 +78,7 @@ CMenuScreen::CMenuScreen(const JsonNode & configNode)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
|
||||
background = std::make_shared<CPicture>(config["background"].String());
|
||||
background = std::make_shared<CPicture>(ImagePath::fromJson(config["background"]));
|
||||
if(config["scalable"].Bool())
|
||||
background->scaleTo(GH.screenDimensions());
|
||||
|
||||
@ -114,9 +114,9 @@ void CMenuScreen::show(Canvas & to)
|
||||
|
||||
void CMenuScreen::activate()
|
||||
{
|
||||
CCS->musich->playMusic("Music/MainMenu", true, true);
|
||||
CCS->musich->playMusic(AudioPath::builtin("Music/MainMenu"), true, true);
|
||||
if(!config["video"].isNull())
|
||||
CCS->videoh->open(config["video"]["name"].String());
|
||||
CCS->videoh->open(VideoPath::fromJson(config["video"]["name"]));
|
||||
CIntObject::activate();
|
||||
}
|
||||
|
||||
@ -237,7 +237,7 @@ std::shared_ptr<CButton> CMenuEntry::createButton(CMenuScreen * parent, const Js
|
||||
|
||||
EShortcut shortcut = GH.shortcuts().findShortcut(button["shortcut"].String());
|
||||
|
||||
auto result = std::make_shared<CButton>(Point(posx, posy), button["name"].String(), help, command, shortcut);
|
||||
auto result = std::make_shared<CButton>(Point(posx, posy), AnimationPath::fromJson(button["name"]), help, command, shortcut);
|
||||
|
||||
if (button["center"].Bool())
|
||||
result->moveBy(Point(-result->pos.w/2, -result->pos.h/2));
|
||||
@ -262,7 +262,8 @@ CMenuEntry::CMenuEntry(CMenuScreen * parent, const JsonNode & config)
|
||||
}
|
||||
|
||||
CMainMenuConfig::CMainMenuConfig()
|
||||
: campaignSets(JsonNode(ResourceID("config/campaignSets.json"))), config(JsonNode(ResourceID("config/mainmenu.json")))
|
||||
: campaignSets(JsonPath::builtin("config/campaignSets.json"))
|
||||
, config(JsonPath::builtin("config/mainmenu.json"))
|
||||
{
|
||||
|
||||
}
|
||||
@ -291,7 +292,7 @@ CMainMenu::CMainMenu()
|
||||
GH.defActionsDef = 63;
|
||||
menu = std::make_shared<CMenuScreen>(CMainMenuConfig::get().getConfig()["window"]);
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
backgroundAroundMenu = std::make_shared<CFilledTexture>("DIBOXBCK", pos);
|
||||
backgroundAroundMenu = std::make_shared<CFilledTexture>(ImagePath::builtin("DIBOXBCK"), pos);
|
||||
}
|
||||
|
||||
CMainMenu::~CMainMenu()
|
||||
@ -374,7 +375,7 @@ void CMainMenu::openCampaignScreen(std::string name)
|
||||
|
||||
void CMainMenu::startTutorial()
|
||||
{
|
||||
ResourceID tutorialMap("Maps/Tutorial.tut", EResType::MAP);
|
||||
ResourcePath tutorialMap("Maps/Tutorial.tut", EResType::MAP);
|
||||
if(!CResourceHandler::get()->existsResource(tutorialMap))
|
||||
{
|
||||
CInfoWindow::showInfoDialog(CGI->generaltexth->translate("core.genrltxt.742"), std::vector<std::shared_ptr<CComponent>>(), PlayerColor(1));
|
||||
@ -397,7 +398,7 @@ std::shared_ptr<CMainMenu> CMainMenu::create()
|
||||
|
||||
std::shared_ptr<CPicture> CMainMenu::createPicture(const JsonNode & config)
|
||||
{
|
||||
return std::make_shared<CPicture>(config["name"].String(), (int)config["x"].Float(), (int)config["y"].Float());
|
||||
return std::make_shared<CPicture>(ImagePath::fromJson(config["name"]), (int)config["x"].Float(), (int)config["y"].Float());
|
||||
}
|
||||
|
||||
CMultiMode::CMultiMode(ESelectionScreen ScreenType)
|
||||
@ -405,20 +406,20 @@ CMultiMode::CMultiMode(ESelectionScreen ScreenType)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
|
||||
background = std::make_shared<CPicture>("MUPOPUP.bmp");
|
||||
background = std::make_shared<CPicture>(ImagePath::builtin("MUPOPUP.bmp"));
|
||||
pos = background->center(); //center, window has size of bg graphic
|
||||
|
||||
picture = std::make_shared<CPicture>("MUMAP.bmp", 16, 77);
|
||||
picture = std::make_shared<CPicture>(ImagePath::builtin("MUMAP.bmp"), 16, 77);
|
||||
|
||||
statusBar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(7, 465, 440, 18), 7, 465));
|
||||
playerName = std::make_shared<CTextInput>(Rect(19, 436, 334, 16), background->getSurface());
|
||||
playerName->setText(getPlayerName());
|
||||
playerName->cb += std::bind(&CMultiMode::onNameChange, this, _1);
|
||||
|
||||
buttonHotseat = std::make_shared<CButton>(Point(373, 78), "MUBHOT.DEF", CGI->generaltexth->zelp[266], std::bind(&CMultiMode::hostTCP, this));
|
||||
buttonHost = std::make_shared<CButton>(Point(373, 78 + 57 * 1), "MUBHOST.DEF", CButton::tooltip(CGI->generaltexth->translate("vcmi.mainMenu.hostTCP"), ""), std::bind(&CMultiMode::hostTCP, this));
|
||||
buttonJoin = std::make_shared<CButton>(Point(373, 78 + 57 * 2), "MUBJOIN.DEF", CButton::tooltip(CGI->generaltexth->translate("vcmi.mainMenu.joinTCP"), ""), std::bind(&CMultiMode::joinTCP, this));
|
||||
buttonCancel = std::make_shared<CButton>(Point(373, 424), "MUBCANC.DEF", CGI->generaltexth->zelp[288], [=](){ close();}, EShortcut::GLOBAL_CANCEL);
|
||||
buttonHotseat = std::make_shared<CButton>(Point(373, 78), AnimationPath::builtin("MUBHOT.DEF"), CGI->generaltexth->zelp[266], std::bind(&CMultiMode::hostTCP, this));
|
||||
buttonHost = std::make_shared<CButton>(Point(373, 78 + 57 * 1), AnimationPath::builtin("MUBHOST.DEF"), CButton::tooltip(CGI->generaltexth->translate("vcmi.mainMenu.hostTCP"), ""), std::bind(&CMultiMode::hostTCP, this));
|
||||
buttonJoin = std::make_shared<CButton>(Point(373, 78 + 57 * 2), AnimationPath::builtin("MUBJOIN.DEF"), CButton::tooltip(CGI->generaltexth->translate("vcmi.mainMenu.joinTCP"), ""), std::bind(&CMultiMode::joinTCP, this));
|
||||
buttonCancel = std::make_shared<CButton>(Point(373, 424), AnimationPath::builtin("MUBCANC.DEF"), CGI->generaltexth->zelp[288], [=](){ close();}, EShortcut::GLOBAL_CANCEL);
|
||||
}
|
||||
|
||||
void CMultiMode::hostTCP()
|
||||
@ -453,7 +454,7 @@ CMultiPlayers::CMultiPlayers(const std::string & firstPlayer, ESelectionScreen S
|
||||
: loadMode(LoadMode), screenType(ScreenType), host(Host)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
background = std::make_shared<CPicture>("MUHOTSEA.bmp");
|
||||
background = std::make_shared<CPicture>(ImagePath::builtin("MUHOTSEA.bmp"));
|
||||
pos = background->center(); //center, window has size of bg graphic
|
||||
|
||||
std::string text = CGI->generaltexth->allTexts[446];
|
||||
@ -466,8 +467,8 @@ CMultiPlayers::CMultiPlayers(const std::string & firstPlayer, ESelectionScreen S
|
||||
inputNames[i]->cb += std::bind(&CMultiPlayers::onChange, this, _1);
|
||||
}
|
||||
|
||||
buttonOk = std::make_shared<CButton>(Point(95, 338), "MUBCHCK.DEF", CGI->generaltexth->zelp[560], std::bind(&CMultiPlayers::enterSelectionScreen, this), EShortcut::GLOBAL_ACCEPT);
|
||||
buttonCancel = std::make_shared<CButton>(Point(205, 338), "MUBCANC.DEF", CGI->generaltexth->zelp[561], [=](){ close();}, EShortcut::GLOBAL_CANCEL);
|
||||
buttonOk = std::make_shared<CButton>(Point(95, 338), AnimationPath::builtin("MUBCHCK.DEF"), CGI->generaltexth->zelp[560], std::bind(&CMultiPlayers::enterSelectionScreen, this), EShortcut::GLOBAL_ACCEPT);
|
||||
buttonCancel = std::make_shared<CButton>(Point(205, 338), AnimationPath::builtin("MUBCANC.DEF"), CGI->generaltexth->zelp[561], [=](){ close();}, EShortcut::GLOBAL_CANCEL);
|
||||
statusBar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(7, 381, 348, 18), 7, 381));
|
||||
|
||||
inputNames[0]->setText(firstPlayer, true);
|
||||
@ -498,7 +499,7 @@ void CMultiPlayers::enterSelectionScreen()
|
||||
CSimpleJoinScreen::CSimpleJoinScreen(bool host)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
background = std::make_shared<CPicture>("MUDIALOG.bmp"); // address background
|
||||
background = std::make_shared<CPicture>(ImagePath::builtin("MUDIALOG.bmp")); // address background
|
||||
pos = background->center(); //center, window has size of bg graphic (x,y = 396,278 w=232 h=212)
|
||||
|
||||
textTitle = std::make_shared<CTextBox>("", Rect(20, 20, 205, 50), 0, FONT_BIG, ETextAlignment::CENTER, Colors::WHITE);
|
||||
@ -515,14 +516,14 @@ CSimpleJoinScreen::CSimpleJoinScreen(bool host)
|
||||
inputAddress->cb += std::bind(&CSimpleJoinScreen::onChange, this, _1);
|
||||
inputPort->cb += std::bind(&CSimpleJoinScreen::onChange, this, _1);
|
||||
inputPort->filters += std::bind(&CTextInput::numberFilter, _1, _2, 0, 65535);
|
||||
buttonOk = std::make_shared<CButton>(Point(26, 142), "MUBCHCK.DEF", CGI->generaltexth->zelp[560], std::bind(&CSimpleJoinScreen::connectToServer, this), EShortcut::GLOBAL_ACCEPT);
|
||||
buttonOk = std::make_shared<CButton>(Point(26, 142), AnimationPath::builtin("MUBCHCK.DEF"), CGI->generaltexth->zelp[560], std::bind(&CSimpleJoinScreen::connectToServer, this), EShortcut::GLOBAL_ACCEPT);
|
||||
|
||||
inputAddress->giveFocus();
|
||||
}
|
||||
inputAddress->setText(host ? CServerHandler::localhostAddress : CSH->getHostAddress(), true);
|
||||
inputPort->setText(std::to_string(CSH->getHostPort()), true);
|
||||
|
||||
buttonCancel = std::make_shared<CButton>(Point(142, 142), "MUBCANC.DEF", CGI->generaltexth->zelp[561], std::bind(&CSimpleJoinScreen::leaveScreen, this), EShortcut::GLOBAL_CANCEL);
|
||||
buttonCancel = std::make_shared<CButton>(Point(142, 142), AnimationPath::builtin("MUBCANC.DEF"), CGI->generaltexth->zelp[561], std::bind(&CSimpleJoinScreen::leaveScreen, this), EShortcut::GLOBAL_CANCEL);
|
||||
statusBar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(7, 186, 218, 18), 7, 186));
|
||||
}
|
||||
|
||||
@ -601,7 +602,7 @@ CLoadingScreen::CLoadingScreen()
|
||||
|
||||
for(int i = 0; i < blocksAmount; ++i)
|
||||
{
|
||||
progressBlocks.push_back(std::make_shared<CAnimImage>(conf["name"].String(), i, 0, posx + i * blockSize, posy));
|
||||
progressBlocks.push_back(std::make_shared<CAnimImage>(AnimationPath::fromJson(conf["name"]), i, 0, posx + i * blockSize, posy));
|
||||
progressBlocks.back()->deactivate();
|
||||
progressBlocks.back()->visible = false;
|
||||
}
|
||||
@ -626,24 +627,24 @@ void CLoadingScreen::tick(uint32_t msPassed)
|
||||
}
|
||||
}
|
||||
|
||||
std::string CLoadingScreen::getBackground()
|
||||
ImagePath CLoadingScreen::getBackground()
|
||||
{
|
||||
std::string fname = "loadbar";
|
||||
ImagePath fname = ImagePath::builtin("loadbar");
|
||||
const auto & conf = CMainMenuConfig::get().getConfig()["loading"];
|
||||
|
||||
if(conf.isStruct())
|
||||
{
|
||||
if(conf["background"].isVector())
|
||||
return RandomGeneratorUtil::nextItem(conf["background"].Vector(), CRandomGenerator::getDefault())->String();
|
||||
return ImagePath::fromJson(*RandomGeneratorUtil::nextItem(conf["background"].Vector(), CRandomGenerator::getDefault()));
|
||||
|
||||
if(conf["background"].isString())
|
||||
return conf["background"].String();
|
||||
return ImagePath::fromJson(conf["background"]);
|
||||
|
||||
return fname;
|
||||
}
|
||||
|
||||
if(conf.isVector() && !conf.Vector().empty())
|
||||
return RandomGeneratorUtil::nextItem(conf.Vector(), CRandomGenerator::getDefault())->String();
|
||||
return ImagePath::fromJson(*RandomGeneratorUtil::nextItem(conf.Vector(), CRandomGenerator::getDefault()));
|
||||
|
||||
return fname;
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ class CLoadingScreen : virtual public CWindowObject, virtual public Load::Progre
|
||||
{
|
||||
std::vector<std::shared_ptr<CAnimImage>> progressBlocks;
|
||||
|
||||
std::string getBackground();
|
||||
ImagePath getBackground();
|
||||
|
||||
public:
|
||||
CLoadingScreen();
|
||||
|
@ -28,7 +28,7 @@ CPrologEpilogVideo::CPrologEpilogVideo(CampaignScenarioPrologEpilog _spe, std::f
|
||||
updateShadow();
|
||||
|
||||
CCS->videoh->open(spe.prologVideo);
|
||||
CCS->musich->playMusic("Music/" + spe.prologMusic, true, true);
|
||||
CCS->musich->playMusic(spe.prologMusic, true, true);
|
||||
// MPTODO: Custom campaign crashing on this?
|
||||
// voiceSoundHandle = CCS->soundh->playSound(CCampaignHandler::prologVoiceName(spe.prologVideo));
|
||||
|
||||
|
@ -26,7 +26,7 @@ CreditsScreen::CreditsScreen(Rect rect)
|
||||
pos.h = rect.h;
|
||||
setRedrawParent(true);
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
auto textFile = CResourceHandler::get()->load(ResourceID("DATA/CREDITS.TXT"))->readAll();
|
||||
auto textFile = CResourceHandler::get()->load(ResourcePath("DATA/CREDITS.TXT"))->readAll();
|
||||
std::string text((char *)textFile.first.get(), textFile.second);
|
||||
size_t firstQuote = text.find('\"') + 1;
|
||||
text = text.substr(firstQuote, text.find('\"', firstQuote) - firstQuote);
|
||||
|
@ -15,9 +15,11 @@
|
||||
#include "mapHandler.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
|
||||
@ -94,7 +96,7 @@ MapTileStorage::MapTileStorage(size_t capacity)
|
||||
{
|
||||
}
|
||||
|
||||
void MapTileStorage::load(size_t index, const std::string & filename, EImageBlitMode blitMode)
|
||||
void MapTileStorage::load(size_t index, const AnimationPath & filename, EImageBlitMode blitMode)
|
||||
{
|
||||
auto & terrainAnimations = animations[index];
|
||||
|
||||
@ -102,11 +104,11 @@ void MapTileStorage::load(size_t index, const std::string & filename, EImageBlit
|
||||
{
|
||||
if (!filename.empty())
|
||||
{
|
||||
entry = std::make_unique<CAnimation>(filename);
|
||||
entry = GH.renderHandler().loadAnimation(filename);
|
||||
entry->preload();
|
||||
}
|
||||
else
|
||||
entry = std::make_unique<CAnimation>();
|
||||
entry = GH.renderHandler().createAnimation();
|
||||
|
||||
for(size_t i = 0; i < entry->size(); ++i)
|
||||
entry->getImage(i)->setBlitMode(blitMode);
|
||||
@ -247,7 +249,7 @@ uint8_t MapRendererRoad::checksum(IMapRendererContext & context, const int3 & co
|
||||
MapRendererBorder::MapRendererBorder()
|
||||
{
|
||||
emptyFill = std::make_unique<Canvas>(Point(32,32));
|
||||
animation = std::make_unique<CAnimation>("EDG");
|
||||
animation = GH.renderHandler().loadAnimation(AnimationPath::builtin("EDG"));
|
||||
animation->preload();
|
||||
}
|
||||
|
||||
@ -309,9 +311,9 @@ uint8_t MapRendererBorder::checksum(IMapRendererContext & context, const int3 &
|
||||
|
||||
MapRendererFow::MapRendererFow()
|
||||
{
|
||||
fogOfWarFullHide = std::make_unique<CAnimation>("TSHRC");
|
||||
fogOfWarFullHide = GH.renderHandler().loadAnimation(AnimationPath::builtin("TSHRC"));
|
||||
fogOfWarFullHide->preload();
|
||||
fogOfWarPartialHide = std::make_unique<CAnimation>("TSHRE");
|
||||
fogOfWarPartialHide = GH.renderHandler().loadAnimation(AnimationPath::builtin("TSHRE"));
|
||||
fogOfWarPartialHide->preload();
|
||||
|
||||
for(size_t i = 0; i < fogOfWarFullHide->size(); ++i)
|
||||
@ -387,14 +389,14 @@ std::shared_ptr<CAnimation> MapRendererObjects::getBaseAnimation(const CGObjectI
|
||||
return getAnimation(info->animationFile, generateMovementGroups);
|
||||
}
|
||||
|
||||
std::shared_ptr<CAnimation> MapRendererObjects::getAnimation(const std::string & filename, bool generateMovementGroups)
|
||||
std::shared_ptr<CAnimation> MapRendererObjects::getAnimation(const AnimationPath & filename, bool generateMovementGroups)
|
||||
{
|
||||
auto it = animations.find(filename);
|
||||
|
||||
if(it != animations.end())
|
||||
return it->second;
|
||||
|
||||
auto ret = std::make_shared<CAnimation>(filename);
|
||||
auto ret = GH.renderHandler().loadAnimation(filename);
|
||||
animations[filename] = ret;
|
||||
ret->preload();
|
||||
|
||||
@ -422,7 +424,7 @@ std::shared_ptr<CAnimation> MapRendererObjects::getFlagAnimation(const CGObjectI
|
||||
{
|
||||
assert(dynamic_cast<const CGHeroInstance *>(obj) != nullptr);
|
||||
assert(obj->tempOwner.isValidPlayer());
|
||||
return getAnimation(heroFlags[obj->tempOwner.getNum()], true);
|
||||
return getAnimation(AnimationPath::builtin(heroFlags[obj->tempOwner.getNum()]), true);
|
||||
}
|
||||
|
||||
if(obj->ID == Obj::BOAT)
|
||||
@ -557,10 +559,10 @@ uint8_t MapRendererObjects::checksum(IMapRendererContext & context, const int3 &
|
||||
}
|
||||
|
||||
MapRendererOverlay::MapRendererOverlay()
|
||||
: imageGrid(IImage::createFromFile("debug/grid", EImageBlitMode::ALPHA))
|
||||
, imageBlocked(IImage::createFromFile("debug/blocked", EImageBlitMode::ALPHA))
|
||||
, imageVisitable(IImage::createFromFile("debug/visitable", EImageBlitMode::ALPHA))
|
||||
, imageSpellRange(IImage::createFromFile("debug/spellRange", EImageBlitMode::ALPHA))
|
||||
: imageGrid(GH.renderHandler().loadImage(ImagePath::builtin("debug/grid"), EImageBlitMode::ALPHA))
|
||||
, imageBlocked(GH.renderHandler().loadImage(ImagePath::builtin("debug/blocked"), EImageBlitMode::ALPHA))
|
||||
, imageVisitable(GH.renderHandler().loadImage(ImagePath::builtin("debug/visitable"), EImageBlitMode::ALPHA))
|
||||
, imageSpellRange(GH.renderHandler().loadImage(ImagePath::builtin("debug/spellRange"), EImageBlitMode::ALPHA))
|
||||
{
|
||||
|
||||
}
|
||||
@ -616,7 +618,7 @@ uint8_t MapRendererOverlay::checksum(IMapRendererContext & context, const int3 &
|
||||
}
|
||||
|
||||
MapRendererPath::MapRendererPath()
|
||||
: pathNodes(new CAnimation("ADAG"))
|
||||
: pathNodes(GH.renderHandler().loadAnimation(AnimationPath::builtin("ADAG")))
|
||||
{
|
||||
pathNodes->preload();
|
||||
}
|
||||
|
@ -9,6 +9,8 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class int3;
|
||||
@ -21,16 +23,16 @@ class CAnimation;
|
||||
class IImage;
|
||||
class Canvas;
|
||||
class IMapRendererContext;
|
||||
enum class EImageBlitMode : uint8_t;
|
||||
enum class EImageBlitMode;
|
||||
|
||||
class MapTileStorage
|
||||
{
|
||||
using TerrainAnimation = std::array<std::unique_ptr<CAnimation>, 4>;
|
||||
using TerrainAnimation = std::array<std::shared_ptr<CAnimation>, 4>;
|
||||
std::vector<TerrainAnimation> animations;
|
||||
|
||||
public:
|
||||
explicit MapTileStorage(size_t capacity);
|
||||
void load(size_t index, const std::string & filename, EImageBlitMode blitMode);
|
||||
void load(size_t index, const AnimationPath & filename, EImageBlitMode blitMode);
|
||||
std::shared_ptr<IImage> find(size_t fileIndex, size_t rotationIndex, size_t imageIndex);
|
||||
};
|
||||
|
||||
@ -69,13 +71,13 @@ public:
|
||||
|
||||
class MapRendererObjects
|
||||
{
|
||||
std::unordered_map<std::string, std::shared_ptr<CAnimation>> animations;
|
||||
std::map<AnimationPath, std::shared_ptr<CAnimation>> animations;
|
||||
|
||||
std::shared_ptr<CAnimation> getBaseAnimation(const CGObjectInstance * obj);
|
||||
std::shared_ptr<CAnimation> getFlagAnimation(const CGObjectInstance * obj);
|
||||
std::shared_ptr<CAnimation> getOverlayAnimation(const CGObjectInstance * obj);
|
||||
|
||||
std::shared_ptr<CAnimation> getAnimation(const std::string & filename, bool generateMovementGroups);
|
||||
std::shared_ptr<CAnimation> getAnimation(const AnimationPath & filename, bool generateMovementGroups);
|
||||
|
||||
std::shared_ptr<IImage> getImage(IMapRendererContext & context, const CGObjectInstance * obj, const std::shared_ptr<CAnimation> & animation) const;
|
||||
|
||||
@ -89,7 +91,7 @@ public:
|
||||
|
||||
class MapRendererBorder
|
||||
{
|
||||
std::unique_ptr<CAnimation> animation;
|
||||
std::shared_ptr<CAnimation> animation;
|
||||
std::unique_ptr<Canvas> emptyFill;
|
||||
|
||||
size_t getIndexForTile(IMapRendererContext & context, const int3 & coordinates);
|
||||
@ -103,8 +105,8 @@ public:
|
||||
|
||||
class MapRendererFow
|
||||
{
|
||||
std::unique_ptr<CAnimation> fogOfWarFullHide;
|
||||
std::unique_ptr<CAnimation> fogOfWarPartialHide;
|
||||
std::shared_ptr<CAnimation> fogOfWarFullHide;
|
||||
std::shared_ptr<CAnimation> fogOfWarPartialHide;
|
||||
|
||||
public:
|
||||
MapRendererFow();
|
||||
@ -115,7 +117,7 @@ public:
|
||||
|
||||
class MapRendererPath
|
||||
{
|
||||
std::unique_ptr<CAnimation> pathNodes;
|
||||
std::shared_ptr<CAnimation> pathNodes;
|
||||
|
||||
size_t selectImageReachability(bool reachableToday, size_t imageIndex);
|
||||
size_t selectImageCross(bool reachableToday, const int3 & curr);
|
||||
|
@ -18,6 +18,9 @@
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
|
||||
#include "../gui/CGuiHandler.h"
|
||||
|
||||
#include "../../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../../lib/int3.h"
|
||||
@ -28,7 +31,7 @@ MapViewCache::MapViewCache(const std::shared_ptr<MapViewModel> & model)
|
||||
: model(model)
|
||||
, cachedLevel(0)
|
||||
, mapRenderer(new MapRenderer())
|
||||
, iconsStorage(new CAnimation("VwSymbol"))
|
||||
, iconsStorage(GH.renderHandler().loadAnimation(AnimationPath::builtin("VwSymbol")))
|
||||
, intermediate(new Canvas(Point(32, 32)))
|
||||
, terrain(new Canvas(model->getCacheDimensionsPixels()))
|
||||
, terrainTransition(new Canvas(model->getPixelsVisibleDimensions()))
|
||||
|
@ -52,7 +52,7 @@ class MapViewCache
|
||||
std::unique_ptr<Canvas> intermediate;
|
||||
std::unique_ptr<MapRenderer> mapRenderer;
|
||||
|
||||
std::unique_ptr<CAnimation> iconsStorage;
|
||||
std::shared_ptr<CAnimation> iconsStorage;
|
||||
|
||||
Canvas getTile(const int3 & coordinates);
|
||||
void updateTile(const std::shared_ptr<IMapRendererContext> & context, const int3 & coordinates);
|
||||
|
@ -22,7 +22,7 @@ std::shared_ptr<IImage> CAnimation::getFromExtraDef(std::string filename)
|
||||
size_t pos = filename.find(':');
|
||||
if (pos == -1)
|
||||
return nullptr;
|
||||
CAnimation anim(filename.substr(0, pos));
|
||||
CAnimation anim(AnimationPath::builtinTODO(filename.substr(0, pos)));
|
||||
pos++;
|
||||
size_t frame = atoi(filename.c_str()+pos);
|
||||
size_t group = 0;
|
||||
@ -69,7 +69,7 @@ bool CAnimation::loadFrame(size_t frame, size_t group)
|
||||
// still here? image is missing
|
||||
|
||||
printError(frame, group, "LoadFrame");
|
||||
images[group][frame] = std::make_shared<SDLImage>("DEFAULT", EImageBlitMode::ALPHA);
|
||||
images[group][frame] = std::make_shared<SDLImage>(ImagePath::builtin("DEFAULT"), EImageBlitMode::ALPHA);
|
||||
}
|
||||
else //load from separate file
|
||||
{
|
||||
@ -144,7 +144,7 @@ void CAnimation::exportBitmaps(const boost::filesystem::path& path) const
|
||||
return;
|
||||
}
|
||||
|
||||
boost::filesystem::path actualPath = path / "SPRITES" / name;
|
||||
boost::filesystem::path actualPath = path / "SPRITES" / name.getName();
|
||||
boost::filesystem::create_directories(actualPath);
|
||||
|
||||
size_t counter = 0;
|
||||
@ -179,16 +179,15 @@ void CAnimation::init()
|
||||
source[defEntry.first].resize(defEntry.second);
|
||||
}
|
||||
|
||||
ResourceID resID(std::string("SPRITES/") + name, EResType::TEXT);
|
||||
if (vstd::contains(graphics->imageLists, name.getName()))
|
||||
initFromJson(graphics->imageLists[name.getName()]);
|
||||
|
||||
if (vstd::contains(graphics->imageLists, resID.getName()))
|
||||
initFromJson(graphics->imageLists[resID.getName()]);
|
||||
|
||||
auto configList = CResourceHandler::get()->getResourcesWithName(resID);
|
||||
auto jsonResource = name.toType<EResType::JSON>();
|
||||
auto configList = CResourceHandler::get()->getResourcesWithName(jsonResource);
|
||||
|
||||
for(auto & loader : configList)
|
||||
{
|
||||
auto stream = loader->load(resID);
|
||||
auto stream = loader->load(jsonResource);
|
||||
std::unique_ptr<ui8[]> textData(new ui8[stream->getSize()]);
|
||||
stream->read(textData.get(), stream->getSize());
|
||||
|
||||
@ -200,34 +199,25 @@ void CAnimation::init()
|
||||
|
||||
void CAnimation::printError(size_t frame, size_t group, std::string type) const
|
||||
{
|
||||
logGlobal->error("%s error: Request for frame not present in CAnimation! File name: %s, Group: %d, Frame: %d", type, name, group, frame);
|
||||
logGlobal->error("%s error: Request for frame not present in CAnimation! File name: %s, Group: %d, Frame: %d", type, name.getOriginalName(), group, frame);
|
||||
}
|
||||
|
||||
CAnimation::CAnimation(std::string Name):
|
||||
name(Name),
|
||||
CAnimation::CAnimation(const AnimationPath & Name):
|
||||
name(boost::starts_with(Name.getName(), "SPRITES") ? Name : Name.addPrefix("SPRITES/")),
|
||||
preloaded(false),
|
||||
defFile()
|
||||
{
|
||||
size_t dotPos = name.find_last_of('.');
|
||||
if ( dotPos!=-1 )
|
||||
name.erase(dotPos);
|
||||
std::transform(name.begin(), name.end(), name.begin(), toupper);
|
||||
|
||||
ResourceID resource(std::string("SPRITES/") + name, EResType::ANIMATION);
|
||||
|
||||
if(CResourceHandler::get()->existsResource(resource))
|
||||
if(CResourceHandler::get()->existsResource(name))
|
||||
defFile = std::make_shared<CDefFile>(name);
|
||||
|
||||
init();
|
||||
|
||||
if(source.empty())
|
||||
logAnim->error("Animation %s failed to load", Name);
|
||||
logAnim->error("Animation %s failed to load", Name.getOriginalName());
|
||||
}
|
||||
|
||||
CAnimation::CAnimation():
|
||||
name(""),
|
||||
preloaded(false),
|
||||
defFile()
|
||||
preloaded(false)
|
||||
{
|
||||
init();
|
||||
}
|
||||
@ -238,13 +228,13 @@ void CAnimation::duplicateImage(const size_t sourceGroup, const size_t sourceFra
|
||||
{
|
||||
if(!source.count(sourceGroup))
|
||||
{
|
||||
logAnim->error("Group %d missing in %s", sourceGroup, name);
|
||||
logAnim->error("Group %d missing in %s", sourceGroup, name.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
if(source[sourceGroup].size() <= sourceFrame)
|
||||
{
|
||||
logAnim->error("Frame [%d %d] missing in %s", sourceGroup, sourceFrame, name);
|
||||
logAnim->error("Frame [%d %d] missing in %s", sourceGroup, sourceFrame, name.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -253,7 +243,7 @@ void CAnimation::duplicateImage(const size_t sourceGroup, const size_t sourceFra
|
||||
|
||||
if(clone.getType() == JsonNode::JsonType::DATA_NULL)
|
||||
{
|
||||
std::string temp = name+":"+std::to_string(sourceGroup)+":"+std::to_string(sourceFrame);
|
||||
std::string temp = name.getName()+":"+std::to_string(sourceGroup)+":"+std::to_string(sourceFrame);
|
||||
clone["file"].String() = temp;
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/GameConstants.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class JsonNode;
|
||||
@ -17,6 +18,7 @@ VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class CDefFile;
|
||||
class IImage;
|
||||
class RenderHandler;
|
||||
|
||||
/// Class for handling animation
|
||||
class CAnimation
|
||||
@ -29,7 +31,7 @@ private:
|
||||
std::map<size_t, std::map<size_t, std::shared_ptr<IImage> > > images;
|
||||
|
||||
//animation file name
|
||||
std::string name;
|
||||
AnimationPath name;
|
||||
|
||||
bool preloaded;
|
||||
|
||||
@ -53,7 +55,7 @@ private:
|
||||
std::shared_ptr<IImage> getFromExtraDef(std::string filename);
|
||||
|
||||
public:
|
||||
CAnimation(std::string Name);
|
||||
CAnimation(const AnimationPath & Name);
|
||||
CAnimation();
|
||||
~CAnimation();
|
||||
|
||||
|
@ -21,7 +21,7 @@ namespace BitmapHandler
|
||||
{
|
||||
SDL_Surface * loadH3PCX(ui8 * data, size_t size);
|
||||
|
||||
SDL_Surface * loadBitmapFromDir(std::string path, std::string fname);
|
||||
SDL_Surface * loadBitmapFromDir(const ImagePath & path);
|
||||
}
|
||||
|
||||
bool isPCX(const ui8 *header)//check whether file can be PCX according to header
|
||||
@ -103,28 +103,23 @@ SDL_Surface * BitmapHandler::loadH3PCX(ui8 * pcx, size_t size)
|
||||
return ret;
|
||||
}
|
||||
|
||||
SDL_Surface * BitmapHandler::loadBitmapFromDir(std::string path, std::string fname)
|
||||
SDL_Surface * BitmapHandler::loadBitmapFromDir(const ImagePath & path)
|
||||
{
|
||||
if(!fname.size())
|
||||
{
|
||||
logGlobal->warn("Call to loadBitmap with void fname!");
|
||||
return nullptr;
|
||||
}
|
||||
if (!CResourceHandler::get()->existsResource(ResourceID(path + fname, EResType::IMAGE)))
|
||||
if (!CResourceHandler::get()->existsResource(path))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SDL_Surface * ret=nullptr;
|
||||
|
||||
auto readFile = CResourceHandler::get()->load(ResourceID(path + fname, EResType::IMAGE))->readAll();
|
||||
auto readFile = CResourceHandler::get()->load(path)->readAll();
|
||||
|
||||
if (isPCX(readFile.first.get()))
|
||||
{//H3-style PCX
|
||||
ret = loadH3PCX(readFile.first.get(), readFile.second);
|
||||
if (!ret)
|
||||
{
|
||||
logGlobal->error("Failed to open %s as H3 PCX!", fname);
|
||||
logGlobal->error("Failed to open %s as H3 PCX!", path.getOriginalName());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@ -146,7 +141,7 @@ SDL_Surface * BitmapHandler::loadBitmapFromDir(std::string path, std::string fna
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->error("Failed to open %s via SDL_Image", fname);
|
||||
logGlobal->error("Failed to open %s via SDL_Image", path.getOriginalName());
|
||||
logGlobal->error("Reason: %s", IMG_GetError());
|
||||
return nullptr;
|
||||
}
|
||||
@ -187,19 +182,29 @@ SDL_Surface * BitmapHandler::loadBitmapFromDir(std::string path, std::string fna
|
||||
{
|
||||
CSDL_Ext::setDefaultColorKey(ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SDL_Surface * BitmapHandler::loadBitmap(std::string fname)
|
||||
SDL_Surface * BitmapHandler::loadBitmap(const ImagePath & fname)
|
||||
{
|
||||
SDL_Surface * bitmap = nullptr;
|
||||
|
||||
if (!(bitmap = loadBitmapFromDir("DATA/", fname)) &&
|
||||
!(bitmap = loadBitmapFromDir("SPRITES/", fname)))
|
||||
if(fname.empty())
|
||||
{
|
||||
logGlobal->error("Error: Failed to find file %s", fname);
|
||||
logGlobal->warn("Call to loadBitmap with void fname!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
SDL_Surface * bitmap = loadBitmapFromDir(fname);
|
||||
if (bitmap != nullptr)
|
||||
return bitmap;
|
||||
|
||||
SDL_Surface * bitmapData = loadBitmapFromDir(fname.addPrefix("DATA/"));
|
||||
if (bitmapData != nullptr)
|
||||
return bitmapData;
|
||||
|
||||
SDL_Surface * bitmapSprites = loadBitmapFromDir(fname.addPrefix("SPRITES/"));
|
||||
if (bitmapSprites != nullptr)
|
||||
return bitmapSprites;
|
||||
|
||||
logGlobal->error("Error: Failed to find file %s", fname.getOriginalName());
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -9,10 +9,12 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
|
||||
struct SDL_Surface;
|
||||
|
||||
namespace BitmapHandler
|
||||
{
|
||||
//Load file from /DATA or /SPRITES
|
||||
SDL_Surface * loadBitmap(std::string fname);
|
||||
SDL_Surface * loadBitmap(const ImagePath & fname);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ class CFileCache
|
||||
static const int cacheSize = 50; //Max number of cached files
|
||||
struct FileData
|
||||
{
|
||||
ResourceID name;
|
||||
AnimationPath name;
|
||||
size_t size;
|
||||
std::unique_ptr<ui8[]> data;
|
||||
|
||||
@ -34,7 +34,7 @@ class CFileCache
|
||||
std::copy(data.get(), data.get() + size, ret.get());
|
||||
return ret;
|
||||
}
|
||||
FileData(ResourceID name_, size_t size_, std::unique_ptr<ui8[]> data_):
|
||||
FileData(AnimationPath name_, size_t size_, std::unique_ptr<ui8[]> data_):
|
||||
name{std::move(name_)},
|
||||
size{size_},
|
||||
data{std::move(data_)}
|
||||
@ -43,7 +43,7 @@ class CFileCache
|
||||
|
||||
std::deque<FileData> cache;
|
||||
public:
|
||||
std::unique_ptr<ui8[]> getCachedFile(ResourceID rid)
|
||||
std::unique_ptr<ui8[]> getCachedFile(AnimationPath rid)
|
||||
{
|
||||
for(auto & file : cache)
|
||||
{
|
||||
@ -97,7 +97,7 @@ static bool colorsSimilar (const SDL_Color & lhs, const SDL_Color & rhs)
|
||||
return std::abs(diffR) < threshold && std::abs(diffG) < threshold && std::abs(diffB) < threshold && std::abs(diffA) < threshold;
|
||||
}
|
||||
|
||||
CDefFile::CDefFile(std::string Name):
|
||||
CDefFile::CDefFile(const AnimationPath & Name):
|
||||
data(nullptr),
|
||||
palette(nullptr)
|
||||
{
|
||||
@ -124,7 +124,7 @@ CDefFile::CDefFile(std::string Name):
|
||||
{0, 0, 0, 64 } // shadow border below selection ( used in battle def's )
|
||||
};
|
||||
|
||||
data = animationCache.getCachedFile(ResourceID(std::string("SPRITES/") + Name, EResType::ANIMATION));
|
||||
data = animationCache.getCachedFile(Name);
|
||||
|
||||
palette = std::unique_ptr<SDL_Color[]>(new SDL_Color[256]);
|
||||
int it = 0;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/vcmi_endian.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
|
||||
class IImageLoader;
|
||||
struct SDL_Color;
|
||||
@ -39,7 +40,7 @@ private:
|
||||
std::unique_ptr<SDL_Color[]> palette;
|
||||
|
||||
public:
|
||||
CDefFile(std::string Name);
|
||||
CDefFile(const AnimationPath & Name);
|
||||
~CDefFile();
|
||||
|
||||
//load frame as SDL_Surface
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "../renderSDL/CTrueTypeFont.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
#include "../lib/filesystem/CBinaryReader.h"
|
||||
@ -44,7 +46,7 @@ Graphics * graphics = nullptr;
|
||||
|
||||
void Graphics::loadPaletteAndColors()
|
||||
{
|
||||
auto textFile = CResourceHandler::get()->load(ResourceID("DATA/PLAYERS.PAL"))->readAll();
|
||||
auto textFile = CResourceHandler::get()->load(ResourcePath("DATA/PLAYERS.PAL"))->readAll();
|
||||
std::string pals((char*)textFile.first.get(), textFile.second);
|
||||
|
||||
int startPoint = 24; //beginning byte; used to read
|
||||
@ -62,7 +64,7 @@ void Graphics::loadPaletteAndColors()
|
||||
}
|
||||
}
|
||||
|
||||
auto stream = CResourceHandler::get()->load(ResourceID("config/NEUTRAL.PAL"));
|
||||
auto stream = CResourceHandler::get()->load(ResourcePath("config/NEUTRAL.PAL"));
|
||||
CBinaryReader reader(stream.get());
|
||||
|
||||
for(int i=0; i<32; ++i)
|
||||
@ -102,10 +104,10 @@ void Graphics::initializeBattleGraphics()
|
||||
allConfigs.insert(allConfigs.begin(), ModScope::scopeBuiltin());
|
||||
for(auto & mod : allConfigs)
|
||||
{
|
||||
if(!CResourceHandler::get(mod)->existsResource(ResourceID("config/battles_graphics.json")))
|
||||
if(!CResourceHandler::get(mod)->existsResource(ResourcePath("config/battles_graphics.json")))
|
||||
continue;
|
||||
|
||||
const JsonNode config(mod, ResourceID("config/battles_graphics.json"));
|
||||
const JsonNode config(mod, JsonPath::builtin("config/battles_graphics.json"));
|
||||
|
||||
//initialization of AC->def name mapping
|
||||
if(!config["ac_mapping"].isNull())
|
||||
@ -151,7 +153,7 @@ void Graphics::blueToPlayersAdv(SDL_Surface * sur, PlayerColor player)
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->error("Wrong player id in blueToPlayersAdv (%s)!", player.getStr());
|
||||
logGlobal->error("Wrong player id in blueToPlayersAdv (%s)!", player.toString());
|
||||
return;
|
||||
}
|
||||
//FIXME: not all player colored images have player palette at last 32 indexes
|
||||
@ -204,7 +206,7 @@ void Graphics::blueToPlayersAdv(SDL_Surface * sur, PlayerColor player)
|
||||
|
||||
void Graphics::loadFonts()
|
||||
{
|
||||
const JsonNode config(ResourceID("config/fonts.json"));
|
||||
const JsonNode config(JsonPath::builtin("config/fonts.json"));
|
||||
|
||||
const JsonVector & bmpConf = config["bitmap"].Vector();
|
||||
const JsonNode & ttfConf = config["trueType"];
|
||||
@ -228,7 +230,7 @@ void Graphics::loadFonts()
|
||||
void Graphics::loadErmuToPicture()
|
||||
{
|
||||
//loading ERMU to picture
|
||||
const JsonNode config(ResourceID("config/ERMU_to_picture.json"));
|
||||
const JsonNode config(JsonPath::builtin("config/ERMU_to_picture.json"));
|
||||
int etp_idx = 0;
|
||||
for(const JsonNode &etp : config["ERMU_to_picture"].Vector()) {
|
||||
int idx = 0;
|
||||
@ -279,16 +281,14 @@ void Graphics::initializeImageLists()
|
||||
addImageListEntries(CGI->skills());
|
||||
}
|
||||
|
||||
std::shared_ptr<CAnimation> Graphics::getAnimation(const std::string & path)
|
||||
std::shared_ptr<CAnimation> Graphics::getAnimation(const AnimationPath & path)
|
||||
{
|
||||
ResourceID animationPath(path, EResType::ANIMATION);
|
||||
if (cachedAnimations.count(path) != 0)
|
||||
return cachedAnimations.at(path);
|
||||
|
||||
if (cachedAnimations.count(animationPath.getName()) != 0)
|
||||
return cachedAnimations.at(animationPath.getName());
|
||||
|
||||
auto newAnimation = std::make_shared<CAnimation>(animationPath.getName());
|
||||
auto newAnimation = GH.renderHandler().loadAnimation(path);
|
||||
|
||||
newAnimation->preload();
|
||||
cachedAnimations[animationPath.getName()] = newAnimation;
|
||||
cachedAnimations[path] = newAnimation;
|
||||
return newAnimation;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "../lib/Color.h"
|
||||
#include "../lib/filesystem/ResourcePath.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@ -42,10 +43,10 @@ class Graphics
|
||||
void loadFonts();
|
||||
void initializeImageLists();
|
||||
|
||||
std::map<std::string, std::shared_ptr<CAnimation>> cachedAnimations;
|
||||
std::map<AnimationPath, std::shared_ptr<CAnimation>> cachedAnimations;
|
||||
|
||||
public:
|
||||
std::shared_ptr<CAnimation> getAnimation(const std::string & path);
|
||||
std::shared_ptr<CAnimation> getAnimation(const AnimationPath & path);
|
||||
|
||||
//Fonts
|
||||
static const int FONTS_NUMBER = 9;
|
||||
|
@ -9,6 +9,8 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class PlayerColor;
|
||||
@ -22,7 +24,7 @@ struct SDL_Surface;
|
||||
class ColorFilter;
|
||||
|
||||
/// Defines which blit method will be selected when image is used for rendering
|
||||
enum class EImageBlitMode : uint8_t
|
||||
enum class EImageBlitMode
|
||||
{
|
||||
/// Image can have no transparency and can be only used as background
|
||||
OPAQUE,
|
||||
@ -80,15 +82,7 @@ public:
|
||||
virtual void verticalFlip() = 0;
|
||||
virtual void doubleFlip() = 0;
|
||||
|
||||
IImage();
|
||||
virtual ~IImage();
|
||||
|
||||
/// loads image from specified file. Returns 0-sized images on failure
|
||||
static std::shared_ptr<IImage> createFromFile( const std::string & path );
|
||||
static std::shared_ptr<IImage> createFromFile( const std::string & path, EImageBlitMode mode );
|
||||
|
||||
/// temporary compatibility method. Creates IImage from existing SDL_Surface
|
||||
/// Surface will be shared, called must still free it with SDL_FreeSurface
|
||||
static std::shared_ptr<IImage> createFromSurface( SDL_Surface * source );
|
||||
IImage() = default;
|
||||
virtual ~IImage() = default;
|
||||
};
|
||||
|
||||
|
38
client/render/IRenderHandler.h
Normal file
38
client/render/IRenderHandler.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* IRenderHandler.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
|
||||
struct SDL_Surface;
|
||||
|
||||
class IImage;
|
||||
class CAnimation;
|
||||
enum class EImageBlitMode;
|
||||
|
||||
class IRenderHandler : public boost::noncopyable
|
||||
{
|
||||
public:
|
||||
virtual ~IRenderHandler() = default;
|
||||
|
||||
/// Loads image using given path
|
||||
virtual std::shared_ptr<IImage> loadImage(const ImagePath & path) = 0;
|
||||
virtual std::shared_ptr<IImage> loadImage(const ImagePath & path, EImageBlitMode mode) = 0;
|
||||
|
||||
/// temporary compatibility method. Creates IImage from existing SDL_Surface
|
||||
/// Surface will be shared, caller must still free it with SDL_FreeSurface
|
||||
virtual std::shared_ptr<IImage> createImage(SDL_Surface * source) = 0;
|
||||
|
||||
/// Loads animation using given path
|
||||
virtual std::shared_ptr<CAnimation> loadAnimation(const AnimationPath & path) = 0;
|
||||
|
||||
/// Creates empty CAnimation
|
||||
virtual std::shared_ptr<CAnimation> createAnimation() = 0;
|
||||
};
|
@ -24,7 +24,7 @@
|
||||
|
||||
#include <SDL_surface.h>
|
||||
|
||||
void CBitmapFont::loadModFont(const std::string & modName, const ResourceID & resource)
|
||||
void CBitmapFont::loadModFont(const std::string & modName, const ResourcePath & resource)
|
||||
{
|
||||
if (!CResourceHandler::get(modName)->existsResource(resource))
|
||||
{
|
||||
@ -72,7 +72,7 @@ void CBitmapFont::loadModFont(const std::string & modName, const ResourceID & re
|
||||
CBitmapFont::CBitmapFont(const std::string & filename):
|
||||
maxHeight(0)
|
||||
{
|
||||
ResourceID resource("data/" + filename, EResType::BMP_FONT);
|
||||
ResourcePath resource("data/" + filename, EResType::BMP_FONT);
|
||||
|
||||
loadModFont("core", resource);
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user