make forts project cultural borders and zones of control

lth

Chieftain
Joined
Jul 29, 2007
Messages
13
Hi,

I'd like to make it so that forts will add a tiny amount of culture to the square they are built in and the surrounding ones in order that they extend your borders into unclaimed territory (thus if they are built on a border with an opposing civ, the borders are not extended).

Secondly, I'd like units stationed in forts (and cities...) to exhibit the kind of zone-of-control rule of Civs of old, such that if you are in a tile adjacent to a (staffed) enemy fort, then you can't move to another tile adjacent to that (or any other) fort.

Do I need the SDK to do this, or will Python suffice? Either way, whereabouts should I be looking in the code in order to make the right changes?

Thanks!
 
I am working on makeing forts extend culture right now and should have it done in a few days. :)
 
I got forts to extend cultural borders, it was pretty easy with the pPlot.setOwner(iPlayer) method that BtS added.

I am going to work on the ZoC movement restriction tomorrow. I don't think it will be that hard, I think they added a cannotMove event and that will make it simple.
 
Alright, I got the movement restriction part done. I'm going to add in a Fort Management screen sometime today.

Are there any other features yall think should be added to forts?
 
Thanks for all the comments, guys.

Unfortunately I only have vanilla Civ4.

I was really hoping to use this question as a way to get into modding Civ4 myself - I've done a hella lot of Quake modding, so it was great to see that Civ4 is super-moddable.

So if someone wouldn't mind talking me through the steps I'd need to go through to do what Jeckel's done, that would be really helpful. I've got the SDK and VS2k3 (haven't tried opening and compiling the project yet, that's tonight's task after I watch disc 4 of the Wire season 2!), and a pretty good grasp of programming, I just don't really know where to start looking for this stuff in the source files.

Thanks again!
 
Well, this stuff is going to be alot harder to do in vanilla, but a place you might want to start looking is CvUnit.cpp, specificly canMoveInto(). It is the function that controls, surprisingly enough, what tiles a unit can move into.

As for forts extending cultural borders, there was a thread that told where to look, but I can't seem to find it. I'll look around some more and see if I can find it. :)
 
Brilliant, thanks for that.

Goodness, the C++ source is rather daunting :)
 
Right, after fiddling for a bit, I've added this onto the end of my cvunit->canmoveinto code:

Code:
	// if currently adjacent to a fort that isn't mine
	int aX = getX();
	int aY = getY();
	bool aBlocked = false;
		

	for (int i=-1;i<1;i++)
	{
		for (int j=-1;j<1;j++)
		{
			if (i != 0 && j != 0)
			{
				CvPlot* samplePlot = GC.getMap().plot(aX + i, aY + j);

				if (samplePlot->getImprovementType() == GC.getInfoTypeForString("IMPROVEMENT_FORT") ||
					samplePlot->getImprovementType() == GC.getInfoTypeForString("IMPROVEMENT_FORTRESS"))
				{
					if (samplePlot->getOwnerINLINE() != getOwnerINLINE())
					{
						aBlocked = true;
						break;
					}
				}
			}
		}
	}

	if (aBlocked)
	{
		int bX = pPlot->getX();
		int bY = pPlot->getY();
		bool bBlocked = false;

		for (int i=-1;i<1;i++)
		{
			for (int j=-1;j<1;j++)
			{
				if (i != 0 && j != 0)
				{
					CvPlot* samplePlot = GC.getMap().plot(bX + i, bY + j);
					if (samplePlot->getImprovementType() == GC.getInfoTypeForString("IMPROVEMENT_FORT") ||
						samplePlot->getImprovementType() == GC.getInfoTypeForString("IMPROVEMENT_FORTRESS"))
					{
						if (samplePlot->getOwnerINLINE() != getOwnerINLINE())
						{
							bBlocked = true;
							break;
						}
					}
				}
			}
		}


		// if target plot is also adjacent to a fort that isn't mine
		if (bBlocked)
		{
			return false;
		}
	}

However, it doesn't seem to work. All I'm trying to do is to check to see whether there is a fort (or fortress, my own custom type) adjacent to either the plot the unit is moving from or that the unit is trying to move to. However, having tested it, it doesn't work. I expect that I'm doing something really stupid and obvious, but can't spot it. Also, there doesn't seem to be any easy way to send debug messages to the in-game console. Does anyone have any ideas?

Thanks a lot.
 
I hate the canMoveInto function. I have fought with it so many times for so many hours on several different mods. I wish you good luck with this.

I am having some progress on the culture border extending side of it. I have the SDK set up with new improvementinfo tag that gives improvements a range and I have them extending borders over that range, but I am currently working on how I will remove the borders when the improvement is destroyed.

When you get the movement figured out I will definetly be adding that to my mod. :)
 
