1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-05 00:49:09 +02:00

Improved creature casting GUI.

* "F" is new hotkey for creature spells
* creature spells now have lowest priority unless F pressed
* creatures can cast NO_LOCATION spells (only with hotkey)
This commit is contained in:
AlexVinS
2016-10-15 23:50:12 +03:00
parent 4876cc178d
commit b256c4c36d
2 changed files with 94 additions and 20 deletions

View File

@ -583,7 +583,11 @@ void CBattleInterface::keyPressed(const SDL_KeyboardEvent & key)
showQueue(); showQueue();
} }
else if(key.keysym.sym == SDLK_ESCAPE && spellDestSelectMode) else if(key.keysym.sym == SDLK_f && key.state == SDL_PRESSED)
{
enterCreatureCastingMode();
}
else if(key.keysym.sym == SDLK_ESCAPE)
{ {
endCastingSpell(); endCastingSpell();
} }
@ -773,7 +777,7 @@ void CBattleInterface::setBattleCursor(const int myNumber)
void CBattleInterface::clickRight(tribool down, bool previousState) void CBattleInterface::clickRight(tribool down, bool previousState)
{ {
if(!down && spellDestSelectMode) if(!down)
{ {
endCastingSpell(); endCastingSpell();
} }
@ -1596,15 +1600,15 @@ void CBattleInterface::activateStack()
creatureSpellToCast = -1; creatureSpellToCast = -1;
} }
getPossibleActionsForStack (s); getPossibleActionsForStack(s, false);
GH.fakeMouseMove(); GH.fakeMouseMove();
} }
void CBattleInterface::endCastingSpell() void CBattleInterface::endCastingSpell()
{ {
assert(spellDestSelectMode); if(spellDestSelectMode)
{
vstd::clear_pointer(spellToCast); vstd::clear_pointer(spellToCast);
sp = nullptr; sp = nullptr;
@ -1613,12 +1617,67 @@ void CBattleInterface::endCastingSpell()
if (activeStack) if (activeStack)
{ {
getPossibleActionsForStack (activeStack); //restore actions after they were cleared getPossibleActionsForStack(activeStack, false); //restore actions after they were cleared
myTurn = true; myTurn = true;
} }
}
else
{
if (activeStack)
{
getPossibleActionsForStack(activeStack, false);
GH.fakeMouseMove();
}
}
} }
void CBattleInterface::getPossibleActionsForStack(const CStack * stack) void CBattleInterface::enterCreatureCastingMode()
{
//silently check for possible errors
if(!myTurn)
return;
if(tacticsMode)
return;
//hero is casting a spell
if(spellDestSelectMode)
return;
if(!activeStack)
return;
if(!stackCanCastSpell)
return;
//random spellcaster
if(creatureSpellToCast == -1)
return;
if(vstd::contains(possibleActions, NO_LOCATION))
{
const ISpellCaster * caster = activeStack;
const CSpell * spell = SpellID(creatureSpellToCast).toSpell();
const bool isCastingPossible = (curInt->cb->battleCanCastThisSpellHere(caster, spell, ECastingMode::CREATURE_ACTIVE_CASTING, BattleHex::INVALID) == ESpellCastProblem::OK);
if(isCastingPossible)
{
myTurn = false;
giveCommand(Battle::MONSTER_SPELL, BattleHex::INVALID, activeStack->ID, creatureSpellToCast);
selectedStack = nullptr;
CCS->curh->changeGraphic(ECursor::COMBAT, ECursor::COMBAT_POINTER);
}
}
else
{
getPossibleActionsForStack(activeStack, true);
GH.fakeMouseMove();
}
}
void CBattleInterface::getPossibleActionsForStack(const CStack * stack, const bool forceCast)
{ {
possibleActions.clear(); possibleActions.clear();
if (tacticsMode) if (tacticsMode)
@ -1628,6 +1687,7 @@ void CBattleInterface::getPossibleActionsForStack(const CStack * stack)
} }
else else
{ {
PossibleActions notPriority = INVALID;
//first action will be prioritized over later ones //first action will be prioritized over later ones
if (stack->casts) //TODO: check for battlefield effects that prevent casting? if (stack->casts) //TODO: check for battlefield effects that prevent casting?
{ {
@ -1637,10 +1697,16 @@ void CBattleInterface::getPossibleActionsForStack(const CStack * stack)
{ {
const CSpell * spell = SpellID(creatureSpellToCast).toSpell(); const CSpell * spell = SpellID(creatureSpellToCast).toSpell();
PossibleActions act = getCasterAction(spell, stack, ECastingMode::CREATURE_ACTIVE_CASTING); PossibleActions act = getCasterAction(spell, stack, ECastingMode::CREATURE_ACTIVE_CASTING);
if(act == NO_LOCATION)
logGlobal->error("NO_LOCATION action target is not yet supported for creatures"); if (forceCast)
else {
//forced action to be only one possible
possibleActions.push_back(act); possibleActions.push_back(act);
return;
}
else
//if cast is not forced, cast action will have lowest priority
notPriority = act;
} }
} }
if (stack->hasBonusOfType (Bonus::RANDOM_SPELLCASTER)) if (stack->hasBonusOfType (Bonus::RANDOM_SPELLCASTER))
@ -1663,6 +1729,9 @@ void CBattleInterface::getPossibleActionsForStack(const CStack * stack)
possibleActions.push_back (CATAPULT); possibleActions.push_back (CATAPULT);
if (stack->hasBonusOfType (Bonus::HEALER)) if (stack->hasBonusOfType (Bonus::HEALER))
possibleActions.push_back (HEAL); possibleActions.push_back (HEAL);
if (notPriority != INVALID)
possibleActions.push_back(notPriority);
} }
} }
@ -2004,6 +2073,8 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
localActions.clear(); localActions.clear();
illegalActions.clear(); illegalActions.clear();
const bool forcedAction = possibleActions.size() == 1;
for (PossibleActions action : possibleActions) for (PossibleActions action : possibleActions)
{ {
bool legalAction = false; //this action is legal and can be performed bool legalAction = false; //this action is legal and can be performed
@ -2125,7 +2196,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
} }
if (legalAction) if (legalAction)
localActions.push_back (action); localActions.push_back (action);
else if (notLegal) else if (notLegal || forcedAction)
illegalActions.push_back (action); illegalActions.push_back (action);
} }
illegalAction = INVALID; //clear it in first place illegalAction = INVALID; //clear it in first place

View File

@ -174,9 +174,12 @@ private:
void requestAutofightingAIToTakeAction(); void requestAutofightingAIToTakeAction();
void getPossibleActionsForStack (const CStack * stack); //called when stack gets its turn void getPossibleActionsForStack (const CStack * stack, const bool forceCast); //called when stack gets its turn
void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled) void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled)
//force active stack to cast a spell if possible
void enterCreatureCastingMode();
void printConsoleAttacked(const CStack * defender, int dmg, int killed, const CStack * attacker, bool Multiple); void printConsoleAttacked(const CStack * defender, int dmg, int killed, const CStack * attacker, bool Multiple);
std::list<ProjectileInfo> projectiles; //projectiles flying on battlefield std::list<ProjectileInfo> projectiles; //projectiles flying on battlefield