1492: Global Colonization. Mod development

Hello KJ Jansson, first of all let me say that your ideas are great and your work seems to lead colonization in a very interesting direction. I downloaded and played your resources pack. I played on a huge random map and the game crashed a couple of times but, as you said in a previous post, i was able to restart from my last saved game. I don't really know if i should report any bug because i'm actually playing with mac via crossover (xp) (though i never had any problem with the core game patched or with AoD). By the way, when i tried to play on the huge earth map, i couldn't start the game 'cause the king dialog window started to pop up with, I guess, all the possible messages the king can give you during a game. I was stuck and had to shut down crossover. I can't say if that's an actual bug or it's related to the emulator.

About the gameplay. I enjoyed very much my game (played on marathon until the beginning of 1600). I had the feeling of how hard can be to settle in a new world and, more important on my point of view, i could develop in a realistic way (had camps to collect resources and cities to work those resources). If i can make a critic, is about incense. You now need incense to produce crosses but that's a real pain and there's no point in it. You can think at incense as a resource to sell (though it was more precious and strategic in ancient times than in XVI century) but the use of incense for crosses is really a distraction from the main objective of the game: produce, loot and trade the rich resources of a new land.

Though I love complex mods, sometimes i had the feeling there are way too many resources in yours. I assume that in the final version of your mod we won't be able to find any resource anywhere, but mind that in a random game, as the one I played, sometimes you can get lost or lose interest (and think that I play civ games since ever, so i'm not scared by complexity or new challenges).

Anyway, great work. I don't really know if my bug reports will be useful but I will continue to play and test your mod in the next days.
 
Hello again. I played a bit more your resources pack (and also other mods in the meanwhile). Didn't find any bug except for a journeyman-gem miner which in the end became a pearl collector. Tried to educate him again. Same result.

Talking about journeymen (and i'm referring also to the original professions mod), I think the progression from amateur to professional is too fast and makes the game too easy. This time I played aggresively (with english) on governor and i could buy from europe a lot of cheap farmers in order to trasform them in more expensive workers. Well, I imagine you have already a solution for that, but I want to share my idea. What if:

a) When a colonist apply for a new work he'll never become professional but remains, so to say, halfway. He gets a bonus but anyway inferior to the one he would have if he was an actual professional. The icon of such worker could be divided in two: half journeyman/half professional.
b) Maybe such a semi-professional will become professional eventually but only after a huge amount of time.
c) This shall represent the fact that the first colonists often improvised themselves in a profession they didn't know and became good at it but never exceptional. I mean, there should be a difference between someone who learned politics on the rough field of the new world and a refined, educated statesman coming from, say, an english university (and later from an american one).

About incense/crosses, i'm still of the same idea i had in my last post, though in my new game I didn't have any problem. I had two colonies with gems and I was making so much money that i could buy all the incense i wanted. Gems are really overpowered at this point of your mod. Maybe gems should never appear too close to the coast.

One last thought. Dutch, with merchantman and with all the resources in your mod, are really overpowered in the beginning. Few settlements with good resources on the coast and dutch rules.

I understand you are only at the beginning, but I hope anyway my thoughts could be of some help.
 
Hi KJ,

Can you tell me how the hell did you manage to add new yield types without using modules?!? :crazyeye: I've never been able to do that!

