Browse Source

* corrected typo in cr_shots
* recruiting creatures

Michał W. Urbańczyk 17 years ago
parent
commit
6e02c1c5db
11 changed files with 186 additions and 163 deletions
  1. 4 5
      CBattleInterface.cpp
  2. 3 65
      CCallback.cpp
  3. 2 2
      CCallback.h
  4. 19 18
      CGameState.cpp
  5. 1 0
      CGameState.h
  6. 15 3
      client/Client.cpp
  7. 1 1
      config/cr_shots.txt
  8. 12 1
      int3.h
  9. 51 50
      lib/NetPacks.h
  10. 77 17
      server/CGameHandler.cpp
  11. 1 1
      server/VCMI_server.vcproj

+ 4 - 5
CBattleInterface.cpp

@@ -728,19 +728,18 @@ void CBattleInterface::hexLclicked(int whichOne)
 		if(!myTurn)
 			return; //we are not permit to do anything
 
-		int atCre = LOCPLINT->cb->battleGetStack(whichOne); //creature at destination tile; -1 if there is no one
-		//LOCPLINT->cb->battleGetCreature();
-		if(atCre==-1) //no creature at that tile
+		CStack* dest = LOCPLINT->cb->battleGetStackByPos(whichOne); //creature at destination tile; -1 if there is no one
+		if(!dest || !dest->alive) //no creature at that tile
 		{
 			if(std::find(shadedHexes.begin(),shadedHexes.end(),whichOne)!=shadedHexes.end())// and it's in our range
 				giveCommand(2,whichOne,activeStack);
 		}
-		else if(LOCPLINT->cb->battleGetStackByID(atCre)->owner != attackingHeroInstance->tempOwner
+		else if(dest->owner != attackingHeroInstance->tempOwner
 			&& LOCPLINT->cb->battleCanShoot(activeStack, whichOne)) //shooting
 		{
 			giveCommand(7,whichOne,activeStack);
 		}
-		else if(LOCPLINT->cb->battleGetStackByID(atCre)->owner != attackingHeroInstance->tempOwner) //attacking
+		else if(dest->owner != attackingHeroInstance->tempOwner) //attacking
 		{
 			std::vector<int> n = BattleInfo::neighbouringTiles(whichOne);
 			for(int i=0;i<n.size();i++)

+ 3 - 65
CCallback.cpp

@@ -110,72 +110,10 @@ void CCallback::selectionMade(int selection, int asker)
 	//IChosen * ask = (IChosen *)asker;
 	//ask->chosen(selection);
 }
-void CCallback::recruitCreatures(const CGObjectInstance *obj, int ID, int amount)
+void CCallback::recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount)
 {
-	if(amount<=0) return;
-	if(obj->ID==98) //recruiting from town
-	{
-		int ser=-1; //used dwelling level
-		CGTownInstance *t = const_cast<CGTownInstance*>(static_cast<const CGTownInstance*>(obj));
-
-		//verify
-		bool found = false;
-		typedef std::pair<const int,int> Parka;
-		for(std::map<si32,ui32>::iterator av=t->strInfo.creatures.begin();av!=t->strInfo.creatures.end();av++)
-		{
-			if(	(   found  = (ID == t->town->basicCreatures[av->first])   ) //creature is available among basic cretures
-				|| (found  = (ID == t->town->upgradedCreatures[av->first]))			)//creature is available among upgraded cretures
-			{
-				amount = std::min(amount,(int)av->second); //reduce recruited amount up to available amount
-				ser = av->first;
-				break;
-			}
-		}
-		if(!found)	//no such creature
-			return;
-
-		if(amount > CGI->creh->creatures[ID].maxAmount(gs->players[player].resources))
-			return; //not enough resources
-
-		//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; //slot ID
-		std::pair<si32,std::pair<ui32,si32> > parb;	
-
-		for(int i=0;i<7;i++) //TODO: if there is already stack of same creatures it should be used always
-		{
-			if(((!t->army.slots[i].first) && (!t->army.slots[i].second)) || (t->army.slots[i].first == ID)) //slot is free or there is saem creature
-			{
-				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->strInfo.creatures[ser] -= amount;
-		if(t->army.slots[slot].first) //add new creatures to the existing stack
-		{
-			t->army.slots[slot].second += amount;
-		}
-		else //create new stack in the garrison
-		{
-			t->army.slots[slot].first = ID;
-			t->army.slots[slot].second = amount;
-		}
-		cl->playerint[player]->garrisonChanged(obj);
-
-	}
-	//TODO: recruit from dwellings on the adventure map
+	if(player!=obj->tempOwner) return;
+	*cl->serv << ui16(506) << obj->id << ID << amount;
 }
 
 

+ 2 - 2
CCallback.h

@@ -42,7 +42,7 @@ public:
 	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;
+	virtual void recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount)=0;
 	virtual bool dismissCreature(const CArmedInstance *obj, int stackPos)=0;
 	virtual bool upgradeCreature(const CArmedInstance *obj, int stackPos, int newID=-1)=0; //if newID==-1 then best possible upgrade will be made
 	virtual void endTurn()=0;
@@ -114,7 +114,7 @@ public:
 	bool dismissHero(const CGHeroInstance * hero);
 	bool swapArifacts(const CGHeroInstance * hero1, bool worn1, int pos1, const CGHeroInstance * hero2, bool worn2, int pos2);
 	bool buildBuilding(const CGTownInstance *town, si32 buildingID);
-	void recruitCreatures(const CGObjectInstance *obj, int ID, int amount);
+	void recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount);
 	bool dismissCreature(const CArmedInstance *obj, int stackPos);
 	bool upgradeCreature(const CArmedInstance *obj, int stackPos, int newID=-1);
 	void endTurn();

