mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-21 21:17:49 +02:00
* Fixed the artifact screen completely, hopefully. Structural overhaul of the CArtPlace and CArtifactsOfHero classes, and I had to add a new server message SetArtifact to deal with things properly. The only thing that differs from H3 now is that you can't have gaps of empty slots in the backpack.
* Preliminary work on bug #112, a bigArtifacts set is added to CArtHandler.
This commit is contained in:
parent
df3ef1c330
commit
0a96decf87
@ -416,6 +416,16 @@ bool CCallback::swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGH
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CCallback::setArtifact(const CGHeroInstance * hero, ui16 pos, int artID)
|
||||||
|
{
|
||||||
|
if(player != hero->tempOwner)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SetArtifact sa(hero->id, pos, artID);
|
||||||
|
sendRequest(&sa);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID)
|
bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID)
|
||||||
{
|
{
|
||||||
CGTownInstance * t = const_cast<CGTownInstance *>(town);
|
CGTownInstance * t = const_cast<CGTownInstance *>(town);
|
||||||
|
@ -224,6 +224,7 @@ public:
|
|||||||
int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2, int val);
|
int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2, int val);
|
||||||
bool dismissHero(const CGHeroInstance * hero);
|
bool dismissHero(const CGHeroInstance * hero);
|
||||||
bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2);
|
bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2);
|
||||||
|
bool setArtifact(const CGHeroInstance * hero, ui16 pos, int artID);
|
||||||
bool buildBuilding(const CGTownInstance *town, si32 buildingID);
|
bool buildBuilding(const CGTownInstance *town, si32 buildingID);
|
||||||
void recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount);
|
void recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount);
|
||||||
bool dismissCreature(const CArmedInstance *obj, int stackPos);
|
bool dismissCreature(const CArmedInstance *obj, int stackPos);
|
||||||
|
@ -55,7 +55,6 @@ CHeroWindow::CHeroWindow(int playerColor):
|
|||||||
artifs = new CArtifactsOfHero(pos);
|
artifs = new CArtifactsOfHero(pos);
|
||||||
artifs->commonInfo = new CArtifactsOfHero::SCommonPart;
|
artifs->commonInfo = new CArtifactsOfHero::SCommonPart;
|
||||||
artifs->commonInfo->participants.insert(artifs);
|
artifs->commonInfo->participants.insert(artifs);
|
||||||
artifs->commonInfo->activeArtPlace = NULL;
|
|
||||||
|
|
||||||
garr = NULL;
|
garr = NULL;
|
||||||
ourBar = new CStatusBar(pos.x+72, pos.y+567, "ADROLLVR.bmp", 660);
|
ourBar = new CStatusBar(pos.x+72, pos.y+567, "ADROLLVR.bmp", 660);
|
||||||
@ -146,6 +145,7 @@ CHeroWindow::~CHeroWindow()
|
|||||||
delete garr;
|
delete garr;
|
||||||
delete ourBar;
|
delete ourBar;
|
||||||
|
|
||||||
|
artifs->rollback();
|
||||||
delete artifs->commonInfo;
|
delete artifs->commonInfo;
|
||||||
artifs->commonInfo = NULL; //to prevent heap corruption
|
artifs->commonInfo = NULL; //to prevent heap corruption
|
||||||
delete artifs;
|
delete artifs;
|
||||||
@ -506,6 +506,7 @@ void CHeroWindow::dispose()
|
|||||||
curBack = NULL;
|
curBack = NULL;
|
||||||
curHero = NULL;
|
curHero = NULL;
|
||||||
|
|
||||||
|
artifs->rollback();
|
||||||
artifs->dispose();
|
artifs->dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3497,7 +3497,7 @@ CRClickPopupInt::~CRClickPopupInt()
|
|||||||
CGI->curh->show();
|
CGI->curh->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
CArtPlace::CArtPlace(const CArtifact* Art): active(false), clicked(false), marked(false), ourArt(Art)/*,
|
CArtPlace::CArtPlace(const CArtifact* Art): active(false), marked(false), ourArt(Art)/*,
|
||||||
spellBook(false), warMachine1(false), warMachine2(false), warMachine3(false),
|
spellBook(false), warMachine1(false), warMachine2(false), warMachine3(false),
|
||||||
warMachine4(false),misc1(false), misc2(false), misc3(false), misc4(false),
|
warMachine4(false),misc1(false), misc2(false), misc3(false), misc4(false),
|
||||||
misc5(false), feet(false), lRing(false), rRing(false), torso(false),
|
misc5(false), feet(false), lRing(false), rRing(false), torso(false),
|
||||||
@ -3520,7 +3520,7 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
|
|||||||
//LRClickableAreaWTextComp::clickLeft(down);
|
//LRClickableAreaWTextComp::clickLeft(down);
|
||||||
|
|
||||||
// If clicked on spellbook, open it only if no artifact is held at the moment.
|
// If clicked on spellbook, open it only if no artifact is held at the moment.
|
||||||
if(ourArt && !down && previousState && !ourOwner->commonInfo->activeArtPlace)
|
if(ourArt && !down && previousState && !ourOwner->commonInfo->srcAOH)
|
||||||
{
|
{
|
||||||
if(ourArt->id == 0)
|
if(ourArt->id == 0)
|
||||||
{
|
{
|
||||||
@ -3528,11 +3528,11 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
|
|||||||
GH.pushInt(spellWindow);
|
GH.pushInt(spellWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!down && (!clicked || ourOwner->commonInfo->srcSlotID >= 19) && previousState) //not clicked before
|
if (!down && previousState)
|
||||||
{
|
{
|
||||||
if(ourArt && ourArt->id == 0)
|
if(ourArt && ourArt->id == 0)
|
||||||
return; //this is handled separately
|
return; //this is handled separately
|
||||||
if(!ourOwner->commonInfo->activeArtPlace) //nothing has been clicked
|
if(!ourOwner->commonInfo->srcAOH) //nothing has been clicked
|
||||||
{
|
{
|
||||||
if(ourArt) //to prevent selecting empty slots (bugfix to what GrayFace reported)
|
if(ourArt) //to prevent selecting empty slots (bugfix to what GrayFace reported)
|
||||||
{
|
{
|
||||||
@ -3567,39 +3567,36 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
|
|||||||
default:
|
default:
|
||||||
ourOwner->commonInfo->destAOH = ourOwner;
|
ourOwner->commonInfo->destAOH = ourOwner;
|
||||||
ourOwner->commonInfo->destSlotID = slotID;
|
ourOwner->commonInfo->destSlotID = slotID;
|
||||||
|
ourOwner->commonInfo->destArtifact = NULL;
|
||||||
|
|
||||||
LOCPLINT->cb->swapArtifacts(
|
LOCPLINT->cb->setArtifact(
|
||||||
ourOwner->commonInfo->activeArtPlace->ourOwner->curHero,
|
|
||||||
ourOwner->commonInfo->srcSlotID,
|
|
||||||
ourOwner->curHero,
|
ourOwner->curHero,
|
||||||
slotID);
|
slotID,
|
||||||
|
ourOwner->commonInfo->srcArtifact->id);
|
||||||
|
|
||||||
ourOwner->commonInfo->activeArtPlace->deselect();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//check if swap is possible
|
//check if swap is possible
|
||||||
else if(this->fitsHere(ourOwner->commonInfo->srcArtifact) && ourOwner->commonInfo->activeArtPlace->fitsHere(this->ourArt))
|
else if (this->fitsHere(ourOwner->commonInfo->srcArtifact))
|
||||||
{
|
{
|
||||||
ourOwner->commonInfo->destAOH = ourOwner;
|
ourOwner->commonInfo->destAOH = ourOwner;
|
||||||
ourOwner->commonInfo->destSlotID = slotID;
|
ourOwner->commonInfo->destSlotID = slotID;
|
||||||
|
ourOwner->commonInfo->destArtifact = ourArt;
|
||||||
|
|
||||||
LOCPLINT->cb->swapArtifacts(
|
LOCPLINT->cb->setArtifact(
|
||||||
ourOwner->commonInfo->activeArtPlace->ourOwner->curHero,
|
|
||||||
ourOwner->commonInfo->srcSlotID,
|
|
||||||
ourOwner->curHero,
|
ourOwner->curHero,
|
||||||
slotID);
|
slotID,
|
||||||
|
ourOwner->commonInfo->srcArtifact->id);
|
||||||
ourOwner->commonInfo->activeArtPlace->deselect();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(!down && clicked)
|
/*else if(!down && clicked)
|
||||||
{
|
{
|
||||||
if(ourArt && ourArt->id == 0)
|
if(ourArt && ourArt->id == 0)
|
||||||
return; //this is handled separately
|
return; //this is handled separately
|
||||||
deselect();
|
deselect();
|
||||||
}
|
}*/
|
||||||
//ClickableL::clickLeft(down);
|
//ClickableL::clickLeft(down);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3615,20 +3612,19 @@ void CArtPlace::clickRight(tribool down, bool previousState)
|
|||||||
void CArtPlace::select ()
|
void CArtPlace::select ()
|
||||||
{
|
{
|
||||||
CGI->curh->dragAndDropCursor(graphics->artDefs->ourImages[ourArt->id].bitmap);
|
CGI->curh->dragAndDropCursor(graphics->artDefs->ourImages[ourArt->id].bitmap);
|
||||||
clicked = true;
|
|
||||||
ourOwner->markPossibleSlots(ourArt);
|
ourOwner->markPossibleSlots(ourArt);
|
||||||
|
|
||||||
ourOwner->commonInfo->activeArtPlace = this;
|
|
||||||
ourOwner->commonInfo->srcArtifact = ourArt;
|
ourOwner->commonInfo->srcArtifact = ourArt;
|
||||||
ourOwner->commonInfo->srcSlotID = slotID;
|
ourOwner->commonInfo->srcSlotID = slotID;
|
||||||
ourOwner->commonInfo->srcAOH = ourOwner;
|
ourOwner->commonInfo->srcAOH = ourOwner;
|
||||||
|
|
||||||
if (slotID >= 19) {
|
if (slotID >= 19) {
|
||||||
// Updates backpack, possibly correcting the position.
|
// Correcting position in backpack.
|
||||||
ourOwner->scrollBackpack(-(slotID - 19 < ourOwner->backpackPos));
|
ourOwner->scrollBackpack(-(slotID - 19 < ourOwner->backpackPos));
|
||||||
} else {
|
} else {
|
||||||
ourOwner->eraseSlotData(this, slotID);
|
ourOwner->eraseSlotData(this, slotID);
|
||||||
}
|
}
|
||||||
|
LOCPLINT->cb->setArtifact(ourOwner->curHero, slotID, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3636,14 +3632,8 @@ void CArtPlace::select ()
|
|||||||
*/
|
*/
|
||||||
void CArtPlace::deselect ()
|
void CArtPlace::deselect ()
|
||||||
{
|
{
|
||||||
clicked = false;
|
|
||||||
CGI->curh->dragAndDropCursor(NULL);
|
CGI->curh->dragAndDropCursor(NULL);
|
||||||
ourOwner->unmarkSlots();
|
ourOwner->unmarkSlots();
|
||||||
ourOwner->commonInfo->activeArtPlace = NULL;
|
|
||||||
|
|
||||||
// If a worn artifact is deselected, restore it's picture.
|
|
||||||
if (slotID < 19 && !ourOwner->commonInfo->destAOH)
|
|
||||||
ourOwner->setSlotData(this, slotID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CArtPlace::deactivate()
|
void CArtPlace::deactivate()
|
||||||
@ -3658,10 +3648,9 @@ void CArtPlace::deactivate()
|
|||||||
|
|
||||||
void CArtPlace::show(SDL_Surface *to)
|
void CArtPlace::show(SDL_Surface *to)
|
||||||
{
|
{
|
||||||
if(ourArt && (!clicked || slotID >= 19))
|
if (ourArt)
|
||||||
{
|
|
||||||
blitAt(graphics->artDefs->ourImages[ourArt->id].bitmap, pos.x, pos.y, to);
|
blitAt(graphics->artDefs->ourImages[ourArt->id].bitmap, pos.x, pos.y, to);
|
||||||
}
|
|
||||||
if(marked && active)
|
if(marked && active)
|
||||||
{
|
{
|
||||||
// Draw vertical bars.
|
// Draw vertical bars.
|
||||||
@ -3685,8 +3674,8 @@ bool CArtPlace::fitsHere(const CArtifact * art)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Anything can be placed in the backpack, except War Machines.
|
// Anything can be placed in the backpack, except War Machines.
|
||||||
if(slotID > 18 && !(art->id >= 3 && art->id <= 6)
|
if (slotID >= 19 && !CGI->arth->isBigArtifact(art->id)
|
||||||
|| vstd::contains(art->possibleSlots,slotID))
|
|| vstd::contains(art->possibleSlots, slotID))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3697,10 +3686,6 @@ bool CArtPlace::fitsHere(const CArtifact * art)
|
|||||||
CArtPlace::~CArtPlace()
|
CArtPlace::~CArtPlace()
|
||||||
{
|
{
|
||||||
deactivate();
|
deactivate();
|
||||||
|
|
||||||
// Make sure a currently held artifact does not affect the outside.
|
|
||||||
if (clicked)
|
|
||||||
CGI->curh->dragAndDropCursor(NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LClickableArea::activate()
|
void LClickableArea::activate()
|
||||||
@ -3867,124 +3852,141 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
|
|||||||
{
|
{
|
||||||
// An update is made, rather than initialization.
|
// An update is made, rather than initialization.
|
||||||
if (curHero == hero) {
|
if (curHero == hero) {
|
||||||
// Compensate backpack pos if an artifact is insertad before it.
|
// Compensate backpack pos if an artifact was insertad before it.
|
||||||
if (commonInfo->destSlotID >= 19 && commonInfo->destAOH == this
|
if (commonInfo->destSlotID >= 19 && commonInfo->destAOH == this
|
||||||
&& commonInfo->destSlotID - 19 < backpackPos)
|
&& commonInfo->destSlotID - 19 < backpackPos)
|
||||||
{
|
{
|
||||||
backpackPos++;
|
backpackPos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A swap was made, make the replaced artifact into current selected.
|
||||||
|
if (commonInfo->destSlotID < 19 && commonInfo->destArtifact) {
|
||||||
|
// Source <- Dest
|
||||||
|
commonInfo->srcAOH = commonInfo->destAOH;
|
||||||
|
commonInfo->srcArtifact = commonInfo->destArtifact;
|
||||||
|
commonInfo->srcSlotID = -1; // The artifact's original place is taken now.
|
||||||
|
|
||||||
|
// Reset destination parameters.
|
||||||
|
commonInfo->destAOH = NULL;
|
||||||
|
commonInfo->destArtifact = NULL;
|
||||||
|
commonInfo->destSlotID = -1;
|
||||||
|
|
||||||
|
CGI->curh->dragAndDropCursor(
|
||||||
|
graphics->artDefs->ourImages[commonInfo->srcArtifact->id].bitmap);
|
||||||
|
markPossibleSlots(commonInfo->srcArtifact);
|
||||||
|
} else if (commonInfo->destAOH != NULL) {
|
||||||
|
// Reset all parameters.
|
||||||
|
commonInfo->srcAOH = NULL;
|
||||||
|
commonInfo->srcArtifact = NULL;
|
||||||
|
commonInfo->srcSlotID = -1;
|
||||||
|
commonInfo->destAOH = NULL;
|
||||||
|
commonInfo->destArtifact = NULL;
|
||||||
|
commonInfo->destSlotID = -1;
|
||||||
|
|
||||||
|
CGI->curh->dragAndDropCursor(NULL);
|
||||||
|
unmarkSlots();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rollback();
|
||||||
}
|
}
|
||||||
|
|
||||||
commonInfo->srcAOH = NULL;
|
|
||||||
commonInfo->srcArtifact = NULL;
|
|
||||||
commonInfo->srcSlotID = 0; // Can be anything that's not in backpack range.
|
|
||||||
commonInfo->destAOH = NULL;
|
|
||||||
commonInfo->destSlotID = 0;
|
|
||||||
|
|
||||||
curHero = hero;
|
curHero = hero;
|
||||||
backpackSize = curHero->artifacts.size();
|
|
||||||
|
|
||||||
// Remove any previously allocated slots.
|
|
||||||
for(size_t g=0; g<artWorn.size(); ++g)
|
|
||||||
delete artWorn[g];
|
|
||||||
for(size_t g=0; g<backpack.size(); ++g)
|
|
||||||
delete backpack[g];
|
|
||||||
backpack.clear();
|
|
||||||
|
|
||||||
std::vector<SDL_Rect> slotPos;
|
|
||||||
if (curHero->artifacts.size() > 0)
|
if (curHero->artifacts.size() > 0)
|
||||||
backpackPos %= curHero->artifacts.size();
|
backpackPos %= curHero->artifacts.size();
|
||||||
else
|
else
|
||||||
backpackPos = 0;
|
backpackPos = 0;
|
||||||
|
|
||||||
slotPos += genRect(44,44,pos.x+509,pos.y+30), genRect(44,44,pos.x+567,pos.y+240), genRect(44,44,pos.x+509,pos.y+80),
|
// Fill the slots for worn artifacts and backpack.
|
||||||
genRect(44,44,pos.x+383,pos.y+68), genRect(44,44,pos.x+564,pos.y+183), genRect(44,44,pos.x+509,pos.y+130),
|
|
||||||
genRect(44,44,pos.x+431,pos.y+68), genRect(44,44,pos.x+610,pos.y+183), genRect(44,44,pos.x+515,pos.y+295),
|
|
||||||
genRect(44,44,pos.x+383,pos.y+143), genRect(44,44,pos.x+399,pos.y+194), genRect(44,44,pos.x+415,pos.y+245),
|
|
||||||
genRect(44,44,pos.x+431,pos.y+296), genRect(44,44,pos.x+564,pos.y+30), genRect(44,44,pos.x+610,pos.y+30),
|
|
||||||
genRect(44,44,pos.x+610,pos.y+76), genRect(44,44,pos.x+610,pos.y+122), genRect(44,44,pos.x+610,pos.y+310),
|
|
||||||
genRect(44,44,pos.x+381,pos.y+296);
|
|
||||||
|
|
||||||
// Fill the slots for worn artifacts.
|
|
||||||
for (int g = 0; g < 19 ; g++)
|
for (int g = 0; g < 19 ; g++)
|
||||||
{
|
|
||||||
artWorn[g] = new CArtPlace(hero->getArt(g));
|
|
||||||
artWorn[g]->pos = slotPos[g];
|
|
||||||
artWorn[g]->ourOwner = this;
|
|
||||||
setSlotData(artWorn[g], g);
|
setSlotData(artWorn[g], g);
|
||||||
}
|
scrollBackpack(0);
|
||||||
|
|
||||||
// Fill the slots for the backpack.
|
|
||||||
for(size_t s=0; s<5; ++s)
|
|
||||||
{
|
|
||||||
CArtPlace * add = new CArtPlace(NULL);
|
|
||||||
|
|
||||||
add->ourOwner = this;
|
|
||||||
add->pos.x = pos.x + 403 + 46*s;
|
|
||||||
add->pos.y = pos.y + 365;
|
|
||||||
add->pos.h = add->pos.w = 44;
|
|
||||||
|
|
||||||
if (s < curHero->artifacts.size())
|
|
||||||
setSlotData(add, 19 + (s + backpackPos)%curHero->artifacts.size());
|
|
||||||
else
|
|
||||||
setSlotData(add, 19 + s);
|
|
||||||
backpack.push_back(add);
|
|
||||||
}
|
|
||||||
commonInfo->activeArtPlace = NULL;
|
|
||||||
|
|
||||||
//blocking scrolling if there is not enough artifacts to scroll
|
//blocking scrolling if there is not enough artifacts to scroll
|
||||||
leftArtRoll->block(curHero->artifacts.size() <= backpack.size());
|
leftArtRoll->block(curHero->artifacts.size() <= backpack.size());
|
||||||
rightArtRoll->block(curHero->artifacts.size() <= backpack.size());
|
rightArtRoll->block(curHero->artifacts.size() <= backpack.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any held artifacts, marked slots etc. will be restored to it's original way.
|
||||||
|
*/
|
||||||
|
void CArtifactsOfHero::rollback()
|
||||||
|
{
|
||||||
|
if (curHero != NULL) {
|
||||||
|
// Restore any held artifact to it's original position.
|
||||||
|
if (commonInfo->destArtifact && commonInfo->destAOH == this) {
|
||||||
|
// For an unlikely race condition scenario, put swapped artifact into backpack.
|
||||||
|
LOCPLINT->cb->setArtifact(
|
||||||
|
curHero,
|
||||||
|
19 + curHero->artifacts.size(),
|
||||||
|
commonInfo->destArtifact->id);
|
||||||
|
}
|
||||||
|
else if (commonInfo->srcArtifact && commonInfo->srcAOH == this) {
|
||||||
|
if (commonInfo->srcSlotID != -1) { // Held artifact, just put it back to it's spot.
|
||||||
|
LOCPLINT->cb->setArtifact(
|
||||||
|
curHero,
|
||||||
|
commonInfo->srcSlotID,
|
||||||
|
commonInfo->srcArtifact->id);
|
||||||
|
} else { // Swapped artifact.
|
||||||
|
// Wear the artifact in a suitable spot.
|
||||||
|
ui16 i = 0;
|
||||||
|
for (; i < 19; i++) {
|
||||||
|
if (artWorn[i]->fitsHere(commonInfo->srcArtifact)
|
||||||
|
&& curHero->artifWorn.find(i) == curHero->artifWorn.end())
|
||||||
|
{
|
||||||
|
LOCPLINT->cb->setArtifact(
|
||||||
|
curHero, i, commonInfo->srcArtifact->id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it can't be worn, put it in the backpack.
|
||||||
|
if (i == 19)
|
||||||
|
LOCPLINT->cb->setArtifact(
|
||||||
|
curHero,
|
||||||
|
19 + curHero->artifacts.size(),
|
||||||
|
commonInfo->srcArtifact->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unmarkSlots();
|
||||||
|
backpackPos = 0;
|
||||||
|
|
||||||
|
commonInfo->srcAOH = NULL;
|
||||||
|
commonInfo->srcArtifact = NULL;
|
||||||
|
commonInfo->srcSlotID = -1;
|
||||||
|
commonInfo->destAOH = NULL;
|
||||||
|
commonInfo->destArtifact = NULL;
|
||||||
|
commonInfo->destSlotID = -1;
|
||||||
|
|
||||||
|
CGI->curh->dragAndDropCursor(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void CArtifactsOfHero::dispose()
|
void CArtifactsOfHero::dispose()
|
||||||
{
|
{
|
||||||
curHero = NULL;
|
curHero = NULL;
|
||||||
for(size_t g=0; g<artWorn.size(); ++g)
|
|
||||||
{
|
|
||||||
delete artWorn[g];
|
|
||||||
artWorn[g] = NULL;
|
|
||||||
}
|
|
||||||
for(size_t g=0; g<backpack.size(); ++g)
|
|
||||||
{
|
|
||||||
delete backpack[g];
|
|
||||||
backpack[g] = NULL;
|
|
||||||
}
|
|
||||||
backpack.clear();
|
|
||||||
if(commonInfo)
|
|
||||||
commonInfo->activeArtPlace = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CArtifactsOfHero::scrollBackpack(int dir)
|
void CArtifactsOfHero::scrollBackpack(int dir)
|
||||||
{
|
{
|
||||||
backpackPos += dir;
|
backpackPos += dir;
|
||||||
if (backpackPos < 0) { // No guarantee of modulus behavior with negative operands.
|
if (curHero->artifacts.size() > 0) {
|
||||||
do {
|
if (backpackPos < 0) { // No guarantee of modulus behavior with negative operands.
|
||||||
backpackPos += curHero->artifacts.size();
|
do {
|
||||||
} while (backpackPos < 0);
|
backpackPos += curHero->artifacts.size();
|
||||||
} else {
|
} while (backpackPos < 0);
|
||||||
backpackPos %= curHero->artifacts.size();
|
} else {
|
||||||
|
backpackPos %= curHero->artifacts.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const int tempBackpackSize = curHero->artifacts.size() - (commonInfo->srcSlotID >= 19);
|
|
||||||
|
|
||||||
//set new data
|
//set new data
|
||||||
for (size_t s = 0; s < backpack.size(); ++s) {
|
for (size_t s = 0; s < backpack.size(); ++s) {
|
||||||
int slotID = 19 + (s + backpackPos)%tempBackpackSize;
|
if (s < curHero->artifacts.size())
|
||||||
|
setSlotData(backpack[s], 19 + (s + backpackPos)%curHero->artifacts.size());
|
||||||
// Don't show the held artifact, skip it.
|
|
||||||
if (commonInfo->srcAOH == this && commonInfo->srcSlotID >= 19 && slotID >= commonInfo->srcSlotID)
|
|
||||||
slotID++;
|
|
||||||
|
|
||||||
if (s < tempBackpackSize)
|
|
||||||
setSlotData(backpack[s], slotID);
|
|
||||||
else
|
else
|
||||||
eraseSlotData(backpack[s], slotID);
|
eraseSlotData(backpack[s], 19 + s);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activate/deactivate sliders.
|
|
||||||
leftArtRoll->block(tempBackpackSize <= backpack.size());
|
|
||||||
rightArtRoll->block(tempBackpackSize <= backpack.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4053,6 +4055,38 @@ CArtifactsOfHero::CArtifactsOfHero(const SDL_Rect & position) :
|
|||||||
pos = position;
|
pos = position;
|
||||||
artWorn.resize(19);
|
artWorn.resize(19);
|
||||||
|
|
||||||
|
std::vector<SDL_Rect> slotPos;
|
||||||
|
slotPos += genRect(44,44,pos.x+509,pos.y+30), genRect(44,44,pos.x+567,pos.y+240), genRect(44,44,pos.x+509,pos.y+80),
|
||||||
|
genRect(44,44,pos.x+383,pos.y+68), genRect(44,44,pos.x+564,pos.y+183), genRect(44,44,pos.x+509,pos.y+130),
|
||||||
|
genRect(44,44,pos.x+431,pos.y+68), genRect(44,44,pos.x+610,pos.y+183), genRect(44,44,pos.x+515,pos.y+295),
|
||||||
|
genRect(44,44,pos.x+383,pos.y+143), genRect(44,44,pos.x+399,pos.y+194), genRect(44,44,pos.x+415,pos.y+245),
|
||||||
|
genRect(44,44,pos.x+431,pos.y+296), genRect(44,44,pos.x+564,pos.y+30), genRect(44,44,pos.x+610,pos.y+30),
|
||||||
|
genRect(44,44,pos.x+610,pos.y+76), genRect(44,44,pos.x+610,pos.y+122), genRect(44,44,pos.x+610,pos.y+310),
|
||||||
|
genRect(44,44,pos.x+381,pos.y+296);
|
||||||
|
|
||||||
|
// Create slots for worn artifacts.
|
||||||
|
for (int g = 0; g < 19 ; g++)
|
||||||
|
{
|
||||||
|
artWorn[g] = new CArtPlace(NULL);
|
||||||
|
artWorn[g]->pos = slotPos[g];
|
||||||
|
artWorn[g]->ourOwner = this;
|
||||||
|
eraseSlotData(artWorn[g], g);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create slots for the backpack.
|
||||||
|
for(size_t s=0; s<5; ++s)
|
||||||
|
{
|
||||||
|
CArtPlace * add = new CArtPlace(NULL);
|
||||||
|
|
||||||
|
add->ourOwner = this;
|
||||||
|
add->pos.x = pos.x + 403 + 46*s;
|
||||||
|
add->pos.y = pos.y + 365;
|
||||||
|
add->pos.h = add->pos.w = 44;
|
||||||
|
eraseSlotData(add, 19 + s);
|
||||||
|
|
||||||
|
backpack.push_back(add);
|
||||||
|
}
|
||||||
|
|
||||||
leftArtRoll = new AdventureMapButton(std::string(), std::string(), boost::bind(&CArtifactsOfHero::scrollBackpack,this,-1), pos.x+379, pos.y+364, "hsbtns3.def", SDLK_LEFT);
|
leftArtRoll = new AdventureMapButton(std::string(), std::string(), boost::bind(&CArtifactsOfHero::scrollBackpack,this,-1), pos.x+379, pos.y+364, "hsbtns3.def", SDLK_LEFT);
|
||||||
rightArtRoll = new AdventureMapButton(std::string(), std::string(), boost::bind(&CArtifactsOfHero::scrollBackpack,this,+1), pos.x+632, pos.y+364, "hsbtns5.def", SDLK_RIGHT);
|
rightArtRoll = new AdventureMapButton(std::string(), std::string(), boost::bind(&CArtifactsOfHero::scrollBackpack,this,+1), pos.x+632, pos.y+364, "hsbtns5.def", SDLK_RIGHT);
|
||||||
}
|
}
|
||||||
@ -4060,6 +4094,17 @@ CArtifactsOfHero::CArtifactsOfHero(const SDL_Rect & position) :
|
|||||||
CArtifactsOfHero::~CArtifactsOfHero()
|
CArtifactsOfHero::~CArtifactsOfHero()
|
||||||
{
|
{
|
||||||
dispose();
|
dispose();
|
||||||
|
for(size_t g=0; g<artWorn.size(); ++g)
|
||||||
|
{
|
||||||
|
delete artWorn[g];
|
||||||
|
artWorn[g] = NULL;
|
||||||
|
}
|
||||||
|
for(size_t g=0; g<backpack.size(); ++g)
|
||||||
|
{
|
||||||
|
delete backpack[g];
|
||||||
|
backpack[g] = NULL;
|
||||||
|
}
|
||||||
|
backpack.clear();
|
||||||
artWorn.clear();
|
artWorn.clear();
|
||||||
|
|
||||||
delete leftArtRoll;
|
delete leftArtRoll;
|
||||||
@ -4261,7 +4306,6 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL)
|
|||||||
artifs[0] = new CArtifactsOfHero(genRect(600, 800, pos.x + -334, pos.y + 150));
|
artifs[0] = new CArtifactsOfHero(genRect(600, 800, pos.x + -334, pos.y + 150));
|
||||||
artifs[0]->commonInfo = new CArtifactsOfHero::SCommonPart;
|
artifs[0]->commonInfo = new CArtifactsOfHero::SCommonPart;
|
||||||
artifs[0]->commonInfo->participants.insert(artifs[0]);
|
artifs[0]->commonInfo->participants.insert(artifs[0]);
|
||||||
artifs[0]->commonInfo->activeArtPlace = NULL;
|
|
||||||
artifs[0]->setHero(heroInst[0]);
|
artifs[0]->setHero(heroInst[0]);
|
||||||
artifs[1] = new CArtifactsOfHero(genRect(600, 800, pos.x + 96, pos.y + 150));
|
artifs[1] = new CArtifactsOfHero(genRect(600, 800, pos.x + 96, pos.y + 150));
|
||||||
artifs[1]->commonInfo = artifs[0]->commonInfo;
|
artifs[1]->commonInfo = artifs[0]->commonInfo;
|
||||||
@ -4353,6 +4397,8 @@ CExchangeWindow::~CExchangeWindow() //d-tor
|
|||||||
delete quit;
|
delete quit;
|
||||||
|
|
||||||
//warning: don't experiment with these =NULL lines, they prevent heap corruption!
|
//warning: don't experiment with these =NULL lines, they prevent heap corruption!
|
||||||
|
artifs[0]->rollback();
|
||||||
|
artifs[1]->rollback();
|
||||||
delete artifs[0]->commonInfo;
|
delete artifs[0]->commonInfo;
|
||||||
artifs[0]->commonInfo = NULL;
|
artifs[0]->commonInfo = NULL;
|
||||||
delete artifs[0];
|
delete artifs[0];
|
||||||
|
@ -645,7 +645,6 @@ public:
|
|||||||
// lHand, rHand, neck, shoulders, head; //my types
|
// lHand, rHand, neck, shoulders, head; //my types
|
||||||
ui16 slotID; //0 head 1 shoulders 2 neck 3 right hand 4 left hand 5 torso 6 right ring 7 left ring 8 feet 9 misc. slot 1 10 misc. slot 2 11 misc. slot 3 12 misc. slot 4 13 ballista (war machine 1) 14 ammo cart (war machine 2) 15 first aid tent (war machine 3) 16 catapult 17 spell book 18 misc. slot 5 19+ backpack slots
|
ui16 slotID; //0 head 1 shoulders 2 neck 3 right hand 4 left hand 5 torso 6 right ring 7 left ring 8 feet 9 misc. slot 1 10 misc. slot 2 11 misc. slot 3 12 misc. slot 4 13 ballista (war machine 1) 14 ammo cart (war machine 2) 15 first aid tent (war machine 3) 16 catapult 17 spell book 18 misc. slot 5 19+ backpack slots
|
||||||
|
|
||||||
bool clicked;
|
|
||||||
bool marked;
|
bool marked;
|
||||||
CArtifactsOfHero * ourOwner;
|
CArtifactsOfHero * ourOwner;
|
||||||
const CArtifact * ourArt;
|
const CArtifact * ourArt;
|
||||||
@ -666,7 +665,6 @@ class CArtifactsOfHero : public CIntObject
|
|||||||
{
|
{
|
||||||
const CGHeroInstance * curHero;
|
const CGHeroInstance * curHero;
|
||||||
|
|
||||||
size_t backpackSize; // Used to check differences in backpack sizes.
|
|
||||||
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 *> 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!)
|
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; //unmber of first art visible in backpack (in hero's vector)
|
||||||
@ -675,12 +673,12 @@ public:
|
|||||||
struct SCommonPart
|
struct SCommonPart
|
||||||
{
|
{
|
||||||
std::set<CArtifactsOfHero *> participants; // Needed to mark slots.
|
std::set<CArtifactsOfHero *> participants; // Needed to mark slots.
|
||||||
CArtPlace * activeArtPlace;
|
const CArtifact * srcArtifact; // Held artifact.
|
||||||
const CArtifact * srcArtifact; // Held artifact., technically superfluous right now.
|
|
||||||
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.
|
||||||
} * 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;
|
||||||
@ -691,6 +689,7 @@ public:
|
|||||||
|
|
||||||
void setHero(const CGHeroInstance * hero);
|
void setHero(const CGHeroInstance * hero);
|
||||||
void dispose(); //free resources not needed after closing windows and reset state
|
void dispose(); //free resources not needed after closing windows and reset state
|
||||||
|
void rollback();
|
||||||
void scrollBackpack(int dir); //dir==-1 => to left; dir==1 => to right
|
void scrollBackpack(int dir); //dir==-1 => to left; dir==1 => to right
|
||||||
void markPossibleSlots (const CArtifact* art);
|
void markPossibleSlots (const CArtifact* art);
|
||||||
void unmarkSlots ();
|
void unmarkSlots ();
|
||||||
|
@ -38,6 +38,10 @@ const std::string & CArtifact::Description() const
|
|||||||
CArtHandler::CArtHandler()
|
CArtHandler::CArtHandler()
|
||||||
{
|
{
|
||||||
VLC->arth = this;
|
VLC->arth = this;
|
||||||
|
|
||||||
|
// War machines are the default big artifacts.
|
||||||
|
for (ui32 i = 3; i <= 6; i++)
|
||||||
|
bigArtifacts.insert(i);
|
||||||
}
|
}
|
||||||
void CArtHandler::loadArtifacts(bool onlyTxt)
|
void CArtHandler::loadArtifacts(bool onlyTxt)
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define __CARTHANDLER_H__
|
#define __CARTHANDLER_H__
|
||||||
#include "../global.h"
|
#include "../global.h"
|
||||||
#include "../lib/HeroBonus.h"
|
#include "../lib/HeroBonus.h"
|
||||||
|
#include <set>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -43,11 +44,13 @@ class DLL_EXPORT CArtHandler //handles artifacts
|
|||||||
public:
|
public:
|
||||||
std::vector<CArtifact*> treasures, minors, majors, relics;
|
std::vector<CArtifact*> treasures, minors, majors, relics;
|
||||||
std::vector<CArtifact> artifacts;
|
std::vector<CArtifact> artifacts;
|
||||||
|
std::set<ui32> bigArtifacts; // Artifacts that cannot be moved to backpack, e.g. war machines.
|
||||||
|
|
||||||
void loadArtifacts(bool onlyTxt);
|
void loadArtifacts(bool onlyTxt);
|
||||||
void sortArts();
|
void sortArts();
|
||||||
void addBonuses();
|
void addBonuses();
|
||||||
void clear();
|
void clear();
|
||||||
|
bool isBigArtifact (ui32 artID) {return bigArtifacts.find(artID) != bigArtifacts.end();}
|
||||||
static int convertMachineID(int id, bool creToArt);
|
static int convertMachineID(int id, bool creToArt);
|
||||||
CArtHandler();
|
CArtHandler();
|
||||||
|
|
||||||
|
@ -1307,7 +1307,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
|
|||||||
players.insert(ins);
|
players.insert(ins);
|
||||||
}
|
}
|
||||||
/******************RESOURCES****************************************************/
|
/******************RESOURCES****************************************************/
|
||||||
//TODO: computer player should receive other amount of resource than computer (depending on difficulty)
|
//TODO: computer player should receive other amount of resource than player (depending on difficulty)
|
||||||
std::vector<int> startres;
|
std::vector<int> startres;
|
||||||
std::ifstream tis(DATA_DIR "/config/startres.txt");
|
std::ifstream tis(DATA_DIR "/config/startres.txt");
|
||||||
int k;
|
int k;
|
||||||
|
@ -1226,6 +1226,22 @@ struct ExchangeArtifacts : public CPackForServer
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SetArtifact : public CPackForServer
|
||||||
|
{
|
||||||
|
SetArtifact () {};
|
||||||
|
SetArtifact (si32 hid, ui16 slot, int artID)
|
||||||
|
:hid(hid), slot(slot), artID(artID) {};
|
||||||
|
si32 hid;
|
||||||
|
ui16 slot;
|
||||||
|
int artID;
|
||||||
|
|
||||||
|
bool applyGh(CGameHandler *gh);
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & hid & slot & artID;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct BuyArtifact : public CPackForServer
|
struct BuyArtifact : public CPackForServer
|
||||||
{
|
{
|
||||||
BuyArtifact(){};
|
BuyArtifact(){};
|
||||||
|
@ -137,6 +137,7 @@ void registerTypes3(Serializer &s)
|
|||||||
s.template registerType<UpgradeCreature>();
|
s.template registerType<UpgradeCreature>();
|
||||||
s.template registerType<GarrisonHeroSwap>();
|
s.template registerType<GarrisonHeroSwap>();
|
||||||
s.template registerType<ExchangeArtifacts>();
|
s.template registerType<ExchangeArtifacts>();
|
||||||
|
s.template registerType<SetArtifact>();
|
||||||
s.template registerType<BuyArtifact>();
|
s.template registerType<BuyArtifact>();
|
||||||
s.template registerType<TradeOnMarketplace>();
|
s.template registerType<TradeOnMarketplace>();
|
||||||
s.template registerType<SetFormation>();
|
s.template registerType<SetFormation>();
|
||||||
|
@ -2326,6 +2326,7 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This relates to bug #112, fix later.
|
||||||
// Make sure the artifacts are not war machines.
|
// Make sure the artifacts are not war machines.
|
||||||
if ((srcSlot>=13 && srcSlot<=16) || (destSlot>=13 && destSlot<=16)) {
|
if ((srcSlot>=13 && srcSlot<=16) || (destSlot>=13 && destSlot<=16)) {
|
||||||
complain("Cannot move war machine!");
|
complain("Cannot move war machine!");
|
||||||
@ -2363,6 +2364,28 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a hero artifact slot to contain a specific artifact.
|
||||||
|
*
|
||||||
|
* @param artID ID of an artifact or -1 for no artifact.
|
||||||
|
*/
|
||||||
|
bool CGameHandler::setArtifact(si32 heroID, ui16 slot, int artID)
|
||||||
|
{
|
||||||
|
CGHeroInstance *hero = gs->getHero(heroID);
|
||||||
|
|
||||||
|
// TODO: Deal with war machine placement.
|
||||||
|
|
||||||
|
// Perform the exchange.
|
||||||
|
SetHeroArtifacts sha;
|
||||||
|
sha.hid = heroID;
|
||||||
|
sha.artifacts = hero->artifacts;
|
||||||
|
sha.artifWorn = hero->artifWorn;
|
||||||
|
sha.setArtAtPos(slot, artID);
|
||||||
|
sendAndApply(&sha);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
|
bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
|
||||||
{
|
{
|
||||||
CGHeroInstance *hero = gs->getHero(hid);
|
CGHeroInstance *hero = gs->getHero(hid);
|
||||||
|
@ -155,6 +155,7 @@ public:
|
|||||||
bool tradeResources( ui32 val, ui8 player, ui32 id1, ui32 id2 );
|
bool tradeResources( ui32 val, ui8 player, ui32 id1, ui32 id2 );
|
||||||
bool buyArtifact( ui32 hid, si32 aid );
|
bool buyArtifact( ui32 hid, si32 aid );
|
||||||
bool swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, ui16 destSlot);
|
bool swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, ui16 destSlot);
|
||||||
|
bool setArtifact(si32 heroID, ui16 slot, int artID);
|
||||||
bool garrisonSwap(si32 tid);
|
bool garrisonSwap(si32 tid);
|
||||||
bool upgradeCreature( ui32 objid, ui8 pos, ui32 upgID );
|
bool upgradeCreature( ui32 objid, ui8 pos, ui32 upgID );
|
||||||
bool recruitCreatures(si32 objid, ui32 crid, ui32 cram);
|
bool recruitCreatures(si32 objid, ui32 crid, ui32 cram);
|
||||||
|
@ -98,6 +98,12 @@ bool ExchangeArtifacts::applyGh( CGameHandler *gh )
|
|||||||
return gh->swapArtifacts(hid1,hid2,slot1,slot2);
|
return gh->swapArtifacts(hid1,hid2,slot1,slot2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SetArtifact::applyGh( CGameHandler *gh )
|
||||||
|
{
|
||||||
|
ERROR_IF_NOT_OWNS(hid);
|
||||||
|
return gh->setArtifact(hid, slot, artID);
|
||||||
|
}
|
||||||
|
|
||||||
bool BuyArtifact::applyGh( CGameHandler *gh )
|
bool BuyArtifact::applyGh( CGameHandler *gh )
|
||||||
{
|
{
|
||||||
ERROR_IF_NOT_OWNS(hid);
|
ERROR_IF_NOT_OWNS(hid);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user