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 {};
bool swapGarrisonOnSiege(ObjectInstanceID tid) override {return false;};
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 removeArtifact(const ArtifactLocation & al) override {};
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))
return false;
if(ArtifactUtils::isSlotBackpack(slot))
return true; //TODO backpack limit
return true;
CArtifactFittingSet fittingSet(artSet->bearerType());
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::putAt(al); //puts combined art (this)
for(ConstituentInfo &ci : constituentsInfo)
for(ConstituentInfo & ci : constituentsInfo)
{
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 suggestedPosValid = ci.art->canBePutAt(suggestedPos);
ArtifactPosition pos = ArtifactPosition::PRE_FIRST;
if(inActiveSlot && suggestedPosValid) //there is a valid suggestion where to place lock
pos = ci.slot;
else
ci.slot = pos = ci.art->firstAvailableSlot(al.getHolderArtSet());
if(!(inActiveSlot && suggestedPosValid)) //there is a valid suggestion where to place lock
ci.slot = ArtifactUtils::getArtifactDstPosition(ci.art->artType->getId(), al.getHolderArtSet());
assert(!ArtifactUtils::isSlotBackpack(pos));
al.getHolderArtSet()->setNewArtSlot(pos, ci.art, true); //sets as lock
assert(ArtifactUtils::isSlotEquipment(ci.slot));
al.getHolderArtSet()->setNewArtSlot(ci.slot, ci.art, true); //sets as lock
}
else
{
@ -1525,8 +1522,10 @@ void CArtifactFittingSet::putArtifact(ArtifactPosition pos, CArtifactInstance *
{
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
this->setNewArtSlot(part.art->firstAvailableSlot(this), part.art, true);
this->setNewArtSlot(slot, part.art, true);
}
}
else
@ -1650,4 +1649,13 @@ DLL_LINKAGE bool ArtifactUtils::isBackpackFreeSlots(const CArtifactSet * target,
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

View File

@ -389,6 +389,7 @@ namespace ArtifactUtils
DLL_LINKAGE bool isSlotBackpack(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 isPossibleToGetArt(const CArtifactSet * target, const ArtifactID & aid);
}
VCMI_LIB_NAMESPACE_END

View File

@ -1588,12 +1588,17 @@ void CGameState::giveCampaignBonusToHero(CGHeroInstance * hero)
}
break;
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;
case CScenarioTravel::STravelBonus::SPELL_SCROLL:
{
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;
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());
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;
}
@ -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
CArtifactInstance *ai = CArtifactInstance::createNewArtifactInstance(artifact);
CArtifactInstance * ai = CArtifactInstance::createNewArtifactInstance(artifact);
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

View File

@ -178,7 +178,7 @@ public:
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);
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 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 removeArtifact(const ArtifactLocation &al) = 0;
virtual bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) = 0;

View File

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

View File

@ -1300,9 +1300,12 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
InfoWindow iw;
iw.type = EInfoWindowMode::AUTO;
iw.player = h->tempOwner;
switch(ID)
if(ArtifactUtils::isPossibleToGetArt(h, storedArtifact->artType->getId()))
{
case Obj::ARTIFACT:
switch (ID)
{
case Obj::ARTIFACT:
{
iw.components.emplace_back(Component::EComponentType::ARTIFACT, subID, 0, 0);
if(message.length())
@ -1311,7 +1314,7 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
iw.text.addTxt(MetaString::ART_EVNTS, subID);
}
break;
case Obj::SPELL_SCROLL:
case Obj::SPELL_SCROLL:
{
int spellID = storedArtifact->getGivenSpellID();
iw.components.emplace_back(Component::EComponentType::SPELL, spellID, 0, 0);
@ -1319,11 +1322,16 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
iw.text << message;
else
{
iw.text.addTxt(MetaString::ADVOB_TXT,135);
iw.text.addTxt(MetaString::ADVOB_TXT, 135);
iw.text.addReplacement(MetaString::SPELL_NAME, spellID);
}
}
break;
}
}
else
{
iw.text << "no slots";
}
cb->showInfoDialog(&iw);
pick(h);
@ -1368,8 +1376,8 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
void CGArtifact::pick(const CGHeroInstance * h) const
{
cb->giveHeroArtifact(h, storedArtifact, ArtifactPosition::FIRST_AVAILABLE);
cb->removeObject(this);
if(cb->giveHeroArtifact(h, storedArtifact, ArtifactPosition::FIRST_AVAILABLE))
cb->removeObject(this);
}
BattleField CGArtifact::getBattlefield() const

