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

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

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

@ -15,7 +15,7 @@ void Dialogue::Init(LuaState &lua)
lua.getState()->new_usertype<Dialogue>("Dialogue", lua.getState()->new_usertype<Dialogue>("Dialogue",
"addTopic", &Dialogue::addTopic, "addTopic", &Dialogue::addTopic,
"getTopicId", &Dialogue::getTopicId, "getTopicId", &Dialogue::getTopicId,
"getChanges", &Dialogue::getChanges, "size", &Dialogue::size,
"reset", &Dialogue::reset); "reset", &Dialogue::reset);
} }
@ -57,7 +57,30 @@ std::string Dialogue::getTopicId(unsigned int i) const
return player->topicChanges.topics.at(i).topicId; return player->topicChanges.topics.at(i).topicId;
} }
unsigned int Dialogue::getChanges() const size_t Dialogue::size() const
{ {
return player->topicChanges.topics.size(); 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); void addTopic(const std::string &topicId);
std::string getTopicId(unsigned int i) const; 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 reset();
void update(); void update();

@ -19,22 +19,7 @@ void Factions::Init(LuaState &lua)
"setFaction", &Factions::setFaction, "setFaction", &Factions::setFaction,
"clear", &Factions::clear, "clear", &Factions::clear,
"size", &Factions::size "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) Factions::Factions(Player *player): player(player), changed(false)

@ -143,3 +143,109 @@ void GUI::onGUIWindowAction()
it->second->call(player->guiWindow); 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); std::shared_ptr<Window> createWindow(short x, short y, sol::function fn, sol::this_environment te);
void deleteWindow(std::shared_ptr<Window> window); void deleteWindow(std::shared_ptr<Window> window);
void onGUIWindowAction(); 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: private:
Player *player; Player *player;
bool changed; bool changed;
@ -41,4 +46,44 @@ private:
int lastWindowId; 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(); 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].refId = refId;
netActor->getNetCreature()->equipmentItems[slot].count = count; netActor->getNetCreature()->equipmentItems[slot].count = count;
netActor->getNetCreature()->equipmentItems[slot].charge = charge; netActor->getNetCreature()->equipmentItems[slot].charge = charge;
netActor->getNetCreature()->equipmentItems[slot].enchantmentCharge = enchantmentCharge;
if (!Utils::vectorContains(&netActor->getNetCreature()->equipmentIndexChanges, slot)) if (!Utils::vectorContains(&netActor->getNetCreature()->equipmentIndexChanges, slot))
netActor->getNetCreature()->equipmentIndexChanges.push_back(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) 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) if (inventoryChanged == mwmp::InventoryChanges::REMOVE)
return; return;
@ -105,6 +106,7 @@ void Inventory::addItem(const std::string &refId, unsigned int count, int charge
item.refId = refId; item.refId = refId;
item.count = count; item.count = count;
item.charge = charge; item.charge = charge;
item.enchantmentCharge = enchantmentCharge;
netActor->getNetCreature()->inventoryChanges.items.push_back(item); netActor->getNetCreature()->inventoryChanges.items.push_back(item);
netActor->getNetCreature()->inventoryChanges.action = mwmp::InventoryChanges::ADD; netActor->getNetCreature()->inventoryChanges.action = mwmp::InventoryChanges::ADD;
@ -135,16 +137,16 @@ bool Inventory::hasItemEquipped(const std::string &refId) const
return false; 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]; 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); 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() void Inventory::resetEquipmentFlag()

