1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-28 03:57:02 +02:00

* new spell (disrupting ray)

* a few code cleanups
This commit is contained in:
mateuszb 2009-04-21 17:32:43 +00:00
parent c8b6858716
commit 35f63bdc5f
5 changed files with 106 additions and 94 deletions

View File

@ -273,6 +273,7 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
spellToEffect[43] = 4; //bloodlust spellToEffect[43] = 4; //bloodlust
spellToEffect[45] = 56; //weakness spellToEffect[45] = 56; //weakness
spellToEffect[46] = 54; //stone skin spellToEffect[46] = 54; //stone skin
spellToEffect[47] = 14; //disrupting ray
spellToEffect[48] = 0; //prayer spellToEffect[48] = 0; //prayer
spellToEffect[49] = 20; //mirth spellToEffect[49] = 20; //mirth
spellToEffect[50] = 30; //sorrow spellToEffect[50] = 30; //sorrow
@ -1862,7 +1863,9 @@ void CBattleInterface::spellCasted(SpellCasted * sc)
SDL_SetClipRect(screen, &buf); //restoring previous clip rect SDL_SetClipRect(screen, &buf); //restoring previous clip rect
break; //for 15 and 16 cases break; //for 15 and 16 cases
} }
} case 35: //dispel
displayEffect(spellToEffect[sc->id], sc->tile);
} //switch(sc->id)
} }
void CBattleInterface::battleStacksEffectsSet(const SetStackEffect & sse) void CBattleInterface::battleStacksEffectsSet(const SetStackEffect & sse)

View File

