View Full Version : Snaitf's Upgradable Buildings Demo


Snaitf
Dec 07, 2005, 02:50 PM
Although this can be played as a stand-alone mod, it's really meant to be a reference for modders looking for this functionality to their mods.

2 new buildings, Barracks II and Barracks III

Barracks II [+5 exp] requires Barracks, and when Barracks II is built, Barracks is removed from city

Barracks III [+6 exp] requires Barracks II, and when Barracks III is built, Barracks II is removed from city

XML changes are enclosed between

<!-- Start Modification Block -->
...
<!-- End Modification Block -->

and Python changes enclosed between

## Start Modification Block ##
...
## End Modification Block ##

This was requested, so I'm hoping more people will find it helpfull...

Snaitf
Dec 07, 2005, 03:03 PM
Oops, just found a bug, after building Barracks II, you can go back and build Barracks again, I'm gonna see if I can fix that...

Rufus T. Firefly
Dec 07, 2005, 04:28 PM
Interesting... something like the old barracks on Civ1

Fireb
Dec 07, 2005, 04:42 PM
Hmm...might be nice to upgrate temples into bigger temples :)

Roetghoer
Dec 07, 2005, 05:01 PM
I would like to get you (and Rufus as well because of his extensive activities on this forum) acquainted with the 'Modswitcher' by TDB ( http://forums.civfanatics.com/showthread.php?t=140188 ) This little prog, currently still in an immature form, will allow a large audience to combine different mods together without the hassle of modding the scripts by hand!

I think TDB could use either a little help or at least some encouragement for his activities, because this prog feels like the missing link in the current game to me.

Eventually, I hope we can come to some kind of standardized modding using a program like TDB's which would greatly anhance playability of mods on the game.

BTW i posted this here because Snaitf explicitely mentions the reference usage of his mod, which i like btw. I would like to see some different names for the Barracks II etc though, but i guess this kind of modding is easy for anyone(?)

KR R.

Mylon
Dec 07, 2005, 05:14 PM
I think it would be simpler to merely have a Barracks II and Barracks III buildings that each added +1 exp respectively. II requiring a Barracks and III requiring a II. This also prevents the user from building another Barracks.

Snaitf
Dec 07, 2005, 05:49 PM
I think it would be simpler to merely have a Barracks II and Barracks III buildings that each added +1 exp respectively. II requiring a Barracks and III requiring a II. This also prevents the user from building another Barracks.


I agree, this would be easier, but the original request specifically asked for a building that replaces the original, not just another building. And I just wanted to see if I could do it ;) But I'm stuck and can't figure out how to dis-allow the building of the original one again, any suggestions? :confused:

Snaitf
Dec 07, 2005, 05:53 PM
BTW i posted this here because Snaitf explicitely mentions the reference usage of his mod, which i like btw. I would like to see some different names for the Barracks II etc though, but i guess this kind of modding is easy for anyone(?)KR R.

Thanks, and yea, the I just chose those names quickly as this was mainly for instructional use, maybes something like "Upgrade Barracks (II)" or something, to give it the feel that the production is going towards actually adding-on to original building as opposed to just felling like your producting a seperate building...

maxpublic
Dec 07, 2005, 06:28 PM
I agree, this would be easier, but the original request specifically asked for a building that replaces the original, not just another building.

Yeah, this 'solution' had already occurred to me, but in the scenario I'm creating there are between 3 and 5 versions of every building type, along with a 7th era uber-building in that line.

Imagine having 5 barracks buildings on your building list. Now add five warehouse (granaries) buildings. Now add 5 different versions of the justice system (courthouse). Add to that...starting to get the picture? It becomes a cluttered mess for the player. And I don't even know if the game will insist on drawing all 5 barracks/warehouses/whatever on the map itself....

The problem with being able to build lower-end barracks and stacking them in the city didn't occur to me. I can, however, see a somewhat sloppy way to fix it: add in all instances of that building type to the 'remove' command in the code. Like this:


if (gc.getBuildingInfo(iBuildingType).getType() == "BUILDING_BARRACKS_III"):
for i in range(gc.getNumBuildingInfos()):
if (gc.getBuildingInfo(i).getType() == "BUILDING_BARRACKS"):
pCity.setHasRealBuilding(i, False)
if (gc.getBuildingInfo(i).getType() == "BUILDING_BARRACKS_II"):
pCity.setHasRealBuilding(i, False)



And so on. If you build a lower-end barracks while you have an upper-end barracks in the city, you'll destroy the upper-end barracks. I'm not sure what the if/elsif/else structure is like in Python, so forgive the crude example.

My only concern is that the AI may think it appropriate to replace a Barracks V with a Barracks II - again, and again, and again.

The best solution would be one that obsoletes all lower-class buildings in that city unless the higher-class building is actively destroyed. I would just obsolete the buildings with advancing tech, but that means until you build (in this example) a new barracks your city has *no* barracks - which is silly.

