1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-03 13:01:33 +02:00

progress in battles

This commit is contained in:
mateuszb 2008-03-23 17:25:38 +00:00
parent ac82c2fe5a
commit d5a5a04811
11 changed files with 198 additions and 14 deletions

View File

@ -8,12 +8,13 @@
#include "hch\CDefHandler.h"
#include "CCallback.h"
#include "CGameState.h"
#include <queue>
extern SDL_Surface * screen;
SDL_Surface * CBattleInterface::cellBorder, * CBattleInterface::cellShade;
CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2)
: printCellBorders(true), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0)
: printCellBorders(true), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), activeStack(-1)
{
//initializing armies
this->army1 = army1;
@ -79,7 +80,14 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
int x = 14 + ((h/17)%2==0 ? 22 : 0) + 44*(h%17);
int y = 86 + 42 * (h/17);
bfield[h].pos = genRect(cellShade->h, cellShade->w, x, y);
bfield[h].accesible = true;
}
//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;
}
}
CBattleInterface::~CBattleInterface()
@ -142,6 +150,7 @@ void CBattleInterface::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;
@ -170,6 +179,15 @@ void CBattleInterface::show(SDL_Surface * to)
CSDL_Ext::blit8bppAlphaTo24bpp(cellShade, NULL, to, &genRect(cellShade->h, cellShade->w, x, y));
}
}
//showing selected unit's range
for(std::map<int, CCreatureAnimation*>::iterator j=creAnims.begin(); j!=creAnims.end(); ++j)
{
if(j->first == activeStack) //print range of selected unit //TODO: check if it is to be done
{
showRange(to, stacks[j->first].position, LOCPLINT->cb->battleGetCreature(j->first).speed);
break;
}
}
//showing menu background
blitAt(menu, 0, 556, to);
@ -191,11 +209,10 @@ void CBattleInterface::show(SDL_Surface * to)
defendingHero->show(to);
//showing units //a lot of work...
std::map<int, CStack> stacks = LOCPLINT->cb->battleGetStacks();
for(std::map<int, CCreatureAnimation*>::iterator j=creAnims.begin(); j!=creAnims.end(); ++j)
{
std::pair <int, int> coords = CBattleHex::getXYUnitAnim(stacks[j->first].position, stacks[j->first].owner == attackingHeroInstance->tempOwner);
j->second->nextFrame(to, coords.first, coords.second, stacks[j->first].owner == attackingHeroInstance->tempOwner, animCount%2==0);
j->second->nextFrame(to, coords.first, coords.second, stacks[j->first].owner == attackingHeroInstance->tempOwner, animCount%2==0, j->first==activeStack);
}
//units shown
@ -261,6 +278,67 @@ void CBattleInterface::stackRemoved(CStack stack)
creAnims.erase(stack.ID);
}
void CBattleInterface::stackActivated(int number)
{
activeStack = number;
}
void CBattleInterface::stackMoved(int number, int destHex)
{
}
void CBattleInterface::showRange(SDL_Surface * to, int initialPlace, int radius)
{
int dists[187]; //calculated distances
std::queue<int> hexq; //bfs queue
hexq.push(initialPlace);
for(int g=0; g<187; ++g)
dists[g] = 100000000;
dists[initialPlace] = 0;
while(!hexq.empty()) //bfs loop
{
int curHex = hexq.front();
hexq.pop();
if((curHex - 18 > 0) && bfield[curHex-18].accesible && (dists[curHex] + 1 < dists[curHex-18]) && (curHex-18)%17!=0 && (curHex-18)%17!=16) //top left
{
hexq.push(curHex - 18);
dists[curHex-18] = dists[curHex] + 1;
}
if((curHex - 17 > 0) && bfield[curHex-17].accesible && (dists[curHex] + 1 < dists[curHex-17]) && (curHex-17)%17!=0 && (curHex-17)%17!=16) //top right
{
hexq.push(curHex - 17);
dists[curHex-17] = dists[curHex] + 1;
}
if((curHex - 1 > 0) && bfield[curHex-1].accesible && (dists[curHex] + 1 < dists[curHex-1]) && (curHex-1)%17!=0 && (curHex-1)%17!=16) //left
{
hexq.push(curHex - 1);
dists[curHex-1] = dists[curHex] + 1;
}
if((curHex + 1 < 187) && bfield[curHex+1].accesible && (dists[curHex] + 1 < dists[curHex+1]) && (curHex+1)%17!=0 && (curHex+1)%17!=16) //right
{
hexq.push(curHex + 1);
dists[curHex+1] = dists[curHex] + 1;
}
if((curHex + 17 < 187) && bfield[curHex+17].accesible && (dists[curHex] + 1 < dists[curHex+17]) && (curHex+17)%17!=0 && (curHex+17)%17!=16) //bottom left
{
hexq.push(curHex + 17);
dists[curHex+17] = dists[curHex] + 1;
}
if((curHex + 18 < 187) && bfield[curHex+18].accesible && (dists[curHex] + 1 < dists[curHex+18]) && (curHex+18)%17!=0 && (curHex+18)%17!=16) //bottom right
{
hexq.push(curHex + 18);
dists[curHex+18] = dists[curHex] + 1;
}
}
for(int i=0; i<187; ++i)
{
if(dists[i]<=radius)
{
CSDL_Ext::blit8bppAlphaTo24bpp(CBattleInterface::cellShade, NULL, to, &bfield[i].pos);
}
}
}
void CBattleHero::show(SDL_Surface *to)
{
int tick=-1;

View File

@ -54,6 +54,8 @@ private:
CGHeroInstance * attackingHeroInstance, * defendingHeroInstance;
std::map< int, CCreatureAnimation * > creAnims; //animations of creatures from fighting armies (order like in BattleInfo's stacks)
unsigned char animCount;
int activeStack; //number of active stack; -1 - no one
void showRange(SDL_Surface * to, int initialPlace, int radius); //show helper funtion ot mark range of a unit
public:
CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2); //c-tor
@ -82,6 +84,8 @@ public:
void show(SDL_Surface * to);
//call-ins
void newStack(CStack stack);
void stackRemoved(CStack stack);
void newStack(CStack stack); //new stack appeared on battlefield
void stackRemoved(CStack stack); //stack disappeared from batlefiled
void stackActivated(int number); //active stack has been changed
void stackMoved(int number, int destHex); //stack with id number moved to destHex
};