@ -25,19 +25,19 @@ public:
//inventory //inventory
int getChangesSize() const; 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); void removeItem(const std::string& refId, unsigned short count);
/** /**
* *
* @param slot * @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 // 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); void unequipItem(unsigned short slot);
bool hasItemEquipped(const std::string& refId) const; bool hasItemEquipped(const std::string& refId) const;
@ -45,9 +45,9 @@ public:
/** /**
* *
* @param slot * @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: private:

@ -17,6 +17,7 @@ void Object::Init(LuaState &lua)
"refId", sol::property(&BaseObject::getRefId, &BaseObject::setRefId), "refId", sol::property(&BaseObject::getRefId, &BaseObject::setRefId),
"refNum", sol::property(&BaseObject::getRefNum, &BaseObject::setRefNum), "refNum", sol::property(&BaseObject::getRefNum, &BaseObject::setRefNum),
"mpNum", sol::property(&BaseObject::getMpNum, &BaseObject::setMpNum), "mpNum", sol::property(&BaseObject::getMpNum, &BaseObject::setMpNum),
"guid", sol::property(&BaseObject::getGuid, &BaseObject::setGuid),
"getPosition", &Object::getPosition, "getPosition", &Object::getPosition,
"setPosition", &Object::setPosition, "setPosition", &Object::setPosition,
"getRotation", &Object::getRotation, "getRotation", &Object::getRotation,
@ -111,6 +112,18 @@ void BaseObject::setMpNum(unsigned mpNum)
object.mpNum = 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 int Object::getCount() const
{ {
return object.count; 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 int Object::getGoldValue() const
{ {
return object.goldValue; 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); 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); auto &item = object.containerItems.at(i);
item.refId = refId; item.refId = refId;
item.count = count; item.count = count;
item.charge = charge; item.charge = charge;
item.enchantmentCharge = enchantmentCharge;
changed = true; 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; mwmp::ContainerItem item;
item.refId = refId; item.refId = refId;
item.count = count; item.count = count;
item.charge = charge; item.charge = charge;
item.enchantmentCharge = enchantmentCharge;
object.containerItems.push_back(item); object.containerItems.push_back(item);
changed = true; changed = true;
} }
@ -304,7 +331,7 @@ shared_ptr<vector<shared_ptr<Container>>> ObjectController::copyContainers(mwmp:
return containers; 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 enum Type
{ {
@ -384,60 +411,105 @@ void ObjectController::sendObjects(shared_ptr<Player> player, shared_ptr<vector<
auto packet = worldCtrl->GetPacket(ID_DOOR_STATE); auto packet = worldCtrl->GetPacket(ID_DOOR_STATE);
auto &event = events[Type::DOOR_STATE]; auto &event = events[Type::DOOR_STATE];
packet->setEvent(&event); packet->setEvent(&event);
packet->Send(event.guid); packet->Send(false);
if (broadcast)
packet->Send(true);
} }
if (changed[Type::OBJECT_STATE]) if (changed[Type::OBJECT_STATE])
{ {
auto packet = worldCtrl->GetPacket(ID_OBJECT_STATE); auto packet = worldCtrl->GetPacket(ID_OBJECT_STATE);
auto &event = events[Type::OBJECT_STATE]; auto &event = events[Type::OBJECT_STATE];
packet->setEvent(&event); packet->setEvent(&event);
packet->Send(event.guid); packet->Send(false);
if (broadcast)
packet->Send(true);
} }
if (changed[Type::OBJECT_SCALE]) if (changed[Type::OBJECT_SCALE])
{ {
auto packet = worldCtrl->GetPacket(ID_OBJECT_SCALE); auto packet = worldCtrl->GetPacket(ID_OBJECT_SCALE);
auto &event = events[Type::OBJECT_SCALE]; auto &event = events[Type::OBJECT_SCALE];
packet->setEvent(&event); packet->setEvent(&event);
packet->Send(event.guid); packet->Send(false);
if (broadcast)
packet->Send(true);
} }
if (changed[Type::OBJECT_TRAP]) if (changed[Type::OBJECT_TRAP])
{ {
auto packet = worldCtrl->GetPacket(ID_OBJECT_TRAP); auto packet = worldCtrl->GetPacket(ID_OBJECT_TRAP);
auto &event = events[Type::OBJECT_TRAP]; auto &event = events[Type::OBJECT_TRAP];
packet->setEvent(&event); packet->setEvent(&event);
packet->Send(event.guid); packet->Send(false);
if (broadcast)
packet->Send(true);
} }
if (changed[Type::OBJECT_LOCK]) if (changed[Type::OBJECT_LOCK])
{ {
auto packet = worldCtrl->GetPacket(ID_OBJECT_LOCK); auto packet = worldCtrl->GetPacket(ID_OBJECT_LOCK);
auto &event = events[Type::OBJECT_LOCK]; auto &event = events[Type::OBJECT_LOCK];
packet->setEvent(&event); packet->setEvent(&event);
packet->Send(event.guid); packet->Send(false);
if (broadcast)
packet->Send(true);
} }
if (changed[Type::OBJECT_DELETE]) if (changed[Type::OBJECT_DELETE])
{ {
auto packet = worldCtrl->GetPacket(ID_OBJECT_DELETE); auto packet = worldCtrl->GetPacket(ID_OBJECT_DELETE);
auto &event = events[Type::OBJECT_DELETE]; auto &event = events[Type::OBJECT_DELETE];
packet->setEvent(&event); packet->setEvent(&event);
packet->Send(event.guid); packet->Send(false);
if (broadcast)
packet->Send(true);
} }
if (changed[Type::OBJECT_SCALE]) if (changed[Type::OBJECT_SCALE])
{ {
auto packet = worldCtrl->GetPacket(ID_OBJECT_SPAWN); auto packet = worldCtrl->GetPacket(ID_OBJECT_SPAWN);
auto &event = events[Type::OBJECT_SCALE]; auto &event = events[Type::OBJECT_SCALE];
packet->setEvent(&event); packet->setEvent(&event);
packet->Send(event.guid); packet->Send(false);
if (broadcast)
packet->Send(true);
} }
if (changed[Type::OBJECT_PLACE]) if (changed[Type::OBJECT_PLACE])
{ {
auto packet = worldCtrl->GetPacket(ID_OBJECT_PLACE); auto packet = worldCtrl->GetPacket(ID_OBJECT_PLACE);
auto &event = events[Type::OBJECT_PLACE]; auto &event = events[Type::OBJECT_PLACE];
packet->setEvent(&event); 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; 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); auto packet = mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_CONTAINER);
packet->setEvent(&event); packet->setEvent(&event);
packet->Send(event.guid); packet->Send(false);
if (broadcast)
packet->Send(true);
} }
void ObjectController::requestContainers(shared_ptr<Player> player) void ObjectController::requestContainers(shared_ptr<Player> player)

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

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

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

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

@ -13,8 +13,11 @@
void GameSettings::Init(LuaState &lua) void GameSettings::Init(LuaState &lua)
{ {
lua.getState()->new_usertype<GameSettings>("Settings", 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; player->consoleAllowed = state;
changed = true; changed = true;
} }
void GameSettings::SetDifficulty(int difficulty) void GameSettings::setDifficulty(int difficulty)
{ {
player->difficulty = difficulty; player->difficulty = difficulty;
changed = true; 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() void GameSettings::update()
{ {
if (!changed) if (!changed)

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

@ -31,6 +31,7 @@
#include "player/ProcessorPlayerLevel.hpp" #include "player/ProcessorPlayerLevel.hpp"
#include "player/ProcessorPlayerMap.hpp" #include "player/ProcessorPlayerMap.hpp"
#include "player/ProcessorPlayerPosition.hpp" #include "player/ProcessorPlayerPosition.hpp"
#include "player/ProcessorPlayerQuickKeys.hpp"
#include "player/ProcessorPlayerRest.hpp" #include "player/ProcessorPlayerRest.hpp"
#include "player/ProcessorPlayerResurrect.hpp" #include "player/ProcessorPlayerResurrect.hpp"
#include "player/ProcessorPlayerShapeshift.hpp" #include "player/ProcessorPlayerShapeshift.hpp"
@ -101,6 +102,7 @@ void ProcessorInitializer()
PlayerProcessor::AddProcessor(new ProcessorPlayerLevel()); PlayerProcessor::AddProcessor(new ProcessorPlayerLevel());
PlayerProcessor::AddProcessor(new ProcessorPlayerMap()); PlayerProcessor::AddProcessor(new ProcessorPlayerMap());
PlayerProcessor::AddProcessor(new ProcessorPlayerPosition()); PlayerProcessor::AddProcessor(new ProcessorPlayerPosition());
PlayerProcessor::AddProcessor(new ProcessorPlayerQuickKeys());
PlayerProcessor::AddProcessor(new ProcessorPlayerRest()); PlayerProcessor::AddProcessor(new ProcessorPlayerRest());
PlayerProcessor::AddProcessor(new ProcessorPlayerResurrect()); PlayerProcessor::AddProcessor(new ProcessorPlayerResurrect());
PlayerProcessor::AddProcessor(new ProcessorPlayerShapeshift()); 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 ProcessorPlayerBook ProcessorPlayerBounty ProcessorPlayerCellChange ProcessorPlayerCellState ProcessorPlayerCharClass
ProcessorPlayerCharGen ProcessorPlayerDeath ProcessorPlayerDisposition ProcessorPlayerEquipment ProcessorPlayerFaction ProcessorPlayerCharGen ProcessorPlayerDeath ProcessorPlayerDisposition ProcessorPlayerEquipment ProcessorPlayerFaction
ProcessorPlayerInventory ProcessorPlayerJail ProcessorPlayerJournal ProcessorPlayerKillCount ProcessorPlayerLevel ProcessorPlayerInventory ProcessorPlayerJail ProcessorPlayerJournal ProcessorPlayerKillCount ProcessorPlayerLevel
ProcessorPlayerMap ProcessorPlayerPosition ProcessorPlayerResurrect ProcessorPlayerShapeshift ProcessorPlayerSkill ProcessorPlayerMap ProcessorPlayerPosition ProcessorPlayerQuickKeys ProcessorPlayerResurrect ProcessorPlayerShapeshift
ProcessorPlayerSpeech ProcessorPlayerSpellbook ProcessorPlayerStatsDynamic ProcessorPlayerTopic ProcessorPlayerSkill ProcessorPlayerSpeech ProcessorPlayerSpellbook ProcessorPlayerStatsDynamic ProcessorPlayerTopic
) )
add_openmw_dir (mwmp/processors/world BaseObjectProcessor ProcessorConsoleCommand ProcessorContainer ProcessorDoorState 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. // 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), // 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) // 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 // sound
if (mUseSound) if (mUseSound)

@ -114,6 +114,16 @@ namespace MWBase
/* /*
End of tes3mp addition 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; 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. /// Set value for the given ID.
virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value) = 0; virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value) = 0;
virtual void setValue (int parSkill, const MWMechanics::SkillValue& 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(int &x, int &y) = 0;
virtual void getMousePosition(float &x, float &y) = 0; virtual void getMousePosition(float &x, float &y) = 0;
virtual void setDragDrop(bool dragDrop) = 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 getWorldMouseOver() = 0;
virtual bool toggleFogOfWar() = 0; virtual bool toggleFogOfWar() = 0;
@ -223,6 +257,16 @@ namespace MWBase
/// update activated quick key state (if action executing was delayed for some reason) /// update activated quick key state (if action executing was delayed for some reason)
virtual void updateActivatedQuickKey () = 0; 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 std::string getSelectedSpell() = 0;
virtual void setSelectedSpell(const std::string& spellId, int successChancePercent) = 0; virtual void setSelectedSpell(const std::string& spellId, int successChancePercent) = 0;
virtual void setSelectedEnchantItem(const MWWorld::Ptr& item) = 0; virtual void setSelectedEnchantItem(const MWWorld::Ptr& item) = 0;
@ -291,6 +335,16 @@ namespace MWBase
virtual void executeInConsole (const std::string& path) = 0; 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 void enableRest() = 0;
virtual bool getRestEnabled() = 0; virtual bool getRestEnabled() = 0;
virtual bool getJournalAllowed() = 0; virtual bool getJournalAllowed() = 0;

@ -636,7 +636,6 @@ namespace MWDialogue
if (mwmp::Main::get().getCellController()->isLocalActor(actor)) if (mwmp::Main::get().getCellController()->isLocalActor(actor))
{ {
mwmp::LocalActor *localActor = mwmp::Main::get().getCellController()->getLocalActor(actor); mwmp::LocalActor *localActor = mwmp::Main::get().getCellController()->getLocalActor(actor);
localActor->response = info->mResponse;
localActor->sound = info->mSound; localActor->sound = info->mSound;
} }
/* /*
@ -741,4 +740,32 @@ namespace MWDialogue
Misc::StringUtils::lowerCase(mLastTopic), actor.getClass().getName(actor)); 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 /// Removes the last added topic response for the given actor from the journal
virtual void clearInfoActor (const MWWorld::Ptr& actor) const; 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() void Console::onReferenceUnavailable()
{ {
setSelectedObject(MWWorld::Ptr()); setSelectedObject(MWWorld::Ptr());

@ -27,6 +27,18 @@ namespace MWGui
/// Set the implicit object for script execution /// Set the implicit object for script execution
void setSelectedObject(const MWWorld::Ptr& object); 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* mCommandLine;
MyGUI::EditBox* mHistory; MyGUI::EditBox* mHistory;

@ -1,5 +1,12 @@
#include "hud.hpp" #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 Start of tes3mp addition
@ -14,13 +21,6 @@
End of tes3mp addition 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/settings/settings.hpp>
#include <components/openmw-mp/Log.hpp> #include <components/openmw-mp/Log.hpp>

@ -8,6 +8,18 @@
#include <components/esm/esmwriter.hpp> #include <components/esm/esmwriter.hpp>
#include <components/esm/quickkeys.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/inventorystore.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
@ -106,8 +118,36 @@ namespace MWGui
textBox->setCaption (MyGUI::utility::toString(index+1)); textBox->setCaption (MyGUI::utility::toString(index+1));
textBox->setNeedMouseFocus (false); 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) void QuickKeysMenu::onQuickKeyButtonClicked(MyGUI::Widget* sender)
{ {
int index = -1; int index = -1;
@ -188,6 +228,17 @@ namespace MWGui
if (mItemSelectionDialog) if (mItemSelectionDialog)
mItemSelectionDialog->setVisible(false); 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() void QuickKeysMenu::onAssignItemCancel()
@ -212,6 +263,17 @@ namespace MWGui
if (mMagicSelectionDialog) if (mMagicSelectionDialog)
mMagicSelectionDialog->setVisible(false); 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) void QuickKeysMenu::onAssignMagic (const std::string& spellId)
@ -246,6 +308,17 @@ namespace MWGui
if (mMagicSelectionDialog) if (mMagicSelectionDialog)
mMagicSelectionDialog->setVisible(false); 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 () 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) QuickKeysMenuAssign::QuickKeysMenuAssign (QuickKeysMenu* parent)

@ -38,6 +38,16 @@ namespace MWGui
void activateQuickKey(int index); void activateQuickKey(int index);
void updateActivatedQuickKey(); 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! /// @note This enum is serialized, so don't move the items around!
enum QuickKeyType enum QuickKeyType
{ {
@ -52,6 +62,16 @@ namespace MWGui
void readRecord (ESM::ESMReader& reader, uint32_t type); void readRecord (ESM::ESMReader& reader, uint32_t type);
void clear(); 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: private:
MyGUI::EditBox* mInstructionLabel; MyGUI::EditBox* mInstructionLabel;

@ -6,6 +6,17 @@
#include <MyGUI_InputManager.h> #include <MyGUI_InputManager.h>
#include <MyGUI_ControllerManager.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 <components/widgets/numericeditbox.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
@ -357,6 +368,16 @@ namespace MWGui
mPtr.getClass().getCreatureStats(mPtr).getGoldPool() - mCurrentBalance ); 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(); eventTradeDone();
MWBase::Environment::get().getWindowManager()->playSound("Item Gold Up"); MWBase::Environment::get().getWindowManager()->playSound("Item Gold Up");

@ -2,6 +2,17 @@
#include <MyGUI_Gui.h> #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/windowmanager.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -167,6 +178,16 @@ namespace MWGui
// remove gold // remove gold
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player); 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 // add gold to NPC trading gold pool
npcStats.setGoldPool(npcStats.getGoldPool() + price); npcStats.setGoldPool(npcStats.getGoldPool() + price);

@ -26,6 +26,7 @@
Include additional headers for multiplayer purposes Include additional headers for multiplayer purposes
*/ */
#include <components/openmw-mp/Log.hpp>
#include "../mwmp/Main.hpp" #include "../mwmp/Main.hpp"
#include "../mwmp/GUIController.hpp" #include "../mwmp/GUIController.hpp"
/* /*
@ -1061,6 +1062,20 @@ namespace MWGui
MWBase::Environment::get().getInputManager()->setDragDrop(dragDrop); 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) void WindowManager::setCursorVisible(bool visible)
{ {
if (visible == mCursorVisible) if (visible == mCursorVisible)
@ -1347,6 +1362,19 @@ namespace MWGui
mConsole->executeFile (path); 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::InventoryWindow* WindowManager::getInventoryWindow() { return mInventoryWindow; }
MWGui::CountDialog* WindowManager::getCountDialog() { return mCountDialog; } MWGui::CountDialog* WindowManager::getCountDialog() { return mCountDialog; }
MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; } MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; }
@ -1487,6 +1515,35 @@ namespace MWGui
mQuickKeysMenu->activateQuickKey(index); 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 () bool WindowManager::getSubtitlesEnabled ()
{ {
return mSubtitlesEnabled; return mSubtitlesEnabled;
@ -1964,6 +2021,35 @@ namespace MWGui
mConsole->setSelectedObject(object); 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) std::string WindowManager::correctIconPath(const std::string& path)
{ {
return Misc::ResourceHelpers::correctIconPath(path, mResourceSystem->getVFS()); return Misc::ResourceHelpers::correctIconPath(path, mResourceSystem->getVFS());

@ -191,6 +191,29 @@ namespace MWGui
virtual void setConsoleSelectedObject(const MWWorld::Ptr& object); 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. ///< Set value for the given ID.
virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value); virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value);
virtual void setValue (int parSkill, const MWMechanics::SkillValue& 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(int &x, int &y);
virtual void getMousePosition(float &x, float &y); virtual void getMousePosition(float &x, float &y);
virtual void setDragDrop(bool dragDrop); 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 getWorldMouseOver();
virtual bool toggleFogOfWar(); virtual bool toggleFogOfWar();
@ -250,6 +284,16 @@ namespace MWGui
/// update activated quick key state (if action executing was delayed for some reason) /// update activated quick key state (if action executing was delayed for some reason)
virtual void updateActivatedQuickKey (); 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 std::string getSelectedSpell() { return mSelectedSpell; }
virtual void setSelectedSpell(const std::string& spellId, int successChancePercent); virtual void setSelectedSpell(const std::string& spellId, int successChancePercent);
virtual void setSelectedEnchantItem(const MWWorld::Ptr& item); virtual void setSelectedEnchantItem(const MWWorld::Ptr& item);
@ -318,6 +362,16 @@ namespace MWGui
virtual void executeInConsole (const std::string& path); 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 void enableRest() { mRestAllowed = true; }
virtual bool getRestEnabled(); virtual bool getRestEnabled();

@ -1050,6 +1050,28 @@ namespace MWInput
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage2}"); //Nope, MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage2}"); //Nope,
return; 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 MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_Rest); //Open rest GUI
} }

@ -295,6 +295,30 @@ namespace MWMechanics
mSpellsChanged = true; 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() void ActiveSpells::clear()
{ {
mSpells.clear(); mSpells.clear();

@ -94,6 +94,16 @@ namespace MWMechanics
/// Remove all effects with CASTER_LINKED flag that were cast by \a casterActorId /// Remove all effects with CASTER_LINKED flag that were cast by \a casterActorId
void purge (int 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 /// Remove all spells
void clear(); void clear();

@ -87,18 +87,20 @@ bool AiPursue::execute (const MWWorld::Ptr& actor, CharacterController& characte
if (pathTo(actor, dest, duration, pathTolerance) && 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 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 Start of tes3mp addition
Record that the player has not died since the last attempt to arrest them 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()); 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()->diedSinceArrestAttempt = false;
mwmp::Main::get().getLocalPlayer()->closeInventoryWindows();
/* /*
End of tes3mp addition End of tes3mp addition
*/ */
target.getClass().activate(target,actor).get()->execute(actor); //Arrest player when reached
return true; 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(mJumpState == JumpState_InAir)
{ {
if (mAnimation->hasAnimation(jumpAnimName)) mAnimation->disable(mCurrentJump);
{
mAnimation->play(jumpAnimName, Priority_Jump, jumpmask, false,
1.0f, (startAtLoop?"loop start":"start"), "stop", 0.0f, ~0ul);
mCurrentJump = jumpAnimName; mCurrentJump = jumpAnimName;
if (mAnimation->hasAnimation("jump"))
mAnimation->play(mCurrentJump, Priority_Jump, jumpmask, false,
1.0f, (startAtLoop?"loop start":"start"), "stop", 0.0f, ~0ul);
} }
} else
else if (mJumpState == JumpState_Landing)
{
if (mAnimation->hasAnimation(jumpAnimName))
{ {
mAnimation->disable(mCurrentJump);
mCurrentJump.clear();
if (mAnimation->hasAnimation("jump"))
mAnimation->play(jumpAnimName, Priority_Jump, jumpmask, true, mAnimation->play(jumpAnimName, Priority_Jump, jumpmask, true,
1.0f, "loop stop", "stop", 0.0f, 0); 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; mHasMovedInXY = std::abs(vec.x())+std::abs(vec.y()) > 0.0f;
isrunning = isrunning && mHasMovedInXY; isrunning = isrunning && mHasMovedInXY;
// advance athletics // advance athletics
if(mHasMovedInXY && mPtr == getPlayer()) if(mHasMovedInXY && mPtr == getPlayer())
{ {
@ -1987,8 +1980,7 @@ void CharacterController::update(float duration)
} }
else else
{ {
jumpstate = mAnimation->isPlaying(mCurrentJump) ? JumpState_Landing : JumpState_None; jumpstate = JumpState_None;
vec.z() = 0.0f; vec.z() = 0.0f;
inJump = false; 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())) else if(rot.z() != 0.0f && !sneak && !(mPtr == getPlayer() && MWBase::Environment::get().getWorld()->isFirstPerson()))
{ {
if(rot.z() > 0.0f) if(rot.z() > 0.0f)
{
movestate = inwater ? CharState_SwimTurnRight : CharState_TurnRight; movestate = inwater ? CharState_SwimTurnRight : CharState_TurnRight;
mAnimation->disable(mCurrentJump);
}
else if(rot.z() < 0.0f) else if(rot.z() < 0.0f)
{
movestate = inwater ? CharState_SwimTurnLeft : CharState_TurnLeft; movestate = inwater ? CharState_SwimTurnLeft : CharState_TurnLeft;
mAnimation->disable(mCurrentJump);
}
} }
} }

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

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

@ -7,11 +7,14 @@
#include <apps/openmw/mwmechanics/steering.hpp> #include <apps/openmw/mwmechanics/steering.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwgui/windowmanagerimp.hpp"
#include "../mwclass/npc.hpp" #include "../mwclass/npc.hpp"
#include "../mwdialogue/dialoguemanagerimp.hpp"
#include "../mwgui/windowmanagerimp.hpp"
#include "../mwinput/inputmanagerimp.hpp" #include "../mwinput/inputmanagerimp.hpp"
#include "../mwmechanics/actor.hpp" #include "../mwmechanics/actor.hpp"
@ -283,6 +286,21 @@ void DedicatedPlayer::setMarkerState(bool state)
removeMarker(); 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() MWWorld::Ptr DedicatedPlayer::getPtr()
{ {
return ptr; return ptr;

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

@ -1,12 +1,9 @@
//
// Created by koncord on 14.01.16.
//
#include <components/esm/esmwriter.hpp> #include <components/esm/esmwriter.hpp>
#include <components/openmw-mp/Log.hpp> #include <components/openmw-mp/Log.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/journal.hpp" #include "../mwbase/journal.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwclass/creature.hpp" #include "../mwclass/creature.hpp"
#include "../mwclass/npc.hpp" #include "../mwclass/npc.hpp"
@ -18,6 +15,7 @@
#include "../mwinput/inputmanagerimp.hpp" #include "../mwinput/inputmanagerimp.hpp"
#include "../mwmechanics/activespells.hpp"
#include "../mwmechanics/aitravel.hpp" #include "../mwmechanics/aitravel.hpp"
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/mechanicsmanagerimp.hpp" #include "../mwmechanics/mechanicsmanagerimp.hpp"
@ -48,8 +46,11 @@ LocalPlayer::LocalPlayer()
charGenState.endStage = 1; charGenState.endStage = 1;
charGenState.isFinished = false; charGenState.isFinished = false;
consoleAllowed = false;
difficulty = 0; difficulty = 0;
consoleAllowed = false;
bedRestAllowed = true;
wildernessRestAllowed = true;
waitAllowed = true;
ignorePosPacket = false; ignorePosPacket = false;
ignoreJailTeleportation = false; ignoreJailTeleportation = false;
@ -66,6 +67,8 @@ LocalPlayer::LocalPlayer()
isWerewolf = false; isWerewolf = false;
diedSinceArrestAttempt = false; diedSinceArrestAttempt = false;
isReceivingQuickKeys = false;
isPlayingAnimation = false;
} }
LocalPlayer::~LocalPlayer() LocalPlayer::~LocalPlayer()
@ -241,6 +244,7 @@ void LocalPlayer::updateAttributes(bool forceUpdate)
for (int i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i)
{ {
if (ptrNpcStats.getAttribute(i).getBase() != creatureStats.mAttributes[i].mBase || if (ptrNpcStats.getAttribute(i).getBase() != creatureStats.mAttributes[i].mBase ||
ptrNpcStats.getAttribute(i).getModifier() != creatureStats.mAttributes[i].mMod ||
ptrNpcStats.getSkillIncrease(i) != npcStats.mSkillIncrease[i] || ptrNpcStats.getSkillIncrease(i) != npcStats.mSkillIncrease[i] ||
forceUpdate) 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 // 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 || 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 || ptrNpcStats.getSkill(i).getProgress() != npcStats.mSkills[i].mProgress ||
forceUpdate) forceUpdate)
{ {
@ -331,6 +336,16 @@ void LocalPlayer::updatePosition(bool forceUpdate)
bool posIsChanging = (direction.pos[0] != 0 || direction.pos[1] != 0 || bool posIsChanging = (direction.pos[0] != 0 || direction.pos[1] != 0 ||
position.rot[0] != oldRot[0] || position.rot[2] != oldRot[1]); 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) if (forceUpdate || posIsChanging || posWasChanged)
{ {
oldRot[0] = position.rot[0]; oldRot[0] = position.rot[0];
@ -420,6 +435,7 @@ void LocalPlayer::updateEquipment(bool forceUpdate)
equipmentIndexChanges.push_back(slot); equipmentIndexChanges.push_back(slot);
item.refId = it->getCellRef().getRefId(); item.refId = it->getCellRef().getRefId();
item.charge = it->getCellRef().getCharge(); item.charge = it->getCellRef().getCharge();
item.enchantmentCharge = it->getCellRef().getEnchantmentCharge();
if (slot == MWWorld::InventoryStore::Slot_CarriedRight) if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
{ {
@ -438,7 +454,8 @@ void LocalPlayer::updateEquipment(bool forceUpdate)
equipmentIndexChanges.push_back(slot); equipmentIndexChanges.push_back(slot);
item.refId = ""; item.refId = "";
item.count = 0; item.count = 0;
item.charge = 0; item.charge = -1;
item.enchantmentCharge = -1;
} }
} }
@ -467,6 +484,7 @@ void LocalPlayer::updateInventory(bool forceUpdate)
return true; return true;
item.count = iter.getRefData().getCount(); item.count = iter.getRefData().getCount();
item.charge = iter.getCellRef().getCharge(); item.charge = iter.getCellRef().getCharge();
item.enchantmentCharge = iter.getCellRef().getEnchantmentCharge();
return false; return false;
}; };
@ -642,6 +660,9 @@ void LocalPlayer::addItems()
MWWorld::Ptr itemPtr = *ptrStore.add(item.refId, item.count, ptrPlayer); MWWorld::Ptr itemPtr = *ptrStore.add(item.refId, item.count, ptrPlayer);
if (item.charge != -1) if (item.charge != -1)
itemPtr.getCellRef().setCharge(item.charge); itemPtr.getCellRef().setCharge(item.charge);
if (item.enchantmentCharge != -1)
itemPtr.getCellRef().setEnchantmentCharge(item.enchantmentCharge);
} }
catch (std::exception&) 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() void LocalPlayer::setDynamicStats()
{ {
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
@ -759,6 +789,12 @@ void LocalPlayer::setAttributes()
for (int i = 0; i < 8; ++i) 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]); attributeValue.readState(creatureStats.mAttributes[i]);
ptrCreatureStats->setAttribute(i, attributeValue); ptrCreatureStats->setAttribute(i, attributeValue);
} }
@ -774,6 +810,12 @@ void LocalPlayer::setSkills()
for (int i = 0; i < 27; ++i) 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]); skillValue.readState(npcStats.mSkills[i]);
ptrNpcStats->setSkill(i, skillValue); ptrNpcStats->setSkill(i, skillValue);
} }
@ -832,12 +874,8 @@ void LocalPlayer::setCell()
MWWorld::Ptr ptrPlayer = world->getPlayerPtr(); MWWorld::Ptr ptrPlayer = world->getPlayerPtr();
ESM::Position pos; ESM::Position pos;
// To avoid crashes, close any container menus this player may be in // To avoid crashes, close container windows this player may be in
if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_Container)) closeInventoryWindows();
{
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
MWBase::Environment::get().getWindowManager()->setDragDrop(false);
}
world->getPlayer().setTeleported(true); world->getPlayer().setTeleported(true);
@ -940,6 +978,9 @@ void LocalPlayer::setInventory()
MWWorld::Ptr ptrPlayer = getPlayerPtr(); MWWorld::Ptr ptrPlayer = getPlayerPtr();
MWWorld::ContainerStore &ptrStore = ptrPlayer.getClass().getContainerStore(ptrPlayer); MWWorld::ContainerStore &ptrStore = ptrPlayer.getClass().getContainerStore(ptrPlayer);
// Ensure no item is being drag and dropped
MWBase::Environment::get().getWindowManager()->finishDragDrop();
// Clear items in inventory // Clear items in inventory
ptrStore.clear(); ptrStore.clear();
@ -979,6 +1020,57 @@ void LocalPlayer::setSpellbook()
addSpells(); 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() void LocalPlayer::setFactions()
{ {
MWWorld::Ptr ptrPlayer = getPlayerPtr(); MWWorld::Ptr ptrPlayer = getPlayerPtr();
@ -1088,6 +1180,7 @@ void LocalPlayer::sendInventory()
item.count = iter.getRefData().getCount(); item.count = iter.getRefData().getCount();
item.charge = iter.getCellRef().getCharge(); item.charge = iter.getCellRef().getCharge();
item.enchantmentCharge = iter.getCellRef().getEnchantmentCharge();
inventoryChanges.items.push_back(item); 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) void LocalPlayer::sendJournalEntry(const std::string& quest, int index, const MWWorld::Ptr& actor)
{ {
journalChanges.journalItems.clear(); journalChanges.journalItems.clear();
@ -1357,3 +1468,20 @@ void LocalPlayer::storeCurrentContainer(const MWWorld::Ptr &container)
currentContainer.refNumIndex = container.getCellRef().getRefNum().mIndex; currentContainer.refNumIndex = container.getCellRef().getRefNum().mIndex;
currentContainer.mpNum = container.getCellRef().getMpNum(); 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 removeItems();
void removeSpells(); void removeSpells();
void closeInventoryWindows();
void setDynamicStats(); void setDynamicStats();
void setAttributes(); void setAttributes();
void setSkills(); void setSkills();
@ -57,6 +59,7 @@ namespace mwmp
void setEquipment(); void setEquipment();
void setInventory(); void setInventory();
void setSpellbook(); void setSpellbook();
void setQuickKeys();
void setFactions(); void setFactions();
void setKills(); void setKills();
void setBooks(); void setBooks();
@ -71,6 +74,7 @@ namespace mwmp
void sendSpellAddition(const ESM::Spell &spell); void sendSpellAddition(const ESM::Spell &spell);
void sendSpellRemoval(std::string id); void sendSpellRemoval(std::string id);
void sendSpellRemoval(const ESM::Spell &spell); 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 sendJournalEntry(const std::string& quest, int index, const MWWorld::Ptr& actor);
void sendJournalIndex(const std::string& quest, int index); void sendJournalIndex(const std::string& quest, int index);
void sendFactionRank(const std::string& factionId, int rank); void sendFactionRank(const std::string& factionId, int rank);
@ -87,9 +91,13 @@ namespace mwmp
void storeCurrentContainer(const MWWorld::Ptr& container); void storeCurrentContainer(const MWWorld::Ptr& container);
void storeCellState(const ESM::Cell& cell, int stateType); void storeCellState(const ESM::Cell& cell, int stateType);
void playAnimation();
void playSpeech();
MWWorld::Ptr getPlayerPtr();
private: private:
Networking *getNetworking(); Networking *getNetworking();
MWWorld::Ptr getPlayerPtr();
}; };
} }

