1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Support for Death Stare.

Some tweaks are still needed. Level 0 spell-like abilities won't work correctly.
This commit is contained in:
DjWarmonger 2011-04-23 17:10:54 +00:00
parent 61af4c745e
commit 7591d06b05
9 changed files with 92 additions and 13 deletions

View File

@ -2843,19 +2843,39 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
}
//displaying message in console
bool customSpell = false;
if(sc->affectedCres.size() == 1)
{
std::string text = CGI->generaltexth->allTexts[195];
if(sc->castedByHero)
{
boost::algorithm::replace_first(text, "%s", curInt->cb->battleGetFightingHero(sc->side)->name);
boost::algorithm::replace_first(text, "%s", curInt->cb->battleGetStackByID(*sc->affectedCres.begin(), false)->getCreature()->namePl ); //target
}
else
{
if (sc->id == 79) // Death Stare
{
customSpell = true;
if (sc->dmgToDisplay > 1)
{
text = CGI->generaltexth->allTexts[119]; //%d %s die under the terrible gaze of the %s.
boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(sc->dmgToDisplay));
boost::algorithm::replace_first(text, "%s", curInt->cb->battleGetStackByID(*sc->affectedCres.begin(), false)->getCreature()->namePl );
}
else
{
text = CGI->generaltexth->allTexts[118]; //One %s dies under the terrible gaze of the %s.
boost::algorithm::replace_first(text, "%s", curInt->cb->battleGetStackByID(*sc->affectedCres.begin())->type->nameSing);
}
boost::algorithm::replace_first(text, "%s", "Creatures"); //casting stack
}
else
boost::algorithm::replace_first(text, "%s", "Creature"); //TODO: better fix
}
if (!customSpell)
boost::algorithm::replace_first(text, "%s", CGI->spellh->spells[sc->id]->name);
boost::algorithm::replace_first(text, "%s", curInt->cb->battleGetStackByID(*sc->affectedCres.begin(), false)->getCreature()->namePl );
console->addText(text);
}
else
@ -2872,7 +2892,7 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
boost::algorithm::replace_first(text, "%s", CGI->spellh->spells[sc->id]->name);
console->addText(text);
}
if(sc->dmgToDisplay != 0)
if(sc->dmgToDisplay && !customSpell)
{
std::string dmgInfo = CGI->generaltexth->allTexts[343].substr(1, CGI->generaltexth->allTexts[343].size() - 1);
boost::algorithm::replace_first(dmgInfo, "%d", boost::lexical_cast<std::string>(sc->dmgToDisplay));

View File

@ -115,7 +115,7 @@
+ 93 SPELL_AFTER_ATTACK 0 77 20 //thunderbirds
+ 96 ENEMY_DEFENCE_REDUCTION 40 0 0 //behemots
+ 97 ENEMY_DEFENCE_REDUCTION 80 0 0 //ancient behemots
+ 103 SPELL_AFTER_ATTACK 0 79 10 //mighty gorgons
+ 103 DEATH_STARE 10 0 0 //mighty gorgons
+ 104 SPELL_AFTER_ATTACK 0 78 100 //serpent fly
+ 105 SPELL_AFTER_ATTACK 0 45 100 //mighty gorgons
+ 105 SPELL_AFTER_ATTACK 0 78 100 //dragon fly

View File

@ -18,6 +18,7 @@
31 PROTECTF.wav # protection from fire
32 PROTECTW.wav # protection from water
33 PROTECTE.wav # protection from earth
35 DISPELL.wav # dispell
41 BLESS.wav # bless
42 CURSE.wav # curse
43 BLOODLUS.wav # bloodlust
@ -35,7 +36,7 @@
55 SLAYER.wav # slayer
56 FRENZY.wav # frenzy
61 FORGET.wav # forgetfulness
79 DEATHSTR.wav # Death Stare
@ -47,7 +48,6 @@
#DEATHBLO.wav
#DRAINLIF.wav
#DRGNSLAY.wav
#DISPELL.wav
#DISGUISE.wav
#DISEASE.wav
#QUIKSAND.wav

View File

@ -79,6 +79,6 @@
76 -1 -1 0 0 0 0
77 -1 38 0 0 0 0
78 -1 41 0 0 0 0
79 -1 -1 0 0 0 0
79 0 80 0 0 0 0
80 -1 -1 0 0 0 0
-1

View File

@ -1791,8 +1791,9 @@ SpellCasting::ESpellCastProblem BattleInfo::battleIsImmune(const CGHeroInstance
std::remove_if(immunities.begin(), immunities.end(), NegateRemover);
}
if(subject->hasBonusOfType(Bonus::SPELL_IMMUNITY, spell->id)
|| ( immunities.size() > 0 && immunities.totalValue() >= spell->level))
if(subject->hasBonusOfType(Bonus::SPELL_IMMUNITY, spell->id) ||
( immunities.size() > 0 && immunities.totalValue() >= spell->level)
&& spell->level) //many creature abilities have level equal to 0, may cause bugs
{
return SpellCasting::STACK_IMMUNE_TO_SPELL;
}

View File

@ -841,6 +841,10 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, std::string & src
b.type = Bonus::CHANGES_SPELL_COST_FOR_ALLY; break;
case 'e':
b.type = Bonus::DOUBLE_DAMAGE_CHANCE; break;
case 'E':
b.type = Bonus::DEATH_STARE;
b.subtype = 0; //Gorgon
break;
case 'g':
b.type = Bonus::SPELL_DAMAGE_REDUCTION;
b.subtype = -1; //all magic schools

View File

@ -600,6 +600,7 @@ std::string CStackInstance::bonusToString(Bonus *bonus, bool description) const
case Bonus::CHANGES_SPELL_COST_FOR_ALLY:
case Bonus::CHANGES_SPELL_COST_FOR_ENEMY:
case Bonus::ENEMY_DEFENCE_REDUCTION:
case Bonus::DEATH_STARE:
boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(valOfBonuses(Selector::typeSybtype(bonus->type, bonus->subtype))));
break;
case Bonus::HATE:
@ -644,7 +645,8 @@ std::string CStackInstance::bonusToGraphics(Bonus *bonus) const
fileName = "E_CHAMP.bmp"; break;
case Bonus::DOUBLE_DAMAGE_CHANCE:
fileName = "E_DBLOW.bmp"; break;
//"E_DEATH.bmp"
case Bonus::DEATH_STARE:
fileName = "E_DEATH.bmp"; break;
//"E_DEFBON.bmp"
case Bonus::NO_DISTANCE_PENALTY:
fileName = "E_DIST.bmp"; break;

