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

* moving units and some minor improvements

This commit is contained in:
mateuszb 2008-03-29 10:59:18 +00:00
parent 137f62798b
commit fc4e0215fb
9 changed files with 143 additions and 78 deletions

View File

@ -14,7 +14,7 @@ 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), activeStack(-1)
: printCellBorders(true), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), activeStack(-1), curStackActed(false)
{
//initializing armies
this->army1 = army1;
@ -181,14 +181,8 @@ void CBattleInterface::show(SDL_Surface * to)
}
}
//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;
}
}
showRange(to, activeStack);
//showing menu background
blitAt(menu, 0, 556, to);
@ -281,75 +275,33 @@ void CBattleInterface::stackRemoved(CStack stack)
void CBattleInterface::stackActivated(int number)
{
curStackActed = false;
activeStack = number;
}
void CBattleInterface::stackMoved(int number, int destHex)
{
int curStackPos = LOCPLINT->cb->battleGetPos(number);
for(int i=0; i<6; ++i)
{
//creAnims[number]->setType(0);
}
}
void CBattleInterface::hexLclicked(int whichOne)
{
if((whichOne%17)!=0 && (whichOne%17)!=16)
{
LOCPLINT->cb->battleMoveCreature(activeStack, whichOne);
}
}
void CBattleInterface::showRange(SDL_Surface * to, int initialPlace, int radius)
void CBattleInterface::showRange(SDL_Surface * to, int ID)
{
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;
int curNext = -1; //for bfs loop only (helper var)
while(!hexq.empty()) //bfs loop
std::vector<int> shadedHexes = LOCPLINT->cb->battleGetAvailableHexes(ID);
for(int i=0; i<shadedHexes.size(); ++i)
{
int curHex = hexq.front();
hexq.pop();
curNext = curHex - ( (curHex/17)%2 ? 17 : 18 );
if((curNext > 0) && bfield[curNext].accesible && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top left
{
hexq.push(curNext);
dists[curNext] = dists[curHex] + 1;
}
curNext = curHex - ( (curHex/17)%2 ? 16 : 17 );
if((curNext > 0) && bfield[curNext].accesible && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top right
{
hexq.push(curNext);
dists[curNext] = dists[curHex] + 1;
}
curNext = curHex - 1;
if((curNext > 0) && bfield[curNext].accesible && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //left
{
hexq.push(curNext);
dists[curNext] = dists[curHex] + 1;
}
curNext = curHex + 1;
if((curNext < 187) && bfield[curNext].accesible && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //right
{
hexq.push(curNext);
dists[curNext] = dists[curHex] + 1;
}
curNext = curHex + ( (curHex/17)%2 ? 16 : 17 );
if((curNext < 187) && bfield[curNext].accesible && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom left
{
hexq.push(curNext);
dists[curNext] = dists[curHex] + 1;
}
curNext = curHex + ( (curHex/17)%2 ? 17 : 18 );
if((curNext < 187) && bfield[curNext].accesible && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom right
{
hexq.push(curNext);
dists[curNext] = dists[curHex] + 1;
}
}
for(int i=0; i<187; ++i)
{
if(dists[i]<=radius)
{
CSDL_Ext::blit8bppAlphaTo24bpp(CBattleInterface::cellShade, NULL, to, &bfield[i].pos);
}
CSDL_Ext::blit8bppAlphaTo24bpp(CBattleInterface::cellShade, NULL, to, &bfield[shadedHexes[i]].pos);
}
}

View File

@ -56,10 +56,10 @@ private:
CBattleHero * attackingHero, * defendingHero;
CCreatureSet * army1, * army2; //fighting armies
CGHeroInstance * attackingHeroInstance, * defendingHeroInstance;
std::map< int, CCreatureAnimation * > creAnims; //animations of creatures from fighting armies (order like in BattleInfo's stacks)
std::map< int, CCreatureAnimation * > creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
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
void showRange(SDL_Surface * to, int ID); //show helper funtion ot mark range of a unit
public:
CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2); //c-tor
@ -70,6 +70,7 @@ public:
CBattleHex bfield[187]; //11 lines, 17 hexes on each
std::vector< CBattleObstacle * > obstacles; //vector of obstacles on the battlefield
static SDL_Surface * cellBorder, * cellShade;
bool curStackActed; //true if we have i.e. moved current unit
//button handle funcs:
void bOptionsf();
@ -92,5 +93,6 @@ public:
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
void turnEnded(); //caled when current unit cannot get new orders
void hexLclicked(int whichOne); //hex only call-in
};

View File

@ -540,6 +540,15 @@ int CCallback::battleGetBattlefieldType()
return CGI->mh->ttiles[CGI->state->curB->tile.x][CGI->state->curB->tile.y][CGI->state->curB->tile.z].terType;
}
int CCallback::battleGetPos(int stack)
{
for(int g=0; g<CGI->state->curB->stacks.size(); ++g)
{
if(CGI->state->curB->stacks[g]->ID == stack)
return CGI->state->curB->stacks[g]->position;
}
}
std::map<int, CStack> CCallback::battleGetStacks()
{
std::map<int, CStack> ret;
@ -568,6 +577,11 @@ bool CCallback::battleMoveCreature(int ID, int dest)
return CGI->state->battleMoveCreatureStack(ID, dest); //everything finished successfully
}
std::vector<int> CCallback::battleGetAvailableHexes(int ID)
{
return CGI->state->battleGetRange(ID);
}
int3 CScriptCallback::getPos(CGObjectInstance * ob)
{
return ob->pos;

View File

@ -11,7 +11,7 @@ class CGObjectInstance;
class SComponent;
class IChosen;
class CSelectableComponent;
struct Action;
struct BattleAction;
typedef struct lua_State lua_State;
class ICallback
@ -98,10 +98,11 @@ public:
int battleGetObstaclesAtTile(int tile); //returns bitfield
int battleGetStack(int pos); //returns ID of stack on the tile
int battleGetPos(int stack); //returns position (tile ID) of stack
int battleMakeAction(Action* action);//perform action with an active stack (or custom action)
int battleMakeAction(BattleAction* 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
std::vector<int> battleGetAvailableHexes(int ID); //reutrns numbers of hexes reachable by creature with id ID
//friends

View File

@ -15,11 +15,11 @@ class CObstacle
int position;
//TODO: add some kind of the blockmap
};
struct Action
struct BattleAction
{
bool side; //who made this action: false - left, true - right player
int stackNumber;//stack ID, -1 left hero, -2 right hero,
int actionType; // 0 = Cancel Action 1 = Hero cast a spell 2 = Walk 3 = Defend 4 = Retreat from the battle 5 = Surrender 6 = Walk and Attack 7 = Shoot 8 = Wait 9 = Catapult 10 = Monster casts a spell (i.e. Faerie Dragons)
int actionType; // 0 = Cancel BattleAction 1 = Hero cast a spell 2 = Walk 3 = Defend 4 = Retreat from the battle 5 = Surrender 6 = Walk and Attack 7 = Shoot 8 = Wait 9 = Catapult 10 = Monster casts a spell (i.e. Faerie Dragons)
int destinationTile;
int additionalInfo; // e.g. spell number if type is 1 || 10
};
@ -46,8 +46,8 @@ public:
virtual void battleStart(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right
virtual void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles){}; //called when battlefield is prepared, prior the battle beginning
virtual void battleNewRound(int round){}; //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
virtual void actionStarted(Action action){};//occurs BEFORE every action taken by any stack or by the hero
virtual void actionFinished(Action action){};//occurs AFTER every action taken by any stack or by the hero
virtual void actionStarted(BattleAction action){};//occurs BEFORE every action taken by any stack or by the hero
virtual void actionFinished(BattleAction 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;

View File

@ -28,6 +28,7 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C
curB->side1=(hero1)?(hero1->tempOwner):(-1);
curB->side2=(hero2)?(hero2->tempOwner):(-1);
curB->round = -2;
curB->stackActionPerformed = false;
for(std::map<int,std::pair<CCreature*,int> >::iterator i = army1->slots.begin(); i!=army1->slots.end(); i++)
{
stacks.push_back(new CStack(i->second.first,i->second.second,0, stacks.size()));
@ -176,6 +177,7 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C
for(int i=0;i<stacks.size();i++)
{
curB->activeStack = i;
curB->stackActionPerformed = false;
if(stacks[i]->alive) //niech interfejs ruszy oddzialem
{
unsigned char owner = (stacks[i]->owner)?(hero2->tempOwner):(hero1->tempOwner);
@ -210,6 +212,9 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C
bool CGameState::battleMoveCreatureStack(int ID, int dest)
{
//first checks
if(curB->stackActionPerformed) //because unit cannot be moved more than once
return false;
//selecting moved stack
CStack * curStack = NULL;
for(int y=0; y<curB->stacks.size(); ++y)
@ -245,14 +250,14 @@ bool CGameState::battleMoveCreatureStack(int ID, int dest)
{
int curHex = hexq.front();
hexq.pop();
curNext = curHex - ( (curHex/17)%2 ? 17 : 18 );
curNext = curHex - ( (curHex/17)%2 ? 18 : 17 );
if((curNext > 0) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top left
{
hexq.push(curNext);
dists[curNext] = dists[curHex] + 1;
predecessor[curNext] = curHex;
}
curNext = curHex - ( (curHex/17)%2 ? 16 : 17 );
curNext = curHex - ( (curHex/17)%2 ? 17 : 16 );
if((curNext > 0) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top right
{
hexq.push(curNext);
@ -301,6 +306,94 @@ bool CGameState::battleMoveCreatureStack(int ID, int dest)
for(int v=path.size()-1; v>=0; --v)
{
LOCPLINT->battleStackMoved(ID, path[v]);
curStack->position = path[v];
}
curB->stackActionPerformed = true;
LOCPLINT->actionFinished(BattleAction());
return true;
}
std::vector<int> CGameState::battleGetRange(int ID)
{
int initialPlace=-1; //position of unit
int radius=-1; //range of unit
for(int g=0; g<curB->stacks.size(); ++g)
{
if(curB->stacks[g]->ID == ID)
{
initialPlace = curB->stacks[g]->position;
radius = curB->stacks[g]->creature->speed;
break;
}
}
bool accessibility[187]; //accesibility of hexes
for(int k=0; k<187; k++)
accessibility[k] = true;
for(int g=0; g<curB->stacks.size(); ++g)
{
accessibility[curB->stacks[g]->position] = false;
}
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;
int curNext = -1; //for bfs loop only (helper var)
while(!hexq.empty()) //bfs loop
{
int curHex = hexq.front();
hexq.pop();
curNext = curHex - ( (curHex/17)%2 ? 18 : 17 );
if((curNext > 0) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top left
{
hexq.push(curNext);
dists[curNext] = dists[curHex] + 1;
}
curNext = curHex - ( (curHex/17)%2 ? 17 : 16 );
if((curNext > 0) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top right
{
hexq.push(curNext);
dists[curNext] = dists[curHex] + 1;
}
curNext = curHex - 1;
if((curNext > 0) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //left
{
hexq.push(curNext);
dists[curNext] = dists[curHex] + 1;
}
curNext = curHex + 1;
if((curNext < 187) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //right
{
hexq.push(curNext);
dists[curNext] = dists[curHex] + 1;
}
curNext = curHex + ( (curHex/17)%2 ? 16 : 17 );
if((curNext < 187) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom left
{
hexq.push(curNext);
dists[curNext] = dists[curHex] + 1;
}
curNext = curHex + ( (curHex/17)%2 ? 17 : 18 );
if((curNext < 187) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom right
{
hexq.push(curNext);
dists[curNext] = dists[curHex] + 1;
}
}
std::vector<int> ret;
for(int i=0; i<187; ++i)
{
if(dists[i]<=radius)
{
ret.push_back(i);
}
}
return ret;
}

View File

@ -35,6 +35,7 @@ struct BattleInfo
CGHeroInstance *hero1, *hero2;
CCreatureSet * army1, * army2;
std::vector<CStack*> stacks;
bool stackActionPerformed; //true if current stack has been moved
};
class CStack
@ -88,6 +89,7 @@ private:
}
void battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CArmedInstance *hero1, CArmedInstance *hero2);
bool battleMoveCreatureStack(int ID, int dest);
std::vector<int> battleGetRange(int ID); //called by std::vector<int> CCallback::battleGetAvailableHexes(int ID);
public:
friend CCallback;
friend CPathfinder;;

View File

@ -1889,19 +1889,20 @@ void CPlayerInterface::battleNewRound(int round) //called at the beggining of ea
{
}
void CPlayerInterface::actionStarted(Action action)//occurs BEFORE every action taken by any stack or by the hero
void CPlayerInterface::actionStarted(BattleAction action)//occurs BEFORE every action taken by any stack or by the hero
{
}
void CPlayerInterface::actionFinished(Action action)//occurs AFTER every action taken by any stack or by the hero
void CPlayerInterface::actionFinished(BattleAction action)//occurs AFTER every action taken by any stack or by the hero
{
dynamic_cast<CBattleInterface*>(curint)->curStackActed = true;
}
void CPlayerInterface::activeStack(int stackID) //called when it's turn of that stack
{
unsigned char showCount = 0;
dynamic_cast<CBattleInterface*>(curint)->stackActivated(stackID);
while(true)
while(!dynamic_cast<CBattleInterface*>(curint)->curStackActed) //while current unit can perform an action
{
++showCount;
SDL_Event sEvent;

View File

@ -314,8 +314,8 @@ public:
void battleStart(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, tribool side); //called by engine when battle starts; side=0 - left, side=1 - right
void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles); //called when battlefield is prepared, prior the battle beginning
void battleNewRound(int round); //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
void actionStarted(Action action);//occurs BEFORE every action taken by any stack or by the hero
void actionFinished(Action action);//occurs AFTER every action taken by any stack or by the hero
void actionStarted(BattleAction action);//occurs BEFORE every action taken by any stack or by the hero
void actionFinished(BattleAction 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);