+ 19 - 18
CGameState.cpp

@@ -249,9 +249,8 @@ CStack::CStack(CCreature * C, int A, int O, int I, bool AO)
 	:creature(C),amount(A),owner(O), alive(true), position(-1), ID(I), attackerOwned(AO), firstHPleft(C->hitPoints)
 {
 }
-void CGameState::apply(IPack * pack)
+void CGameState::applyNL(IPack * pack)
 {
-	mx->lock();
 	switch(pack->getType())
 	{
 	case 101://NewTurn
@@ -263,11 +262,10 @@ void CGameState::apply(IPack * pack)
 				static_cast<CGHeroInstance*>(map->objects[h.id])->movement = h.move;
 				static_cast<CGHeroInstance*>(map->objects[h.id])->mana = h.mana;
 			}
-			BOOST_FOREACH(NewTurn::Resources h, n->res) //give resources
-			{
-				for(int i=0;i<RESOURCE_QUANTITY;i++)
-					players[h.player].resources[i] = h.resources[i];
-			}
+			BOOST_FOREACH(SetResources h, n->res) //give resources
+				applyNL(&h);
+			BOOST_FOREACH(SetAvailableCreatures h, n->cres) //set available creatures in towns
+				applyNL(&h);
 			if(n->resetBuilded) //reset amount of structures set in this turn in towns
 				BOOST_FOREACH(CGTownInstance* t, map->towns)
 					t->builded = 0;
@@ -340,8 +338,8 @@ void CGameState::apply(IPack * pack)
 		}
 	case 503:
 		{
-			SetStrInfo *ssi = static_cast<SetStrInfo*>(pack);
-			static_cast<CGTownInstance*>(map->objects[ssi->tid])->strInfo.creatures = ssi->cres;
+			//SetStrInfo *ssi = static_cast<SetStrInfo*>(pack);
+			//static_cast<CGTownInstance*>(map->objects[ssi->tid])->strInfo.creatures = ssi->cres;
 			break;
 		}
 	case 504:
@@ -353,6 +351,12 @@ void CGameState::apply(IPack * pack)
 			t->builded = ns->builded;
 			break;
 		}
+	case 506:
+		{
+			SetAvailableCreatures *sac = static_cast<SetAvailableCreatures*>(pack);
+			static_cast<CGTownInstance*>(map->objects[sac->tid])->strInfo.creatures = sac->creatures;
+			break;
+		}
 	case 1001://set object property
 		{
 			SetObjectProperty *p = static_cast<SetObjectProperty*>(pack);
@@ -417,18 +421,15 @@ void CGameState::apply(IPack * pack)
 	case 3006:
 		{
 			BattleAttack *br = static_cast<BattleAttack*>(pack);
-			mx->unlock();
-			apply(&br->bsa);
-			mx->lock();
+			applyNL(&br->bsa);
 			break;
 		}
-	//case 1002://set hover name
-	//	{
-	//		SetHoverName * shn = static_cast<SetHoverName*>(pack);
-	//		map->objects[shn->id]->hoverName = toString(shn->name);
-	//		break;
-	//	}
 	}
