浏览代码

- part of castle gate handling (need to make server-client interaction)
- minor fixes ( 361, 507, 466 )

Ivan Savenko 15 年之前
父节点
当前提交
2a99bc76da
共有 6 个文件被更改,包括 208 次插入8 次删除
  1. 35 7
      client/CCastleInterface.cpp
  2. 2 1
      client/CCastleInterface.h
  3. 129 0
      client/GUIClasses.cpp
  4. 31 0
      client/GUIClasses.h
  5. 1 0
      config/buildings.txt
  6. 10 0
      lib/map.cpp

+ 35 - 7
client/CCastleInterface.cpp

@@ -618,7 +618,8 @@ void CCastleInterface::buildingClicked(int building)
 				break;
 			}
 		case 10: case 11: case 12: case 13: //hall
-			if(town->visitingHero && town->visitingHero->hasArt(2)) //hero has grail
+			if(town->visitingHero && town->visitingHero->hasArt(2) &&
+					!vstd::contains(town->builtBuildings, 26)) //hero has grail, but town does not have it
 			{
 				if(!vstd::contains(town->forbiddenBuildings, 26))
 				{
@@ -700,9 +701,30 @@ void CCastleInterface::buildingClicked(int building)
 					enterTavern();
 					break;
 	/*Inferno*/		case 3: //Castle Gate
-					tlog4<<"Castle Gate not handled\n";
-					break;
-	/*Necropolis*/		case 4: //Skeleton Transformer
+						{
+							std::vector <int> availableTowns;
+							std::vector <const CGTownInstance*> Towns = LOCPLINT->cb->getTownsInfo(false);
+							for(size_t i=0;i<Towns.size();i++)
+							{
+								const CGTownInstance *t = Towns[i];
+								if (t->id != this->town->id && t->visitingHero == NULL && //another town, empty and this is
+									t->subID == 3 && vstd::contains(t->builtBuildings, 26))//inferno with castle gate
+								{
+									availableTowns.push_back(t->id);//add to the list
+								}
+							}
+							if (!town->visitingHero)
+							{
+								LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[126], std::vector<SComponent*>(), soundBase::sound_todo);
+								break;//only visiting hero can use castle gates
+							}
+							tlog4<<"Warning: implementation is unfinished\n";
+							CPicture *titlePic = new CPicture (bicons->ourImages[building].bitmap, 0,0, false);
+							GH.pushInt (new CObjectListWindow(availableTowns, titlePic, CGI->generaltexth->jktexts[40],
+							    CGI->generaltexth->jktexts[41], boost::bind (&CCastleInterface::castleTeleport, this, _1)));
+							break;
+						}
+	/*Necropolis*/	case 4: //Skeleton Transformer
 					tlog4<<"Skeleton Transformer not handled\n";
 					break;
 	/*Dungeon*/		case 5: //Portal of Summoning
@@ -727,6 +749,14 @@ void CCastleInterface::buildingClicked(int building)
 		}
 	}
 }
