diff --git a/apps/openmw-mp/processors/player/ProcessorPlayerFaction.hpp b/apps/openmw-mp/processors/player/ProcessorPlayerFaction.hpp index ffac74e88..304a56410 100644 --- a/apps/openmw-mp/processors/player/ProcessorPlayerFaction.hpp +++ b/apps/openmw-mp/processors/player/ProcessorPlayerFaction.hpp @@ -18,6 +18,8 @@ namespace mwmp { DEBUG_PRINTF(strPacketID.c_str()); + packet.Send(true); + Script::Call(player.getId()); } }; diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index eca8770b8..12bb1c3b3 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -107,9 +107,9 @@ add_openmw_dir (mwmp\\processors\\actor ProcessorActorAnimFlags ProcessorActorAn ) add_openmw_dir (mwmp\\processors\\player ProcessorChatMessage ProcessorGameConsole ProcessorGameTime ProcessorGUIMessageBox - ProcessorHandshake ProcessorUserDisconnected ProcessorUserMyID ProcessorPlayerBaseInfo - ProcessorPlayerAnimFlags ProcessorPlayerAttack ProcessorPlayerAttribute ProcessorPlayerBounty ProcessorPlayerCellChange - ProcessorPlayerCellState ProcessorPlayerCharClass ProcessorPlayerCharGen ProcessorPlayerDeath ProcessorPlayerEquipment + ProcessorHandshake ProcessorUserDisconnected ProcessorUserMyID ProcessorPlayerBaseInfo ProcessorPlayerAnimFlags + ProcessorPlayerAttack ProcessorPlayerAttribute ProcessorPlayerBounty ProcessorPlayerCellChange ProcessorPlayerCellState + ProcessorPlayerCharClass ProcessorPlayerCharGen ProcessorPlayerDeath ProcessorPlayerEquipment ProcessorPlayerFaction ProcessorPlayerInventory ProcessorPlayerJournal ProcessorPlayerLevel ProcessorPlayerPosition ProcessorPlayerResurrect ProcessorPlayerSkill ProcessorPlayerSpellbook ProcessorPlayerStatsDynamic ) diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index e18d32683..f16222a53 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -568,7 +568,6 @@ void LocalPlayer::updateAnimFlags(bool forceUpdate) MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); - MWMechanics::NpcStats ptrNpcStats = player.getClass().getNpcStats(player); using namespace MWMechanics; @@ -962,6 +961,41 @@ void LocalPlayer::setSpellbook() addSpells(); } +void LocalPlayer::setFactions() +{ + MWWorld::Ptr player = getPlayerPtr(); + MWMechanics::NpcStats &ptrNpcStats = player.getClass().getNpcStats(player); + + for (unsigned int i = 0; i < factionChanges.count; i++) + { + mwmp::Faction faction = factionChanges.factions.at(i); + + // If the player isn't in this faction, make them join it + if (!ptrNpcStats.isInFaction(faction.factionId)) + ptrNpcStats.joinFaction(faction.factionId); + + // While the faction rank is different in the packet than in the NpcStats, + // adjust the NpcStats accordingly + while (faction.rank != ptrNpcStats.getFactionRanks().at(faction.factionId)) + { + if (faction.rank > ptrNpcStats.getFactionRanks().at(faction.factionId)) + ptrNpcStats.raiseRank(faction.factionId); + else + ptrNpcStats.lowerRank(faction.factionId); + } + + // If the expelled state is different in the packet than in the NpcStats, + // adjust the NpcStats accordingly + if (faction.isExpelled != ptrNpcStats.getExpelled(faction.factionId)) + { + if (faction.isExpelled) + ptrNpcStats.expell(faction.factionId); + else + ptrNpcStats.clearExpelled(faction.factionId); + } + } +} + void LocalPlayer::sendClass() { MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -1117,6 +1151,21 @@ void LocalPlayer::sendJournalIndex(const std::string& quest, int index) getNetworking()->getPlayerPacket(ID_PLAYER_JOURNAL)->Send(); } +void LocalPlayer::sendFaction(const std::string& factionId, int rank, bool isExpelled) +{ + factionChanges.factions.clear(); + + mwmp::Faction faction; + faction.factionId = factionId; + faction.rank = rank; + faction.isExpelled = isExpelled; + + factionChanges.factions.push_back(faction); + + getNetworking()->getPlayerPacket(ID_PLAYER_FACTION)->setPlayer(this); + getNetworking()->getPlayerPacket(ID_PLAYER_FACTION)->Send(); +} + void LocalPlayer::clearCellStates() { cellStateChanges.cellStates.clear(); diff --git a/apps/openmw/mwmp/LocalPlayer.hpp b/apps/openmw/mwmp/LocalPlayer.hpp index cf4d27a60..948c975c5 100644 --- a/apps/openmw/mwmp/LocalPlayer.hpp +++ b/apps/openmw/mwmp/LocalPlayer.hpp @@ -57,6 +57,7 @@ namespace mwmp void setEquipment(); void setInventory(); void setSpellbook(); + void setFactions(); void sendClass(); void sendInventory(); @@ -66,8 +67,9 @@ namespace mwmp void sendSpellAddition(const ESM::Spell &spell); void sendSpellRemoval(std::string id); void sendSpellRemoval(const ESM::Spell &spell); - void sendJournalEntry(const std::string& id, int index, const MWWorld::Ptr& actor); - void sendJournalIndex(const std::string& id, int index); + void sendJournalEntry(const std::string& quest, int index, const MWWorld::Ptr& actor); + void sendJournalIndex(const std::string& quest, int index); + void sendFaction(const std::string& factionId, int rank, bool isExpelled); void clearCellStates(); void clearCurrentContainer(); diff --git a/apps/openmw/mwmp/processors/player/ProcessorPlayerFaction.hpp b/apps/openmw/mwmp/processors/player/ProcessorPlayerFaction.hpp index ef6d4f83a..a4a250f52 100644 --- a/apps/openmw/mwmp/processors/player/ProcessorPlayerFaction.hpp +++ b/apps/openmw/mwmp/processors/player/ProcessorPlayerFaction.hpp @@ -16,7 +16,12 @@ namespace mwmp virtual void Do(PlayerPacket &packet, BasePlayer *player) { - if (!isLocal()) return; + if (isRequest()) + { + // Entire faction membership cannot currently be requested from players + } + else + static_cast(player)->setFactions(); } }; } diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 52275c5a0..3194528d6 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -3,8 +3,16 @@ #include #include +/* + Start of tes3mp addition + + Include additional headers for multiplayer purposes +*/ #include "../mwmp/Main.hpp" #include "../mwmp/LocalPlayer.hpp" +/* + End of tes3mp addition +*/ #include @@ -595,6 +603,16 @@ namespace MWScript { MWWorld::Ptr player = MWMechanics::getPlayer(); player.getClass().getNpcStats(player).joinFaction(factionID); + + /* + Start of tes3mp addition + + Send an ID_PLAYER_FACTION packet every time a player joins a faction + */ + mwmp::Main::get().getLocalPlayer()->sendFaction(factionID, player.getClass().getNpcStats(player).getFactionRanks().at(factionID), false); + /* + End of tes3mp addition + */ } } }; @@ -634,6 +652,16 @@ namespace MWScript { player.getClass().getNpcStats(player).raiseRank(factionID); } + + /* + Start of tes3mp addition + + Send an ID_PLAYER_FACTION packet every time a player rises in a faction + */ + mwmp::Main::get().getLocalPlayer()->sendFaction(factionID, player.getClass().getNpcStats(player).getFactionRanks().at(factionID), player.getClass().getNpcStats(player).getExpelled(factionID)); + /* + End of tes3mp addition + */ } } }; @@ -666,6 +694,16 @@ namespace MWScript { MWWorld::Ptr player = MWMechanics::getPlayer(); player.getClass().getNpcStats(player).lowerRank(factionID); + + /* + Start of tes3mp addition + + Send an ID_PLAYER_FACTION packet every time a player falls in a faction + */ + mwmp::Main::get().getLocalPlayer()->sendFaction(factionID, player.getClass().getNpcStats(player).getFactionRanks().at(factionID), player.getClass().getNpcStats(player).getExpelled(factionID)); + /* + End of tes3mp addition + */ } } }; @@ -991,6 +1029,16 @@ namespace MWScript if(factionID!="") { player.getClass().getNpcStats(player).expell(factionID); + + /* + Start of tes3mp addition + + Send an ID_PLAYER_FACTION packet every time a player is expelled from a faction + */ + mwmp::Main::get().getLocalPlayer()->sendFaction(factionID, player.getClass().getNpcStats(player).getFactionRanks().at(factionID), true); + /* + End of tes3mp addition + */ } } }; @@ -1017,6 +1065,17 @@ namespace MWScript MWWorld::Ptr player = MWMechanics::getPlayer(); if(factionID!="") player.getClass().getNpcStats(player).clearExpelled(factionID); + + /* + Start of tes3mp addition + + Send an ID_PLAYER_FACTION packet every time a player is no longer expelled from a faction + */ + if (factionID != "") + mwmp::Main::get().getLocalPlayer()->sendFaction(factionID, player.getClass().getNpcStats(player).getFactionRanks().at(factionID), false); + /* + End of tes3mp addition + */ } }; diff --git a/components/openmw-mp/Base/BasePlayer.hpp b/components/openmw-mp/Base/BasePlayer.hpp index ed87bd46e..e9afac9eb 100644 --- a/components/openmw-mp/Base/BasePlayer.hpp +++ b/components/openmw-mp/Base/BasePlayer.hpp @@ -56,6 +56,13 @@ namespace mwmp int type; // 0 - An entire entry, 1 - An index }; + struct Faction + { + std::string factionId; + int rank; + bool isExpelled; + }; + struct CellState { ESM::Cell cell; @@ -75,6 +82,12 @@ namespace mwmp unsigned int count; }; + struct FactionChanges + { + std::vector factions; + unsigned int count; + }; + struct InventoryChanges { std::vector items; @@ -157,6 +170,7 @@ namespace mwmp InventoryChanges inventoryChanges; SpellbookChanges spellbookChanges; JournalChanges journalChanges; + FactionChanges factionChanges; CellStateChanges cellStateChanges; ESM::ActiveSpells activeSpells; CurrentContainer currentContainer; diff --git a/components/openmw-mp/Packets/Player/PacketPlayerFaction.cpp b/components/openmw-mp/Packets/Player/PacketPlayerFaction.cpp index 57c037a80..3f6b0eeb9 100644 --- a/components/openmw-mp/Packets/Player/PacketPlayerFaction.cpp +++ b/components/openmw-mp/Packets/Player/PacketPlayerFaction.cpp @@ -12,4 +12,26 @@ PacketPlayerFaction::PacketPlayerFaction(RakNet::RakPeerInterface *peer) : Playe void PacketPlayerFaction::Packet(RakNet::BitStream *bs, bool send) { PlayerPacket::Packet(bs, send); + + if (!send) + player->factionChanges.factions.clear(); + else + player->factionChanges.count = (unsigned int)(player->factionChanges.factions.size()); + + RW(player->factionChanges.count, send); + + for (unsigned int i = 0; i < player->factionChanges.count; i++) + { + Faction faction; + + if (send) + faction = player->factionChanges.factions.at(i); + + RW(faction.factionId, send); + RW(faction.rank, send); + RW(faction.isExpelled, send); + + if (!send) + player->factionChanges.factions.push_back(faction); + } }