[TUTORIAL] Easily Modding in Python

Louis the XIV

Sun King
Joined
Jun 23, 2020
Messages
837
Location
Court of Versailles
Hello everyone!
I'm not the greatest python modder but
I remember when I started modding and wanted to understand python better in civ 4, so I decided to create a tutorial explaining how to easily create various python scripts via event! Feel free to ask questions.
Credit has to go to Spillsandstains for teaching me how to achieve this and much more!


EVENT 1: Giving Units at a defined location via event

The first event will show you how to give a number of units to a defined civ when certain conditions are met. As an example I will be creating an event that gives some units to the spanish in Mesoamerica.

First go to Assets/XML/Events/CIV4EventInfos.
Then simply copy the forest fire event and paste it under, so you have a base to work with.
Code:
        </EventInfo>
        <EventInfo>
            <Type>EVENT_CONQUISTADORS</Type> #Change this to whatever you want, this defines the #event#
            <Description>Conquistadors</Description> #Change this to what ever you want#
            <LocalInfoText>Conquer Mesoamerica and prove yourself to the Spanish monarchs!</LocalInfoText>
                                         #Above is the text that will appear when the event triggers#
            <WorldNewsTexts>The Spanish have sent a group of explorers to explore the New World!</WorlNewsTexts> #This part is what will appear to every player#
            <OtherPlayerPopup/>
            <QuestFailText/>
            <bQuest>0</bQuest>
            <bGlobal>0</bGlobal>
            <bTeam>0</bTeam>
            <bPickCity>1</bPickCity>  #Has to be 1#
            <bPickOtherPlayerCity>0</bPickOtherPlayerCity>
            <bDeclareWar>0</bDeclareWar>
            <iGold>-300</iGold>  #Let's say the expedition cost 300 gold#
            <bGoldToPlayer>0</bGoldToPlayer>
            <iRandomGold>0</iRandomGold>
            <iCulture>0</iCulture>
            <iEspionagePoints>0</iEspionagePoints>
            <bGoldenAge>0</bGoldenAge>
            <iFreeUnitSupport>0</iFreeUnitSupport>
            <iInflationMod>0</iInflationMod>
            <iSpaceProductionMod>0</iSpaceProductionMod>
            <Tech>NONE</Tech>  #This is not the trigger tech so leave it blank#
            <TechFlavors/>
            <iTechPercent>0</iTechPercent>
            <iTechCostPercent>0</iTechCostPercent>
            <iTechMinTurnsLeft>0</iTechMinTurnsLeft>
            <PrereqTech>NONE</PrereqTech>
            <UnitClass>NONE</UnitClass>
            <iNumFreeUnits>0</iNumFreeUnits>
            <bDisbandUnit>0</bDisbandUnit>
            <iUnitExperience>0</iUnitExperience>
            <iUnitImmobileTurns>0</iUnitImmobileTurns>
            <UnitPromotion/>
            <UnitName/>
            <UnitCombatPromotions/>
            <UnitClassPromotions/>
            <BuildingClass>NONE</BuildingClass>
            <iBuildingChange>0</iBuildingChange>
            <BuildingExtraYields/>
            <BuildingExtraCommerces/>
            <BuildingExtraHappies/>
            <BuildingExtraHealths/>
            <iHappy>0</iHappy>
            <iHealth>0</iHealth>
            <iHurryAnger>0</iHurryAnger>
            <iHappyTurns>0</iHappyTurns>
            <iRevoltTurns>0</iRevoltTurns>
            <iMinPillage>0</iMinPillage>
            <iMaxPillage>0</iMaxPillage>
            <iFood>0</iFood>
            <iFoodPercent>0</iFoodPercent>
            <FreeSpecialistCounts/>
            <FeatureType>NONE</FeatureType>
            <iFeatureChange>0</iFeatureChange>
            <ImprovementType>NONE</ImprovementType>
            <iImprovementChange>0</iImprovementChange>
            <BonusType>NONE</BonusType>
            <iBonusChange>0</iBonusChange>
            <RouteType>NONE</RouteType>
            <iRouteChange>0</iRouteChange>
            <BonusRevealed>NONE</BonusRevealed>
            <BonusGift>NONE</BonusGift>
            <PlotExtraYields/>
            <iConvertOwnCities>0</iConvertOwnCities>
            <iConvertOtherCities>0</iConvertOtherCities>
            <iMaxNumReligions>-1</iMaxNumReligions>
            <iOurAttitudeModifier>0</iOurAttitudeModifier>
            <iAttitudeModifier>0</iAttitudeModifier>
            <iTheirEnemyAttitudeModifier>0</iTheirEnemyAttitudeModifier>
            <iPopulationChange>0</iPopulationChange>
            <AdditionalEvents/>
            <EventTimes/>
            <ClearEvents/>
            <PythonCallback>applyConquistador</PythonCallback> ##This is important for later##
            <PythonExpireCheck/>
            <PythonCanDo/>
            <PythonHelp/>
            <Button>,Art/Interface/Buttons/Process/Blank.dds,Art/Interface/Buttons/Beyond_the_Sword_Atlas.dds,8,5</Button>
            <iAIValue>1001</iAIValue>

