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