[General] Rework ObjectDialogueChoice for multilingual compatibility

Use a different system for sending and applying ObjectDialogueChoice packets.
pull/593/head
David Cernat 4 years ago
parent 4620adc662
commit 1a4b817b31

@ -154,9 +154,14 @@ int ObjectFunctions::GetObjectLockLevel(unsigned int index) noexcept
return readObjectList->baseObjects.at(index).lockLevel;
}
const char* ObjectFunctions::GetObjectDialogueChoice(unsigned int index) noexcept
unsigned int ObjectFunctions::GetObjectDialogueChoiceType(unsigned int index) noexcept
{
return readObjectList->baseObjects.at(index).dialogueChoice.c_str();
return readObjectList->baseObjects.at(index).dialogueChoiceType;
}
const char* ObjectFunctions::GetObjectDialogueChoiceTopic(unsigned int index) noexcept
{
return readObjectList->baseObjects.at(index).topicId.c_str();
}
unsigned int ObjectFunctions::GetObjectGoldPool(unsigned int index) noexcept
@ -500,9 +505,14 @@ void ObjectFunctions::SetObjectLockLevel(int lockLevel) noexcept
tempObject.lockLevel = lockLevel;
}
void ObjectFunctions::SetObjectDialogueChoice(const char* dialogueChoice) noexcept
void ObjectFunctions::SetObjectDialogueChoiceType(unsigned int dialogueChoiceType) noexcept
{
tempObject.dialogueChoiceType = dialogueChoiceType;
}
void ObjectFunctions::SetObjectDialogueChoiceTopic(const char* topic) noexcept
{
tempObject.dialogueChoice = dialogueChoice;
tempObject.topicId = topic;
}
void ObjectFunctions::SetObjectGoldPool(unsigned int goldPool) noexcept