I think I have recalled how to do it without modules (in SoI it's without modules, but I made the changes so long ago I had forgotten exactly how). IIRC you should add the new tradable yields in the xml before the "special" yields, that is, bells, crosses and education.
 
I think I have recalled how to do it without modules (in SoI it's without modules, but I made the changes so long ago I had forgotten exactly how). IIRC you should add the new tradable yields in the xml before the "special" yields, that is, bells, crosses and education.
I already described how it was made. Here my previous message:

I modified SDK, a number of xml and python files.

In SDK I changed only 4 files: CvCityAI.cpp, CvEnums.h, CvPlayerAI.cpp and CyEnumInterface.cpp. Here I added new resources, then I compiled a new CvGameCoreDLL.dll. All this changes including the new dll-file compilation are required maximum 10-15 minutes.

All new resources must be described in xml files: CIV4YieldInfos.xml (!!!!!), CIV4BonusInfos.xml, CIVBuildinInfos, xml, CIV4UnitClassInfos.xml, CIV4UnitInfos.xml, etc., plus a number of corresponding ART and TEXT files. Here I used "fake" icons and descriptions for ART and TEXT files. The icons and text files could be corrected later.

Correct both Gamefonts files.

Here (if I remember correctly) I started a mod with new resources. Icons of new resources on Europe and City screens look terrible, of course.

The correction of python files is required a little bit more time. Here I changed CvMainInterface.py, CvEuropeScreen.py (very much changes), CvDomesticAdvisor.py.

All these changes of SDK, xml and python files could be made during about few hours even without knowledge of programming languages.

Now if it's necessary, I can give more detailed explanation concerning SDK changes.

1. CvEnums.h

Spoiler :
Code:
enum DllExport YieldTypes							
{
	NO_YIELD = -1,

	YIELD_FOOD,
	YIELD_LUMBER,
	YIELD_STONE,										//KJ RESOURCES	
	YIELD_ORE,	
	YIELD_SILVER,
	YIELD_GOLD,											//MORE_YIELD_TYPES		05/05/09		Aymerick
	YIELD_GEMS,											//KJ RESOURCES
	YIELD_COTTON,
	YIELD_FUR,
	YIELD_SUGAR,
	YIELD_TOBACCO,
	YIELD_DRUGS,										//KJ RESOURCES
	YIELD_INDIGO,										//MORE_YIELD_TYPES		05/05/09		Aymerick
	YIELD_INCENSE,										//KJ RESOURCES
	YIELD_COFFEE,										//MORE_YIELD_TYPES		05/05/09		Aymerick
	YIELD_COCOA,										//KJ RESOURCES
	YIELD_TEA,											//KJ RESOURCES
	YIELD_SPICES,										//KJ RESOURCES
	YIELD_IVORY,										//KJ RESOURCES
	YIELD_EBONY,										//KJ RESOURCES
	YIELD_CLOTH,
	YIELD_COATS,
	YIELD_RUM,
	YIELD_CIGARS,
	YIELD_TOOLS,
	YIELD_MUSKETS,
	YIELD_HORSES,
	YIELD_TRADE_GOODS,
	YIELD_ARTISANS_PRODUCTS,							//KJ RESOURCES
	YIELD_SLAVES,										//KJ RESOURCES	
	YIELD_HAMMERS,
	YIELD_BELLS,
	YIELD_CROSSES,
	YIELD_EDUCATION,
2. CyEnumsInterface.cpp

Spoiler :
Code:
	python::enum_<YieldTypes>("YieldTypes")
		.value("NO_YIELD", NO_YIELD)
		.value("YIELD_FOOD", YIELD_FOOD)
		.value("YIELD_LUMBER", YIELD_LUMBER)
		.value("YIELD_STONE", YIELD_STONE)											//KJ RESOURCES
		.value("YIELD_ORE", YIELD_ORE)		
		.value("YIELD_SILVER", YIELD_SILVER)
		.value("YIELD_GOLD", YIELD_GOLD)											//MORE_YIELD_TYPES		05/05/09		Aymerick
		.value("YIELD_GEMS", YIELD_GEMS)											//KJ RESOURCES
		.value("YIELD_COTTON", YIELD_COTTON)
		.value("YIELD_FUR", YIELD_FUR)
		.value("YIELD_SUGAR", YIELD_SUGAR)
		.value("YIELD_TOBACCO", YIELD_TOBACCO)		
		.value("YIELD_DRUGS", YIELD_DRUGS)											//KJ RESOURCES
		.value("YIELD_INDIGO", YIELD_INDIGO)										//MORE_YIELD_TYPES		05/05/09		Aymerick
		.value("YIELD_INCENSE", YIELD_INCENSE)										//KJ RESOURCES
		.value("YIELD_COFFEE", YIELD_COFFEE)										//MORE_YIELD_TYPES		05/05/09		Aymerick		
		.value("YIELD_COCOA", YIELD_COCOA)											//KJ RESOURCES
		.value("YIELD_TEA", YIELD_TEA)												//KJ RESOURCES
		.value("YIELD_SPICES", YIELD_SPICES)										//KJ RESOURCES
		.value("YIELD_IVORY", YIELD_IVORY)											//KJ RESOURCES		
		.value("YIELD_EBONY", YIELD_EBONY)											//KJ RESOURCES
		.value("YIELD_CLOTH", YIELD_CLOTH)
		.value("YIELD_COATS", YIELD_COATS)
		.value("YIELD_RUM", YIELD_RUM)
		.value("YIELD_CIGARS", YIELD_CIGARS)
		.value("YIELD_TOOLS", YIELD_TOOLS)
		.value("YIELD_MUSKETS", YIELD_MUSKETS)
		.value("YIELD_HORSES", YIELD_HORSES)
		.value("YIELD_TRADE_GOODS", YIELD_TRADE_GOODS)
		.value("YIELD_ARTISANS_PRODUCTS", YIELD_ARTISANS_PRODUCTS)					//KJ RESOURCES		
		.value("YIELD_SLAVES", YIELD_SLAVES)										//KJ RESOURCES		
		.value("YIELD_HAMMERS", YIELD_HAMMERS)
		.value("YIELD_BELLS", YIELD_BELLS)
		.value("YIELD_CROSSES", YIELD_CROSSES)
		.value("YIELD_EDUCATION", YIELD_EDUCATION)
		.value("NUM_YIELD_TYPES", NUM_YIELD_TYPES)
		;
3. CvCityAI.cpp

Spoiler :
Code:
int CvCityAI::AI_estimateYieldValue(YieldTypes eYield, int iAmount) const
{
	int iValue = iAmount * GET_PLAYER(getOwnerINLINE()).AI_yieldValue(eYield);
	
	switch (eYield)
	{
		case YIELD_FOOD:
		case YIELD_LUMBER:
		case YIELD_ORE:		
		case YIELD_STONE:										//KJ RESOURCES
		case YIELD_SILVER:
		case YIELD_GOLD:										//MORE_YIELD_TYPES		05/05/09		Aymerick		
		case YIELD_GEMS:										//KJ RESOURCES
		case YIELD_COTTON:	
		case YIELD_FUR:
		case YIELD_SUGAR:
		case YIELD_TOBACCO:
		case YIELD_DRUGS:										//KJ RESOURCES		
		case YIELD_INDIGO:										//MORE_YIELD_TYPES		05/05/09		Aymerick
		case YIELD_INCENSE:										//KJ RESOURCES
		case YIELD_COFFEE:										//MORE_YIELD_TYPES		05/05/09		Aymerick
		case YIELD_COCOA:										//KJ RESOURCES
		case YIELD_TEA:											//KJ RESOURCES
		case YIELD_SPICES:										//KJ RESOURCES
		case YIELD_IVORY:										//KJ RESOURCES
		case YIELD_EBONY:										//KJ RESOURCES		
		case YIELD_CLOTH:
		case YIELD_COATS:
		case YIELD_RUM:
		case YIELD_CIGARS:
		case YIELD_TOOLS:
		case YIELD_MUSKETS:
		case YIELD_HORSES:
		case YIELD_TRADE_GOODS:
		case YIELD_ARTISANS_PRODUCTS:							//KJ RESOURCES
		case YIELD_SLAVES:										//KJ RESOURCES		
		case YIELD_HAMMERS:
			break;
		case YIELD_BELLS:
			break;
		case YIELD_CROSSES:
			break;
		case YIELD_EDUCATION:
			break;
		default:
			FAssert(false);
	}
	
	return iValue;
}

4. CvPlayerAI.cpp

4.1

Spoiler :
Code:
bool CvPlayerAI::AI_isYieldForSale(YieldTypes eYield) const
{
	if (!GC.getYieldInfo(eYield).isCargo())
	{
		return false;
	}
	
	switch (eYield)
	{
		case YIELD_FOOD:
		case YIELD_LUMBER:
		case YIELD_STONE:										//	KJ RESORCES
			return false;
			break;

		case YIELD_ORE:			
		case YIELD_SILVER:
		case YIELD_GOLD:										//MORE_YIELD_TYPES		05/05/09		Aymerick		
		case YIELD_GEMS:										//	KJ RESORCES		
		case YIELD_COTTON:
		case YIELD_FUR:
		case YIELD_SUGAR:
		case YIELD_TOBACCO:
		case YIELD_DRUGS:										//	KJ RESORCES	
		case YIELD_INDIGO:										//MORE_YIELD_TYPES		05/05/09		Aymerick
		case YIELD_INCENSE:										//	KJ RESORCES	
		case YIELD_COFFEE:										//MORE_YIELD_TYPES		05/05/09		Aymerick
		case YIELD_COCOA:										//	KJ RESORCES
		case YIELD_TEA:											//	KJ RESORCES
		case YIELD_SPICES:										//	KJ RESORCES
		case YIELD_IVORY:										//	KJ RESORCES			
		case YIELD_EBONY:										//	KJ RESORCES	
		case YIELD_CLOTH:
		case YIELD_COATS:
		case YIELD_RUM:
		case YIELD_CIGARS:
			return true;
			break;
			
		case YIELD_TOOLS:
		case YIELD_MUSKETS:
		case YIELD_HORSES:
		case YIELD_TRADE_GOODS:
		case YIELD_ARTISANS_PRODUCTS:							//	KJ RESORCES	
		case YIELD_SLAVES:										//	KJ RESORCES			
			return false;
			break;
			
		case YIELD_HAMMERS:
		case YIELD_BELLS:
		case YIELD_CROSSES:
			FAssertMsg(false, "Selling intangibles?");
			break;
		default:
			FAssert(false);
	}
	
	return false;
	
	
}
4.2 NB! Criically important part!!!

Spoiler :
Code:
bool CvPlayerAI::AI_isYieldFinalProduct(YieldTypes eYield) const
{
	if (!GC.getYieldInfo(eYield).isCargo())
	{
		return false;
	}
	
	bool bFinal = true;
	
	switch (eYield)
	{
		case YIELD_FOOD:
		case YIELD_LUMBER:
			bFinal = false;
			break;

		case YIELD_STONE:										//	KJ RESOURCES
			bFinal = true;
			break;
			
		case YIELD_ORE:			
		{
				int iLoop;
				CvCity* pLoopCity = NULL;
				for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
				{
					if (pLoopCity->AI_getNeededYield(eYield) > 0)
					{
						bFinal = false;
						break;
					}					
				}
			}
			break;
		case YIELD_SILVER:
		case YIELD_GOLD:										//MORE_YIELD_TYPES		05/05/09		Aymerick
		case YIELD_GEMS:										//	KJ RESOURCES		
			bFinal = true;
			break;

		case YIELD_COTTON:
		case YIELD_FUR:
		case YIELD_SUGAR:
		case YIELD_TOBACCO:
		{
				int iLoop;
				CvCity* pLoopCity = NULL;
				for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
				{
					if (pLoopCity->AI_getNeededYield(eYield) > 0)
					{
						bFinal = false;
						break;
					}					
				}
			}
			break;

		case YIELD_DRUGS:										//	KJ RESOURCES
		case YIELD_INDIGO:										//MORE_YIELD_TYPES		05/05/09		Aymerick
		case YIELD_INCENSE:										//	KJ RESOURCES
		case YIELD_COFFEE:										//MORE_YIELD_TYPES		05/05/09		Aymerick
		case YIELD_COCOA:										//	KJ RESOURCES
		case YIELD_TEA:											//	KJ RESOURCES
		case YIELD_SPICES:										//	KJ RESOURCES
		case YIELD_IVORY:										//	KJ RESOURCES		
		case YIELD_EBONY:										//	KJ RESOURCES
			bFinal = true;
			break;
			
		case YIELD_CLOTH:
		case YIELD_COATS:
		case YIELD_RUM:
		case YIELD_CIGARS:
			bFinal = true;
			break;
			
		case YIELD_TOOLS:
		case YIELD_MUSKETS:
		case YIELD_HORSES:
			bFinal = false;
			break;
			
		case YIELD_TRADE_GOODS:
		case YIELD_ARTISANS_PRODUCTS:							//	KJ RESOURCES
		case YIELD_SLAVES:										//	KJ RESOURCES		
			bFinal = true;
			break;
			
		case YIELD_HAMMERS:
		case YIELD_BELLS:
		case YIELD_CROSSES:
			bFinal = false;
			FAssertMsg(false, "Selling intangibles?");
			break;
		default:
			FAssert(false);
	}
	
	return bFinal;	
}
Comments:

- Here we have FINAL YIELDS DISTRIBUTION!
- Yields must be in correct order.
- The SAME YIELDS ORDER must be in CIV4YieldInfos.xml.
- Yield that could be only sell in Europe must have part


Code:
			bFinal = true;
			break;

For instance, SILVER, GOLD, GEMS:

Code:
 		case YIELD_SILVER:
		case YIELD_GOLD:										//MORE_YIELD_TYPES		05/05/09		Aymerick
		case YIELD_GEMS:										//	KJ RESOURCES		
			bFinal = true;
			break;

- Yield that could be used for other good production must have

Code:
		{
				int iLoop;
				CvCity* pLoopCity = NULL;
				for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
				{
					if (pLoopCity->AI_getNeededYield(eYield) > 0)
					{
						bFinal = false;
						break;
					}					
				}
			}
			break;

For instance, COTTON, FUR, SUGAR, TOBACCO, that used for CLOTH, COAT, RUM, SIGARS production.
Code:
		case YIELD_COTTON:
		case YIELD_FUR:
		case YIELD_SUGAR:
		case YIELD_TOBACCO:
		{
				int iLoop;
				CvCity* pLoopCity = NULL;
				for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
				{
					if (pLoopCity->AI_getNeededYield(eYield) > 0)
					{
						bFinal = false;
						break;
					}					
				}
			}
			break;

4.3.

Spoiler :
Code:
bool CvPlayerAI::AI_shouldBuyFromEurope(YieldTypes eYield) const
{
	if (!GC.getYieldInfo(eYield).isCargo())
	{
		return false;
	}
	
	bool bBuy = false;
	
	switch (eYield)
	{
		case YIELD_FOOD:
		case YIELD_LUMBER:
		case YIELD_STONE:										//	KJ RESOURCES
		case YIELD_ORE:		
		case YIELD_SILVER:
		case YIELD_GOLD:										//MORE_YIELD_TYPES		05/05/09		Aymerick
		case YIELD_GEMS:										//	KJ RESOURCES
		case YIELD_COTTON:
		case YIELD_FUR:
		case YIELD_SUGAR:
		case YIELD_TOBACCO:
		case YIELD_DRUGS:										//	KJ RESOURCES
		case YIELD_INDIGO:										//MORE_YIELD_TYPES		05/05/09		Aymerick
		case YIELD_INCENSE:										//	KJ RESOURCES
		case YIELD_COFFEE:										//MORE_YIELD_TYPES		05/05/09		Aymerick		
		case YIELD_COCOA:										//	KJ RESOURCES
		case YIELD_TEA:											//	KJ RESOURCES
		case YIELD_SPICES:										//	KJ RESOURCES
		case YIELD_IVORY:										//	KJ RESOURCES		
		case YIELD_EBONY:										//	KJ RESOURCES
		case YIELD_CLOTH:
		case YIELD_COATS:
		case YIELD_RUM:
		case YIELD_CIGARS:
			bBuy = false;
			break;

		case YIELD_TOOLS:
		case YIELD_MUSKETS:
		case YIELD_HORSES:
		case YIELD_TRADE_GOODS:
		case YIELD_ARTISANS_PRODUCTS:							//	KJ RESOURCES
		case YIELD_SLAVES:										//	KJ RESOURCES		
			bBuy = true;
			break;
			
		case YIELD_HAMMERS:
		case YIELD_BELLS:
		case YIELD_CROSSES:
			bBuy = false;
			FAssertMsg(false, "Selling intangibles?");
			break;
		default:
			FAssert(false);
	}
	
	return bBuy;
}
4.4.

Spoiler :
Code:
int CvPlayerAI::AI_yieldValue(YieldTypes eYield, bool bProduce, int iAmount)
{
	int iValue = 0;
	if (bProduce)
	{
		iValue += 100 * (isNative() ? GC.getYieldInfo(eYield).getNativeBaseValue() : GC.getYieldInfo(eYield).getAIBaseValue());
	}
	if (eYield == YIELD_FOOD)
	{
	
	}
	else if (isNative())
	{
		CvYieldInfo& kYieldInfo = GC.getYieldInfo(eYield);
		int iPrice = 0;
		int iValidPrices = 0;
		if (kYieldInfo.getNativeBuyPrice() > 0)
		{
			iPrice += kYieldInfo.getNativeBuyPrice();
			iValidPrices++;
		}
		if (kYieldInfo.getNativeSellPrice() > 0)
		{
			iPrice += kYieldInfo.getNativeSellPrice();
			iValidPrices++;
		}

		if (iPrice > 0)
		{
			//If both buy and sell, use average. Otherwise, use 2/3rd the value.
			iPrice *= 2;
			iPrice /= 2 + iValidPrices;
		
			iValue += iPrice * 100;
		}
	}
	else
	{
		iValue += m_aiYieldValuesTimes100[eYield];
	}

	iValue *= AI_yieldWeight(eYield);
	iValue /= 100;
	
	if (bProduce)
	{
		int iWeaponsMultiplier = 100;
		if (AI_isStrategy(STRATEGY_REVOLUTION_PREPARING))
		{
			iWeaponsMultiplier += 50;
		}

		int iGoodsMultiplier = 100;
		if (AI_isStrategy(STRATEGY_REVOLUTION_DECLARING))
		{
			iGoodsMultiplier -= 15;
			iWeaponsMultiplier += 25;
		}
		else if (AI_isStrategy(STRATEGY_CASH_FOCUS))
		{
			iGoodsMultiplier += 50;
		}

		if (AI_isStrategy(STRATEGY_REVOLUTION))
		{
			iGoodsMultiplier -= 15;
			iWeaponsMultiplier += 50;
		}

		switch (eYield)
		{
			case YIELD_FOOD:
				break;
			case YIELD_LUMBER:
			case YIELD_STONE:										//KJ RESORCES
				iValue *= 100;
				iValue /= iGoodsMultiplier;
				break;				
				
			case YIELD_ORE:
			case YIELD_SILVER:
			case YIELD_GOLD:										//MORE_YIELD_TYPES		05/05/09		Aymerick
			case YIELD_GEMS:										//KJ RESORCES
			case YIELD_COTTON:
			case YIELD_FUR:
			case YIELD_SUGAR:
			case YIELD_TOBACCO:			
			case YIELD_DRUGS:										//KJ RESORCES
			case YIELD_INDIGO:										//MORE_YIELD_TYPES		05/05/09		Aymerick
			case YIELD_INCENSE:										//KJ RESORCES
			case YIELD_COFFEE:										//MORE_YIELD_TYPES		05/05/09		Aymerick		
			case YIELD_COCOA:										//KJ RESORCES
			case YIELD_TEA:											//KJ RESORCES
			case YIELD_SPICES:										//KJ RESORCES
			case YIELD_IVORY:										//KJ RESORCES			
			case YIELD_EBONY:										//KJ RESORCES
			case YIELD_CLOTH:
			case YIELD_COATS:
			case YIELD_RUM:
			case YIELD_CIGARS:
				iValue *= iGoodsMultiplier;
				iValue /= 100;
				break;
				
			case YIELD_TOOLS:
				break;

			case YIELD_MUSKETS:
			case YIELD_HORSES:
				iValue *= iWeaponsMultiplier;
				iValue /= 100;
				break;
				
			case YIELD_TRADE_GOODS:
			case YIELD_ARTISANS_PRODUCTS:							//KJ RESORCES
			case YIELD_SLAVES:										//KJ RESORCES			
				break;
	
			case YIELD_HAMMERS:
				if (AI_isStrategy(STRATEGY_REVOLUTION_PREPARING))
				{
					iValue *= 125;
					iValue /= 100;
					if (AI_isStrategy(STRATEGY_REVOLUTION_DECLARING))
					{
						iValue *= 125;
						iValue /= 100;
					}
				}
				break;
			
			case YIELD_BELLS:
				if (AI_isStrategy(STRATEGY_REVOLUTION_PREPARING))
				{
					iValue *= 150;
					iValue /= 100;
					if (AI_isStrategy(STRATEGY_REVOLUTION_DECLARING))
					{
						iValue *= 150;
						iValue /= 100;
					}
				}
				break;
			case YIELD_CROSSES:
			case YIELD_EDUCATION:
				iValue *= 100;
				iValue /= iWeaponsMultiplier;
				break;
			default:
			break;
		}
	}
	
	iValue *= iAmount;
	iValue /= 100;
	
	return iValue;
}
4.5.

Spoiler :
Code:
void CvPlayerAI::AI_updateYieldValues()
{
	if (isNative())
	{
		return;
	}

	PlayerTypes eParent = getParent();
	
	if (getParent() == NO_PLAYER)
	{
		eParent = getID();
	}
	
	CvPlayer& kParent = GET_PLAYER(eParent);
	for (int i = 0; i < NUM_YIELD_TYPES; ++i)
	{
		YieldTypes eYield = (YieldTypes)i;
		int iValue = 0;
		switch (eYield)
		{
			case YIELD_FOOD:
				iValue += (kParent.getYieldSellPrice(eYield) + kParent.getYieldBuyPrice(eYield)) / 2;
				break;
			case YIELD_LUMBER:
				iValue += (kParent.getYieldSellPrice(eYield) + kParent.getYieldBuyPrice(eYield)) / 2;
				break;
			case YIELD_STONE:										//KJ RESOURSES
				iValue += (kParent.getYieldSellPrice(eYield) + kParent.getYieldBuyPrice(eYield)) / 2;
				break;				

			case YIELD_ORE:
			case YIELD_SILVER:
			case YIELD_GOLD:										//MORE_YIELD_TYPES		05/05/09		Aymerick
			case YIELD_GEMS:										//KJ RESOURCES
			case YIELD_COTTON:
			case YIELD_FUR:
			case YIELD_SUGAR:
			case YIELD_TOBACCO:			
			case YIELD_DRUGS:										//KJ RESOURCES
			case YIELD_INDIGO:										//MORE_YIELD_TYPES		05/05/09		Aymerick
			case YIELD_INCENSE:										//KJ RESOURCES
			case YIELD_COFFEE:										//MORE_YIELD_TYPES		05/05/09		Aymerick
			case YIELD_COCOA:										//KJ RESOURCES
			case YIELD_TEA:											//KJ RESOURCES
			case YIELD_SPICES:										//KJ RESOURCES
			case YIELD_IVORY:										//KJ RESOURCES			
			case YIELD_EBONY:										//KJ RESOURCES
			case YIELD_CLOTH:
				iValue += kParent.getYieldBuyPrice(eYield);
				break;
				
			case YIELD_COATS:
			case YIELD_RUM:
			case YIELD_CIGARS:
				iValue += kParent.getYieldBuyPrice(eYield);
				break;
				
			case YIELD_TOOLS:
			case YIELD_MUSKETS:
			case YIELD_HORSES:
				iValue += kParent.getYieldSellPrice(eYield);
				break;
				
			case YIELD_TRADE_GOODS:
			case YIELD_ARTISANS_PRODUCTS:							//KJ RESOURCES
			case YIELD_SLAVES:										//KJ RESOURCES			
				iValue += kParent.getYieldSellPrice(eYield);
				break;
				
			case YIELD_HAMMERS:
			case YIELD_BELLS:
			case YIELD_CROSSES:
			case YIELD_EDUCATION:
				break;
			default:
				FAssert(false);
		}

		m_aiYieldValuesTimes100[i] = 100 * iValue;
	}
	int iCrossValue = m_aiYieldValuesTimes100[YIELD_FOOD] * getGrowthThreshold(1) / (50 + immigrationThreshold() * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGrowthPercent() / 100);
	iCrossValue /= 2;
	
	//Crosses
	m_aiYieldValuesTimes100[YIELD_CROSSES] = std::max(m_aiYieldValuesTimes100[YIELD_CROSSES], iCrossValue);
	
	//The function is quite simple. Iterate over every citizen which has input yield.
	//Calculate the value of their output yield, and assign half of that to the input.
	if (!isHuman())
	{
		int iLoop;
		CvCity* pLoopCity;
		for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
		{
			for (int i = 0; i < pLoopCity->getPopulation(); ++i)
			{
				CvUnit* pLoopUnit = pLoopCity->getPopulationUnitByIndex(i);
				
				ProfessionTypes eProfession = pLoopUnit->getProfession();
				if (eProfession != NO_PROFESSION)
				{
					CvProfessionInfo& kProfession = GC.getProfessionInfo(eProfession);
					if (kProfession.getYieldConsumed() != NO_YIELD)
					{
						int iValue = 0;
						FAssert(kProfession.getYieldProduced() != NO_YIELD);//damn welfware cheats.
						
						int iInput = pLoopCity->getProfessionInput(eProfession, pLoopUnit);
						int iOutput = pLoopCity->getProfessionOutput(eProfession, pLoopUnit);
						
						int iProfit = (m_aiYieldValuesTimes100[kProfession.getYieldProduced()] * iOutput);
		
						int iInputValue = iProfit / (2 * iInput); //Assign 50% of the yield value to the input.
						m_aiYieldValuesTimes100[kProfession.getYieldConsumed()] = std::max(iInputValue, m_aiYieldValuesTimes100[kProfession.getYieldConsumed()]);
					}
				}
				ProfessionTypes eIdealProfesion = AI_idealProfessionForUnit(pLoopUnit->getUnitType());
				if (eIdealProfesion != NO_PROFESSION && eIdealProfesion != eProfession)
				{
					CvProfessionInfo& kIdealPro = GC.getProfessionInfo(eIdealProfesion);
					YieldTypes eYieldConsumed = (YieldTypes)kIdealPro.getYieldConsumed();
					if (eYieldConsumed != NO_YIELD)
					{
						YieldTypes eYieldProduced = (YieldTypes)kIdealPro.getYieldProduced();
						FAssert(kIdealPro.getYieldProduced() != NO_YIELD);
						int iInputValue = m_aiYieldValuesTimes100[eYieldProduced] / 2;
						m_aiYieldValuesTimes100[eYieldConsumed] = std::max(iInputValue, m_aiYieldValuesTimes100[eYieldConsumed]);
					}
				}
			}
		}
	}
}

And finally the CIV4YieldInfos.xml file.

Compare the YIELD_ distribution in this file with the data from source files above. It's the SAME!!!

In source files we have:
Code:
			case YIELD_FOOD:
			case YIELD_LUMBER:
			case YIELD_STONE:										//KJ RESORCES
			case YIELD_ORE:
			case YIELD_SILVER:
			case YIELD_GOLD:										//MORE_YIELD_TYPES		05/05/09		Aymerick
			case YIELD_GEMS:										//KJ RESORCES
			case YIELD_COTTON:
			case YIELD_FUR:
			case YIELD_SUGAR:
			case YIELD_TOBACCO:			
			case YIELD_DRUGS:										//KJ RESORCES
			case YIELD_INDIGO:										//MORE_YIELD_TYPES		05/05/09		Aymerick
			case YIELD_INCENSE:										//KJ RESORCES
			case YIELD_COFFEE:										//MORE_YIELD_TYPES		05/05/09		Aymerick		
			case YIELD_COCOA:										//KJ RESORCES
			case YIELD_TEA:											//KJ RESORCES
			case YIELD_SPICES:										//KJ RESORCES
			case YIELD_IVORY:										//KJ RESORCES			
			case YIELD_EBONY:										//KJ RESORCES
			case YIELD_CLOTH:
			case YIELD_COATS:
			case YIELD_RUM:
			case YIELD_CIGARS:
			case YIELD_TOOLS:
			case YIELD_MUSKETS:
			case YIELD_HORSES:
			case YIELD_TRADE_GOODS:
			case YIELD_ARTISANS_PRODUCTS:							//KJ RESORCES
			case YIELD_SLAVES:										//KJ RESORCES			
			case YIELD_HAMMERS:
			case YIELD_BELLS:
			case YIELD_CROSSES:
			case YIELD_EDUCATION:

In CIV4YieldInfos.xml file we have the SAME distribution.

Code:
			<Type>YIELD_FOOD</Type>
			<Type>YIELD_LUMBER</Type>
			<Type>YIELD_STONE</Type>
			<Type>YIELD_ORE</Type>
			<Type>YIELD_SILVER</Type>
			<Type>YIELD_GOLD</Type>
			<Type>YIELD_GEMS</Type>
			<Type>YIELD_COTTON</Type>
			<Type>YIELD_FUR</Type>
			<Type>YIELD_SUGAR</Type>
			<Type>YIELD_TOBACCO</Type>
			<Type>YIELD_DRUGS</Type>
			<Type>YIELD_INDIGO</Type>
			<Type>YIELD_INCENSE</Type>
			<Type>YIELD_COFFEE</Type>
			<Type>YIELD_COCOA</Type>
			<Type>YIELD_TEA</Type>
			<Type>YIELD_SPICES</Type>
			<Type>YIELD_IVORY</Type>
			<Type>YIELD_EBONY</Type>
			<Type>YIELD_CLOTH</Type>
			<Type>YIELD_COATS</Type>
			<Type>YIELD_RUM</Type>
			<Type>YIELD_CIGARS</Type>
			<Type>YIELD_TOOLS</Type>
			<Type>YIELD_MUSKETS</Type>
			<Type>YIELD_HORSES</Type>
			<Type>YIELD_TRADE_GOODS</Type>
			<Type>YIELD_ARTISANS_PRODUCTS</Type>
			<Type>YIELD_SLAVES</Type>
			<Type>YIELD_HAMMERS</Type>
			<Type>YIELD_BELLS</Type>
			<Type>YIELD_CROSSES</Type>
			<Type>YIELD_EDUCATION</Type>

Everything is working without modules at all. All other files (CIV4BonusInfos.xml, CIVBuildinInfos, xml, CIV4UnitClassInfos.xml, CIV4UnitInfos.xml, etc., plus a number of corresponding ART and TEXT files) are very easy to modify.
 
Thank you Eg Atma Oom for your comments and excuse me for delay with the answer. I missed your previous message.

"1492: GC. Resource Pack" is a test version and of course, has some bugs. I could catch and fix only critical bugs that stopped the game at all. However a number of small bugs I could find and fix only after Resource Pack was released. Fortunately these bugs are not critical.

when i tried to play on the huge earth map, i couldn't start the game 'cause the king dialog window started to pop up with, I guess, all the possible messages the king can give you during a game.

Such message appears when your ship starts on a land tile. Your king gives you a second ship and increases tax. The second ship also appears on the same tile and king again .... etc. etc.

Here there is only one solution. Start a new game. Such error is quite typical for small size maps, on huge size map this is a very rare bug.

If i can make a critic, is about incense.

Incense is a special case. Let's return to the history of a New World colonization.

In the beginning of XVI-th century only few settlers decided to go in the New World. That is, the flow of colonists from Europe to the New World in the beginning was minimal. Just as the strengthening and expansion of the colonies appeared more willing to risk for such journey.

In the original Civ4Colonization game everythin is reversed. A lot of the colonists at the beginning and almost none by the end of the game. Introduction of incense and a ban on the generation of crosses without incense can rebalance the flow of colonists from Europe. Less in the beginning, that is, the slower development of the colony, then more rapidly due to incense, which the colonists could produce themselves or buy in Europe.

I assume that in the final version of your mod we won't be able to find any resource anywhere

Soon each player have to fight for the resources. They will not be more widely accessible.

Didn't find any bug except for a journeyman-gem miner which in the end became a pearl collector.

Thank you, I'll check. I didn't have this error. Gemstone miner and Pearl collector have different areas of work. Gemstone is working only on land, Pearl collector is working only on the water tiles. According to the current game codes, they cannot intersect.

I think the progression from amateur to professional is too fast and makes the game too easy.

I made the maximum number of parameters as easy as possible only to show how they work. In fact, professional education of colonists must take much greater number of turns (30-40).

a) When a colonist apply for a new work he'll never become professional but remains, so to say, halfway. He gets a bonus but anyway inferior to the one he would have if he was an actual professional. The icon of such worker could be divided in two: half journeyman/half professional.
b) Maybe such a semi-professional will become professional eventually but only after a huge amount of time.

Agree, this may be one solution to the problem. It could be correted very easily.

Gems are really overpowered at this point of your mod.

Prices also will be rebalanced to the downside, especially for expensive items (gems, gold, silver).
 
hey how is this coming along is it done yet
 
Thank you for your answers KJ Jansson.

About incense, sorry if I insist, i think what I really found a bit involved was the game mechanic: the necessity to buy incense from the old world or, worst, apply one of my precious colonists to collect incense instead of cutting wood or mine some ore. Maybe the solution could be to sell incense at a very low price. Still, I think it would be kind of distracting. But I will not discuss this anymore. It&#8217;s your mod and you surely know what&#8217;s better.

I agree completly with you about the upside down structure of both the old and new col games. It always made me wondering why when the new world becomes a real hope, then the colonists stop migrating. The crosses needed to attract colonists, if it&#8217;s possible, should be costant so that in the end you can face a dramatic pick of immigration and, as a player, you can choose either to devolope further your lands and/or start rushing to the west either to select only the immigrants you need and leave the others waiting for better times.

I played a bit the spread of imperialism mod and I want to tell you what I found very interesting in it. First, the selected starting position. Scenario-wise I had the impression that starting with the first settlement already built in the right spot was great. Second, well, not having a pioneer since the beginning made the &#8220;origins&#8221; very hard and challenging. I don&#8217;t know if this last condition is a bug of any sort &#8216;cause, actually, that mod is still very buggy, but wondering between my underdeveloped settlements without roads, risking a natives attack at every step was realistic and funny.

Two more things, and sorry if I&#8217;m being verbose.

1) Remember that you will have as many workers as many resources. This means that the workers you find on the dock could sometimes not match the resources in the new land. &#8220;Sometimes&#8221; is ok, but in one game i played with your pack, &#8220;sometimes&#8221; became a very long time. With the fast learning pace that actually is in your mod, having so many &#8220;wrong&#8221; workers was not a real problem, but I imagine in your final release this could become annoying and take away some of the fun of the game.

