Initial commit
This commit is contained in:
424
engines/saga2/beegee.cpp
Normal file
424
engines/saga2/beegee.cpp
Normal file
@@ -0,0 +1,424 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include "saga2/saga2.h"
|
||||
#include "saga2/idtypes.h"
|
||||
#include "saga2/tile.h"
|
||||
#include "saga2/beegee.h"
|
||||
#include "saga2/player.h"
|
||||
|
||||
namespace Saga2 {
|
||||
|
||||
#define AUXTHEMES 2
|
||||
#define USEAUXTHEME 0xe0
|
||||
|
||||
void addAuxTheme(Location loc, uint32 lid);
|
||||
void killAuxTheme(uint32 lid);
|
||||
void killAllAuxThemes();
|
||||
|
||||
|
||||
enum audioTerrains {
|
||||
kAudioTerrainForest = 1,
|
||||
kAudioTerrainSurf,
|
||||
kAudioTerrainCity,
|
||||
kAudioTerrainCavern,
|
||||
kAudioTerrainColdWind,
|
||||
kAudioTerrainJungle,
|
||||
kAudioTerrainLava,
|
||||
kAudioTerrainRiver,
|
||||
kAudioTerrainFire,
|
||||
|
||||
kAudioTerrainLIMIT
|
||||
};
|
||||
|
||||
enum {
|
||||
kCheckGameTime = 1000
|
||||
};
|
||||
|
||||
struct IntermittentAudioRecord {
|
||||
int noSoundOdds;
|
||||
int soundOdds[4];
|
||||
};
|
||||
|
||||
const IntermittentAudioRecord intermittentAudioRecords[kAudioTerrainLIMIT] = {
|
||||
//
|
||||
// none 1 2 3 4
|
||||
//
|
||||
{ 0, { 0, 0, 0, 0 } }, // no record
|
||||
{ 1, { 1, 0, 0, 0 } }, // Forest
|
||||
{ 0, { 0, 0, 0, 0 } }, // Surf
|
||||
{ 0, { 0, 0, 0, 0 } }, // City
|
||||
{ 0, { 0, 0, 0, 0 } }, // Cavern
|
||||
{ 0, { 0, 0, 0, 0 } }, // ColdWind
|
||||
{ 0, { 0, 0, 0, 0 } }, // Jungle
|
||||
{ 0, { 0, 0, 0, 0 } }, // Lava
|
||||
{ 0, { 0, 0, 0, 0 } }, // River
|
||||
{ 0, { 0, 0, 0, 0 } } // Fire
|
||||
};
|
||||
|
||||
|
||||
// Factional music mapping
|
||||
// Built in factions
|
||||
// 0 = suspended
|
||||
// 1 = daytime 1
|
||||
// 2 = daytime 2
|
||||
// 3 = underground
|
||||
// 4 = nighttime
|
||||
// 5 = aggressive
|
||||
// Faction based
|
||||
// 6 = faction 0
|
||||
// 7 = faction 1
|
||||
// etc
|
||||
|
||||
inline int8 musicMapping(int16 musicChoice) {
|
||||
if (musicChoice < 1) {
|
||||
return 0;
|
||||
} else if (musicChoice < 6) {
|
||||
return musicChoice;
|
||||
} else if (musicChoice == 6) {
|
||||
return 6;
|
||||
} else if (musicChoice > 11 && musicChoice < 14) {
|
||||
return 7;
|
||||
} else if (musicChoice > 8 && musicChoice < 12) {
|
||||
return 8;
|
||||
} else {
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
const static StaticTilePoint AudibilityVector = { 1, 1, 0 };
|
||||
|
||||
/* ===================================================================== *
|
||||
Imports
|
||||
* ===================================================================== */
|
||||
|
||||
extern volatile int32 gameTime;
|
||||
|
||||
extern uint16 rippedRoofID;
|
||||
|
||||
extern GameObject *getViewCenterObject();
|
||||
|
||||
#if DEBUG
|
||||
extern bool debugAudioThemes;
|
||||
#endif
|
||||
|
||||
/* ===================================================================== *
|
||||
Prototypes
|
||||
* ===================================================================== */
|
||||
|
||||
#define musicResID(i) MKTAG('X','M','I',i)
|
||||
|
||||
inline metaTileNoise getSound(MetaTilePtr mt) {
|
||||
int hmm = mt->HeavyMetaMusic();
|
||||
return (hmm >= 0 && hmm < kMaxThemes) ? hmm : 0;
|
||||
}
|
||||
inline uint32 metaNoiseID(metaTileNoise mtnID) {
|
||||
return mtnID ? MKTAG('T', 'E', 'R', mtnID) : 0;
|
||||
}
|
||||
|
||||
void _playLoop(uint32 s);
|
||||
MetaTileID lookupMetaID(TilePoint coords);
|
||||
|
||||
/* ===================================================================== *
|
||||
Module code
|
||||
* ===================================================================== */
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// init
|
||||
|
||||
void initAudioEnvirons() {
|
||||
}
|
||||
|
||||
/* ===================================================================== *
|
||||
Looped sound engine
|
||||
* ===================================================================== */
|
||||
|
||||
void addAuxTheme(Location loc, uint32 lid) {
|
||||
for (int i = 0; i < AUXTHEMES; i++) {
|
||||
if (!g_vm->_grandMasterFTA->_aats[i].active) {
|
||||
g_vm->_grandMasterFTA->_aats[i].l = loc;
|
||||
g_vm->_grandMasterFTA->_aats[i].loopID = lid;
|
||||
g_vm->_grandMasterFTA->_aats[i].active = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void killAuxTheme(uint32 lid) {
|
||||
for (int i = 0; i < AUXTHEMES; i++) {
|
||||
if (g_vm->_grandMasterFTA->_aats[i].active && g_vm->_grandMasterFTA->_aats[i].loopID == lid) {
|
||||
g_vm->_grandMasterFTA->_aats[i].active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void killAllAuxThemes() {
|
||||
for (int i = 0; i < AUXTHEMES; i++) {
|
||||
g_vm->_grandMasterFTA->_aats[i].active = false;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Hooks to allow other loops to play
|
||||
|
||||
void disableBGLoop(bool s) {
|
||||
g_vm->_grandMasterFTA->_playingExternalLoop = s;
|
||||
}
|
||||
|
||||
void enableBGLoop() {
|
||||
uint32 cr = g_vm->_grandMasterFTA->_currentTheme;
|
||||
g_vm->_grandMasterFTA->_playingExternalLoop = false;
|
||||
g_vm->_grandMasterFTA->_currentTheme = 0;
|
||||
audioEnvironmentUseSet(cr, g_vm->_grandMasterFTA->_auxTheme, g_vm->_grandMasterFTA->_themeAt);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Main loop selection routine - called from Tile.cpp
|
||||
|
||||
void setAreaSound(const TilePoint &) {
|
||||
g_vm->_grandMasterFTA->_pct = (g_vm->_grandMasterFTA->_pct + 1) % 8;
|
||||
if (g_vm->_grandMasterFTA->_pct == 0) {
|
||||
if (!g_vm->_grandMasterFTA->_playingExternalLoop) {
|
||||
TilePoint baseCoords = centerActorCoords() >> kTileUVShift;
|
||||
TilePoint mtPos;
|
||||
metaTileNoise loopID = 0;
|
||||
uint32 ss = 0;
|
||||
Point32 themePos;
|
||||
for (int r = 1; r < 5 && loopID == 0 ; r++) {
|
||||
TileRegion regn;
|
||||
TilePoint AudVec = TilePoint(AudibilityVector);
|
||||
regn.max = baseCoords + ((AudVec * r) << kPlatShift) ; ///kTileUVSize;
|
||||
regn.min = baseCoords - ((AudVec * r) << kPlatShift); ///kTileUVSize;
|
||||
MetaTileIterator mIter(g_vm->_currentMapNum, regn);
|
||||
int i = 0;
|
||||
|
||||
TilePoint dist = AudVec * r << (kPlatShift + 1);
|
||||
dist = dist << 4;
|
||||
themePos.x = dist.u;
|
||||
themePos.y = dist.v;
|
||||
MetaTilePtr mt = mIter.first(&mtPos);
|
||||
while (mt) {
|
||||
i++;
|
||||
if (getSound(mt)) {
|
||||
TilePoint thisDist = mtPos - baseCoords;
|
||||
if (thisDist.magnitude() < dist.magnitude()) {
|
||||
dist = thisDist;
|
||||
loopID = getSound(mt);
|
||||
themePos.x = thisDist.u;
|
||||
themePos.y = thisDist.v;
|
||||
}
|
||||
}
|
||||
mt = mIter.next(&mtPos);
|
||||
}
|
||||
for (i = 0; i < AUXTHEMES; i++) {
|
||||
if (g_vm->_grandMasterFTA->_aats[i].active) {
|
||||
Location loc = getCenterActor()->notGetWorldLocation();
|
||||
if (g_vm->_grandMasterFTA->_aats[i].l._context == Nothing || loc._context == g_vm->_grandMasterFTA->_aats[i].l._context) {
|
||||
TilePoint tp = (g_vm->_grandMasterFTA->_aats[i].l >> kTileUVShift) - baseCoords;
|
||||
if (tp.magnitude() < dist.magnitude()) {
|
||||
dist = tp;
|
||||
loopID = USEAUXTHEME;
|
||||
ss = g_vm->_grandMasterFTA->_aats[i].loopID;
|
||||
themePos.x = tp.u;
|
||||
themePos.y = tp.v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rippedRoofID) {
|
||||
loopID = 0;
|
||||
}
|
||||
audioEnvironmentUseSet(loopID, ss, themePos << kPlatShift);
|
||||
} else if (g_vm->_grandMasterFTA->_playingExternalLoop) {
|
||||
audioEnvironmentUseSet(g_vm->_grandMasterFTA->_playingExternalLoop, 0, Point16(0, 0)); //themePos << kPlatShift);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Implement a particular loop
|
||||
|
||||
void audioEnvironmentUseSet(int16 audioSet, int32 auxID, Point32 relPos) {
|
||||
uint32 res;
|
||||
if (audioSet == USEAUXTHEME)
|
||||
res = auxID;
|
||||
else if (audioSet > 0 && audioSet <= 16)
|
||||
res = metaNoiseID(audioSet);
|
||||
else
|
||||
res = 0;
|
||||
if (g_vm->_grandMasterFTA->_currentTheme != (uint16)audioSet || g_vm->_grandMasterFTA->_auxTheme != (uint32)auxID) {
|
||||
g_vm->_grandMasterFTA->_currentTheme = audioSet;
|
||||
g_vm->_grandMasterFTA->_auxTheme = auxID;
|
||||
g_vm->_grandMasterFTA->_themeAt.x = relPos.x;
|
||||
g_vm->_grandMasterFTA->_themeAt.y = relPos.y;
|
||||
_playLoop(0);
|
||||
if (g_vm->_grandMasterFTA->_currentTheme)
|
||||
playLoopAt(res, g_vm->_grandMasterFTA->_themeAt);
|
||||
|
||||
} else if (g_vm->_grandMasterFTA->_currentTheme && g_vm->_grandMasterFTA->_themeAt != relPos) {
|
||||
#if DEBUG
|
||||
if (debugAudioThemes) {
|
||||
WriteStatusF(9, "Thm: %2.2d (%d,%d) was (%d,%d) ", audioSet, relPos.x, relPos.y, g_vm->_grandMasterFTA->_themeAt.x, g_vm->_grandMasterFTA->_themeAt.y);
|
||||
}
|
||||
#endif
|
||||
g_vm->_grandMasterFTA->_themeAt.x = relPos.x;
|
||||
g_vm->_grandMasterFTA->_themeAt.y = relPos.y;
|
||||
moveLoop(g_vm->_grandMasterFTA->_themeAt);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Intermittent sound check
|
||||
|
||||
void audioEnvironmentCheck() {
|
||||
|
||||
uint32 delta = gameTime - g_vm->_grandMasterFTA->_lastGameTime;
|
||||
g_vm->_grandMasterFTA->_lastGameTime = gameTime;
|
||||
if (g_vm->_grandMasterFTA->_currentTheme > 0 && g_vm->_grandMasterFTA->_currentTheme <= kAudioTerrainLIMIT) {
|
||||
g_vm->_grandMasterFTA->_elapsedGameTime += delta;
|
||||
if (g_vm->_grandMasterFTA->_elapsedGameTime > kCheckGameTime) {
|
||||
int i;
|
||||
g_vm->_grandMasterFTA->_elapsedGameTime = 0;
|
||||
const IntermittentAudioRecord &iar = intermittentAudioRecords[g_vm->_grandMasterFTA->_currentTheme];
|
||||
int16 totalProb = iar.noSoundOdds;
|
||||
for (i = 0; i < 4; i++)
|
||||
totalProb += iar.soundOdds[i];
|
||||
if (totalProb <= iar.noSoundOdds)
|
||||
return;
|
||||
int32 pval = g_vm->_rnd->getRandomNumber(totalProb - 1);
|
||||
if (pval < iar.noSoundOdds)
|
||||
return;
|
||||
pval -= iar.noSoundOdds;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (pval < iar.soundOdds[i]) {
|
||||
//GameObject *go=getViewCenterObject();
|
||||
//Location cal=Location(TilePoint(g_vm->_grandMasterFTA->_themeAt.x,g_vm->_grandMasterFTA->_themeAt.y,0),go->IDParent());
|
||||
//playSound(metaNoiseID((g_vm->_grandMasterFTA->_currentTheme*10)+i));
|
||||
playSoundAt(metaNoiseID((g_vm->_grandMasterFTA->_currentTheme * 10) + i), g_vm->_grandMasterFTA->_themeAt);
|
||||
return;
|
||||
} else
|
||||
pval -= iar.soundOdds[i];
|
||||
}
|
||||
|
||||
}
|
||||
} else if (g_vm->_grandMasterFTA->_currentTheme)
|
||||
warning("currentTheme out of range: %d", g_vm->_grandMasterFTA->_currentTheme);
|
||||
|
||||
}
|
||||
|
||||
/* ===================================================================== *
|
||||
Music environment engine
|
||||
* ===================================================================== */
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Intermittent sound check
|
||||
|
||||
void Deejay::select() {
|
||||
int choice = 0;
|
||||
#if DEBUG & 0
|
||||
if (1)
|
||||
choice = 0;
|
||||
else
|
||||
#endif
|
||||
if (_susp)
|
||||
choice = 0;
|
||||
else if (_enemy >= 0)
|
||||
choice = _enemy + 6;
|
||||
else if (_aggr)
|
||||
choice = 5;
|
||||
else if (_ugd)
|
||||
choice = 3;
|
||||
//else if ( !day )
|
||||
// choice=4;
|
||||
else if (_current != 4 && (_current > 2 || _current < 1)) {
|
||||
choice = 1 + g_vm->_rnd->getRandomNumber(2);
|
||||
if (choice == 3) choice++;
|
||||
} else
|
||||
choice = _current;
|
||||
|
||||
if (_currentID != musicMapping(choice)) {
|
||||
_currentID = musicMapping(choice);
|
||||
if (_currentID)
|
||||
playMusic(musicResID(_currentID));
|
||||
else
|
||||
playMusic(0);
|
||||
}
|
||||
_current = choice;
|
||||
#if DEBUG
|
||||
if (debugAudioThemes) {
|
||||
WriteStatusF(8, "Music: %2.2d => %2.2d ", _current, _currentID);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Faction enumeration routines
|
||||
|
||||
void clearActiveFactions() {
|
||||
for (int i = 0; i < kMaxFactions; i++)
|
||||
g_vm->_grandMasterFTA->_activeFactions[i] = 0;
|
||||
}
|
||||
|
||||
void incrementActiveFaction(Actor *a) {
|
||||
g_vm->_grandMasterFTA->_activeFactions[a->_faction]++;
|
||||
}
|
||||
|
||||
void useActiveFactions() {
|
||||
int highCount = 0;
|
||||
int highFaction = 0;
|
||||
for (int i = 0; i < kMaxFactions; i++) {
|
||||
if (g_vm->_grandMasterFTA->_activeFactions[i] > highCount) {
|
||||
highCount = g_vm->_grandMasterFTA->_activeFactions[i];
|
||||
highFaction = i;
|
||||
}
|
||||
}
|
||||
if (highCount)
|
||||
g_vm->_grandMasterFTA->setEnemy(highFaction);
|
||||
else
|
||||
g_vm->_grandMasterFTA->setEnemy(kNoEnemy);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Aggresssion & day/night control
|
||||
|
||||
void audioEnvironmentSetAggression(bool onOff) {
|
||||
g_vm->_grandMasterFTA->setAggression(onOff);
|
||||
}
|
||||
|
||||
void audioEnvironmentSetDaytime(bool onOff) {
|
||||
g_vm->_grandMasterFTA->setDaytime(onOff);
|
||||
}
|
||||
|
||||
void audioEnvironmentSuspend(bool onOff) {
|
||||
g_vm->_grandMasterFTA->setSuspend(onOff);
|
||||
}
|
||||
|
||||
void audioEnvironmentSetWorld(int mapNum) {
|
||||
g_vm->_grandMasterFTA->setWorld(mapNum == 1);
|
||||
}
|
||||
|
||||
} // end of namespace Saga2
|
||||
Reference in New Issue
Block a user