Vassals

Yes they are very nice. Perhaps spoiler tags around images though might make the forum easier to navigate? :)

Just in case the humour in my post isn't clear enough, I'm not taking a shot at you, just a reminder.

Good idea. Done.

Can we discuss diplomatic penalties for taxation? The most obvious solution would be to have a formula (which right now is x^1.5 / 3) to determine the diplo hit, but that'll vary depending on how you set it, which could be a good or bad thing.

Another solution is to track taxed GPT / total GPT gained while vassaled and then make the diplo hit based on that. If you tax them for long periods of time then they'll hate you more. However, that'll make it very hard to recover from heavy taxation diplomatically.

Do you like either of those solutions or perhaps something different?
 
Almost done with the Vassal Overview screen. Doing lots of polish, some things still remain.

Going to work on getting the AI to understand the new features this week, and then I have to do the master overview, which should be less work overall.

Spoiler :
gFawEu6.png
 
Almost done with the Vassal Overview screen. Doing lots of polish, some things still remain.

Going to work on getting the AI to understand the new features this week, and then I have to do the master overview, which should be less work overall.

Spoiler :
gFawEu6.png

One thing - might be worthwhile to have a tab showing who is vassalized to whom, and the current status of that vassal relationship (forced/friendly/unfriendly).

Also, another thought - it'd be an interesting side-effect of vassal dislike if they could refuse to join your wars or, when you raise your taxes, declare war on you.
G
 
One more thing:
Vassals shouldn't be allowed to sign defensive pacts, and existing ones should be cancelled once one side is vassalaged.
I had a game where I declared war on a civ wich had a defensive pact with one of my vassals. My vassal actually declared war on me. The game eventually sorted it out, the next turn we were at peace again and he was fighting at my side, but it was quite confusing.
 
One more thing:
Vassals shouldn't be allowed to sign defensive pacts, and existing ones should be cancelled once one side is vassalaged.
I had a game where I declared war on a civ wich had a defensive pact with one of my vassals. My vassal actually declared war on me. The game eventually sorted it out, the next turn we were at peace again and he was fighting at my side, but it was quite confusing.

Thanks for the bug report! I'll fix that.

Regarding the vassal tab view, I agree, but I want to push that off until a future update. I'm anxious to get this patch into Beta testing as I really want to play a game with the new changes and get feedback on what needs fixing. I think by next week i can get a beta out, but Gazebo, I think we'll need to discuss how to properly integrate my changes because they're very involved,and I'm planning two deployments.
 
I had an idea - if you have multiple vassals, and one successfully fulfills the requirements to request independence, it would be neat if your remaining vassals were to get a negative diplo boost with you, because they've become enticed with the idea of their own independence, and begin a more aggressive push to be able to declare their own.

Or, pairing with G's idea, maybe when one vassal becomes ready to ask for their independence, if you decline, one or more of your other vassals who are unsatisfied with you may team up with them, even though they've only completed 75% or so of their own requirements needed for independence. Just spit-balling ideas :lol:
 
Thanks for the bug report! I'll fix that.

Regarding the vassal tab view, I agree, but I want to push that off until a future update. I'm anxious to get this patch into Beta testing as I really want to play a game with the new changes and get feedback on what needs fixing. I think by next week i can get a beta out, but Gazebo, I think we'll need to discuss how to properly integrate my changes because they're very involved,and I'm planning two deployments.

Well, as long as your changes are inside of preprocessor directives, it is pretty easy. Make the commit so that I can see what files you changed, and then I'll manage the merge (I'm weird and old-fashioned, I like to merge things by hand using winmerge :) ).

G
 
Well, as long as your changes are inside of preprocessor directives, it is pretty easy. Make the commit so that I can see what files you changed, and then I'll manage the merge (I'm weird and old-fashioned, I like to merge things by hand using winmerge :) ).

G

Everything will be inside the directives. The problem ain't the DLL, I'm more concerned about the LUA and SQL changes being done correctly. Not sure how much could change between CP and CBP and all the compatability files.
 
Well, as long as your changes are inside of preprocessor directives, it is pretty easy. Make the commit so that I can see what files you changed, and then I'll manage the merge (I'm weird and old-fashioned, I like to merge things by hand using winmerge :) ).

G

I found Winmerge to be awesome, and quite fast by hand! What a handy little tool.
 
I found Winmerge to be awesome, and quite fast by hand! What a handy little tool.

