1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

A bunch of spellbook-related fixes: #91, #454, #462, #526, #527, #536

This commit is contained in:
Michał W. Urbańczyk 2010-07-21 10:09:29 +00:00
parent 29e7530ff5
commit 931949e349
9 changed files with 297 additions and 298 deletions

View File

@ -849,13 +849,14 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector
showInfoDialog(text,intComps,soundID);
}
void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<SComponent*> & components, int soundID)
void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<SComponent*> & components, int soundID, bool delComps)
{
waitWhileDialog();
boost::unique_lock<boost::recursive_mutex> un(*pim);
stopMovement();
CInfoWindow *temp = CInfoWindow::create(text, playerID, &components);
temp->setDelComps(delComps);
if(makingTurn && GH.listInt.size() && LOCPLINT == this)
{
CGI->soundh->playSound(static_cast<soundBase::soundID>(soundID));
@ -1012,6 +1013,7 @@ template <typename Handler> void CPlayerInterface::serializeTempl( Handler &h, c
{
h & playerID & serialID;
h & sysOpts;
h & spellbookSettings;
}
void CPlayerInterface::serialize( COSer<CSaveFile> &h, const int version )
@ -1100,6 +1102,11 @@ bool CPlayerInterface::shiftPressed() const
return SDL_GetKeyState(NULL)[SDLK_LSHIFT] || SDL_GetKeyState(NULL)[SDLK_RSHIFT];
}
bool CPlayerInterface::altPressed() const
{
return SDL_GetKeyState(NULL)[SDLK_LALT] || SDL_GetKeyState(NULL)[SDLK_RALT];
}
void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd )
{
if(stillMoveHero.get() == DURING_MOVE && adventureInt->terrain.currentPath->nodes.size() > 1) //to ignore calls on passing through garrisons
@ -2052,4 +2059,10 @@ void CPlayerInterface::showShipyardDialogOrProblemPopup(const IShipyard *obj)
}
else
showShipyardDialog(obj);
}
CPlayerInterface::SpellbookLastSetting::SpellbookLastSetting()
{
spellbookLastPageBattle = spellbokLastPageAdvmap = 0;
spellbookLastTabBattle = spellbookLastTabAdvmap = 4;
}

View File

@ -137,6 +137,18 @@ public:
std::vector<const CGTownInstance *> towns; //our heroes on the adventure map (not the garrisoned ones)
std::map<const CGHeroInstance *, CGPath> paths; //maps hero => selected path in adventure map
struct SpellbookLastSetting
{
int spellbookLastPageBattle, spellbokLastPageAdvmap; //on which page we left spellbook
int spellbookLastTabBattle, spellbookLastTabAdvmap; //on which page we left spellbook
SpellbookLastSetting();
template <typename Handler> void serialize( Handler &h, const int version )
{
h & spellbookLastPageBattle & spellbokLastPageAdvmap & spellbookLastTabBattle & spellbookLastTabAdvmap;
}
} spellbookSettings;
void update();
void recreateHeroTownList();
const CGHeroInstance *getWHero(int pos); //returns NULL if position is not valid
@ -210,6 +222,7 @@ public:
void waitWhileDialog();
bool shiftPressed() const; //determines if shift key is pressed (left or right or both)
bool ctrlPressed() const; //determines if ctrl key is pressed (left or right or both)
bool altPressed() const; //determines if alt key is pressed (left or right or both)
void redrawHeroWin(const CGHeroInstance * hero);
void showComp(SComponent comp); //TODO: comment me
void openTownWindow(const CGTownInstance * town); //shows townscreen
@ -218,7 +231,7 @@ public:
void updateInfo(const CGObjectInstance * specific);
void init(ICallback * CB);
int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on
void showInfoDialog(const std::string &text, const std::vector<SComponent*> & components = std::vector<SComponent*>(), int soundID = 0);
void showInfoDialog(const std::string &text, const std::vector<SComponent*> & components = std::vector<SComponent*>(), int soundID = 0, bool delComps = false);
void showYesNoDialog(const std::string &text, const std::vector<SComponent*> & components, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool DelComps); //deactivateCur - whether current main interface should be deactivated; delComps - if components will be deleted on window close
void stopMovement();
bool moveHero(const CGHeroInstance *h, CGPath path);

View File

