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
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (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, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 *
22 * Based on the original sources
23 * Faery Tale II -- The Halls of the Dead
24 * (c) 1993-1996 The Wyrmkeep Entertainment Co.
25 */
26
27 #ifndef SAGA2_EFFECTS_H
28 #define SAGA2_EFFECTS_H
29
30 #include "saga2/dice.h"
31
32 namespace Saga2 {
33
34 class Actor;
35 class GameObject;
36
37 // ------------------------------------------------------------------
38 // Effects of spells and other things
39
40 //
41 // 1 Enchantments
42 // A Object (non-Actor) Enchantments
43 // Object : There aren't a lot of these
44 // B Actor Enchantments
45 // Attrib : affects attributes of actors
46 // Resist : Enable resistance to various things
47 // Immune : Enable immunity to various things
48 // Others : Misc flags
49 // C Player Enchantments
50 // Player : Flags that really only affect players
51 // 2 Effects
52 // A General effects
53 // Damage : does damage of various types
54 // B Actor only effects
55 // Drains : mana drains, money drains, food drains
56 // Special : must be handled manually
57 // C TAG effects : There aren't many of these
58 // D Global Effects : Effects that have signifigant effect on the game engine
59 //
60
61 enum effectTypes {
62 effectNone = 0, // no functional effect
63 effectAttrib, // (enchant) affects attributes of actors
64 effectResist, // (enchant) Enable resistance to various things
65 effectImmune, // (enchant) Enable immunity to various things
66 effectOthers, // (enchant) Enable immunity to various things
67 effectNonActor, // (enchant) change an object
68 effectPoison, // (enchant) change an object
69 // Effect types greater than 8 cannot be enchantments
70 effectDamage = 8, // does damage of various types
71 effectDrains, // mana drain, money drain
72 effectTAG, // mana drain, money drain
73 effectLocation, // mana drain, money drain
74 effectSpecial,
75 effectStrike // weapon strike effect
76 };
77
78
79 //
80 // Resistance Effects - these correspond exactly to the Damage types
81 // A separate enum is defined to permit differentiation between
82 // damage, resistance, and immunity effects
83 //
84
85 enum effectResistTypes {
86 resistOther = kDamageOther,
87 // Combat resist
88 resistImpact = kDamageImpact,
89 resistSlash = kDamageSlash,
90 resistProjectile = kDamageProjectile,
91 // Magic resist
92 resistFire = kDamageFire,
93 resistAcid = kDamageAcid,
94 resistHeat = kDamageHeat,
95 resistCold = kDamageCold,
96 resistLightning = kDamageLightning,
97 resistPoison = kDamagePoison,
98 // Other magic resist
99 resistMental = kDamageMental,
100 resistToUndead = kDamageToUndead,
101 resistDirMagic = kDamageDirMagic,
102 // Physiological Damage
103 resistStarve = kDamageStarve,
104 // other
105 resistEnergy = kDamageEnergy
106 };
107
108 //
109 // Immunity Effects - See the notes for resistance effects
110 //
111
112 // Types of damage an effect can give immunity to
113 enum effectImmuneTypes {
114 immuneOther = resistOther,
115 // Combat imm
116 immuneImpact = resistImpact,
117 immuneSlash = resistSlash,
118 immuneProjectile = resistProjectile,
119 // Magic immu
120 immuneFire = resistFire,
121 immuneAcid = resistAcid,
122 immuneHeat = resistHeat,
123 immuneCold = resistCold,
124 immuneLightning = resistLightning,
125 immunePoison = resistPoison,
126 // Other magimune
127 immuneMental = resistMental,
128 immuneToUndead = resistToUndead,
129 immuneDirMagic = resistDirMagic,
130 // PhysiologiDamage
131 immuneStarve = resistStarve,
132 // other
133 immuneEnergy = resistEnergy
134 };
135
136 //
137 // Other Effects - general flags in the actor structure most of which
138 // aren't hooked up to anything.
139 //
140
141 enum effectOthersTypes {
142 // Movement flags
143 actorNoncorporeal = 1, // The creature can walk through things
144 actorWaterBreathe = 2, // death spell
145 actorSlowFall = 3, // the creature is not harmed by falling (but falls none the less)
146 actorLevitate = 4, // flying with no height control ?
147 actorFlying = 5, // the creature flys
148 // speed flags
149 actorFastMove = 6, //
150 actorFastAttack = 7, //
151 actorSlowAttack = 8, // come... back... here... lit... tle... bun... ny...
152
153 actorImmobile = 9, // I thought I told you to leave the piano at home
154 // ill effects
155 actorAsleep = 10, // Zzzzzzzzzzz
156 actorParalyzed = 11, // the creature can't move an inch
157 actorFear = 12, // run away! run away
158 actorDiseased = 13, // cannot heal
159 actorPoisoned = 14, // death spell
160 // perception & perceivability flags
161 actorBlind = 15, // can't see
162 actorSeeInvis = 16, // can see invisible
163 actorClairvoyant = 17, // unknown effects
164 actorInvisible = 18, // is invisible
165 actorUndetectable = 19, // can't be seen, smelled
166 actorDetPoison = 20, // poison things glow green
167 // flags preventing changes to other flags
168 actorNoEnchant = 21, // no bad enchantments
169 actorNoDrain = 22, // no mana / food drains
170 // flags that make things run away
171 actorRepelEvil = 23, // death spell
172 actorRepelGood = 24, // death spell
173 actorRepelUndead = 25, // death spell
174 // miscellaneous
175 actorNotDefenseless = 26, // forgo defenselessness check
176 actorDisappearOnDeath = 27, // gets deleted on death and spews inventory
177 // dead or moved flags
178 actorWaterWalk // can walk on water (same as float ?)
179 };
180
181 //
182 // Drains Effects - these correspond to values in the actor that are
183 // drained & replenished
184 //
185
186 enum effectDrainsTypes {
187 // mana pools
188 drainsManaRed = 1,
189 drainsManaOrange,
190 drainsManaYellow,
191 drainsManaGreen,
192 drainsManaBlue,
193 drainsManaViolet,
194 drainsLifeLevel,
195 drainsVitality,
196 drainsMoney
197 };
198
199
200 //
201 // TAG Effects - effects that apply when a TAG is the target
202 //
203
204 enum effectTAGTypes {
205 settagLocked = 1,
206 settagOpen = 2
207 };
208
209
210 //
211 // Location Effects - effects that apply when a Location is the target
212 //
213
214 enum effectLocationTypes {
215 locateDummy = 1
216 };
217
218 enum objectFlags {
219 objectOpen = (1 << 0), // object is in the "open" state
220 objectLocked = (1 << 1), // object cannot be opened
221 objectImportant = (1 << 2), // object must be recycled when trashed
222 objectGhosted = (1 << 3), // object drawn translucent
223 objectInvisible = (1 << 4), // object cannot be seen
224 objectObscured = (1 << 5), // object obscured by terrain
225 objectMoving = (1 << 6), // object has attached motion task
226 objectScavengable = (1 << 7), // object can be deleted
227 objectFloating = (1 << 8), // object not affected by Gravity
228 objectNoRecycle = (1 << 9), // object is referred to by script, don't delete
229 objectActivated = (1 << 10), // object is activated
230 objectAlias = (1 << 11), // object is not real, just a copy of another object
231 objectTriggeringTAG = (1 << 12), // object has triggerred TAG upon which it rests
232 objectOnScreen = (1 << 13), // object is on display list
233 objectSightedByCenter = (1 << 14) // there is a line of sight to center actor
234 };
235
236
237 //
238 // Special Effects - these are spells that need to be handled manually
239 //
240
241 enum effectSpecialTypes {
242 specialDispellHelpfulEnch = 1, // clears helpful enchantments
243 specialDispellHarmfulEnch, // clears harmful enchantments
244 specialKill, // death spell
245 specialRessurect, // raise dead spell
246 specialTeleport, // Teleportation
247 specialCreateActor, // Create an actor or wall
248 specialSagaFunc, // calls a saga function
249 specialCreateWWisp, // calls a saga function
250 specialCreateFWisp, // calls a saga function
251 specialCreateWraith, // calls a saga function
252 specialCreateFood, // calls a saga function
253 specialRejoin
254 };
255
256 // ------------------------------------------------------------------
257 // ENCHANTMENT IDs
258 // It is necessary to combine all these possibilities into a 16 bit integer
259 // Here's how its mapped
260 // 3 bits - general effect type
261 // 5 bits - sub class enum value
262 // 8 bits - damage amount, boolean on/off etc.
263 //
264
makeEnchantmentID(uint16 type,uint16 damtyp,int16 damamt)265 inline uint16 makeEnchantmentID(uint16 type, uint16 damtyp, int16 damamt) {
266 assert(type < 8);
267 assert(damtyp < 32);
268 assert(damamt < 128 && damamt > -128);
269 return ((type << 13) | (damtyp << 8)) + (damamt + 128);
270 }
271
272 /* skill* are now in the spellid enum ;AS;
273 inline uint16 makeEnchantmentID(effectAttribTypes atttyp, int16 damamt)
274 { return (effectAttrib << 13) | (atttyp << 8) + (damamt+128); }
275 */
276
makeEnchantmentID(effectResistTypes restyp,bool damamt)277 inline uint16 makeEnchantmentID(effectResistTypes restyp, bool damamt) {
278 return ((effectResist << 13) | (restyp << 8)) + (damamt + 128);
279 }
280
makeEnchantmentID(effectImmuneTypes immtyp,bool damamt)281 inline uint16 makeEnchantmentID(effectImmuneTypes immtyp, bool damamt) {
282 return ((effectImmune << 13) | (immtyp << 8)) + (damamt + 128);
283 }
284
makeEnchantmentID(effectOthersTypes othtyp,bool damamt)285 inline uint16 makeEnchantmentID(effectOthersTypes othtyp, bool damamt) {
286 return ((effectOthers << 13) | (othtyp << 8)) + (damamt + 128);
287 }
288
makeEnchantmentID(objectFlags othtyp,bool damamt)289 inline uint16 makeEnchantmentID(objectFlags othtyp, bool damamt) {
290 return ((effectNonActor << 13) | (othtyp << 8)) + (damamt + 128);
291 }
292
makeEnchantmentID(uint8 damamt)293 inline uint16 makeEnchantmentID(uint8 damamt) {
294 return ((effectPoison << 13) | (0 << 8)) + damamt;
295 }
296
getEnchantmentType(uint16 eID)297 inline effectTypes getEnchantmentType(uint16 eID) {
298 return (effectTypes)(eID >> 13);
299 }
300
getEnchantmentSubType(uint16 eID)301 inline uint16 getEnchantmentSubType(uint16 eID) {
302 return (eID >> 8) & 0x1F;
303 }
304
getEnchantmentAmount(uint16 eID)305 inline int16 getEnchantmentAmount(uint16 eID) {
306 return (eID & 0xFF) - 128;
307 }
308
309 // ------------------------------------------------------------------
310 // Determine whether an enchantment is harmful
311
isHarmful(uint16 enchID)312 inline bool isHarmful(uint16 enchID) {
313 int16 typ = getEnchantmentType(enchID);
314 int16 sub = getEnchantmentSubType(enchID);
315 int16 amt = getEnchantmentAmount(enchID);
316 if (typ == effectAttrib) return amt < 0;
317 if (typ == effectOthers)
318 return (sub >= actorSlowAttack && sub <= actorBlind);
319 return false;
320 }
321
322 // ------------------------------------------------------------------
323 // Determine whether an enchantment can fail
324
isSaveable(uint16 enchID)325 inline bool isSaveable(uint16 enchID) {
326 int16 typ = getEnchantmentType(enchID);
327 return (typ == effectOthers && isHarmful(enchID));
328 }
329
330 // ------------------------------------------------------------------
331 // Determine whether a damage type is magical
332
isMagicDamage(effectDamageTypes t)333 inline bool isMagicDamage(effectDamageTypes t) {
334 return t >= kDamageFire && t <= kDamageDirMagic;
335 }
336
337 #define Forever (255)
338
339 class SpellTarget;
340
341 //-------------------------------------------------------------------
342 // ProtoEffects
343
344 // This is the base class of several spell effect prototype classes
345 // The implement routine carries out the instantiation of a
346 // particular effect on a given target (doing damage or whatever)
347
348
349 class ProtoEffect {
350 //protected:
351 //int imp; // enchant or immediate
352
353 public:
354 ProtoEffect *next; // pointer to additional effects
355
ProtoEffect()356 ProtoEffect() {
357 next = NULL;
358 }
~ProtoEffect()359 virtual ~ProtoEffect() {
360 if (next) delete next;
361 next = NULL;
362 }
363 //int implementation( void ) { return imp; }
applicable(SpellTarget &)364 virtual bool applicable(SpellTarget &) {
365 return false;
366 }
367 virtual void implement(GameObject *, SpellTarget *, int8 = 0) {}
368 };
369
370
371 //-------------------------------------------------------------------
372 // ProtoDamage
373 // This class of effects does a range of damage to the target
374
375 class ProtoDamage: public ProtoEffect {
376 effectDamageTypes type; // damage type
377 int8 dice, // # of dice to roll
378 sides, // # of sides on dice
379 skillDice, // multiply by spellcraft to get additional dice
380 base, // absolute damage amount
381 skillBase; // absolute damage amount
382 int8 self; // casts at self
383
384 public:
385
386 ProtoDamage(int8 d, int8 s, int8 sd, int8 b, effectDamageTypes t, int, bool afSelf = false, int8 sb = 0) {
387 type = t;
388 dice = d;
389 sides = s;
390 skillDice = sd;
391 base = b;
392 self = afSelf;
393 skillBase = sb;
394 }
395
396 bool applicable(SpellTarget &trg);
397
398 void implement(GameObject *cst, SpellTarget *trg, int8 deltaDamage = 0);
399
400 static int16 getRelevantStat(effectDamageTypes dt, Actor *a);
401 };
402
403 //-------------------------------------------------------------------
404 // ProtoDrainage
405 // This class of effects does a range of damage to the target's
406 // mana, money or food supply
407
408 class ProtoDrainage: public ProtoEffect {
409 effectDrainsTypes type; // damage type
410 int8 dice, // # of dice to roll
411 sides, // # of sides on dice
412 skillDice, // multiply by spellcraft to get additional dice
413 base; // absolute damage amount
414 int8 self; // casts at self
415
416 public:
417
418 ProtoDrainage(int8 d, int8 s, int8 sd, int8 b, effectDrainsTypes t, int, bool afSelf = false) {
419 type = t;
420 dice = d;
421 sides = s;
422 skillDice = sd;
423 base = b;
424 self = afSelf;
425 }
426
427 bool applicable(SpellTarget &trg);
428
429 void implement(GameObject *cst, SpellTarget *trg, int8 deltaDamage = 0);
430
431 static int16 currentLevel(Actor *a, effectDrainsTypes edt);
432 static void drainLevel(GameObject *cst, Actor *a, effectDrainsTypes edt, int16 amt);
433 };
434
435 //-------------------------------------------------------------------
436 // ProtoEnchantment
437 // This can be any of several types of enchantments (see EFFECTS.H)
438 //
439
440 class ProtoEnchantment: public ProtoEffect {
441 uint16 enchID;
442 uint32 minEnch;
443 RandomDice dice; // enchantment time
444
445 public:
ProtoEnchantment(uint16 e,uint32 loTime,uint32 hiTime)446 ProtoEnchantment(uint16 e, uint32 loTime, uint32 hiTime) {
447 enchID = e;
448 dice = RandomDice(1, hiTime - loTime);
449 minEnch = loTime;
450 }
451
452 bool applicable(SpellTarget &trg);
453
454 void implement(GameObject *, SpellTarget *trg, int8 deltaDamage = 0);
455
canFail(void)456 bool canFail(void) {
457 return isSaveable(enchID);
458 }
459
460 static bool realSavingThrow(Actor *a);
461 };
462
463 //-------------------------------------------------------------------
464 // ProtoTAGEffect
465 // this type of spell sets up spells that are used to alter tags
466
467 class ProtoTAGEffect: public ProtoEffect {
468 effectTAGTypes affectBit;
469 int16 onOff; // lock/unlock or trigger ID
470 ObjectID trigger;
471
472 public:
ProtoTAGEffect(effectTAGTypes ett,int16 v,ObjectID t)473 ProtoTAGEffect(effectTAGTypes ett, int16 v, ObjectID t) {
474 affectBit = ett;
475 onOff = v;
476 trigger = t;
477 }
478
479 bool applicable(SpellTarget &trg);
480
481 void implement(GameObject *, SpellTarget *trg, int8 deltaDamage = 0);
482 };
483
484 //-------------------------------------------------------------------
485 // ProtoObjectEffect
486 // These effects are used only on non-actor objects.
487
488 class ProtoObjectEffect: public ProtoEffect {
489 uint16 affectBit;
490 int16 onOff;
491 RandomDice dice; // enchantment time
492
493 public:
ProtoObjectEffect(uint16 e,int16 v,uint32 loT,uint32 hiT)494 ProtoObjectEffect(uint16 e, int16 v, uint32 loT, uint32 hiT) {
495 affectBit = e;
496 onOff = v;
497 dice = RandomDice(loT, hiT);
498 }
499
500 bool applicable(SpellTarget &trg);
501
502 void implement(GameObject *, SpellTarget *trg, int8 deltaDamage = 0);
503 };
504
505 //-------------------------------------------------------------------
506 // If spells ever need to do things to Locations this
507 // is where they'll be
508
509 class ProtoLocationEffect: public ProtoEffect {
510 effectLocationTypes affectBit;
511 int16 value;
512
513 public:
ProtoLocationEffect(effectLocationTypes elt,int16 v)514 ProtoLocationEffect(effectLocationTypes elt, int16 v) {
515 affectBit = elt;
516 value = v;
517 }
518
applicable(SpellTarget &)519 bool applicable(SpellTarget &) {
520 return (true);
521 }
522
523 void implement(GameObject *, SpellTarget *trg, int8 deltaDamage = 0);
524 };
525
526 //-------------------------------------------------------------------
527 // ProtoSpecialEffects
528 // As always there are spells that just don't fit any of the other
529 // molds. These protoEffects allow customized spell handlers to be
530 // implemented.
531 //
532
533 typedef void SPELLIMPLEMENTATION(GameObject *, SpellTarget *);
534
535 #define SPECIALSPELL(name) void name(GameObject *cst, SpellTarget *trg)
536
537 class ProtoSpecialEffect: public ProtoEffect {
538 int16 routineID;
539 SPELLIMPLEMENTATION *handler;
540
541 public:
542 ProtoSpecialEffect(SPELLIMPLEMENTATION *newHandler, int16 callID = 0) {
543 handler = newHandler;
544 routineID = callID;
545 }
546
applicable(SpellTarget &)547 bool applicable(SpellTarget &) {
548 return true;
549 //return (trg.getType()==SpellTarget::spellTargetObject ||
550 // trg.getType()==SpellTarget::spellTargetObjectPoint) &&
551 // isActor(trg.getObject());
552 }
553
554 void implement(GameObject *, SpellTarget *trg, int8 deltaDamage = 0);
555 };
556
557 } // end of namespace Saga2
558
559 #endif
560