So now you have created the event, now it's time for the triggering of the event in Assets/XML/Events/CIV4EventTriggerInfos:

Code:
        <EventTriggerInfo>
            <Type>EVENTTRIGGER_CONQUISTADORS</Type>
            <WorldNewsTexts>
                <Text>The Spanish are exploring the New World!</Text>
            </WorldNewsTexts>
            <TriggerTexts>
                <TriggerText>
                    <Text>Wow great!</Text>
                    <Era>NONE</Era>
                </TriggerText>
            </TriggerTexts>
            <bSinglePlayer>0</bSinglePlayer>
            <iPercentGamesActive>100</iPercentGamesActive>
            <iWeight>-1</iWeight>
            <bProbabilityUnitMultiply>0</bProbabilityUnitMultiply>
            <bProbabilityBuildingMultiply>0</bProbabilityBuildingMultiply>
            <Civic>NONE</Civic>
            <iMinTreasury>0</iMinTreasury>
            <iMinPopulation>0</iMinPopulation>
            <iMaxPopulation>0</iMaxPopulation>
            <iMinMapLandmass>0</iMinMapLandmass>
            <iMinOurLandmass>0</iMinOurLandmass>
            <iMaxOurLandmass>-1</iMaxOurLandmass>
            <MinDifficulty>NONE</MinDifficulty>
            <iAngry>0</iAngry>
            <iUnhealthy>0</iUnhealthy>
            <UnitsRequired/>
            <iNumUnits>0</iNumUnits>
            <iNumUnitsGlobal>0</iNumUnitsGlobal>
            <iUnitDamagedWeight>0</iUnitDamagedWeight>
            <iUnitDistanceWeight>0</iUnitDistanceWeight>
            <iUnitExperienceWeight>0</iUnitExperienceWeight>
            <bUnitsOnPlot>0</bUnitsOnPlot>
            <BuildingsRequired>
                <BuildingClass>NONE</BuildingClass>
            </BuildingsRequired>
            <iNumBuildings>0</iNumBuildings>
            <iNumBuildingsGlobal>0</iNumBuildingsGlobal>
            <iNumPlotsRequired>0</iNumPlotsRequired>
            <bOwnPlot>1</bOwnPlot>
            <iPlotType>-1</iPlotType>
            <FeaturesRequired/>
            <TerrainsRequired/>
            <ImprovementsRequired/>
            <BonusesRequired/>
            <RoutesRequired/>
            <ReligionsRequired/>
            <iNumReligions>0</iNumReligions>
            <CorporationsRequired/>
            <iNumCorporations>0</iNumCorporations>
            <bPickReligion>0</bPickReligion>
            <bStateReligion>0</bStateReligion>
            <bHolyCity>0</bHolyCity>
            <bPickCorporation>0</bPickCorporation>
            <bHeadquarters>0</bHeadquarters>
            <Events>
                <Event>EVENT_CONQUISTADORS</Event> #Remember the tag for the event#
            </Events>
            <PrereqEvents/>
            <bPrereqEventPlot>0</bPrereqEventPlot>
            <OrPreReqs/>
            <AndPreReqs>
                <PrereqTech>TECH_ASTRONOMY</PrereqTech>#The Trigger Tech#
            </AndPreReqs>
            <ObsoleteTechs>
                <ObsoleteTech>TECH_COMBUSTION</ObsoleteTech> #Whatver#
            </ObsoleteTechs>
            <bRecurring>0</bRecurring>
            <bTeam>0</bTeam>
            <bGlobal>1</bGlobal>
            <bPickPlayer>0</bPickPlayer>
            <bOtherPlayerWar>0</bOtherPlayerWar>
            <bOtherPlayerHasReligion>0</bOtherPlayerHasReligion>
            <bOtherPlayerHasOtherReligion>0</bOtherPlayerHasOtherReligion>
            <bOtherPlayerAI>0</bOtherPlayerAI>
            <iOtherPlayerShareBorders>0</iOtherPlayerShareBorders>
            <OtherPlayerHasTech>NONE</OtherPlayerHasTech>
            <bPickCity>1</bPickCity>
            <bPickOtherPlayerCity>0</bPickOtherPlayerCity>
            <bShowPlot>1</bShowPlot>
            <iCityFoodWeight>0</iCityFoodWeight>
            <PythonCanDo>canTriggerConquistadors</PythonCanDo>
            <PythonCanDoCity/>
            <PythonCanDoUnit/>
            <PythonCallback/>
        </EventTriggerInfo>

