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

Partially redone combined artifacts.

This commit is contained in:
Michał W. Urbańczyk 2011-01-22 03:43:20 +00:00
parent 591ba76f69
commit 3fde9e45df
16 changed files with 291 additions and 48 deletions

View File

@ -103,6 +103,8 @@ public:
//artifacts operations
virtual void artifactPut(const ArtifactLocation &al){};
virtual void artifactRemoved(const ArtifactLocation &al){};
virtual void artifactAssembled(const ArtifactLocation &al){};
virtual void artifactDisassembled(const ArtifactLocation &al){};
virtual void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst){};
virtual void heroCreated(const CGHeroInstance*){};

View File

@ -2176,6 +2176,16 @@ void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const Artifact
aoh->artifactMoved(src, dst);
}
void CPlayerInterface::artifactAssembled(const ArtifactLocation &al)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
}
void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
}
CPlayerInterface::SpellbookLastSetting::SpellbookLastSetting()
{
spellbookLastPageBattle = spellbokLastPageAdvmap = 0;

View File

@ -170,6 +170,8 @@ public:
void artifactPut(const ArtifactLocation &al);
void artifactRemoved(const ArtifactLocation &al);
void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst);
void artifactAssembled(const ArtifactLocation &al);
void artifactDisassembled(const ArtifactLocation &al);
void heroCreated(const CGHeroInstance* hero) OVERRIDE;
void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback) OVERRIDE;

View File

