From b8a5d0d43011fe78381c00b0d3630b98d5c628c9 Mon Sep 17 00:00:00 2001 From: DjWarmonger Date: Mon, 30 Jan 2012 16:07:52 +0000 Subject: [PATCH] Stack artifacts - part 1 --- CCallback.cpp | 48 +++++++++++++-- CCallback.h | 9 ++- client/GUIClasses.cpp | 71 +++++++++++++++++---- client/GUIClasses.h | 7 ++- lib/CArtHandler.cpp | 133 ++++++++++++++++++++++++++++++---------- lib/CArtHandler.h | 35 ++++++++++- lib/CCreatureSet.h | 9 +-- lib/CGameState.cpp | 1 + lib/GameConstants.h | 8 ++- lib/NetPacks.h | 14 ++++- lib/RegisterTypes.h | 1 + server/CGameHandler.cpp | 51 ++++++++++++--- server/CGameHandler.h | 3 + 13 files changed, 318 insertions(+), 72 deletions(-) diff --git a/CCallback.cpp b/CCallback.cpp index db6ff4339..0bdea91c4 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -127,14 +127,50 @@ bool CCallback::dismissHero(const CGHeroInstance *hero) // return gs->players[player].serial; // } -bool CCallback::swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2) +bool CCallback::swapArtifacts(const IArtifactSetBase * src, ui16 pos1, const IArtifactSetBase * dest, ui16 pos2) { - if(player!=hero1->tempOwner && player!=hero2->tempOwner) - return false; + const CStackInstance * stack1 = dynamic_cast(src); + const CStackInstance * stack2 = dynamic_cast(dest); + const CGHeroInstance * hero1 = dynamic_cast(src); + const CGHeroInstance * hero2 = dynamic_cast(dest); - ExchangeArtifacts ea(hero1->id, hero2->id, pos1, pos2); - sendRequest(&ea); - return true; + ExchangeArtifacts ea; + + if (hero1 && hero2) + { + if(player!=hero1->tempOwner && player!=hero2->tempOwner) //player can exchange artifacts only between his own heroes + return false; + else + { + ExchangeArtifacts ea(hero1->id, hero2->id, pos1, pos2); + sendRequest(&ea); + return true; + } + } + else if (hero1 && stack2) //move artifact from hero to stack + { + ea.hid1 = hero1->id; + ea.s2 = StackLocation(stack2->armyObj, stack2->armyObj->findStack(stack2)); + ea.slot1 = pos1; + ea.slot2 = pos2; + sendRequest(&ea); + return true; + } + else if (stack1 && hero2) //move artifacts from stakc to hero + { + ea.s1 = StackLocation(stack1->armyObj, stack1->armyObj->findStack(stack1)); + ea.hid2 = hero2->id; + ea.slot1 = pos1; + ea.slot2 = pos2; + sendRequest(&ea); + return true; + } + else if (stack1 && stack2) + { + //TODO: merge stacks? + } + else + return false; } /** diff --git a/CCallback.h b/CCallback.h index 28ea9492a..5590f33b1 100644 --- a/CCallback.h +++ b/CCallback.h @@ -13,6 +13,7 @@ * */ +class IArtifactSetBase; class CGHeroInstance; class CGameState; struct CPath; @@ -60,7 +61,8 @@ public: virtual int swapCreatures(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2)=0;//swaps creatures between two possibly different garrisons // TODO: AI-unsafe code - fix it! virtual int mergeStacks(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2)=0;//joins first stack to the second (creatures must be same type) virtual int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2, int val)=0;//split creatures from the first stack - virtual bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2)=0; //swaps artifacts between two given heroes + //virtual bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2)=0; //swaps artifacts between two given heroes + virtual bool swapArtifacts(const IArtifactSetBase * src, ui16 pos1, const IArtifactSetBase * dest, ui16 pos2)=0; virtual bool assembleArtifacts(const CGHeroInstance * hero, ui16 artifactSlot, bool assemble, ui32 assembleTo)=0; virtual bool dismissCreature(const CArmedInstance *obj, int stackPos)=0; virtual void endTurn()=0; @@ -117,7 +119,10 @@ public: int mergeStacks(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2); //first goes to the second int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2, int val); bool dismissHero(const CGHeroInstance * hero); - bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2); + //bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2); + bool swapArtifacts(const IArtifactSetBase * src, ui16 pos1, const IArtifactSetBase * dest, ui16 pos2); + //bool moveArtifact(const CGHeroInstance * hero, ui16 src, const CStackInstance * stack, ui16 dest); // TODO: unify classes + //bool moveArtifact(const CStackInstance * stack, ui16 src , const CGHeroInstance * hero, ui16 dest); // TODO: unify classes bool assembleArtifacts(const CGHeroInstance * hero, ui16 artifactSlot, bool assemble, ui32 assembleTo); bool buildBuilding(const CGTownInstance *town, si32 buildingID); void recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount, si32 level=-1); diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index 22f57507a..10f267558 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -262,14 +262,33 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState) } } } - else //highlight + else //drop artifact or highlight { - if(creature) + bool artSelected = false; + if (CHeroWindow* chw = dynamic_cast(GH.topInt())) //dirty solution { - owner->highlighted = this; + BOOST_FOREACH(CArtifactsOfHero *aoh, chw->artSets) // why they are multiple? + { + if (const CArtifactInstance *art = aoh->commonInfo->src.art) + { + artSelected = true; + if (art->canBePutAt(ArtifactLocation(myStack, GameConstants::CREATURE_ART))) + { + //TODO : move + break; + } + } + } + } + if (!artSelected) + { + if(creature) + { + owner->highlighted = this; - for(size_t i = 0; isplitButtons.size(); i++) - owner->splitButtons[i]->block(false); + for(size_t i = 0; isplitButtons.size(); i++) + owner->splitButtons[i]->block(false); + } } redraw(); refr = true; @@ -297,6 +316,7 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg { //assert(Creature == CGI->creh->creatures[Creature->idNumber]); active = false; + highlight = false; upg = Upg; ID = IID; myStack = Creature; @@ -334,7 +354,11 @@ void CGarrisonSlot::showAll(SDL_Surface * to) if((owner->highlighted==this) || (owner->splitting && owner->highlighted->creature == creature)) { - blitAt(imgs[-1],pos,to); + highlight = true; + } + { + if (highlight) + blitAt(imgs[-1],pos,to); } } else//empty slot @@ -2700,7 +2724,7 @@ void CTradeWindow::artifactSelected(CArtPlace *slot) { assert(mode == EMarketMode::ARTIFACT_RESOURCE); items[1][0]->setArtInstance(slot->ourArt); - if(slot->ourArt) + if(slot->ourArt && slot->ourArt->id >= 0) hLeft = items[1][0]; else hLeft = NULL; @@ -4813,6 +4837,21 @@ void CArtifactsOfHero::markPossibleSlots(const CArtifactInstance* art) BOOST_FOREACH(CArtifactsOfHero *aoh, commonInfo->participants) BOOST_FOREACH(CArtPlace *place, aoh->artWorn) place->marked = art->canBePutAt(ArtifactLocation(aoh->curHero, place->slotID), true); + + if (CHeroWindow* chw = dynamic_cast(GH.topInt())) + { + //FIXME: garrison window has two rows of cretaures :? + BOOST_FOREACH (CGarrisonSlot *g, chw->garr->slotsDown) + { + if (g->myStack) + if (art->canBePutAt(ArtifactLocation(g->myStack, GameConstants::CREATURE_ART), false)); + g->highlight = true; + } + } + else if(CExchangeWindow* cew = dynamic_cast(GH.topInt())) + { + //TODO + } safeRedraw(); } @@ -5012,10 +5051,10 @@ void CArtifactsOfHero::safeRedraw() void CArtifactsOfHero::realizeCurrentTransaction() { - assert(commonInfo->src.AOH); - assert(commonInfo->dst.AOH); - LOCPLINT->cb->swapArtifacts(commonInfo->src.AOH->curHero, commonInfo->src.slotID, - commonInfo->dst.AOH->curHero, commonInfo->dst.slotID); + assert(commonInfo->src.AOH || commonInfo->src.CAS); + assert(commonInfo->dst.AOH || commonInfo->dst.CAS); + LOCPLINT->cb->swapArtifacts(commonInfo->src.AOH ? (IArtifactSetBase*)commonInfo->src.AOH->curHero : commonInfo->src.CAS, commonInfo->src.slotID, + commonInfo->dst.AOH ? (IArtifactSetBase*)commonInfo->dst.AOH->curHero : commonInfo->dst.CAS, commonInfo->dst.slotID); } void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst) @@ -6273,6 +6312,16 @@ void CArtifactsOfHero::SCommonPart::Artpos::setTo(const CArtPlace *place, bool d art = place->ourArt; } +IArtifactSetBase * CArtifactsOfHero::SCommonPart::Artpos::getArtHolder() +{ + if (AOH) + return (IArtifactSetBase*)AOH; + if (CAS) + return (IArtifactSetBase*)CAS; + tlog2 <<"Warning! Artpos without source\n"; + return NULL; +} + bool CArtifactsOfHero::SCommonPart::Artpos::operator==(const ArtifactLocation &al) const { if(!AOH) diff --git a/client/GUIClasses.h b/client/GUIClasses.h index 5909de70e..9657c2d4a 100644 --- a/client/GUIClasses.h +++ b/client/GUIClasses.h @@ -25,6 +25,7 @@ */ struct ArtifactLocation; +class IArtifactSetBase; class CStackBasicDescriptor; class CBonusSystemNode; class CArtifact; @@ -62,6 +63,7 @@ class CPlayerInterface; class CHeroWindow; class CArtifact; class CArtifactsOfHero; +class CCreatureArtifactSet; class CResDataBar; struct SPuzzleInfo; class CGGarrison; @@ -222,6 +224,7 @@ public: int count; //number of creatures int upg; //0 - up garrison, 1 - down garrison bool active; //TODO: comment me + bool highlight; virtual void hover (bool on); //call-in const CArmedInstance * getObj(); @@ -851,12 +854,14 @@ public: struct Artpos { int slotID; - const CArtifactsOfHero * AOH; + const CArtifactsOfHero *AOH; + const CCreatureArtifactSet *CAS; const CArtifactInstance *art; Artpos(); void clear(); void setTo(const CArtPlace *place, bool dontTakeBackpack); + IArtifactSetBase * getArtHolder(); // returns AOH or CAS bool valid(); bool operator==(const ArtifactLocation &al) const; } src, dst; diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 123f6b828..6e84aa6e6 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -7,6 +7,7 @@ #include "../lib/VCMI_Lib.h" #include "CSpellHandler.h" #include "CObjectHandler.h" +//#include "CCreatureSet.h" #include "NetPacks.h" extern CLodHandler *bitmaph; @@ -195,7 +196,8 @@ CArtHandler::CArtHandler() // War machines are the default big artifacts. for (ui32 i = 3; i <= 6; i++) bigArtifacts.insert(i); - //modableArtifacts = boost::assign::map_list_of(1, 1)(146,3)(147,3)(148,3)(150,3)(151,3)(152,3)(154,3)(156,2); + if (GameConstants::STACK_ARTIFACT) + creatureArtifacts += 141, 142, 143, 156; //basic Wog arts and Warlord's banner } CArtHandler::~CArtHandler() @@ -225,23 +227,6 @@ void CArtHandler::loadArtifacts(bool onlyTxt) for (int i=0; isecond) -// { -// case 1: -// art = new CScroll; -// break; -// case 2: -// art = new CCustomizableArt; -// break; -// case 3: -// art = new CCommanderArt; -// break; -// }; -// } -// else -// art = new CArtifact; CArtifact &nart = *art; nart.id=i; @@ -941,19 +926,24 @@ int CArtifactInstance::firstBackpackSlot(const CGHeroInstance *h) const bool CArtifactInstance::canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved /*= false*/) const { - if(al.slot >= GameConstants::BACKPACK_START) + if (al.hero) { - if(artType->isBig()) - return false; + if(al.slot >= GameConstants::BACKPACK_START) + { + if(artType->isBig()) + return false; - //TODO backpack limit - return true; + //TODO backpack limit + return true; + } + + if(!vstd::contains(artType->possibleSlots, al.slot)) + return false; + + return al.hero->isPositionFree(al.slot, assumeDestRemoved); } - - if(!vstd::contains(artType->possibleSlots, al.slot)) + else return false; - - return al.hero->isPositionFree(al.slot, assumeDestRemoved); } void CArtifactInstance::putAt(CGHeroInstance *h, ui16 slot) @@ -975,6 +965,15 @@ void CArtifactInstance::removeFrom(CGHeroInstance *h, ui16 slot) //TODO delete me? } +void CArtifactInstance::putAt(CStackInstance *s, ui16 slot) +{ + tlog2 <<"Hero artifacts shouldn't be put on creatures!\n"; +} +void CArtifactInstance::removeFrom(CStackInstance *s, ui16 slot) +{ + tlog2 <<"Strange, we try to remove hero artifact from CStackInstance\n"; +} + bool CArtifactInstance::canBeDisassembled() const { return artType->constituents && artType->constituentOf->size(); @@ -1011,16 +1010,36 @@ std::vector CArtifactInstance::assemblyPossibilities(const CG void CArtifactInstance::move(ArtifactLocation &src, ArtifactLocation &dst) { - removeFrom(src.hero, src.slot); - putAt(dst.hero, dst.slot); - if (artType->id == 135 && dst.slot == ArtifactPosition::RIGHT_HAND && !dst.hero->hasSpellbook()) //Titan's Thunder creates new spellbook on equip - dst.hero->giveArtifact(0); + if (src.hero) + removeFrom(src.hero, src.slot); + else if (src.stack) + removeFrom(src.stack, src.slot); + else + tlog1 << "No source for moved artifact found!\n"; + + if (dst.hero) + { + putAt(dst.hero, dst.slot); + if (artType->id == 135 && dst.slot == ArtifactPosition::RIGHT_HAND && !dst.hero->hasSpellbook()) //Titan's Thunder creates new spellbook on equip + dst.hero->giveArtifact(0); + } + else if (dst.stack) + putAt(dst.stack, dst.slot); + else + tlog1 << "No destination for moved artifact found!\n"; + + } CArtifactInstance * CArtifactInstance::createNewArtifactInstance(CArtifact *Art) { if(!Art->constituents) - return new CArtifactInstance(Art); + { + if (vstd::contains(VLC->arth->creatureArtifacts, Art->id)) + return new CCreatureArtifactInstance(Art); + else + return new CArtifactInstance(Art); + } else { CCombinedArtifactInstance * ret = new CCombinedArtifactInstance(Art); @@ -1233,6 +1252,56 @@ bool CCombinedArtifactInstance::ConstituentInfo::operator==(const ConstituentInf { return art == rhs.art && slot == rhs.slot; } +CCreatureArtifactInstance::CCreatureArtifactInstance() +{ + init(); +} + +CCreatureArtifactInstance::CCreatureArtifactInstance(CArtifact *Art) +{ + init(); + setType(Art); +} + +bool CCreatureArtifactInstance::isPart(const CArtifactInstance *supposedPart) const +{ + return false; //TODO: any other proposals? +} + +std::string CCreatureArtifactInstance::nodeName() const +{ + return "Creature artifact instance of " + (artType ? artType->Name() : std::string("uninitialized")) + " type"; +} + +bool CCreatureArtifactInstance::canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved /*= false*/) const +{ + if (al.stack) + { + return true; //all artifacts should fit on creature + } + else if(al.slot >= GameConstants::BACKPACK_START) + { //TODO backpack limit? + return true; + } + return false; //hero can't wear creature art +} + +void CCreatureArtifactInstance::putAt(CStackInstance *s, ui16 slot) +{ + assert(canBePutAt(ArtifactLocation(s, slot))); + + s->setNewArtSlot(slot, this, false); + if(slot == GameConstants::CREATURE_ART) + s->attachTo(this); +} + +void CCreatureArtifactInstance::removeFrom(CStackInstance *s, ui16 slot) +{ + assert(s->CCreatureArtifactSet::getArt(slot) == this); + s->eraseArtSlot(slot); + if(slot == GameConstants::CREATURE_ART) //we remove worn artifact + s->detachFrom(this); +} const CArtifactInstance* IArtifactSetBase::getArt(ui16 pos, bool excludeLocked) const { diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index 5c9be27e3..50b205094 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -16,6 +16,8 @@ class CDefHandler; class CArtifact; class CGHeroInstance; +class CStackInstance; +//class CCreatureArtifactSet; struct ArtifactLocation; namespace ArtifactPosition @@ -75,7 +77,7 @@ public: //CArtifactInstance(int aid); - std::string nodeName() const OVERRIDE; + virtual std::string nodeName() const OVERRIDE; void deserializationFix(); void setType(CArtifact *Art); @@ -87,6 +89,8 @@ public: virtual bool canBeDisassembled() const; virtual void putAt(CGHeroInstance *h, ui16 slot); virtual void removeFrom(CGHeroInstance *h, ui16 slot); + virtual void putAt(CStackInstance *s, ui16 slot); + virtual void removeFrom(CStackInstance *s, ui16 slot); virtual bool isPart(const CArtifactInstance *supposedPart) const; //checks if this a part of this artifact: artifact instance is a part of itself, additionally truth is returned for consituents of combined arts std::vector assemblyPossibilities(const CGHeroInstance *h) const; @@ -147,6 +151,30 @@ public: } }; +class DLL_LINKAGE CCreatureArtifactInstance : public CArtifactInstance +{ + CCreatureArtifactInstance(CArtifact *Art); +public: + + bool canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved = false) const OVERRIDE; + void putAt(CStackInstance *s, ui16 slot) OVERRIDE; + void removeFrom(CStackInstance *s, ui16 slot) OVERRIDE; + bool isPart(const CArtifactInstance *supposedPart) const OVERRIDE; + + std::string nodeName() const OVERRIDE; + + CCreatureArtifactInstance(); + + //void deserializationFix(); ..inherit from CArtifactInstance + + friend class CArtifactInstance; + template void serialize(Handler &h, const int version) + { + h & static_cast(*this); + BONUS_TREE_DESERIALIZATION_FIX + } +}; + // class DLL_LINKAGE IModableArt : public CArtifact //artifact which can have different properties, such as scroll or banner // { //used only for dynamic cast :P // public: @@ -212,7 +240,7 @@ public: std::vector< ConstTransitivePtr > artifacts; std::vector allowedArtifacts; std::set bigArtifacts; // Artifacts that cannot be moved to backpack, e.g. war machines. - //std::map modableArtifacts; //1-scroll, 2-banner, 3-commander art with progressive bonus + std::set creatureArtifacts; // can be held by Stacks void loadArtifacts(bool onlyTxt); void sortArts(); @@ -235,6 +263,7 @@ public: template void serialize(Handler &h, const int version) { h & artifacts & allowedArtifacts & treasures & minors & majors & relics; + h & creatureArtifacts; //if(!h.saving) sortArts(); } }; @@ -299,7 +328,7 @@ public: class DLL_LINKAGE CCreatureArtifactSet : public IArtifactSetBase { ///creature artifacts public: - std::vector artifactsInBackpack; //artifacts carried by creature - 4 max + std::vector artifactsInBackpack; //artifacts carried by creature - 4 max (according to WoG) ArtSlotInfo activeArtifact; //position 0 - Arts::CREATURE_ART ArtSlotInfo &retreiveNewArtSlot(ui16 slot); diff --git a/lib/CCreatureSet.h b/lib/CCreatureSet.h index 88b138a7e..0b151120d 100644 --- a/lib/CCreatureSet.h +++ b/lib/CCreatureSet.h @@ -3,11 +3,12 @@ #include "HeroBonus.h" #include "GameConstants.h" +#include "CArtHandler.h" class CCreature; class CGHeroInstance; class CArmedInstance; - +class CCreatureArtifactSet; class DLL_LINKAGE CStackBasicDescriptor { @@ -25,20 +26,20 @@ public: } }; -class DLL_LINKAGE CStackInstance : public CBonusSystemNode, public CStackBasicDescriptor +class DLL_LINKAGE CStackInstance : public CBonusSystemNode, public CStackBasicDescriptor, public CCreatureArtifactSet { const CArmedInstance *_armyObj; //stack must be part of some army, army must be part of some object public: int idRand; //hlp variable used during loading game -> "id" placeholder for randomization const CArmedInstance * const & armyObj; //stack must be part of some army, army must be part of some object - ui32 experience; //TODO: handle - //TODO: stack artifacts + ui32 experience; template void serialize(Handler &h, const int version) { h & static_cast(*this); h & static_cast(*this); + h & static_cast(*this); h & _armyObj & experience; BONUS_TREE_DESERIALIZATION_FIX } diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 53cc8adde..4925cb542 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -1410,6 +1410,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed ) CGHeroInstance *hero = k->second.heroes[0]; hero->giveArtifact(toGive->id); } + break; } } /****************************TOWNS************************************************/ diff --git a/lib/GameConstants.h b/lib/GameConstants.h index f9df714d7..71d55cd54 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -83,13 +83,17 @@ namespace GameConstants const int WEEKLY_GROWTH = 10; //percent const int AVAILABLE_HEROES_PER_PLAYER = 2; const bool DWELLINGS_ACCUMULATE_CREATURES = false; - const bool STACK_EXP = true; - const bool STACK_ARTIFACT = true; const int SPELLBOOK_GOLD_COST = 500; const ui16 BACKPACK_START = 19; const int ID_CATAPULT = 3, ID_LOCK = 145; const ui16 CREATURE_ART = 0; + + //game modules + const bool STACK_EXP = true; + const bool STACK_ARTIFACT = true; //now toggle for testing + const bool COMMANDERS = false; + const bool MITHRIL = false; } // Enum declarations diff --git a/lib/NetPacks.h b/lib/NetPacks.h index 80d1e50a8..315cbb001 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -845,6 +845,7 @@ typedef si32 TArtPos; struct ArtifactLocation { ConstTransitivePtr hero; + ConstTransitivePtr stack; TArtPos slot; ArtifactLocation() @@ -854,6 +855,13 @@ struct ArtifactLocation ArtifactLocation(const CGHeroInstance *Hero, TArtPos Slot) { hero = const_cast(Hero); //we are allowed here to const cast -> change will go through one of our packages... do not abuse! + stack = NULL; + slot = Slot; + } + ArtifactLocation(const CStackInstance *Stack, TArtPos Slot) + { + stack = const_cast(Stack); //we are allowed here to const cast -> change will go through one of our packages... do not abuse! + hero = NULL; slot = Slot; } DLL_LINKAGE const CArtifactInstance *getArt() const; @@ -861,7 +869,7 @@ struct ArtifactLocation DLL_LINKAGE const ArtSlotInfo *getSlot() const; template void serialize(Handler &h, const int version) { - h & hero & slot; + h & hero & stack & slot; } }; @@ -1746,17 +1754,19 @@ struct GarrisonHeroSwap : public CPackForServer }; struct ExchangeArtifacts : public CPackForServer +//TODO: allow exchange between heroes, stacks and commanders { ExchangeArtifacts(){}; ExchangeArtifacts(si32 H1, si32 H2, ui16 S1, ui16 S2) :hid1(H1),hid2(H2),slot1(S1),slot2(S2){}; si32 hid1, hid2; + StackLocation s1, s2; //for creature stacks ui16 slot1, slot2; bool applyGh(CGameHandler *gh); template void serialize(Handler &h, const int version) { - h & hid1 & hid2 & slot1 & slot2; + h & hid1 & hid2 & s1 & s2 & slot1 & slot2; } }; diff --git a/lib/RegisterTypes.h b/lib/RegisterTypes.h index 1d20a88e3..026ea00d4 100644 --- a/lib/RegisterTypes.h +++ b/lib/RegisterTypes.h @@ -94,6 +94,7 @@ void registerTypes1(Serializer &s) s.template registerType(); s.template registerType(); s.template registerType(); + s.template registerType(); } template diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index d0d49e7c1..03cd2b2e5 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2572,6 +2572,40 @@ bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, u return true; } +bool CGameHandler::moveArtifact(StackLocation s1, StackLocation s2, ui16 srcSlot, ui16 destSlot) +{ + ArtifactLocation src(s1.getStack(), srcSlot), dst(s2.getStack(), destSlot); + moveArtifact(src, dst); + return true; +} + +bool CGameHandler::moveArtifact(si32 srcHeroID, StackLocation s2, ui16 srcSlot, ui16 destSlot) +{ + ArtifactLocation src(getHero(srcHeroID), srcSlot); + ArtifactLocation dst(s2.getStack(), destSlot); + moveArtifact(src, dst); + return true; +} +bool CGameHandler::moveArtifact(StackLocation s1, si32 destHeroID, ui16 srcSlot, ui16 destSlot) +{ + ArtifactLocation src(s1.getStack(), srcSlot); + ArtifactLocation dst(getHero(destHeroID), destSlot); + //hero should not wear stack artifact + vstd::amin(dst.slot, GameConstants::BACKPACK_START + dst.hero->artifactsInBackpack.size()); //put on first free position + moveArtifact(src, dst); + return true; +} + +void CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) +{ + MoveArtifact ma; + ma.src = al1; + ma.dst = al2; + sendAndApply(&ma); +} + + + /** * Assembles or disassembles a combination artifact. * @param heroID ID of hero holding the artifact(s). @@ -5501,21 +5535,20 @@ void CGameHandler::putArtifact(const ArtifactLocation &al, const CArtifactInstan sendAndApply(&pa); } -void CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) -{ - MoveArtifact ma; - ma.src = al1; - ma.dst = al2; - sendAndApply(&ma); -} - void CGameHandler::giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, int pos) { CArtifactInstance *a = NULL; if(!artType->constituents) - a = new CArtifactInstance(); + { + if (vstd::contains(VLC->arth->creatureArtifacts, artType->id)) + a = new CCreatureArtifactInstance(); + else + a = new CArtifactInstance(); + } else + { a = new CCombinedArtifactInstance(); + } a->artType = artType; //*NOT* via settype -> all bonus-related stuff must be done by NewArtifact apply NewArtifact na; diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 5cc6a7079..4ac5f9b98 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -210,6 +210,9 @@ public: bool sellArtifact( const IMarket *m, const CGHeroInstance *h, int aid, int rid); //for artifact merchant selling bool buySecSkill( const IMarket *m, const CGHeroInstance *h, int skill); bool moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, ui16 destSlot); + bool moveArtifact(StackLocation s1, StackLocation s2, ui16 srcSlot, ui16 destSlot); //called when stacks merge + bool moveArtifact(si32 srcHeroID, StackLocation s2, ui16 srcSlot, ui16 destSlot); //equip artifact + bool moveArtifact(StackLocation s1, si32 destHeroID, ui16 srcSlot, ui16 destSlot); //return artifact to backpack bool garrisonSwap(si32 tid); bool upgradeCreature( ui32 objid, ui8 pos, ui32 upgID ); bool recruitCreatures(si32 objid, ui32 crid, ui32 cram, si32 level);