2) A small list of thoughts/dreams:
a) Silver not gold was the main money-maker during the first 200 years of the colonization period. Maybe the gold resource could be triggered by a late event in the game (if you intend to use events).
b) Yielding and consuming buffalos. They were almost extinct, well, more for the fun of the gun users than for food, but I&#8217;d like to have the possibility to create food from buffalos (or to try my new winchester...).
c) What I don&#8217;t like at all is that natives give you money in exchange of your refined products. They should instead give you either a treasure (yes it&#8217;s money but it sounds more like something that is worthless for them and precious for the colonist), either silver or raw materials. I don&#8217;t know if it is possible but this would be a great improvement. No more 3000 gold for 150 rifles, but something like 300 furs for 50 rifles, which sounds way better.
d) Exploring should be more risky. Now also on patriot level you can collect most of the treasures and make most of the first contacts. Too easy.

I will now go back to the vanilla game and wait for your next release. Keep the good work and thank you again for your answer.
 
Hey KJ,

First off this MOD is pretty great. I cannot wait for the "final" version of it. But while playing I had a few ideas and thought I'd run them by you to see if their even possible:

1) Wagon Trains with an option to just trade with Indian Villages. Basically, after you build a wagon train instead of just having the auto trade route (which works within your colonies) there would be a "Auto Indian trade Route" that would seek out nearby Indian villages and trade with them. I've always found that land trading with Indians is something I always plan to do, but hate to micromanage. Perhaps they will only go to villages where you've established a mission or not? Just a thought.

