1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-27 22:49:25 +02:00

Moved battle effects to bonus system. May be buggy.

Moved creature damage to bonus system, simplified its handling. Some changes and tweaks.

Support for Adela's bless.
This commit is contained in:
DjWarmonger
2010-08-30 18:06:17 +00:00
parent 34b4e09927
commit bfe266a377
16 changed files with 259 additions and 248 deletions

View File

@@ -760,13 +760,13 @@ DLL_EXPORT void BattleNextRound::applyGs( CGameState *gs )
s->firstHPleft = s->MaxHealth();
//remove effects and restore only those with remaining turns in duration
std::vector<CStack::StackEffect> tmpEffects = s->effects;
s->effects.clear();
for(int i=0; i < tmpEffects.size(); i++)
BonusList tmpEffects = s->bonuses;
s->bonuses.removeSpells(Bonus::CASTED_SPELL);
for (BonusList::iterator it = tmpEffects.begin(); it != tmpEffects.end(); it++)
{
tmpEffects[i].turnsRemain--;
if(tmpEffects[i].turnsRemain > 0)
s->effects.push_back(tmpEffects[i]);
it->turnsRemain--;
if(it->turnsRemain > 0)
s->bonuses.push_back(*it);
}
//the same as above for features
@@ -929,17 +929,17 @@ DLL_EXPORT void BattleSpellCast::applyGs( CGameState *gs )
CStack *s = gs->curB->getStack(*it);
if(s && !vstd::contains(resisted, s->ID)) //if stack exists and it didn't resist
{
std::vector<CStack::StackEffect> remainingEff;
for(int g=0; g< s->effects.size(); ++g)
BonusList remainingEff;
for (BonusList::iterator it = remainingEff.begin(); it != remainingEff.end(); it++)
{
if (onlyHelpful && VLC->spellh->spells[ s->effects[g].id ].positiveness != 1)
if (onlyHelpful && VLC->spellh->spells[ it->id ].positiveness != 1)
{
remainingEff.push_back(s->effects[g]);
remainingEff.push_back(*it);
}
}
s->effects.clear(); //removing all effects
s->effects = remainingEff; //assigning effects that should remain
s->bonuses.removeSpells(Bonus::CASTED_SPELL); //removing all effects
s->bonuses = remainingEff; //assigning effects that should remain
//removing all features from spells
BonusList tmpFeatures = s->bonuses;
@@ -1000,169 +1000,23 @@ DLL_EXPORT void BattleSpellCast::applyGs( CGameState *gs )
}
}
static inline Bonus featureGenerator(Bonus::BonusType type, si16 subtype, si32 value, ui16 turnsRemain, si32 additionalInfo = 0, si32 limit = Bonus::NO_LIMIT)
{
Bonus hb(makeFeature(type, Bonus::N_TURNS, subtype, value, Bonus::SPELL_EFFECT, turnsRemain, additionalInfo));
hb.effectRange = limit;
return hb;
}
static inline Bonus featureGeneratorVT(Bonus::BonusType type, si16 subtype, si32 value, ui16 turnsRemain, ui8 valType)
{
Bonus ret(makeFeature(type, Bonus::N_TURNS, subtype, value, Bonus::SPELL_EFFECT, turnsRemain));
ret.valType = valType;
return ret;
}
static BonusList stackEffectToFeature(const CStack::StackEffect & sse)
{
BonusList sf;
si32 power = VLC->spellh->spells[sse.id].powers[sse.level];
switch(sse.id)
{
case 27: //shield
sf.push_back(featureGenerator(Bonus::GENERAL_DAMAGE_REDUCTION, 0, power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 28: //air shield
sf.push_back(featureGenerator(Bonus::GENERAL_DAMAGE_REDUCTION, 1, power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 29: //fire shield
sf.push_back(featureGenerator(Bonus::FIRE_SHIELD, 0, power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 30: //protection from air
sf.push_back(featureGenerator(Bonus::SPELL_DAMAGE_REDUCTION, 0, power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 31: //protection from fire
sf.push_back(featureGenerator(Bonus::SPELL_DAMAGE_REDUCTION, 1, power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 32: //protection from water
sf.push_back(featureGenerator(Bonus::SPELL_DAMAGE_REDUCTION, 2, power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 33: //protection from earth
sf.push_back(featureGenerator(Bonus::SPELL_DAMAGE_REDUCTION, 3, power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 34: //anti-magic
sf.push_back(featureGenerator(Bonus::LEVEL_SPELL_IMMUNITY, 0, power - 1, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 41: //bless
sf.push_back(featureGenerator(Bonus::ALWAYS_MAXIMUM_DAMAGE, -1, power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 42: //curse
sf.push_back(featureGenerator(Bonus::ALWAYS_MINIMUM_DAMAGE, -1, -1 * power, sse.turnsRemain, sse.level >= 2 ? 20 : 0));
sf.back().id = sse.id;
break;
case 43: //bloodlust
sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, power, sse.turnsRemain, 0, Bonus::ONLY_MELEE_FIGHT));
sf.back().id = sse.id;
break;
case 44: //precision
sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, power, sse.turnsRemain, 0, Bonus::ONLY_DISTANCE_FIGHT));
sf.back().id = sse.id;
break;
case 45: //weakness
sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, -1 * power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 46: //stone skin
sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 47: //disrupting ray
sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, -1 * power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 48: //prayer
sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, power, sse.turnsRemain));
sf.back().id = sse.id;
sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, power, sse.turnsRemain));
sf.back().id = sse.id;
sf.push_back(featureGenerator(Bonus::STACKS_SPEED, 0, power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 49: //mirth
sf.push_back(featureGenerator(Bonus::MORALE, 0, power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 50: //sorrow
sf.push_back(featureGenerator(Bonus::MORALE, 0, -1 * power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 51: //fortune
sf.push_back(featureGenerator(Bonus::LUCK, 0, power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 52: //misfortune
sf.push_back(featureGenerator(Bonus::LUCK, 0, -1 * power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 53: //haste
sf.push_back(featureGenerator(Bonus::STACKS_SPEED, 0, power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 54: //slow
sf.push_back(featureGeneratorVT(Bonus::STACKS_SPEED, 0, -1 * ( 100 - power ), sse.turnsRemain, Bonus::PERCENT_TO_ALL));
sf.back().id = sse.id;
break;
case 55: //slayer
sf.push_back(featureGenerator(Bonus::SLAYER, 0, sse.level, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 56: //frenzy
sf.push_back(featureGenerator(Bonus::IN_FRENZY, 0, VLC->spellh->spells[56].powers[sse.level]/100.0, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 58: //counterstrike
sf.push_back(featureGenerator(Bonus::ADDITIONAL_RETALIATION, 0, power, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 59: //bersek
sf.push_back(featureGenerator(Bonus::ATTACKS_NEAREST_CREATURE, 0, sse.level, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 60: //hypnotize
sf.push_back(featureGenerator(Bonus::HYPNOTIZED, 0, sse.level, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 61: //forgetfulness
sf.push_back(featureGenerator(Bonus::FORGETFULL, 0, sse.level, sse.turnsRemain));
sf.back().id = sse.id;
break;
case 62: //blind
sf.push_back(makeFeature(Bonus::NOT_ACTIVE, Bonus::UNITL_BEING_ATTACKED | Bonus::N_TURNS, 0, 0, Bonus::SPELL_EFFECT, sse.turnsRemain));
sf.back().id = sse.id;
sf.push_back(makeFeature(Bonus::GENERAL_ATTACK_REDUCTION, Bonus::UNTIL_ATTACK | Bonus::N_TURNS, 0, power, Bonus::SPELL_EFFECT, sse.turnsRemain));
sf.back().id = sse.id;
break;
}
return sf;
}
void actualizeEffect(CStack * s, CStack::StackEffect & ef)
void actualizeEffect(CStack * s, Bonus & ef)
{
//actualizing effects vector
for(int g=0; g<s->effects.size(); ++g)
for (BonusList::iterator it = s->bonuses.begin(); it != s->bonuses.end(); it++)
{
if(s->effects[g].id == ef.id)
if(it->id == ef.id)
{
s->effects[g].turnsRemain = std::max(s->effects[g].turnsRemain, ef.turnsRemain);
it->turnsRemain = std::max(it->turnsRemain, ef.turnsRemain);
}
}
//actualizing features vector
BonusList sf = stackEffectToFeature(ef);
BonusList sf;
s->stackEffectToFeature(sf, ef);
BOOST_FOREACH(const Bonus &fromEffect, sf)
{
BOOST_FOREACH(Bonus &stackBonus, s->bonuses)
BOOST_FOREACH(Bonus &stackBonus, s->bonuses) //TODO: optimize
{
if(stackBonus.source == Bonus::SPELL_EFFECT && stackBonus.type == fromEffect.type && stackBonus.subtype == fromEffect.subtype)
{
@@ -1173,16 +1027,6 @@ void actualizeEffect(CStack * s, CStack::StackEffect & ef)
}
bool containsEff(const std::vector<CStack::StackEffect> & vec, int effectId)
{
for(int g=0; g<vec.size(); ++g)
{
if(vec[g].id == effectId)
return true;
}
return false;
}
DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs )
{
BOOST_FOREACH(ui32 id, stacks)
@@ -1190,10 +1034,11 @@ DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs )
CStack *s = gs->curB->getStack(id);
if(s)
{
if(effect.id == 42 || !containsEff(s->effects, effect.id))//disrupting ray or not on the list - just add
if(effect.id == 42 || !s->hasBonus(Selector::source(Bonus::CASTED_SPELL, effect.id)))//disrupting ray or not on the list - just add
{
s->effects.push_back(effect);
BonusList sf = stackEffectToFeature(effect);
s->bonuses.push_back(effect);
BonusList sf;
s->stackEffectToFeature(sf, effect);
BOOST_FOREACH(const Bonus &fromEffect, sf)
{
s->bonuses.push_back(fromEffect);
@@ -1258,11 +1103,11 @@ DLL_EXPORT void StacksHealedOrResurrected::applyGs( CGameState *gs )
//removal of negative effects
if(resurrected)
{
for(int h=0; h<changedStack->effects.size(); ++h)
for (BonusList::iterator it = changedStack->bonuses.begin(); it != changedStack->bonuses.end(); it++)
{
if(VLC->spellh->spells[changedStack->effects[h].id].positiveness < 0)
if(VLC->spellh->spells[it->id].positiveness < 0)
{
changedStack->effects.erase(changedStack->effects.begin() + h);
changedStack->bonuses.erase(it);
}
}