1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Backpack limit part2 (Pick up, Dig up, Object rewards)

This commit is contained in:
SoundSSGood 2023-03-18 22:58:39 +02:00
parent 96e8a1f21c
commit e23766280f
11 changed files with 108 additions and 63 deletions

View File

@ -212,7 +212,7 @@ public:
void removeAfterVisit(const CGObjectInstance * object) override {}; void removeAfterVisit(const CGObjectInstance * object) override {};
bool swapGarrisonOnSiege(ObjectInstanceID tid) override {return false;}; bool swapGarrisonOnSiege(ObjectInstanceID tid) override {return false;};
void giveHeroNewArtifact(const CGHeroInstance * h, const CArtifact * artType, ArtifactPosition pos) override {}; void giveHeroNewArtifact(const CGHeroInstance * h, const CArtifact * artType, ArtifactPosition pos) override {};
void giveHeroArtifact(const CGHeroInstance * h, const CArtifactInstance * a, ArtifactPosition pos) override {}; bool giveHeroArtifact(const CGHeroInstance * h, const CArtifactInstance * a, ArtifactPosition pos) override {return false;};
void putArtifact(const ArtifactLocation & al, const CArtifactInstance * a) override {}; void putArtifact(const ArtifactLocation & al, const CArtifactInstance * a) override {};
void removeArtifact(const ArtifactLocation & al) override {}; void removeArtifact(const ArtifactLocation & al) override {};
bool moveArtifact(const ArtifactLocation & al1, const ArtifactLocation & al2) override {return false;}; bool moveArtifact(const ArtifactLocation & al1, const ArtifactLocation & al2) override {return false;};

View File

