@@ -626,24 +626,75 @@ void InventoryState::btnApplyTemplateClick(Action *action)
626626 {
627627 // search for template item in ground inventory
628628 std::vector<BattleItem*>::iterator groundItem;
629+ const bool needsAmmo = !_game->getRuleset ()->getItem ((*templateIt)->getItemType ())->getCompatibleAmmo ()->empty ();
629630 bool found = false ;
630- for (groundItem = groundInv->begin (); groundItem != groundInv->end (); ++groundItem)
631+ bool rescan = true ;
632+ while (rescan)
631633 {
632- if ((*templateIt)->getItemType () == (*groundItem)->getRules ()->getType ())
634+ rescan = false ;
635+
636+ const std::string targetAmmo = (*templateIt)->getAmmoItem ();
637+ BattleItem *matchedWeapon = NULL ;
638+ BattleItem *matchedAmmo = NULL ;
639+ for (groundItem = groundInv->begin (); groundItem != groundInv->end (); ++groundItem)
640+ {
641+ // if we find the appropriate ammo, remember it for later for if we find
642+ // the right weapon but with the wrong ammo
643+ const std::string groundItemName = (*groundItem)->getRules ()->getType ();
644+ if (needsAmmo && targetAmmo == groundItemName)
645+ {
646+ matchedAmmo = *groundItem;
647+ }
648+
649+ if ((*templateIt)->getItemType () == groundItemName)
650+ {
651+ // if the loaded ammo doesn't match the template item's,
652+ // remember the weapon for later and continue scanning
653+ BattleItem *loadedAmmo = (*groundItem)->getAmmoItem ();
654+ if ((needsAmmo && loadedAmmo && targetAmmo != loadedAmmo->getRules ()->getType ())
655+ || (needsAmmo && !loadedAmmo))
656+ {
657+ // remember the last matched weapon for simplicity (but prefer empty weapons if any are found)
658+ if (!matchedWeapon || matchedWeapon->getAmmoItem ())
659+ {
660+ matchedWeapon = *groundItem;
661+ }
662+ continue ;
663+ }
664+
665+ // move matched item from ground to the appropriate inv slot
666+ (*groundItem)->setOwner (unit);
667+ (*groundItem)->setSlot (_game->getRuleset ()->getInventory ((*templateIt)->getSlot ()));
668+ (*groundItem)->setSlotX ((*templateIt)->getSlotX ());
669+ (*groundItem)->setSlotY ((*templateIt)->getSlotY ());
670+ unitInv->push_back (*groundItem);
671+ groundInv->erase (groundItem);
672+ found = true ;
673+ break ;
674+ }
675+ }
676+
677+ // if we failed to find an exact match, but found unloaded ammo and
678+ // the right weapon, unload the target weapon, load the right ammo, and use it
679+ if (!found && matchedWeapon && (!needsAmmo || matchedAmmo))
633680 {
634- // move matched item from ground to the appropriate inv slot
635- // note that this doesn't attempt to match the isLoaded status
636- // of ammo-bearing weapons. presumably as many weapons as
637- // possible were already loaded when the battlescape was
638- // generated
639- (*groundItem)->setOwner (unit);
640- (*groundItem)->setSlot (_game->getRuleset ()->getInventory ((*templateIt)->getSlot ()));
641- (*groundItem)->setSlotX ((*templateIt)->getSlotX ());
642- (*groundItem)->setSlotY ((*templateIt)->getSlotY ());
643- unitInv->push_back (*groundItem);
644- groundInv->erase (groundItem);
645- found = true ;
646- break ;
681+ // unload the existing ammo (if any) from the weapon
682+ BattleItem *loadedAmmo = matchedWeapon->getAmmoItem ();
683+ if (loadedAmmo)
684+ {
685+ groundTile->addItem (loadedAmmo, groundRuleInv);
686+ matchedWeapon->setAmmoItem (NULL );
687+ }
688+
689+ // load the correct ammo into the weapon
690+ if (matchedAmmo)
691+ {
692+ matchedWeapon->setAmmoItem (matchedAmmo);
693+ groundTile->removeItem (matchedAmmo);
694+ }
695+
696+ // rescan and pick up the newly-loaded/unloaded weapon
697+ rescan = true ;
647698 }
648699 }
649700
0 commit comments