@ -33,6 +33,7 @@ extern SDL_Color tytulowy, zwykly, darkTitle;
SpellbookInteractiveArea::SpellbookInteractiveArea(const SDL_Rect & myRect, boost::function<void()> funcL,
const std::string & textR, boost::function<void()> funcHon, boost::function<void()> funcHoff, CPlayerInterface * _myInt)
{
used = LCLICK | RCLICK | HOVER;
pos = myRect;
onLeft = funcL;
textOnRclick = textR;
@ -67,24 +68,10 @@ void SpellbookInteractiveArea::hover(bool on)
}
}
void SpellbookInteractiveArea::activate()
{
activateLClick();
activateRClick();
activateHover();
}
void SpellbookInteractiveArea::deactivate()
{
deactivateLClick();
deactivateRClick();
deactivateHover();
}
CSpellWindow::CSpellWindow(const SDL_Rect & myRect, const CGHeroInstance * _myHero, CPlayerInterface * _myInt, bool openOnBattleSpells):
battleSpellsOnly(openOnBattleSpells),
selectedTab(4),
spellSite(0),
currentPage(0),
myHero(_myHero),
myInt(_myInt)
{
@ -95,87 +82,27 @@ CSpellWindow::CSpellWindow(const SDL_Rect & myRect, const CGHeroInstance * _myHe
mySpells.insert(v);
}
//initializing schools' levels
for(int b=0; b<4; ++b) schoolLvls[b] = 0;
for(size_t b=0; b<myHero->secSkills.size(); ++b)
{
switch(myHero->secSkills[b].first)
{
case 14: //fire magic
schoolLvls[1] = myHero->secSkills[b].second;
break;
case 15: //air magic
schoolLvls[0] = myHero->secSkills[b].second;
break;
case 16: //water magic
schoolLvls[2] = myHero->secSkills[b].second;
break;
case 17: //earth magic
schoolLvls[3] = myHero->secSkills[b].second;
break;
}
}
//initializing sizes of spellbook's parts
for(int b=0; b<5; ++b)
sitesPerTabAdv[b] = 0;
for(int b=0; b<5; ++b)
sitesPerTabBattle[b] = 0;
for(std::set<ui32>::const_iterator g = mySpells.begin(); g!=mySpells.end(); ++g)
{
if(CGI->spellh->spells[*g].combatSpell)
{
++(sitesPerTabBattle[4]);
}
else
{
++(sitesPerTabAdv[4]);
}
const CSpell &s = CGI->spellh->spells[*g];
Uint8 *sitesPerOurTab = s.combatSpell ? sitesPerTabBattle : sitesPerTabAdv;
if(CGI->spellh->spells[*g].air)
{
if(CGI->spellh->spells[*g].combatSpell)
{
++(sitesPerTabBattle[0]);
}
else
{
++(sitesPerTabAdv[0]);
}
}
if(CGI->spellh->spells[*g].fire)
{
if(CGI->spellh->spells[*g].combatSpell)
{
++(sitesPerTabBattle[1]);
}
else
{
++(sitesPerTabAdv[1]);
}
}
if(CGI->spellh->spells[*g].water)
{
if(CGI->spellh->spells[*g].combatSpell)
{
++(sitesPerTabBattle[2]);
}
else
{
++(sitesPerTabAdv[2]);
}
}
if(CGI->spellh->spells[*g].earth)
{
if(CGI->spellh->spells[*g].combatSpell)
{
++(sitesPerTabBattle[3]);
}
else
{
++(sitesPerTabAdv[3]);
}
}
++sitesPerOurTab[4];
if(s.air)
++sitesPerOurTab[0];
if(s.fire)
++sitesPerOurTab[1];
if(s.water)
++sitesPerOurTab[2];
if(s.earth)
++sitesPerOurTab[3];
}
if(sitesPerTabAdv[4] % 12 == 0)
sitesPerTabAdv[4]/=12;
@ -243,15 +170,15 @@ CSpellWindow::CSpellWindow(const SDL_Rect & myRect, const CGHeroInstance * _myHe
manaPoints = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fmanaPtsb, this), CGI->generaltexth->zelp[459].second, boost::bind(&CStatusBar::print, statusBar, (CGI->generaltexth->zelp[459].first)), boost::bind(&CStatusBar::clear, statusBar), myInt);
temp_rect = genRect(36, 56, 549 + pos.x, 94 + pos.y);
selectSpellsA = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fspellsAb, this), CGI->generaltexth->zelp[454].second, boost::bind(&CStatusBar::print, statusBar, (CGI->generaltexth->zelp[454].first)), boost::bind(&CStatusBar::clear, statusBar), myInt);
selectSpellsA = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::selectSchool, this, 0), CGI->generaltexth->zelp[454].second, boost::bind(&CStatusBar::print, statusBar, (CGI->generaltexth->zelp[454].first)), boost::bind(&CStatusBar::clear, statusBar), myInt);
temp_rect = genRect(36, 56, 549 + pos.x, 151 + pos.y);
selectSpellsE = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fspellsEb, this), CGI->generaltexth->zelp[457].second, boost::bind(&CStatusBar::print, statusBar, (CGI->generaltexth->zelp[457].first)), boost::bind(&CStatusBar::clear, statusBar), myInt);
selectSpellsE = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::selectSchool, this, 3), CGI->generaltexth->zelp[457].second, boost::bind(&CStatusBar::print, statusBar, (CGI->generaltexth->zelp[457].first)), boost::bind(&CStatusBar::clear, statusBar), myInt);
temp_rect = genRect(36, 56, 549 + pos.x, 210 + pos.y);
selectSpellsF = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fspellsFb, this), CGI->generaltexth->zelp[455].second, boost::bind(&CStatusBar::print, statusBar, (CGI->generaltexth->zelp[455].first)), boost::bind(&CStatusBar::clear, statusBar), myInt);
selectSpellsF = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::selectSchool, this, 1), CGI->generaltexth->zelp[455].second, boost::bind(&CStatusBar::print, statusBar, (CGI->generaltexth->zelp[455].first)), boost::bind(&CStatusBar::clear, statusBar), myInt);
temp_rect = genRect(36, 56, 549 + pos.x, 270 + pos.y);
selectSpellsW = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fspellsWb, this), CGI->generaltexth->zelp[456].second, boost::bind(&CStatusBar::print, statusBar, (CGI->generaltexth->zelp[456].first)), boost::bind(&CStatusBar::clear, statusBar), myInt);
selectSpellsW = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::selectSchool, this, 2), CGI->generaltexth->zelp[456].second, boost::bind(&CStatusBar::print, statusBar, (CGI->generaltexth->zelp[456].first)), boost::bind(&CStatusBar::clear, statusBar), myInt);
temp_rect = genRect(36, 56, 549 + pos.x, 330 + pos.y);
selectSpellsAll = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fspellsAllb, this), CGI->generaltexth->zelp[458].second, boost::bind(&CStatusBar::print, statusBar, (CGI->generaltexth->zelp[458].first)), boost::bind(&CStatusBar::clear, statusBar), myInt);
selectSpellsAll = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::selectSchool, this, 4), CGI->generaltexth->zelp[458].second, boost::bind(&CStatusBar::print, statusBar, (CGI->generaltexth->zelp[458].first)), boost::bind(&CStatusBar::clear, statusBar), myInt);
temp_rect = genRect(leftCorner->h, leftCorner->w, 97 + pos.x, 77 + pos.y);
lCorner = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fLcornerb, this), CGI->generaltexth->zelp[450].second, boost::bind(&CStatusBar::print, statusBar, (CGI->generaltexth->zelp[450].first)), boost::bind(&CStatusBar::clear, statusBar), myInt);
@ -282,6 +209,10 @@ CSpellWindow::CSpellWindow(const SDL_Rect & myRect, const CGHeroInstance * _myHe
}
}
}
selectedTab = battleSpellsOnly ? LOCPLINT->spellbookSettings.spellbookLastTabBattle : LOCPLINT->spellbookSettings.spellbookLastTabAdvmap;
currentPage = battleSpellsOnly ? LOCPLINT->spellbookSettings.spellbookLastPageBattle : LOCPLINT->spellbookSettings.spellbokLastPageAdvmap;
abetw(currentPage, 0, pagesWithinCurrentTab());
computeSpellsPerArea();
}
@ -319,25 +250,30 @@ CSpellWindow::~CSpellWindow()
void CSpellWindow::fexitb()
{
(LOCPLINT->battleInt ? LOCPLINT->spellbookSettings.spellbookLastTabBattle : LOCPLINT->spellbookSettings.spellbookLastTabAdvmap) = selectedTab;
(LOCPLINT->battleInt ? LOCPLINT->spellbookSettings.spellbookLastPageBattle : LOCPLINT->spellbookSettings.spellbokLastPageAdvmap) = currentPage;
GH.popIntTotally(this);
}
void CSpellWindow::fadvSpellsb()
{
if (battleSpellsOnly == true) {
if (battleSpellsOnly == true)
{
turnPageRight();
battleSpellsOnly = false;
spellSite = 0;
currentPage = 0;
}
computeSpellsPerArea();
}
void CSpellWindow::fbattleSpellsb()
{
if (battleSpellsOnly == false) {
if (battleSpellsOnly == false)
{
turnPageLeft();
battleSpellsOnly = true;
spellSite = 0;
currentPage = 0;
}
computeSpellsPerArea();
}
@ -346,75 +282,40 @@ void CSpellWindow::fmanaPtsb()
{
}
void CSpellWindow::fspellsAb()
void CSpellWindow::selectSchool(int school)
{
if (selectedTab != 0) {
if (selectedTab != school)
{
turnPageRight();
selectedTab = 0;
spellSite = 0;
}
computeSpellsPerArea();
}
void CSpellWindow::fspellsEb()
{
if (selectedTab != 3) {
turnPageRight();
selectedTab = 3;
spellSite = 0;
}
computeSpellsPerArea();
}
void CSpellWindow::fspellsFb()
{
if (selectedTab != 1) {
turnPageRight();
selectedTab = 1;
spellSite = 0;
}
computeSpellsPerArea();
}
void CSpellWindow::fspellsWb()
{
if (selectedTab != 2) {
turnPageRight();
selectedTab = 2;
spellSite = 0;
}
computeSpellsPerArea();
}
void CSpellWindow::fspellsAllb()
{
if (selectedTab != 4) {
turnPageRight();
selectedTab = 4;
spellSite = 0;
selectedTab = school;
currentPage = 0;
}
computeSpellsPerArea();
}
void CSpellWindow::fLcornerb()
{
if(spellSite>0) {
if(currentPage>0)
{
turnPageLeft();
--spellSite;
--currentPage;
}
computeSpellsPerArea();
GH.breakEventHandling();
}
void CSpellWindow::fRcornerb()
{
if((spellSite + 1) < (battleSpellsOnly ? sitesPerTabBattle[selectedTab] : sitesPerTabAdv[selectedTab])) {
if((currentPage + 1) < (pagesWithinCurrentTab()))
{
turnPageRight();
++spellSite;
++currentPage;
}
computeSpellsPerArea();
GH.breakEventHandling();
}
void CSpellWindow::show(SDL_Surface *to)
void CSpellWindow::showAll(SDL_Surface *to)
{
SDL_BlitSurface(background, NULL, to, &pos);
blitAt(spellTab->ourImages[selectedTab].bitmap, 524 + pos.x, 88 + pos.y, to);
@ -423,20 +324,20 @@ void CSpellWindow::show(SDL_Surface *to)
mana<<myHero->mana;
CSDL_Ext::printAtMiddle(mana.str(), pos.x+435, pos.y +426, FONT_SMALL, tytulowy, to);
statusBar->show(to);
statusBar->showAll(to);
//printing school images
if(selectedTab!=4 && spellSite == 0)
if(selectedTab!=4 && currentPage == 0)
{
blitAt(schools->ourImages[selectedTab].bitmap, 117 + pos.x, 74 + pos.y, to);
}
//printing corners
if(spellSite!=0)
if(currentPage!=0)
{
blitAt(leftCorner, lCorner->pos.x, lCorner->pos.y, to);
}
if((spellSite+1) < (battleSpellsOnly ? sitesPerTabBattle[selectedTab] : sitesPerTabAdv[selectedTab]) )
if((currentPage+1) < (pagesWithinCurrentTab()) )
{
blitAt(rightCorner, rCorner->pos.x, rCorner->pos.y, to);
}
@ -444,48 +345,7 @@ void CSpellWindow::show(SDL_Surface *to)
//printing spell info
for(int b=0; b<12; ++b)
{
if(spellAreas[b]->mySpell == -1)
continue;
const CSpell * spell = &CGI->spellh->spells[spellAreas[b]->mySpell];
//int b2 = -1; //TODO use me
blitAt(spells->ourImages[spellAreas[b]->mySpell].bitmap, spellAreas[b]->pos.x, spellAreas[b]->pos.y, to);
Uint8 bestSchool = -1,
bestslvl = myHero->getSpellSchoolLevel( spell );
if(spell->air)
bestSchool = 0;
if(spell->fire)
bestSchool = 1;
if(spell->water)
bestSchool = 2;
if(spell->earth)
bestSchool = 3;
//printing border (indicates level of magic school)
blitAt(schoolBorders[bestSchool]->ourImages[bestslvl].bitmap, spellAreas[b]->pos.x, spellAreas[b]->pos.y, to);
SDL_Color firstLineColor, secondLineColor;
if(myInt->cb->getSpellCost(spell, myHero) > myHero->mana) //hero cannot cast this spell
{
firstLineColor = zwykly;
secondLineColor = darkTitle;
}
else
{
firstLineColor = tytulowy;
secondLineColor = zwykly;
}
//printing spell's name
CSDL_Ext::printAtMiddle(spell->name, spellAreas[b]->pos.x + 39, spellAreas[b]->pos.y + 70, FONT_TINY, firstLineColor, to);
//printing lvl
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[171 + spell->level], spellAreas[b]->pos.x + 39, spellAreas[b]->pos.y + 82, FONT_TINY, secondLineColor, to);
//printing cost
std::ostringstream ss;
ss<<CGI->generaltexth->allTexts[387]<<": "<<myInt->cb->getSpellCost(spell, myHero);
CSDL_Ext::printAtMiddle(ss.str(), spellAreas[b]->pos.x + 39, spellAreas[b]->pos.y + 94, FONT_TINY, secondLineColor, to);
spellAreas[b]->showAll(to);
}
}
@ -541,7 +401,7 @@ void CSpellWindow::computeSpellsPerArea()
{
if(spellsCurSite.size() > 12)
{
spellsCurSite = std::vector<ui32>(spellsCurSite.begin() + spellSite*12, spellsCurSite.end());
spellsCurSite = std::vector<ui32>(spellsCurSite.begin() + currentPage*12, spellsCurSite.end());
if(spellsCurSite.size() > 12)
{
spellsCurSite.erase(spellsCurSite.begin()+12, spellsCurSite.end());
@ -552,13 +412,13 @@ void CSpellWindow::computeSpellsPerArea()
{
if(spellsCurSite.size() > 10)
{
if(spellSite == 0)
if(currentPage == 0)
{
spellsCurSite.erase(spellsCurSite.begin()+10, spellsCurSite.end());
}
else
{
spellsCurSite = std::vector<ui32>(spellsCurSite.begin() + (spellSite-1)*12 + 10, spellsCurSite.end());
spellsCurSite = std::vector<ui32>(spellsCurSite.begin() + (currentPage-1)*12 + 10, spellsCurSite.end());
if(spellsCurSite.size() > 12)
{
spellsCurSite.erase(spellsCurSite.begin()+12, spellsCurSite.end());
@ -567,33 +427,33 @@ void CSpellWindow::computeSpellsPerArea()
}
}
//applying
if(selectedTab == 4 || spellSite != 0)
if(selectedTab == 4 || currentPage != 0)
{
for(size_t c=0; c<12; ++c)
{
if(c<spellsCurSite.size())
{
spellAreas[c]->mySpell = spellsCurSite[c];
spellAreas[c]->setSpell(spellsCurSite[c]);
}
else
{
spellAreas[c]->mySpell = -1;
spellAreas[c]->setSpell(-1);
}
}
}
else
{
spellAreas[0]->mySpell = -1;
spellAreas[1]->mySpell = -1;
spellAreas[0]->setSpell(-1);
spellAreas[1]->setSpell(-1);
for(size_t c=0; c<10; ++c)
{
if(c<spellsCurSite.size())
spellAreas[c+2]->mySpell = spellsCurSite[c];
spellAreas[c+2]->setSpell(spellsCurSite[c]);
else
spellAreas[c+2]->mySpell = -1;
spellAreas[c+2]->setSpell(-1);
}
}
redraw();
}
void CSpellWindow::activate()
@ -610,13 +470,13 @@ void CSpellWindow::activate()
selectSpellsW->activate();
selectSpellsAll->activate();
lCorner->activate();
rCorner->activate();
for(int g=0; g<12; ++g)
{
spellAreas[g]->activate();
}
lCorner->activate();
rCorner->activate();
}
void CSpellWindow::deactivate()
@ -632,14 +492,14 @@ void CSpellWindow::deactivate()
selectSpellsF->deactivate();
selectSpellsW->deactivate();
selectSpellsAll->deactivate();
lCorner->deactivate();
rCorner->deactivate();
for(int g=0; g<12; ++g)
{
spellAreas[g]->deactivate();
}
lCorner->deactivate();
rCorner->deactivate();
}
void CSpellWindow::turnPageLeft()
@ -656,12 +516,62 @@ void CSpellWindow::keyPressed(const SDL_KeyboardEvent & key)
{
if(key.keysym.sym == SDLK_ESCAPE || key.keysym.sym == SDLK_RETURN)
fexitb();
if(key.state == SDL_PRESSED)
{
switch(key.keysym.sym)
{
case SDLK_LEFT:
fLcornerb();
break;
case SDLK_RIGHT:
fRcornerb();
break;
case SDLK_UP:
case SDLK_DOWN:
bool down = key.keysym.sym == SDLK_DOWN;
static const int schoolsOrder[] = {0, 3, 1, 2, 4};
int index = -1;
while(schoolsOrder[++index] != selectedTab);
index += (down ? 1 : -1);
abetw(index, 0, ARRAY_COUNT(schoolsOrder) - 1);
if(selectedTab != schoolsOrder[index])
selectSchool(schoolsOrder[index]);
break;
}
//alt + 1234567890-= casts spell from 1 - 12 slot
if(LOCPLINT->altPressed())
{
SDLKey hlpKey = key.keysym.sym;
if(isNumKey(hlpKey, false))
hlpKey = numToDigit(hlpKey);
static const SDLKey spellSelectors[] = {SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5, SDLK_6, SDLK_7, SDLK_8, SDLK_9, SDLK_0, SDLK_MINUS, SDLK_EQUALS};
int index = -1;
while(++index < ARRAY_COUNT(spellSelectors) && spellSelectors[index] != hlpKey);
if(index >= ARRAY_COUNT(spellSelectors))
return;
//try casting spell
spellAreas[index]->clickLeft(false, true);
}
}
}
Uint8 CSpellWindow::pagesWithinCurrentTab()
{
return battleSpellsOnly ? sitesPerTabBattle[selectedTab] : sitesPerTabAdv[selectedTab];
}
CSpellWindow::SpellArea::SpellArea(SDL_Rect pos, CSpellWindow * owner)
{
this->pos = pos;
this->owner = owner;
used = LCLICK | RCLICK | HOVER;
spellCost = mySpell = whichSchool = schoolLevel = -1;
}
void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
@ -669,9 +579,26 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
if(!down && mySpell!=-1)
{
const CSpell *sp = &CGI->spellh->spells[mySpell];
int spellCost = owner->myInt->cb->getSpellCost(sp, owner->myHero);
if(spellCost > owner->myHero->mana) //insufficient mana
{
char msgBuf[500];
sprintf(msgBuf, CGI->generaltexth->allTexts[206].c_str(), spellCost, owner->myHero->mana);
owner->myInt->showInfoDialog(std::string(msgBuf));
}
//battle spell on adv map or adventure map spell during combat => display infowindow, not cast
if(sp->combatSpell && !owner->myInt->battleInt
|| !sp->combatSpell && owner->myInt->battleInt)
{
std::vector<SComponent*> hlp(1, new SComponent(SComponent::spell, mySpell, 0));
LOCPLINT->showInfoDialog(sp->descriptions[schoolLevel], hlp);
return;
}
//we will cast a spell
if(owner->myInt->battleInt && owner->myInt->cb->battleCanCastSpell() && spellCost <= owner->myHero->mana) //if battle window is open
if(sp->combatSpell && owner->myInt->battleInt && owner->myInt->cb->battleCanCastSpell()) //if battle window is open
{
int spell = mySpell;
owner->fexitb();
@ -679,50 +606,40 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
}
else //adventure spell
{
//insufficient mana
if(spellCost > owner->myHero->mana)
{
char msgBuf[500];
sprintf(msgBuf, CGI->generaltexth->allTexts[206].c_str(), spellCost, owner->myHero->mana);
owner->myInt->showInfoDialog(std::string(msgBuf));
}
else
{
using namespace Spells;
int spell = mySpell;
const CGHeroInstance *h = owner->myHero;
owner->fexitb();
using namespace Spells;
int spell = mySpell;
const CGHeroInstance *h = owner->myHero;
owner->fexitb();
switch(spell)
switch(spell)
{
case SUMMON_BOAT:
{
case SUMMON_BOAT:
int3 pos = h->bestLocation();
if(pos.x < 0)
{
int3 pos = h->bestLocation();
if(pos.x < 0)
{
LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[334]); //There is no place to put the boat.
return;
}
LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[334]); //There is no place to put the boat.
return;
}
break;
case SCUTTLE_BOAT:
case DIMENSION_DOOR:
adventureInt->enterCastingMode(sp);
return;
case VISIONS:
case VIEW_EARTH:
case DISGUISE:
case VIEW_AIR:
case FLY:
case WATER_WALK:
case TOWN_PORTAL:
break;
default:
assert(0);
}
LOCPLINT->cb->castSpell(h, spell);
break;
case SCUTTLE_BOAT:
case DIMENSION_DOOR:
adventureInt->enterCastingMode(sp);
return;
case VISIONS:
case VIEW_EARTH:
case DISGUISE:
case VIEW_AIR:
case FLY:
case WATER_WALK:
case TOWN_PORTAL:
break;
default:
assert(0);
}
LOCPLINT->cb->castSpell(h, spell);
}
}
}
@ -743,7 +660,7 @@ void CSpellWindow::SpellArea::clickRight(tribool down, bool previousState)
SDL_Surface *spellBox = CMessage::drawBoxTextBitmapSub(
owner->myInt->playerID,
CGI->spellh->spells[mySpell].descriptions[0] + dmgInfo, this->owner->spells->ourImages[mySpell].bitmap,
CGI->spellh->spells[mySpell].descriptions[schoolLevel] + dmgInfo, this->owner->spells->ourImages[mySpell].bitmap,
CGI->spellh->spells[mySpell].name,30,30);
CInfoPopup *vinya = new CInfoPopup(spellBox, true);
GH.pushInt(vinya);
@ -768,16 +685,45 @@ void CSpellWindow::SpellArea::hover(bool on)
}
}
void CSpellWindow::SpellArea::activate()
void CSpellWindow::SpellArea::showAll(SDL_Surface *to)
{
activateLClick();
activateRClick();
activateHover();
if(mySpell < 0)
return;
const CSpell * spell = &CGI->spellh->spells[mySpell];
blitAt(owner->spells->ourImages[mySpell].bitmap, pos.x, pos.y, to);
blitAt(owner->schoolBorders[owner->selectedTab >= 4 ? whichSchool : owner->selectedTab]->ourImages[schoolLevel].bitmap, pos.x, pos.y, to); //printing border (indicates level of magic school)
SDL_Color firstLineColor, secondLineColor;
if(spellCost > owner->myHero->mana) //hero cannot cast this spell
{
static const SDL_Color unavailableSpell = {239, 189, 33, 0};
firstLineColor = zwykly;
secondLineColor = unavailableSpell;
}
else
{
firstLineColor = tytulowy;
secondLineColor = zwykly;
}
//printing spell's name
CSDL_Ext::printAtMiddle(spell->name, pos.x + 39, pos.y + 70, FONT_TINY, firstLineColor, to);
//printing lvl
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[171 + spell->level], pos.x + 39, pos.y + 82, FONT_TINY, secondLineColor, to);
//printing cost
std::ostringstream ss;
ss << CGI->generaltexth->allTexts[387] << ": " << spellCost;
CSDL_Ext::printAtMiddle(ss.str(), pos.x + 39, pos.y + 94, FONT_TINY, secondLineColor, to);
}
void CSpellWindow::SpellArea::deactivate()
void CSpellWindow::SpellArea::setSpell(int spellID)
{
deactivateLClick();
deactivateRClick();
deactivateHover();
}
mySpell = spellID;
if(mySpell < 0)
return;
const CSpell * spell = &CGI->spellh->spells[mySpell];
schoolLevel = owner->myHero->getSpellSchoolLevel(spell, &whichSchool);
spellCost = owner->myInt->cb->getSpellCost(spell, owner->myHero);
}