+}
+void CGameState::apply(IPack * pack)
+{
+	mx->lock();
+	applyNL(pack);
 	mx->unlock();
 }
 int CGameState::pickHero(int owner)

+ 1 - 0
CGameState.h

@@ -128,6 +128,7 @@ private:
 	CGameState();
 	~CGameState();
 	void init(StartInfo * si, Mapa * map, int Seed);
+	void applyNL(IPack * pack);
 	void apply(IPack * pack);
 	void randomizeObject(CGObjectInstance *cur);
 	std::pair<int,int> pickObject(CGObjectInstance *obj);

+ 15 - 3
client/Client.cpp

@@ -280,6 +280,7 @@ void CClient::process(int what)
 		{
 			SetGarrisons sg;
 			*serv >> sg;
+			std::cout << "Setting garrisons." << std::endl;
 			gs->apply(&sg);
 			for(std::map<ui32,CCreatureSet>::iterator i = sg.garrs.begin(); i!=sg.garrs.end(); i++)
 				playerint[gs->map->objects[i->first]->tempOwner]->garrisonChanged(gs->map->objects[i->first]);
@@ -287,9 +288,9 @@ void CClient::process(int what)
 		}
 	case 503:
 		{
-			SetStrInfo ssi;
-			*serv >> ssi;
-			gs->apply(&ssi);
+			//SetStrInfo ssi;
+			//*serv >> ssi;
+			//gs->apply(&ssi);
 			//TODO: notify interfaces
 			break;
 		}
@@ -297,11 +298,21 @@ void CClient::process(int what)
 		{
 			NewStructures ns;
 			*serv >> ns;
+			std::cout << "New structure(s) in " << ns.tid << " - " << *ns.bid.begin() << std::endl;
 			gs->apply(&ns);
 			BOOST_FOREACH(si32 bid, ns.bid)
 				playerint[gs->map->objects[ns.tid]->tempOwner]->buildChanged(static_cast<CGTownInstance*>(gs->map->objects[ns.tid]),bid,1);
 			break;
 		}
+	case 506:
+		{
+			SetAvailableCreatures ns;
+			*serv >> ns;
+			std::cout << "Setting available creatures in " << ns.tid << std::endl;
+			gs->apply(&ns);
+			//TODO: do we need to inform interface? 
+			break;
+		}
 	case 1001:
 		{
 			SetObjectProperty sop;
@@ -398,6 +409,7 @@ void CClient::process(int what)
 		{
 			BattleAttack ba;
 			*serv >> ba;
+			std::cout << "Stack: " << ba.stackAttacking << " is attacking stack "<< ba.bsa.stackAttacked <<std::endl;
 			gs->apply(&ba);
 			LOCPLINT->battleAttack(&ba);
 			break;

+ 1 - 1
config/cr_shots.txt

@@ -34,7 +34,7 @@
 169 SMBALX.DEF 0
 170 PLCBOWX.DEF 0
 171 PLCBOWX.DEF 0
-173 CPGRE.DEF 1
+173 CPRGRE.DEF 1
 193 SMBALX.DEF 0
 196 SMBALX.DEF 0
 -1

+ 12 - 1
int3.h

@@ -6,7 +6,18 @@ 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 formation; //false - wide, true - tight
+	si32 getSlotFor(ui32 creature, ui32 slotsAmount=7) //returns -1 if no slot available
+	{
+		
+		for(std::map<si32,std::pair<ui32,si32> >::iterator i=slots.begin(); i!=slots.end(); i++)
+			if(i->second.first == creature)
+				return i->first; //if there is already such creature we return its slot id
+		for(si32 i=0; i<slotsAmount; i++)
+			if(slots.find(i) == slots.end())
+				return i; //return first free slot
+		return -1; //no slot available
+	}
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & slots & formation;

+ 51 - 50
lib/NetPacks.h

@@ -25,40 +25,17 @@ template <typename T> struct CPack
 	ui16 getType() const{return type;}
 	T* This(){return static_cast<T*>(this);};
 };
-struct NewTurn : public CPack<NewTurn> //101
+struct SetResources : public CPack<SetResources> //104
 {
-	struct Hero
-	{
-		ui32 id, move, mana; //id is a general serial id
-		template <typename Handler> void serialize(Handler &h, const int version)
-		{
-			h & id & move & mana;
-		}
-		bool operator<(const Hero&h)const{return id < h.id;}
-	};
-	struct Resources
-	{
-		ui8 player;
-		si32 resources[RESOURCE_QUANTITY];
-		template <typename Handler> void serialize(Handler &h, const int version)
-		{
-			h & player & resources;
-		}
-		bool operator<(const Resources&h)const{return player < h.player;}
-	};
-
-	std::set<Hero> heroes; //updates movement and mana points
-	std::set<Resources> res;//resource list
-	ui32 day;
-	bool resetBuilded;
-
-	NewTurn(){type = 101;};
+	SetResources(){res.resize(RESOURCE_QUANTITY);type = 104;};
+	ui8 player;
+	std::vector<si32> res; //res[resid] => res amount
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & heroes & res & day & resetBuilded;
+		h & player & res;
 	}
-}; 
+};
 struct SetResource : public CPack<SetResource> //102
 {
 	SetResource(){type = 102;};
@@ -71,17 +48,6 @@ struct SetResource : public CPack<SetResource> //102
 		h & player & resid & val;
 	}
 }; 