I love winmerge.

Everything will be inside the directives. The problem ain't the DLL, I'm more concerned about the LUA and SQL changes being done correctly. Not sure how much could change between CP and CBP and all the compatability files.

Winmerge works there as well. Really, you only need to look at the EUI/No-EUI CBP compatibility files - all the lua files originally modified by C4DF are in those mods (labeled C4DF or Putmalk as per your original design). Any wholly original lua files (i.e. your new vassal screens) will be added to the C4DF module (as they won't need to be overwritten by anything from the CBP). Thus the only files that will need to really be looked at will be the toppanel.lua, diplolist.lua, and possibly tradelogic.lua. Everything else should be independent, and should thus work.

Once I know what files you have changed, I can offer more concrete answers.

G
 
I have never actually been able to get any Vassals in CPP. I've fought nations down to their very last city and tried to get them to capitulate but every time they refuse. I'm not sure why they prefer to be wiped out instead of capitulating.
 
I have never actually been able to get any Vassals in CPP. I've fought nations down to their very last city and tried to get them to capitulate but every time they refuse. I'm not sure why they prefer to be wiped out instead of capitulating.

This was maybe the situation and I say maybe because I recall having vassal few times I chose to use this feature but now you can achieve that quite convenient. with last few betas
 
I'll be extensively testing the vassal system to make sure it conforms to my expectations. Hopefully issues where you can't make them capitulate will be addressed. :)
 
One more thing:
Vassals shouldn't be allowed to sign defensive pacts, and existing ones should be cancelled once one side is vassalaged.
I had a game where I declared war on a civ wich had a defensive pact with one of my vassals. My vassal actually declared war on me. The game eventually sorted it out, the next turn we were at peace again and he was fighting at my side, but it was quite confusing.

Okay made it so that you can't make Defensive Pacts when you're a vassal. (haven't updated front end)

Regarding dissolution of defensive pacts - seems to be already implemented by the CPP folks!
 
Update: AI should know how to set taxes intelligently, but I will also post the routine so if any code monkeys wanna critique, go ahead :)

Spoiler :

vGJ0wtU.jpg

g073zQX.png



