mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
* luck support
* support for distance/wall penalties & no * penalty abilities * reworked damage calculation to fit OH3 formula better
This commit is contained in:
parent
943c433d3f
commit
5d3d9689e8
@ -669,7 +669,7 @@ std::pair<ui32, ui32> CCallback::battleEstimateDamage(int attackerID, int defend
|
||||
const CStack * attacker = gs->curB->getStack(attackerID, false),
|
||||
* defender = gs->curB->getStack(defenderID);
|
||||
|
||||
return BattleInfo::calculateDmgRange(attacker, defender, attackerHero, defenderHero, battleCanShoot(attacker->ID, defender->position), 0);
|
||||
return gs->curB->calculateDmgRange(attacker, defender, attackerHero, defenderHero, battleCanShoot(attacker->ID, defender->position), 0, false);
|
||||
}
|
||||
|
||||
ui8 CCallback::battleGetSiegeLevel()
|
||||
@ -961,6 +961,16 @@ bool CCallback::hasAccess(int playerId) const
|
||||
return playerId == player || player < 0;
|
||||
}
|
||||
|
||||
si8 CCallback::battleHasDistancePenalty( int stackID, int destHex )
|
||||
{
|
||||
return gs->curB->hasDistancePenalty(stackID, destHex);
|
||||
}
|
||||
|
||||
si8 CCallback::battleHasWallPenalty( int stackID, int destHex )
|
||||
{
|
||||
return gs->curB->hasWallPenalty(stackID, destHex);
|
||||
}
|
||||
|
||||
InfoAboutTown::InfoAboutTown()
|
||||
{
|
||||
tType = NULL;
|
||||
|
@ -167,7 +167,7 @@ public:
|
||||
virtual void getStackQueue( std::vector<const CStack *> &out, int howMany )=0; //returns vector of stack in order of their move sequence
|
||||
virtual CCreature battleGetCreature(int number)=0; //returns type of creature by given number of stack
|
||||
//virtual bool battleMoveCreature(int ID, int dest)=0; //moves creature with id ID to dest if possible
|
||||
virtual std::vector<int> battleGetAvailableHexes(int ID, bool addOccupiable)=0; //reutrns numbers of hexes reachable by creature with id ID
|
||||
virtual std::vector<int> battleGetAvailableHexes(int ID, bool addOccupiable)=0; //returns numbers of hexes reachable by creature with id ID
|
||||
virtual bool battleIsStackMine(int ID)=0; //returns true if stack with id ID belongs to caller
|
||||
virtual bool battleCanShoot(int ID, int dest)=0; //returns true if unit with id ID can shoot to dest
|
||||
virtual bool battleCanCastSpell()=0; //returns true, if caller can cast a spell
|
||||
@ -177,9 +177,11 @@ public:
|
||||
virtual int battleGetWallUnderHex(int hex)=0; //returns part of destructible wall / gate / keep under given hex or -1 if not found
|
||||
virtual std::pair<ui32, ui32> battleEstimateDamage(int attackerID, int defenderID)=0; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
|
||||
virtual ui8 battleGetSiegeLevel()=0; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
|
||||
virtual const CGHeroInstance * battleGetFightingHero(ui8 side) const =0; //returns hero corresponding ot given side (0 - attacker, 1 - defender)
|
||||
virtual const CGHeroInstance * battleGetFightingHero(ui8 side) const =0; //returns hero corresponding to given side (0 - attacker, 1 - defender)
|
||||
virtual si8 battleGetStackMorale(int stackID) =0; //returns morale of given stack
|
||||
virtual si8 battleGetStackLuck(int stackID) =0; //returns luck of given stack
|
||||
virtual si8 battleHasDistancePenalty(int stackID, int destHex) =0; //checks if given stack has distance penalty
|
||||
virtual si8 battleHasWallPenalty(int stackID, int destHex) =0; //checks if given stack has wall penalty
|
||||
};
|
||||
|
||||
struct HeroMoveDetails
|
||||
@ -302,6 +304,8 @@ public:
|
||||
const CGHeroInstance * battleGetFightingHero(ui8 side) const; //returns hero corresponding ot given side (0 - attacker, 1 - defender)
|
||||
si8 battleGetStackMorale(int stackID); //returns morale of given stack
|
||||
si8 battleGetStackLuck(int stackID); //returns luck of given stack
|
||||
si8 battleHasDistancePenalty(int stackID, int destHex); //checks if given stack has distance penalty
|
||||
si8 battleHasWallPenalty(int stackID, int destHex); //checks if given stack has wall penalty
|
||||
|
||||
//XXX hmmm _tmain on _GNUC_ wtf?
|
||||
//friends
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "../hch/CObjectHandler.h"
|
||||
#include "../hch/CTownHandler.h"
|
||||
#include "../lib/map.h"
|
||||
#include "../mapHandler.h"
|
||||
#include "mapHandler.h"
|
||||
#include "../stdafx.h"
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
@ -1757,7 +1757,15 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
|
||||
}
|
||||
else if(curInt->cb->battleCanShoot(activeStack,myNumber)) //we can shoot enemy
|
||||
{
|
||||
CGI->curh->changeGraphic(1,3);
|
||||
if(curInt->cb->battleHasDistancePenalty(activeStack, myNumber) ||
|
||||
curInt->cb->battleHasWallPenalty(activeStack, myNumber))
|
||||
{
|
||||
CGI->curh->changeGraphic(1,15);
|
||||
}
|
||||
else
|
||||
{
|
||||
CGI->curh->changeGraphic(1,3);
|
||||
}
|
||||
//setting console text
|
||||
char buf[500];
|
||||
//calculating estimated dmg
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "../lib/NetPacks.h"
|
||||
#include "../lib/map.h"
|
||||
#include "../lib/VCMIDirs.h"
|
||||
#include "../mapHandler.h"
|
||||
#include "mapHandler.h"
|
||||
#include "../timeHandler.h"
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "../lib/NetPacks.h"
|
||||
#include "../lib/VCMI_Lib.h"
|
||||
#include "../lib/map.h"
|
||||
#include "../mapHandler.h"
|
||||
#include "mapHandler.h"
|
||||
#include "CConfigHandler.h"
|
||||
#include "Client.h"
|
||||
#include "GUIBase.h"
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <boost/assign/list_of.hpp>
|
||||
#include "RegisterTypes.cpp"
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
boost::rand48 ran;
|
||||
|
||||
@ -2373,9 +2375,9 @@ bool CGameState::checkForVisitableDir( const int3 & src, const TerrainTile *pom,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
std::pair<ui32, ui32> BattleInfo::calculateDmgRange(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge)
|
||||
std::pair<ui32, ui32> BattleInfo::calculateDmgRange( const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky )
|
||||
{
|
||||
float attackDefenseBonus,
|
||||
float additiveBonus=1.0f, multBonus=1.0f,
|
||||
minDmg = attacker->creature->damageMin * attacker->amount,
|
||||
maxDmg = attacker->creature->damageMax * attacker->amount;
|
||||
|
||||
@ -2400,36 +2402,37 @@ std::pair<ui32, ui32> BattleInfo::calculateDmgRange(const CStack* attacker, cons
|
||||
maxDmg *= attackerHero->getPrimSkillLevel(0) + 1;
|
||||
}
|
||||
|
||||
int attackDefenceDifference = 0;
|
||||
if(attacker->hasFeatureOfType(StackFeature::GENERAL_ATTACK_REDUCTION))
|
||||
{
|
||||
float multAttackReduction = attacker->valOfFeatures(StackFeature::GENERAL_ATTACK_REDUCTION, -1024) / 100.0f;
|
||||
attackDefenseBonus = attacker->Attack() * multAttackReduction;
|
||||
attackDefenceDifference = attacker->Attack() * multAttackReduction;
|
||||
}
|
||||
else
|
||||
{
|
||||
attackDefenseBonus = attacker->Attack();
|
||||
attackDefenceDifference = attacker->Attack();
|
||||
}
|
||||
|
||||
if(attacker->hasFeatureOfType(StackFeature::ENEMY_DEFENCE_REDUCTION))
|
||||
{
|
||||
float multDefenceReduction = (100.0f - attacker->valOfFeatures(StackFeature::ENEMY_DEFENCE_REDUCTION, -1024)) / 100.0f;
|
||||
attackDefenseBonus -= defender->Defense() * multDefenceReduction;
|
||||
attackDefenceDifference -= defender->Defense() * multDefenceReduction;
|
||||
}
|
||||
else
|
||||
{
|
||||
attackDefenseBonus -= defender->Defense();
|
||||
attackDefenceDifference -= defender->Defense();
|
||||
}
|
||||
|
||||
//calculating total attack/defense skills modifier
|
||||
|
||||
if(!shooting && attacker->hasFeatureOfType(StackFeature::ATTACK_BONUS, 0)) //bloodlust handling (etc.)
|
||||
{
|
||||
attackDefenseBonus += attacker->valOfFeatures(StackFeature::ATTACK_BONUS, 0);
|
||||
attackDefenceDifference += attacker->valOfFeatures(StackFeature::ATTACK_BONUS, 0);
|
||||
}
|
||||
|
||||
if(shooting && attacker->hasFeatureOfType(StackFeature::ATTACK_BONUS, 1)) //precision handling (etc.)
|
||||
{
|
||||
attackDefenseBonus += attacker->valOfFeatures(StackFeature::ATTACK_BONUS, 1);
|
||||
attackDefenceDifference += attacker->valOfFeatures(StackFeature::ATTACK_BONUS, 1);
|
||||
}
|
||||
|
||||
if(attacker->getEffect(55)) //slayer handling
|
||||
@ -2455,42 +2458,44 @@ std::pair<ui32, ui32> BattleInfo::calculateDmgRange(const CStack* attacker, cons
|
||||
{
|
||||
if(defender->creature->idNumber == affectedIds[g])
|
||||
{
|
||||
attackDefenseBonus += VLC->spellh->spells[55].powers[attacker->getEffect(55)->level];
|
||||
attackDefenceDifference += VLC->spellh->spells[55].powers[attacker->getEffect(55)->level];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float dmgBonusMultiplier = 1.0f;
|
||||
|
||||
//applying jousting bonus
|
||||
if( attacker->hasFeatureOfType(StackFeature::JOUSTING) && !defender->hasFeatureOfType(StackFeature::CHARGE_IMMUNITY) )
|
||||
dmgBonusMultiplier += charge * 0.05f;
|
||||
|
||||
//bonus from attack/defense skills
|
||||
if(attackDefenseBonus < 0) //decreasing dmg
|
||||
if(attackDefenceDifference < 0) //decreasing dmg
|
||||
{
|
||||
if(0.02f * (-attackDefenseBonus) > 0.3f)
|
||||
float dec = 0.025f * (-attackDefenceDifference);
|
||||
if(dec > 0.7f)
|
||||
{
|
||||
dmgBonusMultiplier += -0.3f;
|
||||
multBonus *= 1.0f - dec;
|
||||
}
|
||||
else
|
||||
{
|
||||
dmgBonusMultiplier += 0.02f * attackDefenseBonus;
|
||||
multBonus *= dec;
|
||||
}
|
||||
}
|
||||
else //increasing dmg
|
||||
{
|
||||
if(0.05f * attackDefenseBonus > 4.0f)
|
||||
float inc = 0.05f * attackDefenceDifference;
|
||||
if(inc > 4.0f)
|
||||
{
|
||||
dmgBonusMultiplier += 4.0f;
|
||||
additiveBonus += 4.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
dmgBonusMultiplier += 0.05f * attackDefenseBonus;
|
||||
additiveBonus += inc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//applying jousting bonus
|
||||
if( attacker->hasFeatureOfType(StackFeature::JOUSTING) && !defender->hasFeatureOfType(StackFeature::CHARGE_IMMUNITY) )
|
||||
additiveBonus += charge * 0.05f;
|
||||
|
||||
|
||||
//handling secondary abilities and artifacts giving premies to them
|
||||
if(attackerHero)
|
||||
{
|
||||
@ -2499,20 +2504,20 @@ std::pair<ui32, ui32> BattleInfo::calculateDmgRange(const CStack* attacker, cons
|
||||
switch(attackerHero->getSecSkillLevel(1)) //archery
|
||||
{
|
||||
case 1: //basic
|
||||
dmgBonusMultiplier += 0.1f;
|
||||
additiveBonus += 0.1f;
|
||||
break;
|
||||
case 2: //advanced
|
||||
dmgBonusMultiplier += 0.25f;
|
||||
additiveBonus += 0.25f;
|
||||
break;
|
||||
case 3: //expert
|
||||
dmgBonusMultiplier += 0.5f;
|
||||
additiveBonus += 0.5f;
|
||||
break;
|
||||
}
|
||||
|
||||
if(attackerHero->getSecSkillLevel(1) > 0) //non-none level
|
||||
{
|
||||
//apply artifact premy to archery
|
||||
dmgBonusMultiplier += attackerHero->valOfBonuses(HeroBonus::SECONDARY_SKILL_PREMY, 1) / 100.0f;
|
||||
additiveBonus += attackerHero->valOfBonuses(HeroBonus::SECONDARY_SKILL_PREMY, 1) / 100.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -2520,54 +2525,85 @@ std::pair<ui32, ui32> BattleInfo::calculateDmgRange(const CStack* attacker, cons
|
||||
switch(attackerHero->getSecSkillLevel(22)) //offense
|
||||
{
|
||||
case 1: //basic
|
||||
dmgBonusMultiplier += 0.1f;
|
||||
additiveBonus += 0.1f;
|
||||
break;
|
||||
case 2: //advanced
|
||||
dmgBonusMultiplier += 0.2f;
|
||||
additiveBonus += 0.2f;
|
||||
break;
|
||||
case 3: //expert
|
||||
dmgBonusMultiplier += 0.3f;
|
||||
additiveBonus += 0.3f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(defendingHero)
|
||||
{
|
||||
switch(defendingHero->getSecSkillLevel(23)) //armorer
|
||||
{
|
||||
case 1: //basic
|
||||
dmgBonusMultiplier *= 0.95f;
|
||||
multBonus *= 0.95f;
|
||||
break;
|
||||
case 2: //advanced
|
||||
dmgBonusMultiplier *= 0.9f;
|
||||
multBonus *= 0.9f;
|
||||
break;
|
||||
case 3: //expert
|
||||
dmgBonusMultiplier *= 0.85f;
|
||||
multBonus *= 0.85f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//handling hate effect
|
||||
if( attacker->hasFeatureOfType(StackFeature::HATE, defender->creature->idNumber) )
|
||||
dmgBonusMultiplier += 0.5f;
|
||||
additiveBonus += 0.5f;
|
||||
|
||||
//luck bonus
|
||||
if (lucky)
|
||||
{
|
||||
additiveBonus += 1.0f;
|
||||
}
|
||||
|
||||
//handling spell effects
|
||||
if(!shooting && defender->hasFeatureOfType(StackFeature::GENERAL_DAMAGE_REDUCTION, 0)) //eg. shield
|
||||
{
|
||||
dmgBonusMultiplier *= float(defender->valOfFeatures(StackFeature::GENERAL_DAMAGE_REDUCTION, 0)) / 100.0f;
|
||||
multBonus *= float(defender->valOfFeatures(StackFeature::GENERAL_DAMAGE_REDUCTION, 0)) / 100.0f;
|
||||
}
|
||||
else if(shooting && defender->hasFeatureOfType(StackFeature::GENERAL_DAMAGE_REDUCTION, 1)) //eg. air shield
|
||||
{
|
||||
dmgBonusMultiplier *= float(defender->valOfFeatures(StackFeature::GENERAL_DAMAGE_REDUCTION, 1)) / 100.0f;
|
||||
multBonus *= float(defender->valOfFeatures(StackFeature::GENERAL_DAMAGE_REDUCTION, 1)) / 100.0f;
|
||||
}
|
||||
if(attacker->getEffect(42)) //curse handling (partial, the rest is below)
|
||||
{
|
||||
dmgBonusMultiplier *= 0.8f * float(VLC->spellh->spells[42].powers[attacker->getEffect(42)->level]); //the second factor is 1 or 0
|
||||
multBonus *= 0.8f * float(VLC->spellh->spells[42].powers[attacker->getEffect(42)->level]); //the second factor is 1 or 0
|
||||
}
|
||||
|
||||
class HLP
|
||||
{
|
||||
public:
|
||||
static bool hasAdvancedAirShield(const CStack * stack)
|
||||
{
|
||||
for(int g=0; g<stack->effects.size(); ++g)
|
||||
{
|
||||
if (stack->effects[g].id == 28 && stack->effects[g].level >= 2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
minDmg *= dmgBonusMultiplier;
|
||||
maxDmg *= dmgBonusMultiplier;
|
||||
//wall / distance penalty + advanced air shield
|
||||
if (shooting && (
|
||||
hasDistancePenalty(attacker->ID, defender->position) || hasWallPenalty(attacker->ID, defender->position) ||
|
||||
HLP::hasAdvancedAirShield(defender) )
|
||||
)
|
||||
{
|
||||
multBonus *= 0.5;
|
||||
}
|
||||
|
||||
minDmg *= additiveBonus * multBonus;
|
||||
maxDmg *= additiveBonus * multBonus;
|
||||
|
||||
std::pair<ui32, ui32> returnedVal;
|
||||
|
||||
@ -2593,12 +2629,21 @@ std::pair<ui32, ui32> BattleInfo::calculateDmgRange(const CStack* attacker, cons
|
||||
return returnedVal;
|
||||
}
|
||||
|
||||
ui32 BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge)
|
||||
ui32 BattleInfo::calculateDmg( const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky )
|
||||
{
|
||||
std::pair<ui32, ui32> range = calculateDmgRange(attacker, defender, attackerHero, defendingHero, shooting, charge);
|
||||
std::pair<ui32, ui32> range = calculateDmgRange(attacker, defender, attackerHero, defendingHero, shooting, charge, lucky);
|
||||
|
||||
if(range.first != range.second)
|
||||
return range.first + rand() % (range.second - range.first + 1);
|
||||
{
|
||||
int valuesToAverage[10];
|
||||
int howManyToAv = std::min<ui32>(10, attacker->amount);
|
||||
for (int g=0; g<howManyToAv; ++g)
|
||||
{
|
||||
valuesToAverage[g] = range.first + rand() % (range.second - range.first + 1);
|
||||
}
|
||||
|
||||
return std::accumulate(valuesToAverage, valuesToAverage + howManyToAv, 0) / howManyToAv;
|
||||
}
|
||||
else
|
||||
return range.first;
|
||||
}
|
||||
@ -2809,6 +2854,13 @@ int BattleInfo::hexToWallPart(int hex) const
|
||||
return -1; //not found!
|
||||
}
|
||||
|
||||
int BattleInfo::lineToWallHex( int line ) const
|
||||
{
|
||||
static const int lineToHex[] = {12, 29, 45, 62, 78, 95, 112, 130, 147, 165, 182};
|
||||
|
||||
return lineToHex[line];
|
||||
}
|
||||
|
||||
std::pair<const CStack *, int> BattleInfo::getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const
|
||||
{
|
||||
bool ac[BFIELD_SIZE];
|
||||
@ -3585,6 +3637,36 @@ si8 BattleInfo::Luck( const CStack * st ) const
|
||||
return ret;
|
||||
}
|
||||
|
||||
si8 BattleInfo::hasDistancePenalty( int stackID, int destHex )
|
||||
{
|
||||
const CStack * stack = getStack(stackID);
|
||||
|
||||
int distance = std::abs(destHex % BFIELD_WIDTH - stack->position % BFIELD_WIDTH);
|
||||
|
||||
//I hope it's approximately correct
|
||||
return distance > 8 && !stack->hasFeatureOfType(StackFeature::NO_DISTANCE_PENALTY);
|
||||
}
|
||||
|
||||
si8 BattleInfo::hasWallPenalty( int stackID, int destHex )
|
||||
{
|
||||
if (siege == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const CStack * stack = getStack(stackID);
|
||||
if (stack->hasFeatureOfType(StackFeature::NO_WALL_PENALTY));
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int wallInStackLine = lineToWallHex(stack->position/BFIELD_WIDTH);
|
||||
int wallInDestLine = lineToWallHex(destHex/BFIELD_WIDTH);
|
||||
|
||||
bool stackLeft = stack->position < wallInStackLine;
|
||||
bool destLeft = destHex < wallInDestLine;
|
||||
|
||||
return stackLeft != destLeft;
|
||||
}
|
||||
|
||||
int3 CPath::startPos() const
|
||||
{
|
||||
return nodes[nodes.size()-1].coord;
|
||||
|
@ -188,19 +188,22 @@ struct DLL_EXPORT BattleInfo
|
||||
si8 Morale(const CStack * st) const; //get morale of stack with all modificators
|
||||
si8 Luck(const CStack * st) const; //get luck of stack with all modificators
|
||||
|
||||
bool isStackBlocked(int ID); //returns true if there is neighbouring enemy stack
|
||||
bool isStackBlocked(int ID); //returns true if there is neighboring enemy stack
|
||||
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 ui32 calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge); //charge - number of hexes travelled before attack (for champion's jousting)
|
||||
static std::pair<ui32, ui32> calculateDmgRange(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge); //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
|
||||
ui32 calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky); //charge - number of hexes travelled before attack (for champion's jousting)
|
||||
std::pair<ui32, ui32> calculateDmgRange(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky); //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
|
||||
void calculateCasualties(std::map<ui32,si32> *casualties) const; //casualties are array of maps size 2 (attacker, defeneder), maps are (crid => amount)
|
||||
std::set<CStack*> getAttackedCreatures(const CSpell * s, int skillLevel, ui8 attackerOwner, int destinationTile); //calculates stack affected by given spell
|
||||
static int calculateSpellDuration(const CSpell * spell, const CGHeroInstance * caster);
|
||||
CStack * generateNewStack(const CGHeroInstance * owner, int creatureID, int amount, int stackID, bool attackerOwned, int slot, int /*TerrainTile::EterrainType*/ terrain, int position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
|
||||
ui32 getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell
|
||||
int hexToWallPart(int hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
|
||||
int lineToWallHex(int line) const; //returns hex with wall in given line
|
||||
std::pair<const CStack *, int> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const; //if attackerOwned is indetermnate, returened stack is of any owner; hex is the number of hex we should be looking from; returns (nerarest creature, predecessorHex)
|
||||
ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const; //calculates damage inflicted by spell
|
||||
si8 hasDistancePenalty(int stackID, int destHex); //determines if given stack has distance penalty shooting given pos
|
||||
si8 hasWallPenalty(int stackID, int destHex); //determines if given stack has wall penalty shooting given pos
|
||||
};
|
||||
|
||||
class DLL_EXPORT CStack
|
||||
|
@ -637,13 +637,15 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
|
||||
BattleStackAttacked *bsa = &bat.bsa.back();
|
||||
bsa->stackAttacked = def->ID;
|
||||
bsa->attackerID = att->ID;
|
||||
bsa->damageAmount = BattleInfo::calculateDmg(att, def, gs->battleGetOwner(att->ID), gs->battleGetOwner(def->ID), bat.shot(), distance);//counting dealt damage
|
||||
|
||||
if(gs->curB->Luck(att) > 0 && rand()%24 < gs->curB->Luck(att))
|
||||
{
|
||||
bsa->damageAmount *= 2;
|
||||
bat.flags |= 4;
|
||||
}
|
||||
|
||||
bsa->damageAmount = gs->curB->calculateDmg(att, def, gs->battleGetOwner(att->ID), gs->battleGetOwner(def->ID), bat.shot(), distance, bat.lucky());//counting dealt damage
|
||||
|
||||
|
||||
int dmg = bsa->damageAmount;
|
||||
prepareAttacked(*bsa, def);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user