Auto-Sell or Delete Buildings when Obsolete

Ulixes

Prince
Joined
May 2, 2010
Messages
312
Hi Everybody.

I hope some of you can help me, or at least give me an hint on how to do this.

I would like to find a way (in Lua) to make the buildings auto sold or deleted (which way is easier) when obsolete.

Why?

I'm creating buildings for Ancient, Classical and Medieval Era and I want to make them obsolete at a certain tech.

Problem: the player can still fill the specialist slots of an obsolete building. :confused:
So, I thought that the solution could be to auto-sell or delete the entire building once obsolete (of course, if someone of you as a better idea, feel free to suggest it).

I don't know if this has ever bothered someone else but I finally found the time to return to modding some day ago and I really would like to fix this problem.

Is there an event fired when a building become obsolete?
Since I never saw a code who deletes a building, is there anyone that has an idea on how to do it?

:please:
 
For the event to fire on, you're most likely looking at using GameEvents.TeamTechResearched and to remove a building from a city you can use city_object:SetNumRealBuilding(YOUR_BUILDING, 0).

I think the real challenge may be making it so that the obsolete building can no longer be built and handling the case of said building being under construction on the turn where it becomes obsolete. It might be possible to set up a second version of the building using the same building type that has no yields or specialist slots and granting that upon obsolescence to solve the issue of it still being buildable.
 
[Sniped]

Though to be clear, Bobert, I think he's using the ObsoleteTech column of the Buildings table, which should prevent NEW buildings from being made, but even if that wasn't available, Player.CanConstruct and City.CanConstruct are very easy to use if he had to roll his own obsolescence function.
 
But, once set the building as obsolete at a certain tech, shouldn't it be automatically unbuildable?

The only problem should be removing the ones already built.
The 'obsolete' tag (already present in the XML and working) should make the building unbuildable, after that tech, without any further effort, don't you think?
 
Yes, I just saw it. :)

I won't lie, I'm a newbie with Lua (the best I did was this).

I'm working on this mod for a long time but serious lack of time prevented me to learn properly Lua (as I would like to), so, I get all the help I can find.

Usually I look for something similar to what I need and than I modify it for my purposes (the few things I learned, I learned them this way) but there is nothing similar to this anywhere so I have to start from zero and anything more complicated of what I've linked is unknown land for me.

Anyway, I'll try tomorrow. If I make a total mess I hope you guys will still be around! :)
 
  1. The buildings should become unbuildable with the ObsoleteTech.
  2. In addition to what Nutty and Bobert13 have already mentioned, it will also probably be necessary to look through all the player's cities to determine what is in the current production of the build qeue, and take some action if it is one of the buildings that has just gone obsolete.
    • I think the GameEvents.TeamTechResearched will fire before the rest of turn processing is conducted, so you should be able to grab the current production-progress on a building that has just gone obsolete and apply it to the next item (if any) in a city build qeue.
    • Otherwise, I am pretty sure that building that just became obsolete is going to be removed from the build-qeue on the next "NEXT TURN" processing, and the production progress is otherwise going to be lost. What I am not 100% sure of is whether there will be any turn-lag between the turn number when the ObsoleteTech is discovered, and the building is removed from the city build qeue.
    • Or it will be removed and the production lost as part of the same turn processing when the player techs up, depending exactly on when these game actions occur with respect to each other so far as when (1) the game actually "grants" the newly-discovered tech, (2) the game processes through a player's city and updates production, city build-qeue items, etc.
    • AI are really not going to understand buildings that go obsolete, nor will they consider whether or not they can finish a building in city-X before the building goes obsolete.
  3. What you are doing is somewhat similar to this although there a couple of fundamental differences in what we are doing.
    • The main fundamental difference is that I am making use of ReplacementBuildingClass from the Buildings table in addition to the use of ObsoleteTech
      • The Advantage of ReplacementBuildingClass is that it preserves and updates the build-qeue of a city while also preserving the hammers-progress a city had invested into a building.
      • Essentially, I use ReplacementBuildingClass to no longer allow an old building to be produced, requiring a newer better class of building to be constructed instead, and then later in the tech tree the ObsoleteTech removes the effects of any existing "old" buildings.
      • If you are stringing multiple ReplacementBuildingClass designations from Building-A to Building-B to Building-C, when Building-B is unlocked by its technology, Building-A can no longer be constructed, and Buiding-B is inserted into a city's build qeue in Building-A's place by the game, while preserving all the production progress on Building-A and applying it to Building-B. Later on, when the tech that allows Building-C is discovered, it replaces Building-B in the same way, and with the same advantages in terms of the Building-B/Building-C relationship.
      • The way I am using it, Building-A is made completely obsolete by the ObsoleteTech a few techs higher up the tree from when Building-B is unlocked, and before Building-C becomes available as a replacement for Building-B.
    • In case it is of any value to you I have attached my current working version, where I am reworking it somewhat and searching for better balance. This attached version is not the same as and is newer than the one in the linked thread.
    • There are some parts of it, especially in the lua, that need some house-cleaning for comments, currently-unused code, etc.
 
