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

* support for increasing / decreasing luck / morale for allies / enemies

* support for spell 77 (thunder-sth)
This commit is contained in:
mateuszb 2010-02-24 18:11:08 +00:00
parent 0a950c508b
commit 3a76d72b69
9 changed files with 110 additions and 64 deletions

View File

@ -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;

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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));

View File

@ -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);
}
}
}

View File

@ -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 );