Modding/Conditionals

Logical conditions
The Quest and Conversation structures posses a condition feature. This is used to encode logical formulas. The game will evaluate these formulas to determine if the node should be accessible. In the files this feature is contained in the  tags.

The Conditions can be nested arbitrarily deep and be connected with the logical operators AND, OR, NOT. In the files are two kinds of Elements: ConditionalExpression which combine different Conditions and ConditionalCall which contain game functions e.g. to check a global variable.

To evaluate the Conditions as given in the XML files the game goes from top to bottom and evaluate each part. The logical operators which will also be used from top to bottom, with each new one occurring replacing the current remembered. This encoding makes it possible to evaluate the formulas in one go without the need of a stack or multiple recursive branches. A side effect of this encoding is, that in the files occur more Operator tags than necessary to build the logical formula.

Example
data/conversation/07_gilded_vale/07_cv_fisherman.conversation contains the following code:

&lt; Conditionals > &lt; Operator > And &lt;/ Operator > &lt; Components > &lt; ExpressionComponent xsi : type = " ConditionalCall " > &lt; Data > &lt; FullName > Boolean IsGlobalValue(String, Operator, Int32) &lt;/ FullName > &lt; Parameters > &lt; string > n_Clyver_Quest_Stage &lt;/ string > &lt; string > GreaterThan &lt;/ string > &lt; string > 1 &lt;/ string > &lt;/ Parameters > &lt;/ Data > &lt; Not > false &lt;/ Not > &lt; Operator > And &lt;/ Operator > &lt;/ ExpressionComponent > &lt; ExpressionComponent xsi : type = " ConditionalCall " > &lt; Data > &lt; FullName > Boolean IsGlobalValue(String, Operator, Int32) &lt;/ FullName > &lt; Parameters > &lt; string > n_Clyver_Quest_Stage &lt;/ string > &lt; string > LessThan &lt;/ string > &lt; string > 4 &lt;/ string > &lt;/ Parameters > &lt;/ Data > &lt; Not > false &lt;/ Not > &lt; Operator > And &lt;/ Operator > &lt;/ ExpressionComponent > &lt; ExpressionComponent xsi : type = " ConditionalCall " > &lt; Data > &lt; FullName > Boolean HasConversationNodeBeenPlayed(String, Int32) &lt;/ FullName > &lt; Parameters > &lt; string > assets/data/conversations/07_gilded_vale/07_cv_fishermen.conversation &lt;/ string > &lt; string > 6 &lt;/ string > &lt;/ Parameters > &lt;/ Data > &lt; Not > true &lt;/ Not > &lt; Operator > And &lt;/ Operator > &lt;/ ExpressionComponent > &lt;/ Components > &lt;/ Conditionals >

In shorter terms:

IsGlobalValue(n_Clyver_Quest_Stage, GreaterThan, 1) AND IsGlobalValue(n_Clyver_Quest_Stage, LessThan, 4) AND NOT HasConversationNodeBeenPlayed(assets/data/conversations/07_gilded_vale/07_cv_fishermen.conversation, 6)

which is in plain logical writing:

A ≥ 1 ∧ A ≤ 4 ∧ ¬B

Example 2
data/conversations/02_defiance_bay_first_fires/02_bs_controller_crucible_knight_guard_guid.conversation

