mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
Hero speciality will now affect Resurrection and other remaining spells.
Minor refactoring of spell mechanics, more to come.
This commit is contained in:
@@ -3282,23 +3282,9 @@ std::pair<const CStack *, int> BattleInfo::getNearestStack(const CStack * closes
|
|||||||
|
|
||||||
return std::make_pair<const CStack * , int>(NULL, -1);
|
return std::make_pair<const CStack * , int>(NULL, -1);
|
||||||
}
|
}
|
||||||
|
ui32 BattleInfo::calculateSpellBonus(ui32 baseDamage, const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature) const
|
||||||
ui32 BattleInfo::calculateSpellDmg( const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower ) const
|
|
||||||
{
|
{
|
||||||
ui32 ret = 0; //value to return
|
ui32 ret = baseDamage;
|
||||||
|
|
||||||
//15 - magic arrows, 16 - ice bolt, 17 - lightning bolt, 18 - implosion, 20 - frost ring, 21 - fireball, 22 - inferno, 23 - meteor shower,
|
|
||||||
//24 - death ripple, 25 - destroy undead, 26 - armageddon, 77 - thunderbolt
|
|
||||||
static std::map <int, int> dmgMultipliers = boost::assign::map_list_of(15, 10)(16, 20)(17, 25)(18, 75)(20, 10)(21, 10)(22, 10)(23, 10)(24, 5)(25, 10)(26, 50)(77, 10);
|
|
||||||
|
|
||||||
//check if spell really does damage - if not, return 0
|
|
||||||
if(dmgMultipliers.find(sp->id) == dmgMultipliers.end())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
|
||||||
ret = usedSpellPower * dmgMultipliers[sp->id];
|
|
||||||
ret += sp->powers[spellSchoolLevel];
|
|
||||||
|
|
||||||
//applying sorcery secondary skill
|
//applying sorcery secondary skill
|
||||||
if(caster)
|
if(caster)
|
||||||
{
|
{
|
||||||
@@ -3314,6 +3300,26 @@ ui32 BattleInfo::calculateSpellDmg( const CSpell * sp, const CGHeroInstance * ca
|
|||||||
else if(sp->earth)
|
else if(sp->earth)
|
||||||
ret *= (100.0f + caster->valOfBonuses(Bonus::EARTH_SPELL_DMG_PREMY)) / 100.0f;
|
ret *= (100.0f + caster->valOfBonuses(Bonus::EARTH_SPELL_DMG_PREMY)) / 100.0f;
|
||||||
}
|
}
|
||||||
|
if (caster) //Hero specials like Solmyr, Deemer
|
||||||
|
ret *= (100.f + ((caster->valOfBonuses(Bonus::SPECIAL_SPELL_LEV, sp->id) * caster->level) / affectedCreature->type->level)) / 100.0f;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui32 BattleInfo::calculateSpellDmg( const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower ) const
|
||||||
|
{
|
||||||
|
ui32 ret = 0; //value to return
|
||||||
|
|
||||||
|
//15 - magic arrows, 16 - ice bolt, 17 - lightning bolt, 18 - implosion, 20 - frost ring, 21 - fireball, 22 - inferno, 23 - meteor shower,
|
||||||
|
//24 - death ripple, 25 - destroy undead, 26 - armageddon, 77 - thunderbolt
|
||||||
|
static std::map <int, int> dmgMultipliers = boost::assign::map_list_of(15, 10)(16, 20)(17, 25)(18, 75)(20, 10)(21, 10)(22, 10)(23, 10)(24, 5)(25, 10)(26, 50)(77, 10);
|
||||||
|
|
||||||
|
//check if spell really does damage - if not, return 0
|
||||||
|
if(dmgMultipliers.find(sp->id) == dmgMultipliers.end())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = usedSpellPower * dmgMultipliers[sp->id];
|
||||||
|
ret += sp->powers[spellSchoolLevel];
|
||||||
|
|
||||||
//affected creature-specific part
|
//affected creature-specific part
|
||||||
if(affectedCreature)
|
if(affectedCreature)
|
||||||
{
|
{
|
||||||
@@ -3350,13 +3356,36 @@ ui32 BattleInfo::calculateSpellDmg( const CSpell * sp, const CGHeroInstance * ca
|
|||||||
ret *= 100 + affectedCreature->valOfBonuses(Bonus::MORE_DAMAGE_FROM_SPELL, sp->id);
|
ret *= 100 + affectedCreature->valOfBonuses(Bonus::MORE_DAMAGE_FROM_SPELL, sp->id);
|
||||||
ret /= 100;
|
ret /= 100;
|
||||||
}
|
}
|
||||||
if (caster) //Hero specials like Solmyr, Deemer
|
|
||||||
ret *= (100.f + ((caster->valOfBonuses(Bonus::SPECIAL_SPELL_LEV, sp->id) * caster->level) / affectedCreature->type->level)) / 100.0f;
|
|
||||||
}
|
}
|
||||||
|
calculateSpellBonus(ret, sp, caster, affectedCreature);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui32 BattleInfo::calculateHealedHP(const CGHeroInstance * caster, const CSpell * spell, const CStack * stack) const
|
||||||
|
{
|
||||||
|
int powerPerLevel;
|
||||||
|
bool resurrect;
|
||||||
|
switch(spell->id)
|
||||||
|
{
|
||||||
|
case 37: //cure
|
||||||
|
{
|
||||||
|
powerPerLevel = 5;
|
||||||
|
resurrect = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 38: //resurrection
|
||||||
|
case 39: //animate dead
|
||||||
|
{
|
||||||
|
powerPerLevel = 50;
|
||||||
|
resurrect = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int healedHealth = caster->getPrimSkillLevel(2) * powerPerLevel + spell->powers[caster->getSpellSchoolLevel(spell)];
|
||||||
|
healedHealth = calculateSpellBonus(healedHealth, spell, caster, stack);
|
||||||
|
return std::min<ui32>(healedHealth, stack->MaxHealth() - stack->firstHPleft + (resurrect ? stack->baseAmount * stack->MaxHealth() : 0));
|
||||||
|
}
|
||||||
|
|
||||||
bool CGameState::battleCanShoot(int ID, int dest)
|
bool CGameState::battleCanShoot(int ID, int dest)
|
||||||
{
|
{
|
||||||
if(!curB)
|
if(!curB)
|
||||||
|
@@ -239,7 +239,9 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode
|
|||||||
int hexToWallPart(int hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
|
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
|
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)
|
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 calculateSpellBonus(ui32 baseDamage, const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature) const;
|
||||||
ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const; //calculates damage inflicted by spell
|
ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const; //calculates damage inflicted by spell
|
||||||
|
ui32 calculateHealedHP(const CGHeroInstance * caster, const CSpell * spell, const CStack * stack) const;
|
||||||
si8 hasDistancePenalty(int stackID, int destHex); //determines if given stack has distance penalty shooting given pos
|
si8 hasDistancePenalty(int stackID, int destHex); //determines if given stack has distance penalty shooting given pos
|
||||||
si8 sameSideOfWall(int pos1, int pos2); //determines if given positions are on the same side of wall
|
si8 sameSideOfWall(int pos1, int pos2); //determines if given positions are on the same side of wall
|
||||||
si8 hasWallPenalty(int stackID, int destHex); //determines if given stack has wall penalty shooting given pos
|
si8 hasWallPenalty(int stackID, int destHex); //determines if given stack has wall penalty shooting given pos
|
||||||
|
@@ -4118,34 +4118,6 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ui32 calculateHealedHP(const CGHeroInstance * caster, const CSpell * spell, const CStack * stack)
|
|
||||||
{
|
|
||||||
switch(spell->id)
|
|
||||||
{
|
|
||||||
case 37: //cure
|
|
||||||
{
|
|
||||||
int healedHealth = caster->getPrimSkillLevel(2) * 5 + spell->powers[caster->getSpellSchoolLevel(spell)];
|
|
||||||
return std::min<ui32>(healedHealth, stack->MaxHealth() - stack->firstHPleft);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 38: //resurrection
|
|
||||||
{
|
|
||||||
int healedHealth = caster->getPrimSkillLevel(2) * 50 + spell->powers[caster->getSpellSchoolLevel(spell)];
|
|
||||||
return std::min<ui32>(healedHealth, stack->MaxHealth() - stack->firstHPleft + stack->baseAmount * stack->MaxHealth());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 39: //animate dead
|
|
||||||
{
|
|
||||||
int healedHealth = caster->getPrimSkillLevel(2) * 50 + spell->powers[caster->getSpellSchoolLevel(spell)];
|
|
||||||
return std::min<ui32>(healedHealth, stack->MaxHealth() - stack->firstHPleft + stack->baseAmount * stack->MaxHealth());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//we shouldn't be here
|
|
||||||
tlog1 << "calculateHealedHP called for non-healing spell: " << spell->name << std::endl;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHeroInstance * caster, const CGHeroInstance * hero2, const std::set<CStack*> affectedCreatures)
|
static std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHeroInstance * caster, const CGHeroInstance * hero2, const std::set<CStack*> affectedCreatures)
|
||||||
{
|
{
|
||||||
std::vector<ui32> ret;
|
std::vector<ui32> ret;
|
||||||
@@ -4334,7 +4306,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
|
|||||||
}
|
}
|
||||||
sse.effect.id = spellID;
|
sse.effect.id = spellID;
|
||||||
sse.effect.level = spellLvl;
|
sse.effect.level = spellLvl;
|
||||||
sse.effect.turnsRemain = BattleInfo::calculateSpellDuration(spell, caster, usedSpellPower);
|
sse.effect.turnsRemain = gs->curB->calculateSpellDuration(spell, caster, usedSpellPower);
|
||||||
if(!sse.stacks.empty())
|
if(!sse.stacks.empty())
|
||||||
sendAndApply(&sse);
|
sendAndApply(&sse);
|
||||||
break;
|
break;
|
||||||
@@ -4365,7 +4337,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
|
|||||||
continue;
|
continue;
|
||||||
StacksHealedOrResurrected::HealInfo hi;
|
StacksHealedOrResurrected::HealInfo hi;
|
||||||
hi.stackID = (*it)->ID;
|
hi.stackID = (*it)->ID;
|
||||||
hi.healedHP = calculateHealedHP(caster, spell, *it);
|
hi.healedHP = gs->curB->calculateHealedHP(caster, spell, *it);
|
||||||
hi.lowLevelResurrection = spellLvl <= 1;
|
hi.lowLevelResurrection = spellLvl <= 1;
|
||||||
shr.healedStacks.push_back(hi);
|
shr.healedStacks.push_back(hi);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user