@ -176,7 +176,7 @@ bool CArtifact::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, b
if(!simpleArtCanBePutAt(artSet, slot, assumeDestRemoved)) if(!simpleArtCanBePutAt(artSet, slot, assumeDestRemoved))
return false; return false;
if(ArtifactUtils::isSlotBackpack(slot)) if(ArtifactUtils::isSlotBackpack(slot))
return true; //TODO backpack limit return true;
CArtifactFittingSet fittingSet(artSet->bearerType()); CArtifactFittingSet fittingSet(artSet->bearerType());
fittingSet.artifactsWorn = artSet->artifactsWorn; fittingSet.artifactsWorn = artSet->artifactsWorn;
@ -1082,7 +1082,7 @@ void CCombinedArtifactInstance::putAt(ArtifactLocation al)
CArtifactInstance *mainConstituent = figureMainConstituent(al); //it'll be replaced with combined artifact, not a lock CArtifactInstance *mainConstituent = figureMainConstituent(al); //it'll be replaced with combined artifact, not a lock
CArtifactInstance::putAt(al); //puts combined art (this) CArtifactInstance::putAt(al); //puts combined art (this)
for(ConstituentInfo &ci : constituentsInfo) for(ConstituentInfo & ci : constituentsInfo)
{ {
if(ci.art != mainConstituent) if(ci.art != mainConstituent)
{ {
@ -1090,14 +1090,11 @@ void CCombinedArtifactInstance::putAt(ArtifactLocation al)
const bool inActiveSlot = vstd::isbetween(ci.slot, 0, GameConstants::BACKPACK_START); const bool inActiveSlot = vstd::isbetween(ci.slot, 0, GameConstants::BACKPACK_START);
const bool suggestedPosValid = ci.art->canBePutAt(suggestedPos); const bool suggestedPosValid = ci.art->canBePutAt(suggestedPos);
ArtifactPosition pos = ArtifactPosition::PRE_FIRST; if(!(inActiveSlot && suggestedPosValid)) //there is a valid suggestion where to place lock
if(inActiveSlot && suggestedPosValid) //there is a valid suggestion where to place lock ci.slot = ArtifactUtils::getArtifactDstPosition(ci.art->artType->getId(), al.getHolderArtSet());
pos = ci.slot;
else
ci.slot = pos = ci.art->firstAvailableSlot(al.getHolderArtSet());
assert(!ArtifactUtils::isSlotBackpack(pos)); assert(ArtifactUtils::isSlotEquipment(ci.slot));
al.getHolderArtSet()->setNewArtSlot(pos, ci.art, true); //sets as lock al.getHolderArtSet()->setNewArtSlot(ci.slot, ci.art, true); //sets as lock
} }
else else
{ {
@ -1525,8 +1522,10 @@ void CArtifactFittingSet::putArtifact(ArtifactPosition pos, CArtifactInstance *
{ {
for(auto & part : dynamic_cast<CCombinedArtifactInstance*>(art)->constituentsInfo) for(auto & part : dynamic_cast<CCombinedArtifactInstance*>(art)->constituentsInfo)
{ {
const auto slot = ArtifactUtils::getArtifactDstPosition(part.art->artType->getId(), this);
assert(slot != ArtifactPosition::PRE_FIRST);
// For the ArtFittingSet is no needed to do figureMainConstituent, just lock slots // For the ArtFittingSet is no needed to do figureMainConstituent, just lock slots
this->setNewArtSlot(part.art->firstAvailableSlot(this), part.art, true); this->setNewArtSlot(slot, part.art, true);
} }
} }
else else
@ -1650,4 +1649,13 @@ DLL_LINKAGE bool ArtifactUtils::isBackpackFreeSlots(const CArtifactSet * target,
return target->artifactsInBackpack.size() + reqSlots <= backpackCap; return target->artifactsInBackpack.size() + reqSlots <= backpackCap;
} }
DLL_LINKAGE bool ArtifactUtils::isPossibleToGetArt(const CArtifactSet * target, const ArtifactID & aid)
{
const auto slot = getArtifactDstPosition(aid, target);
if(isSlotEquipment(slot) || (isSlotBackpack(slot) && isBackpackFreeSlots(target)))
return true;
else
return false;
}
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -389,6 +389,7 @@ namespace ArtifactUtils
DLL_LINKAGE bool isSlotBackpack(const ArtifactPosition & slot); DLL_LINKAGE bool isSlotBackpack(const ArtifactPosition & slot);
DLL_LINKAGE bool isSlotEquipment(const ArtifactPosition & slot); DLL_LINKAGE bool isSlotEquipment(const ArtifactPosition & slot);
DLL_LINKAGE bool isBackpackFreeSlots(const CArtifactSet * target, const size_t reqSlots = 1); DLL_LINKAGE bool isBackpackFreeSlots(const CArtifactSet * target, const size_t reqSlots = 1);
DLL_LINKAGE bool isPossibleToGetArt(const CArtifactSet * target, const ArtifactID & aid);
} }
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -1588,12 +1588,17 @@ void CGameState::giveCampaignBonusToHero(CGHeroInstance * hero)
} }
break; break;
case CScenarioTravel::STravelBonus::ARTIFACT: case CScenarioTravel::STravelBonus::ARTIFACT:
gs->giveHeroArtifact(hero, static_cast<ArtifactID>(curBonus->info2)); if(!gs->giveHeroArtifact(hero, static_cast<ArtifactID>(curBonus->info2)))
logGlobal->error("Cannot give starting artifact - no free slots!");
break; break;
case CScenarioTravel::STravelBonus::SPELL_SCROLL: case CScenarioTravel::STravelBonus::SPELL_SCROLL:
{ {
CArtifactInstance * scroll = CArtifactInstance::createScroll(SpellID(curBonus->info2)); CArtifactInstance * scroll = CArtifactInstance::createScroll(SpellID(curBonus->info2));
scroll->putAt(ArtifactLocation(hero, scroll->firstAvailableSlot(hero))); const auto slot = ArtifactUtils::getArtifactDstPosition(scroll->artType->getId(), hero);
if(ArtifactUtils::isSlotEquipment(slot) || ArtifactUtils::isSlotBackpack(slot))
scroll->putAt(ArtifactLocation(hero, slot));
else
logGlobal->error("Cannot give starting scroll - no free slots!");
} }
break; break;
case CScenarioTravel::STravelBonus::PRIMARY_SKILL: case CScenarioTravel::STravelBonus::PRIMARY_SKILL:
@ -1686,7 +1691,10 @@ void CGameState::initStartingBonus()
const Artifact * toGive = VLC->arth->pickRandomArtifact(getRandomGenerator(), CArtifact::ART_TREASURE).toArtifact(VLC->artifacts()); const Artifact * toGive = VLC->arth->pickRandomArtifact(getRandomGenerator(), CArtifact::ART_TREASURE).toArtifact(VLC->artifacts());
CGHeroInstance *hero = elem.second.heroes[0]; CGHeroInstance *hero = elem.second.heroes[0];
giveHeroArtifact(hero, toGive->getId()); if(!giveHeroArtifact(hero, toGive->getId()))
{
logGlobal->error("Cannot give starting artifact - no free slots!");
}
} }
break; break;
} }
@ -2805,12 +2813,21 @@ void CGameState::attachArmedObjects()
} }
} }
void CGameState::giveHeroArtifact(CGHeroInstance * h, const ArtifactID & aid) bool CGameState::giveHeroArtifact(CGHeroInstance * h, const ArtifactID & aid)
{ {
CArtifact * const artifact = VLC->arth->objects[aid]; //pointer to constant object CArtifact * const artifact = VLC->arth->objects[aid]; //pointer to constant object
CArtifactInstance *ai = CArtifactInstance::createNewArtifactInstance(artifact); CArtifactInstance * ai = CArtifactInstance::createNewArtifactInstance(artifact);
map->addNewArtifactInstance(ai); map->addNewArtifactInstance(ai);
ai->putAt(ArtifactLocation(h, ai->firstAvailableSlot(h))); auto slot = ArtifactUtils::getArtifactDstPosition(aid, h);
if(ArtifactUtils::isSlotEquipment(slot) || ArtifactUtils::isSlotBackpack(slot))
{
ai->putAt(ArtifactLocation(h, slot));
return true;
}
else
{
return false;
}
} }
std::set<HeroTypeID> CGameState::getUnusedAllowedHeroes(bool alsoIncludeNotAllowed) const std::set<HeroTypeID> CGameState::getUnusedAllowedHeroes(bool alsoIncludeNotAllowed) const

