1
0
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:
DjWarmonger 2011-05-13 09:02:16 +00:00
parent 09a51acfc2
commit 515ab7e7c1
8 changed files with 90 additions and 42 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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