mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-06 09:09:40 +02:00
Fix handling of creatures in configurable town buildings
- Fixed removal of partial stacks of creatures - It is now possible to give units via town building, but only if visitor has slots to take them
This commit is contained in:
@@ -635,7 +635,8 @@ List of supported slots names:
|
||||
|
||||
- Can be used as limiter
|
||||
- Can be used as reward, to give new creatures to a hero
|
||||
- If hero does not have enough free slots, game will show selection dialog to pick troops to keep
|
||||
- For map objects, if hero does not have enough free slots, game will show selection dialog to pick troops to keep
|
||||
- For town buildings, hero must either have free slot(s) to take them, or have creatures of this type. Othervice reward would fail to give any creatures
|
||||
- It is possible to specify probability to receive upgraded creature
|
||||
|
||||
```json
|
||||
|
||||
@@ -76,6 +76,7 @@ public:
|
||||
virtual void giveResource(PlayerColor player, GameResID which, int val)=0;
|
||||
virtual void giveResources(PlayerColor player, ResourceSet resources)=0;
|
||||
|
||||
virtual void giveCreatures(const CGHeroInstance * h, const CCreatureSet &creatures) =0;
|
||||
virtual void giveCreatures(const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) =0;
|
||||
virtual void takeCreatures(ObjectInstanceID objid, const std::vector<CStackBasicDescriptor> &creatures, bool forceRemoval = false) =0;
|
||||
virtual bool changeStackCount(const StackLocation &sl, TQuantity count, ChangeValueMode mode) =0;
|
||||
|
||||
@@ -254,8 +254,11 @@ void Rewardable::Interface::grantRewardAfterLevelup(IGameEventCallback & gameEve
|
||||
for(const auto & crea : info.reward.creatures)
|
||||
creatures.addToSlot(creatures.getFreeSlot(), std::make_unique<CStackInstance>(cb, crea.getId(), crea.getCount()));
|
||||
|
||||
if(auto * army = dynamic_cast<const CArmedInstance*>(this)) //TODO: to fix that, CArmedInstance must be split on map instance part and interface part
|
||||
auto * army = dynamic_cast<const CArmedInstance*>(this);
|
||||
if (army)
|
||||
gameEvents.giveCreatures(army, hero, creatures, false);
|
||||
else
|
||||
gameEvents.giveCreatures(hero, creatures);
|
||||
}
|
||||
|
||||
if(info.reward.spellCast.first != SpellID::NONE)
|
||||
|
||||
@@ -1139,6 +1139,37 @@ void CGameHandler::giveResources(PlayerColor player, TResources resources)
|
||||
sendAndApply(sr);
|
||||
}
|
||||
|
||||
void CGameHandler::giveCreatures(const CGHeroInstance * hero, const CCreatureSet &creatures)
|
||||
{
|
||||
if (!hero->canBeMergedWith(creatures, true))
|
||||
{
|
||||
complain("Unable to give creatures! Hero does not have enough free slots to receive them!");
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto & unit : creatures.Slots())
|
||||
{
|
||||
SlotID pos = hero->getSlotFor(unit.second->getCreature());
|
||||
if (!pos.validSlot())
|
||||
{
|
||||
//try to merge two other stacks to make place
|
||||
std::pair<SlotID, SlotID> toMerge;
|
||||
if (hero->mergeableStacks(toMerge))
|
||||
{
|
||||
moveStack(StackLocation(hero->id, toMerge.first), StackLocation(hero->id, toMerge.second)); //merge toMerge.first into toMerge.second
|
||||
pos = toMerge.first;
|
||||
}
|
||||
}
|
||||
assert(pos.validSlot());
|
||||
assert(hero->slotEmpty(pos) || hero->getCreature(pos) == unit.second->getCreature());
|
||||
|
||||
if (hero->hasStackAtSlot(pos))
|
||||
changeStackCount(StackLocation(hero->id, pos), unit.second->getCount(), ChangeValueMode::RELATIVE);
|
||||
else
|
||||
insertNewStack(StackLocation(hero->id, pos), unit.second->getCreature(), unit.second->getCount());
|
||||
}
|
||||
}
|
||||
|
||||
void CGameHandler::giveCreatures(const CArmedInstance *obj, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove)
|
||||
{
|
||||
COMPLAIN_RET_IF(!creatures.stacksCount(), "Strange, giveCreatures called without args!");
|
||||
@@ -1181,8 +1212,8 @@ void CGameHandler::takeCreatures(ObjectInstanceID objid, const std::vector<CStac
|
||||
else
|
||||
{
|
||||
// take part of the stack
|
||||
collected = stackToTake.getCount();
|
||||
changeStackCount(StackLocation(army->id, armySlot.first), collected - stackToTake.getCount(), ChangeValueMode::RELATIVE);
|
||||
collected = stackToTake.getCount();
|
||||
}
|
||||
foundSth = true;
|
||||
break;
|
||||
@@ -3811,7 +3842,7 @@ bool CGameHandler::changeStackCount(const StackLocation &sl, TQuantity count, Ch
|
||||
auto army = dynamic_cast<const CArmedInstance*>(getObj(sl.army));
|
||||
|
||||
TQuantity currentCount = army->getStackCount(sl.slot);
|
||||
if ((mode == ChangeValueMode::RELATIVE && count < 0)
|
||||
if ((mode == ChangeValueMode::ABSOLUTE && count < 0)
|
||||
|| (mode == ChangeValueMode::RELATIVE && -count > currentCount))
|
||||
{
|
||||
COMPLAIN_RET("Cannot take more stacks than present!");
|
||||
|
||||
@@ -125,6 +125,7 @@ public:
|
||||
void giveResource(PlayerColor player, GameResID which, int val) override;
|
||||
void giveResources(PlayerColor player, TResources resources) override;
|
||||
|
||||
void giveCreatures(const CGHeroInstance * h, const CCreatureSet &creatures) override;
|
||||
void giveCreatures(const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) override;
|
||||
void takeCreatures(ObjectInstanceID objid, const std::vector<CStackBasicDescriptor> &creatures, bool forceRemoval) override;
|
||||
bool changeStackType(const StackLocation &sl, const CCreature *c) override;
|
||||
|
||||
@@ -60,6 +60,7 @@ public:
|
||||
void giveResource(PlayerColor player, GameResID which, int val) override {}
|
||||
void giveResources(PlayerColor player, ResourceSet resources) override {}
|
||||
|
||||
void giveCreatures(const CGHeroInstance * h, const CCreatureSet &creatures) override{}
|
||||
void giveCreatures(const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) override {}
|
||||
void takeCreatures(ObjectInstanceID objid, const std::vector<CStackBasicDescriptor> &creatures, bool forceRemoval) override {}
|
||||
bool changeStackCount(const StackLocation &sl, TQuantity count, ChangeValueMode mode) override {return false;}
|
||||
|
||||
Reference in New Issue
Block a user