Explorar el Código

- fixed empty tavern in new towns
- by default new heroes\new towns will be enabled on maps (no effect without mods)

Ivan Savenko hace 13 años
padre
commit
ff146a80fe
Se han modificado 7 ficheros con 61 adiciones y 31 borrados
  1. 12 11
      client/CPreGame.cpp
  2. 2 2
      client/CPreGame.h
  3. 13 0
      config/heroes.json
  4. 10 9
      lib/CHeroHandler.cpp
  5. 1 0
      lib/CHeroHandler.h
  6. 11 0
      lib/CTownHandler.cpp
  7. 12 9
      lib/Map/CMapService.cpp

+ 12 - 11
client/CPreGame.cpp

@@ -2298,16 +2298,16 @@ void OptionsTab::nextHero( int player, int dir )
 
 	if (s.hero == PlayerSettings::RANDOM) // first/last available
 	{
-		int max = (s.castle*GameConstants::HEROES_PER_TYPE*2+15),
-			min = (s.castle*GameConstants::HEROES_PER_TYPE*2);
-		s.hero = nextAllowedHero(min,max,0,dir);
+		int max = CGI->heroh->heroes.size(),
+			min = 0;
+		s.hero = nextAllowedHero(player, min,max,0,dir);
 	}
 	else
 	{
 		if(dir > 0)
-			s.hero = nextAllowedHero(s.hero,(s.castle*GameConstants::HEROES_PER_TYPE*2+16),1,dir);
+			s.hero = nextAllowedHero(player, s.hero, CGI->heroh->heroes.size(), 1, dir);
 		else
-			s.hero = nextAllowedHero(s.castle*GameConstants::HEROES_PER_TYPE*2-1,s.hero,1,dir);
+			s.hero = nextAllowedHero(player,  0, s.hero, 1, dir);
 	}
 
 	if(old != s.hero)
@@ -2320,28 +2320,29 @@ void OptionsTab::nextHero( int player, int dir )
 	SEL->propagateOptions();
 }
 
-int OptionsTab::nextAllowedHero( int min, int max, int incl, int dir )
+int OptionsTab::nextAllowedHero( int player, int min, int max, int incl, int dir )
 {
 	if(dir>0)
 	{
 		for(int i=min+incl; i<=max-incl; i++)
-			if(canUseThisHero(i))
+			if(canUseThisHero(player, i))
 				return i;
 	}
 	else
 	{
 		for(int i=max-incl; i>=min+incl; i--)
-			if(canUseThisHero(i))
+			if(canUseThisHero(player, i))
 				return i;
 	}
 	return -1;
 }
 
-bool OptionsTab::canUseThisHero( int ID )
+bool OptionsTab::canUseThisHero( int player, int ID )
 {
 	return CGI->heroh->heroes.size() > ID
-		&& !vstd::contains(usedHeroes, ID)
-		&& SEL->current->mapHeader->allowedHeroes[ID];
+	        && SEL->sInfo.playerInfos[player].castle == CGI->heroh->heroes[ID]->heroClass->faction
+	        && !vstd::contains(usedHeroes, ID)
+	        && SEL->current->mapHeader->allowedHeroes[ID];
 }
 
 void OptionsTab::nextBonus( int player, int dir )

+ 2 - 2
client/CPreGame.h

@@ -276,9 +276,9 @@ public:
 	~OptionsTab();
 	void showAll(SDL_Surface * to);
 
-	int nextAllowedHero( int min, int max, int incl, int dir );
+	int nextAllowedHero(int player, int min, int max, int incl, int dir );
 
