Jelajahi Sumber

Some more work on bonus-to-string feature.

DjWarmonger 14 tahun lalu
induk
melakukan
c11f7c2020
6 mengubah file dengan 117 tambahan dan 40 penghapusan
  1. 41 27
      config/bonusnames.txt
  2. 21 5
      hch/CCreatureHandler.cpp
  3. 3 0
      hch/CCreatureHandler.h
  4. 0 3
      hch/CGeneralTextHandler.h
  5. 51 4
      lib/CCreatureSet.cpp
  6. 1 1
      lib/HeroBonus.h

+ 41 - 27
config/bonusnames.txt

@@ -1,27 +1,41 @@
-"Bonus"	"Name (24 characters?)"	"Description"
-"FLYING"	"Fly"	"Can Fly (ignores obstacles)"
-"UNLIMITED_RETALIATIONS"	"Unlimited retaliations"	"May retaliate any number of attacks"
-"SHOOTER"	"Ranged"	"Creature can make a Ranged Attack"
-"FREE_SHOOTING"	"Shoot Close"	"Can make a Ranged Attack in Close Combat"
-"NO_SHOTING_PENALTY"	"?"	"???"
-"NO_MELEE_PENALTY"	"No melee penalty"	"Creature has no Melee Penalty"
-"NO_DISTANCE_PENALTY"	"No distance penalty"	"Does full ranged damage from any distance"
-"NO_OBSTACLES_PENALTY"	"No obstacle penalty"	"Creature has no Obstacle Penalty"
-"JOUSTING"	"Champion"	"Champion Distance Bonus (+5% damage per square travelled)"
-"RETURN_AFTER_STRIKE"	"Attack and Return"	"Returns to starting position after making a melee attack"
-"BLOCKS_RETALIATION"	"No retaliation"	"Enemy cannot Retaliate"
-"TWO_HEX_ATTACK_BREATH"	"Breath"	"Creature has a Breath Attack (2-hex range)"
-"THREE_HEADED_ATTACK"	"Three-headed attack"	"Creature attacks three adjacent units"
-"ATTACKS_ALL_ADJACENT"	"Attack all around"	"Creature attacks all adjacent enemies"
-"FULL_HP_REGENERATION"	"Regeneration"	"May Regenerate full Health"
-"LIFE_DRAIN"	"Drain life"	"Drains life equal to damage dealt"
-"SELF_MORALE"	"Positive morale"	"Always has Positive Morale"
-"SELF_LUCK"	"Positive luck"	"Always has Positive Luck"
-"FEAR"	"Fear"	"Has a chance to cause Fear on an enemy stack"
-"FEARLESS"	"Fearless"	"Immune to Fear ability"
-"CHARGE_IMMUNITY"	"Immune to Charge"	"Immune to Champion charge bonus"
-"HEALER"	"Healer"	"Heals allied units"
-"CATAPULT "	"Catapult"	"Attacks siege walls"
-"DRAGON_NATURE"	"Dragon"	"Creature has a Dragon Nature"
-"NON_LIVING"	"Non living"	"Creature is immune to effects affecting Living units"
-"UNDEAD"	"Undead"	"Creature is Undead"
+Bonus	Name (24 characters?)	Description
+FLYING	Fly	Can Fly (ignores obstacles)
+UNLIMITED_RETALIATIONS	Unlimited retaliations	May retaliate any number of attacks
+SHOOTER	Ranged	Creature can make a Ranged Attack
+FREE_SHOOTING	Shoot Close	Can make a Ranged Attack in Close Combat
+NO_SHOTING_PENALTY	?	???
+NO_MELEE_PENALTY	No melee penalty	Creature has no Melee Penalty
+NO_DISTANCE_PENALTY	No distance penalty	Does full ranged damage from any distance
+NO_OBSTACLES_PENALTY	No obstacle penalty	Creature has no Obstacle Penalty
+JOUSTING	Champion	Champion Distance Bonus (+5% damage per square travelled)
+RETURN_AFTER_STRIKE	Attack and Return	Returns to starting position after making a melee attack
+BLOCKS_RETALIATION	No retaliation	Enemy cannot Retaliate
+TWO_HEX_ATTACK_BREATH	Breath	Creature has a Breath Attack (2-hex range)
+THREE_HEADED_ATTACK	Three-headed attack	Creature attacks three adjacent units
+ATTACKS_ALL_ADJACENT	Attack all around	Creature attacks all adjacent enemies
+FULL_HP_REGENERATION	Regeneration	May Regenerate full Health
+LIFE_DRAIN	Drain life	Drains life equal to damage dealt
+SELF_MORALE	Positive morale	Always has Positive Morale
+SELF_LUCK	Positive luck	Always has Positive Luck
+FEAR	Fear	Has a chance to cause Fear on an enemy stack
+FEARLESS	Fearless	Immune to Fear ability
+CHARGE_IMMUNITY	Immune to Charge	Immune to Champion charge bonus
+HEALER	Healer	Heals allied units
+CATAPULT 	Catapult	Attacks siege walls
+DRAGON_NATURE	Dragon	Creature has a Dragon Nature
+NON_LIVING	Non living	Creature is immune to effects affecting Living units
+UNDEAD	Undead	Creature is Undead
+HATE	Hates %s	Does more damage to %s
+DOUBLE_DAMAGE_CHANCE	Death Blow	Has %d% chance to deal double damage
+MAGIC_RESISTANCE	Magic Resistance	Has %d% chance to resist enemy spell
+SPELL_DAMAGE_REDUCTION	Spell Resistance	Damage from spells reduced 50%.
+LEVEL_SPELL_IMMUNITY	Spell immunity 1-%d	Immune to spells levels 1-%d
+HP_REGENERATION	Regeneration	Heals %d hit points every round
+SPELL_IMMUNITY	Immune to %s	Immune to %s spell
+ENEMY_DEFENCE_REDUCTION	Reduces Enemy Defense	Reduces Enemy Defense by %d% for this attack
+MAGIC_MIRROR	Magic Mirror	Has %d% chance to redirect offensive spell back to enemy
+ADDITIONAL_RETALIATION	Additional retaliations	May Retaliate %d extra times
+CHANGES_SPELL_COST_FOR_ALLY	Reduce Casting Cost 	Reduce Casting Cost of allied hero spells by %d
+CHANGES_SPELL_COST_FOR_ENEMY	Magic Damper	Increase Casting Cost of enemy hero spells by %d
+MANA_CHANNELING	Magic Channel	%d% mana spent by enemy is transfered to your hero
+SPELL_AFTER_ATTACK	Caster - %s	%d% chance to cast %s after attack

