Vikings shouldnt get kjøbmandehavn(Copenhagen)

I'm coding this as we speak and there's currently only an option for one religion per spawned city. But I've added the city list option though (the third one from my previous post).

It could be noted that all variables starting with i are integer values, and all integer values corresponding to CivIV stuff like Civs, unit, Techs or buildings are constants. So you could just look up what index number (integer value) say a building has in Consts.py (as set by Rhye and corresponding to the WB) and use a numerical value instead.

This means you can use the number 3 in the buildings list instead of con.iWalls if you like. There's actually a reason for using variables, but both work just the same. I'd say use what works for you.

Other stuff included are a setting for forcing the city spawn. By this I mean ignoring any culture or units present on or adjacent to the city tile. I'm also looking into auto-razing cities on adjacent tiles that would otherwise block the spawn, so the Force Spawn option should be used with some afterthought!

Also, there is a setting for how much of the city owners culture will be spread throughout the tiles adjacent to the city. Its a percentile value from 0 to 100.

Anything else that could be added?
 
I'm pretty much done with this so I'll attach the files for you guys to test out. Its not any kind of final release but all the functions are there. Things may need to be tweaked and stuff could still be added (or taken away).

Firstly, the install. Unpack all the files into:
...\Sid Meier's Civilization 4\Beyond the Sword\Mods\Rhye's and Fall of Civilization\Assets\Python\
You still work inside the Barbs.py file just like before. The difference is that you now have the option of using my custom function called custom.foundCity(). All the settings or arguments go inside the parenthesis, just like before.

You begin with building a list (or two, see below) though. The list is defined at the start of the Barbs.py file (anywhere before the line "class Barbs:") and you get to name it whatever you want, preferably the letter "l" (for "list") followed by the name of the city. Lets just call it lList for the sake of argument. You define your list like this:
Code:
[COLOR="DarkOliveGreen"]lList[/COLOR] = [[COLOR="Sienna"]iXcoord[/COLOR], [COLOR="Sienna"]iYcoord[/COLOR], [COLOR="Sienna"]iGameTurn[/COLOR], [COLOR="Sienna"]iOwner[/COLOR]]
These are all integer values but they can also be variables. I've supplied two default city spawns with this install: Birka and Roskilde, both in Scandinavia. Their lists look like this:
Code:
lBirka = [63, 58, 200, -1]
lRoskilde = [60, 55, 220, con.iVikings]
Note that the list lBirka has the value -1 as the city owner, which would seem strange as this value doens't correspond to any of the Civs. (These are defined by both numerical value and variable in the Consts.py file.) This is actually a feature to this function, as the value -1 assigns a random minor Civ as the city owner. So if you can't or don't want to assign one yourself, use this option. (Pre-Nationalism there is also a 20% chance that the city will be a Barbarian one.)

lRoskilde uses the variable iVikings instead, but since this variable isn't defined in Barbs.py it must be fetched from Consts.py instead. Therefore its important not to forget the "con." (as in Consts) part! You could just as well look up the index number of the Viking Civ (11) and use that.

As a side note, my code doesn't allow any city spawns for the human player. If you play the Civ that would get the spawning city, then that city will spawn as an Independent city instead. This is a feature and not a bug, and its added by design.

It could also be noted that Rhye has defined game turns in Consts.py to variables like "i1200AD", but once again those would have to be used with the "con." prefix. Also make sure that the date is actually defined in Consts.py before calling on it! (Because not all are.)

