From 48f83b7bb48a1625f6c195e396f8d40047f50915 Mon Sep 17 00:00:00 2001 From: athrxx Date: Mon, 1 Aug 2011 22:50:51 +0200 Subject: KYRA: (EOB) - implement npc sequences and fix some bugs --- devtools/create_kyradat/create_kyradat.cpp | 46 +++++ devtools/create_kyradat/create_kyradat.h | 16 ++ devtools/create_kyradat/extract.cpp | 2 +- devtools/create_kyradat/games.cpp | 16 ++ devtools/create_kyradat/tables.cpp | 112 ++++++++++++ dists/engine-data/kyra.dat | Bin 458977 -> 460294 bytes engines/kyra/eob1.cpp | 271 ++++++++++++++++++++++++++++- engines/kyra/eob1.h | 26 ++- engines/kyra/eob2.cpp | 117 ++++++------- engines/kyra/eob2.h | 3 +- engines/kyra/eobcommon.cpp | 101 +++++++++-- engines/kyra/eobcommon.h | 27 ++- engines/kyra/gui_eob.cpp | 64 +++++-- engines/kyra/gui_eob.h | 2 + engines/kyra/items_eob.cpp | 59 ++++++- engines/kyra/lol.cpp | 5 +- engines/kyra/loleobbase.cpp | 12 +- engines/kyra/loleobbase.h | 4 + engines/kyra/magic_eob.cpp | 13 +- engines/kyra/resource.h | 16 ++ engines/kyra/script_eob.cpp | 35 +++- engines/kyra/script_eob.h | 7 +- engines/kyra/sprites_eob.cpp | 6 +- engines/kyra/staticres_eob.cpp | 23 ++- engines/kyra/text_eob.cpp | 70 +++++--- 25 files changed, 884 insertions(+), 169 deletions(-) diff --git a/devtools/create_kyradat/create_kyradat.cpp b/devtools/create_kyradat/create_kyradat.cpp index 276564bc64..68fc8cc5b7 100644 --- a/devtools/create_kyradat/create_kyradat.cpp +++ b/devtools/create_kyradat/create_kyradat.cpp @@ -409,6 +409,22 @@ const ExtractFilename extractFilenames[] = { { kEob1MonsterDistAttSfx17, kTypeRawData, false }, { kEob1TurnUndeadString, kTypeStringList, true }, + { kEob1NpcShpData, kTypeRawData, false }, + { kEob1NpcSubShpIndex1, kTypeRawData, false }, + { kEob1NpcSubShpIndex2, kTypeRawData, false }, + { kEob1NpcSubShpY, kTypeRawData, false }, + { kEob1Npc0Strings, kTypeStringList, true }, + { kEob1Npc11Strings, kTypeStringList, true }, + { kEob1Npc12Strings, kTypeStringList, true }, + { kEob1Npc21Strings, kTypeStringList, true }, + { kEob1Npc22Strings, kTypeStringList, true }, + { kEob1Npc31Strings, kTypeStringList, true }, + { kEob1Npc32Strings, kTypeStringList, true }, + { kEob1Npc4Strings, kTypeStringList, true }, + { kEob1Npc5Strings, kTypeStringList, true }, + { kEob1Npc6Strings, kTypeStringList, true }, + { kEob1Npc7Strings, kTypeStringList, true }, + // EYE OF THE BEHOLDER II { kEob2MainMenuStrings, kTypeStringList, true }, @@ -1624,6 +1640,36 @@ const char *getIdString(const int id) { return "kEob1MonsterDistAttSfx17"; case kEob1TurnUndeadString: return "kEob1TurnUndeadString"; + case kEob1NpcShpData: + return "kEob1NpcShpData"; + case kEob1NpcSubShpIndex1: + return "kEob1NpcSubShpIndex1"; + case kEob1NpcSubShpIndex2: + return "kEob1NpcSubShpIndex2"; + case kEob1NpcSubShpY: + return "kEob1NpcSubShpY"; + case kEob1Npc0Strings: + return "kEob1Npc0Strings"; + case kEob1Npc11Strings: + return "kEob1Npc11Strings"; + case kEob1Npc12Strings: + return "kEob1Npc12Strings"; + case kEob1Npc21Strings: + return "kEob1Npc21Strings"; + case kEob1Npc22Strings: + return "kEob1Npc22Strings"; + case kEob1Npc31Strings: + return "kEob1Npc31Strings"; + case kEob1Npc32Strings: + return "kEob1Npc32Strings"; + case kEob1Npc4Strings: + return "kEob1Npc4Strings"; + case kEob1Npc5Strings: + return "kEob1Npc5Strings"; + case kEob1Npc6Strings: + return "kEob1Npc6Strings"; + case kEob1Npc7Strings: + return "kEob1Npc7Strings"; case kEob2MainMenuStrings: return "kEob2MainMenuStrings"; case kEob2IntroStrings: diff --git a/devtools/create_kyradat/create_kyradat.h b/devtools/create_kyradat/create_kyradat.h index a587147974..54fd91b394 100644 --- a/devtools/create_kyradat/create_kyradat.h +++ b/devtools/create_kyradat/create_kyradat.h @@ -410,6 +410,22 @@ enum kExtractID { kEob1MonsterDistAttSfx17, kEob1TurnUndeadString, + kEob1NpcShpData, + kEob1NpcSubShpIndex1, + kEob1NpcSubShpIndex2, + kEob1NpcSubShpY, + kEob1Npc0Strings, + kEob1Npc11Strings, + kEob1Npc12Strings, + kEob1Npc21Strings, + kEob1Npc22Strings, + kEob1Npc31Strings, + kEob1Npc32Strings, + kEob1Npc4Strings, + kEob1Npc5Strings, + kEob1Npc6Strings, + kEob1Npc7Strings, + kEob2MainMenuStrings, kEob2IntroStrings, kEob2IntroCPSFiles, diff --git a/devtools/create_kyradat/extract.cpp b/devtools/create_kyradat/extract.cpp index c9ece8223a..b330c469c6 100644 --- a/devtools/create_kyradat/extract.cpp +++ b/devtools/create_kyradat/extract.cpp @@ -1114,7 +1114,7 @@ bool extractEobNpcData(PAKFile &out, const ExtractInformation *info, const byte WRITE_BE_UINT32(dst, READ_LE_UINT32(src)); src += 4; dst += 4; // skipping lots of zero space - src += 60; + src += 64; WRITE_BE_UINT32(dst, READ_LE_UINT32(src)); src += 4; dst += 4; for (int ii = 0; ii < 27; ii++) { diff --git a/devtools/create_kyradat/games.cpp b/devtools/create_kyradat/games.cpp index 4ab12028c2..5f710507f4 100644 --- a/devtools/create_kyradat/games.cpp +++ b/devtools/create_kyradat/games.cpp @@ -1065,6 +1065,22 @@ const int eob1FloppyNeed[] = { kEob1MonsterDistAttSfx17, kEob1TurnUndeadString, + kEob1NpcShpData, + kEob1NpcSubShpIndex1, + kEob1NpcSubShpIndex2, + kEob1NpcSubShpY, + kEob1Npc0Strings, + kEob1Npc11Strings, + kEob1Npc12Strings, + kEob1Npc21Strings, + kEob1Npc22Strings, + kEob1Npc31Strings, + kEob1Npc32Strings, + kEob1Npc4Strings, + kEob1Npc5Strings, + kEob1Npc6Strings, + kEob1Npc7Strings, + kEobBasePryDoorStrings, kEobBaseWarningStrings, diff --git a/devtools/create_kyradat/tables.cpp b/devtools/create_kyradat/tables.cpp index 46239c2bee..663652d4be 100644 --- a/devtools/create_kyradat/tables.cpp +++ b/devtools/create_kyradat/tables.cpp @@ -2368,6 +2368,102 @@ const ExtractEntrySearchData kEob1TurnUndeadStringProvider[] = { EXTRACT_END_ENTRY }; +const ExtractEntrySearchData kEob1NpcShpDataProvider[] = { + { UNK_LANG, kPlatformPC, { 0x0000004C, 0x00000A42, { { 0x70, 0x21, 0x85, 0x8C, 0xD4, 0x04, 0xAA, 0x20, 0x1D, 0x0E, 0x9D, 0xB7, 0x74, 0x58, 0xCC, 0x0C } } } }, + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob1NpcSubShpIndex1Provider[] = { + { UNK_LANG, kPlatformPC, { 0x00000006, 0x00000035, { { 0x9A, 0x83, 0xF9, 0xA4, 0x27, 0xBA, 0xFC, 0xD2, 0xDE, 0x03, 0x65, 0xF2, 0xFA, 0x37, 0xDA, 0xF1 } } } }, + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob1NpcSubShpIndex2Provider[] = { + { UNK_LANG, kPlatformPC, { 0x00000006, 0x00000051, { { 0x7E, 0xAC, 0x0E, 0x54, 0x59, 0x5D, 0xF6, 0x53, 0x03, 0x22, 0x1D, 0xC7, 0xFC, 0x16, 0xC8, 0x88 } } } }, + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob1NpcSubShpYProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000006, 0x00000143, { { 0xC1, 0xED, 0x93, 0x5E, 0x84, 0xCE, 0x48, 0xCF, 0x4C, 0xF3, 0x9C, 0x93, 0xBF, 0xFE, 0xB8, 0x6F } } } }, + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob1Npc0StringsProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x00000044, 0x000016E2, { { 0x7C, 0x28, 0x72, 0xC9, 0x57, 0xF5, 0xAB, 0x02, 0xD1, 0x42, 0xE8, 0xA3, 0xF9, 0x33, 0x70, 0xEE } } } }, + { DE_DEU, kPlatformUnknown, { 0x00000050, 0x00001B13, { { 0x69, 0x05, 0xEB, 0xB6, 0x86, 0x81, 0xAC, 0x09, 0x53, 0x35, 0x4D, 0x55, 0xF3, 0x13, 0x6F, 0xC0 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob1Npc11StringsProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x0000001B, 0x00000928, { { 0x86, 0x08, 0x95, 0x6B, 0xBF, 0x12, 0x2D, 0xF9, 0x62, 0x25, 0xD9, 0xAE, 0x25, 0x10, 0xDF, 0xDC } } } }, + { DE_DEU, kPlatformUnknown, { 0x0000001A, 0x000008DB, { { 0xBD, 0xBB, 0x48, 0x8E, 0x04, 0x7D, 0xE4, 0x78, 0xBB, 0x59, 0x6E, 0x86, 0xE1, 0x06, 0x27, 0x50 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob1Npc12StringsProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x00000016, 0x0000079C, { { 0x22, 0x57, 0x3A, 0x9C, 0x7C, 0xDB, 0x55, 0xD0, 0x9C, 0x84, 0x28, 0xA6, 0x9D, 0x40, 0x38, 0x6E } } } }, + { DE_DEU, kPlatformUnknown, { 0x00000014, 0x000006ED, { { 0x88, 0x1C, 0x09, 0x61, 0x5D, 0x9D, 0xDE, 0x8A, 0x54, 0x1C, 0x40, 0xCF, 0x28, 0x2B, 0x52, 0x9D } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob1Npc21StringsProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x00000014, 0x000006FD, { { 0x55, 0x77, 0x2F, 0xB0, 0xB3, 0x2D, 0x81, 0x29, 0xDE, 0x71, 0x83, 0x41, 0x06, 0x5B, 0x72, 0x21 } } } }, + { DE_DEU, kPlatformUnknown, { 0x00000015, 0x00000748, { { 0x3E, 0x15, 0x27, 0xFD, 0x76, 0xFB, 0x14, 0x8C, 0xF6, 0x14, 0x3E, 0x20, 0x0A, 0x04, 0xF5, 0x32 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob1Npc22StringsProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x0000000F, 0x000004D4, { { 0xE5, 0x97, 0x06, 0x45, 0x6A, 0xAC, 0x96, 0x6D, 0x0A, 0xC9, 0xDF, 0x8F, 0x96, 0x2D, 0x01, 0x5D } } } }, + { DE_DEU, kPlatformUnknown, { 0x0000000D, 0x00000439, { { 0x87, 0xCB, 0x17, 0xD2, 0xC8, 0x7F, 0x34, 0xDA, 0x82, 0x30, 0xB2, 0x68, 0xB0, 0x10, 0xD9, 0x52 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob1Npc31StringsProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x00000011, 0x00000597, { { 0x5C, 0xEB, 0x0A, 0xE6, 0xB1, 0x37, 0x0E, 0x8F, 0x14, 0xB4, 0x68, 0x86, 0xE5, 0xD2, 0xDE, 0xC7 } } } }, + { DE_DEU, kPlatformUnknown, { 0x00000012, 0x00000603, { { 0x8E, 0x68, 0x55, 0xCD, 0x29, 0x1E, 0x3C, 0x06, 0x7B, 0x97, 0xE1, 0x07, 0x49, 0x09, 0xF0, 0x57 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob1Npc32StringsProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x00000020, 0x00000AE4, { { 0xED, 0x09, 0x04, 0xEC, 0xE3, 0x43, 0xDA, 0xEE, 0x5D, 0x78, 0x32, 0x63, 0x68, 0xFC, 0x4F, 0x9E } } } }, + { DE_DEU, kPlatformUnknown, { 0x00000020, 0x00000B13, { { 0x87, 0x40, 0x88, 0xA5, 0xE2, 0x6F, 0x83, 0xBC, 0x99, 0x2B, 0xD3, 0xF5, 0x8D, 0x6B, 0x6E, 0x7D } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob1Npc4StringsProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x0000000D, 0x0000043C, { { 0x2C, 0xE7, 0xE5, 0xAA, 0xF3, 0x50, 0xA8, 0x6D, 0xC2, 0xC6, 0x88, 0xFE, 0x12, 0x96, 0xFE, 0x54 } } } }, + { DE_DEU, kPlatformUnknown, { 0x00000014, 0x00000720, { { 0xF8, 0x58, 0x9A, 0xDB, 0xE5, 0x3F, 0x67, 0x53, 0x1F, 0x27, 0x2E, 0x8D, 0x6E, 0xAD, 0x45, 0xF5 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob1Npc5StringsProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x00000021, 0x00000ABC, { { 0xF1, 0xB5, 0x9E, 0x51, 0x9E, 0xF8, 0x84, 0x95, 0x55, 0x55, 0xE7, 0xDF, 0x36, 0xE1, 0x78, 0x9A } } } }, + { DE_DEU, kPlatformUnknown, { 0x0000001D, 0x00000A8C, { { 0x4A, 0xAE, 0x5B, 0x3B, 0xAD, 0x18, 0x91, 0x3F, 0xC9, 0x5A, 0x82, 0x5D, 0xA7, 0x06, 0x1A, 0xAE } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob1Npc6StringsProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x00000011, 0x00000612, { { 0x1B, 0xE2, 0x23, 0xD9, 0x00, 0x5C, 0xB9, 0x54, 0xCE, 0xA7, 0x6A, 0x51, 0xF6, 0xBB, 0x8A, 0xC9 } } } }, + { DE_DEU, kPlatformUnknown, { 0x00000012, 0x00000647, { { 0x6C, 0x3F, 0xE2, 0xD0, 0xB0, 0x75, 0x2D, 0x73, 0xEE, 0x6F, 0x17, 0x74, 0xAA, 0x7D, 0xA2, 0x21 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob1Npc7StringsProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x00000018, 0x00000777, { { 0x60, 0xB4, 0x17, 0x72, 0x89, 0x87, 0x47, 0xE3, 0xD9, 0xC3, 0x59, 0x16, 0xFD, 0x03, 0x31, 0xD4 } } } }, + { DE_DEU, kPlatformUnknown, { 0x00000016, 0x000007B6, { { 0xAE, 0xB6, 0x3C, 0x14, 0x2B, 0x34, 0xB8, 0x7C, 0xCF, 0x87, 0xDA, 0x70, 0xBF, 0x0D, 0xAB, 0xE2 } } } }, + + EXTRACT_END_ENTRY +}; const ExtractEntrySearchData kEob2MainMenuStringsProvider[] = { { EN_ANY, kPlatformUnknown, { 0x0000005F, 0x000017BE, { { 0x77, 0x8A, 0x50, 0x9F, 0x42, 0xD8, 0x00, 0x05, 0x60, 0x2A, 0x80, 0x25, 0x00, 0xDC, 0x7C, 0x92 } } } }, @@ -3725,6 +3821,22 @@ const ExtractEntry extractProviders[] = { { kEob1MonsterDistAttSfx17, kEob1MonsterDistAttSfx17Provider }, { kEob1TurnUndeadString, kEob1TurnUndeadStringProvider }, + { kEob1NpcShpData, kEob1NpcShpDataProvider }, + { kEob1NpcSubShpIndex1, kEob1NpcSubShpIndex1Provider }, + { kEob1NpcSubShpIndex2, kEob1NpcSubShpIndex2Provider }, + { kEob1NpcSubShpY, kEob1NpcSubShpYProvider }, + { kEob1Npc0Strings, kEob1Npc0StringsProvider }, + { kEob1Npc11Strings, kEob1Npc11StringsProvider }, + { kEob1Npc12Strings, kEob1Npc12StringsProvider }, + { kEob1Npc21Strings, kEob1Npc21StringsProvider }, + { kEob1Npc22Strings, kEob1Npc22StringsProvider }, + { kEob1Npc31Strings, kEob1Npc31StringsProvider }, + { kEob1Npc32Strings, kEob1Npc32StringsProvider }, + { kEob1Npc4Strings, kEob1Npc4StringsProvider }, + { kEob1Npc5Strings, kEob1Npc5StringsProvider }, + { kEob1Npc6Strings, kEob1Npc6StringsProvider }, + { kEob1Npc7Strings, kEob1Npc7StringsProvider }, + { kEob2MainMenuStrings, kEob2MainMenuStringsProvider }, { kEob2IntroStrings, kEob2IntroStringsProvider }, { kEob2IntroCPSFiles, kEob2IntroCPSFilesProvider }, diff --git a/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat index 2128a448b6..3b79f0406d 100644 Binary files a/dists/engine-data/kyra.dat and b/dists/engine-data/kyra.dat differ diff --git a/engines/kyra/eob1.cpp b/engines/kyra/eob1.cpp index d12283f140..95052311ff 100644 --- a/engines/kyra/eob1.cpp +++ b/engines/kyra/eob1.cpp @@ -46,6 +46,19 @@ Common::Error EobEngine::init() { _itemsOverlay = _res->fileData("ITEMRMP.VGA", 0); + static const uint16 wX[] = { 285, 139 }; + static const uint8 wY[] = { 189, 162 }; + static const uint16 wW[] = { 31, 31 }; + + _dialogueButtonLabelCol1 = 9; + _dialogueButtonLabelCol2 = 15; + _dialogueButtonW = 95; + _dialogueButtonH = 9; + _waitButtonPresX = wX; + _waitButtonPresY = wY; + _waitButtonPresW = wW; + _waitButtonReverveW = 7; + _bkgColor_1 = 132; _color1_1 = 135; _color2_1 = 130; @@ -82,11 +95,227 @@ void EobEngine::startupLoad() { _sound->loadSoundFile("ADLIB"); } -void EobEngine::npcSequence(int npcIndex) { - error("EobEngine::npcSequence(): unimplemented"); +void EobEngine::drawNpcScene(int npcIndex) { + _screen->copyRegion(0, 0, 0, 0, 176, 120, 6, 0, Screen::CR_NO_P_CHECK); + switch (npcIndex) { + case 0: + encodeDrawNpcSeqShape(2, 88, 104); + break; + + case 1: + if (_npcSequenceSub == -1) { + encodeDrawNpcSeqShape(0, 88, 104); + } else { + encodeDrawNpcSeqShape(0, 60, 104); + encodeDrawNpcSeqShape(5, 116, 104); + } + break; + + case 2: + if (_npcSequenceSub == -1) { + encodeDrawNpcSeqShape(3, 88, 104); + } else { + encodeDrawNpcSeqShape(3, 60, 104); + encodeDrawNpcSeqShape(_npcSubShpIndex1[_npcSequenceSub], 116, 104); + encodeDrawNpcSeqShape(_npcSubShpIndex2[_npcSequenceSub], 116, _npcSubShpY[_npcSequenceSub]); + } + break; + + case 3: + encodeDrawNpcSeqShape(7, 88, 104); + break; + + case 4: + encodeDrawNpcSeqShape(6, 88, 104); + break; + + case 5: + encodeDrawNpcSeqShape(18, 88, 88); + break; + + case 6: + encodeDrawNpcSeqShape(17, 88, 104); + break; + + case 7: + encodeDrawNpcSeqShape(4, 88, 104); + break; + + default: + break; + } +} +void EobEngine::encodeDrawNpcSeqShape(int npcIndex, int drawX, int drawY) { + const uint8 *shpDef = &_npcShpData[npcIndex << 2]; + _screen->_curPage = 2; + const uint8 *shp = _screen->encodeShape(shpDef[0], shpDef[1], shpDef[2], shpDef[3]); + _screen->_curPage = 0; + _screen->drawShape(0, shp, drawX - (shp[2] << 2), drawY - shp[1], 5); + delete[] shp; } +#define DLG2(txt, buttonstr) (runDialogue(txt, 0, _npc##buttonstr##Strings[0], _npc##buttonstr##Strings[1], 0) - 1) +#define DLG3(txt, buttonstr) (runDialogue(txt, 1, _npc##buttonstr##Strings[0], _npc##buttonstr##Strings[1], _npc##buttonstr##Strings[2], 0) - 1) +#define DLG2A3(cond, txt, buttonstr1, buttonstr2) ((cond) ? (DLG2(txt, buttonstr1) ? 2 : 0) : DLG3(txt, buttonstr2)) +#define TXT(txt) _txt->printDialogueText(txt, _moreStrings[0]) + +void EobEngine::runNpcDialogue(int npcIndex) { + int r = 0; + int a = 0; + Item itm = 0; + + switch (npcIndex) { + case 0: + for (r = 1; r == 1; ) { + gui_drawDialogueBox(); + r = DLG2A3(checkScriptFlag(0x2000), 8, 12, 11); + if (r == 1) { + TXT(1); + setScriptFlag(0x2000); + } else if (r == 0) { + npcJoinDialogue(6, 12, 23, 2); + setScriptFlag(0x4000); + } + } + break; + + case 1: + if (!checkScriptFlag(0x10000)) { + if (checkScriptFlag(0x8000)) { + a = 1; + } else { + setScriptFlag(0x8000); + r = DLG2(3, 21); + } + if (!r) + r = DLG2(a ? 13 : 4, 22); + + if (!r) { + for (a = 0; a < 6; a++) + createItemOnCurrentBlock(55); + createItemOnCurrentBlock(62); + setScriptFlag(0x10000); + TXT(6); + npcJoinDialogue(7, 7, 29, 30); + } else { + TXT(5); + } + r = 1; + } + + if (!checkScriptFlag(0x80000)) { + for (a = 0; a < 6; a++) { + if (testCharacter(a, 1) && _characters[a].portrait == -9) + break; + } + if (a != 6) { + TXT(25); + TXT(26); + setScriptFlag(0x80000); + r = 1; + } + } + + if (!checkScriptFlag(0x100000)) { + if (deletePartyItems(6, -1)) { + TXT(28); + createItemOnCurrentBlock(32); + setScriptFlag(0x100000); + r = 1; + } + } + + if (!r) + _txt->printDialogueText(_npc0Strings[0], true); + + break; + + case 2: + if (checkScriptFlag(0x10000)) { + if (checkScriptFlag(0x20000)) { + TXT(11); + } else { + r = DLG2A3(!countResurrectionCandidates(), 9, 31, 32); + if (r < 2) { + if (r == 0) + healParty(); + else + resurrectionSelectDialogue(); + setScriptFlag(0x20000); + } + } + } else { + TXT(24); + } + break; + + case 3: + if (!DLG2(18, 4)) { + setScriptFlag(0x8400000); + for (a = 0; a < 30; a++) { + if (_monsters[a].mode == 8) + _monsters[a].mode = 5; + } + } else if (deletePartyItems(49, -1)) { + TXT(20); + setScriptFlag(0x400000); + } else { + TXT(19); + } + break; + + case 4: + r = DLG3(14, 5); + if (r == 0) + setScriptFlag(0x200000); + else if (r == 1) + TXT(15); + setScriptFlag(0x800000); + break; + + case 5: + if (!DLG2(16, 6)) { + TXT(17); + for (a = 0; a < 6; a++) { + for (r = 0; r < 2; r++) { + itm = _characters[a].inventory[r]; + if (itm && (_items[itm].type < 51 || _items[itm].type > 56)) { + _characters[a].inventory[r] = 0; + setItemPosition((Item*)&_levelBlockProperties[_currentBlock].drawObjects, _currentBlock, itm, _dropItemDirIndex[(_currentDirection << 2) + rollDice(1, 2, -1)]); + } + } + } + } + setScriptFlag(0x2000000); + break; + + case 6: + TXT(21); + setScriptFlag(0x1000000); + break; + + case 7: + r = DLG3(22, 7); + if (r < 2) { + if (r == 0) + npcJoinDialogue(8, 27, 44, 45); + else + TXT(31); + setScriptFlag(0x4000000); + } + break; + + default: + break; + } +} + +#undef TXT +#undef DLG2 +#undef DLG3 +#undef DLG2A3 + void EobEngine::updateUsedCharacterHandItem(int charIndex, int slot) { EobItem *itm = &_items[_characters[charIndex].inventory[slot]]; if (itm->type == 48) { @@ -269,6 +498,44 @@ bool EobEngine::checkPartyStatusExtra() { return true; } +int EobEngine::resurrectionSelectDialogue() { + gui_drawDialogueBox(); + _txt->printDialogueText(_npc0Strings[1]); + + int r = _rrId[runDialogue(-1, 1, _rrNames[0], _rrNames[1], _rrNames[2], _rrNames[3], _rrNames[4], _rrNames[5], _rrNames[6], _rrNames[7], _rrNames[8]) - 1]; + + if (r < 0) { + r = -r; + deletePartyItems(33, r); + _npcSequenceSub = r - 1; + drawNpcScene(2); + npcJoinDialogue(_npcSequenceSub, 32 + (_npcSequenceSub << 1), -1, 33 + (_npcSequenceSub << 1)); + } else { + _characters[r].hitPointsCur = _characters[r].hitPointsMax; + } + + return 1; +} + +void EobEngine::healParty() { + int cnt = rollDice(1, 3, 2); + for (int i = 0; i < 6 && cnt; i++) { + if (testCharacter(i, 3)) + continue; + + _characters[i].flags &= ~4; + neutralizePoison(i); + + if (_characters[i].hitPointsCur >= _characters[i].hitPointsMax) + continue; + + cnt--; + _characters[i].hitPointsCur += rollDice(1, 8, 9); + if (_characters[i].hitPointsCur > _characters[i].hitPointsMax) + _characters[i].hitPointsCur = _characters[i].hitPointsMax; + } +} + uint32 EobEngine::convertSpellFlagToEob2Format(uint32 flag, int ignoreInvisibility) { uint32 res = 0; if (flag & 0x01) diff --git a/engines/kyra/eob1.h b/engines/kyra/eob1.h index 8d41118e52..8b805c00e8 100644 --- a/engines/kyra/eob1.h +++ b/engines/kyra/eob1.h @@ -56,10 +56,25 @@ private: void seq_playFinale(); // characters - void npcSequence(int npcIndex); - - //const char *const *_npc1Strings; - //const char *const *_npc2Strings; + void drawNpcScene(int npcIndex); + void encodeDrawNpcSeqShape(int npcIndex, int drawX, int drawY); + void runNpcDialogue(int npcIndex); + + const uint8 *_npcShpData; + const uint8 *_npcSubShpIndex1; + const uint8 *_npcSubShpIndex2; + const uint8 *_npcSubShpY; + const char *const *_npc0Strings; + const char *const *_npc11Strings; + const char *const *_npc12Strings; + const char *const *_npc21Strings; + const char *const *_npc22Strings; + const char *const *_npc31Strings; + const char *const *_npc32Strings; + const char *const *_npc4Strings; + const char *const *_npc5Strings; + const char *const *_npc6Strings; + const char *const *_npc7Strings; // items void updateUsedCharacterHandItem(int charIndex, int slot); @@ -92,6 +107,9 @@ private: // Misc bool checkPartyStatusExtra(); + int resurrectionSelectDialogue(); + void healParty(); + uint32 convertSpellFlagToEob2Format(uint32 flag, int ignoreInvisibility); uint32 convertCharacterEffectFlagToEob2Format(uint32 flag); }; diff --git a/engines/kyra/eob2.cpp b/engines/kyra/eob2.cpp index cd306863ba..2b4cf46afe 100644 --- a/engines/kyra/eob2.cpp +++ b/engines/kyra/eob2.cpp @@ -52,6 +52,19 @@ Common::Error DarkMoonEngine::init() { _monsterProps = new EobMonsterProperty[10]; + static const uint16 wX[] = { 221, 76 }; + static const uint8 wY[] = { 189, 162 }; + static const uint16 wW[] = { 95, 95 }; + + _dialogueButtonLabelCol1 = 9; + _dialogueButtonLabelCol2 = 15; + _dialogueButtonW = 95; + _dialogueButtonH = 9; + _waitButtonPresX = wX; + _waitButtonPresY = wY; + _waitButtonPresW = wW; + _waitButtonReverveW = 7; + _bkgColor_1 = 183; _color1_1 = 186; _color2_1 = 181; @@ -77,11 +90,8 @@ void DarkMoonEngine::startupNew() { EobCoreEngine::startupNew(); } -void DarkMoonEngine::npcSequence(int npcIndex) { - _screen->loadEobBitmap("OUTTAKE", 5, 3); - _screen->copyRegion(0, 0, 0, 0, 176, 120, 0, 6, Screen::CR_NO_P_CHECK); +void DarkMoonEngine::drawNpcScene(int npcIndex) { const uint8 *shpDef = &_npcShpData[npcIndex << 3]; - for (int i = npcIndex; i != 255; i = shpDef[7]) { shpDef = &_npcShpData[i << 3]; _screen->_curPage = 2; @@ -90,15 +100,9 @@ void DarkMoonEngine::npcSequence(int npcIndex) { _screen->drawShape(0, shp, 88 + shpDef[5] - (shp[2] << 2), 104 + shpDef[6] - shp[1], 5); delete[] shp; } +} - Common::SeekableReadStream *s = _res->createReadStream("TEXT.DAT"); - _screen->loadFileDataToPage(s, 5, 32000); - delete s; - - gui_drawBox(0, 121, 320, 79, _color1_1, _color2_1, _bkgColor_1); - _txt->setupField(9, true); - _txt->resetPageBreakString(); - +void DarkMoonEngine::runNpcDialogue(int npcIndex) { if (npcIndex == 0) { snd_playSoundEffect(57); if (npcJoinDialogue(0, 1, 3, 2)) @@ -108,7 +112,7 @@ void DarkMoonEngine::npcSequence(int npcIndex) { gui_drawDialogueBox(); _txt->printDialogueText(4, 0); - int r = runDialogue(-1, 0, _npc1Strings[0], _npc1Strings[1]) - 1; + int r = runDialogue(-1, 0, _npc1Strings[0], _npc1Strings[1], 0) - 1; if (r == 0) { _sound->playTrack(0); @@ -124,7 +128,7 @@ void DarkMoonEngine::npcSequence(int npcIndex) { gui_drawDialogueBox(); _txt->printDialogueText(8, 0); - int r = runDialogue(-1, 0, _npc2Strings[0], _npc2Strings[1]) - 1; + int r = runDialogue(-1, 0, _npc2Strings[0], _npc2Strings[1], 0) - 1; if (r == 0) { if (rollDice(1, 2, -1)) @@ -136,9 +140,6 @@ void DarkMoonEngine::npcSequence(int npcIndex) { _currentDirection = 0; } } - - _txt->removePageBreakFlag(); - gui_restorePlayField(); } void DarkMoonEngine::updateUsedCharacterHandItem(int charIndex, int slot) { @@ -338,7 +339,40 @@ void DarkMoonEngine::drawDoorIntern(int type, int, int x, int y, int w, int wall } void DarkMoonEngine::restParty_npc() { - warning("DarkMoonEngine::restParty_npc(): implement!"); + int insalId = -1; + int numChar = 0; + + for (int i = 0; i < 6; i++) { + if (!testCharacter(i, 1)) + continue; + if (testCharacter(i, 2) && _characters[i].portrait == -1) + insalId = i; + numChar++; + } + + if (insalId == -1 || numChar < 5) + return; + + removeCharacterFromParty(insalId); + if (insalId < 4) + exchangeCharacters(insalId, testCharacter(5, 1) ? 5 : 4); + + clearScriptFlag(6); + + if (!stripPartyItems(1, 1, 1, 1)) + stripPartyItems(2, 1, 1, 1); + stripPartyItems(31, 0, 1, 3); + stripPartyItems(39, 1, 0, 3); + stripPartyItems(47, 0, 1, 2); + + _items[createItemOnCurrentBlock(28)].value = 26; + + gui_drawPlayField(false); + gui_drawAllCharPortraitsWithStats(); + + _screen->setClearScreenDim(10); + _gui->messageDialogue2(11, 63, 6); + _gui->messageDialogue2(11, 64, 6); } bool DarkMoonEngine::restParty_extraAbortCondition() { @@ -357,7 +391,7 @@ void DarkMoonEngine::useHorn(int charIndex, int weaponSlot) { } bool DarkMoonEngine::checkPartyStatusExtra() { - if (checkScriptFlag(0x10)) + if (checkScriptFlag(0x100000)) seq_dranFools(); return _gui->confirmDialogue2(14, 67, 1); } @@ -374,49 +408,12 @@ void DarkMoonEngine::drawLightningColumn() { } int DarkMoonEngine::resurrectionSelectDialogue() { - int cnt = 0; - const char *namesList[10]; - memset(namesList, 0, 10 * sizeof(const char*)); - int8 indexList[10]; - - for (int i = 0; i < 6; i++) { - if (!testCharacter(i, 1)) - continue; - if (_characters[i].hitPointsCur != -10) - continue; - - namesList[cnt] = _characters[i].name; - indexList[cnt++] = i; - } - - for (int i = 0; i < 6; i++) { - if (!testCharacter(i, 1)) - continue; - - for (int ii = 0; ii < 27; ii++) { - uint16 inv = _characters[i].inventory[ii]; - if (!inv) - continue; - - if (_items[inv].type != 33) - continue; - - namesList[cnt] = _npcPreset[_items[inv].value - 1].name; - indexList[cnt++] = -_items[inv].value; - } - } - - if (_itemInHand) { - if (_items[_itemInHand].type == 33) { - namesList[cnt] = _npcPreset[_items[_itemInHand].value - 1].name; - indexList[cnt++] = -_items[_itemInHand].value; - } - } + countResurrectionCandidates(); - namesList[cnt] = _abortStrings[0]; - indexList[cnt++] = 99; + _rrNames[_rrCount] = _abortStrings[0]; + _rrId[_rrCount++] = 99; - int r = indexList[runDialogue(-1, 1, namesList[0], namesList[1], namesList[2], namesList[3], namesList[4], namesList[5], namesList[6], namesList[7], namesList[8]) - 1]; + int r = _rrId[runDialogue(-1, 1, _rrNames[0], _rrNames[1], _rrNames[2], _rrNames[3], _rrNames[4], _rrNames[5], _rrNames[6], _rrNames[7], _rrNames[8]) - 1]; if (r == 99) return 0; diff --git a/engines/kyra/eob2.h b/engines/kyra/eob2.h index e1c574a243..f24db79e62 100644 --- a/engines/kyra/eob2.h +++ b/engines/kyra/eob2.h @@ -94,7 +94,8 @@ private: const char *const *_dranFoolsStrings; // characters - void npcSequence(int npcIndex); + void drawNpcScene(int npcIndex); + void runNpcDialogue(int npcIndex); const uint8 *_npcShpData; const char *const *_npc1Strings; diff --git a/engines/kyra/eobcommon.cpp b/engines/kyra/eobcommon.cpp index 22c0519069..eef3873285 100644 --- a/engines/kyra/eobcommon.cpp +++ b/engines/kyra/eobcommon.cpp @@ -110,7 +110,7 @@ EobCoreEngine::EobCoreEngine(OSystem *system, const GameFlags &flags) : LolEobBa _configHpBarGraphs = true; memset(_dialogueLastBitmap, 0, 13); - _dlgUnk1 = 0; + _npcSequenceSub = 0; _moveCounter = 0; _partyResting = false; @@ -137,6 +137,10 @@ EobCoreEngine::EobCoreEngine(OSystem *system, const GameFlags &flags) : LolEobBa _spellAnimBuffer = 0; _clericSpellOffset = 0; _restPartyElapsedTime = 0; + + _rrCount = 0; + memset(_rrNames, 0, 10 * sizeof(const char*)); + memset(_rrId, 0, 10 * sizeof(int8)); } EobCoreEngine::~EobCoreEngine() { @@ -975,6 +979,26 @@ void EobCoreEngine::neutralizePoison(int character) { gui_drawCharPortraitWithStats(character); } +void EobCoreEngine::npcSequence(int npcIndex) { + _screen->loadEobBitmap("OUTTAKE", 5, 3); + _screen->copyRegion(0, 0, 0, 0, 176, 120, 0, 6, Screen::CR_NO_P_CHECK); + + drawNpcScene(npcIndex); + + Common::SeekableReadStream *s = _res->createReadStream("TEXT.DAT"); + _screen->loadFileDataToPage(s, 5, 32000); + delete s; + + gui_drawBox(0, 121, 320, 79, _color1_1, _color2_1, _bkgColor_1); + _txt->setupField(9, true); + _txt->resetPageBreakString(); + + runNpcDialogue(npcIndex); + + _txt->removePageBreakFlag(); + gui_restorePlayField(); +} + void EobCoreEngine::initNpc(int npcIndex) { EobCharacter *c = _characters; int i = 0; @@ -1005,7 +1029,7 @@ int EobCoreEngine::npcJoinDialogue(int npcIndex, int queryJoinTextId, int confir gui_drawDialogueBox(); _txt->printDialogueText(queryJoinTextId, 0); - int r = runDialogue(-1, 0, _yesNoStrings[0], _yesNoStrings[1]) - 1; + int r = runDialogue(-1, 0, _yesNoStrings[0], _yesNoStrings[1], 0) - 1; if (r == 0) { if (confirmJoinTextId == -1) { Common::String tmp = Common::String::format(_npcJoinStrings[0], _npcPreset[npcIndex].name); @@ -1030,7 +1054,7 @@ int EobCoreEngine::prepareForNewPartyMember(int16 itemType, int16 itemValue) { numChars += (_characters[i].flags & 1); if (numChars < 6) { - deletePartyItem(itemType, itemValue); + deletePartyItems(itemType, itemValue); } else { gui_drawDialogueBox(); _txt->printDialogueText(_npcMaxStrings[0]); @@ -1040,7 +1064,7 @@ int EobCoreEngine::prepareForNewPartyMember(int16 itemType, int16 itemValue) { if (r == 6) return 0; - deletePartyItem(itemType, itemValue); + deletePartyItems(itemType, itemValue); removeCharacterFromParty(r); } @@ -1165,11 +1189,11 @@ void EobCoreEngine::setupDialogueButtons(int presetfirst, int numStr, const char va_list args; va_start(args, str1); - const char **s5p = va_arg(args, const char**); + const char **sp = va_arg(args, const char**); va_end(args); for (int i = 1; i < numStr; i++) { - if (s5p[i - 1]) - _dialogueButtonString[i] = s5p[i - 1]; + if (sp[i - 1]) + _dialogueButtonString[i] = sp[i - 1]; else _dialogueNumButtons = numStr = i; } @@ -1191,7 +1215,7 @@ void EobCoreEngine::setupDialogueButtons(int presetfirst, int numStr, const char } void EobCoreEngine::initDialogueSequence() { - _dlgUnk1 = -1; + _npcSequenceSub = -1; _txt->setWaitButtonMode(0); _dialogueField = true; @@ -1435,6 +1459,47 @@ void EobCoreEngine::displayParchment(int id) { restoreAfterDialogueSequence(); } +int EobCoreEngine::countResurrectionCandidates() { + _rrCount = 0; + memset(_rrNames, 0, 10 * sizeof(const char*)); + + for (int i = 0; i < 6; i++) { + if (!testCharacter(i, 1)) + continue; + if (_characters[i].hitPointsCur != -10) + continue; + + _rrNames[_rrCount] = _characters[i].name; + _rrId[_rrCount++] = i; + } + + for (int i = 0; i < 6; i++) { + if (!testCharacter(i, 1)) + continue; + + for (int ii = 0; ii < 27; ii++) { + uint16 inv = _characters[i].inventory[ii]; + if (!inv) + continue; + + if ((_flags.gameID == GI_EOB1 && ((_itemTypes[_items[inv].type].extraProperties & 0x7f) != 8)) || (_flags.gameID == GI_EOB2 && _items[inv].type != 33)) + continue; + + _rrNames[_rrCount] = _npcPreset[_items[inv].value - 1].name; + _rrId[_rrCount++] = -_items[inv].value; + } + } + + if (_itemInHand > 0) { + if ((_flags.gameID == GI_EOB1 && ((_itemTypes[_items[_itemInHand].type].extraProperties & 0x7f) == 8)) || (_flags.gameID == GI_EOB2 && _items[_itemInHand].type == 33)) { + _rrNames[_rrCount] = _npcPreset[_items[_itemInHand].value - 1].name; + _rrId[_rrCount++] = -_items[_itemInHand].value; + } + } + + return _rrCount; +} + void EobCoreEngine::useSlotWeapon(int charIndex, int slotIndex, Item item) { EobCharacter *c = &_characters[charIndex]; int tp = item ? _items[item].type : 0; @@ -1621,7 +1686,7 @@ int EobCoreEngine::calcCharacterDamage(int charIndex, int times, int itemOrPips, EobCharacter *c = &_characters[charIndex]; if (a != 5) { - if (checkUnkConstModifiers(c, _charClassModUnk[c->cClass], c->level[0], a, c->raceSex)) + if (checkMonsterLevelConstModifiers(c, _charClassModUnk[c->cClass], c->level[0], a, c->raceSex)) s = recalcDamageModifier(damageType, s); } @@ -1699,7 +1764,7 @@ bool EobCoreEngine::characterAttackHitTest(int charIndex, int monsterIndex, int if (_flags.gameID == GI_EOB2) { if ((p > 0 && p < 4) || !item ){ - if (((_monsterProps[t].statusFlags & 0x200) && (d <= 0)) || ((_monsterProps[t].statusFlags & 0x1000) && (d <= 1))) + if (((_monsterProps[t].immunityFlags & 0x200) && (d <= 0)) || ((_monsterProps[t].immunityFlags & 0x1000) && (d <= 1))) return false; } } @@ -1877,7 +1942,7 @@ int EobCoreEngine::calcCloseDistanceMonsterDamage(EobMonsterInPlay *m, int times EobMonsterProperty *p = &_monsterProps[m->type]; if (b == 5) { - if (checkUnkConstModifiers(m, 0, p->level, b, 6)) + if (checkMonsterLevelConstModifiers(m, 0, p->level, b, 6)) s = recalcDamageModifier(damageType, s); } @@ -1886,10 +1951,12 @@ int EobCoreEngine::calcCloseDistanceMonsterDamage(EobMonsterInPlay *m, int times s = 1; } - if ((flags & 0x100) && ((_flags.gameID == GI_EOB2 && (p->statusFlags & 0x100)) || (_flags.gameID == GI_EOB1 && (p->capsFlags & 4))) && (!(_itemTypes[_items[pips].type].allowedClasses & 4 /* bug in original code ??*/))) - s >>= 1; + if ((flags & 0x100) && (!(_itemTypes[_items[pips].type].allowedClasses & 4 /* bug in original code ??*/)) && + ((_flags.gameID == GI_EOB2 && (p->immunityFlags & 0x100)) || + (_flags.gameID == GI_EOB1 && (p->capsFlags & 4)))) + s >>= 1; - if (p->statusFlags & 0x2000) { + if (p->immunityFlags & 0x2000) { if (flags & 0x100) { if (_items[pips].value < 3) s >>= 2; @@ -1913,7 +1980,7 @@ int EobCoreEngine::calcCloseDistanceMonsterDamage(EobMonsterInPlay *m, int times static const uint16 damageImmunityFlags[] = { 0x01, 0x10, 0x02, 0x20, 0x80, 0x400, 0x20, 0x800, 0x40, 0x80, 0x400, 0x40 }; for (int i = 0; i < 12; i += 2) { - if ((flags & damageImmunityFlags[i]) && (p->statusFlags & damageImmunityFlags[i + 1])) + if ((flags & damageImmunityFlags[i]) && (p->immunityFlags & damageImmunityFlags[i + 1])) s = 0; } @@ -1935,7 +2002,7 @@ int EobCoreEngine::calcDamageModifers(int charIndex, EobMonsterInPlay *m, int it return (s < 0) ? 0 : s; } -bool EobCoreEngine::checkUnkConstModifiers(void *target, int hpModifier, int level, int b, int race) { +bool EobCoreEngine::checkMonsterLevelConstModifiers(void *target, int hpModifier, int level, int b, int race) { static const int8 constMod[] = { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5 }; if (b == 5) @@ -1951,7 +2018,7 @@ bool EobCoreEngine::checkUnkConstModifiers(void *target, int hpModifier, int lev } bool EobCoreEngine::specialAttackConstTest(int charIndex, int b) { - return checkUnkConstModifiers(&_characters[charIndex], _charClassModUnk[_characters[charIndex].cClass], _characters[charIndex].level[0], b, _characters[charIndex].raceSex >> 1); + return checkMonsterLevelConstModifiers(&_characters[charIndex], _charClassModUnk[_characters[charIndex].cClass], _characters[charIndex].level[0], b, _characters[charIndex].raceSex >> 1); } int EobCoreEngine::getConstModifierTableValue(int hpModifier, int level, int b) { diff --git a/engines/kyra/eobcommon.h b/engines/kyra/eobcommon.h index 6463f839c8..1c730f7687 100644 --- a/engines/kyra/eobcommon.h +++ b/engines/kyra/eobcommon.h @@ -158,7 +158,7 @@ struct SpriteDecoration { struct EobMonsterProperty { int8 armorClass; int8 hitChance; - uint8 level; + int8 level; uint8 hpDcTimes; uint8 hpDcPips; uint8 hpDcBase; @@ -168,7 +168,7 @@ struct EobMonsterProperty { uint8 pips; int8 base; } dmgDc[3]; - uint16 statusFlags; + uint16 immunityFlags; uint32 capsFlags; uint32 typeFlags; int32 experience; @@ -376,7 +376,9 @@ protected: void modifyCharacterHitpoints(int character, int16 points); void neutralizePoison(int character); - virtual void npcSequence(int npcIndex) = 0; + void npcSequence(int npcIndex); + virtual void drawNpcScene(int npcIndex) = 0; + virtual void runNpcDialogue(int npcIndex) = 0; void initNpc(int npcIndex); int npcJoinDialogue(int npcIndex, int queryJoinTextId, int confirmJoinTextId, int noJoinTextId); int prepareForNewPartyMember(int16 itemType, int16 itemValue); @@ -405,6 +407,7 @@ protected: const uint8 *_constModExt; const EobCharacter *_npcPreset; + int _npcSequenceSub; bool _partyResting; bool _loading; @@ -412,11 +415,13 @@ protected: void loadItemDefs(); Item duplicateItem(Item itemIndex); void setItemPosition(Item *itemQueue, int block, Item item, int pos); - void createInventoryItem(EobCharacter *c, Item itemIndex, int itemValue, int preferedInventorySlot); + Item createItemOnCurrentBlock(Item itemIndex); + void createInventoryItem(EobCharacter *c, Item itemIndex, int16 itemValue, int preferedInventorySlot); int deleteInventoryItem(int charIndex, int slot); void deleteBlockItem(uint16 block, int type); int validateInventorySlotForItem(Item item, int charIndex, int slot); - void deletePartyItem(Item itemType, int16 itemValue); + int stripPartyItems(int16 itemType, int16 itemValue, int handleValueMode, int numItems); + bool deletePartyItems(int16 itemType, int16 itemValue); virtual void updateUsedCharacterHandItem(int charIndex, int slot) = 0; int itemUsableByCharacter(int charIndex, Item item); int countQueuedItems(Item itemQueue, int16 id, int16 type, int count, int includeFlyingItems); @@ -622,6 +627,7 @@ protected: // Script void runLevelScript(int block, int flags); void setScriptFlag(int flag); + void clearScriptFlag(int flag); bool checkScriptFlag(int flag); const uint8 *initScriptTimers(const uint8 *pos); @@ -739,7 +745,6 @@ protected: int runDialogue(int dialogueTextId, int style, const char *button1, ...); char _dialogueLastBitmap[13]; - int _dlgUnk1; int _moveCounter; uint8 _color4; @@ -803,11 +808,12 @@ protected: // misc void delay(uint32 millis, bool doUpdate = false, bool isMainLoop = false); void displayParchment(int id); + int countResurrectionCandidates(); + virtual int resurrectionSelectDialogue() = 0; virtual void useHorn(int charIndex, int weaponSlot) {} virtual bool checkPartyStatusExtra() = 0; virtual void drawLightningColumn() {} - virtual int resurrectionSelectDialogue() { return -1; } virtual int charSelectDialogue() { return -1; } virtual void characterLevelGain(int charIndex) {} @@ -820,6 +826,10 @@ protected: const char * const *_saveLoadStrings; + int _rrCount; + const char *_rrNames[10]; + int8 _rrId[10]; + Screen_Eob *_screen; GUI_Eob *_gui; @@ -846,7 +856,7 @@ protected: int calcCloseDistanceMonsterDamage(EobMonsterInPlay *m, int times, int pips, int offs, int flags, int b, int damageType); int calcDamageModifers(int charIndex, EobMonsterInPlay *m, int item, int itemType, int useStrModifier); - bool checkUnkConstModifiers(void *target, int hpModifier, int level, int b, int race); + bool checkMonsterLevelConstModifiers(void *target, int hpModifier, int level, int b, int race); bool specialAttackConstTest(int charIndex, int b); int getConstModifierTableValue(int hpModifier, int level, int b); bool calcDamageCheckItemType(int itemType); @@ -1045,6 +1055,7 @@ protected: const char *const *_menuStringsDefeat; const char *_errorSlotEmptyString; const char *_errorSlotNoNameString; + const char *_menuOkString; const char *const *_menuStringsTransfer; const char *const *_menuStringsSpec; diff --git a/engines/kyra/gui_eob.cpp b/engines/kyra/gui_eob.cpp index ce5f3ea53f..c495eb541f 100644 --- a/engines/kyra/gui_eob.cpp +++ b/engines/kyra/gui_eob.cpp @@ -385,7 +385,7 @@ void EobCoreEngine::gui_drawWeaponSlot(int charIndex, int slot) { if (itm) drawItemIconShape(_screen->_curPage, itm, x + 8, y); - else if (!slot && checkScriptFlag(0x8000)) + else if (!slot && _flags.gameID == GI_EOB2 && checkScriptFlag(0x80000000)) _screen->drawShape(_screen->_curPage, _itemIconShapes[103], x + 8, y, 0); else _screen->drawShape(_screen->_curPage, _itemIconShapes[85], x + 8, y, 0); @@ -2410,6 +2410,44 @@ bool GUI_Eob::confirmDialogue2(int dim, int id, int deflt) { return newHighlight ? false : true; } +void GUI_Eob::messageDialogue2(int dim, int id, int buttonTextCol) { + drawMenuButtonBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, false, false); + + _screen->_curPage = 2; + _screen->setClearScreenDim(dim); + drawMenuButtonBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, false, false); + _screen->printShadedText(getMenuString(id), (_screen->_curDim->sx << 3) + 5, _screen->_curDim->sy + 5, 15, 0); + _screen->_curPage = 0; + _screen->copyRegion(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, 2, 0, Screen::CR_NO_P_CHECK); + + int x = (_screen->_curDim->sx << 3) + (_screen->_curDim->w << 2) - (strlen(_vm->_menuOkString) << 2); + int y = _screen->_curDim->sy + _screen->_curDim->h - 21; + int w = (strlen(_vm->_menuOkString) << 3) + 8; + drawMenuButtonBox(x, y, w, 14, false, false); + _screen->printShadedText(_vm->_menuOkString, x + 4, y + 3, buttonTextCol, 0); + _screen->updateScreen(); + + for (bool runLoop = true; runLoop && !_vm->shouldQuit(); ) { + int inputFlag = _vm->checkInput(0, false, 0) & 0x8ff; + _vm->removeInputTop(); + + if (inputFlag == 199 || inputFlag == 201) { + if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, x, y, x + w, y + 14)) + runLoop = false; + } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN] || inputFlag == _vm->_keyMap[Common::KEYCODE_o]) { + runLoop = false; + } + } + + _vm->gui_drawBox(x, y, w, 14, _vm->_color2_1, _vm->_bkgColor_1, -1); + _screen->updateScreen(); + _vm->_system->delayMillis(80); + drawMenuButtonBox(x, y, w, 14, false, false); + _screen->printShadedText(_vm->_menuOkString, x + 4, y + 3, buttonTextCol, 0); + _screen->updateScreen(); + +} + void GUI_Eob::updateBoxFrameHighLight(int box) { static const uint8 colorTable[] = { 0x0F, 0xB0, 0xB2, 0xB4, 0xB6, 0xB8, 0xBA, 0xBC, 0x0C, 0xBC, 0xBA, 0xB8, 0xB6, 0xB4, 0xB2, 0xB0, 0x00 @@ -3375,11 +3413,12 @@ bool GUI_Eob::restParty() { _screen->setScreenDim(4); _screen->setFont(Screen::FID_8_FNT); - if (!injured && !res) - displayTextBox(43); - - if (res && hours > 4) - _vm->restParty_npc(); + if (!res) { + if (!injured) + displayTextBox(43); + if (hours > 4) + _vm->restParty_npc(); + } return res; } @@ -3447,8 +3486,6 @@ bool GUI_Eob::confirmDialogue(int id) { } void GUI_Eob::messageDialogue(int dim, int id, int buttonTextCol) { - static const char buttonText[] = "OK"; - int od = _screen->curDimIndex(); _screen->setScreenDim(dim); Screen::FontId of = _screen->setFont(Screen::FID_8_FNT); @@ -3456,12 +3493,12 @@ void GUI_Eob::messageDialogue(int dim, int id, int buttonTextCol) { drawTextBox(dim, id); const ScreenDim *dm = _screen->getScreenDim(dim); - int bx = ((dm->sx + dm->w) << 3) - ((strlen(buttonText) << 3) + 16); + int bx = ((dm->sx + dm->w) << 3) - ((strlen(_vm->_menuOkString) << 3) + 16); int by = dm->sy + dm->h - 19; - int bw = (strlen(buttonText) << 3) + 7; + int bw = (strlen(_vm->_menuOkString) << 3) + 7; drawMenuButtonBox(bx, by, bw, 14, false, false); - _screen->printShadedText(buttonText, bx + 4, by + 3, buttonTextCol, 0); + _screen->printShadedText(_vm->_menuOkString, bx + 4, by + 3, buttonTextCol, 0); _screen->updateScreen(); for (bool runLoop = true; runLoop && !_vm->shouldQuit(); ) { @@ -3469,9 +3506,8 @@ void GUI_Eob::messageDialogue(int dim, int id, int buttonTextCol) { _vm->removeInputTop(); if (inputFlag == 199 || inputFlag == 201) { - Common::Point p = _vm->getMousePos(); - if (_vm->posWithinRect(p.x, p.y, bx, by, bx + bw, by + 14)) - runLoop = false; + if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, bx, by, bx + bw, by + 14)) + runLoop = false; } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN] || inputFlag == _vm->_keyMap[Common::KEYCODE_o]) { runLoop = false; } diff --git a/engines/kyra/gui_eob.h b/engines/kyra/gui_eob.h index 709c676517..af3d3d2e48 100644 --- a/engines/kyra/gui_eob.h +++ b/engines/kyra/gui_eob.h @@ -63,6 +63,8 @@ public: bool runLoadMenu(int x, int y); bool confirmDialogue2(int dim, int id, int deflt); + void messageDialogue2(int dim, int id, int buttonTextCol); + void updateBoxFrameHighLight(int box); int getTextInput(char *dest, int x, int y, int destMaxLen, int textColor1, int textColor2, int cursorColor); diff --git a/engines/kyra/items_eob.cpp b/engines/kyra/items_eob.cpp index de5fe6b32a..78d3f8b8aa 100644 --- a/engines/kyra/items_eob.cpp +++ b/engines/kyra/items_eob.cpp @@ -103,6 +103,12 @@ Kyra::Item EobCoreEngine::duplicateItem(Item itemIndex) { return i; } +Item EobCoreEngine::createItemOnCurrentBlock(Item itemIndex) { + Item itm = duplicateItem(itemIndex); + setItemPosition((Item*)&_levelBlockProperties[_currentBlock].drawObjects, _currentBlock, itm, _dropItemDirIndex[(_currentDirection << 2) + rollDice(1, 2, -1)]); + return itm; +} + void EobCoreEngine::setItemPosition(Item *itemQueue, int block, Item item, int pos) { if (!item) return; @@ -123,7 +129,7 @@ void EobCoreEngine::setItemPosition(Item *itemQueue, int block, Item item, int p } } -void EobCoreEngine::createInventoryItem(EobCharacter *c, Item itemIndex, int itemValue, int preferedInventorySlot) { +void EobCoreEngine::createInventoryItem(EobCharacter *c, Item itemIndex, int16 itemValue, int preferedInventorySlot) { if (itemIndex <= 0) return; @@ -214,7 +220,35 @@ int EobCoreEngine::validateInventorySlotForItem(Item item, int charIndex, int sl return 0; } -void EobCoreEngine::deletePartyItem(Item itemType, int16 itemValue) { +int EobCoreEngine::stripPartyItems(int16 itemType, int16 itemValue, int handleValueMode, int numItems) { + int itemsLeft = numItems; + + for (bool runloop = true; runloop && itemsLeft; ) { + runloop = false; + for (int i = 0; i < 6 && itemsLeft; i++) { + if (!testCharacter(i, 1)) + continue; + + for (int ii = 0; ii < 27 && itemsLeft; ii++) { + if (ii == 16) + continue; + + Item itm = _characters[i].inventory[ii]; + if ((_items[itm].type == itemType) && ((handleValueMode == -1 && _items[itm].value <= itemValue) || (handleValueMode == 0 && _items[itm].value == itemValue) || (handleValueMode == 1 && _items[itm].value >= itemValue))) { + _characters[i].inventory[ii] = 0; + _items[itm].block = -1; + itemsLeft--; + runloop = true; + } + } + } + } + + return numItems - itemsLeft; +} + +bool EobCoreEngine::deletePartyItems(int16 itemType, int16 itemValue) { + bool res = false; for (int i = 0; i < 6; i++) { if (!testCharacter(i, 1)) continue; @@ -228,13 +262,26 @@ void EobCoreEngine::deletePartyItem(Item itemType, int16 itemValue) { int itm = c->inventory[slot]; _items[itm].block = -1; c->inventory[slot] = 0; + res = true; - if (_currentControlMode == 0 && slot < 2 && i < 5) - gui_drawWeaponSlot(i, slot); + if (!_dialogueField) { + if (_currentControlMode == 0 && slot < 2 && i < 5) + gui_drawWeaponSlot(i, slot); - if (_currentControlMode == 1 && i == _updateCharNum) - gui_drawInventoryItem(slot, 1, 0); + if (_currentControlMode == 1 && i == _updateCharNum) + gui_drawInventoryItem(slot, 1, 0); + } } + + if (_itemInHand > 0) { + if ((itemType == -1 || itemType == _items[_itemInHand].type) && (itemValue == -1 || itemValue == _items[_itemInHand].value)) { + _items[_itemInHand].block = -1; + setHandItem(0); + res = true; + } + } + + return res; } int EobCoreEngine::itemUsableByCharacter(int charIndex, Item item) { diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 7a4a3ec3e2..4fc78c0b64 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -376,11 +376,14 @@ Common::Error LoLEngine::init() { assert(_gui); _gui->initStaticData(); - _txt = new TextDisplayer_LoL(this, _screen); _dialogueButtonLabelCol1 = 144; _dialogueButtonLabelCol2 = 254; _dialogueButtonW = 74; _dialogueButtonH = 9; + _waitButtonReverveW = 80; + + _txt = new TextDisplayer_LoL(this, _screen); + _bkgColor_1 = -1; _color1_1 = 136; _color2_1 = 251; diff --git a/engines/kyra/loleobbase.cpp b/engines/kyra/loleobbase.cpp index 47a261be6f..2ffae915b1 100644 --- a/engines/kyra/loleobbase.cpp +++ b/engines/kyra/loleobbase.cpp @@ -103,10 +103,14 @@ LolEobBaseEngine::LolEobBaseEngine(OSystem *system, const GameFlags &flags) : Ky _dialogueNumButtons = _dialogueButtonYoffs = _dialogueHighlightedButton = 0; _currentControlMode = 0; _specialSceneFlag = 0; - _dialogueButtonLabelCol1 = 9; - _dialogueButtonLabelCol2 = 15; - _dialogueButtonW = 95; - _dialogueButtonH = 9; + _dialogueButtonLabelCol1 = 0; + _dialogueButtonLabelCol2 = 0; + _dialogueButtonW = 0; + _dialogueButtonH = 0; + _waitButtonPresX = 0; + _waitButtonPresY = 0; + _waitButtonPresW = 0; + _waitButtonReverveW = 0; _updateCharNum = -1; _activeVoiceFileTotalTime = 0; diff --git a/engines/kyra/loleobbase.h b/engines/kyra/loleobbase.h index a2c13827fc..ba59fe796b 100644 --- a/engines/kyra/loleobbase.h +++ b/engines/kyra/loleobbase.h @@ -281,6 +281,10 @@ protected: int16 _dialogueButtonYoffs; uint16 _dialogueButtonW; uint16 _dialogueButtonH; + const uint16 *_waitButtonPresX; + const uint8 *_waitButtonPresY; + const uint16 *_waitButtonPresW; + int _waitButtonReverveW; int _dialogueNumButtons; int _dialogueHighlightedButton; int _currentControlMode; diff --git a/engines/kyra/magic_eob.cpp b/engines/kyra/magic_eob.cpp index f828625dbb..70e4892342 100644 --- a/engines/kyra/magic_eob.cpp +++ b/engines/kyra/magic_eob.cpp @@ -555,11 +555,11 @@ bool EobCoreEngine::magicObjectDamageHit(EobFlyingObject *fo, int dcTimes, int d bool EobCoreEngine::magicObjectStatusHit(EobMonsterInPlay *m, int type, bool tryEvade, int mod) { EobMonsterProperty *p = &_monsterProps[m->type]; if (tryEvade) { - if (tryMonsterAttackEvasion(m) || (p->capsFlags & 0x10)) + if (tryMonsterAttackEvasion(m) || (p->immunityFlags & 0x10)) return true; } - if (checkUnkConstModifiers(m, 0, p->level, mod, 6)) + if (checkMonsterLevelConstModifiers(m, 0, p->level, mod, 6)) return false; int para = 0; @@ -569,7 +569,7 @@ bool EobCoreEngine::magicObjectStatusHit(EobMonsterInPlay *m, int type, bool try case 1: case 2: para = (type == 0) ? ((p->typeFlags & 1) ? 1 : 0) : ((type == 1) ? ((p->typeFlags & 2) ? 1 : 0) : 1); - if (para && !(p->statusFlags & 2)) { + if (para && !(p->immunityFlags & 2)) { m->mode = 10; m->spellStatusLeft = 15; } @@ -577,7 +577,7 @@ bool EobCoreEngine::magicObjectStatusHit(EobMonsterInPlay *m, int type, bool try break; case 3: - if (!(p->statusFlags & 8)) + if (!(p->immunityFlags & 8)) inflictMonsterDamage(m, 1000, true); break; @@ -591,12 +591,11 @@ bool EobCoreEngine::magicObjectStatusHit(EobMonsterInPlay *m, int type, bool try break; case 6: - if (!(p->statusFlags & 4) && m->mode != 7 && m->mode != 8 && m->mode != 10) { + if (!(_flags.gameID == GI_EOB1 && !(p->typeFlags & 3)) && !(p->immunityFlags & 4) && m->mode != 7 && m->mode != 8 && m->mode != 10) { m->mode = 0; m->spellStatusLeft = 20; - para = (getNextMonsterDirection(m->block, _currentBlock) ^ 4) >> 1; m->flags |= 8; - walkMonsterNextStep(m, -1, para); + walkMonsterNextStep(m, -1, (getNextMonsterDirection(m->block, _currentBlock) ^ 4) >> 1); } break; diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 5328aeff35..55946e5b7f 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -484,6 +484,22 @@ enum KyraResources { kEob1TurnUndeadString, + kEob1NpcShpData, + kEob1NpcSubShpIndex1, + kEob1NpcSubShpIndex2, + kEob1NpcSubShpY, + kEob1Npc0Strings, + kEob1Npc11Strings, + kEob1Npc12Strings, + kEob1Npc21Strings, + kEob1Npc22Strings, + kEob1Npc31Strings, + kEob1Npc32Strings, + kEob1Npc4Strings, + kEob1Npc5Strings, + kEob1Npc6Strings, + kEob1Npc7Strings, + kEob2MainMenuStrings, kEob2IntroStrings, kEob2IntroCPSFiles, diff --git a/engines/kyra/script_eob.cpp b/engines/kyra/script_eob.cpp index 833413c69b..1e113fb2ae 100644 --- a/engines/kyra/script_eob.cpp +++ b/engines/kyra/script_eob.cpp @@ -40,8 +40,12 @@ void EobCoreEngine::setScriptFlag(int flag) { _inf->setFlag(flag); } +void EobCoreEngine::clearScriptFlag(int flag) { + _inf->clearFlag(flag); +} + bool EobCoreEngine::checkScriptFlag(int flag) { - return _inf->checkFlag(0x8000); + return _inf->checkFlag(flag); } const uint8 *EobCoreEngine::initScriptTimers(const uint8 *pos) { @@ -188,6 +192,22 @@ void EobInfProcessor::run(int func, int sub) { } while (!_abortScript && !_abortAfterSubroutine); } +void EobInfProcessor::setFlag(int flag) { + _flagTable[17] |= flag; +} + +void EobInfProcessor::clearFlag(int flag) { + _flagTable[17] &= ~flag; +} + +bool EobInfProcessor::checkFlag(int flag) const { + return (_flagTable[17] & flag) ? true : false; +} + +bool EobInfProcessor::preventRest() const { + return _preventRest ? true : false; +} + void EobInfProcessor::loadState(Common::SeekableSubReadStreamEndian &in) { _preventRest = in.readByte(); for (int i = 0; i < 18; i++) @@ -469,11 +489,11 @@ int EobInfProcessor::oeob_moveInventoryItemToBlock(int8 *data) { } int EobInfProcessor::oeob_printMessage_v1(int8 *data) { - static const char ColorConfig[] = { 6, 33, 2, 33, 0 }; + static const char colorConfig[] = "\x6\x21\x2\x21"; char col[5]; int8 *pos = data; - strcpy(col, ColorConfig); + strcpy(col, colorConfig); const char *str = (const char*) pos; pos += (strlen(str) + 1); @@ -720,7 +740,7 @@ int EobInfProcessor::oeob_eval_v1(int8 *data) { for (i = 0; i < 6; i++) { if (!(_vm->_characters[i].flags & 1)) continue; - if ((_vm->_characters[a].raceSex >> 1) == cmd) { + if ((_vm->_characters[i].raceSex >> 1) == cmd) { b = 1; break; } @@ -1371,7 +1391,7 @@ int EobInfProcessor::oeob_identifyItems(int8 *data) { int EobInfProcessor::oeob_sequence(int8 *data) { int8 *pos = data; - _vm->_dlgUnk1 = -1; + _vm->_npcSequenceSub = -1; _vm->txt()->setWaitButtonMode(0); _vm->gui_updateControls(); _vm->drawScene(1); @@ -1402,7 +1422,6 @@ int EobInfProcessor::oeob_sequence(int8 *data) { case -1: // copy protection - error("EobInfProcessor::oeob_sequence(): unimplemented cmd -1"); break; default: @@ -1508,8 +1527,8 @@ int EobInfProcessor::oeob_specialEvent(int8 *data) { break; case 5: - _vm->deletePartyItem(46, 5); - _vm->deletePartyItem(46, 6); + _vm->deletePartyItems(46, 5); + _vm->deletePartyItems(46, 6); break; case 6: diff --git a/engines/kyra/script_eob.h b/engines/kyra/script_eob.h index 322322ae1f..71e53bc802 100644 --- a/engines/kyra/script_eob.h +++ b/engines/kyra/script_eob.h @@ -42,9 +42,10 @@ public: void loadData(const uint8 *data, uint32 dataSize); void run(int func, int sub); - void setFlag(int flag) { _flagTable[17] |= flag; } - bool checkFlag(int flag) const { return (_flagTable[17] & flag) ? true : false; } - bool preventRest() const { return _preventRest ? true : false; } + void setFlag(int flag); + void clearFlag(int flag); + bool checkFlag(int flag) const; + bool preventRest() const; void loadState(Common::SeekableSubReadStreamEndian &in); void saveState(Common::OutSaveFile *out); diff --git a/engines/kyra/sprites_eob.cpp b/engines/kyra/sprites_eob.cpp index 0874de82e3..97ee51bd22 100644 --- a/engines/kyra/sprites_eob.cpp +++ b/engines/kyra/sprites_eob.cpp @@ -83,7 +83,7 @@ const uint8 *EobCoreEngine::loadMonsterProperties(const uint8 *data) { EobMonsterProperty *d = &_monsterProps[cmd]; d->armorClass = (int8)*data++; d->hitChance = (int8)*data++; - d->level = *data++; + d->level = (int8)*data++; d->hpDcTimes = *data++; d->hpDcPips = *data++; d->hpDcBase = *data++; @@ -97,7 +97,7 @@ const uint8 *EobCoreEngine::loadMonsterProperties(const uint8 *data) { d->dmgDc[2].times = *data++; d->dmgDc[2].pips = *data++; d->dmgDc[3].base = (int8)*data++; - d->statusFlags = READ_LE_UINT16(data); + d->immunityFlags = READ_LE_UINT16(data); data += 2; d->capsFlags = READ_LE_UINT16(data); data += 2; @@ -185,7 +185,7 @@ void EobCoreEngine::initMonster(int index, int unit, uint16 block, int pos, int m->spellStatusLeft = i; m->dir = dir; m->palette = _flags.gameID == GI_EOB2 ? (index % 3) : 0; - m->hitPointsCur = m->hitPointsMax = _flags.gameID == GI_EOB2 ? rollDice(p->hpDcTimes, p->hpDcPips, p->hpDcBase) : (p->hpDcTimes == 255 ? rollDice(1, 4, 0) : rollDice(p->hpDcTimes, 8, 0)); + m->hitPointsCur = m->hitPointsMax = _flags.gameID == GI_EOB2 ? rollDice(p->hpDcTimes, p->hpDcPips, p->hpDcBase) : (p->level == -1 ? rollDice(1, 4, 0) : rollDice(p->level, 8, 0)); m->randItem = randItem; m->fixedItem = fixedItem; m->sub = _currentSub; diff --git a/engines/kyra/staticres_eob.cpp b/engines/kyra/staticres_eob.cpp index 1cf78eef5c..ea943f32d4 100644 --- a/engines/kyra/staticres_eob.cpp +++ b/engines/kyra/staticres_eob.cpp @@ -151,7 +151,7 @@ bool StaticResource::loadEobNpcData(Common::SeekableReadStream &stream, void *&p s->raceSex = stream.readByte(); s->cClass = stream.readByte(); s->alignment = stream.readByte(); - s->portrait = stream.readByte(); + s->portrait = stream.readSByte(); s->food = stream.readByte(); stream.read(s->level, 3); s->experience[0] = stream.readUint32BE(); @@ -159,7 +159,7 @@ bool StaticResource::loadEobNpcData(Common::SeekableReadStream &stream, void *&p s->experience[2] = stream.readUint32BE(); s->mageSpellsAvailableFlags = stream.readUint32BE(); for (int ii = 0; ii < 27; ii++) - s->inventory[i] = stream.readUint16BE(); + s->inventory[ii] = stream.readSint16BE(); } ptr = e; @@ -555,6 +555,7 @@ void EobCoreEngine::initStaticResource() { _saveLoadStrings = saveLoadStrings[(_flags.lang == Common::EN_ANY) ? 0 : ((_flags.lang == Common::DE_DEU) ? 1 : 2)]; _errorSlotEmptyString = errorSlotEmptyString[(_flags.lang == Common::EN_ANY) ? 0 : ((_flags.lang == Common::DE_DEU) ? 1 : 2)]; _errorSlotNoNameString = errorSlotNoNameString[(_flags.lang == Common::EN_ANY) ? 0 : ((_flags.lang == Common::DE_DEU) ? 1 : 2)]; + _menuOkString = "OK"; } void EobCoreEngine::initButtonData() { @@ -1068,6 +1069,22 @@ void EobEngine::initStaticResource() { _turnUndeadString = _staticres->loadStrings(kEob1TurnUndeadString, temp); + _npcShpData = _staticres->loadRawData(kEob1NpcShpData, temp); + _npcSubShpIndex1 = _staticres->loadRawData(kEob1NpcSubShpIndex1, temp); + _npcSubShpIndex2 = _staticres->loadRawData(kEob1NpcSubShpIndex2, temp); + _npcSubShpY = _staticres->loadRawData(kEob1NpcSubShpY, temp); + _npc0Strings = _staticres->loadStrings(kEob1Npc0Strings, temp); + _npc11Strings = _staticres->loadStrings(kEob1Npc11Strings, temp); + _npc12Strings = _staticres->loadStrings(kEob1Npc12Strings, temp); + _npc21Strings = _staticres->loadStrings(kEob1Npc21Strings, temp); + _npc22Strings = _staticres->loadStrings(kEob1Npc22Strings, temp); + _npc31Strings = _staticres->loadStrings(kEob1Npc31Strings, temp); + _npc32Strings = _staticres->loadStrings(kEob1Npc32Strings, temp); + _npc4Strings = _staticres->loadStrings(kEob1Npc4Strings, temp); + _npc5Strings = _staticres->loadStrings(kEob1Npc5Strings, temp); + _npc6Strings = _staticres->loadStrings(kEob1Npc6Strings, temp); + _npc7Strings = _staticres->loadStrings(kEob1Npc7Strings, temp); + const uint8 *ps = _staticres->loadRawData(kEob1MonsterProperties, temp); temp /= 27; _monsterProps = new EobMonsterProperty[temp]; @@ -1077,7 +1094,7 @@ void EobEngine::initStaticResource() { EobMonsterProperty *p = &_monsterProps[i]; p->armorClass = (int8)*ps++; p->hitChance = (int8)*ps++; - p->hpDcTimes = *ps++; + p->level = (int8)*ps++; p->attacksPerRound = *ps++; p->dmgDc[0].times = *ps++; p->dmgDc[0].pips = *ps++; diff --git a/engines/kyra/text_eob.cpp b/engines/kyra/text_eob.cpp index 63d893d2cc..80858d1743 100644 --- a/engines/kyra/text_eob.cpp +++ b/engines/kyra/text_eob.cpp @@ -29,14 +29,16 @@ #include "common/system.h" +#define EOBTEXTBUFFERSIZE 2048 + namespace Kyra { TextDisplayer_Eob::TextDisplayer_Eob(LolEobBaseEngine *engine, Screen *sScreen) : _vm(engine), _screen(sScreen), _lineCount(0), _printFlag(false), _lineWidth(0), _numCharsTotal(0), _allowPageBreak(true), _numCharsLeft(0), _numCharsPrinted(0), _sjisLineBreakFlag(false), _waitButtonMode(1) { - _dialogueBuffer = new char[1024]; - memset(_dialogueBuffer, 0, 1024); + _dialogueBuffer = new char[EOBTEXTBUFFERSIZE]; + memset(_dialogueBuffer, 0, EOBTEXTBUFFERSIZE); _currentLine = new char[85]; memset(_currentLine, 0, 85); @@ -313,13 +315,13 @@ void TextDisplayer_Eob::printLine(char *str) { if ((lw + _textDimData[sdx].column) > w) { if ((lines - 1 - (_waitButtonSpace << 1)) <= _lineCount) // cut off line to leave space for "MORE" button - w -= 80; + w -= vm()->_waitButtonReverveW; } else { if (!_sjisLineBreakFlag || (_lineCount + 1 < lines - 1)) ct = false; else // cut off line to leave space for "MORE" button - w -= 80; + w -= vm()->_waitButtonReverveW; } if (ct) { @@ -341,7 +343,7 @@ void TextDisplayer_Eob::printLine(char *str) { if ((lw + _textDimData[sdx].column) > w) { if ((lines - 1) <= _lineCount && _allowPageBreak) // cut off line to leave space for "MORE" button - w -= (10 * (_screen->getFontWidth() + _screen->_charWidth)); + w -= vm()->_waitButtonReverveW; w -= _textDimData[sdx].column; @@ -439,7 +441,10 @@ void TextDisplayer_Eob::printLine(char *str) { } void TextDisplayer_Eob::printDialogueText(int stringId, const char *pageBreakString) { - strcpy(_dialogueBuffer, (const char *)(screen()->getCPagePtr(5) + READ_LE_UINT16(&screen()->getCPagePtr(5)[(stringId - 1) << 1]))); + const char * str = (const char *)(screen()->getCPagePtr(5) + READ_LE_UINT16(&screen()->getCPagePtr(5)[(stringId - 1) << 1])); + assert (strlen(str) < EOBTEXTBUFFERSIZE); + Common::strlcpy(_dialogueBuffer, str, EOBTEXTBUFFERSIZE); + displayText(_dialogueBuffer); if (pageBreakString) { @@ -452,6 +457,9 @@ void TextDisplayer_Eob::printDialogueText(int stringId, const char *pageBreakStr } void TextDisplayer_Eob::printDialogueText(const char *str, bool wait) { + assert (strlen(str) < EOBTEXTBUFFERSIZE); + Common::strlcpy(_dialogueBuffer, str, EOBTEXTBUFFERSIZE); + strcpy(_dialogueBuffer, str); displayText(_dialogueBuffer); if (wait) @@ -471,7 +479,8 @@ void TextDisplayer_Eob::printMessage(const char *str, int textColor, ...) { displayText(_dialogueBuffer); - _textDimData[screen()->curDimIndex()].color1 = tc; + if (vm()->game() != GI_EOB1) + _textDimData[screen()->curDimIndex()].color1 = tc; if (!screen()->_curPage) screen()->updateScreen(); @@ -505,7 +514,8 @@ void TextDisplayer_Eob::textPageBreak() { int cp = _screen->setCurPage(0); Screen::FontId cf = screen()->setFont(vm()->gameFlags().use16ColorMode ? Screen::FID_SJIS_FNT : Screen::FID_6_FNT); - vm()->_timer->pauseSingleTimer(11, true); + if (vm()->game() == GI_LOL) + vm()->_timer->pauseSingleTimer(11, true); vm()->_fadeText = false; int resetPortraitAfterSpeechAnim = 0; @@ -527,27 +537,31 @@ void TextDisplayer_Eob::textPageBreak() { int x = ((dim->sx + dim->w) << 3) - (_vm->_dialogueButtonW + 3); int y = 0; + int w = vm()->_dialogueButtonW; - if (vm()->_needSceneRestore && (vm()->_updateFlags & 2)) { - if (vm()->_currentControlMode || !(vm()->_updateFlags & 2)) { - y = dim->sy + dim->h - 5; + if (vm()->game() == GI_LOL) { + if (vm()->_needSceneRestore && (vm()->_updateFlags & 2)) { + if (vm()->_currentControlMode || !(vm()->_updateFlags & 2)) { + y = dim->sy + dim->h - 5; + } else { + x += 6; + y = dim->sy + dim->h - 2; + } } else { - x += 6; - y = dim->sy + dim->h - 2; + y = dim->sy + dim->h - 10; } - } else if (vm()->game() == GI_LOL) { - y = dim->sy + dim->h - 10; } else { - y = _waitButtonMode ? 162 : 189; - x = _waitButtonMode ? 76 : 221; + y = vm()->_waitButtonPresY[_waitButtonMode]; + x = vm()->_waitButtonPresX[_waitButtonMode]; + w = vm()->_waitButtonPresW[_waitButtonMode]; } if (vm()->gameFlags().use16ColorMode) { vm()->gui_drawBox(x + 8, (y & ~7) - 1, 66, 10, 0xee, 0xcc, -1); screen()->printText(_pageBreakString, (x + 37 - (strlen(_pageBreakString) << 1) + 4) & ~3, (y + 2) & ~7, 0xc1, 0); } else { - vm()->gui_drawBox(x, y, vm()->_dialogueButtonW, vm()->_dialogueButtonH, vm()->_color1_1, vm()->_color2_1, vm()->_bkgColor_1); - screen()->printText(_pageBreakString, x + (vm()->_dialogueButtonW >> 1) - (vm()->screen()->getTextWidth(_pageBreakString) >> 1), y + 2, vm()->_dialogueButtonLabelCol1, 0); + vm()->gui_drawBox(x, y, w, vm()->_dialogueButtonH, vm()->_color1_1, vm()->_color2_1, vm()->_bkgColor_1); + screen()->printText(_pageBreakString, x + (w >> 1) - (vm()->screen()->getTextWidth(_pageBreakString) >> 1), y + 2, vm()->_dialogueButtonLabelCol1, 0); } vm()->removeInputTop(); @@ -579,7 +593,7 @@ void TextDisplayer_Eob::textPageBreak() { if (inputFlag == vm()->_keyMap[Common::KEYCODE_SPACE] || inputFlag == vm()->_keyMap[Common::KEYCODE_RETURN]) { loop = false; } else if (inputFlag == 199 || inputFlag == 201) { - if (vm()->posWithinRect(vm()->_mouseX, vm()->_mouseY, x, y, x + _vm->_dialogueButtonW, y + 9)) { + if (vm()->posWithinRect(vm()->_mouseX, vm()->_mouseY, x, y, x + w, y + 9)) { if (_vm->game() == GI_LOL) target = true; else @@ -594,11 +608,12 @@ void TextDisplayer_Eob::textPageBreak() { if (vm()->gameFlags().use16ColorMode) screen()->fillRect(x + 8, y, x + 57, y + 9, _textDimData[screen()->curDimIndex()].color2); else - screen()->fillRect(x, y, x + 73, y + 8, _textDimData[screen()->curDimIndex()].color2); + screen()->fillRect(x, y, x + w - 1, y + 8, _textDimData[screen()->curDimIndex()].color2); clearCurDim(); - vm()->_timer->pauseSingleTimer(11, false); + if (vm()->game() == GI_LOL) + vm()->_timer->pauseSingleTimer(11, false); if (vm()->_updateCharNum != -1) { vm()->_resetPortraitAfterSpeechAnim = resetPortraitAfterSpeechAnim; @@ -626,11 +641,9 @@ void TextDisplayer_Eob::displayWaitButton() { vm()->_dialogueButtonString[2] = 0; vm()->_dialogueHighlightedButton = 0; - static const uint16 posX[] = { 221, 76 }; - static const uint8 posY[] = { 189, 162 }; - - vm()->_dialogueButtonPosX = &posX[_waitButtonMode]; - vm()->_dialogueButtonPosY = &posY[_waitButtonMode]; + vm()->_dialogueButtonPosX = &vm()->_waitButtonPresX[_waitButtonMode]; + vm()->_dialogueButtonPosY = &vm()->_waitButtonPresY[_waitButtonMode]; + vm()->_dialogueButtonW = vm()->_waitButtonPresW[_waitButtonMode]; vm()->_dialogueButtonYoffs = 0; SWAP(_vm->_dialogueButtonLabelCol1, _vm->_dialogueButtonLabelCol2); @@ -640,7 +653,10 @@ void TextDisplayer_Eob::displayWaitButton() { vm()->removeInputTop(); while (!vm()->processDialogue() && !vm()->shouldQuit()) {} + + vm()->_dialogueButtonW = 95; SWAP(_vm->_dialogueButtonLabelCol1, _vm->_dialogueButtonLabelCol2); + clearCurDim(); } } // End of namespace Kyra -- cgit v1.2.3