Delete Player's Cities via LUA

Except Custom Civs are heavily modded.

I know, though most of the ones we have added aren't complex code-wise.


The first thing I would do is as mentioned earlier. Lace print statements into the code to see if any of them are printed into the lua.log as the last thing before the crash.

As you've currently written your code, however, the owner of the unit can delete their own cities and de-tech themselves if they kill off the unit within their own territory.

One thing I remember causing one of my games a long time ago to become unrecoverable was using IGE to delete an adversary city that had a trade-route starting from that city. It CTD'd when I progressed turns and if I tried to load a save from the turn when I deleted the city.

I'm not concerned about the code firing by deletion since this is just meant to be a joke event for AI-only games, so it's just another comedic possibility.

As for the issue you mentioned regarding deleted cities, that's a very good point, though these crashes are happening before the unit is even expended, and none of the lace statements are in the LUA log right before the game crashes. It just...happens. We'll try running it without the LUA attached to see if anything changes.

EDIT: I tested the Trade Route crash by having the unit delete a city two active caravans were originating from, and so far there haven't been any crashes after 30 turns. I guess whatever caused the crash was fixed in a patch at one point if it was that long ago. In my first Brave New World game I remember nuking a Dom Pedro city that had a trade route coming from it and that crashed the game.

I also noticed that I forgot to add a unit flavor to the Big Chungus unit (even though they can't be built, Musicians, Artists, etc have flavors of 1). Could this have something to do with it?
 
Last edited:
Assigned specialists also cause issues IIRC, so you probably want to do a SetPop(0) before you actually kill the city
 
I'm also curious if Holy Cities may have to do something with this, since you should not be able to remove (I.e. raze) those under normal circumstances. That being said, AFAIK, the AI will always found their religion in their capital so that may not be part of the problem here.
 
I added city:SetPopulation(0) to the code right before the city kill routine, thank you for the suggestion, whoward!

I tested out the Holy Cities theory by letting a civ found a religion, giving another nearby civ powerful units to take the religion founder civ, the I use Big Chungus on the Civ that conquered the first one. One thing I noticed was that captured capitals are deleted alongside all of the other cities when the code runs (in the Victory Progress screen it'll say that the Civ who had its' capital deleted "hasn't founded a capital city"). I then founded a religion myself. The deleted Holy City's religion still exists, and its' records still show up in religion overview, but the World Religions panel is broken. It doesn't show the amount of religions that can still be founded (under OVERALL STATUS it is completely blank) and the screen thinks no religions have been founded at all.

Despite these issues they have not caused the game to crash.
 
I added city:SetPopulation(0) to the code right before the city kill routine, thank you for the suggestion, whoward!

I tested out the Holy Cities theory by letting a civ found a religion, giving another nearby civ powerful units to take the religion founder civ, the I use Big Chungus on the Civ that conquered the first one. One thing I noticed was that captured capitals are deleted alongside all of the other cities when the code runs (in the Victory Progress screen it'll say that the Civ who had its' capital deleted "hasn't founded a capital city").
Luckily Firaxis also provided us with pCity:IsOriginalCapital() and pCity:IsOriginalMajorCapital() (of which the latter is used in VictoryProgress.lua)

I then founded a religion myself. The deleted Holy City's religion still exists, and its' records still show up in religion overview, but the World Religions panel is broken. It doesn't show the amount of religions that can still be founded (under OVERALL STATUS it is completely blank) and the screen thinks no religions have been founded at all.
And we've also got pCity:IsHolyCityAnyReligion()

Adding in both of those checks (and not deleting these cities) should solve the UI issues you encountered.

Despite these issues they have not caused the game to crash.
But at least we now know the problem was not related to these things! Moreover, we fixed another problem we had not yet encountered :)
 
Added in both of those checks just to be safe, and thank you again! :) Gonna run some tests with this on my friend's setup this weekend, hopefully this will do the trick!
 
Sorry l am necroing an old thread, but I'm trying deleting a city with a script as well. However, the game crashes.when I delete the city. I don't know if OP got it working, but I've tried the things in this thread. The goal would be to make a somewhat nomadic test civ that can pack up a city and get a settler to relocate it, I've not delved into the implementation of the other functionalities, just trying to delete the city first. Code looks like this:

Code:
function AtarkaMigrate(iPlayer, iCity, iBuilding, bGold, bFaithCulture)
    local pPlayer = Players[iPlayer];
    if (pPlayer:IsEverAlive()) then
        local civType = pPlayer:GetCivilizationType();
        if (civType == iJGAtarkaCiv) then
            local pCity = pPlayer:GetCityByID(iCity);
            if (pCity:IsHasBuilding(GameInfoTypes.BUILDING_MONUMENT)) then
                if (pCity:IsCapital() == false) then
                    if (pCity:IsOriginalCapital() == false) then
                        if (pCity:IsHolyCityAnyReligion() == false) then
                            local hexpos = ToHexFromGrid(Vector2(pCity:GetX(), pCity:GetY()));
                            pCity:SetPopulation(0);
                            print("City kill initiated");
                            pCity:Kill();
                            print("City kill successful");
                            Events.SerialEventCityDestroyed(hexpos, iPlayer, iCity, -1)

                        end
                    end
                end
            end
        end
    end
end

What is peculiar is that the "City kill successful" print statement executes and is visible in the Lua log. So it might not be the city:Kill() that causes the problem but something else going haywire in the aftermath. Function is hooked on the CityConstructed event and temporarily uses building a Monument as the trigger for city deletion. I attempted deleting a city a month or two ago for the first time, and tested the player:Disband(city) method as well, but I might have not included every anti-crash procedure in this thread, so I've got to test that again once I have the time.

So, does anyone know if this is even possible, or have more ideas of preventing crashes? Part of the code I copied from this thread, so that is why the semicolons are inconsistent, but that shouldn't matter in getting the code to run.
 
I've had problems before with GameEvents.CityConstructed where it consistently crashed my game if I tried to unsubscribe from it in its own hook (i.e., call GameEvents.CityConstructed.Remove(...))
While that's a different problem, I would not be surprised if calling pCity:Kill() in this hook would also crash the game. For instance, the game core could expect the city to still exist at the end of the calls to GameEvnets.CityConstructed

You could try to directly call your city-kill method within FireTuner (in the Lua console, select your script from the dropdown menu, and execute for pCity in Players[0]:Cities() do AtarkaMigrate(0, pCity:GetID(), false, false) end) This executes your method for all of the human player's cities)
If doing so doesn't crash your game, then this must mean that GameEvents.CityConstructed is (part of) the problem. If it doesn't crash, there's something else you're missing (although I wouldn't know what it would be)
 
I've found that in general unsubscribing from hook events has a high tendency to CTD regardless of the circumstances of where the GameEvents.Hook.Remove(function_name) is executed. Removing a function from a hook event within the same function that is being removed has a really high percentage chance of just creating instant CTD regardless of the hook event being executed.

I no longer write Civ5 scripts to ever use the Remove command and it tends to result in more stable games mystery-CTD-wise.

I tend to write my scripts with the equivalent of a boolean for "We're Done With This Event" and set it to false until it is time to stop running that event function. Instead of doing a "Remove" I reset the boolean to true and then at the top of the function I just do a return if the boolean has been reset to true.
 
I've had problems before with GameEvents.CityConstructed where it consistently crashed my game if I tried to unsubscribe from it in its own hook (i.e., call GameEvents.CityConstructed.Remove(...))
While that's a different problem, I would not be surprised if calling pCity:Kill() in this hook would also crash the game. For instance, the game core could expect the city to still exist at the end of the calls to GameEvnets.CityConstructed

You could try to directly call your city-kill method within FireTuner (in the Lua console, select your script from the dropdown menu, and execute for pCity in Players[0]:Cities() do AtarkaMigrate(0, pCity:GetID(), false, false) end) This executes your method for all of the human player's cities)
If doing so doesn't crash your game, then this must mean that GameEvents.CityConstructed is (part of) the problem. If it doesn't crash, there's something else you're missing (although I wouldn't know what it would be)

I've found that in general unsubscribing from hook events has a high tendency to CTD regardless of the circumstances of where the GameEvents.Hook.Remove(function_name) is executed. Removing a function from a hook event within the same function that is being removed has a really high percentage chance of just creating instant CTD regardless of the hook event being executed.

I no longer write Civ5 scripts to ever use the Remove command and it tends to result in more stable games mystery-CTD-wise.

I tend to write my scripts with the equivalent of a boolean for "We're Done With This Event" and set it to false until it is time to stop running that event function. Instead of doing a "Remove" I reset the boolean to true and then at the top of the function I just do a return if the boolean has been reset to true.

Thank you to both of you, the script works if I execute it via the console. I think I understand the problem now, maybe removing the city in PlayerDoTurn event could work as it doesn't deal with the city itself, though it might be somewhat clunky.
 
Top Bottom