So, on to the function itself. You add this bit anywhere after the line "def checkTurn(...):" - and before "def getCity(...):". But before you actually write any code, make sure there is exactly 16 blank spaces at the start of the line! (Otherwise your code won't be a part of the logical structure of the file and thus will not work.) The structure of the function looks like this:
custom.foundCity(lList, "City Name", iCitySize, bForceCity, iCityCulture, iPlotCulture, iCityDefender, iNumberUnits, iReligion, lBuildings)
This is the breakup of all the settings:
  • lList we already discussed above. It holds four values corresponding to the two city coordinates, the spawn date and the city owner.
  • "City Name" can be anything you wanna call the city, but it must be written inside he quotations.
  • iCitySize is a value of 1 or above.
  • bForceCity is a so called boolean and can either be set to "True" or "False" (without the quotations). This particular boolean determines if the normal limitations of city spawns apply or not. Its a very potent setting and is discussed in more detail below.
  • iCityCulture is the amount of :culture: present in the city on spawn and can be any value of 0 (zero) and above. This has an impact on both the city's cultural borders and the defensive bonus of the city.
  • iPlotCulture is another way of spreading culture around the city. Its actually the percentage of the city owners culture present on the tiles adjacent to the city. It can very well be set to over 100% (without the percentile character), and if set to 0 (zero) there will only be the default amount of culture present on the tiles. (Which is basically nothing for a newly spawned city.)
  • iCityDefender is the type of unit(s) that will spawn together with the city. This is expressed by the index number of that unit and is defined in the Consts.py file. You could use the variables set by Rhye but don't forget to fetch them with the con. prefix! If no units will be spawned set this argument to -1.
  • iNumberUnits is a numerical value corresponding to the number of defending units. If no unit type has been set in the previous setting this should also be set to -1.
  • iReligion can be used to give the city a preset religion on spawn. It's also a integer value and the values or corresponding variables can be found in Consts.py, see above. If no religion is present the default setting is -1.
  • lBuildings refers to a second, optional list that you can provide for your city spawn. This list contains the buildings that will be pre-built in the city and if no list is defined it should be set to "None" (without the quotations). The list follows this format:
    Code:
    [COLOR="DarkOliveGreen"]lBuildings[/COLOR] = [[COLOR="Sienna"]iBuilding[/COLOR], [COLOR="Sienna"]iBuilding[/COLOR], [COLOR="Sienna"]iBuilding[/COLOR], ...]
    Every instance of iBuilding would be an integer value corresponding to a index number of a building. These can be found in Consts.py and there are also variables for each building (used with con.).
The code for spawning Birka and Roskilde looks like this:
Code:
                custom.foundCity(lBirka, "Birka", 2, False, 0, 0, con.iLongbowman, 1, -1, lVikingBuildings)
                custom.foundCity(lRoskilde, "Roskilde", 2, True, 10, 50, con.iLongbowman, 1, con.iChristianity, None)
There are a number of similarities and differences between these spawns. Both are size 2 cities and come with one Longbowman unit. Note however that the Force Spawn option is enabled ("True") for Roskilde, as are both cultural values (10 :culture: in the city and 50% Viking culture present on all adjacent tiles). Also, Roskilde spawns with Christianity while Birka gets buildings instead. The actual buildings list looks like this:
Code:
lVikingBuildings = [con.iVikingTradingPost, con.iMarket]
Note that I didn't call it lBirkaBuildings as I figured I might use the same list for some more spawns later. So its quite possible for city spawns to share a list or to have generic lists with only one or a couple of buildings, like:
Code:
lWalls = [con.iWalls]
When used this list would give any city the City Walls building.

As for the limitations that can be avoided with the Force Spawn setting: If not enabled a city will never spawn on a tile owned by any Civ - even the Civ that the spawned city would belong to. Furthermore, a city will not spawn if there are units - any units - on that tile at the turn the spawn triggers. There can also be no units controlled by the human player on any adjacent tile! And finally, there can of course not be any cities on target tile - or on any adjacent tile.

But with the Force Spawn setting enabled, most of these limitations don't apply. Actually, any city belonging to a minor Civ that would be blocking the city spawn will be razed! (So a minor Civ Iverness could be razed by spawning Edinburgh on adjacent tile.) Any units present will be automatically moved outside of the city owner's cultural borders.
 

Attachments

Thank you so very much for this. I will try and make a bunch of spawns in python for 600AD (the start I usually use) instead of editing the world in WB and report back to you :)
 
Thank you so very much for this. I will try and make a bunch of spawns in python for 600AD (the start I usually use) instead of editing the world in WB and report back to you :)
I'm looking forward to hearing from you then! :D

This is in fact something that is long overdue, as the city spawns have been giving me all sorts of headaches. I'm redoing my own stuff right now and once I get all my ducks in a row I can actually look forward to going forward with my own pet project (which is a historical Russia scenario).

Next up would be units spawns then, since these are just as restricted within RFC and the Barbs.py file as are city spawns. More power to the mod-modders! :king:
 
A quick question (not about cities, but you seem to know your way around this civ editing):
I've been trying to add more resource spawns, terrain changes and improvement spawns using the resources.py file. It refers to consts.py just as your file does, however I can't figure out a few things:

- I've worked out how to add a resource at a certain gameturn, but I can't figure out how to remove a resource from a tile.
- I've worked out how to change grassland/plains to grasslandhills/plainshills but not how to change this back.
- The consts file only has IDs for huts, cottages/hamlets/village/town. If I want to spawn a winery for instance, what do I have to add to the consts file?
 
A quick question (not about cities, but you seem to know your way around this civ editing):
If you're interested to get into Python modding you could view it like I'm just a few steps ahead of you. So, in about two months you'll be anwering these questions for someone else still at the initial stumbling blocks. :D

I'll try to answer any questions to the best of my ability, but I'm really only a beginner at this also.

- I've worked out how to add a resource at a certain gameturn, but I can't figure out how to remove a resource from a tile.
I've yet to spawn resources myself (but I've done a lot of improvements though). The answers to these kinds of questions should be sought in the CivIV API where all the functions are listed. I quick look gave me no ideas as to any other function that could be used to erase existing resources, so I'd just try entering "None" (or -1) in the setBonusType() function. :confused:
- I've worked out how to change grassland/plains to grasslandhills/plainshills but not how to change this back.
Hmm... It shouldn't be any different than to change it in the first place, but if you post the code you have I could take a look.
- The consts file only has IDs for huts, cottages/hamlets/village/town. If I want to spawn a winery for instance, what do I have to add to the consts file?
AFAIK the values found in Consts.py are the same that are used in the World Builder. Rhye isn't actually assigning any values, but rather defining variables for the values already in the game. So you don't need to use any variable at all, as they only point to a value. Instead you need to figure out the value yourself.

If you use simple logic and look where in the order a Winery is compared to the rest of the improvements, you should also be able to determine its index number. Two things to remember: 1. The game always starts any count from 0 (zero) and so should you! 2. Additions to the game (Warlords, BTS) and to the World Builder wouldn't necessarily be entered into the WB interface at the end - where they belong - so you'd have to skip those when you count and only count those in at the end.

There is also another (more advanced) method of doing this, but I'll look it up and get back to you. It's a real life saver in any case...
 
Ok, the way you could get the ID number of a certain game element is to use the getInfoTypeForString() function. A "string" is a series of letters or characters within quotations, just like the cityname in the foundCity() function(s). In this case you feed the function the string that identifies a element in the game, as it is defined in the XML files. What you get is the integer value for that element.

So, the string for identifying a Winery is "IMPROVEMENT_WINERY", so you stuff this function with this string inside the function you wanna use. In your case it would look like this:
Code:
gc.getMap().plot(iX, iY).setImprovementType(gc.getInfoTypeForString("IMPROVEMENT_WINERY"))
This way you'd never ever need to use the variables set in Consts.py for the stuff already in the game. You just fetch them yourself whenever you need them.

If this seems complex, you could always assign your own variables, as they only apply inside the file (or function) you are using them. So, your code could also look like this:
Code:
iWinery = gc.getInfoTypeForString("IMPROVEMENT_WINERY")
gc.getMap().plot(iX, iY).setImprovementType(iWinery)
Clever, eh? :goodjob: Note that you never actually need to know the value for a Winery, its sufficient that the code knows it!

If you're gonna use the ID in question more than once you might as well define a variable and use that instead. That's what they are for!
 
- I've worked out how to add a resource at a certain gameturn, but I can't figure out how to remove a resource from a tile.
Here's something else I found in the API; a function called erase(). As far as I can tell you just use it like any other function in the CyPlot group.
Code:
gc.getMap().plot(iX, iY).erase()
I haven't tried any of this myself and I'm not sure what this particular function will erase. :p

It should be interesting though, so don't forget to tell me what happened! :mischief:
 
So far, I have this:

