Merge pull request #363 from TES3MP/0.6.2 while resolving conflicts, 2nd try

sol2-server-rewrite
David Cernat 6 years ago
commit 09958681cd

@ -85,11 +85,12 @@ set(PROCESSORS_PLAYER
processors/player/ProcessorPlayerFaction.hpp processors/player/ProcessorPlayerInventory.hpp
processors/player/ProcessorPlayerJournal.hpp processors/player/ProcessorPlayerKillCount.hpp
processors/player/ProcessorPlayerLevel.hpp processors/player/ProcessorPlayerMap.hpp
processors/player/ProcessorPlayerPosition.hpp processors/player/ProcessorPlayerRest.hpp
processors/player/ProcessorPlayerResurrect.hpp processors/player/ProcessorPlayerShapeshift.hpp
processors/player/ProcessorPlayerSkill.hpp processors/player/ProcessorPlayerSpeech.hpp
processors/player/ProcessorPlayerSpellbook.hpp processors/player/ProcessorPlayerStatsDynamic.hpp
processors/player/ProcessorPlayerTopic.hpp processors/player/ProcessorGUIWindow.hpp
processors/player/ProcessorPlayerPosition.hpp processors/player/ProcessorPlayerQuickKeys.hpp
processors/player/ProcessorPlayerRest.hpp processors/player/ProcessorPlayerResurrect.hpp
processors/player/ProcessorPlayerShapeshift.hpp processors/player/ProcessorPlayerSkill.hpp
processors/player/ProcessorPlayerSpeech.hpp processors/player/ProcessorPlayerSpellbook.hpp
processors/player/ProcessorPlayerStatsDynamic.hpp processors/player/ProcessorPlayerTopic.hpp
processors/player/ProcessorGUIWindow.hpp
)
source_group(tes3mp-server\\processors\\player FILES ${PROCESSORS_PLAYER})

@ -15,7 +15,7 @@ void Dialogue::Init(LuaState &lua)
lua.getState()->new_usertype<Dialogue>("Dialogue",
"addTopic", &Dialogue::addTopic,
"getTopicId", &Dialogue::getTopicId,
"getChanges", &Dialogue::getChanges,
"size", &Dialogue::size,
"reset", &Dialogue::reset);
}
@ -57,7 +57,30 @@ std::string Dialogue::getTopicId(unsigned int i) const
return player->topicChanges.topics.at(i).topicId;
}
unsigned int Dialogue::getChanges() const
size_t Dialogue::size() const
{
return player->topicChanges.topics.size();
}
void Dialogue::playAnimation(const std::string &groupname, int mode, int count, bool persist)
{
player->animation.groupname = groupname;
player->animation.mode = mode;
player->animation.count = count;
player->animation.persist = persist;
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_ANIM_PLAY);
packet->setPlayer(player);
packet->Send(false);
player->sendToLoaded(*packet);
}
void Dialogue::playSpeech(const std::string &sound)
{
player->sound = sound;
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_SPEECH);
packet->setPlayer(player);
packet->Send(false);
player->sendToLoaded(*packet);
}

@ -18,7 +18,10 @@ public:
void addTopic(const std::string &topicId);
std::string getTopicId(unsigned int i) const;
unsigned int getChanges() const;
size_t size() const;
void playAnimation(const std::string &groupname, int mode, int count, bool persist);
void playSpeech(const std::string &sound);
void reset();
void update();

@ -19,22 +19,7 @@ void Factions::Init(LuaState &lua)
"setFaction", &Factions::setFaction,
"clear", &Factions::clear,
"size", &Factions::size
);
/*"InitializeFactionChanges", FactionFunctions::InitializeFactionChanges,
"GetFactionChangesSize", FactionFunctions::GetFactionChangesSize,
"GetFactionChangesAction", FactionFunctions::GetFactionChangesAction,
"GetFactionId", FactionFunctions::GetFactionId,
"GetFactionRank", FactionFunctions::GetFactionRank,
"GetFactionExpulsionState", FactionFunctions::GetFactionExpulsionState,
"GetFactionReputation", FactionFunctions::GetFactionReputation,
"SetFactionChangesAction", FactionFunctions::SetFactionChangesAction,
"SetFactionId", FactionFunctions::SetFactionId,
"SetFactionRank", FactionFunctions::SetFactionRank,
"SetFactionExpulsionState", FactionFunctions::SetFactionExpulsionState,
"SetFactionReputation", FactionFunctions::SetFactionReputation,
"AddFaction", FactionFunctions::AddFaction,
"SendFactionChanges", FactionFunctions::SendFactionChanges*/
}
Factions::Factions(Player *player): player(player), changed(false)

@ -143,3 +143,109 @@ void GUI::onGUIWindowAction()
it->second->call(player->guiWindow);
}
}
void QuickKeys::Init(LuaState &lua)
{
lua.getState()->new_usertype<QuickKeys>("QuickKeys",
"addQuickKey", &QuickKeys::addQuickKey,
"getQuickKey", &QuickKeys::getQuickKey,
"setQuickKey", &QuickKeys::setQuickKey,
"clear", &QuickKeys::clear,
"size", &QuickKeys::size
);
}
QuickKeys::QuickKeys(Player *player) : player(player), changed(false)
{
}
QuickKeys::~QuickKeys()
{
}
void QuickKeys::update()
{
if (!changed)
return;
changed = false;
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_QUICKKEYS);
packet->setPlayer(player);
packet->Send(false);
clear();
}
void QuickKeys::addQuickKey(QuickKey quickKey)
{
player->quickKeyChanges.quickKeys.push_back(quickKey.quickKey);
changed = true;
}
QuickKey QuickKeys::getQuickKey(int id) const
{
return QuickKey(player->quickKeyChanges.quickKeys.at(id));
}
void QuickKeys::setQuickKey(int id, QuickKey quickKey)
{
player->quickKeyChanges.quickKeys.at(id) = quickKey.quickKey;
changed = true;
}
void QuickKeys::clear()
{
player->quickKeyChanges.quickKeys.clear();
changed = true;
}
size_t QuickKeys::size() const
{
return player->quickKeyChanges.quickKeys.size();
}
void QuickKey::Init(LuaState &lua)
{
lua.getState()->new_usertype<QuickKey>("QuickKey",
"slot", sol::property(&QuickKey::getSlot, &QuickKey::setSlot),
"type", sol::property(&QuickKey::getType, &QuickKey::setType),
"itemId", sol::property(&QuickKey::getItemId, &QuickKey::setItemId)
);
}
QuickKey::QuickKey(mwmp::QuickKey &quickKey): quickKey(quickKey)
{
}
int QuickKey::getSlot() const
{
return quickKey.slot;
}
void QuickKey::setSlot(unsigned short slot)
{
quickKey.slot = slot;
}
int QuickKey::getType() const
{
return quickKey.type;
}
void QuickKey::setType(int type)
{
quickKey.type = type;
}
std::string QuickKey::getItemId() const
{
return quickKey.itemId;
}
void QuickKey::setItemId(const std::string &itemId)
{
quickKey.itemId = itemId;
}

@ -34,6 +34,11 @@ public:
std::shared_ptr<Window> createWindow(short x, short y, sol::function fn, sol::this_environment te);
void deleteWindow(std::shared_ptr<Window> window);
void onGUIWindowAction();
void addQuickKey(unsigned short slot, int type, const std::string &itemId);
std::string getTopicId(unsigned int i) const;
unsigned int getChanges() const;
private:
Player *player;
bool changed;
@ -41,4 +46,44 @@ private:
int lastWindowId;
};
class QuickKey
{
friend class QuickKeys;
public:
static void Init(LuaState &lua);
public:
explicit QuickKey(mwmp::QuickKey &quickKey);
int getSlot() const;
void setSlot(unsigned short slot);
int getType() const;
void setType(int slot);
std::string getItemId() const;
void setItemId(const std::string &itemId);
mwmp::QuickKey quickKey;
};
class QuickKeys
{
public:
static void Init(LuaState &lua);
public:
explicit QuickKeys(Player *player);
~QuickKeys();
void update();
void addQuickKey(QuickKey quickKey);
QuickKey getQuickKey(int id) const;
void setQuickKey(int id, QuickKey quickKey);
size_t size() const;
void clear();
private:
mwmp::QuickKey tempQuickKey;
Player *player;
bool changed;
};

