scummvm/engines/saga2/spellini.cpp
2022-10-29 14:44:54 +02:00

290 lines
10 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 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
* aint32 with this program; if not, write to the Free Software
*
*
* Based on the original sources
* Faery Tale II -- The Halls of the Dead
* (c) 1993-1996 The Wyrmkeep Entertainment Co.
*/
#include "saga2/saga2.h"
#include "saga2/spelshow.h"
#include "saga2/spelvals.h"
#include "saga2/tilevect.h"
namespace Saga2 {
// ------------------------------------------------------------------
// Spell Display Initialization handlers
//
// What is primarily done in these routines is to set up
// the positions, velocities & accelerations of the individual
// effectrons
// In most cases, once the effectrons are given their initial
// push they can be updated by just adding the velocity to the
// position.
// Sprite directionality is also set up here
//
/* ===================================================================== *
Inlines
* ===================================================================== */
#define randOff (randomVector(TilePoint(-1,-1,0),TilePoint(1,1,0)))
/* ===================================================================== *
Effect specific code
* ===================================================================== */
// ------------------------------------------------------------------
// null effect
SPELLINITFUNCTION(invisibleSpellInit) {
effectron->_velocity = TilePoint(0, 0, 0);
effectron->_acceleration = TilePoint(0, 0, 0);
}
// ------------------------------------------------------------------
// aura that tracks target
SPELLINITFUNCTION(auraSpellInit) {
if (effectron->_parent->_maxAge)
effectron->_totalSteps = effectron->_parent->_maxAge;
else
effectron->_totalSteps = 20;
effectron->_current = effectron->_parent->_target->getPoint();
effectron->_velocity = TilePoint(0, 0, 0);
effectron->_acceleration = TilePoint(0, 0, 0);
}
// ------------------------------------------------------------------
// aura that tracks target (in front)
SPELLINITFUNCTION(glowSpellInit) {
if (effectron->_parent->_maxAge)
effectron->_totalSteps = effectron->_parent->_maxAge;
else
effectron->_totalSteps = 20;
effectron->_current = effectron->_parent->_target->getPoint() - TilePoint(1, 1, 0);
effectron->_finish = effectron->_current;
effectron->_velocity = TilePoint(0, 0, 0);
effectron->_acceleration = TilePoint(0, 0, 0);
}
// ------------------------------------------------------------------
// sprites that surround target
SPELLINITFUNCTION(wallSpellInit) {
if (effectron->_parent->_maxAge)
effectron->_totalSteps = effectron->_parent->_maxAge;
else
effectron->_totalSteps = 20;
effectron->_current = effectron->_parent->_target->getPoint();
effectron->_velocity = WallVectors[effectron->_partno] * kWallSpellRadius / 3;
effectron->_current = effectron->_parent->_target->getPoint() + effectron->_velocity;
effectron->_acceleration = TilePoint(0, 0, 0);
}
// ------------------------------------------------------------------
// projectile from caster to target
SPELLINITFUNCTION(projectileSpellInit) {
effectron->_start = effectron->_current;
effectron->_finish = effectron->_parent->_target->getPoint();
TilePoint tp = (effectron->_finish - effectron->_start);
effectron->_totalSteps = 1 + (tp.magnitude() / (2 * kSpellJumpiness));
effectron->_velocity = tp / effectron->_totalSteps;
effectron->_acceleration = TilePoint(0, 0, 0);
}
// ------------------------------------------------------------------
// bi-directional beams of energy
SPELLINITFUNCTION(exchangeSpellInit) {
if (effectron->_partno % 2) {
effectron->_finish = effectron->_current;
effectron->_start = effectron->_parent->_target->getPoint();
} else {
effectron->_start = effectron->_current;
effectron->_finish = effectron->_parent->_target->getPoint();
}
TilePoint tp = (effectron->_finish - effectron->_start);
effectron->_totalSteps = 1 + (tp.magnitude() / (kSpellJumpiness));
effectron->_velocity = tp / effectron->_totalSteps;
effectron->_totalSteps += (effectron->_partno / 2);
effectron->_acceleration = TilePoint(0, 0, 0);
effectron->_current = effectron->_start;
}
// ------------------------------------------------------------------
// lightning bolt shaped spell
SPELLINITFUNCTION(boltSpellInit) {
effectron->_stepNo = 0;
if (effectron->_parent->_maxAge)
effectron->_totalSteps = effectron->_parent->_maxAge;
else
effectron->_totalSteps = 1 + (kBoltSpellLength / (kSpellJumpiness * 3));
effectron->_start = effectron->_current;
effectron->_finish = effectron->_parent->_target->getPoint();
TilePoint tVect = effectron->_finish - effectron->_start ;
setMagnitude(tVect, kBoltSpellLength);
TilePoint orth = rightVector(tVect, 0);
setMagnitude(orth, kBoltSpellWidth * (effectron->_partno % 3 - 1) / 6);
TilePoint offVect = tVect * ((effectron->_partno / 3) % 3) / (kSpellJumpiness * 3);
effectron->_start += orth;
effectron->_finish += orth + offVect;
effectron->_velocity = tVect / effectron->_totalSteps + randOff;
effectron->_acceleration = TilePoint(0, 0, 0);
effectron->_current = effectron->_start;
}
// ------------------------------------------------------------------
// narrow bolt
SPELLINITFUNCTION(beamSpellInit) {
effectron->_stepNo = 0;
if (effectron->_parent->_maxAge)
effectron->_totalSteps = effectron->_parent->_maxAge;
else
effectron->_totalSteps = 1 + (kBeamSpellLength / (kSpellJumpiness));
effectron->_start = effectron->_current;
effectron->_finish = effectron->_parent->_target->getPoint();
TilePoint tVect = effectron->_finish - effectron->_start ;
setMagnitude(tVect, kBeamSpellLength);
TilePoint orth = rightVector(tVect, 0);
setMagnitude(orth, kBeamSpellWidth / 2);
effectron->_start += (tVect * effectron->_partno) / effectron->_totalSteps;
effectron->_finish = effectron->_start;
effectron->_velocity = orth;
effectron->_acceleration = TilePoint(0, 0, 0);
effectron->_current = effectron->_start;
}
// ------------------------------------------------------------------
// narrow cone shaped spell
SPELLINITFUNCTION(coneSpellInit) {
effectron->_stepNo = 0;
effectron->_totalSteps = 1 + (kConeSpellLength / (kSpellJumpiness * 3));
effectron->_start = effectron->_current;
effectron->_finish = effectron->_parent->_target->getPoint();
TilePoint tVect = effectron->_finish - effectron->_start ;
setMagnitude(tVect, kConeSpellLength);
TilePoint orth = rightVector(tVect, 0);
setMagnitude(orth, kConeSpellWidth * (effectron->_partno % 9 - 4) / 8);
effectron->_finish = effectron->_start + tVect + orth;
effectron->_velocity = (effectron->_finish - effectron->_start) / effectron->_totalSteps + randOff;
effectron->_acceleration = TilePoint(0, 0, 0);
}
// ------------------------------------------------------------------
// wide cone shaped spell
SPELLINITFUNCTION(waveSpellInit) {
effectron->_stepNo = 0;
effectron->_totalSteps = 1 + (kConeSpellLength / (kSpellJumpiness * 2));
effectron->_start = effectron->_current;
effectron->_finish = effectron->_parent->_target->getPoint();
TilePoint tVect = effectron->_finish - effectron->_start ;
setMagnitude(tVect, kWaveSpellLength);
TilePoint orth = rightVector(tVect, 0);
setMagnitude(orth, kWaveSpellWidth * (effectron->_partno % 17 - 8) / 8);
effectron->_finish = effectron->_start + tVect + orth;
effectron->_velocity = (effectron->_finish - effectron->_start) / effectron->_totalSteps + randOff;
effectron->_acceleration = TilePoint(0, 0, 0);
}
// ------------------------------------------------------------------
// small exploding ball
SPELLINITFUNCTION(ballSpellInit) {
effectron->_stepNo = 0;
effectron->_start = effectron->_current;
effectron->_finish = FireballVectors[effectron->_partno];
setMagnitude(effectron->_finish, kBallSpellRadius);
effectron->_finish = effectron->_finish + effectron->_start;
effectron->_totalSteps = 1 + (kBallSpellRadius / kSpellJumpiness);
effectron->_acceleration = TilePoint(0, 0, 0);
TilePoint tp = (effectron->_finish - effectron->_start);
effectron->_totalSteps = 1 + (tp.magnitude() / kSpellJumpiness);
effectron->_velocity = tp / effectron->_totalSteps;
effectron->_velocity.z = 0;
effectron->_acceleration = TilePoint(0, 0, 0);
}
// ------------------------------------------------------------------
// square exploding ball
SPELLINITFUNCTION(squareSpellInit) {
effectron->_stepNo = 0;
effectron->_start = effectron->_current;
effectron->_finish = SquareSpellVectors[effectron->_partno];
setMagnitude(effectron->_finish, effectron->_finish.magnitude()*kSquareSpellSize / 4);
effectron->_finish = effectron->_finish + effectron->_start;
effectron->_totalSteps = 1 + (kSquareSpellSize / kSpellJumpiness);
effectron->_acceleration = TilePoint(0, 0, 0);
TilePoint tp = (effectron->_finish - effectron->_start);
effectron->_totalSteps = 1 + (tp.magnitude() / kSpellJumpiness);
effectron->_velocity = tp / effectron->_totalSteps;
effectron->_velocity.z = 0;
effectron->_acceleration = TilePoint(0, 0, 0);
}
// ------------------------------------------------------------------
// large exploding ball
SPELLINITFUNCTION(stormSpellInit) {
effectron->_stepNo = 0;
effectron->_start = effectron->_current;
effectron->_finish = FireballVectors[effectron->_partno];
setMagnitude(effectron->_finish, kBallSpellRadius);
effectron->_finish = effectron->_finish + effectron->_start;
effectron->_totalSteps = 1 + (kBallSpellRadius / kSpellJumpiness);
effectron->_acceleration = TilePoint(0, 0, 0);
TilePoint tp = (effectron->_finish - effectron->_start);
effectron->_totalSteps = 1 + (2 * tp.magnitude() / kSpellJumpiness);
effectron->_velocity = tp / effectron->_totalSteps;
effectron->_velocity.z = 0;
effectron->_acceleration = TilePoint(0, 0, 0);
}
} // end of namespace Saga2