1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-05-13 22:06:58 +02:00

Applied suggestions from review

This commit is contained in:
Ivan Savenko 2022-12-13 13:58:16 +02:00
parent 602e52127b
commit 264f5c91e8
23 changed files with 481 additions and 489 deletions

View File

@ -41,7 +41,7 @@ static std::string formatDmgRange(std::pair<ui32, ui32> dmgRange)
} }
BattleActionsController::BattleActionsController(BattleInterface * owner): BattleActionsController::BattleActionsController(BattleInterface & owner):
owner(owner), owner(owner),
creatureCasting(false), creatureCasting(false),
spellDestSelectMode(false), spellDestSelectMode(false),
@ -62,17 +62,17 @@ void BattleActionsController::endCastingSpell()
spellDestSelectMode = false; spellDestSelectMode = false;
CCS->curh->changeGraphic(ECursor::COMBAT, ECursor::COMBAT_POINTER); CCS->curh->changeGraphic(ECursor::COMBAT, ECursor::COMBAT_POINTER);
if(owner->stacksController->getActiveStack()) if(owner.stacksController->getActiveStack())
{ {
possibleActions = getPossibleActionsForStack(owner->stacksController->getActiveStack()); //restore actions after they were cleared possibleActions = getPossibleActionsForStack(owner.stacksController->getActiveStack()); //restore actions after they were cleared
owner->myTurn = true; owner.myTurn = true;
} }
} }
else else
{ {
if(owner->stacksController->getActiveStack()) if(owner.stacksController->getActiveStack())
{ {
possibleActions = getPossibleActionsForStack(owner->stacksController->getActiveStack()); possibleActions = getPossibleActionsForStack(owner.stacksController->getActiveStack());
GH.fakeMouseMove(); GH.fakeMouseMove();
} }
} }
@ -81,35 +81,35 @@ void BattleActionsController::endCastingSpell()
void BattleActionsController::enterCreatureCastingMode() void BattleActionsController::enterCreatureCastingMode()
{ {
//silently check for possible errors //silently check for possible errors
if (!owner->myTurn) if (!owner.myTurn)
return; return;
if (owner->tacticsMode) if (owner.tacticsMode)
return; return;
//hero is casting a spell //hero is casting a spell
if (spellDestSelectMode) if (spellDestSelectMode)
return; return;
if (!owner->stacksController->getActiveStack()) if (!owner.stacksController->getActiveStack())
return; return;
if (!owner->stacksController->activeStackSpellcaster()) if (!owner.stacksController->activeStackSpellcaster())
return; return;
//random spellcaster //random spellcaster
if (owner->stacksController->activeStackSpellToCast() == SpellID::NONE) if (owner.stacksController->activeStackSpellToCast() == SpellID::NONE)
return; return;
if (vstd::contains(possibleActions, PossiblePlayerBattleAction::NO_LOCATION)) if (vstd::contains(possibleActions, PossiblePlayerBattleAction::NO_LOCATION))
{ {
const spells::Caster * caster = owner->stacksController->getActiveStack(); const spells::Caster * caster = owner.stacksController->getActiveStack();
const CSpell * spell = owner->stacksController->activeStackSpellToCast().toSpell(); const CSpell * spell = owner.stacksController->activeStackSpellToCast().toSpell();
spells::Target target; spells::Target target;
target.emplace_back(); target.emplace_back();
spells::BattleCast cast(owner->curInt->cb.get(), caster, spells::Mode::CREATURE_ACTIVE, spell); spells::BattleCast cast(owner.curInt->cb.get(), caster, spells::Mode::CREATURE_ACTIVE, spell);
auto m = spell->battleMechanics(&cast); auto m = spell->battleMechanics(&cast);
spells::detail::ProblemImpl ignored; spells::detail::ProblemImpl ignored;
@ -118,16 +118,16 @@ void BattleActionsController::enterCreatureCastingMode()
if (isCastingPossible) if (isCastingPossible)
{ {
owner->myTurn = false; owner.myTurn = false;
owner->giveCommand(EActionType::MONSTER_SPELL, BattleHex::INVALID, owner->stacksController->activeStackSpellToCast()); owner.giveCommand(EActionType::MONSTER_SPELL, BattleHex::INVALID, owner.stacksController->activeStackSpellToCast());
owner->stacksController->setSelectedStack(nullptr); owner.stacksController->setSelectedStack(nullptr);
CCS->curh->changeGraphic(ECursor::COMBAT, ECursor::COMBAT_POINTER); CCS->curh->changeGraphic(ECursor::COMBAT, ECursor::COMBAT_POINTER);
} }
} }
else else
{ {
possibleActions = getPossibleActionsForStack(owner->stacksController->getActiveStack()); possibleActions = getPossibleActionsForStack(owner.stacksController->getActiveStack());
auto actionFilterPredicate = [](const PossiblePlayerBattleAction x) auto actionFilterPredicate = [](const PossiblePlayerBattleAction x)
{ {
@ -144,16 +144,16 @@ void BattleActionsController::enterCreatureCastingMode()
std::vector<PossiblePlayerBattleAction> BattleActionsController::getPossibleActionsForStack(const CStack *stack) const std::vector<PossiblePlayerBattleAction> BattleActionsController::getPossibleActionsForStack(const CStack *stack) const
{ {
BattleClientInterfaceData data; //hard to get rid of these things so for now they're required data to pass BattleClientInterfaceData data; //hard to get rid of these things so for now they're required data to pass
data.creatureSpellToCast = owner->stacksController->activeStackSpellToCast(); data.creatureSpellToCast = owner.stacksController->activeStackSpellToCast();
data.tacticsMode = owner->tacticsMode; data.tacticsMode = owner.tacticsMode;
auto allActions = owner->curInt->cb->getClientActionsForStack(stack, data); auto allActions = owner.curInt->cb->getClientActionsForStack(stack, data);
return std::vector<PossiblePlayerBattleAction>(allActions); return std::vector<PossiblePlayerBattleAction>(allActions);
} }
void BattleActionsController::reorderPossibleActionsPriority(const CStack * stack, MouseHoveredHexContext context) void BattleActionsController::reorderPossibleActionsPriority(const CStack * stack, MouseHoveredHexContext context)
{ {
if(owner->tacticsMode || possibleActions.empty()) return; //this function is not supposed to be called in tactics mode or before getPossibleActionsForStack if(owner.tacticsMode || possibleActions.empty()) return; //this function is not supposed to be called in tactics mode or before getPossibleActionsForStack
auto assignPriority = [&](PossiblePlayerBattleAction const & item) -> uint8_t //large lambda assigning priority which would have to be part of possibleActions without it auto assignPriority = [&](PossiblePlayerBattleAction const & item) -> uint8_t //large lambda assigning priority which would have to be part of possibleActions without it
{ {
@ -205,21 +205,21 @@ void BattleActionsController::castThisSpell(SpellID spellID)
spellToCast = std::make_shared<BattleAction>(); spellToCast = std::make_shared<BattleAction>();
spellToCast->actionType = EActionType::HERO_SPELL; spellToCast->actionType = EActionType::HERO_SPELL;
spellToCast->actionSubtype = spellID; //spell number spellToCast->actionSubtype = spellID; //spell number
spellToCast->stackNumber = (owner->attackingHeroInstance->tempOwner == owner->curInt->playerID) ? -1 : -2; spellToCast->stackNumber = (owner.attackingHeroInstance->tempOwner == owner.curInt->playerID) ? -1 : -2;
spellToCast->side = owner->defendingHeroInstance ? (owner->curInt->playerID == owner->defendingHeroInstance->tempOwner) : false; spellToCast->side = owner.defendingHeroInstance ? (owner.curInt->playerID == owner.defendingHeroInstance->tempOwner) : false;
spellDestSelectMode = true; spellDestSelectMode = true;
creatureCasting = false; creatureCasting = false;
//choosing possible targets //choosing possible targets
const CGHeroInstance *castingHero = (owner->attackingHeroInstance->tempOwner == owner->curInt->playerID) ? owner->attackingHeroInstance : owner->defendingHeroInstance; const CGHeroInstance *castingHero = (owner.attackingHeroInstance->tempOwner == owner.curInt->playerID) ? owner.attackingHeroInstance : owner.defendingHeroInstance;
assert(castingHero); // code below assumes non-null hero assert(castingHero); // code below assumes non-null hero
currentSpell = spellID.toSpell(); currentSpell = spellID.toSpell();
PossiblePlayerBattleAction spellSelMode = owner->curInt->cb->getCasterAction(currentSpell, castingHero, spells::Mode::HERO); PossiblePlayerBattleAction spellSelMode = owner.curInt->cb->getCasterAction(currentSpell, castingHero, spells::Mode::HERO);
if (spellSelMode == PossiblePlayerBattleAction::NO_LOCATION) //user does not have to select location if (spellSelMode == PossiblePlayerBattleAction::NO_LOCATION) //user does not have to select location
{ {
spellToCast->aimToHex(BattleHex::INVALID); spellToCast->aimToHex(BattleHex::INVALID);
owner->curInt->cb->battleMakeAction(spellToCast.get()); owner.curInt->cb->battleMakeAction(spellToCast.get());
endCastingSpell(); endCastingSpell();
} }
else else
@ -233,7 +233,7 @@ void BattleActionsController::castThisSpell(SpellID spellID)
void BattleActionsController::handleHex(BattleHex myNumber, int eventType) void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
{ {
if (!owner->myTurn || !owner->battleActionsStarted) //we are not permit to do anything if (!owner.myTurn || !owner.battleActionsStarted) //we are not permit to do anything
return; return;
// This function handles mouse move over hexes and l-clicking on them. // This function handles mouse move over hexes and l-clicking on them.
@ -252,24 +252,24 @@ void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
std::function<void()> realizeAction; std::function<void()> realizeAction;
//Get stack on the hex - first try to grab the alive one, if not found -> allow dead stacks. //Get stack on the hex - first try to grab the alive one, if not found -> allow dead stacks.
const CStack * shere = owner->curInt->cb->battleGetStackByPos(myNumber, true); const CStack * shere = owner.curInt->cb->battleGetStackByPos(myNumber, true);
if(!shere) if(!shere)
shere = owner->curInt->cb->battleGetStackByPos(myNumber, false); shere = owner.curInt->cb->battleGetStackByPos(myNumber, false);
if(!owner->stacksController->getActiveStack()) if(!owner.stacksController->getActiveStack())
return; return;
bool ourStack = false; bool ourStack = false;
if (shere) if (shere)
ourStack = shere->owner == owner->curInt->playerID; ourStack = shere->owner == owner.curInt->playerID;
//stack may have changed, update selection border //stack may have changed, update selection border
owner->stacksController->setHoveredStack(shere); owner.stacksController->setHoveredStack(shere);
localActions.clear(); localActions.clear();
illegalActions.clear(); illegalActions.clear();
reorderPossibleActionsPriority(owner->stacksController->getActiveStack(), shere ? MouseHoveredHexContext::OCCUPIED_HEX : MouseHoveredHexContext::UNOCCUPIED_HEX); reorderPossibleActionsPriority(owner.stacksController->getActiveStack(), shere ? MouseHoveredHexContext::OCCUPIED_HEX : MouseHoveredHexContext::UNOCCUPIED_HEX);
const bool forcedAction = possibleActions.size() == 1; const bool forcedAction = possibleActions.size() == 1;
for (PossiblePlayerBattleAction action : possibleActions) for (PossiblePlayerBattleAction action : possibleActions)
@ -288,7 +288,7 @@ void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
{ {
if (!(shere && shere->alive())) //we can walk on dead stacks if (!(shere && shere->alive())) //we can walk on dead stacks
{ {
if(canStackMoveHere(owner->stacksController->getActiveStack(), myNumber)) if(canStackMoveHere(owner.stacksController->getActiveStack(), myNumber))
legalAction = true; legalAction = true;
} }
break; break;
@ -297,12 +297,12 @@ void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
case PossiblePlayerBattleAction::WALK_AND_ATTACK: case PossiblePlayerBattleAction::WALK_AND_ATTACK:
case PossiblePlayerBattleAction::ATTACK_AND_RETURN: case PossiblePlayerBattleAction::ATTACK_AND_RETURN:
{ {
if(owner->curInt->cb->battleCanAttack(owner->stacksController->getActiveStack(), shere, myNumber)) if(owner.curInt->cb->battleCanAttack(owner.stacksController->getActiveStack(), shere, myNumber))
{ {
if (owner->fieldController->isTileAttackable(myNumber)) // move isTileAttackable to be part of battleCanAttack? if (owner.fieldController->isTileAttackable(myNumber)) // move isTileAttackable to be part of battleCanAttack?
{ {
owner->fieldController->setBattleCursor(myNumber); // temporary - needed for following function :( owner.fieldController->setBattleCursor(myNumber); // temporary - needed for following function :(
BattleHex attackFromHex = owner->fieldController->fromWhichHexAttack(myNumber); BattleHex attackFromHex = owner.fieldController->fromWhichHexAttack(myNumber);
if (attackFromHex >= 0) //we can be in this line when unreachable creature is L - clicked (as of revision 1308) if (attackFromHex >= 0) //we can be in this line when unreachable creature is L - clicked (as of revision 1308)
legalAction = true; legalAction = true;
@ -311,25 +311,25 @@ void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
} }
break; break;
case PossiblePlayerBattleAction::SHOOT: case PossiblePlayerBattleAction::SHOOT:
if(owner->curInt->cb->battleCanShoot(owner->stacksController->getActiveStack(), myNumber)) if(owner.curInt->cb->battleCanShoot(owner.stacksController->getActiveStack(), myNumber))
legalAction = true; legalAction = true;
break; break;
case PossiblePlayerBattleAction::ANY_LOCATION: case PossiblePlayerBattleAction::ANY_LOCATION:
if (myNumber > -1) //TODO: this should be checked for all actions if (myNumber > -1) //TODO: this should be checked for all actions
{ {
if(isCastingPossibleHere(owner->stacksController->getActiveStack(), shere, myNumber)) if(isCastingPossibleHere(owner.stacksController->getActiveStack(), shere, myNumber))
legalAction = true; legalAction = true;
} }
break; break;
case PossiblePlayerBattleAction::AIMED_SPELL_CREATURE: case PossiblePlayerBattleAction::AIMED_SPELL_CREATURE:
if(shere && isCastingPossibleHere(owner->stacksController->getActiveStack(), shere, myNumber)) if(shere && isCastingPossibleHere(owner.stacksController->getActiveStack(), shere, myNumber))
legalAction = true; legalAction = true;
break; break;
case PossiblePlayerBattleAction::RANDOM_GENIE_SPELL: case PossiblePlayerBattleAction::RANDOM_GENIE_SPELL:
{ {
if(shere && ourStack && shere != owner->stacksController->getActiveStack() && shere->alive()) //only positive spells for other allied creatures if(shere && ourStack && shere != owner.stacksController->getActiveStack() && shere->alive()) //only positive spells for other allied creatures
{ {
int spellID = owner->curInt->cb->battleGetRandomStackSpell(CRandomGenerator::getDefault(), shere, CBattleInfoCallback::RANDOM_GENIE); int spellID = owner.curInt->cb->battleGetRandomStackSpell(CRandomGenerator::getDefault(), shere, CBattleInfoCallback::RANDOM_GENIE);
if(spellID > -1) if(spellID > -1)
{ {
legalAction = true; legalAction = true;
@ -338,7 +338,7 @@ void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
} }
break; break;
case PossiblePlayerBattleAction::OBSTACLE: case PossiblePlayerBattleAction::OBSTACLE:
if(isCastingPossibleHere(owner->stacksController->getActiveStack(), shere, myNumber)) if(isCastingPossibleHere(owner.stacksController->getActiveStack(), shere, myNumber))
legalAction = true; legalAction = true;
break; break;
case PossiblePlayerBattleAction::TELEPORT: case PossiblePlayerBattleAction::TELEPORT:
@ -346,32 +346,32 @@ void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
//todo: move to mechanics //todo: move to mechanics
ui8 skill = 0; ui8 skill = 0;
if (creatureCasting) if (creatureCasting)
skill = owner->stacksController->getActiveStack()->getEffectLevel(SpellID(SpellID::TELEPORT).toSpell()); skill = owner.stacksController->getActiveStack()->getEffectLevel(SpellID(SpellID::TELEPORT).toSpell());
else else
skill = owner->getActiveHero()->getEffectLevel(SpellID(SpellID::TELEPORT).toSpell()); skill = owner.getActiveHero()->getEffectLevel(SpellID(SpellID::TELEPORT).toSpell());
//TODO: explicitely save power, skill //TODO: explicitely save power, skill
if (owner->curInt->cb->battleCanTeleportTo(owner->stacksController->getSelectedStack(), myNumber, skill)) if (owner.curInt->cb->battleCanTeleportTo(owner.stacksController->getSelectedStack(), myNumber, skill))
legalAction = true; legalAction = true;
else else
notLegal = true; notLegal = true;
} }
break; break;
case PossiblePlayerBattleAction::SACRIFICE: //choose our living stack to sacrifice case PossiblePlayerBattleAction::SACRIFICE: //choose our living stack to sacrifice
if (shere && shere != owner->stacksController->getSelectedStack() && ourStack && shere->alive()) if (shere && shere != owner.stacksController->getSelectedStack() && ourStack && shere->alive())
legalAction = true; legalAction = true;
else else
notLegal = true; notLegal = true;
break; break;
case PossiblePlayerBattleAction::FREE_LOCATION: case PossiblePlayerBattleAction::FREE_LOCATION:
legalAction = true; legalAction = true;
if(!isCastingPossibleHere(owner->stacksController->getActiveStack(), shere, myNumber)) if(!isCastingPossibleHere(owner.stacksController->getActiveStack(), shere, myNumber))
{ {
legalAction = false; legalAction = false;
notLegal = true; notLegal = true;
} }
break; break;
case PossiblePlayerBattleAction::CATAPULT: case PossiblePlayerBattleAction::CATAPULT:
if (owner->siegeController && owner->siegeController->isAttackableByCatapult(myNumber)) if (owner.siegeController && owner.siegeController->isAttackableByCatapult(myNumber))
legalAction = true; legalAction = true;
break; break;
case PossiblePlayerBattleAction::HEAL: case PossiblePlayerBattleAction::HEAL:
@ -428,35 +428,35 @@ void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
{ {
case PossiblePlayerBattleAction::CHOOSE_TACTICS_STACK: case PossiblePlayerBattleAction::CHOOSE_TACTICS_STACK:
newConsoleMsg = (boost::format(CGI->generaltexth->allTexts[481]) % shere->getName()).str(); //Select %s newConsoleMsg = (boost::format(CGI->generaltexth->allTexts[481]) % shere->getName()).str(); //Select %s
realizeAction = [=](){ owner->stackActivated(shere); }; realizeAction = [=](){ owner.stackActivated(shere); };
break; break;
case PossiblePlayerBattleAction::MOVE_TACTICS: case PossiblePlayerBattleAction::MOVE_TACTICS:
case PossiblePlayerBattleAction::MOVE_STACK: case PossiblePlayerBattleAction::MOVE_STACK:
if (owner->stacksController->getActiveStack()->hasBonusOfType(Bonus::FLYING)) if (owner.stacksController->getActiveStack()->hasBonusOfType(Bonus::FLYING))
{ {
cursorFrame = ECursor::COMBAT_FLY; cursorFrame = ECursor::COMBAT_FLY;
newConsoleMsg = (boost::format(CGI->generaltexth->allTexts[295]) % owner->stacksController->getActiveStack()->getName()).str(); //Fly %s here newConsoleMsg = (boost::format(CGI->generaltexth->allTexts[295]) % owner.stacksController->getActiveStack()->getName()).str(); //Fly %s here
} }
else else
{ {
cursorFrame = ECursor::COMBAT_MOVE; cursorFrame = ECursor::COMBAT_MOVE;
newConsoleMsg = (boost::format(CGI->generaltexth->allTexts[294]) % owner->stacksController->getActiveStack()->getName()).str(); //Move %s here newConsoleMsg = (boost::format(CGI->generaltexth->allTexts[294]) % owner.stacksController->getActiveStack()->getName()).str(); //Move %s here
} }
realizeAction = [=]() realizeAction = [=]()
{ {
if(owner->stacksController->getActiveStack()->doubleWide()) if(owner.stacksController->getActiveStack()->doubleWide())
{ {
std::vector<BattleHex> acc = owner->curInt->cb->battleGetAvailableHexes(owner->stacksController->getActiveStack()); std::vector<BattleHex> acc = owner.curInt->cb->battleGetAvailableHexes(owner.stacksController->getActiveStack());
BattleHex shiftedDest = myNumber.cloneInDirection(owner->stacksController->getActiveStack()->destShiftDir(), false); BattleHex shiftedDest = myNumber.cloneInDirection(owner.stacksController->getActiveStack()->destShiftDir(), false);
if(vstd::contains(acc, myNumber)) if(vstd::contains(acc, myNumber))
owner->giveCommand(EActionType::WALK, myNumber); owner.giveCommand(EActionType::WALK, myNumber);
else if(vstd::contains(acc, shiftedDest)) else if(vstd::contains(acc, shiftedDest))
owner->giveCommand(EActionType::WALK, shiftedDest); owner.giveCommand(EActionType::WALK, shiftedDest);
} }
else else
{ {
owner->giveCommand(EActionType::WALK, myNumber); owner.giveCommand(EActionType::WALK, myNumber);
} }
}; };
break; break;
@ -464,55 +464,55 @@ void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
case PossiblePlayerBattleAction::WALK_AND_ATTACK: case PossiblePlayerBattleAction::WALK_AND_ATTACK:
case PossiblePlayerBattleAction::ATTACK_AND_RETURN: //TODO: allow to disable return case PossiblePlayerBattleAction::ATTACK_AND_RETURN: //TODO: allow to disable return
{ {
owner->fieldController->setBattleCursor(myNumber); //handle direction of cursor and attackable tile owner.fieldController->setBattleCursor(myNumber); //handle direction of cursor and attackable tile
setCursor = false; //don't overwrite settings from the call above //TODO: what does it mean? setCursor = false; //don't overwrite settings from the call above //TODO: what does it mean?
bool returnAfterAttack = currentAction == PossiblePlayerBattleAction::ATTACK_AND_RETURN; bool returnAfterAttack = currentAction == PossiblePlayerBattleAction::ATTACK_AND_RETURN;
realizeAction = [=]() realizeAction = [=]()
{ {
BattleHex attackFromHex = owner->fieldController->fromWhichHexAttack(myNumber); BattleHex attackFromHex = owner.fieldController->fromWhichHexAttack(myNumber);
if(attackFromHex.isValid()) //we can be in this line when unreachable creature is L - clicked (as of revision 1308) if(attackFromHex.isValid()) //we can be in this line when unreachable creature is L - clicked (as of revision 1308)
{ {
auto command = new BattleAction(BattleAction::makeMeleeAttack(owner->stacksController->getActiveStack(), myNumber, attackFromHex, returnAfterAttack)); auto command = new BattleAction(BattleAction::makeMeleeAttack(owner.stacksController->getActiveStack(), myNumber, attackFromHex, returnAfterAttack));
owner->sendCommand(command, owner->stacksController->getActiveStack()); owner.sendCommand(command, owner.stacksController->getActiveStack());
} }
}; };
TDmgRange damage = owner->curInt->cb->battleEstimateDamage(owner->stacksController->getActiveStack(), shere); TDmgRange damage = owner.curInt->cb->battleEstimateDamage(owner.stacksController->getActiveStack(), shere);
std::string estDmgText = formatDmgRange(std::make_pair((ui32)damage.first, (ui32)damage.second)); //calculating estimated dmg std::string estDmgText = formatDmgRange(std::make_pair((ui32)damage.first, (ui32)damage.second)); //calculating estimated dmg
newConsoleMsg = (boost::format(CGI->generaltexth->allTexts[36]) % shere->getName() % estDmgText).str(); //Attack %s (%s damage) newConsoleMsg = (boost::format(CGI->generaltexth->allTexts[36]) % shere->getName() % estDmgText).str(); //Attack %s (%s damage)
} }
break; break;
case PossiblePlayerBattleAction::SHOOT: case PossiblePlayerBattleAction::SHOOT:
{ {
if (owner->curInt->cb->battleHasShootingPenalty(owner->stacksController->getActiveStack(), myNumber)) if (owner.curInt->cb->battleHasShootingPenalty(owner.stacksController->getActiveStack(), myNumber))
cursorFrame = ECursor::COMBAT_SHOOT_PENALTY; cursorFrame = ECursor::COMBAT_SHOOT_PENALTY;
else else
cursorFrame = ECursor::COMBAT_SHOOT; cursorFrame = ECursor::COMBAT_SHOOT;
realizeAction = [=](){owner->giveCommand(EActionType::SHOOT, myNumber);}; realizeAction = [=](){owner.giveCommand(EActionType::SHOOT, myNumber);};
TDmgRange damage = owner->curInt->cb->battleEstimateDamage(owner->stacksController->getActiveStack(), shere); TDmgRange damage = owner.curInt->cb->battleEstimateDamage(owner.stacksController->getActiveStack(), shere);
std::string estDmgText = formatDmgRange(std::make_pair((ui32)damage.first, (ui32)damage.second)); //calculating estimated dmg std::string estDmgText = formatDmgRange(std::make_pair((ui32)damage.first, (ui32)damage.second)); //calculating estimated dmg
//printing - Shoot %s (%d shots left, %s damage) //printing - Shoot %s (%d shots left, %s damage)
newConsoleMsg = (boost::format(CGI->generaltexth->allTexts[296]) % shere->getName() % owner->stacksController->getActiveStack()->shots.available() % estDmgText).str(); newConsoleMsg = (boost::format(CGI->generaltexth->allTexts[296]) % shere->getName() % owner.stacksController->getActiveStack()->shots.available() % estDmgText).str();
} }
break; break;
case PossiblePlayerBattleAction::AIMED_SPELL_CREATURE: case PossiblePlayerBattleAction::AIMED_SPELL_CREATURE:
currentSpell = CGI->spellh->objects[creatureCasting ? owner->stacksController->activeStackSpellToCast() : spellToCast->actionSubtype]; //necessary if creature has random Genie spell at same time currentSpell = CGI->spellh->objects[creatureCasting ? owner.stacksController->activeStackSpellToCast() : spellToCast->actionSubtype]; //necessary if creature has random Genie spell at same time
newConsoleMsg = boost::str(boost::format(CGI->generaltexth->allTexts[27]) % currentSpell->name % shere->getName()); //Cast %s on %s newConsoleMsg = boost::str(boost::format(CGI->generaltexth->allTexts[27]) % currentSpell->name % shere->getName()); //Cast %s on %s
switch (currentSpell->id) switch (currentSpell->id)
{ {
case SpellID::SACRIFICE: case SpellID::SACRIFICE:
case SpellID::TELEPORT: case SpellID::TELEPORT:
owner->stacksController->setSelectedStack(shere); //remember first target owner.stacksController->setSelectedStack(shere); //remember first target
secondaryTarget = true; secondaryTarget = true;
break; break;
} }
isCastingPossible = true; isCastingPossible = true;
break; break;
case PossiblePlayerBattleAction::ANY_LOCATION: case PossiblePlayerBattleAction::ANY_LOCATION:
currentSpell = CGI->spellh->objects[creatureCasting ? owner->stacksController->activeStackSpellToCast() : spellToCast->actionSubtype]; //necessary if creature has random Genie spell at same time currentSpell = CGI->spellh->objects[creatureCasting ? owner.stacksController->activeStackSpellToCast() : spellToCast->actionSubtype]; //necessary if creature has random Genie spell at same time
newConsoleMsg = boost::str(boost::format(CGI->generaltexth->allTexts[26]) % currentSpell->name); //Cast %s newConsoleMsg = boost::str(boost::format(CGI->generaltexth->allTexts[26]) % currentSpell->name); //Cast %s
isCastingPossible = true; isCastingPossible = true;
break; break;
@ -544,18 +544,18 @@ void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
case PossiblePlayerBattleAction::HEAL: case PossiblePlayerBattleAction::HEAL:
cursorFrame = ECursor::COMBAT_HEAL; cursorFrame = ECursor::COMBAT_HEAL;
newConsoleMsg = (boost::format(CGI->generaltexth->allTexts[419]) % shere->getName()).str(); //Apply first aid to the %s newConsoleMsg = (boost::format(CGI->generaltexth->allTexts[419]) % shere->getName()).str(); //Apply first aid to the %s
realizeAction = [=](){ owner->giveCommand(EActionType::STACK_HEAL, myNumber); }; //command healing realizeAction = [=](){ owner.giveCommand(EActionType::STACK_HEAL, myNumber); }; //command healing
break; break;
case PossiblePlayerBattleAction::RISE_DEMONS: case PossiblePlayerBattleAction::RISE_DEMONS:
cursorType = ECursor::SPELLBOOK; cursorType = ECursor::SPELLBOOK;
realizeAction = [=]() realizeAction = [=]()
{ {
owner->giveCommand(EActionType::DAEMON_SUMMONING, myNumber); owner.giveCommand(EActionType::DAEMON_SUMMONING, myNumber);
}; };
break; break;
case PossiblePlayerBattleAction::CATAPULT: case PossiblePlayerBattleAction::CATAPULT:
cursorFrame = ECursor::COMBAT_SHOOT_CATAPULT; cursorFrame = ECursor::COMBAT_SHOOT_CATAPULT;
realizeAction = [=](){ owner->giveCommand(EActionType::CATAPULT, myNumber); }; realizeAction = [=](){ owner.giveCommand(EActionType::CATAPULT, myNumber); };
break; break;
case PossiblePlayerBattleAction::CREATURE_INFO: case PossiblePlayerBattleAction::CREATURE_INFO:
{ {
@ -634,11 +634,11 @@ void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
{ {
if (currentSpell) if (currentSpell)
{ {
owner->giveCommand(EActionType::MONSTER_SPELL, myNumber, owner->stacksController->activeStackSpellToCast()); owner.giveCommand(EActionType::MONSTER_SPELL, myNumber, owner.stacksController->activeStackSpellToCast());
} }
else //unknown random spell else //unknown random spell
{ {
owner->giveCommand(EActionType::MONSTER_SPELL, myNumber); owner.giveCommand(EActionType::MONSTER_SPELL, myNumber);
} }
} }
else else
@ -653,10 +653,10 @@ void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
spellToCast->aimToHex(myNumber); spellToCast->aimToHex(myNumber);
break; break;
} }
owner->curInt->cb->battleMakeAction(spellToCast.get()); owner.curInt->cb->battleMakeAction(spellToCast.get());
endCastingSpell(); endCastingSpell();
} }
owner->stacksController->setSelectedStack(nullptr); owner.stacksController->setSelectedStack(nullptr);
} }
}; };
} }
@ -668,9 +668,9 @@ void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
CCS->curh->changeGraphic(cursorType, cursorFrame); CCS->curh->changeGraphic(cursorType, cursorFrame);
if (!currentConsoleMsg.empty()) if (!currentConsoleMsg.empty())
owner->controlPanel->console->clearIfMatching(currentConsoleMsg); owner.controlPanel->console->clearIfMatching(currentConsoleMsg);
if (!newConsoleMsg.empty()) if (!newConsoleMsg.empty())
owner->controlPanel->console->write(newConsoleMsg); owner.controlPanel->console->write(newConsoleMsg);
currentConsoleMsg = newConsoleMsg; currentConsoleMsg = newConsoleMsg;
} }
@ -679,12 +679,12 @@ void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
//opening creature window shouldn't affect myTurn... //opening creature window shouldn't affect myTurn...
if ((currentAction != PossiblePlayerBattleAction::CREATURE_INFO) && !secondaryTarget) if ((currentAction != PossiblePlayerBattleAction::CREATURE_INFO) && !secondaryTarget)
{ {
owner->myTurn = false; //tends to crash with empty calls owner.myTurn = false; //tends to crash with empty calls
} }
realizeAction(); realizeAction();
if (!secondaryTarget) //do not replace teleport or sacrifice cursor if (!secondaryTarget) //do not replace teleport or sacrifice cursor
CCS->curh->changeGraphic(ECursor::COMBAT, ECursor::COMBAT_POINTER); CCS->curh->changeGraphic(ECursor::COMBAT, ECursor::COMBAT_POINTER);
owner->controlPanel->console->clear(); owner.controlPanel->console->clear();
} }
} }
} }
@ -692,15 +692,15 @@ void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
bool BattleActionsController::isCastingPossibleHere(const CStack *sactive, const CStack *shere, BattleHex myNumber) bool BattleActionsController::isCastingPossibleHere(const CStack *sactive, const CStack *shere, BattleHex myNumber)
{ {
creatureCasting = owner->stacksController->activeStackSpellcaster() && !spellDestSelectMode; //TODO: allow creatures to cast aimed spells creatureCasting = owner.stacksController->activeStackSpellcaster() && !spellDestSelectMode; //TODO: allow creatures to cast aimed spells
bool isCastingPossible = true; bool isCastingPossible = true;
int spellID = -1; int spellID = -1;
if (creatureCasting) if (creatureCasting)
{ {
if (owner->stacksController->activeStackSpellToCast() != SpellID::NONE && (shere != sactive)) //can't cast on itself if (owner.stacksController->activeStackSpellToCast() != SpellID::NONE && (shere != sactive)) //can't cast on itself
spellID = owner->stacksController->activeStackSpellToCast(); //TODO: merge with SpellTocast? spellID = owner.stacksController->activeStackSpellToCast(); //TODO: merge with SpellTocast?
} }
else //hero casting else //hero casting
{ {
@ -714,7 +714,7 @@ bool BattleActionsController::isCastingPossibleHere(const CStack *sactive, const
if (currentSpell) if (currentSpell)
{ {
const spells::Caster *caster = creatureCasting ? static_cast<const spells::Caster *>(sactive) : static_cast<const spells::Caster *>(owner->curInt->cb->battleGetMyHero()); const spells::Caster *caster = creatureCasting ? static_cast<const spells::Caster *>(sactive) : static_cast<const spells::Caster *>(owner.curInt->cb->battleGetMyHero());
if (caster == nullptr) if (caster == nullptr)
{ {
isCastingPossible = false;//just in case isCastingPossible = false;//just in case
@ -726,7 +726,7 @@ bool BattleActionsController::isCastingPossibleHere(const CStack *sactive, const
spells::Target target; spells::Target target;
target.emplace_back(myNumber); target.emplace_back(myNumber);
spells::BattleCast cast(owner->curInt->cb.get(), caster, mode, currentSpell); spells::BattleCast cast(owner.curInt->cb.get(), caster, mode, currentSpell);
auto m = currentSpell->battleMechanics(&cast); auto m = currentSpell->battleMechanics(&cast);
spells::detail::ProblemImpl problem; //todo: display problem in status bar spells::detail::ProblemImpl problem; //todo: display problem in status bar
@ -744,7 +744,7 @@ bool BattleActionsController::isCastingPossibleHere(const CStack *sactive, const
bool BattleActionsController::canStackMoveHere(const CStack * stackToMove, BattleHex myNumber) const bool BattleActionsController::canStackMoveHere(const CStack * stackToMove, BattleHex myNumber) const
{ {
std::vector<BattleHex> acc = owner->curInt->cb->battleGetAvailableHexes(stackToMove); std::vector<BattleHex> acc = owner.curInt->cb->battleGetAvailableHexes(stackToMove);
BattleHex shiftedDest = myNumber.cloneInDirection(stackToMove->destShiftDir(), false); BattleHex shiftedDest = myNumber.cloneInDirection(stackToMove->destShiftDir(), false);
if (vstd::contains(acc, myNumber)) if (vstd::contains(acc, myNumber))
@ -757,7 +757,7 @@ bool BattleActionsController::canStackMoveHere(const CStack * stackToMove, Battl
void BattleActionsController::activateStack() void BattleActionsController::activateStack()
{ {
const CStack * s = owner->stacksController->getActiveStack(); const CStack * s = owner.stacksController->getActiveStack();
if(s) if(s)
possibleActions = getPossibleActionsForStack(s); possibleActions = getPossibleActionsForStack(s);
} }

View File

@ -29,7 +29,7 @@ enum class MouseHoveredHexContext
/// As well as all relevant feedback for these actions in user interface /// As well as all relevant feedback for these actions in user interface
class BattleActionsController class BattleActionsController
{ {
BattleInterface * owner; BattleInterface & owner;
/// all actions possible to call at the moment by player /// all actions possible to call at the moment by player
std::vector<PossiblePlayerBattleAction> possibleActions; std::vector<PossiblePlayerBattleAction> possibleActions;
@ -70,7 +70,7 @@ class BattleActionsController
void reorderPossibleActionsPriority(const CStack * stack, MouseHoveredHexContext context); void reorderPossibleActionsPriority(const CStack * stack, MouseHoveredHexContext context);
public: public:
BattleActionsController(BattleInterface * owner); BattleActionsController(BattleInterface & owner);
/// initialize list of potential actions for new active stack /// initialize list of potential actions for new active stack
void activateStack(); void activateStack();

View File

@ -34,9 +34,9 @@
#include "../../lib/CTownHandler.h" #include "../../lib/CTownHandler.h"
#include "../../lib/mapObjects/CGTownInstance.h" #include "../../lib/mapObjects/CGTownInstance.h"
CBattleAnimation::CBattleAnimation(BattleInterface * _owner) CBattleAnimation::CBattleAnimation(BattleInterface & owner)
: owner(_owner), : owner(owner),
ID(_owner->stacksController->animIDhelper++), ID(owner.stacksController->animIDhelper++),
initialized(false) initialized(false)
{ {
logAnim->trace("Animation #%d created", ID); logAnim->trace("Animation #%d created", ID);
@ -72,22 +72,22 @@ CBattleAnimation::~CBattleAnimation()
std::vector<CBattleAnimation *> & CBattleAnimation::pendingAnimations() std::vector<CBattleAnimation *> & CBattleAnimation::pendingAnimations()
{ {
return owner->stacksController->currentAnimations; return owner.stacksController->currentAnimations;
} }
std::shared_ptr<CreatureAnimation> CBattleAnimation::stackAnimation(const CStack * stack) const std::shared_ptr<CreatureAnimation> CBattleAnimation::stackAnimation(const CStack * stack) const
{ {
return owner->stacksController->stackAnimation[stack->ID]; return owner.stacksController->stackAnimation[stack->ID];
} }
bool CBattleAnimation::stackFacingRight(const CStack * stack) bool CBattleAnimation::stackFacingRight(const CStack * stack)
{ {
return owner->stacksController->stackFacingRight[stack->ID]; return owner.stacksController->stackFacingRight[stack->ID];
} }
void CBattleAnimation::setStackFacingRight(const CStack * stack, bool facingRight) void CBattleAnimation::setStackFacingRight(const CStack * stack, bool facingRight)
{ {
owner->stacksController->stackFacingRight[stack->ID] = facingRight; owner.stacksController->stackFacingRight[stack->ID] = facingRight;
} }
bool CBattleAnimation::checkInitialConditions() bool CBattleAnimation::checkInitialConditions()
@ -116,7 +116,7 @@ bool CBattleAnimation::checkInitialConditions()
return ID == lowestMoveID; return ID == lowestMoveID;
} }
CBattleStackAnimation::CBattleStackAnimation(BattleInterface * owner, const CStack * stack) CBattleStackAnimation::CBattleStackAnimation(BattleInterface & owner, const CStack * stack)
: CBattleAnimation(owner), : CBattleAnimation(owner),
myAnim(stackAnimation(stack)), myAnim(stackAnimation(stack)),
stack(stack) stack(stack)
@ -172,13 +172,13 @@ bool CAttackAnimation::checkInitialConditions()
const CCreature * CAttackAnimation::getCreature() const const CCreature * CAttackAnimation::getCreature() const
{ {
if (attackingStack->getCreature()->idNumber == CreatureID::ARROW_TOWERS) if (attackingStack->getCreature()->idNumber == CreatureID::ARROW_TOWERS)
return owner->siegeController->getTurretCreature(); return owner.siegeController->getTurretCreature();
else else
return attackingStack->getCreature(); return attackingStack->getCreature();
} }
CAttackAnimation::CAttackAnimation(BattleInterface *_owner, const CStack *attacker, BattleHex _dest, const CStack *defender) CAttackAnimation::CAttackAnimation(BattleInterface & owner, const CStack *attacker, BattleHex _dest, const CStack *defender)
: CBattleStackAnimation(_owner, attacker), : CBattleStackAnimation(owner, attacker),
shooting(false), shooting(false),
group(CCreatureAnim::SHOOT_FRONT), group(CCreatureAnim::SHOOT_FRONT),
soundPlayed(false), soundPlayed(false),
@ -190,8 +190,8 @@ CAttackAnimation::CAttackAnimation(BattleInterface *_owner, const CStack *attack
attackingStackPosBeforeReturn = attackingStack->getPosition(); attackingStackPosBeforeReturn = attackingStack->getPosition();
} }
CDefenceAnimation::CDefenceAnimation(StackAttackedInfo _attackedInfo, BattleInterface * _owner) CDefenceAnimation::CDefenceAnimation(StackAttackedInfo _attackedInfo, BattleInterface & owner)
: CBattleStackAnimation(_owner, _attackedInfo.defender), : CBattleStackAnimation(owner, _attackedInfo.defender),
attacker(_attackedInfo.attacker), attacker(_attackedInfo.attacker),
rangedAttack(_attackedInfo.indirectAttack), rangedAttack(_attackedInfo.indirectAttack),
killed(_attackedInfo.killed), killed(_attackedInfo.killed),
@ -235,14 +235,14 @@ bool CDefenceAnimation::init()
//reverse unit if necessary //reverse unit if necessary
if(attacker && owner->getCurrentPlayerInterface()->cb->isToReverse(stack->getPosition(), attacker->getPosition(), stackFacingRight(stack), attacker->doubleWide(), stackFacingRight(attacker))) if(attacker && owner.getCurrentPlayerInterface()->cb->isToReverse(stack->getPosition(), attacker->getPosition(), stackFacingRight(stack), attacker->doubleWide(), stackFacingRight(attacker)))
{ {
owner->stacksController->addNewAnim(new CReverseAnimation(owner, stack, stack->getPosition(), true)); owner.stacksController->addNewAnim(new CReverseAnimation(owner, stack, stack->getPosition(), true));
return false; return false;
} }
//unit reversed //unit reversed
if(rangedAttack && attacker != nullptr && owner->projectilesController->hasActiveProjectile(attacker)) //delay hit animation if(rangedAttack && attacker != nullptr && owner.projectilesController->hasActiveProjectile(attacker)) //delay hit animation
{ {
return false; return false;
} }
@ -327,8 +327,8 @@ CDefenceAnimation::~CDefenceAnimation()
} }
} }
CDummyAnimation::CDummyAnimation(BattleInterface * _owner, int howManyFrames) CDummyAnimation::CDummyAnimation(BattleInterface & owner, int howManyFrames)
: CBattleAnimation(_owner), : CBattleAnimation(owner),
counter(0), counter(0),
howMany(howManyFrames) howMany(howManyFrames)
{ {
@ -358,11 +358,11 @@ bool CMeleeAttackAnimation::init()
return false; return false;
} }
bool toReverse = owner->getCurrentPlayerInterface()->cb->isToReverse(attackingStackPosBeforeReturn, attackedStack->getPosition(), stackFacingRight(stack), attackedStack->doubleWide(), stackFacingRight(attackedStack)); bool toReverse = owner.getCurrentPlayerInterface()->cb->isToReverse(attackingStackPosBeforeReturn, attackedStack->getPosition(), stackFacingRight(stack), attackedStack->doubleWide(), stackFacingRight(attackedStack));
if(toReverse) if(toReverse)
{ {
owner->stacksController->addNewAnim(new CReverseAnimation(owner, stack, attackingStackPosBeforeReturn, true)); owner.stacksController->addNewAnim(new CReverseAnimation(owner, stack, attackingStackPosBeforeReturn, true));
return false; return false;
} }
@ -438,14 +438,14 @@ bool CMeleeAttackAnimation::init()
return true; return true;
} }
CMeleeAttackAnimation::CMeleeAttackAnimation(BattleInterface * _owner, const CStack * attacker, BattleHex _dest, const CStack * _attacked) CMeleeAttackAnimation::CMeleeAttackAnimation(BattleInterface & owner, const CStack * attacker, BattleHex _dest, const CStack * _attacked)
: CAttackAnimation(_owner, attacker, _dest, _attacked) : CAttackAnimation(owner, attacker, _dest, _attacked)
{ {
logAnim->debug("Created melee attack anim for %s", attacker->getName()); logAnim->debug("Created melee attack anim for %s", attacker->getName());
} }
CStackMoveAnimation::CStackMoveAnimation(BattleInterface * _owner, const CStack * _stack, BattleHex _currentHex): CStackMoveAnimation::CStackMoveAnimation(BattleInterface & owner, const CStack * _stack, BattleHex _currentHex):
CBattleStackAnimation(_owner, _stack), CBattleStackAnimation(owner, _stack),
currentHex(_currentHex) currentHex(_currentHex)
{ {
@ -471,13 +471,13 @@ bool CMovementAnimation::init()
} }
//reverse unit if necessary //reverse unit if necessary
if(owner->stacksController->shouldRotate(stack, oldPos, currentHex)) if(owner.stacksController->shouldRotate(stack, oldPos, currentHex))
{ {
// it seems that H3 does NOT plays full rotation animation here in most situations // it seems that H3 does NOT plays full rotation animation here in most situations
// Logical since it takes quite a lot of time // Logical since it takes quite a lot of time
if (curentMoveIndex == 0) // full rotation only for moving towards first tile. if (curentMoveIndex == 0) // full rotation only for moving towards first tile.
{ {
owner->stacksController->addNewAnim(new CReverseAnimation(owner, stack, oldPos, true)); owner.stacksController->addNewAnim(new CReverseAnimation(owner, stack, oldPos, true));
return false; return false;
} }
else else
@ -491,13 +491,13 @@ bool CMovementAnimation::init()
myAnim->setType(CCreatureAnim::MOVING); myAnim->setType(CCreatureAnim::MOVING);
} }
if (owner->moveSoundHander == -1) if (owner.moveSoundHander == -1)
{ {
owner->moveSoundHander = CCS->soundh->playSound(battle_sound(stack->getCreature(), move), -1); owner.moveSoundHander = CCS->soundh->playSound(battle_sound(stack->getCreature(), move), -1);
} }
Point begPosition = owner->stacksController->getStackPositionAtHex(oldPos, stack); Point begPosition = owner.stacksController->getStackPositionAtHex(oldPos, stack);
Point endPosition = owner->stacksController->getStackPositionAtHex(currentHex, stack); Point endPosition = owner.stacksController->getStackPositionAtHex(currentHex, stack);
timeToMove = AnimationControls::getMovementDuration(stack->getCreature()); timeToMove = AnimationControls::getMovementDuration(stack->getCreature());
@ -530,7 +530,7 @@ void CMovementAnimation::nextFrame()
if(progress >= 1.0) if(progress >= 1.0)
{ {
// Sets the position of the creature animation sprites // Sets the position of the creature animation sprites
Point coords = owner->stacksController->getStackPositionAtHex(currentHex, stack); Point coords = owner.stacksController->getStackPositionAtHex(currentHex, stack);
myAnim->pos = coords; myAnim->pos = coords;
// true if creature haven't reached the final destination hex // true if creature haven't reached the final destination hex
@ -553,18 +553,18 @@ CMovementAnimation::~CMovementAnimation()
{ {
assert(stack); assert(stack);
myAnim->pos = owner->stacksController->getStackPositionAtHex(currentHex, stack); myAnim->pos = owner.stacksController->getStackPositionAtHex(currentHex, stack);
owner->stacksController->addNewAnim(new CMovementEndAnimation(owner, stack, currentHex)); owner.stacksController->addNewAnim(new CMovementEndAnimation(owner, stack, currentHex));
if(owner->moveSoundHander != -1) if(owner.moveSoundHander != -1)
{ {
CCS->soundh->stopSound(owner->moveSoundHander); CCS->soundh->stopSound(owner.moveSoundHander);
owner->moveSoundHander = -1; owner.moveSoundHander = -1;
} }
} }
CMovementAnimation::CMovementAnimation(BattleInterface *_owner, const CStack *_stack, std::vector<BattleHex> _destTiles, int _distance) CMovementAnimation::CMovementAnimation(BattleInterface & owner, const CStack *_stack, std::vector<BattleHex> _destTiles, int _distance)
: CStackMoveAnimation(_owner, _stack, _destTiles.front()), : CStackMoveAnimation(owner, _stack, _destTiles.front()),
destTiles(_destTiles), destTiles(_destTiles),
curentMoveIndex(0), curentMoveIndex(0),
oldPos(stack->getPosition()), oldPos(stack->getPosition()),
@ -576,8 +576,8 @@ CMovementAnimation::CMovementAnimation(BattleInterface *_owner, const CStack *_s
logAnim->debug("Created movement anim for %s", stack->getName()); logAnim->debug("Created movement anim for %s", stack->getName());
} }
CMovementEndAnimation::CMovementEndAnimation(BattleInterface * _owner, const CStack * _stack, BattleHex destTile) CMovementEndAnimation::CMovementEndAnimation(BattleInterface & owner, const CStack * _stack, BattleHex destTile)
: CStackMoveAnimation(_owner, _stack, destTile) : CStackMoveAnimation(owner, _stack, destTile)
{ {
logAnim->debug("Created movement end anim for %s", stack->getName()); logAnim->debug("Created movement end anim for %s", stack->getName());
} }
@ -611,8 +611,8 @@ CMovementEndAnimation::~CMovementEndAnimation()
CCS->curh->show(); CCS->curh->show();
} }
CMovementStartAnimation::CMovementStartAnimation(BattleInterface * _owner, const CStack * _stack) CMovementStartAnimation::CMovementStartAnimation(BattleInterface & owner, const CStack * _stack)
: CStackMoveAnimation(_owner, _stack, _stack->getPosition()) : CStackMoveAnimation(owner, _stack, _stack->getPosition())
{ {
logAnim->debug("Created movement start anim for %s", stack->getName()); logAnim->debug("Created movement start anim for %s", stack->getName());
} }
@ -636,8 +636,8 @@ bool CMovementStartAnimation::init()
return true; return true;
} }
CReverseAnimation::CReverseAnimation(BattleInterface * _owner, const CStack * stack, BattleHex dest, bool _priority) CReverseAnimation::CReverseAnimation(BattleInterface & owner, const CStack * stack, BattleHex dest, bool _priority)
: CStackMoveAnimation(_owner, stack, dest), : CStackMoveAnimation(owner, stack, dest),
priority(_priority) priority(_priority)
{ {
logAnim->debug("Created reverse anim for %s", stack->getName()); logAnim->debug("Created reverse anim for %s", stack->getName());
@ -676,7 +676,7 @@ void CBattleStackAnimation::rotateStack(BattleHex hex)
{ {
setStackFacingRight(stack, !stackFacingRight(stack)); setStackFacingRight(stack, !stackFacingRight(stack));
stackAnimation(stack)->pos = owner->stacksController->getStackPositionAtHex(hex, stack); stackAnimation(stack)->pos = owner.stacksController->getStackPositionAtHex(hex, stack);
} }
void CReverseAnimation::setupSecondPart() void CReverseAnimation::setupSecondPart()
@ -698,8 +698,8 @@ void CReverseAnimation::setupSecondPart()
delete this; delete this;
} }
CRangedAttackAnimation::CRangedAttackAnimation(BattleInterface * owner_, const CStack * attacker, BattleHex dest_, const CStack * defender) CRangedAttackAnimation::CRangedAttackAnimation(BattleInterface & owner, const CStack * attacker, BattleHex dest_, const CStack * defender)
: CAttackAnimation(owner_, attacker, dest_, defender), : CAttackAnimation(owner, attacker, dest_, defender),
projectileEmitted(false) projectileEmitted(false)
{ {
logAnim->info("Ranged attack animation created"); logAnim->info("Ranged attack animation created");
@ -722,9 +722,9 @@ bool CRangedAttackAnimation::init()
} }
//reverse unit if necessary //reverse unit if necessary
if (attackingStack && attackedStack && owner->getCurrentPlayerInterface()->cb->isToReverse(attackingStack->getPosition(), attackedStack->getPosition(), stackFacingRight(attackingStack), attackingStack->doubleWide(), stackFacingRight(attackedStack))) if (attackingStack && attackedStack && owner.getCurrentPlayerInterface()->cb->isToReverse(attackingStack->getPosition(), attackedStack->getPosition(), stackFacingRight(attackingStack), attackingStack->doubleWide(), stackFacingRight(attackedStack)))
{ {
owner->stacksController->addNewAnim(new CReverseAnimation(owner, attackingStack, attackingStack->getPosition(), true)); owner.stacksController->addNewAnim(new CReverseAnimation(owner, attackingStack, attackingStack->getPosition(), true));
return false; return false;
} }
@ -738,7 +738,7 @@ bool CRangedAttackAnimation::init()
void CRangedAttackAnimation::setAnimationGroup() void CRangedAttackAnimation::setAnimationGroup()
{ {
Point shooterPos = stackAnimation(attackingStack)->pos.topLeft(); Point shooterPos = stackAnimation(attackingStack)->pos.topLeft();
Point shotTarget = owner->stacksController->getStackPositionAtHex(dest, attackedStack); Point shotTarget = owner.stacksController->getStackPositionAtHex(dest, attackedStack);
//maximal angle in radians between straight horizontal line and shooting line for which shot is considered to be straight (absoulte value) //maximal angle in radians between straight horizontal line and shooting line for which shot is considered to be straight (absoulte value)
static const double straightAngle = 0.2; static const double straightAngle = 0.2;
@ -757,7 +757,7 @@ void CRangedAttackAnimation::setAnimationGroup()
void CRangedAttackAnimation::initializeProjectile() void CRangedAttackAnimation::initializeProjectile()
{ {
const CCreature *shooterInfo = getCreature(); const CCreature *shooterInfo = getCreature();
Point shotTarget = owner->stacksController->getStackPositionAtHex(dest, attackedStack) + Point(225, 225); Point shotTarget = owner.stacksController->getStackPositionAtHex(dest, attackedStack) + Point(225, 225);
Point shotOrigin = stackAnimation(attackingStack)->pos.topLeft() + Point(222, 265); Point shotOrigin = stackAnimation(attackingStack)->pos.topLeft() + Point(222, 265);
int multiplier = stackFacingRight(attackingStack) ? 1 : -1; int multiplier = stackFacingRight(attackingStack) ? 1 : -1;
@ -787,7 +787,7 @@ void CRangedAttackAnimation::initializeProjectile()
void CRangedAttackAnimation::emitProjectile() void CRangedAttackAnimation::emitProjectile()
{ {
logAnim->info("Ranged attack projectile emitted"); logAnim->info("Ranged attack projectile emitted");
owner->projectilesController->emitStackProjectile(attackingStack); owner.projectilesController->emitStackProjectile(attackingStack);
projectileEmitted = true; projectileEmitted = true;
} }
@ -807,7 +807,7 @@ void CRangedAttackAnimation::nextFrame()
// animation should be paused if there is an active projectile // animation should be paused if there is an active projectile
if (projectileEmitted) if (projectileEmitted)
{ {
if (owner->projectilesController->hasActiveProjectile(attackingStack)) if (owner.projectilesController->hasActiveProjectile(attackingStack))
stackAnimation(attackingStack)->pause(); stackAnimation(attackingStack)->pause();
else else
stackAnimation(attackingStack)->play(); stackAnimation(attackingStack)->play();
@ -836,7 +836,7 @@ CRangedAttackAnimation::~CRangedAttackAnimation()
{ {
logAnim->info("Ranged attack animation is over"); logAnim->info("Ranged attack animation is over");
//FIXME: this assert triggers under some unclear, rare conditions. Possibly - if game window is inactive and/or in foreground/minimized? //FIXME: this assert triggers under some unclear, rare conditions. Possibly - if game window is inactive and/or in foreground/minimized?
assert(!owner->projectilesController->hasActiveProjectile(attackingStack)); assert(!owner.projectilesController->hasActiveProjectile(attackingStack));
assert(projectileEmitted); assert(projectileEmitted);
// FIXME: is this possible? Animation is over but we're yet to fire projectile? // FIXME: is this possible? Animation is over but we're yet to fire projectile?
@ -847,15 +847,15 @@ CRangedAttackAnimation::~CRangedAttackAnimation()
} }
} }
CShootingAnimation::CShootingAnimation(BattleInterface * _owner, const CStack * attacker, BattleHex _dest, const CStack * _attacked) CShootingAnimation::CShootingAnimation(BattleInterface & owner, const CStack * attacker, BattleHex _dest, const CStack * _attacked)
: CRangedAttackAnimation(_owner, attacker, _dest, _attacked) : CRangedAttackAnimation(owner, attacker, _dest, _attacked)
{ {
logAnim->debug("Created shooting anim for %s", stack->getName()); logAnim->debug("Created shooting anim for %s", stack->getName());
} }
void CShootingAnimation::createProjectile(const Point & from, const Point & dest) const void CShootingAnimation::createProjectile(const Point & from, const Point & dest) const
{ {
owner->projectilesController->createProjectile(attackingStack, from, dest); owner.projectilesController->createProjectile(attackingStack, from, dest);
} }
uint32_t CShootingAnimation::getAttackClimaxFrame() const uint32_t CShootingAnimation::getAttackClimaxFrame() const
@ -879,8 +879,8 @@ CCreatureAnim::EAnimType CShootingAnimation::getDownwardsGroup() const
return CCreatureAnim::SHOOT_DOWN; return CCreatureAnim::SHOOT_DOWN;
} }
CCatapultAnimation::CCatapultAnimation(BattleInterface * _owner, const CStack * attacker, BattleHex _dest, const CStack * _attacked, int _catapultDmg) CCatapultAnimation::CCatapultAnimation(BattleInterface & owner, const CStack * attacker, BattleHex _dest, const CStack * _attacked, int _catapultDmg)
: CShootingAnimation(_owner, attacker, _dest, _attacked), : CShootingAnimation(owner, attacker, _dest, _attacked),
catapultDamage(_catapultDmg), catapultDamage(_catapultDmg),
explosionEmitted(false) explosionEmitted(false)
{ {
@ -897,26 +897,26 @@ void CCatapultAnimation::nextFrame()
if ( !projectileEmitted) if ( !projectileEmitted)
return; return;
if (owner->projectilesController->hasActiveProjectile(attackingStack)) if (owner.projectilesController->hasActiveProjectile(attackingStack))
return; return;
explosionEmitted = true; explosionEmitted = true;
Point shotTarget = owner->stacksController->getStackPositionAtHex(dest, attackedStack) + Point(225, 225) - Point(126, 105); Point shotTarget = owner.stacksController->getStackPositionAtHex(dest, attackedStack) + Point(225, 225) - Point(126, 105);
if(catapultDamage > 0) if(catapultDamage > 0)
owner->stacksController->addNewAnim( new CPointEffectAnimation(owner, soundBase::WALLHIT, "SGEXPL.DEF", shotTarget)); owner.stacksController->addNewAnim( new CPointEffectAnimation(owner, soundBase::WALLHIT, "SGEXPL.DEF", shotTarget));
else else
owner->stacksController->addNewAnim( new CPointEffectAnimation(owner, soundBase::WALLMISS, "CSGRCK.DEF", shotTarget)); owner.stacksController->addNewAnim( new CPointEffectAnimation(owner, soundBase::WALLMISS, "CSGRCK.DEF", shotTarget));
} }
void CCatapultAnimation::createProjectile(const Point & from, const Point & dest) const void CCatapultAnimation::createProjectile(const Point & from, const Point & dest) const
{ {
owner->projectilesController->createCatapultProjectile(attackingStack, from, dest); owner.projectilesController->createCatapultProjectile(attackingStack, from, dest);
} }
CCastAnimation::CCastAnimation(BattleInterface * owner_, const CStack * attacker, BattleHex dest_, const CStack * defender, const CSpell * spell) CCastAnimation::CCastAnimation(BattleInterface & owner, const CStack * attacker, BattleHex dest_, const CStack * defender, const CSpell * spell)
: CRangedAttackAnimation(owner_, attacker, dest_, defender), : CRangedAttackAnimation(owner, attacker, dest_, defender),
spell(spell) spell(spell)
{ {
assert(dest.isValid());// FIXME: when? assert(dest.isValid());// FIXME: when?
@ -970,7 +970,7 @@ CCreatureAnim::EAnimType CCastAnimation::getDownwardsGroup() const
void CCastAnimation::createProjectile(const Point & from, const Point & dest) const void CCastAnimation::createProjectile(const Point & from, const Point & dest) const
{ {
if (!spell->animationInfo.projectile.empty()) if (!spell->animationInfo.projectile.empty())
owner->projectilesController->createSpellProjectile(attackingStack, from, dest, spell); owner.projectilesController->createSpellProjectile(attackingStack, from, dest, spell);
} }
uint32_t CCastAnimation::getAttackClimaxFrame() const uint32_t CCastAnimation::getAttackClimaxFrame() const
@ -983,8 +983,8 @@ uint32_t CCastAnimation::getAttackClimaxFrame() const
return 0; return 0;
} }
CPointEffectAnimation::CPointEffectAnimation(BattleInterface * _owner, soundBase::soundID sound, std::string animationName, int effects): CPointEffectAnimation::CPointEffectAnimation(BattleInterface & owner, soundBase::soundID sound, std::string animationName, int effects):
CBattleAnimation(_owner), CBattleAnimation(owner),
animation(std::make_shared<CAnimation>(animationName)), animation(std::make_shared<CAnimation>(animationName)),
sound(sound), sound(sound),
effectFlags(effects), effectFlags(effects),
@ -994,33 +994,33 @@ CPointEffectAnimation::CPointEffectAnimation(BattleInterface * _owner, soundBase
{ {
} }
CPointEffectAnimation::CPointEffectAnimation(BattleInterface * _owner, soundBase::soundID sound, std::string animationName, std::vector<BattleHex> hex, int effects): CPointEffectAnimation::CPointEffectAnimation(BattleInterface & owner, soundBase::soundID sound, std::string animationName, std::vector<BattleHex> hex, int effects):
CPointEffectAnimation(_owner, sound, animationName, effects) CPointEffectAnimation(owner, sound, animationName, effects)
{ {
battlehexes = hex; battlehexes = hex;
} }
CPointEffectAnimation::CPointEffectAnimation(BattleInterface * _owner, soundBase::soundID sound, std::string animationName, BattleHex hex, int effects): CPointEffectAnimation::CPointEffectAnimation(BattleInterface & owner, soundBase::soundID sound, std::string animationName, BattleHex hex, int effects):
CPointEffectAnimation(_owner, sound, animationName, effects) CPointEffectAnimation(owner, sound, animationName, effects)
{ {
assert(hex.isValid()); assert(hex.isValid());
battlehexes.push_back(hex); battlehexes.push_back(hex);
} }
CPointEffectAnimation::CPointEffectAnimation(BattleInterface * _owner, soundBase::soundID sound, std::string animationName, std::vector<Point> pos, int effects): CPointEffectAnimation::CPointEffectAnimation(BattleInterface & owner, soundBase::soundID sound, std::string animationName, std::vector<Point> pos, int effects):
CPointEffectAnimation(_owner, sound, animationName, effects) CPointEffectAnimation(owner, sound, animationName, effects)
{ {
positions = pos; positions = pos;
} }
CPointEffectAnimation::CPointEffectAnimation(BattleInterface * _owner, soundBase::soundID sound, std::string animationName, Point pos, int effects): CPointEffectAnimation::CPointEffectAnimation(BattleInterface & owner, soundBase::soundID sound, std::string animationName, Point pos, int effects):
CPointEffectAnimation(_owner, sound, animationName, effects) CPointEffectAnimation(owner, sound, animationName, effects)
{ {
positions.push_back(pos); positions.push_back(pos);
} }
CPointEffectAnimation::CPointEffectAnimation(BattleInterface * _owner, soundBase::soundID sound, std::string animationName, Point pos, BattleHex hex, int effects): CPointEffectAnimation::CPointEffectAnimation(BattleInterface & owner, soundBase::soundID sound, std::string animationName, Point pos, BattleHex hex, int effects):
CPointEffectAnimation(_owner, sound, animationName, effects) CPointEffectAnimation(owner, sound, animationName, effects)
{ {
assert(hex.isValid()); assert(hex.isValid());
battlehexes.push_back(hex); battlehexes.push_back(hex);
@ -1043,9 +1043,9 @@ bool CPointEffectAnimation::init()
if (screenFill()) if (screenFill())
{ {
for(int i=0; i * first->width() < owner->pos.w ; ++i) for(int i=0; i * first->width() < owner.pos.w ; ++i)
for(int j=0; j * first->height() < owner->pos.h ; ++j) for(int j=0; j * first->height() < owner.pos.h ; ++j)
positions.push_back(Point( owner->pos.x + i * first->width(), owner->pos.y + j * first->height())); positions.push_back(Point( owner.pos.x + i * first->width(), owner.pos.y + j * first->height()));
} }
BattleEffect be; BattleEffect be;
@ -1070,8 +1070,8 @@ bool CPointEffectAnimation::init()
} }
else else
{ {
const CStack * destStack = owner->getCurrentPlayerInterface()->cb->battleGetStackByPos(battlehexes[i], false); const CStack * destStack = owner.getCurrentPlayerInterface()->cb->battleGetStackByPos(battlehexes[i], false);
Rect tilePos = owner->fieldController->hexPositionAbsolute(battlehexes[i]); Rect tilePos = owner.fieldController->hexPositionAbsolute(battlehexes[i]);
be.x = tilePos.x + tilePos.w/2 - first->width()/2; be.x = tilePos.x + tilePos.w/2 - first->width()/2;
@ -1083,7 +1083,7 @@ bool CPointEffectAnimation::init()
else else
be.y = tilePos.y - first->height()/2; be.y = tilePos.y - first->height()/2;
} }
owner->effectsController->battleEffects.push_back(be); owner.effectsController->battleEffects.push_back(be);
} }
return true; return true;
} }
@ -1156,7 +1156,7 @@ void CPointEffectAnimation::playEffect()
if ( effectFinished ) if ( effectFinished )
return; return;
for(auto & elem : owner->effectsController->battleEffects) for(auto & elem : owner.effectsController->battleEffects)
{ {
if(elem.effectID == ID) if(elem.effectID == ID)
{ {
@ -1174,7 +1174,7 @@ void CPointEffectAnimation::playEffect()
void CPointEffectAnimation::clearEffect() void CPointEffectAnimation::clearEffect()
{ {
auto & effects = owner->effectsController->battleEffects; auto & effects = owner.effectsController->battleEffects;
for ( auto it = effects.begin(); it != effects.end(); ) for ( auto it = effects.begin(); it != effects.end(); )
{ {
@ -1191,8 +1191,8 @@ CPointEffectAnimation::~CPointEffectAnimation()
assert(soundFinished); assert(soundFinished);
} }
CWaitingAnimation::CWaitingAnimation(BattleInterface * owner_): CWaitingAnimation::CWaitingAnimation(BattleInterface & owner):
CBattleAnimation(owner_) CBattleAnimation(owner)
{} {}
void CWaitingAnimation::nextFrame() void CWaitingAnimation::nextFrame()
@ -1201,8 +1201,8 @@ void CWaitingAnimation::nextFrame()
delete this; delete this;
} }
CWaitingProjectileAnimation::CWaitingProjectileAnimation(BattleInterface * owner_, const CStack * shooter): CWaitingProjectileAnimation::CWaitingProjectileAnimation(BattleInterface & owner, const CStack * shooter):
CWaitingAnimation(owner_), CWaitingAnimation(owner),
shooter(shooter) shooter(shooter)
{} {}
@ -1219,7 +1219,7 @@ bool CWaitingProjectileAnimation::init()
} }
} }
if(owner->projectilesController->hasActiveProjectile(shooter)) if(owner.projectilesController->hasActiveProjectile(shooter))
return false; return false;
return true; return true;

View File

@ -30,7 +30,7 @@ class CBattleAnimation
{ {
protected: protected:
BattleInterface * owner; BattleInterface & owner;
bool initialized; bool initialized;
std::vector<CBattleAnimation *> & pendingAnimations(); std::vector<CBattleAnimation *> & pendingAnimations();
@ -49,7 +49,7 @@ public:
virtual void nextFrame() {} //call every new frame virtual void nextFrame() {} //call every new frame
virtual ~CBattleAnimation(); virtual ~CBattleAnimation();
CBattleAnimation(BattleInterface * _owner); CBattleAnimation(BattleInterface & owner);
}; };
/// Sub-class which is responsible for managing the battle stack animation. /// Sub-class which is responsible for managing the battle stack animation.
@ -59,7 +59,7 @@ public:
std::shared_ptr<CreatureAnimation> myAnim; //animation for our stack, managed by CBattleInterface std::shared_ptr<CreatureAnimation> myAnim; //animation for our stack, managed by CBattleInterface
const CStack * stack; //id of stack whose animation it is const CStack * stack; //id of stack whose animation it is
CBattleStackAnimation(BattleInterface * _owner, const CStack * _stack); CBattleStackAnimation(BattleInterface & owner, const CStack * _stack);
void shiftColor(const ColorShifter * shifter); void shiftColor(const ColorShifter * shifter);
void rotateStack(BattleHex hex); void rotateStack(BattleHex hex);
@ -83,7 +83,7 @@ public:
void nextFrame() override; void nextFrame() override;
bool checkInitialConditions(); bool checkInitialConditions();
CAttackAnimation(BattleInterface *_owner, const CStack *attacker, BattleHex _dest, const CStack *defender); CAttackAnimation(BattleInterface & owner, const CStack *attacker, BattleHex _dest, const CStack *defender);
~CAttackAnimation(); ~CAttackAnimation();
}; };
@ -104,7 +104,7 @@ public:
bool init() override; bool init() override;
void nextFrame() override; void nextFrame() override;
CDefenceAnimation(StackAttackedInfo _attackedInfo, BattleInterface * _owner); CDefenceAnimation(StackAttackedInfo _attackedInfo, BattleInterface & owner);
~CDefenceAnimation(); ~CDefenceAnimation();
}; };
@ -117,7 +117,7 @@ public:
bool init() override; bool init() override;
void nextFrame() override; void nextFrame() override;
CDummyAnimation(BattleInterface * _owner, int howManyFrames); CDummyAnimation(BattleInterface & owner, int howManyFrames);
}; };
/// Hand-to-hand attack /// Hand-to-hand attack
@ -126,7 +126,7 @@ class CMeleeAttackAnimation : public CAttackAnimation
public: public:
bool init() override; bool init() override;
CMeleeAttackAnimation(BattleInterface * _owner, const CStack * attacker, BattleHex _dest, const CStack * _attacked); CMeleeAttackAnimation(BattleInterface & owner, const CStack * attacker, BattleHex _dest, const CStack * _attacked);
}; };
/// Base class for all animations that play during stack movement /// Base class for all animations that play during stack movement
@ -136,7 +136,7 @@ public:
BattleHex currentHex; BattleHex currentHex;
protected: protected:
CStackMoveAnimation(BattleInterface * _owner, const CStack * _stack, BattleHex _currentHex); CStackMoveAnimation(BattleInterface & owner, const CStack * _stack, BattleHex _currentHex);
}; };
/// Move animation of a creature /// Move animation of a creature
@ -158,7 +158,7 @@ public:
bool init() override; bool init() override;
void nextFrame() override; void nextFrame() override;
CMovementAnimation(BattleInterface *_owner, const CStack *_stack, std::vector<BattleHex> _destTiles, int _distance); CMovementAnimation(BattleInterface & owner, const CStack *_stack, std::vector<BattleHex> _destTiles, int _distance);
~CMovementAnimation(); ~CMovementAnimation();
}; };
@ -168,7 +168,7 @@ class CMovementEndAnimation : public CStackMoveAnimation
public: public:
bool init() override; bool init() override;
CMovementEndAnimation(BattleInterface * _owner, const CStack * _stack, BattleHex destTile); CMovementEndAnimation(BattleInterface & owner, const CStack * _stack, BattleHex destTile);
~CMovementEndAnimation(); ~CMovementEndAnimation();
}; };
@ -178,7 +178,7 @@ class CMovementStartAnimation : public CStackMoveAnimation
public: public:
bool init() override; bool init() override;
CMovementStartAnimation(BattleInterface * _owner, const CStack * _stack); CMovementStartAnimation(BattleInterface & owner, const CStack * _stack);
}; };
/// Class responsible for animation of stack chaning direction (left <-> right) /// Class responsible for animation of stack chaning direction (left <-> right)
@ -190,7 +190,7 @@ public:
void setupSecondPart(); void setupSecondPart();
CReverseAnimation(BattleInterface * _owner, const CStack * stack, BattleHex dest, bool _priority); CReverseAnimation(BattleInterface & owner, const CStack * stack, BattleHex dest, bool _priority);
~CReverseAnimation(); ~CReverseAnimation();
}; };
@ -213,7 +213,7 @@ protected:
virtual uint32_t getAttackClimaxFrame() const = 0; virtual uint32_t getAttackClimaxFrame() const = 0;
public: public:
CRangedAttackAnimation(BattleInterface * owner_, const CStack * attacker, BattleHex dest, const CStack * defender); CRangedAttackAnimation(BattleInterface & owner, const CStack * attacker, BattleHex dest, const CStack * defender);
~CRangedAttackAnimation(); ~CRangedAttackAnimation();
bool init() override; bool init() override;
@ -231,7 +231,7 @@ class CShootingAnimation : public CRangedAttackAnimation
uint32_t getAttackClimaxFrame() const override; uint32_t getAttackClimaxFrame() const override;
public: public:
CShootingAnimation(BattleInterface * _owner, const CStack * attacker, BattleHex dest, const CStack * defender); CShootingAnimation(BattleInterface & owner, const CStack * attacker, BattleHex dest, const CStack * defender);
}; };
@ -243,7 +243,7 @@ private:
int catapultDamage; int catapultDamage;
public: public:
CCatapultAnimation(BattleInterface * _owner, const CStack * attacker, BattleHex dest, const CStack * defender, int _catapultDmg = 0); CCatapultAnimation(BattleInterface & owner, const CStack * attacker, BattleHex dest, const CStack * defender, int _catapultDmg = 0);
void createProjectile(const Point & from, const Point & dest) const override; void createProjectile(const Point & from, const Point & dest) const override;
void nextFrame() override; void nextFrame() override;
@ -262,7 +262,7 @@ class CCastAnimation : public CRangedAttackAnimation
uint32_t getAttackClimaxFrame() const override; uint32_t getAttackClimaxFrame() const override;
public: public:
CCastAnimation(BattleInterface * owner_, const CStack * attacker, BattleHex dest_, const CStack * defender, const CSpell * spell); CCastAnimation(BattleInterface & owner, const CStack * attacker, BattleHex dest_, const CStack * defender, const CSpell * spell);
}; };
struct CPointEffectParameters struct CPointEffectParameters
@ -313,17 +313,17 @@ public:
}; };
/// Create animation with screen-wide effect /// Create animation with screen-wide effect
CPointEffectAnimation(BattleInterface * _owner, soundBase::soundID sound, std::string animationName, int effects = 0); CPointEffectAnimation(BattleInterface & owner, soundBase::soundID sound, std::string animationName, int effects = 0);
/// Create animation positioned at point(s). Note that positions must be are absolute, including battleint position offset /// Create animation positioned at point(s). Note that positions must be are absolute, including battleint position offset
CPointEffectAnimation(BattleInterface * _owner, soundBase::soundID sound, std::string animationName, Point pos , int effects = 0); CPointEffectAnimation(BattleInterface & owner, soundBase::soundID sound, std::string animationName, Point pos , int effects = 0);
CPointEffectAnimation(BattleInterface * _owner, soundBase::soundID sound, std::string animationName, std::vector<Point> pos , int effects = 0); CPointEffectAnimation(BattleInterface & owner, soundBase::soundID sound, std::string animationName, std::vector<Point> pos , int effects = 0);
/// Create animation positioned at certain hex(es) /// Create animation positioned at certain hex(es)
CPointEffectAnimation(BattleInterface * _owner, soundBase::soundID sound, std::string animationName, BattleHex hex , int effects = 0); CPointEffectAnimation(BattleInterface & owner, soundBase::soundID sound, std::string animationName, BattleHex hex , int effects = 0);
CPointEffectAnimation(BattleInterface * _owner, soundBase::soundID sound, std::string animationName, std::vector<BattleHex> hex, int effects = 0); CPointEffectAnimation(BattleInterface & owner, soundBase::soundID sound, std::string animationName, std::vector<BattleHex> hex, int effects = 0);
CPointEffectAnimation(BattleInterface * _owner, soundBase::soundID sound, std::string animationName, Point pos, BattleHex hex, int effects = 0); CPointEffectAnimation(BattleInterface & owner, soundBase::soundID sound, std::string animationName, Point pos, BattleHex hex, int effects = 0);
~CPointEffectAnimation(); ~CPointEffectAnimation();
bool init() override; bool init() override;
@ -334,7 +334,7 @@ public:
class CWaitingAnimation : public CBattleAnimation class CWaitingAnimation : public CBattleAnimation
{ {
protected: protected:
CWaitingAnimation(BattleInterface * owner_); CWaitingAnimation(BattleInterface & owner);
public: public:
void nextFrame() override; void nextFrame() override;
}; };
@ -344,7 +344,7 @@ class CWaitingProjectileAnimation : public CWaitingAnimation
{ {
const CStack * shooter; const CStack * shooter;
public: public:
CWaitingProjectileAnimation(BattleInterface * owner_, const CStack * shooter); CWaitingProjectileAnimation(BattleInterface & owner, const CStack * shooter);
bool init() override; bool init() override;
}; };