@ -76,11 +76,12 @@ int Inventory::getChangesSize() const
return netActor->getNetCreature()->inventoryChanges.items.size();
}
void Inventory::equipItem(unsigned short slot, const std::string& refId, unsigned int count, int charge)
void Inventory::equipItem(unsigned short slot, const std::string& refId, unsigned int count, int charge, int enchantmentCharge)
{
netActor->getNetCreature()->equipmentItems[slot].refId = refId;
netActor->getNetCreature()->equipmentItems[slot].count = count;
netActor->getNetCreature()->equipmentItems[slot].charge = charge;
netActor->getNetCreature()->equipmentItems[slot].enchantmentCharge = enchantmentCharge;
if (!Utils::vectorContains(&netActor->getNetCreature()->equipmentIndexChanges, slot))
netActor->getNetCreature()->equipmentIndexChanges.push_back(slot);
@ -90,11 +91,11 @@ void Inventory::equipItem(unsigned short slot, const std::string& refId, unsigne
void Inventory::unequipItem( unsigned short slot)
{
equipItem(slot, "", 0, -1);
equipItem(slot, "", 0, -1, -1);
}
void Inventory::addItem(const std::string &refId, unsigned int count, int charge)
void Inventory::addItem(const std::string &refId, unsigned int count, int charge, int enchantmentCharge)
{
if (inventoryChanged == mwmp::InventoryChanges::REMOVE)
return;
@ -105,6 +106,7 @@ void Inventory::addItem(const std::string &refId, unsigned int count, int charge
item.refId = refId;
item.count = count;
item.charge = charge;
item.enchantmentCharge = enchantmentCharge;
netActor->getNetCreature()->inventoryChanges.items.push_back(item);
netActor->getNetCreature()->inventoryChanges.action = mwmp::InventoryChanges::ADD;
@ -135,16 +137,16 @@ bool Inventory::hasItemEquipped(const std::string &refId) const
return false;
}
std::tuple<std::string, int, int> Inventory::getEquipmentItem(unsigned short slot) const
std::tuple<std::string, int, int, int> Inventory::getEquipmentItem(unsigned short slot) const
{
const auto &item = netActor->getNetCreature()->equipmentItems[slot];
return make_tuple(item.refId, item.count, item.charge);
return make_tuple(item.refId, item.count, item.charge, item.enchantmentCharge);
}
std::tuple<std::string, int, int> Inventory::getInventoryItem(unsigned int slot) const
std::tuple<std::string, int, int, int> Inventory::getInventoryItem(unsigned int slot) const
{
const auto &item = netActor->getNetCreature()->inventoryChanges.items.at(slot);
return make_tuple(item.refId, item.count, item.charge);
return make_tuple(item.refId, item.count, item.charge, item.enchantmentCharge);
}
void Inventory::resetEquipmentFlag()

@ -25,19 +25,19 @@ public:
//inventory
int getChangesSize() const;
void addItem(const std::string& refId, unsigned int count, int charge);
void addItem(const std::string& refId, unsigned int count, int charge, int enchantmentCharge);
void removeItem(const std::string& refId, unsigned short count);
/**
*
* @param slot
* @return refid, count, charge
* @return refid, count, charge, enchantmentCharge
*/
std::tuple<std::string,int, int> getInventoryItem(unsigned int slot) const;
std::tuple<std::string,int, int, int> getInventoryItem(unsigned int slot) const;
// equipment
void equipItem(unsigned short slot, const std::string& refId, unsigned int count, int charge);
void equipItem(unsigned short slot, const std::string& refId, unsigned int count, int charge, int enchantmentCharge);
void unequipItem(unsigned short slot);
bool hasItemEquipped(const std::string& refId) const;
@ -45,9 +45,9 @@ public:
/**
*
* @param slot
* @return refid, count, charge
* @return refid, count, charge, enchantmentCharge
*/
std::tuple<std::string,int, int> getEquipmentItem(unsigned short slot) const;
std::tuple<std::string,int, int, int> getEquipmentItem(unsigned short slot) const;
private:

@ -17,6 +17,7 @@ void Object::Init(LuaState &lua)
"refId", sol::property(&BaseObject::getRefId, &BaseObject::setRefId),
"refNum", sol::property(&BaseObject::getRefNum, &BaseObject::setRefNum),
"mpNum", sol::property(&BaseObject::getMpNum, &BaseObject::setMpNum),
"guid", sol::property(&BaseObject::getGuid, &BaseObject::setGuid),
"getPosition", &Object::getPosition,
"setPosition", &Object::setPosition,
"getRotation", &Object::getRotation,
@ -111,6 +112,18 @@ void BaseObject::setMpNum(unsigned mpNum)
object.mpNum = mpNum;
}
RakNet::RakNetGUID BaseObject::getGuid() const
{
return object.guid;
}
void BaseObject::setGuid(const RakNet::RakNetGUID &guid)
{
changedBase = true;
object.guid = guid;
object.isPlayer = true;
}
int Object::getCount() const
{
return object.count;
@ -134,6 +147,18 @@ void Object::setCharge(int charge)
}
int Object::getEnchantmentCharge() const
{
return object.enchantmentCharge;
}
void Object::setEnchantmentCharge(int enchantmentCharge)
{
changedObjectPlace = true;
object.enchantmentCharge = enchantmentCharge;
}
int Object::getGoldValue() const
{
return object.goldValue;
@ -220,27 +245,29 @@ Container::Container()
}
tuple<string, int, int> Container::getItem(int i) const
tuple<string, int, int, int> Container::getItem(int i) const
{
auto &item = object.containerItems.at(i);
return make_tuple(item.refId, item.count, item.charge);
return make_tuple(item.refId, item.count, item.charge, item.enchantmentCharge);
}
void Container::setItem(int i, const string &refId, int count, int charge)
void Container::setItem(int i, const string &refId, int count, int charge, int enchantmentCharge)
{
auto &item = object.containerItems.at(i);
item.refId = refId;
item.count = count;
item.charge = charge;
item.enchantmentCharge = enchantmentCharge;
changed = true;
}
void Container::addItem(const string &refId, int count, int charge)
void Container::addItem(const string &refId, int count, int charge, int enchantmentCharge)
{
mwmp::ContainerItem item;
item.refId = refId;
item.count = count;
item.charge = charge;
item.enchantmentCharge = enchantmentCharge;
object.containerItems.push_back(item);
changed = true;
}
@ -304,7 +331,7 @@ shared_ptr<vector<shared_ptr<Container>>> ObjectController::copyContainers(mwmp:
return containers;
}
void ObjectController::sendObjects(shared_ptr<Player> player, shared_ptr<vector<shared_ptr<Object>>> objects, const ESM::Cell &cell)
void ObjectController::sendObjects(shared_ptr<Player> player, shared_ptr<vector<shared_ptr<Object>>> objects, const ESM::Cell &cell, bool broadcast)
{
enum Type
{
@ -384,60 +411,105 @@ void ObjectController::sendObjects(shared_ptr<Player> player, shared_ptr<vector<
auto packet = worldCtrl->GetPacket(ID_DOOR_STATE);
auto &event = events[Type::DOOR_STATE];
packet->setEvent(&event);
packet->Send(event.guid);
packet->Send(false);
if (broadcast)
packet->Send(true);
}
if (changed[Type::OBJECT_STATE])
{
auto packet = worldCtrl->GetPacket(ID_OBJECT_STATE);
auto &event = events[Type::OBJECT_STATE];
packet->setEvent(&event);
packet->Send(event.guid);
packet->Send(false);
if (broadcast)
packet->Send(true);
}
if (changed[Type::OBJECT_SCALE])
{
auto packet = worldCtrl->GetPacket(ID_OBJECT_SCALE);
auto &event = events[Type::OBJECT_SCALE];
packet->setEvent(&event);
packet->Send(event.guid);
packet->Send(false);
if (broadcast)
packet->Send(true);
}
if (changed[Type::OBJECT_TRAP])
{
auto packet = worldCtrl->GetPacket(ID_OBJECT_TRAP);
auto &event = events[Type::OBJECT_TRAP];
packet->setEvent(&event);
packet->Send(event.guid);
packet->Send(false);
if (broadcast)
packet->Send(true);
}
if (changed[Type::OBJECT_LOCK])
{
auto packet = worldCtrl->GetPacket(ID_OBJECT_LOCK);
auto &event = events[Type::OBJECT_LOCK];
packet->setEvent(&event);
packet->Send(event.guid);
packet->Send(false);
if (broadcast)
packet->Send(true);
}
if (changed[Type::OBJECT_DELETE])
{
auto packet = worldCtrl->GetPacket(ID_OBJECT_DELETE);
auto &event = events[Type::OBJECT_DELETE];
packet->setEvent(&event);
packet->Send(event.guid);
packet->Send(false);
if (broadcast)
packet->Send(true);
}
if (changed[Type::OBJECT_SCALE])
{
auto packet = worldCtrl->GetPacket(ID_OBJECT_SPAWN);
auto &event = events[Type::OBJECT_SCALE];
packet->setEvent(&event);
packet->Send(event.guid);
packet->Send(false);
if (broadcast)
packet->Send(true);
}
if (changed[Type::OBJECT_PLACE])
{
auto packet = worldCtrl->GetPacket(ID_OBJECT_PLACE);
auto &event = events[Type::OBJECT_PLACE];
packet->setEvent(&event);
packet->Send(event.guid);
packet->Send(false);
if (broadcast)
packet->Send(true);
}
}
void ObjectController::sendContainers(shared_ptr<Player> player, shared_ptr<vector<shared_ptr<Container>>> objects, const ESM::Cell &cell)
void ObjectController::sendConsoleCommand(shared_ptr<Player> player, shared_ptr<vector<shared_ptr<Object>>> objects,
const ESM::Cell &cell, const std::string &consoleCommand, bool broadcast)
{
mwmp::BaseEvent event;
event.cell = cell;
event.consoleCommand = consoleCommand;
event.guid = player->guid;
for (auto &object : *objects)
event.worldObjects.push_back(object->object);
auto packet = mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_CONSOLE_COMMAND);
packet->setEvent(&event);
packet->Send(false);
if (broadcast)
packet->Send(true);
}
void ObjectController::sendContainers(shared_ptr<Player> player, shared_ptr<vector<shared_ptr<Container>>> objects,
const ESM::Cell &cell, bool broadcast)
{
mwmp::BaseEvent event;
@ -454,7 +526,10 @@ void ObjectController::sendContainers(shared_ptr<Player> player, shared_ptr<vect
auto packet = mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_CONTAINER);
packet->setEvent(&event);
packet->Send(event.guid);
packet->Send(false);
if (broadcast)
packet->Send(true);
}
void ObjectController::requestContainers(shared_ptr<Player> player)

@ -24,6 +24,9 @@ public:
unsigned getMpNum() const;
void setMpNum(unsigned mpNum);
RakNet::RakNetGUID getGuid() const;
void setGuid(const RakNet::RakNetGUID &guid);
//void setEventCell(const std::string &cellDescription);
@ -63,6 +66,9 @@ public:
int getCharge() const;
void setCharge(int charge);
int getEnchantmentCharge() const;
void setEnchantmentCharge(int enchantmentCharge);
int getGoldValue() const;
void setGoldValue(int gold);
@ -92,10 +98,10 @@ public:
public:
Container();
std::tuple<std::string, int, int> getItem(int i) const;
void addItem(const std::string &refId, int count, int charge);
std::tuple<std::string, int, int, int> getItem(int i) const;
void addItem(const std::string &refId, int count, int charge, int enchantmentCharge);
void setItem(int i, const std::string &refId, int count, int charge);
void setItem(int i, const std::string &refId, int count, int charge, int enchantmentCharge);
int getActionCount(int i) const;
size_t size() const;
@ -112,8 +118,12 @@ public:
std::shared_ptr<std::vector<std::shared_ptr<Object>>> copyObjects(mwmp::BaseEvent &event);
std::shared_ptr<std::vector<std::shared_ptr<Container>>> copyContainers(mwmp::BaseEvent &event);
void sendObjects(std::shared_ptr<Player> player, std::shared_ptr<std::vector<std::shared_ptr<Object>>> objects, const ESM::Cell &cell);
void sendContainers(std::shared_ptr<Player> player, std::shared_ptr<std::vector<std::shared_ptr<Container>>> objects, const ESM::Cell &cell);
void sendObjects(std::shared_ptr<Player> player, std::shared_ptr<std::vector<std::shared_ptr<Object>>> objects,
const ESM::Cell &cell, bool broadcast = false);
void sendConsoleCommand(std::shared_ptr<Player> player, std::shared_ptr<std::vector<std::shared_ptr<Object>>> objects,
const ESM::Cell &cell, const std::string &consoleCommand, bool broadcast = false);
void sendContainers(std::shared_ptr<Player> player, std::shared_ptr<std::vector<std::shared_ptr<Container>>> objects,
const ESM::Cell &cell, bool broadcast = false);
void requestContainers(std::shared_ptr<Player> player);
};
};

