1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-30 08:57:00 +02:00

Locks for combination artifacts largely implemented, only one or two bugs when moving them around in a certain way. Artifact assembly still remaining.

To make sure these artifacts get (un)equipped properly the functions CArtHandler::equipArtifact and CArtHandler::unequipArtifact should be used instead of modifying artifWorn manually.
This commit is contained in:
OnionKnight 2010-02-08 21:17:22 +00:00
parent 28f8ef3b0f
commit 790a77c280
12 changed files with 248 additions and 72 deletions

View File

@ -257,7 +257,9 @@ void CHeroWindow::setHero(const CGHeroInstance *hero)
sprintf(bufor, CGI->generaltexth->allTexts[205].c_str(), hero->name.c_str(), hero->mana, hero->manaLimit());
spellPointsArea->text = std::string(bufor);
artifs->updateState = true;
artifs->setHero(hero);
artifs->updateState = false;
//if we have exchange window with this hero open
bool noDismiss=false;

View File

@ -853,7 +853,9 @@ void CPlayerInterface::heroArtifactSetChanged(const CGHeroInstance*hero)
{
if(cew->heroInst[g] == hero)
{
cew->artifs[g]->updateState = true;
cew->artifs[g]->setHero(hero);
cew->artifs[g]->updateState = false;
}
}
cew->prepareBackground();

View File

