浏览代码

* town visiting
* improvements in garrisons

Michał W. Urbańczyk 17 年之前
父节点
当前提交
e6de19e17d
共有 11 个文件被更改,包括 154 次插入32 次删除
  1. 59 9
      CCallback.cpp
  2. 7 2
      CCallback.h
  3. 5 1
      CCastleInterface.cpp
  4. 4 2
      CGameInterface.h
  5. 25 1
      CLua.cpp
  6. 12 0
      CLua.h
  7. 4 2
      CMT.cpp
  8. 31 12
      CPlayerInterface.cpp
  9. 5 2
      CPlayerInterface.h
  10. 1 0
      hch/CObjectHandler.cpp
  11. 1 1
      hch/CObjectHandler.h

+ 59 - 9
CCallback.cpp

@@ -126,24 +126,31 @@ bool CCallback::moveHero(int ID, CPath * path, int idtype, int pathType)
 			{
 				curd.successful = true;
 				hero->pos = curd.dst;
-				int heroSight = hero->getSightDistance();
 
+				//inform leaved objects
+				std::vector< CGObjectInstance * > leave = CGI->mh->getVisitableObjs(CHeroInstance::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->ac->map.width)
 					xend = CGI->ac->map.width;
-
 				int ybeg = stpos.y - heroSight - 2;
 				if(ybeg < 0)
 					ybeg = 0;
-
 				int yend = stpos.y + heroSight + 2;
 				if(yend >= CGI->ac->map.height)
 					yend = CGI->ac->map.height;
-
 				for(int xd=xbeg; xd<xend; ++xd) //revealing part of map around heroes
 				{
 					for(int yd=ybeg; yd<yend; ++yd)
@@ -161,6 +168,8 @@ bool CCallback::moveHero(int ID, CPath * path, int idtype, int pathType)
 					}
 				}
 
+
+				//notify interfacesabout move
 				int nn=0; //number of interfece of currently browsed player
 				for(std::map<int, PlayerState>::iterator j=CGI->state->players.begin(); j!=CGI->state->players.end(); ++j)//CGI->state->players.size(); ++j) //for testing
 				{
@@ -172,6 +181,9 @@ bool CCallback::moveHero(int ID, CPath * path, int idtype, int pathType)
 					}
 					++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
@@ -373,10 +385,18 @@ int CCallback::getHeroSerial(const CGHeroInstance * hero)
 	}
 	return -1;
 }
+const CCreatureSet* CCallback::getGarrison(const CGObjectInstance *obj)
+{
+	if(obj->ID == 34)
+		return &(dynamic_cast<const CGHeroInstance*>(obj))->army;
+	else if(obj->ID == 98)
+		return &(dynamic_cast<const CGTownInstance*>(obj)->garrison);
+	else return NULL;
+}
 
-int CCallback::swapCreatures(const CCreatureSet *s1, const CCreatureSet *s2, int p1, int p2)
+int CCallback::swapCreatures(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2)
 {
-	CCreatureSet *S1=const_cast<CCreatureSet *>(s1), *S2 = const_cast<CCreatureSet *>(s2);//todo - ugly
+	CCreatureSet *S1 = const_cast<CCreatureSet*>(getGarrison(s1)), *S2 = const_cast<CCreatureSet*>(getGarrison(s2));
 	if (false)
 	{
 		//TODO: check if we are allowed to swap these creatures
@@ -392,6 +412,15 @@ int CCallback::swapCreatures(const CCreatureSet *s1, const CCreatureSet *s2, int
 			int pom2 = S2->slots[p2].second;
 			S2->slots[p2].second = S1->slots[p1].second;
 			S1->slots[p1].second = pom2;
+
+			if(!S1->slots[p1].first)
+				S1->slots.erase(p1);
+			if(!S2->slots[p2].first)
+				S2->slots.erase(p2);
+			if(s1->tempOwner<PLAYER_LIMIT)
+				CGI->playerint[s1->tempOwner]->garrisonChanged(s1);
+			if(s2->tempOwner<PLAYER_LIMIT)
+				CGI->playerint[s2->tempOwner]->garrisonChanged(s2);
 		}
 	}
 	return -1;
@@ -519,7 +548,29 @@ void CScriptCallback::showCompInfo(int player, SComponent * comp)
 	if(i)
 		i->showComp(*comp);
 }