@ -87,6 +87,9 @@ void WorldEvent::editContainers(MWWorld::CellStore* cellStore)
if (containerItem.charge > -1) if (containerItem.charge > -1)
newPtr.getCellRef().setCharge(containerItem.charge); newPtr.getCellRef().setCharge(containerItem.charge);
if (containerItem.enchantmentCharge > -1)
newPtr.getCellRef().setEnchantmentCharge(containerItem.enchantmentCharge);
containerStore.add(newPtr, containerItem.count, ownerPtr, true); containerStore.add(newPtr, containerItem.count, ownerPtr, true);
} }
else if (action == BaseEvent::REMOVE) 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 (Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), containerItem.refId))
{ {
if (ptr.getCellRef().getCharge() == containerItem.charge && if (ptr.getRefData().getCount() == containerItem.count &&
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 // Is this an actor's container? If so, unequip this item if it was equipped
if (ptrFound.getClass().isActor()) if (ptrFound.getClass().isActor())
@ -145,8 +149,8 @@ void WorldEvent::placeObjects(MWWorld::CellStore* cellStore)
{ {
for (const auto &worldObject : worldObjects) for (const auto &worldObject : worldObjects)
{ {
LOG_APPEND(Log::LOG_VERBOSE, "- cellRef: %s, %i, %i, charge: %i, count: %i", worldObject.refId.c_str(), LOG_APPEND(Log::LOG_VERBOSE, "- cellRef: %s, %i, %i, count: %i, charge: %i, enchantmentCharge: %i", worldObject.refId.c_str(),
worldObject.refNumIndex, worldObject.mpNum, worldObject.charge, worldObject.count); worldObject.refNumIndex, worldObject.mpNum, worldObject.count, worldObject.charge, worldObject.enchantmentCharge);
MWWorld::Ptr ptrFound = cellStore->searchExact(0, worldObject.mpNum); 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::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), worldObject.refId, 1);
MWWorld::Ptr newPtr = ref.getPtr(); MWWorld::Ptr newPtr = ref.getPtr();
if (worldObject.count > 1)
newPtr.getRefData().setCount(worldObject.count);
if (worldObject.charge > -1) if (worldObject.charge > -1)
newPtr.getCellRef().setCharge(worldObject.charge); newPtr.getCellRef().setCharge(worldObject.charge);
if (worldObject.count > 1) if (worldObject.enchantmentCharge > -1)
newPtr.getRefData().setCount(worldObject.count); newPtr.getCellRef().setEnchantmentCharge(worldObject.enchantmentCharge);
newPtr.getCellRef().setGoldValue(worldObject.goldValue); newPtr.getCellRef().setGoldValue(worldObject.goldValue);
newPtr = MWBase::Environment::get().getWorld()->placeObject(newPtr, cellStore, worldObject.position); 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) void WorldEvent::setLocalShorts(MWWorld::CellStore* cellStore)
{ {
for (const auto &worldObject : worldObjects) for (const auto &worldObject : worldObjects)
@ -527,6 +595,7 @@ void WorldEvent::addObjectPlace(const MWWorld::Ptr& ptr)
worldObject.refNumIndex = ptr.getCellRef().getRefNum().mIndex; worldObject.refNumIndex = ptr.getCellRef().getRefNum().mIndex;
worldObject.mpNum = 0; worldObject.mpNum = 0;
worldObject.charge = ptr.getCellRef().getCharge(); 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 // Make sure we send the RefData position instead of the CellRef one, because that's what
// we actually see on this client // we actually see on this client
@ -891,6 +960,7 @@ void WorldEvent::sendContainers(MWWorld::CellStore* cellStore)
containerItem.refId = itemPtr.getCellRef().getRefId(); containerItem.refId = itemPtr.getCellRef().getRefId();
containerItem.count = itemPtr.getRefData().getCount(); containerItem.count = itemPtr.getRefData().getCount();
containerItem.charge = itemPtr.getCellRef().getCharge(); containerItem.charge = itemPtr.getCellRef().getCharge();
containerItem.enchantmentCharge = itemPtr.getCellRef().getEnchantmentCharge();
worldObject.containerItems.push_back(move(containerItem)); worldObject.containerItems.push_back(move(containerItem));
} }

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

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

@ -23,9 +23,10 @@ namespace mwmp
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{ {
if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Console && !player->consoleAllowed) if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Console && !player->consoleAllowed)
{
MWBase::Environment::get().getWindowManager()->popGuiMode(); 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) 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) 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 #ifndef OPENMW_PROCESSORCONSOLECOMMAND_HPP
#define OPENMW_PROCESSORCONSOLECOMMAND_HPP #define OPENMW_PROCESSORCONSOLECOMMAND_HPP
#include "../WorldProcessor.hpp" #include "BaseObjectProcessor.hpp"
namespace mwmp namespace mwmp
{ {
class ProcessorConsoleCommand final: public WorldProcessor class ProcessorConsoleCommand : public BaseObjectProcessor
{ {
public: public:
ProcessorConsoleCommand() ProcessorConsoleCommand()
@ -15,8 +15,9 @@ namespace mwmp
virtual void Do(WorldPacket &packet, WorldEvent &event) virtual void Do(WorldPacket &packet, WorldEvent &event)
{ {
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Received %s", strPacketID.c_str()); BaseObjectProcessor::Do(packet, event);
//event.runConsoleCommand();
event.runConsoleCommands(ptrCellStore);
} }
}; };
} }

@ -1,5 +1,16 @@
#include "guiextensions.hpp" #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/extensions.hpp>
#include <components/compiler/opcodes.hpp> #include <components/compiler/opcodes.hpp>
@ -57,8 +68,21 @@ namespace MWScript
if (bed.isEmpty() || !MWBase::Environment::get().getMechanicsManager()->sleepInBed(MWMechanics::getPlayer(), if (bed.isEmpty() || !MWBase::Environment::get().getMechanicsManager()->sleepInBed(MWMechanics::getPlayer(),
bed)) 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); MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Rest, bed);
} }
/*
End of tes3mp change (minor)
*/
}
}; };
class OpShowDialogue : public Interpreter::Opcode0 class OpShowDialogue : public Interpreter::Opcode0

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

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