View File

@ -178,7 +178,7 @@ public:
void updateEntity(Metatype metatype, int32_t index, const JsonNode & data) override; void updateEntity(Metatype metatype, int32_t index, const JsonNode & data) override;
void giveHeroArtifact(CGHeroInstance * h, const ArtifactID & aid); bool giveHeroArtifact(CGHeroInstance * h, const ArtifactID & aid);
void apply(CPack *pack); void apply(CPack *pack);
BattleField battleGetBattlefieldType(int3 tile, CRandomGenerator & rand); BattleField battleGetBattlefieldType(int3 tile, CRandomGenerator & rand);

View File

@ -110,7 +110,7 @@ public:
virtual void removeAfterVisit(const CGObjectInstance *object) = 0; //object will be destroyed when interaction is over. Do not call when interaction is not ongoing! virtual void removeAfterVisit(const CGObjectInstance *object) = 0; //object will be destroyed when interaction is over. Do not call when interaction is not ongoing!
virtual void giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, ArtifactPosition pos) = 0; virtual void giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, ArtifactPosition pos) = 0;
virtual void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, ArtifactPosition pos) = 0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack virtual bool giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, ArtifactPosition pos) = 0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
virtual void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) = 0; virtual void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) = 0;
virtual void removeArtifact(const ArtifactLocation &al) = 0; virtual void removeArtifact(const ArtifactLocation &al) = 0;
virtual bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) = 0; virtual bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) = 0;

View File

@ -855,6 +855,7 @@ void CGSeerHut::completeQuest (const CGHeroInstance * h) const //reward
cb->changeSecSkill(h, SecondarySkill(rID), rVal, false); cb->changeSecSkill(h, SecondarySkill(rID), rVal, false);
break; break;
case ARTIFACT: case ARTIFACT:
if(ArtifactUtils::isPossibleToGetArt(h, VLC->arth->objects[rID]->getId()))
cb->giveHeroNewArtifact(h, VLC->arth->objects[rID],ArtifactPosition::FIRST_AVAILABLE); cb->giveHeroNewArtifact(h, VLC->arth->objects[rID],ArtifactPosition::FIRST_AVAILABLE);
break; break;
case SPELL: case SPELL:

View File

@ -1300,7 +1300,10 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
InfoWindow iw; InfoWindow iw;
iw.type = EInfoWindowMode::AUTO; iw.type = EInfoWindowMode::AUTO;
iw.player = h->tempOwner; iw.player = h->tempOwner;
switch(ID)
if(ArtifactUtils::isPossibleToGetArt(h, storedArtifact->artType->getId()))
{
switch (ID)
{ {
case Obj::ARTIFACT: case Obj::ARTIFACT:
{ {
@ -1319,12 +1322,17 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
iw.text << message; iw.text << message;
else else
{ {
iw.text.addTxt(MetaString::ADVOB_TXT,135); iw.text.addTxt(MetaString::ADVOB_TXT, 135);
iw.text.addReplacement(MetaString::SPELL_NAME, spellID); iw.text.addReplacement(MetaString::SPELL_NAME, spellID);
} }
} }
break; break;
} }
}
else
{
iw.text << "no slots";
}
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
pick(h); pick(h);
} }
@ -1368,7 +1376,7 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
void CGArtifact::pick(const CGHeroInstance * h) const void CGArtifact::pick(const CGHeroInstance * h) const
{ {
cb->giveHeroArtifact(h, storedArtifact, ArtifactPosition::FIRST_AVAILABLE); if(cb->giveHeroArtifact(h, storedArtifact, ArtifactPosition::FIRST_AVAILABLE))
cb->removeObject(this); cb->removeObject(this);
} }

View File