View File

@ -34,8 +34,6 @@ public:
void clickLeft(tribool down, bool previousState);
void clickRight(tribool down, bool previousState);
void hover(bool on);
void activate();
void deactivate();
SpellbookInteractiveArea(const SDL_Rect & myRect, boost::function<void()> funcL, const std::string & textR,
boost::function<void()> funcHon, boost::function<void()> funcHoff, CPlayerInterface * _myInt);//c-tor
@ -48,14 +46,19 @@ private:
{
public:
int mySpell;
int schoolLevel; //range: 0 none, 3 - expert
int whichSchool; //0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic,
int spellCost;
CSpellWindow * owner;
SpellArea(SDL_Rect pos, CSpellWindow * owner);
void setSpell(int spellID);
void clickLeft(tribool down, bool previousState);
void clickRight(tribool down, bool previousState);
void hover(bool on);
void activate();
void deactivate();
void showAll(SDL_Surface *to);
};
SDL_Surface * background, * leftCorner, * rightCorner;
@ -75,9 +78,8 @@ private:
bool battleSpellsOnly; //if true, only battle spells are displayed; if false, only adventure map spells are displayed
Uint8 selectedTab; // 0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic, 4 - all schools
Uint8 spellSite; //changes when corners are clicked
Uint8 currentPage; //changes when corners are clicked
std::set<ui32> mySpells; //all spels in this spellbook
Uint8 schoolLvls[4]; //levels of magic for different schools: [0]: air, [1]: fire, [2]: water, [3]: earth; 0 - none, 1 - beginner, 2 - medium, 3 - expert
const CGHeroInstance * myHero; //hero whose spells are presented
@ -98,19 +100,15 @@ public:
void fbattleSpellsb();
void fmanaPtsb();
void fspellsAb();
void fspellsEb();
void fspellsFb();
void fspellsWb();
void fspellsAllb();
void fLcornerb();
void fRcornerb();
void selectSchool(int school); //schools: 0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic, 4 - all schools
Uint8 pagesWithinCurrentTab();
void keyPressed(const SDL_KeyboardEvent & key);
void activate();
void deactivate();
void show(SDL_Surface * to);
void showAll(SDL_Surface * to);
};
#endif // __CSPELLWINDOW_H__

