mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
* correct handling of flying creatures in battles
* minor changes
This commit is contained in:
parent
329eab2f6a
commit
9eb6128b27
@ -466,7 +466,7 @@ void CBattleInterface::show(SDL_Surface * to)
|
||||
for(size_t v=0; v<stackAliveByHex[b].size(); ++v)
|
||||
{
|
||||
int animType = creAnims[stackAliveByHex[b][v]]->getType();
|
||||
bool incrementFrame = (animCount%(4/animSpeed)==0) && animType!=0 && animType!=5 && animType!=20 && animType!=21 && animType!=3 && animType!=2;
|
||||
bool incrementFrame = (animCount%(4/animSpeed)==0) && animType!=5 && animType!=20 && animType!=3 && animType!=2;
|
||||
if(animType == 2)
|
||||
{
|
||||
if(standingFrame.find(stackAliveByHex[b][v])!=standingFrame.end())
|
||||
@ -854,8 +854,9 @@ 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)
|
||||
//int firstFrame = creAnims[number]->getFrame();
|
||||
//for(int g=0; creAnims[number]->getFrame() != creAnims[number]->framesInGroup(8) + firstFrame - 1; ++g)
|
||||
while(!creAnims[number]->onLastFrameInGroup())
|
||||
{
|
||||
show();
|
||||
CSDL_Ext::update();
|
||||
@ -883,8 +884,9 @@ bool CBattleInterface::reverseCreature(int number, int hex, bool wideTrick)
|
||||
}
|
||||
|
||||
creAnims[number]->setType(7);
|
||||
firstFrame = creAnims[number]->getFrame();
|
||||
for(int g=0; creAnims[number]->getFrame() != creAnims[number]->framesInGroup(7) + firstFrame - 1; ++g)
|
||||
//firstFrame = creAnims[number]->getFrame();
|
||||
//for(int g=0; creAnims[number]->getFrame() != creAnims[number]->framesInGroup(7) + firstFrame - 1; ++g)
|
||||
while(!creAnims[number]->onLastFrameInGroup())
|
||||
{
|
||||
show();
|
||||
CSDL_Ext::update();
|
||||
@ -1006,7 +1008,7 @@ void CBattleInterface::stackActivated(int number)
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleInterface::stackMoved(int number, int destHex, bool endMoving)
|
||||
void CBattleInterface::stackMoved(int number, int destHex, bool endMoving, int distance)
|
||||
{
|
||||
bool startMoving = creAnims[number]->getType()==20;
|
||||
//a few useful variables
|
||||
@ -1014,6 +1016,10 @@ void CBattleInterface::stackMoved(int number, int destHex, bool endMoving)
|
||||
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)
|
||||
{
|
||||
@ -1027,78 +1033,102 @@ void CBattleInterface::stackMoved(int number, int destHex, bool endMoving)
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
switch(mutPos) //reverse unit if necessary
|
||||
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: case 4: case 5:
|
||||
if(creDir[number] == true)
|
||||
reverseCreature(number, curStackPos, twoTiles);
|
||||
case 0:
|
||||
stepX = (-1.0)*((float)hexWbase)/(2.0f*steps);
|
||||
stepY = (-1.0)*((float)hexHbase)/((float)steps);
|
||||
break;
|
||||
case 1: case 2: case 3:
|
||||
if(creDir[number] == false)
|
||||
reverseCreature(number, curStackPos, twoTiles);
|
||||
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;
|
||||
}
|
||||
//moving instructions
|
||||
float posX = creAnims[number]->pos.x, posY = creAnims[number]->pos.y; // for precise calculations ;]
|
||||
for(int i=0; i<steps; ++i)
|
||||
{
|
||||
switch(mutPos)
|
||||
{
|
||||
case 0:
|
||||
posX -= ((float)hexWbase)/(2.0f*steps);
|
||||
creAnims[number]->pos.x = posX;
|
||||
posY -= ((float)hexHbase)/((float)steps);
|
||||
creAnims[number]->pos.y = posY;
|
||||
break;
|
||||
case 1:
|
||||
posX += ((float)hexWbase)/(2.0f*steps);
|
||||
creAnims[number]->pos.x = posX;
|
||||
posY -= ((float)hexHbase)/((float)steps);
|
||||
creAnims[number]->pos.y = posY;
|
||||
break;
|
||||
case 2:
|
||||
posX += ((float)hexWbase)/((float)steps);
|
||||
creAnims[number]->pos.x = posX;
|
||||
break;
|
||||
case 3:
|
||||
posX += ((float)hexWbase)/(2.0f*steps);
|
||||
creAnims[number]->pos.x = posX;
|
||||
posY += ((float)hexHbase)/((float)steps);
|
||||
creAnims[number]->pos.y = posY;
|
||||
break;
|
||||
case 4:
|
||||
posX -= ((float)hexWbase)/(2.0f*steps);
|
||||
creAnims[number]->pos.x = posX;
|
||||
posY += ((float)hexHbase)/((float)steps);
|
||||
creAnims[number]->pos.y = posY;
|
||||
break;
|
||||
case 5:
|
||||
posX -= ((float)hexWbase)/((float)steps);
|
||||
creAnims[number]->pos.x = posX;
|
||||
break;
|
||||
}
|
||||
show();
|
||||
CSDL_Ext::update();
|
||||
SDL_framerateDelay(LOCPLINT->mainFPSmng);
|
||||
if((animCount+1)%(4/animSpeed)==0)
|
||||
creAnims[number]->incrementFrame();
|
||||
}
|
||||
}
|
||||
//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();
|
||||
CSDL_Ext::update();
|
||||
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)
|
||||
|
||||
//for(int i=0; i<creAnims[number]->framesInGroup(21)*getAnimSpeedMultiplier()-1; ++i)
|
||||
while(!creAnims[number]->onLastFrameInGroup())
|
||||
{
|
||||
show();
|
||||
CSDL_Ext::update();
|
||||
SDL_framerateDelay(LOCPLINT->mainFPSmng);
|
||||
if((animCount+1)%(4/animSpeed)==0)
|
||||
creAnims[number]->incrementFrame();
|
||||
}
|
||||
}
|
||||
creAnims[number]->setType(2); //resetting to default
|
||||
|
@ -249,7 +249,7 @@ public:
|
||||
void stackRemoved(CStack stack); //stack disappeared from batlefiled
|
||||
//void stackKilled(int ID, int dmg, int killed, int IDby, bool byShooting); //stack has been killed (but corpses remain)
|
||||
void stackActivated(int number); //active stack has been changed
|
||||
void stackMoved(int number, int destHex, bool endMoving); //stack with id number moved to destHex
|
||||
void stackMoved(int number, int destHex, bool endMoving, int distance); //stack with id number moved to destHex
|
||||
void stacksAreAttacked(std::vector<SStackAttackedInfo> attackedInfos); //called when a certain amount of stacks has been attacked
|
||||
void stackAttacking(int ID, int dest); //called when stack with id ID is attacking something on hex dest
|
||||
void newRound(int number); //caled when round is ended; number is the number of round
|
||||
|
@ -78,7 +78,7 @@ public:
|
||||
virtual void battleStackAttacked(BattleStackAttacked * bsa){}; //called when stack receives damage (after battleAttack())
|
||||
virtual void battleEnd(BattleResult *br){};
|
||||
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 battleStackMoved(int ID, int dest){};
|
||||
virtual void battleStackMoved(int ID, int dest, int distance){};
|
||||
virtual void battleSpellCasted(SpellCasted *sc){};
|
||||
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
|
||||
@ -95,7 +95,7 @@ public:
|
||||
virtual void yourTurn(){};
|
||||
virtual void heroKilled(const CGHeroInstance*){};
|
||||
virtual void heroCreated(const CGHeroInstance*){};
|
||||
virtual void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving){};
|
||||
virtual void battleStackMoved(int ID, int dest, int distance){};
|
||||
virtual void battleStackAttacking(int ID, int dest){};
|
||||
virtual void battleStackIsAttacked(int ID, int dmg, int killed, int IDby, bool byShooting){};
|
||||
virtual BattleAction activeStack(int stackID) {BattleAction ba; ba.actionType = 3; ba.stackNumber = stackID; return ba;};
|
||||
|
@ -333,6 +333,7 @@ signed char BattleInfo::mutualPosition(int hex1, int hex2)
|
||||
return 3;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::vector<int> BattleInfo::neighbouringTiles(int hex)
|
||||
{
|
||||
#define CHECK_AND_PUSH(tile) {int hlp = (tile); if(hlp>=0 && hlp<BFIELD_SIZE && (hlp%BFIELD_WIDTH!=16) && hlp%BFIELD_WIDTH) ret.push_back(hlp);}
|
||||
@ -346,12 +347,25 @@ std::vector<int> BattleInfo::neighbouringTiles(int hex)
|
||||
#undef CHECK_AND_PUSH
|
||||
return ret;
|
||||
}
|
||||
std::vector<int> BattleInfo::getPath(int start, int dest, bool*accessibility)
|
||||
std::pair< std::vector<int>, int > BattleInfo::getPath(int start, int dest, bool*accessibility, bool flyingCreature)
|
||||
{
|
||||
int predecessor[BFIELD_SIZE]; //for getting the Path
|
||||
int dist[BFIELD_SIZE]; //calculated distances
|
||||
|
||||
makeBFS(start,accessibility,predecessor,dist);
|
||||
if(flyingCreature)
|
||||
{
|
||||
bool acc[BFIELD_SIZE]; //full accessibility table
|
||||
for(int b=0; b<BFIELD_SIZE; ++b) //initialization of acc
|
||||
{
|
||||
acc[b] = true;
|
||||
}
|
||||
|
||||
makeBFS(start, acc, predecessor, dist);
|
||||
}
|
||||
else
|
||||
{
|
||||
makeBFS(start, accessibility, predecessor, dist);
|
||||
}
|
||||
|
||||
//making the Path
|
||||
std::vector<int> path;
|
||||
@ -361,7 +375,8 @@ std::vector<int> BattleInfo::getPath(int start, int dest, bool*accessibility)
|
||||
path.push_back(curElem);
|
||||
curElem = predecessor[curElem];
|
||||
}
|
||||
return path;
|
||||
|
||||
return std::make_pair(path, dist[dest]);
|
||||
}
|
||||
|
||||
CStack::CStack(CCreature * C, int A, int O, int I, bool AO, int S)
|
||||
|
@ -118,7 +118,7 @@ struct DLL_EXPORT BattleInfo
|
||||
void getAccessibilityMap(bool *accessibility, int stackToOmmit=-1); //send pointer to at least 187 allocated bytes
|
||||
void getAccessibilityMapForTwoHex(bool *accessibility, bool atackerSide, int stackToOmmit=-1, bool addOccupiable = false); //send pointer to at least 187 allocated bytes
|
||||
void makeBFS(int start, bool*accessibility, int *predecessor, int *dists); //*accessibility must be prepared bool[187] array; last two pointers must point to the at least 187-elements int arrays - there is written result
|
||||
std::vector<int> getPath(int start, int dest, bool*accessibility);
|
||||
std::pair< std::vector<int>, int > getPath(int start, int dest, bool*accessibility, bool flyingCreature); //returned value: pair<path, length>; length may be different than number of elements in path since flying vreatures jump between distant hexes
|
||||
std::vector<int> getAccessibility(int stackID, bool addOccupiable); //returns vector of accessible tiles (taking into account the creature range)
|
||||
|
||||
bool isStackBlocked(int ID); //returns true if there is neighbouring enemy stack
|
||||
|
@ -2215,10 +2215,10 @@ void CPlayerInterface::battleResultQuited()
|
||||
LOCPLINT->showingDialog->setn(false);
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleStackMoved(int ID, int dest)
|
||||
void CPlayerInterface::battleStackMoved(int ID, int dest, int distance)
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
||||
battleInt->stackMoved(ID, dest, dest==curAction->destinationTile);
|
||||
battleInt->stackMoved(ID, dest, dest==curAction->destinationTile, distance);
|
||||
}
|
||||
void CPlayerInterface::battleSpellCasted(SpellCasted *sc)
|
||||
{
|
||||
|
@ -490,7 +490,7 @@ public:
|
||||
void battleEnd(BattleResult *br);
|
||||
void battleResultQuited();
|
||||
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 battleStackMoved(int ID, int dest);
|
||||
void battleStackMoved(int ID, int dest, int distance);
|
||||
void battleSpellCasted(SpellCasted *sc);
|
||||
void battleStackAttacked(BattleStackAttacked * bsa);
|
||||
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
|
||||
|
@ -520,9 +520,9 @@ void CClient::process(int what)
|
||||
*serv >> br;
|
||||
tlog5 << "Stack "<<br.stack <<" moves to the tile "<<br.tile<<std::endl;
|
||||
if(playerint.find(gs->curB->side1) != playerint.end())
|
||||
playerint[gs->curB->side1]->battleStackMoved(br.stack,br.tile);
|
||||
playerint[gs->curB->side1]->battleStackMoved(br.stack, br.tile, br.distance);
|
||||
if(playerint.find(gs->curB->side2) != playerint.end())
|
||||
playerint[gs->curB->side2]->battleStackMoved(br.stack,br.tile);
|
||||
playerint[gs->curB->side2]->battleStackMoved(br.stack, br.tile, br.distance);
|
||||
gs->apply(&br);
|
||||
break;
|
||||
}
|
||||
|
@ -520,11 +520,11 @@ struct BattleResult : public CPack<BattleResult>//3003
|
||||
|
||||
struct BattleStackMoved : public CPack<BattleStackMoved>//3004
|
||||
{
|
||||
ui32 stack, tile;
|
||||
ui32 stack, tile, distance;
|
||||
BattleStackMoved(){type = 3004;};
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & stack & tile;
|
||||
h & stack & tile & distance;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1574,15 +1574,31 @@ void CGameHandler::moveStack(int stack, int dest)
|
||||
//if(dists[dest] > curStack->creature->speed && !(stackAtEnd && dists[dest] == curStack->creature->speed+1)) //we can attack a stack if we can go to adjacent hex
|
||||
// return false;
|
||||
|
||||
std::vector<int> path = gs->curB->getPath(curStack->position,dest,accessibility);
|
||||
int tilesToMove = std::max((int)(path.size() - curStack->speed()), 0);
|
||||
for(int v=path.size()-1; v>=tilesToMove; --v)
|
||||
std::pair< std::vector<int>, int > path = gs->curB->getPath(curStack->position, dest, accessibility, curStack->creature->isFlying());
|
||||
if(curStack->creature->isFlying())
|
||||
{
|
||||
//inform clients about move
|
||||
BattleStackMoved sm;
|
||||
sm.stack = curStack->ID;
|
||||
sm.tile = path[v];
|
||||
sendAndApply(&sm);
|
||||
if(path.second <= curStack->speed() && path.first.size() > 0)
|
||||
{
|
||||
//inform clients about move
|
||||
BattleStackMoved sm;
|
||||
sm.stack = curStack->ID;
|
||||
sm.tile = path.first[0];
|
||||
sm.distance = path.second;
|
||||
sendAndApply(&sm);
|
||||
}
|
||||
}
|
||||
else //for non-flying creatures
|
||||
{
|
||||
int tilesToMove = std::max((int)(path.first.size() - curStack->speed()), 0);
|
||||
for(int v=path.first.size()-1; v>=tilesToMove; --v)
|
||||
{
|
||||
//inform clients about move
|
||||
BattleStackMoved sm;
|
||||
sm.stack = curStack->ID;
|
||||
sm.tile = path.first[v];
|
||||
sm.distance = path.second;
|
||||
sendAndApply(&sm);
|
||||
}
|
||||
}
|
||||
}
|
||||
CGameHandler::CGameHandler(void)
|
||||
|
Loading…
Reference in New Issue
Block a user