[Client] Equip items silently for newly met dedicated players/actors

This commit is contained in:
David Cernat 2020-05-25 21:50:19 +03:00
parent ea57aaef34
commit c99e20e3b4
4 changed files with 44 additions and 22 deletions

View File

@ -42,6 +42,7 @@ DedicatedActor::DedicatedActor()
hasPositionData = false; hasPositionData = false;
hasStatsDynamicData = false; hasStatsDynamicData = false;
hasReceivedInitialEquipment = false;
hasChangedCell = true; hasChangedCell = true;
attack.pressed = false; attack.pressed = false;
@ -195,14 +196,16 @@ void DedicatedActor::setEquipment()
if (packetRefId.empty() || equal) if (packetRefId.empty() || equal)
continue; continue;
if (hasItem(packetRefId, packetCharge)) if (!hasItem(packetRefId, packetCharge))
equipItem(packetRefId, packetCharge);
else
{ {
ptr.getClass().getContainerStore(ptr).add(packetRefId, count, ptr); ptr.getClass().getContainerStore(ptr).add(packetRefId, count, ptr);
equipItem(packetRefId, packetCharge);
} }
// Equip items silently if this is the first time equipment is being set for this character
equipItem(packetRefId, packetCharge, !hasReceivedInitialEquipment);
} }
hasReceivedInitialEquipment = true;
} }
void DedicatedActor::setAi() void DedicatedActor::setAi()
@ -344,14 +347,14 @@ bool DedicatedActor::hasItem(std::string itemId, int charge)
return false; return false;
} }
void DedicatedActor::equipItem(std::string itemId, int charge) void DedicatedActor::equipItem(std::string itemId, int charge, bool noSound)
{ {
for (const auto &itemPtr : ptr.getClass().getInventoryStore(ptr)) for (const auto &itemPtr : ptr.getClass().getInventoryStore(ptr))
{ {
if (::Misc::StringUtils::ciEqual(itemPtr.getCellRef().getRefId(), itemId) && itemPtr.getCellRef().getCharge() == charge) if (::Misc::StringUtils::ciEqual(itemPtr.getCellRef().getRefId(), itemId) && itemPtr.getCellRef().getCharge() == charge)
{ {
std::shared_ptr<MWWorld::Action> action = itemPtr.getClass().use(itemPtr); std::shared_ptr<MWWorld::Action> action = itemPtr.getClass().use(itemPtr);
action->execute(ptr); action->execute(ptr, noSound);
break; break;
} }
} }

View File

@ -27,7 +27,7 @@ namespace mwmp
void playSound(); void playSound();
bool hasItem(std::string itemId, int charge); bool hasItem(std::string itemId, int charge);
void equipItem(std::string itemId, int charge); void equipItem(std::string itemId, int charge, bool noSound = false);
MWWorld::Ptr getPtr(); MWWorld::Ptr getPtr();
void setPtr(const MWWorld::Ptr& newPtr); void setPtr(const MWWorld::Ptr& newPtr);
@ -35,6 +35,7 @@ namespace mwmp
private: private:
MWWorld::Ptr ptr; MWWorld::Ptr ptr;
bool hasReceivedInitialEquipment;
bool hasChangedCell; bool hasChangedCell;
}; };
} }

View File