2) A unit that can establish a "base camp" on a special good (ie: tea, furs, gold, etc). A lot of times there are several special items outside the city radius that go unused the entire game. Having a unit able to build a small "base camp" on a good and let wagon trains come collect the goods would be a nice way of utilizing the entire map.

Perhaps you could alter the Indentured Servant with this ability. Make their yields small (like 2) but worth setting up. Perhaps later, when you finishing putting in the slave trade stuff, you could have slaves have this ability too but their yields could be higher (4-5). However, with slaves, you could also have penalties: A knock against the closest colonies Liberty Bell production and, if you use slaves to establish a base camp, you also have to have a veteran solider there to oversee it.

3) Multiple Indian nation alliances. You can already establish alliances and defense pacts with Indian tribes, but what if there were pre-established alliances (ie: 5 Nation Iroquois) or new forming alliances between Indian tribes. Perhaps Indian tribes that feel threatened by encroaching colonies could join forces against them?


Just thought I'd throw those out there. I have no idea if their possible or not but what the hell, might as well throw them against the wall and sees what sticks.

Thanks!
 
Any progress on the world map? Will you be modding the mod further for the map, or will it just be a scenario of the first?
I continue to work on the mod. At the moment I use the world map generated by Earth31.py as a basis. The transition on the real map of the Earth will be made when will be ready
- a full list of the European and native civilization (leaders, units) and
- a new economic model of development (resources, production cycles, professions).
 
