1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

* new spells

- protection from air
- protection from fire
- protection from water
- protection from earth
* a bit of refactoring in spell handling code
This commit is contained in:
mateuszb 2009-04-22 10:03:13 +00:00
parent e88ba16ffa
commit d14083272d
6 changed files with 178 additions and 142 deletions

View File

@ -261,28 +261,6 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
SDL_SetColorKey(idToObstacle[obst[t].ID]->ourImages[n].bitmap, SDL_SRCCOLORKEY, SDL_MapRGB(idToObstacle[obst[t].ID]->ourImages[n].bitmap->format,0,255,255));
}
}
//initializing spellToEffect
spellToEffect[17] = 1; //lightning bolt
spellToEffect[18] = 10; //implosion
spellToEffect[27] = 27; //shield
spellToEffect[28] = 2; //air shield
spellToEffect[35] = 41; //dispel
spellToEffect[41] = 36; //bless
spellToEffect[42] = 40; //curse
spellToEffect[43] = 4; //bloodlust
spellToEffect[45] = 56; //weakness
spellToEffect[46] = 54; //stone skin
spellToEffect[47] = 14; //disrupting ray
spellToEffect[48] = 0; //prayer
spellToEffect[49] = 20; //mirth
spellToEffect[50] = 30; //sorrow
spellToEffect[51] = 18; //fortune
spellToEffect[52] = 48; //misfortune
spellToEffect[53] = 31; //haste
spellToEffect[54] = 19; //slow
spellToEffect[56] = 17; //frenzy
spellToEffect[61] = 42; //forgetfulness
}
CBattleInterface::~CBattleInterface()
@ -1863,8 +1841,11 @@ void CBattleInterface::spellCasted(SpellCasted * sc)
SDL_SetClipRect(screen, &buf); //restoring previous clip rect
break; //for 15 and 16 cases
}
case 17: //lightning bolt
displayEffect(1, sc->tile);
displayEffect(CGI->spellh->spells[sc->id].mainEffectAnim, sc->tile);
case 35: //dispel
displayEffect(spellToEffect[sc->id], sc->tile);
displayEffect(CGI->spellh->spells[sc->id].mainEffectAnim, sc->tile);
} //switch(sc->id)
}
@ -1872,7 +1853,7 @@ void CBattleInterface::battleStacksEffectsSet(const SetStackEffect & sse)
{
for(std::set<ui32>::const_iterator ci = sse.stacks.begin(); ci!=sse.stacks.end(); ++ci)
{
displayEffect(spellToEffect[sse.effect.id], LOCPLINT->cb->battleGetStackByID(*ci)->position);
displayEffect(CGI->spellh->spells[sse.effect.id].mainEffectAnim, LOCPLINT->cb->battleGetStackByID(*ci)->position);
}
redrawBackgroundWithHexes(activeStack);
}

View File

@ -165,7 +165,6 @@ private:
std::map< int, CDefHandler * > idToProjectile; //projectiles of creaures (creatureID, defhandler)
std::map< int, CDefHandler * > idToObstacle; //obstacles located on the battlefield
std::map< int, bool > creDir; // <creatureID, if false reverse creature's animation>
std::map< int, int > spellToEffect; //which effect should be played when different spells are casted (spellID, effectID)
unsigned char animCount;
int activeStack; //number of active stack; -1 - no one
int mouseHoveredStack; //stack hovered by mouse; if -1 -> none

View File