@ -4532,7 +4532,7 @@ CRClickPopupInt::~CRClickPopupInt()
}
CArtPlace::CArtPlace(const CArtifactInstance* Art)
: marked(false), ourArt(Art), picked(false)
: marked(false), ourArt(Art), picked(false), locked(false)
{
}
@ -4647,7 +4647,7 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
void CArtPlace::clickRight(tribool down, bool previousState)
{
if(down && ourArt && !locked() && text.size()) //if there is no description or it's a lock, do nothing ;]
if(down && ourArt && !locked && text.size()) //if there is no description or it's a lock, do nothing ;]
{
if (slotID < 19)
{
@ -4695,7 +4695,7 @@ void CArtPlace::clickRight(tribool down, bool previousState)
*/
void CArtPlace::select ()
{
if (locked())
if (locked)
return;
picked = true;
@ -4741,7 +4741,10 @@ void CArtPlace::deactivate()
void CArtPlace::showAll(SDL_Surface *to)
{
if (ourArt && !picked)
blitAt(graphics->artDefs->ourImages[ourArt->artType->id].bitmap, pos.x, pos.y, to);
{
int graphic = locked ? 145 : ourArt->artType->id;
blitAt(graphics->artDefs->ourImages[graphic].bitmap, pos.x, pos.y, to);
}
if(marked && active)
{
@ -4779,11 +4782,6 @@ CArtPlace::~CArtPlace()
deactivate();
}
bool CArtPlace::locked() const
{
return ourArt && ourArt->id == 145;
}
void CArtPlace::setMeAsDest(bool backpackAsVoid /*= true*/)
{
ourOwner->commonInfo->dst.setTo(this, backpackAsVoid);
@ -4800,7 +4798,7 @@ void CArtPlace::setArtifact(const CArtifactInstance *art)
else
{
text = ourArt->artType->Description();
if (locked()) // Locks should appear as empty.
if (locked) // Locks should appear as empty.
hoverText = CGI->generaltexth->allTexts[507];
else
hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1]) % ourArt->artType->Name());
@ -5113,7 +5111,14 @@ void CArtifactsOfHero::setSlotData(CArtPlace* artPlace, int slotID)
artPlace->picked = false;
artPlace->slotID = slotID;
artPlace->setArtifact(curHero->getArt(slotID));
if(const ArtSlotInfo *asi = curHero->getSlot(slotID))
{
artPlace->setArtifact(asi->artifact);
artPlace->locked = asi->locked;
}
else
artPlace->setArtifact(NULL);
}
/**

View File

@ -925,6 +925,7 @@ public:
bool picked;
bool marked;
bool locked;
CArtifactsOfHero * ourOwner;
const CArtifactInstance * ourArt;
@ -937,7 +938,6 @@ public:
void deactivate();
void showAll(SDL_Surface * to);
bool fitsHere (const CArtifactInstance * art) const; //returns true if given artifact can be placed here
bool locked () const;
void setMeAsDest(bool backpackAsVoid = true);
void setArtifact(const CArtifactInstance *art);

View File

@ -184,6 +184,20 @@ void MoveArtifact::applyCl( CClient *cl )
INTERFACE_CALL_IF_PRESENT(src.hero->tempOwner, artifactMoved, src, dst);
}
void AssembledArtifact::applyCl( CClient *cl )
{
// INTERFACE_CALL_IF_PRESENT(src.hero->tempOwner, artifactMoved, src, dst);
// if(src.hero->tempOwner != dst.hero->tempOwner)
// INTERFACE_CALL_IF_PRESENT(src.hero->tempOwner, artifactMoved, src, dst);
}
void DisassembledArtifact::applyCl( CClient *cl )
{
// INTERFACE_CALL_IF_PRESENT(src.hero->tempOwner, artifactMoved, src, dst);
// if(src.hero->tempOwner != dst.hero->tempOwner)
// INTERFACE_CALL_IF_PRESENT(src.hero->tempOwner, artifactMoved, src, dst);
}
void GiveBonus::applyCl( CClient *cl )
{
switch(who)

View File

@ -547,6 +547,12 @@ t1 & abetw(t1 &a, const t2 &b, const t3 &c) //makes a to fit the range <b, c>
return a;
}
template <typename t1, typename t2, typename t3>
bool isbetw(const t1 &a, const t2 &b, const t3 &c) //checks if a is between b and c
{
return a > b && a < c;
}
template <typename T>
void delNull(T* &ptr) //deleted pointer and sets it to NULL
{

View File

@ -951,13 +951,7 @@ void CArtifactInstance::putAt(CGHeroInstance *h, ui16 slot)
{
assert(canBePutAt(ArtifactLocation(h, slot)));
ArtSlotInfo &asi = slot < Arts::BACKPACK_START
? h->artifactsWorn[slot]
: *h->artifactsInBackpack.insert(h->artifactsInBackpack.begin() + (slot - Arts::BACKPACK_START), ArtSlotInfo());
asi.artifact = this;
asi.locked = false;
h->setNewArtSlot(slot, this, false);
if(slot < Arts::BACKPACK_START)
h->attachTo(this);
}
@ -965,16 +959,9 @@ void CArtifactInstance::putAt(CGHeroInstance *h, ui16 slot)
void CArtifactInstance::removeFrom(CGHeroInstance *h, ui16 slot)
{
assert(h->CArtifactSet::getArt(slot) == this);
h->eraseArtSlot(slot);
if(slot < Arts::BACKPACK_START)
{
h->artifactsWorn.erase(slot);
h->detachFrom(this);
}
else
{
slot -= Arts::BACKPACK_START;
h->artifactsInBackpack.erase(h->artifactsInBackpack.begin() + slot);
}
//TODO delete me?
}
@ -1024,7 +1011,11 @@ CArtifactInstance * CArtifactInstance::createNewArtifactInstance(CArtifact *Art)
if(!Art->constituents)
return new CArtifactInstance(Art);
else
return new CCombinedArtifactInstance(Art);
{
CCombinedArtifactInstance * ret = new CCombinedArtifactInstance(Art);
ret->createConstituents();
return ret;
}
}
CArtifactInstance * CArtifactInstance::createNewArtifactInstance(int aid)
@ -1060,10 +1051,96 @@ void CCombinedArtifactInstance::createConstituents()
BOOST_FOREACH(ui32 a, *artType->constituents)
{
constituentsInfo.push_back(ConstituentInfo(CArtifactInstance::createNewArtifactInstance(a)));
addAsConstituent(CArtifactInstance::createNewArtifactInstance(a), -1);
}
}
void CCombinedArtifactInstance::addAsConstituent(CArtifactInstance *art, int slot)
{
assert(vstd::contains(*artType->constituents, art->artType->id));
assert(art->parents.size() == 1 && art->parents.front() == art->artType);
constituentsInfo.push_back(ConstituentInfo(art, slot));
art->attachTo(this);
}
void CCombinedArtifactInstance::putAt(CGHeroInstance *h, ui16 slot)
{
if(slot >= Arts::BACKPACK_START)
{
CArtifactInstance::putAt(h, slot);
BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo)
ci.slot = -1;
}
else
{
CArtifactInstance *mainConstituent = figureMainConstituent(slot); //it'll be replaced with combined artifact, not a lock
BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo)
{
if(ci.art != mainConstituent)
{
int pos = -1;
if(isbetw(ci.slot, 0, Arts::BACKPACK_START) && ci.art->canBePutAt(ArtifactLocation(h, ci.slot))) //there is a valid suggestion where to place lock
pos = ci.slot;
else
ci.slot = pos = ci.art->firstAvailableSlot(h);
assert(pos < Arts::BACKPACK_START);
h->setNewArtSlot(pos, ci.art, true); //sets as lock
}
else
{
ci.slot = -1;
CArtifactInstance::putAt(h, slot); //puts combined art (this)
}
}
}
}
void CCombinedArtifactInstance::removeFrom(CGHeroInstance *h, ui16 slot)
{
if(slot >= Arts::BACKPACK_START)
{
CArtifactInstance::removeFrom(h, slot);
}
else
{
BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo)
{
if(ci.slot >= 0)
{
h->eraseArtSlot(ci.slot);
ci.slot = -1;
}
else
{
//main constituent
CArtifactInstance::removeFrom(h, slot);
}
}
}
}
CArtifactInstance * CCombinedArtifactInstance::figureMainConstituent(ui16 slot)
{
CArtifactInstance *mainConstituent = NULL; //it'll be replaced with combined artifact, not a lock
BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo)
if(ci.slot == slot)
mainConstituent = ci.art;
if(!mainConstituent)
{
BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo)
{
if(vstd::contains(ci.art->artType->possibleSlots, slot))
{
mainConstituent = ci.art;
}
}
}
return mainConstituent;
}
CCombinedArtifactInstance::ConstituentInfo::ConstituentInfo(CArtifactInstance *Art /*= NULL*/, ui16 Slot /*= -1*/)
{

View File

@ -81,10 +81,10 @@ public:
virtual bool canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved = false) const;
virtual bool canBeDisassembled() const;
std::vector<const CArtifact *> assemblyPossibilities(const CGHeroInstance *h) const;
virtual void putAt(CGHeroInstance *h, ui16 slot);
virtual void removeFrom(CGHeroInstance *h, ui16 slot);
void putAt(CGHeroInstance *h, ui16 slot);
void removeFrom(CGHeroInstance *h, ui16 slot);
std::vector<const CArtifact *> assemblyPossibilities(const CGHeroInstance *h) const;
void move(ArtifactLocation &src, ArtifactLocation &dst);
template <typename Handler> void serialize(Handler &h, const int version)
@ -118,11 +118,17 @@ public:
bool canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved = false) const OVERRIDE;
bool canBeDisassembled() const OVERRIDE;
void putAt(CGHeroInstance *h, ui16 slot) OVERRIDE;
void removeFrom(CGHeroInstance *h, ui16 slot) OVERRIDE;
void createConstituents();
void addAsConstituent(CArtifactInstance *art, int slot);
CArtifactInstance *figureMainConstituent(ui16 slot); //main constituent is replcaed with us (combined art), not lock
CCombinedArtifactInstance();
void createConstituents();
friend class CArtifactInstance;
friend class AssembledArtifact;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CArtifactInstance&>(*this);

View File

@ -6940,6 +6940,10 @@ const CArtifactInstance* CArtifactSet::getArt(ui16 pos) const
return NULL;
}
CArtifactInstance* CArtifactSet::getArt(ui16 pos)
{
return const_cast<CArtifactInstance*>((const_cast<const CArtifactSet*>(this))->getArt(pos));
}
// if(pos<19)
// if(vstd::contains(artifWorn,pos))
// return artifWorn.find(pos)->second;
@ -7023,4 +7027,34 @@ si32 CArtifactSet::getArtTypeId(ui16 pos) const
CArtifactSet::~CArtifactSet()
{
}
ArtSlotInfo & CArtifactSet::retreiveNewArtSlot(ui16 slot)
{
assert(!vstd::contains(artifactsWorn, slot));
ArtSlotInfo &ret = slot < Arts::BACKPACK_START
? artifactsWorn[slot]
: *artifactsInBackpack.insert(artifactsInBackpack.begin() + (slot - Arts::BACKPACK_START), ArtSlotInfo());
return ret;
}
void CArtifactSet::setNewArtSlot(ui16 slot, CArtifactInstance *art, bool locked)
{
ArtSlotInfo &asi = retreiveNewArtSlot(slot);
asi.artifact = art;
asi.locked = locked;
}
void CArtifactSet::eraseArtSlot(ui16 slot)
{
if(slot < Arts::BACKPACK_START)
{
artifactsWorn.erase(slot);
}
else
{
slot -= Arts::BACKPACK_START;
artifactsInBackpack.erase(artifactsInBackpack.begin() + slot);
}
}

