Quick Modding Questions Thread

Hello World! How to replace the reward that is given for capturing a city with gold instead of technology? The fact is that I turned off technology trading, turned off technology self-distribution, but I just started fighting more and got an incredible advantage again. I want it to be more complicated, I want it without light technologies. This is better than increasing the difficulty by turning a computer opponent into a cheater.
 
Seeing that you've been playing Rise of Mankind, this sounds like the (Enhanced) Tech Conquest mod component. Looks like one way to disable that is to remove
Code:
<events module="CvEnhancedTechConquestEventManager"></events>
from \Assets\Config\init.xml. Or else to sabotage one of the scripts in \Assets\Python\EnhancedTechConquestUtils somehow. Could also add a check for the "No Tech Trading" option there.
 
Seeing that you've been playing Rise of Mankind, this sounds like the (Enhanced) Tech Conquest mod component. Looks like one way to disable that is to remove
Code:
<events module="CvEnhancedTechConquestEventManager"></events>
from \Assets\Config\init.xml. Or else to sabotage one of the scripts in \Assets\Python\EnhancedTechConquestUtils somehow. Could also add a check for the "No Tech Trading" option there.
I deleted it, now a little gold comes as before, but it is not registered in the chat how much, which, however, does not matter
 
Great that it mostly worked. The amount of gold is normally shown (only) in the "Would you like to keep it" popup that allows razing the conquered city.
A small clarification. There is no pop-up window when taking a city in this mod, since it is impossible to demolish a city by default with a message. A robbery is being done.
 
I've done some preliminary work for a BTS mod that adds civ-unique techs and religions (using only xml and python) that so far has incorporated another mod I made (Normable), but now I want them to be separate (to reach a greater audience) yet easily combined. I could deliver three mods (third being the combination), but this seems impractical for updates (especially if I decide later to add more mods to the family).

Since both mods use some of the same xml files (e.g. Civ4UnitInfos) but different tags, looks like modular loading is the way to go, though I can't determine if the default system (in 3.19) will be sufficient. The only alternative I've come across is WoC but am unconvinced it is worth the hassle of incorporating. Are there any other modular loading systems I should consider?
 
I've done some preliminary work for a BTS mod that adds civ-unique techs and religions (using only xml and python) that so far has incorporated another mod I made (Normable), but now I want them to be separate (to reach a greater audience) yet easily combined. I could deliver three mods (third being the combination), but this seems impractical for updates (especially if I decide later to add more mods to the family).

Since both mods use some of the same xml files (e.g. Civ4UnitInfos) but different tags, looks like modular loading is the way to go, though I can't determine if the default system (in 3.19) will be sufficient. The only alternative I've come across is WoC but am unconvinced it is worth the hassle of incorporating. Are there any other modular loading systems I should consider?
After scouring the forums more (and stubbornly performing some trial and error), I've determined getting all files from a sufficiently complex mod into a single plug-and-play module is impossible without significant DLL changes (which I'm hoping to avoid). Particularly, the problem points are removing xml entries (e.g. VICTORY_DIPLOMATIC from CIV4VictoryInfo.xml) and using python.
 
After scouring the forums more (and stubbornly performing some trial and error), I've determined getting all files from a sufficiently complex mod into a single plug-and-play module is impossible without significant DLL changes (which I'm hoping to avoid). Particularly, the problem points are removing xml entries (e.g. VICTORY_DIPLOMATIC from CIV4VictoryInfo.xml) and using python.
I've decided to keep all victories and add an option which allows AP and UN to be built without diplomatic victory. This has been accomplished with a duplicate set of building classes/types (changing VictoryPrereq) and diplo/vote types (with victory removed).

It all works as expected unless both "Diplomatic" and "(AP and UN) No Diplomatic" victories are selected which allows two instances of AP and UN each to be built.
This is a nonissue in CUSTOM GAME since the user can easily toggle to a valid state, but becomes a problem in PLAY NOW since it seems only the user-defined ini file can control the victory defaults.

VictoryConditions only seems to work in "\Documents\My Games\beyond the sword\CivilizationIV.ini".
Attempts to override it in "\beyond the sword\MODS\Normable 1.1\Normable 1.1.ini" and a new ini "\beyond the sword\MODS\Normable 1.1\CivilizationIV.ini" have failed.

Any ideas?
 

Attachments

  • Normable_Victories_Invalid.png
    Normable_Victories_Invalid.png
    14.1 KB · Views: 5
  • Normable_Victories_Valid0.png
    Normable_Victories_Valid0.png
    14 KB · Views: 6
  • Normable_Victories_Valid1.png
    Normable_Victories_Valid1.png
    13.9 KB · Views: 6
  • Normable_Victories_Valid2.png
    Normable_Victories_Valid2.png
    13.9 KB · Views: 5
True, and it would be preferable to have it as a standard option instead of a victory, although my impression has been that requires DLL changes. Is there an xml/python only solution you can point me towards?
 
I've decided to keep all victories and add an option which allows AP and UN to be built without diplomatic victory. This has been accomplished with a duplicate set of building classes/types (changing VictoryPrereq) and diplo/vote types (with victory removed).