+
+void CCastleInterface::castleTeleport(int where)
+{
+	//TODO: send message to move hero,
+	//find a way to do this without new message type
+	//and update interface
+}
+
 void CCastleInterface::defaultBuildingClicked(int building)
 {
 	std::vector<SComponent*> comps(1,
@@ -829,7 +859,7 @@ void CCastleInterface::townChange()
 void CCastleInterface::show(SDL_Surface * to)
 {
 	count++;
-	if(count==8)
+	if(count==5)
 	{
 		count=0;
 		animval++;
@@ -1173,7 +1203,6 @@ void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
 				CGI->creh->creatures[crid]->hordeGrowth);
 
 		cnt = 0;
-		int creaLevel = (bid-30)%CREATURES_PER_TOWN;//dwellings have unupgraded units
 
 		for (std::vector<CGDwelling*>::const_iterator it = CGI->state->players[ci->town->tempOwner].dwellings.begin();
 			it !=CGI->state->players[ci->town->tempOwner].dwellings.end(); ++it)
@@ -1224,7 +1253,6 @@ CCastleInterface::CTownInfo::~CTownInfo()
 CCastleInterface::CTownInfo::CTownInfo(int BID)
 {
 	used = LCLICK | RCLICK | HOVER;
-	int pom=0;
 	CCastleInterface * ci=LOCPLINT->castleInt;
 	switch (BID)
 	{

+ 2 - 1
client/CCastleInterface.h

@@ -50,6 +50,7 @@ public:
 	void clickRight(tribool down, bool previousState);
 	void mouseMoved (const SDL_MouseMotionEvent & sEvent);
 };
+
 class CHeroGSlot : public CIntObject
 {
 public:
@@ -97,7 +98,6 @@ class CCastleInterface : public CWindowWithGarrison
 		void show(SDL_Surface * to);
 	};
 public:
-	SDL_Rect pos; //why not inherit this member from CIntObject ?
 	bool showing; //indicates if interface is active
 	CBuildingRect * hBuild; //highlighted building
 	SDL_Surface * townInt;
@@ -125,6 +125,7 @@ public:
 	CCastleInterface(const CGTownInstance * Town, int listPos = 1); //c-tor
 	~CCastleInterface(); //d-tor
 
+	void castleTeleport(int where);
 	void townChange();
 	void keyPressed(const SDL_KeyboardEvent & key);
 	void show(SDL_Surface * to);

+ 129 - 0
client/GUIClasses.cpp

@@ -2581,6 +2581,135 @@ CCustomImgComponent::~CCustomImgComponent()
 		SDL_FreeSurface(bmp);
 }
 
+CObjectListWindow::CObjectListWindow(const std::vector<int> &_items, CPicture * titlePic, std::string _title, std::string _descr,
+				boost::function<void(int)> Callback, int initState):items(_items), title(_title), descr(_descr),selected(initState)
+{
+	init = false;
+	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	defActions = ACTIVATE | DEACTIVATE | UPDATE | SHOWALL | DISPOSE | SHARE_POS;
+	used = LCLICK | KEYBOARD;
+	
+	onSelect = Callback;
+	length = 9;
+	pos.x = (screen->w-306)/2;
+	pos.y = (screen->h-468)/2;
+	
+	bg = new CPicture("TPGATE.pcx");//x=0, y=0
+	bg->colorizeAndConvert(LOCPLINT->playerID);
+	
+	slider = new CSlider(277, 120, 256, boost::bind(&CObjectListWindow::moveList,this, _1), length, items.size(), 0, false, 0);
+	ok = new AdventureMapButton("","",boost::bind(&CObjectListWindow::elementSelected, this),15,402,"IOKAY.DEF", SDLK_RETURN);
+	exit = new AdventureMapButton("","",boost::bind(&CGuiHandler::popIntTotally,&GH, this),228,402,"ICANCEL.DEF",SDLK_ESCAPE);
+	pos.w = bg->pos.w;
+	pos.h = bg->pos.h;
+	titleImage = titlePic;
+	titleImage->pos.x =153+pos.x-titleImage->pos.w/2;
+	titleImage->pos.y =75 +pos.y-titleImage->pos.h/2;
+	
+	for (int i=0; i<length; i++)
+		areas.push_back(genRect(22, 260, pos.x+15, pos.y+152+i*25 ));//rects for selecting\printing items
+	init = true;
+}
+
+CObjectListWindow::~CObjectListWindow()
+{
+	delete titleImage;
+}
+
+void CObjectListWindow::elementSelected()
+{
+	onSelect(items[slider->value]);
+	GH.popIntTotally(this);
+}
+
+void CObjectListWindow::moveList(int which)
+{
+	if (init)//TODO: is there a way to disable running this when CSlider is created?
+		showAll(screen2);
+}
+
+void CObjectListWindow::clickLeft(tribool down, bool previousState)
+{
+	if (previousState && (!down))
+	{
+		for (int i=0; i<areas.size(); i++)
+			if(slider->value+i < items.size() && isItIn(&areas[i],GH.current->motion.x,GH.current->motion.y))
+			{//check all areas to find element which was clicked
+				selected = i+slider->value;
+				showAll(screen2);
+				return;
+			}
+	}
+}
+
+void CObjectListWindow::keyPressed (const SDL_KeyboardEvent & key)
+{
+	if(key.state != SDL_PRESSED) return;
+
+	int sel = selected;
+
+	switch(key.keysym.sym)
+	{
+	case SDLK_UP:	
+					sel -=1;
+					break;
+	case SDLK_DOWN:
+					sel +=1;
+					break;
+	case SDLK_PAGEUP:
+					sel -=length;
+					break;
+	case SDLK_PAGEDOWN:
+					sel +=length;
+					break;
+	case SDLK_HOME:
+					sel = 0;
+					break;
+	case SDLK_END:
+					sel = slider->amount;
+					break;
+	default:
+		return;
+	}
+	if (sel<0)//start of list reached
+		sel = 0;
+	else if ( sel >= slider->amount )//end of list reached
+		sel = slider->amount-1;
+	if ( sel >= items.size() )
+		sel = items.size()-1;
+	if ( sel < slider->value )//need to move list up
+		slider->moveTo(sel);
+	else 
+	if ( sel >= slider->value+length )//move to bottom
+		slider->moveTo(sel-length+1);
+	selected = sel;
+	showAll(screen2);
+}
+
+void CObjectListWindow::show(SDL_Surface * to)
+{
+	
+}
+
+void CObjectListWindow::showAll(SDL_Surface * to)
+{
+	ok->block((selected<0)?2:0);
+	CIntObject::showAll(to);
+	CSDL_Ext::printAtMiddle(title,pos.x+152,pos.y+27,FONT_BIG,tytulowy,to);//"castle gate"
+	CSDL_Ext::printAtMiddle(descr,pos.x+145,pos.y+133,FONT_SMALL,zwykly,to);//"select destination"
+	titleImage->showAll(to);
+	if ( selected >= slider->value && selected < slider->value+length )//if selected item is visible 
+	{
+		SDL_Rect a = areas[selected-slider->value];
+		CSDL_Ext::drawBorder(to, a.x,   a.y,   a.w,   a.h,   int3(255, 231, 148));
+		CSDL_Ext::drawBorder(to, a.x-1, a.y-1, a.w+2, a.h+2, int3(255, 231, 148));//border shoul be 2 pixels width
+	}
+	int position = slider->value;
+	for ( int i = 0; i<9 && i<items.size()-position; i++)
+		CSDL_Ext::printAtMiddle(CGI->mh->map->objects[items[i+position]]->hoverName,pos.x+145,pos.y+163+25*i,
+			FONT_SMALL, zwykly, to);//print item names in list
+}
+
 CMarketplaceWindow::CTradeableItem::CTradeableItem( EType Type, int ID, bool Left, int Serial)
 {
 	serial = Serial;

+ 31 - 0
client/GUIClasses.h

@@ -516,6 +516,37 @@ public:
 	~CMinorResDataBar(); //d-tor
 };
 
+class CObjectListWindow : public CIntObject
+{
+public:
+
+	boost::function<void(int)> onSelect;//called when OK button is pressed, returns id of selected item.
+	std::string title,descr;//text for title and description
+
+	CPicture *bg; //background
+	CSlider *slider;
+	CPicture *titleImage;//title image (castle gate\town portal picture)
+	AdventureMapButton *ok, *exit;
+
+	std::vector<Rect> areas;//areas for each visible item
+	std::vector<int> items;//id of all items present in list
+	int selected;//currently selected item
+	int length;//size of list (=9)
+	bool init;//true = initialization completed
+
+	/// Callback will be called when OK button is pressed, returns id of selected item. initState = initially selected item
+	CObjectListWindow(const std::vector<int> &_items, CPicture * titlePic, std::string _title, std::string _descr,
+                      boost::function<void(int)> Callback, int initState=-1); //c-tor
+	~CObjectListWindow(); //d-tor
+
+	void elementSelected();//call callback and exit
+	void moveList(int which);//called when slider moves
+	void clickLeft(tribool down, bool previousState);  //call-in
+	void keyPressed (const SDL_KeyboardEvent & key);  //call-in
+	void show(SDL_Surface * to);
+	void showAll(SDL_Surface * to);
+};
+
 class CMarketplaceWindow : public CIntObject
 {
 	bool printButtonFor(EMarketMode M) const;

+ 1 - 0
config/buildings.txt

@@ -12,6 +12,7 @@
 0 36 TBCSDW_6.def 303 0
 0 21 TBCSEXT0.def 384 193
 0 22 TBCSEXT1.def 0 198
+0 -1 TBCSEXT2.def 46 119
 0 11 TBCSHAL2.def 0 176
 0 12 TBCSHAL3.def 0 164
 0 13 TBCSHAL4.def 0 154

+ 10 - 0
lib/map.cpp

@@ -32,6 +32,16 @@ static std::set<si32> convertBuildings(const std::set<si32> h3m, int castleID)
 		b5 >> a >> b;
 		if(castleID==8 && b==17) //magic university ID 17 (h3m) => 21 (vcmi)
 			b=21;
+		if(castleID==4 && a==20) //necropolis, skeleton transformer
+			b=22;
+		if(castleID==4 && a==19) //necropolis, necromancy aplifier
+			b=21;
+		if(castleID==3 && a==18) //inferno, brimstone clouds
+			b=21;
+		if(castleID==3 && a==20) //inferno, order of fire
+			b=23;
+		if(castleID==8 && a==10) //conflux, artifact merchant
+			b=17;
 		mapa[a]=b;
 	}