+void CScriptCallback::heroVisitCastle(CGObjectInstance * ob, int heroID)
+{
+	CGTownInstance * n;
+	if(n = dynamic_cast<CGTownInstance*>(ob))
+	{
+		n->visitingHero = CGI->state->getHero(heroID,0);
+		CGI->playerint[getHeroOwner(heroID)]->heroVisitsTown(CGI->state->getHero(heroID,0),n);
+	}
+	else
+		return;
+}
 
+void CScriptCallback::stopHeroVisitCastle(CGObjectInstance * ob, int heroID)
+{
+	CGTownInstance * n;
+	if(n = dynamic_cast<CGTownInstance*>(ob))
+	{
+		if(n->visitingHero->type->ID == heroID)
+			n->visitingHero = NULL;
+	}
+	else
+		return;
+}
 void CLuaCallback::registerFuncs(lua_State * L)
 {
 	lua_newtable(L);
@@ -544,8 +595,7 @@ void CLuaCallback::registerFuncs(lua_State * L)
 	
 
 	lua_setglobal(L, "vcmi");
-	#undef REGISTER_C_FUNC(x)
-
+	#undef REGISTER_C_FUNC
 }
 int CLuaCallback::getPos(lua_State * L)//(CGObjectInstance * object);
 {	

+ 7 - 2
CCallback.h

@@ -34,8 +34,9 @@ public:
 	virtual int getMyColor()=0;
 	virtual int getMySerial()=0;
 	virtual int getHeroSerial(const CGHeroInstance * hero)=0;
-	virtual int swapCreatures(const CCreatureSet *s1, const CCreatureSet *s2, int p1, int p2)=0;//swaps creatures between two posiibly different garrisons // TODO: AI-unsafe code - fix it!
+	virtual int swapCreatures(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2)=0;//swaps creatures between two posiibly different garrisons // TODO: AI-unsafe code - fix it!
 	virtual bool dismissHero(const CGHeroInstance * hero)=0; //dismisses diven hero; true - successfuly, false - not successfuly
+	virtual const CCreatureSet* getGarrison(const CGObjectInstance *obj)=0;
 };
 
 struct HeroMoveDetails
@@ -80,8 +81,9 @@ public:
 	int getMyColor();
 	int getHeroSerial(const CGHeroInstance * hero);
 	int getMySerial();
-	int swapCreatures(const CCreatureSet *s1, const CCreatureSet *s2, int p1, int p2);
+	int swapCreatures(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2);
 	bool dismissHero(const CGHeroInstance * hero);
+	const CCreatureSet* getGarrison(const CGObjectInstance *obj);
 
 //friends
 	friend int _tmain(int argc, _TCHAR* argv[]);
@@ -103,6 +105,9 @@ public:
 	void showSelDialog(int player, std::string text, std::vector<CSelectableComponent*>*components, IChosen * asker);
 	void giveResource(int player, int which, int val);
 	void showCompInfo(int player, SComponent * comp);
+	void heroVisitCastle(CGObjectInstance * ob, int heroID);
+	void stopHeroVisitCastle(CGObjectInstance * ob, int heroID);
+
 
 	//friends
 	friend void initGameState(CGameInfo * cgi);

+ 5 - 1
CCastleInterface.cpp

@@ -168,6 +168,8 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, bool Activate)
 	statusbar = new CStatusBar(8,555,"TSTATBAR.bmp",732);
 	std::set< std::pair<int,int> > s; //group - id
 
+
+	//buildings
 	for (std::set<int>::const_iterator i=town->builtBuildings.begin();i!=town->builtBuildings.end();i++)
 	{
 		if(CGI->townh->structures.find(town->subID) != CGI->townh->structures.end()) //we have info about structures in this town
@@ -218,8 +220,10 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, bool Activate)
 			break;
 	}
 
