Explorar el Código

Support for Acid Breath (both effects are now separate).

Minor fixes.
DjWarmonger hace 14 años
padre
commit
515ab7e7c1

+ 2 - 0
client/CBattleInterface.cpp

@@ -2935,6 +2935,8 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
 					else
 						text = "";
 					break;
+				case 81:
+					break; //handled as hero spell - display damage
 				default:
 					boost::algorithm::replace_first(text, "%s", "Creature"); //TODO: better fix
 			}

+ 8 - 5
client/CCreatureWindow.cpp

@@ -240,9 +240,12 @@ void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode *
 		std::vector<si32> spells = battleStack->activeSpells();
 		BOOST_FOREACH(si32 effect, spells)
 		{
-			blitAt(graphics->spellEffectsPics->ourImages[effect + 1].bitmap, 20 + 52 * printed, 184, *bitmap); 
-			if (++printed >= 10) //we can fit only 10 effects
-				break;
+			if (effect < graphics->spellEffectsPics->ourImages.size()) //not all effects have graphics (for eg. Acid Breath)
+			{
+				blitAt(graphics->spellEffectsPics->ourImages[effect + 1].bitmap, 20 + 52 * printed, 184, *bitmap); 
+				if (++printed >= 10) //we can fit only 10 effects
+					break;
+			}
 		}
 		//print current health
 		printLine (5, CGI->generaltexth->allTexts[200], battleStack->firstHPleft);
@@ -314,8 +317,8 @@ void CCreatureWindow::showAll(SDL_Surface * to)
 		printTo(count, 117, 174, FONT_SMALL, tytulowy,*bitmap);
 	printAtMiddle(c->namePl, 180, 30, FONT_SMALL, tytulowy,*bitmap); //creature name
 
-	printLine(0, CGI->generaltexth->primarySkillNames[0], c->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK), stackNode->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK));
-	printLine(1, CGI->generaltexth->primarySkillNames[1], c->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE), stackNode->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE));
+	printLine(0, CGI->generaltexth->primarySkillNames[0], c->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK), stackNode->Attack());
+	printLine(1, CGI->generaltexth->primarySkillNames[1], c->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE), stackNode->Defense());
 	//if(c->shots)
 	//	printLine(2, CGI->generaltexth->allTexts[198], c->shots);
 	if(stackNode->valOfBonuses(Bonus::SHOTS))

+ 14 - 12
config/cr_abils.txt

@@ -179,22 +179,24 @@
 + 133 DRAGON_NATURE 0 0 0			//crystal dragon is a dragon			
 + 134 DRAGON_NATURE 0 0 0			//faerie dragon is a dragon			
 + 135 DRAGON_NATURE 0 0 0			//rust dragon is a dragon			
++ 135 ACID_BREATH 25 0 20			//20% chance to do 25 damage			
++ 135 SPELL_AFTER_ATTACK 100 80 0			//always reduce defense			
 + 136 NO_OBSTACLES_PENALTY 0 0 0			//Enchanter			
 + 137 NO_DISTANCE_PENALTY 0 0 0			//Sharpshooter			
 + 137 NO_OBSTACLES_PENALTY 0 0 0						
 + 140 DOUBLE_WIDE 0 0 0 			//boar should be treated as double-wide			
-+ 142 DOUBLE_WIDE 0 0 0 			//nomads should be treated as double-wide			
-+ 144 FULL_HP_REGENERATION 0 0 0 			//troll			
-+ 147 HEALER 0 0 0					//first aid tent can heal	
-+ 148 NOT_ACTIVE 0 0 0				//Ammo Cart		
-+ 149 SHOOTER 0 0 0					//arrow turret	
++ 142 DOUBLE_WIDE 0 0 0 			//nomads should be treated as double-wide		//first aid tent can heal	
++ 144 FULL_HP_REGENERATION 0 0 0 			//troll	//Ammo Cart		
++ 147 HEALER 0 0 0					//arrow turret	
++ 148 NOT_ACTIVE 0 0 0						
++ 149 SHOOTER 0 0 0						
 + 151 DRAGON_NATURE 0 0 0			//diamond dragon is a dragon			