View File

@ -550,6 +550,20 @@ std::map<int, CStack> CCallback::battleGetStacks()
return ret;
}
CCreature CCallback::battleGetCreature(int number)
{
return *(CGI->state->curB->stacks[number]->creature);
}
bool CCallback::battleMoveCreature(int ID, int dest)
{
//checking parameters
if(dest<0 || dest > 187 || ID<0 || ID>=CGI->state->curB->stacks.size())
return false;
return CGI->state->battleMoveCreatureStack(ID, dest); //everything finished successfully
}
int3 CScriptCallback::getPos(CGObjectInstance * ob)
{
return ob->pos;

View File

@ -100,6 +100,8 @@ public:
int battleGetPos(int stack); //returns position (tile ID) of stack
int battleMakeAction(Action* action);//perform action with an active stack (or custom action)
std::map<int, CStack> battleGetStacks(); //returns stacks on battlefield
CCreature battleGetCreature(int number); //returns type of creature by given number of stack
bool battleMoveCreature(int ID, int dest); //moves creature with id ID to dest if possible
//friends

View File

@ -50,6 +50,7 @@ public:
virtual void actionFinished(Action action){};//occurs AFTER every action taken by any stack or by the hero
virtual void activeStack(int stackID){}; //called when it's turn of that stack
virtual void battleEnd(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, std::vector<int> capturedArtifacts, int expForWinner, bool winner){};
virtual void battleStackMoved(int ID, int dest)=0;
//
};
@ -65,5 +66,6 @@ public:
virtual void yourTurn(){};
virtual void heroKilled(const CGHeroInstance*){};
virtual void heroCreated(const CGHeroInstance*){};
virtual void battleStackMoved(int ID, int dest){};
};
#endif //CGAMEINTERFACE_H

View File

