mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	* CGameInterface.h/.cpp moved from client project to lib (and, appropriately, to lib subfolder).
* New files in lib: ResourceSet.h/.cpp -> containing new structure for managing resources logic * Minor changes and fixes
This commit is contained in:
		| @@ -325,8 +325,8 @@ float CGeniusAI::TownObjective::getValue() const | ||||
|  | ||||
| 			newID = ui.newID.back(); | ||||
| 			int upgrade_serial = ui.newID.size() - 1; | ||||
| 			for (std::set< std::pair<int,int> >::iterator j = ui.cost[upgrade_serial].begin(); j != ui.cost[upgrade_serial].end(); j++) | ||||
| 				resourceCosts[j->first] = j->second*howMany; | ||||
| // 			for (std::set< std::pair<int,int> >::iterator j = ui.cost[upgrade_serial].begin(); j != ui.cost[upgrade_serial].end(); j++) | ||||
| // 				resourceCosts[j->first] = j->second*howMany; | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| @@ -762,9 +762,9 @@ void CGeniusAI::HeroObjective::fulfill(CGeniusAI& cg, HypotheticalGameState& hgs | ||||
| 				std::set<std::pair<int,int> >::iterator j; | ||||
| 				for (int ii = 0; ii < ui.cost.size(); ii++) // Can afford the upgrade? | ||||
| 				{ | ||||
| 					for (j = ui.cost[ii].begin(); j != ui.cost[ii].end(); j++) | ||||
| 						if (hgs.resourceAmounts[j->first] < j->second * i->second->count) | ||||
| 							canUpgrade = false; | ||||
| // 					for (j = ui.cost[ii].begin(); j != ui.cost[ii].end(); j++) | ||||
| // 						if (hgs.resourceAmounts[j->first] < j->second * i->second->count) | ||||
| // 							canUpgrade = false; | ||||
| 				} | ||||
| 			} | ||||
| 			if (canUpgrade) | ||||
| @@ -889,11 +889,11 @@ void CGeniusAI::addTownObjectives (HypotheticalGameState::TownModel& t, Hypothet | ||||
| 			bool canAfford = true; | ||||
| 			 | ||||
| 			int upgrade_serial = ui.newID.size() - 1; | ||||
| 			for (std::set< std::pair<int, int> >::iterator j = ui.cost[upgrade_serial].begin(); j != ui.cost[upgrade_serial].end(); j++) | ||||
| 			{ | ||||
| 				if (hgs.resourceAmounts[j->first] < j->second * i->second->count) | ||||
| 					canAfford = false; | ||||
| 			} | ||||
| // 			for (std::set< std::pair<int, int> >::iterator j = ui.cost[upgrade_serial].begin(); j != ui.cost[upgrade_serial].end(); j++) | ||||
| // 			{ | ||||
| // 				if (hgs.resourceAmounts[j->first] < j->second * i->second->count) | ||||
| // 					canAfford = false; | ||||
| // 			} | ||||
| 			if (canAfford) | ||||
| 			{ | ||||
| 				TownObjective to(hgs,AIObjective::upgradeCreatures,&t,i->first,this); | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
|  | ||||
| #include <vector> | ||||
| #include <iostream> | ||||
| #include "CGameInterface.h" | ||||
| #include "lib/CGameInterface.h" | ||||
|  | ||||
| /* | ||||
|  * AI_Base.h, part of VCMI engine | ||||
|   | ||||
| @@ -157,14 +157,17 @@ bool CCallback::assembleArtifacts (const CGHeroInstance * hero, ui16 artifactSlo | ||||
|  | ||||
| bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID) | ||||
| { | ||||
| 	CGTownInstance * t = const_cast<CGTownInstance *>(town); | ||||
| 	//CGTownInstance * t = const_cast<CGTownInstance *>(town); | ||||
|  | ||||
| 	if(town->tempOwner!=player) | ||||
| 		return false; | ||||
| 	const CBuilding *b = CGI->buildh->buildings[t->subID][buildingID]; | ||||
| 	for(int i=0;i<b->resources.size();i++) | ||||
| 		if(b->resources[i] > gs->players[player].resources[i]) | ||||
| 			return false; //lack of resources | ||||
|  | ||||
| 	if(!canBuildStructure(town, buildingID)) | ||||
| 		return false; | ||||
| // 	const CBuilding *b = CGI->buildh->buildings[t->subID][buildingID]; | ||||
| // 	for(int i=0;i<b->resources.size();i++) | ||||
| // 		if(b->resources[i] > gs->players[player].resources[i]) | ||||
| // 			return false; //lack of resources | ||||
|  | ||||
| 	BuildStructure pack(town->id,buildingID); | ||||
| 	sendRequest(&pack); | ||||
|   | ||||
| @@ -82,16 +82,14 @@ CCreatureWindow::CCreatureWindow(const CStackInstance &st, int Type, boost::func | ||||
| 	{ | ||||
| 		if(Upg && ui) | ||||
| 		{ | ||||
| 			bool enough = true; | ||||
| 			for(std::set<std::pair<int,int> >::iterator i=ui->cost[0].begin(); i!=ui->cost[0].end(); i++) //calculate upgrade cost | ||||
| 			TResources upgradeCost = ui->cost[0] * st.count; | ||||
| 			for(TResources::nziterator i(upgradeCost); i.valid(); i++) | ||||
| 			{ | ||||
| 				BLOCK_CAPTURING; | ||||
| 				if(LOCPLINT->cb->getResourceAmount(i->first) < i->second*st.count) | ||||
| 					enough = false; | ||||
| 				upgResCost.push_back(new SComponent(SComponent::resource,i->first,i->second*st.count));  | ||||
| 				upgResCost.push_back(new SComponent(SComponent::resource, i->resType, i->resVal));  | ||||
| 			} | ||||
|  | ||||
| 			if(enough) | ||||
| 			if(LOCPLINT->cb->getResourceAmount().canAfford(upgradeCost)) | ||||
| 			{ | ||||
| 				CFunctionList<void()> fs; | ||||
| 				fs += Upg; | ||||
|   | ||||
| @@ -1,12 +1,13 @@ | ||||
| #ifndef __CPLAYERINTERFACE_H__ | ||||
| #define __CPLAYERINTERFACE_H__ | ||||
| #include "../global.h" | ||||
| #include "../CGameInterface.h" | ||||
| #include "../lib/CGameInterface.h" | ||||
| #include "../lib/CondSh.h" | ||||
| #include <map> | ||||
| #include <list> | ||||
| #include <algorithm> | ||||
| #include "GUIBase.h" | ||||
| #include "FunctionList.h" | ||||
|  | ||||
| #ifdef __GNUC__ | ||||
| #define sprintf_s snprintf  | ||||
|   | ||||
| @@ -820,6 +820,11 @@ void CIntObject::changeUsedEvents(ui16 what, bool enable, bool adjust /*= true*/ | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CIntObject::drawBorderLoc(SDL_Surface * sur, const Rect &r, const int3 &color) | ||||
| { | ||||
| 	CSDL_Ext::drawBorder(sur, r + pos, color); | ||||
| } | ||||
|  | ||||
| CPicture::CPicture( SDL_Surface *BG, int x, int y, bool Free ) | ||||
| { | ||||
| 	init(); | ||||
|   | ||||
| @@ -416,6 +416,7 @@ public: | ||||
| 	void show(SDL_Surface * to); | ||||
| 	void showAll(SDL_Surface * to); | ||||
|  | ||||
| 	void drawBorderLoc(SDL_Surface * sur, const Rect &r, const int3 &color); | ||||
| 	void printAtLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst); | ||||
| 	void printToLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst); | ||||
| 	void printAtMiddleLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst); | ||||
|   | ||||
| @@ -1741,7 +1741,7 @@ void CRecruitmentWindow::clickLeft(tribool down, bool previousState) | ||||
| { | ||||
| 	for(int i=0;i<creatures.size();i++) | ||||
| 	{ | ||||
| 		Rect creaPos = pos + creatures[i].pos; | ||||
| 		Rect creaPos = Rect(creatures[i].pos) + pos; | ||||
| 		if(isItIn(&creaPos, GH.current->motion.x, GH.current->motion.y)) | ||||
| 		{ | ||||
| 			which = i; | ||||
| @@ -1804,9 +1804,9 @@ void CRecruitmentWindow::showAll( SDL_Surface * to ) | ||||
| 	for(int j=0;j<creatures.size();j++) | ||||
| 	{ | ||||
| 		if(which==j) | ||||
| 			drawBorder(*bitmap,creatures[j].pos,int3(255,0,0)); | ||||
| 			drawBorderLoc(to,creatures[j].pos,int3(255,0,0)); | ||||
| 		else | ||||
| 			drawBorder(*bitmap,creatures[j].pos,int3(239,215,123)); | ||||
| 			drawBorderLoc(to,creatures[j].pos,int3(239,215,123)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -2076,22 +2076,20 @@ CCreInfoWindow::CCreInfoWindow(const CStackInstance &st, int Type, boost::functi | ||||
| 	{ | ||||
| 		if(Upg && ui) | ||||
| 		{ | ||||
| 			bool enough = true; | ||||
| 			for(std::set<std::pair<int,int> >::iterator i=ui->cost[0].begin(); i!=ui->cost[0].end(); i++) //calculate upgrade cost | ||||
| 			TResources upgradeCost = ui->cost[0] * st.count; | ||||
| 			for(TResources::nziterator i(upgradeCost); i.valid(); i++) | ||||
| 			{ | ||||
| 				BLOCK_CAPTURING; | ||||
| 				if(LOCPLINT->cb->getResourceAmount(i->first) < i->second*st.count) | ||||
| 					enough = false; | ||||
| 				upgResCost.push_back(new SComponent(SComponent::resource,i->first,i->second*st.count));  | ||||
| 				upgResCost.push_back(new SComponent(SComponent::resource, i->resType, i->resVal));  | ||||
| 			} | ||||
|  | ||||
| 			if(enough) | ||||
| 			if(LOCPLINT->cb->getResourceAmount().canAfford(upgradeCost)) | ||||
| 			{ | ||||
| 				CFunctionList<void()> fs; | ||||
| 				fs += Upg; | ||||
| 				fs += boost::bind(&CCreInfoWindow::close,this); | ||||
| 				CFunctionList<void()> cfl; | ||||
| 				cfl = boost::bind(&CPlayerInterface::showYesNoDialog, LOCPLINT, CGI->generaltexth->allTexts[207], boost::ref(upgResCost), fs, 0, false); | ||||
| 				cfl = boost::bind(&CPlayerInterface::showYesNoDialog, LOCPLINT, CGI->generaltexth->allTexts[207], boost::ref(upgResCost), fs, 0, true); | ||||
| 				upgrade = new AdventureMapButton("",CGI->generaltexth->zelp[446].second,cfl,76,237,"IVIEWCR.DEF",SDLK_u); | ||||
| 			} | ||||
| 			else | ||||
| @@ -2109,7 +2107,7 @@ CCreInfoWindow::CCreInfoWindow(const CStackInstance &st, int Type, boost::functi | ||||
| 			fs[0] += Dsm; //dismiss | ||||
| 			fs[0] += boost::bind(&CCreInfoWindow::close,this);//close this window | ||||
| 			CFunctionList<void()> cfl; | ||||
| 			cfl = boost::bind(&CPlayerInterface::showYesNoDialog,LOCPLINT,CGI->generaltexth->allTexts[12],std::vector<SComponent*>(),fs[0],fs[1],false); | ||||
| 			cfl = boost::bind(&CPlayerInterface::showYesNoDialog,LOCPLINT,CGI->generaltexth->allTexts[12],std::vector<SComponent*>(),fs[0],fs[1],true); | ||||
| 			dismiss = new AdventureMapButton("",CGI->generaltexth->zelp[445].second,cfl,21,237,"IVIEWCR2.DEF",SDLK_d); | ||||
| 		} | ||||
| 		ok = new AdventureMapButton("",CGI->generaltexth->zelp[445].second,boost::bind(&CCreInfoWindow::close,this),216,237,"IOKAY.DEF",SDLK_RETURN); | ||||
| @@ -6417,12 +6415,10 @@ void CHillFortWindow::updateGarrisons() | ||||
| 			UpgradeInfo info; | ||||
| 			LOCPLINT->cb->getUpgradeInfo(hero, i, info); | ||||
| 			if (info.newID.size())//we have upgrades here - update costs | ||||
| 				for(std::set<std::pair<int,int> >::iterator it=info.cost[0].begin(); it!=info.cost[0].end(); it++) | ||||
| 				{ | ||||
| 					std::pair<int, int> pair = std::make_pair(it->first, it->second * hero->getStackCount(i) ); | ||||
| 					costs[i].insert(pair); | ||||
| 					totalSumm[pair.first] += pair.second; | ||||
| 				} | ||||
| 			{ | ||||
| 				costs[i] = info.cost[0] * hero->getStackCount(i); | ||||
| 				totalSumm += costs[i]; | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		currState[i] = newState; | ||||
| @@ -6474,10 +6470,13 @@ void CHillFortWindow::showAll (SDL_Surface *to) | ||||
| 			if ( costs[i].size() )//we have several elements | ||||
| 			{ | ||||
| 				int curY = 128;//reverse iterator is used to display gold as first element | ||||
| 				for( std::map<int,int>::reverse_iterator rit=costs[i].rbegin(); rit!=costs[i].rend(); rit++) | ||||
| 				for(int j = costs[i].size()-1; j >= 0; j--) | ||||
| 				{ | ||||
| 					blitAtLoc(resources->ourImages[rit->first].bitmap, 104+76*i, curY, to); | ||||
| 					printToLoc(boost::lexical_cast<std::string>(rit->second), 168+76*i, curY+16, FONT_SMALL, zwykly, to); | ||||
| 					int val = costs[i][j]; | ||||
| 					if(!val) continue; | ||||
|  | ||||
| 					blitAtLoc(resources->ourImages[j].bitmap, 104+76*i, curY, to); | ||||
| 					printToLoc(boost::lexical_cast<std::string>(val), 168+76*i, curY+16, FONT_SMALL, zwykly, to); | ||||
| 					curY += 20; | ||||
| 				} | ||||
| 			} | ||||
| @@ -6515,6 +6514,7 @@ std::string CHillFortWindow::getTextForSlot(int slot) | ||||
|  | ||||
| int CHillFortWindow::getState(int slot) | ||||
| { | ||||
| 	TResources myRes = LOCPLINT->cb->getResourceAmount(); | ||||
| 	if ( slot == slotsCount )//"Upgrade all" slot | ||||
| 	{ | ||||
| 		bool allUpgraded = true;//All creatures are upgraded? | ||||
| @@ -6524,10 +6524,9 @@ int CHillFortWindow::getState(int slot) | ||||
| 		if (allUpgraded) | ||||
| 			return 1; | ||||
|  | ||||
| 		for ( int i=0; i<RESOURCE_QUANTITY; i++)//if we need more resources | ||||
| 			if(LOCPLINT->cb->getResourceAmount(i) < totalSumm[i]) | ||||
| 				return 0; | ||||
| 				 | ||||
| 		if(!totalSumm.canBeAfforded(myRes)) | ||||
| 			return 0; | ||||
|  | ||||
| 		return 2; | ||||
| 	} | ||||
|  | ||||
| @@ -6539,9 +6538,9 @@ int CHillFortWindow::getState(int slot) | ||||
| 	if (!info.newID.size())//already upgraded | ||||
| 		return 1; | ||||
|  | ||||
| 	for(std::set<std::pair<int,int> >::iterator it=info.cost[0].begin(); it!=info.cost[0].end(); it++) | ||||
| 		if(LOCPLINT->cb->getResourceAmount(it->first) < it->second * hero->getStackCount(slot)) | ||||
| 	if(!(info.cost[0] * hero->getStackCount(slot)).canBeAfforded(myRes)) | ||||
| 			return 0; | ||||
|  | ||||
| 	return 2;//can upgrade | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -7,6 +7,7 @@ | ||||
| #include <set> | ||||
| #include <list> | ||||
| #include <boost/thread/mutex.hpp> | ||||
| #include "../lib/ResourceSet.h" | ||||
|  | ||||
| #ifdef max | ||||
| #undef max | ||||
| @@ -1246,8 +1247,8 @@ public: | ||||
| 	const CGObjectInstance * fort; | ||||
| 	const CGHeroInstance * hero; | ||||
| 	std::vector<int> currState;//current state of slot - to avoid calls to getState or updating buttons | ||||
| 	std::vector<std::map<int,int> > costs;// costs [slot ID] [resource ID] = resource count for upgrade | ||||
| 	std::vector<int> totalSumm; // totalSum[resource ID] = value | ||||
| 	std::vector<TResources> costs;// costs [slot ID] [resource ID] = resource count for upgrade | ||||
| 	TResources totalSumm; // totalSum[resource ID] = value | ||||
|  | ||||
| 	CHillFortWindow(const CGHeroInstance *visitor, const CGObjectInstance *object); //c-tor | ||||
| 	~CHillFortWindow(); //d-tor | ||||
|   | ||||
| @@ -183,7 +183,6 @@ | ||||
|     <ClCompile Include="CCursorHandler.cpp" /> | ||||
|     <ClCompile Include="CDefHandler.cpp" /> | ||||
|     <ClCompile Include="CGameInfo.cpp" /> | ||||
|     <ClCompile Include="..\CGameInterface.cpp" /> | ||||
|     <ClCompile Include="CHeroWindow.cpp" /> | ||||
|     <ClCompile Include="CKingdomInterface.cpp" /> | ||||
|     <ClCompile Include="Client.cpp" /> | ||||
| @@ -218,7 +217,6 @@ | ||||
|     <ClInclude Include="CCursorHandler.h" /> | ||||
|     <ClInclude Include="CDefHandler.h" /> | ||||
|     <ClInclude Include="CGameInfo.h" /> | ||||
|     <ClInclude Include="..\CGameInterface.h" /> | ||||
|     <ClInclude Include="CHeroWindow.h" /> | ||||
|     <ClInclude Include="CKingdomInterface.h" /> | ||||
|     <ClInclude Include="Client.h" /> | ||||
|   | ||||
							
								
								
									
										8
									
								
								global.h
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								global.h
									
									
									
									
									
								
							| @@ -349,14 +349,6 @@ namespace Buildings | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| namespace Res | ||||
| { | ||||
| 	enum ERes  | ||||
| 	{ | ||||
| 		WOOD = 0, MERCURY, ORE, SULFUR, CRYSTAL, GEMS, GOLD, MITHRIL | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| namespace Arts | ||||
| { | ||||
| 	enum EPos | ||||
|   | ||||
| @@ -38,7 +38,6 @@ static unsigned int readNr(std::string &in, int &it) | ||||
| static CBuilding * readBg(std::string &buf, int& it) | ||||
| { | ||||
| 	CBuilding * nb = new CBuilding(); | ||||
| 	nb->resources.resize(RESOURCE_QUANTITY); | ||||
| 	for(int res=0;res<7;res++) | ||||
| 		nb->resources[res] = readNr(buf,it); | ||||
| 	/*nb->refName = */readTo(buf,it,'\n'); | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
| #include <set> | ||||
|  | ||||
| #include "../lib/ConstTransitivePtr.h" | ||||
| #include "ResourceSet.h" | ||||
|  | ||||
| /* | ||||
|  * CBuildingHandler.h, part of VCMI engine | ||||
| @@ -22,7 +23,7 @@ class DLL_EXPORT CBuilding //a typical building encountered in every castle ;] | ||||
| { | ||||
| public: | ||||
| 	si32 tid, bid; //town ID and structure ID | ||||
| 	std::vector<si32> resources; | ||||
| 	TResources resources; | ||||
| 	std::string name; | ||||
| 	std::string description; | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
|  | ||||
| #include "../lib/HeroBonus.h" | ||||
| #include "../lib/ConstTransitivePtr.h" | ||||
| #include "ResourceSet.h" | ||||
|  | ||||
| /* | ||||
|  * CCreatureHandler.h, part of VCMI engine | ||||
| @@ -28,7 +29,7 @@ class DLL_EXPORT CCreature : public CBonusSystemNode | ||||
| { | ||||
| public: | ||||
| 	std::string namePl, nameSing, nameRef; //name in singular and plural form; and reference name | ||||
| 	std::vector<ui32> cost; //cost[res_id] - amount of that resource | ||||
| 	TResources cost; //cost[res_id] - amount of that resource | ||||
| 	std::set<ui32> upgrades; // IDs of creatures to which this creature can be upgraded | ||||
| 	ui32 hitPoints, speed, attack, defence; | ||||
| 	ui32 fightValue, AIValue, growth, hordeGrowth, shots, spells; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| #include "stdafx.h" | ||||
| #define VCMI_DLL | ||||
| #include "CGameInterface.h" | ||||
| #include "lib/BattleState.h" | ||||
| #include "BattleState.h" | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| 	#define WIN32_LEAN_AND_MEAN //excludes rarely used stuff from windows headers - delete this line if something is missing
 | ||||
| @@ -102,3 +102,91 @@ BattleAction CGlobalAI::activeStack( const CStack * stack ) | ||||
| 	ba.stackNumber = stack->ID; | ||||
| 	return ba; | ||||
| } | ||||
| 
 | ||||
| CGlobalAI::CGlobalAI() | ||||
| { | ||||
| 	human = false; | ||||
| } | ||||
| 
 | ||||
| void CAdventureAI::battleNewRound(int round) | ||||
| { | ||||
| 	battleAI->battleNewRound(round); | ||||
| } | ||||
| 
 | ||||
| void CAdventureAI::battleCatapultAttacked(const CatapultAttack & ca) | ||||
| { | ||||
| 	battleAI->battleCatapultAttacked(ca); | ||||
| } | ||||
| 
 | ||||
| void CAdventureAI::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) | ||||
| { | ||||
| 	assert(!battleAI); | ||||
| 	battleAI = CDynLibHandler::getNewBattleAI(battleAIName); | ||||
| 	battleAI->battleStart(army1, army2, tile, hero1, hero2, side); | ||||
| } | ||||
| 
 | ||||
| void CAdventureAI::battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa) | ||||
| { | ||||
| 	battleAI->battleStacksAttacked(bsa); | ||||
| } | ||||
| 
 | ||||
| void CAdventureAI::actionStarted(const BattleAction *action) | ||||
| { | ||||
| 	battleAI->actionStarted(action); | ||||
| } | ||||
| 
 | ||||
| void CAdventureAI::battleNewRoundFirst(int round) | ||||
| { | ||||
| 	battleAI->battleNewRoundFirst(round); | ||||
| } | ||||
| 
 | ||||
| void CAdventureAI::actionFinished(const BattleAction *action) | ||||
| { | ||||
| 	battleAI->actionFinished(action); | ||||
| } | ||||
| 
 | ||||
| void CAdventureAI::battleStacksEffectsSet(const SetStackEffect & sse) | ||||
| { | ||||
| 	battleAI->battleStacksEffectsSet(sse); | ||||
| } | ||||
| 
 | ||||
| void CAdventureAI::battleStacksRemoved(const BattleStacksRemoved & bsr) | ||||
| { | ||||
| 	battleAI->battleStacksRemoved(bsr); | ||||
| } | ||||
| 
 | ||||
| void CAdventureAI::battleObstaclesRemoved(const std::set<si32> & removedObstacles) | ||||
| { | ||||
| 	battleAI->battleObstaclesRemoved(removedObstacles); | ||||
| } | ||||
| 
 | ||||
| void CAdventureAI::battleNewStackAppeared(const CStack * stack) | ||||
| { | ||||
| 	battleAI->battleNewStackAppeared(stack); | ||||
| } | ||||
| 
 | ||||
| void CAdventureAI::battleStackMoved(const CStack * stack, THex dest, int distance, bool end) | ||||
| { | ||||
| 	battleAI->battleStackMoved(stack, dest, distance, end); | ||||
| } | ||||
| 
 | ||||
| void CAdventureAI::battleAttack(const BattleAttack *ba) | ||||
| { | ||||
| 	battleAI->battleAttack(ba); | ||||
| } | ||||
| 
 | ||||
| void CAdventureAI::battleSpellCast(const BattleSpellCast *sc) | ||||
| { | ||||
| 	battleAI->battleSpellCast(sc); | ||||
| } | ||||
| 
 | ||||
| void CAdventureAI::battleEnd(const BattleResult *br) | ||||
| { | ||||
| 	battleAI->battleEnd(br); | ||||
| 	delNull(battleAI); | ||||
| } | ||||
| 
 | ||||
| void CAdventureAI::battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom) | ||||
| { | ||||
| 	battleAI->battleStacksHealedRes(healedStacks, lifeDrain, tentHeal, lifeDrainFrom); | ||||
| } | ||||
| @@ -1,11 +1,10 @@ | ||||
| #ifndef __CGAMEINTERFACE_H__ | ||||
| #define __CGAMEINTERFACE_H__ | ||||
| #include "global.h" | ||||
| #include "../global.h" | ||||
| #include <set> | ||||
| #include <vector> | ||||
| #include "lib/BattleAction.h" | ||||
| #include "client/FunctionList.h" | ||||
| #include "lib/IGameEventsReceiver.h" | ||||
| #include "BattleAction.h" | ||||
| #include "IGameEventsReceiver.h" | ||||
| 
 | ||||
| /*
 | ||||
|  * CGameInterface.h, part of VCMI engine | ||||
| @@ -83,7 +82,7 @@ public: | ||||
| 	virtual void serialize(CISer<CLoadFile> &h, const int version){}; //loading
 | ||||
| }; | ||||
| 
 | ||||
| class CDynLibHandler | ||||
| class DLL_EXPORT CDynLibHandler | ||||
| { | ||||
| public: | ||||
| 	static CGlobalAI * getNewAI(std::string dllname); | ||||
| @@ -91,10 +90,10 @@ public: | ||||
| 	static CScriptingModule * getNewScriptingModule(std::string dllname); | ||||
| }; | ||||
| 
 | ||||
| class CGlobalAI : public CGameInterface // AI class (to derivate)
 | ||||
| class DLL_EXPORT CGlobalAI : public CGameInterface // AI class (to derivate)
 | ||||
| { | ||||
| public: | ||||
| 	//CGlobalAI();
 | ||||
| 	CGlobalAI(); | ||||
| 	virtual void yourTurn() OVERRIDE{}; | ||||
| 	virtual void heroKilled(const CGHeroInstance*){}; | ||||
| 	virtual void heroCreated(const CGHeroInstance*) OVERRIDE{}; | ||||
| @@ -104,4 +103,34 @@ public: | ||||
| 	virtual BattleAction activeStack(const CStack * stack) OVERRIDE; | ||||
| }; | ||||
| 
 | ||||
| //class to  be inherited by adventure-only AIs, it cedes battle actions to given battle-AI
 | ||||
| class DLL_EXPORT CAdventureAI : public CGlobalAI | ||||
| { | ||||
| public: | ||||
| 	CAdventureAI() : battleAI(NULL) {}; | ||||
| 	CAdventureAI(const std::string &BattleAIName) : battleAIName(BattleAIName), battleAI(NULL) {}; | ||||
| 
 | ||||
| 	std::string battleAIName; | ||||
| 	CBattleGameInterface *battleAI; | ||||
| 
 | ||||
| 	//battle interface
 | ||||
| 	virtual void battleNewRound(int round); | ||||
| 	virtual void battleCatapultAttacked(const CatapultAttack & ca); | ||||
| 	virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side); | ||||
| 	virtual void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa); | ||||
| 	virtual void actionStarted(const BattleAction *action); | ||||
| 	virtual void battleNewRoundFirst(int round); | ||||
| 	virtual void actionFinished(const BattleAction *action); | ||||
| 	virtual void battleStacksEffectsSet(const SetStackEffect & sse); | ||||
| 	virtual void battleStacksRemoved(const BattleStacksRemoved & bsr); | ||||
| 	virtual void battleObstaclesRemoved(const std::set<si32> & removedObstacles); | ||||
| 	virtual void battleNewStackAppeared(const CStack * stack); | ||||
| 	virtual void battleStackMoved(const CStack * stack, THex dest, int distance, bool end); | ||||
| 	virtual void battleAttack(const BattleAttack *ba); | ||||
| 	virtual void battleSpellCast(const BattleSpellCast *sc); | ||||
| 	virtual void battleEnd(const BattleResult *br); | ||||
| 	virtual void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom); | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #endif // __CGAMEINTERFACE_H__
 | ||||
| @@ -1184,7 +1184,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed ) | ||||
| 	} | ||||
|  | ||||
| 	/******************RESOURCES****************************************************/ | ||||
| 	std::vector<int> startresAI, startresHuman; | ||||
| 	TResources startresAI, startresHuman; | ||||
| 	std::ifstream tis(DATA_DIR "/config/startres.txt"); | ||||
| 	int k; | ||||
| 	for (int j=0; j<scenarioOps->difficulty * 2; j++) | ||||
| @@ -1195,32 +1195,22 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed ) | ||||
| 	} | ||||
| 	tis >> k; | ||||
| 	for (int i=0; i<RESOURCE_QUANTITY; i++) | ||||
| 	{ | ||||
| 		tis >> k; | ||||
| 		startresHuman.push_back(k); | ||||
| 	} | ||||
| 		tis >> startresHuman[i]; | ||||
|  | ||||
| 	tis >> k; | ||||
| 	for (int i=0; i<RESOURCE_QUANTITY; i++) | ||||
| 	{ | ||||
| 		tis >> k; | ||||
| 		startresAI.push_back(k); | ||||
| 	} | ||||
| 		tis >> startresAI[i]; | ||||
|  | ||||
| 	tis.close(); | ||||
| 	tis.clear(); | ||||
| 	for (std::map<ui8,PlayerState>::iterator i = players.begin(); i!=players.end(); i++) | ||||
| 	{ | ||||
| 		(*i).second.resources.resize(RESOURCE_QUANTITY); | ||||
| 		for (int x=0;x<RESOURCE_QUANTITY;x++) | ||||
| 		{ | ||||
| 			if (i->second.human) | ||||
| 			{ | ||||
| 				(*i).second.resources[x] = startresHuman[x]; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				(*i).second.resources[x] = startresAI[x]; | ||||
| 			} | ||||
| 		} | ||||
| 		PlayerState &p = i->second; | ||||
|  | ||||
| 		if (p.human) | ||||
| 			p.resources = startresHuman; | ||||
| 		else | ||||
| 			p.resources = startresAI; | ||||
| 	} | ||||
|  | ||||
| 	//give start resource bonus in case of campaign | ||||
| @@ -1231,7 +1221,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed ) | ||||
| 		if(chosenBonus.type == 7) //resource | ||||
| 		{ | ||||
| 			std::vector<const PlayerSettings *> people = HLP::getHumanPlayerInfo(scenarioOps); //players we will give resource bonus | ||||
| 			for (int b=0; b<people.size(); ++b) | ||||
| 			BOOST_FOREACH(const PlayerSettings *ps, people) | ||||
| 			{ | ||||
| 				std::vector<int> res; //resources we will give | ||||
| 				switch (chosenBonus.info1) | ||||
| @@ -1240,10 +1230,10 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed ) | ||||
| 					res.push_back(chosenBonus.info1); | ||||
| 					break; | ||||
| 				case 0xFD: //wood+ore | ||||
| 					res.push_back(0); res.push_back(2); | ||||
| 					res.push_back(Res::WOOD); res.push_back(Res::ORE); | ||||
| 					break; | ||||
| 				case 0xFE:  //rare | ||||
| 					res.push_back(1); res.push_back(3); res.push_back(4); res.push_back(5); | ||||
| 					res.push_back(Res::MERCURY); res.push_back(Res::SULFUR); res.push_back(Res::CRYSTAL); res.push_back(Res::GEMS); | ||||
| 					break; | ||||
| 				default: | ||||
| 					assert(0); | ||||
| @@ -1252,7 +1242,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed ) | ||||
| 				//increasing resource quantity | ||||
| 				for (int n=0; n<res.size(); ++n) | ||||
| 				{ | ||||
| 					players[people[b]->color].resources[res[n]] += chosenBonus.info2; | ||||
| 					players[ps->color].resources[res[n]] += chosenBonus.info2; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| @@ -1393,15 +1383,15 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed ) | ||||
| 		switch(scenarioOps->playerInfos[k->first].bonus) | ||||
| 		{ | ||||
| 		case PlayerSettings::bgold: | ||||
| 			k->second.resources[6] += 500 + (ran()%6)*100; | ||||
| 			k->second.resources[Res::GOLD] += 500 + (ran()%6)*100; | ||||
| 			break; | ||||
| 		case PlayerSettings::bresource: | ||||
| 			{ | ||||
| 				int res = VLC->townh->towns[scenarioOps->playerInfos[k->first].castle].primaryRes; | ||||
| 				if(res == 127) | ||||
| 				{ | ||||
| 					k->second.resources[0] += 5 + ran()%6; | ||||
| 					k->second.resources[2] += 5 + ran()%6; | ||||
| 					k->second.resources[Res::WOOD] += 5 + ran()%6; | ||||
| 					k->second.resources[Res::ORE] += 5 + ran()%6; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| @@ -1682,10 +1672,10 @@ UpgradeInfo CGameState::getUpgradeInfo(const CStackInstance &stack) | ||||
| 		BOOST_FOREACH(const Bonus *it, *lista) | ||||
| 		{ | ||||
| 			ui16 nid = it->additionalInfo; | ||||
| 			if (nid != base->idNumber) //in very specific case the upgrade is avaliable by default (?) | ||||
| 			if (nid != base->idNumber) //in very specific case the upgrade is available by default (?) | ||||
| 			{ | ||||
| 				ret.newID.push_back(nid); | ||||
| 				ret.cost.push_back(costDiff(VLC->creh->creatures[nid]->cost, base->cost)); | ||||
| 				ret.cost.push_back(VLC->creh->creatures[nid]->cost - base->cost); | ||||
| 			} | ||||
| 		} | ||||
| 		t = h->visitedTown; | ||||
| @@ -1700,7 +1690,7 @@ UpgradeInfo CGameState::getUpgradeInfo(const CStackInstance &stack) | ||||
| 				if(vstd::contains(base->upgrades, nid)) //possible upgrade | ||||
| 				{ | ||||
| 					ret.newID.push_back(nid); | ||||
| 					ret.cost.push_back(costDiff(VLC->creh->creatures[nid]->cost, base->cost)); | ||||
| 					ret.cost.push_back(VLC->creh->creatures[nid]->cost - base->cost); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| @@ -1715,7 +1705,7 @@ UpgradeInfo CGameState::getUpgradeInfo(const CStackInstance &stack) | ||||
| 		BOOST_FOREACH(si32 nid, base->upgrades) | ||||
| 		{ | ||||
| 			ret.newID.push_back(nid); | ||||
| 			ret.cost.push_back(costDiff(VLC->creh->creatures[nid]->cost, base->cost, costModifier)); | ||||
| 			ret.cost.push_back((VLC->creh->creatures[nid]->cost - base->cost) * costModifier / 100); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -2619,15 +2609,15 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level) | ||||
| 	} | ||||
| 	if(level >= 2) //gold | ||||
| 	{ | ||||
| 		FILL_FIELD(gold, g->second.resources[6]) | ||||
| 		FILL_FIELD(gold, g->second.resources[Res::GOLD]) | ||||
| 	} | ||||
| 	if(level >= 2) //wood & ore | ||||
| 	{ | ||||
| 		FILL_FIELD(woodOre, g->second.resources[0] + g->second.resources[1]) | ||||
| 		FILL_FIELD(woodOre, g->second.resources[Res::WOOD] + g->second.resources[Res::ORE]) | ||||
| 	} | ||||
| 	if(level >= 3) //mercury, sulfur, crystal, gems | ||||
| 	{ | ||||
| 		FILL_FIELD(mercSulfCrystGems, g->second.resources[2] + g->second.resources[3] + g->second.resources[4] + g->second.resources[5]) | ||||
| 		FILL_FIELD(mercSulfCrystGems, g->second.resources[Res::MERCURY] + g->second.resources[Res::SULFUR] + g->second.resources[Res::CRYSTAL] + g->second.resources[Res::GEMS]) | ||||
| 	} | ||||
| 	if(level >= 4) //obelisks found | ||||
| 	{ | ||||
|   | ||||
| @@ -23,6 +23,7 @@ | ||||
|  | ||||
| #include "ConstTransitivePtr.h" | ||||
| #include "IGameCallback.h" | ||||
| #include "ResourceSet.h" | ||||
|  | ||||
|  | ||||
| /* | ||||
| @@ -161,7 +162,7 @@ public: | ||||
| 	ui8 human; //true if human controlled player, false for AI | ||||
| 	ui32 currentSelection; //id of hero/town, 0xffffffff if none | ||||
| 	ui8 team; | ||||
| 	std::vector<si32> resources; | ||||
| 	TResources resources; | ||||
| 	std::vector<ConstTransitivePtr<CGHeroInstance> > heroes; | ||||
| 	std::vector<ConstTransitivePtr<CGTownInstance> > towns; | ||||
| 	std::vector<ConstTransitivePtr<CGHeroInstance> > availableHeroes; //heroes available in taverns | ||||
| @@ -209,7 +210,7 @@ struct UpgradeInfo | ||||
| { | ||||
| 	int oldID; //creature to be upgraded | ||||
| 	std::vector<int> newID; //possible upgrades | ||||
| 	std::vector<std::set<std::pair<int,int> > > cost; // cost[upgrade_serial] -> set of pairs<resource_ID,resource_amount> | ||||
| 	std::vector<TResources> cost; // cost[upgrade_serial] -> set of pairs<resource_ID,resource_amount>; cost is for single unit (not entire stack) | ||||
| 	UpgradeInfo(){oldID = -1;}; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -848,11 +848,8 @@ int CGameInfoCallback::canBuildStructure( const CGTownInstance *t, int ID ) | ||||
| 		return Buildings::ERROR; | ||||
|  | ||||
| 	//checking resources | ||||
| 	for(int res=0; res<RESOURCE_QUANTITY; res++) | ||||
| 	{ | ||||
| 		if(pom->resources[res] > getResource(t->tempOwner, res)) | ||||
| 			ret = Buildings::NO_RESOURCES; //lack of res | ||||
| 	} | ||||
| 	if(pom->resources.canBeAfforded(getPlayer(t->tempOwner)->resources)) | ||||
| 		ret = Buildings::NO_RESOURCES; //lack of res | ||||
|  | ||||
| 	//checking for requirements | ||||
| 	std::set<int> reqs = getBuildingRequiments(t, ID);//getting all requirements | ||||
| @@ -1122,10 +1119,10 @@ int CPlayerSpecificInfoCallback::getResourceAmount(int type) const | ||||
| 	return getResource(player, type); | ||||
| } | ||||
|  | ||||
| std::vector<si32> CPlayerSpecificInfoCallback::getResourceAmount() const | ||||
| TResources CPlayerSpecificInfoCallback::getResourceAmount() const | ||||
| { | ||||
| 	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx); | ||||
| 	ERROR_RET_VAL_IF(player == -1, "Applicable only for player callbacks", std::vector<si32>()); | ||||
| 	ERROR_RET_VAL_IF(player == -1, "Applicable only for player callbacks", TResources()); | ||||
| 	return gs->players[player].resources; | ||||
| } | ||||
|  | ||||
| @@ -1214,7 +1211,7 @@ const CGObjectInstance * IGameCallback::putNewObject(int ID, int subID, int3 pos | ||||
| 	no.subID= subID; | ||||
| 	no.pos = pos; | ||||
| 	commitPackage(&no); | ||||
| 	return getObj(no.id); //id field will be filled during applaying on gs | ||||
| 	return getObj(no.id); //id field will be filled during applying on gs | ||||
| } | ||||
|  | ||||
| const CGCreature * IGameCallback::putNewMonster(int creID, int count, int3 pos) | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
| #include <set> | ||||
| #include "../client/FunctionList.h" | ||||
| #include "CObstacleInstance.h" | ||||
| #include "ResourceSet.h" | ||||
|  | ||||
| /* | ||||
|  * IGameCallback.h, part of VCMI engine | ||||
| @@ -213,7 +214,7 @@ public: | ||||
| 	std::vector <const CGObjectInstance * > getMyObjects() const; //returns all objects flagged by belonging player | ||||
|  | ||||
| 	int getResourceAmount(int type)const; | ||||
| 	std::vector<si32> getResourceAmount() const; | ||||
| 	TResources getResourceAmount() const; | ||||
| 	const std::vector< std::vector< std::vector<unsigned char> > > & getVisibilityMap()const; //returns visibility map  | ||||
| 	const PlayerSettings * getPlayerSettings(int color) const; | ||||
| }; | ||||
|   | ||||
| @@ -10,6 +10,7 @@ | ||||
| #include "../StartInfo.h" | ||||
| #include "ConstTransitivePtr.h" | ||||
| #include "../int3.h" | ||||
| #include "ResourceSet.h" | ||||
|  | ||||
| /* | ||||
|  * NetPacks.h, part of VCMI engine | ||||
| @@ -238,12 +239,12 @@ struct SetResource : public CPackForClient //102 | ||||
| };  | ||||
|  struct SetResources : public CPackForClient //104 | ||||
|  { | ||||
|  	SetResources(){res.resize(RESOURCE_QUANTITY);type = 104;}; | ||||
|  	SetResources(){type = 104;}; | ||||
|  	void applyCl(CClient *cl); | ||||
|  	DLL_EXPORT void applyGs(CGameState *gs); | ||||
|   | ||||
|  	ui8 player; | ||||
|  	std::vector<si32> res; //res[resid] => res amount | ||||
|  	TResources res; //res[resid] => res amount | ||||
|   | ||||
|  	template <typename Handler> void serialize(Handler &h, const int version) | ||||
|  	{ | ||||
| @@ -965,7 +966,7 @@ struct NewTurn : public CPackForClient //101 | ||||
|  | ||||
| 	std::set<Hero> heroes; //updates movement and mana points | ||||
| 	//std::vector<SetResources> res;//resource list | ||||
| 	std::map<ui8, std::vector<si32> > res; //player ID => resource value[res_id] | ||||
| 	std::map<ui8, TResources> res; //player ID => resource value[res_id] | ||||
| 	std::vector<SetAvailableCreatures> cres;//creatures to be placed in towns | ||||
| 	ui32 day; | ||||
| 	bool resetBuilded; | ||||
|   | ||||
| @@ -45,12 +45,11 @@ DLL_EXPORT void SetResource::applyGs( CGameState *gs ) | ||||
| 	gs->getPlayer(player)->resources[resid] = val; | ||||
| } | ||||
|  | ||||
|  DLL_EXPORT void SetResources::applyGs( CGameState *gs ) | ||||
|  { | ||||
|  	assert(player < PLAYER_LIMIT); | ||||
|  	for(int i=0;i<res.size();i++) | ||||
|  		gs->getPlayer(player)->resources[i] = res[i]; | ||||
|  } | ||||
| DLL_EXPORT void SetResources::applyGs( CGameState *gs ) | ||||
| { | ||||
| 	assert(player < PLAYER_LIMIT); | ||||
| 	gs->getPlayer(player)->resources = res; | ||||
| } | ||||
|  | ||||
| DLL_EXPORT void SetPrimSkill::applyGs( CGameState *gs ) | ||||
| { | ||||
| @@ -751,12 +750,10 @@ DLL_EXPORT void NewTurn::applyGs( CGameState *gs ) | ||||
| 		hero->mana = h.mana; | ||||
| 	} | ||||
|  | ||||
| 	for(std::map<ui8, std::vector<si32> >::iterator i = res.begin(); i != res.end(); i++) | ||||
| 	for(std::map<ui8, TResources>::iterator i = res.begin(); i != res.end(); i++) | ||||
| 	{ | ||||
| 		assert(i->first < PLAYER_LIMIT); | ||||
| 		std::vector<si32> &playerRes = gs->getPlayer(i->first)->resources; | ||||
| 		for(int j = 0;  j < i->second.size();  j++) | ||||
| 			playerRes[j] = i->second[j]; | ||||
| 		gs->getPlayer(i->first)->resources = i->second; | ||||
| 	} | ||||
|  | ||||
| 	BOOST_FOREACH(SetAvailableCreatures h, cres) //set available creatures in towns | ||||
|   | ||||
							
								
								
									
										91
									
								
								lib/ResourceSet.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								lib/ResourceSet.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | ||||
| #define VCMI_DLL | ||||
| #include "ResourceSet.h" | ||||
|  | ||||
| Res::ResourceSet::ResourceSet() | ||||
| { | ||||
| 	resize(RESOURCE_QUANTITY, 0); | ||||
| } | ||||
|  | ||||
| bool Res::ResourceSet::nonZero() const | ||||
| { | ||||
| 	for(int i = 0; i < size(); i++) | ||||
| 		if(at(i)) | ||||
| 			return true; | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| void Res::ResourceSet::amax(const TResource &val) | ||||
| { | ||||
| 	for(int i = 0; i < size(); i++) | ||||
| 		::amax(at(i), val); | ||||
| } | ||||
|  | ||||
| bool Res::ResourceSet::canBeAfforded(const ResourceSet &res) const | ||||
| { | ||||
| 	return Res::canAfford(res, *this); | ||||
| } | ||||
|  | ||||
| bool Res::ResourceSet::canAfford(const ResourceSet &price) const | ||||
| { | ||||
| 	return Res::canAfford(*this, price); | ||||
| } | ||||
|  | ||||
| bool Res::canAfford(const ResourceSet &res, const ResourceSet &price) | ||||
| { | ||||
| 	assert(res.size() == price.size() && price.size() == RESOURCE_QUANTITY); | ||||
| 	for(int i = 0; i < RESOURCE_QUANTITY; i++) | ||||
| 		if(price[i] > res[i]) | ||||
| 			return false; | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool Res::ResourceSet::nziterator::valid() | ||||
| { | ||||
| 	return cur.resType < RESOURCE_QUANTITY && cur.resVal; | ||||
| } | ||||
|  | ||||
| Res::ResourceSet::nziterator Res::ResourceSet::nziterator::operator++() | ||||
| { | ||||
| 	advance(); | ||||
| 	return *this; | ||||
| } | ||||
|  | ||||
| Res::ResourceSet::nziterator Res::ResourceSet::nziterator::operator++(int) | ||||
| { | ||||
| 	nziterator ret = *this; | ||||
| 	advance(); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| const Res::ResourceSet::nziterator::ResEntry& Res::ResourceSet::nziterator::operator*() const | ||||
| { | ||||
| 	return cur; | ||||
| } | ||||
|  | ||||
| const Res::ResourceSet::nziterator::ResEntry * Res::ResourceSet::nziterator::operator->() const | ||||
| { | ||||
| 	return &cur; | ||||
| } | ||||
|  | ||||
| void Res::ResourceSet::nziterator::advance() | ||||
| { | ||||
| 	do | ||||
| 	{ | ||||
| 		cur.resType++; | ||||
| 	} while(cur.resType < RESOURCE_QUANTITY && !(cur.resVal=rs[cur.resType])); | ||||
|  | ||||
| 	if(cur.resType >= RESOURCE_QUANTITY) | ||||
| 		cur.resVal = -1; | ||||
| } | ||||
|  | ||||
| Res::ResourceSet::nziterator::nziterator(const ResourceSet &RS) | ||||
| 	: rs(RS) | ||||
| { | ||||
| 	cur.resType = 0; | ||||
| 	cur.resVal = rs[0]; | ||||
|  | ||||
| 	if(!valid()) | ||||
| 		advance(); | ||||
| } | ||||
							
								
								
									
										123
									
								
								lib/ResourceSet.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								lib/ResourceSet.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include"../global.h" | ||||
|  | ||||
| typedef si32 TResource; | ||||
|  | ||||
| namespace Res | ||||
| { | ||||
| 	class ResourceSet; | ||||
| 	bool canAfford(const ResourceSet &res, const ResourceSet &price); //can a be used to pay price b | ||||
|  | ||||
| 	enum ERes  | ||||
| 	{ | ||||
| 		WOOD = 0, MERCURY, ORE, SULFUR, CRYSTAL, GEMS, GOLD, MITHRIL | ||||
| 	}; | ||||
|  | ||||
| 	//class to be representing a vector of resource | ||||
| 	class ResourceSet : public std::vector<int> | ||||
| 	{ | ||||
| 	public: | ||||
| 		DLL_EXPORT ResourceSet(); | ||||
|  | ||||
|  | ||||
| #define scalarOperator(OPSIGN)									\ | ||||
| 		DLL_EXPORT ResourceSet operator OPSIGN(const TResource &rhs) const	\ | ||||
| 		{														\ | ||||
| 			ResourceSet ret = *this;							\ | ||||
| 			for(int i = 0; i < size(); i++)						\ | ||||
| 				ret[i] = at(i) OPSIGN rhs;						\ | ||||
| 																\ | ||||
| 			return ret;											\ | ||||
| 		} | ||||
|  | ||||
|  | ||||
|  | ||||
| #define vectorOperator(OPSIGN)										\ | ||||
| 		DLL_EXPORT ResourceSet operator OPSIGN(const ResourceSet &rhs) const	\ | ||||
| 		{															\ | ||||
| 			ResourceSet ret = *this;								\ | ||||
| 			for(int i = 0; i < size(); i++)							\ | ||||
| 				ret[i] = at(i) OPSIGN rhs[i];						\ | ||||
| 																	\ | ||||
| 			return ret;												\ | ||||
| 		} | ||||
|  | ||||
|  | ||||
| #define opEqOperator(OPSIGN, RHS_TYPE)							\ | ||||
| 		DLL_EXPORT ResourceSet& operator OPSIGN ## =(const RHS_TYPE &rhs)	\ | ||||
| 		{														\ | ||||
| 			return *this = *this OPSIGN rhs;					\ | ||||
| 		} | ||||
|  | ||||
| 		scalarOperator(+) | ||||
| 		scalarOperator(-) | ||||
| 		scalarOperator(*) | ||||
| 		scalarOperator(/) | ||||
| 		opEqOperator(+, TResource) | ||||
| 		opEqOperator(-, TResource) | ||||
| 		opEqOperator(*, TResource) | ||||
| 		vectorOperator(+) | ||||
| 		vectorOperator(-) | ||||
| 		opEqOperator(+, ResourceSet) | ||||
| 		opEqOperator(-, ResourceSet) | ||||
|  | ||||
| #undef scalarOperator | ||||
| #undef vectorOperator | ||||
| #undef opEqOperator | ||||
|  | ||||
| 		//to be used for calculations of type "how many units of sth can I afford?" | ||||
| 		DLL_EXPORT int operator/(const ResourceSet &rhs) | ||||
| 		{ | ||||
| 			int ret = INT_MAX; | ||||
| 			for(int i = 0; i < size(); i++) | ||||
| 				amin(ret, at(i) / rhs[i]); | ||||
|  | ||||
| 			return ret; | ||||
| 		} | ||||
|  | ||||
| 	// WARNING: comparison operators are used for "can afford" relation: a <= b means that foreach i a[i] <= b[i]  | ||||
| 	// that doesn't work the other way: a > b doesn't mean that a cannot be afforded with b, it's still b can afford a | ||||
| // 		bool operator<(const ResourceSet &rhs) | ||||
| // 		{ | ||||
| // 			for(int i = 0; i < size(); i++) | ||||
| // 				if(at(i) >= rhs[i]) | ||||
| // 					return false; | ||||
| //  | ||||
| // 			return true; | ||||
| // 		} | ||||
|  | ||||
| 		template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 		{ | ||||
| 			h & static_cast<std::vector<int>&>(*this); | ||||
| 		} | ||||
|  | ||||
| 		DLL_EXPORT void amax(const TResource &val); //performs amax on each element | ||||
| 		DLL_EXPORT bool nonZero() const; //returns true if at least one value is non-zero; | ||||
| 		DLL_EXPORT bool canAfford(const ResourceSet &price) const; | ||||
| 		DLL_EXPORT bool canBeAfforded(const ResourceSet &res) const; | ||||
|  | ||||
| 		//special iterator of iterating over non-zero resources in set | ||||
| 		class DLL_EXPORT nziterator | ||||
| 		{ | ||||
| 			struct ResEntry | ||||
| 			{ | ||||
| 				TResource resType, resVal; | ||||
| 			} cur; | ||||
| 			const ResourceSet &rs; | ||||
| 			void advance(); | ||||
| 		 | ||||
| 		public: | ||||
| 			nziterator(const ResourceSet &RS); | ||||
| 			bool valid(); | ||||
| 			nziterator operator++(); | ||||
| 			nziterator operator++(int); | ||||
| 			const ResEntry& operator*() const; | ||||
| 			const ResEntry* operator->() const; | ||||
| 		 | ||||
| 		}; | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| typedef Res::ResourceSet TResources; | ||||
|  | ||||
| @@ -173,6 +173,7 @@ | ||||
|     <ClCompile Include="CCreatureSet.cpp" /> | ||||
|     <ClCompile Include="CDefObjInfoHandler.cpp" /> | ||||
|     <ClCompile Include="CFileUtility.cpp" /> | ||||
|     <ClCompile Include="CGameInterface.cpp" /> | ||||
|     <ClCompile Include="CGameState.cpp" /> | ||||
|     <ClCompile Include="CGeneralTextHandler.cpp" /> | ||||
|     <ClCompile Include="CHeroHandler.cpp" /> | ||||
| @@ -188,6 +189,7 @@ | ||||
|     <ClCompile Include="NetPacksLib.cpp" /> | ||||
|     <ClCompile Include="RegisterTypes.cpp" /> | ||||
|     <ClCompile Include="..\stdafx.cpp" /> | ||||
|     <ClCompile Include="ResourceSet.cpp" /> | ||||
|     <ClCompile Include="VCMI_Lib.cpp" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
| @@ -203,6 +205,7 @@ | ||||
|     <ClInclude Include="CCreatureSet.h" /> | ||||
|     <ClInclude Include="CDefObjInfoHandler.h" /> | ||||
|     <ClInclude Include="CFileUtility.h" /> | ||||
|     <ClInclude Include="CGameInterface.h" /> | ||||
|     <ClInclude Include="CGameState.h" /> | ||||
|     <ClInclude Include="CGeneralTextHandler.h" /> | ||||
|     <ClInclude Include="CHeroHandler.h" /> | ||||
| @@ -223,6 +226,7 @@ | ||||
|     <ClInclude Include="map.h" /> | ||||
|     <ClInclude Include="NetPacks.h" /> | ||||
|     <ClInclude Include="RegisterTypes.h" /> | ||||
|     <ClInclude Include="ResourceSet.h" /> | ||||
|     <ClInclude Include="VCMI_Lib.h" /> | ||||
|     <ClInclude Include="VCMIDirs.h" /> | ||||
|   </ItemGroup> | ||||
|   | ||||
| @@ -724,7 +724,6 @@ void Mapa::loadTown( CGObjectInstance * &nobj, const unsigned char * bufor, int | ||||
| 		nce->town = nt; | ||||
| 		nce->name = readString(bufor,i); | ||||
| 		nce->message = readString(bufor,i); | ||||
| 		nce->resources.resize(RESOURCE_QUANTITY); | ||||
| 		for(int x=0; x < 7; x++) | ||||
| 		{ | ||||
| 			nce->resources[x] = readNormalNr(bufor,i);  | ||||
| @@ -1885,7 +1884,6 @@ void Mapa::readEvents( const unsigned char * bufor, int &i ) | ||||
| 		{ | ||||
| 			ne->message +=bufor[i]; ++i; | ||||
| 		} | ||||
| 		ne->resources.resize(RESOURCE_QUANTITY); | ||||
| 		for(int k=0; k < 7; k++) | ||||
| 		{ | ||||
| 			ne->resources[k] = readNormalNr(bufor,i); i+=4; | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| #endif | ||||
|  | ||||
| #include "ConstTransitivePtr.h" | ||||
| #include "ResourceSet.h" | ||||
|  | ||||
| /* | ||||
|  * map.h, part of VCMI engine | ||||
| @@ -211,7 +212,7 @@ class DLL_EXPORT CMapEvent | ||||
| { | ||||
| public: | ||||
| 	std::string name, message; | ||||
| 	std::vector<si32> resources; //gained / taken resources | ||||
| 	TResources resources; //gained / taken resources | ||||
| 	ui8 players; //affected players | ||||
| 	ui8 humanAffected; | ||||
| 	ui8 computerAffected; | ||||
|   | ||||
| @@ -924,11 +924,7 @@ void CGameHandler::newTurn() | ||||
| 		} | ||||
|  | ||||
| 		n.res[i->first] = i->second.resources; | ||||
| // 		SetResources r; | ||||
| // 		r.player = i->first; | ||||
| // 		for(int j=0;j<RESOURCE_QUANTITY;j++) | ||||
| // 			r.res[j] = i->second.resources[j]; | ||||
| 		 | ||||
|  | ||||
| 		BOOST_FOREACH(CGHeroInstance *h, (*i).second.heroes) | ||||
| 		{ | ||||
| 			if(h->visitedTown) | ||||
| @@ -955,7 +951,6 @@ void CGameHandler::newTurn() | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		//n.res.push_back(r); | ||||
| 	} | ||||
| 	//      townID,    creatureID, amount | ||||
| 	std::map<si32, std::map<si32, si32> > newCreas;//creatures that needs to be added by town events | ||||
| @@ -987,7 +982,7 @@ void CGameHandler::newTurn() | ||||
| 					n.res[player][(**j).town->primaryRes] ++;; | ||||
| 				} | ||||
| 			} | ||||
| 			n.res[player][6] += (**j).dailyIncome(); | ||||
| 			n.res[player][Res::GOLD] += (**j).dailyIncome(); | ||||
| 		} | ||||
| 		handleTownEvents(*j, n, newCreas); | ||||
| 		if (vstd::contains((**j).builtBuildings, 26))  | ||||
| @@ -2211,9 +2206,7 @@ bool CGameHandler::buildStructure( si32 tid, si32 bid, bool force /*=false*/ ) | ||||
| 	{ | ||||
| 		SetResources sr; | ||||
| 		sr.player = t->tempOwner; | ||||
| 		sr.res = gs->getPlayer(t->tempOwner)->resources; | ||||
| 		for(int i=0;i<b->resources.size();i++) | ||||
| 			sr.res[i]-=b->resources[i]; | ||||
| 		sr.res = gs->getPlayer(t->tempOwner)->resources - b->resources; | ||||
| 		sendAndApply(&sr); | ||||
| 	} | ||||
|  | ||||
| @@ -2315,8 +2308,7 @@ bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram, si32 from | ||||
| 	//recruit | ||||
| 	SetResources sr; | ||||
| 	sr.player = dst->tempOwner; | ||||
| 	for(int i=0;i<RESOURCE_QUANTITY;i++) | ||||
| 		sr.res[i]  =  gs->getPlayer(dst->tempOwner)->resources[i] - (c->cost[i] * cram); | ||||
| 	sr.res = gs->getPlayer(dst->tempOwner)->resources - (c->cost * cram); | ||||
|  | ||||
| 	SetAvailableCreatures sac; | ||||
| 	sac.tid = objid; | ||||
| @@ -2361,8 +2353,10 @@ bool CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID ) | ||||
| 	assert(obj->hasStackAtSlot(pos)); | ||||
| 	UpgradeInfo ui = gs->getUpgradeInfo(obj->getStack(pos)); | ||||
| 	int player = obj->tempOwner; | ||||
| 	const PlayerState *p = getPlayer(player); | ||||
| 	int crQuantity = obj->stacks[pos]->count; | ||||
| 	int newIDpos= vstd::findPos(ui.newID, upgID);//get position of new id in UpgradeInfo | ||||
| 	TResources totalCost = ui.cost[newIDpos] * crQuantity; | ||||
|  | ||||
| 	//check if upgrade is possible | ||||
| 	if( (ui.oldID<0 || newIDpos == -1 ) && complain("That upgrade is not possible!"))  | ||||
| @@ -2372,24 +2366,14 @@ bool CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID ) | ||||
| 	 | ||||
|  | ||||
| 	//check if player has enough resources | ||||
| 	for (std::set<std::pair<int,int> >::iterator j=ui.cost[newIDpos].begin(); j!=ui.cost[newIDpos].end(); j++) | ||||
| 	{ | ||||
| 		if(gs->getPlayer(player)->resources[j->first] < j->second*crQuantity) | ||||
| 		{ | ||||
| 			complain("Cannot upgrade, not enough resources!"); | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| 	if(!p->resources.canAfford(totalCost)) | ||||
| 		COMPLAIN_RET("Cannot upgrade, not enough resources!"); | ||||
| 	 | ||||
| 	//take resources | ||||
| 	for (std::set<std::pair<int,int> >::iterator j=ui.cost[newIDpos].begin(); j!=ui.cost[newIDpos].end(); j++) | ||||
| 	{ | ||||
| 		SetResource sr; | ||||
| 		sr.player = player; | ||||
| 		sr.resid = j->first; | ||||
| 		sr.val = gs->getPlayer(player)->resources[j->first] - j->second*crQuantity; | ||||
| 		sendAndApply(&sr); | ||||
| 	} | ||||
| 	SetResources sr; | ||||
| 	sr.player = player; | ||||
| 	sr.res = p->resources - totalCost; | ||||
| 	sendAndApply(&sr); | ||||
| 	 | ||||
| 	//upgrade creature | ||||
| 	changeStackType(StackLocation(obj, pos), VLC->creh->creatures[upgID]); | ||||
| @@ -2854,8 +2838,8 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, ui8 player) | ||||
| 	const PlayerState *p = gs->getPlayer(player); | ||||
| 	const CGTownInstance *t = gs->getTown(obj->id); | ||||
|  | ||||
| 	//common prconditions | ||||
| 	if( p->resources[6]<2500  && complain("Not enough gold for buying hero!") | ||||
| 	//common preconditions | ||||
| 	if( p->resources[Res::GOLD]<2500  && complain("Not enough gold for buying hero!") | ||||
| 		|| getHeroCount(player, false) >= 8 && complain("Cannot hire hero, only 8 wandering heroes are allowed!")) | ||||
| 		return false; | ||||
|  | ||||
| @@ -2905,8 +2889,8 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, ui8 player) | ||||
|  | ||||
| 	SetResource sr; | ||||
| 	sr.player = player; | ||||
| 	sr.resid = 6; | ||||
| 	sr.val = p->resources[6] - 2500; | ||||
| 	sr.resid = Res::GOLD; | ||||
| 	sr.val = p->resources[Res::GOLD] - 2500; | ||||
| 	sendAndApply(&sr); | ||||
|  | ||||
| 	if(t) | ||||
| @@ -3775,30 +3759,22 @@ void CGameHandler::handleTimeEvents() | ||||
| 				//give resources | ||||
| 				SetResources sr; | ||||
| 				sr.player = player; | ||||
| 				sr.res = pinfo->resources; | ||||
| 				sr.res = pinfo->resources + ev->resources; | ||||
|  | ||||
| 				//prepare dialog | ||||
| 				InfoWindow iw; | ||||
| 				iw.player = player; | ||||
| 				iw.text << ev->message; | ||||
|  | ||||
| 				for (int i=0; i<ev->resources.size(); i++) | ||||
| 				{ | ||||
| 					if(ev->resources[i]) //if resource is changed, we add it to the dialog | ||||
| 					{ | ||||
| 						// If removing too much resources, adjust the | ||||
| 						// amount so the total doesn't become negative. | ||||
| 						if (sr.res[i] + ev->resources[i] < 0) | ||||
| 							ev->resources[i] = -sr.res[i]; | ||||
|  | ||||
| 						if(ev->resources[i]) //if non-zero res change | ||||
| 						{ | ||||
| 							iw.components.push_back(Component(Component::RESOURCE,i,ev->resources[i],0)); | ||||
| 							sr.res[i] += ev->resources[i]; | ||||
| 						} | ||||
| 					} | ||||
| 						iw.components.push_back(Component(Component::RESOURCE,i,ev->resources[i],0)); | ||||
| 				} | ||||
|  | ||||
| 				if (iw.components.size()) | ||||
| 				{ | ||||
| 					sr.res.amax(0); // If removing too much resources, adjust the amount so the total doesn't become negative. | ||||
| 					sendAndApply(&sr); //update player resources if changed | ||||
| 				} | ||||
|  | ||||
| @@ -3839,21 +3815,24 @@ void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n, std::map< | ||||
| 				|| (ev->humanAffected && pinfo->human) ) ) | ||||
| 		{ | ||||
|  | ||||
|  | ||||
| 			// dialog | ||||
| 			InfoWindow iw; | ||||
| 			iw.player = player; | ||||
| 			iw.text << ev->message; | ||||
|  | ||||
| 			for (int i=0; i<ev->resources.size(); i++) | ||||
| 				if(ev->resources[i]) //if resource had changed, we add it to the dialog | ||||
| 				{ | ||||
| 					int was = n.res[player][i]; | ||||
| 					n.res[player][i] += ev->resources[i]; | ||||
| 					n.res[player][i] = std::max<si32>(n.res[player][i], 0); | ||||
| 			if(ev->resources.nonZero()) | ||||
| 			{ | ||||
| 				TResources was = n.res[player]; | ||||
| 				n.res[player] += ev->resources; | ||||
| 				n.res[player].amax(0); | ||||
|  | ||||
| 				for (int i=0; i<ev->resources.size(); i++) | ||||
| 					if(ev->resources[i] && pinfo->resources[i] != n.res[player][i]) //if resource had changed, we add it to the dialog | ||||
| 						iw.components.push_back(Component(Component::RESOURCE,i,n.res[player][i]-was[i],0)); | ||||
|  | ||||
| 			} | ||||
|  | ||||
| 					if(pinfo->resources[i] != n.res[player][i]) //if non-zero res change | ||||
| 						iw.components.push_back(Component(Component::RESOURCE,i,n.res[player][i]-was,0)); | ||||
| 				} | ||||
| 			for(std::set<si32>::iterator i = ev->buildings.begin(); i!=ev->buildings.end();i++) | ||||
| 				if ( !vstd::contains(town->builtBuildings, *i)) | ||||
| 				{ | ||||
| @@ -4018,8 +3997,8 @@ bool CGameHandler::buildBoat( ui32 objid ) | ||||
| 	SetResources sr; | ||||
| 	sr.player = obj->o->tempOwner; | ||||
| 	sr.res = gs->getPlayer(obj->o->tempOwner)->resources; | ||||
| 	sr.res[0] -= 10; | ||||
| 	sr.res[6] -= 1000; | ||||
| 	sr.res[Res::WOOD] -= 10; | ||||
| 	sr.res[Res::GOLD] -= 1000; | ||||
| 	sendAndApply(&sr); | ||||
|  | ||||
| 	//create boat | ||||
|   | ||||
		Reference in New Issue
	
	Block a user