@ -86,6 +86,7 @@ void Player::Init(LuaState &lua)
"getFactions", &Player::getFactions,
"getQuests", &Player::getQuests,
"getSpells", &Player::getSpells,
"getQuickKeys", &Player::getQuickKeys,
"getWeatherMgr", &Player::getWeatherMgr,
"getCellState", &Player::getCellState,
@ -106,7 +107,7 @@ void Player::Init(LuaState &lua)
Player::Player(RakNet::RakNetGUID guid) : BasePlayer(guid), NetActor(), changedMap(false), cClass(this),
settings(this), books(this), gui(this), dialogue(this), factions(this),
quests(this), spells(this), weatherMgr(this)
quests(this), spells(this), quickKeys(this), weatherMgr(this)
{
basePlayer = this;
netCreature = this;
@ -231,6 +232,7 @@ void Player::update()
factions.update();
quests.update();
spells.update();
quickKeys.update();
weatherMgr.update();
resetUpdateFlags();
@ -635,16 +637,18 @@ std::tuple<int, int> Player::getAttribute(unsigned short attributeId) const
if (attributeId >= ESM::Attribute::Length)
return make_tuple(0, 0);
return make_tuple(creatureStats.mAttributes[attributeId].mBase, creatureStats.mAttributes[attributeId].mCurrent);
return make_tuple(creatureStats.mAttributes[attributeId].mBase, creatureStats.mAttributes[attributeId].mMod);
}
void Player::setAttribute(unsigned short attributeId, int base, int current)
void Player::setAttribute(unsigned short attributeId, int base, bool clearModifier)
{
if (attributeId >= ESM::Attribute::Length)
return;
creatureStats.mAttributes[attributeId].mBase = base;
creatureStats.mAttributes[attributeId].mCurrent = current;
if (clearModifier)
creatureStats.mAttributes[attributeId].mMod = 0;
if (!Utils::vectorContains(&attributeIndexChanges, attributeId))
attributeIndexChanges.push_back(attributeId);
@ -659,17 +663,18 @@ std::tuple<int, int, float> Player::getSkill(unsigned short skillId) const
const auto &skill = npcStats.mSkills[skillId];
return make_tuple(skill.mBase, skill.mCurrent, skill.mProgress);
return make_tuple(skill.mBase, skill.mMod, skill.mProgress);
}
void Player::setSkill(unsigned short skillId, int base, int current, float progress)
void Player::setSkill(unsigned short skillId, int base, bool clearModifier, float progress)
{
if (skillId >= ESM::Skill::Length)
return;
auto &skill = npcStats.mSkills[skillId];
skill.mBase = base;
skill.mCurrent = current;
if (clearModifier)
skill.mMod = 0;
skill.mProgress = progress;
if (!Utils::vectorContains(&skillIndexChanges, skillId))
@ -736,6 +741,11 @@ Spells &Player::getSpells()
return spells;
}
QuickKeys &Player::getQuickKeys()
{
return quickKeys;
}
WeatherMgr &Player::getWeatherMgr()
{
return weatherMgr;

@ -160,14 +160,14 @@ public:
* @return base, current
*/
std::tuple<int, int> getAttribute(unsigned short id) const;
void setAttribute(unsigned short id, int base, int current);
void setAttribute(unsigned short id, int base, bool clearModifier);
/**
*
* @return base, current, progress, increase
*/
std::tuple<int, int, float> getSkill(unsigned short id) const;
void setSkill(unsigned short id, int base, int current, float progress);
void setSkill(unsigned short id, int base, bool clearModifier, float progress);
int getSkillIncrease(unsigned short attributeId) const;
void setSkillIncrease(unsigned short attributeId, int increase);
@ -184,6 +184,7 @@ public:
Factions &getFactions();
Quests &getQuests();
Spells &getSpells();
QuickKeys &getQuickKeys();
WeatherMgr &getWeatherMgr();
void setAuthority();
@ -203,6 +204,7 @@ private:
Factions factions;
Quests quests;
Spells spells;
QuickKeys quickKeys;
WeatherMgr weatherMgr;
sol::table storedData;
sol::table customData;

@ -33,6 +33,7 @@ namespace CoreEvent
ON_PLAYER_FACTION,
ON_PLAYER_SHAPESHIFT,
ON_PLAYER_SPELLBOOK,
ON_PLAYER_QUICKKEYS,
ON_PLAYER_TOPIC,
ON_PLAYER_DISPOSITION,
ON_PLAYER_BOOK,

@ -13,8 +13,11 @@
void GameSettings::Init(LuaState &lua)
{
lua.getState()->new_usertype<GameSettings>("Settings",
"setConsoleAllow", &GameSettings::SetConsoleAllow,
"setDifficulty", &GameSettings::SetDifficulty
"setDifficulty", &GameSettings::setDifficulty,
"setConsoleAllowed", &GameSettings::setConsoleAllowed,
"setBedRestAllowed", &GameSettings::setConsoleAllowed,
"setWildernessRestAllowed", &GameSettings::setWildernessRestAllowed,
"setWaitAllowed", &GameSettings::setWaitAllowed
);
}
@ -27,18 +30,36 @@ GameSettings::~GameSettings()
{
}
void GameSettings::SetConsoleAllow(bool state)
void GameSettings::setConsoleAllowed(bool state)
{
player->consoleAllowed = state;
changed = true;
}
void GameSettings::SetDifficulty(int difficulty)
void GameSettings::setDifficulty(int difficulty)
{
player->difficulty = difficulty;
changed = true;
}
void GameSettings::setBedRestAllowed(bool state)
{
player->bedRestAllowed = state;
changed = true;
}
void GameSettings::setWildernessRestAllowed(bool state)
{
player->wildernessRestAllowed = state;
changed = true;
}
void GameSettings::setWaitAllowed(bool state)
{
player->waitAllowed = state;
changed = true;
}
void GameSettings::update()
{
if (!changed)

@ -16,25 +16,16 @@ public:
explicit GameSettings(Player *player);
~GameSettings();
/**
* \brief Set whether the console is allowed for a player.
*
* This changes the console permission for that player in the server memory, but does not
* by itself send a packet.
*
* \param The console permission state.
*/
void SetConsoleAllow(bool state);
/**
* \brief Set the difficulty for a player.
*
* This changes the difficulty for that player in the server memory, but does not by itself
* send a packet.
*
* \param The difficulty.
*/
void SetDifficulty(int difficulty);
void setConsoleAllowed(bool state);
void setDifficulty(int difficulty);
void setBedRestAllowed(bool state);
void setWildernessRestAllowed(bool state);
void setWaitAllowed(bool state);
void update();
private:

@ -31,6 +31,7 @@
#include "player/ProcessorPlayerLevel.hpp"
#include "player/ProcessorPlayerMap.hpp"
#include "player/ProcessorPlayerPosition.hpp"
#include "player/ProcessorPlayerQuickKeys.hpp"
#include "player/ProcessorPlayerRest.hpp"
#include "player/ProcessorPlayerResurrect.hpp"
#include "player/ProcessorPlayerShapeshift.hpp"
@ -101,6 +102,7 @@ void ProcessorInitializer()
PlayerProcessor::AddProcessor(new ProcessorPlayerLevel());
PlayerProcessor::AddProcessor(new ProcessorPlayerMap());
PlayerProcessor::AddProcessor(new ProcessorPlayerPosition());
PlayerProcessor::AddProcessor(new ProcessorPlayerQuickKeys());
PlayerProcessor::AddProcessor(new ProcessorPlayerRest());
PlayerProcessor::AddProcessor(new ProcessorPlayerResurrect());
PlayerProcessor::AddProcessor(new ProcessorPlayerShapeshift());

@ -0,0 +1,26 @@
#ifndef OPENMW_PROCESSORPLAYERQUICKKEYS_HPP
#define OPENMW_PROCESSORPLAYERQUICKKEYS_HPP
#include "../PlayerProcessor.hpp"
namespace mwmp
{
class ProcessorPlayerQuickKeys : public PlayerProcessor
{
public:
ProcessorPlayerQuickKeys()
{
BPP_INIT(ID_PLAYER_QUICKKEYS)
}
void Do(PlayerPacket &packet, const std::shared_ptr<Player> &player) override
{
DEBUG_PRINTF(strPacketID.c_str());
Networking::get().getState().getEventCtrl().Call<CoreEvent::ON_PLAYER_QUICKKEYS>(player);
}
};
}
#endif //OPENMW_PROCESSORPLAYERQUICKKEYS_HPP

@ -118,8 +118,8 @@ add_openmw_dir (mwmp/processors/player ProcessorChatMessage ProcessorGUIMessageB
ProcessorPlayerBook ProcessorPlayerBounty ProcessorPlayerCellChange ProcessorPlayerCellState ProcessorPlayerCharClass
ProcessorPlayerCharGen ProcessorPlayerDeath ProcessorPlayerDisposition ProcessorPlayerEquipment ProcessorPlayerFaction
ProcessorPlayerInventory ProcessorPlayerJail ProcessorPlayerJournal ProcessorPlayerKillCount ProcessorPlayerLevel
ProcessorPlayerMap ProcessorPlayerPosition ProcessorPlayerResurrect ProcessorPlayerShapeshift ProcessorPlayerSkill
ProcessorPlayerSpeech ProcessorPlayerSpellbook ProcessorPlayerStatsDynamic ProcessorPlayerTopic
ProcessorPlayerMap ProcessorPlayerPosition ProcessorPlayerQuickKeys ProcessorPlayerResurrect ProcessorPlayerShapeshift
ProcessorPlayerSkill ProcessorPlayerSpeech ProcessorPlayerSpellbook ProcessorPlayerStatsDynamic ProcessorPlayerTopic
)
add_openmw_dir (mwmp/processors/world BaseObjectProcessor ProcessorConsoleCommand ProcessorContainer ProcessorDoorState

@ -122,8 +122,17 @@ bool OMW::Engine::frame(float frametime)
// When the window is minimized, pause the game. Currently this *has* to be here to work around a MyGUI bug.
// If we are not currently rendering, then RenderItems will not be reused resulting in a memory leak upon changing widget textures (fixed in MyGUI 3.3.2),
// and destroyed widgets will not be deleted (not fixed yet, https://github.com/MyGUI/mygui/issues/21)
if (!mEnvironment.getInputManager()->isWindowVisible())
return false;
/*
Start of tes3mp change (major)
The game cannot be paused in multiplayer, so prevent that from happening even here
*/
//if (!mEnvironment.getInputManager()->isWindowVisible())
// return false;
/*
End of tes3mp change (major)
*/
// sound
if (mUseSound)

@ -114,6 +114,16 @@ namespace MWBase
/*
End of tes3mp addition
*/
/*
Start of tes3mp addition
Make it possible to get the caption of a voice dialogue
*/
virtual std::string getVoiceCaption(const std::string& sound) const = 0;
/*
End of tes3mp addition
*/
};
}

@ -152,6 +152,29 @@ namespace MWBase
virtual void setConsoleSelectedObject(const MWWorld::Ptr& object) = 0;
/*
Start of tes3mp addition
Allow the direct setting of a console's Ptr, without the assumption that an object
was clicked and that key focus should be restored to the console window, for console
commands executed via server scripts
*/
virtual void setConsolePtr(const MWWorld::Ptr& object) = 0;
/*
End of tes3mp addition
*/
/*
Start of tes3mp addition
Allow the clearing of the console's Ptr from elsewhere in the code, so that
Ptrs used in console commands run from server scripts do not stay selected
*/
virtual void clearConsolePtr() = 0;
/*
End of tes3mp addition
*/
/// Set value for the given ID.
virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value) = 0;
virtual void setValue (int parSkill, const MWMechanics::SkillValue& value) = 0;
@ -194,6 +217,17 @@ namespace MWBase
virtual void getMousePosition(int &x, int &y) = 0;
virtual void getMousePosition(float &x, float &y) = 0;
virtual void setDragDrop(bool dragDrop) = 0;
/*
Start of tes3mp addition
Allow the completion of a drag and drop from elsewhere in the code
*/
virtual void finishDragDrop() = 0;
/*
End of tes3mp addition
*/
virtual bool getWorldMouseOver() = 0;
virtual bool toggleFogOfWar() = 0;
@ -223,6 +257,16 @@ namespace MWBase
/// update activated quick key state (if action executing was delayed for some reason)
virtual void updateActivatedQuickKey () = 0;
/*
Start of tes3mp addition
Make it possible to add quickKeys from elsewhere in the code
*/
virtual void setQuickKey(int slot, int quickKeyType, MWWorld::Ptr item, const std::string& spellId = "") = 0;
/*
End of tes3mp addition
*/
virtual std::string getSelectedSpell() = 0;
virtual void setSelectedSpell(const std::string& spellId, int successChancePercent) = 0;
virtual void setSelectedEnchantItem(const MWWorld::Ptr& item) = 0;
@ -291,6 +335,16 @@ namespace MWBase
virtual void executeInConsole (const std::string& path) = 0;
/*
Start of tes3mp addition
Allow the execution of console commands from elsewhere in the code
*/
virtual void executeCommandInConsole(const std::string& command) = 0;
/*
End of tes3mp addition
*/
virtual void enableRest() = 0;
virtual bool getRestEnabled() = 0;
virtual bool getJournalAllowed() = 0;

@ -636,7 +636,6 @@ namespace MWDialogue
if (mwmp::Main::get().getCellController()->isLocalActor(actor))
{
mwmp::LocalActor *localActor = mwmp::Main::get().getCellController()->getLocalActor(actor);
localActor->response = info->mResponse;
localActor->sound = info->mSound;
}
/*
@ -741,4 +740,32 @@ namespace MWDialogue
Misc::StringUtils::lowerCase(mLastTopic), actor.getClass().getName(actor));
}
}
/*
Start of tes3mp addition
Make it possible to get the caption of a voice dialogue
*/
std::string DialogueManager::getVoiceCaption(const std::string& sound) const
{
const MWWorld::Store<ESM::Dialogue>& dialogues = MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
for (MWWorld::Store<ESM::Dialogue>::iterator dialogueIter = dialogues.begin(); dialogueIter != dialogues.end(); ++dialogueIter)
{
if (dialogueIter->mType == ESM::Dialogue::Voice)
{
for (ESM::Dialogue::InfoContainer::const_iterator infoIter = dialogueIter->mInfo.begin();
infoIter != dialogueIter->mInfo.end(); ++infoIter)
{
if (!infoIter->mSound.empty() && Misc::StringUtils::ciEqual(sound, infoIter->mSound))
return infoIter->mResponse;
}
}
}
return "???";
}
/*
End of tes3mp addition
*/
}

