diff --git a/CBattleInterface.cpp b/CBattleInterface.cpp index 013e1ead9..7000fed33 100644 --- a/CBattleInterface.cpp +++ b/CBattleInterface.cpp @@ -361,6 +361,10 @@ void CBattleInterface::stackRemoved(CStack stack) creAnims.erase(stack.ID); } +void CBattleInterface::stackKilled(int ID) +{ +} + void CBattleInterface::stackActivated(int number) { givenCommand = NULL; diff --git a/CBattleInterface.h b/CBattleInterface.h index 3ca5f55ac..1fc55e3b7 100644 --- a/CBattleInterface.h +++ b/CBattleInterface.h @@ -112,6 +112,7 @@ public: //call-ins void newStack(CStack stack); //new stack appeared on battlefield void stackRemoved(CStack stack); //stack disappeared from batlefiled + void stackKilled(int ID); //stack has been killed (but corpses remain) void stackActivated(int number); //active stack has been changed void stackMoved(int number, int destHex, bool startMoving, bool endMoving); //stack with id number moved to destHex void stackIsAttacked(int ID); //called when stack id attacked diff --git a/CGameInterface.h b/CGameInterface.h index b87cd109e..b2305b429 100644 --- a/CGameInterface.h +++ b/CGameInterface.h @@ -70,6 +70,9 @@ public: virtual BattleAction activeStack(int stackID)=0; //called when it's turn of that stack virtual void battleEnd(CCreatureSet * army1, CCreatureSet * army2, CArmedInstance *hero1, CArmedInstance *hero2, std::vector capturedArtifacts, int expForWinner, bool winner){}; 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)=0; + virtual void battleStackKilled(int ID)=0; // }; @@ -86,6 +89,9 @@ public: virtual void heroKilled(const CGHeroInstance*){}; virtual void heroCreated(const CGHeroInstance*){}; virtual void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving){}; + virtual void battleStackAttacking(int ID, int dest){}; + virtual void battleStackIsAttacked(int ID){}; + virtual void battleStackKilled(int ID){}; virtual BattleAction activeStack(int stackID) {BattleAction ba; ba.actionType = 3; ba.stackNumber = stackID; return ba;}; }; #endif //CGAMEINTERFACE_H \ No newline at end of file diff --git a/CGameState.cpp b/CGameState.cpp index a93ffe8bf..cef417b11 100644 --- a/CGameState.cpp +++ b/CGameState.cpp @@ -264,17 +264,9 @@ bool CGameState::battleMoveCreatureStack(int ID, int dest) //first checks if(curB->stackActionPerformed) //because unit cannot be moved more than once return false; - bool stackAtEnd = false; //true if there is a stack at the end of the path (we should attack it) + unsigned char owner = -1; //owner moved of unit for(int g=0; gstacks.size(); ++g) - { - if(curB->stacks[g]->position == dest) - { - stackAtEnd = true; - break; - } - } - for(int g=0; gstacks.size(); ++g) { if(curB->stacks[g]->ID == ID) { @@ -282,6 +274,21 @@ bool CGameState::battleMoveCreatureStack(int ID, int dest) break; } } + + bool stackAtEnd = false; //true if there is a stack at the end of the path (we should attack it) + int numberOfStackAtEnd = -1; + for(int g=0; gstacks.size(); ++g) + { + if(curB->stacks[g]->position == dest + || (curB->stacks[g]->creature->isDoubleWide() && curB->stacks[g]->attackerOwned && curB->stacks[g]->position-1 == dest) + || (curB->stacks[g]->creature->isDoubleWide() && !curB->stacks[g]->attackerOwned && curB->stacks[g]->position+1 == dest)) + { + stackAtEnd = true; + numberOfStackAtEnd = g; + break; + } + } + //selecting moved stack CStack * curStack = NULL; for(int y=0; ystacks.size(); ++y) @@ -408,12 +415,74 @@ bool CGameState::battleMoveCreatureStack(int ID, int dest) { if(v!=0 || !stackAtEnd) //it's not the last step { - LOCPLINT->battleStackMoved(ID, path[v], v==path.size()-1, v==0); + LOCPLINT->battleStackMoved(ID, path[v], v==path.size()-1, v==0 || (stackAtEnd && v==1) ); curStack->position = path[v]; } else //if it's last step and we should attack unit at the end { LOCPLINT->battleStackAttacking(ID, path[v]); + //counting dealt damage + int numberOfCres = curStack->amount; //number of attacking creatures + int attackDefenseBonus = curStack->creature->attack - curB->stacks[numberOfStackAtEnd]->creature->defence; + int damageBase = 0; + if(curStack->creature->damageMax == curStack->creature->damageMin) //constant damage + { + damageBase = curStack->creature->damageMin; + } + else + { + damageBase = rand()%(curStack->creature->damageMax - curStack->creature->damageMin) + curStack->creature->damageMin + 1; + } + + float dmgBonusMultiplier = 1.0; + if(attackDefenseBonus < 0) //decreasing dmg + { + if(0.02f * (-attackDefenseBonus) > 0.3f) + { + dmgBonusMultiplier += -0.3f; + } + else + { + dmgBonusMultiplier += 0.02f * attackDefenseBonus; + } + } + else //increasing dmg + { + if(0.05f * attackDefenseBonus > 4.0f) + { + dmgBonusMultiplier += 4.0f; + } + else + { + dmgBonusMultiplier += 0.05f * attackDefenseBonus; + } + } + + int finalDmg = (float)damageBase * (float)curStack->amount * dmgBonusMultiplier; + + //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; + } + + curB->stacks[numberOfStackAtEnd]->amount -= cresKilled; + if(curB->stacks[numberOfStackAtEnd]->amount<=0) //stack killed + { + curB->stacks[numberOfStackAtEnd]->amount = 0; + curB->stacks[numberOfStackAtEnd]->alive = false; + LOCPLINT->battleStackKilled(curB->stacks[numberOfStackAtEnd]->ID); + } + + //damage applied } } curB->stackActionPerformed = true; @@ -470,7 +539,7 @@ std::vector CGameState::battleGetRange(int ID) accessibility[k] = true; for(int g=0; gstacks.size(); ++g) { - if(curB->stacks[g]->owner == owner && curB->stacks[g]->ID != ID) //we don't want to lock enemy's positions or current unit's position + if(curB->stacks[g]->ID != ID) //we don't want to lock current unit's position { accessibility[curB->stacks[g]->position] = false; if(curB->stacks[g]->creature->isDoubleWide()) //if it's a double hex creature diff --git a/CGameState.h b/CGameState.h index bdae333a7..966909625 100644 --- a/CGameState.h +++ b/CGameState.h @@ -44,12 +44,13 @@ public: int ID; //unique ID of stack CCreature * creature; int amount; + int firstHPleft; //HP of first creature in stack int owner; bool attackerOwned; //if true, this stack is owned by attakcer (this one from left hand side of battle) int position; //position on battlefield bool alive; //true if it is alive - 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){}; - CStack() : creature(NULL),amount(-1),owner(255), alive(true), position(-1), ID(-1), attackerOwned(true){}; + 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){}; + CStack() : creature(NULL),amount(-1),owner(255), alive(true), position(-1), ID(-1), attackerOwned(true), firstHPleft(-1){}; }; class CGameState diff --git a/CPlayerInterface.cpp b/CPlayerInterface.cpp index 47d68a5b8..18bb06b92 100644 --- a/CPlayerInterface.cpp +++ b/CPlayerInterface.cpp @@ -2078,6 +2078,11 @@ void CPlayerInterface::battleStackIsAttacked(int ID) dynamic_cast(curint)->stackIsAttacked(ID); } +void CPlayerInterface::battleStackKilled(int ID) +{ + dynamic_cast(curint)->stackKilled(ID); +} + void CPlayerInterface::showComp(SComponent comp) { adventureInt->infoBar.showComp(&comp,4000); diff --git a/CPlayerInterface.h b/CPlayerInterface.h index dc2e98f7c..a82f0ed6b 100644 --- a/CPlayerInterface.h +++ b/CPlayerInterface.h @@ -342,6 +342,7 @@ public: void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving); void battleStackAttacking(int ID, int dest); void battleStackIsAttacked(int ID); + void battleStackKilled(int ID); //-------------//