+ 21 - 5
hch/CCreatureHandler.cpp

@@ -467,11 +467,6 @@ void CCreatureHandler::loadCreatures()
 		{
 			int id, lvl;
 			ifs >> id >> lvl;
-			if(lvl>0)
-			{
-				creatures[id]->level = lvl;
-				levelCreatures[lvl].push_back(creatures[id]);
-			}
 		}
 	}
 	ifs.close();
@@ -579,6 +574,27 @@ void CCreatureHandler::loadCreatures()
 		inp3 >> factionToTurretCreature[g];
 	}
 	inp3.close();
+
+	//reading creature ability names
+	ifs.open(DATA_DIR "/config/bonusnames.txt");
+	{
+		std::string buf2, buf3, line;
+		int i;
+		std::map<std::string,int>::const_iterator it;
+		getline(ifs, line); //skip 1st line
+		while(!ifs.eof())
+		{
+			getline(ifs, buf, '\t');
+			getline(ifs, buf2, '\t');
+			getline(ifs, buf3);
+			it = bonusNameMap.find(buf);
+			if (it != bonusNameMap.end())
+				stackBonuses[it->second] = std::pair<std::string, std::string>(buf2,buf3);
+			else
+				tlog2 << "Bonus " << buf << " not recognized, ingoring\n";
+		}
+	}
+	ifs.close();
 }
 
 void CCreatureHandler::loadAnimationInfo()

+ 3 - 0
hch/CCreatureHandler.h

@@ -110,6 +110,9 @@ public:
 	std::vector<si8> factionAlignments; //1 for good, 0 for neutral and -1 for evil with faction ID as index
 	int factionToTurretCreature[F_NUMBER]; //which creature's animation should be used to dispaly creature in turret while siege
 
+	//bonus names and descriptions
+	std::map<TBonusType, std::pair<std::string, std::string>> stackBonuses; // bonus => name, description
+
 	void loadCreatures();
 	void loadAnimationInfo();
 	void loadUnitAnimInfo(CCreature & unit, std::string & src, int & i);

+ 0 - 3
hch/CGeneralTextHandler.h

@@ -74,9 +74,6 @@ public:
 	std::vector <std::vector <std::string> > skillInfoTexts; //[id][level] : level 0 - basic; 2 - advanced
 	std::vector<std::string> levels;
 
-	//bonuses
-	std::map<TBonusType, std::pair<std::string, std::string>> stackBonuses; // bonus => name, description
-
 	//campaigns
 	std::vector <std::string> campaignMapNames;
 	std::vector < std::vector <std::string> > campaignRegionNames;

