aboutsummaryrefslogtreecommitdiff
path: root/engines/kyra
diff options
context:
space:
mode:
Diffstat (limited to 'engines/kyra')
-rw-r--r--engines/kyra/items_lol.cpp47
-rw-r--r--engines/kyra/lol.cpp75
-rw-r--r--engines/kyra/lol.h38
-rw-r--r--engines/kyra/resource.h2
-rw-r--r--engines/kyra/script_lol.cpp177
-rw-r--r--engines/kyra/script_tim.cpp166
-rw-r--r--engines/kyra/script_tim.h48
-rw-r--r--engines/kyra/staticres.cpp6
-rw-r--r--engines/kyra/text_lol.cpp13
9 files changed, 500 insertions, 72 deletions
diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp
index 5eb0214ac6..3852bcf55b 100644
--- a/engines/kyra/items_lol.cpp
+++ b/engines/kyra/items_lol.cpp
@@ -31,10 +31,8 @@
namespace Kyra {
void LoLEngine::giveCredits(int credits, int redraw) {
- static const uint8 stashSetupData[] = { 4, 4, 4, 4, 2, 2, 2, 3, 3, 0, 1, 1 };
-
if (redraw)
- snd_playSoundEffect(0x65, 0xff);
+ snd_playSoundEffect(101, -1);
int t = credits / 30;
if (!t)
@@ -51,7 +49,7 @@ void LoLEngine::giveCredits(int credits, int redraw) {
do {
if (_credits < 60) {
- int d = stashSetupData[_credits % 12] - _credits / 12;
+ int d = _stashSetupData[_credits % 12] - _credits / 12;
if (d < 0)
d += 5;
_moneyColumnHeight[d]++;
@@ -71,6 +69,47 @@ void LoLEngine::giveCredits(int credits, int redraw) {
}
}
+void LoLEngine::takeCredits(int credits, int redraw) {
+ if (redraw)
+ snd_playSoundEffect(101, -1);
+
+ if (credits > _credits)
+ credits = _credits;
+
+ int t = credits / 30;
+ if (!t)
+ t = 1;
+
+ int cnt = 0;
+
+ while (credits && _credits > 0) {
+ if (t > credits)
+ t = credits;
+
+ if (_credits - t < 60 && t >= 0) {
+ cnt = 0;
+
+ do {
+ if (--_credits < 60) {
+ int d = _stashSetupData[_credits % 12] - _credits / 12;
+ if (d < 0)
+ d += 5;
+ _moneyColumnHeight[d]--;
+ }
+ } while (++cnt < t);
+ } else if (_credits - t < 60) {
+ _credits -= t;
+ }
+
+ if (redraw) {
+ gui_drawMoneyBox(6);
+ if (credits)
+ delay(_tickLength, 1);
+ }
+ credits -= t;
+ }
+}
+
int LoLEngine::makeItem(int itemIndex, int curFrame, int flags) {
int cnt = 0;
int r = 0;
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index ceb756b3c7..022375fd90 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -76,7 +76,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_lastMusicTrack = -1;
_lastSfxTrack = -1;
_curTlkFile = -1;
- _lastSpeaker = _lastSpeechId = -1;
+ _lastSpeaker = _lastSpeechId = _nextSpeechId = _nextSpeaker = -1;
memset(_moneyColumnHeight, 0, 5);
_credits = 0;
@@ -95,6 +95,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_monsterShapesEx = 0;
_gameShapeMap = 0;
memset(_monsterUnk, 0, 3);
+ _pageSavedFlag = false;
_ingameMT32SoundIndex = _ingameGMSoundIndex = /*_ingameADLSoundIndex =*/ 0;
@@ -791,7 +792,7 @@ void LoLEngine::runLoop() {
}
void LoLEngine::update() {
- updateWsaAnimations();
+ updateSequenceBackgroundAnimations();
if (_updateCharNum != -1 && _system->getMillis() > _updatePortraitNext)
updatePortraitSpeechAnim();
@@ -1278,11 +1279,31 @@ void LoLEngine::generateBrightnessPalette(uint8 *src, uint8 *dst, int brightness
}
}
-void LoLEngine::updateWsaAnimations() {
+void LoLEngine::updateSequenceBackgroundAnimations() {
if (_updateFlags & 8)
return;
- //TODO
+ for (int i = 0; i < 6; i++)
+ _tim->updateBackgroundAnimation(i);
+}
+
+void LoLEngine::savePage5() {
+ if (_pageSavedFlag)
+ return;
+
+ _screen->copyRegionToBuffer(5, 0, 0, 320, 200, _pageBuffer2);
+ _pageSavedFlag = true;
+}
+
+void LoLEngine::restorePage5() {
+ if (!_pageSavedFlag)
+ return;
+
+ for (int i = 0; i < 6; i++)
+ _tim->freeAnimStruct(i);
+
+ _screen->copyBlockToPage(5, 0, 0, 320, 200, _pageBuffer2);
+ _pageSavedFlag = false;
}
void LoLEngine::loadTalkFile(int index) {
@@ -1319,6 +1340,7 @@ bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) {
_lastSpeechId = id;
_lastSpeaker = speaker;
+ _nextSpeechId = _nextSpeaker = -1;
Common::List<const char*> playList;
@@ -1326,6 +1348,8 @@ bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) {
char pattern2[5];
char file1[13];
char file2[13];
+ char file3[13];
+ file3[0] = 0;
snprintf(pattern2, sizeof(pattern2), "%02d", id & 0x4000 ? 0 : _curTlkFile);
@@ -1334,23 +1358,30 @@ bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) {
} else if (id < 1000) {
snprintf(pattern1, sizeof(pattern1), "%03d", id);
} else {
- snprintf(pattern1, sizeof(pattern1), "@%04d", id - 1000);
+ snprintf(file3, sizeof(file3), "@%04d%c.%s", id - 1000, (char)speaker, pattern2);
+ if (_res->exists(file3)) {
+ char *f = new char[strlen(file3) + 1];
+ strcpy(f, file3);
+ playList.push_back(f);
+ }
}
- for (char i = 0; ; i++) {
- char symbol = '0' + i;
- snprintf(file1, sizeof(file1), "%s%c%c.%s", pattern1, (char)speaker, symbol, pattern2);
- snprintf(file2, sizeof(file2), "%s%c%c.%s", pattern1, '_', symbol, pattern2);
- if (_res->exists(file1)) {
- char *f = new char[strlen(file1) + 1];
- strcpy(f, file1);
- playList.push_back(f);
- } else if (_res->exists(file2)) {
- char *f = new char[strlen(file2) + 1];
- strcpy(f, file2);
- playList.push_back(f);
- } else {
- break;
+ if (!file3[0]) {
+ for (char i = 0; ; i++) {
+ char symbol = '0' + i;
+ snprintf(file1, sizeof(file1), "%s%c%c.%s", pattern1, (char)speaker, symbol, pattern2);
+ snprintf(file2, sizeof(file2), "%s%c%c.%s", pattern1, '_', symbol, pattern2);
+ if (_res->exists(file1)) {
+ char *f = new char[strlen(file1) + 1];
+ strcpy(f, file1);
+ playList.push_back(f);
+ } else if (_res->exists(file2)) {
+ char *f = new char[strlen(file2) + 1];
+ strcpy(f, file2);
+ playList.push_back(f);
+ } else {
+ break;
+ }
}
}
@@ -1381,6 +1412,11 @@ int LoLEngine::snd_characterSpeaking() {
_lastSpeechId = _lastSpeaker = -1;
_activeVoiceFileTotalTime = 0;
+ if (_nextSpeechId != -1) {
+ if (snd_playCharacterSpeech(_nextSpeechId, _nextSpeaker, 0))
+ return 2;
+ }
+
return 1;
}
@@ -1391,6 +1427,7 @@ void LoLEngine::snd_stopSpeech(bool setFlag) {
//_dlgTimer = 0;
_sound->voiceStop(_activeVoiceFile);
_activeVoiceFileTotalTime = 0;
+ _nextSpeechId = _nextSpeaker = -1;
if (setFlag)
_tim->_abortFlag = 1;
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h
index f433de7f4c..3759953536 100644
--- a/engines/kyra/lol.h
+++ b/engines/kyra/lol.h
@@ -344,6 +344,8 @@ private:
int _environmentSfx;
int _environmentSfxVol;
int _environmentSfxDistThreshold;
+ int _nextSpeechId;
+ int _nextSpeaker;
int _curTlkFile;
int _speechFlag;
@@ -476,7 +478,7 @@ private:
// text
bool characterSays(int track, int charId, bool redraw);
- int playCharacterScriptChat(int charId, int y, int unk1, char *str, EMCState *script, const uint16 *paramList, int16 paramIndex);
+ int playCharacterScriptChat(int charId, int mode, int unk1, char *str, EMCState *script, const uint16 *paramList, int16 paramIndex);
TextDisplayer_LoL *_txt;
@@ -516,12 +518,17 @@ private:
int olol_closeLevelShapeFile(EMCState *script);
int olol_loadDoorShapes(EMCState *script);
int olol_initAnimStruct(EMCState *script);
+ int olol_playAnimSequence(EMCState *script);
int olol_freeAnimStruct(EMCState *script);
int olol_getDirection(EMCState *script);
int olol_setMusicTrack(EMCState *script);
int olol_checkRectForMousePointer(EMCState *script);
int olol_clearDialogueField(EMCState *script);
+ int olol_setupBackgroundAnimationPart(EMCState *script);
+ int olol_startBackgroundAnimation(EMCState *script);
+ int olol_fadePalette(EMCState *script);
int olol_loadBitmap(EMCState *script);
+ int olol_stopBackgroundAnimation(EMCState *script);
int olol_getGlobalScriptVar(EMCState *script);
int olol_setGlobalScriptVar(EMCState *script);
int olol_getGlobalVar(EMCState *script);
@@ -533,10 +540,14 @@ private:
int olol_copyRegion(EMCState *script);
int olol_initMonster(EMCState *script);
int olol_fadeClearSceneWindow(EMCState *script);
+ int olol_fadeSequencePalette(EMCState *script);
int olol_loadMonsterProperties(EMCState *script);
int olol_moveMonster(EMCState *script);
int olol_dialogueBox(EMCState *script);
+ int olol_giveTakeMoney(EMCState *script);
+ int olol_checkMoney(EMCState *script);
int olol_setScriptTimer(EMCState *script);
+ int olol_createHandItem(EMCState *script);
int olol_loadTimScript(EMCState *script);
int olol_runTimScript(EMCState *script);
int olol_releaseTimScript(EMCState *script);
@@ -562,11 +573,15 @@ private:
int olol_setNextFunc(EMCState *script);
int olol_setDoorState(EMCState *script);
int olol_processButtonClick(EMCState *script);
+ int olol_savePage5(EMCState *script);
+ int olol_restorePage5(EMCState *script);
int olol_initNonAnimatedDialogue(EMCState *script);
int olol_restoreAfterNonAnimatedDialogue(EMCState *script);
int olol_assignCustomSfx(EMCState *script);
int olol_resetPortraitsArea(EMCState *script);
int olol_enableSysTimer(EMCState *script);
+ int olol_queueSpeech(EMCState *script);
+ int olol_getItemPrice(EMCState *script);
// tim scripts
TIM *_activeTim[10];
@@ -586,11 +601,16 @@ private:
int tlol_giveItem(const TIM *tim, const uint16 *param);
int tlol_setPartyPosition(const TIM *tim, const uint16 *param);
int tlol_fadeClearWindow(const TIM *tim, const uint16 *param);
+ int tlol_copyRegion(const TIM *tim, const uint16 *param);
+ int tlol_characterChat(const TIM *tim, const uint16 *param);
+ int tlol_drawScene(const TIM *tim, const uint16 *param);
int tlol_update(const TIM *tim, const uint16 *param);
int tlol_loadSoundFile(const TIM *tim, const uint16 *param);
int tlol_playMusicTrack(const TIM *tim, const uint16 *param);
int tlol_playDialogueTalkText(const TIM *tim, const uint16 *param);
int tlol_playSoundEffect(const TIM *tim, const uint16 *param);
+ int tlol_startBackgroundAnimation(const TIM *tim, const uint16 *param);
+ int tlol_stopBackgroundAnimation(const TIM *tim, const uint16 *param);
Common::Array<const TIMOpcode*> _timIngameOpcodes;
@@ -619,7 +639,9 @@ private:
void fadeText();
void setPaletteBrightness(uint8 *palette, int brightness, int modifier);
void generateBrightnessPalette(uint8 *src, uint8 *dst, int brightness, int modifier);
- void updateWsaAnimations();
+ void updateSequenceBackgroundAnimations();
+ void savePage5();
+ void restorePage5();
bool _dialogueField;
uint8 **_itemIconShapes;
@@ -640,6 +662,8 @@ private:
uint8 *_characterFaceShapes[40][3];
+ bool _pageSavedFlag;
+
// characters
bool addCharacter(int id);
void initCharacter(int charNum, int firstFaceFrame, int unk2, int redraw);
@@ -916,6 +940,7 @@ private:
// items
void giveCredits(int credits, int redraw);
+ void takeCredits(int credits, int redraw);
int makeItem(int itemIndex, int curFrame, int flags);
bool addItemToInventory(int itemIndex);
bool testUnkItemFlags(int itemIndex);
@@ -940,15 +965,18 @@ private:
int _hideControls;
int _lastCharInventory;
+ EMCData _itemScript;
+
const uint8 *_charInvIndex;
int _charInvIndexSize;
const uint8 *_charInvDefs;
int _charInvDefsSize;
-
- EMCData _itemScript;
-
const uint16 *_inventorySlotDesc;
int _inventorySlotDescSize;
+ const uint16 *_itemCost;
+ int _itemCostSize;
+ const uint8 *_stashSetupData;
+ int _stashSetupDataSize;
// monsters
void loadMonsterShapes(const char *file, int monsterIndex, int b);
diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h
index 66cc883667..3de89bc3c9 100644
--- a/engines/kyra/resource.h
+++ b/engines/kyra/resource.h
@@ -240,6 +240,8 @@ enum kKyraResources {
kLolLevelShpList,
kLolLevelDatList,
kLolCompassDefs,
+ kLolItemPrices,
+ kLolStashSetup,
kLolDscUnk1,
kLolDscShapeIndex,
diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp
index 2e6e9671ec..d9a7d9cb6e 100644
--- a/engines/kyra/script_lol.cpp
+++ b/engines/kyra/script_lol.cpp
@@ -421,6 +421,12 @@ int LoLEngine::olol_initAnimStruct(EMCState *script) {
return 0;
}
+int LoLEngine::olol_playAnimSequence(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playAnimSequence(%p) (%s, %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3));
+
+ return 1;
+}
+
int LoLEngine::olol_freeAnimStruct(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_freeAnimStruct(%p) (%d)", (const void *)script, stackPos(0));
if (_tim->freeAnimStruct(stackPos(0)))
@@ -457,6 +463,25 @@ int LoLEngine::olol_clearDialogueField(EMCState *script) {
return 1;
}
+int LoLEngine::olol_setupBackgroundAnimationPart(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setupBackgroundAnimationPart(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9));
+ _tim->setupBackgroundAnimationPart(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9));
+ return 0;
+}
+
+int LoLEngine::olol_startBackgroundAnimation(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_startBackgroundAnimation(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ _tim->startBackgroundAnimation(stackPos(0), stackPos(1));
+ return 1;
+}
+
+int LoLEngine::olol_fadePalette(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_fadePalette(%p)", (const void *)script);
+ _screen->fadePalette(_screen->getPalette(3), 10);
+ _screen->_fadeFlag = 0;
+ return 1;
+}
+
int LoLEngine::olol_loadBitmap(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_clearDialogueField(%p) (%s, %d)", (const void *)script, stackPosString(0), stackPos(1));
_screen->loadBitmap(stackPosString(0), 3, 3, _screen->getPalette(3));
@@ -465,6 +490,12 @@ int LoLEngine::olol_loadBitmap(EMCState *script) {
return 1;
}
+int LoLEngine::olol_stopBackgroundAnimation(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_stopBackgroundAnimation(%p) (%d)", (const void *)script, stackPos(0));
+ _tim->stopBackgroundAnimation(stackPos(0));
+ return 1;
+}
+
int LoLEngine::olol_getGlobalScriptVar(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getGlobalScriptVar(%p) (%d)", (const void *)script, stackPos(0));
assert(stackPos(0) < 16);
@@ -681,6 +712,15 @@ int LoLEngine::olol_fadeClearSceneWindow(EMCState *script) {
return 1;
}
+int LoLEngine::olol_fadeSequencePalette(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_fadeSequencePalette(%p)", (const void *)script);
+ memcpy(_screen->getPalette(3) + 0x180, _screen->_currentPalette + 0x180, 0x180);
+ _screen->loadSpecialColours(_screen->getPalette(3));
+ _screen->fadePalette(_screen->getPalette(3), 10);
+ _screen->_fadeFlag = 0;
+ return 1;
+}
+
int LoLEngine::olol_loadMonsterProperties(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_loadMonsterProperties(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)",
(const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5),
@@ -763,6 +803,22 @@ int LoLEngine::olol_dialogueBox(EMCState *script) {
return 1;
}
+int LoLEngine::olol_giveTakeMoney(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_giveTakeMoney(%p) (%d)", (const void *)script, stackPos(0));
+ int c = stackPos(0);
+ if (c >= 0)
+ giveCredits(c, 1);
+ else
+ takeCredits(-c, 1);
+
+ return 1;
+}
+
+int LoLEngine::olol_checkMoney(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_checkMoney(%p) (%d)", (const void *)script, stackPos(0));
+ return (stackPos(0) > _credits) ? 0 : 1;
+}
+
int LoLEngine::olol_setScriptTimer(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setScriptTimer(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
uint8 id = 0x50 + stackPos(0);
@@ -778,6 +834,14 @@ int LoLEngine::olol_setScriptTimer(EMCState *script) {
return 1;
}
+int LoLEngine::olol_createHandItem(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_createHandItem(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ if (_itemInHand)
+ return 0;
+ setHandItem(makeItem(stackPos(0), stackPos(1), stackPos(2)));
+ return 1;
+}
+
int LoLEngine::olol_loadTimScript(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_loadTimScript(%p) (%d, %s)", (const void *)script, stackPos(0), stackPosString(1));
if (_activeTim[stackPos(0)])
@@ -967,10 +1031,19 @@ int LoLEngine::olol_setDoorState(EMCState *script) {
int LoLEngine::olol_processButtonClick(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_processButtonClick(%p) (%d)", (const void *)script, stackPos(0));
- int n = _tim->getNumberOfDialogueButtons();
- _activeTim[stackPos(0)]->procFunc = 0;
- _activeTim[stackPos(0)]->procParam = n ? n : 1;
- _tim->setDialogueParameters(0, -1);
+ _tim->resetDialogueState(_activeTim[stackPos(0)]);
+ return 1;
+}
+
+int LoLEngine::olol_savePage5(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_savePage5(%p)", (const void *)script);
+ savePage5();
+ return 1;
+}
+
+int LoLEngine::olol_restorePage5(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_restorePage5(%p)", (const void *)script);
+ restorePage5();
return 1;
}
@@ -1014,6 +1087,34 @@ int LoLEngine::olol_enableSysTimer(EMCState *script) {
return 1;
}
+int LoLEngine::olol_queueSpeech(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_queueSpeech(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ if (stackPos(0) && stackPos(1)) {
+ _nextSpeechId = stackPos(0) + 1000;
+ _nextSpeaker = stackPos(1);
+ }
+ return 1;
+}
+
+int LoLEngine::olol_getItemPrice(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getItemPrice(%p) (%d)", (const void *)script, stackPos(0));
+ int c = stackPos(0);
+ if (c < 0) {
+ c = -c;
+ if (c < 50)
+ return 50;
+ c = (c + 99) / 100;
+ return c * 100;
+
+ } else {
+ for (int i = 0; i < 46; i++) {
+ if (_itemCost[i] >= c)
+ return _itemCost[i];
+ }
+ }
+
+ return 0;
+}
#pragma mark -
@@ -1158,6 +1259,26 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) {
return 1;
}
+int LoLEngine::tlol_copyRegion(const TIM *tim, const uint16 *param) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_copyRegion(%p, %p) (%d, %d, %d, %d, %d, %d, %d, %d)", (const void*)tim, (const void*)param, param[0], param[1], param[2], param[3], param[4], param[5], param[6], param[7]);
+ _screen->copyRegion(param[0], param[1], param[2], param[3], param[4], param[5], param[6], param[7], Screen::CR_NO_P_CHECK);
+ return 1;
+}
+
+int LoLEngine::tlol_characterChat(const TIM *tim, const uint16 *param) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_characterChat(%p, %p) (%d, %d, %d)", (const void*)tim, (const void*)param, param[0], param[1], param[2]);
+ playCharacterScriptChat(param[0], param[1], 1, getLangString(param[2]), 0, param, 3);
+ return 1;
+}
+
+int LoLEngine::tlol_drawScene(const TIM *tim, const uint16 *param) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_drawScene(%p, %p) (%d)", (const void*)tim, (const void*)param, param[0]);
+ gui_drawScene(param[0]);
+ if (_sceneDrawPage2 != 2 && param[0] == 2)
+ _screen->copyRegion(112, 0, 112, 0, 176, 120, _sceneDrawPage2, 2, Screen::CR_NO_P_CHECK);
+ return 1;
+}
+
int LoLEngine::tlol_update(const TIM *tim, const uint16 *param) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_update(%p, %p)", (const void*)tim, (const void*)param);
update();
@@ -1189,6 +1310,18 @@ int LoLEngine::tlol_playSoundEffect(const TIM *tim, const uint16 *param) {
return 1;
}
+int LoLEngine::tlol_startBackgroundAnimation(const TIM *tim, const uint16 *param) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_startBackgroundAnimation(%p, %p) (%d, %d)", (const void*)tim, (const void*)param, param[0], param[1]);
+ _tim->startBackgroundAnimation(param[0], param[1]);
+ return 1;
+}
+
+int LoLEngine::tlol_stopBackgroundAnimation(const TIM *tim, const uint16 *param) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_stopBackgroundAnimation(%p, %p) (%d)", (const void*)tim, (const void*)param, param[0]);
+ _tim->stopBackgroundAnimation(param[0]);
+ return 1;
+}
+
#pragma mark -
typedef Common::Functor1Mem<EMCState*, int, LoLEngine> OpcodeV2;
@@ -1244,7 +1377,7 @@ void LoLEngine::setupOpcodeTable() {
// 0x18
Opcode(olol_loadDoorShapes);
Opcode(olol_initAnimStruct);
- OpcodeUnImpl();
+ Opcode(olol_playAnimSequence);
Opcode(olol_freeAnimStruct);
// 0x1C
@@ -1257,18 +1390,18 @@ void LoLEngine::setupOpcodeTable() {
OpcodeUnImpl();
Opcode(olol_checkRectForMousePointer);
Opcode(olol_clearDialogueField);
- OpcodeUnImpl();
+ Opcode(olol_setupBackgroundAnimationPart);
// 0x24
- OpcodeUnImpl();
+ Opcode(olol_startBackgroundAnimation);
OpcodeUnImpl();
OpcodeUnImpl();
OpcodeUnImpl();
// 0x28
- OpcodeUnImpl();
+ Opcode(olol_fadePalette);
Opcode(olol_loadBitmap);
- OpcodeUnImpl();
+ Opcode(olol_stopBackgroundAnimation);
OpcodeUnImpl();
// 0x2C
@@ -1292,7 +1425,7 @@ void LoLEngine::setupOpcodeTable() {
// 0x38
Opcode(olol_initMonster);
Opcode(olol_fadeClearSceneWindow);
- OpcodeUnImpl();
+ Opcode(olol_fadeSequencePalette);
OpcodeUnImpl();
// 0x3C
@@ -1310,12 +1443,12 @@ void LoLEngine::setupOpcodeTable() {
// 0x44
Opcode(olol_moveMonster);
Opcode(olol_dialogueBox);
- OpcodeUnImpl();
- OpcodeUnImpl();
+ Opcode(olol_giveTakeMoney);
+ Opcode(olol_checkMoney);
// 0x48
Opcode(olol_setScriptTimer);
- OpcodeUnImpl();
+ Opcode(olol_createHandItem);
OpcodeUnImpl();
OpcodeUnImpl();
@@ -1412,8 +1545,8 @@ void LoLEngine::setupOpcodeTable() {
// 0x88
OpcodeUnImpl();
OpcodeUnImpl();
- OpcodeUnImpl();
- OpcodeUnImpl();
+ Opcode(olol_savePage5);
+ Opcode(olol_restorePage5);
// 0x8C
Opcode(olol_initNonAnimatedDialogue);
@@ -1488,8 +1621,8 @@ void LoLEngine::setupOpcodeTable() {
OpcodeUnImpl();
// 0xBC
- OpcodeUnImpl();
- OpcodeUnImpl();
+ Opcode(olol_queueSpeech);
+ Opcode(olol_getItemPrice);
OpcodeUnImpl();
OpcodeUnImpl();
@@ -1519,11 +1652,11 @@ void LoLEngine::setupOpcodeTable() {
// 0x04
OpcodeTim(tlol_setPartyPosition);
OpcodeTim(tlol_fadeClearWindow);
- OpcodeTimUnImpl();
- OpcodeTimUnImpl();
+ OpcodeTim(tlol_copyRegion);
+ OpcodeTim(tlol_characterChat);
// 0x08
- OpcodeTimUnImpl();
+ OpcodeTim(tlol_drawScene);
OpcodeTim(tlol_update);
OpcodeTimUnImpl();
OpcodeTim(tlol_loadSoundFile);
@@ -1532,10 +1665,10 @@ void LoLEngine::setupOpcodeTable() {
OpcodeTim(tlol_playMusicTrack);
OpcodeTim(tlol_playDialogueTalkText);
OpcodeTim(tlol_playSoundEffect);
- OpcodeTimUnImpl();
+ OpcodeTim(tlol_startBackgroundAnimation);
// 0x10
- OpcodeTimUnImpl();
+ OpcodeTim(tlol_stopBackgroundAnimation);
}
} // end of namespace Kyra
diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp
index 3150e7ab01..207f53b8de 100644
--- a/engines/kyra/script_tim.cpp
+++ b/engines/kyra/script_tim.cpp
@@ -90,7 +90,9 @@ TIMInterpreter::TIMInterpreter(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSys
_commands = commandProcs ;
_commandsSize = ARRAYSIZE(commandProcs);
- memset(&_animations, 0, sizeof(_animations));
+ _animations = new Animation[TIM::kWSASlots];
+ memset(_animations, 0, TIM::kWSASlots * sizeof(Animation));
+
_langData = 0;
_textDisplayed = false;
_textAreaBuffer = new uint8[320*40];
@@ -104,6 +106,13 @@ TIMInterpreter::TIMInterpreter(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSys
TIMInterpreter::~TIMInterpreter() {
delete[] _langData;
delete[] _textAreaBuffer;
+
+ for (int i = 0; i < TIM::kWSASlots; i++) {
+ delete _animations[i].wsa;
+ delete[] _animations[i].parts;
+ }
+
+ delete[] _animations;
}
TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpcode*> *opcodes) {
@@ -196,7 +205,6 @@ int TIMInterpreter::exec(TIM *tim, bool loop) {
if (cnt++ > 0) {
if (_currentTim->procFunc != -1)
execCommand(28, &_currentTim->procParam);
-
update();
}
@@ -451,7 +459,6 @@ int TIMInterpreter::freeAnimStruct(int index) {
delete anim->wsa;
memset(anim, 0, sizeof(Animation));
-
return 1;
}
@@ -539,8 +546,16 @@ int TIMInterpreter::cmd_uninitWSA(const uint16 *param) {
//XXX
delete anim.wsa;
+ bool hasParts = anim.parts ? true : false;
+ delete[] anim.parts;
+
memset(&anim, 0, sizeof(Animation));
memset(&slot, 0, sizeof(TIM::WSASlot));
+
+ if (hasParts) {
+ anim.parts = new AnimPart[TIM::kAnimParts];
+ memset(anim.parts, 0, TIM::kAnimParts * sizeof(AnimPart));
+ }
}
return 1;
@@ -698,7 +713,7 @@ int TIMInterpreter::cmd_stopFuncNow(const uint16 *param) {
}
int TIMInterpreter::cmd_stopAllFuncs(const uint16 *param) {
- while (_currentTim->dlgFunc == -1 && _currentTim->clickedButton == 0 && vm()->shouldQuit()) {
+ while (_currentTim->dlgFunc == -1 && _currentTim->clickedButton == 0 && !vm()->shouldQuit()) {
update();
_currentTim->clickedButton = processDialogue();
}
@@ -768,6 +783,11 @@ TIMInterpreter_LoL::TIMInterpreter_LoL(LoLEngine *engine, Screen_v2 *screen_v2,
_commandsSize = ARRAYSIZE(commandProcs);
_screen = engine->_screen;
+
+ for (int i = 0; i < TIM::kWSASlots; i++) {
+ _animations[i].parts = new AnimPart[TIM::kAnimParts];
+ memset(_animations[i].parts, 0, TIM::kAnimParts * sizeof(AnimPart));
+ }
_drawPage2 = 0;
@@ -775,11 +795,14 @@ TIMInterpreter_LoL::TIMInterpreter_LoL(LoLEngine *engine, Screen_v2 *screen_v2,
_dialogueButtonPosX = _dialogueButtonPosY = _dialogueNumButtons = _dialogueButtonXoffs = _dialogueHighlightedButton = 0;
}
-TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const char *filename, int x, int y, int copyPara, int, uint16 wsaFlags) {
+TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int offscreenBuffer, uint16 wsaFlags) {
Animation *anim = &_animations[index];
anim->x = x;
anim->y = y;
+ anim->frameDelay = frameDelay;
anim->wsaCopyParams = wsaFlags;
+ anim->enable = 0;
+ anim->lastPart = -1;
uint16 wsaOpenFlags = 0;
if (wsaFlags & 0x10)
@@ -822,6 +845,21 @@ TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const c
return anim;
}
+int TIMInterpreter_LoL::freeAnimStruct(int index) {
+ Animation *anim = &_animations[index];
+ if (!anim)
+ return 0;
+
+ delete anim->wsa;
+ delete[] anim->parts;
+ memset(anim, 0, sizeof(Animation));
+
+ anim->parts = new AnimPart[TIM::kAnimParts];
+ memset(anim->parts, 0, TIM::kAnimParts * sizeof(AnimPart));
+
+ return 1;
+}
+
KyraEngine_v1 *TIMInterpreter_LoL::vm() {
return _vm;
}
@@ -847,11 +885,12 @@ void TIMInterpreter_LoL::advanceToOpcode(int opcode) {
}
void TIMInterpreter_LoL::drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3) {
+ _screen->setScreenDim(5);
+
if (numStr == 1 && _vm->_speechFlag) {
- _screen->setScreenDim(5);
+ _dialogueNumButtons = 0;
_dialogueButtonString[0] = _dialogueButtonString[1] = _dialogueButtonString[2] = 0;
} else {
- _screen->setScreenDim(5);
_dialogueNumButtons = numStr;
_dialogueButtonString[0] = s1;
_dialogueButtonString[1] = s2;
@@ -876,6 +915,96 @@ void TIMInterpreter_LoL::drawDialogueBox(int numStr, const char *s1, const char
_vm->removeInputTop();
}
+void TIMInterpreter_LoL::setupBackgroundAnimationPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame) {
+ AnimPart *a = &_animations[animIndex].parts[part];
+ a->firstFrame = firstFrame;
+ a->lastFrame = lastFrame;
+ a->cycles = cycles;
+ a->nextPart = nextPart;
+ a->partDelay = partDelay;
+ a->field_A = f;
+ a->sfxIndex = sfxIndex;
+ a->sfxFrame = sfxFrame;
+}
+
+void TIMInterpreter_LoL::startBackgroundAnimation(int animIndex, int part) {
+ Animation *anim = &_animations[animIndex];
+ anim->curPart = part;
+ AnimPart *p = &anim->parts[part];
+ anim->enable = 1;
+ anim->nextFrame = _system->getMillis() + anim->frameDelay * _vm->_tickLength;
+ anim->curFrame = p->firstFrame;
+ anim->cyclesCompleted = 0;
+
+ anim->wsa->setX(anim->x);
+ anim->wsa->setY(anim->y);
+ anim->wsa->setDrawPage(0);
+ anim->wsa->displayFrame(anim->curFrame - 1, 0, 0);
+}
+
+void TIMInterpreter_LoL::stopBackgroundAnimation(int animIndex) {
+ Animation *anim = &_animations[animIndex];
+ anim->enable = 0;
+ anim->field_D = 0;
+ if (animIndex == 5) {
+ delete anim->wsa;
+ anim->wsa = 0;
+ }
+}
+
+void TIMInterpreter_LoL::updateBackgroundAnimation(int animIndex) {
+ Animation *anim = &_animations[animIndex];
+ if (!anim->enable || anim->nextFrame >= _system->getMillis())
+ return;
+
+ AnimPart *p = &anim->parts[anim->curPart];
+ anim->nextFrame = 0;
+
+ int step = 0;
+ if (p->lastFrame >= p->firstFrame) {
+ step = 1;
+ anim->curFrame++;
+ } else {
+ step = -1;
+ anim->curFrame--;
+ }
+
+ if (anim->curFrame == (p->lastFrame + step)) {
+ anim->cyclesCompleted++;
+
+ if ((anim->cyclesCompleted > p->cycles) || anim->field_D) {
+ anim->lastPart = anim->curPart;
+
+ if ((p->nextPart == -1) || (anim->field_D && p->field_A)) {
+ anim->enable = 0;
+ anim->field_D = 0;
+ return;
+ }
+
+ anim->nextFrame += (p->partDelay * _vm->_tickLength);
+ anim->curPart = p->nextPart;
+
+ p = &anim->parts[anim->curPart];
+ anim->curFrame = p->firstFrame;
+ anim->cyclesCompleted = 0;
+
+ } else {
+ anim->curFrame = p->firstFrame;
+ }
+ }
+
+ if (p->sfxIndex != -1 && p->sfxFrame == anim->curFrame)
+ _vm->snd_playSoundEffect(p->sfxIndex, -1);
+
+ anim->nextFrame += (anim->frameDelay * _vm->_tickLength);
+
+ anim->wsa->setX(anim->x);
+ anim->wsa->setY(anim->y);
+ anim->wsa->setDrawPage(0);
+ anim->wsa->displayFrame(anim->curFrame - 1, 0, 0);
+ anim->nextFrame += _system->getMillis();
+}
+
void TIMInterpreter_LoL::drawDialogueButtons() {
int cp = _screen->setCurPage(0);
Screen::FontId of = _screen->setFont(Screen::FID_6_FNT);
@@ -996,6 +1125,16 @@ uint16 TIMInterpreter_LoL::processDialogue() {
return res;
}
+void TIMInterpreter_LoL::resetDialogueState(TIM *tim) {
+ if (!tim)
+ return;
+
+ tim->procFunc = 0;
+ tim->procParam = _dialogueNumButtons ? _dialogueNumButtons : 1;
+ tim->clickedButton = 0;
+ tim->dlgFunc = -1;
+}
+
void TIMInterpreter_LoL::update() {
_vm->update();
}
@@ -1007,6 +1146,10 @@ void TIMInterpreter_LoL::checkSpeechProgress() {
_currentTim->dlgFunc = _currentFunc;
advanceToOpcode(21);
_currentTim->dlgFunc = -1;
+ _animations[5].field_D = 0;
+ _animations[5].enable = 0;
+ delete _animations[5].wsa;
+ _animations[5].wsa = 0;
}
}
}
@@ -1064,8 +1207,8 @@ int TIMInterpreter_LoL::cmd_continueLoop(const uint16 *param) {
int TIMInterpreter_LoL::cmd_processDialogue(const uint16 *param) {
int res = processDialogue();
- if (!res ||!_currentTim->procParam)
- return 0;
+ if (!res || !_currentTim->procParam)
+ return res;
_vm->snd_stopSpeech(false);
@@ -1074,6 +1217,11 @@ int TIMInterpreter_LoL::cmd_processDialogue(const uint16 *param) {
_currentTim->procFunc = -1;
_currentTim->clickedButton = res;
+ _animations[5].field_D = 0;
+ _animations[5].enable = 0;
+ delete _animations[5].wsa;
+ _animations[5].wsa = 0;
+
if (_currentTim->procParam)
advanceToOpcode(21);
diff --git a/engines/kyra/script_tim.h b/engines/kyra/script_tim.h
index eb3d972fa2..f73c63a2c7 100644
--- a/engines/kyra/script_tim.h
+++ b/engines/kyra/script_tim.h
@@ -64,7 +64,8 @@ struct TIM {
} func[kCountFuncs];
enum {
- kWSASlots = 10
+ kWSASlots = 6,
+ kAnimParts = 10
};
struct WSASlot {
@@ -83,10 +84,30 @@ struct TIM {
class TIMInterpreter {
public:
+ struct AnimPart {
+ uint16 firstFrame;
+ uint16 lastFrame;
+ uint16 cycles;
+ int16 nextPart;
+ int16 partDelay;
+ uint16 field_A;
+ int16 sfxIndex;
+ uint16 sfxFrame;
+ };
+
struct Animation {
WSAMovie_v2 *wsa;
int16 x, y;
+ uint32 nextFrame;
+ uint8 enable;
+ uint8 field_D;
+ uint8 frameDelay;
+ int8 curPart;
+ uint8 curFrame;
+ uint8 cyclesCompleted;
uint16 wsaCopyParams;
+ int8 lastPart;
+ AnimPart *parts;
};
TIMInterpreter(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSystem *system);
@@ -96,7 +117,7 @@ public:
void unload(TIM *&tim) const;
virtual Animation *initAnimStruct(int index, const char *filename, int x, int y, int, int offscreenBuffer, uint16 wsaFlags);
- int freeAnimStruct(int index);
+ virtual int freeAnimStruct(int index);
void setLangData(const char *filename);
void clearLangData() { delete[] _langData; _langData = 0; }
@@ -118,8 +139,12 @@ public:
virtual void drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3) {}
virtual uint16 processDialogue() { return 1; }
- void setDialogueParameters(int clickedButton, int dlgFunc) { _currentTim->clickedButton = clickedButton; _currentTim->dlgFunc = dlgFunc; }
- virtual int getNumberOfDialogueButtons() { return 0; }
+ virtual void setupBackgroundAnimationPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame) {}
+ virtual void startBackgroundAnimation(int animIndex, int part) {}
+ virtual void stopBackgroundAnimation(int animIndex) {}
+ virtual void updateBackgroundAnimation(int animIndex) {}
+
+ virtual void resetDialogueState(TIM *tim) {}
int _drawPage2;
@@ -141,7 +166,7 @@ protected:
Common::String _vocFiles[120];
- Animation _animations[TIM::kWSASlots];
+ Animation *_animations;
virtual void update() {}
virtual void checkSpeechProgress() {}
@@ -199,12 +224,19 @@ class TIMInterpreter_LoL : public TIMInterpreter {
friend class LoLEngine;
public:
TIMInterpreter_LoL(LoLEngine *engine, Screen_v2 *screen_v2, OSystem *system);
- Animation *initAnimStruct(int index, const char *filename, int x, int y, int copyPara, int, uint16 wsaFlags);
+ Animation *initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int offscreenBuffer, uint16 wsaCopyParams);
+ int freeAnimStruct(int index);
+
void drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3);
uint16 processDialogue();
+
+ void setupBackgroundAnimationPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame);
+ void startBackgroundAnimation(int animIndex, int part);
+ void stopBackgroundAnimation(int animIndex);
+ void updateBackgroundAnimation(int animIndex);
- int getNumberOfDialogueButtons() { return _dialogueNumButtons; }
+ void resetDialogueState(TIM *tim);
private:
KyraEngine_v1 *vm();
@@ -212,7 +244,7 @@ private:
void update();
void checkSpeechProgress();
-
+
char *getTableString(int id);
void advanceToOpcode(int opcode);
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index 03bc59448b..dfe1f00d56 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -44,7 +44,7 @@
namespace Kyra {
-#define RESFILE_VERSION 40
+#define RESFILE_VERSION 41
namespace {
bool checkKyraDat(Common::SeekableReadStream *file) {
@@ -401,6 +401,8 @@ bool StaticResource::init() {
{ kLolLevelShpList, kStringList, "SHPFILES.TXT" },
{ kLolLevelDatList, kStringList, "DATFILES.TXT" },
{ kLolCompassDefs, kLolCompassData, "COMPASS.DEF" },
+ { kLolItemPrices, kLolRawDataBe16, "ITEMCOST.DEF" },
+ { kLolStashSetup, kRawData, "MONEYSTS.DEF" },
{ kLolDscUnk1, kRawData, "DSCSHPU1.DEF" },
{ kLolDscShapeIndex, kRawData, "DSCSHPI1.DEF" },
@@ -1771,6 +1773,8 @@ void LoLEngine::initStaticResource() {
_levelShpList = _staticres->loadStrings(kLolLevelShpList, _levelShpListSize);
_levelDatList = _staticres->loadStrings(kLolLevelDatList, _levelDatListSize);
_compassDefs = _staticres->loadCompassData(kLolCompassDefs, _compassDefsSize);
+ _itemCost = _staticres->loadRawDataBe16(kLolItemPrices, _itemCostSize);
+ _stashSetupData = _staticres->loadRawData(kLolStashSetup, _stashSetupDataSize);
_dscUnk1 = (const int8*)_staticres->loadRawData(kLolDscUnk1, _dscUnk1Size);
_dscShapeIndex = (const int8*)_staticres->loadRawData(kLolDscShapeIndex, _dscShapeIndexSize);
diff --git a/engines/kyra/text_lol.cpp b/engines/kyra/text_lol.cpp
index 99be70214a..7b0024d62d 100644
--- a/engines/kyra/text_lol.cpp
+++ b/engines/kyra/text_lol.cpp
@@ -187,15 +187,16 @@ void TextDisplayer_LoL::printMessage(uint16 type, char *str, ...) {
if (_vm->_updateFlags & 2) {
_screen->setScreenDim(4);
- clearCurDim();
+ clearCurDim();
+ _colour1 = col;
} else {
_screen->setScreenDim(3);
clearCurDim();
_screen->copyColour(192, col);
+ _colour1 = 192;
_vm->enableTimer(11);
}
-
- _colour1 = 192;
+
_colour1prot = true;
va_list args;
@@ -551,7 +552,11 @@ void TextDisplayer_LoL::printLine(char *str) {
if (str[s] == ' ')
s++;
- strcpy(str, &str[s]);
+ uint32 len = strlen(&str[s]);
+ for (uint32 i = 0; i < len; i++)
+ str[i] = str[s + i];
+ str[len] = 0;
+
_numCharsLeft = strlen(str);
_lineWidth = _screen->getTextWidth(str);