@ -3657,9 +3657,20 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
ourOwner->commonInfo->destSlotID = slotID;
ourOwner->commonInfo->destArtifact = ourArt;
// Special case when the dest artifact can't be fit into the src slot.
CGHeroInstance *destHero = const_cast<CGHeroInstance *>(ourOwner->curHero);
CGI->arth->unequipArtifact(destHero->artifWorn, slotID);
const CArtifactsOfHero* srcAOH = ourOwner->commonInfo->srcAOH;
ui16 srcSlotID = ourOwner->commonInfo->srcSlotID;
if (ourArt && srcSlotID < 19 && !ourArt->fitsAt(srcAOH->curHero->artifWorn, srcSlotID)) {
// Put dest artifact into owner's backpack.
ourOwner->commonInfo->srcAOH = ourOwner;
ourOwner->commonInfo->srcSlotID = ourOwner->curHero->artifacts.size() + 19;
}
LOCPLINT->cb->swapArtifacts(
ourOwner->commonInfo->srcAOH->curHero,
ourOwner->commonInfo->srcSlotID,
srcAOH->curHero,
srcSlotID,
ourOwner->curHero,
slotID);
}
@ -3676,7 +3687,7 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
void CArtPlace::clickRight(tribool down, bool previousState)
{
if(text.size()) //if there is no description, do nothing ;]
if(!locked() && text.size()) //if there is no description or it's a lock, do nothing ;]
LRClickableAreaWTextComp::clickRight(down, previousState);
}
@ -3685,8 +3696,10 @@ void CArtPlace::clickRight(tribool down, bool previousState)
*/
void CArtPlace::select ()
{
if (locked())
return;
CGI->curh->dragAndDropCursor(graphics->artDefs->ourImages[ourArt->id].bitmap);
ourOwner->markPossibleSlots(ourArt);
ourOwner->commonInfo->srcArtifact = ourArt;
ourOwner->commonInfo->srcSlotID = slotID;
@ -3695,9 +3708,10 @@ void CArtPlace::select ()
// Temporarily remove artifact from hero.
CGHeroInstance* hero = const_cast<CGHeroInstance*>(ourOwner->curHero);
if (slotID < 19)
hero->artifWorn.erase(slotID);
CGI->arth->unequipArtifact(hero->artifWorn, slotID);
else
hero->artifacts.erase(hero->artifacts.begin() + (slotID - 19));
ourOwner->markPossibleSlots(ourArt);
hero->recreateArtBonuses();
// Update the hero bonuses.
@ -3776,14 +3790,10 @@ bool CArtPlace::fitsHere(const CArtifact * art)
return true;
// Anything can but War Machines can be placed in backpack.
if (slotID >= 19) {
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;
}
return false;
return art->fitsAt(ourOwner->curHero->artifWorn, slotID);
}
CArtPlace::~CArtPlace()
@ -3988,21 +3998,20 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
backpackPos++;
}
if (commonInfo->srcAOH == this) {
if (updateState && commonInfo->srcAOH == this) {
curHero = hero;
// A swap was made, make the replaced artifact the current selected.
if (commonInfo->destSlotID < 19 && commonInfo->destArtifact) {
// Temporarily remove artifact from hero.
CGHeroInstance * hero = const_cast<CGHeroInstance *>(curHero);
CGHeroInstance * nonconstCurHero = const_cast<CGHeroInstance *>(curHero);
if (commonInfo->srcSlotID < 19)
hero->artifWorn.erase(commonInfo->srcSlotID);
CGI->arth->unequipArtifact(nonconstCurHero->artifWorn, commonInfo->srcSlotID);
else
hero->artifacts.erase(hero->artifacts.begin() + (commonInfo->srcSlotID - 19));
hero->recreateArtBonuses();
nonconstCurHero->artifacts.erase(nonconstCurHero->artifacts.begin() + (commonInfo->srcSlotID - 19));
nonconstCurHero->recreateArtBonuses();
// Source <- Dest
//commonInfo->srcAOH = commonInfo->destAOH;
commonInfo->srcArtifact = commonInfo->destArtifact;
//commonInfo->srcSlotID = commonInfo->destSlotID;
// Reset destination parameters.
commonInfo->destAOH = NULL;
@ -4059,7 +4068,7 @@ void CArtifactsOfHero::rollback()
if (commonInfo->srcSlotID != -1) {
// Put a held artifact back to it's spot.
if (commonInfo->srcSlotID < 19)
hero->artifWorn[commonInfo->srcSlotID] = commonInfo->srcArtifact->id;
CGI->arth->equipArtifact(hero->artifWorn, commonInfo->srcSlotID, commonInfo->srcArtifact->id);
else
hero->artifacts.insert(hero->artifacts.begin() + (commonInfo->srcSlotID - 19), commonInfo->srcArtifact->id);
} else { // Held swapped artifact.
@ -4069,7 +4078,7 @@ void CArtifactsOfHero::rollback()
if (artWorn[i]->fitsHere(commonInfo->srcArtifact)
&& curHero->artifWorn.find(i) == curHero->artifWorn.end())
{
hero->artifWorn[i] = commonInfo->srcArtifact->id;
CGI->arth->equipArtifact(hero->artifWorn, i, commonInfo->srcArtifact->id);
break;
}
}
@ -4137,6 +4146,8 @@ void CArtifactsOfHero::markPossibleSlots (const CArtifact* art)
for (int i = 0; i < (*it)->artWorn.size(); i++) {
if ((*it)->artWorn[i]->fitsHere(art))
(*it)->artWorn[i]->marked = true;
else
(*it)->artWorn[i]->marked = false;
}
}
}
@ -4166,7 +4177,10 @@ void CArtifactsOfHero::setSlotData (CArtPlace* artPlace, int slotID)
if (artPlace->ourArt) {
artPlace->text = artPlace->ourArt->Description();
artPlace->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % artPlace->ourArt->Name().c_str());
if (artPlace->locked()) // Locks should appear as empty.
artPlace->hoverText = CGI->generaltexth->allTexts[507];
else
artPlace->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % artPlace->ourArt->Name().c_str());
} else {
eraseSlotData(artPlace, slotID);
}
@ -4184,7 +4198,7 @@ void CArtifactsOfHero::eraseSlotData (CArtPlace* artPlace, int slotID)
}
CArtifactsOfHero::CArtifactsOfHero(const SDL_Rect & position) :
backpackPos(0)
backpackPos(0), updateState(false)
{
pos = position;
artWorn.resize(19);

View File

@ -2,6 +2,7 @@
#define __GUICLASSES_H__
#include "../global.h"
#include "../hch/CArtHandler.h"
#include "SDL_framerate.h"
#include "GUIBase.h"
#include "FunctionList.h"
@ -691,10 +692,15 @@ public:
void activate();
void deactivate();
void show(SDL_Surface * to);
bool fitsHere(const CArtifact * art); //returns true if given artifact can be placed here
bool fitsHere (const CArtifact * art); //returns true if given artifact can be placed here
bool locked () const;
~CArtPlace(); //d-tor
};
inline bool CArtPlace::locked () const
{
return ourArt && ourArt->id == 145;
}
class CArtifactsOfHero : public CIntObject
{
@ -702,7 +708,7 @@ class CArtifactsOfHero : public CIntObject
std::vector<CArtPlace *> artWorn; // 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5
std::vector<CArtPlace *> backpack; //hero's visible backpack (only 5 elements!)
int backpackPos; //unmber of first art visible in backpack (in hero's vector)
int backpackPos; //number of first art visible in backpack (in hero's vector)
public:
struct SCommonPart
@ -716,6 +722,8 @@ public:
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
bool updateState; // Whether the commonInfo should be updated on setHero or not.
AdventureMapButton * leftArtRoll, * rightArtRoll;
void activate();

View File

@ -6,6 +6,7 @@
#include <boost/assign/std/vector.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/foreach.hpp>
#include "../lib/VCMI_Lib.h"
extern CLodHandler *bitmaph;
using namespace boost::assign;
@ -36,11 +37,69 @@ const std::string & CArtifact::Description() const
return VLC->generaltexth->artifDescriptions[id];
}
bool CArtifact::isBig () const
inline bool CArtifact::isBig () const
{
return VLC->arth->isBigArtifact(id);
}
/**
* Checks whether the artifact fits at a given slot.
* @param artifWorn A hero's set of worn artifacts.
*/
bool CArtifact::fitsAt (const std::map<ui16, ui32> &artifWorn, ui16 slotID) const
{
if (!vstd::contains(possibleSlots, slotID))
return false;
// Can't put an artifact in a locked slot.
std::map<ui16, ui32>::const_iterator it = artifWorn.find(slotID);
if (it != artifWorn.end() && it->second == 145)
return false;
// Check if a combination artifact fits.
// TODO: Might want a more general algorithm?
// Assumes that misc & rings fits only in their slots, and others in only one slot and no duplicates.
if (constituents != NULL) {
std::map<ui16, ui32> tempArtifWorn = artifWorn;
const ui16 ringSlots[] = {6, 7};
const ui16 miscSlots[] = {9, 10, 11, 12, 18};
int rings = 0;
int misc = 0;
VLC->arth->unequipArtifact(tempArtifWorn, slotID);
BOOST_FOREACH(ui32 constituentID, *constituents) {
const CArtifact& constituent = VLC->arth->artifacts[constituentID];
const int slot = constituent.possibleSlots[0];
if (slot == 6 || slot == 7)
rings++;
else if (slot >= 9 && slot <= 12 || slot == 18)
misc++;
else if (tempArtifWorn.find(slot) != tempArtifWorn.end())
return false;
}
// Ensure enough ring slots are free
for (int i = 0; i < sizeof(ringSlots)/sizeof(*ringSlots); i++) {
if (tempArtifWorn.find(ringSlots[i]) == tempArtifWorn.end() || ringSlots[i] == slotID)
rings--;
}
if (rings > 0)
return false;
// Ensure enough misc slots are free.
for (int i = 0; i < sizeof(miscSlots)/sizeof(*miscSlots); i++) {
if (tempArtifWorn.find(miscSlots[i]) == tempArtifWorn.end() || miscSlots[i] == slotID)
misc--;
}
if (misc > 0)
return false;
}
return true;
}
CArtHandler::CArtHandler()
{
VLC->arth = this;
@ -52,7 +111,7 @@ CArtHandler::CArtHandler()
void CArtHandler::loadArtifacts(bool onlyTxt)
{
std::vector<ui16> slots;
slots += 17, 16, 15,14,13, 18, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0;
slots += 17, 16, 15, 14, 13, 18, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0;
static std::map<char, CArtifact::EartClass> classes =
map_list_of('S',CArtifact::ART_SPECIAL)('T',CArtifact::ART_TREASURE)('N',CArtifact::ART_MINOR)('J',CArtifact::ART_MAJOR)('R',CArtifact::ART_RELIC);
std::string buf = bitmaph->getTextFile("ARTRAITS.TXT"), dump, pom;
@ -85,65 +144,65 @@ 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.
// Fill in information about combined artifacts. Should perhaps be moved to a config file?
switch (nart.id) {
case 129: // Angelic Alliance
nart.constituents = new std::vector<ui32>(6);
nart.constituents = new std::vector<ui32>();
*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 = new std::vector<ui32>();
*nart.constituents += 54, 55, 56;
break;
case 131: // Elixir of Life
nart.constituents = new std::vector<ui32>(3);
nart.constituents = new std::vector<ui32>();
*nart.constituents += 94, 95, 96;
break;
case 132: // Armor of the Damned
nart.constituents = new std::vector<ui32>(4);
nart.constituents = new std::vector<ui32>();
*nart.constituents += 8, 14, 20, 26;
break;
case 133: // Statue of Legion
nart.constituents = new std::vector<ui32>(5);
nart.constituents = new std::vector<ui32>();
*nart.constituents += 118, 119, 120, 121, 122;
break;
case 134: // Power of the Dragon Father
nart.constituents = new std::vector<ui32>(9);
nart.constituents = new std::vector<ui32>();
*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 = new std::vector<ui32>();
*nart.constituents += 12, 18, 24, 30;
break;
case 136: // Admiral's Hat
nart.constituents = new std::vector<ui32>(2);
nart.constituents = new std::vector<ui32>();
*nart.constituents += 71, 123;
break;
case 137: // Bow of the Sharpshooter
nart.constituents = new std::vector<ui32>(3);
nart.constituents = new std::vector<ui32>();
*nart.constituents += 60, 61, 62;
break;
case 138: // Wizards' Well
nart.constituents = new std::vector<ui32>(3);
nart.constituents = new std::vector<ui32>();
*nart.constituents += 73, 74, 75;
break;
case 139: // Ring of the Magi
nart.constituents = new std::vector<ui32>(3);
nart.constituents = new std::vector<ui32>();
*nart.constituents += 76, 77, 78;
break;
case 140: // Cornucopia
nart.constituents = new std::vector<ui32>(4);
nart.constituents = new std::vector<ui32>();
*nart.constituents += 109, 110, 111, 113;
break;
@ -485,3 +544,75 @@ void CArtHandler::clear()
majors.clear();
relics.clear();
}
/**
* Locally equips an artifact to a hero's worn slots. Unequips an already present artifact.
* Does not test if the operation is legal.
* @param artifWorn A hero's set of worn artifacts.
*/
void CArtHandler::equipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID, ui32 artifactID)
{
unequipArtifact(artifWorn, slotID);
const CArtifact &artifact = artifacts[artifactID];
// Add artifact.
artifWorn[slotID] = artifactID;
// Add locks, in reverse order of being removed.
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];
if (!destConsumed && vstd::contains(constituent.possibleSlots, slotID)) {
destConsumed = true;
} else {
BOOST_FOREACH(ui16 slot, constituent.possibleSlots) {
if (artifWorn.find(slot) == artifWorn.end()) {
artifWorn[slot] = 145;
break;
}
}
}
}
}
}
/**
* Locally unequips an artifact from a hero's worn slots.
* Does not test if the operation is legal.
* @param artifWorn A hero's set of worn artifacts.
*/
void CArtHandler::unequipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID)
{
if (artifWorn.find(slotID) == artifWorn.end())
return;
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) {
bool destConsumed = false;
BOOST_FOREACH(ui32 constituentID, *artifact.constituents) {
const CArtifact &constituent = artifacts[constituentID];
if (!destConsumed && vstd::contains(constituent.possibleSlots, slotID)) {
destConsumed = true;
} else {
BOOST_REVERSE_FOREACH(ui16 slot, constituent.possibleSlots) {
if (artifWorn.find(slot) != artifWorn.end() && artifWorn[slot] == 145) {
artifWorn.erase(slot);
break;
}
}
}
}
}
}

