Skip to content

Commit 6d0700c

Browse files
authored
AHuman.cpp - preserve inventory order WITHOUT CRASHING
odksjhgvsdhgkjsdhghdsafoieh
1 parent b5a1b76 commit 6d0700c

File tree

1 file changed

+34
-8
lines changed

1 file changed

+34
-8
lines changed

Source/Entities/AHuman.cpp

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -648,14 +648,18 @@ bool AHuman::EquipFirearm(bool doEquip) {
648648
// Found proper device to equip, so make the switch!
649649
if (pWeapon && pWeapon->IsWeapon()) {
650650
if (doEquip) {
651+
// The next code may cause reallocation, so we can't just use the same pointer.
652+
// Store how far into the inventory the device is, memory wise.
653+
size_t device_offset = itr - m_Inventory.begin();
654+
651655
// Put back into the inventory what we had in our hands, if anything
652656
if (HeldDevice* heldDevice = m_pFGArm->GetHeldDevice()) {
653657
heldDevice->Deactivate();
654658
AddToInventoryBack(m_pFGArm->RemoveAttachable(heldDevice));
655659
}
656660

657661
// We want to preserve inventory order, so rotate to the device in question.
658-
std::rotate(m_Inventory.begin(), itr, m_Inventory.end());
662+
std::rotate(m_Inventory.begin(), m_Inventory.begin() + device_offset, m_Inventory.end());
659663

660664
// Erase the inventory entry containing the device we now have switched to
661665
*m_Inventory.begin() = 0;
@@ -697,6 +701,10 @@ bool AHuman::EquipDeviceInGroup(std::string group, bool doEquip) {
697701
// Found proper device to equip, so make the switch!
698702
if (pDevice && pDevice->IsInGroup(group)) {
699703
if (doEquip) {
704+
// The next code may cause reallocation, so we can't just use the same pointer.
705+
// Store how far into the inventory the device is, memory wise.
706+
size_t device_offset = itr - m_Inventory.begin();
707+
700708
// Put back into the inventory what we had in our hands, if anything
701709
if (HeldDevice* heldDevice = m_pFGArm->GetHeldDevice()) {
702710
heldDevice->Deactivate();
@@ -713,7 +721,7 @@ bool AHuman::EquipDeviceInGroup(std::string group, bool doEquip) {
713721
}
714722

715723
// We want to preserve inventory order, so rotate it to the device in question.
716-
std::rotate(m_Inventory.begin(), itr, m_Inventory.end());
724+
std::rotate(m_Inventory.begin(), m_Inventory.begin() + device_offset, m_Inventory.end());
717725

718726
// Erase the inventory entry containing the device we now have switched to
719727
*m_Inventory.begin() = 0;
@@ -755,14 +763,18 @@ bool AHuman::EquipLoadedFirearmInGroup(std::string group, std::string excludeGro
755763
// Found proper device to equip, so make the switch!
756764
if (pFirearm && !pFirearm->NeedsReloading() && pFirearm->IsInGroup(group) && !pFirearm->IsInGroup(excludeGroup)) {
757765
if (doEquip) {
766+
// The next code may cause reallocation, so we can't just use the same pointer.
767+
// Store how far into the inventory the device is, memory wise.
768+
size_t device_offset = itr - m_Inventory.begin();
769+
758770
// Put back into the inventory what we had in our hands, if anything
759771
if (HeldDevice* heldDevice = m_pFGArm->GetHeldDevice()) {
760772
m_pFGArm->GetHeldDevice()->Deactivate();
761773
AddToInventoryBack(m_pFGArm->RemoveAttachable(heldDevice));
762774
}
763775

764776
// We want to preserve inventory order, so rotate it to the device in question.
765-
std::rotate(m_Inventory.begin(), itr, m_Inventory.end());
777+
std::rotate(m_Inventory.begin(), m_Inventory.begin() + device_offset, m_Inventory.end());
766778
m_Inventory.pop_front();
767779

768780
// Erase the inventory entry containing the device we now have switched to
@@ -806,16 +818,20 @@ bool AHuman::EquipNamedDevice(const std::string& moduleName, const std::string&
806818
// Found proper device to equip, so make the switch!
807819
if (pDevice && (moduleName.empty() || pDevice->GetModuleName() == moduleName) && pDevice->GetPresetName() == presetName) {
808820
if (doEquip) {
821+
// The next code may cause reallocation, so we can't just use the same pointer.
822+
// Store how far into the inventory the device is, memory wise.
823+
size_t device_offset = itr - m_Inventory.begin();
824+
809825
// Put back into the inventory what we had in our hands, if anything
810826
if (HeldDevice* heldDevice = m_pFGArm->GetHeldDevice()) {
811827
heldDevice->Deactivate();
812828
AddToInventoryBack(m_pFGArm->RemoveAttachable(heldDevice));
813829
}
814830

815831
// We want to preserve inventory order, so rotate to the device in question.
816-
std::rotate(m_Inventory.begin(), itr, m_Inventory.end());
832+
std::rotate(m_Inventory.begin(), m_Inventory.begin() + device_offset, m_Inventory.end());
817833

818-
// Erase the inventory entry containing the device we now have switched to
834+
// Erase the inventory entry containing the device.
819835
*m_Inventory.begin() = 0;
820836
m_Inventory.pop_front();
821837

@@ -857,6 +873,9 @@ bool AHuman::EquipThrowable(bool doEquip) {
857873
if (pThrown) // && pThrown->IsWeapon())
858874
{
859875
if (doEquip) {
876+
// The next code may cause reallocation, so we can't just use the same pointer.
877+
// Store how far into the inventory the device is, memory wise.
878+
size_t device_offset = itr - m_Inventory.begin();
860879

861880
// Put back into the inventory what we had in our hands, if anything
862881
if (HeldDevice* heldDevice = m_pFGArm->GetHeldDevice()) {
@@ -865,7 +884,7 @@ bool AHuman::EquipThrowable(bool doEquip) {
865884
}
866885

867886
// We want to preserve inventory order, so rotate it to the device in question.
868-
std::rotate(m_Inventory.begin(), itr, m_Inventory.end());
887+
std::rotate(m_Inventory.begin(), m_Inventory.begin() + device_offset, m_Inventory.end());
869888

870889
// Erase the inventory entry containing the device we now have switched to
871890
*m_Inventory.begin() = 0;
@@ -985,6 +1004,9 @@ bool AHuman::EquipShield() {
9851004
HeldDevice* pShield = dynamic_cast<HeldDevice*>(*itr);
9861005
// Found proper device to equip, so make the switch!
9871006
if (pShield && pShield->IsShield()) {
1007+
// The next code may cause reallocation, so we can't just use the same pointer.
1008+
// Store how far into the inventory the device is, memory wise.
1009+
size_t device_offset = itr - m_Inventory.begin();
9881010

9891011
// Put back into the inventory what we had in our hands, if anything
9901012
if (HeldDevice* heldDevice = m_pFGArm->GetHeldDevice()) {
@@ -993,7 +1015,7 @@ bool AHuman::EquipShield() {
9931015
}
9941016

9951017
// We want to preserve inventory order, so rotate it to the device in question.
996-
std::rotate(m_Inventory.begin(), itr, m_Inventory.end());
1018+
std::rotate(m_Inventory.begin(), m_Inventory.begin() + device_offset, m_Inventory.end());
9971019

9981020
// Erase the inventory entry containing the device we now have switched to
9991021
*m_Inventory.begin() = 0;
@@ -1048,6 +1070,10 @@ bool AHuman::EquipShieldInBGArm(bool depositToFront) {
10481070
HeldDevice* pShield = dynamic_cast<HeldDevice*>(*itr);
10491071
// Found proper device to equip, so make the switch!
10501072
if (pShield && (pShield->IsShield() || pShield->IsDualWieldable())) {
1073+
// The next code may cause reallocation, so we can't just use the same pointer.
1074+
// Store how far into the inventory the device is, memory wise.
1075+
size_t device_offset = itr - m_Inventory.begin();
1076+
10511077
// Put back into the inventory what we had in our hands, if anything
10521078
if (HeldDevice* heldDevice = m_pBGArm->GetHeldDevice()) {
10531079
heldDevice->Deactivate();
@@ -1059,7 +1085,7 @@ bool AHuman::EquipShieldInBGArm(bool depositToFront) {
10591085
}
10601086

10611087
// We want to preserve inventory order, so rotate it to the device in question.
1062-
std::rotate(m_Inventory.begin(), itr, m_Inventory.end());
1088+
std::rotate(m_Inventory.begin(), m_Inventory.begin() + device_offset, m_Inventory.end());
10631089

10641090
// Erase the inventory entry containing the device we now have switched to
10651091
*m_Inventory.begin() = 0;

0 commit comments

Comments
 (0)