From 15ff21e84c5b25eb0c6184df7615cecda80cd519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Fri, 8 Aug 2008 23:02:32 +0000 Subject: [PATCH] Battles: attacking, shooting, killing. --- CBattleInterface.cpp | 49 +++++++++--- CBattleInterface.h | 2 +- CGameInterface.h | 8 +- CGameState.cpp | 129 +++++------------------------- CGameState.h | 3 +- CMT.cpp | 17 +++- CPlayerInterface.cpp | 49 +++++++----- CPlayerInterface.h | 7 +- client/Client.cpp | 8 ++ global.h | 16 ++++ lib/NetPacks.h | 43 +++++++++- server/CGameHandler.cpp | 168 +++++++++++++++++++++------------------- server/CGameHandler.h | 1 + 13 files changed, 268 insertions(+), 232 deletions(-) diff --git a/CBattleInterface.cpp b/CBattleInterface.cpp index 46917c73f..ebd7f7319 100644 --- a/CBattleInterface.cpp +++ b/CBattleInterface.cpp @@ -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 n = BattleInfo::neighbouringTiles(whichOne); + for(int i=0;ishadedHexes.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(),boost::function())) ->activate(); diff --git a/CBattleInterface.h b/CBattleInterface.h index c1bd45b76..3501538d4 100644 --- a/CBattleInterface.h +++ b/CBattleInterface.h @@ -112,7 +112,7 @@ private: }; std::list 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 diff --git a/CGameInterface.h b/CGameInterface.h index 9f4752236..6a92fd8a2 100644 --- a/CGameInterface.h +++ b/CGameInterface.h @@ -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 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; // diff --git a/CGameState.cpp b/CGameState.cpp index 74f859f54..373245b44 100644 --- a/CGameState.cpp +++ b/CGameState.cpp @@ -405,6 +405,23 @@ void CGameState::apply(IPack * pack) curB->getStack(br->stack)->position = br->tile; break; } + case 3005: + { + BattleStackAttacked *br = static_cast(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(pack); + mx->unlock(); + apply(&br->bsa); + mx->lock(); + break; + } //case 1002://set hover name // { // SetHoverName * shn = static_cast(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; ystacks.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; vstacks.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 CGameState::battleGetRange(int ID) -{/* - std::vector additionals; - - //adding enemies' positions - for(int c=0; cstacks.size(); ++c) - { - if(curB->stacks[c]->alive && curB->stacks[c]->owner != owner) - { - for(int g=0; gstacks[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::iterator nend = std::unique(ret.begin(), ret.end()); - - std::vector ret2; - - for(std::vector::iterator it = ret.begin(); it != nend; ++it) - { - ret2.push_back(*it); - } - - return ret2;*/ - return std::vector(); -} - +} \ No newline at end of file diff --git a/CGameState.h b/CGameState.h index 99fd11502..a15411c3a 100644 --- a/CGameState.h +++ b/CGameState.h @@ -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 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 battleGetRange(int ID); //called by std::vector 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 diff --git a/CMT.cpp b/CMT.cpp index 8f7e097fd..4c3296836 100644 --- a/CMT.cpp +++ b/CMT.cpp @@ -150,7 +150,22 @@ int main(int argc, _TCHAR* argv[]) THC std::cout<<"\tCallback and console: "<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(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(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(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 un(*pim); dynamic_cast(curint)->stackMoved(ID, dest, startMoving, endMoving); } - -void CPlayerInterface::battleStackAttacking(int ID, int dest) +void CPlayerInterface::battleAttack(BattleAttack *ba) { - dynamic_cast(curint)->stackAttacking(ID, dest); + boost::unique_lock un(*pim); + if(ba->shot()) + dynamic_cast(curint)->stackIsShooting(ba->stackAttacking,cb->battleGetPos(ba->bsa.stackAttacked)); + else + dynamic_cast(curint)->stackAttacking( ba->stackAttacking, cb->battleGetPos(ba->bsa.stackAttacked) ); + if(ba->killed()) + dynamic_cast(curint)->stackKilled(ba->bsa.stackAttacked, ba->bsa.damageAmount, ba->bsa.killedAmount, ba->stackAttacking, ba->shot()); + else + dynamic_cast(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(curint)->stackIsAttacked(ID, dmg, killed, IDby, byShooting); -} - void CPlayerInterface::battleStackKilled(int ID, int dmg, int killed, int IDby, bool byShooting) { dynamic_cast(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); diff --git a/CPlayerInterface.h b/CPlayerInterface.h index 1da22d45b..3778bfbbd 100644 --- a/CPlayerInterface.h +++ b/CPlayerInterface.h @@ -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 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 diff --git a/client/Client.cpp b/client/Client.cpp index 9b00bb45e..687b1fd68 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -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: diff --git a/global.h b/global.h index c28537ef4..2a4e68663 100644 --- a/global.h +++ b/global.h @@ -89,4 +89,20 @@ const int MAX_BUILDING_PER_TURN = 1; delete e; \ } + +namespace vstd +{ + template + bool contains(const Container & c, const Item &i) + { + return std::find(c.begin(),c.end(),i) != c.end(); + } + template + typename Container::iterator find(const Container & c, const Item &i) + { + return std::find(c.begin(),c.end(),i); + } + +} + #endif //GLOBAL_H diff --git a/lib/NetPacks.h b/lib/NetPacks.h index a53fa5ad9..94b5af6d3 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -304,7 +304,7 @@ struct BattleResult : public CPack//3003 struct BattleStackMoved : public CPack//3004 { ui32 stack, tile; - ui8 flags; + ui8 flags; // 1 - start moving, 2 - end moving @@ -323,6 +323,47 @@ struct BattleStackMoved : public CPack//3004 } }; +struct BattleStackAttacked : public CPack//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 void serialize(Handler &h, const int version) + { + h & stackAttacked & newAmount & newHP & flags & killedAmount & damageAmount; + } +}; + +struct BattleAttack : public CPack//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 void serialize(Handler &h, const int version) + { + h & bsa & stackAttacking & flags; + } +}; + struct ShowInInfobox : public CPack //107 { ShowInInfobox(){type = 107;}; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 51600fe38..0c45abe66 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -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 +#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 players, CConnection &c) { try @@ -585,80 +616,7 @@ void CGameHandler::handleConnection(std::set 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 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 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 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 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(p.total_seconds()); - cTurn.wait(lock); - //cTurn.timed_wait(lock,time); + cTurn.timed_wait(lock,time); +#endif } } } diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 47683243b..4e3482bf4 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -28,6 +28,7 @@ class CGameHandler void handleCPPObjS(std::map * 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