A few screenshots of the features, I'm working at the moment. All data on screens are very preliminary. They are given just to show differences.

"Triangle Trade" mod by Dom Pedro II was used as a basic. Unfortunately, Dom Pedro II stopped his mod development in the end of 2008. Last version of "Triangle Trade" mod is rather buggy and "worked" only on vanilla version of Civ4Col. Here I took some elements from his old mod, modified for last 1.01f patch and added some additional possibilities.

In original Civ4Col the player can visit only Europe. Here three additional places are available to visit: Africa, the Orient and Port-Royal.



Please, compare the prices on European market and in Africa, Orient and Port-Royal. They are especially made too different just for demonstration. Thus, the player could choose the best place, where he could sell his goods with better profit.



In Africa, Orient and Port-Royal you can only sell your goods. At the moment it is impossible to buy goods on these markets. However the list of available units could be different in each new place. Africa, for instance, is the source of cheap slaves.



The Orient should be the source of cheap silk and species, that could be sell in Europe with huge profit, if the possibility to "buy" goods in new places will be open.



Port-Royal could be a source of criminals and various "Pirate" units (Pirate captains, buccaneers, etc.). The player could buy "Pirate" units only in this city. To my opinion "Privateer ships" also should be available only in Port-Royal.



A short description of each new place you could find in this section.