@ -1,73 +1,73 @@
//additional spell info, not included in original heroes III files
//[spellID - -1 is the end of data in file] [-1 -> spell is negative for influenced creatures; 0 - spell is indifferent for them; 1 - spell is poitive for them] [spell range description in SRSL, none magic] [basic] [advanced] [expert]
0 0 X X X X
1 0 X X X X
2 0 X X X X
3 0 X X X X
4 0 X X X X
5 0 X X X X
6 0 X X X X
7 0 X X X X
8 0 X X X X
9 0 X X X X
10 0 X X X X
11 0 X X X X
12 0 0 0 0 0
13 0 0 0 0 0
14 0 X X X X
15 -1 0 0 0 0
16 -1 0 0 0 0
17 -1 0 0 0 0
18 -1 0 0 0 0
19 -1 0 0 0 0
20 -1 1 1 1 1
21 -1 0,1 0,1 0,1 0,1
22 -1 0-2 0-2 0-2 0-2
23 -1 0,1 0,1 0,1 0,1
24 -1 X X X X
25 -1 X X X X
26 -1 X X X X
27 1 0 0 0 X
28 1 0 0 0 X
29 1 0 0 0 X
30 1 0 0 0 X
31 1 0 0 0 X
32 1 0 0 0 X
33 1 0 0 0 X
34 1 0 0 0 X
35 0 0 0 0 X
36 1 0 0 0 0
37 1 0 0 0 0
38 1 0 0 0 0
39 1 0 0 0 0
40 1 0 0 0 0
41 1 0 0 0 X
42 -1 0 0 0 X
43 1 0 0 0 X
44 1 0 0 0 X
45 -1 0 0 0 X
46 1 0 0 0 X
47 -1 0 0 0 X
48 1 0 0 0 X
49 1 0 0 0 X
50 -1 0 0 0 X
51 1 0 0 0 X
52 -1 0 0 0 X
53 1 0 0 0 X
54 -1 0 0 0 X
55 1 0 0 0 0
56 1 0 0 0 0
57 -1 0 0 0 0
58 1 0 0 0 X
59 -1 0 0 0-1 0-2
60 -1 0 0 0 0
61 -1 0 0 0 X
62 -1 0 0 0 0
63 1 0 0 0 0
64 0 X X X X
65 1 0 0 0 0
66 0 X X X X
67 0 X X X X
68 0 X X X X
69 0 X X X X
//[spellID - -1 is the end of data in file] [-1 -> spell is negative for influenced creatures; 0 - spell is indifferent for them; 1 - spell is poitive for them] [main effect animation (AC format), -1 - none] [spell range description in SRSL, none magic] [basic] [advanced] [expert]
0 0 -1 X X X X
1 0 -1 X X X X
2 0 -1 X X X X
3 0 -1 X X X X
4 0 -1 X X X X
5 0 -1 X X X X
6 0 -1 X X X X
7 0 -1 X X X X
8 0 -1 X X X X
9 0 -1 X X X X
10 0 -1 X X X X
11 0 -1 X X X X
12 0 -1 0 0 0 0
13 0 -1 0 0 0 0
14 0 -1 X X X X
15 -1 64 0 0 0 0
16 -1 46 0 0 0 0
17 -1 38 0 0 0 0
18 -1 10 0 0 0 0
19 -1 -1 0 0 0 0
20 -1 45 1 1 1 1
21 -1 53 0,1 0,1 0,1 0,1
22 -1 9 0-2 0-2 0-2 0-2
23 -1 16 0,1 0,1 0,1 0,1
24 -1 8 X X X X
25 -1 29 X X X X
26 -1 12 X X X X
27 1 27 0 0 0 X
28 1 2 0 0 0 X
29 1 -1 0 0 0 X
30 1 22 0 0 0 X
31 1 24 0 0 0 X
32 1 23 0 0 0 X
33 1 26 0 0 0 X
34 1 -1 0 0 0 X
35 0 41 0 0 0 X
36 1 -1 0 0 0 0
37 1 -1 0 0 0 0
38 1 -1 0 0 0 0
39 1 -1 0 0 0 0
40 1 -1 0 0 0 0
41 1 36 0 0 0 X
42 -1 40 0 0 0 X
43 1 4 0 0 0 X
44 1 -1 0 0 0 X
45 -1 56 0 0 0 X
46 1 54 0 0 0 X
47 -1 14 0 0 0 X
48 1 0 0 0 0 X
49 1 20 0 0 0 X
50 -1 30 0 0 0 X
51 1 18 0 0 0 X
52 -1 48 0 0 0 X
53 1 31 0 0 0 X
54 -1 19 0 0 0 X
55 1 -1 0 0 0 0
56 1 17 0 0 0 0
57 -1 -1 0 0 0 0
58 1 -1 0 0 0 X
59 -1 -1 0 0 0-1 0-2
60 -1 -1 0 0 0 0
61 -1 42 0 0 0 X
62 -1 -1 0 0 0 0
63 1 -1 0 0 0 0
64 0 -1 X X X X
65 1 -1 0 0 0 0
66 0 -1 X X X X
67 0 -1 X X X X
68 0 -1 X X X X
69 0 -1 X X X X
-1

