369 lines
11 KiB
C++
369 lines
11 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
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "watchmaker/classes/do_sound.h"
|
|
#include "watchmaker/utils.h"
|
|
#include "watchmaker/types.h"
|
|
#include "watchmaker/globvar.h"
|
|
#include "watchmaker/windows_hacks.h"
|
|
#include "watchmaker/define.h"
|
|
#include "watchmaker/ll/ll_sound.h"
|
|
#include "watchmaker/3d/geometry.h"
|
|
#include "watchmaker/3d/t3d_body.h"
|
|
#include "watchmaker/3d/t3d_mesh.h"
|
|
#include "watchmaker/work_dirs.h"
|
|
#include "watchmaker/ll/ll_util.h"
|
|
#include "watchmaker/game.h"
|
|
#include "watchmaker/walk/walkutil.h"
|
|
|
|
#define METER2UNIT 256.051971816707218167072181680248f
|
|
|
|
#define PG 3.14159265358979323846f
|
|
#define GradToRad ((2.0f*PG)/360.0f)
|
|
|
|
#define gCOS(G) cos(G*GradToRad)
|
|
#define gSIN(G) sin(G*GradToRad)
|
|
|
|
namespace Watchmaker {
|
|
|
|
/* -----------------28/06/00 16.33-------------------
|
|
* InitMusic
|
|
* --------------------------------------------------*/
|
|
bool InitMusic() {
|
|
warning("STUBBED InitMusic");
|
|
#if 0
|
|
if (!mInitMusicSystem())
|
|
return false;
|
|
if (!sInitSoundSystem(hWnd))
|
|
return false;
|
|
|
|
sSetDistanceFactor(METER2UNIT);
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
bool ListenerUpdate() {
|
|
sListener CurListener;
|
|
|
|
CurListener.flDistanceFactor = 1.0f;
|
|
CurListener.flRolloff = 0.1f;
|
|
CurListener.v3flFrontOrientation.x = t3dCurCamera->NormalizedDir.x;
|
|
CurListener.v3flFrontOrientation.y = t3dCurCamera->NormalizedDir.y;
|
|
CurListener.v3flFrontOrientation.z = t3dCurCamera->NormalizedDir.z;
|
|
CurListener.v3flTopOrientation.x = 0.0f;
|
|
CurListener.v3flTopOrientation.y = 1.0f;
|
|
CurListener.v3flTopOrientation.z = 0.0f;
|
|
CurListener.v3flPosition.x = t3dCurCamera->Source.x;
|
|
CurListener.v3flPosition.y = t3dCurCamera->Source.y;
|
|
CurListener.v3flPosition.z = t3dCurCamera->Source.z;
|
|
return sSetListener(&CurListener);
|
|
}
|
|
|
|
/* -----------------06/04/00 11.52-------------------
|
|
* PlaySound
|
|
* --------------------------------------------------*/
|
|
bool StartSpeech(WGame &game, int32 n) {
|
|
sSound CurSound;
|
|
|
|
if (game.gameOptions.speech_on == FALSE) return true;
|
|
|
|
snprintf(CurSound.name, SOUND_NAME_LEN, "%ss%04d.wav", game.workDirs._speechDir.c_str(), n);
|
|
|
|
CurSound.lIndex = MAX_SOUNDS + n;
|
|
CurSound.dwLooped = FALSE;
|
|
CurSound.flMinDistance = 1000 * METER2UNIT;
|
|
CurSound.flMaxDistance = 1001 * METER2UNIT;
|
|
//CurSound.flMinDistance = 1*METER2UNIT;
|
|
//CurSound.flMaxDistance = 1*METER2UNIT;
|
|
CurSound.v3flPosition.x = 0;
|
|
CurSound.v3flPosition.y = 0;
|
|
CurSound.v3flPosition.z = 0;
|
|
|
|
/* Queste righe dovrebbero dare spazialita' al suono, ma visto che non funziona lo playamo diffuso
|
|
if( Anim[TimeAnim].obj )
|
|
{
|
|
CurSound.v3flPosition.x = Character[Anim[TimeAnim].obj]->Pos.x;
|
|
CurSound.v3flPosition.y = Character[Anim[TimeAnim].obj]->Pos.y;
|
|
CurSound.v3flPosition.z = Character[Anim[TimeAnim].obj]->Pos.z;
|
|
DebugLogWindow("StartSpeech(%d): %s",n,Character[Anim[TimeAnim].obj]->Body->Name);
|
|
}else
|
|
{
|
|
CurSound.v3flPosition.x = Character[CurPlayer+ocCURPLAYER]->Pos.x;
|
|
CurSound.v3flPosition.y = Character[CurPlayer+ocCURPLAYER]->Pos.y;
|
|
CurSound.v3flPosition.z = Character[CurPlayer+ocCURPLAYER]->Pos.z;
|
|
DebugLogWindow("StartSpeech(%d): %s",n,Character[CurPlayer+ocCURPLAYER]->Body->Name);
|
|
}*/
|
|
|
|
|
|
// 12 Ore
|
|
CurSound.v3flConeOrientation.x = 1;
|
|
CurSound.v3flConeOrientation.y = 0;
|
|
CurSound.v3flConeOrientation.z = 0;
|
|
|
|
CurSound.dwConeInsideAngle = 360;
|
|
CurSound.dwConeOutsideAngle = 360;
|
|
CurSound.dwConeOutsideVolume = 0;
|
|
|
|
CurSound.dwFlags = SOUND_SPEECH;
|
|
ListenerUpdate();
|
|
return (sStartSoundDiffuse(&CurSound));
|
|
// return( sStartSound( &CurSound, FALSE ) );
|
|
}
|
|
|
|
/* -----------------06/04/00 11.52-------------------
|
|
* PlaySound
|
|
* --------------------------------------------------*/
|
|
bool StartSound(WGame &game, int32 index) {
|
|
sSound CurSound;
|
|
t3dMESH *m;
|
|
Init &init = game.init;
|
|
|
|
if (game.gameOptions.sound_on == FALSE) return TRUE;
|
|
|
|
snprintf(CurSound.name, SOUND_NAME_LEN, "%s%s", game.workDirs._wavDir.c_str(), init.Sound[index].name);
|
|
CurSound.lIndex = index;
|
|
CurSound.dwLooped = (init.Sound[index].flags & SOUND_LOOP);
|
|
CurSound.flMinDistance = init.Sound[index].MinDist * METER2UNIT;
|
|
CurSound.flMaxDistance = init.Sound[index].MaxDist * METER2UNIT;
|
|
|
|
m = LinkMeshToStr(init, (char *)init.Sound[index].meshlink[0].rawArray());
|
|
if (m) {
|
|
CurSound.v3flPosition.x = m->Pos.x;
|
|
CurSound.v3flPosition.y = m->Pos.y;
|
|
CurSound.v3flPosition.z = m->Pos.z;
|
|
} else {
|
|
CurSound.v3flPosition.x = 0.f;
|
|
CurSound.v3flPosition.y = 0.f;
|
|
CurSound.v3flPosition.z = 0.f;
|
|
}
|
|
|
|
// 360 gradi
|
|
// CurSound.v3flConeOrientation.x = gCOS(Sound[index].Angle);
|
|
// CurSound.v3flConeOrientation.y = 0;
|
|
// CurSound.v3flConeOrientation.z = gSIN(Sound[index].Angle);
|
|
// 12 Ore
|
|
CurSound.v3flConeOrientation.x = (float) - gCOS((double)(init.Sound[index].Angle * 30.0f));
|
|
CurSound.v3flConeOrientation.y = 0.0f;
|
|
CurSound.v3flConeOrientation.z = (float) - gSIN((double)(init.Sound[index].Angle * 30.0f));
|
|
|
|
CurSound.dwConeInsideAngle = init.Sound[index].ConeInside;
|
|
CurSound.dwConeOutsideAngle = init.Sound[index].ConeOutside;
|
|
CurSound.dwConeOutsideVolume = init.Sound[index].ConeOutsideVolume;
|
|
|
|
CurSound.dwFlags = init.Sound[index].flags;
|
|
|
|
if (!sStartSound(&CurSound, FALSE)) return FALSE;
|
|
if (!ListenerUpdate()) return FALSE;
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
/* -----------------06/04/00 11.52-------------------
|
|
* StopSound
|
|
* --------------------------------------------------*/
|
|
bool StopSound(int32 index) {
|
|
return (sStopSound(index));
|
|
}
|
|
|
|
/* -----------------05/06/00 12.18-------------------
|
|
* StartStepSound
|
|
* --------------------------------------------------*/
|
|
bool StartStepSound(WGame &game, t3dV3F *pos, uint8 side) {
|
|
double pgon[4][2];
|
|
int32 cs, ts, index;
|
|
sSound CurSound;
|
|
Init &init = game.init;
|
|
|
|
if (game.gameOptions.sound_on == FALSE) return TRUE;
|
|
|
|
if (!pos) return FALSE;
|
|
|
|
double px = (double)pos->x;
|
|
double pz = (double)pos->z;
|
|
if ((pos == &Player->Mesh->Trasl) && (side & SOUND_STAIRS)) {
|
|
px += (double)(Player->Dir.x * HALF_STEP);
|
|
pz += (double)(Player->Dir.z * HALF_STEP);
|
|
side &= ~SOUND_STAIRS;
|
|
}
|
|
|
|
index = cs = wNULL;
|
|
for (int32 i = 0; i < MAX_SOUNDS_IN_ROOM; i++) {
|
|
if (((cs = game.getCurRoom().sounds[i]) != wNULL) && (init.Sound[cs].flags & side)) {
|
|
bool found = false;
|
|
for (int32 j = 0; j < MAX_SOUND_MESHLINKS; j++) {
|
|
if (init.Sound[cs].meshlink[j][0] == '\0')
|
|
break;
|
|
|
|
auto it = t3dCurRoom->MeshTable.begin();
|
|
for (; it != t3dCurRoom->MeshTable.end(); ++it)
|
|
if (it->name.equalsIgnoreCase((const char *)init.Sound[cs].meshlink[j].rawArray())) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((init.Sound[cs].meshlink[0][0] == '\0') || (!found)) { // se non ci sono meshlink o tutti i meshlinks sono in un'altra stanza
|
|
index = cs; // prende questo suono e continua la ricerca
|
|
continue;
|
|
}
|
|
|
|
ts = wNULL;
|
|
for (int32 j = 0; j < MAX_SOUND_MESHLINKS; j++) {
|
|
if (init.Sound[cs].meshlink[j][0] == '\0')
|
|
break;
|
|
|
|
auto it = t3dCurRoom->MeshTable.begin();
|
|
for (; it != t3dCurRoom->MeshTable.end(); ++it)
|
|
if (it->name.equalsIgnoreCase((const char *)init.Sound[cs].meshlink[j].rawArray()))
|
|
break;
|
|
|
|
if (it != t3dCurRoom->MeshTable.end()) {
|
|
auto &m = *it;
|
|
pgon[0][0] = (double)m.BBox[0].p.x;
|
|
pgon[0][1] = (double)m.BBox[0].p.z;
|
|
|
|
pgon[1][0] = (double)m.BBox[4].p.x;
|
|
pgon[1][1] = (double)m.BBox[4].p.z;
|
|
|
|
pgon[2][0] = (double)m.BBox[5].p.x;
|
|
pgon[2][1] = (double)m.BBox[5].p.z;
|
|
|
|
pgon[3][0] = (double)m.BBox[1].p.x;
|
|
pgon[3][1] = (double)m.BBox[1].p.z;
|
|
|
|
if (PointInside2DRectangle(pgon, px, pz)) {
|
|
ts = cs;
|
|
break;
|
|
} else
|
|
ts = -1;
|
|
}
|
|
}
|
|
|
|
if (ts > wNULL) {
|
|
index = ts;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (index == wNULL)
|
|
return FALSE;
|
|
|
|
snprintf(CurSound.name, SOUND_NAME_LEN, "%s%s", game.workDirs._wavDir.c_str(), init.Sound[index].name);
|
|
CurSound.lIndex = index;
|
|
CurSound.dwLooped = (init.Sound[index].flags & SOUND_LOOP);
|
|
CurSound.flMinDistance = init.Sound[index].MinDist * METER2UNIT;
|
|
CurSound.flMaxDistance = init.Sound[index].MaxDist * METER2UNIT;
|
|
if (pos != nullptr) {
|
|
CurSound.v3flPosition.x = pos->x;
|
|
CurSound.v3flPosition.y = pos->y;
|
|
CurSound.v3flPosition.z = pos->z;
|
|
}
|
|
|
|
//12 Ore
|
|
CurSound.v3flConeOrientation.x = (float) - gCOS((double)(init.Sound[index].Angle * 30));
|
|
CurSound.v3flConeOrientation.y = 0;
|
|
CurSound.v3flConeOrientation.z = (float) - gSIN((double)(init.Sound[index].Angle * 30));
|
|
|
|
CurSound.dwConeInsideAngle = init.Sound[index].ConeInside;
|
|
CurSound.dwConeOutsideAngle = init.Sound[index].ConeOutside;
|
|
CurSound.dwConeOutsideVolume = init.Sound[index].ConeOutsideVolume;
|
|
|
|
CurSound.dwFlags = init.Sound[index].flags;
|
|
|
|
if (!ListenerUpdate()) return FALSE;
|
|
if (!bDontPlaySteps) {
|
|
if (!sStartSound(&CurSound, FALSE)) return FALSE;
|
|
}
|
|
//if (!sStartInstantSound( &CurSound ) ) return FALSE;
|
|
//if (!ListenerUpdate()) return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
/* -----------------28/06/00 16.33-------------------
|
|
* Ferma tutti i midi in Play
|
|
* --------------------------------------------------*/
|
|
bool StopMusic() {
|
|
if (!mStopMusic()) return FALSE;
|
|
//if( !sStopAllSounds() ) return FALSE;
|
|
warning("STUBBED: StopMusic");
|
|
#if 0
|
|
CurPlayIndex = -1;
|
|
CurPlaySubMusic = -1;
|
|
CurMusicName[0] = 0;
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
/* -----------------28/06/00 16.33-------------------
|
|
* Ferma il MIDI con un fade di FadeOutTime ms,
|
|
* fa partire il MIDI index con un fade di FadeInTime ms.
|
|
* --------------------------------------------------*/
|
|
|
|
bool PlayMusic(int32 index, uint32 FadeOutTime, uint32 FadeInTime) {
|
|
warning("STUBBED: PlayMusic");
|
|
#if 0
|
|
char FileName[MAX_PATH];
|
|
|
|
if (GameOptions.music_on == FALSE) return TRUE;
|
|
|
|
if ((CurPlayIndex == index) && (CurPlaySubMusic == CurSubMusic)) return TRUE;
|
|
if (!strcasecmp(CurMusicName, Music[index].name[CurSubMusic])) return TRUE;
|
|
|
|
if ((Music[index].vol[CurSubMusic] != 0) &&
|
|
(Music[index].vol[CurSubMusic] != mGetAllVolume())) {
|
|
if (!mSetAllVolume((BYTE)Music[index].vol[CurSubMusic])) return FALSE;
|
|
}
|
|
snprintf(FileName, MAX_PATH, "%s%s", WmMidiDir, Music[index].name[CurSubMusic]);
|
|
if (!mLoadMusic(FileName)) {
|
|
if (CurPlayIndex == -1) return TRUE;
|
|
mInstantFadeOut(NULL, FadeOutTime);
|
|
CurPlayIndex = -1;
|
|
CurPlaySubMusic = -1;
|
|
CurMusicName[0] = '\0';
|
|
return TRUE;
|
|
}
|
|
|
|
//if (!mPlayMusic(FileName))
|
|
if (!mCrossFade(FileName, FadeOutTime, FadeInTime)) {
|
|
CurPlayIndex = -1;
|
|
CurPlaySubMusic = -1;
|
|
CurMusicName[0] = '\0';
|
|
return FALSE;
|
|
}
|
|
|
|
DebugLogFile("PM %s", FileName);
|
|
|
|
CurPlayIndex = index;
|
|
CurPlaySubMusic = CurSubMusic;
|
|
strcpy(CurMusicName, Music[index].name[CurSubMusic]);
|
|
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
bool StopSounds() {
|
|
if (!sStopAllSounds()) return false;
|
|
return true;
|
|
}
|
|
|
|
} // End of namespace Watchmaker
|