mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
Support for secondary skill specialities. Lots of changes, may be buggy.
This commit is contained in:
@@ -536,23 +536,23 @@ void CArtHandler::addBonuses()
|
||||
giveArtBonus(53,Bonus::SIGHT_RADIOUS,+1);//Spyglass
|
||||
|
||||
//necromancy bonus
|
||||
giveArtBonus(54,Bonus::SECONDARY_SKILL_PREMY,+5,12);//Amulet of the Undertaker
|
||||
giveArtBonus(55,Bonus::SECONDARY_SKILL_PREMY,+10,12);//Vampire's Cowl
|
||||
giveArtBonus(56,Bonus::SECONDARY_SKILL_PREMY,+15,12);//Dead Man's Boots
|
||||
giveArtBonus(54,Bonus::SECONDARY_SKILL_PREMY,+5,12, Bonus::ADDITIVE_VALUE);//Amulet of the Undertaker
|
||||
giveArtBonus(55,Bonus::SECONDARY_SKILL_PREMY,+10,12, Bonus::ADDITIVE_VALUE);//Vampire's Cowl
|
||||
giveArtBonus(56,Bonus::SECONDARY_SKILL_PREMY,+15,12, Bonus::ADDITIVE_VALUE);//Dead Man's Boots
|
||||
|
||||
giveArtBonus(57,Bonus::MAGIC_RESISTANCE,+5);//Garniture of Interference
|
||||
giveArtBonus(58,Bonus::MAGIC_RESISTANCE,+10);//Surcoat of Counterpoise
|
||||
giveArtBonus(59,Bonus::MAGIC_RESISTANCE,+15);//Boots of Polarity
|
||||
|
||||
//archery bonus
|
||||
giveArtBonus(60,Bonus::SECONDARY_SKILL_PREMY,+5,1);//Bow of Elven Cherrywood
|
||||
giveArtBonus(61,Bonus::SECONDARY_SKILL_PREMY,+10,1);//Bowstring of the Unicorn's Mane
|
||||
giveArtBonus(62,Bonus::SECONDARY_SKILL_PREMY,+15,1);//Angel Feather Arrows
|
||||
giveArtBonus(60,Bonus::SECONDARY_SKILL_PREMY,+5,1, Bonus::ADDITIVE_VALUE);//Bow of Elven Cherrywood
|
||||
giveArtBonus(61,Bonus::SECONDARY_SKILL_PREMY,+10,1, Bonus::ADDITIVE_VALUE);//Bowstring of the Unicorn's Mane
|
||||
giveArtBonus(62,Bonus::SECONDARY_SKILL_PREMY,+15,1, Bonus::ADDITIVE_VALUE);//Angel Feather Arrows
|
||||
|
||||
//eagle eye bonus
|
||||
giveArtBonus(63,Bonus::SECONDARY_SKILL_PREMY,+5,11);//Bird of Perception
|
||||
giveArtBonus(64,Bonus::SECONDARY_SKILL_PREMY,+10,11);//Stoic Watchman
|
||||
giveArtBonus(65,Bonus::SECONDARY_SKILL_PREMY,+15,11);//Emblem of Cognizance
|
||||
giveArtBonus(63,Bonus::SECONDARY_SKILL_PREMY,+5,11, Bonus::ADDITIVE_VALUE);//Bird of Perception
|
||||
giveArtBonus(64,Bonus::SECONDARY_SKILL_PREMY,+10,11, Bonus::ADDITIVE_VALUE);//Stoic Watchman
|
||||
giveArtBonus(65,Bonus::SECONDARY_SKILL_PREMY,+15,11, Bonus::ADDITIVE_VALUE);//Emblem of Cognizance
|
||||
|
||||
//reducing cost of surrendering
|
||||
giveArtBonus(66,Bonus::SURRENDER_DISCOUNT,+10);//Statesman's Medal
|
||||
|
@@ -615,13 +615,7 @@ int3 CGHeroInstance::getPosition(bool h3m) const //h3m=true - returns position o
|
||||
|
||||
si32 CGHeroInstance::manaLimit() const
|
||||
{
|
||||
double modifier = 1.0;
|
||||
switch(getSecSkillLevel(24)) //intelligence level
|
||||
{
|
||||
case 1: modifier+=0.25; break;
|
||||
case 2: modifier+=0.5; break;
|
||||
case 3: modifier+=1.0; break;
|
||||
}
|
||||
double modifier = (100.0f + valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 24)) / 100.0f;
|
||||
return si32(10*getPrimSkillLevel(3)*modifier);
|
||||
}
|
||||
//void CGHeroInstance::setPosition(int3 Pos, bool h3m) //as above, but sets position
|
||||
@@ -673,34 +667,12 @@ int CGHeroInstance::maxMovePoints(bool onLand) const
|
||||
if(onLand)
|
||||
{
|
||||
//logistics:
|
||||
switch(getSecSkillLevel(2))
|
||||
{
|
||||
case 1:
|
||||
modifier = 0.1;
|
||||
break;
|
||||
case 2:
|
||||
modifier = 0.2;
|
||||
break;
|
||||
case 3:
|
||||
modifier = 0.3;
|
||||
break;
|
||||
}
|
||||
modifier = valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 2) / 100.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
//navigation:
|
||||
switch(getSecSkillLevel(5))
|
||||
{
|
||||
case 1:
|
||||
modifier = 0.5;
|
||||
break;
|
||||
case 2:
|
||||
modifier = 1.0;
|
||||
break;
|
||||
case 3:
|
||||
modifier = 1.5;
|
||||
break;
|
||||
}
|
||||
modifier = valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 5) / 100.0f;
|
||||
}
|
||||
return int(base + base*modifier) + bonus;
|
||||
}
|
||||
@@ -1132,6 +1104,9 @@ void CGHeroInstance::initObj()
|
||||
tlog2 << "Unexpected hero speciality " << type <<'\n';
|
||||
}
|
||||
}
|
||||
//initialize bonuses
|
||||
for (std::vector<std::pair<ui8,ui8> >::iterator it = secSkills.begin(); it != secSkills.end(); it++)
|
||||
updateSkill(it->first, it->second, true);
|
||||
UpdateSpeciality();
|
||||
}
|
||||
void CGHeroInstance::UpdateSpeciality()
|
||||
@@ -1145,7 +1120,8 @@ void CGHeroInstance::UpdateSpeciality()
|
||||
{
|
||||
case Bonus::SECONDARY_SKILL_PREMY:
|
||||
it->val = (speciality.valOfBonuses(Bonus::SPECIAL_SECONDARY_SKILL, it->subtype) *
|
||||
valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, it->subtype) * level); //TODO: use only skills as bonuses
|
||||
valOfBonuses(Selector::typeSybtype(Bonus::SECONDARY_SKILL_PREMY, it->subtype),this) * level);
|
||||
//use only hero skills as bonuses to avoid feedback loop
|
||||
break;
|
||||
case Bonus::PRIMARY_SKILL: //for crearures, that is
|
||||
int creLevel = (*creatures)[it->additionalInfo]->level;
|
||||
@@ -1177,6 +1153,56 @@ void CGHeroInstance::UpdateSpeciality()
|
||||
}
|
||||
}
|
||||
}
|
||||
void CGHeroInstance::updateSkill(int which, int val, bool abs)
|
||||
{
|
||||
int skillVal = 0;
|
||||
switch (which)
|
||||
{
|
||||
case 1: //Archery
|
||||
switch (val)
|
||||
{
|
||||
case 1:
|
||||
skillVal = 10; break;
|
||||
case 2:
|
||||
skillVal = 25; break;
|
||||
case 3:
|
||||
skillVal = 50; break;
|
||||
}
|
||||
break;
|
||||
case 2: //Logistics
|
||||
skillVal = 10 * val; break;
|
||||
case 5: //Navigation
|
||||
skillVal = 50 * val; break;
|
||||
case 8: //Mysticism
|
||||
skillVal = val; break;
|
||||
case 11: //eagle Eye
|
||||
skillVal = 30 + 10 * val; break;
|
||||
case 12: //Necromancy
|
||||
skillVal = 10 * val; break;
|
||||
case 22: //Offense
|
||||
skillVal = 10 * val; break;
|
||||
case 23: //Armorer
|
||||
skillVal = 5 * val; break;
|
||||
case 24: //Intelligence
|
||||
skillVal = 25 << val-1; break;
|
||||
case 25: //Sorcery
|
||||
skillVal = 5 * val; break;
|
||||
case 26: //Resistance
|
||||
skillVal = 5 << val-1; break;
|
||||
case 27: //First Aid
|
||||
skillVal = 25 + 25*val; break;
|
||||
}
|
||||
if(!hasBonusOfType(Bonus::SECONDARY_SKILL_PREMY, which))
|
||||
{
|
||||
bonuses.push_back
|
||||
(Bonus(Bonus::PERMANENT, Bonus::SECONDARY_SKILL_PREMY, id, skillVal, ID, which, Bonus::BASE_NUMBER));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (skillVal)
|
||||
getBonus(Selector::typeSybtype(Bonus::SECONDARY_SKILL_PREMY, which))->val = skillVal;
|
||||
}
|
||||
}
|
||||
void CGHeroInstance::setPropertyDer( ui8 what, ui32 val )
|
||||
{
|
||||
if(what == ObjProperty::PRIMARY_STACK_COUNT)
|
||||
@@ -1253,8 +1279,7 @@ CStackInstance CGHeroInstance::calculateNecromancy (const BattleResult &battleRe
|
||||
// Hero knows necromancy.
|
||||
if (necromancyLevel > 0)
|
||||
{
|
||||
double necromancySkill = necromancyLevel*0.1
|
||||
+ valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 12)/100.0;
|
||||
double necromancySkill = valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 12)/100.0;
|
||||
amin(necromancySkill, 1.0); //it's impossible to raise more creatures than all...
|
||||
const std::map<ui32,si32> &casualties = battleResult.casualties[!battleResult.winner];
|
||||
ui32 raisedUnits = 0;
|
||||
@@ -1334,7 +1359,7 @@ si32 CGHeroInstance::manaRegain() const
|
||||
if (hasBonusOfType(Bonus::FULL_MANA_REGENERATION))
|
||||
return manaLimit();
|
||||
|
||||
return 1 + getSecSkillLevel(8) + valOfBonuses(Bonus::MANA_REGENERATION); //1 + Mysticism level
|
||||
return 1 + valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 8) + valOfBonuses(Bonus::MANA_REGENERATION); //1 + Mysticism level
|
||||
}
|
||||
|
||||
si32 CGHeroInstance::getArtPos(int aid) const
|
||||
|
@@ -380,6 +380,7 @@ public:
|
||||
void initHeroDefInfo();
|
||||
void pushPrimSkill(int which, int val);
|
||||
void UpdateSpeciality();
|
||||
void updateSkill(int which, int val, bool abs);
|
||||
|
||||
CGHeroInstance();
|
||||
virtual ~CGHeroInstance();
|
||||
|
@@ -2623,56 +2623,17 @@ std::pair<ui32, ui32> BattleInfo::calculateDmgRange( const CStack* attacker, con
|
||||
{
|
||||
if(shooting)
|
||||
{
|
||||
switch(attackerHero->getSecSkillLevel(1)) //archery
|
||||
{
|
||||
case 1: //basic
|
||||
additiveBonus += 0.1f;
|
||||
break;
|
||||
case 2: //advanced
|
||||
additiveBonus += 0.25f;
|
||||
break;
|
||||
case 3: //expert
|
||||
additiveBonus += 0.5f;
|
||||
break;
|
||||
}
|
||||
|
||||
if(attackerHero->getSecSkillLevel(1) > 0) //non-none level
|
||||
{
|
||||
//apply artifact premy to archery
|
||||
additiveBonus += attackerHero->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 1) / 100.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(attackerHero->getSecSkillLevel(22)) //offense
|
||||
{
|
||||
case 1: //basic
|
||||
additiveBonus += 0.1f;
|
||||
break;
|
||||
case 2: //advanced
|
||||
additiveBonus += 0.2f;
|
||||
break;
|
||||
case 3: //expert
|
||||
additiveBonus += 0.3f;
|
||||
break;
|
||||
}
|
||||
additiveBonus += attackerHero->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 22) / 100.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if(defendingHero)
|
||||
{
|
||||
switch(defendingHero->getSecSkillLevel(23)) //armorer
|
||||
{
|
||||
case 1: //basic
|
||||
multBonus *= 0.95f;
|
||||
break;
|
||||
case 2: //advanced
|
||||
multBonus *= 0.9f;
|
||||
break;
|
||||
case 3: //expert
|
||||
multBonus *= 0.85f;
|
||||
break;
|
||||
}
|
||||
multBonus *= (std::max(0, 100-attackerHero->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 23))) / 100.0f;
|
||||
}
|
||||
|
||||
//handling hate effect
|
||||
|
@@ -83,7 +83,7 @@ DLL_EXPORT void SetSecSkill::applyGs( CGameState *gs )
|
||||
}
|
||||
else
|
||||
{
|
||||
for(unsigned i=0;i<hero->secSkills.size();i++)
|
||||
for (unsigned i=0; i<hero->secSkills.size(); i++)
|
||||
{
|
||||
if(hero->secSkills[i].first == which)
|
||||
{
|
||||
@@ -100,6 +100,7 @@ DLL_EXPORT void SetSecSkill::applyGs( CGameState *gs )
|
||||
}
|
||||
}
|
||||
}
|
||||
hero->updateSkill(which, val, abs);
|
||||
}
|
||||
|
||||
DLL_EXPORT void HeroVisitCastle::applyGs( CGameState *gs )
|
||||
|
@@ -3685,7 +3685,6 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
||||
}
|
||||
case 12: //healing
|
||||
{
|
||||
static const int healingPerLevel[] = {50, 50, 75, 100};
|
||||
sendAndApply(&StartAction(ba));
|
||||
const CGHeroInstance * attackingHero = gs->curB->heroes[ba.side];
|
||||
CStack *healer = gs->curB->getStack(ba.stackNumber),
|
||||
@@ -3696,7 +3695,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
||||
complain("There is either no healer, no destination, or healer cannot heal :P");
|
||||
}
|
||||
int maxHealable = destStack->MaxHealth() - destStack->firstHPleft;
|
||||
int maxiumHeal = healingPerLevel[ attackingHero->getSecSkillLevel(27) ];
|
||||
int maxiumHeal = std::max(10, attackingHero->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 27));
|
||||
|
||||
int healed = std::min(maxHealable, maxiumHeal);
|
||||
|
||||
@@ -3932,19 +3931,8 @@ static std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHero
|
||||
{
|
||||
//bonusHero's resistance support (secondary skils and artifacts)
|
||||
prob += bonusHero->valOfBonuses(Bonus::MAGIC_RESISTANCE);
|
||||
|
||||
switch(bonusHero->getSecSkillLevel(26)) //resistance
|
||||
{
|
||||
case 1: //basic
|
||||
prob += 5;
|
||||
break;
|
||||
case 2: //advanced
|
||||
prob += 10;
|
||||
break;
|
||||
case 3: //expert
|
||||
prob += 20;
|
||||
break;
|
||||
}
|
||||
//resistance skill
|
||||
prob += bonusHero->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 26) / 100.0f;
|
||||
}
|
||||
|
||||
if(prob > 100) prob = 100;
|
||||
|
Reference in New Issue
Block a user