1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2006 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.
23 * Declares Projectile, class for supporting functionality of spell/item projectiles
24 * @author The GemRB Project
34 #include "CharAnimations.h" //contains MAX_ORIENT
37 #include "PathFinder.h"
39 //this is the height of the projectile when Spark Flag Fly = 1
41 //this is supposed to move the projectile to the background
46 #define P_TRAVEL 0 //projectile moves to target
47 #define P_TRIGGER 1 //projectile hovers over target, waits for trigger
48 #define P_EXPLODING1 2 //projectile explosion spreads
49 #define P_EXPLODING2 3 //projectile explosion repeats
50 #define P_EXPLODED 4 //projectile spread over area
51 #define P_EXPIRED 99 //projectile scheduled for removal (existing parts are still drawn)
53 //projectile spark flags
56 #define PSF_LOOPING 4 //looping sound
57 #define PSF_IGNORE_CENTER 16
59 //projectile travel flags
60 #define PTF_COLOUR 1 //fake colours
61 #define PTF_SMOKE 2 //has smoke
62 #define PTF_TINT 8 //tint projectile
63 #define PTF_SHADOW 32 //has shadow bam
64 #define PTF_LIGHT 64 //has light shadow
65 #define PTF_BLEND 128 //blend colours
67 //projectile extended travel flags (gemrb specific)
68 #define PEF_BOUNCE 1 //bounce from walls (lightning bolt)
69 #define PEF_CONTINUE 2 //continue as a travel projectile after trigger (lightning bolt)
70 #define PEF_FREEZE 4 //stay around (ice dagger)
71 #define PEF_NO_TRAVEL 8 //all instant projectiles (draw upon holy might, finger of death)
72 #define PEF_TRAIL 16 //trail bams facing value uses the same field as the travel projectile (otherwise it defaults to 9) (shout in iwd)
73 #define PEF_CURVE 32 //curved path (magic missile)
74 #define PEF_RANDOM 64 //random starting frame for animation (?)
75 #define PEF_PILLAR 128 //draw all cycles simultaneously on top of each other (call lightning, flamestrike)
76 #define PEF_HALFTRANS 256 //half-transparency (holy might)
77 #define PEF_TINT 512 //use palette gradient as tint
78 #define PEF_ITERATION 1024 //create another projectile of type-1 (magic missiles)
79 #define PEF_TILED 2048 //tiled AOE (bg1 cone of cold/fire)
80 #define PEF_FALLING 4096 //projectile falls down vertically (cow)
81 #define PEF_INCOMING 8192 //projectile falls in on trajectory (comet)
82 #define PEF_LINE 16384 //solid line between source and target (agannazar's scorcher)
83 #define PEF_WALL 32768 //solid line in front of source, crossing target (wall of fire)
84 #define PEF_BACKGROUND 0x10000 //draw under target,overrides flying (dimension door)
85 #define PEF_POP 0x20000 //draw travel bam, then shadow, then travel bam backwards
86 #define PEF_UNPOP 0x40000 //draw shadow, then travel bam (this is an internal flag)
87 #define PEF_FADE 0x80000 //gradually fade on spot if used with PEF_FREEZE (ice dagger)
88 #define PEF_TEXT 0x100000//display text during setup
89 #define PEF_WANDERING 0x200000//random movement (no real path)
90 #define PEF_CYCLE 0x400000//random cycle
91 #define PEF_RGB 0x800000//rgb pulse on hit
93 //projectile area flags
94 #define PAF_VISIBLE 1 //the travel projectile is visible until explosion
95 #define PAF_INANIMATE 2 //target inanimates
96 #define PAF_TRIGGER 4 //explosion needs to be triggered
97 #define PAF_SYNC 8 //one explosion at a time
98 #define PAF_SECONDARY 16 //secondary projectiles at explosion
99 #define PAF_FRAGMENT 32 //fragments (charanimation) at explosion
100 #define PAF_ENEMY 64 //target party or not party
101 #define PAF_PARTY 128 //target party
102 #define PAF_TARGET (64|128)
104 #define PAF_CONE 2048
105 #define PAF_DELAY 0x4000
106 #define PAF_AFFECT_ONE 0x8000
109 //area projectile flags (in areapro.2da)
110 //this functionality was hardcoded in the original engine, so the bit flags are
111 //completely arbitrary (i assign them as need arises)
112 //child projectiles need to be tinted (example: stinking cloud, counter example: fireball)
114 //child projectiles fill the whole area (example: stinking cloud, counter example: fireball)
116 //child projectiles start in their destination (example: icestorm, counter example: fireball)
117 #define APF_SCATTER 4
118 //the explosion vvc has gradient (example: icestorm, counter example: fireball)
120 //there is an additional added scatter after the initial spreading ring
121 #define APF_SPREAD 16
122 //the spread projectile needs gradient colouring,not tint (example:web, counter example: stinking cloud)
123 #define APF_PALETTE 32
124 //use both animations in the spread
126 //more child projectiles
128 //apply spell on caster if failed to find target
129 #define APF_SPELLFAIL 256
131 struct ProjectileExtension
134 ieWord TriggerRadius
;
135 ieWord ExplosionRadius
;
136 ieResRef SoundRes
; //used for areapro.2da explosion sound
140 ieByte ExplosionCount
;
144 ieResRef VVCRes
; //used for areapro.2da second resref (center animation)
146 //these are GemRB specific (from areapro.2da)
147 ieDword APFlags
; //areapro.2da flags
148 ieResRef Spread
; //areapro.2da first resref
149 ieResRef Secondary
; //areapro.2da third resref
150 ieResRef AreaSound
; //areapro.2da second sound resource
153 class GEM_EXPORT Projectile
158 void InitExtension();
185 ieResRef TrailBAM
[3];
186 ieWord TrailSpeed
[3];
187 //these are public but not in the .pro file
188 ProjectileExtension
* Extension
;
194 ieDword timeStartStep
;
195 //attributes from moveable object
196 unsigned char Orientation
, NewOrientation
;
197 PathNode
* path
; //whole path
198 PathNode
* step
; //actual step
199 //similar to normal actors
204 ieDword Caster
; //the globalID of the caster actor
205 ieDword Target
; //the globalID of target actor
210 //these come from the extension area
212 int extension_explosioncount
;
215 //special (not using char animations)
216 Animation
* travel
[MAX_ORIENT
];
217 Animation
* shadow
[MAX_ORIENT
];
218 Sprite2D
* light
;//this is just a round/halftrans sprite, has no animation
219 EffectQueue
* effects
;
220 Projectile
**children
;
224 void SetCaster(ieDword t
);
225 ieDword
GetCaster() const;
226 void SetTarget(ieDword t
);
227 void SetTarget(const Point
&p
);
228 bool PointInRadius(const Point
&p
) const;
231 //inliners to protect data consistency
232 inline PathNode
* GetNextStep() {
234 DoStep((unsigned int) ~0);
239 inline Point
GetDestination() const { return Destination
; }
240 inline const char * GetName() const { return name
; }
241 inline ieWord
GetType() const { return type
; }
242 //This assumes that the effect queue cannot be bigger than 65535
243 //which is a sane expectation
244 inline EffectQueue
*GetEffects() const {
248 inline unsigned char GetOrientation() const {
251 //no idea if projectiles got height, using y
252 inline int GetHeight() const {
253 //if projectile is drawn behind target
254 if (ExtFlags
&PEF_BACKGROUND
) {
255 return Pos
.y
-BACK_DEPTH
;
258 //if projectile is flying
259 if (SFlags
&PSF_FLYING
) {
260 return Pos
.y
+FLY_HEIGHT
;
265 void SetIdentifiers(const char *name
, ieWord type
);
267 void SetEffectsCopy(EffectQueue
*eq
);
269 //don't forget to set effects to NULL when the projectile discharges
270 //unexploded projectiles are responsible to destruct their payload
272 inline void SetEffects(EffectQueue
*fx
) {
276 inline unsigned char GetNextFace() {
278 if (Orientation
!= NewOrientation
) {
279 if ( ( (NewOrientation
-Orientation
) & (MAX_ORIENT
-1) ) <= MAX_ORIENT
/2) {
284 Orientation
= Orientation
&(MAX_ORIENT
-1);
290 inline void SetOrientation(int value
, bool slow
) {
291 //MAX_ORIENT == 16, so we can do this
292 NewOrientation
= (unsigned char) (value
&(MAX_ORIENT
-1));
294 Orientation
= NewOrientation
;
299 //sets how long a created travel projectile will hover over a spot
300 //before vanishing (without the need of area extension)
301 void SetDelay(int delay
);
302 void MoveTo(Map
*map
, const Point
&Des
);
304 //handle phases, return 0 when expired
307 void Draw(const Region
&screen
);
308 void SetGradient(int gradient
, bool tint
);
309 void StaticTint(const Color
&newtint
);
311 //creates a child projectile with current_projectile_id - 1
312 void CreateIteration();
313 void CreateAnimations(Animation
**anims
, const ieResRef bam
, int Seq
);
314 //pillar type animations
315 void CreateCompositeAnimation(Animation
**anims
, AnimationFactory
*af
, int Seq
);
316 //oriented animations (also simple ones)
317 void CreateOrientedAnimations(Animation
**anims
, AnimationFactory
*af
, int Seq
);
318 void GetPaletteCopy(Animation
*anim
[], Palette
*&pal
);
324 void AddTrail(ieResRef BAM
, const ieByte
*pal
);
325 void DoStep(unsigned int walk_speed
);
326 void LineTarget(); //line projectiles (walls, scorchers)
327 void SecondaryTarget(); //area projectiles (circles, cones)
328 void CheckTrigger(unsigned int radius
);
330 void DrawLine(const Region
&screen
, int face
, ieDword flag
);
331 void DrawTravel(const Region
&screen
);
332 bool DrawChildren(const Region
&screen
);
333 void DrawExplosion(const Region
&screen
);
334 void DrawExploded(const Region
&screen
);
335 int GetTravelPos(int face
);
336 int GetShadowPos(int face
);
337 void SetPos(int face
, int frame1
, int frame2
);
338 //logic to resolve target when single projectile hit destination
339 int CalculateTargetFlag();
341 void NextTarget(const Point
&p
);
342 void SetupPalette(Animation
*anim
[], Palette
*&pal
, const ieByte
*gradients
);
345 #endif // PROJECTILE_H