+ 51 - 4
lib/CCreatureSet.cpp

@@ -7,6 +7,9 @@
 #include "IGameCallback.h"
 #include "CGameState.h"
 #include "../hch/CGeneralTextHandler.h"
+#include "../hch/CSpellHandler.h"
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string/replace.hpp>
 
 const CStackInstance CCreatureSet::operator[](TSlot slot) const
 {
@@ -279,11 +282,11 @@ void CStackInstance::getParents(TCNodes &out, const CBonusSystemNode *source /*=
 }
 std::string CStackInstance::bonusToString(Bonus *bonus, bool description) const
 {
-	std::map<TBonusType, std::pair<std::string, std::string>>::iterator it = VLC->generaltexth->stackBonuses.find(bonus->type);
-	if (it != VLC->generaltexth->stackBonuses.end())
+	std::map<TBonusType, std::pair<std::string, std::string>>::iterator it = VLC->creh->stackBonuses.find(bonus->type);
+	if (it != VLC->creh->stackBonuses.end())
 	{
 		std::string text;
-		if (description)
+		if (description) //long ability description
 		{
 			text = it->second.second;
 			switch (bonus->type)
@@ -316,11 +319,55 @@ std::string CStackInstance::bonusToString(Bonus *bonus, bool description) const
 				case Bonus::NON_LIVING:
 				case Bonus::UNDEAD:
 				break;
+				//One numeric value
+				//case Bonus::STACKS_SPEED: //Do we need description for creature stats?
+				//case Bonus::STACK_HEALTH:
+				case Bonus::MAGIC_RESISTANCE:
+				case Bonus::SPELL_DAMAGE_REDUCTION:
+				case Bonus::LEVEL_SPELL_IMMUNITY:
+				case Bonus::CHANGES_SPELL_COST_FOR_ALLY:
+				case Bonus::CHANGES_SPELL_COST_FOR_ENEMY:
+				case Bonus::MANA_CHANNELING:
+				case Bonus::MANA_DRAIN:
+				case Bonus::HP_REGENERATION:
+				case Bonus::ADDITIONAL_RETALIATION:
+				case Bonus::DOUBLE_DAMAGE_CHANCE:
+				case Bonus::ENEMY_DEFENCE_REDUCTION:
+				case Bonus::MAGIC_MIRROR:
+				case Bonus::DARKNESS: //Darkness Dragons any1?
+					boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(bonus->val));
+					break;
+				//Complex descriptions
+				case Bonus::HATE: //TODO: customize damage percent
+					boost::algorithm::replace_first(text, "%s", VLC->creh->creatures[bonus->subtype]->namePl);
+					break;
+				case Bonus::SPELL_IMMUNITY:
+					boost::algorithm::replace_first(text, "%s", VLC->spellh->spells[bonus->subtype].name);
+					break;
+				case Bonus::SPELL_AFTER_ATTACK:
+					boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(bonus->additionalInfo % 100));
+					boost::algorithm::replace_first(text, "%s", VLC->spellh->spells[bonus->subtype].name);
+					break;
+				default:
+					{}//TODO: allow custom bonus types... someday, somehow
 			}
 		}
-		else
+		else //short name
 		{
 			text = it->second.first;
+			switch (bonus->type)
+			{
+				case Bonus::HATE:
+					boost::algorithm::replace_first(text, "%s", VLC->creh->creatures[bonus->subtype]->namePl);
+					break;
+				case Bonus::LEVEL_SPELL_IMMUNITY:
+					boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(bonus->val));
+					break;
+				case Bonus::SPELL_IMMUNITY:
+				case Bonus::SPELL_AFTER_ATTACK:
+					boost::algorithm::replace_first(text, "%s", VLC->spellh->spells[bonus->subtype].name);
+					break;
+			}
 		}
 		return text;
 	}

+ 1 - 1
lib/HeroBonus.h

@@ -152,7 +152,7 @@ namespace PrimarySkill
 	BONUS_NAME(MAXED_SPELL) /*val = id*/\
 	BONUS_NAME(SPECIAL_PECULIAR_ENCHANT) /*blesses and curses with id = val dependent on unit's level, subtype = 0 or 1 for Coronius*/\
 	BONUS_NAME(SPECIAL_UPGRADE) /*val = base, additionalInfo = target */\
-	BONUS_NAME(DRAGON_NATURE) /*TODO: implement it!*/\
+	BONUS_NAME(DRAGON_NATURE) \
 	BONUS_NAME(CREATURE_DAMAGE)/*subtype 0 = both, 1 = min, 2 = max*/
 
 struct DLL_EXPORT Bonus