1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-28 08:48:48 +02:00

arts altar - arts holder

This commit is contained in:
SoundSSGood 2024-01-12 23:57:19 +02:00
parent 4d0c0f10a9
commit 652f009181
15 changed files with 104 additions and 101 deletions

View File

@ -20,14 +20,12 @@
#include "../../lib/networkPacks/ArtifactLocation.h"
CArtifactsOfHeroAltar::CArtifactsOfHeroAltar(const Point & position)
: visibleArtSet(ArtBearer::ArtBearer::HERO)
{
init(
std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2),
std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2),
position,
std::bind(&CArtifactsOfHeroAltar::scrollBackpack, this, _1));
pickedArtFromSlot = ArtifactPosition::PRE_FIRST;
// The backpack is in the altar window above and to the right
for(auto & slot : backpack)
@ -41,80 +39,19 @@ CArtifactsOfHeroAltar::~CArtifactsOfHeroAltar()
putBackPickedArtifact();
}
void CArtifactsOfHeroAltar::setHero(const CGHeroInstance * hero)
{
if(hero)
{
visibleArtSet.artifactsWorn = hero->artifactsWorn;
visibleArtSet.artifactsInBackpack = hero->artifactsInBackpack;
CArtifactsOfHeroBase::setHero(hero);
}
}
void CArtifactsOfHeroAltar::updateWornSlots()
{
for(auto place : artWorn)
setSlotData(getArtPlace(place.first), place.first, visibleArtSet);
}
void CArtifactsOfHeroAltar::updateBackpackSlots()
{
for(auto artPlace : backpack)
setSlotData(getArtPlace(artPlace->slot), artPlace->slot, visibleArtSet);
}
void CArtifactsOfHeroAltar::scrollBackpack(int offset)
{
CArtifactsOfHeroBase::scrollBackpackForArtSet(offset, visibleArtSet);
CArtifactsOfHeroBase::scrollBackpackForArtSet(offset, *curHero);
redraw();
}
void CArtifactsOfHeroAltar::pickUpArtifact(CArtPlace & artPlace)
{
if(const auto art = artPlace.getArt())
{
pickedArtFromSlot = artPlace.slot;
artPlace.setArtifact(nullptr);
deleteFromVisible(art);
if(ArtifactUtils::isSlotBackpack(pickedArtFromSlot))
pickedArtFromSlot = curHero->getSlotByInstance(art);
assert(pickedArtFromSlot != ArtifactPosition::PRE_FIRST);
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, pickedArtFromSlot), ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS));
}
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, artPlace.slot),
ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS));
}
void CArtifactsOfHeroAltar::swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc)
{
LOCPLINT->cb->swapArtifacts(srcLoc, dstLoc);
const auto pickedArtInst = curHero->getArt(ArtifactPosition::TRANSITION_POS);
assert(pickedArtInst);
visibleArtSet.putArtifact(dstLoc.slot, const_cast<CArtifactInstance*>(pickedArtInst));
}
void CArtifactsOfHeroAltar::pickedArtMoveToAltar(const ArtifactPosition & slot)
{
if(ArtifactUtils::isSlotBackpack(slot) || ArtifactUtils::isSlotEquipment(slot) || slot == ArtifactPosition::TRANSITION_POS)
{
assert(curHero->getSlot(slot)->getArt());
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, slot), ArtifactLocation(curHero->id, pickedArtFromSlot));
pickedArtFromSlot = ArtifactPosition::PRE_FIRST;
}
}
void CArtifactsOfHeroAltar::deleteFromVisible(const CArtifactInstance * artInst)
{
const auto slot = visibleArtSet.getSlotByInstance(artInst);
visibleArtSet.removeArtifact(slot);
if(ArtifactUtils::isSlotBackpack(slot))
{
scrollBackpackForArtSet(0, visibleArtSet);
}
else
{
for(const auto & part : artInst->getPartsInfo())
{
if(part.slot != ArtifactPosition::PRE_FIRST)
getArtPlace(part.slot)->setArtifact(nullptr);
}
}
}

View File

@ -17,17 +17,10 @@ class CArtifactsOfHeroAltar : public CArtifactsOfHeroBase
{
public:
std::set<const CArtifactInstance*> artifactsOnAltar;
ArtifactPosition pickedArtFromSlot;
CArtifactFittingSet visibleArtSet;
CArtifactsOfHeroAltar(const Point & position);
~CArtifactsOfHeroAltar();
void setHero(const CGHeroInstance * hero) override;
void updateWornSlots() override;
void updateBackpackSlots() override;
void scrollBackpack(int offset) override;
void pickUpArtifact(CArtPlace & artPlace);
void swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc);
void pickedArtMoveToAltar(const ArtifactPosition & slot);
void deleteFromVisible(const CArtifactInstance * artInst);
};

