Need help with Forts/Improvements giving Culture

Civilicious

Warlord
Joined
Mar 14, 2005
Messages
109
Location
United States of Canada
What I am trying to accomplish is the following:

I have the XML set up to allow fort and other improvements outside of borders, but what I want to happen is this. When the fort or improvment is created, the builder becomes the owner of the tile (just the tile itself, no other spaces), if it had no previous owner. When an improvement is destroyed the culture should be lost as well.

This would include whales and fish out in the open ocean often times out of reach of city borders and would allow you to gain access to this resource. Also using forts and improvements you could access various resources in a type of colonial scenario without building cities to access everything.

I found this component http://forums.civfanatics.com/showthread.php?t=243427 that generates culture around a fort when it is built but also spawns a commander and has some other functionality I am not looking for.

Does anyone have an idea of how this may easily be done? Or can give me any pointers on how to start going about it? I got the idea that I would set up workers like the WORKBOAT and have the selection button cause the unit to destruct and create the improvment. So I planned to add something in to have it set tile ownership at the same time it does this, however from looking through all the files I cannot find where the improvment is created. Any input would be appreciated.
 
This sounds like it would require changes in the SDK. But I am a Python-phobe, so could be wrong. :)

Class CvPlot defines methods called setCulture and changeCulture. If you were to call either of these methods when the improvement is first created you could set the culture on the tile for the Civ that built the improvement.

This wouldn't cause the tile to "emit" culture every turn the way a city does though. Neighboring cities could out-culture the tile and take it (unless you set the culture to some high value, which is pretty abuseable.)

Isau
 
This sounds like it would require changes in the SDK. But I am a Python-phobe, so could be wrong. :)

Class CvPlot defines methods called setCulture and changeCulture. If you were to call either of these methods when the improvement is first created you could set the culture on the tile for the Civ that built the improvement.

This wouldn't cause the tile to "emit" culture every turn the way a city does though. Neighboring cities could out-culture the tile and take it (unless you set the culture to some high value, which is pretty abuseable.)

Isau

I imagine that I can figure out how to set the tile culture using one of the ways you described, the problem is I cannot find the exact spot in the files/python where the improvment is created, either for build actions which take a number of turns, or for the instantaneous ones like the workboat.

And I don't want the tile emitting culture, if someone builds up a nearby area and culture displaces the original builder off the fort or improvement that is ok for my purposes.
 
Got your pm, internet is lagging so it is easyer to respond here.

If your making your mod in BtS then what you are wanting to do will be pretty easy. However, if your wanting to do this in Warlords or vanilla Civ4 it will take alot more work.

In BtS find CvEventManager.py and find the methods onImprovementBuilt. It will allow you to run code whenever an improvement is built. Then to add cultureal border to a plot use pPlot.setOwner(iPlayer). The cultural borders are redrawn every game turn so you will have to reaply the pPlot.setOwner() each turn for all the improvements. To do that try the onGameTurn method in the CvEventManager.py file.

The reason my fort mod adds the commander unit is the same reason Final Frontier made their Starbases a Unit instead of an improvement. It seems the setOwner method has some funky behavior and it doesn't seem to "stick" to the tile if the unit is not created. Don't have any idea why it works like this, but it did. I'm pretty sure it isn't nessessary to create the unit, but it was the easy fix for the weird issue. But I'm sure if you play around with it you can find a better way to make it work that suits your purposes.

Now if you are wanting to do this in pre-BtS civ, that is going to be harder and will require SDK work. I can't tell you how to do it as I don't know exactly, but I would suggest starting in CvPlot.cpp by looking for the setOwner function, I assume it was always there and just not exposed to python before BtS. If that is the case, it should take only a few lines of code to have the same functionality as offered by BtS.
 
I suggest you add an aditional m_TeamOwner variable and supporting setTeamOwner and getTeamOwner methods to the Plot class to prevent interference with the existing plotowner functions. To create culture every turn, simply add a doCulture procedure to the Plot class which effectivly should perform the same functionality as the doCultere method from the City class. Then simply add a loop plot method to the doTurn in the Game class that loops all plots which should checks if the TeamOwner isn't equal to NULL. if not NULL, execute the plot->doCulture function and you got your fort generating culture.