GameEvents.TeamTechResearched() can fire any time.

Consider using a Great Scientist to bulb a tech ...

Or when player B on the same team as player A starts their turn and so completes the tech that obsoletes the building being constructed by player A


Edit: IIRC using SetNumRealBuilding() to delete buildings causes issues if those buildings contain in-use specialist slots, you need to un-assign the specialists first. And I'm not sure of the effect if the deleted building has assigned great works.
 
Yeah, I was ignoring the Great Scientist bulbing and the Goody Hut issues. I was speaking only in terms of the order in which things occur as part of turn processing.

If you use a Great Scientist and get the tech instantly that obsoletes a building, the obsolete buildings may stay in the city build-qeues until next-turning processing, but I have never tried to make that specific test. Same with the techs you can get from Goody Huts, but this would only apply to the buildings he is wanting to have usable during the Ancient Era.

Pulling Great Works (if any) and sticking them elsewhere is, as whoward says, an issue, along with the specialists that may be working the specialist-slots.

If the buildings are flavored high enough, the AI are going to want to construct the building(s), which means they can lose-out on a lot of production potential over the course of the 1st three Game-Eras, because the AI won't understand that the buildings go obsolete.

Ulixes,
If you decide because of some of these issues to keep the obsolete buildings in the cities, be aware that a player still pays maintenance on an obsolete building, even if all the other effects from the building have gone poof from discovering the obsolete tech.
 
Probably not an issue for the OP, but there's also an issue with deleting buildings that provide resources (eg Ally from the recycling plant) - especially if the AI has units that need those resources (and their army suddenly becomes only 50% effective!)
 