&lt; Conditionals > &lt; Operator > And &lt;/ Operator > &lt; Components > &lt; ExpressionComponent xsi : type = " ConditionalCall " > &lt; Data > &lt; FullName > Boolean IsGlobalValue(String, Operator, Int32) &lt;/ FullName > &lt; Parameters > &lt; string > b_Disable_Knight_Barks &lt;/ string > &lt; string > EqualTo &lt;/ string > &lt; string > 0 &lt;/ string > &lt;/ Parameters > &lt;/ Data > &lt; Not > false &lt;/ Not > &lt; Operator > And &lt;/ Operator > &lt;/ ExpressionComponent > &lt; ExpressionComponent xsi : type = " ConditionalExpression " > &lt; Operator > And &lt;/ Operator > &lt; Components > &lt; ExpressionComponent xsi : type = " ConditionalExpression " > &lt; Operator > Or &lt;/ Operator > &lt; Components > &lt; ExpressionComponent xsi : type = " ConditionalCall " > &lt; Data > &lt; FullName > Boolean IsGlobalValue(String, Operator, Int32) &lt;/ FullName > &lt; Parameters > &lt; string > bReceivedAcolyteHeritageHillVision &lt;/ string > &lt; string > EqualTo &lt;/ string > &lt; string > 1 &lt;/ string > &lt;/ Parameters > &lt;/ Data > &lt; Not > false &lt;/ Not > &lt; Operator > And &lt;/ Operator > &lt;/ ExpressionComponent > &lt; ExpressionComponent xsi : type = " ConditionalCall " > &lt; Data > &lt; FullName > Boolean IsGlobalValue(String, Operator, Int32) &lt;/ FullName > &lt; Parameters > &lt; string > n_HH_Quest_Stage &lt;/ string > &lt; string > EqualTo &lt;/ string > &lt; string > 0 &lt;/ string > &lt;/ Parameters > &lt;/ Data > &lt; Not > false &lt;/ Not > &lt; Operator > And &lt;/ Operator > &lt;/ ExpressionComponent > &lt;/ Components > &lt;/ ExpressionComponent > &lt; ExpressionComponent xsi : type = " ConditionalExpression " > &lt; Operator > Or &lt;/ Operator > &lt; Components > &lt; ExpressionComponent xsi : type = " ConditionalCall " > &lt; Data > &lt; FullName > Boolean IsGlobalValue(String, Operator, Int32) &lt;/ FullName > &lt; Parameters > &lt; string > bReceivedAcolyteSanitariumVision &lt;/ string > &lt; string > EqualTo &lt;/ string > &lt; string > 1 &lt;/ string > &lt;/ Parameters > &lt;/ Data > &lt; Not > false &lt;/ Not > &lt; Operator > And &lt;/ Operator > &lt;/ ExpressionComponent > &lt; ExpressionComponent xsi : type = " ConditionalCall " > &lt; Data > &lt; FullName > Boolean IsGlobalValue(String, Operator, Int32) &lt;/ FullName > &lt; Parameters > &lt; string > n_Sanitarium_Quest_Stage &lt;/ string > &lt; string > EqualTo &lt;/ string > &lt; string > 0 &lt;/ string > &lt;/ Parameters > &lt;/ Data > &lt; Not > false &lt;/ Not > &lt; Operator > And &lt;/ Operator > &lt;/ ExpressionComponent > &lt;/ Components > &lt;/ ExpressionComponent > &lt;/ Components > &lt;/ ExpressionComponent > &lt;/ Components > &lt;/ Conditionals >

In more readable terms it is:

IsGlobalValue(b_Disable_Knight_Barks, EqualTo, 0) AND ((IsGlobalValue(bReceivedAcolyteHeritageHillVision, EqualTo, 1) AND IsGlobalValue(n_HH_Quest_Stage, EqualTo, 0)) OR (IsGlobalValue(bReceivedAcolyteSanitariumVision, EqualTo, 1) AND IsGlobalValue(n_Sanitarium_Quest_Stage, EqualTo, 0)))

or if you like the programming aspect more:

b_Disable_Knight_Barks == 0 && ((bReceivedAcolyteHeritageHillVision == 1 && n_HH_Quest_Stage == 0) || (bReceivedAcolyteSanitariumVision == 1 && n_Sanitarium_Quest_Stage == 0))

Conditional Functions
There are currently (1.0.6) 79 conditional functions which can be used in a logical formula. All of them evaluate to a logical value. The following table lists all of them, including a short description.

The following is a list of all available condition checks (in version 1.0.6)