@@ -648,16 +648,23 @@ bool AHuman::EquipFirearm(bool doEquip) {
648648 // Found proper device to equip, so make the switch!
649649 if (pWeapon && pWeapon->IsWeapon ()) {
650650 if (doEquip) {
651- // Erase the inventory entry containing the device we now have switched to
652- *itr = 0 ;
653- m_Inventory.erase (itr );
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 ( );
654654
655655 // Put back into the inventory what we had in our hands, if anything
656656 if (HeldDevice* heldDevice = m_pFGArm->GetHeldDevice ()) {
657657 heldDevice->Deactivate ();
658658 AddToInventoryBack (m_pFGArm->RemoveAttachable (heldDevice));
659659 }
660660
661+ // We want to preserve inventory order, so rotate to the device in question.
662+ std::rotate (m_Inventory.begin (), m_Inventory.begin () + device_offset, m_Inventory.end ());
663+
664+ // Erase the inventory entry containing the device we now have switched to
665+ *m_Inventory.begin () = 0 ;
666+ m_Inventory.pop_front ();
667+
661668 // Now put the device we were looking for and found into the hand
662669 m_pFGArm->SetHeldDevice (pWeapon);
663670 // Move the hand to a poisition so it looks like the new device was drawn from inventory
@@ -694,9 +701,9 @@ bool AHuman::EquipDeviceInGroup(std::string group, bool doEquip) {
694701 // Found proper device to equip, so make the switch!
695702 if (pDevice && pDevice->IsInGroup (group)) {
696703 if (doEquip) {
697- // Erase the inventory entry containing the device we now have switched to
698- *itr = 0 ;
699- m_Inventory.erase (itr );
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 ( );
700707
701708 // Put back into the inventory what we had in our hands, if anything
702709 if (HeldDevice* heldDevice = m_pFGArm->GetHeldDevice ()) {
@@ -713,6 +720,13 @@ bool AHuman::EquipDeviceInGroup(std::string group, bool doEquip) {
713720 }
714721 }
715722
723+ // We want to preserve inventory order, so rotate it to the device in question.
724+ std::rotate (m_Inventory.begin (), m_Inventory.begin () + device_offset, m_Inventory.end ());
725+
726+ // Erase the inventory entry containing the device we now have switched to
727+ *m_Inventory.begin () = 0 ;
728+ m_Inventory.pop_front ();
729+
716730 // Now put the device we were looking for and found into the hand
717731 m_pFGArm->SetHeldDevice (pDevice);
718732 // Move the hand to a poisition so it looks like the new device was drawn from inventory
@@ -749,16 +763,24 @@ bool AHuman::EquipLoadedFirearmInGroup(std::string group, std::string excludeGro
749763 // Found proper device to equip, so make the switch!
750764 if (pFirearm && !pFirearm->NeedsReloading () && pFirearm->IsInGroup (group) && !pFirearm->IsInGroup (excludeGroup)) {
751765 if (doEquip) {
752- // Erase the inventory entry containing the device we now have switched to
753- *itr = 0 ;
754- m_Inventory.erase (itr );
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 ( );
755769
756770 // Put back into the inventory what we had in our hands, if anything
757771 if (HeldDevice* heldDevice = m_pFGArm->GetHeldDevice ()) {
758772 m_pFGArm->GetHeldDevice ()->Deactivate ();
759773 AddToInventoryBack (m_pFGArm->RemoveAttachable (heldDevice));
760774 }
761775
776+ // We want to preserve inventory order, so rotate it to the device in question.
777+ std::rotate (m_Inventory.begin (), m_Inventory.begin () + device_offset, m_Inventory.end ());
778+ m_Inventory.pop_front ();
779+
780+ // Erase the inventory entry containing the device we now have switched to
781+ *m_Inventory.begin () = 0 ;
782+ m_Inventory.pop_front ();
783+
762784 // Now put the device we were looking for and found into the hand
763785 m_pFGArm->SetHeldDevice (pFirearm);
764786 // Move the hand to a poisition so it looks like the new device was drawn from inventory
@@ -796,16 +818,23 @@ bool AHuman::EquipNamedDevice(const std::string& moduleName, const std::string&
796818 // Found proper device to equip, so make the switch!
797819 if (pDevice && (moduleName.empty () || pDevice->GetModuleName () == moduleName) && pDevice->GetPresetName () == presetName) {
798820 if (doEquip) {
799- // Erase the inventory entry containing the device we now have switched to
800- *itr = 0 ;
801- m_Inventory.erase (itr );
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 ( );
802824
803825 // Put back into the inventory what we had in our hands, if anything
804826 if (HeldDevice* heldDevice = m_pFGArm->GetHeldDevice ()) {
805827 heldDevice->Deactivate ();
806828 AddToInventoryBack (m_pFGArm->RemoveAttachable (heldDevice));
807829 }
808830
831+ // We want to preserve inventory order, so rotate to the device in question.
832+ std::rotate (m_Inventory.begin (), m_Inventory.begin () + device_offset, m_Inventory.end ());
833+
834+ // Erase the inventory entry containing the device.
835+ *m_Inventory.begin () = 0 ;
836+ m_Inventory.pop_front ();
837+
809838 // Now put the device we were looking for and found into the hand
810839 m_pFGArm->SetHeldDevice (pDevice);
811840 // Move the hand to a poisition so it looks like the new device was drawn from inventory
@@ -844,16 +873,23 @@ bool AHuman::EquipThrowable(bool doEquip) {
844873 if (pThrown) // && pThrown->IsWeapon())
845874 {
846875 if (doEquip) {
847- // Erase the inventory entry containing the device we now have switched to
848- *itr = 0 ;
849- m_Inventory.erase (itr );
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 ( );
850879
851880 // Put back into the inventory what we had in our hands, if anything
852881 if (HeldDevice* heldDevice = m_pFGArm->GetHeldDevice ()) {
853882 heldDevice->Deactivate ();
854883 AddToInventoryBack (m_pFGArm->RemoveAttachable (heldDevice));
855884 }
856885
886+ // We want to preserve inventory order, so rotate it to the device in question.
887+ std::rotate (m_Inventory.begin (), m_Inventory.begin () + device_offset, m_Inventory.end ());
888+
889+ // Erase the inventory entry containing the device we now have switched to
890+ *m_Inventory.begin () = 0 ;
891+ m_Inventory.pop_front ();
892+
857893 // Now put the device we were looking for and found into the hand
858894 m_pFGArm->SetHeldDevice (pThrown);
859895 // Move the hand to a poisition so it looks like the new device was drawn from inventory
@@ -968,16 +1004,23 @@ bool AHuman::EquipShield() {
9681004 HeldDevice* pShield = dynamic_cast <HeldDevice*>(*itr);
9691005 // Found proper device to equip, so make the switch!
9701006 if (pShield && pShield->IsShield ()) {
971- // Erase the inventory entry containing the device we now have switched to
972- *itr = 0 ;
973- m_Inventory.erase (itr );
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 ( );
9741010
9751011 // Put back into the inventory what we had in our hands, if anything
9761012 if (HeldDevice* heldDevice = m_pFGArm->GetHeldDevice ()) {
9771013 heldDevice->Deactivate ();
9781014 AddToInventoryBack (m_pFGArm->RemoveAttachable (heldDevice));
9791015 }
9801016
1017+ // We want to preserve inventory order, so rotate it to the device in question.
1018+ std::rotate (m_Inventory.begin (), m_Inventory.begin () + device_offset, m_Inventory.end ());
1019+
1020+ // Erase the inventory entry containing the device we now have switched to
1021+ *m_Inventory.begin () = 0 ;
1022+ m_Inventory.pop_front ();
1023+
9811024 // Now put the device we were looking for and found into the hand
9821025 m_pFGArm->SetHeldDevice (pShield);
9831026 // Move the hand to a poisition so it looks like the new device was drawn from inventory
@@ -1027,9 +1070,9 @@ bool AHuman::EquipShieldInBGArm(bool depositToFront) {
10271070 HeldDevice* pShield = dynamic_cast <HeldDevice*>(*itr);
10281071 // Found proper device to equip, so make the switch!
10291072 if (pShield && (pShield->IsShield () || pShield->IsDualWieldable ())) {
1030- // Erase the inventory entry containing the device we now have switched to
1031- *itr = 0 ;
1032- m_Inventory.erase (itr );
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 ( );
10331076
10341077 // Put back into the inventory what we had in our hands, if anything
10351078 if (HeldDevice* heldDevice = m_pBGArm->GetHeldDevice ()) {
@@ -1041,6 +1084,13 @@ bool AHuman::EquipShieldInBGArm(bool depositToFront) {
10411084 }
10421085 }
10431086
1087+ // We want to preserve inventory order, so rotate it to the device in question.
1088+ std::rotate (m_Inventory.begin (), m_Inventory.begin () + device_offset, m_Inventory.end ());
1089+
1090+ // Erase the inventory entry containing the device we now have switched to
1091+ *m_Inventory.begin () = 0 ;
1092+ m_Inventory.pop_front ();
1093+
10441094 // Now put the device we were looking for and found into the hand
10451095 m_pBGArm->SetHeldDevice (pShield);
10461096 // Move the hand to a poisition so it looks like the new device was drawn from inventory
0 commit comments