Ok, so until now you have accomplished that the event will subtract 300 gold from the player so as to finance the expedition, and the event will trigger once Astronomy is discovered.
Now it's time to give the units, define that only Spain can get this, and where the units should go.
The following goes into Assets/Python/EntryPoints/CvRandomEventInterface:

Code:
######## Conquistador Event ########

def canTriggerConquistador(argsList):  ##Remember that that's the tag##
    kTriggeredData = argsList[0]
    player = gc.getPlayer(kTriggeredData.ePlayer)

    if (player.getCivilizationType() == gc.getInfoTypeForString("CIVILIZATION_SPAIN")):  ##Defines the Civilization
        return True

    return False

def applyConquistadors(argsList):  ##Remember from the EventInfos.xml##
    iEvent = argsList[0]
    kTriggeredData = argsList[1]

    player = gc.getPlayer(kTriggeredData.ePlayer)
    plot = gc.getMap().plot(1, 1) ##THE COORINATES##
 
    iUnitType = CvUtil.findInfoTypeNum(gc.getUnitInfo, gc.getNumUnitInfos(), 'UNIT_SPANISH_CONQUISTADOR') #######The Units, here are 3 conquistadors, 1 explorer#
    player.initUnit(iUnitType, plot.getX(), plot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
    player.initUnit(iUnitType, plot.getX(), plot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
    player.initUnit(iUnitType, plot.getX(), plot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)
    iUnitType = CvUtil.findInfoTypeNum(gc.getUnitInfo, gc.getNumUnitInfos(), 'UNIT_EXPLORER')
    player.initUnit(iUnitType, plot.getX(), plot.getY(), UnitAITypes.NO_UNITAI, DirectionTypes.DIRECTION_SOUTH)

To have a better look I uploaded a txt file with all of this so you can have a better view.

I will post the next tutorial in the weekend on how to make specific civs declare war on each other once certain conditions are met.

P.S. Also feel free to ask me anything but just so you know I might not be able to answer everything.
 

Attachments

  • Conquistador Event.txt
    7.8 KB · Views: 82
Last edited:
Top Bottom