From a5354271e226cfb5b12426f53ba95b2f5599109c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Mon, 4 Aug 2008 23:04:15 +0000 Subject: [PATCH] * improvements in battle support - moving creatures work though there are small graphic glitches * @neweagle - I've replaced in VCMI_Lib.h your #ifndef with #ifdef since you modification affected (and broke) compilation only on MSVC. Is it ok now? --- CCallback.cpp | 86 ++++----- CGameState.cpp | 389 +++++++++++++++------------------------- CGameState.h | 8 +- CPlayerInterface.cpp | 2 + client/Client.cpp | 16 +- lib/NetPacks.h | 22 +++ lib/VCMI_Lib.h | 2 +- server/CGameHandler.cpp | 78 +++++++- server/CGameHandler.h | 2 + 9 files changed, 303 insertions(+), 302 deletions(-) diff --git a/CCallback.cpp b/CCallback.cpp index d304b808b..eb60d1705 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -18,6 +18,7 @@ #include #include #include "lib/NetPacks.h" +#include #ifdef min #undef min #endif @@ -53,7 +54,7 @@ bool CCallback::moveHero(int ID, CPath * path, int idtype, int pathType) else //idtype==1; player<0 { - for(std::map::iterator j=CGI->state->players.begin(); j!=CGI->state->players.end(); ++j) + for(std::map::iterator j=gs->players.begin(); j!=gs->players.end(); ++j) { for (int i=0; i<(*j).second.heroes.size();i++) { @@ -264,10 +265,12 @@ const CGTownInstance * CCallback::getTownInfo(int val, bool mode) //mode = 0 -> } int CCallback::howManyHeroes() { + boost::shared_lock lock(*gs->mx); return gs->players[player].heroes.size(); } const CGHeroInstance * CCallback::getHeroInfo(int player, int val, bool mode) //mode = 0 -> val = serial; mode = 1 -> val = ID { + boost::shared_lock lock(*gs->mx); if (gs->currentPlayer!=player) //TODO: checking if we are allowed to give that info return NULL; if (!mode) @@ -287,41 +290,22 @@ const CGHeroInstance * CCallback::getHeroInfo(int player, int val, bool mode) // int CCallback::getResourceAmount(int type) { + boost::shared_lock lock(*gs->mx); return gs->players[player].resources[type]; } std::vector CCallback::getResourceAmount() { + boost::shared_lock lock(*gs->mx); return gs->players[player].resources; } int CCallback::getDate(int mode) { + boost::shared_lock lock(*gs->mx); return gs->getDate(mode); - - - - - - - - - - - - - - - - - - - - - - - } std::vector < std::string > CCallback::getObjDescriptions(int3 pos) { + boost::shared_lock lock(*gs->mx); std::vector ret; BOOST_FOREACH(const CGObjectInstance * obj, gs->map->terrain[pos.x][pos.y][pos.z].blockingObjects) ret.push_back(obj->hoverName); @@ -362,17 +346,20 @@ bool CCallback::verifyPath(CPath * path, bool blockSea) std::vector< std::vector< std::vector > > & CCallback::getVisibilityMap() { + boost::shared_lock lock(*gs->mx); return gs->players[player].fogOfWarMap; } bool CCallback::isVisible(int3 pos, int Player) { + boost::shared_lock lock(*gs->mx); return gs->players[Player].fogOfWarMap[pos.x][pos.y][pos.z]; } std::vector < const CGTownInstance *> CCallback::getTownsInfo(bool onlyOur) { + boost::shared_lock lock(*gs->mx); std::vector < const CGTownInstance *> ret = std::vector < const CGTownInstance *>(); for ( std::map::iterator i=gs->players.begin() ; i!=gs->players.end();i++) { @@ -388,6 +375,7 @@ std::vector < const CGTownInstance *> CCallback::getTownsInfo(bool onlyOur) } std::vector < const CGHeroInstance *> CCallback::getHeroesInfo(bool onlyOur) { + boost::shared_lock lock(*gs->mx); std::vector < const CGHeroInstance *> ret; for(int i=0;imap->heroes.size();i++) { @@ -411,6 +399,7 @@ int CCallback::getMyColor() } int CCallback::getHeroSerial(const CGHeroInstance * hero) { + boost::shared_lock lock(*gs->mx); for (int i=0; iplayers[player].heroes.size();i++) { if (gs->players[player].heroes[i]==hero) @@ -432,9 +421,6 @@ const CCreatureSet* CCallback::getGarrison(const CGObjectInstance *obj) int CCallback::swapCreatures(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2) { if(s1->tempOwner != player || s2->tempOwner != player) - - - return -1; *cl->serv << ui16(502) << ui8(1) << s1->id << ui8(p1) << s2->id << ui8(p2); @@ -469,6 +455,7 @@ bool CCallback::dismissHero(const CGHeroInstance *hero) int CCallback::getMySerial() { + boost::shared_lock lock(*gs->mx); return gs->players[player].serial; } @@ -517,7 +504,8 @@ bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID) int CCallback::battleGetBattlefieldType() { - return CGI->mh->ttiles[CGI->state->curB->tile.x][CGI->state->curB->tile.y][CGI->state->curB->tile.z].tileInfo->tertype; + boost::shared_lock lock(*gs->mx); + return CGI->mh->ttiles[gs->curB->tile.x][gs->curB->tile.y][gs->curB->tile.z].tileInfo->tertype; } int CCallback::battleGetObstaclesAtTile(int tile) //returns bitfield @@ -527,17 +515,15 @@ int CCallback::battleGetObstaclesAtTile(int tile) //returns bitfield } int CCallback::battleGetStack(int pos) { - return CGI->state->battleGetStack(pos); + boost::shared_lock lock(*gs->mx); + return gs->battleGetStack(pos); } CStack* CCallback::battleGetStackByID(int ID) { - for(int g=0; gstate->curB->stacks.size(); ++g) - { - if(CGI->state->curB->stacks[g]->ID == ID) - return CGI->state->curB->stacks[g]; - } - return NULL; + boost::shared_lock lock(*gs->mx); + if(!gs->curB) return NULL; + return gs->curB->getStack(ID); } CStack* CCallback::battleGetStackByPos(int pos) @@ -547,30 +533,33 @@ CStack* CCallback::battleGetStackByPos(int pos) int CCallback::battleGetPos(int stack) { - for(int g=0; gstate->curB->stacks.size(); ++g) + boost::shared_lock lock(*gs->mx); + for(int g=0; gcurB->stacks.size(); ++g) { - if(CGI->state->curB->stacks[g]->ID == stack) - return CGI->state->curB->stacks[g]->position; + if(gs->curB->stacks[g]->ID == stack) + return gs->curB->stacks[g]->position; } return -1; } std::map CCallback::battleGetStacks() { + boost::shared_lock lock(*gs->mx); std::map ret; - for(int g=0; gstate->curB->stacks.size(); ++g) + for(int g=0; gcurB->stacks.size(); ++g) { - ret[CGI->state->curB->stacks[g]->ID] = *(CGI->state->curB->stacks[g]); + ret[gs->curB->stacks[g]->ID] = *(gs->curB->stacks[g]); } return ret; } CCreature CCallback::battleGetCreature(int number) { - for(int h=0; hstate->curB->stacks.size(); ++h) + boost::shared_lock lock(*gs->mx); + for(int h=0; hcurB->stacks.size(); ++h) { - if(CGI->state->curB->stacks[h]->ID == number) //creature found - return *(CGI->state->curB->stacks[h]->creature); + if(gs->curB->stacks[h]->ID == number) //creature found + return *(gs->curB->stacks[h]->creature); } #ifndef __GNUC__ throw new std::exception("Cannot find the creature"); @@ -581,20 +570,23 @@ CCreature CCallback::battleGetCreature(int number) std::vector CCallback::battleGetAvailableHexes(int ID) { - return CGI->state->battleGetRange(ID); + boost::shared_lock lock(*gs->mx); + return gs->battleGetRange(ID); } bool CCallback::battleIsStackMine(int ID) { - for(int h=0; hstate->curB->stacks.size(); ++h) + boost::shared_lock lock(*gs->mx); + for(int h=0; hcurB->stacks.size(); ++h) { - if(CGI->state->curB->stacks[h]->ID == ID) //creature found - return CGI->state->curB->stacks[h]->owner == player; + if(gs->curB->stacks[h]->ID == ID) //creature found + return gs->curB->stacks[h]->owner == player; } return false; } bool CCallback::battleCanShoot(int ID, int dest) //TODO: finish { + boost::shared_lock lock(*gs->mx); if(battleGetStackByID(ID)->creature->isShooting() && battleGetStack(dest) != -1 && battleGetStackByPos(dest)->owner != battleGetStackByID(ID)->owner diff --git a/CGameState.cpp b/CGameState.cpp index fbff5897a..6c945371c 100644 --- a/CGameState.cpp +++ b/CGameState.cpp @@ -86,6 +86,140 @@ CGObjectInstance * createObject(int id, int subid, int3 pos, int owner) //} return nobj; } +CStack * BattleInfo::getStack(int stackID) +{ + for(int g=0; gID == stackID) + return stacks[g]; + } + return NULL; +} +CStack * BattleInfo::getStackT(int tileID) +{ + for(int g=0; gposition == tileID + || (stacks[g]->creature->isDoubleWide() && stacks[g]->attackerOwned && stacks[g]->position-1 == tileID) + || (stacks[g]->creature->isDoubleWide() && !stacks[g]->attackerOwned && stacks[g]->position+1 == tileID)) + { + if(stacks[g]->alive) + { + return stacks[g]; + } + } + } + return NULL; +} +void BattleInfo::getAccessibilityMap(bool *accessibility) +{ + memset(accessibility,1,187); //initialize array with trues + for(int g=0; galive) //we don't want to lock enemy's positions and this units' position + continue; + + accessibility[stacks[g]->position] = false; + if(stacks[g]->creature->isDoubleWide()) //if it's a double hex creature + { + if(stacks[g]->attackerOwned) + accessibility[stacks[g]->position-1] = false; + else + accessibility[stacks[g]->position+1] = false; + } + } +} +void BattleInfo::getAccessibilityMapForTwoHex(bool *accessibility, bool atackerSide) //send pointer to at least 187 allocated bytes +{ + bool mac[187]; + getAccessibilityMap(mac); + memcpy(accessibility,mac,187); + + for(int b=0; b<187; ++b) + { + if( mac[b] && !(atackerSide ? mac[b-1] : mac[b+1])) + { + accessibility[b] = false; + } + } + //removing accessibility for side hexes + for(int v=0; v<187; ++v) + if(atackerSide ? (v%17)==1 : (v%17)==15) + accessibility[v] = false; +} + +std::vector BattleInfo::getPath(int start, int dest, bool*accessibility) +{ + 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 hexq; //bfs queue + hexq.push(start); + for(int g=0; g<187; ++g) + dists[g] = 100000000; + dists[hexq.front()] = 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] || curNext==dest) && (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 ? 17 : 16 ); + if((curNext > 0) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top right + { + hexq.push(curNext); + dists[curNext] = dists[curHex] + 1; + predecessor[curNext] = curHex; + } + curNext = curHex - 1; + if((curNext > 0) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //left + { + hexq.push(curNext); + dists[curNext] = dists[curHex] + 1; + predecessor[curNext] = curHex; + } + curNext = curHex + 1; + if((curNext < 187) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //right + { + hexq.push(curNext); + dists[curNext] = dists[curHex] + 1; + predecessor[curNext] = curHex; + } + curNext = curHex + ( (curHex/17)%2 ? 16 : 17 ); + if((curNext < 187) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom left + { + hexq.push(curNext); + dists[curNext] = dists[curHex] + 1; + predecessor[curNext] = curHex; + } + curNext = curHex + ( (curHex/17)%2 ? 17 : 18 ); + if((curNext < 187) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom right + { + hexq.push(curNext); + dists[curNext] = dists[curHex] + 1; + predecessor[curNext] = curHex; + } + } + + //following the Path + std::vector path; + int curElem = dest; + while(curElem != start) + { + path.push_back(curElem); + curElem = predecessor[curElem]; + } + return path; +} + CStack::CStack(CCreature * C, int A, int O, int I, bool AO) :creature(C),amount(A),owner(O), alive(true), position(-1), ID(I), attackerOwned(AO), firstHPleft(C->hitPoints) { @@ -238,6 +372,13 @@ void CGameState::apply(IPack * pack) delete curB->stacks[i]; delete curB; curB = NULL; + break; + } + case 3004: + { + BattleStackMoved *br = static_cast(pack); + curB->getStack(br->stack)->position = br->tile; + break; } //case 1002://set hover name // { @@ -749,254 +890,6 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed) } } } -void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CArmedInstance *hero1, CArmedInstance *hero2) -{/* - curB = new BattleInfo(); - std::vector & stacks = (curB->stacks); - - curB->army1=army1; - curB->army2=army2; - curB->hero1=dynamic_cast(hero1); - curB->hero2=dynamic_cast(hero2); - curB->side1=(hero1)?(hero1->tempOwner):(-1); - curB->side2=(hero2)?(hero2->tempOwner):(-1); - curB->round = -2; - curB->stackActionPerformed = false; - for(std::map >::iterator i = army1->slots.begin(); i!=army1->slots.end(); i++) - { - stacks.push_back(new CStack(i->second.first,i->second.second,0, stacks.size(), true)); - stacks[stacks.size()-1]->ID = stacks.size()-1; - } - //initialization of positions - switch(army1->slots.size()) //for attacker - { - case 0: - break; - case 1: - stacks[0]->position = 86; //6 - break; - case 2: - stacks[0]->position = 35; //3 - stacks[1]->position = 137; //9 - break; - case 3: - stacks[0]->position = 35; //3 - stacks[1]->position = 86; //6 - stacks[2]->position = 137; //9 - break; - case 4: - stacks[0]->position = 1; //1 - stacks[1]->position = 69; //5 - stacks[2]->position = 103; //7 - stacks[3]->position = 171; //11 - break; - case 5: - stacks[0]->position = 1; //1 - stacks[1]->position = 35; //3 - stacks[2]->position = 86; //6 - stacks[3]->position = 137; //9 - stacks[4]->position = 171; //11 - break; - case 6: - stacks[0]->position = 1; //1 - stacks[1]->position = 35; //3 - stacks[2]->position = 69; //5 - stacks[3]->position = 103; //7 - stacks[4]->position = 137; //9 - stacks[5]->position = 171; //11 - break; - case 7: - stacks[0]->position = 1; //1 - stacks[1]->position = 35; //3 - stacks[2]->position = 69; //5 - stacks[3]->position = 86; //6 - stacks[4]->position = 103; //7 - stacks[5]->position = 137; //9 - stacks[6]->position = 171; //11 - break; - default: //fault - break; - } - for(std::map >::iterator i = army2->slots.begin(); i!=army2->slots.end(); i++) - stacks.push_back(new CStack(i->second.first,i->second.second,1, stacks.size(), false)); - switch(army2->slots.size()) //for defender - { - case 0: - break; - case 1: - stacks[0+army1->slots.size()]->position = 100; //6 - break; - case 2: - stacks[0+army1->slots.size()]->position = 49; //3 - stacks[1+army1->slots.size()]->position = 151; //9 - break; - case 3: - stacks[0+army1->slots.size()]->position = 49; //3 - stacks[1+army1->slots.size()]->position = 100; //6 - stacks[2+army1->slots.size()]->position = 151; //9 - break; - case 4: - stacks[0+army1->slots.size()]->position = 15; //1 - stacks[1+army1->slots.size()]->position = 83; //5 - stacks[2+army1->slots.size()]->position = 117; //7 - stacks[3+army1->slots.size()]->position = 185; //11 - break; - case 5: - stacks[0+army1->slots.size()]->position = 15; //1 - stacks[1+army1->slots.size()]->position = 49; //3 - stacks[2+army1->slots.size()]->position = 100; //6 - stacks[3+army1->slots.size()]->position = 151; //9 - stacks[4+army1->slots.size()]->position = 185; //11 - break; - case 6: - stacks[0+army1->slots.size()]->position = 15; //1 - stacks[1+army1->slots.size()]->position = 49; //3 - stacks[2+army1->slots.size()]->position = 83; //5 - stacks[3+army1->slots.size()]->position = 117; //7 - stacks[4+army1->slots.size()]->position = 151; //9 - stacks[5+army1->slots.size()]->position = 185; //11 - break; - case 7: - stacks[0+army1->slots.size()]->position = 15; //1 - stacks[1+army1->slots.size()]->position = 49; //3 - stacks[2+army1->slots.size()]->position = 83; //5 - stacks[3+army1->slots.size()]->position = 100; //6 - stacks[4+army1->slots.size()]->position = 117; //7 - stacks[5+army1->slots.size()]->position = 151; //9 - stacks[6+army1->slots.size()]->position = 185; //11 - break; - default: //fault - break; - } - for(int g=0; gposition%17)==1 && stacks[g]->creature->isDoubleWide()) - { - stacks[g]->position += 1; - } - else if((stacks[g]->position%17)==15 && stacks[g]->creature->isDoubleWide()) - { - stacks[g]->position -= 1; - } - } - std::stable_sort(stacks.begin(),stacks.end(),cmpst); - - //for start inform players about battle - for(std::map::iterator j=players.begin(); j!=players.end(); ++j)//->players.size(); ++j) //for testing - { - if (j->first > PLAYER_LIMIT) - break; - if(j->second.fogOfWarMap[tile.x][tile.y][tile.z]) - { //player should be notified - tribool side = tribool::indeterminate_value; - if(j->first == curB->side1) //player is attacker - side = false; - else if(j->first == curB->side2) //player is defender - side = true; - else - continue; //no witnesses - if(VLC->playerint[j->second.serial]->human) - { - ((CPlayerInterface*)( VLC->playerint[j->second.serial] ))->battleStart(army1, army2, tile, curB->hero1, curB->hero2, side); - } - else - { - //VLC->playerint[j->second.serial]->battleStart(army1, army2, tile, curB->hero1, curB->hero2, side); - } - } - } - - curB->round++; - if( (curB->hero1 && curB->hero1->getSecSkillLevel(19)>=0) || ( curB->hero2 && curB->hero2->getSecSkillLevel(19)>=0) )//someone has tactics - { - //TODO: wywolania dla rundy -1, ograniczenie pola ruchu, etc - } - - curB->round++; - - //SDL_Thread * eventh = SDL_CreateThread(battleEventThread, NULL); - - while(true) //till the end of the battle ;] - { - bool battleEnd = false; - //tell players about next round - for(int v=0; vplayerint.size(); ++v) - VLC->playerint[v]->battleNewRound(curB->round); - - //stack loop - for(int i=0;iactiveStack = i; - curB->stackActionPerformed = false; - if(stacks[i]->alive) //indicate posiibility of making action for this unit - { - unsigned char owner = (stacks[i]->owner)?(hero2 ? hero2->tempOwner : 255):(hero1->tempOwner); - unsigned char serialOwner = -1; - for(int g=0; gplayerint.size(); ++g) - { - if(VLC->playerint[g]->playerID == owner) - { - serialOwner = g; - break; - } - } - if(serialOwner==255) //neutral unit - { - } - else if(VLC->playerint[serialOwner]->human) - { - BattleAction ba = ((CPlayerInterface*)VLC->playerint[serialOwner])->activeStack(stacks[i]->ID); - switch(ba.actionType) - { - case 2: //walk - { - battleMoveCreatureStack(ba.stackNumber, ba.destinationTile); - } - case 3: //defend - { - break; - } - case 4: //retreat/flee - { - for(int v=0; vplayerint.size(); ++v) //tell about the end of this battle to interfaces - VLC->playerint[v]->battleEnd(army1, army2, hero1, hero2, std::vector(), 0, false); - battleEnd = true; - break; - } - case 6: //walk or attack - { - battleMoveCreatureStack(ba.stackNumber, ba.destinationTile); - battleAttackCreatureStack(ba.stackNumber, ba.destinationTile); - break; - } - case 7: //shoot - { - battleShootCreatureStack(ba.stackNumber, ba.destinationTile); - break; - } - } - } - else - { - //VLC->playerint[serialOwner]->activeStack(stacks[i]->ID); - } - } - if(battleEnd) - break; - //sprawdzic czy po tej akcji ktoras strona nie wygrala bitwy - } - if(battleEnd) - break; - curB->round++; - SDL_Delay(50); - } - - for(int i=0;i #include #ifdef _WIN32 @@ -61,6 +63,11 @@ struct DLL_EXPORT BattleInfo { h & side1 & side2 & round & activeStack & siege & tile & stacks & army1 & army2 & hero1 & hero2; } + CStack * getStack(int stackID); + CStack * getStackT(int tileID); + void getAccessibilityMap(bool *accessibility); //send pointer to at least 187 allocated bytes + void getAccessibilityMapForTwoHex(bool *accessibility, bool atackerSide); //send pointer to at least 187 allocated bytes + std::vector getPath(int start, int dest, bool*accessibility); }; class DLL_EXPORT CStack @@ -122,7 +129,6 @@ private: CGHeroInstance *getHero(int objid); - void battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CArmedInstance *hero1, CArmedInstance *hero2); bool battleMoveCreatureStack(int ID, int dest); bool battleAttackCreatureStack(int ID, int dest); bool battleShootCreatureStack(int ID, int dest); diff --git a/CPlayerInterface.cpp b/CPlayerInterface.cpp index 91f4fdca5..f77d3302a 100644 --- a/CPlayerInterface.cpp +++ b/CPlayerInterface.cpp @@ -1993,6 +1993,7 @@ BattleAction CPlayerInterface::activeStack(int stackID) //called when it's turn //tidy up BattleAction ret = *(b->givenCommand->data); delete b->givenCommand->data; + b->givenCommand->data = NULL; //return command return ret; @@ -2010,6 +2011,7 @@ void CPlayerInterface::battleEnd(BattleResult *br) void CPlayerInterface::battleStackMoved(int ID, int dest, bool startMoving, bool endMoving) { + boost::unique_lock un(*pim); dynamic_cast(curint)->stackMoved(ID, dest, startMoving, endMoving); } diff --git a/client/Client.cpp b/client/Client.cpp index 9208c7b32..c4bfaec6c 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -353,7 +353,7 @@ void CClient::process(int what) *serv >> sas; std::cout << "Active stack: " << sas.stack <apply(&sas); - boost::thread(boost::bind(&CClient::waitForMoveAndSend,this,gs->curB->stacks[sas.stack]->owner)); + boost::thread(boost::bind(&CClient::waitForMoveAndSend,this,gs->curB->getStack(sas.stack)->owner)); break; } case 3003: @@ -368,8 +368,18 @@ void CClient::process(int what) playerint[gs->curB->side2]->battleEnd(&br); gs->apply(&br); - - + break; + } + case 3004: + { + BattleStackMoved br; + *serv >> br; + std::cout << "Stack "<curB->side1) != playerint.end()) + playerint[gs->curB->side1]->battleStackMoved(br.stack,br.tile,br.flags&1,br.flags&2); + if(playerint.find(gs->curB->side2) != playerint.end()) + playerint[gs->curB->side2]->battleStackMoved(br.stack,br.tile,br.flags&1,br.flags&2); + gs->apply(&br); break; } case 9999: diff --git a/lib/NetPacks.h b/lib/NetPacks.h index 3f9823441..a53fa5ad9 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -301,6 +301,28 @@ struct BattleResult : public CPack//3003 } }; +struct BattleStackMoved : public CPack//3004 +{ + ui32 stack, tile; + ui8 flags; + + + + BattleStackMoved(){flags = 0; type = 3004;}; + bool startMoving() + { + return flags & 1; + } + bool endMoving() + { + return flags & 2; + } + template void serialize(Handler &h, const int version) + { + h & stack & tile & flags; + } +}; + struct ShowInInfobox : public CPack //107 { ShowInInfobox(){type = 107;}; diff --git a/lib/VCMI_Lib.h b/lib/VCMI_Lib.h index b2fd10281..69a45014b 100644 --- a/lib/VCMI_Lib.h +++ b/lib/VCMI_Lib.h @@ -57,7 +57,7 @@ public: //StartInfo scenarioOps; }; -#ifndef __GNUC__ +#ifdef __GNUC__ DLL_EXPORT LibClasses * VLC; #else extern DLL_EXPORT LibClasses * VLC; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 173bf54f6..15807ad34 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -315,7 +315,7 @@ void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile { if(!stacks[i]->alive) continue;//indicates imposiibility of making action for this dead unit BattleSetActiveStack sas; - sas.stack = i; + sas.stack = stacks[i]->ID; sendAndApply(&sas); //wait for response about battle action @@ -323,6 +323,7 @@ void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile boost::unique_lock lock(battleMadeAction.mx); while(!battleMadeAction.data) battleMadeAction.cond.wait(lock); + battleMadeAction.data = false; } } @@ -584,7 +585,80 @@ void CGameHandler::handleConnection(std::set players, CConnection &c) { case 2: //walk { - //battleMoveCreatureStack(ba.stackNumber, ba.destinationTile); + 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); + accessibility[curStack->attackerOwned ? curStack->position+1 : curStack->position-1]=true;//OUR second tile is for US accessible + } + else + gs->curB->getAccessibilityMap(accessibility); + 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 path = gs->curB->getPath(curStack->position,ba.destinationTile,accessibility); + + for(int v=path.size()-1; v>=0; --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()); break; } case 3: //defend diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 1b0bf5d53..47683243b 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -3,7 +3,9 @@ #include #include "../CGameState.h" #include "../lib/Connection.h" +#ifndef _MSC_VER #include +#endif class CVCMIServer; class CGameState; //class CConnection;