See, it's easy as pie.;)
 
Jeckel, Fanatic thanks for the replies. I am currently at work and so unable to test some of this stuff out but will try in the morning when I get home.

Just ran across your comments in another thread Jeckel about a guy wanting to know how to assign ownership when the improvement is built, which is a problem I will have with this as well. I understand your method, at least I understand what you did to mark a unit, even if I don't understand how to write the code. Due to my limited coding skills, I am hoping to avoid making it this complex.

What I am hoping to do, and I will try to explain this more clearly than I did above, its hard since I don't have all the coding nomenclature correct.

To get around the problem of having no reliable way to setOwner upon improvement completion, I was going to set up the improvements to consume the worker like the workboat does. This would not be ideal but considering my scenario idea, it would sort of fit in with the theme.

Anyway, I assume that when you have your Workboat on a tile and press the button to turn it into fishing boats, whaling boats, etc., that the button click itself is some sort of function that points to the makeImprovement function, so what I was going to try to do was have the button click set the culture just before making the improvement. After thinking about it, I guess the same problem arises, how will it know who to set the owner to? Also I have not yet found the file where the button functions are located.

Also the other issue is that I want a pillage action to setOwner to Null which should be easy enough to code but might end up giving me an issue if the tile pillaged is within a city radius, I don't know if it will remove culture, then regenerate the culture right away or not until the next turn. My goal is not to have culture removed from tiles in the normal city radius, just these forts/improvements on resources out in the hinterlands or on other continents.
 
Simple, add plot->setTeamOwner (pUnit->getTeam()) to Unit::Build

I tried adding this in but kept running into errors, here is the CvUnit::Build in CvUnit.cpp

// Returns true if build finished...
bool CvUnit::build(BuildTypes eBuild)
{
bool bFinished;

FAssertMsg(eBuild < GC.getNumBuildInfos(), "Invalid Build");

if (!canBuild(plot(), eBuild))
{
return false;
}

// Note: notify entity must come before changeBuildProgress - because once the unit is done building,
// that function will notify the entity to stop building.
NotifyEntity((MissionTypes)GC.getBuildInfo(eBuild).getMissionType());

bFinished = plot()->changeBuildProgress(eBuild, workRate(false), getTeam());

GET_PLAYER(getOwnerINLINE()).changeGold(-(GET_PLAYER(getOwnerINLINE()).getBuildCost(plot(), eBuild)));

finishMoves(); // needs to be at bottom because movesLeft() can affect workRate()...

if (bFinished)
{
if (GC.getBuildInfo(eBuild).isKill())
{
kill(true);
}
}

// Python Event
gDLL->getEventReporterIFace()->unitBuildImprovement(this, eBuild, bFinished);

return bFinished;
}

Fanatic if you get a chance would you please point out where exactly I should put the line?
 
Well, I got it working finally, although a skilled programmer would probably laugh at the code. Not sure if I should post it as a whole mod pack or not. It does make things a bit more interesting. Basically any time you build an improvement (road,mine,fort, etc. the tile becomes yours. There is no built up culture however and a city built nearby will quickly displace you from ownership of the tiles which is logical. You can access resources on another continent with a fort and routes to the resources, without having to build a full fledged city, which is sort of historically correct for the colonial time period. You don't get the city worked bonus obviously but you get the benefit of having the resources hooked up to your trade network.

The only area where it is still lacking is in the AI. Obviously the Ai behavior dosen't change to take advantage of this which isn't that big of a deal. But I was using it along with a change to make borders stop at the shore. Was going to give coastal cities bonuses via buildings (harbor, lighthouse, etc) to compensate for the loss of water tiles and make the coast still very desirable. Just always hated the borders going out over the water, which is ahistorical for much of the time period. The only problem is that the AI will not build on water resources at present as it dosen't see them in the city work area. Probably can be corrected via programming but probably very difficult.
 
I am just about done rewriting the AI code from Final Frontier mod that causes the AI to build improvements outside of city radiuses. I need to do some tests and tweak the decision making for where to build forts, but should have it done in a few days and it will be pretty easy to plug the new file into other mods. :)
 
Top Bottom