@ -63,6 +63,7 @@ DedicatedPlayer::DedicatedPlayer(RakNet::RakNetGUID guid) : BasePlayer(guid)
npc.mId = ""; npc.mId = "";
previousRace = npc.mRace; previousRace = npc.mRace;
hasReceivedInitialEquipment = false;
hasFinishedInitialTeleportation = false; hasFinishedInitialTeleportation = false;
} }
@ -306,12 +307,14 @@ void DedicatedPlayer::setEquipment()
// Go no further if the player is disguised as a creature // Go no further if the player is disguised as a creature
if (!ptr.getClass().hasInventoryStore(ptr)) return; if (!ptr.getClass().hasInventoryStore(ptr)) return;
bool equippedSomething = false;
MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore(ptr); MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore(ptr);
for (int slot = 0; slot < MWWorld::InventoryStore::Slots; ++slot) for (int slot = 0; slot < MWWorld::InventoryStore::Slots; ++slot)
{ {
MWWorld::ContainerStoreIterator it = invStore.getSlot(slot); MWWorld::ContainerStoreIterator it = invStore.getSlot(slot);
const string &packetItemId = equipmentItems[slot].refId; const string &packetRefId = equipmentItems[slot].refId;
std::string ptrItemId = ""; std::string ptrItemId = "";
bool equal = false; bool equal = false;
@ -319,7 +322,7 @@ void DedicatedPlayer::setEquipment()
{ {
ptrItemId = it->getCellRef().getRefId(); ptrItemId = it->getCellRef().getRefId();
if (!Misc::StringUtils::ciEqual(ptrItemId, packetItemId)) // if other item is now equipped if (!Misc::StringUtils::ciEqual(ptrItemId, packetRefId)) // if other item is now equipped
{ {
MWWorld::ContainerStore &store = ptr.getClass().getContainerStore(ptr); MWWorld::ContainerStore &store = ptr.getClass().getContainerStore(ptr);
@ -327,7 +330,7 @@ void DedicatedPlayer::setEquipment()
// have just run out but still need to be kept briefly so they can be used in attacks about to be released // have just run out but still need to be kept briefly so they can be used in attacks about to be released
bool shouldRemove = true; bool shouldRemove = true;
if (attack.type == mwmp::Attack::RANGED && packetItemId.empty() && !attack.pressed) if (attack.type == mwmp::Attack::RANGED && packetRefId.empty() && !attack.pressed)
{ {
if (slot == MWWorld::InventoryStore::Slot_CarriedRight && Misc::StringUtils::ciEqual(ptrItemId, attack.rangedWeaponId)) if (slot == MWWorld::InventoryStore::Slot_CarriedRight && Misc::StringUtils::ciEqual(ptrItemId, attack.rangedWeaponId))
shouldRemove = false; shouldRemove = false;
@ -336,28 +339,27 @@ void DedicatedPlayer::setEquipment()
} }
if (shouldRemove) if (shouldRemove)
{
store.remove(ptrItemId, store.count(ptrItemId), ptr); store.remove(ptrItemId, store.count(ptrItemId), ptr);
}
} }
else else
equal = true; equal = true;
} }
if (packetItemId.empty() || equal) if (packetRefId.empty() || equal)
continue; continue;
const int count = equipmentItems[slot].count; const int count = equipmentItems[slot].count;
ptr.getClass().getContainerStore(ptr).add(packetItemId, count, ptr); ptr.getClass().getContainerStore(ptr).add(packetRefId, count, ptr);
// Equip items silently if this is the first time equipment is being set for this character
for (const auto &itemPtr : invStore) equipItem(packetRefId, !hasReceivedInitialEquipment);
{ equippedSomething = true;
if (::Misc::StringUtils::ciEqual(itemPtr.getCellRef().getRefId(), packetItemId)) // equip item
{
std::shared_ptr<MWWorld::Action> action = itemPtr.getClass().use(itemPtr);
action->execute(ptr);
break;
}
}
} }
// Only track the initial equipment as received if at least one item has been equipped
if (equippedSomething)
hasReceivedInitialEquipment = true;
} }
void DedicatedPlayer::setCell() void DedicatedPlayer::setCell()
@ -469,6 +471,19 @@ void DedicatedPlayer::playSpeech()
winMgr->messageBox(MWBase::Environment::get().getDialogueManager()->getVoiceCaption(sound), MWGui::ShowInDialogueMode_Never); winMgr->messageBox(MWBase::Environment::get().getDialogueManager()->getVoiceCaption(sound), MWGui::ShowInDialogueMode_Never);
} }
void DedicatedPlayer::equipItem(std::string itemId, bool noSound)
{
for (const auto& itemPtr : ptr.getClass().getInventoryStore(ptr))
{
if (::Misc::StringUtils::ciEqual(itemPtr.getCellRef().getRefId(), itemId))
{
std::shared_ptr<MWWorld::Action> action = itemPtr.getClass().use(itemPtr);
action->execute(ptr, noSound);
break;
}
}
}
void DedicatedPlayer::createReference(const std::string& recId) void DedicatedPlayer::createReference(const std::string& recId)
{ {
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();

View File

@ -48,6 +48,8 @@ namespace mwmp
void playAnimation(); void playAnimation();
void playSpeech(); void playSpeech();
void equipItem(std::string itemId, bool noSound = false);
void createReference(const std::string& recId); void createReference(const std::string& recId);
void deleteReference(); void deleteReference();
@ -75,6 +77,7 @@ namespace mwmp
std::string creatureRecordId; std::string creatureRecordId;
bool hasReceivedInitialEquipment;
bool hasFinishedInitialTeleportation; bool hasFinishedInitialTeleportation;
bool isLevitationPurged; bool isLevitationPurged;
}; };