mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-04 01:46:42 +00:00
353 lines
9.3 KiB
C++
353 lines
9.3 KiB
C++
/* 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 2
|
|
* 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
|
|
* aint32 with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*
|
|
* Based on the original sources
|
|
* Faery Tale II -- The Halls of the Dead
|
|
* (c) 1993-1996 The Wyrmkeep Entertainment Co.
|
|
*/
|
|
|
|
#define FORBIDDEN_SYMBOL_ALLOW_ALL // FIXME: Remove
|
|
|
|
#include "saga2/std.h"
|
|
#include "saga2/rmemfta.h"
|
|
#include "saga2/weapons.h"
|
|
|
|
namespace Saga2 {
|
|
|
|
//-------------------------------------------------------------------
|
|
// The initialization for spells is done in this module:
|
|
// - Display Effects are defined (ball spell, bolt spell, etc)
|
|
// - The spell definitions are loaded from the resource file
|
|
// - The spell internal effect definitions are loaded from disk
|
|
// and attached to the appropriate spell
|
|
// - Spell Color maps are loaded from the resource file
|
|
// - This file is also home to most of the global variables
|
|
// which relate to spell casting
|
|
//
|
|
|
|
/* ===================================================================== *
|
|
Constants
|
|
* ===================================================================== */
|
|
|
|
const int32 maxWeapons = 256;
|
|
const int32 maxWeaponPrototypes = 256;
|
|
|
|
/* ===================================================================== *
|
|
Global data
|
|
* ===================================================================== */
|
|
|
|
WeaponStuff weaponRack[maxWeapons];
|
|
weaponID loadedWeapons = 0;
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
// prototypes
|
|
|
|
static void loadWeaponData(void);
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
ProtoEffect *createNewProtoEffect(ResourceItemEffect *rie) {
|
|
ProtoEffect *pe = NULL;
|
|
|
|
switch (rie->effectGroup) {
|
|
case effectNone :
|
|
return NULL;
|
|
|
|
case effectAttrib :
|
|
pe = NEW_EFCT ProtoEnchantment(
|
|
makeEnchantmentID(
|
|
rie->effectGroup,
|
|
rie->effectType,
|
|
rie->baseDamage),
|
|
rie->reserved0,
|
|
rie->reserved1);
|
|
break;
|
|
case effectResist :
|
|
case effectImmune :
|
|
case effectOthers :
|
|
case effectNonActor :
|
|
pe = NEW_EFCT ProtoEnchantment(
|
|
makeEnchantmentID(
|
|
rie->effectGroup,
|
|
rie->effectType,
|
|
rie->skillDamage),
|
|
rie->reserved0,
|
|
rie->reserved1);
|
|
break;
|
|
case effectDamage :
|
|
pe = NEW_EFCT ProtoDamage(
|
|
rie->baseDice,
|
|
rie->diceSides ? rie->diceSides : 6,
|
|
rie->skillDice,
|
|
rie->baseDamage,
|
|
(effectDamageTypes) rie->effectType,
|
|
0,
|
|
rie->targeting & spellTargCaster,
|
|
rie->skillDamage);
|
|
break;
|
|
case effectDrains :
|
|
pe = NEW_EFCT ProtoDrainage(
|
|
rie->baseDice,
|
|
rie->diceSides ? rie->diceSides : 6,
|
|
rie->skillDice,
|
|
rie->baseDamage,
|
|
(effectDrainsTypes) rie->effectType,
|
|
0,
|
|
rie->targeting & spellTargCaster);
|
|
break;
|
|
|
|
case effectPoison :
|
|
pe = NEW_EFCT ProtoEnchantment(
|
|
makeEnchantmentID(rie->baseDamage), // poison
|
|
rie->reserved0,
|
|
rie->reserved1);
|
|
|
|
case effectTAG :
|
|
pe = NEW_EFCT ProtoTAGEffect(
|
|
(effectTAGTypes) rie->effectType,
|
|
rie->skillDamage,
|
|
rie->baseDamage);
|
|
break;
|
|
case effectLocation :
|
|
pe = NEW_EFCT ProtoLocationEffect(
|
|
(effectLocationTypes) rie->effectType,
|
|
rie->baseDamage);
|
|
break;
|
|
case effectSpecial :
|
|
pe = NEW_EFCT ProtoSpecialEffect(
|
|
SagaSpellCall,
|
|
rie->baseDamage);
|
|
break;
|
|
}
|
|
|
|
if (pe == NULL)
|
|
error("failed to alloc protoEffect");
|
|
|
|
return pe;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// InitMagic called from main startup code
|
|
|
|
void initWeapons(void) {
|
|
loadWeaponData();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void cleanupWeapons(void) {
|
|
for (int i = 0; i < maxWeapons; i++)
|
|
weaponRack[i].killEffects();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
WeaponStuff &getWeapon(weaponID i) {
|
|
if (i < loadedWeapons)
|
|
return weaponRack[i];
|
|
return weaponRack[nullWeapon];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
GameObject *getShieldItem(GameObject *defender) {
|
|
assert(isActor(defender));
|
|
Actor *a = (Actor *) defender;
|
|
GameObject *obj;
|
|
|
|
a->defensiveObject(&obj);
|
|
return obj;
|
|
}
|
|
|
|
/* ===================================================================== *
|
|
WeaponProtoEffect member functions
|
|
* ===================================================================== */
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void WeaponProtoEffect::implement(
|
|
Actor *enactor,
|
|
GameObject *target,
|
|
GameObject *,
|
|
uint8) {
|
|
SpellTarget targ(target);
|
|
|
|
if (effect != NULL)
|
|
effect->implement(enactor, &targ);
|
|
}
|
|
|
|
/* ===================================================================== *
|
|
WeaponStrikeEffect member functions
|
|
* ===================================================================== */
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void WeaponStrikeEffect::implement(
|
|
Actor *enactor,
|
|
GameObject *target,
|
|
GameObject *strikingObj,
|
|
uint8 strength) {
|
|
assert(isActor(enactor));
|
|
assert(isObject(target) || isActor(target));
|
|
assert(isObject(strikingObj) || isActor(strikingObj));
|
|
|
|
int8 totalDice,
|
|
totalBase;
|
|
|
|
totalDice = dice + strength * skillDice;
|
|
totalBase = base + strength * skillBase;
|
|
|
|
target->acceptDamage(
|
|
enactor->thisID(),
|
|
totalBase,
|
|
type,
|
|
totalDice,
|
|
sides);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
WeaponStuff::WeaponStuff() {
|
|
effects = NULL;
|
|
master = nullWeapon;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
WeaponStuff::~WeaponStuff() {
|
|
while (effects != NULL) {
|
|
WeaponEffect *curEffect = effects;
|
|
|
|
effects = effects->next;
|
|
delete curEffect;
|
|
}
|
|
master = nullWeapon;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void WeaponStuff::killEffects(void) {
|
|
while (effects != NULL) {
|
|
WeaponEffect *curEffect = effects;
|
|
|
|
effects = effects->next;
|
|
delete curEffect;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void WeaponStuff::addEffect(WeaponEffect *we) {
|
|
WeaponEffect *e = effects;
|
|
if (effects) {
|
|
while (e->next) e = e->next;
|
|
e->next = we;
|
|
} else {
|
|
effects = we;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void WeaponStuff::addEffect(ResourceItemEffect *rie) {
|
|
WeaponEffect *we;
|
|
assert(rie);
|
|
assert(rie && rie->item == master);
|
|
|
|
if (rie->effectGroup == effectStrike) {
|
|
we = NEW_EFCT WeaponStrikeEffect(
|
|
(effectDamageTypes)rie->effectType,
|
|
rie->baseDice,
|
|
rie->diceSides != 0 ? rie->diceSides : 6,
|
|
rie->skillDice,
|
|
rie->baseDamage,
|
|
rie->skillDamage);
|
|
} else
|
|
we = NEW_EFCT WeaponProtoEffect(rie);
|
|
|
|
if (we == NULL)
|
|
error("failed to alloc weapon effect");
|
|
|
|
if (effects == NULL)
|
|
effects = we;
|
|
else {
|
|
WeaponEffect *tail;
|
|
for (tail = effects; tail->next; tail = tail->next) ;
|
|
tail->next = we;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void WeaponStuff::implement(
|
|
Actor *enactor,
|
|
GameObject *target,
|
|
GameObject *strikingObj,
|
|
uint8 strength) {
|
|
WeaponEffect *we;
|
|
|
|
for (we = effects; we != NULL; we = we->next)
|
|
we->implement(enactor, target, strikingObj, strength);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
static void loadWeaponData(void) {
|
|
int16 i;
|
|
hResContext *spellRes;
|
|
|
|
// Get spell definitions
|
|
spellRes = auxResFile->newContext(
|
|
RES_ID('I', 'T', 'E', 'M'),
|
|
"weapon resources");
|
|
if (spellRes == NULL || !spellRes->_valid)
|
|
error("Error accessing weapon resource group.");
|
|
|
|
// get spell effects
|
|
i = 0;
|
|
while (spellRes->size(
|
|
RES_ID('E', 'F', 'F', i)) > 0) {
|
|
ResourceItemEffect *rie =
|
|
(ResourceItemEffect *)LoadResource(
|
|
spellRes,
|
|
RES_ID('E', 'F', 'F', i),
|
|
"weapon effect");
|
|
|
|
if (rie == NULL)
|
|
error("Unable to load weapon effect %d", i);
|
|
|
|
if (rie->item) {
|
|
weaponRack[rie->item].setID(rie->item);
|
|
weaponRack[rie->item].addEffect(rie);
|
|
}
|
|
|
|
RDisposePtr(rie);
|
|
i++;
|
|
}
|
|
loadedWeapons = i;
|
|
assert(i > 1);
|
|
|
|
auxResFile->disposeContext(spellRes);
|
|
}
|
|
|
|
} // end of namespace Saga2
|