Add TES3MP 0.8.0 commits up to 28 Apr 2022

# Conflicts:
#	apps/openmw/mwclass/creature.cpp
#	apps/openmw/mwclass/npc.cpp
0.8.0-vr
David Cernat 3 years ago
commit a032c8d399

@ -10,7 +10,7 @@ When it's combined with Mads Buvik Sandvei's [fork adding VR support to OpenMW](
* TES3MP version: 0.8.0
* OpenMW version: 0.47.0
* License: GPLv3 (see [LICENSE](https://github.com/TES3MP/TES3MP/blob/master/LICENSE) for more information)
* License: GPLv3 with additional allowed terms (see [LICENSE](https://github.com/TES3MP/TES3MP/blob/master/LICENSE) for more information)
Font Licenses:
* DejaVuLGCSansMono.ttf: custom (see [files/mygui/DejaVuFontLicense.txt](https://github.com/TES3MP/TES3MP/blob/master/files/mygui/DejaVuFontLicense.txt) for more information)

@ -489,7 +489,7 @@ void signalHandler(int signum)
{
std::cout << "Interrupt signal (" << signum << ") received.\n";
//15 is SIGTERM(Normal OS stop call), 2 is SIGINT(Ctrl+C)
if(signum == 15 or signum == 2)
if(signum == 15 || signum == 2)
{
killLoop = true;
}
@ -507,7 +507,7 @@ int Networking::mainLoop()
sigIntHandler.sa_flags = 0;
#endif
while (running and !killLoop)
while (running && !killLoop)
{
#ifndef _WIN32
sigaction(SIGTERM, &sigIntHandler, NULL);

@ -15,6 +15,7 @@ namespace mwmp
void Do(ActorPacket &packet, Player &player, BaseActorList &actorList) override
{
bool isAccepted = false;
Cell *serverCell = CellController::get()->getCell(&actorList.cell);
if (serverCell != nullptr)
@ -31,17 +32,26 @@ namespace mwmp
}
}
// Only accept regular cell changes from a cell's authority, but accept follower
// If the cell is loaded, only accept regular cell changes from a cell's authority, but accept follower
// cell changes from other players
if (*serverCell->getAuthority() == actorList.guid || isFollowerCellChange)
{
serverCell->removeActors(&actorList);
isAccepted = true;
}
}
// If the cell isn't loaded, the packet must be from dialogue or a script, so accept it
else
{
isAccepted = true;
}
Script::Call<Script::CallbackIdentity("OnActorCellChange")>(player.getId(), actorList.cell.getShortDescription().c_str());
if (isAccepted)
{
Script::Call<Script::CallbackIdentity("OnActorCellChange")>(player.getId(), actorList.cell.getShortDescription().c_str());
// Send this to everyone
packet.Send(true);
}
// Send this to everyone
packet.Send(true);
}
}
};

@ -698,7 +698,15 @@ void OMW::Engine::createWindow(Settings::Manager& settings)
{
while (!mWindow)
{
mWindow = SDL_CreateWindow("OpenMW", pos_x, pos_y, width, height, flags);
/*
Start of tes3mp change (major)
Rename the window into TES3MP
*/
mWindow = SDL_CreateWindow("TES3MP", pos_x, pos_y, width, height, flags);
/*
End of tes3mp change (major)
*/
if (!mWindow)
{
// Try with a lower AA
@ -776,7 +784,15 @@ void OMW::Engine::createWindow(Settings::Manager& settings)
void OMW::Engine::setWindowIcon()
{
boost::filesystem::ifstream windowIconStream;
std::string windowIcon = (mResDir / "mygui" / "openmw.png").string();
/*
Start of tes3mp change (major)
Use TES3MP's logo for the window icon
*/
std::string windowIcon = (mResDir / "mygui" / "tes3mp_logo.png").string();
/*
End of tes3mp change (major)
*/
windowIconStream.open(windowIcon, std::ios_base::in | std::ios_base::binary);
if (windowIconStream.fail())
Log(Debug::Error) << "Error: Failed to open " << windowIcon;

@ -279,11 +279,23 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
engine.setCompileAll(variables["script-all"].as<bool>());
engine.setCompileAllDialogue(variables["script-all-dialogue"].as<bool>());
engine.setScriptConsoleMode (variables["script-console"].as<bool>());
/*
Start of tes3mp change (major)
Clients should not be allowed to set any of these unilaterally in multiplayer, so
disable them
*/
/*
engine.setStartupScript (variables["script-run"].as<Files::EscapeHashString>().toStdString());
engine.setWarningsMode (variables["script-warn"].as<int>());
engine.setScriptBlacklist (variables["script-blacklist"].as<Files::EscapeStringVector>().toStdStringVector());
engine.setScriptBlacklistUse (variables["script-blacklist-use"].as<bool>());
engine.setSaveGameFile (variables["load-savegame"].as<Files::EscapePath>().mPath.string());
*/
/*
End of tes3mp change (major)
*/
// other settings
Fallback::Map::init(variables["fallback"].as<FallbackMap>().mMap);

@ -17,6 +17,17 @@
#include "../mwworld/esmstore.hpp"
#include "../mwworld/player.hpp"
/*
Start of tes3mp addition
Include additional headers for multiplayer purposes
*/
#include "../mwmp/Main.hpp"
#include "../mwmp/LocalPlayer.hpp"
/*
End of tes3mp addition
*/
#include "textinput.hpp"
#include "race.hpp"
#include "class.hpp"
@ -329,6 +340,16 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Birth);
/*
Start of tes3mp addition
Decrease the character generation stage tracked for the LocalPlayer
*/
mwmp::Main::get().getLocalPlayer()->charGenState.currentStage--;
/*
End of tes3mp addition
*/
}
void CharacterCreation::onReviewActivateDialog(int parDialog)
@ -381,6 +402,16 @@ namespace MWGui
selectPickedClass();
handleDialogDone(CSE_ClassChosen, GM_Birth);
/*
Start of tes3mp addition
Increase the character generation stage tracked for the LocalPlayer
*/
mwmp::Main::get().getLocalPlayer()->charGenState.currentStage++;
/*
End of tes3mp addition
*/
}
void CharacterCreation::onPickClassDialogBack()
@ -411,6 +442,16 @@ namespace MWGui
break;
case ClassChoiceDialog::Class_Back:
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Race);
/*
Start of tes3mp addition
Decrease the character generation stage tracked for the LocalPlayer
*/
mwmp::Main::get().getLocalPlayer()->charGenState.currentStage--;
/*
End of tes3mp addition
*/
break;
};
@ -439,6 +480,16 @@ namespace MWGui
}
handleDialogDone(CSE_NameChosen, GM_Race);
/*
Start of tes3mp addition
Increase the character generation stage tracked for the LocalPlayer
*/
mwmp::Main::get().getLocalPlayer()->charGenState.currentStage++;
/*
End of tes3mp addition
*/
}
void CharacterCreation::selectRace()
@ -477,6 +528,16 @@ namespace MWGui
selectRace();
handleDialogDone(CSE_RaceChosen, GM_Class);
/*
Start of tes3mp addition
Increase the character generation stage tracked for the LocalPlayer
*/
mwmp::Main::get().getLocalPlayer()->charGenState.currentStage++;
/*
End of tes3mp addition
*/
}
void CharacterCreation::selectBirthSign()
@ -498,6 +559,16 @@ namespace MWGui
selectBirthSign();
handleDialogDone(CSE_BirthSignChosen, GM_Review);
/*
Start of tes3mp addition
Increase the character generation stage tracked for the LocalPlayer
*/
mwmp::Main::get().getLocalPlayer()->charGenState.currentStage++;
/*
End of tes3mp addition
*/
}
void CharacterCreation::onBirthSignDialogBack()
@ -506,6 +577,16 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
/*
Start of tes3mp addition
Decrease the character generation stage tracked for the LocalPlayer
*/
mwmp::Main::get().getLocalPlayer()->charGenState.currentStage--;
/*
End of tes3mp addition
*/
}
void CharacterCreation::selectCreatedClass()
@ -547,6 +628,16 @@ namespace MWGui
selectCreatedClass();
handleDialogDone(CSE_ClassChosen, GM_Birth);
/*
Start of tes3mp addition
Increase the character generation stage tracked for the LocalPlayer
*/
mwmp::Main::get().getLocalPlayer()->charGenState.currentStage++;
/*
End of tes3mp addition
*/
}
void CharacterCreation::onCreateClassDialogBack()
@ -556,6 +647,16 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
/*
Start of tes3mp addition
Decrease the character generation stage tracked for the LocalPlayer
*/
mwmp::Main::get().getLocalPlayer()->charGenState.currentStage--;
/*
End of tes3mp addition
*/
}
void CharacterCreation::onClassQuestionChosen(int _index)
@ -748,6 +849,16 @@ namespace MWGui
selectGeneratedClass();
handleDialogDone(CSE_ClassChosen, GM_Birth);
/*
Start of tes3mp addition
Increase the character generation stage tracked for the LocalPlayer
*/
mwmp::Main::get().getLocalPlayer()->charGenState.currentStage++;
/*
End of tes3mp addition
*/
}
CharacterCreation::~CharacterCreation()