Code:
// Determine how much we are going to tax this player, if we can
void CvDiplomacyAI::DoDetermineTaxRateForVassalOnePlayer(PlayerTypes ePlayer)
{
	// Must be able to set taxes for player
	if(!GET_TEAM(GetPlayer()->getTeam()).CanSetVassalTax(ePlayer))
		return;

	TeamTypes eMyTeam = GetPlayer()->getTeam();
	CvTeam& kMyTeam = GET_TEAM(eMyTeam);

	// Do not allow an AI teammate to do this for a human
	if(!GetPlayer()->isHuman() && kMyTeam.isHuman())
		return;

	// Current tax rate
	int iTaxRate = kMyTeam.GetVassalTax(ePlayer);

	// Make sure we can actually do that...
	bool bWantToLower = iTaxRate > GC.getVASSALAGE_VASSAL_TAX_PERCENT_MINIMUM();
	bool bWantToRaise = iTaxRate < GC.getVASSALAGE_VASSAL_TAX_PERCENT_MAXIMUM();

	// Because this function will involve lots of iteration over team members, let's store all alive team members in temporary vectors to improve the speed of this function
	std::vector<CvPlayerAI*> m_MasterTeam;
	std::vector<CvPlayerAI*> m_VassalTeam;

	for(int iI=0; iI < MAX_MAJOR_CIVS; iI++)
	{
		PlayerTypes eLoopPlayer = (PlayerTypes) iI;
		if(GET_PLAYER(eLoopPlayer).isAlive())
		{
			// Master team
			if(GET_PLAYER(eLoopPlayer).getTeam() == GetPlayer()->getTeam())
			{
				m_MasterTeam.push_back(&GET_PLAYER(eLoopPlayer));
			}
			// Vassal team
			else if(GET_PLAYER(eLoopPlayer).getTeam() == GET_PLAYER(ePlayer).getTeam())
			{
				m_VassalTeam.push_back(&GET_PLAYER(eLoopPlayer));
			}
		}
	}
	
	MajorCivOpinionTypes eTeamOpinion = MAJOR_CIV_OPINION_NEUTRAL;
	int iMyCurrentGPT = 0, iMyCurrentGross = 0, iAverageMeanness = 0, iAverageLoyalty = 0, iAverageOpinionScore = 0;
	for(std::vector<CvPlayerAI*>::iterator it = m_MasterTeam.begin(); it != m_MasterTeam.end(); it++)
	{
		iMyCurrentGPT += (*it)->GetTreasury()->CalculateBaseNetGoldTimes100();
		iMyCurrentGross += (*it)->GetTreasury()->CalculateBaseNetGoldTimes100();

		iAverageMeanness += (*it)->GetDiplomacyAI()->GetMeanness();
		iAverageLoyalty += (*it)->GetDiplomacyAI()->GetLoyalty();
		iAverageOpinionScore += (int) (*it)->GetDiplomacyAI()->GetMajorCivOpinion(ePlayer);
	}
	iAverageMeanness /= m_MasterTeam.size();
	iAverageLoyalty /= m_MasterTeam.size();
	iAverageOpinionScore /= m_MasterTeam.size();

	eTeamOpinion = (MajorCivOpinionTypes) iAverageOpinionScore;

	int iVassalCurrentGPT = 0, iVassalCurrentGross = 0;
	for(std::vector<CvPlayerAI*>::iterator it = m_VassalTeam.begin(); it != m_VassalTeam.end(); it++)
	{
		iVassalCurrentGPT += (*it)->GetTreasury()->CalculateBaseNetGoldTimes100();
		iVassalCurrentGross += (*it)->GetTreasury()->CalculateGrossGoldTimes100();
	}

	// Hate him? Don't consider lowering!
	if(eTeamOpinion == MAJOR_CIV_OPINION_UNFORGIVABLE)
		bWantToLower = false;

	
	// Like him? Don't consider raising!
	if(eTeamOpinion == MAJOR_CIV_OPINION_ALLY)
		bWantToRaise = false;

	// We have some choice in the direction taxes can go - pick a direction so we can start deciding
	if(bWantToLower && bWantToRaise)
	{
		// We're in dire straights
		if(iMyCurrentGPT <= 0)
		{
			bWantToLower = false;	// don't even consider lowering
			
			// Check to see if taxing the vassal the maximum would get us out of dire straights
			if(bWantToRaise)
			{
				// Wouldn't help us out at all
				if((iVassalCurrentGross * GC.getVASSALAGE_VASSAL_TAX_PERCENT_MAXIMUM() / 100 < 100))
				{
					bWantToRaise = false;
				}
				// Tax vassal the maximum to get us out of trouble - his feelings be damned
				else
				{
					kMyTeam.DoApplyVassalTax(ePlayer, GC.getVASSALAGE_VASSAL_TAX_PERCENT_MAXIMUM());
					return;
				}
			}
		}
		// Doing fine - have some choice
		else
		{	

			int iScoreForLower = 0;
			int iScoreForRaise = 0;

			// Starting values based on opinion
			switch(eTeamOpinion)
			{
			case MAJOR_CIV_OPINION_ENEMY:
				iScoreForLower = -25;
				iScoreForRaise = 25;
			case MAJOR_CIV_OPINION_COMPETITOR:
				iScoreForLower = -10;
				iScoreForRaise = 10;
				break;
			case MAJOR_CIV_OPINION_NEUTRAL:
				iScoreForLower = 0;
				iScoreForRaise = 0;
				break;
			case MAJOR_CIV_OPINION_FAVORABLE:
				iScoreForLower = 10;
				iScoreForRaise = -10;
				break;
			case MAJOR_CIV_OPINION_FRIEND:
				iScoreForLower = 25;
				iScoreForRaise = -25;
				break;
			default:
				CvAssertMsg(false, "Should not have gotten here.");
			}

			// Still deciding what to be done?
			if(bWantToLower && bWantToRaise)
			{
				// Is our vassal doing better than us monetarily?
				if(iVassalCurrentGPT >= iMyCurrentGPT)
				{
					iScoreForLower *= 75;
					iScoreForLower /= 100;

					iScoreForRaise *= 125;
					iScoreForRaise /= 100;
				}
				// He is doing worse than 85% of our GPT
				else if(iVassalCurrentGPT * 85 <= iMyCurrentGPT * 100)
				{
					// Have to like the vassal
					if(eTeamOpinion > MAJOR_CIV_OPINION_NEUTRAL)
					{
						// Determine a percentage to lower
						int iThreshold = 33;

						// He is doing REALLY bad
						if(iVassalCurrentGPT * 150 < iMyCurrentGPT * 100)
							iThreshold = 75;

						int iRand = GC.getGame().getJonRandNum(100, "CvDiplomacyAI: Do we want to give this vassal a nice boost in GPT cus his GPT is less and we like him?");
						if(iRand < iThreshold)
						{
							iScoreForLower *= 150;
							iScoreForLower /= 100;
						}
					}
				}

				// Raise score for lowering based on loyalty
				iScoreForLower *= 100 + (iAverageLoyalty - 5) * 10;
				iScoreForLower /= 100;

				// Raise score for lowering based on meanness
				iScoreForRaise *= 100 + (iAverageMeanness - 5) * 10;
				iScoreForRaise /= 100;

				bWantToLower = (iScoreForLower > iScoreForRaise);
				bWantToRaise = (iScoreForLower < iScoreForRaise);
			}
		}
	}

	CvWeightedVector<int, 20, true> aPossibleValues;	// in case changed, 100 / 5  is a safe bet for number of possible elements
	
	// New tax value defaults to current tax rate
	int iNewTaxValue = iTaxRate;

	// Decided we're going to lower - figure out by how much
	if(bWantToLower)
	{
		int iCurrentIndex = 0;

		// Possible values are determined by increments of 5 starting from below the current tax line
		for(int i = (iTaxRate - 5); i >= GC.getVASSALAGE_VASSAL_TAX_PERCENT_MINIMUM(); i -= 5)
		{
			int iValue = i;
			int iWeight = (iAverageOpinionScore - 3) * iCurrentIndex + 100;
			
			// Determine if we will make at least one GPT profit off of this value, if not, then decentivize
			if(iVassalCurrentGross * iValue < 10000)
				iWeight /= 4;

			aPossibleValues.push_back(iValue, iWeight);
			iCurrentIndex++;
		}

		RandomNumberDelegate fcn;
		fcn = MakeDelegate(&GC.getGame(), &CvGame::getJonRandNum);
		iNewTaxValue = aPossibleValues.ChooseByWeight(&fcn, "Choose the tax value to assign");
	}
	// Decided we're going to raise - figure out by how much
	else
	{
		int iCurrentIndex = 0;
		
		// Possible values are determined by increments of 5 starting from above the current tax line
		for(int i = (iTaxRate + 5); i <= GC.getVASSALAGE_VASSAL_TAX_PERCENT_MAXIMUM(); i += 5)
		{
			int iValue = i;
			int iWeight = (3 - iAverageOpinionScore) * iCurrentIndex + 100;
			
			// Determine if we will make at least one GPT profit off of this value, if not, then decentivize
			if(iVassalCurrentGross * iValue < 10000)
				iWeight /= 4;
			
			aPossibleValues.push_back(iValue, iWeight);
			iCurrentIndex++;
		}

		RandomNumberDelegate fcn;
		fcn = MakeDelegate(&GC.getGame(), &CvGame::getJonRandNum);
		iNewTaxValue = aPossibleValues.ChooseByWeight(&fcn, "Choose the tax value to assign");
	}

	// Set the tax.
	kMyTeam.DoApplyVassalTax(ePlayer, iNewTaxValue);
}
 
