浏览代码

- Config settings & parsing for Commanders.
- Fix for Regeneration icon

DjWarmonger 13 年之前
父节点
当前提交
81e74f8c33

+ 2 - 2
client/BattleInterface/CBattleInterface.cpp

@@ -3005,7 +3005,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 
 bool CBattleInterface::isCastingPossibleHere (const CStack * sactive, const CStack * shere, BattleHex myNumber)
 {
-	creatureCasting = stackCanCastSpell; //is it really useful?
+	creatureCasting = stackCanCastSpell && !spellDestSelectMode; //TODO: allow creatures to cast aimed spells
 							
 	bool isCastingPossible = true;
 
@@ -3022,7 +3022,7 @@ bool CBattleInterface::isCastingPossibleHere (const CStack * sactive, const CSta
 	if (spellID >= 0) 
 		sp = CGI->spellh->spells[spellID];
 
-	if (sp) //TODO: refactor?
+	if (sp)
 	{
 		if (creatureCasting)
 			isCastingPossible = (curInt->cb->battleCanCreatureCastThisSpell (sp, myNumber) == ESpellCastProblem::OK);

+ 55 - 0
config/commanders.json

@@ -0,0 +1,55 @@
+
+{
+	//Map faction - commander creature
+	//Using "attacking creature" from WoG - whatever it means
+	"factionCreatures":
+	[
+		{"faction": 0, "id": 174},
+		{"faction": 1, "id": 175},
+		{"faction": 2, "id": 176},
+		{"faction": 3, "id": 177},
+		{"faction": 4, "id": 178},
+		{"faction": 5, "id": 179},
+		{"faction": 6, "id": 180},
+		{"faction": 7, "id": 181},
+		{"faction": 8, "id": 182}
+	],
+	//Commander receives these bonuses on level-up
+	"bonusPerLevel":
+	[
+		["CREATURE_DAMAGE", 1, 1, 0 ], //+1 minimum damage
+		["CREATURE_DAMAGE", 2, 2, 0 ], //+2 maximum damage
+		["STACK_HEALTH", 5, 0, 0 ] //+5 hp
+	],
+	//Value of bonuses given by each skill level
+	"skillLevels":
+	[
+		{"ATTACK": [2, 5, 9, 15, 25]}, //0
+		{"DEFENSE": [4, 10, 18, 30, 50]}, //1
+		{"HEALTH": [10, 25, 45, 70, 100]}, //2
+		{"DAMAGE": [10, 25, 45, 70, 100]}, //3
+		{"SPEED": [1, 2, 3, 4, 6]}, //4
+		{"SPELL_POWER":[1, 3, 6, 14, 29]}, //5
+		{"CASTS": [1, 2, 3, 4, 5]},
+		{"RESISTANCE": [5, 15, 35, 60, 90]}
+	],
+	"abilityRequiremenets":
+	//Two secondary skills needed for each special ability
+	[
+		{"ability": ["ENEMY_DEFENCE_REDUCTION", 50, 0, 0 ], "skills": [0, 1]},
+		{"ability": ["FEAR", 0, 0, 0 ], "skills": [0, 2]},
+		{"ability": ["ALWAYS_MAXIMUM_DAMAGE", 0, -1, 0 ], "skills": [0, 3]},
+		{"ability": ["SHOOTER", 0, 0, 0 ], "skills": [0, 4]},
+		{"ability": ["BLOCKS_RETALIATION", 0, 1, 0 ], "skills": [0,5]},
+		{"ability": ["UNLIMITED_RETALIATIONS", 0, 0, 0 ], "skills": [1, 2]},
+		{"ability": ["ATTACKS_ALL_ADJACENT", 0, 0, 0 ], "skills": [1, 3]},
+		{"ability": ["BLOCK", 30, 0, 0 ], "skills": [1, 4]},
+		{"ability": ["FIRE_SHIELD", 1, 1, 0 ], "skills": [1, 5]},
+		{"ability": ["ADDITIONAL_ATTACK", 1, 0, 0 ], "skills": [2, 3]},
+		{"ability": ["HP_REGENERATION", 50, 0, 0 ], "skills": [2, 4]},
+		{"ability": ["SPELL_AFTER_ATTACK", 30, 74, 0 ], "skills": [2, 5]},
+		{"ability": ["JOUSTING", 0, 0, 0 ], "skills": [3, 4]},
+		{"ability": ["DEATH_STARE", 1, 1, 0 ], "skills": [3,5]},
+		{"ability": ["FLYING", 0, 0, 0 ], "skills": [4,5]}
+	]
+}

+ 65 - 9
lib/CCreatureHandler.cpp

@@ -191,6 +191,24 @@ bool CCreatureHandler::isEvil (si8 faction) const
 {
 	return faction != -1 && factionAlignments[faction] == -1;
 }
+static Bonus ParseBonus (const JsonVector &ability_vec) //TODO: merge with AddAbility, create universal parser for all bonus properties
+{
+	Bonus b;
+	std::string type = ability_vec[0].String();
+	auto it = bonusNameMap.find(type);
+	if (it == bonusNameMap.end())
+	{
+		tlog1 << "Error: invalid ability type " << type << " in creatures.txt" << std::endl;
+		return b;
+	}
+	b.type = it->second;
+	b.val = ability_vec[1].Float();
+	b.subtype = ability_vec[2].Float();
+	b.additionalInfo = ability_vec[3].Float();
+	b.duration = Bonus::PERMANENT;
+	b.turnsRemain = 0;
+	return b;
+}
 
 static void AddAbility(CCreature *cre, const JsonVector &ability_vec)
 {
@@ -402,12 +420,14 @@ void CCreatureHandler::loadCreatures()
 	tlog5 << "\t\tReading config/creatures.json" << std::endl;
 	const JsonNode config(GameConstants::DATA_DIR + "/config/creatures.json");
 
-	BOOST_FOREACH(const JsonNode &creature, config["creatures"].Vector()) {
+	BOOST_FOREACH(const JsonNode &creature, config["creatures"].Vector())
+	{
 		int creatureID = creature["id"].Float();
 		const JsonNode *value;
 
 		/* A creature can have several names. */
-		BOOST_FOREACH(const JsonNode &name, creature["name"].Vector()) {
+		BOOST_FOREACH(const JsonNode &name, creature["name"].Vector())
+		{
 			boost::assign::insert(nameToID)(name.String(), creatureID);
 		}
 
@@ -422,7 +442,8 @@ void CCreatureHandler::loadCreatures()
 			c->upgrades.insert(value->Float());
 
 		value = &creature["projectile_defname"];
-		if (!value->isNull()) {
+		if (!value->isNull())
+		{
 			idToProjectile[creatureID] = value->String();
 
 			value = &creature["projectile_spin"];
@@ -435,14 +456,17 @@ void CCreatureHandler::loadCreatures()
 
 		value = &creature["ability_add"];
 		if (!value->isNull()) {
-			BOOST_FOREACH(const JsonNode &ability, value->Vector()) {
+			BOOST_FOREACH(const JsonNode &ability, value->Vector())
+			{
 				AddAbility(c, ability.Vector());
 			}
 		}
 
 		value = &creature["ability_remove"];
-		if (!value->isNull()) {
-			BOOST_FOREACH(const JsonNode &ability, value->Vector()) {
+		if (!value->isNull())
+		{
+			BOOST_FOREACH(const JsonNode &ability, value->Vector())
+			{
 				RemoveAbility(c, ability);
 			}
 		}
@@ -458,14 +482,15 @@ void CCreatureHandler::loadCreatures()
 	//reading creature ability names
 	const JsonNode config2(GameConstants::DATA_DIR + "/config/bonusnames.json");
 
-	BOOST_FOREACH(const JsonNode &bonus, config2["bonuses"].Vector()) {
+	BOOST_FOREACH(const JsonNode &bonus, config2["bonuses"].Vector())
+	{
 		std::map<std::string,int>::const_iterator it_map;
 		std::string bonusID = bonus["id"].String();
 
 		it_map = bonusNameMap.find(bonusID);
-		if (it_map != bonusNameMap.end()) {
+		if (it_map != bonusNameMap.end())
 			stackBonuses[it_map->second] = std::pair<std::string, std::string>(bonus["name"].String(), bonus["description"].String());
-		} else
+		else
 			tlog2 << "Bonus " << bonusID << " not recognized, ignoring\n";
 	}
 
@@ -581,6 +606,37 @@ void CCreatureHandler::loadCreatures()
 	//experiment - add 100 to attack for creatures of tier 1
 // 	Bonus *b = new Bonus(Bonus::PERMANENT, Bonus::PRIMARY_SKILL, Bonus::OTHER, +100, 0, 0);
 // 	addBonusForTier(1, b);
+
+	tlog5 << "\t\tReading config/commanders.json" << std::endl;
+	const JsonNode config3(GameConstants::DATA_DIR + "/config/commanders.json");
+
+	BOOST_FOREACH (auto creature, config3["factionCreatures"].Vector())
+	{
+		factionCommanders[creature["faction"].Float()] =  creature["id"].Float();
+	}
+	BOOST_FOREACH (auto bonus, config3["bonusPerLevel"].Vector())
+	{
+		commanderLevelPremy.push_back(&ParseBonus (bonus.Vector()));
+	}
+
+	i = 0;
+	BOOST_FOREACH (auto skill, config3["skillLevels"].Vector())
+	{
+		BOOST_FOREACH (auto skillLevel, skill.Vector())
+		{
+			skillLevels[i].push_back (skillLevel.Float());
+		}
+		++i;
+	}
+
+	BOOST_FOREACH (auto ability, config3["abilityRequirements"].Vector())
+	{
+		std::pair <Bonus, std::pair <ui8, ui8> > a;
+		a.first = ParseBonus (ability["ability"].Vector());
+		a.second.first = ability["skills"].Vector()[0].Float();
+		a.second.second = ability["skills"].Vector()[1].Float();
+		skillRequirements.push_back (a);
+	}
 }
 
 void CCreatureHandler::loadAnimationInfo()

+ 2 - 2
lib/CCreatureHandler.h

@@ -117,9 +117,9 @@ public:
 
 	//Commanders
 	std::map <ui8, ui32> factionCommanders;
-	std::vector< std::vector <ui8> > skillLevels; //how much of a bonus will be given to commander with every level. We assume that number of casts equals skill level
-	std::vector <std::pair <Bonus, std::pair <ui8, ui8> > > skillRequirements; // first - Bonus, second - which two skills are needed to use it
 	BonusList commanderLevelPremy; //bonus values added with each level-up
+	std::vector< std::vector <ui8> > skillLevels; //how much of a bonus will be given to commander with every level. SPELL_POWER also gives CASTS and RESISTANCE
+	std::vector <std::pair <Bonus, std::pair <ui8, ui8> > > skillRequirements; // first - Bonus, second - which two skills are needed to use it
 
 	void deserializationFix();
 	void loadCreatures();

+ 1 - 0
lib/CCreatureSet.cpp

@@ -852,6 +852,7 @@ std::string CStackInstance::bonusToGraphics(Bonus *bonus) const
 			//"E_SUMMON1.bmp"
 			//"E_SUMMON2.bmp"
 		case Bonus::FULL_HP_REGENERATION:
+		case Bonus::HP_REGENERATION:
 			fileName = "E_TROLL.bmp"; break;
 		case Bonus::UNDEAD:
 			fileName = "E_UNDEAD.bmp"; break;

+ 1 - 1
lib/GameConstants.h

@@ -177,7 +177,7 @@ namespace EBattleStackState
 
 namespace ECommander
 {
-	enum SecondarySkills {ATTACK, DEFENSE, HEALTH, DAMAGE, SPEED, SPELL_POWER};
+	enum SecondarySkills {ATTACK, DEFENSE, HEALTH, DAMAGE, SPEED, SPELL_POWER, CASTS, RESISTANCE};
 }
 
 namespace Obj

+ 2 - 1
lib/HeroBonus.h

@@ -172,7 +172,8 @@ typedef boost::function<bool(const Bonus*)> CSelector;
 	BONUS_NAME(CREATURE_ENCHANT_POWER) /* total duration of spells casted by creature */ \
 	BONUS_NAME(REBIRTH) /* val - percent of life restored, subtype = 0 - regular, 1 - at least one unit (sacred Phoenix) */\
 	BONUS_NAME(ADDITIONAL_UNITS) /*val of units with id = subtype will be added to hero's army at the beginning of battle */\
-	BONUS_NAME(SPOILS_OF_WAR) /*val * 10^-6 * gained exp resources of subtype will be given to hero after battle*/
+	BONUS_NAME(SPOILS_OF_WAR) /*val * 10^-6 * gained exp resources of subtype will be given to hero after battle*/\
+	BONUS_NAME(BLOCK)
 
 /// Struct for handling bonuses of several types. Can be transferred to any hero
 struct DLL_LINKAGE Bonus