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;
// }
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);
const CStackInstance * stack2 = dynamic_cast<const CStackInstance*>(dest);
const CGHeroInstance * hero1 = dynamic_cast<const CGHeroInstance*>(src);
const CGHeroInstance * hero2 = dynamic_cast<const CGHeroInstance*>(dest);
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;
ExchangeArtifacts ea;
ea.src = l1;
ea.dst = l2;
sendRequest(&ea);
return true;
}
/**

View File

@ -13,7 +13,6 @@
*
*/
class IArtifactSetBase;
class CGHeroInstance;
class CGameState;
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 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 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 dismissCreature(const CArmedInstance *obj, int stackPos)=0;
virtual void endTurn()=0;
@ -127,7 +126,7 @@ public:
int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2, int val);
bool dismissHero(const CGHeroInstance * hero);
//bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2);
bool swapArtifacts(const 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 CStackInstance * stack, ui16 src , const CGHeroInstance * hero, ui16 dest); // TODO: unify classes
bool assembleArtifacts(const CGHeroInstance * hero, ui16 artifactSlot, bool assemble, ui32 assembleTo);

View File

@ -68,6 +68,7 @@
#include <boost/range/algorithm.hpp>
#include <boost/thread.hpp>
#include <boost/unordered_set.hpp>
#include <boost/variant.hpp>
#ifdef ANDROID
#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)
{
creatureArtifact = NULL; //may be set later
stack = Stack;
c = stack->type;
if(!StackNode)
@ -264,11 +265,9 @@ void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode *
if (heroOwner)
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))
blitAt(graphics->artDefs->ourImages[art->id].bitmap, 466, 161, *bitmap);
if (creatureArtifact = stack->getArt(ArtifactPosition::CREATURE_SLOT))
blitAt(graphics->artDefs->ourImages[creatureArtifact->artType->id].bitmap, 466, 100, *bitmap);
}
else
creatureArtifact = NULL;
}
if (battleStack) //only during battle
@ -398,7 +397,7 @@ void CCreatureWindow::sliderMoved(int newpos)
void CCreatureWindow::scrollArt(int dir)
{
//TODO: get next artifact
creatureArtifact = const_cast<CArtifactInstance*>(stack->getArt(GameConstants::CREATURE_ART));
creatureArtifact = stack->getArt(ArtifactPosition::CREATURE_SLOT);
}
void CCreatureWindow::passArtifactToHero()

View File

@ -48,7 +48,7 @@ public:
const CStackInstance *stack;
const CBonusSystemNode *stackNode;
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<CBonusItem*> bonusItems;
std::vector<LRClickableAreaWText*> spellEffects;

View File