Update: AI should know how to set taxes intelligently, but I will also post the routine so if any code monkeys wanna critique, go ahead :)

Spoiler :

vGJ0wtU.jpg

g073zQX.png

OXxgz5P.png

0XPvsqs.png



Spoiler :
Code:
// Determine how much we are going to tax this player, if we can
void CvDiplomacyAI::DoDetermineTaxRateForVassalOnePlayer(PlayerTypes ePlayer)
{
	// Must be able to set taxes for player
	if(!GET_TEAM(GetPlayer()->getTeam()).CanSetVassalTax(ePlayer))
		return;

	TeamTypes eMyTeam = GetPlayer()->getTeam();
	CvTeam& kMyTeam = GET_TEAM(eMyTeam);

	// Do not allow an AI teammate to do this for a human
	if(!GetPlayer()->isHuman() && kMyTeam.isHuman())
		return;

	// Current tax rate
	int iTaxRate = GET_TEAM(GetPlayer()->getTeam()).GetVassalTax(ePlayer);

	// Make sure we can actually do that...
	bool bWantToLower = iTaxRate > GC.getVASSALAGE_VASSAL_TAX_PERCENT_MINIMUM();
	bool bWantToRaise = iTaxRate < GC.getVASSALAGE_VASSAL_TAX_PERCENT_MAXIMUM();

	// Because this function will involve lots of iteration over team members, let's store all alive team members in temporary vectors to improve the speed of this function
	std::vector<CvPlayerAI*> m_MasterTeam;
	std::vector<CvPlayerAI*> m_VassalTeam;

	for(int iI=0; iI < MAX_MAJOR_CIVS; iI++)
	{
		PlayerTypes eLoopPlayer = (PlayerTypes) iI;
		if(GET_PLAYER(eLoopPlayer).isAlive())
		{
			// Master team
			if(GET_PLAYER(eLoopPlayer).getTeam() == GetPlayer()->getTeam())
			{
				m_MasterTeam.push_back(&GET_PLAYER(eLoopPlayer));
			}
			// Vassal team
			else if(GET_PLAYER(eLoopPlayer).getTeam() == GET_PLAYER(ePlayer).getTeam())
			{
				m_VassalTeam.push_back(&GET_PLAYER(eLoopPlayer));
			}
		}
	}
	
	MajorCivOpinionTypes eTeamOpinion = MAJOR_CIV_OPINION_NEUTRAL;
	int iMyCurrentGPT = 0, iMyCurrentGross = 0, iAverageMeanness = 0, iAverageLoyalty = 0, iAverageOpinionScore = 0;
	for(std::vector<CvPlayerAI*>::iterator it = m_MasterTeam.begin(); it != m_MasterTeam.end(); it++)
	{
		iMyCurrentGPT += (*it)->GetTreasury()->CalculateBaseNetGoldTimes100();
		iMyCurrentGross += (*it)->GetTreasury()->CalculateBaseNetGoldTimes100();

		iAverageMeanness += (*it)->GetDiplomacyAI()->GetMeanness();
		iAverageLoyalty += (*it)->GetDiplomacyAI()->GetLoyalty();
		iAverageOpinionScore += (int) (*it)->GetDiplomacyAI()->GetMajorCivOpinion(ePlayer);
	}
	iAverageMeanness /= m_MasterTeam.size();
	iAverageLoyalty /= m_MasterTeam.size();
	iAverageOpinionScore /= m_MasterTeam.size();

	eTeamOpinion = (MajorCivOpinionTypes) iAverageOpinionScore;

	int iVassalCurrentGPT = 0, iVassalCurrentGross = 0;
	for(std::vector<CvPlayerAI*>::iterator it = m_VassalTeam.begin(); it != m_VassalTeam.end(); it++)
	{
		iVassalCurrentGPT += (*it)->GetTreasury()->CalculateBaseNetGoldTimes100();
		iVassalCurrentGross += (*it)->GetTreasury()->CalculateGrossGoldTimes100();
	}

	// Hate him? Don't consider lowering!
	if(eTeamOpinion == MAJOR_CIV_OPINION_UNFORGIVABLE)
		bWantToLower = false;

	
	// Like him? Don't consider raising!
	if(eTeamOpinion == MAJOR_CIV_OPINION_ALLY)
		bWantToRaise = false;

	// We have some choice in the direction taxes can go - pick a direction so we can start deciding
	if(bWantToLower && bWantToRaise)
	{
		// We're in dire straights
		if(iMyCurrentGPT <= 0)
		{
			bWantToLower = false;	// don't even consider lowering
			
			// Check to see if taxing the vassal the maximum would get us out of dire straights
			if(bWantToRaise)
			{
				// Wouldn't help us out at all
				if((iVassalCurrentGross * GC.getVASSALAGE_VASSAL_TAX_PERCENT_MAXIMUM() / 100 < 0))
				{
					bWantToRaise = false;
				}
				// Tax vassal the maximum to get us out of trouble - his feelings be damned
				else
				{
					GET_TEAM(GetPlayer()->getTeam()).DoApplyVassalTax(ePlayer, GC.getVASSALAGE_VASSAL_TAX_PERCENT_MAXIMUM());
				}
			}
		}
		// Doing fine - have some choice
		else
		{	

			int iScoreForLower = 0;
			int iScoreForRaise = 0;

			// Starting values based on opinion
			switch(eTeamOpinion)
			{
			case MAJOR_CIV_OPINION_ENEMY:
				iScoreForLower = -25;
				iScoreForRaise = 25;
			case MAJOR_CIV_OPINION_COMPETITOR:
				iScoreForLower = -10;
				iScoreForRaise = 10;
				break;
			case MAJOR_CIV_OPINION_NEUTRAL:
				iScoreForLower = 0;
				iScoreForRaise = 0;
				break;
			case MAJOR_CIV_OPINION_FAVORABLE:
				iScoreForLower = 10;
				iScoreForRaise = -10;
				break;
			case MAJOR_CIV_OPINION_FRIEND:
				iScoreForLower = 25;
				iScoreForRaise = -25;
				break;
			default:
				CvAssertMsg(false, "Should not have gotten here.");
			}

			// Still deciding what to be done?
			if(bWantToLower && bWantToRaise)
			{
				// Is our vassal doing better than us monetarily?
				if(iVassalCurrentGPT >= iMyCurrentGPT)
				{
					iScoreForLower *= 75;
					iScoreForLower /= 100;

					iScoreForRaise *= 125;
					iScoreForRaise /= 100;
				}
				// He is doing worse than 85% of our GPT
				else if(iVassalCurrentGPT * 85 <= iMyCurrentGPT * 100)
				{
					// Have to like the vassal
					if(eTeamOpinion > MAJOR_CIV_OPINION_NEUTRAL)
					{
						// Determine a percentage to lower
						int iThreshold = 33;

						// He is doing REALLY bad
						if(iVassalCurrentGPT * 150 < iMyCurrentGPT * 100)
							iThreshold = 75;

						int iRand = GC.getGame().getJonRandNum(100, "CvDiplomacyAI: Do we want to give this vassal a nice boost in GPT cus his GPT is less and we like him?");
						if(iRand < iThreshold)
						{
							iScoreForLower *= 150;
							iScoreForLower /= 100;
						}
					}
				}

				// Raise score for lowering based on loyalty
				iScoreForLower *= 100 + (iAverageLoyalty - 5) * 10;
				iScoreForLower /= 100;

				// Raise score for lowering based on meanness
				iScoreForRaise *= 100 + (iAverageMeanness - 5) * 10;
				iScoreForRaise /= 100;

				bWantToLower = (iScoreForLower > iScoreForRaise);
				bWantToRaise = (iScoreForLower < iScoreForRaise);
			}
		}
	}

	CvWeightedVector<int, 20, true> aPossibleValues;	// in case changed, 100 / 5  is a safe bet for number of possible elements
	
	// New tax value defaults to current tax rate
	int iNewTaxValue = iTaxRate;

	// Decided we're going to lower - figure out by how much
	if(bWantToLower)
	{
		int iCurrentIndex = 0;

		// Possible values are determined by increments of 5 starting from below the current tax line
		for(int i = (iTaxRate - 5); i >= GC.getVASSALAGE_VASSAL_TAX_PERCENT_MINIMUM(); i -= 5)
		{
			int iValue = i;
			int iWeight = (iAverageOpinionScore - 3) * iCurrentIndex + 100;
			
			// Determine if we will make at least one GPT profit off of this value, if not, then decentivize
			if(iVassalCurrentGross * iValue < 10000)
				iWeight /= 4;

			aPossibleValues.push_back(iValue, iWeight);
			iCurrentIndex++;
		}

		RandomNumberDelegate fcn;
		fcn = MakeDelegate(&GC.getGame(), &CvGame::getJonRandNum);
		iNewTaxValue = aPossibleValues.ChooseByWeight(&fcn, "Choose the tax value to assign");
	}
	// Decided we're going to raise - figure out by how much
	else
	{
		int iCurrentIndex = 0;
		
		// Possible values are determined by increments of 5 starting from above the current tax line
		for(int i = (iTaxRate + 5); i <= GC.getVASSALAGE_VASSAL_TAX_PERCENT_MAXIMUM(); i += 5)
		{
			int iValue = i;
			int iWeight = (3 - iAverageOpinionScore) * iCurrentIndex + 100;
			
			// Determine if we will make at least one GPT profit off of this value, if not, then decentivize
			if(iVassalCurrentGross * iValue < 10000)
				iWeight /= 4;
			
			aPossibleValues.push_back(iValue, iWeight);
			iCurrentIndex++;
		}

		RandomNumberDelegate fcn;
		fcn = MakeDelegate(&GC.getGame(), &CvGame::getJonRandNum);
		iNewTaxValue = aPossibleValues.ChooseByWeight(&fcn, "Choose the tax value to assign");
	}

	// Set the tax.
	kMyTeam.DoApplyVassalTax(ePlayer, iNewTaxValue);
}


