1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Battles: attacking, shooting, killing.

This commit is contained in:
Michał W. Urbańczyk 2008-08-08 23:02:32 +00:00
parent 92971e0df0
commit 15ff21e84c
13 changed files with 268 additions and 232 deletions

View File

@ -461,6 +461,8 @@ void CBattleInterface::stackKilled(int ID, int dmg, int killed, int IDby, bool b
show();
CSDL_Ext::update();
SDL_framerateDelay(LOCPLINT->mainFPSmng);
if((animCount+1)%4)
creAnims[ID]->incrementFrame();
}
printConsoleAttacked(ID, dmg, killed, IDby);
@ -614,6 +616,8 @@ void CBattleInterface::stackIsAttacked(int ID, int dmg, int killed, int IDby, bo
show();
CSDL_Ext::update();
SDL_framerateDelay(LOCPLINT->mainFPSmng);
if((animCount+1)%4)
creAnims[ID]->incrementFrame();
}
creAnims[ID]->setType(2);
@ -680,22 +684,22 @@ void CBattleInterface::stackAttacking(int ID, int dest)
switch(BattleInfo::mutualPosition(aStack.position, dest)) //attack direction
{
case 0:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(10);
attackingInfo->maxframe = creAnims[ID]->framesInGroup(11);
break;
case 1:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(10);
attackingInfo->maxframe = creAnims[ID]->framesInGroup(11);
break;
case 2:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(11);
attackingInfo->maxframe = creAnims[ID]->framesInGroup(12);
break;
case 3:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(12);
attackingInfo->maxframe = creAnims[ID]->framesInGroup(13);
break;
case 4:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(12);
attackingInfo->maxframe = creAnims[ID]->framesInGroup(13);
break;
case 5:
attackingInfo->maxframe = creAnims[ID]->framesInGroup(11);
attackingInfo->maxframe = creAnims[ID]->framesInGroup(12);
break;
}
}
@ -705,12 +709,13 @@ void CBattleInterface::newRound(int number)
console->addText(CGI->generaltexth->allTexts[412]);
}
void CBattleInterface::giveCommand(ui8 action, ui16 tile, ui32 stack)
void CBattleInterface::giveCommand(ui8 action, ui16 tile, ui32 stack, si32 additional)
{
BattleAction * ba = new BattleAction(); //to be deleted by engine
BattleAction * ba = new BattleAction(); //is deleted in CPlayerInterface::activeStack()
ba->actionType = action;
ba->destinationTile = tile;
ba->stackNumber = stack;
ba->additionalInfo = additional;
givenCommand->setn(ba);
myTurn = false;
activeStack = -1;
@ -737,7 +742,16 @@ void CBattleInterface::hexLclicked(int whichOne)
}
else if(LOCPLINT->cb->battleGetStackByID(atCre)->owner != attackingHeroInstance->tempOwner) //attacking
{
giveCommand(6,whichOne,activeStack);
std::vector<int> n = BattleInfo::neighbouringTiles(whichOne);
for(int i=0;i<n.size();i++)
{
//TODO: now we are using first available tile, but in the future we should add possibility of choosing from which tile we want to attack
if(vstd::contains(shadedHexes,n[i]))
{
giveCommand(6,n[i],activeStack,whichOne);
return;
}
}
}
}
}
@ -1151,9 +1165,20 @@ void CBattleHex::mouseMoved(SDL_MouseMotionEvent &sEvent)
{
if(std::find(myInterface->shadedHexes.begin(),myInterface->shadedHexes.end(),myNumber) == myInterface->shadedHexes.end())
{
CGI->curh->changeGraphic(1,0);
CStack *shere = LOCPLINT->cb->battleGetStackByPos(myNumber);
if(shere)
{
if(shere->owner == LOCPLINT->playerID) //our stack
CGI->curh->changeGraphic(1,5);
else if(LOCPLINT->cb->battleGetStackByID(myInterface->activeStack)->creature->isShooting()) //we can shoot enemy
CGI->curh->changeGraphic(1,3);
else //unavailable enemy
CGI->curh->changeGraphic(1,0);
}
else //empty unavailable tile
CGI->curh->changeGraphic(1,0);
}
else
else //available tile
{
if(LOCPLINT->cb->battleGetStackByID(myInterface->activeStack)->creature->isFlying())
CGI->curh->changeGraphic(1,2);
@ -1199,6 +1224,7 @@ void CBattleHex::clickRight(boost::logic::tribool down)
if(hovered && strictHovered && stID!=-1)
{
CStack myst = *LOCPLINT->cb->battleGetStackByID(stID); //stack info
if(!myst.alive) return;
StackState *pom = NULL;
if(down)
{
@ -1210,6 +1236,7 @@ void CBattleHex::clickRight(boost::logic::tribool down)
pom->defenseBonus = h->primSkills[1];
pom->luck = h->getCurrentLuck();
pom->morale = h->getCurrentMorale();
pom->currentHealth = myst.firstHPleft;
}
(new CCreInfoWindow(myst.creature->idNumber,0,pom,boost::function<void()>(),boost::function<void()>()))
->activate();

View File

@ -112,7 +112,7 @@ private:
};
std::list<SProjectileInfo> projectiles;
void projectileShowHelper(SDL_Surface * to=NULL); //prints projectiles present on the battlefield
void giveCommand(ui8 action, ui16 tile, ui32 stack);
void giveCommand(ui8 action, ui16 tile, ui32 stack, si32 additional=-1);
public:
CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2); //c-tor
~CBattleInterface(); //d-tor

View File

@ -20,6 +20,7 @@ class CGObjectInstance;
class CCreatureSet;
class CArmedInstance;
struct BattleResult;
struct BattleAttack;
class CObstacle
{
int ID;
@ -61,13 +62,12 @@ 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(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 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 BattleAction activeStack(int stackID)=0; //called when it's turn of that stack
virtual void battleEnd(BattleResult *br){};
virtual void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving)=0;
virtual void battleStackAttacking(int ID, int dest)=0;
virtual void battleStackIsAttacked(int ID, int dmg, int killed, int IDby, bool byShooting)=0;
virtual void battleAttack(BattleAttack *ba){};
virtual void battleStackKilled(int ID, int dmg, int killed, int IDby, bool byShooting)=0;
//

View File

@ -405,6 +405,23 @@ void CGameState::apply(IPack * pack)
curB->getStack(br->stack)->position = br->tile;
break;
}
case 3005:
{
BattleStackAttacked *br = static_cast<BattleStackAttacked*>(pack);
CStack * at = curB->getStack(br->stackAttacked);
at->amount = br->newAmount;
at->firstHPleft = br->newHP;
at->alive = !br->killed();
break;
}
case 3006:
{
BattleAttack *br = static_cast<BattleAttack*>(pack);
mx->unlock();
apply(&br->bsa);
mx->lock();
break;
}
//case 1002://set hover name
// {
// SetHoverName * shn = static_cast<SetHoverName*>(pack);
@ -921,65 +938,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
}
bool CGameState::battleShootCreatureStack(int ID, int dest)
{/*
CStack * curStack = NULL;
for(int y=0; y<curB->stacks.size(); ++y)
{
if(curB->stacks[y]->ID == ID)
{
curStack = curB->stacks[y];
break;
}
}
if(!curStack)
return false;
int IDOfStackAtEnd = battleGetStack(dest);
int numberOfStackAtEnd = -1;
for(int v=0; v<curB->stacks.size(); ++v)
{
if(curB->stacks[v]->ID == IDOfStackAtEnd)
{
numberOfStackAtEnd = v;
break;
}
}
if(IDOfStackAtEnd == -1 || curB->stacks[numberOfStackAtEnd]->owner == curStack->owner || !curB->stacks[numberOfStackAtEnd]->alive)
return false;
LOCPLINT->battleStackIsShooting(ID, dest);
//counting dealt damage
int finalDmg = calculateDmg(curStack, curB->stacks[numberOfStackAtEnd]);
//applying damages
int cresKilled = finalDmg / curB->stacks[ID]->creature->hitPoints;
int damageFirst = finalDmg % curB->stacks[ID]->creature->hitPoints;
if( curB->stacks[numberOfStackAtEnd]->firstHPleft <= damageFirst )
{
curB->stacks[numberOfStackAtEnd]->amount -= 1;
curB->stacks[numberOfStackAtEnd]->firstHPleft += curB->stacks[numberOfStackAtEnd]->creature->hitPoints - damageFirst;
}
else
{
curB->stacks[numberOfStackAtEnd]->firstHPleft -= damageFirst;
}
int cresInstackBefore = curB->stacks[numberOfStackAtEnd]->amount;
curB->stacks[numberOfStackAtEnd]->amount -= cresKilled;
if(curB->stacks[numberOfStackAtEnd]->amount<=0) //stack killed
{
curB->stacks[numberOfStackAtEnd]->amount = 0;
LOCPLINT->battleStackKilled(curB->stacks[numberOfStackAtEnd]->ID, finalDmg, std::min(cresKilled, cresInstackBefore), ID, true);
curB->stacks[numberOfStackAtEnd]->alive = false;
}
else
{
LOCPLINT->battleStackIsAttacked(curB->stacks[numberOfStackAtEnd]->ID, finalDmg, std::min(cresKilled, cresInstackBefore), ID, true);
}
//damage applied*/
{
return true;
}
@ -990,7 +949,7 @@ int CGameState::battleGetStack(int pos)
if(curB->stacks[g]->position == pos ||
( curB->stacks[g]->creature->isDoubleWide() &&
( (curB->stacks[g]->attackerOwned && curB->stacks[g]->position-1 == pos) ||
(!curB->stacks[g]->attackerOwned && curB->stacks[g]->position+1 == pos)
(!curB->stacks[g]->attackerOwned && curB->stacks[g]->position-1 == pos)
)
)
)
@ -999,7 +958,7 @@ int CGameState::battleGetStack(int pos)
return -1;
}
int CGameState::calculateDmg(const CStack* attacker, const CStack* defender)
int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender)
{
int attackDefenseBonus = attacker->creature->attack - defender->creature->defence;
int damageBase = 0;
@ -1037,50 +996,4 @@ int CGameState::calculateDmg(const CStack* attacker, const CStack* defender)
}
return (float)damageBase * (float)attacker->amount * dmgBonusMultiplier;
}
std::vector<int> CGameState::battleGetRange(int ID)
{/*
std::vector<int> additionals;
//adding enemies' positions
for(int c=0; c<curB->stacks.size(); ++c)
{
if(curB->stacks[c]->alive && curB->stacks[c]->owner != owner)
{
for(int g=0; g<ret.size(); ++g)
{
if(CBattleHex::mutualPosition(ret[g], curB->stacks[c]->position) != -1)
{
additionals.push_back(curB->stacks[c]->position);
}
if(curB->stacks[c]->creature->isDoubleWide() && curB->stacks[c]->attackerOwned && CBattleHex::mutualPosition(ret[g], curB->stacks[c]->position-1) != -1)
{
additionals.push_back(curB->stacks[c]->position-1);
}
if(curB->stacks[c]->creature->isDoubleWide() && !curB->stacks[c]->attackerOwned && CBattleHex::mutualPosition(ret[g], curB->stacks[c]->position+1) != -1)
{
additionals.push_back(curB->stacks[c]->position+1);
}
}
}
}
for(int g=0; g<additionals.size(); ++g)
{
ret.push_back(additionals[g]);
}
std::sort(ret.begin(), ret.end());
std::vector<int>::iterator nend = std::unique(ret.begin(), ret.end());
std::vector<int> ret2;
for(std::vector<int>::iterator it = ret.begin(); it != nend; ++it)
{
ret2.push_back(*it);
}
return ret2;*/
return std::vector<int>();
}
}

