Browse Source

Recruitment should work (todo - growths, counting remaining creatures)

Michał W. Urbańczyk 17 years ago
parent
commit
ffc93639ab
12 changed files with 123 additions and 34 deletions
  1. 55 2
      CCallback.cpp
  2. 8 5
      CCallback.h
  3. 6 3
      CCastleInterface.cpp
  4. 2 1
      CCastleInterface.h
  5. 3 3
      CMT.cpp
  6. 2 2
      CMessage.cpp
  7. 24 6
      CPlayerInterface.cpp
  8. 12 2
      CPlayerInterface.h
  9. 0 2
      hch/CAmbarCendamo.cpp
  10. 1 1
      hch/CCreatureHandler.h
  11. 7 2
      hch/CObjectHandler.cpp
  12. 3 5
      hch/CObjectHandler.h

+ 55 - 2
CCallback.cpp

@@ -246,6 +246,59 @@ void CCallback::selectionMade(int selection, int asker)
 	IChosen * ask = (IChosen *)asker;
 	ask->chosen(selection);
 }
+void CCallback::recruitCreatures(const CGObjectInstance *obj, int ID, int amount)
+{
+	if(amount<=0) return;
+	if(obj->ID==98)
+	{
+		CGTownInstance *t = const_cast<CGTownInstance*>(static_cast<const CGTownInstance*>(obj));
+
+		//verify
+		bool found = false;
+		typedef std::pair<const int,int> Parka;
+		for(std::map<int,int>::iterator av=t->strInfo.creatures.begin();av!=t->strInfo.creatures.end();av++)
+		{
+			if(	(   found  = (ID == t->town->basicCreatures[av->first])   )
+				|| (found  = (ID == t->town->upgradedCreatures[av->first]))			)
+			{
+				amount = std::min(amount,av->second);
+				break;
+			}
+		}
+		if(!found)	//no such creature
+			return;
+
+		for(int i=0;i<RESOURCE_QUANTITY;i++)
+			if (gs->players[player].resources[i]  <  (CGI->creh->creatures[ID].cost[i] * amount))
+				return; //not enough resources
+
+		if(amount<=0) return;
+
+		//recruit
+		int slot = -1;
+		std::pair<int,std::pair<CCreature*,int> > parb;	
+
+		for(int i=0;i<7;i++)
+		{
+			if(!t->army.slots[i].first)
+			{
+				slot = i;
+				break;
+			}
+		}
+
+		if(slot<0) //no free slot
+			return;
+
+		for(int i=0;i<RESOURCE_QUANTITY;i++)
+			gs->players[player].resources[i]  -=  (CGI->creh->creatures[ID].cost[i] * amount);
+		
+		t->army.slots[slot].first = &CGI->creh->creatures[ID];
+		t->army.slots[slot].second = amount;
+		CGI->playerint[gs->players[player].serial]->garrisonChanged(obj);
+
+	}
+}
 
 int CCallback::howManyTowns()
 {
@@ -618,7 +671,7 @@ CCreature CCallback::battleGetCreature(int number)
 		if(CGI->state->curB->stacks[h]->ID == number) //creature found
 			return *(CGI->state->curB->stacks[h]->creature);
 	}
-	return CCreature();
+	throw new std::exception("Cannot find the creature");
 }
 
 bool CCallback::battleMoveCreature(int ID, int dest)
@@ -892,4 +945,4 @@ int CLuaCallback::getSelectedHero(lua_State * L) //(),returns int (ID of hero, -
 		ret = -1;
 	lua_pushinteger(L,ret);
 	return 1;
-}
+}

+ 8 - 5
CCallback.h

@@ -19,6 +19,12 @@ class ICallback
 public:
 	virtual bool moveHero(int ID, CPath * path, int idtype, int pathType=0)=0;//idtype: 0 - position in vector of heroes (of that player); 1 - ID of hero 
 															//pathType: 0 - nodes are manifestation pos, 1 - nodes are object pos
+	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 int mergeStacks(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2)=0;//joins first stack tothe second (creatures must be same type)
+	virtual int splitStack(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2, int val)=0;//split creatures from the first stack
+	virtual bool dismissHero(const CGHeroInstance * hero)=0; //dismisses diven hero; true - successfuly, false - not successfuly
+	virtual bool swapArifacts(const CGHeroInstance * hero1, bool worn1, int pos1, const CGHeroInstance * hero2, bool worn2, int pos2)=0; //swaps artifacts between two given heroes
+	virtual void recruitCreatures(const CGObjectInstance *obj, int ID, int amount)=0;
 
 //get info
 	virtual bool verifyPath(CPath * path, bool blockSea)=0;
