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:
parent
b79fe389a2
commit
ef5b1ca1de
@ -3696,10 +3696,11 @@ bool CArtPlace::fitsHere(const CArtifact * art)
|
|||||||
if(!art)
|
if(!art)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Anything can be placed in the backpack, except War Machines.
|
// Anything can but War Machines can be placed in backpack.
|
||||||
if (slotID >= 19 && !CGI->arth->isBigArtifact(art->id)
|
if (slotID >= 19) {
|
||||||
|| vstd::contains(art->possibleSlots, slotID))
|
return !CGI->arth->isBigArtifact(art->id);
|
||||||
{
|
} else if (vstd::contains(art->possibleSlots, slotID)) {
|
||||||
|
// TODO: Deal with combinational at dest and as src.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,11 +674,11 @@ public:
|
|||||||
{
|
{
|
||||||
std::set<CArtifactsOfHero *> participants; // Needed to mark slots.
|
std::set<CArtifactsOfHero *> participants; // Needed to mark slots.
|
||||||
const CArtifact * srcArtifact; // Held artifact.
|
const CArtifact * srcArtifact; // Held artifact.
|
||||||
const CArtifactsOfHero * srcAOH; // Following two needed to uniquely identify the source.
|
const CArtifactsOfHero * srcAOH; // Following two needed to uniquely identify the source.
|
||||||
int srcSlotID; //
|
int srcSlotID; //
|
||||||
const CArtifactsOfHero * destAOH; // For swapping. (i.e. changing what is held)
|
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
|
int destSlotID; // Needed to determine what kind of action was last taken in setHero
|
||||||
const CArtifact * destArtifact; // For swapping.
|
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
|
} * 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;
|
AdventureMapButton * leftArtRoll, * rightArtRoll;
|
||||||
@ -812,4 +812,4 @@ class CFreelancersWindow : public CShopWindow
|
|||||||
{};
|
{};
|
||||||
class CHillFortWindow : public CIntObject //garrison dialog? shop?
|
class CHillFortWindow : public CIntObject //garrison dialog? shop?
|
||||||
{};
|
{};
|
||||||
#endif //__GUICLASSES_H__
|
#endif //__GUICLASSES_H__
|
@ -35,6 +35,12 @@ const std::string & CArtifact::Description() const
|
|||||||
else
|
else
|
||||||
return VLC->generaltexth->artifDescriptions[id];
|
return VLC->generaltexth->artifDescriptions[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CArtifact::isBig () const
|
||||||
|
{
|
||||||
|
return VLC->arth->isBigArtifact(id);
|
||||||
|
}
|
||||||
|
|
||||||
CArtHandler::CArtHandler()
|
CArtHandler::CArtHandler()
|
||||||
{
|
{
|
||||||
VLC->arth = this;
|
VLC->arth = this;
|
||||||
@ -79,6 +85,75 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
|
|||||||
if(desc[0] == '\"' && desc[desc.size()-1] == '\"')
|
if(desc[0] == '\"' && desc[desc.size()-1] == '\"')
|
||||||
desc = desc.substr(1,desc.size()-2);
|
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)
|
if(!onlyTxt)
|
||||||
artifacts.push_back(nart);
|
artifacts.push_back(nart);
|
||||||
}
|
}
|
||||||
|
@ -25,16 +25,18 @@ public:
|
|||||||
enum EartClass {ART_SPECIAL=1, ART_TREASURE=2, ART_MINOR=4, ART_MAJOR=8, ART_RELIC=16}; //artifact classes
|
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 &Name() const; //getter
|
||||||
const std::string &Description() const; //getter
|
const std::string &Description() const; //getter
|
||||||
|
bool isBig () const;
|
||||||
|
|
||||||
ui32 price;
|
ui32 price;
|
||||||
std::vector<ui16> possibleSlots; //ids of slots where artifact can be placed
|
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;
|
EartClass aClass;
|
||||||
ui32 id;
|
ui32 id;
|
||||||
std::list<HeroBonus> bonuses; //bonuses given by artifact
|
std::list<HeroBonus> bonuses; //bonuses given by artifact
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1197,6 +1197,26 @@ si32 CGHeroInstance::getArtPos(int aid) const
|
|||||||
return -1;
|
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()
|
void CGHeroInstance::recreateArtBonuses()
|
||||||
{
|
{
|
||||||
//clear all bonuses from artifacts (if present) and give them again
|
//clear all bonuses from artifacts (if present) and give them again
|
||||||
|
@ -296,6 +296,7 @@ public:
|
|||||||
ui32 getArtAtPos(ui16 pos) const; //-1 - no artifact
|
ui32 getArtAtPos(ui16 pos) const; //-1 - no artifact
|
||||||
const CArtifact * getArt(int pos) const;
|
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)
|
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
|
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
|
static int3 convertPosition(int3 src, bool toh3m); //toh3m=true: manifest->h3m; toh3m=false: h3m->manifest
|
||||||
double getHeroStrength() const;
|
double getHeroStrength() const;
|
||||||
|
@ -1448,7 +1448,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
|
|||||||
hero->recreateArtBonuses();
|
hero->recreateArtBonuses();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
hero->artifacts.push_back(toGive->id);
|
hero->giveArtifact(toGive->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1005,7 +1005,7 @@ void Mapa::loadHero( CGObjectInstance * &nobj, const unsigned char * bufor, int
|
|||||||
{
|
{
|
||||||
id = readNormalNr(bufor,i, artidlen); i+=artidlen;
|
id = readNormalNr(bufor,i, artidlen); i+=artidlen;
|
||||||
if(id!=artmask)
|
if(id!=artmask)
|
||||||
nhi->artifacts.push_back(id);
|
nhi->giveArtifact(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} //artifacts
|
} //artifacts
|
||||||
@ -1244,7 +1244,7 @@ void Mapa::readPredefinedHeroes( const unsigned char * bufor, int &i)
|
|||||||
{
|
{
|
||||||
id = readNormalNr(bufor,i, artidlen); i+=artidlen;
|
id = readNormalNr(bufor,i, artidlen); i+=artidlen;
|
||||||
if(id!=artmask)
|
if(id!=artmask)
|
||||||
cgh->artifacts.push_back(id);
|
cgh->giveArtifact(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} //artifacts
|
} //artifacts
|
||||||
|
@ -1673,10 +1673,10 @@ void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1
|
|||||||
break;
|
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);
|
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);
|
sha.artifacts.push_back(artid);
|
||||||
}
|
}
|
||||||
@ -1687,7 +1687,7 @@ void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1
|
|||||||
{
|
{
|
||||||
sha.artifWorn[position] = artid;
|
sha.artifWorn[position] = artid;
|
||||||
}
|
}
|
||||||
else
|
else if (!art.isBig())
|
||||||
{
|
{
|
||||||
sha.artifacts.push_back(artid);
|
sha.artifacts.push_back(artid);
|
||||||
}
|
}
|
||||||
@ -2330,10 +2330,13 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This relates to bug #112, fix later.
|
if (destSlot >= 19 && srcArtifact->isBig()) {
|
||||||
// Make sure the artifacts are not war machines.
|
complain("Cannot put big artifacts in backpack!");
|
||||||
if ((srcSlot>=13 && srcSlot<=16) || (destSlot>=13 && destSlot<=16)) {
|
return false;
|
||||||
complain("Cannot move war machine!");
|
}
|
||||||
|
|
||||||
|
if (srcSlot == 16 || destSlot == 16) {
|
||||||
|
complain("Cannot move catapult!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2375,9 +2378,26 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
|
|||||||
*/
|
*/
|
||||||
bool CGameHandler::setArtifact(si32 heroID, ui16 slot, int artID)
|
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.
|
// Perform the exchange.
|
||||||
SetHeroArtifacts sha;
|
SetHeroArtifacts sha;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user