Code:
		if (iGameTurn == con.i600AD):
			gc.getMap().plot(54, 39).isHills(1) #Algiers
			gc.getMap().plot(55, 39).isHills(0) #Algiers	
			gc.getMap().plot(106, 11).setBonusType(iFish) #Perth
			gc.getMap().plot(64, 38).setBonusType(iClam) #Banghazi
			gc.getMap().plot(99, 30).setBonusType(iClam) #Singapore
			gc.getMap().plot(56, 41).setBonusType(iClam) #Algiers
			gc.getMap().plot(54, 39).setBonusType(iWheat) #Algiers
			gc.getMap().plot(54, 37).setBonusType(iHorse) #Algiers
			gc.getMap().plot(51, 59).setBonusType(iCow) #Edinburgh
			gc.getMap().plot(27, 19).setBonusType(iWhale) #Arequipa
			gc.getMap().plot(24, 22).setBonusType(iWhale) #Lima
			gc.getMap().plot(123, 6).setBonusType(iWhale) #Wellington
			gc.getMap().plot(107, 11).setBonusType(-1) #Perth
			gc.getMap().plot(64, 39).setBonusType(-1) #Banghazi
			gc.getMap().plot(57, 42).setBonusType(-1) #Tunis
			gc.getMap().plot(99, 32).setBonusType(-1) #Singapore
			gc.getMap().plot(55, 39).setBonusType(-1) #Algiers
			gc.getMap().plot(53, 37).setBonusType(-1) #Algiers
			gc.getMap().plot(52, 59).setBonusType(-1) #Edinburgh
			gc.getMap().plot(26, 19).setBonusType(-1) #Arequipa
			gc.getMap().plot(23, 22).setBonusType(-1) #Lima
			gc.getMap().plot(123, 5).setBonusType(-1) #Wellington

The new resources appear, but the old ones don't disappear (I am trying to move the resources one tile in a certain direction, so that the AI uses them instead of just leaving them in some sort of no mans land. In other cases, I am moving the resources so that certain cities (such as Edinburgh) don't end up on top of a resource.

In the case of Algiers, I intend to make it spawn where the wheat resource currently exists. I wanted to:
- Make the wheat move one tile West
- Move the hills one tile West so that the wheat is on plains and the city of Algiers will be on the hill

The only thing that happens with the code I have input is that the new resources are created, but nothing else. I can't even get the terrain to change, even though I thought I could with "setTerrainType" :(
I have since looked at the API and in the "cyplot" section there is the "isHills()" boolean that I thought I'd try, but my syntax must be wrong.

Also fixed is the whale resource. Turns out in consts.py it is spelt "whales" :D
 
Ok, you need to back up one step here. If you wanna edit the starting setup for the AD600 scenario, then you need to work with the WB save instead. There's no reason to edit anything in Python! This is true both for terrain and bonuses, as for cities and units.

If you, on the other hand, wanna spawn stuff after that point "dynamically" - these would be actual "spawns" - then you use Python to edit the map.

You can find what you need for editing the WB save in here.

The way I managed my very extensive editing of the WB file was via the World Builder, then I saved my changes as a separate scenario, and finally used a application (WinMerge) to go through all my changes one by one and implemented the ones I needed to keep. (I couldn't just have it auto-replace everything since I messed around with Swamps - and Rhye actually made somewhat of a mess of creating those...)

I use Python (Barbs.py and Resources.py) to spawn cities, units and improvements (mostly Towns) on historical dates. This way I have been able to make a "historical scenario" out of the framework supplied by Rhye. But my AD600 WB savefile scenario is also modified.
 
So, heres your "Perth" tile from the WB save:
Code:
BeginPlot
	x=107,y=11
[COLOR="Red"]	BonusType=BONUS_FISH[/COLOR]
	TerrainType=TERRAIN_COAST
	PlotType=3
EndPlot
In order to get rid of the Fish resource you simply delete (or better yet, cut) the line marked with red.

This is what the tile you wanna move that resource to looks like by default.
Code:
BeginPlot
	x=106,y=11
	TerrainType=TERRAIN_COAST
	PlotType=3
EndPlot
Simply put (I'd suggest cut'n'paste) that same line anywhere in there between "BeginPlot" and "EndPlot". Something like this:
Code:
BeginPlot
	x=106,y=11
[COLOR="Red"]	BonusType=BONUS_FISH[/COLOR]
	TerrainType=TERRAIN_COAST
	PlotType=3
EndPlot

Mission accomplished! :goodjob:

This is easier to do in World Builder, and you could just save your changes as a scenario. When you do this however, make sure you start as the Chinese (so that no cities have yet been founded) - and make sure you delete all the units for the Chinese, the Japanese, the Arabs and the Vikings. (Otherwise they will spawn yet another load of units when you start up your scenario.)

Note that the scenario file uses Tabs - and not blank spaces - for indentation.
 
I have since looked at the API and in the "cyplot" section there is the "isHills()" boolean that I thought I'd try, but my syntax must be wrong.
When you use the API you need to differentiate between those functions that are flagged "VOID" and those that are not. You can only change stuff in the game with functions that are "VOID".

The isHills() function is a boolean (flagged BOOL) and can thus not be used to change tiles into hills. It is used to check whether or not a tile has hills - or "isHills". Like:
Code:
if (pTile.[B]isHills()[/B]):
or
Code:
if (not pTile.[B]isHills()[/B]):
Most of the time the VOID functions are called something with "set" - and not "get" or "is".
 
Thank you again. I have managed to make all my changes by editing the WB file in a text editor instead of using WB ingame, with good results :)

I haven't tested all the late game changes yet, so I'll get back to you on those later :)

