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

Redid stack artifacts. Broken save compatibility. Added serializer support for boost::variant and sending CStackInstace* over network by implicitly passing IDs. Moved seeds and checksum to StartInfo. Various minor changes.

This commit is contained in:
Michał W. Urbańczyk 2012-04-14 02:20:22 +00:00
parent d55d48b978
commit 722ec55384
31 changed files with 529 additions and 640 deletions

View File

@ -128,51 +128,13 @@ bool CCallback::dismissHero(const CGHeroInstance *hero)
// return gs->players[player].serial; // return gs->players[player].serial;
// } // }
bool CCallback::swapArtifacts(const IArtifactSetBase * src, ui16 pos1, const IArtifactSetBase * dest, ui16 pos2) bool CCallback::swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2)
{ {
const CStackInstance * stack1 = dynamic_cast<const CStackInstance*>(src); ExchangeArtifacts ea;
const CStackInstance * stack2 = dynamic_cast<const CStackInstance*>(dest); ea.src = l1;
const CGHeroInstance * hero1 = dynamic_cast<const CGHeroInstance*>(src); ea.dst = l2;
const CGHeroInstance * hero2 = dynamic_cast<const CGHeroInstance*>(dest); sendRequest(&ea);
return true;
ExchangeArtifacts ea(0,0,0,0);
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?
return false;
}
else
return false;
} }
/** /**

View File

@ -13,7 +13,6 @@
* *
*/ */
class IArtifactSetBase;
class CGHeroInstance; class CGHeroInstance;
class CGameState; class CGameState;
struct CPath; struct CPath;
@ -63,7 +62,7 @@ public:
virtual int mergeOrSwapStacks(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2) =0; //first goes to the second virtual int mergeOrSwapStacks(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2) =0; //first goes to the second
virtual int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2, int val)=0;//split creatures from the first stack 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 swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2)=0;
virtual bool assembleArtifacts(const CGHeroInstance * hero, ui16 artifactSlot, bool assemble, ui32 assembleTo)=0; virtual bool assembleArtifacts(const CGHeroInstance * hero, ui16 artifactSlot, bool assemble, ui32 assembleTo)=0;
virtual bool dismissCreature(const CArmedInstance *obj, int stackPos)=0; virtual bool dismissCreature(const CArmedInstance *obj, int stackPos)=0;
virtual void endTurn()=0; virtual void endTurn()=0;
@ -127,7 +126,7 @@ public:
int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2, int val); int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2, int val);
bool dismissHero(const CGHeroInstance * hero); 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 swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2);
//bool moveArtifact(const CGHeroInstance * hero, ui16 src, const CStackInstance * stack, ui16 dest); // TODO: unify classes //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 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 assembleArtifacts(const CGHeroInstance * hero, ui16 artifactSlot, bool assemble, ui32 assembleTo);

View File

@ -68,6 +68,7 @@
#include <boost/range/algorithm.hpp> #include <boost/range/algorithm.hpp>
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include <boost/unordered_set.hpp> #include <boost/unordered_set.hpp>
#include <boost/variant.hpp>
#ifdef ANDROID #ifdef ANDROID
#include <android/log.h> #include <android/log.h>

View File

@ -121,6 +121,7 @@ CCreatureWindow::CCreatureWindow(const CStackInstance &st, int Type, boost::func
void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode *StackNode, const CGHeroInstance *HeroOwner) void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode *StackNode, const CGHeroInstance *HeroOwner)
{ {
creatureArtifact = NULL; //may be set later
stack = Stack; stack = Stack;
c = stack->type; c = stack->type;
if(!StackNode) if(!StackNode)
@ -264,11 +265,9 @@ void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode *
if (heroOwner) if (heroOwner)
passArtToHero = new CAdventureMapButton(std::string(), std::string(), boost::bind (&CCreatureWindow::scrollArt, this, 0), 437, 148, "OVBUTN1.DEF", SDLK_HOME); passArtToHero = new CAdventureMapButton(std::string(), std::string(), boost::bind (&CCreatureWindow::scrollArt, this, 0), 437, 148, "OVBUTN1.DEF", SDLK_HOME);
} }
if (const CArtifactInstance * art = stack->getArt(GameConstants::CREATURE_ART)) if (creatureArtifact = stack->getArt(ArtifactPosition::CREATURE_SLOT))
blitAt(graphics->artDefs->ourImages[art->id].bitmap, 466, 161, *bitmap); blitAt(graphics->artDefs->ourImages[creatureArtifact->artType->id].bitmap, 466, 100, *bitmap);
} }
else
creatureArtifact = NULL;
} }
if (battleStack) //only during battle if (battleStack) //only during battle
@ -398,7 +397,7 @@ void CCreatureWindow::sliderMoved(int newpos)
void CCreatureWindow::scrollArt(int dir) void CCreatureWindow::scrollArt(int dir)
{ {
//TODO: get next artifact //TODO: get next artifact
creatureArtifact = const_cast<CArtifactInstance*>(stack->getArt(GameConstants::CREATURE_ART)); creatureArtifact = stack->getArt(ArtifactPosition::CREATURE_SLOT);
} }
void CCreatureWindow::passArtifactToHero() void CCreatureWindow::passArtifactToHero()

View File

@ -48,7 +48,7 @@ public:
const CStackInstance *stack; const CStackInstance *stack;
const CBonusSystemNode *stackNode; const CBonusSystemNode *stackNode;
const CGHeroInstance *heroOwner; const CGHeroInstance *heroOwner;
CArtifactInstance *creatureArtifact; //currently worn artifact const CArtifactInstance *creatureArtifact; //currently worn artifact
std::vector<CComponent*> upgResCost; //cost of upgrade (if not possible then empty) std::vector<CComponent*> upgResCost; //cost of upgrade (if not possible then empty)
std::vector<CBonusItem*> bonusItems; std::vector<CBonusItem*> bonusItems;
std::vector<LRClickableAreaWText*> spellEffects; std::vector<LRClickableAreaWText*> spellEffects;

View File

@ -99,6 +99,12 @@ void startGameFromFile(const std::string &fname)
{ {
StartInfo si; StartInfo si;
CLoadFile out(fname); CLoadFile out(fname);
if(!out.sfile || !*out.sfile)
{
tlog1 << "Failed to open startfile, falling back to the main menu!\n";
GH.curInt = new CGPreGame;
return;
}
out >> si; out >> si;
while(GH.topInt()) while(GH.topInt())
GH.popIntTotally(GH.topInt()); GH.popIntTotally(GH.topInt());

View File

@ -333,15 +333,12 @@ void CClient::newGame( CConnection *con, StartInfo *si )
c << myPlayers; c << myPlayers;
ui32 seed, sum; c >> si;
si32 seedPostInit;
c >> si >> sum >> seed >> seedPostInit;
tlog0 <<"\tSending/Getting info to/from the server: "<<tmh.getDiff()<<std::endl; tlog0 <<"\tSending/Getting info to/from the server: "<<tmh.getDiff()<<std::endl;
tlog0 << "\tUsing random seed: "<<seed << std::endl;
gs = const_cast<CGameInfo*>(CGI)->state; gs = const_cast<CGameInfo*>(CGI)->state;
gs->scenarioOps = si; gs->scenarioOps = si;
gs->init(si, sum, seed, seedPostInit); gs->init(si);
tlog0 <<"Initializing GameState (together): "<<tmh.getDiff()<<std::endl; tlog0 <<"Initializing GameState (together): "<<tmh.getDiff()<<std::endl;
if(gs->map) if(gs->map)

View File

@ -189,7 +189,7 @@ public:
void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, int pos) OVERRIDE {}; void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, int pos) OVERRIDE {};
void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) OVERRIDE {}; void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) OVERRIDE {};
void removeArtifact(const ArtifactLocation &al) OVERRIDE {}; void removeArtifact(const ArtifactLocation &al) OVERRIDE {};
void moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) OVERRIDE {}; bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) OVERRIDE {return false;};
void showCompInfo(ShowInInfobox * comp) OVERRIDE {}; void showCompInfo(ShowInInfobox * comp) OVERRIDE {};
void heroVisitCastle(int obj, int heroID) OVERRIDE {}; void heroVisitCastle(int obj, int heroID) OVERRIDE {};

View File