It all works as expected unless both "Diplomatic" and "(AP and UN) No Diplomatic" victories are selected which allows two instances of AP and UN each to be built.
This is a nonissue in CUSTOM GAME since the user can easily toggle to a valid state, but becomes a problem in PLAY NOW since it seems only the user-defined ini file can control the victory defaults.

VictoryConditions only seems to work in "\Documents\My Games\beyond the sword\CivilizationIV.ini".
Attempts to override it in "\beyond the sword\MODS\Normable 1.1\Normable 1.1.ini" and a new ini "\beyond the sword\MODS\Normable 1.1\CivilizationIV.ini" have failed.

Any ideas?
I resolved it by treating the invalid state as a random option instead, creating disabled special building types for each AP and UN, and enabling one pair randomly with makeSpecialBuildingValid. Now I just have to clean up the gui.
 
Moderator Action: Please stop repeating the same question - this is considered spam.
 
Last edited:
Figuring out exactly the RNG call that corresponds to a particular leader should be possible, but sounds like a lot of trial and error. Probably easier and cleaner to use CvInitCore::setLeader to overwrite the assignments made by the EXE. That'll involve reimplementing the logic for enumerating the valid leaders for a given civ (really just need to go through all leaders and check CvCivilizationInfo::isLeaders for each, I think), and the timing is a bit tricky: The EXE needs to be finished with its civ and leader randomization, but the trait effects shouldn't already have been cached (CvPlayer::init). In my mod, I do it immediately when the final setLeader call from the EXE happens: CvInitCore::setLeaderExternal
Edit: Re-reading my code, I think it's really crucial to do the re-assignment immediately because, otherwise, the EXE won't sychronize the assignments in network games.

The re-routing of external calls (coming from the EXE) to setLeaderExternal (instead of setLeader) happens through the mod's def file passed to the linker through the /def option here. I don't think you'd need to worry about my Civ/LeaderRandomlyChosen functions (and synchronizing that info in network games); I only keep track of that – iirc – because I want my Settings screen to show which leaders were chosen manually and which ones randomly. Here is where I check CvCivilizationInfo::isLeaders. I've changed the algorithm so that leaders are chosen directly - rather than first civs and then leaders -, so most of the surrounding code is probably not useful or necessary for what you're attempting. Edit: This little trick for setting up the synchronized RNG could be handy.
 
Last edited:
Would it be in any way possible to give leaders a different weight for selection, or is too much of the random selection code inaccessible within the exe?

I came across this piece of information: https://forums.civfanatics.com/threads/advanced-civ.614217/post-15921604 and f1rpo states that the random number generation is handled by the DLL... but that's likely not enough to work with, right?
An easier (dumber) solution is to make hidden copies of leaderhead entries in the xml. A civ with 2 leader options, A with 3 copies and B with 2 copies will have 60% chance to start the game with leader A and only 40% for B.
Of course you will also want to disable and hide Unristrected leaders option.
 
I need to check if a tech was acquired by trade in python, assuming that's even possible.

This is what I've tried using deals, but none of the trade item types are "TRADE_TECHNOLOGIES" after trading techs even though that is listed as a TradeableItem.

Python:
    def onTechAcquired(self, argsList):
        iTechType, iTeam, iPlayer, bAnnounce = argsList
        
        bTechFromTrade = False
        for iDeal in range(game.getNumDeals()):
            pDeal = game.getDeal(iDeal)
            if (pDeal.getFirstPlayer() == iPlayer):
                for iTrade in range(pDeal.getLengthFirstTrades()):
                    pTrade = pDeal.getFirstTrade(iTrade)
                    if (str(pTrade.ItemType) == "TRADE_TECHNOLOGIES" and pTrade.iData == iTechType):
                        bTechFromTrade = True
                        break
            elif (pDeal.getSecondPlayer() == iPlayer):
                for iTrade in range(pDeal.getLengthSecondTrades()):
                    pTrade = pDeal.getSecondTrade(iTrade)
                    if (str(pTrade.ItemType) == "TRADE_TECHNOLOGIES" and pTrade.iData == iTechType):
                        bTechFromTrade = True
                        break
            else:
                continue
            if (bTechFromTrade):
                break

Checking the deals later (in case onTechAcquired executes before the deal is recorded) also turn up nothing.

Anyone know whether this can be done in python, and if so, how?
 
I haven't checked this myself, but "pTrade.ItemType" should be an enum type, which is essentially a wrapper of integer values. TRADE_TECHNOLOGIES equals 10, but when you cast it to a string you will get "10" instead of the expected "TRADE_TECHNOLOGIES". The better way of doing this would be to check for equality with the enum value directly:
Python:
if pTrade.ItemType == TradeableItems.TRADE_TECHNOLOGIES:
    ...
The TradeableItems enum should be available in Python - if it isn't, your best bet is to go via integers:
Python:
TRADEABLE_ITEM_TRADE_TECHNOLOGIES = 10

if int(pTrade.ItemType) == TRADEABLE_ITEM_TRADE_TECHNOLOGIES:
    ...
 
Top Bottom