Thanks for the example code, btw. It's exactly what I was looking for.

Max

Mylon
Dec 07, 2005, 06:44 PM
If I knew how to prevent a building from being built I would love to do so for the case of power plants to shorten the build menu. I don't know how to do this short of using a tech to obsolete the building, but that would be a global change.

I've been wanting to include additional power plants (solar and fusion), but not at the cost of lenghtening the build menu further.

maxpublic
Dec 07, 2005, 06:50 PM
I notice that during the build command loop it gets a list of all buildable buildings for that city. I wonder if we can alter that list directly for a particular city? That would solve all of the problems in one fell blow.

Max

jbfballrb
Dec 07, 2005, 07:14 PM
I agree, this would be easier, but the original request specifically asked for a building that replaces the original, not just another building. And I just wanted to see if I could do it But I'm stuck and can't figure out how to dis-allow the building of the original one again, any suggestions?

this would be cluttery and difficult probably...
you could institute a trigger wherein if Barracks II was built a tech (Obsolecense) was researched, which obsoleted Barracks I. you could repeat this, tho the tech tree would get cluttered. unfortunately, you cant have it researched again w/B3 and have it obsolete B2...unless you can put a tech so that it isnt on the screen somehow...

Snaitf
Dec 07, 2005, 07:27 PM
I notice that during the build command loop it gets a list of all buildable buildings for that city. I wonder if we can alter that list directly for a particular city? That would solve all of the problems in one fell blow.Max

I've thought of this also, but unfortunaltey the CyCity class has no setCanConstruct function, maybe a much more expreienced coder out there knows how we could add something like this?:mischief:

Another work around that would probobly work (in english):

when building is being produced
check to see if it is a barracks
check to see if barracks II or barracks III is present
force production of something different

however, this is very sloppy, and would require alot of code for all the buildings you want to add, and would still let the original barracks be selectable. It would just change the production if you already have the upgraded version...

BLueGreen
Dec 07, 2005, 07:53 PM
Ah thats nice upgradable buildings is a cool idea!

Thanks to your demonstartion snaitf I can now implement some building upgrades for my own mod! :P. That barracks idea like barracks II, III giving +1 extra xp is a awesome idea.

Perhaps making them require a technology or a unit reaching a certain level or something I could....
Barracks II - Requires a unit to reach level 3
Barracks III - Requires a unit to reach level 4 + tech
etc..

Snaitf
Dec 07, 2005, 10:07 PM
this would be cluttery and difficult probably...
you could institute a trigger wherein if Barracks II was built a tech (Obsolecense) was researched, which obsoleted Barracks I. you could repeat this, tho the tech tree would get cluttered. unfortunately, you cant have it researched again w/B3 and have it obsolete B2...unless you can put a tech so that it isnt on the screen somehow...