-struct SetResources : public CPack<SetResources> //104
-{
-	SetResources(){type = 104;};
-	ui8 player;
-	std::vector<si32> res; //res[resid] => res amount
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & player & res;
-	}
-}; 
 struct SetPrimSkill : public CPack<SetPrimSkill> //105
 {
 	SetPrimSkill(){type = 105;};
@@ -129,29 +95,64 @@ struct SetGarrisons : public CPack<SetGarrisons> //502
 		h & garrs;
 	}
 }; 
-struct SetStrInfo : public CPack<SetStrInfo> //503
+struct NewStructures : public CPack<NewStructures> //504
 {
-	SetStrInfo(){type = 503;};
+	NewStructures(){type = 504;};
 	si32 tid;
-	std::map<si32,ui32> cres;
+	std::set<si32> bid;
+	si16 builded; 
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & tid & cres;
+		h & tid & bid & builded;
 	}
-};  
-struct NewStructures : public CPack<NewStructures> //504
+}; 
+struct SetAvailableCreatures : public CPack<SetAvailableCreatures> //506
 {
-	NewStructures(){type = 504;};
+	SetAvailableCreatures(){type = 506;};
 	si32 tid;
-	std::set<si32> bid;
-	si16 builded; 
+	std::map<si32,ui32> creatures;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & tid & bid & builded;
+		h & tid & creatures;
+	}
+};  
+struct NewTurn : public CPack<NewTurn> //101
+{
+	struct Hero
+	{
+		ui32 id, move, mana; //id is a general serial id
+		template <typename Handler> void serialize(Handler &h, const int version)
+		{
+			h & id & move & mana;
+		}
+		bool operator<(const Hero&h)const{return id < h.id;}
+	};
+
+	std::set<Hero> heroes; //updates movement and mana points
+	std::vector<SetResources> res;//resource list
+	std::vector<SetAvailableCreatures> cres;//resource list
+	ui32 day;
+	bool resetBuilded;
+
+	NewTurn(){type = 101;};
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & heroes & cres & res & day & resetBuilded;
 	}
 }; 
+//struct SetStrInfo : public CPack<SetStrInfo> //503
+//{
+//	SetStrInfo(){type = 503;};
+//	SetAvailableCreatures sac;
+//
+//	template <typename Handler> void serialize(Handler &h, const int version)
+//	{
+//		h & sac;
+//	}
+//};  
 struct MetaString : public CPack<MetaString> //2001 helper for object scrips
 {
 	std::vector<std::string> strings;

+ 77 - 17
server/CGameHandler.cpp

@@ -588,10 +588,10 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 					}
 					else if(bid >= 30) //bas. dwelling
 					{
-						SetStrInfo ssi;
+						SetAvailableCreatures ssi;
 						ssi.tid = tid;
-						ssi.cres = t->strInfo.creatures;
-						ssi.cres[bid-30] = VLC->creh->creatures[t->town->basicCreatures[bid-30]].growth;
+						ssi.creatures = t->strInfo.creatures;
+						ssi.creatures[bid-30] = VLC->creh->creatures[t->town->basicCreatures[bid-30]].growth;
 						sendAndApply(&ssi);
 					}
 
@@ -606,6 +606,62 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 						sr.res[i]-=b->resources[i];
 					sendAndApply(&sr);
 
