mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-26 22:57:00 +02:00
Support for Acid Breath (both effects are now separate).
Minor fixes.
This commit is contained in:
parent
09a51acfc2
commit
515ab7e7c1
@ -2935,6 +2935,8 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
|
|||||||
else
|
else
|
||||||
text = "";
|
text = "";
|
||||||
break;
|
break;
|
||||||
|
case 81:
|
||||||
|
break; //handled as hero spell - display damage
|
||||||
default:
|
default:
|
||||||
boost::algorithm::replace_first(text, "%s", "Creature"); //TODO: better fix
|
boost::algorithm::replace_first(text, "%s", "Creature"); //TODO: better fix
|
||||||
}
|
}
|
||||||
|
@ -239,11 +239,14 @@ void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode *
|
|||||||
int printed=0; //how many effect pics have been printed
|
int printed=0; //how many effect pics have been printed
|
||||||
std::vector<si32> spells = battleStack->activeSpells();
|
std::vector<si32> spells = battleStack->activeSpells();
|
||||||
BOOST_FOREACH(si32 effect, spells)
|
BOOST_FOREACH(si32 effect, spells)
|
||||||
|
{
|
||||||
|
if (effect < graphics->spellEffectsPics->ourImages.size()) //not all effects have graphics (for eg. Acid Breath)
|
||||||
{
|
{
|
||||||
blitAt(graphics->spellEffectsPics->ourImages[effect + 1].bitmap, 20 + 52 * printed, 184, *bitmap);
|
blitAt(graphics->spellEffectsPics->ourImages[effect + 1].bitmap, 20 + 52 * printed, 184, *bitmap);
|
||||||
if (++printed >= 10) //we can fit only 10 effects
|
if (++printed >= 10) //we can fit only 10 effects
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//print current health
|
//print current health
|
||||||
printLine (5, CGI->generaltexth->allTexts[200], battleStack->firstHPleft);
|
printLine (5, CGI->generaltexth->allTexts[200], battleStack->firstHPleft);
|
||||||
}
|
}
|
||||||
@ -314,8 +317,8 @@ void CCreatureWindow::showAll(SDL_Surface * to)
|
|||||||
printTo(count, 117, 174, FONT_SMALL, tytulowy,*bitmap);
|
printTo(count, 117, 174, FONT_SMALL, tytulowy,*bitmap);
|
||||||
printAtMiddle(c->namePl, 180, 30, FONT_SMALL, tytulowy,*bitmap); //creature name
|
printAtMiddle(c->namePl, 180, 30, FONT_SMALL, tytulowy,*bitmap); //creature name
|
||||||
|
|
||||||
printLine(0, CGI->generaltexth->primarySkillNames[0], c->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK), stackNode->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK));
|
printLine(0, CGI->generaltexth->primarySkillNames[0], c->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK), stackNode->Attack());
|
||||||
printLine(1, CGI->generaltexth->primarySkillNames[1], c->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE), stackNode->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE));
|
printLine(1, CGI->generaltexth->primarySkillNames[1], c->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE), stackNode->Defense());
|
||||||
//if(c->shots)
|
//if(c->shots)
|
||||||
// printLine(2, CGI->generaltexth->allTexts[198], c->shots);
|
// printLine(2, CGI->generaltexth->allTexts[198], c->shots);
|
||||||
if(stackNode->valOfBonuses(Bonus::SHOTS))
|
if(stackNode->valOfBonuses(Bonus::SHOTS))
|
||||||
|
@ -179,22 +179,24 @@
|
|||||||
+ 133 DRAGON_NATURE 0 0 0 //crystal dragon is a dragon
|
+ 133 DRAGON_NATURE 0 0 0 //crystal dragon is a dragon
|
||||||
+ 134 DRAGON_NATURE 0 0 0 //faerie dragon is a dragon
|
+ 134 DRAGON_NATURE 0 0 0 //faerie dragon is a dragon
|
||||||
+ 135 DRAGON_NATURE 0 0 0 //rust dragon is a dragon
|
+ 135 DRAGON_NATURE 0 0 0 //rust dragon is a dragon
|
||||||
|
+ 135 ACID_BREATH 25 0 20 //20% chance to do 25 damage
|
||||||
|
+ 135 SPELL_AFTER_ATTACK 100 80 0 //always reduce defense
|
||||||
+ 136 NO_OBSTACLES_PENALTY 0 0 0 //Enchanter
|
+ 136 NO_OBSTACLES_PENALTY 0 0 0 //Enchanter
|
||||||
+ 137 NO_DISTANCE_PENALTY 0 0 0 //Sharpshooter
|
+ 137 NO_DISTANCE_PENALTY 0 0 0 //Sharpshooter
|
||||||
+ 137 NO_OBSTACLES_PENALTY 0 0 0
|
+ 137 NO_OBSTACLES_PENALTY 0 0 0
|
||||||
+ 140 DOUBLE_WIDE 0 0 0 //boar should be treated as double-wide
|
+ 140 DOUBLE_WIDE 0 0 0 //boar should be treated as double-wide
|
||||||
+ 142 DOUBLE_WIDE 0 0 0 //nomads should be treated as double-wide
|
+ 142 DOUBLE_WIDE 0 0 0 //nomads should be treated as double-wide //first aid tent can heal
|
||||||
+ 144 FULL_HP_REGENERATION 0 0 0 //troll
|
+ 144 FULL_HP_REGENERATION 0 0 0 //troll //Ammo Cart
|
||||||
+ 147 HEALER 0 0 0 //first aid tent can heal
|
+ 147 HEALER 0 0 0 //arrow turret
|
||||||
+ 148 NOT_ACTIVE 0 0 0 //Ammo Cart
|
+ 148 NOT_ACTIVE 0 0 0
|
||||||
+ 149 SHOOTER 0 0 0 //arrow turret
|
+ 149 SHOOTER 0 0 0
|
||||||
+ 151 DRAGON_NATURE 0 0 0 //diamond dragon is a dragon
|
+ 151 DRAGON_NATURE 0 0 0 //diamond dragon is a dragon
|
||||||
+ 154 DRAGON_NATURE 0 0 0 //blood dragon is a dragon
|
+ 154 DRAGON_NATURE 0 0 0 //blood dragon is a dragon //Gorynyches fly
|
||||||
+ 155 DRAGON_NATURE 0 0 0 //darkness dragon is a dragon
|
+ 155 DRAGON_NATURE 0 0 0 //darkness dragon is a dragon //hell hound doesn't fly
|
||||||
+ 168 FLYING 0 0 0 //Gorynyches fly
|
+ 168 FLYING 0 0 0 //cerberus doesn't fly
|
||||||
- 46 FLYING //hell hound doesn't fly
|
- 46 FLYING //psychic elemental
|
||||||
- 47 FLYING //cerberus doesn't fly
|
- 47 FLYING //magic elemental
|
||||||
- 120 DOUBLE_WIDE //psychic elemental
|
- 120 DOUBLE_WIDE
|
||||||
- 121 DOUBLE_WIDE //magic elemental
|
- 121 DOUBLE_WIDE
|
||||||
- 157 SHOOTER //Hell Hydra certainly does not shoot
|
- 157 SHOOTER //Hell Hydra certainly does not shoot
|
||||||
0
|
0
|
||||||
|
@ -1792,7 +1792,7 @@ SpellCasting::ESpellCastProblem BattleInfo::battleIsImmune(const CGHeroInstance
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(subject->hasBonusOfType(Bonus::SPELL_IMMUNITY, spell->id) ||
|
if(subject->hasBonusOfType(Bonus::SPELL_IMMUNITY, spell->id) ||
|
||||||
( immunities.size() > 0 && immunities.totalValue() >= spell->level)) //many creature abilities have level equal to 0 by default, fixed in config\spell_levels
|
( immunities.size() > 0 && immunities.totalValue() >= spell->level && spell->level))
|
||||||
{
|
{
|
||||||
return SpellCasting::STACK_IMMUNE_TO_SPELL;
|
return SpellCasting::STACK_IMMUNE_TO_SPELL;
|
||||||
}
|
}
|
||||||
@ -2167,6 +2167,12 @@ void CStack::stackEffectToFeature(std::vector<Bonus> & sf, const Bonus & sse)
|
|||||||
sf.push_back(featureGeneratorVT(Bonus::STACK_HEALTH, 0, -50, 3, Bonus::PERCENT_TO_ALL));
|
sf.push_back(featureGeneratorVT(Bonus::STACK_HEALTH, 0, -50, 3, Bonus::PERCENT_TO_ALL));
|
||||||
sf.back().sid = sse.sid;
|
sf.back().sid = sse.sid;
|
||||||
break;
|
break;
|
||||||
|
case 80: //Acid Breath
|
||||||
|
sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, -3, 1));
|
||||||
|
sf.back().sid = sse.sid;
|
||||||
|
sf.back().duration = Bonus::PERMANENT;
|
||||||
|
sf.back().valType = Bonus::ADDITIVE_VALUE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,23 +322,24 @@ void CSpellHandler::loadSpells()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.close();
|
ast.close();
|
||||||
ast.open(DATA_DIR "/config/spell_levels.txt", std::ios::binary);
|
//ast.open(DATA_DIR "/config/spell_levels.txt", std::ios::binary);
|
||||||
if(!ast.is_open())
|
//if(!ast.is_open())
|
||||||
{
|
//{
|
||||||
tlog1<<"lack of config/spell_levels.txt file!"<<std::endl;
|
// tlog1<<"lack of config/spell_levels.txt file!"<<std::endl;
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
{
|
//{
|
||||||
//custom levels of spells. Level 0 seems to not be supported correctly, but we can replace it it something else
|
// //custom levels of spells. Level 0 seems to not be supported correctly, but we can replace it it something else
|
||||||
int spellID;
|
// int spellID;
|
||||||
ast>>spellID;
|
// ast>>spellID;
|
||||||
int buf;
|
// int buf;
|
||||||
while(spellID != -1)
|
// while(spellID != -1)
|
||||||
{
|
// {
|
||||||
ast >> buf;
|
// ast >> buf;
|
||||||
spells[spellID]->level = buf;
|
// spells[spellID]->level = buf;
|
||||||
ast>>spellID;
|
// ast>>spellID;
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
ast.close();
|
//ast.close();
|
||||||
|
spells.push_back(spells[80]); //clone Acid Breath attributes for Acid Breath damage effect
|
||||||
}
|
}
|
||||||
|
@ -269,6 +269,7 @@ si32 IBonusBearer::Attack() const
|
|||||||
{
|
{
|
||||||
ret += frenzyPower * Defense(false);
|
ret += frenzyPower * Defense(false);
|
||||||
}
|
}
|
||||||
|
amax(ret, 0);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -281,6 +282,7 @@ si32 IBonusBearer::Defense(bool withFrenzy /*= true*/) const
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
amax(ret, 0);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,8 @@ namespace PrimarySkill
|
|||||||
BONUS_NAME(SHOTS)\
|
BONUS_NAME(SHOTS)\
|
||||||
BONUS_NAME(DEATH_STARE) /*subtype 0 - gorgon, 1 - commander*/\
|
BONUS_NAME(DEATH_STARE) /*subtype 0 - gorgon, 1 - commander*/\
|
||||||
BONUS_NAME(POISON) /*val - max health penalty from poison possible*/\
|
BONUS_NAME(POISON) /*val - max health penalty from poison possible*/\
|
||||||
BONUS_NAME(BIND_EFFECT) /*doesn't do anything particular, works as a marker)*/
|
BONUS_NAME(BIND_EFFECT) /*doesn't do anything particular, works as a marker)*/\
|
||||||
|
BONUS_NAME(ACID_BREATH) /*additional val damage per creature after attack, additional info - chance in percent*/
|
||||||
|
|
||||||
/// Struct for handling bonuses of several types. Can be transfered to any hero
|
/// Struct for handling bonuses of several types. Can be transfered to any hero
|
||||||
struct DLL_EXPORT Bonus
|
struct DLL_EXPORT Bonus
|
||||||
|
@ -3397,9 +3397,10 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
|
|||||||
continue;
|
continue;
|
||||||
sc.dmgToDisplay += gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl, usedSpellPower);
|
sc.dmgToDisplay += gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl, usedSpellPower);
|
||||||
}
|
}
|
||||||
if (spellID == 79) // Death stare
|
if (spellID == 79 || spellID == 81) // Death stare or Acid Breath
|
||||||
{
|
{
|
||||||
sc.dmgToDisplay = usedSpellPower;
|
sc.dmgToDisplay = usedSpellPower;
|
||||||
|
if (spellID == 79)
|
||||||
amin(sc.dmgToDisplay, (*attackedCres.begin())->count); //stack is already reduced after attack
|
amin(sc.dmgToDisplay, (*attackedCres.begin())->count); //stack is already reduced after attack
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3474,6 +3475,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
|
|||||||
case 73: //Disease
|
case 73: //Disease
|
||||||
case 74: //Paralyze
|
case 74: //Paralyze
|
||||||
case 75: //Aging
|
case 75: //Aging
|
||||||
|
case 80: //Acid Breath defense reduction
|
||||||
{
|
{
|
||||||
SetStackEffect sse;
|
SetStackEffect sse;
|
||||||
Bonus pseudoBonus;
|
Bonus pseudoBonus;
|
||||||
@ -3529,7 +3531,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
|
|||||||
}
|
}
|
||||||
if (caster && caster->hasBonusOfType(Bonus::SPECIAL_BLESS_DAMAGE, spellID)) //TODO: better handling of bonus percentages
|
if (caster && caster->hasBonusOfType(Bonus::SPECIAL_BLESS_DAMAGE, spellID)) //TODO: better handling of bonus percentages
|
||||||
{
|
{
|
||||||
int damagePercent = caster->level * caster->valOfBonuses(Bonus::SPECIAL_BLESS_DAMAGE, 41) / tier;
|
int damagePercent = caster->level * caster->valOfBonuses(Bonus::SPECIAL_BLESS_DAMAGE, spellID) / tier;
|
||||||
Bonus specialBonus = CStack::featureGenerator(Bonus::CREATURE_DAMAGE, 0, damagePercent, pseudoBonus.turnsRemain);
|
Bonus specialBonus = CStack::featureGenerator(Bonus::CREATURE_DAMAGE, 0, damagePercent, pseudoBonus.turnsRemain);
|
||||||
specialBonus.valType = Bonus::PERCENT_TO_ALL;
|
specialBonus.valType = Bonus::PERCENT_TO_ALL;
|
||||||
specialBonus.sid = spellID;
|
specialBonus.sid = spellID;
|
||||||
@ -3617,10 +3619,27 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
|
|||||||
sendAndApply(&si);
|
sendAndApply(&si);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 81: //Acid breath damage - new effect, separate from acid breath defense reduction
|
||||||
|
{
|
||||||
|
StacksInjured si;
|
||||||
|
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it) //no immunities
|
||||||
|
{
|
||||||
|
BattleStackAttacked bsa;
|
||||||
|
bsa.flags |= BattleStackAttacked::EFFECT;
|
||||||
|
bsa.effect = VLC->spellh->spells[80]->mainEffectAnim; //use acid breath
|
||||||
|
bsa.damageAmount = usedSpellPower; //damage times the number of attackers
|
||||||
|
bsa.stackAttacked = (*it)->ID;
|
||||||
|
bsa.attackerID = -1;
|
||||||
|
(*it)->prepareAttacked(bsa);
|
||||||
|
si.stacks.push_back(bsa);
|
||||||
|
}
|
||||||
|
if(!si.stacks.empty())
|
||||||
|
sendAndApply(&si);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendAndApply(&sc);
|
sendAndApply(&sc);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGameHandler::makeCustomAction( BattleAction &ba )
|
bool CGameHandler::makeCustomAction( BattleAction &ba )
|
||||||
@ -4286,6 +4305,18 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat )
|
|||||||
!attacker->attackerOwned, attacker->owner, NULL, NULL, staredCreatures, SpellCasting::AFTER_ATTACK_CASTING);
|
!attacker->attackerOwned, attacker->owner, NULL, NULL, staredCreatures, SpellCasting::AFTER_ATTACK_CASTING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
int acidDamage = 0;
|
||||||
|
BOOST_FOREACH(const Bonus *b, attacker->getBonuses(Selector::type(Bonus::ACID_BREATH)))
|
||||||
|
{
|
||||||
|
if (b->additionalInfo > rand()%100)
|
||||||
|
acidDamage += b->val;
|
||||||
|
}
|
||||||
|
if (acidDamage)
|
||||||
|
{
|
||||||
|
handleSpellCasting(81, 0, gs->curB->getStack(bat.bsa[0].stackAttacked)->position,
|
||||||
|
!attacker->attackerOwned, attacker->owner, NULL, NULL,
|
||||||
|
acidDamage * attacker->count, SpellCasting::AFTER_ATTACK_CASTING);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &pos)
|
bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &pos)
|
||||||
|
Loading…
Reference in New Issue
Block a user