1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-06 09:09:40 +02:00

Support for Death Blow ability.

This commit is contained in:
DjWarmonger
2011-07-06 17:00:45 +00:00
parent c53c226820
commit 8102fd4cf0
6 changed files with 46 additions and 16 deletions

View File

@@ -717,6 +717,7 @@ BattleAction CPlayerInterface::activeStack(const CStack * stack) //called when i
} }
b->stackActivated(stack); b->stackActivated(stack);
//Regeneration & mana drain go there
} }
//wait till BattleInterface sets its command //wait till BattleInterface sets its command
boost::unique_lock<boost::mutex> lock(b->givenCommand->mx); boost::unique_lock<boost::mutex> lock(b->givenCommand->mx);
@@ -822,11 +823,24 @@ void CPlayerInterface::battleAttack(const BattleAttack *ba)
{ {
const CStack *stack = cb->battleGetStackByID(ba->stackAttacking); const CStack *stack = cb->battleGetStackByID(ba->stackAttacking);
std::string hlp = CGI->generaltexth->allTexts[45]; std::string hlp = CGI->generaltexth->allTexts[45];
boost::algorithm::replace_first(hlp,"%s",(stack->count != 1) ? stack->getCreature()->namePl.c_str() : stack->getCreature()->nameSing.c_str()); boost::algorithm::replace_first(hlp,"%s", (stack->count != 1) ? stack->getCreature()->namePl.c_str() : stack->getCreature()->nameSing.c_str());
battleInt->console->addText(hlp); battleInt->console->addText(hlp);
battleInt->displayEffect(18,stack->position); battleInt->displayEffect(18, stack->position);
} }
//TODO: bad luck? //TODO: bad luck?
if (ba->deathBlow())
{
const CStack *stack = cb->battleGetStackByID(ba->stackAttacking);
std::string hlp = CGI->generaltexth->allTexts[(stack->count != 1) ? 336 : 335];
boost::algorithm::replace_first(hlp,"%s", (stack->count != 1) ? stack->getCreature()->namePl.c_str() : stack->getCreature()->nameSing.c_str());
battleInt->console->addText(hlp);
for (std::vector<BattleStackAttacked>::const_iterator i = ba->bsa.begin(); i != ba->bsa.end(); i++)
{
const CStack * attacked = cb->battleGetStackByID(i->stackAttacked);
battleInt->displayEffect(73, attacked->position);
}
}
const CStack * attacker = cb->battleGetStackByID(ba->stackAttacking); const CStack * attacker = cb->battleGetStackByID(ba->stackAttacking);
@@ -834,15 +848,15 @@ void CPlayerInterface::battleAttack(const BattleAttack *ba)
{ {
for(std::vector<BattleStackAttacked>::const_iterator i = ba->bsa.begin(); i != ba->bsa.end(); i++) for(std::vector<BattleStackAttacked>::const_iterator i = ba->bsa.begin(); i != ba->bsa.end(); i++)
{ {
const CStack * attacked = cb->battleGetStackByID(i->stackAttacked);
if (!i->isSecondary()) //display projectile only for primary target if (!i->isSecondary()) //display projectile only for primary target
{ {
const CStack * attacked = cb->battleGetStackByID(i->stackAttacked);
battleInt->stackAttacking(attacker, cb->battleGetPos(i->stackAttacked), attacked, true); battleInt->stackAttacking(attacker, cb->battleGetPos(i->stackAttacked), attacked, true);
} }
} }
} }
else else
{//TODO: support multiple attacked creatures {
int shift = 0; int shift = 0;
if(ba->counter() && THex::mutualPosition(curAction->destinationTile, attacker->position) < 0) if(ba->counter() && THex::mutualPosition(curAction->destinationTile, attacker->position) < 0)
{ {

View File

@@ -425,7 +425,8 @@ std::pair< std::vector<THex>, int > BattleInfo::getPath(THex start, THex dest, b
return std::make_pair(path, dist[dest]); return std::make_pair(path, dist[dest]);
} }
TDmgRange BattleInfo::calculateDmgRange( const CStack* attacker, const CStack* defender, TQuantity attackerCount, TQuantity defenderCount, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky, bool ballistaDoubleDmg ) const TDmgRange BattleInfo::calculateDmgRange( const CStack* attacker, const CStack* defender, TQuantity attackerCount, TQuantity defenderCount, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero,
bool shooting, ui8 charge, bool lucky, bool deathBlow, bool ballistaDoubleDmg ) const
{ {
float additiveBonus=1.0f, multBonus=1.0f, float additiveBonus=1.0f, multBonus=1.0f,
minDmg = attacker->getMinDamage() * attackerCount, minDmg = attacker->getMinDamage() * attackerCount,
@@ -575,6 +576,11 @@ TDmgRange BattleInfo::calculateDmgRange( const CStack* attacker, const CStack* d
additiveBonus += 1.0f; additiveBonus += 1.0f;
} }
if (deathBlow) //Dread Knight and many WoGified creatures
{
additiveBonus += 1.0f;
}
//handling spell effects //handling spell effects
if(!shooting && defender->hasBonusOfType(Bonus::GENERAL_DAMAGE_REDUCTION, 0)) //eg. shield if(!shooting && defender->hasBonusOfType(Bonus::GENERAL_DAMAGE_REDUCTION, 0)) //eg. shield
{ {
@@ -647,14 +653,16 @@ TDmgRange BattleInfo::calculateDmgRange( const CStack* attacker, const CStack* d
return returnedVal; return returnedVal;
} }
TDmgRange BattleInfo::calculateDmgRange(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky, bool ballistaDoubleDmg) const TDmgRange BattleInfo::calculateDmgRange(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero,
bool shooting, ui8 charge, bool lucky, bool deathBlow, bool ballistaDoubleDmg) const
{ {
return calculateDmgRange(attacker, defender, attacker->count, defender->count, attackerHero, defendingHero, shooting, charge, lucky, ballistaDoubleDmg); return calculateDmgRange(attacker, defender, attacker->count, defender->count, attackerHero, defendingHero, shooting, charge, lucky, deathBlow, ballistaDoubleDmg);
} }
ui32 BattleInfo::calculateDmg( const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky, bool ballistaDoubleDmg ) ui32 BattleInfo::calculateDmg( const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero,
bool shooting, ui8 charge, bool lucky, bool deathBlow, bool ballistaDoubleDmg )
{ {
TDmgRange range = calculateDmgRange(attacker, defender, attackerHero, defendingHero, shooting, charge, lucky, ballistaDoubleDmg); TDmgRange range = calculateDmgRange(attacker, defender, attackerHero, defendingHero, shooting, charge, lucky, deathBlow, ballistaDoubleDmg);
if(range.first != range.second) if(range.first != range.second)
{ {

View File

@@ -83,9 +83,9 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode
bool isStackBlocked(const CStack * stack) const; //returns true if there is neighboring enemy stack bool isStackBlocked(const CStack * stack) const; //returns true if there is neighboring enemy stack
ui32 calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky, bool ballistaDoubleDmg); //charge - number of hexes travelled before attack (for champion's jousting) ui32 calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky, bool deathBlow, bool ballistaDoubleDmg); //charge - number of hexes travelled before attack (for champion's jousting)
TDmgRange calculateDmgRange( const CStack* attacker, const CStack* defender, TQuantity attackerCount, TQuantity defenderCount, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky, bool ballistaDoubleDmg) const; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg> TDmgRange calculateDmgRange(const CStack* attacker, const CStack* defender, TQuantity attackerCount, TQuantity defenderCount, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky, bool deathBlow, bool ballistaDoubleDmg) const; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
TDmgRange calculateDmgRange(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky, bool ballistaDoubleDmg) const; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg> TDmgRange calculateDmgRange(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky, bool deathBlow, bool ballistaDoubleDmg) const; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
void calculateCasualties(std::map<ui32,si32> *casualties) const; //casualties are array of maps size 2 (attacker, defeneder), maps are (crid => amount) void calculateCasualties(std::map<ui32,si32> *casualties) const; //casualties are array of maps size 2 (attacker, defeneder), maps are (crid => amount)
std::set<CStack*> getAttackedCreatures(const CSpell * s, int skillLevel, ui8 attackerOwner, THex destinationTile); //calculates stack affected by given spell std::set<CStack*> getAttackedCreatures(const CSpell * s, int skillLevel, ui8 attackerOwner, THex destinationTile); //calculates stack affected by given spell
std::set<CStack*> getAttackedCreatures(const CStack* attacker, THex destinationTile); //calculates range of multi-hex attacks std::set<CStack*> getAttackedCreatures(const CStack* attacker, THex destinationTile); //calculates range of multi-hex attacks

View File

@@ -299,7 +299,7 @@ TDmgRange CBattleInfoCallback::battleEstimateDamage(const CStack * attacker, con
defenderHero = gs->curB->heroes[0]; defenderHero = gs->curB->heroes[0];
} }
TDmgRange ret = gs->curB->calculateDmgRange(attacker, defender, attackerHero, defenderHero, shooting, 0, false, false); TDmgRange ret = gs->curB->calculateDmgRange(attacker, defender, attackerHero, defenderHero, shooting, 0, false, false, false);
if(retaliationDmg) if(retaliationDmg)
{ {
@@ -314,7 +314,7 @@ TDmgRange CBattleInfoCallback::battleEstimateDamage(const CStack * attacker, con
{ {
BattleStackAttacked bsa; BattleStackAttacked bsa;
bsa.damageAmount = ret.*pairElems[i]; bsa.damageAmount = ret.*pairElems[i];
retaliationDmg->*pairElems[!i] = gs->curB->calculateDmgRange(defender, attacker, bsa.newAmount, attacker->count, attackerHero, defenderHero, false, false, false, false).*pairElems[!i]; retaliationDmg->*pairElems[!i] = gs->curB->calculateDmgRange(defender, attacker, bsa.newAmount, attacker->count, attackerHero, defenderHero, false, 0, false, false, false).*pairElems[!i];
} }
} }
} }

View File

@@ -1306,7 +1306,7 @@ struct BattleAttack : public CPackForClient//3006
std::vector<BattleStackAttacked> bsa; std::vector<BattleStackAttacked> bsa;
ui32 stackAttacking; ui32 stackAttacking;
ui8 flags; //uses Eflags (below) ui8 flags; //uses Eflags (below)
enum EFlags{SHOT = 1, COUNTER = 2, LUCKY = 4, UNLUCKY = 8, BALLISTA_DOUBLE_DMG = 16}; enum EFlags{SHOT = 1, COUNTER = 2, LUCKY = 4, UNLUCKY = 8, BALLISTA_DOUBLE_DMG = 16, DEATH_BLOW = 32};
bool shot() const//distance attack - decrease number of shots bool shot() const//distance attack - decrease number of shots
{ {
@@ -1329,6 +1329,10 @@ struct BattleAttack : public CPackForClient//3006
{ {
return flags & BALLISTA_DOUBLE_DMG; return flags & BALLISTA_DOUBLE_DMG;
} }
bool deathBlow() const
{
return flags & DEATH_BLOW;
}
//bool killed() //if target stack was killed //bool killed() //if target stack was killed
//{ //{
// return bsa.killed(); // return bsa.killed();

View File

@@ -522,6 +522,10 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
{ {
bat.flags |= BattleAttack::LUCKY; bat.flags |= BattleAttack::LUCKY;
} }
if (rand()%100 < att->valOfBonuses(Bonus::DOUBLE_DAMAGE_CHANCE))
{
bat.flags |= BattleAttack::DEATH_BLOW;
}
if(att->getCreature()->idNumber == 146) if(att->getCreature()->idNumber == 146)
{ {
@@ -575,7 +579,7 @@ void CGameHandler::applyBattleEffects(BattleAttack &bat, const CStack *att, cons
bsa.flags |= BattleStackAttacked::SECONDARY; //all other targets do not suffer from spells & spell-like abilities bsa.flags |= BattleStackAttacked::SECONDARY; //all other targets do not suffer from spells & spell-like abilities
bsa.attackerID = att->ID; bsa.attackerID = att->ID;
bsa.stackAttacked = def->ID; bsa.stackAttacked = def->ID;
bsa.damageAmount = gs->curB->calculateDmg(att, def, gs->curB->battleGetOwner(att), gs->curB->battleGetOwner(def), bat.shot(), distance, bat.lucky(), bat.ballistaDoubleDmg()); bsa.damageAmount = gs->curB->calculateDmg(att, def, gs->curB->battleGetOwner(att), gs->curB->battleGetOwner(def), bat.shot(), distance, bat.lucky(), bat.deathBlow(), bat.ballistaDoubleDmg());
def->prepareAttacked(bsa); //calculate casualties def->prepareAttacked(bsa); //calculate casualties
bat.bsa.push_back(bsa); //add this stack to the list of victims bat.bsa.push_back(bsa); //add this stack to the list of victims