View File

@ -265,8 +265,13 @@ public:
std::vector<ArtSlotInfo> artifactsInBackpack; //hero's artifacts from bag
bmap<ui16, ArtSlotInfo> artifactsWorn; //map<position,artifact_id>; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5
ArtSlotInfo &retreiveNewArtSlot(ui16 slot);
void setNewArtSlot(ui16 slot, CArtifactInstance *art, bool locked);
void eraseArtSlot(ui16 slot);
const ArtSlotInfo *getSlot(ui16 pos) const;
const CArtifactInstance* getArt(ui16 pos) const; //NULL - no artifact
CArtifactInstance* getArt(ui16 pos); //NULL - no artifact
si32 getArtPos(int aid, bool onlyWorn = true) const; //looks for equipped artifact with given ID and returns its slot ID or -1 if none(if more than one such artifact lower ID is returned)
si32 getArtPos(const CArtifactInstance *art) const;
bool hasArt(ui32 aid, bool onlyWorn = false) const; //checks if hero possess artifact of given id (either in backack or worn)

View File

@ -746,6 +746,10 @@ struct StackLocation
struct CGarrisonOperationPack : CPackForClient
{
};
struct CArtifactOperationPack : CPackForClient
{
};
struct ChangeStackCount : CGarrisonOperationPack //521
{
@ -856,7 +860,7 @@ struct ArtifactLocation
}
};
struct PutArtifact : CGarrisonOperationPack //526
struct PutArtifact : CArtifactOperationPack //526
{
ArtifactLocation al;
ConstTransitivePtr<CArtifactInstance> art;
@ -870,7 +874,7 @@ struct PutArtifact : CGarrisonOperationPack //526
}
};
struct EraseArtifact : CGarrisonOperationPack //527
struct EraseArtifact : CArtifactOperationPack //527
{
ArtifactLocation al;
@ -883,7 +887,7 @@ struct EraseArtifact : CGarrisonOperationPack //527
}
};
struct MoveArtifact : CGarrisonOperationPack //528
struct MoveArtifact : CArtifactOperationPack //528
{
ArtifactLocation src, dst;
@ -896,6 +900,35 @@ struct MoveArtifact : CGarrisonOperationPack //528
}
};
struct AssembledArtifact : CArtifactOperationPack //529
{
ArtifactLocation al; //where assembly will be put
CArtifact *builtArt;
//std::vector<CArtifactInstance *> constituents;
void applyCl(CClient *cl);
DLL_EXPORT void applyGs(CGameState *gs);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & al & builtArt/* & constituents*/;
}
};
struct DisassembledArtifact : CArtifactOperationPack //530
{
ArtifactLocation al;
void applyCl(CClient *cl);
DLL_EXPORT void applyGs(CGameState *gs);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & al;
}
};
struct NewTurn : public CPackForClient //101
{
enum weekType {NORMAL, DOUBLE_GROWTH, BONUS_GROWTH, DEITYOFFIRE, PLAGUE, CUSTOM, NO_ACTION, NONE};

View File

@ -124,10 +124,10 @@ DLL_EXPORT void ChangeSpells::applyGs( CGameState *gs )
if(learn)
BOOST_FOREACH(ui32 sid, spells)
hero->spells.insert(sid);
hero->spells.insert(sid);
else
BOOST_FOREACH(ui32 sid, spells)
hero->spells.erase(sid);
hero->spells.erase(sid);
}
DLL_EXPORT void SetMana::applyGs( CGameState *gs )
@ -586,8 +586,7 @@ DLL_EXPORT void NewObject::applyGs( CGameState *gs )
DLL_EXPORT void NewArtifact::applyGs( CGameState *gs )
{
assert(!vstd::contains(gs->map->artInstances, art));
art->id = gs->map->artInstances.size();
gs->map->artInstances.push_back(art);
gs->map->addNewArtifactInstance(art);
assert(!art->parents.size());
art->setType(art->artType);
@ -718,10 +717,38 @@ DLL_EXPORT void MoveArtifact::applyGs( CGameState *gs )
CArtifactInstance *a = src.getArt();
if(dst.slot < Arts::BACKPACK_START)
assert(!dst.getArt());
a->move(src, dst);
}
DLL_EXPORT void AssembledArtifact::applyGs( CGameState *gs )
{
CGHeroInstance *h = al.hero;
const CArtifactInstance *transformedArt = al.getArt();
assert(transformedArt);
assert(vstd::contains(transformedArt->assemblyPossibilities(al.hero), builtArt));
CCombinedArtifactInstance *combinedArt = new CCombinedArtifactInstance(builtArt);
//retreive all constituents
BOOST_FOREACH(si32 constituentID, *builtArt->constituents)
{
int pos = h->getArtPos(constituentID);
assert(pos >= 0);
CArtifactInstance *constituentInstance = h->getArt(pos);
//move constituent from hero to be part of new, combined artifact
constituentInstance->removeFrom(h, pos);
combinedArt->addAsConstituent(constituentInstance, pos);
}
//put new combined artifacts
combinedArt->putAt(h, al.slot);
}
DLL_EXPORT void DisassembledArtifact::applyGs( CGameState *gs )
{
}
DLL_EXPORT void SetAvailableArtifacts::applyGs( CGameState *gs )
{
if(id >= 0)

View File

@ -155,6 +155,8 @@ void registerTypes2(Serializer &s)
s.template registerType<PutArtifact>();
s.template registerType<EraseArtifact>();
s.template registerType<MoveArtifact>();
s.template registerType<AssembledArtifact>();
s.template registerType<DisassembledArtifact>();
s.template registerType<SaveGame>();
s.template registerType<SetSelection>();

View File

@ -12,6 +12,7 @@
#include <boost/bind.hpp>
#include <assert.h>
#include "CSpellHandler.h"
#include <boost/foreach.hpp>
/*
* map.cpp, part of VCMI engine
@ -1490,9 +1491,9 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
i+=4;
innerArt = CArtifactInstance::createScroll(VLC->spellh->spells[spellID]);
}
else if(art->ID == 5) //specific artifact
else if(defInfo->id == 5) //specific artifact
{
innerArt = createArt(art->subID);
innerArt = createArt(defInfo->subid);
}
else
{
@ -2084,7 +2085,15 @@ CArtifactInstance * Mapa::createArt(int aid)
else
a = new CArtifactInstance();
this->addNewArtifactInstance(a);
addNewArtifactInstance(a);
if(a->artType && a->artType->constituents) //TODO make it nicer
{
CCombinedArtifactInstance *comb = dynamic_cast<CCombinedArtifactInstance*>(a);
BOOST_FOREACH(CCombinedArtifactInstance::ConstituentInfo &ci, comb->constituentsInfo)
{
addNewArtifactInstance(ci.art);
}
}
return a;
}

View File

@ -2565,13 +2565,24 @@ bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, u
*/
bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assemble, ui32 assembleTo)
{
if (artifactSlot < 0 || artifactSlot > 18) {
complain("Illegal artifact slot.");
return false;
}
CGHeroInstance *hero = gs->getHero(heroID);
const CArtifactInstance *destArtifact = hero->getArt(artifactSlot);
if(!destArtifact)
COMPLAIN_RET("assembleArtifacts: there is no such artifact instance!");
CArtifact *combinedArt = VLC->arth->artifacts[assembleTo];
if(!combinedArt->constituents)
COMPLAIN_RET("assembleArtifacts: Artifact being attempted to assemble is not a combined artifacts!");
if(!vstd::contains(destArtifact->assemblyPossibilities(hero), combinedArt))
COMPLAIN_RET("assembleArtifacts: It's impossible to assemble requested artifact!");
AssembledArtifact aa;
aa.al = ArtifactLocation(hero, artifactSlot);
aa.builtArt = combinedArt;
CCombinedArtifactInstance *assembliedArt = new CCombinedArtifactInstance();
/*
SetHeroArtifacts sha;
sha.hid = heroID;