Hey, just took a look at your posted code and think I see a problem.

Here is the the code I use to loop through surronding plots and it works in all the places I use it.

Code:
                    int iRange = 1
                    int iStartX = plot()->getX_INLINE() - iRange;
                    int iStopX = plot()->getX_INLINE() + iRange + 1;
                    int iStartY = plot()->getY_INLINE() - iRange;
                    int iStopY = plot()->getY_INLINE() + iRange + 1;
                    for (int iIX = iStartX; iIX < iStopX; iIX++)
                    {
                        for (int iIY = iStartY; iIY < iStopY; iIY++)
                        {
                            CvPlot* pLoopPlot = GC.getMap().plot(iIX, iIY);

                            if (pLoopPlot != NULL)
                            {
                                code to do goes here
                            }
                        }
                    }

Note the + 1 to iStopX and iStopY. I don't remember why you have to do this, but it is neccessary in Civ4. Don't know if this will make it work for you, but it is one thing. :)
 
Note the + 1 to iStopX and iStopY. I don't remember why you have to do this, but it is neccessary in Civ4. Don't know if this will make it work for you, but it is one thing. :)

Because of this bit: 'iIX < iStopX'

So adding 1 to iStopX is like using this instead: 'iIX <= iStopX'

Hope that makes sense :)
 
Yep, that did it. The final thing that I realized needed doing is that you need an additional exception for if you are trying to move into a tile with a fort in it - obviously you should always be able to do this, or one could just build a string of forts next to each other and the overlapping ZoCs would stop enemy units being able to move into any of them.

Here is the final code, which is at the bottom of canmoveinto (just before the final "return true"), for the benefit of anyone else trying this in vanilla:

Code:
	if (pPlot->getImprovementType() != GC.getInfoTypeForString("IMPROVEMENT_FORT") &&
		pPlot->getImprovementType() != GC.getInfoTypeForString("IMPROVEMENT_FORTRESS") &&
		pPlot->getImprovementType() != GC.getInfoTypeForString("IMPROVEMENT_HILL_FORT")
		)
	{
		int iRange = 1;
		int iStartX = plot()->getX_INLINE() - iRange;
		int iStopX = plot()->getX_INLINE() + iRange + 1;
		int iStartY = plot()->getY_INLINE() - iRange;
		int iStopY = plot()->getY_INLINE() + iRange + 1;
		bool aBlocked = false;
		for (int iIX = iStartX; iIX < iStopX; iIX++)
		{
			for (int iIY = iStartY; iIY < iStopY; iIY++)
			{
				if (iIY != 0 && iIX != 0)
				{
					CvPlot* pLoopPlot = GC.getMap().plot(iIX, iIY);

					if (pLoopPlot != NULL)
					{
						if (pLoopPlot->getImprovementType() == GC.getInfoTypeForString("IMPROVEMENT_FORT") ||
							pLoopPlot->getImprovementType() == GC.getInfoTypeForString("IMPROVEMENT_FORTRESS"))
						{
							if (pLoopPlot->getOwnerINLINE() != getOwnerINLINE())
							{
								aBlocked = true;
								break;
							}
						}
					}
				}
			}
		}

		bool bBlocked = false;
		if (aBlocked)
		{

			iRange = 1;
			iStartX = pPlot->getX_INLINE() - iRange;
			iStopX = pPlot->getX_INLINE() + iRange + 1;
			iStartY = pPlot->getY_INLINE() - iRange;
			iStopY = pPlot->getY_INLINE() + iRange + 1;
			for (int iIX = iStartX; iIX < iStopX; iIX++)
			{
				for (int iIY = iStartY; iIY < iStopY; iIY++)
				{
					if (iIY != 0 && iIX != 0)
					{
						CvPlot* pLoopPlot = GC.getMap().plot(iIX, iIY);

						if (pLoopPlot != NULL)
						{
							if (pLoopPlot->getImprovementType() == GC.getInfoTypeForString("IMPROVEMENT_FORT") ||
								pLoopPlot->getImprovementType() == GC.getInfoTypeForString("IMPROVEMENT_FORTRESS"))
							{
								if (pLoopPlot->getOwnerINLINE() != getOwnerINLINE())
								{
									bBlocked = true;
									break;
								}
							}
						}
					}
				}
			}

			// if target plot is also adjacent to a fort that isn't mine
			if (bBlocked)
			{
				return false;
			}
		}
	}

I should add that the references to IMPROVEMENT_HILL_FORT and IMPROVEMENT_FORTRESS are extras for my mod. Most people can remove them.
 
If anyone is interested, I have finished my SDK mod that allows Improvements to spread Culture Points and Culture Borders.

Here is the Mod's Thread.
 
Top Bottom