View File

@ -26,6 +26,7 @@ public:
const std::string &Name() const; //getter
const std::string &Description() const; //getter
bool isBig () const;
bool fitsAt (const std::map<ui16, ui32> &artifWorn, ui16 slot) const;
ui32 price;
std::vector<ui16> possibleSlots; //ids of slots where artifact can be placed
@ -53,6 +54,8 @@ public:
void addBonuses();
void clear();
bool isBigArtifact (ui32 artID) {return bigArtifacts.find(artID) != bigArtifacts.end();}
void equipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID, ui32 artifactID);
void unequipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID);
static int convertMachineID(int id, bool creToArt);
CArtHandler();

View File

@ -704,9 +704,9 @@ void CGHeroInstance::initHero()
if(!vstd::contains(artifWorn, 16) && type->startingSpell >= 0) //no catapult means we haven't read pre-existant set
{
artifWorn[17] = 0; //give spellbook
VLC->arth->equipArtifact(artifWorn, 17, 0); //give spellbook
}
artifWorn[16] = 3; //everyone has a catapult
VLC->arth->equipArtifact(artifWorn, 16, 3); //everyone has a catapult
if(portrait < 0 || portrait == 255)
portrait = subID;
@ -754,10 +754,10 @@ void CGHeroInstance::initHero()
switch (pom)
{
case 145: //catapult
artifWorn[16] = 3;
VLC->arth->equipArtifact(artifWorn, 16, 3);
break;
default:
artifWorn[9+CArtHandler::convertMachineID(pom,true)] = CArtHandler::convertMachineID(pom,true);
VLC->arth->equipArtifact(artifWorn, 9+CArtHandler::convertMachineID(pom,true), CArtHandler::convertMachineID(pom,true));
break;
}
continue;
@ -1220,7 +1220,7 @@ void CGHeroInstance::giveArtifact (ui32 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;
VLC->arth->equipArtifact(artifWorn, *it, aid);
break;
}
}

