Skip to content

Commit

Permalink
feat(skymp5-server): prevent blocking marksman attacks (skyrim-multip…
Browse files Browse the repository at this point in the history
  • Loading branch information
Pospelove authored Nov 15, 2023
1 parent 13c9fef commit 53d05cc
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 3 deletions.
1 change: 1 addition & 0 deletions libespm/include/libespm/ARMO.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class ARMO final : public RecordHeader
uint32_t baseValue = 0;
float weight = 0;
uint32_t enchantmentFormId = 0;
uint32_t equipSlotId = 0; // only for shields
};

Data GetData(CompressedFieldsCache& compressedFieldsCache) const;
Expand Down
2 changes: 2 additions & 0 deletions libespm/src/ARMO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ ARMO::Data ARMO::GetData(CompressedFieldsCache& compressedFieldsCache) const
} else if (!std::memcmp(type, "DNAM", 4)) {
hasDNAM = true;
result.baseRatingX100 = *reinterpret_cast<const uint32_t*>(data);
} else if (!std::memcmp(type, "ETYP", 4)) {
result.equipSlotId = *reinterpret_cast<const uint32_t*>(data);
}
},
compressedFieldsCache);
Expand Down
49 changes: 46 additions & 3 deletions skymp5-server/cpp/server_guest_lib/ActionListener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -856,9 +856,52 @@ void ActionListener::OnHit(const RawMessageData& rawMsgData_,

float healthPercentage = currentActorValues.healthPercentage;

hitData.isHitBlocked = hitData.isHitBlocked ||
(targetActor.IsBlockActive() ? ShouldBeBlocked(*aggressor, targetActor)
: false);
if (targetActor.IsBlockActive()) {
if (ShouldBeBlocked(*aggressor, targetActor)) {
bool isRemoteBowAttack = false;

auto sourceLookupResult =
targetActor.GetParent()->GetEspm().GetBrowser().LookupById(
hitData.source);
if (sourceLookupResult.rec &&
sourceLookupResult.rec->GetType() == espm::WEAP::kType) {
auto weapData =
espm::GetData<espm::WEAP>(hitData.source, targetActor.GetParent());
if (weapData.weapDNAM) {
if (weapData.weapDNAM->animType == espm::WEAP::AnimType::Bow ||
weapData.weapDNAM->animType == espm::WEAP::AnimType::Crossbow) {
if (!hitData.isBashAttack) {
isRemoteBowAttack = true;
}
}
}
}

bool isBlockingByShield = false;

auto targetActorEquipmentEntries =
targetActor.GetEquipment().inv.entries;
for (auto& entry : targetActorEquipmentEntries) {
if (entry.extra.worn != Inventory::Worn::None) {
auto res =
targetActor.GetParent()->GetEspm().GetBrowser().LookupById(
entry.baseId);
if (res.rec && res.rec->GetType() == espm::ARMO::kType) {
auto data =
espm::GetData<espm::ARMO>(entry.baseId, targetActor.GetParent());
bool isShield = data.equipSlotId > 0;
if (isShield) {
isBlockingByShield = isShield;
}
}
}
}

if (!isRemoteBowAttack || isBlockingByShield) {
hitData.isHitBlocked = true;
}
}
}

float damage = partOne.CalculateDamage(*aggressor, targetActor, hitData);
damage = damage < 0.f ? 0.f : damage;
Expand Down

0 comments on commit 53d05cc

Please sign in to comment.