mirror of
https://github.com/vcmi/vcmi.git
synced 2025-05-27 22:47:48 +02:00
more battles animations:
- UI will be correctly greyed-out during opponent turn - fixed remaining issues with blit order - a bit better handling of catapult attack - fixes #1362
This commit is contained in:
parent
e9d51a2670
commit
a148c39e0a
@ -230,11 +230,8 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
|
|||||||
bOptions = new CAdventureMapButton (CGI->generaltexth->zelp[381].first, CGI->generaltexth->zelp[381].second, boost::bind(&CBattleInterface::bOptionsf,this), 3, 561, "icm003.def", SDLK_o);
|
bOptions = new CAdventureMapButton (CGI->generaltexth->zelp[381].first, CGI->generaltexth->zelp[381].second, boost::bind(&CBattleInterface::bOptionsf,this), 3, 561, "icm003.def", SDLK_o);
|
||||||
bSurrender = new CAdventureMapButton (CGI->generaltexth->zelp[379].first, CGI->generaltexth->zelp[379].second, boost::bind(&CBattleInterface::bSurrenderf,this), 54, 561, "icm001.def", SDLK_s);
|
bSurrender = new CAdventureMapButton (CGI->generaltexth->zelp[379].first, CGI->generaltexth->zelp[379].second, boost::bind(&CBattleInterface::bSurrenderf,this), 54, 561, "icm001.def", SDLK_s);
|
||||||
bFlee = new CAdventureMapButton (CGI->generaltexth->zelp[380].first, CGI->generaltexth->zelp[380].second, boost::bind(&CBattleInterface::bFleef,this), 105, 561, "icm002.def", SDLK_r);
|
bFlee = new CAdventureMapButton (CGI->generaltexth->zelp[380].first, CGI->generaltexth->zelp[380].second, boost::bind(&CBattleInterface::bFleef,this), 105, 561, "icm002.def", SDLK_r);
|
||||||
bFlee->block(!curInt->cb->getMyColor() || !curInt->cb->battleCanFlee());
|
|
||||||
bSurrender->block(!curInt->cb->getMyColor() || curInt->cb->battleGetSurrenderCost() < 0);
|
|
||||||
bAutofight = new CAdventureMapButton (CGI->generaltexth->zelp[382].first, CGI->generaltexth->zelp[382].second, boost::bind(&CBattleInterface::bAutofightf,this), 157, 561, "icm004.def", SDLK_a);
|
bAutofight = new CAdventureMapButton (CGI->generaltexth->zelp[382].first, CGI->generaltexth->zelp[382].second, boost::bind(&CBattleInterface::bAutofightf,this), 157, 561, "icm004.def", SDLK_a);
|
||||||
bSpell = new CAdventureMapButton (CGI->generaltexth->zelp[385].first, CGI->generaltexth->zelp[385].second, boost::bind(&CBattleInterface::bSpellf,this), 645, 561, "icm005.def", SDLK_c);
|
bSpell = new CAdventureMapButton (CGI->generaltexth->zelp[385].first, CGI->generaltexth->zelp[385].second, boost::bind(&CBattleInterface::bSpellf,this), 645, 561, "icm005.def", SDLK_c);
|
||||||
bSpell->block(true);
|
|
||||||
bWait = new CAdventureMapButton (CGI->generaltexth->zelp[386].first, CGI->generaltexth->zelp[386].second, boost::bind(&CBattleInterface::bWaitf,this), 696, 561, "icm006.def", SDLK_w);
|
bWait = new CAdventureMapButton (CGI->generaltexth->zelp[386].first, CGI->generaltexth->zelp[386].second, boost::bind(&CBattleInterface::bWaitf,this), 696, 561, "icm006.def", SDLK_w);
|
||||||
bDefence = new CAdventureMapButton (CGI->generaltexth->zelp[387].first, CGI->generaltexth->zelp[387].second, boost::bind(&CBattleInterface::bDefencef,this), 747, 561, "icm007.def", SDLK_d);
|
bDefence = new CAdventureMapButton (CGI->generaltexth->zelp[387].first, CGI->generaltexth->zelp[387].second, boost::bind(&CBattleInterface::bDefencef,this), 747, 561, "icm007.def", SDLK_d);
|
||||||
bDefence->assignedKeys.insert(SDLK_SPACE);
|
bDefence->assignedKeys.insert(SDLK_SPACE);
|
||||||
@ -250,8 +247,6 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
|
|||||||
{
|
{
|
||||||
btactNext = new CAdventureMapButton(std::string(), std::string(), boost::bind(&CBattleInterface::bTacticNextStack,this, (CStack*)nullptr), 213, 560, "icm011.def", SDLK_SPACE);
|
btactNext = new CAdventureMapButton(std::string(), std::string(), boost::bind(&CBattleInterface::bTacticNextStack,this, (CStack*)nullptr), 213, 560, "icm011.def", SDLK_SPACE);
|
||||||
btactEnd = new CAdventureMapButton(std::string(), std::string(), boost::bind(&CBattleInterface::bEndTacticPhase,this), 419, 560, "icm012.def", SDLK_RETURN);
|
btactEnd = new CAdventureMapButton(std::string(), std::string(), boost::bind(&CBattleInterface::bEndTacticPhase,this), 419, 560, "icm012.def", SDLK_RETURN);
|
||||||
bDefence->block(true);
|
|
||||||
bWait->block(true);
|
|
||||||
menu = BitmapHandler::loadBitmap("COPLACBR.BMP");
|
menu = BitmapHandler::loadBitmap("COPLACBR.BMP");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -884,8 +879,7 @@ void CBattleInterface::bAutofightf()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
curInt->isAutoFightOn = true;
|
curInt->isAutoFightOn = true;
|
||||||
deactivate();
|
blockUI(true);
|
||||||
bAutofight->activate();
|
|
||||||
|
|
||||||
auto ai = CDynLibHandler::getNewBattleAI(settings["server"]["neutralAI"].String());
|
auto ai = CDynLibHandler::getNewBattleAI(settings["server"]["neutralAI"].String());
|
||||||
ai->init(curInt->cb);
|
ai->init(curInt->cb);
|
||||||
@ -1201,12 +1195,16 @@ void CBattleInterface::stackIsCatapulting(const CatapultAttack & ca)
|
|||||||
{
|
{
|
||||||
const CStack * stack = curInt->cb->battleGetStackByID(ca.attacker);
|
const CStack * stack = curInt->cb->battleGetStackByID(ca.attacker);
|
||||||
addNewAnim(new CShootingAnimation(this, stack, it->first.second, nullptr, true, it->second));
|
addNewAnim(new CShootingAnimation(this, stack, it->first.second, nullptr, true, it->second));
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForAnims();
|
||||||
|
|
||||||
|
for(auto it = ca.attackedParts.begin(); it != ca.attackedParts.end(); ++it)
|
||||||
|
{
|
||||||
SDL_FreeSurface(siegeH->walls[it->first.first + 2]);
|
SDL_FreeSurface(siegeH->walls[it->first.first + 2]);
|
||||||
siegeH->walls[it->first.first + 2] = BitmapHandler::loadBitmap(
|
siegeH->walls[it->first.first + 2] = BitmapHandler::loadBitmap(
|
||||||
siegeH->getSiegeName(it->first.first + 2, curInt->cb->battleGetWallState(it->first.first)) );
|
siegeH->getSiegeName(it->first.first + 2, curInt->cb->battleGetWallState(it->first.first)) );
|
||||||
}
|
}
|
||||||
waitForAnims();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::battleFinished(const BattleResult& br)
|
void CBattleInterface::battleFinished(const BattleResult& br)
|
||||||
@ -1233,10 +1231,6 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
|
|||||||
{
|
{
|
||||||
const CSpell &spell = *CGI->spellh->spells[sc->id];
|
const CSpell &spell = *CGI->spellh->spells[sc->id];
|
||||||
|
|
||||||
//spell opening battle is cast when no stack is active
|
|
||||||
if(sc->castedByHero && ( activeStack == nullptr || sc->side == !activeStack->attackerOwned) )
|
|
||||||
bSpell->block(true);
|
|
||||||
|
|
||||||
std::vector< std::string > anims; //for magic arrow and ice bolt
|
std::vector< std::string > anims; //for magic arrow and ice bolt
|
||||||
|
|
||||||
if (vstd::contains(CCS->soundh->spellSounds, &spell))
|
if (vstd::contains(CCS->soundh->spellSounds, &spell))
|
||||||
@ -1658,6 +1652,8 @@ void CBattleInterface::setActiveStack(const CStack * stack)
|
|||||||
|
|
||||||
if (activeStack) // update UI
|
if (activeStack) // update UI
|
||||||
creAnims[activeStack->ID]->setBorderColor(AnimationControls::getGoldBorder());
|
creAnims[activeStack->ID]->setBorderColor(AnimationControls::getGoldBorder());
|
||||||
|
|
||||||
|
blockUI(activeStack == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::setHoveredStack(const CStack * stack)
|
void CBattleInterface::setHoveredStack(const CStack * stack)
|
||||||
@ -1693,16 +1689,6 @@ void CBattleInterface::activateStack()
|
|||||||
|
|
||||||
queue->update();
|
queue->update();
|
||||||
redrawBackgroundWithHexes(activeStack);
|
redrawBackgroundWithHexes(activeStack);
|
||||||
bWait->block(s->waited() || tacticsMode); //block waiting button if stack has been already waiting
|
|
||||||
|
|
||||||
//block cast spell button if hero doesn't have a spellbook
|
|
||||||
ESpellCastProblem::ESpellCastProblem spellcastingProblem;
|
|
||||||
bool canCastSpells = curInt->cb->battleCanCastSpell(&spellcastingProblem);
|
|
||||||
bSpell->block(!canCastSpells && spellcastingProblem != ESpellCastProblem::MAGIC_IS_BLOCKED); //if magic is blocked, we leave button active, so the message can be displayed (cf bug #97)
|
|
||||||
bSurrender->block((curInt == attackerInt ? defendingHeroInstance : attackingHeroInstance) == nullptr);
|
|
||||||
bFlee->block(!curInt->cb->battleCanFlee());
|
|
||||||
bSurrender->block(curInt->cb->battleGetSurrenderCost() < 0);
|
|
||||||
|
|
||||||
|
|
||||||
//set casting flag to true if creature can use it to not check it every time
|
//set casting flag to true if creature can use it to not check it every time
|
||||||
const Bonus *spellcaster = s->getBonusLocalFirst(Selector::type(Bonus::SPELLCASTER)),
|
const Bonus *spellcaster = s->getBonusLocalFirst(Selector::type(Bonus::SPELLCASTER)),
|
||||||
@ -1724,9 +1710,6 @@ void CBattleInterface::activateStack()
|
|||||||
|
|
||||||
getPossibleActionsForStack (s);
|
getPossibleActionsForStack (s);
|
||||||
|
|
||||||
if(!pendingAnims.size() && !active)
|
|
||||||
activate();
|
|
||||||
|
|
||||||
GH.fakeMouseMove();
|
GH.fakeMouseMove();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1886,7 +1869,12 @@ void CBattleInterface::endAction(const BattleAction* action)
|
|||||||
if(activeStack && !animsAreDisplayed.get() && pendingAnims.empty() && !active)
|
if(activeStack && !animsAreDisplayed.get() && pendingAnims.empty() && !active)
|
||||||
{
|
{
|
||||||
logGlobal->warnStream() << "Something wrong... interface was deactivated but there is no animation. Reactivating...";
|
logGlobal->warnStream() << "Something wrong... interface was deactivated but there is no animation. Reactivating...";
|
||||||
activate();
|
blockUI(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// block UI if no active stack (e.g. enemy turn);
|
||||||
|
blockUI(activeStack == nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1918,10 +1906,42 @@ void CBattleInterface::showQueue()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CBattleInterface::blockUI(bool on)
|
||||||
|
{
|
||||||
|
ESpellCastProblem::ESpellCastProblem spellcastingProblem;
|
||||||
|
bool canCastSpells = curInt->cb->battleCanCastSpell(&spellcastingProblem);
|
||||||
|
bool canWait = activeStack ? !activeStack->waited() : false;
|
||||||
|
|
||||||
|
bOptions->block(on);
|
||||||
|
bFlee->block(on || !curInt->cb->battleCanFlee());
|
||||||
|
bSurrender->block(on || curInt->cb->battleGetSurrenderCost() < 0);
|
||||||
|
|
||||||
|
// never block autofight button
|
||||||
|
//FIXME: is that correct?
|
||||||
|
bAutofight->block(false); //curInt->isAutoFightOn
|
||||||
|
|
||||||
|
if(tacticsMode && btactEnd && btactNext)
|
||||||
|
{
|
||||||
|
btactNext->block(on);
|
||||||
|
btactEnd->block(on);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bConsoleUp->block(on);
|
||||||
|
bConsoleDown->block(on);
|
||||||
|
}
|
||||||
|
|
||||||
|
//if magic is blocked, we leave button active, so the message can be displayed (cf bug #97)
|
||||||
|
bSpell->block(on || (!canCastSpells && spellcastingProblem != ESpellCastProblem::MAGIC_IS_BLOCKED));
|
||||||
|
bWait->block(on || tacticsMode || !canWait);
|
||||||
|
bDefence->block(on || tacticsMode);
|
||||||
|
}
|
||||||
|
|
||||||
void CBattleInterface::startAction(const BattleAction* action)
|
void CBattleInterface::startAction(const BattleAction* action)
|
||||||
{
|
{
|
||||||
//setActiveStack(nullptr);
|
//setActiveStack(nullptr);
|
||||||
setHoveredStack(nullptr);
|
setHoveredStack(nullptr);
|
||||||
|
blockUI(true);
|
||||||
|
|
||||||
if(action->actionType == Battle::END_TACTIC_PHASE)
|
if(action->actionType == Battle::END_TACTIC_PHASE)
|
||||||
{
|
{
|
||||||
@ -1929,19 +1949,6 @@ void CBattleInterface::startAction(const BattleAction* action)
|
|||||||
menu = BitmapHandler::loadBitmap("CBAR.bmp");
|
menu = BitmapHandler::loadBitmap("CBAR.bmp");
|
||||||
|
|
||||||
graphics->blueToPlayersAdv(menu, curInt->playerID);
|
graphics->blueToPlayersAdv(menu, curInt->playerID);
|
||||||
bDefence->block(false);
|
|
||||||
bWait->block(false);
|
|
||||||
if(active)
|
|
||||||
{
|
|
||||||
if(btactEnd && btactNext) //if the other side had tactics, there are no buttons
|
|
||||||
{
|
|
||||||
btactEnd->deactivate();
|
|
||||||
btactNext->deactivate();
|
|
||||||
bConsoleDown->activate();
|
|
||||||
bConsoleUp->activate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1967,8 +1974,6 @@ void CBattleInterface::startAction(const BattleAction* action)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(active)
|
|
||||||
deactivate();
|
|
||||||
redraw(); // redraw after deactivation, including proper handling of hovered hexes
|
redraw(); // redraw after deactivation, including proper handling of hovered hexes
|
||||||
|
|
||||||
char txt[400];
|
char txt[400];
|
||||||
@ -2030,7 +2035,7 @@ void CBattleInterface::waitForAnims()
|
|||||||
void CBattleInterface::bEndTacticPhase()
|
void CBattleInterface::bEndTacticPhase()
|
||||||
{
|
{
|
||||||
setActiveStack(nullptr);
|
setActiveStack(nullptr);
|
||||||
btactEnd->block(true);
|
blockUI(true);
|
||||||
tacticsMode = false;
|
tacticsMode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3128,7 +3133,9 @@ void CBattleInterface::showProjectiles(SDL_Surface * to)
|
|||||||
// Check if projectile is already visible (shooter animation did the shot)
|
// Check if projectile is already visible (shooter animation did the shot)
|
||||||
if (!it->shotDone)
|
if (!it->shotDone)
|
||||||
{
|
{
|
||||||
if (creAnims[it->stackID]->getCurrentFrame() >= it->animStartDelay)
|
// frame we're waiting for is reached OR animation has already finished
|
||||||
|
if (creAnims[it->stackID]->getCurrentFrame() >= it->animStartDelay ||
|
||||||
|
creAnims[it->stackID]->isShooting() == false)
|
||||||
{
|
{
|
||||||
//at this point projectile should become visible
|
//at this point projectile should become visible
|
||||||
creAnims[it->stackID]->pause(); // pause animation
|
creAnims[it->stackID]->pause(); // pause animation
|
||||||
@ -3197,27 +3204,29 @@ void CBattleInterface::showBattlefieldObjects(SDL_Surface * to)
|
|||||||
{
|
{
|
||||||
showPiecesOfWall(to, hex.walls);
|
showPiecesOfWall(to, hex.walls);
|
||||||
showObstacles(to, hex.obstacles);
|
showObstacles(to, hex.obstacles);
|
||||||
showStacks(to, hex.dead);
|
|
||||||
showAliveStacks(to, hex.alive);
|
showAliveStacks(to, hex.alive);
|
||||||
showBattleEffects(to, hex.effects);
|
showBattleEffects(to, hex.effects);
|
||||||
};
|
};
|
||||||
|
|
||||||
if(attackingHero)
|
if(attackingHero)
|
||||||
attackingHero->show(to);
|
attackingHero->show(to);
|
||||||
|
|
||||||
if(defendingHero)
|
if(defendingHero)
|
||||||
defendingHero->show(to);
|
defendingHero->show(to);
|
||||||
|
|
||||||
BattleObjectsByHex objects = sortObjectsByHex();
|
BattleObjectsByHex objects = sortObjectsByHex();
|
||||||
|
|
||||||
|
// dead stacks should be blit first
|
||||||
|
showStacks(to, objects.beforeAll.dead);
|
||||||
|
for( auto & data : objects.hex )
|
||||||
|
showStacks(to, data.dead);
|
||||||
|
showStacks(to, objects.afterAll.dead);
|
||||||
|
|
||||||
// display objects that must be blit before anything else (e.g. topmost walls)
|
// display objects that must be blit before anything else (e.g. topmost walls)
|
||||||
showHexEntry(objects.beforeAll);
|
showHexEntry(objects.beforeAll);
|
||||||
|
|
||||||
// actual blit of most of objects, hex by hex
|
// actual blit of most of objects, hex by hex
|
||||||
// NOTE: row-by-row blitting may be a better approach
|
// NOTE: row-by-row blitting may be a better approach
|
||||||
for( auto & data : objects.hex )
|
for( auto & data : objects.hex )
|
||||||
showHexEntry(data);
|
showHexEntry(data);
|
||||||
|
|
||||||
// objects that must be blit *after* everything else - e.g. bottom tower or some spell effects
|
// objects that must be blit *after* everything else - e.g. bottom tower or some spell effects
|
||||||
showHexEntry(objects.afterAll);
|
showHexEntry(objects.afterAll);
|
||||||
}
|
}
|
||||||
@ -3412,7 +3421,7 @@ BattleObjectsByHex CBattleInterface::sortObjectsByHex()
|
|||||||
|
|
||||||
if(!creAnims[stack->ID]->isDead())
|
if(!creAnims[stack->ID]->isDead())
|
||||||
{
|
{
|
||||||
if (creAnims[stack->ID]->getType() != CCreatureAnim::MOVING)
|
if (!creAnims[stack->ID]->isMoving())
|
||||||
sorted.hex[stack->position].alive.push_back(stack);
|
sorted.hex[stack->position].alive.push_back(stack);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -3500,11 +3509,9 @@ void CBattleInterface::updateBattleAnimations()
|
|||||||
|
|
||||||
if(preSize > 0 && pendingAnims.size() == 0)
|
if(preSize > 0 && pendingAnims.size() == 0)
|
||||||
{
|
{
|
||||||
//action finished, restore the interface
|
|
||||||
if(!active)
|
|
||||||
activate();
|
|
||||||
|
|
||||||
//anims ended
|
//anims ended
|
||||||
|
blockUI(activeStack == nullptr);
|
||||||
|
|
||||||
animsAreDisplayed.setn(false);
|
animsAreDisplayed.setn(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,7 +218,6 @@ private:
|
|||||||
void showHighlightedHex(SDL_Surface * to, BattleHex hex);
|
void showHighlightedHex(SDL_Surface * to, BattleHex hex);
|
||||||
void showInterface(SDL_Surface * to);
|
void showInterface(SDL_Surface * to);
|
||||||
|
|
||||||
|
|
||||||
void showBattlefieldObjects(SDL_Surface * to);
|
void showBattlefieldObjects(SDL_Surface * to);
|
||||||
|
|
||||||
void showAliveStacks(SDL_Surface * to, std::vector<const CStack *> stacks);
|
void showAliveStacks(SDL_Surface * to, std::vector<const CStack *> stacks);
|
||||||
@ -265,6 +264,10 @@ public:
|
|||||||
|
|
||||||
const BattleResult * bresult; //result of a battle; if non-zero then display when all animations end
|
const BattleResult * bresult; //result of a battle; if non-zero then display when all animations end
|
||||||
|
|
||||||
|
// block all UI elements, e.g. during enemy turn
|
||||||
|
// unlike activate/deactivate this method will correctly grey-out all elements
|
||||||
|
void blockUI(bool on);
|
||||||
|
|
||||||
//button handle funcs:
|
//button handle funcs:
|
||||||
void bOptionsf();
|
void bOptionsf();
|
||||||
void bSurrenderf();
|
void bSurrenderf();
|
||||||
|
@ -429,6 +429,20 @@ bool CCreatureAnimation::isIdle() const
|
|||||||
|| getType() == CCreatureAnim::MOUSEON;
|
|| getType() == CCreatureAnim::MOUSEON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CCreatureAnimation::isMoving() const
|
||||||
|
{
|
||||||
|
return getType() == CCreatureAnim::MOVE_START
|
||||||
|
|| getType() == CCreatureAnim::MOVING
|
||||||
|
|| getType() == CCreatureAnim::MOVE_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCreatureAnimation::isShooting() const
|
||||||
|
{
|
||||||
|
return getType() == CCreatureAnim::SHOOT_UP
|
||||||
|
|| getType() == CCreatureAnim::SHOOT_FRONT
|
||||||
|
|| getType() == CCreatureAnim::SHOOT_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
void CCreatureAnimation::pause()
|
void CCreatureAnimation::pause()
|
||||||
{
|
{
|
||||||
speed = 0;
|
speed = 0;
|
||||||
|
@ -137,4 +137,6 @@ public:
|
|||||||
//helpers. TODO: move them somewhere else
|
//helpers. TODO: move them somewhere else
|
||||||
bool isDead() const;
|
bool isDead() const;
|
||||||
bool isIdle() const;
|
bool isIdle() const;
|
||||||
|
bool isMoving() const;
|
||||||
|
bool isShooting() const;
|
||||||
};
|
};
|
||||||
|
@ -1931,8 +1931,10 @@ std::set<const CStack*> CBattleInfoCallback::getAffectedCreatures(const CSpell *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
int targetsOnLevel[4] = {4, 4, 5, 5};
|
||||||
|
|
||||||
BattleHex lightningHex = destinationTile;
|
BattleHex lightningHex = destinationTile;
|
||||||
for (int i = 0; i < 5; ++i) //TODO: depends on spell school level
|
for (int i = 0; i < targetsOnLevel[skillLevel]; ++i)
|
||||||
{
|
{
|
||||||
auto stack = battleGetStackByPos (lightningHex, true);
|
auto stack = battleGetStackByPos (lightningHex, true);
|
||||||
if (!stack)
|
if (!stack)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user