@ -31,7 +31,8 @@
{"GetObjectState", ObjectFunctions::GetObjectState},\
{"GetObjectDoorState", ObjectFunctions::GetObjectDoorState},\
{"GetObjectLockLevel", ObjectFunctions::GetObjectLockLevel},\
{"GetObjectDialogueChoice", ObjectFunctions::GetObjectDialogueChoice},\
{"GetObjectDialogueChoiceType", ObjectFunctions::GetObjectDialogueChoiceType},\
{"GetObjectDialogueChoiceTopic", ObjectFunctions::GetObjectDialogueChoiceTopic},\
{"GetObjectGoldPool", ObjectFunctions::GetObjectGoldPool},\
{"GetObjectLastGoldRestockHour", ObjectFunctions::GetObjectLastGoldRestockHour},\
{"GetObjectLastGoldRestockDay", ObjectFunctions::GetObjectLastGoldRestockDay},\
@ -106,7 +107,8 @@
{"SetObjectScale", ObjectFunctions::SetObjectScale},\
{"SetObjectState", ObjectFunctions::SetObjectState},\
{"SetObjectLockLevel", ObjectFunctions::SetObjectLockLevel},\
{"SetObjectDialogueChoice", ObjectFunctions::SetObjectDialogueChoice},\
{"SetObjectDialogueChoiceType", ObjectFunctions::SetObjectDialogueChoiceType},\
{"SetObjectDialogueChoiceTopic", ObjectFunctions::SetObjectDialogueChoiceTopic},\
{"SetObjectGoldPool", ObjectFunctions::SetObjectGoldPool},\
{"SetObjectLastGoldRestockHour", ObjectFunctions::SetObjectLastGoldRestockHour},\
{"SetObjectLastGoldRestockDay", ObjectFunctions::SetObjectLastGoldRestockDay},\
@ -393,12 +395,20 @@ public:
static int GetObjectLockLevel(unsigned int index) noexcept;
/**
* \brief Get the dialogue choice for the object at a certain index in the read object list.
* \brief Get the dialogue choice type for the object at a certain index in the read object list.
*
* \param index The index of the object.
* \return The dialogue choice.
* \return The dialogue choice type.
*/
static const char *GetObjectDialogueChoice(unsigned int index) noexcept;
static unsigned int GetObjectDialogueChoiceType(unsigned int index) noexcept;
/**
* \brief Get the dialogue choice topic for the object at a certain index in the read object list.
*
* \param index The index of the object.
* \return The dialogue choice topic.
*/
static const char *GetObjectDialogueChoiceTopic(unsigned int index) noexcept;
/**
* \brief Get the gold pool of the object at a certain index in the read object list.
@ -1000,12 +1010,20 @@ public:
static void SetObjectLockLevel(int lockLevel) noexcept;
/**
* \brief Set the dialogue choice for the temporary object stored on the server.
* \brief Set the dialogue choice type of the temporary object stored on the server.
*
* \param dialogueChoiceType The dialogue choice type.
* \return void
*/
static void SetObjectDialogueChoiceType(unsigned int dialogueChoiceType) noexcept;
/**
* \brief Set the dialogue choice topic for the temporary object stored on the server.
*
* \param dialogueChoice The dialogue choice.
* \param topic The dialogue choice topic.
* \return void
*/
static void SetObjectDialogueChoice(const char* dialogueChoice) noexcept;
static void SetObjectDialogueChoiceTopic(const char* topic) noexcept;
/**
* \brief Set the gold pool of the temporary object stored on the server.

@ -296,16 +296,7 @@ namespace MWGui
//Topics list
getWidget(mTopicsList, "TopicsList");
/*
Start of tes3mp change (major)
Instead of running DialogueWindow::onSelectListItem() when clicking a list item, run
onSendDialoguePacket() so the server can approve or deny a dialogue choice
*/
mTopicsList->eventItemSelected += MyGUI::newDelegate(this, &DialogueWindow::onSendDialoguePacket);
/*
End of tes3mp change (major)
*/
mTopicsList->eventItemSelected += MyGUI::newDelegate(this, &DialogueWindow::onSelectListItem);
getWidget(mGoodbyeButton, "ByeButton");
mGoodbyeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DialogueWindow::onByeClicked);
@ -382,27 +373,25 @@ namespace MWGui
}
}
/*
Start of tes3mp addition
A different event that should be used in multiplayer when clicking on list items
in the dialogue screen, sending DialogueChoice packets to the server so they can
be approved or denied
*/
void DialogueWindow::onSendDialoguePacket(const std::string& topic, int id)
void DialogueWindow::onSelectListItem(const std::string& topic, int id)
{
/*
Start of tes3mp change (major)
Instead of activating a list item here, send an ObjectDialogueChoice packet to the server
and let it decide whether the list item gets activated
*/
mwmp::ObjectList* objectList = mwmp::Main::get().getNetworking()->getObjectList();
objectList->reset();
objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY;
objectList->addObjectDialogueChoice(mPtr, topic, id);
objectList->sendObjectDialogueChoice();
}
/*
End of tes3mp addition
*/
void DialogueWindow::onSelectListItem(const std::string& topic, int id)
{
return;
/*
End of tes3mp change (major)
*/
MWBase::DialogueManager* dialogueManager = MWBase::Environment::get().getDialogueManager();
if (mGoodbye || dialogueManager->isInChoice())
@ -453,6 +442,49 @@ namespace MWGui
updateTopics();
}
/*
Start of tes3mp addition
Make it possible to activate any dialogue choice from elsewhere in the code
*/
void DialogueWindow::activateDialogueChoice(unsigned char dialogueChoiceType, std::string topic)
{
if (dialogueChoiceType == mwmp::DialogueChoiceType::TOPIC)
{
// If we're using a translated version of Morrowind, translate this topic from English into our language
if (MWBase::Environment::get().getWindowManager()->getTranslationDataStorage().hasTranslation())
topic = MWBase::Environment::get().getWindowManager()->getTranslationDataStorage().getLocalizedTopicId(topic);
onTopicActivated(topic);
}
else if (dialogueChoiceType == mwmp::DialogueChoiceType::PERSUASION)
mPersuasionDialog.setVisible(true);
else if (dialogueChoiceType == mwmp::DialogueChoiceType::COMPANION_SHARE)
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Companion, mPtr);
else
{
MWBase::DialogueManager* dialogueManager = MWBase::Environment::get().getDialogueManager();
if (dialogueChoiceType == mwmp::DialogueChoiceType::BARTER && !dialogueManager->checkServiceRefused(mCallback.get(), MWBase::DialogueManager::Barter))
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Barter, mPtr);
else if (dialogueChoiceType == mwmp::DialogueChoiceType::SPELLS && !dialogueManager->checkServiceRefused(mCallback.get(), MWBase::DialogueManager::Spells))
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_SpellBuying, mPtr);
else if (dialogueChoiceType == mwmp::DialogueChoiceType::TRAVEL && !dialogueManager->checkServiceRefused(mCallback.get(), MWBase::DialogueManager::Travel))
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Travel, mPtr);
else if (dialogueChoiceType == mwmp::DialogueChoiceType::SPELLMAKING && !dialogueManager->checkServiceRefused(mCallback.get(), MWBase::DialogueManager::Spellmaking))
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_SpellCreation, mPtr);
else if (dialogueChoiceType == mwmp::DialogueChoiceType::ENCHANTING && !dialogueManager->checkServiceRefused(mCallback.get(), MWBase::DialogueManager::Enchanting))
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Enchanting, mPtr);
else if (dialogueChoiceType == mwmp::DialogueChoiceType::TRAINING && !dialogueManager->checkServiceRefused(mCallback.get(), MWBase::DialogueManager::Training))
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Training, mPtr);
else if (dialogueChoiceType == mwmp::DialogueChoiceType::REPAIR && !dialogueManager->checkServiceRefused(mCallback.get(), MWBase::DialogueManager::Repair))
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_MerchantRepair, mPtr);
}
}
/*
End of tes3mp addition
*/
/*
Start of tes3mp addition

@ -120,6 +120,16 @@ namespace MWGui
void notifyLinkClicked (TypesetBook::InteractiveId link);
/*
Start of tes3mp addition
Make it possible to activate any dialogue choice from elsewhere in the code
*/
void activateDialogueChoice(unsigned char dialogueChoiceType, std::string topic = "");
/*
End of tes3mp addition
*/
/*
Start of tes3mp addition
@ -150,30 +160,7 @@ namespace MWGui
bool isCompanion(const MWWorld::Ptr& actor);
bool isCompanion();
/*
Start of tes3mp addition
A different event that should be used in multiplayer when clicking on list items
in the dialogue screen, sending DialogueChoice packets to the server so they can
be approved or denied
*/
void onSendDialoguePacket(const std::string& topic, int id);
/*
End of tes3mp addition
*/
/*
Start of tes3mp change (major)
Turn onSelectListItem() into a public function so it can be used elsewhere when
receiving ObjectDialogueChoice packets
*/
public:
void onSelectListItem(const std::string& topic, int id);
protected:
/*
End of tes3mp change (major)
*/
void onByeClicked(MyGUI::Widget* _sender);
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
void onWindowResize(MyGUI::Window* _sender);