These lines didn't work as intended:

Code:
iPasture = gc.getInfoTypeForString("IMPROVEMENT_PASTURE")
iPlantation = gc.getInfoTypeForString("IMPROVEMENT_PLANTATION")
iWinery = gc.getInfoTypeForString("IMPROVEMENT_WINERY")
iFort = gc.getInfoTypeForString("IMPROVEMENT_FORT")

                if (iGameTurn == con.i1250AD):
                        gc.getMap().plot(68, 39).setImprovementType(iWinery) #Cyprus
                        gc.getMap().plot(58, 43).setImprovementType(iPasture) #Corsica

                if (iGameTurn == con.i1800AD):
                        gc.getMap().plot(27, 36).setImprovementType(iPlantation) #Jamaica
                        gc.getMap().plot(32, 37).setImprovementType(iPlantation) #Puerto Rico

                if (iGameTurn == con.i1850AD):
                        gc.getMap().plot(71, 36).setImprovementType(iFort) #Suez

These edits were because the AI never improves resources that are locked on islands (you can guess which ones I mean from the comments). The improvements don't appear as you said they would, however. Is it because the tiles are in a Civ's culture area, or have I forgotten to define something?
 
Ah, if this is what your actual code looks like, then the problem is indentations, the usual suspect when it comes to Python. The problem is twofold: First of all constants (variables with values that doens't change, or non-variable variables :crazyeye:) should be defined at the beginning of the .py file. That is before any function definitions - and those begin with the "class" command ("class Resources:" in this case). Like this:
Code:
# initialise bonuses variables

iHorse = con.iHorse
iBanana = con.iBanana
iCorn = con.iCorn
iCow = con.iCow
iPig = con.iPig
iSheep = con.iSheep
iWheat = con.iWheat
iSugar = con.iSugar
iWine = con.iWine
iCotton = con.iCotton
iDye = con.iDye
iRice = con.iRice

iVillage = con.iVillage
iTown = con.iTown
     
iPasture = gc.getInfoTypeForString("IMPROVEMENT_PASTURE")
iPlantation = gc.getInfoTypeForString("IMPROVEMENT_PLANTATION")
iWinery = gc.getInfoTypeForString("IMPROVEMENT_WINERY")
iFort = gc.getInfoTypeForString("IMPROVEMENT_FORT")
The reason your code isn't reading the variables where they are now is that you have no blankspace's at the beginning of the lines defining the variables. The problem would be that they appear after the "def checkTurn(...):" line - and anything after that needs to have one level of indentation more than the definition itself! So, the "if" clauses and the setImprovementType() functions are working thanks to the indentation (16 and 24 blankspace's respectively).

(I set the turn dates to 181 as in the first turn in the AD600 scenario and they all seem to work fine. The Suez Canal was a very nice idea, by the way! :goodjob:)
 
Hmm I don't understand. In my file the identations seem correct. Let me post the entire file, that was just my extract of the lines that didn't work in particular:

Code:
# Rhye's and Fall of Civilization - Dynamic resources

from CvPythonExtensions import *
import CvUtil
import PyHelpers  
import Popup
import Consts as con

# globals
gc = CyGlobalContext()
PyPlayer = PyHelpers.PyPlayer

### Constants ###


# initialise bonuses variables

iHorse = con.iHorse
iBanana = con.iBanana
iCorn = con.iCorn
iCow = con.iCow
iPig = con.iPig
iSheep = con.iSheep
iWheat = con.iWheat
iSugar = con.iSugar
iWine = con.iWine
iCotton = con.iCotton
iDye = con.iDye
iRice = con.iRice
iFish = con.iFish
iClam = con.iClam
iWhales = con.iWhales
iForest = con.iForest
iFloodPlains = con.iFloodPlains

[COLOR="Red"]iPasture = gc.getInfoTypeForString("IMPROVEMENT_PASTURE")
iPlantation = gc.getInfoTypeForString("IMPROVEMENT_PLANTATION")
iWinery = gc.getInfoTypeForString("IMPROVEMENT_WINERY")
iFort = gc.getInfoTypeForString("IMPROVEMENT_FORT")[/COLOR]
     

class Resources:
       	
        def checkTurn(self, iGameTurn):


                if (iGameTurn == 5): #otherwise it's picked by Portugal at the beginning
                        gc.getMap().plot(49, 43).setImprovementType(con.iHut)


                if (iGameTurn == con.i450AD): #(dye added later to prevent Carthaginian UHV exploit)
                        gc.getMap().plot(53, 51).setBonusType(iDye) #France
                        gc.getMap().plot(53, 55).setBonusType(iDye) #England
                if (not gc.getPlayer(0).isPlayable()): #late start condition
                        if (iGameTurn == con.i600AD): 
                                gc.getMap().plot(53, 51).setBonusType(iDye) #France
                                gc.getMap().plot(53, 55).setBonusType(iDye) #England
			
                if (iGameTurn == con.i1100AD):
                        gc.getMap().plot(71, 30).setBonusType(iSugar) #Egypt
                        gc.getMap().plot(72, 24).setBonusType(iSugar) #East Africa
                        gc.getMap().plot(70, 17).setBonusType(iSugar) #Zimbabwe
                        gc.getMap().plot(68, 11).setBonusType(iSugar) #South Africa

                        gc.getMap().plot(66, 23).setBonusType(iBanana) #Central Africa
                        gc.getMap().plot(67, 21).setBonusType(iBanana) #Central Africa

                if (iGameTurn == con.i1250AD):
                        gc.getMap().plot(57, 52).setBonusType(iWheat) #Amsterdam

[COLOR="#ff0000"]                        gc.getMap().plot(68, 39).setImprovementType(iWinery) #Cyprus
                        gc.getMap().plot(58, 43).setImprovementType(iPasture) #Corsica[/COLOR]
                        
                if (iGameTurn == con.i1600AD):
                        gc.getMap().plot(28, 46).setBonusType(iCow) #Washington area
                        gc.getMap().plot(30, 49).setBonusType(iCow) #New York area
                        gc.getMap().plot(25, 49).setBonusType(iCow) #Lakes
                        gc.getMap().plot(24, 43).setBonusType(iCow) #Jacksonville area
                        gc.getMap().plot(18, 46).setBonusType(iCow) #Colorado 
                        gc.getMap().plot(11, 47).setBonusType(iCow) #California
                        gc.getMap().plot(20, 45).setBonusType(iCow) #Texas
                        gc.getMap().plot(37, 14).setBonusType(iCow) #Argentina
                        gc.getMap().plot(33, 11).setBonusType(iCow) #Argentina
                        gc.getMap().plot(35, 10).setBonusType(iCow) #Pampas

                        gc.getMap().plot(24, 43).setBonusType(iCotton) #near Florida
                        gc.getMap().plot(23, 45).setBonusType(iCotton) #Louisiana
                        gc.getMap().plot(22, 44).setBonusType(iCotton) #Louisiana
                        
                        gc.getMap().plot(22, 49).setBonusType(iPig) #Lakes
                        
                        gc.getMap().plot(21, 50).setBonusType(iWheat) #Canadian border
                        gc.getMap().plot(19, 48).setBonusType(iWheat) #Midwest

                        gc.getMap().plot(22, 33).setBonusType(iBanana) #Guatemala
                        gc.getMap().plot(27, 31).setBonusType(iBanana) #Colombia
                        gc.getMap().plot(43, 23).setBonusType(iBanana) #Brazil
                        gc.getMap().plot(39, 26).setBonusType(iBanana) #Brazil

                        gc.getMap().plot(49, 44).setBonusType(iCorn) #Galicia
                        gc.getMap().plot(54, 48).setBonusType(iCorn) #France
                        gc.getMap().plot(67, 47).setBonusType(iCorn) #Romania

                        gc.getMap().plot(106, 50).setBonusType(iCorn) #Manchuria

                        gc.getMap().plot(58, 26).setFeatureType(iForest,1) #Lagos
                        gc.getMap().plot(59, 26).setFeatureType(iForest,1) #Port Harcourt
                        gc.getMap().plot(85, 37).setFeatureType(iFloodPlains,0) #Karachi
                        gc.getMap().plot(85, 38).setFeatureType(iFloodPlains,0) #Central Pakistan
                        gc.getMap().plot(86, 36).setFeatureType(iForest,1) #Gujarat
                        gc.getMap().plot(93, 29).setFeatureType(iForest,1) #Colombo
                        gc.getMap().plot(105, 29).setFeatureType(iForest,1) #Bandar Seri Begawan
                        gc.getMap().plot(109, 33).setFeatureType(iForest,1) #Manila

                        gc.getMap().plot(59, 24).setBonusType(iFish) #Port Harcourt
                        gc.getMap().plot(86, 35).setBonusType(iFish) #Gujarat
                        gc.getMap().plot(87, 36).setBonusType(iClam) #Mumbai
                        gc.getMap().plot(104, 29).setBonusType(iFish) #Bandar Seri Begawan
                        gc.getMap().plot(110, 33).setBonusType(iFish) #Manila

                        gc.getMap().plot(94, 29).setBonusType(iFish) #Colombo
                       

                if (iGameTurn == con.i1700AD):
                        gc.getMap().plot(26, 45).setBonusType(iHorse) #Washington area                        
                        gc.getMap().plot(21, 48).setBonusType(iHorse) #Midwest
                        gc.getMap().plot(19, 45).setBonusType(iHorse) #Texas
                        gc.getMap().plot(40, 25).setBonusType(iHorse) #Brazil
                        gc.getMap().plot(33, 10).setBonusType(iHorse) #Buenos Aires area
                        gc.getMap().plot(32, 8).setBonusType(iHorse) #Pampas

                        gc.getMap().plot(27, 36).setBonusType(iSugar) #Caribbean
                        gc.getMap().plot(39, 25).setBonusType(iSugar) #Brazil
                        gc.getMap().plot(37, 20).setBonusType(iSugar) #inner Brazil

                        gc.getMap().plot(104, 52).setBonusType(iCorn) #Manchuria

                if (iGameTurn == con.i1800AD):
[COLOR="#ff0000"]                        gc.getMap().plot(27, 36).setImprovementType(iPlantation) #Jamaica
                        gc.getMap().plot(32, 37).setImprovementType(iPlantation) #Puerto Rico[/COLOR]

                if (iGameTurn == con.i1850AD):
                        gc.getMap().plot(12, 45).setBonusType(iWine) #California
                        gc.getMap().plot(31, 10).setBonusType(iWine) #Andes

                        gc.getMap().plot(114, 11).setBonusType(iSheep) #Australia
                        gc.getMap().plot(116, 13).setBonusType(iSheep) #Australia
                        gc.getMap().plot(121, 6).setBonusType(iSheep) #New Zealand

                        gc.getMap().plot(19, 41).setBonusType(iHorse) #Mexico

                        gc.getMap().plot(58, 47).setBonusType(iRice) #Vercelli
                        gc.getMap().plot(12, 49).setBonusType(iRice) #California

[COLOR="#ff0000"]                        gc.getMap().plot(71, 36).setImprovementType(iFort) #Suez[/COLOR]


                
                #setImprovementType(ImprovementType eNewValue)
                #setPlotType(PlotType eNewValue, BOOL bRecalculate, BOOL bRebuildGraphics)
                #setTerrainType(TerrainType eNewValue, BOOL bRecalculate, BOOL bRebuildGraphics)
 
As far as I can tell your code checks out. (I tried it as I believe I already said. Try and change the dates for these to "181" and they should work alright on the first game turn. That way you now its not your actual code.) At least as far as for Resources.py - the problem is most likely in another .py file you've edited. My best guess would be Barbs.py - right? ;)

What happens is that when the game encounters illogical code all the Python breaks down as it will start producing error messages instead. But since you probably haven't enabled debugging yet you wouldn't know about his. Here's a guide.

I could debug this one for you though, if you attach all the files you have edited (zip compress them into one attachable file). What ever the reason it shouldn't be impossible to hunt this bug down.

But if you're serious about learning this stuff you should know how to debug. :king:
 
Ok, it turns out I was wrong on this one. I actually tried you code and now, for some inexplicable reason, I can't get those improvements to spawn either. I did get it to work again by doing this:

Use the getInfoTypeForString() function inside the setImprovementType() function as I suggested originally, and it should work. For whatever reason the index value of the improvement can't be stored in a variable at this point. Why this is I don't know, but I've seen examples of this kind method being used in other RFC code also, so I guess Rhye also get these issues from time to time...
Code:
gc.getMap().plot(71, 36).setImprovementType(gc.getInfoTypeForString("IMPROVEMENT_FORT")) #Suez
As you probably can see, there's a lot to learn when it comes to Python...

edit: And now it works with the variables, again, all of a sudden. :crazyeye: Perhaps these variables shouldn't be defined in the "constants" section at the start of the file, but rather at the beginning of function itself (after the "def checkGameTurn(...)" line but before any "if" clause that would use actually use them).
 
Perhaps these variables shouldn't be defined in the "constants" section at the start of the file, but rather at the beginning of function itself (after the "def checkGameTurn(...)" line but before any "if" clause that would use actually use them).
Yeah, this seems to be it. So constants defined at the start of a .py file shouldn't be defined with functions, then. I guess you learn something new every day...

Your code should look like this:
Code:
class Resources:
       	
        def checkTurn(self, iGameTurn):

                iPasture = gc.getInfoTypeForString("IMPROVEMENT_PASTURE")
                iPlantation = gc.getInfoTypeForString("IMPROVEMENT_PLANTATION")
                iWinery = gc.getInfoTypeForString("IMPROVEMENT_WINERY")
                iFort = gc.getInfoTypeForString("IMPROVEMENT_FORT")
edit: I actually think I figured this one out. When initializing the game, the Python is loaded before the XML, and since the strings would be actual XML, the variables get set to nothing at all. Because, the variables at the beginning of the file are only loaded once. I got it to work after I reloaded the Python files after the XML had already been loaded. The setup above should work though?
 
I found this in the API:
Spoiler :
Code:
  -1 = NO_IMPROVEMENT
  0 = IMPROVEMENT_LAND_WORKED
  1 = IMPROVEMENT_WATER_WORKED
  2 = IMPROVEMENT_CITY_RUINS
  3 = IMPROVEMENT_GOODY_HUT
  4 = IMPROVEMENT_FARM
  5 = IMPROVEMENT_FISHING_BOATS
  6 = IMPROVEMENT_WHALING_BOATS
  7 = IMPROVEMENT_MINE
  8 = IMPROVEMENT_WORKSHOP
  9 = IMPROVEMENT_LUMBERMILL
 10 = IMPROVEMENT_WINDMILL
 11 = IMPROVEMENT_WATERMILL
 12 = IMPROVEMENT_PLANTATION
 13 = IMPROVEMENT_QUARRY
 14 = IMPROVEMENT_PASTURE
 15 = IMPROVEMENT_CAMP
 16 = IMPROVEMENT_WELL
 17 = IMPROVEMENT_OFFSHORE_PLATFORM
 18 = IMPROVEMENT_WINERY
 19 = IMPROVEMENT_COTTAGE
 20 = IMPROVEMENT_HAMLET
 21 = IMPROVEMENT_VILLAGE
 22 = IMPROVEMENT_TOWN
 23 = IMPROVEMENT_FORT
 24 = IMPROVEMENT_FOREST_PRESERVE
So there really is no reason to even use the getInfoTypeForString() function - or even any variables! Just type the index number directly into setImprovementType() :D

getInfoTypeForString() would still be useful for fetching the ID of anything Rhye might has added to the game and not defined in Consts.py.
 
Thank you so, so much. I could post a quick list of changes I am trying out and testing if you want :)

In the meantime I've run into yet another problem. I wanted to change the starting unit for some of the 600AD start civs (mainly Arabia, Japan and China). The reason for this is the fact that I am already allocating them some free cities so that they settle more intelligently, however giving them settlers as well would just make them settle useless spots in the first few turns.
I reduced the starting settlers to:
China: 2
Arabia: 1
Japan: 1
Vikings: 1
However now when I start the game no units appear, and I have been defeated :(

I edited Riseandfall.py, however having restored my original copy of riseandfall.py the problem persists. Clearly it is something else I have done, but other than dynamic resources and city spawning, I haven't made any changes... what could stop civs from spawning?
 
Back
Top Bottom