mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-26 08:41:13 +02:00
use only CSpell in CSpellWindow
This commit is contained in:
parent
63cbf960df
commit
2eb61533fa
@ -74,6 +74,29 @@ void CSpellWindow::InteractiveArea::hover(bool on)
|
||||
owner->statusBar->clear();
|
||||
}
|
||||
|
||||
class SpellbookSpellSorter
|
||||
{
|
||||
public:
|
||||
bool operator()(const CSpell * A, const CSpell * B)
|
||||
{
|
||||
if(A->level < B->level)
|
||||
return true;
|
||||
if(A->level > B->level)
|
||||
return false;
|
||||
|
||||
|
||||
for(ui8 schoolId = 0; schoolId < 4; schoolId++)
|
||||
{
|
||||
if(A->school.at((ESpellSchool)schoolId) && !B->school.at((ESpellSchool)schoolId))
|
||||
return true;
|
||||
if(!A->school.at((ESpellSchool)schoolId) && B->school.at((ESpellSchool)schoolId))
|
||||
return false;
|
||||
}
|
||||
|
||||
return A->name < B->name;
|
||||
}
|
||||
} spellsorter;
|
||||
|
||||
CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _myInt, bool openOnBattleSpells):
|
||||
CWindowObject(PLAYER_COLORED, "SpelBack"),
|
||||
battleSpellsOnly(openOnBattleSpells),
|
||||
@ -83,11 +106,13 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
|
||||
myInt(_myInt)
|
||||
{
|
||||
//initializing castable spells
|
||||
for(const auto & spell : CGI->spellh->objects)
|
||||
mySpells.reserve(CGI->spellh->objects.size());
|
||||
for(const CSpell * spell : CGI->spellh->objects)
|
||||
{
|
||||
if(!spell->isCreatureAbility() && myHero->canCastThisSpell(spell.get()))
|
||||
mySpells.insert(spell->id);
|
||||
if(!spell->isCreatureAbility() && myHero->canCastThisSpell(spell))
|
||||
mySpells.push_back(spell);
|
||||
}
|
||||
std::sort(mySpells.begin(), mySpells.end(), spellsorter);
|
||||
|
||||
//initializing sizes of spellbook's parts
|
||||
for(auto & elem : sitesPerTabAdv)
|
||||
@ -95,9 +120,8 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
|
||||
for(auto & elem : sitesPerTabBattle)
|
||||
elem = 0;
|
||||
|
||||
for(const auto & g : mySpells)
|
||||
for(const auto spell : mySpells)
|
||||
{
|
||||
const CSpell * spell = g.toSpell();
|
||||
int * sitesPerOurTab = spell->isCombatSpell() ? sitesPerTabBattle : sitesPerTabAdv;
|
||||
|
||||
++sitesPerOurTab[4];
|
||||
@ -361,51 +385,25 @@ void CSpellWindow::show(SDL_Surface * to)
|
||||
statusBar->show(to);
|
||||
}
|
||||
|
||||
class SpellbookSpellSorter
|
||||
{
|
||||
public:
|
||||
bool operator()(const SpellID & a, const SpellID & b)
|
||||
{
|
||||
const CSpell & A = *(a.toSpell());
|
||||
const CSpell & B = *(b.toSpell());
|
||||
if(A.level<B.level)
|
||||
return true;
|
||||
if(A.level>B.level)
|
||||
return false;
|
||||
|
||||
|
||||
for(ui8 schoolId = 0; schoolId < 4; schoolId++)
|
||||
{
|
||||
if(A.school.at((ESpellSchool)schoolId) && !B.school.at((ESpellSchool)schoolId))
|
||||
return true;
|
||||
if(!A.school.at((ESpellSchool)schoolId) && B.school.at((ESpellSchool)schoolId))
|
||||
return false;
|
||||
}
|
||||
|
||||
return A.name < B.name;
|
||||
}
|
||||
} spellsorter;
|
||||
|
||||
void CSpellWindow::computeSpellsPerArea()
|
||||
{
|
||||
std::vector<SpellID> spellsCurSite;
|
||||
for(const SpellID & spellID : mySpells)
|
||||
std::vector<const CSpell *> spellsCurSite;
|
||||
spellsCurSite.reserve(mySpells.size());
|
||||
for(const CSpell * spell : mySpells)
|
||||
{
|
||||
const CSpell * s = spellID.toSpell();
|
||||
|
||||
if(s->combatSpell ^ !battleSpellsOnly
|
||||
&& ((selectedTab == 4) || s->school.at((ESpellSchool)selectedTab))
|
||||
if(spell->combatSpell ^ !battleSpellsOnly
|
||||
&& ((selectedTab == 4) || spell->school.at((ESpellSchool)selectedTab))
|
||||
)
|
||||
{
|
||||
spellsCurSite.push_back(spellID);
|
||||
spellsCurSite.push_back(spell);
|
||||
}
|
||||
}
|
||||
std::sort(spellsCurSite.begin(), spellsCurSite.end(), spellsorter);
|
||||
|
||||
if(selectedTab == 4)
|
||||
{
|
||||
if(spellsCurSite.size() > 12)
|
||||
{
|
||||
spellsCurSite = std::vector<SpellID>(spellsCurSite.begin() + currentPage*12, spellsCurSite.end());
|
||||
spellsCurSite = std::vector<const CSpell *>(spellsCurSite.begin() + currentPage*12, spellsCurSite.end());
|
||||
if(spellsCurSite.size() > 12)
|
||||
{
|
||||
spellsCurSite.erase(spellsCurSite.begin()+12, spellsCurSite.end());
|
||||
@ -422,7 +420,7 @@ void CSpellWindow::computeSpellsPerArea()
|
||||
}
|
||||
else
|
||||
{
|
||||
spellsCurSite = std::vector<SpellID>(spellsCurSite.begin() + (currentPage-1)*12 + 10, spellsCurSite.end());
|
||||
spellsCurSite = std::vector<const CSpell *>(spellsCurSite.begin() + (currentPage-1)*12 + 10, spellsCurSite.end());
|
||||
if(spellsCurSite.size() > 12)
|
||||
{
|
||||
spellsCurSite.erase(spellsCurSite.begin()+12, spellsCurSite.end());
|
||||
@ -435,26 +433,26 @@ void CSpellWindow::computeSpellsPerArea()
|
||||
{
|
||||
for(size_t c=0; c<12; ++c)
|
||||
{
|
||||
if(c<spellsCurSite.size())
|
||||
if(c < spellsCurSite.size())
|
||||
{
|
||||
spellAreas[c]->setSpell(spellsCurSite[c]);
|
||||
}
|
||||
else
|
||||
{
|
||||
spellAreas[c]->setSpell(SpellID::NONE);
|
||||
spellAreas[c]->setSpell(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
spellAreas[0]->setSpell(SpellID::NONE);
|
||||
spellAreas[1]->setSpell(SpellID::NONE);
|
||||
spellAreas[0]->setSpell(nullptr);
|
||||
spellAreas[1]->setSpell(nullptr);
|
||||
for(size_t c=0; c<10; ++c)
|
||||
{
|
||||
if(c<spellsCurSite.size())
|
||||
if(c < spellsCurSite.size())
|
||||
spellAreas[c+2]->setSpell(spellsCurSite[c]);
|
||||
else
|
||||
spellAreas[c+2]->setSpell(SpellID::NONE);
|
||||
spellAreas[c+2]->setSpell(nullptr);
|
||||
}
|
||||
}
|
||||
redraw();
|
||||
@ -596,39 +594,37 @@ CSpellWindow::SpellArea::SpellArea(SDL_Rect pos, CSpellWindow * owner)
|
||||
addUsedEvents(LCLICK | RCLICK | HOVER);
|
||||
|
||||
spellCost = whichSchool = schoolLevel = -1;
|
||||
mySpell = SpellID::NONE;
|
||||
mySpell = nullptr;
|
||||
}
|
||||
|
||||
void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
if(!down && mySpell != SpellID::NONE)
|
||||
if(!down && mySpell)
|
||||
{
|
||||
const CSpell * sp = mySpell.toSpell();
|
||||
|
||||
int spellCost = owner->myInt->cb->getSpellCost(sp, owner->myHero);
|
||||
int spellCost = owner->myInt->cb->getSpellCost(mySpell, owner->myHero);
|
||||
if(spellCost > owner->myHero->mana) //insufficient mana
|
||||
{
|
||||
owner->myInt->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[206]) % spellCost % owner->myHero->mana));
|
||||
return;
|
||||
}
|
||||
//battle spell on adv map or adventure map spell during combat => display infowindow, not cast
|
||||
if((sp->isCombatSpell() && !owner->myInt->battleInt)
|
||||
|| (sp->isAdventureSpell() && (owner->myInt->battleInt || owner->myInt->castleInt)))
|
||||
if((mySpell->isCombatSpell() && !owner->myInt->battleInt)
|
||||
|| (mySpell->isAdventureSpell() && (owner->myInt->battleInt || owner->myInt->castleInt)))
|
||||
{
|
||||
std::vector<CComponent*> hlp(1, new CComponent(CComponent::spell, mySpell, 0));
|
||||
LOCPLINT->showInfoDialog(sp->getLevelInfo(schoolLevel).description, hlp);
|
||||
std::vector<CComponent*> hlp(1, new CComponent(CComponent::spell, mySpell->id, 0));
|
||||
LOCPLINT->showInfoDialog(mySpell->getLevelInfo(schoolLevel).description, hlp);
|
||||
return;
|
||||
}
|
||||
|
||||
//we will cast a spell
|
||||
if(sp->combatSpell && owner->myInt->battleInt && owner->myInt->cb->battleCanCastSpell()) //if battle window is open
|
||||
if(mySpell->combatSpell && owner->myInt->battleInt && owner->myInt->cb->battleCanCastSpell()) //if battle window is open
|
||||
{
|
||||
ESpellCastProblem::ESpellCastProblem problem = owner->myInt->cb->battleCanCastThisSpell(sp);
|
||||
ESpellCastProblem::ESpellCastProblem problem = owner->myInt->cb->battleCanCastThisSpell(mySpell);
|
||||
switch (problem)
|
||||
{
|
||||
case ESpellCastProblem::OK:
|
||||
{
|
||||
owner->myInt->battleInt->castThisSpell(mySpell);
|
||||
owner->myInt->battleInt->castThisSpell(mySpell->id);
|
||||
owner->fexitb();
|
||||
return;
|
||||
}
|
||||
@ -703,7 +699,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(sp->isAdventureSpell() && !owner->myInt->battleInt) //adventure spell and not in battle
|
||||
else if(mySpell->isAdventureSpell() && !owner->myInt->battleInt) //adventure spell and not in battle
|
||||
{
|
||||
const CGHeroInstance *h = owner->myHero;
|
||||
GH.popInt(owner);
|
||||
@ -715,7 +711,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
|
||||
delete owner;
|
||||
});
|
||||
|
||||
if(mySpell == SpellID::TOWN_PORTAL)
|
||||
if(mySpell->id == SpellID::TOWN_PORTAL)
|
||||
{
|
||||
//special case
|
||||
//todo: move to mechanics
|
||||
@ -735,7 +731,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
|
||||
return;
|
||||
}
|
||||
|
||||
const int movementCost = (h->getSpellSchoolLevel(sp) >= 3) ? 200 : 300;
|
||||
const int movementCost = (h->getSpellSchoolLevel(mySpell) >= 3) ? 200 : 300;
|
||||
|
||||
if(h->movement < movementCost)
|
||||
{
|
||||
@ -743,7 +739,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
|
||||
return;
|
||||
}
|
||||
|
||||
if (h->getSpellSchoolLevel(sp) < 2) //not advanced or expert - teleport to nearest available city
|
||||
if (h->getSpellSchoolLevel(mySpell) < 2) //not advanced or expert - teleport to nearest available city
|
||||
{
|
||||
auto nearest = Towns.cbegin(); //nearest town's iterator
|
||||
si32 dist = LOCPLINT->cb->getTown((*nearest)->id)->pos.dist2dSQ(h->pos);
|
||||
@ -765,7 +761,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
|
||||
else
|
||||
{
|
||||
const CGTownInstance * town = LOCPLINT->cb->getTown((*nearest)->id);
|
||||
LOCPLINT->cb->castSpell(h, mySpell, town->visitablePos());// - town->getVisitableOffset());
|
||||
LOCPLINT->cb->castSpell(h, mySpell->id, town->visitablePos());// - town->getVisitableOffset());
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -789,14 +785,14 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
|
||||
LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[124]);
|
||||
else
|
||||
GH.pushInt (new CObjectListWindow(availableTowns,
|
||||
new CAnimImage("SPELLSCR",mySpell),
|
||||
new CAnimImage("SPELLSCR",mySpell->id),
|
||||
CGI->generaltexth->jktexts[40], CGI->generaltexth->jktexts[41],
|
||||
castTownPortal));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(mySpell == SpellID::SUMMON_BOAT)
|
||||
if(mySpell->id == SpellID::SUMMON_BOAT)
|
||||
{
|
||||
//special case
|
||||
//todo: move to mechanics
|
||||
@ -808,13 +804,13 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
|
||||
}
|
||||
}
|
||||
|
||||
if(sp->getTargetType() == CSpell::LOCATION)
|
||||
if(mySpell->getTargetType() == CSpell::LOCATION)
|
||||
{
|
||||
adventureInt->enterCastingMode(sp);
|
||||
adventureInt->enterCastingMode(mySpell);
|
||||
}
|
||||
else if(sp->getTargetType() == CSpell::NO_TARGET)
|
||||
else if(mySpell->getTargetType() == CSpell::NO_TARGET)
|
||||
{
|
||||
LOCPLINT->cb->castSpell(h, mySpell);
|
||||
LOCPLINT->cb->castSpell(h, mySpell->id);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -826,12 +822,11 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
|
||||
|
||||
void CSpellWindow::SpellArea::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
if(down && mySpell != -1)
|
||||
if(down && mySpell)
|
||||
{
|
||||
std::string dmgInfo;
|
||||
const CGHeroInstance * hero = owner->myHero;
|
||||
int causedDmg = owner->myInt->cb->estimateSpellDamage( CGI->spellh->objects[mySpell], (hero ? hero : nullptr));
|
||||
if(causedDmg == 0 || mySpell == SpellID::TITANS_LIGHTNING_BOLT) //Titan's Lightning Bolt already has damage info included
|
||||
int causedDmg = owner->myInt->cb->estimateSpellDamage(mySpell, owner->myHero);
|
||||
if(causedDmg == 0 || mySpell->id == SpellID::TITANS_LIGHTNING_BOLT) //Titan's Lightning Bolt already has damage info included
|
||||
dmgInfo = "";
|
||||
else
|
||||
{
|
||||
@ -839,43 +834,35 @@ void CSpellWindow::SpellArea::clickRight(tribool down, bool previousState)
|
||||
boost::algorithm::replace_first(dmgInfo, "%d", boost::lexical_cast<std::string>(causedDmg));
|
||||
}
|
||||
|
||||
CRClickPopup::createAndPush(CGI->spellh->objects[mySpell]->getLevelInfo(schoolLevel).description + dmgInfo,
|
||||
new CComponent(CComponent::spell, mySpell));
|
||||
CRClickPopup::createAndPush(mySpell->getLevelInfo(schoolLevel).description + dmgInfo,
|
||||
new CComponent(CComponent::spell, mySpell->id));
|
||||
}
|
||||
}
|
||||
|
||||
void CSpellWindow::SpellArea::hover(bool on)
|
||||
{
|
||||
//Hoverable::hover(on);
|
||||
if(mySpell != -1)
|
||||
if(mySpell)
|
||||
{
|
||||
if(on)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss<<CGI->spellh->objects[mySpell]->name<<" ("<<CGI->generaltexth->allTexts[171+CGI->spellh->objects[mySpell]->level]<<")";
|
||||
owner->statusBar->setText(ss.str());
|
||||
}
|
||||
owner->statusBar->setText(boost::to_string(boost::format("%s (%s)") % mySpell->name % CGI->generaltexth->allTexts[171+mySpell->level]));
|
||||
else
|
||||
{
|
||||
owner->statusBar->clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSpellWindow::SpellArea::showAll(SDL_Surface * to)
|
||||
{
|
||||
if(mySpell < 0)
|
||||
if(!mySpell)
|
||||
return;
|
||||
|
||||
const CSpell * spell = mySpell.toSpell();
|
||||
owner->spells->load(mySpell);
|
||||
owner->spells->load(mySpell->id);
|
||||
|
||||
IImage * icon = owner->spells->getImage(mySpell,0,false);
|
||||
IImage * icon = owner->spells->getImage(mySpell->id,0,false);
|
||||
|
||||
if(icon != nullptr)
|
||||
icon->draw(to, pos.x, pos.y);
|
||||
else
|
||||
logGlobal->errorStream() << __FUNCTION__ << ": failed to load spell icon for spell with id " << mySpell;
|
||||
logGlobal->errorStream() << __FUNCTION__ << ": failed to load icon for spell " << mySpell->name;
|
||||
|
||||
blitAt(owner->schoolBorders[owner->selectedTab >= 4 ? whichSchool : owner->selectedTab]->ourImages[schoolLevel].bitmap, pos.x, pos.y, to); //printing border (indicates level of magic school)
|
||||
|
||||
@ -892,30 +879,29 @@ void CSpellWindow::SpellArea::showAll(SDL_Surface * to)
|
||||
secondLineColor = Colors::WHITE;
|
||||
}
|
||||
//printing spell's name
|
||||
printAtMiddleLoc(spell->name, 39, 70, FONT_TINY, firstLineColor, to);
|
||||
printAtMiddleLoc(mySpell->name, 39, 70, FONT_TINY, firstLineColor, to);
|
||||
//printing lvl
|
||||
if(schoolLevel > 0)
|
||||
{
|
||||
boost::format fmt("%s/%s");
|
||||
fmt % CGI->generaltexth->allTexts[171 + spell->level];
|
||||
fmt % CGI->generaltexth->allTexts[171 + mySpell->level];
|
||||
fmt % CGI->generaltexth->levels.at(3+(schoolLevel-1));//lines 4-6
|
||||
printAtMiddleLoc(fmt.str(), 39, 82, FONT_TINY, secondLineColor, to);
|
||||
}
|
||||
else
|
||||
printAtMiddleLoc(CGI->generaltexth->allTexts[171 + spell->level], 39, 82, FONT_TINY, secondLineColor, to);
|
||||
printAtMiddleLoc(CGI->generaltexth->allTexts[171 + mySpell->level], 39, 82, FONT_TINY, secondLineColor, to);
|
||||
//printing cost
|
||||
std::ostringstream ss;
|
||||
ss << CGI->generaltexth->allTexts[387] << ": " << spellCost;
|
||||
printAtMiddleLoc(ss.str(), 39, 94, FONT_TINY, secondLineColor, to);
|
||||
}
|
||||
|
||||
void CSpellWindow::SpellArea::setSpell(SpellID spellID)
|
||||
void CSpellWindow::SpellArea::setSpell(const CSpell * spell)
|
||||
{
|
||||
mySpell = spellID;
|
||||
if(mySpell < 0)
|
||||
return;
|
||||
|
||||
const CSpell * spell = CGI->spellh->objects[mySpell];
|
||||
schoolLevel = owner->myHero->getSpellSchoolLevel(spell, &whichSchool);
|
||||
spellCost = owner->myInt->cb->getSpellCost(spell, owner->myHero);
|
||||
mySpell = spell;
|
||||
if(mySpell)
|
||||
{
|
||||
schoolLevel = owner->myHero->getSpellSchoolLevel(mySpell, &whichSchool);
|
||||
spellCost = owner->myInt->cb->getSpellCost(mySpell, owner->myHero);
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ class CGHeroInstance;
|
||||
class CGStatusBar;
|
||||
class CPlayerInterface;
|
||||
class CSpellWindow;
|
||||
class CSpell;
|
||||
|
||||
/// The spell window
|
||||
class CSpellWindow : public CWindowObject
|
||||
@ -27,7 +28,7 @@ private:
|
||||
class SpellArea : public CIntObject
|
||||
{
|
||||
public:
|
||||
SpellID mySpell;
|
||||
const CSpell * mySpell;
|
||||
int schoolLevel; //range: 0 none, 3 - expert
|
||||
int whichSchool; //0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic,
|
||||
int spellCost;
|
||||
@ -35,7 +36,7 @@ private:
|
||||
|
||||
SpellArea(SDL_Rect pos, CSpellWindow * owner);
|
||||
|
||||
void setSpell(SpellID spellID);
|
||||
void setSpell(const CSpell * spell);
|
||||
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
@ -79,7 +80,7 @@ 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
|
||||
int currentPage; //changes when corners are clicked
|
||||
std::set<SpellID> mySpells; //all spels in this spellbook
|
||||
std::vector<const CSpell *> mySpells; //all spels in this spellbook
|
||||
|
||||
const CGHeroInstance * myHero; //hero whose spells are presented
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user