@ -4,7 +4,7 @@
#include <algorithm>
#include "SDL_Thread.h"
#include "SDL_Extensions.h"
#include <queue>
class CMP_stack
@ -207,3 +207,79 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C
delete curB;
curB = NULL;
}
bool CGameState::battleMoveCreatureStack(int ID, int dest)
{
//initing necessary tables
bool accessibility[187]; //accesibility of hexes
for(int k=0; k<187; k++)
accessibility[k] = true;
for(int g=0; g<CGI->state->curB->stacks.size(); ++g)
{
accessibility[CGI->state->curB->stacks[g]->position] = false;
}
int predecessor[187]; //for getting the Path
for(int b=0; b<187; ++b)
predecessor[b] = -1;
//bfsing
int dists[187]; //calculated distances
std::queue<int> hexq; //bfs queue
hexq.push(CGI->state->curB->stacks[ID]->position);
for(int g=0; g<187; ++g)
dists[g] = 100000000;
dists[hexq.front()] = 0;
while(!hexq.empty()) //bfs loop
{
int curHex = hexq.front();
hexq.pop();
if((curHex - 18 > 0) && accessibility[curHex-18] && (dists[curHex] + 1 < dists[curHex-18]) && (curHex-18)%17!=0 && (curHex-18)%17!=16) //top left
{
hexq.push(curHex - 18);
dists[curHex-18] = dists[curHex] + 1;
predecessor[curHex-18] = curHex;
}
if((curHex - 17 > 0) && accessibility[curHex-17] && (dists[curHex] + 1 < dists[curHex-17]) && (curHex-17)%17!=0 && (curHex-17)%17!=16) //top right
{
hexq.push(curHex - 17);
dists[curHex-17] = dists[curHex] + 1;
predecessor[curHex-17] = curHex;
}
if((curHex - 1 > 0) && accessibility[curHex-1] && (dists[curHex] + 1 < dists[curHex-1]) && (curHex-1)%17!=0 && (curHex-1)%17!=16) //left
{
hexq.push(curHex - 1);
dists[curHex-1] = dists[curHex] + 1;
predecessor[curHex-1] = curHex;
}
if((curHex + 1 < 187) && accessibility[curHex+1] && (dists[curHex] + 1 < dists[curHex+1]) && (curHex+1)%17!=0 && (curHex+1)%17!=16) //right
{
hexq.push(curHex + 1);
dists[curHex+1] = dists[curHex] + 1;
predecessor[curHex+1] = curHex;
}
if((curHex + 17 < 187) && accessibility[curHex+17] && (dists[curHex] + 1 < dists[curHex+17]) && (curHex+17)%17!=0 && (curHex+17)%17!=16) //bottom left
{
hexq.push(curHex + 17);
dists[curHex+17] = dists[curHex] + 1;
predecessor[curHex+17] = curHex;
}
if((curHex + 18 < 187) && accessibility[curHex+18] && (dists[curHex] + 1 < dists[curHex+18]) && (curHex+18)%17!=0 && (curHex+18)%17!=16) //bottom right
{
hexq.push(curHex + 18);
dists[curHex+18] = dists[curHex] + 1;
predecessor[curHex+18] = curHex;
}
}
//following the Path
std::vector<int> path;
int curElem = dest;
while(curElem!=CGI->state->curB->stacks[ID]->position)
{
path.push_back(curElem);
curElem = predecessor[curElem];
}
for(int v=path.size()-1; v>=0; --v)
{
LOCPLINT->battleStackMoved(ID, path[v]);
}
return true;
}

View File

@ -87,6 +87,7 @@ private:
return NULL;
}
void battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CArmedInstance *hero1, CArmedInstance *hero2);
bool battleMoveCreatureStack(int ID, int dest);
public:
friend CCallback;
friend CPathfinder;;

View File