@ -301,27 +301,33 @@ namespace MWGui
/*
Start of tes3mp addition
Trigger crimes related to the attempted taking of these items, if applicable
Send an ID_CONTAINER packet every time the Take All button is used on
a container
*/
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
objectList->reset();
objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY;
objectList->cell = *mPtr.getCell()->getCell();
objectList->action = mwmp::BaseObjectList::REMOVE;
objectList->containerSubAction = mwmp::BaseObjectList::TAKE_ALL;
mwmp::BaseObject baseObject = objectList->getBaseObjectFromPtr(mPtr);
for (size_t i = 0; i < mModel->getItemCount(); ++i)
{
const ItemStack& item = mModel->getItem(i);
// Trigger crimes related to the attempted taking of these items, if applicable
if (!onTakeItem(item, item.mCount))
break;
objectList->addContainerItem(baseObject, item, item.mCount, item.mCount);
}
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
objectList->reset();
objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY;
objectList->cell = *mPtr.getCell()->getCell();
objectList->action = mwmp::BaseObjectList::REMOVE;
objectList->containerSubAction = mwmp::BaseObjectList::TAKE_ALL;
objectList->addEntireContainer(mPtr);
objectList->sendContainer();
if (baseObject.containerItems.size() > 0)
{
objectList->addBaseObject(baseObject);
objectList->sendContainer();
}
/*
End of tes3mp addition
*/

@ -469,10 +469,6 @@ namespace MWGui
{
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)

@ -514,22 +514,21 @@ namespace MWGui
Instead of unilaterally using an item, send an ID_PLAYER_ITEM_USE packet and let the server
decide if the item actually gets used
*/
/*
if (!item.getClass().getEquipmentSlots(item).first.empty() && !store.isEquipped(item))
{
/*
MWBase::Environment::get().getWindowManager()->useItem(item);
// make sure that item was successfully equipped
if (!store.isEquipped(item))
return;
*/
mwmp::Main::get().getLocalPlayer()->sendItemUse(item, true, MWMechanics::DrawState_Spell);
}
//store.setSelectedEnchantItem(it);
//MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Spell);
store.setSelectedEnchantItem(it);
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Spell);
*/
mwmp::Main::get().getLocalPlayer()->sendItemUse(item, true, MWMechanics::DrawState_Spell);
/*
End of tes3mp change (major)
*/