@ -486,6 +486,17 @@ const CStack::StackEffect * CStack::getEffect(ui16 id) const
return NULL; return NULL;
} }
ui8 CStack::howManyEffectsSet(ui16 id) const
{
ui8 ret = 0;
for (int i=0; i< effects.size(); i++)
if(effects[i].id == id) //effect found
{
++ret;
}
return ret;
}
si8 CStack::Morale() const si8 CStack::Morale() const
{ {
si8 ret = morale; si8 ret = morale;
@ -1697,7 +1708,7 @@ int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, con
//calculating total attack/defense skills modifier //calculating total attack/defense skills modifier
if(attacker->getEffect(56)) //frenzy for attacker if(attacker->getEffect(56)) //frenzy for attacker
{ {
attackerAttackBonus += (VLC->spellh->spells[attacker->getEffect(56)->id].powers[attacker->getEffect(56)->level]/100.0) *(attacker->creature->defence + (attackerHero ? attackerHero->getPrimSkillLevel(1) : 0)); attackerAttackBonus += (VLC->spellh->spells[56].powers[attacker->getEffect(56)->level]/100.0) *(attacker->creature->defence + (attackerHero ? attackerHero->getPrimSkillLevel(1) : 0));
} }
if(defender->getEffect(56)) //frenzy for defender if(defender->getEffect(56)) //frenzy for defender
{ {
@ -1706,23 +1717,28 @@ int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, con
attackDefenseBonus = attackerAttackBonus - defenderDefenseBonus; attackDefenseBonus = attackerAttackBonus - defenderDefenseBonus;
if(defender->getEffect(48)) //defender's prayer handling if(defender->getEffect(48)) //defender's prayer handling
{ {
attackDefenseBonus -= VLC->spellh->spells[defender->getEffect(48)->id].powers[defender->getEffect(48)->level]; attackDefenseBonus -= VLC->spellh->spells[48].powers[defender->getEffect(48)->level];
} }
if(attacker->getEffect(48)) //attacker's prayer handling if(attacker->getEffect(48)) //attacker's prayer handling
{ {
attackDefenseBonus += VLC->spellh->spells[attacker->getEffect(48)->id].powers[attacker->getEffect(48)->level]; attackDefenseBonus += VLC->spellh->spells[48].powers[attacker->getEffect(48)->level];
}
if(defender->getEffect(47)) //defender's disrupting ray handling
{
int howMany = defender->howManyEffectsSet(47);
attackDefenseBonus += VLC->spellh->spells[47].powers[attacker->getEffect(47)->level] * howMany;
} }
if(defender->getEffect(46)) //stone skin handling if(defender->getEffect(46)) //stone skin handling
{ {
attackDefenseBonus -= VLC->spellh->spells[defender->getEffect(46)->id].powers[defender->getEffect(46)->level]; attackDefenseBonus -= VLC->spellh->spells[46].powers[defender->getEffect(46)->level];
} }
if(attacker->getEffect(45)) //weakness handling if(attacker->getEffect(45)) //weakness handling
{ {
attackDefenseBonus -= VLC->spellh->spells[attacker->getEffect(45)->id].powers[attacker->getEffect(45)->level]; attackDefenseBonus -= VLC->spellh->spells[45].powers[attacker->getEffect(45)->level];
} }
if(!shooting && attacker->getEffect(43)) //bloodlust handling if(!shooting && attacker->getEffect(43)) //bloodlust handling
{ {
attackDefenseBonus += VLC->spellh->spells[attacker->getEffect(43)->id].powers[attacker->getEffect(43)->level]; attackDefenseBonus += VLC->spellh->spells[43].powers[attacker->getEffect(43)->level];
} }
float dmgBonusMultiplier = 1.0f; float dmgBonusMultiplier = 1.0f;
@ -1828,12 +1844,12 @@ int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, con
if(attacker->getEffect(42)) //curse handling (rest) if(attacker->getEffect(42)) //curse handling (rest)
{ {
minDmg -= VLC->spellh->spells[attacker->getEffect(42)->id].powers[attacker->getEffect(42)->level]; minDmg -= VLC->spellh->spells[42].powers[attacker->getEffect(42)->level];
return minDmg; return minDmg;
} }
else if(attacker->getEffect(41)) //bless handling else if(attacker->getEffect(41)) //bless handling
{ {
maxDmg += VLC->spellh->spells[attacker->getEffect(41)->id].powers[attacker->getEffect(41)->level]; maxDmg += VLC->spellh->spells[41].powers[attacker->getEffect(41)->level];
return maxDmg; return maxDmg;
} }
else else

View File

@ -171,6 +171,7 @@ public:
CStack(CCreature * C, int A, int O, int I, bool AO, int S); CStack(CCreature * C, int A, int O, int I, bool AO, int S);
CStack() : ID(-1), creature(NULL), amount(-1), baseAmount(-1), firstHPleft(-1), owner(255), slot(255), attackerOwned(true), position(-1), counterAttacks(1), abilities(), state(), effects() {} CStack() : ID(-1), creature(NULL), amount(-1), baseAmount(-1), firstHPleft(-1), owner(255), slot(255), attackerOwned(true), position(-1), counterAttacks(1), abilities(), state(), effects() {}
const StackEffect * getEffect(ui16 id) const; //effect id (SP) const StackEffect * getEffect(ui16 id) const; //effect id (SP)
ui8 howManyEffectsSet(ui16 id) const; //returns amount of effects with given id set for this stack
bool willMove(); //if stack has remaining move this turn bool willMove(); //if stack has remaining move this turn
ui32 Speed() const; ui32 Speed() const;
si8 Morale() const; si8 Morale() const;

View File

@ -558,6 +558,14 @@ DLL_EXPORT void SpellCasted::applyGs( CGameState *gs )
{ {
gs->curB->castedSpells[side]++; gs->curB->castedSpells[side]++;
} }
if(gs->curB && id == 35) //dispel
{
CStack *s = gs->curB->getStackT(tile);
if(s)
{
s->effects.clear(); //removing all effects
}
}
} }
DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs ) DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs )
@ -567,14 +575,7 @@ DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs )
CStack *s = gs->curB->getStack(id); CStack *s = gs->curB->getStack(id);
if(s) if(s)
{ {
if(effect.id == 35) //dispel - removing all effects s->effects.push_back(effect); //adding effect
{
s->effects.clear();
}
else //adding effect
{
s->effects.push_back(effect);
}
} }
else else
tlog1 << "Cannot find stack " << id << std::endl; tlog1 << "Cannot find stack " << id << std::endl;

View File

