How do you debug a mod when you're not getting any lua errors?

Jiska

Warlord
Joined
Apr 23, 2016
Messages
164
So say you have a mod:

https://steamcommunity.com/sharedfiles/filedetails/?id=1737956594

and you're experiencing random crashes. All your code seems to work, and the crashes aren't reproducible. You've put a debug print at the beginning and end of each of your blocks of code, and the game doesn't seem to be crashing when you code is fired.

I've checked the database, gamecore, and net_message_debug logs, and none of them seem to have any pertinent information. Are there any additional ways of diagnosing the cause of the crashes?
 
If you are allowing purchase of buildings with Faith via Pantheon, Founder, or Enhancer Beliefs this is a prime candidate for mystery-crashes unless you've also re-written the DLL to accomodate.

With the base-game DLL for G&K / BNW, only Follower and Reformation Beliefs execute properly for unlocking faith-purchased buildings.
  • Pantheons are not allowed to do this without crash-happiness of the game, nor will the game's standard DLL implement such an effect - the pantheon can be chosen and the religion "screens" may even say the Pantheon unlocks buying the building, but the game does not actually allow it.
  • Under the game's standard DLL, allowing a Founder or Enhancer Belief to unlock purchase of a building by faith leads directly to intermittent crashing of the game, either when the human attempts to spread such a religion or when the AI does so, and when the religion is spread to a city via religious pressure.
    • The CTD's are intermittent, essentially random, and unfixable.
    • A save of a game right before spreading religion to a new city can be reloaded and the CTD may or may not recur for spreading the religion to the city with the same Missionary, for example. Multiple repeat tests of the same actions after repeat reloads of the save may or may not show differing behavior each time the reload is done.
CTDs that come from these Belief issues don't give any real usable clues in any of the logs, either.
 
Thanks for the reply LeeS!

No actually, I have some buildings in the Pantheon portion of my mod, but they're unlocked for regular construction via dummy-prerequisite-building-added-by-lua rather than by Faith purchase. However, I do have a lot, like 50+ dummy buildings used as substitutes for Beliefs when purchasing additional Pantheon Beliefs. There probably aren't more than a few of them in a City at any given time, but does mass adding dummy Buildings affect game stability?
 
Do your dummy buildings have specialist slots? And if so, does your code for removing the dummy buildings take extra care to remove any pop assigned as specialists in them and relocate them elsewhere? As this is also a cause of rando CTDs
 
Nope, they're all super simple, nothing much but greatworkcount -1
The beliefs and dummy-belief-buildings are here: https://pastebin.com/h441ZpE9
and they almost all look like:
Code:
<Type>ISKA_BUILDING_PANTHEON_0_ALL_FATHER</Type>
            <BuildingClass>BUILDINGCLASS_ISKA_PANTHEON_0_ALL_FATHER</BuildingClass>
            <Cost>-1</Cost>
            <FaithCost>-1</FaithCost>
            <PrereqTech>NULL</PrereqTech>
            <ArtDefineTag>NONE</ArtDefineTag>
            <MinAreaSize>-1</MinAreaSize>
            <NeverCapture>true</NeverCapture>
            <HurryCostModifier>-1</HurryCostModifier>
            <IconAtlas>BW_ATLAS_1</IconAtlas>
            <PortraitIndex>19</PortraitIndex>
            <Description>TXT_KEY_ISKA_DUMMY</Description>
            <GreatWorkCount>-1</GreatWorkCount>
and the Pantheon buildings are here: https://pastebin.com/1XAuhB48
 
You have a whole smattering of beliefs for which you've never stated the Type of Belief. Instead of for example
Code:
<Pantheon>true</Pantheon>
You've got
Code:
<LandBarbarianConversionPercent>-1</LandBarbarianConversionPercent>
Beliefs need to be assigned to a Belief-type: Pantheon, Founder, Follower, Enhancer, or Reformation.

While LandBarbarianConversionPercent is a valid column, I don't think Firaxis used it anywhere in either of G&K or BNW.