@ -124,6 +124,16 @@ namespace MWDialogue
/// Removes the last added topic response for the given actor from the journal
virtual void clearInfoActor (const MWWorld::Ptr& actor) const;
/*
Start of tes3mp addition
Make it possible to get the caption of a voice dialogue
*/
virtual std::string getVoiceCaption(const std::string& sound) const;
/*
End of tes3mp addition
*/
};
}

@ -439,6 +439,21 @@ namespace MWGui
}
}
/*
Start of tes3mp addition
Allow the direct setting of a console's Ptr, without the assumption that an object
was clicked and that key focus should be restored to the console window, for console
commands executed via server scripts
*/
void Console::setPtr(const MWWorld::Ptr& object)
{
mPtr = object;
}
/*
End of tes3mp addition
*/
void Console::onReferenceUnavailable()
{
setSelectedObject(MWWorld::Ptr());

@ -27,6 +27,18 @@ namespace MWGui
/// Set the implicit object for script execution
void setSelectedObject(const MWWorld::Ptr& object);
/*
Start of tes3mp addition
Allow the direct setting of a console's Ptr, without the assumption that an object
was clicked and that key focus should be restored to the console window, for console
commands executed via server scripts
*/
void setPtr(const MWWorld::Ptr& object);
/*
End of tes3mp addition
*/
MyGUI::EditBox* mCommandLine;
MyGUI::EditBox* mHistory;

@ -1,5 +1,12 @@
#include "hud.hpp"
#include <MyGUI_RenderManager.h>
#include <MyGUI_ProgressBar.h>
#include <MyGUI_Button.h>
#include <MyGUI_InputManager.h>
#include <MyGUI_ImageBox.h>
#include <MyGUI_ScrollView.h>
/*
Start of tes3mp addition
@ -14,13 +21,6 @@
End of tes3mp addition
*/
#include <MyGUI_RenderManager.h>
#include <MyGUI_ProgressBar.h>
#include <MyGUI_Button.h>
#include <MyGUI_InputManager.h>
#include <MyGUI_ImageBox.h>
#include <MyGUI_ScrollView.h>
#include <components/settings/settings.hpp>
#include <components/openmw-mp/Log.hpp>

@ -8,6 +8,18 @@
#include <components/esm/esmwriter.hpp>
#include <components/esm/quickkeys.hpp>
/*
Start of tes3mp addition
Include additional headers for multiplayer purposes
*/
#include <components/openmw-mp/Log.hpp>
#include "../mwmp/Main.hpp"
#include "../mwmp/LocalPlayer.hpp"
/*
End of tes3mp addition
*/
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
@ -106,8 +118,36 @@ namespace MWGui
textBox->setCaption (MyGUI::utility::toString(index+1));
textBox->setNeedMouseFocus (false);
}
/*
Start of tes3mp addition
Send a PLAYER_QUICKKEYS packet whenever a key is unassigned, but only if the player
has finished character generation, so as to avoid doing anything doing startup when all
quick keys get unassigned by default
*/
if (mwmp::Main::get().getLocalPlayer()->hasFinishedCharGen() && !mwmp::Main::get().getLocalPlayer()->isReceivingQuickKeys)
{
mwmp::Main::get().getLocalPlayer()->sendQuickKey(index, Type_Unassigned);
}
/*
End of tes3mp addition
*/
}
/*
Start of tes3mp addition
Allow unassigning an index directly from elsewhere in the code
*/
void QuickKeysMenu::unassignIndex(int index)
{
unassign(mQuickKeyButtons[index], index);
}
/*
End of tes3mp addition
*/
void QuickKeysMenu::onQuickKeyButtonClicked(MyGUI::Widget* sender)
{
int index = -1;
@ -188,6 +228,17 @@ namespace MWGui
if (mItemSelectionDialog)
mItemSelectionDialog->setVisible(false);
/*
Start of tes3mp addition
Send a PLAYER_QUICKKEYS packet whenever a key is assigned to an item
*/
if (!mwmp::Main::get().getLocalPlayer()->isReceivingQuickKeys)
mwmp::Main::get().getLocalPlayer()->sendQuickKey(mSelectedIndex, Type_Item, item.getCellRef().getRefId());
/*
End of tes3mp addition
*/
}
void QuickKeysMenu::onAssignItemCancel()
@ -212,6 +263,17 @@ namespace MWGui
if (mMagicSelectionDialog)
mMagicSelectionDialog->setVisible(false);
/*
Start of tes3mp addition
Send a PLAYER_QUICKKEYS packet whenever a key is assigned to an item's magic
*/
if (!mwmp::Main::get().getLocalPlayer()->isReceivingQuickKeys)
mwmp::Main::get().getLocalPlayer()->sendQuickKey(mSelectedIndex, Type_MagicItem, item.getCellRef().getRefId());
/*
End of tes3mp addition
*/
}
void QuickKeysMenu::onAssignMagic (const std::string& spellId)
@ -246,6 +308,17 @@ namespace MWGui
if (mMagicSelectionDialog)
mMagicSelectionDialog->setVisible(false);
/*
Start of tes3mp addition
Send a PLAYER_QUICKKEYS packet whenever a key is assigned to a spell
*/
if (!mwmp::Main::get().getLocalPlayer()->isReceivingQuickKeys)
mwmp::Main::get().getLocalPlayer()->sendQuickKey(mSelectedIndex, Type_Magic, spellId);
/*
End of tes3mp addition
*/
}
void QuickKeysMenu::onAssignMagicCancel ()
@ -397,6 +470,19 @@ namespace MWGui
}
}
/*
Start of tes3mp addition
Make it possible to add quickKeys from elsewhere in the code
*/
void QuickKeysMenu::setSelectedIndex(int index)
{
mSelectedIndex = index;
}
/*
End of tes3mp addition
*/
// ---------------------------------------------------------------------------------------------------------
QuickKeysMenuAssign::QuickKeysMenuAssign (QuickKeysMenu* parent)

@ -38,6 +38,16 @@ namespace MWGui
void activateQuickKey(int index);
void updateActivatedQuickKey();
/*
Start of tes3mp addition
Allow the setting of the selected index from elsewhere in the code
*/
void setSelectedIndex(int index);
/*
End of tes3mp addition
*/
/// @note This enum is serialized, so don't move the items around!
enum QuickKeyType
{
@ -52,6 +62,16 @@ namespace MWGui
void readRecord (ESM::ESMReader& reader, uint32_t type);
void clear();
/*
Start of tes3mp addition
Allow unassigning an index directly from elsewhere in the code
*/
void unassignIndex(int index);
/*
End of tes3mp addition
*/
private:
MyGUI::EditBox* mInstructionLabel;

@ -6,6 +6,17 @@
#include <MyGUI_InputManager.h>
#include <MyGUI_ControllerManager.h>
/*
Start of tes3mp addition
Include additional headers for multiplayer purposes
*/
#include "../mwmp/Main.hpp"
#include "../mwmp/LocalPlayer.hpp"
/*
End of tes3mp addition
*/
#include <components/widgets/numericeditbox.hpp>
#include "../mwbase/environment.hpp"
@ -357,6 +368,16 @@ namespace MWGui
mPtr.getClass().getCreatureStats(mPtr).getGoldPool() - mCurrentBalance );
}
/*
Start of tes3mp addition
Send an ID_PLAYER_INVENTORY packet every time a player completes a trade
*/
mwmp::Main::get().getLocalPlayer()->sendInventory();
/*
End of tes3mp addition
*/
eventTradeDone();
MWBase::Environment::get().getWindowManager()->playSound("Item Gold Up");

@ -2,6 +2,17 @@
#include <MyGUI_Gui.h>
/*
Start of tes3mp addition
Include additional headers for multiplayer purposes
*/
#include "../mwmp/Main.hpp"
#include "../mwmp/LocalPlayer.hpp"
/*
End of tes3mp addition
*/
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
@ -167,6 +178,16 @@ namespace MWGui
// remove gold
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
/*
Start of tes3mp addition
Send an ID_PLAYER_INVENTORY packet every time a player buys training
*/
mwmp::Main::get().getLocalPlayer()->sendInventory();
/*
End of tes3mp addition
*/
// add gold to NPC trading gold pool
npcStats.setGoldPool(npcStats.getGoldPool() + price);

@ -26,6 +26,7 @@
Include additional headers for multiplayer purposes
*/
#include <components/openmw-mp/Log.hpp>
#include "../mwmp/Main.hpp"
#include "../mwmp/GUIController.hpp"
/*
@ -1061,6 +1062,20 @@ namespace MWGui
MWBase::Environment::get().getInputManager()->setDragDrop(dragDrop);
}
/*
Start of tes3mp addition
Allow the completion of a drag and drop from elsewhere in the code
*/
void WindowManager::finishDragDrop()
{
if (mDragAndDrop->mIsOnDragAndDrop)
mDragAndDrop->finish();
}
/*
End of tes3mp addition
*/
void WindowManager::setCursorVisible(bool visible)
{
if (visible == mCursorVisible)
@ -1347,6 +1362,19 @@ namespace MWGui
mConsole->executeFile (path);
}
/*
Start of tes3mp addition
Allow the execution of console commands from elsewhere in the code
*/
void WindowManager::executeCommandInConsole(const std::string& command)
{
mConsole->execute(command);
}
/*
End of tes3mp addition
*/
MWGui::InventoryWindow* WindowManager::getInventoryWindow() { return mInventoryWindow; }
MWGui::CountDialog* WindowManager::getCountDialog() { return mCountDialog; }
MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; }
@ -1487,6 +1515,35 @@ namespace MWGui
mQuickKeysMenu->activateQuickKey(index);
}
/*
Start of tes3mp addition
Make it possible to add quickKeys from elsewhere in the code
*/
void WindowManager::setQuickKey(int slot, int quickKeyType, MWWorld::Ptr item, const std::string& spellId)
{
mQuickKeysMenu->setSelectedIndex(slot);
switch (quickKeyType)
{
case QuickKeysMenu::Type_Unassigned:
mQuickKeysMenu->unassignIndex(slot);
break;
case QuickKeysMenu::Type_Item:
mQuickKeysMenu->onAssignItem(item);
break;
case QuickKeysMenu::Type_MagicItem:
mQuickKeysMenu->onAssignMagicItem(item);
break;
case QuickKeysMenu::Type_Magic:
mQuickKeysMenu->onAssignMagic(spellId);
break;
}
}
/*
End of tes3mp addition
*/
bool WindowManager::getSubtitlesEnabled ()
{
return mSubtitlesEnabled;
@ -1964,6 +2021,35 @@ namespace MWGui
mConsole->setSelectedObject(object);
}
/*
Start of tes3mp addition
Allow the direct setting of a console's Ptr, without the assumption that an object
was clicked and that key focus should be restored to the console window, for console
commands executed via server scripts
*/
void WindowManager::setConsolePtr(const MWWorld::Ptr &object)
{
mConsole->setPtr(object);
}
/*
End of tes3mp addition
*/
/*
Start of tes3mp addition
Allow the clearing of the console's Ptr from elsewhere in the code, so that
Ptrs used in console commands run from server scripts do not stay selected
*/
void WindowManager::clearConsolePtr()
{
mConsole->resetReference();
}
/*
End of tes3mp addition
*/
std::string WindowManager::correctIconPath(const std::string& path)
{
return Misc::ResourceHelpers::correctIconPath(path, mResourceSystem->getVFS());

@ -191,6 +191,29 @@ namespace MWGui
virtual void setConsoleSelectedObject(const MWWorld::Ptr& object);
/*
Start of tes3mp addition
Allow the direct setting of a console's Ptr, without the assumption that an object
was clicked and that key focus should be restored to the console window, for console
commands executed via server scripts
*/
virtual void setConsolePtr(const MWWorld::Ptr& object);
/*
End of tes3mp addition
*/
/*
Start of tes3mp addition
Allow the clearing of the console's Ptr from elsewhere in the code, so that
Ptrs used in console commands run from server scripts do not stay selected
*/
virtual void clearConsolePtr();
/*
End of tes3mp addition
*/
///< Set value for the given ID.
virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value);
virtual void setValue (int parSkill, const MWMechanics::SkillValue& value);
@ -225,6 +248,17 @@ namespace MWGui
virtual void getMousePosition(int &x, int &y);
virtual void getMousePosition(float &x, float &y);
virtual void setDragDrop(bool dragDrop);
/*
Start of tes3mp addition
Allow the completion of a drag and drop from elsewhere in the code
*/
virtual void finishDragDrop();
/*
End of tes3mp addition
*/
virtual bool getWorldMouseOver();
virtual bool toggleFogOfWar();
@ -250,6 +284,16 @@ namespace MWGui
/// update activated quick key state (if action executing was delayed for some reason)
virtual void updateActivatedQuickKey ();
/*
Start of tes3mp addition
Make it possible to add quickKeys from elsewhere in the code
*/
virtual void setQuickKey(int slot, int quickKeyType, MWWorld::Ptr item, const std::string& spellId = "");
/*
End of tes3mp addition
*/
virtual std::string getSelectedSpell() { return mSelectedSpell; }
virtual void setSelectedSpell(const std::string& spellId, int successChancePercent);
virtual void setSelectedEnchantItem(const MWWorld::Ptr& item);
@ -318,6 +362,16 @@ namespace MWGui
virtual void executeInConsole (const std::string& path);
/*
Start of tes3mp addition
Allow the execution of console commands from elsewhere in the code
*/
virtual void executeCommandInConsole(const std::string& command);
/*
End of tes3mp addition
*/
virtual void enableRest() { mRestAllowed = true; }
virtual bool getRestEnabled();