View File

@ -156,7 +156,8 @@ namespace PrimarySkill
BONUS_NAME(DRAGON_NATURE) \
BONUS_NAME(CREATURE_DAMAGE)/*subtype 0 = both, 1 = min, 2 = max*/\
BONUS_NAME(EXP_MULTIPLIER)/* val - percent of additional exp gained by stack/commander (base value 100)*/\
BONUS_NAME(SHOTS)
BONUS_NAME(SHOTS)\
BONUS_NAME(DEATH_STARE) /*subtype 0 - gorgon, 1 - commander*/
/// Struct for handling bonuses of several types. Can be transfered to any hero
struct DLL_EXPORT Bonus

View File

@ -20,6 +20,9 @@
#include "../lib/VCMIDirs.h"
#include "../client/CSoundBase.h"
#include "CGameHandler.h"
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/variate_generator.hpp>
#include <boost/random/poisson_distribution.hpp>
/*
* CGameHandler.cpp, part of VCMI engine
@ -3401,6 +3404,11 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
continue;
sc.dmgToDisplay += gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl, usedSpellPower);
}
if (spellID = 79) // Death stare
{
sc.dmgToDisplay = usedSpellPower;
amin(sc.dmgToDisplay, (*attackedCres.begin())->count); // hopefully stack is already reduced after attack
}
sendAndApply(&sc);
@ -3585,6 +3593,27 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
break;
}
case 79: //Death stare - handled in a bit different way
{
StacksInjured si;
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
{
if((*it)->hasBonusOfType (Bonus::UNDEAD) || (*it)->hasBonusOfType (Bonus::NON_LIVING)) //this creature is immune
continue;
BattleStackAttacked bsa;
bsa.flags |= BattleStackAttacked::EFFECT;
bsa.effect = spell->mainEffectAnim; //TODO: find which it is
bsa.damageAmount = usedSpellPower * (*it)->valOfBonuses(Bonus::STACK_HEALTH);
bsa.stackAttacked = (*it)->ID;
bsa.attackerID = -1;
(*it)->prepareAttacked(bsa);
si.stacks.push_back(bsa);
}
if(!si.stacks.empty())
sendAndApply(&si);
}
break;
}
}
@ -4210,6 +4239,28 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat )
}
}
}
if (attacker->hasBonusOfType(Bonus::DEATH_STARE)) // spell id 79
{
int staredCreatures = 0;
double mean = attacker->count * attacker->valOfBonuses(Bonus::DEATH_STARE, 0) / 100;
if (mean >= 1)
{
boost::poisson_distribution<int, double> p((int)mean);
boost::mt19937 rng;
boost::variate_generator<boost::mt19937&, boost::poisson_distribution<int, double>> dice (rng, p);
staredCreatures += dice();
}
if (((int)(mean * 100)) < rand() % 100) //fractional chance for one last kill
++staredCreatures;
staredCreatures += attacker->type->level * attacker->valOfBonuses(Bonus::DEATH_STARE, 1);
if (staredCreatures)
{
if (bat.bsa.size() && bat.bsa[0].newAmount > 0) //TODO: death stare was not originally avaliable for multiple-hex attacks, but...
handleSpellCasting(79, 0, gs->curB->getStack(bat.bsa[0].stackAttacked)->position,
!attacker->attackerOwned, attacker->owner, NULL, NULL, staredCreatures, SpellCasting::AFTER_ATTACK_CASTING);
}
}
}
bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &pos)