mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-28 08:48:48 +02:00
Merge pull request #1148 from SoundSSGood/ask-assemble
Feature to assemble/disassemble arts in backpack
This commit is contained in:
commit
dfee2eda68
@ -206,12 +206,13 @@ void CHeroArtPlace::clickLeft(tribool down, bool previousState)
|
||||
bool CHeroArtPlace::askToAssemble(const CArtifactInstance *art, ArtifactPosition slot,
|
||||
const CGHeroInstance *hero)
|
||||
{
|
||||
assert(art != nullptr);
|
||||
assert(hero != nullptr);
|
||||
std::vector<const CArtifact *> assemblyPossibilities = art->assemblyPossibilities(hero);
|
||||
assert(art);
|
||||
assert(hero);
|
||||
bool assembleEqipped = !ArtifactUtils::isSlotBackpack(slot);
|
||||
auto assemblyPossibilities = art->assemblyPossibilities(hero, assembleEqipped);
|
||||
|
||||
// If the artifact can be assembled, display dialog.
|
||||
for(const CArtifact *combination : assemblyPossibilities)
|
||||
for(const auto * combination : assemblyPossibilities)
|
||||
{
|
||||
LOCPLINT->showArtifactAssemblyDialog(
|
||||
art->artType,
|
||||
@ -229,27 +230,22 @@ void CHeroArtPlace::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
if(ourArt && down && !locked && text.size() && !picked) //if there is no description or it's a lock, do nothing ;]
|
||||
{
|
||||
if(slotID < GameConstants::BACKPACK_START)
|
||||
if(ourOwner->allowedAssembling)
|
||||
{
|
||||
if(ourOwner->allowedAssembling)
|
||||
// If the artifact can be assembled, display dialog.
|
||||
if(askToAssemble(ourArt, slotID, ourOwner->curHero))
|
||||
{
|
||||
std::vector<const CArtifact *> assemblyPossibilities = ourArt->assemblyPossibilities(ourOwner->curHero);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the artifact can be assembled, display dialog.
|
||||
if(askToAssemble(ourArt, slotID, ourOwner->curHero))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise if the artifact can be diasassembled, display dialog.
|
||||
if(ourArt->canBeDisassembled())
|
||||
{
|
||||
LOCPLINT->showArtifactAssemblyDialog(
|
||||
ourArt->artType,
|
||||
nullptr,
|
||||
std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), ourOwner->curHero, slotID, false, ArtifactID()));
|
||||
return;
|
||||
}
|
||||
// Otherwise if the artifact can be diasassembled, display dialog.
|
||||
if(ourArt->canBeDisassembled())
|
||||
{
|
||||
LOCPLINT->showArtifactAssemblyDialog(
|
||||
ourArt->artType,
|
||||
nullptr,
|
||||
std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), ourOwner->curHero, slotID, false, ArtifactID()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -819,16 +815,15 @@ CArtifactsOfHero::ArtPlacePtr CArtifactsOfHero::getArtPlace(int slot)
|
||||
}
|
||||
}
|
||||
|
||||
void CArtifactsOfHero::artifactAssembled(const ArtifactLocation &al)
|
||||
void CArtifactsOfHero::artifactUpdateSlots(const ArtifactLocation & al)
|
||||
{
|
||||
if(al.isHolder(curHero))
|
||||
updateWornSlots();
|
||||
}
|
||||
|
||||
void CArtifactsOfHero::artifactDisassembled(const ArtifactLocation &al)
|
||||
{
|
||||
if(al.isHolder(curHero))
|
||||
updateWornSlots();
|
||||
{
|
||||
if(ArtifactUtils::isSlotBackpack(al.slot))
|
||||
updateBackpackSlots();
|
||||
else
|
||||
updateWornSlots();
|
||||
}
|
||||
}
|
||||
|
||||
void CArtifactsOfHero::updateWornSlots(bool redrawParent)
|
||||
@ -840,6 +835,16 @@ void CArtifactsOfHero::updateWornSlots(bool redrawParent)
|
||||
updateParentWindow();
|
||||
}
|
||||
|
||||
void CArtifactsOfHero::updateBackpackSlots(bool redrawParent)
|
||||
{
|
||||
for(auto artPlace : backpack)
|
||||
updateSlot(artPlace->slotID);
|
||||
scrollBackpack(0);
|
||||
|
||||
if(redrawParent)
|
||||
updateParentWindow();
|
||||
}
|
||||
|
||||
const CGHeroInstance * CArtifactsOfHero::getHero() const
|
||||
{
|
||||
return curHero;
|
||||
@ -910,7 +915,7 @@ void CWindowWithArtifacts::artifactDisassembled(const ArtifactLocation &artLoc)
|
||||
{
|
||||
std::shared_ptr<CArtifactsOfHero> realPtr = artSetWeak.lock();
|
||||
if(realPtr)
|
||||
realPtr->artifactDisassembled(artLoc);
|
||||
realPtr->artifactUpdateSlots(artLoc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -920,7 +925,7 @@ void CWindowWithArtifacts::artifactAssembled(const ArtifactLocation &artLoc)
|
||||
{
|
||||
std::shared_ptr<CArtifactsOfHero> realPtr = artSetWeak.lock();
|
||||
if(realPtr)
|
||||
realPtr->artifactAssembled(artLoc);
|
||||
realPtr->artifactUpdateSlots(artLoc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,8 +140,7 @@ public:
|
||||
void realizeCurrentTransaction(); //calls callback with parameters stored in commonInfo
|
||||
void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst);
|
||||
void artifactRemoved(const ArtifactLocation &al);
|
||||
void artifactAssembled(const ArtifactLocation &al);
|
||||
void artifactDisassembled(const ArtifactLocation &al);
|
||||
void artifactUpdateSlots(const ArtifactLocation &al);
|
||||
ArtPlacePtr getArtPlace(int slot);//may return null
|
||||
|
||||
void setHero(const CGHeroInstance * hero);
|
||||
@ -153,7 +152,8 @@ public:
|
||||
void markPossibleSlots(const CArtifactInstance* art);
|
||||
void unmarkSlots(bool withRedraw = true); //unmarks slots in all visible AOHs
|
||||
void unmarkLocalSlots(bool withRedraw = true); //unmarks slots in that particular AOH
|
||||
void updateWornSlots (bool redrawParent = true);
|
||||
void updateWornSlots(bool redrawParent = true);
|
||||
void updateBackpackSlots(bool redrawParent = true);
|
||||
|
||||
void updateSlot(ArtifactPosition i);
|
||||
|
||||
|
@ -870,26 +870,36 @@ bool CArtifactInstance::canBeDisassembled() const
|
||||
return bool(artType->constituents);
|
||||
}
|
||||
|
||||
std::vector<const CArtifact *> CArtifactInstance::assemblyPossibilities(const CArtifactSet *h) const
|
||||
std::vector<const CArtifact *> CArtifactInstance::assemblyPossibilities(const CArtifactSet * h, bool equipped) const
|
||||
{
|
||||
std::vector<const CArtifact *> ret;
|
||||
if(artType->constituents) //combined artifact already: no combining of combined artifacts... for now.
|
||||
return ret;
|
||||
|
||||
for(const CArtifact * artifact : artType->constituentOf)
|
||||
for(const auto * artifact : artType->constituentOf)
|
||||
{
|
||||
assert(artifact->constituents);
|
||||
bool possible = true;
|
||||
|
||||
for(const CArtifact * constituent : *artifact->constituents) //check if all constituents are available
|
||||
for(const auto * constituent : *artifact->constituents) //check if all constituents are available
|
||||
{
|
||||
const bool noBackpack = false;
|
||||
const bool notAlreadyAssembled = false;
|
||||
|
||||
if(!h->hasArt(constituent->id, true, noBackpack, notAlreadyAssembled)) //constituent must be equipped
|
||||
if(equipped)
|
||||
{
|
||||
possible = false;
|
||||
break;
|
||||
// Search for equipped arts
|
||||
if (!h->hasArt(constituent->id, true, false, false))
|
||||
{
|
||||
possible = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search in backpack
|
||||
if(!h->hasArtBackpack(constituent->id))
|
||||
{
|
||||
possible = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1195,22 +1205,41 @@ ArtifactPosition CArtifactSet::getArtPos(int aid, bool onlyWorn, bool allowLocke
|
||||
return result.empty() ? ArtifactPosition{ArtifactPosition::PRE_FIRST} : result[0];
|
||||
}
|
||||
|
||||
ArtifactPosition CArtifactSet::getArtBackpackPos(int aid) const
|
||||
{
|
||||
const auto result = getBackpackArtPositions(aid);
|
||||
return result.empty() ? ArtifactPosition{ArtifactPosition::PRE_FIRST} : result[0];
|
||||
}
|
||||
|
||||
std::vector<ArtifactPosition> CArtifactSet::getAllArtPositions(int aid, bool onlyWorn, bool allowLocked, bool getAll) const
|
||||
{
|
||||
std::vector<ArtifactPosition> result;
|
||||
for(auto i = artifactsWorn.cbegin(); i != artifactsWorn.cend(); i++)
|
||||
if(i->second.artifact->artType->id == aid && (allowLocked || !i->second.locked))
|
||||
result.push_back(i->first);
|
||||
for(auto & slotInfo : artifactsWorn)
|
||||
if(slotInfo.second.artifact->artType->id == aid && (allowLocked || !slotInfo.second.locked))
|
||||
result.push_back(slotInfo.first);
|
||||
|
||||
if(onlyWorn)
|
||||
return result;
|
||||
if(!getAll && !result.empty())
|
||||
return result;
|
||||
|
||||
for(int i = 0; i < artifactsInBackpack.size(); i++)
|
||||
if(artifactsInBackpack[i].artifact->artType->id == aid)
|
||||
result.push_back(ArtifactPosition(GameConstants::BACKPACK_START + i));
|
||||
auto backpackPositions = getBackpackArtPositions(aid);
|
||||
result.insert(result.end(), backpackPositions.begin(), backpackPositions.end());
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<ArtifactPosition> CArtifactSet::getBackpackArtPositions(int aid) const
|
||||
{
|
||||
std::vector<ArtifactPosition> result;
|
||||
|
||||
si32 backpackPosition = GameConstants::BACKPACK_START;
|
||||
for(auto & artInfo : artifactsInBackpack)
|
||||
{
|
||||
auto * art = artInfo.getArt();
|
||||
if(art && art->artType->id == aid)
|
||||
result.emplace_back(backpackPosition);
|
||||
backpackPosition++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1249,6 +1278,11 @@ bool CArtifactSet::hasArt(
|
||||
return getArtPosCount(aid, onlyWorn, searchBackpackAssemblies, allowLocked) > 0;
|
||||
}
|
||||
|
||||
bool CArtifactSet::hasArtBackpack(ui32 aid) const
|
||||
{
|
||||
return getBackpackArtPositions(aid).size() > 0;
|
||||
}
|
||||
|
||||
unsigned CArtifactSet::getArtPosCount(int aid, bool onlyWorn, bool searchBackpackAssemblies, bool allowLocked) const
|
||||
{
|
||||
const auto allPositions = getAllArtPositions(aid, onlyWorn, allowLocked, true);
|
||||
@ -1536,4 +1570,9 @@ DLL_LINKAGE bool ArtifactUtils::checkSpellbookIsNeeded(const CGHeroInstance * he
|
||||
return false;
|
||||
}
|
||||
|
||||
DLL_LINKAGE bool ArtifactUtils::isSlotBackpack(ArtifactPosition slot)
|
||||
{
|
||||
return slot >= GameConstants::BACKPACK_START;
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -163,7 +163,7 @@ public:
|
||||
/// of itself, additionally truth is returned for constituents of combined arts
|
||||
virtual bool isPart(const CArtifactInstance *supposedPart) const;
|
||||
|
||||
std::vector<const CArtifact *> assemblyPossibilities(const CArtifactSet *h) const;
|
||||
std::vector<const CArtifact *> assemblyPossibilities(const CArtifactSet * h, bool equipped) const;
|
||||
void move(ArtifactLocation src, ArtifactLocation dst);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
@ -329,13 +329,16 @@ public:
|
||||
/// (if more than one such artifact lower ID is returned)
|
||||
ArtifactPosition getArtPos(int aid, bool onlyWorn = true, bool allowLocked = true) const;
|
||||
ArtifactPosition getArtPos(const CArtifactInstance *art) const;
|
||||
ArtifactPosition getArtBackpackPos(int aid) const;
|
||||
std::vector<ArtifactPosition> getAllArtPositions(int aid, bool onlyWorn, bool allowLocked, bool getAll) const;
|
||||
std::vector<ArtifactPosition> getBackpackArtPositions(int aid) const;
|
||||
const CArtifactInstance *getArtByInstanceId(ArtifactInstanceID artInstId) const;
|
||||
/// Search for constituents of assemblies in backpack which do not have an ArtifactPosition
|
||||
const CArtifactInstance *getHiddenArt(int aid) const;
|
||||
const CCombinedArtifactInstance *getAssemblyByConstituent(int aid) const;
|
||||
/// Checks if hero possess artifact of given id (either in backack or worn)
|
||||
bool hasArt(ui32 aid, bool onlyWorn = false, bool searchBackpackAssemblies = false, bool allowLocked = true) const;
|
||||
bool hasArtBackpack(ui32 aid) const;
|
||||
bool isPositionFree(ArtifactPosition pos, bool onlyLockCheck = false) const;
|
||||
unsigned getArtPosCount(int aid, bool onlyWorn = true, bool searchBackpackAssemblies = true, bool allowLocked = true) const;
|
||||
|
||||
@ -386,6 +389,7 @@ namespace ArtifactUtils
|
||||
DLL_LINKAGE std::vector<ArtifactPosition> unmovablePositions(); // TODO: Make this constexpr when the toolset is upgraded
|
||||
DLL_LINKAGE bool isArtRemovable(const std::pair<ArtifactPosition, ArtSlotInfo> & slot);
|
||||
DLL_LINKAGE bool checkSpellbookIsNeeded(const CGHeroInstance * heroPtr, ArtifactID artID, ArtifactPosition slot);
|
||||
DLL_LINKAGE bool isSlotBackpack(ArtifactPosition slot);
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -1089,7 +1089,7 @@ DLL_LINKAGE void EraseArtifact::applyGs(CGameState *gs)
|
||||
DLL_LINKAGE void MoveArtifact::applyGs(CGameState * gs)
|
||||
{
|
||||
CArtifactInstance * art = src.getArt();
|
||||
if(dst.slot < GameConstants::BACKPACK_START)
|
||||
if(!ArtifactUtils::isSlotBackpack(dst.slot))
|
||||
assert(!dst.getArt());
|
||||
|
||||
art->move(src, dst);
|
||||
@ -1114,7 +1114,7 @@ DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs)
|
||||
// so all the following indices will be affected. Thus, we need to update
|
||||
// the subsequent artifact slots to account for that
|
||||
auto srcPos = slot.srcPos;
|
||||
if((srcPos >= GameConstants::BACKPACK_START) && (operation != EBulkArtsOp::BULK_PUT))
|
||||
if(ArtifactUtils::isSlotBackpack(srcPos) && (operation != EBulkArtsOp::BULK_PUT))
|
||||
{
|
||||
srcPos = ArtifactPosition(srcPos.num - numBackpackArtifactsMoved);
|
||||
}
|
||||
@ -1167,26 +1167,36 @@ DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs)
|
||||
|
||||
DLL_LINKAGE void AssembledArtifact::applyGs(CGameState *gs)
|
||||
{
|
||||
CArtifactSet *artSet = al.getHolderArtSet();
|
||||
CArtifactSet * artSet = al.getHolderArtSet();
|
||||
const CArtifactInstance *transformedArt = al.getArt();
|
||||
assert(transformedArt);
|
||||
assert(vstd::contains(transformedArt->assemblyPossibilities(artSet), builtArt));
|
||||
bool combineEquipped = !ArtifactUtils::isSlotBackpack(al.slot);
|
||||
assert(vstd::contains(transformedArt->assemblyPossibilities(artSet, combineEquipped), builtArt));
|
||||
UNUSED(transformedArt);
|
||||
|
||||
auto combinedArt = new CCombinedArtifactInstance(builtArt);
|
||||
gs->map->addNewArtifactInstance(combinedArt);
|
||||
//retrieve all constituents
|
||||
// Retrieve all constituents
|
||||
for(const CArtifact * constituent : *builtArt->constituents)
|
||||
{
|
||||
ArtifactPosition pos = artSet->getArtPos(constituent->id);
|
||||
ArtifactPosition pos = combineEquipped ? artSet->getArtPos(constituent->id, true, false) :
|
||||
artSet->getArtBackpackPos(constituent->id);
|
||||
assert(pos >= 0);
|
||||
CArtifactInstance *constituentInstance = artSet->getArt(pos);
|
||||
CArtifactInstance * constituentInstance = artSet->getArt(pos);
|
||||
|
||||
//move constituent from hero to be part of new, combined artifact
|
||||
constituentInstance->removeFrom(ArtifactLocation(al.artHolder, pos));
|
||||
combinedArt->addAsConstituent(constituentInstance, pos);
|
||||
if(!vstd::contains(combinedArt->artType->possibleSlots[artSet->bearerType()], al.slot) && vstd::contains(combinedArt->artType->possibleSlots[artSet->bearerType()], pos))
|
||||
al.slot = pos;
|
||||
if(combineEquipped)
|
||||
{
|
||||
if(!vstd::contains(combinedArt->artType->possibleSlots[artSet->bearerType()], al.slot)
|
||||
&& vstd::contains(combinedArt->artType->possibleSlots[artSet->bearerType()], pos))
|
||||
al.slot = pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
al.slot = std::min(al.slot, pos);
|
||||
}
|
||||
}
|
||||
|
||||
//put new combined artifacts
|
||||
|
@ -4031,13 +4031,15 @@ bool CGameHandler::assembleArtifacts (ObjectInstanceID heroID, ArtifactPosition
|
||||
if (!destArtifact)
|
||||
COMPLAIN_RET("assembleArtifacts: there is no such artifact instance!");
|
||||
|
||||
if (assemble)
|
||||
if(assemble)
|
||||
{
|
||||
CArtifact *combinedArt = VLC->arth->objects[assembleTo];
|
||||
if (!combinedArt->constituents)
|
||||
if(!combinedArt->constituents)
|
||||
COMPLAIN_RET("assembleArtifacts: Artifact being attempted to assemble is not a combined artifacts!");
|
||||
if (!vstd::contains(destArtifact->assemblyPossibilities(hero), combinedArt))
|
||||
bool combineEquipped = !ArtifactUtils::isSlotBackpack(artifactSlot);
|
||||
if(!vstd::contains(destArtifact->assemblyPossibilities(hero, combineEquipped), combinedArt))
|
||||
COMPLAIN_RET("assembleArtifacts: It's impossible to assemble requested artifact!");
|
||||
|
||||
|
||||
if(ArtifactUtils::checkSpellbookIsNeeded(hero, assembleTo, artifactSlot))
|
||||
giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
|
||||
|
Loading…
Reference in New Issue
Block a user