1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-25 21:38:59 +02:00

Spell scroll improvements, fixing , , .

CArtPlace now uses common CInfoWindow for r-click popup (with or without a custom component), old CMessage::genWindow no longer needed.
This commit is contained in:
Michał W. Urbańczyk 2011-03-12 21:55:31 +00:00
parent 122a6a039e
commit 39120fe4a5
10 changed files with 140 additions and 76 deletions

@ -326,37 +326,37 @@ std::vector<std::vector<SDL_Surface*> > * CMessage::drawText(std::vector<std::st
} //ends for(int i=0; i<brtext->size();i++)
return txtg;
}
CSimpleWindow * CMessage::genWindow(std::string text, int player, bool centerOnMouse, int Lmar, int Rmar, int Tmar, int Bmar)
{
CSimpleWindow * ret = new CSimpleWindow();
int fontHeight;
std::vector<std::string> brtext = breakText(text,32);
std::vector<std::vector<SDL_Surface*> > * txtg = drawText(&brtext, fontHeight);
std::pair<int,int> txts = getMaxSizes(txtg, fontHeight);
ret->bitmap = drawBox1(txts.first+Lmar+Rmar,txts.second+Tmar+Bmar,player);
ret->pos.h = ret->bitmap->h;
ret->pos.w = ret->bitmap->w;
if (centerOnMouse)
{
ret->pos.x = GH.current->motion.x - ret->pos.w/2;
ret->pos.y = GH.current->motion.y - ret->pos.h/2;
// Put the window back on screen if necessary
amax(ret->pos.x, 0);
amax(ret->pos.y, 0);
amin(ret->pos.x, conf.cc.resx - ret->pos.w);
amin(ret->pos.y, conf.cc.resy - ret->pos.h);
}
else
{
// Center on screen
ret->pos.x = screen->w/2 - (ret->pos.w/2);
ret->pos.y = screen->h/2 - (ret->pos.h/2);
}
int curh = ret->bitmap->h/2 - (fontHeight*txtg->size())/2;
blitTextOnSur(txtg,fontHeight,curh,ret->bitmap);
delete txtg;
return ret;
}
//CSimpleWindow * CMessage::genWindow(std::string text, int player, bool centerOnMouse, int Lmar, int Rmar, int Tmar, int Bmar)
//{
// CSimpleWindow * ret = new CSimpleWindow();
// int fontHeight;
// std::vector<std::string> brtext = breakText(text,32);
// std::vector<std::vector<SDL_Surface*> > * txtg = drawText(&brtext, fontHeight);
// std::pair<int,int> txts = getMaxSizes(txtg, fontHeight);
// ret->bitmap = drawBox1(txts.first+Lmar+Rmar,txts.second+Tmar+Bmar,player);
// ret->pos.h = ret->bitmap->h;
// ret->pos.w = ret->bitmap->w;
// if (centerOnMouse)
// {
// ret->pos.x = GH.current->motion.x - ret->pos.w/2;
// ret->pos.y = GH.current->motion.y - ret->pos.h/2;
// // Put the window back on screen if necessary
// amax(ret->pos.x, 0);
// amax(ret->pos.y, 0);
// amin(ret->pos.x, conf.cc.resx - ret->pos.w);
// amin(ret->pos.y, conf.cc.resy - ret->pos.h);
// }
// else
// {
// // Center on screen
// ret->pos.x = screen->w/2 - (ret->pos.w/2);
// ret->pos.y = screen->h/2 - (ret->pos.h/2);
// }
// int curh = ret->bitmap->h/2 - (fontHeight*txtg->size())/2;
// blitTextOnSur(txtg,fontHeight,curh,ret->bitmap);
// delete txtg;
// return ret;
//}
SDL_Surface * CMessage::drawBoxTextBitmapSub( int player, std::string text, SDL_Surface* bitmap, std::string sub, int charperline/*=30*/, int imgToBmp/*=55*/ )
{
int curh;

@ -706,10 +706,7 @@ const Rect & CIntObject::center( const Rect &r, bool propagate )
{
pos.w = r.w;
pos.h = r.h;
moveBy(Point(screen->w/2 - r.w/2 - pos.x,
screen->h/2 - r.h/2 - pos.y),
propagate);
return pos;
return center(Point(screen->w/2, screen->h/2), propagate);
}
const Rect & CIntObject::center( bool propagate )
@ -717,6 +714,14 @@ const Rect & CIntObject::center( bool propagate )
return center(pos, propagate);
}
const Rect & CIntObject::center(const Point &p, bool propagate /*= true*/)
{
moveBy(Point(p.x - pos.w/2 - pos.x,
p.y - pos.h/2 - pos.y),
propagate);
return pos;
}
void CIntObject::moveBy( const Point &p, bool propagate /*= true*/ )
{
pos.x += p.x;

@ -418,7 +418,8 @@ public:
void blitAtLoc(SDL_Surface * src, const Point &p, SDL_Surface * dst);
bool isItInLoc(const SDL_Rect &rect, int x, int y);
bool isItInLoc(const SDL_Rect &rect, const Point &p);
const Rect & center(const Rect &r, bool propagate = true); //sets pos so that r will be in the center of screen, returns new position
const Rect & center(const Rect &r, bool propagate = true); //sets pos so that r will be in the center of screen, assigns sizes of r to pos, returns new position
const Rect & center(const Point &p, bool propagate = true); //moves object so that point p will be in its center
const Rect & center(bool propagate = true); //centers when pos.w and pos.h are set, returns new position
void moveBy(const Point &p, bool propagate = true);
void moveTo(const Point &p, bool propagate = true);

@ -491,7 +491,7 @@ void CGarrisonInt::setArmy(const CArmedInstance *army, bool bottomGarrison)
armedObjs[bottomGarrison] = army;
}
CInfoWindow::CInfoWindow(std::string Text, int player, const std::vector<SComponent*> &comps, std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons, bool delComps)
CInfoWindow::CInfoWindow(std::string Text, int player, const TCompsInfo &comps, const TButtonsInfo &Buttons, bool delComps)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
ID = -1;
@ -504,8 +504,11 @@ CInfoWindow::CInfoWindow(std::string Text, int player, const std::vector<SCompon
text = new CTextBox(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, zwykly);
text->redrawParentOnScrolling = true;
buttons.front()->assignedKeys.insert(SDLK_RETURN); //first button - reacts on enter
buttons.back()->assignedKeys.insert(SDLK_ESCAPE); //last button - reacts on escape
if(buttons.size())
{
buttons.front()->assignedKeys.insert(SDLK_RETURN); //first button - reacts on enter
buttons.back()->assignedKeys.insert(SDLK_ESCAPE); //last button - reacts on escape
}
for(int i=0;i<comps.size();i++)
{
@ -609,11 +612,12 @@ void CRClickPopup::close()
GH.popIntTotally(this);
}
void CRClickPopup::createAndPush(const std::string &txt)
void CRClickPopup::createAndPush(const std::string &txt, const CInfoWindow::TCompsInfo &comps)
{
int player = LOCPLINT ? LOCPLINT->playerID : 1; //if no player, then use blue
CSimpleWindow * temp = CMessage::genWindow(txt,player,true);
CSimpleWindow * temp = new CInfoWindow(txt, player, comps);
temp->center(Point(GH.current->motion)); //center on mouse
CRClickPopupInt *rcpi = new CRClickPopupInt(temp,true);
GH.pushInt(rcpi);
}
@ -4750,6 +4754,7 @@ void CArtPlace::setMeAsDest(bool backpackAsVoid /*= true*/)
void CArtPlace::setArtifact(const CArtifactInstance *art)
{
baseType = -1; //by default we don't store any component
ourArt = art;
if(!art)
{
@ -4759,6 +4764,26 @@ void CArtPlace::setArtifact(const CArtifactInstance *art)
else
{
text = ourArt->artType->Description();
if(art->artType->id == 1) //spell scroll
{
// we expect scroll description to be like this: This scroll contains the [spell name] spell which is added into your spell book for as long as you carry the scroll.
// so we want to replace text in [...] with a spell name
// however other language versions don't have name placeholder at all, so we have to be careful
int spellID = art->getGivenSpellID();
int nameStart = text.find_first_of('[');
int nameEnd = text.find_first_of(']', nameStart);
if(spellID >= 0)
{
if(nameStart != std::string::npos && nameEnd != std::string::npos)
text = text.replace(nameStart, nameEnd - nameStart + 1, CGI->spellh->spells[spellID]->name);
//add spell component info (used to provide a pic in r-click popup)
baseType = SComponent::spell;
type = spellID;
bonusValue = 0;
}
}
if (locked) // Locks should appear as empty.
hoverText = CGI->generaltexth->allTexts[507];
else
@ -4821,7 +4846,7 @@ void LRClickableAreaWTextComp::clickLeft(tribool down, bool previousState)
{
if((!down) && previousState)
{
std::vector<SComponent*> comp(1, new SComponent(SComponent::Etype(baseType), type, bonusValue));
std::vector<SComponent*> comp(1, createComponent());
LOCPLINT->showInfoDialog(text, comp);
}
}
@ -4831,6 +4856,28 @@ LRClickableAreaWTextComp::LRClickableAreaWTextComp(const Rect &Pos, int BaseType
{
}
SComponent * LRClickableAreaWTextComp::createComponent() const
{
if(baseType >= 0)
return new SComponent(SComponent::Etype(baseType), type, bonusValue);
else
return NULL;
}
void LRClickableAreaWTextComp::clickRight(tribool down, bool previousState)
{
if(down)
{
if(SComponent *comp = createComponent())
{
CRClickPopup::createAndPush(text, CInfoWindow::TCompsInfo(1, comp));
return;
}
}
LRClickableAreaWText::clickRight(down, previousState); //only if with-component variant not occured
}
CHeroArea::CHeroArea(int x, int y, const CGHeroInstance * _hero):hero(_hero)
{
used = LCLICK | RCLICK | HOVER;

@ -80,6 +80,8 @@ class CInfoWindow : public CSimpleWindow
bool delComps; //whether comps will be deleted
public:
typedef std::vector<std::pair<std::string,CFunctionList<void()> > > TButtonsInfo;
typedef std::vector<SComponent*> TCompsInfo;
int ID; //for identification
CTextBox *text;
std::vector<AdventureMapButton *> buttons;
@ -93,7 +95,7 @@ public:
void showAll(SDL_Surface * to);
void sliderMoved(int to);
CInfoWindow(std::string Text, int player, const std::vector<SComponent*> &comps, std::vector<std::pair<std::string,CFunctionList<void()> > > &Buttons, bool delComps); //c-tor
CInfoWindow(std::string Text, int player, const TCompsInfo &comps = TCompsInfo(), const TButtonsInfo &Buttons = TButtonsInfo(), bool delComps = true); //c-tor
CInfoWindow(); //c-tor
~CInfoWindow(); //d-tor
@ -124,7 +126,7 @@ public:
CRClickPopup();
virtual ~CRClickPopup(); //d-tor
static void createAndPush(const std::string &txt);
static void createAndPush(const std::string &txt, const CInfoWindow::TCompsInfo &comps = CInfoWindow::TCompsInfo());
static void createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment = BOTTOMRIGHT);
};
@ -870,8 +872,10 @@ public:
int baseType;
int bonusValue, type;
virtual void clickLeft(tribool down, bool previousState);
virtual void clickRight(tribool down, bool previousState);
LRClickableAreaWTextComp(const Rect &Pos = Rect(0,0,0,0), int BaseType = -1);
SComponent * createComponent() const;
};
class MoraleLuckBox : public LRClickableAreaWTextComp

@ -1026,6 +1026,17 @@ void CArtifactInstance::deserializationFix()
setType(artType);
}
int CArtifactInstance::getGivenSpellID() const
{
const Bonus * b = getBonus(Selector::type(Bonus::SPELL));
if(!b)
{
tlog3 << "Warning: " << nodeName() << " doesn't bear any spell!\n";
return -1;
}
return b->subtype;
}
bool CCombinedArtifactInstance::canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved /*= false*/) const
{
bool canMainArtifactBePlaced = CArtifactInstance::canBePutAt(al, assumeDestRemoved);

@ -30,13 +30,7 @@ public:
const std::string &Name() const; //getter
const std::string &Description() const; //getter
bool isBig () const;
//bool isModable () const;
//bool fitsAt (const std::map<ui16, const CArtifact*> &artifWorn, ui16 slot) const;
//bool canBeAssembledTo (const std::map<ui16, const CArtifact*> &artifWorn, ui32 artifactID) const;
// void addBonusesTo (BonusList *otherBonuses) const;
// void removeBonusesFrom (BonusList *otherBonuses) const;
virtual void SetProperty (int mod){};
virtual void Init(){};
int getArtClassSerial() const; //0 - treasure, 1 - minor, 2 - major, 3 - relic, 4 - spell scroll, 5 - other
std::string nodeName() const OVERRIDE;
@ -79,6 +73,7 @@ public:
int firstAvailableSlot(const CGHeroInstance *h) const;
int firstBackpackSlot(const CGHeroInstance *h) const;
int getGivenSpellID() const; //to be used with scrolls (and similiar arts), -1 if none
virtual bool canBePutAt(const ArtifactLocation &al, bool assumeDestRemoved = false) const;
virtual bool canBeDisassembled() const;

@ -3612,12 +3612,12 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
if(!stacksCount())
{
InfoWindow iw;
iw.soundID = soundBase::treasure;
iw.player = h->tempOwner;
switch(ID)
{
case 5:
case 5:
{
iw.soundID = soundBase::treasure; //play sound only for non-scroll arts
iw.components.push_back(Component(4,subID,0,0));
if(message.length())
iw.text << message;
@ -3625,15 +3625,14 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
iw.text << std::pair<ui8,ui32>(12,subID);
}
break;
case 93:
{
int spellID = storedArtifact->getBonus(Selector::type(Bonus::SPELL))->subtype;
iw.components.push_back (Component(Component::SPELL, spellID,0,0));
iw.text.addTxt (MetaString::ADVOB_TXT,135);
iw.text.addReplacement(MetaString::SPELL_NAME, spellID);
}
case 93:
{
int spellID = storedArtifact->getGivenSpellID();
iw.components.push_back (Component(Component::SPELL, spellID,0,0));
iw.text.addTxt (MetaString::ADVOB_TXT,135);
iw.text.addReplacement(MetaString::SPELL_NAME, spellID);
}
break;
}
cb->showInfoDialog(&iw);
pick(h);

@ -1471,14 +1471,16 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
case 65: case 66: case 67: case 68: case 69: //random artifact
case 93: //spell scroll
{
int artID = -1;
int spellID = -1;
CGArtifact *art = new CGArtifact();
nobj = art;
bool areSettings = bufor[i]; ++i;
bool areSettings = bufor[i++];
if(areSettings)
{
art->message = readString(bufor,i);
bool areGuards = bufor[i]; ++i;
bool areGuards = bufor[i++];
if(areGuards)
{
readCreatureSet(art, bufor, i, 7, version > RoE);
@ -1486,22 +1488,17 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
i+=4;
}
CArtifactInstance *innerArt = NULL;
if(defInfo->id==93)
{
int spellID = readNormalNr(bufor,i);
i+=4;
innerArt = CArtifactInstance::createScroll(VLC->spellh->spells[spellID]);
spellID = readNormalNr(bufor,i); i+=4;
artID = 1;
}
else if(defInfo->id == 5) //specific artifact
{
innerArt = createArt(defInfo->subid);
artID = defInfo->subid;
}
else
{
innerArt = createArt(-1);
}
art->storedArtifact = innerArt;
art->storedArtifact = createArt(artID, spellID);
break;
}
case 76: case 79: //random resource; resource
@ -2080,11 +2077,16 @@ void Mapa::loadArtifactsOfHero(const unsigned char * bufor, int & i, CGHeroInsta
} //artifacts
}
CArtifactInstance * Mapa::createArt(int aid)
CArtifactInstance * Mapa::createArt(int aid, int spellID /*= -1*/)
{
CArtifactInstance *a = NULL;
if(aid >= 0)
a = CArtifactInstance::createNewArtifactInstance(aid);
{
if(spellID < 0)
a = CArtifactInstance::createNewArtifactInstance(aid);
else
a = CArtifactInstance::createScroll(VLC->spellh->spells[spellID]);
}
else
a = new CArtifactInstance();

@ -325,7 +325,7 @@ struct DLL_EXPORT Mapa : public CMapHeader
void loadTown( CGObjectInstance * &nobj, const unsigned char * bufor, int &i, int subid);
int loadSeerHut( const unsigned char * bufor, int i, CGObjectInstance *& nobj);
CArtifactInstance *createArt(int aid);
CArtifactInstance *createArt(int aid, int spellID = -1);
void addNewArtifactInstance(CArtifactInstance *art);
void eraseArtifactInstance(CArtifactInstance *art);