1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-26 22:57:00 +02:00
vcmi/CBattleInterface.cpp
Michał W. Urbańczyk 985b4930e4 Major changes to the GUI. Introduced list of interfaces (listInt) containing pointers to all shown interfaces / windows. Only top layer is active and regularly updated.
Windows should be shown using pushInt and closed with popInt or PopIntTotally (if interface needs to be also deleted).
Some things are not working yet properly, I'll try to fix them ASAP.
2009-04-14 12:47:09 +00:00

2863 lines
90 KiB
C++

#include "CBattleInterface.h"
#include "CGameInfo.h"
#include "hch/CLodHandler.h"
#include "SDL_Extensions.h"
#include "CAdvmapInterface.h"
#include "AdventureMapButton.h"
#include "hch/CObjectHandler.h"
#include "hch/CHeroHandler.h"
#include "hch/CDefHandler.h"
#include "hch/CSpellHandler.h"
#include "CMessage.h"
#include "CCursorHandler.h"
#include "CCallback.h"
#include "CGameState.h"
#include "hch/CGeneralTextHandler.h"
#include "client/CCreatureAnimation.h"
#include "client/Graphics.h"
#include "client/CSpellWindow.h"
#include "client/CConfigHandler.h"
#include <queue>
#include <sstream>
#include "lib/CondSh.h"
#include "lib/NetPacks.h"
#include <boost/assign/list_of.hpp>
#ifndef __GNUC__
const double M_PI = 3.14159265358979323846;
#else
#define _USE_MATH_DEFINES
#include <cmath>
#endif
extern SDL_Surface * screen;
extern TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM, *GEOR16;
extern SDL_Color zwykly;
BattleSettings CBattleInterface::settings;
struct CMP_stack2
{
inline bool operator ()(const CStack& a, const CStack& b)
{
return (a.Speed())>(b.Speed());
}
} cmpst2 ;
CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, const SDL_Rect & myRect)
: attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), activeStack(-1), givenCommand(NULL),
attackingInfo(NULL), myTurn(false), resWindow(NULL), showStackQueue(false),
spellDestSelectMode(false), spellToCast(NULL), previouslyHoveredHex(-1), moveStarted(false), mouseHoveredStack(-1)
{
pos = myRect;
strongInterest = true;
givenCommand = new CondSh<BattleAction *>(NULL);
//initializing armies
this->army1 = army1;
this->army2 = army2;
std::map<int, CStack> stacks = LOCPLINT->cb->battleGetStacks();
for(std::map<int, CStack>::iterator b=stacks.begin(); b!=stacks.end(); ++b)
{
std::pair <int, int> coords = CBattleHex::getXYUnitAnim(b->second.position, b->second.owner == attackingHeroInstance->tempOwner, b->second.creature);
creAnims[b->second.ID] = (new CCreatureAnimation(b->second.creature->animDefName));
creAnims[b->second.ID]->setType(2);
creAnims[b->second.ID]->pos = genRect(creAnims[b->second.ID]->fullHeight, creAnims[b->second.ID]->fullWidth, coords.first, coords.second);
creDir[b->second.ID] = b->second.owner==attackingHeroInstance->tempOwner;
}
//preparing menu background and terrain
std::vector< std::string > & backref = graphics->battleBacks[ LOCPLINT->cb->battleGetBattlefieldType() ];
background = BitmapHandler::loadBitmap(backref[ rand() % backref.size()] );
menu = BitmapHandler::loadBitmap("CBAR.BMP");
graphics->blueToPlayersAdv(menu, hero1->tempOwner);
//preparing graphics for displaying amounts of creatures
amountNormal = BitmapHandler::loadBitmap("CMNUMWIN.BMP");
CSDL_Ext::alphaTransform(amountNormal);
for(int g=0; g<amountNormal->format->palette->ncolors; ++g)
{
if((amountNormal->format->palette->colors+g)->b != 132 &&
(amountNormal->format->palette->colors+g)->g != 231 &&
(amountNormal->format->palette->colors+g)->r != 255) //it's not yellow border
{
(amountNormal->format->palette->colors+g)->r = (float)((amountNormal->format->palette->colors+g)->r) * 0.54f;
(amountNormal->format->palette->colors+g)->g = (float)((amountNormal->format->palette->colors+g)->g) * 0.19f;
(amountNormal->format->palette->colors+g)->b = (float)((amountNormal->format->palette->colors+g)->b) * 0.93f;
}
}
amountPositive = BitmapHandler::loadBitmap("CMNUMWIN.BMP");
CSDL_Ext::alphaTransform(amountPositive);
for(int g=0; g<amountPositive->format->palette->ncolors; ++g)
{
if((amountPositive->format->palette->colors+g)->b != 132 &&
(amountPositive->format->palette->colors+g)->g != 231 &&
(amountPositive->format->palette->colors+g)->r != 255) //it's not yellow border
{
(amountPositive->format->palette->colors+g)->r = (float)((amountPositive->format->palette->colors+g)->r) * 0.18f;
(amountPositive->format->palette->colors+g)->g = (float)((amountPositive->format->palette->colors+g)->g) * 1.00f;
(amountPositive->format->palette->colors+g)->b = (float)((amountPositive->format->palette->colors+g)->b) * 0.18f;
}
}
amountNegative = BitmapHandler::loadBitmap("CMNUMWIN.BMP");
CSDL_Ext::alphaTransform(amountNegative);
for(int g=0; g<amountNegative->format->palette->ncolors; ++g)
{
if((amountNegative->format->palette->colors+g)->b != 132 &&
(amountNegative->format->palette->colors+g)->g != 231 &&
(amountNegative->format->palette->colors+g)->r != 255) //it's not yellow border
{
(amountNegative->format->palette->colors+g)->r = (float)((amountNegative->format->palette->colors+g)->r) * 1.00f;
(amountNegative->format->palette->colors+g)->g = (float)((amountNegative->format->palette->colors+g)->g) * 0.18f;
(amountNegative->format->palette->colors+g)->b = (float)((amountNegative->format->palette->colors+g)->b) * 0.18f;
}
}
amountEffNeutral = BitmapHandler::loadBitmap("CMNUMWIN.BMP");
CSDL_Ext::alphaTransform(amountNegative);
for(int g=0; g<amountNegative->format->palette->ncolors; ++g)
{
if((amountNegative->format->palette->colors+g)->b != 132 &&
(amountNegative->format->palette->colors+g)->g != 231 &&
(amountNegative->format->palette->colors+g)->r != 255) //it's not yellow border
{
(amountNegative->format->palette->colors+g)->r = (float)((amountNegative->format->palette->colors+g)->r) * 1.00f;
(amountNegative->format->palette->colors+g)->g = (float)((amountNegative->format->palette->colors+g)->g) * 1.00f;
(amountNegative->format->palette->colors+g)->b = (float)((amountNegative->format->palette->colors+g)->b) * 0.18f;
}
}
////blitting menu background and terrain
blitAt(background, pos.x, pos.y);
blitAt(menu, pos.x, 556 + pos.y);
CSDL_Ext::update();
//preparing buttons and console
bOptions = new AdventureMapButton (CGI->generaltexth->zelp[381].first, CGI->generaltexth->zelp[381].second, boost::bind(&CBattleInterface::bOptionsf,this), 3 + pos.x, 561 + pos.y, "icm003.def", SDLK_o);
bSurrender = new AdventureMapButton (CGI->generaltexth->zelp[379].first, CGI->generaltexth->zelp[379].second, boost::bind(&CBattleInterface::bSurrenderf,this), 54 + pos.x, 561 + pos.y, "icm001.def", SDLK_s);
bFlee = new AdventureMapButton (CGI->generaltexth->zelp[380].first, CGI->generaltexth->zelp[380].second, boost::bind(&CBattleInterface::bFleef,this), 105 + pos.x, 561 + pos.y, "icm002.def", SDLK_r);
bAutofight = new AdventureMapButton (CGI->generaltexth->zelp[382].first, CGI->generaltexth->zelp[382].second, boost::bind(&CBattleInterface::bAutofightf,this), 157 + pos.x, 561 + pos.y, "icm004.def", SDLK_a);
bSpell = new AdventureMapButton (CGI->generaltexth->zelp[385].first, CGI->generaltexth->zelp[385].second, boost::bind(&CBattleInterface::bSpellf,this), 645 + pos.x, 561 + pos.y, "icm005.def", SDLK_c);
bWait = new AdventureMapButton (CGI->generaltexth->zelp[386].first, CGI->generaltexth->zelp[386].second, boost::bind(&CBattleInterface::bWaitf,this), 696 + pos.x, 561 + pos.y, "icm006.def", SDLK_w);
bDefence = new AdventureMapButton (CGI->generaltexth->zelp[387].first, CGI->generaltexth->zelp[387].second, boost::bind(&CBattleInterface::bDefencef,this), 747 + pos.x, 561 + pos.y, "icm007.def", SDLK_d);
bDefence->assignedKeys.insert(SDLK_SPACE);
bConsoleUp = new AdventureMapButton (std::string(), std::string(), boost::bind(&CBattleInterface::bConsoleUpf,this), 624 + pos.x, 561 + pos.y, "ComSlide.def", SDLK_UP);
bConsoleDown = new AdventureMapButton (std::string(), std::string(), boost::bind(&CBattleInterface::bConsoleDownf,this), 624 + pos.x, 580 + pos.y, "ComSlide.def", SDLK_DOWN);
bConsoleDown->bitmapOffset = 2;
console = new CBattleConsole();
console->pos.x = 211 + pos.x;
console->pos.y = 560 + pos.y;
console->pos.w = 406;
console->pos.h = 38;
//loading hero animations
if(hero1) // attacking hero
{
attackingHero = new CBattleHero(graphics->battleHeroes[hero1->type->heroType], 0, 0, false, hero1->tempOwner, hero1->tempOwner == LOCPLINT->playerID ? hero1 : NULL, this);
attackingHero->pos = genRect(attackingHero->dh->ourImages[0].bitmap->h, attackingHero->dh->ourImages[0].bitmap->w, -40 + pos.x, pos.y);
}
else
{
attackingHero = NULL;
}
if(hero2) // defending hero
{
defendingHero = new CBattleHero(graphics->battleHeroes[hero2->type->heroType], 0, 0, true, hero2->tempOwner, hero2->tempOwner == LOCPLINT->playerID ? hero2 : NULL, this);
defendingHero->pos = genRect(defendingHero->dh->ourImages[0].bitmap->h, defendingHero->dh->ourImages[0].bitmap->w, 690 + pos.x, pos.y);
}
else
{
defendingHero = NULL;
}
//preparing cells and hexes
cellBorder = BitmapHandler::loadBitmap("CCELLGRD.BMP");
CSDL_Ext::alphaTransform(cellBorder);
cellShade = BitmapHandler::loadBitmap("CCELLSHD.BMP");
CSDL_Ext::alphaTransform(cellShade);
for(int h=0; h<BFIELD_SIZE; ++h)
{
bfield[h].myNumber = h;
int x = 14 + ((h/BFIELD_WIDTH)%2==0 ? 22 : 0) + 44*(h%BFIELD_WIDTH);
int y = 86 + 42 * (h/BFIELD_WIDTH);
bfield[h].pos = genRect(cellShade->h, cellShade->w, x + pos.x, y + pos.y);
bfield[h].accesible = true;
bfield[h].myInterface = this;
}
//locking occupied positions on batlefield
for(std::map<int, CStack>::iterator it = stacks.begin(); it!=stacks.end(); ++it) //stacks gained at top of this function
{
bfield[it->second.position].accesible = false;
}
//loading projectiles for units
for(std::map<int, CStack>::iterator g = stacks.begin(); g != stacks.end(); ++g)
{
if(g->second.creature->isShooting() && CGI->creh->idToProjectile[g->second.creature->idNumber] != std::string())
{
idToProjectile[g->second.creature->idNumber] = CDefHandler::giveDef(CGI->creh->idToProjectile[g->second.creature->idNumber]);
if(idToProjectile[g->second.creature->idNumber]->ourImages.size() > 2) //add symmetric images
{
for(int k = idToProjectile[g->second.creature->idNumber]->ourImages.size()-2; k > 1; --k)
{
Cimage ci;
ci.bitmap = CSDL_Ext::rotate01(idToProjectile[g->second.creature->idNumber]->ourImages[k].bitmap);
ci.groupNumber = 0;
ci.imName = std::string();
idToProjectile[g->second.creature->idNumber]->ourImages.push_back(ci);
}
}
for(int s=0; s<idToProjectile[g->second.creature->idNumber]->ourImages.size(); ++s) //alpha transforming
{
CSDL_Ext::alphaTransform(idToProjectile[g->second.creature->idNumber]->ourImages[s].bitmap);
}
}
}
//preparing graphic with cell borders
cellBorders = CSDL_Ext::newSurface(background->w, background->h, cellBorder);
//copying palette
for(int g=0; g<cellBorder->format->palette->ncolors; ++g) //we assume that cellBorders->format->palette->ncolors == 256
{
cellBorders->format->palette->colors[g] = cellBorder->format->palette->colors[g];
}
//palette copied
for(int i=0; i<BFIELD_HEIGHT; ++i) //rows
{
for(int j=0; j<BFIELD_WIDTH-2; ++j) //columns
{
int x = 58 + (i%2==0 ? 22 : 0) + 44*j;
int y = 86 + 42 * i;
for(int cellX = 0; cellX < cellBorder->w; ++cellX)
{
for(int cellY = 0; cellY < cellBorder->h; ++cellY)
{
if(y+cellY < cellBorders->h && x+cellX < cellBorders->w)
* ((Uint8*)cellBorders->pixels + (y+cellY) * cellBorders->pitch + (x+cellX)) |= * ((Uint8*)cellBorder->pixels + cellY * cellBorder->pitch + cellX);
}
}
}
}
backgroundWithHexes = CSDL_Ext::newSurface(background->w, background->h, screen);
//preparing obstacle defs
std::vector<CObstacleInstance> obst = LOCPLINT->cb->battleGetAllObstacles();
for(int t=0; t<obst.size(); ++t)
{
idToObstacle[obst[t].ID] = CDefHandler::giveDef(CGI->heroh->obstacles[obst[t].ID].defName);
for(int n=0; n<idToObstacle[obst[t].ID]->ourImages.size(); ++n)
{
SDL_SetColorKey(idToObstacle[obst[t].ID]->ourImages[n].bitmap, SDL_SRCCOLORKEY, SDL_MapRGB(idToObstacle[obst[t].ID]->ourImages[n].bitmap->format,0,255,255));
}
}
//initializing spellToEffect
spellToEffect[17] = 1; //lightning bolt
spellToEffect[18] = 10; //implosion
spellToEffect[27] = 27; //shield
spellToEffect[28] = 2; //air shield
spellToEffect[41] = 36; //bless
spellToEffect[42] = 40; //curse
spellToEffect[43] = 4; //bloodlust
spellToEffect[45] = 56; //weakness
spellToEffect[46] = 54; //stone skin
spellToEffect[48] = 0; //prayer
spellToEffect[49] = 20; //mirth
spellToEffect[50] = 30; //sorrow
spellToEffect[51] = 18; //fortune
spellToEffect[52] = 48; //misfortune
spellToEffect[53] = 31; //haste
spellToEffect[54] = 19; //slow
spellToEffect[56] = 17; //frenzy
spellToEffect[61] = 42; //forgetfulness
}
CBattleInterface::~CBattleInterface()
{
SDL_FreeSurface(background);
SDL_FreeSurface(menu);
SDL_FreeSurface(amountNormal);
SDL_FreeSurface(amountNegative);
SDL_FreeSurface(amountPositive);
SDL_FreeSurface(amountEffNeutral);
SDL_FreeSurface(cellBorders);
SDL_FreeSurface(backgroundWithHexes);
delete bOptions;
delete bSurrender;
delete bFlee;
delete bAutofight;
delete bSpell;
delete bWait;
delete bDefence;
delete bConsoleUp;
delete bConsoleDown;
delete console;
delete givenCommand;
delete attackingHero;
delete defendingHero;
SDL_FreeSurface(cellBorder);
SDL_FreeSurface(cellShade);
for(std::map< int, CCreatureAnimation * >::iterator g=creAnims.begin(); g!=creAnims.end(); ++g)
delete g->second;
for(std::map< int, CDefHandler * >::iterator g=idToProjectile.begin(); g!=idToProjectile.end(); ++g)
delete g->second;
for(std::map< int, CDefHandler * >::iterator g=idToObstacle.begin(); g!=idToObstacle.end(); ++g)
delete g->second;
LOCPLINT->battleInt = NULL;
}
void CBattleInterface::setPrintCellBorders(bool set)
{
settings.printCellBorders = set;
redrawBackgroundWithHexes(activeStack);
}
void CBattleInterface::setPrintStackRange(bool set)
{
settings.printStackRange = set;
redrawBackgroundWithHexes(activeStack);
}
void CBattleInterface::setPrintMouseShadow(bool set)
{
settings.printMouseShadow = set;
}
void CBattleInterface::activate()
{
KeyInterested::activate();
MotionInterested::activate();
subInt = NULL;
bOptions->activate();
bSurrender->activate();
bFlee->activate();
bAutofight->activate();
bSpell->activate();
bWait->activate();
bDefence->activate();
bConsoleUp->activate();
bConsoleDown->activate();
for(int b=0; b<BFIELD_SIZE; ++b)
{
bfield[b].activate();
}
if(attackingHero)
attackingHero->activate();
if(defendingHero)
defendingHero->activate();
LOCPLINT->cingconsole->activate();
}
void CBattleInterface::deactivate()
{
KeyInterested::deactivate();
MotionInterested::deactivate();
bOptions->deactivate();
bSurrender->deactivate();
bFlee->deactivate();
bAutofight->deactivate();
bSpell->deactivate();
bWait->deactivate();
bDefence->deactivate();
bConsoleUp->deactivate();
bConsoleDown->deactivate();
for(int b=0; b<BFIELD_SIZE; ++b)
{
bfield[b].deactivate();
}
if(attackingHero)
attackingHero->deactivate();
if(defendingHero)
defendingHero->deactivate();
LOCPLINT->cingconsole->deactivate();
}
void CBattleInterface::show(SDL_Surface * to)
{
std::map<int, CStack> stacks = LOCPLINT->cb->battleGetStacks(); //used in a few places
++animCount;
if(!to) //"evaluating" to
to = screen;
SDL_Rect buf;
SDL_GetClipRect(to, &buf);
SDL_SetClipRect(to, &pos);
//printing background and hexes
if(activeStack != -1 && creAnims[activeStack]->getType() != 0) //show everything with range
{
blitAt(backgroundWithHexes, pos.x, pos.y, to);
}
else
{
//showing background
blitAt(background, pos.x, pos.y, to);
if(settings.printCellBorders)
{
CSDL_Ext::blit8bppAlphaTo24bpp(cellBorders, NULL, to, &pos);
}
}
//printing hovered cell
for(int b=0; b<BFIELD_SIZE; ++b)
{
if(bfield[b].strictHovered && bfield[b].hovered)
{
if(previouslyHoveredHex == -1) previouslyHoveredHex = b; //something to start with
if(currentlyHoveredHex == -1) currentlyHoveredHex = b; //something to start with
if(currentlyHoveredHex != b) //repair hover info
{
previouslyHoveredHex = currentlyHoveredHex;
currentlyHoveredHex = b;
}
//print shade
if(settings.printMouseShadow)
{
int x = 14 + ((b/BFIELD_WIDTH)%2==0 ? 22 : 0) + 44*(b%BFIELD_WIDTH) + pos.x;
int y = 86 + 42 * (b/BFIELD_WIDTH) + pos.y;
CSDL_Ext::blit8bppAlphaTo24bpp(cellShade, NULL, to, &genRect(cellShade->h, cellShade->w, x, y));
}
}
}
SDL_SetClipRect(to, &buf); //restoring previous clip_rect
//showing menu background and console
blitAt(menu, pos.x, 556 + pos.y, to);
console->show(to);
//showing buttons
bOptions->show(to);
bSurrender->show(to);
bFlee->show(to);
bAutofight->show(to);
bSpell->show(to);
bWait->show(to);
bDefence->show(to);
bConsoleUp->show(to);
bConsoleDown->show(to);
SDL_GetClipRect(to, &buf);
SDL_SetClipRect(to, &pos);
//showing obstacles
std::vector<CObstacleInstance> obstacles = LOCPLINT->cb->battleGetAllObstacles();
for(int b=0; b<obstacles.size(); ++b)
{
int x = ((obstacles[b].pos/BFIELD_WIDTH)%2==0 ? 22 : 0) + 44*(obstacles[b].pos%BFIELD_WIDTH);
int y = 86 + 42 * (obstacles[b].pos/BFIELD_WIDTH);
std::vector<Cimage> &images = idToObstacle[obstacles[b].ID]->ourImages;
blitAt(images[((animCount+1)/(4/settings.animSpeed))%images.size()].bitmap, x, y, to);
}
//showing hero animations
if(attackingHero)
attackingHero->show(to);
if(defendingHero)
defendingHero->show(to);
////showing units //a lot of work...
std::vector<int> stackAliveByHex[BFIELD_SIZE];
//double loop because dead stacks should be printed first
for(std::map<int, CStack>::iterator j=stacks.begin(); j!=stacks.end(); ++j)
{
if(j->second.alive())
stackAliveByHex[j->second.position].push_back(j->second.ID);
}
std::vector<int> stackDeadByHex[BFIELD_SIZE];
for(std::map<int, CStack>::iterator j=stacks.begin(); j!=stacks.end(); ++j)
{
if(!j->second.alive())
stackDeadByHex[j->second.position].push_back(j->second.ID);
}
attackingShowHelper(); // handle attack animation
for(int b=0; b<BFIELD_SIZE; ++b) //showing dead stacks
{
for(size_t v=0; v<stackDeadByHex[b].size(); ++v)
{
creAnims[stackDeadByHex[b][v]]->nextFrame(to, creAnims[stackDeadByHex[b][v]]->pos.x + pos.x, creAnims[stackDeadByHex[b][v]]->pos.y + pos.y, creDir[stackDeadByHex[b][v]], animCount, false); //increment always when moving, never if stack died
}
}
for(int b=0; b<BFIELD_SIZE; ++b) //showing alive stacks
{
for(size_t v=0; v<stackAliveByHex[b].size(); ++v)
{
int curStackID = stackAliveByHex[b][v];
const CStack &curStack = stacks[curStackID];
int animType = creAnims[curStackID]->getType();
bool incrementFrame = (animCount%(4/settings.animSpeed)==0) && animType!=5 && animType!=20 && animType!=3 && animType!=2;
if(animType == 2)
{
if(standingFrame.find(curStackID)!=standingFrame.end())
{
incrementFrame = (animCount%(8/settings.animSpeed)==0);
if(incrementFrame)
{
++standingFrame[curStackID];
if(standingFrame[curStackID] == creAnims[curStackID]->framesInGroup(2))
{
standingFrame.erase(standingFrame.find(curStackID));
}
}
}
else
{
if((rand()%50) == 0)
{
standingFrame.insert(std::make_pair(curStackID, 0));
}
}
}
creAnims[curStackID]->nextFrame(to, creAnims[curStackID]->pos.x + pos.x, creAnims[curStackID]->pos.y + pos.y, creDir[curStackID], animCount, incrementFrame, curStackID==activeStack, curStackID==mouseHoveredStack); //increment always when moving, never if stack died
//printing amount
if(curStack.amount > 0 //don't print if stack is not alive
&& (!LOCPLINT->curAction
|| (LOCPLINT->curAction->stackNumber != curStackID //don't print if stack is currently taking an action
&& (LOCPLINT->curAction->actionType != 6 || curStack.position != LOCPLINT->curAction->additionalInfo) //nor if it's an object of attack
&& (LOCPLINT->curAction->destinationTile != curStack.position) //nor if it's on destination tile for current action
)
)
&& !vstd::contains(curStack.abilities,SIEGE_WEAPON) //and not a war machine...
)
{
int xAdd = curStack.attackerOwned ? 220 : 202;
//blitting amoutn background box
SDL_Surface *amountBG = NULL;
if(curStack.effects.size() == 0)
{
amountBG = amountNormal;
}
else
{
int pos=0; //determining total positiveness of effects
for(int c=0; c<curStack.effects.size(); ++c)
{
pos += CGI->spellh->spells[ curStack.effects[c].id ].positiveness;
}
if(pos > 0)
{
amountBG = amountPositive;
}
else if(pos < 0)
{
amountBG = amountNegative;
}
else
{
amountBG = amountEffNeutral;
}
}
SDL_BlitSurface(amountBG, NULL, to, &genRect(amountNormal->h, amountNormal->w, creAnims[curStackID]->pos.x + xAdd + pos.x, creAnims[curStackID]->pos.y + 260 + pos.y));
//blitting amount
std::stringstream ss;
ss<<curStack.amount;
CSDL_Ext::printAtMiddleWB(
ss.str(),
creAnims[curStackID]->pos.x + xAdd + 14 + pos.x,
creAnims[curStackID]->pos.y + 260 + 4 + pos.y,
GEOR13,
20,
zwykly,
to
);
}
}
}
//units shown
projectileShowHelper(to);//showing projectiles
//showing spell effects
if(battleEffects.size())
{
std::vector< std::list<SBattleEffect>::iterator > toErase;
for(std::list<SBattleEffect>::iterator it = battleEffects.begin(); it!=battleEffects.end(); ++it)
{
SDL_Surface * bitmapToBlit = it->anim->ourImages[(it->frame)%it->anim->ourImages.size()].bitmap;
SDL_BlitSurface(bitmapToBlit, NULL, to, &genRect(bitmapToBlit->h, bitmapToBlit->w, pos.x + it->x, pos.y + it->y));
++(it->frame);
if(it->frame == it->maxFrame)
{
toErase.push_back(it);
}
}
for(size_t b=0; b<toErase.size(); ++b)
{
delete toErase[b]->anim;
battleEffects.erase(toErase[b]);
}
}
//showing queue of stacks
if(showStackQueue)
{
int xPos = screen->w/2 - ( stacks.size() * 37 )/2;
int yPos = (screen->h - 600)/2 + 10;
std::vector<CStack> stacksSorted;
stacksSorted = LOCPLINT->cb->battleGetStackQueue();
int startFrom = -1;
for(size_t n=0; n<stacksSorted.size(); ++n)
{
if(stacksSorted[n].ID == activeStack)
{
startFrom = n;
break;
}
}
if(startFrom != -1)
{
for(size_t b=startFrom; b<stacksSorted.size()+startFrom; ++b)
{
SDL_BlitSurface(graphics->smallImgs[-2], NULL, to, &genRect(32, 32, xPos, yPos));
//printing colored border
for(int xFrom = xPos-1; xFrom<xPos+33; ++xFrom)
{
for(int yFrom = yPos-1; yFrom<yPos+33; ++yFrom)
{
if(xFrom == xPos-1 || xFrom == xPos+32 || yFrom == yPos-1 || yFrom == yPos+32)
{
SDL_Color pc;
if(stacksSorted[b % stacksSorted.size()].owner != 255)
{
pc = graphics->playerColors[stacksSorted[b % stacksSorted.size()].owner];
}
else
{
pc = *graphics->neutralColor;
}
CSDL_Ext::SDL_PutPixelWithoutRefresh(to, xFrom, yFrom, pc.r, pc.g, pc.b);
}
}
}
//colored border printed
SDL_BlitSurface(graphics->smallImgs[stacksSorted[b % stacksSorted.size()].creature->idNumber], NULL, to, &genRect(32, 32, xPos, yPos));
xPos += 37;
}
}
}
SDL_SetClipRect(to, &buf); //restoring previous clip_rect
//showing window with result of battle
if(resWindow)
{
resWindow->show(to);
}
//showing in-gmae console
LOCPLINT->cingconsole->show(to);
//printing border around interface
if(screen->w != 800 || screen->h !=600)
CMessage::drawBorder(LOCPLINT->playerID,to,828,628,pos.x-14,pos.y-15);
}
void CBattleInterface::keyPressed(const SDL_KeyboardEvent & key)
{
if(key.keysym.sym == SDLK_q)
{
showStackQueue = key.state==SDL_PRESSED;
}
}
void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
{
if(activeStack>=0 && !spellDestSelectMode)
{
mouseHoveredStack = -1;
int myNumber = -1; //number of hovered tile
for(int g=0; g<BFIELD_SIZE; ++g)
{
if(bfield[g].hovered && bfield[g].strictHovered)
{
myNumber = g;
break;
}
}
if(myNumber == -1)
{
CGI->curh->changeGraphic(1, 6);
if(console->whoSetAlter == 0)
{
console->alterTxt = "";
}
}
else
{
if(std::find(shadedHexes.begin(),shadedHexes.end(),myNumber) == shadedHexes.end())
{
CStack *shere = LOCPLINT->cb->battleGetStackByPos(myNumber);
CStack *sactive = LOCPLINT->cb->battleGetStackByID(activeStack);
if(shere)
{
if(shere->owner == LOCPLINT->playerID) //our stack
{
CGI->curh->changeGraphic(1,5);
//setting console text
char buf[500];
sprintf(buf, CGI->generaltexth->allTexts[297].c_str(), shere->amount == 1 ? shere->creature->nameSing.c_str() : shere->creature->namePl.c_str());
console->alterTxt = buf;
console->whoSetAlter = 0;
mouseHoveredStack = shere->ID;
if(creAnims[shere->ID]->getType() == 2 && creAnims[shere->ID]->framesInGroup(1) > 0)
{
creAnims[shere->ID]->playOnce(1);
}
}
else if(LOCPLINT->cb->battleCanShoot(activeStack,myNumber)) //we can shoot enemy
{
CGI->curh->changeGraphic(1,3);
//setting console text
char buf[500];
sprintf(buf, CGI->generaltexth->allTexts[296].c_str(), shere->amount == 1 ? shere->creature->nameSing.c_str() : shere->creature->namePl.c_str(), sactive->shots, "?");
console->alterTxt = buf;
console->whoSetAlter = 0;
}
else if(isTileAttackable(myNumber)) //available enemy (melee attackable)
{
int fromHex = previouslyHoveredHex;
if(fromHex!=-1 && fromHex%BFIELD_WIDTH!=0 && fromHex%BFIELD_WIDTH!=(BFIELD_WIDTH-1) && vstd::contains(shadedHexes, fromHex))
{
switch(BattleInfo::mutualPosition(fromHex, myNumber))
{
case 0:
CGI->curh->changeGraphic(1,12);
break;
case 1:
CGI->curh->changeGraphic(1,7);
break;
case 2:
CGI->curh->changeGraphic(1,8);
break;
case 3:
CGI->curh->changeGraphic(1,9);
break;
case 4:
CGI->curh->changeGraphic(1,10);
break;
case 5:
CGI->curh->changeGraphic(1,11);
break;
}
}
}
else //unavailable enemy
{
CGI->curh->changeGraphic(1,0);
console->alterTxt = "";
console->whoSetAlter = 0;
}
}
else //empty unavailable tile
{
CGI->curh->changeGraphic(1,0);
console->alterTxt = "";
console->whoSetAlter = 0;
}
}
else //available tile
{
CStack *sactive = LOCPLINT->cb->battleGetStackByID(activeStack);
if(LOCPLINT->cb->battleGetStackByID(activeStack)->creature->isFlying())
{
CGI->curh->changeGraphic(1,2);
//setting console text
char buf[500];
sprintf(buf, CGI->generaltexth->allTexts[295].c_str(), sactive->amount == 1 ? sactive->creature->nameSing.c_str() : sactive->creature->namePl.c_str());
console->alterTxt = buf;
console->whoSetAlter = 0;
}
else
{
CGI->curh->changeGraphic(1,1);
//setting console text
char buf[500];
sprintf(buf, CGI->generaltexth->allTexts[294].c_str(), sactive->amount == 1 ? sactive->creature->nameSing.c_str() : sactive->creature->namePl.c_str());
console->alterTxt = buf;
console->whoSetAlter = 0;
}
}
}
}
else if(spellDestSelectMode)
{
int myNumber = -1; //number of hovered tile
for(int g=0; g<BFIELD_SIZE; ++g)
{
if(bfield[g].hovered && bfield[g].strictHovered)
{
myNumber = g;
break;
}
}
if(myNumber == -1)
{
CGI->curh->changeGraphic(1, 0);
//setting console text
console->alterTxt = CGI->generaltexth->allTexts[23];
console->whoSetAlter = 0;
}
else
{
CStack * stackUnder = LOCPLINT->cb->battleGetStackByPos(myNumber);
switch(spellSelMode)
{
case 0:
CGI->curh->changeGraphic(3, 0);
//setting console text
char buf[500];
sprintf(buf, CGI->generaltexth->allTexts[26].c_str(), CGI->spellh->spells[spellToCast->additionalInfo].name.c_str());
console->alterTxt = buf;
console->whoSetAlter = 0;
break;
case 1:
if(stackUnder && LOCPLINT->playerID == stackUnder->owner )
{
CGI->curh->changeGraphic(3, 0);
//setting console text
char buf[500];
std::string creName = stackUnder->amount > 1 ? stackUnder->creature->namePl : stackUnder->creature->nameSing;
sprintf(buf, CGI->generaltexth->allTexts[27].c_str(), CGI->spellh->spells[spellToCast->additionalInfo].name.c_str(), creName.c_str());
console->alterTxt = buf;
console->whoSetAlter = 0;
break;
}
else
{
CGI->curh->changeGraphic(1, 0);
//setting console text
console->alterTxt = CGI->generaltexth->allTexts[23];
console->whoSetAlter = 0;
}
break;
case 2:
if(stackUnder && LOCPLINT->playerID != stackUnder->owner )
{
CGI->curh->changeGraphic(3, 0);
//setting console text
char buf[500];
std::string creName = stackUnder->amount > 1 ? stackUnder->creature->namePl : stackUnder->creature->nameSing;
sprintf(buf, CGI->generaltexth->allTexts[27].c_str(), CGI->spellh->spells[spellToCast->additionalInfo].name.c_str(), creName.c_str());
console->alterTxt = buf;
console->whoSetAlter = 0;
}
else
{
CGI->curh->changeGraphic(1, 0);
//setting console text
console->alterTxt = CGI->generaltexth->allTexts[23];
console->whoSetAlter = 0;
}
break;
case 3:
if(stackUnder)
{
CGI->curh->changeGraphic(3, 0);
//setting console text
char buf[500];
std::string creName = stackUnder->amount > 1 ? stackUnder->creature->namePl : stackUnder->creature->nameSing;
sprintf(buf, CGI->generaltexth->allTexts[27].c_str(), CGI->spellh->spells[spellToCast->additionalInfo].name.c_str(), creName.c_str());
console->alterTxt = buf;
console->whoSetAlter = 0;
}
else
{
CGI->curh->changeGraphic(1, 0);
//setting console text
console->alterTxt = CGI->generaltexth->allTexts[23];
console->whoSetAlter = 0;
}
break;
case 4: //TODO: implement this case
break;
}
}
}
}
bool CBattleInterface::reverseCreature(int number, int hex, bool wideTrick)
{
if(creAnims[number]==NULL)
return false; //there is no such creature
creAnims[number]->setType(8);
//int firstFrame = creAnims[number]->getFrame();
//for(int g=0; creAnims[number]->getFrame() != creAnims[number]->framesInGroup(8) + firstFrame - 1; ++g)
while(!creAnims[number]->onLastFrameInGroup())
{
show(screen);
CSDL_Ext::update(screen);
SDL_framerateDelay(LOCPLINT->mainFPSmng);
}
creDir[number] = !creDir[number];
CStack curs = *LOCPLINT->cb->battleGetStackByID(number);
std::pair <int, int> coords = CBattleHex::getXYUnitAnim(hex, creDir[number], curs.creature);
creAnims[number]->pos.x = coords.first;
//creAnims[number]->pos.y = coords.second;
if(wideTrick && curs.creature->isDoubleWide())
{
if(curs.attackerOwned)
{
if(!creDir[number])
creAnims[number]->pos.x -= 44;
}
else
{
if(creDir[number])
creAnims[number]->pos.x += 44;
}
}
creAnims[number]->setType(7);
//firstFrame = creAnims[number]->getFrame();
//for(int g=0; creAnims[number]->getFrame() != creAnims[number]->framesInGroup(7) + firstFrame - 1; ++g)
while(!creAnims[number]->onLastFrameInGroup())
{
show(screen);
CSDL_Ext::update(screen);
SDL_framerateDelay(LOCPLINT->mainFPSmng);
}
creAnims[number]->setType(2);
return true;
}
void CBattleInterface::handleStartMoving(int number)
{
for(int i=0; i<creAnims[number]->framesInGroup(20)*getAnimSpeedMultiplier()-1; ++i)
{
show(screen);
CSDL_Ext::update(screen);
SDL_framerateDelay(LOCPLINT->mainFPSmng);
if((animCount+1)%(4/settings.animSpeed)==0)
creAnims[number]->incrementFrame();
}
}
void CBattleInterface::bOptionsf()
{
CGI->curh->changeGraphic(0,0);
deactivate();
SDL_Rect temp_rect = genRect(431, 481, 160, 84);
CBattleOptionsWindow * optionsWin = new CBattleOptionsWindow(temp_rect, this);
optionsWin->activate();
LOCPLINT->objsToBlit.push_back(optionsWin);
}
void CBattleInterface::bSurrenderf()
{
}
void CBattleInterface::bFleef()
{
CFunctionList<void()> ony = boost::bind(&CBattleInterface::reallyFlee,this);
LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[28],std::vector<SComponent*>(), ony, 0, false);
}
void CBattleInterface::reallyFlee()
{
giveCommand(4,0,0);
CGI->curh->changeGraphic(0, 0);
}
void CBattleInterface::bAutofightf()
{
}
void CBattleInterface::bSpellf()
{
CGI->curh->changeGraphic(0,0);
deactivate();
const CGHeroInstance * chi = NULL;
if(attackingHeroInstance->tempOwner == LOCPLINT->playerID)
chi = attackingHeroInstance;
else
chi = defendingHeroInstance;
CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (conf.cc.resx - 620)/2, (conf.cc.resy - 595)/2), chi);
spellWindow->activate();
LOCPLINT->objsToBlit.push_back(spellWindow);
}
void CBattleInterface::bWaitf()
{
giveCommand(8,0,activeStack);
}
void CBattleInterface::bDefencef()
{
giveCommand(3,0,activeStack);
}
void CBattleInterface::bConsoleUpf()
{
console->scrollUp();
}
void CBattleInterface::bConsoleDownf()
{
console->scrollDown();
}
void CBattleInterface::newStack(CStack stack)
{
creAnims[stack.ID] = new CCreatureAnimation(stack.creature->animDefName);
creAnims[stack.ID]->setType(2);
creDir[stack.ID] = stack.owner==attackingHeroInstance->tempOwner;
}
void CBattleInterface::stackRemoved(CStack stack)
{
delete creAnims[stack.ID];
creAnims.erase(stack.ID);
}
void CBattleInterface::stackActivated(int number)
{
//givenCommand = NULL;
activeStack = number;
myTurn = true;
redrawBackgroundWithHexes(number);
bWait->block(vstd::contains(LOCPLINT->cb->battleGetStackByID(number)->state,WAITING)); //block waiting button if stack has been already waiting
//block cast spell button if hero doesn't have a spellbook
if(attackingHeroInstance && attackingHeroInstance->tempOwner==LOCPLINT->cb->battleGetStackByID(number)->owner)
{
bSpell->block(!attackingHeroInstance->getArt(17));
}
else if(defendingHeroInstance && defendingHeroInstance->tempOwner==LOCPLINT->cb->battleGetStackByID(number)->owner)
{
bSpell->block(!defendingHeroInstance->getArt(17));
}
}
void CBattleInterface::stackMoved(int number, int destHex, bool endMoving, int distance)
{
bool startMoving = creAnims[number]->getType()==20;
//a few useful variables
int curStackPos = LOCPLINT->cb->battleGetPos(number);
int steps = creAnims[number]->framesInGroup(0)*getAnimSpeedMultiplier()-1;
int hexWbase = 44, hexHbase = 42;
bool twoTiles = LOCPLINT->cb->battleGetCreature(number).isDoubleWide();
CStack * movedStack = LOCPLINT->cb->battleGetStackByID(number);
std::pair<int, int> begPosition = CBattleHex::getXYUnitAnim(curStackPos, movedStack->attackerOwned, movedStack->creature);
std::pair<int, int> endPosition = CBattleHex::getXYUnitAnim(destHex, movedStack->attackerOwned, movedStack->creature);
if(startMoving) //animation of starting move; some units don't have this animation (ie. halberdier)
{
handleStartMoving(number);
}
if(moveStarted)
{
CGI->curh->hide();
creAnims[number]->setType(0);
moveStarted = false;
}
int mutPos = BattleInfo::mutualPosition(curStackPos, destHex);
float stepX=0.0, stepY=0.0; //how far stack is moved in one frame; calculated later
//reverse unit if necessary
if((begPosition.first > endPosition.first) && creDir[number] == true)
{
reverseCreature(number, curStackPos, twoTiles);
}
else if ((begPosition.first < endPosition.first) && creDir[number] == false)
{
reverseCreature(number, curStackPos, twoTiles);
}
if(creAnims[number]->getType() != 0)
{
creAnims[number]->setType(0);
}
//unit reversed
//step shift calculation
float posX = creAnims[number]->pos.x, posY = creAnims[number]->pos.y; // for precise calculations ;]
if(mutPos == -1 && movedStack->creature->isFlying())
{
steps *= distance;
stepX = (endPosition.first - (float)begPosition.first)/steps;
stepY = (endPosition.second - (float)begPosition.second)/steps;
}
else
{
switch(mutPos)
{
case 0:
stepX = (-1.0)*((float)hexWbase)/(2.0f*steps);
stepY = (-1.0)*((float)hexHbase)/((float)steps);
break;
case 1:
stepX = ((float)hexWbase)/(2.0f*steps);
stepY = (-1.0)*((float)hexHbase)/((float)steps);
break;
case 2:
stepX = ((float)hexWbase)/((float)steps);
stepY = 0.0;
break;
case 3:
stepX = ((float)hexWbase)/(2.0f*steps);
stepY = ((float)hexHbase)/((float)steps);
break;
case 4:
stepX = (-1.0)*((float)hexWbase)/(2.0f*steps);
stepY = ((float)hexHbase)/((float)steps);
break;
case 5:
stepX = (-1.0)*((float)hexWbase)/((float)steps);
stepY = 0.0;
break;
}
}
//step shifts calculated
//switch(mutPos) //reverse unit if necessary
//{
//case 0: case 4: case 5:
// if(creDir[number] == true)
// reverseCreature(number, curStackPos, twoTiles);
// break;
//case 1: case 2: case 3:
// if(creDir[number] == false)
// reverseCreature(number, curStackPos, twoTiles);
// break;
//}
//moving instructions
for(int i=0; i<steps; ++i)
{
posX += stepX;
creAnims[number]->pos.x = posX;
posY += stepY;
creAnims[number]->pos.y = posY;
show(screen);
CSDL_Ext::update(screen);
SDL_framerateDelay(LOCPLINT->mainFPSmng);
}
//unit moved
if(endMoving) //animation of ending move
{
if(creAnims[number]->framesInGroup(21)!=0) // some units don't have this animation (ie. halberdier)
{
creAnims[number]->setType(21);
//for(int i=0; i<creAnims[number]->framesInGroup(21)*getAnimSpeedMultiplier()-1; ++i)
while(!creAnims[number]->onLastFrameInGroup())
{
show(screen);
CSDL_Ext::update(screen);
SDL_framerateDelay(LOCPLINT->mainFPSmng);
}
}
creAnims[number]->setType(2); //resetting to default
CGI->curh->show();
}
CStack curs = *LOCPLINT->cb->battleGetStackByID(number);
if(endMoving) //resetting to default
{
if(creDir[number] != (curs.owner == attackingHeroInstance->tempOwner))
reverseCreature(number, destHex, twoTiles);
}
std::pair <int, int> coords = CBattleHex::getXYUnitAnim(destHex, creDir[number], curs.creature);
creAnims[number]->pos.x = coords.first;
if(!endMoving && twoTiles && (curs.owner == attackingHeroInstance->tempOwner) && (creDir[number] != (curs.owner == attackingHeroInstance->tempOwner))) //big attacker creature is reversed
creAnims[number]->pos.x -= 44;
else if(!endMoving && twoTiles && (curs.owner != attackingHeroInstance->tempOwner) && (creDir[number] != (curs.owner == attackingHeroInstance->tempOwner))) //big defender creature is reversed
creAnims[number]->pos.x += 44;
creAnims[number]->pos.y = coords.second;
}
void CBattleInterface::stacksAreAttacked(std::vector<CBattleInterface::SStackAttackedInfo> attackedInfos)
{
//restoring default state of battleWindow by calling show func
while(true)
{
show(screen);
CSDL_Ext::update();
SDL_framerateDelay(LOCPLINT->mainFPSmng);
//checking break conditions
bool break_loop = true;
for(size_t g=0; g<attackedInfos.size(); ++g)
{
if(creAnims[attackedInfos[g].ID]->getType() != 2)
{
break_loop = false;
}
if(attackingInfo && attackingInfo->IDby == attackedInfos[g].IDby)
{
break_loop = false;
}
}
if(break_loop) break;
}
if(attackedInfos.size() == 1 && attackedInfos[0].byShooting) //delay hit animation
{
CStack attacker = *LOCPLINT->cb->battleGetStackByID(attackedInfos[0].IDby);
while(true)
{
bool found = false;
for(std::list<SProjectileInfo>::const_iterator it = projectiles.begin(); it!=projectiles.end(); ++it)
{
if(it->creID == attacker.creature->idNumber)
{
found = true;
break;
}
}
if(!found)
break;
else
{
show(screen);
CSDL_Ext::update(screen);
SDL_framerateDelay(LOCPLINT->mainFPSmng);
}
}
}
//initializing
int maxLen = 0;
for(size_t g=0; g<attackedInfos.size(); ++g)
{
if(attackedInfos[g].killed)
{
creAnims[attackedInfos[g].ID]->setType(5); //death
}
else
{
creAnims[attackedInfos[g].ID]->setType(3); //getting hit
}
}
//main showing loop
bool continueLoop = true;
while(continueLoop)
{
show(screen);
CSDL_Ext::update(screen);
SDL_framerateDelay(LOCPLINT->mainFPSmng);
for(size_t g=0; g<attackedInfos.size(); ++g)
{
if((animCount+1)%(4/settings.animSpeed)==0 && !creAnims[attackedInfos[g].ID]->onLastFrameInGroup())
{
creAnims[attackedInfos[g].ID]->incrementFrame();
}
if(creAnims[attackedInfos[g].ID]->onLastFrameInGroup() && creAnims[attackedInfos[g].ID]->getType() == 3)
creAnims[attackedInfos[g].ID]->setType(2);
}
bool isAnotherOne = false; //if true, there is a stack whose hit/death anim must be continued
for(size_t g=0; g<attackedInfos.size(); ++g)
{
if(!creAnims[attackedInfos[g].ID]->onLastFrameInGroup())
{
isAnotherOne = true;
break;
}
}
if(!isAnotherOne)
continueLoop = false;
}
//restoring animType
for(size_t g=0; g<attackedInfos.size(); ++g)
{
if(creAnims[attackedInfos[g].ID]->getType() == 3)
creAnims[attackedInfos[g].ID]->setType(2);
}
//printing info to console
for(size_t g=0; g<attackedInfos.size(); ++g)
{
if(attackedInfos[g].IDby!=-1)
printConsoleAttacked(attackedInfos[g].ID, attackedInfos[g].dmg, attackedInfos[g].amountKilled, attackedInfos[g].IDby);
}
}
void CBattleInterface::stackAttacking(int ID, int dest)
{
if(attackingInfo == NULL && creAnims[ID]->getType() == 20)
{
handleStartMoving(ID);
creAnims[ID]->setType(2);
}
while(attackingInfo != NULL || creAnims[ID]->getType()!=2)
{
show(screen);
CSDL_Ext::update(screen);
SDL_framerateDelay(LOCPLINT->mainFPSmng);
}
CStack aStack = *LOCPLINT->cb->battleGetStackByID(ID); //attacking stack
int reversedShift = 0; //shift of attacking stack's position due to reversing
if(aStack.attackerOwned)
{
if(aStack.creature->isDoubleWide())
{
switch(BattleInfo::mutualPosition(aStack.position, dest)) //attack direction
{
case 0:
//reverseCreature(ID, aStack.position, true);
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
//reverseCreature(ID, aStack.position, true);
break;
case 5:
reverseCreature(ID, aStack.position, true);
break;
case -1:
if(BattleInfo::mutualPosition(aStack.position + (aStack.attackerOwned ? -1 : 1), dest) >= 0) //if reversing stack will make its position adjacent to dest
{
reverseCreature(ID, aStack.position, true);
reversedShift = (aStack.attackerOwned ? -1 : 1);
}
break;
}
}
else //else for if(aStack.creature->isDoubleWide())
{
switch(BattleInfo::mutualPosition(aStack.position, dest)) //attack direction
{
case 0:
reverseCreature(ID, aStack.position, true);
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
reverseCreature(ID, aStack.position, true);
break;
case 5:
reverseCreature(ID, aStack.position, true);
break;
}
}
}
else //if(aStack.attackerOwned)
{
if(aStack.creature->isDoubleWide())
{
switch(BattleInfo::mutualPosition(aStack.position, dest)) //attack direction
{
case 0:
//reverseCreature(ID, aStack.position, true);
break;
case 1:
break;
case 2:
reverseCreature(ID, aStack.position, true);
break;
case 3:
break;
case 4:
//reverseCreature(ID, aStack.position, true);
break;
case 5:
//reverseCreature(ID, aStack.position, true);
break;
case -1:
if(BattleInfo::mutualPosition(aStack.position + (aStack.attackerOwned ? -1 : 1), dest) >= 0) //if reversing stack will make its position adjacent to dest
{
reverseCreature(ID, aStack.position, true);
reversedShift = (aStack.attackerOwned ? -1 : 1);
}
break;
}
}
else //else for if(aStack.creature->isDoubleWide())
{
switch(BattleInfo::mutualPosition(aStack.position, dest)) //attack direction
{
case 0:
//reverseCreature(ID, aStack.position, true);
break;
case 1:
reverseCreature(ID, aStack.position, true);
break;
case 2:
reverseCreature(ID, aStack.position, true);
break;
case 3:
reverseCreature(ID, aStack.position, true);
break;
case 4:
//reverseCreature(ID, aStack.position, true);
break;
case 5:
//reverseCreature(ID, aStack.position, true);
break;
}
}
}
attackingInfo = new CAttHelper;
attackingInfo->dest = dest;
attackingInfo->frame = 0;
attackingInfo->hitCount = 0;
attackingInfo->ID = ID;
attackingInfo->IDby = LOCPLINT->cb->battleGetStackByPos(dest)->ID;
attackingInfo->reversing = false;
attackingInfo->posShiftDueToDist = reversedShift;
attackingInfo->shooting = false;
switch(BattleInfo::mutualPosition(aStack.position + reversedShift, dest)) //attack direction
{
case 0:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(11);
break;
case 1:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(11);
break;
case 2:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(12);
break;
case 3:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(13);
break;
case 4:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(13);
break;
case 5:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(12);
break;
default:
tlog1<<"Critical Error! Wrong dest in stackAttacking! dest: "<<dest<<" attacking stack pos: "<<aStack.position<<" reversed shift: "<<reversedShift<<std::endl;
}
}
void CBattleInterface::newRound(int number)
{
console->addText(CGI->generaltexth->allTexts[412]);
}
void CBattleInterface::giveCommand(ui8 action, ui16 tile, ui32 stack, si32 additional)
{
BattleAction * ba = new BattleAction(); //is deleted in CPlayerInterface::activeStack()
ba->side = defendingHeroInstance ? (LOCPLINT->playerID == defendingHeroInstance->tempOwner) : false;
ba->actionType = action;
ba->destinationTile = tile;
ba->stackNumber = stack;
ba->additionalInfo = additional;
givenCommand->setn(ba);
myTurn = false;
activeStack = -1;
}
bool CBattleInterface::isTileAttackable(const int & number) const
{
for(size_t b=0; b<shadedHexes.size(); ++b)
{
if(BattleInfo::mutualPosition(shadedHexes[b], number) != -1 || shadedHexes[b] == number)
return true;
}
return false;
}
void CBattleInterface::hexLclicked(int whichOne)
{
if((whichOne%BFIELD_WIDTH)!=0 && (whichOne%BFIELD_WIDTH)!=(BFIELD_WIDTH-1)) //if player is trying to attack enemey unit or move creature stack
{
if(!myTurn)
return; //we are not permit to do anything
if(spellDestSelectMode)
{
//checking destination
bool allowCasting = true;
switch(spellSelMode)
{
case 1:
if(!LOCPLINT->cb->battleGetStackByPos(whichOne) || LOCPLINT->playerID != LOCPLINT->cb->battleGetStackByPos(whichOne)->owner )
allowCasting = false;
break;
case 2:
if(!LOCPLINT->cb->battleGetStackByPos(whichOne) || LOCPLINT->playerID == LOCPLINT->cb->battleGetStackByPos(whichOne)->owner )
allowCasting = false;
break;
case 3:
if(!LOCPLINT->cb->battleGetStackByPos(whichOne))
allowCasting = false;
break;
case 4: //TODO: implement this case
break;
}
//destination checked
if(allowCasting)
{
spellToCast->destinationTile = whichOne;
LOCPLINT->cb->battleMakeAction(spellToCast);
delete spellToCast;
spellToCast = NULL;
spellDestSelectMode = false;
CGI->curh->changeGraphic(1, 6);
}
}
else
{
CStack* dest = LOCPLINT->cb->battleGetStackByPos(whichOne); //creature at destination tile; -1 if there is no one
if(!dest || !dest->alive()) //no creature at that tile
{
if(std::find(shadedHexes.begin(),shadedHexes.end(),whichOne)!=shadedHexes.end())// and it's in our range
{
CGI->curh->changeGraphic(1, 6); //cursor should be changed
if(LOCPLINT->cb->battleGetStackByID(activeStack)->creature->isDoubleWide())
{
std::vector<int> acc = LOCPLINT->cb->battleGetAvailableHexes(activeStack, false);
int shiftedDest = whichOne + (LOCPLINT->cb->battleGetStackByID(activeStack)->attackerOwned ? 1 : -1);
if(vstd::contains(acc, whichOne))
giveCommand(2,whichOne,activeStack);
else if(vstd::contains(acc, shiftedDest))
giveCommand(2,shiftedDest,activeStack);
}
else
{
giveCommand(2,whichOne,activeStack);
}
}
}
else if(dest->owner != attackingHeroInstance->tempOwner
&& LOCPLINT->cb->battleCanShoot(activeStack, whichOne) ) //shooting
{
CGI->curh->changeGraphic(1, 6); //cursor should be changed
giveCommand(7,whichOne,activeStack);
}
else if(dest->owner != attackingHeroInstance->tempOwner) //attacking
{
switch(CGI->curh->number)
{
case 12: //from bottom right
{
int destHex = whichOne + ( (whichOne/BFIELD_WIDTH)%2 ? BFIELD_WIDTH : BFIELD_WIDTH+1 );
if(vstd::contains(shadedHexes, destHex))
giveCommand(6,destHex,activeStack,whichOne);
else if(attackingHeroInstance->tempOwner == LOCPLINT->cb->getMyColor()) //if we are attacker
{
if(vstd::contains(shadedHexes, destHex+1))
giveCommand(6,destHex+1,activeStack,whichOne);
}
else //if we are defneder
{
if(vstd::contains(shadedHexes, destHex-1))
giveCommand(6,destHex-1,activeStack,whichOne);
}
break;
}
case 7: //from bottom left
{
int destHex = whichOne + ( (whichOne/BFIELD_WIDTH)%2 ? BFIELD_WIDTH-1 : BFIELD_WIDTH );
if(vstd::contains(shadedHexes, destHex))
giveCommand(6,destHex,activeStack,whichOne);
else if(attackingHeroInstance->tempOwner == LOCPLINT->cb->getMyColor()) //if we are attacker
{
if(vstd::contains(shadedHexes, destHex+1))
giveCommand(6,destHex+1,activeStack,whichOne);
}
else //if we are defneder
{
if(vstd::contains(shadedHexes, destHex-1))
giveCommand(6,destHex-1,activeStack,whichOne);
}
break;
}
case 8: //from left
if(LOCPLINT->cb->battleGetStackByID(activeStack)->creature->isDoubleWide() && !LOCPLINT->cb->battleGetStackByID(activeStack)->attackerOwned)
{
std::vector<int> acc = LOCPLINT->cb->battleGetAvailableHexes(activeStack, false);
if(vstd::contains(acc, whichOne))
giveCommand(6,whichOne - 1,activeStack,whichOne);
else
giveCommand(6,whichOne - 2,activeStack,whichOne);
}
else
{
giveCommand(6,whichOne - 1,activeStack,whichOne);
}
break;
case 9: //from top left
{
int destHex = whichOne - ( (whichOne/BFIELD_WIDTH)%2 ? BFIELD_WIDTH+1 : BFIELD_WIDTH );
if(vstd::contains(shadedHexes, destHex))
giveCommand(6,destHex,activeStack,whichOne);
else if(attackingHeroInstance->tempOwner == LOCPLINT->cb->getMyColor()) //if we are attacker
{
if(vstd::contains(shadedHexes, destHex+1))
giveCommand(6,destHex+1,activeStack,whichOne);
}
else //if we are defneder
{
if(vstd::contains(shadedHexes, destHex-1))
giveCommand(6,destHex-1,activeStack,whichOne);
}
break;
}
case 10: //from top right
{
int destHex = whichOne - ( (whichOne/BFIELD_WIDTH)%2 ? BFIELD_WIDTH : BFIELD_WIDTH-1 );
if(vstd::contains(shadedHexes, destHex))
giveCommand(6,destHex,activeStack,whichOne);
else if(attackingHeroInstance->tempOwner == LOCPLINT->cb->getMyColor()) //if we are attacker
{
if(vstd::contains(shadedHexes, destHex+1))
giveCommand(6,destHex+1,activeStack,whichOne);
}
else //if we are defneder
{
if(vstd::contains(shadedHexes, destHex-1))
giveCommand(6,destHex-1,activeStack,whichOne);
}
break;
}
case 11: //from right
if(LOCPLINT->cb->battleGetStackByID(activeStack)->creature->isDoubleWide() && LOCPLINT->cb->battleGetStackByID(activeStack)->attackerOwned)
{
std::vector<int> acc = LOCPLINT->cb->battleGetAvailableHexes(activeStack, false);
if(vstd::contains(acc, whichOne))
giveCommand(6,whichOne + 1,activeStack,whichOne);
else
giveCommand(6,whichOne + 2,activeStack,whichOne);
}
else
{
giveCommand(6,whichOne + 1,activeStack,whichOne);
}
break;
}
CGI->curh->changeGraphic(1, 6); //cursor should be changed
}
}
}
}
void CBattleInterface::stackIsShooting(int ID, int dest)
{
if(attackingInfo != NULL)
{
return; //something went wrong
}
//projectile
float projectileAngle; //in radians; if positive, projectiles goes up
float straightAngle = 0.2f; //maximal angle in radians between straight horizontal line and shooting line for which shot is considered to be straight (absoulte value)
int fromHex = LOCPLINT->cb->battleGetPos(ID);
projectileAngle = atan2(float(abs(dest - fromHex)/BFIELD_WIDTH), float(abs(dest - fromHex)%BFIELD_WIDTH));
if(fromHex < dest)
projectileAngle = -projectileAngle;
SProjectileInfo spi;
spi.creID = LOCPLINT->cb->battleGetStackByID(ID)->creature->idNumber;
spi.reverse = !LOCPLINT->cb->battleGetStackByID(ID)->attackerOwned;
spi.step = 0;
spi.frameNum = 0;
spi.spin = CGI->creh->idToProjectileSpin[spi.creID];
std::pair<int, int> xycoord = CBattleHex::getXYUnitAnim(LOCPLINT->cb->battleGetPos(ID), true, &LOCPLINT->cb->battleGetCreature(ID));
std::pair<int, int> destcoord = CBattleHex::getXYUnitAnim(dest, false, &LOCPLINT->cb->battleGetCreature(ID));
destcoord.first += 250; destcoord.second += 210; //TODO: find a better place to shoot
if(projectileAngle > straightAngle) //upper shot
{
spi.x = xycoord.first + 200 + LOCPLINT->cb->battleGetCreature(ID).upperRightMissleOffsetX;
spi.y = xycoord.second + 100 - LOCPLINT->cb->battleGetCreature(ID).upperRightMissleOffsetY;
}
else if(projectileAngle < -straightAngle) //lower shot
{
spi.x = xycoord.first + 200 + LOCPLINT->cb->battleGetCreature(ID).lowerRightMissleOffsetX;
spi.y = xycoord.second + 150 - LOCPLINT->cb->battleGetCreature(ID).lowerRightMissleOffsetY;
}
else //straight shot
{
spi.x = xycoord.first + 200 + LOCPLINT->cb->battleGetCreature(ID).rightMissleOffsetX;
spi.y = xycoord.second + 125 - LOCPLINT->cb->battleGetCreature(ID).rightMissleOffsetY;
}
spi.lastStep = sqrt((float)((destcoord.first - spi.x)*(destcoord.first - spi.x) + (destcoord.second - spi.y) * (destcoord.second - spi.y))) / 40;
if(spi.lastStep == 0)
spi.lastStep = 1;
spi.dx = (destcoord.first - spi.x) / spi.lastStep;
spi.dy = (destcoord.second - spi.y) / spi.lastStep;
//set starting frame
if(spi.spin)
{
spi.frameNum = 0;
}
else
{
spi.frameNum = ((M_PI/2.0f - projectileAngle) / (2.0f *M_PI) + 1/((float)(2*(idToProjectile[spi.creID]->ourImages.size()-1)))) * (idToProjectile[spi.creID]->ourImages.size()-1);
}
//set delay
spi.animStartDelay = CGI->creh->creatures[spi.creID].attackClimaxFrame;
projectiles.push_back(spi);
//attack aniamtion
attackingInfo = new CAttHelper;
attackingInfo->dest = dest;
attackingInfo->frame = 0;
attackingInfo->hitCount = 0;
attackingInfo->ID = ID;
attackingInfo->reversing = false;
attackingInfo->posShiftDueToDist = 0;
attackingInfo->shooting = true;
if(projectileAngle > straightAngle) //upper shot
attackingInfo->shootingGroup = 14;
else if(projectileAngle < -straightAngle) //lower shot
attackingInfo->shootingGroup = 16;
else //straight shot
attackingInfo->shootingGroup = 15;
attackingInfo->maxframe = creAnims[ID]->framesInGroup(attackingInfo->shootingGroup);
}
void CBattleInterface::battleFinished(const BattleResult& br)
{
CGI->curh->changeGraphic(0,0);
SDL_Rect temp_rect = genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19);
resWindow = new CBattleReslutWindow(br, temp_rect, this);
LOCPLINT->pushInt(resWindow);
}
void CBattleInterface::spellCasted(SpellCasted * sc)
{
if(sc->side == !LOCPLINT->cb->battleGetStackByID(activeStack)->attackerOwned)
bSpell->block(true);
std::vector< std::string > anims; //for magic arrow and ice bolt
switch(sc->id)
{
case 15: //magic arrow
{
//initialization of anims
anims.push_back("C20SPX0.DEF"); anims.push_back("C20SPX1.DEF"); anims.push_back("C20SPX2.DEF"); anims.push_back("C20SPX3.DEF"); anims.push_back("C20SPX4.DEF");
}
case 16: //ice bolt
{
if(anims.size() == 0) //initialiaztion of anims
{
anims.push_back("C08SPW0.DEF"); anims.push_back("C08SPW1.DEF"); anims.push_back("C08SPW2.DEF"); anims.push_back("C08SPW3.DEF"); anims.push_back("C08SPW4.DEF");
}
} //end of ice bolt only part
{ //common ice bolt and magic arrow part
//initial variables
std::string animToDisplay;
std::pair<int, int> srccoord = sc->side ? std::make_pair(770, 60) : std::make_pair(30, 60);
std::pair<int, int> destcoord = CBattleHex::getXYUnitAnim(sc->tile, !sc->side, LOCPLINT->cb->battleGetStackByPos(sc->tile)->creature); //position attacked by arrow
destcoord.first += 250; destcoord.second += 240;
//animation angle
float angle = atan2(float(destcoord.first - srccoord.first), float(destcoord.second - srccoord.second));
//choosing animation by angle
if(angle > 1.50)
animToDisplay = anims[0];
else if(angle > 1.20)
animToDisplay = anims[1];
else if(angle > 0.90)
animToDisplay = anims[2];
else if(angle > 0.60)
animToDisplay = anims[3];
else
animToDisplay = anims[4];
//displaying animation
int steps = sqrt((float)((destcoord.first - srccoord.first)*(destcoord.first - srccoord.first) + (destcoord.second - srccoord.second) * (destcoord.second - srccoord.second))) / 40;
if(steps <= 0)
steps = 1;
CDefHandler * animDef = CDefHandler::giveDef(animToDisplay);
int dx = (destcoord.first - srccoord.first - animDef->ourImages[0].bitmap->w)/steps, dy = (destcoord.second - srccoord.second - animDef->ourImages[0].bitmap->h)/steps;
SDL_Rect buf;
SDL_GetClipRect(screen, &buf);
SDL_SetClipRect(screen, &pos); //setting rect we can blit to
for(int g=0; g<steps; ++g)
{
show(screen);
SDL_Rect & srcr = animDef->ourImages[g%animDef->ourImages.size()].bitmap->clip_rect;
SDL_Rect dstr = genRect(srcr.h, srcr.w, srccoord.first + g*dx, srccoord.second + g*dy);
SDL_BlitSurface(animDef->ourImages[g%animDef->ourImages.size()].bitmap, &srcr, screen, &dstr);
CSDL_Ext::update(screen);
SDL_framerateDelay(LOCPLINT->mainFPSmng);
}
SDL_SetClipRect(screen, &buf); //restoring previous clip rect
break; //for 15 and 16 cases
}
}
}
void CBattleInterface::battleStacksEffectsSet(const SetStackEffect & sse)
{
for(std::set<ui32>::const_iterator ci = sse.stacks.begin(); ci!=sse.stacks.end(); ++ci)
{
displayEffect(spellToEffect[sse.effect.id], LOCPLINT->cb->battleGetStackByID(*ci)->position);
}
redrawBackgroundWithHexes(activeStack);
}
void CBattleInterface::castThisSpell(int spellID)
{
BattleAction * ba = new BattleAction;
ba->actionType = 1;
ba->additionalInfo = spellID; //spell number
ba->destinationTile = -1;
ba->stackNumber = (attackingHeroInstance->tempOwner == LOCPLINT->playerID) ? -1 : -2;
ba->side = defendingHeroInstance ? (LOCPLINT->playerID == defendingHeroInstance->tempOwner) : false;
spellToCast = ba;
spellDestSelectMode = true;
//choosing possible tragets
const CGHeroInstance * castingHero = (attackingHeroInstance->tempOwner == LOCPLINT->playerID) ? attackingHeroInstance : attackingHeroInstance;
spellSelMode = 0;
if(CGI->spellh->spells[spellID].attributes.find("CREATURE_TARGET") != std::string::npos) //spell to be cast on one specific creature
{
switch(CGI->spellh->spells[spellID].positiveness)
{
case -1 :
spellSelMode = 2;
break;
case 0:
spellSelMode = 3;
break;
case 1:
spellSelMode = 1;
break;
}
}
if(CGI->spellh->spells[spellID].attributes.find("CREATURE_TARGET_2") != std::string::npos) //spell to be cast on a specific creature but massive on expert
{
if(castingHero && castingHero->getSpellSecLevel(spellID) < 3)
{
switch(CGI->spellh->spells[spellID].positiveness)
{
case -1 :
spellSelMode = 2;
break;
case 0:
spellSelMode = 3;
break;
case 1:
spellSelMode = 1;
break;
}
}
else
{
spellSelMode = -1;
}
}
if(spellSelMode == -1) //user does not have to select location
{
spellToCast->destinationTile = -1;
LOCPLINT->cb->battleMakeAction(spellToCast);
delete spellToCast;
spellToCast = NULL;
spellDestSelectMode = false;
CGI->curh->changeGraphic(1, 6);
}
else
{
CGI->curh->changeGraphic(3, 0);
}
}
void CBattleInterface::displayEffect(ui32 effect, int destTile)
{
if(graphics->battleACToDef[effect].size() != 0)
{
SBattleEffect be;
be.anim = CDefHandler::giveDef(graphics->battleACToDef[effect][0]);
be.frame = 0;
be.maxFrame = be.anim->ourImages.size();
be.x = 22 * ( ((destTile/BFIELD_WIDTH) + 1)%2 ) + 44 * (destTile % BFIELD_WIDTH) + 45;
be.y = 105 + 42 * (destTile/BFIELD_WIDTH);
if(effect != 1 && effect != 0)
{
be.x -= be.anim->ourImages[0].bitmap->w/2;
be.y -= be.anim->ourImages[0].bitmap->h/2;
}
else if(effect == 1)
{
be.x -= be.anim->ourImages[0].bitmap->w;
be.y -= be.anim->ourImages[0].bitmap->h;
}
else if (effect == 0)
{
be.x -= be.anim->ourImages[0].bitmap->w/2;
be.y -= be.anim->ourImages[0].bitmap->h;
}
battleEffects.push_back(be);
}
//battleEffects
}
void CBattleInterface::setAnimSpeed(int set)
{
settings.animSpeed = set;
}
int CBattleInterface::getAnimSpeed() const
{
return settings.animSpeed;
}
float CBattleInterface::getAnimSpeedMultiplier() const
{
switch(settings.animSpeed)
{
case 1:
return 3.5f;
case 2:
return 2.2f;
case 4:
return 1.0f;
default:
return 0.0f;
}
}
void CBattleInterface::attackingShowHelper()
{
if(attackingInfo && !attackingInfo->reversing)
{
if(attackingInfo->frame == 0)
{
CStack aStack = *LOCPLINT->cb->battleGetStackByID(attackingInfo->ID); //attacking stack
if(attackingInfo->shooting)
{
creAnims[attackingInfo->ID]->setType(attackingInfo->shootingGroup);
}
else
{
if(aStack.creature->isDoubleWide())
{
switch(BattleInfo::mutualPosition(aStack.position+attackingInfo->posShiftDueToDist, attackingInfo->dest)) //attack direction
{
case 0:
creAnims[attackingInfo->ID]->setType(11);
break;
case 1:
creAnims[attackingInfo->ID]->setType(11);
break;
case 2:
creAnims[attackingInfo->ID]->setType(12);
break;
case 3:
creAnims[attackingInfo->ID]->setType(13);
break;
case 4:
creAnims[attackingInfo->ID]->setType(13);
break;
case 5:
creAnims[attackingInfo->ID]->setType(12);
break;
}
}
else //else for if(aStack.creature->isDoubleWide())
{
switch(BattleInfo::mutualPosition(aStack.position, attackingInfo->dest)) //attack direction
{
case 0:
creAnims[attackingInfo->ID]->setType(11);
break;
case 1:
creAnims[attackingInfo->ID]->setType(11);
break;
case 2:
creAnims[attackingInfo->ID]->setType(12);
break;
case 3:
creAnims[attackingInfo->ID]->setType(13);
break;
case 4:
creAnims[attackingInfo->ID]->setType(13);
break;
case 5:
creAnims[attackingInfo->ID]->setType(12);
break;
}
}
}
}
else if(attackingInfo->frame == (attackingInfo->maxframe - 1))
{
attackingInfo->reversing = true;
CStack* aStackp = LOCPLINT->cb->battleGetStackByID(attackingInfo->ID); //attacking stack
if(aStackp == NULL)
return;
CStack aStack = *aStackp;
if(aStack.attackerOwned)
{
if(aStack.creature->isDoubleWide())
{
switch(BattleInfo::mutualPosition(aStack.position, attackingInfo->dest)) //attack direction
{
case 0:
//reverseCreature(ID, aStack.position, true);
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
//reverseCreature(ID, aStack.position, true);
break;
case 5:
reverseCreature(attackingInfo->ID, aStack.position, true);
break;
case -1:
if(attackingInfo->posShiftDueToDist) //if reversing stack will make its position adjacent to dest
{
reverseCreature(attackingInfo->ID, aStack.position, true);
}
break;
}
}
else //else for if(aStack.creature->isDoubleWide())
{
switch(BattleInfo::mutualPosition(aStack.position, attackingInfo->dest)) //attack direction
{
case 0:
reverseCreature(attackingInfo->ID, aStack.position, true);
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
reverseCreature(attackingInfo->ID, aStack.position, true);
break;
case 5:
reverseCreature(attackingInfo->ID, aStack.position, true);
break;
}
}
}
else //if(aStack.attackerOwned)
{
if(aStack.creature->isDoubleWide())
{
switch(BattleInfo::mutualPosition(aStack.position, attackingInfo->dest)) //attack direction
{
case 0:
//reverseCreature(ID, aStack.position, true);
break;
case 1:
break;
case 2:
reverseCreature(attackingInfo->ID, aStack.position, true);
break;
case 3:
break;
case 4:
//reverseCreature(ID, aStack.position, true);
break;
case 5:
//reverseCreature(ID, aStack.position, true);
break;
case -1:
if(attackingInfo->posShiftDueToDist) //if reversing stack will make its position adjacent to dest
{
reverseCreature(attackingInfo->ID, aStack.position, true);
}
break;
}
}
else //else for if(aStack.creature->isDoubleWide())
{
switch(BattleInfo::mutualPosition(aStack.position, attackingInfo->dest)) //attack direction
{
case 0:
//reverseCreature(ID, aStack.position, true);
break;
case 1:
reverseCreature(attackingInfo->ID, aStack.position, true);
break;
case 2:
reverseCreature(attackingInfo->ID, aStack.position, true);
break;
case 3:
reverseCreature(attackingInfo->ID, aStack.position, true);
break;
case 4:
//reverseCreature(ID, aStack.position, true);
break;
case 5:
//reverseCreature(ID, aStack.position, true);
break;
}
}
}
attackingInfo->reversing = false;
creAnims[attackingInfo->ID]->setType(2);
delete attackingInfo;
attackingInfo = NULL;
}
if(attackingInfo)
{
attackingInfo->hitCount++;
if(attackingInfo->hitCount%(4/settings.animSpeed) == 0)
attackingInfo->frame++;
}
}
}
void CBattleInterface::redrawBackgroundWithHexes(int activeStack)
{
shadedHexes = LOCPLINT->cb->battleGetAvailableHexes(activeStack, true);
//preparating background graphic with hexes and shaded hexes
blitAt(background, 0, 0, backgroundWithHexes);
if(settings.printCellBorders)
CSDL_Ext::blit8bppAlphaTo24bpp(cellBorders, NULL, backgroundWithHexes, NULL);
if(settings.printStackRange)
{
for(size_t m=0; m<shadedHexes.size(); ++m) //rows
{
int i = shadedHexes[m]/BFIELD_WIDTH; //row
int j = shadedHexes[m]%BFIELD_WIDTH-1; //column
int x = 58 + (i%2==0 ? 22 : 0) + 44*j;
int y = 86 + 42 * i;
CSDL_Ext::blit8bppAlphaTo24bpp(cellShade, NULL, backgroundWithHexes, &genRect(cellShade->h, cellShade->w, x, y));
}
}
}
void CBattleInterface::printConsoleAttacked(int ID, int dmg, int killed, int IDby)
{
char tabh[200];
CStack attacker = *LOCPLINT->cb->battleGetStackByID(IDby);
CStack defender = *LOCPLINT->cb->battleGetStackByID(ID);
int end = sprintf(tabh, CGI->generaltexth->allTexts[attacker.amount > 1 ? 377 : 376].c_str(),
(attacker.amount > 1 ? attacker.creature->namePl.c_str() : attacker.creature->nameSing.c_str()),
dmg);
if(killed > 0)
{
if(killed > 1)
{
sprintf(tabh + end, CGI->generaltexth->allTexts[379].c_str(), killed, defender.creature->namePl.c_str());
}
else //killed == 1
{
sprintf(tabh + end, CGI->generaltexth->allTexts[378].c_str(), defender.creature->nameSing.c_str());
}
}
console->addText(std::string(tabh));
}
void CBattleInterface::projectileShowHelper(SDL_Surface * to)
{
if(to == NULL)
to = screen;
std::list< std::list<SProjectileInfo>::iterator > toBeDeleted;
for(std::list<SProjectileInfo>::iterator it=projectiles.begin(); it!=projectiles.end(); ++it)
{
if(it->animStartDelay>0)
{
--(it->animStartDelay);
continue;
}
SDL_Rect dst;
dst.h = idToProjectile[it->creID]->ourImages[it->frameNum].bitmap->h;
dst.w = idToProjectile[it->creID]->ourImages[it->frameNum].bitmap->w;
dst.x = it->x;
dst.y = it->y;
if(it->reverse)
{
SDL_Surface * rev = CSDL_Ext::rotate01(idToProjectile[it->creID]->ourImages[it->frameNum].bitmap);
CSDL_Ext::blit8bppAlphaTo24bpp(rev, NULL, to, &dst);
SDL_FreeSurface(rev);
}
else
{
CSDL_Ext::blit8bppAlphaTo24bpp(idToProjectile[it->creID]->ourImages[it->frameNum].bitmap, NULL, to, &dst);
}
//actualizing projectile
++it->step;
if(it->step == it->lastStep)
{
toBeDeleted.insert(toBeDeleted.end(), it);
}
else
{
it->x += it->dx;
it->y += it->dy;
if(it->spin)
{
++(it->frameNum);
it->frameNum %= idToProjectile[it->creID]->ourImages.size();
}
}
}
for(std::list< std::list<SProjectileInfo>::iterator >::iterator it = toBeDeleted.begin(); it!= toBeDeleted.end(); ++it)
{
projectiles.erase(*it);
}
}
void CBattleHero::show(SDL_Surface *to)
{
//animation of flag
if(flip)
{
CSDL_Ext::blit8bppAlphaTo24bpp(
flag->ourImages[flagAnim].bitmap,
NULL,
screen,
&genRect(
flag->ourImages[flagAnim].bitmap->h,
flag->ourImages[flagAnim].bitmap->w,
62 + pos.x,
39 + pos.y
)
);
}
else
{
CSDL_Ext::blit8bppAlphaTo24bpp(
flag->ourImages[flagAnim].bitmap,
NULL,
screen,
&genRect(
flag->ourImages[flagAnim].bitmap->h,
flag->ourImages[flagAnim].bitmap->w,
71 + pos.x,
39 + pos.y
)
);
}
++flagAnimCount;
if(flagAnimCount%4==0)
{
++flagAnim;
flagAnim %= flag->ourImages.size();
}
//animation of hero
int tick=-1;
for(int i=0; i<dh->ourImages.size(); ++i)
{
if(dh->ourImages[i].groupNumber==phase)
++tick;
if(tick==image)
{
SDL_Rect posb = pos;
CSDL_Ext::blit8bppAlphaTo24bpp(dh->ourImages[i].bitmap, NULL, to, &posb);
if(phase != 4 || nextPhase != -1 || image < 4)
{
if(flagAnimCount%2==0)
{
++image;
}
if(dh->ourImages[(i+1)%dh->ourImages.size()].groupNumber!=phase) //back to appropriate frame
{
image = 0;
}
}
if(phase == 4 && nextPhase != -1 && image == 7)
{
phase = nextPhase;
nextPhase = -1;
image = 0;
}
break;
}
}
}
void CBattleHero::activate()
{
ClickableL::activate();
}
void CBattleHero::deactivate()
{
ClickableL::deactivate();
}
void CBattleHero::setPhase(int newPhase)
{
if(phase != 4)
{
phase = newPhase;
image = 0;
}
else
{
nextPhase = newPhase;
}
}
void CBattleHero::clickLeft(boost::logic::tribool down)
{
if(!down && myHero) if(myHero->getArt(17)) //if both conditions are satisfied; for certain reason myHero->getArt(17) has been checked once even though myHero was NULL
{
for(int it=0; it<BFIELD_SIZE; ++it) //do nothing when any hex is hovered - hero's animation overlaps battlefield
{
if(myOwner->bfield[it].hovered && myOwner->bfield[it].strictHovered)
return;
}
CGI->curh->changeGraphic(0,0);
CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (conf.cc.resx - 620)/2, (conf.cc.resy - 595)/2), myHero);
LOCPLINT->pushInt(spellWindow);
}
}
CBattleHero::CBattleHero(const std::string & defName, int phaseG, int imageG, bool flipG, unsigned char player, const CGHeroInstance * hero, const CBattleInterface * owner): phase(phaseG), image(imageG), flip(flipG), flagAnim(0), myHero(hero), myOwner(owner), nextPhase(-1)
{
dh = CDefHandler::giveDef( defName );
for(int i=0; i<dh->ourImages.size(); ++i) //transforming images
{
if(flip)
{
SDL_Surface * hlp = CSDL_Ext::rotate01(dh->ourImages[i].bitmap);
SDL_FreeSurface(dh->ourImages[i].bitmap);
dh->ourImages[i].bitmap = hlp;
}
dh->ourImages[i].bitmap = CSDL_Ext::alphaTransform(dh->ourImages[i].bitmap);
}
dh->alphaTransformed = true;
if(flip)
flag = CDefHandler::giveDef("CMFLAGR.DEF");
else
flag = CDefHandler::giveDef("CMFLAGL.DEF");
//coloring flag and adding transparency
for(int i=0; i<flag->ourImages.size(); ++i)
{
flag->ourImages[i].bitmap = CSDL_Ext::alphaTransform(flag->ourImages[i].bitmap);
graphics->blueToPlayersAdv(flag->ourImages[i].bitmap, player);
}
}
CBattleHero::~CBattleHero()
{
delete dh;
delete flag;
}
std::pair<int, int> CBattleHex::getXYUnitAnim(const int & hexNum, const bool & attacker, const CCreature * creature)
{
std::pair<int, int> ret = std::make_pair(-500, -500); //returned value
ret.second = -139 + 42 * (hexNum/BFIELD_WIDTH); //counting y
//counting x
if(attacker)
{
ret.first = -160 + 22 * ( ((hexNum/BFIELD_WIDTH) + 1)%2 ) + 44 * (hexNum % BFIELD_WIDTH);
}
else
{
ret.first = -219 + 22 * ( ((hexNum/BFIELD_WIDTH) + 1)%2 ) + 44 * (hexNum % BFIELD_WIDTH);
}
//shifting position for double - hex creatures
if(creature && creature->isDoubleWide())
{
if(attacker)
{
ret.first -= 42;
}
else
{
ret.first += 42;
}
}
//returning
return ret;
}
void CBattleHex::activate()
{
Hoverable::activate();
MotionInterested::activate();
ClickableL::activate();
ClickableR::activate();
}
void CBattleHex::deactivate()
{
Hoverable::deactivate();
MotionInterested::deactivate();
ClickableL::deactivate();
ClickableR::deactivate();
}
void CBattleHex::hover(bool on)
{
hovered = on;
Hoverable::hover(on);
if(!on && setAlterText)
{
myInterface->console->alterTxt = std::string();
setAlterText = false;
}
}
CBattleHex::CBattleHex() : myNumber(-1), accesible(true), hovered(false), strictHovered(false), myInterface(NULL), setAlterText(false)
{
}
void CBattleHex::mouseMoved(const SDL_MouseMotionEvent &sEvent)
{
if(myInterface->cellShade)
{
if(CSDL_Ext::SDL_GetPixel(myInterface->cellShade, sEvent.x-pos.x, sEvent.y-pos.y) == 0) //hovered pixel is outside hex
{
strictHovered = false;
}
else //hovered pixel is inside hex
{
strictHovered = true;
}
}
if(hovered && strictHovered) //print attacked creature to console
{
if(myInterface->console->alterTxt.size() == 0 && LOCPLINT->cb->battleGetStack(myNumber) != -1 &&
LOCPLINT->cb->battleGetStackByPos(myNumber)->owner != LOCPLINT->playerID &&
LOCPLINT->cb->battleGetStackByPos(myNumber)->alive())
{
char tabh[160];
CStack attackedStack = *LOCPLINT->cb->battleGetStackByPos(myNumber);
const std::string & attackedName = attackedStack.amount == 1 ? attackedStack.creature->nameSing : attackedStack.creature->namePl;
sprintf(tabh, CGI->generaltexth->allTexts[220].c_str(), attackedName.c_str());
myInterface->console->alterTxt = std::string(tabh);
setAlterText = true;
}
}
else if(setAlterText)
{
myInterface->console->alterTxt = std::string();
setAlterText = false;
}
}
void CBattleHex::clickLeft(boost::logic::tribool down)
{
if(!down && hovered && strictHovered) //we've been really clicked!
{
myInterface->hexLclicked(myNumber);
}
}
void CBattleHex::clickRight(boost::logic::tribool down)
{
int stID = LOCPLINT->cb->battleGetStack(myNumber); //id of stack being on this tile
if(hovered && strictHovered && stID!=-1)
{
CStack myst = *LOCPLINT->cb->battleGetStackByID(stID); //stack info
if(!myst.alive()) return;
StackState *pom = NULL;
if(down)
{
pom = new StackState();
const CGHeroInstance *h = myst.owner == myInterface->attackingHeroInstance->tempOwner ? myInterface->attackingHeroInstance : myInterface->defendingHeroInstance;
if(h)
{
pom->attackBonus = h->getPrimSkillLevel(0);
pom->defenseBonus = h->getPrimSkillLevel(1);
pom->luck = myst.Luck();
pom->morale = myst.Morale();
pom->speedBonus = myst.Speed() - myst.creature->speed;
}
pom->shotsLeft = myst.shots;
for(int vb=0; vb<myst.effects.size(); ++vb)
{
pom->effects.insert(myst.effects[vb].id);
}
pom->currentHealth = myst.firstHPleft;
LOCPLINT->pushInt(new CCreInfoWindow(myst.creature->idNumber,0,myst.amount,pom,0,0,NULL));
}
delete pom;
}
}
CBattleConsole::CBattleConsole() : lastShown(-1), alterTxt(""), whoSetAlter(0)
{
}
CBattleConsole::~CBattleConsole()
{
texts.clear();
}
void CBattleConsole::show(SDL_Surface * to)
{
if(ingcAlter.size())
{
CSDL_Ext::printAtMiddleWB(ingcAlter, pos.x + pos.w/2, pos.y + 10, GEOR13, 80, zwykly, to);
}
else if(alterTxt.size())
{
CSDL_Ext::printAtMiddleWB(alterTxt, pos.x + pos.w/2, pos.y + 10, GEOR13, 80, zwykly, to);
}
else if(texts.size())
{
if(texts.size()==1)
{
CSDL_Ext::printAtMiddleWB(texts[0], pos.x + pos.w/2, pos.y + 10, GEOR13, 80, zwykly, to);
}
else
{
CSDL_Ext::printAtMiddleWB(texts[lastShown-1], pos.x + pos.w/2, pos.y + 10, GEOR13, 80, zwykly, to);
CSDL_Ext::printAtMiddleWB(texts[lastShown], pos.x + pos.w/2, pos.y + 26, GEOR13, 80, zwykly, to);
}
}
}
bool CBattleConsole::addText(const std::string & text)
{
if(text.size()>70)
return false; //text too long!
int firstInToken = 0;
for(int i=0; i<text.size(); ++i) //tokenize
{
if(text[i] == 10)
{
texts.push_back( text.substr(firstInToken, i-firstInToken) );
firstInToken = i+1;
}
}
texts.push_back( text.substr(firstInToken, text.size()) );
lastShown = texts.size()-1;
return true;
}
void CBattleConsole::eraseText(unsigned int pos)
{
if(pos < texts.size())
{
texts.erase(texts.begin() + pos);
if(lastShown == texts.size())
--lastShown;
}
}
void CBattleConsole::changeTextAt(const std::string & text, unsigned int pos)
{
if(pos >= texts.size()) //no such pos
return;
texts[pos] = text;
}
void CBattleConsole::scrollUp(unsigned int by)
{
if(lastShown > by)
lastShown -= by;
}
void CBattleConsole::scrollDown(unsigned int by)
{
if(lastShown + by < texts.size())
lastShown += by;
}
CBattleReslutWindow::CBattleReslutWindow(const BattleResult &br, const SDL_Rect & pos, const CBattleInterface * owner)
{
this->pos = pos;
background = BitmapHandler::loadBitmap("CPRESULT.BMP", true);
graphics->blueToPlayersAdv(background, LOCPLINT->playerID);
SDL_Surface * pom = SDL_ConvertSurface(background, screen->format, screen->flags);
SDL_FreeSurface(background);
background = pom;
exit = new AdventureMapButton (std::string(), std::string(), boost::bind(&CBattleReslutWindow::bExitf,this), 384 + pos.x, 505 + pos.y, "iok6432.def", SDLK_RETURN);
if(br.winner==0) //attacker won
{
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[410], 60, 122, GEOR13, zwykly, background);
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[411], 410, 122, GEOR13, zwykly, background);
}
else //if(br.winner==1)
{
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[411], 60, 122, GEOR13, zwykly, background);
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[410], 410, 122, GEOR13, zwykly, background);
}
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[407], 235, 299, GEOR16, tytulowy, background);
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[408], 235, 329, GEOR16, zwykly, background);
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[409], 235, 426, GEOR16, zwykly, background);
std::string attackerName, defenderName;
if(owner->attackingHeroInstance) //a hero attacked
{
SDL_BlitSurface(graphics->portraitLarge[owner->attackingHeroInstance->portrait], NULL, background, &genRect(64, 58, 21, 38));
//setting attackerName
attackerName = owner->attackingHeroInstance->name;
}
else //a monster attacked
{
int bestMonsterID = -1;
int bestPower = 0;
for(std::map<si32,std::pair<ui32,si32> >::const_iterator it = owner->army1->slots.begin(); it!=owner->army1->slots.end(); ++it)
{
if( CGI->creh->creatures[it->first].AIValue > bestPower)
{
bestPower = CGI->creh->creatures[it->first].AIValue;
bestMonsterID = it->first;
}
}
SDL_BlitSurface(graphics->bigImgs[bestMonsterID], NULL, background, &genRect(64, 58, 21, 38));
//setting attackerName
attackerName = CGI->creh->creatures[bestMonsterID].namePl;
}
if(owner->defendingHeroInstance) //a hero defended
{
SDL_BlitSurface(graphics->portraitLarge[owner->defendingHeroInstance->portrait], NULL, background, &genRect(64, 58, 391, 38));
//setting defenderName
defenderName = owner->defendingHeroInstance->name;
}
else //a monster defended
{
int bestMonsterID = -1;
int bestPower = 0;
for(std::map<si32,std::pair<ui32,si32> >::const_iterator it = owner->army2->slots.begin(); it!=owner->army2->slots.end(); ++it)
{
if( CGI->creh->creatures[it->second.first].AIValue > bestPower)
{
bestPower = CGI->creh->creatures[it->second.first].AIValue;
bestMonsterID = it->second.first;
}
}
SDL_BlitSurface(graphics->bigImgs[bestMonsterID], NULL, background, &genRect(64, 58, 391, 38));
//setting defenderName
defenderName = CGI->creh->creatures[bestMonsterID].namePl;
}
//printing attacker and defender's names
CSDL_Ext::printAtMiddle(attackerName, 156, 44, GEOR16, zwykly, background);
CSDL_Ext::printAtMiddle(defenderName, 314, 44, GEOR16, zwykly, background);
//printing casualities
for(int step = 0; step < 2; ++step)
{
if(br.casualties[step].size()==0)
{
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[523], 235, 360 + 97*step, GEOR16, zwykly, background);
}
else
{
int xPos = 235 - (br.casualties[step].size()*32 + (br.casualties[step].size() - 1)*10)/2; //increment by 42 with each picture
int yPos = 344 + step*97;
for(std::set<std::pair<ui32,si32> >::const_iterator it=br.casualties[step].begin(); it!=br.casualties[step].end(); ++it)
{
blitAt(graphics->smallImgs[it->first], xPos, yPos, background);
std::stringstream amount;
amount<<it->second;
CSDL_Ext::printAtMiddle(amount.str(), xPos+16, yPos + 42, GEOR13, zwykly, background);
xPos += 42;
}
}
}
//printing result description
bool weAreAttacker = (LOCPLINT->playerID == owner->attackingHeroInstance->tempOwner);
switch(br.result)
{
case 0: //normal victory
if((br.winner == 0 && weAreAttacker) || (br.winner == 1 && !weAreAttacker)) //we've won
{
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[304], 235, 235, GEOR13, zwykly, background);
}
else
{
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[311], 235, 235, GEOR13, zwykly, background);
}
break;
case 1: //flee
if((br.winner == 0 && weAreAttacker) || (br.winner == 1 && !weAreAttacker)) //we've won
{
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[303], 235, 235, GEOR13, zwykly, background);
}
else
{
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[310], 235, 235, GEOR13, zwykly, background);
}
break;
case 2: //surrender
if((br.winner == 0 && weAreAttacker) || (br.winner == 1 && !weAreAttacker)) //we've won
{
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[302], 235, 235, GEOR13, zwykly, background);
}
else
{
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[309], 235, 235, GEOR13, zwykly, background);
}
break;
}
}
CBattleReslutWindow::~CBattleReslutWindow()
{
SDL_FreeSurface(background);
}
void CBattleReslutWindow::activate()
{
LOCPLINT->showingDialog->set(true);
exit->activate();
}
void CBattleReslutWindow::deactivate()
{
exit->deactivate();
}
void CBattleReslutWindow::show(SDL_Surface *to)
{
//evaluating to
if(!to)
to = screen;
SDL_BlitSurface(background, NULL, to, &pos);
exit->show(to);
}
void CBattleReslutWindow::bExitf()
{
LOCPLINT->popInts(2); //first - we; second - battle interface
LOCPLINT->showingDialog->setn(false);
}
CBattleOptionsWindow::CBattleOptionsWindow(const SDL_Rect & position, CBattleInterface *owner): myInt(owner)
{
pos = position;
background = BitmapHandler::loadBitmap("comopbck.bmp", true);
graphics->blueToPlayersAdv(background, LOCPLINT->playerID);
viewGrid = new CHighlightableButton(boost::bind(&CBattleInterface::setPrintCellBorders, owner, true), boost::bind(&CBattleInterface::setPrintCellBorders, owner, false), boost::assign::map_list_of(0,CGI->generaltexth->zelp[427].first)(3,CGI->generaltexth->zelp[427].first), CGI->generaltexth->zelp[427].second, false, "sysopchk.def", NULL, 185, 140, false);
viewGrid->select(owner->settings.printCellBorders);
movementShadow = new CHighlightableButton(boost::bind(&CBattleInterface::setPrintStackRange, owner, true), boost::bind(&CBattleInterface::setPrintStackRange, owner, false), boost::assign::map_list_of(0,CGI->generaltexth->zelp[428].first)(3,CGI->generaltexth->zelp[428].first), CGI->generaltexth->zelp[428].second, false, "sysopchk.def", NULL, 185, 173, false);
movementShadow->select(owner->settings.printStackRange);
mouseShadow = new CHighlightableButton(boost::bind(&CBattleInterface::setPrintMouseShadow, owner, true), boost::bind(&CBattleInterface::setPrintMouseShadow, owner, false), boost::assign::map_list_of(0,CGI->generaltexth->zelp[429].first)(3,CGI->generaltexth->zelp[429].first), CGI->generaltexth->zelp[429].second, false, "sysopchk.def", NULL, 185, 207, false);
mouseShadow->select(owner->settings.printMouseShadow);
animSpeeds = new CHighlightableButtonsGroup(0);
animSpeeds->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[422].first),CGI->generaltexth->zelp[422].second, "sysopb9.def",188, 309, 1);
animSpeeds->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[423].first),CGI->generaltexth->zelp[423].second, "sysob10.def",252, 309, 2);
animSpeeds->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[424].first),CGI->generaltexth->zelp[424].second, "sysob11.def",315, 309, 4);
animSpeeds->select(owner->getAnimSpeed(), 1);
animSpeeds->onChange = boost::bind(&CBattleInterface::setAnimSpeed, owner, _1);
setToDefault = new AdventureMapButton (CGI->generaltexth->zelp[392].first, CGI->generaltexth->zelp[392].second, boost::bind(&CBattleOptionsWindow::bDefaultf,this), 405, 443, "codefaul.def");
std::swap(setToDefault->imgs[0][0], setToDefault->imgs[0][1]);
exit = new AdventureMapButton (CGI->generaltexth->zelp[393].first, CGI->generaltexth->zelp[393].second, boost::bind(&CBattleOptionsWindow::bExitf,this), 516, 443, "soretrn.def",SDLK_RETURN);
std::swap(exit->imgs[0][0], exit->imgs[0][1]);
//printing texts to background
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[392], 240, 32, GEOR16, tytulowy, background); //window title
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[393], 122, 211, GEOR16, tytulowy, background); //animation speed
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[394], 122, 292, GEOR16, tytulowy, background); //music volume
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[395], 122, 358, GEOR16, tytulowy, background); //effects' volume
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[396], 353, 64, GEOR16, tytulowy, background); //auto - combat options
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[397], 353, 264, GEOR16, tytulowy, background); //creature info
//auto - combat options
CSDL_Ext::printAt(CGI->generaltexth->allTexts[398], 283, 87, GEOR16, zwykly, background); //creatures
CSDL_Ext::printAt(CGI->generaltexth->allTexts[399], 283, 117, GEOR16, zwykly, background); //spells
CSDL_Ext::printAt(CGI->generaltexth->allTexts[400], 283, 147, GEOR16, zwykly, background); //catapult
CSDL_Ext::printAt(CGI->generaltexth->allTexts[151], 283, 177, GEOR16, zwykly, background); //ballista
CSDL_Ext::printAt(CGI->generaltexth->allTexts[401], 283, 207, GEOR16, zwykly, background); //first aid tent
//creature info
CSDL_Ext::printAt(CGI->generaltexth->allTexts[402], 283, 286, GEOR16, zwykly, background); //all stats
CSDL_Ext::printAt(CGI->generaltexth->allTexts[403], 283, 316, GEOR16, zwykly, background); //spells only
//general options
CSDL_Ext::printAt(CGI->generaltexth->allTexts[404], 61, 58, GEOR16, zwykly, background); //hex grid
CSDL_Ext::printAt(CGI->generaltexth->allTexts[405], 61, 91, GEOR16, zwykly, background); //movement shadow
CSDL_Ext::printAt(CGI->generaltexth->allTexts[406], 61, 124, GEOR16, zwykly, background); //cursor shadow
CSDL_Ext::printAt(CGI->generaltexth->allTexts[577], 61, 157, GEOR16, zwykly, background); //spellbook animation
//texts printed
}
CBattleOptionsWindow::~CBattleOptionsWindow()
{
SDL_FreeSurface(background);
delete setToDefault;
delete exit;
delete viewGrid;
delete movementShadow;
delete animSpeeds;
delete mouseShadow;
}
void CBattleOptionsWindow::activate()
{
setToDefault->activate();
exit->activate();
viewGrid->activate();
movementShadow->activate();
animSpeeds->activate();
mouseShadow->activate();
}
void CBattleOptionsWindow::deactivate()
{
setToDefault->deactivate();
exit->deactivate();
viewGrid->deactivate();
movementShadow->deactivate();
animSpeeds->deactivate();
mouseShadow->deactivate();
}
void CBattleOptionsWindow::show(SDL_Surface *to)
{
if(!to) //"evaluating" to
to = screen;
SDL_BlitSurface(background, NULL, to, &pos);
setToDefault->show(to);
exit->show(to);
viewGrid->show(to);
movementShadow->show(to);
animSpeeds->show(to);
mouseShadow->show(to);
}
void CBattleOptionsWindow::bDefaultf()
{
}
void CBattleOptionsWindow::bExitf()
{
LOCPLINT->popIntTotally(this);
}