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

This commit is contained in:
David Cernat 2018-01-01 12:04:25 +02:00
commit 09958681cd
74 changed files with 1389 additions and 218 deletions

View file

@ -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})

View file

@ -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);
}

View file

@ -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();

View file

@ -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)

View file

@ -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;
}

View file

@ -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;
};

View file

@ -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()

View file

@ -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:

View file

@ -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)

View file

@ -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);
}; };

View file

@ -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;

View file

@ -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;

View file

@ -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,

View file

@ -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)

View file

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

View file

@ -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());

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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
*/
}; };
} }

View file

@ -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;

View file

@ -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
*/
} }

View file

@ -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
*/
}; };
} }

View file

@ -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());

View file

@ -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;

View file

@ -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>

View file

@ -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,7 +118,35 @@ 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)
{ {
@ -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)

View file

@ -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;

View file

@ -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");

View file

@ -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);

View file

@ -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());

View file

@ -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();

View file

@ -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
} }

View file

@ -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();

View file

@ -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();

View file

@ -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;
} }

View file

@ -390,29 +390,21 @@ void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState
} }
} }
if (!mCurrentJump.empty()) if(mJumpState == JumpState_InAir)
{
mAnimation->disable(mCurrentJump);
mCurrentJump = jumpAnimName;
if (mAnimation->hasAnimation("jump"))
mAnimation->play(mCurrentJump, Priority_Jump, jumpmask, false,
1.0f, (startAtLoop?"loop start":"start"), "stop", 0.0f, ~0ul);
}
else
{ {
mAnimation->disable(mCurrentJump); mAnimation->disable(mCurrentJump);
mCurrentJump.clear(); mCurrentJump.clear();
} if (mAnimation->hasAnimation("jump"))
if(mJumpState == JumpState_InAir)
{
if (mAnimation->hasAnimation(jumpAnimName))
{
mAnimation->play(jumpAnimName, Priority_Jump, jumpmask, false,
1.0f, (startAtLoop?"loop start":"start"), "stop", 0.0f, ~0ul);
mCurrentJump = jumpAnimName;
}
}
else if (mJumpState == JumpState_Landing)
{
if (mAnimation->hasAnimation(jumpAnimName))
{
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);
}
} }
} }

View file

@ -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;
} }
} }

View file

@ -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();
} }

View file

@ -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;

View file

@ -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();

View file

@ -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);
}

View file

@ -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();
}; };
} }

View file

@ -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));
} }

View file

@ -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);

View file

@ -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());

View file

@ -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();
} }
} }
} }

View file

@ -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();
} }
}; };
} }

View file

@ -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

View file

@ -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();
} }
}; };
} }

View file

@ -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);
} }
}; };
} }

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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;
}; };
} }

View file

@ -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;
} }
}; };

View file

@ -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);

View file

@ -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,

View file

@ -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);
} }
} }

View file

@ -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);
} }

View file

@ -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);
} }

View file

@ -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);
} }

View file

@ -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);
} }
} }

View file

@ -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);
}
}

View file

@ -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

View file

@ -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);
} }

View file

@ -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);
} }
} }
}
}

View file

@ -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);
}
} }

View file

@ -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;
}; };
} }

View file

@ -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);
} }
} }

View file

@ -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);
} }

View file

@ -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
----- -----

View file

@ -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