-+ 154 DRAGON_NATURE 0 0 0			//blood dragon is a dragon			
-+ 155 DRAGON_NATURE 0 0 0			//darkness dragon is a dragon			
-+ 168 FLYING 0 0 0					//Gorynyches fly	
--  46 FLYING		  				//hell hound doesn't fly
--  47 FLYING			  			//cerberus doesn't fly
-- 120 DOUBLE_WIDE					//psychic elemental	
-- 121 DOUBLE_WIDE					//magic elemental	
++ 154 DRAGON_NATURE 0 0 0			//blood dragon is a dragon		//Gorynyches fly	
++ 155 DRAGON_NATURE 0 0 0			//darkness dragon is a dragon			//hell hound doesn't fly
++ 168 FLYING 0 0 0						//cerberus doesn't fly
+-  46 FLYING		  			//psychic elemental	
+-  47 FLYING			  		//magic elemental	
+- 120 DOUBLE_WIDE						
+- 121 DOUBLE_WIDE						
 - 157 SHOOTER	//Hell Hydra certainly does not shoot					
 0						

+ 7 - 1
lib/BattleState.cpp

@@ -1792,7 +1792,7 @@ SpellCasting::ESpellCastProblem BattleInfo::battleIsImmune(const CGHeroInstance
 		}
 
 		if(subject->hasBonusOfType(Bonus::SPELL_IMMUNITY, spell->id) ||
-			( immunities.size() > 0 && immunities.totalValue() >= spell->level)) //many creature abilities have level equal to 0 by default, fixed in config\spell_levels
+			( immunities.size() > 0 && immunities.totalValue() >= spell->level && spell->level))
 		{ 
 			return SpellCasting::STACK_IMMUNE_TO_SPELL;
 		}
@@ -2167,6 +2167,12 @@ void CStack::stackEffectToFeature(std::vector<Bonus> & sf, const Bonus & sse)
 		sf.push_back(featureGeneratorVT(Bonus::STACK_HEALTH, 0, -50, 3, Bonus::PERCENT_TO_ALL));
 		sf.back().sid = sse.sid;
 		break;
+	case 80: //Acid Breath
+		sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, -3, 1));
+	 	sf.back().sid = sse.sid;
+		sf.back().duration = Bonus::PERMANENT;
+		sf.back().valType = Bonus::ADDITIVE_VALUE;
+		break;
 	}
 }
 

+ 20 - 19
lib/CSpellHandler.cpp

@@ -322,23 +322,24 @@ void CSpellHandler::loadSpells()
 		}
 	}
 	ast.close();
-	ast.open(DATA_DIR "/config/spell_levels.txt", std::ios::binary);
-	if(!ast.is_open())
-	{
-		tlog1<<"lack of config/spell_levels.txt file!"<<std::endl;
-	}
-	else
-	{
-		//custom levels of spells. Level 0 seems to not be supported correctly, but we can replace it it something else
-		int spellID;
-		ast>>spellID;
-		int buf;
-		while(spellID != -1)
-		{
-			ast >> buf;
-			spells[spellID]->level = buf;
-			ast>>spellID;
-		}
-	}
-	ast.close();
+	//ast.open(DATA_DIR "/config/spell_levels.txt", std::ios::binary);
+	//if(!ast.is_open())
+	//{
+	//	tlog1<<"lack of config/spell_levels.txt file!"<<std::endl;
+	//}
+	//else
+	//{
+	//	//custom levels of spells. Level 0 seems to not be supported correctly, but we can replace it it something else
+	//	int spellID;
+	//	ast>>spellID;
+	//	int buf;
+	//	while(spellID != -1)
+	//	{
+	//		ast >> buf;
+	//		spells[spellID]->level = buf;
+	//		ast>>spellID;
+	//	}
+	//}
+	//ast.close();
+	spells.push_back(spells[80]); //clone Acid Breath attributes for Acid Breath damage effect
 }

+ 2 - 0
lib/HeroBonus.cpp

@@ -269,6 +269,7 @@ si32 IBonusBearer::Attack() const
 	{
 		ret += frenzyPower * Defense(false);
 	}