@ -154,9 +154,10 @@ namespace MWGui
Prevent resting and waiting if they have been disabled by the server for the local player
*/
else if (canRest == MWBase::World::Rest_Allowed && !mwmp::Main::get().getLocalPlayer()->wildernessRestAllowed)
else if (canRest == MWBase::World::Rest_Allowed && !mwmp::Main::get().getLocalPlayer()->wildernessRestAllowed &&
!mwmp::Main::get().getLocalPlayer()->isUsingBed)
{
MWBase::Environment::get().getWindowManager()->messageBox("You are not allowed to rest in the wilderness.");
MWBase::Environment::get().getWindowManager()->messageBox("You are not allowed to rest without a bed.");
MWBase::Environment::get().getWindowManager()->popGuiMode();
}
else if (canRest == MWBase::World::Rest_OnlyWaiting && !mwmp::Main::get().getLocalPlayer()->waitAllowed &&

@ -13,6 +13,7 @@
*/
#include "../mwmp/Main.hpp"
#include "../mwmp/LocalPlayer.hpp"
#include "../mwmp/GUIController.hpp"
/*
End of tes3mp addition
*/
@ -366,6 +367,19 @@ namespace MWInput
void ActionManager::toggleMainMenu()
{
/*
Start of tes3mp addition
Don't allow the main menu to be toggled while TES3MP listboxes are open
*/
if (MWBase::Environment::get().getWindowManager()->getMode() == mwmp::GUIController::GM_TES3MP_ListBox)
{
return;
}
/*
End of tes3mp addition
*/
if (MyGUI::InputManager::getInstance().isModalAny())
{
MWBase::Environment::get().getWindowManager()->exitCurrentModal();

@ -2479,24 +2479,24 @@ namespace MWMechanics
void Actors::cleanupSummonedCreature (MWMechanics::CreatureStats& casterStats, int creatureActorId)
{
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaActorId(creatureActorId);
if (!ptr.isEmpty())
{
/*
Start of tes3mp change (major)
Send an ID_OBJECT_DELETE packet every time a summoned creature despawns
*/
if (mwmp::Main::get().getCellController()->hasLocalAuthority(*ptr.getCell()->getCell()))
{
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
objectList->reset();
objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY;
objectList->addObjectGeneric(ptr);
objectList->sendObjectDelete();
}
/*
End of tes3mp change (major)
*/
/*
Start of tes3mp change (major)
Do a cleanup here and send an ID_OBJECT_DELETE packet every time a summoned creature
despawns for the local player or for a local actor
*/
if (!ptr.isEmpty() &&
(casterStats.getActorId() == getPlayer().getClass().getCreatureStats(getPlayer()).getActorId() || mwmp::Main::get().getCellController()->hasLocalAuthority(*ptr.getCell()->getCell())))
{
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
objectList->reset();
objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY;
objectList->addObjectGeneric(ptr);
objectList->sendObjectDelete();
/*
End of tes3mp change (major)
*/
const ESM::Static* fx = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>()
.search("VFX_Summon_End");

@ -553,8 +553,20 @@ MWMechanics::Alchemy::Result MWMechanics::Alchemy::create (const std::string& na
if (readyStatus == Result_NoEffects)
removeIngredients();
/*
Start of tes3mp change (minor)
Set avoidSendingInventoryPackets to false again if this has not been a successful
potion creation
*/
if (readyStatus != Result_Success)
{
mwmp::Main::get().getLocalPlayer()->avoidSendingInventoryPackets = false;
return readyStatus;
}
/*
End of tes3mp change (major)
*/
Result result = Result_RandomFailure;
int brewedCount = 0;

@ -79,10 +79,24 @@ void Cell::updateLocal(bool forceUpdate)
}
else
{
// Forcibly update this local actor if its data has never been sent before;
// otherwise, use the current forceUpdate value
if (actor->getPtr().getRefData().isEnabled() && !actor->getPtr().getRefData().isDeleted())
actor->update(actor->hasSentData ? forceUpdate : true);
if (actor->getPtr().getRefData().isEnabled())
{
if (actor->getPtr().getRefData().isDeleted())
{
std::string mapIndex = it->first;
LOG_APPEND(TimedLog::LOG_VERBOSE, "- Deleting LocalActor %s whose reference has been deleted",
mapIndex.c_str(), getShortDescription().c_str());
cellController->removeLocalActorRecord(mapIndex);
delete actor;
localActors.erase(it++);
}
else
{
// Forcibly update this local actor if its data has never been sent before;
// otherwise, use the current forceUpdate value
actor->update(actor->hasSentData ? forceUpdate : true);
}
}
++it;
}
@ -531,7 +545,7 @@ void Cell::initializeDedicatedActors(ActorList& actorList)
// If this key doesn't exist, create it
if (dedicatedActors.count(mapIndex) == 0)
{
MWWorld::Ptr ptrFound = store->searchExact(baseActor.refNum, baseActor.mpNum);
MWWorld::Ptr ptrFound = store->searchExact(baseActor.refNum, baseActor.mpNum, baseActor.refId, true);
if (!ptrFound) continue;

@ -39,7 +39,7 @@ namespace mwmp
mHistory->setNeedKeyFocus(false);
windowState = 0;
windowState = CHAT_DISABLED;
mCommandLine->setVisible(0);
delay = 3; // 3 sec.
}
@ -49,7 +49,9 @@ namespace mwmp
// Give keyboard focus to the combo box whenever the console is
// turned on
setEditState(0);
windowState = CHAT_ENABLED;
if (windowState == CHAT_DISABLED)
windowState = CHAT_ENABLED;
}
void GUIChat::onClose()
@ -114,7 +116,7 @@ namespace mwmp
void GUIChat::print(const std::string &msg, const std::string &color)
{
if (windowState == 2 && !isVisible())
if (windowState == CHAT_HIDDENMODE && !isVisible())
{
setVisible(true);
}

@ -211,6 +211,11 @@ bool mwmp::GUIController::pressedKey(int key)
return false;
}
void mwmp::GUIController::changeChatMode()
{
mChat->pressedChatMode();
}
bool mwmp::GUIController::getChatEditState()
{
return mChat->editState;

@ -45,11 +45,13 @@ namespace mwmp
void showDialogList(const BasePlayer::GUIMessageBox &guiMessageBox);
bool getChatEditState();
/// Returns 0 if there was no events
bool pressedKey(int key);
void changeChatMode();
bool getChatEditState();
void update(float dt);
void processCustomMessageBoxInput(int pressedButton);

@ -155,7 +155,6 @@ bool LocalPlayer::processCharGen()
}
getNetworking()->getPlayerPacket(ID_PLAYER_CHARGEN)->setPlayer(this);
getNetworking()->getPlayerPacket(ID_PLAYER_CHARGEN)->Send();
charGenState.currentStage++;
return false;
}

@ -112,6 +112,22 @@ void ObjectList::addContainerItem(mwmp::BaseObject& baseObject, const MWWorld::P
baseObject.containerItems.push_back(containerItem);
}
void ObjectList::addContainerItem(mwmp::BaseObject& baseObject, const MWGui::ItemStack& itemStack, int itemCount, int actionCount)
{
mwmp::ContainerItem containerItem;
containerItem.refId = itemStack.mBase.getCellRef().getRefId();
containerItem.count = itemCount;
containerItem.charge = itemStack.mBase.getCellRef().getCharge();
containerItem.enchantmentCharge = itemStack.mBase.getCellRef().getEnchantmentCharge();
containerItem.soul = itemStack.mBase.getCellRef().getSoul();
containerItem.actionCount = actionCount;
LOG_APPEND(TimedLog::LOG_VERBOSE, "--- Adding container item %s to packet with count %i and actionCount %i",
containerItem.refId.c_str(), itemCount, actionCount);
baseObject.containerItems.push_back(containerItem);
}
void ObjectList::addContainerItem(mwmp::BaseObject& baseObject, const std::string itemId, int itemCount, int actionCount)
{
mwmp::ContainerItem containerItem;
@ -163,7 +179,7 @@ void ObjectList::editContainers(MWWorld::CellStore* cellStore)
LOG_APPEND(TimedLog::LOG_VERBOSE, "- container %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
if (ptrFound)
{
@ -349,14 +365,7 @@ void ObjectList::activateObjects(MWWorld::CellStore* cellStore)
else
{
LOG_APPEND(TimedLog::LOG_VERBOSE, "-- Activated object is %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
if (baseObject.refId.empty())
{
ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
}
else
{
ptrFound = cellStore->searchExactPlus(baseObject.refId, baseObject.refNum, baseObject.mpNum);
}
ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
}
if (ptrFound)
@ -371,7 +380,7 @@ void ObjectList::activateObjects(MWWorld::CellStore* cellStore)
}
else
{
activatingActorPtr = cellStore->searchExact(baseObject.activatingActor.refNum, baseObject.activatingActor.mpNum);
activatingActorPtr = cellStore->searchExact(baseObject.activatingActor.refNum, baseObject.activatingActor.mpNum, baseObject.activatingActor.refId);
LOG_APPEND(TimedLog::LOG_VERBOSE, "-- Object has been activated by actor %s %i-%i", activatingActorPtr.getCellRef().getRefId().c_str(),
activatingActorPtr.getCellRef().getRefNum().mIndex, activatingActorPtr.getCellRef().getMpNum());
}
@ -491,7 +500,7 @@ void ObjectList::spawnObjects(MWWorld::CellStore* cellStore)
if (baseObject.master.isPlayer)
masterPtr = MechanicsHelper::getPlayerPtr(baseObject.master);
else
masterPtr = cellStore->searchExact(baseObject.master.refNum, baseObject.master.mpNum);
masterPtr = cellStore->searchExact(baseObject.master.refNum, baseObject.master.mpNum, baseObject.master.refId);
if (masterPtr)
{
@ -541,6 +550,7 @@ void ObjectList::spawnObjects(MWWorld::CellStore* cellStore)
foundSummonedCreature = true;
break;
}
++it;
}
// If it is, update its creatureActorId
@ -570,7 +580,7 @@ void ObjectList::deleteObjects(MWWorld::CellStore* cellStore)
{
LOG_APPEND(TimedLog::LOG_VERBOSE, "- cellRef: %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
if (ptrFound)
{
@ -623,7 +633,7 @@ void ObjectList::lockObjects(MWWorld::CellStore* cellStore)
{
LOG_APPEND(TimedLog::LOG_VERBOSE, "- cellRef: %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
if (ptrFound)
{
@ -644,7 +654,7 @@ void ObjectList::triggerTrapObjects(MWWorld::CellStore* cellStore)
{
LOG_APPEND(TimedLog::LOG_VERBOSE, "- cellRef: %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
if (ptrFound)
{
@ -671,7 +681,7 @@ void ObjectList::scaleObjects(MWWorld::CellStore* cellStore)
LOG_APPEND(TimedLog::LOG_VERBOSE, "- cellRef: %s %i-%i, scale: %f", baseObject.refId.c_str(), baseObject.refNum,
baseObject.mpNum, baseObject.scale);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
if (ptrFound)
{
@ -690,7 +700,7 @@ void ObjectList::setObjectStates(MWWorld::CellStore* cellStore)
LOG_APPEND(TimedLog::LOG_VERBOSE, "- cellRef: %s %i-%i, state: %s", baseObject.refId.c_str(), baseObject.refNum,
baseObject.mpNum, baseObject.objectState ? "true" : "false");
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
if (ptrFound)
{
@ -720,7 +730,7 @@ void ObjectList::moveObjects(MWWorld::CellStore* cellStore)
{
LOG_APPEND(TimedLog::LOG_VERBOSE, "- cellRef: %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
if (ptrFound)
{
@ -739,7 +749,7 @@ void ObjectList::restockObjects(MWWorld::CellStore* cellStore)
{
LOG_APPEND(TimedLog::LOG_VERBOSE, "- cellRef: %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
if (ptrFound)
{
@ -765,7 +775,7 @@ void ObjectList::rotateObjects(MWWorld::CellStore* cellStore)
{
LOG_APPEND(TimedLog::LOG_VERBOSE, "- cellRef: %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
if (ptrFound)
{
@ -784,7 +794,7 @@ void ObjectList::animateObjects(MWWorld::CellStore* cellStore)
{
LOG_APPEND(TimedLog::LOG_VERBOSE, "- cellRef: %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
if (ptrFound)
{
@ -826,7 +836,7 @@ void ObjectList::playObjectSounds(MWWorld::CellStore* cellStore)
else
{
objectDescription = baseObject.refId + " " + std::to_string(baseObject.refNum) + "-" + std::to_string(baseObject.mpNum);
ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
}
if (ptrFound)
@ -857,7 +867,7 @@ void ObjectList::setGoldPoolsForObjects(MWWorld::CellStore* cellStore)
{
LOG_APPEND(TimedLog::LOG_VERBOSE, "- cellRef: %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
if (ptrFound)
{
@ -889,7 +899,7 @@ void ObjectList::activateDoors(MWWorld::CellStore* cellStore)
{
LOG_APPEND(TimedLog::LOG_VERBOSE, "- cellRef: %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
if (ptrFound)
{
@ -910,7 +920,7 @@ void ObjectList::setDoorDestinations(MWWorld::CellStore* cellStore)
{
LOG_APPEND(TimedLog::LOG_VERBOSE, "- cellRef: %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
if (ptrFound)
{
@ -976,7 +986,7 @@ void ObjectList::runConsoleCommands(MWWorld::CellStore* cellStore)
{
LOG_APPEND(TimedLog::LOG_VERBOSE, "-- Running on object %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
if (ptrFound)
{
@ -998,16 +1008,8 @@ void ObjectList::makeDialogueChoices(MWWorld::CellStore* cellStore)
for (const auto& baseObject : baseObjects)
{
LOG_APPEND(TimedLog::LOG_VERBOSE, "- cellRef: %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound;
if (baseObject.refId.empty())
{
ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
}
else
{
ptrFound = cellStore->searchExactPlus(baseObject.refId, baseObject.refNum, baseObject.mpNum);
}
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
if (ptrFound)
{
@ -1036,7 +1038,33 @@ void ObjectList::makeDialogueChoices(MWWorld::CellStore* cellStore)
LOG_APPEND(TimedLog::LOG_VERBOSE, "-- topic was %s", baseObject.topicId.c_str());
}
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->activateDialogueChoice(baseObject.dialogueChoiceType, baseObject.topicId);
std::string topic = baseObject.topicId;
if (MWBase::Environment::get().getWindowManager()->getTranslationDataStorage().hasTranslation())
{
char delimiter = '|';
// If we're using a translated version of Morrowind, we may have received a string that had the original
// topic delimited from its possible English translation by a | character, in which case we need to use
// the original topic here
if (topic.find(delimiter) != std::string::npos)
{
topic = topic.substr(0, topic.find(delimiter));
}
// Alternatively, we may have received a topic that needs to be translated into the current language's
// version of it
else
{
std::string translatedTopic = MWBase::Environment::get().getWindowManager()->getTranslationDataStorage().getLocalizedTopicId(topic);
if (!translatedTopic.empty())
{
topic = translatedTopic;
}
}
}
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->activateDialogueChoice(baseObject.dialogueChoiceType, topic);
}
else
{
@ -1053,7 +1081,7 @@ void ObjectList::setClientLocals(MWWorld::CellStore* cellStore)
{
LOG_APPEND(TimedLog::LOG_VERBOSE, "- cellRef: %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
if (ptrFound)
{
@ -1163,7 +1191,7 @@ void ObjectList::addRequestedContainers(MWWorld::CellStore* cellStore, const std
LOG_APPEND(TimedLog::LOG_VERBOSE, "- cellRef: %s %i-%i", baseObject.refId.c_str(),
baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum, baseObject.refId);
if (ptrFound)
{
@ -1329,7 +1357,7 @@ void ObjectList::addObjectDialogueChoice(const MWWorld::Ptr& ptr, std::string di
// 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);
baseObject.topicId = dialogueChoice + "|" + MWBase::Environment::get().getWindowManager()->getTranslationDataStorage().topicID(dialogueChoice);
else
baseObject.topicId = dialogueChoice;
}

@ -2,6 +2,7 @@
#define OPENMW_OBJECTLIST_HPP
#include <components/openmw-mp/Base/BaseObject.hpp>
#include "../mwgui/itemmodel.hpp"
#include "../mwworld/worldimp.hpp"
#include <RakNetTypes.h>
@ -20,6 +21,7 @@ namespace mwmp
void addBaseObject(BaseObject baseObject);
mwmp::BaseObject getBaseObjectFromPtr(const MWWorld::Ptr& ptr);
void addContainerItem(mwmp::BaseObject& baseObject, const MWWorld::Ptr& itemPtr, int itemCount, int actionCount);
void addContainerItem(mwmp::BaseObject& baseObject, const MWGui::ItemStack& itemStack, int itemCount, int actionCount);
void addContainerItem(mwmp::BaseObject& baseObject, const std::string itemId, int itemCount, int actionCount);
void addEntireContainer(const MWWorld::Ptr& ptr);

@ -368,6 +368,18 @@ void RecordHelper::overrideRecord(const mwmp::CellRecord& record)
world->unloadCell(finalData);
world->clearCellStore(finalData);
world->getModifiableStore().overrideRecord(finalData);
// Create a Pathgrid record for this new Cell based on the base Cell's Pathgrid
// Note: This has to be done after the new Cell has been created so the Pathgrid override
// can correctly determine whether the Cell is an interior or an exterior
const ESM::Pathgrid* basePathgrid = world->getStore().get<ESM::Pathgrid>().search(record.baseId);
if (basePathgrid)
{
ESM::Pathgrid finalPathgrid = *basePathgrid;
finalPathgrid.mCell = recordData.mName;
world->getModifiableStore().overrideRecord(finalPathgrid);
}
}
else
{

@ -195,21 +195,23 @@ namespace MWScript
/*
Start of tes3mp addition
Send an ID_OBJECT_STATE packet whenever an object is enabled, as long as
the player is logged in on the server, the object is still disabled, and our last
packet regarding its state did not already attempt to enable it (to prevent
Send an ID_OBJECT_STATE packet whenever an object should be enabled, as long as the
player is logged in on the server and if triggered from a clientside script our
last packet regarding its state did not already attempt to enable it (to prevent
packet spam)
*/
if (mwmp::Main::get().getLocalPlayer()->isLoggedIn())
{
if (ptr.isInCell() && !ptr.getRefData().isEnabled() &&
ptr.getRefData().getLastCommunicatedState() != MWWorld::RefData::StateCommunication::Enabled)
unsigned char packetOrigin = ScriptController::getPacketOriginFromContextType(runtime.getContext().getContextType());
if (packetOrigin == Interpreter::Context::CONSOLE || packetOrigin == Interpreter::Context::DIALOGUE ||
(ptr.isInCell() && ptr.getRefData().getLastCommunicatedState() != MWWorld::RefData::StateCommunication::Enabled))
{
ptr.getRefData().setLastCommunicatedState(MWWorld::RefData::StateCommunication::Enabled);
mwmp::ObjectList* objectList = mwmp::Main::get().getNetworking()->getObjectList();
objectList->reset();
objectList->packetOrigin = ScriptController::getPacketOriginFromContextType(runtime.getContext().getContextType());
objectList->packetOrigin = packetOrigin;
objectList->originClientScript = runtime.getContext().getCurrentScriptName();
objectList->addObjectState(ptr, true);
objectList->sendObjectState();
@ -244,21 +246,23 @@ namespace MWScript
/*
Start of tes3mp addition
Send an ID_OBJECT_STATE packet whenever an object should be disabled, as long as
the player is logged in on the server, the object is still enabled, and our last
packet regarding its state did not already attempt to disable it (to prevent
Send an ID_OBJECT_STATE packet whenever an object should be disabled, as long as the
player is logged in on the server and if triggered from a clientside script our
last packet regarding its state did not already attempt to disable it (to prevent
packet spam)
*/
if (mwmp::Main::get().getLocalPlayer()->isLoggedIn())
{
if (ptr.isInCell() && ptr.getRefData().isEnabled() &&
ptr.getRefData().getLastCommunicatedState() != MWWorld::RefData::StateCommunication::Disabled)
unsigned char packetOrigin = ScriptController::getPacketOriginFromContextType(runtime.getContext().getContextType());
if (packetOrigin == Interpreter::Context::CONSOLE || packetOrigin == Interpreter::Context::DIALOGUE ||
(ptr.isInCell() && ptr.getRefData().getLastCommunicatedState() != MWWorld::RefData::StateCommunication::Disabled))
{
ptr.getRefData().setLastCommunicatedState(MWWorld::RefData::StateCommunication::Disabled);
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
objectList->reset();
objectList->packetOrigin = ScriptController::getPacketOriginFromContextType(runtime.getContext().getContextType());
objectList->packetOrigin = packetOrigin;
objectList->originClientScript = runtime.getContext().getCurrentScriptName();
objectList->addObjectState(ptr, false);
objectList->sendObjectState();
@ -423,9 +427,10 @@ namespace MWScript
Start of tes3mp addition
Send an ID_OBJECT_LOCK packet every time an object is locked
through a script
through a script, as long as the lock level being set is not
the one it already has
*/
if (mwmp::Main::get().getLocalPlayer()->isLoggedIn())
if (mwmp::Main::get().getLocalPlayer()->isLoggedIn() && ptr.getCellRef().getLockLevel() != lockLevel)
{
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
objectList->reset();
@ -471,9 +476,9 @@ namespace MWScript
Start of tes3mp addition
Send an ID_OBJECT_LOCK packet every time an object is unlocked
through a script
through a script, as long as it's not already unlocked
*/
if (mwmp::Main::get().getLocalPlayer()->isLoggedIn())
if (mwmp::Main::get().getLocalPlayer()->isLoggedIn() && ptr.getCellRef().getLockLevel() > 0)
{
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
objectList->reset();

@ -12,6 +12,7 @@
#include "../mwmp/LocalPlayer.hpp"
#include "../mwmp/PlayerList.hpp"
#include "../mwmp/ObjectList.hpp"
#include "../mwmp/CellController.hpp"
#include "../mwmp/ScriptController.hpp"
/*
End of tes3mp addition
@ -443,10 +444,52 @@ namespace MWScript
}
if(store)
{
/*
Start of tes3mp addition
Track the original cell of this object in case we need to use it when sending a packet
*/
ESM::Cell originalCell = *ptr.getCell()->getCell();
/*
End of tes3mp addition
*/
MWWorld::Ptr base = ptr;
ptr = MWBase::Environment::get().getWorld()->moveObject(ptr,store,x,y,z);
dynamic_cast<MWScript::InterpreterContext&>(runtime.getContext()).updatePtr(base,ptr);
/*
Start of tes3mp addition
Send ActorCellChange packets when actors are moved here, regardless of whether we're
the cell authority or not; the server can decide if it wants to comply with them
*/
if (ptr.getClass().isActor() && !mwmp::Main::get().getCellController()->isSameCell(originalCell, *store->getCell()))
{
mwmp::BaseActor baseActor;
baseActor.refNum = ptr.getCellRef().getRefNum().mIndex;
baseActor.mpNum = ptr.getCellRef().getMpNum();
baseActor.cell = *store->getCell();
baseActor.position = ptr.getRefData().getPosition();
baseActor.isFollowerCellChange = true;
mwmp::ActorList* actorList = mwmp::Main::get().getNetworking()->getActorList();
actorList->reset();
actorList->cell = originalCell;
LOG_MESSAGE_SIMPLE(TimedLog::LOG_INFO, "Sending ID_ACTOR_CELL_CHANGE about %s %i-%i to server",
ptr.getCellRef().getRefId().c_str(), baseActor.refNum, baseActor.mpNum);
LOG_APPEND(TimedLog::LOG_INFO, "- Moved from %s to %s", actorList->cell.getDescription().c_str(),
baseActor.cell.getDescription().c_str());
actorList->addCellChangeActor(baseActor);
actorList->sendCellChangeActors();
}
/*
End of tes3mp addition
*/
float ax = ptr.getRefData().getPosition().rot[0];
float ay = ptr.getRefData().getPosition().rot[1];
// Note that you must specify ZRot in minutes (1 degree = 60 minutes; north = 0, east = 5400, south = 10800, west = 16200)

@ -605,47 +605,26 @@ namespace MWWorld
{
const unsigned int mRefNumToFind;
const unsigned int mMpNumToFind;
public:
SearchExactVisitor(const unsigned int refNum, const unsigned int mpNum) : mRefNumToFind(refNum), mMpNumToFind(mpNum) {}
Ptr mFound;
bool operator()(const Ptr& ptr)
{
if (ptr.getCellRef().getRefNum().mIndex == mRefNumToFind && ptr.getCellRef().getMpNum() == mMpNumToFind)
{
mFound = ptr;
return false;
}
return true;
}
};
/*
End of tes3mp addition
*/
/*
Start of tes3mp addition
A custom type of search visitor used to find objects by their reference numbers
while ensuring they have a certain refId
*/
class SearchExactPlusVisitor
{
const std::string mRefIdToFind;
const unsigned int mRefNumToFind;
const unsigned int mMpNumToFind;
const bool mActorsOnly;
public:
SearchExactPlusVisitor(const std::string refId, const unsigned int refNum, const unsigned int mpNum) : mRefIdToFind(refId), mRefNumToFind(refNum), mMpNumToFind(mpNum) {}
SearchExactVisitor(const unsigned int refNum, const unsigned int mpNum, const std::string refId, const bool actorsOnly) :
mRefNumToFind(refNum), mMpNumToFind(mpNum), mRefIdToFind(refId), mActorsOnly(actorsOnly) {}
Ptr mFound;
bool operator()(const Ptr& ptr)
{
if (ptr.getCellRef().getRefNum().mIndex == mRefNumToFind && ptr.getCellRef().getMpNum() == mMpNumToFind && Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), mRefIdToFind))
if (ptr.getCellRef().getRefNum().mIndex == mRefNumToFind && ptr.getCellRef().getMpNum() == mMpNumToFind)
{
mFound = ptr;
return false;
if (!mActorsOnly || ptr.getClass().isActor())
{
if (mRefIdToFind.empty() || Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), mRefIdToFind))
{
mFound = ptr;
return false;
}
}
}
return true;
}
@ -659,33 +638,13 @@ namespace MWWorld
Allow the searching of objects by their reference numbers
*/
Ptr CellStore::searchExact (const unsigned int refNum, const unsigned int mpNum)
{
// Ensure that all objects searched for have a valid reference number
if (refNum == 0 && mpNum == 0)
return 0;
SearchExactVisitor searchVisitor(refNum, mpNum);
forEach(searchVisitor);
return searchVisitor.mFound;
}
/*
End of tes3mp addition
*/
/*
Start of tes3mp addition
Allow the searching of objects by their reference numbers while ensuring
they have a certain refId
*/
Ptr CellStore::searchExactPlus(const std::string refId, const unsigned int refNum, const unsigned int mpNum)
Ptr CellStore::searchExact (const unsigned int refNum, const unsigned int mpNum, const std::string refId, bool actorsOnly)
{
// Ensure that all objects searched for have a valid reference number
if (refNum == 0 && mpNum == 0)
return 0;
SearchExactPlusVisitor searchVisitor(refId, refNum, mpNum);
SearchExactVisitor searchVisitor(refNum, mpNum, refId, actorsOnly);
forEach(searchVisitor);
return searchVisitor.mFound;
}

@ -262,20 +262,10 @@ namespace MWWorld
/*
Start of tes3mp addition
Allow the searching of objects by their reference numbers
Allow the searching of objects by their reference numbers and, optionally,
their refIds
*/
Ptr searchExact (unsigned int refNum, unsigned int mpNum);
/*
End of tes3mp addition
*/
/*
Start of tes3mp addition
Allow the searching of objects by their reference numbers while ensuring
they have a certain refId
*/
Ptr searchExactPlus (std::string refId, unsigned int refNum, unsigned int mpNum);
Ptr searchExact (unsigned int refNum, unsigned int mpNum, std::string refId = "", bool actorsOnly = false);
/*
End of tes3mp addition
*/

@ -331,7 +331,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr
Send an ID_PLAYER_INVENTORY packet every time an item gets added for a player here
*/
if (actorPtr == player && this == &player.getClass().getContainerStore(player))
if (this == &player.getClass().getContainerStore(player))
{
mwmp::LocalPlayer *localPlayer = mwmp::Main::get().getLocalPlayer();
@ -562,7 +562,7 @@ int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor
*/
Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
if (actor == player && this == &player.getClass().getContainerStore(player))
if (this == &player.getClass().getContainerStore(player))
{
mwmp::LocalPlayer *localPlayer = mwmp::Main::get().getLocalPlayer();

@ -276,7 +276,7 @@ namespace MWWorld
/*
Start of tes3mp addition
Make it possible to override a cell record similarly to how
Make it possible to override a Cell record similarly to how
other types of records can be overridden
*/
template <>
@ -287,6 +287,20 @@ namespace MWWorld
End of tes3mp addition
*/
/*
Start of tes3mp addition
Make it possible to override a Pathgrid record similarly to how
other types of records can be overridden
*/
template <>
inline const ESM::Pathgrid* ESMStore::overrideRecord<ESM::Pathgrid>(const ESM::Pathgrid& pathgrid) {
return mPathgrids.override(pathgrid);
}
/*
End of tes3mp addition
*/
template <>
inline const ESM::Cell *ESMStore::insert<ESM::Cell>(const ESM::Cell &cell) {
return mCells.insert(cell);

@ -796,7 +796,7 @@ namespace MWWorld
/*
Start of tes3mp addition
Make it possible to override a cell record similarly to how
Make it possible to override a Cell record similarly to how
other types of records can be overridden
*/
ESM::Cell *Store<ESM::Cell>::override(const ESM::Cell &cell)
@ -949,6 +949,37 @@ namespace MWWorld
return RecordId("", isDeleted);
}
/*
Start of tes3mp addition
Make it possible to override a Pathgrid record similarly to how
other types of records can be overridden
*/
ESM::Pathgrid* Store<ESM::Pathgrid>::override(const ESM::Pathgrid& pathgrid)
{
bool interior = mCells->search(pathgrid.mCell) != nullptr;
// Try to overwrite existing record
if (interior)
{
std::pair<Interior::iterator, bool> ret = mInt.insert(std::make_pair(pathgrid.mCell, pathgrid));
if (!ret.second)
ret.first->second = pathgrid;
return &ret.first->second;
}
else
{
std::pair<Exterior::iterator, bool> ret = mExt.insert(std::make_pair(std::make_pair(pathgrid.mData.mX, pathgrid.mData.mY), pathgrid));
if (!ret.second)
ret.first->second = pathgrid;
return &ret.first->second;
}
}
/*
End of tes3mp addition
*/
size_t Store<ESM::Pathgrid>::getSize() const
{
return mInt.size() + mExt.size();

@ -325,7 +325,7 @@ namespace MWWorld
/*
Start of tes3mp addition
Make it possible to override a cell record similarly to how
Make it possible to override a Cell record similarly to how
other types of records can be overridden
*/
ESM::Cell *override(const ESM::Cell &cell);
@ -362,6 +362,17 @@ namespace MWWorld
void setUp() override;
/*
Start of tes3mp addition
Make it possible to override a Pathgrid record similarly to how
other types of records can be overridden
*/
ESM::Pathgrid* override(const ESM::Pathgrid& pathgrid);
/*
End of tes3mp addition
*/
const ESM::Pathgrid *search(int x, int y) const;
const ESM::Pathgrid *search(const std::string& name) const;
const ESM::Pathgrid *find(int x, int y) const;

@ -3971,6 +3971,12 @@ namespace MWWorld
MWWorld::Ptr player = getPlayerPtr();
player.getClass().getInventoryStore(player).rechargeItems(duration);
/*
Start of tes3mp change (major)
Don't unilaterally recharge world items on clients
*/
/*
if (activeOnly)
{
for (auto &cell : mWorldScene->getActiveCells())
@ -3980,6 +3986,10 @@ namespace MWWorld
}
else
mCells.recharge(duration);
*/
/*
End of tes3mp change (major)
*/
}
void World::teleportToClosestMarker (const MWWorld::Ptr& ptr,

@ -19,7 +19,7 @@ namespace mwmp
hasStatsDynamicData = false;
}
std::string refId;
std::string refId = "";
unsigned int refNum;
unsigned int mpNum;

@ -26,7 +26,7 @@ namespace mwmp
struct BaseObject
{
std::string refId;
std::string refId = "";
unsigned int refNum;
unsigned int mpNum;
int count;

@ -106,6 +106,9 @@ set(MYGUI_FILES
openmw_windows.skin.xml
DejaVuLGCSansMono.ttf
../launcher/images/openmw.png
# Start of tes3mp addition
../tes3mp/tes3mp_logo.png
# End of tes3mp addition
OpenMWResourcePlugin.xml
skins.xml

Loading…
Cancel
Save