@ -1050,6 +1050,28 @@ namespace MWInput
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage2}"); //Nope,
return;
}
/*
Start of tes3mp addition
Prevent resting and waiting if they have been disabled by the server for the local player
*/
int canRest = MWBase::Environment::get().getWorld()->canRest();
if (canRest == 0 && !mwmp::Main::get().getLocalPlayer()->wildernessRestAllowed)
{
MWBase::Environment::get().getWindowManager()->messageBox("You are not allowed to rest in the wilderness.");
return;
}
else if (canRest == 1 && !mwmp::Main::get().getLocalPlayer()->waitAllowed)
{
MWBase::Environment::get().getWindowManager()->messageBox("You are not allowed to wait.");
return;
}
/*
End of tes3mp addition
*/
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_Rest); //Open rest GUI
}

@ -295,6 +295,30 @@ namespace MWMechanics
mSpellsChanged = true;
}
/*
Start of tes3mp addition
Allow the purging of an effect for a specific arg (attribute or skill)
*/
void ActiveSpells::purgeEffectByArg(short effectId, int effectArg)
{
for (TContainer::iterator it = mSpells.begin(); it != mSpells.end(); ++it)
{
for (std::vector<ActiveEffect>::iterator effectIt = it->second.mEffects.begin();
effectIt != it->second.mEffects.end();)
{
if (effectIt->mEffectId == effectId && effectIt->mArg == effectArg)
effectIt = it->second.mEffects.erase(effectIt);
else
++effectIt;
}
}
mSpellsChanged = true;
}
/*
End of tes3mp addition
*/
void ActiveSpells::clear()
{
mSpells.clear();

@ -94,6 +94,16 @@ namespace MWMechanics
/// Remove all effects with CASTER_LINKED flag that were cast by \a casterActorId
void purge (int casterActorId);
/*
Start of tes3mp addition
Allow the purging of an effect for a specific arg (attribute or skill)
*/
void purgeEffectByArg(short effectId, int effectArg);
/*
End of tes3mp addition
*/
/// Remove all spells
void clear();

@ -87,18 +87,20 @@ bool AiPursue::execute (const MWWorld::Ptr& actor, CharacterController& characte
if (pathTo(actor, dest, duration, pathTolerance) &&
std::abs(dest.mZ - aPos.pos[2]) < pathTolerance) // check the true distance in case the target is far away in Z-direction
{
target.getClass().activate(target,actor).get()->execute(actor); //Arrest player when reached
/*
Start of tes3mp addition
Record that the player has not died since the last attempt to arrest them
Close the player's inventory or open container and cancel any drag and drops
*/
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "After being pursued by %s, diedSinceArrestAttempt is now false", actor.getCellRef().getRefId().c_str());
mwmp::Main::get().getLocalPlayer()->diedSinceArrestAttempt = false;
mwmp::Main::get().getLocalPlayer()->closeInventoryWindows();
/*
End of tes3mp addition
*/
target.getClass().activate(target,actor).get()->execute(actor); //Arrest player when reached
return true;
}

@ -390,29 +390,21 @@ void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState
}
}
if (!mCurrentJump.empty())
{
mAnimation->disable(mCurrentJump);
mCurrentJump.clear();
}
if(mJumpState == JumpState_InAir)
{
if (mAnimation->hasAnimation(jumpAnimName))
{
mAnimation->play(jumpAnimName, Priority_Jump, jumpmask, false,
mAnimation->disable(mCurrentJump);
mCurrentJump = jumpAnimName;
if (mAnimation->hasAnimation("jump"))
mAnimation->play(mCurrentJump, Priority_Jump, jumpmask, false,
1.0f, (startAtLoop?"loop start":"start"), "stop", 0.0f, ~0ul);
mCurrentJump = jumpAnimName;
}
}
else if (mJumpState == JumpState_Landing)
else
{
if (mAnimation->hasAnimation(jumpAnimName))
{
mAnimation->disable(mCurrentJump);
mCurrentJump.clear();
if (mAnimation->hasAnimation("jump"))
mAnimation->play(jumpAnimName, Priority_Jump, jumpmask, true,
1.0f, "loop stop", "stop", 0.0f, 0);
mCurrentJump = jumpAnimName;
}
}
}
}
@ -1833,6 +1825,7 @@ void CharacterController::update(float duration)
mHasMovedInXY = std::abs(vec.x())+std::abs(vec.y()) > 0.0f;
isrunning = isrunning && mHasMovedInXY;
// advance athletics
if(mHasMovedInXY && mPtr == getPlayer())
{
@ -1987,8 +1980,7 @@ void CharacterController::update(float duration)
}
else
{
jumpstate = mAnimation->isPlaying(mCurrentJump) ? JumpState_Landing : JumpState_None;
jumpstate = JumpState_None;
vec.z() = 0.0f;
inJump = false;
@ -2018,15 +2010,9 @@ void CharacterController::update(float duration)
else if(rot.z() != 0.0f && !sneak && !(mPtr == getPlayer() && MWBase::Environment::get().getWorld()->isFirstPerson()))
{
if(rot.z() > 0.0f)
{
movestate = inwater ? CharState_SwimTurnRight : CharState_TurnRight;
mAnimation->disable(mCurrentJump);
}
else if(rot.z() < 0.0f)
{
movestate = inwater ? CharState_SwimTurnLeft : CharState_TurnLeft;
mAnimation->disable(mCurrentJump);
}
}
}

@ -237,7 +237,6 @@ void Cell::readSpeech(ActorList& actorList)
if (dedicatedActors.count(mapIndex) > 0)
{
DedicatedActor *actor = dedicatedActors[mapIndex];
actor->response = baseActor->response;
actor->sound = baseActor->sound;
}
}

@ -4,6 +4,8 @@
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwdialogue/dialoguemanagerimp.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/mechanicsmanagerimp.hpp"
#include "../mwmechanics/movement.hpp"
@ -217,7 +219,7 @@ void DedicatedActor::playSound()
MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager();
if (winMgr->getSubtitlesEnabled())
winMgr->messageBox(response, MWGui::ShowInDialogueMode_Never);
winMgr->messageBox(MWBase::Environment::get().getDialogueManager()->getVoiceCaption(sound), MWGui::ShowInDialogueMode_Never);
sound.clear();
}