View File

@ -362,6 +362,11 @@ CGuiHandler::~CGuiHandler()
}
void CGuiHandler::breakEventHandling()
{
current = NULL;
}
void CIntObject::activateLClick()
{
GH.lclickable.push_front(this);
@ -931,7 +936,28 @@ SDLKey arrowToNum( SDLKey key )
SDLKey numToDigit( SDLKey key )
{
return SDLKey(key - SDLK_KP0 + SDLK_0);
if(key >= SDLK_KP0 && key <= SDLK_KP9)
return SDLKey(key - SDLK_KP0 + SDLK_0);
#define REMOVE_KP(keyName) case SDLK_KP_ ## keyName ## : return SDLK_ ## keyName;
switch(key)
{
REMOVE_KP(PERIOD)
REMOVE_KP(MINUS)
REMOVE_KP(PLUS)
REMOVE_KP(EQUALS)
case SDLK_KP_MULTIPLY:
return SDLK_ASTERISK;
case SDLK_KP_DIVIDE:
return SDLK_SLASH;
case SDLK_KP_ENTER:
return SDLK_RETURN;
default:
tlog3 << "Illegal numkey conversion!" << std::endl;
return SDLK_UNKNOWN;
}
#undef REMOVE_KP
}
bool isNumKey( SDLKey key, bool number )

View File

@ -509,6 +509,7 @@ public:
void handleMouseMotion(SDL_Event *sEvent);
void handleMoveInterested( const SDL_MouseMotionEvent & motion );
void fakeMouseMove();
void breakEventHandling(); //current event won't be propagated anymore
ui8 defActionsDef; //default auto actions
ui8 captureChildren; //all newly created objects will get their parents from stack and will be added to parents children list
std::list<CIntObject *> createdObj; //stack of objs being created

View File

@ -632,6 +632,7 @@ CInfoWindow::CInfoWindow(std::string Text, int player, int charperline, const st
{
comps[i]->recActions = 0xff;
addChild(comps[i]);
comps[i]->recActions &= ~(SHOWALL | UPDATE);
components.push_back(comps[i]);
}
setDelComps(delComps);
@ -1168,7 +1169,7 @@ void CStatusBar::clear()
if(LOCPLINT->cingconsole->enteredText == "") //for appropriate support for in-game console
{
current="";
show(screen);
redraw();
}
}
@ -1177,7 +1178,7 @@ void CStatusBar::print(const std::string & text)
if(LOCPLINT->cingconsole->enteredText == "" || text == LOCPLINT->cingconsole->enteredText) //for appropriate support for in-game console
{
current=text;
show(GH.topInt()==adventureInt ? screen : screen2); //if there are now windows opened, update statusbar on screen, else to cache surface
redraw();
}
}
@ -6206,7 +6207,7 @@ void CTextInput::keyPressed( const SDL_KeyboardEvent & key )
if(key.keysym.sym == SDLK_TAB)
{
moveFocus();
GH.current = NULL;
GH.breakEventHandling();
return;
}

