DB/WorldStateExpression
expression is a flattened AST. is hex byte strings.
- AST is static in terms of operands. First level is logical, second is relational, third is arithmetic, fourth is values. - The first three levels are each of form value_0, operator, [value_1, operator, [value_2, operator, […]]]. The chain continues until operator is 0. - The last level, values, is either a constant, a world state id or a binary function that recursively has a value again as operands. - the whole expression is prefixed by a byte enabled which stops the entire thing if 0x00.
- level 0: enabled
uint8_t enabled; LogicalLevel logical;
- level 1: logical
The first level forms a chain of value_0, operator, [value_1, operator, [value_2, operator, […]]]. The chain continues until operator is None.
struct LogicalLevel { RelationalLevel value_0; LogicalOperator op; if (op ≠ 0) { LogicalLevel value_1; } };
The operations are left associative, i.e.
<value_0> 02 <value_1> 01 <value_2> 03 <value_3> 00
results in ((value_0 or value_1) and value_2) xor <value_3>.
- LogicalOperator
enum LogicalOperator : uint8_t { None = 0, And = 1, Or = 2, Xor = 3, };
- level 2: relational
This level is either unary -- to degrade to top level constants -- or binary:
struct RelationalLevel { ArithmeticLevel lhs; RelationalOperator op; if (op ≠ 0) { ArithmeticLevel rhs; } };
So
<lhs> 00
evaluates to lhs ≠ 0, and
<lhs> 01 <rhs>
evaluates to lhs == rhs.
- RelationalOperator
enum RelationalOperator : uint8_t { id = 0, // lhs; do not read rhs eq = 1, // lhs = rhs ne = 2, // lhs ≠ rhs lt = 3, // lhs < rhs le = 4, // lhs ≤ rhs gt = 5, // lhs > rhs ge = 6, // lhs ≥ rhs };
- level 3: arithmetic
This level again, is either unary or binary:
struct ArithmeticLevel { ValueLevel lhs; ArithmeticOperator op; if (op ≠ 0) { ValueLevel rhs; } };
If op is 0, the value of lhs is the result of the "operation".
- ArithmeticOperator
enum ArithmeticOperator : uint8_t { id = 0, // lhs; do not read rhs add = 1, // lhs + rhs sub = 2, // lhs - rhs mul = 3, // lhs * rhs div = 4, // rhs ≠ 0 ? (lhs / rhs) : 0 mod = 5, // rhs ≠ 0 ? (lhs % rhs) : 0 };
- level 4…: values
The leaf level is a value: a constant, world state (i.e. variable) or a binary function of values.
struct ValueLevel { uint8_t type; switch (type) { case 0: // result = 0 break; case 1: int32_t value; // result = value break; case 2: int32_t world_state_id; // result = current world state value of given state break; case 3: enum function_id : int { none = 0, // => 0 random = 1, // min, max => random in [min, max) month = 2, // => g_clientGameTime.month + 1 day = 3, // => g_clientGameTime.day + 1 time_of_day = 4, // => g_clientGameTime.GetHourAndMinutes() (in minutes) region = 5, // => CGServerInfo::regionID clock_hour = 6, // => g_clientGameTime.hours % 12 difficulty_id = 7, // => CGGameUI::m_instanceDifficultyID ("old" id, DifficultyRec::OldEnumValue) holiday_start = 8, // holiday_id, duration_id => minutes to begin holiday_left = 9, // holiday_id, duration_id => minutes to end holiday_active = 10, // holiday_id => 1 if any left > 0 timer_current_time = 11, // => time(nullptr) week_number = 12, // => weeks since raid origin // added after 6.0.1: difficulty_id_new = 15, // => DifficultyRec::ID war_mode_active = 16, // => 1 if war mode currently enabled on player world_state_expression = 22, // world_state_expression_id => eval (world_state_expression_id) keystone_affix = 23, // => KeystoneAffixRec::IDᵘ keystone_level = 28, // => random_new = 33, // max, seed => std::mt19937 {seed ? seed : 1}() % max + 1 ui_widget_data = 37, // ???????? }; function_id type; value lhs; // note: regardless of number of used arguments! value rhs; // result = fun(lhs, rhs) break; } } };
6.0.1.18179
struct WorldStateExpressionRec { uint32_t m_ID; stringrefⁱ m_expression; };