diff --git a/apps/openmw-mp/CMakeLists.txt b/apps/openmw-mp/CMakeLists.txt index fc9ee0527..1d4386511 100644 --- a/apps/openmw-mp/CMakeLists.txt +++ b/apps/openmw-mp/CMakeLists.txt @@ -130,11 +130,11 @@ set(PROCESSORS_PLAYER processors/player/ProcessorPlayerFaction.hpp processors/player/ProcessorPlayerInventory.hpp processors/player/ProcessorPlayerJournal.hpp processors/player/ProcessorPlayerKillCount.hpp processors/player/ProcessorPlayerLevel.hpp processors/player/ProcessorPlayerMap.hpp - processors/player/ProcessorPlayerPosition.hpp processors/player/ProcessorPlayerRest.hpp - processors/player/ProcessorPlayerResurrect.hpp processors/player/ProcessorPlayerShapeshift.hpp - processors/player/ProcessorPlayerSkill.hpp processors/player/ProcessorPlayerSpeech.hpp - processors/player/ProcessorPlayerSpellbook.hpp processors/player/ProcessorPlayerStatsDynamic.hpp - processors/player/ProcessorPlayerTopic.hpp + processors/player/ProcessorPlayerPosition.hpp processors/player/ProcessorPlayerQuickKeys.hpp + processors/player/ProcessorPlayerRest.hpp processors/player/ProcessorPlayerResurrect.hpp + processors/player/ProcessorPlayerShapeshift.hpp processors/player/ProcessorPlayerSkill.hpp + processors/player/ProcessorPlayerSpeech.hpp processors/player/ProcessorPlayerSpellbook.hpp + processors/player/ProcessorPlayerStatsDynamic.hpp processors/player/ProcessorPlayerTopic.hpp ) source_group(tes3mp-server\\processors\\player FILES ${PROCESSORS_PLAYER}) diff --git a/apps/openmw-mp/Script/Functions/GUI.cpp b/apps/openmw-mp/Script/Functions/GUI.cpp index fcf5860f8..259845000 100644 --- a/apps/openmw-mp/Script/Functions/GUI.cpp +++ b/apps/openmw-mp/Script/Functions/GUI.cpp @@ -77,6 +77,77 @@ void GUIFunctions::ListBox(unsigned short pid, int id, const char *label, const mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GUI_MESSAGEBOX)->Send(false); } +void GUIFunctions::InitializeQuickKeyChanges(unsigned short pid) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + player->quickKeyChanges.quickKeys.clear(); +} + +unsigned int GUIFunctions::GetQuickKeyChangesSize(unsigned short pid) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + return player->quickKeyChanges.count; +} + +int GUIFunctions::GetQuickKeySlot(unsigned short pid, unsigned int i) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + if (i >= player->quickKeyChanges.count) + return 0; + + return player->quickKeyChanges.quickKeys.at(i).slot; +} + +int GUIFunctions::GetQuickKeyType(unsigned short pid, unsigned int i) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + if (i >= player->quickKeyChanges.count) + return 0; + + return player->quickKeyChanges.quickKeys.at(i).type; +} + +const char *GUIFunctions::GetQuickKeyItemId(unsigned short pid, unsigned int i) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ""); + + if (i >= player->quickKeyChanges.count) + return "invalid"; + + return player->quickKeyChanges.quickKeys.at(i).itemId.c_str(); +} + +void GUIFunctions::AddQuickKey(unsigned short pid, unsigned short slot, int type, const char* itemId) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + mwmp::QuickKey quickKey; + quickKey.slot = slot; + quickKey.type = type; + quickKey.itemId = itemId; + + player->quickKeyChanges.quickKeys.push_back(quickKey); +} + +void GUIFunctions::SendQuickKeyChanges(unsigned short pid) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_QUICKKEYS)->setPlayer(player); + mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_QUICKKEYS)->Send(false); +} + void GUIFunctions::SetMapVisibility(unsigned short targetPID, unsigned short affectedPID, unsigned short state) noexcept { LOG_MESSAGE(Log::LOG_WARN, "stub"); diff --git a/apps/openmw-mp/Script/Functions/GUI.hpp b/apps/openmw-mp/Script/Functions/GUI.hpp index f76fda70a..f30ae0aad 100644 --- a/apps/openmw-mp/Script/Functions/GUI.hpp +++ b/apps/openmw-mp/Script/Functions/GUI.hpp @@ -6,13 +6,26 @@ #define OPENMW_GUIAPI_HPP #define GUIAPI \ - {"MessageBox", GUIFunctions::_MessageBox},\ - {"CustomMessageBox", GUIFunctions::CustomMessageBox},\ - {"InputDialog", GUIFunctions::InputDialog},\ - {"PasswordDialog", GUIFunctions::PasswordDialog},\ - {"ListBox", GUIFunctions::ListBox},\ - {"SetMapVisibility", GUIFunctions::SetMapVisibility},\ - {"SetMapVisibilityAll", GUIFunctions::SetMapVisibilityAll} + {"MessageBox", GUIFunctions::_MessageBox},\ + {"CustomMessageBox", GUIFunctions::CustomMessageBox},\ + {"InputDialog", GUIFunctions::InputDialog},\ + {"PasswordDialog", GUIFunctions::PasswordDialog},\ + {"ListBox", GUIFunctions::ListBox},\ + \ + {"InitializeQuickKeyChanges", GUIFunctions::InitializeQuickKeyChanges},\ + \ + {"GetQuickKeyChangesSize", GUIFunctions::GetQuickKeyChangesSize},\ + \ + {"GetQuickKeySlot", GUIFunctions::GetQuickKeySlot},\ + {"GetQuickKeyType", GUIFunctions::GetQuickKeyType},\ + {"GetQuickKeyItemId", GUIFunctions::GetQuickKeyItemId},\ + \ + {"AddQuickKey", GUIFunctions::AddQuickKey},\ + \ + {"SendQuickKeyChanges", GUIFunctions::SendQuickKeyChanges},\ + \ + {"SetMapVisibility", GUIFunctions::SetMapVisibility},\ + {"SetMapVisibilityAll", GUIFunctions::SetMapVisibilityAll} class GUIFunctions { @@ -26,6 +39,70 @@ public: static void ListBox(unsigned short pid, int id, const char *label, const char *items); + /** + * \brief Clear the last recorded quick key changes for a player. + * + * This is used to initialize the sending of new PlayerQuickKeys packets. + * + * \param pid The player ID whose quick key changes should be used. + * \return void + */ + static void InitializeQuickKeyChanges(unsigned short pid) noexcept; + + /** + * \brief Get the number of indexes in a player's latest quick key changes. + * + * \param pid The player ID whose quick key changes should be used. + * \return The number of indexes. + */ + static unsigned int GetQuickKeyChangesSize(unsigned short pid) noexcept; + + /** + * \brief Add a new quick key to the quick key changes for a player. + * + * \param pid The player ID whose quick key changes should be used. + * \param slot The slot to be used. + * \param slot The type of the quick key (0 for ITEM, 1 for ITEM_MAGIC, 2 for MAGIC, 3 for UNASSIGNED). + * \param itemId The itemId of the item. + * \return void + */ + static void AddQuickKey(unsigned short pid, unsigned short slot, int type, const char* itemId = "") noexcept; + + /** + * \brief Get the slot of the quick key at a certain index in a player's latest quick key changes. + * + * \param pid The player ID whose quick key changes should be used. + * \param i The index of the quick key in the quick key changes vector. + * \return The slot. + */ + static int GetQuickKeySlot(unsigned short pid, unsigned int i) noexcept; + + /** + * \brief Get the type of the quick key at a certain index in a player's latest quick key changes. + * + * \param pid The player ID whose quick key changes should be used. + * \param i The index of the quick key in the quick key changes vector. + * \return The quick key type. + */ + static int GetQuickKeyType(unsigned short pid, unsigned int i) noexcept; + + /** + * \brief Get the itemId at a certain index in a player's latest quick key changes. + * + * \param pid The player ID whose quick key changes should be used. + * \param i The index of the quick key in the quick key changes vector. + * \return The itemId. + */ + static const char *GetQuickKeyItemId(unsigned short pid, unsigned int i) noexcept; + + /** + * \brief Send a PlayerQuickKeys packet with a player's recorded quick key changes. + * + * \param pid The player ID whose quick key changes should be used. + * \return void + */ + static void SendQuickKeyChanges(unsigned short pid) noexcept; + //state 0 - disallow, 1 - allow static void SetMapVisibility(unsigned short targetPID, unsigned short affectedPID, unsigned short state) noexcept; static void SetMapVisibilityAll(unsigned short targetPID, unsigned short state) noexcept; diff --git a/apps/openmw-mp/Script/Functions/Spells.hpp b/apps/openmw-mp/Script/Functions/Spells.hpp index 6984a8455..f1d8ecbed 100644 --- a/apps/openmw-mp/Script/Functions/Spells.hpp +++ b/apps/openmw-mp/Script/Functions/Spells.hpp @@ -9,24 +9,24 @@ \ {"SetSpellbookChangesAction", SpellFunctions::SetSpellbookChangesAction},\ {"AddSpell", SpellFunctions::AddSpell},\ - {"AddCustomSpell", SpellFunctions::AddCustomSpell},\ - {"AddCustomSpellData", SpellFunctions::AddCustomSpellData},\ - {"AddCustomSpellEffect", SpellFunctions::AddCustomSpellEffect},\ + {"AddCustomSpell", SpellFunctions::AddCustomSpell},\ + {"AddCustomSpellData", SpellFunctions::AddCustomSpellData},\ + {"AddCustomSpellEffect", SpellFunctions::AddCustomSpellEffect},\ \ {"GetSpellId", SpellFunctions::GetSpellId},\ - {"GetSpellName", SpellFunctions::GetSpellName},\ - {"GetSpellType", SpellFunctions::GetSpellType},\ - {"GetSpellCost", SpellFunctions::GetSpellCost},\ - {"GetSpellFlags", SpellFunctions::GetSpellFlags},\ - {"GetSpellEffectCount", SpellFunctions::GetSpellEffectCount},\ - {"GetSpellEffectId", SpellFunctions::GetSpellEffectId},\ - {"GetSpellEffectSkill", SpellFunctions::GetSpellEffectSkill},\ - {"GetSpellEffectAttribute", SpellFunctions::GetSpellEffectAttribute},\ - {"GetSpellEffectRange", SpellFunctions::GetSpellEffectRange},\ - {"GetSpellEffectArea", SpellFunctions::GetSpellEffectArea},\ - {"GetSpellEffectDuration", SpellFunctions::GetSpellEffectDuration},\ - {"GetSpellEffectMagnMin", SpellFunctions::GetSpellEffectMagnMin},\ - {"GetSpellEffectMagnMax", SpellFunctions::GetSpellEffectMagnMax},\ + {"GetSpellName", SpellFunctions::GetSpellName},\ + {"GetSpellType", SpellFunctions::GetSpellType},\ + {"GetSpellCost", SpellFunctions::GetSpellCost},\ + {"GetSpellFlags", SpellFunctions::GetSpellFlags},\ + {"GetSpellEffectCount", SpellFunctions::GetSpellEffectCount},\ + {"GetSpellEffectId", SpellFunctions::GetSpellEffectId},\ + {"GetSpellEffectSkill", SpellFunctions::GetSpellEffectSkill},\ + {"GetSpellEffectAttribute", SpellFunctions::GetSpellEffectAttribute},\ + {"GetSpellEffectRange", SpellFunctions::GetSpellEffectRange},\ + {"GetSpellEffectArea", SpellFunctions::GetSpellEffectArea},\ + {"GetSpellEffectDuration", SpellFunctions::GetSpellEffectDuration},\ + {"GetSpellEffectMagnMin", SpellFunctions::GetSpellEffectMagnMin},\ + {"GetSpellEffectMagnMax", SpellFunctions::GetSpellEffectMagnMax},\ \ {"SendSpellbookChanges", SpellFunctions::SendSpellbookChanges} diff --git a/apps/openmw-mp/Script/ScriptFunctions.hpp b/apps/openmw-mp/Script/ScriptFunctions.hpp index c46cd8917..bf6d3558c 100644 --- a/apps/openmw-mp/Script/ScriptFunctions.hpp +++ b/apps/openmw-mp/Script/ScriptFunctions.hpp @@ -154,6 +154,7 @@ public: {"OnPlayerFaction", Function()}, {"OnPlayerShapeshift", Function()}, {"OnPlayerSpellbook", Function()}, + {"OnPlayerQuickKeys", Function()}, {"OnPlayerTopic", Function()}, {"OnPlayerDisposition", Function()}, {"OnPlayerBook", Function()}, diff --git a/apps/openmw-mp/processors/ProcessorInitializer.cpp b/apps/openmw-mp/processors/ProcessorInitializer.cpp index 62257b63e..c2cad7ecf 100644 --- a/apps/openmw-mp/processors/ProcessorInitializer.cpp +++ b/apps/openmw-mp/processors/ProcessorInitializer.cpp @@ -31,6 +31,7 @@ #include "player/ProcessorPlayerLevel.hpp" #include "player/ProcessorPlayerMap.hpp" #include "player/ProcessorPlayerPosition.hpp" +#include "player/ProcessorPlayerQuickKeys.hpp" #include "player/ProcessorPlayerRest.hpp" #include "player/ProcessorPlayerResurrect.hpp" #include "player/ProcessorPlayerShapeshift.hpp" @@ -100,6 +101,7 @@ void ProcessorInitializer() PlayerProcessor::AddProcessor(new ProcessorPlayerLevel()); PlayerProcessor::AddProcessor(new ProcessorPlayerMap()); PlayerProcessor::AddProcessor(new ProcessorPlayerPosition()); + PlayerProcessor::AddProcessor(new ProcessorPlayerQuickKeys()); PlayerProcessor::AddProcessor(new ProcessorPlayerRest()); PlayerProcessor::AddProcessor(new ProcessorPlayerResurrect()); PlayerProcessor::AddProcessor(new ProcessorPlayerShapeshift()); diff --git a/apps/openmw-mp/processors/player/ProcessorPlayerQuickKeys.hpp b/apps/openmw-mp/processors/player/ProcessorPlayerQuickKeys.hpp new file mode 100644 index 000000000..9f5265b00 --- /dev/null +++ b/apps/openmw-mp/processors/player/ProcessorPlayerQuickKeys.hpp @@ -0,0 +1,26 @@ +#ifndef OPENMW_PROCESSORPLAYERQUICKKEYS_HPP +#define OPENMW_PROCESSORPLAYERQUICKKEYS_HPP + +#include "../PlayerProcessor.hpp" + +namespace mwmp +{ + class ProcessorPlayerQuickKeys : public PlayerProcessor + { + public: + ProcessorPlayerQuickKeys() + { + BPP_INIT(ID_PLAYER_QUICKKEYS) + } + + void Do(PlayerPacket &packet, Player &player) override + { + DEBUG_PRINTF(strPacketID.c_str()); + + Script::Call(player.getId()); + } + }; +} + + +#endif //OPENMW_PROCESSORPLAYERQUICKKEYS_HPP diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 92fa5da2d..d71c9d5f3 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -117,8 +117,8 @@ add_openmw_dir (mwmp/processors/player ProcessorChatMessage ProcessorGUIMessageB ProcessorPlayerBook ProcessorPlayerBounty ProcessorPlayerCellChange ProcessorPlayerCellState ProcessorPlayerCharClass ProcessorPlayerCharGen ProcessorPlayerDeath ProcessorPlayerDisposition ProcessorPlayerEquipment ProcessorPlayerFaction ProcessorPlayerInventory ProcessorPlayerJail ProcessorPlayerJournal ProcessorPlayerKillCount ProcessorPlayerLevel - ProcessorPlayerMap ProcessorPlayerPosition ProcessorPlayerResurrect ProcessorPlayerShapeshift ProcessorPlayerSkill - ProcessorPlayerSpeech ProcessorPlayerSpellbook ProcessorPlayerStatsDynamic ProcessorPlayerTopic + ProcessorPlayerMap ProcessorPlayerPosition ProcessorPlayerQuickKeys ProcessorPlayerResurrect ProcessorPlayerShapeshift + ProcessorPlayerSkill ProcessorPlayerSpeech ProcessorPlayerSpellbook ProcessorPlayerStatsDynamic ProcessorPlayerTopic ) add_openmw_dir (mwmp/processors/world BaseObjectProcessor ProcessorConsoleCommand ProcessorContainer ProcessorDoorState diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index aa4cdf22c..b6cd36e19 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -227,6 +227,16 @@ namespace MWBase /// update activated quick key state (if action executing was delayed for some reason) virtual void updateActivatedQuickKey () = 0; + /* + Start of tes3mp addition + + Make it possible to add quickKeys from elsewhere in the code + */ + virtual void setQuickKey(int slot, int quickKeyType, MWWorld::Ptr item, const std::string& spellId = "") = 0; + /* + End of tes3mp addition + */ + virtual std::string getSelectedSpell() = 0; virtual void setSelectedSpell(const std::string& spellId, int successChancePercent) = 0; virtual void setSelectedEnchantItem(const MWWorld::Ptr& item) = 0; diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index e912193bf..6198372e0 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -8,6 +8,18 @@ #include #include +/* + Start of tes3mp addition + + Include additional headers for multiplayer purposes +*/ +#include +#include "../mwmp/Main.hpp" +#include "../mwmp/LocalPlayer.hpp" +/* + End of tes3mp addition +*/ + #include "../mwworld/inventorystore.hpp" #include "../mwworld/class.hpp" #include "../mwworld/player.hpp" @@ -111,8 +123,36 @@ namespace MWGui textBox->setCaption (MyGUI::utility::toString(index+1)); textBox->setNeedMouseFocus (false); } + + /* + Start of tes3mp addition + + Send a PLAYER_QUICKKEYS packet whenever a key is unassigned, but only if the player + has finished character generation, so as to avoid doing anything doing startup when all + quick keys get unassigned by default + */ + if (mwmp::Main::get().getLocalPlayer()->hasFinishedCharGen() && !mwmp::Main::get().getLocalPlayer()->isReceivingQuickKeys) + { + mwmp::Main::get().getLocalPlayer()->sendQuickKey(index, Type_Unassigned); + } + /* + End of tes3mp addition + */ } + /* + Start of tes3mp addition + + Allow unassigning an index directly from elsewhere in the code + */ + void QuickKeysMenu::unassignIndex(int index) + { + unassign(mQuickKeyButtons[index], index); + } + /* + End of tes3mp addition + */ + void QuickKeysMenu::onQuickKeyButtonClicked(MyGUI::Widget* sender) { int index = -1; @@ -193,6 +233,17 @@ namespace MWGui if (mItemSelectionDialog) mItemSelectionDialog->setVisible(false); + + /* + Start of tes3mp addition + + Send a PLAYER_QUICKKEYS packet whenever a key is assigned to an item + */ + if (!mwmp::Main::get().getLocalPlayer()->isReceivingQuickKeys) + mwmp::Main::get().getLocalPlayer()->sendQuickKey(mSelectedIndex, Type_Item, item.getCellRef().getRefId()); + /* + End of tes3mp addition + */ } void QuickKeysMenu::onAssignItemCancel() @@ -217,6 +268,17 @@ namespace MWGui if (mMagicSelectionDialog) mMagicSelectionDialog->setVisible(false); + + /* + Start of tes3mp addition + + Send a PLAYER_QUICKKEYS packet whenever a key is assigned to an item's magic + */ + if (!mwmp::Main::get().getLocalPlayer()->isReceivingQuickKeys) + mwmp::Main::get().getLocalPlayer()->sendQuickKey(mSelectedIndex, Type_MagicItem, item.getCellRef().getRefId()); + /* + End of tes3mp addition + */ } void QuickKeysMenu::onAssignMagic (const std::string& spellId) @@ -251,6 +313,17 @@ namespace MWGui if (mMagicSelectionDialog) mMagicSelectionDialog->setVisible(false); + + /* + Start of tes3mp addition + + Send a PLAYER_QUICKKEYS packet whenever a key is assigned to a spell + */ + if (!mwmp::Main::get().getLocalPlayer()->isReceivingQuickKeys) + mwmp::Main::get().getLocalPlayer()->sendQuickKey(mSelectedIndex, Type_Magic, spellId); + /* + End of tes3mp addition + */ } void QuickKeysMenu::onAssignMagicCancel () @@ -402,6 +475,19 @@ namespace MWGui } } + /* + Start of tes3mp addition + + Make it possible to add quickKeys from elsewhere in the code + */ + void QuickKeysMenu::setSelectedIndex(int index) + { + mSelectedIndex = index; + } + /* + End of tes3mp addition + */ + // --------------------------------------------------------------------------------------------------------- QuickKeysMenuAssign::QuickKeysMenuAssign (QuickKeysMenu* parent) diff --git a/apps/openmw/mwgui/quickkeysmenu.hpp b/apps/openmw/mwgui/quickkeysmenu.hpp index 64db9043e..e89da52a6 100644 --- a/apps/openmw/mwgui/quickkeysmenu.hpp +++ b/apps/openmw/mwgui/quickkeysmenu.hpp @@ -38,6 +38,16 @@ namespace MWGui void activateQuickKey(int index); void updateActivatedQuickKey(); + /* + Start of tes3mp addition + + Allow the setting of the selected index from elsewhere in the code + */ + void setSelectedIndex(int index); + /* + End of tes3mp addition + */ + /// @note This enum is serialized, so don't move the items around! enum QuickKeyType { @@ -52,6 +62,16 @@ namespace MWGui void readRecord (ESM::ESMReader& reader, uint32_t type); void clear(); + /* + Start of tes3mp addition + + Allow unassigning an index directly from elsewhere in the code + */ + void unassignIndex(int index); + /* + End of tes3mp addition + */ + private: MyGUI::EditBox* mInstructionLabel; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 73acd3c2f..8d98e55d9 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -25,6 +25,7 @@ Include additional headers for multiplayer purposes */ +#include #include "../mwmp/Main.hpp" #include "../mwmp/GUIController.hpp" /* @@ -1589,6 +1590,35 @@ namespace MWGui mQuickKeysMenu->activateQuickKey(index); } + /* + Start of tes3mp addition + + Make it possible to add quickKeys from elsewhere in the code + */ + void WindowManager::setQuickKey(int slot, int quickKeyType, MWWorld::Ptr item, const std::string& spellId) + { + mQuickKeysMenu->setSelectedIndex(slot); + + switch (quickKeyType) + { + case QuickKeysMenu::Type_Unassigned: + mQuickKeysMenu->unassignIndex(slot); + break; + case QuickKeysMenu::Type_Item: + mQuickKeysMenu->onAssignItem(item); + break; + case QuickKeysMenu::Type_MagicItem: + mQuickKeysMenu->onAssignMagicItem(item); + break; + case QuickKeysMenu::Type_Magic: + mQuickKeysMenu->onAssignMagic(spellId); + break; + } + } + /* + End of tes3mp addition + */ + bool WindowManager::getSubtitlesEnabled () { return mSubtitlesEnabled; diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index de9898b34..4f5ff1275 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -256,6 +256,16 @@ namespace MWGui /// update activated quick key state (if action executing was delayed for some reason) virtual void updateActivatedQuickKey (); + /* + Start of tes3mp addition + + Make it possible to add quickKeys from elsewhere in the code + */ + virtual void setQuickKey(int slot, int quickKeyType, MWWorld::Ptr item, const std::string& spellId = ""); + /* + End of tes3mp addition + */ + virtual std::string getSelectedSpell() { return mSelectedSpell; } virtual void setSelectedSpell(const std::string& spellId, int successChancePercent); virtual void setSelectedEnchantItem(const MWWorld::Ptr& item); diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index 16a3d4441..71d1de8f7 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -65,6 +65,7 @@ LocalPlayer::LocalPlayer() isWerewolf = false; diedSinceArrestAttempt = false; + isReceivingQuickKeys = false; } LocalPlayer::~LocalPlayer() @@ -993,6 +994,57 @@ void LocalPlayer::setSpellbook() addSpells(); } +void LocalPlayer::setQuickKeys() +{ + MWWorld::Ptr ptrPlayer = getPlayerPtr(); + + LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Received ID_PLAYER_QUICKKEYS from server"); + + // Because we send QuickKeys packets from the same OpenMW methods that we use to set received ones with, + // we need a boolean to prevent their sending here + isReceivingQuickKeys = true; + + for (const auto &quickKey : quickKeyChanges.quickKeys) + { + LOG_APPEND(Log::LOG_INFO, "- slot: %i, type: %i, itemId: %s", quickKey.slot, quickKey.type, quickKey.itemId.c_str()); + + if (quickKey.type == QuickKey::ITEM || quickKey.type == QuickKey::ITEM_MAGIC) + { + MWWorld::InventoryStore &ptrInventory = ptrPlayer.getClass().getInventoryStore(ptrPlayer); + + auto it = find_if(ptrInventory.begin(), ptrInventory.end(), [&quickKey](const MWWorld::Ptr &inventoryItem) { + return Misc::StringUtils::ciEqual(inventoryItem.getCellRef().getRefId(), quickKey.itemId); + }); + + if (it != ptrInventory.end()) + MWBase::Environment::get().getWindowManager()->setQuickKey(quickKey.slot, quickKey.type, (*it)); + } + else if (quickKey.type == QuickKey::MAGIC) + { + MWMechanics::Spells &ptrSpells = ptrPlayer.getClass().getCreatureStats(ptrPlayer).getSpells(); + bool hasSpell = false; + + MWMechanics::Spells::TIterator iter = ptrSpells.begin(); + for (; iter != ptrSpells.end(); iter++) + { + const ESM::Spell *spell = iter->first; + if (Misc::StringUtils::ciEqual(spell->mId, quickKey.itemId)) + { + hasSpell = true; + break; + } + } + + if (hasSpell) + MWBase::Environment::get().getWindowManager()->setQuickKey(quickKey.slot, quickKey.type, 0, quickKey.itemId); + } + else + MWBase::Environment::get().getWindowManager()->setQuickKey(quickKey.slot, quickKey.type, 0); + } + + isReceivingQuickKeys = false; +} + void LocalPlayer::setFactions() { MWWorld::Ptr ptrPlayer = getPlayerPtr(); @@ -1199,6 +1251,24 @@ void LocalPlayer::sendSpellRemoval(const ESM::Spell &spell) */ } +void LocalPlayer::sendQuickKey(unsigned short slot, int type, const std::string& itemId) +{ + quickKeyChanges.quickKeys.clear(); + + mwmp::QuickKey quickKey; + quickKey.slot = slot; + quickKey.type = type; + quickKey.itemId = itemId; + + LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Sending ID_PLAYER_QUICKKEYS", itemId.c_str()); + LOG_APPEND(Log::LOG_INFO, "- slot: %i, type: %i, itemId: %s", quickKey.slot, quickKey.type, quickKey.itemId.c_str()); + + quickKeyChanges.quickKeys.push_back(quickKey); + + getNetworking()->getPlayerPacket(ID_PLAYER_QUICKKEYS)->setPlayer(this); + getNetworking()->getPlayerPacket(ID_PLAYER_QUICKKEYS)->Send(); +} + void LocalPlayer::sendJournalEntry(const std::string& quest, int index, const MWWorld::Ptr& actor) { journalChanges.journalItems.clear(); diff --git a/apps/openmw/mwmp/LocalPlayer.hpp b/apps/openmw/mwmp/LocalPlayer.hpp index 23308428c..56302fa31 100644 --- a/apps/openmw/mwmp/LocalPlayer.hpp +++ b/apps/openmw/mwmp/LocalPlayer.hpp @@ -58,6 +58,7 @@ namespace mwmp void setEquipment(); void setInventory(); void setSpellbook(); + void setQuickKeys(); void setFactions(); void setKills(); void setBooks(); @@ -72,6 +73,7 @@ namespace mwmp void sendSpellAddition(const ESM::Spell &spell); void sendSpellRemoval(std::string id); void sendSpellRemoval(const ESM::Spell &spell); + void sendQuickKey(unsigned short slot, int type, const std::string& itemId = ""); void sendJournalEntry(const std::string& quest, int index, const MWWorld::Ptr& actor); void sendJournalIndex(const std::string& quest, int index); void sendFactionRank(const std::string& factionId, int rank); diff --git a/apps/openmw/mwmp/processors/ProcessorInitializer.cpp b/apps/openmw/mwmp/processors/ProcessorInitializer.cpp index 537177970..254655b18 100644 --- a/apps/openmw/mwmp/processors/ProcessorInitializer.cpp +++ b/apps/openmw/mwmp/processors/ProcessorInitializer.cpp @@ -35,6 +35,7 @@ #include "player/ProcessorPlayerLevel.hpp" #include "player/ProcessorPlayerMap.hpp" #include "player/ProcessorPlayerPosition.hpp" +#include "player/ProcessorPlayerQuickKeys.hpp" #include "player/ProcessorPlayerRegionAuthority.hpp" #include "player/ProcessorPlayerRest.hpp" #include "player/ProcessorPlayerResurrect.hpp" @@ -113,6 +114,7 @@ void ProcessorInitializer() PlayerProcessor::AddProcessor(new ProcessorPlayerLevel()); PlayerProcessor::AddProcessor(new ProcessorPlayerMap()); PlayerProcessor::AddProcessor(new ProcessorPlayerPosition()); + PlayerProcessor::AddProcessor(new ProcessorPlayerQuickKeys()); PlayerProcessor::AddProcessor(new ProcessorPlayerRegionAuthority()); PlayerProcessor::AddProcessor(new ProcessorPlayerRest()); PlayerProcessor::AddProcessor(new ProcessorPlayerResurrect()); diff --git a/apps/openmw/mwmp/processors/player/ProcessorPlayerQuickKeys.hpp b/apps/openmw/mwmp/processors/player/ProcessorPlayerQuickKeys.hpp new file mode 100644 index 000000000..5515162a6 --- /dev/null +++ b/apps/openmw/mwmp/processors/player/ProcessorPlayerQuickKeys.hpp @@ -0,0 +1,32 @@ +#ifndef OPENMW_PROCESSORPLAYERQUICKKEYS_HPP +#define OPENMW_PROCESSORPLAYERQUICKKEYS_HPP + + +#include "../PlayerProcessor.hpp" + +namespace mwmp +{ + class ProcessorPlayerQuickKeys : public PlayerProcessor + { + public: + ProcessorPlayerQuickKeys() + { + BPP_INIT(ID_PLAYER_QUICKKEYS) + } + + virtual void Do(PlayerPacket &packet, BasePlayer *player) + { + if (!isLocal()) return; + + LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Received ID_PLAYER_QUICKKEYS about LocalPlayer from server"); + + if (!isRequest()) + { + LocalPlayer &localPlayer = static_cast(*player); + localPlayer.setQuickKeys(); + } + } + }; +} + +#endif //OPENMW_PROCESSORPLAYERQUICKKEYS_HPP diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index b25adbbd1..f57f1353d 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -181,9 +181,9 @@ add_component_dir (openmw-mp/Packets/Player PacketPlayerAttack PacketPlayerAttribute PacketPlayerBook PacketPlayerBounty PacketPlayerCellChange PacketPlayerCellState PacketPlayerClass PacketPlayerDeath PacketPlayerEquipment PacketPlayerFaction PacketPlayerInventory PacketPlayerJail PacketPlayerJournal PacketPlayerKillCount PacketPlayerLevel - PacketPlayerMap PacketPlayerPosition PacketPlayerRegionAuthority PacketPlayerRest PacketPlayerResurrect - PacketPlayerShapeshift PacketPlayerSkill PacketPlayerSpeech PacketPlayerSpellbook PacketPlayerStatsDynamic - PacketPlayerTopic + PacketPlayerMap PacketPlayerPosition PacketPlayerQuickKeys PacketPlayerRegionAuthority PacketPlayerRest + PacketPlayerResurrect PacketPlayerShapeshift PacketPlayerSkill PacketPlayerSpeech PacketPlayerSpellbook + PacketPlayerStatsDynamic PacketPlayerTopic ) add_component_dir (openmw-mp/Packets/World diff --git a/components/openmw-mp/Base/BasePlayer.hpp b/components/openmw-mp/Base/BasePlayer.hpp index 0b3a2cc9a..a3fcf3e22 100644 --- a/components/openmw-mp/Base/BasePlayer.hpp +++ b/components/openmw-mp/Base/BasePlayer.hpp @@ -65,6 +65,22 @@ namespace mwmp std::string bookId; }; + struct QuickKey + { + std::string itemId; + + enum QUICKKEY_TYPE + { + ITEM = 0, + MAGIC = 1, + ITEM_MAGIC = 2, + UNASSIGNED = 3 + }; + + unsigned short slot; + int type; + }; + struct CellState { ESM::Cell cell; @@ -149,6 +165,12 @@ namespace mwmp int action; // 0 - Clear and set in entirety, 1 - Add spell, 2 - Remove spell }; + struct QuickKeyChanges + { + std::vector quickKeys; + unsigned int count; + }; + struct CellStateChanges { std::vector cellStates; @@ -212,6 +234,7 @@ namespace mwmp InventoryChanges inventoryChanges; SpellbookChanges spellbookChanges; + QuickKeyChanges quickKeyChanges; JournalChanges journalChanges; FactionChanges factionChanges; TopicChanges topicChanges; @@ -265,6 +288,7 @@ namespace mwmp unsigned int resurrectType; bool diedSinceArrestAttempt; + bool isReceivingQuickKeys; }; } diff --git a/components/openmw-mp/Controllers/PlayerPacketController.cpp b/components/openmw-mp/Controllers/PlayerPacketController.cpp index d155b5066..897e1f8df 100644 --- a/components/openmw-mp/Controllers/PlayerPacketController.cpp +++ b/components/openmw-mp/Controllers/PlayerPacketController.cpp @@ -28,6 +28,7 @@ #include "../Packets/Player/PacketPlayerLevel.hpp" #include "../Packets/Player/PacketPlayerMap.hpp" #include "../Packets/Player/PacketPlayerPosition.hpp" +#include "../Packets/Player/PacketPlayerQuickKeys.hpp" #include "../Packets/Player/PacketPlayerRegionAuthority.hpp" #include "../Packets/Player/PacketPlayerRest.hpp" #include "../Packets/Player/PacketPlayerResurrect.hpp" @@ -81,6 +82,7 @@ mwmp::PlayerPacketController::PlayerPacketController(RakNet::RakPeerInterface *p AddPacket(&packets, peer); AddPacket(&packets, peer); AddPacket(&packets, peer); + AddPacket(&packets, peer); AddPacket(&packets, peer); AddPacket(&packets, peer); AddPacket(&packets, peer); diff --git a/components/openmw-mp/NetworkMessages.hpp b/components/openmw-mp/NetworkMessages.hpp index 7c4823a15..ad5a34235 100644 --- a/components/openmw-mp/NetworkMessages.hpp +++ b/components/openmw-mp/NetworkMessages.hpp @@ -44,6 +44,7 @@ enum GameMessages ID_PLAYER_LEVEL, ID_PLAYER_MAP, ID_PLAYER_POSITION, + ID_PLAYER_QUICKKEYS, ID_PLAYER_REGION_AUTHORITY, ID_PLAYER_RESURRECT, ID_PLAYER_REST, diff --git a/components/openmw-mp/Packets/Player/PacketPlayerQuickKeys.cpp b/components/openmw-mp/Packets/Player/PacketPlayerQuickKeys.cpp new file mode 100644 index 000000000..0be42e565 --- /dev/null +++ b/components/openmw-mp/Packets/Player/PacketPlayerQuickKeys.cpp @@ -0,0 +1,40 @@ +#include +#include "PacketPlayerQuickKeys.hpp" + +using namespace std; +using namespace mwmp; + +PacketPlayerQuickKeys::PacketPlayerQuickKeys(RakNet::RakPeerInterface *peer) : PlayerPacket(peer) +{ + packetID = ID_PLAYER_QUICKKEYS; +} + +void PacketPlayerQuickKeys::Packet(RakNet::BitStream *bs, bool send) +{ + PlayerPacket::Packet(bs, send); + + if (send) + player->quickKeyChanges.count = (unsigned int) (player->quickKeyChanges.quickKeys.size()); + else + player->quickKeyChanges.quickKeys.clear(); + + RW(player->quickKeyChanges.count, send); + + for (unsigned int i = 0; i < player->quickKeyChanges.count; i++) + { + QuickKey quickKey; + + if (send) + quickKey = player->quickKeyChanges.quickKeys.at(i); + + RW(quickKey.type, send); + RW(quickKey.slot, send); + + if (quickKey.type != QuickKey::UNASSIGNED) + RW(quickKey.itemId, send); + + if (!send) + player->quickKeyChanges.quickKeys.push_back(quickKey); + } + +} diff --git a/components/openmw-mp/Packets/Player/PacketPlayerQuickKeys.hpp b/components/openmw-mp/Packets/Player/PacketPlayerQuickKeys.hpp new file mode 100644 index 000000000..26a6f64b0 --- /dev/null +++ b/components/openmw-mp/Packets/Player/PacketPlayerQuickKeys.hpp @@ -0,0 +1,17 @@ +#ifndef OPENMW_PACKETPLAYERQUICKKEYS_HPP +#define OPENMW_PACKETPLAYERQUICKKEYS_HPP + +#include + +namespace mwmp +{ + class PacketPlayerQuickKeys : public PlayerPacket + { + public: + PacketPlayerQuickKeys(RakNet::RakPeerInterface *peer); + + virtual void Packet(RakNet::BitStream *bs, bool send); + }; +} + +#endif //OPENMW_PACKETPLAYERQUICKKEYS_HPP