@@ -35,12 +41,7 @@ public:
 	virtual int getMyColor()=0;
 	virtual int getMySerial()=0;
 	virtual int getHeroSerial(const CGHeroInstance * hero)=0;
-	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 int mergeStacks(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2)=0;//joins first stack tothe second (creatures must be same type)
-	virtual int splitStack(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2, int val)=0;//split creatures from the first stack
-	virtual bool dismissHero(const CGHeroInstance * hero)=0; //dismisses diven hero; true - successfuly, false - not successfuly
 	virtual const CCreatureSet* getGarrison(const CGObjectInstance *obj)=0;
-	virtual bool swapArifacts(const CGHeroInstance * hero1, bool worn1, int pos1, const CGHeroInstance * hero2, bool worn2, int pos2)=0; //swaps artifacts between two given heroes
 };
 
 struct HeroMoveDetails
@@ -69,6 +70,8 @@ public:
 	bool moveHero(int ID, CPath * path, int idtype, int pathType=0);//idtype: 0 - position in vector of heroes (of that player); 1 - ID of hero 
 															//pathType: 0 - nodes are manifestation pos, 1 - nodes are object pos
 	void selectionMade(int selection, int asker);
+	void recruitCreatures(const CGObjectInstance *obj, int ID, int amount);
+
 
 //get info
 	bool verifyPath(CPath * path, bool blockSea);

+ 6 - 3
CCastleInterface.cpp

@@ -322,7 +322,7 @@ void CCastleInterface::buildingClicked(int building)
 
 		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));
-		CRecrutationWindow *rw = new CRecrutationWindow(crs);
+		CRecrutationWindow *rw = new CRecrutationWindow(crs,this);
 		rw->activate();
 	}
 	switch(building)
@@ -392,7 +392,7 @@ void CCastleInterface::showAll(SDL_Surface * to)
 			pomy = (i>3)?(507):(459);
 			blitAt(CGI->creh->smallImgs[cid],pomx,pomy,to);
 			std::ostringstream oss;
-			oss << '+' << (CGI->creh->creatures[cid].growth + town->creatureIncome[i]);
+			oss << '+' << town->creatureGrowth(i);
 			CSDL_Ext::printAtMiddle(oss.str(),pomx+16,pomy+37,GEOR13,zwykly,to);
 		}
 	}
@@ -559,7 +559,10 @@ void CCastleInterface::recreateBuildings()
 	}
 	std::sort(buildings.begin(),buildings.end(),srthlp);
 }
-
+void CCastleInterface::recruit(int ID, int amount)
+{
+	LOCPLINT->cb->recruitCreatures(town,ID,amount);
+}
 void CHallInterface::CResDataBar::show(SDL_Surface * to)
 {
 	blitAt(bg,pos.x,pos.y);

+ 2 - 1
CCastleInterface.h

@@ -27,7 +27,7 @@ public:
 	void mouseMoved (SDL_MouseMotionEvent & sEvent);
 };
 
-class CCastleInterface : public IShowable, public IActivable
+class CCastleInterface : public IShowable, public IActivable, public IRecruit
 {
 public:
 	bool showing;
@@ -62,6 +62,7 @@ public:
 	void addBuilding(int bid);
 	void removeBuilding(int bid);
 	void recreateBuildings();
+	void recruit(int ID, int amount);
 };
 
 class CHallInterface : public IShowable, public IActivable

+ 3 - 3
CMT.cpp

@@ -62,7 +62,7 @@
 CGameInfo* CGI;
 #endif
 #define CHUNK 16384
-const char * NAME = "VCMI 0.5x \"Tirion\" Techdemo";
+const char * NAME = "VCMI pre-0.6";
 
 SDL_Color playerColorPalette[256]; //palette to make interface colors good
 
@@ -212,8 +212,8 @@ void initGameState(CGameInfo * cgi)
 		//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);
+		//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
 			vti->name=vti->town->names[rand()%vti->town->names.size()];
 		

+ 2 - 2
CMessage.cpp

@@ -520,7 +520,7 @@ SDL_Surface * CMessage::genMessage
 	if (title.length())
 		hh=110+(21*tekst->size());
 	else hh=60+(21*tekst->size());
-	if (type==EWindowType::yesOrNO) //make place for buttons
+	if (type==yesOrNO) //make place for buttons
 	{
 		if (ww<200) ww=200; 
 		hh+=70;
@@ -550,7 +550,7 @@ SDL_Surface * CMessage::genMessage
 		SDL_BlitSurface(tresc,NULL,ret,&trescRect);
 		SDL_FreeSurface(tresc);
 	}