-	bool canUseThisHero( int ID );
+	bool canUseThisHero(int player, int ID );
 };
 
 /**

+ 13 - 0
config/heroes.json

@@ -66,6 +66,7 @@
 			"id": 4,
 			"class" : "knight",
 			"female": false,
+			"special" : true,
 			"skills":
 			[
 				{ "skill" : "leadership", "level": "basic" },
@@ -2103,6 +2104,7 @@
 			"id": 144,
 			"class" : "knight",
 			"female": false,
+			"special" : true,
 			"skills":
 			[
 				{ "skill" : "leadership", "level": "advanced" }
@@ -2116,6 +2118,7 @@
 			"id": 145,
 			"class" : "witch",
 			"female": true,
+			"special" : true,
 			"spellbook": [ 22 ],
 			"skills":
 			[
@@ -2130,6 +2133,7 @@
 			"id": 146,
 			"class" : "knight",
 			"female": true,
+			"special" : true,
 			"skills":
 			[
 				{ "skill" : "leadership", "level": "basic" },
@@ -2144,6 +2148,7 @@
 			"id": 147,
 			"class" : "wizard",
 			"female": false,
+			"special" : true,
 			"spellbook": [ 53 ],
 			"skills":
 			[
@@ -2159,6 +2164,7 @@
 			"id": 148,
 			"class" : "ranger",
 			"female": false,
+			"special" : true,
 			"skills":
 			[
 				{ "skill" : "archery", "level": "basic" },
@@ -2174,6 +2180,7 @@
 			"id": 149,
 			"class" : "barbarian",
 			"female": false,
+			"special" : true,
 			"skills":
 			[
 				{ "skill" : "offence", "level": "advanced" }
@@ -2189,6 +2196,7 @@
 			"id": 150,
 			"class" : "deathknight",
 			"female": false,
+			"special" : true,
 			"spellbook": [ 54 ],
 			"skills":
 			[
@@ -2205,6 +2213,7 @@
 			"id": 151,
 			"class" : "warlock",
 			"female": true,
+			"special" : true,
 			"spellbook": [ 15 ],
 			"skills":
 			[
@@ -2221,6 +2230,7 @@
 			"id": 152,
 			"class" : "knight",
 			"female": false,
+			"special" : true,
 			"skills":
 			[
 				{ "skill" : "leadership", "level": "basic" },
@@ -2235,6 +2245,7 @@
 			"id": 153,
 			"class" : "warlock",
 			"female": true,
+			"special" : true,
 			"spellbook": [ 15 ],
 			"skills":
 			[
@@ -2251,6 +2262,7 @@
 			"id": 154,
 			"class" : "barbarian",
 			"female": false,
+			"special" : true,
 			"skills":
 			[
 				{ "skill" : "tactics", "level": "basic" },
@@ -2265,6 +2277,7 @@
 			"id": 155,
 			"class" : "demoniac",
 			"female": false,
+			"special" : true,
 			"skills":
 			[
 				{ "skill" : "leadership", "level": "basic" },

+ 10 - 9
lib/CHeroHandler.cpp

@@ -217,7 +217,7 @@ void CHeroHandler::load(const JsonNode & input)
 			hero->ID = heroes.size();
 
 			heroes.push_back(hero);
-			tlog3 << "Added hero : " << entry.first << "\n";
+			tlog3 << "Added hero: " << entry.first << "\n";
 			VLC->modh->identifiers.registerObject("hero." + entry.first, hero->ID);
 		}
 	}
@@ -264,7 +264,8 @@ CHero * CHeroHandler::loadHero(const JsonNode & node)
 void CHeroHandler::loadHeroJson(CHero * hero, const JsonNode & node)
 {
 	// sex: 0=male, 1=female
-	hero->sex = !!node["female"].Bool();
+	hero->sex = node["female"].Bool();
+	hero->special = node["special"].Bool();
 
 	BOOST_FOREACH(const JsonNode &set, node["skills"].Vector())
 	{
@@ -418,7 +419,7 @@ void CHeroHandler::loadHeroTexts()
 		hero->specDescr   = parser.readString();
 		hero->biography   = bioParser.readString();
 	}
-	while (parser.endLine() && bioParser.endLine() && heroes.size() < i);
+	while (parser.endLine() && bioParser.endLine() && heroes.size() > i);
 }
 
 void CHeroHandler::loadBallistics()
@@ -482,12 +483,12 @@ std::vector<ui8> CHeroHandler::getDefaultAllowedHeroes() const
 {
 	// Look Data/HOTRAITS.txt for reference
 	std::vector<ui8> allowedHeroes;
-	allowedHeroes.resize(156, 1);
-	for(int i = 145; i < 156; ++i)
+	allowedHeroes.reserve(heroes.size());
+
+	BOOST_FOREACH(const CHero * hero, heroes)
 	{
-		allowedHeroes[i] = 0;
+		allowedHeroes.push_back(!hero->special);
 	}
-	allowedHeroes[4] = 0;
-	allowedHeroes[25] = 0;
+
 	return allowedHeroes;
-}
+}

+ 1 - 0
lib/CHeroHandler.h

@@ -56,6 +56,7 @@ public:
 	std::vector<SSpecialtyInfo> spec;
 	std::set<si32> spells;
 	ui8 sex; // default sex: 0=male, 1=female
+	ui8 special; // hero is special and won't be placed in game (unless preset on map), e.g. campaign heroes
 
 	/// Localized texts
 	std::string name; //name of hero

+ 11 - 0
lib/CTownHandler.cpp

@@ -6,6 +6,7 @@
 #include "JsonNode.h"
 #include "StringConstants.h"
 #include "CModHandler.h"
+#include "CHeroHandler.h"
 #include "CArtHandler.h"
 #include "Filesystem/CResourceLoader.h"
 
@@ -435,7 +436,17 @@ void CTownHandler::loadTown(CTown &town, const JsonNode & source)
 				town.creatures[i][j] = creature;
 			});
 		}
+	}
+
+	/// set chance of specific hero class to appear in this town
+	BOOST_FOREACH(auto &node, source["tavern"].Struct())
+	{
+		int chance = node.second.Float();
 
+		VLC->modh->identifiers.requestIdentifier(std::string("heroClass.") + node.first, [=, &town](si32 classID)
+		{
+			VLC->heroh->classes.heroClasses[classID]->selectionProbability[town.typeID] = chance;
+		});
 	}
 
 	loadBuildings(town, source["buildings"]);

+ 12 - 9
lib/Map/CMapService.cpp

@@ -12,6 +12,7 @@
 #include "../VCMI_Lib.h"
 #include "../CSpellHandler.h"
 #include "../CCreatureHandler.h"
+#include "../CHeroHandler.h"
 #include "../CObjectHandler.h"
 #include "../CDefObjInfoHandler.h"
 
@@ -268,17 +269,19 @@ void CMapLoaderH3M::readPlayerInfo()
 
 		// Factions this player can choose
 		ui16 allowedFactions = buffer[pos++];
+		// How many factions will be read from map
+		ui16 totalFactions = GameConstants::F_NUMBER;
+
 		if(mapHeader->version != EMapFormat::ROE)
-		{
 			allowedFactions += (buffer[pos++]) * 256;
-		}
+		else
+			totalFactions--; //exclude conflux for ROE
 
-		mapHeader->players[i].allowedFactions.clear();
-		for(int fact = 0; fact < 16; ++fact)
+		for(int fact = 0; fact < totalFactions; ++fact)
 		{
-			if(allowedFactions & (1 << fact))
+			if(!(allowedFactions & (1 << fact)))
 			{
-				mapHeader->players[i].allowedFactions.insert(fact);
+				mapHeader->players[i].allowedFactions.erase(fact);
 			}
 		}
 
@@ -475,7 +478,7 @@ void CMapLoaderH3M::readTeamInfo()
 void CMapLoaderH3M::readAllowedHeroes()
 {
 	int pom = pos;
-	mapHeader->allowedHeroes.resize(GameConstants::HEROES_QUANTITY, false);
+	mapHeader->allowedHeroes.resize(VLC->heroh->heroes.size(), true);
 	for(; pos < pom + (mapHeader->version == EMapFormat::ROE ? 16 : 20) ; ++pos)
 	{
 		ui8 c = buffer[pos];
@@ -483,9 +486,9 @@ void CMapLoaderH3M::readAllowedHeroes()
 		{
 			if((pos - pom) * 8 + yy < GameConstants::HEROES_QUANTITY)
 			{
-				if(c == (c | static_cast<ui8>(std::pow(2., yy))))
+				if(c != (c | static_cast<ui8>(std::pow(2., yy))))
 				{
-					mapHeader->allowedHeroes[(pos - pom) * 8 + yy] = true;
+					mapHeader->allowedHeroes[(pos - pom) * 8 + yy] = false;
 				}
 			}
 		}