1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +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();
}
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();
}
@ -773,7 +777,7 @@ void CBattleInterface::setBattleCursor(const int myNumber)
void CBattleInterface::clickRight(tribool down, bool previousState)
{
if(!down && spellDestSelectMode)
if(!down)
{
endCastingSpell();
}
@ -1596,29 +1600,84 @@ void CBattleInterface::activateStack()
creatureSpellToCast = -1;
}
getPossibleActionsForStack (s);
getPossibleActionsForStack(s, false);
GH.fakeMouseMove();
}
void CBattleInterface::endCastingSpell()
{
assert(spellDestSelectMode);
vstd::clear_pointer(spellToCast);
sp = nullptr;
spellDestSelectMode = false;
CCS->curh->changeGraphic(ECursor::COMBAT, ECursor::COMBAT_POINTER);
if (activeStack)
if(spellDestSelectMode)
{
getPossibleActionsForStack (activeStack); //restore actions after they were cleared
myTurn = true;
vstd::clear_pointer(spellToCast);
sp = nullptr;
spellDestSelectMode = false;
CCS->curh->changeGraphic(ECursor::COMBAT, ECursor::COMBAT_POINTER);
if (activeStack)
{
getPossibleActionsForStack(activeStack, false); //restore actions after they were cleared
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();
if (tacticsMode)
@ -1628,6 +1687,7 @@ void CBattleInterface::getPossibleActionsForStack(const CStack * stack)
}
else
{
PossibleActions notPriority = INVALID;
//first action will be prioritized over later ones
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();
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");
else
if (forceCast)
{
//forced action to be only one possible
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))
@ -1663,6 +1729,9 @@ void CBattleInterface::getPossibleActionsForStack(const CStack * stack)
possibleActions.push_back (CATAPULT);
if (stack->hasBonusOfType (Bonus::HEALER))
possibleActions.push_back (HEAL);
if (notPriority != INVALID)
possibleActions.push_back(notPriority);
}
}
@ -2004,6 +2073,8 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
localActions.clear();
illegalActions.clear();
const bool forcedAction = possibleActions.size() == 1;
for (PossibleActions action : possibleActions)
{
bool legalAction = false; //this action is legal and can be performed
@ -2125,7 +2196,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
}
if (legalAction)
localActions.push_back (action);
else if (notLegal)
else if (notLegal || forcedAction)
illegalActions.push_back (action);
}
illegalAction = INVALID; //clear it in first place

View File

@ -174,9 +174,12 @@ private:
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)
//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);
std::list<ProjectileInfo> projectiles; //projectiles flying on battlefield