@ -99,6 +99,12 @@ void startGameFromFile(const std::string &fname)
{
StartInfo si;
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;
while(GH.topInt())
GH.popIntTotally(GH.topInt());

View File

@ -333,15 +333,12 @@ void CClient::newGame( CConnection *con, StartInfo *si )
c << myPlayers;
ui32 seed, sum;
si32 seedPostInit;
c >> si >> sum >> seed >> seedPostInit;
c >> si;
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->scenarioOps = si;
gs->init(si, sum, seed, seedPostInit);
gs->init(si);
tlog0 <<"Initializing GameState (together): "<<tmh.getDiff()<<std::endl;
if(gs->map)

View File

@ -189,7 +189,7 @@ public:
void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, int pos) OVERRIDE {};
void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) 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 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;
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)
{
artSelected = true;
if (art->canBePutAt(ArtifactLocation(myStack, GameConstants::CREATURE_ART)))
{ //equip clicked stack
LOCPLINT->cb->swapArtifacts(aoh->getHero(), aoh->commonInfo->src.slotID, myStack, GameConstants::CREATURE_ART);
break;
const CGHeroInstance *srcHero = commonInfo->src.AOH->getHero();
artSelected = true;
ArtifactLocation src(srcHero, commonInfo->src.slotID);
ArtifactLocation dst(myStack, ArtifactPosition::CREATURE_SLOT);
if (art->canBePutAt(dst, true))
{ //equip clicked stack
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;
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]);
active = false;
highlight = false;
upg = Upg;
ID = IID;
myStack = Creature;
@ -353,11 +358,7 @@ void CGarrisonSlot::showAll(SDL_Surface * to)
if((owner->highlighted==this)
|| (owner->splitting && owner->highlighted->creature == creature))
{
highlight = true;
}
{
if (highlight)
blitAt(imgs[-1],pos,to);
blitAt(imgs[-1],pos,to);
}
}
else//empty slot
@ -2738,7 +2739,7 @@ void CTradeWindow::artifactSelected(CArtPlace *slot)
{
assert(mode == EMarketMode::ARTIFACT_RESOURCE);
items[1][0]->setArtInstance(slot->ourArt);
if(slot->ourArt && slot->ourArt->id >= 0)
if(slot->ourArt)
hLeft = items[1][0];
else
hLeft = NULL;
@ -3606,7 +3607,7 @@ void CAltarWindow::moveFromSlotToAltar(int slotID, CTradeableItem* altarSlot, co
if(putOnAltar(altarSlot, art))
{
if(slotID < GameConstants::BACKPACK_START)
LOCPLINT->cb->swapArtifacts(hero, slotID, hero, freeBackpackSlot);
LOCPLINT->cb->swapArtifacts(ArtifactLocation(hero, slotID), ArtifactLocation(hero, freeBackpackSlot));
else
{
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 (slotID < 19)
if (slotID < GameConstants::BACKPACK_START)
{
if(ourOwner->allowedAssembling)
{
@ -4556,7 +4557,7 @@ bool CArtPlace::fitsHere(const CArtifactInstance * art) const
return true;
// 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 art->canBePutAt(ArtifactLocation(ourOwner->curHero, slotID), true);
@ -4812,7 +4813,7 @@ void CArtifactsOfHero::scrollBackpack(int dir)
if (s < artsInBackpack)
{
int slotID = 19 + (s + backpackPos)%artsInBackpack;
int slotID = GameConstants::BACKPACK_START + (s + backpackPos)%artsInBackpack;
const CArtifactInstance *art = curHero->getArt(slotID);
assert(art);
if(!vstd::contains(toOmit, art))
@ -4829,7 +4830,7 @@ void CArtifactsOfHero::scrollBackpack(int dir)
}
}
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
if(highlightModeCallback)
@ -4864,21 +4865,6 @@ void CArtifactsOfHero::markPossibleSlots(const CArtifactInstance* art)
BOOST_FOREACH(CArtPlace *place, aoh->artWorn)
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();
}
@ -4966,7 +4952,7 @@ CArtifactsOfHero::CArtifactsOfHero(std::vector<CArtPlace *> ArtWorn, std::vector
for(size_t s=0; s<backpack.size(); ++s)
{
backpack[s]->ourOwner = this;
eraseSlotData(backpack[s], 19 + s);
eraseSlotData(backpack[s], GameConstants::BACKPACK_START + s);
}
leftArtRoll->callback += boost::bind(&CArtifactsOfHero::scrollBackpack,this,-1);
@ -5077,28 +5063,31 @@ void CArtifactsOfHero::safeRedraw()
void CArtifactsOfHero::realizeCurrentTransaction()
{
assert(commonInfo->src.AOH || commonInfo->src.CAS);
assert(commonInfo->dst.AOH || commonInfo->dst.CAS);
LOCPLINT->cb->swapArtifacts(commonInfo->src.AOH ? (IArtifactSetBase*)commonInfo->src.AOH->curHero : commonInfo->src.CAS, commonInfo->src.slotID,
commonInfo->dst.AOH ? (IArtifactSetBase*)commonInfo->dst.AOH->curHero : commonInfo->dst.CAS, commonInfo->dst.slotID);
assert(commonInfo->src.AOH);
assert(commonInfo->dst.AOH);
LOCPLINT->cb->swapArtifacts(ArtifactLocation(commonInfo->src.AOH->curHero, commonInfo->src.slotID),
ArtifactLocation(commonInfo->dst.AOH->curHero, commonInfo->dst.slotID));
}
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);
if(dst.hero == curHero && dst.slot >= GameConstants::BACKPACK_START)
if(isCurHeroDst && dst.slot >= GameConstants::BACKPACK_START)
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);
if (src.hero != curHero && dst.hero != curHero)
if (!src.isHolder(curHero) && !isCurHeroDst)
return;
if(commonInfo->src == src) //artifact was taken from us
{
//assert(commonInfo->dst == dst || dst.slot == dst.hero->artifactsInBackpack.size() + GameConstants::BACKPACK_START);
//FIXME: assertion fails for stack artifacts
assert(commonInfo->dst == dst //expected movement from slot ot slot
|| 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();
unmarkSlots();
}
@ -5110,7 +5099,7 @@ void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const Artifact
CArtPlace *ap = NULL;
BOOST_FOREACH(CArtifactsOfHero *aoh, commonInfo->participants)
{
if(aoh->curHero == dst.hero)
if(dst.isHolder(aoh->curHero))
{
commonInfo->src.AOH = aoh;
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 &&
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);
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)
shift--;
if( (src.hero == curHero && src.slot >= GameConstants::BACKPACK_START)
|| (dst.hero == curHero && dst.slot >= GameConstants::BACKPACK_START) )
if( (isCurHeroSrc && src.slot >= GameConstants::BACKPACK_START)
|| (isCurHeroDst && dst.slot >= GameConstants::BACKPACK_START) )
scrollBackpack(shift); //update backpack slots
}
void CArtifactsOfHero::artifactRemoved(const ArtifactLocation &al)
{
if(al.hero == curHero)
if(al.isHolder(curHero))
{
if(al.slot < GameConstants::BACKPACK_START)
updateWornSlots(0);
@ -5191,13 +5180,13 @@ CArtPlace * CArtifactsOfHero::getArtPlace(int slot)
void CArtifactsOfHero::artifactAssembled(const ArtifactLocation &al)
{
if(al.hero == curHero)
if(al.isHolder(curHero))
updateWornSlots();
}
void CArtifactsOfHero::artifactDisassembled(const ArtifactLocation &al)
{
if(al.hero == curHero)
if(al.isHolder(curHero))
updateWornSlots();
}
@ -6323,21 +6312,11 @@ void CArtifactsOfHero::SCommonPart::Artpos::setTo(const CArtPlace *place, bool d
art = place->ourArt;
}
IArtifactSetBase * CArtifactsOfHero::SCommonPart::Artpos::getArtHolder()
{
if (AOH)
return (IArtifactSetBase*)AOH;
if (CAS)
return (IArtifactSetBase*)CAS;
tlog2 <<"Warning! Artpos without source\n";
return NULL;
}
bool CArtifactsOfHero::SCommonPart::Artpos::operator==(const ArtifactLocation &al) const
{
if(!AOH)
return false;
bool ret = al.hero == AOH->curHero && al.slot == slotID;
bool ret = al.isHolder(AOH->curHero) && al.slot == slotID;
//assert(al.getArt() == art);
return ret;

View File

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

View File

@ -210,30 +210,29 @@ void RebalanceStacks::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 )
{
INTERFACE_CALL_IF_PRESENT(al.hero->tempOwner, artifactRemoved, al);
INTERFACE_CALL_IF_PRESENT(al.owningPlayer(), artifactRemoved, al);
}
void MoveArtifact::applyCl( CClient *cl )
{
INTERFACE_CALL_IF_PRESENT(src.hero->tempOwner, artifactMoved, src, dst);
if (src.hero.get() && dst.hero.get())
if(src.hero->tempOwner != dst.hero->tempOwner)
INTERFACE_CALL_IF_PRESENT(src.hero->tempOwner, artifactMoved, src, dst);
INTERFACE_CALL_IF_PRESENT(src.owningPlayer(), artifactMoved, src, dst);
if(src.owningPlayer() != dst.owningPlayer())
INTERFACE_CALL_IF_PRESENT(src.owningPlayer(), artifactMoved, src, dst);
}
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 )
{
INTERFACE_CALL_IF_PRESENT(al.hero->tempOwner, artifactDisassembled, al);
INTERFACE_CALL_IF_PRESENT(al.owningPlayer(), artifactDisassembled, al);
}
void HeroVisit::applyCl( CClient *cl )

View File

@ -7,7 +7,6 @@
#include "../lib/VCMI_Lib.h"
#include "CSpellHandler.h"
#include "CObjectHandler.h"
//#include "CCreatureSet.h"
#include "NetPacks.h"
extern CLodHandler *bitmaph;
@ -196,8 +195,7 @@ CArtHandler::CArtHandler()
// War machines are the default big artifacts.
for (ui32 i = 3; i <= 6; i++)
bigArtifacts.insert(i);
if (GameConstants::STACK_ARTIFACT)
creatureArtifacts += 141, 142, 143, 156; //basic Wog arts and Warlord's banner
//modableArtifacts = boost::assign::map_list_of(1, 1)(146,3)(147,3)(148,3)(150,3)(151,3)(152,3)(154,3)(156,2);
}
CArtHandler::~CArtHandler()
@ -233,11 +231,13 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
loadToIt(VLC->generaltexth->artifNames[i],buf,it,4);
loadToIt(pom,buf,it,4);
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++)
{
loadToIt(pom,buf,it,4);
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);
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::GEMS);
//Stack artifact test
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(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
@ -910,11 +920,11 @@ void CArtifactInstance::init()
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.
return slot;
@ -925,7 +935,7 @@ int CArtifactInstance::firstAvailableSlot(const CGHeroInstance *h) const
return firstBackpackSlot(h);
}
int CArtifactInstance::firstBackpackSlot(const CGHeroInstance *h) const
int CArtifactInstance::firstBackpackSlot(const CArtifactSet *h) const
{
if(!artType->isBig()) //discard big artifact
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
{
if (al.hero)
{
if(al.slot >= GameConstants::BACKPACK_START)
{
if(artType->isBig())
return false;
//TODO backpack limit
return true;
}
return canBePutAt(al.getHolderArtSet(), al.slot, assumeDestRemoved);
}
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 al.hero->isPositionFree(al.slot, assumeDestRemoved);
//TODO backpack limit
return true;
}
else
if(!vstd::contains(artType->possibleSlots[artSet->bearerType()], slot))
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);
if(slot < GameConstants::BACKPACK_START)
h->attachTo(this);
al.getHolderArtSet()->setNewArtSlot(al.slot, this, false);
if(al.slot < GameConstants::BACKPACK_START)
al.getHolderNode()->attachTo(this);
}
void CArtifactInstance::removeFrom(CGHeroInstance *h, ui16 slot)
void CArtifactInstance::removeFrom(ArtifactLocation &al)
{
assert(h->CArtifactSet::getArt(slot) == this);
h->eraseArtSlot(slot);
if(slot < GameConstants::BACKPACK_START)
h->detachFrom(this);
assert(al.getHolderArtSet()->getArt(al.slot) == this);
al.getHolderArtSet()->eraseArtSlot(al.slot);
if(al.slot < GameConstants::BACKPACK_START)
al.getHolderNode()->detachFrom(this);
//TODO delete me?
}
void CArtifactInstance::putAt(CStackInstance *s, ui16 slot)
{
tlog2 <<"Hero artifacts shouldn't be put on creatures!\n";
}
void CArtifactInstance::removeFrom(CStackInstance *s, ui16 slot)
{
tlog2 <<"Strange, we try to remove hero artifact from CStackInstance\n";
}
bool CArtifactInstance::canBeDisassembled() const
{
return artType->constituents && artType->constituentOf->size();
}
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;
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)
{
if (src.hero)
removeFrom(src.hero, src.slot);
else if (src.stack)
removeFrom(src.stack, src.slot);
else
tlog1 << "No source for moved artifact found!\n";
if (dst.hero)
putAt(dst.hero, dst.slot);
else if (dst.stack)
putAt(dst.stack, dst.slot);
else
tlog1 << "No destination for moved artifact found!\n";
removeFrom(src);
putAt(dst);
}
CArtifactInstance * CArtifactInstance::createNewArtifactInstance(CArtifact *Art)
{
if(!Art->constituents)
{
if (vstd::contains(VLC->arth->creatureArtifacts, Art->id))
return new CCreatureArtifactInstance(Art);
else
return new CArtifactInstance(Art);
}
return new CArtifactInstance(Art);
else
{
CCombinedArtifactInstance * ret = new CCombinedArtifactInstance(Art);
@ -1077,12 +1062,12 @@ bool CArtifactInstance::isPart(const CArtifactInstance *supposedPart) const
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)
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
@ -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
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;
}
//we iterate over all active slots and check if constituents fits them
for (int i = 0; i < GameConstants::BACKPACK_START; i++)
{
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);
break;
@ -1146,31 +1131,35 @@ void CCombinedArtifactInstance::addAsConstituent(CArtifactInstance *art, int slo
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)
ci.slot = -1;
}
else
{
CArtifactInstance *mainConstituent = figureMainConstituent(slot); //it'll be replaced with combined artifact, not a lock
CArtifactInstance::putAt(h, slot); //puts combined art (this)
CArtifactInstance *mainConstituent = figureMainConstituent(al); //it'll be replaced with combined artifact, not a lock
CArtifactInstance::putAt(al); //puts combined art (this)
BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo)
{
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;
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;
else
ci.slot = pos = ci.art->firstAvailableSlot(h);
ci.slot = pos = ci.art->firstAvailableSlot(al.getHolderArtSet());
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
{
@ -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
{
@ -1192,30 +1181,30 @@ void CCombinedArtifactInstance::removeFrom(CGHeroInstance *h, ui16 slot)
{
if(ci.slot >= 0)
{
h->eraseArtSlot(ci.slot);
al.getHolderArtSet()->eraseArtSlot(ci.slot);
ci.slot = -1;
}
else
{
//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
BOOST_FOREACH(ConstituentInfo &ci, constituentsInfo)
if(ci.slot == slot)
if(ci.slot == al.slot)
mainConstituent = ci.art;
if(!mainConstituent)
{
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;
}
@ -1255,58 +1244,8 @@ bool CCombinedArtifactInstance::ConstituentInfo::operator==(const ConstituentInf
{
return art == rhs.art && slot == rhs.slot;
}
CCreatureArtifactInstance::CCreatureArtifactInstance()
{
init();
}
CCreatureArtifactInstance::CCreatureArtifactInstance(CArtifact *Art)
{
init();
setType(Art);
}
bool CCreatureArtifactInstance::isPart(const CArtifactInstance *supposedPart) const
{
return false; //TODO: any other proposals?
}
std::string CCreatureArtifactInstance::nodeName() const
{
return "Creature artifact instance of " + (artType ? artType->Name() : std::string("uninitialized")) + " type";
}
bool CCreatureArtifactInstance::canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved /*= false*/) const
{
if (al.stack)
{
return 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
const CArtifactInstance* CArtifactSet::getArt(ui16 pos, bool excludeLocked /*= true*/) const
{
if(const ArtSlotInfo *si = getSlot(pos))
{
@ -1317,29 +1256,9 @@ const CArtifactInstance* IArtifactSetBase::getArt(ui16 pos, bool excludeLocked)
return NULL;
}
bool IArtifactSetBase::hasArt(ui32 aid, bool onlyWorn) const
CArtifactInstance* CArtifactSet::getArt(ui16 pos, bool excludeLocked /*= true*/)
{
return getArtPos(aid, onlyWorn) != -1;
}
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));
return const_cast<CArtifactInstance*>((const_cast<const CArtifactSet*>(this))->getArt(pos, excludeLocked));
}
si32 CArtifactSet::getArtPos(int aid, bool onlyWorn /*= true*/) const
@ -1384,6 +1303,11 @@ const CArtifactInstance * CArtifactSet::getArtByInstanceId(int artInstId) const
return NULL;
}
bool CArtifactSet::hasArt(ui32 aid, bool onlyWorn /*= false*/) const
{
return getArtPos(aid, onlyWorn) != -1;
}
const ArtSlotInfo * CArtifactSet::getSlot(ui16 pos) const
{
if(vstd::contains(artifactsWorn, pos))
@ -1400,6 +1324,14 @@ const ArtSlotInfo * CArtifactSet::getSlot(ui16 pos) const
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
{
const CArtifactInstance * const a = getArt(pos);
@ -1426,6 +1358,13 @@ ArtSlotInfo & CArtifactSet::retreiveNewArtSlot(ui16 slot)
return ret;
}
void CArtifactSet::setNewArtSlot(ui16 slot, CArtifactInstance *art, bool locked)
{
ArtSlotInfo &asi = retreiveNewArtSlot(slot);
asi.artifact = art;
asi.locked = locked;
}
void CArtifactSet::eraseArtSlot(ui16 slot)
{
if(slot < 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
? activeArtifact
: *artifactsInBackpack.insert(artifactsInBackpack.begin() + (slot - GameConstants::CREATURE_ART), ArtSlotInfo());
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;
}
for(bmap<ui16, ArtSlotInfo>::iterator i = artifactsWorn.begin(); i != artifactsWorn.end(); i++)
if(i->second.artifact && !i->second.locked)
node->attachTo(i->second.artifact);
}

View File

@ -16,9 +16,8 @@
class CDefHandler;
class CArtifact;
class CGHeroInstance;
class CStackInstance;
//class CCreatureArtifactSet;
struct ArtifactLocation;
class CArtifactSet;
namespace ArtifactPosition
{
@ -27,7 +26,17 @@ namespace ArtifactPosition
PRE_FIRST = -1,
HEAD, SHOULDERS, NECK, RIGHT_HAND, LEFT_HAND, TORSO, RIGHT_RING, LEFT_RING, FEET, MISC1, MISC2, MISC3, MISC4,
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;
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> * constituentOf; // Reverse map of constituents.
EartClass aClass;
@ -77,23 +86,22 @@ public:
//CArtifactInstance(int aid);
virtual std::string nodeName() const OVERRIDE;
std::string nodeName() const OVERRIDE;
void deserializationFix();
void setType(CArtifact *Art);
int firstAvailableSlot(const CGHeroInstance *h) const;
int firstBackpackSlot(const CGHeroInstance *h) const;
int firstAvailableSlot(const CArtifactSet *h) const;
int firstBackpackSlot(const CArtifactSet *h) const;
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 void putAt(CGHeroInstance *h, ui16 slot);
virtual void removeFrom(CGHeroInstance *h, ui16 slot);
virtual void putAt(CStackInstance *s, ui16 slot);
virtual void removeFrom(CStackInstance *s, ui16 slot);
virtual void putAt(ArtifactLocation &al);
virtual void removeFrom(ArtifactLocation &al);
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);
template <typename Handler> void serialize(Handler &h, const int version)
@ -127,15 +135,15 @@ public:
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;
void putAt(CGHeroInstance *h, ui16 slot) OVERRIDE;
void removeFrom(CGHeroInstance *h, ui16 slot) OVERRIDE;
void putAt(ArtifactLocation &al) OVERRIDE;
void removeFrom(ArtifactLocation &al) OVERRIDE;
bool isPart(const CArtifactInstance *supposedPart) const OVERRIDE;
void createConstituents();
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();
@ -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
// { //used only for dynamic cast :P
// public:
@ -240,7 +224,7 @@ public:
std::vector< ConstTransitivePtr<CArtifact> > artifacts;
std::vector<CArtifact *> allowedArtifacts;
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 sortArts();
@ -263,7 +247,6 @@ public:
template <typename Handler> void serialize(Handler &h, const int version)
{
h & artifacts & allowedArtifacts & treasures & minors & majors & relics;
h & creatureArtifacts;
//if(!h.saving) sortArts();
}
};
@ -283,67 +266,33 @@ struct DLL_LINKAGE ArtSlotInfo
}
};
class DLL_LINKAGE IArtifactSetBase
{ ///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
class DLL_LINKAGE CArtifactSet
{
public:
std::vector<ArtSlotInfo> artifactsInBackpack; //hero's artifacts from bag
bmap<ui16, ArtSlotInfo> artifactsWorn; //map<position,artifact_id>; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5
ArtSlotInfo &retreiveNewArtSlot(ui16 slot);
void setNewArtSlot(ui16 slot, CArtifactInstance *art, bool locked);
void eraseArtSlot(ui16 slot);
const ArtSlotInfo *getSlot(ui16 pos) const;
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;
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;
virtual ui8 bearerType() const = 0;
virtual ~CArtifactSet();
template <typename Handler> void serialize(Handler &h, const int version)
{
h & artifactsInBackpack & artifactsWorn;
}
};
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;
}
void artDeserializationFix(CBonusSystemNode *node);
};

View File

@ -874,18 +874,6 @@ void CStackInstance::setArmyObj(const 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
{
@ -930,9 +918,7 @@ void CStackInstance::deserializationFix()
const CArmedInstance *armyBackup = _armyObj;
_armyObj = NULL;
setArmyObj(armyBackup);
if(activeArtifact.artifact)
attachTo(activeArtifact.artifact);
artDeserializationFix(this);
}
int CStackInstance::getCreatureID() const
@ -954,6 +940,11 @@ ui64 CStackInstance::getPower() const
return type->AIValue * count;
}
ui8 CStackInstance::bearerType() const
{
return ArtBearer::CREATURE;
}
CStackBasicDescriptor::CStackBasicDescriptor()
{
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
public:
@ -39,7 +39,7 @@ public:
{
h & static_cast<CBonusSystemNode&>(*this);
h & static_cast<CStackBasicDescriptor&>(*this);
h & static_cast<CCreatureArtifactSet&>(*this);
h & static_cast<CArtifactSet&>(*this);
h & _armyObj & experience;
BONUS_TREE_DESERIALIZATION_FIX
}
@ -67,7 +67,8 @@ public:
void setArmyObj(const CArmedInstance *ArmyObj);
void giveStackExp(expType exp);
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();
};

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);
}
void CGameState::init(StartInfo * si, ui32 checksum, int Seed, int expectedPostInitSeed /*= -1*/)
void CGameState::init(StartInfo * si)
{
struct HLP
{
@ -852,7 +852,7 @@ void CGameState::init(StartInfo * si, ui32 checksum, int Seed, int expectedPostI
case 4: //spell scroll
{
CArtifactInstance * scroll = CArtifactInstance::createScroll(VLC->spellh->spells[curBonus.info2]);
scroll->putAt(hero, scroll->firstAvailableSlot(hero));
scroll->putAt(ArtifactLocation(hero, scroll->firstAvailableSlot(hero)));
}
break;
case 5: //prim skill
@ -904,8 +904,8 @@ void CGameState::init(StartInfo * si, ui32 checksum, int Seed, int expectedPostI
}
};
seed = Seed;
ran.seed((boost::int32_t)seed);
tlog0 << "\tUsing random seed: "<< si->seedToBeUsed << std::endl;
ran.seed((boost::int32_t)si->seedToBeUsed);
scenarioOps = new StartInfo(*si);
initialOpts = new StartInfo(*si);
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;
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 << "\tOur checksum for the map: "<< map->checksum << std::endl;
if(map->checksum != checksum)
tlog0 << "\tServer checksum for " << scenarioOps->mapname <<": "<< scenarioOps->mapfileChecksum << std::endl;
if(map->checksum != scenarioOps->mapfileChecksum)
{
tlog1 << "Wrong map checksum!!!" << std::endl;
throw std::string("Wrong checksum");
}
}
else
scenarioOps->mapfileChecksum = map->checksum;
day = 0;
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
if(expectedPostInitSeed >= 0)
if(scenarioOps->seedPostInit > 0)
{
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
CArtifactInstance *ai = CArtifactInstance::createNewArtifactInstance(artifact);
map->addNewArtifactInstance(ai);
ai->putAt(h, ai->firstAvailableSlot(h));
ai->putAt(ArtifactLocation(h, ai->firstAvailableSlot(h)));
}
int3 CPath::startPos() const

View File

@ -348,7 +348,6 @@ class DLL_LINKAGE CGameState : public CNonConstInfoCallback
public:
ConstTransitivePtr<StartInfo> scenarioOps, initialOpts; //second one is a copy of settings received from pregame (not randomized)
ConstTransitivePtr<CCampaignState> campaign;
ui32 seed;
ui8 currentPlayer; //ID of player currently having turn
ConstTransitivePtr<BattleInfo> curB; //current battle
ui32 day; //total number of days in game
@ -374,7 +373,7 @@ public:
boost::shared_mutex *mx;
void init(StartInfo * si, ui32 checksum, int Seed, int expectedPostInitSeed = -1);
void init(StartInfo * si);
void loadTownDInfos();
void randomizeObject(CGObjectInstance *cur);
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
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;
if(!h.saving)
{

View File

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

View File

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

View File

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

View File

@ -20,9 +20,10 @@
#include "ConstTransitivePtr.h"
const ui32 version = 731;
const ui32 version = 732;
class CConnection;
class CGObjectInstance;
class CStackInstance;
class CGameState;
class CCreature;
class LibClasses;
@ -246,6 +247,7 @@ public:
TTypeVecMap vectors; //entry must be a pointer to vector containing pointers to the objects of key type
bool smartVectorMembersSerialization;
bool sendStackInstanceByIds;
CSerializer();
~CSerializer();
@ -344,6 +346,63 @@ struct VectorisedTypeFor
>::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.
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)
{
@ -552,6 +617,15 @@ public:
for(typename std::map<T1,T2>::const_iterator i=data.begin();i!=data.end();i++)
*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));
}
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
typedef typename boost::remove_const<T>::type nonConstT;
@ -672,6 +747,12 @@ public:
hlp.serialize(*this,myVersion);
//data.serialize(*this,myVersion);
}
template <typename T>
void loadSerializable(T &data)
{
loadSerializableBySerializeCall(data);
}
template <typename T>
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)
if(smartPointerSerialization)
{
@ -832,10 +920,43 @@ public:
data.resize(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
: public COSer<CSaveFile>
{

View File

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

View File

@ -1,7 +1,5 @@
#pragma once
#include <boost/range.hpp>
#include "GameConstants.h"
/*
@ -31,10 +29,7 @@ typedef std::set<const CBonusSystemNode*> TCNodes;
typedef std::vector<CBonusSystemNode *> TNodesVector;
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();

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 putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) = 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 heroVisitCastle(int obj, int heroID)=0;

View File

@ -845,34 +845,52 @@ typedef si32 TArtPos;
struct ArtifactLocation
{
ConstTransitivePtr<CGHeroInstance> hero;
ConstTransitivePtr<CStackInstance> stack;
typedef boost::variant<ConstTransitivePtr<CGHeroInstance>, ConstTransitivePtr<CStackInstance> > TArtHolder;
TArtHolder artHolder;
TArtPos slot;
ArtifactLocation()
{
artHolder = ConstTransitivePtr<CGHeroInstance>();
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;
}
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!
hero = NULL;
artHolder = ArtHolder;
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 CArtifactInstance *getArt();
DLL_LINKAGE const ArtSlotInfo *getSlot() const;
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
//TODO: allow exchange between heroes, stacks and commanders
{
ArtifactLocation src, dst;
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);
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);
}
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
{
const ArtSlotInfo *s = getSlot();
@ -552,6 +594,18 @@ DLL_LINKAGE const CArtifactInstance *ArtifactLocation::getArt() const
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()
{
const ArtifactLocation *t = this;
@ -560,11 +614,7 @@ DLL_LINKAGE CArtifactInstance *ArtifactLocation::getArt()
DLL_LINKAGE const ArtSlotInfo *ArtifactLocation::getSlot() const
{
if (hero)
return hero->getSlot(slot);
if (stack)
return stack->getSlot(slot);
return NULL;
return getHolderArtSet()->getSlot(slot);
}
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 )
{
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 )
{
CArtifactInstance *a = al.getArt();
assert(a);
a->removeFrom(al.hero, al.slot);
a->removeFrom(al);
}
DLL_LINKAGE void MoveArtifact::applyGs( CGameState *gs )
@ -681,49 +732,58 @@ DLL_LINKAGE void MoveArtifact::applyGs( CGameState *gs )
a->move(src, dst);
//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
gs->giveHeroArtifact(dst.hero, 0);
if (a->artType->id == 135 && dst.slot == ArtifactPosition::RIGHT_HAND) //Titan's Thunder creates new spellbook on equip
{
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 )
{
CGHeroInstance *h = al.hero;
CArtifactSet *artSet = al.getHolderArtSet();
const CArtifactInstance *transformedArt = al.getArt();
assert(transformedArt);
assert(vstd::contains(transformedArt->assemblyPossibilities(al.hero), builtArt));
assert(vstd::contains(transformedArt->assemblyPossibilities(artSet), builtArt));
CCombinedArtifactInstance *combinedArt = new CCombinedArtifactInstance(builtArt);
gs->map->addNewArtifactInstance(combinedArt);
//retrieve all constituents
BOOST_FOREACH(si32 constituentID, *builtArt->constituents)
{
int pos = h->getArtPos(constituentID);
int pos = artSet->getArtPos(constituentID);
assert(pos >= 0);
CArtifactInstance *constituentInstance = h->getArt(pos);
CArtifactInstance *constituentInstance = artSet->getArt(pos);
//move constituent from hero to be part of new, combined artifact
constituentInstance->removeFrom(h, pos);
constituentInstance->removeFrom(al);
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;
}
//put new combined artifacts
combinedArt->putAt(h, al.slot);
combinedArt->putAt(al);
}
DLL_LINKAGE void DisassembledArtifact::applyGs( CGameState *gs )
{
CGHeroInstance *h = al.hero;
CCombinedArtifactInstance *disassembled = dynamic_cast<CCombinedArtifactInstance*>(al.getArt());
assert(disassembled);
std::vector<CCombinedArtifactInstance::ConstituentInfo> constituents = disassembled->constituentsInfo;
disassembled->removeFrom(h, al.slot);
disassembled->removeFrom(al);
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);
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);

View File

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

View File

@ -58,6 +58,9 @@ struct StartInfo
typedef bmap<int, PlayerSettings> TPlayerInfos;
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
std::string mapname;
ui8 whichMapInCampaign; //used only for mode CAMPAIGN
@ -84,6 +87,8 @@ struct StartInfo
h & mode;
h & difficulty;
h & playerInfos;
h & seedToBeUsed & seedPostInit;
h & mapfileChecksum;
h & turnTime;
h & mapname;
h & whichMapInCampaign;
@ -92,6 +97,7 @@ struct StartInfo
StartInfo()
{
mapfileChecksum = seedPostInit = seedToBeUsed = 0;
mode = INVALID;
choosenCampaignBonus = -1;
}

View File

@ -794,7 +794,6 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
CGameHandler::CGameHandler(void)
{
seedInitial = seedPostInit = -1;
QID = 1;
//gs = NULL;
IObjectInterface::cb = this;
@ -814,13 +813,12 @@ CGameHandler::~CGameHandler(void)
void CGameHandler::init(StartInfo *si)
{
extern DLL_LINKAGE boost::rand48 ran;
if(seedInitial < 0)
seedInitial = std::time(NULL);
if(!si->seedToBeUsed)
si->seedToBeUsed = std::time(NULL);
gs = new CGameState();
tlog0 << "Gamestate created!" << std::endl;
gs->init(si, 0, seedInitial);
seedPostInit = ran();
gs->init(si);
tlog0 << "Gamestate initialized!" << std::endl;
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;
if(!resume)
{
ui32 sum = gs->map ? gs->map->checksum : 612;
(*cc) << gs->initialOpts << sum << gs->seed << seedPostInit; // gs->scenarioOps
(*cc) << gs->initialOpts; // gs->scenarioOps
}
(*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.
// 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);
const CGHeroInstance *destHero = getHero(destHeroID);
ArtifactLocation src(srcHero, srcSlot), dst(destHero, destSlot);
ArtifactLocation src = al1, dst = al2;
const int srcPlayer = src.owningPlayer(), dstPlayer = dst.owningPlayer();
const CArmedInstance *srcObj = src.relatedObj(), *dstObj = dst.relatedObj();
// 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!");
const CArtifactInstance *srcArtifact = src.getArt();
@ -2518,72 +2515,38 @@ bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, u
if (srcArtifact == NULL)
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!");
// Check if src/dest slots are appropriate for the artifacts exchanged.
// 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))
COMPLAIN_RET("Cannot move artifact!");
if ((srcArtifact && srcArtifact->artType->id == GameConstants::ID_LOCK) || (destArtifact && destArtifact->artType->id == GameConstants::ID_LOCK))
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!");
if (srcSlot == ArtifactPosition::MACH4 || destSlot == ArtifactPosition::MACH4)
if (src.slot == ArtifactPosition::MACH4 || dst.slot == ArtifactPosition::MACH4)
COMPLAIN_RET("Cannot move catapult!");
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!");
//moving art to backpack is always allowed (we've ruled out exceptions)
if(destSlot >= GameConstants::BACKPACK_START)
if(dst.slot < GameConstants::BACKPACK_START && destArtifact) //moving art to another slot
{
moveArtifact(src, dst);
}
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);
//old artifact must be removed first
moveArtifact(dst, ArtifactLocation(dst.artHolder, dst.getHolderArtSet()->artifactsInBackpack.size() + GameConstants::BACKPACK_START));
}
return true;
}
bool CGameHandler::moveArtifact(StackLocation s1, StackLocation s2, ui16 srcSlot, ui16 destSlot)
{
ArtifactLocation src(s1.getStack(), srcSlot), dst(s2.getStack(), destSlot);
moveArtifact(src, dst);
return true;
}
bool CGameHandler::moveArtifact(si32 srcHeroID, StackLocation s2, ui16 srcSlot, ui16 destSlot)
{
ArtifactLocation src(getHero(srcHeroID), srcSlot);
ArtifactLocation dst(s2.getStack(), destSlot);
moveArtifact(src, dst);
return true;
}
bool CGameHandler::moveArtifact(StackLocation s1, si32 destHeroID, ui16 srcSlot, ui16 destSlot)
{
ArtifactLocation src(s1.getStack(), srcSlot);
ArtifactLocation dst(getHero(destHeroID), destSlot);
//hero should not wear stack artifact
vstd::amin(dst.slot, GameConstants::BACKPACK_START + dst.hero->artifactsInBackpack.size()); //put on first free position
moveArtifact(src, dst);
return true;
}
void CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2)
{
MoveArtifact ma;
ma.src = al1;
ma.dst = al2;
ma.src = src;
ma.dst = dst;
sendAndApply(&ma);
}
@ -5550,7 +5513,7 @@ void CGameHandler::giveHeroArtifact(const CGHeroInstance *h, const CArtifactInst
{
assert(a->artType);
ArtifactLocation al;
al.hero = h;
al.artHolder = const_cast<CGHeroInstance*>(h);
int slot = -1;
if(pos < 0)
@ -5588,10 +5551,7 @@ void CGameHandler::giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact
CArtifactInstance *a = NULL;
if(!artType->constituents)
{
if (vstd::contains(VLC->arth->creatureArtifacts, artType->id))
a = new CCreatureArtifactInstance();
else
a = new CArtifactInstance();
a = new CArtifactInstance();
}
else
{

View File

@ -91,8 +91,6 @@ public:
PlayerStatuses states; //player color -> player state
std::set<CConnection*> conns;
si32 seedInitial, seedPostInit;
//queries stuff
boost::recursive_mutex gsm;
ui32 QID;
@ -158,7 +156,7 @@ public:
void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, int pos) OVERRIDE;
void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) 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 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 sellArtifact( const IMarket *m, const CGHeroInstance *h, int aid, int rid); //for artifact merchant selling
bool buySecSkill( const IMarket *m, const CGHeroInstance *h, int skill);
bool moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, ui16 destSlot);
bool moveArtifact(StackLocation s1, StackLocation s2, ui16 srcSlot, ui16 destSlot); //called when stacks merge
bool moveArtifact(si32 srcHeroID, StackLocation s2, ui16 srcSlot, ui16 destSlot); //equip artifact
bool moveArtifact(StackLocation s1, si32 destHeroID, ui16 srcSlot, ui16 destSlot); //return artifact to backpack
bool garrisonSwap(si32 tid);
bool upgradeCreature( ui32 objid, ui8 pos, ui32 upgID );
bool recruitCreatures(si32 objid, ui32 crid, ui32 cram, si32 level);

View File

@ -133,21 +133,8 @@ bool GarrisonHeroSwap::applyGh( CGameHandler *gh )
bool ExchangeArtifacts::applyGh( CGameHandler *gh )
{
ERROR_IF_NOT_OWNS(hid1);//second hero can be ally
if (hid1)
{ //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);
}
ERROR_IF_NOT(src.owningPlayer());//second hero can be ally
return gh->moveArtifact(src, dst);
}
bool AssembleArtifacts::applyGh( CGameHandler *gh )