Thank you all for your time, and I apologize for the delay of my answer (couldn't get to my pc earlier).

I like your approach to building updates, LeeS, you're right about the AI wasting time and production and I think your solution to this issue can be adopted almost entirely (tweaking techs, flavours, and production values can grant that the AI is not always updating its buildings) but the problem of specialist slots (and maintenance cost) remains.

If there is no way to fix it I have to accept the idea that I shall never give specialists or maintenance cost to a building I want to make obsolete at a certain tech.
Otherwise, cities would cumulate far too many specialists slot and a far too high total maintenance cost.
(not to mention the absurdity of seeing a modern doctor working at the "Temple of Healing" or a modern lawyer in the "Forum" :lol: )

Considering the "assigned specialists" issue that Whoward pointed out, I fear this could be much more complicated than I thought...

I see Whoward point about resources and units, I already thought about that, so, I don't plan to allow ancient buildings to produce military relevant resources.

Supposing I will never give great works to a building I plan to make obsolete (ever), the only problem is to unassign the specialists.
Is there a way to do that in Lua?

If so, about that, I've to beg your help because I suspect this is far more beyond my skills :(
 
the only problem is to unassign the specialists.
Is there a way to do that in Lua?

Yes.

Couldn't code it off the top of my head ...

BUT, the code is already in the CityView screen (when you click on the specialist to make them unemployed)
 
I gave a look to CityView.lua but unassigning specialists through Lua is too far beyond my current skills.

Anyway, if this can be of some interest for anyone, I used Bobert13 suggestion to try something else and, with LeeS help, it worked!

This is the thread.
 
Supposing I will never give great works to a building I plan to make obsolete (ever), the only problem is to unassign the specialists.
Is there a way to do that in Lua?
Yes, but there may still be an issue with doing it for AI.

I have some code in the social policies grant buildings that removes specialists from a building about to be deleted. I'll dig it up later today. It works fine for humans but a year or so ago an update made it so that it wouldn't work on AIs. I don't know if that limitation still exists but I assume it does.

The end result is that if you delete a building an AI owns their citizen data for that city gets malformed with no way I could figure out for fixing it or working around it short of a custom DLL. This malform won't cause a crash, from the outside it will look like the AI has the same population, but the citizens that were in the deleted building won't be able to be assigned anywhere to provide yield.
 
Hi Machiavelli, glad to see you again! (here too) :)

If the limitation you mentioned regarding the AI is still there (and I assume too that it is), sadly, everything returns to the starting point, since every building made obsolete (and deleted) would be obsolete (and deleted) for the AI too (at least for me, I'm usually against human-only features).

Usually Whoward doesn't accept requests and probably Gazebo is far too busy to be interested in this (at least, I think so).

I don't know any other who can mess with the Community DLL (that I use as base for my project therefore I can't use any other modified DLL) so the obsolete/delete idea remains in a Dead End...

Thank you anyway for your time, I really appreciate it. :)
 
Code:
--Assumes:
--local city = city object you want
--local buildingID = building ID you want to remove
--local playerID = the id of the owner of the city

-- Remove any specialists from the building
if(city:GetNumSpecialistsInBuilding(buildingID) > 0) then
	local numSpecialists = city:GetNumSpecialistsInBuilding(buildingID);
	local isNoAutoAssign = city:IsNoAutoAssignSpecialists();

	city:DoTask(TaskTypes.TASK_NO_AUTO_ASSIGN_SPECIALISTS, 0, 0, 1); -- Turn on manual specialist control

	for i = city:GetNumSpecialistsInBuilding(buildingID), 0, -1 do
		city:DoTask(TaskTypes.TASK_REMOVE_SPECIALIST, 1, buildingID, playerID);
	end
	-- Error check
	if(city:GetNumSpecialistsInBuilding(buildingID) > 0) then
		print("WARN -- Failed to remove all specialists from " .. tostring(GameInfoTypes[buildingID]) .. " in " .. tostring(city:GetName()) .. "!  The Citizens data will become malformed when the building is removed!");
	end
	-- Restore AutoAssign Specialist if it was enabled
	if(not isNoAutoAssign) then
		city:DoTask(TaskTypes.TASK_NO_AUTO_ASSIGN_SPECIALISTS, 0, 0, 0); -- Turn off manual specialist control
	end
end
-- Remove the building
city:SetNumRealBuilding(buildingID, 0);

You'll only run into problems if the building has specialists slots for AI players.
 
Only poroblem left is a way to break the the AI limitation...

Thank you Machiavelli :)
 
That piece of code was exactly what I needed to fix a bug I had! So thank you from me too :D.

A correction though, for others stumbling upon this: the "city:SetNumRealBuilding(buildingID, 0)"-statement needs to happen after the TASK_REMOVE_SPECIALIST-loop, too. While testing I noticed some citizens were still disappearing. I assume because when restoring the AutoAssign they are reassigned to the building to be deleted.
 
Back
Top Bottom