@ -7,11 +7,14 @@
#include <apps/openmw/mwmechanics/steering.hpp>
#include "../mwbase/environment.hpp"
#include "../mwgui/windowmanagerimp.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwclass/npc.hpp"
#include "../mwdialogue/dialoguemanagerimp.hpp"
#include "../mwgui/windowmanagerimp.hpp"
#include "../mwinput/inputmanagerimp.hpp"
#include "../mwmechanics/actor.hpp"
@ -283,6 +286,21 @@ void DedicatedPlayer::setMarkerState(bool state)
removeMarker();
}
void DedicatedPlayer::playAnimation()
{
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(getPtr(),
animation.groupname, animation.mode, animation.count, animation.persist);
}
void DedicatedPlayer::playSpeech()
{
MWBase::Environment::get().getSoundManager()->say(getPtr(), sound);
MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager();
if (winMgr->getSubtitlesEnabled())
winMgr->messageBox(MWBase::Environment::get().getDialogueManager()->getVoiceCaption(sound), MWGui::ShowInDialogueMode_Never);
}
MWWorld::Ptr DedicatedPlayer::getPtr()
{
return ptr;

@ -41,6 +41,9 @@ namespace mwmp
void removeMarker();
void setMarkerState(bool state);
void playAnimation();
void playSpeech();
MWWorld::Ptr getPtr();
MWWorld::Ptr getLiveCellPtr();
MWWorld::ManualRef* getRef();

@ -1,12 +1,9 @@
//
// Created by koncord on 14.01.16.
//
#include <components/esm/esmwriter.hpp>
#include <components/openmw-mp/Log.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/journal.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwclass/creature.hpp"
#include "../mwclass/npc.hpp"
@ -18,6 +15,7 @@
#include "../mwinput/inputmanagerimp.hpp"
#include "../mwmechanics/activespells.hpp"
#include "../mwmechanics/aitravel.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/mechanicsmanagerimp.hpp"
@ -48,8 +46,11 @@ LocalPlayer::LocalPlayer()
charGenState.endStage = 1;
charGenState.isFinished = false;
consoleAllowed = false;
difficulty = 0;
consoleAllowed = false;
bedRestAllowed = true;
wildernessRestAllowed = true;
waitAllowed = true;
ignorePosPacket = false;
ignoreJailTeleportation = false;
@ -66,6 +67,8 @@ LocalPlayer::LocalPlayer()
isWerewolf = false;
diedSinceArrestAttempt = false;
isReceivingQuickKeys = false;
isPlayingAnimation = false;
}
LocalPlayer::~LocalPlayer()
@ -241,6 +244,7 @@ void LocalPlayer::updateAttributes(bool forceUpdate)
for (int i = 0; i < 8; ++i)
{
if (ptrNpcStats.getAttribute(i).getBase() != creatureStats.mAttributes[i].mBase ||
ptrNpcStats.getAttribute(i).getModifier() != creatureStats.mAttributes[i].mMod ||
ptrNpcStats.getSkillIncrease(i) != npcStats.mSkillIncrease[i] ||
forceUpdate)
{
@ -271,6 +275,7 @@ void LocalPlayer::updateSkills(bool forceUpdate)
{
// Update a skill if its base value has changed at all or its progress has changed enough
if (ptrNpcStats.getSkill(i).getBase() != npcStats.mSkills[i].mBase ||
ptrNpcStats.getSkill(i).getModifier() != npcStats.mSkills[i].mMod ||
ptrNpcStats.getSkill(i).getProgress() != npcStats.mSkills[i].mProgress ||
forceUpdate)
{
@ -331,6 +336,16 @@ void LocalPlayer::updatePosition(bool forceUpdate)
bool posIsChanging = (direction.pos[0] != 0 || direction.pos[1] != 0 ||
position.rot[0] != oldRot[0] || position.rot[2] != oldRot[1]);
// Animations can change a player's position without actually creating directional movement,
// so update positions accordingly
if (!posIsChanging && isPlayingAnimation)
{
if (MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(ptrPlayer, animation.groupname))
posIsChanging = true;
else
isPlayingAnimation = false;
}
if (forceUpdate || posIsChanging || posWasChanged)
{
oldRot[0] = position.rot[0];
@ -420,6 +435,7 @@ void LocalPlayer::updateEquipment(bool forceUpdate)
equipmentIndexChanges.push_back(slot);
item.refId = it->getCellRef().getRefId();
item.charge = it->getCellRef().getCharge();
item.enchantmentCharge = it->getCellRef().getEnchantmentCharge();
if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
{
@ -438,7 +454,8 @@ void LocalPlayer::updateEquipment(bool forceUpdate)
equipmentIndexChanges.push_back(slot);
item.refId = "";
item.count = 0;
item.charge = 0;
item.charge = -1;
item.enchantmentCharge = -1;
}
}
@ -467,6 +484,7 @@ void LocalPlayer::updateInventory(bool forceUpdate)
return true;
item.count = iter.getRefData().getCount();
item.charge = iter.getCellRef().getCharge();
item.enchantmentCharge = iter.getCellRef().getEnchantmentCharge();
return false;
};
@ -642,6 +660,9 @@ void LocalPlayer::addItems()
MWWorld::Ptr itemPtr = *ptrStore.add(item.refId, item.count, ptrPlayer);
if (item.charge != -1)
itemPtr.getCellRef().setCharge(item.charge);
if (item.enchantmentCharge != -1)
itemPtr.getCellRef().setEnchantmentCharge(item.enchantmentCharge);
}
catch (std::exception&)
{
@ -732,6 +753,15 @@ void LocalPlayer::removeSpells()
}
}
void LocalPlayer::closeInventoryWindows()
{
if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_Container) ||
MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_Inventory))
MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->finishDragDrop();
}
void LocalPlayer::setDynamicStats()
{
MWBase::World *world = MWBase::Environment::get().getWorld();
@ -759,6 +789,12 @@ void LocalPlayer::setAttributes()
for (int i = 0; i < 8; ++i)
{
// If the server wants to clear our attribute's non-zero modifier, we need to remove
// the spell effect causing it, to avoid an infinite loop where the effect keeps resetting
// the modifier
if (creatureStats.mAttributes[i].mMod == 0 && ptrCreatureStats->getAttribute(i).getModifier() > 0)
ptrCreatureStats->getActiveSpells().purgeEffectByArg(ESM::MagicEffect::FortifyAttribute, i);
attributeValue.readState(creatureStats.mAttributes[i]);
ptrCreatureStats->setAttribute(i, attributeValue);
}
@ -774,6 +810,12 @@ void LocalPlayer::setSkills()
for (int i = 0; i < 27; ++i)
{
// If the server wants to clear our skill's non-zero modifier, we need to remove
// the spell effect causing it, to avoid an infinite loop where the effect keeps resetting
// the modifier
if (npcStats.mSkills[i].mMod == 0 && ptrNpcStats->getSkill(i).getModifier() > 0)
ptrNpcStats->getActiveSpells().purgeEffectByArg(ESM::MagicEffect::FortifySkill, i);
skillValue.readState(npcStats.mSkills[i]);
ptrNpcStats->setSkill(i, skillValue);
}
@ -832,12 +874,8 @@ void LocalPlayer::setCell()
MWWorld::Ptr ptrPlayer = world->getPlayerPtr();
ESM::Position pos;
// To avoid crashes, close any container menus this player may be in
if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_Container))
{
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
MWBase::Environment::get().getWindowManager()->setDragDrop(false);
}
// To avoid crashes, close container windows this player may be in
closeInventoryWindows();
world->getPlayer().setTeleported(true);
@ -940,6 +978,9 @@ void LocalPlayer::setInventory()
MWWorld::Ptr ptrPlayer = getPlayerPtr();
MWWorld::ContainerStore &ptrStore = ptrPlayer.getClass().getContainerStore(ptrPlayer);
// Ensure no item is being drag and dropped
MWBase::Environment::get().getWindowManager()->finishDragDrop();
// Clear items in inventory
ptrStore.clear();
@ -979,6 +1020,57 @@ void LocalPlayer::setSpellbook()
addSpells();
}
void LocalPlayer::setQuickKeys()
{
MWWorld::Ptr ptrPlayer = getPlayerPtr();
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Received ID_PLAYER_QUICKKEYS from server");
// Because we send QuickKeys packets from the same OpenMW methods that we use to set received ones with,
// we need a boolean to prevent their sending here
isReceivingQuickKeys = true;
for (const auto &quickKey : quickKeyChanges.quickKeys)
{
LOG_APPEND(Log::LOG_INFO, "- slot: %i, type: %i, itemId: %s", quickKey.slot, quickKey.type, quickKey.itemId.c_str());
if (quickKey.type == QuickKey::ITEM || quickKey.type == QuickKey::ITEM_MAGIC)
{
MWWorld::InventoryStore &ptrInventory = ptrPlayer.getClass().getInventoryStore(ptrPlayer);
auto it = find_if(ptrInventory.begin(), ptrInventory.end(), [&quickKey](const MWWorld::Ptr &inventoryItem) {
return Misc::StringUtils::ciEqual(inventoryItem.getCellRef().getRefId(), quickKey.itemId);
});
if (it != ptrInventory.end())
MWBase::Environment::get().getWindowManager()->setQuickKey(quickKey.slot, quickKey.type, (*it));
}
else if (quickKey.type == QuickKey::MAGIC)
{
MWMechanics::Spells &ptrSpells = ptrPlayer.getClass().getCreatureStats(ptrPlayer).getSpells();
bool hasSpell = false;
MWMechanics::Spells::TIterator iter = ptrSpells.begin();
for (; iter != ptrSpells.end(); iter++)
{
const ESM::Spell *spell = iter->first;
if (Misc::StringUtils::ciEqual(spell->mId, quickKey.itemId))
{
hasSpell = true;
break;
}
}
if (hasSpell)
MWBase::Environment::get().getWindowManager()->setQuickKey(quickKey.slot, quickKey.type, 0, quickKey.itemId);
}
else
MWBase::Environment::get().getWindowManager()->setQuickKey(quickKey.slot, quickKey.type, 0);
}
isReceivingQuickKeys = false;
}
void LocalPlayer::setFactions()
{
MWWorld::Ptr ptrPlayer = getPlayerPtr();
@ -1088,6 +1180,7 @@ void LocalPlayer::sendInventory()
item.count = iter.getRefData().getCount();
item.charge = iter.getCellRef().getCharge();
item.enchantmentCharge = iter.getCellRef().getEnchantmentCharge();
inventoryChanges.items.push_back(item);
}
@ -1181,6 +1274,24 @@ void LocalPlayer::sendSpellRemoval(const ESM::Spell &spell)
*/
}
void LocalPlayer::sendQuickKey(unsigned short slot, int type, const std::string& itemId)
{
quickKeyChanges.quickKeys.clear();
mwmp::QuickKey quickKey;
quickKey.slot = slot;
quickKey.type = type;
quickKey.itemId = itemId;
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Sending ID_PLAYER_QUICKKEYS", itemId.c_str());
LOG_APPEND(Log::LOG_INFO, "- slot: %i, type: %i, itemId: %s", quickKey.slot, quickKey.type, quickKey.itemId.c_str());
quickKeyChanges.quickKeys.push_back(quickKey);
getNetworking()->getPlayerPacket(ID_PLAYER_QUICKKEYS)->setPlayer(this);
getNetworking()->getPlayerPacket(ID_PLAYER_QUICKKEYS)->Send();
}
void LocalPlayer::sendJournalEntry(const std::string& quest, int index, const MWWorld::Ptr& actor)
{
journalChanges.journalItems.clear();
@ -1357,3 +1468,20 @@ void LocalPlayer::storeCurrentContainer(const MWWorld::Ptr &container)
currentContainer.refNumIndex = container.getCellRef().getRefNum().mIndex;
currentContainer.mpNum = container.getCellRef().getMpNum();
}
void LocalPlayer::playAnimation()
{
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(getPlayerPtr(),
animation.groupname, animation.mode, animation.count, animation.persist);
isPlayingAnimation = true;
}
void LocalPlayer::playSpeech()
{
MWBase::Environment::get().getSoundManager()->say(getPlayerPtr(), sound);
MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager();
if (winMgr->getSubtitlesEnabled())
winMgr->messageBox(MWBase::Environment::get().getDialogueManager()->getVoiceCaption(sound), MWGui::ShowInDialogueMode_Never);
}

@ -46,6 +46,8 @@ namespace mwmp
void removeItems();
void removeSpells();
void closeInventoryWindows();
void setDynamicStats();
void setAttributes();
void setSkills();
@ -57,6 +59,7 @@ namespace mwmp
void setEquipment();
void setInventory();
void setSpellbook();
void setQuickKeys();
void setFactions();
void setKills();
void setBooks();
@ -71,6 +74,7 @@ namespace mwmp
void sendSpellAddition(const ESM::Spell &spell);
void sendSpellRemoval(std::string id);
void sendSpellRemoval(const ESM::Spell &spell);
void sendQuickKey(unsigned short slot, int type, const std::string& itemId = "");
void sendJournalEntry(const std::string& quest, int index, const MWWorld::Ptr& actor);
void sendJournalIndex(const std::string& quest, int index);
void sendFactionRank(const std::string& factionId, int rank);
@ -87,9 +91,13 @@ namespace mwmp
void storeCurrentContainer(const MWWorld::Ptr& container);
void storeCellState(const ESM::Cell& cell, int stateType);
void playAnimation();
void playSpeech();
MWWorld::Ptr getPlayerPtr();
private:
Networking *getNetworking();
MWWorld::Ptr getPlayerPtr();
};
}

