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

Serializer will now smartly send over network CArtifact* and CHero*. Unified handling of items stored in vector.

Started making support for Black Market / Artifact merchant.
This commit is contained in:
Michał W. Urbańczyk 2010-06-26 16:02:10 +00:00
parent 627a1a5905
commit ec6342d9a7
20 changed files with 367 additions and 278 deletions

View File

@ -798,7 +798,7 @@ void CCastleInterface::enterBlacksmith(int ArtifactID)
LOCPLINT->showInfoDialog(pom,std::vector<SComponent*>(), soundBase::sound_todo);
return;
}
int price = CGI->arth->artifacts[ArtifactID].price;
int price = CGI->arth->artifacts[ArtifactID]->price;
bool possible = (LOCPLINT->cb->getResourceAmount(6) >= price);
if(vstd::contains(hero->artifWorn,ui16(ArtifactID+9))) //hero already has machine
possible = false;
@ -1218,7 +1218,7 @@ void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
for(std::list<Bonus>::const_iterator i=ch->bonuses.begin(); i != ch->bonuses.end(); i++)
if(i->type == Bonus::CREATURE_GROWTH && i->subtype == level)
if (i->source == Bonus::ARTIFACT)
summ+=AddToString(CGI->arth->artifacts[i->id].Name()+" %+d",descr,i->val);
summ+=AddToString(CGI->arth->artifacts[i->id]->Name()+" %+d",descr,i->val);
};
ch = ci->town->visitingHero;
};
@ -2056,7 +2056,7 @@ CBlacksmithDialog::CBlacksmithDialog(bool possible, int creMachineID, int aid, i
sprintf(pom,CGI->generaltexth->allTexts[274].c_str(),CGI->creh->creatures[creMachineID]->nameSing.c_str()); //build a new ...
printAtMiddle(pom,165,28,FONT_MEDIUM,tytulowy,bmp);
printAtMiddle(CGI->generaltexth->jktexts[43],165,218,FONT_MEDIUM,zwykly,bmp); //resource cost
SDL_itoa(CGI->arth->artifacts[aid].price,pom,10);
SDL_itoa(CGI->arth->artifacts[aid]->price,pom,10);
printAtMiddle(pom,165,290,FONT_MEDIUM,zwykly,bmp);
pos.w = bmp->w;

View File

@ -820,7 +820,7 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero)
else
{
artifacts[i]->text = CGI->generaltexth->artifDescriptions[artifacts[i]->type];
artifacts[i]->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % CGI->arth->artifacts[artifacts[i]->type].Name());
artifacts[i]->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % CGI->arth->artifacts[artifacts[i]->type]->Name());
}
}
@ -832,7 +832,7 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero)
else
{
backpack[i]->text = CGI->generaltexth->artifDescriptions[backpack[i]->type];
backpack[i]->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % CGI->arth->artifacts[backpack[i]->type].Name());
backpack[i]->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % CGI->arth->artifacts[backpack[i]->type]->Name());
}
}
@ -883,7 +883,7 @@ void CKingdomInterface::CHeroItem::scrollArts(int move)
else
{
backpack[i]->text = CGI->generaltexth->artifDescriptions[backpack[i]->type];
backpack[i]->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % CGI->arth->artifacts[backpack[i]->type].Name());
backpack[i]->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % CGI->arth->artifacts[backpack[i]->type]->Name());
}
}
showAll(screen2);

View File

