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:
parent
61af4c745e
commit
7591d06b05
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user