Also, it is emphatically not true that YIELD_FAITH is the only yield that works in table <Building_BuildingClassYieldChanges>. Any of the yields PRODUCTION, GOLD, FOOD, CULTURE, FAITH, SCIENCE can be used with the game's standard DLL. Using this table with dummy buildings can often have weird results especially as dummies are removed or added. There is a common misunderstanding however with regard to how the effects of this table stack for multiple copies of a dummy building. The effects do not stack for multiple copies of a BuildingType within the same city. So this will only provide more than 1 faith for each shrine when more than one city contains a ISKA_BUILDING_PANTHEON_0_ALL_FATHER
Code:
<Row>
      <BuildingType>ISKA_BUILDING_PANTHEON_0_ALL_FATHER</BuildingType>
     <BuildingClassType>BUILDINGCLASS_SHRINE</BuildingClassType>
      <YieldType>YIELD_FAITH</YieldType>
     <YieldChange>1</YieldChange>
 </Row>
I use the table all the time with "normal" buildings as the BuildingType for all of the yields noted above -- there is no problem with any of them.

Database Error:
Code:
2378.        <Row>
2379.            <BuildingType>ISKA_BUILDING_PANTHEON_20_ASPECT_OF_NATURE</BuildingType>
2380.            <FeatureType></FeatureType>
2381.            <YieldType>YIELD_FAITH</YieldType>
2382.            <Yield>4</Yield>
2383.        </Row>
You can't have a null in that column
Code:
<Column name="FeatureType" type="text" reference="Features(Type)"/>
 
Thanks for the reply LeeS!

You have a whole smattering of beliefs for which you've never stated the Type of Belief.
This is intentional. These second set of Pantheon Beliefs aren't supposed to show up when choosing Pantheon, Founder, Follower, Enhancer, or Reformation Beliefs, but instead are flagged by
Code:
<LandBarbarianConversionPercent>-1</LandBarbarianConversionPercent>
which isn't actually supposed to do anything, but instead mark them as to be shown among the other Pantheon Beliefs when choosing secondary, tertiary, and quaternary Pantheon Beliefs.

So since these things are intentional and their idiosyncrasies seem to be working as intended with the rest of my code... is it possible that <LandBarbarianConversionPercent>-1 is crashing my game at some point when a missionary moves adjacent to a barbarbian? But that can't be, because those Beliefs are never actually given to a player within the DLL's Belief system, so LandBarbarianConversionPercent is never actually checked by the DLL. (I surmise.)

Similarly, the reason the second set of Pantheon Beliefs aren't marked as Pantheon, Founder, Follower, Enhancer, or Reformation Beliefs is because I don't want them to actually be choosable as those types of Beliefs. So the worst that could happen by not flagging them as such would that the game simply wouldn't display them as such, right? That couldn't be the cause of ctds?

Also, it is emphatically not true that YIELD_FAITH is the only yield that works in table <Building_BuildingClassYieldChanges>. Any of the yields PRODUCTION, GOLD, FOOD, CULTURE, FAITH, SCIENCE can be used with the game's standard DLL. Using this table with dummy buildings can often have weird results especially as dummies are removed or added.

Yes, I have a YIELD_FOOD on a few of the Beliefs... I distinctly remember Culture not working (maybe I futzed it somehow?), but I in the end I circumvented this problem by just ignoring it!

There is a common misunderstanding however with regard to how the effects of this table stack for multiple copies of a dummy building. The effects do not stack for multiple copies of a BuildingType within the same city. So this will only provide more than 1 faith for each shrine when more than one city contains a ISKA_BUILDING_PANTHEON_0_ALL_FATHER

I don't quite understand what you're trying to say here... I'm not trying to stack dummy or regular Buildings, each dummy is only supposed to be added at most once to Cities, and that particular Belief should only provide +2(Primary)/+1(secondary, tertiary, and quaternary). The dummy Buildings are only added by secondary, tertiary, and quaternary Pantheon Beliefs, so they shouldn't be overlapping with the (primary) Pantheon Belief effects.

Database Error... You can't have a null in that column

Thanks! Must have missed that... is it possible that and that alone was the cause of my CTDs?
 
Belief_BuildingClassYieldChanges is a different table to Building_BuildingClassYieldChanges, but it should still accept all the "standard" types of yield.