Neat! Looks pretty good, though I'll give it another, more analytic glance later. First thought: why not take a cue from my major civ opinion overhaul and vector in major civ opinions for your +/- integer defines? That way civ personality will have an even stronger effect on master behavior. Also, obviously the answer to 'should they raise taxes' should always return true. It's positively imperial. :)

G
 
Spoiler :

w1lVOjQ.jpg



Last update for the night, it's time for me to get ready to sleep for work tomorrow. I'm going to also include a hostile version, which is more like "I'm raising your taxes and nothing you can do to stop it"

Neat! Looks pretty good, though I'll give it another, more analytic glance later. First thought: why not take a cue from my major civ opinion overhaul and vector in major civ opinions for your +/- integer defines? That way civ personality will have an even stronger effect on master behavior. Also, obviously the answer to 'should they raise taxes' should always return true. It's positively imperial.

G

Care to describe your system in further detail? I'm not going to look through the code tonight, and a summary would help out more for me :).

Also England should have a 100% chance to raise taxes all the time. :D
 
Spoiler :

w1lVOjQ.jpg



Last update for the night, it's time for me to get ready to sleep for work tomorrow. I'm going to also include a hostile version, which is more like "I'm raising your taxes and nothing you can do to stop it"



Care to describe your system in further detail? I'm not going to look through the code tonight, and a summary would help out more for me :).

