Guide to event modding in BtS

Solver,

I am playing around with the idea of adding some new events....I scanned your Events modding guide surreptitiously at work this afternoon. I had a couple of questions:

1.) Is there a way to force a civics change for five turns along the lines of the espionage change government mission as a result of an event via XML? Or is this something that can only be done via Python?

2.) Is there a way to specify multiple civics as a trigger -- e.g., must be running UNIVERSAL_SUFFRAGE and ENVIRONMENTALISM for the event to be triggered?

3.) Can multiple cities be selected as the object of an event? I am thinking here, for example, of specifying all cities on a different continent that is NOT the location of the civ's palace as being the object of a certain event.

4.) Can I specify a turn limit for the duration of an extra bonus granted to a plot via <PlotExtraYields>? I want to decrease food output in a given plot by 1, but only for 20 turns.
 
1.) Is there a way to force a civics change for five turns along the lines of the espionage change government mission as a result of an event via XML? Or is this something that can only be done via Python?

Python only.

2.) Is there a way to specify multiple civics as a trigger -- e.g., must be running UNIVERSAL_SUFFRAGE and ENVIRONMENTALISM for the event to be triggered?

Yeah, but... Python only ;)

3.) Can multiple cities be selected as the object of an event? I am thinking here, for example, of specifying all cities on a different continent that is NOT the location of the civ's palace as being the object of a certain event.

Yeah, with Python again ;) You can then set up multiple cities according to some criteria you want.

4.) Can I specify a turn limit for the duration of an extra bonus granted to a plot via <PlotExtraYields>? I want to decrease food output in a given plot by 1, but only for 20 turns.

No. You can, though, create a second event that will fire 20 turns later and add +1 food, to effectively achieve what you want. I haven't tried if it works with plot events though.
 
Python only.



Yeah, but... Python only ;)



Yeah, with Python again ;) You can then set up multiple cities according to some criteria you want.



No. You can, though, create a second event that will fire 20 turns later and add +1 food, to effectively achieve what you want. I haven't tried if it works with plot events though.

I have to admit, all of those answers were what I suspected. Can you point me in the right direction concerning the appropriate Python scripting for forcing a civics change? Could I re-use the code from the force civics espionage mission? I am coming up with some new events, and I think it's important for one group of them in particular to have a forced civics change as an option.

I will give the delayed event thing a try and let you know how that works.
 
I've noticed in some modded events files that there may be multiple <TriggerTexts> given, all set to NONE regarding the era. When the event triggers, will one of these be chosen randomly, or only the first one? How does that work?

Thanks.
 
I have not verified this with 100% reliability (read: in the SDK), but I believe that manually triggering an event is slightly different, and not taking the Civic requirement into account is one thing I've noticed.


I've noticed that if you actually put the Civic requirements in CvRandomEventInterface.py instead of using the XML, the civic requirements will be enforced even when manually triggering the event in-game.

