mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
* support for increasing / decreasing luck / morale for allies / enemies
* support for spell 77 (thunder-sth)
This commit is contained in:
parent
0a950c508b
commit
3a76d72b69
@ -132,7 +132,7 @@ int CCallback::estimateSpellDamage(const CSpell * sp) const
|
||||
return 0;
|
||||
|
||||
const CGHeroInstance * ourHero = gs->curB->heroes[0]->tempOwner == player ? gs->curB->heroes[0] : gs->curB->heroes[1];
|
||||
return gs->curB->calculateSpellDmg(sp, ourHero, NULL, ourHero->getSpellSchoolLevel(sp));
|
||||
return gs->curB->calculateSpellDmg(sp, ourHero, NULL, ourHero->getSpellSchoolLevel(sp), ourHero->getPrimSkillLevel(2));
|
||||
}
|
||||
|
||||
void CCallback::getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj)
|
||||
@ -943,6 +943,16 @@ void CCallback::dig( const CGObjectInstance *hero )
|
||||
sendRequest(&dwh);
|
||||
}
|
||||
|
||||
si8 CCallback::battleGetStackMorale( int stackID )
|
||||
{
|
||||
return gs->curB->Morale( gs->curB->getStack(stackID) );
|
||||
}
|
||||
|
||||
si8 CCallback::battleGetStackLuck( int stackID )
|
||||
{
|
||||
return gs->curB->Luck( gs->curB->getStack(stackID) );
|
||||
}
|
||||
|
||||
InfoAboutTown::InfoAboutTown()
|
||||
{
|
||||
tType = NULL;
|
||||
|
@ -175,6 +175,8 @@ public:
|
||||
virtual std::pair<ui32, ui32> battleEstimateDamage(int attackerID, int defenderID)=0; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
|
||||
virtual ui8 battleGetSiegeLevel()=0; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
|
||||
virtual const CGHeroInstance * battleGetFightingHero(ui8 side) const =0; //returns hero corresponding ot given side (0 - attacker, 1 - defender)
|
||||
virtual si8 battleGetStackMorale(int stackID) =0; //returns morale of given stack
|
||||
virtual si8 battleGetStackLuck(int stackID) =0; //returns luck of given stack
|
||||
};
|
||||
|
||||
struct HeroMoveDetails
|
||||
@ -293,6 +295,8 @@ public:
|
||||
std::pair<ui32, ui32> battleEstimateDamage(int attackerID, int defenderID); //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
|
||||
ui8 battleGetSiegeLevel(); //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
|
||||
const CGHeroInstance * battleGetFightingHero(ui8 side) const; //returns hero corresponding ot given side (0 - attacker, 1 - defender)
|
||||
si8 battleGetStackMorale(int stackID); //returns morale of given stack
|
||||
si8 battleGetStackLuck(int stackID); //returns luck of given stack
|
||||
|
||||
//XXX hmmm _tmain on _GNUC_ wtf?
|
||||
//friends
|
||||
|
@ -3467,8 +3467,8 @@ void CBattleHex::clickRight(tribool down, bool previousState)
|
||||
|
||||
pom->attackBonus = myst.Attack() - myst.creature->attack;
|
||||
pom->defenseBonus = myst.Defense() - myst.creature->defence;
|
||||
pom->luck = myst.Luck();
|
||||
pom->morale = myst.Morale();
|
||||
pom->luck = myInterface->curInt->cb->battleGetStackLuck(myst.ID);
|
||||
pom->morale = myInterface->curInt->cb->battleGetStackMorale(myst.ID);
|
||||
pom->speedBonus = myst.Speed() - myst.creature->speed;
|
||||
pom->healthBonus = myst.MaxHealth() - myst.creature->hitPoints;
|
||||
if(myst.hasFeatureOfType(StackFeature::SIEGE_WEAPON))
|
||||
|
@ -69,11 +69,11 @@
|
||||
+ 53 HATE 0 36 0 //efreet sultans hate genies
|
||||
+ 53 HATE 0 37 0 //efreet sultans hate master genies
|
||||
+ 54 BLOCKS_RETALIATION 0 0 0 //devils
|
||||
+ 54 ENEMY_LUCK_DECREASING -1 0 0 //devils
|
||||
+ 54 ENEMY_LUCK_DECREASING 1 0 0 //devils
|
||||
+ 54 HATE 0 12 0 //devils hate angels
|
||||
+ 54 HATE 0 13 0 //devils hate archangles
|
||||
+ 55 BLOCKS_RETALIATION 0 0 0 //archdevils
|
||||
+ 55 ENEMY_LUCK_DECREASING -1 0 0 //archdevils
|
||||
+ 55 ENEMY_LUCK_DECREASING 1 0 0 //archdevils
|
||||
+ 55 HATE 0 12 0 //archdevils hate angels
|
||||
+ 55 HATE 0 13 0 //archdevils hate archangles
|
||||
+ 60 FULL_HP_REGENERATION 0 1 0 //wight
|
||||
|
@ -772,44 +772,6 @@ ui8 CStack::howManyEffectsSet(ui16 id) const
|
||||
return ret;
|
||||
}
|
||||
|
||||
si8 CStack::Morale() const
|
||||
{
|
||||
si8 ret = morale;
|
||||
|
||||
if(hasFeatureOfType(StackFeature::NON_LIVING) || hasFeatureOfType(StackFeature::UNDEAD) || hasFeatureOfType(StackFeature::NO_MORALE))
|
||||
return 0;
|
||||
|
||||
ret += valOfFeatures(StackFeature::MORALE_BONUS); //mirth & sorrow & other
|
||||
|
||||
if(hasFeatureOfType(StackFeature::SELF_MORALE)) //eg. minotaur
|
||||
{
|
||||
ret = std::max<si8>(ret, +1);
|
||||
}
|
||||
|
||||
if(ret > 3) ret = 3;
|
||||
if(ret < -3) ret = -3;
|
||||
return ret;
|
||||
}
|
||||
|
||||
si8 CStack::Luck() const
|
||||
{
|
||||
si8 ret = luck;
|
||||
|
||||
if(hasFeatureOfType(StackFeature::NO_LUCK))
|
||||
return 0;
|
||||
|
||||
ret += valOfFeatures(StackFeature::LUCK_BONUS); //fortune & misfortune & other
|
||||
|
||||
if(hasFeatureOfType(StackFeature::SELF_LUCK)) //eg. halfling
|
||||
{
|
||||
ret = std::max<si8>(ret, +1);
|
||||
}
|
||||
|
||||
if(ret > 3) ret = 3;
|
||||
if(ret < -3) ret = -3;
|
||||
return ret;
|
||||
}
|
||||
|
||||
si32 CStack::Attack() const
|
||||
{
|
||||
si32 ret = creature->attack; //value to be returned
|
||||
@ -2884,7 +2846,7 @@ std::pair<const CStack *, int> BattleInfo::getNearestStack(const CStack * closes
|
||||
return std::make_pair<const CStack * , int>(NULL, -1);
|
||||
}
|
||||
|
||||
ui32 BattleInfo::calculateSpellDmg( const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel ) const
|
||||
ui32 BattleInfo::calculateSpellDmg( const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower ) const
|
||||
{
|
||||
ui32 ret = 0; //value to return
|
||||
|
||||
@ -2896,10 +2858,8 @@ ui32 BattleInfo::calculateSpellDmg( const CSpell * sp, const CGHeroInstance * ca
|
||||
if(dmgMultipliers.find(sp->id) == dmgMultipliers.end())
|
||||
return 0;
|
||||
|
||||
if (caster)
|
||||
{
|
||||
ret = caster->getPrimSkillLevel(2) * dmgMultipliers[sp->id];
|
||||
}
|
||||
|
||||
ret = usedSpellPower * dmgMultipliers[sp->id];
|
||||
ret += sp->powers[spellSchoolLevel];
|
||||
|
||||
//applying sorcerery secondary skill
|
||||
@ -3539,6 +3499,76 @@ void BattleInfo::getStackQueue( std::vector<const CStack *> &out, int howMany, i
|
||||
}
|
||||
}
|
||||
|
||||
si8 BattleInfo::Morale( const CStack * st ) const
|
||||
{
|
||||
si8 ret = st->morale;
|
||||
|
||||
if(st->hasFeatureOfType(StackFeature::NON_LIVING) || st->hasFeatureOfType(StackFeature::UNDEAD) || st->hasFeatureOfType(StackFeature::NO_MORALE))
|
||||
return 0;
|
||||
|
||||
ret += st->valOfFeatures(StackFeature::MORALE_BONUS); //mirth & sorrow & other
|
||||
|
||||
//decreasing / increasing morale from other stacks
|
||||
for (int g=0; g<stacks.size(); ++g)
|
||||
{
|
||||
if (stacks[g]->owner == st->owner) //ally
|
||||
{
|
||||
if (stacks[g]->hasFeatureOfType(StackFeature::RAISING_MORALE))
|
||||
{
|
||||
ret += stacks[g]->valOfFeatures(StackFeature::RAISING_MORALE);
|
||||
}
|
||||
}
|
||||
else //enemy
|
||||
{
|
||||
if (stacks[g]->hasFeatureOfType(StackFeature::ENEMY_MORALE_DECREASING))
|
||||
{
|
||||
ret -= stacks[g]->valOfFeatures(StackFeature::ENEMY_MORALE_DECREASING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(st->hasFeatureOfType(StackFeature::SELF_MORALE)) //eg. minotaur
|
||||
{
|
||||
ret = std::max<si8>(ret, +1);
|
||||
}
|
||||
|
||||
if(ret > 3) ret = 3;
|
||||
if(ret < -3) ret = -3;
|
||||
return ret;
|
||||
}
|
||||
|
||||
si8 BattleInfo::Luck( const CStack * st ) const
|
||||
{
|
||||
si8 ret = st->luck;
|
||||
|
||||
if(st->hasFeatureOfType(StackFeature::NO_LUCK))
|
||||
return 0;
|
||||
|
||||
ret += st->valOfFeatures(StackFeature::LUCK_BONUS); //fortune & misfortune & other
|
||||
|
||||
//decreasing / increasing morale from other stacks
|
||||
for (int g=0; g<stacks.size(); ++g)
|
||||
{
|
||||
if (stacks[g]->owner == st->owner) //ally
|
||||
{
|
||||
//no such feature (yet)
|
||||
}
|
||||
else //enemy
|
||||
{
|
||||
ret -= stacks[g]->valOfFeatures(StackFeature::ENEMY_LUCK_DECREASING);
|
||||
}
|
||||
}
|
||||
|
||||
if(st->hasFeatureOfType(StackFeature::SELF_LUCK)) //eg. halfling
|
||||
{
|
||||
ret = std::max<si8>(ret, +1);
|
||||
}
|
||||
|
||||
if(ret > 3) ret = 3;
|
||||
if(ret < -3) ret = -3;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int3 CPath::startPos() const
|
||||
{
|
||||
return nodes[nodes.size()-1].coord;
|
||||
|
@ -217,6 +217,9 @@ struct DLL_EXPORT BattleInfo
|
||||
std::pair< std::vector<int>, int > getPath(int start, int dest, bool*accessibility, bool flyingCreature, bool twoHex, bool attackerOwned); //returned value: pair<path, length>; length may be different than number of elements in path since flying vreatures jump between distant hexes
|
||||
std::vector<int> getAccessibility(int stackID, bool addOccupiable) const; //returns vector of accessible tiles (taking into account the creature range)
|
||||
|
||||
si8 Morale(const CStack * st) const; //get morale of stack with all modificators
|
||||
si8 Luck(const CStack * st) const; //get luck of stack with all modificators
|
||||
|
||||
bool isStackBlocked(int ID); //returns true if there is neighbouring enemy stack
|
||||
static signed char mutualPosition(int hex1, int hex2); //returns info about mutual position of given hexes (-1 - they're distant, 0 - left top, 1 - right top, 2 - right, 3 - right bottom, 4 - left bottom, 5 - left)
|
||||
static std::vector<int> neighbouringTiles(int hex);
|
||||
@ -229,7 +232,7 @@ struct DLL_EXPORT BattleInfo
|
||||
ui32 getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell
|
||||
int hexToWallPart(int hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
|
||||
std::pair<const CStack *, int> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const; //if attackerOwned is indetermnate, returened stack is of any owner; hex is the number of hex we should be looking from; returns (nerarest creature, predecessorHex)
|
||||
ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel) const; //calculates damage inflicted by spell
|
||||
ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const; //calculates damage inflicted by spell
|
||||
};
|
||||
|
||||
class DLL_EXPORT CStack
|
||||
@ -271,8 +274,6 @@ public:
|
||||
bool moved(int turn = 0) const; //if stack was already moved this turn
|
||||
bool canMove(int turn = 0) const; //if stack can move
|
||||
ui32 Speed(int turn = 0) const; //get speed of creature with all modificators
|
||||
si8 Morale() const; //get morale of stack with all modificators
|
||||
si8 Luck() const; //get luck of stack with all modificators
|
||||
si32 Attack() const; //get attack of stack with all modificators
|
||||
si32 Defense(bool withFrenzy = true) const; //get defense of stack with all modificators
|
||||
ui16 MaxHealth() const; //get max HP of stack with all modifiers
|
||||
|
@ -990,7 +990,7 @@ static std::vector<StackFeature> stackEffectToFeature(const CStack::StackEffect
|
||||
sf.push_back(featureGenerator(StackFeature::SLAYER, 0, sse.level, sse.turnsRemain));
|
||||
break;
|
||||
case 56: //frenzy
|
||||
sf.push_back(featureGenerator(StackFeature::SLAYER, 0, sse.level, sse.turnsRemain));
|
||||
sf.push_back(featureGenerator(StackFeature::IN_FRENZY, 0, sse.level, sse.turnsRemain));
|
||||
break;
|
||||
case 58: //counterstrike
|
||||
sf.push_back(featureGenerator(StackFeature::ADDITIONAL_RETALIATION, 0, VLC->spellh->spells[sse.id].powers[sse.level], sse.turnsRemain));
|
||||
@ -1002,7 +1002,7 @@ static std::vector<StackFeature> stackEffectToFeature(const CStack::StackEffect
|
||||
sf.push_back(featureGenerator(StackFeature::HYPNOTIZED, 0, sse.level, sse.turnsRemain));
|
||||
break;
|
||||
case 61: //forgetfulness
|
||||
sf.push_back(featureGenerator(StackFeature::SLAYER, 0, sse.level, sse.turnsRemain));
|
||||
sf.push_back(featureGenerator(StackFeature::FORGETFULL, 0, sse.level, sse.turnsRemain));
|
||||
break;
|
||||
case 62: //blind
|
||||
sf.push_back(makeFeature(StackFeature::NOT_ACTIVE, StackFeature::UNITL_BEING_ATTACKED | StackFeature::N_TURNS, 0, 0, StackFeature::SPELL_EFFECT, sse.turnsRemain, 0));
|
||||
|
@ -359,11 +359,11 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
|
||||
{
|
||||
|
||||
//check for bad morale => freeze
|
||||
if(next->Morale() < 0 &&
|
||||
if( curB.Morale(next) < 0 &&
|
||||
!((hero1->hasBonusOfType(HeroBonus::BLOCK_MORALE)) || (hero2->hasBonusOfType(HeroBonus::BLOCK_MORALE))) //checking if heroes have (or don't have) morale blocking bonuses)
|
||||
)
|
||||
{
|
||||
if( rand()%24 < (-next->Morale())*2 )
|
||||
if( rand()%24 < (-curB.Morale(next))*2 )
|
||||
{
|
||||
//unit loses its turn - empty freeze action
|
||||
BattleAction ba;
|
||||
@ -462,10 +462,10 @@ askInterfaceForMove:
|
||||
&& !vstd::contains(next->state,DEFENDING)
|
||||
&& !vstd::contains(next->state,WAITING)
|
||||
&& next->alive()
|
||||
&& next->Morale() > 0
|
||||
&& curB.Morale(next) > 0
|
||||
&& !((hero1->hasBonusOfType(HeroBonus::BLOCK_MORALE)) || (hero2->hasBonusOfType(HeroBonus::BLOCK_MORALE)) ) //checking if heroes have (or don't have) morale blocking bonuses
|
||||
)
|
||||
if(rand()%24 < next->Morale()) //this stack hasn't got morale this turn
|
||||
if(rand()%24 < curB.Morale(next)) //this stack hasn't got morale this turn
|
||||
goto askInterfaceForMove; //move this stack once more
|
||||
}
|
||||
}
|
||||
@ -593,7 +593,8 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
|
||||
bsa->stackAttacked = def->ID;
|
||||
bsa->attackerID = att->ID;
|
||||
bsa->damageAmount = BattleInfo::calculateDmg(att, def, gs->battleGetOwner(att->ID), gs->battleGetOwner(def->ID), bat.shot(), distance);//counting dealt damage
|
||||
if(att->Luck() > 0 && rand()%24 < att->Luck())
|
||||
|
||||
if(gs->curB->Luck(att) > 0 && rand()%24 < gs->curB->Luck(att))
|
||||
{
|
||||
bsa->damageAmount *= 2;
|
||||
bat.flags |= 4;
|
||||
@ -3324,7 +3325,7 @@ static std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHero
|
||||
}
|
||||
|
||||
void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destination, ui8 casterSide, ui8 casterColor,
|
||||
const CGHeroInstance * caster, const CGHeroInstance * secHero )
|
||||
const CGHeroInstance * caster, const CGHeroInstance * secHero, int usedSpellPower )
|
||||
{
|
||||
CSpell *spell = &VLC->spellh->spells[spellID];
|
||||
|
||||
@ -3351,7 +3352,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
|
||||
{
|
||||
if(vstd::contains(sc.resisted, (*it)->ID)) //this creature resisted the spell
|
||||
continue;
|
||||
sc.dmgToDisplay += gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl);
|
||||
sc.dmgToDisplay += gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl, usedSpellPower);
|
||||
}
|
||||
|
||||
sendAndApply(&sc);
|
||||
@ -3381,7 +3382,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
|
||||
BattleStackAttacked bsa;
|
||||
bsa.flags |= 2;
|
||||
bsa.effect = spell->mainEffectAnim;
|
||||
bsa.damageAmount = gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl);
|
||||
bsa.damageAmount = gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl, usedSpellPower);
|
||||
bsa.stackAttacked = (*it)->ID;
|
||||
bsa.attackerID = -1;
|
||||
prepareAttacked(bsa,*it);
|
||||
@ -3512,7 +3513,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
||||
|
||||
sendAndApply(&StartAction(ba)); //start spell casting
|
||||
|
||||
handleSpellCasting(ba.additionalInfo, skill, ba.destinationTile, ba.side, h->tempOwner, h, secondHero);
|
||||
handleSpellCasting(ba.additionalInfo, skill, ba.destinationTile, ba.side, h->tempOwner, h, secondHero, h->getPrimSkillLevel(2));
|
||||
|
||||
sendAndApply(&EndAction());
|
||||
if( !gs->curB->getStack(gs->curB->activeStack, false)->alive() )
|
||||
@ -3994,7 +3995,7 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat )
|
||||
continue;
|
||||
|
||||
//casting
|
||||
handleSpellCasting(spellID, spellLevel, destination, !attacker->attackerOwned, attacker->owner, NULL, NULL);
|
||||
handleSpellCasting(spellID, spellLevel, destination, !attacker->attackerOwned, attacker->owner, NULL, NULL, attacker->amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ public:
|
||||
|
||||
void playerMessage( ui8 player, const std::string &message);
|
||||
bool makeBattleAction(BattleAction &ba);
|
||||
void handleSpellCasting(int spellID, int spellLvl, int destination, ui8 casterSide, ui8 casterColor, const CGHeroInstance * caster, const CGHeroInstance * secHero);
|
||||
void handleSpellCasting(int spellID, int spellLvl, int destination, ui8 casterSide, ui8 casterColor, const CGHeroInstance * caster, const CGHeroInstance * secHero, int usedSpellPower);
|
||||
bool makeCustomAction(BattleAction &ba);
|
||||
bool queryReply( ui32 qid, ui32 answer );
|
||||
bool hireHero( ui32 tid, ui8 hid );
|
||||
|
Loading…
Reference in New Issue
Block a user