Problem with this is that it would affect ALL cities, if you build a Barracks II in city A, but city B never had a Barracks, then Barracks becomes obsolete and city B can never build a Barracks at all :(

Requies
Dec 08, 2005, 01:16 AM
I've thought of this also, but unfortunaltey the CyCity class has no setCanConstruct function, maybe a much more expreienced coder out there knows how we could add something like this?:mischief:

Another work around that would probobly work (in english):

when building is being produced
check to see if it is a barracks
check to see if barracks II or barracks III is present
force production of something different

however, this is very sloppy, and would require alot of code for all the buildings you want to add, and would still let the original barracks be selectable. It would just change the production if you already have the upgraded version...

Instead of using CyCity directly, have it call a similar function through PyCity (which would at its base call the CyCity function) and then alter the PyCity function to do the check.

The only unfortunate thing is that you're going to have to add all the PyCity functions which the Main Interface uses to the PyCity class.

BTW, you could probably make it more elegant by having some "MadeObsolete" dictionary where each building will "be made obsolete" by a dictionary of buildings. For example,

def PyCity.canConstruct:
if obsolete_dict.has_key (building):
obsbuildings = obsolete_dict[building]
for i in range (len (obsbuildings)):
if (self.city.hasBuilding (obsbuilding[i])):
return False
return True


Req

NikG
Dec 08, 2005, 04:36 AM
After having messed around wiht the xml files, I have found this for stopping constuction (note that they are not covered in the API, and I really dont know the syntax):

def cannotConstruct(self,argsList):
pCity = argsList[0]
eBuilding = argsList[1]
bContinue = argsList[2]
bTestVisible = argsList[3]
bIgnoreCost = argsList[4]
return False

in the CvGameUntils.py

In this file there exists alot of canXXXX, cannotXXXX, so if someone would like to mess more around with it, to find the syntax.

More important, I think the Desert War mod uses something like this...

maxpublic
Dec 08, 2005, 05:31 AM
I did a cursory run through the code and I see where it accesses the argument list to find what buildings it can construct, but I don't see how the argument list itself is generated. If we could find that little bit of code (assuming we have access to it) then all our problems are solved.

Edit: did a cursory test. It appears the AI will build Barracks I, then build Barracks II, which destroys Barracks I. It'll then build Barracks I again, which destroys Barracks II. And so on.

Max

omegaleader
Dec 12, 2005, 09:50 AM
Is it possible to make it require a high level unit?

ie. If you have a level 4 unit you can move it to a city with Barracks I and use the unit to build (like a great person) or upgrage to a Barracks II which gives more experience. Sort of like putting verterans on desk duty to teach the new troops.

Might make it more valuable than just a new building.

screwtype
Dec 28, 2005, 07:22 AM
Hmmm, I quite like that idea omegabuilder.

jjsheets
Jan 02, 2006, 09:45 PM
I just got Civ 4, and started reading up on how to mod stuff. Then I saw this thread. I really like the idea of upgrading buildings, and decided to hunt down exactly how to fix the problem of being able to build older versions when the newer building is already built.

Here's what I came up with:

You have to either create a copy of the CvGameUtils.py file, or create a class that inherits from the original. See the tutorial mod to see how that's done. Since I'm putting all the mods I like into my customassets folder, I simply copied CvGameUtils.py.

Whichever way you do it, you need to replace or override the cannotConstruct function of CvGameUtils. Replace it with this:

def cannotConstruct(self,argsList):
pCity = argsList[0]
eBuilding = argsList[1]
bContinue = argsList[2]
bTestVisible = argsList[3]
bIgnoreCost = argsList[4]

if (gc.getBuildingInfo(eBuilding).getType() == "BUILDING_BARRACKS"):
for i in range(gc.getNumBuildingInfos()):
if (gc.getBuildingInfo(i).getType() == "BUILDING_BARRACKS_II"):
if (pCity.hasBuilding(i)):
return True
elif (gc.getBuildingInfo(i).getType() == "BUILDING_BARRACKS_III"):
if (pCity.hasBuilding(i)):
return True
elif (gc.getBuildingInfo(eBuilding).getType() == "BUILDING_BARRACKS_II"):
for i in range(gc.getNumBuildingInfos()):
if (gc.getBuildingInfo(i).getType() == "BUILDING_BARRACKS_III"):
if (pCity.hasBuilding(i)):
return True
return False

You'd have to change it for every building you want, it would be annoying, and much simpler to not remove the earlier building versions, but this properly upgrades buildings without fail.

If you wanted to add a new upgradeable building you have to make sure that you add the building to be deleted in Snaitf's code section and add the deleted buildings to this code section and change all the names accordingly.

Impaler[WrG]
Jan 03, 2006, 10:37 AM
I've noticed that buildings like units have two identifiers, a "Building Class" and a "Type". Unlike Units their is no real use of the Type attribute because every building has a different building Class and this will differentiate them. Two bildings can have the same class with no noticable effect both of them build and both of them can be present

I am wondering if a check based on Building Type can be used as the basis of a ConConstruct function and possibly even a delete old version function that would limit a city to have only 1 building of each class. So for example Barracks I, II and III would all be member of the single Barracks class and the once one such building is in a city none of the others can be built. If this were possible then the mod maker could set up the upgrade path of a building entirely in XML without needing to modify any Python other then pluging in a standardized function or two.

Tenketsu
Mar 08, 2006, 06:59 PM
Has there been any further progress with this idea by anyone?

TheLopez
Mar 08, 2006, 07:11 PM
I don't think so, but it is on my todo list...

Vadus
Mar 09, 2006, 10:50 AM
nice nice, I'll need this for my space mod :)

J_Period
Mar 09, 2006, 11:54 AM
']I've noticed that buildings like units have two identifiers, a "Building Class" and a "Type". Unlike Units their is no real use of the Type attribute because every building has a different building Class and this will differentiate them. Two bildings can have the same class with no noticable effect both of them build and both of them can be present

I am wondering if a check based on Building Type can be used as the basis of a ConConstruct function and possibly even a delete old version function that would limit a city to have only 1 building of each class. So for example Barracks I, II and III would all be member of the single Barracks class and the once one such building is in a city none of the others can be built. If this were possible then the mod maker could set up the upgrade path of a building entirely in XML without needing to modify any Python other then pluging in a standardized function or two.

I tried, the problem is that each Civ can only use ONE building of each building type, like each civ can build only the unique unit of the type, not the default unit of that type.

Crighton
Mar 16, 2006, 02:17 PM
personally I thought this would be great idea, you merely anticipated me by about 3 or 4 months and actually knew how to make it work.

bravo.

J_Period
Mar 16, 2006, 03:40 PM
personally I thought this would be great idea, you merely anticipated me by about 3 or 4 months and actually knew how to make it work.

bravo.

unfortunately it doesn't quite work yet, but if you could make it work, I'd be your fan ;)