aboutsummaryrefslogtreecommitdiff
path: root/engines/zvision/scripting
diff options
context:
space:
mode:
Diffstat (limited to 'engines/zvision/scripting')
-rw-r--r--engines/zvision/scripting/actions.cpp381
-rw-r--r--engines/zvision/scripting/actions.h16
-rw-r--r--engines/zvision/scripting/controls/fist_control.cpp7
-rw-r--r--engines/zvision/scripting/controls/input_control.cpp35
-rw-r--r--engines/zvision/scripting/controls/input_control.h10
-rw-r--r--engines/zvision/scripting/controls/lever_control.cpp3
-rw-r--r--engines/zvision/scripting/controls/safe_control.cpp4
-rw-r--r--engines/zvision/scripting/controls/titler_control.cpp2
-rw-r--r--engines/zvision/scripting/effects/distort_effect.cpp2
-rw-r--r--engines/zvision/scripting/effects/music_effect.cpp156
-rw-r--r--engines/zvision/scripting/effects/music_effect.h28
-rw-r--r--engines/zvision/scripting/effects/ttytext_effect.cpp40
-rw-r--r--engines/zvision/scripting/effects/ttytext_effect.h2
-rw-r--r--engines/zvision/scripting/menu.cpp100
-rw-r--r--engines/zvision/scripting/menu.h16
-rw-r--r--engines/zvision/scripting/scr_file_handling.cpp72
-rw-r--r--engines/zvision/scripting/script_manager.cpp240
-rw-r--r--engines/zvision/scripting/script_manager.h28
-rw-r--r--engines/zvision/scripting/scripting_effect.h2
19 files changed, 713 insertions, 431 deletions
diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp
index f60fdbb973..e1380b0eb2 100644
--- a/engines/zvision/scripting/actions.cpp
+++ b/engines/zvision/scripting/actions.cpp
@@ -23,11 +23,12 @@
#include "common/scummsys.h"
#include "video/video_decoder.h"
+#include "zvision/scripting/actions.h"
+
#include "zvision/zvision.h"
#include "zvision/scripting/script_manager.h"
#include "zvision/graphics/render_manager.h"
#include "zvision/file/save_manager.h"
-#include "zvision/scripting/actions.h"
#include "zvision/scripting/menu.h"
#include "zvision/scripting/effects/timer_effect.h"
#include "zvision/scripting/effects/music_effect.h"
@@ -46,12 +47,18 @@
namespace ZVision {
+ResultAction::ResultAction(ZVision *engine, int32 slotKey) :
+ _engine(engine),
+ _slotKey(slotKey),
+ _scriptManager(engine->getScriptManager()) {
+}
+
//////////////////////////////////////////////////////////////////////////////
// ActionAdd
//////////////////////////////////////////////////////////////////////////////
-ActionAdd::ActionAdd(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionAdd::ActionAdd(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_key = 0;
_value = 0;
@@ -59,7 +66,7 @@ ActionAdd::ActionAdd(ZVision *engine, int32 slotkey, const Common::String &line)
}
bool ActionAdd::execute() {
- _engine->getScriptManager()->setStateValue(_key, _engine->getScriptManager()->getStateValue(_key) + _value);
+ _scriptManager->setStateValue(_key, _scriptManager->getStateValue(_key) + _value);
return true;
}
@@ -67,23 +74,22 @@ bool ActionAdd::execute() {
// ActionAssign
//////////////////////////////////////////////////////////////////////////////
-ActionAssign::ActionAssign(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionAssign::ActionAssign(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_key = 0;
char buf[64];
memset(buf, 0, 64);
sscanf(line.c_str(), "%u, %s", &_key, buf);
- _value = new ValueSlot(_engine->getScriptManager(), buf);
+ _value = new ValueSlot(_scriptManager, buf);
}
ActionAssign::~ActionAssign() {
- if (_value)
- delete _value;
+ delete _value;
}
bool ActionAssign::execute() {
- _engine->getScriptManager()->setStateValue(_key, _value->getValue());
+ _scriptManager->setStateValue(_key, _value->getValue());
return true;
}
@@ -91,8 +97,8 @@ bool ActionAssign::execute() {
// ActionAttenuate
//////////////////////////////////////////////////////////////////////////////
-ActionAttenuate::ActionAttenuate(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionAttenuate::ActionAttenuate(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_key = 0;
_attenuation = 0;
@@ -100,10 +106,10 @@ ActionAttenuate::ActionAttenuate(ZVision *engine, int32 slotkey, const Common::S
}
bool ActionAttenuate::execute() {
- ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_key);
+ ScriptingEffect *fx = _scriptManager->getSideFX(_key);
if (fx && fx->getType() == ScriptingEffect::SCRIPTING_EFFECT_AUDIO) {
- MusicNode *mus = (MusicNode *)fx;
- mus->setVolume(255 - (abs(_attenuation) >> 7));
+ MusicNodeBASE *mus = (MusicNodeBASE *)fx;
+ mus->setVolume(255 * (10000 - abs(_attenuation)) / 10000 );
}
return true;
}
@@ -112,8 +118,8 @@ bool ActionAttenuate::execute() {
// ActionChangeLocation
//////////////////////////////////////////////////////////////////////////////
-ActionChangeLocation::ActionChangeLocation(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionChangeLocation::ActionChangeLocation(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_world = 'g';
_room = 'a';
_node = 'r';
@@ -125,7 +131,7 @@ ActionChangeLocation::ActionChangeLocation(ZVision *engine, int32 slotkey, const
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);
+ _scriptManager->changeLocation(_world, _room, _node, _view, _offset);
// Tell the puzzle system to stop checking any more puzzles
return false;
}
@@ -134,8 +140,8 @@ bool ActionChangeLocation::execute() {
// ActionCrossfade
//////////////////////////////////////////////////////////////////////////////
-ActionCrossfade::ActionCrossfade(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionCrossfade::ActionCrossfade(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_keyOne = 0;
_keyTwo = 0;
_oneStartVolume = 0;
@@ -151,9 +157,9 @@ ActionCrossfade::ActionCrossfade(ZVision *engine, int32 slotkey, const Common::S
bool ActionCrossfade::execute() {
if (_keyOne) {
- ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_keyOne);
+ ScriptingEffect *fx = _scriptManager->getSideFX(_keyOne);
if (fx && fx->getType() == ScriptingEffect::SCRIPTING_EFFECT_AUDIO) {
- MusicNode *mus = (MusicNode *)fx;
+ MusicNodeBASE *mus = (MusicNodeBASE *)fx;
if (_oneStartVolume >= 0)
mus->setVolume((_oneStartVolume * 255) / 100);
@@ -162,9 +168,9 @@ bool ActionCrossfade::execute() {
}
if (_keyTwo) {
- ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_keyTwo);
+ ScriptingEffect *fx = _scriptManager->getSideFX(_keyTwo);
if (fx && fx->getType() == ScriptingEffect::SCRIPTING_EFFECT_AUDIO) {
- MusicNode *mus = (MusicNode *)fx;
+ MusicNodeBASE *mus = (MusicNodeBASE *)fx;
if (_twoStartVolume >= 0)
mus->setVolume((_twoStartVolume * 255) / 100);
@@ -178,8 +184,8 @@ bool ActionCrossfade::execute() {
// ActionCursor
//////////////////////////////////////////////////////////////////////////////
-ActionCursor::ActionCursor(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionCursor::ActionCursor(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
Common::String up = line;
up.toUppercase();
_action = 0;
@@ -210,10 +216,13 @@ bool ActionCursor::execute() {
// ActionDelayRender
//////////////////////////////////////////////////////////////////////////////
-ActionDelayRender::ActionDelayRender(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionDelayRender::ActionDelayRender(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_framesToDelay = 0;
sscanf(line.c_str(), "%u", &_framesToDelay);
+ // Limit to 10 frames maximum. This fixes the script bug in ZGI scene px10
+ // (outside Frobozz Electric building), where this is set to 100 (bug #6791).
+ _framesToDelay = MIN<uint32>(_framesToDelay, 10);
}
bool ActionDelayRender::execute() {
@@ -225,15 +234,15 @@ bool ActionDelayRender::execute() {
// ActionDisableControl
//////////////////////////////////////////////////////////////////////////////
-ActionDisableControl::ActionDisableControl(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionDisableControl::ActionDisableControl(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_key = 0;
sscanf(line.c_str(), "%u", &_key);
}
bool ActionDisableControl::execute() {
- _engine->getScriptManager()->setStateFlag(_key, Puzzle::DISABLED);
+ _scriptManager->setStateFlag(_key, Puzzle::DISABLED);
return true;
}
@@ -241,8 +250,8 @@ bool ActionDisableControl::execute() {
// ActionDisplayMessage
//////////////////////////////////////////////////////////////////////////////
-ActionDisplayMessage::ActionDisplayMessage(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionDisplayMessage::ActionDisplayMessage(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_control = 0;
_msgid = 0;
@@ -250,7 +259,7 @@ ActionDisplayMessage::ActionDisplayMessage(ZVision *engine, int32 slotkey, const
}
bool ActionDisplayMessage::execute() {
- Control *ctrl = _engine->getScriptManager()->getControl(_control);
+ Control *ctrl = _scriptManager->getControl(_control);
if (ctrl && ctrl->getType() == Control::CONTROL_TITLER) {
TitlerControl *titler = (TitlerControl *)ctrl;
titler->setString(_msgid);
@@ -276,8 +285,8 @@ bool ActionDissolve::execute() {
// ActionDistort - only used by Zork: Nemesis for the "treatment" puzzle in the Sanitarium (aj30)
//////////////////////////////////////////////////////////////////////////////
-ActionDistort::ActionDistort(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionDistort::ActionDistort(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_distSlot = 0;
_speed = 0;
_startAngle = 60.0;
@@ -289,14 +298,14 @@ ActionDistort::ActionDistort(ZVision *engine, int32 slotkey, const Common::Strin
}
ActionDistort::~ActionDistort() {
- _engine->getScriptManager()->killSideFx(_distSlot);
+ _scriptManager->killSideFx(_distSlot);
}
bool ActionDistort::execute() {
- if (_engine->getScriptManager()->getSideFX(_distSlot))
+ if (_scriptManager->getSideFX(_distSlot))
return true;
- _engine->getScriptManager()->addSideFX(new DistortNode(_engine, _distSlot, _speed, _startAngle, _endAngle, _startLineScale, _endLineScale));
+ _scriptManager->addSideFX(new DistortNode(_engine, _distSlot, _speed, _startAngle, _endAngle, _startLineScale, _endLineScale));
return true;
}
@@ -305,15 +314,15 @@ bool ActionDistort::execute() {
// ActionEnableControl
//////////////////////////////////////////////////////////////////////////////
-ActionEnableControl::ActionEnableControl(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionEnableControl::ActionEnableControl(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_key = 0;
sscanf(line.c_str(), "%u", &_key);
}
bool ActionEnableControl::execute() {
- _engine->getScriptManager()->unsetStateFlag(_key, Puzzle::DISABLED);
+ _scriptManager->unsetStateFlag(_key, Puzzle::DISABLED);
return true;
}
@@ -321,13 +330,13 @@ bool ActionEnableControl::execute() {
// ActionFlushMouseEvents
//////////////////////////////////////////////////////////////////////////////
-ActionFlushMouseEvents::ActionFlushMouseEvents(ZVision *engine, int32 slotkey) :
- ResultAction(engine, slotkey) {
+ActionFlushMouseEvents::ActionFlushMouseEvents(ZVision *engine, int32 slotKey) :
+ ResultAction(engine, slotKey) {
}
bool ActionFlushMouseEvents::execute() {
- _engine->getScriptManager()->flushEvent(Common::EVENT_LBUTTONUP);
- _engine->getScriptManager()->flushEvent(Common::EVENT_LBUTTONDOWN);
+ _scriptManager->flushEvent(Common::EVENT_LBUTTONUP);
+ _scriptManager->flushEvent(Common::EVENT_LBUTTONDOWN);
return true;
}
@@ -335,8 +344,8 @@ bool ActionFlushMouseEvents::execute() {
// ActionInventory
//////////////////////////////////////////////////////////////////////////////
-ActionInventory::ActionInventory(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionInventory::ActionInventory(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_type = -1;
_key = 0;
@@ -360,22 +369,22 @@ ActionInventory::ActionInventory(ZVision *engine, int32 slotkey, const Common::S
bool ActionInventory::execute() {
switch (_type) {
case 0: // add
- _engine->getScriptManager()->inventoryAdd(_key);
+ _scriptManager->inventoryAdd(_key);
break;
case 1: // addi
- _engine->getScriptManager()->inventoryAdd(_engine->getScriptManager()->getStateValue(_key));
+ _scriptManager->inventoryAdd(_scriptManager->getStateValue(_key));
break;
case 2: // drop
if (_key >= 0)
- _engine->getScriptManager()->inventoryDrop(_key);
+ _scriptManager->inventoryDrop(_key);
else
- _engine->getScriptManager()->inventoryDrop(_engine->getScriptManager()->getStateValue(StateKey_InventoryItem));
+ _scriptManager->inventoryDrop(_scriptManager->getStateValue(StateKey_InventoryItem));
break;
case 3: // dropi
- _engine->getScriptManager()->inventoryDrop(_engine->getScriptManager()->getStateValue(_key));
+ _scriptManager->inventoryDrop(_scriptManager->getStateValue(_key));
break;
case 4: // cycle
- _engine->getScriptManager()->inventoryCycle();
+ _scriptManager->inventoryCycle();
break;
default:
break;
@@ -387,8 +396,8 @@ bool ActionInventory::execute() {
// ActionKill - only used by ZGI
//////////////////////////////////////////////////////////////////////////////
-ActionKill::ActionKill(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionKill::ActionKill(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_key = 0;
_type = 0;
char keytype[25];
@@ -416,9 +425,9 @@ ActionKill::ActionKill(ZVision *engine, int32 slotkey, const Common::String &lin
bool ActionKill::execute() {
if (_type)
- _engine->getScriptManager()->killSideFxType((ScriptingEffect::ScriptingEffectType)_type);
+ _scriptManager->killSideFxType((ScriptingEffect::ScriptingEffectType)_type);
else
- _engine->getScriptManager()->killSideFx(_key);
+ _scriptManager->killSideFx(_key);
return true;
}
@@ -426,8 +435,8 @@ bool ActionKill::execute() {
// ActionMenuBarEnable
//////////////////////////////////////////////////////////////////////////////
-ActionMenuBarEnable::ActionMenuBarEnable(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionMenuBarEnable::ActionMenuBarEnable(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_menus = 0xFFFF;
sscanf(line.c_str(), "%hu", &_menus);
@@ -442,18 +451,20 @@ bool ActionMenuBarEnable::execute() {
// ActionMusic
//////////////////////////////////////////////////////////////////////////////
-ActionMusic::ActionMusic(ZVision *engine, int32 slotkey, const Common::String &line, bool global) :
- ResultAction(engine, slotkey),
- _volume(255),
+ActionMusic::ActionMusic(ZVision *engine, int32 slotKey, const Common::String &line, bool global) :
+ ResultAction(engine, slotKey),
_note(0),
_prog(0),
_universe(global) {
uint type = 0;
char fileNameBuffer[25];
uint loop = 0;
- uint volume = 255;
+ char volumeBuffer[15];
+
+ // Volume is optional. If it doesn't appear, assume full volume
+ strcpy(volumeBuffer, "100");
- sscanf(line.c_str(), "%u %24s %u %u", &type, fileNameBuffer, &loop, &volume);
+ sscanf(line.c_str(), "%u %24s %u %14s", &type, fileNameBuffer, &loop, volumeBuffer);
// Type 4 actions are MIDI commands, not files. These are only used by
// Zork: Nemesis, for the flute and piano puzzles (tj4e and ve6f, as well
@@ -462,39 +473,54 @@ ActionMusic::ActionMusic(ZVision *engine, int32 slotkey, const Common::String &l
_midi = true;
int note;
int prog;
- sscanf(line.c_str(), "%u %d %d %u", &type, &prog, &note, &volume);
- _volume = volume;
+ sscanf(line.c_str(), "%u %d %d %14s", &type, &prog, &note, volumeBuffer);
+ _volume = new ValueSlot(_scriptManager, volumeBuffer);
_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;
+ if (volumeBuffer[0] != '[' && atoi(volumeBuffer) > 100) {
+ // I thought I saw a case like this in Zork Nemesis, so
+ // let's guard against it.
+ warning("ActionMusic: Adjusting volume for %s from %s to 100", _fileName.c_str(), volumeBuffer);
+ strcpy(volumeBuffer, "100");
}
+ _volume = new ValueSlot(_scriptManager, volumeBuffer);
}
+
+ // WORKAROUND for a script bug in Zork Nemesis, rooms mq70/mq80.
+ // Fixes an edge case where the player goes to the dark room with the grue
+ // without holding a torch, and then quickly runs away before the grue's
+ // sound effect finishes. Fixes script bug #6794.
+ if (engine->getGameId() == GID_NEMESIS && _slotKey == 14822 && _scriptManager->getStateValue(_slotKey) == 2)
+ _scriptManager->setStateValue(_slotKey, 0);
+
}
ActionMusic::~ActionMusic() {
if (!_universe)
- _engine->getScriptManager()->killSideFx(_slotKey);
+ _scriptManager->killSideFx(_slotKey);
+ delete _volume;
}
bool ActionMusic::execute() {
- if (_engine->getScriptManager()->getSideFX(_slotKey))
- return true;
+ if (_scriptManager->getSideFX(_slotKey)) {
+ _scriptManager->killSideFx(_slotKey);
+ _scriptManager->setStateValue(_slotKey, 2);
+ }
+
+ uint volume = _volume->getValue();
if (_midi) {
- _engine->getScriptManager()->addSideFX(new MusicMidiNode(_engine, _slotKey, _prog, _note, _volume));
+ _scriptManager->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));
+ // Volume in the script files is mapped to [0, 100], but the ScummVM mixer uses [0, 255]
+ _scriptManager->addSideFX(new MusicNode(_engine, _slotKey, _fileName, _loop, volume * 255 / 100));
}
return true;
@@ -504,8 +530,8 @@ bool ActionMusic::execute() {
// ActionPanTrack
//////////////////////////////////////////////////////////////////////////////
-ActionPanTrack::ActionPanTrack(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey),
+ActionPanTrack::ActionPanTrack(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey),
_pos(0),
_musicSlot(0) {
@@ -513,14 +539,14 @@ ActionPanTrack::ActionPanTrack(ZVision *engine, int32 slotkey, const Common::Str
}
ActionPanTrack::~ActionPanTrack() {
- _engine->getScriptManager()->killSideFx(_slotKey);
+ _scriptManager->killSideFx(_slotKey);
}
bool ActionPanTrack::execute() {
- if (_engine->getScriptManager()->getSideFX(_slotKey))
+ if (_scriptManager->getSideFX(_slotKey))
return true;
- _engine->getScriptManager()->addSideFX(new PanTrackNode(_engine, _slotKey, _musicSlot, _pos));
+ _scriptManager->addSideFX(new PanTrackNode(_engine, _slotKey, _musicSlot, _pos));
return true;
}
@@ -529,8 +555,8 @@ bool ActionPanTrack::execute() {
// ActionPreferences
//////////////////////////////////////////////////////////////////////////////
-ActionPreferences::ActionPreferences(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionPreferences::ActionPreferences(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
if (line.compareToIgnoreCase("save") == 0)
_save = true;
else
@@ -550,8 +576,8 @@ bool ActionPreferences::execute() {
// ActionPreloadAnimation
//////////////////////////////////////////////////////////////////////////////
-ActionPreloadAnimation::ActionPreloadAnimation(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionPreloadAnimation::ActionPreloadAnimation(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_mask = 0;
_framerate = 0;
@@ -570,18 +596,18 @@ ActionPreloadAnimation::ActionPreloadAnimation(ZVision *engine, int32 slotkey, c
}
ActionPreloadAnimation::~ActionPreloadAnimation() {
- _engine->getScriptManager()->deleteSideFx(_slotKey);
+ _scriptManager->deleteSideFx(_slotKey);
}
bool ActionPreloadAnimation::execute() {
- AnimationEffect *nod = (AnimationEffect *)_engine->getScriptManager()->getSideFX(_slotKey);
+ AnimationEffect *nod = (AnimationEffect *)_scriptManager->getSideFX(_slotKey);
if (!nod) {
nod = new AnimationEffect(_engine, _slotKey, _fileName, _mask, _framerate, false);
- _engine->getScriptManager()->addSideFX(nod);
+ _scriptManager->addSideFX(nod);
} else
nod->stop();
- _engine->getScriptManager()->setStateValue(_slotKey, 2);
+ _scriptManager->setStateValue(_slotKey, 2);
return true;
}
@@ -589,18 +615,18 @@ bool ActionPreloadAnimation::execute() {
// ActionUnloadAnimation
//////////////////////////////////////////////////////////////////////////////
-ActionUnloadAnimation::ActionUnloadAnimation(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionUnloadAnimation::ActionUnloadAnimation(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_key = 0;
sscanf(line.c_str(), "%u", &_key);
}
bool ActionUnloadAnimation::execute() {
- AnimationEffect *nod = (AnimationEffect *)_engine->getScriptManager()->getSideFX(_key);
+ AnimationEffect *nod = (AnimationEffect *)_scriptManager->getSideFX(_key);
if (nod && nod->getType() == ScriptingEffect::SCRIPTING_EFFECT_ANIM)
- _engine->getScriptManager()->deleteSideFx(_key);
+ _scriptManager->deleteSideFx(_key);
return true;
}
@@ -609,8 +635,8 @@ bool ActionUnloadAnimation::execute() {
// ActionPlayAnimation
//////////////////////////////////////////////////////////////////////////////
-ActionPlayAnimation::ActionPlayAnimation(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionPlayAnimation::ActionPlayAnimation(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_x = 0;
_y = 0;
_x2 = 0;
@@ -635,18 +661,25 @@ ActionPlayAnimation::ActionPlayAnimation(ZVision *engine, int32 slotkey, const C
_mask = -1;
_fileName = Common::String(fileName);
+
+ // WORKAROUND for bug #6769, location me1g.scr (the "Alchemical debacle"
+ // video in ZGI). We only scale up by 2x, in AnimationEffect::process(),
+ // but the dimensions of the target frame are off by 2 pixels. We fix that
+ // here, so that the video can be scaled.
+ if (_fileName == "me1ga011.avi" && _y2 == 213)
+ _y2 = 215;
}
ActionPlayAnimation::~ActionPlayAnimation() {
- _engine->getScriptManager()->deleteSideFx(_slotKey);
+ _scriptManager->deleteSideFx(_slotKey);
}
bool ActionPlayAnimation::execute() {
- AnimationEffect *nod = (AnimationEffect *)_engine->getScriptManager()->getSideFX(_slotKey);
+ AnimationEffect *nod = (AnimationEffect *)_scriptManager->getSideFX(_slotKey);
if (!nod) {
nod = new AnimationEffect(_engine, _slotKey, _fileName, _mask, _framerate);
- _engine->getScriptManager()->addSideFX(nod);
+ _scriptManager->addSideFX(nod);
} else
nod->stop();
@@ -660,8 +693,8 @@ bool ActionPlayAnimation::execute() {
// ActionPlayPreloadAnimation
//////////////////////////////////////////////////////////////////////////////
-ActionPlayPreloadAnimation::ActionPlayPreloadAnimation(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionPlayPreloadAnimation::ActionPlayPreloadAnimation(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_controlKey = 0;
_x1 = 0;
_y1 = 0;
@@ -677,7 +710,7 @@ ActionPlayPreloadAnimation::ActionPlayPreloadAnimation(ZVision *engine, int32 sl
}
bool ActionPlayPreloadAnimation::execute() {
- AnimationEffect *nod = (AnimationEffect *)_engine->getScriptManager()->getSideFX(_controlKey);
+ AnimationEffect *nod = (AnimationEffect *)_scriptManager->getSideFX(_controlKey);
if (nod)
nod->addPlayNode(_slotKey, _x1, _y1, _x2, _y2, _startFrame, _endFrame, _loopCount);
@@ -699,8 +732,8 @@ bool ActionQuit::execute() {
// ActionRegion - only used by Zork: Nemesis
//////////////////////////////////////////////////////////////////////////////
-ActionRegion::ActionRegion(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionRegion::ActionRegion(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_delay = 0;
_type = 0;
_unk1 = 0;
@@ -718,11 +751,11 @@ ActionRegion::ActionRegion(ZVision *engine, int32 slotkey, const Common::String
}
ActionRegion::~ActionRegion() {
- _engine->getScriptManager()->killSideFx(_slotKey);
+ _scriptManager->killSideFx(_slotKey);
}
bool ActionRegion::execute() {
- if (_engine->getScriptManager()->getSideFX(_slotKey))
+ if (_scriptManager->getSideFX(_slotKey))
return true;
GraphicsEffect *effect = NULL;
@@ -767,7 +800,7 @@ bool ActionRegion::execute() {
}
if (effect) {
- _engine->getScriptManager()->addSideFX(new RegionNode(_engine, _slotKey, effect, _delay));
+ _scriptManager->addSideFX(new RegionNode(_engine, _slotKey, effect, _delay));
_engine->getRenderManager()->addEffect(effect);
}
@@ -778,31 +811,46 @@ bool ActionRegion::execute() {
// ActionRandom
//////////////////////////////////////////////////////////////////////////////
-ActionRandom::ActionRandom(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+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);
+ _max = new ValueSlot(_scriptManager, maxBuffer);
}
ActionRandom::~ActionRandom() {
- if (_max)
- delete _max;
+ delete _max;
}
bool ActionRandom::execute() {
uint randNumber = _engine->getRandomSource()->getRandomNumber(_max->getValue());
- _engine->getScriptManager()->setStateValue(_slotKey, randNumber);
+ _scriptManager->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(-1);
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
// ActionRotateTo
//////////////////////////////////////////////////////////////////////////////
-ActionRotateTo::ActionRotateTo(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionRotateTo::ActionRotateTo(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_time = 0;
_toPos = 0;
@@ -819,8 +867,8 @@ bool ActionRotateTo::execute() {
// ActionSetPartialScreen
//////////////////////////////////////////////////////////////////////////////
-ActionSetPartialScreen::ActionSetPartialScreen(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionSetPartialScreen::ActionSetPartialScreen(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_x = 0;
_y = 0;
@@ -859,8 +907,8 @@ bool ActionSetPartialScreen::execute() {
// ActionSetScreen
//////////////////////////////////////////////////////////////////////////////
-ActionSetScreen::ActionSetScreen(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionSetScreen::ActionSetScreen(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
char fileName[25];
sscanf(line.c_str(), "%24s", fileName);
@@ -877,14 +925,14 @@ bool ActionSetScreen::execute() {
// ActionStop
//////////////////////////////////////////////////////////////////////////////
-ActionStop::ActionStop(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+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);
+ _scriptManager->stopSideFx(_key);
return true;
}
@@ -892,8 +940,8 @@ bool ActionStop::execute() {
// ActionStreamVideo
//////////////////////////////////////////////////////////////////////////////
-ActionStreamVideo::ActionStreamVideo(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionStreamVideo::ActionStreamVideo(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_x1 = 0;
_x2 = 0;
_y1 = 0;
@@ -912,7 +960,15 @@ ActionStreamVideo::ActionStreamVideo(ZVision *engine, int32 slotkey, const Commo
bool ActionStreamVideo::execute() {
Video::VideoDecoder *decoder;
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);
+ bool subtitleExists = _engine->getSearchManager()->hasFile(subname);
+ bool switchToHires = false;
+// NOTE: We only show the hires MPEG2 videos when libmpeg2 is compiled in,
+// otherwise we fall back to the lowres ones
#ifdef USE_MPEG2
Common::String hiresFileName = _fileName;
hiresFileName.setChar('d', hiresFileName.size() - 8);
@@ -920,36 +976,44 @@ bool ActionStreamVideo::execute() {
hiresFileName.setChar('o', hiresFileName.size() - 2);
hiresFileName.setChar('b', hiresFileName.size() - 1);
- if (_engine->getScriptManager()->getStateValue(StateKey_MPEGMovies) == 1 &&_engine->getSearchManager()->hasFile(hiresFileName))
- // TODO: Enable once VOB + AC3 support is implemented
- //_fileName = hiresFileName;
+ if (_scriptManager->getStateValue(StateKey_MPEGMovies) == 1 &&_engine->getSearchManager()->hasFile(hiresFileName)) {
+ // TODO: Enable once AC3 support is implemented
+ if (!_engine->getSearchManager()->hasFile(_fileName)) // Check for the regular video
+ return true;
warning("The hires videos of the DVD version of ZGI aren't supported yet, using lowres");
-#endif
-
- Common::String subname = _fileName;
- subname.setChar('s', subname.size() - 3);
- subname.setChar('u', subname.size() - 2);
- subname.setChar('b', subname.size() - 1);
-
+ //_fileName = hiresFileName;
+ //switchToHires = true;
+ } else if (!_engine->getSearchManager()->hasFile(_fileName))
+ return true;
+#else
if (!_engine->getSearchManager()->hasFile(_fileName))
return true;
+#endif
decoder = _engine->loadAnimation(_fileName);
+ Subtitle *sub = (subtitleExists) ? new Subtitle(_engine, subname, switchToHires) : NULL;
_engine->getCursorManager()->showMouse(false);
- Subtitle *sub = NULL;
-
- if (_engine->getSearchManager()->hasFile(subname))
- sub = new Subtitle(_engine, subname);
+ if (switchToHires) {
+ _engine->initHiresScreen();
+ destRect = Common::Rect(40, -40, 760, 440);
+ Common::Rect workingWindow = _engine->_workingWindow;
+ workingWindow.translate(0, -40);
+ _engine->getRenderManager()->initSubArea(HIRES_WINDOW_WIDTH, HIRES_WINDOW_HEIGHT, workingWindow);
+ }
_engine->playVideo(*decoder, destRect, _skippable, sub);
- delete decoder;
+
+ if (switchToHires) {
+ _engine->initScreen();
+ _engine->getRenderManager()->initSubArea(WINDOW_WIDTH, WINDOW_HEIGHT, _engine->_workingWindow);
+ }
_engine->getCursorManager()->showMouse(true);
- if (sub)
- delete sub;
+ delete decoder;
+ delete sub;
return true;
}
@@ -958,8 +1022,8 @@ bool ActionStreamVideo::execute() {
// ActionSyncSound
//////////////////////////////////////////////////////////////////////////////
-ActionSyncSound::ActionSyncSound(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionSyncSound::ActionSyncSound(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_syncto = 0;
char fileName[25];
@@ -971,14 +1035,14 @@ ActionSyncSound::ActionSyncSound(ZVision *engine, int32 slotkey, const Common::S
}
bool ActionSyncSound::execute() {
- ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_syncto);
+ ScriptingEffect *fx = _scriptManager->getSideFX(_syncto);
if (!fx)
return true;
if (!(fx->getType() & ScriptingEffect::SCRIPTING_EFFECT_ANIM))
return true;
- _engine->getScriptManager()->addSideFX(new SyncSoundNode(_engine, _slotKey, _fileName, _syncto));
+ _scriptManager->addSideFX(new SyncSoundNode(_engine, _slotKey, _fileName, _syncto));
return true;
}
@@ -986,24 +1050,23 @@ bool ActionSyncSound::execute() {
// ActionTimer
//////////////////////////////////////////////////////////////////////////////
-ActionTimer::ActionTimer(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+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);
+ _time = new ValueSlot(_scriptManager, timeBuffer);
}
ActionTimer::~ActionTimer() {
- if (_time)
- delete _time;
- _engine->getScriptManager()->killSideFx(_slotKey);
+ delete _time;
+ _scriptManager->killSideFx(_slotKey);
}
bool ActionTimer::execute() {
- if (_engine->getScriptManager()->getSideFX(_slotKey))
+ if (_scriptManager->getSideFX(_slotKey))
return true;
- _engine->getScriptManager()->addSideFX(new TimerNode(_engine, _slotKey, _time->getValue()));
+ _scriptManager->addSideFX(new TimerNode(_engine, _slotKey, _time->getValue()));
return true;
}
@@ -1011,25 +1074,25 @@ bool ActionTimer::execute() {
// ActionTtyText
//////////////////////////////////////////////////////////////////////////////
-ActionTtyText::ActionTtyText(ZVision *engine, int32 slotkey, const Common::String &line) :
- ResultAction(engine, slotkey) {
+ActionTtyText::ActionTtyText(ZVision *engine, int32 slotKey, const Common::String &line) :
+ ResultAction(engine, slotKey) {
_delay = 0;
char filename[64];
int32 x1 = 0, y1 = 0, x2 = 0, y2 = 0;
- sscanf(line.c_str(), "%d %d %d %d %64s %u", &x1, &y1, &x2, &y2, filename, &_delay);
+ sscanf(line.c_str(), "%d %d %d %d %63s %u", &x1, &y1, &x2, &y2, filename, &_delay);
_r = Common::Rect(x1, y1, x2, y2);
_filename = Common::String(filename);
}
ActionTtyText::~ActionTtyText() {
- _engine->getScriptManager()->killSideFx(_slotKey);
+ _scriptManager->killSideFx(_slotKey);
}
bool ActionTtyText::execute() {
- if (_engine->getScriptManager()->getSideFX(_slotKey))
+ if (_scriptManager->getSideFX(_slotKey))
return true;
- _engine->getScriptManager()->addSideFX(new ttyTextNode(_engine, _slotKey, _filename, _r, _delay));
+ _scriptManager->addSideFX(new ttyTextNode(_engine, _slotKey, _filename, _r, _delay));
return true;
}
diff --git a/engines/zvision/scripting/actions.h b/engines/zvision/scripting/actions.h
index c2350bc83a..bde1baa291 100644
--- a/engines/zvision/scripting/actions.h
+++ b/engines/zvision/scripting/actions.h
@@ -32,6 +32,7 @@ namespace ZVision {
// Forward declaration of ZVision. This file is included before ZVision is declared
class ZVision;
+class ScriptManager;
class ValueSlot;
/**
@@ -40,7 +41,7 @@ class ValueSlot;
*/
class ResultAction {
public:
- ResultAction(ZVision *engine, int32 slotkey) : _engine(engine), _slotKey(slotkey) {}
+ ResultAction(ZVision *engine, int32 slotkey);
virtual ~ResultAction() {}
/**
* This is called by the script system whenever a Puzzle's criteria are found to be true.
@@ -53,6 +54,7 @@ public:
virtual bool execute() = 0;
protected:
ZVision *_engine;
+ ScriptManager *_scriptManager;
int32 _slotKey;
};
@@ -224,7 +226,7 @@ public:
private:
Common::String _fileName;
bool _loop;
- byte _volume;
+ ValueSlot *_volume;
bool _universe;
bool _midi;
int8 _note;
@@ -267,7 +269,6 @@ public:
bool execute();
private:
- uint32 _animationKey;
uint32 _controlKey;
uint32 _x1;
uint32 _y1;
@@ -340,6 +341,15 @@ private:
ValueSlot *_max;
};
+class ActionRestoreGame : public ResultAction {
+public:
+ ActionRestoreGame(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
+
+private:
+ Common::String _fileName;
+};
+
class ActionRotateTo : public ResultAction {
public:
ActionRotateTo(ZVision *engine, int32 slotkey, const Common::String &line);
diff --git a/engines/zvision/scripting/controls/fist_control.cpp b/engines/zvision/scripting/controls/fist_control.cpp
index 4a8e8b1bbd..f79c82dc79 100644
--- a/engines/zvision/scripting/controls/fist_control.cpp
+++ b/engines/zvision/scripting/controls/fist_control.cpp
@@ -105,7 +105,12 @@ bool FistControl::process(uint32 deltaTimeInMillis) {
if (_animation->needsUpdate()) {
const Graphics::Surface *frameData = _animation->decodeNextFrame();
if (frameData)
- _engine->getRenderManager()->blitSurfaceToBkgScaled(*frameData, _anmRect);
+ // WORKAROUND: Ignore the target frame dimensions for the finger animations.
+ // The target dimensions specify an area smaller than expected, thus if we
+ // scale the finger videos to fit these dimensions, they are not aligned
+ // correctly. Not scaling these videos yields a result identical to the
+ // original. Fixes bug #6784.
+ _engine->getRenderManager()->blitSurfaceToBkg(*frameData, _anmRect.left, _anmRect.top);
}
}
diff --git a/engines/zvision/scripting/controls/input_control.cpp b/engines/zvision/scripting/controls/input_control.cpp
index 47da27fa08..9525333ef0 100644
--- a/engines/zvision/scripting/controls/input_control.cpp
+++ b/engines/zvision/scripting/controls/input_control.cpp
@@ -39,10 +39,10 @@ namespace ZVision {
InputControl::InputControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
: Control(engine, key, CONTROL_INPUT),
+ _background(0),
_nextTabstop(0),
_focused(false),
_textChanged(false),
- _cursorOffset(0),
_enterPressed(false),
_readOnly(false),
_txtWidth(0),
@@ -78,13 +78,13 @@ InputControl::InputControl(ZVision *engine, uint32 key, Common::SeekableReadStre
sscanf(values.c_str(), "%u", &fontFormatNumber);
- _stringInit.readAllStyle(_engine->getStringManager()->getTextLine(fontFormatNumber));
+ _stringInit.readAllStyles(_engine->getStringManager()->getTextLine(fontFormatNumber));
} else if (param.matchString("chooser_init_string", true)) {
uint fontFormatNumber;
sscanf(values.c_str(), "%u", &fontFormatNumber);
- _stringChooserInit.readAllStyle(_engine->getStringManager()->getTextLine(fontFormatNumber));
+ _stringChooserInit.readAllStyles(_engine->getStringManager()->getTextLine(fontFormatNumber));
} else if (param.matchString("next_tabstop", true)) {
sscanf(values.c_str(), "%u", &_nextTabstop);
} else if (param.matchString("cursor_dimensions", true)) {
@@ -109,6 +109,15 @@ InputControl::InputControl(ZVision *engine, uint32 key, Common::SeekableReadStre
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
getParams(line, param, values);
}
+
+ _maxTxtWidth = _textRectangle.width();
+ if (_animation)
+ _maxTxtWidth -= _animation->getWidth();
+}
+
+InputControl::~InputControl() {
+ _background->free();
+ delete _background;
}
bool InputControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
@@ -191,19 +200,31 @@ bool InputControl::process(uint32 deltaTimeInMillis) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
+ if (!_background) {
+ _background = _engine->getRenderManager()->getBkgRect(_textRectangle);
+ }
+
// First see if we need to render the text
if (_textChanged) {
// Blit the text using the RenderManager
Graphics::Surface txt;
- txt.create(_textRectangle.width(), _textRectangle.height(), _engine->_resourcePixelFormat);
+ txt.copyFrom(*_background);
+
+ int32 oldTxtWidth = _txtWidth;
if (!_readOnly || !_focused)
- _txtWidth = _engine->getTextRenderer()->drawTxt(_currentInputText, _stringInit, txt);
+ _txtWidth = _engine->getTextRenderer()->drawText(_currentInputText, _stringInit, txt);
else
- _txtWidth = _engine->getTextRenderer()->drawTxt(_currentInputText, _stringChooserInit, txt);
+ _txtWidth = _engine->getTextRenderer()->drawText(_currentInputText, _stringChooserInit, txt);
- _engine->getRenderManager()->blitSurfaceToBkg(txt, _textRectangle.left, _textRectangle.top);
+ if (_readOnly || _txtWidth <= _maxTxtWidth)
+ _engine->getRenderManager()->blitSurfaceToBkg(txt, _textRectangle.left, _textRectangle.top);
+ else {
+ // Assume the last character caused the overflow.
+ _currentInputText.deleteLastChar();
+ _txtWidth = oldTxtWidth;
+ }
txt.free();
}
diff --git a/engines/zvision/scripting/controls/input_control.h b/engines/zvision/scripting/controls/input_control.h
index 99f7f5287d..6abdb3c692 100644
--- a/engines/zvision/scripting/controls/input_control.h
+++ b/engines/zvision/scripting/controls/input_control.h
@@ -38,25 +38,25 @@ namespace ZVision {
class InputControl : public Control {
public:
InputControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
+ ~InputControl();
private:
+ Graphics::Surface *_background;
Common::Rect _textRectangle;
Common::Rect _headerRectangle;
- cTxtStyle _stringInit;
- cTxtStyle _stringChooserInit;
+ TextStyleState _stringInit;
+ TextStyleState _stringChooserInit;
uint32 _nextTabstop;
bool _focused;
Common::String _currentInputText;
bool _textChanged;
- uint _cursorOffset;
bool _enterPressed;
bool _readOnly;
int16 _txtWidth;
+ int16 _maxTxtWidth;
Video::VideoDecoder *_animation;
- int32 _frameDelay;
- int16 _frame;
public:
void focus() {
diff --git a/engines/zvision/scripting/controls/lever_control.cpp b/engines/zvision/scripting/controls/lever_control.cpp
index bef51f0e91..0f105b424c 100644
--- a/engines/zvision/scripting/controls/lever_control.cpp
+++ b/engines/zvision/scripting/controls/lever_control.cpp
@@ -232,10 +232,13 @@ bool LeverControl::onMouseMove(const Common::Point &screenSpacePos, const Common
if (angle >= (int)iter->angle - ANGLE_DELTA && angle <= (int)iter->angle + ANGLE_DELTA) {
_currentFrame = iter->toFrame;
renderFrame(_currentFrame);
+ _engine->getScriptManager()->setStateValue(_key, _currentFrame);
break;
}
}
}
+ _engine->getCursorManager()->changeCursor(_cursor);
+ cursorWasChanged = true;
} else if (_frameInfo[_currentFrame].hotspot.contains(backgroundImageSpacePos)) {
_engine->getCursorManager()->changeCursor(_cursor);
cursorWasChanged = true;
diff --git a/engines/zvision/scripting/controls/safe_control.cpp b/engines/zvision/scripting/controls/safe_control.cpp
index 6ba34106d0..4d2a91a1ad 100644
--- a/engines/zvision/scripting/controls/safe_control.cpp
+++ b/engines/zvision/scripting/controls/safe_control.cpp
@@ -123,6 +123,8 @@ bool SafeControl::process(uint32 deltaTimeInMillis) {
_animation->seekToFrame(_animation->getCurFrame() - 1);
const Graphics::Surface *frameData = _animation->decodeNextFrame();
+ if (_animation->getCurFrame() == _targetFrame)
+ _engine->getScriptManager()->setStateValue(_key, _curState);
if (frameData)
_engine->getRenderManager()->blitSurfaceToBkg(*frameData, _rectangle.left, _rectangle.top);
}
@@ -169,8 +171,6 @@ bool SafeControl::onMouseUp(const Common::Point &screenSpacePos, const Common::P
_curState = (_statesCount * 2 + tmp2) % _statesCount;
_targetFrame = (_curState + _statesCount - _startPointer) % _statesCount;
-
- _engine->getScriptManager()->setStateValue(_key, _curState);
return true;
}
}
diff --git a/engines/zvision/scripting/controls/titler_control.cpp b/engines/zvision/scripting/controls/titler_control.cpp
index 542e0a0b67..683d6660af 100644
--- a/engines/zvision/scripting/controls/titler_control.cpp
+++ b/engines/zvision/scripting/controls/titler_control.cpp
@@ -82,7 +82,7 @@ TitlerControl::~TitlerControl() {
void TitlerControl::setString(int strLine) {
if (strLine != _curString && strLine >= 0 && strLine < (int)_strings.size()) {
_surface->fillRect(Common::Rect(_surface->w, _surface->h), 0);
- _engine->getTextRenderer()->drawTxtInOneLine(_strings[strLine], *_surface);
+ _engine->getTextRenderer()->drawTextWithWordWrapping(_strings[strLine], *_surface);
_engine->getRenderManager()->blitSurfaceToBkg(*_surface, _rectangle.left, _rectangle.top);
_curString = strLine;
}
diff --git a/engines/zvision/scripting/effects/distort_effect.cpp b/engines/zvision/scripting/effects/distort_effect.cpp
index 78c4a1b9a8..113b5d048d 100644
--- a/engines/zvision/scripting/effects/distort_effect.cpp
+++ b/engines/zvision/scripting/effects/distort_effect.cpp
@@ -52,7 +52,7 @@ DistortNode::DistortNode(ZVision *engine, uint32 key, int16 speed, float startAn
_diffLinScale = endLineScale - startLineScale;
_frmSpeed = (float)speed / 15.0;
- _frames = ceil((5.0 - _frmSpeed * 2.0) / _frmSpeed);
+ _frames = (int)ceil((5.0 - _frmSpeed * 2.0) / _frmSpeed);
if (_frames <= 0)
_frames = 1;
diff --git a/engines/zvision/scripting/effects/music_effect.cpp b/engines/zvision/scripting/effects/music_effect.cpp
index 102f330305..e3fdc96dba 100644
--- a/engines/zvision/scripting/effects/music_effect.cpp
+++ b/engines/zvision/scripting/effects/music_effect.cpp
@@ -36,16 +36,33 @@
namespace ZVision {
-MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool loop, int8 volume)
+static const uint8 dbMapLinear[256] =
+{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
+2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
+4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
+8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14,
+14, 15, 15, 16, 16, 17, 18, 18, 19, 20, 21, 21, 22, 23, 24, 25,
+26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 40, 41, 43, 45,
+46, 48, 50, 52, 53, 55, 57, 60, 62, 64, 67, 69, 72, 74, 77, 80,
+83, 86, 89, 92, 96, 99, 103, 107, 111, 115, 119, 123, 128, 133, 137, 143,
+148, 153, 159, 165, 171, 177, 184, 191, 198, 205, 212, 220, 228, 237, 245, 255};
+
+MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool loop, uint8 volume)
: MusicNodeBASE(engine, key, SCRIPTING_EFFECT_AUDIO) {
_loop = loop;
_volume = volume;
+ _deltaVolume = 0;
+ _balance = 0;
_crossfade = false;
_crossfadeTarget = 0;
_crossfadeTime = 0;
- _attenuate = 0;
- _pantrack = false;
- _pantrackPosition = 0;
_sub = NULL;
_stereo = false;
_loaded = false;
@@ -66,9 +83,9 @@ MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool
if (_loop) {
Audio::LoopingAudioStream *loopingAudioStream = new Audio::LoopingAudioStream(audioStream, 0, DisposeAfterUse::YES);
- _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, loopingAudioStream, -1, _volume);
+ _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, loopingAudioStream, -1, dbMapLinear[_volume]);
} else {
- _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, audioStream, -1, _volume);
+ _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, audioStream, -1, dbMapLinear[_volume]);
}
if (_key != StateKey_NotSet)
@@ -94,20 +111,17 @@ MusicNode::~MusicNode() {
_engine->getScriptManager()->setStateValue(_key, 2);
if (_sub)
delete _sub;
- debug(1, "MusicNode: %d destroyed\n", _key);
+ debug(1, "MusicNode: %d destroyed", _key);
}
-void MusicNode::setPanTrack(int16 pos) {
- if (!_stereo) {
- _pantrack = true;
- _pantrackPosition = pos;
- setVolume(_volume);
- }
+void MusicNode::setDeltaVolume(uint8 volume) {
+ _deltaVolume = volume;
+ setVolume(_volume);
}
-void MusicNode::unsetPanTrack() {
- _pantrack = false;
- setVolume(_volume);
+void MusicNode::setBalance(int8 balance) {
+ _balance = balance;
+ _engine->_mixer->setChannelBalance(_handle, _balance);
}
void MusicNode::setFade(int32 time, uint8 target) {
@@ -126,7 +140,7 @@ bool MusicNode::process(uint32 deltaTimeInMillis) {
if (_crossfadeTime > 0) {
if ((int32)deltaTimeInMillis > _crossfadeTime)
deltaTimeInMillis = _crossfadeTime;
- _newvol += floor(((float)(_crossfadeTarget - _newvol) / (float)_crossfadeTime)) * (float)deltaTimeInMillis;
+ _newvol += (int)(floor(((float)(_crossfadeTarget - _newvol) / (float)_crossfadeTime)) * (float)deltaTimeInMillis);
_crossfadeTime -= deltaTimeInMillis;
} else {
_crossfade = false;
@@ -134,7 +148,7 @@ bool MusicNode::process(uint32 deltaTimeInMillis) {
}
}
- if (_pantrack || _volume != _newvol)
+ if (_volume != _newvol)
setVolume(_newvol);
if (_sub && _engine->getScriptManager()->getStateValue(StateKey_Subtitles) == 1)
@@ -146,55 +160,85 @@ bool MusicNode::process(uint32 deltaTimeInMillis) {
void MusicNode::setVolume(uint8 newVolume) {
if (!_loaded)
return;
- if (_pantrack) {
- int curX = _engine->getScriptManager()->getStateValue(StateKey_ViewPos);
- curX -= _pantrackPosition;
- int32 _width = _engine->getRenderManager()->getBkgSize().x;
- if (curX < (-_width) / 2)
- curX += _width;
- else if (curX >= _width / 2)
- curX -= _width;
-
- float norm = (float)curX / ((float)_width / 2.0);
- float lvl = fabs(norm);
- if (lvl > 0.5)
- lvl = (lvl - 0.5) * 1.7;
- else
- lvl = 1.0;
- float bal = sin(-norm * 3.1415926) * 127.0;
+ _volume = newVolume;
- if (_engine->_mixer->isSoundHandleActive(_handle)) {
- _engine->_mixer->setChannelBalance(_handle, bal);
- _engine->_mixer->setChannelVolume(_handle, newVolume * lvl);
- }
- } else {
- if (_engine->_mixer->isSoundHandleActive(_handle)) {
- _engine->_mixer->setChannelBalance(_handle, 0);
- _engine->_mixer->setChannelVolume(_handle, newVolume);
- }
- }
+ if (_deltaVolume >= _volume)
+ _engine->_mixer->setChannelVolume(_handle, 0);
+ else
+ _engine->_mixer->setChannelVolume(_handle, dbMapLinear[_volume - _deltaVolume]);
+}
- _volume = newVolume;
+uint8 MusicNode::getVolume() {
+ return _volume;
}
PanTrackNode::PanTrackNode(ZVision *engine, uint32 key, uint32 slot, int16 pos)
: ScriptingEffect(engine, key, SCRIPTING_EFFECT_PANTRACK) {
_slot = slot;
+ _position = pos;
- ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(slot);
- if (fx && fx->getType() == SCRIPTING_EFFECT_AUDIO) {
- MusicNodeBASE *mus = (MusicNodeBASE *)fx;
- mus->setPanTrack(pos);
- }
+ // Try to set pan value for music node immediately
+ process(0);
}
PanTrackNode::~PanTrackNode() {
- ScriptingEffect *fx = _engine->getScriptManager()->getSideFX(_slot);
+}
+
+bool PanTrackNode::process(uint32 deltaTimeInMillis) {
+ ScriptManager * scriptManager = _engine->getScriptManager();
+ ScriptingEffect *fx = scriptManager->getSideFX(_slot);
if (fx && fx->getType() == SCRIPTING_EFFECT_AUDIO) {
MusicNodeBASE *mus = (MusicNodeBASE *)fx;
- mus->unsetPanTrack();
+
+ int curPos = scriptManager->getStateValue(StateKey_ViewPos);
+ int16 _width = _engine->getRenderManager()->getBkgSize().x;
+ int16 _halfWidth = _width / 2;
+ int16 _quarterWidth = _width / 4;
+
+ int tmp = 0;
+ if (curPos <= _position)
+ tmp = _position - curPos;
+ else
+ tmp = _position - curPos + _width;
+
+ int balance = 0;
+
+ if (tmp > _halfWidth)
+ tmp -= _width;
+
+ if (tmp > _quarterWidth) {
+ balance = 1;
+ tmp = _halfWidth - tmp;
+ } else if (tmp < -_quarterWidth) {
+ balance = -1;
+ tmp = -_halfWidth - tmp;
+ }
+
+ // Originally it's value -90...90 but we use -127...127 and therefore 360 replaced by 508
+ mus->setBalance( (508 * tmp) / _width );
+
+ tmp = (360 * tmp) / _width;
+
+ int deltaVol = balance;
+
+ // This value sets how fast volume goes off than sound source back of you
+ // By this value we can hack some "bugs" have place in originall game engine like beat sound in ZGI-dc10
+ int volumeCorrection = 2;
+
+ if (_engine->getGameId() == GID_GRANDINQUISITOR) {
+ if (scriptManager->getCurrentLocation() == "dc10")
+ volumeCorrection = 5;
+ }
+
+ if (deltaVol != 0)
+ deltaVol = (mus->getVolume() * volumeCorrection) * (90 - tmp * balance) / 90;
+ if (deltaVol > 255)
+ deltaVol = 255;
+
+ mus->setDeltaVolume(deltaVol);
}
+ return false;
}
MusicMidiNode::MusicMidiNode(ZVision *engine, uint32 key, int8 program, int8 note, int8 volume)
@@ -225,10 +269,10 @@ MusicMidiNode::~MusicMidiNode() {
_engine->getScriptManager()->setStateValue(_key, 2);
}
-void MusicMidiNode::setPanTrack(int16 pos) {
+void MusicMidiNode::setDeltaVolume(uint8 volume) {
}
-void MusicMidiNode::unsetPanTrack() {
+void MusicMidiNode::setBalance(int8 balance) {
}
void MusicMidiNode::setFade(int32 time, uint8 target) {
@@ -245,4 +289,8 @@ void MusicMidiNode::setVolume(uint8 newVolume) {
_volume = newVolume;
}
+uint8 MusicMidiNode::getVolume() {
+ return _volume;
+}
+
} // End of namespace ZVision
diff --git a/engines/zvision/scripting/effects/music_effect.h b/engines/zvision/scripting/effects/music_effect.h
index 31d538f668..7657be8e09 100644
--- a/engines/zvision/scripting/effects/music_effect.h
+++ b/engines/zvision/scripting/effects/music_effect.h
@@ -48,16 +48,16 @@ public:
virtual bool process(uint32 deltaTimeInMillis) = 0;
virtual void setVolume(uint8 volume) = 0;
-
- virtual void setPanTrack(int16 pos) = 0;
- virtual void unsetPanTrack() = 0;
+ virtual uint8 getVolume() = 0;
+ virtual void setDeltaVolume(uint8 volume) = 0;
+ virtual void setBalance(int8 balance) = 0;
virtual void setFade(int32 time, uint8 target) = 0;
};
class MusicNode : public MusicNodeBASE {
public:
- MusicNode(ZVision *engine, uint32 key, Common::String &file, bool loop, int8 volume);
+ MusicNode(ZVision *engine, uint32 key, Common::String &file, bool loop, uint8 volume);
~MusicNode();
/**
@@ -70,17 +70,16 @@ public:
bool process(uint32 deltaTimeInMillis);
void setVolume(uint8 volume);
-
- void setPanTrack(int16 pos);
- void unsetPanTrack();
+ uint8 getVolume();
+ void setDeltaVolume(uint8 volume);
+ void setBalance(int8 balance);
void setFade(int32 time, uint8 target);
private:
- bool _pantrack;
- int32 _pantrackPosition;
- int32 _attenuate;
uint8 _volume;
+ uint8 _deltaVolume;
+ int8 _balance;
bool _loop;
bool _crossfade;
uint8 _crossfadeTarget;
@@ -107,9 +106,9 @@ public:
bool process(uint32 deltaTimeInMillis);
void setVolume(uint8 volume);
-
- void setPanTrack(int16 pos);
- void unsetPanTrack();
+ uint8 getVolume();
+ void setDeltaVolume(uint8 volume);
+ void setBalance(int8 balance);
void setFade(int32 time, uint8 target);
@@ -126,8 +125,11 @@ public:
PanTrackNode(ZVision *engine, uint32 key, uint32 slot, int16 pos);
~PanTrackNode();
+ bool process(uint32 deltaTimeInMillis);
+
private:
uint32 _slot;
+ int16 _position;
};
} // End of namespace ZVision
diff --git a/engines/zvision/scripting/effects/ttytext_effect.cpp b/engines/zvision/scripting/effects/ttytext_effect.cpp
index c60b3aa8c5..8d340dae39 100644
--- a/engines/zvision/scripting/effects/ttytext_effect.cpp
+++ b/engines/zvision/scripting/effects/ttytext_effect.cpp
@@ -57,9 +57,9 @@ ttyTextNode::ttyTextNode(ZVision *engine, uint32 key, const Common::String &file
delete infile;
}
_img.create(_r.width(), _r.height(), _engine->_resourcePixelFormat);
- _style._sharp = true;
- _style.readAllStyle(_txtbuf);
- _style.setFont(_fnt);
+ _state._sharp = true;
+ _state.readAllStyles(_txtbuf);
+ _state.updateFontWithTextState(_fnt);
_engine->getScriptManager()->setStateValue(_key, 1);
}
@@ -74,29 +74,27 @@ bool ttyTextNode::process(uint32 deltaTimeInMillis) {
if (_nexttime < 0) {
if (_txtpos < _txtbuf.size()) {
if (_txtbuf[_txtpos] == '<') {
- int32 strt = _txtpos;
- int32 endt = 0;
+ int32 start = _txtpos;
+ int32 end = 0;
int16 ret = 0;
while (_txtbuf[_txtpos] != '>' && _txtpos < _txtbuf.size())
_txtpos++;
- endt = _txtpos;
- if (strt != -1)
- if ((endt - strt - 1) > 0)
- ret = _style.parseStyle(_txtbuf.c_str() + strt + 1, endt - strt - 1);
-
- if (ret & (TXT_RET_FNTCHG | TXT_RET_FNTSTL | TXT_RET_NEWLN)) {
- if (ret & TXT_RET_FNTCHG)
- _style.setFont(_fnt);
- if (ret & TXT_RET_FNTSTL)
- _style.setFontStyle(_fnt);
-
- if (ret & TXT_RET_NEWLN)
- newline();
+ end = _txtpos;
+ if (start != -1) {
+ if ((end - start - 1) > 0) {
+ ret = _state.parseStyle(_txtbuf.c_str() + start + 1, end - start - 1);
+ }
+ }
+
+ if (ret & (TEXT_CHANGE_FONT_TYPE | TEXT_CHANGE_FONT_STYLE)) {
+ _state.updateFontWithTextState(_fnt);
+ } else if (ret & TEXT_CHANGE_NEWLINE) {
+ newline();
}
- if (ret & TXT_RET_HASSTBOX) {
+ if (ret & TEXT_CHANGE_HAS_STATE_BOX) {
Common::String buf;
- buf = Common::String::format("%d", _engine->getScriptManager()->getStateValue(_style._statebox));
+ buf = Common::String::format("%d", _engine->getScriptManager()->getStateValue(_state._statebox));
for (uint8 j = 0; j < buf.size(); j++)
outchar(buf[j]);
@@ -158,7 +156,7 @@ void ttyTextNode::newline() {
}
void ttyTextNode::outchar(uint16 chr) {
- uint32 clr = _engine->_resourcePixelFormat.RGBToColor(_style._red, _style._green, _style._blue);
+ uint32 clr = _engine->_resourcePixelFormat.RGBToColor(_state._red, _state._green, _state._blue);
if (_dx + _fnt.getCharWidth(chr) > _r.width())
newline();
diff --git a/engines/zvision/scripting/effects/ttytext_effect.h b/engines/zvision/scripting/effects/ttytext_effect.h
index 8d8a2518c7..18cbbbaee3 100644
--- a/engines/zvision/scripting/effects/ttytext_effect.h
+++ b/engines/zvision/scripting/effects/ttytext_effect.h
@@ -51,7 +51,7 @@ public:
private:
Common::Rect _r;
- cTxtStyle _style;
+ TextStyleState _state;
StyledTTFont _fnt;
Common::String _txtbuf;
uint32 _txtpos;
diff --git a/engines/zvision/scripting/menu.cpp b/engines/zvision/scripting/menu.cpp
index 16aa57e3ae..064bd1b57d 100644
--- a/engines/zvision/scripting/menu.cpp
+++ b/engines/zvision/scripting/menu.cpp
@@ -46,13 +46,13 @@ MenuHandler::MenuHandler(ZVision *engine) {
MenuZGI::MenuZGI(ZVision *engine) :
MenuHandler(engine) {
menuMouseFocus = -1;
- inmenu = false;
+ inMenu = false;
scrolled[0] = false;
scrolled[1] = false;
scrolled[2] = false;
- scrollPos[0] = 0.0;
- scrollPos[1] = 0.0;
- scrollPos[2] = 0.0;
+ scrollPos[0] = 0;
+ scrollPos[1] = 0;
+ scrollPos[2] = 0;
mouseOnItem = -1;
redraw = false;
clean = false;
@@ -60,15 +60,15 @@ MenuZGI::MenuZGI(ZVision *engine) :
char buf[24];
for (int i = 1; i < 4; i++) {
sprintf(buf, "gmzau%2.2x1.tga", i);
- _engine->getRenderManager()->readImageToSurface(buf, menuback[i - 1][0], false);
+ _engine->getRenderManager()->readImageToSurface(buf, menuBack[i - 1][0], false);
sprintf(buf, "gmzau%2.2x1.tga", i + 0x10);
- _engine->getRenderManager()->readImageToSurface(buf, menuback[i - 1][1], false);
+ _engine->getRenderManager()->readImageToSurface(buf, menuBack[i - 1][1], false);
}
for (int i = 0; i < 4; i++) {
sprintf(buf, "gmzmu%2.2x1.tga", i);
- _engine->getRenderManager()->readImageToSurface(buf, menubar[i][0], false);
+ _engine->getRenderManager()->readImageToSurface(buf, menuBar[i][0], false);
sprintf(buf, "gmznu%2.2x1.tga", i);
- _engine->getRenderManager()->readImageToSurface(buf, menubar[i][1], false);
+ _engine->getRenderManager()->readImageToSurface(buf, menuBar[i][1], false);
}
for (int i = 0; i < 50; i++) {
@@ -86,12 +86,12 @@ MenuZGI::MenuZGI(ZVision *engine) :
MenuZGI::~MenuZGI() {
for (int i = 0; i < 3; i++) {
- menuback[i][0].free();
- menuback[i][1].free();
+ menuBack[i][0].free();
+ menuBack[i][1].free();
}
for (int i = 0; i < 4; i++) {
- menubar[i][0].free();
- menubar[i][1].free();
+ menuBar[i][0].free();
+ menuBar[i][1].free();
}
for (int i = 0; i < 50; i++) {
if (items[i][0]) {
@@ -208,9 +208,9 @@ void MenuZGI::onMouseUp(const Common::Point &Pos) {
void MenuZGI::onMouseMove(const Common::Point &Pos) {
if (Pos.y < 40) {
- if (!inmenu)
+ if (!inMenu)
redraw = true;
- inmenu = true;
+ inMenu = true;
switch (menuMouseFocus) {
case kMenuItem:
if (menuBarFlag & kMenubarItems) {
@@ -311,7 +311,7 @@ void MenuZGI::onMouseMove(const Common::Point &Pos) {
if (Common::Rect(64, 0, 64 + 512, 8).contains(Pos)) { // Main
menuMouseFocus = kMenuMain;
scrolled[kMenuMain] = false;
- scrollPos[kMenuMain] = menuback[kMenuMain][1].h - menuback[kMenuMain][0].h;
+ scrollPos[kMenuMain] = menuBack[kMenuMain][1].h - menuBack[kMenuMain][0].h;
_engine->getScriptManager()->setStateValue(StateKey_MenuState, 2);
}
@@ -337,9 +337,9 @@ void MenuZGI::onMouseMove(const Common::Point &Pos) {
break;
}
} else {
- if (inmenu)
+ if (inMenu)
clean = true;
- inmenu = false;
+ inMenu = false;
if (_engine->getScriptManager()->getStateValue(StateKey_MenuState) != 0)
_engine->getScriptManager()->setStateValue(StateKey_MenuState, 0);
menuMouseFocus = -1;
@@ -361,15 +361,15 @@ void MenuZGI::process(uint32 deltatime) {
if (scrl == 0)
scrl = 1.0;
- scrollPos [kMenuItem] += scrl;
+ scrollPos[kMenuItem] += (int)scrl;
if (scrollPos[kMenuItem] >= 0) {
scrolled[kMenuItem] = true;
- scrollPos [kMenuItem] = 0;
+ scrollPos[kMenuItem] = 0;
}
}
if (redraw) {
- _engine->getRenderManager()->blitSurfaceToMenu(menuback[kMenuItem][0], scrollPos[kMenuItem], 0);
+ _engine->getRenderManager()->blitSurfaceToMenu(menuBack[kMenuItem][0], scrollPos[kMenuItem], 0);
int itemCount = _engine->getScriptManager()->getStateValue(StateKey_Inv_TotalSlots);
if (itemCount == 0)
@@ -430,15 +430,15 @@ void MenuZGI::process(uint32 deltatime) {
if (scrl == 0)
scrl = 1.0;
- scrollPos [kMenuMagic] += scrl;
+ scrollPos[kMenuMagic] += (int)scrl;
if (scrollPos[kMenuMagic] >= 600) {
scrolled[kMenuMagic] = true;
- scrollPos [kMenuMagic] = 600;
+ scrollPos[kMenuMagic] = 600;
}
}
if (redraw) {
- _engine->getRenderManager()->blitSurfaceToMenu(menuback[kMenuMagic][0], 640 - scrollPos[kMenuMagic], 0);
+ _engine->getRenderManager()->blitSurfaceToMenu(menuBack[kMenuMagic][0], 640 - scrollPos[kMenuMagic], 0);
for (int i = 0; i < 12; i++) {
bool inrect = false;
@@ -495,53 +495,53 @@ void MenuZGI::process(uint32 deltatime) {
if (scrl == 0)
scrl = 1.0;
- scrollPos [kMenuMain] += scrl;
+ scrollPos[kMenuMain] += (int)scrl;
if (scrollPos[kMenuMain] >= 0) {
scrolled[kMenuMain] = true;
- scrollPos [kMenuMain] = 0;
+ scrollPos[kMenuMain] = 0;
}
}
if (redraw) {
- _engine->getRenderManager()->blitSurfaceToMenu(menuback[kMenuMain][0], 30, scrollPos[kMenuMain]);
+ _engine->getRenderManager()->blitSurfaceToMenu(menuBack[kMenuMain][0], 30, scrollPos[kMenuMain]);
if (menuBarFlag & kMenubarExit) {
if (mouseOnItem == kMainMenuExit)
- _engine->getRenderManager()->blitSurfaceToMenu(menubar[kMainMenuExit][1], 320 + 135, scrollPos[kMenuMain]);
+ _engine->getRenderManager()->blitSurfaceToMenu(menuBar[kMainMenuExit][1], 320 + 135, scrollPos[kMenuMain]);
else
- _engine->getRenderManager()->blitSurfaceToMenu(menubar[kMainMenuExit][0], 320 + 135, scrollPos[kMenuMain]);
+ _engine->getRenderManager()->blitSurfaceToMenu(menuBar[kMainMenuExit][0], 320 + 135, scrollPos[kMenuMain]);
}
if (menuBarFlag & kMenubarSettings) {
if (mouseOnItem == kMainMenuPrefs)
- _engine->getRenderManager()->blitSurfaceToMenu(menubar[kMainMenuPrefs][1], 320, scrollPos[kMenuMain]);
+ _engine->getRenderManager()->blitSurfaceToMenu(menuBar[kMainMenuPrefs][1], 320, scrollPos[kMenuMain]);
else
- _engine->getRenderManager()->blitSurfaceToMenu(menubar[kMainMenuPrefs][0], 320, scrollPos[kMenuMain]);
+ _engine->getRenderManager()->blitSurfaceToMenu(menuBar[kMainMenuPrefs][0], 320, scrollPos[kMenuMain]);
}
if (menuBarFlag & kMenubarRestore) {
if (mouseOnItem == kMainMenuLoad)
- _engine->getRenderManager()->blitSurfaceToMenu(menubar[kMainMenuLoad][1], 320 - 135, scrollPos[kMenuMain]);
+ _engine->getRenderManager()->blitSurfaceToMenu(menuBar[kMainMenuLoad][1], 320 - 135, scrollPos[kMenuMain]);
else
- _engine->getRenderManager()->blitSurfaceToMenu(menubar[kMainMenuLoad][0], 320 - 135, scrollPos[kMenuMain]);
+ _engine->getRenderManager()->blitSurfaceToMenu(menuBar[kMainMenuLoad][0], 320 - 135, scrollPos[kMenuMain]);
}
if (menuBarFlag & kMenubarSave) {
if (mouseOnItem == kMainMenuSave)
- _engine->getRenderManager()->blitSurfaceToMenu(menubar[kMainMenuSave][1], 320 - 135 * 2, scrollPos[kMenuMain]);
+ _engine->getRenderManager()->blitSurfaceToMenu(menuBar[kMainMenuSave][1], 320 - 135 * 2, scrollPos[kMenuMain]);
else
- _engine->getRenderManager()->blitSurfaceToMenu(menubar[kMainMenuSave][0], 320 - 135 * 2, scrollPos[kMenuMain]);
+ _engine->getRenderManager()->blitSurfaceToMenu(menuBar[kMainMenuSave][0], 320 - 135 * 2, scrollPos[kMenuMain]);
}
redraw = false;
}
break;
default:
if (redraw) {
- if (inmenu) {
- _engine->getRenderManager()->blitSurfaceToMenu(menuback[kMenuMain][1], 30, 0);
+ if (inMenu) {
+ _engine->getRenderManager()->blitSurfaceToMenu(menuBack[kMenuMain][1], 30, 0);
if (menuBarFlag & kMenubarItems)
- _engine->getRenderManager()->blitSurfaceToMenu(menuback[kMenuItem][1], 0, 0);
+ _engine->getRenderManager()->blitSurfaceToMenu(menuBack[kMenuItem][1], 0, 0);
if (menuBarFlag & kMenubarMagic)
- _engine->getRenderManager()->blitSurfaceToMenu(menuback[kMenuMagic][1], 640 - 28, 0);
+ _engine->getRenderManager()->blitSurfaceToMenu(menuBack[kMenuMagic][1], 640 - 28, 0);
}
redraw = false;
}
@@ -551,9 +551,9 @@ void MenuZGI::process(uint32 deltatime) {
MenuNemesis::MenuNemesis(ZVision *engine) :
MenuHandler(engine) {
- inmenu = false;
+ inMenu = false;
scrolled = false;
- scrollPos = 0.0;
+ scrollPos = 0;
mouseOnItem = -1;
redraw = false;
delay = 0;
@@ -565,7 +565,7 @@ MenuNemesis::MenuNemesis(ZVision *engine) :
_engine->getRenderManager()->readImageToSurface(buf, but[i][j], false);
}
- _engine->getRenderManager()->readImageToSurface("bar.tga", menubar, false);
+ _engine->getRenderManager()->readImageToSurface("bar.tga", menuBar, false);
frm = 0;
}
@@ -575,7 +575,7 @@ MenuNemesis::~MenuNemesis() {
for (int j = 0; j < 6; j++)
but[i][j].free();
- menubar.free();
+ menuBar.free();
}
static const int16 buts[4][2] = { {120 , 64}, {144, 184}, {128, 328}, {120, 456} };
@@ -631,7 +631,7 @@ void MenuNemesis::onMouseUp(const Common::Point &Pos) {
void MenuNemesis::onMouseMove(const Common::Point &Pos) {
if (Pos.y < 40) {
- inmenu = true;
+ inMenu = true;
if (_engine->getScriptManager()->getStateValue(StateKey_MenuState) != 2)
_engine->getScriptManager()->setStateValue(StateKey_MenuState, 2);
@@ -681,7 +681,7 @@ void MenuNemesis::onMouseMove(const Common::Point &Pos) {
delay = 200;
}
} else {
- inmenu = false;
+ inMenu = false;
if (_engine->getScriptManager()->getStateValue(StateKey_MenuState) != 0)
_engine->getScriptManager()->setStateValue(StateKey_MenuState, 0);
mouseOnItem = -1;
@@ -689,14 +689,14 @@ void MenuNemesis::onMouseMove(const Common::Point &Pos) {
}
void MenuNemesis::process(uint32 deltatime) {
- if (inmenu) {
+ if (inMenu) {
if (!scrolled) {
float scrl = 32.0 * 2.0 * (deltatime / 1000.0);
if (scrl == 0)
scrl = 1.0;
- scrollPos += scrl;
+ scrollPos += (int)scrl;
redraw = true;
}
@@ -715,7 +715,7 @@ void MenuNemesis::process(uint32 deltatime) {
}
if (redraw) {
- _engine->getRenderManager()->blitSurfaceToMenu(menubar, 64, scrollPos);
+ _engine->getRenderManager()->blitSurfaceToMenu(menuBar, 64, scrollPos);
if (menuBarFlag & kMenubarExit)
if (mouseOnItem == kMainMenuExit)
@@ -743,16 +743,16 @@ void MenuNemesis::process(uint32 deltatime) {
if (scrl == 0)
scrl = 1.0;
- Common::Rect cl(64, 32 + scrollPos - scrl, 64 + 512, 32 + scrollPos + 1);
+ Common::Rect cl(64, (int16)(32 + scrollPos - scrl), 64 + 512, 32 + scrollPos + 1);
_engine->getRenderManager()->clearMenuSurface(cl);
- scrollPos -= scrl;
+ scrollPos -= (int)scrl;
redraw = true;
} else
scrollPos = -32;
if (redraw) {
- _engine->getRenderManager()->blitSurfaceToMenu(menubar, 64, scrollPos);
+ _engine->getRenderManager()->blitSurfaceToMenu(menuBar, 64, scrollPos);
redraw = false;
}
}
diff --git a/engines/zvision/scripting/menu.h b/engines/zvision/scripting/menu.h
index a88587966f..f6b21b9c97 100644
--- a/engines/zvision/scripting/menu.h
+++ b/engines/zvision/scripting/menu.h
@@ -68,8 +68,8 @@ public:
void onMouseUp(const Common::Point &Pos);
void process(uint32 deltaTimeInMillis);
private:
- Graphics::Surface menuback[3][2];
- Graphics::Surface menubar[4][2];
+ Graphics::Surface menuBack[3][2];
+ Graphics::Surface menuBar[4][2];
Graphics::Surface *items[50][2];
uint itemId[50];
@@ -77,11 +77,11 @@ private:
uint magicId[12];
int menuMouseFocus;
- bool inmenu;
+ bool inMenu;
int mouseOnItem;
- bool scrolled[3];
+ bool scrolled[3];
int16 scrollPos[3];
bool clean;
@@ -98,13 +98,13 @@ public:
void process(uint32 deltaTimeInMillis);
private:
Graphics::Surface but[4][6];
- Graphics::Surface menubar;
+ Graphics::Surface menuBar;
- bool inmenu;
+ bool inMenu;
int mouseOnItem;
- bool scrolled;
+ bool scrolled;
int16 scrollPos;
bool redraw;
@@ -114,6 +114,6 @@ private:
};
-}
+} // End of namespace ZVision
#endif
diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp
index 7856bf7b2e..edc1b8622c 100644
--- a/engines/zvision/scripting/scr_file_handling.cpp
+++ b/engines/zvision/scripting/scr_file_handling.cpp
@@ -47,15 +47,13 @@ namespace ZVision {
void ScriptManager::parseScrFile(const Common::String &fileName, ScriptScope &scope) {
Common::File file;
if (!_engine->getSearchManager()->openFile(file, fileName)) {
- warning("Script file not found: %s", fileName.c_str());
- return;
+ error("Script file not found: %s", fileName.c_str());
}
while (!file.eos()) {
Common::String line = file.readLine();
if (file.err()) {
- warning("Error parsing scr file: %s", fileName.c_str());
- return;
+ error("Error parsing scr file: %s", fileName.c_str());
}
trimCommentsAndWhiteSpace(&line);
@@ -85,9 +83,18 @@ void ScriptManager::parsePuzzle(Puzzle *puzzle, Common::SeekableReadStream &stre
while (!stream.eos() && !line.contains('}')) {
if (line.matchString("criteria {", true)) {
- parseCriteria(stream, puzzle->criteriaList);
+ parseCriteria(stream, puzzle->criteriaList, puzzle->key);
} else if (line.matchString("results {", true)) {
parseResults(stream, puzzle->resultActions);
+
+ // WORKAROUND for a script bug in Zork Nemesis, room ve5e (tuning
+ // fork box closeup). If the player leaves the screen while the
+ // box is open, puzzle 19398 shows the animation where the box
+ // closes, but the box state (state variable 19397) is not updated.
+ // We insert the missing assignment for the box state here.
+ // Fixes bug #6803.
+ if (_engine->getGameId() == GID_NEMESIS && puzzle->key == 19398)
+ puzzle->resultActions.push_back(new ActionAssign(_engine, 11, "19397, 0"));
} else if (line.matchString("flags {", true)) {
setStateFlag(puzzle->key, parseFlags(stream));
}
@@ -99,11 +106,18 @@ void ScriptManager::parsePuzzle(Puzzle *puzzle, Common::SeekableReadStream &stre
puzzle->addedBySetState = false;
}
-bool ScriptManager::parseCriteria(Common::SeekableReadStream &stream, Common::List<Common::List<Puzzle::CriteriaEntry> > &criteriaList) const {
+bool ScriptManager::parseCriteria(Common::SeekableReadStream &stream, Common::List<Common::List<Puzzle::CriteriaEntry> > &criteriaList, uint32 key) const {
// Loop until we find the closing brace
Common::String line = stream.readLine();
trimCommentsAndWhiteSpace(&line);
+ // Skip any commented out criteria. If all the criteria are commented out,
+ // we might end up with an invalid criteria list (bug #6776).
+ while (line.empty()) {
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ }
+
// Criteria can be empty
if (line.contains('}')) {
return false;
@@ -112,6 +126,21 @@ bool ScriptManager::parseCriteria(Common::SeekableReadStream &stream, Common::Li
// Create a new List to hold the CriteriaEntries
criteriaList.push_back(Common::List<Puzzle::CriteriaEntry>());
+ // WORKAROUND for a script bug in Zork: Nemesis, room td9e (fist puzzle)
+ // Since we patch the script that triggers when manipulating the left fist
+ // (below), we add an additional check for the left fist sound, so that it
+ // doesn't get killed immediately when the left fist animation starts.
+ // Together with the workaround below, it fixes bug #6783.
+ if (_engine->getGameId() == GID_NEMESIS && key == 3594) {
+ Puzzle::CriteriaEntry entry;
+ entry.key = 567;
+ entry.criteriaOperator = Puzzle::NOT_EQUAL_TO;
+ entry.argumentIsAKey = false;
+ entry.argument = 1;
+
+ criteriaList.back().push_back(entry);
+ }
+
while (!stream.eos() && !line.contains('}')) {
Puzzle::CriteriaEntry entry;
@@ -123,6 +152,13 @@ bool ScriptManager::parseCriteria(Common::SeekableReadStream &stream, Common::Li
token = tokenizer.nextToken();
sscanf(token.c_str(), "[%u]", &(entry.key));
+ // WORKAROUND for a script bug in Zork: Nemesis, room td9e (fist puzzle)
+ // Check for the state of animation 567 (left fist) when manipulating
+ // the fingers of the left fist (puzzle slots 3582, 3583).
+ // Together with the workaround above, it fixes bug #6783.
+ if (_engine->getGameId() == GID_NEMESIS && (key == 3582 || key == 3583) && entry.key == 568)
+ entry.key = 567;
+
// Parse the operator out of the second token
token = tokenizer.nextToken();
if (token.c_str()[0] == '=')
@@ -134,9 +170,17 @@ bool ScriptManager::parseCriteria(Common::SeekableReadStream &stream, Common::Li
else if (token.c_str()[0] == '<')
entry.criteriaOperator = Puzzle::LESS_THAN;
+ // There are supposed to be three tokens, but there is no
+ // guarantee that there will be a space between the second and
+ // the third one (bug #6774)
+ if (token.size() == 1) {
+ token = tokenizer.nextToken();
+ } else {
+ token.deleteChar(0);
+ }
+
// First determine if the last token is an id or a value
// Then parse it into 'argument'
- token = tokenizer.nextToken();
if (token.contains('[')) {
sscanf(token.c_str(), "[%u]", &(entry.argument));
entry.argumentIsAKey = true;
@@ -271,8 +315,8 @@ void ScriptManager::parseResults(Common::SeekableReadStream &stream, Common::Lis
actionList.push_back(new ActionRegion(_engine, slot, args));
} else if (act.matchString("restore_game", true)) {
// Only used by ZGI to load the restart game slot, r.svr.
- _engine->getScriptManager()->reset();
- _engine->getScriptManager()->changeLocation('g', 'a', 'r', 'y', 0);
+ // Used by the credits screen.
+ actionList.push_back(new ActionRestoreGame(_engine, slot, args));
} else if (act.matchString("rotate_to", true)) {
actionList.push_back(new ActionRotateTo(_engine, slot, args));
} else if (act.matchString("save_game", true)) {
@@ -343,6 +387,16 @@ Control *ScriptManager::parseControl(Common::String &line, Common::SeekableReadS
Common::String controlType(controlTypeBuffer);
if (controlType.equalsIgnoreCase("push_toggle")) {
+ // WORKAROUND for a script bug in ZGI: There is an invalid hotspot
+ // at scene em1h (bottom of tower), which points to a missing
+ // script em1n. This is a hotspot at the right of the screen.
+ // In the original, this hotspot doesn't lead anywhere anyway,
+ // so instead of moving to a missing scene, we just remove the
+ // hotspot altogether. The alternative would be to just process
+ // and ignore invalid scenes, but I don't think it's worth the
+ // effort. Fixes bug #6780.
+ if (_engine->getGameId() == GID_GRANDINQUISITOR && key == 5653)
+ return NULL;
return new PushToggleControl(_engine, key, stream);
} else if (controlType.equalsIgnoreCase("flat")) {
Control::parseFlatControl(_engine);
diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp
index ba38d3a0e4..70eaab2a0a 100644
--- a/engines/zvision/scripting/script_manager.cpp
+++ b/engines/zvision/scripting/script_manager.cpp
@@ -72,21 +72,23 @@ void ScriptManager::initialize() {
}
void ScriptManager::update(uint deltaTimeMillis) {
- if (_currentLocation.node != _nextLocation.node ||
- _currentLocation.room != _nextLocation.room ||
- _currentLocation.view != _nextLocation.view ||
- _currentLocation.world != _nextLocation.world)
- ChangeLocationReal();
+ if (_currentLocation != _nextLocation) {
+ ChangeLocationReal(false);
+ }
updateNodes(deltaTimeMillis);
- if (! execScope(nodeview))
+ if (!execScope(nodeview)) {
return;
- if (! execScope(room))
+ }
+ if (!execScope(room)) {
return;
- if (! execScope(world))
+ }
+ if (!execScope(world)) {
return;
- if (! execScope(universe))
+ }
+ if (!execScope(universe)) {
return;
+ }
updateControls(deltaTimeMillis);
}
@@ -97,17 +99,22 @@ bool ScriptManager::execScope(ScriptScope &scope) {
scope.scopeQueue = tmp;
scope.scopeQueue->clear();
- for (PuzzleList::iterator PuzzleIter = scope.puzzles.begin(); PuzzleIter != scope.puzzles.end(); ++PuzzleIter)
+ for (PuzzleList::iterator PuzzleIter = scope.puzzles.begin(); PuzzleIter != scope.puzzles.end(); ++PuzzleIter) {
(*PuzzleIter)->addedBySetState = false;
+ }
if (scope.procCount < 2 || getStateValue(StateKey_ExecScopeStyle)) {
- for (PuzzleList::iterator PuzzleIter = scope.puzzles.begin(); PuzzleIter != scope.puzzles.end(); ++PuzzleIter)
- if (!checkPuzzleCriteria(*PuzzleIter, scope.procCount))
+ for (PuzzleList::iterator PuzzleIter = scope.puzzles.begin(); PuzzleIter != scope.puzzles.end(); ++PuzzleIter) {
+ if (!checkPuzzleCriteria(*PuzzleIter, scope.procCount)) {
return false;
+ }
+ }
} else {
- for (PuzzleList::iterator PuzzleIter = scope.execQueue->begin(); PuzzleIter != scope.execQueue->end(); ++PuzzleIter)
- if (!checkPuzzleCriteria(*PuzzleIter, scope.procCount))
+ for (PuzzleList::iterator PuzzleIter = scope.execQueue->begin(); PuzzleIter != scope.execQueue->end(); ++PuzzleIter) {
+ if (!checkPuzzleCriteria(*PuzzleIter, scope.procCount)) {
return false;
+ }
+ }
}
if (scope.procCount < 2) {
@@ -119,9 +126,11 @@ bool ScriptManager::execScope(ScriptScope &scope) {
void ScriptManager::referenceTableAddPuzzle(uint32 key, PuzzleRef ref) {
if (_referenceTable.contains(key)) {
Common::Array<PuzzleRef> *arr = &_referenceTable[key];
- for (uint32 i = 0; i < arr->size(); i++)
- if ((*arr)[i].puz == ref.puz)
+ for (uint32 i = 0; i < arr->size(); i++) {
+ if ((*arr)[i].puz == ref.puz) {
return;
+ }
+ }
}
_referenceTable[key].push_back(ref);
@@ -139,9 +148,11 @@ void ScriptManager::addPuzzlesToReferenceTable(ScriptScope &scope) {
referenceTableAddPuzzle(puzzlePtr->key, ref);
// Iterate through each CriteriaEntry and add a reference from the criteria key to the Puzzle
- for (Common::List<Common::List<Puzzle::CriteriaEntry> >::iterator criteriaIter = (*PuzzleIter)->criteriaList.begin(); criteriaIter != (*PuzzleIter)->criteriaList.end(); ++criteriaIter)
- for (Common::List<Puzzle::CriteriaEntry>::iterator entryIter = criteriaIter->begin(); entryIter != criteriaIter->end(); ++entryIter)
+ for (Common::List<Common::List<Puzzle::CriteriaEntry> >::iterator criteriaIter = (*PuzzleIter)->criteriaList.begin(); criteriaIter != (*PuzzleIter)->criteriaList.end(); ++criteriaIter) {
+ for (Common::List<Puzzle::CriteriaEntry>::iterator entryIter = criteriaIter->begin(); entryIter != criteriaIter->end(); ++entryIter) {
referenceTableAddPuzzle(entryIter->key, ref);
+ }
+ }
}
}
@@ -159,8 +170,9 @@ void ScriptManager::updateNodes(uint deltaTimeMillis) {
}
void ScriptManager::updateControls(uint deltaTimeMillis) {
- if (!_activeControls)
+ if (!_activeControls) {
return;
+ }
// Process only one event
if (!_controlEvents.empty()) {
@@ -187,21 +199,24 @@ void ScriptManager::updateControls(uint deltaTimeMillis) {
_controlEvents.pop_front();
}
- for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); iter++)
- if ((*iter)->process(deltaTimeMillis))
+ for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); iter++) {
+ if ((*iter)->process(deltaTimeMillis)) {
break;
+ }
+ }
}
bool ScriptManager::checkPuzzleCriteria(Puzzle *puzzle, uint counter) {
// Check if the puzzle is already finished
// Also check that the puzzle isn't disabled
- if (getStateValue(puzzle->key) == 1 || (getStateFlag(puzzle->key) & Puzzle::DISABLED) == Puzzle::DISABLED) {
+ if (getStateValue(puzzle->key) == 1 || (getStateFlag(puzzle->key) & Puzzle::DISABLED)) {
return true;
}
// Check each Criteria
- if (counter == 0 && (getStateFlag(puzzle->key) & Puzzle::DO_ME_NOW) == 0)
+ if (counter == 0 && (getStateFlag(puzzle->key) & Puzzle::DO_ME_NOW) == 0) {
return true;
+ }
bool criteriaMet = false;
for (Common::List<Common::List<Puzzle::CriteriaEntry> >::iterator criteriaIter = puzzle->criteriaList.begin(); criteriaIter != puzzle->criteriaList.end(); ++criteriaIter) {
@@ -210,10 +225,11 @@ bool ScriptManager::checkPuzzleCriteria(Puzzle *puzzle, uint counter) {
for (Common::List<Puzzle::CriteriaEntry>::iterator entryIter = criteriaIter->begin(); entryIter != criteriaIter->end(); ++entryIter) {
// Get the value to compare against
int argumentValue;
- if (entryIter->argumentIsAKey)
+ if (entryIter->argumentIsAKey) {
argumentValue = getStateValue(entryIter->argument);
- else
+ } else {
argumentValue = entryIter->argument;
+ }
// Do the comparison
switch (entryIter->criteriaOperator) {
@@ -251,8 +267,9 @@ bool ScriptManager::checkPuzzleCriteria(Puzzle *puzzle, uint counter) {
setStateValue(puzzle->key, 1);
for (Common::List<ResultAction *>::iterator resultIter = puzzle->resultActions.begin(); resultIter != puzzle->resultActions.end(); ++resultIter) {
- if (!(*resultIter)->execute())
+ if (!(*resultIter)->execute()) {
return false;
+ }
}
}
@@ -275,13 +292,15 @@ void ScriptManager::cleanScriptScope(ScriptScope &scope) {
scope.privQueueTwo.clear();
scope.scopeQueue = &scope.privQueueOne;
scope.execQueue = &scope.privQueueTwo;
- for (PuzzleList::iterator iter = scope.puzzles.begin(); iter != scope.puzzles.end(); ++iter)
+ for (PuzzleList::iterator iter = scope.puzzles.begin(); iter != scope.puzzles.end(); ++iter) {
delete(*iter);
+ }
scope.puzzles.clear();
- for (ControlList::iterator iter = scope.controls.begin(); iter != scope.controls.end(); ++iter)
+ for (ControlList::iterator iter = scope.controls.begin(); iter != scope.controls.end(); ++iter) {
delete(*iter);
+ }
scope.controls.clear();
@@ -289,44 +308,49 @@ void ScriptManager::cleanScriptScope(ScriptScope &scope) {
}
int ScriptManager::getStateValue(uint32 key) {
- if (_globalState.contains(key))
+ if (_globalState.contains(key)) {
return _globalState[key];
- else
+ } else {
return 0;
+ }
}
void ScriptManager::queuePuzzles(uint32 key) {
if (_referenceTable.contains(key)) {
Common::Array<PuzzleRef> *arr = &_referenceTable[key];
- for (int32 i = arr->size() - 1; i >= 0; i--)
+ for (int32 i = arr->size() - 1; i >= 0; i--) {
if (!(*arr)[i].puz->addedBySetState) {
(*arr)[i].scope->scopeQueue->push_back((*arr)[i].puz);
(*arr)[i].puz->addedBySetState = true;
}
+ }
}
}
void ScriptManager::setStateValue(uint32 key, int value) {
- if (value == 0)
+ if (value == 0) {
_globalState.erase(key);
- else
+ } else {
_globalState[key] = value;
+ }
queuePuzzles(key);
}
void ScriptManager::setStateValueSilent(uint32 key, int value) {
- if (value == 0)
+ if (value == 0) {
_globalState.erase(key);
- else
+ } else {
_globalState[key] = value;
+ }
}
uint ScriptManager::getStateFlag(uint32 key) {
- if (_globalStateFlags.contains(key))
+ if (_globalStateFlags.contains(key)) {
return _globalStateFlags[key];
- else
+ } else {
return 0;
+ }
}
void ScriptManager::setStateFlag(uint32 key, uint value) {
@@ -336,10 +360,11 @@ void ScriptManager::setStateFlag(uint32 key, uint value) {
}
void ScriptManager::setStateFlagSilent(uint32 key, uint value) {
- if (value == 0)
+ if (value == 0) {
_globalStateFlags.erase(key);
- else
+ } else {
_globalStateFlags[key] = value;
+ }
}
void ScriptManager::unsetStateFlag(uint32 key, uint value) {
@@ -348,23 +373,29 @@ void ScriptManager::unsetStateFlag(uint32 key, uint value) {
if (_globalStateFlags.contains(key)) {
_globalStateFlags[key] &= ~value;
- if (_globalStateFlags[key] == 0)
+ if (_globalStateFlags[key] == 0) {
_globalStateFlags.erase(key);
+ }
}
}
Control *ScriptManager::getControl(uint32 key) {
- for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); ++iter)
- if ((*iter)->getKey() == key)
+ for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); ++iter) {
+ if ((*iter)->getKey() == key) {
return *iter;
+ }
+ }
+
return nullptr;
}
void ScriptManager::focusControl(uint32 key) {
- if (!_activeControls)
+ if (!_activeControls) {
return;
- if (_currentlyFocusedControl == key)
+ }
+ if (_currentlyFocusedControl == key) {
return;
+ }
for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); ++iter) {
uint32 controlKey = (*iter)->getKey();
@@ -443,50 +474,60 @@ void ScriptManager::killSideFxType(ScriptingEffect::ScriptingEffectType type) {
}
void ScriptManager::onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
- if (!_activeControls)
+ if (!_activeControls) {
return;
+ }
for (ControlList::iterator iter = _activeControls->reverse_begin(); iter != _activeControls->end(); iter--) {
- if ((*iter)->onMouseDown(screenSpacePos, backgroundImageSpacePos))
+ if ((*iter)->onMouseDown(screenSpacePos, backgroundImageSpacePos)) {
return;
+ }
}
}
void ScriptManager::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
- if (!_activeControls)
+ if (!_activeControls) {
return;
+ }
for (ControlList::iterator iter = _activeControls->reverse_begin(); iter != _activeControls->end(); iter--) {
- if ((*iter)->onMouseUp(screenSpacePos, backgroundImageSpacePos))
+ if ((*iter)->onMouseUp(screenSpacePos, backgroundImageSpacePos)) {
return;
+ }
}
}
bool ScriptManager::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
- if (!_activeControls)
+ if (!_activeControls) {
return false;
+ }
for (ControlList::iterator iter = _activeControls->reverse_begin(); iter != _activeControls->end(); iter--) {
- if ((*iter)->onMouseMove(screenSpacePos, backgroundImageSpacePos))
+ if ((*iter)->onMouseMove(screenSpacePos, backgroundImageSpacePos)) {
return true;
+ }
}
return false;
}
void ScriptManager::onKeyDown(Common::KeyState keyState) {
- if (!_activeControls)
+ if (!_activeControls) {
return;
+ }
for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); ++iter) {
- if ((*iter)->onKeyDown(keyState))
+ if ((*iter)->onKeyDown(keyState)) {
return;
+ }
}
}
void ScriptManager::onKeyUp(Common::KeyState keyState) {
- if (!_activeControls)
+ if (!_activeControls) {
return;
+ }
for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); ++iter) {
- if ((*iter)->onKeyUp(keyState))
+ if ((*iter)->onKeyUp(keyState)) {
return;
+ }
}
}
@@ -500,8 +541,8 @@ void ScriptManager::changeLocation(char _world, char _room, char _node, char _vi
_nextLocation.node = _node;
_nextLocation.view = _view;
_nextLocation.offset = offset;
- // If next location 0000 - it's indicate to go to previous location.
- if (_nextLocation.world == '0' && _nextLocation.room == '0' && _nextLocation.node == '0' && _nextLocation.view == '0') {
+ // If next location is 0000, return to the previous location.
+ if (_nextLocation == "0000") {
if (getStateValue(StateKey_World) != 'g' || getStateValue(StateKey_Room) != 'j') {
_nextLocation.world = getStateValue(StateKey_LastWorld);
_nextLocation.room = getStateValue(StateKey_LastRoom);
@@ -518,36 +559,42 @@ void ScriptManager::changeLocation(char _world, char _room, char _node, char _vi
}
}
-void ScriptManager::ChangeLocationReal() {
+void ScriptManager::ChangeLocationReal(bool isLoading) {
assert(_nextLocation.world != 0);
debug(1, "Changing location to: %c %c %c %c %u", _nextLocation.world, _nextLocation.room, _nextLocation.node, _nextLocation.view, _nextLocation.offset);
- if (_nextLocation.world == 'g' && _nextLocation.room == 'j' && !ConfMan.getBool("originalsaveload")) {
- if ((_nextLocation.node == 's' || _nextLocation.node == 'r') && _nextLocation.view == 'e') {
+ const bool enteringMenu = (_nextLocation.world == 'g' && _nextLocation.room == 'j');
+ const bool leavingMenu = (_currentLocation.world == 'g' && _currentLocation.room == 'j');
+ const bool isSaveScreen = (enteringMenu && _nextLocation.node == 's' && _nextLocation.view == 'e');
+ const bool isRestoreScreen = (enteringMenu && _nextLocation.node == 'r' && _nextLocation.view == 'e');
+
+ if (enteringMenu && !ConfMan.getBool("originalsaveload")) {
+ if (isSaveScreen || isRestoreScreen) {
// Hook up the ScummVM save/restore dialog
- bool isSave = (_nextLocation.node == 's');
- bool gameSavedOrLoaded = _engine->getSaveManager()->scummVMSaveLoadDialog(isSave);
- if (!gameSavedOrLoaded || isSave) {
+ bool gameSavedOrLoaded = _engine->getSaveManager()->scummVMSaveLoadDialog(isSaveScreen);
+ if (!gameSavedOrLoaded || isSaveScreen) {
// Reload the current room
_nextLocation.world = _currentLocation.world;
_nextLocation.room = _currentLocation.room;
_nextLocation.node = _currentLocation.node;
_nextLocation.view = _currentLocation.view;
_nextLocation.offset = _currentLocation.offset;
- _currentLocation.world = '0';
+
+ return;
+ } else {
+ _currentLocation.world = 'g';
_currentLocation.room = '0';
_currentLocation.node = '0';
_currentLocation.view = '0';
_currentLocation.offset = 0;
- } else
- return;
+ }
}
}
_engine->setRenderDelay(2);
- if (getStateValue(StateKey_World) != 'g' || getStateValue(StateKey_Room) != 'j') {
- if (_nextLocation.world != 'g' || _nextLocation.room != 'j') {
+ if (!leavingMenu) {
+ if (!isLoading && !enteringMenu) {
setStateValue(StateKey_LastWorld, getStateValue(StateKey_World));
setStateValue(StateKey_LastRoom, getStateValue(StateKey_Room));
setStateValue(StateKey_LastNode, getStateValue(StateKey_Node));
@@ -562,13 +609,14 @@ void ScriptManager::ChangeLocationReal() {
}
}
- if (_nextLocation.world == 'g' && _nextLocation.room == 'j') {
- if (_nextLocation.node == 's' && _nextLocation.view == 'e' &&
- _currentLocation.world != 'g' && _currentLocation.room != 'j')
+ if (enteringMenu) {
+ if (isSaveScreen && !leavingMenu) {
_engine->getSaveManager()->prepareSaveBuffer();
+ }
} else {
- if (_currentLocation.world == 'g' && _currentLocation.room == 'j')
+ if (leavingMenu) {
_engine->getSaveManager()->flushSaveBuffer();
+ }
}
setStateValue(StateKey_World, _nextLocation.world);
@@ -631,7 +679,7 @@ void ScriptManager::ChangeLocationReal() {
// Change the background position
_engine->getRenderManager()->setBackgroundPosition(_nextLocation.offset);
- if (_currentLocation.world == 0 && _currentLocation.room == 0 && _currentLocation.node == 0 && _currentLocation.view == 0) {
+ if (_currentLocation == "0000") {
_currentLocation = _nextLocation;
execScope(world);
execScope(room);
@@ -664,29 +712,33 @@ void ScriptManager::serialize(Common::WriteStream *stream) {
stream->writeByte(getStateValue(StateKey_View));
stream->writeUint32LE(getStateValue(StateKey_ViewPos));
- for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end(); ++iter)
+ for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end(); ++iter) {
(*iter)->serialize(stream);
+ }
stream->writeUint32BE(MKTAG('F', 'L', 'A', 'G'));
int32 slots = 20000;
- if (_engine->getGameId() == GID_NEMESIS)
+ if (_engine->getGameId() == GID_NEMESIS) {
slots = 30000;
+ }
stream->writeUint32LE(slots * 2);
- for (int32 i = 0; i < slots; i++)
+ for (int32 i = 0; i < slots; i++) {
stream->writeUint16LE(getStateFlag(i));
+ }
stream->writeUint32BE(MKTAG('P', 'U', 'Z', 'Z'));
stream->writeUint32LE(slots * 2);
- for (int32 i = 0; i < slots; i++)
+ for (int32 i = 0; i < slots; i++) {
stream->writeSint16LE(getStateValue(i));
+ }
}
-void ScriptManager::reset() {
+void ScriptManager::deserialize(Common::SeekableReadStream *stream) {
// Clear out the current table values
_globalState.clear();
_globalStateFlags.clear();
@@ -700,16 +752,13 @@ void ScriptManager::reset() {
_currentLocation.room = 0;
_currentLocation.view = 0;
- for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end(); iter++)
+ for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end(); iter++) {
delete(*iter);
+ }
_activeSideFx.clear();
_referenceTable.clear();
-}
-
-void ScriptManager::deserialize(Common::SeekableReadStream *stream) {
- reset();
if (stream->readUint32BE() != MKTAG('Z', 'N', 'S', 'G') || stream->readUint32LE() != 4) {
changeLocation('g', 'a', 'r', 'y', 0);
@@ -738,20 +787,23 @@ void ScriptManager::deserialize(Common::SeekableReadStream *stream) {
case MKTAG('T', 'I', 'M', 'R'): {
uint32 key = stream->readUint32LE();
uint32 time = stream->readUint32LE();
- if (_engine->getGameId() == GID_GRANDINQUISITOR)
+ if (_engine->getGameId() == GID_GRANDINQUISITOR) {
time /= 100;
- else if (_engine->getGameId() == GID_NEMESIS)
+ } else if (_engine->getGameId() == GID_NEMESIS) {
time /= 1000;
+ }
addSideFX(new TimerNode(_engine, key, time));
}
break;
case MKTAG('F', 'L', 'A', 'G'):
- for (uint32 i = 0; i < tagSize / 2; i++)
+ for (uint32 i = 0; i < tagSize / 2; i++) {
setStateFlagSilent(i, stream->readUint16LE());
+ }
break;
case MKTAG('P', 'U', 'Z', 'Z'):
- for (uint32 i = 0; i < tagSize / 2; i++)
+ for (uint32 i = 0; i < tagSize / 2; i++) {
setStateValueSilent(i, stream->readUint16LE());
+ }
break;
default:
stream->seek(tagSize, SEEK_CUR);
@@ -760,7 +812,7 @@ void ScriptManager::deserialize(Common::SeekableReadStream *stream) {
_nextLocation = nextLocation;
- ChangeLocationReal();
+ ChangeLocationReal(true);
_engine->setRenderDelay(10);
setStateValue(StateKey_RestoreFlag, 1);
@@ -805,10 +857,11 @@ void ScriptManager::flushEvent(Common::EventType type) {
EventList::iterator it = _controlEvents.begin();
while (it != _controlEvents.end()) {
- if ((*it).type == type)
+ if ((*it).type == type) {
it = _controlEvents.erase(it);
- else
+ } else {
it++;
+ }
}
}
@@ -837,12 +890,15 @@ ValueSlot::ValueSlot(ScriptManager *scriptManager, const char *slotValue):
}
int16 ValueSlot::getValue() {
if (slot) {
- if (value >= 0)
+ if (value >= 0) {
return _scriptManager->getStateValue(value);
- else
+ }
+ else {
return 0;
- } else
+ }
+ } else {
return value;
+ }
}
} // End of namespace ZVision
diff --git a/engines/zvision/scripting/script_manager.h b/engines/zvision/scripting/script_manager.h
index a05c112a18..7c276bf917 100644
--- a/engines/zvision/scripting/script_manager.h
+++ b/engines/zvision/scripting/script_manager.h
@@ -113,6 +113,28 @@ struct Location {
uint32 offset;
};
+inline bool operator==(const Location& lhs, const Location& rhs) {
+ return (
+ lhs.world == rhs.world &&
+ lhs.room == rhs.room &&
+ lhs.node == rhs.node &&
+ lhs.view == rhs.view
+ );
+}
+
+inline bool operator==(const Location& lhs, const char* rhs) {
+ Common::String lhsStr = Common::String::format("%c%c%c%c", lhs.world, lhs.room, lhs.node, lhs.view);
+ return lhsStr == rhs;
+}
+
+inline bool operator!=(const Location& lhs, const Location& rhs) {
+ return !(lhs == rhs);
+}
+
+inline bool operator!=(const Location& lhs, const char* rhs) {
+ return !(lhs == rhs);
+}
+
typedef Common::List<Puzzle *> PuzzleList;
typedef Common::Queue<Puzzle *> PuzzleQueue;
typedef Common::List<Control *> ControlList;
@@ -248,7 +270,6 @@ public:
void serialize(Common::WriteStream *stream);
void deserialize(Common::SeekableReadStream *stream);
- void reset();
Location getCurrentLocation() const;
Location getLastLocation();
@@ -274,7 +295,7 @@ private:
bool execScope(ScriptScope &scope);
/** Perform change location */
- void ChangeLocationReal();
+ void ChangeLocationReal(bool isLoading);
int8 inventoryGetCount();
void inventorySetCount(int8 cnt);
@@ -313,9 +334,10 @@ private:
*
* @param criteria Pointer to the Criteria object to fill
* @param stream Scr file stream
+ * @param key Puzzle key (for workarounds)
* @return Whether any criteria were read
*/
- bool parseCriteria(Common::SeekableReadStream &stream, Common::List<Common::List<Puzzle::CriteriaEntry> > &criteriaList) const;
+ bool parseCriteria(Common::SeekableReadStream &stream, Common::List<Common::List<Puzzle::CriteriaEntry> > &criteriaList, uint32 key) const;
/**
* Parses the stream into a ResultAction objects
diff --git a/engines/zvision/scripting/scripting_effect.h b/engines/zvision/scripting/scripting_effect.h
index 0af1d9c21c..2a2153204f 100644
--- a/engines/zvision/scripting/scripting_effect.h
+++ b/engines/zvision/scripting/scripting_effect.h
@@ -37,7 +37,7 @@ class ZVision;
* The base class that represents effects created from Actions.
* This class is virtual.
*
- * Detailed Description:
+ * Detailed Description:
* A scene has Controls. By interacting with the controls, the user
* causes Actions to execute. Certain Actions create 'effects', for
* example, a sound or an animation. This is the base class for