+
+	//garrison
 	std::sort(buildings.begin(),buildings.end(),srthlp);
-	garr = new CGarrisonInt(305,387,4,32,townInt,243,13,&town->garrison,(town->garrisonHero)?(&town->garrisonHero->army):(NULL));
+	garr = new CGarrisonInt(305,387,4,32,townInt,243,13,town,town->visitingHero);
 
 	if(Activate)
 	{

+ 4 - 2
CGameInterface.h

@@ -21,10 +21,12 @@ public:
 	virtual void heroCreated(const CGHeroInstance*)=0{};
 	virtual void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, int val)=0{};
 	virtual void heroMoved(const HeroMoveDetails & details)=0{};
-	virtual void tileRevealed(int3 pos)=0{};
-	virtual void tileHidden(int3 pos)=0{};
+	virtual void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town){};
+	virtual void tileRevealed(int3 pos){};
+	virtual void tileHidden(int3 pos){};
 	virtual void receivedResource(int type, int val){};
 	virtual void showSelDialog(std::string text, std::vector<CSelectableComponent*> & components, int askID)=0{};
+	virtual void garrisonChanged(const CGObjectInstance * obj){};
 };
 class CAIHandler
 {

+ 25 - 1
CLua.cpp

@@ -12,6 +12,7 @@
 #include "CGameState.h"
 #include <sstream>
 #include "hch/CObjectHandler.h"
+#include "hch/CTownHandler.h"
 #include "CCallback.h"
 #include "hch/CGeneralTextHandler.h"
 #include <sstream>
@@ -589,4 +590,27 @@ std::vector<int> CPickable::yourObjects() //returns IDs of objects which are han
 	ret.push_back(5); //artifact
 	ret.push_back(101); //treasure chest / commander stone
 	return ret;
-}
+}
+
+void CTownScript::onHeroVisit(CGObjectInstance *os, int heroID)
+{
+	cb->heroVisitCastle(os,heroID);
+}
+void CTownScript::onHeroLeave(CGObjectInstance *os, int heroID)
+{
+	cb->stopHeroVisitCastle(os,heroID);
+}
+std::string CTownScript::hoverText(CGObjectInstance *os)
+{
+	CGTownInstance * n;
+	if(n = dynamic_cast<CGTownInstance*>(os))
+		return n->name + ", " + n->town->name;
+	else return "";
+}
+
+std::vector<int> CTownScript::yourObjects() //returns IDs of objects which are handled by script
+{
+	std::vector<int> ret(1);
+	ret.push_back(98); //town
+	return ret;
+}

+ 12 - 0
CLua.h

@@ -26,6 +26,7 @@ public:
 	//virtual void init(){};
 	virtual void newObject(CGObjectInstance *os){};
 	virtual void onHeroVisit(CGObjectInstance *os, int heroID){};
+	virtual void onHeroLeave(CGObjectInstance *os, int heroID){};
 	virtual std::string hoverText(CGObjectInstance *os){return "";};
 	virtual void newTurn (){}; 
 
@@ -148,5 +149,16 @@ class CPickable : public CCPPObjectScript, public IChosen  //pickable - resource
 	std::string hoverText(CGObjectInstance *os);
 	std::vector<int> yourObjects(); //returns IDs of objects which are handled by script
 
+	friend void initGameState(CGameInfo * cgi);
+};
+
+class CTownScript : public CCPPObjectScript  //pickable - resources, artifacts, etc
+{
+	CTownScript(CScriptCallback * CB):CCPPObjectScript(CB){};
+	void onHeroVisit(CGObjectInstance *os, int heroID);
+	void onHeroLeave(CGObjectInstance *os, int heroID);
+	std::string hoverText(CGObjectInstance *os);
+	std::vector<int> yourObjects(); //returns IDs of objects which are handled by script
+
 	friend void initGameState(CGameInfo * cgi);
 };

+ 4 - 2
CMT.cpp

