void ActorFactory::createChar(Encounter* parent, PFMapCharInstance& data)
{
   GameObject* temp = new GameObject(parent, data.pos);

   temp->addComponent(new ActorComponent(temp, data.id));
   temp->addComponent(new RenderComponent(temp, data.sprite.first, data.sprite.second));

   // Get a reference to the actor component of our new character
   auto actor = temp->getComponent<ActorComponent>(ComponentType::ACTOR);

   actor->getCharacter().getRawData().name = data.name;
   actor->setTeam(data.team);

   // Construct and equip all of the items that this character is supposed to have equipped
   for (auto &item : data.equipped)
   {
      auto itemInstance = PFWeaponBuilder().load( item.second.id )->build();
      actor->getInventory().equippedItems().equipItem(item.first, itemInstance);
   }

   // Construct and equip all of the items that this character is supposed to have equipped
   for (auto &item : data.backpack)
   {
      auto itemInstance = PFWeaponBuilder().load( item.id )->build();
      actor->getInventory().backpack().addItem( itemInstance );
   }

   parent->addGameObj(temp);
}
Example #2
0
void SaveLoad::readEntry(SavegameType *type, EntityIndex *entity, uint32 *val, bool keepIndex) {
#define LOAD_ENTRY(name, func, val) { \
	uint32 _prevPosition = (uint32)_savegame->pos(); \
	func; \
	uint32 _count = (uint32)_savegame->pos() - _prevPosition; \
	debugC(kLastExpressDebugSavegame, "Savegame: Reading " #name ": %d bytes", _count); \
	if (_count != val) \
		error("SaveLoad::readEntry: Number of bytes read (%d) differ from expected count (%d)", _count, val); \
}

#define LOAD_ENTRY_ONLY(name, func) { \
	uint32 _prevPosition = (uint32)_savegame->pos(); \
	func; \
	uint32 _count = (uint32)_savegame->pos() - _prevPosition; \
	debugC(kLastExpressDebugSavegame, "Savegame: Reading " #name ": %d bytes", _count); \
}

	if (!type || !entity || !val)
		error("SaveLoad::readEntry: Invalid parameters passed!");

	// Load entry header
	SavegameEntryHeader entry;
	Common::Serializer ser(_savegame, NULL);
	entry.saveLoadWithSerializer(ser);

	if (!entry.isValid())
		error("SaveLoad::readEntry: entry header is invalid!");

	// Init type, entity & value
	*type = entry.type;
	*val = entry.value;

	// Save position
	uint32 originalPosition = (uint32)_savegame->pos();

	// Load game data
	LOAD_ENTRY("entity index", ser.syncAsUint32LE(*entity), 4);
	LOAD_ENTRY("state", getState()->saveLoadWithSerializer(ser), 4 + 4 + 4 + 4 + 1 + 4 + 4);
	LOAD_ENTRY("selected item", getInventory()->saveSelectedItem(ser), 4);
	LOAD_ENTRY("positions", getEntities()->savePositions(ser), 4 * 1000);
	LOAD_ENTRY("compartments", getEntities()->saveCompartments(ser), 4 * 16 * 2);
	LOAD_ENTRY("progress", getProgress().saveLoadWithSerializer(ser), 4 * 128);
	LOAD_ENTRY("events", getState()->syncEvents(ser), 512);
	LOAD_ENTRY("inventory", getInventory()->saveLoadWithSerializer(ser), 7 * 32);
	LOAD_ENTRY("objects", getObjects()->saveLoadWithSerializer(ser), 5 * 128);
	LOAD_ENTRY("entities", getEntities()->saveLoadWithSerializer(ser), 1262 * 40);
	LOAD_ENTRY_ONLY("sound", getSound()->saveLoadWithSerializer(ser));
	LOAD_ENTRY_ONLY("savepoints", getSavePoints()->saveLoadWithSerializer(ser));

	// Update chapter
	getProgress().chapter = entry.chapter;

	// Skip padding
	uint32 offset = _savegame->pos() - originalPosition;
	if (offset & 0xF) {
		_savegame->seek((~offset & 0xF) + 1, SEEK_SET);
	}
}
Example #3
0
bool Beetle::catchBeetle() {
	if (!_data)
		error("Beetle::catchBeetle: sequences have not been loaded!");

	if (getInventory()->getSelectedItem() == kItemMatchBox
	 && getInventory()->hasItem(kItemMatch)
	 && ABS((int16)(getCoords().x - _data->coordX)) < 10
	 && ABS((int16)(getCoords().y - _data->coordY)) < 10) {
		return true;
	}

	_data->field_D5 = 0;
	move();

	return false;
}
Example #4
0
void RohonDealer::cancelOrder(Order *order)
{
    //修改map中相应单子的状态,执行相应动作
    TRACE_LOG("RohonDealer::cancelOrder, orderid:%s.",order->getId().c_str());
    if(!started)
    {
        TRACE_LOG("RohonDealer::cancelOrder failed. sfit not started.");
        return;
    }
    //查看order状态,是否需要撤单
    if(order->isCanceled()||order->isDealed()||order->isRejected())
    {
        TRACE_LOG("RohonDealer::cancelOrder failed. orderid:%s is not in right status.",order->getId().c_str());
        return;
    }
    //从仓库中拿出ref
    int ref;
    EnterCriticalSection(&cs);
    RohonDealerInventory* pInventory = getInventory(order->getId());
    if(pInventory==NULL)
    {
        LeaveCriticalSection(&cs);
        TRACE_LOG("RohonDealer::cancelOrder failed. orderid:%s is not in this dealer.",order->getId().c_str());
        return;
    }
    ref = pInventory->localRef;
    LeaveCriticalSection(&cs);
    //执行相应动作
    if(0 != pUserSpi->CancelOrder(ref,order))
    {
        TRACE_LOG("RohonDealer::cancelOrder failed. orderid:%s 撤单直接失败",order->getId().c_str());
        return;
    }
    return;
}
void Food::description() const
{
	cout << "商品名称: " << getName() << endl;
	cout << "原价: " << getUnitPrice() << endl;
	cout << "折扣价: " << getUnitPrice() * getDiscount() << endl;
	cout << "折扣系数: " << getDiscount() << endl;
	cout << "库存: " << getInventory() << endl;
	cout << "商品详情: " << endl << getDetails() << endl;
}
ItemStack PlayerSAO::getWieldedItem() const
{
	const Inventory *inv = getInventory();
	ItemStack ret;
	const InventoryList *mlist = inv->getList(getWieldList());
	if (mlist && getWieldIndex() < (s32)mlist->getSize())
		ret = mlist->getItem(getWieldIndex());
	return ret;
}
Example #7
0
bool ServerActiveObject::setWieldedItem(const ItemStack &item)
{
	if(Inventory *inv = getInventory()) {
		if (InventoryList *list = inv->getList(getWieldList())) {
			list->changeItem(getWieldIndex(), item);
			return true;
		}
	}
	return false;
}
Example #8
0
ItemStack ServerActiveObject::getWieldedItem() const
{
	const Inventory *inv = getInventory();
	if(inv)
	{
		const InventoryList *list = inv->getList(getWieldList());
		if(list && (getWieldIndex() < (s32)list->getSize())) 
			return list->getItem(getWieldIndex());
	}
	return ItemStack();
}
bool PlayerSAO::setWieldedItem(const ItemStack &item)
{
	Inventory *inv = getInventory();
	if (inv) {
		InventoryList *mlist = inv->getList(getWieldList());
		if (mlist) {
			mlist->changeItem(getWieldIndex(), item);
			return true;
		}
	}
	return false;
}
ItemStack PlayerSAO::getWieldedItemOrHand() const
{
	const Inventory *inv = getInventory();
	ItemStack ret;
	const InventoryList *mlist = inv->getList(getWieldList());
	if (mlist && getWieldIndex() < (s32)mlist->getSize())
		ret = mlist->getItem(getWieldIndex());
	if (ret.name.empty()) {
		const InventoryList *hlist = inv->getList("hand");
		if (hlist)
			ret = hlist->getItem(0);
	}
	return ret;
}
Example #11
0
bool PlayerSAO::setWieldedItem(const ItemStack &item)
{
	Inventory *inv = getInventory();
	if (inv) {
		InventoryList *mlist = inv->getList(getWieldList());
		if (mlist) {
			ItemStack olditem = mlist->getItem(getWieldIndex());
			if (olditem.name.empty()) {
				InventoryList *hlist = inv->getList("hand");
				if (hlist) {
					hlist->changeItem(0, item);
					return true;
				}
			}
			mlist->changeItem(getWieldIndex(), item);
			return true;
		}
	}
	return false;
}
Example #12
0
void Beetle::update() {
	if (!_data)
		error("Beetle::update: sequences have not been loaded!");

	if (!_data->isLoaded)
		return;

	move();

	if (_data->field_D5)
		_data->field_D5--;

	if (_data->currentSequence && _data->indexes[_data->offset] != 29) {
		drawUpdate();
		return;
	}

	if (getInventory()->get(kItemBeetle)->location == kObjectLocation3) {
		if ((!_data->field_DD && rnd(10) < 1)
		  || (_data->field_DD && rnd(30) < 1)
		  || rnd(100) < 1) {

			_data->field_DD++;
			if (_data->field_DD > 3)
				_data->field_DD = 0;

			updateData(24);

			_data->coordX = (int16)(rnd(250) + 190);
			_data->coordOffset = (int16)(rnd(5) + 5);

			if (_data->field_D9 > 1)
				_data->field_D9--;

			drawUpdate();
		}
	}
}
Example #13
0
void Beetle::load() {
	// Only load in chapter 2 & 3
	if (getProgress().chapter != kChapter2 &&  getProgress().chapter != kChapter3)
		return;

	// Already loaded
	if (_data)
		return;

	// Do not load if beetle is in the wrong location
	if (getInventory()->get(kItemBeetle)->location != kObjectLocation3)
		return;

	///////////////////////
	// Load Beetle data
	_data = new BeetleData();

	// Load sequences
	_data->sequences.push_back(loadSequence("BW000.seq"));        // 0
	_data->sequences.push_back(loadSequence("BT000045.seq"));
	_data->sequences.push_back(loadSequence("BT045000.seq"));
	_data->sequences.push_back(loadSequence("BW045.seq"));
	_data->sequences.push_back(loadSequence("BT045090.seq"));
	_data->sequences.push_back(loadSequence("BT090045.seq"));     // 5
	_data->sequences.push_back(loadSequence("BW090.seq"));
	_data->sequences.push_back(loadSequence("BT090135.seq"));
	_data->sequences.push_back(loadSequence("BT135090.seq"));
	_data->sequences.push_back(loadSequence("BW135.seq"));
	_data->sequences.push_back(loadSequence("BT135180.seq"));     // 10
	_data->sequences.push_back(loadSequence("BT180135.seq"));
	_data->sequences.push_back(loadSequence("BW180.seq"));
	_data->sequences.push_back(loadSequence("BT180225.seq"));
	_data->sequences.push_back(loadSequence("BT225180.seq"));
	_data->sequences.push_back(loadSequence("BW225.seq"));        // 15
	_data->sequences.push_back(loadSequence("BT225270.seq"));
	_data->sequences.push_back(loadSequence("BT270225.seq"));
	_data->sequences.push_back(loadSequence("BW270.seq"));
	_data->sequences.push_back(loadSequence("BT270315.seq"));
	_data->sequences.push_back(loadSequence("BT315270.seq"));     // 20
	_data->sequences.push_back(loadSequence("BW315.seq"));
	_data->sequences.push_back(loadSequence("BT315000.seq"));
	_data->sequences.push_back(loadSequence("BT000315.seq"));
	_data->sequences.push_back(loadSequence("BA135.seq"));
	_data->sequences.push_back(loadSequence("BL045.seq"));        // 25
	_data->sequences.push_back(loadSequence("BL000.seq"));
	_data->sequences.push_back(loadSequence("BL315.seq"));
	_data->sequences.push_back(loadSequence("BL180.seq"));

	// Init fields
	_data->field_74 = 0;

	// Check that all sequences are loaded properly
	_data->isLoaded = true;
	for (int i = 0; i < (int)_data->sequences.size(); i++) {
		if (!_data->sequences[i]->isLoaded()) {
			_data->isLoaded = false;
			break;
		}
	}

	_data->field_D9 = 10;
	_data->coordOffset = 5;
	_data->coordY = 178;
	_data->currentSequence = 0;
	_data->offset = 0;
	_data->frame = NULL;
	_data->field_D5 = 0;
	_data->indexes[0] = 29;
	_data->field_DD = 0;
}
Example #14
0
int Yeast::inventory() const { return getInventory("quanta").toInt(); }
Example #15
0
// inventory must be handled separately, to my great annoyance
double Fermentable::inventory() const 
{ 
   return getInventory("amount").toDouble();
}
Example #16
0
bool Menu::handleEvent(StartMenuAction action, Common::EventType type) {
	bool clicked = (type == Common::EVENT_LBUTTONUP);

	switch(action) {
	default:
		hideOverlays();
		break;

	//////////////////////////////////////////////////////////////////////////
	case kMenuCredits:
		if (hasTimeDelta()) {
			hideOverlays();
			break;
		}

		if (clicked) {
			showFrame(kOverlayEggButtons, kButtonCreditsPushed, true);
			showFrame(kOverlayTooltip, -1, true);

			getSound()->playSound(kEntityPlayer, "LIB046");

			hideOverlays();

			_isShowingCredits = true;
			_creditsSequenceIndex = 0;

			showFrame(kOverlayCredits, 0, true);
		} else {
			// TODO check flags ?

			showFrame(kOverlayEggButtons, kButtonCredits, true);
			showFrame(kOverlayTooltip, kTooltipCredits, true);
		}
		break;

	//////////////////////////////////////////////////////////////////////////
	case kMenuQuitGame:
		showFrame(kOverlayTooltip, kTooltipQuit, true);

		if (clicked) {
			showFrame(kOverlayButtons, kButtonQuitPushed, true);

			getSound()->clearStatus();
			getSound()->updateQueue();
			getSound()->playSound(kEntityPlayer, "LIB046");

			// FIXME uncomment when sound queue is properly implemented
			/*while (getSound()->isBuffered("LIB046"))
				getSound()->updateQueue();*/

			getFlags()->shouldRedraw = false;

			Engine::quitGame();

			return false;
		} else {
			showFrame(kOverlayButtons, kButtonQuit, true);
		}
		break;

	//////////////////////////////////////////////////////////////////////////
	case kMenuCase4:
		if (clicked)
			_index = 0;
		// fall down to kMenuContinue

	//////////////////////////////////////////////////////////////////////////
	case kMenuContinue: {
		if (hasTimeDelta()) {
			hideOverlays();
			break;
		}

		// Determine the proper CD archive
		ArchiveIndex cd = kArchiveCd1;
		if (getProgress().chapter > kChapter1)
			cd = (getProgress().chapter > kChapter3) ? kArchiveCd3 : kArchiveCd2;

		// Show tooltips & buttons to start a game, continue a game or load the proper cd
		if (ResourceManager::isArchivePresent(cd)) {
			if (_isGameStarted) {
				showFrame(kOverlayEggButtons, kButtonContinue, true);

				if (_lastIndex == _index) {
					showFrame(kOverlayTooltip, getSaveLoad()->isGameFinished(_index, _lastIndex) ? kTooltipViewGameEnding : kTooltipContinueGame, true);
				} else {
					showFrame(kOverlayTooltip, kTooltipContinueRewoundGame, true);
				}

			} else {
				showFrame(kOverlayEggButtons, kButtonShield, true);
				showFrame(kOverlayTooltip, kTooltipPlayNewGame, true);
			}
		} else {
			showFrame(kOverlayEggButtons, -1, true);
			showFrame(kOverlayTooltip, cd - 1, true);
		}

		if (!clicked)
			break;

		// Try loading the archive file
		if (!_engine->getResourceManager()->loadArchive(cd))
			break;

		// Load the train data file and setup game
		getScenes()->loadSceneDataFile(cd);
		showFrame(kOverlayTooltip, -1, true);
		getSound()->playSound(kEntityPlayer, "LIB046");

		// Setup new game
		getSavePoints()->reset();
		setLogicEventHandlers();

		if (_index) {
			getSound()->processEntry(SoundManager::kSoundType11);
		} else {
			if (!getFlags()->mouseRightClick) {
				getScenes()->loadScene((SceneIndex)(5 * _gameId + 3));

				if (!getFlags()->mouseRightClick) {
					getScenes()->loadScene((SceneIndex)(5 * _gameId + 4));

					if (!getFlags()->mouseRightClick) {
						getScenes()->loadScene((SceneIndex)(5 * _gameId + 5));

						if (!getFlags()->mouseRightClick) {
							getSound()->processEntry(SoundManager::kSoundType11);

							// Show intro
							Animation animation;
							if (animation.load(getArchive("1601.nis")))
								animation.play();

							getEvent(kEventIntro) = 1;
						}
					}
				}
			}

			if (!getEvent(kEventIntro))	{
				getEvent(kEventIntro) = 1;

				getSound()->processEntry(SoundManager::kSoundType11);
			}
		}

		// Setup game
		getFlags()->isGameRunning = true;
		startGame();

		if (!_isShowingMenu)
			getInventory()->show();

		return false;
	}

	//////////////////////////////////////////////////////////////////////////
	case kMenuSwitchSaveGame:
		if (hasTimeDelta()) {
			hideOverlays();
			break;
		}

		if (clicked) {
			showFrame(kOverlayAcorn, 1, true);
			showFrame(kOverlayTooltip, -1, true);
			getSound()->playSound(kEntityPlayer, "LIB047");

			// Setup new menu screen
			switchGame();
			setup();

			// Set fight state to 0
			getFight()->resetState();

			return true;
		}

		// TODO Check for flag

		showFrame(kOverlayAcorn, 0, true);

		if (_isGameStarted) {
			showFrame(kOverlayTooltip, kTooltipSwitchBlueGame, true);
			break;
		}

		if (_gameId == kGameGold) {
			showFrame(kOverlayTooltip, kTooltipSwitchBlueGame, true);
			break;
		}

		if (!SaveLoad::isSavegameValid(getNextGameId())) {
			showFrame(kOverlayTooltip, kTooltipStartAnotherGame, true);
			break;
		}

		// Stupid tooltips ids are not in order, so we can't just increment them...
		switch(_gameId) {
		default:
			break;

		case kGameBlue:
			showFrame(kOverlayTooltip, kTooltipSwitchRedGame, true);
			break;

		case kGameRed:
			showFrame(kOverlayTooltip, kTooltipSwitchGreenGame, true);
			break;

		case kGameGreen:
			showFrame(kOverlayTooltip, kTooltipSwitchPurpleGame, true);
			break;

		case kGamePurple:
			showFrame(kOverlayTooltip, kTooltipSwitchTealGame, true);
			break;

		case kGameTeal:
			showFrame(kOverlayTooltip, kTooltipSwitchGoldGame, true);
			break;
		}
		break;

	//////////////////////////////////////////////////////////////////////////
	case kMenuRewindGame:
		if (!_index || _currentTime < _time) {
			hideOverlays();
			break;
		}

		if (clicked) {
			if (hasTimeDelta())
				_handleTimeDelta = false;

			showFrame(kOverlayEggButtons, kButtonRewindPushed, true);
			showFrame(kOverlayTooltip, -1, true);

			getSound()->playSound(kEntityPlayer, "LIB046");

			rewindTime();

			_handleTimeDelta = false;
		} else {
			showFrame(kOverlayEggButtons, kButtonRewind, true);
			showFrame(kOverlayTooltip, kTooltipRewind, true);
		}
		break;

	//////////////////////////////////////////////////////////////////////////
	case kMenuForwardGame:
		if (_lastIndex <= _index || _currentTime > _time) {
			hideOverlays();
			break;
		}

		if (clicked) {
			if (hasTimeDelta())
				_handleTimeDelta = false;

			showFrame(kOverlayEggButtons, kButtonForwardPushed, true);
			showFrame(kOverlayTooltip, -1, true);

			getSound()->playSound(kEntityPlayer, "LIB046");

			forwardTime();

			_handleTimeDelta = false;
		} else {
			showFrame(kOverlayEggButtons, kButtonForward, true);
			showFrame(kOverlayTooltip, kTooltipFastForward, true);
		}
		break;

	//////////////////////////////////////////////////////////////////////////
	case kMenuParis:
		moveToCity(kParis, clicked);
		break;

	//////////////////////////////////////////////////////////////////////////
	case kMenuStrasBourg:
		moveToCity(kStrasbourg, clicked);
		break;

	//////////////////////////////////////////////////////////////////////////
	case kMenuMunich:
		moveToCity(kMunich, clicked);
		break;

	//////////////////////////////////////////////////////////////////////////
	case kMenuVienna:
		moveToCity(kVienna, clicked);
		break;

	//////////////////////////////////////////////////////////////////////////
	case kMenuBudapest:
		moveToCity(kBudapest, clicked);
		break;

	//////////////////////////////////////////////////////////////////////////
	case kMenuBelgrade:
		moveToCity(kBelgrade, clicked);
		break;

	//////////////////////////////////////////////////////////////////////////
	case kMenuConstantinople:
		moveToCity(kConstantinople, clicked);
		break;

	//////////////////////////////////////////////////////////////////////////
	case kMenuDecreaseVolume:
		if (hasTimeDelta()) {
			hideOverlays();
			break;
		}

		// Cannot decrease volume further
		if (getVolume() == 0) {
			showFrame(kOverlayButtons, kButtonVolume, true);
			showFrame(kOverlayTooltip, -1, true);
			break;
		}

		showFrame(kOverlayTooltip, kTooltipVolumeDown, true);

		// Show highlight on button & adjust volume if needed
		if (clicked) {
			showFrame(kOverlayButtons, kButtonVolumeDownPushed, true);
			getSound()->playSound(kEntityPlayer, "LIB046");
			setVolume(getVolume() - 1);

			getSaveLoad()->saveVolumeBrightness();

			uint32 nextFrameCount = getFrameCount() + 15;
			while (nextFrameCount > getFrameCount()) {
				_engine->pollEvents();

				getSound()->updateQueue();
			}
		} else {
			showFrame(kOverlayButtons, kButtonVolumeDown, true);
		}
		break;

	//////////////////////////////////////////////////////////////////////////
	case kMenuIncreaseVolume:
		if (hasTimeDelta()) {
			hideOverlays();
			break;
		}

		// Cannot increase volume further
		if (getVolume() >= 7) {
			showFrame(kOverlayButtons, kButtonVolume, true);
			showFrame(kOverlayTooltip, -1, true);
			break;
		}

		showFrame(kOverlayTooltip, kTooltipVolumeUp, true);

		// Show highlight on button & adjust volume if needed
		if (clicked) {
			showFrame(kOverlayButtons, kButtonVolumeUpPushed, true);
			getSound()->playSound(kEntityPlayer, "LIB046");
			setVolume(getVolume() + 1);

			getSaveLoad()->saveVolumeBrightness();

			uint32 nextFrameCount = getFrameCount() + 15;
			while (nextFrameCount > getFrameCount()) {
				_engine->pollEvents();

				getSound()->updateQueue();
			}
		} else {
			showFrame(kOverlayButtons, kButtonVolumeUp, true);
		}
		break;

	//////////////////////////////////////////////////////////////////////////
	case kMenuDecreaseBrightness:
		if (hasTimeDelta()) {
			hideOverlays();
			break;
		}

		// Cannot increase brightness further
		if (getBrightness() == 0) {
			showFrame(kOverlayButtons, kButtonBrightness, true);
			showFrame(kOverlayTooltip, -1, true);
			break;
		}

		showFrame(kOverlayTooltip, kTooltipBrightnessDown, true);

		// Show highlight on button & adjust brightness if needed
		if (clicked) {
			showFrame(kOverlayButtons, kButtonBrightnessDownPushed, true);
			getSound()->playSound(kEntityPlayer, "LIB046");
			setBrightness(getBrightness() - 1);

			getSaveLoad()->saveVolumeBrightness();

			// Reshow the background and frames (they will pick up the new brightness through the GraphicsManager)
			_engine->getGraphicsManager()->draw(getScenes()->get((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2)), GraphicsManager::kBackgroundC, true);
			showFrame(kOverlayTooltip, kTooltipBrightnessDown, false);
			showFrame(kOverlayButtons, kButtonBrightnessDownPushed, false);
		} else {
			showFrame(kOverlayButtons, kButtonBrightnessDown, true);
		}
		break;

	//////////////////////////////////////////////////////////////////////////
	case kMenuIncreaseBrightness:
		if (hasTimeDelta()) {
			hideOverlays();
			break;
		}

		// Cannot increase brightness further
		if (getBrightness() >= 6) {
			showFrame(kOverlayButtons, kButtonBrightness, true);
			showFrame(kOverlayTooltip, -1, true);
			break;
		}

		showFrame(kOverlayTooltip, kTooltipBrightnessUp, true);

		// Show highlight on button & adjust brightness if needed
		if (clicked) {
			showFrame(kOverlayButtons, kButtonBrightnessUpPushed, true);
			getSound()->playSound(kEntityPlayer, "LIB046");
			setBrightness(getBrightness() + 1);

			getSaveLoad()->saveVolumeBrightness();

			// Reshow the background and frames (they will pick up the new brightness through the GraphicsManager)
			_engine->getGraphicsManager()->draw(getScenes()->get((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2)), GraphicsManager::kBackgroundC, true);
			showFrame(kOverlayTooltip, kTooltipBrightnessUp, false);
			showFrame(kOverlayButtons, kButtonBrightnessUpPushed, false);
		} else {
			showFrame(kOverlayButtons, kButtonBrightnessUp, true);
		}
		break;
	}

	return true;
}
Example #17
0
//////////////////////////////////////////////////////////////////////////
// Show the intro and load the main menu scene
void Menu::show(bool doSavegame, SavegameType type, uint32 value) {

	if (_isShowingMenu)
		return;

	_isShowingMenu = true;
	getEntities()->reset();

	// If no blue savegame exists, this might be the first time we start the game, so we show the full intro
	if (!getFlags()->mouseRightClick) {
		if (!SaveLoad::isSavegameValid(kGameBlue) && _engine->getResourceManager()->loadArchive(kArchiveCd1)) {

			if (!_hasShownIntro) {
				// Show Broderbrund logo
				Animation animation;
				if (animation.load(getArchive("1930.nis")))
					animation.play();

				getFlags()->mouseRightClick = false;

				// Play intro music
				getSound()->playSoundWithSubtitles("MUS001.SND", SoundManager::kFlagMusic, kEntityPlayer);

				// Show The Smoking Car logo
				if (animation.load(getArchive("1931.nis")))
					animation.play();

				_hasShownIntro = true;
			}
		} else {
			// Only show the quick intro
			if (!_hasShownStartScreen) {
				getSound()->playSoundWithSubtitles("MUS018.SND", SoundManager::kFlagMusic, kEntityPlayer);
				getScenes()->loadScene(kSceneStartScreen);

				// Original game waits 60 frames and loops Sound::unknownFunction1 unless the right button is pressed
				uint32 nextFrameCount = getFrameCount() + 60;
				while (getFrameCount() < nextFrameCount) {
					_engine->pollEvents();

					if (getFlags()->mouseRightClick)
						break;

					getSound()->updateQueue();
				}
			}
		}
	}

	_hasShownStartScreen = true;

	// Init Menu
	init(doSavegame, type, value);

	// Setup sound
	getSound()->unknownFunction4();
	getSound()->resetQueue(SoundManager::kSoundType11, SoundManager::kSoundType13);
	if (getSound()->isBuffered("TIMER"))
		getSound()->removeFromQueue("TIMER");

	// Init flags & misc
	_isShowingCredits = false;
	_handleTimeDelta = hasTimeDelta();
	getInventory()->unselectItem();

	// Set Cursor type
	_engine->getCursor()->setStyle(kCursorNormal);
	_engine->getCursor()->show(true);

	setup();
	checkHotspots();

	// Set event handlers
	SET_EVENT_HANDLERS(Menu, this);
}
Example #18
0
ScValue *AdObject::scGetProperty(const Common::String &name) {
	_scValue->setNULL();

	//////////////////////////////////////////////////////////////////////////
	// Type
	//////////////////////////////////////////////////////////////////////////
	if (name == "Type") {
		_scValue->setString("object");
		return _scValue;
	}

	//////////////////////////////////////////////////////////////////////////
	// Active
	//////////////////////////////////////////////////////////////////////////
	else if (name == "Active") {
		_scValue->setBool(_active);
		return _scValue;
	}

	//////////////////////////////////////////////////////////////////////////
	// IgnoreItems
	//////////////////////////////////////////////////////////////////////////
	else if (name == "IgnoreItems") {
		_scValue->setBool(_ignoreItems);
		return _scValue;
	}

	//////////////////////////////////////////////////////////////////////////
	// SceneIndependent
	//////////////////////////////////////////////////////////////////////////
	else if (name == "SceneIndependent") {
		_scValue->setBool(_sceneIndependent);
		return _scValue;
	}

	//////////////////////////////////////////////////////////////////////////
	// SubtitlesWidth
	//////////////////////////////////////////////////////////////////////////
	else if (name == "SubtitlesWidth") {
		_scValue->setInt(_subtitlesWidth);
		return _scValue;
	}

	//////////////////////////////////////////////////////////////////////////
	// SubtitlesPosRelative
	//////////////////////////////////////////////////////////////////////////
	else if (name == "SubtitlesPosRelative") {
		_scValue->setBool(_subtitlesModRelative);
		return _scValue;
	}

	//////////////////////////////////////////////////////////////////////////
	// SubtitlesPosX
	//////////////////////////////////////////////////////////////////////////
	else if (name == "SubtitlesPosX") {
		_scValue->setInt(_subtitlesModX);
		return _scValue;
	}

	//////////////////////////////////////////////////////////////////////////
	// SubtitlesPosY
	//////////////////////////////////////////////////////////////////////////
	else if (name == "SubtitlesPosY") {
		_scValue->setInt(_subtitlesModY);
		return _scValue;
	}

	//////////////////////////////////////////////////////////////////////////
	// SubtitlesPosXCenter
	//////////////////////////////////////////////////////////////////////////
	else if (name == "SubtitlesPosXCenter") {
		_scValue->setBool(_subtitlesModXCenter);
		return _scValue;
	}

	//////////////////////////////////////////////////////////////////////////
	// NumItems (RO)
	//////////////////////////////////////////////////////////////////////////
	else if (name == "NumItems") {
		_scValue->setInt(getInventory()->_takenItems.size());
		return _scValue;
	}

	//////////////////////////////////////////////////////////////////////////
	// ParticleEmitter (RO)
	//////////////////////////////////////////////////////////////////////////
	else if (name == "ParticleEmitter") {
		if (_partEmitter) {
			_scValue->setNative(_partEmitter, true);
		} else {
			_scValue->setNULL();
		}

		return _scValue;
	}

	//////////////////////////////////////////////////////////////////////////
	// NumAttachments (RO)
	//////////////////////////////////////////////////////////////////////////
	else if (name == "NumAttachments") {
		_scValue->setInt(_attachmentsPre.size() + _attachmentsPost.size());
		return _scValue;
	} else {
		return BaseObject::scGetProperty(name);
	}
}
void Server::handleCommand_Interact(NetworkPacket* pkt) {
	const auto peer_id = pkt->getPeerId();
	auto & packet = *(pkt->packet);
	auto player = m_env->getPlayer(pkt->getPeerId());
	if (!player) {
		m_con.DisconnectPeer(pkt->getPeerId());
		return;
	}
	auto playersao = player->getPlayerSAO();
	if (!playersao) {
		m_con.DisconnectPeer(pkt->getPeerId());
		return;
	}

	u8 action;
	u16 item_i;
	PointedThing pointed;

	packet[TOSERVER_INTERACT_ACTION].convert(action);
	packet[TOSERVER_INTERACT_ITEM].convert(item_i);
	packet[TOSERVER_INTERACT_POINTED_THING].convert(pointed);

	if(player->hp == 0) {
		verbosestream << "TOSERVER_INTERACT: " << player->getName()
		              << " tried to interact, but is dead!" << std::endl;
		return;
	}

	MAP_NOTHREAD_LOCK((&m_env->getMap()));

	v3f player_pos = playersao->getLastGoodPosition();

	// Update wielded item
	playersao->setWieldIndex(item_i);

	// Get pointed to node (undefined if not POINTEDTYPE_NODE)
	v3s16 p_under = pointed.node_undersurface;
	v3s16 p_above = pointed.node_abovesurface;

	// Get pointed to object (NULL if not POINTEDTYPE_OBJECT)
	ServerActiveObject *pointed_object = NULL;
	if(pointed.type == POINTEDTHING_OBJECT) {
		pointed_object = m_env->getActiveObject(pointed.object_id);
		if(pointed_object == NULL) {
			verbosestream << "TOSERVER_INTERACT: "
			              "pointed object is NULL" << std::endl;
			return;
		}

	}

	v3f pointed_pos_under = player_pos;
	v3f pointed_pos_above = player_pos;
	if(pointed.type == POINTEDTHING_NODE) {
		pointed_pos_under = intToFloat(p_under, BS);
		pointed_pos_above = intToFloat(p_above, BS);
	} else if(pointed.type == POINTEDTHING_OBJECT) {
		pointed_pos_under = pointed_object->getBasePosition();
		pointed_pos_above = pointed_pos_under;
	}

	/*
		Check that target is reasonably close
		(only when digging or placing things)
	*/
	static const bool enable_anticheat = !g_settings->getBool("disable_anticheat");
	if ((action == 0 || action == 2 || action == 3) &&
	        (enable_anticheat && !isSingleplayer())) {
		float d = player_pos.getDistanceFrom(pointed_pos_under);
		float max_d = BS * 14; // Just some large enough value
		if(d > max_d) {
			actionstream << "Player " << player->getName()
			             << " tried to access " << pointed.dump()
			             << " from too far: "
			             << "d=" << d << ", max_d=" << max_d
			             << ". ignoring." << std::endl;
			// Re-send block to revert change on client-side
			RemoteClient *client = getClient(peer_id);
			v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
			client->SetBlockNotSent(blockpos);
			// Call callbacks
			m_script->on_cheat(playersao, "interacted_too_far");
			// Do nothing else
			return;
		}
	}

	/*
		Make sure the player is allowed to do it
	*/
	if(!checkPriv(player->getName(), "interact")) {
		actionstream << player->getName() << " attempted to interact with "
		             << pointed.dump() << " without 'interact' privilege"
		             << std::endl;
		// Re-send block to revert change on client-side
		RemoteClient *client = getClient(peer_id);
		// Digging completed -> under
		if(action == 2) {
			v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
			client->SetBlockNotSent(blockpos);
		}
		// Placement -> above
		if(action == 3) {
			v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
			client->SetBlockNotSent(blockpos);
		}
		stat.add("interact_denied", player->getName());
		return;
	}

	/*
		If something goes wrong, this player is to blame
	*/
	RollbackScopeActor rollback_scope(m_rollback,
	                                  std::string("player:") + player->getName());

	/*
		0: start digging or punch object
	*/
	if(action == 0) {
		if(pointed.type == POINTEDTHING_NODE) {
			/*
				NOTE: This can be used in the future to check if
				somebody is cheating, by checking the timing.
			*/
			MapNode n = m_env->getMap().getNode(p_under);

			if (!n) {
				infostream << "Server: Not punching: Node not found."
				           << " Adding block to emerge queue."
				           << std::endl;
				m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
			}

			if(n.getContent() != CONTENT_IGNORE)
				m_script->node_on_punch(p_under, n, playersao, pointed);
			// Cheat prevention
			playersao->noCheatDigStart(p_under);
		} else if(pointed.type == POINTEDTHING_OBJECT) {
			// Skip if object has been removed
			if(pointed_object->m_removed)
				return;

			actionstream << player->getName() << " punches object "
			             << pointed.object_id << ": "
			             << pointed_object->getDescription() << std::endl;

			ItemStack punchitem = playersao->getWieldedItem();
			ToolCapabilities toolcap =
			    punchitem.getToolCapabilities(m_itemdef);
			v3f dir = (pointed_object->getBasePosition() -
			           (player->getPosition() + player->getEyeOffset())
			          ).normalize();
			float time_from_last_punch =
			    playersao->resetTimeFromLastPunch();

			s16 src_original_hp = pointed_object->getHP();
			s16 dst_origin_hp = playersao->getHP();

			pointed_object->punch(dir, &toolcap, playersao,
			                      time_from_last_punch);

			// If the object is a player and its HP changed
			if (src_original_hp != pointed_object->getHP() &&
			        pointed_object->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
				SendPlayerHPOrDie(((PlayerSAO*)pointed_object));
			}

			// If the puncher is a player and its HP changed
			if (dst_origin_hp != playersao->getHP()) {
				SendPlayerHPOrDie(playersao);
			}

			stat.add("punch", player->getName());
		}

	} // action == 0

	/*
		1: stop digging
	*/
	else if(action == 1) {
	} // action == 1

	/*
		2: Digging completed
	*/
	else if(action == 2) {
		// Only digging of nodes
		if(pointed.type == POINTEDTHING_NODE) {
			MapNode n = m_env->getMap().getNode(p_under);
			if (!n) {
				infostream << "Server: Not finishing digging: Node not found."
				           << " Adding block to emerge queue."
				           << std::endl;
				m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
			}

			/* Cheat prevention */
			bool is_valid_dig = true;
			if (enable_anticheat && !isSingleplayer()) {
				v3s16 nocheat_p = playersao->getNoCheatDigPos();
				float nocheat_t = playersao->getNoCheatDigTime();
				playersao->noCheatDigEnd();
				// If player didn't start digging this, ignore dig
				if(nocheat_p != p_under) {
					infostream << "Server: NoCheat: " << player->getName()
					           << " started digging "
					           << PP(nocheat_p) << " and completed digging "
					           << PP(p_under) << "; not digging." << std::endl;
					is_valid_dig = false;
					// Call callbacks
					m_script->on_cheat(playersao, "finished_unknown_dig");
				}
				// Get player's wielded item
				ItemStack playeritem;
				InventoryList *mlist = playersao->getInventory()->getList("main");
				if(mlist != NULL)
					playeritem = mlist->getItem(playersao->getWieldIndex());
				ToolCapabilities playeritem_toolcap =
				    playeritem.getToolCapabilities(m_itemdef);
				// Get diggability and expected digging time
				DigParams params = getDigParams(m_nodedef->get(n).groups,
				                                &playeritem_toolcap);
				// If can't dig, try hand
				if(!params.diggable) {
					const ItemDefinition &hand = m_itemdef->get("");
					const ToolCapabilities *tp = hand.tool_capabilities;
					if(tp)
						params = getDigParams(m_nodedef->get(n).groups, tp);
				}
				// If can't dig, ignore dig
				if(!params.diggable) {
					infostream << "Server: NoCheat: " << player->getName()
					           << " completed digging " << PP(p_under)
					           << ", which is not diggable with tool. not digging."
					           << std::endl;
					is_valid_dig = false;
					// Call callbacks
					m_script->on_cheat(playersao, "dug_unbreakable");
				}
				// Check digging time
				// If already invalidated, we don't have to
				if(!is_valid_dig) {
					// Well not our problem then
				}
				// Clean and long dig
				else if(params.time > 2.0 && nocheat_t * 1.2 > params.time) {
					// All is good, but grab time from pool; don't care if
					// it's actually available
					playersao->getDigPool().grab(params.time);
				}
				// Short or laggy dig
				// Try getting the time from pool
				else if(playersao->getDigPool().grab(params.time)) {
					// All is good
				}
				// Dig not possible
				else {
					infostream << "Server: NoCheat: " << player->getName()
					           << " completed digging " << PP(p_under)
					           << "too fast; not digging." << std::endl;
					is_valid_dig = false;
					// Call callbacks
					m_script->on_cheat(playersao, "dug_too_fast");
				}
			}

			/* Actually dig node */

			if(is_valid_dig && n.getContent() != CONTENT_IGNORE) {
				m_script->node_on_dig(p_under, n, playersao);
				stat.add("dig", player->getName());
				stat.add("dig_" + m_nodedef->get(n).name , player->getName());
			}

			v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
			RemoteClient *client = getClient(peer_id);
			// Send unusual result (that is, node not being removed)
			if(m_env->getMap().getNode(p_under).getContent() != CONTENT_AIR) {
				// Re-send block to revert change on client-side
				client->SetBlockNotSent(blockpos);
			} else {
				client->ResendBlockIfOnWire(blockpos);
			}
			m_env->nodeUpdate(p_under, 5, 0);
		}
	} // action == 2

	/*
		3: place block or right-click object
	*/
	else if(action == 3) {
		ItemStack item = playersao->getWieldedItem();

		// Reset build time counter
		if(pointed.type == POINTEDTHING_NODE &&
		        item.getDefinition(m_itemdef).type == ITEM_NODE)
			getClient(peer_id)->m_time_from_building = 0.0;

		if(pointed.type == POINTEDTHING_OBJECT) {
			// Right click object

			// Skip if object has been removed
			if(pointed_object->m_removed)
				return;

			/* android bug - too many
							actionstream<<player->getName()<<" right-clicks object "
									<<pointed.object_id<<": "
									<<pointed_object->getDescription()<<std::endl;
			*/

			// Do stuff
			pointed_object->rightClick(playersao);
		} else if(m_script->item_OnPlace(
		              item, playersao, pointed)) {
			// Placement was handled in lua

			// Apply returned ItemStack
			if (playersao->setWieldedItem(item)) {
				SendInventory(playersao);
			}

			stat.add("place", player->getName());
			//stat.add("place_" + item.name, player->getName());
		}

		// If item has node placement prediction, always send the
		// blocks to make sure the client knows what exactly happened
		RemoteClient *client = getClient(peer_id);
		v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
		v3s16 blockpos2 = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
		if(item.getDefinition(m_itemdef).node_placement_prediction != "") {
			client->SetBlockNotSent(blockpos);
			if(blockpos2 != blockpos) {
				client->SetBlockNotSent(blockpos2);
			}
		} else {
			client->ResendBlockIfOnWire(blockpos);
			if(blockpos2 != blockpos) {
				client->ResendBlockIfOnWire(blockpos2);
			}
		}
		m_env->nodeUpdate(p_under, 5, 0);
	} // action == 3

	/*
		4: use
	*/
	else if(action == 4) {
		ItemStack item = playersao->getWieldedItem();

		actionstream << player->getName() << " uses " << item.name
		             << ", pointing at " << pointed.dump() << std::endl;

		if(m_script->item_OnUse(
		            item, playersao, pointed)) {
			// Apply returned ItemStack
			if (playersao->setWieldedItem(item)) {
				SendInventory(playersao);
			}
			stat.add("use", player->getName());
			stat.add("use_" + item.name, player->getName());
			m_env->nodeUpdate(p_under, 5, 0);
		}

	} // action == 4

	/*
		5: rightclick air
	*/
	else if (action == 5) {
		ItemStack item = playersao->getWieldedItem();

		actionstream << player->getName() << " activates "
		             << item.name << std::endl;

		if (m_script->item_OnSecondaryUse(
		            item, playersao)) {
			if( playersao->setWieldedItem(item)) {
				SendInventory(playersao);
			}
		}
	}


	/*
		Catch invalid actions
	*/
	else {
		infostream << "WARNING: Server: Invalid action "
		           << action << std::endl;
	}

}
Example #20
0
//////////////////////////////////////////////////////////////////////////
// Entries
//////////////////////////////////////////////////////////////////////////
void SaveLoad::writeEntry(SavegameType type, EntityIndex entity, uint32 value) {
#define WRITE_ENTRY(name, func, val) { \
	uint32 _prevPosition = (uint32)_savegame->pos(); \
	func; \
	uint32 _count = (uint32)_savegame->pos() - _prevPosition; \
	debugC(kLastExpressDebugSavegame, "Savegame: Writing " #name ": %d bytes", _count); \
	if (_count != val)\
		error("SaveLoad::writeEntry: Number of bytes written (%d) differ from expected count (%d)", _count, val); \
}

	if (!_savegame)
		error("SaveLoad::writeEntry: savegame stream is invalid");

	SavegameEntryHeader header;

	header.type = type;
	header.time = (uint32)getState()->time;
	header.chapter = getProgress().chapter;
	header.value = value;

	// Save position
	uint32 originalPosition = (uint32)_savegame->pos();

	// Write header
	Common::Serializer ser(NULL, _savegame);
	header.saveLoadWithSerializer(ser);

	// Write game data
	WRITE_ENTRY("entity index", ser.syncAsUint32LE(entity), 4);
	WRITE_ENTRY("state", getState()->saveLoadWithSerializer(ser), 4 + 4 + 4 + 4 + 1 + 4 + 4);
	WRITE_ENTRY("selected item", getInventory()->saveSelectedItem(ser), 4);
	WRITE_ENTRY("positions", getEntities()->savePositions(ser), 4 * 1000);
	WRITE_ENTRY("compartments", getEntities()->saveCompartments(ser), 4 * 16 * 2);
	WRITE_ENTRY("progress", getProgress().saveLoadWithSerializer(ser), 4 * 128);
	WRITE_ENTRY("events", getState()->syncEvents(ser), 512);
	WRITE_ENTRY("inventory", getInventory()->saveLoadWithSerializer(ser), 7 * 32);
	WRITE_ENTRY("objects", getObjects()->saveLoadWithSerializer(ser), 5 * 128);
	WRITE_ENTRY("entities", getEntities()->saveLoadWithSerializer(ser), 1262 * 40);
	WRITE_ENTRY("sound", getSound()->saveLoadWithSerializer(ser), 3 * 4 + getSound()->count() * 64);
	WRITE_ENTRY("savepoints", getSavePoints()->saveLoadWithSerializer(ser), 128 * 16 + 4 + getSavePoints()->count() * 16);

	header.offset = (uint32)_savegame->pos() - (originalPosition + 32);

	// Add padding if necessary
	while (header.offset & 0xF) {
		_savegame->writeByte(0);
		header.offset++;
	}

	// Save end position
	uint32 endPosition = (uint32)_savegame->pos();

	// Validate entry header
	if (!header.isValid())
		error("SaveLoad::writeEntry: entry header is invalid");

	// Save the header with the updated info
	_savegame->seek(originalPosition);
	header.saveLoadWithSerializer(ser);

	// Move back to the end of the entry
	_savegame->seek(endPosition);
}
Example #21
0
void Logic::eventMouse(const Common::Event &ev) {
	bool hotspotHandled = false;

	// Reset mouse flags
	getFlags()->mouseLeftClick = false;
	getFlags()->mouseRightClick = false;

	// Process event flags
	if (ev.type == Common::EVENT_LBUTTONDOWN) {

		if (getFlags()->frameInterval)
			_ignoreFrameInterval = false;

		getFlags()->frameInterval = false;
	}

	if (getFlags()->flag_0) {
		if (ev.type == Common::EVENT_LBUTTONDOWN || ev.type == Common::EVENT_RBUTTONDOWN) {
			getFlags()->flag_0 = false;
			getFlags()->shouldRedraw = true;
			updateCursor(true);
			getFlags()->frameInterval = true;
		}
		return;
	}

	if (_ignoreFrameInterval && getScenes()->checkCurrentPosition(true) && _engine->getCursor()->getStyle() == kCursorForward) {
		getFlags()->shouldRedraw = false;
		getFlags()->flag_0 = true;
		return;
	}

	// Update coordinates
	getGameState()->setCoordinates(ev.mouse);

	// Handle inventory
	getInventory()->handleMouseEvent(ev);

	// Stop processing is inside the menu
	if (getMenu()->isShown())
		return;

	// Handle whistle case
	if (getInventory()->getSelectedItem() == kItemWhistle
	 && !getProgress().isEggOpen
	 && !getEntities()->isPlayerPosition(kCarGreenSleeping, 59)
	 && !getEntities()->isPlayerPosition(kCarGreenSleeping, 76)
	 && !getInventory()->isPortraitHighlighted()
	 && !getInventory()->isOpened()
	 && !getInventory()->isEggHighlighted()
	 && !getInventory()->isMagnifierInUse()) {

		 // Update cursor
		_engine->getCursor()->setStyle(getInventory()->get(kItemWhistle)->cursor);

		// Check if clicked
		if (ev.type == Common::EVENT_LBUTTONUP && !getSoundQueue()->isBuffered("LIB045")) {

			getSound()->playSoundEvent(kEntityPlayer, 45);

			if (getEntities()->isPlayerPosition(kCarGreenSleeping, 26) || getEntities()->isPlayerPosition(kCarGreenSleeping, 25) || getEntities()->isPlayerPosition(kCarGreenSleeping, 23)) {
				getSavePoints()->push(kEntityPlayer, kEntityMertens, kAction226078300);
			} else if (getEntities()->isPlayerPosition(kCarRedSleeping, 26) || getEntities()->isPlayerPosition(kCarRedSleeping, 25) || getEntities()->isPlayerPosition(kCarRedSleeping, 23)) {
				getSavePoints()->push(kEntityPlayer, kEntityCoudert, kAction226078300);
			}

			if (!getState()->sceneUseBackup)
				getInventory()->unselectItem();
		}

		REDRAW_CURSOR()
	}