Explorar o código

* hopefully last bugfix for Pandora's Box
* fixed blockmap for generated hero
* one can't choose already disposed hero in pregame
* fixes in heroes and towns picking
* improved hero selection in pregame
* version changed to 0.53
* CGI will be in debug mode a global pointer (much more convenient debugging)

Michał W. Urbańczyk %!s(int64=18) %!d(string=hai) anos
pai
achega
ec072972ee
Modificáronse 8 ficheiros con 104 adicións e 23 borrados
  1. 8 13
      CMT.cpp
  2. BIN=BIN
      CPreGame.cpp
  3. 5 0
      CPreGame.h
  4. 6 0
      global.h
  5. 9 1
      hch/CAmbarCendamo.cpp
  6. 1 1
      hch/CCastleHandler.h
  7. 73 7
      mapHandler.cpp
  8. 2 1
      mapHandler.h

+ 8 - 13
CMT.cpp

@@ -58,9 +58,11 @@
 #else
 #  define SET_BINARY_MODE(file)
 #endif
-
+#ifdef _DEBUG
+CGameInfo* CGI;
+#endif
 #define CHUNK 16384
-const char * NAME = "VCMI 0.52 \"Tirion\" Techdemo";
+const char * NAME = "VCMI 0.53 \"Tirion\" Techdemo";
 
 SDL_Surface * ekran, * screen, * screen2;
 extern SDL_Surface * CSDL_Ext::std32bppSurface;
@@ -353,7 +355,10 @@ int _tmain(int argc, _TCHAR* argv[])
 
 		SDL_WM_SetCaption(NAME,""); //set window title
 		CGameInfo * cgi = new CGameInfo; //contains all global informations about game (texts, lodHandlers, map handler itp.)
-		CGameInfo::mainObj = cgi;
+		CGameInfo::mainObj = cgi;		
+		#ifdef _DEBUG
+		CGI = cgi;
+		#endif
 		cgi->consoleh = new CConsoleHandler;
 		cgi->mush = mush;
 		cgi->curh = new CCursorHandler;
@@ -761,16 +766,6 @@ int _tmain(int argc, _TCHAR* argv[])
 		}
 		std::cout<<"done."<<std::endl;
 
-		for(int pru=0;pru<cgi->scenarioOps.playerInfos.size();pru++)
-		{
-			if(cgi->scenarioOps.playerInfos[pru].castle<0)
-				cgi->scenarioOps.playerInfos[pru].castle = rand()%F_NUMBER;
-			if(cgi->scenarioOps.playerInfos[pru].hero<0)
-				cgi->scenarioOps.playerInfos[pru].hero= cgi->scenarioOps.playerInfos[pru].castle*HEROES_PER_TYPE*2+(rand()%(HEROES_PER_TYPE*2));//cgi->scenarioOps.playerInfos[pru].hero = cgi->
-		}
-
-
-
 #define CHOOSE
 #ifdef CHOOSE
 		CAmbarCendamo * ac = new CAmbarCendamo(initTable); //4gryf

BIN=BIN
CPreGame.cpp


+ 5 - 0
CPreGame.h

@@ -1,5 +1,7 @@
 #ifndef CPREGAME_H
 #define CPREGAME_H
+#include "global.h"
+#include <set>
 #include "SDL.h"
 #include "StartInfo.h"
 #include "hch\CSemiDefHandler.h"
@@ -156,6 +158,7 @@ class Options : public PreGameTab
 		int nr;
 	};
 public:
+	std::set<int> usedHeroes;
 	Slider<> * turnLength;
 	SDL_Surface * bg,
 		* rHero, * rCastle, * nHero, * nCastle;
@@ -169,6 +172,8 @@ public:
 	void hide();
 	void init();
 	void showIcon (int what, int nr, bool abs); //what: -1=castle, 0=hero, 1=bonus, 2=all; abs=true -> nr is absolute
+	bool canUseThisHero(int ID);
+	int nextAllowedHero(int min, int max, int incl, int dir); //incl 0 - wlacznie; incl 1 - wylacznie; min-max - zakres szukania
 	Options(){inited=showed=false;};
 	~Options();
 };

+ 6 - 0
global.h

@@ -22,7 +22,12 @@ enum EHeroClasses {HERO_KNIGHT, HERO_CLERIC, HERO_RANGER, HERO_DRUID, HERO_ALCHE
 	HERO_DEMONIAC, HERO_HERETIC, HERO_DEATHKNIGHT, HERO_NECROMANCER, HERO_WARLOCK, HERO_OVERLORD, 
 	HERO_BARBARIAN, HERO_BATTLEMAGE, HERO_BEASTMASTER, HERO_WITCH, HERO_PLANESWALKER, HERO_ELEMENTALIST};
 
+#ifdef _DEBUG
+class CGameInfo;
+extern CGameInfo* CGI;
+#else
 #define CGI (CGameInfo::mainObj)