@@ -188,8 +188,9 @@ void initGameState(CGameInfo * cgi)
 	/****************************TOWNS************************************************/
 	for (int i=0;i<cgi->townh->townInstances.size();i++)
 	{
-		CGTownInstance * vti = new CGTownInstance();
-		(*vti)=*(cgi->townh->townInstances[i]);
+		//CGTownInstance * vti = new CGTownInstance();
+		//(*vti)=*(cgi->townh->townInstances[i]);
+		CGTownInstance * vti =(cgi->townh->townInstances[i]);
 		vti->creatureIncome.resize(CREATURES_PER_TOWN);
 		vti->creaturesLeft.resize(CREATURES_PER_TOWN);
 		if (vti->name.length()==0) // if town hasn't name we draw it
@@ -226,6 +227,7 @@ void initGameState(CGameInfo * cgi)
 	handleCPPObjS(&scripts,new CVisitableOPW(csc));
 	handleCPPObjS(&scripts,new CPickable(csc));
 	handleCPPObjS(&scripts,new CMines(csc));
+	handleCPPObjS(&scripts,new CTownScript(csc));
 	//created map
 
 	/****************************LUA OBJECT SCRIPTS************************************************/

+ 31 - 12
CPlayerInterface.cpp

@@ -47,8 +47,8 @@ void CGarrisonSlot::clickLeft(tribool down)
 		if(owner->highlighted)
 		{
 			LOCPLINT->cb->swapCreatures(
-				(!upg)?(owner->set1):(owner->set2),
-				(!owner->highlighted->upg)?(owner->set1):(owner->set2),
+				(!upg)?(owner->oup):(owner->odown),
+				(!owner->highlighted->upg)?(owner->oup):(owner->odown),
 				ID,owner->highlighted->ID);
 			owner->highlighted = NULL;
 			owner->recreateSlots();
@@ -71,9 +71,9 @@ void CGarrisonSlot::deactivate()
 	ClickableR::deactivate();
 	Hoverable::deactivate();
 }
-CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, const CCreature * Creature, int Count)
+CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg, const CCreature * Creature, int Count)
 {
-	upg = 0;
+	upg = Upg;
 	count = Count;
 	ID = IID;
 	creature = Creature;
@@ -190,11 +190,11 @@ void CGarrisonInt::createSlots()
 			i!=set1->slots.end(); i++)
 		{
 			(*sup)[i->first] = 
-				new CGarrisonSlot(this, pos.x + (i->first*(58+interx)), pos.y,i->first, i->second.first,i->second.second);
+				new CGarrisonSlot(this, pos.x + (i->first*(58+interx)), pos.y,i->first, 0, i->second.first,i->second.second);
 		}
 		for(int i=0; i<sup->size(); i++)
 			if((*sup)[i] == NULL)
-				(*sup)[i] = new CGarrisonSlot(this, pos.x + (i*(58+interx)), pos.y,i, NULL, 0);
+				(*sup)[i] = new CGarrisonSlot(this, pos.x + (i*(58+interx)), pos.y,i,0,NULL, 0);
 	}
 	if(set2)
 	{	
@@ -204,11 +204,11 @@ void CGarrisonInt::createSlots()
 			i!=set2->slots.end(); i++)
 		{
 			(*sdown)[i->first] = 
-				new CGarrisonSlot(this, pos.x + (i->first*(58+interx)), pos.y + 64 + intery,i->first, i->second.first,i->second.second);
+				new CGarrisonSlot(this, pos.x + (i->first*(58+interx)), pos.y + 64 + intery,i->first,1, i->second.first,i->second.second);
 		}
 		for(int i=0; i<sup->size(); i++)
 			if((*sdown)[i] == NULL)
-				(*sdown)[i] = new CGarrisonSlot(this, pos.x + (i*(58+interx)), pos.y,i, NULL, 0);
+				(*sdown)[i] = new CGarrisonSlot(this, pos.x + (i*(58+interx)), pos.y + 64 + intery,i,1, NULL, 0);
 	}
 }
 void CGarrisonInt::deleteSlots()
@@ -243,11 +243,12 @@ void CGarrisonInt::recreateSlots()
 	activeteSlots();
 	show();
 }
