mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	* fixes for moving War Machines
* automatic merging same creatures stacks if needed when moving hero to town garrison * minor improvements
This commit is contained in:
		| @@ -199,27 +199,28 @@ void AdventureMapButton::hover (bool on) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void AdventureMapButton::activate() | ||||
| { | ||||
| // 	if (active) return; | ||||
| // 	active=true; | ||||
| 	activateLClick(); | ||||
| 	activateRClick(); | ||||
| 	activateHover(); | ||||
| 	activateKeys(); | ||||
| } | ||||
| void AdventureMapButton::deactivate() | ||||
| { | ||||
| // 	if (!active) return; | ||||
| // 	active=false; | ||||
| 	deactivateLClick(); | ||||
| 	deactivateRClick(); | ||||
| 	deactivateHover(); | ||||
| 	deactivateKeys(); | ||||
| } | ||||
| //void AdventureMapButton::activate() | ||||
| //{ | ||||
| //// 	if (active) return; | ||||
| //// 	active=true; | ||||
| //	activateLClick(); | ||||
| //	activateRClick(); | ||||
| //	activateHover(); | ||||
| //	activateKeys(); | ||||
| //} | ||||
| //void AdventureMapButton::deactivate() | ||||
| //{ | ||||
| //// 	if (!active) return; | ||||
| //// 	active=false; | ||||
| //	deactivateLClick(); | ||||
| //	deactivateRClick(); | ||||
| //	deactivateHover(); | ||||
| //	deactivateKeys(); | ||||
| //} | ||||
|  | ||||
| void AdventureMapButton::init(const CFunctionList<void()> &Callback, const std::map<int,std::string> &Name, const std::string &HelpBox, bool playerColoredButton, const std::string &defName, std::vector<std::string> * add, int x, int y, int key) | ||||
| { | ||||
| 	used = LCLICK | RCLICK | HOVER | KEYBOARD; | ||||
| 	callback = Callback; | ||||
| 	blocked = actOnDown = false; | ||||
| 	type=2; | ||||
|   | ||||
| @@ -42,8 +42,8 @@ public: | ||||
| 	int curimg; //curently displayed image from imgs | ||||
| 	virtual void show(SDL_Surface * to); | ||||
| 	virtual void showAll(SDL_Surface * to); | ||||
| 	virtual void activate()=0; | ||||
| 	virtual void deactivate()=0; | ||||
| 	//virtual void activate()=0; | ||||
| 	//virtual void deactivate()=0; | ||||
| 	CButtonBase(); //c-tor | ||||
| 	virtual ~CButtonBase(); //d-tor | ||||
| }; | ||||
| @@ -63,8 +63,8 @@ public: | ||||
| 	virtual void clickLeft(tribool down, bool previousState); | ||||
| 	void hover (bool on); | ||||
| 	void block(ui8 on); //if button is blocked then it'll change it's graphic to inactive (offset==2) and won't react on l-clicks | ||||
| 	void activate(); // makes button active | ||||
| 	void deactivate(); // makes button inactive (but doesn't delete) | ||||
| 	//void activate(); // makes button active | ||||
| 	//void deactivate(); // makes button inactive (but doesn't delete) | ||||
|  | ||||
| 	AdventureMapButton(); //c-tor | ||||
| 	AdventureMapButton( const std::map<int,std::string> &, const std::string &HelpBox, const CFunctionList<void()> &Callback, int x, int y, const std::string &defName, int key=0, std::vector<std::string> * add = NULL, bool playerColoredButton = false );//c-tor | ||||
|   | ||||
| @@ -571,7 +571,7 @@ void CTerrainRect::clickRight(tribool down, bool previousState) | ||||
| 	if(!objs.size()) | ||||
| 		return; | ||||
|  | ||||
| 	const CGObjectInstance * obj = objs.front(); | ||||
| 	const CGObjectInstance * obj = objs.back(); | ||||
| 	switch(obj->ID) | ||||
| 	{ | ||||
| 	case HEROI_TYPE: | ||||
| @@ -1728,6 +1728,8 @@ void CAdvMapInt::centerOn(int3 on) | ||||
| 	LOCPLINT->adventureInt->position = on; | ||||
| 	LOCPLINT->adventureInt->updateScreen=true; | ||||
| 	updateMinimap=true; | ||||
| 	underground.curimg = on.z; //change underground switch button image  | ||||
| 	underground.redraw(); | ||||
| } | ||||
| void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key) | ||||
| { | ||||
|   | ||||
| @@ -270,7 +270,7 @@ void CHeroGSlot::clickLeft(tribool down, bool previousState) | ||||
| 		else if(other->hero && other->highlight) | ||||
| 		{ | ||||
| 			bool allow = true; | ||||
| 			if(upg) //moving hero out of town - check if it is allowed | ||||
| 			if(!upg) //moving hero out of town - check if it is allowed | ||||
| 			{ | ||||
| 				if(!hero && LOCPLINT->cb->howManyHeroes(false) >= 8) | ||||
| 				{ | ||||
| @@ -505,7 +505,7 @@ CCastleInterface::~CCastleInterface() | ||||
| 	SDL_FreeSurface(townInt); | ||||
| 	SDL_FreeSurface(cityBg); | ||||
| 	delete exit; | ||||
| 	delete split; | ||||
| 	//delete split; | ||||
| 	delete hall; | ||||
| 	delete fort; | ||||
| 	delete garr; | ||||
| @@ -749,7 +749,7 @@ void CCastleInterface::showAll( SDL_Surface * to/*=NULL*/) | ||||
| 	if(screen->w != 800 || screen->h !=600) | ||||
| 		CMessage::drawBorder(LOCPLINT->playerID,to,828,628,pos.x-14,pos.y-15); | ||||
| 	exit->show(to); | ||||
| 	split->show(to); | ||||
| 	//split->show(to); | ||||
| } | ||||
|  | ||||
| void CCastleInterface::townChange() | ||||
| @@ -796,7 +796,7 @@ void CCastleInterface::activate() | ||||
| 	garr->activate(); | ||||
| 	LOCPLINT->statusbar = statusbar; | ||||
| 	exit->activate(); | ||||
| 	split->activate(); | ||||
| 	//split->activate(); | ||||
| 	for(size_t i=0;i<buildings.size();i++) //XXX pls use iterators or at() but not [] | ||||
| 	{ | ||||
| 		buildings[i]->activate(); | ||||
| @@ -812,7 +812,7 @@ void CCastleInterface::deactivate() | ||||
| 	townlist->deactivate(); | ||||
| 	garr->deactivate(); | ||||
| 	exit->deactivate(); | ||||
| 	split->deactivate(); | ||||
| 	//split->deactivate(); | ||||
| 	for(size_t i=0;i<buildings.size();i++) //XXX iterators | ||||
| 	{ | ||||
| 		buildings[i]->deactivate(); | ||||
|   | ||||
| @@ -386,6 +386,9 @@ CGarrisonInt::~CGarrisonInt() | ||||
| 		} | ||||
| 		delete sdown; | ||||
| 	} | ||||
|  | ||||
| 	for(size_t i = 0; i<splitButtons.size(); i++) | ||||
| 		delete splitButtons[i]; | ||||
| } | ||||
|  | ||||
| void CGarrisonInt::show(SDL_Surface * to) | ||||
| @@ -459,9 +462,6 @@ void CGarrisonInt::activeteSlots() | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for(size_t i = 0; i<splitButtons.size(); i++) | ||||
| 		splitButtons[i]->activate(); | ||||
| } | ||||
| void CGarrisonInt::createSlots() | ||||
| { | ||||
| @@ -3424,6 +3424,12 @@ void CArtPlace::clickLeft(tribool down, bool previousState) | ||||
| 		{ | ||||
| 			if(ourArt) //to prevent selecting empty slots (bugfix to what GrayFace reported) | ||||
| 			{ | ||||
| 				if(ourArt->id == 3) //catapult cannot be highlighted | ||||
| 				{ | ||||
| 					std::vector<SComponent *> catapult(1, new SComponent(SComponent::artifact, 3, 0)); | ||||
| 					LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[312], catapult); //The Catapult must be equipped. | ||||
| 					return; | ||||
| 				} | ||||
| 				clicked = true; | ||||
| 				ourOwner->commonInfo->activeArtPlace = this; | ||||
| 			} | ||||
| @@ -3432,8 +3438,24 @@ void CArtPlace::clickLeft(tribool down, bool previousState) | ||||
| 		{ | ||||
| 			if(slotID >= 19)	//we are an backpack slot - remove active artifact and put it to the last free pos in backpack | ||||
| 			{					//TODO: putting artifacts in the middle of backpack (pushing following arts) | ||||
| 				 | ||||
| 				LOCPLINT->cb->swapArtifacts(ourOwner->commonInfo->activeArtPlace->ourOwner->curHero, ourOwner->commonInfo->activeArtPlace->slotID, ourOwner->curHero, ourOwner->curHero->artifacts.size()+19); | ||||
| 				const CArtifact *cur = ourOwner->commonInfo->activeArtPlace->ourArt; | ||||
| 				assert(cur); //there is highlighted slot, it must contain an art | ||||
| 				switch(cur->id) | ||||
| 				{ | ||||
| 				case 3: | ||||
| 					//should not happen, catapult cannot be selected | ||||
| 					break; | ||||
| 				case 4: case 5: case 6: | ||||
| 					{ | ||||
| 						std::string text = CGI->generaltexth->allTexts[153]; | ||||
| 						boost::algorithm::replace_first(text, "%s", cur->Name()); | ||||
| 						LOCPLINT->showInfoDialog(text); | ||||
| 					} | ||||
| 					break; | ||||
| 				default: | ||||
| 					LOCPLINT->cb->swapArtifacts(ourOwner->commonInfo->activeArtPlace->ourOwner->curHero, ourOwner->commonInfo->activeArtPlace->slotID, ourOwner->curHero, ourOwner->curHero->artifacts.size()+19); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 			//check if swap is possible | ||||
| 			else if(this->fitsHere(ourOwner->commonInfo->activeArtPlace->ourArt) && ourOwner->commonInfo->activeArtPlace->fitsHere(this->ourArt)) | ||||
| @@ -3495,8 +3517,12 @@ bool CArtPlace::fitsHere(const CArtifact * art) | ||||
| { | ||||
| 	if(!art) | ||||
| 		return true; //you can have no artifact somewhere | ||||
| 	if(slotID > 18   ||   vstd::contains(art->possibleSlots,slotID)) //backpack or right slot | ||||
| 	if(slotID > 18 && art->id >= 3 && art->id <= 6		//everything can bee placed in backpack exept of War Machines | ||||
| 	  || vstd::contains(art->possibleSlots,slotID)) | ||||
| 	{ | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
| CArtPlace::~CArtPlace() | ||||
| @@ -4075,7 +4101,7 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL) | ||||
| 	ourBar = new CStatusBar(pos.x + 3, pos.y + 577, "TSTATBAR.bmp", 726); | ||||
|  | ||||
| 	//garrison interface | ||||
| 	garr = new CGarrisonInt(pos.x + 69, pos.y + 131, 4, Point(418,0), bg, Point(69,131), heroInst[0],heroInst[1], true); | ||||
| 	garr = new CGarrisonInt(pos.x + 69, pos.y + 131, 4, Point(418,0), bg, Point(69,131), heroInst[0],heroInst[1], true, true); | ||||
|  | ||||
| 	garr->splitButtons.push_back(new AdventureMapButton(CGI->generaltexth->tcommands[3],"",boost::bind(&CGarrisonInt::splitClick,garr),pos.x+10,pos.y+132,"TSBTNS.DEF")); | ||||
| 	garr->splitButtons.push_back(new AdventureMapButton(CGI->generaltexth->tcommands[3],"",boost::bind(&CGarrisonInt::splitClick,garr),pos.x+740,pos.y+132,"TSBTNS.DEF")); | ||||
|   | ||||
							
								
								
									
										53
									
								
								int3.h
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								int3.h
									
									
									
									
									
								
							| @@ -15,20 +15,28 @@ | ||||
|  */ | ||||
|  | ||||
| class CCreature; | ||||
|  | ||||
| //a few typedefs for CCreatureSet | ||||
| typedef si32 TSlot, TQuantity; | ||||
| typedef ui32 TCreature; | ||||
| typedef std::pair<TCreature, TQuantity> TStack; | ||||
| typedef std::map<TSlot, TStack> TSlots; | ||||
|  | ||||
| class CCreatureSet //seven combined creatures | ||||
| { | ||||
| public: | ||||
| 	std::map<si32, std::pair<ui32,si32> > slots; //slots[slot_id]=> pair(creature_id,creature_quantity) | ||||
| 	bool formation; //false - wide, true - tight | ||||
| 	bool setCreature (si32 slot, ui32 type, si32 quantity) //slots 0 to 6 | ||||
| 	TSlots slots; //slots[slot_id]=> pair(creature_id,creature_quantity) | ||||
| 	ui8 formation; //false - wide, true - tight | ||||
|  | ||||
| 	bool setCreature (TSlot slot, TCreature type, TQuantity quantity) //slots 0 to 6 | ||||
| 	{ | ||||
| 		slots[slot] = std::pair<ui32, si32>(type, quantity);  //brutal force | ||||
| 		slots[slot] = TStack(type, quantity);  //brutal force | ||||
| 		if (slots.size() > 7) return false; | ||||
| 		else return true; | ||||
| 	} | ||||
| 	si32 getSlotFor(ui32 creature, ui32 slotsAmount=7) const //returns -1 if no slot available | ||||
| 	TSlot getSlotFor(TCreature creature, ui32 slotsAmount=7) const //returns -1 if no slot available | ||||
| 	{	 | ||||
| 		for(std::map<si32,std::pair<ui32,si32> >::const_iterator i=slots.begin(); i!=slots.end(); ++i) | ||||
| 		for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i) | ||||
| 		{ | ||||
| 			if(i->second.first == creature) | ||||
| 			{ | ||||
| @@ -44,6 +52,37 @@ public: | ||||
| 		} | ||||
| 		return -1; //no slot available | ||||
| 	} | ||||
| 	bool mergableStacks(std::pair<TSlot, TSlot> &out, TSlot preferable = -1) //looks for two same stacks, returns slot positions | ||||
| 	{ | ||||
| 		//try to match creature to our preferred stack | ||||
| 		if(preferable >= 0  &&  slots.find(preferable) != slots.end()) | ||||
| 		{ | ||||
| 			TCreature id = slots[preferable].first; | ||||
| 			for(TSlots::const_iterator j=slots.begin(); j!=slots.end(); ++j) | ||||
| 			{ | ||||
| 				if(id == j->second.first) | ||||
| 				{ | ||||
| 					out.first = preferable; | ||||
| 					out.second = j->first; | ||||
| 					return true; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i) | ||||
| 		{ | ||||
| 			for(TSlots::const_iterator j=slots.begin(); j!=slots.end(); ++j) | ||||
| 			{ | ||||
| 				if(i->second.first == j->second.first) | ||||
| 				{ | ||||
| 					out.first = i->first; | ||||
| 					out.second = j->first; | ||||
| 					return true; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return false; | ||||
| 	} | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & slots & formation; | ||||
| @@ -54,7 +93,7 @@ public: | ||||
| 	} | ||||
| 	void sweep() | ||||
| 	{ | ||||
| 		for(std::map<si32,std::pair<ui32,si32> >::iterator i=slots.begin(); i!=slots.end(); ++i) | ||||
| 		for(TSlots::iterator i=slots.begin(); i!=slots.end(); ++i) | ||||
| 		{ | ||||
| 			if(!i->second.second) | ||||
| 			{ | ||||
|   | ||||
| @@ -2097,6 +2097,7 @@ void CGameState::calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int | ||||
| 				|| dp.turns > turn | ||||
| 				|| (dp.turns >= turn  &&  dp.moveRemains < remains)) //this route is faster | ||||
| 			{ | ||||
| 				assert(&dp != cp->theNodeBefore); //two tiles can't point to each other | ||||
| 				dp.moveRemains = remains; | ||||
| 				dp.turns = turn; | ||||
| 				dp.theNodeBefore = cp; | ||||
|   | ||||
| @@ -2162,10 +2162,21 @@ bool CGameHandler::garrisonSwap( si32 tid ) | ||||
| 			int pos = csn.getSlotFor(cso.slots.begin()->second.first); | ||||
| 			if(pos<0) | ||||
| 			{ | ||||
| 				complain("Cannot make garrison swap, not enough free slots!"); | ||||
| 				return false; | ||||
| 				//try to merge two other stacks to make place | ||||
| 				std::pair<TSlot, TSlot> toMerge; | ||||
| 				if(csn.mergableStacks(toMerge, cso.slots.begin()->first)) | ||||
| 				{ | ||||
| 					//merge | ||||
| 					csn.slots[toMerge.second].second += csn.slots[toMerge.first].second; | ||||
| 					csn.slots[toMerge.first] = cso.slots.begin()->second; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					complain("Cannot make garrison swap, not enough free slots!"); | ||||
| 					return false; | ||||
| 				} | ||||
| 			} | ||||
| 			if(csn.slots.find(pos)!=csn.slots.end()) //add creatures to the existing stack | ||||
| 			else if(csn.slots.find(pos) != csn.slots.end()) //add creatures to the existing stack | ||||
| 			{ | ||||
| 				csn.slots[pos].second += cso.slots.begin()->second.second; | ||||
| 			} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user