"Slave" unit. At the moment I found only one possibility to release "Slave". I can send him for education in any native village, where he became, for instance, a professional farmer or miner.



More information will be provided in a separate mini-mod next week. Source codes will be included. I plan to explain all advantages and to show all problems that I have at the moment.
 
I continue to work on the mod. At the moment I use the world map generated by Earth31.py as a basis. The transition on the real map of the Earth will be made when will be ready
- a full list of the European and native civilization (leaders, units) and
- a new economic model of development (resources, production cycles, professions).

What are your ideas for the new economic model of development? Did you change the way that prices are rise and fall?
 
What are your ideas for the new economic model of development? Did you change the way that prices are rise and fall?

The prices in Europe will oscillate in some interval and gold/silver never will cheaper that wood. The sell prices in Africa, Orient, Port-Royal will be stable. "Buy" prices in these places do not work yet. :(

New resources will be added (for instance, silk and porcelain on the Orient). More complicated and more realistic technological lines for some good's production. For instance: "Hire-Furs-Leather" line:

and many-many others.
 
The prices in Europe will oscillate in some interval and gold/silver never will cheaper that wood. The sell prices in Africa, Orient, Port-Royal will be stable. "Buy" prices in these places do not work yet. :(

One idea is that you could make the Africa, Orient and Port-Royal prices be the same as the European ones, but with a modifier for certain yields. For example, Rum in Port-Royal could cost 150% of what it would cost in Europe. Do you have consumption of luxury commodities (coats, etc.) in place? Because if you do, and since in the Earth map you would have European cities placed on the map, you could have the prices be based on supply and demand of commodities in the European civ's cities.

In SoI I am using a simple formula, basically a base price multiplied by the demand and divided by the supply. Supply is the amount stored in all cities plus the net production. Demand is the amount demanded by citizens each turn (they have their own money reserves in SoI; if the price is higher than their reserves, they won't demand the commodity, and thus the price won't rise too much), plus the amount required by the building in production to reach completion (hammers are counted for lumber instead). There is also something else that adds to demand of horses and guns, but it's a bit complex to explain, so I won't go into it here. Then, inputs have their demand value increased by the demand of the output made from them, as long they cost less than the output.

This system has been working fine for me so far, so it could be useful to you if you have a luxury consumption system in place.

New resources will be added (for instance, silk and porcelain on the Orient). More complicated and more realistic technological lines for some good's production. For instance: "Hire-Furs-Leather" line:

and many-many others.

Interesting :) Are these going to be implemented in new buildings? Or are you going to use the old ones? One thing I think would be cool is if a building's slots could be used for different professions.
 
One idea is that you could make the Africa, Orient and Port-Royal prices be the same as the European ones, but with a modifier for certain yields. For example, Rum in Port-Royal could cost 150% of what it would cost in Europe. Do you have consumption of luxury commodities (coats, etc.) in place? Because if you do, and since in the Earth map you would have European cities placed on the map, you could have the prices be based on supply and demand of commodities in the European civ's cities.

In SoI I am using a simple formula, basically a base price multiplied by the demand and divided by the supply. Supply is the amount stored in all cities plus the net production. Demand is the amount demanded by citizens each turn (they have their own money reserves in SoI; if the price is higher than their reserves, they won't demand the commodity, and thus the price won't rise too much), plus the amount required by the building in production to reach completion (hammers are counted for lumber instead). There is also something else that adds to demand of horses and guns, but it's a bit complex to explain, so I won't go into it here. Then, inputs have their demand value increased by the demand of the output made from them, as long they cost less than the output.

This system has been working fine for me so far, so it could be useful to you if you have a luxury consumption system in place.
At the moment I have no consumption system of luxury commodities in my cities. However taking into account the list of new resources it would be very usefull to add such feature in the mod.

Are these going to be implemented in new buildings? Or are you going to use the old ones? One thing I think would be cool is if a building's slots could be used for different professions.
New buildings and new professions will be added. In current case "Tannery" building and "Tanner" profession will be necessary for the effective Leather production. However, Leather is not a final product. It could be used for Boots (one of luxury commodities) production, plus some quantity will be required for Wagon Train construction and as Scout equipment, etc. The final scheme could be probably rather complicate, however logically correct.

In my work I follow to a very simple idea:
"New colonist arrives in absolutely new place. What he need? Independence, as the game developpers think. :lol: Of course, not! First of all he needs food, everyday goods, tools to build his new home, arms to protect himself from wild animals and enemies, money to buy necessary goods from Europe, etc. "Independence" is his last priority".

One thing I think would be cool is if a building's slots could be used for different professions.
I'm afraid in such case we could create various unexpected problems in our mods.
 
At the moment I have no consumption system of luxury commodities in my cities. However taking into account the list of new resources it would be very usefull to add such feature in the mod.

New buildings and new professions will be added. In current case "Tannery" building and "Tanner" profession will be necessary for the effective Leather production. However, Leather is not a final product. It could be used for Boots (one of luxury commodities) production, plus some quantity will be required for Wagon Train construction and as Scout equipment, etc. The final scheme could be probably rather complicate, however logically correct.[/quote]

Well, nice to hear.

In my work I follow to a very simple idea:
"New colonist arrives in absolutely new place. What he need? Independence, as the game developpers think. :lol: Of course, not! First of all he needs food, everyday goods, tools to build his new home, arms to protect himself from wild animals and enemies, money to buy necessary goods from Europe, etc. "Independence" is his last priority".

:lol: yes, indeed :p I find vanilla Civ4Col to be too peaceful.

I'm afraid in such case we could create various unexpected problems in our mods.

If you are talking about technical problems, I made a modification to make it possible for multiple professions to use the same building a little while ago in preparation, as I have plans to have, for example, Wool and Silk Weavers working in the SPECIALBUILDING_CLOTH buildings. I changed CvCity::isAvailableProfessionSlot, here is how it became:

Code:
bool CvCity::isAvailableProfessionSlot(ProfessionTypes eProfession, const CvUnit* pUnit) const
{
	if (GC.getProfessionInfo(eProfession).isCitizen())
	{
		if (GC.getProfessionInfo(eProfession).isWorkPlot())
		{
			if (!isUnitWorkingAnyPlot(pUnit) && getNumAvailableWorkPlots() == 0)
			{
				return false;
			}
		}
		else
		{
			int iSlots = getNumProfessionBuildingSlots(eProfession);

			for (uint i = 0; i < m_aPopulationUnits.size() && iSlots > 0; ++i)
			{
				CvUnit* pLoopUnit = m_aPopulationUnits[i];
				if (pUnit != pLoopUnit)
				{
					//profession slot modification, so that different professions can use the same slot total in a building
					for (int iProfession = 0; iProfession < GC.getNumProfessionInfos(); iProfession++)
					{
						ProfessionTypes eSlotProfession = (ProfessionTypes) iProfession;
						if (GC.getProfessionInfo(eProfession).getSpecialBuilding() == GC.getProfessionInfo(eSlotProfession).getSpecialBuilding() && pLoopUnit->getProfession() == eSlotProfession)
						{
							--iSlots;
						}
//					if (pLoopUnit->getProfession() == eProfession)
//					{
//						--iSlots;
//					}
					}
				}
			}

			if (iSlots <= 0)
			{
				FAssert(iSlots == 0);
				return false;
			}
		}
	}

	return true;
}

I have tested it and so far it works, but there is a problem with the interface in CvMainInterface.py, as it creates the graphics for profession slots per profession instead of per SpecialBuilding.

EDIT: Fixed the interface problem. Here is the code in case you want to use multiple professions for the same special building:

Code:
		# IN CITY WORKERS
			pHeadSelectedCity = CyInterface().getHeadSelectedCity()
			pHeadSelectedUnit = CyInterface().getHeadSelectedUnit()
			
			if (pHeadSelectedCity and CyInterface().getShowInterface() == InterfaceVisibility.INTERFACE_SHOW):
				CitizenProfessionIndexArray = []
				#Androrc - added a similar index array for buildings
				CitizenSpecialBuildingIndexArray = []
				CitizenBarCount = 0
				for iProfession in range(gc.getNumProfessionInfos()):
					CitizenProfessionIndexArray.append([])
						
				for iSpecialBuilding in range(gc.getNumSpecialBuildingInfos()):
					CitizenSpecialBuildingIndexArray.append([])

				for j in range(pHeadSelectedCity.getPopulation()):
					pCitizen = pHeadSelectedCity.getPopulationUnitByIndex(j)
					CitizenProfessionIndexArray[pCitizen.getProfession()].append(pCitizen)
					CitizenSpecialBuildingIndexArray[gc.getProfessionInfo(pCitizen.getProfession()).getSpecialBuilding()].append(pCitizen)
					CitizenBarCount += 1

				for iBuilding in range(gc.getNumBuildingInfos()):
					if (pHeadSelectedCity.isHasBuilding(iBuilding)):
						iSpecialBuildingType = gc.getBuildingInfo(iBuilding).getSpecialBuildingType()
						CityBuilding = iBuilding
						iProfession = -1
						if (gc.getBuildingInfo(CityBuilding).getMaxWorkers() > 0):
							for iArrayProfession in range(gc.getNumProfessionInfos()):
								if (gc.getProfessionInfo(iArrayProfession).getSpecialBuilding() == iSpecialBuildingType):
									if (not gc.getProfessionInfo(iArrayProfession).isWorkPlot() and gc.getProfessionInfo(iArrayProfession).isCitizen()):
										if gc.getCivilizationInfo(pHeadSelectedCity.getCivilizationType()).isValidProfession(iArrayProfession):
											iYield = gc.getProfessionInfo(iArrayProfession).getYieldProduced()
											iProfession = iArrayProfession
											break

							if (CityBuilding != -1 and iProfession != -1):
								ButtonSize = LARGE_BUTTON_SIZE * 5 / 2
								ProducedYield = pHeadSelectedCity.getBaseRawYieldProduced(iYield)
								UnproducedYield = ProducedYield - pHeadSelectedCity.calculateActualYieldProduced(iYield)
								bHasYield = (pHeadSelectedCity.getBaseRawYieldProduced(iYield) != 0 or pHeadSelectedCity.getRawYieldConsumed(iYield) != 0)

								if (gc.getBuildingInfo(CityBuilding).getMaxWorkers() > 0):
									CitizenSpacing = BUILDING_GRID[iSpecialBuildingType][3] / gc.getBuildingInfo(iBuilding).getMaxWorkers()
								else:
									CitizenSpacing = ButtonSize / 2

								if (CityBuilding != -1):
									screen.show("ProductionBox" + str(iSpecialBuildingType))
									szName = "YieldOutPutIcon" + str(iYield)
									screen.addDDSGFC(szName, gc.getYieldInfo(iYield).getIcon(), BUILDING_GRID[iSpecialBuildingType][0] + (STACK_BAR_HEIGHT / 2), BUILDING_GRID[iSpecialBuildingType][1] + BUILDING_GRID[iSpecialBuildingType][2] - (BUILDING_GRID[iSpecialBuildingType][2] / 6) + STACK_BAR_HEIGHT, STACK_BAR_HEIGHT * 5 / 2, STACK_BAR_HEIGHT * 5 / 2, WidgetTypes.WIDGET_HELP_YIELD, iYield, -1)
									CitizenHideList.append(szName)
								else:
									screen.hide("ProductionBox" + str(iSpecialBuildingType))

								ProfessionCount = len(CitizenSpecialBuildingIndexArray[iSpecialBuildingType])
								for GroupIndex in range(ProfessionCount):
									pCitizen = CitizenSpecialBuildingIndexArray[iSpecialBuildingType][GroupIndex]

									if (pCitizen.isColonistLocked()):
										szName = "CitizenButtonLock" + str(pCitizen.getID())
										screen.addDDSGFC(szName, ArtFileMgr.getInterfaceArtInfo("INTERFACE_CITY_CITIZEN_LOCK").getPath(), BUILDING_GRID[iSpecialBuildingType][0] + (CitizenSpacing * GroupIndex) + (CitizenSpacing / 2) - (STACK_BAR_HEIGHT / 3), BUILDING_GRID[iSpecialBuildingType][1] + BUILDING_GRID[iSpecialBuildingType][2] - (ButtonSize) - (STACK_BAR_HEIGHT / 3), STACK_BAR_HEIGHT * 3 / 2, STACK_BAR_HEIGHT * 3 / 2, WidgetTypes.WIDGET_GENERAL, -1, -1)
										CitizenHideList.append(szName)

									szName = "CitizenButton" + str(iProfession) + "-" + str(GroupIndex)
									screen.addDragableButton(szName, pCitizen.getFullLengthIcon(), "", BUILDING_GRID[iSpecialBuildingType][0] + (CitizenSpacing * GroupIndex) + (CitizenSpacing/ 2), BUILDING_GRID[iSpecialBuildingType][1] + BUILDING_GRID[iSpecialBuildingType][2] - (ButtonSize), ButtonSize / 2, ButtonSize, WidgetTypes.WIDGET_CITIZEN, pCitizen.getID(), -1, ButtonStyles.BUTTON_STYLE_IMAGE)							
									CitizenHideList.append(szName)

								for iSlot in range (gc.getBuildingInfo(CityBuilding).getMaxWorkers() - ProfessionCount):
									szName = "CitizenSlot" + str(iProfession) + "-" + str(iSlot)
									screen.addDDSGFC(szName, ArtFileMgr.getInterfaceArtInfo("INTERFACE_CITIZEN_SLOT").getPath(), BUILDING_GRID[iSpecialBuildingType][0] + (CitizenSpacing * (iSlot + ProfessionCount)) + (CitizenSpacing/ 2), BUILDING_GRID[iSpecialBuildingType][1] + BUILDING_GRID[iSpecialBuildingType][2] - ButtonSize, ButtonSize / 2, ButtonSize, WidgetTypes.WIDGET_CITY_UNIT_ASSIGN_PROFESSION, -1, iProfession)
									CitizenHideList.append(szName)

								SzText = ""
								if (ProducedYield > 0):
									SzText += u"<color=0,255,0> +" + str(ProducedYield) + "</color>"
								if (UnproducedYield > 0):
									SzText += u"<color=255,0,0> -" + str(UnproducedYield) + "</color>"

								szName = "WorkerOutputText" + str(iYield)
								screen.setLabelAt(szName, "ProductionBox" + str(iSpecialBuildingType), self.setFontSize(SzText , 1), CvUtil.FONT_RIGHT_JUSTIFY, BUILDING_GRID[iSpecialBuildingType][3] + (STACK_BAR_HEIGHT / 2), STACK_BAR_HEIGHT / 2, -0.3, FontTypes.GAME_FONT, WidgetTypes.WIDGET_HELP_YIELD, iYield, -1)
								CitizenHideList.append(szName)

							else:
								screen.hide("ProductionBox" + str(iSpecialBuildingType))
								
				iSpace = CITIZEN_BAR_WIDTH - (LARGE_BUTTON_SIZE * 3)
				iSeperation = iSpace / CitizenBarCount
				if (iSeperation > (LARGE_BUTTON_SIZE * 2)):
					iSeperation = (LARGE_BUTTON_SIZE * 2)
				iCount = 0
	
				for iProfession in range(gc.getNumProfessionInfos()):
					for GroupIndex in range(len(CitizenProfessionIndexArray[iProfession])):
						pCitizen = CitizenProfessionIndexArray[iProfession][GroupIndex]
						szName = "PopulationButton" + str(iCount)
						ButtonSize = LARGE_BUTTON_SIZE * 3
						screen.show(szName)
						screen.setState(szName, pCitizen.isColonistLocked())
						CitizenHideList.append(szName)
						iCount += 1

			screen.registerHideList(CitizenHideList, len(CitizenHideList), CITIZEN_HIDE)
			self.updateGarrisonAndTransports()
			self.updateResourceTable()
 
If you are talking about technical problems, I made a modification to make it possible for multiple professions to use the same building a little while ago in preparation, as I have plans to have, for example, Wool and Silk Weavers working in the SPECIALBUILDING_CLOTH buildings. I changed CvCity::isAvailableProfessionSlot, here is how it became:

I have tested it and so far it works, but there is a problem with the interface in CvMainInterface.py, as it creates the graphics for profession slots per profession instead of per SpecialBuilding.

EDIT: Fixed the interface problem.

Does it means that for this case


I could send in the same building Cotton_Weaver and Wool_Weaver and they both will produce "Cloth"?
 
Does it means that for this case


I could send in the same building Cotton_Weaver and Wool_Weaver and they both will produce "Cloth"?

Yes. They can produce different yields too, but only the produced yield of the profession first in the xml order will appear as the icon next to the building. The same will apply for when you drop a citizen in the building: it will become the profession that is located first in the xml order (not that that matters much though, as you can set the profession through the profession choice popup).
 
Back
Top Bottom