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); }
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); } }
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; }
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; }
bool ServerActiveObject::setWieldedItem(const ItemStack &item) { if(Inventory *inv = getInventory()) { if (InventoryList *list = inv->getList(getWieldList())) { list->changeItem(getWieldIndex(), item); return true; } } return false; }
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; }
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; }
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(); } } }
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; }
int Yeast::inventory() const { return getInventory("quanta").toInt(); }
// inventory must be handled separately, to my great annoyance double Fermentable::inventory() const { return getInventory("amount").toDouble(); }
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; }
////////////////////////////////////////////////////////////////////////// // 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); }
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; } }
////////////////////////////////////////////////////////////////////////// // 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); }
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() }