mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Rewrote hero moving code. Seems to be working.
This commit is contained in:
		
							
								
								
									
										337
									
								
								CCallback.cpp
									
									
									
									
									
								
							
							
						
						
									
										337
									
								
								CCallback.cpp
									
									
									
									
									
								
							| @@ -17,8 +17,16 @@ | ||||
| #include "lib/Connection.h" | ||||
| #include "client/Client.h" | ||||
| #include <boost/thread.hpp> | ||||
| #include <boost/foreach.hpp> | ||||
| #include "lib/NetPacks.h" | ||||
| //LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); | ||||
| extern CSharedCond<std::set<IPack*> > mess; | ||||
|  | ||||
| HeroMoveDetails::HeroMoveDetails(int3 Src, int3 Dst, CGHeroInstance*Ho) | ||||
| 	:src(Src),dst(Dst),ho(Ho) | ||||
| { | ||||
| 	owner = ho->getOwner(); | ||||
| }; | ||||
| bool CCallback::moveHero(int ID, CPath * path, int idtype, int pathType) | ||||
| { | ||||
| 	CGHeroInstance * hero = NULL; | ||||
| @@ -69,120 +77,123 @@ bool CCallback::moveHero(int ID, CPath * path, int idtype, int pathType) | ||||
| 		return false; | ||||
| 	for(int i=ourPath->nodes.size()-1; i>0; i--) | ||||
| 	{ | ||||
| 		int3 stpos, endpos; | ||||
| 		stpos = int3(ourPath->nodes[i].coord.x, ourPath->nodes[i].coord.y, hero->pos.z); | ||||
| 		endpos = int3(ourPath->nodes[i-1].coord.x, ourPath->nodes[i-1].coord.y, hero->pos.z); | ||||
| 		HeroMoveDetails curd; | ||||
| 		curd.src = stpos; | ||||
| 		curd.dst = endpos; | ||||
| 		curd.ho = hero; | ||||
| 		curd.owner = hero->getOwner(); | ||||
| 		/*if(player!=-1) | ||||
| 		{ | ||||
| 			hero->pos = endpos; | ||||
| 		}*/ | ||||
| 		if(hero->movement >= (ourPath->nodes.size()>=2 ?  (*(ourPath->nodes.end()-2)).dist : 0) - ourPath->nodes[i].dist  || player==-1) | ||||
| 		{ //performing move | ||||
| 			hero->movement -= (ourPath->nodes.size()>=2 ?  (*(ourPath->nodes.end()-2)).dist : 0) - ourPath->nodes[i].dist; | ||||
| 			ourPath->nodes.pop_back(); | ||||
| 			 | ||||
| 			std::vector< CGObjectInstance * > vis = CGI->mh->getVisitableObjs(CGHeroInstance::convertPosition(curd.dst,false)); | ||||
| 			bool blockvis = false; | ||||
| 			for (int pit = 0; pit<vis.size();pit++) | ||||
| 				if (vis[pit]->blockVisit) | ||||
| 					blockvis = true; | ||||
| 		int3 stpos(ourPath->nodes[i].coord.x, ourPath->nodes[i].coord.y, hero->pos.z),  | ||||
| 			endpos(ourPath->nodes[i-1].coord.x, ourPath->nodes[i-1].coord.y, hero->pos.z); | ||||
| 		HeroMoveDetails curd(stpos,endpos,hero); | ||||
|  | ||||
| 			if (!blockvis) | ||||
| 			{ | ||||
| 				curd.successful = true; | ||||
| 				hero->pos = curd.dst; | ||||
|  | ||||
| 				//inform leaved objects | ||||
| 				std::vector< CGObjectInstance * > leave = CGI->mh->getVisitableObjs(CGHeroInstance::convertPosition(curd.src,false)); | ||||
| 				for (int iii=0; iii<leave.size(); iii++) //if object is visitable we call onHeroVisit | ||||
| 				{ | ||||
| 					//TODO: allow to handle this in LUA | ||||
| 					if(leave[iii]->state) //hard-coded function | ||||
| 						leave[iii]->state->onHeroLeave(leave[iii],curd.ho->subID); | ||||
| 				} | ||||
|  | ||||
|  | ||||
| 				//reveal fog of war | ||||
| 				int heroSight = hero->getSightDistance(); | ||||
| 				int xbeg = stpos.x - heroSight - 2; | ||||
| 				if(xbeg < 0) | ||||
| 					xbeg = 0; | ||||
| 				int xend = stpos.x + heroSight + 2; | ||||
| 				if(xend >= CGI->mh->map->width) | ||||
| 					xend = CGI->mh->map->width; | ||||
| 				int ybeg = stpos.y - heroSight - 2; | ||||
| 				if(ybeg < 0) | ||||
| 					ybeg = 0; | ||||
| 				int yend = stpos.y + heroSight + 2; | ||||
| 				if(yend >= CGI->mh->map->height) | ||||
| 					yend = CGI->mh->map->height; | ||||
| 				for(int xd=xbeg; xd<xend; ++xd) //revealing part of map around heroes | ||||
| 				{ | ||||
| 					for(int yd=ybeg; yd<yend; ++yd) | ||||
| 					{ | ||||
| 						int deltaX = (hero->getPosition(false).x-xd)*(hero->getPosition(false).x-xd); | ||||
| 						int deltaY = (hero->getPosition(false).y-yd)*(hero->getPosition(false).y-yd); | ||||
| 						if(deltaX+deltaY<hero->getSightDistance()*hero->getSightDistance()) | ||||
| 						{ | ||||
| 							if(gs->players[player].fogOfWarMap[xd][yd][hero->getPosition(false).z] == 0) | ||||
| 							{ | ||||
| 								CGI->playerint[gs->players[player].serial]->tileRevealed(int3(xd, yd, hero->getPosition(false).z)); | ||||
| 							} | ||||
| 							gs->players[player].fogOfWarMap[xd][yd][hero->getPosition(false).z] = 1; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
|  | ||||
| 				//notify interfacesabout move | ||||
| 				int nn=0; //number of interfece of currently browsed player | ||||
| 				for(std::map<ui8, PlayerState>::iterator j=CGI->state->players.begin(); j!=CGI->state->players.end(); ++j)//CGI->state->players.size(); ++j) //for testing | ||||
| 				{ | ||||
| 					if (j->first > PLAYER_LIMIT) | ||||
| 						break; | ||||
| 					if(j->second.fogOfWarMap[stpos.x-1][stpos.y][stpos.z] || j->second.fogOfWarMap[endpos.x-1][endpos.y][endpos.z]) | ||||
| 					{ //player should be notified | ||||
| 						CGI->playerint[j->second.serial]->heroMoved(curd); | ||||
| 					} | ||||
| 					++nn; | ||||
| 				} | ||||
|  | ||||
|  | ||||
| 				//call objects if they arevisited | ||||
| 				for (int iii=0; iii<vis.size(); iii++) //if object is visitable we call onHeroVisit | ||||
| 				{ | ||||
| 					if(gs->checkFunc(vis[iii]->ID,"heroVisit")) //script function | ||||
| 						gs->objscr[vis[iii]->ID]["heroVisit"]->onHeroVisit(vis[iii],curd.ho->subID); | ||||
| 					if(vis[iii]->state) //hard-coded function | ||||
| 						vis[iii]->state->onHeroVisit(vis[iii],curd.ho->subID); | ||||
| 				} | ||||
| 			} | ||||
| 			else //interaction with blocking object (like resources) | ||||
| 			{ | ||||
| 				curd.successful = false; | ||||
| 				CGI->playerint[gs->players[hero->getOwner()].serial]->heroMoved(curd); | ||||
| 				for (int iii=0; iii<vis.size(); iii++) //if object is visitable we call onHeroVisit | ||||
| 				{ | ||||
| 					if (vis[iii]->blockVisit) | ||||
| 					{ | ||||
| 						if(gs->checkFunc(vis[iii]->ID,"heroVisit")) //script function | ||||
| 							gs->objscr[vis[iii]->ID]["heroVisit"]->onHeroVisit(vis[iii],curd.ho->subID); | ||||
| 						if(vis[iii]->state) //hard-coded function | ||||
| 							vis[iii]->state->onHeroVisit(vis[iii],curd.ho->subID); | ||||
| 					} | ||||
| 				} | ||||
| 		*cl->serv << ui16(501) << hero->id << stpos << endpos; | ||||
| 		{//wait till there is server answer | ||||
| 			boost::unique_lock<boost::mutex> lock(*mess.mx); | ||||
| 			while(std::find_if(mess.res->begin(),mess.res->end(),IPack::isType<501>) == mess.res->end()) | ||||
| 				mess.cv->wait(lock); | ||||
| 			std::set<IPack*>::iterator itr = std::find_if(mess.res->begin(),mess.res->end(),IPack::isType<501>); | ||||
| 			TryMoveHero tmh = *static_cast<TryMoveHero*>(*itr); | ||||
| 			mess.res->erase(itr); | ||||
| 			if(!tmh.result) | ||||
| 				return false; | ||||
| 			} | ||||
|  | ||||
| 		} | ||||
| 		else | ||||
| 			return true; //move ended - no more movement points | ||||
| 	} | ||||
|  | ||||
| 	//	if(hero->movement >= (ourPath->nodes.size()>=2 ?  (*(ourPath->nodes.end()-2)).dist : 0) - ourPath->nodes[i].dist  || player==-1) | ||||
| 	//	{ //performing move | ||||
| 	//		hero->movement -= (ourPath->nodes.size()>=2 ?  (*(ourPath->nodes.end()-2)).dist : 0) - ourPath->nodes[i].dist; | ||||
| 	//		ourPath->nodes.pop_back(); | ||||
| 	//		 | ||||
| 	//		std::vector< CGObjectInstance * > vis = CGI->mh->getVisitableObjs(CGHeroInstance::convertPosition(curd.dst,false)); | ||||
| 	//		bool blockvis = false; | ||||
| 	//		for (int pit = 0; pit<vis.size();pit++) | ||||
| 	//			if (vis[pit]->blockVisit) | ||||
| 	//				blockvis = true; | ||||
|  | ||||
| 	//		if (!blockvis) | ||||
| 	//		{ | ||||
| 	//			curd.successful = true; | ||||
| 	//			hero->pos = curd.dst; | ||||
|  | ||||
| 	//			//inform leaved objects | ||||
| 	//			std::vector< CGObjectInstance * > leave = CGI->mh->getVisitableObjs(CGHeroInstance::convertPosition(curd.src,false)); | ||||
| 	//			for (int iii=0; iii<leave.size(); iii++) //if object is visitable we call onHeroVisit | ||||
| 	//			{ | ||||
| 	//				//TODO: allow to handle this in LUA | ||||
| 	//				if(leave[iii]->state) //hard-coded function | ||||
| 	//					leave[iii]->state->onHeroLeave(leave[iii],curd.ho->subID); | ||||
| 	//			} | ||||
|  | ||||
|  | ||||
| 	//			//reveal fog of war | ||||
| 	//			int heroSight = hero->getSightDistance(); | ||||
| 	//			int xbeg = stpos.x - heroSight - 2; | ||||
| 	//			if(xbeg < 0) | ||||
| 	//				xbeg = 0; | ||||
| 	//			int xend = stpos.x + heroSight + 2; | ||||
| 	//			if(xend >= CGI->mh->map->width) | ||||
| 	//				xend = CGI->mh->map->width; | ||||
| 	//			int ybeg = stpos.y - heroSight - 2; | ||||
| 	//			if(ybeg < 0) | ||||
| 	//				ybeg = 0; | ||||
| 	//			int yend = stpos.y + heroSight + 2; | ||||
| 	//			if(yend >= CGI->mh->map->height) | ||||
| 	//				yend = CGI->mh->map->height; | ||||
| 	//			for(int xd=xbeg; xd<xend; ++xd) //revealing part of map around heroes | ||||
| 	//			{ | ||||
| 	//				for(int yd=ybeg; yd<yend; ++yd) | ||||
| 	//				{ | ||||
| 	//					int deltaX = (hero->getPosition(false).x-xd)*(hero->getPosition(false).x-xd); | ||||
| 	//					int deltaY = (hero->getPosition(false).y-yd)*(hero->getPosition(false).y-yd); | ||||
| 	//					if(deltaX+deltaY<hero->getSightDistance()*hero->getSightDistance()) | ||||
| 	//					{ | ||||
| 	//						if(gs->players[player].fogOfWarMap[xd][yd][hero->getPosition(false).z] == 0) | ||||
| 	//						{ | ||||
| 	//							cl->playerint[player]->tileRevealed(int3(xd, yd, hero->getPosition(false).z)); | ||||
| 	//						} | ||||
| 	//						gs->players[player].fogOfWarMap[xd][yd][hero->getPosition(false).z] = 1; | ||||
| 	//					} | ||||
| 	//				} | ||||
| 	//			} | ||||
|  | ||||
|  | ||||
| 	//			//notify interfacesabout move | ||||
| 	//			int nn=0; //number of interfece of currently browsed player | ||||
| 	//			for(std::map<ui8, PlayerState>::iterator j=CGI->state->players.begin(); j!=CGI->state->players.end(); ++j)//CGI->state->players.size(); ++j) //for testing | ||||
| 	//			{ | ||||
| 	//				if (j->first > PLAYER_LIMIT) | ||||
| 	//					break; | ||||
| 	//				if(j->second.fogOfWarMap[stpos.x-1][stpos.y][stpos.z] || j->second.fogOfWarMap[endpos.x-1][endpos.y][endpos.z]) | ||||
| 	//				{ //player should be notified | ||||
| 	//					cl->playerint[j->second.color]->heroMoved(curd); | ||||
| 	//				} | ||||
| 	//				++nn; | ||||
| 	//			} | ||||
|  | ||||
|  | ||||
| 	//			//call objects if they arevisited | ||||
| 	//			for (int iii=0; iii<vis.size(); iii++) //if object is visitable we call onHeroVisit | ||||
| 	//			{ | ||||
| 	//				if(gs->checkFunc(vis[iii]->ID,"heroVisit")) //script function | ||||
| 	//					gs->objscr[vis[iii]->ID]["heroVisit"]->onHeroVisit(vis[iii],curd.ho->subID); | ||||
| 	//				if(vis[iii]->state) //hard-coded function | ||||
| 	//					vis[iii]->state->onHeroVisit(vis[iii],curd.ho->subID); | ||||
| 	//			} | ||||
| 	//		} | ||||
| 	//		else //interaction with blocking object (like resources) | ||||
| 	//		{ | ||||
| 	//			curd.successful = false; | ||||
| 	//			cl->playerint[gs->players[hero->getOwner()].color]->heroMoved(curd); | ||||
| 	//			for (int iii=0; iii<vis.size(); iii++) //if object is visitable we call onHeroVisit | ||||
| 	//			{ | ||||
| 	//				if (vis[iii]->blockVisit) | ||||
| 	//				{ | ||||
| 	//					if(gs->checkFunc(vis[iii]->ID,"heroVisit")) //script function | ||||
| 	//						gs->objscr[vis[iii]->ID]["heroVisit"]->onHeroVisit(vis[iii],curd.ho->subID); | ||||
| 	//					if(vis[iii]->state) //hard-coded function | ||||
| 	//						vis[iii]->state->onHeroVisit(vis[iii],curd.ho->subID); | ||||
| 	//				} | ||||
| 	//			} | ||||
| 	//			return false; | ||||
| 	//		} | ||||
|  | ||||
| 	//	} | ||||
| 	//} | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| @@ -254,7 +265,7 @@ void CCallback::recruitCreatures(const CGObjectInstance *obj, int ID, int amount | ||||
| 			t->army.slots[slot].first = &CGI->creh->creatures[ID]; | ||||
| 			t->army.slots[slot].second = amount; | ||||
| 		} | ||||
| 		CGI->playerint[gs->players[player].serial]->garrisonChanged(obj); | ||||
| 		cl->playerint[player]->garrisonChanged(obj); | ||||
|  | ||||
| 	} | ||||
| 	//TODO: recruit from dwellings on the adventure map | ||||
| @@ -267,7 +278,7 @@ bool CCallback::dismissCreature(const CArmedInstance *obj, int stackPos) | ||||
| 		return false; | ||||
| 	CArmedInstance *ob = const_cast<CArmedInstance*>(obj); | ||||
| 	ob->army.slots.erase(stackPos); | ||||
| 	CGI->playerint[gs->players[player].serial]->garrisonChanged(obj); | ||||
| 	cl->playerint[player]->garrisonChanged(obj); | ||||
| 	return true; | ||||
| } | ||||
| bool CCallback::upgradeCreature(const CArmedInstance *obj, int stackPos, int newID) | ||||
| @@ -515,27 +526,9 @@ int CCallback::swapCreatures(const CGObjectInstance *s1, const CGObjectInstance | ||||
| 		S2->slots.erase(p2); | ||||
|  | ||||
| 	if(s1->tempOwner<PLAYER_LIMIT) | ||||
| 	{ | ||||
| 		for(int b=0; b<CGI->playerint.size(); ++b) | ||||
| 		{ | ||||
| 			if(CGI->playerint[b]->playerID == s1->tempOwner) | ||||
| 			{ | ||||
| 				CGI->playerint[b]->garrisonChanged(s1); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 		cl->playerint[s1->tempOwner]->garrisonChanged(s1); | ||||
| 	if((s2->tempOwner<PLAYER_LIMIT) && (s2 != s1)) | ||||
| 	{ | ||||
| 		for(int b=0; b<CGI->playerint.size(); ++b) | ||||
| 		{ | ||||
| 			if(CGI->playerint[b]->playerID == s2->tempOwner) | ||||
| 			{ | ||||
| 				CGI->playerint[b]->garrisonChanged(s2); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 		cl->playerint[s2->tempOwner]->garrisonChanged(s2); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -555,27 +548,10 @@ int CCallback::mergeStacks(const CGObjectInstance *s1, const CGObjectInstance *s | ||||
| 	S1->slots.erase(p1); | ||||
|  | ||||
| 	if(s1->tempOwner<PLAYER_LIMIT) | ||||
| 	{ | ||||
| 		for(int b=0; b<CGI->playerint.size(); ++b) | ||||
| 		{ | ||||
| 			if(CGI->playerint[b]->playerID == s1->tempOwner) | ||||
| 			{ | ||||
| 				CGI->playerint[b]->garrisonChanged(s1); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 		cl->playerint[s1->tempOwner]->garrisonChanged(s1); | ||||
|  | ||||
| 	if((s2->tempOwner<PLAYER_LIMIT) && (s2 != s1)) | ||||
| 	{ | ||||
| 		for(int b=0; b<CGI->playerint.size(); ++b) | ||||
| 		{ | ||||
| 			if(CGI->playerint[b]->playerID == s2->tempOwner) | ||||
| 			{ | ||||
| 				CGI->playerint[b]->garrisonChanged(s2); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 		cl->playerint[s2->tempOwner]->garrisonChanged(s2); | ||||
| 	return 0; | ||||
| } | ||||
| int CCallback::splitStack(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2, int val) | ||||
| @@ -597,25 +573,11 @@ int CCallback::splitStack(const CGObjectInstance *s1, const CGObjectInstance *s2 | ||||
|  | ||||
| 	if(s1->tempOwner<PLAYER_LIMIT) | ||||
| 	{ | ||||
| 		for(int b=0; b<CGI->playerint.size(); ++b) | ||||
| 		{ | ||||
| 			if(CGI->playerint[b]->playerID == s1->tempOwner) | ||||
| 			{ | ||||
| 				CGI->playerint[b]->garrisonChanged(s1); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		cl->playerint[s1->tempOwner]->garrisonChanged(s1); | ||||
| 	} | ||||
| 	if((s2->tempOwner<PLAYER_LIMIT) && (s2 != s1)) | ||||
| 	{ | ||||
| 		for(int b=0; b<CGI->playerint.size(); ++b) | ||||
| 		{ | ||||
| 			if(CGI->playerint[b]->playerID == s2->tempOwner) | ||||
| 			{ | ||||
| 				CGI->playerint[b]->garrisonChanged(s2); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		cl->playerint[s2->tempOwner]->garrisonChanged(s2); | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| @@ -686,7 +648,7 @@ bool CCallback::buildBuilding(const CGTownInstance *town, int buildingID) | ||||
| 	for(int i=0;i<7;i++) | ||||
| 		gs->players[player].resources[i]-=b->resources[i]; | ||||
| 	t->builded++; | ||||
| 	CGI->playerint[CGI->state->players[player].serial]->buildChanged(town,buildingID,1); | ||||
| 	cl->playerint[player]->buildChanged(town,buildingID,1); | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| @@ -782,18 +744,11 @@ int3 CScriptCallback::getPos(CGObjectInstance * ob) | ||||
| } | ||||
| void CScriptCallback::changePrimSkill(int ID, int which, int val) | ||||
| {	 | ||||
| 	CGHeroInstance * hero = CGI->state->map->getHero(ID,0); | ||||
| 	CGHeroInstance * hero = gs->map->getHero(ID,0); | ||||
| 	if (which<PRIMARY_SKILLS) | ||||
| 	{ | ||||
| 		hero->primSkills[which]+=val; | ||||
| 		for (int i=0; i<CGI->playerint.size(); i++) | ||||
| 		{ | ||||
| 			if (CGI->playerint[i]->playerID == hero->getOwner()) | ||||
| 			{ | ||||
| 				CGI->playerint[i]->heroPrimarySkillChanged(hero, which, val); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		cl->playerint[hero->getOwner()]->heroPrimarySkillChanged(hero, which, val); | ||||
| 	} | ||||
| 	else if (which==4) | ||||
| 	{ | ||||
| @@ -830,24 +785,25 @@ void CScriptCallback::showInfoDialog(int player, std::string text, std::vector<S | ||||
| 	//TODO: upewniac sie ze mozemy to zrzutowac (przy customowych interfejsach cos moze sie kopnac) | ||||
| 	if (player>=0) | ||||
| 	{ | ||||
| 		CGameInterface * temp = CGI->playerint[CGI->state->players[player].serial]; | ||||
| 		CGameInterface * temp = cl->playerint[player]; | ||||
| 		if (temp->human) | ||||
| 			((CPlayerInterface*)(temp))->showInfoDialog(text,*components); | ||||
| 		return; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		for (int i=0; i<CGI->playerint.size();i++) | ||||
| 		typedef std::pair<const ui8, CGameInterface*> intf; | ||||
| 		BOOST_FOREACH(intf & i, cl->playerint) | ||||
| 		{ | ||||
| 			if (CGI->playerint[i]->human) | ||||
| 				((CPlayerInterface*)(CGI->playerint[i]))->showInfoDialog(text,*components); | ||||
| 			if (i.second->human) | ||||
| 				((CPlayerInterface*)(i.second))->showInfoDialog(text,*components); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CScriptCallback::showSelDialog(int player, std::string text, std::vector<CSelectableComponent*>*components, IChosen * asker) | ||||
| { | ||||
| 	CGameInterface * temp = CGI->playerint[CGI->state->players[player].serial]; | ||||
| 	CGameInterface * temp = cl->playerint[player]; | ||||
| 	if (temp->human) | ||||
| 		((CPlayerInterface*)(temp))->showSelDialog(text,*components,(int)asker); | ||||
| 	return; | ||||
| @@ -891,11 +847,11 @@ int CScriptCallback::getDate(int mode) | ||||
| void CScriptCallback::giveResource(int player, int which, int val) | ||||
| { | ||||
| 	gs->players[player].resources[which]+=val; | ||||
| 	CGI->playerint[gs->players[player].serial]->receivedResource(which,val); | ||||
| 	cl->playerint[player]->receivedResource(which,val); | ||||
| } | ||||
| void CScriptCallback::showCompInfo(int player, SComponent * comp) | ||||
| { | ||||
| 	CPlayerInterface * i = dynamic_cast<CPlayerInterface*>(CGI->playerint[gs->players[player].serial]); | ||||
| 	CPlayerInterface * i = dynamic_cast<CPlayerInterface*>(cl->playerint[player]); | ||||
| 	if(i) | ||||
| 		i->showComp(*comp); | ||||
| } | ||||
| @@ -905,15 +861,8 @@ void CScriptCallback::heroVisitCastle(CGObjectInstance * ob, int heroID) | ||||
| 	if(n = dynamic_cast<CGTownInstance*>(ob)) | ||||
| 	{ | ||||
| 		n->visitingHero = CGI->state->map->getHero(heroID,0); | ||||
| 		CGI->state->map->getHero(heroID,0)->visitedTown = n; | ||||
| 		for(int b=0; b<CGI->playerint.size(); ++b) | ||||
| 		{ | ||||
| 			if(CGI->playerint[b]->playerID == getHeroOwner(heroID)) | ||||
| 			{ | ||||
| 				CGI->playerint[b]->heroVisitsTown(CGI->state->map->getHero(heroID,0),n); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		gs->map->getHero(heroID,0)->visitedTown = n; | ||||
| 		cl->playerint[getHeroOwner(heroID)]->heroVisitsTown(CGI->state->map->getHero(heroID,0),n); | ||||
| 	} | ||||
| 	else | ||||
| 		return; | ||||
|   | ||||
| @@ -78,6 +78,8 @@ public: | ||||
|  | ||||
| struct HeroMoveDetails | ||||
| { | ||||
| 	HeroMoveDetails(){}; | ||||
| 	HeroMoveDetails(int3 Src, int3 Dst, CGHeroInstance*Ho); | ||||
| 	int3 src, dst; //source and destination points | ||||
| 	CGHeroInstance * ho; //object instance of this hero | ||||
| 	int owner; | ||||
| @@ -152,8 +154,10 @@ public: | ||||
| }; | ||||
| class CScriptCallback | ||||
| { | ||||
| 	CScriptCallback(){}; | ||||
| public: | ||||
| 	CGameState * gs; | ||||
| 	CClient *cl; | ||||
|  | ||||
| 	//get info | ||||
| 	static int3 getPos(CGObjectInstance * ob); | ||||
| @@ -162,7 +166,7 @@ public: | ||||
| 	int getDate(int mode=0); | ||||
|  | ||||
| 	//do sth | ||||
| 	static void changePrimSkill(int ID, int which, int val); | ||||
| 	void changePrimSkill(int ID, int which, int val); | ||||
| 	void showInfoDialog(int player, std::string text, std::vector<SComponent*> * components); //TODO: obslugiwac nulle | ||||
| 	void showSelDialog(int player, std::string text, std::vector<CSelectableComponent*>*components, IChosen * asker); | ||||
| 	void giveResource(int player, int which, int val); | ||||
|   | ||||
| @@ -58,8 +58,6 @@ public: | ||||
| 	CPathfinder * pathf; | ||||
| 	CCursorHandler * curh; | ||||
| 	CScreenHandler * screenh; | ||||
| 	int localPlayer; | ||||
| 	std::vector<CGameInterface *> playerint; | ||||
| }; | ||||
|  | ||||
| #endif //CGAMEINFO_H | ||||
| @@ -128,6 +128,20 @@ void CGameState::apply(IPack * pack) | ||||
| 			if(n->resetBuilded) //reset amount of structures set in this turn in towns | ||||
| 				BOOST_FOREACH(CGTownInstance* t, map->towns) | ||||
| 					t->builded = 0; | ||||
| 			break; | ||||
| 		} | ||||
| 	case 501://hero try-move | ||||
| 		{ | ||||
| 			TryMoveHero * n = static_cast<TryMoveHero*>(pack); | ||||
| 			CGHeroInstance *h = static_cast<CGHeroInstance*>(map->objects[n->id]); | ||||
| 			h->movement = n->movePoints; | ||||
| 			if(n->result) | ||||
| 				h->pos = n->end; | ||||
| 			else | ||||
| 				h->pos = n->start;			 | ||||
| 			BOOST_FOREACH(int3 t, n->fowRevealed) | ||||
| 				players[h->getOwner()].fogOfWarMap[t.x][t.y][t.z] = 1; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	mx->unlock(); | ||||
|   | ||||
| @@ -340,7 +340,7 @@ void CGarrisonInt::createSlots() | ||||
| 	{ | ||||
| 		sup = new std::vector<CGarrisonSlot*>(7,(CGarrisonSlot *)(NULL)); | ||||
| 		for | ||||
| 			(std::map<int,std::pair<CCreature*,int> >::const_iterator i=set1->slots.begin(); | ||||
| 			(std::map<si32,std::pair<CCreature*,si32> >::const_iterator i=set1->slots.begin(); | ||||
| 			i!=set1->slots.end(); i++) | ||||
| 		{ | ||||
| 			(*sup)[i->first] =  | ||||
| @@ -354,7 +354,7 @@ void CGarrisonInt::createSlots() | ||||
| 	{	 | ||||
| 		sdown = new std::vector<CGarrisonSlot*>(7,(CGarrisonSlot *)(NULL)); | ||||
| 		for | ||||
| 			(std::map<int,std::pair<CCreature*,int> >::const_iterator i=set2->slots.begin(); | ||||
| 			(std::map<si32,std::pair<CCreature*,si32> >::const_iterator i=set2->slots.begin(); | ||||
| 			i!=set2->slots.end(); i++) | ||||
| 		{ | ||||
| 			(*sdown)[i->first] =  | ||||
| @@ -902,13 +902,11 @@ CPlayerInterface::CPlayerInterface(int Player, int serial) | ||||
| 	LOCPLINT = this; | ||||
| 	playerID=Player; | ||||
| 	serialID=serial; | ||||
| 	CGI->localPlayer = playerID; | ||||
| 	human=true; | ||||
| } | ||||
| void CPlayerInterface::init(ICallback * CB) | ||||
| { | ||||
| 	cb = dynamic_cast<CCallback*>(CB); | ||||
| 	CGI->localPlayer = serialID; | ||||
| 	adventureInt = new CAdvMapInt(playerID); | ||||
| 	castleInt = NULL; | ||||
| 	std::vector <const CGHeroInstance *> hh = cb->getHeroesInfo(false); | ||||
| @@ -928,7 +926,6 @@ void CPlayerInterface::yourTurn() | ||||
| { | ||||
| 	LOCPLINT = this; | ||||
| 	makingTurn = true; | ||||
| 	CGI->localPlayer = serialID; | ||||
| 	unsigned char & animVal = LOCPLINT->adventureInt->anim; //for animations handling | ||||
| 	unsigned char & heroAnimVal = LOCPLINT->adventureInt->heroAnim; | ||||
| 	adventureInt->infoBar.newDay(cb->getDate(1)); | ||||
|   | ||||
| @@ -11,6 +11,9 @@ | ||||
| #include "../lib/NetPacks.h" | ||||
| #include <boost/bind.hpp> | ||||
| #include <boost/thread.hpp> | ||||
| #include "../hch/CObjectHandler.h" | ||||
| CSharedCond<std::set<IPack*> > mess(new std::set<IPack*>); | ||||
|  | ||||
| CClient::CClient(void) | ||||
| { | ||||
| } | ||||
| @@ -58,17 +61,18 @@ CClient::CClient(CConnection *con, StartInfo *si) | ||||
|  | ||||
| 	for (int i=0; i<CGI->state->scenarioOps->playerInfos.size();i++) //initializing interfaces | ||||
| 	{  | ||||
| 		CCallback *cb = new CCallback(CGI->state,CGI->state->scenarioOps->playerInfos[i].color,this); | ||||
| 		if(!CGI->state->scenarioOps->playerInfos[i].human) | ||||
| 			CGI->playerint.push_back(static_cast<CGameInterface*>(CAIHandler::getNewAI(cb,"EmptyAI.dll"))); | ||||
| 		ui8 color = gs->scenarioOps->playerInfos[i].color; | ||||
| 		CCallback *cb = new CCallback(gs,color,this); | ||||
| 		if(!gs->scenarioOps->playerInfos[i].human) | ||||
| 			playerint[color] = static_cast<CGameInterface*>(CAIHandler::getNewAI(cb,"EmptyAI.dll")); | ||||
| 		else  | ||||
| 		{ | ||||
| 			CGI->state->currentPlayer=CGI->state->scenarioOps->playerInfos[i].color; | ||||
| 			CGI->playerint.push_back(new CPlayerInterface(CGI->state->scenarioOps->playerInfos[i].color,i)); | ||||
| 			((CPlayerInterface*)(CGI->playerint[i]))->init(cb); | ||||
| 			gs->currentPlayer = color; | ||||
| 			playerint[color] = new CPlayerInterface(color,i); | ||||
| 			playerint[color]->init(cb); | ||||
| 		} | ||||
| 	} | ||||
| 	CGI->consoleh->cb = new CCallback(CGI->state,-1,this); | ||||
| 	CGI->consoleh->cb = new CCallback(gs,-1,this); | ||||
| } | ||||
| CClient::~CClient(void) | ||||
| { | ||||
| @@ -82,7 +86,7 @@ void CClient::process(int what) | ||||
| 			ui8 player; | ||||
| 			*serv >> player;//who? | ||||
| 			std::cout << "It's turn of "<<(unsigned)player<<" player."<<std::endl; | ||||
| 			boost::thread(boost::bind(&CGameInterface::yourTurn,CGI->playerint[gs->players[player].serial])); | ||||
| 			boost::thread(boost::bind(&CGameInterface::yourTurn,playerint[player])); | ||||
| 			break; | ||||
| 		} | ||||
| 	case 101: | ||||
| @@ -94,6 +98,42 @@ void CClient::process(int what) | ||||
| 			std::cout << "done!"<<std::endl; | ||||
| 			break; | ||||
| 		} | ||||
| 	case 501: //hero movement response - we have to notify interfaces and callback | ||||
| 		{ | ||||
| 			TryMoveHero *th = new TryMoveHero; | ||||
| 			*serv >> *th; | ||||
| 			std::cout << "HeroMove: id="<<th->id<<"\tResult: "<<(unsigned)th->result<<"\tPosition "<<th->end<<std::endl; | ||||
|  | ||||
| 			gs->apply(th); | ||||
| 			int player = gs->map->objects[th->id]->getOwner(); | ||||
|  | ||||
| 			if(playerint[player]) | ||||
| 			{ | ||||
| 				for(std::set<int3>::iterator i=th->fowRevealed.begin(); i != th->fowRevealed.end(); i++) | ||||
| 					playerint[player]->tileRevealed(*i); | ||||
| 				//boost::function<void(int3)> tr = boost::bind(&CGameInterface::tileRevealed,playerint[player]); | ||||
| 				//std::for_each(th->fowRevealed.begin(),th->fowRevealed.end(),tr); | ||||
| 			} | ||||
|  | ||||
| 			//notify interfacesabout move | ||||
| 			int nn=0; //number of interfece of currently browsed player | ||||
| 			for(std::map<ui8, CGameInterface*>::iterator i=playerint.begin();i!=playerint.end();i++) | ||||
| 			{ | ||||
| 				if(gs->players[i->first].fogOfWarMap[th->start.x-1][th->start.y][th->start.z] || gs->players[i->first].fogOfWarMap[th->end.x-1][th->end.y][th->end.z]) | ||||
| 				{ | ||||
| 					HeroMoveDetails hmd(th->start,th->end,static_cast<CGHeroInstance*>(gs->map->objects[th->id])); | ||||
| 					hmd.successful = th->result; | ||||
| 					i->second->heroMoved(hmd); | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			//add info for callback | ||||
| 			mess.mx->lock(); | ||||
| 			mess.res->insert(th); | ||||
| 			mess.mx->unlock(); | ||||
| 			mess.cv->notify_all(); | ||||
| 			break; | ||||
| 		} | ||||
| 	default: | ||||
| 		throw std::exception("Not supported server message!"); | ||||
| 		break; | ||||
|   | ||||
| @@ -5,10 +5,37 @@ class CGameState; | ||||
| class CGameInterface; | ||||
| class CConnection; | ||||
| class CCallback; | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
| 	class mutex; | ||||
| 	class condition_variable; | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| struct CSharedCond | ||||
| { | ||||
| 	boost::mutex *mx; | ||||
| 	boost::condition_variable *cv; | ||||
| 	T *res; | ||||
| 	CSharedCond(T*R) | ||||
| 	{ | ||||
| 		res = R; | ||||
| 		mx = new boost::mutex; | ||||
| 		cv = new boost::condition_variable; | ||||
| 	} | ||||
| 	~CSharedCond() | ||||
| 	{ | ||||
| 		delete res; | ||||
| 		delete mx; | ||||
| 		delete cv; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class CClient | ||||
| { | ||||
| 	CGameState *gs; | ||||
| 	std::map<int,CGameInterface *> playerint; | ||||
| 	std::map<ui8,CGameInterface *> playerint; | ||||
| 	CConnection *serv; | ||||
| public: | ||||
| 	CClient(void); | ||||
| @@ -19,4 +46,5 @@ public: | ||||
| 	void run(); | ||||
|  | ||||
| 	friend class CCallback; | ||||
| 	friend class CScriptCallback; | ||||
| }; | ||||
|   | ||||
| @@ -35,7 +35,7 @@ SDL_Surface * Graphics::drawHeroInfoWin(const CGHeroInstance * curh) | ||||
| 	SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format,0,255,255)); | ||||
| 	printAt(curh->name,75,15,GEOR13,zwykly,ret); | ||||
| 	drawPrimarySkill(curh, ret); | ||||
| 	for (std::map<int,std::pair<CCreature*,int> >::const_iterator i=curh->army.slots.begin(); i!=curh->army.slots.end();i++) | ||||
| 	for (std::map<si32,std::pair<CCreature*,si32> >::const_iterator i=curh->army.slots.begin(); i!=curh->army.slots.end();i++) | ||||
| 	{ | ||||
| 		blitAt(graphics->smallImgs[(*i).second.first->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret); | ||||
| 		itoa((*i).second.second,buf,10); | ||||
| @@ -64,7 +64,7 @@ SDL_Surface * Graphics::drawTownInfoWin(const CGTownInstance * curh) | ||||
| 		blitAt(halls->ourImages[pom].bitmap,77,42,ret); | ||||
| 	itoa(curh->dailyIncome(),buf,10); | ||||
| 	printAtMiddle(buf,167,70,GEORM,zwykly,ret); | ||||
| 	for (std::map<int,std::pair<CCreature*,int> >::const_iterator i=curh->army.slots.begin(); i!=curh->army.slots.end();i++) | ||||
| 	for (std::map<si32,std::pair<CCreature*,si32> >::const_iterator i=curh->army.slots.begin(); i!=curh->army.slots.end();i++) | ||||
| 	{ | ||||
| 		if(!i->second.first) | ||||
| 			continue; | ||||
|   | ||||
| @@ -53,7 +53,7 @@ class DLL_EXPORT CGObjectInstance | ||||
| public: | ||||
| 	int3 pos; //h3m pos | ||||
| 	int ID, subID; //normal ID (this one from OH3 maps ;]) - eg. town=98; hero=34 | ||||
| 	int id;//number of object in CObjectHandler's vector		 | ||||
| 	si32 id;//number of object in CObjectHandler's vector		 | ||||
| 	CGDefInfo * defInfo; | ||||
| 	CCPPObjectScript * state; | ||||
| 	CSpecObjInfo * info; | ||||
|   | ||||
							
								
								
									
										20
									
								
								int3.h
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								int3.h
									
									
									
									
									
								
							| @@ -5,26 +5,26 @@ class CCreature; | ||||
| class CCreatureSet //seven combined creatures | ||||
| { | ||||
| public: | ||||
| 	std::map<int,std::pair<CCreature*,int> > slots; | ||||
| 	std::map<si32,std::pair<CCreature*,si32> > slots; | ||||
| 	bool formation; //false - wide, true - tight | ||||
| }; | ||||
|  | ||||
| class int3 | ||||
| { | ||||
| public: | ||||
| 	int x,y,z; | ||||
| 	si32 x,y,z; | ||||
| 	inline int3():x(0),y(0),z(0){}; //c-tor, x/y/z initialized to 0 | ||||
| 	inline int3(const int & X, const int & Y, const int & Z):x(X),y(Y),z(Z){}; //c-tor | ||||
| 	inline int3(const si32 & X, const si32 & Y, const si32 & Z):x(X),y(Y),z(Z){}; //c-tor | ||||
| 	inline ~int3(){} // d-tor - does nothing | ||||
| 	inline int3 operator+(const int3 & i) const | ||||
| 		{return int3(x+i.x,y+i.y,z+i.z);} | ||||
| 	inline int3 operator+(const int i) const //increases all components by int | ||||
| 	inline int3 operator+(const si32 i) const //increases all components by si32 | ||||
| 		{return int3(x+i,y+i,z+i);} | ||||
| 	inline int3 operator-(const int3 & i) const | ||||
| 		{return int3(x-i.x,y-i.y,z-i.z);} | ||||
| 	inline int3 operator-(const int i) const | ||||
| 	inline int3 operator-(const si32 i) const | ||||
| 		{return int3(x-i,y-i,z-i);} | ||||
| 	inline int3 operator-() const //increases all components by int | ||||
| 	inline int3 operator-() const //increases all components by si32 | ||||
| 		{return int3(-x,-y,-z);} | ||||
| 	inline void operator+=(const int3 & i) | ||||
| 	{ | ||||
| @@ -32,7 +32,7 @@ public: | ||||
| 		y+=i.y; | ||||
| 		z+=i.z; | ||||
| 	}	 | ||||
| 	inline void operator+=(const int & i) | ||||
| 	inline void operator+=(const si32 & i) | ||||
| 	{ | ||||
| 		x+=i; | ||||
| 		y+=i; | ||||
| @@ -44,7 +44,7 @@ public: | ||||
| 		y-=i.y; | ||||
| 		z-=i.z; | ||||
| 	}	 | ||||
| 	inline void operator-=(const int & i) | ||||
| 	inline void operator-=(const si32 & i) | ||||
| 	{ | ||||
| 		x+=i; | ||||
| 		y+=i; | ||||
| @@ -70,6 +70,10 @@ public: | ||||
| 			return false; | ||||
| 		return false; | ||||
| 	} | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & x & y & z; | ||||
| 	} | ||||
| }; | ||||
| inline std::istream & operator>>(std::istream & str, int3 & dest) | ||||
| { | ||||
|   | ||||
| @@ -1,13 +1,28 @@ | ||||
| #include "../global.h" | ||||
| struct IPack | ||||
| { | ||||
| 	virtual ui16 getType()=0; | ||||
| 	virtual ui16 getType()const = 0 ; | ||||
| 	//template<ui16 Type> | ||||
| 	//static bool isType(const IPack * ip) | ||||
| 	//{ | ||||
| 	//	return Type == ip->getType(); | ||||
| 	//} | ||||
| 	template<ui16 Type> | ||||
| 	static bool isType(IPack * ip) | ||||
| 	{ | ||||
| 		return Type == ip->getType(); | ||||
| 	} | ||||
| 	//template<ui16 Type> | ||||
| 	//static bool isType(const IPack & ip) | ||||
| 	//{ | ||||
| 	//	return Type == ip.getType(); | ||||
| 	//} | ||||
| }; | ||||
| template <typename T> struct CPack | ||||
| 	:public IPack | ||||
| { | ||||
| 	ui16 type;  | ||||
| 	ui16 getType(){return type;} | ||||
| 	ui16 getType() const{return type;} | ||||
| 	T* This(){return static_cast<T*>(this);}; | ||||
| }; | ||||
| struct NewTurn : public CPack<NewTurn> //101 | ||||
| @@ -43,4 +58,18 @@ struct NewTurn : public CPack<NewTurn> //101 | ||||
| 	{ | ||||
| 		h & heroes & res & day & resetBuilded; | ||||
| 	} | ||||
| };  | ||||
| struct TryMoveHero : public CPack<TryMoveHero> //501 | ||||
| { | ||||
| 	TryMoveHero(){type = 501;}; | ||||
|  | ||||
| 	ui32 id, movePoints; | ||||
| 	ui8 result; | ||||
| 	int3 start, end; | ||||
| 	std::set<int3> fowRevealed; //revealed tiles | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & id & result & start & end & movePoints & fowRevealed; | ||||
| 	} | ||||
| };  | ||||
							
								
								
									
										32
									
								
								map.cpp
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								map.cpp
									
									
									
									
									
								
							| @@ -926,6 +926,8 @@ void Mapa::initFromBytes(unsigned char * bufor) | ||||
| 			terrain[z][c].malle = (Eroad)bufor[i++]; | ||||
| 			terrain[z][c].roadDir = bufor[i++]; | ||||
| 			terrain[z][c].siodmyTajemniczyBajt = bufor[i++]; | ||||
| 			terrain[z][c].blocked = 0; | ||||
| 			terrain[z][c].visitable = 0; | ||||
| 		} | ||||
| 	} | ||||
| 	if (twoLevel) // read underground terrain | ||||
| @@ -941,6 +943,8 @@ void Mapa::initFromBytes(unsigned char * bufor) | ||||
| 				undergroungTerrain[z][c].malle = (Eroad)bufor[i++]; | ||||
| 				undergroungTerrain[z][c].roadDir = bufor[i++]; | ||||
| 				undergroungTerrain[z][c].siodmyTajemniczyBajt = bufor[i++]; | ||||
| 				undergroungTerrain[z][c].blocked = 0; | ||||
| 				undergroungTerrain[z][c].visitable = 0; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| @@ -2289,6 +2293,34 @@ borderguardend: | ||||
|  | ||||
| 	//map readed, bufor no longer needed | ||||
| 	delete[] bufor; bufor=NULL; | ||||
|  | ||||
| 	 | ||||
| 	for(int f=0; f<objects.size(); ++f) //calculationg blocked / visitable positions | ||||
| 	{ | ||||
| 		if(!objects[f]->defInfo) | ||||
| 			continue; | ||||
| 		CDefHandler * curd = objects[f]->defInfo->handler; | ||||
| 		for(int fx=0; fx<8; ++fx) | ||||
| 		{ | ||||
| 			for(int fy=0; fy<6; ++fy) | ||||
| 			{ | ||||
| 				int xVal = objects[f]->pos.x + fx - 7; | ||||
| 				int yVal = objects[f]->pos.y + fy - 5; | ||||
| 				int zVal = objects[f]->pos.z; | ||||
| 				if(xVal>=0 && xVal<width && yVal>=0 && yVal<height) | ||||
| 				{ | ||||
| 					TerrainTile & curt = (zVal) ? (undergroungTerrain[xVal][yVal]) : (terrain[xVal][yVal]); | ||||
| 					if(((objects[f]->defInfo->visitMap[fy] >> (7 - fx)) & 1)) | ||||
| 					{ | ||||
| 						curt.visitableObjects.push_back(objects[f]); | ||||
| 						curt.visitable = true; | ||||
| 					} | ||||
| 					if(!((objects[f]->defInfo->blockMap[fy] >> (7 - fx)) & 1)) | ||||
| 						curt.blocked = true; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| }	 | ||||
|  | ||||
| Mapa::Mapa(std::string filename) | ||||
|   | ||||
							
								
								
									
										5
									
								
								map.h
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								map.h
									
									
									
									
									
								
							| @@ -263,6 +263,11 @@ struct DLL_EXPORT TerrainTile | ||||
| 	Eroad malle; // type of Eroad (0 if there is no Eriver) | ||||
| 	unsigned char roadDir; // direction of Eroad | ||||
| 	unsigned char siodmyTajemniczyBajt; //bitfield, info whether this tile is coastal and how to rotate tile graphics | ||||
|  | ||||
| 	bool visitable; //false = not visitable; true = visitable | ||||
| 	bool blocked; //false = free; true = blocked; | ||||
|  | ||||
| 	std::vector <CGObjectInstance*> visitableObjects; //pointers to objects hero can visit while being on this tile | ||||
| }; | ||||
| struct DLL_EXPORT SheroName //name of starting hero | ||||
| { | ||||
|   | ||||
| @@ -1325,7 +1325,7 @@ unsigned char CMapHandler::getHeroFrameNum(const unsigned char &dir, const bool | ||||
| 		case 8: | ||||
| 			return 11; | ||||
| 		default: | ||||
| 			return -1; //should never happen | ||||
| 			throw std::exception("Something very wrong1."); | ||||
| 		} | ||||
| 	} | ||||
| 	else //if(isMoving) | ||||
| @@ -1349,7 +1349,7 @@ unsigned char CMapHandler::getHeroFrameNum(const unsigned char &dir, const bool | ||||
| 		case 8: | ||||
| 			return 14; | ||||
| 		default: | ||||
| 			return -1; //should never happen | ||||
| 			throw std::exception("Something very wrong2."); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| #include <boost/thread/shared_mutex.hpp> | ||||
| #include <boost/bind.hpp> | ||||
| #include "CGameHandler.h" | ||||
| #include "../CLua.h" | ||||
| #include "../CGameState.h" | ||||
| #include "../StartInfo.h" | ||||
| #include "../map.h" | ||||
| @@ -19,6 +20,11 @@ boost::condition_variable cTurn; | ||||
| boost::mutex mTurn; | ||||
| boost::shared_mutex gsm; | ||||
|  | ||||
| double neighbours(int3 a, int3 b) | ||||
| { | ||||
| 	return std::sqrt( (double)(a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) ); | ||||
| } | ||||
|  | ||||
| void CGameHandler::handleConnection(std::set<int> players, CConnection &c) | ||||
| { | ||||
| 	try | ||||
| @@ -29,12 +35,126 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c) | ||||
| 			c >> pom; | ||||
| 			switch(pom) | ||||
| 			{ | ||||
| 			case 100: //my interface end its turn | ||||
| 				mTurn.lock(); | ||||
| 				makingTurn = false; | ||||
| 				mTurn.unlock(); | ||||
| 				cTurn.notify_all(); | ||||
| 				break; | ||||
| 			case 100: //my interface ended its turn | ||||
| 				{ | ||||
| 					mTurn.lock(); | ||||
| 					makingTurn = false; | ||||
| 					mTurn.unlock(); | ||||
| 					cTurn.notify_all(); | ||||
| 					break; | ||||
| 				} | ||||
| 			case 501://interface wants to move hero | ||||
| 				{ | ||||
| 					int3 start, end; | ||||
| 					si32 id; | ||||
| 					c >> id >> start >> end; | ||||
| 					int3 hmpos = end + int3(-1,0,0); | ||||
| 					TerrainTile t = (hmpos.z) ? (gs->map->undergroungTerrain[hmpos.x][hmpos.y]) : (gs->map->terrain[hmpos.x][hmpos.y]); | ||||
| 					CGHeroInstance *h = static_cast<CGHeroInstance *>(gs->map->objects[id]); | ||||
| 					int cost = (double)h->getTileCost(t.tertype,t.malle,t.nuine) * neighbours(start,end); | ||||
|  | ||||
| 					TryMoveHero tmh; | ||||
| 					tmh.id = id; | ||||
| 					tmh.start = tmh.end = start; | ||||
| 					tmh.end = end; | ||||
| 					tmh.result = 0; | ||||
| 					tmh.movePoints = h->movement; | ||||
|  | ||||
| 					if((h->getOwner() != gs->currentPlayer) || //not turn of that hero | ||||
| 						(neighbours(start,end)>=1.5) || //tiles are not neighouring | ||||
| 						(h->movement < cost) || //lack of movement points | ||||
| 						(t.tertype == rock) || //rock | ||||
| 						(!h->canWalkOnSea() && t.tertype == water) || | ||||
| 						(t.blocked && !t.visitable) ) //tile is blocked andnot visitable | ||||
| 						goto fail; | ||||
|  | ||||
| 					//we start moving | ||||
| 					bool blockvis = false; | ||||
| 					tmh.movePoints = h->movement = (h->movement-cost); //take move points | ||||
| 					BOOST_FOREACH(CGObjectInstance *obj, t.visitableObjects) | ||||
| 					{ | ||||
| 						if(obj->blockVisit) | ||||
| 						{ | ||||
| 							blockvis = true; | ||||
| 							break; | ||||
| 						} | ||||
| 					} | ||||
|  | ||||
| 					if(blockvis)//interaction with blocking object (like resources) | ||||
| 					{ | ||||
| 						gs->apply(&tmh); | ||||
| 						sendToAllClients(&tmh); | ||||
| 						BOOST_FOREACH(CGObjectInstance *obj, t.visitableObjects) | ||||
| 						{ | ||||
| 							if (obj->blockVisit) | ||||
| 							{ | ||||
| 								if(gs->checkFunc(obj->ID,"heroVisit")) //script function | ||||
| 									gs->objscr[obj->ID]["heroVisit"]->onHeroVisit(obj,h->subID); | ||||
| 								if(obj->state) //hard-coded function | ||||
| 									obj->state->onHeroVisit(obj,h->subID); | ||||
| 							} | ||||
| 						} | ||||
| 						break; | ||||
| 					} | ||||
| 					else //normal move | ||||
| 					{ | ||||
| 						tmh.result = 1; | ||||
|  | ||||
| 						BOOST_FOREACH(CGObjectInstance *obj, ((start.z) ? (gs->map->undergroungTerrain[start.x][start.y]) : (gs->map->terrain[start.x][start.y])).visitableObjects) | ||||
| 						{ | ||||
| 							//TODO: allow to handle this in script-languages | ||||
| 							if(obj->state) //hard-coded function | ||||
| 								obj->state->onHeroLeave(obj,h->subID); | ||||
| 						} | ||||
|  | ||||
| 						//reveal fog of war | ||||
| 						int heroSight = h->getSightDistance(); | ||||
| 						int xbeg = start.x - heroSight - 2; | ||||
| 						if(xbeg < 0) | ||||
| 							xbeg = 0; | ||||
| 						int xend = start.x + heroSight + 2; | ||||
| 						if(xend >= gs->map->width) | ||||
| 							xend = gs->map->width; | ||||
| 						int ybeg = start.y - heroSight - 2; | ||||
| 						if(ybeg < 0) | ||||
| 							ybeg = 0; | ||||
| 						int yend = start.y + heroSight + 2; | ||||
| 						if(yend >= gs->map->height) | ||||
| 							yend = gs->map->height; | ||||
| 						for(int xd=xbeg; xd<xend; ++xd) //revealing part of map around heroes | ||||
| 						{ | ||||
| 							for(int yd=ybeg; yd<yend; ++yd) | ||||
| 							{ | ||||
| 								int deltaX = (hmpos.x-xd)*(hmpos.x-xd); | ||||
| 								int deltaY = (hmpos.y-yd)*(hmpos.y-yd); | ||||
| 								if(deltaX+deltaY<h->getSightDistance()*h->getSightDistance()) | ||||
| 								{ | ||||
| 									if(gs->players[h->getOwner()].fogOfWarMap[xd][yd][hmpos.z] == 0) | ||||
| 									{ | ||||
| 										tmh.fowRevealed.insert(int3(xd,yd,hmpos.z)); | ||||
| 									} | ||||
| 								} | ||||
| 							} | ||||
| 						} | ||||
|  | ||||
| 						gs->apply(&tmh); | ||||
| 						sendToAllClients(&tmh); | ||||
|  | ||||
| 						//call objects if they arevisited | ||||
| 						BOOST_FOREACH(CGObjectInstance *obj, t.visitableObjects) | ||||
| 						{ | ||||
| 							if(gs->checkFunc(obj->ID,"heroVisit")) //script function | ||||
| 								gs->objscr[obj->ID]["heroVisit"]->onHeroVisit(obj,h->subID); | ||||
| 							if(obj->state) //hard-coded function | ||||
| 								obj->state->onHeroVisit(obj,h->subID); | ||||
| 						} | ||||
| 					} | ||||
| 					break; | ||||
| 				fail: | ||||
| 					gs->apply(&tmh); | ||||
| 					sendToAllClients(&tmh); | ||||
| 					break; | ||||
| 				} | ||||
| 			default: | ||||
| 				throw std::exception("Not supported client message!"); | ||||
| 				break; | ||||
| @@ -79,7 +199,7 @@ void CGameHandler::init(StartInfo *si, int Seed) | ||||
| } | ||||
| int lowestSpeed(CGHeroInstance * chi) | ||||
| { | ||||
| 	std::map<int,std::pair<CCreature*,int> >::iterator i = chi->army.slots.begin(); | ||||
| 	std::map<si32,std::pair<CCreature*,si32> >::iterator i = chi->army.slots.begin(); | ||||
| 	int ret = (*i++).second.first->speed; | ||||
| 	for (;i!=chi->army.slots.end();i++) | ||||
| 	{ | ||||
| @@ -174,6 +294,7 @@ void CGameHandler::run() | ||||
| 		{ | ||||
| 			if((i->second.towns.size()==0 && i->second.heroes.size()==0)  || i->second.color<0) continue; //players has not towns/castle - loser | ||||
| 			makingTurn = true; | ||||
| 			gs->currentPlayer = i->first; | ||||
| 			*connections[i->first] << ui16(100) << i->first;     | ||||
| 			//wait till turn is done | ||||
| 			boost::unique_lock<boost::mutex> lock(mTurn); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user