Unmodded Game code:
Code:
<Belief_BuildingClassYieldChanges>
	<Row>
		<BeliefType>BELIEF_ANCESTOR_WORSHIP</BeliefType>
		<BuildingClassType>BUILDINGCLASS_SHRINE</BuildingClassType>
		<YieldType>YIELD_CULTURE</YieldType>
		<YieldChange>1</YieldChange>
	</Row>
	<Row>
		<BeliefType>BELIEF_FEED_WORLD</BeliefType>
		<BuildingClassType>BUILDINGCLASS_SHRINE</BuildingClassType>
		<YieldType>YIELD_FOOD</YieldType>
		<YieldChange>1</YieldChange>
	</Row>
	<Row>
		<BeliefType>BELIEF_CHORAL_MUSIC</BeliefType>
		<BuildingClassType>BUILDINGCLASS_TEMPLE</BuildingClassType>
		<YieldType>YIELD_CULTURE</YieldType>
		<YieldChange>2</YieldChange>
	</Row>
	<Row>
		<BeliefType>BELIEF_LITURGICAL_DRAMA</BeliefType>
		<BuildingClassType>BUILDINGCLASS_AMPHITHEATER</BuildingClassType>
		<YieldType>YIELD_FAITH</YieldType>
		<YieldChange>1</YieldChange>
	</Row>
</Belief_BuildingClassYieldChanges>
The only yield that "stacks" for multiple copies of a building within the same city for the Belief_BuildingClassYieldChanges table is Faith. So if there are 10 copies of a building called BUILDING_DUMMY_SOMETHING in a single city, each of these ten copies will be affected by the Belief_BuildingClassYieldChanges so long as YIELD_FAITH is the YieldType. If any other YieldType is specified, the YieldChange will only be applied once per city. Blame the Firaxis base DLL for this particular bit of wierdness.


-----------------------------

Multiple Cities each getting a copy of BUILDING_DUMMY will cause stacking effects on the Shrine-Class of buildings' yields, but a single city with 15 copies of BUILDING_DUMMY will only add 1 yield to Shrine-Class buildings:
Code:
<Building_BuildingClassYieldChanges>
	<Row>
		<BuildingType>BUILDING_DUMMY</BuildingType>
		<BuildingClassType>BUILDINGCLASS_SHRINE</BuildingClassType>
		<YieldType>YIELD_GOLD</YieldType>
		<YieldChange>1</YieldChange>
	</Row>
</Building_BuildingClassYieldChanges>
-------

I would expect Beliefs that are not properly registered as to "type" would be a prime suspect for intermittent / rando CTD.

I'm also not following what function they would achieve if not selectable, therefore why add to the mix of possible reasons the game is crashing ?
 
Last edited:
Multiple Cities each getting a copy of BUILDING_DUMMY will cause stacking effects on the Shrine-Class of buildings' yields, but a single city with 15 copies of BUILDING_DUMMY will only add 1 yield to Shrine-Class buildings:
That is some weird horsehockey right there. Thanks for telling me, probably never would have figured that out on my own.
I would expect Beliefs that are not properly registered as to "type" would be a prime suspect for intermittent / rando CTD.
Well then I guess I know what to begin scrutinizing.
I'm also not following what function they would achieve if not selectable, therefore why add to the mix of possible reasons the game is crashing ?
They are selectable, just not as Primary (Major Deity) Beliefs. Part of my mod allows you to select up to 3 additional, weaker, Pantheon Beliefs before founding a Religion. This part of my also removes the base game's Beliefs, and adds 22 Beliefs that can be chosen as a 1st (Regular Pantheon) Belief, and an additional 22 (Rituals, null-type LandBarbarianConversionPercent -1) Beliefs that are added to the pool of selectable Beliefs when choosing secondary, tertiary, or quaternary Pantheon Beliefs.
 
If it were me I'd create an entirely new table to hold these not-Beliefs rather than trying to subborn the game's Religion systems into using a new system it is not even remotely coded to handle. You're going to have to re-write the religions screen lua files anyway to handle these extra choices, so you may as well remove the potential CTD issue by removing odd-defined "beliefs" from the Beliefs table. And you'd have to write "directing" code for the AI in order for them to use the system anyway, so there again is no real need for the extra issues of having oddball definitions in the Beliefs table.

The game's religions and belief systems are one of Civ5's "Third Rail" systems -- touch it in order to alter how it works, and your mod dies.
 
