ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

animscript.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "engines/stark/resources/animscript.h"
00024 
00025 #include "common/debug.h"
00026 #include "common/random.h"
00027 
00028 #include "engines/stark/debug.h"
00029 
00030 #include "engines/stark/formats/xrc.h"
00031 
00032 #include "engines/stark/resources/anim.h"
00033 #include "engines/stark/resources/container.h"
00034 #include "engines/stark/resources/location.h"
00035 #include "engines/stark/resources/sound.h"
00036 
00037 #include "engines/stark/services/global.h"
00038 #include "engines/stark/services/services.h"
00039 #include "engines/stark/services/stateprovider.h"
00040 
00041 namespace Stark {
00042 namespace Resources {
00043 
00044 AnimScript::~AnimScript() {
00045 }
00046 
00047 AnimScript::AnimScript(Object *parent, byte subType, uint16 index, const Common::String &name) :
00048         Object(parent, subType, index, name),
00049         _anim(nullptr),
00050         _nextItemIndex(-1),
00051         _msecsToNextUpdate(0),
00052         _done(false) {
00053     _type = TYPE;
00054 }
00055 
00056 void AnimScript::onAllLoaded() {
00057     Object::onAllLoaded();
00058 
00059     _anim = Object::cast<Anim>(_parent);
00060     _items = listChildren<AnimScriptItem>();
00061 
00062     if (!_items.empty()) {
00063         // Setup the next item to the first
00064         _nextItemIndex = 0;
00065     }
00066 }
00067 
00068 void AnimScript::onGameLoop() {
00069     Object::onGameLoop();
00070 
00071     if (!_anim || !_anim->isInUse() || _nextItemIndex == -1) {
00072         // The script is disabled, do nothing
00073         return;
00074     }
00075 
00076     int executedCommandCount = 0;
00077 
00078     while (_msecsToNextUpdate <= (int32)StarkGlobal->getMillisecondsPerGameloop()) {
00079         bool goingBackwards = false;
00080         AnimScriptItem *item = _items[_nextItemIndex];
00081         _msecsToNextUpdate += item->getDuration();
00082 
00083         switch (item->getOpcode()) {
00084         case AnimScriptItem::kDisplayFrame:
00085             _anim->selectFrame(item->getOperand());
00086             goToNextItem();
00087             break;
00088         case AnimScriptItem::kPlayAnimSound: {
00089             Container *sounds = _parent->findChildWithSubtype<Container>(Container::kSounds);
00090             Sound *sound = sounds->findChildWithOrder<Sound>(item->getOperand());
00091             sound->play();
00092 
00093             goToNextItem();
00094             break;
00095         }
00096         case AnimScriptItem::kGoToItem:
00097             if (item->getOperand() <= (uint32) _nextItemIndex) {
00098                 goingBackwards = true;
00099             }
00100             _nextItemIndex = item->getOperand();
00101             break;
00102         case AnimScriptItem::kDisplayRandomFrame: {
00103             uint32 startFrame = item->getOperand() >> 16;
00104             uint32 endFrame = item->getOperand() & 0xFFFF;
00105 
00106             uint32 frame = StarkRandomSource->getRandomNumberRng(startFrame, endFrame);
00107             _anim->selectFrame(frame);
00108             goToNextItem();
00109             break;
00110         }
00111         case AnimScriptItem::kSleepRandomDuration: {
00112             uint duration = StarkRandomSource->getRandomNumber(item->getOperand());
00113             _msecsToNextUpdate += duration;
00114             goToNextItem();
00115             break;
00116         }
00117         case AnimScriptItem::kPlayStockSound: {
00118             Location *location = StarkGlobal->getCurrent()->getLocation();
00119             Sound *sound = location->findStockSound(item->getOperand());
00120             if (sound) {
00121                 sound->play();
00122             }
00123             goToNextItem();
00124             break;
00125         }
00126         default:
00127             error("Unknown anim script type %d", item->getOpcode());
00128         }
00129 
00130         if (_nextItemIndex == 0 || goingBackwards) {
00131             _done = true;
00132         }
00133 
00134         executedCommandCount++;
00135         if (executedCommandCount >= 10) {
00136             debugC(kDebugAnimation, "Potential infinite loop in anim script %s", getName().c_str());
00137             break;
00138         }
00139     }
00140 
00141     _msecsToNextUpdate -= StarkGlobal->getMillisecondsPerGameloop();
00142 }
00143 
00144 void AnimScript::goToNextItem() {
00145     _nextItemIndex += 1;
00146     _nextItemIndex %= _items.size();
00147 }
00148 
00149 void AnimScript::goToScriptItem(AnimScriptItem *item) {
00150     _nextItemIndex = findItemIndex(item);
00151     _msecsToNextUpdate = 0;
00152     _done = false;
00153 
00154     if (item && item->getOpcode() == AnimScriptItem::kDisplayFrame) {
00155         _anim->selectFrame(item->getOperand());
00156     }
00157 }
00158 
00159 bool AnimScript::hasReached(AnimScriptItem *item) {
00160     int32 index = findItemIndex(item);
00161     return _nextItemIndex >= index;
00162 }
00163 
00164 bool AnimScript::isDone() const {
00165     return _done;
00166 }
00167 
00168 int32 AnimScript::findItemIndex(AnimScriptItem *item) {
00169     if (!item) {
00170         return 0;
00171     }
00172 
00173     for (uint i = 0; i < _items.size(); i++) {
00174         if (_items[i] == item) {
00175             return i;
00176         }
00177     }
00178 
00179     return 0;
00180 }
00181 
00182 void AnimScript::saveLoad(ResourceSerializer *serializer) {
00183     serializer->syncAsSint32LE(_nextItemIndex);
00184 
00185     if (serializer->isLoading()) {
00186         _msecsToNextUpdate = 0;
00187     }
00188 }
00189 
00190 AnimScriptItem::~AnimScriptItem() {
00191 }
00192 
00193 AnimScriptItem::AnimScriptItem(Object *parent, byte subType, uint16 index, const Common::String &name) :
00194         Object(parent, subType, index, name),
00195         _opcode(0),
00196         _duration(0),
00197         _operand(0) {
00198     _type = TYPE;
00199 }
00200 
00201 void AnimScriptItem::readData(Formats::XRCReadStream *stream) {
00202     _opcode = stream->readUint32LE();
00203     _duration = stream->readUint32LE();
00204     _operand = stream->readUint32LE();
00205 }
00206 
00207 void AnimScriptItem::printData() {
00208     debug("op: %d, duration: %d ms, operand: %d", _opcode, _duration, _operand);
00209 }
00210 
00211 } // End of namespace Resources
00212 } // End of namespace Stark


Generated on Sat Feb 16 2019 05:00:44 for ResidualVM by doxygen 1.7.1
curved edge   curved edge