mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
* fix for bug 573
* minor changes
This commit is contained in:
parent
44619757e8
commit
4e631fc530
@ -596,10 +596,7 @@ bool CBattleCallback::battleCanCastSpell()
|
||||
if(!gs->curB) //there is no battle
|
||||
return false;
|
||||
|
||||
if(gs->curB->sides[0] == player)
|
||||
return gs->curB->castSpells[0] == 0 && gs->curB->heroes[0] && gs->curB->heroes[0]->getArt(17);
|
||||
else
|
||||
return gs->curB->castSpells[1] == 0 && gs->curB->heroes[1] && gs->curB->heroes[1]->getArt(17);
|
||||
return gs->curB->battleCanCastSpell(player) == SpellCasting::OK;
|
||||
}
|
||||
|
||||
bool CBattleCallback::battleCanFlee()
|
||||
@ -1091,29 +1088,16 @@ std::vector<int> CBattleCallback::battleGetDistances(const CStack * stack, THex
|
||||
return ret;
|
||||
}
|
||||
|
||||
CBattleCallback::ESpellCastProblem CBattleCallback::battleCanCastThisSpell( const CSpell * spell )
|
||||
SpellCasting::ESpellCastProblem CBattleCallback::battleCanCastThisSpell( const CSpell * spell )
|
||||
{
|
||||
if(!battleCanCastSpell())
|
||||
return GENERAL_CASTING_PROBLEM;
|
||||
|
||||
int spellIDs[] = {66, 67, 68, 69}; //IDs of summon elemental spells (fire, earth, water, air)
|
||||
int creIDs[] = {114, 113, 115, 112}; //(fire, earth, water, air)
|
||||
|
||||
int * idp = std::find(spellIDs, spellIDs + ARRAY_COUNT(spellIDs), spell->id);
|
||||
int arpos = idp - spellIDs;
|
||||
if(arpos < ARRAY_COUNT(spellIDs))
|
||||
if(!gs->curB)
|
||||
{
|
||||
//check if there are summoned elementals of other type
|
||||
BOOST_FOREACH ( const CStack * st, gs->curB->stacks)
|
||||
{
|
||||
if (vstd::contains(st->state, SUMMONED) && st->getCreature()->idNumber != creIDs[arpos])
|
||||
{
|
||||
return ANOTHER_ELEMENTAL_SUMMONED;
|
||||
}
|
||||
}
|
||||
|
||||
tlog1 << "battleCanCastThisSpell called when there is no battle!\n";
|
||||
return SpellCasting::NO_HERO_TO_CAST_SPELL;
|
||||
}
|
||||
|
||||
return OK;
|
||||
return gs->curB->battleCanCastThisSpell(player, spell);
|
||||
}
|
||||
|
||||
si8 CBattleCallback::battleGetTacticDist()
|
||||
|
@ -75,10 +75,6 @@ class IBattleCallback
|
||||
{
|
||||
public:
|
||||
///describes why player cannot cast a specific spell
|
||||
enum ESpellCastProblem
|
||||
{
|
||||
OK, GENERAL_CASTING_PROBLEM, ANOTHER_ELEMENTAL_SUMMONED
|
||||
};
|
||||
|
||||
enum EStackOwnership
|
||||
{
|
||||
@ -100,7 +96,7 @@ public:
|
||||
virtual std::vector<int> battleGetDistances(const CStack * stack, THex hex = THex::INVALID, THex * predecessors = NULL)=0; //returns vector of distances to [dest hex number]
|
||||
virtual bool battleCanShoot(const CStack * stack, THex dest)=0; //returns true if unit with id ID can shoot to dest
|
||||
virtual bool battleCanCastSpell()=0; //returns true, if caller can cast a spell
|
||||
virtual ESpellCastProblem battleCanCastThisSpell(const CSpell * spell)=0; //determines if given spell can be casted (and returns problem description)
|
||||
virtual SpellCasting::ESpellCastProblem battleCanCastThisSpell(const CSpell * spell)=0; //determines if given spell can be casted (and returns problem description)
|
||||
virtual bool battleCanFlee()=0; //returns true if caller can flee from the battle
|
||||
virtual const CGTownInstance * battleGetDefendedTown()=0; //returns defended town if current battle is a siege, NULL instead
|
||||
virtual ui8 battleGetWallState(int partOfWall)=0; //for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall, [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle
|
||||
@ -238,7 +234,7 @@ public:
|
||||
std::vector<int> battleGetDistances(const CStack * stack, THex hex = THex::INVALID, THex * predecessors = NULL) OVERRIDE; //returns vector of distances to [dest hex number]; if predecessors is not null, it must point to BFIELD_SIZE * sizeof(int) of allocated memory
|
||||
bool battleCanShoot(const CStack * stack, THex dest) OVERRIDE; //returns true if unit with id ID can shoot to dest
|
||||
bool battleCanCastSpell() OVERRIDE; //returns true, if caller can cast a spell
|
||||
ESpellCastProblem battleCanCastThisSpell(const CSpell * spell) OVERRIDE; //determines if given spell can be casted (and returns problem description)
|
||||
SpellCasting::ESpellCastProblem battleCanCastThisSpell(const CSpell * spell) OVERRIDE; //determines if given spell can be casted (and returns problem description)
|
||||
bool battleCanFlee() OVERRIDE; //returns true if caller can flee from the battle
|
||||
const CGTownInstance * battleGetDefendedTown() OVERRIDE; //returns defended town if current battle is a siege, NULL instead
|
||||
ui8 battleGetWallState(int partOfWall) OVERRIDE; //for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall, [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle
|
||||
|
@ -17,8 +17,10 @@
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include "CBitmapHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/BattleState.h"
|
||||
|
||||
/*
|
||||
* CSpellWindow.cpp, part of VCMI engine
|
||||
@ -619,20 +621,29 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
|
||||
//we will cast a spell
|
||||
if(sp->combatSpell && owner->myInt->battleInt && owner->myInt->cb->battleCanCastSpell()) //if battle window is open
|
||||
{
|
||||
IBattleCallback::ESpellCastProblem problem = owner->myInt->cb->battleCanCastThisSpell(sp);
|
||||
SpellCasting::ESpellCastProblem problem = owner->myInt->cb->battleCanCastThisSpell(sp);
|
||||
switch (problem)
|
||||
{
|
||||
case IBattleCallback::OK:
|
||||
case SpellCasting::OK:
|
||||
{
|
||||
int spell = mySpell;
|
||||
owner->fexitb();
|
||||
owner->myInt->battleInt->castThisSpell(spell);
|
||||
break;
|
||||
}
|
||||
case IBattleCallback::ANOTHER_ELEMENTAL_SUMMONED:
|
||||
case SpellCasting::ANOTHER_ELEMENTAL_SUMMONED:
|
||||
{
|
||||
std::string text = CGI->generaltexth->allTexts[538], summoner, elemental, caster;
|
||||
std::vector<const CStack *> stacks = owner->myInt->cb->battleGetStacks();
|
||||
BOOST_FOREACH(const CStack * s, stacks)
|
||||
{
|
||||
if(vstd::contains(s->state, SUMMONED))
|
||||
{
|
||||
elemental = s->getCreature()->namePl;
|
||||
summoner = owner->myInt->cb->battleGetFightingHero(!s->attackerOwned)->name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (owner->myHero->type->sex)
|
||||
{ //female
|
||||
caster = CGI->generaltexth->allTexts[540];
|
||||
@ -641,6 +652,8 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
|
||||
{ //male
|
||||
caster = CGI->generaltexth->allTexts[539];
|
||||
}
|
||||
text = boost::str(boost::format(text) % summoner % elemental % caster);
|
||||
|
||||
|
||||
owner->myInt->showInfoDialog(text);
|
||||
}
|
||||
|
10
global.h
10
global.h
@ -307,6 +307,16 @@ enum EMarketMode
|
||||
MARTKET_AFTER_LAST_PLACEHOLDER
|
||||
};
|
||||
|
||||
namespace SpellCasting
|
||||
{
|
||||
enum ESpellCastProblem
|
||||
{
|
||||
OK, NO_HERO_TO_CAST_SPELL, ALREADY_CASTED_THIS_TURN, NO_SPELLBOOK, ANOTHER_ELEMENTAL_SUMMONED,
|
||||
HERO_DOESNT_KNOW_SPELL, NOT_ENOUGH_MANA, ADVMAP_SPELL_INSTEAD_OF_BATTLE_SPELL,
|
||||
SECOND_HEROS_SPELL_IMMUNITY, SPELL_LEVEL_LIMIT_EXCEEDED
|
||||
};
|
||||
}
|
||||
|
||||
namespace Res
|
||||
{
|
||||
enum ERes
|
||||
|
@ -1617,6 +1617,62 @@ bool BattleInfo::isInTacticRange( THex dest ) const
|
||||
|| (tacticsSide && dest.getX() < BFIELD_WIDTH - 1 && dest.getX() >= BFIELD_WIDTH - tacticDistance - 1));
|
||||
}
|
||||
|
||||
SpellCasting::ESpellCastProblem BattleInfo::battleCanCastSpell(int player) const
|
||||
{
|
||||
int side = sides[0] == player ? 0 : 1;
|
||||
|
||||
if(castSpells[side] > 0)
|
||||
return SpellCasting::ALREADY_CASTED_THIS_TURN;
|
||||
if(!heroes[side])
|
||||
return SpellCasting::NO_HERO_TO_CAST_SPELL;
|
||||
if(!heroes[side]->getArt(17))
|
||||
return SpellCasting::NO_SPELLBOOK;
|
||||
|
||||
return SpellCasting::OK;
|
||||
}
|
||||
|
||||
SpellCasting::ESpellCastProblem BattleInfo::battleCanCastThisSpell( int player, const CSpell * spell ) const
|
||||
{
|
||||
SpellCasting::ESpellCastProblem genProblem = battleCanCastSpell(player);
|
||||
if(genProblem != SpellCasting::OK)
|
||||
return genProblem;
|
||||
int cside = sides[0] == player ? 0 : 1; //caster's side
|
||||
const CGHeroInstance * caster = heroes[cside];
|
||||
if(!caster->canCastThisSpell(spell))
|
||||
return SpellCasting::HERO_DOESNT_KNOW_SPELL;
|
||||
|
||||
if(caster->mana < getSpellCost(spell, caster)) //not enough mana
|
||||
return SpellCasting::NOT_ENOUGH_MANA;
|
||||
|
||||
if(spell->id < 10) //it's adventure spell (not combat))
|
||||
return SpellCasting::ADVMAP_SPELL_INSTEAD_OF_BATTLE_SPELL;
|
||||
|
||||
if(NBonus::hasOfType(heroes[1-cside], Bonus::SPELL_IMMUNITY, spell->id)) //non - casting hero provides immunity for this spell
|
||||
return SpellCasting::SECOND_HEROS_SPELL_IMMUNITY;
|
||||
|
||||
if(battleMaxSpellLevel() < spell->level) //non - casting hero stops caster from casting this spell
|
||||
return SpellCasting::SPELL_LEVEL_LIMIT_EXCEEDED;
|
||||
|
||||
int spellIDs[] = {66, 67, 68, 69}; //IDs of summon elemental spells (fire, earth, water, air)
|
||||
int creIDs[] = {114, 113, 115, 112}; //(fire, earth, water, air)
|
||||
|
||||
int * idp = std::find(spellIDs, spellIDs + ARRAY_COUNT(spellIDs), spell->id);
|
||||
int arpos = idp - spellIDs;
|
||||
if(arpos < ARRAY_COUNT(spellIDs))
|
||||
{
|
||||
//check if there are summoned elementals of other type
|
||||
BOOST_FOREACH ( const CStack * st, stacks)
|
||||
{
|
||||
if (vstd::contains(st->state, SUMMONED) && st->getCreature()->idNumber != creIDs[arpos])
|
||||
{
|
||||
return SpellCasting::ANOTHER_ELEMENTAL_SUMMONED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SpellCasting::OK;
|
||||
}
|
||||
|
||||
CStack::CStack(const CStackInstance *Base, int O, int I, bool AO, int S)
|
||||
: base(Base), ID(I), owner(O), slot(S), attackerOwned(AO),
|
||||
counterAttacks(1)
|
||||
|
@ -115,6 +115,9 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode
|
||||
si8 canTeleportTo(const CStack * stack, THex destHex, int telportLevel) const; //determines if given stack can teleport to given place
|
||||
bool battleCanShoot(const CStack * stack, THex dest) const; //determines if stack with given ID shoot at the selected destination
|
||||
|
||||
SpellCasting::ESpellCastProblem battleCanCastSpell(int player) const; //returns true if there are no general issues preventing from castng a spell
|
||||
SpellCasting::ESpellCastProblem battleCanCastThisSpell(int player, const CSpell * spell) const; //chcecks if given player can cast given spell
|
||||
|
||||
bool battleCanFlee(int player) const; //returns true if player can flee from the battle
|
||||
const CStack * battleGetStack(THex pos, bool onlyAlive); //returns stack at given tile
|
||||
const CGHeroInstance * battleGetOwner(const CStack * stack) const; //returns hero that owns given stack; NULL if none
|
||||
|
@ -3824,15 +3824,11 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
||||
const CSpell *s = VLC->spellh->spells[ba.additionalInfo];
|
||||
ui8 skill = h->getSpellSchoolLevel(s); //skill level
|
||||
|
||||
if( !(h->canCastThisSpell(s)) //hero cannot cast this spell at all
|
||||
|| (h->mana < gs->curB->getSpellCost(s, h)) //not enough mana
|
||||
|| (ba.additionalInfo < 10) //it's adventure spell (not combat)
|
||||
|| (gs->curB->castSpells[ba.side]) //spell has been cast
|
||||
|| (NBonus::hasOfType(secondHero, Bonus::SPELL_IMMUNITY, s->id)) //non - casting hero provides immunity for this spell
|
||||
|| (gs->curB->battleMaxSpellLevel() < s->level) //non - casting hero stops caster from casting this spell
|
||||
)
|
||||
SpellCasting::ESpellCastProblem escp = gs->curB->battleCanCastThisSpell(h->tempOwner, s);
|
||||
if(escp != SpellCasting::OK)
|
||||
{
|
||||
tlog2 << "Spell cannot be cast!\n";
|
||||
tlog2 << "Problem : " << escp << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user