Skip to content

Commit b44bf3c

Browse files
committed
Merge pull request OpenXcom#887 from myk002/remember_ammo_in_template
match ammo types when applying inventory templates
2 parents fe44678 + 89abc7b commit b44bf3c

1 file changed

Lines changed: 66 additions & 15 deletions

File tree

src/Battlescape/InventoryState.cpp

Lines changed: 66 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)