-	if (type==EWindowType::yesOrNO) // add buttons
+	if (type==yesOrNO) // add buttons
 	{
 		int by = 77+tekst->size()*21;
 		if (title.length()) by+=40;

+ 24 - 6
CPlayerInterface.cpp

@@ -113,8 +113,6 @@ void CGarrisonSlot::clickLeft(tribool down)
 				(!upg)?(owner->oup):(owner->odown),
 				(!owner->highlighted->upg)?(owner->oup):(owner->odown),
 				ID,owner->highlighted->ID);
-			owner->highlighted = NULL;
-			owner->recreateSlots();
 		}
 		else
 		{
@@ -126,18 +124,23 @@ void CGarrisonSlot::clickLeft(tribool down)
 }
 void CGarrisonSlot::activate()
 {
+	if(!active) active=true;
+	else return;
 	ClickableL::activate();
 	ClickableR::activate();
 	Hoverable::activate();
 }
 void CGarrisonSlot::deactivate()
 {
+	if(active) active=false;
+	else return;
 	ClickableL::deactivate();
 	ClickableR::deactivate();
 	Hoverable::deactivate();
 }
 CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg, const CCreature * Creature, int Count)
 {
+	active = false;
 	upg = Upg;
 	count = Count;
 	ID = IID;
@@ -148,6 +151,11 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg
 	pos.h = 64;
 	owner = Owner;
 }
+CGarrisonSlot::~CGarrisonSlot()
+{
+	if(active)
+		deactivate();
+}
 void CGarrisonSlot::show()
 {
 	if(creature)
@@ -1516,6 +1524,8 @@ SDL_Surface * CPlayerInterface::drawTownInfoWin(const CGTownInstance * curh)
 	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++)
 	{
+		if(!i->second.first)
+			continue;
 		blitAt(CGI->creh->smallImgs[(*i).second.first->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
 		itoa((*i).second.second,buf,10);
 		printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+39,GEORM,zwykly,ret);
@@ -1528,7 +1538,6 @@ SDL_Surface * CPlayerInterface::drawTownInfoWin(const CGTownInstance * curh)
 	if(curh->builded >= MAX_BUILDING_PER_TURN)
 		pom++;
 	blitAt(bigTownPic->ourImages[pom].bitmap,13,13,ret);
-
 	delete[] buf;
 	return ret;
 }
@@ -1858,8 +1867,15 @@ void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
 		const CGTownInstance * tt;
 		if(tt = dynamic_cast<const CGTownInstance*>(obj))
 		{
-			SDL_FreeSurface(heroWins[tt->identifier]);
-			heroWins[tt->identifier] = infoWin(tt);
+			SDL_FreeSurface(townWins[tt->identifier]);
+			townWins[tt->identifier] = infoWin(tt);
+		}
+		
+		const CCastleInterface *ci = dynamic_cast<CCastleInterface*>(curint);
+		if(ci)
+		{
+			ci->garr->highlighted = NULL;
+			ci->garr->recreateSlots();
 		}
 	}
 }
@@ -2325,6 +2341,7 @@ void CRecrutationWindow::Max()
 }
 void CRecrutationWindow::Buy()
 {
+	rec->recruit(creatures[which].ID,slider->value);
 	close();
 }
 void CRecrutationWindow::Cancel()
@@ -2388,7 +2405,8 @@ void CRecrutationWindow::show(SDL_Surface * to)
 	}
 	c++;
 }
-CRecrutationWindow::CRecrutationWindow(std::vector<std::pair<int,int> > &Creatures) //creatures - pairs<creature_ID,amount>
+CRecrutationWindow::CRecrutationWindow(std::vector<std::pair<int,int> > &Creatures, IRecruit *irec) //creatures - pairs<creature_ID,amount>
+:rec(irec)
 {
 	creatures.resize(Creatures.size());
 	for(int i=0;i<creatures.size();i++)

+ 12 - 2
CPlayerInterface.h

@@ -241,6 +241,7 @@ public:
 	const CCreature * creature;
 	int count;
 	int upg; //0 - up garrison, 1 - down garrison
+	bool active;
 	
 	virtual void hover (bool on);
 	void clickRight (boost::logic::tribool down);
@@ -249,6 +250,7 @@ public:
 	void deactivate();
 	void show();
 	CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg=0, const CCreature * Creature=NULL, int Count=0);
+	~CGarrisonSlot();
 };
 
 class CGarrisonInt :public CIntObject
