mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-17 01:32:21 +02:00
A bunch of mechanics & refactorings.
This commit is contained in:
@ -2818,7 +2818,7 @@ void CBattleInterface::hexLclicked(int whichOne)
|
|||||||
{
|
{
|
||||||
//checking destination
|
//checking destination
|
||||||
bool allowCasting = true;
|
bool allowCasting = true;
|
||||||
bool onlyAlive = spellToCast->additionalInfo != 38 && spellToCast->additionalInfo != 39; //when casting resurrection or animate dead we should be allow to select dead stack
|
bool onlyAlive = vstd::contains(CGI->spellh->risingSpells, spellToCast->additionalInfo); //when casting resurrection or animate dead we should be allow to select dead stack
|
||||||
//TODO: more general handling of dead targets
|
//TODO: more general handling of dead targets
|
||||||
switch(spellSelMode)
|
switch(spellSelMode)
|
||||||
{
|
{
|
||||||
@ -3507,7 +3507,7 @@ void CBattleInterface::activateStack()
|
|||||||
bSurrender->block(curInt->cb->battleGetSurrenderCost() < 0);
|
bSurrender->block(curInt->cb->battleGetSurrenderCost() < 0);
|
||||||
|
|
||||||
//set casting flag to true if creature can use it to not check it every time
|
//set casting flag to true if creature can use it to not check it every time
|
||||||
if (s->casts && s->hasBonus(Selector::type(Bonus::SPELLCASTER)))
|
if (s->casts && s->hasBonus(Selector::type(Bonus::SPELLCASTER) || Selector::type(Bonus::RANDOM_SPELLCASTER)))
|
||||||
{
|
{
|
||||||
stackCanCastSpell = true;
|
stackCanCastSpell = true;
|
||||||
|
|
||||||
|
@ -93,8 +93,6 @@ static const CStack *takeStack(std::vector<const CStack *> &st, int &curside, in
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CStack * BattleInfo::getStack(int stackID, bool onlyAlive)
|
CStack * BattleInfo::getStack(int stackID, bool onlyAlive)
|
||||||
{
|
{
|
||||||
for(unsigned int g=0; g<stacks.size(); ++g)
|
for(unsigned int g=0; g<stacks.size(); ++g)
|
||||||
@ -437,7 +435,6 @@ bool BattleInfo::isStackBlocked(const CStack * stack) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::pair< std::vector<THex>, int > BattleInfo::getPath(THex start, THex dest, bool*accessibility, bool flyingCreature, bool twoHex, bool attackerOwned)
|
std::pair< std::vector<THex>, int > BattleInfo::getPath(THex start, THex dest, bool*accessibility, bool flyingCreature, bool twoHex, bool attackerOwned)
|
||||||
{
|
{
|
||||||
THex predecessor[BFIELD_SIZE]; //for getting the Path
|
THex predecessor[BFIELD_SIZE]; //for getting the Path
|
||||||
@ -949,7 +946,6 @@ CStack * BattleInfo::generateNewStack(const CStackInstance &base, int stackID, b
|
|||||||
ret->position = position;
|
ret->position = position;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, int stackID, bool attackerOwned, int slot, THex position) const
|
CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, int stackID, bool attackerOwned, int slot, THex position) const
|
||||||
{
|
{
|
||||||
int owner = attackerOwned ? sides[0] : sides[1];
|
int owner = attackerOwned ? sides[0] : sides[1];
|
||||||
@ -1155,23 +1151,7 @@ ui32 BattleInfo::calculateHealedHP(const CSpell * spell, int usedSpellPower, int
|
|||||||
}
|
}
|
||||||
bool BattleInfo::resurrects(TSpell spellid) const
|
bool BattleInfo::resurrects(TSpell spellid) const
|
||||||
{
|
{
|
||||||
switch(spellid)
|
return vstd::contains(VLC->spellh->risingSpells, spellid);
|
||||||
{
|
|
||||||
case 37: //cure
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 38: //resurrection
|
|
||||||
case 39: //animate dead
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
tlog2 << "BattleInfo::resurrects called for non-healing spell!\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleInfo::getStackQueue( std::vector<const CStack *> &out, int howMany, int turn /*= 0*/, int lastMoved /*= -1*/ ) const
|
void BattleInfo::getStackQueue( std::vector<const CStack *> &out, int howMany, int turn /*= 0*/, int lastMoved /*= -1*/ ) const
|
||||||
@ -1941,6 +1921,99 @@ SpellCasting::ESpellCastProblem BattleInfo::battleCanCastThisSpellHere( int play
|
|||||||
return battleIsImmune(NULL, spell, mode, dest);
|
return battleIsImmune(NULL, spell, mode, dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TSpell BattleInfo::getRandomBeneficialSpell(const CStack * subject) const
|
||||||
|
{
|
||||||
|
std::vector<TSpell> possibleSpells;
|
||||||
|
for (int i = 0; i < SPELLS_QUANTITY; ++i) //should not use future spells added by mods
|
||||||
|
{
|
||||||
|
if (VLC->spellh->spells[i]->positiveness == 1) //only positive
|
||||||
|
{
|
||||||
|
if (subject->hasBonusFrom(Bonus::SPELL_EFFECT, i))
|
||||||
|
continue;
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 27: //shield
|
||||||
|
case 29: //fire shield - not if all enemy units are shooters
|
||||||
|
{
|
||||||
|
bool walkerPresent = false;
|
||||||
|
BOOST_FOREACH (CStack * stack, stacks)
|
||||||
|
{
|
||||||
|
if ((stack->owner != subject->owner) && !stack->shots)
|
||||||
|
{
|
||||||
|
walkerPresent = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!walkerPresent)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 28: //air shield - only against active shooters
|
||||||
|
{
|
||||||
|
bool shooterPresent = false;
|
||||||
|
BOOST_FOREACH (CStack * stack, stacks)
|
||||||
|
{
|
||||||
|
if ((stack->owner != subject->owner) && stack->hasBonusOfType(Bonus::SHOOTER) && stack->shots)
|
||||||
|
{
|
||||||
|
shooterPresent = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!shooterPresent)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 34: //anti-magic
|
||||||
|
case 36: //magic mirror
|
||||||
|
{
|
||||||
|
if (!heroes[whatSide(theOtherPlayer(subject->owner))]) //only if there is enemy hero
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 37: //Cure - only damaged units - what about affected by curse?
|
||||||
|
{
|
||||||
|
if (subject->firstHPleft >= subject->MaxHealth())
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 43: //bloodlust
|
||||||
|
{
|
||||||
|
if (subject->shots) //if can shoot - only if enemy uits are adjacent
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 44: //precision
|
||||||
|
{
|
||||||
|
if (!(subject->hasBonusOfType(Bonus::SHOOTER) && subject->shots))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 55: //slayer - only if monsters are present
|
||||||
|
{
|
||||||
|
bool monsterPresent = false;
|
||||||
|
BOOST_FOREACH (CStack * stack, stacks)
|
||||||
|
{
|
||||||
|
if ((stack->owner != subject->owner) &&
|
||||||
|
(stack->hasBonus(Selector::type(Bonus::KING1) || Selector::type(Bonus::KING2) || Selector::type(Bonus::KING3))))
|
||||||
|
{
|
||||||
|
monsterPresent = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!monsterPresent)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
possibleSpells.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (possibleSpells.size())
|
||||||
|
return possibleSpells[ran() % possibleSpells.size()];
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
const CGHeroInstance * BattleInfo::getHero( int player ) const
|
const CGHeroInstance * BattleInfo::getHero( int player ) const
|
||||||
{
|
{
|
||||||
assert(sides[0] == player || sides[1] == player);
|
assert(sides[0] == player || sides[1] == player);
|
||||||
@ -2158,13 +2231,11 @@ CStack::CStack(const CStackInstance *Base, int O, int I, bool AO, int S)
|
|||||||
count = baseAmount = base->count;
|
count = baseAmount = base->count;
|
||||||
setNodeType(STACK_BATTLE);
|
setNodeType(STACK_BATTLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
CStack::CStack()
|
CStack::CStack()
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
setNodeType(STACK_BATTLE);
|
setNodeType(STACK_BATTLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
CStack::CStack(const CStackBasicDescriptor *stack, int O, int I, bool AO, int S)
|
CStack::CStack(const CStackBasicDescriptor *stack, int O, int I, bool AO, int S)
|
||||||
: base(NULL), ID(I), owner(O), slot(S), attackerOwned(AO), counterAttacks(1)
|
: base(NULL), ID(I), owner(O), slot(S), attackerOwned(AO), counterAttacks(1)
|
||||||
{
|
{
|
||||||
|
@ -127,6 +127,7 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode
|
|||||||
SpellCasting::ESpellCastProblem battleIsImmune(const CGHeroInstance * caster, const CSpell * spell, SpellCasting::ECastingMode mode, THex dest) const; //checks for creature immunity / anything that prevent casting *at given hex* - doesn't take into acount general problems such as not having spellbook or mana points etc.
|
SpellCasting::ESpellCastProblem battleIsImmune(const CGHeroInstance * caster, const CSpell * spell, SpellCasting::ECastingMode mode, THex dest) const; //checks for creature immunity / anything that prevent casting *at given hex* - doesn't take into acount general problems such as not having spellbook or mana points etc.
|
||||||
SpellCasting::ESpellCastProblem battleCanCastThisSpellHere(int player, const CSpell * spell, SpellCasting::ECastingMode mode, THex dest); //checks if given player can cast given spell at given tile in given mode
|
SpellCasting::ESpellCastProblem battleCanCastThisSpellHere(int player, const CSpell * spell, SpellCasting::ECastingMode mode, THex dest); //checks if given player can cast given spell at given tile in given mode
|
||||||
bool battleTestElementalImmunity(const CStack * subject, const CSpell * spell, Bonus::BonusType element, bool damageSpell) const;
|
bool battleTestElementalImmunity(const CStack * subject, const CSpell * spell, Bonus::BonusType element, bool damageSpell) const;
|
||||||
|
TSpell getRandomBeneficialSpell(const CStack * subject) const;
|
||||||
|
|
||||||
std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHeroInstance * caster, const CGHeroInstance * hero2, const std::set<CStack*> affectedCreatures, int casterSideOwner, SpellCasting::ECastingMode mode) const;
|
std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHeroInstance * caster, const CGHeroInstance * hero2, const std::set<CStack*> affectedCreatures, int casterSideOwner, SpellCasting::ECastingMode mode) const;
|
||||||
|
|
||||||
|
@ -319,4 +319,5 @@ void CSpellHandler::loadSpells()
|
|||||||
boost::replace_first(spells[61]->attributes, "CREATURE_TARGET", "CREATURE_TARGET_2"); //TODO: use flags instead?
|
boost::replace_first(spells[61]->attributes, "CREATURE_TARGET", "CREATURE_TARGET_2"); //TODO: use flags instead?
|
||||||
|
|
||||||
damageSpells += 11, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 57, 77;
|
damageSpells += 11, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 57, 77;
|
||||||
|
risingSpells += 38, 39, 40;
|
||||||
}
|
}
|
||||||
|
@ -64,11 +64,12 @@ public:
|
|||||||
CSpellHandler();
|
CSpellHandler();
|
||||||
std::vector< ConstTransitivePtr<CSpell> > spells;
|
std::vector< ConstTransitivePtr<CSpell> > spells;
|
||||||
std::set<TSpell> damageSpells; //they inflict damage and require particular threatment
|
std::set<TSpell> damageSpells; //they inflict damage and require particular threatment
|
||||||
|
std::set<TSpell> risingSpells; //they affect dead stacks and need special target selection
|
||||||
void loadSpells();
|
void loadSpells();
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & spells & damageSpells;
|
h & spells & damageSpells & risingSpells;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ namespace PrimarySkill
|
|||||||
BONUS_NAME(DOUBLE_DAMAGE_CHANCE) /*value in %, eg. dread knight*/ \
|
BONUS_NAME(DOUBLE_DAMAGE_CHANCE) /*value in %, eg. dread knight*/ \
|
||||||
BONUS_NAME(RETURN_AFTER_STRIKE) \
|
BONUS_NAME(RETURN_AFTER_STRIKE) \
|
||||||
BONUS_NAME(SELF_MORALE) /*eg. minotaur*/ \
|
BONUS_NAME(SELF_MORALE) /*eg. minotaur*/ \
|
||||||
BONUS_NAME(SPELLCASTER) /*subtype - spell id, value - level of school. use SPECIFIC_SPELL_POWER, CREATURE_SPELL_POWER or CREATURE_ENCHANT_POWER for calculating the power*/ \
|
BONUS_NAME(SPELLCASTER) /*subtype - spell id, value - level of school, additional info - weighted chance. use SPECIFIC_SPELL_POWER, CREATURE_SPELL_POWER or CREATURE_ENCHANT_POWER for calculating the power*/ \
|
||||||
BONUS_NAME(CATAPULT) \
|
BONUS_NAME(CATAPULT) \
|
||||||
BONUS_NAME(ENEMY_DEFENCE_REDUCTION) /*in % (value) eg. behemots*/ \
|
BONUS_NAME(ENEMY_DEFENCE_REDUCTION) /*in % (value) eg. behemots*/ \
|
||||||
BONUS_NAME(GENERAL_DAMAGE_REDUCTION) /* shield / air shield effect */ \
|
BONUS_NAME(GENERAL_DAMAGE_REDUCTION) /* shield / air shield effect */ \
|
||||||
|
Reference in New Issue
Block a user