View File

@ -255,6 +255,7 @@ void CSpellHandler::loadSpells()
nsp.id = spells.size();
nsp.combatSpell = combSpells;
nsp.creatureAbility = creatureAbility;
nsp.mainEffectAnim = -1;
spells.push_back(nsp);
}
//loading of additional spell traits
@ -268,15 +269,18 @@ void CSpellHandler::loadSpells()
{
//reading header
std::string dump;
for(int i=0; i<52; ++i) ast>>dump;
for(int i=0; i<60; ++i) ast>>dump;
//reading exact info
int spellID;
ast>>spellID;
while(spellID != -1)
{
int buf;
ast>>buf;
ast >> buf;
spells[spellID].positiveness = buf;
ast >> buf;
spells[spellID].mainEffectAnim = buf;
spells[spellID].range.resize(4);
for(int g=0; g<4; ++g)
ast>>spells[spellID].range[g];

View File

@ -38,12 +38,12 @@ public:
si8 positiveness; //1 if spell is positive for influenced stacks, 0 if it is indifferent, -1 if it's negative
std::vector<std::string> range; //description of spell's range in SRSL by magic school level
std::set<ui16> rangeInHexes(unsigned int centralHex, ui8 schoolLvl ) const; //convert range to specific hexes
si16 mainEffectAnim; //main spell effect animation, in AC format (or -1 when none)
template <typename Handler> void serialize(Handler &h, const int version)
{
h & id & name & abbName & descriptions & level & earth & water & fire & air & power & costs
& powers & probabilities & AIVals & attributes & combatSpell & creatureAbility & positiveness & range;
& powers & probabilities & AIVals & attributes & combatSpell & creatureAbility & positiveness & range & mainEffectAnim;
}
};

View File

@ -2246,6 +2246,81 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
}
}
ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature)
{
ui32 ret = 0; //value to return
switch(sp->id)
{
case 15: //magic arrow
{
ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)];
}
case 16: //ice bolt
{
ret = caster->getPrimSkillLevel(2) * 20 + sp->powers[caster->getSpellSchoolLevel(sp)];
}
case 17: //lightning bolt
{
ret = caster->getPrimSkillLevel(2) * 25 + sp->powers[caster->getSpellSchoolLevel(sp)];
}
case 18: //implosion
{
ret = caster->getPrimSkillLevel(2) * 75 + sp->powers[caster->getSpellSchoolLevel(sp)];
}
case 20: //frost ring
{
ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)];
}
case 21: //fireball
{
ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)];
}
case 22: //inferno
{
ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)];
}
case 23: //meteor shower
{
ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)];
}
case 24: //death ripple
{
ret = caster->getPrimSkillLevel(2) * 5 + sp->powers[caster->getSpellSchoolLevel(sp)];
}
case 25: //destroy undead
{
ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)];
}
case 26: //armageddon
{
ret = caster->getPrimSkillLevel(2) * 50 + sp->powers[caster->getSpellSchoolLevel(sp)];
}
}
//applying protections - when spell has more then one elements, only one protection should be applied (I think)
if(sp->air && affectedCreature->getEffect(30)) //air spell & protection from air
{
ret *= VLC->spellh->spells[30].powers[affectedCreature->getEffect(30)->level];
ret /= 100;
}
else if(sp->fire && affectedCreature->getEffect(31)) //fire spell & protection from fire
{
ret *= VLC->spellh->spells[31].powers[affectedCreature->getEffect(31)->level];
ret /= 100;
}
else if(sp->water && affectedCreature->getEffect(32)) //water spell & protection from water
{
ret *= VLC->spellh->spells[32].powers[affectedCreature->getEffect(32)->level];
ret /= 100;
}
else if (sp->earth && affectedCreature->getEffect(33)) //earth spell & protection from earth
{
ret *= VLC->spellh->spells[33].powers[affectedCreature->getEffect(33)->level];
ret /= 100;
}
return ret;
}
bool CGameHandler::makeCustomAction( BattleAction &ba )
{
switch(ba.actionType)
@ -2281,14 +2356,14 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
//TODO: check resistances
#define SPELL_CAST_TEMPLATE_2(EFFECT_ID, DAMAGE) \
#define SPELL_CAST_TEMPLATE_2 \
StacksInjured si; \
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it) \
{ \
BattleStackAttacked bsa; \
bsa.flags |= 2; \
bsa.effect = EFFECT_ID; \
bsa.damageAmount = DAMAGE; \
bsa.effect = VLC->spellh->spells[ba.additionalInfo].mainEffectAnim; \
bsa.damageAmount = calculateSpellDmg(&VLC->spellh->spells[ba.additionalInfo], h, *it); \
bsa.stackAttacked = (*it)->ID; \
prepareAttacked(bsa,*it); \
si.stacks.insert(bsa); \
@ -2306,13 +2381,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
//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(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 */
{
@ -2334,11 +2403,18 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
}
} //if(h->getSpellSchoolLevel(s) < 3)
}
else 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 //custom range from attackedHexes
{
for(std::set<ui16>::iterator it = attackedHexes.begin(); it != attackedHexes.end(); ++it)
{
CStack * st = gs->curB->getStackT(*it);
if(st)
attackedCres.insert(st);
}
}
@ -2347,43 +2423,15 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
switch(ba.additionalInfo) //spell id
{
case 15: //magic arrow
{
SPELL_CAST_TEMPLATE_2(64, h->getPrimSkillLevel(2) * 10 + s->powers[h->getSpellSchoolLevel(s)]);
break;
}
case 16: //ice bolt
{
SPELL_CAST_TEMPLATE_2(46, h->getPrimSkillLevel(2) * 20 + s->powers[h->getSpellSchoolLevel(s)]);
break;
}
case 17: //lightning bolt
{
SPELL_CAST_TEMPLATE_2(38, h->getPrimSkillLevel(2) * 25 + s->powers[h->getSpellSchoolLevel(s)]);
break;
}
case 18: //implosion
{
SPELL_CAST_TEMPLATE_2(10, h->getPrimSkillLevel(2) * 75 + s->powers[h->getSpellSchoolLevel(s)]);
break;
}
case 20: //frost ring
{
SPELL_CAST_TEMPLATE_2(45, h->getPrimSkillLevel(2) * 10 + s->powers[h->getSpellSchoolLevel(s)]);
break;
}
case 21: //fireball
{
SPELL_CAST_TEMPLATE_2(53, h->getPrimSkillLevel(2) * 10 + s->powers[h->getSpellSchoolLevel(s)]);
break;
}
case 22: //inferno
{
SPELL_CAST_TEMPLATE_2(9, h->getPrimSkillLevel(2) * 10 + s->powers[h->getSpellSchoolLevel(s)]);
break;
}
case 23: //meteor shower
{
SPELL_CAST_TEMPLATE_2(16, h->getPrimSkillLevel(2) * 10 + s->powers[h->getSpellSchoolLevel(s)]);
SPELL_CAST_TEMPLATE_2;
break;
}
case 24: //death ripple
@ -2396,7 +2444,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
attackedCres.insert(gs->curB->stacks[it]);
}
if(attackedCres.size() == 0) break;
SPELL_CAST_TEMPLATE_2(8, h->getPrimSkillLevel(2) * 5 + s->powers[h->getSpellSchoolLevel(s)]);
SPELL_CAST_TEMPLATE_2;
break;
}
case 25: //destroy undead
@ -2409,7 +2457,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
attackedCres.insert(gs->curB->stacks[it]);
}
if(attackedCres.size() == 0) break;
SPELL_CAST_TEMPLATE_2(29, h->getPrimSkillLevel(2) * 10 + s->powers[h->getSpellSchoolLevel(s)]);
SPELL_CAST_TEMPLATE_2;
break;
}
case 26: //armageddon
@ -2421,11 +2469,15 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
attackedCres.insert(gs->curB->stacks[it]);
}
if(attackedCres.size() == 0) break;
SPELL_CAST_TEMPLATE_2(12, h->getPrimSkillLevel(2) * 50 + s->powers[h->getSpellSchoolLevel(s)]);
SPELL_CAST_TEMPLATE_2;
break;
}
case 27: //shield
case 28: //air shield
case 30: //protection from air
case 31: //protection from fire
case 32: //protection from water
case 33: //protection from earth
case 41: //bless
case 42: //curse
case 43: //bloodlust