Refactored running loop().

- shouldExitLoop() is a bool again and introduced new flag isReloaded() instead
  of adding special hacky value 2
- loop() accepts 2 parameters: loop substatus and shouldExit flag, because each
  caller previously had to set and restore these manually.  loop() now also
  tests whether the substatuses are properly nested.  reordered the
  loop-exitting code.
- renamed loop substatuses to logical names
- enterNewRoom() returns bool whether loop() should continue so that start()
  doesn't have to test and clear shouldEndProgram().  it doesn't need
  force_reload as a parameter anymore.
- dialog selections use new inner substatus instead of outer substatus, for
  consistency

svn-id: r45607
This commit is contained in:
Robert Špalek 2009-11-02 02:28:43 +00:00
parent 9f711bd0ce
commit c45f0343f4
5 changed files with 89 additions and 95 deletions

View file

@ -232,7 +232,7 @@ void DraciEngine::handleEvents() {
break; break;
case Common::KEYCODE_ESCAPE: { case Common::KEYCODE_ESCAPE: {
if (_game->getLoopStatus() == kStatusInventory && if (_game->getLoopStatus() == kStatusInventory &&
_game->getLoopSubstatus() == kSubstatusOrdinary) { _game->getLoopSubstatus() == kOuterLoop) {
_game->inventoryDone(); _game->inventoryDone();
break; break;
} }
@ -246,6 +246,8 @@ void DraciEngine::handleEvents() {
// Schedule room change // Schedule room change
// TODO: gate 0 is not always the best one for returning from the map // TODO: gate 0 is not always the best one for returning from the map
_game->scheduleEnteringRoomUsingGate(escRoom, 0); _game->scheduleEnteringRoomUsingGate(escRoom, 0);
// Immediately cancel any running animation or dubbing.
_game->setExitLoop(true); _game->setExitLoop(true);
// End any currently running GPL programs // End any currently running GPL programs
@ -278,7 +280,7 @@ void DraciEngine::handleEvents() {
break; break;
case Common::KEYCODE_i: case Common::KEYCODE_i:
if (_game->getRoomNum() == _game->getMapRoom() || if (_game->getRoomNum() == _game->getMapRoom() ||
_game->getLoopSubstatus() != kSubstatusOrdinary) { _game->getLoopSubstatus() != kOuterLoop) {
break; break;
} }
if (_game->getLoopStatus() == kStatusInventory) { if (_game->getLoopStatus() == kStatusInventory) {
@ -403,7 +405,7 @@ Common::Error DraciEngine::loadGameState(int slot) {
bool DraciEngine::canLoadGameStateCurrently() { bool DraciEngine::canLoadGameStateCurrently() {
return (_game->getLoopStatus() == kStatusOrdinary) && return (_game->getLoopStatus() == kStatusOrdinary) &&
(_game->getLoopSubstatus() == kSubstatusOrdinary); (_game->getLoopSubstatus() == kOuterLoop);
} }
Common::Error DraciEngine::saveGameState(int slot, const char *desc) { Common::Error DraciEngine::saveGameState(int slot, const char *desc) {
@ -412,7 +414,7 @@ Common::Error DraciEngine::saveGameState(int slot, const char *desc) {
bool DraciEngine::canSaveGameStateCurrently() { bool DraciEngine::canSaveGameStateCurrently() {
return (_game->getLoopStatus() == kStatusOrdinary) && return (_game->getLoopStatus() == kStatusOrdinary) &&
(_game->getLoopSubstatus() == kSubstatusOrdinary); (_game->getLoopSubstatus() == kOuterLoop);
} }
} // End of namespace Draci } // End of namespace Draci

View file

@ -149,36 +149,24 @@ Game::Game(DraciEngine *vm) : _vm(vm) {
void Game::start() { void Game::start() {
while (!shouldQuit()) { while (!shouldQuit()) {
debugC(1, kDraciGeneralDebugLevel, "Game::start()"); if (enterNewRoom()) {
// Call the outer loop doing all the hard job.
// Whenever the top-level loop is entered, it should not finish unless loop(kOuterLoop, false);
// the exit is triggered by a script
const bool force_reload = shouldExitLoop() > 1;
setExitLoop(false);
_vm->_script->endCurrentProgram(false);
enterNewRoom(force_reload);
if (_vm->_script->shouldEndProgram()) {
// Room changed during the initialization (intro or Escape pressed).
continue;
} }
// Call the outer loop doing all the hard job.
loop();
} }
} }
void Game::init() { void Game::init() {
setQuit(false); setQuit(false);
setExitLoop(false); setExitLoop(false);
setIsReloaded(false);
_scheduledPalette = 0; _scheduledPalette = 0;
_fadePhases = _fadePhase = 0; _fadePhases = _fadePhase = 0;
setEnableQuickHero(true); setEnableQuickHero(true);
setWantQuickHero(false); setWantQuickHero(false);
setEnableSpeedText(true); setEnableSpeedText(true);
setLoopStatus(kStatusGate); setLoopStatus(kStatusGate);
setLoopSubstatus(kSubstatusOrdinary); setLoopSubstatus(kOuterLoop);
_animUnderCursor = kOverlayImage; _animUnderCursor = kOverlayImage;
@ -240,22 +228,32 @@ void Game::init() {
_pushedNewRoom = _pushedNewGate = -1; _pushedNewRoom = _pushedNewGate = -1;
} }
void Game::loop() { void Game::loop(LoopSubstatus substatus, bool shouldExit) {
assert(getLoopSubstatus() == kOuterLoop);
setLoopSubstatus(substatus);
setExitLoop(shouldExit);
// Can run both as an outer and inner loop. In both mode it updates // Can run both as an outer and inner loop. In both mode it updates
// the screen according to the timer. It the outer mode // the screen according to the timer. It the outer mode (kOuterLoop)
// (kSubstatusOrdinary) it also reacts to user events. In the inner // it also reacts to user events. In the inner mode (all kInner*
// mode (all other kSubstatus* enums), the loop runs until its stopping // enums), the loop runs until its stopping condition, possibly
// condition, possibly stopping earlier if the user interrupts it, // stopping earlier if the user interrupts it, however no other user
// however no other user intervention is allowed. // intervention is allowed.
Surface *surface = _vm->_screen->getSurface(); Surface *surface = _vm->_screen->getSurface();
// Always enter the first pass of the loop, even if shouldExitLoop() is
// true, exactly to ensure to make at least one pass.
do { do {
debugC(4, kDraciLogicDebugLevel, "loopstatus: %d, loopsubstatus: %d", debugC(4, kDraciLogicDebugLevel, "loopstatus: %d, loopsubstatus: %d",
_loopStatus, _loopSubstatus); _loopStatus, _loopSubstatus);
_vm->handleEvents(); _vm->handleEvents();
if (shouldExitLoop() > 1) // after loading if (isReloaded()) {
// Cannot continue with the same animation objects,
// because the real data structures of the game have
// completely been changed.
break; break;
}
if (_fadePhase > 0 && (_vm->_system->getMillis() - _fadeTick) >= kFadingTimeUnit) { if (_fadePhase > 0 && (_vm->_system->getMillis() - _fadeTick) >= kFadingTimeUnit) {
_fadeTick = _vm->_system->getMillis(); _fadeTick = _vm->_system->getMillis();
@ -263,7 +261,7 @@ void Game::loop() {
const byte *startPal = _currentRoom._palette >= 0 ? _vm->_paletteArchive->getFile(_currentRoom._palette)->_data : NULL; const byte *startPal = _currentRoom._palette >= 0 ? _vm->_paletteArchive->getFile(_currentRoom._palette)->_data : NULL;
const byte *endPal = getScheduledPalette() >= 0 ? _vm->_paletteArchive->getFile(getScheduledPalette())->_data : NULL; const byte *endPal = getScheduledPalette() >= 0 ? _vm->_paletteArchive->getFile(getScheduledPalette())->_data : NULL;
_vm->_screen->interpolatePalettes(startPal, endPal, 0, kNumColours, _fadePhases - _fadePhase, _fadePhases); _vm->_screen->interpolatePalettes(startPal, endPal, 0, kNumColours, _fadePhases - _fadePhase, _fadePhases);
if (_loopSubstatus == kSubstatusFade && _fadePhase == 0) { if (_loopSubstatus == kInnerWhileFade && _fadePhase == 0) {
setExitLoop(true); setExitLoop(true);
// Rewrite the palette index of the current // Rewrite the palette index of the current
// room. This is necessary when two fadings // room. This is necessary when two fadings
@ -277,7 +275,7 @@ void Game::loop() {
int x = _vm->_mouse->getPosX(); int x = _vm->_mouse->getPosX();
int y = _vm->_mouse->getPosY(); int y = _vm->_mouse->getPosY();
if (_loopStatus == kStatusDialogue && _loopSubstatus == kSubstatusOrdinary) { if (_loopStatus == kStatusDialogue && _loopSubstatus == kInnerDuringDialogue) {
Text *text; Text *text;
for (int i = 0; i < kDialogueLines; ++i) { for (int i = 0; i < kDialogueLines; ++i) {
text = reinterpret_cast<Text *>(_dialogueAnims[i]->getCurrentFrame()); text = reinterpret_cast<Text *>(_dialogueAnims[i]->getCurrentFrame());
@ -306,7 +304,7 @@ void Game::loop() {
// During the normal game-play, in particular not when // During the normal game-play, in particular not when
// running the init-scripts, enable interactivity. // running the init-scripts, enable interactivity.
if (_loopStatus == kStatusOrdinary && _loopSubstatus == kSubstatusOrdinary) { if (_loopStatus == kStatusOrdinary && _loopSubstatus == kOuterLoop) {
if (_vm->_mouse->lButtonPressed()) { if (_vm->_mouse->lButtonPressed()) {
_vm->_mouse->lButtonSet(false); _vm->_mouse->lButtonSet(false);
@ -380,7 +378,7 @@ void Game::loop() {
} }
} }
if (_loopStatus == kStatusInventory && _loopSubstatus == kSubstatusOrdinary) { if (_loopStatus == kStatusInventory && _loopSubstatus == kOuterLoop) {
if (_inventoryExit) { if (_inventoryExit) {
inventoryDone(); inventoryDone();
} }
@ -455,7 +453,7 @@ void Game::loop() {
debugC(5, kDraciLogicDebugLevel, "Anim under cursor: %d", _animUnderCursor); debugC(5, kDraciLogicDebugLevel, "Anim under cursor: %d", _animUnderCursor);
// Handle character talking (if there is any) // Handle character talking (if there is any)
if (_loopSubstatus == kSubstatusTalk) { if (_loopSubstatus == kInnerWhileTalk) {
// If the current speech text has expired or the user clicked a mouse button, // If the current speech text has expired or the user clicked a mouse button,
// advance to the next line of text // advance to the next line of text
if ((getEnableSpeedText() && (_vm->_mouse->lButtonPressed() || _vm->_mouse->rButtonPressed())) || if ((getEnableSpeedText() && (_vm->_mouse->lButtonPressed() || _vm->_mouse->rButtonPressed())) ||
@ -467,20 +465,27 @@ void Game::loop() {
_vm->_mouse->rButtonSet(false); _vm->_mouse->rButtonSet(false);
} }
// A script has scheduled changing the room (either triggered
// by the user clicking on something or run at the end of a
// gate script in the intro).
if ((_loopStatus == kStatusOrdinary || _loopStatus == kStatusGate) && _newRoom != getRoomNum()) {
setExitLoop(true);
}
// This returns true if we got a signal to quit the game // This returns true if we got a signal to quit the game
if (shouldQuit()) if (shouldQuit()) {
return; setExitLoop(true);
}
// Advance animations and redraw screen // Advance animations and redraw screen
_vm->_anims->drawScene(surface); _vm->_anims->drawScene(surface);
_vm->_screen->copyToScreen(); _vm->_screen->copyToScreen();
_vm->_system->delayMillis(20); _vm->_system->delayMillis(20);
// HACK: Won't be needed once the game loop is implemented properly
setExitLoop(shouldExitLoop() || (_newRoom != getRoomNum() &&
(_loopStatus == kStatusOrdinary || _loopStatus == kStatusGate)));
} while (!shouldExitLoop()); } while (!shouldExitLoop());
setLoopSubstatus(kOuterLoop);
setExitLoop(false);
} }
void Game::updateCursor() { void Game::updateCursor() {
@ -502,7 +507,7 @@ void Game::updateCursor() {
// If we are in inventory mode, we do a different kind of updating that handles // If we are in inventory mode, we do a different kind of updating that handles
// inventory items and return early // inventory items and return early
if (_loopStatus == kStatusInventory && _loopSubstatus == kSubstatusOrdinary) { if (_loopStatus == kStatusInventory && _loopSubstatus == kOuterLoop) {
if (_itemUnderCursor != kNoItem) { if (_itemUnderCursor != kNoItem) {
const GameItem *item = &_items[_itemUnderCursor]; const GameItem *item = &_items[_itemUnderCursor];
@ -708,7 +713,7 @@ void Game::putItem(int itemID, int position) {
// If we are in inventory mode, we need to play the item animation, immediately // If we are in inventory mode, we need to play the item animation, immediately
// upon returning it to its slot but *not* in other modes because it should be // upon returning it to its slot but *not* in other modes because it should be
// invisible then (along with the inventory) // invisible then (along with the inventory)
if (_loopStatus == kStatusInventory && _loopSubstatus == kSubstatusOrdinary) { if (_loopStatus == kStatusInventory && _loopSubstatus == kOuterLoop) {
_vm->_anims->play(anim_id); _vm->_anims->play(anim_id);
} }
} }
@ -850,8 +855,7 @@ int Game::dialogueDraw() {
// Call the game loop to enable interactivity until the user // Call the game loop to enable interactivity until the user
// selects his choice. // selects his choice.
_vm->_mouse->cursorOn(); _vm->_mouse->cursorOn();
setExitLoop(false); loop(kInnerDuringDialogue, false);
loop();
_vm->_mouse->cursorOff(); _vm->_mouse->cursorOff();
bool notDialogueAnim = true; bool notDialogueAnim = true;
@ -1302,9 +1306,10 @@ int Game::playingObjectAnimation(const GameObject *obj) const {
return -1; return -1;
} }
void Game::enterNewRoom(bool force_reload) { bool Game::enterNewRoom() {
if (_newRoom == getRoomNum() && !force_reload) { if (_newRoom == getRoomNum() && !isReloaded()) {
return; // If the game has been reloaded, force reloading all animations.
return true;
} }
debugC(1, kDraciLogicDebugLevel, "Entering room %d using gate %d", _newRoom, _newGate); debugC(1, kDraciLogicDebugLevel, "Entering room %d using gate %d", _newRoom, _newGate);
@ -1357,7 +1362,9 @@ void Game::enterNewRoom(bool force_reload) {
// Set the appropriate loop statu before loading the room // Set the appropriate loop statu before loading the room
setLoopStatus(kStatusGate); setLoopStatus(kStatusGate);
setLoopSubstatus(kSubstatusOrdinary); // Reset the flag allowing to run the scripts. It may have been turned
// on by pressing Escape in the intro or in the map room.
_vm->_script->endCurrentProgram(false);
loadRoom(_newRoom); loadRoom(_newRoom);
loadOverlays(); loadOverlays();
@ -1379,6 +1386,16 @@ void Game::enterNewRoom(bool force_reload) {
setLoopStatus(kStatusOrdinary); setLoopStatus(kStatusOrdinary);
_vm->_mouse->setCursorType(kNormalCursor); _vm->_mouse->setCursorType(kNormalCursor);
setIsReloaded(false);
if (_vm->_script->shouldEndProgram()) {
// Escape pressed during the intro or map animations run in the
// init scripts. This flag was turned on to skip the rest of
// those programs. Return false to make start() rerun us from
// the beginning, because the room number has changed.
return false;
}
return true;
} }
void Game::runGateProgram(int gate) { void Game::runGateProgram(int gate) {

View file

@ -166,10 +166,11 @@ enum LoopStatus {
}; };
enum LoopSubstatus { enum LoopSubstatus {
kSubstatusOrdinary, // outer loop: everything is allowed kOuterLoop, // outer loop: everything is allowed
kSubstatusTalk, // playing a voice: inner loop will exit afterwards kInnerWhileTalk, // playing a voice: inner loop will exit afterwards
kSubstatusFade, // fading a palette: inner loop will exit when done kInnerWhileFade, // fading a palette: inner loop will exit when done
kSubstatusStrange // other inner loop: either immediately exiting or waiting for an animation to end (whose callback ends the loop) kInnerDuringDialogue, // selecting continuation block: inner block will exit afterwards
kInnerUntilExit // other inner loop: either immediately exiting or waiting for an animation to end (whose callback ends the loop)
}; };
class Game { class Game {
@ -179,7 +180,7 @@ public:
void init(); void init();
void start(); void start();
void loop(); void loop(LoopSubstatus substatus, bool shouldExit);
// HACK: this is only for testing // HACK: this is only for testing
int nextRoomNum() const { int nextRoomNum() const {
@ -271,9 +272,10 @@ public:
bool shouldQuit() const { return _shouldQuit; } bool shouldQuit() const { return _shouldQuit; }
void setQuit(bool quit) { _shouldQuit = quit; } void setQuit(bool quit) { _shouldQuit = quit; }
bool shouldExitLoop() const { return _shouldExitLoop; }
int shouldExitLoop() const { return _shouldExitLoop; } void setExitLoop(bool exit) { _shouldExitLoop = exit; }
void setExitLoop(int exit) { _shouldExitLoop = exit; } bool isReloaded() const { return _isReloaded; }
void setIsReloaded(bool value) { _isReloaded = value; }
void setSpeechTiming(uint tick, uint duration); void setSpeechTiming(uint tick, uint duration);
void shiftSpeechAndFadeTick(int delta); void shiftSpeechAndFadeTick(int delta);
@ -318,7 +320,7 @@ public:
void DoSync(Common::Serializer &s); void DoSync(Common::Serializer &s);
private: private:
void enterNewRoom(bool force_reload); bool enterNewRoom(); // Returns false if another room change has been triggered and therefore loop() shouldn't be called yet.
void loadRoom(int roomNum); void loadRoom(int roomNum);
void runGateProgram(int gate); void runGateProgram(int gate);
void redrawWalkingPath(int id, byte colour, const WalkingMap::Path &path); void redrawWalkingPath(int id, byte colour, const WalkingMap::Path &path);
@ -367,7 +369,8 @@ private:
LoopSubstatus _loopSubstatus; LoopSubstatus _loopSubstatus;
bool _shouldQuit; bool _shouldQuit;
int _shouldExitLoop; // 0=false and 1=true are normal, 2=immediate exit after loading bool _shouldExitLoop;
bool _isReloaded;
uint _speechTick; uint _speechTick;
uint _speechDuration; uint _speechDuration;

View file

@ -152,7 +152,7 @@ Common::Error loadSavegameData(int saveGameIdx, DraciEngine *vm) {
// Post-processing // Post-processing
vm->_game->scheduleEnteringRoomUsingGate(vm->_game->getRoomNum(), 0); vm->_game->scheduleEnteringRoomUsingGate(vm->_game->getRoomNum(), 0);
vm->_game->setRoomNum(vm->_game->getPreviousRoomNum()); vm->_game->setRoomNum(vm->_game->getPreviousRoomNum());
vm->_game->setExitLoop(2); // 2 > true means immediate exit for the loop vm->_game->setIsReloaded(true);
vm->_game->inventoryReload(); vm->_game->inventoryReload();

View file

@ -359,11 +359,7 @@ void Script::play(Common::Queue<int> &params) {
// Runs just one phase of the loop and exits. Used when waiting for a // Runs just one phase of the loop and exits. Used when waiting for a
// particular animation phase to come. // particular animation phase to come.
_vm->_game->setLoopSubstatus(kSubstatusStrange); _vm->_game->loop(kInnerUntilExit, true);
_vm->_game->setExitLoop(true);
_vm->_game->loop();
_vm->_game->setExitLoop(false);
_vm->_game->setLoopSubstatus(kSubstatusOrdinary);
} }
Animation *Script::loadObjectAnimation(GameObject *obj, int animID) { Animation *Script::loadObjectAnimation(GameObject *obj, int animID) {
@ -463,19 +459,14 @@ void Script::startPlay(Common::Queue<int> &params) {
anim->registerCallback(&Animation::exitGameLoop); anim->registerCallback(&Animation::exitGameLoop);
_vm->_game->setLoopSubstatus(kSubstatusStrange);
bool visible = (obj->_location == _vm->_game->getRoomNum() && obj->_visible); bool visible = (obj->_location == _vm->_game->getRoomNum() && obj->_visible);
if (objID == kDragonObject || visible) { if (objID == kDragonObject || visible) {
_vm->_anims->play(animID); _vm->_anims->play(animID);
} }
// Runs an inner loop until the animation ends. // Runs an inner loop until the animation ends.
_vm->_game->loop(); _vm->_game->loop(kInnerUntilExit, false);
_vm->_game->setExitLoop(false);
_vm->_anims->stop(animID); _vm->_anims->stop(animID);
_vm->_game->setLoopSubstatus(kSubstatusOrdinary);
anim->registerCallback(&Animation::doNothing); anim->registerCallback(&Animation::doNothing);
} }
@ -677,17 +668,12 @@ void Script::walkOnPlay(Common::Queue<int> &params) {
int y = params.pop(); int y = params.pop();
SightDirection dir = static_cast<SightDirection> (params.pop()); SightDirection dir = static_cast<SightDirection> (params.pop());
// HACK: This should be an onDest action when hero walking is properly implemented
// For now, we just go throught the loop-body once to redraw the screen.
_vm->_game->setExitLoop(true);
_vm->_game->walkHero(x, y, dir); _vm->_game->walkHero(x, y, dir);
_vm->_game->setLoopSubstatus(kSubstatusStrange); // HACK: This (shouldExit==true) should be an onDest action when hero
_vm->_game->loop(); // walking is properly implemented For now, we just go throught the
_vm->_game->setLoopSubstatus(kSubstatusOrdinary); // loop-body once to redraw the screen.
_vm->_game->loop(kInnerUntilExit, true);
_vm->_game->setExitLoop(false);
} }
void Script::newRoom(Common::Queue<int> &params) { void Script::newRoom(Common::Queue<int> &params) {
@ -737,9 +723,6 @@ void Script::talk(Common::Queue<int> &params) {
speechFrame->setFont(_vm->_smallFont); speechFrame->setFont(_vm->_smallFont);
} }
// Set the loop substatus to an appropriate value
_vm->_game->setLoopSubstatus(kSubstatusTalk);
// Speak the dubbing if possible // Speak the dubbing if possible
uint dubbingDuration = 0; uint dubbingDuration = 0;
if (sample) { if (sample) {
@ -776,12 +759,8 @@ void Script::talk(Common::Queue<int> &params) {
speechFrame->setX(x); speechFrame->setX(x);
speechFrame->setY(y); speechFrame->setY(y);
// Prevent the loop from exiting early if other things left the loop in the
// "exit immediately" state
_vm->_game->setExitLoop(false);
// Call the game loop to enable interactivity until the text expires. // Call the game loop to enable interactivity until the text expires.
_vm->_game->loop(); _vm->_game->loop(kInnerWhileTalk, false);
// Delete the text // Delete the text
_vm->_screen->getSurface()->markDirtyRect(speechFrame->getRect(kNoDisplacement)); _vm->_screen->getSurface()->markDirtyRect(speechFrame->getRect(kNoDisplacement));
@ -793,10 +772,6 @@ void Script::talk(Common::Queue<int> &params) {
_vm->_sound->stopVoice(); _vm->_sound->stopVoice();
sample->close(); sample->close();
} }
// Revert to "normal" loop status
_vm->_game->setLoopSubstatus(kSubstatusOrdinary);
_vm->_game->setExitLoop(false);
} }
void Script::dialogue(Common::Queue<int> &params) { void Script::dialogue(Common::Queue<int> &params) {
@ -877,7 +852,7 @@ void Script::fadePalette(Common::Queue<int> &params) {
int phases = params.pop(); int phases = params.pop();
// Let the palette fade in the background while the game continues. // Let the palette fade in the background while the game continues.
// Since we don't set substatus to kSubstatusFade, the outer loop will // Since we don't set substatus to kInnerWhileFade, the outer loop will
// just continue rather than exit. // just continue rather than exit.
_vm->_game->initializeFading(phases); _vm->_game->initializeFading(phases);
} }
@ -889,10 +864,7 @@ void Script::fadePalettePlay(Common::Queue<int> &params) {
_vm->_game->initializeFading(phases); _vm->_game->initializeFading(phases);
// Call the game loop to enable interactivity until the fading is done. // Call the game loop to enable interactivity until the fading is done.
_vm->_game->setLoopSubstatus(kSubstatusFade); _vm->_game->loop(kInnerWhileFade, false);
_vm->_game->loop();
_vm->_game->setExitLoop(false);
_vm->_game->setLoopSubstatus(kSubstatusOrdinary);
} }
void Script::setPalette(Common::Queue<int> &params) { void Script::setPalette(Common::Queue<int> &params) {