Browse Source

Partial support for immunities & receptive ability.

TODO: Immunity to direct damage spells.
DjWarmonger 14 years ago
parent
commit
bc114a89f4
4 changed files with 114 additions and 3 deletions
  1. 57 0
      lib/BattleState.cpp
  2. 49 0
      lib/CCreatureHandler.cpp
  3. 1 1
      lib/HeroBonus.cpp
  4. 7 2
      lib/HeroBonus.h

+ 57 - 0
lib/BattleState.cpp

@@ -1785,6 +1785,63 @@ SpellCasting::ESpellCastProblem BattleInfo::battleIsImmune(const CGHeroInstance
 	const CStack * subject = getStackT(dest, false);
 	if(subject)
 	{
+		if (spell->positiveness ==1 && subject->hasBonusOfType(Bonus::RECEPTIVE)) //accept all positive spells
+			return SpellCasting::OK;
+
+		if (spell->fire)
+		{
+
+			if (spell->positiveness == -1) //negative
+			{
+				if (subject->hasBonusOfType(Bonus::FIRE_IMMUNITY)) //both damage and curse spells, TODO: separate them
+					return SpellCasting::STACK_IMMUNE_TO_SPELL;
+			}
+			else if (spell->positiveness == 1)
+			{
+				if (subject->hasBonusOfType(Bonus::FIRE_IMMUNITY, 1))
+					return SpellCasting::STACK_IMMUNE_TO_SPELL;
+			}
+		}
+		if (spell->water)
+		{
+			if (spell->positiveness == -1) //negative
+			{
+				if (subject->hasBonusOfType(Bonus::WATER_IMMUNITY)) //both damage and curse spells, TODO: separate them
+					return SpellCasting::STACK_IMMUNE_TO_SPELL;
+			}
+			else if (spell->positiveness == 1)
+			{
+				if (subject->hasBonusOfType(Bonus::WATER_IMMUNITY, 1))
+					return SpellCasting::STACK_IMMUNE_TO_SPELL;
+			}
+		}
+		if (spell->earth)
+		{
+			if (spell->positiveness == -1) //negative
+			{
+				if (subject->hasBonusOfType(Bonus::EARTH_IMMUNITY)) //both damage and curse spells, TODO: separate them
+					return SpellCasting::STACK_IMMUNE_TO_SPELL;
+			}
+			else if (spell->positiveness == 1)
+			{
+				if (subject->hasBonusOfType(Bonus::EARTH_IMMUNITY, 1))
+					return SpellCasting::STACK_IMMUNE_TO_SPELL;
+			}
+		}
+		if (spell->air)
+		{
+			if (spell->positiveness == -1) //negative
+			{
+				if (subject->hasBonusOfType(Bonus::AIR_IMMUNITY)) //both damage and curse spells, TODO: separate them
+					return SpellCasting::STACK_IMMUNE_TO_SPELL;
+			}
+			else if (spell->positiveness == 1)
+			{
+				if (subject->hasBonusOfType(Bonus::AIR_IMMUNITY, 1))
+					return SpellCasting::STACK_IMMUNE_TO_SPELL;
+			}
+		}
+
 		BonusList immunities = subject->getBonuses(Selector::type(Bonus::LEVEL_SPELL_IMMUNITY));
 		if(subject->hasBonusOfType(Bonus::NEGATE_ALL_NATURAL_IMMUNITIES))
 		{

+ 49 - 0
lib/CCreatureHandler.cpp

@@ -850,6 +850,9 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, std::string & src
 		break;
 	case 'R':
 		b.type = Bonus::ADDITIONAL_RETALIATION; break;
+	case 'W':
+		b.type = Bonus::MAGIC_RESISTANCE;
+		break;
 
 	case 'f': //on-off skill
 		enable = true; //sometimes format is: 2 -> 0, 1 -> 1
@@ -939,6 +942,52 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, std::string & src
 				b.type = Bonus::LEVEL_SPELL_IMMUNITY;
 				b.val = SPELL_LEVELS; //in case someone adds higher level spells?
 				break;
+			case 'F':
+				b.type = Bonus::FIRE_IMMUNITY;
+				b.subtype = 1; //not positive
+				break;
+			case 'O':
+				b.type = Bonus::FIRE_IMMUNITY;
+				b.subtype = 2; //only direct damage
+				break;
+			case 'f':
+				b.type = Bonus::FIRE_IMMUNITY;
+				b.subtype = 0; //all
+				break;
+			case 'C':
+				b.type = Bonus::WATER_IMMUNITY;
+				b.subtype = 1; //not positive
+				break;
+			case 'W':
+				b.type = Bonus::WATER_IMMUNITY;
+				b.subtype = 2; //only direct damage
+				break;
+			case 'w':
+				b.type = Bonus::WATER_IMMUNITY;
+				b.subtype = 0; //all
+				break;
+			case 'E':
+				b.type = Bonus::EARTH_IMMUNITY;
+				b.subtype = 2; //only direct damage
+				break;
+			case 'e':
+				b.type = Bonus::EARTH_IMMUNITY;
+				b.subtype = 0; //all
+				break;
+			case 'A':
+				b.type = Bonus::AIR_IMMUNITY;
+				b.subtype = 2; //only direct damage
+				break;
+			case 'a':
+				b.type = Bonus::AIR_IMMUNITY;
+				b.subtype = 0; //all
+				break;
+			case 'D':
+				b.type = Bonus::DIRECT_DAMAGE_IMMUNITY;
+				break;
+			case '0':
+				b.type = Bonus::RECEPTIVE;
+				break;
 			default:
 				tlog3 << "Not parsed bonus " << buf << mod << "\n";
 				return;

+ 1 - 1
lib/HeroBonus.cpp

@@ -289,7 +289,7 @@ si32 IBonusBearer::Defense(bool withFrenzy /*= true*/) const
 
 ui16 IBonusBearer::MaxHealth() const
 {
-	return valOfBonuses(Bonus::STACK_HEALTH);
+	return std::max(1, valOfBonuses(Bonus::STACK_HEALTH)); //never 0 or negative
 }
 
 ui32 IBonusBearer::getMinDamage() const

+ 7 - 2
lib/HeroBonus.h

@@ -106,7 +106,10 @@ namespace PrimarySkill
 	BONUS_NAME(SPELL_LIKE_ATTACK) /*value - spell id; range is taken from spell, but damage from creature; eg. magog*/ \
 	BONUS_NAME(THREE_HEADED_ATTACK) /*eg. cerberus*/	\
 	BONUS_NAME(DAEMON_SUMMONING) /*pit lord*/			\
-	BONUS_NAME(FIRE_IMMUNITY)							\
+	BONUS_NAME(FIRE_IMMUNITY)	/*subtype 0 - all, 1 - all except positive, 2 - only damage spells*/						\
+	BONUS_NAME(WATER_IMMUNITY)							\
+	BONUS_NAME(EARTH_IMMUNITY)							\
+	BONUS_NAME(AIR_IMMUNITY)							\
 	BONUS_NAME(FIRE_SHIELD)								\
 	BONUS_NAME(UNDEAD)									\
 	BONUS_NAME(HP_REGENERATION) /*creature regenerates val HP every new round*/					\
@@ -160,7 +163,9 @@ namespace PrimarySkill
 	BONUS_NAME(DEATH_STARE) /*subtype 0 - gorgon, 1 - commander*/\
 	BONUS_NAME(POISON) /*val - max health penalty from poison possible*/\
 	BONUS_NAME(BIND_EFFECT) /*doesn't do anything particular, works as a marker)*/\
-	BONUS_NAME(ACID_BREATH) /*additional val damage per creature after attack, additional info - chance in percent*/
+	BONUS_NAME(ACID_BREATH) /*additional val damage per creature after attack, additional info - chance in percent*/\
+	BONUS_NAME(RECEPTIVE) /*accepts friendly spells even with immunity*/\
+	BONUS_NAME(DIRECT_DAMAGE_IMMUNITY) /*direct damage spells, that is*/
 
 /// Struct for handling bonuses of several types. Can be transfered to any hero
 struct DLL_EXPORT Bonus