1 /* GemRB - Infinity Engine Emulator 2 * Copyright (C) 2006 The GemRB Project 3 * 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. 8 * 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. 13 * 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. 17 * 18 * 19 */ 20 21 /** 22 * @file Projectile.h 23 * Declares Projectile, class for supporting functionality of spell/item projectiles 24 * @author The GemRB Project 25 */ 26 27 28 #ifndef PROJECTILE_H 29 #define PROJECTILE_H 30 31 #include "exports.h" 32 #include "ie_types.h" 33 34 #include "CharAnimations.h" //contains MAX_ORIENT 35 #include "EffectQueue.h" 36 #include "Map.h" 37 #include "Palette.h" 38 #include "PathFinder.h" 39 #include "Audio.h" 40 #include "Video.h" 41 42 namespace GemRB { 43 44 //this is the height of the projectile when Spark Flag Fly = 1 45 #define FLY_HEIGHT 50 46 //this is supposed to move the projectile to the background 47 #define BACK_DEPTH 50 48 49 //projectile phases 50 #define P_UNINITED -1 51 #define P_TRAVEL 0 //projectile moves to target 52 #define P_TRAVEL2 1 //projectile hit target 53 #define P_TRIGGER 2 //projectile hovers over target, waits for trigger 54 #define P_EXPLODING1 3 //projectile explosion spreads 55 #define P_EXPLODING2 4 //projectile explosion repeats 56 #define P_EXPLODED 5 //projectile spread over area 57 #define P_EXPIRED 99 //projectile scheduled for removal (existing parts are still drawn) 58 59 //projectile spark flags 60 #define PSF_SPARKS 1 61 #define PSF_FLYING 2 62 #define PSF_LOOPING 4 //looping sound 63 #define PSF_LOOPING2 8 //looping second sound 64 #define PSF_IGNORE_CENTER 16 65 #define PSF_BACKGROUND 32 66 //gemrb specific internal flag 67 #define PSF_SOUND2 0x80000000//already started sound2 68 69 //projectile travel flags 70 #define PTF_COLOUR 1 //fake colours 71 #define PTF_SMOKE 2 //has smoke 72 // bg2: 4 smoke is false colored 73 #define PTF_TINT 8 //tint projectile 74 // bg2: 10 height 75 #define PTF_SHADOW 32 //has shadow bam 76 #define PTF_LIGHT 64 //has light shadow / glow 77 #define PTF_TRANS 128 // glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE); 78 #define PTF_BRIGHTEN 256 //brighten alpha; CPROJECTILEBAMFILEFORMAT_FLAGS_BRIGHTEST in bg2 79 #define PTF_BLEND 512 // glBlendFunc(GL_DST_COLOR, GL_ONE); 80 #define PTF_TRANS_BLEND (PTF_TRANS | PTF_BLEND) // glBlendFunc(GL_SRC_COLOR, GL_ONE); IWD only? 81 // 0x100 and 0x200: FLAGS_BRIGHTESTIFFAST BRIGHTEST3DONLYOFF 82 #define PTF_TIMELESS 0x4000 // GemRB extension to differentiate projectiles that ignore timestop 83 84 //projectile extended travel flags (gemrb specific) 85 #define PEF_BOUNCE 1 //bounce from walls (lightning bolt) 86 #define PEF_CONTINUE 2 //continue as a travel projectile after trigger (lightning bolt) 87 //TODO: This can probably be replaced by an area projectile trigger (like skull trap, glyph) 88 #define PEF_FREEZE 4 //stay around (ice dagger) 89 #define PEF_NO_TRAVEL 8 //all instant projectiles (draw upon holy might, finger of death) 90 #define PEF_TRAIL 16 //trail bams facing value uses the same field as the travel projectile (otherwise it defaults to 9) (shout in iwd) 91 #define PEF_CURVE 32 //curved path (magic missile) 92 #define PEF_RANDOM 64 //random starting frame for animation (?) 93 #define PEF_PILLAR 128 //draw all cycles simultaneously on top of each other (call lightning, flamestrike) 94 #define PEF_HALFTRANS 256 //half-transparency (holy might) 95 #define PEF_TINT 512 //use palette gradient as tint 96 #define PEF_ITERATION 1024 //create another projectile of type-1 (magic missiles) 97 #define PEF_DEFSPELL 2048 //always apply the default spell on the caster 98 #define PEF_FALLING 4096 //projectile falls down vertically (cow) 99 #define PEF_INCOMING 8192 //projectile falls in on trajectory (comet) 100 #define PEF_LINE 16384 //solid line between source and target (agannazar's scorcher) 101 #define PEF_WALL 32768 //solid line in front of source, crossing target (wall of fire) 102 #define PEF_BACKGROUND 0x10000 //draw under target,overrides flying (dimension door) 103 #define PEF_POP 0x20000 //draw travel bam, then shadow, then travel bam backwards 104 #define PEF_UNPOP 0x40000 //draw shadow, then travel bam (this is an internal flag) 105 //TODO: The next flag is probably not needed, it is done by a separate area hit animation 106 #define PEF_FADE 0x80000 //gradually fade on spot if used with PEF_FREEZE (ice dagger) 107 #define PEF_TEXT 0x100000//display text during setup 108 #define PEF_WANDERING 0x200000//random movement (no real path) 109 #define PEF_CYCLE 0x400000//random cycle 110 #define PEF_RGB 0x800000//rgb pulse on hit 111 #define PEF_TOUCH 0x1000000//successful to hit roll needed 112 #define PEF_NOTIDS 0x2000000//negate IDS check 113 #define PEF_NOTIDS2 0x4000000//negate secondary IDS check 114 #define PEF_BOTH 0x8000000//both IDS check must succeed 115 #define PEF_DELAY 0x10000000//delay payload until travel projectile cycle ends 116 117 //projectile area flags 118 #define PAF_VISIBLE 1 //the travel projectile is visible until explosion; CPROJECTILEAREAFILEFORMAT_FLAGS_CENTERBAM 119 #define PAF_INANIMATE 2 //target inanimates 120 #define PAF_TRIGGER 4 //explosion needs to be triggered 121 #define PAF_SYNC 8 //one explosion at a time 122 #define PAF_SECONDARY 16 //secondary projectiles at explosion 123 #define PAF_FRAGMENT 32 //fragments (charanimation) at explosion 124 #define PAF_ENEMY 64 //target party or not party 125 #define PAF_PARTY 128 //target party 126 #define PAF_TARGET (64|128) 127 #define PAF_LEV_MAGE 256 128 #define PAF_LEV_CLERIC 512 129 #define PAF_VVC 1024 // played at center 130 #define PAF_CONE 2048 //enable cone shape 131 #define PAF_NO_WALL 0x1000 //pass through walls; CPROJECTILEAREAFILEFORMAT_FLAGS_IGNORELOS 132 #define PAF_TRIGGER_D 0x2000 //delayed trigger (only if animation is over 30); CPROJECTILEAREAFILEFORMAT_FLAGS_CENTERBAMWAIT 133 #define PAF_DELAY 0x4000 // CPROJECTILEAREAFILEFORMAT_FLAGS_FORCEINITIALDELAY 134 #define PAF_AFFECT_ONE 0x8000 // CPROJECTILEAREAFILEFORMAT_FLAGS_ONETARGETONLY 135 136 //area projectile flags (in areapro.2da) 137 //this functionality was hardcoded in the original engine, so the bit flags are 138 //completely arbitrary (i assign them as need arises) 139 //child projectiles need to be tinted (example: stinking cloud, counter example: fireball) 140 #define APF_TINT 1 141 //child projectiles fill the whole area (example: stinking cloud, counter example: fireball) 142 #define APF_FILL 2 143 //child projectiles start in their destination (example: icestorm, counter example: fireball) 144 #define APF_SCATTER 4 145 //the explosion vvc has gradient (example: icestorm, counter example: fireball) 146 #define APF_VVCPAL 8 147 //there is an additional added scatter after the initial spreading ring 148 #define APF_SPREAD 16 149 //the spread projectile needs gradient colouring,not tint (example:web, counter example: stinking cloud) 150 #define APF_PALETTE 32 151 //use both animations in the spread 152 #define APF_BOTH 64 153 //more child projectiles 154 #define APF_MORE 128 155 //apply spell on caster if failed to find target 156 #define APF_SPELLFAIL 256 157 //multiple directions 158 #define APF_MULTIDIR 512 159 //target HD counting 160 #define APF_COUNT_HD 1024 161 //target flag enemy ally switched 162 #define APF_INVERT_TARGET 2048 163 //tiled AoE animation 164 #define APF_TILED 4096 165 #define APF_PLAYONCE 8192 166 167 struct ProjectileExtension 168 { 169 ieDword AFlags; 170 ieWord TriggerRadius; 171 ieWord ExplosionRadius; 172 ieResRef SoundRes; //used for areapro.2da explosion sound 173 ieWord Delay; 174 ieWord FragAnimID; 175 ieWord FragProjIdx; 176 ieByte ExplosionCount; 177 ieByte ExplType; 178 ieWord ExplColor; // a byte in the original, followed by padding 179 ieWord ExplProjIdx; 180 ieResRef VVCRes; //used for areapro.2da second resref (center animation) 181 ieWord ConeWidth; 182 //these are GemRB specific (from areapro.2da) 183 ieDword APFlags; //areapro.2da flags 184 ieResRef Spread; //areapro.2da first resref 185 ieResRef Secondary; //areapro.2da third resref 186 ieResRef AreaSound; //areapro.2da second sound resource 187 //used for target or HD counting 188 ieWord DiceCount; 189 ieWord DiceSize; 190 ieWord TileX; 191 ieWord TileY; 192 }; 193 194 class GEM_EXPORT Projectile 195 { 196 public: 197 Projectile(); 198 ~Projectile(); 199 void InitExtension(); 200 201 ieWord Speed; 202 ieDword SFlags; 203 ieResRef FiringSound; 204 ieResRef ArrivalSound; 205 ieResRef TravelVVC; 206 ieDword SparkColor; 207 ieDword ExtFlags; 208 ieDword StrRef; 209 Color RGB; 210 ieWord ColorSpeed; 211 ieWord Shake; 212 ieWord IDSType; 213 ieWord IDSValue; 214 ieWord IDSType2; 215 ieWord IDSValue2; 216 ieResRef FailSpell; 217 ieResRef SuccSpell; 218 ////// gap 219 ieDword TFlags; 220 ieResRef BAMRes1; 221 ieResRef BAMRes2; 222 ieByte Seq1, Seq2; 223 ieWord LightX; 224 ieWord LightY; 225 ieWord LightZ; 226 ieResRef PaletteRes; 227 ieByte Gradients[7]; 228 ieByte SmokeSpeed; 229 ieByte SmokeGrad[7]; 230 ieByte Aim; // original bg2: m_numDirections // list of {1, 5, 9} 231 ieWord SmokeAnimID; 232 ieResRef TrailBAM[3]; 233 ieWord TrailSpeed[3]; 234 unsigned int Range; 235 //these are public but not in the .pro file 236 ProjectileExtension* Extension; 237 bool autofree; 238 PaletteHolder palette; 239 //internals 240 protected: 241 ieResRef smokebam; 242 ieDword timeStartStep; 243 //attributes from moveable object 244 unsigned char Orientation, NewOrientation; 245 PathNode* path; //whole path 246 PathNode* step; //actual step 247 //similar to normal actors 248 Map *area; 249 Point Pos; 250 int ZPos; 251 Point Destination; 252 Point Origin; 253 ieDword Caster; //the globalID of the caster actor 254 int Level; //the caster's level 255 ieDword Target; //the globalID of target actor 256 ieDword FakeTarget; //a globalID for target that isn't followed 257 int phase; 258 //saved in area 259 ieResRef name; 260 ieWord type; 261 //these come from the extension area 262 int extension_delay; 263 int extension_explosioncount; 264 int extension_targetcount; 265 Color tint; 266 267 //special (not using char animations) 268 Animation* travel[MAX_ORIENT]; 269 Animation* shadow[MAX_ORIENT]; 270 Holder<Sprite2D> light;//this is just a round/halftrans sprite, has no animation 271 EffectQueue* effects; 272 Projectile **children; 273 int child_size; 274 int pathcounter; 275 int bend; 276 int drawSpark; 277 Holder<SoundHandle> travel_handle; 278 public: 279 void SetCaster(ieDword t, int level); 280 ieDword GetCaster() const; 281 bool FailedIDS(const Actor *target) const; 282 void SetTarget(ieDword t, bool fake); 283 void SetTarget(const Point &p); 284 bool PointInRadius(const Point &p) const; 285 int GetPhase() const; 286 void Cleanup(); 287 GetDestination()288 inline Point GetDestination() const { return Destination; } GetName()289 inline const char * GetName() const { return name; } GetType()290 inline ieWord GetType() const { return type; } 291 //This assumes that the effect queue cannot be bigger than 65535 292 //which is a sane expectation GetEffects()293 inline EffectQueue *GetEffects() const { 294 return effects; 295 } 296 GetOrientation()297 inline unsigned char GetOrientation() const { 298 return Orientation; 299 } 300 //no idea if projectiles got height, using y GetHeight()301 inline int GetHeight() const { 302 //if projectile is drawn absolutely on the ground 303 if (SFlags&PSF_BACKGROUND) { 304 return 0; 305 } 306 //if projectile is drawn behind target (not behind everyone) 307 if (ExtFlags&PEF_BACKGROUND) { 308 return Pos.y-BACK_DEPTH; 309 } 310 311 //if projectile is flying 312 if (SFlags&PSF_FLYING) { 313 return Pos.y+FLY_HEIGHT; 314 } 315 return Pos.y; 316 } 317 318 void SetIdentifiers(const char *name, ieWord type); 319 320 void SetEffectsCopy(const EffectQueue *eq, const Point &source); 321 322 //don't forget to set effects to NULL when the projectile discharges 323 //unexploded projectiles are responsible to destruct their payload 324 SetEffects(EffectQueue * fx)325 inline void SetEffects(EffectQueue *fx) { 326 effects = fx; 327 } 328 GetNextFace()329 inline unsigned char GetNextFace() { 330 //slow turning 331 if (Orientation != NewOrientation) { 332 if ( ( (NewOrientation-Orientation) & (MAX_ORIENT-1) ) <= MAX_ORIENT/2) { 333 Orientation++; 334 } else { 335 Orientation--; 336 } 337 Orientation = Orientation&(MAX_ORIENT-1); 338 } 339 340 return Orientation; 341 } 342 SetOrientation(int value,bool slow)343 inline void SetOrientation(int value, bool slow) { 344 //MAX_ORIENT == 16, so we can do this 345 NewOrientation = (unsigned char) (value&(MAX_ORIENT-1)); 346 if (!slow) { 347 Orientation = NewOrientation; 348 } 349 } 350 351 void Setup(); 352 //sets how long a created travel projectile will hover over a spot 353 //before vanishing (without the need of area extension) 354 void SetDelay(int delay); 355 void MoveTo(Map *map, const Point &Des); 356 void ClearPath(); 357 //handle phases, return 0 when expired 358 int Update(); 359 //draw object 360 void Draw(const Region &screen); 361 void SetGradient(int gradient, bool tint); 362 void StaticTint(const Color &newtint); 363 private: 364 //creates a child projectile with current_projectile_id - 1 365 void CreateIteration(); 366 void CreateAnimations(Animation **anims, const ieResRef bam, int Seq); 367 //pillar type animations 368 void CreateCompositeAnimation(Animation **anims, AnimationFactory *af, int Seq); 369 //oriented animations (also simple ones) 370 void CreateOrientedAnimations(Animation **anims, AnimationFactory *af, int Seq); 371 void GetPaletteCopy(Animation *anim[], PaletteHolder &pal); 372 void GetSmokeAnim(); 373 void SetBlend(int brighten); 374 //apply spells and effects on the target, only in single travel mode 375 //area effect projectiles call a separate single travel projectile for each affected target 376 void Payload(); 377 //if there is an extension, convert to exploding or wait for trigger 378 void EndTravel(); 379 //apply default spell 380 void ApplyDefault(); 381 //stops the current sound 382 void StopSound(); 383 //kickstarts the secondary sound 384 void UpdateSound(); 385 //reached end of single travel missile, explode or expire now 386 void ChangePhase(); 387 //drop a BAM or VVC on the trail path, return the length of the animation 388 int AddTrail(const ieResRef BAM, const ieByte *pal) const; 389 void DoStep(unsigned int walk_speed); 390 void LineTarget() const; //line projectiles (walls, scorchers) 391 void LineTarget(const PathNode *beg, const PathNode *end) const; 392 void SecondaryTarget(); //area projectiles (circles, cones) 393 void CheckTrigger(unsigned int radius); 394 //calculate target and destination points for a firewall 395 void SetupWall(); 396 void DrawLine(const Region &screen, int face, BlitFlags flag); 397 void DrawTravel(const Region &screen); 398 bool DrawChildren(const Region &screen); 399 void DrawExplosion(const Region &screen); 400 void SpawnFragment(Point &pos); 401 void DrawExploded(const Region &screen); 402 int GetTravelPos(int face) const; 403 int GetShadowPos(int face) const; 404 void SetPos(int face, int frame1, int frame2); 405 inline int GetZPos() const; 406 407 //logic to resolve target when single projectile hit destination 408 int CalculateTargetFlag() const; 409 //logic to resolve the explosion count (may be based on caster level) 410 int CalculateExplosionCount(); 411 412 Actor *GetTarget(); 413 void NextTarget(const Point &p); 414 void SetupPalette(Animation *anim[], PaletteHolder &pal, const ieByte *gradients); 415 416 private: 417 void Draw(Holder<Sprite2D> spr, const Point& p, 418 BlitFlags flags, Color tint) const; 419 }; 420 421 } 422 423 #endif // PROJECTILE_H 424