@ -87,6 +87,9 @@ void WorldEvent::editContainers(MWWorld::CellStore* cellStore)
if (containerItem.charge > -1)
newPtr.getCellRef().setCharge(containerItem.charge);
if (containerItem.enchantmentCharge > -1)
newPtr.getCellRef().setEnchantmentCharge(containerItem.enchantmentCharge);
containerStore.add(newPtr, containerItem.count, ownerPtr, true);
}
else if (action == BaseEvent::REMOVE)
@ -97,8 +100,9 @@ void WorldEvent::editContainers(MWWorld::CellStore* cellStore)
{
if (Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), containerItem.refId))
{
if (ptr.getCellRef().getCharge() == containerItem.charge &&
ptr.getRefData().getCount() == containerItem.count)
if (ptr.getRefData().getCount() == containerItem.count &&
ptr.getCellRef().getCharge() == containerItem.charge &&
ptr.getCellRef().getEnchantmentCharge() == containerItem.enchantmentCharge)
{
// Is this an actor's container? If so, unequip this item if it was equipped
if (ptrFound.getClass().isActor())
@ -145,8 +149,8 @@ void WorldEvent::placeObjects(MWWorld::CellStore* cellStore)
{
for (const auto &worldObject : worldObjects)
{
LOG_APPEND(Log::LOG_VERBOSE, "- cellRef: %s, %i, %i, charge: %i, count: %i", worldObject.refId.c_str(),
worldObject.refNumIndex, worldObject.mpNum, worldObject.charge, worldObject.count);
LOG_APPEND(Log::LOG_VERBOSE, "- cellRef: %s, %i, %i, count: %i, charge: %i, enchantmentCharge: %i", worldObject.refId.c_str(),
worldObject.refNumIndex, worldObject.mpNum, worldObject.count, worldObject.charge, worldObject.enchantmentCharge);
MWWorld::Ptr ptrFound = cellStore->searchExact(0, worldObject.mpNum);
@ -156,11 +160,14 @@ void WorldEvent::placeObjects(MWWorld::CellStore* cellStore)
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), worldObject.refId, 1);
MWWorld::Ptr newPtr = ref.getPtr();
if (worldObject.count > 1)
newPtr.getRefData().setCount(worldObject.count);
if (worldObject.charge > -1)
newPtr.getCellRef().setCharge(worldObject.charge);
if (worldObject.count > 1)
newPtr.getRefData().setCount(worldObject.count);
if (worldObject.enchantmentCharge > -1)
newPtr.getCellRef().setEnchantmentCharge(worldObject.enchantmentCharge);
newPtr.getCellRef().setGoldValue(worldObject.goldValue);
newPtr = MWBase::Environment::get().getWorld()->placeObject(newPtr, cellStore, worldObject.position);
@ -424,6 +431,67 @@ void WorldEvent::activateDoors(MWWorld::CellStore* cellStore)
}
}
void WorldEvent::runConsoleCommands(MWWorld::CellStore* cellStore)
{
MWBase::WindowManager *windowManager = MWBase::Environment::get().getWindowManager();
LOG_APPEND(Log::LOG_VERBOSE, "- console command: %s", consoleCommand.c_str());
if (worldObjects.empty())
{
windowManager->clearConsolePtr();
LOG_APPEND(Log::LOG_VERBOSE, "-- running with no object reference");
windowManager->executeCommandInConsole(consoleCommand);
}
else
{
for (const auto &worldObject : worldObjects)
{
windowManager->clearConsolePtr();
if (worldObject.isPlayer)
{
BasePlayer *player = 0;
if (worldObject.guid == Main::get().getLocalPlayer()->guid)
{
player = Main::get().getLocalPlayer();
LOG_APPEND(Log::LOG_VERBOSE, "-- running on local player");
windowManager->setConsolePtr(static_cast<LocalPlayer*>(player)->getPlayerPtr());
windowManager->executeCommandInConsole(consoleCommand);
}
else if (player != 0)
{
player = PlayerList::getPlayer(guid);
LOG_APPEND(Log::LOG_VERBOSE, "-- running on player %s", player->npc.mName.c_str());
windowManager->setConsolePtr(static_cast<DedicatedPlayer*>(player)->getPtr());
windowManager->executeCommandInConsole(consoleCommand);
}
}
else
{
LOG_APPEND(Log::LOG_VERBOSE, "-- running on cellRef: %s, %i, %i", worldObject.refId.c_str(), worldObject.refNumIndex, worldObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(worldObject.refNumIndex, worldObject.mpNum);
if (ptrFound)
{
LOG_APPEND(Log::LOG_VERBOSE, "-- Found %s, %i, %i", ptrFound.getCellRef().getRefId().c_str(),
ptrFound.getCellRef().getRefNum(), ptrFound.getCellRef().getMpNum());
windowManager->setConsolePtr(ptrFound);
windowManager->executeCommandInConsole(consoleCommand);
}
}
}
windowManager->clearConsolePtr();
}
}
void WorldEvent::setLocalShorts(MWWorld::CellStore* cellStore)
{
for (const auto &worldObject : worldObjects)
@ -527,6 +595,7 @@ void WorldEvent::addObjectPlace(const MWWorld::Ptr& ptr)
worldObject.refNumIndex = ptr.getCellRef().getRefNum().mIndex;
worldObject.mpNum = 0;
worldObject.charge = ptr.getCellRef().getCharge();
worldObject.enchantmentCharge = ptr.getCellRef().getEnchantmentCharge();
// Make sure we send the RefData position instead of the CellRef one, because that's what
// we actually see on this client
@ -891,6 +960,7 @@ void WorldEvent::sendContainers(MWWorld::CellStore* cellStore)
containerItem.refId = itemPtr.getCellRef().getRefId();
containerItem.count = itemPtr.getRefData().getCount();
containerItem.charge = itemPtr.getCellRef().getCharge();
containerItem.enchantmentCharge = itemPtr.getCellRef().getEnchantmentCharge();
worldObject.containerItems.push_back(move(containerItem));
}

@ -30,6 +30,7 @@ namespace mwmp
void rotateObjects(MWWorld::CellStore* cellStore);
void animateObjects(MWWorld::CellStore* cellStore);
void activateDoors(MWWorld::CellStore* cellStore);
void runConsoleCommands(MWWorld::CellStore* cellStore);
void setLocalShorts(MWWorld::CellStore* cellStore);
void setLocalFloats(MWWorld::CellStore* cellStore);

@ -36,6 +36,7 @@
#include "player/ProcessorPlayerLevel.hpp"
#include "player/ProcessorPlayerMap.hpp"
#include "player/ProcessorPlayerPosition.hpp"
#include "player/ProcessorPlayerQuickKeys.hpp"
#include "player/ProcessorPlayerRegionAuthority.hpp"
#include "player/ProcessorPlayerRest.hpp"
#include "player/ProcessorPlayerResurrect.hpp"
@ -115,6 +116,7 @@ void ProcessorInitializer()
PlayerProcessor::AddProcessor(new ProcessorPlayerLevel());
PlayerProcessor::AddProcessor(new ProcessorPlayerMap());
PlayerProcessor::AddProcessor(new ProcessorPlayerPosition());
PlayerProcessor::AddProcessor(new ProcessorPlayerQuickKeys());
PlayerProcessor::AddProcessor(new ProcessorPlayerRegionAuthority());
PlayerProcessor::AddProcessor(new ProcessorPlayerRest());
PlayerProcessor::AddProcessor(new ProcessorPlayerResurrect());
@ -125,6 +127,7 @@ void ProcessorInitializer()
PlayerProcessor::AddProcessor(new ProcessorPlayerStatsDynamic());
PlayerProcessor::AddProcessor(new ProcessorPlayerTopic());
WorldProcessor::AddProcessor(new ProcessorConsoleCommand());
WorldProcessor::AddProcessor(new ProcessorContainer());
WorldProcessor::AddProcessor(new ProcessorDoorState());
WorldProcessor::AddProcessor(new ProcessorMusicPlay());

@ -23,9 +23,10 @@ namespace mwmp
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{
if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Console && !player->consoleAllowed)
{
MWBase::Environment::get().getWindowManager()->popGuiMode();
}
else if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Rest &&
(!player->bedRestAllowed || !player->wildernessRestAllowed || !player->waitAllowed))
MWBase::Environment::get().getWindowManager()->popGuiMode();
}
}
}

@ -15,7 +15,13 @@ namespace mwmp
virtual void Do(PlayerPacket &packet, BasePlayer *player)
{
// Placeholder to be filled in later
if (isLocal())
{
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Received ID_PLAYER_ANIM_PLAY about LocalPlayer from server");
static_cast<LocalPlayer*>(player)->playAnimation();
}
else if (player != 0)
static_cast<DedicatedPlayer*>(player)->playAnimation();
}
};
}

@ -0,0 +1,32 @@
#ifndef OPENMW_PROCESSORPLAYERQUICKKEYS_HPP
#define OPENMW_PROCESSORPLAYERQUICKKEYS_HPP
#include "../PlayerProcessor.hpp"
namespace mwmp
{
class ProcessorPlayerQuickKeys : public PlayerProcessor
{
public:
ProcessorPlayerQuickKeys()
{
BPP_INIT(ID_PLAYER_QUICKKEYS)
}
virtual void Do(PlayerPacket &packet, BasePlayer *player)
{
if (!isLocal()) return;
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Received ID_PLAYER_QUICKKEYS about LocalPlayer from server");
if (!isRequest())
{
LocalPlayer &localPlayer = static_cast<LocalPlayer&>(*player);
localPlayer.setQuickKeys();
}
}
};
}
#endif //OPENMW_PROCESSORPLAYERQUICKKEYS_HPP

@ -15,7 +15,13 @@ namespace mwmp
virtual void Do(PlayerPacket &packet, BasePlayer *player)
{
// Placeholder to be filled in later
if (isLocal())
{
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Received ID_PLAYER_SPEECH about LocalPlayer from server");
static_cast<LocalPlayer*>(player)->playSpeech();
}
else if (player != 0)
static_cast<DedicatedPlayer*>(player)->playSpeech();
}
};
}

@ -1,11 +1,11 @@
#ifndef OPENMW_PROCESSORCONSOLECOMMAND_HPP
#define OPENMW_PROCESSORCONSOLECOMMAND_HPP
#include "../WorldProcessor.hpp"
#include "BaseObjectProcessor.hpp"
namespace mwmp
{
class ProcessorConsoleCommand final: public WorldProcessor
class ProcessorConsoleCommand : public BaseObjectProcessor
{
public:
ProcessorConsoleCommand()
@ -15,8 +15,9 @@ namespace mwmp
virtual void Do(WorldPacket &packet, WorldEvent &event)
{
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Received %s", strPacketID.c_str());
//event.runConsoleCommand();
BaseObjectProcessor::Do(packet, event);
event.runConsoleCommands(ptrCellStore);
}
};
}

@ -1,5 +1,16 @@
#include "guiextensions.hpp"
/*
Start of tes3mp addition
Include additional headers for multiplayer purposes
*/
#include "../mwmp/Main.hpp"
#include "../mwmp/LocalPlayer.hpp"
/*
End of tes3mp addition
*/
#include <components/compiler/extensions.hpp>
#include <components/compiler/opcodes.hpp>
@ -57,7 +68,20 @@ namespace MWScript
if (bed.isEmpty() || !MWBase::Environment::get().getMechanicsManager()->sleepInBed(MWMechanics::getPlayer(),
bed))
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Rest, bed);
/*
Start of tes3mp change (minor)
Prevent resting if it has been disabled by the server for the local player
*/
{
if (!mwmp::Main::get().getLocalPlayer()->bedRestAllowed)
MWBase::Environment::get().getWindowManager()->messageBox("You are not allowed to rest in beds.");
else
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Rest, bed);
}
/*
End of tes3mp change (minor)
*/
}
};

@ -187,9 +187,8 @@ add_component_dir (openmw-mp/Packets/Player
PacketPlayerAttack PacketPlayerAttribute PacketPlayerBook PacketPlayerBounty PacketPlayerCellChange
PacketPlayerCellState PacketPlayerClass PacketPlayerDeath PacketPlayerEquipment PacketPlayerFaction
PacketPlayerInventory PacketPlayerJail PacketPlayerJournal PacketPlayerKillCount PacketPlayerLevel
PacketPlayerMap PacketPlayerPosition PacketPlayerRegionAuthority PacketPlayerRest PacketPlayerResurrect
PacketPlayerShapeshift PacketPlayerSkill PacketPlayerSpeech PacketPlayerSpellbook PacketPlayerStatsDynamic
PacketPlayerTopic PacketGUIWindow
PacketPlayerMap PacketPlayerPosition PacketPlayerQuickKeys PacketPlayerRegionAuthority PacketPlayerRest
PacketPlayerResurrect PacketPlayerShapeshift PacketPlayerSkill PacketPlayerSpeech PacketPlayerSpellbook PacketPlayerStatsDynamic PacketPlayerTopic PacketGUIWindow
)
add_component_dir (openmw-mp/Packets/World

@ -29,7 +29,6 @@ namespace mwmp
unsigned refNumIndex;
unsigned mpNum;
std::string response;
std::string sound;
Animation animation;

@ -12,12 +12,13 @@ namespace mwmp
std::string refId;
int count;
int charge;
int enchantmentCharge;
int actionCount;
inline bool operator==(const ContainerItem& rhs)
{
return refId == rhs.refId && count == rhs.count && charge == rhs.charge;
return refId == rhs.refId && count == rhs.count && charge == rhs.charge && enchantmentCharge == rhs.enchantmentCharge;
}
};
@ -28,6 +29,7 @@ namespace mwmp
unsigned mpNum;
int count;
int charge;
int enchantmentCharge;
int goldValue;
ESM::Position position;
@ -55,6 +57,9 @@ namespace mwmp
std::vector<ContainerItem> containerItems;
unsigned int containerItemCount;
RakNet::RakNetGUID guid; // only for events that can also affect players
bool isPlayer;
};
class BaseEvent
@ -84,6 +89,7 @@ namespace mwmp
std::vector<WorldObject> worldObjects;
ESM::Cell cell;
std::string consoleCommand;
unsigned char action; // 0 - Clear and set in entirety, 1 - Add item, 2 - Remove item, 3 - Request items