Also England should have a 100% chance to raise taxes all the time. :D

Check out the UpdateOnePlayerMajorCivOpinion (I think that's the name).

At the top of it, I use a vector to store off the personality data for MAJOR_CIV_APPROACH_WAR/FRIENDLY/NEUTRAL/DECEPTIVE/GUARDED etc. those values are then used for opinion checks for positive/negative values (i.e. viPlayerApproach[MAJOR_CIV_APPROACH_WAR] is added to the approach value for an other civ that's weaker than the civ itself.

G
 
So the weekend is here. This week I managed to get a few unpolished systems in place: taxation affecting GPT, and vassal treatment, a diplomatic gauge of how your vassal feels you've treated them.

Current modifiers:

- Tax rate
- Protection score
- # of times you've demanded from them

Do you guys have any ideas of what else constitutes "treatment of a vassal" and how I might add some positive ways of improving their opinion of you?

Thanks.

Firstly, awesome work on this. Looks very exciting.

Can I suggest a subsystem in which the vassal receives a bonus to military production based on culture output? The theory is that the more culturally power a vassal is, the more difficult it should be to be for their overlord to control them. Culture could kind of act as patriotic resistance. Also provides a nice bonus for vassals to help become independent through military. Alternatively perhaps if they do revolt, their culture score might modify the number of "free" units that pop up for the vassal?

Unsure if you've coveres this already but if the vassal revolts, it should automatically sign peace treaties in any other wars they may be in (usually due to master being at war). Would also be good to prevent other civs declaring war on them which they may do if the vassal is losing/lost military units.

In regards to suggestions for treatment modifiers:

- Providing them with science/techs/research points. Perhaps tax rate can include research points?
- Subsidies for Military upkeep (master to pay a % of military upkeep? Although tax rate might a better way of handling this)
- Master going to war should count somewhat like a demand and hence incur a penalty
- Some Policies or ideolgies may modify treatment
- Trade routes from Master (perhaps count the sum of incoming gold to target vassal)


Some suggestions for overall formulation of revolt chance modifiers:

- Difference in military power (unless this is already be formulated in protection score)
- Culture delta or ratio between master and vassal (if vassal has strong culture this should increase their restive state)
- Happiness of the master (lower happiness should embolden the vassals yearn for independence as unhappiness weakens the master through usual penalties)
- Master being at war with powerful civs. Although this could modify chance of revolt organically with the loss of military power during the war (military power ratio of vassal vs master)
 
Some Thoughts!!


Maybye you can have something like pledge to protect for your Vassal!
so you get positive points from Vassal or Negative from Civs that hate your Vassal Civ!
other Civs should know that u protect your Vassal!

Get positive if u Gifts units like to City states?

If you have Troops in your Vassal Territory you get positive points,
like please remove your troops from our borders but the opposite for Vassal!
instead !Thank u for protecting us!

When u Demand something from your vassal he should give u that!!
maybye not a City but if u want 5 Iron he should give it!
(but that get negative relationship)
 
Back
Top Bottom