@ -2281,42 +2281,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
//TODO: check resistances //TODO: check resistances
#define SPELL_CAST_TEMPLATE_1(NUMBER, DURATION) SetStackEffect sse; \ #define SPELL_CAST_TEMPLATE_2(EFFECT_ID, DAMAGE) \
if(h->getSpellSchoolLevel(s) < 3) /*not expert */ \
{ \
sse.stacks.insert(gs->curB->getStackT(ba.destinationTile)->ID); \
sse.effect.id = (NUMBER); \
sse.effect.level = h->getSpellSchoolLevel(s); \
sse.effect.turnsRemain = (DURATION); /*! - any duration */ \
sendAndApply(&sse); \
} \
else \
{ \
for(int it=0; it<gs->curB->stacks.size(); ++it) \
{ \
/*if it's non negative spell and our unit or non positive spell and hostile unit */ \
if((VLC->spellh->spells[ba.additionalInfo].positiveness >= 0 && gs->curB->stacks[it]->owner == h->tempOwner) \
||(VLC->spellh->spells[ba.additionalInfo].positiveness <= 0 && gs->curB->stacks[it]->owner != h->tempOwner ) \
) \
{ \
sse.stacks.insert(gs->curB->stacks[it]->ID); \
} \
} \
sse.effect.id = (NUMBER); \
sse.effect.level = h->getSpellSchoolLevel(s); \
sse.effect.turnsRemain = (DURATION); \
sendAndApply(&sse); \
}
#define SPELL_CAST_TEMPLATE_2(EFFECT_ID, DAMAGE) std::set<ui16> attackedHexes = s->rangeInHexes(ba.destinationTile, h->getSpellSchoolLevel(s)); \
std::set<CStack*> attackedCres; /*std::set to exclude multiple occurences of two hex creatures*/ \
for(std::set<ui16>::iterator it = attackedHexes.begin(); it != attackedHexes.end(); ++it) \
{ \
CStack * st = gs->curB->getStackT(*it); \
if(st) \
attackedCres.insert(st); \
} \
if(attackedCres.size() == 0) break; \
StacksInjured si; \ StacksInjured si; \
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it) \ for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it) \
{ \ { \
@ -2336,6 +2301,49 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
sc.skill = skill; sc.skill = skill;
sc.tile = ba.destinationTile; sc.tile = ba.destinationTile;
sendAndApply(&sc); sendAndApply(&sc);
//calculating affected creatures - not for all spells, but for many of them
//it should spoil anything for other spells
std::set<ui16> attackedHexes = s->rangeInHexes(ba.destinationTile, h->getSpellSchoolLevel(s));
std::set<CStack*> attackedCres; /*std::set to exclude multiple occurences of two hex creatures*/
if(VLC->spellh->spells[ba.additionalInfo].attributes.find("CREATURE_TARGET") != std::string::npos) //spell to be cast on one specific creature
{
CStack * st = gs->curB->getStackT(ba.destinationTile);
if(st)
attackedCres.insert(st);
}
else if(VLC->spellh->spells[ba.additionalInfo].attributes.find("CREATURE_TARGET_2") != std::string::npos) //spell to be cast on a specific creature but massive on expert
{
if(h->getSpellSchoolLevel(s) < 3) /*not expert */
{
CStack * st = gs->curB->getStackT(ba.destinationTile);
if(st)
attackedCres.insert(st);
}
else
{
for(int it=0; it<gs->curB->stacks.size(); ++it)
{
/*if it's non negative spell and our unit or non positive spell and hostile unit */
if((VLC->spellh->spells[ba.additionalInfo].positiveness >= 0 && gs->curB->stacks[it]->owner == h->tempOwner)
||(VLC->spellh->spells[ba.additionalInfo].positiveness <= 0 && gs->curB->stacks[it]->owner != h->tempOwner )
)
{
attackedCres.insert(gs->curB->stacks[it]);
}
}
} //if(h->getSpellSchoolLevel(s) < 3)
}
else //custom range from attackedHexes
{
for(std::set<ui16>::iterator it = attackedHexes.begin(); it != attackedHexes.end(); ++it)
{
CStack * st = gs->curB->getStackT(*it);
attackedCres.insert(st);
}
}
//affected creatures calculated
//applying effects
switch(ba.additionalInfo) //spell id switch(ba.additionalInfo) //spell id
{ {
case 15: //magic arrow case 15: //magic arrow
@ -2388,18 +2396,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
attackedCres.insert(gs->curB->stacks[it]); attackedCres.insert(gs->curB->stacks[it]);
} }
if(attackedCres.size() == 0) break; if(attackedCres.size() == 0) break;
StacksInjured si; SPELL_CAST_TEMPLATE_2(8, h->getPrimSkillLevel(2) * 5 + s->powers[h->getSpellSchoolLevel(s)]);
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
{
BattleStackAttacked bsa;
bsa.flags |= 2;
bsa.effect = 8;
bsa.damageAmount = h->getPrimSkillLevel(2) * 5 + s->powers[h->getSpellSchoolLevel(s)];
bsa.stackAttacked = (*it)->ID;
prepareAttacked(bsa,*it);
si.stacks.insert(bsa);
}
sendAndApply(&si);
break; break;
} }
case 25: //destroy undead case 25: //destroy undead
@ -2412,18 +2409,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
attackedCres.insert(gs->curB->stacks[it]); attackedCres.insert(gs->curB->stacks[it]);
} }
if(attackedCres.size() == 0) break; if(attackedCres.size() == 0) break;
StacksInjured si; SPELL_CAST_TEMPLATE_2(29, h->getPrimSkillLevel(2) * 10 + s->powers[h->getSpellSchoolLevel(s)]);
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
{
BattleStackAttacked bsa;
bsa.flags |= 2;
bsa.effect = 29;
bsa.damageAmount = h->getPrimSkillLevel(2) * 10 + s->powers[h->getSpellSchoolLevel(s)];
bsa.stackAttacked = (*it)->ID;
prepareAttacked(bsa,*it);
si.stacks.insert(bsa);
}
sendAndApply(&si);
break; break;
} }
case 26: //armageddon case 26: //armageddon
@ -2435,28 +2421,17 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
attackedCres.insert(gs->curB->stacks[it]); attackedCres.insert(gs->curB->stacks[it]);
} }
if(attackedCres.size() == 0) break; if(attackedCres.size() == 0) break;
StacksInjured si; SPELL_CAST_TEMPLATE_2(12, h->getPrimSkillLevel(2) * 50 + s->powers[h->getSpellSchoolLevel(s)]);
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
{
BattleStackAttacked bsa;
bsa.flags |= 2;
bsa.effect = 12;
bsa.damageAmount = h->getPrimSkillLevel(2) * 10 + s->powers[h->getSpellSchoolLevel(s)];
bsa.stackAttacked = (*it)->ID;
prepareAttacked(bsa,*it);
si.stacks.insert(bsa);
}
sendAndApply(&si);
break; break;
} }
case 27: //shield case 27: //shield
case 28: //air shield case 28: //air shield
case 35: //dispel
case 41: //bless case 41: //bless
case 42: //curse case 42: //curse
case 43: //bloodlust case 43: //bloodlust
case 45: //weakness case 45: //weakness
case 46: //stone skin case 46: //stone skin
case 47: //disrupting ray
case 48: //prayer case 48: //prayer
case 49: //mirth case 49: //mirth
case 50: //sorrow case 50: //sorrow
@ -2466,12 +2441,28 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
case 54: //slow case 54: //slow
case 61: //forgetfulness case 61: //forgetfulness
{ {
SPELL_CAST_TEMPLATE_1(ba.additionalInfo, h->getPrimSkillLevel(2) + h->valOfBonuses(HeroBonus::SPELL_DURATION) ) SetStackEffect sse;
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
{
sse.stacks.insert((*it)->ID);
}
sse.effect.id = ba.additionalInfo;
sse.effect.level = h->getSpellSchoolLevel(s);
sse.effect.turnsRemain = h->getPrimSkillLevel(2) + h->valOfBonuses(HeroBonus::SPELL_DURATION);
sendAndApply(&sse);
break; break;
} }
case 56: //frenzy case 56: //frenzy
{ {
SPELL_CAST_TEMPLATE_1(ba.additionalInfo, 1) SetStackEffect sse;
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
{
sse.stacks.insert((*it)->ID);
}
sse.effect.id = ba.additionalInfo;
sse.effect.level = h->getSpellSchoolLevel(s);
sse.effect.turnsRemain = 1;
sendAndApply(&sse);
break; break;
} }
} }