View File

@ -73,6 +73,7 @@ struct DLL_EXPORT BattleInfo
static signed char mutualPosition(int hex1, int hex2); //returns info about mutual position of given hexes (-1 - they're distant, 0 - left top, 1 - right top, 2 - right, 3 - right bottom, 4 - left bottom, 5 - left)
static std::vector<int> neighbouringTiles(int hex);
static int calculateDmg(const CStack* attacker, const CStack* defender); //TODO: add additional conditions and require necessary data
};
class DLL_EXPORT CStack
@ -138,8 +139,6 @@ private:
bool battleAttackCreatureStack(int ID, int dest);
bool battleShootCreatureStack(int ID, int dest);
int battleGetStack(int pos); //returns ID of stack at given tile
static int calculateDmg(const CStack* attacker, const CStack* defender); //TODO: add additional conditions and require necessary data
std::vector<int> battleGetRange(int ID); //called by std::vector<int> CCallback::battleGetAvailableHexes(int ID);
public:
int getDate(int mode=0) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month

17
CMT.cpp
View File

@ -150,7 +150,22 @@ int main(int argc, _TCHAR* argv[])
THC std::cout<<"\tCallback and console: "<<pomtime.getDif()<<std::endl;
THC std::cout<<"Handlers initialization (together): "<<tmh.getDif()<<std::endl;
std::ofstream lll("client_log.txt");
CConnection *c = new CConnection("localhost","3030",NAME,lll);
CConnection *c=NULL;
while(!c)
{
try
{
std::cout << "Establishing connection...\t";
c = new CConnection("localhost","3030",NAME,lll);
std::cout << "done!" <<std::endl;
}
catch(...)
{
std::cout << "\nCannot establish connection! Retrying within 3 seconds" <<std::endl;
SDL_Delay(3000);
}
}
THC std::cout<<"\tConnecting to the server: "<<tmh.getDif()<<std::endl;
CClient cl(c,options);
boost::thread t(boost::bind(&CClient::run,&cl));