@ -262,25 +262,31 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState)
} }
} }
} }
else //drop artifact or highlight else //highlight or drop artifact
{ {
bool artSelected = false; bool artSelected = false;
if (CHeroWindow* chw = dynamic_cast<CHeroWindow*>(GH.topInt())) //dirty solution if (CWindowWithArtifacts* chw = dynamic_cast<CWindowWithArtifacts*>(GH.topInt())) //dirty solution
{ {
BOOST_FOREACH(CArtifactsOfHero *aoh, chw->artSets) // why they are multiple? const CArtifactsOfHero::SCommonPart *commonInfo = chw->artSets.front()->commonInfo;
if (const CArtifactInstance *art = commonInfo->src.art)
{ {
if (const CArtifactInstance *art = aoh->commonInfo->src.art) const CGHeroInstance *srcHero = commonInfo->src.AOH->getHero();
{ artSelected = true;
artSelected = true; ArtifactLocation src(srcHero, commonInfo->src.slotID);
if (art->canBePutAt(ArtifactLocation(myStack, GameConstants::CREATURE_ART))) ArtifactLocation dst(myStack, ArtifactPosition::CREATURE_SLOT);
{ //equip clicked stack if (art->canBePutAt(dst, true))
LOCPLINT->cb->swapArtifacts(aoh->getHero(), aoh->commonInfo->src.slotID, myStack, GameConstants::CREATURE_ART); { //equip clicked stack
break; if(dst.getArt())
{
//creature can wear only one active artifact
//if we are placing a new one, the old one will be returned to the hero's backpack
LOCPLINT->cb->swapArtifacts(dst, ArtifactLocation(srcHero, dst.getArt()->firstBackpackSlot(srcHero)));
} }
LOCPLINT->cb->swapArtifacts(src, dst);
} }
} }
} }
if (artSelected || creature) if (!artSelected && creature)
{ {
owner->highlighted = this; owner->highlighted = this;
if(creature) if(creature)
@ -315,7 +321,6 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg
{ {
//assert(Creature == CGI->creh->creatures[Creature->idNumber]); //assert(Creature == CGI->creh->creatures[Creature->idNumber]);
active = false; active = false;
highlight = false;
upg = Upg; upg = Upg;
ID = IID; ID = IID;
myStack = Creature; myStack = Creature;
@ -353,11 +358,7 @@ void CGarrisonSlot::showAll(SDL_Surface * to)
if((owner->highlighted==this) if((owner->highlighted==this)
|| (owner->splitting && owner->highlighted->creature == creature)) || (owner->splitting && owner->highlighted->creature == creature))
{ {
highlight = true; blitAt(imgs[-1],pos,to);
}
{
if (highlight)
blitAt(imgs[-1],pos,to);
} }
} }
else//empty slot else//empty slot
@ -2738,7 +2739,7 @@ void CTradeWindow::artifactSelected(CArtPlace *slot)
{ {
assert(mode == EMarketMode::ARTIFACT_RESOURCE); assert(mode == EMarketMode::ARTIFACT_RESOURCE);
items[1][0]->setArtInstance(slot->ourArt); items[1][0]->setArtInstance(slot->ourArt);
if(slot->ourArt && slot->ourArt->id >= 0) if(slot->ourArt)
hLeft = items[1][0]; hLeft = items[1][0];
else else
hLeft = NULL; hLeft = NULL;
@ -3606,7 +3607,7 @@ void CAltarWindow::moveFromSlotToAltar(int slotID, CTradeableItem* altarSlot, co
if(putOnAltar(altarSlot, art)) if(putOnAltar(altarSlot, art))
{ {
if(slotID < GameConstants::BACKPACK_START) if(slotID < GameConstants::BACKPACK_START)
LOCPLINT->cb->swapArtifacts(hero, slotID, hero, freeBackpackSlot); LOCPLINT->cb->swapArtifacts(ArtifactLocation(hero, slotID), ArtifactLocation(hero, freeBackpackSlot));
else else
{ {
arts->commonInfo->src.clear(); arts->commonInfo->src.clear();
@ -4418,7 +4419,7 @@ void CArtPlace::clickRight(tribool down, bool previousState)
{ {
if(down && ourArt && !locked && text.size() && !picked) //if there is no description or it's a lock, do nothing ;] if(down && ourArt && !locked && text.size() && !picked) //if there is no description or it's a lock, do nothing ;]
{ {
if (slotID < 19) if (slotID < GameConstants::BACKPACK_START)
{ {
if(ourOwner->allowedAssembling) if(ourOwner->allowedAssembling)
{ {
@ -4556,7 +4557,7 @@ bool CArtPlace::fitsHere(const CArtifactInstance * art) const
return true; return true;
// Anything can but War Machines can be placed in backpack. // Anything can but War Machines can be placed in backpack.
if (slotID >= 19) if (slotID >= GameConstants::BACKPACK_START)
return !CGI->arth->isBigArtifact(art->id); return !CGI->arth->isBigArtifact(art->id);
return art->canBePutAt(ArtifactLocation(ourOwner->curHero, slotID), true); return art->canBePutAt(ArtifactLocation(ourOwner->curHero, slotID), true);
@ -4812,7 +4813,7 @@ void CArtifactsOfHero::scrollBackpack(int dir)
if (s < artsInBackpack) if (s < artsInBackpack)
{ {
int slotID = 19 + (s + backpackPos)%artsInBackpack; int slotID = GameConstants::BACKPACK_START + (s + backpackPos)%artsInBackpack;
const CArtifactInstance *art = curHero->getArt(slotID); const CArtifactInstance *art = curHero->getArt(slotID);
assert(art); assert(art);
if(!vstd::contains(toOmit, art)) if(!vstd::contains(toOmit, art))
@ -4829,7 +4830,7 @@ void CArtifactsOfHero::scrollBackpack(int dir)
} }
} }
for( ; s - omitedSoFar < backpack.size(); s++) for( ; s - omitedSoFar < backpack.size(); s++)
eraseSlotData(backpack[s-omitedSoFar], 19 + s); eraseSlotData(backpack[s-omitedSoFar], GameConstants::BACKPACK_START + s);
//in artifact merchant selling artifacts we may have highlight on one of backpack artifacts -> market needs update, cause artifact under highlight changed //in artifact merchant selling artifacts we may have highlight on one of backpack artifacts -> market needs update, cause artifact under highlight changed
if(highlightModeCallback) if(highlightModeCallback)
@ -4864,21 +4865,6 @@ void CArtifactsOfHero::markPossibleSlots(const CArtifactInstance* art)
BOOST_FOREACH(CArtPlace *place, aoh->artWorn) BOOST_FOREACH(CArtPlace *place, aoh->artWorn)
place->marked = art->canBePutAt(ArtifactLocation(aoh->curHero, place->slotID), true); place->marked = art->canBePutAt(ArtifactLocation(aoh->curHero, place->slotID), true);
if (CHeroWindow* chw = dynamic_cast<CHeroWindow*>(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<CExchangeWindow*>(GH.topInt()))
{
//TODO
}*/
safeRedraw(); safeRedraw();
} }
@ -4966,7 +4952,7 @@ CArtifactsOfHero::CArtifactsOfHero(std::vector<CArtPlace *> ArtWorn, std::vector
for(size_t s=0; s<backpack.size(); ++s) for(size_t s=0; s<backpack.size(); ++s)
{ {
backpack[s]->ourOwner = this; backpack[s]->ourOwner = this;
eraseSlotData(backpack[s], 19 + s); eraseSlotData(backpack[s], GameConstants::BACKPACK_START + s);
} }
leftArtRoll->callback += boost::bind(&CArtifactsOfHero::scrollBackpack,this,-1); leftArtRoll->callback += boost::bind(&CArtifactsOfHero::scrollBackpack,this,-1);
@ -5077,28 +5063,31 @@ void CArtifactsOfHero::safeRedraw()
void CArtifactsOfHero::realizeCurrentTransaction() void CArtifactsOfHero::realizeCurrentTransaction()
{ {
assert(commonInfo->src.AOH || commonInfo->src.CAS); assert(commonInfo->src.AOH);
assert(commonInfo->dst.AOH || commonInfo->dst.CAS); assert(commonInfo->dst.AOH);
LOCPLINT->cb->swapArtifacts(commonInfo->src.AOH ? (IArtifactSetBase*)commonInfo->src.AOH->curHero : commonInfo->src.CAS, commonInfo->src.slotID, LOCPLINT->cb->swapArtifacts(ArtifactLocation(commonInfo->src.AOH->curHero, commonInfo->src.slotID),
commonInfo->dst.AOH ? (IArtifactSetBase*)commonInfo->dst.AOH->curHero : commonInfo->dst.CAS, commonInfo->dst.slotID); ArtifactLocation(commonInfo->dst.AOH->curHero, commonInfo->dst.slotID));
} }
void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst) void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst)
{ {
if(src.hero == curHero && src.slot >= GameConstants::BACKPACK_START) bool isCurHeroSrc = src.isHolder(curHero),
isCurHeroDst = dst.isHolder(curHero);
if(isCurHeroSrc && src.slot >= GameConstants::BACKPACK_START)
updateSlot(src.slot); updateSlot(src.slot);
if(dst.hero == curHero && dst.slot >= GameConstants::BACKPACK_START) if(isCurHeroDst && dst.slot >= GameConstants::BACKPACK_START)
updateSlot(dst.slot); updateSlot(dst.slot);
if(src.hero == curHero || dst.hero == curHero) //we need to update all slots, artifact might be combined and affect more slots if(isCurHeroSrc || isCurHeroDst) //we need to update all slots, artifact might be combined and affect more slots
updateWornSlots(false); updateWornSlots(false);
if (src.hero != curHero && dst.hero != curHero) if (!src.isHolder(curHero) && !isCurHeroDst)
return; return;
if(commonInfo->src == src) //artifact was taken from us if(commonInfo->src == src) //artifact was taken from us
{ {
//assert(commonInfo->dst == dst || dst.slot == dst.hero->artifactsInBackpack.size() + GameConstants::BACKPACK_START); assert(commonInfo->dst == dst //expected movement from slot ot slot
//FIXME: assertion fails for stack artifacts || dst.slot == dst.getHolderArtSet()->artifactsInBackpack.size() + GameConstants::BACKPACK_START //artifact moved back to backpack (eg. to make place for art we are moving)
|| dst.getHolderArtSet()->bearerType() == ArtBearer::CREATURE);
commonInfo->reset(); commonInfo->reset();
unmarkSlots(); unmarkSlots();
} }
@ -5110,7 +5099,7 @@ void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const Artifact
CArtPlace *ap = NULL; CArtPlace *ap = NULL;
BOOST_FOREACH(CArtifactsOfHero *aoh, commonInfo->participants) BOOST_FOREACH(CArtifactsOfHero *aoh, commonInfo->participants)
{ {
if(aoh->curHero == dst.hero) if(dst.isHolder(aoh->curHero))
{ {
commonInfo->src.AOH = aoh; commonInfo->src.AOH = aoh;
if((ap = aoh->getArtPlace(dst.slot))) if((ap = aoh->getArtPlace(dst.slot)))
@ -5133,7 +5122,7 @@ void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const Artifact
} }
else if(src.slot >= GameConstants::BACKPACK_START && else if(src.slot >= GameConstants::BACKPACK_START &&
src.slot < commonInfo->src.slotID && src.slot < commonInfo->src.slotID &&
src.hero == commonInfo->src.AOH->curHero) //artifact taken from before currently picked one src.isHolder(commonInfo->src.AOH->curHero)) //artifact taken from before currently picked one
{ {
//int fixedSlot = src.hero->getArtPos(commonInfo->src.art); //int fixedSlot = src.hero->getArtPos(commonInfo->src.art);
commonInfo->src.slotID--; commonInfo->src.slotID--;
@ -5157,14 +5146,14 @@ void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const Artifact
if(dst.slot < GameConstants::BACKPACK_START && src.slot - GameConstants::BACKPACK_START < backpackPos) if(dst.slot < GameConstants::BACKPACK_START && src.slot - GameConstants::BACKPACK_START < backpackPos)
shift--; shift--;
if( (src.hero == curHero && src.slot >= GameConstants::BACKPACK_START) if( (isCurHeroSrc && src.slot >= GameConstants::BACKPACK_START)
|| (dst.hero == curHero && dst.slot >= GameConstants::BACKPACK_START) ) || (isCurHeroDst && dst.slot >= GameConstants::BACKPACK_START) )
scrollBackpack(shift); //update backpack slots scrollBackpack(shift); //update backpack slots
} }
void CArtifactsOfHero::artifactRemoved(const ArtifactLocation &al) void CArtifactsOfHero::artifactRemoved(const ArtifactLocation &al)
{ {
if(al.hero == curHero) if(al.isHolder(curHero))
{ {
if(al.slot < GameConstants::BACKPACK_START) if(al.slot < GameConstants::BACKPACK_START)
updateWornSlots(0); updateWornSlots(0);
@ -5191,13 +5180,13 @@ CArtPlace * CArtifactsOfHero::getArtPlace(int slot)
void CArtifactsOfHero::artifactAssembled(const ArtifactLocation &al) void CArtifactsOfHero::artifactAssembled(const ArtifactLocation &al)
{ {
if(al.hero == curHero) if(al.isHolder(curHero))
updateWornSlots(); updateWornSlots();
} }
void CArtifactsOfHero::artifactDisassembled(const ArtifactLocation &al) void CArtifactsOfHero::artifactDisassembled(const ArtifactLocation &al)
{ {
if(al.hero == curHero) if(al.isHolder(curHero))
updateWornSlots(); updateWornSlots();
} }
@ -6323,21 +6312,11 @@ void CArtifactsOfHero::SCommonPart::Artpos::setTo(const CArtPlace *place, bool d
art = place->ourArt; 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 bool CArtifactsOfHero::SCommonPart::Artpos::operator==(const ArtifactLocation &al) const
{ {
if(!AOH) if(!AOH)
return false; return false;
bool ret = al.hero == AOH->curHero && al.slot == slotID; bool ret = al.isHolder(AOH->curHero) && al.slot == slotID;
//assert(al.getArt() == art); //assert(al.getArt() == art);
return ret; return ret;

View File

@ -25,7 +25,6 @@
*/ */
struct ArtifactLocation; struct ArtifactLocation;
class IArtifactSetBase;
class CStackBasicDescriptor; class CStackBasicDescriptor;
class CBonusSystemNode; class CBonusSystemNode;
class CArtifact; class CArtifact;
@ -858,13 +857,11 @@ public:
{ {
int slotID; int slotID;
const CArtifactsOfHero *AOH; const CArtifactsOfHero *AOH;
const CCreatureArtifactSet *CAS;
const CArtifactInstance *art; const CArtifactInstance *art;
Artpos(); Artpos();
void clear(); void clear();
void setTo(const CArtPlace *place, bool dontTakeBackpack); void setTo(const CArtPlace *place, bool dontTakeBackpack);
IArtifactSetBase * getArtHolder(); // returns AOH or CAS
bool valid(); bool valid();
bool operator==(const ArtifactLocation &al) const; bool operator==(const ArtifactLocation &al) const;
} src, dst; } src, dst;

View File

@ -210,30 +210,29 @@ void RebalanceStacks::applyCl( CClient *cl )
void PutArtifact::applyCl( CClient *cl ) void PutArtifact::applyCl( CClient *cl )
{ {
INTERFACE_CALL_IF_PRESENT(al.hero->tempOwner, artifactPut, al); INTERFACE_CALL_IF_PRESENT(al.owningPlayer(), artifactPut, al);
} }
void EraseArtifact::applyCl( CClient *cl ) void EraseArtifact::applyCl( CClient *cl )
{ {
INTERFACE_CALL_IF_PRESENT(al.hero->tempOwner, artifactRemoved, al); INTERFACE_CALL_IF_PRESENT(al.owningPlayer(), artifactRemoved, al);
} }
void MoveArtifact::applyCl( CClient *cl ) void MoveArtifact::applyCl( CClient *cl )
{ {
INTERFACE_CALL_IF_PRESENT(src.hero->tempOwner, artifactMoved, src, dst); INTERFACE_CALL_IF_PRESENT(src.owningPlayer(), artifactMoved, src, dst);
if (src.hero.get() && dst.hero.get()) if(src.owningPlayer() != dst.owningPlayer())
if(src.hero->tempOwner != dst.hero->tempOwner) INTERFACE_CALL_IF_PRESENT(src.owningPlayer(), artifactMoved, src, dst);
INTERFACE_CALL_IF_PRESENT(src.hero->tempOwner, artifactMoved, src, dst);
} }
void AssembledArtifact::applyCl( CClient *cl ) void AssembledArtifact::applyCl( CClient *cl )
{ {
INTERFACE_CALL_IF_PRESENT(al.hero->tempOwner, artifactAssembled, al); INTERFACE_CALL_IF_PRESENT(al.owningPlayer(), artifactAssembled, al);
} }
void DisassembledArtifact::applyCl( CClient *cl ) void DisassembledArtifact::applyCl( CClient *cl )
{ {
INTERFACE_CALL_IF_PRESENT(al.hero->tempOwner, artifactDisassembled, al); INTERFACE_CALL_IF_PRESENT(al.owningPlayer(), artifactDisassembled, al);
} }
void HeroVisit::applyCl( CClient *cl ) void HeroVisit::applyCl( CClient *cl )

View File

@ -7,7 +7,6 @@
#include "../lib/VCMI_Lib.h" #include "../lib/VCMI_Lib.h"
#include "CSpellHandler.h" #include "CSpellHandler.h"
#include "CObjectHandler.h" #include "CObjectHandler.h"
//#include "CCreatureSet.h"
#include "NetPacks.h" #include "NetPacks.h"
extern CLodHandler *bitmaph; extern CLodHandler *bitmaph;
@ -196,8 +195,7 @@ CArtHandler::CArtHandler()
// War machines are the default big artifacts. // War machines are the default big artifacts.
for (ui32 i = 3; i <= 6; i++) for (ui32 i = 3; i <= 6; i++)
bigArtifacts.insert(i); bigArtifacts.insert(i);
if (GameConstants::STACK_ARTIFACT) //modableArtifacts = boost::assign::map_list_of(1, 1)(146,3)(147,3)(148,3)(150,3)(151,3)(152,3)(154,3)(156,2);
creatureArtifacts += 141, 142, 143, 156; //basic Wog arts and Warlord's banner
} }
CArtHandler::~CArtHandler() CArtHandler::~CArtHandler()
@ -233,11 +231,13 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
loadToIt(VLC->generaltexth->artifNames[i],buf,it,4); loadToIt(VLC->generaltexth->artifNames[i],buf,it,4);
loadToIt(pom,buf,it,4); loadToIt(pom,buf,it,4);
nart.price=atoi(pom.c_str()); nart.price=atoi(pom.c_str());
nart.possibleSlots[ArtBearer::HERO]; //we want to generate map entry even if it will be empty
nart.possibleSlots[ArtBearer::CREATURE]; //we want to generate map entry even if it will be empty
for(int j=0;j<slots.size();j++) for(int j=0;j<slots.size();j++)
{ {
loadToIt(pom,buf,it,4); loadToIt(pom,buf,it,4);
if(pom.size() && pom[0]=='x') if(pom.size() && pom[0]=='x')
nart.possibleSlots.push_back(slots[j]); nart.possibleSlots[ArtBearer::HERO].push_back(slots[j]);
} }
loadToIt(pom,buf,it,4); loadToIt(pom,buf,it,4);
nart.aClass = classes[pom[0]]; nart.aClass = classes[pom[0]];
@ -739,9 +739,19 @@ void CArtHandler::addBonuses()
giveArtBonus(140, Bonus::GENERATE_RESOURCE, +4, Res::CRYSTAL); giveArtBonus(140, Bonus::GENERATE_RESOURCE, +4, Res::CRYSTAL);
giveArtBonus(140, Bonus::GENERATE_RESOURCE, +4, Res::GEMS); giveArtBonus(140, Bonus::GENERATE_RESOURCE, +4, Res::GEMS);
//Stack artifact test //Stack artifact test
if (GameConstants::STACK_ARTIFACT) if (GameConstants::STACK_ARTIFACT)
{ {
auto makeItCreatureArt = [this](int aid)
{
CArtifact *a = artifacts[aid];
a->possibleSlots[ArtBearer::CREATURE].push_back(ArtifactPosition::CREATURE_SLOT);
};
makeItCreatureArt(141);
makeItCreatureArt(142);
makeItCreatureArt(143);
makeItCreatureArt(156);
giveArtBonus(141, Bonus::STACK_HEALTH, +400, -1, Bonus::PERCENT_TO_BASE); //Magic Wans giveArtBonus(141, Bonus::STACK_HEALTH, +400, -1, Bonus::PERCENT_TO_BASE); //Magic Wans
giveArtBonus(142, Bonus::STACK_HEALTH, +400, -1, Bonus::PERCENT_TO_BASE); //Tower Arrow giveArtBonus(142, Bonus::STACK_HEALTH, +400, -1, Bonus::PERCENT_TO_BASE); //Tower Arrow
giveArtBonus(143, Bonus::STACK_HEALTH, +400, -1, Bonus::PERCENT_TO_BASE); //Monster's Power giveArtBonus(143, Bonus::STACK_HEALTH, +400, -1, Bonus::PERCENT_TO_BASE); //Monster's Power
@ -910,11 +920,11 @@ void CArtifactInstance::init()
setNodeType(ARTIFACT_INSTANCE); setNodeType(ARTIFACT_INSTANCE);
} }
int CArtifactInstance::firstAvailableSlot(const CGHeroInstance *h) const int CArtifactInstance::firstAvailableSlot(const CArtifactSet *h) const
{ {
BOOST_FOREACH(ui16 slot, artType->possibleSlots) BOOST_FOREACH(ui16 slot, artType->possibleSlots[h->bearerType()])
{ {
if(canBePutAt(ArtifactLocation(h, slot))) //if(artType->fitsAt(h->artifWorn, slot)) if(canBePutAt(h, slot)) //if(artType->fitsAt(h->artifWorn, slot))
{ {
//we've found a free suitable slot. //we've found a free suitable slot.
return slot; return slot;
@ -925,7 +935,7 @@ int CArtifactInstance::firstAvailableSlot(const CGHeroInstance *h) const
return firstBackpackSlot(h); return firstBackpackSlot(h);
} }
int CArtifactInstance::firstBackpackSlot(const CGHeroInstance *h) const int CArtifactInstance::firstBackpackSlot(const CArtifactSet *h) const
{ {
if(!artType->isBig()) //discard big artifact if(!artType->isBig()) //discard big artifact
return GameConstants::BACKPACK_START + h->artifactsInBackpack.size(); return GameConstants::BACKPACK_START + h->artifactsInBackpack.size();
@ -935,60 +945,51 @@ int CArtifactInstance::firstBackpackSlot(const CGHeroInstance *h) const
bool CArtifactInstance::canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved /*= false*/) const bool CArtifactInstance::canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved /*= false*/) const
{ {
if (al.hero) return canBePutAt(al.getHolderArtSet(), al.slot, assumeDestRemoved);
{ }
if(al.slot >= GameConstants::BACKPACK_START)
{
if(artType->isBig())
return false;
//TODO backpack limit
return true;
}
if(!vstd::contains(artType->possibleSlots, al.slot)) bool CArtifactInstance::canBePutAt(const CArtifactSet *artSet, int slot, bool assumeDestRemoved /*= false*/) const
{
if(slot >= GameConstants::BACKPACK_START)
{
if(artType->isBig())
return false; return false;
return al.hero->isPositionFree(al.slot, assumeDestRemoved); //TODO backpack limit
return true;
} }
else
if(!vstd::contains(artType->possibleSlots[artSet->bearerType()], slot))
return false; return false;
return artSet->isPositionFree(slot, assumeDestRemoved);
} }
void CArtifactInstance::putAt(CGHeroInstance *h, ui16 slot) void CArtifactInstance::putAt(ArtifactLocation &al)
{ {
assert(canBePutAt(ArtifactLocation(h, slot))); assert(canBePutAt(al));
h->setNewArtSlot(slot, this, false); al.getHolderArtSet()->setNewArtSlot(al.slot, this, false);
if(slot < GameConstants::BACKPACK_START) if(al.slot < GameConstants::BACKPACK_START)
h->attachTo(this); al.getHolderNode()->attachTo(this);
} }
void CArtifactInstance::removeFrom(CGHeroInstance *h, ui16 slot) void CArtifactInstance::removeFrom(ArtifactLocation &al)
{ {
assert(h->CArtifactSet::getArt(slot) == this); assert(al.getHolderArtSet()->getArt(al.slot) == this);
h->eraseArtSlot(slot); al.getHolderArtSet()->eraseArtSlot(al.slot);
if(slot < GameConstants::BACKPACK_START) if(al.slot < GameConstants::BACKPACK_START)
h->detachFrom(this); al.getHolderNode()->detachFrom(this);
//TODO delete me? //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 bool CArtifactInstance::canBeDisassembled() const
{ {
return artType->constituents && artType->constituentOf->size(); return artType->constituents && artType->constituentOf->size();
} }
std::vector<const CArtifact *> CArtifactInstance::assemblyPossibilities(const CGHeroInstance *h) const std::vector<const CArtifact *> CArtifactInstance::assemblyPossibilities(const CArtifactSet *h) const
{ {
std::vector<const CArtifact *> ret; std::vector<const CArtifact *> ret;
if(!artType->constituentOf //not a part of combined artifact if(!artType->constituentOf //not a part of combined artifact
@ -1019,30 +1020,14 @@ std::vector<const CArtifact *> CArtifactInstance::assemblyPossibilities(const CG
void CArtifactInstance::move(ArtifactLocation &src, ArtifactLocation &dst) void CArtifactInstance::move(ArtifactLocation &src, ArtifactLocation &dst)
{ {
if (src.hero) removeFrom(src);
removeFrom(src.hero, src.slot); putAt(dst);
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);
else if (dst.stack)
putAt(dst.stack, dst.slot);
else
tlog1 << "No destination for moved artifact found!\n";
} }
CArtifactInstance * CArtifactInstance::createNewArtifactInstance(CArtifact *Art) CArtifactInstance * CArtifactInstance::createNewArtifactInstance(CArtifact *Art)
{ {
if(!Art->constituents) 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 else
{ {
CCombinedArtifactInstance * ret = new CCombinedArtifactInstance(Art); CCombinedArtifactInstance * ret = new CCombinedArtifactInstance(Art);
@ -1077,12 +1062,12 @@ bool CArtifactInstance::isPart(const CArtifactInstance *supposedPart) const
return supposedPart == this; return supposedPart == this;
} }
bool CCombinedArtifactInstance::canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved /*= false*/) const bool CCombinedArtifactInstance::canBePutAt(const CArtifactSet *artSet, int slot, bool assumeDestRemoved /*= false*/) const
{ {
bool canMainArtifactBePlaced = CArtifactInstance::canBePutAt(al, assumeDestRemoved); bool canMainArtifactBePlaced = CArtifactInstance::canBePutAt(artSet, slot, assumeDestRemoved);
if(!canMainArtifactBePlaced) if(!canMainArtifactBePlaced)
return false; //no is no... return false; //no is no...
if(al.slot >= GameConstants::BACKPACK_START) if(slot >= GameConstants::BACKPACK_START)
return true; //we can always remove combined art to the backapck return true; //we can always remove combined art to the backapck
@ -1093,16 +1078,16 @@ bool CCombinedArtifactInstance::canBePutAt(const ArtifactLocation &al, bool assu
//so we remove from the list all constituents that are already present on dst hero in the form of locks //so we remove from the list all constituents that are already present on dst hero in the form of locks
BOOST_FOREACH(const ConstituentInfo &constituent, constituentsInfo) BOOST_FOREACH(const ConstituentInfo &constituent, constituentsInfo)
{ {
if(constituent.art == al.hero->getArt(constituent.slot, false)) //no need to worry about locked constituent if(constituent.art == artSet->getArt(constituent.slot, false)) //no need to worry about locked constituent
constituentsToBePlaced -= constituent; constituentsToBePlaced -= constituent;
} }
//we iterate over all active slots and check if constituents fits them //we iterate over all active slots and check if constituents fits them
for (int i = 0; i < GameConstants::BACKPACK_START; i++) for (int i = 0; i < GameConstants::BACKPACK_START; i++)
{ {
for(std::vector<ConstituentInfo>::iterator art = constituentsToBePlaced.begin(); art != constituentsToBePlaced.end(); art++) for(std::vector<ConstituentInfo>::iterator art = constituentsToBePlaced.begin(); art != constituentsToBePlaced.end(); art++)
{ {
if(art->art->canBePutAt(ArtifactLocation(al.hero, i), i == al.slot)) // i == al.slot because we can remove already worn artifact only from that slot that is our main destination if(art->art->canBePutAt(artSet, i, i == slot)) // i == al.slot because we can remove already worn artifact only from that slot that is our main destination
{ {
constituentsToBePlaced.erase(art); constituentsToBePlaced.erase(art);
break; break;
@ -1146,31 +1131,35 @@ void CCombinedArtifactInstance::addAsConstituent(CArtifactInstance *art, int slo
attachTo(art); attachTo(art);
} }
void CCombinedArtifactInstance::putAt(CGHeroInstance *h, ui16 slot) void CCombinedArtifactInstance::putAt(ArtifactLocation &al)
{ {
if(slot >= GameConstants::BACKPACK_START) if(al.slot >= GameConstants::BACKPACK_START)
{ {
CArtifactInstance::putAt(h, slot); CArtifactInstance::putAt(al);
BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo) BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo)
ci.slot = -1; ci.slot = -1;
} }
else else
{ {
CArtifactInstance *mainConstituent = figureMainConstituent(slot); //it'll be replaced with combined artifact, not a lock CArtifactInstance *mainConstituent = figureMainConstituent(al); //it'll be replaced with combined artifact, not a lock
CArtifactInstance::putAt(h, slot); //puts combined art (this) CArtifactInstance::putAt(al); //puts combined art (this)
BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo) BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo)
{ {
if(ci.art != mainConstituent) if(ci.art != mainConstituent)
{ {
const ArtifactLocation suggestedPos(al.artHolder, ci.slot);
const bool inActiveSlot = vstd::isbetween(ci.slot, 0, GameConstants::BACKPACK_START);
const bool suggestedPosValid = ci.art->canBePutAt(suggestedPos);
int pos = -1; int pos = -1;
if(vstd::isbetween(ci.slot, 0, GameConstants::BACKPACK_START) && ci.art->canBePutAt(ArtifactLocation(h, ci.slot))) //there is a valid suggestion where to place lock if(inActiveSlot && suggestedPosValid) //there is a valid suggestion where to place lock
pos = ci.slot; pos = ci.slot;
else else
ci.slot = pos = ci.art->firstAvailableSlot(h); ci.slot = pos = ci.art->firstAvailableSlot(al.getHolderArtSet());
assert(pos < GameConstants::BACKPACK_START); assert(pos < GameConstants::BACKPACK_START);
h->setNewArtSlot(pos, ci.art, true); //sets as lock al.getHolderArtSet()->setNewArtSlot(pos, ci.art, true); //sets as lock
} }
else else
{ {
@ -1180,11 +1169,11 @@ void CCombinedArtifactInstance::putAt(CGHeroInstance *h, ui16 slot)
} }
} }
void CCombinedArtifactInstance::removeFrom(CGHeroInstance *h, ui16 slot) void CCombinedArtifactInstance::removeFrom(ArtifactLocation &al)
{ {
if(slot >= GameConstants::BACKPACK_START) if(al.slot >= GameConstants::BACKPACK_START)
{ {
CArtifactInstance::removeFrom(h, slot); CArtifactInstance::removeFrom(al);
} }
else else
{ {
@ -1192,30 +1181,30 @@ void CCombinedArtifactInstance::removeFrom(CGHeroInstance *h, ui16 slot)
{ {
if(ci.slot >= 0) if(ci.slot >= 0)
{ {
h->eraseArtSlot(ci.slot); al.getHolderArtSet()->eraseArtSlot(ci.slot);
ci.slot = -1; ci.slot = -1;
} }
else else
{ {
//main constituent //main constituent
CArtifactInstance::removeFrom(h, slot); CArtifactInstance::removeFrom(al);
} }
} }
} }
} }
CArtifactInstance * CCombinedArtifactInstance::figureMainConstituent(ui16 slot) CArtifactInstance * CCombinedArtifactInstance::figureMainConstituent(const ArtifactLocation &al)
{ {
CArtifactInstance *mainConstituent = NULL; //it'll be replaced with combined artifact, not a lock CArtifactInstance *mainConstituent = NULL; //it'll be replaced with combined artifact, not a lock
BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo) BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo)
if(ci.slot == slot) if(ci.slot == al.slot)
mainConstituent = ci.art; mainConstituent = ci.art;
if(!mainConstituent) if(!mainConstituent)
{ {
BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo) BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo)
{ {
if(vstd::contains(ci.art->artType->possibleSlots, slot)) if(vstd::contains(ci.art->artType->possibleSlots[al.getHolderArtSet()->bearerType()], al.slot))
{ {
mainConstituent = ci.art; mainConstituent = ci.art;
} }
@ -1255,58 +1244,8 @@ bool CCombinedArtifactInstance::ConstituentInfo::operator==(const ConstituentInf
{ {
return art == rhs.art && slot == rhs.slot; return art == rhs.art && slot == rhs.slot;
} }
CCreatureArtifactInstance::CCreatureArtifactInstance()
{
init();
}
CCreatureArtifactInstance::CCreatureArtifactInstance(CArtifact *Art) const CArtifactInstance* CArtifactSet::getArt(ui16 pos, bool excludeLocked /*= true*/) const
{
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 al.stack->isPositionFree(al.slot, assumeDestRemoved);
}
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
{ {
if(const ArtSlotInfo *si = getSlot(pos)) if(const ArtSlotInfo *si = getSlot(pos))
{ {
@ -1317,29 +1256,9 @@ const CArtifactInstance* IArtifactSetBase::getArt(ui16 pos, bool excludeLocked)
return NULL; return NULL;
} }
bool IArtifactSetBase::hasArt(ui32 aid, bool onlyWorn) const CArtifactInstance* CArtifactSet::getArt(ui16 pos, bool excludeLocked /*= true*/)
{ {
return getArtPos(aid, onlyWorn) != -1; return const_cast<CArtifactInstance*>((const_cast<const CArtifactSet*>(this))->getArt(pos, excludeLocked));
}
bool IArtifactSetBase::isPositionFree(ui16 pos, bool onlyLockCheck) const
{
if(const ArtSlotInfo *s = getSlot(pos))
return (onlyLockCheck || !s->artifact) && !s->locked;
return true; //no slot means not used
}
void IArtifactSetBase::setNewArtSlot(ui16 slot, CArtifactInstance *art, bool locked)
{
ArtSlotInfo &asi = retreiveNewArtSlot(slot);
asi.artifact = art;
asi.locked = locked;
}
CArtifactInstance* IArtifactSetBase::getArt(ui16 pos, bool excludeLocked /*= true*/)
{
return const_cast<CArtifactInstance*>((const_cast<const IArtifactSetBase*>(this))->getArt(pos, excludeLocked));
} }
si32 CArtifactSet::getArtPos(int aid, bool onlyWorn /*= true*/) const si32 CArtifactSet::getArtPos(int aid, bool onlyWorn /*= true*/) const
@ -1384,6 +1303,11 @@ const CArtifactInstance * CArtifactSet::getArtByInstanceId(int artInstId) const
return NULL; return NULL;
} }
bool CArtifactSet::hasArt(ui32 aid, bool onlyWorn /*= false*/) const
{
return getArtPos(aid, onlyWorn) != -1;
}
const ArtSlotInfo * CArtifactSet::getSlot(ui16 pos) const const ArtSlotInfo * CArtifactSet::getSlot(ui16 pos) const
{ {
if(vstd::contains(artifactsWorn, pos)) if(vstd::contains(artifactsWorn, pos))
@ -1400,6 +1324,14 @@ const ArtSlotInfo * CArtifactSet::getSlot(ui16 pos) const
return NULL; return NULL;
} }
bool CArtifactSet::isPositionFree(ui16 pos, bool onlyLockCheck /*= false*/) const
{
if(const ArtSlotInfo *s = getSlot(pos))
return (onlyLockCheck || !s->artifact) && !s->locked;
return true; //no slot means not used
}
si32 CArtifactSet::getArtTypeId(ui16 pos) const si32 CArtifactSet::getArtTypeId(ui16 pos) const
{ {
const CArtifactInstance * const a = getArt(pos); const CArtifactInstance * const a = getArt(pos);
@ -1426,6 +1358,13 @@ ArtSlotInfo & CArtifactSet::retreiveNewArtSlot(ui16 slot)
return ret; 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) void CArtifactSet::eraseArtSlot(ui16 slot)
{ {
if(slot < GameConstants::BACKPACK_START) if(slot < GameConstants::BACKPACK_START)
@ -1439,88 +1378,9 @@ void CArtifactSet::eraseArtSlot(ui16 slot)
} }
} }
ArtSlotInfo & CCreatureArtifactSet::retreiveNewArtSlot(ui16 slot) void CArtifactSet::artDeserializationFix(CBonusSystemNode *node)
{ {
ArtSlotInfo &ret = slot == GameConstants::CREATURE_ART for(bmap<ui16, ArtSlotInfo>::iterator i = artifactsWorn.begin(); i != artifactsWorn.end(); i++)
? activeArtifact if(i->second.artifact && !i->second.locked)
: *artifactsInBackpack.insert(artifactsInBackpack.begin() + (slot - GameConstants::CREATURE_ART), ArtSlotInfo()); node->attachTo(i->second.artifact);
}
return ret;
}
void CCreatureArtifactSet::eraseArtSlot(ui16 slot)
{
if(slot == GameConstants::CREATURE_ART)
{
activeArtifact.artifact = NULL; //hmm?
}
else
{
slot -= 1;
artifactsInBackpack.erase(artifactsInBackpack.begin() + slot);
}
}
const ArtSlotInfo * CCreatureArtifactSet::getSlot(ui16 pos) const
{
if (pos == GameConstants::CREATURE_ART)
return &activeArtifact;
else if(pos > GameConstants::CREATURE_ART)
{
int backpackPos = (int)pos - 1;
if(backpackPos < 0 || backpackPos >= artifactsInBackpack.size())
return NULL;
else
return &artifactsInBackpack[backpackPos];
}
return NULL;
}
si32 CCreatureArtifactSet::getArtPos(int aid, bool onlyWorn) const
{
if (aid == activeArtifact.artifact->artType->id )
return GameConstants::CREATURE_ART;
for(int i = 0; i < artifactsInBackpack.size(); i++)
{
if(artifactsInBackpack[i].artifact->artType->id == aid)
return i + 1;
}
return -1;
}
si32 CCreatureArtifactSet::getArtPos(const CArtifactInstance *art) const
{
if (activeArtifact.artifact == art)
return GameConstants::CREATURE_ART;
for(int i = 0; i < artifactsInBackpack.size(); i++)
if(artifactsInBackpack[i].artifact == art)
return i + 1;
return -1;
}
const CArtifactInstance * CCreatureArtifactSet::getArtByInstanceId(int artInstId) const
{
if (activeArtifact.artifact->id == artInstId)
return activeArtifact.artifact;
for(int i = 0; i < artifactsInBackpack.size(); i++)
if(artifactsInBackpack[i].artifact->id == artInstId)
return artifactsInBackpack[i].artifact;
return NULL;
}
si32 CCreatureArtifactSet::getArtTypeId(ui16 pos) const
{
const CArtifactInstance * const a = getArt(pos);
if(!a)
{
tlog2 << "Stack has no artifact at " << pos << " (getArtTypeId)\n";
return -1;
}
return a->artType->id;
}

View File

@ -16,9 +16,8 @@
class CDefHandler; class CDefHandler;
class CArtifact; class CArtifact;
class CGHeroInstance; class CGHeroInstance;
class CStackInstance;
//class CCreatureArtifactSet;
struct ArtifactLocation; struct ArtifactLocation;
class CArtifactSet;
namespace ArtifactPosition namespace ArtifactPosition
{ {
@ -27,7 +26,17 @@ namespace ArtifactPosition
PRE_FIRST = -1, PRE_FIRST = -1,
HEAD, SHOULDERS, NECK, RIGHT_HAND, LEFT_HAND, TORSO, RIGHT_RING, LEFT_RING, FEET, MISC1, MISC2, MISC3, MISC4, HEAD, SHOULDERS, NECK, RIGHT_HAND, LEFT_HAND, TORSO, RIGHT_RING, LEFT_RING, FEET, MISC1, MISC2, MISC3, MISC4,
MACH1, MACH2, MACH3, MACH4, SPELLBOOK, MISC5, MACH1, MACH2, MACH3, MACH4, SPELLBOOK, MISC5,
AFTER_LAST AFTER_LAST,
//cres
CREATURE_SLOT = 0
};
}
namespace ArtBearer
{
enum
{
HERO, CREATURE
}; };
} }
@ -45,7 +54,7 @@ public:
std::string nodeName() const OVERRIDE; std::string nodeName() const OVERRIDE;
ui32 price; ui32 price;
std::vector<ui16> possibleSlots; //ids of slots where artifact can be placed bmap<ui8, std::vector<ui16> > possibleSlots; //Bearer Type => ids of slots where artifact can be placed
std::vector<ui32> * constituents; // Artifacts IDs a combined artifact consists of, or NULL. std::vector<ui32> * constituents; // Artifacts IDs a combined artifact consists of, or NULL.
std::vector<ui32> * constituentOf; // Reverse map of constituents. std::vector<ui32> * constituentOf; // Reverse map of constituents.
EartClass aClass; EartClass aClass;
@ -77,23 +86,22 @@ public:
//CArtifactInstance(int aid); //CArtifactInstance(int aid);
virtual std::string nodeName() const OVERRIDE; std::string nodeName() const OVERRIDE;
void deserializationFix(); void deserializationFix();
void setType(CArtifact *Art); void setType(CArtifact *Art);
int firstAvailableSlot(const CGHeroInstance *h) const; int firstAvailableSlot(const CArtifactSet *h) const;
int firstBackpackSlot(const CGHeroInstance *h) const; int firstBackpackSlot(const CArtifactSet *h) const;
int getGivenSpellID() const; //to be used with scrolls (and similar arts), -1 if none int getGivenSpellID() const; //to be used with scrolls (and similar arts), -1 if none
virtual bool canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved = false) const; virtual bool canBePutAt(const CArtifactSet *artSet, int slot, bool assumeDestRemoved = false) const;
bool canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved = false) const; //forwards to the above one
virtual bool canBeDisassembled() const; virtual bool canBeDisassembled() const;
virtual void putAt(CGHeroInstance *h, ui16 slot); virtual void putAt(ArtifactLocation &al);
virtual void removeFrom(CGHeroInstance *h, ui16 slot); virtual void removeFrom(ArtifactLocation &al);
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 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<const CArtifact *> assemblyPossibilities(const CGHeroInstance *h) const; std::vector<const CArtifact *> assemblyPossibilities(const CArtifactSet *h) const;
void move(ArtifactLocation &src, ArtifactLocation &dst); void move(ArtifactLocation &src, ArtifactLocation &dst);
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
@ -127,15 +135,15 @@ public:
std::vector<ConstituentInfo> constituentsInfo; std::vector<ConstituentInfo> constituentsInfo;
bool canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved = false) const OVERRIDE; bool canBePutAt(const CArtifactSet *artSet, int slot, bool assumeDestRemoved = false) const OVERRIDE;
bool canBeDisassembled() const OVERRIDE; bool canBeDisassembled() const OVERRIDE;
void putAt(CGHeroInstance *h, ui16 slot) OVERRIDE; void putAt(ArtifactLocation &al) OVERRIDE;
void removeFrom(CGHeroInstance *h, ui16 slot) OVERRIDE; void removeFrom(ArtifactLocation &al) OVERRIDE;
bool isPart(const CArtifactInstance *supposedPart) const OVERRIDE; bool isPart(const CArtifactInstance *supposedPart) const OVERRIDE;
void createConstituents(); void createConstituents();
void addAsConstituent(CArtifactInstance *art, int slot); void addAsConstituent(CArtifactInstance *art, int slot);
CArtifactInstance *figureMainConstituent(ui16 slot); //main constituent is replcaed with us (combined art), not lock CArtifactInstance *figureMainConstituent(const ArtifactLocation &al); //main constituent is replcaed with us (combined art), not lock
CCombinedArtifactInstance(); CCombinedArtifactInstance();
@ -151,30 +159,6 @@ 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 <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CArtifactInstance&>(*this);
//BONUS_TREE_DESERIALIZATION_FIX
}
};
// class DLL_LINKAGE IModableArt : public CArtifact //artifact which can have different properties, such as scroll or banner // class DLL_LINKAGE IModableArt : public CArtifact //artifact which can have different properties, such as scroll or banner
// { //used only for dynamic cast :P // { //used only for dynamic cast :P
// public: // public:
@ -240,7 +224,7 @@ public:
std::vector< ConstTransitivePtr<CArtifact> > artifacts; std::vector< ConstTransitivePtr<CArtifact> > artifacts;
std::vector<CArtifact *> allowedArtifacts; std::vector<CArtifact *> allowedArtifacts;
std::set<ui32> bigArtifacts; // Artifacts that cannot be moved to backpack, e.g. war machines. std::set<ui32> bigArtifacts; // Artifacts that cannot be moved to backpack, e.g. war machines.
std::set<ui32> creatureArtifacts; // can be held by Stacks //std::map<ui32, ui8> modableArtifacts; //1-scroll, 2-banner, 3-commander art with progressive bonus
void loadArtifacts(bool onlyTxt); void loadArtifacts(bool onlyTxt);
void sortArts(); void sortArts();
@ -263,7 +247,6 @@ public:
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & artifacts & allowedArtifacts & treasures & minors & majors & relics; h & artifacts & allowedArtifacts & treasures & minors & majors & relics;
h & creatureArtifacts;
//if(!h.saving) sortArts(); //if(!h.saving) sortArts();
} }
}; };
@ -283,67 +266,33 @@ struct DLL_LINKAGE ArtSlotInfo
} }
}; };
class DLL_LINKAGE IArtifactSetBase class DLL_LINKAGE CArtifactSet
{ ///artifacts container {
public:
virtual void setNewArtSlot(ui16 slot, CArtifactInstance *art, bool locked);
virtual const CArtifactInstance* getArt(ui16 pos, bool excludeLocked = true) const;
virtual CArtifactInstance* getArt(ui16 pos, bool excludeLocked = true); //NULL - no artifact
virtual bool hasArt(ui32 aid, bool onlyWorn = false) const;
virtual bool isPositionFree(ui16 pos, bool onlyLockCheck = false) const;
virtual ArtSlotInfo &retreiveNewArtSlot(ui16 slot)=0;
virtual void eraseArtSlot(ui16 slot)=0;
virtual const ArtSlotInfo *getSlot(ui16 pos) const=0;
virtual si32 getArtPos(int aid, bool onlyWorn = true) const=0; //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)
virtual si32 getArtPos(const CArtifactInstance *art) const=0;
virtual const CArtifactInstance *getArtByInstanceId(int artInstId) const=0;
virtual si32 getArtTypeId(ui16 pos) const=0;
};
class DLL_LINKAGE CArtifactSet : public IArtifactSetBase
{ ///hero artifacts
public: public:
std::vector<ArtSlotInfo> artifactsInBackpack; //hero's artifacts from bag 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 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); ArtSlotInfo &retreiveNewArtSlot(ui16 slot);
void setNewArtSlot(ui16 slot, CArtifactInstance *art, bool locked);
void eraseArtSlot(ui16 slot); void eraseArtSlot(ui16 slot);
const ArtSlotInfo *getSlot(ui16 pos) const; const ArtSlotInfo *getSlot(ui16 pos) const;
si32 getArtPos(int aid, bool onlyWorn = true) const; const CArtifactInstance* getArt(ui16 pos, bool excludeLocked = true) const; //NULL - no artifact
CArtifactInstance* getArt(ui16 pos, bool excludeLocked = true); //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; si32 getArtPos(const CArtifactInstance *art) const;
const CArtifactInstance *getArtByInstanceId(int artInstId) const; const CArtifactInstance *getArtByInstanceId(int artInstId) const;
bool hasArt(ui32 aid, bool onlyWorn = false) const; //checks if hero possess artifact of given id (either in backack or worn)
bool isPositionFree(ui16 pos, bool onlyLockCheck = false) const;
si32 getArtTypeId(ui16 pos) const; si32 getArtTypeId(ui16 pos) const;
virtual ui8 bearerType() const = 0;
virtual ~CArtifactSet(); virtual ~CArtifactSet();
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & artifactsInBackpack & artifactsWorn; h & artifactsInBackpack & artifactsWorn;
} }
};
void artDeserializationFix(CBonusSystemNode *node);
class DLL_LINKAGE CCreatureArtifactSet : public IArtifactSetBase
{ ///creature artifacts
public:
std::vector<ArtSlotInfo> artifactsInBackpack; //artifacts carried by creature - 4 max (according to WoG)
ArtSlotInfo activeArtifact; //position 0 - GameConstants::CREATURE_ART
ArtSlotInfo &retreiveNewArtSlot(ui16 slot);
void eraseArtSlot(ui16 slot);
const ArtSlotInfo *getSlot(ui16 pos)const;
si32 getArtPos(int aid, bool onlyWorn = true) const;
si32 getArtPos(const CArtifactInstance *art) const;
const CArtifactInstance *getArtByInstanceId(int artInstId) const;
si32 getArtTypeId(ui16 pos) const;
virtual ~CCreatureArtifactSet(){};
template <typename Handler> void serialize(Handler &h, const int version)
{
h & artifactsInBackpack & activeArtifact;
}
}; };

View File

@ -874,18 +874,6 @@ void CStackInstance::setArmyObj(const CArmedInstance *ArmyObj)
attachTo(const_cast<CArmedInstance*>(_armyObj)); attachTo(const_cast<CArmedInstance*>(_armyObj));
} }
} }
// void CStackInstance::getParents(TCNodes &out, const CBonusSystemNode *source /*= NULL*/) const
// {
// out.insert(type);
//
// if(source && source != this) //we should be root, if not - do not inherit anything
// return;
//
// if(armyObj)
// out.insert(armyObj);
// else
// out.insert(&IObjectInterface::cb->gameState()->globalEffects);
// }
std::string CStackInstance::getQuantityTXT(bool capitalized /*= true*/) const std::string CStackInstance::getQuantityTXT(bool capitalized /*= true*/) const
{ {
@ -930,9 +918,7 @@ void CStackInstance::deserializationFix()
const CArmedInstance *armyBackup = _armyObj; const CArmedInstance *armyBackup = _armyObj;
_armyObj = NULL; _armyObj = NULL;
setArmyObj(armyBackup); setArmyObj(armyBackup);
artDeserializationFix(this);
if(activeArtifact.artifact)
attachTo(activeArtifact.artifact);
} }
int CStackInstance::getCreatureID() const int CStackInstance::getCreatureID() const
@ -954,6 +940,11 @@ ui64 CStackInstance::getPower() const
return type->AIValue * count; return type->AIValue * count;
} }
ui8 CStackInstance::bearerType() const
{
return ArtBearer::CREATURE;
}
CStackBasicDescriptor::CStackBasicDescriptor() CStackBasicDescriptor::CStackBasicDescriptor()
{ {
type = NULL; type = NULL;

View File

@ -26,7 +26,7 @@ public:
} }
}; };
class DLL_LINKAGE CStackInstance : public CBonusSystemNode, public CStackBasicDescriptor, public CCreatureArtifactSet class DLL_LINKAGE CStackInstance : public CBonusSystemNode, public CStackBasicDescriptor, public CArtifactSet
{ {
const CArmedInstance *_armyObj; //stack must be part of some army, army must be part of some object const CArmedInstance *_armyObj; //stack must be part of some army, army must be part of some object
public: public:
@ -39,7 +39,7 @@ public:
{ {
h & static_cast<CBonusSystemNode&>(*this); h & static_cast<CBonusSystemNode&>(*this);
h & static_cast<CStackBasicDescriptor&>(*this); h & static_cast<CStackBasicDescriptor&>(*this);
h & static_cast<CCreatureArtifactSet&>(*this); h & static_cast<CArtifactSet&>(*this);
h & _armyObj & experience; h & _armyObj & experience;
BONUS_TREE_DESERIALIZATION_FIX BONUS_TREE_DESERIALIZATION_FIX
} }
@ -67,7 +67,8 @@ public:
void setArmyObj(const CArmedInstance *ArmyObj); void setArmyObj(const CArmedInstance *ArmyObj);
void giveStackExp(expType exp); void giveStackExp(expType exp);
bool valid(bool allowUnrandomized) const; bool valid(bool allowUnrandomized) const;
virtual std::string nodeName() const OVERRIDE; ui8 bearerType() const OVERRIDE; //from CArtifactSet
virtual std::string nodeName() const OVERRIDE; //from CBonusSystemnode
void deserializationFix(); void deserializationFix();
}; };

View File

@ -818,7 +818,7 @@ BattleInfo * CGameState::setupBattle(int3 tile, const CArmedInstance *armies[2],
return BattleInfo::setupBattle(tile, terrain, terType, armies, heroes, creatureBank, town); return BattleInfo::setupBattle(tile, terrain, terType, armies, heroes, creatureBank, town);
} }
void CGameState::init(StartInfo * si, ui32 checksum, int Seed, int expectedPostInitSeed /*= -1*/) void CGameState::init(StartInfo * si)
{ {
struct HLP struct HLP
{ {
@ -852,7 +852,7 @@ void CGameState::init(StartInfo * si, ui32 checksum, int Seed, int expectedPostI
case 4: //spell scroll case 4: //spell scroll
{ {
CArtifactInstance * scroll = CArtifactInstance::createScroll(VLC->spellh->spells[curBonus.info2]); CArtifactInstance * scroll = CArtifactInstance::createScroll(VLC->spellh->spells[curBonus.info2]);
scroll->putAt(hero, scroll->firstAvailableSlot(hero)); scroll->putAt(ArtifactLocation(hero, scroll->firstAvailableSlot(hero)));
} }
break; break;
case 5: //prim skill case 5: //prim skill
@ -904,8 +904,8 @@ void CGameState::init(StartInfo * si, ui32 checksum, int Seed, int expectedPostI
} }
}; };
seed = Seed; tlog0 << "\tUsing random seed: "<< si->seedToBeUsed << std::endl;
ran.seed((boost::int32_t)seed); ran.seed((boost::int32_t)si->seedToBeUsed);
scenarioOps = new StartInfo(*si); scenarioOps = new StartInfo(*si);
initialOpts = new StartInfo(*si); initialOpts = new StartInfo(*si);
si = NULL; si = NULL;
@ -986,16 +986,18 @@ void CGameState::init(StartInfo * si, ui32 checksum, int Seed, int expectedPostI
//tlog0 <<"Reading and detecting map file (together): "<<tmh.getDif()<<std::endl; //tlog0 <<"Reading and detecting map file (together): "<<tmh.getDif()<<std::endl;
if(checksum) tlog0 << "\tOur checksum for the map: "<< map->checksum << std::endl;
if(scenarioOps->mapfileChecksum)
{ {
tlog0 << "\tServer checksum for " << scenarioOps->mapname <<": "<< checksum << std::endl; tlog0 << "\tServer checksum for " << scenarioOps->mapname <<": "<< scenarioOps->mapfileChecksum << std::endl;
tlog0 << "\tOur checksum for the map: "<< map->checksum << std::endl; if(map->checksum != scenarioOps->mapfileChecksum)
if(map->checksum != checksum)
{ {
tlog1 << "Wrong map checksum!!!" << std::endl; tlog1 << "Wrong map checksum!!!" << std::endl;
throw std::string("Wrong checksum"); throw std::string("Wrong checksum");
} }
} }
else
scenarioOps->mapfileChecksum = map->checksum;
day = 0; day = 0;
loadTownDInfos(); loadTownDInfos();
@ -1576,10 +1578,14 @@ void CGameState::init(StartInfo * si, ui32 checksum, int Seed, int expectedPostI
map->checkForObjectives(); //needs to be run when all objects are properly placed map->checkForObjectives(); //needs to be run when all objects are properly placed
if(expectedPostInitSeed >= 0) if(scenarioOps->seedPostInit > 0)
{ {
int actualSeed = ran(); int actualSeed = ran();
assert(expectedPostInitSeed == actualSeed); //RNG must be in the same state on all machines when initialization is done (otherwise we have desync) assert(scenarioOps->seedPostInit == actualSeed); //RNG must be in the same state on all machines when initialization is done (otherwise we have desync)
}
else
{
scenarioOps->seedPostInit = ran(); //store the post init "seed"
} }
} }
@ -2473,7 +2479,7 @@ void CGameState::giveHeroArtifact(CGHeroInstance *h, int aid)
CArtifact * const artifact = VLC->arth->artifacts[aid]; //pointer to constant object CArtifact * const artifact = VLC->arth->artifacts[aid]; //pointer to constant object
CArtifactInstance *ai = CArtifactInstance::createNewArtifactInstance(artifact); CArtifactInstance *ai = CArtifactInstance::createNewArtifactInstance(artifact);
map->addNewArtifactInstance(ai); map->addNewArtifactInstance(ai);
ai->putAt(h, ai->firstAvailableSlot(h)); ai->putAt(ArtifactLocation(h, ai->firstAvailableSlot(h)));
} }
int3 CPath::startPos() const int3 CPath::startPos() const

View File

@ -348,7 +348,6 @@ class DLL_LINKAGE CGameState : public CNonConstInfoCallback
public: public:
ConstTransitivePtr<StartInfo> scenarioOps, initialOpts; //second one is a copy of settings received from pregame (not randomized) ConstTransitivePtr<StartInfo> scenarioOps, initialOpts; //second one is a copy of settings received from pregame (not randomized)
ConstTransitivePtr<CCampaignState> campaign; ConstTransitivePtr<CCampaignState> campaign;
ui32 seed;
ui8 currentPlayer; //ID of player currently having turn ui8 currentPlayer; //ID of player currently having turn
ConstTransitivePtr<BattleInfo> curB; //current battle ConstTransitivePtr<BattleInfo> curB; //current battle
ui32 day; //total number of days in game ui32 day; //total number of days in game
@ -374,7 +373,7 @@ public:
boost::shared_mutex *mx; boost::shared_mutex *mx;
void init(StartInfo * si, ui32 checksum, int Seed, int expectedPostInitSeed = -1); void init(StartInfo * si);
void loadTownDInfos(); void loadTownDInfos();
void randomizeObject(CGObjectInstance *cur); void randomizeObject(CGObjectInstance *cur);
std::pair<int,int> pickObject(CGObjectInstance *obj); //chooses type of object to be randomized, returns <type, subtype> std::pair<int,int> pickObject(CGObjectInstance *obj); //chooses type of object to be randomized, returns <type, subtype>
@ -413,7 +412,7 @@ public:
int getDate(int mode=0) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month int getDate(int mode=0) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & scenarioOps & initialOpts & seed & currentPlayer & day & map & players & teams & hpool & globalEffects & campaign; h & scenarioOps & initialOpts & currentPlayer & day & map & players & teams & hpool & globalEffects & campaign;
h & villages & forts & capitols; h & villages & forts & capitols;
if(!h.saving) if(!h.saving)
{ {

View File

@ -1473,7 +1473,7 @@ std::string CGHeroInstance::nodeName() const
void CGHeroInstance::putArtifact(ui16 pos, CArtifactInstance *art) void CGHeroInstance::putArtifact(ui16 pos, CArtifactInstance *art)
{ {
assert(!getArt(pos)); assert(!getArt(pos));
art->putAt(this, pos); art->putAt(ArtifactLocation(this, pos));
} }
void CGHeroInstance::putInBackpack(CArtifactInstance *art) void CGHeroInstance::putInBackpack(CArtifactInstance *art)
@ -1488,11 +1488,7 @@ bool CGHeroInstance::hasSpellbook() const
void CGHeroInstance::deserializationFix() void CGHeroInstance::deserializationFix()
{ {
for(bmap<ui16, ArtSlotInfo>::iterator i = artifactsWorn.begin(); i != artifactsWorn.end(); i++) artDeserializationFix(this);
if(i->second.artifact && !i->second.locked)
attachTo(i->second.artifact);
//attachTo(&speciality);
} }
CBonusSystemNode * CGHeroInstance::whereShouldBeAttached(CGameState *gs) CBonusSystemNode * CGHeroInstance::whereShouldBeAttached(CGameState *gs)
@ -1535,6 +1531,11 @@ CGHeroInstance::ECanDig CGHeroInstance::diggingStatus() const
} }
} }
ui8 CGHeroInstance::bearerType() const
{
return ArtBearer::HERO;
}
void CGDwelling::initObj() void CGDwelling::initObj()
{ {
switch(ID) switch(ID)

View File

@ -395,7 +395,9 @@ public:
CGHeroInstance(); CGHeroInstance();
virtual ~CGHeroInstance(); virtual ~CGHeroInstance();
//////////////////////////////////////////////////////////////////////////
//
ui8 bearerType() const OVERRIDE;
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
virtual CBonusSystemNode *whereShouldBeAttached(CGameState *gs) OVERRIDE; virtual CBonusSystemNode *whereShouldBeAttached(CGameState *gs) OVERRIDE;

View File

@ -56,6 +56,8 @@ void CConnection::init()
{ {
CISer<CConnection>::smartPointerSerialization = false; CISer<CConnection>::smartPointerSerialization = false;
COSer<CConnection>::smartPointerSerialization = false; COSer<CConnection>::smartPointerSerialization = false;
CISer<CConnection>::sendStackInstanceByIds = true;
COSer<CConnection>::sendStackInstanceByIds = true;
registerTypes(static_cast<CISer<CConnection>&>(*this)); registerTypes(static_cast<CISer<CConnection>&>(*this));
registerTypes(static_cast<COSer<CConnection>&>(*this)); registerTypes(static_cast<COSer<CConnection>&>(*this));
#ifdef LIL_ENDIAN #ifdef LIL_ENDIAN
@ -382,6 +384,7 @@ CSerializer::~CSerializer()
CSerializer::CSerializer() CSerializer::CSerializer()
{ {
smartVectorMembersSerialization = false; smartVectorMembersSerialization = false;
sendStackInstanceByIds = false;
} }

View File

@ -20,9 +20,10 @@
#include "ConstTransitivePtr.h" #include "ConstTransitivePtr.h"
const ui32 version = 731; const ui32 version = 732;
class CConnection; class CConnection;
class CGObjectInstance; class CGObjectInstance;
class CStackInstance;
class CGameState; class CGameState;
class CCreature; class CCreature;
class LibClasses; class LibClasses;
@ -246,6 +247,7 @@ public:
TTypeVecMap vectors; //entry must be a pointer to vector containing pointers to the objects of key type TTypeVecMap vectors; //entry must be a pointer to vector containing pointers to the objects of key type
bool smartVectorMembersSerialization; bool smartVectorMembersSerialization;
bool sendStackInstanceByIds;
CSerializer(); CSerializer();
~CSerializer(); ~CSerializer();
@ -344,6 +346,63 @@ struct VectorisedTypeFor
>::type type; >::type type;
}; };
template <typename Handler>
struct VariantVisitorSaver : boost::static_visitor<>
{
Handler &h;
VariantVisitorSaver(Handler &H):h(H)
{
}
template <typename T>
void operator()(const T &t)
{
h << t;
}
};
template<typename Ser,typename T>
struct SaveIfStackInstance
{
static bool invoke(Ser &s, const T &data)
{
return false;
}
};
template<typename Ser>
struct SaveIfStackInstance<Ser, CStackInstance *>
{
static bool invoke(Ser &s, const CStackInstance* const &data)
{
assert(data->armyObj);
TSlot slot = data->armyObj->findStack(data);
s << data->armyObj << slot;
return true;
}
};
template<typename Ser,typename T>
struct LoadIfStackInstance
{
static bool invoke(Ser &s, T &data)
{
return false;
}
};
template<typename Ser>
struct LoadIfStackInstance<Ser, CStackInstance *>
{
static bool invoke(Ser &s, CStackInstance* &data)
{
CArmedInstance *armedObj;
TSlot slot;
s >> armedObj >> slot;
assert(armedObj->hasStackAtSlot(slot));
data = armedObj->stacks[slot];
return true;
}
};
/// The class which manages saving objects. /// The class which manages saving objects.
template <typename Serializer> class DLL_LINKAGE COSer : public CSaverBase template <typename Serializer> class DLL_LINKAGE COSer : public CSaverBase
{ {
@ -424,6 +483,12 @@ public:
} }
} }
if(sendStackInstanceByIds)
{
const bool gotSaved = SaveIfStackInstance<Serializer,T>::invoke(*This(), data);
if(gotSaved)
return;
}
if(smartPointerSerialization) if(smartPointerSerialization)
{ {
@ -552,6 +617,15 @@ public:
for(typename std::map<T1,T2>::const_iterator i=data.begin();i!=data.end();i++) for(typename std::map<T1,T2>::const_iterator i=data.begin();i!=data.end();i++)
*this << i->first << i->second; *this << i->first << i->second;
} }
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
void saveSerializable(const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> &data)
{
si32 which = data.which();
*this << which;
VariantVisitorSaver<Serializer> visitor(*this->This());
boost::apply_visitor(visitor, data);
}
}; };
@ -663,8 +737,9 @@ public:
{ {
this->This()->read(&data,sizeof(data)); this->This()->read(&data,sizeof(data));
} }
template <typename T> template <typename T>
void loadSerializable(T &data) void loadSerializableBySerializeCall(T &data)
{ {
////that const cast is evil because it allows to implicitly overwrite const objects when deserializing ////that const cast is evil because it allows to implicitly overwrite const objects when deserializing
typedef typename boost::remove_const<T>::type nonConstT; typedef typename boost::remove_const<T>::type nonConstT;
@ -672,6 +747,12 @@ public:
hlp.serialize(*this,myVersion); hlp.serialize(*this,myVersion);
//data.serialize(*this,myVersion); //data.serialize(*this,myVersion);
} }
template <typename T>
void loadSerializable(T &data)
{
loadSerializableBySerializeCall(data);
}
template <typename T> template <typename T>
void loadArray(T &data) void loadArray(T &data)
{ {
@ -706,6 +787,13 @@ public:
} }
} }
if(sendStackInstanceByIds)
{
bool gotLoaded = LoadIfStackInstance<Serializer,T>::invoke(*This(), data);
if(gotLoaded)
return;
}
ui32 pid = 0xffffffff; //pointer id (or maybe rather pointee id) ui32 pid = 0xffffffff; //pointer id (or maybe rather pointee id)
if(smartPointerSerialization) if(smartPointerSerialization)
{ {
@ -832,10 +920,43 @@ public:
data.resize(length); data.resize(length);
this->This()->read((void*)data.c_str(),length); this->This()->read((void*)data.c_str(),length);
} }
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
void loadSerializable(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> &data)
{
si32 which;
*this >> which;
if(which == 0)
{
T0 obj;
*this >> obj;
data = obj;
}
else if(which == 1)
{
T1 obj;
*this >> obj;
data = obj;
}
else
assert(0);
//TODO write more if needed, general solution would be much longer
}
void loadSerializable(CStackInstance *&s)
{
if(sendStackInstanceByIds)
{
CArmedInstance *armed;
TSlot slot;
*this >> armed >> slot;
assert(armed->hasStackAtSlot(slot));
s = armed->stacks[slot];
}
else
loadSerializableBySerializeCall(s);
}
}; };
class DLL_LINKAGE CSaveFile class DLL_LINKAGE CSaveFile
: public COSer<CSaveFile> : public COSer<CSaveFile>
{ {

View File

@ -88,7 +88,6 @@ namespace GameConstants
const ui16 BACKPACK_START = 19; const ui16 BACKPACK_START = 19;
const int ID_CATAPULT = 3, ID_LOCK = 145; const int ID_CATAPULT = 3, ID_LOCK = 145;
const ui16 CREATURE_ART = 0; //position in CCreatureArtifactSet
//game modules //game modules
const bool STACK_EXP = true; const bool STACK_EXP = true;
@ -98,6 +97,11 @@ namespace GameConstants
} }
// Enum declarations // Enum declarations
namespace PrimarySkill
{
enum { ATTACK, DEFENSE, SPELL_POWER, KNOWLEDGE};
}
namespace EVictoryConditionType namespace EVictoryConditionType
{ {
enum EVictoryConditionType { ARTIFACT, GATHERTROOP, GATHERRESOURCE, BUILDCITY, BUILDGRAIL, BEATHERO, enum EVictoryConditionType { ARTIFACT, GATHERTROOP, GATHERRESOURCE, BUILDCITY, BUILDGRAIL, BEATHERO,

View File

@ -1,7 +1,5 @@
#pragma once #pragma once
#include <boost/range.hpp>
#include "GameConstants.h" #include "GameConstants.h"
/* /*
@ -31,10 +29,7 @@ typedef std::set<const CBonusSystemNode*> TCNodes;
typedef std::vector<CBonusSystemNode *> TNodesVector; typedef std::vector<CBonusSystemNode *> TNodesVector;
typedef boost::function<bool(const Bonus*)> CSelector; typedef boost::function<bool(const Bonus*)> CSelector;
namespace PrimarySkill
{
enum { ATTACK, DEFENSE, SPELL_POWER, KNOWLEDGE};
}
#define BONUS_TREE_DESERIALIZATION_FIX if(!h.saving && h.smartPointerSerialization) deserializationFix(); #define BONUS_TREE_DESERIALIZATION_FIX if(!h.saving && h.smartPointerSerialization) deserializationFix();

View File

@ -307,7 +307,7 @@ public:
virtual void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, int pos) = 0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack virtual void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, int pos) = 0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
virtual void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) = 0; virtual void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) = 0;
virtual void removeArtifact(const ArtifactLocation &al) = 0; virtual void removeArtifact(const ArtifactLocation &al) = 0;
virtual void moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) = 0; virtual bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) = 0;
virtual void showCompInfo(ShowInInfobox * comp)=0; virtual void showCompInfo(ShowInInfobox * comp)=0;
virtual void heroVisitCastle(int obj, int heroID)=0; virtual void heroVisitCastle(int obj, int heroID)=0;

View File

@ -845,34 +845,52 @@ typedef si32 TArtPos;
struct ArtifactLocation struct ArtifactLocation
{ {
ConstTransitivePtr<CGHeroInstance> hero; typedef boost::variant<ConstTransitivePtr<CGHeroInstance>, ConstTransitivePtr<CStackInstance> > TArtHolder;
ConstTransitivePtr<CStackInstance> stack;
TArtHolder artHolder;
TArtPos slot; TArtPos slot;
ArtifactLocation() ArtifactLocation()
{ {
artHolder = ConstTransitivePtr<CGHeroInstance>();
slot = -1; slot = -1;
stack = NULL;
hero = NULL;
} }
ArtifactLocation(const CGHeroInstance *Hero, TArtPos Slot) template <typename T>
ArtifactLocation(const T *ArtHolder, TArtPos Slot)
{ {
hero = const_cast<CGHeroInstance*>(Hero); //we are allowed here to const cast -> change will go through one of our packages... do not abuse!
stack = NULL; artHolder = const_cast<T*>(ArtHolder); //we are allowed here to const cast -> change will go through one of our packages... do not abuse!
slot = Slot; slot = Slot;
} }
ArtifactLocation(const CStackInstance *Stack, TArtPos Slot) ArtifactLocation(TArtHolder ArtHolder, TArtPos Slot)
{ {
stack = const_cast<CStackInstance*>(Stack); //we are allowed here to const cast -> change will go through one of our packages... do not abuse! artHolder = ArtHolder;
hero = NULL;
slot = Slot; slot = Slot;
} }
template <typename T>
bool isHolder(const T *t) const
{
if(auto ptrToT = boost::get<ConstTransitivePtr<T> >(&artHolder))
{
return ptrToT->get() == t;
}
return false;
}
DLL_LINKAGE const CArmedInstance *relatedObj() const; //hero or the stack owner
DLL_LINKAGE int owningPlayer() const;
DLL_LINKAGE CArtifactSet *getHolderArtSet();
DLL_LINKAGE CBonusSystemNode *getHolderNode();
DLL_LINKAGE const CArtifactSet *getHolderArtSet() const;
DLL_LINKAGE const CBonusSystemNode *getHolderNode() const;
DLL_LINKAGE const CArtifactInstance *getArt() const; DLL_LINKAGE const CArtifactInstance *getArt() const;
DLL_LINKAGE CArtifactInstance *getArt(); DLL_LINKAGE CArtifactInstance *getArt();
DLL_LINKAGE const ArtSlotInfo *getSlot() const; DLL_LINKAGE const ArtSlotInfo *getSlot() const;
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & hero & stack & slot; h & artHolder & slot;
} }
}; };
@ -1764,20 +1782,13 @@ struct GarrisonHeroSwap : public CPackForServer
struct ExchangeArtifacts : public CPackForServer struct ExchangeArtifacts : public CPackForServer
//TODO: allow exchange between heroes, stacks and commanders //TODO: allow exchange between heroes, stacks and commanders
{ {
ArtifactLocation src, dst;
ExchangeArtifacts(){}; ExchangeArtifacts(){};
ExchangeArtifacts(si32 H1, si32 H2, ui16 S1, ui16 S2)
:hid1(H1),hid2(H2),slot1(S1),slot2(S2)
{
s1 = s2 = StackLocation(NULL,0);
};
si32 hid1, hid2;
StackLocation s1, s2; //for creature stacks
ui16 slot1, slot2;
bool applyGh(CGameHandler *gh); bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & hid1 & hid2 & s1 & s2 & slot1 & slot2; h & src & dst;
} }
}; };

View File

@ -536,6 +536,48 @@ DLL_LINKAGE const CStackInstance * StackLocation::getStack()
return &army->getStack(slot); return &army->getStack(slot);
} }
struct ObjectRetriever : boost::static_visitor<const CArmedInstance *>
{
const CArmedInstance * operator()(const ConstTransitivePtr<CGHeroInstance> &h) const
{
return h;
}
const CArmedInstance * operator()(const ConstTransitivePtr<CStackInstance> &s) const
{
return s->armyObj;
}
};
template <typename T>
struct GetBase : boost::static_visitor<T*>
{
template <typename TArg>
T * operator()(TArg &arg) const
{
return arg;
}
};
DLL_LINKAGE const CArmedInstance * ArtifactLocation::relatedObj() const
{
return boost::apply_visitor(ObjectRetriever(), artHolder);
}
DLL_LINKAGE int ArtifactLocation::owningPlayer() const
{
auto obj = relatedObj();
return obj ? obj->tempOwner : GameConstants::NEUTRAL_PLAYER;
}
DLL_LINKAGE CArtifactSet *ArtifactLocation::getHolderArtSet()
{
return boost::apply_visitor(GetBase<CArtifactSet>(), artHolder);
}
DLL_LINKAGE CBonusSystemNode *ArtifactLocation::getHolderNode()
{
return boost::apply_visitor(GetBase<CBonusSystemNode>(), artHolder);
}
DLL_LINKAGE const CArtifactInstance *ArtifactLocation::getArt() const DLL_LINKAGE const CArtifactInstance *ArtifactLocation::getArt() const
{ {
const ArtSlotInfo *s = getSlot(); const ArtSlotInfo *s = getSlot();
@ -552,6 +594,18 @@ DLL_LINKAGE const CArtifactInstance *ArtifactLocation::getArt() const
return NULL; return NULL;
} }
DLL_LINKAGE const CArtifactSet * ArtifactLocation::getHolderArtSet() const
{
ArtifactLocation *t = const_cast<ArtifactLocation*>(this);
return t->getHolderArtSet();
}
DLL_LINKAGE const CBonusSystemNode * ArtifactLocation::getHolderNode() const
{
ArtifactLocation *t = const_cast<ArtifactLocation*>(this);
return t->getHolderNode();
}
DLL_LINKAGE CArtifactInstance *ArtifactLocation::getArt() DLL_LINKAGE CArtifactInstance *ArtifactLocation::getArt()
{ {
const ArtifactLocation *t = this; const ArtifactLocation *t = this;
@ -560,11 +614,7 @@ DLL_LINKAGE CArtifactInstance *ArtifactLocation::getArt()
DLL_LINKAGE const ArtSlotInfo *ArtifactLocation::getSlot() const DLL_LINKAGE const ArtSlotInfo *ArtifactLocation::getSlot() const
{ {
if (hero) return getHolderArtSet()->getSlot(slot);
return hero->getSlot(slot);
if (stack)
return stack->getSlot(slot);
return NULL;
} }
DLL_LINKAGE void ChangeStackCount::applyGs( CGameState *gs ) DLL_LINKAGE void ChangeStackCount::applyGs( CGameState *gs )
@ -662,14 +712,15 @@ DLL_LINKAGE void RebalanceStacks::applyGs( CGameState *gs )
DLL_LINKAGE void PutArtifact::applyGs( CGameState *gs ) DLL_LINKAGE void PutArtifact::applyGs( CGameState *gs )
{ {
assert(art->canBePutAt(al)); assert(art->canBePutAt(al));
al.hero->putArtifact(al.slot, art); art->putAt(al);
//al.hero->putArtifact(al.slot, art);
} }
DLL_LINKAGE void EraseArtifact::applyGs( CGameState *gs ) DLL_LINKAGE void EraseArtifact::applyGs( CGameState *gs )
{ {
CArtifactInstance *a = al.getArt(); CArtifactInstance *a = al.getArt();
assert(a); assert(a);
a->removeFrom(al.hero, al.slot); a->removeFrom(al);
} }
DLL_LINKAGE void MoveArtifact::applyGs( CGameState *gs ) DLL_LINKAGE void MoveArtifact::applyGs( CGameState *gs )
@ -681,49 +732,58 @@ DLL_LINKAGE void MoveArtifact::applyGs( CGameState *gs )
a->move(src, dst); a->move(src, dst);
//TODO what'll happen if Titan's thunder is equiped by pickin git up or the start of game? //TODO what'll happen if Titan's thunder is equiped by pickin git up or the start of game?
if (a->artType->id == 135 && dst.hero && dst.slot == ArtifactPosition::RIGHT_HAND && !dst.hero->hasSpellbook()) //Titan's Thunder creates new spellbook on equip if (a->artType->id == 135 && dst.slot == ArtifactPosition::RIGHT_HAND) //Titan's Thunder creates new spellbook on equip
gs->giveHeroArtifact(dst.hero, 0); {
auto hPtr = boost::get<ConstTransitivePtr<CGHeroInstance> >(&dst.artHolder);
if(hPtr)
{
CGHeroInstance *h = *hPtr;
if(h && !h->hasSpellbook())
gs->giveHeroArtifact(h, 0);
}
}
} }
DLL_LINKAGE void AssembledArtifact::applyGs( CGameState *gs ) DLL_LINKAGE void AssembledArtifact::applyGs( CGameState *gs )
{ {
CGHeroInstance *h = al.hero; CArtifactSet *artSet = al.getHolderArtSet();
const CArtifactInstance *transformedArt = al.getArt(); const CArtifactInstance *transformedArt = al.getArt();
assert(transformedArt); assert(transformedArt);
assert(vstd::contains(transformedArt->assemblyPossibilities(al.hero), builtArt)); assert(vstd::contains(transformedArt->assemblyPossibilities(artSet), builtArt));
CCombinedArtifactInstance *combinedArt = new CCombinedArtifactInstance(builtArt); CCombinedArtifactInstance *combinedArt = new CCombinedArtifactInstance(builtArt);
gs->map->addNewArtifactInstance(combinedArt); gs->map->addNewArtifactInstance(combinedArt);
//retrieve all constituents //retrieve all constituents
BOOST_FOREACH(si32 constituentID, *builtArt->constituents) BOOST_FOREACH(si32 constituentID, *builtArt->constituents)
{ {
int pos = h->getArtPos(constituentID); int pos = artSet->getArtPos(constituentID);
assert(pos >= 0); assert(pos >= 0);
CArtifactInstance *constituentInstance = h->getArt(pos); CArtifactInstance *constituentInstance = artSet->getArt(pos);
//move constituent from hero to be part of new, combined artifact //move constituent from hero to be part of new, combined artifact
constituentInstance->removeFrom(h, pos); constituentInstance->removeFrom(al);
combinedArt->addAsConstituent(constituentInstance, pos); combinedArt->addAsConstituent(constituentInstance, pos);
if(!vstd::contains(combinedArt->artType->possibleSlots, al.slot) && vstd::contains(combinedArt->artType->possibleSlots, pos)) if(!vstd::contains(combinedArt->artType->possibleSlots[artSet->bearerType()], al.slot) && vstd::contains(combinedArt->artType->possibleSlots[artSet->bearerType()], pos))
al.slot = pos; al.slot = pos;
} }
//put new combined artifacts //put new combined artifacts
combinedArt->putAt(h, al.slot); combinedArt->putAt(al);
} }
DLL_LINKAGE void DisassembledArtifact::applyGs( CGameState *gs ) DLL_LINKAGE void DisassembledArtifact::applyGs( CGameState *gs )
{ {
CGHeroInstance *h = al.hero;
CCombinedArtifactInstance *disassembled = dynamic_cast<CCombinedArtifactInstance*>(al.getArt()); CCombinedArtifactInstance *disassembled = dynamic_cast<CCombinedArtifactInstance*>(al.getArt());
assert(disassembled); assert(disassembled);
std::vector<CCombinedArtifactInstance::ConstituentInfo> constituents = disassembled->constituentsInfo; std::vector<CCombinedArtifactInstance::ConstituentInfo> constituents = disassembled->constituentsInfo;
disassembled->removeFrom(h, al.slot); disassembled->removeFrom(al);
BOOST_FOREACH(CCombinedArtifactInstance::ConstituentInfo &ci, constituents) BOOST_FOREACH(CCombinedArtifactInstance::ConstituentInfo &ci, constituents)
{ {
ArtifactLocation constituentLoc = al;
constituentLoc.slot = (ci.slot >= 0 ? ci.slot : al.slot); //-1 is slot of main constituent -> it'll replace combined artifact in its pos
disassembled->detachFrom(ci.art); disassembled->detachFrom(ci.art);
ci.art->putAt(h, ci.slot >= 0 ? ci.slot : al.slot); //-1 is slot of main constituent -> it'll replace combined artifact in its pos ci.art->putAt(constituentLoc);
} }
gs->map->eraseArtifactInstance(disassembled); gs->map->eraseArtifactInstance(disassembled);

View File

@ -94,7 +94,7 @@ void registerTypes1(Serializer &s)
s.template registerType<BattleInfo>(); s.template registerType<BattleInfo>();
s.template registerType<CArtifactInstance>(); s.template registerType<CArtifactInstance>();
s.template registerType<CCombinedArtifactInstance>(); s.template registerType<CCombinedArtifactInstance>();
s.template registerType<CCreatureArtifactInstance>(); //s.template registerType<CCreatureArtifactInstance>();
//s.template registerType<ArtSlotInfo>(); //s.template registerType<ArtSlotInfo>();
//s.template registerType<ArtifactLocation>(); //s.template registerType<ArtifactLocation>();
//s.template registerType<StackLocation>(); //s.template registerType<StackLocation>();

View File

@ -58,6 +58,9 @@ struct StartInfo
typedef bmap<int, PlayerSettings> TPlayerInfos; typedef bmap<int, PlayerSettings> TPlayerInfos;
TPlayerInfos playerInfos; //color indexed TPlayerInfos playerInfos; //color indexed
ui32 seedToBeUsed; //0 if not sure (client requests server to decide, will be send in reply pack)
ui32 seedPostInit; //so we know that game is correctly synced at the start; 0 if not known yet
ui32 mapfileChecksum; //0 if not relevant
ui8 turnTime; //in minutes, 0=unlimited ui8 turnTime; //in minutes, 0=unlimited
std::string mapname; std::string mapname;
ui8 whichMapInCampaign; //used only for mode CAMPAIGN ui8 whichMapInCampaign; //used only for mode CAMPAIGN
@ -84,6 +87,8 @@ struct StartInfo
h & mode; h & mode;
h & difficulty; h & difficulty;
h & playerInfos; h & playerInfos;
h & seedToBeUsed & seedPostInit;
h & mapfileChecksum;
h & turnTime; h & turnTime;
h & mapname; h & mapname;
h & whichMapInCampaign; h & whichMapInCampaign;
@ -92,6 +97,7 @@ struct StartInfo
StartInfo() StartInfo()
{ {
mapfileChecksum = seedPostInit = seedToBeUsed = 0;
mode = INVALID; mode = INVALID;
choosenCampaignBonus = -1; choosenCampaignBonus = -1;
} }

View File

@ -794,7 +794,6 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
CGameHandler::CGameHandler(void) CGameHandler::CGameHandler(void)
{ {
seedInitial = seedPostInit = -1;
QID = 1; QID = 1;
//gs = NULL; //gs = NULL;
IObjectInterface::cb = this; IObjectInterface::cb = this;
@ -814,13 +813,12 @@ CGameHandler::~CGameHandler(void)
void CGameHandler::init(StartInfo *si) void CGameHandler::init(StartInfo *si)
{ {
extern DLL_LINKAGE boost::rand48 ran; extern DLL_LINKAGE boost::rand48 ran;
if(seedInitial < 0) if(!si->seedToBeUsed)
seedInitial = std::time(NULL); si->seedToBeUsed = std::time(NULL);
gs = new CGameState(); gs = new CGameState();
tlog0 << "Gamestate created!" << std::endl; tlog0 << "Gamestate created!" << std::endl;
gs->init(si, 0, seedInitial); gs->init(si);
seedPostInit = ran();
tlog0 << "Gamestate initialized!" << std::endl; tlog0 << "Gamestate initialized!" << std::endl;
for(std::map<ui8,PlayerState>::iterator i = gs->players.begin(); i != gs->players.end(); i++) for(std::map<ui8,PlayerState>::iterator i = gs->players.begin(); i != gs->players.end(); i++)
@ -1207,8 +1205,7 @@ void CGameHandler::run(bool resume)
//ui32 seed; //ui32 seed;
if(!resume) if(!resume)
{ {
ui32 sum = gs->map ? gs->map->checksum : 612; (*cc) << gs->initialOpts; // gs->scenarioOps
(*cc) << gs->initialOpts << sum << gs->seed << seedPostInit; // gs->scenarioOps
} }
(*cc) >> quantity; //how many players will be handled at that client (*cc) >> quantity; //how many players will be handled at that client
@ -2503,14 +2500,14 @@ bool CGameHandler::garrisonSwap( si32 tid )
// With the amount of changes done to the function, it's more like transferArtifacts. // With the amount of changes done to the function, it's more like transferArtifacts.
// Function moves artifact from src to dst. If dst is not a backpack and is already occupied, old dst art goes to backpack and is replaced. // Function moves artifact from src to dst. If dst is not a backpack and is already occupied, old dst art goes to backpack and is replaced.
bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, ui16 destSlot) bool CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2)
{ {
const CGHeroInstance *srcHero = getHero(srcHeroID); ArtifactLocation src = al1, dst = al2;
const CGHeroInstance *destHero = getHero(destHeroID); const int srcPlayer = src.owningPlayer(), dstPlayer = dst.owningPlayer();
ArtifactLocation src(srcHero, srcSlot), dst(destHero, destSlot); const CArmedInstance *srcObj = src.relatedObj(), *dstObj = dst.relatedObj();
// Make sure exchange is even possible between the two heroes. // Make sure exchange is even possible between the two heroes.
if(!isAllowedExchange(srcHeroID, destHeroID)) if(!isAllowedExchange(srcObj->id, dstObj->id))
COMPLAIN_RET("That heroes cannot make any exchange!"); COMPLAIN_RET("That heroes cannot make any exchange!");
const CArtifactInstance *srcArtifact = src.getArt(); const CArtifactInstance *srcArtifact = src.getArt();
@ -2518,72 +2515,38 @@ bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, u
if (srcArtifact == NULL) if (srcArtifact == NULL)
COMPLAIN_RET("No artifact to move!"); COMPLAIN_RET("No artifact to move!");
if (destArtifact && srcHero->tempOwner != destHero->tempOwner) if (destArtifact && srcPlayer != dstPlayer)
COMPLAIN_RET("Can't touch artifact on hero of another player!"); COMPLAIN_RET("Can't touch artifact on hero of another player!");
// Check if src/dest slots are appropriate for the artifacts exchanged. // Check if src/dest slots are appropriate for the artifacts exchanged.
// Moving to the backpack is always allowed. // Moving to the backpack is always allowed.
if ((!srcArtifact || destSlot < GameConstants::BACKPACK_START) if ((!srcArtifact || dst.slot < GameConstants::BACKPACK_START)
&& srcArtifact && !srcArtifact->canBePutAt(dst, true)) && srcArtifact && !srcArtifact->canBePutAt(dst, true))
COMPLAIN_RET("Cannot move artifact!"); COMPLAIN_RET("Cannot move artifact!");
if ((srcArtifact && srcArtifact->artType->id == GameConstants::ID_LOCK) || (destArtifact && destArtifact->artType->id == GameConstants::ID_LOCK)) if ((srcArtifact && srcArtifact->artType->id == GameConstants::ID_LOCK) || (destArtifact && destArtifact->artType->id == GameConstants::ID_LOCK))
COMPLAIN_RET("Cannot move artifact locks."); COMPLAIN_RET("Cannot move artifact locks.");
if (destSlot >= GameConstants::BACKPACK_START && srcArtifact->artType->isBig()) if (dst.slot >= GameConstants::BACKPACK_START && srcArtifact->artType->isBig())
COMPLAIN_RET("Cannot put big artifacts in backpack!"); COMPLAIN_RET("Cannot put big artifacts in backpack!");
if (srcSlot == ArtifactPosition::MACH4 || destSlot == ArtifactPosition::MACH4) if (src.slot == ArtifactPosition::MACH4 || dst.slot == ArtifactPosition::MACH4)
COMPLAIN_RET("Cannot move catapult!"); COMPLAIN_RET("Cannot move catapult!");
if(dst.slot >= GameConstants::BACKPACK_START) if(dst.slot >= GameConstants::BACKPACK_START)
vstd::amin(dst.slot, GameConstants::BACKPACK_START + dst.hero->artifactsInBackpack.size()); vstd::amin(dst.slot, GameConstants::BACKPACK_START + dst.getHolderArtSet()->artifactsInBackpack.size());
if (src.slot == dst.slot && src.hero == dst.hero) if (src.slot == dst.slot && src.artHolder == dst.artHolder)
COMPLAIN_RET("Won't move artifact: Dest same as source!"); COMPLAIN_RET("Won't move artifact: Dest same as source!");
//moving art to backpack is always allowed (we've ruled out exceptions) if(dst.slot < GameConstants::BACKPACK_START && destArtifact) //moving art to another slot
if(destSlot >= GameConstants::BACKPACK_START)
{ {
moveArtifact(src, dst); //old artifact must be removed first
} moveArtifact(dst, ArtifactLocation(dst.artHolder, dst.getHolderArtSet()->artifactsInBackpack.size() + GameConstants::BACKPACK_START));
else //moving art to another slot
{
if(destArtifact) //old artifact must be removed first
{
moveArtifact(dst, ArtifactLocation(destHero, destHero->artifactsInBackpack.size() + GameConstants::BACKPACK_START));
}
moveArtifact(src, dst);
} }
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; MoveArtifact ma;
ma.src = al1; ma.src = src;
ma.dst = al2; ma.dst = dst;
sendAndApply(&ma); sendAndApply(&ma);
} }
@ -5550,7 +5513,7 @@ void CGameHandler::giveHeroArtifact(const CGHeroInstance *h, const CArtifactInst
{ {
assert(a->artType); assert(a->artType);
ArtifactLocation al; ArtifactLocation al;
al.hero = h; al.artHolder = const_cast<CGHeroInstance*>(h);
int slot = -1; int slot = -1;
if(pos < 0) if(pos < 0)
@ -5588,10 +5551,7 @@ void CGameHandler::giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact
CArtifactInstance *a = NULL; CArtifactInstance *a = NULL;
if(!artType->constituents) if(!artType->constituents)
{ {
if (vstd::contains(VLC->arth->creatureArtifacts, artType->id)) a = new CArtifactInstance();
a = new CCreatureArtifactInstance();
else
a = new CArtifactInstance();
} }
else else
{ {

View File

@ -91,8 +91,6 @@ public:
PlayerStatuses states; //player color -> player state PlayerStatuses states; //player color -> player state
std::set<CConnection*> conns; std::set<CConnection*> conns;
si32 seedInitial, seedPostInit;
//queries stuff //queries stuff
boost::recursive_mutex gsm; boost::recursive_mutex gsm;
ui32 QID; ui32 QID;
@ -158,7 +156,7 @@ public:
void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, int pos) OVERRIDE; void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, int pos) OVERRIDE;
void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) OVERRIDE; void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) OVERRIDE;
void removeArtifact(const ArtifactLocation &al) OVERRIDE; void removeArtifact(const ArtifactLocation &al) OVERRIDE;
void moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) OVERRIDE; bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) OVERRIDE;
void showCompInfo(ShowInInfobox * comp) OVERRIDE; void showCompInfo(ShowInInfobox * comp) OVERRIDE;
void heroVisitCastle(int obj, int heroID) OVERRIDE; void heroVisitCastle(int obj, int heroID) OVERRIDE;
@ -212,10 +210,6 @@ public:
bool buyArtifact( const IMarket *m, const CGHeroInstance *h, int rid, int aid); //for artifact merchant and black market -> buying for any resource in special building / advobject bool buyArtifact( const IMarket *m, const CGHeroInstance *h, int rid, int aid); //for artifact merchant and black market -> buying for any resource in special building / advobject
bool sellArtifact( const IMarket *m, const CGHeroInstance *h, int aid, int rid); //for artifact merchant selling 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 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 garrisonSwap(si32 tid);
bool upgradeCreature( ui32 objid, ui8 pos, ui32 upgID ); bool upgradeCreature( ui32 objid, ui8 pos, ui32 upgID );
bool recruitCreatures(si32 objid, ui32 crid, ui32 cram, si32 level); bool recruitCreatures(si32 objid, ui32 crid, ui32 cram, si32 level);

View File

@ -133,21 +133,8 @@ bool GarrisonHeroSwap::applyGh( CGameHandler *gh )
bool ExchangeArtifacts::applyGh( CGameHandler *gh ) bool ExchangeArtifacts::applyGh( CGameHandler *gh )
{ {
ERROR_IF_NOT_OWNS(hid1);//second hero can be ally ERROR_IF_NOT(src.owningPlayer());//second hero can be ally
if (hid1) return gh->moveArtifact(src, dst);
{ //TODO: polymorph
if (hid2)
return gh->moveArtifact(hid1,hid2,slot1,slot2);
else
return gh->moveArtifact(hid1,s2,slot1,slot2);
}
else
{
if (hid2)
return gh->moveArtifact(s1,hid2,slot1,slot2);
else
return gh->moveArtifact(s1,s2,slot1,slot2);
}
} }
bool AssembleArtifacts::applyGh( CGameHandler *gh ) bool AssembleArtifacts::applyGh( CGameHandler *gh )