void ResourceProvider::shutdown() {
	_stateProvider->clear();

	// Flush the locations list
	for (CurrentList::const_iterator it = _locations.begin(); it != _locations.end(); it++) {
		Current *location = *it;

		_archiveLoader->returnRoot(_archiveLoader->buildArchiveName(location->getLevel(), location->getLocation()));
		_archiveLoader->returnRoot(_archiveLoader->buildArchiveName(location->getLevel()));

		delete location;
	}
	_locations.clear();

	// Return the global resources
	if (_global->getLevel()) {
		_archiveLoader->returnRoot(_archiveLoader->buildArchiveName(_global->getLevel()));
		_global->setLevel(nullptr);
	}

	if (_global->getRoot()) {
		_archiveLoader->returnRoot("x.xarc");
		_global->setRoot(nullptr);
	}

	_global->setCurrent(nullptr);
	_global->setInventory(nullptr);
	_global->setApril(nullptr);

	_archiveLoader->unloadUnused();
}
void ResourceProvider::purgeOldLocations() {
	while (_locations.size() > 2) {
		Current *location = _locations.front();

		_stateProvider->saveLocationState(location->getLevel(), location->getLocation());
		_stateProvider->saveLevelState(location->getLevel());

		_archiveLoader->returnRoot(_archiveLoader->buildArchiveName(location->getLevel(), location->getLocation()));
		_archiveLoader->returnRoot(_archiveLoader->buildArchiveName(location->getLevel()));

		delete location;

		_locations.pop_front();
	}

	_archiveLoader->unloadUnused();
}
void ResourceProvider::requestLocationChange(uint16 level, uint16 location) {
	Current *currentLocation = new Current();
	_locations.push_back(currentLocation);

	// Retrieve the level archive name
	Resources::Root *root = _global->getRoot();
	Resources::Level *rootLevelResource = root->findChildWithIndex<Resources::Level>(level);
	Common::String levelArchive = _archiveLoader->buildArchiveName(rootLevelResource);

	// Load the archive, and get the resource sub-tree root
	bool newlyLoaded = _archiveLoader->load(levelArchive);
	currentLocation->setLevel(_archiveLoader->useRoot<Resources::Level>(levelArchive));

	// If we just loaded a resource tree, restore its state
	if (newlyLoaded) {
		currentLocation->getLevel()->onAllLoaded();
		_stateProvider->restoreLevelState(currentLocation->getLevel());
	}

	// Retrieve the location archive name
	Resources::Level *levelResource = currentLocation->getLevel();
	Resources::Location *levelLocationResource = levelResource->findChildWithIndex<Resources::Location>(location);
	Common::String locationArchive = _archiveLoader->buildArchiveName(levelResource, levelLocationResource);

	// Load the archive, and get the resource sub-tree root
	newlyLoaded = _archiveLoader->load(locationArchive);
	currentLocation->setLocation(_archiveLoader->useRoot<Resources::Location>(locationArchive));

	if (currentLocation->getLocation()->has3DLayer()) {
		Resources::Layer3D *layer = currentLocation->getLocation()->findChildWithSubtype<Resources::Layer3D>(Resources::Layer::kLayer3D);
		currentLocation->setFloor(layer->findChild<Resources::Floor>());
		currentLocation->setCamera(layer->findChild<Resources::Camera>());
	} else {
		currentLocation->setFloor(nullptr);
		currentLocation->setCamera(nullptr);
	}

	// If we just loaded a resource tree, restore its state
	if (newlyLoaded) {
		currentLocation->getLocation()->onAllLoaded();
		_stateProvider->restoreLocationState(currentLocation->getLevel(), currentLocation->getLocation());
	}

	_locationChangeRequest = true;
}
Resources::Location *ResourceProvider::getLocation(uint16 level, uint16 location) const {
	Current *current = findLocation(level, location);

	if (current) {
		return current->getLocation();
	}

	return nullptr;
}
예제 #5
0
Command *Command::opRumbleScene(Script *script, int32 rumbleDuration, int32 pause) {
	Current *current = StarkGlobal->getCurrent();
	Location *location = current->getLocation();
	location->startRumble(rumbleDuration);

	if (pause) {
		script->pause(rumbleDuration);
		return this; // Stay on this command while the script is suspended
	} else {
		return nextCommand();
	}
}
예제 #6
0
ItemVisual *Speech::getCharacterItem() const {
	Current *current = StarkGlobal->getCurrent();
	if (!current) {
		return nullptr;
	}

	Location *location = current->getLocation();
	if (!location) {
		return nullptr;
	}

	return location->getCharacterItem(_character);
}
예제 #7
0
bool Console::Cmd_Location(int argc, const char **argv) {
	if (argc != 1) {
		debugPrintf("Display the current location.\n");
		debugPrintf("Usage :\n");
		debugPrintf("location\n");
		return true;
	}

	Current *current = StarkGlobal->getCurrent();

	debugPrintf("location: %02x %02x\n", current->getLevel()->getIndex(), current->getLocation()->getIndex());

	return true;
}
예제 #8
0
Command *Command::opFadeScene(Script *script, bool fadeOut, int32 fadeDuration, bool pause) {
	Current *current = StarkGlobal->getCurrent();
	Location *location = current->getLocation();
	if (fadeOut) {
		location->fadeOutInit(fadeDuration);
	} else {
		location->fadeInInit(fadeDuration);
	}

	if (pause) {
		script->pause(fadeDuration);
		return this; // Stay on this command while the script is suspended
	} else {
		return nextCommand();
	}
}
void ResourceProvider::commitActiveLocationsState() {
	// Save active location states
	for (CurrentList::const_iterator it = _locations.begin(); it != _locations.end(); it++) {
		_stateProvider->saveLocationState((*it)->getLevel(), (*it)->getLocation());
		_stateProvider->saveLevelState((*it)->getLevel());
	}

	_stateProvider->saveLevelState(_global->getLevel());

	// Save the current location "extended" state, to be able to restore them to the exact same state.
	Current *location = _global->getCurrent();
	_stateProvider->saveCurrentLocationState(location->getLevel(), location->getLocation());
	_stateProvider->saveCurrentLevelState(location->getLevel());

	_stateProvider->saveGlobalState(_global->getLevel());
}
예제 #10
0
void ResourceProvider::performLocationChange() {
	Current *current = _locations.back();
	Current *previous = _global->getCurrent();
	bool levelChanged = !previous || previous->getLevel() != current->getLevel();

	// Exit the previous location
	if (previous) {
		// Trigger location change scripts
		if (levelChanged) {
			runLocationChangeScripts(previous->getLevel(), Resources::Script::kCallModeExitLocation);
		}
		runLocationChangeScripts(previous->getLocation(), Resources::Script::kCallModeExitLocation);

		// Resources lifecycle update
		previous->getLocation()->onExitLocation();
		previous->getLevel()->onExitLocation();
		_global->getLevel()->onExitLocation();
	}

	// Clear all pointers to location objects in the UI instances
	StarkUserInterface->clearLocationDependentState();

	// Set the new current location
	_global->setCurrent(current);

	// Resources lifecycle update
	_global->getLevel()->onEnterLocation();
	current->getLevel()->onEnterLocation();
	current->getLocation()->onEnterLocation();

	if (current->getLocation()->has3DLayer()) {
		// Fetch the scene item for April
		current->setInteractive(Resources::Object::cast<Resources::ModelItem>(_global->getApril()->getSceneInstance()));
	}

	if (_restoreCurrentState) {
		_stateProvider->restoreGlobalState(_global->getLevel());
		_stateProvider->restoreCurrentLevelState(current->getLevel());
		_stateProvider->restoreCurrentLocationState(current->getLevel(), current->getLocation());
		_restoreCurrentState = false;
	} else {
		setAprilInitialPosition();
		setScrollInitialPosition();

		// Trigger location change scripts
		if (levelChanged) {
			runLocationChangeScripts(current->getLevel(), Resources::Script::kCallModeEnterLocation);
		}
		runLocationChangeScripts(current->getLocation(), Resources::Script::kCallModeEnterLocation);
	}

	purgeOldLocations();

	_locationChangeRequest = false;
}
예제 #11
0
Command *Command::opFullMotionVideoPlay(Script *script, const ResourceReference &movieRef, int32 unknown) {
	// Stop skipping frames
	StarkGlobal->setNormalSpeed();

	// Characters don't need to continue their previous action after the FMV ends
	Current *current = StarkGlobal->getCurrent();
	Location *location = current->getLocation();
	location->resetAnimationBlending();

	FMV *movie =  movieRef.resolve<FMV>();
	movie->requestPlayback();

	// Unconditional suspension
	script->suspend(movie);

	return this; // Stay on the same command while suspended
}
예제 #12
0
void GameInterface::skipCurrentSpeeches() {
	Current *current = StarkGlobal->getCurrent();

	if (!current) {
		return; // No current location, nothing to do
	}

	// Get all speeches
	Common::Array<Resources::Speech *> speeches;
	speeches.push_back(StarkGlobal->getLevel()->listChildrenRecursive<Resources::Speech>());
	speeches.push_back(current->getLevel()->listChildrenRecursive<Resources::Speech>());
	speeches.push_back(current->getLocation()->listChildrenRecursive<Resources::Speech>());

	// Stop them
	for (uint i = 0; i < speeches.size(); i++) {
		Resources::Speech *speech = speeches[i];
		if (speech->isPlaying()) {
			speech->stop();
		}
	}
}
예제 #13
0
Command *Command::opIsLocation2D() {
	Current *current = StarkGlobal->getCurrent();
	Location *location = current->getLocation();

	return nextCommandIf(!location->has3DLayer());
}
예제 #14
0
void ResourceProvider::setScrollInitialPosition() {
	Current *current = _global->getCurrent();
	Resources::Location *location = current->getLocation();
	location->scrollToCharacterImmediate();
}