mirror of
https://github.com/vcmi/vcmi.git
synced 2025-04-15 11:46:56 +02:00
* life drain implemented
* fixed #134 * fixed damage calculation formula
This commit is contained in:
parent
cc616616c1
commit
dbbbaa1e18
@ -106,13 +106,14 @@ public:
|
|||||||
virtual void battleStacksAttacked(std::vector<BattleStackAttacked> & bsa){}; //called when stack receives damage (after battleAttack())
|
virtual void battleStacksAttacked(std::vector<BattleStackAttacked> & bsa){}; //called when stack receives damage (after battleAttack())
|
||||||
virtual void battleEnd(BattleResult *br){};
|
virtual void battleEnd(BattleResult *br){};
|
||||||
virtual void battleResultsApplied(){}; //called when all effects of last battle are applied
|
virtual void battleResultsApplied(){}; //called when all effects of last battle are applied
|
||||||
|
virtual void battleNewRoundFirst(int round){}; //called at the beginning of each turn before changes are applied;
|
||||||
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 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 battleStackMoved(int ID, int dest, int distance, bool end){};
|
virtual void battleStackMoved(int ID, int dest, int distance, bool end){};
|
||||||
virtual void battleSpellCast(SpellCast *sc){};
|
virtual void battleSpellCast(SpellCast *sc){};
|
||||||
virtual void battleStacksEffectsSet(SetStackEffect & sse){};//called when a specific effect is set to stacks
|
virtual void battleStacksEffectsSet(SetStackEffect & sse){};//called when a specific effect is set to stacks
|
||||||
virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right
|
virtual void battleStart(const CCreatureSet *army1, const 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 battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles){}; //called when battlefield is prepared, prior the battle beginning
|
||||||
virtual void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks){}; //called when stacks are healed / resurrected first element of pair - stack id, second - healed hp
|
virtual void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, si32 lifeDrainFrom){}; //called when stacks are healed / resurrected first element of pair - stack id, second - healed hp
|
||||||
virtual void battleNewStackAppeared(int stackID){}; //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
|
virtual void battleNewStackAppeared(int stackID){}; //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
|
||||||
virtual void battleObstaclesRemoved(const std::set<si32> & removedObstacles){}; //called when a certain set of obstacles is removed from batlefield; IDs of them are given
|
virtual void battleObstaclesRemoved(const std::set<si32> & removedObstacles){}; //called when a certain set of obstacles is removed from batlefield; IDs of them are given
|
||||||
virtual void battleCatapultAttacked(const CatapultAttack & ca){}; //called when catapult makes an attack
|
virtual void battleCatapultAttacked(const CatapultAttack & ca){}; //called when catapult makes an attack
|
||||||
|
@ -2227,18 +2227,18 @@ void CBattleInterface::stackAttacking(int ID, int dest, int attackedID)
|
|||||||
addNewAnim(new CMeleeAttack(this, ID, dest, attackedID));
|
addNewAnim(new CMeleeAttack(this, ID, dest, attackedID));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::newRound(int number)
|
void CBattleInterface::newRoundFirst( int round )
|
||||||
{
|
{
|
||||||
console->addText(CGI->generaltexth->allTexts[412]);
|
|
||||||
|
|
||||||
//unlock spellbook
|
|
||||||
//bSpell->block(!curInt->cb->battleCanCastSpell());
|
|
||||||
//don't unlock spellbook - this should be done when we have axctive creature
|
|
||||||
|
|
||||||
//handle regeneration
|
//handle regeneration
|
||||||
std::map<int, CStack> stacks = curInt->cb->battleGetStacks();
|
std::map<int, CStack> stacks = curInt->cb->battleGetStacks();
|
||||||
for(std::map<int, CStack>::const_iterator it = stacks.begin(); it != stacks.end(); ++it)
|
for(std::map<int, CStack>::const_iterator it = stacks.begin(); it != stacks.end(); ++it)
|
||||||
{
|
{
|
||||||
|
//don't show animation when no HP is regenerated
|
||||||
|
if (it->second.firstHPleft == it->second.MaxHealth())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if( it->second.hasBonusOfType(Bonus::HP_REGENERATION) && it->second.alive() )
|
if( it->second.hasBonusOfType(Bonus::HP_REGENERATION) && it->second.alive() )
|
||||||
displayEffect(74, it->second.position);
|
displayEffect(74, it->second.position);
|
||||||
|
|
||||||
@ -2250,6 +2250,17 @@ void CBattleInterface::newRound(int number)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CBattleInterface::newRound(int number)
|
||||||
|
{
|
||||||
|
console->addText(CGI->generaltexth->allTexts[412]);
|
||||||
|
|
||||||
|
//unlock spellbook
|
||||||
|
//bSpell->block(!curInt->cb->battleCanCastSpell());
|
||||||
|
//don't unlock spellbook - this should be done when we have axctive creature
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void CBattleInterface::giveCommand(ui8 action, ui16 tile, ui32 stack, si32 additional)
|
void CBattleInterface::giveCommand(ui8 action, ui16 tile, ui32 stack, si32 additional)
|
||||||
{
|
{
|
||||||
if(!curInt->cb->battleGetStackByID(stack) && action != 1 && action != 4 && action != 5)
|
if(!curInt->cb->battleGetStackByID(stack) && action != 1 && action != 4 && action != 5)
|
||||||
@ -3237,6 +3248,7 @@ void CBattleInterface::startAction(const BattleAction* action)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CBattleHero::show(SDL_Surface *to)
|
void CBattleHero::show(SDL_Surface *to)
|
||||||
{
|
{
|
||||||
//animation of flag
|
//animation of flag
|
||||||
|
@ -495,6 +495,7 @@ public:
|
|||||||
void stackMoved(int number, int destHex, bool endMoving, int distance); //stack with id number moved to destHex
|
void stackMoved(int number, int destHex, bool endMoving, int distance); //stack with id number moved to destHex
|
||||||
void stacksAreAttacked(std::vector<SStackAttackedInfo> attackedInfos); //called when a certain amount of stacks has been attacked
|
void stacksAreAttacked(std::vector<SStackAttackedInfo> attackedInfos); //called when a certain amount of stacks has been attacked
|
||||||
void stackAttacking(int ID, int dest, int attackedID); //called when stack with id ID is attacking something on hex dest
|
void stackAttacking(int ID, int dest, int attackedID); //called when stack with id ID is attacking something on hex dest
|
||||||
|
void newRoundFirst( int round );
|
||||||
void newRound(int number); //caled when round is ended; number is the number of round
|
void newRound(int number); //caled when round is ended; number is the number of round
|
||||||
void hexLclicked(int whichOne); //hex only call-in
|
void hexLclicked(int whichOne); //hex only call-in
|
||||||
void stackIsShooting(int ID, int dest, int attackedID); //called when stack with id ID is shooting to hex dest
|
void stackIsShooting(int ID, int dest, int attackedID); //called when stack with id ID is shooting to hex dest
|
||||||
|
@ -534,7 +534,7 @@ void CPlayerInterface::battlefieldPrepared(int battlefieldType, std::vector<CObs
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPlayerInterface::battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks)
|
void CPlayerInterface::battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, si32 lifeDrainFrom)
|
||||||
{
|
{
|
||||||
if(LOCPLINT != this)
|
if(LOCPLINT != this)
|
||||||
{ //another local interface should do this
|
{ //another local interface should do this
|
||||||
@ -550,6 +550,26 @@ void CPlayerInterface::battleStacksHealedRes(const std::vector<std::pair<ui32, u
|
|||||||
battleInt->creAnims[healed->ID]->setType(2);
|
battleInt->creAnims[healed->ID]->setType(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lifeDrain)
|
||||||
|
{
|
||||||
|
const CStack *attacker = cb->battleGetStackByID(healedStacks[0].first, false);
|
||||||
|
const CStack *defender = cb->battleGetStackByID(lifeDrainFrom, false);
|
||||||
|
if (attacker)
|
||||||
|
{
|
||||||
|
battleInt->displayEffect(50, attacker->position);
|
||||||
|
}
|
||||||
|
//print info about life drain
|
||||||
|
int textOff = 0;
|
||||||
|
if (attacker->count > 1)
|
||||||
|
{
|
||||||
|
textOff += 1;
|
||||||
|
}
|
||||||
|
char textBuf[1000];
|
||||||
|
sprintf(textBuf, CGI->generaltexth->allTexts[361 + textOff].c_str(), attacker->getCreature()->nameSing.c_str(),
|
||||||
|
healedStacks[0].second, defender->getCreature()->namePl.c_str());
|
||||||
|
battleInt->console->addText(textBuf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPlayerInterface::battleNewStackAppeared(int stackID)
|
void CPlayerInterface::battleNewStackAppeared(int stackID)
|
||||||
@ -740,6 +760,7 @@ void CPlayerInterface::battleStacksAttacked(std::vector<BattleStackAttacked> & b
|
|||||||
}
|
}
|
||||||
SStackAttackedInfo to_put = {i->stackAttacked, i->damageAmount, i->killedAmount, i->attackerID, LOCPLINT->curAction->actionType==7, i->killed()};
|
SStackAttackedInfo to_put = {i->stackAttacked, i->damageAmount, i->killedAmount, i->attackerID, LOCPLINT->curAction->actionType==7, i->killed()};
|
||||||
arg.push_back(to_put);
|
arg.push_back(to_put);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bsa.begin()->isEffect() && bsa.begin()->effect == 12) //for armageddon - I hope this condition is enough
|
if(bsa.begin()->isEffect() && bsa.begin()->effect == 12) //for armageddon - I hope this condition is enough
|
||||||
@ -1910,3 +1931,14 @@ void CPlayerInterface::updateInfo(const CGObjectInstance * specific)
|
|||||||
// if (adventureInt->selection == specific)
|
// if (adventureInt->selection == specific)
|
||||||
// adventureInt->infoBar.showAll(screen);
|
// adventureInt->infoBar.showAll(screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPlayerInterface::battleNewRoundFirst( int round )
|
||||||
|
{
|
||||||
|
if(LOCPLINT != this)
|
||||||
|
{ //another local interface should do this
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
||||||
|
battleInt->newRoundFirst(round);
|
||||||
|
}
|
||||||
|
@ -184,6 +184,7 @@ public:
|
|||||||
void battleAttack(BattleAttack *ba); //stack performs attack
|
void battleAttack(BattleAttack *ba); //stack performs attack
|
||||||
void battleEnd(BattleResult *br); //end of battle
|
void battleEnd(BattleResult *br); //end of battle
|
||||||
//void battleResultQuited();
|
//void battleResultQuited();
|
||||||
|
void battleNewRoundFirst(int round); //called at the beginning of each turn before changes are applied; used for HP regen handling
|
||||||
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 battleNewRound(int round); //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
|
||||||
void battleStackMoved(int ID, int dest, int distance, bool end);
|
void battleStackMoved(int ID, int dest, int distance, bool end);
|
||||||
void battleSpellCast(SpellCast *sc);
|
void battleSpellCast(SpellCast *sc);
|
||||||
@ -191,7 +192,7 @@ public:
|
|||||||
void battleStacksAttacked(std::vector<BattleStackAttacked> & bsa);
|
void battleStacksAttacked(std::vector<BattleStackAttacked> & bsa);
|
||||||
void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side); //called by engine when battle starts; side=0 - left, side=1 - right
|
void battleStart(const CCreatureSet *army1, const 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 battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles); //called when battlefield is prepared, prior the battle beginning
|
||||||
void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks); //called when stacks are healed / resurrected
|
void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, si32 lifeDrainFrom); //called when stacks are healed / resurrected
|
||||||
void battleNewStackAppeared(int stackID); //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
|
void battleNewStackAppeared(int stackID); //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
|
||||||
void battleObstaclesRemoved(const std::set<si32> & removedObstacles); //called when a certain set of obstacles is removed from batlefield; IDs of them are given
|
void battleObstaclesRemoved(const std::set<si32> & removedObstacles); //called when a certain set of obstacles is removed from batlefield; IDs of them are given
|
||||||
void battleCatapultAttacked(const CatapultAttack & ca); //called when catapult makes an attack
|
void battleCatapultAttacked(const CatapultAttack & ca); //called when catapult makes an attack
|
||||||
|
@ -436,6 +436,14 @@ void BattleStart::applyCl( CClient *cl )
|
|||||||
cl->playerint[info->side2]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1);
|
cl->playerint[info->side2]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BattleNextRound::applyFirstCl(CClient *cl)
|
||||||
|
{
|
||||||
|
if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end())
|
||||||
|
cl->playerint[GS(cl)->curB->side1]->battleNewRoundFirst(round);
|
||||||
|
if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end())
|
||||||
|
cl->playerint[GS(cl)->curB->side2]->battleNewRoundFirst(round);
|
||||||
|
}
|
||||||
|
|
||||||
void BattleNextRound::applyCl( CClient *cl )
|
void BattleNextRound::applyCl( CClient *cl )
|
||||||
{
|
{
|
||||||
if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end())
|
if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end())
|
||||||
@ -489,6 +497,13 @@ void BattleAttack::applyFirstCl( CClient *cl )
|
|||||||
cl->playerint[GS(cl)->curB->side1]->battleAttack(this);
|
cl->playerint[GS(cl)->curB->side1]->battleAttack(this);
|
||||||
if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end())
|
if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end())
|
||||||
cl->playerint[GS(cl)->curB->side2]->battleAttack(this);
|
cl->playerint[GS(cl)->curB->side2]->battleAttack(this);
|
||||||
|
for (int g=0; g<bsa.size(); ++g)
|
||||||
|
{
|
||||||
|
for (int z=0; z<bsa[g].healedStacks.size(); ++z)
|
||||||
|
{
|
||||||
|
bsa[g].healedStacks[z].applyCl(cl);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleAttack::applyCl( CClient *cl )
|
void BattleAttack::applyCl( CClient *cl )
|
||||||
@ -555,8 +570,8 @@ void StacksHealedOrResurrected::applyCl( CClient *cl )
|
|||||||
{
|
{
|
||||||
shiftedHealed.push_back(std::make_pair(healedStacks[v].stackID, healedStacks[v].healedHP));
|
shiftedHealed.push_back(std::make_pair(healedStacks[v].stackID, healedStacks[v].healedHP));
|
||||||
}
|
}
|
||||||
INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1, battleStacksHealedRes, shiftedHealed);
|
INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1, battleStacksHealedRes, shiftedHealed, lifeDrain, drainedFrom);
|
||||||
INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2, battleStacksHealedRes, shiftedHealed);
|
INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2, battleStacksHealedRes, shiftedHealed, lifeDrain, drainedFrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObstaclesRemoved::applyCl( CClient *cl )
|
void ObstaclesRemoved::applyCl( CClient *cl )
|
||||||
|
@ -2441,11 +2441,11 @@ std::pair<ui32, ui32> BattleInfo::calculateDmgRange( const CStack* attacker, con
|
|||||||
float dec = 0.025f * (-attackDefenceDifference);
|
float dec = 0.025f * (-attackDefenceDifference);
|
||||||
if(dec > 0.7f)
|
if(dec > 0.7f)
|
||||||
{
|
{
|
||||||
multBonus *= 1.0f - dec;
|
multBonus *= 0.3f; //1.0 - 0.7
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
multBonus *= dec;
|
multBonus *= 1.0f - dec;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else //increasing dmg
|
else //increasing dmg
|
||||||
|
@ -860,9 +860,9 @@ struct BattleStart : public CPackForClient//3000
|
|||||||
struct BattleNextRound : public CPackForClient//3001
|
struct BattleNextRound : public CPackForClient//3001
|
||||||
{
|
{
|
||||||
BattleNextRound(){type = 3001;};
|
BattleNextRound(){type = 3001;};
|
||||||
|
void applyFirstCl(CClient *cl);
|
||||||
void applyCl(CClient *cl);
|
void applyCl(CClient *cl);
|
||||||
DLL_EXPORT void applyGs(CGameState *gs);
|
DLL_EXPORT void applyGs( CGameState *gs );
|
||||||
|
|
||||||
si32 round;
|
si32 round;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
@ -916,6 +916,34 @@ struct BattleStackMoved : public CPackForClient//3004
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct StacksHealedOrResurrected : public CPackForClient //3013
|
||||||
|
{
|
||||||
|
StacksHealedOrResurrected(){type = 3013;}
|
||||||
|
|
||||||
|
DLL_EXPORT void applyGs(CGameState *gs);
|
||||||
|
void applyCl(CClient *cl);
|
||||||
|
|
||||||
|
struct HealInfo
|
||||||
|
{
|
||||||
|
ui32 stackID;
|
||||||
|
ui32 healedHP;
|
||||||
|
ui8 lowLevelResurrection; //in case this stack is resurrected by this heal, it will be marked as SUMMONED
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & stackID & healedHP & lowLevelResurrection;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<HealInfo> healedStacks;
|
||||||
|
ui8 lifeDrain; //if true, this heal is an effect of life drain
|
||||||
|
si32 drainedFrom; //if life drain - then stack life was drain from
|
||||||
|
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & healedStacks & lifeDrain & drainedFrom;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct BattleStackAttacked : public CPackForClient//3005
|
struct BattleStackAttacked : public CPackForClient//3005
|
||||||
{
|
{
|
||||||
BattleStackAttacked(){flags = 0; type = 3005;};
|
BattleStackAttacked(){flags = 0; type = 3005;};
|
||||||
@ -926,18 +954,24 @@ struct BattleStackAttacked : public CPackForClient//3005
|
|||||||
ui32 newAmount, newHP, killedAmount, damageAmount;
|
ui32 newAmount, newHP, killedAmount, damageAmount;
|
||||||
ui8 flags; //1 - is stack killed; 2 - is there special effect to be shown;
|
ui8 flags; //1 - is stack killed; 2 - is there special effect to be shown;
|
||||||
ui32 effect; //set only if flag 2 is present
|
ui32 effect; //set only if flag 2 is present
|
||||||
|
std::vector<StacksHealedOrResurrected> healedStacks; //used when life drain
|
||||||
|
|
||||||
bool killed() const//if target stack was killed
|
bool killed() const//if target stack was killed
|
||||||
{
|
{
|
||||||
return flags & 1;
|
return flags & 1;
|
||||||
}
|
}
|
||||||
bool isEffect() const//if target stack was killed
|
bool isEffect() const//if stack has been attacked by a spell
|
||||||
{
|
{
|
||||||
return flags & 2;
|
return flags & 2;
|
||||||
}
|
}
|
||||||
|
bool lifeDrain() const //if this attack involves life drain effect
|
||||||
|
{
|
||||||
|
return healedStacks.size() > 0;
|
||||||
|
}
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & stackAttacked & attackerID & newAmount & newHP & flags & killedAmount & damageAmount & effect;
|
h & stackAttacked & attackerID & newAmount & newHP & flags & killedAmount & damageAmount & effect
|
||||||
|
& healedStacks;
|
||||||
}
|
}
|
||||||
bool operator<(const BattleStackAttacked &b) const
|
bool operator<(const BattleStackAttacked &b) const
|
||||||
{
|
{
|
||||||
@ -1067,32 +1101,6 @@ struct BattleResultsApplied : public CPackForClient //3012
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StacksHealedOrResurrected : public CPackForClient //3013
|
|
||||||
{
|
|
||||||
StacksHealedOrResurrected(){type = 3013;}
|
|
||||||
|
|
||||||
DLL_EXPORT void applyGs(CGameState *gs);
|
|
||||||
void applyCl(CClient *cl);
|
|
||||||
|
|
||||||
struct HealInfo
|
|
||||||
{
|
|
||||||
ui32 stackID;
|
|
||||||
ui32 healedHP;
|
|
||||||
ui8 lowLevelResurrection; //in case this stack is resurrected by this heal, it will be marked as SUMMONED
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
|
||||||
{
|
|
||||||
h & stackID & healedHP & lowLevelResurrection;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<HealInfo> healedStacks;
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
|
||||||
{
|
|
||||||
h & healedStacks;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ObstaclesRemoved : public CPackForClient //3014
|
struct ObstaclesRemoved : public CPackForClient //3014
|
||||||
{
|
{
|
||||||
ObstaclesRemoved(){type = 3014;}
|
ObstaclesRemoved(){type = 3014;}
|
||||||
|
@ -770,6 +770,12 @@ DLL_EXPORT void BattleStackAttacked::applyGs( CGameState *gs )
|
|||||||
at->firstHPleft = newHP;
|
at->firstHPleft = newHP;
|
||||||
if(killed())
|
if(killed())
|
||||||
at->state -= ALIVE;
|
at->state -= ALIVE;
|
||||||
|
|
||||||
|
//life drain handling
|
||||||
|
for (int g=0; g<healedStacks.size(); ++g)
|
||||||
|
{
|
||||||
|
healedStacks[g].applyGs(gs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DLL_EXPORT void BattleAttack::applyGs( CGameState *gs )
|
DLL_EXPORT void BattleAttack::applyGs( CGameState *gs )
|
||||||
@ -1121,7 +1127,7 @@ DLL_EXPORT void StacksHealedOrResurrected::applyGs( CGameState *gs )
|
|||||||
|
|
||||||
//applying changes
|
//applying changes
|
||||||
bool resurrected = !changedStack->alive(); //indicates if stack is resurrected or just healed
|
bool resurrected = !changedStack->alive(); //indicates if stack is resurrected or just healed
|
||||||
if(!changedStack->alive())
|
if(resurrected)
|
||||||
{
|
{
|
||||||
changedStack->state.insert(ALIVE);
|
changedStack->state.insert(ALIVE);
|
||||||
if(healedStacks[g].lowLevelResurrection)
|
if(healedStacks[g].lowLevelResurrection)
|
||||||
|
@ -654,6 +654,28 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
|
|||||||
int dmg = bsa->damageAmount;
|
int dmg = bsa->damageAmount;
|
||||||
prepareAttacked(*bsa, def);
|
prepareAttacked(*bsa, def);
|
||||||
|
|
||||||
|
//life drain handling
|
||||||
|
if (att->hasBonusOfType(Bonus::LIFE_DRAIN))
|
||||||
|
{
|
||||||
|
StacksHealedOrResurrected shi;
|
||||||
|
shi.lifeDrain = true;
|
||||||
|
shi.drainedFrom = def->ID;
|
||||||
|
|
||||||
|
StacksHealedOrResurrected::HealInfo hi;
|
||||||
|
hi.stackID = att->ID;
|
||||||
|
hi.healedHP = std::min<int>(dmg, att->MaxHealth() - att->firstHPleft + att->MaxHealth() * (att->baseAmount - att->count) );
|
||||||
|
hi.lowLevelResurrection = false;
|
||||||
|
shi.healedStacks.push_back(hi);
|
||||||
|
|
||||||
|
if (hi.healedHP > 0)
|
||||||
|
{
|
||||||
|
bsa->healedStacks.push_back(shi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
//fire shield handling
|
//fire shield handling
|
||||||
if ( !bat.shot() && def->hasBonusOfType(Bonus::FIRE_SHIELD) && !bsa->killed() )
|
if ( !bat.shot() && def->hasBonusOfType(Bonus::FIRE_SHIELD) && !bsa->killed() )
|
||||||
{
|
{
|
||||||
@ -667,6 +689,7 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
|
|||||||
bsa->damageAmount = (dmg * def->valOfBonuses(Bonus::FIRE_SHIELD)) / 100;
|
bsa->damageAmount = (dmg * def->valOfBonuses(Bonus::FIRE_SHIELD)) / 100;
|
||||||
prepareAttacked(*bsa, att);
|
prepareAttacked(*bsa, att);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
|
void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
|
||||||
{
|
{
|
||||||
@ -3290,6 +3313,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
StacksHealedOrResurrected shr;
|
StacksHealedOrResurrected shr;
|
||||||
|
shr.lifeDrain = false;
|
||||||
StacksHealedOrResurrected::HealInfo hi;
|
StacksHealedOrResurrected::HealInfo hi;
|
||||||
|
|
||||||
hi.healedHP = healed;
|
hi.healedHP = healed;
|
||||||
@ -3647,6 +3671,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
|
|||||||
case 39: //animate dead
|
case 39: //animate dead
|
||||||
{
|
{
|
||||||
StacksHealedOrResurrected shr;
|
StacksHealedOrResurrected shr;
|
||||||
|
shr.lifeDrain = false;
|
||||||
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
|
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
|
||||||
{
|
{
|
||||||
if(vstd::contains(sc.resisted, (*it)->ID) //this creature resisted the spell
|
if(vstd::contains(sc.resisted, (*it)->ID) //this creature resisted the spell
|
||||||
|
Loading…
x
Reference in New Issue
Block a user