View File

@ -29,7 +29,7 @@
#include "../../lib/CStack.h" #include "../../lib/CStack.h"
#include "../../lib/CConfigHandler.h" #include "../../lib/CConfigHandler.h"
BattleControlPanel::BattleControlPanel(BattleInterface * owner, const Point & position): BattleControlPanel::BattleControlPanel(BattleInterface & owner, const Point & position):
owner(owner) owner(owner)
{ {
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
@ -53,7 +53,7 @@ BattleControlPanel::BattleControlPanel(BattleInterface * owner, const Point & po
console = std::make_shared<BattleConsole>(Rect(211, 4, 406,38)); console = std::make_shared<BattleConsole>(Rect(211, 4, 406,38));
GH.statusbar = console; GH.statusbar = console;
if ( owner->tacticsMode ) if ( owner.tacticsMode )
tacticPhaseStarted(); tacticPhaseStarted();
else else
tacticPhaseEnded(); tacticPhaseEnded();
@ -81,7 +81,7 @@ void BattleControlPanel::tacticPhaseStarted()
btactNext = std::make_shared<CButton>(Point(213, 4), "icm011.def", std::make_pair("", ""), [&]() { bTacticNextStack();}, SDLK_SPACE); btactNext = std::make_shared<CButton>(Point(213, 4), "icm011.def", std::make_pair("", ""), [&]() { bTacticNextStack();}, SDLK_SPACE);
btactEnd = std::make_shared<CButton>(Point(419, 4), "icm012.def", std::make_pair("", ""), [&](){ bTacticPhaseEnd();}, SDLK_RETURN); btactEnd = std::make_shared<CButton>(Point(419, 4), "icm012.def", std::make_pair("", ""), [&](){ bTacticPhaseEnd();}, SDLK_RETURN);
menu = std::make_shared<CPicture>("COPLACBR.BMP", 0, 0); menu = std::make_shared<CPicture>("COPLACBR.BMP", 0, 0);
menu->colorize(owner->curInt->playerID); menu->colorize(owner.curInt->playerID);
menu->recActions &= ~(SHOWALL | UPDATE); menu->recActions &= ~(SHOWALL | UPDATE);
} }
void BattleControlPanel::tacticPhaseEnded() void BattleControlPanel::tacticPhaseEnded()
@ -92,13 +92,13 @@ void BattleControlPanel::tacticPhaseEnded()
btactEnd.reset(); btactEnd.reset();
menu = std::make_shared<CPicture>("CBAR.BMP", 0, 0); menu = std::make_shared<CPicture>("CBAR.BMP", 0, 0);
menu->colorize(owner->curInt->playerID); menu->colorize(owner.curInt->playerID);
menu->recActions &= ~(SHOWALL | UPDATE); menu->recActions &= ~(SHOWALL | UPDATE);
} }
void BattleControlPanel::bOptionsf() void BattleControlPanel::bOptionsf()
{ {
if (owner->actionsController->spellcastingModeActive()) if (owner.actionsController->spellcastingModeActive())
return; return;
CCS->curh->changeGraphic(ECursor::ADVENTURE,0); CCS->curh->changeGraphic(ECursor::ADVENTURE,0);
@ -108,13 +108,13 @@ void BattleControlPanel::bOptionsf()
void BattleControlPanel::bSurrenderf() void BattleControlPanel::bSurrenderf()
{ {
if (owner->actionsController->spellcastingModeActive()) if (owner.actionsController->spellcastingModeActive())
return; return;
int cost = owner->curInt->cb->battleGetSurrenderCost(); int cost = owner.curInt->cb->battleGetSurrenderCost();
if(cost >= 0) if(cost >= 0)
{ {
std::string enemyHeroName = owner->curInt->cb->battleGetEnemyHero().name; std::string enemyHeroName = owner.curInt->cb->battleGetEnemyHero().name;
if(enemyHeroName.empty()) if(enemyHeroName.empty())
{ {
logGlobal->warn("Surrender performed without enemy hero, should not happen!"); logGlobal->warn("Surrender performed without enemy hero, should not happen!");
@ -122,110 +122,110 @@ void BattleControlPanel::bSurrenderf()
} }
std::string surrenderMessage = boost::str(boost::format(CGI->generaltexth->allTexts[32]) % enemyHeroName % cost); //%s states: "I will accept your surrender and grant you and your troops safe passage for the price of %d gold." std::string surrenderMessage = boost::str(boost::format(CGI->generaltexth->allTexts[32]) % enemyHeroName % cost); //%s states: "I will accept your surrender and grant you and your troops safe passage for the price of %d gold."
owner->curInt->showYesNoDialog(surrenderMessage, [this](){ reallySurrender(); }, nullptr); owner.curInt->showYesNoDialog(surrenderMessage, [this](){ reallySurrender(); }, nullptr);
} }
} }
void BattleControlPanel::bFleef() void BattleControlPanel::bFleef()
{ {
if (owner->actionsController->spellcastingModeActive()) if (owner.actionsController->spellcastingModeActive())
return; return;
if ( owner->curInt->cb->battleCanFlee() ) if ( owner.curInt->cb->battleCanFlee() )
{ {
CFunctionList<void()> ony = std::bind(&BattleControlPanel::reallyFlee,this); CFunctionList<void()> ony = std::bind(&BattleControlPanel::reallyFlee,this);
owner->curInt->showYesNoDialog(CGI->generaltexth->allTexts[28], ony, nullptr); //Are you sure you want to retreat? owner.curInt->showYesNoDialog(CGI->generaltexth->allTexts[28], ony, nullptr); //Are you sure you want to retreat?
} }
else else
{ {
std::vector<std::shared_ptr<CComponent>> comps; std::vector<std::shared_ptr<CComponent>> comps;
std::string heroName; std::string heroName;
//calculating fleeing hero's name //calculating fleeing hero's name
if (owner->attackingHeroInstance) if (owner.attackingHeroInstance)
if (owner->attackingHeroInstance->tempOwner == owner->curInt->cb->getMyColor()) if (owner.attackingHeroInstance->tempOwner == owner.curInt->cb->getMyColor())
heroName = owner->attackingHeroInstance->name; heroName = owner.attackingHeroInstance->name;
if (owner->defendingHeroInstance) if (owner.defendingHeroInstance)
if (owner->defendingHeroInstance->tempOwner == owner->curInt->cb->getMyColor()) if (owner.defendingHeroInstance->tempOwner == owner.curInt->cb->getMyColor())
heroName = owner->defendingHeroInstance->name; heroName = owner.defendingHeroInstance->name;
//calculating text //calculating text
auto txt = boost::format(CGI->generaltexth->allTexts[340]) % heroName; //The Shackles of War are present. %s can not retreat! auto txt = boost::format(CGI->generaltexth->allTexts[340]) % heroName; //The Shackles of War are present. %s can not retreat!
//printing message //printing message
owner->curInt->showInfoDialog(boost::to_string(txt), comps); owner.curInt->showInfoDialog(boost::to_string(txt), comps);
} }
} }
void BattleControlPanel::reallyFlee() void BattleControlPanel::reallyFlee()
{ {
owner->giveCommand(EActionType::RETREAT); owner.giveCommand(EActionType::RETREAT);
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0); CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
} }
void BattleControlPanel::reallySurrender() void BattleControlPanel::reallySurrender()
{ {
if (owner->curInt->cb->getResourceAmount(Res::GOLD) < owner->curInt->cb->battleGetSurrenderCost()) if (owner.curInt->cb->getResourceAmount(Res::GOLD) < owner.curInt->cb->battleGetSurrenderCost())
{ {
owner->curInt->showInfoDialog(CGI->generaltexth->allTexts[29]); //You don't have enough gold! owner.curInt->showInfoDialog(CGI->generaltexth->allTexts[29]); //You don't have enough gold!
} }
else else
{ {
owner->giveCommand(EActionType::SURRENDER); owner.giveCommand(EActionType::SURRENDER);
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0); CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
} }
} }
void BattleControlPanel::bAutofightf() void BattleControlPanel::bAutofightf()
{ {
if (owner->actionsController->spellcastingModeActive()) if (owner.actionsController->spellcastingModeActive())
return; return;
//Stop auto-fight mode //Stop auto-fight mode
if(owner->curInt->isAutoFightOn) if(owner.curInt->isAutoFightOn)
{ {
assert(owner->curInt->autofightingAI); assert(owner.curInt->autofightingAI);
owner->curInt->isAutoFightOn = false; owner.curInt->isAutoFightOn = false;
logGlobal->trace("Stopping the autofight..."); logGlobal->trace("Stopping the autofight...");
} }
else if(!owner->curInt->autofightingAI) else if(!owner.curInt->autofightingAI)
{ {
owner->curInt->isAutoFightOn = true; owner.curInt->isAutoFightOn = true;
blockUI(true); blockUI(true);
auto ai = CDynLibHandler::getNewBattleAI(settings["server"]["friendlyAI"].String()); auto ai = CDynLibHandler::getNewBattleAI(settings["server"]["friendlyAI"].String());
ai->init(owner->curInt->env, owner->curInt->cb); ai->init(owner.curInt->env, owner.curInt->cb);
ai->battleStart(owner->army1, owner->army2, int3(0,0,0), owner->attackingHeroInstance, owner->defendingHeroInstance, owner->curInt->cb->battleGetMySide()); ai->battleStart(owner.army1, owner.army2, int3(0,0,0), owner.attackingHeroInstance, owner.defendingHeroInstance, owner.curInt->cb->battleGetMySide());
owner->curInt->autofightingAI = ai; owner.curInt->autofightingAI = ai;
owner->curInt->cb->registerBattleInterface(ai); owner.curInt->cb->registerBattleInterface(ai);
owner->requestAutofightingAIToTakeAction(); owner.requestAutofightingAIToTakeAction();
} }
} }
void BattleControlPanel::bSpellf() void BattleControlPanel::bSpellf()
{ {
if (owner->actionsController->spellcastingModeActive()) if (owner.actionsController->spellcastingModeActive())
return; return;
if (!owner->myTurn) if (!owner.myTurn)
return; return;
auto myHero = owner->currentHero(); auto myHero = owner.currentHero();
if(!myHero) if(!myHero)
return; return;
CCS->curh->changeGraphic(ECursor::ADVENTURE,0); CCS->curh->changeGraphic(ECursor::ADVENTURE,0);
ESpellCastProblem::ESpellCastProblem spellCastProblem = owner->curInt->cb->battleCanCastSpell(myHero, spells::Mode::HERO); ESpellCastProblem::ESpellCastProblem spellCastProblem = owner.curInt->cb->battleCanCastSpell(myHero, spells::Mode::HERO);
if(spellCastProblem == ESpellCastProblem::OK) if(spellCastProblem == ESpellCastProblem::OK)
{ {
GH.pushIntT<CSpellWindow>(myHero, owner->curInt.get()); GH.pushIntT<CSpellWindow>(myHero, owner.curInt.get());
} }
else if (spellCastProblem == ESpellCastProblem::MAGIC_IS_BLOCKED) else if (spellCastProblem == ESpellCastProblem::MAGIC_IS_BLOCKED)
{ {
//TODO: move to spell mechanics, add more information to spell cast problem //TODO: move to spell mechanics, add more information to spell cast problem
//Handle Orb of Inhibition-like effects -> we want to display dialog with info, why casting is impossible //Handle Orb of Inhibition-like effects -> we want to display dialog with info, why casting is impossible
auto blockingBonus = owner->currentHero()->getBonusLocalFirst(Selector::type()(Bonus::BLOCK_ALL_MAGIC)); auto blockingBonus = owner.currentHero()->getBonusLocalFirst(Selector::type()(Bonus::BLOCK_ALL_MAGIC));
if (!blockingBonus) if (!blockingBonus)
return; return;
@ -234,7 +234,7 @@ void BattleControlPanel::bSpellf()
const auto artID = ArtifactID(blockingBonus->sid); const auto artID = ArtifactID(blockingBonus->sid);
//If we have artifact, put name of our hero. Otherwise assume it's the enemy. //If we have artifact, put name of our hero. Otherwise assume it's the enemy.
//TODO check who *really* is source of bonus //TODO check who *really* is source of bonus
std::string heroName = myHero->hasArt(artID) ? myHero->name : owner->enemyHero().name; std::string heroName = myHero->hasArt(artID) ? myHero->name : owner.enemyHero().name;
//%s wields the %s, an ancient artifact which creates a p dead to all magic. //%s wields the %s, an ancient artifact which creates a p dead to all magic.
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[683]) LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[683])
@ -245,25 +245,25 @@ void BattleControlPanel::bSpellf()
void BattleControlPanel::bWaitf() void BattleControlPanel::bWaitf()
{ {
if (owner->actionsController->spellcastingModeActive()) if (owner.actionsController->spellcastingModeActive())
return; return;
if (owner->stacksController->getActiveStack() != nullptr) if (owner.stacksController->getActiveStack() != nullptr)
owner->giveCommand(EActionType::WAIT); owner.giveCommand(EActionType::WAIT);
} }
void BattleControlPanel::bDefencef() void BattleControlPanel::bDefencef()
{ {
if (owner->actionsController->spellcastingModeActive()) if (owner.actionsController->spellcastingModeActive())
return; return;
if (owner->stacksController->getActiveStack() != nullptr) if (owner.stacksController->getActiveStack() != nullptr)
owner->giveCommand(EActionType::DEFEND); owner.giveCommand(EActionType::DEFEND);
} }
void BattleControlPanel::bConsoleUpf() void BattleControlPanel::bConsoleUpf()
{ {
if (owner->actionsController->spellcastingModeActive()) if (owner.actionsController->spellcastingModeActive())
return; return;
console->scrollUp(); console->scrollUp();
@ -271,7 +271,7 @@ void BattleControlPanel::bConsoleUpf()
void BattleControlPanel::bConsoleDownf() void BattleControlPanel::bConsoleDownf()
{ {
if (owner->actionsController->spellcastingModeActive()) if (owner.actionsController->spellcastingModeActive())
return; return;
console->scrollDown(); console->scrollDown();
@ -279,38 +279,38 @@ void BattleControlPanel::bConsoleDownf()
void BattleControlPanel::bTacticNextStack() void BattleControlPanel::bTacticNextStack()
{ {
owner->tacticNextStack(nullptr); owner.tacticNextStack(nullptr);
} }
void BattleControlPanel::bTacticPhaseEnd() void BattleControlPanel::bTacticPhaseEnd()
{ {
owner->tacticPhaseEnd(); owner.tacticPhaseEnd();
} }
void BattleControlPanel::blockUI(bool on) void BattleControlPanel::blockUI(bool on)
{ {
bool canCastSpells = false; bool canCastSpells = false;
auto hero = owner->curInt->cb->battleGetMyHero(); auto hero = owner.curInt->cb->battleGetMyHero();
if(hero) if(hero)
{ {
ESpellCastProblem::ESpellCastProblem spellcastingProblem = owner->curInt->cb->battleCanCastSpell(hero, spells::Mode::HERO); ESpellCastProblem::ESpellCastProblem spellcastingProblem = owner.curInt->cb->battleCanCastSpell(hero, spells::Mode::HERO);
//if magic is blocked, we leave button active, so the message can be displayed after button click //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; canCastSpells = spellcastingProblem == ESpellCastProblem::OK || spellcastingProblem == ESpellCastProblem::MAGIC_IS_BLOCKED;
} }
bool canWait = owner->stacksController->getActiveStack() ? !owner->stacksController->getActiveStack()->waitedThisTurn : false; bool canWait = owner.stacksController->getActiveStack() ? !owner.stacksController->getActiveStack()->waitedThisTurn : false;
bOptions->block(on); bOptions->block(on);
bFlee->block(on || !owner->curInt->cb->battleCanFlee()); bFlee->block(on || !owner.curInt->cb->battleCanFlee());
bSurrender->block(on || owner->curInt->cb->battleGetSurrenderCost() < 0); bSurrender->block(on || owner.curInt->cb->battleGetSurrenderCost() < 0);
// block only if during enemy turn and auto-fight is off // block only if during enemy turn and auto-fight is off
// otherwise - crash on accessing non-exisiting active stack // otherwise - crash on accessing non-exisiting active stack
bAutofight->block(!owner->curInt->isAutoFightOn && !owner->stacksController->getActiveStack()); bAutofight->block(!owner.curInt->isAutoFightOn && !owner.stacksController->getActiveStack());
if (owner->tacticsMode && btactEnd && btactNext) if (owner.tacticsMode && btactEnd && btactNext)
{ {
btactNext->block(on); btactNext->block(on);
btactEnd->block(on); btactEnd->block(on);
@ -322,7 +322,7 @@ void BattleControlPanel::blockUI(bool on)
} }
bSpell->block(on || owner->tacticsMode || !canCastSpells); bSpell->block(on || owner.tacticsMode || !canCastSpells);
bWait->block(on || owner->tacticsMode || !canWait); bWait->block(on || owner.tacticsMode || !canWait);
bDefence->block(on || owner->tacticsMode); bDefence->block(on || owner.tacticsMode);
} }

View File

@ -23,7 +23,7 @@ class BattleConsole;
/// GUI object that handles functionality of panel at the bottom of combat screen /// GUI object that handles functionality of panel at the bottom of combat screen
class BattleControlPanel : public CIntObject class BattleControlPanel : public CIntObject
{ {
BattleInterface * owner; BattleInterface & owner;
std::shared_ptr<CPicture> menu; std::shared_ptr<CPicture> menu;
@ -71,6 +71,6 @@ public:
/// Toggle UI to displaying battle log in place of tactics UI /// Toggle UI to displaying battle log in place of tactics UI
void tacticPhaseEnded(); void tacticPhaseEnded();
BattleControlPanel(BattleInterface * owner, const Point & position); BattleControlPanel(BattleInterface & owner, const Point & position);
}; };

View File

@ -31,7 +31,7 @@
#include "../../lib/IGameEventsReceiver.h" #include "../../lib/IGameEventsReceiver.h"
#include "../../lib/CGeneralTextHandler.h" #include "../../lib/CGeneralTextHandler.h"
BattleEffectsController::BattleEffectsController(BattleInterface * owner): BattleEffectsController::BattleEffectsController(BattleInterface & owner):
owner(owner) owner(owner)
{} {}
@ -44,14 +44,14 @@ void BattleEffectsController::displayEffect(EBattleEffect::EBattleEffect effect,
{ {
std::string customAnim = graphics->battleACToDef[effect][0]; std::string customAnim = graphics->battleACToDef[effect][0];
owner->stacksController->addNewAnim(new CPointEffectAnimation(owner, soundBase::soundID(soundID), customAnim, destTile)); owner.stacksController->addNewAnim(new CPointEffectAnimation(owner, soundBase::soundID(soundID), customAnim, destTile));
} }
void BattleEffectsController::displayCustomEffects(const std::vector<CustomEffectInfo> & customEffects) void BattleEffectsController::displayCustomEffects(const std::vector<CustomEffectInfo> & customEffects)
{ {
for(const CustomEffectInfo & one : customEffects) for(const CustomEffectInfo & one : customEffects)
{ {
const CStack * s = owner->curInt->cb->battleGetStackByID(one.stack, false); const CStack * s = owner.curInt->cb->battleGetStackByID(one.stack, false);
assert(s); assert(s);
assert(one.effect != 0); assert(one.effect != 0);
@ -62,7 +62,7 @@ void BattleEffectsController::displayCustomEffects(const std::vector<CustomEffec
void BattleEffectsController::battleTriggerEffect(const BattleTriggerEffect & bte) void BattleEffectsController::battleTriggerEffect(const BattleTriggerEffect & bte)
{ {
const CStack * stack = owner->curInt->cb->battleGetStackByID(bte.stackID); const CStack * stack = owner.curInt->cb->battleGetStackByID(bte.stackID);
if(!stack) if(!stack)
{ {
logGlobal->error("Invalid stack ID %d", bte.stackID); logGlobal->error("Invalid stack ID %d", bte.stackID);
@ -89,7 +89,7 @@ void BattleEffectsController::battleTriggerEffect(const BattleTriggerEffect & bt
std::string hlp = CGI->generaltexth->allTexts[33]; std::string hlp = CGI->generaltexth->allTexts[33];
boost::algorithm::replace_first(hlp,"%s",(stack->getName())); boost::algorithm::replace_first(hlp,"%s",(stack->getName()));
displayEffect(EBattleEffect::GOOD_MORALE, soundBase::GOODMRLE, stack->getPosition()); displayEffect(EBattleEffect::GOOD_MORALE, soundBase::GOODMRLE, stack->getPosition());
owner->controlPanel->console->addText(hlp); owner.controlPanel->console->addText(hlp);
break; break;
} }
default: default:
@ -100,21 +100,21 @@ void BattleEffectsController::battleTriggerEffect(const BattleTriggerEffect & bt
void BattleEffectsController::startAction(const BattleAction* action) void BattleEffectsController::startAction(const BattleAction* action)
{ {
const CStack *stack = owner->curInt->cb->battleGetStackByID(action->stackNumber); const CStack *stack = owner.curInt->cb->battleGetStackByID(action->stackNumber);
switch(action->actionType) switch(action->actionType)
{ {
case EActionType::WAIT: case EActionType::WAIT:
owner->controlPanel->console->addText(stack->formatGeneralMessage(136)); owner.controlPanel->console->addText(stack->formatGeneralMessage(136));
break; break;
case EActionType::BAD_MORALE: case EActionType::BAD_MORALE:
owner->controlPanel->console->addText(stack->formatGeneralMessage(-34)); owner.controlPanel->console->addText(stack->formatGeneralMessage(-34));
displayEffect(EBattleEffect::BAD_MORALE, soundBase::BADMRLE, stack->getPosition()); displayEffect(EBattleEffect::BAD_MORALE, soundBase::BADMRLE, stack->getPosition());
break; break;
} }
//displaying special abilities //displaying special abilities
auto actionTarget = action->getTarget(owner->curInt->cb.get()); auto actionTarget = action->getTarget(owner.curInt->cb.get());
switch(action->actionType) switch(action->actionType)
{ {
case EActionType::STACK_HEAL: case EActionType::STACK_HEAL:

View File

@ -59,13 +59,13 @@ struct BattleEffect
/// Controls rendering of effects in battle, e.g. from spells, abilities and various other actions like morale /// Controls rendering of effects in battle, e.g. from spells, abilities and various other actions like morale
class BattleEffectsController class BattleEffectsController
{ {
BattleInterface * owner; BattleInterface & owner;
/// list of current effects that are being displayed on screen (spells & creature abilities) /// list of current effects that are being displayed on screen (spells & creature abilities)
std::vector<BattleEffect> battleEffects; std::vector<BattleEffect> battleEffects;
public: public:
BattleEffectsController(BattleInterface * owner); BattleEffectsController(BattleInterface & owner);
void startAction(const BattleAction* action); void startAction(const BattleAction* action);

View File

@ -33,21 +33,21 @@
#include "../../lib/CStack.h" #include "../../lib/CStack.h"
#include "../../lib/spells/ISpellMechanics.h" #include "../../lib/spells/ISpellMechanics.h"
BattleFieldController::BattleFieldController(BattleInterface * owner): BattleFieldController::BattleFieldController(BattleInterface & owner):
owner(owner), owner(owner),
attackingHex(BattleHex::INVALID) attackingHex(BattleHex::INVALID)
{ {
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
pos.w = owner->pos.w; pos.w = owner.pos.w;
pos.h = owner->pos.h; pos.h = owner.pos.h;
//preparing cells and hexes //preparing cells and hexes
cellBorder = IImage::createFromFile("CCELLGRD.BMP"); cellBorder = IImage::createFromFile("CCELLGRD.BMP");
cellShade = IImage::createFromFile("CCELLSHD.BMP"); cellShade = IImage::createFromFile("CCELLSHD.BMP");
if(!owner->siegeController) if(!owner.siegeController)
{ {
auto bfieldType = owner->curInt->cb->battleGetBattlefieldType(); auto bfieldType = owner.curInt->cb->battleGetBattlefieldType();
if(bfieldType == BattleField::NONE) if(bfieldType == BattleField::NONE)
logGlobal->error("Invalid battlefield returned for current battle"); logGlobal->error("Invalid battlefield returned for current battle");
@ -56,7 +56,7 @@ BattleFieldController::BattleFieldController(BattleInterface * owner):
} }
else else
{ {
std::string backgroundName = owner->siegeController->getBattleBackgroundName(); std::string backgroundName = owner.siegeController->getBattleBackgroundName();
background = IImage::createFromFile(backgroundName); background = IImage::createFromFile(backgroundName);
} }
@ -80,11 +80,11 @@ BattleFieldController::BattleFieldController(BattleInterface * owner):
auto hex = std::make_shared<ClickableHex>(); auto hex = std::make_shared<ClickableHex>();
hex->myNumber = h; hex->myNumber = h;
hex->pos = hexPositionAbsolute(h); hex->pos = hexPositionAbsolute(h);
hex->myInterface = owner; hex->myInterface = &owner;
bfield.push_back(hex); bfield.push_back(hex);
} }
auto accessibility = owner->curInt->cb->getAccesibility(); auto accessibility = owner.curInt->cb->getAccesibility();
for(int i = 0; i < accessibility.size(); i++) for(int i = 0; i < accessibility.size(); i++)
stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE); stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE);
} }
@ -97,12 +97,12 @@ void BattleFieldController::renderBattlefield(Canvas & canvas)
renderer.execute(canvas); renderer.execute(canvas);
owner->projectilesController->showProjectiles(canvas); owner.projectilesController->showProjectiles(canvas);
} }
void BattleFieldController::showBackground(Canvas & canvas) void BattleFieldController::showBackground(Canvas & canvas)
{ {
if (owner->stacksController->getActiveStack() != nullptr ) //&& creAnims[stacksController->getActiveStack()->ID]->isIdle() //show everything with range if (owner.stacksController->getActiveStack() != nullptr ) //&& creAnims[stacksController->getActiveStack()->ID]->isIdle() //show everything with range
showBackgroundImageWithHexes(canvas); showBackgroundImageWithHexes(canvas);
else else
showBackgroundImage(canvas); showBackgroundImage(canvas);
@ -113,38 +113,38 @@ void BattleFieldController::showBackground(Canvas & canvas)
void BattleFieldController::showBackgroundImage(Canvas & canvas) void BattleFieldController::showBackgroundImage(Canvas & canvas)
{ {
canvas.draw(background, owner->pos.topLeft()); canvas.draw(background, owner.pos.topLeft());
owner->obstacleController->showAbsoluteObstacles(canvas, pos.topLeft()); owner.obstacleController->showAbsoluteObstacles(canvas, pos.topLeft());
if ( owner->siegeController ) if ( owner.siegeController )
owner->siegeController->showAbsoluteObstacles(canvas, pos.topLeft()); owner.siegeController->showAbsoluteObstacles(canvas, pos.topLeft());
if (settings["battle"]["cellBorders"].Bool()) if (settings["battle"]["cellBorders"].Bool())
canvas.draw(*cellBorders, owner->pos.topLeft()); canvas.draw(*cellBorders, owner.pos.topLeft());
} }
void BattleFieldController::showBackgroundImageWithHexes(Canvas & canvas) void BattleFieldController::showBackgroundImageWithHexes(Canvas & canvas)
{ {
canvas.draw(*backgroundWithHexes.get(), owner->pos.topLeft()); canvas.draw(*backgroundWithHexes.get(), owner.pos.topLeft());
} }
void BattleFieldController::redrawBackgroundWithHexes() void BattleFieldController::redrawBackgroundWithHexes()
{ {
const CStack *activeStack = owner->stacksController->getActiveStack(); const CStack *activeStack = owner.stacksController->getActiveStack();
std::vector<BattleHex> attackableHexes; std::vector<BattleHex> attackableHexes;
if (activeStack) if (activeStack)
occupyableHexes = owner->curInt->cb->battleGetAvailableHexes(activeStack, true, &attackableHexes); occupyableHexes = owner.curInt->cb->battleGetAvailableHexes(activeStack, true, &attackableHexes);
auto accessibility = owner->curInt->cb->getAccesibility(); auto accessibility = owner.curInt->cb->getAccesibility();
for(int i = 0; i < accessibility.size(); i++) for(int i = 0; i < accessibility.size(); i++)
stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE); stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE);
//prepare background graphic with hexes and shaded hexes //prepare background graphic with hexes and shaded hexes
backgroundWithHexes->draw(background, Point(0,0)); backgroundWithHexes->draw(background, Point(0,0));
owner->obstacleController->showAbsoluteObstacles(*backgroundWithHexes, Point(0,0)); owner.obstacleController->showAbsoluteObstacles(*backgroundWithHexes, Point(0,0));
if ( owner->siegeController ) if ( owner.siegeController )
owner->siegeController->showAbsoluteObstacles(*backgroundWithHexes, Point(0,0)); owner.siegeController->showAbsoluteObstacles(*backgroundWithHexes, Point(0,0));
if (settings["battle"]["stackRange"].Bool()) if (settings["battle"]["stackRange"].Bool())
{ {
@ -173,7 +173,7 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesStackRange()
{ {
std::set<BattleHex> result; std::set<BattleHex> result;
if ( !owner->stacksController->getActiveStack()) if ( !owner.stacksController->getActiveStack())
return result; return result;
if ( !settings["battle"]["stackRange"].Bool()) if ( !settings["battle"]["stackRange"].Bool())
@ -181,15 +181,15 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesStackRange()
auto hoveredHex = getHoveredHex(); auto hoveredHex = getHoveredHex();
std::set<BattleHex> set = owner->curInt->cb->battleGetAttackedHexes(owner->stacksController->getActiveStack(), hoveredHex, attackingHex); std::set<BattleHex> set = owner.curInt->cb->battleGetAttackedHexes(owner.stacksController->getActiveStack(), hoveredHex, attackingHex);
for(BattleHex hex : set) for(BattleHex hex : set)
result.insert(hex); result.insert(hex);
// display the movement shadow of the stack at b (i.e. stack under mouse) // display the movement shadow of the stack at b (i.e. stack under mouse)
const CStack * const shere = owner->curInt->cb->battleGetStackByPos(hoveredHex, false); const CStack * const shere = owner.curInt->cb->battleGetStackByPos(hoveredHex, false);
if(shere && shere != owner->stacksController->getActiveStack() && shere->alive()) if(shere && shere != owner.stacksController->getActiveStack() && shere->alive())
{ {
std::vector<BattleHex> v = owner->curInt->cb->battleGetAvailableHexes(shere, true, nullptr); std::vector<BattleHex> v = owner.curInt->cb->battleGetAvailableHexes(shere, true, nullptr);
for(BattleHex hex : v) for(BattleHex hex : v)
result.insert(hex); result.insert(hex);
} }
@ -209,22 +209,22 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesSpellRange()
spells::Mode mode = spells::Mode::HERO; spells::Mode mode = spells::Mode::HERO;
if(owner->actionsController->spellcastingModeActive())//hero casts spell if(owner.actionsController->spellcastingModeActive())//hero casts spell
{ {
spell = owner->actionsController->selectedSpell().toSpell(); spell = owner.actionsController->selectedSpell().toSpell();
caster = owner->getActiveHero(); caster = owner.getActiveHero();
} }
else if(owner->stacksController->activeStackSpellToCast() != SpellID::NONE)//stack casts spell else if(owner.stacksController->activeStackSpellToCast() != SpellID::NONE)//stack casts spell
{ {
spell = SpellID(owner->stacksController->activeStackSpellToCast()).toSpell(); spell = SpellID(owner.stacksController->activeStackSpellToCast()).toSpell();
caster = owner->stacksController->getActiveStack(); caster = owner.stacksController->getActiveStack();
mode = spells::Mode::CREATURE_ACTIVE; mode = spells::Mode::CREATURE_ACTIVE;
} }
if(caster && spell) //when casting spell if(caster && spell) //when casting spell
{ {
// printing shaded hex(es) // printing shaded hex(es)
spells::BattleCast event(owner->curInt->cb.get(), caster, mode, spell); spells::BattleCast event(owner.curInt->cb.get(), caster, mode, spell);
auto shaded = spell->battleMechanics(&event)->rangeInHexes(hoveredHex); auto shaded = spell->battleMechanics(&event)->rangeInHexes(hoveredHex);
for(BattleHex shadedHex : shaded) for(BattleHex shadedHex : shaded)
@ -233,7 +233,7 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesSpellRange()
result.insert(shadedHex); result.insert(shadedHex);
} }
} }
else if(owner->active) //always highlight pointed hex else if(owner.active) //always highlight pointed hex
{ {
if(hoveredHex.getX() != 0 && hoveredHex.getX() != GameConstants::BFIELD_WIDTH - 1) if(hoveredHex.getX() != 0 && hoveredHex.getX() != GameConstants::BFIELD_WIDTH - 1)
result.insert(hoveredHex); result.insert(hoveredHex);
@ -280,7 +280,7 @@ Rect BattleFieldController::hexPositionLocal(BattleHex hex) const
Rect BattleFieldController::hexPositionAbsolute(BattleHex hex) const Rect BattleFieldController::hexPositionAbsolute(BattleHex hex) const
{ {
return hexPositionLocal(hex) + owner->pos.topLeft(); return hexPositionLocal(hex) + owner.pos.topLeft();
} }
bool BattleFieldController::isPixelInHex(Point const & position) bool BattleFieldController::isPixelInHex(Point const & position)
@ -317,7 +317,7 @@ void BattleFieldController::setBattleCursor(BattleHex myNumber)
sectorCursor.push_back(12); sectorCursor.push_back(12);
sectorCursor.push_back(7); sectorCursor.push_back(7);
const bool doubleWide = owner->stacksController->getActiveStack()->doubleWide(); const bool doubleWide = owner.stacksController->getActiveStack()->doubleWide();
bool aboveAttackable = true, belowAttackable = true; bool aboveAttackable = true, belowAttackable = true;
// Exclude directions which cannot be attacked from. // Exclude directions which cannot be attacked from.
@ -478,12 +478,12 @@ BattleHex BattleFieldController::fromWhichHexAttack(BattleHex myNumber)
{ {
case 12: //from bottom right case 12: //from bottom right
{ {
bool doubleWide = owner->stacksController->getActiveStack()->doubleWide(); bool doubleWide = owner.stacksController->getActiveStack()->doubleWide();
destHex = myNumber + ( (myNumber/GameConstants::BFIELD_WIDTH)%2 ? GameConstants::BFIELD_WIDTH : GameConstants::BFIELD_WIDTH+1 ) + destHex = myNumber + ( (myNumber/GameConstants::BFIELD_WIDTH)%2 ? GameConstants::BFIELD_WIDTH : GameConstants::BFIELD_WIDTH+1 ) +
(owner->stacksController->getActiveStack()->side == BattleSide::ATTACKER && doubleWide ? 1 : 0); (owner.stacksController->getActiveStack()->side == BattleSide::ATTACKER && doubleWide ? 1 : 0);
if(vstd::contains(occupyableHexes, destHex)) if(vstd::contains(occupyableHexes, destHex))
return destHex; return destHex;
else if(owner->stacksController->getActiveStack()->side == BattleSide::ATTACKER) else if(owner.stacksController->getActiveStack()->side == BattleSide::ATTACKER)
{ {
if (vstd::contains(occupyableHexes, destHex+1)) if (vstd::contains(occupyableHexes, destHex+1))
return destHex+1; return destHex+1;
@ -500,7 +500,7 @@ BattleHex BattleFieldController::fromWhichHexAttack(BattleHex myNumber)
destHex = myNumber + ( (myNumber/GameConstants::BFIELD_WIDTH)%2 ? GameConstants::BFIELD_WIDTH-1 : GameConstants::BFIELD_WIDTH ); destHex = myNumber + ( (myNumber/GameConstants::BFIELD_WIDTH)%2 ? GameConstants::BFIELD_WIDTH-1 : GameConstants::BFIELD_WIDTH );
if (vstd::contains(occupyableHexes, destHex)) if (vstd::contains(occupyableHexes, destHex))
return destHex; return destHex;
else if(owner->stacksController->getActiveStack()->side == BattleSide::ATTACKER) else if(owner.stacksController->getActiveStack()->side == BattleSide::ATTACKER)
{ {
if(vstd::contains(occupyableHexes, destHex+1)) if(vstd::contains(occupyableHexes, destHex+1))
return destHex+1; return destHex+1;
@ -514,9 +514,9 @@ BattleHex BattleFieldController::fromWhichHexAttack(BattleHex myNumber)
} }
case 8: //from left case 8: //from left
{ {
if(owner->stacksController->getActiveStack()->doubleWide() && owner->stacksController->getActiveStack()->side == BattleSide::DEFENDER) if(owner.stacksController->getActiveStack()->doubleWide() && owner.stacksController->getActiveStack()->side == BattleSide::DEFENDER)
{ {
std::vector<BattleHex> acc = owner->curInt->cb->battleGetAvailableHexes(owner->stacksController->getActiveStack()); std::vector<BattleHex> acc = owner.curInt->cb->battleGetAvailableHexes(owner.stacksController->getActiveStack());
if (vstd::contains(acc, myNumber)) if (vstd::contains(acc, myNumber))
return myNumber - 1; return myNumber - 1;
else else
@ -533,7 +533,7 @@ BattleHex BattleFieldController::fromWhichHexAttack(BattleHex myNumber)
destHex = myNumber - ((myNumber/GameConstants::BFIELD_WIDTH) % 2 ? GameConstants::BFIELD_WIDTH + 1 : GameConstants::BFIELD_WIDTH); destHex = myNumber - ((myNumber/GameConstants::BFIELD_WIDTH) % 2 ? GameConstants::BFIELD_WIDTH + 1 : GameConstants::BFIELD_WIDTH);
if(vstd::contains(occupyableHexes, destHex)) if(vstd::contains(occupyableHexes, destHex))
return destHex; return destHex;
else if(owner->stacksController->getActiveStack()->side == BattleSide::ATTACKER) else if(owner.stacksController->getActiveStack()->side == BattleSide::ATTACKER)
{ {
if(vstd::contains(occupyableHexes, destHex+1)) if(vstd::contains(occupyableHexes, destHex+1))
return destHex+1; return destHex+1;
@ -547,12 +547,12 @@ BattleHex BattleFieldController::fromWhichHexAttack(BattleHex myNumber)
} }
case 10: //from top right case 10: //from top right
{ {
bool doubleWide = owner->stacksController->getActiveStack()->doubleWide(); bool doubleWide = owner.stacksController->getActiveStack()->doubleWide();
destHex = myNumber - ( (myNumber/GameConstants::BFIELD_WIDTH)%2 ? GameConstants::BFIELD_WIDTH : GameConstants::BFIELD_WIDTH-1 ) + destHex = myNumber - ( (myNumber/GameConstants::BFIELD_WIDTH)%2 ? GameConstants::BFIELD_WIDTH : GameConstants::BFIELD_WIDTH-1 ) +
(owner->stacksController->getActiveStack()->side == BattleSide::ATTACKER && doubleWide ? 1 : 0); (owner.stacksController->getActiveStack()->side == BattleSide::ATTACKER && doubleWide ? 1 : 0);
if(vstd::contains(occupyableHexes, destHex)) if(vstd::contains(occupyableHexes, destHex))
return destHex; return destHex;
else if(owner->stacksController->getActiveStack()->side == BattleSide::ATTACKER) else if(owner.stacksController->getActiveStack()->side == BattleSide::ATTACKER)
{ {
if(vstd::contains(occupyableHexes, destHex+1)) if(vstd::contains(occupyableHexes, destHex+1))
return destHex+1; return destHex+1;
@ -566,9 +566,9 @@ BattleHex BattleFieldController::fromWhichHexAttack(BattleHex myNumber)
} }
case 11: //from right case 11: //from right
{ {
if(owner->stacksController->getActiveStack()->doubleWide() && owner->stacksController->getActiveStack()->side == BattleSide::ATTACKER) if(owner.stacksController->getActiveStack()->doubleWide() && owner.stacksController->getActiveStack()->side == BattleSide::ATTACKER)
{ {
std::vector<BattleHex> acc = owner->curInt->cb->battleGetAvailableHexes(owner->stacksController->getActiveStack()); std::vector<BattleHex> acc = owner.curInt->cb->battleGetAvailableHexes(owner.stacksController->getActiveStack());
if(vstd::contains(acc, myNumber)) if(vstd::contains(acc, myNumber))
return myNumber + 1; return myNumber + 1;
else else
@ -585,7 +585,7 @@ BattleHex BattleFieldController::fromWhichHexAttack(BattleHex myNumber)
destHex = myNumber + ( (myNumber/GameConstants::BFIELD_WIDTH)%2 ? GameConstants::BFIELD_WIDTH : GameConstants::BFIELD_WIDTH+1 ); destHex = myNumber + ( (myNumber/GameConstants::BFIELD_WIDTH)%2 ? GameConstants::BFIELD_WIDTH : GameConstants::BFIELD_WIDTH+1 );
if(vstd::contains(occupyableHexes, destHex)) if(vstd::contains(occupyableHexes, destHex))
return destHex; return destHex;
else if(owner->stacksController->getActiveStack()->side == BattleSide::ATTACKER) else if(owner.stacksController->getActiveStack()->side == BattleSide::ATTACKER)
{ {
if(vstd::contains(occupyableHexes, destHex+1)) if(vstd::contains(occupyableHexes, destHex+1))
return destHex+1; return destHex+1;
@ -602,7 +602,7 @@ BattleHex BattleFieldController::fromWhichHexAttack(BattleHex myNumber)
destHex = myNumber - ( (myNumber/GameConstants::BFIELD_WIDTH)%2 ? GameConstants::BFIELD_WIDTH : GameConstants::BFIELD_WIDTH-1 ); destHex = myNumber - ( (myNumber/GameConstants::BFIELD_WIDTH)%2 ? GameConstants::BFIELD_WIDTH : GameConstants::BFIELD_WIDTH-1 );
if (vstd::contains(occupyableHexes, destHex)) if (vstd::contains(occupyableHexes, destHex))
return destHex; return destHex;
else if(owner->stacksController->getActiveStack()->side == BattleSide::ATTACKER) else if(owner.stacksController->getActiveStack()->side == BattleSide::ATTACKER)
{ {
if(vstd::contains(occupyableHexes, destHex+1)) if(vstd::contains(occupyableHexes, destHex+1))
return destHex+1; return destHex+1;

View File

@ -29,7 +29,7 @@ class BattleInterface;
/// Handles battlefield grid as well as rendering of background layer of battle interface /// Handles battlefield grid as well as rendering of background layer of battle interface
class BattleFieldController : public CIntObject class BattleFieldController : public CIntObject
{ {
BattleInterface * owner; BattleInterface & owner;
std::shared_ptr<IImage> background; std::shared_ptr<IImage> background;
std::shared_ptr<IImage> cellBorder; std::shared_ptr<IImage> cellBorder;
@ -63,7 +63,7 @@ class BattleFieldController : public CIntObject
void showHighlightedHexes(Canvas & canvas); void showHighlightedHexes(Canvas & canvas);
public: public:
BattleFieldController(BattleInterface * owner); BattleFieldController(BattleInterface & owner);
void redrawBackgroundWithHexes(); void redrawBackgroundWithHexes();
void renderBattlefield(Canvas & canvas); void renderBattlefield(Canvas & canvas);

View File

@ -55,8 +55,6 @@ BattleInterface::BattleInterface(const CCreatureSet *army1, const CCreatureSet *
{ {
OBJ_CONSTRUCTION; OBJ_CONSTRUCTION;
projectilesController.reset(new BattleProjectileController(this));
if(spectatorInt) if(spectatorInt)
{ {
curInt = spectatorInt; curInt = spectatorInt;
@ -90,7 +88,7 @@ BattleInterface::BattleInterface(const CCreatureSet *army1, const CCreatureSet *
else else
embedQueue = screen->h < 700 || queueSize == "small"; embedQueue = screen->h < 700 || queueSize == "small";
queue = std::make_shared<StackQueue>(embedQueue, this); queue = std::make_shared<StackQueue>(embedQueue, *this);
if(!embedQueue) if(!embedQueue)
{ {
if (settings["battle"]["showQueue"].Bool()) if (settings["battle"]["showQueue"].Bool())
@ -99,10 +97,6 @@ BattleInterface::BattleInterface(const CCreatureSet *army1, const CCreatureSet *
queue->moveTo(Point(pos.x, pos.y - queue->pos.h)); queue->moveTo(Point(pos.x, pos.y - queue->pos.h));
} }
//preparing siege info
const CGTownInstance *town = curInt->cb->battleGetDefendedTown();
if(town && town->hasFort())
siegeController.reset(new BattleSiegeController(this, town));
CPlayerInterface::battleInt = this; CPlayerInterface::battleInt = this;
@ -110,13 +104,16 @@ BattleInterface::BattleInterface(const CCreatureSet *army1, const CCreatureSet *
this->army1 = army1; this->army1 = army1;
this->army2 = army2; this->army2 = army2;
controlPanel = std::make_shared<BattleControlPanel>(this, Point(0, 556)); const CGTownInstance *town = curInt->cb->battleGetDefendedTown();
if(town && town->hasFort())
siegeController.reset(new BattleSiegeController(*this, town));
//preparing menu background and terrain controlPanel = std::make_shared<BattleControlPanel>(*this, Point(0, 556));
fieldController.reset( new BattleFieldController(this)); projectilesController.reset(new BattleProjectileController(*this));
stacksController.reset( new BattleStacksController(this)); fieldController.reset( new BattleFieldController(*this));
actionsController.reset( new BattleActionsController(this)); stacksController.reset( new BattleStacksController(*this));
effectsController.reset(new BattleEffectsController(this)); actionsController.reset( new BattleActionsController(*this));
effectsController.reset(new BattleEffectsController(*this));
//loading hero animations //loading hero animations
if(hero1) // attacking hero if(hero1) // attacking hero
@ -134,7 +131,7 @@ BattleInterface::BattleInterface(const CCreatureSet *army1, const CCreatureSet *
battleImage = hero1->type->heroClass->imageBattleMale; battleImage = hero1->type->heroClass->imageBattleMale;
} }
attackingHero = std::make_shared<BattleHero>(battleImage, false, hero1->tempOwner, hero1->tempOwner == curInt->playerID ? hero1 : nullptr, this); attackingHero = std::make_shared<BattleHero>(battleImage, false, hero1->tempOwner, hero1->tempOwner == curInt->playerID ? hero1 : nullptr, *this);
auto img = attackingHero->animation->getImage(0, 0, true); auto img = attackingHero->animation->getImage(0, 0, true);
if(img) if(img)
@ -158,14 +155,14 @@ BattleInterface::BattleInterface(const CCreatureSet *army1, const CCreatureSet *
battleImage = hero2->type->heroClass->imageBattleMale; battleImage = hero2->type->heroClass->imageBattleMale;
} }
defendingHero = std::make_shared<BattleHero>(battleImage, true, hero2->tempOwner, hero2->tempOwner == curInt->playerID ? hero2 : nullptr, this); defendingHero = std::make_shared<BattleHero>(battleImage, true, hero2->tempOwner, hero2->tempOwner == curInt->playerID ? hero2 : nullptr, *this);
auto img = defendingHero->animation->getImage(0, 0, true); auto img = defendingHero->animation->getImage(0, 0, true);
if(img) if(img)
defendingHero->pos = genRect(img->height(), img->width(), pos.x + 693, pos.y - 19); defendingHero->pos = genRect(img->height(), img->width(), pos.x + 693, pos.y - 19);
} }
obstacleController.reset(new BattleObstacleController(this)); obstacleController.reset(new BattleObstacleController(*this));
if(tacticsMode) if(tacticsMode)
tacticNextStack(nullptr); tacticNextStack(nullptr);
@ -502,7 +499,7 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
{ {
displaySpellCast(spellID, casterStack->getPosition()); displaySpellCast(spellID, casterStack->getPosition());
stacksController->addNewAnim(new CCastAnimation(this, casterStack, sc->tile, curInt->cb->battleGetStackByPos(sc->tile), spell)); stacksController->addNewAnim(new CCastAnimation(*this, casterStack, sc->tile, curInt->cb->battleGetStackByPos(sc->tile), spell));
} }
else else
if (sc->tile.isValid() && !spell->animationInfo.projectile.empty()) if (sc->tile.isValid() && !spell->animationInfo.projectile.empty())
@ -518,7 +515,7 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
projectilesController->emitStackProjectile( nullptr ); projectilesController->emitStackProjectile( nullptr );
// wait fo projectile to end // wait fo projectile to end
stacksController->addNewAnim(new CWaitingProjectileAnimation(this, nullptr)); stacksController->addNewAnim(new CWaitingProjectileAnimation(*this, nullptr));
} }
} }
@ -548,8 +545,8 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
{ {
Point leftHero = Point(15, 30) + pos; Point leftHero = Point(15, 30) + pos;
Point rightHero = Point(755, 30) + pos; Point rightHero = Point(755, 30) + pos;
stacksController->addNewAnim(new CPointEffectAnimation(this, soundBase::invalid, sc->side ? "SP07_A.DEF" : "SP07_B.DEF", leftHero)); stacksController->addNewAnim(new CPointEffectAnimation(*this, soundBase::invalid, sc->side ? "SP07_A.DEF" : "SP07_B.DEF", leftHero));
stacksController->addNewAnim(new CPointEffectAnimation(this, soundBase::invalid, sc->side ? "SP07_B.DEF" : "SP07_A.DEF", rightHero)); stacksController->addNewAnim(new CPointEffectAnimation(*this, soundBase::invalid, sc->side ? "SP07_B.DEF" : "SP07_A.DEF", rightHero));
} }
} }
@ -589,7 +586,7 @@ void BattleInterface::displaySpellAnimationQueue(const CSpell::TAnimationQueue &
for(const CSpell::TAnimation & animation : q) for(const CSpell::TAnimation & animation : q)
{ {
if(animation.pause > 0) if(animation.pause > 0)
stacksController->addNewAnim(new CDummyAnimation(this, animation.pause)); stacksController->addNewAnim(new CDummyAnimation(*this, animation.pause));
else else
{ {
int flags = 0; int flags = 0;
@ -604,9 +601,9 @@ void BattleInterface::displaySpellAnimationQueue(const CSpell::TAnimationQueue &
flags |= CPointEffectAnimation::SCREEN_FILL; flags |= CPointEffectAnimation::SCREEN_FILL;
if (!destinationTile.isValid()) if (!destinationTile.isValid())
stacksController->addNewAnim(new CPointEffectAnimation(this, soundBase::invalid, animation.resourceName, flags)); stacksController->addNewAnim(new CPointEffectAnimation(*this, soundBase::invalid, animation.resourceName, flags));
else else
stacksController->addNewAnim(new CPointEffectAnimation(this, soundBase::invalid, animation.resourceName, destinationTile, flags)); stacksController->addNewAnim(new CPointEffectAnimation(*this, soundBase::invalid, animation.resourceName, destinationTile, flags));
} }
} }
} }
@ -827,10 +824,13 @@ void BattleInterface::obstaclePlaced(const std::vector<std::shared_ptr<const COb
const CGHeroInstance *BattleInterface::currentHero() const const CGHeroInstance *BattleInterface::currentHero() const
{ {
if (attackingHeroInstance->tempOwner == curInt->playerID) if (attackingHeroInstance && attackingHeroInstance->tempOwner == curInt->playerID)
return attackingHeroInstance; return attackingHeroInstance;
else
if (defendingHeroInstance && defendingHeroInstance->tempOwner == curInt->playerID)
return defendingHeroInstance; return defendingHeroInstance;
return nullptr;
} }
InfoAboutHero BattleInterface::enemyHero() const InfoAboutHero BattleInterface::enemyHero() const

View File

@ -262,10 +262,10 @@ void BattleHero::switchToNextPhase()
currentFrame = firstFrame; currentFrame = firstFrame;
} }
BattleHero::BattleHero(const std::string & animationPath, bool flipG, PlayerColor player, const CGHeroInstance * hero, const BattleInterface * owner): BattleHero::BattleHero(const std::string & animationPath, bool flipG, PlayerColor player, const CGHeroInstance * hero, const BattleInterface & owner):
flip(flipG), flip(flipG),
myHero(hero), myHero(hero),
myOwner(owner), myOwner(&owner),
phase(1), phase(1),
nextPhase(0), nextPhase(0),
flagAnim(0), flagAnim(0),
@ -331,24 +331,24 @@ HeroInfoWindow::HeroInfoWindow(const InfoAboutHero & hero, Point * position)
labels.push_back(std::make_shared<CLabel>(39, 186, EFonts::FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, std::to_string(currentSpellPoints) + "/" + std::to_string(maxSpellPoints))); labels.push_back(std::make_shared<CLabel>(39, 186, EFonts::FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, std::to_string(currentSpellPoints) + "/" + std::to_string(maxSpellPoints)));
} }
BattleOptionsWindow::BattleOptionsWindow(BattleInterface *owner): BattleOptionsWindow::BattleOptionsWindow(BattleInterface & owner):
CWindowObject(PLAYER_COLORED, "comopbck.bmp") CWindowObject(PLAYER_COLORED, "comopbck.bmp")
{ {
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
auto viewGrid = std::make_shared<CToggleButton>(Point(25, 56), "sysopchk.def", CGI->generaltexth->zelp[427], [=](bool on){owner->setPrintCellBorders(on);} ); auto viewGrid = std::make_shared<CToggleButton>(Point(25, 56), "sysopchk.def", CGI->generaltexth->zelp[427], [&](bool on){owner.setPrintCellBorders(on);} );
viewGrid->setSelected(settings["battle"]["cellBorders"].Bool()); viewGrid->setSelected(settings["battle"]["cellBorders"].Bool());
toggles.push_back(viewGrid); toggles.push_back(viewGrid);
auto movementShadow = std::make_shared<CToggleButton>(Point(25, 89), "sysopchk.def", CGI->generaltexth->zelp[428], [=](bool on){owner->setPrintStackRange(on);}); auto movementShadow = std::make_shared<CToggleButton>(Point(25, 89), "sysopchk.def", CGI->generaltexth->zelp[428], [&](bool on){owner.setPrintStackRange(on);});
movementShadow->setSelected(settings["battle"]["stackRange"].Bool()); movementShadow->setSelected(settings["battle"]["stackRange"].Bool());
toggles.push_back(movementShadow); toggles.push_back(movementShadow);
auto mouseShadow = std::make_shared<CToggleButton>(Point(25, 122), "sysopchk.def", CGI->generaltexth->zelp[429], [=](bool on){owner->setPrintMouseShadow(on);}); auto mouseShadow = std::make_shared<CToggleButton>(Point(25, 122), "sysopchk.def", CGI->generaltexth->zelp[429], [&](bool on){owner.setPrintMouseShadow(on);});
mouseShadow->setSelected(settings["battle"]["mouseShadow"].Bool()); mouseShadow->setSelected(settings["battle"]["mouseShadow"].Bool());
toggles.push_back(mouseShadow); toggles.push_back(mouseShadow);
animSpeeds = std::make_shared<CToggleGroup>([=](int value){ owner->setAnimSpeed(value);}); animSpeeds = std::make_shared<CToggleGroup>([&](int value){ owner.setAnimSpeed(value);});
std::shared_ptr<CToggleButton> toggle; std::shared_ptr<CToggleButton> toggle;
toggle = std::make_shared<CToggleButton>(Point( 28, 225), "sysopb9.def", CGI->generaltexth->zelp[422]); toggle = std::make_shared<CToggleButton>(Point( 28, 225), "sysopb9.def", CGI->generaltexth->zelp[422]);
@ -360,7 +360,7 @@ BattleOptionsWindow::BattleOptionsWindow(BattleInterface *owner):
toggle = std::make_shared<CToggleButton>(Point(156, 225), "sysob11.def", CGI->generaltexth->zelp[424]); toggle = std::make_shared<CToggleButton>(Point(156, 225), "sysob11.def", CGI->generaltexth->zelp[424]);
animSpeeds->addToggle(100, toggle); animSpeeds->addToggle(100, toggle);
animSpeeds->setSelected(owner->getAnimSpeed()); animSpeeds->setSelected(owner.getAnimSpeed());
setToDefault = std::make_shared<CButton>(Point(246, 359), "codefaul.def", CGI->generaltexth->zelp[393], [&](){ bDefaultf(); }); setToDefault = std::make_shared<CButton>(Point(246, 359), "codefaul.def", CGI->generaltexth->zelp[393], [&](){ bDefaultf(); });
setToDefault->setImageOrder(1, 0, 2, 3); setToDefault->setImageOrder(1, 0, 2, 3);
@ -648,9 +648,9 @@ void ClickableHex::clickRight(tribool down, bool previousState)
} }
} }
StackQueue::StackQueue(bool Embedded, BattleInterface * _owner) StackQueue::StackQueue(bool Embedded, BattleInterface & owner)
: embedded(Embedded), : embedded(Embedded),
owner(_owner) owner(owner)
{ {
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
if(embedded) if(embedded)
@ -689,7 +689,7 @@ void StackQueue::update()
{ {
std::vector<battle::Units> queueData; std::vector<battle::Units> queueData;
owner->getCurrentPlayerInterface()->cb->battleGetTurnOrder(queueData, stackBoxes.size(), 0); owner.getCurrentPlayerInterface()->cb->battleGetTurnOrder(queueData, stackBoxes.size(), 0);
size_t boxIndex = 0; size_t boxIndex = 0;
@ -705,7 +705,7 @@ void StackQueue::update()
int32_t StackQueue::getSiegeShooterIconID() int32_t StackQueue::getSiegeShooterIconID()
{ {
return owner->siegeController->getSiegedTown()->town->faction->index; return owner.siegeController->getSiegedTown()->town->faction->index;
} }
StackQueue::StackBox::StackBox(StackQueue * owner): StackQueue::StackBox::StackBox(StackQueue * owner):

View File

@ -97,7 +97,7 @@ public:
void hover(bool on) override; void hover(bool on) override;
void clickLeft(tribool down, bool previousState) override; //call-in void clickLeft(tribool down, bool previousState) override; //call-in
void clickRight(tribool down, bool previousState) override; //call-in void clickRight(tribool down, bool previousState) override; //call-in
BattleHero(const std::string & animationPath, bool filpG, PlayerColor player, const CGHeroInstance * hero, const BattleInterface * owner); BattleHero(const std::string & animationPath, bool filpG, PlayerColor player, const CGHeroInstance * hero, const BattleInterface & owner);
}; };
class HeroInfoWindow : public CWindowObject class HeroInfoWindow : public CWindowObject
@ -119,7 +119,7 @@ private:
std::vector<std::shared_ptr<CLabel>> labels; std::vector<std::shared_ptr<CLabel>> labels;
std::vector<std::shared_ptr<CToggleButton>> toggles; std::vector<std::shared_ptr<CToggleButton>> toggles;
public: public:
BattleOptionsWindow(BattleInterface * owner); BattleOptionsWindow(BattleInterface & owner);
void bDefaultf(); //default button callback void bDefaultf(); //default button callback
void bExitf(); //exit button callback void bExitf(); //exit button callback
@ -151,8 +151,6 @@ private:
bool setAlterText; //if true, this hex has set alternative text in console and will clean it bool setAlterText; //if true, this hex has set alternative text in console and will clean it
public: public:
ui32 myNumber; //number of hex in commonly used format ui32 myNumber; //number of hex in commonly used format
//bool accessible; //if true, this hex is accessible for units
//CStack * ourStack;
bool strictHovered; //for determining if hex is hovered by mouse (this is different problem than hex's graphic hovering) bool strictHovered; //for determining if hex is hovered by mouse (this is different problem than hex's graphic hovering)
BattleInterface * myInterface; //interface that owns me BattleInterface * myInterface; //interface that owns me
@ -183,7 +181,7 @@ class StackQueue : public CIntObject
static const int QUEUE_SIZE = 10; static const int QUEUE_SIZE = 10;
std::shared_ptr<CFilledTexture> background; std::shared_ptr<CFilledTexture> background;
std::vector<std::shared_ptr<StackBox>> stackBoxes; std::vector<std::shared_ptr<StackBox>> stackBoxes;
BattleInterface * owner; BattleInterface & owner;
std::shared_ptr<CAnimation> icons; std::shared_ptr<CAnimation> icons;
std::shared_ptr<CAnimation> stateIcons; std::shared_ptr<CAnimation> stateIcons;
@ -192,6 +190,6 @@ class StackQueue : public CIntObject
public: public:
const bool embedded; const bool embedded;
StackQueue(bool Embedded, BattleInterface * _owner); StackQueue(bool Embedded, BattleInterface & owner);
void update(); void update();
}; };

View File

@ -24,10 +24,10 @@
#include "../../lib/battle/CObstacleInstance.h" #include "../../lib/battle/CObstacleInstance.h"
#include "../../lib/ObstacleHandler.h" #include "../../lib/ObstacleHandler.h"
BattleObstacleController::BattleObstacleController(BattleInterface * owner): BattleObstacleController::BattleObstacleController(BattleInterface & owner):
owner(owner) owner(owner)
{ {
auto obst = owner->curInt->cb->battleGetAllObstacles(); auto obst = owner.curInt->cb->battleGetAllObstacles();
for(auto & elem : obst) for(auto & elem : obst)
{ {
if ( elem->obstacleType == CObstacleInstance::MOAT ) if ( elem->obstacleType == CObstacleInstance::MOAT )
@ -104,10 +104,10 @@ void BattleObstacleController::obstaclePlaced(const std::vector<std::shared_ptr<
//we assume here that effect graphics have the same size as the usual obstacle image //we assume here that effect graphics have the same size as the usual obstacle image
// -> if we know how to blit obstacle, let's blit the effect in the same place // -> if we know how to blit obstacle, let's blit the effect in the same place
Point whereTo = getObstaclePosition(first, *oi); Point whereTo = getObstaclePosition(first, *oi);
owner->stacksController->addNewAnim(new CPointEffectAnimation(owner, soundBase::invalid, spellObstacle->appearAnimation, whereTo, oi->pos, CPointEffectAnimation::WAIT_FOR_SOUND)); owner.stacksController->addNewAnim(new CPointEffectAnimation(owner, soundBase::invalid, spellObstacle->appearAnimation, whereTo, oi->pos, CPointEffectAnimation::WAIT_FOR_SOUND));
//so when multiple obstacles are added, they show up one after another //so when multiple obstacles are added, they show up one after another
owner->waitForAnims(); owner.waitForAnims();
obstaclesBeingPlaced.erase(obstaclesBeingPlaced.begin()); obstaclesBeingPlaced.erase(obstaclesBeingPlaced.begin());
loadObstacleImage(*spellObstacle); loadObstacleImage(*spellObstacle);
@ -117,7 +117,7 @@ void BattleObstacleController::obstaclePlaced(const std::vector<std::shared_ptr<
void BattleObstacleController::showAbsoluteObstacles(Canvas & canvas, const Point & offset) void BattleObstacleController::showAbsoluteObstacles(Canvas & canvas, const Point & offset)
{ {
//Blit absolute obstacles //Blit absolute obstacles
for(auto & oi : owner->curInt->cb->battleGetAllObstacles()) for(auto & oi : owner.curInt->cb->battleGetAllObstacles())
{ {
if(oi->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE) if(oi->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
{ {
@ -130,7 +130,7 @@ void BattleObstacleController::showAbsoluteObstacles(Canvas & canvas, const Poin
void BattleObstacleController::collectRenderableObjects(BattleRenderer & renderer) void BattleObstacleController::collectRenderableObjects(BattleRenderer & renderer)
{ {
for (auto obstacle : owner->curInt->cb->battleGetAllObstacles()) for (auto obstacle : owner.curInt->cb->battleGetAllObstacles())
{ {
if (obstacle->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE) if (obstacle->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
continue; continue;
@ -151,7 +151,7 @@ void BattleObstacleController::collectRenderableObjects(BattleRenderer & rendere
std::shared_ptr<IImage> BattleObstacleController::getObstacleImage(const CObstacleInstance & oi) std::shared_ptr<IImage> BattleObstacleController::getObstacleImage(const CObstacleInstance & oi)
{ {
int frameIndex = (owner->animCount+1) *25 / owner->getAnimSpeed(); int frameIndex = (owner.animCount+1) *25 / owner.getAnimSpeed();
std::shared_ptr<CAnimation> animation; std::shared_ptr<CAnimation> animation;
if (obstacleAnimations.count(oi.uniqueID) == 0) if (obstacleAnimations.count(oi.uniqueID) == 0)
@ -183,7 +183,7 @@ Point BattleObstacleController::getObstaclePosition(std::shared_ptr<IImage> imag
{ {
int offset = obstacle.getAnimationYOffset(image->height()); int offset = obstacle.getAnimationYOffset(image->height());
Rect r = owner->fieldController->hexPositionAbsolute(obstacle.pos); Rect r = owner.fieldController->hexPositionAbsolute(obstacle.pos);
r.y += 42 - image->height() + offset; r.y += 42 - image->height() + offset;
return r.topLeft(); return r.topLeft();

View File

@ -27,7 +27,7 @@ struct Point;
/// (with exception of moat, which is apparently handled by siege controller) /// (with exception of moat, which is apparently handled by siege controller)
class BattleObstacleController class BattleObstacleController
{ {
BattleInterface * owner; BattleInterface & owner;
/// cached animations of all obstacles in current battle /// cached animations of all obstacles in current battle
std::map<std::string, std::shared_ptr<CAnimation>> animationsCache; std::map<std::string, std::shared_ptr<CAnimation>> animationsCache;
@ -45,7 +45,7 @@ class BattleObstacleController
Point getObstaclePosition(std::shared_ptr<IImage> image, const CObstacleInstance & obstacle); Point getObstaclePosition(std::shared_ptr<IImage> image, const CObstacleInstance & obstacle);
public: public:
BattleObstacleController(BattleInterface * owner); BattleObstacleController(BattleInterface & owner);
/// call-in from network pack, add newly placed obstacles with any required animations /// call-in from network pack, add newly placed obstacles with any required animations
void obstaclePlaced(const std::vector<std::shared_ptr<const CObstacleInstance>> & oi); void obstaclePlaced(const std::vector<std::shared_ptr<const CObstacleInstance>> & oi);

View File

@ -146,16 +146,16 @@ void ProjectileRay::show(Canvas & canvas)
++step; ++step;
} }
BattleProjectileController::BattleProjectileController(BattleInterface * owner): BattleProjectileController::BattleProjectileController(BattleInterface & owner):
owner(owner) owner(owner)
{} {}
const CCreature * BattleProjectileController::getShooter(const CStack * stack) const CCreature & BattleProjectileController::getShooter(const CStack * stack) const
{ {
const CCreature * creature = stack->getCreature(); const CCreature * creature = stack->getCreature();
if(creature->idNumber == CreatureID::ARROW_TOWERS) if(creature->idNumber == CreatureID::ARROW_TOWERS)
creature = owner->siegeController->getTurretCreature(); creature = owner.siegeController->getTurretCreature();
if(creature->animation.missleFrameAngles.empty()) if(creature->animation.missleFrameAngles.empty())
{ {
@ -163,17 +163,17 @@ const CCreature * BattleProjectileController::getShooter(const CStack * stack)
creature = CGI->creh->objects[CreatureID::ARCHER]; creature = CGI->creh->objects[CreatureID::ARCHER];
} }
return creature; return *creature;
} }
bool BattleProjectileController::stackUsesRayProjectile(const CStack * stack) bool BattleProjectileController::stackUsesRayProjectile(const CStack * stack) const
{ {
return !getShooter(stack)->animation.projectileRay.empty(); return !getShooter(stack).animation.projectileRay.empty();
} }
bool BattleProjectileController::stackUsesMissileProjectile(const CStack * stack) bool BattleProjectileController::stackUsesMissileProjectile(const CStack * stack) const
{ {
return !getShooter(stack)->animation.projectileImageName.empty(); return !getShooter(stack).animation.projectileImageName.empty();
} }
void BattleProjectileController::initStackProjectile(const CStack * stack) void BattleProjectileController::initStackProjectile(const CStack * stack)
@ -181,8 +181,8 @@ void BattleProjectileController::initStackProjectile(const CStack * stack)
if (!stackUsesMissileProjectile(stack)) if (!stackUsesMissileProjectile(stack))
return; return;
const CCreature * creature = getShooter(stack); const CCreature & creature = getShooter(stack);
projectilesCache[creature->animation.projectileImageName] = createProjectileImage(creature->animation.projectileImageName); 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 std::string & path )
@ -200,8 +200,8 @@ std::shared_ptr<CAnimation> BattleProjectileController::createProjectileImage(co
std::shared_ptr<CAnimation> BattleProjectileController::getProjectileImage(const CStack * stack) std::shared_ptr<CAnimation> BattleProjectileController::getProjectileImage(const CStack * stack)
{ {
const CCreature * creature = getShooter(stack); const CCreature & creature = getShooter(stack);
std::string imageName = creature->animation.projectileImageName; std::string imageName = creature.animation.projectileImageName;
if (!projectilesCache.count(imageName)) if (!projectilesCache.count(imageName))
initStackProjectile(stack); initStackProjectile(stack);
@ -266,9 +266,9 @@ int BattleProjectileController::computeProjectileFlightTime( Point from, Point d
int BattleProjectileController::computeProjectileFrameID( Point from, Point dest, const CStack * stack) int BattleProjectileController::computeProjectileFrameID( Point from, Point dest, const CStack * stack)
{ {
const CCreature * creature = getShooter(stack); const CCreature & creature = getShooter(stack);
auto & angles = creature->animation.missleFrameAngles; auto & angles = creature.animation.missleFrameAngles;
auto animation = getProjectileImage(stack); auto animation = getProjectileImage(stack);
// only frames below maxFrame are usable: anything higher is either no present or we don't know when it should be used // only frames below maxFrame are usable: anything higher is either no present or we don't know when it should be used
@ -314,12 +314,12 @@ void BattleProjectileController::createCatapultProjectile(const CStack * shooter
void BattleProjectileController::createProjectile(const CStack * shooter, Point from, Point dest) void BattleProjectileController::createProjectile(const CStack * shooter, Point from, Point dest)
{ {
const CCreature *shooterInfo = getShooter(shooter); const CCreature & shooterInfo = getShooter(shooter);
std::shared_ptr<ProjectileBase> projectile; std::shared_ptr<ProjectileBase> projectile;
if (stackUsesRayProjectile(shooter) && stackUsesMissileProjectile(shooter)) if (stackUsesRayProjectile(shooter) && stackUsesMissileProjectile(shooter))
{ {
logAnim->error("Mod error: Creature '%s' has both missile and ray projectiles configured. Mod should be fixed. Using ray projectile configuration...", shooterInfo->nameSing); logAnim->error("Mod error: Creature '%s' has both missile and ray projectiles configured. Mod should be fixed. Using ray projectile configuration...", shooterInfo.nameSing);
} }
if (stackUsesRayProjectile(shooter)) if (stackUsesRayProjectile(shooter))
@ -327,7 +327,7 @@ void BattleProjectileController::createProjectile(const CStack * shooter, Point
auto rayProjectile = new ProjectileRay(); auto rayProjectile = new ProjectileRay();
projectile.reset(rayProjectile); projectile.reset(rayProjectile);
rayProjectile->rayConfig = shooterInfo->animation.projectileRay; rayProjectile->rayConfig = shooterInfo.animation.projectileRay;
} }
else if (stackUsesMissileProjectile(shooter)) else if (stackUsesMissileProjectile(shooter))
{ {
@ -335,7 +335,7 @@ void BattleProjectileController::createProjectile(const CStack * shooter, Point
projectile.reset(missileProjectile); projectile.reset(missileProjectile);
missileProjectile->animation = getProjectileImage(shooter); missileProjectile->animation = getProjectileImage(shooter);
missileProjectile->reverse = !owner->stacksController->facingRight(shooter); missileProjectile->reverse = !owner.stacksController->facingRight(shooter);
missileProjectile->frameNum = computeProjectileFrameID(from, dest, shooter); missileProjectile->frameNum = computeProjectileFrameID(from, dest, shooter);
} }

View File

@ -77,7 +77,7 @@ struct ProjectileRay : ProjectileBase
/// ... even though in H3 only 1 projectile can be on screen at any point of time /// ... even though in H3 only 1 projectile can be on screen at any point of time
class BattleProjectileController class BattleProjectileController
{ {
BattleInterface * owner; BattleInterface & owner;
/// all projectiles loaded during current battle /// all projectiles loaded during current battle
std::map<std::string, std::shared_ptr<CAnimation>> projectilesCache; std::map<std::string, std::shared_ptr<CAnimation>> projectilesCache;
@ -89,18 +89,18 @@ class BattleProjectileController
std::shared_ptr<CAnimation> createProjectileImage(const std::string & path ); std::shared_ptr<CAnimation> createProjectileImage(const std::string & path );
void initStackProjectile(const CStack * stack); void initStackProjectile(const CStack * stack);
bool stackUsesRayProjectile(const CStack * stack); bool stackUsesRayProjectile(const CStack * stack) const;
bool stackUsesMissileProjectile(const CStack * stack); bool stackUsesMissileProjectile(const CStack * stack) const;
void showProjectile(Canvas & canvas, std::shared_ptr<ProjectileBase> projectile); void showProjectile(Canvas & canvas, std::shared_ptr<ProjectileBase> projectile);
const CCreature * getShooter(const CStack * stack); const CCreature & getShooter(const CStack * stack) const;
int computeProjectileFrameID( Point from, Point dest, const CStack * stack); int computeProjectileFrameID( Point from, Point dest, const CStack * stack);
int computeProjectileFlightTime( Point from, Point dest, double speed); int computeProjectileFlightTime( Point from, Point dest, double speed);
public: public:
BattleProjectileController(BattleInterface * owner); BattleProjectileController(BattleInterface & owner);
/// renders all currently active projectiles /// renders all currently active projectiles
void showProjectiles(Canvas & canvas); void showProjectiles(Canvas & canvas);

View File

@ -18,12 +18,12 @@
void BattleRenderer::collectObjects() void BattleRenderer::collectObjects()
{ {
owner->collectRenderableObjects(*this); owner.collectRenderableObjects(*this);
owner->effectsController->collectRenderableObjects(*this); owner.effectsController->collectRenderableObjects(*this);
owner->obstacleController->collectRenderableObjects(*this); owner.obstacleController->collectRenderableObjects(*this);
owner->stacksController->collectRenderableObjects(*this); owner.stacksController->collectRenderableObjects(*this);
if (owner->siegeController) if (owner.siegeController)
owner->siegeController->collectRenderableObjects(*this); owner.siegeController->collectRenderableObjects(*this);
} }
void BattleRenderer::sortObjects() void BattleRenderer::sortObjects()
@ -36,13 +36,7 @@ void BattleRenderer::sortObjects()
if ( object.tile == BattleHex::HEX_BEFORE_ALL ) if ( object.tile == BattleHex::HEX_BEFORE_ALL )
return -1; return -1;
if ( object.tile == BattleHex::HEX_AFTER_ALL ) assert( object.tile == BattleHex::HEX_AFTER_ALL || object.tile == BattleHex::INVALID);
return GameConstants::BFIELD_HEIGHT;
if ( object.tile == BattleHex::INVALID )
return GameConstants::BFIELD_HEIGHT;
assert(0);
return GameConstants::BFIELD_HEIGHT; return GameConstants::BFIELD_HEIGHT;
}; };
@ -59,14 +53,14 @@ void BattleRenderer::renderObjects(BattleRenderer::RendererPtr targetCanvas)
object.functor(targetCanvas); object.functor(targetCanvas);
} }
BattleRenderer::BattleRenderer(BattleInterface * owner): BattleRenderer::BattleRenderer(BattleInterface & owner):
owner(owner) owner(owner)
{ {
} }
void BattleRenderer::insert(EBattleFieldLayer layer, BattleHex tile, BattleRenderer::RenderFunctor functor) void BattleRenderer::insert(EBattleFieldLayer layer, BattleHex tile, BattleRenderer::RenderFunctor functor)
{ {
objects.push_back({ functor, layer, tile }); objects.push_back({functor, layer, tile});
} }
void BattleRenderer::execute(BattleRenderer::RendererPtr targetCanvas) void BattleRenderer::execute(BattleRenderer::RendererPtr targetCanvas)

View File

@ -33,7 +33,7 @@ public:
using RenderFunctor = std::function<void(RendererPtr)>; using RenderFunctor = std::function<void(RendererPtr)>;
private: private:
BattleInterface * owner; BattleInterface & owner;
struct RenderableInstance struct RenderableInstance
{ {
@ -47,7 +47,7 @@ private:
void sortObjects(); void sortObjects();
void renderObjects(RendererPtr targetCanvas); void renderObjects(RendererPtr targetCanvas);
public: public:
BattleRenderer(BattleInterface * owner); BattleRenderer(BattleInterface & owner);
void insert(EBattleFieldLayer layer, BattleHex tile, RenderFunctor functor); void insert(EBattleFieldLayer layer, BattleHex tile, RenderFunctor functor);
void execute(RendererPtr targetCanvas); void execute(RendererPtr targetCanvas);

View File

@ -124,15 +124,15 @@ std::string BattleSiegeController::getBattleBackgroundName() const
bool BattleSiegeController::getWallPieceExistance(EWallVisual::EWallVisual what) const bool BattleSiegeController::getWallPieceExistance(EWallVisual::EWallVisual what) const
{ {
//FIXME: use this instead of buildings test? //FIXME: use this instead of buildings test?
//ui8 siegeLevel = owner->curInt->cb->battleGetSiegeLevel(); //ui8 siegeLevel = owner.curInt->cb->battleGetSiegeLevel();
switch (what) switch (what)
{ {
case EWallVisual::MOAT: return town->hasBuilt(BuildingID::CITADEL) && town->town->faction->index != ETownType::TOWER; case EWallVisual::MOAT: return town->hasBuilt(BuildingID::CITADEL) && town->town->faction->index != ETownType::TOWER;
case EWallVisual::MOAT_BANK: return town->hasBuilt(BuildingID::CITADEL) && town->town->faction->index != ETownType::TOWER && town->town->faction->index != ETownType::NECROPOLIS; case EWallVisual::MOAT_BANK: return town->hasBuilt(BuildingID::CITADEL) && town->town->faction->index != ETownType::TOWER && town->town->faction->index != ETownType::NECROPOLIS;
case EWallVisual::KEEP_BATTLEMENT: return town->hasBuilt(BuildingID::CITADEL) && EWallState::EWallState(owner->curInt->cb->battleGetWallState(EWallPart::KEEP)) != EWallState::DESTROYED; case EWallVisual::KEEP_BATTLEMENT: return town->hasBuilt(BuildingID::CITADEL) && EWallState::EWallState(owner.curInt->cb->battleGetWallState(EWallPart::KEEP)) != EWallState::DESTROYED;
case EWallVisual::UPPER_BATTLEMENT: return town->hasBuilt(BuildingID::CASTLE) && EWallState::EWallState(owner->curInt->cb->battleGetWallState(EWallPart::UPPER_TOWER)) != EWallState::DESTROYED; case EWallVisual::UPPER_BATTLEMENT: return town->hasBuilt(BuildingID::CASTLE) && EWallState::EWallState(owner.curInt->cb->battleGetWallState(EWallPart::UPPER_TOWER)) != EWallState::DESTROYED;
case EWallVisual::BOTTOM_BATTLEMENT: return town->hasBuilt(BuildingID::CASTLE) && EWallState::EWallState(owner->curInt->cb->battleGetWallState(EWallPart::BOTTOM_TOWER)) != EWallState::DESTROYED; case EWallVisual::BOTTOM_BATTLEMENT: return town->hasBuilt(BuildingID::CASTLE) && EWallState::EWallState(owner.curInt->cb->battleGetWallState(EWallPart::BOTTOM_TOWER)) != EWallState::DESTROYED;
default: return true; default: return true;
} }
} }
@ -163,11 +163,11 @@ BattleHex BattleSiegeController::getWallPiecePosition(EWallVisual::EWallVisual w
return wallsPositions[what]; return wallsPositions[what];
} }
BattleSiegeController::BattleSiegeController(BattleInterface * owner, const CGTownInstance *siegeTown): BattleSiegeController::BattleSiegeController(BattleInterface & owner, const CGTownInstance *siegeTown):
owner(owner), owner(owner),
town(siegeTown) town(siegeTown)
{ {
assert(owner->fieldController.get() == nullptr); // must be created after this assert(owner.fieldController.get() == nullptr); // must be created after this
for (int g = 0; g < wallPieceImages.size(); ++g) for (int g = 0; g < wallPieceImages.size(); ++g)
{ {
@ -205,7 +205,7 @@ Point BattleSiegeController::getTurretCreaturePosition( BattleHex position ) con
if (posID != 0) if (posID != 0)
{ {
Point result = owner->pos.topLeft(); Point result = owner.pos.topLeft();
result.x += town->town->clientInfo.siegePositions[posID].x; result.x += town->town->clientInfo.siegePositions[posID].x;
result.y += town->town->clientInfo.siegePositions[posID].y; result.y += town->town->clientInfo.siegePositions[posID].y;
return result; return result;
@ -217,7 +217,7 @@ Point BattleSiegeController::getTurretCreaturePosition( BattleHex position ) con
void BattleSiegeController::gateStateChanged(const EGateState state) void BattleSiegeController::gateStateChanged(const EGateState state)
{ {
auto oldState = owner->curInt->cb->battleGetGateState(); auto oldState = owner.curInt->cb->battleGetGateState();
bool playSound = false; bool playSound = false;
auto stateId = EWallState::NONE; auto stateId = EWallState::NONE;
switch(state) switch(state)
@ -272,7 +272,7 @@ BattleHex BattleSiegeController::getTurretBattleHex(EWallVisual::EWallVisual wal
const CStack * BattleSiegeController::getTurretStack(EWallVisual::EWallVisual wallPiece) const const CStack * BattleSiegeController::getTurretStack(EWallVisual::EWallVisual wallPiece) const
{ {
for (auto & stack : owner->curInt->cb->battleGetAllStacks(true)) for (auto & stack : owner.curInt->cb->battleGetAllStacks(true))
{ {
if ( stack->initialPosition == getTurretBattleHex(wallPiece)) if ( stack->initialPosition == getTurretBattleHex(wallPiece))
return stack; return stack;
@ -298,14 +298,14 @@ void BattleSiegeController::collectRenderableObjects(BattleRenderer & renderer)
wallPiece == EWallVisual::UPPER_BATTLEMENT) wallPiece == EWallVisual::UPPER_BATTLEMENT)
{ {
renderer.insert( EBattleFieldLayer::STACKS, getWallPiecePosition(wallPiece), [this, wallPiece](BattleRenderer::RendererPtr canvas){ renderer.insert( EBattleFieldLayer::STACKS, getWallPiecePosition(wallPiece), [this, wallPiece](BattleRenderer::RendererPtr canvas){
owner->stacksController->showStack(canvas, getTurretStack(wallPiece)); owner.stacksController->showStack(canvas, getTurretStack(wallPiece));
}); });
renderer.insert( EBattleFieldLayer::BATTLEMENTS, getWallPiecePosition(wallPiece), [this, wallPiece](BattleRenderer::RendererPtr canvas){ renderer.insert( EBattleFieldLayer::BATTLEMENTS, getWallPiecePosition(wallPiece), [this, wallPiece](BattleRenderer::RendererPtr canvas){
showWallPiece(canvas, wallPiece, owner->pos.topLeft()); showWallPiece(canvas, wallPiece, owner.pos.topLeft());
}); });
} }
renderer.insert( EBattleFieldLayer::WALLS, getWallPiecePosition(wallPiece), [this, wallPiece](BattleRenderer::RendererPtr canvas){ renderer.insert( EBattleFieldLayer::WALLS, getWallPiecePosition(wallPiece), [this, wallPiece](BattleRenderer::RendererPtr canvas){
showWallPiece(canvas, wallPiece, owner->pos.topLeft()); showWallPiece(canvas, wallPiece, owner.pos.topLeft());
}); });
@ -314,14 +314,14 @@ void BattleSiegeController::collectRenderableObjects(BattleRenderer & renderer)
bool BattleSiegeController::isAttackableByCatapult(BattleHex hex) const bool BattleSiegeController::isAttackableByCatapult(BattleHex hex) const
{ {
if (owner->tacticsMode) if (owner.tacticsMode)
return false; return false;
auto wallPart = owner->curInt->cb->battleHexToWallPart(hex); auto wallPart = owner.curInt->cb->battleHexToWallPart(hex);
if (!owner->curInt->cb->isWallPartPotentiallyAttackable(wallPart)) if (!owner.curInt->cb->isWallPartPotentiallyAttackable(wallPart))
return false; return false;
auto state = owner->curInt->cb->battleGetWallState(static_cast<int>(wallPart)); auto state = owner.curInt->cb->battleGetWallState(static_cast<int>(wallPart));
return state != EWallState::DESTROYED && state != EWallState::NONE; return state != EWallState::DESTROYED && state != EWallState::NONE;
} }
@ -329,10 +329,10 @@ void BattleSiegeController::stackIsCatapulting(const CatapultAttack & ca)
{ {
if (ca.attacker != -1) if (ca.attacker != -1)
{ {
const CStack *stack = owner->curInt->cb->battleGetStackByID(ca.attacker); const CStack *stack = owner.curInt->cb->battleGetStackByID(ca.attacker);
for (auto attackInfo : ca.attackedParts) for (auto attackInfo : ca.attackedParts)
{ {
owner->stacksController->addNewAnim(new CCatapultAnimation(owner, stack, attackInfo.destinationTile, nullptr, attackInfo.damageDealt)); owner.stacksController->addNewAnim(new CCatapultAnimation(owner, stack, attackInfo.destinationTile, nullptr, attackInfo.damageDealt));
} }
} }
else else
@ -341,13 +341,13 @@ void BattleSiegeController::stackIsCatapulting(const CatapultAttack & ca)
//no attacker stack, assume spell-related (earthquake) - only hit animation //no attacker stack, assume spell-related (earthquake) - only hit animation
for (auto attackInfo : ca.attackedParts) for (auto attackInfo : ca.attackedParts)
positions.push_back(owner->stacksController->getStackPositionAtHex(attackInfo.destinationTile, nullptr) + Point(99, 120)); positions.push_back(owner.stacksController->getStackPositionAtHex(attackInfo.destinationTile, nullptr) + Point(99, 120));
owner->stacksController->addNewAnim(new CPointEffectAnimation(owner, soundBase::WALLHIT, "SGEXPL.DEF", positions)); owner.stacksController->addNewAnim(new CPointEffectAnimation(owner, soundBase::WALLHIT, "SGEXPL.DEF", positions));
} }
owner->waitForAnims(); owner.waitForAnims();
for (auto attackInfo : ca.attackedParts) for (auto attackInfo : ca.attackedParts)
{ {
@ -356,7 +356,7 @@ void BattleSiegeController::stackIsCatapulting(const CatapultAttack & ca)
if (wallId == EWallVisual::GATE) if (wallId == EWallVisual::GATE)
continue; continue;
auto wallState = EWallState::EWallState(owner->curInt->cb->battleGetWallState(attackInfo.attackedPart)); auto wallState = EWallState::EWallState(owner.curInt->cb->battleGetWallState(attackInfo.attackedPart));
wallPieceImages[wallId] = IImage::createFromFile(getWallPieceImageName(EWallVisual::EWallVisual(wallId), wallState)); wallPieceImages[wallId] = IImage::createFromFile(getWallPieceImageName(EWallVisual::EWallVisual(wallId), wallState));
} }

View File

@ -67,7 +67,7 @@ namespace EWallVisual
class BattleSiegeController class BattleSiegeController
{ {
BattleInterface * owner; BattleInterface & owner;
/// besieged town /// besieged town
const CGTownInstance *town; const CGTownInstance *town;
@ -90,7 +90,7 @@ class BattleSiegeController
const CStack * getTurretStack(EWallVisual::EWallVisual wallPiece) const; const CStack * getTurretStack(EWallVisual::EWallVisual wallPiece) const;
public: public:
BattleSiegeController(BattleInterface * owner, const CGTownInstance *siegeTown); BattleSiegeController(BattleInterface & owner, const CGTownInstance *siegeTown);
/// call-ins from server /// call-ins from server
void gateStateChanged(const EGateState state); void gateStateChanged(const EGateState state);

View File

@ -60,7 +60,7 @@ static void onAnimationFinished(const CStack *stack, std::weak_ptr<CreatureAnima
animation->onAnimationReset += std::bind(&onAnimationFinished, stack, anim); animation->onAnimationReset += std::bind(&onAnimationFinished, stack, anim);
} }
BattleStacksController::BattleStacksController(BattleInterface * owner): BattleStacksController::BattleStacksController(BattleInterface & owner):
owner(owner), owner(owner),
activeStack(nullptr), activeStack(nullptr),
mouseHoveredStack(nullptr), mouseHoveredStack(nullptr),
@ -86,7 +86,7 @@ BattleStacksController::BattleStacksController(BattleInterface * owner):
amountNegative->adjustPalette(&shifterNegative); amountNegative->adjustPalette(&shifterNegative);
amountEffNeutral->adjustPalette(&shifterNeutral); amountEffNeutral->adjustPalette(&shifterNeutral);
std::vector<const CStack*> stacks = owner->curInt->cb->battleGetAllStacks(true); std::vector<const CStack*> stacks = owner.curInt->cb->battleGetAllStacks(true);
for(const CStack * s : stacks) for(const CStack * s : stacks)
{ {
stackAdded(s); stackAdded(s);
@ -118,7 +118,7 @@ BattleHex BattleStacksController::getStackCurrentPosition(const CStack * stack)
void BattleStacksController::collectRenderableObjects(BattleRenderer & renderer) void BattleStacksController::collectRenderableObjects(BattleRenderer & renderer)
{ {
auto stacks = owner->curInt->cb->battleGetAllStacks(false); auto stacks = owner.curInt->cb->battleGetAllStacks(false);
for (auto stack : stacks) for (auto stack : stacks)
{ {
@ -178,14 +178,14 @@ void BattleStacksController::stackAdded(const CStack * stack)
if(stack->initialPosition < 0) //turret if(stack->initialPosition < 0) //turret
{ {
assert(owner->siegeController); assert(owner.siegeController);
const CCreature *turretCreature = owner->siegeController->getTurretCreature(); const CCreature *turretCreature = owner.siegeController->getTurretCreature();
stackAnimation[stack->ID] = AnimationControls::getAnimation(turretCreature); stackAnimation[stack->ID] = AnimationControls::getAnimation(turretCreature);
stackAnimation[stack->ID]->pos.h = 235; stackAnimation[stack->ID]->pos.h = 235;
coords = owner->siegeController->getTurretCreaturePosition(stack->initialPosition); coords = owner.siegeController->getTurretCreaturePosition(stack->initialPosition);
} }
else else
{ {
@ -209,7 +209,7 @@ void BattleStacksController::setActiveStack(const CStack *stack)
if (activeStack) // update UI if (activeStack) // update UI
stackAnimation[activeStack->ID]->setBorderColor(AnimationControls::getGoldBorder()); stackAnimation[activeStack->ID]->setBorderColor(AnimationControls::getGoldBorder());
owner->controlPanel->blockUI(activeStack == nullptr); owner.controlPanel->blockUI(activeStack == nullptr);
} }
void BattleStacksController::setHoveredStack(const CStack *stack) void BattleStacksController::setHoveredStack(const CStack *stack)
@ -239,9 +239,9 @@ void BattleStacksController::setHoveredStack(const CStack *stack)
bool BattleStacksController::stackNeedsAmountBox(const CStack * stack) bool BattleStacksController::stackNeedsAmountBox(const CStack * stack)
{ {
BattleHex currentActionTarget; BattleHex currentActionTarget;
if(owner->curInt->curAction) if(owner.curInt->curAction)
{ {
auto target = owner->curInt->curAction->getTarget(owner->curInt->cb.get()); auto target = owner.curInt->curAction->getTarget(owner.curInt->cb.get());
if(!target.empty()) if(!target.empty())
currentActionTarget = target.at(0).hexValue; currentActionTarget = target.at(0).hexValue;
} }
@ -249,7 +249,7 @@ bool BattleStacksController::stackNeedsAmountBox(const CStack * stack)
if(stack->hasBonusOfType(Bonus::SIEGE_WEAPON) && stack->getCount() == 1) //do not show box for singular war machines, stacked war machines with box shown are supported as extension feature if(stack->hasBonusOfType(Bonus::SIEGE_WEAPON) && stack->getCount() == 1) //do not show box for singular war machines, stacked war machines with box shown are supported as extension feature
return false; return false;
if (!owner->battleActionsStarted) // do not perform any further checks since they are related to actions that will only occur after intro music if (!owner.battleActionsStarted) // do not perform any further checks since they are related to actions that will only occur after intro music
return true; return true;
if(!stack->alive()) if(!stack->alive())
@ -265,18 +265,18 @@ bool BattleStacksController::stackNeedsAmountBox(const CStack * stack)
return false; return false;
} }
if(owner->curInt->curAction) if(owner.curInt->curAction)
{ {
if(owner->curInt->curAction->stackNumber == stack->ID) //stack is currently taking action (is not a target of another creature's action etc) if(owner.curInt->curAction->stackNumber == stack->ID) //stack is currently taking action (is not a target of another creature's action etc)
{ {
if(owner->curInt->curAction->actionType == EActionType::WALK || owner->curInt->curAction->actionType == EActionType::SHOOT) //hide when stack walks or shoots if(owner.curInt->curAction->actionType == EActionType::WALK || owner.curInt->curAction->actionType == EActionType::SHOOT) //hide when stack walks or shoots
return false; return false;
else if(owner->curInt->curAction->actionType == EActionType::WALK_AND_ATTACK && currentActionTarget != stack->getPosition()) //when attacking, hide until walk phase finished else if(owner.curInt->curAction->actionType == EActionType::WALK_AND_ATTACK && currentActionTarget != stack->getPosition()) //when attacking, hide until walk phase finished
return false; return false;
} }
if(owner->curInt->curAction->actionType == EActionType::SHOOT && currentActionTarget == stack->getPosition()) //hide if we are ranged attack target if(owner.curInt->curAction->actionType == EActionType::SHOOT && currentActionTarget == stack->getPosition()) //hide if we are ranged attack target
return false; return false;
} }
return true; return true;
@ -312,7 +312,7 @@ void BattleStacksController::showStackAmountBox(Canvas & canvas, const CStack *
const int reverseSideShift = stack->side == BattleSide::ATTACKER ? -1 : 1; const int reverseSideShift = stack->side == BattleSide::ATTACKER ? -1 : 1;
const BattleHex nextPos = stack->getPosition() + sideShift; const BattleHex nextPos = stack->getPosition() + sideShift;
const bool edge = stack->getPosition() % GameConstants::BFIELD_WIDTH == (stack->side == BattleSide::ATTACKER ? GameConstants::BFIELD_WIDTH - 2 : 1); const bool edge = stack->getPosition() % GameConstants::BFIELD_WIDTH == (stack->side == BattleSide::ATTACKER ? GameConstants::BFIELD_WIDTH - 2 : 1);
const bool moveInside = !edge && !owner->fieldController->stackCountOutsideHex(nextPos); const bool moveInside = !edge && !owner.fieldController->stackCountOutsideHex(nextPos);
int xAdd = (stack->side == BattleSide::ATTACKER ? 220 : 202) + int xAdd = (stack->side == BattleSide::ATTACKER ? 220 : 202) +
(stack->doubleWide() ? 44 : 0) * sideShift + (stack->doubleWide() ? 44 : 0) * sideShift +
@ -358,23 +358,23 @@ void BattleStacksController::updateBattleAnimations()
if (hadAnimations && currentAnimations.empty()) if (hadAnimations && currentAnimations.empty())
{ {
//anims ended //anims ended
owner->controlPanel->blockUI(activeStack == nullptr); owner.controlPanel->blockUI(activeStack == nullptr);
owner->animsAreDisplayed.setn(false); owner.animsAreDisplayed.setn(false);
} }
} }
void BattleStacksController::addNewAnim(CBattleAnimation *anim) void BattleStacksController::addNewAnim(CBattleAnimation *anim)
{ {
currentAnimations.push_back(anim); currentAnimations.push_back(anim);
owner->animsAreDisplayed.setn(true); owner.animsAreDisplayed.setn(true);
} }
void BattleStacksController::stackActivated(const CStack *stack) //TODO: check it all before game state is changed due to abilities void BattleStacksController::stackActivated(const CStack *stack) //TODO: check it all before game state is changed due to abilities
{ {
stackToActivate = stack; stackToActivate = stack;
owner->waitForAnims(); owner.waitForAnims();
if (stackToActivate) //during waiting stack may have gotten activated through show if (stackToActivate) //during waiting stack may have gotten activated through show
owner->activateStack(); owner.activateStack();
} }
void BattleStacksController::stackRemoved(uint32_t stackID) void BattleStacksController::stackRemoved(uint32_t stackID)
@ -384,10 +384,10 @@ void BattleStacksController::stackRemoved(uint32_t stackID)
if (getActiveStack()->ID == stackID) if (getActiveStack()->ID == stackID)
{ {
BattleAction *action = new BattleAction(); BattleAction *action = new BattleAction();
action->side = owner->defendingHeroInstance ? (owner->curInt->playerID == owner->defendingHeroInstance->tempOwner) : false; action->side = owner.defendingHeroInstance ? (owner.curInt->playerID == owner.defendingHeroInstance->tempOwner) : false;
action->actionType = EActionType::CANCEL; action->actionType = EActionType::CANCEL;
action->stackNumber = getActiveStack()->ID; action->stackNumber = getActiveStack()->ID;
owner->givenCommand.setn(action); owner.givenCommand.setn(action);
setActiveStack(nullptr); setActiveStack(nullptr);
} }
} }
@ -403,10 +403,10 @@ void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> at
if(attackedInfo.rebirth) if(attackedInfo.rebirth)
{ {
owner->effectsController->displayEffect(EBattleEffect::RESURRECT, soundBase::RESURECT, attackedInfo.defender->getPosition()); //TODO: play reverse death animation owner.effectsController->displayEffect(EBattleEffect::RESURRECT, soundBase::RESURECT, attackedInfo.defender->getPosition()); //TODO: play reverse death animation
} }
} }
owner->waitForAnims(); owner.waitForAnims();
for (auto & attackedInfo : attackedInfos) for (auto & attackedInfo : attackedInfos)
{ {
@ -420,7 +420,7 @@ void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> at
void BattleStacksController::stackMoved(const CStack *stack, std::vector<BattleHex> destHex, int distance) void BattleStacksController::stackMoved(const CStack *stack, std::vector<BattleHex> destHex, int distance)
{ {
addNewAnim(new CMovementAnimation(owner, stack, destHex, distance)); addNewAnim(new CMovementAnimation(owner, stack, destHex, distance));
owner->waitForAnims(); owner.waitForAnims();
} }
void BattleStacksController::stackAttacking( const CStack *attacker, BattleHex dest, const CStack *attacked, bool shooting ) void BattleStacksController::stackAttacking( const CStack *attacker, BattleHex dest, const CStack *attacked, bool shooting )
@ -454,7 +454,7 @@ void BattleStacksController::endAction(const BattleAction* action)
{ {
//check if we should reverse stacks //check if we should reverse stacks
//for some strange reason, it's not enough //for some strange reason, it's not enough
TStacks stacks = owner->curInt->cb->battleGetStacks(CBattleCallback::MINE_AND_ENEMY); TStacks stacks = owner.curInt->cb->battleGetStacks(CBattleCallback::MINE_AND_ENEMY);
for (const CStack *s : stacks) for (const CStack *s : stacks)
{ {
@ -469,16 +469,16 @@ void BattleStacksController::endAction(const BattleAction* action)
void BattleStacksController::startAction(const BattleAction* action) void BattleStacksController::startAction(const BattleAction* action)
{ {
const CStack *stack = owner->curInt->cb->battleGetStackByID(action->stackNumber); const CStack *stack = owner.curInt->cb->battleGetStackByID(action->stackNumber);
setHoveredStack(nullptr); setHoveredStack(nullptr);
auto actionTarget = action->getTarget(owner->curInt->cb.get()); auto actionTarget = action->getTarget(owner.curInt->cb.get());
if(action->actionType == EActionType::WALK if(action->actionType == EActionType::WALK
|| (action->actionType == EActionType::WALK_AND_ATTACK && actionTarget.at(0).hexValue != stack->getPosition())) || (action->actionType == EActionType::WALK_AND_ATTACK && actionTarget.at(0).hexValue != stack->getPosition()))
{ {
assert(stack); assert(stack);
owner->moveStarted = true; owner.moveStarted = true;
if (stackAnimation[action->stackNumber]->framesInGroup(CCreatureAnim::MOVE_START)) if (stackAnimation[action->stackNumber]->framesInGroup(CCreatureAnim::MOVE_START))
addNewAnim(new CMovementStartAnimation(owner, stack)); addNewAnim(new CMovementStartAnimation(owner, stack));
@ -495,7 +495,7 @@ void BattleStacksController::activateStack()
if ( !stackToActivate) if ( !stackToActivate)
return; return;
owner->trySetActivePlayer(stackToActivate->owner); owner.trySetActivePlayer(stackToActivate->owner);
setActiveStack(stackToActivate); setActiveStack(stackToActivate);
stackToActivate = nullptr; stackToActivate = nullptr;
@ -513,7 +513,7 @@ void BattleStacksController::activateStack()
if(randomSpellcaster) if(randomSpellcaster)
creatureSpellToCast = -1; //spell will be set later on cast creatureSpellToCast = -1; //spell will be set later on cast
else else
creatureSpellToCast = owner->curInt->cb->battleGetRandomStackSpell(CRandomGenerator::getDefault(), s, CBattleInfoCallback::RANDOM_AIMED); //faerie dragon can cast only one spell until their next move creatureSpellToCast = owner.curInt->cb->battleGetRandomStackSpell(CRandomGenerator::getDefault(), s, CBattleInfoCallback::RANDOM_AIMED); //faerie dragon can cast only one spell until their next move
//TODO: what if creature can cast BOTH random genie spell and aimed spell? //TODO: what if creature can cast BOTH random genie spell and aimed spell?
//TODO: faerie dragon type spell should be selected by server //TODO: faerie dragon type spell should be selected by server
} }
@ -560,7 +560,7 @@ Point BattleStacksController::getStackPositionAtHex(BattleHex hexNum, const CSta
{ {
Point ret(-500, -500); //returned value Point ret(-500, -500); //returned value
if(stack && stack->initialPosition < 0) //creatures in turrets if(stack && stack->initialPosition < 0) //creatures in turrets
return owner->siegeController->getTurretCreaturePosition(stack->initialPosition); return owner.siegeController->getTurretCreaturePosition(stack->initialPosition);
static const Point basePos(-190, -139); // position of creature in topleft corner static const Point basePos(-190, -139); // position of creature in topleft corner
static const int imageShiftX = 30; // X offset to base pos for facing right stacks, negative for facing left static const int imageShiftX = 30; // X offset to base pos for facing right stacks, negative for facing left
@ -591,6 +591,6 @@ Point BattleStacksController::getStackPositionAtHex(BattleHex hexNum, const CSta
} }
} }
//returning //returning
return ret + owner->pos.topLeft(); return ret + owner.pos.topLeft();
} }

View File

@ -36,7 +36,7 @@ class IImage;
/// And any other effect applied to stacks /// And any other effect applied to stacks
class BattleStacksController class BattleStacksController
{ {
BattleInterface * owner; BattleInterface & owner;
std::shared_ptr<IImage> amountNormal; std::shared_ptr<IImage> amountNormal;
std::shared_ptr<IImage> amountNegative; std::shared_ptr<IImage> amountNegative;
@ -78,7 +78,7 @@ class BattleStacksController
std::shared_ptr<IImage> getStackAmountBox(const CStack * stack); std::shared_ptr<IImage> getStackAmountBox(const CStack * stack);
public: public:
BattleStacksController(BattleInterface * owner); BattleStacksController(BattleInterface & owner);
bool shouldRotate(const CStack * stack, const BattleHex & oldPos, const BattleHex & nextHex) const; bool shouldRotate(const CStack * stack, const BattleHex & oldPos, const BattleHex & nextHex) const;
bool facingRight(const CStack * stack) const; bool facingRight(const CStack * stack) const;