1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-06 09:09:40 +02:00

Merged most of the changes from trunk.

Because of really huge amount of modifications here I've probably missed some minor stuff. I doubt if it's still compatible with gcc - some changes should be reapplied.
This commit is contained in:
Michał W. Urbańczyk
2008-08-02 15:08:03 +00:00
parent dc82232e70
commit cc7be20b07
79 changed files with 1635 additions and 721 deletions

View File

@@ -15,13 +15,15 @@
#include <queue>
#include <sstream>
const double M_PI = 3.14159265358979323846;
extern SDL_Surface * screen;
extern TTF_Font * GEOR13;
extern SDL_Color zwykly;
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), givenCommand(NULL), attackingInfo(NULL)
CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2)
: printCellBorders(true), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), activeStack(-1), givenCommand(NULL), attackingInfo(NULL), myTurn(false)
{
//initializing armies
this->army1 = army1;
@@ -61,7 +63,7 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
blitAt(background, 0, 0);
blitAt(menu, 0, 556);
CSDL_Ext::update();
//preparing buttons and console
bOptions = new AdventureMapButton (std::string(), std::string(), boost::bind(&CBattleInterface::bOptionsf,this), 3, 561, "icm003.def", false, NULL, false);
bSurrender = new AdventureMapButton (std::string(), std::string(), boost::bind(&CBattleInterface::bSurrenderf,this), 54, 561, "icm001.def", false, NULL, false);
@@ -78,7 +80,7 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
console->pos.y = 560;
console->pos.w = 406;
console->pos.h = 38;
//loading hero animations
if(hero1) // attacking hero
{
@@ -107,7 +109,7 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
for(int h=0; h<187; ++h)
{
bfield[h].myNumber = h;
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);
@@ -119,7 +121,31 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
{
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);
}
}
}
}
CBattleInterface::~CBattleInterface()
@@ -147,6 +173,9 @@ CBattleInterface::~CBattleInterface()
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;
}
void CBattleInterface::activate()
@@ -241,7 +270,7 @@ void CBattleInterface::show(SDL_Surface * to)
if(defendingHero)
defendingHero->show(to);
//showing units //a lot of work...
////showing units //a lot of work...
std::vector<int> stackAliveByHex[187];
//double loop because dead stacks should be printed first
for(std::map<int, CStack>::iterator j=stacks.begin(); j!=stacks.end(); ++j)
@@ -309,6 +338,7 @@ void CBattleInterface::show(SDL_Surface * to)
}
}
//units shown
projectileShowHelper(to);//showing projectiles
}
bool CBattleInterface::reverseCreature(int number, int hex, bool wideTrick)
@@ -404,8 +434,36 @@ void CBattleInterface::stackRemoved(CStack stack)
creAnims.erase(stack.ID);
}
void CBattleInterface::stackKilled(int ID, int dmg, int killed, int IDby)
void CBattleInterface::stackKilled(int ID, int dmg, int killed, int IDby, bool byShooting)
{
if(creAnims[ID]->getType() != 2)
{
return; //something went wrong
}
if(byShooting) //delay hit animation
{
CStack attacker = *LOCPLINT->cb->battleGetStackByID(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();
CSDL_Ext::update();
SDL_framerateDelay(LOCPLINT->mainFPSmng);
}
}
}
creAnims[ID]->setType(5); //death
for(int i=0; i<creAnims[ID]->framesInGroup(5)-1; ++i)
{
@@ -413,7 +471,7 @@ void CBattleInterface::stackKilled(int ID, int dmg, int killed, int IDby)
CSDL_Ext::update();
SDL_framerateDelay(LOCPLINT->mainFPSmng);
}
printConsoleAttacked(ID, dmg, killed, IDby);
}
@@ -421,6 +479,8 @@ void CBattleInterface::stackActivated(int number)
{
givenCommand = NULL;
activeStack = number;
shadedHexes = LOCPLINT->cb->battleGetAvailableHexes(number);
myTurn = true;
}
void CBattleInterface::stackMoved(int number, int destHex, bool startMoving, bool endMoving)
@@ -442,7 +502,7 @@ void CBattleInterface::stackMoved(int number, int destHex, bool startMoving, boo
int mutPos = CBattleHex::mutualPosition(curStackPos, destHex);
if(LOCPLINT->cb->battleGetCreature(number).isDoubleWide() &&
if(LOCPLINT->cb->battleGetCreature(number).isDoubleWide() &&
((creDir[number] && mutPos == 5) || (creDir[number] && mutPos == 0) || (creDir[number] && mutPos == 4))) //for special cases
{
switch(CBattleHex::mutualPosition(curStackPos, destHex)) //reverse unit if necessary
@@ -593,14 +653,42 @@ void CBattleInterface::stackMoved(int number, int destHex, bool startMoving, boo
reverseCreature(number, destHex);
//creDir[number] = (curs.owner == attackingHeroInstance->tempOwner);
}
std::pair <int, int> coords = CBattleHex::getXYUnitAnim(destHex, creDir[number], curs.creature);
creAnims[number]->pos.x = coords.first;
creAnims[number]->pos.y = coords.second;
}
void CBattleInterface::stackIsAttacked(int ID, int dmg, int killed, int IDby)
void CBattleInterface::stackIsAttacked(int ID, int dmg, int killed, int IDby, bool byShooting)
{
if(creAnims[ID]->getType() != 2)
{
return; //something went wrong
}
if(byShooting) //delay hit animation
{
CStack attacker = *LOCPLINT->cb->battleGetStackByID(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();
CSDL_Ext::update();
SDL_framerateDelay(LOCPLINT->mainFPSmng);
}
}
}
creAnims[ID]->setType(3); //getting hit
for(int i=0; i<creAnims[ID]->framesInGroup(3); ++i)
{
@@ -615,6 +703,10 @@ void CBattleInterface::stackIsAttacked(int ID, int dmg, int killed, int IDby)
void CBattleInterface::stackAttacking(int ID, int dest)
{
if(attackingInfo != NULL)
{
return; //something went wrong
}
CStack aStack = *LOCPLINT->cb->battleGetStackByID(ID); //attacking stack
if(aStack.creature->isDoubleWide())
{
@@ -664,54 +756,28 @@ void CBattleInterface::stackAttacking(int ID, int dest)
attackingInfo->frame = 0;
attackingInfo->ID = ID;
attackingInfo->reversing = false;
attackingInfo->shooting = false;
if(aStack.creature->isDoubleWide())
switch(CBattleHex::mutualPosition(aStack.position, dest)) //attack direction
{
switch(CBattleHex::mutualPosition(aStack.position, dest)) //attack direction
{
case 0:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(10);
break;
case 1:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(10);
break;
case 2:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(11);
break;
case 3:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(12);
break;
case 4:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(12);
break;
case 5:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(11);
break;
}
}
else //else for if(aStack.creature->isDoubleWide())
{
switch(CBattleHex::mutualPosition(aStack.position, dest)) //attack direction
{
case 0:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(10);
break;
case 1:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(10);
break;
case 2:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(11);
break;
case 3:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(12);
break;
case 4:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(12);
break;
case 5:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(11);
break;
}
case 0:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(10);
break;
case 1:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(10);
break;
case 2:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(11);
break;
case 3:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(12);
break;
case 4:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(12);
break;
case 5:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(11);
break;
}
}
@@ -724,6 +790,9 @@ void CBattleInterface::hexLclicked(int whichOne)
{
if((whichOne%17)!=0 && (whichOne%17)!=16) //if player is trying to attack enemey unit or move creature stack
{
if(!myTurn)
return; //we are not permit to do anything
int atCre = LOCPLINT->cb->battleGetStack(whichOne); //creature at destination tile; -1 if there is no one
//LOCPLINT->cb->battleGetCreature();
if(atCre==-1) //normal move action
@@ -734,6 +803,15 @@ void CBattleInterface::hexLclicked(int whichOne)
ba->stackNumber = activeStack;
givenCommand = ba;
}
else if(LOCPLINT->cb->battleGetStackByID(atCre)->owner != attackingHeroInstance->tempOwner
&& LOCPLINT->cb->battleCanShoot(activeStack, whichOne)) //shooting
{
BattleAction * ba = new BattleAction(); //to be deleted by engine
ba->actionType = 7;
ba->destinationTile = whichOne;
ba->stackNumber = activeStack;
givenCommand = ba;
}
else if(LOCPLINT->cb->battleGetStackByID(atCre)->owner != attackingHeroInstance->tempOwner) //attacking
{
BattleAction * ba = new BattleAction(); //to be deleted by engine
@@ -745,9 +823,80 @@ void CBattleInterface::hexLclicked(int whichOne)
}
}
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)/17), float(abs(dest - fromHex)%17));
if(fromHex < dest)
projectileAngle = -projectileAngle;
SProjectileInfo spi;
spi.creID = LOCPLINT->cb->battleGetStackByID(ID)->creature->idNumber;
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 + 150 - 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 + 150 - 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;
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->ID = ID;
attackingInfo->reversing = false;
attackingInfo->shooting = true;
if(projectileAngle > straightAngle) //upper shot
attackingInfo->shootingGroup = 14;
else if(projectileAngle < -straightAngle) //lower shot
attackingInfo->shootingGroup = 15;
else //straight shot
attackingInfo->shootingGroup = 16;
attackingInfo->maxframe = creAnims[ID]->framesInGroup(attackingInfo->shootingGroup);
}
void CBattleInterface::showRange(SDL_Surface * to, int ID)
{
std::vector<int> shadedHexes = LOCPLINT->cb->battleGetAvailableHexes(ID);
for(int i=0; i<shadedHexes.size(); ++i)
{
CSDL_Ext::blit8bppAlphaTo24bpp(CBattleInterface::cellShade, NULL, to, &bfield[shadedHexes[i]].pos);
@@ -762,52 +911,59 @@ void CBattleInterface::attackingShowHelper()
if(attackingInfo->frame == 0)
{
CStack aStack = *LOCPLINT->cb->battleGetStackByID(attackingInfo->ID); //attacking stack
if(aStack.creature->isDoubleWide())
if(attackingInfo->shooting)
{
switch(CBattleHex::mutualPosition(aStack.position, attackingInfo->dest)) //attack direction
{
case 0:
creAnims[attackingInfo->ID]->setType(10);
break;
case 1:
creAnims[attackingInfo->ID]->setType(10);
break;
case 2:
creAnims[attackingInfo->ID]->setType(11);
break;
case 3:
creAnims[attackingInfo->ID]->setType(12);
break;
case 4:
creAnims[attackingInfo->ID]->setType(12);
break;
case 5:
creAnims[attackingInfo->ID]->setType(11);
break;
}
creAnims[attackingInfo->ID]->setType(attackingInfo->shootingGroup);
}
else //else for if(aStack.creature->isDoubleWide())
else
{
switch(CBattleHex::mutualPosition(aStack.position, attackingInfo->dest)) //attack direction
if(aStack.creature->isDoubleWide())
{
case 0:
creAnims[attackingInfo->ID]->setType(10);
break;
case 1:
creAnims[attackingInfo->ID]->setType(10);
break;
case 2:
creAnims[attackingInfo->ID]->setType(11);
break;
case 3:
creAnims[attackingInfo->ID]->setType(12);
break;
case 4:
creAnims[attackingInfo->ID]->setType(12);
break;
case 5:
creAnims[attackingInfo->ID]->setType(11);
break;
switch(CBattleHex::mutualPosition(aStack.position, attackingInfo->dest)) //attack direction
{
case 0:
creAnims[attackingInfo->ID]->setType(10);
break;
case 1:
creAnims[attackingInfo->ID]->setType(10);
break;
case 2:
creAnims[attackingInfo->ID]->setType(11);
break;
case 3:
creAnims[attackingInfo->ID]->setType(12);
break;
case 4:
creAnims[attackingInfo->ID]->setType(12);
break;
case 5:
creAnims[attackingInfo->ID]->setType(11);
break;
}
}
else //else for if(aStack.creature->isDoubleWide())
{
switch(CBattleHex::mutualPosition(aStack.position, attackingInfo->dest)) //attack direction
{
case 0:
creAnims[attackingInfo->ID]->setType(10);
break;
case 1:
creAnims[attackingInfo->ID]->setType(10);
break;
case 2:
creAnims[attackingInfo->ID]->setType(11);
break;
case 3:
creAnims[attackingInfo->ID]->setType(12);
break;
case 4:
creAnims[attackingInfo->ID]->setType(12);
break;
case 5:
creAnims[attackingInfo->ID]->setType(11);
break;
}
}
}
}
@@ -892,6 +1048,47 @@ void CBattleInterface::printConsoleAttacked(int ID, int dmg, int killed, int IDb
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;
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
@@ -935,7 +1132,7 @@ CBattleHero::CBattleHero(std::string defName, int phaseG, int imageG, bool flipG
if(flip)
{
SDL_Surface * hlp = CSDL_Ext::rotate01(dh->ourImages[i].bitmap);
SDL_FreeSurface(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);