/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "lastexpress/game/savepoint.h" #include "lastexpress/game/entities.h" #include "lastexpress/game/logic.h" #include "lastexpress/game/state.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" namespace LastExpress { SavePoints::SavePoints(LastExpressEngine *engine) : _engine(engine) { for (int i = 0; i < 40; i++) _callbacks[i] = NULL; } SavePoints::~SavePoints() { // Zero passed pointers _engine = NULL; } ////////////////////////////////////////////////////////////////////////// // Savepoints ////////////////////////////////////////////////////////////////////////// void SavePoints::push(EntityIndex entity2, EntityIndex entity1, ActionIndex action, uint32 param) { if (_savepoints.size() >= _savePointsMaxSize) return; SavePoint point; point.entity1 = entity1; point.action = action; point.entity2 = entity2; point.param.intValue = param; _savepoints.push_back(point); } void SavePoints::push(EntityIndex entity2, EntityIndex entity1, ActionIndex action, const char *param) { if (_savepoints.size() >= _savePointsMaxSize) return; SavePoint point; point.entity1 = entity1; point.action = action; point.entity2 = entity2; strcpy((char *)&point.param.charValue, param); _savepoints.push_back(point); } SavePoint SavePoints::pop() { SavePoint point = _savepoints.front(); _savepoints.pop_front(); return point; } void SavePoints::pushAll(EntityIndex entity, ActionIndex action, uint32 param) { for (uint32 index = 1; index < 40; index++) { if ((EntityIndex)index != entity) push(entity, (EntityIndex)index, action, param); } } // Process all savepoints void SavePoints::process() { while (_savepoints.size() > 0 && getFlags()->isGameRunning) { SavePoint savepoint = pop(); // If this is a data savepoint, update the entity // otherwise, execute the callback if (!updateEntityFromData(savepoint)) { // Call requested callback Entity::Callback *callback = getCallback(savepoint.entity1); if (callback && callback->isValid()) { debugC(8, kLastExpressDebugLogic, "Savepoint: entity1=%s, action=%s, entity2=%s", ENTITY_NAME(savepoint.entity1), ACTION_NAME(savepoint.action), ENTITY_NAME(savepoint.entity2)); (*callback)(savepoint); } } } } void SavePoints::reset() { _savepoints.clear(); } ////////////////////////////////////////////////////////////////////////// // Data ////////////////////////////////////////////////////////////////////////// void SavePoints::addData(EntityIndex entity, ActionIndex action, uint32 param) { if (_data.size() >= _savePointsMaxSize) return; SavePointData data; data.entity1 = entity; data.action = action; data.param = param; _data.push_back(data); } ////////////////////////////////////////////////////////////////////////// // Callbacks ////////////////////////////////////////////////////////////////////////// void SavePoints::setCallback(EntityIndex index, Entity::Callback *callback) { if (index >= 40) error("[SavePoints::setCallback] Attempting to use an invalid entity index. Valid values 0-39, was %d", index); if (!callback || !callback->isValid()) error("[SavePoints::setCallback] Attempting to set an invalid callback for entity %s", ENTITY_NAME(index)); _callbacks[index] = callback; } Entity::Callback *SavePoints::getCallback(EntityIndex index) const { if (index >= 40) error("[SavePoints::getCallback] Attempting to use an invalid entity index. Valid values 0-39, was %d", index); return _callbacks[index]; } void SavePoints::call(EntityIndex entity2, EntityIndex entity1, ActionIndex action, uint32 param) const { SavePoint point; point.entity1 = entity1; point.action = action; point.entity2 = entity2; point.param.intValue = param; Entity::Callback *callback = getCallback(entity1); if (callback != NULL && callback->isValid()) { debugC(8, kLastExpressDebugLogic, "Savepoint: entity1=%s, action=%s, entity2=%s, param=%d", ENTITY_NAME(entity1), ACTION_NAME(action), ENTITY_NAME(entity2), param); (*callback)(point); } } void SavePoints::call(EntityIndex entity2, EntityIndex entity1, ActionIndex action, const char *param) const { SavePoint point; point.entity1 = entity1; point.action = action; point.entity2 = entity2; strcpy((char *)&point.param.charValue, param); Entity::Callback *callback = getCallback(entity1); if (callback != NULL && callback->isValid()) { debugC(8, kLastExpressDebugLogic, "Savepoint: entity1=%s, action=%s, entity2=%s, param=%s", ENTITY_NAME(entity1), ACTION_NAME(action), ENTITY_NAME(entity2), param); (*callback)(point); } } void SavePoints::callAndProcess() { SavePoint savepoint; // empty parameters // We ignore the kEntityPlayer callback in the list EntityIndex index = kEntityAnna; // Call all callbacks with empty parameters bool isRunning = getFlags()->isGameRunning; while (isRunning) { Entity::Callback *callback = getCallback(index); if (callback != NULL && callback->isValid()) { (*callback)(savepoint); isRunning = getFlags()->isGameRunning; } index = (EntityIndex)(index + 1); // Process all savepoints when done if (index >= 40) { if (isRunning) process(); return; } } } ////////////////////////////////////////////////////////////////////////// // Misc ////////////////////////////////////////////////////////////////////////// bool SavePoints::updateEntityFromData(const SavePoint &savepoint) { for (int i = 0; i < (int)_data.size(); i++) { // Not a data savepoint! if (!_data[i].entity1) return false; // Found our data! if (_data[i].entity1 == savepoint.entity1 && _data[i].action == savepoint.action) { debugC(8, kLastExpressDebugLogic, "Update entity from data: entity1=%s, action=%s, param=%d", ENTITY_NAME(_data[i].entity1), ACTION_NAME(_data[i].action), _data[i].param); // the SavePoint param value is the index of the entity call parameter to update getEntities()->get(_data[i].entity1)->getParamData()->updateParameters(_data[i].param); return true; } } return false; } ////////////////////////////////////////////////////////////////////////// // Serializable ////////////////////////////////////////////////////////////////////////// void SavePoints::saveLoadWithSerializer(Common::Serializer &s) { // Serialize savepoint data uint32 dataSize = (s.isLoading() ? _savePointsMaxSize : _data.size()); for (uint i = 0; i < dataSize; i++) { if (s.isLoading()) { SavePointData data; _data.push_back(data); } s.syncAsUint32LE(_data[i].entity1); s.syncAsUint32LE(_data[i].action); s.syncAsUint32LE(_data[i].entity2); s.syncAsUint32LE(_data[i].param); } // Skip uninitialized data if any s.skip((_savePointsMaxSize - dataSize) * 16); // Number of savepoints uint32 numSavepoints = _savepoints.size(); s.syncAsUint32LE(numSavepoints); // Savepoints if (s.isLoading()) { for (uint i = 0; i < numSavepoints; i++) { SavePoint point; s.syncAsUint32LE(point.entity1); s.syncAsUint32LE(point.action); s.syncAsUint32LE(point.entity2); s.syncAsUint32LE(point.param.intValue); _savepoints.push_back(point); if (_savepoints.size() >= _savePointsMaxSize) break; } } else { for (Common::List::iterator it = _savepoints.begin(); it != _savepoints.end(); ++it) { s.syncAsUint32LE((*it).entity1); s.syncAsUint32LE((*it).action); s.syncAsUint32LE((*it).entity2); s.syncAsUint32LE((*it).param.intValue); } } } ////////////////////////////////////////////////////////////////////////// // toString ////////////////////////////////////////////////////////////////////////// Common::String SavePoints::toString() { Common::String ret = ""; ret += "Savepoint Data\n"; for (uint i = 0; i < _data.size(); i++) ret += _data[i].toString() + "\n"; ret += "\nSavepoints\n"; for (Common::List::iterator it = _savepoints.begin(); it != _savepoints.end(); ++it) ret += (*it).toString() + "\n"; return ret; } } // End of namespace LastExpress