1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

Spellcasters UI now shares handling with hero spellcasting

This commit is contained in:
Ivan Savenko 2023-01-29 14:27:57 +02:00
parent dbbbba5f2d
commit c3b79c786b
4 changed files with 88 additions and 67 deletions

View File

@ -86,7 +86,7 @@ void BattleActionsController::enterCreatureCastingMode()
if (vstd::contains(possibleActions, PossiblePlayerBattleAction::NO_LOCATION))
{
const spells::Caster * caster = owner.stacksController->getActiveStack();
const CSpell * spell = getStackSpellToCast(BattleHex::INVALID);
const CSpell * spell = getStackSpellToCast();
spells::Target target;
target.emplace_back();
@ -126,8 +126,8 @@ std::vector<PossiblePlayerBattleAction> BattleActionsController::getPossibleActi
{
BattleClientInterfaceData data; //hard to get rid of these things so for now they're required data to pass
if (getStackSpellToCast(BattleHex::INVALID))
data.creatureSpellToCast = getStackSpellToCast(BattleHex::INVALID)->getId();
if (getStackSpellToCast())
data.creatureSpellToCast = getStackSpellToCast()->getId();
else
data.creatureSpellToCast = SpellID::NONE;
@ -175,6 +175,8 @@ void BattleActionsController::reorderPossibleActionsPriority(const CStack * stac
return 10; break;
case PossiblePlayerBattleAction::CREATURE_INFO:
return 11; break;
case PossiblePlayerBattleAction::TELEPORT:
return 12; break;
default:
assert(0);
return 200; break;
@ -223,7 +225,7 @@ const CSpell * BattleActionsController::getHeroSpellToCast( ) const
return nullptr;
}
const CSpell * BattleActionsController::getStackSpellToCast( BattleHex targetHex ) const
const CSpell * BattleActionsController::getStackSpellToCast( ) const
{
if (isActiveStackSpellcaster())
return creatureSpellToCast;
@ -231,11 +233,11 @@ const CSpell * BattleActionsController::getStackSpellToCast( BattleHex targetHex
return nullptr;
}
const CSpell * BattleActionsController::getAnySpellToCast( BattleHex targetHex ) const
const CSpell * BattleActionsController::getCurrentSpell( ) const
{
if (getHeroSpellToCast())
return getHeroSpellToCast();
return getStackSpellToCast(targetHex);
return getStackSpellToCast();
}
const CStack * BattleActionsController::getStackForHex(BattleHex hoveredHex)
@ -364,10 +366,10 @@ std::string BattleActionsController::actionGetStatusMessage(PossiblePlayerBattle
}
case PossiblePlayerBattleAction::AIMED_SPELL_CREATURE:
return boost::str(boost::format(CGI->generaltexth->allTexts[27]) % getAnySpellToCast(targetHex)->getNameTranslated() % targetStack->getName()); //Cast %s on %s
return boost::str(boost::format(CGI->generaltexth->allTexts[27]) % getCurrentSpell()->getNameTranslated() % targetStack->getName()); //Cast %s on %s
case PossiblePlayerBattleAction::ANY_LOCATION:
return boost::str(boost::format(CGI->generaltexth->allTexts[26]) % getAnySpellToCast(targetHex)->getNameTranslated()); //Cast %s
return boost::str(boost::format(CGI->generaltexth->allTexts[26]) % getCurrentSpell()->getNameTranslated()); //Cast %s
case PossiblePlayerBattleAction::RANDOM_GENIE_SPELL: //we assume that teleport / sacrifice will never be available as random spell
return boost::str(boost::format(CGI->generaltexth->allTexts[301]) % targetStack->getName()); //Cast a spell on %
@ -382,7 +384,7 @@ std::string BattleActionsController::actionGetStatusMessage(PossiblePlayerBattle
return (boost::format(CGI->generaltexth->allTexts[549]) % targetStack->getName()).str(); //sacrifice the %s
case PossiblePlayerBattleAction::FREE_LOCATION:
return boost::str(boost::format(CGI->generaltexth->allTexts[26]) % getAnySpellToCast(targetHex)->getNameTranslated()); //Cast %s
return boost::str(boost::format(CGI->generaltexth->allTexts[26]) % getCurrentSpell()->getNameTranslated()); //Cast %s
case PossiblePlayerBattleAction::HEAL:
return (boost::format(CGI->generaltexth->allTexts[419]) % targetStack->getName()).str(); //Apply first aid to the %s
@ -412,7 +414,7 @@ std::string BattleActionsController::actionGetStatusMessageBlocked(PossiblePlaye
return CGI->generaltexth->allTexts[543]; //choose army to sacrifice
break;
case PossiblePlayerBattleAction::FREE_LOCATION:
return boost::str(boost::format(CGI->generaltexth->allTexts[181]) % getAnySpellToCast(targetHex)->getNameTranslated()); //No room to place %s here
return boost::str(boost::format(CGI->generaltexth->allTexts[181]) % getCurrentSpell()->getNameTranslated()); //No room to place %s here
break;
default:
return "";
@ -570,25 +572,27 @@ void BattleActionsController::actionRealize(PossiblePlayerBattleAction action, B
{
if (action == PossiblePlayerBattleAction::AIMED_SPELL_CREATURE )
{
if (getAnySpellToCast(targetHex)->id == SpellID::SACRIFICE)
if (getCurrentSpell()->id == SpellID::SACRIFICE)
{
heroSpellToCast->aimToHex(targetHex);
possibleActions.push_back(PossiblePlayerBattleAction::SACRIFICE);
owner.stacksController->setSelectedStack(targetStack);
return;
}
if (getAnySpellToCast(targetHex)->id == SpellID::TELEPORT)
if (getCurrentSpell()->id == SpellID::TELEPORT)
{
heroSpellToCast->aimToUnit(targetStack);
possibleActions.push_back(PossiblePlayerBattleAction::TELEPORT);
owner.stacksController->setSelectedStack(targetStack);
return;
}
}
if (!spellcastingModeActive())
{
if (getStackSpellToCast(targetHex))
if (getStackSpellToCast())
{
owner.giveCommand(EActionType::MONSTER_SPELL, targetHex, getStackSpellToCast(targetHex)->getId());
owner.giveCommand(EActionType::MONSTER_SPELL, targetHex, getStackSpellToCast()->getId());
}
else //unknown random spell
{
@ -703,7 +707,6 @@ void BattleActionsController::tryActivateStackSpellcasting(const CStack *casterS
if(casterStack->canCast() && spellcaster)
{
// faerie dragon can cast only one, randomly selected spell until their next move
//TODO: what if creature can cast BOTH random genie spell and aimed spell?
//TODO: faerie dragon type spell should be selected by server
creatureSpellToCast = owner.curInt->cb->battleGetRandomStackSpell(CRandomGenerator::getDefault(), casterStack, CBattleInfoCallback::RANDOM_AIMED).toSpell();
}
@ -715,12 +718,20 @@ const spells::Caster * BattleActionsController::getCurrentSpellcaster() const
return owner.getActiveHero();
else
return owner.stacksController->getActiveStack();
}
spells::Mode BattleActionsController::getCurrentCastMode() const
{
if (heroSpellToCast)
return spells::Mode::HERO;
else
return spells::Mode::CREATURE_ACTIVE;
}
bool BattleActionsController::isCastingPossibleHere(const CStack *casterStack, const CStack *targetStack, BattleHex targetHex)
{
auto currentSpell = getAnySpellToCast(targetHex);
auto currentSpell = getCurrentSpell();
assert(currentSpell);
if (!currentSpell)
@ -791,6 +802,24 @@ bool BattleActionsController::spellcastingModeActive() const
return heroSpellToCast != nullptr;;
}
bool BattleActionsController::currentActionSpellcasting(BattleHex hoveredHex)
{
if (heroSpellToCast)
return true;
if (!owner.stacksController->getActiveStack())
return false;
auto action = selectAction(hoveredHex);
return
action == PossiblePlayerBattleAction::ANY_LOCATION ||
action == PossiblePlayerBattleAction::NO_LOCATION ||
action == PossiblePlayerBattleAction::FREE_LOCATION ||
action == PossiblePlayerBattleAction::AIMED_SPELL_CREATURE ||
action == PossiblePlayerBattleAction::OBSTACLE;
}
const std::vector<PossiblePlayerBattleAction> & BattleActionsController::getPossibleActions() const
{
return possibleActions;

View File

@ -16,6 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN
class BattleAction;
namespace spells {
class Caster;
enum class Mode;
}
VCMI_LIB_NAMESPACE_END
@ -63,13 +64,21 @@ class BattleActionsController
PossiblePlayerBattleAction selectAction(BattleHex myNumber);
const CStack * getStackForHex(BattleHex myNumber);
const CStack * getStackForHex(BattleHex myNumber) ;
/// attempts to initialize spellcasting action for stack
/// will silently return if stack is not a spellcaster
void tryActivateStackSpellcasting(const CStack *casterStack);
const spells::Caster * getCurrentSpellcaster() const;
/// returns spell that is currently being cast by hero or nullptr if none
const CSpell * getHeroSpellToCast() const;
/// if current stack is spellcaster, returns spell being cast, or null othervice
const CSpell * getStackSpellToCast( ) const;
/// returns true if current stack is a spellcaster
bool isActiveStackSpellcaster() const;
public:
BattleActionsController(BattleInterface & owner);
@ -79,6 +88,12 @@ public:
/// returns true if UI is currently in target selection mode
bool spellcastingModeActive() const;
/// returns true if one of the following is true:
/// - we are casting spell by hero
/// - we are casting spell by creature in targeted mode (F hotkey)
/// - current creature is spellcaster and preferred action for current hex is spellcast
bool currentActionSpellcasting(BattleHex hoveredHex);
/// enter targeted spellcasting mode for creature, e.g. via "F" hotkey
void enterCreatureCastingMode();
@ -94,15 +109,9 @@ public:
/// performs action according to selected hex
void onHexClicked(BattleHex clickedHex);
/// returns spell that is currently being cast by hero or nullptr if none
const CSpell * getHeroSpellToCast() const;
/// if current stack is spellcaster, returns spell being cast, or null othervice
const CSpell * getStackSpellToCast( BattleHex targetHex ) const;
const CSpell * getAnySpellToCast( BattleHex targetHex ) const;
/// returns true if current stack is a spellcaster
bool isActiveStackSpellcaster() const;
const spells::Caster * getCurrentSpellcaster() const;
const CSpell * getCurrentSpell() const;
spells::Mode getCurrentCastMode() const;
/// methods to work with array of possible actions, needed to control special creatures abilities
const std::vector<PossiblePlayerBattleAction> & getPossibleActions() const;

View File

@ -230,25 +230,15 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesSpellRange()
if(!settings["battle"]["mouseShadow"].Bool())
return result;
const spells::Caster *caster = nullptr;
const CSpell *spell = nullptr;
spells::Mode mode = spells::Mode::HERO;
if(owner.actionsController->spellcastingModeActive())//hero casts spell
{
spell = owner.actionsController->getHeroSpellToCast();
caster = owner.getActiveHero();
}
else if(owner.actionsController->getStackSpellToCast(hoveredHex) != nullptr)//stack casts spell
{
spell = owner.actionsController->getStackSpellToCast(hoveredHex);
caster = owner.stacksController->getActiveStack();
mode = spells::Mode::CREATURE_ACTIVE;
}
if(caster && spell) //when casting spell
{
const spells::Caster *caster = nullptr;
const CSpell *spell = nullptr;
spells::Mode mode = owner.actionsController->getCurrentCastMode();
spell = owner.actionsController->getCurrentSpell();
caster = owner.actionsController->getCurrentSpellcaster();
if(caster && spell) //when casting spell
{
// printing shaded hex(es)
spells::BattleCast event(owner.curInt->cb.get(), caster, mode, spell);
auto shaded = spell->battleMechanics(&event)->rangeInHexes(hoveredHex);
@ -307,13 +297,16 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesMovementTarget()
void BattleFieldController::showHighlightedHexes(Canvas & canvas)
{
std::set<BattleHex> hoveredStack = getHighlightedHexesStackRange();
std::set<BattleHex> hoveredSpell = getHighlightedHexesSpellRange();
std::set<BattleHex> hoveredMove = getHighlightedHexesMovementTarget();
auto const & hoveredMouse = owner.actionsController->spellcastingModeActive() ? hoveredSpell : hoveredMove;
for(int b=0; b<GameConstants::BFIELD_SIZE; ++b)
{
std::set<BattleHex> hoveredSpell = getHighlightedHexesSpellRange();
std::set<BattleHex> hoveredMove = getHighlightedHexesMovementTarget();
if (getHoveredHex() == BattleHex::INVALID)
return;
auto const & hoveredMouse = owner.actionsController->currentActionSpellcasting(getHoveredHex()) ? hoveredSpell : hoveredMove;
for(int b=0; b<GameConstants::BFIELD_SIZE; ++b)
{
bool stack = hoveredStack.count(b);
bool mouse = hoveredMouse.count(b);

View File

@ -871,21 +871,11 @@ std::vector<const CStack *> BattleStacksController::selectHoveredStacks()
const spells::Caster *caster = nullptr;
const CSpell *spell = nullptr;
spells::Mode mode = spells::Mode::HERO;
spells::Mode mode = owner.actionsController->getCurrentCastMode();
spell = owner.actionsController->getCurrentSpell();
caster = owner.actionsController->getCurrentSpellcaster();
if(owner.actionsController->spellcastingModeActive())//hero casts spell
{
spell = owner.actionsController->getHeroSpellToCast();
caster = owner.getActiveHero();
}
else if(owner.actionsController->getStackSpellToCast(hoveredHex) != nullptr)//stack casts spell
{
spell = owner.actionsController->getStackSpellToCast(hoveredHex);
caster = owner.stacksController->getActiveStack();
mode = spells::Mode::CREATURE_ACTIVE;
}
if(caster && spell) //when casting spell
if(caster && spell && owner.actionsController->currentActionSpellcasting(hoveredHex) ) //when casting spell
{
spells::Target target;
target.emplace_back(hoveredHex);