@@ -259,7 +261,7 @@ public:
 
 	SDL_Surface *sur;
 	int offx, offy;
-	bool ignoreEvent, update;
+	bool ignoreEvent, update, active;
 
 	const CCreatureSet *set1;
 	const CCreatureSet *set2;
@@ -440,6 +442,13 @@ public:
 	void keyPressed (SDL_KeyboardEvent & key);
 	void draw();
 };
+
+class IRecruit
+{
+public:
+	virtual void recruit(int ID, int amount)=0;
+};
+
 class CRecrutationWindow : public IShowable, public ClickableL
 {
 public:
@@ -451,6 +460,7 @@ public:
 		std::vector<std::pair<int,int> > res; //res_id - cost_per_unit
 	};
 	std::vector<creinfo> creatures;
+	IRecruit *rec;
 	CSlider<CRecrutationWindow> *slider;
 	AdventureMapButton<CRecrutationWindow> *max, *buy, *cancel;
 	SDL_Surface *bitmap;
@@ -465,7 +475,7 @@ public:
 	void activate(); 
 	void deactivate();
 	void show(SDL_Surface * to = NULL);
-	CRecrutationWindow(std::vector<std::pair<int,int> > & Creatures); //creatures - pairs<creature_ID,amount>
+	CRecrutationWindow(std::vector<std::pair<int,int> > & Creatures, IRecruit *irec); //creatures - pairs<creature_ID,amount>
 	~CRecrutationWindow();
 };
 

+ 0 - 2
hch/CAmbarCendamo.cpp

@@ -1988,8 +1988,6 @@ void CAmbarCendamo::deh3m()
 				nt->possibleSpells = spec->possibleSpells;
 				nt->obligatorySpells = spec->obligatorySpells;
 				nt->availableSpells = std::vector<CSpell*>();
-				nt->creatureIncome = std::vector<int>();
-				nt->creaturesLeft = std::vector<int>();
 				CGI->townh->townInstances.push_back(nt);
 				break;
 			}

+ 1 - 1
hch/CCreatureHandler.h

@@ -1,7 +1,7 @@
 #ifndef CCREATUREHANDLER_H
 #define CCREATUREHANDLER_H
 
-#include "CPlayerInterface.h"
+#include "../CPlayerInterface.h"
 #include <string>
 #include <vector>
 #include <map>

+ 7 - 2
hch/CObjectHandler.cpp

@@ -266,15 +266,20 @@ int CGTownInstance::hallLevel() const // -1 - none, 0 - village, 1 - town, 2 - c
 		return 0;
 	return -1;
 }
-bool CGTownInstance::creatureDwelling(int level, bool upgraded)
+bool CGTownInstance::creatureDwelling(int level, bool upgraded) const
 {
 	return builtBuildings.find(30+level+upgraded*7)!=builtBuildings.end();
 }
-int CGTownInstance::getHordeLevel(int HID) //HID - 0 or 1; returns creature level or -1 if that horde structure is not present
+int CGTownInstance::getHordeLevel(int HID)  const//HID - 0 or 1; returns creature level or -1 if that horde structure is not present
 {
 	//TODO: write
 	return -1;
 }
+int CGTownInstance::creatureGrowth(int level) const
+{
+	//TODO: write 
+	return -1;
+}
 int CGTownInstance::dailyIncome() const
 {
 	int ret = 0;

+ 3 - 5
hch/CObjectHandler.h

@@ -395,10 +395,7 @@ public:
 		std::map<int,int> creatures; //level - available amount
 	} strInfo;
 	
-	//TODO:
 	std::set<int> forbiddenBuildings, builtBuildings, h3mbuildings;
-	std::vector<int> creatureIncome; //vector by level - that valueis addedto thebasic growth
-	std::vector<int> creaturesLeft; //that can be recruited
 
 	const CGHeroInstance * garrisonHero, *visitingHero;
 
@@ -408,8 +405,9 @@ public:
 
 	int fortLevel() const; //0 - none, 1 - fort, 2 - citadel, 3 - castle
 	int hallLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol
-	bool creatureDwelling(int level, bool upgraded=false);
-	int getHordeLevel(int HID); //HID - 0 or 1; returns creature level or -1 if that horde structure is not present
+	bool creatureDwelling(int level, bool upgraded=false) const;
+	int getHordeLevel(int HID) const; //HID - 0 or 1; returns creature level or -1 if that horde structure is not present
+	int creatureGrowth(int level) const;
 
 	bool hasFort() const;
 	bool hasCapitol() const;