@ -81,6 +81,22 @@ namespace mwmp
std::string bookId;
};
struct QuickKey
{
std::string itemId;
enum QUICKKEY_TYPE
{
ITEM = 0,
MAGIC = 1,
ITEM_MAGIC = 2,
UNASSIGNED = 3
};
unsigned short slot;
int type;
};
struct CellState
{
ESM::Cell cell;
@ -146,6 +162,11 @@ namespace mwmp
int action; // 0 - Clear and set in entirety, 1 - Add spell, 2 - Remove spell
};
struct QuickKeyChanges
{
std::vector<QuickKey> quickKeys;
};
struct CellStateChanges
{
std::vector<CellState> cellStates;
@ -248,6 +269,7 @@ namespace mwmp
std::vector<int> skillIndexChanges;
SpellbookChanges spellbookChanges;
QuickKeyChanges quickKeyChanges;
JournalChanges journalChanges;
FactionChanges factionChanges;
TopicChanges topicChanges;
@ -259,8 +281,17 @@ namespace mwmp
ESM::ActiveSpells activeSpells;
CurrentContainer currentContainer;
bool consoleAllowed;
struct
{
int currentWeather, nextWeather;
float updateTime, transitionFactor;
} weather;
int difficulty;
bool consoleAllowed;
bool bedRestAllowed;
bool wildernessRestAllowed;
bool waitAllowed;
bool ignorePosPacket;
@ -273,6 +304,9 @@ namespace mwmp
CharGenState charGenState;
std::string passw;
std::string sound;
Animation animation;
bool isWerewolf;
std::string creatureModel;
bool useCreatureName;
@ -288,12 +322,8 @@ namespace mwmp
ResurrectType resurrectType;
bool diedSinceArrestAttempt;
struct
{
int currentWeather, nextWeather;
float updateTime, transitionFactor;
} weather;
bool isReceivingQuickKeys;
bool isPlayingAnimation;
};
}

@ -12,10 +12,11 @@ namespace mwmp
std::string refId;
int count;
int charge;
int enchantmentCharge;
inline bool operator==(const Item& rhs)
{
return refId == rhs.refId && count == rhs.count && charge == rhs.charge;
return refId == rhs.refId && count == rhs.count && charge == rhs.charge && enchantmentCharge == rhs.enchantmentCharge;
}
};

@ -29,6 +29,7 @@
#include "../Packets/Player/PacketPlayerLevel.hpp"
#include "../Packets/Player/PacketPlayerMap.hpp"
#include "../Packets/Player/PacketPlayerPosition.hpp"
#include "../Packets/Player/PacketPlayerQuickKeys.hpp"
#include "../Packets/Player/PacketPlayerRegionAuthority.hpp"
#include "../Packets/Player/PacketPlayerRest.hpp"
#include "../Packets/Player/PacketPlayerResurrect.hpp"
@ -83,6 +84,7 @@ mwmp::PlayerPacketController::PlayerPacketController(RakNet::RakPeerInterface *p
AddPacket<PacketPlayerLevel>(&packets, peer);
AddPacket<PacketPlayerMap>(&packets, peer);
AddPacket<PacketPlayerPosition>(&packets, peer);
AddPacket<PacketPlayerQuickKeys>(&packets, peer);
AddPacket<PacketPlayerRegionAuthority>(&packets, peer);
AddPacket<PacketPlayerRest>(&packets, peer);
AddPacket<PacketPlayerResurrect>(&packets, peer);

@ -45,6 +45,7 @@ enum GameMessages
ID_PLAYER_LEVEL,
ID_PLAYER_MAP,
ID_PLAYER_POSITION,
ID_PLAYER_QUICKKEYS,
ID_PLAYER_REGION_AUTHORITY,
ID_PLAYER_RESURRECT,
ID_PLAYER_REST,

@ -16,5 +16,6 @@ void PacketActorEquipment::Actor(BaseActor &actor, bool send)
RW(equipmentItem.refId, send);
RW(equipmentItem.count, send);
RW(equipmentItem.charge, send);
RW(equipmentItem.enchantmentCharge, send);
}
}

@ -11,6 +11,5 @@ PacketActorSpeech::PacketActorSpeech(RakNet::RakPeerInterface *peer) : ActorPack
void PacketActorSpeech::Actor(BaseActor &actor, bool send)
{
RW(actor.response, send);
RW(actor.sound, send);
}

@ -13,6 +13,9 @@ void PacketGameSettings::Packet(RakNet::BitStream *bs, bool send)
{
PlayerPacket::Packet(bs, send);
RW(player->consoleAllowed, send);
RW(player->difficulty, send);
RW(player->consoleAllowed, send);
RW(player->bedRestAllowed, send);
RW(player->wildernessRestAllowed, send);
RW(player->waitAllowed, send);
}

@ -10,5 +10,8 @@ void mwmp::PacketPlayerAnimPlay::Packet(RakNet::BitStream *bs, bool send)
{
PlayerPacket::Packet(bs, send);
// Placeholder to be filled in later
RW(player->animation.groupname, send);
RW(player->animation.mode, send);
RW(player->animation.count, send);
RW(player->animation.persist, send);
}

@ -37,5 +37,6 @@ void PacketPlayerInventory::Packet(RakNet::BitStream *bs, bool send)
RW(item.refId, send, true);
RW(item.count, send);
RW(item.charge, send);
RW(item.enchantmentCharge, send);
}
}

@ -0,0 +1,31 @@
#include <components/openmw-mp/NetworkMessages.hpp>
#include "PacketPlayerQuickKeys.hpp"
using namespace std;
using namespace mwmp;
PacketPlayerQuickKeys::PacketPlayerQuickKeys(RakNet::RakPeerInterface *peer) : PlayerPacket(peer)
{
packetID = ID_PLAYER_QUICKKEYS;
}
void PacketPlayerQuickKeys::Packet(RakNet::BitStream *bs, bool send)
{
PlayerPacket::Packet(bs, send);
uint32_t count;
if (send)
count = static_cast<uint32_t>(player->quickKeyChanges.quickKeys.size());
RW(count, send);
for (auto &&quickKey : player->quickKeyChanges.quickKeys)
{
RW(quickKey.type, send);
RW(quickKey.slot, send);
if (quickKey.type != QuickKey::UNASSIGNED)
RW(quickKey.itemId, send);
}
}

@ -0,0 +1,17 @@
#ifndef OPENMW_PACKETPLAYERQUICKKEYS_HPP
#define OPENMW_PACKETPLAYERQUICKKEYS_HPP
#include <components/openmw-mp/Packets/Player/PlayerPacket.hpp>
namespace mwmp
{
class PacketPlayerQuickKeys : public PlayerPacket
{
public:
PacketPlayerQuickKeys(RakNet::RakPeerInterface *peer);
virtual void Packet(RakNet::BitStream *bs, bool send);
};
}
#endif //OPENMW_PACKETPLAYERQUICKKEYS_HPP

@ -10,5 +10,5 @@ void mwmp::PacketPlayerSpeech::Packet(RakNet::BitStream *bs, bool send)
{
PlayerPacket::Packet(bs, send);
// Placeholder to be filled in later
RW(player->sound, send);
}

@ -30,41 +30,6 @@ void PacketPlayerSpellbook::Packet(RakNet::BitStream *bs, bool send)
for (auto &&spell : player->spellbookChanges.spells)
{
RW(spell.mId, send, true);
if (spell.mId.find("$dynamic") != string::npos)
{
RW(spell.mName, send, true);
RW(spell.mData.mType, send, true);
RW(spell.mData.mCost, send, true);
RW(spell.mData.mFlags, send, true);
uint32_t effectCount;
if (send)
effectCount = static_cast<uint32_t>(spell.mEffects.mList.size());
RW(effectCount, send, true);
if (!send)
{
spell.mEffects.mList.resize(effectCount);
}
for (auto &&effect : spell.mEffects.mList)
{
RW(effect.mEffectID, send, true);
RW(effect.mSkill, send, true);
RW(effect.mAttribute, send, true);
RW(effect.mRange, send, true);
RW(effect.mArea, send, true);
RW(effect.mDuration, send, true);
RW(effect.mMagnMin, send, true);
RW(effect.mMagnMax, send, true);
}
}
}
}

@ -8,7 +8,21 @@ PacketConsoleCommand::PacketConsoleCommand(RakNet::RakPeerInterface *peer) : Wor
packetID = ID_CONSOLE_COMMAND;
}
void PacketConsoleCommand::Object(WorldObject &worldObject, bool send)
void PacketConsoleCommand::Packet(RakNet::BitStream *bs, bool send)
{
WorldPacket::Object(worldObject, send);
if (!PacketHeader(bs, send))
return;
RW(event->consoleCommand, send);
WorldObject worldObject;
for (auto &&worldObject : event->worldObjects)
{
RW(worldObject.isPlayer, send);
if (worldObject.isPlayer)
RW(worldObject.guid, send);
else
Object(worldObject, send);
}
}

@ -9,8 +9,8 @@ namespace mwmp
{
public:
explicit PacketConsoleCommand(RakNet::RakPeerInterface *peer);
void Object(WorldObject &obj, bool send) override;
void Packet(RakNet::BitStream *bs, bool send) override;
};
}

@ -46,6 +46,7 @@ void PacketContainer::Packet(RakNet::BitStream *bs, bool send)
RW(containerItem.refId, send);
RW(containerItem.count, send);
RW(containerItem.charge, send);
RW(containerItem.enchantmentCharge, send);
RW(containerItem.actionCount, send);
}
}

@ -14,6 +14,7 @@ void PacketObjectPlace::Object(WorldObject &worldObject, bool send)
WorldPacket::Object(worldObject, send);
RW(worldObject.count, send);
RW(worldObject.charge, send);
RW(worldObject.enchantmentCharge, send);
RW(worldObject.goldValue, send);
RW(worldObject.position, send);
}

@ -1,3 +1,19 @@
0.6.2
-----
* Packet for quick keys
* Packet for player sounds
* Packet for player animations
* Packet for console commands
* Enchantment charge values are now included in item and object placement packets
* Settings packet can now be used to separately enable or disable resting in beds, resting in the wilderness and waiting
* Changes in attribute and skill modifiers now send their respective packets
* Attribute and skill packets using 0 as a modifier can now remove all attribute or skill fortification effects from a player
* Completion of vendor trades and skill training now sends inventory packets
* Item drag and dropping is now finished when arrested or when moved to another cell by the server
* Window minimization no longer pauses the game
* Actor speech captions are now searched for in dialogues instead of being sent in packets
0.6.1
-----

@ -23,6 +23,13 @@ Community administrators
Testman
Community moderators
--------------------
Capostrophic
Michael Fitzmayer (mupf)
Art
---
@ -33,8 +40,7 @@ Special thanks (in alphabetical order)
--------------------------------------
Camul
Capostrophic
Dave
David Wery
DestinedToDie
Gluka
Goodevil
@ -45,6 +51,7 @@ Special thanks (in alphabetical order)
Jeremiah
Lewis Sadlier
Luc Keating
Malseph
Michael Zagar (Zoops)
Olaxan
psi29a

Loading…
Cancel
Save