/engines/kyra/lol.cpp
C++ | 4513 lines | 3520 code | 925 blank | 68 comment | 918 complexity | f942aa9b567e49540d9a3439c93ff8fe MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1, GPL-2.0
Large files files are truncated, but you can click here to view the full file
- /* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
- #ifdef ENABLE_LOL
- #include "kyra/lol.h"
- #include "kyra/screen_lol.h"
- #include "kyra/resource.h"
- #include "kyra/timer.h"
- #include "kyra/util.h"
- #include "kyra/debugger.h"
- #include "kyra/sound.h"
- #include "audio/audiostream.h"
- #include "common/config-manager.h"
- #include "common/system.h"
- #include "common/translation.h"
- #include "backends/keymapper/keymapper.h"
- namespace Kyra {
- const char *const LoLEngine::kKeymapName = "lol";
- LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraRpgEngine(system, flags) {
- _screen = 0;
- _gui = 0;
- _tim = 0;
- _lang = 0;
- Common::Language lang = Common::parseLanguage(ConfMan.get("language"));
- if (lang == _flags.fanLang && _flags.replacedLang != Common::UNK_LANG)
- lang = _flags.replacedLang;
- switch (lang) {
- case Common::EN_ANY:
- case Common::EN_USA:
- case Common::EN_GRB:
- _lang = 0;
- break;
- case Common::FR_FRA:
- _lang = 1;
- break;
- case Common::DE_DEU:
- _lang = 2;
- break;
- case Common::JA_JPN:
- _lang = 0;
- break;
- default:
- warning("unsupported language, switching back to English");
- _lang = 0;
- }
- _chargenFrameTable = _flags.isTalkie ? _chargenFrameTableTalkie : _chargenFrameTableFloppy;
- _chargenWSA = 0;
- _lastUsedStringBuffer = 0;
- _landsFile = 0;
- _levelLangFile = 0;
- _lastMusicTrack = -1;
- _lastSfxTrack = -1;
- _curTlkFile = -1;
- _lastSpeaker = _lastSpeechId = _nextSpeechId = _nextSpeaker = -1;
- memset(_moneyColumnHeight, 0, sizeof(_moneyColumnHeight));
- _credits = 0;
- _itemsInPlay = 0;
- _itemProperties = 0;
- _itemInHand = 0;
- memset(_inventory, 0, sizeof(_inventory));
- memset(_charStatusFlags, 0, sizeof(_charStatusFlags));
- _inventoryCurItem = 0;
- _lastCharInventory = -1;
- _emcLastItem = -1;
- _itemIconShapes = _itemShapes = _gameShapes = _thrownShapes = _effectShapes = _fireballShapes = _healShapes = _healiShapes = 0;
- _levelShpList = _levelDatList = 0;
- _gameShapeMap = 0;
- memset(_monsterAnimType, 0, 3);
- _healOverlay = 0;
- _swarmSpellStatus = 0;
- _ingameMT32SoundIndex = _ingameGMSoundIndex = _ingamePCSpeakerSoundIndex = 0;
- _charSelection = -1;
- _characters = 0;
- _spellProperties = 0;
- _selectedSpell = 0;
- _updateCharNum = _portraitSpeechAnimMode = _textColorFlag = 0;
- _palUpdateTimer = _updatePortraitNext = 0;
- _lampStatusTimer = 0xFFFFFFFF;
- _weaponsDisabled = false;
- _charInventoryUnk = 0;
- _lastButtonShape = 0;
- _buttonPressTimer = 0;
- _selectedCharacter = 0;
- _suspendScript = false;
- _scriptDirection = 0;
- _compassDirectionIndex = -1;
- _compassStep = 0;
- _smoothScrollModeNormal = 1;
- _wllAutomapData = 0;
- _sceneXoffset = 112;
- _sceneShpDim = 13;
- _monsters = 0;
- _monsterProperties = 0;
- _lvlShapeIndex = 0;
- _partyAwake = true;
- _transparencyTable2 = 0;
- _transparencyTable1 = 0;
- _specialGuiShape = 0;
- _specialGuiShapeX = _specialGuiShapeY = _specialGuiShapeMirrorFlag = 0;
- memset(_characterFaceShapes, 0, sizeof(_characterFaceShapes));
- _lampEffect = _brightness = _lampOilStatus = 0;
- _lampStatusSuspended = false;
- _tempBuffer5120 = 0;
- _flyingObjects = 0;
- _monsters = 0;
- _lastMouseRegion = 0;
- _objectLastDirection = 0;
- _monsterCurBlock = 0;
- _seqWindowX1 = _seqWindowY1 = _seqWindowX2 = _seqWindowY2 = _seqTrigger = 0;
- _spsWindowX = _spsWindowY = _spsWindowW = _spsWindowH = 0;
- _dscWalls = 0;
- _dscOvlMap = 0;
- _dscShapeScaleW = 0;
- _dscShapeScaleH = 0;
- _dscShapeY = 0;
- _dscShapeOvlIndex = 0;
- _dscDoorMonsterX = _dscDoorMonsterY = 0;
- _dscDoor4 = 0;
- _ingameSoundList = 0;
- _ingameSoundIndex = 0;
- _ingameSoundListSize = 0;
- _musicTrackMap = 0;
- _curMusicTheme = -1;
- _curMusicFileExt = 0;
- _curMusicFileIndex = -1;
- _envSfxUseQueue = false;
- _envSfxNumTracksInQueue = 0;
- memset(_envSfxQueuedTracks, 0, sizeof(_envSfxQueuedTracks));
- memset(_envSfxQueuedBlocks, 0, sizeof(_envSfxQueuedBlocks));
- _partyPosX = _partyPosY = 0;
- _shpDmX = _shpDmY = _dmScaleW = _dmScaleH = 0;
- _floatingCursorControl = _currentFloatingCursor = 0;
- memset(_activeTim, 0, sizeof(_activeTim));
- memset(&_activeSpell, 0, sizeof(_activeSpell));
- _pageBuffer1 = _pageBuffer2 = 0;
- memset(_charStatsTemp, 0, sizeof(_charStatsTemp));
- _compassBroken = _drainMagic = 0;
- _buttonData = 0;
- _preserveEvents = false;
- _buttonList1 = _buttonList2 = _buttonList3 = _buttonList4 = _buttonList5 = _buttonList6 = _buttonList7 = _buttonList8 = 0;
- _mapOverlay = 0;
- _automapShapes = 0;
- _defaultLegendData = 0;
- _mapCursorOverlay = 0;
- _lightningProps = 0;
- _lightningCurSfx = -1;
- _lightningDiv = 0;
- _lightningFirstSfx = 0;
- _lightningSfxFrame = 0;
- _compassTimer = 0;
- _scriptCharacterCycle = 0;
- _partyDamageFlags = -1;
- memset(&_itemScript, 0, sizeof(_itemScript));
- }
- LoLEngine::~LoLEngine() {
- setupPrologueData(false);
- releaseTempData();
- delete[] _landsFile;
- delete[] _levelLangFile;
- delete _screen;
- _screen = 0;
- delete _gui;
- _gui = 0;
- delete _tim;
- _tim = 0;
- delete _txt;
- _txt = 0;
- delete[] _itemsInPlay;
- delete[] _itemProperties;
- delete[] _characters;
- delete[] _pageBuffer1;
- delete[] _pageBuffer2;
- if (_itemIconShapes) {
- for (int i = 0; i < _numItemIconShapes; i++)
- delete[] _itemIconShapes[i];
- delete[] _itemIconShapes;
- }
- if (_itemShapes) {
- for (int i = 0; i < _numItemShapes; i++)
- delete[] _itemShapes[i];
- delete[] _itemShapes;
- }
- if (_gameShapes) {
- for (int i = 0; i < _numGameShapes; i++)
- delete[] _gameShapes[i];
- delete[] _gameShapes;
- }
- if (_thrownShapes) {
- for (int i = 0; i < _numThrownShapes; i++)
- delete[] _thrownShapes[i];
- delete[] _thrownShapes;
- }
- if (_effectShapes) {
- for (int i = 0; i < _numEffectShapes; i++)
- delete[] _effectShapes[i];
- delete[] _effectShapes;
- }
- if (_fireballShapes) {
- for (int i = 0; i < _numFireballShapes; i++)
- delete[] _fireballShapes[i];
- delete[] _fireballShapes;
- }
- if (_healShapes) {
- for (int i = 0; i < _numHealShapes; i++)
- delete[] _healShapes[i];
- delete[] _healShapes;
- }
- if (_healiShapes) {
- for (int i = 0; i < _numHealiShapes; i++)
- delete[] _healiShapes[i];
- delete[] _healiShapes;
- }
- if (_monsterDecorationShapes) {
- for (int i = 0; i < 3; i++)
- releaseMonsterShapes(i);
- delete[] _monsterShapes;
- _monsterShapes = 0;
- delete[] _monsterPalettes;
- _monsterPalettes = 0;
- delete[] _monsterDecorationShapes;
- _monsterDecorationShapes = 0;
- }
- for (int i = 0; i < 6; i++) {
- delete[] _doorShapes[i];
- _doorShapes[i] = 0;
- }
- releaseDecorations();
- delete[] _automapShapes;
- for (Common::Array<const TIMOpcode *>::iterator i = _timIntroOpcodes.begin(); i != _timIntroOpcodes.end(); ++i)
- delete *i;
- _timIntroOpcodes.clear();
- for (Common::Array<const TIMOpcode *>::iterator i = _timOutroOpcodes.begin(); i != _timOutroOpcodes.end(); ++i)
- delete *i;
- _timOutroOpcodes.clear();
- for (Common::Array<const TIMOpcode *>::iterator i = _timIngameOpcodes.begin(); i != _timIngameOpcodes.end(); ++i)
- delete *i;
- _timIngameOpcodes.clear();
- delete[] _wllAutomapData;
- delete[] _tempBuffer5120;
- delete[] _flyingObjects;
- delete[] _monsters;
- delete[] _monsterProperties;
- delete[] _transparencyTable2;
- delete[] _transparencyTable1;
- delete[] _lightningProps;
- delete _lvlShpFileHandle;
- if (_ingameSoundList) {
- for (int i = 0; i < _ingameSoundListSize; i++)
- delete[] _ingameSoundList[i];
- delete[] _ingameSoundList;
- }
- for (int i = 0; i < 3; i++) {
- for (int ii = 0; ii < 40; ii++)
- delete[] _characterFaceShapes[ii][i];
- }
- delete[] _healOverlay;
- delete[] _defaultLegendData;
- delete[] _mapCursorOverlay;
- delete[] _mapOverlay;
- for (Common::Array<const SpellProc *>::iterator i = _spellProcs.begin(); i != _spellProcs.end(); ++i)
- delete *i;
- _spellProcs.clear();
- for (SpeechList::iterator i = _speechList.begin(); i != _speechList.end(); ++i)
- delete *i;
- _speechList.clear();
- _emc->unload(&_itemScript);
- _emc->unload(&_scriptData);
- }
- Screen *LoLEngine::screen() {
- return _screen;
- }
- GUI *LoLEngine::gui() const {
- return _gui;
- }
- Common::Error LoLEngine::init() {
- _screen = new Screen_LoL(this, _system);
- assert(_screen);
- _screen->setResolution();
- _debugger = new Debugger_LoL(this);
- assert(_debugger);
- KyraEngine_v1::init();
- initStaticResource();
- _gui = new GUI_LoL(this);
- assert(_gui);
- _gui->initStaticData();
- _txt = new TextDisplayer_LoL(this, _screen);
- _screen->setAnimBlockPtr(10000);
- _screen->setScreenDim(0);
- _pageBuffer1 = new uint8[0xFA00];
- memset(_pageBuffer1, 0, 0xFA00);
- _pageBuffer2 = new uint8[0xFA00];
- memset(_pageBuffer2, 0, 0xFA00);
- _itemsInPlay = new LoLItem[400];
- memset(_itemsInPlay, 0, sizeof(LoLItem) * 400);
- _characters = new LoLCharacter[4];
- memset(_characters, 0, sizeof(LoLCharacter) * 4);
- if (!_sound->init())
- error("Couldn't init sound");
- KyraRpgEngine::init();
- _wllAutomapData = new uint8[80];
- memset(_wllAutomapData, 0, 80);
- _monsters = new LoLMonster[30];
- memset(_monsters, 0, 30 * sizeof(LoLMonster));
- _monsterProperties = new LoLMonsterProperty[5];
- memset(_monsterProperties, 0, 5 * sizeof(LoLMonsterProperty));
- _tempBuffer5120 = new uint8[5120];
- memset(_tempBuffer5120, 0, 5120);
- _flyingObjects = new FlyingObject[_numFlyingObjects];
- _flyingObjectsPtr = _flyingObjects;
- _flyingObjectStructSize = sizeof(FlyingObject);
- memset(_flyingObjects, 0, _numFlyingObjects * sizeof(FlyingObject));
- memset(_globalScriptVars, 0, sizeof(_globalScriptVars));
- _lvlShpFileHandle = 0;
- _sceneDrawPage1 = 2;
- _sceneDrawPage2 = 6;
- _clickedShapeXOffs = 136;
- _clickedShapeYOffs = 8;
- _clickedSpecialFlag = 0x40;
- _monsterShapes = new uint8*[48];
- memset(_monsterShapes, 0, 48 * sizeof(uint8 *));
- _monsterPalettes = new uint8*[48];
- memset(_monsterPalettes, 0, 48 * sizeof(uint8 *));
- _monsterDecorationShapes = new uint8*[576];
- memset(_monsterDecorationShapes, 0, 576 * sizeof(uint8 *));
- memset(&_scriptData, 0, sizeof(EMCData));
- _activeMagicMenu = -1;
- _automapShapes = new const uint8*[109];
- _mapOverlay = new uint8[256];
- memset(_availableSpells, -1, 8);
- _spellProcs.push_back(new SpellProc(this, &LoLEngine::castSpark));
- _spellProcs.push_back(new SpellProc(this, &LoLEngine::castHeal));
- _spellProcs.push_back(new SpellProc(this, &LoLEngine::castIce));
- _spellProcs.push_back(new SpellProc(this, &LoLEngine::castFireball));
- _spellProcs.push_back(new SpellProc(this, &LoLEngine::castHandOfFate));
- _spellProcs.push_back(new SpellProc(this, &LoLEngine::castMistOfDoom));
- _spellProcs.push_back(new SpellProc(this, &LoLEngine::castLightning));
- _spellProcs.push_back(new SpellProc(this, 0));
- _spellProcs.push_back(new SpellProc(this, &LoLEngine::castFog));
- _spellProcs.push_back(new SpellProc(this, &LoLEngine::castSwarm));
- _spellProcs.push_back(new SpellProc(this, 0));
- _spellProcs.push_back(new SpellProc(this, 0));
- _spellProcs.push_back(new SpellProc(this, &LoLEngine::castVaelansCube));
- _spellProcs.push_back(new SpellProc(this, 0));
- _spellProcs.push_back(new SpellProc(this, 0));
- _spellProcs.push_back(new SpellProc(this, 0));
- _spellProcs.push_back(new SpellProc(this, &LoLEngine::castGuardian));
- #ifdef ENABLE_KEYMAPPER
- _eventMan->getKeymapper()->pushKeymap(kKeymapName, true);
- #endif
- return Common::kNoError;
- }
- void LoLEngine::initKeymap() {
- #ifdef ENABLE_KEYMAPPER
- Common::Keymapper *const mapper = _eventMan->getKeymapper();
- // Do not try to recreate same keymap over again
- if (mapper->getKeymap(kKeymapName) != 0)
- return;
- Common::Keymap *const engineKeyMap = new Common::Keymap(kKeymapName);
- const Common::KeyActionEntry keyActionEntries[] = {
- {Common::KeyState(Common::KEYCODE_F1, Common::ASCII_F1), "AT1", _("Attack 1")},
- {Common::KeyState(Common::KEYCODE_F2, Common::ASCII_F2), "AT2", _("Attack 2")},
- {Common::KeyState(Common::KEYCODE_F3, Common::ASCII_F3), "AT3", _("Attack 3")},
- {Common::KeyState(Common::KEYCODE_UP), "MVF", _("Move Forward")},
- {Common::KeyState(Common::KEYCODE_DOWN), "MVB", _("Move Back")},
- {Common::KeyState(Common::KEYCODE_LEFT), "SLL", _("Slide Left")},
- {Common::KeyState(Common::KEYCODE_RIGHT), "SLR", _("Slide Right")},
- {Common::KeyState(Common::KEYCODE_HOME), "TL", _("Turn Left")},
- {Common::KeyState(Common::KEYCODE_PAGEUP), "TR", _("Turn Right")},
- {Common::KeyState(Common::KEYCODE_r), "RST", _("Rest")},
- {Common::KeyState(Common::KEYCODE_o), "OPT", _("Options")},
- {Common::KeyState(Common::KEYCODE_SLASH), "SPL", _("Choose Spell")},
- {Common::KeyState(), 0, 0}
- };
- for (const Common::KeyActionEntry *entry = keyActionEntries; entry->id; ++entry) {
- Common::Action *const act = new Common::Action(engineKeyMap, entry->id, entry->description);
- act->addKeyEvent(entry->ks);
- }
- mapper->addGameKeymap(engineKeyMap);
- #endif
- }
- void LoLEngine::pauseEngineIntern(bool pause) {
- KyraEngine_v1::pauseEngineIntern(pause);
- pauseDemoPlayer(pause);
- }
- Common::Error LoLEngine::go() {
- int action = -1;
- if (_gameToLoad == -1) {
- action = processPrologue();
- if (action == -1)
- return Common::kNoError;
- }
- if (_flags.isTalkie && !_flags.isDemo) {
- if (!_res->loadFileList("FILEDATA.FDT"))
- error("Couldn't load file list: 'FILEDATA.FDT'");
- } else if (_pakFileList) {
- _res->loadFileList(_pakFileList, _pakFileListSize);
- }
- // Usually fonts etc. would be setup by the prologue code, if we skip
- // the prologue code we need to setup them manually here.
- if (_gameToLoad != -1 && action != 3) {
- preInit();
- _screen->setFont((_flags.lang == Common::JA_JPN && _flags.use16ColorMode) ? Screen::FID_SJIS_FNT : Screen::FID_9_FNT);
- }
- // We have three sound.dat files, one for the intro, one for the
- // end sequence and one for ingame, each contained in a different
- // PAK file. Therefore a new call to loadSoundFile() is required
- // whenever the PAK file configuration changes.
- if (_flags.platform == Common::kPlatformPC98)
- _sound->loadSoundFile("sound.dat");
- _sound->selectAudioResourceSet(kMusicIngame);
- if (_flags.platform != Common::kPlatformDOS)
- _sound->loadSoundFile(0);
- _tim = new TIMInterpreter_LoL(this, _screen, _system);
- assert(_tim);
- if (shouldQuit())
- return Common::kNoError;
- startup();
- if (action == 0) {
- startupNew();
- } else if (_gameToLoad != -1) {
- // FIXME: Instead of throwing away the error returned by
- // loadGameState, we should use it / augment it.
- if (loadGameState(_gameToLoad).getCode() != Common::kNoError)
- error("Couldn't load game slot %d on startup", _gameToLoad);
- _gameToLoad = -1;
- }
- _screen->_fadeFlag = 3;
- _sceneUpdateRequired = true;
- enableSysTimer(1);
- runLoop();
- return Common::kNoError;
- }
- #pragma mark - Initialization
- void LoLEngine::preInit() {
- _res->loadPakFile("GENERAL.PAK");
- if (_flags.isTalkie)
- _res->loadPakFile("STARTUP.PAK");
- _screen->loadFont(Screen::FID_9_FNT, "FONT9P.FNT");
- _screen->loadFont(Screen::FID_6_FNT, "FONT6P.FNT");
- loadTalkFile(0);
- Common::String filename;
- filename = Common::String::format("LANDS.%s", _languageExt[_lang]);
- _res->exists(filename.c_str(), true);
- delete[] _landsFile;
- _landsFile = _res->fileData(filename.c_str(), 0);
- loadItemIconShapes();
- }
- void LoLEngine::loadItemIconShapes() {
- if (_itemIconShapes) {
- for (int i = 0; i < _numItemIconShapes; i++)
- delete[] _itemIconShapes[i];
- delete[] _itemIconShapes;
- }
- _screen->loadBitmap("ITEMICN.SHP", 3, 3, 0);
- const uint8 *shp = _screen->getCPagePtr(3);
- _numItemIconShapes = READ_LE_UINT16(shp);
- _itemIconShapes = new uint8*[_numItemIconShapes];
- for (int i = 0; i < _numItemIconShapes; i++)
- _itemIconShapes[i] = _screen->makeShapeCopy(shp, i);
- _screen->setMouseCursor(0, 0, _itemIconShapes[0]);
- if (!_gameShapes) {
- _screen->loadBitmap("GAMESHP.SHP", 3, 3, 0);
- shp = _screen->getCPagePtr(3);
- _numGameShapes = READ_LE_UINT16(shp);
- _gameShapes = new uint8*[_numGameShapes];
- for (int i = 0; i < _numGameShapes; i++)
- _gameShapes[i] = _screen->makeShapeCopy(shp, i);
- }
- }
- void LoLEngine::setMouseCursorToIcon(int icon) {
- _flagsTable[31] |= 0x02;
- int i = _itemProperties[_itemsInPlay[_itemInHand].itemPropertyIndex].shpIndex;
- if (i == icon)
- return;
- _screen->setMouseCursor(0, 0, _itemIconShapes[icon]);
- }
- void LoLEngine::setMouseCursorToItemInHand() {
- _flagsTable[31] &= 0xFD;
- int o = (_itemInHand == 0) ? 0 : 10;
- _screen->setMouseCursor(o, o, getItemIconShapePtr(_itemInHand));
- }
- void LoLEngine::checkFloatingPointerRegions() {
- if (!_floatingCursorsEnabled)
- return;
- int t = -1;
- Common::Point p = getMousePos();
- if (!(_updateFlags & 4) & !_floatingCursorControl) {
- if (posWithinRect(p.x, p.y, 96, 0, 303, 136)) {
- if (!posWithinRect(p.x, p.y, 128, 16, 271, 119)) {
- if (posWithinRect(p.x, p.y, 112, 0, 287, 15))
- t = 0;
- if (posWithinRect(p.x, p.y, 272, 88, 303, 319))
- t = 1;
- if (posWithinRect(p.x, p.y, 112, 110, 287, 135))
- t = 2;
- if (posWithinRect(p.x, p.y, 96, 88, 127, 119))
- t = 3;
- if (posWithinRect(p.x, p.y, 96, 16, 127, 87))
- t = 4;
- if (posWithinRect(p.x, p.y, 272, 16, 303, 87))
- t = 5;
- if (t < 4) {
- int d = (_currentDirection + t) & 3;
- if (!checkBlockPassability(calcNewBlockPosition(_currentBlock, d), d))
- t = 6;
- }
- }
- }
- }
- if (t == _currentFloatingCursor)
- return;
- if (t == -1) {
- setMouseCursorToItemInHand();
- } else {
- static const uint8 floatingPtrX[] = { 7, 13, 7, 0, 0, 15, 7 };
- static const uint8 floatingPtrY[] = { 0, 7, 12, 7, 6, 6, 7 };
- _screen->setMouseCursor(floatingPtrX[t], floatingPtrY[t], _gameShapes[10 + t]);
- }
- _currentFloatingCursor = t;
- }
- uint8 *LoLEngine::getItemIconShapePtr(int index) {
- int ix = _itemProperties[_itemsInPlay[index].itemPropertyIndex].shpIndex;
- if (_itemProperties[_itemsInPlay[index].itemPropertyIndex].flags & 0x200)
- ix += (_itemsInPlay[index].shpCurFrame_flg & 0x1FFF) - 1;
- return _itemIconShapes[ix];
- }
- int LoLEngine::mainMenu() {
- bool hasSave = saveFileLoadable(0);
- MainMenu::StaticData data[] = {
- // 256 color ASCII mode
- {
- { 0, 0, 0, 0, 0 },
- { 0x01, 0x04, 0x0C, 0x04, 0x00, 0x3D, 0x9F },
- { 0x2C, 0x19, 0x48, 0x2C },
- Screen::FID_9_FNT, 1
- },
- // 16 color SJIS mode
- {
- { 0, 0, 0, 0, 0 },
- { 0x01, 0x04, 0x0C, 0x04, 0x00, 0xC1, 0xE1 },
- { 0xCC, 0xDD, 0xDD, 0xDD },
- Screen::FID_SJIS_FNT, 1
- }
- };
- int dataIndex = _flags.use16ColorMode ? 1 : 0;
- if (!_flags.isTalkie)
- --data[dataIndex].menuTable[3];
- if (hasSave)
- ++data[dataIndex].menuTable[3];
- static const uint16 mainMenuStrings[4][5] = {
- { 0x4248, 0x4249, 0x42DD, 0x424A, 0x0000 },
- { 0x4248, 0x4249, 0x42DD, 0x4001, 0x424A },
- { 0x4248, 0x4249, 0x424A, 0x0000, 0x0000 },
- { 0x4248, 0x4249, 0x4001, 0x424A, 0x0000 }
- };
- int tableOffs = _flags.isTalkie ? 0 : 2;
- for (int i = 0; i < 5; ++i) {
- if (hasSave)
- data[dataIndex].strings[i] = getLangString(mainMenuStrings[1 + tableOffs][i]);
- else
- data[dataIndex].strings[i] = getLangString(mainMenuStrings[tableOffs][i]);
- }
- MainMenu *menu = new MainMenu(this);
- assert(menu);
- menu->init(data[dataIndex], MainMenu::Animation());
- int selection = menu->handle(_flags.isTalkie ? (hasSave ? 19 : 6) : (hasSave ? 6 : 20));
- delete menu;
- _screen->setScreenDim(0);
- if (!_flags.isTalkie && selection >= 2)
- selection++;
- if (!hasSave && selection == 3)
- selection = 4;
- return selection;
- }
- void LoLEngine::startup() {
- _screen->clearPage(0);
- Palette &pal = _screen->getPalette(0);
- _screen->loadBitmap("PLAYFLD.CPS", 3, 3, &pal);
- if (_flags.use16ColorMode) {
- memset(_screen->_paletteOverlay1, 0, 256);
- memset(_screen->_paletteOverlay2, 0, 256);
- static const uint8 colTable1[] = { 0x00, 0xEE, 0xCC, 0xFF, 0x44, 0x66, 0x44, 0x88, 0xEE, 0xAA, 0x11, 0xCC, 0xDD, 0xEE, 0x44, 0xCC };
- static const uint8 colTable2[] = { 0x00, 0xCC, 0xFF, 0xBB, 0xEE, 0xBB, 0x55, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xFF, 0xCC, 0xDD, 0xBB };
- static const uint8 colTable3[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
- for (int i = 0; i < 16; i++) {
- _screen->_paletteOverlay1[colTable3[i]] = colTable1[i];
- _screen->_paletteOverlay2[colTable3[i]] = colTable2[i];
- }
- } else {
- _screen->copyPalette(1, 0);
- pal.fill(0, 1, 0x3F);
- pal.fill(2, 126, 0x3F);
- pal.fill(192, 4, 0x3F);
- _screen->generateOverlay(pal, _screen->_paletteOverlay1, 1, 96, 254);
- _screen->generateOverlay(pal, _screen->_paletteOverlay2, 144, 65, 254);
- _screen->copyPalette(0, 1);
- }
- _screen->getPalette(1).clear();
- _screen->getPalette(2).clear();
- loadItemIconShapes();
- _screen->setMouseCursor(0, 0, _itemIconShapes[0x85]);
- _screen->loadBitmap("ITEMSHP.SHP", 3, 3, 0);
- const uint8 *shp = _screen->getCPagePtr(3);
- _numItemShapes = READ_LE_UINT16(shp);
- _itemShapes = new uint8*[_numItemShapes];
- for (int i = 0; i < _numItemShapes; i++)
- _itemShapes[i] = _screen->makeShapeCopy(shp, i);
- _screen->loadBitmap("THROWN.SHP", 3, 3, 0);
- shp = _screen->getCPagePtr(3);
- _numThrownShapes = READ_LE_UINT16(shp);
- _thrownShapes = new uint8*[_numThrownShapes];
- for (int i = 0; i < _numThrownShapes; i++)
- _thrownShapes[i] = _screen->makeShapeCopy(shp, i);
- _screen->loadBitmap("ICE.SHP", 3, 3, 0);
- shp = _screen->getCPagePtr(3);
- _numEffectShapes = READ_LE_UINT16(shp);
- _effectShapes = new uint8*[_numEffectShapes];
- for (int i = 0; i < _numEffectShapes; i++)
- _effectShapes[i] = _screen->makeShapeCopy(shp, i);
- _screen->loadBitmap("FIREBALL.SHP", 3, 3, 0);
- shp = _screen->getCPagePtr(3);
- _numFireballShapes = READ_LE_UINT16(shp);
- _fireballShapes = new uint8*[_numFireballShapes];
- for (int i = 0; i < _numFireballShapes; i++)
- _fireballShapes[i] = _screen->makeShapeCopy(shp, i);
- _screen->loadBitmap("HEAL.SHP", 3, 3, 0);
- shp = _screen->getCPagePtr(3);
- _numHealShapes = READ_LE_UINT16(shp);
- _healShapes = new uint8*[_numHealShapes];
- for (int i = 0; i < _numHealShapes; i++)
- _healShapes[i] = _screen->makeShapeCopy(shp, i);
- _screen->loadBitmap("HEALI.SHP", 3, 3, 0);
- shp = _screen->getCPagePtr(3);
- _numHealiShapes = READ_LE_UINT16(shp);
- _healiShapes = new uint8*[_numHealiShapes];
- for (int i = 0; i < _numHealiShapes; i++)
- _healiShapes[i] = _screen->makeShapeCopy(shp, i);
- memset(_itemsInPlay, 0, 400 * sizeof(LoLItem));
- for (int i = 0; i < 400; i++)
- _itemsInPlay[i].shpCurFrame_flg |= 0x8000;
- runInitScript("ONETIME.INF", 0);
- _emc->load("ITEM.INF", &_itemScript, &_opcodes);
- _transparencyTable1 = new uint8[256];
- _transparencyTable2 = new uint8[5120];
- _loadSuppFilesFlag = 1;
- _sound->loadSfxFile("LORESFX");
- setMouseCursorToItemInHand();
- }
- void LoLEngine::startupNew() {
- _selectedSpell = 0;
- _compassStep = 0;
- _compassDirection = _compassDirectionIndex = -1;
- _lastMouseRegion = -1;
- _currentLevel = 1;
- giveCredits(41, 0);
- _inventory[0] = makeItem(216, 0, 0);
- _inventory[1] = makeItem(217, 0, 0);
- _inventory[2] = makeItem(218, 0, 0);
- _availableSpells[0] = 0;
- setupScreenDims();
- Common::fill(_globalScriptVars2, ARRAYEND(_globalScriptVars2), 0x100);
- static const int selectIds[] = { -9, -1, -8, -5 };
- assert(_charSelection >= 0);
- assert(_charSelection < ARRAYSIZE(selectIds));
- addCharacter(selectIds[_charSelection]);
- gui_enableDefaultPlayfieldButtons();
- loadLevel(_currentLevel);
- _screen->showMouse();
- }
- void LoLEngine::runLoop() {
- // Initialize debugger since how it should be fully usable
- _debugger->initialize();
- enableSysTimer(2);
- _flagsTable[73] |= 0x08;
- while (!shouldQuit()) {
- if (_gameToLoad != -1) {
- // FIXME: Instead of throwing away the error returned by
- // loadGameState, we should use it / augment it.
- if (loadGameState(_gameToLoad).getCode() != Common::kNoError)
- error("Couldn't load game slot %d", _gameToLoad);
- _gameToLoad = -1;
- }
- if (_nextScriptFunc) {
- runLevelScript(_nextScriptFunc, 2);
- _nextScriptFunc = 0;
- }
- _timer->update();
- checkFloatingPointerRegions();
- gui_updateInput();
- update();
- if (_sceneUpdateRequired)
- gui_drawScene(0);
- else
- updateEnvironmentalSfx(0);
- if (_partyDamageFlags != -1) {
- checkForPartyDeath();
- _partyDamageFlags = -1;
- }
- delay(_tickLength);
- }
- }
- void LoLEngine::registerDefaultSettings() {
- KyraEngine_v1::registerDefaultSettings();
- // Most settings already have sensible defaults. This one, however, is
- // specific to the LoL engine.
- ConfMan.registerDefault("floating_cursors", false);
- ConfMan.registerDefault("smooth_scrolling", true);
- ConfMan.registerDefault("monster_difficulty", 1);
- }
- void LoLEngine::writeSettings() {
- ConfMan.setInt("monster_difficulty", _monsterDifficulty);
- ConfMan.setBool("floating_cursors", _floatingCursorsEnabled);
- ConfMan.setBool("smooth_scrolling", _smoothScrollingEnabled);
- switch (_lang) {
- case 1:
- _flags.lang = Common::FR_FRA;
- break;
- case 2:
- _flags.lang = Common::DE_DEU;
- break;
- case 0:
- default:
- if (_flags.platform == Common::kPlatformPC98 || _flags.platform == Common::kPlatformFMTowns)
- _flags.lang = Common::JA_JPN;
- else
- _flags.lang = Common::EN_ANY;
- }
- if (_flags.lang == _flags.replacedLang && _flags.fanLang != Common::UNK_LANG)
- _flags.lang = _flags.fanLang;
- ConfMan.set("language", Common::getLanguageCode(_flags.lang));
- KyraEngine_v1::writeSettings();
- }
- void LoLEngine::readSettings() {
- _monsterDifficulty = ConfMan.getInt("monster_difficulty");
- if (_monsterDifficulty < 0 || _monsterDifficulty > 2) {
- _monsterDifficulty = CLIP(_monsterDifficulty, 0, 2);
- warning("LoLEngine: Config file contains invalid difficulty setting.");
- }
- _smoothScrollingEnabled = ConfMan.getBool("smooth_scrolling");
- _floatingCursorsEnabled = ConfMan.getBool("floating_cursors");
- KyraEngine_v1::readSettings();
- }
- void LoLEngine::update() {
- updateSequenceBackgroundAnimations();
- if (_updateCharNum != -1 && _system->getMillis() > _updatePortraitNext)
- updatePortraitSpeechAnim();
- if (_flagsTable[31] & 0x08 || !(_updateFlags & 4))
- updateLampStatus();
- if (_flagsTable[31] & 0x40 && !(_updateFlags & 4) && (_compassDirection == -1 || (_currentDirection << 6) != _compassDirection || _compassStep))
- updateCompass();
- snd_updateCharacterSpeech();
- fadeText();
- updateInput();
- _screen->updateScreen();
- }
- #pragma mark - Localization
- char *LoLEngine::getLangString(uint16 id) {
- if (id == 0xFFFF)
- return 0;
- uint16 realId = id & 0x3FFF;
- uint8 *buffer = 0;
- if (id & 0x4000)
- buffer = _landsFile;
- else
- buffer = _levelLangFile;
- if (!buffer)
- return 0;
- char *string = (char *)getTableEntry(buffer, realId);
- char *srcBuffer = _stringBuffer[_lastUsedStringBuffer];
- if (_flags.lang == Common::JA_JPN) {
- decodeSjis(string, srcBuffer);
- } else if (_flags.lang == Common::RU_RUS && !_flags.isTalkie) {
- decodeCyrillic(string, srcBuffer);
- Util::decodeString2(srcBuffer, srcBuffer);
- } else {
- Util::decodeString1(string, srcBuffer);
- Util::decodeString2(srcBuffer, srcBuffer);
- }
- ++_lastUsedStringBuffer;
- _lastUsedStringBuffer %= ARRAYSIZE(_stringBuffer);
- return srcBuffer;
- }
- uint8 *LoLEngine::getTableEntry(uint8 *buffer, uint16 id) {
- if (!buffer)
- return 0;
- return buffer + READ_LE_UINT16(buffer + (id << 1));
- }
- void LoLEngine::decodeSjis(const char *src, char *dst) {
- char s[2];
- char d[3];
- s[1] = 0;
- uint8 cmd = 0;
- while ((cmd = *src++) != 0) {
- if (cmd == 27) {
- cmd = *src++ & 0x7F;
- memcpy(dst, src, cmd * 2);
- dst += cmd * 2;
- src += cmd * 2;
- } else {
- s[0] = cmd;
- int size = Util::decodeString1(s, d);
- memcpy(dst, d, size);
- dst += size;
- }
- }
- *dst = 0;
- }
- int LoLEngine::decodeCyrillic(const char *src, char *dst) {
- static const uint8 decodeTable1[] = {
- 0x20, 0xAE, 0xA5, 0xA0, 0xE2, 0xAD, 0xA8, 0xE0, 0xE1, 0xAB, 0xA2,
- 0xA4, 0xAC, 0xAA, 0xE3, 0x2E
- };
- static const uint8 decodeTable2[] = {
- 0xAD, 0xAF, 0xA2, 0xE1, 0xAC, 0xAA, 0x20, 0xA4, 0xAB, 0x20,
- 0xE0, 0xE2, 0xA4, 0xA2, 0xA6, 0xAA, 0x20, 0xAD, 0xE2, 0xE0,
- 0xAB, 0xAC, 0xE1, 0xA1, 0x20, 0xAC, 0xE1, 0xAA, 0xAB, 0xE0,
- 0xE2, 0xAD, 0xAE, 0xEC, 0xA8, 0xA5, 0xA0, 0x20, 0xE0, 0xEB,
- 0xAE, 0xA0, 0xA8, 0xA5, 0xEB, 0xEF, 0x20, 0xE3, 0xE2, 0x20,
- 0xAD, 0xE7, 0xAB, 0xAC, 0xA5, 0xE0, 0xAE, 0xA0, 0xA5, 0xA8,
- 0xE3, 0xEB, 0xEF, 0xAA, 0xE2, 0xEF, 0xA5, 0xEC, 0xAB, 0xAE,
- 0xAA, 0xAF, 0xA8, 0xA0, 0xA5, 0xEF, 0xAE, 0xEE, 0xEC, 0xE3,
- 0xA0, 0xAE, 0xA5, 0xA8, 0xEB, 0x20, 0xE0, 0xE3, 0xA0, 0xA5,
- 0xAE, 0xA8, 0xE3, 0xE1, 0xAD, 0xAB, 0x20, 0xAE, 0xA5, 0xA0,
- 0xA8, 0xAD, 0x2E, 0xE3, 0xAE, 0xA0, 0xA8, 0x20, 0xE0, 0xE3,
- 0xAB, 0xE1, 0x20, 0xA4, 0xAD, 0xE2, 0xA1, 0xA6, 0xAC, 0xE1,
- 0x0D, 0x20, 0x2E, 0x09, 0xA0, 0xA1, 0x9D, 0xA5
- };
- int size = 0;
- uint cChar = 0;
- while ((cChar = *src++) != 0) {
- if (cChar & 0x80) {
- cChar &= 0x7F;
- int index = (cChar & 0x78) >> 3;
- *dst++ = decodeTable1[index];
- ++size;
- assert(cChar < sizeof(decodeTable2));
- cChar = decodeTable2[cChar];
- } else if (cChar >= 0x70) {
- cChar = *src++;
- } else if (cChar >= 0x30) {
- if (cChar < 0x60)
- cChar -= 0x30;
- cChar |= 0x80;
- }
- *dst++ = cChar;
- ++size;
- }
- *dst++ = 0;
- return size;
- }
- bool LoLEngine::addCharacter(int id) {
- const uint16 *cdf[] = {
- _charDefsMan, _charDefsMan, _charDefsMan, _charDefsWoman,
- _charDefsMan, _charDefsMan, _charDefsWoman, _charDefsKieran, _charDefsAkshel
- };
- int numChars = countActiveCharacters();
- if (numChars == 4)
- return false;
- int i = 0;
- for (; i < _charDefaultsSize; i++) {
- if (_charDefaults[i].id == id) {
- memcpy(&_characters[numChars], &_charDefaults[i], sizeof(LoLCharacter));
- _characters[numChars].defaultModifiers = cdf[i];
- break;
- }
- }
- if (i == _charDefaultsSize)
- return false;
- loadCharFaceShapes(numChars, id);
- _characters[numChars].nextAnimUpdateCountdown = rollDice(1, 12) + 6;
- for (i = 0; i < 11; i++) {
- if (_characters[numChars].items[i]) {
- _characters[numChars].items[i] = makeItem(_characters[numChars].items[i], 0, 0);
- runItemScript(numChars, _characters[numChars].items[i], 0x80, 0, 0);
- }
- }
- calcCharPortraitXpos();
- if (numChars > 0)
- setTemporaryFaceFrame(numChars, 2, 6, 0);
- return true;
- }
- void LoLEngine::setTemporaryFaceFrame(int charNum, int frame, int updateDelay, int redraw) {
- _characters[charNum].tempFaceFrame = frame;
- if (frame || updateDelay)
- setCharacterUpdateEvent(charNum, 6, updateDelay, 1);
- if (redraw)
- gui_drawCharPortraitWithStats(charNum);
- }
- void LoLEngine::setTemporaryFaceFrameForAllCharacters(int frame, int updateDelay, int redraw) {
- for (int i = 0; i < 4; i++)
- setTemporaryFaceFrame(i, frame, updateDelay, 0);
- if (redraw)
- gui_drawAllCharPortraitsWithStats();
- }
- void LoLEngine::setCharacterUpdateEvent(int charNum, int updateType, int updateDelay, int overwrite) {
- LoLCharacter *l = &_characters[charNum];
- for (int i = 0; i < 5; i++) {
- if (l->characterUpdateEvents[i] && (!overwrite || l->characterUpdateEvents[i] != updateType))
- continue;
- l->characterUpdateEvents[i] = updateType;
- l->characterUpdateDelay[i] = updateDelay;
- _timer->setNextRun(3, _system->getMillis());
- _timer->resetNextRun();
- _timer->enable(3);
- break;
- }
- }
- int LoLEngine::countActiveCharacters() {
- int i = 0;
- while (_characters[i].flags & 1)
- i++;
- return i;
- }
- void LoLEngine::loadCharFaceShapes(int charNum, int id) {
- if (id < 0)
- id = -id;
- Common::String file = Common::String::format("FACE%02d.SHP", id);
- _screen->loadBitmap(file.c_str(), 3, 3, 0);
- const uint8 *p = _screen->getCPagePtr(3);
- for (int i = 0; i < 40; i++) {
- delete[] _characterFaceShapes[i][charNum];
- _characterFaceShapes[i][charNum] = _screen->makeShapeCopy(p, i);
- }
- }
- void LoLEngine::updatePortraitSpeechAnim() {
- int x = 0;
- int y = 0;
- bool redraw = false;
- if (_portraitSpeechAnimMode == 0) {
- x = _activeCharsXpos[_updateCharNum];
- y = 144;
- redraw = true;
- } else if (_portraitSpeechAnimMode == 1) {
- if (textEnabled()) {
- x = 90;
- y = 130;
- } else {
- x = _activeCharsXpos[_updateCharNum];
- y = 144;
- }
- } else if (_portraitSpeechAnimMode == 2) {
- if (textEnabled()) {
- x = 16;
- y = 134;
- } else {
- x = _activeCharsXpos[_updateCharNum] + 10;
- y = 145;
- }
- }
- int f = rollDice(1, 6) - 1;
- if (f == _characters[_updateCharNum].curFaceFrame)
- f++;
- if (f > 5)
- f -= 5;
- f += 7;
- if (speechEnabled()) {
- if (snd_updateCharacterSpeech() == 2)
- // WORKAROUND for portrait speech animations which would "freeze" in some situations
- if (_resetPortraitAfterSpeechAnim == 2)
- _resetPortraitAfterSpeechAnim = 1;
- else
- _updatePortraitSpeechAnimDuration = 2;
- else
- _updatePortraitSpeechAnimDuration = 1;
- } else if (_resetPortraitAfterSpeechAnim == 2) {
- _resetPortraitAfterSpeechAnim = 1;
- }
- _updatePortraitSpeechAnimDuration--;
- if (_updatePortraitSpeechAnimDuration) {
- setCharFaceFrame(_updateCharNum, f);
- if (redraw)
- gui_drawCharPortraitWithStats(_updateCharNum);
- else
- gui_drawCharFaceShape(_updateCharNum, x, y, 0);
- _updatePortraitNext = _system->getMillis() + 10 * _tickLength;
- } else if (_resetPortraitAfterSpeechAnim != 0) {
- faceFrameRefresh(_updateCharNum);
- if (redraw) {
- gui_drawCharPortraitWithStats(_updateCharNum);
- initTextFading(0, 0);
- } else {
- gui_drawCharFaceShape(_updateCharNum, x, y, 0);
- }
- _updateCharNum = -1;
- }
- }
- void LoLEngine::stopPortraitSpeechAnim() {
- if (_updateCharNum == -1)
- return;
- _updatePortraitSpeechAnimDuration = 1;
- // WORKAROUND for portrait speech animations which would "freeze" in some situations
- _resetPortraitAfterSpeechAnim = 2;
- updatePortraitSpeechAnim();
- _updatePortraitSpeechAnimDuration = 1;
- _updateCharNum = -1;
- if (!_portraitSpeechAnimMode)
- initTextFading(0, 0);
- }
- void LoLEngine::initTextFading(int textType, int clearField) {
- if (_textColorFlag == textType || !textType) {
- _fadeText = true;
- _palUpdateTimer = _system->getMillis();
- }
- if (!clearField)
- return;
- stopPortraitSpeechAnim();
- if (_needSceneRestore)
- _screen->setScreenDim(_txt->clearDim(3));
- _fadeText = false;
- _timer->disable(11);
- }
- void LoLEngine::setCharFaceFrame(int charNum, int frameNum) {
- _characters[charNum].curFaceFrame = frameNum;
- }
- void LoLEngine::faceFrameRefresh(int charNum) {
- if (_characters[charNum].curFaceFrame == 1)
- setTemporaryFaceFrame(charNum, 0, 0, 0);
- else if (_characters[charNum].curFaceFrame == 6)
- if (_characters[charNum].tempFaceFrame != 5)
- setTemporaryFaceFrame(charNum, 0, 0, 0);
- else
- _characters[charNum].curFaceFrame = 5;
- else
- _characters[charNum].curFaceFrame = 0;
- }
- void LoLEngine::recalcCharacterStats(int charNum) {
- for (int i = 0; i < 5; i++)
- _charStatsTemp[i] = calculateCharacterStats(charNum, i);
- }
- int LoLEngine::calculateCharacterStats(int charNum, int index) {
- if (index == 0) {
- // Might
- int c = 0;
- for (int i = 0; i < 8; i++)
- c += _characters[charNum].itemsMight[i];
- if (c)
- c += _characters[charNum].might;
- else
- c = _characters[charNum].defaultModifiers[8];
- c = (c * _characters[charNum].defaultModifiers[1]) >> 8;
- c = (c * _characters[charNum].totalMightModifier) >> 8;
- return c;
- } else if (index == 1) {
- // Protection
- return calculateProtection(charNum);
- } else if (index > 4) {
- return -1;
- } else {
- // Fighter
- // Rogue
- // Mage
- index -= 2;
- return _characters[charNum].skillLevels[index] + _characters[charNum].skillModifiers[index];
- }
- //return 1;
- }
- int LoLEngine::calculateProtection(int index) {
- int c = 0;
- if (index & 0x8000) {
- // Monster
- index &= 0x7FFF;
- c = (_monsters[index].properties->itemProtection * _monsters[index].properties->fightingStats[2]) >> 8;
- } else {
- // Character
- c = _characters[index].itemProtection + _characters[index].protection;
- c = (c * _characters[index].defaultModifiers[2]) >> 8;
- c = (c * _characters[index].totalProtectionModifier) >> 8;
- }
- return c;
- }
- void LoLEngine::setCharacterMagicOrHitPoints(int charNum, int type, int points, int mode) {
- static const uint16 barData[4][5] = {
- // xPos, bar color, text color, flag, string id
- { 0x27, 0x9A, 0x98, 0x01, 0x4254 },
- { 0x21, 0xA2, 0xA0, 0x00, 0x4253 },
- // 16 color mode
- { 0x27, 0x66, 0x55, 0x01, 0x4254 },
- { 0x21, 0xAA, 0x99, 0x00, 0x4253 }
- };
- if (charNum > 2)
- return;
- LoLCharacter *c = &_characters[charNum];
- if (!(c->flags & 1))
- return;
- int pointsMax = type ? c->magicPointsMax : c->hitPointsMax;
- int pointsCur = type ? c->magicPointsCur : c->hitPointsCur;
- int newVal = (mode == 2) ? (pointsMax + points) : (mode ? (pointsCur + points) : points);
- newVal = CLIP(newVal, 0, pointsMax);
- if (type) {
- c->magicPointsCur = newVal;
- } else {
- c->hitPointsCur = newVal;
- if (c->hitPointsCur < 1)
- c->flags |= 8;
- }
- if (_updateFlags & 2)
- return;
- Screen::FontId cf = _screen->setFont(Screen::FID_6_FNT);
- int cp = _screen->setCurPage(0);
- int s = 8192 / pointsMax;
- pointsMax = (s * pointsMax) >> 8;
- pointsCur = (s * pointsCur) >> 8;
- newVal = (s * newVal) >> 8;
- int newValScl = CLIP(newVal, 0, pointsMax);
- int step = (newVal > pointsCur) ? 2 : -2;
- newVal = CLIP(newVal + step, 0, pointsMax);
- if (_flags.use16ColorMode)
- type += 2;
- if (newVal != pointsCur) {
- step = (newVal >= pointsCur) ? 2 : -2;
- for (int i = pointsCur; i != newVal || newVal != newValScl;) {
- if (ABS(i - newVal) < ABS(step))
- step >>= 1;
- i += step;
- uint32 delayTimer = _system->getMillis() + _tickLength;
- gui_drawLiveMagicBar(barData[type][0] + _activeCharsXpos[charNum], 175, i, 0, pointsMax, 5, 32, barData[type][1], _flags.use16ColorMode ? 0x44 : 1, barData[type][3]);
- _screen->printText(getLangString(barData[type][4]), barData[type][0] + _activeCharsXpos[charNum], 144, barData[type][2], 0);
- _screen->updateScreen();
- if (i == newVal) {
- newVal = newValScl;
- step = -step;
- }
- delayUntil(delayTimer);
- }
- }
- _screen->setFont(cf);
- _screen->setCurPage(cp);
- }
- void LoLEngine::increaseExperience(int charNum, int skill, uint32 points) {
- if (charNum & 0x8000)
- return;
- if (_characters[charNum].flags & 8)
- return;
- _characters[charNum].experiencePts[skill] += points;
- bool loop = true;
- while (loop) {
- if (_characters[charNum].experiencePts[skill] < _expRequirements[_characters[charNum].skillLevels[skill]])
- break;
- _characters[charNum].skillLevels[skill]++;
- _characters[charNum].flags |= (0x200 << skill);
- int inc = 0;
- switch (skill) {
- case 0:
- _txt->printMessage(0x8003, getLangString(0x4023), _characters[charNum].name);
- inc = rollDice(4, 6);
- _characters[charNum].hitPointsCur += inc;
- _characters[charNum].hitPointsMax += inc;
- break;
- case 1:
- _txt->printMessage(0x8003, getLangString(0x4025), _characters[charNum].name);
- inc = rollDice(2, 6);
- _characters[charNum].hitPointsCur += inc;
- _characters[charNum].hitPointsMax += inc;
- break;
- case 2:
- _txt->printMessage(0x8003, getLangString(0x4024), _characters[charNum].name);
- inc = (_characters[charNum].defaultModifiers[6] * (rollDice(1, 8) + 17)) >> 8;
- _characters[charNum].magicPointsCur += inc;
- _characters[charNum].magicPointsMax += inc;
- inc = rollDice(1, 6);
- _characters[charNum].hitPointsCur += inc;
- _characters[charNum].hitPointsMax += inc;
- break;
- default:
- break;
- }
- snd_playSoundEffect(118, -1);
- gui_drawCharPortraitWithStats(charNum);
- }
- }
- void LoLEngine::increaseCharacterHitpoints(int charNum, int points, bool ignoreDeath) {
- if (_characters[charNum].hitPointsCur <= 0 && !ignoreDeath)
- return;
- if (points <= 1)
- points = 1;
- _characters[charNum].hitPointsCur = CLIP<int16>(_characters[charNum].hitPointsCur + points, 1, _characters[charNum].hitPointsMax);
- _characters[charNum].flags &= 0xFFF7;
- }
- void LoLEngine::setupScreenDims() {
- if (textEnabled()) {
- _screen->modifyScreenDim(4, 11, 124, 28, 45);
- _screen->modifyScreenDim(5, 85, 123, 233, 54);
- } else {
- _screen->modifyScreenDim(4, 11, 124, 28, 9);
- _screen->modifyScreenDim(5, 85, 123, 233, 18);
- }
- }
- void LoLEngine::initSceneWindowDialogue(int controlMode) {
- resetPortraitsAndDisableSysTimer();
- gui_prepareForSequence(112, 0, 176, 120, controlMode);
- _updateFlags |= 3;
- _txt->setupField(true);
- _txt->expandField();
- setupScreenDims();
- gui_disableControls(controlMode);
- }
- void LoLEngine::toggleSelectedCharacterFrame(bool mode) {
- if (countActiveCharacters() == 1)
- return;
- int col = mode ? 212 : 1;
- int cp = _screen->setCurPage(0);
- int x = _activeCharsXpos[_selectedCharacter];
- _screen->drawBox(x, 143, x + 65, 176, col);
- _screen->setCurPage(cp);
- }
- void LoLEngine::gui_prepareForSequence(int x, int y, int w, int h, int buttonFlags) {
- setSequenceButtons(x, y, w, h, buttonFlags);
- _seqWindowX1 = x;
- _seqWindowY1 = y;
- _seqWindowX2 = x + w;
- _seqWindowY2 = y + h;
- int mouseOffs = _itemInHand ? 10 : 0;
- _screen->setMouseCursor(mouseOffs, mouseOffs, getItemIconShapePtr(_itemInHand));
- _lastMouseRegion = -1;
- if (w == 320) {
- setLampMode(false);
- _lampStatusSuspended = true;
- }
- }
- void LoLEngine::gui_specialSceneSuspendControls(int controlMode) {
- if (controlMode) {
- _updateFlags |= 4;
- setLampMode(false);
- }
- _updateFlags |= 1;
- _specialSceneFlag = 1;
- _currentControlMode = controlMode;
- calcCharPortraitXpos();
- checkFloatingPointerRegions();
- }
- void LoLEngine::gui_specialSceneRestoreControls(int restoreLamp) {
- if (restoreLamp) {
- _updateFlags &= 0xFFFA;
- resetLampStatus();
- }
- _updateFlags &= 0xFFFE;
- _specialSceneFlag = 0;
- checkFloatingPointerRegions();
- }
- void LoLEngine::restoreAfterSceneWindowDialogue(int redraw) {
- gui_enableControls();
- _txt->setupField(false);
- _updateFlags &= 0xFFDF;
- setDefaultButtonState();
- for (int i = 0; i < 6; i++)
- _tim->freeAnimStruct(i);
- _updateFlags = 0;
- if (redraw) {
- if (_screen->_fadeFlag != 2)
- _screen->fadeClearSceneWindow(10);
- gui_drawPlayField();
- setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect);
- _screen->_fadeFlag = 0;
- }
- _needSceneRestore = 0;
- enableSysTimer(2);
- }
- void LoLEngine::initDialogueSequence(int controlMode, int pageNum) {
- if (controlMode) {
- _timer->disable(11);
- _fadeText = false;
- int cp = _screen->setCurPage(pageNum);
- if (_flags.use16ColorMode) {
- _screen->fillRect(0, 128, 319, 199, 0x44);
- gui_drawBox(0, 129, 320, 71, 0xEE, 0xCC, -1);
- gui_drawBox(1, 130, 318, 69, 0xEE, 0xCC, 0x11);
- } else {
- _screen->fillRect(0, 128, 319, 199, 1);
- gui_drawBox(0, 129, 320, 71, 136, 251, -1);
- gui_drawBox(1, 130, 318, 69, 136, 251, 252);
- }
- _screen->modifyScreenDim(5, 8, 131, 306, 66);
- _screen->modifyScreenDim(4, 1, 133, 38, 60);
- _txt->clearDim(4);
- _updateFlags |= 2;
- _currentControlMode = controlMode;
- calcCharPortraitXpos();
- if (!textEnabled() && (!(controlMode & 2))) {
- int nc = countActiveCharacters();
- for (int i = 0; i < nc; i++) {
- _portraitSpeechAnimMode = 2;
- _updateCharNum = i;
- _screen->drawShape(0, _gameShapes[88], _activeCharsXpos[_updateCharNum] + 8, 142, 0, 0);
- stopPortraitSpeechAnim();
- }
- }
- _screen->setCurPage(cp);
- } else {
- _txt->setupField(true);
- _txt->expandField();
- setupScreenDims();
- _txt->clearDim(4);
- }
- _currentControlMode = controlMode;
- _dialogueField = true;
- }
- void LoLEngine::restoreAfterDialogueSequence(int controlMode) {
- if (!_dialogueField)
- return;
- stopPortraitSpeechAnim();
- _currentControlMode = controlMode;
- calcCharPortraitXpos();
- if (_currentControlMode) {
- _screen->modifyScreenDim(4, 11, 124, 28, 45);
- _screen->modifyScreenDim(5, 85, 123, 233, 54);
- _updateFlags &= 0xFFFD;
- } else {
- const ScreenDim *d = _screen->getScreenDim(5);
- _screen->fillRect(d->sx, d->sy, d->sx + d->w - (_flags.use16ColorMode ? 3 : 2), d->sy + d->h - 2, d->unkA);
- _txt->clearDim(4);
- _txt->setupField(false);
- }
- _dialogueField = false;
- }
- void LoLEngine::resetPortraitsAndDisableSysTimer() {
- _needSceneRestore = 1;
- if (!textEnabled() || (!(_currentControlMode & 2)))
- timerUpdatePortraitAnimations(1);
- disableSysTimer(2);
- }
- void LoLEngine::fadeText() {
- if (!_fadeText)
- return;
- if (_screen->fadeColor(192, 252, (_system->getMillis() - _palUpdateTimer) / _tickLength, 60))
- return;
- if (_needSceneRestore)
- return;
- _screen->setScreenDim(_txt->clearDim(3));
- _timer->disable(11);
- _fadeText = false;
- }
- void LoLEngine::setPaletteBrightness(const Palette &srcPal, int brightness, int modifier) {
- generateBrightnessPalette(srcPal, _screen->getPalette(1), brightness, modifier);
- _screen->fadePalette(_screen->getPalette(1), 5, 0);
- _screen->_fadeFlag = 0;
- }
- void LoLEngine::generateBrightnessPalette(const Palette &src, Palette &dst, int brightness, int16 modifier) {
- dst.copy(src);
- if (_flags.use16ColorMode) {
- if (!brightness)
- modifier = 0;
- else if (modifier < 0 || modifier > 7 || !(_flagsTable[31] & 0x08))
- modifier = 8;
- modifier >>= 1;
- if (modifier)
- modifier--;
- if (modifier > 3)
- modifier = 3;
- _blockBrightness = modifier << 4;
- _sceneUpdateRequired = true;
- } else {
- _screen->loadSpecialColors(dst);
- brightness = (8 - brightness) << 5;
- if (modifier >= 0 && modifier < 8 && (_flagsTable[31] & 0x08)) {
- brightness = 256 - ((((modifier & 0xFFFE) << 5) * (256 - brightness)) >> 8);
- if (brightness < 0)
- brightness = 0;
- }
- for (int i = 0; i < 384; i++) {
- uint16 c = (dst[i] * brightness) >> 8;
- dst[i] = c & 0xFF;
- }
- }
- }
- void LoLEngine::generateFlashPalette(const Palette &src, Palette &dst, int colorFlags) {
- dst.copy(src, 0, 2);
- for (int i = 2; i < 128; i++) {
- for (int ii = 0; ii < 3; ii++) {
- uint8 t = src[i * 3 + ii] & 0x3F;
- if (colorFlags & (1 << ii))
- t += ((0x3F - t) >> 1);
- else
- t -= (t >> 1);
- dst[i * 3 + ii] = t;
- }
- }
- dst.copy(src, 128);
- }
- void LoLEngine::createTransparencyTables() {
- if (_flags.isTalkie || _loadSuppFilesFlag)
- return;
- uint8 *tpal = new uint8[768];
- if (_flags.use16ColorMode) {
- static const uint8 colTbl[] = {
- 0x00, 0x00, 0x11, 0x00, 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x55, 0x00, 0x66, 0x00, 0x77, 0x00,
- 0x88, 0x00, 0x99, 0x00, 0xAA, 0x00, 0xBB, 0x00, 0xCC, 0x00, 0xDD, 0x00, 0xEE, 0x00, 0xFF, 0x00
- };
- memset(tpal, 0xFF, 768);
- _res->loadFileToBuf("LOL.NOL", tpal, 48);
- for (int i = 15; i > -1; i--) {
- int s = colTbl[i << 1] * 3;
- tpal[s] = tpal[i * 3];
- tpal[s + 1] = tpal[i * 3 + 1];
- tpal[s + 2] = tpal[i * 3 + 2];
- tpal[i * 3 + 2] = tpal[i * 3 + 1] = tpal[i * 3] = 0xFF;
- }
- _screen->createTransparencyTablesIntern(colTbl, 16, tpal, tpal, _transparencyTable1, _transparencyTable2, 80);
- } else {
- _res->loadFileToBuf("fxpal.col", tpal, 768);
- _screen->loadBitmap("fxpal.shp", 3, 3, 0);
- const uint8 *shpPal = _screen->getPtrToShape(_screen->getCPagePtr(2), 0) + 11;
- _screen->createTransparencyTablesIntern(shpPal, 20, tpal, _screen->getPalette(1).getData(), _transparencyTable1, _transparencyTable2, 70);
- }
- delete[] tpal;
- _loadSuppFilesFlag = 1;
- }
- void LoLEngine::updateSequenceBackgroundAnimations() {
- if (_updateFlags & 8 || !_tim)
- return;
- if (!_tim->animator())
- return;
- for (int i = 0; i < 6; i++)
- _tim->animator()->update(i);
- }
- void LoLEngine::loadTalkFile(int index) {
- if (index == _curTlkFile)
- return;
- if (_curTlkFile > 0 && index > 0)
- _res->unloadPakFile(Common::String::format("%02d.TLK", _curTlkFile));
- if (index > 0)
- _curTlkFile = index;
- _res->loadPakFile(Common::String::format("%02d.TLK", index));
- }
- int LoLEngine::characterSays(int track, int charId, bool redraw) {
- if (charId == 1) {
- charId = _selectedCharacter;
- } if (charId <= 0) {
- charId = 0;
- } else {
- int i = 0;
- for (; i < 4; i++) {
- if (charId != _characters[i].id || !(_characters[i].flags & 1))
- continue;
- charId = i;
- break;
- }
- if (i == 4)
- return 0;
- }
- bool r = snd_playCharacterSpeech(track, charId, 0);
- if (r && redraw) {
- stopPortraitSpeechAnim();
- _updateCharNum = charId;
- _portraitSpeechAnimMode = 0;
- _resetPortraitAfterSpeechAnim = 1;
- _fadeText = false;
- updatePortraitSpeechAnim();
- }
- return r ? (textEnabled() ? 1 : 0) : 1;
- }
- int LoLEngine::playCharacterScriptChat(int charId, int mode, int restorePortrait, char *str, EMCState *script, const uint16 *paramList, int16 paramIndex) {
- int ch = 0;
- bool skipAnim = false;
- if ((charId == -1) || (!(charId & 0x70)))
- charId = ch = (charId == 1) ? (_selectedCharacter ? _characters[_selectedCharacter].id : 0) : charId;
- else
- charId ^= 0x70;
- stopPortraitSpeechAnim();
- if (charId < 0) {
- charId = ch = _rnd.getRandomNumber(countActiveCharacters() - 1);
- } else if (charId > 0) {
- int i = 0;
- for (; i < 3; i++) {
- if (_characters[i].id != charId || !(_characters[i].flags & 1))
- continue;
- if (charId == ch)
- ch = i;
- charId = i;
- break;
- }
- if (i == 4) {
- if (charId == 8)
- skipAnim = true;
- else
- return 0;
- }
- }
- if (!skipAnim) {
- _updateCharNum = charId;
- _portraitSpeechAnimMode = mode;
- _updatePortraitSpeechAnimDuration = strlen(str) >> 1;
- _resetPortraitAfterSpeechAnim = restorePortrait;
- }
- if (script)
- snd_playCharacterSpeech(script->stack[script->sp + 2], ch, 0);
- else if (paramList)
- snd_playCharacterSpeech(paramList[2], ch, 0);
- if (textEnabled()) {
- if (mode == 0) {
- _txt->printDialogueText(3, str, script, paramList, paramIndex);
- } else if (mode == 1) {
- _txt->clearDim(4);
- _screen->modifyScreenDim(4, 16, 123, 23, 47);
- _txt->printDialogueText(4, str, script, paramList, paramIndex);
- _screen->modifyScreenDim(4, 11, 123, 28, 47);
- } else if (mode == 2) {
- _txt->clearDim(4);
- _screen->modifyScreenDim(4, 9, 133, 30, 60);
- _txt->printDialogueText(4, str, script, paramList, 3…
Large files files are truncated, but you can click here to view the full file