@ -1900,6 +1900,7 @@ void CPlayerInterface::actionFinished(Action action)//occurs AFTER every action
void CPlayerInterface::activeStack(int stackID) //called when it's turn of that stack
{
unsigned char showCount = 0;
((CBattleInterface*)curint)->stackActivated(stackID);
while(true)
{
++showCount;
@ -1934,6 +1935,11 @@ void CPlayerInterface::battleEnd(CCreatureSet * army1, CCreatureSet * army2, CGH
{
}
void CPlayerInterface::battleStackMoved(int ID, int dest)
{
dynamic_cast<CBattleInterface*>(curint)->stackMoved(ID, dest);
}
void CPlayerInterface::showComp(SComponent comp)
{
adventureInt->infoBar.showComp(&comp,4000);

View File

@ -318,6 +318,7 @@ public:
void actionFinished(Action action);//occurs AFTER every action taken by any stack or by the hero
void activeStack(int stackID); //called when it's turn of that stack
void battleEnd(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, std::vector<int> capturedArtifacts, int expForWinner, bool winner);
void battleStackMoved(int ID, int dest);
//-------------//

View File

@ -743,7 +743,7 @@ int CCreatureAnimation::readNormalNr (int pos, int bytCon, unsigned char * str,
return ret;
}
int CCreatureAnimation::nextFrame(SDL_Surface *dest, int x, int y, bool attacker, bool incrementFrame)
int CCreatureAnimation::nextFrame(SDL_Surface *dest, int x, int y, bool attacker, bool incrementFrame, bool yellowBorder)
{
if(dest->format->BytesPerPixel<3)
return -1; //not enough depth
@ -842,7 +842,7 @@ int CCreatureAnimation::nextFrame(SDL_Surface *dest, int x, int y, bool attacker
int yB = ftcp/(FullWidth+add) + y;
if(xB>=0 && yB>=0 && xB<dest->w && yB<dest->h)
{
putPixel(dest, xB + yB*dest->w, palette[FDef[BaseOffset+k]], FDef[BaseOffset+k]);
putPixel(dest, xB + yB*dest->w, palette[FDef[BaseOffset+k]], FDef[BaseOffset+k], yellowBorder);
}
ftcp++; //increment pos
if ((TotalRowLength+k+1)>=SpriteWidth)
@ -859,7 +859,7 @@ int CCreatureAnimation::nextFrame(SDL_Surface *dest, int x, int y, bool attacker
int yB = ftcp/(FullWidth+add) + y;
if(xB>=0 && yB>=0 && xB<dest->w && yB<dest->h)
{
putPixel(dest, xB + yB*dest->w, palette[SegmentType], SegmentType);
putPixel(dest, xB + yB*dest->w, palette[SegmentType], SegmentType, yellowBorder);
}
ftcp++; //increment pos
}
@ -931,7 +931,7 @@ CCreatureAnimation::~CCreatureAnimation()
delete [] RLEntries;
}
void CCreatureAnimation::putPixel(SDL_Surface * dest, const int & ftcp, const BMPPalette & color, const unsigned char & palc) const
void CCreatureAnimation::putPixel(SDL_Surface * dest, const int & ftcp, const BMPPalette & color, const unsigned char & palc, const bool & yellowBorder) const
{
if(palc!=0)
{
@ -942,13 +942,13 @@ void CCreatureAnimation::putPixel(SDL_Surface * dest, const int & ftcp, const BM
p[1] = color.G;
p[2] = color.R;
}
else if(palc == 6 || palc == 7) //dark yellow border
else if(yellowBorder && (palc == 6 || palc == 7)) //dark yellow border
{
p[0] = 0;
p[1] = 0xff;
p[2] = 0xff;
}
else if(palc == 5) //yellow border
else if(yellowBorder && (palc == 5)) //yellow border
{
p[0] = color.B;
p[1] = color.G;

View File

@ -82,7 +82,7 @@ private:
char id[2];
std::string defName, curDir;
int readNormalNr (int pos, int bytCon, unsigned char * str=NULL, bool cyclic=false);
void putPixel(SDL_Surface * dest, const int & ftcp, const BMPPalette & color, const unsigned char & palc) const;
void putPixel(SDL_Surface * dest, const int & ftcp, const BMPPalette & color, const unsigned char & palc, const bool & yellowBorder) const;
////////////
@ -97,7 +97,7 @@ public:
void setType(int type); //sets type of animation and cleares framecount
int getType() const; //returns type of animation
int nextFrame(SDL_Surface * dest, int x, int y, bool attacker, bool incrementFrame = true); //0 - success, any other - error //print next
int nextFrame(SDL_Surface * dest, int x, int y, bool attacker, bool incrementFrame = true, bool yellowBorder = false); //0 - success, any other - error //print next
};
#endif //CCREATUREHANDLER_H