From 7595b334617d6088d3465330eae4ca703e409e52 Mon Sep 17 00:00:00 2001 From: Koncord Date: Thu, 29 Dec 2016 21:19:26 +0800 Subject: [PATCH] Implement spellbook --- apps/openmw-mp/Networking.cpp | 17 +++++++++- apps/openmw-mp/Player.hpp | 1 + apps/openmw-mp/Script/Functions/Spells.cpp | 28 ++++++++++------ apps/openmw-mp/Script/ScriptFunctions.hpp | 2 +- apps/openmw/mwgui/spellbuyingwindow.cpp | 9 ++++++ apps/openmw/mwgui/spellcreationdialog.cpp | 8 +++++ apps/openmw/mwgui/spellwindow.cpp | 8 +++++ apps/openmw/mwmp/LocalPlayer.cpp | 24 +++++++++++--- apps/openmw/mwmp/LocalPlayer.hpp | 2 ++ apps/openmw/mwmp/Networking.cpp | 32 +++++++++++++++++++ components/openmw-mp/Base/BasePlayer.hpp | 8 ++--- .../Packets/Player/PacketSpellbook.cpp | 6 ++-- 12 files changed, 121 insertions(+), 24 deletions(-) diff --git a/apps/openmw-mp/Networking.cpp b/apps/openmw-mp/Networking.cpp index 2c3a4f1bc..ffa0fef5a 100644 --- a/apps/openmw-mp/Networking.cpp +++ b/apps/openmw-mp/Networking.cpp @@ -236,7 +236,22 @@ void Networking::processPlayerPacket(RakNet::Packet *packet) DEBUG_PRINTF("ID_GAME_SPELLBOOK\n"); myPacket->Read(player); - Script::Call(player->getId(), player->spellbook.action); + string str; + for (auto spell : player->spellbook.spells) + { + str += spell.mId; + if (spell.mId != player->spellbook.spells.back().mId) + str += ";"; + if (player->spellbook.action == Spellbook::ADD) + player->realSpellbook.push_back(spell); + else if (player->spellbook.action == Spellbook::REMOVE) + { + player->realSpellbook.erase(remove_if(player->realSpellbook.begin(), player->realSpellbook.end(), [&spell](ESM::Spell s)->bool + {return spell.mId == s.mId; }), player->realSpellbook.end()); + } + } + + Script::Call(player->getId(), player->spellbook.action, str.c_str()); break; } diff --git a/apps/openmw-mp/Player.hpp b/apps/openmw-mp/Player.hpp index 4e4298d5f..b648e4097 100644 --- a/apps/openmw-mp/Player.hpp +++ b/apps/openmw-mp/Player.hpp @@ -70,6 +70,7 @@ public: public: mwmp::Inventory inventorySendBuffer; mwmp::Spellbook spellbookSendBuffer; + std::vector realSpellbook; private: bool handshakeState; diff --git a/apps/openmw-mp/Script/Functions/Spells.cpp b/apps/openmw-mp/Script/Functions/Spells.cpp index 4373f18a1..3ac1b6bf3 100644 --- a/apps/openmw-mp/Script/Functions/Spells.cpp +++ b/apps/openmw-mp/Script/Functions/Spells.cpp @@ -11,7 +11,7 @@ unsigned int SpellFunctions::GetSpellbookSize(unsigned short pid) noexcept Player *player; GET_PLAYER(pid, player, 0); - return player->spellbook.count; + return player->realSpellbook.size(); } void SpellFunctions::AddSpell(unsigned short pid, const char* spellId) noexcept @@ -19,8 +19,8 @@ void SpellFunctions::AddSpell(unsigned short pid, const char* spellId) noexcept Player *player; GET_PLAYER(pid, player, ); - Spell spell; - spell.id = spellId; + ESM::Spell spell; + spell.mId = spellId; player->spellbookSendBuffer.spells.push_back(spell); player->spellbookSendBuffer.action = Spellbook::ADD; @@ -31,8 +31,8 @@ void SpellFunctions::RemoveSpell(unsigned short pid, const char* spellId) noexce Player *player; GET_PLAYER(pid, player, ); - Spell spell; - spell.id = spellId; + ESM::Spell spell; + spell.mId = spellId; player->spellbookSendBuffer.spells.push_back(spell); player->spellbookSendBuffer.action = Spellbook::REMOVE; @@ -52,8 +52,8 @@ bool SpellFunctions::HasSpell(unsigned short pid, const char* spellId) Player *player; GET_PLAYER(pid, player, false); - for (unsigned int i = 0; i < player->spellbook.count; i++) - if (Misc::StringUtils::ciEqual(player->spellbook.spells.at(i).id, spellId)) + for (unsigned int i = 0; i < player->realSpellbook.size(); i++) + if (Misc::StringUtils::ciEqual(player->realSpellbook.at(i).mId, spellId)) return true; return false; } @@ -63,16 +63,26 @@ const char *SpellFunctions::GetSpellId(unsigned short pid, unsigned int i) noexc Player *player; GET_PLAYER(pid, player, ""); - if (i >= player->spellbook.count) + if (i >= player->realSpellbook.size()) return "invalid"; - return player->spellbook.spells.at(i).id.c_str(); + return player->realSpellbook.at(i).mId.c_str(); } void SpellFunctions::SendSpellbook(unsigned short pid) noexcept { Player *player; GET_PLAYER(pid, player, ); + + for (auto spell : player->spellbookSendBuffer.spells) + { + if (player->spellbookSendBuffer.action == Spellbook::ADD) + player->realSpellbook.push_back(spell); + else if (player->spellbook.action == Spellbook::REMOVE) + player->realSpellbook.erase(remove_if(player->realSpellbook.begin(), player->realSpellbook.end(), [&spell](ESM::Spell s)->bool + {return spell.mId == s.mId; }), player->realSpellbook.end()); + } + std::swap(player->spellbook, player->spellbookSendBuffer); mwmp::Networking::get().getPlayerController()->GetPacket(ID_GAME_SPELLBOOK)->Send(player, false); player->spellbook = std::move(player->spellbookSendBuffer); diff --git a/apps/openmw-mp/Script/ScriptFunctions.hpp b/apps/openmw-mp/Script/ScriptFunctions.hpp index c348df6f3..a3f5fac9e 100644 --- a/apps/openmw-mp/Script/ScriptFunctions.hpp +++ b/apps/openmw-mp/Script/ScriptFunctions.hpp @@ -106,7 +106,7 @@ public: {"OnPlayerChangeLevel", Function()}, {"OnPlayerChangeEquipment", Function()}, {"OnPlayerChangeInventory", Function()}, - {"OnPlayerChangeSpellbook", Function()}, + {"OnPlayerChangeSpellbook", Function()}, {"OnPlayerSendMessage", Function()}, {"OnPlayerEndCharGen", Function()}, {"OnGUIAction", Function()} diff --git a/apps/openmw/mwgui/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp index 843731cff..6116e199b 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.cpp +++ b/apps/openmw/mwgui/spellbuyingwindow.cpp @@ -17,6 +17,9 @@ #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/actorutil.hpp" +#include "../mwmp/Main.hpp" +#include "../mwmp/LocalPlayer.hpp" + namespace MWGui { const int SpellBuyingWindow::sLineHeight = 18; @@ -140,6 +143,12 @@ namespace MWGui MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); MWMechanics::Spells& spells = stats.getSpells(); spells.add (mSpellsWidgetMap.find(_sender)->second); + + // Added by tes3mp + // + // LocalPlayer has gained a spell, so send a packet with it + mwmp::Main::get().getLocalPlayer()->sendSpellAddition(mSpellsWidgetMap.find(_sender)->second); + player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player); // add gold to NPC trading gold pool diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index 64d4d86c6..21f1cb8b7 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -6,6 +6,9 @@ #include #include +#include "../mwmp/Main.hpp" +#include "../mwmp/LocalPlayer.hpp" + #include "../mwbase/windowmanager.hpp" #include "../mwbase/soundmanager.hpp" #include "../mwbase/mechanicsmanager.hpp" @@ -404,6 +407,11 @@ namespace MWGui MWMechanics::Spells& spells = stats.getSpells(); spells.add (spell->mId); + // Added by tes3mp + // + // LocalPlayer has gained a spell, so send a packet with it + mwmp::Main::get().getLocalPlayer()->sendSpellAddition(*spell); + MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_SpellCreation); } diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 7c12a8fc2..553bcfdd6 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -22,6 +22,9 @@ #include "confirmationdialog.hpp" #include "spellview.hpp" +#include"../mwmp/Main.hpp" +#include"../mwmp/LocalPlayer.hpp" + namespace MWGui { @@ -186,6 +189,11 @@ namespace MWGui spells.remove(mSpellToDelete); + // Added by tes3mp + // + // LocalPlayer has lost a spell, so send a packet with it + mwmp::Main::get().getLocalPlayer()->sendSpellRemoval(mSpellToDelete); + updateSpells(); } diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index ffb43a40a..2a7995eb9 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -848,10 +848,13 @@ void LocalPlayer::sendInventory() void LocalPlayer::sendSpellAddition(std::string id) { + if (id.find("$dynamic") != string::npos) // skip custom spells + return; + spellbook.spells.clear(); - mwmp::Spell spell; - spell.id = id; + ESM::Spell spell; + spell.mId = id; spellbook.spells.push_back(spell); spellbook.action = Spellbook::ADD; @@ -860,16 +863,29 @@ void LocalPlayer::sendSpellAddition(std::string id) void LocalPlayer::sendSpellRemoval(std::string id) { + if (id.find("$dynamic") != string::npos) // skip custom spells + return; + spellbook.spells.clear(); - mwmp::Spell spell; - spell.id = id; + ESM::Spell spell; + spell.mId = id; spellbook.spells.push_back(spell); spellbook.action = Spellbook::REMOVE; Main::get().getNetworking()->getPlayerPacket(ID_GAME_SPELLBOOK)->Send(this); } +void LocalPlayer::sendSpellAddition(const ESM::Spell &spell) +{ + LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Not implemented."); +} + +void LocalPlayer::sendSpellRemoval(const ESM::Spell &spell) +{ + LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Not implemented."); +} + void LocalPlayer::sendAttack(Attack::TYPE type) { MWMechanics::DrawState_ state = getPlayerPtr().getClass().getNpcStats(getPlayerPtr()).getDrawState(); diff --git a/apps/openmw/mwmp/LocalPlayer.hpp b/apps/openmw/mwmp/LocalPlayer.hpp index 4fd7fc52e..2585a72fe 100644 --- a/apps/openmw/mwmp/LocalPlayer.hpp +++ b/apps/openmw/mwmp/LocalPlayer.hpp @@ -48,7 +48,9 @@ namespace mwmp void sendClass(); void sendInventory(); void sendSpellAddition(std::string id); + void sendSpellAddition(const ESM::Spell &spell); void sendSpellRemoval(std::string id); + void sendSpellRemoval(const ESM::Spell &spell); void sendAttack(Attack::TYPE type); void prepareAttack(Attack::TYPE type, bool state); diff --git a/apps/openmw/mwmp/Networking.cpp b/apps/openmw/mwmp/Networking.cpp index 6ea26f748..c68fe89b8 100644 --- a/apps/openmw/mwmp/Networking.cpp +++ b/apps/openmw/mwmp/Networking.cpp @@ -345,6 +345,38 @@ void Networking::processPlayerPacket(RakNet::Packet *packet) } case ID_GAME_SPELLBOOK: { + if (guid == myGuid) + { + if (packet->length == myPacket->headerSize()) + { + + } + else + { + myPacket->Packet(&bsIn, getLocalPlayer(), false); + const Spellbook& spellbook = getLocalPlayer()->spellbook; + MWWorld::Ptr playerptr = MWBase::Environment::get().getWorld()->getPlayerPtr(); + MWMechanics::Spells &spells = playerptr.getClass().getCreatureStats (playerptr).getSpells(); + if (spellbook.action == Spellbook::ADD) + for (vector::const_iterator spell = spellbook.spells.begin(); spell != spellbook.spells.end(); spell++) + spells.add (spell->mId); + else if (spellbook.action == Spellbook::REMOVE) + for (vector::const_iterator spell = spellbook.spells.begin(); spell != spellbook.spells.end(); spell++) + { + spells.remove (spell->mId); + + MWBase::WindowManager *wm = MWBase::Environment::get().getWindowManager(); + if (spell->mId == wm->getSelectedSpell()) + wm->unsetSelectedSpell(); + } + else // Spellbook::UPDATE + { + spells.clear(); + for (vector::const_iterator spell = spellbook.spells.begin(); spell != spellbook.spells.end(); spell++) + spells.add (spell->mId); + } + } + } break; } case ID_GAME_ATTACK: diff --git a/components/openmw-mp/Base/BasePlayer.hpp b/components/openmw-mp/Base/BasePlayer.hpp index a0dbda3a1..426fa5050 100644 --- a/components/openmw-mp/Base/BasePlayer.hpp +++ b/components/openmw-mp/Base/BasePlayer.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include namespace mwmp @@ -58,14 +59,9 @@ namespace mwmp int action; //0 - FullUpdate, 1 - AddItem, 2 - RemoveItem }; - struct Spell - { - std::string id; - }; - struct Spellbook { - std::vector spells; + std::vector spells; unsigned int count; enum ACTION_TYPE { diff --git a/components/openmw-mp/Packets/Player/PacketSpellbook.cpp b/components/openmw-mp/Packets/Player/PacketSpellbook.cpp index 1bbb995cc..256707d35 100644 --- a/components/openmw-mp/Packets/Player/PacketSpellbook.cpp +++ b/components/openmw-mp/Packets/Player/PacketSpellbook.cpp @@ -24,16 +24,16 @@ void PacketSpellbook::Packet(RakNet::BitStream *bs, BasePlayer *player, bool sen for (unsigned int i = 0; i < player->spellbook.count; i++) { - Spell spell; + ESM::Spell spell; if (send) { spell = player->spellbook.spells[i]; - RW(spell.id, send); + RW(spell.mId, send); } else { - RW(spell.id, send); + RW(spell.mId, send); player->spellbook.spells.push_back(spell); } }