1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-19 21:10:12 +02:00

* Fixed bug #112

* Improved the security checks for ExchangeArtifact and SetArtifact, but have also come to realize that SetArtifact  is inherently broken and can be used for cheating. :(
* Preliminary work for combination artifacts, it's now possible to identify artifacts that are combined and what they're made up of.
* Happy New Year!
This commit is contained in:
OnionKnight 2009-12-30 15:33:28 +00:00
parent b79fe389a2
commit ef5b1ca1de
9 changed files with 141 additions and 22 deletions

View File

@ -3696,10 +3696,11 @@ bool CArtPlace::fitsHere(const CArtifact * art)
if(!art)
return true;
// Anything can be placed in the backpack, except War Machines.
if (slotID >= 19 && !CGI->arth->isBigArtifact(art->id)
|| vstd::contains(art->possibleSlots, slotID))
{
// Anything can but War Machines can be placed in backpack.
if (slotID >= 19) {
return !CGI->arth->isBigArtifact(art->id);
} else if (vstd::contains(art->possibleSlots, slotID)) {
// TODO: Deal with combinational at dest and as src.
return true;
}

View File

@ -674,11 +674,11 @@ public:
{
std::set<CArtifactsOfHero *> participants; // Needed to mark slots.
const CArtifact * srcArtifact; // Held artifact.
const CArtifactsOfHero * srcAOH; // Following two needed to uniquely identify the source.
int srcSlotID; //
const CArtifactsOfHero * srcAOH; // Following two needed to uniquely identify the source.
int srcSlotID; //
const CArtifactsOfHero * destAOH; // For swapping. (i.e. changing what is held)
int destSlotID; // Needed to determine what kind of action was last taken in setHero
const CArtifact * destArtifact; // For swapping.
int destSlotID; // Needed to determine what kind of action was last taken in setHero
const CArtifact * destArtifact; // For swapping.
} * commonInfo; //when we have more than one CArtifactsOfHero in one window with exchange possibility, we use this (eg. in exchange window); to be provided externally
AdventureMapButton * leftArtRoll, * rightArtRoll;
@ -812,4 +812,4 @@ class CFreelancersWindow : public CShopWindow
{};
class CHillFortWindow : public CIntObject //garrison dialog? shop?
{};
#endif //__GUICLASSES_H__
#endif //__GUICLASSES_H__

View File

@ -35,6 +35,12 @@ const std::string & CArtifact::Description() const
else
return VLC->generaltexth->artifDescriptions[id];
}
bool CArtifact::isBig () const
{
return VLC->arth->isBigArtifact(id);
}
CArtHandler::CArtHandler()
{
VLC->arth = this;
@ -79,6 +85,75 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
if(desc[0] == '\"' && desc[desc.size()-1] == '\"')
desc = desc.substr(1,desc.size()-2);
// Fill in information about combined artifacts.
switch (nart.id) {
case 129: // Angelic Alliance
nart.constituents = new std::vector<ui32>(6);
*nart.constituents += 31, 32, 33, 34, 35, 36;
break;
case 130: // Cloak of the Undead King
nart.constituents = new std::vector<ui32>(3);
*nart.constituents += 54, 55, 56;
break;
case 131: // Elixir of Life
nart.constituents = new std::vector<ui32>(3);
*nart.constituents += 94, 95, 96;
break;
case 132: // Armor of the Damned
nart.constituents = new std::vector<ui32>(4);
*nart.constituents += 8, 14, 20, 26;
break;
case 133: // Statue of Legion
nart.constituents = new std::vector<ui32>(5);
*nart.constituents += 118, 119, 120, 121, 122;
break;
case 134: // Power of the Dragon Father
nart.constituents = new std::vector<ui32>(9);
*nart.constituents += 37, 38, 39, 40, 41, 42, 43, 44, 45;
break;
case 135: // Titan's Thunder
nart.constituents = new std::vector<ui32>(4);
*nart.constituents += 12, 18, 24, 30;
break;
case 136: // Admiral's Hat
nart.constituents = new std::vector<ui32>(2);
*nart.constituents += 71, 123;
break;
case 137: // Bow of the Sharpshooter
nart.constituents = new std::vector<ui32>(3);
*nart.constituents += 60, 61, 62;
break;
case 138: // Wizards' Well
nart.constituents = new std::vector<ui32>(3);
*nart.constituents += 73, 74, 75;
break;
case 139: // Ring of the Magi
nart.constituents = new std::vector<ui32>(3);
*nart.constituents += 76, 77, 78;
break;
case 140: // Cornucopia
nart.constituents = new std::vector<ui32>(4);
*nart.constituents += 109, 110, 111, 113;
break;
// TODO: WoG combinationals
default:
nart.constituents = NULL;
break;
}
if(!onlyTxt)
artifacts.push_back(nart);
}

View File

@ -25,16 +25,18 @@ public:
enum EartClass {ART_SPECIAL=1, ART_TREASURE=2, ART_MINOR=4, ART_MAJOR=8, ART_RELIC=16}; //artifact classes
const std::string &Name() const; //getter
const std::string &Description() const; //getter
bool isBig () const;
ui32 price;
std::vector<ui16> possibleSlots; //ids of slots where artifact can be placed
std::vector<ui32> * constituents; // Artifacts IDs a combined artifact consists of, or NULL.
EartClass aClass;
ui32 id;
std::list<HeroBonus> bonuses; //bonuses given by artifact
template <typename Handler> void serialize(Handler &h, const int version)
{
h & name & description & price & possibleSlots & aClass & id & bonuses;
h & name & description & price & possibleSlots & constituents & aClass & id & bonuses;
}
};

