/* 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. * */ #include "common/scummsys.h" #include "zvision/scripting/actions.h" #include "zvision/zvision.h" #include "zvision/scripting/script_manager.h" #include "zvision/graphics/render_manager.h" #include "zvision/sound/zork_raw.h" #include "zvision/video/zork_avi_decoder.h" #include "zvision/scripting/sidefx/timer_node.h" #include "zvision/scripting/sidefx/music_node.h" #include "zvision/scripting/sidefx/syncsound_node.h" #include "zvision/scripting/sidefx/animation_node.h" #include "zvision/scripting/sidefx/distort_node.h" #include "zvision/scripting/sidefx/ttytext_node.h" #include "zvision/scripting/sidefx/region_node.h" #include "zvision/scripting/controls/titler_control.h" #include "zvision/graphics/render_table.h" #include "zvision/graphics/effect.h" #include "zvision/graphics/effects/fog.h" #include "zvision/graphics/effects/light.h" #include "zvision/graphics/effects/wave.h" #include "zvision/core/save_manager.h" #include "zvision/cursors/cursor_manager.h" #include "common/file.h" #include "audio/decoders/wave.h" namespace ZVision { ////////////////////////////////////////////////////////////////////////////// // ActionAdd ////////////////////////////////////////////////////////////////////////////// ActionAdd::ActionAdd(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { sscanf(line.c_str(), "%u,%d", &_key, &_value); } bool ActionAdd::execute() { _engine->getScriptManager()->setStateValue(_key, _engine->getScriptManager()->getStateValue(_key) + _value); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionAssign ////////////////////////////////////////////////////////////////////////////// ActionAssign::ActionAssign(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { char buf[64]; memset(buf, 0, 64); sscanf(line.c_str(), "%u, %s", &_key, buf); _value = new ValueSlot(_engine->getScriptManager(), buf); } ActionAssign::~ActionAssign() { if (_value) delete _value; } bool ActionAssign::execute() { _engine->getScriptManager()->setStateValue(_key, _value->getValue()); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionAttenuate ////////////////////////////////////////////////////////////////////////////// ActionAttenuate::ActionAttenuate(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { sscanf(line.c_str(), "%u, %d", &_key, &_attenuation); } bool ActionAttenuate::execute() { SideFX *fx = _engine->getScriptManager()->getSideFX(_key); if (fx && fx->getType() == SideFX::SIDEFX_AUDIO) { MusicNode *mus = (MusicNode *)fx; mus->setVolume(255 - (abs(_attenuation) >> 7)); } return true; } ////////////////////////////////////////////////////////////////////////////// // ActionChangeLocation ////////////////////////////////////////////////////////////////////////////// ActionChangeLocation::ActionChangeLocation(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { sscanf(line.c_str(), "%c, %c, %c%c, %u", &_world, &_room, &_node, &_view, &_offset); } bool ActionChangeLocation::execute() { // We can't directly call ScriptManager::ChangeLocationIntern() because doing so clears all the Puzzles, and thus would corrupt the current puzzle checking _engine->getScriptManager()->changeLocation(_world, _room, _node, _view, _offset); // Tell the puzzle system to stop checking any more puzzles return false; } ////////////////////////////////////////////////////////////////////////////// // ActionCrossfade ////////////////////////////////////////////////////////////////////////////// ActionCrossfade::ActionCrossfade(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { sscanf(line.c_str(), "%u %u %d %d %d %d %d", &_keyOne, &_keyTwo, &_oneStartVolume, &_twoStartVolume, &_oneEndVolume, &_twoEndVolume, &_timeInMillis); } bool ActionCrossfade::execute() { if (_keyOne) { SideFX *fx = _engine->getScriptManager()->getSideFX(_keyOne); if (fx && fx->getType() == SideFX::SIDEFX_AUDIO) { MusicNode *mus = (MusicNode *)fx; if (_oneStartVolume >= 0) mus->setVolume((_oneStartVolume * 255) / 100); mus->setFade(_timeInMillis, (_oneEndVolume * 255) / 100); } } if (_keyTwo) { SideFX *fx = _engine->getScriptManager()->getSideFX(_keyTwo); if (fx && fx->getType() == SideFX::SIDEFX_AUDIO) { MusicNode *mus = (MusicNode *)fx; if (_twoStartVolume >= 0) mus->setVolume((_twoStartVolume * 255) / 100); mus->setFade(_timeInMillis, (_twoEndVolume * 255) / 100); } } return true; } ////////////////////////////////////////////////////////////////////////////// // ActionCursor ////////////////////////////////////////////////////////////////////////////// ActionCursor::ActionCursor(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { Common::String up = line; up.toUppercase(); _action = 0; if (up[0] == 'B') _action = 2; else if (up[0] == 'I') _action = 3; else if (up[0] == 'U') _action = 0; else if (up[0] == 'H') _action = 1; } bool ActionCursor::execute() { switch (_action) { case 1: _engine->getCursorManager()->showMouse(false); break; default: _engine->getCursorManager()->showMouse(true); break; } return true; } ////////////////////////////////////////////////////////////////////////////// // ActionDelayRender ////////////////////////////////////////////////////////////////////////////// ActionDelayRender::ActionDelayRender(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { sscanf(line.c_str(), "%u", &_framesToDelay); } bool ActionDelayRender::execute() { _engine->setRenderDelay(_framesToDelay); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionDisableControl ////////////////////////////////////////////////////////////////////////////// ActionDisableControl::ActionDisableControl(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { sscanf(line.c_str(), "%u", &_key); } bool ActionDisableControl::execute() { _engine->getScriptManager()->setStateFlag(_key, Puzzle::DISABLED); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionDisableVenus ////////////////////////////////////////////////////////////////////////////// ActionDisableVenus::ActionDisableVenus(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { sscanf(line.c_str(), "%d", &_key); } bool ActionDisableVenus::execute() { _engine->getScriptManager()->setStateValue(_key, 0); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionDisplayMessage ////////////////////////////////////////////////////////////////////////////// ActionDisplayMessage::ActionDisplayMessage(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { sscanf(line.c_str(), "%hd %hd", &_control, &_msgid); } bool ActionDisplayMessage::execute() { Control *ctrl = _engine->getScriptManager()->getControl(_control); if (ctrl && ctrl->getType() == Control::CONTROL_TITLER) { TitlerControl *titler = (TitlerControl *)ctrl; titler->setString(_msgid); } return true; } ////////////////////////////////////////////////////////////////////////////// // ActionDissolve ////////////////////////////////////////////////////////////////////////////// ActionDissolve::ActionDissolve(ZVision *engine) : ResultAction(engine, 0) { } bool ActionDissolve::execute() { // Cause black screen flick // _engine->getRenderManager()->bkgFill(0, 0, 0); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionDistort ////////////////////////////////////////////////////////////////////////////// ActionDistort::ActionDistort(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { sscanf(line.c_str(), "%hd %hd %f %f %f %f", &_distSlot, &_speed, &_startAngle, &_endAngle, &_startLineScale, &_endLineScale); } ActionDistort::~ActionDistort() { _engine->getScriptManager()->killSideFx(_distSlot); } bool ActionDistort::execute() { if (_engine->getScriptManager()->getSideFX(_distSlot)) return true; _engine->getScriptManager()->addSideFX(new DistortNode(_engine, _distSlot, _speed, _startAngle, _endAngle, _startLineScale, _endLineScale)); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionEnableControl ////////////////////////////////////////////////////////////////////////////// ActionEnableControl::ActionEnableControl(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { sscanf(line.c_str(), "%u", &_key); } bool ActionEnableControl::execute() { _engine->getScriptManager()->unsetStateFlag(_key, Puzzle::DISABLED); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionFlushMouseEvents ////////////////////////////////////////////////////////////////////////////// ActionFlushMouseEvents::ActionFlushMouseEvents(ZVision *engine, int32 slotkey) : ResultAction(engine, slotkey) { } bool ActionFlushMouseEvents::execute() { _engine->getScriptManager()->flushEvent(Common::EVENT_LBUTTONUP); _engine->getScriptManager()->flushEvent(Common::EVENT_LBUTTONDOWN); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionInventory ////////////////////////////////////////////////////////////////////////////// ActionInventory::ActionInventory(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { char buf[25]; sscanf(line.c_str(), "%25s %d", buf, &_key); if (strcmp(buf, "add") == 0) { _type = 0; } else if (strcmp(buf, "addi") == 0) { _type = 1; } else if (strcmp(buf, "drop") == 0) { _type = 2; } else if (strcmp(buf, "dropi") == 0) { _type = 3; } else if (strcmp(buf, "cycle") == 0) { _type = 4; } } bool ActionInventory::execute() { switch (_type) { case 0: // add _engine->getScriptManager()->inventoryAdd(_key); break; case 1: // addi _engine->getScriptManager()->inventoryAdd(_engine->getScriptManager()->getStateValue(_key)); break; case 2: // drop if (_key >= 0) _engine->getScriptManager()->inventoryDrop(_key); else _engine->getScriptManager()->inventoryDrop(_engine->getScriptManager()->getStateValue(StateKey_InventoryItem)); break; case 3: // dropi _engine->getScriptManager()->inventoryDrop(_engine->getScriptManager()->getStateValue(_key)); break; case 4: // cycle _engine->getScriptManager()->inventoryCycle(); break; default: break; } return true; } ////////////////////////////////////////////////////////////////////////////// // ActionKill ////////////////////////////////////////////////////////////////////////////// ActionKill::ActionKill(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { _key = 0; _type = 0; char keytype[25]; sscanf(line.c_str(), "%25s", keytype); if (keytype[0] == '"') { if (!scumm_stricmp(keytype, "\"ANIM\"")) _type = SideFX::SIDEFX_ANIM; else if (!scumm_stricmp(keytype, "\"AUDIO\"")) _type = SideFX::SIDEFX_AUDIO; else if (!scumm_stricmp(keytype, "\"DISTORT\"")) _type = SideFX::SIDEFX_DISTORT; else if (!scumm_stricmp(keytype, "\"PANTRACK\"")) _type = SideFX::SIDEFX_PANTRACK; else if (!scumm_stricmp(keytype, "\"REGION\"")) _type = SideFX::SIDEFX_REGION; else if (!scumm_stricmp(keytype, "\"TIMER\"")) _type = SideFX::SIDEFX_TIMER; else if (!scumm_stricmp(keytype, "\"TTYTEXT\"")) _type = SideFX::SIDEFX_TTYTXT; else if (!scumm_stricmp(keytype, "\"ALL\"")) _type = SideFX::SIDEFX_ALL; } else _key = atoi(keytype); } bool ActionKill::execute() { if (_type) _engine->getScriptManager()->killSideFxType((SideFX::SideFXType)_type); else _engine->getScriptManager()->killSideFx(_key); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionMenuBarEnable ////////////////////////////////////////////////////////////////////////////// ActionMenuBarEnable::ActionMenuBarEnable(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { sscanf(line.c_str(), "%hu", &_menus); } bool ActionMenuBarEnable::execute() { _engine->menuBarEnable(_menus); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionMusic ////////////////////////////////////////////////////////////////////////////// ActionMusic::ActionMusic(ZVision *engine, int32 slotkey, const Common::String &line, bool global) : ResultAction(engine, slotkey), _volume(255), _universe(global) { uint type; char fileNameBuffer[25]; uint loop; uint volume = 255; sscanf(line.c_str(), "%u %25s %u %u", &type, fileNameBuffer, &loop, &volume); // type 4 are midi sound effect files if (type == 4) { _midi = true; int note; int prog; sscanf(line.c_str(), "%u %d %d %u", &type, &prog, ¬e, &volume); _volume = volume; _note = note; _prog = prog; } else { _midi = false; _fileName = Common::String(fileNameBuffer); _loop = loop == 1 ? true : false; // Volume is optional. If it doesn't appear, assume full volume if (volume != 255) { // Volume in the script files is mapped to [0, 100], but the ScummVM mixer uses [0, 255] _volume = volume * 255 / 100; } } } ActionMusic::~ActionMusic() { if (!_universe) _engine->getScriptManager()->killSideFx(_slotKey); } bool ActionMusic::execute() { if (_engine->getScriptManager()->getSideFX(_slotKey)) return true; if (_midi) { _engine->getScriptManager()->addSideFX(new MusicMidiNode(_engine, _slotKey, _prog, _note, _volume)); } else { if (!_engine->getSearchManager()->hasFile(_fileName)) return true; _engine->getScriptManager()->addSideFX(new MusicNode(_engine, _slotKey, _fileName, _loop, _volume)); } return true; } ////////////////////////////////////////////////////////////////////////////// // ActionPanTrack ////////////////////////////////////////////////////////////////////////////// ActionPanTrack::ActionPanTrack(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey), _pos(0), _musicSlot(0) { sscanf(line.c_str(), "%u %d", &_musicSlot, &_pos); } ActionPanTrack::~ActionPanTrack() { _engine->getScriptManager()->killSideFx(_slotKey); } bool ActionPanTrack::execute() { if (_engine->getScriptManager()->getSideFX(_slotKey)) return true; _engine->getScriptManager()->addSideFX(new PanTrackNode(_engine, _slotKey, _musicSlot, _pos)); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionPreferences ////////////////////////////////////////////////////////////////////////////// ActionPreferences::ActionPreferences(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { if (line.compareToIgnoreCase("save") == 0) _save = true; else _save = false; } bool ActionPreferences::execute() { if (_save) _engine->saveSettings(); else _engine->loadSettings(); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionPreloadAnimation ////////////////////////////////////////////////////////////////////////////// ActionPreloadAnimation::ActionPreloadAnimation(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { char fileName[25]; // The two %*u are always 0 and dont seem to have a use sscanf(line.c_str(), "%25s %*u %*u %d %d", fileName, &_mask, &_framerate); if (_mask > 0) { byte r, g, b; Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(_mask, r, g, b); _mask = _engine->_pixelFormat.RGBToColor(r, g, b); } _fileName = Common::String(fileName); } ActionPreloadAnimation::~ActionPreloadAnimation() { _engine->getScriptManager()->deleteSideFx(_slotKey); } bool ActionPreloadAnimation::execute() { AnimationNode *nod = (AnimationNode *)_engine->getScriptManager()->getSideFX(_slotKey); if (!nod) { nod = new AnimationNode(_engine, _slotKey, _fileName, _mask, _framerate, false); _engine->getScriptManager()->addSideFX(nod); } else nod->stop(); _engine->getScriptManager()->setStateValue(_slotKey, 2); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionUnloadAnimation ////////////////////////////////////////////////////////////////////////////// ActionUnloadAnimation::ActionUnloadAnimation(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { sscanf(line.c_str(), "%u", &_key); } bool ActionUnloadAnimation::execute() { AnimationNode *nod = (AnimationNode *)_engine->getScriptManager()->getSideFX(_key); if (nod && nod->getType() == SideFX::SIDEFX_ANIM) _engine->getScriptManager()->deleteSideFx(_key); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionPlayAnimation ////////////////////////////////////////////////////////////////////////////// ActionPlayAnimation::ActionPlayAnimation(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { char fileName[25]; // The two %*u are always 0 and dont seem to have a use sscanf(line.c_str(), "%25s %u %u %u %u %u %u %d %*u %*u %d %d", fileName, &_x, &_y, &_x2, &_y2, &_start, &_end, &_loopCount, &_mask, &_framerate); if (_mask > 0) { byte r, g, b; Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(_mask, r, g, b); _mask = _engine->_pixelFormat.RGBToColor(r, g, b); } _fileName = Common::String(fileName); } ActionPlayAnimation::~ActionPlayAnimation() { _engine->getScriptManager()->deleteSideFx(_slotKey); } bool ActionPlayAnimation::execute() { AnimationNode *nod = (AnimationNode *)_engine->getScriptManager()->getSideFX(_slotKey); if (!nod) { nod = new AnimationNode(_engine, _slotKey, _fileName, _mask, _framerate); _engine->getScriptManager()->addSideFX(nod); } else nod->stop(); if (nod) nod->addPlayNode(_slotKey, _x, _y, _x2, _y2, _start, _end, _loopCount); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionPlayPreloadAnimation ////////////////////////////////////////////////////////////////////////////// ActionPlayPreloadAnimation::ActionPlayPreloadAnimation(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { sscanf(line.c_str(), "%u %u %u %u %u %u %u %u", &_controlKey, &_x1, &_y1, &_x2, &_y2, &_startFrame, &_endFrame, &_loopCount); } bool ActionPlayPreloadAnimation::execute() { AnimationNode *nod = (AnimationNode *)_engine->getScriptManager()->getSideFX(_controlKey); if (nod) nod->addPlayNode(_slotKey, _x1, _y1, _x2, _y2, _startFrame, _endFrame, _loopCount); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionQuit ////////////////////////////////////////////////////////////////////////////// bool ActionQuit::execute() { _engine->quitGame(); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionRegion ////////////////////////////////////////////////////////////////////////////// ActionRegion::ActionRegion(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { char art[64]; char custom[64]; int32 x1, x2, y1, y2; sscanf(line.c_str(), "%s %d %d %d %d %hu %hu %hu %hu %s", art, &x1, &y1, &x2, &y2, &_delay, &_type, &_unk1, &_unk2, custom); _art = Common::String(art); _custom = Common::String(custom); _rect = Common::Rect(x1, y1, x2 + 1, y2 + 1); } ActionRegion::~ActionRegion() { _engine->getScriptManager()->killSideFx(_slotKey); } bool ActionRegion::execute() { if (_engine->getScriptManager()->getSideFX(_slotKey)) return true; Effect *effct = NULL; switch (_type) { case 0: { uint16 centerX, centerY, frames; double amplitude, waveln, speed; sscanf(_custom.c_str(), "%hu,%hu,%hu,%lf,%lf,%lf,", ¢erX, ¢erY, &frames, &litude, &waveln, &speed); effct = new WaveFx(_engine, _slotKey, _rect, _unk1, frames, centerX, centerY, amplitude, waveln, speed); } break; case 1: { uint16 aX, aY, aD; if (_engine->getRenderManager()->getRenderTable()->getRenderState() == RenderTable::PANORAMA) sscanf(_art.c_str(), "useart[%hu,%hu,%hu]", &aY, &aX, &aD); else sscanf(_art.c_str(), "useart[%hu,%hu,%hu]", &aX, &aY, &aD); int8 minD; int8 maxD; EffectMap *_map = _engine->getRenderManager()->makeEffectMap(Common::Point(aX, aY), aD, _rect, &minD, &maxD); effct = new LightFx(_engine, _slotKey, _rect, _unk1, _map, atoi(_custom.c_str()), minD, maxD); } break; case 9: { int16 dum1; int32 dum2; char buf[64]; sscanf(_custom.c_str(), "%hd,%d,%s", &dum1, &dum2, buf); Graphics::Surface tempMask; _engine->getRenderManager()->readImageToSurface(_art, tempMask); if (_rect.width() != tempMask.w) _rect.setWidth(tempMask.w); if (_rect.height() != tempMask.h) _rect.setHeight(tempMask.h); EffectMap *_map = _engine->getRenderManager()->makeEffectMap(tempMask, 0); effct = new FogFx(_engine, _slotKey, _rect, _unk1, _map, Common::String(buf)); } break; default: break; } if (effct) { _engine->getScriptManager()->addSideFX(new RegionNode(_engine, _slotKey, effct, _delay)); _engine->getRenderManager()->addEffect(effct); } return true; } ////////////////////////////////////////////////////////////////////////////// // ActionRandom ////////////////////////////////////////////////////////////////////////////// ActionRandom::ActionRandom(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { char maxBuffer[64]; memset(maxBuffer, 0, 64); sscanf(line.c_str(), "%s", maxBuffer); _max = new ValueSlot(_engine->getScriptManager(), maxBuffer); } ActionRandom::~ActionRandom() { if (_max) delete _max; } bool ActionRandom::execute() { uint randNumber = _engine->getRandomSource()->getRandomNumber(_max->getValue()); _engine->getScriptManager()->setStateValue(_slotKey, randNumber); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionRestoreGame ////////////////////////////////////////////////////////////////////////////// ActionRestoreGame::ActionRestoreGame(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { char buf[128]; sscanf(line.c_str(), "%s", buf); _fileName = Common::String(buf); } bool ActionRestoreGame::execute() { _engine->getSaveManager()->loadGame(_fileName); return false; } ////////////////////////////////////////////////////////////////////////////// // ActionRotateTo ////////////////////////////////////////////////////////////////////////////// ActionRotateTo::ActionRotateTo(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { sscanf(line.c_str(), "%d, %d", &_toPos, &_time); } bool ActionRotateTo::execute() { _engine->rotateTo(_toPos, _time); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionSetPartialScreen ////////////////////////////////////////////////////////////////////////////// ActionSetPartialScreen::ActionSetPartialScreen(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { char fileName[25]; int color; sscanf(line.c_str(), "%u %u %25s %*u %d", &_x, &_y, fileName, &color); _fileName = Common::String(fileName); if (color >= 0) { byte r, g, b; Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(color, r, g, b); _backgroundColor = _engine->_pixelFormat.RGBToColor(r, g, b); } else { _backgroundColor = color; } if (color > 65535) { warning("Background color for ActionSetPartialScreen is bigger than a uint16"); } } bool ActionSetPartialScreen::execute() { RenderManager *renderManager = _engine->getRenderManager(); if (_engine->getGameId() == GID_NEMESIS) { if (_backgroundColor) renderManager->renderImageToBackground(_fileName, _x, _y, 0, 0); else renderManager->renderImageToBackground(_fileName, _x, _y); } else { if (_backgroundColor >= 0) renderManager->renderImageToBackground(_fileName, _x, _y, _backgroundColor); else if (_backgroundColor == -2) renderManager->renderImageToBackground(_fileName, _x, _y, 0, 0); else renderManager->renderImageToBackground(_fileName, _x, _y); } return true; } ////////////////////////////////////////////////////////////////////////////// // ActionSetScreen ////////////////////////////////////////////////////////////////////////////// ActionSetScreen::ActionSetScreen(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { char fileName[25]; sscanf(line.c_str(), "%25s", fileName); _fileName = Common::String(fileName); } bool ActionSetScreen::execute() { _engine->getRenderManager()->setBackgroundImage(_fileName); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionSetVenus ////////////////////////////////////////////////////////////////////////////// ActionSetVenus::ActionSetVenus(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { sscanf(line.c_str(), "%d", &_key); } bool ActionSetVenus::execute() { if (_engine->getScriptManager()->getStateValue(_key)) _engine->getScriptManager()->setStateValue(StateKey_Venus, _key); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionStop ////////////////////////////////////////////////////////////////////////////// ActionStop::ActionStop(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { _key = 0; sscanf(line.c_str(), "%u", &_key); } bool ActionStop::execute() { _engine->getScriptManager()->stopSideFx(_key); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionStreamVideo ////////////////////////////////////////////////////////////////////////////// ActionStreamVideo::ActionStreamVideo(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { char fileName[25]; uint skipline; //skipline - render video with skip every second line, not skippable. sscanf(line.c_str(), "%25s %u %u %u %u %u %u", fileName, &_x1, &_y1, &_x2, &_y2, &_flags, &skipline); _fileName = Common::String(fileName); _skippable = true; } bool ActionStreamVideo::execute() { ZorkAVIDecoder decoder; Common::File *_file = _engine->getSearchManager()->openFile(_fileName); if (_file) { if (!decoder.loadStream(_file)) { return true; } _engine->getCursorManager()->showMouse(false); Common::Rect destRect = Common::Rect(_x1, _y1, _x2 + 1, _y2 + 1); Common::String subname = _fileName; subname.setChar('s', subname.size() - 3); subname.setChar('u', subname.size() - 2); subname.setChar('b', subname.size() - 1); Subtitle *sub = NULL; if (_engine->getSearchManager()->hasFile(subname)) sub = new Subtitle(_engine, subname); _engine->playVideo(decoder, destRect, _skippable, sub); _engine->getCursorManager()->showMouse(true); if (sub) delete sub; } return true; } ////////////////////////////////////////////////////////////////////////////// // ActionSyncSound ////////////////////////////////////////////////////////////////////////////// ActionSyncSound::ActionSyncSound(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { char fileName[25]; int notUsed; sscanf(line.c_str(), "%d %d %25s", &_syncto, ¬Used, fileName); _fileName = Common::String(fileName); } bool ActionSyncSound::execute() { SideFX *fx = _engine->getScriptManager()->getSideFX(_syncto); if (!fx) return true; if (!(fx->getType() & SideFX::SIDEFX_ANIM)) return true; AnimationNode *animnode = (AnimationNode *)fx; if (animnode->getFrameDelay() > 200) // Hack for fix incorrect framedelay in some animpreload animnode->setNewFrameDelay(66); // ~15fps _engine->getScriptManager()->addSideFX(new SyncSoundNode(_engine, _slotKey, _fileName, _syncto)); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionTimer ////////////////////////////////////////////////////////////////////////////// ActionTimer::ActionTimer(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { char timeBuffer[64]; memset(timeBuffer, 0, 64); sscanf(line.c_str(), "%s", timeBuffer); _time = new ValueSlot(_engine->getScriptManager(), timeBuffer); } ActionTimer::~ActionTimer() { if (_time) delete _time; _engine->getScriptManager()->killSideFx(_slotKey); } bool ActionTimer::execute() { if (_engine->getScriptManager()->getSideFX(_slotKey)) return true; _engine->getScriptManager()->addSideFX(new TimerNode(_engine, _slotKey, _time->getValue())); return true; } ////////////////////////////////////////////////////////////////////////////// // ActionTtyText ////////////////////////////////////////////////////////////////////////////// ActionTtyText::ActionTtyText(ZVision *engine, int32 slotkey, const Common::String &line) : ResultAction(engine, slotkey) { char filename[64]; int32 x1, y1, x2, y2; sscanf(line.c_str(), "%d %d %d %d %s %u", &x1, &y1, &x2, &y2, filename, &_delay); _r = Common::Rect(x1, y1, x2, y2); _filename = Common::String(filename); } ActionTtyText::~ActionTtyText() { _engine->getScriptManager()->killSideFx(_slotKey); } bool ActionTtyText::execute() { if (_engine->getScriptManager()->getSideFX(_slotKey)) return true; _engine->getScriptManager()->addSideFX(new ttyTextNode(_engine, _slotKey, _filename, _r, _delay)); return true; } } // End of namespace ZVision