DB/WorldStateExpression: Difference between revisions

From wowdev
Jump to navigation Jump to search
mNo edit summary
 
(10 intermediate revisions by 2 users not shown)
Line 1: Line 1:
expression is a flattened AST. is bytewise. First is enabled == always 1. then, operand {0 (disabled), 1 (uint32), 2 (worldStateID (evals to something other than id, likely something in worldStateRec)), 3 (uint8 op, recurse left, recurse right; where op <=0xc: none, random, month, day, timeofday, region, clockHour, difficultyID, holidayStart, holidayLeft, holidayActive, currentTime, weeknumber)}, then op {1: +, 2:-, 3:*, 4*/, 5:%, 0: no op}, then op2 {…. See CGWorldStateInfo::EvalWorldStateExpression.
{{Template:SectionBox/VersionRange|min_expansionlevel=5}}
 
= Expression format =
 
* String is a hex printed byte blob.
* 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 <tt>value_0, operator, [value_1, operator, [value_2, operator, […]]]</tt>. The chain continues until <tt>operator</tt> is <tt>0</tt>.
* 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 <tt>enabled</tt> which stops the entire thing if <tt>0x00</tt>.
 
== level 0: enabled ==
 
uint8_t enabled;
if (enabled) {
  LogicalLevel logical;
}
 
If <tt>enabled == 0</tt>, the expression evaluates to <tt>false</tt>.
 
== level 1: logical ==
 
The first level forms a chain of <tt>value_0, operator, [value_1, operator, [value_2, operator, […]]]</tt>. The chain continues until <tt>operator</tt> is <tt>None</tt>.
 
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 <tt>((value_0 or value_1) and value_2) xor <value_3></tt>.
 
=== 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 <tt>lhs ≠ 0</tt>, and
 
  <lhs> 01 <rhs>
 
evaluates to <tt>lhs == rhs</tt>.
 
=== 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 <tt>op</tt> is 0, the value of <tt>lhs</tt> 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, {{DBField|table=Difficulty|column=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,      //                            => {{DBField|table=Difficulty|column=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,        //                            => {{Unverified|{{DBField|table=KeystoneAffix|column=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==
==6.0.1.18179==
  struct WorldStateExpressionRec {
  struct WorldStateExpressionRec {
   uint32_t m_ID;
   uint32_t m_ID;
   stringref m_expression;
   {{Template:Type|stringref}} m_expression;
  };
  };
[[Category:DBC]]
[[Category:DBC]]
[[Category:DBC_WoD]]
[[Category:DBC_WoD]]
[[Category:6.0.1.18179]]
[[Category:6.0.1.18179]]

Latest revision as of 16:41, 5 April 2020

This section only applies to versions ≥ Mists.

Expression format

  • String is a hex printed byte blob.
  • 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;
if (enabled) {
  LogicalLevel logical;
}

If enabled == 0, the expression evaluates to false.

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;
};