diff --git a/apps/openmw-mp/Player.hpp b/apps/openmw-mp/Player.hpp index c6bdc43d8..b1dc900ae 100644 --- a/apps/openmw-mp/Player.hpp +++ b/apps/openmw-mp/Player.hpp @@ -76,6 +76,7 @@ public: mwmp::JournalChanges journalChangesBuffer; mwmp::FactionChanges factionChangesBuffer; mwmp::TopicChanges topicChangesBuffer; + mwmp::KillChanges killChangesBuffer; private: CellController::TContainer cells; diff --git a/apps/openmw-mp/Script/Functions/Dialogue.cpp b/apps/openmw-mp/Script/Functions/Dialogue.cpp index b467640fe..cda37a025 100644 --- a/apps/openmw-mp/Script/Functions/Dialogue.cpp +++ b/apps/openmw-mp/Script/Functions/Dialogue.cpp @@ -14,6 +14,14 @@ unsigned int DialogueFunctions::GetTopicChangesSize(unsigned short pid) noexcept return player->topicChanges.count; } +unsigned int DialogueFunctions::GetKillChangesSize(unsigned short pid) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + return player->killChanges.count; +} + void DialogueFunctions::AddTopic(unsigned short pid, const char* topicId) noexcept { Player *player; @@ -25,6 +33,18 @@ void DialogueFunctions::AddTopic(unsigned short pid, const char* topicId) noexce player->topicChangesBuffer.topics.push_back(topic); } +void DialogueFunctions::AddKill(unsigned short pid, const char* refId, int number) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + mwmp::Kill kill; + kill.refId = refId; + kill.number = number; + + player->killChangesBuffer.kills.push_back(kill); +} + const char *DialogueFunctions::GetTopicId(unsigned short pid, unsigned int i) noexcept { Player *player; @@ -36,6 +56,25 @@ const char *DialogueFunctions::GetTopicId(unsigned short pid, unsigned int i) no return player->topicChanges.topics.at(i).topicId.c_str(); } +const char *DialogueFunctions::GetKillRefId(unsigned short pid, unsigned int i) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ""); + + if (i >= player->killChanges.count) + return "invalid"; + + return player->killChanges.kills.at(i).refId.c_str(); +} + +int DialogueFunctions::GetKillNumber(unsigned short pid, unsigned int i) noexcept +{ + Player *player; + GET_PLAYER(pid, player, 0); + + return player->killChanges.kills.at(i).number; +} + void DialogueFunctions::SendTopicChanges(unsigned short pid) noexcept { Player *player; @@ -47,3 +86,15 @@ void DialogueFunctions::SendTopicChanges(unsigned short pid) noexcept player->topicChanges = std::move(player->topicChangesBuffer); player->topicChangesBuffer.topics.clear(); } + +void DialogueFunctions::SendKillChanges(unsigned short pid) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + std::swap(player->killChanges, player->killChangesBuffer); + mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_KILL_COUNT)->setPlayer(player); + mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_KILL_COUNT)->Send(false); + player->killChanges = std::move(player->killChangesBuffer); + player->killChangesBuffer.kills.clear(); +} diff --git a/apps/openmw-mp/Script/Functions/Dialogue.hpp b/apps/openmw-mp/Script/Functions/Dialogue.hpp index db16fe201..e1773cc5a 100644 --- a/apps/openmw-mp/Script/Functions/Dialogue.hpp +++ b/apps/openmw-mp/Script/Functions/Dialogue.hpp @@ -3,24 +3,34 @@ #define DIALOGUEAPI \ {"GetTopicChangesSize", DialogueFunctions::GetTopicChangesSize},\ + {"GetKillChangesSize", DialogueFunctions::GetKillChangesSize},\ \ {"AddTopic", DialogueFunctions::AddTopic},\ + {"AddKill", DialogueFunctions::AddKill},\ \ {"GetTopicId", DialogueFunctions::GetTopicId},\ + {"GetKillRefId", DialogueFunctions::GetKillRefId},\ + {"GetKillNumber", DialogueFunctions::GetKillNumber},\ \ - {"SendTopicChanges", DialogueFunctions::SendTopicChanges} + {"SendTopicChanges", DialogueFunctions::SendTopicChanges},\ + {"SendKillChanges", DialogueFunctions::SendKillChanges} class DialogueFunctions { public: static unsigned int GetTopicChangesSize(unsigned short pid) noexcept; + static unsigned int GetKillChangesSize(unsigned short pid) noexcept; static void AddTopic(unsigned short pid, const char* topicId) noexcept; + static void AddKill(unsigned short pid, const char* refId, int number) noexcept; static const char *GetTopicId(unsigned short pid, unsigned int i) noexcept; + static const char *GetKillRefId(unsigned short pid, unsigned int i) noexcept; + static int GetKillNumber(unsigned short pid, unsigned int i) noexcept; static void SendTopicChanges(unsigned short pid) noexcept; + static void SendKillChanges(unsigned short pid) noexcept; private: }; diff --git a/apps/openmw-mp/processors/player/ProcessorPlayerKillCount.hpp b/apps/openmw-mp/processors/player/ProcessorPlayerKillCount.hpp index 89843bf01..86f171332 100644 --- a/apps/openmw-mp/processors/player/ProcessorPlayerKillCount.hpp +++ b/apps/openmw-mp/processors/player/ProcessorPlayerKillCount.hpp @@ -17,6 +17,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 a31e0f66a..613dc1d0f 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -116,8 +116,9 @@ add_openmw_dir (mwmp/processors/player ProcessorChatMessage ProcessorGUIMessageB ProcessorPlayerAnimFlags ProcessorPlayerAnimPlay ProcessorPlayerAttack ProcessorPlayerAttribute ProcessorPlayerBook ProcessorPlayerBounty ProcessorPlayerCellChange ProcessorPlayerCellState ProcessorPlayerCharClass ProcessorPlayerCharGen ProcessorPlayerDeath ProcessorPlayerDisposition ProcessorPlayerEquipment ProcessorPlayerFaction ProcessorPlayerInventory - ProcessorPlayerJournal ProcessorPlayerLevel ProcessorPlayerMap ProcessorPlayerPosition ProcessorPlayerResurrect - ProcessorPlayerSkill ProcessorPlayerSpeech ProcessorPlayerSpellbook ProcessorPlayerStatsDynamic ProcessorPlayerTopic + ProcessorPlayerJournal ProcessorPlayerKillCount ProcessorPlayerLevel ProcessorPlayerMap ProcessorPlayerPosition + ProcessorPlayerResurrect ProcessorPlayerSkill ProcessorPlayerSpeech ProcessorPlayerSpellbook ProcessorPlayerStatsDynamic + ProcessorPlayerTopic ) add_openmw_dir (mwmp/processors/world BaseObjectProcessor ProcessorContainer ProcessorDoorState ProcessorMusicPlay diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index bd0d2ea4a..84063247d 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -104,6 +104,16 @@ namespace MWBase virtual int countDeaths (const std::string& id) const = 0; ///< Return the number of deaths for actors with the given ID. + /* + Start of tes3mp addition + + Make it possible to set the number of deaths for an actor with the given refId + */ + virtual void setDeaths(const std::string& refId, int number) = 0; + /* + End of tes3mp addition + */ + /// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check! virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer) = 0; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index d0656270b..c7c2e206c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1484,6 +1484,23 @@ namespace MWMechanics ++mDeathCount[Misc::StringUtils::lowerCase(iter->first.getCellRef().getRefId())]; + /* + Start of tes3mp addition + + Send an ID_PLAYER_KILL_COUNT packet every time the kill count changes, + as long as we are the authority over the actor's cell + */ + if (mwmp::Main::get().getCellController()->isLocalActor(iter->first)) + { + std::string refId = Misc::StringUtils::lowerCase(iter->first.getCellRef().getRefId()); + int number = mDeathCount[refId]; + + mwmp::Main::get().getLocalPlayer()->sendKill(refId, number); + } + /* + End of tes3mp addition + */ + // Make sure spell effects are removed purgeSpellEffects(stats.getActorId()); @@ -1615,6 +1632,19 @@ namespace MWMechanics return 0; } + /* + Start of tes3mp addition + + Make it possible to set the number of deaths for an actor with the given refId + */ + void Actors::setDeaths(const std::string& refId, int number) + { + mDeathCount[refId] = number; + } + /* + End of tes3mp addition + */ + void Actors::forceStateUpdate(const MWWorld::Ptr & ptr) { PtrActorMap::iterator iter = mActors.find(ptr); diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 362c2f126..0e59ce1ba 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -107,6 +107,16 @@ namespace MWMechanics int countDeaths (const std::string& id) const; ///< Return the number of deaths for actors with the given ID. + /* + Start of tes3mp addition + + Make it possible to set the number of deaths for an actor with the given refId + */ + void setDeaths(const std::string& refId, int number); + /* + End of tes3mp addition + */ + void forceStateUpdate(const MWWorld::Ptr &ptr); bool playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number, bool persist=false); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index da4ca0695..5a280416e 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -637,6 +637,19 @@ namespace MWMechanics return mActors.countDeaths (id); } + /* + Start of tes3mp addition + + Make it possible to set the number of deaths for an actor with the given refId + */ + void MechanicsManager::setDeaths(const std::string& refId, int number) + { + mActors.setDeaths(refId, number); + } + /* + End of tes3mp addition + */ + void MechanicsManager::getPersuasionDispositionChange (const MWWorld::Ptr& npc, PersuasionType type, bool& success, float& tempChange, float& permChange) { const MWWorld::Store &gmst = diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index ed06f58c5..55481024c 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -107,6 +107,16 @@ namespace MWMechanics virtual int countDeaths (const std::string& id) const; ///< Return the number of deaths for actors with the given ID. + /* + Start of tes3mp addition + + Make it possible to set the number of deaths for an actor with the given refId + */ + virtual void setDeaths(const std::string& refId, int number); + /* + End of tes3mp addition + */ + virtual void getPersuasionDispositionChange (const MWWorld::Ptr& npc, PersuasionType type, bool& success, float& tempChange, float& permChange); ///< Perform a persuasion action on NPC diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index 5d3116435..e44f46037 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -1014,6 +1014,18 @@ void LocalPlayer::setFactions() } } +void LocalPlayer::setKills() +{ + for (unsigned int i = 0; i < killChanges.count; i++) + { + mwmp::Kill kill = killChanges.kills.at(i); + std::string refId = kill.refId; + int number = kill.number; + + MWBase::Environment::get().getMechanicsManager()->setDeaths(refId, number); + } +} + void LocalPlayer::sendClass() { MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -1204,6 +1216,22 @@ void LocalPlayer::sendTopic(const std::string& topicId) getNetworking()->getPlayerPacket(ID_PLAYER_TOPIC)->Send(); } +void LocalPlayer::sendKill(const std::string& refId, int number) +{ + killChanges.kills.clear(); + + mwmp::Kill kill; + kill.refId = refId; + kill.number = number; + + LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Sending ID_PLAYER_KILL_COUNT with refId %s, number %i", refId.c_str(), number); + + killChanges.kills.push_back(kill); + + getNetworking()->getPlayerPacket(ID_PLAYER_KILL_COUNT)->setPlayer(this); + getNetworking()->getPlayerPacket(ID_PLAYER_KILL_COUNT)->Send(); +} + void LocalPlayer::clearCellStates() { cellStateChanges.cellStates.clear(); diff --git a/apps/openmw/mwmp/LocalPlayer.hpp b/apps/openmw/mwmp/LocalPlayer.hpp index afafef167..66e0611ea 100644 --- a/apps/openmw/mwmp/LocalPlayer.hpp +++ b/apps/openmw/mwmp/LocalPlayer.hpp @@ -59,6 +59,7 @@ namespace mwmp void setInventory(); void setSpellbook(); void setFactions(); + void setKills(); void sendClass(); void sendInventory(); @@ -72,6 +73,7 @@ namespace mwmp void sendJournalIndex(const std::string& quest, int index); void sendFaction(const std::string& factionId, int rank, bool isExpelled); void sendTopic(const std::string& topic); + void sendKill(const std::string& refId, int number); void clearCellStates(); void clearCurrentContainer(); diff --git a/apps/openmw/mwmp/processors/ProcessorInitializer.cpp b/apps/openmw/mwmp/processors/ProcessorInitializer.cpp index 076a643f9..1fcba13ad 100644 --- a/apps/openmw/mwmp/processors/ProcessorInitializer.cpp +++ b/apps/openmw/mwmp/processors/ProcessorInitializer.cpp @@ -30,6 +30,7 @@ #include "player/ProcessorPlayerFaction.hpp" #include "player/ProcessorPlayerInventory.hpp" #include "player/ProcessorPlayerJournal.hpp" +#include "player/ProcessorPlayerKillCount.hpp" #include "player/ProcessorPlayerLevel.hpp" #include "player/ProcessorPlayerMap.hpp" #include "player/ProcessorPlayerPosition.hpp" @@ -103,6 +104,7 @@ void ProcessorInitializer() PlayerProcessor::AddProcessor(new ProcessorPlayerFaction()); PlayerProcessor::AddProcessor(new ProcessorPlayerInventory()); PlayerProcessor::AddProcessor(new ProcessorPlayerJournal()); + PlayerProcessor::AddProcessor(new ProcessorPlayerKillCount()); PlayerProcessor::AddProcessor(new ProcessorPlayerLevel()); PlayerProcessor::AddProcessor(new ProcessorPlayerMap()); PlayerProcessor::AddProcessor(new ProcessorPlayerPosition()); diff --git a/apps/openmw/mwmp/processors/player/ProcessorPlayerKillCount.hpp b/apps/openmw/mwmp/processors/player/ProcessorPlayerKillCount.hpp new file mode 100644 index 000000000..17b9440ae --- /dev/null +++ b/apps/openmw/mwmp/processors/player/ProcessorPlayerKillCount.hpp @@ -0,0 +1,30 @@ +#ifndef OPENMW_PROCESSORPLAYERKILLCOUNT_HPP +#define OPENMW_PROCESSORPLAYERKILLCOUNT_HPP + +#include "../PlayerProcessor.hpp" + +namespace mwmp +{ + class ProcessorPlayerKillCount : public PlayerProcessor + { + public: + ProcessorPlayerKillCount() + { + BPP_INIT(ID_PLAYER_KILL_COUNT) + } + + virtual void Do(PlayerPacket &packet, BasePlayer *player) + { + if (isRequest()) + { + // Entire list of topics cannot currently be requested from players + } + else if (player != 0) + { + static_cast(player)->setKills(); + } + } + }; +} + +#endif //OPENMW_PROCESSORPLAYERKILLCOUNT_HPP diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index ffa7de76c..8faa880c4 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -178,10 +178,11 @@ add_component_dir (openmw-mp/Packets/Player PlayerPacket PacketHandshake PacketChatMessage PacketGUIBoxes PacketGameTime PacketGameWeather PacketPlayerBaseInfo PacketPlayerCharGen PacketPlayerActiveSkills PacketPlayerAnimFlags PacketPlayerAnimPlay PacketPlayerAttack PacketPlayerAttribute - PacketPlayerBook PacketPlayerBounty PacketPlayerCellChange PacketPlayerCellState PacketPlayerClass PacketPlayerDeath - PacketPlayerEquipment PacketPlayerFaction PacketPlayerInventory PacketPlayerJournal PacketPlayerLevel PacketPlayerMap - PacketPlayerPosition PacketPlayerRegionAuthority PacketPlayerRegionChange PacketPlayerRest PacketPlayerResurrect - PacketPlayerSkill PacketPlayerSpeech PacketPlayerSpellbook PacketPlayerStatsDynamic PacketPlayerTopic + PacketPlayerBook PacketPlayerBounty PacketPlayerCellChange PacketPlayerCellState PacketPlayerClass + PacketPlayerDeath PacketPlayerEquipment PacketPlayerFaction PacketPlayerInventory PacketPlayerJournal + PacketPlayerKillCount PacketPlayerLevel PacketPlayerMap PacketPlayerPosition PacketPlayerRegionAuthority + PacketPlayerRest PacketPlayerResurrect 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 a7282ed75..42db1e83b 100644 --- a/components/openmw-mp/Base/BasePlayer.hpp +++ b/components/openmw-mp/Base/BasePlayer.hpp @@ -56,6 +56,12 @@ namespace mwmp std::string topicId; }; + struct Kill + { + std::string refId; + int number; + }; + struct CellState { ESM::Cell cell; @@ -87,6 +93,12 @@ namespace mwmp unsigned int count; }; + struct KillChanges + { + std::vector kills; + unsigned int count; + }; + struct InventoryChanges { std::vector items; @@ -171,6 +183,7 @@ namespace mwmp JournalChanges journalChanges; FactionChanges factionChanges; TopicChanges topicChanges; + KillChanges killChanges; CellStateChanges cellStateChanges; ESM::ActiveSpells activeSpells; CurrentContainer currentContainer; diff --git a/components/openmw-mp/Packets/Player/PacketPlayerKillCount.cpp b/components/openmw-mp/Packets/Player/PacketPlayerKillCount.cpp index 010bf8921..df648dd35 100644 --- a/components/openmw-mp/Packets/Player/PacketPlayerKillCount.cpp +++ b/components/openmw-mp/Packets/Player/PacketPlayerKillCount.cpp @@ -10,5 +10,24 @@ void mwmp::PacketPlayerKillCount::Packet(RakNet::BitStream *bs, bool send) { PlayerPacket::Packet(bs, send); - // Placeholder to be filled in later + if (send) + player->killChanges.count = (unsigned int)(player->killChanges.kills.size()); + else + player->killChanges.kills.clear(); + + RW(player->killChanges.count, send); + + for (unsigned int i = 0; i < player->killChanges.count; i++) + { + Kill kill; + + if (send) + kill = player->killChanges.kills.at(i); + + RW(kill.refId, send, 1); + RW(kill.number, send); + + if (!send) + player->killChanges.kills.push_back(kill); + } }