Also -- I noticed something else. If you put down a certain building as a prerequisite of a trigger (in my case, it was broadcast towers), and the subject civ has constructed a wonder that gives one instance of each of those buildings in every city for free (e.g., Eiffel Tower), then the event will not trigger. I decided to leave my event as-is (if you didn't get Eiffel, you might as well have the advantage of getting this specific event, I figured), but this is something useful to know.
 
Hello, all

I am pleased to announce that thanks in no small part to the help Solver provided in this thread and elsewhere, I have released a BETA test version of my new events. Please feel free to check it out in this thread:

http://forums.civfanatics.com/showthread.php?t=251885
 
Hello everyone...

How does iAIValue work?

I'm asking because I've fashioned an event that allows one to use settlers to add population to cities, but I'm wondering how the AI makes a decision regarding this....I fashioned the event to show whether or not the population was added, and the AI actually sometimes does and sometimes does not add (trigger set to always firing), but I'm trying to understand the dynamics behind this...

Thanks in advance
 
I have what may be a stupid question, but I feel the need to post it here:

I'm trying to program in an event called "Levittown", that represents suburbanization. The event finds a cottage or a hamlet with a railroad route, and then upgrades it instantly into a village.

I think I have it programmed correctly, but I cannot get the event to occur in the game, ever. I don't know how to manually trigger events, so I have been setting the percentage in game to 100%, and turning the weight to 5 million or some other absurdly high number. Then, I start a game, open Worldbuilder, put down what should trigger the event, and hit the enter button until I get the event triggered. Although this has worked for my other events, the last one I have programmed doesn't seem to trigger, despite being given over 120 turns.

Here's the trigger and event info:

Spoiler :
<EventTriggerInfo>
<Type>EVENTTRIGGER_LEVITTOWN</Type>
<WorldNewsTexts>
<Text>TXT_KEY_EVENTTRIGGER_LEVITTOWN</Text>
</WorldNewsTexts>
<TriggerTexts>
<TriggerText>
<Text>TXT_KEY_EVENT_LEVITTOWN</Text>
<Era>NONE</Era>
</TriggerText>
</TriggerTexts>
<bSinglePlayer>0</bSinglePlayer>
<iPercentGamesActive>100</iPercentGamesActive>
<iWeight>9000000</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/>
<iNumBuildings>0</iNumBuildings>
<iNumBuildingsGlobal>0</iNumBuildingsGlobal>
<iNumPlotsRequired>1</iNumPlotsRequired>
<bOwnPlot>1</bOwnPlot>
<iPlotType>-1</iPlotType>
<FeaturesRequired/>
<TerrainsRequired/>
<ImprovementsRequired>
<ImprovementType>IMPROVEMENT_COTTAGE</ImprovementType>
<ImprovementType>IMPROVEMENT_HAMLET</ImprovementType>
</ImprovementsRequired>
<BonusesRequired/>
<RoutesRequired>
<RouteType>ROUTE_RAILROAD</RouteType>
</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_LEVITTOWN_1</Event>
</Events>
<PrereqEvents/>
<bPrereqEventPlot>0</bPrereqEventPlot>
<OrPreReqs/>
<AndPreReqs/>
<ObsoleteTechs/>
<bRecurring>1</bRecurring>
<bTeam>0</bTeam>
<bGlobal>0</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/>
<PythonCanDoCity/>
<PythonCanDoUnit/>
<PythonCallback/>
</EventTriggerInfo>

Spoiler :
<EventInfo>
<Type>EVENT_LEVITTOWN_1</Type>
<Description>TXT_KEY_EVENT_LEVITTOWN_1</Description>
<LocalInfoText/>
<WorldNewsTexts/>
<OtherPlayerPopup/>
<QuestFailText/>
<bQuest>0</bQuest>
<bGlobal>0</bGlobal>
<bTeam>0</bTeam>
<bPickCity>1</bPickCity>
<bPickOtherPlayerCity>0</bPickOtherPlayerCity>
<bDeclareWar>0</bDeclareWar>
<iGold>0</iGold>
<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>
<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/>
<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>IMPROVEMENT_VILLAGE</ImprovementType>
<iImprovementChange>1</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/>
<PythonExpireCheck/>
<PythonCanDo/>
<PythonHelp/>
<Button>,Art/Interface/Buttons/Process/Blank.dds,Art/Interface/Buttons/Beyond_the_Sword_Atlas.dds,8,5</Button>
<iAIValue>1000</iAIValue>
</EventInfo>


Maybe I'm just a little nutty and forgot something, but I'll walk through the steps I made:

For the Trigger...

<iNumPlotsRequired> and <bOwnPlot> should both be 1, so that it selects a plot that meets my criteria below that belongs to affected player.

The <ImprovementsRequired> tag should have both Cottages and Hamlets, and <RoutesRequired> should have Railroads, so that my trigger conditions are met.

<bRecurring> is set to 1 so the event may happen more than once.

<bPickCity> is currently set to 1...I'm not too sure about this one. I looked at other events that affected plots near cities, and some had this set to 1. I went ahead and set it to 1 as well.

<bShowPlot> is set to 1, so that you know which plot was affected.

For the Event itself...

<bPickCity> is set to 1, just to match the previous file. Again, unsure about this one.

<ImprovementType> and <iImprovementChange> are selected so that a village will be placed in the selected plot.


So, I guess one of my questions is when do you use the <PickCity> = 1 in conjunction with finding a plot, or will that not work? The second question I have is why the event is not even triggering...even if the event information did not work, I think the trigger itself would still work and give me something in the game. Therefore, I'm concluding that the trigger mechanism is flawed. Is there any guidance anyone can give on how to make an event that selects a particular plot and places an improvement?
 
You do not trigger an event artificially using WorldBuilder (although it may be necessary to use WorldBuilder to setup the event's prerequisites that way.) Instead, you need to use the Python Console. You bring this up by hitting the "~" key. [In other words: SHIFT+`]

Once it is up, you need to find the list number that is assigned to the new event. Do this in the following manner:

Code:
num = gc.getInfoTypeForString("EVENTTRIGGER_[YOUR RANDOM EVENT NAME HERE]") 
print num

If you get "-1" as a number, there was an error. Go check to see what's wrong in the Eventtriggerinfos.XML file.

Next, assign the variable "p" to player zero (i.e., in single player games, the Human player):

Code:
p = gc.getPlayer(0)

Then trigger the event:

Code:
p.trigger(num)

Yes, you have to type all of that in each time. As far as I can tell, there's no way to copy and paste into the python console. Don't worry, after debugging about 50 times, you'll memorize it.

By the way, unless you alter the order of the events in the EventTriggerInfos.XML file later, the list number won't change, so if you remember it, you won't have to do the "gc.getInfoTypeForString("EVENTTRIGGER_[YOUR RANDOM EVENT NAME HERE]" line. You can just insert it directly into the Trigger command.

The list numbers should go in sequential order...although in my mod, the numbers jumped from 210 to 212 for no obvious reason. So always check it the first time you test an event.



Solver posted on this earlier in the thread if you want to read his comments:


http://forums.civfanatics.com/showpost.php?p=5658815&postcount=4

And pick city + show plot should work.
 
That is most odd; I thought I had read through all his early posts, but I must have missed that part.

Thanks for your help! The manual trigger looks much easier for playtesting than my artificial method.
 
Hello everyone...

How does iAIValue work?

I'm asking because I've fashioned an event that allows one to use settlers to add population to cities, but I'm wondering how the AI makes a decision regarding this....I fashioned the event to show whether or not the population was added, and the AI actually sometimes does and sometimes does not add (trigger set to always firing), but I'm trying to understand the dynamics behind this...

Thanks in advance

It makes the AI prefer that particular choice, if set to a higher value. Say, you have a trigger that offers two choices. If you set the iAIValue to 1500 for one choice, the AI will almost always go for that choice when hit with this event.
 
It makes the AI prefer that particular choice, if set to a higher value. Say, you have a trigger that offers two choices. If you set the iAIValue to 1500 for one choice, the AI will almost always go for that choice when hit with this event.

Thanks Solver! :) So maybe the settler add population mini mod can work using just XML....back to the lab! :borg:
 
I want to add a new condition for events. What I'm thinking is that each time a particular unit type is killed, it will trigger an event. The actual coding is fairly straightforward for someone like me who has experience with the SDK...

What I'm debating though is whether this additional condition will need to be triggered from a different part of the code. Currently, each turn the game runs through the events and checks whether the conditions have been met to do the event.

However, for a trigger to be activated on a unit's death (rather than the following turn when the events are processed next), you'd have to make it so that when a unit dies, the game runs through to check the event triggers to see if that unit's death is required to activate a trigger and if so, then to trigger the event immediately.

A few other changes and ideas I've got bouncing around are the following:

I've noticed that there doesn't seem to be any game-wide events. I'm not sure how I'd implement this, but I'd like to see a possibility for events that would cause general changes to the map or to global values rather than to a particular player.

Another thing I'm interested in is having the possibility for a set of possible triggers and varying possibilities. So for example, instead of A leads to B leads to C. You'd have A leading to either B or C with a greater chance of B occurring.

Basically, I want to use this to make it so that every time a particular unit dies, there's a set of choices that will come up, but I don't want it to make it somewhat random to prevent players from knowing exactly which options he will get to choose from.
 
I've noticed that there doesn't seem to be any game-wide events. I'm not sure how I'd implement this, but I'd like to see a possibility for events that would cause general changes to the map or to global values rather than to a particular player.

Yeah, I found that out trying to make a global plague....even though I don't know Python or using the SDK, I would nonetheless like to see the code that would be used in something like this and maybe try to somehow splice it into files I have
 
Dom Pedro, I wouldn't make those events triggered in the middle of a turn. If it just happens for a couple of events, that would be pretty confusing. I would keep that stuff until the next turn as well.
 
Hi Solver -- I have a question about ClearEvents:

You said:

ClearEvents- if non-empty, specifies the events which get reset and the probability of that happening. For example:
Code:
[FONT=&quot]<ClearEvents> [/FONT]
[FONT=&quot] <EventChance> [/FONT]
[FONT=&quot] <Event>EVENT_DUSTBOWL_2</Event> [/FONT]
[FONT=&quot] <iEventChance>100</iEventChance> [/FONT]
[FONT=&quot] </EventChance> [/FONT]
[FONT=&quot]</ClearEvents>[/FONT]

This resets the EVENT_DUSTBOWL_2 unconditionally, which means that the event is considered to not have occurred.


But I notice that the DUSTBOWL event seems to imply that the event will 'loop'. So is the "eventchance" the chance of the event being triggered again? Or is it a chance that the specific event choice (i.e., EVENT_DUSTBOWL_2) will occur immediately on the next turn?
 
It's a good question. ClearEvents is one of the attributes I haven't played with personally, but I believe it's the chance of the game forgetting that this event has ever occurred.

Dustbowl is one of the events that can loop/continue, along with Bandits and something else. Normally, EVENTTRIGGER_DUSTBOWL fires. However, if you choose EVENT_DUSTBOWL_2 when it first does (ignore the problem), EVENTTRIGGER_DUSTBOWL_CONT will fire. If you then choose EVENT_DUSTBOWL_1 (fix the problem), the game forgets you ever ignored the problem - therefore, EVENTTRIGGER_DUSTBOWL_CONT won't trigger because EVENT_DUSTBOWL_2, its prerequisite, is considered to never have happened.
 
Here's a question regarding "additional events"--every time I create an event that uses the additional events feature, it seems to crash.

In one instance, playing around with my Levittown event above, I've found that if I can simply destroy the cottage or hamlet, no problem. However, the game apparently does not recognize there is an additional event tacked on with 100% chance of occurring that places a village on the tile.

The other instance is most unusual: the moment the event is triggered (and I know it is triggered because I hear the sound effect), the game crashes. Disabling the additional event sequence would ruin the event.


So here is a set of questions, I suppose, about the errors I am having:

  • Is the only "link" needed for the additional event the "AdditionalEvents" tag? Or is there some other link required? From looking at other events that use the additional events tag, I know I do not list it in the trigger. However, when I try to imitate this, the game crashes.
  • Can an event that affects a single city then link, using an additional event, to a benefit that affects your entire civilization? I have a loss of one population point in my "first" event after the trigger, and then multiple ways you can respond. Each one gives you a different percentage chance of the additional event, a +1 health for a building bonus. This second bonus is intended to affect your entire civilization.
  • On an unrelated note, I have developed a series of events that are based around how many and what kind of specialists you are running in a city. To code this in Python, I would need to be able to pull out an integer value representing the number of a particular type of specialists the city is currently running (citizens, merchants, scientists, priests, etc.). Where would I look in the myriad of python files to find the functions I need? Or, more easily, is there a good online reference of the Python functions for a beginner to look at?
 
If you can't resolve a crash, you may want to post the full code of your event here.

AdditionalEvents is sufficient for linking to another event, and it can link to any event. You could link to the airplane crash event from the scientific breakthrough event, if you want to.

The best Python API reference is hosted by us over at Apolyton, AFAIK:

http://civilization4.net/files/modding/PythonAPI/

It's not up to date for BtS but better than nothing. To do what you want, you would use the getSpecialistCount() function of CyCity. You can use getForceSpecialistCount() to ignore specialists that are granted for free (from Great Library and the like).

The above link is a good list of functions. I am not aware of any place that has descriptions of many functions - the API is quite big and that would be an enormous undertaking. When you have questions like that, it's generally just better to ask a modder.
 
Thanks for the link to the reference material on Python--that's exactly what I was looking for. Being that I am just starting to poke around in the Python, and there are a myriad of files, that will make things a 10-fold easier.

I'm going to try one more thing with the crashing event, and if that doesn't work, then I'll post it here. Maybe I'm missing something that is blindingly obvious.
 
Back
Top Bottom