@ -12,12 +12,13 @@ namespace mwmp
std::string refId; std::string refId;
int count; int count;
int charge; int charge;
int enchantmentCharge;
int actionCount; int actionCount;
inline bool operator==(const ContainerItem& rhs) 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; unsigned mpNum;
int count; int count;
int charge; int charge;
int enchantmentCharge;
int goldValue; int goldValue;
ESM::Position position; ESM::Position position;
@ -55,6 +57,9 @@ namespace mwmp
std::vector<ContainerItem> containerItems; std::vector<ContainerItem> containerItems;
unsigned int containerItemCount; unsigned int containerItemCount;
RakNet::RakNetGUID guid; // only for events that can also affect players
bool isPlayer;
}; };
class BaseEvent class BaseEvent
@ -84,6 +89,7 @@ namespace mwmp
std::vector<WorldObject> worldObjects; std::vector<WorldObject> worldObjects;
ESM::Cell cell; ESM::Cell cell;
std::string consoleCommand;
unsigned char action; // 0 - Clear and set in entirety, 1 - Add item, 2 - Remove item, 3 - Request items 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; 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 struct CellState
{ {
ESM::Cell cell; ESM::Cell cell;
@ -146,6 +162,11 @@ namespace mwmp
int action; // 0 - Clear and set in entirety, 1 - Add spell, 2 - Remove spell int action; // 0 - Clear and set in entirety, 1 - Add spell, 2 - Remove spell
}; };
struct QuickKeyChanges
{
std::vector<QuickKey> quickKeys;
};
struct CellStateChanges struct CellStateChanges
{ {
std::vector<CellState> cellStates; std::vector<CellState> cellStates;
@ -248,6 +269,7 @@ namespace mwmp
std::vector<int> skillIndexChanges; std::vector<int> skillIndexChanges;
SpellbookChanges spellbookChanges; SpellbookChanges spellbookChanges;
QuickKeyChanges quickKeyChanges;
JournalChanges journalChanges; JournalChanges journalChanges;
FactionChanges factionChanges; FactionChanges factionChanges;
TopicChanges topicChanges; TopicChanges topicChanges;
@ -259,8 +281,17 @@ namespace mwmp
ESM::ActiveSpells activeSpells; ESM::ActiveSpells activeSpells;
CurrentContainer currentContainer; CurrentContainer currentContainer;
bool consoleAllowed; struct
{
int currentWeather, nextWeather;
float updateTime, transitionFactor;
} weather;
int difficulty; int difficulty;
bool consoleAllowed;
bool bedRestAllowed;
bool wildernessRestAllowed;
bool waitAllowed;
bool ignorePosPacket; bool ignorePosPacket;
@ -273,6 +304,9 @@ namespace mwmp
CharGenState charGenState; CharGenState charGenState;
std::string passw; std::string passw;
std::string sound;
Animation animation;
bool isWerewolf; bool isWerewolf;
std::string creatureModel; std::string creatureModel;
bool useCreatureName; bool useCreatureName;
@ -288,12 +322,8 @@ namespace mwmp
ResurrectType resurrectType; ResurrectType resurrectType;
bool diedSinceArrestAttempt; bool diedSinceArrestAttempt;
bool isReceivingQuickKeys;
struct bool isPlayingAnimation;
{
int currentWeather, nextWeather;
float updateTime, transitionFactor;
} weather;
}; };
} }

