ScummVM API documentation
effects.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  *
21  * Based on the original sources
22  * Faery Tale II -- The Halls of the Dead
23  * (c) 1993-1996 The Wyrmkeep Entertainment Co.
24  */
25 
26 #ifndef SAGA2_EFFECTS_H
27 #define SAGA2_EFFECTS_H
28 
29 #include "saga2/dice.h"
30 
31 namespace Saga2 {
32 
33 class Actor;
34 class GameObject;
35 
36 // ------------------------------------------------------------------
37 // Effects of spells and other things
38 
39 //
40 // 1 Enchantments
41 // A Object (non-Actor) Enchantments
42 // Object : There aren't a lot of these
43 // B Actor Enchantments
44 // Attrib : affects attributes of actors
45 // Resist : Enable resistance to various things
46 // Immune : Enable immunity to various things
47 // Others : Misc flags
48 // C Player Enchantments
49 // Player : Flags that really only affect players
50 // 2 Effects
51 // A General effects
52 // Damage : does damage of various types
53 // B Actor only effects
54 // Drains : mana drains, money drains, food drains
55 // Special : must be handled manually
56 // C TAG effects : There aren't many of these
57 // D Global Effects : Effects that have significant effect on the game engine
58 //
59 
60 enum effectTypes {
61  kEffectNone = 0, // no functional effect
62  kEffectAttrib, // (enchant) affects attributes of actors
63  kEffectResist, // (enchant) Enable resistance to various things
64  kEffectImmune, // (enchant) Enable immunity to various things
65  kEffectOthers, // (enchant) Enable immunity to various things
66  kEffectNonActor, // (enchant) change an object
67  kEffectPoison, // (enchant) change an object
68 // Effect types greater than 8 cannot be enchantments
69  kEffectDamage = 8, // does damage of various types
70  kEffectDrains, // mana drain, money drain
71  kEffectTAG, // mana drain, money drain
72  kEffectLocation, // mana drain, money drain
73  kEffectSpecial,
74  kEffectStrike // weapon strike effect
75 };
76 
77 
78 //
79 // Resistance Effects - these correspond exactly to the Damage types
80 // A separate enum is defined to permit differentiation between
81 // damage, resistance, and immunity effects
82 //
83 
84 enum effectResistTypes {
85  kResistOther = kDamageOther,
86  // Combat resist
87  kResistImpact = kDamageImpact,
88  kResistSlash = kDamageSlash,
89  kResistProjectile = kDamageProjectile,
90  // Magic resist
91  kResistFire = kDamageFire,
92  kResistAcid = kDamageAcid,
93  kResistHeat = kDamageHeat,
94  kResistCold = kDamageCold,
95  kResistLightning = kDamageLightning,
96  kResistPoison = kDamagePoison,
97  // Other magic resist
98  kResistMental = kDamageMental,
99  kResistToUndead = kDamageToUndead,
100  kResistDirMagic = kDamageDirMagic,
101  // Physiological Damage
102  kResistStarve = kDamageStarve,
103  // other
104  kResistEnergy = kDamageEnergy
105 };
106 
107 //
108 // Immunity Effects - See the notes for resistance effects
109 //
110 
111 // Types of damage an effect can give immunity to
112 enum effectImmuneTypes {
113  kImmuneOther = kResistOther,
114  // Combat imm
115  kImmuneImpact = kResistImpact,
116  kImmuneSlash = kResistSlash,
117  kImmuneProjectile = kResistProjectile,
118  // Magic immu
119  kImmuneFire = kResistFire,
120  kImmuneAcid = kResistAcid,
121  kImmuneHeat = kResistHeat,
122  kImmuneCold = kResistCold,
123  kImmuneLightning = kResistLightning,
124  kImmunePoison = kResistPoison,
125  // Other magimune
126  kImmuneMental = kResistMental,
127  kImmuneToUndead = kResistToUndead,
128  kImmuneDirMagic = kResistDirMagic,
129  // PhysiologiDamage
130  kImmuneStarve = kResistStarve,
131  // other
132  kImmuneEnergy = kResistEnergy
133 };
134 
135 //
136 // Other Effects - general flags in the actor structure most of which
137 // aren't hooked up to anything.
138 //
139 
140 enum effectOthersTypes {
141  // Movement flags
142  kActorNoncorporeal = 1, // The creature can walk through things
143  kActorWaterBreathe = 2, // death spell
144  kActorSlowFall = 3, // the creature is not harmed by falling (but falls none the less)
145  kActorLevitate = 4, // flying with no height control ?
146  kActorFlying = 5, // the creature flys
147  // speed flags
148  kActorFastMove = 6, //
149  kActorFastAttack = 7, //
150  kActorSlowAttack = 8, // come... back... here... lit... tle... bun... ny...
151 
152  kActorImmobile = 9, // I thought I told you to leave the piano at home
153  // ill effects
154  kActorAsleep = 10, // Zzzzzzzzzzz
155  kActorParalyzed = 11, // the creature can't move an inch
156  kActorFear = 12, // run away! run away
157  kActorDiseased = 13, // cannot heal
158  kActorPoisoned = 14, // death spell
159  // perception & perceivability flags
160  kActorBlind = 15, // can't see
161  kActorSeeInvis = 16, // can see invisible
162  kActorClairvoyant = 17, // unknown effects
163  kActorInvisible = 18, // is invisible
164  kActorUndetectable = 19, // can't be seen, smelled
165  kActorDetPoison = 20, // poison things glow green
166  // flags preventing changes to other flags
167  kActorNoEnchant = 21, // no bad enchantments
168  kActorNoDrain = 22, // no mana / food drains
169  // flags that make things run away
170  kActorRepelEvil = 23, // death spell
171  kActorRepelGood = 24, // death spell
172  kActorRepelUndead = 25, // death spell
173  // miscellaneous
174  kActorNotDefenseless = 26, // forgo defenselessness check
175  kActorDisappearOnDeath = 27, // gets deleted on death and spews inventory
176  // dead or moved flags
177  kActorWaterWalk // can walk on water (same as float ?)
178 };
179 
180 //
181 // Drains Effects - these correspond to values in the actor that are
182 // drained & replenished
183 //
184 
185 enum effectDrainsTypes {
186  // mana pools
187  kDrainsManaRed = 1,
188  kDrainsManaOrange,
189  kDrainsManaYellow,
190  kDrainsManaGreen,
191  kDrainsManaBlue,
192  kDrainsManaViolet,
193  kDrainsLifeLevel,
194  kDrainsVitality,
195  kDrainsMoney
196 };
197 
198 
199 //
200 // TAG Effects - effects that apply when a TAG is the target
201 //
202 
203 enum effectTAGTypes {
204  kSettagLocked = 1,
205  kSettagOpen = 2
206 };
207 
208 
209 //
210 // Location Effects - effects that apply when a Location is the target
211 //
212 
213 enum kEffectLocationTypes {
214  kLocateDummy = 1
215 };
216 
217 enum objectFlags {
218  kObjectOpen = (1 << 0), // object is in the "open" state
219  kObjectLocked = (1 << 1), // object cannot be opened
220  kObjectImportant = (1 << 2), // object must be recycled when trashed
221  kObjectGhosted = (1 << 3), // object drawn translucent
222  kObjectInvisible = (1 << 4), // object cannot be seen
223  kObjectObscured = (1 << 5), // object obscured by terrain
224  kObjectMoving = (1 << 6), // object has attached motion task
225  kObjectScavengable = (1 << 7), // object can be deleted
226  kObjectFloating = (1 << 8), // object not affected by Gravity
227  kObjectNoRecycle = (1 << 9), // object is referred to by script, don't delete
228  kObjectActivated = (1 << 10), // object is activated
229  kObjectAlias = (1 << 11), // object is not real, just a copy of another object
230  kObjectTriggeringTAG = (1 << 12), // object has triggerred TAG upon which it rests
231  kObjectOnScreen = (1 << 13), // object is on display list
232  kObjectSightedByCenter = (1 << 14) // there is a line of sight to center actor
233 };
234 
235 
236 //
237 // Special Effects - these are spells that need to be handled manually
238 //
239 
240 enum effectSpecialTypes {
241  kSpecialDispellHelpfulEnch = 1, // clears helpful enchantments
242  kSpecialDispellHarmfulEnch, // clears harmful enchantments
243  kSpecialKill, // death spell
244  kSpecialRessurect, // raise dead spell
245  kSpecialTeleport, // Teleportation
246  kSpecialCreateActor, // Create an actor or wall
247  kSpecialSagaFunc, // calls a saga function
248  kSpecialCreateWWisp, // calls a saga function
249  kSpecialCreateFWisp, // calls a saga function
250  kSpecialCreateWraith, // calls a saga function
251  kSpecialCreateFood, // calls a saga function
252  kSpecialRejoin
253 };
254 
255 // ------------------------------------------------------------------
256 // ENCHANTMENT IDs
257 // It is necessary to combine all these possibilities into a 16 bit integer
258 // Here's how its mapped
259 // 3 bits - general effect type
260 // 5 bits - sub class enum value
261 // 8 bits - damage amount, boolean on/off etc.
262 //
263 
264 inline uint16 makeEnchantmentID(uint16 type, uint16 damtyp, int16 damamt) {
265  assert(type < 8);
266  assert(damtyp < 32);
267  assert(damamt < 128 && damamt > -128);
268  return ((type << 13) | (damtyp << 8)) + (damamt + 128);
269 }
270 
271 /* skill* are now in the spellid enum ;AS;
272 inline uint16 makeEnchantmentID(effectAttribTypes atttyp, int16 damamt)
273  { return (kEffectAttrib << 13) | (atttyp << 8) + (damamt+128); }
274 */
275 
276 inline uint16 makeEnchantmentID(effectResistTypes restyp, bool damamt) {
277  return ((kEffectResist << 13) | (restyp << 8)) + (damamt + 128);
278 }
279 
280 inline uint16 makeEnchantmentID(effectImmuneTypes immtyp, bool damamt) {
281  return ((kEffectImmune << 13) | (immtyp << 8)) + (damamt + 128);
282 }
283 
284 inline uint16 makeEnchantmentID(effectOthersTypes othtyp, bool damamt) {
285  return ((kEffectOthers << 13) | (othtyp << 8)) + (damamt + 128);
286 }
287 
288 inline uint16 makeEnchantmentID(objectFlags othtyp, bool damamt) {
289  return ((kEffectNonActor << 13) | (othtyp << 8)) + (damamt + 128);
290 }
291 
292 inline uint16 makeEnchantmentID(uint8 damamt) {
293  return ((kEffectPoison << 13) | (0 << 8)) + damamt;
294 }
295 
296 inline effectTypes getEnchantmentType(uint16 eID) {
297  return (effectTypes)(eID >> 13);
298 }
299 
300 inline uint16 getEnchantmentSubType(uint16 eID) {
301  return (eID >> 8) & 0x1F;
302 }
303 
304 inline int16 getEnchantmentAmount(uint16 eID) {
305  return (eID & 0xFF) - 128;
306 }
307 
308 // ------------------------------------------------------------------
309 // Determine whether an enchantment is harmful
310 
311 inline bool isHarmful(uint16 enchID) {
312  int16 typ = getEnchantmentType(enchID);
313  int16 sub = getEnchantmentSubType(enchID);
314  int16 amt = getEnchantmentAmount(enchID);
315  if (typ == kEffectAttrib) return amt < 0;
316  if (typ == kEffectOthers)
317  return (sub >= kActorSlowAttack && sub <= kActorBlind);
318  return false;
319 }
320 
321 // ------------------------------------------------------------------
322 // Determine whether an enchantment can fail
323 
324 inline bool isSaveable(uint16 enchID) {
325  int16 typ = getEnchantmentType(enchID);
326  return (typ == kEffectOthers && isHarmful(enchID));
327 }
328 
329 // ------------------------------------------------------------------
330 // Determine whether a damage type is magical
331 
332 inline bool isMagicDamage(effectDamageTypes t) {
333  return t >= kDamageFire && t <= kDamageDirMagic;
334 }
335 
336 #define Forever (255)
337 
338 class SpellTarget;
339 
340 //-------------------------------------------------------------------
341 // ProtoEffects
342 
343 // This is the base class of several spell effect prototype classes
344 // The implement routine carries out the instantiation of a
345 // particular effect on a given target (doing damage or whatever)
346 
347 
348 class ProtoEffect {
349  //protected:
350  //int imp; // enchant or immediate
351 
352 public:
353  ProtoEffect *_next; // pointer to additional effects
354 
355  ProtoEffect() {
356  _next = NULL;
357  }
358  virtual ~ProtoEffect() {
359  if (_next) delete _next;
360  _next = NULL;
361  }
362  //int implementation( void ) { return imp; }
363  virtual bool applicable(SpellTarget &) {
364  return false;
365  }
366  virtual void implement(GameObject *, SpellTarget *, int8 = 0) {}
367 };
368 
369 
370 //-------------------------------------------------------------------
371 // ProtoDamage
372 // This class of effects does a range of damage to the target
373 
374 class ProtoDamage: public ProtoEffect {
375  effectDamageTypes _type; // damage type
376  int8 _dice, // # of dice to roll
377  _sides, // # of sides on dice
378  _skillDice, // multiply by spellcraft to get additional dice
379  _base, // absolute damage amount
380  _skillBase; // absolute damage amount
381  int8 _self; // casts at self
382 
383 public:
384 
385  ProtoDamage(int8 d, int8 s, int8 sd, int8 b, effectDamageTypes t, int, bool afSelf = false, int8 sb = 0) {
386  _type = t;
387  _dice = d;
388  _sides = s;
389  _skillDice = sd;
390  _base = b;
391  _self = afSelf;
392  _skillBase = sb;
393  }
394 
395  bool applicable(SpellTarget &trg);
396 
397  void implement(GameObject *cst, SpellTarget *trg, int8 deltaDamage = 0);
398 
399  static int16 getRelevantStat(effectDamageTypes dt, Actor *a);
400 };
401 
402 //-------------------------------------------------------------------
403 // ProtoDrainage
404 // This class of effects does a range of damage to the target's
405 // mana, money or food supply
406 
407 class ProtoDrainage: public ProtoEffect {
408  effectDrainsTypes _type; // damage type
409  int8 _dice, // # of dice to roll
410  _sides, // # of sides on dice
411  _skillDice, // multiply by spellcraft to get additional dice
412  _base; // absolute damage amount
413  int8 _self; // casts at self
414 
415 public:
416 
417  ProtoDrainage(int8 d, int8 s, int8 sd, int8 b, effectDrainsTypes t, int, bool afSelf = false) {
418  _type = t;
419  _dice = d;
420  _sides = s;
421  _skillDice = sd;
422  _base = b;
423  _self = afSelf;
424  }
425 
426  bool applicable(SpellTarget &trg);
427 
428  void implement(GameObject *cst, SpellTarget *trg, int8 deltaDamage = 0);
429 
430  static int16 currentLevel(Actor *a, effectDrainsTypes edt);
431  static void drainLevel(GameObject *cst, Actor *a, effectDrainsTypes edt, int16 amt);
432 };
433 
434 //-------------------------------------------------------------------
435 // ProtoEnchantment
436 // This can be any of several types of enchantments (see EFFECTS.H)
437 //
438 
440  uint16 _enchID;
441  uint32 _minEnch;
442  RandomDice _dice; // enchantment time
443 
444 public:
445  ProtoEnchantment(uint16 e, uint32 loTime, uint32 hiTime) {
446  _enchID = e;
447  _dice = RandomDice(1, hiTime - loTime);
448  _minEnch = loTime;
449  }
450 
451  bool applicable(SpellTarget &trg);
452 
453  void implement(GameObject *, SpellTarget *trg, int8 deltaDamage = 0);
454 
455  bool canFail() {
456  return isSaveable(_enchID);
457  }
458 
459  static bool realSavingThrow(Actor *a);
460 };
461 
462 //-------------------------------------------------------------------
463 // ProtoTAGEffect
464 // this type of spell sets up spells that are used to alter tags
465 
467  effectTAGTypes _affectBit;
468  int16 _onOff; // lock/unlock or trigger ID
469  ObjectID _trigger;
470 
471 public:
472  ProtoTAGEffect(effectTAGTypes ett, int16 v, ObjectID t) {
473  _affectBit = ett;
474  _onOff = v;
475  _trigger = t;
476  }
477 
478  bool applicable(SpellTarget &trg);
479 
480  void implement(GameObject *, SpellTarget *trg, int8 deltaDamage = 0);
481 };
482 
483 //-------------------------------------------------------------------
484 // ProtoObjectEffect
485 // These effects are used only on non-actor objects.
486 
488  uint16 _affectBit;
489  int16 _onOff;
490  RandomDice _dice; // enchantment time
491 
492 public:
493  ProtoObjectEffect(uint16 e, int16 v, uint32 loT, uint32 hiT) {
494  _affectBit = e;
495  _onOff = v;
496  _dice = RandomDice(loT, hiT);
497  }
498 
499  bool applicable(SpellTarget &trg);
500 
501  void implement(GameObject *, SpellTarget *trg, int8 deltaDamage = 0);
502 };
503 
504 //-------------------------------------------------------------------
505 // If spells ever need to do things to Locations this
506 // is where they'll be
507 
509  kEffectLocationTypes _affectBit;
510  int16 _value;
511 
512 public:
513  ProtoLocationEffect(kEffectLocationTypes elt, int16 v) {
514  _affectBit = elt;
515  _value = v;
516  }
517 
518  bool applicable(SpellTarget &) {
519  return (true);
520  }
521 
522  void implement(GameObject *, SpellTarget *trg, int8 deltaDamage = 0);
523 };
524 
525 //-------------------------------------------------------------------
526 // ProtoSpecialEffects
527 // As always there are spells that just don't fit any of the other
528 // molds. These protoEffects allow customized spell handlers to be
529 // implemented.
530 //
531 
532 typedef void SPELLIMPLEMENTATION(GameObject *, SpellTarget *);
533 
534 #define SPECIALSPELL(name) void name(GameObject *cst, SpellTarget *trg)
535 
537  int16 _routineID;
538  SPELLIMPLEMENTATION *_handler;
539 
540 public:
541  ProtoSpecialEffect(SPELLIMPLEMENTATION *newHandler, int16 callID = 0) {
542  _handler = newHandler;
543  _routineID = callID;
544  }
545 
546  bool applicable(SpellTarget &) {
547  return true;
548  //return (trg.getType()==SpellTarget::kSpellTargetObject ||
549  // trg.getType()==SpellTarget::kSpellTargetObjectPoint) &&
550  // isActor(trg.getObject());
551  }
552 
553  void implement(GameObject *, SpellTarget *trg, int8 deltaDamage = 0);
554 };
555 
556 } // end of namespace Saga2
557 
558 #endif
Definition: dice.h:43
Definition: actor.h:32
Definition: actor.h:589
Definition: effects.h:407
Definition: effects.h:487
Definition: effects.h:466
Definition: objects.h:118
Definition: effects.h:508
Definition: effects.h:348
Definition: effects.h:374
Definition: speldefs.h:139
Definition: effects.h:439
Definition: effects.h:536