View File

@ -1076,10 +1076,10 @@ void CPlayerInterface::yourTurn()
}
for(int i=0;i<objsToBlit.size();i++)
objsToBlit[i]->show();
pim->unlock();
CGI->curh->draw1();
CSDL_Ext::update(screen);
CGI->curh->draw2();
pim->unlock();
SDL_framerateDelay(mainFPSmng);
}
adventureInt->hide();
@ -1969,14 +1969,14 @@ void CPlayerInterface::battleNewRound(int round) //called at the beggining of ea
dynamic_cast<CBattleInterface*>(curint)->newRound(round);
}
void CPlayerInterface::actionStarted(BattleAction action)//occurs BEFORE 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)->givenCommand = -1;
}
//void CPlayerInterface::actionStarted(BattleAction action)//occurs BEFORE 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)->givenCommand = -1;
//}
BattleAction CPlayerInterface::activeStack(int stackID) //called when it's turn of that stack
{
@ -2014,17 +2014,18 @@ void CPlayerInterface::battleStackMoved(int ID, int dest, bool startMoving, bool
boost::unique_lock<boost::mutex> un(*pim);
dynamic_cast<CBattleInterface*>(curint)->stackMoved(ID, dest, startMoving, endMoving);
}
void CPlayerInterface::battleStackAttacking(int ID, int dest)
void CPlayerInterface::battleAttack(BattleAttack *ba)
{
dynamic_cast<CBattleInterface*>(curint)->stackAttacking(ID, dest);
boost::unique_lock<boost::mutex> un(*pim);
if(ba->shot())
dynamic_cast<CBattleInterface*>(curint)->stackIsShooting(ba->stackAttacking,cb->battleGetPos(ba->bsa.stackAttacked));
else
dynamic_cast<CBattleInterface*>(curint)->stackAttacking( ba->stackAttacking, cb->battleGetPos(ba->bsa.stackAttacked) );
if(ba->killed())
dynamic_cast<CBattleInterface*>(curint)->stackKilled(ba->bsa.stackAttacked, ba->bsa.damageAmount, ba->bsa.killedAmount, ba->stackAttacking, ba->shot());
else
dynamic_cast<CBattleInterface*>(curint)->stackIsAttacked(ba->bsa.stackAttacked, ba->bsa.damageAmount, ba->bsa.killedAmount, ba->stackAttacking, ba->shot());
}
void CPlayerInterface::battleStackIsAttacked(int ID, int dmg, int killed, int IDby, bool byShooting)
{
dynamic_cast<CBattleInterface*>(curint)->stackIsAttacked(ID, dmg, killed, IDby, byShooting);
}
void CPlayerInterface::battleStackKilled(int ID, int dmg, int killed, int IDby, bool byShooting)
{
dynamic_cast<CBattleInterface*>(curint)->stackKilled(ID, dmg, killed, IDby, byShooting);
@ -2970,7 +2971,8 @@ CCreInfoWindow::CCreInfoWindow
int hlp = log10f(c->defence)+2;
pom[hlp-1] = ' '; pom[hlp] = '(';
SDL_itoa(c->defence+State->defenseBonus,pom+hlp+1,10);
pom[hlp+2+(int)log10f(State->defenseBonus+c->defence)] = ')';
hlp += 2+(int)log10f(State->defenseBonus+c->defence);
pom[hlp] = ')'; pom[hlp+1] = '\0';
}
printToWR(pom,276,80,GEOR13,zwykly,bitmap);
@ -2995,8 +2997,13 @@ CCreInfoWindow::CCreInfoWindow
SDL_itoa(c->hitPoints,pom,10);
printToWR(pom,276,137,GEOR13,zwykly,bitmap);
//remaining health - TODO: show during the battles
//printAt(CGI->preth->zelp[440].first,155,143,GEOR13,zwykly,bitmap);
//remaining health
if(State)
{
printAt(CGI->preth->zelp[440].first,155,143,GEOR13,zwykly,bitmap);
SDL_itoa(State->currentHealth,pom,10);
printToWR(pom,276,156,GEOR13,zwykly,bitmap);
}
//speed
printAt(CGI->preth->zelp[441].first,155,162,GEOR13,zwykly,bitmap);

View File

@ -336,13 +336,12 @@ public:
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
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(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 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
BattleAction activeStack(int stackID); //called when it's turn of that stack
void battleEnd(BattleResult *br);
void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving);
void battleStackAttacking(int ID, int dest);
void battleStackIsAttacked(int ID, int dmg, int killed, int IDby, bool byShooting);
void battleAttack(BattleAttack *ba);
void battleStackKilled(int ID, int dmg, int killed, int IDby, bool byShooting);
void battleStackIsShooting(int ID, int dest); //called when stack with id ID is shooting to hex dest

View File

@ -394,6 +394,14 @@ void CClient::process(int what)
gs->apply(&br);
break;
}
case 3006:
{
BattleAttack ba;
*serv >> ba;
gs->apply(&ba);
LOCPLINT->battleAttack(&ba);
break;
}
case 9999:
break;
default:

View File

@ -89,4 +89,20 @@ const int MAX_BUILDING_PER_TURN = 1;
delete e; \
}
namespace vstd
{
template <typename Container, typename Item>
bool contains(const Container & c, const Item &i)
{
return std::find(c.begin(),c.end(),i) != c.end();
}
template <typename Container, typename Item>
typename Container::iterator find(const Container & c, const Item &i)
{
return std::find(c.begin(),c.end(),i);
}
}
#endif //GLOBAL_H

View File

@ -304,7 +304,7 @@ struct BattleResult : public CPack<BattleResult>//3003
struct BattleStackMoved : public CPack<BattleStackMoved>//3004
{
ui32 stack, tile;
ui8 flags;
ui8 flags; // 1 - start moving, 2 - end moving
@ -323,6 +323,47 @@ struct BattleStackMoved : public CPack<BattleStackMoved>//3004
}
};
struct BattleStackAttacked : public CPack<BattleStackAttacked>//3005
{
ui32 stackAttacked;
ui32 newAmount, newHP, killedAmount, damageAmount;
ui8 flags; //1 - is stack killed
BattleStackAttacked(){flags = 0; type = 3005;};
bool killed() //if target stack was killed
{
return flags & 1;
}
template <typename Handler> void serialize(Handler &h, const int version)
{
h & stackAttacked & newAmount & newHP & flags & killedAmount & damageAmount;
}
};
struct BattleAttack : public CPack<BattleAttack>//3006
{
BattleStackAttacked bsa;
ui32 stackAttacking;
ui8 flags;
BattleAttack(){flags = 0; type = 3006;};
bool shot()//distance attack - decrease number of shots
{
return flags & 1;
}
bool killed() //if target stack was killed
{
return bsa.killed();
}
template <typename Handler> void serialize(Handler &h, const int version)
{
h & bsa & stackAttacking & flags;
}
};
struct ShowInInfobox : public CPack<ShowInInfobox> //107
{
ShowInInfobox(){type = 107;};

View File

@ -18,7 +18,9 @@
#include "boost/date_time/posix_time/posix_time_types.hpp" //no i/o just types
#include "../lib/VCMI_Lib.h"
#include "../lib/CondSh.h"
#ifndef _MSC_VER
#include <boost/thread/xtime.hpp>
#endif
extern bool end2;
#include "../lib/BattleAction.h"
#ifdef min
@ -335,7 +337,36 @@ void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile
//delete curB;
//curB = NULL;
}
void prepareAttack(BattleAttack &bat, CStack *att, CStack *def)
{
bat.stackAttacking = att->ID;
bat.bsa.stackAttacked = def->ID;
bat.bsa.damageAmount = BattleInfo::calculateDmg(att, def);//counting dealt damage
//applying damages
bat.bsa.killedAmount = bat.bsa.damageAmount / def->creature->hitPoints;
unsigned damageFirst = bat.bsa.damageAmount % def->creature->hitPoints;
if( def->firstHPleft <= damageFirst )
{
bat.bsa.killedAmount++;
bat.bsa.newHP = def->firstHPleft + def->creature->hitPoints - damageFirst;
}
else
{
bat.bsa.newHP = def->firstHPleft - damageFirst;
}
if(def->amount <= bat.bsa.killedAmount) //stack killed
{
bat.bsa.newAmount = 0;
bat.bsa.flags |= 1;
}
else
{
bat.bsa.newAmount = def->amount - bat.bsa.killedAmount;
}
}
void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
{
try
@ -585,80 +616,7 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
{
case 2: //walk
{
CStack *curStack = gs->curB->getStack(ba.stackNumber),
*stackAtEnd = gs->curB->getStackT(ba.destinationTile);
//initing necessary tables
bool accessibility[187];
if(curStack->creature->isDoubleWide())
{
gs->curB->getAccessibilityMapForTwoHex(accessibility,curStack->attackerOwned,curStack->ID);
//accessibility[curStack->attackerOwned ? curStack->position+1 : curStack->position-1]=true;//OUR second tile is for US accessible
}
else
gs->curB->getAccessibilityMap(accessibility,curStack->ID);
//accessibility[curStack->position] = true; //OUR tile is for US accessible
//if(!stackAtEnd && !accessibility[dest])
// return false;
//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,ba.destinationTile,accessibility);
int tilesToMove = std::max((int)path.size()-curStack->creature->speed, 0);
for(int v=path.size()-1; v>=tilesToMove; --v)
{
if(v!=0 || !stackAtEnd) //it's not the last step or the last tile is free
{
//inform clients about move
BattleStackMoved sm;
sm.stack = curStack->ID;
sm.tile = path[v];
if(v==path.size()-1)//move start - set flag
sm.flags |= 1;
if(v==0 || (stackAtEnd && v==1)) //move end - set flag
sm.flags |= 2;
sendAndApply(&sm);
}
else //if it's last step and we should attack unit at the end
{
//LOCPLINT->battleStackAttacking(ID, path[v]);
////counting dealt damage
//int finalDmg = calculateDmg(curStack, curB->stacks[numberOfStackAtEnd]);
////applying damages
//int cresKilled = finalDmg / curB->stacks[numberOfStackAtEnd]->creature->hitPoints;
//int damageFirst = finalDmg % curB->stacks[numberOfStackAtEnd]->creature->hitPoints;
//if( curB->stacks[numberOfStackAtEnd]->firstHPleft <= damageFirst )
//{
// curB->stacks[numberOfStackAtEnd]->amount -= 1;
// curB->stacks[numberOfStackAtEnd]->firstHPleft += curB->stacks[numberOfStackAtEnd]->creature->hitPoints - damageFirst;
//}
//else
//{
// curB->stacks[numberOfStackAtEnd]->firstHPleft -= damageFirst;
//}
//int cresInstackBefore = curB->stacks[numberOfStackAtEnd]->amount;
//curB->stacks[numberOfStackAtEnd]->amount -= cresKilled;
//if(curB->stacks[numberOfStackAtEnd]->amount<=0) //stack killed
//{
// curB->stacks[numberOfStackAtEnd]->amount = 0;
// LOCPLINT->battleStackKilled(curB->stacks[numberOfStackAtEnd]->ID, finalDmg, std::min(cresKilled, cresInstackBefore) , ID, false);
// curB->stacks[numberOfStackAtEnd]->alive = false;
//}
//else
//{
// LOCPLINT->battleStackIsAttacked(curB->stacks[numberOfStackAtEnd]->ID, finalDmg, std::min(cresKilled, cresInstackBefore), ID, false);
//}
//damage applied
}
}
//curB->stackActionPerformed = true;
//LOCPLINT->actionFinished(BattleAction());
moveStack(ba.stackNumber,ba.destinationTile);
break;
}
case 3: //defend
@ -677,13 +635,29 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
}
case 6: //walk or attack
{
//battleMoveCreatureStack(ba.stackNumber, ba.destinationTile);
//battleAttackCreatureStack(ba.stackNumber, ba.destinationTile);
moveStack(ba.stackNumber,ba.destinationTile);
CStack *curStack = gs->curB->getStack(ba.stackNumber),
*stackAtEnd = gs->curB->getStackT(ba.additionalInfo);
if((curStack->position != ba.destinationTile) || //we wasn't able to reach destination tile
(BattleInfo::mutualPosition(ba.destinationTile,ba.additionalInfo)<0) ) //destination tile is not neighbouring with enemy stack
return;
BattleAttack bat;
prepareAttack(bat,curStack,stackAtEnd);
sendAndApply(&bat);
break;
}
case 7: //shoot
{
//battleShootCreatureStack(ba.stackNumber, ba.destinationTile);
CStack *curStack = gs->curB->getStack(ba.stackNumber),
*destStack= gs->curB->getStackT(ba.destinationTile);
BattleAttack bat;
prepareAttack(bat,curStack,destStack);
bat.flags |= 1;
sendAndApply(&bat);
break;
}
}
@ -717,6 +691,39 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
end2 = true;
}
}
void CGameHandler::moveStack(int stack, int dest)
{
CStack *curStack = gs->curB->getStack(stack),
*stackAtEnd = gs->curB->getStackT(dest);
//initing necessary tables
bool accessibility[187];
if(curStack->creature->isDoubleWide())
gs->curB->getAccessibilityMapForTwoHex(accessibility,curStack->attackerOwned,curStack->ID);
else
gs->curB->getAccessibilityMap(accessibility,curStack->ID);
if((stackAtEnd && stackAtEnd->alive) || !accessibility[dest])
return;
//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->creature->speed, 0);
for(int v=path.size()-1; v>=tilesToMove; --v)
{
//inform clients about move
BattleStackMoved sm;
sm.stack = curStack->ID;
sm.tile = path[v];
if(v==path.size()-1) //move start - set flag
sm.flags |= 1;
if(v==0) //move end - set flag
sm.flags |= 2;
sendAndApply(&sm);
}
}
CGameHandler::CGameHandler(void)
{
gs = NULL;
@ -898,10 +905,13 @@ void CGameHandler::run()
{
boost::posix_time::time_duration p;
p= boost::posix_time::seconds(1);
#ifdef _MSC_VER
cTurn.timed_wait(lock,p);
#else
boost::xtime time={0,0};
time.sec = static_cast<boost::xtime::xtime_sec_t>(p.total_seconds());
cTurn.wait(lock);
//cTurn.timed_wait(lock,time);
cTurn.timed_wait(lock,time);
#endif
}
}
}

View File

@ -28,6 +28,7 @@ class CGameHandler
void handleCPPObjS(std::map<int,CCPPObjectScript*> * mapa, CCPPObjectScript * script);
void changePrimSkill(int ID, int which, int val, bool abs=false);
void moveStack(int stack, int dest);
void startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2); //use hero=NULL for no hero