View File

@ -1490,7 +1490,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
std::vector<ui16>::iterator slot = vstd::findFirstNot(hero->artifWorn,toGive->possibleSlots);
if(slot!=toGive->possibleSlots.end())
{
hero->artifWorn[*slot] = toGive->id;
VLC->arth->equipArtifact(hero->artifWorn, *slot, toGive->id);
hero->recreateArtBonuses();
}
else

View File

@ -31,7 +31,7 @@ struct DLL_EXPORT HeroBonus
NONEVIL_ALIGNMENT_MIX, //good and neutral creatures can be mixed without morale penalty
HP_REGENERATION, //regenerates a certain amount of hp for the top of each stack every turn, val - hp regained
LEVEL_SPELL_IMMUNITY, //val - spell level creatures become immune to and below
//not handled yet:
//might not be handled yet:
MAGIC_RESISTANCE, // %
SECONDARY_SKILL_PREMY, //%
SURRENDER_DISCOUNT, //%

View File

@ -464,14 +464,14 @@ DLL_EXPORT void SetHeroArtifacts::setArtAtPos(ui16 pos, int art)
if(art<0)
{
if(pos<19)
artifWorn.erase(pos);
VLC->arth->unequipArtifact(artifWorn, pos);
else
artifacts.erase(artifacts.begin() + (pos - 19));
}
else
{
if (pos < 19) {
artifWorn[pos] = art;
VLC->arth->equipArtifact(artifWorn, pos, (ui32) art);
} else { // Goes into the backpack.
if(pos - 19 < artifacts.size())
artifacts.insert(artifacts.begin() + (pos - 19), art);

View File

@ -964,27 +964,27 @@ void Mapa::loadHero( CGObjectInstance * &nobj, const unsigned char * bufor, int
{
int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
if(id!=artmask)
nhi->artifWorn[pom] = id;
VLC->arth->equipArtifact(nhi->artifWorn, pom, id);
}
//misc5 art //17
if(version>=SoD)
{
int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
if(id!=artmask)
nhi->artifWorn[16] = id;
VLC->arth->equipArtifact(nhi->artifWorn, 16, id);
else
nhi->artifWorn[16] = 3; //catapult by default
VLC->arth->equipArtifact(nhi->artifWorn, 16, 3); //catapult by default
}
//spellbook
int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
if(id!=artmask)
nhi->artifWorn[17] = id;
VLC->arth->equipArtifact(nhi->artifWorn, 17, id);
//19 //???what is that? gap in file or what? - it's probably fifth slot..
if(version>RoE)
{
id = readNormalNr(bufor,i, artidlen); i+=artidlen;
if(id!=artmask)
nhi->artifWorn[18] = id;
VLC->arth->equipArtifact(nhi->artifWorn, 18, id);
}
else
i+=1;
@ -1204,7 +1204,7 @@ void Mapa::readPredefinedHeroes( const unsigned char * bufor, int &i)
{
int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
if(id!=artmask)
cgh->artifWorn[pom] = id;
VLC->arth->equipArtifact(cgh->artifWorn, pom, id);
}
//misc5 art //17
if(version>=SoD)
@ -1217,13 +1217,13 @@ void Mapa::readPredefinedHeroes( const unsigned char * bufor, int &i)
//spellbook
int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
if(id!=artmask)
cgh->artifWorn[17] = id;
VLC->arth->equipArtifact(cgh->artifWorn, 17, id);
//19 //???what is that? gap in file or what? - it's probably fifth slot..
if(version>RoE)
{
id = readNormalNr(bufor,i, artidlen); i+=artidlen;
if(id!=artmask)
cgh->artifWorn[18] = id;
VLC->arth->equipArtifact(cgh->artifWorn, 18, id);
}
else
i+=1;

View File

@ -1806,7 +1806,7 @@ void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1
if( !vstd::contains(sha.artifWorn,art.possibleSlots[i]) )
{
//we've found a free suitable slot
sha.artifWorn[art.possibleSlots[i]] = artid;
VLC->arth->equipArtifact(sha.artifWorn, art.possibleSlots[i], artid);
break;
}
}
@ -1822,7 +1822,7 @@ void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1
{
if(!vstd::contains(sha.artifWorn,ui16(position)))
{
sha.artifWorn[position] = artid;
VLC->arth->equipArtifact(sha.artifWorn, position, artid);
}
else if (!art.isBig())
{
@ -1850,7 +1850,7 @@ void CGameHandler::removeArtifact(int artid, int hid)
{
if (itr->second == artid)
{
sha.artifWorn.erase(itr);
VLC->arth->unequipArtifact(sha.artifWorn, itr->first);
break;
}
}
@ -2536,6 +2536,7 @@ bool CGameHandler::garrisonSwap( si32 tid )
}
}
// With the amount of changes done to the function, it's more like transferArtifacts.
bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, ui16 destSlot)
{
CGHeroInstance *srcHero = gs->getHero(srcHeroID);
@ -2548,16 +2549,32 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
const CArtifact *srcArtifact = srcHero->getArt(srcSlot);
const CArtifact *destArtifact = destHero->getArt(destSlot);
SetHeroArtifacts sha;
sha.hid = srcHeroID;
sha.artifacts = srcHero->artifacts;
sha.artifWorn = srcHero->artifWorn;
// Combinational artifacts needs to be removed first so they don't get denied movement because of their own locks.
if (srcHeroID == destHeroID && srcSlot < 19) {
VLC->arth->unequipArtifact(sha.artifWorn, srcSlot);
if (sha.artifWorn.find(destSlot) == sha.artifWorn.end())
destArtifact = NULL;
}
// Check if src/dest slots are appropriate for the artifacts exchanged.
// Moving to the backpack is always allowed.
if ((!srcArtifact || destSlot < 19)
&& (((srcArtifact && !vstd::contains(srcArtifact->possibleSlots, destSlot))
|| (destArtifact && srcSlot < 19 && !vstd::contains(destArtifact->possibleSlots, srcSlot)))))
&& (srcArtifact && !srcArtifact->fitsAt(srcHeroID == destHeroID ? sha.artifWorn : destHero->artifWorn, destSlot)))
{
complain("Cannot swap artifacts!");
return false;
}
if ((srcArtifact && srcArtifact->id == 145) || (destArtifact && destArtifact->id == 145)) {
complain("Cannot move artifact locks.");
return false;
}
if (destSlot >= 19 && srcArtifact->isBig()) {
complain("Cannot put big artifacts in backpack!");
return false;
@ -2568,14 +2585,11 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
return false;
}
// Perform the exchange.
SetHeroArtifacts sha;
sha.hid = srcHeroID;
sha.artifacts = srcHero->artifacts;
sha.artifWorn = srcHero->artifWorn;
// If dest does not fit in src, put it in dest's backpack instead.
bool destFits = !destArtifact || srcSlot >= 19 || destArtifact->fitsAt(sha.artifWorn, srcSlot);
sha.setArtAtPos(srcSlot, -1);
if (destSlot < 19 && (destArtifact || srcSlot < 19))
if (destSlot < 19 && (destArtifact || srcSlot < 19) && destFits)
sha.setArtAtPos(srcSlot, destHero->getArtAtPos(destSlot));
// Internal hero artifact arrangement.
@ -2593,6 +2607,8 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
sha.artifacts = destHero->artifacts;
sha.artifWorn = destHero->artifWorn;
sha.setArtAtPos(destSlot, srcArtifact ? srcArtifact->id : -1);
if (!destFits)
sha.setArtAtPos(sha.artifacts.size() + 19, destHero->getArtAtPos(destSlot));
sendAndApply(&sha);
}
@ -3026,7 +3042,7 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
sha.hid = h->id;
sha.artifacts = h->artifacts;
sha.artifWorn = h->artifWorn;
sha.artifWorn[17] = 0;
VLC->arth->equipArtifact(sha.artifWorn, 17, 0);
sendAndApply(&sha);
}
@ -3063,9 +3079,9 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
sha.hid = hero->id;
sha.artifacts = hero->artifacts;
sha.artifWorn = hero->artifWorn;
sha.artifWorn[13] = 4;
sha.artifWorn[14] = 5;
sha.artifWorn[15] = 6;
VLC->arth->equipArtifact(sha.artifWorn, 13, 4);
VLC->arth->equipArtifact(sha.artifWorn, 14, 5);
VLC->arth->equipArtifact(sha.artifWorn, 15, 6);
sendAndApply(&sha);
}
else if(message == "vcminahar") //1000000 movement points