mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Partially done support for external creature dwellings.
This commit is contained in:
		| @@ -28,6 +28,7 @@ struct TryMoveHero; | ||||
| class CGHeroInstance; | ||||
| class CGTownInstance; | ||||
| class CGObjectInstance; | ||||
| class CGDwelling; | ||||
| class CCreatureSet; | ||||
| class CArmedInstance; | ||||
| struct BattleResult; | ||||
| @@ -81,6 +82,7 @@ public: | ||||
| 	virtual void init(ICallback * CB){}; | ||||
| 	virtual void receivedResource(int type, int val){}; | ||||
| 	virtual void showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID){}; | ||||
| 	virtual void showRecruitmentDialog(const CGDwelling *dwelling, int level){} | ||||
| 	//virtual void showSelDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID){}; | ||||
| 	//virtual void showYesNoDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID){}; | ||||
| 	virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, const int soundID, bool selection, bool cancel) = 0; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID. | ||||
|   | ||||
| @@ -932,15 +932,19 @@ void CCastleInterface::recreateBuildings() | ||||
|  | ||||
| CRecruitmentWindow * CCastleInterface::showRecruitmentWindow( int building ) | ||||
| { | ||||
| 	if(building>36) | ||||
| 	if(building>36) //upg dwelling | ||||
| 		building-=7; | ||||
|  | ||||
| 	int level = building-30; | ||||
| 	assert(level >= 0 && level <= 6); | ||||
|  | ||||
| 	std::vector<std::pair<int,int > > crs; | ||||
| 	int amount = (const_cast<CGTownInstance*>(town))->strInfo.creatures[building-30]; //trzeba odconstowac, bo inaczej operator [] by sypal :( | ||||
| 	int amount = town->creatures[level].first; | ||||
|  | ||||
| 	if(town->builtBuildings.find(building+7) != town->builtBuildings.end()) //check if there is an upgraded building | ||||
| 		crs.push_back(std::make_pair(town->town->upgradedCreatures[building-30],amount)); | ||||
| 	const std::vector<ui32> &cres = town->creatures[level].second; | ||||
|  | ||||
| 	crs.push_back(std::make_pair(town->town->basicCreatures[building-30],amount)); | ||||
| 	for(size_t i = 0; i < cres.size(); i++) | ||||
| 		crs.push_back(std::make_pair((int)cres[i],amount)); | ||||
|  | ||||
| 	CRecruitmentWindow *rw = new CRecruitmentWindow(crs,boost::bind(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2)); | ||||
| 	LOCPLINT->pushInt(rw); | ||||
| @@ -1436,7 +1440,7 @@ void CFortScreen::draw( CCastleInterface * owner, bool first) | ||||
| 		printAtMiddle(CGI->buildh->buildings[owner->town->subID][30+i+upgraded*7]->Name(),positions[i].x+79,positions[i].y+100,GEOR13,zwykly,bg); //dwelling name | ||||
| 		if(present) //if creature is present print avail able quantity | ||||
| 		{ | ||||
| 			SDL_itoa(owner->town->strInfo.creatures.find(i)->second,buf,10); | ||||
| 			SDL_itoa(owner->town->creatures[i].first,buf,10); | ||||
| 			printAtMiddle(CGI->generaltexth->allTexts[217] + buf,positions[i].x+79,positions[i].y+118,GEOR13,zwykly,bg); | ||||
| 		} | ||||
| 		blitAt(icons,positions[i].x+261,positions[i].y+3,bg); | ||||
|   | ||||
| @@ -122,7 +122,7 @@ void init() | ||||
| 	tlog0<<"Screen handler: "<<pomtime.getDif()<<std::endl; | ||||
| 	pomtime.getDif(); | ||||
| 	graphics = new Graphics(); | ||||
| 	graphics->loadHeroAnim(); | ||||
| 	graphics->loadHeroAnims(); | ||||
| 	tlog0<<"\tMain graphics: "<<tmh.getDif()<<std::endl; | ||||
| 	tlog0<<"Initializing game graphics: "<<tmh.getDif()<<std::endl; | ||||
|  | ||||
|   | ||||
| @@ -1756,3 +1756,16 @@ const CGHeroInstance * CPlayerInterface::getWHero( int pos ) | ||||
| 		return NULL; | ||||
| 	return wanderingHeroes[pos]; | ||||
| } | ||||
|  | ||||
| void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, int level) | ||||
| { | ||||
| 	std::vector<std::pair<int,int> > cres; | ||||
| 	for(int i = 0; i < dwelling->creatures.size(); i++) | ||||
| 	{ | ||||
| 		if(i == level || level < 0) | ||||
| 			for(size_t j = 0; j < dwelling->creatures[i].second.size(); j++) | ||||
| 				cres.push_back( std::make_pair(dwelling->creatures[i].second[j],dwelling->creatures[i].first)); | ||||
| 	} | ||||
| 	CRecruitmentWindow *cr = new CRecruitmentWindow(cres, boost::bind(&CCallback::recruitCreatures, cb, dwelling, _1, _2)); | ||||
| 	pushInt(cr); | ||||
| } | ||||
| @@ -134,8 +134,7 @@ public: | ||||
| 	void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town); | ||||
| 	void receivedResource(int type, int val); | ||||
| 	void showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID); | ||||
| 	//void showSelDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID); | ||||
| 	//void showYesNoDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID); | ||||
| 	void showRecruitmentDialog(const CGDwelling *dwelling, int level); | ||||
| 	void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, int soundID, bool selection, bool cancel); //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID. | ||||
| 	void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, boost::function<void()> &onEnd); | ||||
| 	void tileHidden(const std::set<int3> &pos); //called when given tiles become hidden under fog of war | ||||
|   | ||||
| @@ -305,49 +305,58 @@ void Graphics::loadHeroPortraits() | ||||
| 	} | ||||
| 	of.close(); | ||||
| } | ||||
| void Graphics::loadHeroAnim() | ||||
| void Graphics::loadHeroAnims() | ||||
| { | ||||
| 	heroAnims.resize(F_NUMBER * 2); | ||||
| 	std::vector<std::pair<int,int> > rotations; //first - group number to be rotated1, second - group number after rotation1 | ||||
| 	rotations += std::make_pair(6,10), std::make_pair(7,11), std::make_pair(8,12), std::make_pair(1,13), | ||||
| 		std::make_pair(2,14), std::make_pair(3,15); | ||||
| 	for(size_t i=0; i<heroAnims.size(); ++i) | ||||
| 	for(size_t i=0; i<F_NUMBER * 2; ++i) | ||||
| 	{ | ||||
| 		std::ostringstream nm; | ||||
| 		nm << "AH" << std::setw(2) << std::setfill('0') << i << "_.DEF"; | ||||
| 		loadHeroAnim(nm.str(), rotations, &Graphics::heroAnims); | ||||
| 		std::string name = nm.str(); | ||||
| 		heroAnims[i] = CDefHandler::giveDefEss(name); | ||||
| 		int pom = 0; //how many groups has been rotated | ||||
| 		for(int o=7; pom<6; ++o) | ||||
| 	}	 | ||||
|  | ||||
| 	loadHeroAnim("AB01_.DEF", rotations, &Graphics::boatAnims); | ||||
| 	loadHeroAnim("AB02_.DEF", rotations, &Graphics::boatAnims); | ||||
| 	loadHeroAnim("AB03_.DEF", rotations, &Graphics::boatAnims); | ||||
| } | ||||
|  | ||||
| void Graphics::loadHeroAnim( const std::string &name, const std::vector<std::pair<int,int> > &rotations, std::vector<CDefEssential *> Graphics::*dst ) | ||||
| { | ||||
| 	CDefEssential *anim = CDefHandler::giveDefEss(name); | ||||
| 	heroAnims.push_back(anim); | ||||
| 	int pom = 0; //how many groups has been rotated | ||||
| 	for(int o=7; pom<6; ++o) | ||||
| 	{ | ||||
| 		for(int p=0;p<6;p++) | ||||
| 		{ | ||||
| 			for(int p=0;p<6;p++) | ||||
| 			if(anim->ourImages[o].groupNumber == rotations[p].first) | ||||
| 			{ | ||||
| 				if(heroAnims[i]->ourImages[o].groupNumber==rotations[p].first) | ||||
| 				for(int e=0; e<8; ++e) | ||||
| 				{ | ||||
| 					for(int e=0; e<8; ++e) | ||||
| 					{ | ||||
| 						Cimage nci; | ||||
| 						nci.bitmap = CSDL_Ext::rotate01(heroAnims[i]->ourImages[o+e].bitmap); | ||||
| 						nci.groupNumber = rotations[p].second; | ||||
| 						nci.imName = std::string(); | ||||
| 						heroAnims[i]->ourImages.push_back(nci); | ||||
| 						if(pom>2) //we need only one frame for groups 13/14/15 | ||||
| 							break; | ||||
| 					} | ||||
| 					if(pom<3) //there are eight frames of animtion of groups 6/7/8 so for speed we'll skip them | ||||
| 						o+=8; | ||||
| 					else //there is only one frame of 1/2/3 | ||||
| 						o+=1; | ||||
| 					++pom; | ||||
| 					if(p==2 && pom<4) //group1 starts at index 1 | ||||
| 						o = 1; | ||||
| 					Cimage nci; | ||||
| 					nci.bitmap = CSDL_Ext::rotate01(anim->ourImages[o+e].bitmap); | ||||
| 					nci.groupNumber = rotations[p].second; | ||||
| 					nci.imName = std::string(); | ||||
| 					anim->ourImages.push_back(nci); | ||||
| 					if(pom>2) //we need only one frame for groups 13/14/15 | ||||
| 						break; | ||||
| 				} | ||||
| 				if(pom<3) //there are eight frames of animtion of groups 6/7/8 so for speed we'll skip them | ||||
| 					o+=8; | ||||
| 				else //there is only one frame of 1/2/3 | ||||
| 					o+=1; | ||||
| 				++pom; | ||||
| 				if(p==2 && pom<4) //group1 starts at index 1 | ||||
| 					o = 1; | ||||
| 			} | ||||
| 		} | ||||
| 		for(size_t ff=0; ff<heroAnims[i]->ourImages.size(); ++ff) | ||||
| 		{ | ||||
| 			CSDL_Ext::alphaTransform(heroAnims[i]->ourImages[ff].bitmap); | ||||
| 		} | ||||
| 	} | ||||
| 	for(size_t ff=0; ff<anim->ourImages.size(); ++ff) | ||||
| 	{ | ||||
| 		CSDL_Ext::alphaTransform(anim->ourImages[ff].bitmap); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -48,6 +48,7 @@ public: | ||||
| 	CDefEssential * smallIcons, *resources32; //resources 32x32 | ||||
| 	CDefEssential * flags; | ||||
| 	std::vector<CDefEssential *> heroAnims; // [class id: 0 - 17]  //added group 10: up - left, 11 - left and 12 - left down // 13 - up-left standing; 14 - left standing; 15 - left down standing | ||||
| 	std::vector<CDefEssential *> boatAnims; // [boat type: 0 - 3]  //added group 10: up - left, 11 - left and 12 - left down // 13 - up-left standing; 14 - left standing; 15 - left down standing | ||||
| 	//creatures | ||||
| 	std::map<int,SDL_Surface*> smallImgs; //creature ID -> small 32x32 img of creature; //ID=-2 is for blank (black) img; -1 for the border | ||||
| 	std::map<int,SDL_Surface*> bigImgs; //creature ID -> big 58x64 img of creature; //ID=-2 is for blank (black) img; -1 for the border | ||||
| @@ -69,7 +70,8 @@ public: | ||||
| 	void loadPaletteAndColors(); | ||||
| 	void loadHeroFlags(); | ||||
| 	void loadHeroFlags(std::pair<std::vector<CDefEssential *> Graphics::*, std::vector<const char *> > &pr, bool mode); | ||||
| 	void loadHeroAnim(); | ||||
| 	void loadHeroAnims(); | ||||
| 	void loadHeroAnim(const std::string &name, const std::vector<std::pair<int,int> > &rotations, std::vector<CDefEssential *> Graphics::*dst); | ||||
| 	void loadHeroPortraits(); | ||||
| 	SDL_Surface * drawHeroInfoWin(const CGHeroInstance * curh); | ||||
| 	SDL_Surface * drawPrimarySkill(const CGHeroInstance *curh, SDL_Surface *ret, int from=0, int to=PRIMARY_SKILLS); | ||||
|   | ||||
| @@ -459,11 +459,27 @@ void ShowInInfobox::applyCl(CClient *cl) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void HeroExchange::applyFirstCl(CClient *cl) | ||||
| void OpenWindow::applyFirstCl(CClient *cl) | ||||
| { | ||||
| } | ||||
|  | ||||
| void HeroExchange::applyCl(CClient *cl) | ||||
| void OpenWindow::applyCl(CClient *cl) | ||||
| { | ||||
| 	cl->playerint[player]->heroExchangeStarted(hero1, hero2); | ||||
| 	switch(window) | ||||
| 	{ | ||||
| 	case EXCHANGE_WINDOW: | ||||
| 		{ | ||||
| 			const CGHeroInstance *h = cl->getHero(id1); | ||||
| 			const CGObjectInstance *h2 = cl->getHero(id2); | ||||
| 			assert(h && h2); | ||||
| 			INTERFACE_CALL_IF_PRESENT(h->tempOwner,heroExchangeStarted, id1, id2); | ||||
| 		} | ||||
| 		break; | ||||
| 	case RECRUITMENT_FIRST: | ||||
| 		{ | ||||
| 			const CGDwelling *dw = dynamic_cast<const CGDwelling*>(cl->getObj(id1)); | ||||
| 			INTERFACE_CALL_IF_PRESENT(dw->tempOwner,showRecruitmentDialog, dw, 0); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -903,6 +903,77 @@ si32 CGHeroInstance::getArtPos(int aid) const | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| void CGDwelling::initObj() | ||||
| { | ||||
| 	switch(ID) | ||||
| 	{ | ||||
| 	case 17: | ||||
| 		creatures.resize(1); | ||||
| 		creatures[0].second.push_back(VLC->objh->cregens[subID]); | ||||
| 		break; | ||||
| 	case 20: | ||||
| 		creatures.resize(4); | ||||
| 		if(subID == 1) // Elemental Conflux  | ||||
| 		{ | ||||
| 			creatures[0].second.push_back(32);  //Stone Golem | ||||
| 			creatures[1].second.push_back(33);  //Iron Golem   | ||||
| 			creatures[2].second.push_back(116); //Gold Golem | ||||
| 			creatures[3].second.push_back(117); //Diamond Golem | ||||
| 		} | ||||
| 		else if(subID == 1) //Golem Factory | ||||
| 		{ | ||||
| 			creatures[0].second.push_back(112); //Air Elemental | ||||
| 			creatures[1].second.push_back(113); //Earth Elemental | ||||
| 			creatures[2].second.push_back(114); //Fire Elemental | ||||
| 			creatures[3].second.push_back(115); //Water Elemental | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			assert(0); | ||||
| 		} | ||||
| 		break; | ||||
| 	default: | ||||
| 		assert(0); | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const | ||||
| { | ||||
| 	if(h->tempOwner != tempOwner) | ||||
| 		cb->setOwner(id, h->tempOwner); | ||||
|  | ||||
| 	OpenWindow ow; | ||||
| 	ow.id1 = id; | ||||
| 	ow.id2 = id; | ||||
| 	ow.window = OpenWindow::RECRUITMENT_FIRST; | ||||
| 	cb->sendAndApply(&ow); | ||||
| } | ||||
|  | ||||
| void CGDwelling::newTurn() const | ||||
| { | ||||
| 	if(cb->getDate(1) != 1) //not first day of week | ||||
| 		return; | ||||
|  | ||||
|  | ||||
| 	bool change = false; | ||||
|  | ||||
| 	SetAvailableCreatures sac; | ||||
| 	sac.creatures = creatures; | ||||
| 	sac.tid = id; | ||||
| 	for (size_t i = 0; i < creatures.size(); i++) | ||||
| 	{ | ||||
| 		if(creatures[i].second.size()) | ||||
| 		{ | ||||
| 			sac.creatures[i].first += VLC->creh->creatures[creatures[i].second[0]].growth; | ||||
| 			change = true; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if(change) | ||||
| 		cb->sendAndApply(&sac); | ||||
| } | ||||
|  | ||||
| int CGTownInstance::getSightRadious() const //returns sight distance | ||||
| { | ||||
| 	return 5; | ||||
| @@ -1042,6 +1113,15 @@ void CGTownInstance::initObj() | ||||
| 	MetaString ms; | ||||
| 	ms << name << ", " << town->Name(); | ||||
| 	hoverName = toString(ms); | ||||
|  | ||||
| 	creatures.resize(CREATURES_PER_TOWN); | ||||
| 	for (int i = 0; i < CREATURES_PER_TOWN; i++) | ||||
| 	{ | ||||
| 		if(creatureDwelling(i,false)) | ||||
| 			creatures[i].second.push_back(town->basicCreatures[i]); | ||||
| 		if(creatureDwelling(i,true)) | ||||
| 			creatures[i].second.push_back(town->upgradedCreatures[i]); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int3 CGTownInstance::getSightCenter() const | ||||
| @@ -2144,17 +2224,6 @@ const std::string & CGWitchHut::getHoverText() const | ||||
| 	return hoverName; | ||||
| } | ||||
|  | ||||
|  | ||||
| void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| void CGDwelling::initObj() | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| void CGBonusingObject::onHeroVisit( const CGHeroInstance * h ) const | ||||
| { | ||||
| 	bool visited = h->getBonus(HeroBonus::OBJECT,ID); | ||||
|   | ||||
| @@ -284,7 +284,22 @@ public: | ||||
| 	void onHeroVisit(const CGHeroInstance * h) const; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT CGTownInstance : public CArmedInstance | ||||
| class DLL_EXPORT CGDwelling : public CArmedInstance | ||||
| { | ||||
| public: | ||||
| 	std::vector<std::pair<ui32, std::vector<ui32> > > creatures; //creatures[level] -> <vector of alternative ids (base creature and upgrades, creatures amount> | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & static_cast<CArmedInstance&>(*this) & creatures; | ||||
| 	} | ||||
|  | ||||
| 	void initObj(); | ||||
| 	void onHeroVisit(const CGHeroInstance * h) const; | ||||
| 	void newTurn() const; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT CGTownInstance : public CGDwelling | ||||
| { | ||||
| public: | ||||
| 	CTown * town; | ||||
| @@ -298,15 +313,15 @@ public: | ||||
| 	std::vector<ui32> possibleSpells, obligatorySpells; | ||||
| 	std::vector<std::vector<ui32> > spells; //spells[level] -> vector of spells, first will be available in guild | ||||
|  | ||||
| 	struct StrInfo | ||||
| 	{ | ||||
| 		std::map<si32,ui32> creatures; //level - available amount | ||||
| 	//struct StrInfo | ||||
| 	//{ | ||||
| 	//	std::map<si32,ui32> creatures; //level - available amount | ||||
|  | ||||
| 		template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 		{ | ||||
| 			h & creatures; | ||||
| 		} | ||||
| 	} strInfo; | ||||
| 	//	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	//	{ | ||||
| 	//		h & creatures; | ||||
| 	//	} | ||||
| 	//} strInfo; | ||||
| 	std::set<CCastleEvent> events; | ||||
|  | ||||
| 	////////////////////////////////////////////////////////////////////////// | ||||
| @@ -316,7 +331,7 @@ public: | ||||
| 	{ | ||||
| 		h & static_cast<CArmedInstance&>(*this); | ||||
| 		h & name & builded & destroyed & identifier & alignment & forbiddenBuildings & builtBuildings | ||||
| 			& possibleSpells & obligatorySpells & spells & strInfo & events; | ||||
| 			& possibleSpells & obligatorySpells & spells & /*strInfo & */events; | ||||
|  | ||||
| 		ui8 standardType = (&VLC->townh->towns[subID] == town); | ||||
| 		h & standardType; | ||||
| @@ -666,19 +681,6 @@ public: | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT CGDwelling : public CGObjectInstance //teleports and subterranean gates | ||||
| { | ||||
| public: | ||||
| 	static std::map<int,std::map<int, std::vector<int> > > objs; //map[ID][subID] => vector of ids | ||||
| 	void onHeroVisit(const CGHeroInstance * h) const; | ||||
| 	void initObj();	 | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & static_cast<CGObjectInstance&>(*this); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT CGBonusingObject : public CGObjectInstance //objects giving bonuses to luck/morale/movement | ||||
| { | ||||
| public: | ||||
|   | ||||
| @@ -1343,11 +1343,12 @@ int CGameState::battleGetBattlefieldType(int3 tile) | ||||
| 	else if(tile==int3() && !curB) | ||||
| 		return -1; | ||||
|  | ||||
| 	std::vector <CGObjectInstance*> & objs = map->objects; | ||||
| 	const std::vector <CGObjectInstance*> & objs = map->objects; | ||||
| 	for(int g=0; g<objs.size(); ++g) | ||||
| 	{ | ||||
| 		if( objs[g]->pos.x - tile.x < 0 || objs[g]->pos.x - tile.x >= 8 || tile.y - objs[g]->pos.y + 5 < 0 || tile.y - objs[g]->pos.y + 5 >=6 || | ||||
| 			!objs[g]->coveringAt(objs[g]->pos.x - tile.x, tile.y - objs[g]->pos.y + 5) | ||||
| 		if( !objs[g] || objs[g]->pos.x - tile.x < 0  ||  objs[g]->pos.x - tile.x >= 8   | ||||
| 			||  tile.y - objs[g]->pos.y + 5 < 0  ||  tile.y - objs[g]->pos.y + 5 >=6  | ||||
| 			|| !objs[g]->coveringAt(objs[g]->pos.x - tile.x, tile.y - objs[g]->pos.y + 5) | ||||
| 			) //look only for objects covering given tile | ||||
| 			continue; | ||||
| 		switch(objs[g]->ID) | ||||
|   | ||||
| @@ -409,7 +409,7 @@ struct SetAvailableCreatures : public CPackForClient //506 | ||||
| 	DLL_EXPORT void applyGs(CGameState *gs); | ||||
|  | ||||
| 	si32 tid; | ||||
| 	std::map<si32,ui32> creatures; | ||||
| 	std::vector<std::pair<ui32, std::vector<ui32> > > creatures; | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| @@ -480,19 +480,20 @@ struct GiveHero : public CPackForClient //516 | ||||
| 	} | ||||
| };   | ||||
|  | ||||
| struct HeroExchange : public CPackForClient //517 | ||||
| struct OpenWindow : public CPackForClient //517 | ||||
| { | ||||
| 	HeroExchange(){type = 517;}; | ||||
| 	OpenWindow(){type = 517;}; | ||||
| 	void applyFirstCl(CClient *cl); | ||||
| 	void applyCl(CClient *cl); | ||||
| 	DLL_EXPORT void applyGs(CGameState *gs); | ||||
|  | ||||
| 	si32 hero1, hero2; //heroes for exchange | ||||
| 	ui8 player; | ||||
| 	enum EWindow {EXCHANGE_WINDOW, RECRUITMENT_FIRST, RECRUITMENT_ALL}; | ||||
| 	ui8 window; | ||||
| 	ui32 id1, id2; | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & hero1 & hero2 & player; | ||||
| 		h & window & id1 & id2; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -278,7 +278,7 @@ DLL_EXPORT void NewStructures::applyGs( CGameState *gs ) | ||||
|  | ||||
| DLL_EXPORT void SetAvailableCreatures::applyGs( CGameState *gs ) | ||||
| { | ||||
| 	gs->getTown(tid)->strInfo.creatures = creatures; | ||||
| 	gs->getTown(tid)->creatures = creatures; | ||||
| } | ||||
|  | ||||
| DLL_EXPORT void SetHeroesInTown::applyGs( CGameState *gs ) | ||||
| @@ -418,7 +418,7 @@ DLL_EXPORT void GiveHero::applyGs( CGameState *gs ) | ||||
| 	h->inTownGarrison = false; | ||||
| } | ||||
|  | ||||
| DLL_EXPORT void HeroExchange::applyGs(CGameState *gs) | ||||
| DLL_EXPORT void OpenWindow::applyGs(CGameState *gs) | ||||
| { | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -93,7 +93,7 @@ void registerTypes2(Serializer &s) | ||||
| 	s.template registerType<SetStackEffect>(); | ||||
| 	s.template registerType<StacksInjured>(); | ||||
| 	s.template registerType<ShowInInfobox>(); | ||||
| 	s.template registerType<HeroExchange>(); | ||||
| 	s.template registerType<OpenWindow>(); | ||||
|  | ||||
| 	s.template registerType<SaveGame>(); | ||||
| 	s.template registerType<SetSelection>(); | ||||
|   | ||||
							
								
								
									
										12
									
								
								lib/map.cpp
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								lib/map.cpp
									
									
									
									
									
								
							| @@ -1672,6 +1672,12 @@ void Mapa::readObjects( unsigned char * bufor, int &i) | ||||
| 				break; | ||||
| 			} | ||||
| 		case 17: case 18: case 19: case 20: //dwellings | ||||
| 			{ | ||||
| 				nobj = new CGDwelling(); | ||||
| 				nobj->setOwner(bufor[i++]); | ||||
| 				i+=3; | ||||
| 				break; | ||||
| 			} | ||||
| 		case 42: //lighthouse | ||||
| 		case 87: //shipyard | ||||
| 		case 220://mine (?) | ||||
| @@ -1759,7 +1765,7 @@ void Mapa::readObjects( unsigned char * bufor, int &i) | ||||
| 			} | ||||
| 		case 217: | ||||
| 			{ | ||||
| 				nobj = new CGObjectInstance(); | ||||
| 				nobj = new CGDwelling(); | ||||
| 				CCreGenObjInfo * spec = new CCreGenObjInfo; | ||||
| 				spec->player = readNormalNr(bufor,i); i+=4; | ||||
| 				spec->identifier =  readNormalNr(bufor,i); i+=4; | ||||
| @@ -1779,7 +1785,7 @@ void Mapa::readObjects( unsigned char * bufor, int &i) | ||||
| 			} | ||||
| 		case 216: | ||||
| 			{ | ||||
| 				nobj = new CGObjectInstance(); | ||||
| 				nobj = new CGDwelling(); | ||||
| 				CCreGen2ObjInfo * spec = new CCreGen2ObjInfo; | ||||
| 				spec->player = readNormalNr(bufor,i); i+=4; | ||||
| 				spec->identifier =  readNormalNr(bufor,i); i+=4; | ||||
| @@ -1801,7 +1807,7 @@ void Mapa::readObjects( unsigned char * bufor, int &i) | ||||
| 			} | ||||
| 		case 218: | ||||
| 			{ | ||||
| 				nobj = new CGObjectInstance(); | ||||
| 				nobj = new CGDwelling(); | ||||
| 				CCreGen3ObjInfo * spec = new CCreGen3ObjInfo; | ||||
| 				spec->player = bufor[i]; ++i; | ||||
| 				i+=3; | ||||
|   | ||||
| @@ -773,63 +773,61 @@ void CMapHandler::terrainRect(int3 top_tile, unsigned char anim, std::vector< st | ||||
| 				SDL_Rect pp = objects[h].second; | ||||
| 				pp.h = sr.h; | ||||
| 				pp.w = sr.w; | ||||
| 				const CGHeroInstance * themp = (dynamic_cast<const CGHeroInstance*>(objects[h].first)); | ||||
|  | ||||
| 				if(themp && themp->moveDir && !themp->isStanding && themp->ID!=62) //last condition - this is not prison | ||||
| 				const CGHeroInstance * themp = (objects[h].first->ID != HEROI_TYPE   | ||||
| 					? NULL   | ||||
| 					: static_cast<const CGHeroInstance*>(objects[h].first)); | ||||
|  | ||||
| 				if(themp && themp->moveDir) //it's hero | ||||
| 				{ | ||||
| 					int imgVal = 8; | ||||
| 					SDL_Surface * tb; | ||||
|  | ||||
| 					if(themp->type==NULL) | ||||
| 						continue; | ||||
| 					std::vector<Cimage> & iv = graphics->heroAnims[themp->type->heroType]->ourImages; | ||||
|  | ||||
|                     size_t gg; | ||||
| 					for(gg=0; gg<iv.size(); ++gg) | ||||
| 					if(!themp->isStanding) //hero is moving | ||||
| 					{ | ||||
| 						if(iv[gg].groupNumber==getHeroFrameNum(themp->moveDir, !themp->isStanding)) | ||||
| 						size_t gg; | ||||
| 						for(gg=0; gg<iv.size(); ++gg) | ||||
| 						{ | ||||
| 							tb = iv[gg+heroAnim%imgVal].bitmap; | ||||
| 							break; | ||||
| 							if(iv[gg].groupNumber==getHeroFrameNum(themp->moveDir, !themp->isStanding)) | ||||
| 							{ | ||||
| 								tb = iv[gg+heroAnim%imgVal].bitmap; | ||||
| 								break; | ||||
| 							} | ||||
| 						} | ||||
| 						CSDL_Ext::blit8bppAlphaTo24bpp(tb,&pp,extSurf,&sr); | ||||
| 						pp.y+=imgVal*2-32; | ||||
| 						sr.y-=16; | ||||
| 						SDL_BlitSurface(graphics->flags4[themp->getOwner()]->ourImages[gg+heroAnim%imgVal+35].bitmap, &pp, extSurf, &sr); | ||||
| 					} | ||||
| 					else //hero stands still | ||||
| 					{ | ||||
| 						size_t gg; | ||||
| 						for(gg=0; gg < iv.size(); ++gg) | ||||
| 						{ | ||||
| 							if(iv[gg].groupNumber==getHeroFrameNum(themp->moveDir, !themp->isStanding)) | ||||
| 							{ | ||||
| 								tb = iv[gg].bitmap; | ||||
| 								break; | ||||
| 							} | ||||
| 						} | ||||
| 						CSDL_Ext::blit8bppAlphaTo24bpp(tb,&pp,extSurf,&sr); | ||||
|  | ||||
| 						if(themp->pos.x==top_tile.x+bx && themp->pos.y==top_tile.y+by) | ||||
| 						{ | ||||
| 							SDL_Rect bufr = sr; | ||||
| 							bufr.x-=2*32; | ||||
| 							bufr.y-=1*32; | ||||
| 							bufr.h = 64; | ||||
| 							bufr.w = 96; | ||||
| 							if(bufr.x-extRect->x>-64) | ||||
| 								SDL_BlitSurface(graphics->flags4[themp->getOwner()]->ourImages[ getHeroFrameNum(themp->moveDir, !themp->isStanding) *8+(heroAnim/4)%imgVal].bitmap, NULL, extSurf, &bufr); | ||||
| 						} | ||||
| 					} | ||||
| 					CSDL_Ext::blit8bppAlphaTo24bpp(tb,&pp,extSurf,&sr); | ||||
| 					pp.y+=imgVal*2-32; | ||||
| 					sr.y-=16; | ||||
| 					SDL_BlitSurface(graphics->flags4[themp->getOwner()]->ourImages[gg+heroAnim%imgVal+35].bitmap, &pp, extSurf, &sr); | ||||
| 				} | ||||
| 				else if(themp && themp->moveDir && themp->isStanding && themp->ID!=62) //last condition - this is not prison) | ||||
| 				{ | ||||
| 					int imgVal = 8; | ||||
| 					SDL_Surface * tb; | ||||
|  | ||||
| 					if(themp->type==NULL) | ||||
| 						continue; | ||||
| 					std::vector<Cimage> & iv = graphics->heroAnims[themp->type->heroType]->ourImages; | ||||
|  | ||||
|                     size_t gg; | ||||
| 					for(gg=0; gg < iv.size(); ++gg) | ||||
| 					{ | ||||
| 						if(iv[gg].groupNumber==getHeroFrameNum(themp->moveDir, !themp->isStanding)) | ||||
| 						{ | ||||
| 							tb = iv[gg].bitmap; | ||||
| 							break; | ||||
| 						} | ||||
| 					} | ||||
| 					CSDL_Ext::blit8bppAlphaTo24bpp(tb,&pp,extSurf,&sr); | ||||
|  | ||||
| 					if(themp->pos.x==top_tile.x+bx && themp->pos.y==top_tile.y+by) | ||||
| 					{ | ||||
| 						SDL_Rect bufr = sr; | ||||
| 						bufr.x-=2*32; | ||||
| 						bufr.y-=1*32; | ||||
| 						bufr.h = 64; | ||||
| 						bufr.w = 96; | ||||
| 						if(bufr.x-extRect->x>-64) | ||||
| 							SDL_BlitSurface(graphics->flags4[themp->getOwner()]->ourImages[ getHeroFrameNum(themp->moveDir, !themp->isStanding) *8+(heroAnim/4)%imgVal].bitmap, NULL, extSurf, &bufr); | ||||
| 					} | ||||
| 				} | ||||
| 				else | ||||
| 				else //blit object | ||||
| 				{ | ||||
| 					const CGObjectInstance *obj = objects[h].first; | ||||
| 					const std::vector<Cimage> &ourImages = obj->defInfo->handler->ourImages; | ||||
|   | ||||
| @@ -709,14 +709,14 @@ void CGameHandler::newTurn() | ||||
| 			{ | ||||
| 				SetAvailableCreatures sac; | ||||
| 				sac.tid = (**j).id; | ||||
| 				sac.creatures = (**j).strInfo.creatures; | ||||
| 				sac.creatures = (**j).creatures; | ||||
| 				for(int k=0;k<CREATURES_PER_TOWN;k++) //creature growths | ||||
| 				{ | ||||
| 					if((**j).creatureDwelling(k))//there is dwelling (k-level) | ||||
| 					{ | ||||
| 						sac.creatures[k] += (**j).creatureGrowth(k); | ||||
| 						sac.creatures[k].first += (**j).creatureGrowth(k); | ||||
| 						if(!gs->getDate(0)) //first day of game: use only basic growths | ||||
| 							amin(sac.creatures[k], VLC->creh->creatures[(*j)->town->basicCreatures[k]].growth); | ||||
| 							amin(sac.creatures[k].first, VLC->creh->creatures[(*j)->town->basicCreatures[k]].growth); | ||||
| 					} | ||||
| 				} | ||||
| 				n.cres.push_back(sac); | ||||
| @@ -1203,7 +1203,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255* | ||||
| 			{ | ||||
| 				if (obj->blockVisit) | ||||
| 				{ | ||||
| 					obj->onHeroVisit(h); | ||||
| 					objectVisited(obj, h); | ||||
| 				} | ||||
| 			} | ||||
| 			tlog5 << "Blocking visit at " << hmpos << std::endl; | ||||
| @@ -1224,7 +1224,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255* | ||||
| 			//call objects if they are visited | ||||
| 			BOOST_FOREACH(CGObjectInstance *obj, t.visitableObjects) | ||||
| 			{ | ||||
| 				obj->onHeroVisit(h); | ||||
| 				objectVisited(obj, h); | ||||
| 			} | ||||
| 		} | ||||
| 		tlog5 << "Movement end!\n"; | ||||
| @@ -1449,10 +1449,10 @@ void CGameHandler::heroExchange(si32 hero1, si32 hero2) | ||||
|  | ||||
| 	if(player1 == player2) | ||||
| 	{ | ||||
| 		HeroExchange hex; | ||||
| 		hex.hero1 = hero1; | ||||
| 		hex.hero2 = hero2; | ||||
| 		hex.player = player1; | ||||
| 		OpenWindow hex; | ||||
| 		hex.window = OpenWindow::EXCHANGE_WINDOW; | ||||
| 		hex.id1 = hero1; | ||||
| 		hex.id2 = hero2; | ||||
| 		sendAndApply(&hex); | ||||
| 	} | ||||
| } | ||||
| @@ -1679,8 +1679,8 @@ bool CGameHandler::buildStructure( si32 tid, si32 bid ) | ||||
| 	{ | ||||
| 		SetAvailableCreatures ssi; | ||||
| 		ssi.tid = tid; | ||||
| 		ssi.creatures = t->strInfo.creatures; | ||||
| 		ssi.creatures[bid-30] = VLC->creh->creatures[t->town->basicCreatures[bid-30]].growth; | ||||
| 		ssi.creatures = t->creatures; | ||||
| 		ssi.creatures[bid-30].first = VLC->creh->creatures[t->town->basicCreatures[bid-30]].growth; | ||||
| 		sendAndApply(&ssi); | ||||
| 	} | ||||
|  | ||||
| @@ -1715,26 +1715,41 @@ void CGameHandler::sendMessageToAll( const std::string &message ) | ||||
|  | ||||
| bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram ) | ||||
| { | ||||
| 	si32 ser = -1; | ||||
| 	CGTownInstance * t = static_cast<CGTownInstance*>(gs->map->objects[objid]); | ||||
| 	const CGDwelling *dw = static_cast<CGDwelling*>(gs->map->objects[objid]); | ||||
| 	const CArmedInstance *dst = NULL; | ||||
|  | ||||
| 	if(dw->ID == TOWNI_TYPE) | ||||
| 		dst = dw; | ||||
| 	else if(dw->ID == 17  ||  dw->ID == 20) //advmap dwelling | ||||
| 		dst = getHero(gs->getPlayer(dw->tempOwner)->currentSelection); //TODO: check if current hero is really visiting dwelling | ||||
|  | ||||
| 	assert(dw && dst); | ||||
|  | ||||
| 	//verify | ||||
| 	bool found = false; | ||||
| 	int level = -1; | ||||
|  | ||||
|  | ||||
| 	typedef std::pair<const int,int> Parka; | ||||
| 	for(std::map<si32,ui32>::iterator av = t->strInfo.creatures.begin();  av!=t->strInfo.creatures.end();  av++) | ||||
| 	for(level = 0; level < dw->creatures.size(); level++) //iterate through all levels | ||||
| 	{ | ||||
| 		if(	(   found  = (crid == t->town->basicCreatures[av->first])   ) //creature is available among basic cretures | ||||
| 			|| (found  = (crid == t->town->upgradedCreatures[av->first]))			)//creature is available among upgraded cretures | ||||
| 		const std::pair<ui32, std::vector<ui32> > &cur = dw->creatures[level]; //current level info <amount, list of cr. ids> | ||||
| 		int i = 0; | ||||
| 		for(; i < cur.second.size(); i++) //look for crid among available creatures list on current level | ||||
| 			if(cur.second[i] == crid) | ||||
| 				break; | ||||
|  | ||||
| 		if(i < cur.second.size()) | ||||
| 		{ | ||||
| 			cram = std::min(cram,av->second); //reduce recruited amount up to available amount | ||||
| 			ser = av->first; | ||||
| 			found = true; | ||||
| 			cram = std::min(cram, cur.first); //reduce recruited amount up to available amount | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	int slot = t->army.getSlotFor(crid); | ||||
| 	int slot = dst->army.getSlotFor(crid); | ||||
|  | ||||
| 	if(!found && complain("Cannot recruit: no such creatures!") | ||||
| 		|| cram > VLC->creh->creatures[crid].maxAmount(gs->getPlayer(t->tempOwner)->resources) && complain("Cannot recruit: lack of resources!") | ||||
| 		|| cram > VLC->creh->creatures[crid].maxAmount(gs->getPlayer(dst->tempOwner)->resources) && complain("Cannot recruit: lack of resources!") | ||||
| 		|| cram<=0	&& complain("Cannot recruit: cram <= 0!") | ||||
| 		|| slot<0  && complain("Cannot recruit: no available slot!"))  | ||||
| 	{ | ||||
| @@ -1743,24 +1758,24 @@ bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram ) | ||||
|  | ||||
| 	//recruit | ||||
| 	SetResources sr; | ||||
| 	sr.player = t->tempOwner; | ||||
| 	sr.player = dst->tempOwner; | ||||
| 	for(int i=0;i<RESOURCE_QUANTITY;i++) | ||||
| 		sr.res[i]  =  gs->getPlayer(t->tempOwner)->resources[i] - (VLC->creh->creatures[crid].cost[i] * cram); | ||||
| 		sr.res[i]  =  gs->getPlayer(dst->tempOwner)->resources[i] - (VLC->creh->creatures[crid].cost[i] * cram); | ||||
|  | ||||
| 	SetAvailableCreatures sac; | ||||
| 	sac.tid = objid; | ||||
| 	sac.creatures = t->strInfo.creatures; | ||||
| 	sac.creatures[ser] -= cram; | ||||
| 	sac.creatures = dw->creatures; | ||||
| 	sac.creatures[level].first -= cram; | ||||
|  | ||||
| 	SetGarrisons sg; | ||||
| 	sg.garrs[objid] = t->army; | ||||
| 	if(sg.garrs[objid].slots.find(slot) == sg.garrs[objid].slots.end()) //take a free slot | ||||
| 	sg.garrs[dst->id] = dst->army; | ||||
| 	if(sg.garrs[dst->id].slots.find(slot) == sg.garrs[dst->id].slots.end()) //take a free slot | ||||
| 	{ | ||||
| 		sg.garrs[objid].slots[slot] = std::make_pair(crid,cram); | ||||
| 		sg.garrs[dst->id].slots[slot] = std::make_pair(crid,cram); | ||||
| 	} | ||||
| 	else //add creatures to a already existing stack | ||||
| 	{ | ||||
| 		sg.garrs[objid].slots[slot].second += cram; | ||||
| 		sg.garrs[dst->id].slots[slot].second += cram; | ||||
| 	} | ||||
| 	sendAndApply(&sr);  | ||||
| 	sendAndApply(&sac); | ||||
| @@ -2667,3 +2682,8 @@ bool CGameHandler::isAllowedExchange( int id1, int id2 ) | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| void CGameHandler::objectVisited( const CGObjectInstance * obj, const CGHeroInstance * h ) | ||||
| { | ||||
| 	obj->onHeroVisit(h); | ||||
| } | ||||
| @@ -156,6 +156,7 @@ public: | ||||
| 	void close(); | ||||
| 	void handleTimeEvents(); | ||||
| 	bool complain(const std::string &problem); //sends message to all clients, prints on the logs and return true | ||||
| 	void objectVisited( const CGObjectInstance * obj, const CGHeroInstance * h ); | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user