1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

HOW TO: BTS non-random Events

Discussion in 'Civ4 - Modding Tutorials & Reference' started by Fierabras, Mar 24, 2008.

  1. Fierabras

    Fierabras Chieftain

    Joined:
    Dec 26, 2006
    Messages:
    1,114
    Introduction:

    While playing around with BTS Events, I wondered if it was possible to make non-random timed events. After some experimentation I found that it was indeed possible. In this tutorial I will show an example of how it can be achieved.

    Explanation:

    As I see it (and correct me if I'm wrong) there are 2 tags in the event trigger that determine the randomness of an event being triggered:

    <iPercentGamesActive>
    <iWeight>

    The first determines the percentage that an event is included in a game and the second sets the change of the event occurring in the game. By setting these to the following, I made them non-random.

    Code:
    <iPercentGamesActive>100</iPercentGamesActive>
    <iWeight>-1</iWeight>
    
    This means the event is always included (100%) and is always triggered (-1), providing all the requirements are met.

    By setting the <bRecurring> tag to 1, the event will be triggered more than once.

    Code:
    <bRecurring>1</bRecurring>
    
    The problem now is, that when the requirements are met, the event will trigger each turn. This is where some Python is needed to add a new requirement that isn't possible with the available XML tags.

    Let's say you want the event to occur each 10 turns. In the XML for each event trigger there is a tag named <PythonCanDo>. It's this tag you can use to hook in a Python function. In the example below I used:

    Code:
    <PythonCanDo>canTriggerZeusSpawn</PythonCanDo>
    
    This function called 'canTriggerZeusSpawn' does not exist yet, so you have to add it to CvRandomEventInterface.py

    (create a folder Assets/Python/EntryPoints in your mod and copy the default BTS file CvRandomEventInterface.py to that folder)

    The function reads as follows:

    Code:
    def canTriggerZeusSpawn(argsList):
    	kTriggeredData = argsList[0]
    	turn = kTriggeredData.iTurn
    					
    	if (turn % 10 == 0):
    		return true
    	return false
    
    For the mathematically challenged :) , this uses the modulus operator:

    18 % 10 = 8
    19 % 10 = 9
    20 % 10 = 0
    21 % 10 = 1
    etc.

    So, this function will return true every tenth turn and this return value let's the trigger know the event gets fired.

    Example:

    Some people might remember the Statue of Zeus from CIV3 that gave free units at certain intervals. With the help of what I have explained above, I have recreated this functionality.

    First, set the event trigger's requirement:

    Code:
    <BuildingsRequired>
    	<BuildingClass>BUILDINGCLASS_STATUE_OF_ZEUS</BuildingClass>
    </BuildingsRequired>
    <iNumBuildings>1</iNumBuildings>
    
    This means the event gets triggered for the civ that owns the Statue of Zeus world wonder (only 1 in the game).

    Second, set the event

    Code:
    <UnitClass>UNITCLASS_AXEMAN</UnitClass>
    <iNumFreeUnits>4</iNumFreeUnits>
    
    Pretty self-explanatory, but notice that it uses UNITCLASS and not UNIT, which means that civs who have a UU that replaces the axeman, will get 4 of those UU's. For example: if the Greek own the Statue of Zeus, the event will gift 4 phalanxes ("Madness!? This is Sparta!")

    Below is a screenshot of all of this in action:



    I have added this example as an attachment.
     

    Attached Files:

  2. Ekmek

    Ekmek on steam: ekmek_e

    Joined:
    Aug 7, 2002
    Messages:
    6,045
    Location:
    San Diego, California
    Very cool. Is there a way to change religions from be founded with techs to quests or random events?

    Or make it so a unit generates units every few turns or captures a unit (like privateers in civ3)?
     
  3. Fierabras

    Fierabras Chieftain

    Joined:
    Dec 26, 2006
    Messages:
    1,114
    Almost anything that is possible in Python, can be 'hooked' through BTS events. Religions are a bit tricky (what happens if you remove a tech requirement from a religion, auto-founding?) and there are no tags in the event-XML for 'gifting' religions, but you can use the <PythonCallback> tag to execute your Python that would found a religion.

    Anyway, for this you would use some more Python and maybe to a point that you start to wonder if you still need a BTS event. I have been down that road before...

    In the example I used the requirement of a building for the event to trigger, but you can also use the requirement of a unit (let's say...some sort of camp unit ;) ) to let the event trigger.
     
  4. Edgecrusher

    Edgecrusher Chieftain

    Joined:
    Aug 7, 2006
    Messages:
    915
    Location:
    Massachusetts
    Awesome, honestly, the Events are the only XML files I havent "gone through" to see what they offer.

    quick question, if the Building were to become obsolete, in the example Statue of Zeus at Chemistry, would the spawning stop?

    @Ekmek, I seem to remember Zebra made an enslavement mod via Python, I am not sure if it works with BTS though. I do remember playing around with it in Warlords though.
     
  5. Fierabras

    Fierabras Chieftain

    Joined:
    Dec 26, 2006
    Messages:
    1,114
    Yes, you can even make any event go obsolete after discovery of another tech (before the building itself goes obsolete). I suggest you look into Solver's excellent Guide to event modding, to see what all the tags do.
     
  6. Edgecrusher

    Edgecrusher Chieftain

    Joined:
    Aug 7, 2006
    Messages:
    915
    Location:
    Massachusetts
  7. ambrox62

    ambrox62 Chieftain

    Joined:
    Mar 24, 2005
    Messages:
    1,294
    Next step could be event trigger at a fixed historical date. Is it doable? Is the game calendar addressable to trigger a specific historical event (instead of # of turns)?
    Example:

    Triggers:
    Year 2000 BC (approx)
    Egyptans are in play and alive
    No one built Pyramids yet

    Effect:
    Egyptians build Pyramids (or receive a huge bonus to do that)
     
  8. Fierabras

    Fierabras Chieftain

    Joined:
    Dec 26, 2006
    Messages:
    1,114
    It's very doable IMO. It will be the topic of my follow-up tutorial, so, stay tuned...

    Edit: might as well give some code to show part of it

    Code:
    def canTriggerPyramidsBuild(argsList):
            kTriggeredData = argsList[0]
    	player = gc.getPlayer(kTriggeredData.ePlayer)
    	turn = kTriggeredData.iTurn
    
    	if (player.getCivilizationType() == gc.getInfoTypeForString("CIVILIZATION_EGYPT")):
    
    		game = gc.getGame()
    						
    		if (game.getTurnYear(turn) == -2000):
    			return true
    		return false
    
    	return false
    
    One important thing to notice is that not all gamespeeds have a turn where the date is exactly 2000 BC, so a better approach would be to check for in-between dates. For the example for the Pyramids this PythonCanDo function needs to be expanded to also check if the Pyramids have been built already.
     
  9. moopoo

    moopoo Chieftain

    Joined:
    Jan 5, 2008
    Messages:
    729
    Location:
    Adelaide, Australia
    ooh ooh ooh. I'm a budding python coder who's struggling to take his first steps. Someone please help me in this.

    In This:

    What is argsList, what does it refer to, why is it referred to, and what does it do here?

    Also, why 0?
     
  10. Fierabras

    Fierabras Chieftain

    Joined:
    Dec 26, 2006
    Messages:
    1,114
    argList is arguments list. It contains data about the event. What it does here, is retrieving the game turn the event is triggered at. Why 0? 0 is the first key in any array (not just Python), but it doesn't always have the same value in BTS events. From Solver's guide:

     
  11. moopoo

    moopoo Chieftain

    Joined:
    Jan 5, 2008
    Messages:
    729
    Location:
    Adelaide, Australia
    ... =S I'll go read his whole post and see if it makes any more sense.
     
  12. jkp1187

    jkp1187 Unindicted Co-Conspirator

    Joined:
    Aug 29, 2004
    Messages:
    2,496
    Location:
    Pittsburgh, Pennsylvania
    Thanks for posting this. I may borrow some of this whenever I come off of my real-life-imposed modding sabbatical.... ;)
     
  13. Fierabras

    Fierabras Chieftain

    Joined:
    Dec 26, 2006
    Messages:
    1,114
    I'm planning on doing a couple of these tutorials on BTS events. I was about to write another when I got side-tracked by a interesting request. For those who are interested in making BTS events more visual with artwork, check out this thread:

    http://forums.civfanatics.com/showthread.php?t=267326

    Some teaser screenshots:



    The next tutorial will be titled: BTS historical events
    I touched upon it in this thread, but posted more extensively in another thread, due to a post by my old pal, Ambreville:

    http://forums.civfanatics.com/showthread.php?t=269280
     
  14. Solver

    Solver Civ4/5 beta tester

    Joined:
    Mar 22, 2002
    Messages:
    1,260
    Location:
    Latvia, Riga
    Good work Fireabras. This is indeed fairly convenient generally, although personally, if I had to do a lot of non-random events, I wouldn't use the random event system but rather script them purely in Python, which is what most mods do for historical events. See Road to War for a very easy to understand (in my opinion) example of doing historical events.
     
  15. Fierabras

    Fierabras Chieftain

    Joined:
    Dec 26, 2006
    Messages:
    1,114
    Convenient, yes, absolutely, but what about modularity? The plus-side of using BTS events is that you could setup modular events XML to script your historical events.

    Let's say I create a generic "Punic Wars" event with modular XML. That way it could be used in several scenarios. Of course copy-pasting parts out of a pure Python mod is easy as well, but dragging and dropping folders from Custom Events might be a bit easier and more practical.
     
  16. Solver

    Solver Civ4/5 beta tester

    Joined:
    Mar 22, 2002
    Messages:
    1,260
    Location:
    Latvia, Riga
    Depends on what you prefer. I don't do modules myself. One other possibility that comes to mind is just creating a list of events in XML, along with a pure Python implementation, where XML would be confined to specifying whether each event is enabled or disabled. It would also allow you to tweak at ease.
     
  17. Fierabras

    Fierabras Chieftain

    Joined:
    Dec 26, 2006
    Messages:
    1,114
    Are we talking about extending PythonCallbackDefines.xml ? If so, we have just taken a leap to the end point of what I assume to be possible.
     
  18. Solver

    Solver Civ4/5 beta tester

    Joined:
    Mar 22, 2002
    Messages:
    1,260
    Location:
    Latvia, Riga
    Yes, that. Or you could just add stuff to GlobalDefines.xml and check via Python whether to run your events based on that - the advantage being how easy GlobalDefines is to access via Python.
     
  19. micmc

    micmc Chieftain

    Joined:
    Apr 17, 2004
    Messages:
    179
    Location:
    atlanta ga usa
    Thanks for these excellent tut's (both on random and non random), I'm right on the verge of "getting it" I think...so far I've managed to make A=B stuff...so I'm confident I can figure it out eventually....

    My questions is with changing plots on cue (like a worker job): I'd like the ability to change a plot (specifically land into ocean/coast but I'm unsure of the method of triggering it...short of running 15 workers & and a spy and Great_prophet over the plot to trigger it that way (a little cumbersome)

    Also can you insert rivers in anyway (I guess they are a feature?)
    and how would you remove a peak, since you can't "get on" the plot the peak is on?
     
  20. moopoo

    moopoo Chieftain

    Joined:
    Jan 5, 2008
    Messages:
    729
    Location:
    Adelaide, Australia
    Lol you could blow it up with a missile :D:D:D
     

Share This Page