+	amax(ret, 0);
 
 	return ret;
 }
@@ -281,6 +282,7 @@ si32 IBonusBearer::Defense(bool withFrenzy /*= true*/) const
 	{
 		return 0;
 	}
+	amax(ret, 0);
 
 	return ret;
 }

+ 2 - 1
lib/HeroBonus.h

@@ -159,7 +159,8 @@ namespace PrimarySkill
 	BONUS_NAME(SHOTS)\
 	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(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*/
 
 /// Struct for handling bonuses of several types. Can be transfered to any hero
 struct DLL_EXPORT Bonus

+ 35 - 4
server/CGameHandler.cpp

@@ -3397,10 +3397,11 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
 			continue;
 		sc.dmgToDisplay += gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl, usedSpellPower);
 	}
-	if (spellID == 79) // Death stare
+	if (spellID == 79 || spellID == 81) // Death stare or Acid Breath
 	{
 		sc.dmgToDisplay = usedSpellPower;
-		amin(sc.dmgToDisplay, (*attackedCres.begin())->count); //stack is already reduced after attack
+		if (spellID == 79)
+			amin(sc.dmgToDisplay, (*attackedCres.begin())->count); //stack is already reduced after attack
 	}
 
 	//applying effects
@@ -3474,6 +3475,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
 	case 73: //Disease
 	case 74: //Paralyze
 	case 75: //Aging
+	case 80: //Acid Breath defense reduction
 		{
 			SetStackEffect sse;
 			Bonus pseudoBonus;
@@ -3529,7 +3531,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
  				}
 				if (caster && caster->hasBonusOfType(Bonus::SPECIAL_BLESS_DAMAGE, spellID)) //TODO: better handling of bonus percentages
  	 			{
- 	 				int damagePercent = caster->level * caster->valOfBonuses(Bonus::SPECIAL_BLESS_DAMAGE, 41) / tier;
+ 	 				int damagePercent = caster->level * caster->valOfBonuses(Bonus::SPECIAL_BLESS_DAMAGE, spellID) / tier;
 					Bonus specialBonus = CStack::featureGenerator(Bonus::CREATURE_DAMAGE, 0, damagePercent, pseudoBonus.turnsRemain);
 					specialBonus.valType = Bonus::PERCENT_TO_ALL;
 					specialBonus.sid = spellID;
@@ -3617,10 +3619,27 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
 				sendAndApply(&si);
 		}
 		break;
+	case 81: //Acid breath damage - new effect, separate from acid breath defense reduction
+		{
+			StacksInjured si;
+			for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it) //no immunities
+			{
+				BattleStackAttacked bsa;
+				bsa.flags |= BattleStackAttacked::EFFECT;
+				bsa.effect = VLC->spellh->spells[80]->mainEffectAnim; //use acid breath 
+				bsa.damageAmount = usedSpellPower; //damage times the number of attackers
+				bsa.stackAttacked = (*it)->ID;
+				bsa.attackerID = -1;
+				(*it)->prepareAttacked(bsa);
+				si.stacks.push_back(bsa);
+			}
+			if(!si.stacks.empty())
+				sendAndApply(&si);
+		}
+		break;
 	}
 
 	sendAndApply(&sc);
-
 }
 
 bool CGameHandler::makeCustomAction( BattleAction &ba )
@@ -4286,6 +4305,18 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat )
 				!attacker->attackerOwned, attacker->owner, NULL, NULL, staredCreatures, SpellCasting::AFTER_ATTACK_CASTING);
 		}
 	}
+	int acidDamage = 0;
+	BOOST_FOREACH(const Bonus *b, attacker->getBonuses(Selector::type(Bonus::ACID_BREATH)))
+	{
+		if (b->additionalInfo > rand()%100)
+			acidDamage += b->val;
+	}
+	if (acidDamage)
+	{
+		handleSpellCasting(81, 0, gs->curB->getStack(bat.bsa[0].stackAttacked)->position,
+				!attacker->attackerOwned, attacker->owner, NULL, NULL,
+				acidDamage * attacker->count, SpellCasting::AFTER_ATTACK_CASTING);
+	}
 }
 
 bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &pos)