diff --git a/hch/CArtHandler.cpp b/hch/CArtHandler.cpp index 054c3d9a6..757d32299 100644 --- a/hch/CArtHandler.cpp +++ b/hch/CArtHandler.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "../lib/VCMI_Lib.h" extern CLodHandler *bitmaph; using namespace boost::assign; @@ -23,6 +24,8 @@ using namespace boost::assign; * */ +extern boost::rand48 ran; + const std::string & CArtifact::Name() const { if(name.size()) @@ -349,26 +352,96 @@ int CArtHandler::convertMachineID(int id, bool creToArt ) void CArtHandler::sortArts() { - for(int i=0;i<144;i++) //do 144, bo nie chcemy bzdurek + for (int i=0; iaClass) + switch (allowedArtifacts[i]->aClass) { case CArtifact::ART_TREASURE: - treasures.push_back(artifacts[i]); + treasures.push_back(allowedArtifacts[i]); break; case CArtifact::ART_MINOR: - minors.push_back(artifacts[i]); + minors.push_back(allowedArtifacts[i]); break; case CArtifact::ART_MAJOR: - majors.push_back(artifacts[i]); + majors.push_back(allowedArtifacts[i]); break; case CArtifact::ART_RELIC: - relics.push_back(artifacts[i]); + relics.push_back(allowedArtifacts[i]); break; } } } +void CArtHandler::erasePickedArt (si32 id) +{ + std::vector* ptr; + CArtifact *art = artifacts[id]; + switch (art->aClass) + { + case CArtifact::ART_TREASURE: + ptr = &treasures; + break; + case CArtifact::ART_MINOR: + ptr = &minors; + break; + case CArtifact::ART_MAJOR: + ptr = &majors; + break; + case CArtifact::ART_RELIC: + ptr = &relics; + break; + default: //special artifacts should not be erased + return; + } + ptr->erase (std::find(ptr->begin(), ptr->end(), art)); //remove the artifact from avaliable list +} +ui16 CArtHandler::getRandomArt(int flags) +{ + std::vector out; + getAllowed(out, flags); + ui16 id = out[ran() % out.size()]->id; + erasePickedArt (id); + return id; +} +ui16 CArtHandler::getArtSync (ui32 rand, int flags) +{ + std::vector out; + getAllowed(out, flags); + CArtifact *art = out[rand % out.size()]; + return art->id; +} +void CArtHandler::getAllowed(std::vector &out, int flags) +{ + if (flags & CArtifact::ART_TREASURE) + getAllowedArts (out, &treasures, CArtifact::ART_TREASURE); + if (flags & CArtifact::ART_MINOR) + getAllowedArts (out, &minors, CArtifact::ART_MINOR); + if (flags & CArtifact::ART_MAJOR) + getAllowedArts (out, &majors, CArtifact::ART_MAJOR); + if (flags & CArtifact::ART_RELIC) + getAllowedArts (out, &relics, CArtifact::ART_RELIC); + if (!out.size()) //no arts are avaliable + { + out.resize (64); + std::fill_n (out.begin(), 64, artifacts[2]); //magic + } +} +void CArtHandler::getAllowedArts(std::vector &out, std::vector *arts, int flag) +{ + if (arts->empty()) //restock avaliable arts + { + for (int i = 0; i < allowedArtifacts.size(); ++i) + { + if (allowedArtifacts[i]->aClass == flag) + arts->push_back(allowedArtifacts[i]); + } + } + for (int i = 0; i < arts->size(); ++i) + { + CArtifact *art = (*arts)[i]; + out.push_back(art); + } +} void CArtHandler::giveArtBonus( int aid, Bonus::BonusType type, int val, int subtype, int valType ) { Bonus added(Bonus::PERMANENT,type,Bonus::ARTIFACT,val,aid,subtype); diff --git a/hch/CArtHandler.h b/hch/CArtHandler.h index 25d696cd7..10312b2ba 100644 --- a/hch/CArtHandler.h +++ b/hch/CArtHandler.h @@ -51,12 +51,18 @@ class DLL_EXPORT CArtHandler //handles artifacts public: std::vector treasures, minors, majors, relics; std::vector artifacts; + std::vector allowedArtifacts; std::set bigArtifacts; // Artifacts that cannot be moved to backpack, e.g. war machines. void loadArtifacts(bool onlyTxt); void sortArts(); void addBonuses(); void clear(); + ui16 getRandomArt (int flags); + ui16 getArtSync (ui32 rand, int flags); + void getAllowedArts(std::vector &out, std::vector *arts, int flag); + void getAllowed(std::vector &out, int flags); + void erasePickedArt (si32 id); bool isBigArtifact (ui32 artID) {return bigArtifacts.find(artID) != bigArtifacts.end();} void equipArtifact (std::map &artifWorn, ui16 slotID, ui32 artifactID, BonusList *bonuses = NULL); void unequipArtifact (std::map &artifWorn, ui16 slotID, BonusList *bonuses = NULL); @@ -66,9 +72,8 @@ public: template void serialize(Handler &h, const int version) { - h & artifacts; - if(!h.saving) - sortArts(); + h & artifacts & allowedArtifacts & treasures & minors & majors & relics; + //if(!h.saving) sortArts(); } }; diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp index 6913fd128..cd8f6418a 100644 --- a/hch/CObjectHandler.cpp +++ b/hch/CObjectHandler.cpp @@ -1767,39 +1767,6 @@ 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::iterator index; - for (ui8 i = 0; i < 3; ++i) //each tier - { - int count = 0; - std::vector 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 @@ -5023,25 +4990,12 @@ void CBank::reset(ui16 var1) //prevents desync void CBank::initialize() const { cb->setObjProperty (id, 14, ran()); //synchronous reset + ui32 artid; for (ui8 i = 0; i <= 3; i++) { for (ui8 n = 0; n < bc->artifacts[i]; n++) //new function using proper randomization algorithm - { - switch (i) - { - case 0: - cb->setObjProperty(id, 18, cb->getRandomArt (CArtifact::ART_TREASURE)); - break; - case 1: - cb->setObjProperty(id, 18, cb->getRandomArt (CArtifact::ART_MINOR)); - break; - case 2: - cb->setObjProperty(id, 18, cb->getRandomArt (CArtifact::ART_MAJOR)); - break; - case 3: - cb->setObjProperty(id, 18, cb->getRandomArt (CArtifact::ART_RELIC)); - break; - } + { + cb->setObjProperty (id, 18 + i, ran()); //synchronic } } } @@ -5052,7 +5006,7 @@ void CBank::setPropertyDer (ui8 what, ui32 val) { case 11: //daycounter if (val == 0) - daycounter = 0; + daycounter = 1; //yes, 1 else daycounter++; break; @@ -5118,8 +5072,33 @@ void CBank::setPropertyDer (ui8 what, ui32 val) } break; case 18: //add Artifact - artifacts.push_back (val); + { + int id = cb->getArtSync(val, CArtifact::ART_TREASURE); + artifacts.push_back (id); + cb->erasePickedArt(id); break; + } + case 19: //add Artifact + { + int id = cb->getArtSync(val, CArtifact::ART_MINOR); + artifacts.push_back (id); + cb->erasePickedArt(id); + break; + } + case 20: //add Artifact + { + int id = cb->getArtSync(val, CArtifact::ART_MAJOR); + artifacts.push_back (id); + cb->erasePickedArt(id); + break; + } + case 21: //add Artifact + { + int id = cb->getArtSync(val, CArtifact::ART_RELIC); + artifacts.push_back (id); + cb->erasePickedArt(id); + break; + } } } diff --git a/hch/CObjectHandler.h b/hch/CObjectHandler.h index c041c28fd..3c61479b9 100644 --- a/hch/CObjectHandler.h +++ b/hch/CObjectHandler.h @@ -302,6 +302,16 @@ public: h & patrolling & patrolRadious; } } patrol; + struct DLL_EXPORT HeroSpecial : CBonusSystemNode + { + bool growthsWithLevel; + void RecalculateSpecials(){}; + template void serialize(Handler &h, const int version) + { + h & static_cast(*this); + h & growthsWithLevel; + } + } speciality; //BonusList bonuses; ////////////////////////////////////////////////////////////////////////// @@ -313,7 +323,7 @@ public: h & exp & level & name & biography & portrait & mana & secSkills & movement & sex & inTownGarrison & artifacts & artifWorn & spells & patrol & moveDir; - h & type; + h & type & speciality; //visitied town pointer will be restored by map serialization method } ////////////////////////////////////////////////////////////////////////// diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 4558bf70f..daa4a2eda 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -904,28 +904,16 @@ std::pair CGameState::pickObject (CGObjectInstance *obj) { switch(obj->ID) { - case 65: //random artifact - return std::pair(5,(ran()%136)+7); //the only reasonable range - there are siege weapons and blanks we must ommit - case 66: //random treasure artifact - return std::pair(5,VLC->arth->treasures[ran()%VLC->arth->treasures.size()]->id); - case 67: //random minor artifact - return std::pair(5,VLC->arth->minors[ran()%VLC->arth->minors.size()]->id); - case 68: //random major artifact - return std::pair(5,VLC->arth->majors[ran()%VLC->arth->majors.size()]->id); - case 69: //random relic artifact - return std::pair(5,VLC->arth->relics[ran()%VLC->arth->relics.size()]->id); - /* case 65: //random artifact //how the hell use IGameCallback for this? - return std::pair(5, obj->cb->getRandomArt (CArtifact::ART_TREASURE | CArtifact::ART_MINOR | CArtifact::ART_MAJOR | CArtifact::ART_RELIC)); + return std::pair(5, VLC->arth->getRandomArt (CArtifact::ART_TREASURE | CArtifact::ART_MINOR | CArtifact::ART_MAJOR | CArtifact::ART_RELIC)); case 66: //random treasure artifact - return std::pair(5, cb->getRandomArt(CArtifact::ART_TREASURE)); + return std::pair(5, VLC->arth->getRandomArt (CArtifact::ART_TREASURE)); case 67: //random minor artifact - return std::pair(5, cb->getRandomArt (CArtifact::ART_MINOR)); + return std::pair(5, VLC->arth->getRandomArt (CArtifact::ART_MINOR)); case 68: //random major artifact - return std::pair(5, cb->getRandomArt (CArtifact::ART_MAJOR)); + return std::pair(5, VLC->arth->getRandomArt (CArtifact::ART_MAJOR)); case 69: //random relic artifact - return std::pair(5, cb->getRandomArt (CArtifact::ART_RELIC)); - */ + return std::pair(5, VLC->arth->getRandomArt (CArtifact::ART_RELIC)); case 70: //random hero { return std::pair(HEROI_TYPE,pickHero(obj->tempOwner)); @@ -1185,6 +1173,11 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed ) { case 0: map = new Mapa(si->mapname); + for (int i=0; i<144; ++i) //yes, 144 + { + if (map->allowedArtifact[i]) + VLC->arth->allowedArtifacts.push_back(VLC->arth->artifacts[i]); + } break; case 2: campaign = new CCampaignState(); @@ -1192,6 +1185,11 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed ) std::string &mapContent = campaign->camp->mapPieces[si->whichMapInCampaign]; map = new Mapa(); map->initFromBytes((const unsigned char*)mapContent.c_str()); + for (int i=0; i<144; ++i) + { + if (map->allowedArtifact[i]) + VLC->arth->allowedArtifacts.push_back(VLC->arth->artifacts[i]); + } break; } tlog0 << "Map loaded!" << std::endl; @@ -3816,11 +3814,24 @@ PlayerState::PlayerState() void PlayerState::getParents(TCNodes &out, const CBonusSystemNode *root /*= NULL*/) const { - //TODO: global effects + /* + for (std::vector::const_iterator it = heroes.begin(); it != heroes.end(); ++it) + { + if (*it != root) + (*it)->getParents(out, root); + } + for (std::vector::const_iterator it = towns.begin(); it != towns.end(); ++it) + { + if (*it != root) + (*it)->getParents(out, root); + } + */ + //TODO - dwellings } void PlayerState::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const -{ +{//temporary + //CBonusSystemNode::getBonuses(out, selector, root); } InfoAboutHero::InfoAboutHero() diff --git a/lib/IGameCallback.cpp b/lib/IGameCallback.cpp index e1b5f9c09..996b02fe9 100644 --- a/lib/IGameCallback.cpp +++ b/lib/IGameCallback.cpp @@ -175,27 +175,6 @@ bool IGameCallback::isAllowed( int type, int id ) } } -void IGameCallback::getAllowedArts(std::vector &out, std::vector CArtHandler::*arts, int flag) -{ - if (!(VLC->arth->*arts).size()) //restock avaliable arts - { - 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]); - } - } - - for (int i = 0; i < (VLC->arth->*arts).size(); i++) - { - CArtifact *art = (VLC->arth->*arts)[i]; - if(isAllowed(1, art->id)) - { - out.push_back(art); - } - } -} - void IGameCallback::pickAllowedArtsSet(std::vector &out) { for (int i = 0; i < 2; i++) @@ -208,50 +187,22 @@ void IGameCallback::pickAllowedArtsSet(std::vector &out) out.push_back(VLC->arth->artifacts[getRandomArt(CArtifact::ART_MAJOR)]); } -void IGameCallback::getAllowed(std::vector &out, int flags) -{ - if(flags & CArtifact::ART_TREASURE) - getAllowedArts(out,&CArtHandler::treasures, CArtifact::ART_TREASURE); - if(flags & CArtifact::ART_MINOR) - getAllowedArts(out,&CArtHandler::minors, CArtifact::ART_MINOR); - if(flags & CArtifact::ART_MAJOR) - getAllowedArts(out,&CArtHandler::majors, CArtifact::ART_MAJOR); - if(flags & CArtifact::ART_RELIC) - getAllowedArts(out,&CArtHandler::relics, CArtifact::ART_RELIC); - if (!out.size()) //no arts are avaliable - { - out.resize(64); - std::fill_n(out.begin(), 64, VLC->arth->artifacts[2]); //magic - } -} - ui16 IGameCallback::getRandomArt (int flags) { - std::vector out; - getAllowed(out, flags); - CArtifact *art = out[ran() % out.size()]; - std::vector* ptr; - switch (art->aClass) - { - case CArtifact::ART_TREASURE: - ptr = &VLC->arth->treasures; - break; - case CArtifact::ART_MINOR: - ptr = &VLC->arth->minors; - break; - case CArtifact::ART_MAJOR: - ptr = &VLC->arth->majors; - break; - case CArtifact::ART_RELIC: - ptr = &VLC->arth->relics; - break; - default: //special artifacts should not be erased - return art->id; - } - ptr->erase (std::find(ptr->begin(), ptr->end(), art)); //remove the artifact from avaliable list - return art->id; + return VLC->arth->getRandomArt(flags); } +ui16 IGameCallback::getArtSync (ui32 rand, int flags) +{ + return VLC->arth->getArtSync (rand, flags); +} + +void IGameCallback::erasePickedArt (si32 id) +{ + VLC->arth->erasePickedArt(id); +} + + void IGameCallback::getAllowedSpells(std::vector &out, ui16 level) { diff --git a/lib/IGameCallback.h b/lib/IGameCallback.h index 198c49dd2..05aed0615 100644 --- a/lib/IGameCallback.h +++ b/lib/IGameCallback.h @@ -60,9 +60,9 @@ public: virtual void getAllTiles (std::set &tiles, int player=-1, int level=-1, int surface=0); //returns all tiles on given level (-1 - both levels, otherwise number of level); surface: 0 - land and water, 1 - only land, 2 - only water virtual bool isAllowed(int type, int id); //type: 0 - spell; 1- artifact virtual ui16 getRandomArt (int flags); - virtual void getAllowedArts(std::vector &out, std::vector CArtHandler::*arts, int flag); + virtual ui16 getArtSync (ui32 rand, int flags); //synchronic virtual void pickAllowedArtsSet(std::vector &out); //gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant - virtual void getAllowed(std::vector &out, int flags); //flags: bitfield uses EartClass + virtual void erasePickedArt (si32 id); virtual void getAllowedSpells(std::vector &out, ui16 level); virtual int3 getMapSize(); //returns size of the map virtual TerrainTile * getTile(int3 pos); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 1f81d29ab..9d838f045 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -1906,7 +1906,6 @@ void CGameHandler::takeCreatures (int objid, TSlots creatures) //probably we cou int slot = newArmy.getSlotFor(creatures.begin()->second.type->idNumber); if (slot < 0) break; - //newArmy.slots[slot].type = creatures.begin()->second.type; newArmy.slots[slot].count -= creatures.begin()->second.count; if (newArmy.getStack(slot).count < 1) newArmy.eraseStack(slot);