1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003 The GemRB Project
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 //This class represents the .spl (spell) files of the game.
29 #include "Interface.h"
30 #include "Projectile.h"
31 #include "ProjectileServer.h"
33 SPLExtHeader::SPLExtHeader(void)
38 SPLExtHeader::~SPLExtHeader(void)
46 casting_features
= NULL
;
51 //Spell is in the core, so this is not needed, i guess (Avenger)
52 //core->FreeSPLExt(ext_headers, casting_features);
53 delete [] ext_headers
;
54 delete [] casting_features
;
57 int Spell::GetHeaderIndexFromLevel(int level
) const
59 if (level
<0) return -1;
60 if (Flags
& SF_SIMPLIFIED_DURATION
) {
64 for(block_index
=0;block_index
<ExtHeaderCount
-1;block_index
++) {
65 if (ext_headers
[block_index
+1].RequiredLevel
>level
) {
69 return ExtHeaderCount
-1;
73 //0 will always return first spell block
74 //otherwise set to caster level
75 static EffectRef fx_casting_glow_ref
={"CastingGlow",NULL
,-1};
77 void Spell::AddCastingGlow(EffectQueue
*fxqueue
, ieDword duration
)
79 Effect
*fx
= EffectQueue::CreateEffect(fx_casting_glow_ref
, 0, CastingGraphics
, FX_DURATION_ABSOLUTE
);
80 fx
->Duration
= core
->GetGame()->GameTime
+ duration
;
81 fx
->InventorySlot
= 0xffff;
83 fxqueue
->AddEffect(fx
);
84 //AddEffect creates a copy, we need to destroy the original
88 EffectQueue
*Spell::GetEffectBlock(Scriptable
*self
, const Point
&pos
, int block_index
, ieDword pro
) const
95 if (Flags
& SF_SIMPLIFIED_DURATION
) {
96 features
= ext_headers
[0].features
;
97 count
= ext_headers
[0].FeatureCount
;
99 features
= ext_headers
[block_index
].features
;
100 count
= ext_headers
[block_index
].FeatureCount
;
103 features
= casting_features
;
104 count
= CastingFeatureCount
;
106 EffectQueue
*fxqueue
= new EffectQueue();
108 for (int i
=0;i
<count
;i
++) {
109 if (Flags
& SF_SIMPLIFIED_DURATION
) {
110 //hack the effect according to Level
111 //fxqueue->AddEffect will copy the effect,
112 //so we don't risk any overwriting
113 if (EffectQueue::HasDuration(features
+i
)) {
114 features
[i
].Duration
= (TimePerLevel
*block_index
+TimeConstant
)*7;
117 //fill these for completeness, inventoryslot is a good way
118 //to discern a spell from an item effect
119 features
[i
].InventorySlot
= 0xffff;
120 if (features
[i
].Target
!= FX_TARGET_SELF
) {
121 features
[i
].Projectile
= pro
;
122 fxqueue
->AddEffect( features
+i
);
124 Actor
*target
= (self
->Type
==ST_ACTOR
)?(Actor
*) self
:NULL
;
125 features
[i
].Projectile
= 0;
126 features
[i
].PosX
=pos
.x
;
127 features
[i
].PosY
=pos
.y
;
129 //This is bad, effects should be able to affect non living targets
130 //This is done by NULL target, the position should be enough
131 //to tell which non-actor object is affected
133 core
->ApplyEffect(features
+i
, target
, self
);
140 Projectile
*Spell::GetProjectile(Scriptable
*self
, int header
, const Point
&target
) const
142 SPLExtHeader
*seh
= GetExtHeader(header
);
144 printMessage("Spell", "Cannot retrieve spell header!!! ",RED
);
145 printf("required header: %d, maximum: %d\n", header
, (int) ExtHeaderCount
);
148 Projectile
*pro
= core
->GetProjectileServer()->GetProjectileByIndex(seh
->ProjectileAnimation
);
149 if (seh
->FeatureCount
) {
150 pro
->SetEffects(GetEffectBlock(self
, target
, header
, seh
->ProjectileAnimation
));
155 //get the casting distance of the spell
156 //it depends on the casting level of the actor
157 //if actor isn't given, then the first header is used
158 //TODO: fix casting level for all class combos
159 unsigned int Spell::GetCastingDistance(Actor
*actor
) const
163 level
= actor
->GetStat(IE_LEVEL
);
164 if(SpellType
==IE_SPL_WIZARD
) {
165 level
+=actor
->GetStat(IE_CASTINGLEVELBONUSMAGE
);
167 else if(SpellType
==IE_SPL_PRIEST
) {
168 level
+=actor
->GetStat(IE_CASTINGLEVELBONUSCLERIC
);
173 int idx
= GetHeaderIndexFromLevel(level
);
174 SPLExtHeader
*seh
= GetExtHeader(idx
);
176 printMessage("Spell", "Cannot retrieve spell header!!! ",RED
);
177 printf("required header: %d, maximum: %d\n", idx
, (int) ExtHeaderCount
);
180 return (unsigned int) seh
->Range
;