+#endif
 #define CURPLINT (((CPlayerInterface*)((CGameInfo::mainObj)->playerint[(CGameInfo::mainObj)->state->currentPlayer]))) 
 #define LOCPLINT (((CPlayerInterface*)((CGameInfo::mainObj)->playerint[(CGameInfo::mainObj)->localPlayer]))) 
 //CURPLINT gives pointer to the interface of human player which is currently making turn, 
@@ -60,6 +65,7 @@ const int MAX_BUILDING_PER_TURN = 1;
 
 #define DEFBYPASS
 
+
 #define HANDLE_EXCEPTION  \
 	catch (const std::exception& e) {	\
 	std::cerr << e.what() << std::endl;	\

+ 9 - 1
hch/CAmbarCendamo.cpp

@@ -210,6 +210,12 @@ void CAmbarCendamo::deh3m()
 				map.players[pom].generateHeroAtMainTown = bufor[i++];
 				map.players[pom].generateHero = bufor[i++];
 			}
+			else
+			{
+				map.players[pom].generateHeroAtMainTown = false;
+				map.players[pom].generateHero = false;
+			}
+
 			map.players[pom].posOfMainTown.x = bufor[i++];
 			map.players[pom].posOfMainTown.y = bufor[i++];
 			map.players[pom].posOfMainTown.z = bufor[i++];
@@ -1824,7 +1830,9 @@ void CAmbarCendamo::deh3m()
 					spec->spells.push_back(&(CGameInfo::mainObj->spellh->spells[readNormalNr(i, 1)])); ++i;
 				}
 				int gcre = readNormalNr(i, 1); ++i; //number of gained creatures
-				spec->creatures = readCreatureSet(i, gcre); i+=4*gcre;
+				spec->creatures = readCreatureSet(i, gcre); i+=3*gcre;
+				if(map.version > RoE)
+					i+=gcre;
 				i+=8;
 				nobj->info = spec;
 				///////end of copied fragment

+ 1 - 1
hch/CCastleHandler.h

@@ -45,7 +45,7 @@ public:
 	
 	std::vector<CCastleEvent> events;
 
-	unsigned char alignment; //what the hell is that??
+	unsigned char alignment; //255 - same as owner/random, 0 - same as red, 1 - same as blue, etc
 };
 
 #endif //CCASTLEHANDLER_H

+ 73 - 7
mapHandler.cpp

@@ -38,6 +38,30 @@ void alphaTransformDef(CGDefInfo * defInfo)
 	}
 	SDL_FreeSurface(alphaTransSurf);
 }
+int CMapHandler::pickHero(int owner)
+{
+	if(usedHeroes.find(CGI->scenarioOps.getIthPlayersSettings(owner).hero)==usedHeroes.end()) //we haven't used selected hero
+	{
+		int h = CGI->scenarioOps.getIthPlayersSettings(owner).hero;
+		usedHeroes.insert(h);
+		return h;
+	}
+	int f = CGI->scenarioOps.getIthPlayersSettings(owner).castle;
+	int i=0, h;
+	do //try to find free hero of our faction
+	{
+		i++;
+		h = CGI->scenarioOps.getIthPlayersSettings(owner).castle*HEROES_PER_TYPE*2+(rand()%(HEROES_PER_TYPE*2));//cgi->scenarioOps.playerInfos[pru].hero = cgi->
+	} while((usedHeroes.find(h)!=usedHeroes.end())  &&  i<175);
+	if(i>174) //probably no free heroes - there's no point in further search, we'll take first free
+	{
+		for(int j=0; j<HEROES_PER_TYPE * 2 * F_NUMBER; j++)
+			if(usedHeroes.find(j)==usedHeroes.end())
+				h=j;
+	}
+	usedHeroes.insert(h);
+	return h;
+}
 std::pair<int,int> CMapHandler::pickObject(CGObjectInstance *obj)
 {
 	switch(obj->ID)
@@ -53,7 +77,9 @@ std::pair<int,int> CMapHandler::pickObject(CGObjectInstance *obj)
 	case 69: //random relic artifact
 		return std::pair<int,int>(5,CGI->arth->relics[rand()%CGI->arth->relics.size()]->id);
 	case 70: //random hero
-		return std::pair<int,int>(34,rand()%CGI->heroh->heroes.size());
+		{
+			return std::pair<int,int>(34,pickHero(obj->tempOwner));
+		}
 	case 71: //random monster
 		return std::pair<int,int>(54,rand()%(CGI->creh->creatures.size())); 
 	case 72: //random monster lvl1
@@ -67,7 +93,23 @@ std::pair<int,int> CMapHandler::pickObject(CGObjectInstance *obj)
 	case 76: //random resource
 		return std::pair<int,int>(79,rand()%7); //now it's OH3 style, use %8 for mithril 
 	case 77: //random town
-		return std::pair<int,int>(98,rand()%CGI->townh->towns.size()); 
+		{
+			int align = ((CCastleObjInfo*)obj->info)->alignment,
+				f;
+			if(align>PLAYER_LIMIT-1)//same as owner / random
+			{
+				if(obj->tempOwner > PLAYER_LIMIT-1)
+					f = -1; //random
+				else
+					f = CGI->scenarioOps.getIthPlayersSettings(obj->tempOwner).castle;
+			}
+			else
+			{
+				f = CGI->scenarioOps.getIthPlayersSettings(align).castle;
+			}
+			if(f<0) f = rand()%CGI->townh->towns.size();
+			return std::pair<int,int>(98,f); 
+		}
 	case 162: //random monster lvl5
 		return std::pair<int,int>(54,CGI->creh->levelCreatures[5][rand()%CGI->creh->levelCreatures[5].size()]->idNumber);
 	case 163: //random monster lvl6
@@ -704,6 +746,7 @@ void CMapHandler::calculateBlockedPos()
 }
 void CMapHandler::init()
 {
+	//loading castles' defs
 	std::ifstream ifs("config/townsDefs.txt");
 	int ccc;
 	ifs>>ccc;
@@ -720,9 +763,29 @@ void CMapHandler::init()
 		alphaTransformDef(n);
 	} 
 