View File

@ -31,6 +31,11 @@ CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance *
{
OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
assert(market);
auto altarObj = dynamic_cast<const CGArtifactsAltar*>(market);
altarId = altarObj->id;
altarArtifacts = altarObj;
deal = std::make_shared<CButton>(dealButtonPos, AnimationPath::builtin("ALTSACR.DEF"),
CGI->generaltexth->zelp[585], [this]() {CAltarArtifacts::makeDeal(); });
labels.emplace_back(std::make_shared<CLabel>(450, 34, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[477]));
@ -117,11 +122,11 @@ void CAltarArtifacts::sacrificeAll()
void CAltarArtifacts::sacrificeBackpack()
{
while(!arts->visibleArtSet.artifactsInBackpack.empty())
/*while (!arts->visibleArtSet.artifactsInBackpack.empty())
{
if(!putArtOnAltar(nullptr, arts->visibleArtSet.artifactsInBackpack[0].artifact))
break;
};
};*/
calcExpAltarForHero();
}
@ -192,20 +197,21 @@ bool CAltarArtifacts::putArtOnAltar(std::shared_ptr<CTradeableItem> altarSlot, c
void CAltarArtifacts::onSlotClickPressed(const std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSlot)
{
const auto pickedArtInst = arts->getPickedArtifact();
if(pickedArtInst)
if(const auto pickedArtInst = arts->getPickedArtifact())
{
arts->pickedArtMoveToAltar(ArtifactPosition::TRANSITION_POS);
moveArtToAltar(newSlot, pickedArtInst);
if(pickedArtInst->canBePutAt(altarArtifacts))
{
LOCPLINT->cb->swapArtifacts(ArtifactLocation(arts->getHero()->id, ArtifactPosition::TRANSITION_POS),
ArtifactLocation(altarId, ArtifactPosition::ALTAR));
moveArtToAltar(newSlot, pickedArtInst);
}
}
else if(const CArtifactInstance * art = newSlot->getArtInstance())
{
const auto hero = arts->getHero();
const auto slot = hero->getSlotByInstance(art);
const auto slot = altarArtifacts->getSlotByInstance(art);
assert(slot != ArtifactPosition::PRE_FIRST);
LOCPLINT->cb->swapArtifacts(ArtifactLocation(hero->id, slot),
LOCPLINT->cb->swapArtifacts(ArtifactLocation(altarId, slot),
ArtifactLocation(hero->id, ArtifactPosition::TRANSITION_POS));
arts->pickedArtFromSlot = slot;
arts->artifactsOnAltar.erase(art);
newSlot->setID(-1);
newSlot->subtitle.clear();

View File

@ -25,6 +25,8 @@ public:
std::shared_ptr<CArtifactsOfHeroAltar> getAOHset() const;
private:
ObjectInstanceID altarId;
const CArtifactSet * altarArtifacts;
std::shared_ptr<CArtPlace> selectedArt;
std::shared_ptr<CLabel> selectedCost;
std::shared_ptr<CButton> sacrificeBackpackButton;

View File

@ -151,11 +151,16 @@ DLL_LINKAGE bool ArtifactUtils::isSlotEquipment(const ArtifactPosition & slot)
DLL_LINKAGE bool ArtifactUtils::isBackpackFreeSlots(const CArtifactSet * target, const size_t reqSlots)
{
const auto backpackCap = VLC->settings()->getInteger(EGameSettings::HEROES_BACKPACK_CAP);
if(backpackCap < 0)
return true;
if(target->bearerType() == ArtBearer::HERO)
{
const auto backpackCap = VLC->settings()->getInteger(EGameSettings::HEROES_BACKPACK_CAP);
if(backpackCap < 0)
return true;
else
return target->artifactsInBackpack.size() + reqSlots <= backpackCap;
}
else
return target->artifactsInBackpack.size() + reqSlots <= backpackCap;
return false;
}
DLL_LINKAGE std::vector<const CArtifact*> ArtifactUtils::assemblyPossibilities(

View File

@ -181,7 +181,7 @@ bool CArtifact::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, b
{
auto simpleArtCanBePutAt = [this](const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) -> bool
{
if(ArtifactUtils::isSlotBackpack(slot))
if(artSet->bearerType() == ArtBearer::HERO && ArtifactUtils::isSlotBackpack(slot))
{
if(isBig() || (!assumeDestRemoved && !ArtifactUtils::isBackpackFreeSlots(artSet)))
return false;
@ -258,6 +258,7 @@ CArtifact::CArtifact()
possibleSlots[ArtBearer::HERO]; //we want to generate map entry even if it will be empty
possibleSlots[ArtBearer::CREATURE]; //we want to generate map entry even if it will be empty
possibleSlots[ArtBearer::COMMANDER];
possibleSlots[ArtBearer::ALTAR].push_back(ArtifactPosition::ALTAR);
}
//This destructor should be placed here to avoid side effects
@ -906,6 +907,9 @@ const ArtSlotInfo * CArtifactSet::getSlot(const ArtifactPosition & pos) const
bool CArtifactSet::isPositionFree(const ArtifactPosition & pos, bool onlyLockCheck) const
{
if(bearerType() == ArtBearer::ALTAR)
return artifactsInBackpack.size() < 22;
if(const ArtSlotInfo *s = getSlot(pos))
return (onlyLockCheck || !s->artifact) && !s->locked;

View File

@ -30,7 +30,8 @@ class JsonSerializeFormat;
#define ART_BEARER_LIST \
ART_BEARER(HERO)\
ART_BEARER(CREATURE)\
ART_BEARER(COMMANDER)
ART_BEARER(COMMANDER)\
ART_BEARER(ALTAR)
namespace ArtBearer
{

View File

@ -18,6 +18,7 @@
#include "mapObjects/CGHeroInstance.h"
#include "mapObjects/CGTownInstance.h"
#include "mapObjects/MiscObjects.h"
#include "mapObjects/CGMarket.h"
#include "networkPacks/ArtifactLocation.h"
#include "CGeneralTextHandler.h"
#include "StartInfo.h" // for StartInfo
@ -970,17 +971,27 @@ const CGObjectInstance * CGameInfoCallback::getObjInstance( ObjectInstanceID oid
CArtifactSet * CGameInfoCallback::getArtSet(const ArtifactLocation & loc) const
{
auto hero = const_cast<CGHeroInstance*>(getHero(loc.artHolder));
if(loc.creature.has_value())
if(auto hero = const_cast<CGHeroInstance*>(getHero(loc.artHolder)))
{
if(loc.creature.value() == SlotID::COMMANDER_SLOT_PLACEHOLDER)
return hero->commander;
if(loc.creature.has_value())
{
if(loc.creature.value() == SlotID::COMMANDER_SLOT_PLACEHOLDER)
return hero->commander;
else
return hero->getStackPtr(loc.creature.value());
}
else
return hero->getStackPtr(loc.creature.value());
{
return hero;
}
}
else if(auto market = dynamic_cast<const CGArtifactsAltar*>(getObj(loc.artHolder, false)))
{
return const_cast<CGArtifactsAltar*>(market);
}
else
{
return hero;
return nullptr;
}
}

View File

@ -610,7 +610,10 @@ public:
CREATURE_SLOT = 0,
// Commander
COMMANDER1 = 0, COMMANDER2, COMMANDER3, COMMANDER4, COMMANDER5, COMMANDER6
COMMANDER1 = 0, COMMANDER2, COMMANDER3, COMMANDER4, COMMANDER5, COMMANDER6,
// Altar
ALTAR = BACKPACK_START
};
static_assert(MISC5 < BACKPACK_START, "incorrect number of artifact slots");

View File

@ -238,6 +238,11 @@ CGMarket * MarketInstanceConstructor::createObject(IGameCallback * cb) const
return new CGUniversity(cb);
}
}
else if(marketModes.size() == 2)
{
if(vstd::contains(marketModes, EMarketMode::ARTIFACT_EXP))
return new CGArtifactsAltar(cb);
}
return new CGMarket(cb);
}

View File

@ -113,4 +113,9 @@ void CGUniversity::onHeroVisit(const CGHeroInstance * h) const
cb->showObjectWindow(this, EOpenWindowMode::UNIVERSITY_WINDOW, h, true);
}
ArtBearer::ArtBearer CGArtifactsAltar::bearerType() const
{
return ArtBearer::ALTAR;
}
VCMI_LIB_NAMESPACE_END

View File

@ -11,6 +11,7 @@
#include "CGObjectInstance.h"
#include "IMarket.h"
#include "../CArtHandler.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -80,4 +81,18 @@ public:
}
};
class DLL_LINKAGE CGArtifactsAltar : public CGMarket, public CArtifactSet
{
public:
using CGMarket::CGMarket;
ArtBearer::ArtBearer bearerType() const override;
template <typename Handler> void serialize(Handler & h)
{
h & static_cast<CGMarket&>(*this);
h & static_cast<CArtifactSet&>(*this);
}
};
VCMI_LIB_NAMESPACE_END

View File

@ -54,6 +54,7 @@ void registerTypesMapObjects(Serializer &s)
s.template registerType<CGObjectInstance, CGMarket>();
s.template registerType<CGMarket, CGBlackMarket>();
s.template registerType<CGMarket, CGUniversity>();
s.template registerType<CGMarket, CGArtifactsAltar>();
s.template registerType<CGObjectInstance, CGHeroPlaceholder>();
s.template registerType<CGObjectInstance, CArmedInstance>(); s.template registerType<CBonusSystemNode, CArmedInstance>(); s.template registerType<CCreatureSet, CArmedInstance>();

View File

@ -2713,17 +2713,17 @@ bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLoca
COMPLAIN_RET("That heroes cannot make any exchange!");
const auto srcArtifact = srcArtSet->getArt(src.slot);
const auto dstArtifact = dstArtSet->getArt(dst.slot);
const bool isDstSlotOccupied = dstArtSet->bearerType() == ArtBearer::ALTAR ? false : dstArtSet->getArt(dst.slot) != nullptr;
const bool isDstSlotBackpack = dstArtSet->bearerType() == ArtBearer::HERO ? ArtifactUtils::isSlotBackpack(dst.slot) : false;
if(srcArtifact == nullptr)
COMPLAIN_RET("No artifact to move!");
if(dstArtifact && getHero(src.artHolder)->getOwner() != getHero(dst.artHolder)->getOwner() && !isDstSlotBackpack)
if(isDstSlotOccupied && getOwner(src.artHolder) != getOwner(dst.artHolder) && !isDstSlotBackpack)
COMPLAIN_RET("Can't touch artifact on hero of another player!");
// Check if src/dest slots are appropriate for the artifacts exchanged.
// Moving to the backpack is always allowed.
if((!srcArtifact || !isDstSlotBackpack) && srcArtifact && !srcArtifact->canBePutAt(dstArtSet, dst.slot, true))
if((!srcArtifact || !isDstSlotBackpack) && !srcArtifact->canBePutAt(dstArtSet, dst.slot, true))
COMPLAIN_RET("Cannot move artifact!");
auto srcSlotInfo = srcArtSet->getSlot(src.slot);
@ -2749,7 +2749,7 @@ bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLoca
ma.dstCreature = dst.creature;
// Check if dst slot is occupied
if(!isDstSlotBackpack && dstArtifact)
if(!isDstSlotBackpack && isDstSlotOccupied)
{
// Previous artifact must be removed
ma.artsPack1.push_back(BulkMoveArtifacts::LinkedSlots(dstSlot, src.slot));
@ -3432,6 +3432,20 @@ bool CGameHandler::isAllowedExchange(ObjectInstanceID id1, ObjectInstanceID id2)
return true;
}
if(o1->ID == Obj::ALTAR_OF_SACRIFICE)
{
const auto visitingHero = getVisitingHero(o1);
const auto thisHero = static_cast<const CGHeroInstance*>(o2);
if(visitingHero == thisHero)
return true;
}
if(o2->ID == Obj::ALTAR_OF_SACRIFICE)
{
const auto visitingHero = getVisitingHero(o2);
const auto thisHero = static_cast<const CGHeroInstance*>(o1);
if(visitingHero == thisHero)
return true;
}
if (o1->ID == Obj::HERO && o2->ID == Obj::HERO)
{
const CGHeroInstance *h1 = static_cast<const CGHeroInstance*>(o1);

View File

@ -134,7 +134,8 @@ void ApplyGhNetPackVisitor::visitGarrisonHeroSwap(GarrisonHeroSwap & pack)
void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & pack)
{
gh.throwIfWrongPlayer(&pack, gh.getOwner(pack.src.artHolder)); //second hero can be ally
if(gh.getHero(pack.src.artHolder))
gh.throwIfWrongPlayer(&pack, gh.getOwner(pack.src.artHolder)); //second hero can be ally
result = gh.moveArtifact(pack.src, pack.dst);
}