Results 1 to 25 of 25

Thread: Tutorial [Beginner coding/scripting]: Triggers&Monitors

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Harbinger of... saliva Member alpaca's Avatar
    Join Date
    Aug 2003
    Location
    Germany
    Posts
    2,767

    Default Tutorial [Beginner coding/scripting]: Triggers&Monitors

    You can link to or quote this tutorial at wish, but please don't mirror it. This is required in order to keep discussion about it in one place.

    Prerequisites

    In order to be able to follow this tutorial, you should be confident with the following:
    - The traits tutorial and all that is required there
    - The docudemon files


    Triggers

    First of all, I want to make sure you understand the enormous spread of the concept of triggers in the MTW2 data files. They are directly used in all of the following files (among which are some of the most-edited files for every mod):
    - descr_faction_standing.txt
    - export_descr_advice.txt
    - export_descr_ancillaries.txt
    - export_descr_character_traits.txt
    - export_descr_guilds.txt

    On top of that, the monitor_event scripting structure works pretty much in the same way.


    1. Overview

    Well, since you are reading this tutorial, I guess you have already had a good look at one of the files containing triggers and formed your own opinion about what they do (if not, have a look at my traits tutorial and read the first part carefully). Now, to see if your assumptions are correct - look at this example:
    Code:
    ;------------------------------------------
    Trigger diplomatinit6
        WhenToTest AgentCreated
    
        Condition Trait Multilingual >= 1
    
        Affects Multilingual  1  Chance  33
    You can clearly see that each trigger consists of four basic parts:
    - A trigger head (aka the name)
    - A WhenToTest event
    - Zero or more conditions
    - Zero or more affects


    2. The trigger head

    The trigger head starts with the keyword Trigger followed by the trigger name.
    The only thing you should observe here is that each trigger is assigned an individual name. I think the game will use the last version of a trigger name it can find (no idea how having the same trigger name in multiple files affects this).


    3. The WhenToTest event

    This part consists of the keyword WhenToTest followed by an event name. This entry determines when the trigger will actually execute. In the above example, the trigger will be run every time an agent is created, but only if the conditions are met (see below).

    You can find a list of all allowed events in docudemon_events.txt which you downloaded with the docudemon package.
    For more info on this file, press on "Show":
    Here's an example from the file:
    Code:
    ---------------------------------------------------
    Identifier:         SettlementTurnStart
    Event:              A Settlement is being processed for the start of its faction's turn
    Exports:            faction, settlement, region_id
    Class:              ET_SETTLEMENT_TURN_START
    Author:             Guy
    ---------------------------------------------------
    Identifier:         SettlementTurnEnd
    Event:              A Settlement is being processed for the end of its faction's turn
    Exports:            faction, settlement, region_id
    Class:              ET_SETTLEMENT_TURN_END
    Author:             Guy
    As you can see, each entry consists of the event name (Identifier - this is what goes behind WhenToTest), a description of the event, which types of objects this event exports (see below) and two (for us) unimportant lines.
    Most of these events are fairly self-explaining, but some take a lot of guessing and/or testing to figure out what they do exactly and what you can do with them.


    4. Conditions

    This section is quite a bit more complex than the first two. Looking at our example from the beginning, you will notice that it has only one condition:
    Code:
    ;------------------------------------------
    Trigger diplomatinit6
        WhenToTest AgentCreated
    
        Condition Trait Multilingual >= 1
    
        Affects Multilingual  1  Chance  33
    This is actually an interesting example for a trigger, because it has a certain level of the trait it is changing as a condition. This means, it will never award the trait in the first place but can amplify it.

    Let's have a look at a more complex example now:
    Code:
    ;------------------------------------------
    Trigger hate_n_fear_29
        WhenToTest PostBattle
    
        Condition IsGeneral
              and not WonBattle
              and BattleSuccess = crushing
              and I_ConflictType Normal
              and BattleOdds >= 0.9
              and GeneralFoughtFaction england
    
        Affects Fearsengland  1  Chance  100
    This is one of the hate&fear triggers that will give your general boni/mali in combat against certain factions or cultures. This trigger contains 6 conditions, that are linked with the and keyword (you should put each condition on a new line), and the Effects section will only be executed if all of the conditions are true.
    The first condition always has to be preceded by the Condition keyword, the others by and. Both of these can in turn be followed by not to negate the condition (like it's done with "and not WonBattle" in the example).
    Be careful when using not. It apparently doesn't work with some conditions that use a logic token (like I_CompareCounter counter = 1).
    If you want to negate these, manually negate the token, so "not condition = 1" would become "condition != 1", "not condition >= 1" would become "condition < 1" and so on.


    You can find a complete list of allowed condtions in docudemon_conditions.txt - shipped with the docudemon package.
    Understanding this section is vitally important for the correct usage of conditions, but before you read this, you should be comfortable with some basic examples (you can find a few here <--ToDo: Write this)

    Ok, since you know the basics about conditions, let's have a look at two examples for the basic condition types in the docudemon:
    Code:
    Identifier:              FactionIsLocal
    Trigger requirements:    faction
    Parameters:              None
    Sample use:              FactionIsLocal
    Description:             Is the faction the local faction?
    Battle or Strat:         Either
    Class:                   FACTION_IS_LOCAL
    Implemented:             Yes
    Author:                  Guy
    ---------------------------------------------------
    Identifier:              I_LocalFaction
    Trigger requirements:    
    Parameters:              faction
    Sample use:              I_LocalFaction romans_julii
    Description:             Is the faction the local faction?
    Battle or Strat:         Either
    Class:                   I_LOCAL_FACTION
    Implemented:             Yes
    Author:                  Guy
    Identifier: the name of the condition

    Trigger requirements: This is one of the most important and apparently most difficult to understand aspects of conditions.
    Basically, each condition has a certain scope (i.e. it only works on certain game objects). This scope is the trigger requirement, and you will notice that this exactly fits the Exports entry for the events.
    If you want to use a condition with a certain trigger requirement, you can only do that in a trigger with a WhenToTest event that exports this object. For example, the FactionIsLocal condition (it is true if and only if the faction the event exports is the player's faction) will work with the SettlementTurnStart event but not with the CrusadeCalled event because the former exports a faction object, while the latter doesn't.

    The second example (I_LocalFaction) is a fine specimen of an independent condition. These conditions don't have a trigger requirement, and they work in all triggers. They are usually fairly inflexible but if you know how to use them properly, they have important applications (especially in scripting).

    Parameters: This is another important entry. It tells you which parameters a condition takes. A lot of conditions simply take one parameter, but a lot of them also take a logic token (<, <=, =, >, >=) or multiple parameters. Independent conditions almost always take at least one parameter, dependent conditions often take one, but as you could view the trigger requirement object as an additional parameter they don't always have to have another one.

    The rest of the file should be fairly self-explanatory, or isn't important for modding purposes.



    5. The affects section

    First of all, don't confuse this with effects for traits. This is something quite different.
    This part of a trigger definition consists of zero or more variations on the theme:
    Code:
    Affects <Trait> <Points> Chance <Percentage>
    This means that, when the trigger is run and all conditions are true, the character in question will have a <Percentage> chance to get <Points> trait points in <Trait>. An example:
    Code:
    Affects GoodCommander 1 Chance 50
    When this is executed, the character has a 50% chance of getting one point in the GoodCommander trait chain, thus making him a more able general.

    As I said, you can use multiple Affects lines in one trigger, or even omit them altogether (although this will make the trigger completely useless), like this:
    ;------------------------------------------
    Trigger corruption4
    WhenToTest CharacterTurnEnd

    Condition EndedInSettlement
    and Treasury > 150000

    Affects Corrupt 1 Chance 3
    Affects Aesthetic 1 Chance 3
    Affects ExpensiveTastes 1 Chance 3
    Affects Epicurean 1 Chance 3
    Affects Embezzler 1 Chance 3


    5.1 Other files

    To view this section, click on Show:
    I told you in the introduction that triggers are actually a concept pretty wide-spread in MTW2 modding. Up until now, the triggers in descr_faction_standing.txt, export_descr_advice.txt, export_descr_ancillaries.txt, export_descr_character_traits.txt and export_descr_guilds.txt look exactly the same. They differ, however, insofar as only the edct file uses an actual Affects line. As for the other files, I will tell you the keywords but not go into too great detail about them:


    export_descr_ancillaries.txt
    This file uses an entry called AcquireAncillary instead of the Affects line. It looks like this:
    Code:
    AcquireAncillary <Ancillary> chance <Percentage>
    You will notice that this is almost the same as an Affects statement, however you can't have different levels of the same ancillary so you only have one parameter, which is the chance to acquire that ancillary.
    An example:
    Code:
    AcquireAncillary holy_lance chance 10

    export_descr_advice.txt
    The equivalent statement here is:
    Code:
    AdviceThread <thread> <points>
    Where <thread> is a thread identifier and <points> is used for Threshold and, I think, MaxRepeats


    descr_faction_standing.txt
    The line here is:
    [code]FactionStanding <factions> [normalise/points]
    A bit more explanation needed I think. However I'd rather leave this to a tutorial about this file as it is pretty complex


    export_descr_guilds.txt
    For this file, it looks like:
    Code:
    Guild <guild> [s/a/o] <points>
    Where <guild> is a guild name and <points> is a numeric value.
    "s" will award the points to the settlement in question only, "a" will award the bonus to all the faction's settlements and "o" will give it to all except for the settlement "s" will award the points to.





    Monitors

    Well, monitors are the scripting equivalent of triggers. Before you read this, you should have some basic grasp about scripting, which you might be able to get from old RTW tutorials.
    Anyways, the thing that is closest to triggers is the monitor_event struct.
    The exact command goes like this:
    Code:
    monitor_event <Event> <Condition>
        [and [not] <Condition>]
    
        ...code...
    end_monitor
    What this does is practically the same as a trigger: When <Event> fires (this is the same as a WhenToTest event in a trigger), and all <Conditions> are satisfied, the code inside the monitor will be executed. It is important to know that here, too, you can only use conditions which trigger requirements fit the exports of the event you are testing for.
    The first <Condition> is compulsory, and if you don't want to use one, supply TrueCondition here (which is, as the name says, always true).

    The [and [not] <Condition>] can be repeated as many times as you like.

    The second monitor struct is monitor_conditions.
    The definition for it is:
    Code:
    monitor_conditions <Condition
        [and [not] <Condition>]
    
        ...code...
    end_monitor
    This is actually a bit similar to monitor_event - but not quite. It is important to notice that, since you don't have any event to export objects, you can only use independent conditions here, whereas in monitor_event, you can also use (fitting) dependent conditions.
    It's also quite apparent that a monitor_conditions will execute multiple times (in fact as long as all its conditions are true), which often has unwanted results as opposed to a monitor_event that will only execute once every time its event fires.
    To prevent this, you can switch monitor_conditions on and off like this:
    Code:
    declare_counter switch
    set_counter switch 1
    monitor_conditions I_CompareCounter switch 1
    
        console_command add_money 10000
        set_counter switch 0
    end_monitor
    This monitor will add 10000 florins to your treasury every time you set the counter switch to 1 somewhere in the script and then switch itself off again.

    Another important concept of monitors is that you can switch them off completely, using the terminate_monitor command. If you use that somewhere inside the monitor, it will be closed to be never executed again until you start a new game.
    Last edited by alpaca; 05-07-2007 at 11:46.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Single Sign On provided by vBSSO