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:
parent
4d0c0f10a9
commit
652f009181
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user