View File

@ -1197,6 +1197,26 @@ si32 CGHeroInstance::getArtPos(int aid) const
return -1;
}
/**
* Places an artifact in hero's backpack. If it's a big artifact equips it
* or discards it if it cannot be equipped.
*/
void CGHeroInstance::giveArtifact (ui32 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 (artifWorn.find(*it) == artifWorn.end()) {
artifWorn[*it] = aid;
break;
}
}
} else {
artifacts.push_back(aid);
}
}
void CGHeroInstance::recreateArtBonuses()
{
//clear all bonuses from artifacts (if present) and give them again

View File

@ -296,6 +296,7 @@ public:
ui32 getArtAtPos(ui16 pos) const; //-1 - no artifact
const CArtifact * getArt(int pos) const;
si32 getArtPos(int aid) 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)
void giveArtifact (ui32 aid);
int getSpellSecLevel(int spell) const; //returns level of secondary ability (fire, water, earth, air magic) known to this hero and applicable to given spell; -1 if error
static int3 convertPosition(int3 src, bool toh3m); //toh3m=true: manifest->h3m; toh3m=false: h3m->manifest
double getHeroStrength() const;

View File

@ -1448,7 +1448,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
hero->recreateArtBonuses();
}
else
hero->artifacts.push_back(toGive->id);
hero->giveArtifact(toGive->id);
}
}
}

View File

@ -1005,7 +1005,7 @@ void Mapa::loadHero( CGObjectInstance * &nobj, const unsigned char * bufor, int
{
id = readNormalNr(bufor,i, artidlen); i+=artidlen;
if(id!=artmask)
nhi->artifacts.push_back(id);
nhi->giveArtifact(id);
}
}
} //artifacts
@ -1244,7 +1244,7 @@ void Mapa::readPredefinedHeroes( const unsigned char * bufor, int &i)
{
id = readNormalNr(bufor,i, artidlen); i+=artidlen;
if(id!=artmask)
cgh->artifacts.push_back(id);
cgh->giveArtifact(id);
}
}
} //artifacts

View File

@ -1673,10 +1673,10 @@ void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1
break;
}
}
if(i == art.possibleSlots.size()) //if haven't find proper slot, use backpack
if(i == art.possibleSlots.size() && !art.isBig()) //if haven't find proper slot, use backpack or discard big artifact
sha.artifacts.push_back(artid);
}
else //should be -1 => put artifact into backpack
else if (!art.isBig()) //should be -1 => put artifact into backpack
{
sha.artifacts.push_back(artid);
}
@ -1687,7 +1687,7 @@ void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1
{
sha.artifWorn[position] = artid;
}
else
else if (!art.isBig())
{
sha.artifacts.push_back(artid);
}
@ -2330,10 +2330,13 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
return false;
}
// TODO: This relates to bug #112, fix later.
// Make sure the artifacts are not war machines.
if ((srcSlot>=13 && srcSlot<=16) || (destSlot>=13 && destSlot<=16)) {
complain("Cannot move war machine!");
if (destSlot >= 19 && srcArtifact->isBig()) {
complain("Cannot put big artifacts in backpack!");
return false;
}
if (srcSlot == 16 || destSlot == 16) {
complain("Cannot move catapult!");
return false;
}
@ -2375,9 +2378,26 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
*/
bool CGameHandler::setArtifact(si32 heroID, ui16 slot, int artID)
{
CGHeroInstance *hero = gs->getHero(heroID);
const CGHeroInstance *hero = gs->getHero(heroID);
// TODO: Deal with war machine placement.
if (artID != -1) {
const CArtifact &artifact = VLC->arth->artifacts[artID];
if (slot < 19 && !vstd::contains(artifact.possibleSlots, slot)) {
complain("Artifact does not fit!");
return false;
}
if (slot >= 19 && artifact.isBig()) {
complain("Cannot put big artifacts in backpack!");
return false;
}
}
if (slot == 16) {
complain("Cannot alter catapult slot!");
return false;
}
// Perform the exchange.
SetHeroArtifacts sha;