View File

@ -1221,30 +1221,31 @@ int CGHeroInstance::getTotalStrength() const
return (int) ret;
}
ui8 CGHeroInstance::getSpellSchoolLevel(const CSpell * spell) const
ui8 CGHeroInstance::getSpellSchoolLevel(const CSpell * spell, int *outSelectedSchool) const
{
ui8 skill = 0; //skill level
si16 skill = -1; //skill level
if(spell->fire)
skill = std::max(skill,getSecSkillLevel(14));
if(spell->air)
skill = std::max(skill,getSecSkillLevel(15));
if(spell->water)
skill = std::max(skill,getSecSkillLevel(16));
if(spell->earth)
skill = std::max(skill,getSecSkillLevel(17));
#define TRY_SCHOOL(schoolName, schoolMechanicsId, schoolOutId) \
if(spell-> ## schoolName) \
{ \
int thisSchool = std::max<int>(getSecSkillLevel(14 + (schoolMechanicsId)), valOfBonuses(Bonus::MAGIC_SCHOOL_SKILL, 1 << (schoolMechanicsId))); \
if(thisSchool > skill) \
{ \
skill = thisSchool; \
if(outSelectedSchool) \
*outSelectedSchool = schoolOutId; \
} \
}
TRY_SCHOOL(fire, 0, 1)
TRY_SCHOOL(air, 1, 0)
TRY_SCHOOL(water, 2, 2)
TRY_SCHOOL(earth, 3, 3)
#undef TRY_SCHOOL;
//bonuses (eg. from special terrains)
skill = std::max<ui8>(skill, valOfBonuses(Bonus::MAGIC_SCHOOL_SKILL, 0)); //any school bonus
if(spell->fire)
skill = std::max<ui8>(skill, valOfBonuses(Bonus::MAGIC_SCHOOL_SKILL, 1));
if(spell->air)
skill = std::max<ui8>(skill, valOfBonuses(Bonus::MAGIC_SCHOOL_SKILL, 2));
if(spell->water)
skill = std::max<ui8>(skill, valOfBonuses(Bonus::MAGIC_SCHOOL_SKILL, 4));
if(spell->earth)
skill = std::max<ui8>(skill, valOfBonuses(Bonus::MAGIC_SCHOOL_SKILL, 8));
amax(skill, valOfBonuses(Bonus::MAGIC_SCHOOL_SKILL, 0)); //any school bonus
assert(skill >= 0 && skill <= 3);
return skill;
}

View File

@ -366,7 +366,7 @@ public:
static int3 convertPosition(int3 src, bool toh3m); //toh3m=true: manifest->h3m; toh3m=false: h3m->manifest
double getHeroStrength() const;
int getTotalStrength() const;
ui8 getSpellSchoolLevel(const CSpell * spell) const; //returns level on which given spell would be cast by this hero (0 - none, 1 - basic etc)
ui8 getSpellSchoolLevel(const CSpell * spell, int *outSelectedSchool = NULL) const; //returns level on which given spell would be cast by this hero (0 - none, 1 - basic etc); optionally returns number of selected school by arg - 0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic,
bool canCastThisSpell(const CSpell * spell) const; //determines if this hero can cast given spell; takes into account existing spell in spellbook, existing spellbook and artifact bonuses
CStackInstance calculateNecromancy (const BattleResult &battleResult) const;
void showNecromancyDialog(const CStackInstance &raisedStack) const;