@ -5876,12 +5876,17 @@ bool CGameHandler::dig(const CGHeroInstance *h)
if (h->diggingStatus() != EDiggingStatus::CAN_DIG) //checks for terrain and movement if (h->diggingStatus() != EDiggingStatus::CAN_DIG) //checks for terrain and movement
COMPLAIN_RETF("Hero cannot dig (error code %d)!", h->diggingStatus()); COMPLAIN_RETF("Hero cannot dig (error code %d)!", h->diggingStatus());
const auto isHeroAbleGet = ArtifactUtils::isPossibleToGetArt(h, ArtifactID::GRAIL);
if(isHeroAbleGet)
{
//create a hole //create a hole
NewObject no; NewObject no;
no.ID = Obj::HOLE; no.ID = Obj::HOLE;
no.pos = h->visitablePos(); no.pos = h->visitablePos();
no.subID = 0; no.subID = 0;
sendAndApply(&no); sendAndApply(&no);
}
//take MPs //take MPs
SetMovePoints smp; SetMovePoints smp;
@ -5893,6 +5898,8 @@ bool CGameHandler::dig(const CGHeroInstance *h)
iw.type = EInfoWindowMode::AUTO; iw.type = EInfoWindowMode::AUTO;
iw.player = h->tempOwner; iw.player = h->tempOwner;
if (gs->map->grailPos == h->visitablePos()) if (gs->map->grailPos == h->visitablePos())
{
if(isHeroAbleGet)
{ {
iw.text.addTxt(MetaString::GENERAL_TXT, 58); //"Congratulations! After spending many hours digging here, your hero has uncovered the " iw.text.addTxt(MetaString::GENERAL_TXT, 58); //"Congratulations! After spending many hours digging here, your hero has uncovered the "
iw.text.addTxt(MetaString::ART_NAMES, ArtifactID::GRAIL); iw.text.addTxt(MetaString::ART_NAMES, ArtifactID::GRAIL);
@ -5907,6 +5914,12 @@ bool CGameHandler::dig(const CGHeroInstance *h)
sendAndApply(&iw); sendAndApply(&iw);
} }
else else
{
iw.text << "found but no free slots";
sendAndApply(&iw);
}
}
else
{ {
iw.text.addTxt(MetaString::GENERAL_TXT, 59); //"Nothing here. \n Where could it be?" iw.text.addTxt(MetaString::GENERAL_TXT, 59); //"Nothing here. \n Where could it be?"
iw.soundID = soundBase::Dig; iw.soundID = soundBase::Dig;
@ -6818,35 +6831,32 @@ bool CGameHandler::makeAutomaticAction(const CStack *stack, BattleAction &ba)
return ret; return ret;
} }
void CGameHandler::giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, ArtifactPosition pos) bool CGameHandler::giveHeroArtifact(const CGHeroInstance * h, const CArtifactInstance * a, ArtifactPosition pos)
{ {
assert(a->artType); assert(a->artType);
ArtifactLocation al; ArtifactLocation al(h, ArtifactPosition::PRE_FIRST);
al.artHolder = const_cast<CGHeroInstance*>(h);
ArtifactPosition slot = ArtifactPosition::PRE_FIRST; if(pos == ArtifactPosition::FIRST_AVAILABLE)
if (pos < 0)
{ {
if (pos == ArtifactPosition::FIRST_AVAILABLE) al.slot = ArtifactUtils::getArtifactDstPosition(a->artType->getId(), h);
slot = a->firstAvailableSlot(h);
else
slot = a->firstBackpackSlot(h);
} }
else else
{ {
slot = pos; if(a->artType->canBePutAt(h, pos, false))
al.slot = pos;
} }
al.slot = slot; if(ArtifactUtils::isSlotEquipment(al.slot) || ArtifactUtils::isSlotBackpack(al.slot))
if (slot < 0 || !a->canBePutAt(al))
{ {
complain("Cannot put artifact in that slot!");
return;
}
putArtifact(al, a); putArtifact(al, a);
return true;
}
else
{
return false;
}
} }
void CGameHandler::putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) void CGameHandler::putArtifact(const ArtifactLocation &al, const CArtifactInstance *a)
{ {
PutArtifact pa; PutArtifact pa;
@ -6884,7 +6894,7 @@ void CGameHandler::giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact
na.art = a; na.art = a;
sendAndApply(&na); // -> updates a!!!, will create a on other machines sendAndApply(&na); // -> updates a!!!, will create a on other machines
giveHeroArtifact(h, a, pos); COMPLAIN_RET_IF(!giveHeroArtifact(h, a, pos), "Cannot put artifact in that slot!");
} }
void CGameHandler::setBattleResult(BattleResult::EResult resultType, int victoriusSide) void CGameHandler::setBattleResult(BattleResult::EResult resultType, int victoriusSide)

View File

@ -177,7 +177,7 @@ public:
bool giveHeroNewArtifact(const CGHeroInstance * h, const CArtifact * art); bool giveHeroNewArtifact(const CGHeroInstance * h, const CArtifact * art);
void giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, ArtifactPosition pos) override; void giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, ArtifactPosition pos) override;
void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, ArtifactPosition pos) override; bool giveHeroArtifact(const CGHeroInstance * h, const CArtifactInstance * a, ArtifactPosition pos) override;
void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) override; void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) override;
void removeArtifact(const ArtifactLocation &al) override; void removeArtifact(const ArtifactLocation &al) override;
bool moveArtifact(const ArtifactLocation & al1, const ArtifactLocation & al2) override; bool moveArtifact(const ArtifactLocation & al1, const ArtifactLocation & al2) override;

View File

@ -65,7 +65,7 @@ public:
void removeAfterVisit(const CGObjectInstance *object) override {} //object will be destroyed when interaction is over. Do not call when interaction is not ongoing! void removeAfterVisit(const CGObjectInstance *object) override {} //object will be destroyed when interaction is over. Do not call when interaction is not ongoing!
void giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, ArtifactPosition pos) override {} void giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, ArtifactPosition pos) override {}
void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, ArtifactPosition pos) override {} //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack bool giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, ArtifactPosition pos) override {} //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) override {} void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) override {}
void removeArtifact(const ArtifactLocation &al) override {} void removeArtifact(const ArtifactLocation &al) override {}
bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) override {return false;} bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) override {return false;}