@ -1109,13 +1109,13 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer
*/
void CPlayerInterface::showArtifactAssemblyDialog (ui32 artifactID, ui32 assembleTo, bool assemble, CFunctionList<void()> onYes, CFunctionList<void()> onNo)
{
const CArtifact &artifact = CGI->arth->artifacts[artifactID];
const CArtifact &artifact = *CGI->arth->artifacts[artifactID];
std::string text = artifact.Description();
text += "\n\n";
std::vector<SComponent*> scs;
if (assemble) {
const CArtifact &assembledArtifact = CGI->arth->artifacts[assembleTo];
const CArtifact &assembledArtifact = *CGI->arth->artifacts[assembleTo];
// You possess all of the components to...
text += boost::str(boost::format(CGI->generaltexth->allTexts[732]) % assembledArtifact.Name());

View File

@ -281,7 +281,7 @@ void CClient::loadGame( const std::string & fname )
tlog0 <<"Waiting for server: "<<tmh.getDif()<<std::endl;
serv = new CConnection(conf.cc.server,portc,NAME);
serv->setGS(gs);
serv->addStdVecItems(gs);
tlog0 <<"Setting up connection: "<<tmh.getDif()<<std::endl;
ui8 pom8;
@ -356,7 +356,6 @@ void CClient::newGame( CConnection *con, StartInfo *si )
CGI->state = new CGameState();
tlog0 <<"\tGamestate: "<<tmh.getDif()<<std::endl;
serv = con;
serv->setGS(CGI->state);
CConnection &c(*con);
////////////////////////////////////////////////////
ui8 pom8;
@ -411,6 +410,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
playerint[color]->init(cb);
}
serv->addStdVecItems(CGI->state);
hotSeat = (humanPlayers > 1);
playerint[255] = CAIHandler::getNewAI(cb,conf.cc.defaultAI);

View File

@ -845,8 +845,8 @@ void SComponent::init(Etype Type, int Subtype, int Val)
switch (Type)
{
case artifact:
description = CGI->arth->artifacts[Subtype].Description();
subtitle = CGI->arth->artifacts[Subtype].Name();
description = CGI->arth->artifacts[Subtype]->Description();
subtitle = CGI->arth->artifacts[Subtype]->Name();
break;
case primskill:
oss << std::showpos << Val << " ";

View File

@ -70,8 +70,9 @@ bool CArtifact::fitsAt (const std::map<ui16, ui32> &artifWorn, ui16 slotID) cons
VLC->arth->unequipArtifact(tempArtifWorn, slotID);
BOOST_FOREACH(ui32 constituentID, *constituents) {
const CArtifact& constituent = VLC->arth->artifacts[constituentID];
BOOST_FOREACH(ui32 constituentID, *constituents)
{
const CArtifact& constituent = *VLC->arth->artifacts[constituentID];
const int slot = constituent.possibleSlots[0];
if (slot == 6 || slot == 7)
@ -107,7 +108,7 @@ bool CArtifact::canBeAssembledTo (const std::map<ui16, ui32> &artifWorn, ui32 ar
if (constituentOf == NULL || !vstd::contains(*constituentOf, artifactID))
return false;
const CArtifact &artifact = VLC->arth->artifacts[artifactID];
const CArtifact &artifact = *VLC->arth->artifacts[artifactID];
assert(artifact.constituents);
BOOST_FOREACH(ui32 constituentID, *artifact.constituents) {
@ -135,8 +136,9 @@ void CArtifact::addBonusesTo (BonusList *otherBonuses) const
otherBonuses->push_back(*i);
if (constituents != NULL) {
BOOST_FOREACH(ui32 artifactID, *constituents) {
VLC->arth->artifacts[artifactID].addBonusesTo(otherBonuses);
BOOST_FOREACH(ui32 artifactID, *constituents)
{
VLC->arth->artifacts[artifactID]->addBonusesTo(otherBonuses);
}
}
}
@ -149,7 +151,7 @@ void CArtifact::removeBonusesFrom (BonusList *otherBonuses) const
{
if (constituents != NULL) {
BOOST_FOREACH(ui32 artifactID, *constituents) {
VLC->arth->artifacts[artifactID].removeBonusesFrom(otherBonuses);
VLC->arth->artifacts[artifactID]->removeBonusesFrom(otherBonuses);
}
}
@ -174,9 +176,9 @@ CArtHandler::CArtHandler()
CArtHandler::~CArtHandler()
{
for (std::vector<CArtifact>::iterator it = artifacts.begin(); it != artifacts.end(); ++it) {
delete it->constituents;
delete it->constituentOf;
for (std::vector<CArtifact*>::iterator it = artifacts.begin(); it != artifacts.end(); ++it) {
delete (*it)->constituents;
delete (*it)->constituentOf;
}
}
@ -196,7 +198,8 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
VLC->generaltexth->artifDescriptions.resize(ARTIFACTS_QUANTITY);
for (int i=0; i<ARTIFACTS_QUANTITY; i++)
{
CArtifact nart;
CArtifact *art = new CArtifact;
CArtifact &nart = *art;
nart.id=i;
loadToIt(VLC->generaltexth->artifNames[i],buf,it,4);
loadToIt(pom,buf,it,4);
@ -290,7 +293,7 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
break;
}
artifacts.push_back(nart);
artifacts.push_back(&nart);
}
sortArts();
if(onlyTxt)
@ -299,12 +302,15 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
addBonuses();
// Populate reverse mappings of combinational artifacts.
BOOST_FOREACH(CArtifact artifact, artifacts) {
if (artifact.constituents != NULL) {
BOOST_FOREACH(ui32 constituentID, *artifact.constituents) {
if (artifacts[constituentID].constituentOf == NULL)
artifacts[constituentID].constituentOf = new std::vector<ui32>();
artifacts[constituentID].constituentOf->push_back(artifact.id);
BOOST_FOREACH(CArtifact *artifact, artifacts)
{
if (artifact->constituents != NULL)
{
BOOST_FOREACH(ui32 constituentID, *artifact->constituents)
{
if (artifacts[constituentID]->constituentOf == NULL)
artifacts[constituentID]->constituentOf = new std::vector<ui32>();
artifacts[constituentID]->constituentOf->push_back(artifact->id);
}
}
}
@ -345,19 +351,19 @@ void CArtHandler::sortArts()
{
for(int i=0;i<144;i++) //do 144, bo nie chcemy bzdurek
{
switch (artifacts[i].aClass)
switch (artifacts[i]->aClass)
{
case CArtifact::ART_TREASURE:
treasures.push_back(&(artifacts[i]));
treasures.push_back(artifacts[i]);
break;
case CArtifact::ART_MINOR:
minors.push_back(&(artifacts[i]));
minors.push_back(artifacts[i]);
break;
case CArtifact::ART_MAJOR:
majors.push_back(&(artifacts[i]));
majors.push_back(artifacts[i]);
break;
case CArtifact::ART_RELIC:
relics.push_back(&(artifacts[i]));
relics.push_back(artifacts[i]);
break;
}
}
@ -368,8 +374,8 @@ void CArtHandler::giveArtBonus( int aid, Bonus::BonusType type, int val, int sub
Bonus added(Bonus::PERMANENT,type,Bonus::ARTIFACT,val,aid,subtype);
added.valType = valType;
if(type == Bonus::MORALE || Bonus::LUCK)
added.description = "\n" + artifacts[aid].Name() + (val > 0 ? " +" : " ") + boost::lexical_cast<std::string>(val);
artifacts[aid].bonuses.push_back(added);
added.description = "\n" + artifacts[aid]->Name() + (val > 0 ? " +" : " ") + boost::lexical_cast<std::string>(val);
artifacts[aid]->bonuses.push_back(added);
}
void CArtHandler::addBonuses()
@ -614,7 +620,10 @@ void CArtHandler::addBonuses()
void CArtHandler::clear()
{
BOOST_FOREACH(CArtifact *art, artifacts)
delete art;
artifacts.clear();
treasures.clear();
minors.clear();
majors.clear();
@ -632,23 +641,30 @@ void CArtHandler::equipArtifact
{
unequipArtifact(artifWorn, slotID, bonuses);
const CArtifact &artifact = artifacts[artifactID];
const CArtifact &artifact = *artifacts[artifactID];
// Add artifact.
artifWorn[slotID] = artifactID;
// Add locks, in reverse order of being removed.
if (artifact.constituents != NULL) {
if (artifact.constituents != NULL)
{
bool destConsumed = false; // Determines which constituent that will be counted for together with the artifact.
BOOST_FOREACH(ui32 constituentID, *artifact.constituents) {
const CArtifact &constituent = artifacts[constituentID];
BOOST_FOREACH(ui32 constituentID, *artifact.constituents)
{
const CArtifact &constituent = *artifacts[constituentID];
if (!destConsumed && vstd::contains(constituent.possibleSlots, slotID)) {
if (!destConsumed && vstd::contains(constituent.possibleSlots, slotID))
{
destConsumed = true;
} else {
BOOST_FOREACH(ui16 slot, constituent.possibleSlots) {
if (!vstd::contains(artifWorn, slot)) {
}
else
{
BOOST_FOREACH(ui16 slot, constituent.possibleSlots)
{
if (!vstd::contains(artifWorn, slot))
{
artifWorn[slot] = 145;
break;
}
@ -673,23 +689,30 @@ void CArtHandler::unequipArtifact
if (!vstd::contains(artifWorn, slotID))
return;
const CArtifact &artifact = artifacts[artifWorn[slotID]];
const CArtifact &artifact = *artifacts[artifWorn[slotID]];
// Remove artifact, if it's not already removed.
artifWorn.erase(slotID);
// Remove locks, in reverse order of being added.
if (artifact.constituents != NULL) {
if (artifact.constituents != NULL)
{
bool destConsumed = false;
BOOST_FOREACH(ui32 constituentID, *artifact.constituents) {
const CArtifact &constituent = artifacts[constituentID];
BOOST_FOREACH(ui32 constituentID, *artifact.constituents)
{
const CArtifact &constituent = *artifacts[constituentID];
if (!destConsumed && vstd::contains(constituent.possibleSlots, slotID)) {
if (!destConsumed && vstd::contains(constituent.possibleSlots, slotID))
{
destConsumed = true;
} else {
BOOST_REVERSE_FOREACH(ui16 slot, constituent.possibleSlots) {
if (vstd::contains(artifWorn, slot) && artifWorn[slot] == 145) {
}
else
{
BOOST_REVERSE_FOREACH(ui16 slot, constituent.possibleSlots)
{
if (vstd::contains(artifWorn, slot) && artifWorn[slot] == 145)
{
artifWorn.erase(slot);
break;
}

View File

@ -36,7 +36,7 @@ public:
std::vector<ui32> * constituents; // Artifacts IDs a combined artifact consists of, or NULL.
std::vector<ui32> * constituentOf; // Reverse map of constituents.
EartClass aClass;
ui32 id;
si32 id;
std::list<Bonus> bonuses; //bonuses given by artifact
template <typename Handler> void serialize(Handler &h, const int version)
@ -50,7 +50,7 @@ class DLL_EXPORT CArtHandler //handles artifacts
void giveArtBonus(int aid, Bonus::BonusType type, int val, int subtype = -1, int valType = Bonus::BASE_NUMBER);
public:
std::vector<CArtifact*> treasures, minors, majors, relics;
std::vector<CArtifact> artifacts;
std::vector<CArtifact *> artifacts;
std::set<ui32> bigArtifacts; // Artifacts that cannot be moved to backpack, e.g. war machines.
void loadArtifacts(bool onlyTxt);

View File

@ -36,7 +36,7 @@ public:
std::string abilityText; //description of abilities
std::string abilityRefs; //references to abilities, in textformat
std::string animDefName;
ui32 idNumber;
si32 idNumber;
si8 faction; //-1 = neutral
ui8 doubleWide;

View File

@ -27,7 +27,7 @@ public:
BARBARIAN, BATTLEMAGE, BEASTMASTER, WITCH, PLANESWALKER, ELEMENTALIST};
std::string name; //name of hero
ui16 ID;
si32 ID;
ui32 lowStack[3], highStack[3]; //amount of units; described below
std::string refTypeStack[3]; //reference names of units appearing in hero's army if he is recruited in tavern
CHeroClass * heroClass;

View File

@ -46,11 +46,12 @@ extern boost::rand48 ran;
std::map <ui8, std::set <ui8> > CGKeys::playerKeyMap;
std::map <si32, std::vector<si32> > CGMagi::eyelist;
BankConfig CGPyramid::pyramidConfig;
std::map<ui16, Component*> CGArtMerchant::advMapArts;
std::map<ui16, Component*> CGArtMerchant::townArts;
ui8 CGObelisk::obeliskCount; //how many obelisks are on map
std::map<ui8, ui8> CGObelisk::visited; //map: color_id => how many obelisks has been visited
std::vector<const CArtifact *> CGTownInstance::merchantArtifacts;
void IObjectInterface::onHeroVisit(const CGHeroInstance * h) const
{};
@ -694,7 +695,7 @@ const CArtifact * CGHeroInstance::getArt(int pos) const
{
int id = getArtAtPos(pos);
if(id>=0)
return &VLC->arth->artifacts[id];
return VLC->arth->artifacts[id];
else
return NULL;
}
@ -1098,16 +1099,21 @@ si32 CGHeroInstance::getArtPos(int aid) const
*/
void CGHeroInstance::giveArtifact (ui32 aid)
{
const CArtifact &artifact = VLC->arth->artifacts[aid];
const CArtifact &artifact = *VLC->arth->artifacts[aid];
if (artifact.isBig()) {
for (std::vector<ui16>::const_iterator it = artifact.possibleSlots.begin(); it != artifact.possibleSlots.end(); ++it) {
if (!vstd::contains(artifWorn, *it)) {
if (artifact.isBig())
{
for (std::vector<ui16>::const_iterator it = artifact.possibleSlots.begin(); it != artifact.possibleSlots.end(); ++it)
{
if (!vstd::contains(artifWorn, *it))
{
VLC->arth->equipArtifact(artifWorn, *it, aid, &bonuses);
break;
}
}
} else {
}
else
{
artifacts.push_back(aid);
}
}
@ -1118,7 +1124,7 @@ void CGHeroInstance::recreateArtBonuses()
bonuses.remove_if(boost::bind(Bonus::IsFrom,_1,Bonus::ARTIFACT,0xffffff));
for (std::map<ui16,ui32>::iterator ari = artifWorn.begin(); ari != artifWorn.end(); ari++)
{
CArtifact &art = VLC->arth->artifacts[ari->second];
CArtifact &art = *VLC->arth->artifacts[ari->second];
art.addBonusesTo(&bonuses);
}
}
@ -1761,6 +1767,39 @@ void CGTownInstance::newTurn() const
cb->setObjProperty (id, 12, (*i)->id); //reset visitors for Mana Vortex
}
}
if(cb->getDate(2) == 1) //reset on new month
{
std::vector<CArtifact*>::iterator index;
for (ui8 i = 0; i < 3; ++i) //each tier
{
int count = 0;
std::vector<CArtifact*> arts; //to avoid addition of different tiers
switch (i)
{
case 0:
cb->getAllowed (arts, CArtifact::ART_TREASURE);
count = 3; // first row - three treasures,
break;
case 1:
cb->getAllowed (arts, CArtifact::ART_MINOR);
count = 3; // second row three minors
break;
case 2:
cb->getAllowed (arts, CArtifact::ART_MAJOR);
count = 1; // and a third row - one major
break;
}
for (ui8 n = 0; n < count; n++)
{
// index = arts.begin() + val % arts.size();
// advMapArts [advMapArts.size()] = new Component (Component::ARTIFACT, (*index)->id, 0, 0);
// arts.erase(index);
// val *= (id + n * i); //randomize
}
}
}
}
int3 CGTownInstance::getSightCenter() const
@ -3027,7 +3066,7 @@ void CGArtifact::initObj()
{
blockVisit = true;
if(ID == 5)
hoverName = VLC->arth->artifacts[subID].Name();
hoverName = VLC->arth->artifacts[subID]->Name();
}
void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
@ -5791,41 +5830,6 @@ void CShop::setPropertyDer (ui8 what, ui32 val)
break;
}
}
void CGArtMerchant::reset(ui32 val)
{//TODO: it should have 2 global pools instead of unique for each merchant:
// 1) for town merchants - resets every month,
// 2) for adv. map - resets only on game start
std::vector<CArtifact*>::iterator index;
for (ui8 i = 0; i < 3; ++i) //each tier
{
int count = 0;
std::vector<CArtifact*> arts; //to avoid addition of different tiers
switch (i)
{
case 0:
cb->getAllowed (arts, CArtifact::ART_TREASURE);
count = 3; // first row - three treasures,
break;
case 1:
cb->getAllowed (arts, CArtifact::ART_MINOR);
count = 3; // second row three minors
break;
case 2:
cb->getAllowed (arts, CArtifact::ART_MAJOR);
count = 1; // and a third row - one major
break;
}
for (ui8 n = 0; n < count; n++)
{
index = arts.begin() + val % arts.size();
advMapArts [advMapArts.size()] = new Component (Component::ARTIFACT, (*index)->id, 0, 0);
arts.erase(index);
val *= (id + n * i); //randomize
}
}
}
void CGRefugeeCamp::reset(ui32 val)
{
@ -6186,16 +6190,6 @@ void CGMarket::onHeroVisit(const CGHeroInstance * h) const
cb->sendAndApply(&ow);
}
void CGMarket::initObj()
{
}
void CGMarket::newTurn() const
{
}
int CGMarket::getMarketEfficiency() const
{
return 5;
@ -6241,4 +6235,35 @@ std::vector<int> CGMarket::availableItemsIds(EMarketMode mode) const
CGMarket::CGMarket()
:IMarket(this)
{
}
std::vector<int> CGBlackMarket::availableItemsIds(EMarketMode mode) const
{
switch(mode)
{
case ARTIFACT_RESOURCE:
return IMarket::availableItemsIds(mode);
case RESOURCE_ARTIFACT:
{
std::vector<int> ret;
BOOST_FOREACH(const CArtifact *a, artifacts)
if(a)
ret.push_back(a->id);
else
ret.push_back(-1);
return ret;
}
default:
return std::vector<int>();
}
}
void CGBlackMarket::initObj()
{
}
void CGBlackMarket::newTurn() const
{
}

View File

@ -487,7 +487,7 @@ public:
std::pair<si32, si32> bonusValue;//var to store town bonuses (rampart = resources from mystic pond);
//////////////////////////////////////////////////////////////////////////
static std::vector<const CArtifact *> merchantArtifacts; //vector of artifacts available at Artifact merchant, NULLs possible (for making empty space when artifact is bought)
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -1095,21 +1095,6 @@ public:
}
};
class DLL_EXPORT CGArtMerchant : public CShop
{
///aka Black Market
public:
static std::map<ui16, Component*> advMapArts;
static std::map<ui16, Component*> townArts;
void reset (ui32 val);
void onHeroVisit (const CGHeroInstance * h) const {};
template <typename Handler> void serialize(Handler &h, const int version)
{
h & advMapArts & townArts & static_cast<CShop&>(*this);
}
};
class DLL_EXPORT CGRefugeeCamp : public CShop
{
public:
@ -1164,8 +1149,6 @@ class DLL_EXPORT CGMarket : public CGObjectInstance, public IMarket
public:
CGMarket();
void onHeroVisit(const CGHeroInstance * h) const; //open trading window
void initObj();
void newTurn() const; //reset artifacts for black market every month
int getMarketEfficiency() const;
bool allowsTrade(EMarketMode mode) const;
@ -1178,6 +1161,21 @@ public:
}
};
class DLL_EXPORT CGBlackMarket : public CGMarket
{
public:
std::vector<const CArtifact *> artifacts; //available artifacts
void initObj();
void newTurn() const; //reset artifacts for black market every month
std::vector<int> availableItemsIds(EMarketMode mode) const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CGMarket&>(*this);
}
};
struct BankConfig
{
BankConfig() {level = chance = upgradeChance = combatValue = value = rewardDifficulty = easiest = 0; };

View File

@ -165,7 +165,7 @@ void MetaString::getLocalString(const std::pair<ui8,ui32> &txt, std::string &dst
if(type == ART_NAMES)
{
dst = VLC->arth->artifacts[ser].Name();
dst = VLC->arth->artifacts[ser]->Name();
}
else if(type == CRE_PL_NAMES)
{
@ -189,7 +189,7 @@ void MetaString::getLocalString(const std::pair<ui8,ui32> &txt, std::string &dst
}
else if(type == ART_DESCR)
{
dst = VLC->arth->artifacts[ser].Description();
dst = VLC->arth->artifacts[ser]->Description();
}
else
{

View File

@ -16,6 +16,9 @@
#include "../hch/CObjectHandler.h"
#include "../hch/CCreatureHandler.h"
#include "VCMI_Lib.h"
#include "../hch/CArtHandler.h"
#include "../hch/CHeroHandler.h"
#include "../hch/CTownHandler.h"
/*
@ -66,7 +69,6 @@ void CConnection::init()
tlog0 << "Established connection with "<<pom<<std::endl;
wmx = new boost::mutex;
rmx = new boost::mutex;
gs = NULL;
}
CConnection::CConnection(std::string host, std::string port, std::string Name)
@ -201,42 +203,6 @@ void CConnection::close()
}
}
CGObjectInstance *CConnection::loadObject()
{
assert(gs);
si32 id;
*this >> id;
assert(id >= 0 && id < gs->map->objects.size());
return gs->map->objects[id];
}
void CConnection::saveObject( const CGObjectInstance *data )
{
assert(gs);
assert(data);
*this << data->id;
}
CCreature * CConnection::loadCreature()
{
si32 id;
*this >> id;
assert(id >= 0 && id < VLC->creh->creatures.size());
return VLC->creh->creatures[id];
}
void CConnection::saveCreature(const CCreature *data)
{
assert(data);
*this << data->idNumber;
}
void CConnection::setGS( CGameState *state )
{
gs = state;
}
bool CConnection::isOpen() const
{
return socket && connected;
@ -362,3 +328,23 @@ ui16 CTypeList::getTypeID( const std::type_info *type )
else
return 0;
}
CSerializer::~CSerializer()
{
}
CSerializer::CSerializer()
{
smartVectorMembersSerialization = false;
}
void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib)
{
registerVectoredType(&gs->map->objects, &CGObjectInstance::id);
registerVectoredType(&lib->creh->creatures, &CCreature::idNumber);
registerVectoredType(&lib->arth->artifacts, &CArtifact::id);
registerVectoredType(&lib->heroh->heroes, &CHero::ID);
smartVectorMembersSerialization = true;
}

View File

@ -20,12 +20,16 @@
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/any.hpp>
const ui32 version = 723;
class CConnection;
class CGObjectInstance;
class CGameState;
class CCreature;
class LibClasses;
class CHero;
extern DLL_EXPORT LibClasses * VLC;
namespace mpl = boost::mpl;
/*
@ -223,7 +227,81 @@ struct SerializationLevel
static const int value = SerializationLevel::type::value;
};
class DLL_EXPORT CSaverBase
template <typename T>
struct VectorisedObjectInfo
{
const std::vector<T*> *vector; //pointer to the appropriate vector
const si32 T::*idPtr; //pointer to the field representing the position in the vector
VectorisedObjectInfo(const std::vector<T*> *Vector, const si32 T::*IdPtr)
:vector(Vector), idPtr(IdPtr)
{
}
};
class DLL_EXPORT CSerializer
{
public:
typedef std::map<const std::type_info *, boost::any, TypeComparer> TTypeVecMap;
TTypeVecMap vectors; //entry must be a pointer to vector containing pointers to the objects of key type
bool smartVectorMembersSerialization;
CSerializer();
~CSerializer();
template <typename T>
void registerVectoredType(const std::vector<T*> *Vector, const si32 T::*IdPtr)
{
vectors[&typeid(T)] = VectorisedObjectInfo<T>(Vector, IdPtr);
}
template <typename T>
const VectorisedObjectInfo<T> *getVectorisedTypeInfo()
{
const std::type_info *myType = NULL;
//
// if(boost::is_base_of<CGObjectInstance, T>::value) //ugly workaround to support also types derived from CGObjectInstance -> if we encounter one, treat it aas CGObj..
// myType = &typeid(CGObjectInstance);
// else
myType = &typeid(T);
TTypeVecMap::iterator i = vectors.find(myType);
if(i == vectors.end())
return NULL;
else
{
assert(!i->second.empty());
assert(i->second.type() == typeid(VectorisedObjectInfo<T>));
VectorisedObjectInfo<T> *ret = &(boost::any_cast<VectorisedObjectInfo<T>&>(i->second));
return ret;
}
}
template <typename T>
T* getVectorItemFromId(const VectorisedObjectInfo<T> &oInfo, si32 id) const
{
if(id < 0)
return NULL;
assert(oInfo.vector);
assert(oInfo.vector->size() > id);
return (*oInfo.vector)[id];
}
template <typename T>
si32 getIdFromVectorItem(const VectorisedObjectInfo<T> &oInfo, const T* obj) const
{
if(!obj)
return -1;
return obj->*oInfo.idPtr;
}
void addStdVecItems(CGameState *gs, LibClasses *lib = VLC);
};
class DLL_EXPORT CSaverBase : public virtual CSerializer
{
};
@ -247,6 +325,18 @@ public:
}
};
template <typename T> //metafunction returning CGObjectInstance if T is its derivate or T elsewise
struct VectorisedTypeFor
{
typedef typename
//if
mpl::eval_if<boost::is_base_of<CGObjectInstance,T>,
mpl::identity<CGObjectInstance>,
//else
mpl::identity<T>
>::type type;
};
template <typename Serializer> class DLL_EXPORT COSer : public CSaverBase
{
public:
@ -313,6 +403,17 @@ public:
if(!hlp)
return;
if(smartVectorMembersSerialization)
{
typedef typename boost::remove_const<typename boost::remove_pointer<T>::type>::type TObjectType;
typedef typename VectorisedTypeFor<TObjectType>::type VType;
if(const VectorisedObjectInfo<VType> *info = getVectorisedTypeInfo<VType>())
{
*this << getIdFromVectorItem<VType>(*info, data);
return;
}
}
if(smartPointerSerialization)
{
std::map<const void*,ui32>::iterator i = savedPointers.find(data);
@ -429,7 +530,7 @@ public:
class DLL_EXPORT CLoaderBase
class DLL_EXPORT CLoaderBase : public virtual CSerializer
{};
class CBasicPointerLoader
@ -456,7 +557,6 @@ public:
}
};
template <typename Serializer> class DLL_EXPORT CISer : public CLoaderBase
{
public:
@ -562,6 +662,19 @@ public:
data = NULL;
return;
}
if(smartVectorMembersSerialization)
{
typedef typename boost::remove_const<typename boost::remove_pointer<T>::type>::type TObjectType; //eg: const CGHeroInstance * => CGHeroInstance
typedef typename VectorisedTypeFor<TObjectType>::type VType; //eg: CGHeroInstance -> CGobjectInstance
if(const VectorisedObjectInfo<VType> *info = getVectorisedTypeInfo<VType>())
{
si32 id;
*this >> id;
data = static_cast<T>(getVectorItemFromId(*info, id));
return;
}
}
ui32 pid = -1; //pointer id (or maybe rather pointee id)
if(smartPointerSerialization)
@ -711,7 +824,7 @@ typedef boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, boost::asio::so
class DLL_EXPORT CConnection
:public CISer<CConnection>, public COSer<CConnection>
{
CGameState *gs;
//CGameState *gs;
CConnection(void);
void init();
@ -735,99 +848,6 @@ public:
template<class T>
CConnection &operator&(const T&);
~CConnection(void);
void setGS(CGameState *state);
CGObjectInstance *loadObject(); //reads id from net and returns that obj
void saveObject(const CGObjectInstance *data);
CCreature *loadCreature(); //reads id from net and returns that obj
void saveCreature(const CCreature *data);
template<typename T>
struct loadObjectHelper
{
static void invoke(CConnection &s, T &data, ui16 tid)
{
data = static_cast<T>(s.loadObject());
}
};
template<typename T>
struct loadCreatureHelper
{
static void invoke(CConnection &s, T &data, ui16 tid)
{
data = static_cast<T>(s.loadCreature());
}
};
template<typename T>
struct loadRestHelper
{
static void invoke(CConnection &s, T &data, ui16 tid)
{
s.CISer<CConnection>::loadPointerHlp(tid, data, -1);
}
};
template<typename T>
struct saveObjectHelper
{
static void invoke(CConnection &s, const T &data, ui16 tid)
{
//CGObjectInstance *&hlp = const_cast<CGObjectInstance*&>(data); //for loading pointer to const obj we must remove the qualifier
s.saveObject(data);
}
};
template<typename T>
struct saveCreatureHelper
{
static void invoke(CConnection &s, const T &data, ui16 tid)
{
//CGObjectInstance *&hlp = const_cast<CGObjectInstance*&>(data); //for loading pointer to const obj we must remove the qualifier
s.saveCreature(data);
}
};
template<typename T>
struct saveRestHelper
{
static void invoke(CConnection &s, const T &data, ui16 tid)
{
s.COSer<CConnection>::savePointerHlp(tid, data);
}
};
//"overload" loading pointer procedure
template <typename T>
void loadPointerHlp( ui16 tid, T & data, ui32 pid )
{
typedef typename
//if
mpl::eval_if< boost::is_base_of<CGObjectInstance, typename boost::remove_pointer<T>::type>,
mpl::identity<loadObjectHelper<T> >,
//else if
mpl::eval_if< boost::is_base_of<CCreature, typename boost::remove_pointer<T>::type>,
mpl::identity<loadCreatureHelper<T> >,
//else
mpl::identity<loadRestHelper<T> >
> >::type typex;
typex::invoke(*this, data, tid);
}
//"overload" saving pointer procedure
template <typename T>
void savePointerHlp( ui16 tid, const T & data )
{
typedef typename
//if
mpl::eval_if< boost::is_base_of<CGObjectInstance, typename boost::remove_pointer<T>::type>,
mpl::identity<saveObjectHelper<T> >,
//else if
mpl::eval_if< boost::is_base_of<CCreature, typename boost::remove_pointer<T>::type>,
mpl::identity<saveCreatureHelper<T> >,
//else
mpl::identity<saveRestHelper<T> >
> >::type typex;
typex::invoke(*this, data, tid);
}
};
#endif // __CONNECTION_H__

View File

@ -181,8 +181,8 @@ void IGameCallback::getAllowedArts(std::vector<CArtifact*> &out, std::vector<CAr
{
for (int i = 0; i < VLC->arth->artifacts.size(); i++)
{
if (VLC->arth->artifacts[i].aClass == flag)
(VLC->arth->*arts).push_back(&(VLC->arth->artifacts[i]));
if (VLC->arth->artifacts[i]->aClass == flag)
(VLC->arth->*arts).push_back(VLC->arth->artifacts[i]);
}
}
@ -209,7 +209,7 @@ void IGameCallback::getAllowed(std::vector<CArtifact*> &out, int flags)
if (!out.size()) //no arts are avaliable
{
out.resize(64);
std::fill_n(out.begin(), 64, &(VLC->arth->artifacts[2])); //magic
std::fill_n(out.begin(), 64, VLC->arth->artifacts[2]); //magic
}
}

View File

@ -22,6 +22,8 @@ class CGameState;
class CGameHandler;
class CConnection;
class CArtifact;
struct CPack
{
ui16 type;
@ -642,6 +644,21 @@ struct NewObject : public CPackForClient //518
}
};
struct SetAvailableArtifacts : public CPackForClient //519
{
SetAvailableArtifacts(){type = 519;};
//void applyCl(CClient *cl);
DLL_EXPORT void applyGs(CGameState *gs);
si32 id; //two variants: id < 0: set artifact pool for Artifact Merchants in towns; id >= 0: set pool for adv. map Black Market (id is the id of Black Market instance then)
std::vector<const CArtifact *> arts;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & id & arts;
}
};
struct NewTurn : public CPackForClient //101
{
DLL_EXPORT void applyGs(CGameState *gs);

View File

@ -487,7 +487,7 @@ DLL_EXPORT void SetHeroArtifacts::applyGs( CGameState *gs )
if(h->getArtPos(id) >= 0)
continue;
CArtifact &art = VLC->arth->artifacts[id];
CArtifact &art = *VLC->arth->artifacts[id];
art.addBonusesTo(&h->bonuses);
art.addBonusesTo(&gained);
}
@ -503,7 +503,7 @@ DLL_EXPORT void SetHeroArtifacts::applyGs( CGameState *gs )
if(h->getArtPos(id) >= 0)
continue;
CArtifact &art = VLC->arth->artifacts[id];
CArtifact &art = *VLC->arth->artifacts[id];
art.removeBonusesFrom(&h->bonuses);
art.addBonusesTo(&lost);
}
@ -606,6 +606,25 @@ DLL_EXPORT void NewObject::applyGs( CGameState *gs )
assert(o->defInfo);
}
DLL_EXPORT void SetAvailableArtifacts::applyGs( CGameState *gs )
{
if(id >= 0)
{
if(CGBlackMarket *bm = dynamic_cast<CGBlackMarket*>(gs->map->objects[id]))
{
bm->artifacts = arts;
}
else
{
tlog1 << "Wrong black market id!" << std::endl;
}
}
else
{
CGTownInstance::merchantArtifacts = arts;
}
}
DLL_EXPORT void NewTurn::applyGs( CGameState *gs )
{
gs->day = day;

View File

@ -373,6 +373,7 @@ struct DLL_EXPORT Mapa : public CMapHeader
h & CGMagi::eyelist;
h & CGPyramid::pyramidConfig;
h & CGObelisk::obeliskCount & CGObelisk::visited;
h & CGTownInstance::merchantArtifacts;
for(unsigned int i=0; i<objects.size(); i++)
{

View File

@ -1944,7 +1944,7 @@ void CGameHandler::stopHeroVisitCastle(int obj, int heroID)
void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1 - first free slot in backpack
{
const CGHeroInstance* h = getHero(hid);
const CArtifact &art = VLC->arth->artifacts[artid];
const CArtifact &art = *VLC->arth->artifacts[artid];
SetHeroArtifacts sha;
sha.hid = hid;
@ -2922,7 +2922,7 @@ bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assem
return false;
}
const CArtifact &artifact = VLC->arth->artifacts[assembleTo];
const CArtifact &artifact = *VLC->arth->artifacts[assembleTo];
if (artifact.constituents == NULL) {
complain("Not a combinational artifact.");
@ -2975,7 +2975,7 @@ bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assem
// Perform disassembly.
bool destConsumed = false; // Determines which constituent that will be counted for together with the artifact.
BOOST_FOREACH(ui32 constituentID, *destArtifact->constituents) {
const CArtifact &constituent = VLC->arth->artifacts[constituentID];
const CArtifact &constituent = *VLC->arth->artifacts[constituentID];
if (!destConsumed && vstd::contains(constituent.possibleSlots, artifactSlot)) {
sha.artifWorn[artifactSlot] = constituentID;
@ -3015,7 +3015,7 @@ bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
}
else if(aid < 7 && aid > 3) //war machine
{
int price = VLC->arth->artifacts[aid].price;
int price = VLC->arth->artifacts[aid]->price;
if(vstd::contains(hero->artifWorn,ui16(9+aid)) && complain("Hero already has this machine!")
|| !vstd::contains(town->builtBuildings,si32(16)) && complain("No blackismith!")
|| gs->getPlayer(hero->getOwner())->resources[6] < price && complain("Not enough gold!") //no gold

View File

@ -94,7 +94,7 @@ void CVCMIServer::newGame(CConnection *c)
StartInfo startInfoCpy = *si;
gh.init(si,rand());
c->setGS(gh.gs);
c->addStdVecItems(gh.gs);
CConnection* cc; //tcp::socket * ss;
for(int i=0; i<clients; i++)
@ -114,7 +114,7 @@ void CVCMIServer::newGame(CConnection *c)
continue;
}
cc = new CConnection(s,NAME);
cc->setGS(gh.gs);
cc->addStdVecItems(gh.gs);
}
gh.conns.insert(cc);
}
@ -201,7 +201,7 @@ void CVCMIServer::loadGame( CConnection *c )
tlog0 <<"Reading handlers"<<std::endl;
lf >> (gh.gs);
c->setGS(gh.gs);
c->addStdVecItems(gh.gs);
tlog0 <<"Reading gamestate"<<std::endl;
}
@ -230,7 +230,7 @@ void CVCMIServer::loadGame( CConnection *c )
continue;
}
cc = new CConnection(s,NAME);
cc->setGS(gh.gs);
cc->addStdVecItems(gh.gs);
}
gh.conns.insert(cc);
}