1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +02:00

Redesigned artifact randomization.

Fixed #119, #128, #433, #493
This commit is contained in:
DjWarmonger
2010-06-28 05:07:21 +00:00
parent 21a05d73cb
commit 12f6d5a380
8 changed files with 172 additions and 144 deletions

View File

@@ -9,6 +9,7 @@
#include <boost/assign/list_of.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/foreach.hpp>
#include <boost/random/linear_congruential.hpp>
#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; i<allowedArtifacts.size(); ++i) //do 144, bo nie chcemy bzdurek
{
switch (artifacts[i]->aClass)
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<CArtifact*>* 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<CArtifact*> out;
getAllowed(out, flags);
ui16 id = out[ran() % out.size()]->id;
erasePickedArt (id);
return id;
}
ui16 CArtHandler::getArtSync (ui32 rand, int flags)
{
std::vector<CArtifact*> out;
getAllowed(out, flags);
CArtifact *art = out[rand % out.size()];
return art->id;
}
void CArtHandler::getAllowed(std::vector<CArtifact*> &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<CArtifact*> &out, std::vector<CArtifact*> *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);

View File

@@ -51,12 +51,18 @@ class DLL_EXPORT CArtHandler //handles artifacts
public:
std::vector<CArtifact*> treasures, minors, majors, relics;
std::vector<CArtifact *> artifacts;
std::vector<CArtifact *> allowedArtifacts;
std::set<ui32> 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<CArtifact*> &out, std::vector<CArtifact*> *arts, int flag);
void getAllowed(std::vector<CArtifact*> &out, int flags);
void erasePickedArt (si32 id);
bool isBigArtifact (ui32 artID) {return bigArtifacts.find(artID) != bigArtifacts.end();}
void equipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID, ui32 artifactID, BonusList *bonuses = NULL);
void unequipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID, BonusList *bonuses = NULL);
@@ -66,9 +72,8 @@ public:
template <typename Handler> void serialize(Handler &h, const int version)
{
h & artifacts;
if(!h.saving)
sortArts();
h & artifacts & allowedArtifacts & treasures & minors & majors & relics;
//if(!h.saving) sortArts();
}
};

View File

@@ -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<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
@@ -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;
}
}
}

View File

@@ -302,6 +302,16 @@ public:
h & patrolling & patrolRadious;
}
} patrol;
struct DLL_EXPORT HeroSpecial : CBonusSystemNode
{
bool growthsWithLevel;
void RecalculateSpecials(){};
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CBonusSystemNode&>(*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
}
//////////////////////////////////////////////////////////////////////////

View File

@@ -904,28 +904,16 @@ std::pair<int,int> CGameState::pickObject (CGObjectInstance *obj)
{
switch(obj->ID)
{
case 65: //random artifact
return std::pair<int,int>(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<int,int>(5,VLC->arth->treasures[ran()%VLC->arth->treasures.size()]->id);
case 67: //random minor artifact
return std::pair<int,int>(5,VLC->arth->minors[ran()%VLC->arth->minors.size()]->id);
case 68: //random major artifact
return std::pair<int,int>(5,VLC->arth->majors[ran()%VLC->arth->majors.size()]->id);
case 69: //random relic artifact
return std::pair<int,int>(5,VLC->arth->relics[ran()%VLC->arth->relics.size()]->id);
/*
case 65: //random artifact //how the hell use IGameCallback for this?
return std::pair<int,int>(5, obj->cb->getRandomArt (CArtifact::ART_TREASURE | CArtifact::ART_MINOR | CArtifact::ART_MAJOR | CArtifact::ART_RELIC));
return std::pair<int,int>(5, VLC->arth->getRandomArt (CArtifact::ART_TREASURE | CArtifact::ART_MINOR | CArtifact::ART_MAJOR | CArtifact::ART_RELIC));
case 66: //random treasure artifact
return std::pair<int,int>(5, cb->getRandomArt(CArtifact::ART_TREASURE));
return std::pair<int,int>(5, VLC->arth->getRandomArt (CArtifact::ART_TREASURE));
case 67: //random minor artifact
return std::pair<int,int>(5, cb->getRandomArt (CArtifact::ART_MINOR));
return std::pair<int,int>(5, VLC->arth->getRandomArt (CArtifact::ART_MINOR));
case 68: //random major artifact
return std::pair<int,int>(5, cb->getRandomArt (CArtifact::ART_MAJOR));
return std::pair<int,int>(5, VLC->arth->getRandomArt (CArtifact::ART_MAJOR));
case 69: //random relic artifact
return std::pair<int,int>(5, cb->getRandomArt (CArtifact::ART_RELIC));
*/
return std::pair<int,int>(5, VLC->arth->getRandomArt (CArtifact::ART_RELIC));
case 70: //random hero
{
return std::pair<int,int>(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<CGHeroInstance *>::const_iterator it = heroes.begin(); it != heroes.end(); ++it)
{
if (*it != root)
(*it)->getParents(out, root);
}
for (std::vector<CGTownInstance *>::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()

View File

@@ -175,27 +175,6 @@ bool IGameCallback::isAllowed( int type, int id )
}
}
void IGameCallback::getAllowedArts(std::vector<CArtifact*> &out, std::vector<CArtifact*> 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<const CArtifact*> &out)
{
for (int i = 0; i < 2; i++)
@@ -208,50 +187,22 @@ void IGameCallback::pickAllowedArtsSet(std::vector<const CArtifact*> &out)
out.push_back(VLC->arth->artifacts[getRandomArt(CArtifact::ART_MAJOR)]);
}
void IGameCallback::getAllowed(std::vector<CArtifact*> &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<CArtifact*> out;
getAllowed(out, flags);
CArtifact *art = out[ran() % out.size()];
std::vector<CArtifact*>* 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<ui16> &out, ui16 level)
{

View File

@@ -60,9 +60,9 @@ public:
virtual void getAllTiles (std::set<int3> &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<CArtifact*> &out, std::vector<CArtifact*> CArtHandler::*arts, int flag);
virtual ui16 getArtSync (ui32 rand, int flags); //synchronic
virtual void pickAllowedArtsSet(std::vector<const CArtifact*> &out); //gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant
virtual void getAllowed(std::vector<CArtifact*> &out, int flags); //flags: bitfield uses EartClass
virtual void erasePickedArt (si32 id);
virtual void getAllowedSpells(std::vector<ui16> &out, ui16 level);
virtual int3 getMapSize(); //returns size of the map
virtual TerrainTile * getTile(int3 pos);

View File

@@ -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);