1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-23 00:28:08 +02:00

* new spell: blind

* a part of hypnotize support
* minor changes and bugfixes
This commit is contained in:
mateuszb
2009-08-07 11:22:17 +00:00
parent 9d531b0d84
commit 0787b6a79b
6 changed files with 79 additions and 18 deletions

View File

@ -1462,6 +1462,8 @@ bool CBattleInterface::isTileAttackable(const int & number) const
void CBattleInterface::handleEndOfMove(int stackNumber, int destinationTile)
{
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 (movedStack->creature->sounds.endMoving)
@ -2199,7 +2201,7 @@ void CBattleInterface::redrawBackgroundWithHexes(int activeStack)
void CBattleInterface::printConsoleAttacked(int ID, int dmg, int killed, int IDby)
{
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);
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()),

View File

@ -29,7 +29,7 @@
26 -1 12 X X X X
27 1 27 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
31 1 24 0 0 0 X
32 1 23 0 0 0 X
@ -58,11 +58,11 @@
55 1 28 0 0 0 0
56 1 17 0 0 0 0
57 -1 -1 0 0 0 0
58 1 -1 0 0 0 X
59 -1 -1 0 0 0-1 0-2
60 -1 -1 0 0 0 0
58 1 7 0 0 0 X
59 -1 35 0 0 0-1 0-2
60 -1 21 0 0 0 0
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
64 0 -1 X X X X
65 1 -1 0 0 0 0

View File

@ -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 attackDefenseBonus = attacker->Attack() - defender->Defense(),
int attackDefenseBonus,
minDmg = attacker->creature->damageMin * 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;
}
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
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);
}
if(attacker->getEffect(55)) //slayer handling
{
std::vector<int> affectedIds;

View File

@ -600,7 +600,7 @@ DLL_EXPORT void BattleNextRound::applyGs( CGameState *gs )
s->features.clear();
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--;
if(tmpFeatures[i].turnsRemain > 0)
@ -663,6 +663,29 @@ DLL_EXPORT void BattleAttack::applyGs( CGameState *gs )
attacker->shots--;
BOOST_FOREACH(BattleStackAttacked stackAttacked, bsa)
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 )
@ -841,11 +864,18 @@ static std::vector<StackFeature> stackEffectToFeature(const CStack::StackEffect
case 55: //slayer
sf.push_back(featureGenerator(StackFeature::SLAYER, 0, sse.level, sse.turnsRemain));
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
sf.push_back(featureGenerator(StackFeature::SLAYER, 0, sse.level, sse.turnsRemain));
break;
case 56: //frenzy
sf.push_back(featureGenerator(StackFeature::SLAYER, 0, sse.level, sse.turnsRemain));
case 62: //blind
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;
}

View File

@ -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(CATAPULT) \
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(MORE_DAMAGE_FROM_SPELL) /*value - damage increase in %, subtype - spell id*/ \
VCMI_CREATURE_ABILITY_NAME(CASTS_SPELL_WHEN_KILLED) /*similar to spell after attack*/ \
@ -92,10 +93,10 @@ struct StackFeature
enum EDuration
{
WHOLE_BATTLE,
N_TURNS,
UNITL_BEING_ATTACKED,/*removed after attack and counterattacks are performed*/
UNTIL_ATTACK /*removed after attack and counterattacks are performed*/
WHOLE_BATTLE = 1,
N_TURNS = 2,
UNITL_BEING_ATTACKED = 4,/*removed after attack and counterattacks are performed*/
UNTIL_ATTACK = 8 /*removed after attack and counterattacks are performed*/
};
enum ESource
@ -107,7 +108,7 @@ struct StackFeature
};
ui8 type;//ECombatFeatures
ui8 duration;//EDuration
ui8 duration;//EDuration //bitfield
ui8 source;//ESource
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
@ -129,7 +130,7 @@ struct StackFeature
};
//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;
sf.type = type;

View File

@ -2332,7 +2332,8 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
if(!curStack->hasFeatureOfType(StackFeature::BLOCKS_RETALIATION)
&& stackAtEnd->alive()
&& 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);
bat.flags |= 2;
@ -2654,6 +2655,21 @@ static std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHero
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;
}
@ -2767,7 +2783,9 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
case 54: //slow
case 55: //slayer
case 56: //frenzy
case 60: //hypnotize
case 61: //forgetfulness
case 62: //blind
{
SetStackEffect sse;
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)