@ -8,6 +8,7 @@
#include "CellController.hpp"
#include "RecordHelper.hpp"
#include <components/translation/translation.hpp>
#include <components/openmw-mp/TimedLog.hpp>
#include "../mwbase/world.hpp"
@ -1007,8 +1008,8 @@ void ObjectList::makeDialogueChoices(MWWorld::CellStore* cellStore)
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Dialogue, ptrFound);
}
LOG_APPEND(TimedLog::LOG_VERBOSE, "-- Making dialogue choice of %s", baseObject.dialogueChoice);
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->onSelectListItem(baseObject.dialogueChoice, baseObject.guiId);
LOG_APPEND(TimedLog::LOG_VERBOSE, "-- Making dialogue choice of type %i", baseObject.dialogueChoiceType);
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->activateDialogueChoice(baseObject.dialogueChoiceType, baseObject.topicId);
}
else
{
@ -1272,7 +1273,40 @@ void ObjectList::addObjectDialogueChoice(const MWWorld::Ptr& ptr, std::string di
cell = *ptr.getCell()->getCell();
mwmp::BaseObject baseObject = getBaseObjectFromPtr(ptr);
baseObject.dialogueChoice = dialogueChoice;
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
// Because the actual text for any of the special dialogue choices can vary according to the game language used,
// set the type of dialogue choice by doing a lot of checks
if (dialogueChoice == gmst.find("sPersuasion")->mValue.getString())
baseObject.dialogueChoiceType = static_cast<int>(DialogueChoiceType::PERSUASION);
else if (dialogueChoice == gmst.find("sCompanionShare")->mValue.getString())
baseObject.dialogueChoiceType = DialogueChoiceType::COMPANION_SHARE;
else if (dialogueChoice == gmst.find("sBarter")->mValue.getString())
baseObject.dialogueChoiceType = DialogueChoiceType::BARTER;
else if (dialogueChoice == gmst.find("sSpells")->mValue.getString())
baseObject.dialogueChoiceType = DialogueChoiceType::SPELLS;
else if (dialogueChoice == gmst.find("sTravel")->mValue.getString())
baseObject.dialogueChoiceType = DialogueChoiceType::TRAVEL;
else if (dialogueChoice == gmst.find("sSpellMakingMenuTitle")->mValue.getString())
baseObject.dialogueChoiceType = DialogueChoiceType::SPELLMAKING;
else if (dialogueChoice == gmst.find("sEnchanting")->mValue.getString())
baseObject.dialogueChoiceType = DialogueChoiceType::ENCHANTING;
else if (dialogueChoice == gmst.find("sServiceTrainingTitle")->mValue.getString())
baseObject.dialogueChoiceType = DialogueChoiceType::TRAINING;
else if (dialogueChoice == gmst.find("sRepair")->mValue.getString())
baseObject.dialogueChoiceType = DialogueChoiceType::REPAIR;
else
{
baseObject.dialogueChoiceType = DialogueChoiceType::TOPIC;
// For translated versions of the game, make sure we translate the topic back into English first
if (MWBase::Environment::get().getWindowManager()->getTranslationDataStorage().hasTranslation())
baseObject.topicId = MWBase::Environment::get().getWindowManager()->getTranslationDataStorage().topicID(dialogueChoice);
else
baseObject.topicId = dialogueChoice;
}
baseObject.guiId = guiId;
addBaseObject(baseObject);
}

@ -41,7 +41,8 @@ namespace mwmp
int lockLevel;
float scale;
std::string dialogueChoice;
unsigned char dialogueChoiceType;
std::string topicId;
int guiId;
std::string soundId;

@ -10,6 +10,23 @@
namespace mwmp
{
namespace DialogueChoiceType
{
enum DIALOGUE_CHOICE
{
TOPIC,
PERSUASION,
COMPANION_SHARE,
BARTER,
SPELLS,
TRAVEL,
SPELLMAKING,
ENCHANTING,
TRAINING,
REPAIR
};
}
enum PACKET_ORIGIN
{
CLIENT_GAMEPLAY = 0,

@ -12,6 +12,10 @@ PacketObjectDialogueChoice::PacketObjectDialogueChoice(RakNet::RakPeerInterface
void PacketObjectDialogueChoice::Object(BaseObject& baseObject, bool send)
{
ObjectPacket::Object(baseObject, send);
RW(baseObject.dialogueChoice, send, true);
RW(baseObject.dialogueChoiceType, send);
if (baseObject.dialogueChoiceType == DialogueChoiceType::TOPIC)
RW(baseObject.topicId, send, true);
RW(baseObject.guiId, send);
}

Loading…
Cancel
Save