+					break;
+				}
+			case 506: //recruit creature
+				{
+					si32 objid, ser=-1; //ser - used dwelling level
+					ui32 crid, cram; //recruited creature id and amount
+					c >> objid >> crid >> cram;
+
+					CGTownInstance * t = static_cast<CGTownInstance*>(gs->map->objects[objid]);
+
+					//verify
+					bool found = false;
+					typedef std::pair<const int,int> Parka;
+					for(std::map<si32,ui32>::iterator av = t->strInfo.creatures.begin();  av!=t->strInfo.creatures.end();  av++)
+					{
+						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
+						{
+							cram = std::min(cram,av->second); //reduce recruited amount up to available amount
+							ser = av->first;
+							break;
+						}
+					}
+					int slot = t->army.getSlotFor(crid);
+
+					if(!found ||	//no such creature
+						cram > VLC->creh->creatures[crid].maxAmount(gs->players[t->tempOwner].resources) ||  //lack of resources
+						cram<=0	||
+						slot<0	) 
+						break;
+
+					//recruit
+					SetResources sr;
+					sr.player = t->tempOwner;
+					for(int i=0;i<RESOURCE_QUANTITY;i++)
+						sr.res[i]  =  gs->players[t->tempOwner].resources[i] - (VLC->creh->creatures[crid].cost[i] * cram);
+
+					SetAvailableCreatures sac;
+					sac.tid = objid;
+					sac.creatures = t->strInfo.creatures;
+					sac.creatures[ser] -= 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[objid].slots[slot] = std::make_pair(crid,cram);
+					}
+					else //add creatures to a already existing stack
+					{
+						sg.garrs[objid].slots[slot].second += cram;
+					}
+
+					sendAndApply(&sr); 
+					sendAndApply(&sac);
+					sendAndApply(&sg);
 					break;
 				}
 			case 3002:
@@ -789,14 +845,15 @@ void CGameHandler::newTurn()
 {
 	NewTurn n;
 	n.day = gs->day + 1;
+	n.resetBuilded = true;
 
 	for ( std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
 	{
 		if(i->first>=PLAYER_LIMIT) continue;
-		NewTurn::Resources r;
+		SetResources r;
 		r.player = i->first;
 		for(int j=0;j<RESOURCE_QUANTITY;j++)
-			r.resources[j] = i->second.resources[j];
+			r.res[j] = i->second.resources[j];
 		
 		for (unsigned j=0;j<(*i).second.heroes.size();j++) //handle heroes
 		{
@@ -806,21 +863,24 @@ void CGameHandler::newTurn()
 			h.mana = (*i).second.heroes[j]->mana;
 			n.heroes.insert(h);
 		}
-		for(unsigned j=0;j<i->second.towns.size();j++)//handle towns
+		for(std::vector<CGTownInstance *>::iterator j=i->second.towns.begin();j!=i->second.towns.end();j++)//handle towns
 		{
-			i->second.towns[j]->builded=0;
-			//if(gs->getDate(1)==1) //first day of week
-			//{
-			//	for(int k=0;k<CREATURES_PER_TOWN;k++) //creature growths
-			//	{
-			//		if(i->second.towns[j]->creatureDwelling(k))//there is dwelling (k-level)
-			//			i->second.towns[j]->strInfo.creatures[k]+=i->second.towns[j]->creatureGrowth(k);
-			//	}
-			//}
+			if(gs->getDate(1)==7) //first day of week
+			{
+				SetAvailableCreatures sac;
+				sac.tid = (**j).id;
+				sac.creatures = (**j).strInfo.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);
+				}
+				n.cres.push_back(sac);
+			}
 			if((gs->day) && i->first<PLAYER_LIMIT)//not the first day and town not neutral
-				r.resources[6] += i->second.towns[j]->dailyIncome();
+				r.res[6] += (**j).dailyIncome();
 		}
-		n.res.insert(r);
+		n.res.push_back(r);
 	}	
 	sendAndApply(&n);
 	for (std::set<CCPPObjectScript *>::iterator i=cppscripts.begin();i!=cppscripts.end();i++)

+ 1 - 1
server/VCMI_server.vcproj

@@ -43,7 +43,7 @@
 				MinimalRebuild="true"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="3"
-				WarningLevel="3"
+				WarningLevel="2"
 				DebugInformationFormat="4"
 				DisableSpecificWarnings="4251"
 			/>