mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Implemented Scuttle Boat and Dimension Door spells.
Fixed #417 and #418. Moved / refactored some code. Minor fixes.
This commit is contained in:
		| @@ -7,6 +7,7 @@ | ||||
| #include "lib/map.h" | ||||
| #include "hch/CBuildingHandler.h" | ||||
| #include "hch/CDefObjInfoHandler.h" | ||||
| #include "hch/CGeneralTextHandler.h" | ||||
| #include "hch/CHeroHandler.h" | ||||
| #include "hch/CObjectHandler.h" | ||||
| #include "lib/Connection.h" | ||||
| @@ -33,21 +34,7 @@ | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| static int gcd(int x, int y) | ||||
| { | ||||
| 	int temp; | ||||
| 	if (y > x) | ||||
| 		std::swap(x,y); | ||||
| 	while (y != 0) | ||||
| 	{ | ||||
| 		temp = y; | ||||
| 		y = x-y; | ||||
| 		x = temp; | ||||
| 		if (y > x) | ||||
| 			std::swap(x,y); | ||||
| 	} | ||||
| 	return x; | ||||
| } | ||||
|  | ||||
| HeroMoveDetails::HeroMoveDetails(int3 Src, int3 Dst, CGHeroInstance*Ho) | ||||
| 	:src(Src),dst(Dst),ho(Ho) | ||||
| { | ||||
| @@ -186,12 +173,18 @@ const CGTownInstance * CCallback::getTownInfo(int val, bool mode) const //mode = | ||||
|  | ||||
| bool CCallback::getTownInfo( const CGObjectInstance *town, InfoAboutTown &dest ) const | ||||
| { | ||||
| 	const CGTownInstance *t = dynamic_cast<const CGTownInstance *>(town); | ||||
| 	if(!t || !isVisible(t, player)) //it's not a town or it's not visible for layer | ||||
| 	if(!isVisible(town, player)) //it's not a town or it's not visible for layer | ||||
| 		return false; | ||||
|  | ||||
| 	bool detailed = hasAccess(town->tempOwner); | ||||
|  | ||||
| 	//TODO vision support, info about allies | ||||
| 	dest.initFromTown(t, false); | ||||
| 	if(town->ID == TOWNI_TYPE) | ||||
| 		dest.initFromTown(static_cast<const CGTownInstance *>(town), detailed); | ||||
| 	else if(town->ID == 33 || town->ID == 219) | ||||
| 		dest.initFromGarrison(static_cast<const CGGarrison *>(town), detailed); | ||||
| 	else | ||||
| 		return false; | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| @@ -245,7 +238,7 @@ bool CCallback::getHeroInfo( const CGObjectInstance *hero, InfoAboutHero &dest ) | ||||
| 		return false; | ||||
| 	 | ||||
| 	//TODO vision support, info about allies | ||||
| 	dest.initFromHero(h, false); | ||||
| 	dest.initFromHero(h, hasAccess(h->tempOwner)); | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| @@ -963,6 +956,11 @@ void CCallback::castSpell(const CGHeroInstance *hero, int spellID, const int3 &p | ||||
| 	sendRequest(&cas); | ||||
| } | ||||
|  | ||||
| bool CCallback::hasAccess(int playerId) const | ||||
| { | ||||
| 	return playerId == player  ||  player < 0; | ||||
| } | ||||
|  | ||||
| InfoAboutTown::InfoAboutTown() | ||||
| { | ||||
| 	tType = NULL; | ||||
| @@ -1004,3 +1002,24 @@ void InfoAboutTown::initFromTown( const CGTownInstance *t, bool detailed ) | ||||
| 		} | ||||
| 	}*/ | ||||
| } | ||||
|  | ||||
| void InfoAboutTown::initFromGarrison(const CGGarrison *garr, bool detailed) | ||||
| { | ||||
| 	obj = garr; | ||||
| 	fortLevel = 0; | ||||
| 	army = garr->army; | ||||
| 	name = CGI->generaltexth->names[33]; // "Garrison" | ||||
| 	owner = garr->tempOwner; | ||||
| 	built = false; | ||||
| 	tType = NULL; | ||||
|  | ||||
| 	// Show detailed info only to owning player. | ||||
| 	if(detailed) | ||||
| 	{ | ||||
| 		details = new InfoAboutTown::Details; | ||||
| 		details->customRes = false; | ||||
| 		details->garrisonedHero = false; | ||||
| 		details->goldIncome = -1; | ||||
| 		details->hallLevel = -1; | ||||
| 	} | ||||
| } | ||||
| @@ -42,6 +42,7 @@ struct CPackForServer; | ||||
| class CMapHeader; | ||||
| struct CGPathNode; | ||||
| struct CGPath; | ||||
| class CGGarrison; | ||||
|  | ||||
| struct InfoAboutTown | ||||
| { | ||||
| @@ -65,6 +66,7 @@ struct InfoAboutTown | ||||
| 	InfoAboutTown(); | ||||
| 	~InfoAboutTown(); | ||||
| 	void initFromTown(const CGTownInstance *t, bool detailed); | ||||
| 	void initFromGarrison(const CGGarrison *garr, bool detailed); | ||||
| }; | ||||
|  | ||||
| class ICallback | ||||
| @@ -201,6 +203,7 @@ private: | ||||
| 	template <typename T> void sendRequest(const T*request); | ||||
|  | ||||
| protected: | ||||
| 	bool hasAccess(int playerId) const; | ||||
| 	int player; | ||||
|  | ||||
| public: | ||||
|   | ||||
| @@ -152,10 +152,7 @@ void AdventureMapButton::clickLeft(tribool down, bool previousState) | ||||
| void AdventureMapButton::clickRight(tribool down, bool previousState) | ||||
| { | ||||
| 	if(down && helpBox.size()) //there is no point to show window with nothing inside... | ||||
| 		if(LOCPLINT) | ||||
| 			adventureInt->handleRightClick(helpBox,down,this); | ||||
| 		else | ||||
| 			GH.pushInt(new CRClickPopupInt(CMessage::genWindow(helpBox, 0),true)); | ||||
| 		CRClickPopup::createAndPush(helpBox); | ||||
| } | ||||
|  | ||||
| void AdventureMapButton::hover (bool on) | ||||
|   | ||||
| @@ -27,6 +27,7 @@ | ||||
| #include <sstream> | ||||
| #include "CPreGame.h" | ||||
| #include "../lib/VCMI_Lib.h" | ||||
| #include "../hch/CSpellHandler.h" | ||||
|  | ||||
| #ifdef _MSC_VER | ||||
| #pragma warning (disable : 4355) | ||||
| @@ -272,7 +273,7 @@ void CMinimap::updateRadar() | ||||
|  | ||||
| void CMinimap::clickRight(tribool down, bool previousState) | ||||
| { | ||||
| 	adventureInt->handleRightClick(rcText,down,this); | ||||
| 	adventureInt->handleRightClick(rcText,down); | ||||
| } | ||||
|  | ||||
| void CMinimap::clickLeft(tribool down, bool previousState) | ||||
| @@ -473,96 +474,12 @@ void CTerrainRect::clickLeft(tribool down, bool previousState) | ||||
| { | ||||
| 	if ((down==false) || indeterminate(down)) | ||||
| 		return; | ||||
|  | ||||
| 	int3 mp = whichTileIsIt(); | ||||
| 	if (mp.x<0 || mp.y<0 || mp.x >= LOCPLINT->cb->getMapSize().x || mp.y >= LOCPLINT->cb->getMapSize().y) | ||||
| 		return; | ||||
|  | ||||
| 	std::vector < const CGObjectInstance * > bobjs = LOCPLINT->cb->getBlockingObjs(mp),  //blocking objects at tile | ||||
| 		vobjs = LOCPLINT->cb->getVisitableObjs(mp); //visitable objects | ||||
|  | ||||
| 	if (adventureInt->selection->ID != HEROI_TYPE) //hero is not selected (presumably town) | ||||
| 	{ | ||||
| 		if(currentPath) | ||||
| 		{ | ||||
| 			tlog2<<"Warning: Lost path?" << std::endl; | ||||
| 			//delete currentPath; | ||||
| 			currentPath = NULL; | ||||
| 		} | ||||
|  | ||||
| 		for(size_t i=0; i < bobjs.size(); ++i) | ||||
| 		{ | ||||
| 			if(bobjs[i]->ID == TOWNI_TYPE && bobjs[i]->getOwner() == LOCPLINT->playerID) //our town clicked | ||||
| 			{ | ||||
| 				if(adventureInt->selection == (bobjs[i])) //selected town clicked | ||||
| 					LOCPLINT->openTownWindow(static_cast<const CGTownInstance*>(bobjs[i])); | ||||
| 				else | ||||
| 					adventureInt->select(static_cast<const CArmedInstance*>(bobjs[i])); | ||||
|  | ||||
| 				return; | ||||
| 			} | ||||
| 			else if(bobjs[i]->ID == HEROI_TYPE && bobjs[i]->tempOwner == LOCPLINT->playerID) //hero clicked - select him | ||||
| 			{ | ||||
| 				adventureInt->select(static_cast<const CArmedInstance*>(bobjs[i])); | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	else //hero is selected | ||||
| 	{ | ||||
| 		bool townEntrance = false; //town entrance tile has been clicked? | ||||
| 		const CGHeroInstance * currentHero = static_cast<const CGHeroInstance*>(adventureInt->selection); | ||||
|  | ||||
| 		for(size_t i=0; i < vobjs.size(); ++i) | ||||
| 		{ | ||||
| 			if(vobjs[i]->ID == TOWNI_TYPE) | ||||
| 				townEntrance = true; | ||||
| 		} | ||||
|  | ||||
| 		if(!townEntrance) //not entrance - select town or open hero window | ||||
| 		{ | ||||
| 			for(size_t i=0; i < bobjs.size(); ++i) | ||||
| 			{ | ||||
| 				const CGObjectInstance *o = bobjs[i]; | ||||
| 				const CGPathNode *pn = LOCPLINT->cb->getPathInfo(mp); | ||||
| 				if(  ((o->ID == HEROI_TYPE && pn->turns == 255)  //inaccessible hero | ||||
| 							|| o->ID == TOWNI_TYPE)										   //or town | ||||
| 					&& o->tempOwner == LOCPLINT->playerID) //but must belong to us | ||||
| 				{ | ||||
| 					adventureInt->select(static_cast<const CArmedInstance*>(o)); | ||||
| 					return; | ||||
| 				} | ||||
| 				else if(o->ID == HEROI_TYPE //it's a hero | ||||
| 					&& o->tempOwner == LOCPLINT->playerID  //our hero (is this condition needed?) | ||||
| 					&& currentHero == (o) ) //and selected one  | ||||
| 				{ | ||||
| 					LOCPLINT->openHeroWindow(currentHero); | ||||
| 					return; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		else if(currentHero == vobjs.back()) //selected hero is standing at the town entrance | ||||
| 		{ | ||||
| 			LOCPLINT->openHeroWindow(currentHero); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		//still here? we need to move hero if we clicked end of already selected path or calculate a new path otherwise | ||||
| 		if (currentPath  &&  currentPath->endPos() == mp)//we'll be moving | ||||
| 		{ | ||||
| 			LOCPLINT->pim->unlock(); | ||||
| 			LOCPLINT->moveHero(currentHero,*currentPath); | ||||
| 			LOCPLINT->pim->lock(); | ||||
| 		} | ||||
| 		else if(mp.z == currentHero->pos.z) //remove old path and find a new one if we clicked on the map level on which hero is present | ||||
| 		{ | ||||
| 			int3 bufpos = currentHero->getPosition(false); | ||||
| 			CGPath &path = LOCPLINT->paths[currentHero]; | ||||
| 			currentPath = &path; | ||||
| 			if(!LOCPLINT->cb->getPath2(mp, path)) | ||||
| 				LOCPLINT->eraseCurrentPathOf(currentHero); | ||||
| 		} | ||||
| 	} //end of hero is selected "case" | ||||
| 	adventureInt->tileLClicked(mp); | ||||
| } | ||||
| void CTerrainRect::clickRight(tribool down, bool previousState) | ||||
| { | ||||
| @@ -571,118 +488,7 @@ void CTerrainRect::clickRight(tribool down, bool previousState) | ||||
| 	if (!CGI->mh->map->isInTheMap(mp) || down != true) | ||||
| 		return; | ||||
|  | ||||
| 	std::vector < const CGObjectInstance * > objs = LOCPLINT->cb->getBlockingObjs(mp); | ||||
| 	if(!objs.size())  | ||||
| 	{ | ||||
| 		// Bare or undiscovered terrain | ||||
| 		const TerrainTile * tile = LOCPLINT->cb->getTileInfo(mp); | ||||
| 		if (tile)  | ||||
| 		{ | ||||
| 			std::string hlp; | ||||
| 			CGI->mh->getTerrainDescr(mp, hlp, true); | ||||
| 			CSimpleWindow * temp = CMessage::genWindow(hlp, LOCPLINT->playerID, true); | ||||
| 			CRClickPopupInt *rcpi = new CRClickPopupInt(temp,true); | ||||
| 			GH.pushInt(rcpi); | ||||
| 		} | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	const CGObjectInstance * obj = objs.back(); | ||||
| 	switch(obj->ID) | ||||
| 	{ | ||||
| 	case HEROI_TYPE: | ||||
| 		{ | ||||
| 			if(!vstd::contains(graphics->heroWins,obj->subID) || obj->tempOwner != LOCPLINT->playerID) | ||||
| 			{ | ||||
| 				InfoAboutHero iah; | ||||
| 				if(LOCPLINT->cb->getHeroInfo(obj, iah)) | ||||
| 				{ | ||||
| 					SDL_Surface *iwin = graphics->drawHeroInfoWin(iah); | ||||
| 					CInfoPopup * ip = new CInfoPopup(iwin, GH.current->motion.x-iwin->w, | ||||
| 													  GH.current->motion.y-iwin->h, true); | ||||
| 					GH.pushInt(ip); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					tlog3 << "Warning - no infowin for hero " << obj->id << std::endl; | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				CInfoPopup * ip = new CInfoPopup(graphics->heroWins[obj->subID], | ||||
| 					GH.current->motion.x-graphics->heroWins[obj->subID]->w, | ||||
| 					GH.current->motion.y-graphics->heroWins[obj->subID]->h,false | ||||
| 					); | ||||
| 				GH.pushInt(ip); | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 	case TOWNI_TYPE: | ||||
| 		{ | ||||
| 			if(!vstd::contains(graphics->townWins,obj->id) || obj->tempOwner != LOCPLINT->playerID) | ||||
| 			{ | ||||
| 				InfoAboutTown iah; | ||||
| 				if(LOCPLINT->cb->getTownInfo(obj, iah)) | ||||
| 				{ | ||||
| 					SDL_Surface *iwin = graphics->drawTownInfoWin(iah); | ||||
| 					CInfoPopup * ip = new CInfoPopup(iwin, GH.current->motion.x - iwin->w/2, | ||||
| 						GH.current->motion.y - iwin->h/2, true); | ||||
| 					GH.pushInt(ip); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					tlog3 << "Warning - no infowin for town " << obj->id << std::endl; | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				CInfoPopup * ip = new CInfoPopup(graphics->townWins[obj->id], | ||||
| 					GH.current->motion.x - graphics->townWins[obj->id]->w/2, | ||||
| 					GH.current->motion.y - graphics->townWins[obj->id]->h/2,false | ||||
| 					); | ||||
| 				GH.pushInt(ip); | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 	case 33: // Garrison | ||||
| 	case 219: | ||||
| 		{ | ||||
| 			const CGGarrison *garr = dynamic_cast<const CGGarrison *>(obj); | ||||
|  | ||||
| 			if (garr != NULL) { | ||||
| 				InfoAboutTown iah; | ||||
|  | ||||
| 				iah.obj = garr; | ||||
| 				iah.fortLevel = 0; | ||||
| 				iah.army = garr->army; | ||||
| 				iah.name = VLC->generaltexth->names[33]; // "Garrison" | ||||
| 				iah.owner = garr->tempOwner; | ||||
| 				iah.built = false; | ||||
| 				iah.tType = NULL; | ||||
|  | ||||
| 				// Show detailed info only to owning player. | ||||
| 				if (garr->tempOwner == LOCPLINT->playerID) { | ||||
| 					iah.details = new InfoAboutTown::Details; | ||||
| 					iah.details->customRes = false; | ||||
| 					iah.details->garrisonedHero = false; | ||||
| 					iah.details->goldIncome = -1; | ||||
| 					iah.details->hallLevel = -1; | ||||
| 				} | ||||
|  | ||||
| 				SDL_Surface *iwin = graphics->drawTownInfoWin(iah); | ||||
| 				CInfoPopup * ip = new CInfoPopup(iwin, | ||||
| 					GH.current->motion.x - iwin->w/2, | ||||
| 					GH.current->motion.y - iwin->h/2, true); | ||||
| 				GH.pushInt(ip); | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 	default: | ||||
| 		{ | ||||
| 			adventureInt->handleRightClick(obj->getHoverText(),down,this); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	adventureInt->tileRClicked(mp); | ||||
| } | ||||
| void CTerrainRect::mouseMoved (const SDL_MouseMotionEvent & sEvent) | ||||
| { | ||||
| @@ -700,163 +506,7 @@ void CTerrainRect::mouseMoved (const SDL_MouseMotionEvent & sEvent) | ||||
| 	else | ||||
| 		return; | ||||
|  | ||||
| 	std::vector<std::string> temp = LOCPLINT->cb->getObjDescriptions(pom); | ||||
| 	if (temp.size()) | ||||
| 	{ | ||||
| 		boost::replace_all(temp.back(),"\n"," "); | ||||
| 		adventureInt->statusbar.print(temp.back()); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		std::string hlp; | ||||
| 		CGI->mh->getTerrainDescr(pom, hlp, false); | ||||
| 		adventureInt->statusbar.print(hlp); | ||||
| 		//adventureInt->statusbar.clear(); | ||||
| 	} | ||||
|  | ||||
| 	const CGPathNode *pnode = LOCPLINT->cb->getPathInfo(pom); | ||||
| 	std::vector<const CGObjectInstance *> objs = LOCPLINT->cb->getBlockingObjs(pom);  | ||||
| 	const CGObjectInstance *obj = objs.size() ? objs.back() : NULL; | ||||
| 	bool accessible  =  pnode->turns < 255; | ||||
|  | ||||
| 	int turns = pnode->turns; | ||||
| 	amin(turns, 3); | ||||
|  | ||||
| 	if(adventureInt->selection) | ||||
| 	{ | ||||
| 		if(adventureInt->selection->ID == TOWNI_TYPE) | ||||
| 		{ | ||||
| 			if(obj && obj->tempOwner == LOCPLINT->playerID) | ||||
| 			{ | ||||
| 				if(obj->ID == TOWNI_TYPE) | ||||
| 				{ | ||||
| 					CGI->curh->changeGraphic(0, 3); | ||||
| 				} | ||||
| 				else if(obj->ID == HEROI_TYPE) | ||||
| 				{ | ||||
| 					CGI->curh->changeGraphic(0, 2); | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				CGI->curh->changeGraphic(0, 0); | ||||
| 			} | ||||
| 		} | ||||
| 		else if(adventureInt->selection->ID == HEROI_TYPE) | ||||
| 		{ | ||||
| 			const CGHeroInstance *h = static_cast<const CGHeroInstance *>(adventureInt->selection); | ||||
| 			if(obj) | ||||
| 			{ | ||||
| 				if(obj->ID == HEROI_TYPE) | ||||
| 				{ | ||||
| 					if(obj->tempOwner != LOCPLINT->playerID) //enemy hero TODO: allies | ||||
| 					{ | ||||
| 						if(accessible) | ||||
| 							CGI->curh->changeGraphic(0, 5 + turns*6); | ||||
| 						else | ||||
| 							CGI->curh->changeGraphic(0, 0); | ||||
| 					} | ||||
| 					else //our hero | ||||
| 					{ | ||||
| 						if(adventureInt->selection == obj) | ||||
| 							CGI->curh->changeGraphic(0, 2); | ||||
| 						else if(accessible) | ||||
| 							CGI->curh->changeGraphic(0, 8 + turns*6); | ||||
| 						else | ||||
| 							CGI->curh->changeGraphic(0, 2); | ||||
| 					} | ||||
| 				} | ||||
| 				else if(obj->ID == TOWNI_TYPE) | ||||
| 				{ | ||||
| 					if(obj->tempOwner != LOCPLINT->playerID) //enemy town TODO: allies | ||||
| 					{ | ||||
| 						if(accessible) { | ||||
| 							const CGTownInstance* townObj = dynamic_cast<const CGTownInstance*>(obj); | ||||
|  | ||||
| 							// Show movement cursor for unguarded enemy towns, otherwise attack cursor. | ||||
| 							if (townObj && townObj->army.slots.empty()) | ||||
| 								CGI->curh->changeGraphic(0, 9 + turns*6); | ||||
| 							else | ||||
| 								CGI->curh->changeGraphic(0, 5 + turns*6); | ||||
| 								 | ||||
| 						} else { | ||||
| 							CGI->curh->changeGraphic(0, 0); | ||||
| 						} | ||||
| 					} | ||||
| 					else //our town | ||||
| 					{ | ||||
| 						if(accessible) | ||||
| 							CGI->curh->changeGraphic(0, 9 + turns*6); | ||||
| 						else | ||||
| 							CGI->curh->changeGraphic(0, 3); | ||||
| 					} | ||||
| 				} | ||||
| 				else if(obj->ID == 54) //monster | ||||
| 				{ | ||||
| 					if(accessible) | ||||
| 						CGI->curh->changeGraphic(0, 5 + turns*6); | ||||
| 					else | ||||
| 						CGI->curh->changeGraphic(0, 0); | ||||
| 				} | ||||
| 				else if(obj->ID == 8) //boat | ||||
| 				{ | ||||
| 					if(accessible) | ||||
| 						CGI->curh->changeGraphic(0, 6 + turns*6); | ||||
| 					else | ||||
| 						CGI->curh->changeGraphic(0, 0); | ||||
| 				} | ||||
| 				else if (obj->ID == 33 || obj->ID == 219) // Garrison | ||||
| 				{ | ||||
| 					if (accessible) { | ||||
| 						const CGGarrison* garrObj = dynamic_cast<const CGGarrison*>(obj); | ||||
|  | ||||
| 						// Show battle cursor for guarded enemy garrisons, otherwise movement cursor. | ||||
| 						if (garrObj && garrObj->tempOwner != LOCPLINT->playerID | ||||
| 							&& !garrObj->army.slots.empty()) | ||||
| 						{ | ||||
| 							CGI->curh->changeGraphic(0, 5 + turns*6); | ||||
| 						} | ||||
| 						else | ||||
| 						{ | ||||
| 							CGI->curh->changeGraphic(0, 9 + turns*6); | ||||
| 						} | ||||
| 					} else { | ||||
| 						CGI->curh->changeGraphic(0, 0); | ||||
| 					} | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					if(accessible) | ||||
| 					{ | ||||
| 						if(pnode->land) | ||||
| 							CGI->curh->changeGraphic(0, 9 + turns*6); | ||||
| 						else | ||||
| 							CGI->curh->changeGraphic(0, 28 + turns); | ||||
| 					} | ||||
| 					else | ||||
| 						CGI->curh->changeGraphic(0, 0); | ||||
| 				} | ||||
| 			}  | ||||
| 			else //no objs  | ||||
| 			{ | ||||
| 				if(accessible) | ||||
| 				{ | ||||
| 					if(pnode->land) | ||||
| 					{ | ||||
| 						if(LOCPLINT->cb->getTileInfo(h->getPosition(false))->tertype != TerrainTile::water) | ||||
| 							CGI->curh->changeGraphic(0, 4 + turns*6); | ||||
| 						else | ||||
| 							CGI->curh->changeGraphic(0, 7 + turns*6); //anchor | ||||
| 					} | ||||
| 					else | ||||
| 						CGI->curh->changeGraphic(0, 6 + turns*6); | ||||
| 				} | ||||
| 				else | ||||
| 					CGI->curh->changeGraphic(0, 0); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	//tlog1 << "Tile " << pom << ": Turns=" << (int)pnode->turns <<"  Move:=" << pnode->moveRemains <</* " (from  "  << ")" << */std::endl; | ||||
| 	adventureInt->tileHovered(curHoveredTile); | ||||
| } | ||||
| void CTerrainRect::hover(bool on) | ||||
| { | ||||
| @@ -1321,6 +971,7 @@ CInfoBar::CInfoBar() | ||||
| 	week2 = CDefHandler::giveDef("NEWWEEK2.DEF"); | ||||
| 	week3 = CDefHandler::giveDef("NEWWEEK3.DEF"); | ||||
| 	week4 = CDefHandler::giveDef("NEWWEEK4.DEF"); | ||||
| 	selInfoWin = NULL; | ||||
| } | ||||
| CInfoBar::~CInfoBar() | ||||
| { | ||||
| @@ -1329,8 +980,12 @@ CInfoBar::~CInfoBar() | ||||
| 	delete week2; | ||||
| 	delete week3; | ||||
| 	delete week4; | ||||
|  | ||||
| 	if(selInfoWin) | ||||
| 		SDL_FreeSurface(selInfoWin); | ||||
| } | ||||
| void CInfoBar::draw(SDL_Surface * to, const CGObjectInstance * specific) | ||||
|  | ||||
| void CInfoBar::showAll(SDL_Surface * to) | ||||
| { | ||||
| 	if ((mode>=0) && mode<5) | ||||
| 	{ | ||||
| @@ -1340,24 +995,11 @@ void CInfoBar::draw(SDL_Surface * to, const CGObjectInstance * specific) | ||||
| 	else if (mode==5) | ||||
| 	{ | ||||
| 		mode = -1; | ||||
| 		draw(to,adventureInt->selection); | ||||
| 	} | ||||
| 	if (!specific) | ||||
| 		specific = adventureInt->selection; | ||||
|  | ||||
| 	if(!specific) | ||||
| 		return; | ||||
|  | ||||
| 	if(specific->ID == HEROI_TYPE) //hero | ||||
| 	if(selInfoWin) | ||||
| 	{ | ||||
| 		if(graphics->heroWins.find(specific->subID)!=graphics->heroWins.end()) | ||||
| 			blitAt(graphics->heroWins[specific->subID],pos.x,pos.y,to); | ||||
| 	} | ||||
| 	else if (specific->ID == TOWNI_TYPE) | ||||
| 	{ | ||||
| 		const CGTownInstance * t = static_cast<const CGTownInstance*>(specific); | ||||
| 		if(graphics->townWins.find(t->id)!=graphics->townWins.end()) | ||||
| 			blitAt(graphics->townWins[t->id],pos.x,pos.y,to); | ||||
| 		blitAt(selInfoWin, pos.x, pos.y, to); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -1450,7 +1092,7 @@ void CInfoBar::showComp(SComponent * comp, int time) | ||||
|  | ||||
| void CInfoBar::tick() | ||||
| { | ||||
| 	if((mode >= 0) && (mode < 5)) | ||||
| 	if(mode >= 0  &&  mode < 5) | ||||
| 	{ | ||||
| 		pom++; | ||||
| 		if (pom >= getAnim(mode)->ourImages.size()) | ||||
| @@ -1458,20 +1100,19 @@ void CInfoBar::tick() | ||||
| 			deactivateTimer(); | ||||
| 			toNextTick = -1; | ||||
| 			mode = 5; | ||||
| 			draw(screen2); | ||||
| 			showAll(screen2); | ||||
| 			return; | ||||
| 		} | ||||
| 		toNextTick = 150; | ||||
| 		blitAnim(mode); | ||||
| 	} | ||||
| 	else if (mode == 6) | ||||
| 	else if(mode == 6) | ||||
| 	{ | ||||
| 		deactivateTimer(); | ||||
| 		toNextTick = -1; | ||||
| 		mode = 5; | ||||
| 		draw(screen2); | ||||
| 		showAll(screen2); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| void CInfoBar::show( SDL_Surface * to ) | ||||
| @@ -1491,6 +1132,13 @@ void CInfoBar::deactivate() | ||||
| 		deactivateTimer(); | ||||
| } | ||||
|  | ||||
| void CInfoBar::updateSelection(const CGObjectInstance *obj) | ||||
| { | ||||
| 	if(selInfoWin) | ||||
| 		SDL_FreeSurface(selInfoWin); | ||||
| 	selInfoWin = LOCPLINT->infoWin(obj); | ||||
| } | ||||
|  | ||||
| CAdvMapInt::CAdvMapInt() | ||||
| :statusbar(ADVOPT.statusbarX,ADVOPT.statusbarY,ADVOPT.statusbarG), | ||||
| kingOverview(CGI->generaltexth->zelp[293].first,CGI->generaltexth->zelp[293].second, | ||||
| @@ -1526,6 +1174,7 @@ endTurn(CGI->generaltexth->zelp[302].first,CGI->generaltexth->zelp[302].second, | ||||
| heroList(ADVOPT.hlistSize), | ||||
| townList(ADVOPT.tlistSize,ADVOPT.tlistX,ADVOPT.tlistY,ADVOPT.tlistAU,ADVOPT.tlistAD)//(5,&genRect(192,48,747,196),747,196,747,372), | ||||
| { | ||||
| 	spellBeingCasted = NULL; | ||||
| 	player = 0; | ||||
| 	pos.x = pos.y = 0; | ||||
| 	pos.w = screen->w; | ||||
| @@ -1593,24 +1242,21 @@ void CAdvMapInt::fsleepWake() | ||||
| { | ||||
| } | ||||
| void CAdvMapInt::fmoveHero() | ||||
| { | ||||
| 	if (selection->ID!=HEROI_TYPE) | ||||
| 		return; | ||||
| 	if (!terrain.currentPath) | ||||
| {	 | ||||
| 	const CGHeroInstance *h = curHero(); | ||||
| 	if (!h || !terrain.currentPath) | ||||
| 		return; | ||||
|  | ||||
| 	LOCPLINT->pim->unlock(); | ||||
| 	LOCPLINT->moveHero(static_cast<const CGHeroInstance*>(adventureInt->selection),*terrain.currentPath); | ||||
| 	LOCPLINT->pim->lock(); | ||||
| 	LOCPLINT->moveHero(h, *terrain.currentPath); | ||||
| } | ||||
|  | ||||
| void CAdvMapInt::fshowSpellbok() | ||||
| { | ||||
| 	if (selection->ID!=HEROI_TYPE) //checking necessary values | ||||
| 	if (!curHero()) //checking necessary values | ||||
| 		return; | ||||
|  | ||||
|  | ||||
| 	CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (conf.cc.resx - 620)/2, (conf.cc.resy - 595)/2), (static_cast<const CGHeroInstance*>(adventureInt->selection)), LOCPLINT, false); | ||||
| 	centerOn(selection); | ||||
| 	CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (conf.cc.resx - 620)/2, (conf.cc.resy - 595)/2), curHero(), LOCPLINT, false); | ||||
| 	GH.pushInt(spellWindow); | ||||
| } | ||||
|  | ||||
| @@ -1736,7 +1382,7 @@ void CAdvMapInt::showAll(SDL_Surface *to) | ||||
|  | ||||
| 	statusbar.show(to); | ||||
|  | ||||
| 	infoBar.draw(to); | ||||
| 	infoBar.showAll(to); | ||||
| 	LOCPLINT->cingconsole->show(to); | ||||
| } | ||||
| void CAdvMapInt::show(SDL_Surface *to) | ||||
| @@ -1802,10 +1448,6 @@ void CAdvMapInt::selectionChanged() | ||||
| } | ||||
| void CAdvMapInt::centerOn(int3 on) | ||||
| { | ||||
| 	// TODO:convertPosition should not belong to CGHeroInstance, and it | ||||
| 	// should be split in 2 methods. | ||||
| 	on = CGHeroInstance::convertPosition(on, false); | ||||
|  | ||||
| 	on.x -= CGI->mh->frameW; | ||||
| 	on.y -= CGI->mh->frameH; | ||||
| 	 | ||||
| @@ -1818,10 +1460,20 @@ void CAdvMapInt::centerOn(int3 on) | ||||
| 	if(GH.topInt() == this) | ||||
| 		underground.redraw(); | ||||
| } | ||||
|  | ||||
| void CAdvMapInt::centerOn(const CGObjectInstance *obj) | ||||
| { | ||||
| 	centerOn(obj->getSightCenter()); | ||||
| } | ||||
|  | ||||
| void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key) | ||||
| { | ||||
| 	ui8 Dir = 0; | ||||
| 	int k = key.keysym.sym; | ||||
| 	const CGHeroInstance *h = curHero(); //selected hero | ||||
| 	const CGTownInstance *t = curTown(); //selected town | ||||
|  | ||||
|  | ||||
| 	switch(k) | ||||
| 	{ | ||||
| 	case SDLK_i:  | ||||
| @@ -1834,7 +1486,6 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key) | ||||
| 		return; | ||||
| 	case SDLK_d:  | ||||
| 		{ | ||||
| 			const CGHeroInstance *h = dynamic_cast<const CGHeroInstance*>(selection); | ||||
| 			if(h && isActive() && key.state == SDL_PRESSED) | ||||
| 				LOCPLINT->tryDiggging(h); | ||||
| 			return; | ||||
| @@ -1847,7 +1498,6 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key) | ||||
| 		{ | ||||
| 			if(!isActive())  | ||||
| 				return; | ||||
| 			const CGHeroInstance *h = dynamic_cast<const CGHeroInstance*>(selection); | ||||
| 			if(h && key.state == SDL_PRESSED) | ||||
| 			{ | ||||
| 				LOCPLINT->pim->unlock(); | ||||
| @@ -1860,10 +1510,10 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key) | ||||
| 		{ | ||||
| 			if(!isActive() || !selection || key.state != SDL_PRESSED)  | ||||
| 				return; | ||||
| 			if(selection->ID == HEROI_TYPE) | ||||
| 				LOCPLINT->openHeroWindow(static_cast<const CGHeroInstance*>(selection)); | ||||
| 			else if(selection->ID == TOWNI_TYPE) | ||||
| 				LOCPLINT->openTownWindow(static_cast<const CGTownInstance*>(selection)); | ||||
| 			if(h) | ||||
| 				LOCPLINT->openHeroWindow(h); | ||||
| 			else if(t) | ||||
| 				LOCPLINT->openTownWindow(t); | ||||
| 			return; | ||||
| 		} | ||||
| 	case SDLK_t: | ||||
| @@ -1919,12 +1569,12 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key) | ||||
| 			if(k < 0 || k > 8 || key.state != SDL_PRESSED) | ||||
| 				return; | ||||
|  | ||||
| 			if(!h)  | ||||
| 				break; | ||||
|  | ||||
| 			const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(selection); | ||||
| 			if(!h) break; | ||||
| 			if(k == 4) | ||||
| 			{ | ||||
| 				centerOn(h->getPosition(false)); | ||||
| 				centerOn(h); | ||||
| 				return; | ||||
| 			} | ||||
|  | ||||
| @@ -1940,9 +1590,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key) | ||||
|  | ||||
| 			if(!path.nodes[0].turns) | ||||
| 			{ | ||||
| 				LOCPLINT->pim->unlock(); | ||||
| 				LOCPLINT->moveHero(h, path); | ||||
| 				LOCPLINT->pim->lock(); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| @@ -1955,13 +1603,11 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key) | ||||
| 	else | ||||
| 		scrollingDir &= ~Dir; | ||||
| } | ||||
| void CAdvMapInt::handleRightClick(std::string text, tribool down, CIntObject * client) | ||||
| void CAdvMapInt::handleRightClick(std::string text, tribool down) | ||||
| { | ||||
| 	if (down) | ||||
| 	if(down) | ||||
| 	{ | ||||
| 		CSimpleWindow * temp = CMessage::genWindow(text,LOCPLINT->playerID,true); | ||||
| 		CRClickPopupInt *rcpi = new CRClickPopupInt(temp,true); | ||||
| 		GH.pushInt(rcpi); | ||||
| 		CRClickPopup::createAndPush(text); | ||||
| 	} | ||||
| } | ||||
| int3 CAdvMapInt::verifyPos(int3 ver) | ||||
| @@ -1981,12 +1627,12 @@ int3 CAdvMapInt::verifyPos(int3 ver) | ||||
| 	return ver; | ||||
| } | ||||
|  | ||||
| void CAdvMapInt::select(const CArmedInstance *sel ) | ||||
| void CAdvMapInt::select(const CArmedInstance *sel, bool centerView /*= true*/) | ||||
| { | ||||
| 	LOCPLINT->cb->setSelection(sel); | ||||
|  | ||||
| 	centerOn(sel->pos); | ||||
| 	selection = sel; | ||||
| 	if(centerView) | ||||
| 		centerOn(sel); | ||||
|  | ||||
| 	terrain.currentPath = NULL; | ||||
| 	if(sel->ID==TOWNI_TYPE) | ||||
| @@ -2009,7 +1655,8 @@ void CAdvMapInt::select(const CArmedInstance *sel ) | ||||
| 	} | ||||
| 	townList.draw(screen); | ||||
| 	heroList.draw(screen); | ||||
| 	infoBar.draw(screen); | ||||
| 	infoBar.updateSelection(sel); | ||||
| 	infoBar.showAll(screen); | ||||
| } | ||||
|  | ||||
| void CAdvMapInt::mouseMoved( const SDL_MouseMotionEvent & sEvent ) | ||||
| @@ -2090,10 +1737,317 @@ void CAdvMapInt::startTurn() | ||||
| 	state = INGAME; | ||||
| } | ||||
|  | ||||
| void CAdvMapInt::tileLClicked(const int3 &mp) | ||||
| { | ||||
| 	std::vector < const CGObjectInstance * > bobjs = LOCPLINT->cb->getBlockingObjs(mp),  //blocking objects at tile | ||||
| 		vobjs = LOCPLINT->cb->getVisitableObjs(mp); //visitable objects | ||||
| 	const TerrainTile *tile = LOCPLINT->cb->getTileInfo(mp); | ||||
| 	const CGObjectInstance *topBlocking = bobjs.size() ? bobjs.back() : NULL; | ||||
|  | ||||
|  | ||||
| 	int3 selPos = selection->getSightCenter(); | ||||
| 	if(spellBeingCasted && isInScreenRange(selPos, mp)) | ||||
| 	{ | ||||
| 		const TerrainTile *heroTile = LOCPLINT->cb->getTileInfo(selPos); | ||||
|  | ||||
| 		switch(spellBeingCasted->id) | ||||
| 		{ | ||||
| 		case Spells::SCUTTLE_BOAT: //Scuttle Boat  | ||||
| 			if(topBlocking && topBlocking->ID == 8) | ||||
| 				leaveCastingMode(true, mp); | ||||
| 			break; | ||||
| 		case Spells::DIMENSION_DOOR: | ||||
| 			if(!tile || tile->isClear(heroTile)) | ||||
| 				leaveCastingMode(true, mp); | ||||
| 			break; | ||||
| 		} | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if (selection->ID != HEROI_TYPE) //hero is not selected (presumably town) | ||||
| 	{ | ||||
| 		assert(!terrain.currentPath); //path can be active only when hero is selected | ||||
| 		if(selection == topBlocking) //selected town clicked | ||||
| 			LOCPLINT->openTownWindow(static_cast<const CGTownInstance*>(topBlocking)); | ||||
| 		else if(topBlocking && (topBlocking->ID == TOWNI_TYPE || topBlocking->ID == HEROI_TYPE) && topBlocking->tempOwner == LOCPLINT->playerID) //our town/hero clicked | ||||
| 			select(static_cast<const CArmedInstance*>(topBlocking), false); | ||||
| 	} | ||||
| 	else if(const CGHeroInstance * currentHero = curHero()) //hero is selected | ||||
| 	{ | ||||
| 		const CGPathNode *pn = LOCPLINT->cb->getPathInfo(mp); | ||||
| 		if(currentHero == topBlocking) //clicked selected hero | ||||
| 		{ | ||||
| 			LOCPLINT->openHeroWindow(currentHero); | ||||
| 		} | ||||
| 		else if(topBlocking && (topBlocking->ID == HEROI_TYPE || topBlocking->ID == TOWNI_TYPE) //clicked our town or hero | ||||
| 			&& pn->turns == 255 && topBlocking->tempOwner == LOCPLINT->playerID) //at inaccessible tile | ||||
| 		{ | ||||
| 			select(static_cast<const CArmedInstance*>(topBlocking), false); | ||||
| 		} | ||||
| 		else //still here? we need to move hero if we clicked end of already selected path or calculate a new path otherwise | ||||
| 		{ | ||||
| 			if (terrain.currentPath  &&  terrain.currentPath->endPos() == mp)//we'll be moving | ||||
| 			{ | ||||
| 				LOCPLINT->moveHero(currentHero,*terrain.currentPath); | ||||
| 			} | ||||
| 			else if(mp.z == currentHero->pos.z) //remove old path and find a new one if we clicked on the map level on which hero is present | ||||
| 			{ | ||||
| 				CGPath &path = LOCPLINT->paths[currentHero]; | ||||
| 				terrain.currentPath = &path; | ||||
| 				if(!LOCPLINT->cb->getPath2(mp, path)) //try getting path, erase if failed | ||||
| 					LOCPLINT->eraseCurrentPathOf(currentHero); | ||||
| 			} | ||||
| 		} | ||||
| 	} //end of hero is selected "case" | ||||
| 	else | ||||
| 	{ | ||||
| 		throw std::string("Nothing is selected..."); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CAdvMapInt::tileHovered(const int3 &tile) | ||||
| { | ||||
| 	std::vector<std::string> temp = LOCPLINT->cb->getObjDescriptions(tile); | ||||
| 	if (temp.size()) | ||||
| 	{ | ||||
| 		boost::replace_all(temp.back(),"\n"," "); | ||||
| 		statusbar.print(temp.back()); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		std::string hlp; | ||||
| 		CGI->mh->getTerrainDescr(tile, hlp, false); | ||||
| 		statusbar.print(hlp); | ||||
| 	} | ||||
|  | ||||
| 	const CGPathNode *pnode = LOCPLINT->cb->getPathInfo(tile); | ||||
| 	std::vector<const CGObjectInstance *> objs = LOCPLINT->cb->getBlockingObjs(tile);  | ||||
| 	const CGObjectInstance *objAtTile = objs.size() ? objs.back() : NULL; | ||||
| 	bool accessible  =  pnode->turns < 255; | ||||
|  | ||||
| 	int turns = pnode->turns; | ||||
| 	amin(turns, 3); | ||||
|  | ||||
| 	if(!selection) //may occur just at the start of game (fake move before full intiialization) | ||||
| 		return; | ||||
|  | ||||
| 	if(spellBeingCasted) | ||||
| 	{ | ||||
| 		switch(spellBeingCasted->id) | ||||
| 		{ | ||||
| 		case Spells::SCUTTLE_BOAT: | ||||
| 			if(objAtTile && objAtTile->ID == 8) | ||||
| 				CGI->curh->changeGraphic(0, 42); | ||||
| 			else | ||||
| 				CGI->curh->changeGraphic(0, 0); | ||||
| 			return; | ||||
| 		case Spells::DIMENSION_DOOR: | ||||
| 			{ | ||||
| 				const TerrainTile *t = LOCPLINT->cb->getTileInfo(tile); | ||||
| 				int3 hpos = selection->getSightCenter(); | ||||
| 				if((!t  ||  t->isClear(LOCPLINT->cb->getTileInfo(hpos)))   &&   isInScreenRange(hpos, tile)) | ||||
| 					CGI->curh->changeGraphic(0, 41); | ||||
| 				else | ||||
| 					CGI->curh->changeGraphic(0, 0); | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if(selection->ID == TOWNI_TYPE) | ||||
| 	{ | ||||
| 		if(objAtTile && objAtTile->tempOwner == LOCPLINT->playerID) | ||||
| 		{ | ||||
| 			if(objAtTile->ID == TOWNI_TYPE) | ||||
| 				CGI->curh->changeGraphic(0, 3); | ||||
| 			else if(objAtTile->ID == HEROI_TYPE) | ||||
| 				CGI->curh->changeGraphic(0, 2); | ||||
| 		} | ||||
| 		else | ||||
| 			CGI->curh->changeGraphic(0, 0); | ||||
| 	} | ||||
| 	else if(const CGHeroInstance *h = curHero()) | ||||
| 	{ | ||||
| 		if(objAtTile) | ||||
| 		{ | ||||
| 			if(objAtTile->ID == HEROI_TYPE) | ||||
| 			{ | ||||
| 				if(objAtTile->tempOwner != LOCPLINT->playerID) //enemy hero TODO: allies | ||||
| 				{ | ||||
| 					if(accessible) | ||||
| 						CGI->curh->changeGraphic(0, 5 + turns*6); | ||||
| 					else | ||||
| 						CGI->curh->changeGraphic(0, 0); | ||||
| 				} | ||||
| 				else //our hero | ||||
| 				{ | ||||
| 					if(selection == objAtTile) | ||||
| 						CGI->curh->changeGraphic(0, 2); | ||||
| 					else if(accessible) | ||||
| 						CGI->curh->changeGraphic(0, 8 + turns*6); | ||||
| 					else | ||||
| 						CGI->curh->changeGraphic(0, 2); | ||||
| 				} | ||||
| 			} | ||||
| 			else if(objAtTile->ID == TOWNI_TYPE) | ||||
| 			{ | ||||
| 				if(objAtTile->tempOwner != LOCPLINT->playerID) //enemy town TODO: allies | ||||
| 				{ | ||||
| 					if(accessible)  | ||||
| 					{ | ||||
| 						const CGTownInstance* townObj = dynamic_cast<const CGTownInstance*>(objAtTile); | ||||
|  | ||||
| 						// Show movement cursor for unguarded enemy towns, otherwise attack cursor. | ||||
| 						if (townObj && townObj->army.slots.empty()) | ||||
| 							CGI->curh->changeGraphic(0, 9 + turns*6); | ||||
| 						else | ||||
| 							CGI->curh->changeGraphic(0, 5 + turns*6); | ||||
|  | ||||
| 					}  | ||||
| 					else  | ||||
| 					{ | ||||
| 						CGI->curh->changeGraphic(0, 0); | ||||
| 					} | ||||
| 				} | ||||
| 				else //our town | ||||
| 				{ | ||||
| 					if(accessible) | ||||
| 						CGI->curh->changeGraphic(0, 9 + turns*6); | ||||
| 					else | ||||
| 						CGI->curh->changeGraphic(0, 3); | ||||
| 				} | ||||
| 			} | ||||
| 			else if(objAtTile->ID == 54) //monster | ||||
| 			{ | ||||
| 				if(accessible) | ||||
| 					CGI->curh->changeGraphic(0, 5 + turns*6); | ||||
| 				else | ||||
| 					CGI->curh->changeGraphic(0, 0); | ||||
| 			} | ||||
| 			else if(objAtTile->ID == 8) //boat | ||||
| 			{ | ||||
| 				if(accessible) | ||||
| 					CGI->curh->changeGraphic(0, 6 + turns*6); | ||||
| 				else | ||||
| 					CGI->curh->changeGraphic(0, 0); | ||||
| 			} | ||||
| 			else if (objAtTile->ID == 33 || objAtTile->ID == 219) // Garrison | ||||
| 			{ | ||||
| 				if (accessible)  | ||||
| 				{ | ||||
| 					const CGGarrison* garrObj = dynamic_cast<const CGGarrison*>(objAtTile); //TODO evil evil cast! | ||||
|  | ||||
| 					// Show battle cursor for guarded enemy garrisons, otherwise movement cursor. | ||||
| 					if (garrObj  &&  garrObj->tempOwner != LOCPLINT->playerID  &&  !garrObj->army.slots.empty()) | ||||
| 						CGI->curh->changeGraphic(0, 5 + turns*6); | ||||
| 					else | ||||
| 						CGI->curh->changeGraphic(0, 9 + turns*6); | ||||
| 				}  | ||||
| 				else  | ||||
| 					CGI->curh->changeGraphic(0, 0); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				if(accessible) | ||||
| 				{ | ||||
| 					if(pnode->land) | ||||
| 						CGI->curh->changeGraphic(0, 9 + turns*6); | ||||
| 					else | ||||
| 						CGI->curh->changeGraphic(0, 28 + turns); | ||||
| 				} | ||||
| 				else | ||||
| 					CGI->curh->changeGraphic(0, 0); | ||||
| 			} | ||||
| 		}  | ||||
| 		else //no objs  | ||||
| 		{ | ||||
| 			if(accessible) | ||||
| 			{ | ||||
| 				if(pnode->land) | ||||
| 				{ | ||||
| 					if(LOCPLINT->cb->getTileInfo(h->getPosition(false))->tertype != TerrainTile::water) | ||||
| 						CGI->curh->changeGraphic(0, 4 + turns*6); | ||||
| 					else | ||||
| 						CGI->curh->changeGraphic(0, 7 + turns*6); //anchor | ||||
| 				} | ||||
| 				else | ||||
| 					CGI->curh->changeGraphic(0, 6 + turns*6); | ||||
| 			} | ||||
| 			else | ||||
| 				CGI->curh->changeGraphic(0, 0); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CAdvMapInt::tileRClicked(const int3 &mp) | ||||
| { | ||||
| 	if(spellBeingCasted) | ||||
| 	{ | ||||
| 		leaveCastingMode(); | ||||
| 		LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[731]); //Spell cancelled | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	std::vector < const CGObjectInstance * > objs = LOCPLINT->cb->getBlockingObjs(mp); | ||||
| 	if(!objs.size())  | ||||
| 	{ | ||||
| 		// Bare or undiscovered terrain | ||||
| 		const TerrainTile * tile = LOCPLINT->cb->getTileInfo(mp); | ||||
| 		if (tile)  | ||||
| 		{ | ||||
| 			std::string hlp; | ||||
| 			CGI->mh->getTerrainDescr(mp, hlp, true); | ||||
| 			CRClickPopup::createAndPush(hlp); | ||||
| 		} | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	const CGObjectInstance * obj = objs.back(); | ||||
| 	CRClickPopup::createAndPush(obj, GH.current->motion, CENTER); | ||||
| } | ||||
|  | ||||
| void CAdvMapInt::enterCastingMode(const CSpell * sp) | ||||
| { | ||||
| 	using namespace Spells; | ||||
| 	assert(sp->id == SCUTTLE_BOAT  ||  sp->id == DIMENSION_DOOR); | ||||
| 	spellBeingCasted = sp; | ||||
|  | ||||
| 	deactivate(); | ||||
| 	terrain.activate(); | ||||
| 	GH.fakeMouseMove(); | ||||
| } | ||||
|  | ||||
| void CAdvMapInt::leaveCastingMode(bool cast /*= false*/, int3 dest /*= int3(-1, -1, -1)*/) | ||||
| { | ||||
| 	assert(spellBeingCasted); | ||||
| 	int id = spellBeingCasted->id; | ||||
| 	spellBeingCasted = NULL; | ||||
| 	terrain.deactivate(); | ||||
| 	activate(); | ||||
|  | ||||
| 	LOCPLINT->cb->castSpell(curHero(), id, dest); | ||||
| } | ||||
|  | ||||
| const CGHeroInstance * CAdvMapInt::curHero() const | ||||
| { | ||||
| 	if(selection && selection->ID == HEROI_TYPE) | ||||
| 		return static_cast<const CGHeroInstance *>(selection); | ||||
| 	else | ||||
| 		return NULL; | ||||
| } | ||||
|  | ||||
| const CGTownInstance * CAdvMapInt::curTown() const | ||||
| { | ||||
| 	if(selection && selection->ID == TOWNI_TYPE) | ||||
| 		return static_cast<const CGTownInstance *>(selection); | ||||
| 	else | ||||
| 		return NULL; | ||||
| } | ||||
|  | ||||
| CAdventureOptions::CAdventureOptions() | ||||
| { | ||||
| 	OBJ_CONSTRUCTION_CAPTURING_ALL; | ||||
| 	bg = new CPicture(BitmapHandler::loadBitmap("ADVOPTS.bmp"), 0, 0); | ||||
| 	bg = new CPicture("ADVOPTS.bmp"); | ||||
| 	graphics->blueToPlayersAdv(bg->bg, LOCPLINT->playerID); | ||||
| 	pos = bg->center(); | ||||
| 	exit = new AdventureMapButton("","",boost::bind(&CGuiHandler::popIntTotally, &GH, this), 204, 313, "IOK6432.DEF",SDLK_RETURN); | ||||
| @@ -2106,13 +2060,11 @@ CAdventureOptions::CAdventureOptions() | ||||
| 	puzzle = new AdventureMapButton("","", boost::bind(&CGuiHandler::popIntTotally, &GH, this), 24, 81, "ADVPUZ.DEF"); | ||||
| 	puzzle->callback += boost::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT); | ||||
|  | ||||
| 	const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(adventureInt->selection); | ||||
| 	dig = new AdventureMapButton("","", boost::bind(&CGuiHandler::popIntTotally, &GH, this), 24, 139, "ADVDIG.DEF"); | ||||
| 	if(h) | ||||
| 	if(const CGHeroInstance *h = adventureInt->curHero()) | ||||
| 		dig->callback += boost::bind(&CPlayerInterface::tryDiggging, LOCPLINT, h); | ||||
| 	else | ||||
| 		dig->block(true); | ||||
|  | ||||
| } | ||||
|  | ||||
| CAdventureOptions::~CAdventureOptions() | ||||
|   | ||||
| @@ -13,6 +13,7 @@ class CAdvMapInt; | ||||
| class CGHeroInstance; | ||||
| class CGTownInstance; | ||||
| class CHeroWindow; | ||||
| class CSpell; | ||||
| /*****************************/ | ||||
|  | ||||
| /* | ||||
| @@ -116,18 +117,20 @@ public: | ||||
| 	SComponent * current; | ||||
| 	int mode; | ||||
| 	int pom; | ||||
| 	SDL_Surface *selInfoWin; //info box for selection | ||||
|  | ||||
| 	CInfoBar(); | ||||
| 	~CInfoBar(); | ||||
| 	void newDay(int Day); //start showing new day/week animation | ||||
| 	void showComp(SComponent * comp, int time=5000); | ||||
| 	void tick(); | ||||
| 	void draw(SDL_Surface * to, const CGObjectInstance * specific=NULL); // if specific==0 function draws info about selected hero/town | ||||
| 	void showAll(SDL_Surface * to); // if specific==0 function draws info about selected hero/town | ||||
| 	void blitAnim(int mode);//0 - day, 1 - week | ||||
| 	CDefHandler * getAnim(int mode); | ||||
| 	void show(SDL_Surface * to); | ||||
| 	void activate(); | ||||
| 	void deactivate(); | ||||
| 	void updateSelection(const CGObjectInstance *obj); | ||||
| }; | ||||
| /*****************************/ | ||||
| class CAdvMapInt : public CIntObject //adventure map interface | ||||
| @@ -166,13 +169,13 @@ public: | ||||
| 		endTurn;//- end turn | ||||
|  | ||||
| 	CTerrainRect terrain; //visible terrain | ||||
|  | ||||
| 	CResDataBar resdatabar; | ||||
|  | ||||
| 	CHeroList heroList; | ||||
| 	CTownList townList; | ||||
| 	CInfoBar infoBar; | ||||
|  | ||||
| 	const CSpell *spellBeingCasted; //NULL if none | ||||
|  | ||||
| 	CHeroWindow * heroWindow; | ||||
|  | ||||
| 	const CArmedInstance *selection; //currently selected town/hero | ||||
| @@ -195,11 +198,12 @@ public: | ||||
| 	void show(SDL_Surface * to); //redraws terrain | ||||
| 	void showAll(SDL_Surface * to); //shows and activates adv. map interface | ||||
|  | ||||
| 	void select(const CArmedInstance *sel); | ||||
| 	void select(const CArmedInstance *sel, bool centerView = true); | ||||
| 	void selectionChanged(); | ||||
| 	void centerOn(int3 on); | ||||
| 	void centerOn(const CGObjectInstance *obj); | ||||
| 	int3 verifyPos(int3 ver); | ||||
| 	void handleRightClick(std::string text, tribool down, CIntObject * client); | ||||
| 	void handleRightClick(std::string text, tribool down); | ||||
| 	void keyPressed(const SDL_KeyboardEvent & key); | ||||
| 	void mouseMoved (const SDL_MouseMotionEvent & sEvent); | ||||
| 	bool isActive(); | ||||
| @@ -207,6 +211,13 @@ public: | ||||
| 	void setPlayer(int Player); | ||||
| 	void startHotSeatWait(int Player); | ||||
| 	void startTurn(); | ||||
| 	void tileLClicked(const int3 &mp); | ||||
| 	void tileHovered(const int3 &tile); | ||||
| 	void tileRClicked(const int3 &mp); | ||||
| 	void enterCastingMode(const CSpell * sp); | ||||
| 	void leaveCastingMode(bool cast = false, int3 dest = int3(-1, -1, -1)); | ||||
| 	const CGHeroInstance * curHero() const; | ||||
| 	const CGTownInstance * curTown() const; | ||||
| }; | ||||
|  | ||||
| extern CAdvMapInt *adventureInt; | ||||
|   | ||||
| @@ -164,7 +164,12 @@ void CCursorHandler::shiftPos( int &x, int &y ) | ||||
| 				y -= 16; | ||||
| 			} | ||||
| 		} | ||||
| 		else if(number < 31) | ||||
| 		else if(number == 41) | ||||
| 		{ | ||||
| 			x -= 14; | ||||
| 			y -= 16; | ||||
| 		} | ||||
| 		else if(number < 31 || number == 42) | ||||
| 		{ | ||||
| 			x -= 20; | ||||
| 			y -= 20; | ||||
|   | ||||
| @@ -77,6 +77,7 @@ std::queue<SDL_Event*> events; | ||||
| boost::mutex eventsM; | ||||
|  | ||||
| static bool gOnlyAI = false; | ||||
| static bool setResolution = false; //set by event handling thread after resolution is adjusted | ||||
|  | ||||
| void processCommand(const std::string &message); | ||||
| static void setScreenRes(int w, int h, int bpp, bool fullscreen); | ||||
| @@ -483,6 +484,7 @@ static void listenForEvents() | ||||
| 		else if(ev->type == SDL_USEREVENT && ev->user.code == 1) | ||||
| 		{ | ||||
| 			setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,conf.cc.fullscreen); | ||||
| 			setResolution = true; | ||||
| 			delete ev; | ||||
| 			continue; | ||||
| 		} | ||||
| @@ -540,5 +542,11 @@ void startGame(StartInfo * options) | ||||
| 	} | ||||
|  | ||||
| 	CGI->musich->stopMusic(); | ||||
|  | ||||
| 	//allow event handling thread change resolution | ||||
| 	eventsM.unlock(); | ||||
| 	while(!setResolution) boost::this_thread::sleep(boost::posix_time::milliseconds(50)); | ||||
| 	eventsM.lock(); | ||||
|  | ||||
| 	client->connectionHandler = new boost::thread(&CClient::run, client); | ||||
| } | ||||
|   | ||||
| @@ -133,14 +133,6 @@ CPlayerInterface::~CPlayerInterface() | ||||
| 		cingconsole->deactivate(); | ||||
| 	delete cingconsole; | ||||
|  | ||||
| 	for(std::map<int,SDL_Surface*>::iterator i=graphics->heroWins.begin(); i!= graphics->heroWins.end(); i++) | ||||
| 		SDL_FreeSurface(i->second); | ||||
| 	graphics->heroWins.clear(); | ||||
|  | ||||
| 	for(std::map<int,SDL_Surface*>::iterator i=graphics->townWins.begin(); i!= graphics->townWins.end(); i++) | ||||
| 		SDL_FreeSurface(i->second); | ||||
| 	graphics->townWins.clear(); | ||||
|  | ||||
| 	LOCPLINT = NULL; | ||||
| } | ||||
| void CPlayerInterface::init(ICallback * CB) | ||||
| @@ -149,13 +141,6 @@ void CPlayerInterface::init(ICallback * CB) | ||||
| 	if(!adventureInt) | ||||
| 		adventureInt = new CAdvMapInt(); | ||||
|  | ||||
| 	std::vector<const CGTownInstance*> tt = cb->getTownsInfo(false); | ||||
| 	for(int i=0;i<tt.size();i++) | ||||
| 	{ | ||||
| 		SDL_Surface * pom = infoWin(tt[i]); | ||||
| 		graphics->townWins.insert(std::pair<int,SDL_Surface*>(tt[i]->id,pom)); | ||||
| 	} | ||||
|  | ||||
| 	if(!towns.size() && !wanderingHeroes.size()) | ||||
| 	{ | ||||
| 		recreateHeroTownList(); | ||||
| @@ -248,7 +233,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details) | ||||
| 	const CGHeroInstance * ho = cb->getHeroInfo(details.id); //object representing this hero | ||||
| 	int3 hp = details.start; | ||||
|  | ||||
| 	adventureInt->centerOn(ho->pos); //actualizing screen pos | ||||
| 	adventureInt->centerOn(ho); //actualizing screen pos | ||||
| 	adventureInt->minimap.draw(screen2); | ||||
| 	adventureInt->heroList.draw(screen2); | ||||
|  | ||||
| @@ -336,15 +321,12 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details) | ||||
| void CPlayerInterface::heroKilled(const CGHeroInstance* hero) | ||||
| { | ||||
| 	boost::unique_lock<boost::recursive_mutex> un(*pim); | ||||
| 	graphics->heroWins.erase(hero->ID); | ||||
| 	wanderingHeroes -= hero; | ||||
| 	adventureInt->heroList.updateHList(hero); | ||||
| } | ||||
| void CPlayerInterface::heroCreated(const CGHeroInstance * hero) | ||||
| { | ||||
| 	boost::unique_lock<boost::recursive_mutex> un(*pim); | ||||
| 	if(graphics->heroWins.find(hero->subID)==graphics->heroWins.end()) | ||||
| 		graphics->heroWins.insert(std::pair<int,SDL_Surface*>(hero->subID,infoWin(hero))); | ||||
| 	wanderingHeroes.push_back(hero); | ||||
| 	adventureInt->heroList.updateHList(); | ||||
| } | ||||
| @@ -356,38 +338,31 @@ void CPlayerInterface::openTownWindow(const CGTownInstance * town) | ||||
|  | ||||
| SDL_Surface * CPlayerInterface::infoWin(const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero | ||||
| { | ||||
| 	if (specific) | ||||
| 	if(!specific) | ||||
| 		specific = adventureInt->selection; | ||||
|  | ||||
| 	assert(specific); | ||||
|  | ||||
| 	switch(specific->ID) | ||||
| 	{ | ||||
| 		switch (specific->ID) | ||||
| 	case HEROI_TYPE: 				 | ||||
| 		{ | ||||
| 		case HEROI_TYPE: | ||||
| 			return graphics->drawHeroInfoWin(dynamic_cast<const CGHeroInstance*>(specific)); | ||||
| 			break; | ||||
| 		case TOWNI_TYPE: | ||||
| 			return graphics->drawTownInfoWin(dynamic_cast<const CGTownInstance*>(specific)); | ||||
| 			break; | ||||
| 		default: | ||||
| 			return NULL; | ||||
| 			break; | ||||
| 			InfoAboutHero iah; | ||||
| 			bool gotInfo = LOCPLINT->cb->getHeroInfo(specific, iah); | ||||
| 			assert(gotInfo); | ||||
| 			return graphics->drawHeroInfoWin(iah); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		switch (adventureInt->selection->ID) | ||||
| 	case TOWNI_TYPE: | ||||
| 	case 33: // Garrison | ||||
| 	case 219: | ||||
| 		{ | ||||
| 		case HEROI_TYPE: | ||||
| 			{ | ||||
| 				const CGHeroInstance * curh = (const CGHeroInstance *)adventureInt->selection; | ||||
| 				return graphics->drawHeroInfoWin(curh); | ||||
| 			} | ||||
| 		case TOWNI_TYPE: | ||||
| 			{ | ||||
| 				return graphics->drawTownInfoWin((const CGTownInstance *)adventureInt->selection); | ||||
| 			} | ||||
| 		default: | ||||
| 			tlog1 << "Strange... selection is neither hero nor town\n"; | ||||
| 			return NULL; | ||||
| 			InfoAboutTown iah; | ||||
| 			bool gotInfo = LOCPLINT->cb->getTownInfo(specific, iah); | ||||
| 			assert(gotInfo); | ||||
| 			return graphics->drawTownInfoWin(iah); | ||||
| 		} | ||||
| 	default: | ||||
| 		return NULL; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -408,12 +383,12 @@ void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int | ||||
| 	if(which >= PRIMARY_SKILLS) //no need to redraw infowin if this is experience (exp is treated as prim skill with id==4) | ||||
| 		return; | ||||
| 	boost::unique_lock<boost::recursive_mutex> un(*pim); | ||||
| 	redrawHeroWin(hero); | ||||
| 	updateInfo(hero); | ||||
| } | ||||
| void CPlayerInterface::heroManaPointsChanged(const CGHeroInstance * hero) | ||||
| { | ||||
| 	boost::unique_lock<boost::recursive_mutex> un(*pim); | ||||
| 	redrawHeroWin(hero); | ||||
| 	updateInfo(hero); | ||||
| } | ||||
| void CPlayerInterface::heroMovePointsChanged(const CGHeroInstance * hero) | ||||
| { | ||||
| @@ -439,10 +414,7 @@ void CPlayerInterface::heroGotLevel(const CGHeroInstance *hero, int pskill, std: | ||||
| void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town) | ||||
| { | ||||
| 	boost::unique_lock<boost::recursive_mutex> un(*pim); | ||||
| 	//redraw infowindow | ||||
| 	SDL_FreeSurface(graphics->townWins[town->id]); | ||||
| 	graphics->townWins[town->id] = infoWin(town); | ||||
|  | ||||
| 	updateInfo(town); | ||||
|  | ||||
| 	if(town->garrisonHero && vstd::contains(wanderingHeroes,town->garrisonHero)) //wandering hero moved to the garrison | ||||
| 	{ | ||||
| @@ -479,30 +451,7 @@ void CPlayerInterface::heroVisitsTown(const CGHeroInstance* hero, const CGTownIn | ||||
| void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj) | ||||
| { | ||||
| 	boost::unique_lock<boost::recursive_mutex> un(*pim); | ||||
| 	if(obj->ID == HEROI_TYPE) //hero | ||||
| 	{ | ||||
| 		const CGHeroInstance * hh; | ||||
| 		if(hh = dynamic_cast<const CGHeroInstance*>(obj)) | ||||
| 		{ | ||||
| 			SDL_FreeSurface(graphics->heroWins[hh->subID]); | ||||
| 			graphics->heroWins[hh->subID] = infoWin(hh); | ||||
| 		} | ||||
| 	} | ||||
| 	else if (obj->ID == TOWNI_TYPE) //town | ||||
| 	{ | ||||
| 		const CGTownInstance * tt; | ||||
| 		if(tt = static_cast<const CGTownInstance*>(obj)) | ||||
| 		{ | ||||
| 			SDL_FreeSurface(graphics->townWins[tt->id]); | ||||
| 			graphics->townWins[tt->id] = infoWin(tt); | ||||
| 		} | ||||
| 		if(tt->visitingHero) | ||||
| 		{ | ||||
| 			SDL_FreeSurface(graphics->heroWins[tt->visitingHero->subID]); | ||||
| 			graphics->heroWins[tt->visitingHero->subID] = infoWin(tt->visitingHero); | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
| 	updateInfo(obj); | ||||
|  | ||||
| 	bool wasGarrison = false; | ||||
| 	for(std::list<IShowActivable*>::iterator i = GH.listInt.begin(); i != GH.listInt.end(); i++) | ||||
| @@ -530,12 +479,10 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID, | ||||
| 	switch (buildingID) | ||||
| 	{ | ||||
| 	case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 15: | ||||
| 		{ | ||||
| 			SDL_FreeSurface(graphics->townWins[town->id]); | ||||
| 			graphics->townWins[town->id] = infoWin(town); | ||||
| 			break; | ||||
| 		} | ||||
| 		updateInfo(town); | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	if(!castleInt) | ||||
| 		return; | ||||
| 	if(castleInt->town!=town) | ||||
| @@ -983,7 +930,7 @@ void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const HeroB | ||||
| { | ||||
| 	if(bonus.type == HeroBonus::NONE)	return; | ||||
| 	boost::unique_lock<boost::recursive_mutex> un(*pim); | ||||
| 	redrawHeroWin(hero); | ||||
| 	updateInfo(hero); | ||||
| } | ||||
|  | ||||
| template <typename Handler> void CPlayerInterface::serializeTempl( Handler &h, const int version ) | ||||
| @@ -1004,72 +951,63 @@ void CPlayerInterface::serialize( CISer<CLoadFile> &h, const int version ) | ||||
| 	firstCall = -1; | ||||
| } | ||||
|  | ||||
| void CPlayerInterface::redrawHeroWin(const CGHeroInstance * hero) | ||||
| { | ||||
| 	if(!vstd::contains(graphics->heroWins,hero->subID)) | ||||
| 	{ | ||||
| 		tlog1 << "Cannot redraw infowindow for hero with subID=" << hero->subID << " - not present in our map\n"; | ||||
| 		return; | ||||
| 	} | ||||
| 	SDL_FreeSurface(graphics->heroWins[hero->subID]); | ||||
| 	graphics->heroWins[hero->subID] = infoWin(hero); | ||||
| 	if (adventureInt->selection == hero) | ||||
| 		adventureInt->infoBar.draw(screen); | ||||
| } | ||||
|  | ||||
| bool CPlayerInterface::moveHero( const CGHeroInstance *h, CGPath path ) | ||||
| { | ||||
| 	if (!h) | ||||
| 		return false; //can't find hero | ||||
|  | ||||
| 	pim->unlock(); | ||||
| 	bool result = false; | ||||
| 	path.convert(0); | ||||
| 	boost::unique_lock<boost::mutex> un(stillMoveHero.mx); | ||||
| 	stillMoveHero.data = CONTINUE_MOVE; | ||||
|  | ||||
| 	enum TerrainTile::EterrainType currentTerrain = TerrainTile::border; // not init yet | ||||
| 	enum TerrainTile::EterrainType newTerrain; | ||||
| 	int sh = -1; | ||||
|  | ||||
| 	for(int i=path.nodes.size()-1; i>0 && stillMoveHero.data == CONTINUE_MOVE; i--) | ||||
| 	{ | ||||
| 		//stop sending move requests if the next node can't be reached at the current turn (hero exhausted his move points) | ||||
| 		if(path.nodes[i-1].turns) | ||||
| 		{ | ||||
| 			stillMoveHero.data = STOP_MOVE; | ||||
| 			break; | ||||
| 		} | ||||
| 		// Start a new sound for the hero movement or let the existing one carry on. | ||||
| #if 0 | ||||
| 		// TODO | ||||
| 		if (hero is flying && sh == -1) | ||||
| 			sh = CGI->soundh->playSound(soundBase::horseFlying, -1); | ||||
| #endif | ||||
| 		{ | ||||
| 			newTerrain = cb->getTileInfo(CGHeroInstance::convertPosition(path.nodes[i].coord, false))->tertype; | ||||
| 		path.convert(0); | ||||
| 		boost::unique_lock<boost::mutex> un(stillMoveHero.mx); | ||||
| 		stillMoveHero.data = CONTINUE_MOVE; | ||||
|  | ||||
| 			if (newTerrain != currentTerrain) { | ||||
| 				CGI->soundh->stopSound(sh); | ||||
| 				sh = CGI->soundh->playSound(CGI->soundh->horseSounds[newTerrain], -1); | ||||
| 				currentTerrain = newTerrain; | ||||
| 		enum TerrainTile::EterrainType currentTerrain = TerrainTile::border; // not init yet | ||||
| 		enum TerrainTile::EterrainType newTerrain; | ||||
| 		int sh = -1; | ||||
|  | ||||
| 		for(int i=path.nodes.size()-1; i>0 && stillMoveHero.data == CONTINUE_MOVE; i--) | ||||
| 		{ | ||||
| 			//stop sending move requests if the next node can't be reached at the current turn (hero exhausted his move points) | ||||
| 			if(path.nodes[i-1].turns) | ||||
| 			{ | ||||
| 				stillMoveHero.data = STOP_MOVE; | ||||
| 				break; | ||||
| 			} | ||||
| 			// Start a new sound for the hero movement or let the existing one carry on. | ||||
| #if 0 | ||||
| 			// TODO | ||||
| 			if (hero is flying && sh == -1) | ||||
| 				sh = CGI->soundh->playSound(soundBase::horseFlying, -1); | ||||
| #endif | ||||
| 			{ | ||||
| 				newTerrain = cb->getTileInfo(CGHeroInstance::convertPosition(path.nodes[i].coord, false))->tertype; | ||||
|  | ||||
| 				if (newTerrain != currentTerrain) { | ||||
| 					CGI->soundh->stopSound(sh); | ||||
| 					sh = CGI->soundh->playSound(CGI->soundh->horseSounds[newTerrain], -1); | ||||
| 					currentTerrain = newTerrain; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			stillMoveHero.data = WAITING_MOVE; | ||||
|  | ||||
| 			int3 endpos(path.nodes[i-1].coord.x, path.nodes[i-1].coord.y, h->pos.z); | ||||
| 			cb->moveHero(h,endpos); | ||||
|  | ||||
| 			eventsM.unlock(); | ||||
| 			while(stillMoveHero.data != STOP_MOVE  &&  stillMoveHero.data != CONTINUE_MOVE) | ||||
| 				stillMoveHero.cond.wait(un); | ||||
| 			eventsM.lock(); | ||||
| 		} | ||||
|  | ||||
| 		stillMoveHero.data = WAITING_MOVE; | ||||
|  | ||||
| 		int3 endpos(path.nodes[i-1].coord.x, path.nodes[i-1].coord.y, h->pos.z); | ||||
| 		cb->moveHero(h,endpos); | ||||
|  | ||||
| 		eventsM.unlock(); | ||||
| 		while(stillMoveHero.data != STOP_MOVE  &&  stillMoveHero.data != CONTINUE_MOVE) | ||||
| 			stillMoveHero.cond.wait(un); | ||||
| 		eventsM.lock(); | ||||
| 		CGI->soundh->stopSound(sh); | ||||
| 		cb->recalculatePaths(); | ||||
| 	} | ||||
|  | ||||
| 	CGI->soundh->stopSound(sh); | ||||
|  | ||||
| 	//stillMoveHero = false; | ||||
| 	cb->recalculatePaths(); | ||||
| 	pim->lock(); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| @@ -1905,15 +1843,6 @@ void CPlayerInterface::acceptTurn() | ||||
| 		adventureInt->startTurn(); | ||||
|  | ||||
| 	boost::unique_lock<boost::recursive_mutex> un(*pim); | ||||
| 	for(std::map<int,SDL_Surface*>::iterator i=graphics->heroWins.begin(); i!=graphics->heroWins.end();i++) //redraw hero infoboxes | ||||
| 		SDL_FreeSurface(i->second); | ||||
| 	graphics->heroWins.clear(); | ||||
| 	std::vector <const CGHeroInstance *> hh = cb->getHeroesInfo(false); | ||||
| 	for(int i=0;i<hh.size();i++) | ||||
| 	{ | ||||
| 		SDL_Surface * pom = infoWin(hh[i]); | ||||
| 		graphics->heroWins.insert(std::pair<int,SDL_Surface*>(hh[i]->subID,pom)); | ||||
| 	} | ||||
|  | ||||
| 	/* TODO: This isn't quite right. First day in game should play | ||||
| 	 * NEWDAY. And we don't play NEWMONTH. */ | ||||
| @@ -1952,3 +1881,10 @@ void CPlayerInterface::tryDiggging(const CGHeroInstance *h) | ||||
| 			cb->dig(h); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CPlayerInterface::updateInfo(const CGObjectInstance * specific) | ||||
| { | ||||
| 	adventureInt->infoBar.updateSelection(specific); | ||||
| // 	if (adventureInt->selection == specific) | ||||
| // 		adventureInt->infoBar.showAll(screen); | ||||
| } | ||||
| @@ -207,6 +207,7 @@ public: | ||||
| 	void openTownWindow(const CGTownInstance * town); //shows townscreen | ||||
| 	void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero | ||||
| 	SDL_Surface * infoWin(const CGObjectInstance * specific); //specific=0 => draws info about selected town/hero | ||||
| 	void updateInfo(const CGObjectInstance * specific); | ||||
| 	void init(ICallback * CB); | ||||
| 	int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on | ||||
| 	void showInfoDialog(const std::string &text, const std::vector<SComponent*> & components = std::vector<SComponent*>(), int soundID = 0); | ||||
|   | ||||
| @@ -2467,9 +2467,7 @@ void CBonusSelection::CRegion::clickRight( tribool down, bool previousState ) | ||||
| 	if( down && !CSDL_Ext::isTransparent(graphics[0], GH.current->motion.x-pos.x, GH.current->motion.y-pos.y) && | ||||
| 		rclickText.size() ) | ||||
| 	{ | ||||
| 		CSimpleWindow * temp = CMessage::genWindow(rclickText, 0, true); | ||||
| 		CRClickPopupInt *rcpi = new CRClickPopupInt(temp, true); | ||||
| 		GH.pushInt(rcpi); | ||||
| 		CRClickPopup::createAndPush(rclickText); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -51,7 +51,7 @@ void SpellbookInteractiveArea::clickLeft(tribool down, bool previousState) | ||||
|  | ||||
| void SpellbookInteractiveArea::clickRight(tribool down, bool previousState) | ||||
| { | ||||
| 	adventureInt->handleRightClick(textOnRclick, down, this); | ||||
| 	adventureInt->handleRightClick(textOnRclick, down); | ||||
| } | ||||
|  | ||||
| void SpellbookInteractiveArea::hover(bool on) | ||||
| @@ -688,13 +688,14 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState) | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				using namespace Spells; | ||||
| 				int spell = mySpell; | ||||
| 				const CGHeroInstance *h = owner->myHero; | ||||
| 				owner->fexitb(); | ||||
|  | ||||
| 				switch(spell) | ||||
| 				{ | ||||
| 				case 0: //summon boat | ||||
| 				case SUMMON_BOAT: | ||||
| 					{ | ||||
| 						int3 pos = h->bestLocation(); | ||||
| 						if(pos.x < 0) | ||||
| @@ -703,6 +704,21 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState) | ||||
| 							return; | ||||
| 						} | ||||
| 					} | ||||
| 					break; | ||||
| 				case SCUTTLE_BOAT: | ||||
| 				case DIMENSION_DOOR: | ||||
| 					adventureInt->enterCastingMode(sp); | ||||
| 					return; | ||||
| 				case VISIONS: | ||||
| 				case VIEW_EARTH: | ||||
| 				case DISGUISE: | ||||
| 				case VIEW_AIR: | ||||
| 				case FLY: | ||||
| 				case WATER_WALK: | ||||
| 				case TOWN_PORTAL: | ||||
| 					break; | ||||
| 				default: | ||||
| 					assert(0); | ||||
| 				} | ||||
|  | ||||
| 				LOCPLINT->cb->castSpell(h, spell); | ||||
|   | ||||
| @@ -313,7 +313,10 @@ int CClient::getCurrentPlayer() | ||||
|  | ||||
| int CClient::getSelectedHero() | ||||
| { | ||||
| 	return IGameCallback::getSelectedHero(getCurrentPlayer())->id; | ||||
| 	if(const CGHeroInstance *selHero = IGameCallback::getSelectedHero(getCurrentPlayer())) | ||||
| 		return selHero->id; | ||||
| 	else | ||||
| 		return -1; | ||||
| } | ||||
|  | ||||
| void CClient::newGame( CConnection *con, StartInfo *si ) | ||||
|   | ||||
| @@ -71,6 +71,9 @@ struct Point | ||||
| 	Point(const int3 &a) | ||||
| 		:x(a.x),y(a.y) | ||||
| 	{} | ||||
| 	Point(const SDL_MouseMotionEvent &a) | ||||
| 		:x(a.x),y(a.y) | ||||
| 	{} | ||||
| 	 | ||||
| 	template<typename T> | ||||
| 	Point operator+(const T &b) const | ||||
| @@ -365,6 +368,8 @@ public: | ||||
| 	ui8 defActions; //which calls will be tried to be redirected to children | ||||
| 	ui8 recActions; //which calls we allow te receive from parent | ||||
|  | ||||
| 	enum EAlignment {TOPLEFT, CENTER, BOTTOMRIGHT}; | ||||
|  | ||||
| 	void disable(); //deactivates if needed, blocks all automatic activity, allows only disposal | ||||
| 	void enable(bool activation = true); //activates if needed, all activity enabled (Warning: may not be symetric with disable if recActions was limited!) | ||||
| 	void defActivate(); | ||||
|   | ||||
| @@ -770,21 +770,55 @@ void CRClickPopup::close() | ||||
| 	GH.popIntTotally(this); | ||||
| } | ||||
|  | ||||
| void CRClickPopup::createAndPush(const std::string &txt) | ||||
| { | ||||
| 	int player = LOCPLINT ? LOCPLINT->playerID : 1; //if no player, then use blue | ||||
| 	CSimpleWindow * temp = CMessage::genWindow(txt,player,true); | ||||
| 	CRClickPopupInt *rcpi = new CRClickPopupInt(temp,true); | ||||
| 	GH.pushInt(rcpi); | ||||
| } | ||||
|  | ||||
| void CRClickPopup::createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment /*= BOTTOMRIGHT*/) | ||||
| { | ||||
| 	SDL_Surface *iWin = LOCPLINT->infoWin(obj); //try get custom infowindow for this obj | ||||
| 	if(iWin) | ||||
| 		GH.pushInt(new CInfoPopup(iWin, p, alignment, true)); | ||||
| 	else | ||||
| 		CRClickPopup::createAndPush(obj->getHoverText()); | ||||
| } | ||||
|  | ||||
| CRClickPopup::CRClickPopup() | ||||
| { | ||||
| } | ||||
|  | ||||
| CRClickPopup::~CRClickPopup() | ||||
| { | ||||
| } | ||||
|  | ||||
| CInfoPopup::CInfoPopup(SDL_Surface * Bitmap, int x, int y, bool Free) | ||||
|  :free(Free),bitmap(Bitmap) | ||||
| { | ||||
| 	CGI->curh->hide(); | ||||
| 	init(x, y); | ||||
| } | ||||
|  | ||||
| 	pos.x = x; | ||||
| 	pos.y = y; | ||||
| 	pos.h = bitmap->h; | ||||
| 	pos.w = bitmap->w; | ||||
|  | ||||
| 	// Put the window back on screen if necessary | ||||
| 	amax(pos.x, 0); | ||||
| 	amax(pos.y, 0); | ||||
| 	amin(pos.x, conf.cc.resx - bitmap->w); | ||||
| 	amin(pos.y, conf.cc.resy - bitmap->h); | ||||
| CInfoPopup::CInfoPopup(SDL_Surface * Bitmap, const Point &p, EAlignment alignment, bool Free/*=false*/) | ||||
|  : free(Free),bitmap(Bitmap) | ||||
| { | ||||
| 	switch(alignment) | ||||
| 	{ | ||||
| 	case BOTTOMRIGHT: | ||||
| 		init(p.x - Bitmap->w, p.y - Bitmap->h); | ||||
| 		break; | ||||
| 	case CENTER: | ||||
| 		init(p.x - Bitmap->w/2, p.y - Bitmap->h/2); | ||||
| 		break; | ||||
| 	case TOPLEFT: | ||||
| 		init(p.x, p.y); | ||||
| 		break; | ||||
| 	default: | ||||
| 		assert(0); //not implemented | ||||
| 	} | ||||
| } | ||||
|  | ||||
| CInfoPopup::CInfoPopup(SDL_Surface *Bitmap, bool Free) | ||||
| @@ -818,6 +852,22 @@ CInfoPopup::~CInfoPopup() | ||||
| 	CGI->curh->show(); | ||||
| } | ||||
|  | ||||
| void CInfoPopup::init(int x, int y) | ||||
| { | ||||
| 	CGI->curh->hide(); | ||||
|  | ||||
| 	pos.x = x; | ||||
| 	pos.y = y; | ||||
| 	pos.h = bitmap->h; | ||||
| 	pos.w = bitmap->w; | ||||
|  | ||||
| 	// Put the window back on screen if necessary | ||||
| 	amax(pos.x, 0); | ||||
| 	amax(pos.y, 0); | ||||
| 	amin(pos.x, conf.cc.resx - bitmap->w); | ||||
| 	amin(pos.y, conf.cc.resy - bitmap->h); | ||||
| } | ||||
|  | ||||
| void SComponent::init(Etype Type, int Subtype, int Val) | ||||
| { | ||||
| 	std::ostringstream oss; | ||||
| @@ -961,7 +1011,7 @@ SDL_Surface * SComponent::getImg() | ||||
| void SComponent::clickRight(tribool down, bool previousState) | ||||
| { | ||||
| 	if(description.size()) | ||||
| 		adventureInt->handleRightClick(description,down,this); | ||||
| 		adventureInt->handleRightClick(description,down); | ||||
| } | ||||
| void SComponent::activate() | ||||
| { | ||||
| @@ -1277,7 +1327,7 @@ void CHeroList::select(int which) | ||||
| 		adventureInt->selection = NULL; | ||||
| 		adventureInt->terrain.currentPath = NULL; | ||||
| 		draw(screen); | ||||
| 		adventureInt->infoBar.draw(screen); | ||||
| 		adventureInt->infoBar.showAll(screen); | ||||
| 	} | ||||
| 	if (which>=LOCPLINT->wanderingHeroes.size()) | ||||
| 		return; | ||||
| @@ -1397,11 +1447,11 @@ void CHeroList::clickRight(tribool down, bool previousState) | ||||
| 		/***************************ARROWS*****************************************/ | ||||
| 		if(isItIn(&arrupp,GH.current->motion.x,GH.current->motion.y) && from>0) | ||||
| 		{ | ||||
| 			adventureInt->handleRightClick(CGI->generaltexth->zelp[303].second,down,this); | ||||
| 			adventureInt->handleRightClick(CGI->generaltexth->zelp[303].second,down); | ||||
| 		} | ||||
| 		else if(isItIn(&arrdop,GH.current->motion.x,GH.current->motion.y) && (LOCPLINT->wanderingHeroes.size()-from>5)) | ||||
| 		{ | ||||
| 			adventureInt->handleRightClick(CGI->generaltexth->zelp[304].second,down,this); | ||||
| 			adventureInt->handleRightClick(CGI->generaltexth->zelp[304].second,down); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| @@ -1413,21 +1463,11 @@ void CHeroList::clickRight(tribool down, bool previousState) | ||||
| 			if ((ny>SIZE || ny<0) || (from+ny>=LOCPLINT->wanderingHeroes.size())) | ||||
| 			{ | ||||
| 				return; | ||||
| 			} | ||||
| 			}			//show popup | ||||
|  | ||||
| 			//show popup | ||||
| 			CInfoPopup * ip = new CInfoPopup(graphics->heroWins[LOCPLINT->wanderingHeroes[from+ny]->subID], | ||||
| 				GH.current->motion.x-graphics->heroWins[LOCPLINT->wanderingHeroes[from+ny]->subID]->w, | ||||
| 				GH.current->motion.y-graphics->heroWins[LOCPLINT->wanderingHeroes[from+ny]->subID]->h, | ||||
| 				false); | ||||
| 			GH.pushInt(ip); | ||||
| 			CRClickPopup::createAndPush(LOCPLINT->wanderingHeroes[from+ny], GH.current->motion); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		adventureInt->handleRightClick(CGI->generaltexth->zelp[303].second,down,this); | ||||
| 		adventureInt->handleRightClick(CGI->generaltexth->zelp[304].second,down,this); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CHeroList::hover (bool on) | ||||
| @@ -1692,11 +1732,11 @@ void CTownList::clickRight(tribool down, bool previousState) | ||||
| 		/***************************ARROWS*****************************************/ | ||||
| 		if(isItIn(&arrupp,GH.current->motion.x,GH.current->motion.y) && from>0) | ||||
| 		{ | ||||
| 			adventureInt->handleRightClick(CGI->generaltexth->zelp[306].second,down,this); | ||||
| 			adventureInt->handleRightClick(CGI->generaltexth->zelp[306].second,down); | ||||
| 		} | ||||
| 		else if(isItIn(&arrdop,GH.current->motion.x,GH.current->motion.y) && (LOCPLINT->towns.size()-from>5)) | ||||
| 		{ | ||||
| 			adventureInt->handleRightClick(CGI->generaltexth->zelp[307].second,down,this); | ||||
| 			adventureInt->handleRightClick(CGI->generaltexth->zelp[307].second,down); | ||||
| 		} | ||||
| 		//if not buttons then towns | ||||
| 		int hx = GH.current->motion.x, hy = GH.current->motion.y; | ||||
| @@ -1709,17 +1749,7 @@ void CTownList::clickRight(tribool down, bool previousState) | ||||
| 		} | ||||
|  | ||||
| 		//show popup | ||||
| 		CInfoPopup * ip = new CInfoPopup( | ||||
| 			graphics->townWins[LOCPLINT->towns[from+ny]->id], | ||||
| 			GH.current->motion.x-graphics->townWins[LOCPLINT->towns[from+ny]->id]->w, | ||||
| 			GH.current->motion.y-graphics->townWins[LOCPLINT->towns[from+ny]->id]->h, | ||||
| 			false); | ||||
| 		GH.pushInt(ip); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 			adventureInt->handleRightClick(CGI->generaltexth->zelp[306].second,down,this); | ||||
| 			adventureInt->handleRightClick(CGI->generaltexth->zelp[307].second,down,this); | ||||
| 		CRClickPopup::createAndPush(LOCPLINT->towns[from+ny], GH.current->motion); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -3912,7 +3942,7 @@ void LRClickableAreaWText::clickLeft(tribool down, bool previousState) | ||||
| } | ||||
| void LRClickableAreaWText::clickRight(tribool down, bool previousState) | ||||
| { | ||||
| 	adventureInt->handleRightClick(text, down, this); | ||||
| 	adventureInt->handleRightClick(text, down); | ||||
| } | ||||
| void LRClickableAreaWText::activate() | ||||
| { | ||||
| @@ -3950,7 +3980,7 @@ void LRClickableAreaWTextComp::clickLeft(tribool down, bool previousState) | ||||
| } | ||||
| void LRClickableAreaWTextComp::clickRight(tribool down, bool previousState) | ||||
| { | ||||
| 	adventureInt->handleRightClick(text, down, this); | ||||
| 	adventureInt->handleRightClick(text, down); | ||||
| } | ||||
| void LRClickableAreaWTextComp::activate() | ||||
| { | ||||
|   | ||||
| @@ -63,6 +63,7 @@ class CArtifact; | ||||
| class CArtifactsOfHero; | ||||
| class CResDataBar; | ||||
| struct SPuzzleInfo; | ||||
| class CGGarrison; | ||||
|  | ||||
| extern SDL_Color tytulowy, tlo, zwykly ; | ||||
|  | ||||
| @@ -103,7 +104,12 @@ public: | ||||
| 	virtual void deactivate(); | ||||
| 	virtual void close(); | ||||
| 	void clickRight(tribool down, bool previousState); | ||||
| 	virtual ~CRClickPopup(){}; //d-tor | ||||
|  | ||||
| 	CRClickPopup(); | ||||
| 	virtual ~CRClickPopup(); //d-tor | ||||
|  | ||||
| 	static void createAndPush(const std::string &txt); | ||||
| 	static void createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment = BOTTOMRIGHT); | ||||
| }; | ||||
|  | ||||
| class CRClickPopupInt : public CRClickPopup //popup displayed on R-click | ||||
| @@ -125,7 +131,10 @@ public: | ||||
| 	void close(); | ||||
| 	void show(SDL_Surface * to); | ||||
| 	CInfoPopup(SDL_Surface * Bitmap, int x, int y, bool Free=false); //c-tor | ||||
| 	CInfoPopup(SDL_Surface * Bitmap, const Point &p, EAlignment alignment, bool Free=false); //c-tor | ||||
| 	CInfoPopup(SDL_Surface *Bitmap = NULL, bool Free = false); //default c-tor | ||||
|  | ||||
| 	void init(int x, int y); | ||||
| 	~CInfoPopup(); //d-tor | ||||
| }; | ||||
|  | ||||
| @@ -265,7 +274,7 @@ class CLabel | ||||
| 	: public virtual CIntObject | ||||
| { | ||||
| public: | ||||
| 	enum EAlignment {TOPLEFT, CENTER, BOTTOMRIGHT} alignment; | ||||
| 	EAlignment alignment; | ||||
| 	EFonts font; | ||||
| 	SDL_Color color; | ||||
| 	std::string text; | ||||
|   | ||||
| @@ -64,8 +64,6 @@ public: | ||||
| 	CDefEssential *luck22, *luck30, *luck42, *luck82, | ||||
| 		*morale22, *morale30, *morale42, *morale82, | ||||
| 		*halls, *forts, *bigTownPic; | ||||
| 	std::map<int,SDL_Surface*> heroWins; //hero_ID => infobox | ||||
| 	std::map<int,SDL_Surface*> townWins; //town_ID => infobox | ||||
| 	CDefEssential * artDefs; //artifacts | ||||
| 	std::vector<SDL_Surface *> portraitSmall; //48x32 px portraits of heroes | ||||
| 	std::vector<SDL_Surface *> portraitLarge; //58x64 px portraits of heroes | ||||
|   | ||||
| @@ -1013,11 +1013,13 @@ void CSDL_Ext::setPlayerColor(SDL_Surface * sur, unsigned char player) | ||||
| 		return; | ||||
| 	if(sur->format->BitsPerPixel==8) | ||||
| 	{ | ||||
| 		if(player != 255) | ||||
| 			*(sur->format->palette->colors+5) = graphics->playerColors[player]; | ||||
| 		else | ||||
| 			*(sur->format->palette->colors+5) = *graphics->neutralColor; | ||||
| 		SDL_Color *color = (player == 255  | ||||
| 							? graphics->neutralColor | ||||
| 							: &graphics->playerColors[player]); | ||||
| 		SDL_SetColors(sur, color, 5, 1); | ||||
| 	} | ||||
| 	else | ||||
| 		tlog3 << "Warning, setPlayerColor called on not 8bpp surface!\n"; | ||||
| } | ||||
| int readNormalNr (std::istream &in, int bytCon) | ||||
| { | ||||
|   | ||||
| @@ -23,6 +23,7 @@ | ||||
| #include "../lib/map.h" | ||||
| #include <sstream> | ||||
| #include <SDL_stdinc.h> | ||||
| #include <boost/foreach.hpp> | ||||
| using namespace boost::assign; | ||||
|  | ||||
| /* | ||||
| @@ -1238,7 +1239,7 @@ int CGHeroInstance::getBoatType() const | ||||
| 	case 2: | ||||
| 		return 2; | ||||
| 	default: | ||||
| 		assert(0); | ||||
| 		throw std::string("Wrong alignment!"); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -1254,6 +1255,17 @@ int CGHeroInstance::getSpellCost(const CSpell *sp) const | ||||
| 	return sp->costs[getSpellSchoolLevel(sp)]; | ||||
| } | ||||
|  | ||||
| int CGHeroInstance::getBonusesCount(int from, int id) const | ||||
| { | ||||
| 	int ret = 0; | ||||
|  | ||||
| 	BOOST_FOREACH(const HeroBonus &hb, bonuses) | ||||
| 		if(hb.source == from  &&  hb.id == id) | ||||
| 			ret++; | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| void CGDwelling::initObj() | ||||
| { | ||||
| 	switch(ID) | ||||
|   | ||||
| @@ -313,6 +313,7 @@ public: | ||||
|  | ||||
| 	const BonusList *ownerBonuses() const; | ||||
| 	const HeroBonus *getBonus(int from, int id) const; | ||||
| 	int getBonusesCount(int from, int id) const; | ||||
| 	int valOfBonuses(HeroBonus::BonusType type, int subtype = -1) const; //subtype -> subtype of bonus, if -1 then any | ||||
| 	bool hasBonusOfType(HeroBonus::BonusType type, int subtype = -1) const; //determines if hero has a bonus of given type (and optionally subtype) | ||||
| 	void getModifiersWDescr(std::vector<std::pair<int,std::string> > &out, HeroBonus::BonusType type, int subtype = -1) const; //out: pairs<modifier value, modifier description> | ||||
|   | ||||
| @@ -194,6 +194,15 @@ static bool startsWithX(const std::string &s) | ||||
| 	return s.size() && s[0] == 'x'; | ||||
| } | ||||
|  | ||||
| bool DLL_EXPORT isInScreenRange(const int3 ¢er, const int3 &pos) | ||||
| { | ||||
| 	int3 diff = pos - center; | ||||
| 	if(diff.x >= -9  &&  diff.x <= 9  &&  diff.y >= -8  &&  diff.y <= 8) | ||||
| 		return true; | ||||
| 	else | ||||
| 		return false; | ||||
| } | ||||
|  | ||||
| void CSpellHandler::loadSpells() | ||||
| { | ||||
| 	std::string buf = bitmaph->getTextFile("SPTRAITS.TXT"), pom; | ||||
|   | ||||
| @@ -51,6 +51,13 @@ public: | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| namespace Spells | ||||
| { | ||||
| 	enum {SUMMON_BOAT=0, SCUTTLE_BOAT, VISIONS, VIEW_EARTH, DISGUISE, VIEW_AIR, FLY, WATER_WALK, DIMENSION_DOOR, TOWN_PORTAL}; | ||||
| } | ||||
|  | ||||
| bool DLL_EXPORT isInScreenRange(const int3 ¢er, const int3 &pos); //for spells like Dimension Door | ||||
|  | ||||
| class DLL_EXPORT CSpellHandler | ||||
| { | ||||
| public: | ||||
|   | ||||
| @@ -1988,12 +1988,16 @@ bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath | ||||
| 		return false; | ||||
|  | ||||
| 	int3 hpos = hero->getPosition(false); | ||||
| 	tribool blockLandSea; //true - blocks sea, false - blocks land, indeterminate - allows all | ||||
|  | ||||
| 	if (!hero->canWalkOnSea()) | ||||
| 		blockLandSea = (map->getTile(hpos).tertype != TerrainTile::water); //block land if hero is on water and vice versa | ||||
| 	else | ||||
| 		blockLandSea = boost::logic::indeterminate; | ||||
| 	bool flying = false; //hero is under flying effect	TODO | ||||
| 	bool waterWalking = false; //hero is on land and can walk on water TODO | ||||
| 	bool onLand = map->getTile(hpos).tertype != TerrainTile::water; | ||||
| // 	tribool blockLandSea; //true - blocks sea, false - blocks land, indeterminate - allows all | ||||
| //  | ||||
| // 	if (!hero->canWalkOnSea()) | ||||
| // 		blockLandSea = (map->getTile(hpos).tertype != TerrainTile::water); //block land if hero is on water and vice versa | ||||
| // 	else | ||||
| // 		blockLandSea = boost::logic::indeterminate; | ||||
|  | ||||
| 	const std::vector<std::vector<std::vector<ui8> > > &FoW = getPlayer(hero->tempOwner)->fogOfWarMap; | ||||
|  | ||||
| @@ -2016,9 +2020,7 @@ bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath | ||||
| 			node.coord.y = j; | ||||
| 			node.coord.z = dest.z; | ||||
|  | ||||
| 			if ((tinfo->tertype == TerrainTile::rock) //it's rock | ||||
| 				|| ((blockLandSea) && (tinfo->tertype == TerrainTile::water)) //it's sea and we cannot walk on sea | ||||
| 				|| ((!blockLandSea) && (tinfo->tertype != TerrainTile::water)) //it's land and we cannot walk on land | ||||
| 			if(!tinfo->entrableTerrain(onLand, flying || waterWalking) | ||||
| 				|| !FoW[i][j][src.z] //tile is covered by the FoW | ||||
| 			) | ||||
| 			{ | ||||
| @@ -2039,7 +2041,7 @@ bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath | ||||
| 			d.accessible = true; //for allowing visiting objects | ||||
| 		} | ||||
|  | ||||
| 		if(blockLandSea && t->tertype == TerrainTile::water) //hero can walk only on land and dst lays on the water | ||||
| 		if(onLand && t->tertype == TerrainTile::water) //hero can walk only on land and dst lays on the water | ||||
| 		{ | ||||
| 			size_t i = 0; | ||||
| 			for(; i < t->visitableObjects.size(); i++) | ||||
| @@ -2048,7 +2050,7 @@ bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath | ||||
|  | ||||
| 			d.accessible = (i < t->visitableObjects.size()); //dest is accessible only if there is boat/hero | ||||
| 		} | ||||
| 		else if(!blockLandSea && t->tertype != TerrainTile::water) //hero is moving by water | ||||
| 		else if(!onLand && t->tertype != TerrainTile::water) //hero is moving by water | ||||
| 		{ | ||||
| 			d.accessible = (t->siodmyTajemniczyBajt & 64) && !t->blocked; //tile is accessible if it's coastal and not blocked | ||||
| 		} | ||||
|   | ||||
| @@ -56,7 +56,7 @@ struct DLL_EXPORT HeroBonus | ||||
| 		FREE_SHIP_BOARDING //movement points preserved with ship boarding and landing | ||||
| 	}; | ||||
| 	enum BonusDuration{PERMANENT, ONE_BATTLE, ONE_DAY, ONE_WEEK}; | ||||
| 	enum BonusSource{ARTIFACT, OBJECT}; | ||||
| 	enum BonusSource{ARTIFACT, OBJECT, CASTED_SPELL}; | ||||
|  | ||||
| 	ui8 duration; //uses BonusDuration values | ||||
| 	ui8 type; //uses BonusType values - says to what is this bonus | ||||
|   | ||||
| @@ -476,7 +476,7 @@ struct TryMoveHero : public CPackForClient //501 | ||||
|  | ||||
| 	ui32 id, movePoints; | ||||
| 	ui8 result; //uses EResult | ||||
| 	int3 start, end; | ||||
| 	int3 start, end; //h3m format | ||||
| 	std::set<int3> fowRevealed; //revealed tiles | ||||
|  | ||||
| 	bool humanKnows; //used locally during applying to client | ||||
|   | ||||
							
								
								
									
										16
									
								
								lib/map.cpp
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								lib/map.cpp
									
									
									
									
									
								
							| @@ -2129,3 +2129,19 @@ CVictoryCondition::CVictoryCondition() | ||||
| 	obj = NULL; | ||||
| 	ID = allowNormalVictory = appliesToAI = count = 0; | ||||
| } | ||||
|  | ||||
| bool TerrainTile::entrableTerrain(const TerrainTile *from /*= NULL*/) const | ||||
| { | ||||
| 	return entrableTerrain(from ? from->tertype != water : true, from ? from->tertype == water : true); | ||||
| } | ||||
|  | ||||
| bool TerrainTile::entrableTerrain(bool allowLand, bool allowSea) const | ||||
| { | ||||
| 	return tertype != rock  | ||||
| 		&& (allowSea && tertype == water   ||   allowLand && tertype != water); | ||||
| } | ||||
|  | ||||
| bool TerrainTile::isClear(const TerrainTile *from /*= NULL*/) const | ||||
| { | ||||
| 	return entrableTerrain(from) && !blocked; | ||||
| } | ||||
| @@ -95,6 +95,10 @@ struct DLL_EXPORT TerrainTile | ||||
| 			//these flags (and obj vectors) will be restored in map serialization | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	bool entrableTerrain(const TerrainTile *from = NULL) const; //checks if terrain is not a rock. If from is water/land, same type is also required.  | ||||
| 	bool entrableTerrain(bool allowLand, bool allowSea) const; //checks if terrain is not a rock. If from is water/land, same type is also required.  | ||||
| 	bool isClear(const TerrainTile *from = NULL) const; //checks for blocking objs and terraint type (water / land) | ||||
| }; | ||||
| struct DLL_EXPORT SheroName //name of starting hero | ||||
| { | ||||
|   | ||||
| @@ -4213,9 +4213,10 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &p | ||||
| 	if(s->combatSpell) | ||||
| 		COMPLAIN_RET("This function can be used only for adventure map spells!"); | ||||
|  | ||||
| 	using namespace Spells; | ||||
| 	switch(spellID) | ||||
| 	{ | ||||
| 	case 0: //Summon Boat  | ||||
| 	case SUMMON_BOAT: //Summon Boat  | ||||
| 		{ | ||||
| 			//check if spell works at all | ||||
| 			if(rand() % 100 >= s->powers[schoolLevel]) //power is % chance of success | ||||
| @@ -4277,15 +4278,79 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &p | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 	case 1: //Scuttle Boat  | ||||
| 	case 2: //Visions  | ||||
| 	case 3: //View Earth  | ||||
| 	case 4: //Disguise  | ||||
| 	case 5: //View Air  | ||||
| 	case 6: //Fly  | ||||
| 	case 7: //Water Walk  | ||||
| 	case 8: //Dimension Door | ||||
| 	case 9: //Town Portal  | ||||
| 	case SCUTTLE_BOAT: //Scuttle Boat  | ||||
| 		{ | ||||
| 			//check if spell works at all | ||||
| 			if(rand() % 100 >= s->powers[schoolLevel]) //power is % chance of success | ||||
| 			{ | ||||
| 				InfoWindow iw; | ||||
| 				iw.player = h->tempOwner; | ||||
| 				iw.text.addTxt(MetaString::GENERAL_TXT, 337); //%s tried to scuttle the boat, but failed | ||||
| 				iw.text.addReplacement(h->name); | ||||
| 				sendAndApply(&iw); | ||||
| 				return true; //TODO? or should it be false? request was correct and realized, but spell failed... | ||||
| 			} | ||||
|  | ||||
| 			//TODO: test range, visibility | ||||
| 			const TerrainTile *t = &gs->map->getTile(pos); | ||||
| 			if(!t->visitableObjects.size() || t->visitableObjects.back()->ID != 8) | ||||
| 				COMPLAIN_RET("There is no boat to scuttle!"); | ||||
|  | ||||
| 			RemoveObject ro; | ||||
| 			ro.id = t->visitableObjects.back()->id; | ||||
| 			sendAndApply(&ro); | ||||
| 			break; | ||||
| 		} | ||||
| 	case DIMENSION_DOOR: //Dimension Door | ||||
| 		{ | ||||
| 			const TerrainTile *dest = getTile(pos); | ||||
| 			const TerrainTile *curr = getTile(h->getSightCenter()); | ||||
|  | ||||
| 			if(!dest) | ||||
| 				COMPLAIN_RET("Destination tile doesn't exist!"); | ||||
| 			if(!h->movement) | ||||
| 				COMPLAIN_RET("Hero needs movement points to cast Dimension Door!"); | ||||
| 			if(h->getBonusesCount(HeroBonus::CASTED_SPELL, Spells::DIMENSION_DOOR) >= s->powers[schoolLevel]) //limit casts per turn | ||||
| 			{ | ||||
| 				InfoWindow iw; | ||||
| 				iw.player = h->tempOwner; | ||||
| 				iw.text.addTxt(MetaString::GENERAL_TXT, 338); //%s is not skilled enough to cast this spell again today. | ||||
| 				iw.text.addReplacement(h->name); | ||||
| 				sendAndApply(&iw); | ||||
| 				break; | ||||
| 			} | ||||
|  | ||||
| 			GiveBonus gb; | ||||
| 			gb.id = h->id; | ||||
| 			gb.bonus = HeroBonus(HeroBonus::ONE_DAY, HeroBonus::NONE, HeroBonus::CASTED_SPELL, 0, Spells::DIMENSION_DOOR); | ||||
| 			sendAndApply(&gb); | ||||
| 			 | ||||
| 			if(!dest->isClear(curr)) //wrong dest tile | ||||
| 			{ | ||||
| 				InfoWindow iw; | ||||
| 				iw.player = h->tempOwner; | ||||
| 				iw.text.addTxt(MetaString::GENERAL_TXT, 70); //Dimension Door failed! | ||||
| 				sendAndApply(&iw); | ||||
| 				break; | ||||
| 			} | ||||
|  | ||||
| 			TryMoveHero tmh; | ||||
| 			tmh.id = h->id; | ||||
| 			tmh.movePoints = std::max<int>(0, h->movement - 300); | ||||
| 			tmh.result = TryMoveHero::TELEPORTATION; | ||||
| 			tmh.start = h->pos; | ||||
| 			tmh.end = pos; | ||||
| 			getTilesInRange(tmh.fowRevealed, pos, h->getSightRadious(), h->tempOwner,1); | ||||
| 			sendAndApply(&tmh); | ||||
| 		} | ||||
| 		break; | ||||
| 	case VISIONS: //Visions  | ||||
| 	case VIEW_EARTH: //View Earth  | ||||
| 	case DISGUISE: //Disguise  | ||||
| 	case VIEW_AIR: //View Air  | ||||
| 	case FLY: //Fly  | ||||
| 	case WATER_WALK: //Water Walk  | ||||
| 	case TOWN_PORTAL: //Town Portal  | ||||
| 	default: | ||||
| 		COMPLAIN_RET("This spell is not implemented yet!"); | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user