Browse Source

* more or less working HERO campaign bonus
* minor improvements

mateuszb 13 years ago
parent
commit
9acfa0d136
6 changed files with 52 additions and 19 deletions
  1. 28 12
      client/CPreGame.cpp
  2. 0 2
      client/CPreGame.h
  3. 3 0
      lib/CCampaignHandler.cpp
  4. 1 1
      lib/CCampaignHandler.h
  5. 19 4
      lib/CGameState.cpp
  6. 1 0
      lib/GameConstants.h

+ 28 - 12
client/CPreGame.cpp

@@ -3052,17 +3052,17 @@ void CBonusSelection::updateBonusSelection()
 			std::string desc;
 			switch(bonDescs[i].type)
 			{
-			case 0: //spell
+			case CScenarioTravel::STravelBonus::SPELL:
 				desc = CGI->generaltexth->allTexts[715];
 				boost::algorithm::replace_first(desc, "%s", CGI->spellh->spells[bonDescs[i].info2]->name);
 				break;
-			case 1: //monster
+			case CScenarioTravel::STravelBonus::MONSTER:
 				picNumber = bonDescs[i].info2 + 2;
 				desc = CGI->generaltexth->allTexts[717];
 				boost::algorithm::replace_first(desc, "%d", boost::lexical_cast<std::string>(bonDescs[i].info3));
 				boost::algorithm::replace_first(desc, "%s", CGI->creh->creatures[bonDescs[i].info2]->namePl);
 				break;
-			case 2: //building
+			case CScenarioTravel::STravelBonus::BUILDING:
 				{
 					int faction = -1;
 					for(std::map<int, PlayerSettings>::iterator it = sInfo.playerInfos.begin();
@@ -3085,15 +3085,15 @@ void CBonusSelection::updateBonusSelection()
 						desc = CGI->townh->towns[faction].buildings.find(buildID)->second->Description();
 				}
 				break;
-			case 3: //artifact
+			case CScenarioTravel::STravelBonus::ARTIFACT:
 				desc = CGI->generaltexth->allTexts[715];
 				boost::algorithm::replace_first(desc, "%s", CGI->arth->artifacts[bonDescs[i].info2]->Name());
 				break;
-			case 4: //spell scroll
+			case CScenarioTravel::STravelBonus::SPELL_SCROLL:
 				desc = CGI->generaltexth->allTexts[716];
 				boost::algorithm::replace_first(desc, "%s", CGI->spellh->spells[bonDescs[i].info2]->name);
 				break;
-			case 5: //primary skill
+			case CScenarioTravel::STravelBonus::PRIMARY_SKILL:
 				{
 					int leadingSkill = -1;
 					std::vector<std::pair<int, int> > toPrint; //primary skills to be listed <num, val>
@@ -3126,14 +3126,14 @@ void CBonusSelection::updateBonusSelection()
 					boost::algorithm::replace_first(desc, "%s", substitute);
 					break;
 				}
-			case 6: //secondary skill
+			case CScenarioTravel::STravelBonus::SECONDARY_SKILL:
 				desc = CGI->generaltexth->allTexts[718];
 
 				boost::algorithm::replace_first(desc, "%s", CGI->generaltexth->levels[bonDescs[i].info3]); //skill level
 				boost::algorithm::replace_first(desc, "%s", CGI->generaltexth->skillName[bonDescs[i].info2]); //skill name
 
 				break;
-			case 7: //resource
+			case CScenarioTravel::STravelBonus::RESOURCE:
 				{
 					int serialResID = 0;
 					switch(bonDescs[i].info1)
@@ -3164,7 +3164,7 @@ void CBonusSelection::updateBonusSelection()
 					boost::algorithm::replace_first(desc, "%s", replacement);
 				}
 				break;
-			case 8: //player aka hero crossover
+			case CScenarioTravel::STravelBonus::PLAYER_PREV_SCENARIO:
 				picNumber = bonDescs[i].info1;
 				desc = CGI->generaltexth->allTexts[718];
 
@@ -3172,14 +3172,14 @@ void CBonusSelection::updateBonusSelection()
 				boost::algorithm::replace_first(desc, "%s", ourCampaign->camp->scenarios[bonDescs[i].info2].mapName); //scenario
 
 				break;
-			case 9: //hero
-
+			case CScenarioTravel::STravelBonus::HERO:
+				
 				desc = CGI->generaltexth->allTexts[718];
 				boost::algorithm::replace_first(desc, "%s", CGI->generaltexth->capColors[bonDescs[i].info1]); //hero's color
 
 				if (bonDescs[i].info2 == 0xFFFF)
 				{
-					boost::algorithm::replace_first(desc, "%s", CGI->heroh->heroes[0]->name); //hero's name
+					boost::algorithm::replace_first(desc, "%s", CGI->generaltexth->allTexts[101]); //hero's name
 					picNumber = 0;
 				}
 				else
@@ -3205,6 +3205,22 @@ void CBonusSelection::updateBonusSelection()
 void CBonusSelection::startMap()
 {
 	StartInfo *si = new StartInfo(sInfo);
+	
+	{ //select human player if HERO bonus
+		auto bonus = si->campState->getBonusForCurrentMap();
+		if(bonus.type == CScenarioTravel::STravelBonus::HERO)
+		{
+			std::map<ui32, std::string> names;
+			names[1] = settings["general"]["playerName"].String();
+			for(auto it = si->playerInfos.begin(); it != si->playerInfos.end(); ++it)
+			{
+				if(it->first == bonus.info1)
+					::setPlayer(it->second, 1, names);
+				else
+					::setPlayer(it->second, 0, names);
+			}
+		}
+	}
 	if (ourCampaign->mapsConquered.size())
 	{
 		GH.popInts(1);

+ 0 - 2
client/CPreGame.h

@@ -427,8 +427,6 @@ class CBonusSelection : public CIntObject
 	CHighlightableButtonsGroup * bonuses;
 
 public:
-	void bonusSelectionChanges(int choosenBonus);
-
 	StartInfo sInfo;
 	CDefHandler *sFlags;
 

+ 3 - 0
lib/CCampaignHandler.cpp

@@ -230,6 +230,9 @@ CScenarioTravel CCampaignHandler::readScenarioTravelFromMemory( const ui8 * buff
 						bonus.info2 = read_le_u32(buffer + outIt); outIt += 4; //count
 						break;
 					}
+				default:
+					tlog1<<"Corrupted h3c file"<<std::endl;
+					break;
 				}
 				ret.bonusesToChoose.push_back(bonus);
 			}

+ 1 - 1
lib/CCampaignHandler.h

@@ -56,7 +56,7 @@ public:
 	struct DLL_LINKAGE STravelBonus
 	{
 		enum EBonusType {SPELL, MONSTER, BUILDING, ARTIFACT, SPELL_SCROLL, PRIMARY_SKILL, SECONDARY_SKILL, RESOURCE,
-			PLAYER_PREV_SCENARIO, HERO /*???*/};
+			PLAYER_PREV_SCENARIO, HERO};
 		ui8 type; //uses EBonusType
 		si32 info1, info2, info3; //purpose depends on type
 

+ 19 - 4
lib/CGameState.cpp

@@ -467,17 +467,30 @@ int CGameState::pickHero(int owner)
 	const PlayerSettings &ps = scenarioOps->getIthPlayersSettings(owner);
 	if(!map->getHero(h = ps.hero,0)  &&  h>=0) //we haven't used selected hero
 		return h;
+
+	if(scenarioOps->mode == StartInfo::CAMPAIGN)
+	{
+		auto bonus = scenarioOps->campState->getBonusForCurrentMap();
+		if(bonus.type == CScenarioTravel::STravelBonus::HERO && owner == bonus.info1)
+		{
+			if(bonus.info2 != 0xffff && !map->getHero(bonus.info2)) //not random and not taken
+			{
+				return bonus.info2;
+			}
+		}
+	}
+
 	int i=0;
 
 	do //try to find free hero of our faction
 	{
 		i++;
 		h = ps.castle*GameConstants::HEROES_PER_TYPE*2+(ran()%(GameConstants::HEROES_PER_TYPE*2));//->scenarioOps->playerInfos[pru].hero = VLC->
-	} while( map->getHero(h)  &&  i<175);
-	if(i>174) //probably no free heroes - there's no point in further search, we'll take first free
+	} while( map->getHero(h)  &&  i<(GameConstants::NUMBER_OF_HEROES+1));
+	if(i>GameConstants::NUMBER_OF_HEROES) //probably no free heroes - there's no point in further search, we'll take first free
 	{
 		tlog3 << "Warning: cannot find free hero - trying to get first available..."<<std::endl;
-		for(int j=0; j<GameConstants::HEROES_PER_TYPE * 2 * GameConstants::F_NUMBER; j++)
+		for(int j=0; j<GameConstants::NUMBER_OF_HEROES; j++)
 			if(!map->getHero(j))
 				h=j;
 	}
@@ -965,7 +978,9 @@ void CGameState::init(StartInfo * si)
 	for(int i=0;i<GameConstants::PLAYER_LIMIT;i++)
 	{
 		const PlayerInfo &p = map->players[i];
-		bool generateHero = (p.generateHeroAtMainTown && p.hasMainTown);
+		bool campaignGiveHero = scenarioOps->playerInfos[i].human && scenarioOps->mode == StartInfo::CAMPAIGN &&
+			scenarioOps->campState->getBonusForCurrentMap().type == CScenarioTravel::STravelBonus::HERO;
+		bool generateHero = (p.generateHeroAtMainTown || campaignGiveHero) && p.hasMainTown;
 		if(generateHero && vstd::contains(scenarioOps->playerInfos, i))
 		{
 			int3 hpos = p.posOfMainTown;

+ 1 - 0
lib/GameConstants.h

@@ -67,6 +67,7 @@ namespace GameConstants
 	const int MAX_HEROES_PER_PLAYER = 8;
 	const int ALL_PLAYERS = 255; //bitfield
 	const int HEROES_PER_TYPE=8; //amount of heroes of each type
+	const int NUMBER_OF_HEROES = 174;
 	const int SKILL_QUANTITY=28;
 	const int SKILL_PER_HERO=8;
 	const int ARTIFACTS_QUANTITY=171;