+	for(int i=0;i<CGI->scenarioOps.playerInfos.size();i++)
+	{
+		if(CGI->scenarioOps.playerInfos[i].castle==-1)
+		{
+			int f;
+			do
+			{
+				f = rand()%F_NUMBER;
+			}while(!(reader->map.players[CGI->scenarioOps.playerInfos[i].color].allowedFactions  & 1<<f));
+			CGI->scenarioOps.playerInfos[i].castle = f;
+		}
+	}
+	for(int i=0;i<PLAYER_LIMIT;i++)
+	{
+		for(int j=0; j<reader->map.players[i].heroesNames.size();j++)
+		{
+			usedHeroes.insert(reader->map.players[i].heroesNames[j].heroID);
+		}
+	}
+
+
 	timeHandler th;
 	th.getDif();
-
 	randomizeObjects();//randomizing objects on map
 	std::cout<<"\tRandomizing objects: "<<th.getDif()<<std::endl;
 
@@ -752,7 +815,10 @@ void CMapHandler::init()
 					break;
 			if(j==CGI->scenarioOps.playerInfos.size())
 				continue;
-			CGHeroInstance * nnn = (CGHeroInstance*)createObject(34,CGI->scenarioOps.playerInfos[j].hero,hpos,i);
+			int h = CGI->scenarioOps.playerInfos[j].hero;
+			if(h<0)
+				h=pickHero(i);
+			CGHeroInstance * nnn = (CGHeroInstance*)createObject(34,h,hpos,i);
 			nnn->defInfo->handler = CGI->heroh->flags1[0];
 			CGI->heroh->heroInstances.push_back(nnn);
 			CGI->objh->objInstances.push_back(nnn);
@@ -1339,14 +1405,14 @@ CGObjectInstance * CMapHandler::createObject(int id, int subid, int3 pos, int ow
 			nobj->type = CGI->heroh->heroes[subid];
 			for(int i=0;i<6;i++)
 			{
-				nobj->defInfo->blockMap[i]=1;
+				nobj->defInfo->blockMap[i]=255;
 				nobj->defInfo->visitMap[i]=0;
 			}
 			nobj->ID = id;
 			nobj->subID = subid;
 			nobj->defInfo->handler=NULL;
-			nobj->defInfo->blockMap[5] = 0x7f;
-			nobj->defInfo->visitMap[5] = 0x80;
+			nobj->defInfo->blockMap[5] = 253;
+			nobj->defInfo->visitMap[5] = 2;
 			nobj->artifWorn.resize(20);
 			nobj->artifacts.resize(20);
 			nobj->artifWorn[16] = &CGI->arth->artifacts[3];

+ 2 - 1
mapHandler.h

@@ -62,7 +62,7 @@ public:
 	PseudoV< PseudoV< PseudoV<TerrainTile2> > > ttiles;
 	int3 sizes;
 	CAmbarCendamo * reader;
-
+	std::set<int> usedHeroes;
 	CDefHandler * fullHide;
 	CDefHandler * partialHide;
 
@@ -92,6 +92,7 @@ public:
 	bool recalculateHideVisPos(int3& pos); //recalculates position for hidden / visitable positions
 	bool recalculateHideVisPosUnderObj(CGObjectInstance * obj, bool withBorder = false); //recalculates position for hidden / visitable positions under given object
 	void init();
+	int pickHero(int owner);
 	std::pair<int,int> pickObject(CGObjectInstance *obj);
 	void randomizeObject(CGObjectInstance *cur);
 	void calculateBlockedPos();