Initial commit
This commit is contained in:
948
engines/cryomni3d/versailles/data.cpp
Normal file
948
engines/cryomni3d/versailles/data.cpp
Normal file
@@ -0,0 +1,948 @@
|
||||
/* 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 "cryomni3d/datstream.h"
|
||||
|
||||
#include "cryomni3d/versailles/engine.h"
|
||||
|
||||
namespace CryOmni3D {
|
||||
namespace Versailles {
|
||||
|
||||
const uint CryOmni3DEngine_Versailles::kSpritesMapTable[] = {
|
||||
/* 0 */ 242, 240, 243, 241, 256, 93, 97, 94, 160, 98, 178, 161, 179, 196, 197, 244,
|
||||
/* 16 */ 142, 245, 143, 254, 95, 99, 113, 96, 100, 180, 114, 181, 73, 144, 74, 250,
|
||||
/* 32 */ 202, 145, 170, 251, 203, 130, 206, 171, 49, 131, 207, 115, 116, 222, 75, 85,
|
||||
/* 48 */ 76, 252, 204, 236, 86, 172, 253, 205, 237, 132, 81, 208, 173, 133, 82, 209,
|
||||
/* 64 */ 24, 101, 25, 102, 87, 198, 88, 83, 258, 199, 84, 259, 257, 260, 26, 103,
|
||||
/* 80 */ 28, 44, 27, 104, 29, 45, 200, 105, 201, 106, 162, 163, 32, 30, 46, 126,
|
||||
/* 96 */ 33, 31, 47, 5, 127, 122, 219, 227, 123, 220, 107, 69, 108, 70, 164, 165,
|
||||
/* 112 */ 89, 4, 90, 36, 34, 58, 128, 109, 37, 35, 255, 129, 110, 124, 125, 71,
|
||||
/* 128 */ 40, 72, 41, 91, 92, 59, 228, 38, 7, 60, 111, 229, 39, 149, 121, 138,
|
||||
/* 144 */ 112, 6, 139, 148, 42, 43, 232, 230, 233, 231, 140, 141, 134, 150, 135, 234,
|
||||
/* 160 */ 151, 20, 226, 261, 235, 21, 262, 166, 246, 167, 136, 50, 247, 215, 152, 137,
|
||||
/* 176 */ 51, 216, 153, 22, 117, 48, 23, 225, 118, 223, 182, 168, 248, 183, 169, 54,
|
||||
/* 192 */ 52, 249, 217, 55, 53, 218, 8, 214, 119, 120, 186, 184, 154, 61, 187, 185,
|
||||
/* 208 */ 155, 62, 56, 57, 188, 156, 65, 63, 210, 189, 157, 66, 64, 211, 19, 3,
|
||||
/* 224 */ 80, 221, 1, 263, 78, 67, 174, 212, 68, 175, 213, 190, 191, 238, 0, 239,
|
||||
/* 240 */ 224, 77, 146, 2, 147, 79, 158, 176, 159, 177, 194, 192, 195, 193, /*-1u, -1u*/
|
||||
};
|
||||
const uint CryOmni3DEngine_Versailles::kSpritesMapTableSize = ARRAYSIZE(kSpritesMapTable);
|
||||
|
||||
const LevelInitialState CryOmni3DEngine_Versailles::kLevelInitialStates[] = {
|
||||
{ 1, M_PI, 0. }, // Level 1
|
||||
{ 9, M_PI, 0. }, // Level 2
|
||||
{ 10, M_PI_2, 0. }, // Level 3
|
||||
{ 10, 0., 0. }, // Level 4
|
||||
{ 14, M_PI, 0. }, // Level 5
|
||||
{ 8, 0., 0. }, // Level 6
|
||||
{ 1, M_PI, 0. }, // Level 7
|
||||
{ 4, M_PI, 0. } // Level 8
|
||||
};
|
||||
|
||||
const FakeTransitionActionPlace CryOmni3DEngine_Versailles::kFakeTransitions[] = {
|
||||
{31141, 15},
|
||||
{31142, 16},
|
||||
{31143, 17},
|
||||
{32201, 18},
|
||||
{32202, 19},
|
||||
{32203, 20},
|
||||
{32204, 21},
|
||||
{35330, 36},
|
||||
{34172, 18},
|
||||
{0, 0} // Must be the last one
|
||||
};
|
||||
|
||||
static void readSubtitles(Common::HashMap<Common::String, Common::Array<SubtitleEntry> > &subtitles,
|
||||
DATSeekableStream *data) {
|
||||
uint16 vidsCount = data->readUint16LE();
|
||||
for (uint16 i = 0; i < vidsCount; i++) {
|
||||
Common::String vidName = data->readString16();
|
||||
Common::Array<SubtitleEntry> &entries = subtitles[vidName];
|
||||
|
||||
uint16 linesCount = data->readUint16LE();
|
||||
entries.resize(linesCount);
|
||||
for (uint16 j = 0; j < linesCount; j++) {
|
||||
SubtitleEntry &entry = entries[j];
|
||||
|
||||
entry.frameStart = data->readUint32LE();
|
||||
entry.text = data->readString16();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::loadStaticData() {
|
||||
// This should match data in devtools/create_cryomni3d_dat
|
||||
DATSeekableStream *data = getStaticData(MKTAG('V', 'R', 'S', 'L'), 1);
|
||||
|
||||
// In the dat file we have
|
||||
// file names
|
||||
data->readString16Array16(_localizedFilenames);
|
||||
assert(_localizedFilenames.size() == LocalizedFilenames::kMax);
|
||||
|
||||
// epigraph settings, bomb password
|
||||
_epigraphContent = data->readString16();
|
||||
_epigraphPassword = data->readString16();
|
||||
|
||||
if (getLanguage() == Common::JA_JPN) {
|
||||
_bombAlphabet = data->readString16().decode(Common::kWindows932);
|
||||
_bombPassword = data->readString16().decode(Common::kWindows932);
|
||||
} else {
|
||||
_bombAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ '";
|
||||
_bombPassword = data->readString16();
|
||||
}
|
||||
|
||||
// messages, paintings titles
|
||||
data->readString16Array16(_messages);
|
||||
if ((getLanguage() == Common::JA_JPN) ||
|
||||
(getLanguage() == Common::KO_KOR) ||
|
||||
(getLanguage() == Common::ZH_TWN)) {
|
||||
assert(_messages.size() == 151);
|
||||
} else {
|
||||
assert(_messages.size() == 146);
|
||||
}
|
||||
data->readString16Array16(_paintingsTitles);
|
||||
assert(_paintingsTitles.size() == 48);
|
||||
|
||||
_subtitles.clear();
|
||||
// Only CJK have subtitles, don't change dat format for other languages
|
||||
if ((getLanguage() == Common::JA_JPN) ||
|
||||
(getLanguage() == Common::KO_KOR) ||
|
||||
(getLanguage() == Common::ZH_TWN)) {
|
||||
readSubtitles(_subtitles, data);
|
||||
}
|
||||
|
||||
delete data;
|
||||
}
|
||||
|
||||
struct VideoSubSetting {
|
||||
const char *videoName;
|
||||
int16 textLeft;
|
||||
int16 textTop;
|
||||
int16 textRight;
|
||||
int16 textBottom;
|
||||
int16 drawLeft;
|
||||
int16 drawTop;
|
||||
int16 drawRight;
|
||||
int16 drawBottom;
|
||||
};
|
||||
|
||||
static const VideoSubSetting kVideoSubSettings[] = {
|
||||
{"11D_LEB", 15, 11, 190, 479, 208, 129, 562, 479},
|
||||
{"11E_HUI", 330, 9, 620, 479, 111, 109, 321, 341},
|
||||
{"11E_MAN", 403, 12, 630, 479, 134, 89, 390, 405},
|
||||
{"11E_RAC", 10, 9, 241, 479, 271, 147, 628, 479},
|
||||
{"12E_HUI", 361, 16, 618, 479, 84, 107, 330, 479},
|
||||
{"13F_HUI", 373, 12, 633, 479, 96, 88, 341, 479},
|
||||
{"21B1_HUI", 355, 13, 625, 479, 96, 104, 337, 479},
|
||||
{"21F_BON", 324, 11, 628, 479, 84, 74, 307, 479},
|
||||
{"21F_BON2", 11, 13, 298, 479, 321, 99, 536, 424},
|
||||
{"21G_CON", 12, 13, 255, 479, 273, 156, 539, 479},
|
||||
{"21G_DAU", 358, 11, 631, 479, 82, 151, 346, 479},
|
||||
{"21G_HUI", 309, 17, 626, 479, 77, 85, 304, 479},
|
||||
{"21I_LEB", 343, 10, 628, 479, 38, 125, 330, 479},
|
||||
{"21Z_ALI", 380, 13, 627, 479, 184, 106, 369, 479},
|
||||
{"21Z_BOU", 365, 13, 629, 479, 95, 65, 341, 321},
|
||||
{"21Z_MON", 12, 11, 309, 479, 336, 101, 561, 406},
|
||||
{"21Z_PR", 10, 16, 352, 471, 375, 104, 567, 400},
|
||||
{"22G_DAU", 339, 13, 629, 479, 114, 152, 326, 479},
|
||||
{"23I_LEB", 341, 15, 627, 479, 67, 140, 325, 410},
|
||||
{"24Z_BON", 253, 23, 620, 479, 58, 166, 228, 439},
|
||||
{"31J_SUI", 9, 9, 183, 475, 195, 159, 428, 479},
|
||||
{"31L1_LUL", 367, 16, 628, 477, 136, 164, 359, 472},
|
||||
{"31M_SUI", 19, 16, 212, 479, 231, 193, 395, 479},
|
||||
{"31O_SUIA", 11, 12, 175, 479, 186, 118, 490, 479},
|
||||
{"31O_SUIP", 12, 9, 277, 466, 296, 183, 380, 349},
|
||||
{"31Q_SUI", 334, 15, 626, 479, 158, 169, 313, 308},
|
||||
{"31X_BO", 332, 11, 615, 479, 89, 78, 313, 296},
|
||||
{"31X_BON", 329, 12, 618, 456, 0, 171, 243, 479},
|
||||
{"31X_LOU", 12, 9, 267, 447, 280, 88, 639, 479},
|
||||
{"31X_SEI", 352, 12, 626, 479, 102, 98, 340, 479},
|
||||
{"32J_CRO", 418, 7, 618, 477, 103, 58, 402, 438},
|
||||
{"32M_MR", 13, 11, 175, 477, 184, 113, 476, 447},
|
||||
{"32Q_MON", 375, 17, 623, 479, 248, 161, 341, 259},
|
||||
{"32Q_RAC", 294, 11, 627, 479, 110, 152, 287, 479},
|
||||
{"32Q_RAC2", 374, 13, 625, 479, 0, 101, 366, 479},
|
||||
{"31O_SUIA", 11, 12, 175, 479, 186, 118, 490, 479},
|
||||
{"41C_HUI", 345, 17, 626, 479, 69, 147, 330, 479},
|
||||
{"41X2_CRO", 13, 13, 281, 479, 305, 113, 548, 427},
|
||||
{"42C_BON", 15, 13, 347, 479, 368, 173, 525, 410},
|
||||
{"43B1_MAI", 264, 15, 625, 479, 127, 154, 249, 296},
|
||||
{"43B1_SEI", 17, 14, 369, 479, 390, 142, 639, 479},
|
||||
{"43C_CON", 312, 11, 635, 479, 21, 137, 294, 476},
|
||||
{"43C_DUR", 11, 10, 295, 479, 311, 166, 639, 479},
|
||||
{"44C_BON", 17, 12, 331, 479, 358, 181, 531, 407},
|
||||
{"4_MAI", 325, 14, 630, 479, 35, 48, 308, 363},
|
||||
{"51L_LOU", 11, 11, 616, 161, 154, 165, 400, 479},
|
||||
{"51L_PRI", 26, 19, 601, 153, 130, 167, 311, 479},
|
||||
{"51M_LEB", 41, 29, 615, 188, 49, 200, 432, 479},
|
||||
{"51M_MAN", 23, 19, 618, 179, 211, 195, 449, 479},
|
||||
{"52A4_LAC", 12, 11, 258, 479, 273, 184, 465, 383},
|
||||
{"52L_BOU", 12, 12, 190, 479, 307, 56, 592, 332},
|
||||
{"52L_LOU", 8, 13, 604, 168, 135, 171, 413, 479},
|
||||
{"52L_PRI", 20, 17, 610, 167, 336, 182, 639, 479},
|
||||
{"53N_BON", 351, 13, 629, 479, 62, 119, 343, 418},
|
||||
{"54I_BON", 343, 14, 623, 479, 72, 117, 339, 440},
|
||||
{"61_BON", 10, 7, 311, 479, 336, 101, 581, 479},
|
||||
{"61_DUC", 10, 14, 344, 473, 376, 156, 639, 479},
|
||||
{"61_LEN", 13, 9, 269, 479, 285, 63, 590, 479},
|
||||
{"62_DUC", 18, 21, 317, 479, 388, 154, 614, 479},
|
||||
};
|
||||
|
||||
void CryOmni3DEngine_Versailles::setupDialogVariables() {
|
||||
#define SET_DIAL_VARIABLE(id, var) _dialogsMan.setupVariable(id, var)
|
||||
SET_DIAL_VARIABLE(0, "JOUEUR-PARLE-HUISSIER-PETIT-LEVER");
|
||||
SET_DIAL_VARIABLE(1, "HUBAS-PARLE-LEVER1");
|
||||
SET_DIAL_VARIABLE(2, "HUBAS-PARLE-LEVER2");
|
||||
SET_DIAL_VARIABLE(3, "LEBRUN-DIT-COLBERT");
|
||||
SET_DIAL_VARIABLE(4, "LEBRUN-PARLE-ESQUISSE");
|
||||
SET_DIAL_VARIABLE(5, "JOUEUR-PARLE-HUISSIER-GRAND-LEVER");
|
||||
SET_DIAL_VARIABLE(6, "BONTEMPS-PARLE-MAINTENON");
|
||||
SET_DIAL_VARIABLE(7, "BONTEMPS-PARLE-MAINTENON2");
|
||||
SET_DIAL_VARIABLE(8, "BONTEMPS-DEMANDE-INDICE");
|
||||
SET_DIAL_VARIABLE(9, "BONTEMPS-DIT-ENQUETE");
|
||||
SET_DIAL_VARIABLE(10, "JOUEUR-CONFIE-MESSAGE-HUISSIER");
|
||||
SET_DIAL_VARIABLE(11, "JOUEUR-PARLE-HUIMA1");
|
||||
SET_DIAL_VARIABLE(12, "MONSEIGNEUR-ATTEND-ESQUISSES");
|
||||
SET_DIAL_VARIABLE(13, "MONSEIGNEUR-PREVIENT-BONTEMPS");
|
||||
SET_DIAL_VARIABLE(14, "JOUEUR-MENT-MONSEIGNEUR");
|
||||
SET_DIAL_VARIABLE(15, "JOUEUR-ECOUTE-ALIAS");
|
||||
SET_DIAL_VARIABLE(16, "JOUEUR-PARLE-HUCON");
|
||||
SET_DIAL_VARIABLE(17, "BONTEMPS-ATTEND-OBJET-GALLERIE");
|
||||
SET_DIAL_VARIABLE(18, "SUISSE-APOLLON-PARLE-CLEF");
|
||||
SET_DIAL_VARIABLE(19, "SUISSE-CABINET-DEMANDE-AUTORISATION");
|
||||
SET_DIAL_VARIABLE(20, "SUISSE-VU-AUTORISATION");
|
||||
SET_DIAL_VARIABLE(21, "CROISSY-ACCEPTE-TEXTE");
|
||||
SET_DIAL_VARIABLE(22, "JOUEUR-POSSEDE-CLEF-PETITE-PORTE");
|
||||
SET_DIAL_VARIABLE(23, "SUISSE-REFUSE-CLEF");
|
||||
SET_DIAL_VARIABLE(24, "LULLY-ATTEND-MISSION-JOUEUR");
|
||||
SET_DIAL_VARIABLE(25, "LULLY-DONNE-MISSION1-JOUEUR");
|
||||
SET_DIAL_VARIABLE(26, "LULLY-DONNE-MISSION-JOUEUR");
|
||||
SET_DIAL_VARIABLE(27, "RACINE-REPOND-ETRANGERE");
|
||||
SET_DIAL_VARIABLE(28, "RACINE-REPOND-PEUPLES");
|
||||
SET_DIAL_VARIABLE(29, "LULLY-DONNE-MISSION2-JOUEUR");
|
||||
SET_DIAL_VARIABLE(30, "LULLY-DIT-CHAT-PENDU-JOUEUR");
|
||||
SET_DIAL_VARIABLE(31, "JOUEUR-DIT-PEUPLES-LULLY");
|
||||
SET_DIAL_VARIABLE(32, "LALANDE-PARLE-BONTEMPS-SCENE3");
|
||||
SET_DIAL_VARIABLE(33, "BONTEMPS-DONNE-AUTORISATION-CURIOSITES");
|
||||
SET_DIAL_VARIABLE(34, "BONTEMPS-ATTEND-PAMPHLET");
|
||||
SET_DIAL_VARIABLE(35, "BONTEMPS-VU-PAMPHLET-DECHIFFRE-LULLY");
|
||||
SET_DIAL_VARIABLE(36, "CROISSY-DIT-INEPTIES");
|
||||
SET_DIAL_VARIABLE(37, "CROISSY-ATTEND-PAMPHLET2");
|
||||
SET_DIAL_VARIABLE(38, "CROISSY-ATTEND-MEDAILLE");
|
||||
SET_DIAL_VARIABLE(39, "CROISSY-ATTEND-PAMPHLET2-2");
|
||||
SET_DIAL_VARIABLE(40, "JOUEUR-PARLE-CROISSY1");
|
||||
SET_DIAL_VARIABLE(41, "MONSIEUR-PARLE-LALANDE1");
|
||||
SET_DIAL_VARIABLE(42, "MONSIEUR-ATTEND-FUSAIN");
|
||||
SET_DIAL_VARIABLE(43, "MONSIEUR-DONNE-SOLUTION-MEDAILLES");
|
||||
SET_DIAL_VARIABLE(44, "HUISSIER-DIT-DINER");
|
||||
SET_DIAL_VARIABLE(45, "HUISSIER-DIT-PREVENIR-BONTEMPS");
|
||||
SET_DIAL_VARIABLE(46, "JOUEUR-POSSEDE-PAMPHLET-RELIGION");
|
||||
SET_DIAL_VARIABLE(47, "JOUEUR-PARLE-BONTEMPS-SCENE4");
|
||||
SET_DIAL_VARIABLE(48, "BONTEMPS-VU-PAPIER-CROISSY");
|
||||
SET_DIAL_VARIABLE(49, "BONTEMPS-ATTEND-OBJET-SCENE4");
|
||||
SET_DIAL_VARIABLE(50, "BONTEMPS-VU-PAMPHLET-GOUVERNEMENT");
|
||||
SET_DIAL_VARIABLE(51, "JOUEUR-PARLE-VAUBAN");
|
||||
SET_DIAL_VARIABLE(52, "JOUEUR-PARLE-CODE-LOUVOIS");
|
||||
SET_DIAL_VARIABLE(53, "LALANDE-ECOUTE-LOUVOIS");
|
||||
SET_DIAL_VARIABLE(54, "JOUEUR-PARLE-LACHAIZE");
|
||||
SET_DIAL_VARIABLE(55, "JOUEUR-PARLE-LACHAIZE2");
|
||||
SET_DIAL_VARIABLE(56, "LACHAIZE-ATTEND-TEXTE");
|
||||
SET_DIAL_VARIABLE(57, "LACHAIZE-VU-PAMPHLET-RELIGION");
|
||||
SET_DIAL_VARIABLE(58, "LACHAIZE-DIT-REFORME");
|
||||
SET_DIAL_VARIABLE(59, "LACHAIZE-PARLE-BOUILLON");
|
||||
SET_DIAL_VARIABLE(60, "BOUILLON-DIT-DRAGONNADES");
|
||||
SET_DIAL_VARIABLE(61, "JOUEUR-PARLE-BOUILLON");
|
||||
SET_DIAL_VARIABLE(62, "LACHAIZE-TROUVE-ECROUELLES");
|
||||
SET_DIAL_VARIABLE(63, "LACHAIZE-DIT-DRAGONNADES");
|
||||
SET_DIAL_VARIABLE(64, "LACHAIZE-DEMANDE-TEXTE");
|
||||
SET_DIAL_VARIABLE(65, "LACHAIZE-PARLE-ARCHITECTURE");
|
||||
SET_DIAL_VARIABLE(66, "JOUEUR-DIT-DRAGONNADES");
|
||||
SET_DIAL_VARIABLE(67, "BOUILLON-ATTEND-PAMPHLET");
|
||||
SET_DIAL_VARIABLE(68, "BONTEMPS-PARLE-LUSTRE");
|
||||
SET_DIAL_VARIABLE(69, "BONTEMPS-ATTEND-MEMORANDUM2");
|
||||
SET_DIAL_VARIABLE(70, "BONTEMPS-DIT-PROMENADE");
|
||||
SET_DIAL_VARIABLE(71, "BONTEMPS-ATTEND-MEMORANDUM");
|
||||
SET_DIAL_VARIABLE(72, "LENOTRE-DIT-CALME");
|
||||
SET_DIAL_VARIABLE(73, "MAINE-DIT-APOTHICAIRIE");
|
||||
SET_DIAL_VARIABLE(74, "JOUEUR-PARLE-BONTEMPS-SCENE6");
|
||||
SET_DIAL_VARIABLE(75, "{JOUEUR-ESSAYE-OUVRIR-PORTE-CHAMBRE}");
|
||||
SET_DIAL_VARIABLE(76, "{JOUEUR-TROUVE-TITRE-ET-PAMPHLET}");
|
||||
SET_DIAL_VARIABLE(77, "{JOUEUR-ESSAYE-OUVRIR-PORTE-SALON}");
|
||||
SET_DIAL_VARIABLE(78, "{JOUEUR-MONTRE-PAPIER-ECRIT-ENCRE-SYMPATHIQUE}");
|
||||
SET_DIAL_VARIABLE(79, "{JOUEUR-MONTRE-UN-PAMPHLET}");
|
||||
SET_DIAL_VARIABLE(80, "{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}");
|
||||
SET_DIAL_VARIABLE(81, "{JOUEUR-MONTRE-PAMPHLET-ARTS}");
|
||||
SET_DIAL_VARIABLE(82, "{JOUEUR-A-MONTRE-ESQUISSES-NON-TRIEES-LEBRUN}");
|
||||
SET_DIAL_VARIABLE(83, "{JOUEUR-DONNE-ESQUISSES}");
|
||||
SET_DIAL_VARIABLE(84, "{JOUEUR-SE-DIRIGE-VERS-MONSEIGNEUR-AVEC-ESQUISSES}");
|
||||
SET_DIAL_VARIABLE(85, "{JOUEUR-PRESENTE-FAUX-CROQUIS3}");
|
||||
SET_DIAL_VARIABLE(86, "{JOUEUR-PRESENTE-FAUX-CROQUIS2}");
|
||||
SET_DIAL_VARIABLE(87, "{JOUEUR-PRESENTE-FAUX-CROQUIS}");
|
||||
SET_DIAL_VARIABLE(88, "{LE JOUEUR-PRESENTE-ESQUISSES-TRIEES}");
|
||||
SET_DIAL_VARIABLE(89, "{LE JOUEUR-PRESENTE-AUTRES-ESQUISSES-OU-ESQUISSE-NON-TRIEES}");
|
||||
SET_DIAL_VARIABLE(90, "{JOUEUR-PRESENTE-PAMPHLET-SUR-LEBRUN}");
|
||||
SET_DIAL_VARIABLE(91, "{JOUEUR-PRESENTE-TOUT-AUTRE-PAMPHLET-OU-LETTRE}");
|
||||
SET_DIAL_VARIABLE(92, "{JOUEUR-MONTRE-ESQUISSE-DETRUITE}");
|
||||
SET_DIAL_VARIABLE(93, "{JOUEUR-MONTRE-TITRE-FABLE-APPARU-SUR-ESQUISSE}");
|
||||
SET_DIAL_VARIABLE(94, "{JOUEUR-MONTRE-AUTORISATION-DE-BONTEMPS}");
|
||||
SET_DIAL_VARIABLE(95, "{LE JOUEUR-A-TENTE-OUVRIR-PETITE-PORTE}");
|
||||
SET_DIAL_VARIABLE(96, "{JOUEUR-POSSEDE-CLE}");
|
||||
SET_DIAL_VARIABLE(97, "{JOUEUR-PRESENTE-PAMPHLET-PARTITION}");
|
||||
SET_DIAL_VARIABLE(98, "{JOUEUR-MONTRE-PAMPHLET-DECHIFFRE-PAR-LULLY}");
|
||||
SET_DIAL_VARIABLE(99, "{JOUEUR-MONTRE-MEDAILLES-MONSIEUR}");
|
||||
SET_DIAL_VARIABLE(100, "{JOUEUR-MONTRE-PAMPHLET-ARCHITECTURE}");
|
||||
SET_DIAL_VARIABLE(101, "{JOUEUR-MONTRE-EPIGRAPHE-MEDAILLES}");
|
||||
SET_DIAL_VARIABLE(102, "{JOUEUR-MONTRE-TOUT-AUTRE-CHOSE}");
|
||||
SET_DIAL_VARIABLE(103, "{JOUEUR-POSSEDE-FUSAIN-MEDAILLES}");
|
||||
SET_DIAL_VARIABLE(104, "{JOUEUR-MONTRE-FUSAIN-MEDAILLES}");
|
||||
SET_DIAL_VARIABLE(105, "{JOUEUR-PRESENTE-OBJET-HUISSIER}");
|
||||
SET_DIAL_VARIABLE(106, "{JOUEUR-APPROCHE-MADAME-MAINTENON}");
|
||||
SET_DIAL_VARIABLE(107, "{JOUEUR-DONNE-REPAS}");
|
||||
SET_DIAL_VARIABLE(108, "{JOUEUR-TROUVE-PLANS-VAUBAN}");
|
||||
SET_DIAL_VARIABLE(109, "{JOUEUR-ALLER-BUREAU-LOUVOIS}");
|
||||
SET_DIAL_VARIABLE(110, "{JOUEUR-MONTRE-PAMPHLET-RELIGION}");
|
||||
SET_DIAL_VARIABLE(111, "{JOUEUR-MONTRE-PAMPHLET-GOUVERNEMENT}");
|
||||
SET_DIAL_VARIABLE(112, "{JOUEUR-MONTRE-PAPIER-CROISSY}");
|
||||
SET_DIAL_VARIABLE(113, "{JOUEUR-MONTRE-ECROUELLES}");
|
||||
SET_DIAL_VARIABLE(114, "{LACHAIZE-TIENT-TEXTE}");
|
||||
SET_DIAL_VARIABLE(115, "{JOUEUR-VU-PLANS-SALON-DIANE}");
|
||||
SET_DIAL_VARIABLE(116, "{JOUEUR-VU-MEMORANDUM-DANS-LUSTRE-DU-SALON-DE-LA-GUERRE}");
|
||||
SET_DIAL_VARIABLE(117, "{JOUEUR-VU-MEMORANDUM-DANS-LUSTRE-DU-SALON-APOLLON}");
|
||||
SET_DIAL_VARIABLE(118, "{JOUEUR-MONTRE-MEMORANDUM}");
|
||||
SET_DIAL_VARIABLE(119, "{JOUEUR-POSSEDE-CLEF-3-ET-4}");
|
||||
SET_DIAL_VARIABLE(120, "{JOUEUR-DONNE-SIROP-DE-ROSE}");
|
||||
SET_DIAL_VARIABLE(121, "{JOUEUR-DONNE-AUTRE-MEDICAMENT}");
|
||||
SET_DIAL_VARIABLE(122, "{DUC_MAIN_A_PARLE}");
|
||||
SET_DIAL_VARIABLE(123, "{LEVEL1_FINI}");
|
||||
SET_DIAL_VARIABLE(124, "{LEVEL2_FINI}");
|
||||
SET_DIAL_VARIABLE(125, "{LEVEL3_FINI}");
|
||||
SET_DIAL_VARIABLE(126, "{LEVEL4_FINI}");
|
||||
SET_DIAL_VARIABLE(127, "{LEVEL5_FINI}");
|
||||
SET_DIAL_VARIABLE(128, "{LEVEL6_FINI}");
|
||||
SET_DIAL_VARIABLE(129, "{LEVEL7_FINI}");
|
||||
SET_DIAL_VARIABLE(130, "{JOUEUR_POSSEDE_PAMPHLET_ARCHI}");
|
||||
SET_DIAL_VARIABLE(131, "{FAUSSE_ESQ_OK}");
|
||||
SET_DIAL_VARIABLE(132, "{CURRENT_GAME_TIME1}");
|
||||
SET_DIAL_VARIABLE(133, "{CURRENT_GAME_TIME2}");
|
||||
SET_DIAL_VARIABLE(134, "{CURRENT_GAME_TIME3}");
|
||||
SET_DIAL_VARIABLE(135, "{CURRENT_GAME_TIME4}");
|
||||
SET_DIAL_VARIABLE(136, "{CURRENT_GAME_TIME5}");
|
||||
SET_DIAL_VARIABLE(137, "{JOUEUR_POSSEDE_EPIGRAPHE}");
|
||||
#undef SET_DIAL_VARIABLE
|
||||
for (uint i = 0; i < ARRAYSIZE(kVideoSubSettings); i++) {
|
||||
const VideoSubSetting &vss = kVideoSubSettings[i];
|
||||
_dialogsMan.registerSubtitlesSettings(
|
||||
vss.videoName,
|
||||
DialogsManager::SubtitlesSettings(
|
||||
vss.textLeft, vss.textTop, vss.textRight, vss.textBottom,
|
||||
vss.drawLeft, vss.drawTop, vss.drawRight, vss.drawBottom));
|
||||
}
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::initPlacesStates() {
|
||||
_placeStates.resize(100);
|
||||
// Reset all the objects before configuring some
|
||||
for (Common::Array<PlaceState>::iterator it = _placeStates.begin(); it != _placeStates.end();
|
||||
it++) {
|
||||
// Useless because it's only a bunch of simple variables
|
||||
it->~PlaceState();
|
||||
new ((void *)it) PlaceState();
|
||||
}
|
||||
#define SET_PLACE_STATE(id, init, filter, docImage) _placeStates[id] = PlaceState(init, filter, docImage)
|
||||
#define FILTER_EVENT(level, place) &CryOmni3DEngine_Versailles::filterEventLevel ## level ## Place ## place
|
||||
#define INIT_PLACE(level, place) &CryOmni3DEngine_Versailles::initPlaceLevel ## level ## Place ## place
|
||||
if (_currentLevel == 1) {
|
||||
SET_PLACE_STATE(1, nullptr, FILTER_EVENT(1, 1), "VS22");
|
||||
SET_PLACE_STATE(2, nullptr, FILTER_EVENT(1, 2), "VS20");
|
||||
SET_PLACE_STATE(3, INIT_PLACE(1, 3), FILTER_EVENT(1, 3), "VS19");
|
||||
SET_PLACE_STATE(4, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(5, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(6, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(7, nullptr, nullptr, nullptr); // Filter is a leftover
|
||||
// WORKAROUND: Missing VS21
|
||||
SET_PLACE_STATE(8, nullptr, nullptr, "VS21");
|
||||
SET_PLACE_STATE(9, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(10, nullptr, nullptr, "VS31");
|
||||
SET_PLACE_STATE(11, nullptr, nullptr, "VS31");
|
||||
SET_PLACE_STATE(12, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(13, nullptr, nullptr, "VS31");
|
||||
SET_PLACE_STATE(14, nullptr, FILTER_EVENT(1, 14), nullptr);
|
||||
} else if (_currentLevel == 2) {
|
||||
SET_PLACE_STATE(1, nullptr, FILTER_EVENT(2, 1), "VS22");
|
||||
SET_PLACE_STATE(2, nullptr, FILTER_EVENT(2, 2), "VS20");
|
||||
SET_PLACE_STATE(3, nullptr, nullptr, "VS19");
|
||||
SET_PLACE_STATE(4, nullptr, nullptr, "VS18");
|
||||
SET_PLACE_STATE(5, nullptr, FILTER_EVENT(2, 5), nullptr);
|
||||
SET_PLACE_STATE(6, nullptr, nullptr, "VS19");
|
||||
SET_PLACE_STATE(7, nullptr, nullptr, nullptr);
|
||||
// WORKAROUND: Missing VS21
|
||||
SET_PLACE_STATE(8, nullptr, nullptr, "VS21");
|
||||
SET_PLACE_STATE(9, INIT_PLACE(2, 9), FILTER_EVENT(2, 9), "VS23");
|
||||
SET_PLACE_STATE(10, nullptr, nullptr, "VS31");
|
||||
SET_PLACE_STATE(11, nullptr, FILTER_EVENT(2, 11), "VS31");
|
||||
SET_PLACE_STATE(12, nullptr, FILTER_EVENT(2, 12), "VS24");
|
||||
SET_PLACE_STATE(13, nullptr, nullptr, "VS31");
|
||||
SET_PLACE_STATE(14, nullptr, FILTER_EVENT(2, 14), nullptr);
|
||||
} else if (_currentLevel == 3) {
|
||||
SET_PLACE_STATE(1, nullptr, nullptr, "VS35");
|
||||
SET_PLACE_STATE(2, nullptr, nullptr, "VS40");
|
||||
SET_PLACE_STATE(3, nullptr, FILTER_EVENT(3, 3), "VS40");
|
||||
SET_PLACE_STATE(4, nullptr, nullptr, "VS36");
|
||||
SET_PLACE_STATE(5, nullptr, nullptr, "VS36");
|
||||
SET_PLACE_STATE(6, nullptr, nullptr, "VS30");
|
||||
SET_PLACE_STATE(7, nullptr, nullptr, "VS30");
|
||||
SET_PLACE_STATE(8, nullptr, nullptr, "VS30");
|
||||
SET_PLACE_STATE(9, nullptr, nullptr, "VS39");
|
||||
SET_PLACE_STATE(10, nullptr, FILTER_EVENT(3, 10), "VS28");
|
||||
SET_PLACE_STATE(11, nullptr, nullptr, "VS28");
|
||||
SET_PLACE_STATE(12, nullptr, nullptr, "VS30");
|
||||
SET_PLACE_STATE(13, nullptr, FILTER_EVENT(3, 13), "VS27");
|
||||
SET_PLACE_STATE(14, nullptr, nullptr, "VS26");
|
||||
SET_PLACE_STATE(15, nullptr, FILTER_EVENT(3, 15), "VS25");
|
||||
SET_PLACE_STATE(16, nullptr, nullptr, "VS24");
|
||||
SET_PLACE_STATE(17, nullptr, FILTER_EVENT(3, 17), "VS25");
|
||||
SET_PLACE_STATE(18, nullptr, FILTER_EVENT(3, 18), nullptr);
|
||||
SET_PLACE_STATE(19, nullptr, FILTER_EVENT(3, 19), "VS26");
|
||||
SET_PLACE_STATE(20, nullptr, FILTER_EVENT(3_5, 20), nullptr);
|
||||
SET_PLACE_STATE(21, nullptr, nullptr, "VS28");
|
||||
SET_PLACE_STATE(22, nullptr, FILTER_EVENT(3, 22), "VS26");
|
||||
SET_PLACE_STATE(23, nullptr, FILTER_EVENT(3, 23), nullptr);
|
||||
SET_PLACE_STATE(24, nullptr, nullptr, "VS30");
|
||||
} else if (_currentLevel == 4) {
|
||||
SET_PLACE_STATE(1, nullptr, nullptr, "VS35");
|
||||
SET_PLACE_STATE(2, nullptr, nullptr, "VS40");
|
||||
SET_PLACE_STATE(3, nullptr, nullptr, "VS40");
|
||||
SET_PLACE_STATE(4, nullptr, nullptr, "VS36");
|
||||
SET_PLACE_STATE(5, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(6, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(7, nullptr, nullptr, "VS17");
|
||||
SET_PLACE_STATE(8, nullptr, nullptr, "VS17");
|
||||
SET_PLACE_STATE(9, INIT_PLACE(4, 9), nullptr, nullptr);
|
||||
SET_PLACE_STATE(10, nullptr, FILTER_EVENT(4, 10), "VS18");
|
||||
SET_PLACE_STATE(11, nullptr, nullptr, "VS20");
|
||||
SET_PLACE_STATE(12, nullptr, FILTER_EVENT(4, 12_13_14), "VS31");
|
||||
SET_PLACE_STATE(13, nullptr, FILTER_EVENT(4, 12_13_14), "VS31");
|
||||
SET_PLACE_STATE(14, nullptr, FILTER_EVENT(4, 12_13_14), "VS31");
|
||||
SET_PLACE_STATE(15, nullptr, FILTER_EVENT(4, 15), "VS36");
|
||||
SET_PLACE_STATE(16, nullptr, FILTER_EVENT(4, 16), nullptr);
|
||||
SET_PLACE_STATE(17, nullptr, FILTER_EVENT(4, 17), nullptr);
|
||||
} else if (_currentLevel == 5) {
|
||||
SET_PLACE_STATE(1, nullptr, nullptr, "VS35");
|
||||
SET_PLACE_STATE(2, nullptr, nullptr, "VS35");
|
||||
SET_PLACE_STATE(3, nullptr, nullptr, "VS36");
|
||||
SET_PLACE_STATE(4, nullptr, nullptr, "VS36");
|
||||
SET_PLACE_STATE(5, nullptr, nullptr, "VS36");
|
||||
SET_PLACE_STATE(6, INIT_PLACE(5, 6), nullptr, "VS30");
|
||||
SET_PLACE_STATE(7, nullptr, nullptr, "VS30");
|
||||
SET_PLACE_STATE(8, nullptr, nullptr, "VS30");
|
||||
SET_PLACE_STATE(9, nullptr, FILTER_EVENT(5, 9), "VS39");
|
||||
SET_PLACE_STATE(10, nullptr, nullptr, "VS28");
|
||||
SET_PLACE_STATE(11, nullptr, nullptr, "VS16");
|
||||
SET_PLACE_STATE(12, nullptr, nullptr, "VS30");
|
||||
SET_PLACE_STATE(13, nullptr, nullptr, "VS27");
|
||||
SET_PLACE_STATE(14, nullptr, FILTER_EVENT(5, 14), "VS26");
|
||||
SET_PLACE_STATE(15, nullptr, FILTER_EVENT(5, 15), "VS25");
|
||||
SET_PLACE_STATE(16, nullptr, FILTER_EVENT(5, 16), "VS24");
|
||||
SET_PLACE_STATE(17, nullptr, nullptr, "VS25");
|
||||
SET_PLACE_STATE(18, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(19, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(20, nullptr, FILTER_EVENT(3_5, 20), nullptr);
|
||||
SET_PLACE_STATE(21, nullptr, nullptr, "VS28");
|
||||
SET_PLACE_STATE(22, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(23, nullptr, FILTER_EVENT(5, 23), nullptr);
|
||||
SET_PLACE_STATE(24, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(25, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(26, nullptr, nullptr, "VS16");
|
||||
SET_PLACE_STATE(27, nullptr, FILTER_EVENT(5, 27), "VS16");
|
||||
SET_PLACE_STATE(28, nullptr, FILTER_EVENT(5, 28), nullptr);
|
||||
SET_PLACE_STATE(29, nullptr, FILTER_EVENT(5, 29), "VS24");
|
||||
SET_PLACE_STATE(30, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(31, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(32, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(33, nullptr, FILTER_EVENT(5, 33), nullptr);
|
||||
SET_PLACE_STATE(34, nullptr, FILTER_EVENT(5, 34), nullptr);
|
||||
} else if (_currentLevel == 6) {
|
||||
SET_PLACE_STATE(1, nullptr, FILTER_EVENT(6, 1), "VS34");
|
||||
SET_PLACE_STATE(2, nullptr, FILTER_EVENT(6, Orangery), "VS32");
|
||||
SET_PLACE_STATE(3, nullptr, FILTER_EVENT(6, 3), "VS32");
|
||||
SET_PLACE_STATE(4, nullptr, FILTER_EVENT(6, Orangery), "VS32");
|
||||
SET_PLACE_STATE(5, nullptr, FILTER_EVENT(6, Orangery), "VS32");
|
||||
SET_PLACE_STATE(6, nullptr, FILTER_EVENT(6, Orangery), "VS32");
|
||||
SET_PLACE_STATE(7, nullptr, FILTER_EVENT(6, Orangery), "VS32");
|
||||
SET_PLACE_STATE(8, nullptr, FILTER_EVENT(6, Orangery), "VS32");
|
||||
SET_PLACE_STATE(9, nullptr, FILTER_EVENT(6, Orangery), "VS32");
|
||||
SET_PLACE_STATE(10, nullptr, FILTER_EVENT(6, Orangery), "VS32");
|
||||
SET_PLACE_STATE(11, nullptr, FILTER_EVENT(6, Orangery), "VS32");
|
||||
SET_PLACE_STATE(12, nullptr, FILTER_EVENT(6, Orangery), "VS32");
|
||||
SET_PLACE_STATE(13, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(14, nullptr, nullptr, "VS33"); // Filter is a leftover
|
||||
SET_PLACE_STATE(15, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(16, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(17, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(18, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(19, nullptr, FILTER_EVENT(6, 19), "VS33");
|
||||
SET_PLACE_STATE(20, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(21, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(22, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(23, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(24, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(25, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(26, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(27, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(28, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(29, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(30, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(31, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(32, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(33, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(34, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(35, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(36, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(37, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(38, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(39, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(40, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(41, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(42, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(43, nullptr, nullptr, "VS33");
|
||||
SET_PLACE_STATE(44, nullptr, nullptr, "VS33");
|
||||
} else if (_currentLevel == 7) {
|
||||
SET_PLACE_STATE(1, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(2, nullptr, FILTER_EVENT(7, 2), nullptr);
|
||||
SET_PLACE_STATE(3, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(4, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(5, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(6, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(7, nullptr, nullptr, nullptr); // Filter is a leftover
|
||||
SET_PLACE_STATE(8, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(9, nullptr, FILTER_EVENT(7, 9), nullptr);
|
||||
SET_PLACE_STATE(10, nullptr, FILTER_EVENT(7, 10_11_13), "VS31");
|
||||
SET_PLACE_STATE(11, nullptr, FILTER_EVENT(7, 10_11_13), "VS31");
|
||||
SET_PLACE_STATE(12, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(13, nullptr, FILTER_EVENT(7, 10_11_13), "VS31");
|
||||
SET_PLACE_STATE(14, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(15, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(16, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(17, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(18, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(19, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(20, nullptr, FILTER_EVENT(7, 20), nullptr);
|
||||
SET_PLACE_STATE(21, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(22, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(23, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(24, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(25, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(26, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(27, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(28, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(29, nullptr, nullptr, nullptr);
|
||||
} else if (_currentLevel == 8) {
|
||||
SET_PLACE_STATE(1, nullptr, nullptr, "VS35");
|
||||
SET_PLACE_STATE(2, nullptr, nullptr, "VS40");
|
||||
SET_PLACE_STATE(3, nullptr, nullptr, "VS40");
|
||||
SET_PLACE_STATE(4, nullptr, nullptr, "VS36");
|
||||
SET_PLACE_STATE(5, nullptr, nullptr, nullptr);
|
||||
// WORKAROUND: Missing VS30
|
||||
SET_PLACE_STATE(6, nullptr, nullptr, "VS30");
|
||||
SET_PLACE_STATE(7, nullptr, nullptr, "VS30");
|
||||
SET_PLACE_STATE(8, nullptr, nullptr, "VS30");
|
||||
SET_PLACE_STATE(9, nullptr, nullptr, "VS39");
|
||||
SET_PLACE_STATE(10, nullptr, nullptr, "VS28");
|
||||
SET_PLACE_STATE(11, nullptr, nullptr, "VS16");
|
||||
SET_PLACE_STATE(12, nullptr, nullptr, "VS30");
|
||||
SET_PLACE_STATE(13, nullptr, nullptr, "VS27");
|
||||
SET_PLACE_STATE(14, nullptr, nullptr, "VS26");
|
||||
SET_PLACE_STATE(15, nullptr, nullptr, "VS25");
|
||||
SET_PLACE_STATE(16, nullptr, nullptr, "VS24");
|
||||
SET_PLACE_STATE(17, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(18, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(19, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(20, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(21, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(22, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(23, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(24, nullptr, nullptr, "VS30");
|
||||
SET_PLACE_STATE(25, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(26, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(27, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(28, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(29, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(30, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(31, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(32, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(33, nullptr, nullptr, "VS31");
|
||||
SET_PLACE_STATE(34, nullptr, nullptr, "VS31");
|
||||
SET_PLACE_STATE(35, nullptr, nullptr, "VS31");
|
||||
SET_PLACE_STATE(36, nullptr, nullptr, "VS23");
|
||||
SET_PLACE_STATE(37, nullptr, nullptr, "VS22");
|
||||
SET_PLACE_STATE(38, nullptr, nullptr, "VS20");
|
||||
// WORKAROUND: In original game VS19 is in 49 and should be in 39
|
||||
SET_PLACE_STATE(39, nullptr, nullptr, "VS19");
|
||||
SET_PLACE_STATE(40, nullptr, nullptr, "VS18");
|
||||
SET_PLACE_STATE(41, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(42, nullptr, nullptr, "VS17");
|
||||
SET_PLACE_STATE(43, nullptr, nullptr, "VS17");
|
||||
SET_PLACE_STATE(44, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(45, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(46, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(47, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(48, nullptr, nullptr, nullptr);
|
||||
SET_PLACE_STATE(49, nullptr, nullptr, nullptr);
|
||||
}
|
||||
#undef INIT_PLACE
|
||||
#undef FILTER_EVENT
|
||||
#undef SET_PLACE_STATE
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::setupLevelActionsMask() {
|
||||
_actionMasks.clear();
|
||||
#define SET_MASK(placeId, placeState, oldActionId, newActionId) _actionMasks[PlaceStateActionKey(placeId, placeState, oldActionId)] = newActionId
|
||||
if (_currentLevel == 1) {
|
||||
SET_MASK(1, 0, 11015, 0);
|
||||
SET_MASK(1, 0, 21015, 0);
|
||||
SET_MASK(1, 1, 21011, 0);
|
||||
SET_MASK(1, 1, 21012, 0);
|
||||
SET_MASK(1, 1, 21013, 0);
|
||||
SET_MASK(1, 1, 21014, 0);
|
||||
// 2, 0 is empty
|
||||
SET_MASK(2, 1, 51201, 0);
|
||||
SET_MASK(2, 1, 21202, 0);
|
||||
SET_MASK(2, 1, 21203, 0);
|
||||
SET_MASK(2, 2, 51201, 0);
|
||||
SET_MASK(2, 2, 21202, 0);
|
||||
SET_MASK(2, 2, 21203, 0);
|
||||
SET_MASK(2, 2, 11201, 1);
|
||||
SET_MASK(2, 2, 21201, 1);
|
||||
// 3, 0 is empty
|
||||
SET_MASK(3, 1, 11301, 0);
|
||||
SET_MASK(3, 1, 21301, 0);
|
||||
// 14, 0 is empty
|
||||
SET_MASK(14, 1, 31141, 0);
|
||||
} else if (_currentLevel == 2) {
|
||||
// 1, 0 is empty
|
||||
SET_MASK(1, 1, 12101, 0);
|
||||
SET_MASK(1, 1, 22101, 0);
|
||||
SET_MASK(11, 0, 12111, 0);
|
||||
SET_MASK(11, 0, 22111, 0);
|
||||
// 11, 1 is empty
|
||||
// 9, 0 is empty
|
||||
SET_MASK(9, 1, 52903, 0);
|
||||
SET_MASK(9, 1, 22903, 0);
|
||||
SET_MASK(9, 1, 52902, 12902);
|
||||
SET_MASK(9, 2, 52903, 0);
|
||||
SET_MASK(9, 2, 22903, 0);
|
||||
SET_MASK(9, 2, 52902, 0);
|
||||
SET_MASK(9, 2, 22902, 0);
|
||||
} else if (_currentLevel == 3) {
|
||||
SET_MASK(13, 0, 13131, 0);
|
||||
SET_MASK(13, 0, 23131, 0);
|
||||
SET_MASK(13, 1, 13131, 0);
|
||||
SET_MASK(13, 1, 23131, 0);
|
||||
SET_MASK(13, 1, 33130, 0);
|
||||
// 13, 2 is empty
|
||||
SET_MASK(13, 3, 33130, 0);
|
||||
// 14, 0 is empty
|
||||
SET_MASK(14, 1, 23220, 0);
|
||||
SET_MASK(15, 0, 13151, 43154);
|
||||
SET_MASK(15, 0, 23151, 0);
|
||||
// 15, 1 is empty
|
||||
SET_MASK(17, 0, 13151, 0);
|
||||
SET_MASK(17, 0, 23151, 0);
|
||||
// 17, 1 is empty
|
||||
// 16, 0 is empty
|
||||
SET_MASK(16, 1, 43160, 0);
|
||||
// 19, 0 is empty
|
||||
SET_MASK(19, 1, 43190, 0);
|
||||
SET_MASK(22, 0, 33220, 0);
|
||||
SET_MASK(22, 1, 13220, 0);
|
||||
SET_MASK(22, 1, 23220, 0);
|
||||
SET_MASK(22, 2, 13220, 0);
|
||||
SET_MASK(22, 2, 23220, 0);
|
||||
SET_MASK(22, 2, 33220, 0);
|
||||
} else if (_currentLevel == 4) {
|
||||
// 16, 0 is empty
|
||||
SET_MASK(16, 1, 14161, 0);
|
||||
SET_MASK(16, 1, 24161, 0);
|
||||
SET_MASK(16, 2, 14161, 0);
|
||||
SET_MASK(16, 2, 24161, 0);
|
||||
// 17, 0 is empty
|
||||
SET_MASK(17, 1, 34171, 0);
|
||||
// 7, 0 is empty
|
||||
SET_MASK(7, 1, 24081, 0);
|
||||
SET_MASK(7, 1, 44071, 0);
|
||||
// 8, 0 is empty
|
||||
SET_MASK(8, 1, 24081, 0);
|
||||
SET_MASK(9, 0, 54091, 0);
|
||||
SET_MASK(9, 0, 14091, 0);
|
||||
SET_MASK(9, 0, 24092, 0);
|
||||
SET_MASK(9, 0, 24091, 0);
|
||||
SET_MASK(9, 1, 14091, 54091);
|
||||
SET_MASK(9, 2, 54091, 24091);
|
||||
SET_MASK(10, 0, 14105, 0);
|
||||
SET_MASK(10, 0, 24105, 0);
|
||||
SET_MASK(10, 0, 24106, 0);
|
||||
SET_MASK(10, 0, 24107, 0);
|
||||
SET_MASK(10, 0, 54106, 0);
|
||||
//SET_MASK(10, 0, 54106, 0);
|
||||
SET_MASK(10, 1, 24106, 0);
|
||||
SET_MASK(10, 1, 24107, 0);
|
||||
SET_MASK(10, 1, 54106, 0);
|
||||
//SET_MASK(10, 1, 54106, 0);
|
||||
SET_MASK(10, 2, 14104, 24104);
|
||||
} else if (_currentLevel == 5) {
|
||||
SET_MASK(27, 0, 15270, 0);
|
||||
SET_MASK(27, 0, 25270, 0);
|
||||
SET_MASK(27, 1, 15270, 0);
|
||||
SET_MASK(27, 1, 25270, 0);
|
||||
SET_MASK(27, 1, 35270, 0);
|
||||
SET_MASK(27, 2, 35270, 0);
|
||||
SET_MASK(9, 0, 15090, 0);
|
||||
SET_MASK(9, 0, 25090, 0);
|
||||
// 9, 1 is empty
|
||||
// 13, 0 is empty
|
||||
SET_MASK(13, 1, 25130, 0);
|
||||
SET_MASK(13, 1, 25131, 0);
|
||||
SET_MASK(13, 1, 55130, 0);
|
||||
SET_MASK(13, 1, 55131, 0);
|
||||
SET_MASK(16, 0, 28, 0);
|
||||
SET_MASK(16, 0, 35162, 0);
|
||||
SET_MASK(16, 1, 28, 0);
|
||||
SET_MASK(16, 1, 35162, 0);
|
||||
SET_MASK(16, 1, 25160, 0);
|
||||
SET_MASK(16, 1, 35161, 0);
|
||||
SET_MASK(16, 2, 28, 0);
|
||||
SET_MASK(16, 2, 35162, 0);
|
||||
SET_MASK(16, 2, 25160, 0);
|
||||
SET_MASK(16, 3, 35162, 28);
|
||||
SET_MASK(16, 3, 25160, 0);
|
||||
SET_MASK(16, 3, 35161, 0);
|
||||
SET_MASK(16, 3, 35160, 0);
|
||||
SET_MASK(16, 4, 35162, 28);
|
||||
SET_MASK(16, 4, 25160, 0);
|
||||
SET_MASK(16, 5, 25160, 0);
|
||||
SET_MASK(16, 5, 35160, 0);
|
||||
SET_MASK(16, 6, 35162, 28);
|
||||
SET_MASK(16, 6, 25160, 0);
|
||||
SET_MASK(16, 6, 35161, 0);
|
||||
SET_MASK(16, 6, 35160, 0);
|
||||
// 29, 0 is empty
|
||||
SET_MASK(29, 1, 35290, 0);
|
||||
SET_MASK(15, 0, 15090, 43154);
|
||||
SET_MASK(15, 0, 25090, 0);
|
||||
// 15, 1 is empty
|
||||
SET_MASK(17, 0, 15090, 0);
|
||||
SET_MASK(17, 0, 25090, 0);
|
||||
// 17, 1 is empty
|
||||
// 33, 0 is empty
|
||||
SET_MASK(33, 1, 35330, 0);
|
||||
} else if (_currentLevel == 6) {
|
||||
// 1, 0 is empty
|
||||
SET_MASK(1, 1, 36010, 0);
|
||||
// 3, 0 is empty
|
||||
SET_MASK(3, 1, 36030, 0);
|
||||
SET_MASK(14, 0, 26140, 0);
|
||||
SET_MASK(14, 0, 16140, 0);
|
||||
// 14, 1 is empty
|
||||
SET_MASK(19, 0, 36190, 0);
|
||||
SET_MASK(19, 1, 16190, 0);
|
||||
SET_MASK(19, 1, 26190, 0);
|
||||
SET_MASK(19, 2, 36190, 0);
|
||||
SET_MASK(19, 2, 16190, 0);
|
||||
SET_MASK(19, 2, 26190, 0);
|
||||
} else if (_currentLevel == 7) {
|
||||
// 9, 0 is empty
|
||||
SET_MASK(9, 1, 37090, 0);
|
||||
} else if (_currentLevel == 8) {
|
||||
// Nothing to mask
|
||||
} else {
|
||||
error("Invalid level");
|
||||
}
|
||||
#undef SET_MASK
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::initWhoSpeaksWhere() {
|
||||
_whoSpeaksWhere.clear();
|
||||
#define SET_WHO(placeId, actionId, dialog) _whoSpeaksWhere[PlaceActionKey(placeId, actionId)] = dialog
|
||||
if (_currentLevel == 1) {
|
||||
SET_WHO(1, 11015, "13F_HUI");
|
||||
SET_WHO(1, 12101, "21F_BON");
|
||||
SET_WHO(1, 52903, "21G_DAU");
|
||||
SET_WHO(1, 52902, "21G_DAU");
|
||||
SET_WHO(2, 11201, "11E_HUI");
|
||||
SET_WHO(2, 51201, "11E_RAC");
|
||||
SET_WHO(3, 11301, "11D_LEB");
|
||||
SET_WHO(5, 12501, "21B1_HUI");
|
||||
if (currentGameTime() >= 2) {
|
||||
SET_WHO(2, 11201, "12E_HUI");
|
||||
}
|
||||
} else if (_currentLevel == 2) {
|
||||
SET_WHO(1, 12101, "21F_BON");
|
||||
SET_WHO(9, 52903, "21G_DAU");
|
||||
SET_WHO(9, 52902, "21G_DAU");
|
||||
SET_WHO(9, 12902, "22G_DAU");
|
||||
SET_WHO(9, 11201, "11E_HUI");
|
||||
SET_WHO(9, 12901, "21G_HUI");
|
||||
SET_WHO(5, 12501, "21B1_HUI");
|
||||
SET_WHO(10, 12130, "21Z_ALI");
|
||||
SET_WHO(10, 12130, "21Z_MON");
|
||||
SET_WHO(10, 12111, "24Z_BON");
|
||||
SET_WHO(11, 12130, "21Z_MON");
|
||||
SET_WHO(11, 12111, "24Z_BON");
|
||||
SET_WHO(13, 12130, "21Z_ALI");
|
||||
SET_WHO(13, 12130, "21Z_MON");
|
||||
SET_WHO(13, 12111, "24Z_BON");
|
||||
SET_WHO(12, 12121, "23I_LEB");
|
||||
SET_WHO(10, 52130, "21Z_ALI");
|
||||
SET_WHO(11, 52130, "21Z_ALI");
|
||||
SET_WHO(13, 52130, "21Z_ALI");
|
||||
SET_WHO(10, 52101, "21Z_MON");
|
||||
if (currentGameTime() >= 2) {
|
||||
SET_WHO(9, 52902, "22G_DAU");
|
||||
}
|
||||
} else if (_currentLevel == 3) {
|
||||
SET_WHO(13, 13130, "31M_SUI");
|
||||
SET_WHO(13, 13131, "32M_MR");
|
||||
SET_WHO(10, 13100, "31O_SUIA");
|
||||
SET_WHO(10, 13101, "31O_SUIP");
|
||||
SET_WHO(22, 13220, "31L1_LUL");
|
||||
SET_WHO(6, 13060, "31Q_SUI");
|
||||
SET_WHO(15, 13150, "31J_SUI");
|
||||
SET_WHO(17, 13150, "31J_SUI");
|
||||
SET_WHO(3, 13030, "31X_BON");
|
||||
SET_WHO(24, 53240, "32Q_MON");
|
||||
SET_WHO(24, 13241, "32Q_RAC2");
|
||||
SET_WHO(4, 53041, "31X_SEI");
|
||||
SET_WHO(4, 53040, "31X_LOU");
|
||||
SET_WHO(15, 13151, "32J_CRO");
|
||||
SET_WHO(17, 13151, "32J_CRO");
|
||||
} else if (_currentLevel == 4) {
|
||||
SET_WHO(10, 14104, "41C_HUI");
|
||||
SET_WHO(10, 14105, "42C_BON");
|
||||
SET_WHO(16, 14161, "41X2_CRO");
|
||||
SET_WHO(10, 54106, "43C_CON");
|
||||
SET_WHO(10, 54106, "43C_DUR");
|
||||
SET_WHO(9, 54091, "43B1_SEI");
|
||||
SET_WHO(9, 14091, "43B1_SEI");
|
||||
if (currentGameTime() >= 4) {
|
||||
SET_WHO(9, 54091, "4_MAI");
|
||||
SET_WHO(9, 14091, "4_MAI");
|
||||
}
|
||||
} else if (_currentLevel == 5) {
|
||||
SET_WHO(27, 15270, "52A4_LAC");
|
||||
SET_WHO(9, 15090, "53N_BON");
|
||||
SET_WHO(13, 55130, "51M_MAN");
|
||||
SET_WHO(13, 55131, "51M_MAN");
|
||||
SET_WHO(14, 55140, "52L_LOU");
|
||||
SET_WHO(14, 55140, "52L_PRI");
|
||||
SET_WHO(14, 15142, "52L_BOU");
|
||||
SET_WHO(13, 13130, "53M_SUI");
|
||||
if (currentGameTime() >= 4) {
|
||||
SET_WHO(9, 15090, "54I_BON");
|
||||
}
|
||||
} else if (_currentLevel == 6) {
|
||||
SET_WHO(9, 16090, "61_LEN");
|
||||
SET_WHO(19, 16190, "61_DUC");
|
||||
SET_WHO(14, 16140, "61_BON");
|
||||
if (_gameVariables[GameVariables::kMaineTalked] == 1) {
|
||||
SET_WHO(19, 16190, "62_DUC");
|
||||
}
|
||||
}
|
||||
#undef SET_WHO
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::initDocPeopleRecord() {
|
||||
_docPeopleRecord.clear();
|
||||
#define SET_INFO(actionId, record) _docPeopleRecord[actionId] = record
|
||||
SET_INFO(22501, "VC25");
|
||||
SET_INFO(22401, "VC19");
|
||||
SET_INFO(22402, "VC24");
|
||||
SET_INFO(22403, "VC24");
|
||||
SET_INFO(22404, "VC24");
|
||||
SET_INFO(22405, "VC24");
|
||||
SET_INFO(22406, "VC24");
|
||||
SET_INFO(22407, "VC24");
|
||||
SET_INFO(22408, "VC24");
|
||||
SET_INFO(21201, "VC25");
|
||||
SET_INFO(21202, "VS12");
|
||||
SET_INFO(21203, "VA13");
|
||||
SET_INFO(21011, "VC13");
|
||||
SET_INFO(21012, "VC11");
|
||||
SET_INFO(21013, "VC10");
|
||||
SET_INFO(21014, "VC18");
|
||||
SET_INFO(22901, "VC25");
|
||||
SET_INFO(21015, "VC25");
|
||||
SET_INFO(22101, "VC18");
|
||||
SET_INFO(22903, "VC12");
|
||||
SET_INFO(22902, "VC10");
|
||||
SET_INFO(22131, "VC16");
|
||||
SET_INFO(22111, "VC18");
|
||||
SET_INFO(21301, "VA12");
|
||||
SET_INFO(22121, "VA12");
|
||||
SET_INFO(22103, "VC20");
|
||||
SET_INFO(22102, "VC15");
|
||||
SET_INFO(23100, "VC23");
|
||||
SET_INFO(23101, "VC23");
|
||||
SET_INFO(23130, "VC23");
|
||||
SET_INFO(23060, "VC23");
|
||||
SET_INFO(23150, "VC23");
|
||||
SET_INFO(23220, "VA11");
|
||||
SET_INFO(23131, "VC11");
|
||||
SET_INFO(23241, "VA13");
|
||||
SET_INFO(23151, "VR12");
|
||||
SET_INFO(23030, "VC18");
|
||||
SET_INFO(23040, "VR11");
|
||||
SET_INFO(23041, "VR13");
|
||||
SET_INFO(23240, "VC15");
|
||||
SET_INFO(24104, "VC25");
|
||||
SET_INFO(24105, "VC18");
|
||||
SET_INFO(24106, "VC12");
|
||||
SET_INFO(24107, "VC19");
|
||||
SET_INFO(24102, "VC21");
|
||||
SET_INFO(24103, "VC21");
|
||||
SET_INFO(24081, "VC21");
|
||||
SET_INFO(24101, "VC24");
|
||||
SET_INFO(24092, "VC14");
|
||||
SET_INFO(24091, "VR13");
|
||||
SET_INFO(24161, "VR12");
|
||||
SET_INFO(25270, "VC26");
|
||||
SET_INFO(25261, "VC26");
|
||||
//SET_INFO(25260, nullptr); // Don't put empty records
|
||||
SET_INFO(25130, "VA12");
|
||||
SET_INFO(25131, "VS12");
|
||||
SET_INFO(25060, "VC23");
|
||||
SET_INFO(25061, "VC22");
|
||||
SET_INFO(25160, "VC23");
|
||||
SET_INFO(25140, "VR11");
|
||||
SET_INFO(25141, "VC16");
|
||||
SET_INFO(25142, "VC20");
|
||||
SET_INFO(25143, "VC15");
|
||||
SET_INFO(25145, "VC17");
|
||||
SET_INFO(25090, "VC18");
|
||||
SET_INFO(26190, "VC13");
|
||||
SET_INFO(24161, "VR12");
|
||||
SET_INFO(26090, "VS13");
|
||||
SET_INFO(26140, "VC18");
|
||||
SET_INFO(27111, "VC21");
|
||||
#undef SET_INFO
|
||||
}
|
||||
|
||||
} // End of namespace Versailles
|
||||
} // End of namespace CryOmni3D
|
||||
322
engines/cryomni3d/versailles/dialogs.cpp
Normal file
322
engines/cryomni3d/versailles/dialogs.cpp
Normal file
@@ -0,0 +1,322 @@
|
||||
/* 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 "cryomni3d/versailles/engine.h"
|
||||
|
||||
namespace CryOmni3D {
|
||||
namespace Versailles {
|
||||
|
||||
bool CryOmni3DEngine_Versailles::preprocessDialog(const Common::String &sequence) {
|
||||
if (_inventory.inInventoryByNameID(96) && _inventory.inInventoryByNameID(98)) {
|
||||
_dialogsMan["{JOUEUR-TROUVE-TITRE-ET-PAMPHLET}"] = 'Y';
|
||||
}
|
||||
if (_inventory.inInventoryByNameID(126)) {
|
||||
_dialogsMan["{JOUEUR_POSSEDE_EPIGRAPHE}"] = 'Y';
|
||||
}
|
||||
|
||||
if (_currentLevel == 1 && _currentPlaceId == 3) {
|
||||
playInGameAnimVideo("11D_LEB1");
|
||||
}
|
||||
|
||||
_dialogsMan["{JOUEUR-VU-MEMORANDUM-DANS-LUSTRE-DU-SALON-DE-LA-GUERRE}"] = 'N';
|
||||
if (_currentLevel == 5 && _gameVariables[GameVariables::kSeenMemorandum] &&
|
||||
!_inventory.inInventoryByNameID(140)) {
|
||||
_dialogsMan["{JOUEUR-VU-MEMORANDUM-DANS-LUSTRE-DU-SALON-DE-LA-GUERRE}"] = 'Y';
|
||||
}
|
||||
|
||||
if (_currentLevel == 1 && _currentPlaceId == 1 && currentGameTime() == 3 &&
|
||||
sequence.hasPrefix("13F_HUI") && _gameVariables[GameVariables::kWarnedIncomplete] == 0 &&
|
||||
_dialogsMan["{JOUEUR-TROUVE-TITRE-ET-PAMPHLET}"] == 'Y' &&
|
||||
(!_inventory.inInventoryByNameID(96) || !_inventory.inInventoryByNameID(98))) {
|
||||
displayMessageBoxWarp(18);
|
||||
_gameVariables[GameVariables::kWarnedIncomplete] = 1;
|
||||
return 0;
|
||||
}
|
||||
if (_currentLevel == 2 && _currentPlaceId == 11 && currentGameTime() == 4 &&
|
||||
sequence.hasPrefix("24Z_BON") && _gameVariables[GameVariables::kWarnedIncomplete] == 0 &&
|
||||
_dialogsMan["{JOUEUR-MONTRE-TITRE-FABLE-APPARU-SUR-ESQUISSE}"] == 'Y' &&
|
||||
(!_inventory.inInventoryByNameID(101) || !_inventory.inInventoryByNameID(103))) {
|
||||
displayMessageBoxWarp(18);
|
||||
_gameVariables[GameVariables::kWarnedIncomplete] = 1;
|
||||
return 0;
|
||||
}
|
||||
if (_currentLevel == 3 && _currentPlaceId == 10 && currentGameTime() == 3 &&
|
||||
sequence.hasPrefix("31O_SUIA") && _gameVariables[GameVariables::kWarnedIncomplete] == 0 &&
|
||||
_dialogsMan["CROISSY-ACCEPTE-TEXTE"] == 'Y' &&
|
||||
(!_inventory.inInventoryByNameID(121) || !_inventory.inInventoryByNameID(119) ||
|
||||
!_inventory.inInventoryByNameID(115) ||
|
||||
_gameVariables[GameVariables::kGotMedalsSolution] == 0)) {
|
||||
displayMessageBoxWarp(18);
|
||||
_gameVariables[GameVariables::kWarnedIncomplete] = 1;
|
||||
return 0;
|
||||
}
|
||||
if (_currentLevel == 4 && _currentPlaceId == 10 && currentGameTime() == 3 &&
|
||||
sequence.hasPrefix("42C_BON") && _gameVariables[GameVariables::kWarnedIncomplete] == 0 &&
|
||||
_dialogsMan["{JOUEUR-MONTRE-PAMPHLET-RELIGION}"] == 'Y' &&
|
||||
(!_inventory.inInventoryByNameID(127) ||
|
||||
_gameVariables[GameVariables::kUsedVaubanBlueprint1] == 0 ||
|
||||
_gameVariables[GameVariables::kUsedVaubanBlueprint2] == 0)) {
|
||||
displayMessageBoxWarp(18);
|
||||
_gameVariables[GameVariables::kWarnedIncomplete] = 1;
|
||||
return 0;
|
||||
}
|
||||
if (_currentLevel == 5 && _currentPlaceId == 10 && currentGameTime() == 3 &&
|
||||
sequence.hasPrefix("42C_BON") && _gameVariables[GameVariables::kWarnedIncomplete] == 0 &&
|
||||
_dialogsMan["{JOUEUR-MONTRE-PAMPHLET-RELIGION}"] == 'Y' &&
|
||||
(!_inventory.inInventoryByNameID(127) ||
|
||||
_gameVariables[GameVariables::kUsedVaubanBlueprint1] == 0 ||
|
||||
_gameVariables[GameVariables::kUsedVaubanBlueprint2] == 0)) {
|
||||
displayMessageBoxWarp(18);
|
||||
_gameVariables[GameVariables::kWarnedIncomplete] = 1;
|
||||
return 0;
|
||||
}
|
||||
if (_currentLevel == 6 && _currentPlaceId == 14 && currentGameTime() == 2 &&
|
||||
sequence.hasPrefix("61_BON") && _gameVariables[GameVariables::kWarnedIncomplete] == 0) {
|
||||
displayMessageBoxWarp(19);
|
||||
_gameVariables[GameVariables::kWarnedIncomplete] = 1;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::postprocessDialog(const Common::String &sequence) {
|
||||
if (_currentLevel == 1) {
|
||||
if (_dialogsMan["{LEVEL1_FINI}"] == 'Y') {
|
||||
playTransitionEndLevel(1);
|
||||
}
|
||||
} else if (_currentLevel == 2) {
|
||||
_dialogsMan["{JOUEUR-PRESENTE-FAUX-CROQUIS}"] = 'N';
|
||||
_dialogsMan["{JOUEUR-PRESENTE-FAUX-CROQUIS2}"] = 'N';
|
||||
_dialogsMan["{JOUEUR-PRESENTE-FAUX-CROQUIS3}"] = 'N';
|
||||
_dialogsMan["{LE JOUEUR-PRESENTE-AUTRES-ESQUISSES-OU-ESQUISSE-NON-TRIEES}"] = 'N';
|
||||
_dialogsMan["{LE JOUEUR-PRESENTE-ESQUISSES-TRIEES}"] = 'N';
|
||||
_dialogsMan["{JOUEUR-MONTRE-TITRE-FABLE-APPARU-SUR-ESQUISSE}"] = 'N';
|
||||
_dialogsMan["{JOUEUR-MONTRE-ESQUISSE-DETRUITE}"] = 'N';
|
||||
if (_dialogsMan["{LEVEL2_FINI}"] == 'Y') {
|
||||
playTransitionEndLevel(2);
|
||||
}
|
||||
} else if (_currentLevel == 3) {
|
||||
if (currentGameTime() == 1 && _dialogsMan["LULLY-DONNE-MISSION1-JOUEUR"] == 'Y') {
|
||||
setGameTime(2, 3);
|
||||
}
|
||||
if (!_gameVariables[GameVariables::kGotMedalsSolution] &&
|
||||
_dialogsMan["MONSIEUR-DONNE-SOLUTION-MEDAILLES"] == 'Y') {
|
||||
playInGameAnimVideo("32M_MR2");
|
||||
_gameVariables[GameVariables::kGotMedalsSolution] = 1;
|
||||
}
|
||||
if (!_gameVariables[GameVariables::kDecipherScore] &&
|
||||
_dialogsMan["LULLY-DIT-CHAT-PENDU-JOUEUR"] == 'Y') {
|
||||
_gameVariables[GameVariables::kDecipherScore] = 1;
|
||||
collectObject(118);
|
||||
setGameTime(3, 3);
|
||||
}
|
||||
if (currentGameTime() == 3 && _dialogsMan["CROISSY-ACCEPTE-TEXTE"] == 'Y') {
|
||||
setGameTime(4, 3);
|
||||
}
|
||||
if (_dialogsMan["{LEVEL3_FINI}"] == 'Y') {
|
||||
playTransitionEndLevel(3);
|
||||
}
|
||||
if (sequence == "32M_MR" && _dialogsMan["MONSIEUR-DONNE-SOLUTION-MEDAILLES"] == 'Y') {
|
||||
_dialogsMan["{JOUEUR-MONTRE-MEDAILLES-MONSIEUR}"] = 'Y';
|
||||
}
|
||||
_dialogsMan["{JOUEUR-MONTRE-PAMPHLET-ARCHITECTURE}"] = 'N';
|
||||
_dialogsMan["{JOUEUR-MONTRE-EPIGRAPHE-MEDAILLES}"] = 'N';
|
||||
_dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-CHOSE}"] = 'N';
|
||||
} else if (_currentLevel == 4) {
|
||||
if (_dialogsMan["{LEVEL4_FINI}"] == 'Y') {
|
||||
playTransitionEndLevel(4);
|
||||
}
|
||||
} else if (_currentLevel == 5) {
|
||||
if (sequence == "54I_BON" && _dialogsMan["BONTEMPS-DIT-PROMENADE"] == 'Y') {
|
||||
collectObject(141);
|
||||
playTransitionEndLevel(5);
|
||||
}
|
||||
if (sequence == "52A4_LAC" && _gameVariables[GameVariables::kStateLampoonReligion] != 3 &&
|
||||
_dialogsMan["LACHAIZE-DIT-REFORME"] == 'Y' && _dialogsMan["LACHAIZE-DIT-DRAGONNADES"] == 'Y' &&
|
||||
_dialogsMan["LACHAIZE-TROUVE-ECROUELLES"] == 'Y') {
|
||||
_inventory.removeByNameID(125);
|
||||
_gameVariables[GameVariables::kStateLampoonReligion] = 3;
|
||||
collectObject(125);
|
||||
_inventory.deselectObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::updateGameTimeDialVariables() {
|
||||
_dialogsMan["{CURRENT_GAME_TIME1}"] = 'N';
|
||||
_dialogsMan["{CURRENT_GAME_TIME2}"] = 'N';
|
||||
_dialogsMan["{CURRENT_GAME_TIME3}"] = 'N';
|
||||
_dialogsMan["{CURRENT_GAME_TIME4}"] = 'N';
|
||||
_dialogsMan["{CURRENT_GAME_TIME5}"] = 'N';
|
||||
switch (currentGameTime()) {
|
||||
case 1:
|
||||
_dialogsMan["{CURRENT_GAME_TIME1}"] = 'Y';
|
||||
break;
|
||||
case 2:
|
||||
_dialogsMan["{CURRENT_GAME_TIME2}"] = 'Y';
|
||||
break;
|
||||
case 3:
|
||||
_dialogsMan["{CURRENT_GAME_TIME3}"] = 'Y';
|
||||
break;
|
||||
case 4:
|
||||
_dialogsMan["{CURRENT_GAME_TIME4}"] = 'Y';
|
||||
break;
|
||||
case 5:
|
||||
_dialogsMan["{CURRENT_GAME_TIME5}"] = 'Y';
|
||||
break;
|
||||
default:
|
||||
error("Invalid current game time %d", currentGameTime());
|
||||
}
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::setupDialogShows() {
|
||||
_dialogsMan.registerShowCallback("(BONTEMPS-MONTRE-TROISIEME-TITRE-DE-FABLE)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowBontempsShowThird);
|
||||
_dialogsMan.registerShowCallback("(HUISSIER DONNE PAMPHLET SUR LA FAMILLE ROYALE)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowHuissierShowPamphlet);
|
||||
_dialogsMan.registerShowCallback("(MONSEIGNEUR TRIE LES ESQUISSES)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowMonseigneurSorts);
|
||||
_dialogsMan.registerShowCallback("(ANIMATION LE BRUN REGARDE LES ESQUISSES)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowLeBrunWatches);
|
||||
_dialogsMan.registerShowCallback("(OUVERTURE DES PORTES)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowDoorsOpen);
|
||||
_dialogsMan.registerShowCallback("(GARDE SUISSE DONNE CLEF PETITE PORTE)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowSwissGuardGives);
|
||||
_dialogsMan.registerShowCallback("(LULLY CORRIGE LA PARTITION.)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowLullyCorrects);
|
||||
_dialogsMan.registerShowCallback("(BONTEMPS DONNE AUTORISATION)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowBontempsGivesAuth);
|
||||
_dialogsMan.registerShowCallback("(CROISSY PART)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowCroissyLeave);
|
||||
_dialogsMan.registerShowCallback("(MAINTENON-DONNE-PAMPHLET-RELIGION)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowMaintenonGives);
|
||||
_dialogsMan.registerShowCallback("(LA CHAIZE REND TEXTE)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowLaChaizeGivesBack);
|
||||
_dialogsMan.registerShowCallback("(LA CHAIZE " "\x83" "CRIT DRAGONNADES)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowLaChaizeWrites);
|
||||
_dialogsMan.registerShowCallback("(LA CHAIZE " "\x8e" "CRIT DRAGONNADES)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowLaChaizeWrites);
|
||||
_dialogsMan.registerShowCallback("(LACHAIZE-DONNE-PAMPHLET-JOUEUR)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowLaChaizeGivesPamphlet);
|
||||
_dialogsMan.registerShowCallback("(BONTEMPS-DONNE-CLEF-DES-COMBLES)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowBontempsGivesKey);
|
||||
_dialogsMan.registerShowCallback("(LE DUC DU MAINE S'EN VA)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowDuMaineLeaves);
|
||||
_dialogsMan.registerShowCallback("(SC" "\xe9" "NE DE TRANSITION)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowTransitionScene);
|
||||
_dialogsMan.registerShowCallback("(FIN DU JEU)", &CryOmni3DEngine_Versailles::dialogShowEndOfGame);
|
||||
_dialogsMan.registerShowCallback("(LEBRUN-DONNE-FAUSSES-ESQUISSES)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowLeBrunGives);
|
||||
_dialogsMan.registerShowCallback("(LEBRUN_S_EN_VA)",
|
||||
&CryOmni3DEngine_Versailles::dialogShowLeBrunLeave);
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowBontempsShowThird() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowHuissierShowPamphlet() {
|
||||
collectObject(101);
|
||||
_inventory.deselectObject();
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowMonseigneurSorts() {
|
||||
_inventory.removeByNameID(105);
|
||||
collectObject(106);
|
||||
_gameVariables[GameVariables::kSketchState] = 2; // Sketches sorted
|
||||
_inventory.deselectObject();
|
||||
setGameTime(3, 2);
|
||||
_dialogsMan["MONSEIGNEUR-ATTEND-ESQUISSES"] = 'N';
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowLeBrunWatches() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowDoorsOpen() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowSwissGuardGives() {
|
||||
collectObject(123);
|
||||
_dialogsMan["{JOUEUR-POSSEDE-CLE}"] = 'Y';
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowLullyCorrects() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowBontempsGivesAuth() {
|
||||
collectObject(120);
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowCroissyLeave() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowMaintenonGives() {
|
||||
collectObject(125);
|
||||
_inventory.deselectObject();
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowLaChaizeGivesBack() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowLaChaizeWrites() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowLaChaizeGivesPamphlet() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowBontempsGivesKey() {
|
||||
collectObject(140);
|
||||
_inventory.deselectObject();
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowDuMaineLeaves() {
|
||||
playInGameAnimVideo("62S_DUC1");
|
||||
_inventory.removeByNameID(144);
|
||||
setPlaceState(19, 1);
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowTransitionScene() {
|
||||
playTransitionEndLevel(6);
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowEndOfGame() {
|
||||
doGameOver();
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowLeBrunGives() {
|
||||
collectObject(107);
|
||||
_inventory.deselectObject();
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::dialogShowLeBrunLeave() {
|
||||
playInGameAnimVideo("11D_LEB3");
|
||||
setGameTime(2, 1);
|
||||
}
|
||||
|
||||
} // End of namespace Versailles
|
||||
} // End of namespace CryOmni3D
|
||||
376
engines/cryomni3d/versailles/dialogs_manager.cpp
Normal file
376
engines/cryomni3d/versailles/dialogs_manager.cpp
Normal file
@@ -0,0 +1,376 @@
|
||||
/* 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 "audio/decoders/wave.h"
|
||||
#include "common/file.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "video/hnm_decoder.h"
|
||||
|
||||
#include "cryomni3d/versailles/dialogs_manager.h"
|
||||
#include "cryomni3d/versailles/engine.h"
|
||||
|
||||
namespace CryOmni3D {
|
||||
namespace Versailles {
|
||||
|
||||
Versailles_DialogsManager::Versailles_DialogsManager(CryOmni3DEngine_Versailles *engine,
|
||||
bool padAudioFileName) :
|
||||
_engine(engine), _padAudioFileName(padAudioFileName) {
|
||||
}
|
||||
|
||||
bool Versailles_DialogsManager::play(const Common::String &sequence) {
|
||||
// Prepare with specific Versailles stuff
|
||||
if (!_engine->preprocessDialog(sequence)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_engine->musicSetQuiet(true);
|
||||
|
||||
_engine->setCursor(181);
|
||||
// No need to adjust hide cursor counter, there isn't any in ScummVM
|
||||
bool cursorWasVisible = _engine->showMouse(true);
|
||||
|
||||
bool slowStop = false;
|
||||
bool didSth = DialogsManager::play(sequence, slowStop);
|
||||
|
||||
_engine->showMouse(cursorWasVisible);
|
||||
|
||||
if (didSth && slowStop) {
|
||||
if (_engine->showSubtitles()) {
|
||||
bool skip = false;
|
||||
uint end = g_system->getMillis() + 2000;
|
||||
while (!_engine->shouldAbort() && g_system->getMillis() < end && !skip) {
|
||||
g_system->updateScreen();
|
||||
g_system->delayMillis(10);
|
||||
if (_engine->pollEvents() &&
|
||||
(_engine->checkKeysPressed(1, Common::KEYCODE_SPACE) ||
|
||||
_engine->getCurrentMouseButton() == 1)) {
|
||||
skip = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_engine->postprocessDialog(sequence);
|
||||
|
||||
_engine->musicSetQuiet(false);
|
||||
|
||||
_lastImage.free();
|
||||
|
||||
_engine->waitMouseRelease();
|
||||
return didSth;
|
||||
}
|
||||
|
||||
void Versailles_DialogsManager::executeShow(const Common::String &show) {
|
||||
Common::HashMap<Common::String, ShowCallback>::iterator showIt = _shows.find(show);
|
||||
|
||||
if (showIt == _shows.end()) {
|
||||
error("Missing show %s", show.c_str());
|
||||
}
|
||||
|
||||
_lastImage.free();
|
||||
|
||||
ShowCallback cb = showIt->_value;
|
||||
(_engine->*cb)();
|
||||
}
|
||||
|
||||
void Versailles_DialogsManager::playDialog(const Common::String &video, const Common::String &sound,
|
||||
const Common::String &text, const SubtitlesSettings &settings) {
|
||||
Common::String soundFName(sound);
|
||||
if (_padAudioFileName) {
|
||||
while (soundFName.size() < 8) {
|
||||
soundFName += '_';
|
||||
}
|
||||
}
|
||||
|
||||
Common::Path videoPath(_engine->getFilePath(kFileTypeDialAnim, video));
|
||||
Common::Path soundPath(_engine->getFilePath(kFileTypeDialSound, soundFName));
|
||||
|
||||
Video::HNMDecoder *videoDecoder = new Video::HNMDecoder(g_system->getScreenFormat(), true);
|
||||
|
||||
if (!videoDecoder->loadFile(videoPath)) {
|
||||
warning("Failed to open movie file %s/%s", video.c_str(), videoPath.toString(Common::Path::kNativeSeparator).c_str());
|
||||
delete videoDecoder;
|
||||
return;
|
||||
}
|
||||
|
||||
Common::File *audioFile = new Common::File();
|
||||
if (!audioFile->open(soundPath)) {
|
||||
warning("Failed to open sound file %s/%s", sound.c_str(), soundPath.toString(Common::Path::kNativeSeparator).c_str());
|
||||
delete videoDecoder;
|
||||
delete audioFile;
|
||||
return;
|
||||
}
|
||||
|
||||
Audio::SeekableAudioStream *audioDecoder = Audio::makeWAVStream(audioFile, DisposeAfterUse::YES);
|
||||
// We lost ownership of the audioFile just set it to nullptr and don't use it
|
||||
audioFile = nullptr;
|
||||
|
||||
if (!audioDecoder) {
|
||||
delete videoDecoder;
|
||||
return;
|
||||
}
|
||||
|
||||
_engine->showMouse(false);
|
||||
|
||||
uint16 width = videoDecoder->getWidth();
|
||||
uint16 height = videoDecoder->getHeight();
|
||||
|
||||
// Preload first frame to draw subtitles from it
|
||||
const Graphics::Surface *firstFrame = videoDecoder->decodeNextFrame();
|
||||
assert(firstFrame != nullptr);
|
||||
|
||||
if (videoDecoder->hasDirtyPalette()) {
|
||||
const byte *palette = videoDecoder->getPalette();
|
||||
_engine->setupPalette(palette, 0, 256);
|
||||
}
|
||||
|
||||
FontManager &fontManager = _engine->_fontManager;
|
||||
_lastImage.create(firstFrame->w, firstFrame->h, firstFrame->format);
|
||||
_lastImage.blitFrom(*firstFrame);
|
||||
|
||||
fontManager.setCurrentFont(7);
|
||||
fontManager.setTransparentBackground(true);
|
||||
fontManager.setForeColor(241);
|
||||
fontManager.setLineHeight(22);
|
||||
fontManager.setSpaceWidth(2);
|
||||
fontManager.setCharSpacing(1);
|
||||
|
||||
if (_engine->showSubtitles()) {
|
||||
Common::Rect block = settings.textRect;
|
||||
|
||||
uint lines = fontManager.getLinesCount(text, block.width() - 8);
|
||||
if (lines == 0) {
|
||||
lines = 5;
|
||||
}
|
||||
uint blockHeight = fontManager.lineHeight() * lines + 6;
|
||||
block.setHeight(blockHeight);
|
||||
|
||||
if (block.bottom >= 480) {
|
||||
block.bottom = 470;
|
||||
warning("Dialog text is really too long");
|
||||
}
|
||||
|
||||
// Make only the block area translucent inplace
|
||||
Graphics::Surface blockSurface = _lastImage.getSubArea(block);
|
||||
_engine->makeTranslucent(blockSurface, blockSurface);
|
||||
|
||||
fontManager.setSurface(&_lastImage);
|
||||
block.grow(-4);
|
||||
fontManager.setupBlock(block);
|
||||
fontManager.displayBlockText(text);
|
||||
}
|
||||
|
||||
g_system->copyRectToScreen(_lastImage.getPixels(), _lastImage.pitch, 0, 0, width, height);
|
||||
g_system->updateScreen();
|
||||
|
||||
const Common::Rect &drawRect = settings.drawRect;
|
||||
|
||||
if (audioDecoder->getLength() == 0) {
|
||||
// Empty wave file
|
||||
delete audioDecoder;
|
||||
|
||||
uint duration = 100 * text.size();
|
||||
if (duration < 1000) {
|
||||
duration = 1000;
|
||||
}
|
||||
|
||||
bool skipWait = false;
|
||||
uint end = g_system->getMillis() + duration;
|
||||
while (!_engine->shouldAbort() && g_system->getMillis() < end && !skipWait) {
|
||||
g_system->updateScreen();
|
||||
g_system->delayMillis(10);
|
||||
if (_engine->pollEvents() && _engine->checkKeysPressed(1, Common::KEYCODE_SPACE)) {
|
||||
skipWait = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Let start the show!
|
||||
videoDecoder->start();
|
||||
|
||||
Audio::SoundHandle audioHandle;
|
||||
_engine->_mixer->playStream(Audio::Mixer::kSpeechSoundType, &audioHandle, audioDecoder);
|
||||
// We lost ownership of the audioDecoder just set it to nullptr and don't use it
|
||||
audioDecoder = nullptr;
|
||||
|
||||
bool skipVideo = false;
|
||||
while (!_engine->shouldAbort() && _engine->_mixer->isSoundHandleActive(audioHandle) && !skipVideo) {
|
||||
if (_engine->pollEvents() && _engine->checkKeysPressed(1, Common::KEYCODE_SPACE)) {
|
||||
skipVideo = true;
|
||||
}
|
||||
|
||||
if (videoDecoder->needsUpdate()) {
|
||||
const Graphics::Surface *frame = videoDecoder->decodeNextFrame();
|
||||
|
||||
if (frame) {
|
||||
if (videoDecoder->hasDirtyPalette()) {
|
||||
const byte *palette = videoDecoder->getPalette();
|
||||
_engine->setupPalette(palette, 0, 256);
|
||||
}
|
||||
|
||||
// Only refresh the moving part of the animation
|
||||
const Graphics::Surface subFrame = frame->getSubArea(drawRect);
|
||||
g_system->copyRectToScreen(subFrame.getPixels(), subFrame.pitch, drawRect.left, drawRect.top,
|
||||
subFrame.w, subFrame.h);
|
||||
}
|
||||
}
|
||||
g_system->updateScreen();
|
||||
g_system->delayMillis(10);
|
||||
}
|
||||
_engine->_mixer->stopHandle(audioHandle);
|
||||
}
|
||||
|
||||
// It's intentional that _lastImage is set with the first video image
|
||||
|
||||
delete videoDecoder;
|
||||
_engine->showMouse(true);
|
||||
}
|
||||
|
||||
void Versailles_DialogsManager::displayMessage(const Common::String &text) {
|
||||
_engine->displayMessageBoxWarp(text);
|
||||
}
|
||||
|
||||
uint Versailles_DialogsManager::askPlayerQuestions(const Common::String &video,
|
||||
const Common::StringArray &questions) {
|
||||
if (_lastImage.empty()) {
|
||||
loadFrame(video);
|
||||
}
|
||||
|
||||
if (questions.size() == 0 || questions.size() > 5) {
|
||||
return uint(-1);
|
||||
}
|
||||
|
||||
FontManager &fontManager = _engine->_fontManager;
|
||||
fontManager.setCurrentFont(7);
|
||||
fontManager.setTransparentBackground(true);
|
||||
fontManager.setLineHeight(18);
|
||||
fontManager.setSpaceWidth(2);
|
||||
fontManager.setSurface(&_lastImage);
|
||||
|
||||
int16 tops[5];
|
||||
int16 bottoms[5];
|
||||
int16 currentHeight = 0;
|
||||
uint questionId = 0;
|
||||
for (Common::StringArray::const_iterator it = questions.begin(); it != questions.end();
|
||||
it++, questionId++) {
|
||||
tops[questionId] = currentHeight;
|
||||
uint lines = fontManager.getLinesCount(*it, 598);
|
||||
if (lines == 0) {
|
||||
lines = 1;
|
||||
}
|
||||
currentHeight += 18 * lines;
|
||||
bottoms[questionId] = currentHeight;
|
||||
}
|
||||
|
||||
int offsetY = 480 - (bottoms[questions.size() - 1] - tops[0]);
|
||||
if (offsetY > 402) {
|
||||
offsetY = 402;
|
||||
} else if (offsetY < 2) {
|
||||
offsetY = 2;
|
||||
}
|
||||
|
||||
for (questionId = 0; questionId < questions.size(); questionId++) {
|
||||
tops[questionId] += offsetY;
|
||||
bottoms[questionId] += offsetY;
|
||||
}
|
||||
|
||||
_engine->setCursor(181);
|
||||
Graphics::Surface alphaSurface = _lastImage.getSubArea(Common::Rect(0, offsetY - 2, 640, 480));
|
||||
_engine->makeTranslucent(alphaSurface, alphaSurface);
|
||||
|
||||
bool finished = false;
|
||||
bool update = true;
|
||||
uint selectedQuestion = uint(-1);
|
||||
while (!finished) {
|
||||
if (update) {
|
||||
update = false;
|
||||
questionId = 0;
|
||||
for (Common::StringArray::const_iterator it = questions.begin(); it != questions.end();
|
||||
it++, questionId++) {
|
||||
fontManager.setForeColor(selectedQuestion == questionId ? 241 : 245);
|
||||
fontManager.setupBlock(Common::Rect(10, tops[questionId], 608, bottoms[questionId]));
|
||||
fontManager.displayBlockText(*it);
|
||||
}
|
||||
g_system->copyRectToScreen(_lastImage.getPixels(), _lastImage.pitch, 0, 0, _lastImage.w,
|
||||
_lastImage.h);
|
||||
}
|
||||
g_system->updateScreen();
|
||||
g_system->delayMillis(10);
|
||||
|
||||
if (_engine->pollEvents()) {
|
||||
_engine->clearKeys();
|
||||
if (_engine->shouldAbort()) {
|
||||
finished = true;
|
||||
selectedQuestion = uint(-1);
|
||||
break;
|
||||
}
|
||||
Common::Point mousePos = _engine->getMousePos();
|
||||
if (_engine->getDragStatus() == kDragStatus_Finished && selectedQuestion != uint(-1)) {
|
||||
finished = true;
|
||||
} else if (mousePos.x >= 608 || mousePos.y < offsetY) {
|
||||
if (selectedQuestion != uint(-1)) {
|
||||
selectedQuestion = uint(-1);
|
||||
update = true;
|
||||
}
|
||||
} else {
|
||||
for (questionId = 0; questionId < questions.size(); questionId++) {
|
||||
if (mousePos.y > tops[questionId] && mousePos.y < bottoms[questionId]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (questionId < questions.size()) {
|
||||
if (selectedQuestion != questionId) {
|
||||
selectedQuestion = questionId;
|
||||
update = true;
|
||||
}
|
||||
} else {
|
||||
selectedQuestion = uint(-1);
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return selectedQuestion;
|
||||
}
|
||||
|
||||
void Versailles_DialogsManager::loadFrame(const Common::String &video) {
|
||||
Common::Path videoPath(_engine->getFilePath(kFileTypeDialAnim, video));
|
||||
|
||||
Video::HNMDecoder videoDecoder(g_system->getScreenFormat());
|
||||
|
||||
if (!videoDecoder.loadFile(videoPath)) {
|
||||
warning("Failed to open movie file %s/%s", video.c_str(), videoPath.toString(Common::Path::kNativeSeparator).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Preload first frame to draw questions on it
|
||||
const Graphics::Surface *firstFrame = videoDecoder.decodeNextFrame();
|
||||
_lastImage.create(firstFrame->w, firstFrame->h, firstFrame->format);
|
||||
_lastImage.blitFrom(*firstFrame);
|
||||
|
||||
if (videoDecoder.hasDirtyPalette()) {
|
||||
const byte *palette = videoDecoder.getPalette();
|
||||
_engine->setupPalette(palette, 0, 256);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Versailles
|
||||
} // End of namespace CryOmni3D
|
||||
68
engines/cryomni3d/versailles/dialogs_manager.h
Normal file
68
engines/cryomni3d/versailles/dialogs_manager.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRYOMNI3D_VERSAILLES_DIALOGS_MANAGER_H
|
||||
#define CRYOMNI3D_VERSAILLES_DIALOGS_MANAGER_H
|
||||
|
||||
#include "common/hashmap.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
#include "cryomni3d/dialogs_manager.h"
|
||||
#include "cryomni3d/font_manager.h"
|
||||
|
||||
namespace CryOmni3D {
|
||||
namespace Versailles {
|
||||
|
||||
class CryOmni3DEngine_Versailles;
|
||||
typedef void (CryOmni3DEngine_Versailles::*ShowCallback)();
|
||||
|
||||
class Versailles_DialogsManager : public DialogsManager {
|
||||
public:
|
||||
Versailles_DialogsManager(CryOmni3DEngine_Versailles *engine, bool padAudioFileName);
|
||||
|
||||
// This overload will hide the base one and this is what we want
|
||||
bool play(const Common::String &sequence);
|
||||
|
||||
void registerShowCallback(const Common::String &showName, ShowCallback callback) { _shows[showName] = callback; }
|
||||
|
||||
protected:
|
||||
void executeShow(const Common::String &show) override;
|
||||
void playDialog(const Common::String &video, const Common::String &sound,
|
||||
const Common::String &text, const SubtitlesSettings &settings) override;
|
||||
void displayMessage(const Common::String &text) override;
|
||||
uint askPlayerQuestions(const Common::String &video,
|
||||
const Common::StringArray &questions) override;
|
||||
|
||||
private:
|
||||
CryOmni3DEngine_Versailles *_engine;
|
||||
Common::HashMap<Common::String, ShowCallback> _shows;
|
||||
bool _padAudioFileName;
|
||||
|
||||
void loadFrame(const Common::String &video);
|
||||
|
||||
Graphics::ManagedSurface _lastImage;
|
||||
};
|
||||
|
||||
} // End of namespace Versailles
|
||||
} // End of namespace CryOmni3D
|
||||
|
||||
#endif
|
||||
2124
engines/cryomni3d/versailles/documentation.cpp
Normal file
2124
engines/cryomni3d/versailles/documentation.cpp
Normal file
File diff suppressed because it is too large
Load Diff
146
engines/cryomni3d/versailles/documentation.h
Normal file
146
engines/cryomni3d/versailles/documentation.h
Normal file
@@ -0,0 +1,146 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRYOMNI3D_VERSAILLES_DOCUMENTATION_H
|
||||
#define CRYOMNI3D_VERSAILLES_DOCUMENTATION_H
|
||||
|
||||
#include "common/hashmap.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/str-array.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
namespace CryOmni3D {
|
||||
class FontManager;
|
||||
class MouseBoxes;
|
||||
class Sprites;
|
||||
|
||||
namespace Versailles {
|
||||
class CryOmni3DEngine_Versailles;
|
||||
|
||||
class Versailles_Documentation {
|
||||
public:
|
||||
Versailles_Documentation() : _engine(nullptr), _fontManager(nullptr), _sprites(nullptr),
|
||||
_messages(nullptr), _multilineAttributes(false), _linksData(nullptr), _linksSize(0),
|
||||
_currentInTimeline(false), _currentMapLayout(false), _currentHasMap(false) { }
|
||||
~Versailles_Documentation() { delete [] _linksData; }
|
||||
|
||||
void init(const Sprites *sprites, FontManager *fontManager, const Common::StringArray *messages,
|
||||
CryOmni3DEngine_Versailles *engine, const Common::Path &allDocsFilePath,
|
||||
const Common::Path &linksDocsFilePath);
|
||||
void handleDocArea();
|
||||
void handleDocInGame(const Common::String &record);
|
||||
|
||||
private:
|
||||
Common::String docAreaHandleSummary();
|
||||
Common::String docAreaHandleTimeline();
|
||||
Common::String docAreaHandleGeneralMap();
|
||||
Common::String docAreaHandleCastleMap();
|
||||
uint docAreaHandleRecords(const Common::String &record);
|
||||
|
||||
void docAreaPrepareNavigation();
|
||||
void docAreaPrepareRecord(Graphics::ManagedSurface &surface, MouseBoxes &boxes);
|
||||
uint docAreaHandleRecord(Graphics::ManagedSurface &surface, MouseBoxes &boxes,
|
||||
Common::String &nextRecord);
|
||||
|
||||
void inGamePrepareRecord(Graphics::ManagedSurface &surface, MouseBoxes &boxes);
|
||||
uint inGameHandleRecord(Graphics::ManagedSurface &surface, MouseBoxes &boxes,
|
||||
Common::String &nextRecord);
|
||||
|
||||
void setupRecordBoxes(bool inDocArea, MouseBoxes &boxes);
|
||||
void setupTimelineBoxes(MouseBoxes &boxes);
|
||||
void drawRecordData(Graphics::ManagedSurface &surface,
|
||||
const Common::String &text, const Common::String &title,
|
||||
const Common::String &subtitle, const Common::String &caption);
|
||||
void drawRecordBoxes(Graphics::ManagedSurface &surface, bool inDocArea, MouseBoxes &boxes);
|
||||
|
||||
uint handlePopupMenu(const Graphics::ManagedSurface &surface,
|
||||
const Common::Point &anchor, bool rightAligned, uint itemHeight,
|
||||
const Common::StringArray &items);
|
||||
|
||||
struct RecordInfo {
|
||||
uint id;
|
||||
uint position;
|
||||
uint size;
|
||||
};
|
||||
|
||||
struct LinkInfo {
|
||||
Common::String record;
|
||||
Common::String title;
|
||||
};
|
||||
|
||||
struct TimelineEntry {
|
||||
char year[8];
|
||||
uint x;
|
||||
uint y;
|
||||
};
|
||||
static const TimelineEntry kTimelineEntries[];
|
||||
|
||||
char *getDocPartAddress(char *start, char *end, const char *patterns[]);
|
||||
const char *getDocTextAddress(char *start, char *end);
|
||||
const char *getRecordTitle(char *start, char *end);
|
||||
const char *getRecordSubtitle(char *start, char *end);
|
||||
const char *getRecordCaption(char *start, char *end);
|
||||
void getRecordHyperlinks(char *start, char *end, Common::StringArray &hyperlinks);
|
||||
|
||||
Common::String getRecordTitle(const Common::String &record);
|
||||
Common::String getRecordData(const Common::String &record, Common::String &title,
|
||||
Common::String &subtitle, Common::String &caption,
|
||||
Common::StringArray &hyperlinks);
|
||||
void convertHyperlinks(const Common::StringArray &hyperlinks, Common::Array<LinkInfo> &links);
|
||||
|
||||
void loadLinksFile();
|
||||
void getLinks(const Common::String &record, Common::Array<LinkInfo> &links);
|
||||
|
||||
Common::Path _allDocsFilePath;
|
||||
Common::Path _linksDocsFilePath;
|
||||
|
||||
static const uint kPopupMenuMargin = 5;
|
||||
|
||||
CryOmni3DEngine_Versailles *_engine;
|
||||
FontManager *_fontManager;
|
||||
const Sprites *_sprites;
|
||||
const Common::StringArray *_messages;
|
||||
|
||||
bool _multilineAttributes;
|
||||
|
||||
Common::StringArray _recordsOrdered;
|
||||
Common::HashMap<Common::String, RecordInfo> _records;
|
||||
char *_linksData;
|
||||
uint _linksSize;
|
||||
|
||||
Common::Array<LinkInfo> _allLinks;
|
||||
|
||||
Common::StringArray _visitTrace;
|
||||
Common::String _currentRecord;
|
||||
Common::String _categoryStartRecord;
|
||||
Common::String _categoryEndRecord;
|
||||
Common::String _categoryTitle;
|
||||
Common::Array<LinkInfo> _currentLinks;
|
||||
bool _currentInTimeline;
|
||||
bool _currentMapLayout;
|
||||
bool _currentHasMap;
|
||||
};
|
||||
|
||||
} // End of namespace Versailles
|
||||
} // End of namespace CryOmni3D
|
||||
|
||||
#endif
|
||||
1961
engines/cryomni3d/versailles/engine.cpp
Normal file
1961
engines/cryomni3d/versailles/engine.cpp
Normal file
File diff suppressed because it is too large
Load Diff
687
engines/cryomni3d/versailles/engine.h
Normal file
687
engines/cryomni3d/versailles/engine.h
Normal file
@@ -0,0 +1,687 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRYOMNI3D_VERSAILLES_ENGINE_H
|
||||
#define CRYOMNI3D_VERSAILLES_ENGINE_H
|
||||
|
||||
#include "common/events.h"
|
||||
#include "common/random.h"
|
||||
#include "common/array.h"
|
||||
#include "common/hashmap.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/str.h"
|
||||
|
||||
#include "cryomni3d/cryomni3d.h"
|
||||
#include "cryomni3d/omni3d.h"
|
||||
#include "cryomni3d/sprites.h"
|
||||
#include "cryomni3d/wam_parser.h"
|
||||
|
||||
#include "cryomni3d/versailles/documentation.h"
|
||||
#include "cryomni3d/versailles/toolbar.h"
|
||||
#include "cryomni3d/versailles/dialogs_manager.h"
|
||||
|
||||
namespace Graphics {
|
||||
class ManagedSurface;
|
||||
struct Surface;
|
||||
}
|
||||
|
||||
namespace CryOmni3D {
|
||||
struct FixedImageConfiguration;
|
||||
class ZonFixedImage;
|
||||
}
|
||||
|
||||
namespace CryOmni3D {
|
||||
namespace Versailles {
|
||||
struct PlaceStateActionKey {
|
||||
uint placeId;
|
||||
uint placeState;
|
||||
uint actionId;
|
||||
PlaceStateActionKey(uint placeId_, uint placeState_, uint actionId_) :
|
||||
placeId(placeId_), placeState(placeState_), actionId(actionId_) {}
|
||||
|
||||
bool operator==(const PlaceStateActionKey &other) const {
|
||||
return other.placeId == placeId && other.placeState == placeState && other.actionId == actionId;
|
||||
}
|
||||
};
|
||||
|
||||
struct PlaceActionKey {
|
||||
uint placeId;
|
||||
uint actionId;
|
||||
PlaceActionKey(uint placeId_, uint actionId_) :
|
||||
placeId(placeId_), actionId(actionId_) {}
|
||||
|
||||
bool operator==(const PlaceActionKey &other) const {
|
||||
return other.placeId == placeId && other.actionId == actionId;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace Common {
|
||||
template<>
|
||||
struct Hash<CryOmni3D::Versailles::PlaceStateActionKey> {
|
||||
uint operator()(const CryOmni3D::Versailles::PlaceStateActionKey &k) const {
|
||||
// placeState shouldn't be greater than 8 and placeId shouldn't be greater than 100
|
||||
// originalActionId shouldn't be greater than 65536
|
||||
return (k.placeId << 24 | k.placeState << 16) ^ k.actionId;
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct Hash<CryOmni3D::Versailles::PlaceActionKey> {
|
||||
uint operator()(const CryOmni3D::Versailles::PlaceActionKey &k) const {
|
||||
// placeId shouldn't be greater than 100
|
||||
// originalActionId shouldn't be greater than 65536
|
||||
return (k.placeId << 16) ^ k.actionId;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace CryOmni3D {
|
||||
namespace Versailles {
|
||||
|
||||
class CryOmni3DEngine_Versailles;
|
||||
|
||||
enum AbortCommand {
|
||||
kAbortNoAbort = 0,
|
||||
kAbortQuit = 1,
|
||||
kAbortLoadGame = 2,
|
||||
kAbortNewGame = 3,
|
||||
kAbortNextLevel = 5,
|
||||
kAbortFinished = 6,
|
||||
kAbortGameOver = 7
|
||||
};
|
||||
|
||||
struct GameVariables {
|
||||
enum Var {
|
||||
kCollectScore = 0, // 0
|
||||
kUnlockHiddenDoor,
|
||||
kAlreadyWent3_19,
|
||||
kMedalsDrawerStatus,
|
||||
kCurrentTime,
|
||||
kGotMedalsSolution,
|
||||
kCabinetDrawerStatus,
|
||||
kDecipherScore,
|
||||
kCollectLampoonArchitecture,
|
||||
kGotRevealedPaper,
|
||||
kCollectKey, // 10
|
||||
kCollectPortfolio,
|
||||
kSketchState,
|
||||
kFakeSketchChatState,
|
||||
kCollectFood,
|
||||
kCollectQuill,
|
||||
kStateLampoonReligion,
|
||||
kCollectSmallKey3,
|
||||
kCollectEngraving,
|
||||
kCollectCord,
|
||||
kCollectVaubanBlueprint1, // 20
|
||||
kCollectVaubanBlueprint2,
|
||||
kLadderState,
|
||||
kOpenedCurtain,
|
||||
kLoweredChandelier,
|
||||
kCombedOrangeTree,
|
||||
kMaineTalked,
|
||||
kUsedLitCandle,
|
||||
kBombState,
|
||||
kInkSpilled,
|
||||
kCollectedPaperOnTable, // 30
|
||||
kSafeUnlocked,
|
||||
//kUselessVar,
|
||||
kCollectedPaperInTrunk = 33,
|
||||
kBrushColor,
|
||||
kUsedScissors,
|
||||
kUnlockedAttic,
|
||||
kHasPlayedLebrun,
|
||||
kWarnedIncomplete,
|
||||
kUsedVaubanBlueprint1,
|
||||
kUsedVaubanBlueprint2, // 40
|
||||
kSeenMemorandum,
|
||||
kCollectScissors,
|
||||
kSavedCountdown,
|
||||
kMax
|
||||
};
|
||||
};
|
||||
|
||||
// For random sounds we set a constant ID and avoid to use it elsewhere
|
||||
struct SoundIds {
|
||||
enum {
|
||||
kOrgue = 0,
|
||||
kLeb001,
|
||||
kMax
|
||||
};
|
||||
};
|
||||
|
||||
struct LocalizedFilenames {
|
||||
enum {
|
||||
kDialogs = 0,
|
||||
kAllDocs,
|
||||
kLinksDocs,
|
||||
kCredits,
|
||||
kLeb001,
|
||||
kMax
|
||||
};
|
||||
};
|
||||
|
||||
enum FileType {
|
||||
kFileTypeAnimacti,
|
||||
kFileTypeDocBg,
|
||||
kFileTypeDialAnim,
|
||||
kFileTypeDialSound,
|
||||
kFileTypeFont,
|
||||
kFileTypeGTO,
|
||||
kFileTypeFixedImg,
|
||||
kFileTypeMenu,
|
||||
kFileTypeMusic,
|
||||
kFileTypeObject,
|
||||
kFileTypeSaveGameVisit,
|
||||
kFileTypeTransScene,
|
||||
kFileTypeTransSceneI,
|
||||
kFileTypeSound,
|
||||
kFileTypeSprite,
|
||||
kFileTypeSpriteBmp,
|
||||
kFileTypeText,
|
||||
kFileTypeWAM,
|
||||
kFileTypeWarpCyclo,
|
||||
kFileTypeWarpHNM
|
||||
};
|
||||
|
||||
struct PlaceState {
|
||||
typedef void (CryOmni3DEngine_Versailles::*InitFunc)();
|
||||
typedef bool (CryOmni3DEngine_Versailles::*FilterEventFunc)(uint *event);
|
||||
|
||||
PlaceState() : initPlace(nullptr), filterEvent(nullptr), docImage(nullptr), state(0) {}
|
||||
PlaceState(InitFunc initPlace_, FilterEventFunc filterEvent_, const char *docImage_) :
|
||||
initPlace(initPlace_), filterEvent(filterEvent_), docImage(docImage_), state(0) {}
|
||||
|
||||
InitFunc initPlace;
|
||||
FilterEventFunc filterEvent;
|
||||
const char *docImage;
|
||||
uint state;
|
||||
};
|
||||
|
||||
struct LevelInitialState {
|
||||
uint placeId;
|
||||
double alpha;
|
||||
double beta;
|
||||
};
|
||||
|
||||
struct FakeTransitionActionPlace {
|
||||
uint actionId;
|
||||
uint placeId;
|
||||
};
|
||||
|
||||
typedef void (CryOmni3DEngine_Versailles::*FixedImgCallback)(ZonFixedImage *);
|
||||
|
||||
struct MsgBoxParameters {
|
||||
int font;
|
||||
byte foreColor;
|
||||
uint lineHeight;
|
||||
uint spaceWidth;
|
||||
uint charSpacing;
|
||||
uint initialWidth;
|
||||
uint incrementWidth;
|
||||
uint initialHeight;
|
||||
uint incrementHeight;
|
||||
uint timeoutChar;
|
||||
};
|
||||
|
||||
struct SubtitleEntry {
|
||||
uint32 frameStart;
|
||||
Common::String text;
|
||||
};
|
||||
|
||||
class CryOmni3DEngine_Versailles : public CryOmni3DEngine {
|
||||
friend class Versailles_DialogsManager;
|
||||
protected:
|
||||
Common::Error run() override;
|
||||
|
||||
public:
|
||||
CryOmni3DEngine_Versailles(OSystem *syst, const CryOmni3DGameDescription *gamedesc);
|
||||
~CryOmni3DEngine_Versailles() override;
|
||||
|
||||
void initializePath(const Common::FSNode &gamePath) override;
|
||||
|
||||
bool hasFeature(EngineFeature f) const override;
|
||||
Common::Error loadGameState(int slot) override;
|
||||
Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
|
||||
Common::String getSaveStateName(int slot) const override;
|
||||
|
||||
Common::Path getFilePath(FileType fileType, const Common::String &baseName) const;
|
||||
|
||||
void setupPalette(const byte *colors, uint start, uint num) override { setupPalette(colors, start, num, true); }
|
||||
void makeTranslucent(Graphics::Surface &dst, const Graphics::Surface &src) const override;
|
||||
|
||||
bool displayToolbar(const Graphics::Surface *original) override { return _toolbar.displayToolbar(original); };
|
||||
bool hasPlaceDocumentation() override;
|
||||
bool displayPlaceDocumentation() override;
|
||||
uint displayOptions() override;
|
||||
bool shouldAbort() override;
|
||||
|
||||
private:
|
||||
void setupFonts();
|
||||
void setupSprites();
|
||||
void loadCursorsPalette();
|
||||
void calculateTransparentMapping();
|
||||
void setupObjects();
|
||||
void setupDialogVariables();
|
||||
void setupImgScripts();
|
||||
void loadStaticData();
|
||||
|
||||
void syncOmni3DSettings();
|
||||
void syncSoundSettings() override;
|
||||
|
||||
void playTransitionEndLevel(int level);
|
||||
void changeLevel(int level);
|
||||
void initNewLevel(int level);
|
||||
void setupLevelWarps(int level);
|
||||
void initPlacesStates();
|
||||
void initWhoSpeaksWhere();
|
||||
void initDocPeopleRecord();
|
||||
void setupLevelActionsMask();
|
||||
|
||||
uint currentGameTime() const { return _gameVariables[GameVariables::kCurrentTime]; }
|
||||
void setGameTime(uint newTime, uint level);
|
||||
void updateGameTimeDialVariables();
|
||||
|
||||
void gameStep();
|
||||
void doGameOver();
|
||||
|
||||
void setPlaceState(uint placeId, uint newState);
|
||||
void doPlaceChange();
|
||||
void executeTransition(uint nextPlaceId);
|
||||
void fakeTransition(uint dstPlaceId);
|
||||
uint determineTransitionAnimation(uint srcId, uint dstId,
|
||||
const Transition **transition);
|
||||
|
||||
uint getFakeTransition(uint actionId) const;
|
||||
void fixActionId(uint *actionId) const;
|
||||
|
||||
int handleWarp();
|
||||
bool handleWarpMouse(uint *actionId, uint movingCuror);
|
||||
void animateWarpTransition(const Transition *transition);
|
||||
void redrawWarp();
|
||||
|
||||
void handleFixedImg(const FixedImgCallback &callback);
|
||||
void executeSeeAction(uint actionId);
|
||||
|
||||
void executeSpeakAction(uint actionId);
|
||||
void setupDialogShows();
|
||||
bool preprocessDialog(const Common::String &sequence);
|
||||
void postprocessDialog(const Common::String &sequence);
|
||||
|
||||
void executeDocAction(uint actionId);
|
||||
|
||||
void drawMenuTitle(Graphics::ManagedSurface *surface, byte color);
|
||||
uint displayFilePicker(const Graphics::Surface *bgFrame, bool saveMode,
|
||||
Common::String &saveName);
|
||||
uint displayYesNoBox(Graphics::ManagedSurface &surface, const Common::Rect &position,
|
||||
uint msg_id);
|
||||
void displayMessageBox(const MsgBoxParameters ¶ms, const Graphics::Surface *surface,
|
||||
uint msg_id, const Common::Point &position,
|
||||
const Common::Functor0<void> &callback) { displayMessageBox(params, surface, _messages[msg_id], position, callback); }
|
||||
void displayMessageBox(const MsgBoxParameters ¶ms, const Graphics::Surface *surface,
|
||||
const Common::String &msg, const Common::Point &position,
|
||||
const Common::Functor0<void> &callback);
|
||||
void displayMessageBoxWarp(const Common::String &message);
|
||||
void displayMessageBoxWarp(uint msg_id) { displayMessageBoxWarp(_messages[msg_id]); }
|
||||
void displayCredits();
|
||||
|
||||
void warpMsgBoxCB();
|
||||
|
||||
bool canVisit() const;
|
||||
Common::String getSaveFileName(bool visit, uint saveNum) const;
|
||||
void getSavesList(bool visit, Common::Array<Common::String> &saveNames, int &nextSaveNum);
|
||||
void saveGame(bool visit, uint saveNum, const Common::String &saveName);
|
||||
bool loadGame(bool visit, uint saveNum);
|
||||
|
||||
void animateCursor(const Object *object);
|
||||
void collectObject(Object *object, const ZonFixedImage *fimg = nullptr,
|
||||
bool showObject = true);
|
||||
void collectObject(uint nameID, const ZonFixedImage *fimg = nullptr,
|
||||
bool showObject = true) { collectObject(_objects.findObjectByNameID(nameID), fimg, showObject); }
|
||||
typedef void (CryOmni3DEngine_Versailles::*DisplayObjectHook)(Graphics::ManagedSurface &surface);
|
||||
void displayObject(const Common::String &imgName, DisplayObjectHook hook = nullptr);
|
||||
|
||||
void setMainPaletteColor(byte color, byte red, byte green, byte blue);
|
||||
void setupPalette(const byte *colors, uint start, uint num, bool commit);
|
||||
|
||||
bool showSubtitles() const;
|
||||
|
||||
void playInGameAnimVideo(const Common::String &filename) {
|
||||
playInGameVideo(getFilePath(kFileTypeAnimacti, filename));
|
||||
}
|
||||
void playInGameVideo(const Common::Path &filename, bool restoreCursorPalette = true);
|
||||
void playSubtitledVideo(const Common::String &filename);
|
||||
|
||||
void loadBMPs(const char *pattern, Graphics::Surface *bmps, uint count);
|
||||
|
||||
uint getMusicId(uint level, uint placeId) const;
|
||||
bool musicWouldChange(uint level, uint placeId) const;
|
||||
void musicUpdate();
|
||||
void musicPause();
|
||||
void musicResume();
|
||||
void musicStop();
|
||||
void musicSetQuiet(bool quiet);
|
||||
|
||||
Common::StringArray _localizedFilenames;
|
||||
Common::StringArray _messages;
|
||||
static const uint kSpritesMapTable[];
|
||||
static const uint kSpritesMapTableSize;
|
||||
static const LevelInitialState kLevelInitialStates[];
|
||||
static const FakeTransitionActionPlace kFakeTransitions[];
|
||||
Common::HashMap<uint, FixedImgCallback> _imgScripts;
|
||||
Common::Array<Common::String> _paintingsTitles;
|
||||
|
||||
Toolbar _toolbar;
|
||||
|
||||
byte *_mainPalette;
|
||||
byte *_cursorPalette;
|
||||
bool _fadedPalette;
|
||||
bool _forcePaletteUpdate;
|
||||
bool _forceRedrawWarp;
|
||||
|
||||
byte *_transparentPaletteMap;
|
||||
uint _transparentSrcStart;
|
||||
uint _transparentSrcStop;
|
||||
uint _transparentDstStart;
|
||||
uint _transparentDstStop;
|
||||
uint _transparentNewStart;
|
||||
uint _transparentNewStop;
|
||||
|
||||
bool _isPlaying;
|
||||
bool _isVisiting;
|
||||
AbortCommand _abortCommand;
|
||||
uint _loadedSave;
|
||||
|
||||
int _omni3dSpeed;
|
||||
|
||||
uint _currentLevel;
|
||||
Versailles_DialogsManager _dialogsMan;
|
||||
|
||||
Omni3DManager _omni3dMan;
|
||||
ZonFixedImage *_fixedImage;
|
||||
|
||||
Common::Array<uint> _gameVariables;
|
||||
Common::Array<PlaceState> _placeStates;
|
||||
Common::HashMap<PlaceStateActionKey, uint> _actionMasks;
|
||||
Common::HashMap<PlaceActionKey, Common::String> _whoSpeaksWhere;
|
||||
Common::HashMap<uint, const char *> _docPeopleRecord;
|
||||
bool _transitionAnimateWarp;
|
||||
uint _nextPlaceId;
|
||||
WAMParser _wam;
|
||||
uint _currentPlaceId;
|
||||
const Place *_currentPlace;
|
||||
const Image::ImageDecoder *_currentWarpImage;
|
||||
|
||||
const char *_musicCurrentFile;
|
||||
Audio::SoundHandle _musicHandle;
|
||||
float _musicVolumeFactor;
|
||||
static const char *kMusicFiles[8][8];
|
||||
|
||||
Versailles_Documentation _docManager;
|
||||
|
||||
static const MsgBoxParameters kWarpMsgBoxParameters;
|
||||
static const MsgBoxParameters kFixedimageMsgBoxParameters;
|
||||
static const FixedImageConfiguration kFixedImageConfiguration;
|
||||
|
||||
// Countdown
|
||||
void initCountdown();
|
||||
void syncCountdown();
|
||||
inline bool countDown() { if (_countingDown) { return doCountDown(); } else { return false; } }
|
||||
inline void drawCountdown(Graphics::ManagedSurface *surface = nullptr) { if (_countingDown) { doDrawCountdown(surface); } }
|
||||
void drawCountdownVideo(uint frameNum) { drawCountdown(); }
|
||||
|
||||
bool _countingDown;
|
||||
uint _countdownNextEvent;
|
||||
char _countdownValue[6];
|
||||
Graphics::ManagedSurface _countdownSurface;
|
||||
bool doCountDown();
|
||||
void doDrawCountdown(Graphics::ManagedSurface *surface);
|
||||
|
||||
// Video subtitles
|
||||
Common::HashMap<Common::String, Common::Array<SubtitleEntry> > _subtitles;
|
||||
const Common::Array<SubtitleEntry> *_currentSubtitleSet;
|
||||
Common::Array<SubtitleEntry>::const_iterator _currentSubtitle;
|
||||
void drawVideoSubtitles(uint frameNum);
|
||||
|
||||
// Objects
|
||||
template<uint ID>
|
||||
void genericDisplayObject();
|
||||
void obj_105();
|
||||
void obj_106();
|
||||
void obj_107();
|
||||
void obj_118();
|
||||
void obj_121();
|
||||
void obj_125();
|
||||
void obj_126();
|
||||
void obj_126hk(Graphics::ManagedSurface &surface);
|
||||
void obj_129();
|
||||
void obj_129hk(Graphics::ManagedSurface &surface);
|
||||
void obj_142();
|
||||
void obj_142hk(Graphics::ManagedSurface &surface);
|
||||
|
||||
// Fixed image
|
||||
template<uint ID>
|
||||
void genericDumbImage(ZonFixedImage *fimg);
|
||||
template<uint ID>
|
||||
void genericPainting(ZonFixedImage *fimg);
|
||||
#define IMG_CB(name) void img_ ## name(ZonFixedImage *fimg)
|
||||
IMG_CB(31101);
|
||||
IMG_CB(31101b);
|
||||
IMG_CB(31142);
|
||||
IMG_CB(31142b);
|
||||
IMG_CB(31142c);
|
||||
IMG_CB(31142d);
|
||||
IMG_CB(31143);
|
||||
IMG_CB(31143b);
|
||||
IMG_CB(31143c);
|
||||
IMG_CB(31143d);
|
||||
IMG_CB(32120);
|
||||
IMG_CB(32120b);
|
||||
IMG_CB(32120c);
|
||||
IMG_CB(32201);
|
||||
IMG_CB(32202);
|
||||
IMG_CB(32203);
|
||||
IMG_CB(32204);
|
||||
IMG_CB(32204b);
|
||||
IMG_CB(34131);
|
||||
IMG_CB(34132);
|
||||
IMG_CB(34172);
|
||||
IMG_CB(34173);
|
||||
IMG_CB(34173b);
|
||||
IMG_CB(34173c);
|
||||
IMG_CB(34174);
|
||||
IMG_CB(34174b);
|
||||
IMG_CB(34174c);
|
||||
IMG_CB(34174d);
|
||||
IMG_CB(34174e);
|
||||
IMG_CB(34174f);
|
||||
static const uint kSafeDigitsCount = 12;
|
||||
static const uint16 kSafeDigitsX[];
|
||||
static const uint16 kSafeDigitsY[];
|
||||
static const char *kSafeDates[];
|
||||
bool handleSafe(ZonFixedImage *fimg);
|
||||
void drawSafeDigits(Graphics::ManagedSurface &surface, const Graphics::Surface(&bmpDigits)[10],
|
||||
const unsigned char (&safeDigits)[kSafeDigitsCount]);
|
||||
bool checkSafeDigits(unsigned char (&safeDigits)[kSafeDigitsCount]);
|
||||
|
||||
IMG_CB(41202);
|
||||
IMG_CB(41202b);
|
||||
IMG_CB(41801);
|
||||
IMG_CB(41801b);
|
||||
IMG_CB(41801c);
|
||||
IMG_CB(41802);
|
||||
IMG_CB(41802b);
|
||||
IMG_CB(41802c);
|
||||
IMG_CB(41802d);
|
||||
IMG_CB(43143);
|
||||
IMG_CB(43143b);
|
||||
IMG_CB(43145);
|
||||
IMG_CB(43145b);
|
||||
IMG_CB(43145c);
|
||||
IMG_CB(43146);
|
||||
IMG_CB(43146b);
|
||||
IMG_CB(43146c);
|
||||
IMG_CB(43160);
|
||||
IMG_CB(43160b);
|
||||
IMG_CB(43160c);
|
||||
IMG_CB(43160d);
|
||||
IMG_CB(43190);
|
||||
IMG_CB(43190b);
|
||||
IMG_CB(43190c);
|
||||
IMG_CB(43190d);
|
||||
IMG_CB(43190e);
|
||||
IMG_CB(43190f);
|
||||
IMG_CB(44071);
|
||||
IMG_CB(44071b);
|
||||
IMG_CB(44161);
|
||||
IMG_CB(44161b);
|
||||
IMG_CB(44161c);
|
||||
IMG_CB(44161d);
|
||||
IMG_CB(44161e);
|
||||
IMG_CB(44161f);
|
||||
static const uint kEpigraphMaxLetters = 32;
|
||||
Common::String _epigraphContent;
|
||||
Common::String _epigraphPassword;
|
||||
bool handleEpigraph(ZonFixedImage *fimg);
|
||||
void drawEpigraphLetters(Graphics::ManagedSurface &surface,
|
||||
const Graphics::Surface(&bmpLetters)[28], const Common::String &letters);
|
||||
IMG_CB(45130);
|
||||
IMG_CB(45270);
|
||||
IMG_CB(45270b);
|
||||
IMG_CB(45270c);
|
||||
IMG_CB(45270d);
|
||||
IMG_CB(45280);
|
||||
|
||||
IMG_CB(88001);
|
||||
IMG_CB(88001b);
|
||||
IMG_CB(88001c);
|
||||
IMG_CB(88002);
|
||||
IMG_CB(88003);
|
||||
IMG_CB(88003b);
|
||||
IMG_CB(88003c);
|
||||
IMG_CB(88003d);
|
||||
IMG_CB(88003e);
|
||||
IMG_CB(88003f);
|
||||
Common::U32String _bombAlphabet; // For Japanese edition
|
||||
Common::U32String _bombPassword;
|
||||
static const uint kBombPasswordSmallLength = 40;
|
||||
static const uint kBombPasswordMaxLength = 60;
|
||||
static const uint16 kBombLettersPos[2][kBombPasswordMaxLength][2];
|
||||
bool handleBomb(ZonFixedImage *fimg);
|
||||
void handleBombTranslation(Graphics::ManagedSurface &surface);
|
||||
void drawBombLetters(Graphics::ManagedSurface &surface, const Graphics::Surface(&bmpLetters)[28],
|
||||
const uint bombPasswordLength,
|
||||
const uint32(&bombPossibilites)[kBombPasswordMaxLength][5],
|
||||
const byte(&bombCurrentLetters)[kBombPasswordMaxLength]);
|
||||
IMG_CB(88004);
|
||||
IMG_CB(88004b);
|
||||
#undef IMG_CB
|
||||
|
||||
#define FILTER_EVENT(level, place) bool filterEventLevel ## level ## Place ## place(uint *event)
|
||||
#define INIT_PLACE(level, place) void initPlaceLevel ## level ## Place ## place()
|
||||
FILTER_EVENT(1, 1);
|
||||
FILTER_EVENT(1, 2);
|
||||
INIT_PLACE(1, 3);
|
||||
FILTER_EVENT(1, 3);
|
||||
//FILTER_EVENT(1, 7); // Not used
|
||||
FILTER_EVENT(1, 14);
|
||||
|
||||
FILTER_EVENT(2, 1);
|
||||
FILTER_EVENT(2, 2);
|
||||
FILTER_EVENT(2, 5);
|
||||
INIT_PLACE(2, 9);
|
||||
FILTER_EVENT(2, 9);
|
||||
FILTER_EVENT(2, 11);
|
||||
FILTER_EVENT(2, 12);
|
||||
FILTER_EVENT(2, 14);
|
||||
|
||||
FILTER_EVENT(3, 3);
|
||||
FILTER_EVENT(3, 10);
|
||||
FILTER_EVENT(3, 13);
|
||||
FILTER_EVENT(3, 15);
|
||||
FILTER_EVENT(3, 17);
|
||||
FILTER_EVENT(3, 18);
|
||||
FILTER_EVENT(3, 19);
|
||||
FILTER_EVENT(3_5, 20);
|
||||
FILTER_EVENT(3, 22);
|
||||
FILTER_EVENT(3, 23);
|
||||
bool filterEventLevel3Obj23151();
|
||||
void collectLampoonArchitecture(const ZonFixedImage *fimg = nullptr);
|
||||
|
||||
INIT_PLACE(4, 9);
|
||||
FILTER_EVENT(4, 10);
|
||||
FILTER_EVENT(4, 12_13_14);
|
||||
FILTER_EVENT(4, 15);
|
||||
FILTER_EVENT(4, 16);
|
||||
FILTER_EVENT(4, 17);
|
||||
|
||||
INIT_PLACE(5, 6);
|
||||
FILTER_EVENT(5, 9);
|
||||
FILTER_EVENT(5, 14);
|
||||
FILTER_EVENT(5, 15);
|
||||
FILTER_EVENT(5, 16);
|
||||
void filterEventLevel5UpdatePlaceStates();
|
||||
//FILTER_EVENT(3_5, 20);
|
||||
FILTER_EVENT(5, 23);
|
||||
FILTER_EVENT(5, 27);
|
||||
FILTER_EVENT(5, 28);
|
||||
FILTER_EVENT(5, 29);
|
||||
FILTER_EVENT(5, 33);
|
||||
FILTER_EVENT(5, 34);
|
||||
|
||||
FILTER_EVENT(6, 1);
|
||||
FILTER_EVENT(6, 3);
|
||||
FILTER_EVENT(6, Orangery);
|
||||
FILTER_EVENT(6, 19);
|
||||
|
||||
FILTER_EVENT(7, 2);
|
||||
FILTER_EVENT(7, 9);
|
||||
FILTER_EVENT(7, 10_11_13);
|
||||
FILTER_EVENT(7, 20);
|
||||
#undef FILTER_EVENT
|
||||
#undef INIT_PLACE
|
||||
|
||||
// Dialogs shows
|
||||
void dialogShowBontempsShowThird();
|
||||
void dialogShowHuissierShowPamphlet();
|
||||
void dialogShowMonseigneurSorts();
|
||||
void dialogShowLeBrunWatches();
|
||||
void dialogShowDoorsOpen();
|
||||
void dialogShowSwissGuardGives();
|
||||
void dialogShowLullyCorrects();
|
||||
void dialogShowBontempsGivesAuth();
|
||||
void dialogShowCroissyLeave();
|
||||
void dialogShowMaintenonGives();
|
||||
void dialogShowLaChaizeGivesBack();
|
||||
void dialogShowLaChaizeWrites();
|
||||
void dialogShowLaChaizeGivesPamphlet();
|
||||
void dialogShowBontempsGivesKey();
|
||||
void dialogShowDuMaineLeaves();
|
||||
void dialogShowTransitionScene();
|
||||
void dialogShowEndOfGame();
|
||||
void dialogShowLeBrunGives();
|
||||
void dialogShowLeBrunLeave();
|
||||
};
|
||||
|
||||
} // End of namespace Versailles
|
||||
} // End of namespace CryOmni3D
|
||||
|
||||
#endif
|
||||
4852
engines/cryomni3d/versailles/logic.cpp
Normal file
4852
engines/cryomni3d/versailles/logic.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1148
engines/cryomni3d/versailles/menus.cpp
Normal file
1148
engines/cryomni3d/versailles/menus.cpp
Normal file
File diff suppressed because it is too large
Load Diff
280
engines/cryomni3d/versailles/music.cpp
Normal file
280
engines/cryomni3d/versailles/music.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
/* 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 "audio/audiostream.h"
|
||||
#include "audio/decoders/wave.h"
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/error.h"
|
||||
#include "common/file.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "cryomni3d/versailles/engine.h"
|
||||
|
||||
namespace CryOmni3D {
|
||||
namespace Versailles {
|
||||
|
||||
const char *CryOmni3DEngine_Versailles::kMusicFiles[8][8] = {
|
||||
{ "1amb", }, // Level 1
|
||||
{ "2amb", "2amb2", "2amb1" }, // Level 2
|
||||
{ "3amb", "3amb1", "3amb2" }, // Level 3
|
||||
{ "4amb", "4amb1" }, // Level 4
|
||||
{ "5amb1", "5amb2" }, // Level 5
|
||||
{ "6amb1", "6amb2", "6amb3", "6amb4" }, // Level 6
|
||||
{ "7amb", }, // Level 7
|
||||
{ "3amb", "3amb1", "3amb2", "2amb", "2amb1", "2amb2", "4amb" }, // Level 8
|
||||
};
|
||||
|
||||
void CryOmni3DEngine_Versailles::musicUpdate() {
|
||||
if (!_isPlaying || _currentLevel <= 0 ||
|
||||
_mixer->isSoundTypeMuted(Audio::Mixer::kMusicSoundType) ||
|
||||
_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) == 0) {
|
||||
// No music in all of these cases
|
||||
musicStop();
|
||||
return;
|
||||
}
|
||||
|
||||
uint musicId = getMusicId(_currentLevel, _currentPlaceId);
|
||||
const char *musicBName = kMusicFiles[_currentLevel - 1][musicId];
|
||||
assert(musicBName != nullptr);
|
||||
|
||||
// Ensure sound is playing in all cases
|
||||
musicResume();
|
||||
|
||||
if (musicBName == _musicCurrentFile) {
|
||||
// Same file, nothing more to do
|
||||
return;
|
||||
}
|
||||
|
||||
// New file, stop the old one first
|
||||
musicStop();
|
||||
|
||||
Common::Path musicPath(getFilePath(kFileTypeMusic, musicBName));
|
||||
|
||||
Common::File *musicFile = new Common::File();
|
||||
if (!musicFile->open(musicPath)) {
|
||||
warning("Failed to open music file %s/%s", musicBName, musicPath.toString(Common::Path::kNativeSeparator).c_str());
|
||||
delete musicFile;
|
||||
return;
|
||||
}
|
||||
|
||||
Audio::SeekableAudioStream *musicDecoder = Audio::makeWAVStream(musicFile, DisposeAfterUse::YES);
|
||||
// We lost ownership of the musicFile just set it to nullptr and don't use it
|
||||
musicFile = nullptr;
|
||||
|
||||
if (!musicDecoder) {
|
||||
warning("Failed to decode music file %s/%s", musicBName, musicPath.toString(Common::Path::kNativeSeparator).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
Audio::AudioStream *loopStream = Audio::makeLoopingAudioStream(musicDecoder, 0);
|
||||
// We lost ownership of musicDecoder just set it to nullptr and don't use it
|
||||
musicDecoder = nullptr;
|
||||
|
||||
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle, loopStream);
|
||||
_musicCurrentFile = musicBName;
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::musicPause() {
|
||||
_mixer->pauseHandle(_musicHandle, true);
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::musicResume() {
|
||||
_mixer->pauseHandle(_musicHandle, false);
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::musicStop() {
|
||||
// Fade the music first
|
||||
if (_mixer->isSoundHandleActive(_musicHandle)) {
|
||||
// We recreate the real channel volume to decrease this one 2 by 2
|
||||
int musicVol = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);
|
||||
byte channelVol = _mixer->getChannelVolume(_musicHandle);
|
||||
int realVolume = (musicVol * channelVol) / Audio::Mixer::kMaxChannelVolume;
|
||||
bool skip = false;
|
||||
while (realVolume > 0 && !skip) {
|
||||
realVolume -= 2;
|
||||
channelVol = CLIP((realVolume * Audio::Mixer::kMaxChannelVolume) / musicVol, 0, 255);
|
||||
_mixer->setChannelVolume(_musicHandle, channelVol);
|
||||
if (pollEvents() && checkKeysPressed(1, Common::KEYCODE_SPACE)) {
|
||||
skip = true;
|
||||
}
|
||||
g_system->delayMillis(10);
|
||||
}
|
||||
}
|
||||
_mixer->stopHandle(_musicHandle);
|
||||
_musicCurrentFile = nullptr;
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::musicSetQuiet(bool quiet) {
|
||||
float newFactor = quiet ? 3.5f : 1.f;
|
||||
if (newFactor != _musicVolumeFactor) {
|
||||
_musicVolumeFactor = newFactor;
|
||||
syncSoundSettings();
|
||||
}
|
||||
}
|
||||
|
||||
bool CryOmni3DEngine_Versailles::musicWouldChange(uint level, uint placeId) const {
|
||||
uint musicId = getMusicId(level, placeId);
|
||||
const char *musicFile = kMusicFiles[_currentLevel - 1][musicId];
|
||||
|
||||
return musicFile != _musicCurrentFile;
|
||||
}
|
||||
|
||||
uint CryOmni3DEngine_Versailles::getMusicId(uint level,
|
||||
uint placeId) const {
|
||||
// No need of place state
|
||||
switch (level) {
|
||||
case 1:
|
||||
// Only one music
|
||||
return 0;
|
||||
case 2:
|
||||
switch (placeId) {
|
||||
case 4:
|
||||
return 1;
|
||||
case 10:
|
||||
case 11:
|
||||
case 13:
|
||||
return 2;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case 3:
|
||||
switch (placeId) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
return 2;
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 12:
|
||||
case 24:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case 4:
|
||||
switch (placeId) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case 5:
|
||||
switch (placeId) {
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 12:
|
||||
case 26:
|
||||
case 27:
|
||||
case 30:
|
||||
case 31:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case 6:
|
||||
switch (placeId) {
|
||||
case 1:
|
||||
return 3;
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
return 0;
|
||||
case 14:
|
||||
case 16:
|
||||
case 17:
|
||||
case 19:
|
||||
case 20:
|
||||
case 22:
|
||||
case 24:
|
||||
case 26:
|
||||
case 27:
|
||||
case 32:
|
||||
case 34:
|
||||
case 38:
|
||||
case 44:
|
||||
return 2;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
case 7:
|
||||
return 0;
|
||||
case 8:
|
||||
switch (placeId) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
return 2;
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
return 1;
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
return 0;
|
||||
case 12:
|
||||
return 1;
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
return 0;
|
||||
case 24:
|
||||
return 1;
|
||||
case 33:
|
||||
case 34:
|
||||
case 35:
|
||||
return 5;
|
||||
case 36:
|
||||
case 37:
|
||||
case 38:
|
||||
case 39:
|
||||
return 3;
|
||||
case 40:
|
||||
return 4;
|
||||
case 42:
|
||||
case 43:
|
||||
case 44:
|
||||
return 6;
|
||||
default:
|
||||
return 0;
|
||||
|
||||
}
|
||||
default:
|
||||
error("Invalid level %d when choosing music", level);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Versailles
|
||||
} // End of namespace CryOmni3D
|
||||
337
engines/cryomni3d/versailles/saveload.cpp
Normal file
337
engines/cryomni3d/versailles/saveload.cpp
Normal file
@@ -0,0 +1,337 @@
|
||||
/* 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 "common/archive.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "cryomni3d/versailles/engine.h"
|
||||
|
||||
namespace CryOmni3D {
|
||||
namespace Versailles {
|
||||
|
||||
Common::Error CryOmni3DEngine_Versailles::loadGameState(int slot) {
|
||||
_loadedSave = slot + 1;
|
||||
_abortCommand = kAbortLoadGame;
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Common::Error CryOmni3DEngine_Versailles::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
|
||||
saveGame(_isVisiting, slot + 1, desc);
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Common::String CryOmni3DEngine_Versailles::getSaveFileName(bool visit, uint saveNum) const {
|
||||
return Common::String::format("%s%s.%04u", _targetName.c_str(), visit ? "_visit" : "", saveNum);
|
||||
}
|
||||
|
||||
Common::String CryOmni3DEngine_Versailles::getSaveStateName(int slot) const {
|
||||
return Common::String::format("%s.%04u", _targetName.c_str(), slot);
|
||||
}
|
||||
|
||||
bool CryOmni3DEngine_Versailles::canVisit() const {
|
||||
return Common::File::exists(getFilePath(kFileTypeSaveGameVisit, "game0001.sav"));
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::getSavesList(bool visit, Common::StringArray &saveNames,
|
||||
int &nextSaveNum) {
|
||||
nextSaveNum = 1;
|
||||
bool supportsAutoName = (_messages.size() >= 148);
|
||||
|
||||
char saveName[kSaveDescriptionLen + 1];
|
||||
// Terminate saveName here forever (we don't overrun kSaveDescriptionLen)
|
||||
saveName[kSaveDescriptionLen] = '\0';
|
||||
Common::String pattern = Common::String::format("%s%s.####", _targetName.c_str(),
|
||||
visit ? "_visit" : "");
|
||||
Common::StringArray filenames = _saveFileMan->listSavefiles(pattern);
|
||||
sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
|
||||
|
||||
saveNames.clear();
|
||||
saveNames.reserve(100);
|
||||
|
||||
int num = 1;
|
||||
int slotNum;
|
||||
|
||||
if (visit) {
|
||||
// Add bootstrap visit
|
||||
Common::Path visitPath(getFilePath(kFileTypeSaveGameVisit, "game0001.sav"));
|
||||
Common::File visitFile;
|
||||
if (visitFile.open(visitPath)) {
|
||||
visitFile.read(saveName, kSaveDescriptionLen);
|
||||
saveNames.push_back(saveName);
|
||||
} else {
|
||||
warning("visiting mode but no bootstrap");
|
||||
// No bootstrap visit, too bad
|
||||
saveNames.push_back(_messages[55]); //Fill with free slot
|
||||
}
|
||||
num++;
|
||||
}
|
||||
|
||||
for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end();
|
||||
++file) {
|
||||
// Obtain the last 4 digits of the filename, since they correspond to the save slot
|
||||
slotNum = atoi(file->c_str() + file->size() - 4);
|
||||
|
||||
if (slotNum >= 1 && slotNum <= 99) {
|
||||
while (num < slotNum) {
|
||||
saveNames.push_back(_messages[55]); //Fill with free slot
|
||||
num++;
|
||||
}
|
||||
|
||||
num++;
|
||||
Common::InSaveFile *in = _saveFileMan->openForLoading(*file);
|
||||
if (in) {
|
||||
if (in->read(saveName, kSaveDescriptionLen) != kSaveDescriptionLen) {
|
||||
warning("getSavesList(): Corrupted save %s", saveName);
|
||||
delete in;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
Common::String saveNameStr = saveName;
|
||||
if (supportsAutoName && saveNameStr.hasPrefix("AUTO")) {
|
||||
int saveNum = atoi(saveName + 4);
|
||||
if (saveNum >= 1 && saveNum <= 9999) {
|
||||
in->seek(436); // Go to current level
|
||||
uint32 level = in->readUint32BE();
|
||||
|
||||
if (level < 8) {
|
||||
saveNameStr = Common::String::format(_messages[146].c_str(), level);
|
||||
} else {
|
||||
saveNameStr = _messages[147];
|
||||
}
|
||||
saveNameStr += Common::String::format(" - %d", saveNum);
|
||||
if (saveNum >= nextSaveNum) {
|
||||
if (saveNum >= 9999) {
|
||||
nextSaveNum = 9999;
|
||||
} else {
|
||||
nextSaveNum = saveNum + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
saveNames.push_back(saveNameStr);
|
||||
delete in;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint i = saveNames.size(); i < 100; i++) {
|
||||
saveNames.push_back(_messages[55]);
|
||||
}
|
||||
}
|
||||
|
||||
void CryOmni3DEngine_Versailles::saveGame(bool visit, uint saveNum,
|
||||
const Common::String &saveName) {
|
||||
if (visit && saveNum == 1) {
|
||||
error("Can't erase bootstrap visit");
|
||||
}
|
||||
|
||||
Common::String saveFileName = getSaveFileName(visit, saveNum);
|
||||
|
||||
Common::OutSaveFile *out;
|
||||
|
||||
if (!(out = _saveFileMan->openForSaving(saveFileName))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sync countdown to game variable before saving it to file
|
||||
syncCountdown();
|
||||
|
||||
// Write save name
|
||||
|
||||
// Allocate one more byte to silence GCC warning
|
||||
// The save name doesn't have to be null terminated in the save file
|
||||
char saveNameC[kSaveDescriptionLen + 1];
|
||||
memset(saveNameC, 0, sizeof(saveNameC));
|
||||
strncpy(saveNameC, saveName.c_str(), kSaveDescriptionLen);
|
||||
out->write(saveNameC, kSaveDescriptionLen);
|
||||
|
||||
// dummy values
|
||||
out->writeUint32LE(0);
|
||||
out->writeUint32BE(0);
|
||||
out->writeUint32BE(0);
|
||||
|
||||
// Dialog variables
|
||||
assert(_dialogsMan.size() < 200);
|
||||
for (uint i = 0; i < _dialogsMan.size(); i++) {
|
||||
out->writeByte(_dialogsMan[i]);
|
||||
}
|
||||
for (uint i = _dialogsMan.size(); i < 200; i++) {
|
||||
out->writeByte(0);
|
||||
}
|
||||
|
||||
// Inventory
|
||||
assert(_inventory.size() == 50);
|
||||
for (Inventory::const_iterator it = _inventory.begin(); it != _inventory.end(); it++) {
|
||||
uint objId = uint(-1);
|
||||
if (*it != nullptr) {
|
||||
// Inventory contains pointers to objects stored in _objects
|
||||
objId = *it - _objects.begin();
|
||||
}
|
||||
out->writeUint32BE(objId);
|
||||
}
|
||||
// Offset of inventory in toolbar
|
||||
out->writeUint32BE(_toolbar.inventoryOffset());
|
||||
|
||||
// Level, place, warp position
|
||||
out->writeUint32BE(_currentLevel);
|
||||
out->writeUint32BE(_currentPlaceId);
|
||||
out->writeDoubleBE(_omni3dMan.getAlpha());
|
||||
out->writeDoubleBE(_omni3dMan.getBeta());
|
||||
|
||||
// Places states
|
||||
assert(_placeStates.size() <= 100);
|
||||
Common::Array<PlaceState>::const_iterator placeIt = _placeStates.begin();
|
||||
for (uint i = 0; placeIt != _placeStates.end(); placeIt++, i++) {
|
||||
out->writeUint32BE(placeIt->state);
|
||||
}
|
||||
for (uint i = _placeStates.size(); i < 100; i++) {
|
||||
out->writeUint32BE(0);
|
||||
}
|
||||
|
||||
// Game variables
|
||||
assert(_gameVariables.size() < 100);
|
||||
for (Common::Array<uint>::const_iterator it = _gameVariables.begin();
|
||||
it != _gameVariables.end(); it++) {
|
||||
out->writeUint32BE(*it);
|
||||
}
|
||||
for (uint i = _gameVariables.size(); i < 100; i++) {
|
||||
out->writeUint32BE(0);
|
||||
}
|
||||
|
||||
out->finalize();
|
||||
|
||||
delete out;
|
||||
}
|
||||
|
||||
bool CryOmni3DEngine_Versailles::loadGame(bool visit, uint saveNum) {
|
||||
Common::SeekableReadStream *in;
|
||||
|
||||
if (visit && saveNum == 1) {
|
||||
// Load bootstrap visit
|
||||
Common::File *visitFile = new Common::File();
|
||||
if (!visitFile->open(getFilePath(kFileTypeSaveGameVisit, "game0001.sav"))) {
|
||||
delete visitFile;
|
||||
error("Can't load visit file");
|
||||
}
|
||||
in = visitFile;
|
||||
} else {
|
||||
Common::String saveFileName = getSaveFileName(visit, saveNum);
|
||||
in = _saveFileMan->openForLoading(saveFileName);
|
||||
}
|
||||
|
||||
if (!in || in->size() != 1260) {
|
||||
return false;
|
||||
}
|
||||
|
||||
musicStop();
|
||||
|
||||
// Load save name but don't use it
|
||||
char saveNameC[kSaveDescriptionLen];
|
||||
in->read(saveNameC, sizeof(saveNameC));
|
||||
|
||||
// dummy values
|
||||
(void) in->readUint32LE();
|
||||
(void) in->readUint32BE();
|
||||
(void) in->readUint32BE();
|
||||
|
||||
// Dialog variables
|
||||
assert(_dialogsMan.size() < 200);
|
||||
for (uint i = 0; i < _dialogsMan.size(); i++) {
|
||||
_dialogsMan[i] = in->readByte();
|
||||
}
|
||||
for (uint i = _dialogsMan.size(); i < 200; i++) {
|
||||
// Read the remaining bytes but don't use them
|
||||
(void) in->readByte();
|
||||
}
|
||||
|
||||
// Inventory
|
||||
assert(_inventory.size() == 50);
|
||||
for (Inventory::iterator it = _inventory.begin(); it != _inventory.end(); it++) {
|
||||
uint objId = in->readUint32BE();
|
||||
if (objId >= _objects.size()) {
|
||||
objId = uint(-1);
|
||||
}
|
||||
if (objId != uint(-1)) {
|
||||
*it = _objects.begin() + objId;
|
||||
} else {
|
||||
*it = nullptr;
|
||||
}
|
||||
}
|
||||
// Offset of inventory in toolbar
|
||||
_toolbar.setInventoryOffset(in->readUint32BE());
|
||||
|
||||
// Level, place, warp position
|
||||
_currentLevel = in->readUint32BE();
|
||||
// Use nextPlace to force place move
|
||||
_nextPlaceId = in->readUint32BE();
|
||||
|
||||
// Store alpha and beta for later use
|
||||
double alpha = in->readDoubleBE();
|
||||
double beta = in->readDoubleBE();
|
||||
|
||||
// Places states
|
||||
// Store them and use them once we called initNewLevel, we can't call it before because it needs _gameVariables (and especially kCurrentTime) to be correctly set
|
||||
uint32 placesStates[100];
|
||||
for (uint i = 0; i < 100; i++) {
|
||||
placesStates[i] = in->readUint32BE();
|
||||
}
|
||||
|
||||
// Game variables
|
||||
assert(_gameVariables.size() < 100);
|
||||
for (Common::Array<uint>::iterator it = _gameVariables.begin(); it != _gameVariables.end();
|
||||
it++) {
|
||||
*it = in->readUint32BE();
|
||||
}
|
||||
for (uint i = _gameVariables.size(); i < 100; i++) {
|
||||
// Read the remaining variables but don't use them
|
||||
(void) in->readUint32BE();
|
||||
}
|
||||
|
||||
delete in;
|
||||
|
||||
if (_gameVariables[GameVariables::kCurrentTime] == 0) {
|
||||
_gameVariables[GameVariables::kCurrentTime] = 1;
|
||||
}
|
||||
initCountdown();
|
||||
|
||||
// Everything has been loaded, setup new level
|
||||
// We will set places states and warp coordinates just after that to avoid them from being reset
|
||||
initNewLevel(_currentLevel);
|
||||
|
||||
_omni3dMan.setAlpha(alpha);
|
||||
_omni3dMan.setBeta(beta);
|
||||
|
||||
// _placeStates has just been resized in initNewLevel
|
||||
uint i = 0;
|
||||
for (Common::Array<PlaceState>::iterator placeIt = _placeStates.begin();
|
||||
placeIt != _placeStates.end() && i < ARRAYSIZE(placesStates); placeIt++, i++) {
|
||||
placeIt->state = placesStates[i];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Versailles
|
||||
} // End of namespace CryOmni3D
|
||||
602
engines/cryomni3d/versailles/toolbar.cpp
Normal file
602
engines/cryomni3d/versailles/toolbar.cpp
Normal file
@@ -0,0 +1,602 @@
|
||||
/* 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 "common/system.h"
|
||||
|
||||
#include "cryomni3d/cryomni3d.h"
|
||||
|
||||
#include "cryomni3d/versailles/toolbar.h"
|
||||
|
||||
namespace CryOmni3D {
|
||||
namespace Versailles {
|
||||
|
||||
void Toolbar::init(const Sprites *sprites, FontManager *fontManager,
|
||||
const Common::Array<Common::String> *messages, Inventory *inventory,
|
||||
CryOmni3DEngine *engine) {
|
||||
_sprites = sprites;
|
||||
_fontManager = fontManager;
|
||||
_messages = messages;
|
||||
_inventory = inventory;
|
||||
_engine = engine;
|
||||
|
||||
_bgSurface.create(640, 60, Graphics::PixelFormat::createFormatCLUT8());
|
||||
_destSurface.create(640, 60, Graphics::PixelFormat::createFormatCLUT8());
|
||||
|
||||
// Inventory
|
||||
addZone(51, 56, Common::Point(211, 8), &Toolbar::callbackInventory<0>);
|
||||
addZone(51, 56, Common::Point(258, 8), &Toolbar::callbackInventory<1>);
|
||||
addZone(51, 56, Common::Point(305, 8), &Toolbar::callbackInventory<2>);
|
||||
addZone(51, 56, Common::Point(352, 8), &Toolbar::callbackInventory<3>);
|
||||
addZone(51, 56, Common::Point(399, 8), &Toolbar::callbackInventory<4>);
|
||||
addZone(51, 56, Common::Point(446, 8), &Toolbar::callbackInventory<5>);
|
||||
addZone(51, 56, Common::Point(493, 8), &Toolbar::callbackInventory<6>);
|
||||
addZone(51, 56, Common::Point(540, 8), &Toolbar::callbackInventory<7>);
|
||||
|
||||
// Documentation
|
||||
const Graphics::Cursor &cursorDoc = _sprites->getCursor(133);
|
||||
Common::Point docPos(627 - cursorDoc.getWidth(), 42 - cursorDoc.getHeight());
|
||||
addZone(133, 137, docPos, &Toolbar::callbackDocumentation);
|
||||
|
||||
// Options
|
||||
const Graphics::Cursor &cursorOpt = _sprites->getCursor(225);
|
||||
Common::Point optPos(0, 60 - cursorOpt.getHeight());
|
||||
addZone(225, 225, optPos, &Toolbar::callbackOptions);
|
||||
|
||||
// Previous or next
|
||||
addZone(183, uint16(-1), Common::Point(190, 18), &Toolbar::callbackInventoryPrev);
|
||||
addZone(240, uint16(-1), Common::Point(574, 18), &Toolbar::callbackInventoryNext);
|
||||
// View
|
||||
addZone(142, uint16(-1), Common::Point(158, 12), &Toolbar::callbackViewObject);
|
||||
}
|
||||
|
||||
Toolbar::~Toolbar() {
|
||||
_bgSurface.free();
|
||||
_destSurface.free();
|
||||
}
|
||||
|
||||
void Toolbar::inventoryChanged(uint newPosition) {
|
||||
if (newPosition != uint(-1) && newPosition > _inventoryOffset) {
|
||||
_inventoryOffset = newPosition - 7;
|
||||
}
|
||||
// Refresh
|
||||
updateZones();
|
||||
}
|
||||
|
||||
void Toolbar::addZone(uint16 cursorMainId, uint16 cursorSecondaryId, Common::Point position,
|
||||
ZoneCallback callback) {
|
||||
const Graphics::Cursor &cursorMain = _sprites->getCursor(cursorMainId);
|
||||
Common::Rect rct(cursorMain.getWidth(), cursorMain.getHeight());
|
||||
rct.moveTo(position);
|
||||
|
||||
// By default it's the secondary image
|
||||
Zone zone = { rct, cursorMainId, cursorSecondaryId, callback, true, false };
|
||||
_zones.push_back(zone);
|
||||
}
|
||||
|
||||
Common::Array<Toolbar::Zone>::const_iterator Toolbar::hitTestZones(const Common::Point &mousePos)
|
||||
const {
|
||||
Common::Array<Zone>::const_iterator it;
|
||||
for (it = _zones.begin(); it != _zones.end(); it++) {
|
||||
if (!it->hidden && it->rect.contains(mousePos) && it->callback) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
uint Toolbar::captureEvent(const Common::Point &mousePos, uint dragStatus) {
|
||||
uint result = 0;
|
||||
Common::Array<Zone>::const_iterator it = hitTestZones(mousePos);
|
||||
if (it != _zones.end()) {
|
||||
result = (this->*(it->callback))(dragStatus);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Toolbar::updateZones() {
|
||||
_zones[8].secondary = !_engine->hasPlaceDocumentation();
|
||||
|
||||
Inventory::const_iterator inventoryIt, inventorySelectedIt;
|
||||
if (!_inventoryEnabled) {
|
||||
_inventoryMaxOffset = 0;
|
||||
_inventoryOffset = 0;
|
||||
_zones[10].secondary = true;
|
||||
_zones[11].secondary = true;
|
||||
inventoryIt = _inventory->end();
|
||||
inventorySelectedIt = _inventory->end();
|
||||
} else {
|
||||
_inventoryMaxOffset = 0;
|
||||
// Find an object in inventory after the 8 first
|
||||
for (inventoryIt = _inventory->begin() + 8; inventoryIt != _inventory->end(); inventoryIt++) {
|
||||
if (*inventoryIt != nullptr) {
|
||||
_inventoryMaxOffset = (inventoryIt - _inventory->begin()) - 7;
|
||||
}
|
||||
}
|
||||
_zones[10].secondary = !_inventoryMaxOffset;
|
||||
_zones[11].secondary = !_inventoryMaxOffset;
|
||||
if (_inventoryOffset > _inventoryMaxOffset) {
|
||||
// Clamp inventory offset to its max
|
||||
_inventoryOffset = _inventoryMaxOffset;
|
||||
}
|
||||
inventoryIt = _inventory->begin() + _inventoryOffset;
|
||||
inventorySelectedIt = _inventory->begin() + _inventorySelected;
|
||||
}
|
||||
// Inventory zones are from 0 to 7
|
||||
for (Common::Array<Zone>::iterator zoneIt = _zones.begin(); zoneIt != _zones.begin() + 8;
|
||||
zoneIt++, inventoryIt++) {
|
||||
if (!_inventoryEnabled) {
|
||||
zoneIt->hidden = true;
|
||||
zoneIt->imageMain = 0;
|
||||
zoneIt->imageSecondary = 0;
|
||||
zoneIt->secondary = false;
|
||||
} else if (inventoryIt >= _inventory->end() || *inventoryIt == nullptr) {
|
||||
// Nothing in inventory at this position
|
||||
zoneIt->hidden = false;
|
||||
zoneIt->imageMain = 51;
|
||||
zoneIt->imageSecondary = 56;
|
||||
zoneIt->secondary = true;
|
||||
} else {
|
||||
// Setup inventory icon
|
||||
zoneIt->hidden = false;
|
||||
zoneIt->imageMain = (*inventoryIt)->idCA();
|
||||
zoneIt->imageSecondary = (*inventoryIt)->idCl();
|
||||
zoneIt->secondary = (inventorySelectedIt != inventoryIt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint Toolbar::callbackInventory(uint invId, uint dragStatus) {
|
||||
if (!_inventoryEnabled) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
invId += _inventoryOffset;
|
||||
Object *obj = nullptr;
|
||||
if (invId < _inventory->size()) {
|
||||
obj = (*_inventory)[invId];
|
||||
}
|
||||
if (obj == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!obj->valid()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (dragStatus) {
|
||||
case kDragStatus_Pressed:
|
||||
_inventorySelected = invId;
|
||||
_engine->setCursor(181);
|
||||
_zones[12].secondary = (obj->viewCallback() == nullptr);
|
||||
_inventoryButtonDragging = true;
|
||||
return 1;
|
||||
case kDragStatus_Dragging:
|
||||
if (_inventorySelected == invId) {
|
||||
return 0;
|
||||
}
|
||||
_inventorySelected = invId;
|
||||
_zones[12].secondary = (obj->viewCallback() == nullptr);
|
||||
_inventoryButtonDragging = true;
|
||||
return 1;
|
||||
case kDragStatus_Finished:
|
||||
_engine->setCursor(obj->idSl());
|
||||
_inventory->setSelectedObject(obj);
|
||||
_inventorySelected = invId;
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint Toolbar::callbackInventoryPrev(uint dragStatus) {
|
||||
if (!_inventoryEnabled) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dragStatus == kDragStatus_Pressed && _inventoryOffset > 0) {
|
||||
// Restart auto repeat only if there could be something
|
||||
_engine->setAutoRepeatClick(150);
|
||||
_inventoryOffset--;
|
||||
return 1;
|
||||
}
|
||||
// In any other case we didn't do anything
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint Toolbar::callbackInventoryNext(uint dragStatus) {
|
||||
if (!_inventoryEnabled) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dragStatus == kDragStatus_Pressed && _inventoryOffset < _inventoryMaxOffset) {
|
||||
_engine->setAutoRepeatClick(150);
|
||||
_inventoryOffset++;
|
||||
return 1;
|
||||
}
|
||||
// In any other case we didn't do anything
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint Toolbar::callbackViewObject(uint dragStatus) {
|
||||
if (!_inventoryEnabled) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_mouseInViewObject = true;
|
||||
|
||||
if (_inventorySelected == uint(-1)) {
|
||||
// Nothing selected in toolbar
|
||||
return 0;
|
||||
}
|
||||
Inventory::const_iterator inventorySelectedIt = _inventory->begin() + _inventorySelected;
|
||||
Object *selectedObject = *inventorySelectedIt;
|
||||
if (selectedObject == nullptr || selectedObject->viewCallback() == nullptr) {
|
||||
// Nothing to view, the sprite isn't even displayed
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (dragStatus) {
|
||||
case kDragStatus_NoDrag:
|
||||
_backupSelectedObject = selectedObject;
|
||||
_engine->setCursor(181);
|
||||
return 0;
|
||||
case kDragStatus_Pressed:
|
||||
case kDragStatus_Dragging:
|
||||
return 1;
|
||||
case kDragStatus_Finished:
|
||||
// Just clicked
|
||||
_engine->showMouse(false);
|
||||
(*selectedObject->viewCallback())();
|
||||
_engine->showMouse(true);
|
||||
_parentMustRedraw = true;
|
||||
_shortExit = true;
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint Toolbar::callbackOptions(uint dragStatus) {
|
||||
_mouseInOptions = true;
|
||||
|
||||
switch (dragStatus) {
|
||||
case kDragStatus_NoDrag:
|
||||
_backupSelectedObject = _inventory->selectedObject();
|
||||
_engine->setCursor(181);
|
||||
return 0;
|
||||
case kDragStatus_Pressed:
|
||||
case kDragStatus_Dragging:
|
||||
// Nothing to do, we wait release
|
||||
return 0;
|
||||
case kDragStatus_Finished:
|
||||
// Just clicked
|
||||
_engine->displayOptions();
|
||||
_parentMustRedraw = true;
|
||||
_shortExit = true;
|
||||
_engine->setMousePos(Common::Point(320, 240)); // Center of screen
|
||||
// Displaying options hides the mouse
|
||||
_engine->showMouse(true);
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint Toolbar::callbackDocumentation(uint dragStatus) {
|
||||
_mouseInOptions = true;
|
||||
|
||||
switch (dragStatus) {
|
||||
case kDragStatus_NoDrag:
|
||||
case kDragStatus_Pressed:
|
||||
case kDragStatus_Dragging:
|
||||
// Nothing to do, we wait release
|
||||
return 0;
|
||||
case kDragStatus_Finished:
|
||||
// Just clicked
|
||||
if (_engine->displayPlaceDocumentation()) {
|
||||
_parentMustRedraw = true;
|
||||
_shortExit = true;
|
||||
_engine->setMousePos(Common::Point(320, 240)); // Center of screen
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Toolbar::drawToolbar(const Graphics::Surface *original) {
|
||||
if (_position > 60) {
|
||||
_position = 60;
|
||||
}
|
||||
|
||||
if (_position != 0) {
|
||||
// Not entirely drawn, we must copy a part of the original image
|
||||
Common::Rect rct(0, 420, 640, 420 + _position);
|
||||
_destSurface.copyRectToSurface(*original, 0, 0, rct);
|
||||
}
|
||||
|
||||
if (_position == 60) {
|
||||
// Entirely hidden, just stop there, we have nothing to draw
|
||||
return;
|
||||
}
|
||||
|
||||
// Not entirely hidden, we must display the transparent background prepared for us
|
||||
Common::Rect rct(0, _position, 640, 60);
|
||||
_destSurface.copyRectToSurface(_bgSurface, 0, _position, rct);
|
||||
|
||||
// Now draw the various zones on the surface
|
||||
for (Common::Array<Zone>::const_iterator it = _zones.begin(); it != _zones.end(); it++) {
|
||||
if (it->hidden) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16 spriteId = it->secondary ? it->imageSecondary : it->imageMain;
|
||||
if (spriteId == uint16(-1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Common::Rect dst = it->rect;
|
||||
dst.translate(0, _position);
|
||||
|
||||
// Clip the rectangle to fit inside the surface
|
||||
dst.clip(Common::Rect(_destSurface.w, _destSurface.h));
|
||||
|
||||
if (dst.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Graphics::Surface &sprite = _sprites->getSurface(spriteId);
|
||||
_destSurface.transBlitFrom(sprite, Common::Rect(dst.width(), dst.height()), dst,
|
||||
_sprites->getKeyColor(spriteId));
|
||||
}
|
||||
|
||||
// And now draw the object description if needed
|
||||
if (_inventoryEnabled && _inventoryHovered != uint(-1)) {
|
||||
Object *obj = (*_inventory)[_inventoryHovered];
|
||||
|
||||
uint zoneId = _inventoryHovered - _inventoryOffset;
|
||||
if (zoneId >= 8) {
|
||||
// The object is hidden: huh?
|
||||
return;
|
||||
}
|
||||
|
||||
_fontManager->setSurface(&_destSurface);
|
||||
_fontManager->setForeColor(243);
|
||||
_fontManager->setCurrentFont(5);
|
||||
_fontManager->setTransparentBackground(true);
|
||||
const Common::String &objName = (*_messages)[obj->idOBJ()];
|
||||
uint x = 195 - _fontManager->getStrWidth(objName);
|
||||
uint startX = _zones[zoneId].rect.left + kTextOffset;
|
||||
_fontManager->displayStr(x, 38 + _position, objName);
|
||||
_destSurface.hLine(x, 54 + _position, startX - 1, 243); // minus 1 because hLine draws inclusive
|
||||
_destSurface.vLine(startX, 42 + _position, 54 + _position, 243);
|
||||
}
|
||||
}
|
||||
|
||||
bool Toolbar::displayToolbar(const Graphics::Surface *original) {
|
||||
/**
|
||||
* In game there are 2 functions to handle toolbar: one in warp and one in fixed images
|
||||
* This one is the warp one and fixed images have a more asynchronous one during pop-up/down phases
|
||||
* Let's make it simple for now
|
||||
*/
|
||||
|
||||
// WORKAROUND: Set cursor here to be more consistent: it's thumb cursor just before showing until just after showed
|
||||
_engine->setCursor(181);
|
||||
|
||||
_parentMustRedraw = false;
|
||||
_shortExit = false;
|
||||
|
||||
// Prepare the background of the toolbar by making it translucent
|
||||
// Get the lowest part of the image
|
||||
const Graphics::Surface subset = original->getSubArea(Common::Rect(0, original->h - _bgSurface.h,
|
||||
_bgSurface.w, original->h));
|
||||
_engine->makeTranslucent(_bgSurface, subset);
|
||||
|
||||
// WORKAROUND: Reset the inventory status at init to let sprites highlighted until toolbar is hidden
|
||||
_inventorySelected = uint(-1);
|
||||
_inventoryHovered = uint(-1);
|
||||
_zones[12].secondary = true;
|
||||
|
||||
updateZones();
|
||||
|
||||
for (_position = 60; _position > 0; _position--) {
|
||||
// Make the toolbar go up
|
||||
drawToolbar(original);
|
||||
g_system->copyRectToScreen(_destSurface.getPixels(), _destSurface.pitch, 0,
|
||||
original->h - _destSurface.h, _destSurface.w, _destSurface.h);
|
||||
g_system->updateScreen();
|
||||
|
||||
// Slow down animation
|
||||
g_system->delayMillis(10);
|
||||
|
||||
_engine->pollEvents();
|
||||
if (_engine->shouldAbort()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Flush events
|
||||
_engine->clearKeys();
|
||||
_engine->waitMouseRelease();
|
||||
|
||||
handleToolbarEvents(original);
|
||||
if (_engine->shouldAbort()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_shortExit) {
|
||||
return _parentMustRedraw;
|
||||
}
|
||||
|
||||
for (_position = 0; _position <= 60; _position++) {
|
||||
// Make the toolbar go up
|
||||
drawToolbar(original);
|
||||
g_system->copyRectToScreen(_destSurface.getPixels(), _destSurface.pitch, 0,
|
||||
original->h - _destSurface.h, _destSurface.w, _destSurface.h);
|
||||
g_system->updateScreen();
|
||||
|
||||
// Slow down animation
|
||||
g_system->delayMillis(10);
|
||||
|
||||
_engine->pollEvents();
|
||||
if (_engine->shouldAbort()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return _parentMustRedraw;
|
||||
}
|
||||
|
||||
void Toolbar::handleToolbarEvents(const Graphics::Surface *original) {
|
||||
bool mouseInsideToolbar;
|
||||
bool exitToolbar = false;
|
||||
bool redrawToolbar;
|
||||
|
||||
// Don't have anything hovered for now
|
||||
_inventoryHovered = uint(-1);
|
||||
_inventorySelected = uint(-1);
|
||||
_inventory->setSelectedObject(nullptr);
|
||||
_backupSelectedObject = nullptr;
|
||||
|
||||
// Refresh zones because we erased selected object
|
||||
updateZones();
|
||||
|
||||
// No need of original surface because the toolbar is fully displayed
|
||||
drawToolbar(original);
|
||||
|
||||
g_system->copyRectToScreen(_destSurface.getPixels(), _destSurface.pitch, 0,
|
||||
original->h - _destSurface.h, _destSurface.w, _destSurface.h);
|
||||
g_system->updateScreen();
|
||||
|
||||
_engine->setCursor(181);
|
||||
|
||||
mouseInsideToolbar = (_engine->getMousePos().y > 388);
|
||||
|
||||
while (!exitToolbar) {
|
||||
_mouseInOptions = false;
|
||||
_mouseInViewObject = false;
|
||||
|
||||
_engine->pollEvents();
|
||||
if (_engine->shouldAbort()) {
|
||||
exitToolbar = true;
|
||||
break;
|
||||
}
|
||||
|
||||
redrawToolbar = false;
|
||||
if (_engine->checkKeysPressed(2, Common::KEYCODE_ESCAPE, Common::KEYCODE_SPACE) ||
|
||||
_engine->getCurrentMouseButton() == 2) {
|
||||
_engine->waitMouseRelease();
|
||||
exitToolbar = true;
|
||||
break;
|
||||
}
|
||||
|
||||
Common::Point mousePosInToolbar = _engine->getMousePos();
|
||||
mousePosInToolbar -= Common::Point(0, 420);
|
||||
|
||||
if (captureEvent(mousePosInToolbar, _engine->getDragStatus())) {
|
||||
// Something has changed with the zones handling, update zones
|
||||
updateZones();
|
||||
redrawToolbar = true;
|
||||
} else if (_engine->getDragStatus() == kDragStatus_Pressed) {
|
||||
// A click happened and wasn't handled, deselect object
|
||||
_inventorySelected = uint(-1);
|
||||
_inventory->setSelectedObject(nullptr);
|
||||
_engine->setCursor(181);
|
||||
// Reset view object
|
||||
_zones[12].secondary = true;
|
||||
updateZones();
|
||||
redrawToolbar = true;
|
||||
}
|
||||
|
||||
if (!mouseInsideToolbar) {
|
||||
mouseInsideToolbar = (_engine->getMousePos().y > 388);
|
||||
} else if (_engine->getMousePos().y <= 388) {
|
||||
// mouseInsideToolbar is true and the mouse is outside the toolbar
|
||||
exitToolbar = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_engine->getCurrentMouseButton() == 1) {
|
||||
// When the mouse button is down, nothing is selected
|
||||
// It's selected on release
|
||||
_inventory->setSelectedObject(nullptr);
|
||||
}
|
||||
|
||||
if (_backupSelectedObject != nullptr && !(_mouseInOptions || _mouseInViewObject) &&
|
||||
!_engine->getCurrentMouseButton()) {
|
||||
_inventory->setSelectedObject(_backupSelectedObject);
|
||||
_engine->setCursor(_backupSelectedObject->idSl());
|
||||
_backupSelectedObject = nullptr;
|
||||
}
|
||||
|
||||
// Hover the inventory objects
|
||||
if (_inventory->selectedObject() == nullptr /* || _inventoryButtonDragging */) {
|
||||
// The 2nd above condition is maybe useless because when the mouse button is down the selected object is always null
|
||||
bool shouldHover = false;
|
||||
Common::Array<Zone>::const_iterator zoneIt = hitTestZones(mousePosInToolbar);
|
||||
uint zoneId = zoneIt - _zones.begin();
|
||||
uint inventoryId = zoneId + _inventoryOffset;
|
||||
if (zoneId < 8 && inventoryId < _inventory->size() && (*_inventory)[inventoryId] != nullptr) {
|
||||
// It's the inventory
|
||||
shouldHover = true;
|
||||
if (_inventoryHovered != inventoryId && (*_inventory)[inventoryId]->valid()) {
|
||||
// It's not the one currently hovered and it's a valid object
|
||||
_inventoryHovered = inventoryId;
|
||||
redrawToolbar = true;
|
||||
}
|
||||
}
|
||||
if (!shouldHover && _inventoryHovered != uint(-1) && !_mouseInViewObject) {
|
||||
// Remove hovering
|
||||
_inventoryHovered = uint(-1);
|
||||
_inventorySelected = uint(-1);
|
||||
updateZones();
|
||||
if (!_inventory->selectedObject()) {
|
||||
// Reset back the cursor if nothing is selected
|
||||
_engine->setCursor(181);
|
||||
}
|
||||
// Remove view
|
||||
_zones[12].secondary = true;
|
||||
redrawToolbar = true;
|
||||
}
|
||||
_inventoryButtonDragging = false;
|
||||
}
|
||||
|
||||
if (_parentMustRedraw) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (redrawToolbar) {
|
||||
drawToolbar(original);
|
||||
g_system->copyRectToScreen(_destSurface.getPixels(), _destSurface.pitch, 0,
|
||||
original->h - _destSurface.h, _destSurface.w, _destSurface.h);
|
||||
}
|
||||
|
||||
g_system->updateScreen();
|
||||
g_system->delayMillis(10);
|
||||
}
|
||||
|
||||
// Hide description when finished and selected object
|
||||
// WORKAROUND: moved to the start to keep the selected object hilighted until the toolbar disappearance
|
||||
}
|
||||
|
||||
} // End of namespace Versailles
|
||||
} // End of namespace CryOmni3D
|
||||
117
engines/cryomni3d/versailles/toolbar.h
Normal file
117
engines/cryomni3d/versailles/toolbar.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRYOMNI3D_VERSAILLES_TOOLBAR_H
|
||||
#define CRYOMNI3D_VERSAILLES_TOOLBAR_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/rect.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "cryomni3d/font_manager.h"
|
||||
#include "cryomni3d/objects.h"
|
||||
#include "cryomni3d/sprites.h"
|
||||
|
||||
namespace CryOmni3D {
|
||||
class CryOmni3DEngine;
|
||||
|
||||
namespace Versailles {
|
||||
|
||||
|
||||
class Toolbar {
|
||||
public:
|
||||
Toolbar() : _sprites(nullptr), _fontManager(nullptr), _inventory(nullptr),
|
||||
_messages(nullptr), _engine(nullptr), _inventoryEnabled(true), _inventoryMaxOffset(0),
|
||||
_inventoryOffset(0), _inventoryHovered(uint(-1)), _inventorySelected(uint(-1)), _backupSelectedObject(nullptr),
|
||||
_mouseInOptions(false), _mouseInViewObject(false), _inventoryButtonDragging(false), _parentMustRedraw(false),
|
||||
_shortExit(false), _position(60) { }
|
||||
~Toolbar();
|
||||
|
||||
void init(const Sprites *sprites, FontManager *fontManager,
|
||||
const Common::Array<Common::String> *messages, Inventory *inventory, CryOmni3DEngine *engine);
|
||||
|
||||
Graphics::Surface &getBackgroundSurface() { return _bgSurface; }
|
||||
bool displayToolbar(const Graphics::Surface *original);
|
||||
void inventoryChanged(uint newPosition);
|
||||
uint inventoryOffset() const { return _inventoryOffset; }
|
||||
void setInventoryOffset(uint offset) { _inventoryOffset = offset; }
|
||||
void setInventoryEnabled(bool enabled) { _inventoryEnabled = enabled; }
|
||||
|
||||
private:
|
||||
typedef uint(Toolbar::*ZoneCallback)(uint dragStatus);
|
||||
struct Zone {
|
||||
Common::Rect rect;
|
||||
uint16 imageMain;
|
||||
uint16 imageSecondary;
|
||||
ZoneCallback callback;
|
||||
bool secondary;
|
||||
bool hidden;
|
||||
};
|
||||
Common::Array<Zone> _zones;
|
||||
const Sprites *_sprites;
|
||||
FontManager *_fontManager;
|
||||
const Common::Array<Common::String> *_messages;
|
||||
Inventory *_inventory;
|
||||
CryOmni3DEngine *_engine;
|
||||
|
||||
static const uint kTextOffset = 13;
|
||||
|
||||
void addZone(uint16 cursorMainId, uint16 cursorSecondaryId, Common::Point position,
|
||||
ZoneCallback callback);
|
||||
void updateZones();
|
||||
Common::Array<Zone>::const_iterator hitTestZones(const Common::Point &mousePos) const;
|
||||
uint captureEvent(const Common::Point &mousePos, uint dragStatus);
|
||||
void drawToolbar(const Graphics::Surface *original);
|
||||
void handleToolbarEvents(const Graphics::Surface *original);
|
||||
|
||||
bool _inventoryEnabled;
|
||||
uint _inventoryMaxOffset;
|
||||
uint _inventoryOffset;
|
||||
uint _inventoryHovered;
|
||||
uint _inventorySelected;
|
||||
|
||||
Object *_backupSelectedObject;
|
||||
bool _mouseInOptions;
|
||||
bool _mouseInViewObject;
|
||||
bool _inventoryButtonDragging;
|
||||
|
||||
bool _parentMustRedraw;
|
||||
bool _shortExit;
|
||||
uint _position;
|
||||
|
||||
Graphics::Surface _bgSurface;
|
||||
Graphics::ManagedSurface _destSurface;
|
||||
|
||||
template<uint N>
|
||||
uint callbackInventory(uint dragStatus) { return callbackInventory(N, dragStatus); }
|
||||
uint callbackInventory(uint invId, uint dragStatus);
|
||||
uint callbackInventoryPrev(uint dragStatus);
|
||||
uint callbackInventoryNext(uint dragStatus);
|
||||
uint callbackViewObject(uint dragStatus);
|
||||
uint callbackOptions(uint dragStatus);
|
||||
uint callbackDocumentation(uint dragStatus);
|
||||
};
|
||||
|
||||
} // End of namespace Versailles
|
||||
} // End of namespace CryOmni3D
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user