diff --git a/apps/openmw/mwmp/ActorList.cpp b/apps/openmw/mwmp/ActorList.cpp index 6abfb5b11..46fb862a3 100644 --- a/apps/openmw/mwmp/ActorList.cpp +++ b/apps/openmw/mwmp/ActorList.cpp @@ -32,6 +32,7 @@ void ActorList::reset() animPlayActors.clear(); speechActors.clear(); statsDynamicActors.clear(); + equipmentActors.clear(); attackActors.clear(); cellChangeActors.clear(); guid = mwmp::Main::get().getNetworking()->getLocalPlayer()->guid; @@ -72,6 +73,11 @@ void ActorList::addStatsDynamicActor(LocalActor localActor) statsDynamicActors.push_back(localActor); } +void ActorList::addEquipmentActor(LocalActor localActor) +{ + equipmentActors.push_back(localActor); +} + void ActorList::addAttackActor(LocalActor localActor) { attackActors.push_back(localActor); @@ -132,6 +138,16 @@ void ActorList::sendStatsDynamicActors() } } +void ActorList::sendEquipmentActors() +{ + if (equipmentActors.size() > 0) + { + baseActors = equipmentActors; + Main::get().getNetworking()->getActorPacket(ID_ACTOR_EQUIPMENT)->setActorList(this); + Main::get().getNetworking()->getActorPacket(ID_ACTOR_EQUIPMENT)->Send(); + } +} + void ActorList::sendAttackActors() { if (attackActors.size() > 0) diff --git a/apps/openmw/mwmp/ActorList.hpp b/apps/openmw/mwmp/ActorList.hpp index e99f5733f..dec817dd2 100644 --- a/apps/openmw/mwmp/ActorList.hpp +++ b/apps/openmw/mwmp/ActorList.hpp @@ -26,6 +26,7 @@ namespace mwmp void addAnimPlayActor(LocalActor localActor); void addSpeechActor(LocalActor localActor); void addStatsDynamicActor(LocalActor localActor); + void addEquipmentActor(LocalActor localActor); void addAttackActor(LocalActor localActor); void addCellChangeActor(LocalActor localActor); @@ -34,6 +35,7 @@ namespace mwmp void sendAnimPlayActors(); void sendSpeechActors(); void sendStatsDynamicActors(); + void sendEquipmentActors(); void sendAttackActors(); void sendCellChangeActors(); @@ -49,6 +51,7 @@ namespace mwmp std::vector animPlayActors; std::vector speechActors; std::vector statsDynamicActors; + std::vector equipmentActors; std::vector attackActors; std::vector cellChangeActors; }; diff --git a/apps/openmw/mwmp/Cell.cpp b/apps/openmw/mwmp/Cell.cpp index 5253a541a..01c86bf28 100644 --- a/apps/openmw/mwmp/Cell.cpp +++ b/apps/openmw/mwmp/Cell.cpp @@ -75,6 +75,7 @@ void Cell::updateLocal(bool forceUpdate) actorList->sendAnimPlayActors(); actorList->sendSpeechActors(); actorList->sendStatsDynamicActors(); + actorList->sendEquipmentActors(); actorList->sendAttackActors(); actorList->sendCellChangeActors(); } @@ -196,6 +197,29 @@ void Cell::readStatsDynamic(ActorList& actorList) } } +void Cell::readEquipment(ActorList& actorList) +{ + initializeDedicatedActors(actorList); + + BaseActor baseActor; + + for (unsigned int i = 0; i < actorList.count; i++) + { + baseActor = actorList.baseActors.at(i); + std::string mapIndex = Main::get().getCellController()->generateMapIndex(baseActor); + + if (dedicatedActors.count(mapIndex) > 0) + { + DedicatedActor *actor = dedicatedActors[mapIndex]; + + for (int slot = 0; slot < 19; ++slot) + actor->equipedItems[slot] = baseActor.equipedItems[slot]; + + actor->setEquipment(); + } + } +} + void Cell::readSpeech(ActorList& actorList) { BaseActor baseActor; diff --git a/apps/openmw/mwmp/Cell.hpp b/apps/openmw/mwmp/Cell.hpp index c4bf04976..caccf0ce9 100644 --- a/apps/openmw/mwmp/Cell.hpp +++ b/apps/openmw/mwmp/Cell.hpp @@ -21,6 +21,7 @@ namespace mwmp void readAnimFlags(ActorList& actorList); void readAnimPlay(ActorList& actorList); void readStatsDynamic(ActorList& actorList); + void readEquipment(ActorList& actorList); void readSpeech(ActorList& actorList); void readAttack(ActorList& actorList); void readCellChange(ActorList& actorList); diff --git a/apps/openmw/mwmp/CellController.cpp b/apps/openmw/mwmp/CellController.cpp index 0f5aefe82..8fb5d7942 100644 --- a/apps/openmw/mwmp/CellController.cpp +++ b/apps/openmw/mwmp/CellController.cpp @@ -136,6 +136,19 @@ void CellController::readStatsDynamic(ActorList& actorList) } } +void CellController::readEquipment(ActorList& actorList) +{ + std::string mapIndex = actorList.cell.getDescription(); + + initializeCell(actorList.cell); + + // If this now exists, send it the data + if (cellsInitialized.count(mapIndex) > 0) + { + cellsInitialized[mapIndex]->readEquipment(actorList); + } +} + void CellController::readSpeech(ActorList& actorList) { std::string mapIndex = actorList.cell.getDescription(); diff --git a/apps/openmw/mwmp/CellController.hpp b/apps/openmw/mwmp/CellController.hpp index d743661a3..a8ec70db6 100644 --- a/apps/openmw/mwmp/CellController.hpp +++ b/apps/openmw/mwmp/CellController.hpp @@ -24,6 +24,7 @@ namespace mwmp void readAnimFlags(mwmp::ActorList& actorList); void readAnimPlay(mwmp::ActorList& actorList); void readStatsDynamic(mwmp::ActorList& actorList); + void readEquipment(mwmp::ActorList& actorList); void readSpeech(mwmp::ActorList& actorList); void readAttack(mwmp::ActorList& actorList); void readCellChange(mwmp::ActorList& actorList); diff --git a/apps/openmw/mwmp/DedicatedActor.cpp b/apps/openmw/mwmp/DedicatedActor.cpp index dbb5c6ce1..1a51517e7 100644 --- a/apps/openmw/mwmp/DedicatedActor.cpp +++ b/apps/openmw/mwmp/DedicatedActor.cpp @@ -10,8 +10,10 @@ #include "../mwrender/animation.hpp" +#include "../mwworld/action.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/inventorystore.hpp" #include "../mwworld/worldimp.hpp" #include "DedicatedActor.hpp" @@ -127,6 +129,68 @@ void DedicatedActor::setAnimFlags() ptrCreatureStats->setMovementFlag(CreatureStats::Flag_ForceMoveJump, (movementFlags & CreatureStats::Flag_ForceMoveJump) != 0); } +void DedicatedActor::setStatsDynamic() +{ + // Only set dynamic stats if we have received at least one packet about them + if (!hasStatsDynamicData) return; + + MWMechanics::CreatureStats *ptrCreatureStats = &ptr.getClass().getCreatureStats(ptr); + MWMechanics::DynamicStat value; + + // Resurrect this Actor if it's not supposed to be dead according to its authority + if (creatureStats.mDynamic[0].mCurrent > 0) + ptrCreatureStats->resurrect(); + + for (int i = 0; i < 3; ++i) + { + value.readState(creatureStats.mDynamic[i]); + ptrCreatureStats->setDynamic(i, value); + } +} + +void DedicatedActor::setEquipment() +{ + if (!ptr.getClass().hasInventoryStore(ptr)) + return; + + MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore(ptr); + for (int slot = 0; slot < MWWorld::InventoryStore::Slots; ++slot) + { + MWWorld::ContainerStoreIterator it = invStore.getSlot(slot); + + const string &dedicItem = equipedItems[slot].refId; + std::string item = ""; + bool equal = false; + if (it != invStore.end()) + { + item = it->getCellRef().getRefId(); + if (!Misc::StringUtils::ciEqual(item, dedicItem)) // if other item equiped + { + MWWorld::ContainerStore &store = ptr.getClass().getContainerStore(ptr); + store.remove(item, store.count(item), ptr); + } + else + equal = true; + } + + if (dedicItem.empty() || equal) + continue; + + int count = equipedItems[slot].count; + ptr.getClass().getContainerStore(ptr).add(dedicItem, count, ptr); + + for (MWWorld::ContainerStoreIterator it2 = invStore.begin(); it2 != invStore.end(); ++it2) + { + if (::Misc::StringUtils::ciEqual(it2->getCellRef().getRefId(), dedicItem)) // equip item + { + boost::shared_ptr action = it2->getClass().use(*it2); + action->execute(ptr); + break; + } + } + } +} + void DedicatedActor::playAnimation() { if (!animation.groupname.empty()) @@ -152,25 +216,6 @@ void DedicatedActor::playSound() } } -void DedicatedActor::setStatsDynamic() -{ - // Only set dynamic stats if we have received at least one packet about them - if (!hasStatsDynamicData) return; - - MWMechanics::CreatureStats *ptrCreatureStats = &ptr.getClass().getCreatureStats(ptr); - MWMechanics::DynamicStat value; - - // Resurrect this Actor if it's not supposed to be dead according to its authority - if (creatureStats.mDynamic[0].mCurrent > 0) - ptrCreatureStats->resurrect(); - - for (int i = 0; i < 3; ++i) - { - value.readState(creatureStats.mDynamic[i]); - ptrCreatureStats->setDynamic(i, value); - } -} - MWWorld::Ptr DedicatedActor::getPtr() { return ptr; diff --git a/apps/openmw/mwmp/DedicatedActor.hpp b/apps/openmw/mwmp/DedicatedActor.hpp index dd9b8b23c..dd3fc5374 100644 --- a/apps/openmw/mwmp/DedicatedActor.hpp +++ b/apps/openmw/mwmp/DedicatedActor.hpp @@ -20,9 +20,10 @@ namespace mwmp void setMovementSettings(); void setPosition(); void setAnimFlags(); + void setStatsDynamic(); + void setEquipment(); void playAnimation(); void playSound(); - void setStatsDynamic(); MWWorld::Ptr getPtr(); void setPtr(const MWWorld::Ptr& newPtr); diff --git a/apps/openmw/mwmp/LocalActor.cpp b/apps/openmw/mwmp/LocalActor.cpp index e6ae504af..b2c5e4ca4 100644 --- a/apps/openmw/mwmp/LocalActor.cpp +++ b/apps/openmw/mwmp/LocalActor.cpp @@ -2,11 +2,13 @@ #include "../mwbase/environment.hpp" +#include "../mwmechanics/mechanicsmanagerimp.hpp" #include "../mwmechanics/movement.hpp" #include "../mwrender/animation.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/inventorystore.hpp" #include "../mwworld/worldimp.hpp" #include "LocalActor.hpp" @@ -21,6 +23,7 @@ using namespace std; LocalActor::LocalActor() { posWasChanged = false; + equipmentChanged = false; wasRunning = false; wasSneaking = false; @@ -45,6 +48,7 @@ LocalActor::~LocalActor() void LocalActor::update(bool forceUpdate) { updateStatsDynamic(forceUpdate); + updateEquipment(forceUpdate); if (forceUpdate || !creatureStats.mDead) { @@ -198,6 +202,49 @@ void LocalActor::updateStatsDynamic(bool forceUpdate) } } +void LocalActor::updateEquipment(bool forceUpdate) +{ + if (!ptr.getClass().hasInventoryStore(ptr)) + return; + + if (forceUpdate) + equipmentChanged = true; + + MWWorld::InventoryStore &invStore = ptr.getClass().getInventoryStore(ptr); + for (int slot = 0; slot < MWWorld::InventoryStore::Slots; slot++) + { + MWWorld::ContainerStoreIterator it = invStore.getSlot(slot); + if (it != invStore.end() && !::Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), equipedItems[slot].refId)) + { + equipmentChanged = true; + + equipedItems[slot].refId = it->getCellRef().getRefId(); + equipedItems[slot].charge = it->getCellRef().getCharge(); + if (slot == MWWorld::InventoryStore::Slot_CarriedRight) + { + MWMechanics::WeaponType weaptype; + MWMechanics::getActiveWeapon(ptr.getClass().getCreatureStats(ptr), ptr.getClass().getInventoryStore(ptr), &weaptype); + if (weaptype != MWMechanics::WeapType_Thrown) + equipedItems[slot].count = 1; + } + else + equipedItems[slot].count = invStore.count(it->getCellRef().getRefId()); + } + else if (it == invStore.end() && !equipedItems[slot].refId.empty()) + { + equipmentChanged = true; + equipedItems[slot].refId = ""; + equipedItems[slot].count = 0; + equipedItems[slot].charge = 0; + } + } + + if (equipmentChanged) + { + mwmp::Main::get().getNetworking()->getActorList()->addEquipmentActor(*this); + } +} + void LocalActor::updateAttack() { if (attack.shouldSend) diff --git a/apps/openmw/mwmp/LocalActor.hpp b/apps/openmw/mwmp/LocalActor.hpp index 80e448de4..991a6a028 100644 --- a/apps/openmw/mwmp/LocalActor.hpp +++ b/apps/openmw/mwmp/LocalActor.hpp @@ -22,6 +22,7 @@ namespace mwmp void updateAnimPlay(); void updateSpeech(); void updateStatsDynamic(bool forceUpdate); + void updateEquipment(bool forceUpdate); void updateAttack(); MWWorld::Ptr getPtr(); @@ -31,6 +32,7 @@ namespace mwmp MWWorld::Ptr ptr; bool posWasChanged; + bool equipmentChanged; bool wasRunning; bool wasSneaking; diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index d550b7243..8aa54f331 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -409,10 +409,10 @@ void LocalPlayer::updateEquipment(bool forceUpdate) { MWWorld::Ptr player = getPlayerPtr(); - static bool equipChanged = false; + static bool equipmentChanged = false; if (forceUpdate) - equipChanged = true; + equipmentChanged = true; MWWorld::InventoryStore &invStore = player.getClass().getInventoryStore(player); for (int slot = 0; slot < MWWorld::InventoryStore::Slots; slot++) @@ -420,7 +420,7 @@ void LocalPlayer::updateEquipment(bool forceUpdate) MWWorld::ContainerStoreIterator it = invStore.getSlot(slot); if (it != invStore.end() && !::Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), equipedItems[slot].refId)) { - equipChanged = true; + equipmentChanged = true; equipedItems[slot].refId = it->getCellRef().getRefId(); equipedItems[slot].charge = it->getCellRef().getCharge(); @@ -436,18 +436,18 @@ void LocalPlayer::updateEquipment(bool forceUpdate) } else if (it == invStore.end() && !equipedItems[slot].refId.empty()) { - equipChanged = true; + equipmentChanged = true; equipedItems[slot].refId = ""; equipedItems[slot].count = 0; equipedItems[slot].charge = 0; } } - if (equipChanged) + if (equipmentChanged) { getNetworking()->getPlayerPacket(ID_PLAYER_EQUIPMENT)->setPlayer(this); getNetworking()->getPlayerPacket(ID_PLAYER_EQUIPMENT)->Send(); - equipChanged = false; + equipmentChanged = false; } } diff --git a/apps/openmw/mwmp/processors/actor/ProcessorActorEquipment.hpp b/apps/openmw/mwmp/processors/actor/ProcessorActorEquipment.hpp index 3e6c76daa..10b05d53e 100644 --- a/apps/openmw/mwmp/processors/actor/ProcessorActorEquipment.hpp +++ b/apps/openmw/mwmp/processors/actor/ProcessorActorEquipment.hpp @@ -18,7 +18,7 @@ namespace mwmp virtual void Do(ActorPacket &packet, ActorList &actorList) { - + Main::get().getCellController()->readEquipment(actorList); } }; } diff --git a/components/openmw-mp/Base/BaseActor.hpp b/components/openmw-mp/Base/BaseActor.hpp index 7a76ea28b..c4b55b4e6 100644 --- a/components/openmw-mp/Base/BaseActor.hpp +++ b/components/openmw-mp/Base/BaseActor.hpp @@ -42,6 +42,8 @@ namespace mwmp bool hasPositionData; bool hasStatsDynamicData; + + Item equipedItems[19]; }; class BaseActorList diff --git a/components/openmw-mp/Base/BasePlayer.hpp b/components/openmw-mp/Base/BasePlayer.hpp index 627252c13..51ccb63f9 100644 --- a/components/openmw-mp/Base/BasePlayer.hpp +++ b/components/openmw-mp/Base/BasePlayer.hpp @@ -26,18 +26,6 @@ namespace mwmp bool loot; }; - struct Item - { - std::string refId; - int count; - int charge; - - inline bool operator==(const Item& rhs) - { - return refId == rhs.refId && count == rhs.count && charge == rhs.charge; - } - }; - struct JournalItem { std::string quest; diff --git a/components/openmw-mp/Base/BaseStructs.hpp b/components/openmw-mp/Base/BaseStructs.hpp index 95fcee848..45af6a44e 100644 --- a/components/openmw-mp/Base/BaseStructs.hpp +++ b/components/openmw-mp/Base/BaseStructs.hpp @@ -7,6 +7,18 @@ namespace mwmp { + struct Item + { + std::string refId; + int count; + int charge; + + inline bool operator==(const Item& rhs) + { + return refId == rhs.refId && count == rhs.count && charge == rhs.charge; + } + }; + struct Target { std::string refId; diff --git a/components/openmw-mp/Packets/Actor/PacketActorEquipment.cpp b/components/openmw-mp/Packets/Actor/PacketActorEquipment.cpp index b75e4ebfd..456428404 100644 --- a/components/openmw-mp/Packets/Actor/PacketActorEquipment.cpp +++ b/components/openmw-mp/Packets/Actor/PacketActorEquipment.cpp @@ -38,6 +38,13 @@ void PacketActorEquipment::Packet(RakNet::BitStream *bs, bool send) RW(actor.refNumIndex, send); RW(actor.mpNum, send); + for (int i = 0; i < 19; i++) + { + RW(actor.equipedItems[i].refId, send); + RW(actor.equipedItems[i].count, send); + RW(actor.equipedItems[i].charge, send); + } + if (!send) { actorList->baseActors.push_back(actor);