@ -12,10 +12,11 @@ namespace mwmp
std::string refId; std::string refId;
int count; int count;
int charge; int charge;
int enchantmentCharge;
inline bool operator==(const Item& rhs) 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/PacketPlayerLevel.hpp"
#include "../Packets/Player/PacketPlayerMap.hpp" #include "../Packets/Player/PacketPlayerMap.hpp"
#include "../Packets/Player/PacketPlayerPosition.hpp" #include "../Packets/Player/PacketPlayerPosition.hpp"
#include "../Packets/Player/PacketPlayerQuickKeys.hpp"
#include "../Packets/Player/PacketPlayerRegionAuthority.hpp" #include "../Packets/Player/PacketPlayerRegionAuthority.hpp"
#include "../Packets/Player/PacketPlayerRest.hpp" #include "../Packets/Player/PacketPlayerRest.hpp"
#include "../Packets/Player/PacketPlayerResurrect.hpp" #include "../Packets/Player/PacketPlayerResurrect.hpp"
@ -83,6 +84,7 @@ mwmp::PlayerPacketController::PlayerPacketController(RakNet::RakPeerInterface *p
AddPacket<PacketPlayerLevel>(&packets, peer); AddPacket<PacketPlayerLevel>(&packets, peer);
AddPacket<PacketPlayerMap>(&packets, peer); AddPacket<PacketPlayerMap>(&packets, peer);
AddPacket<PacketPlayerPosition>(&packets, peer); AddPacket<PacketPlayerPosition>(&packets, peer);
AddPacket<PacketPlayerQuickKeys>(&packets, peer);
AddPacket<PacketPlayerRegionAuthority>(&packets, peer); AddPacket<PacketPlayerRegionAuthority>(&packets, peer);
AddPacket<PacketPlayerRest>(&packets, peer); AddPacket<PacketPlayerRest>(&packets, peer);
AddPacket<PacketPlayerResurrect>(&packets, peer); AddPacket<PacketPlayerResurrect>(&packets, peer);

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

@ -16,5 +16,6 @@ void PacketActorEquipment::Actor(BaseActor &actor, bool send)
RW(equipmentItem.refId, send); RW(equipmentItem.refId, send);
RW(equipmentItem.count, send); RW(equipmentItem.count, send);
RW(equipmentItem.charge, 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) void PacketActorSpeech::Actor(BaseActor &actor, bool send)
{ {
RW(actor.response, send);
RW(actor.sound, send); RW(actor.sound, send);
} }

@ -13,6 +13,9 @@ void PacketGameSettings::Packet(RakNet::BitStream *bs, bool send)
{ {
PlayerPacket::Packet(bs, send); PlayerPacket::Packet(bs, send);
RW(player->consoleAllowed, send);
RW(player->difficulty, 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); 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.refId, send, true);
RW(item.count, send); RW(item.count, send);
RW(item.charge, 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); 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) for (auto &&spell : player->spellbookChanges.spells)
{ {
RW(spell.mId, send, true); 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; 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);
}
} }

@ -10,7 +10,7 @@ namespace mwmp
public: public:
explicit PacketConsoleCommand(RakNet::RakPeerInterface *peer); 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.refId, send);
RW(containerItem.count, send); RW(containerItem.count, send);
RW(containerItem.charge, send); RW(containerItem.charge, send);
RW(containerItem.enchantmentCharge, send);
RW(containerItem.actionCount, send); RW(containerItem.actionCount, send);
} }
} }

@ -14,6 +14,7 @@ void PacketObjectPlace::Object(WorldObject &worldObject, bool send)
WorldPacket::Object(worldObject, send); WorldPacket::Object(worldObject, send);
RW(worldObject.count, send); RW(worldObject.count, send);
RW(worldObject.charge, send); RW(worldObject.charge, send);
RW(worldObject.enchantmentCharge, send);
RW(worldObject.goldValue, send); RW(worldObject.goldValue, send);
RW(worldObject.position, 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 0.6.1
----- -----

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

Loading…
Cancel
Save