If it were me I'd create an entirely new table to hold these not-Beliefs rather than trying to subborn the game's Religion systems into using a new system it is not even remotely coded to handle. You're going to have to re-write the religions screen lua files anyway to handle these extra choices, so you may as well remove the potential CTD issue by removing odd-defined "beliefs" from the Beliefs table. And you'd have to write "directing" code for the AI in order for them to use the system anyway, so there again is no real need for the extra issues of having oddball definitions in the Beliefs table.

The game's religions and belief systems are one of Civ5's "Third Rail" systems -- touch it in order to alter how it works, and your mod dies.

Actually all the necessary Ui is there to choose additional Beliefs, and I've already rewritten the ReligionOverview files and written the necessary code for the AI to pick 2nd, 3rd, and 4th Beliefs. I've also been extensively testing the Pantheons module for the last couple of days, after 15+ uncrashed games I'm coming to the conclusion that it's not that particular module that's causing CTDs. Frustrating.
 
Last edited:
Thanks for the suggestion ThanOscar! That actually looks like something that would be quite useful. I was following this tutorial: https://github.com/LoneGazebo/Community-Patch-DLL/issues/1432
when I realized that my dll changes are miniscule and Gazebo went through them while incorporating them into the CP and din't find anything horrible, and the mod seemed to be stable with just the DLL modded part, so I just started disabling parts of the mod one by one and running test games.

I thought I'd caught it here:

Code:
function Iska_WaW_HW_CityCaptured(hexPos, playerID, cityID, newPlayerID)
    local pPlot = Map.GetPlot( ToGridFromHex( hexPos.x, hexPos.y ) );
    if pPlot:GetPlotCity() == nil then return end
    local city = pPlot:GetPlotCity()
    --if Iska_HW_Debug then print("Pre-start 0 code Iska_WaW_HW_CityCaptured: city: " ..  city:GetName()) end
    if city:IsHolyCityAnyReligion() then
        if Iska_HW_Debug then print("Pre-start 1 code Iska_WaW_HW_CityCaptured: city: " ..  city:GetName()) end
        local defrel
        for row in GameInfo.Religions() do
            if city:IsHolyCityForReligion(row.ID) then
                defrel = row.ID
                break
            end
        end
        --if Iska_HW_Debug then print("Pre-start 2 code Iska_WaW_HW_CityCaptured: city: " ..  city:GetName()) end
        for row in GameInfo.Religions() do
            --if row.ID ~= nil then
                --if Game.GetFounder(row.ID, -1) ~= nil then
                    if Iska_HW_Debug then print("Start code Iska_WaW_HW_CityCaptured: city: " ..  city:GetName()) end

                    if g_PlayerActiveHolyWar[defrel .. "ActiveHolyWarWith" .. row.ID] or g_PlayerActiveHolyWar[row.ID .. "ActiveHolyWarWith" .. defrel] then
                        Iska_WaW_SetValue(defrel .. "ActiveHolyWarWith" .. row.ID, nil)
                        g_PlayerActiveHolyWar[defrel .. "ActiveHolyWarWith" .. row.ID] = nil
                        g_PlayerActiveHolyWar[row.ID .. "ActiveHolyWarWith" .. defrel] = nil
                        Iska_WaW_SetValue(row.ID .. "ActiveHolyWarWith" .. defrel, nil)
                        Iska_WaW_SetValue(Game.GetFounder(defrel, -1) .. "ActiveHolyWar", nil)
                        Iska_WaW_SetValue(Game.GetFounder(row.ID, -1) .. "ActiveHolyWar", nil)
                        g_PlayerActiveHolyWar[Game.GetFounder(defrel, -1)] = nil
                        g_PlayerActiveHolyWar[Game.GetFounder(row.ID, -1)] = nil

                        local hplayer = Players[Game.GetActivePlayer()]
                        local player = Players[newPlayerID]
                        local oplayer = Players[playerID]

                        if Players[newPlayerID]:GetReligionCreatedByPlayer() == row.ID then
                            local decrel = row.ID
                            if Iska_HW_Debug then print("The Holy Armies of " .. GameInfo.Religions[decrel].IconString .. " " .. Locale.Lookup(GameInfo.Religions[decrel].Description) .. " have captured " .. city:GetName() .. ", the Holy City of  " .. GameInfo.Religions[defrel].IconString .. " " .. Locale.Lookup(GameInfo.Religions[defrel].Description) .. "! The Holy War of " .. GameInfo.Religions[decrel].IconString .. " " .. Locale.Lookup(GameInfo.Religions[decrel].Description) .. " has ended.") end
                            if player == hplayer or oplayer == hplayer or hplayer:HasReligionInMostCities(oplayer:GetReligionCreatedByPlayer()) or hplayer:HasReligionInMostCities(player:GetReligionCreatedByPlayer())
                            or Teams[hplayer:GetTeam()]:IsHasMet(player:GetTeam()) or Teams[hplayer:GetTeam()]:IsHasMet(oplayer:GetTeam()) then
                                local sTitle = Locale.Lookup("TXT_KEY_ISKA_HOLY_WAR_ENDED_TITLE")
                                local sText = Locale.ConvertTextKey("TXT_KEY_ISKA_HOLY_WAR_ENDED_CAPTURE_OTHER_DESC", city:GetName(), GameInfo.Religions[defrel].IconString, Locale.Lookup(GameInfo.Religions[defrel].Description), GameInfo.Religions[row.ID].IconString, Locale.Lookup(GameInfo.Religions[row.ID].Description))
                                player:AddNotification(NotificationTypes.NOTIFICATION_RELIGION_FOUNDED, sText, sTitle)
                            end
                            Players[newPlayerID]:ChangeFaith(1000)
                            Events.AddPopupTextEvent(HexToWorld(ToHexFromGrid(Vector2(Players[newPlayerID]:GetCapitalCity():GetX(),Players[newPlayerID]:GetCapitalCity():GetY()))), Locale.Lookup("TXT_KEY_ISKA_HOLY_WAR_ENDED_CELEBRATIONS") .. 1000 .. " [ICON_PEACE] Faith", 0)
                        else
                            if Iska_HW_Debug then print("The Holy City of " .. Locale.Lookup(GameInfo.Religions[defrel].Description) .. " has fallen! The Holy War of " .. Locale.Lookup(GameInfo.Religions[row.ID].Description) .. " has ended.") end
                            local sTitle = Locale.Lookup("TXT_KEY_ISKA_HOLY_WAR_ENDED_TITLE")
                            local sText = Locale.ConvertTextKey("TXT_KEY_ISKA_HOLY_WAR_ENDED_CAPTURE_PLAYER_DESC", city:GetName(), GameInfo.Religions[defrel].IconString, Locale.Lookup(GameInfo.Religions[defrel].Description), GameInfo.Religions[row.ID].IconString, Locale.Lookup(GameInfo.Religions[row.ID].Description))
                            if player == hplayer or oplayer == hplayer or hplayer:HasReligionInMostCities(oplayer:GetReligionCreatedByPlayer()) or hplayer:HasReligionInMostCities(player:GetReligionCreatedByPlayer())
                            or Teams[hplayer:GetTeam()]:IsHasMet(player:GetTeam()) or Teams[hplayer:GetTeam()]:IsHasMet(oplayer:GetTeam()) then
                                hplayer:AddNotification(NotificationTypes.NOTIFICATION_RELIGION_FOUNDED, sText, sTitle)
                            end
                            if Players[newPlayerID]:GetCapitalCity():GetReligiousMajority() == row.ID then
                                Players[newPlayerID]:ChangeFaith(750)
                                Events.AddPopupTextEvent(HexToWorld(ToHexFromGrid(Vector2(Players[newPlayerID]:GetCapitalCity():GetX(),Players[newPlayerID]:GetCapitalCity():GetY()))), Locale.Lookup("TXT_KEY_ISKA_HOLY_WAR_ENDED_CELEBRATIONS") .. 750 .. " [ICON_PEACE] Faith", 0)
                            end
                        end
                    end
                    if Iska_HW_Debug then print("End Iska_WaW_HW_CityCaptured.") end
                end
            --end
        --end
    end
 end
 Events.SerialEventCityCaptured.Add(Iska_WaW_HW_CityCaptured)

with the two bits of code that are commented out, because that almost certainly seemed to be causing a crash. But then I got another crash, so party's still going.
 
Yes, the other ctd was another use of Game.GetFounder(). Seems to be a buggy lua function. (method? idk what to call this)

Muahaha my mod is now bug free!!
 
Back
Top Bottom