-CGarrisonInt::CGarrisonInt(int x, int y, int inx, int iny, SDL_Surface *pomsur, int OX, int OY, const CCreatureSet * s1, const CCreatureSet *s2)
-	:interx(inx),intery(iny),sur(pomsur),highlighted(NULL),sup(NULL),sdown(NULL),set1(s1),set2(s2),
+CGarrisonInt::CGarrisonInt(int x, int y, int inx, int iny, SDL_Surface *pomsur, int OX, int OY, const CGObjectInstance *s1, const CGObjectInstance *s2)
+	:interx(inx),intery(iny),sur(pomsur),highlighted(NULL),sup(NULL),sdown(NULL),oup(s1),odown(s2),
 	offx(OX),offy(OY)
 {
-	
+	set1 = LOCPLINT->cb->getGarrison(s1);
+	set2 = LOCPLINT->cb->getGarrison(s2);
 	ignoreEvent = false;
 	pos.x=(x);
 	pos.y=(y);
@@ -1796,7 +1797,25 @@ void CPlayerInterface::showSelDialog(std::string text, std::vector<CSelectableCo
 	temp->ID = askID;
 	components[0]->clickLeft(true);
 }
-
+void CPlayerInterface::heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town)
+{
+	openTownWindow(town);
+}
+void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
+{
+	if(obj->ID == 34) //hero
+	{
+		const CGHeroInstance * hh;
+		if(hh = dynamic_cast<const CGHeroInstance*>(obj))
+		{
+			SDL_FreeSurface(heroWins[hh->subID]);
+			heroWins[hh->subID] = infoWin(hh);
+		}
+	}
+	else if (obj->ID == 98) //town
+	{
+	}
+}
 void CPlayerInterface::showComp(SComponent comp)
 {
 	adventureInt->infoBar.showComp(&comp,4000);

+ 5 - 2
CPlayerInterface.h

@@ -204,7 +204,7 @@ public:
 	void activate();
 	void deactivate();
 	void show();
-	CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, const CCreature * Creature=NULL, int Count=0);
+	CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg=0, const CCreature * Creature=NULL, int Count=0);
 };
 
 class CGarrisonInt :public CIntObject
@@ -221,6 +221,7 @@ public:
 	const CCreatureSet *set2;
 
 	std::vector<CGarrisonSlot*> *sup, *sdown;
+	const CGObjectInstance *oup, *odown;
 
 	void activate();
 	void deactivate();
@@ -231,7 +232,7 @@ public:
 	void createSlots();
 	void recreateSlots();
 
-	CGarrisonInt(int x, int y, int inx, int iny, SDL_Surface *pomsur, int OX, int OY, const CCreatureSet * s1, const CCreatureSet *s2=NULL);
+	CGarrisonInt(int x, int y, int inx, int iny, SDL_Surface *pomsur, int OX, int OY, const CGObjectInstance *s1, const CGObjectInstance *s2=NULL);
 	~CGarrisonInt();
 };
 
@@ -274,6 +275,8 @@ public:
 	void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, int val);
 	void receivedResource(int type, int val);
 	void showSelDialog(std::string text, std::vector<CSelectableComponent*> & components, int askID);
+	void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town);
+	void garrisonChanged(const CGObjectInstance * obj);
 
 	void showComp(SComponent comp);
 

+ 1 - 0
hch/CObjectHandler.cpp

@@ -280,6 +280,7 @@ CGTownInstance::CGTownInstance()
 	//state->owner=-1;
 	town=NULL;
 	income = 500;
+	visitingHero = NULL;
 }
 
 CGObjectInstance::CGObjectInstance()

+ 1 - 1
hch/CObjectHandler.h

@@ -442,7 +442,7 @@ public:
 	std::vector<int> creatureIncome; //vector by level
 	std::vector<int> creaturesLeft; //that can be recruited
 
-	CGHeroInstance * garrisonHero;
+	const CGHeroInstance * garrisonHero, *visitingHero;
 
 	std::vector<CSpell *> possibleSpells, obligatorySpells, availableSpells;