mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-25 22:42:04 +02:00
* new spell: blind
* a part of hypnotize support * minor changes and bugfixes
This commit is contained in:
@@ -1462,6 +1462,8 @@ bool CBattleInterface::isTileAttackable(const int & number) const
|
|||||||
void CBattleInterface::handleEndOfMove(int stackNumber, int destinationTile)
|
void CBattleInterface::handleEndOfMove(int stackNumber, int destinationTile)
|
||||||
{
|
{
|
||||||
const CStack * movedStack = LOCPLINT->cb->battleGetStackByID(stackNumber);
|
const CStack * movedStack = LOCPLINT->cb->battleGetStackByID(stackNumber);
|
||||||
|
if(!movedStack)
|
||||||
|
return;
|
||||||
if(creAnims[stackNumber]->framesInGroup(21)!=0) // some units don't have this animation (ie. halberdier)
|
if(creAnims[stackNumber]->framesInGroup(21)!=0) // some units don't have this animation (ie. halberdier)
|
||||||
{
|
{
|
||||||
if (movedStack->creature->sounds.endMoving)
|
if (movedStack->creature->sounds.endMoving)
|
||||||
@@ -2199,7 +2201,7 @@ void CBattleInterface::redrawBackgroundWithHexes(int activeStack)
|
|||||||
void CBattleInterface::printConsoleAttacked(int ID, int dmg, int killed, int IDby)
|
void CBattleInterface::printConsoleAttacked(int ID, int dmg, int killed, int IDby)
|
||||||
{
|
{
|
||||||
char tabh[200];
|
char tabh[200];
|
||||||
const CStack * attacker = LOCPLINT->cb->battleGetStackByID(IDby);
|
const CStack * attacker = LOCPLINT->cb->battleGetStackByID(IDby, false);
|
||||||
const CStack * defender = LOCPLINT->cb->battleGetStackByID(ID, false);
|
const CStack * defender = LOCPLINT->cb->battleGetStackByID(ID, false);
|
||||||
int end = sprintf(tabh, CGI->generaltexth->allTexts[attacker->amount > 1 ? 377 : 376].c_str(),
|
int end = sprintf(tabh, CGI->generaltexth->allTexts[attacker->amount > 1 ? 377 : 376].c_str(),
|
||||||
(attacker->amount > 1 ? attacker->creature->namePl.c_str() : attacker->creature->nameSing.c_str()),
|
(attacker->amount > 1 ? attacker->creature->namePl.c_str() : attacker->creature->nameSing.c_str()),
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
26 -1 12 X X X X
|
26 -1 12 X X X X
|
||||||
27 1 27 0 0 0 X
|
27 1 27 0 0 0 X
|
||||||
28 1 2 0 0 0 X
|
28 1 2 0 0 0 X
|
||||||
29 1 -1 0 0 0 X
|
29 1 11 0 0 0 X
|
||||||
30 1 22 0 0 0 X
|
30 1 22 0 0 0 X
|
||||||
31 1 24 0 0 0 X
|
31 1 24 0 0 0 X
|
||||||
32 1 23 0 0 0 X
|
32 1 23 0 0 0 X
|
||||||
@@ -58,11 +58,11 @@
|
|||||||
55 1 28 0 0 0 0
|
55 1 28 0 0 0 0
|
||||||
56 1 17 0 0 0 0
|
56 1 17 0 0 0 0
|
||||||
57 -1 -1 0 0 0 0
|
57 -1 -1 0 0 0 0
|
||||||
58 1 -1 0 0 0 X
|
58 1 7 0 0 0 X
|
||||||
59 -1 -1 0 0 0-1 0-2
|
59 -1 35 0 0 0-1 0-2
|
||||||
60 -1 -1 0 0 0 0
|
60 -1 21 0 0 0 0
|
||||||
61 -1 42 0 0 0 X
|
61 -1 42 0 0 0 X
|
||||||
62 -1 -1 0 0 0 0
|
62 -1 6 0 0 0 0
|
||||||
63 1 -1 0 0 0 0
|
63 1 -1 0 0 0 0
|
||||||
64 0 -1 X X X X
|
64 0 -1 X X X X
|
||||||
65 1 -1 0 0 0 0
|
65 1 -1 0 0 0 0
|
||||||
|
|||||||
@@ -1861,7 +1861,7 @@ bool CGameState::checkForVisitableDir(const int3 & src, const int3 & dst) const
|
|||||||
|
|
||||||
int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting)
|
int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting)
|
||||||
{
|
{
|
||||||
int attackDefenseBonus = attacker->Attack() - defender->Defense(),
|
int attackDefenseBonus,
|
||||||
minDmg = attacker->creature->damageMin * attacker->amount,
|
minDmg = attacker->creature->damageMin * attacker->amount,
|
||||||
maxDmg = attacker->creature->damageMax * attacker->amount;
|
maxDmg = attacker->creature->damageMax * attacker->amount;
|
||||||
|
|
||||||
@@ -1871,6 +1871,15 @@ int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, con
|
|||||||
maxDmg *= attackerHero->getPrimSkillLevel(0) + 1;
|
maxDmg *= attackerHero->getPrimSkillLevel(0) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(attacker->hasFeatureOfType(StackFeature::GENERAL_ATTACK_REDUCTION))
|
||||||
|
{
|
||||||
|
attackDefenseBonus = attacker->Attack() * (attacker->valOfFeatures(StackFeature::GENERAL_ATTACK_REDUCTION, -1024) / 100.0f) - defender->Defense();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
attackDefenseBonus = attacker->Attack() - defender->Defense();
|
||||||
|
}
|
||||||
|
|
||||||
//calculating total attack/defense skills modifier
|
//calculating total attack/defense skills modifier
|
||||||
|
|
||||||
if(!shooting && attacker->hasFeatureOfType(StackFeature::ATTACK_BONUS, 0)) //bloodlust handling (etc.)
|
if(!shooting && attacker->hasFeatureOfType(StackFeature::ATTACK_BONUS, 0)) //bloodlust handling (etc.)
|
||||||
@@ -1883,6 +1892,7 @@ int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, con
|
|||||||
attackDefenseBonus += attacker->valOfFeatures(StackFeature::ATTACK_BONUS, 1);
|
attackDefenseBonus += attacker->valOfFeatures(StackFeature::ATTACK_BONUS, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(attacker->getEffect(55)) //slayer handling
|
if(attacker->getEffect(55)) //slayer handling
|
||||||
{
|
{
|
||||||
std::vector<int> affectedIds;
|
std::vector<int> affectedIds;
|
||||||
|
|||||||
@@ -600,7 +600,7 @@ DLL_EXPORT void BattleNextRound::applyGs( CGameState *gs )
|
|||||||
s->features.clear();
|
s->features.clear();
|
||||||
for(int i=0; i < tmpFeatures.size(); i++)
|
for(int i=0; i < tmpFeatures.size(); i++)
|
||||||
{
|
{
|
||||||
if(tmpFeatures[i].duration == StackFeature::N_TURNS)
|
if((tmpFeatures[i].duration & StackFeature::N_TURNS) != 0)
|
||||||
{
|
{
|
||||||
tmpFeatures[i].turnsRemain--;
|
tmpFeatures[i].turnsRemain--;
|
||||||
if(tmpFeatures[i].turnsRemain > 0)
|
if(tmpFeatures[i].turnsRemain > 0)
|
||||||
@@ -663,6 +663,29 @@ DLL_EXPORT void BattleAttack::applyGs( CGameState *gs )
|
|||||||
attacker->shots--;
|
attacker->shots--;
|
||||||
BOOST_FOREACH(BattleStackAttacked stackAttacked, bsa)
|
BOOST_FOREACH(BattleStackAttacked stackAttacked, bsa)
|
||||||
stackAttacked.applyGs(gs);
|
stackAttacked.applyGs(gs);
|
||||||
|
|
||||||
|
for(int g=0; g<attacker->features.size(); ++g)
|
||||||
|
{
|
||||||
|
if((attacker->features[g].duration & StackFeature::UNTIL_ATTACK) != 0)
|
||||||
|
{
|
||||||
|
attacker->features.erase(attacker->features.begin() + g);
|
||||||
|
g = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(std::set<BattleStackAttacked>::const_iterator it = bsa.begin(); it != bsa.end(); ++it)
|
||||||
|
{
|
||||||
|
CStack * stack = gs->curB->getStack(it->stackAttacked, false);
|
||||||
|
|
||||||
|
for(int g=0; g<stack->features.size(); ++g)
|
||||||
|
{
|
||||||
|
if((stack->features[g].duration & StackFeature::UNITL_BEING_ATTACKED) != 0)
|
||||||
|
{
|
||||||
|
stack->features.erase(stack->features.begin() + g);
|
||||||
|
g = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DLL_EXPORT void StartAction::applyGs( CGameState *gs )
|
DLL_EXPORT void StartAction::applyGs( CGameState *gs )
|
||||||
@@ -841,11 +864,18 @@ static std::vector<StackFeature> stackEffectToFeature(const CStack::StackEffect
|
|||||||
case 55: //slayer
|
case 55: //slayer
|
||||||
sf.push_back(featureGenerator(StackFeature::SLAYER, 0, sse.level, sse.turnsRemain));
|
sf.push_back(featureGenerator(StackFeature::SLAYER, 0, sse.level, sse.turnsRemain));
|
||||||
break;
|
break;
|
||||||
|
case 56: //frenzy
|
||||||
|
sf.push_back(featureGenerator(StackFeature::SLAYER, 0, sse.level, sse.turnsRemain));
|
||||||
|
break;
|
||||||
|
case 60: //hypnotize
|
||||||
|
break;
|
||||||
|
sf.push_back(featureGenerator(StackFeature::HYPNOTIZED, 0, sse.level, sse.turnsRemain));
|
||||||
case 61: //forgetfulness
|
case 61: //forgetfulness
|
||||||
sf.push_back(featureGenerator(StackFeature::SLAYER, 0, sse.level, sse.turnsRemain));
|
sf.push_back(featureGenerator(StackFeature::SLAYER, 0, sse.level, sse.turnsRemain));
|
||||||
break;
|
break;
|
||||||
case 56: //frenzy
|
case 62: //blind
|
||||||
sf.push_back(featureGenerator(StackFeature::SLAYER, 0, sse.level, sse.turnsRemain));
|
sf.push_back(makeFeature(StackFeature::NOT_ACTIVE, StackFeature::UNITL_BEING_ATTACKED | StackFeature::N_TURNS, 0, 0, StackFeature::SPELL_EFFECT, sse.turnsRemain, 0));
|
||||||
|
sf.push_back(makeFeature(StackFeature::GENERAL_ATTACK_REDUCTION, StackFeature::UNTIL_ATTACK | StackFeature::N_TURNS, 0, VLC->spellh->spells[sse.id].powers[sse.level], StackFeature::SPELL_EFFECT, sse.turnsRemain, 0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ struct StackFeature
|
|||||||
VCMI_CREATURE_ABILITY_NAME(SPELLCASTER) /*subtype - spell id, value - level of school, additional info - spell power*/ \
|
VCMI_CREATURE_ABILITY_NAME(SPELLCASTER) /*subtype - spell id, value - level of school, additional info - spell power*/ \
|
||||||
VCMI_CREATURE_ABILITY_NAME(CATAPULT) \
|
VCMI_CREATURE_ABILITY_NAME(CATAPULT) \
|
||||||
VCMI_CREATURE_ABILITY_NAME(ENEMY_DEFENCE_REDUCTION) /*in % (value) eg. behemots*/ \
|
VCMI_CREATURE_ABILITY_NAME(ENEMY_DEFENCE_REDUCTION) /*in % (value) eg. behemots*/ \
|
||||||
VCMI_CREATURE_ABILITY_NAME(GENERAL_DAMAGE_REDUCTION) /*eg. while stoned or blinded - in %, subtype: -1 - any damage, 0 - melee damage, 1 - ranged damage*/ \
|
VCMI_CREATURE_ABILITY_NAME(GENERAL_DAMAGE_REDUCTION) /* shield / air shield effect */ \
|
||||||
|
VCMI_CREATURE_ABILITY_NAME(GENERAL_ATTACK_REDUCTION) /*eg. while stoned or blinded - in %, subtype: -1 - any damage, 0 - melee damage, 1 - ranged damage*/ \
|
||||||
VCMI_CREATURE_ABILITY_NAME(ATTACKS_ALL_ADJACENT) /*eg. hydra*/ \
|
VCMI_CREATURE_ABILITY_NAME(ATTACKS_ALL_ADJACENT) /*eg. hydra*/ \
|
||||||
VCMI_CREATURE_ABILITY_NAME(MORE_DAMAGE_FROM_SPELL) /*value - damage increase in %, subtype - spell id*/ \
|
VCMI_CREATURE_ABILITY_NAME(MORE_DAMAGE_FROM_SPELL) /*value - damage increase in %, subtype - spell id*/ \
|
||||||
VCMI_CREATURE_ABILITY_NAME(CASTS_SPELL_WHEN_KILLED) /*similar to spell after attack*/ \
|
VCMI_CREATURE_ABILITY_NAME(CASTS_SPELL_WHEN_KILLED) /*similar to spell after attack*/ \
|
||||||
@@ -92,10 +93,10 @@ struct StackFeature
|
|||||||
|
|
||||||
enum EDuration
|
enum EDuration
|
||||||
{
|
{
|
||||||
WHOLE_BATTLE,
|
WHOLE_BATTLE = 1,
|
||||||
N_TURNS,
|
N_TURNS = 2,
|
||||||
UNITL_BEING_ATTACKED,/*removed after attack and counterattacks are performed*/
|
UNITL_BEING_ATTACKED = 4,/*removed after attack and counterattacks are performed*/
|
||||||
UNTIL_ATTACK /*removed after attack and counterattacks are performed*/
|
UNTIL_ATTACK = 8 /*removed after attack and counterattacks are performed*/
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ESource
|
enum ESource
|
||||||
@@ -107,7 +108,7 @@ struct StackFeature
|
|||||||
};
|
};
|
||||||
|
|
||||||
ui8 type;//ECombatFeatures
|
ui8 type;//ECombatFeatures
|
||||||
ui8 duration;//EDuration
|
ui8 duration;//EDuration //bitfield
|
||||||
ui8 source;//ESource
|
ui8 source;//ESource
|
||||||
si8 positiveness; //+1 - positive, 0 - neutral, -1 - negative; used mostly for spell features
|
si8 positiveness; //+1 - positive, 0 - neutral, -1 - negative; used mostly for spell features
|
||||||
ui16 turnsRemain; //if duration is N_TURNS it describes how long the effect will last
|
ui16 turnsRemain; //if duration is N_TURNS it describes how long the effect will last
|
||||||
@@ -129,7 +130,7 @@ struct StackFeature
|
|||||||
};
|
};
|
||||||
|
|
||||||
//generates StackFeature from given data
|
//generates StackFeature from given data
|
||||||
inline StackFeature makeFeature(StackFeature::ECombatFeatures type, StackFeature::EDuration duration, si16 subtype, si32 value, StackFeature::ESource source, ui16 turnsRemain = 0, si32 additionalInfo = 0)
|
inline StackFeature makeFeature(StackFeature::ECombatFeatures type, ui8 duration, si16 subtype, si32 value, StackFeature::ESource source, ui16 turnsRemain = 0, si32 additionalInfo = 0)
|
||||||
{
|
{
|
||||||
StackFeature sf;
|
StackFeature sf;
|
||||||
sf.type = type;
|
sf.type = type;
|
||||||
|
|||||||
@@ -2332,7 +2332,8 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
if(!curStack->hasFeatureOfType(StackFeature::BLOCKS_RETALIATION)
|
if(!curStack->hasFeatureOfType(StackFeature::BLOCKS_RETALIATION)
|
||||||
&& stackAtEnd->alive()
|
&& stackAtEnd->alive()
|
||||||
&& stackAtEnd->counterAttacks
|
&& stackAtEnd->counterAttacks
|
||||||
&& !stackAtEnd->hasFeatureOfType(StackFeature::SIEGE_WEAPON)) //TODO: support for multiple retaliatons per turn
|
&& !stackAtEnd->hasFeatureOfType(StackFeature::SIEGE_WEAPON)
|
||||||
|
&& !stackAtEnd->hasFeatureOfType(StackFeature::HYPNOTIZED)) //TODO: support for multiple retaliatons per turn
|
||||||
{
|
{
|
||||||
prepareAttack(bat,stackAtEnd,curStack);
|
prepareAttack(bat,stackAtEnd,curStack);
|
||||||
bat.flags |= 2;
|
bat.flags |= 2;
|
||||||
@@ -2654,6 +2655,21 @@ static std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHero
|
|||||||
ret.push_back((*it)->ID);
|
ret.push_back((*it)->ID);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(sp->id == 60) //hypnotize
|
||||||
|
{
|
||||||
|
for(std::set<CStack*>::const_iterator it = affectedCreatures.begin(); it != affectedCreatures.end(); ++it)
|
||||||
|
{
|
||||||
|
if( (*it)->amount * (*it)->MaxHealth() + (*it)->firstHPleft
|
||||||
|
>
|
||||||
|
caster->getPrimSkillLevel(2) * 25 + sp->powers[caster->getSpellSchoolLevel(sp)]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ret.push_back((*it)->ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2767,7 +2783,9 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
|||||||
case 54: //slow
|
case 54: //slow
|
||||||
case 55: //slayer
|
case 55: //slayer
|
||||||
case 56: //frenzy
|
case 56: //frenzy
|
||||||
|
case 60: //hypnotize
|
||||||
case 61: //forgetfulness
|
case 61: //forgetfulness
|
||||||
|
case 62: //blind
|
||||||
{
|
{
|
||||||
SetStackEffect sse;
|
SetStackEffect sse;
|
||||||
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
|
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
|
||||||
|
|||||||
Reference in New Issue
Block a user