View File

@ -5876,13 +5876,18 @@ bool CGameHandler::dig(const CGHeroInstance *h)
if (h->diggingStatus() != EDiggingStatus::CAN_DIG) //checks for terrain and movement
COMPLAIN_RETF("Hero cannot dig (error code %d)!", h->diggingStatus());
//create a hole
NewObject no;
no.ID = Obj::HOLE;
no.pos = h->visitablePos();
no.subID = 0;
sendAndApply(&no);
const auto isHeroAbleGet = ArtifactUtils::isPossibleToGetArt(h, ArtifactID::GRAIL);
if(isHeroAbleGet)
{
//create a hole
NewObject no;
no.ID = Obj::HOLE;
no.pos = h->visitablePos();
no.subID = 0;
sendAndApply(&no);
}
//take MPs
SetMovePoints smp;
smp.hid = h->id;
@ -5894,17 +5899,25 @@ bool CGameHandler::dig(const CGHeroInstance *h)
iw.player = h->tempOwner;
if (gs->map->grailPos == h->visitablePos())
{
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.soundID = soundBase::ULTIMATEARTIFACT;
giveHeroNewArtifact(h, VLC->arth->objects[ArtifactID::GRAIL], ArtifactPosition::PRE_FIRST); //give grail
sendAndApply(&iw);
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::ART_NAMES, ArtifactID::GRAIL);
iw.soundID = soundBase::ULTIMATEARTIFACT;
giveHeroNewArtifact(h, VLC->arth->objects[ArtifactID::GRAIL], ArtifactPosition::PRE_FIRST); //give grail
sendAndApply(&iw);
iw.soundID = soundBase::invalid;
iw.components.emplace_back(Component::EComponentType::ARTIFACT, ArtifactID::GRAIL, 0, 0);
iw.text.clear();
iw.text.addTxt(MetaString::ART_DESCR, ArtifactID::GRAIL);
sendAndApply(&iw);
iw.soundID = soundBase::invalid;
iw.components.emplace_back(Component::EComponentType::ARTIFACT, ArtifactID::GRAIL, 0, 0);
iw.text.clear();
iw.text.addTxt(MetaString::ART_DESCR, ArtifactID::GRAIL);
sendAndApply(&iw);
}
else
{
iw.text << "found but no free slots";
sendAndApply(&iw);
}
}
else
{
@ -6818,35 +6831,32 @@ bool CGameHandler::makeAutomaticAction(const CStack *stack, BattleAction &ba)
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);
ArtifactLocation al;
al.artHolder = const_cast<CGHeroInstance*>(h);
ArtifactLocation al(h, ArtifactPosition::PRE_FIRST);
ArtifactPosition slot = ArtifactPosition::PRE_FIRST;
if (pos < 0)
if(pos == ArtifactPosition::FIRST_AVAILABLE)
{
if (pos == ArtifactPosition::FIRST_AVAILABLE)
slot = a->firstAvailableSlot(h);
else
slot = a->firstBackpackSlot(h);
al.slot = ArtifactUtils::getArtifactDstPosition(a->artType->getId(), h);
}
else
{
slot = pos;
if(a->artType->canBePutAt(h, pos, false))
al.slot = pos;
}
al.slot = slot;
if (slot < 0 || !a->canBePutAt(al))
if(ArtifactUtils::isSlotEquipment(al.slot) || ArtifactUtils::isSlotBackpack(al.slot))
{
complain("Cannot put artifact in that slot!");
return;
putArtifact(al, a);
return true;
}
else
{
return false;
}
putArtifact(al, a);
}
void CGameHandler::putArtifact(const ArtifactLocation &al, const CArtifactInstance *a)
{
PutArtifact pa;
@ -6884,7 +6894,7 @@ void CGameHandler::giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact
na.art = a;
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)

View File

@ -177,7 +177,7 @@ public:
bool giveHeroNewArtifact(const CGHeroInstance * h, const CArtifact * art);
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 removeArtifact(const ArtifactLocation &al) 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 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 removeArtifact(const ArtifactLocation &al) override {}
bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) override {return false;}