/* 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 "walk_mgr.h" #include "walk_location.h" #include "engines/pink/objects/actions/walk_action.h" #include "engines/pink/objects/actors/lead_actor.h" #include "engines/pink/archive.h" #include "pink/cel_decoder.h" namespace Pink { WalkMgr::WalkMgr() : _isWalking(false), _leadActor(nullptr) { } void WalkMgr::deserialize(Pink::Archive &archive) { _leadActor = static_cast(archive.readObject()); archive >> _locations; } WalkLocation *WalkMgr::findLocation(const Common::String &name) { auto it = Common::find_if(_locations.begin(), _locations.end(), [&name](WalkLocation *location) { return location->getName() == name; }); return (it != _locations.end()) ? *it : nullptr; } void WalkMgr::toConsole() { debug("WalkMgr:"); for (int i = 0; i < _locations.size(); ++i) { _locations[i]->toConsole(); } } void WalkMgr::start(WalkLocation *destination) { if (_isWalking) return; if (_current.name.empty()) { _current.name = _locations[0]->getName(); _current.coord = getLocationCoordinates(_locations[0]->getName()); } _destination = destination; if (_current.name == _destination->getName()) { end(); } else { _isWalking = true; WalkLocation *currentLocation = findLocation(_current.name); WalkShortestPath path(this); WalkLocation *nextLocation = path.next(currentLocation, _destination); initNextWayPoint(nextLocation); _leadActor->setAction(getWalkAction(), 0); } } void WalkMgr::initNextWayPoint(WalkLocation *location) { _next.name = location->getName(); _next.coord = getLocationCoordinates(location->getName()); } WalkAction *WalkMgr::getWalkAction() { Common::String walkActionName; if (_current.coord.z == _next.coord.z){ if (_next.coord.x > _current.coord.x){ walkActionName = Common::String::format("%dRight", _current.coord.z); } else walkActionName = Common::String::format("%dLeft", _next.coord.z); } else walkActionName = Common::String::format("%dTo%d", _current.coord.z, _next.coord.z); Action *action = _leadActor->findAction(walkActionName); return static_cast(action); } double WalkMgr::getLengthBetweenLocations(WalkLocation *first, WalkLocation *second) { Coordinates firstCoord = getLocationCoordinates(first->getName()); Coordinates secondCoord = getLocationCoordinates(second->getName()); return sqrt((secondCoord.x - firstCoord.x) * (secondCoord.x - firstCoord.x) + (secondCoord.y - firstCoord.y) * (secondCoord.y - firstCoord.y)); } WalkMgr::Coordinates WalkMgr::getLocationCoordinates(const Common::String &locationName) { Coordinates coords; ActionCEL *action = static_cast(_leadActor->findAction(locationName)); action->start(0); CelDecoder *decoder = action->getDecoder(); coords.x = decoder->getX() + decoder->getWidth() / 2; coords.y = decoder->getY() + decoder->getHeight() / 2; coords.z = action->getZ(); action->end(); return coords; } void WalkMgr::setCurrentWayPoint(WalkLocation *location) { _current.name = location->getName(); _current.coord = getLocationCoordinates(_current.name); } void WalkMgr::update() { if (_leadActor->isPlaying()) return; WalkShortestPath path(this); _current = _next; WalkLocation *next = path.next(findLocation(_current.name), _destination); if (next){ initNextWayPoint(next); _leadActor->setAction(getWalkAction(), 0); } else end(); } void WalkMgr::end() { _isWalking = false; _leadActor->onWalkEnd(); } } // End of namespace Pink