mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-12 02:28:11 +02:00
- No battle actions will be available during tactics phase
- Fixed moving stacks during tactics - Fixed Genie spell targeting - Fixed AI getting stuck at Tree of Knowledge when no resources
This commit is contained in:
parent
82f3bc8135
commit
d6873d7570
@ -2666,6 +2666,12 @@ bool shouldVisit (const CGHeroInstance * h, const CGObjectInstance * obj)
|
|||||||
case Obj::LIBRARY_OF_ENLIGHTENMENT:
|
case Obj::LIBRARY_OF_ENLIGHTENMENT:
|
||||||
if (h->level < 12)
|
if (h->level < 12)
|
||||||
return false;
|
return false;
|
||||||
|
case Obj::TREE_OF_KNOWLEDGE:
|
||||||
|
{
|
||||||
|
TResources myRes = ai->myCb->getResourceAmount();
|
||||||
|
if (myRes[Res::GOLD] - GOLD_RESERVE < 2000 || myRes[Res::GEMS] < 10)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1941,14 +1941,9 @@ void CBattleInterface::activateStack()
|
|||||||
{
|
{
|
||||||
stackCanCastSpell = true;
|
stackCanCastSpell = true;
|
||||||
if(randomSpellcaster)
|
if(randomSpellcaster)
|
||||||
|
creatureSpellToCast = -1;
|
||||||
|
else
|
||||||
creatureSpellToCast = curInt->cb->battleGetRandomStackSpell(s, CBattleInfoCallback::RANDOM_AIMED); //faerie dragon can cast only one spell until their next move
|
creatureSpellToCast = curInt->cb->battleGetRandomStackSpell(s, CBattleInfoCallback::RANDOM_AIMED); //faerie dragon can cast only one spell until their next move
|
||||||
else
|
|
||||||
creatureSpellToCast = spellcaster->subtype;
|
|
||||||
|
|
||||||
if(creatureSpellToCast < 0) //TODO proper way of detecting casters of positive spells
|
|
||||||
spellSelMode = FRIENDLY_CREATURE_SPELL;
|
|
||||||
else
|
|
||||||
spellSelMode = selectionTypeByPositiveness(*CGI->spellh->spells[creatureSpellToCast]);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1996,63 +1991,69 @@ void CBattleInterface::endCastingSpell()
|
|||||||
void CBattleInterface::getPossibleActionsForStack(const CStack * stack)
|
void CBattleInterface::getPossibleActionsForStack(const CStack * stack)
|
||||||
{
|
{
|
||||||
possibleActions.clear();
|
possibleActions.clear();
|
||||||
//first action will be prioritized over later ones
|
if (tacticsMode)
|
||||||
if (stack->casts) //TODO: check for battlefield effects that prevent casting?
|
|
||||||
{
|
{
|
||||||
if (stack->hasBonusOfType (Bonus::SPELLCASTER))
|
possibleActions += MOVE_TACTICS, CHOOSE_TACTICS_STACK;
|
||||||
{
|
|
||||||
//TODO: poll possible spells
|
|
||||||
const CSpell * spell;
|
|
||||||
BonusList spellBonuses = *stack->getBonuses (Selector::type(Bonus::SPELLCASTER));
|
|
||||||
BOOST_FOREACH (Bonus * spellBonus, spellBonuses)
|
|
||||||
{
|
|
||||||
spell = CGI->spellh->spells[spellBonus->subtype];
|
|
||||||
if (spell->isRisingSpell())
|
|
||||||
{
|
|
||||||
possibleActions.push_back (RISING_SPELL);
|
|
||||||
}
|
|
||||||
//possibleActions.push_back (NO_LOCATION);
|
|
||||||
//possibleActions.push_back (ANY_LOCATION);
|
|
||||||
//possibleActions.push_back (OTHER_SPELL);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (spellBonus->subtype)
|
|
||||||
{
|
|
||||||
case Spells::REMOVE_OBSTACLE:
|
|
||||||
possibleActions.push_back (OBSTACLE);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
possibleActions.push_back (selectionTypeByPositiveness (*spell));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
std::sort(possibleActions.begin(), possibleActions.end());
|
|
||||||
auto it = std::unique (possibleActions.begin(), possibleActions.end());
|
|
||||||
possibleActions.erase (it, possibleActions.end());
|
|
||||||
}
|
|
||||||
if (stack->hasBonusOfType (Bonus::RANDOM_SPELLCASTER))
|
|
||||||
possibleActions.push_back (RANDOM_GENIE_SPELL);
|
|
||||||
if (stack->hasBonusOfType (Bonus::DAEMON_SUMMONING))
|
|
||||||
possibleActions.push_back (RISE_DEMONS);
|
|
||||||
}
|
}
|
||||||
if (stack->shots && stack->hasBonusOfType (Bonus::SHOOTER))
|
else
|
||||||
possibleActions.push_back (SHOOT);
|
{
|
||||||
if (stack->hasBonusOfType (Bonus::RETURN_AFTER_STRIKE))
|
//first action will be prioritized over later ones
|
||||||
possibleActions.push_back (ATTACK_AND_RETURN);
|
if (stack->casts) //TODO: check for battlefield effects that prevent casting?
|
||||||
|
{
|
||||||
|
if (stack->hasBonusOfType (Bonus::SPELLCASTER))
|
||||||
|
{
|
||||||
|
//TODO: poll possible spells
|
||||||
|
const CSpell * spell;
|
||||||
|
BonusList spellBonuses = *stack->getBonuses (Selector::type(Bonus::SPELLCASTER));
|
||||||
|
BOOST_FOREACH (Bonus * spellBonus, spellBonuses)
|
||||||
|
{
|
||||||
|
spell = CGI->spellh->spells[spellBonus->subtype];
|
||||||
|
if (spell->isRisingSpell())
|
||||||
|
{
|
||||||
|
possibleActions.push_back (RISING_SPELL);
|
||||||
|
}
|
||||||
|
//possibleActions.push_back (NO_LOCATION);
|
||||||
|
//possibleActions.push_back (ANY_LOCATION);
|
||||||
|
//possibleActions.push_back (OTHER_SPELL);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (spellBonus->subtype)
|
||||||
|
{
|
||||||
|
case Spells::REMOVE_OBSTACLE:
|
||||||
|
possibleActions.push_back (OBSTACLE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
possibleActions.push_back (selectionTypeByPositiveness (*spell));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
possibleActions.push_back(ATTACK); //all active stacks can attack
|
}
|
||||||
possibleActions.push_back(WALK_AND_ATTACK); //not all stacks can always walk, but we will check this elsewhere
|
std::sort(possibleActions.begin(), possibleActions.end());
|
||||||
|
auto it = std::unique (possibleActions.begin(), possibleActions.end());
|
||||||
|
possibleActions.erase (it, possibleActions.end());
|
||||||
|
}
|
||||||
|
if (stack->hasBonusOfType (Bonus::RANDOM_SPELLCASTER))
|
||||||
|
possibleActions.push_back (RANDOM_GENIE_SPELL);
|
||||||
|
if (stack->hasBonusOfType (Bonus::DAEMON_SUMMONING))
|
||||||
|
possibleActions.push_back (RISE_DEMONS);
|
||||||
|
}
|
||||||
|
if (stack->shots && stack->hasBonusOfType (Bonus::SHOOTER))
|
||||||
|
possibleActions.push_back (SHOOT);
|
||||||
|
if (stack->hasBonusOfType (Bonus::RETURN_AFTER_STRIKE))
|
||||||
|
possibleActions.push_back (ATTACK_AND_RETURN);
|
||||||
|
|
||||||
if (stack->canMove() && stack->Speed()); //probably no reason to try move war machines or bound stacks
|
possibleActions.push_back(ATTACK); //all active stacks can attack
|
||||||
possibleActions.push_back (MOVE_STACK); //all active stacks can attack
|
possibleActions.push_back(WALK_AND_ATTACK); //not all stacks can always walk, but we will check this elsewhere
|
||||||
|
|
||||||
if (siegeH && stack->hasBonusOfType (Bonus::CATAPULT)) //TODO: check shots
|
if (stack->canMove() && stack->Speed()); //probably no reason to try move war machines or bound stacks
|
||||||
possibleActions.push_back (CATAPULT);
|
possibleActions.push_back (MOVE_STACK); //all active stacks can attack
|
||||||
if (stack->hasBonusOfType (Bonus::HEALER))
|
|
||||||
possibleActions.push_back (HEAL);
|
|
||||||
|
|
||||||
|
if (siegeH && stack->hasBonusOfType (Bonus::CATAPULT)) //TODO: check shots
|
||||||
|
possibleActions.push_back (CATAPULT);
|
||||||
|
if (stack->hasBonusOfType (Bonus::HEALER))
|
||||||
|
possibleActions.push_back (HEAL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::showAliveStack(const CStack *stack, SDL_Surface * to)
|
void CBattleInterface::showAliveStack(const CStack *stack, SDL_Surface * to)
|
||||||
@ -2602,8 +2603,6 @@ void CBattleInterface::bTacticNextStack(const CStack *current /*= NULL*/)
|
|||||||
else
|
else
|
||||||
stackActivated(stacksOfMine.front());
|
stackActivated(stacksOfMine.front());
|
||||||
|
|
||||||
possibleActions.clear();
|
|
||||||
possibleActions += MOVE_TACTICS, CHOOSE_TACTICS_STACK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CBattleInterface::PossibleActions CBattleInterface::selectionTypeByPositiveness(const CSpell & spell)
|
CBattleInterface::PossibleActions CBattleInterface::selectionTypeByPositiveness(const CSpell & spell)
|
||||||
@ -2702,17 +2701,14 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
|||||||
|
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case MOVE_TACTICS:
|
|
||||||
break;
|
|
||||||
case CHOOSE_TACTICS_STACK:
|
case CHOOSE_TACTICS_STACK:
|
||||||
if (shere && ourStack)
|
if (shere && ourStack)
|
||||||
legalAction = true;
|
legalAction = true;
|
||||||
break;
|
break;
|
||||||
|
case MOVE_TACTICS:
|
||||||
case MOVE_STACK:
|
case MOVE_STACK:
|
||||||
{
|
if (canStackMoveHere (sactive, myNumber) && !shere)
|
||||||
if (canStackMoveHere (sactive, myNumber))
|
|
||||||
legalAction = true;
|
legalAction = true;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ATTACK:
|
case ATTACK:
|
||||||
case WALK_AND_ATTACK:
|
case WALK_AND_ATTACK:
|
||||||
@ -2749,7 +2745,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
|||||||
break;
|
break;
|
||||||
case RANDOM_GENIE_SPELL:
|
case RANDOM_GENIE_SPELL:
|
||||||
{
|
{
|
||||||
if (shere)
|
if (shere && ourStack && shere != sactive) //only positive spells for other allied creatures
|
||||||
{
|
{
|
||||||
int spellID = curInt->cb->battleGetRandomStackSpell(shere, CBattleInfoCallback::RANDOM_GENIE);
|
int spellID = curInt->cb->battleGetRandomStackSpell(shere, CBattleInfoCallback::RANDOM_GENIE);
|
||||||
if (spellID > -1)
|
if (spellID > -1)
|
||||||
@ -2829,8 +2825,9 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
|||||||
consoleMsg = (boost::format(CGI->generaltexth->allTexts[481]) % shere->getName()).str(); //Select %s
|
consoleMsg = (boost::format(CGI->generaltexth->allTexts[481]) % shere->getName()).str(); //Select %s
|
||||||
realizeAction = [=]{ stackActivated(shere); };
|
realizeAction = [=]{ stackActivated(shere); };
|
||||||
break;
|
break;
|
||||||
|
case MOVE_TACTICS:
|
||||||
case MOVE_STACK:
|
case MOVE_STACK:
|
||||||
if(activeStack->hasBonusOfType(Bonus::FLYING))
|
if (activeStack->hasBonusOfType(Bonus::FLYING))
|
||||||
{
|
{
|
||||||
cursorFrame = ECursor::COMBAT_FLY;
|
cursorFrame = ECursor::COMBAT_FLY;
|
||||||
consoleMsg = (boost::format(CGI->generaltexth->allTexts[295]) % activeStack->getName()).str(); //Fly %s here
|
consoleMsg = (boost::format(CGI->generaltexth->allTexts[295]) % activeStack->getName()).str(); //Fly %s here
|
||||||
@ -2843,7 +2840,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
|||||||
|
|
||||||
realizeAction = [=]
|
realizeAction = [=]
|
||||||
{
|
{
|
||||||
if(activeStack->doubleWide())
|
if (activeStack->doubleWide())
|
||||||
{
|
{
|
||||||
std::vector<BattleHex> acc = curInt->cb->battleGetAvailableHexes(activeStack, false);
|
std::vector<BattleHex> acc = curInt->cb->battleGetAvailableHexes(activeStack, false);
|
||||||
int shiftedDest = myNumber + (activeStack->attackerOwned ? 1 : -1);
|
int shiftedDest = myNumber + (activeStack->attackerOwned ? 1 : -1);
|
||||||
@ -2854,7 +2851,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
giveCommand(BattleAction::WALK, myNumber, activeStack->ID);
|
giveCommand (BattleAction::WALK, myNumber, activeStack->ID);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
@ -2867,7 +2864,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
|||||||
realizeAction = [=]
|
realizeAction = [=]
|
||||||
{
|
{
|
||||||
BattleHex attackFromHex = fromWhichHexAttack(myNumber);
|
BattleHex attackFromHex = 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)
|
||||||
{
|
{
|
||||||
giveCommand(BattleAction::WALK_AND_ATTACK, attackFromHex, activeStack->ID, myNumber);
|
giveCommand(BattleAction::WALK_AND_ATTACK, attackFromHex, activeStack->ID, myNumber);
|
||||||
}
|
}
|
||||||
|
@ -959,7 +959,7 @@ CCommanderInstance::CCommanderInstance (TCreature id)
|
|||||||
name = "Commando"; //TODO - parse them
|
name = "Commando"; //TODO - parse them
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCommanderInstance::init() //called only after CStackInstance::init was executed
|
void CCommanderInstance::init()
|
||||||
{
|
{
|
||||||
alive = true;
|
alive = true;
|
||||||
experience = 0;
|
experience = 0;
|
||||||
|
@ -205,6 +205,7 @@ namespace Obj
|
|||||||
SHIPWRECK = 85,
|
SHIPWRECK = 85,
|
||||||
STABLES = 94,
|
STABLES = 94,
|
||||||
TRADING_POST = 99,
|
TRADING_POST = 99,
|
||||||
|
TREE_OF_KNOWLEDGE = 102,
|
||||||
SUBTERRANEAN_GATE = 103,
|
SUBTERRANEAN_GATE = 103,
|
||||||
UNIVERSITY = 104,
|
UNIVERSITY = 104,
|
||||||
SCHOOL_OF_WAR = 107,
|
SCHOOL_OF_WAR = 107,
|
||||||
|
Loading…
Reference in New Issue
Block a user