The WynnBuilder team has been hard at work giving you the latest and greatest tools for optimizing your most complex Wynncraft builds. Now, we're introducing WynnAtlas, the new, bigger, better, smarter, powerful-er item guide! Featuring an extremely flexible expression language for filtering and sorting items, WynnAtlas' advanced item search system gives build engineers the power to select items with a high degree of granularity. Picking components for your brand-new Divzer WFA build has never been easier!
The advanced item search interface uses two separate expressions: one for filtering items and the other for sorting them. The idea is that you can filter for items matching a set of criteria that are absolutely necessary for the item you want, then sort the remaining items to find the optimal build component. The expressions themselves are mathematical formulae that compute values from the properties of items, such as their damage values and identifications.
As an example, suppose you want a helmet granting at least 10 intelligence that maximizes spell damage gain for a build using the Nepta Floodbringer. We would start by writing a filter for helmets with our desired bound on intelligence:
{prop:type} {op:=} {str:"helmet"} {op:&} {prop:int} {op:>=} {num:10}
Then, we would write an expression that computes the amount of damage we get from the helmet. To do this, we first check the damage numbers for the Nepta Floodbringer: assuming we aren't using any powders, we have 96–112 water damage scaled by the super-fast attack speed modifier of 4.3, giving us a total of 4.3 × (96 + 112) ÷ 2 = 447.2. We then multiply in the spell damage and water damage modifiers and add raw spell damage, giving us:
{prop:sdRaw} {op:+} {num:447.2} {op:*} {op:(}{prop:sdPct} {op:+} {prop:wDamPct}{op:)} {op:/} {num:100}
And, voilĂ ! In the blink of an eye, we've discovered that Caesura is the best helmet for our criteria, granting 448.14 spell damage.
Roughly speaking, the expression language just consists of mathematical expressions with simple operations and functions. Each value in the expression is either a number, a boolean (true or false), or a string (a chunk of text). Numbers are floating-point rather than integers, so any kind of fractional value can also be expressed. String literals can use either single- or double-quotes, so the following is true:
{str:"Hello, world!"} {op:=} {str:'Hello, world!'}
The filtering expression should produce a boolean in the end, which represents whether an item matches the filter or not, and the sorting expression should produce either a number or a string, which are used to order the items. The sorting expression can even contain multiple sub-expressions separated by semicolons, which are then used to sort the result lexicographically. For example, if I want to sort items by loot bonus, then XP bonus if items have equal loot bonus, I could write:
{prop:lb}; {prop:xpb}
The supported mathematical operations include the basic arithmetic operations as well as exponentiation. These operators obey the usual order of operations, with exponentiation having the highest priority. Parentheses are also supported for grouping.
({num:1} {op:+} {num:2}) {op:-} {num:3} {op:*} ({num:4} {op:/} {num:5}) {op:^} {num:6}
The supported boolean operations include conjunction (“AND”) and disjunction (“OR”) using the &
and |
symbols, as well as unary inversion (“NOT”) using the !
symbol. Disjunction has higher priority than conjunction, so the following is true:
{bool:true} {op:|} {bool:false} {op:&} {bool:true} {op:|} {bool:false} {op:=} {op:(}{bool:true} {op:|} {bool:false}{op:)} {op:&} {op:(}{bool:true} {op:|} {bool:false}{op:)}
For comparisons, equality and non-equality are represented by the =
and !=
symbols. The two operands can be of any type, and the result will always be a boolean describing whether the operands are equal. String comparisons are case-insensitive.
{prop:type} {op:=} {str:"wand"} {op:|} {prop:cat} {op:!=} {str:"weapon"}
The relational comparisons are given by <
, <=
, >=
, and >
. The two operands must be of some comparable type—booleans cannot be compared, so it's an error to pass them to a relational comparison.
{prop:str} {op:>=} {num:20} {op:&} {prop:lvl} {op:<} {num:80}
In addition to these comparison operators, there's also a “contains” operator ?=
, which checks whether a string contains a given substring or not. This allows for matching more loosely against strings; for example, if I wanted to see all the Hive master weapons, I could use the filter:
{prop:name} {op:?=} {str:"hive infused"}
Some handy functions are also available, and can be called using a C-like syntax:
{fn:min}{op:(}{prop:int}{op:,} {num:105} {op:-} {prop:intReq}{op:)} {op:+} {fn:min}{op:(}{prop:def}{op:,} {num:80} {op:-} {prop:defReq}{op:)}
Try some of these examples out in the item guide! Experimenting with weird and unusual expressions is a great way to get used to the syntax. The more you practice, the faster and more effective you'll be at using WynnAtlas to optimize your powerful Wynncraft builds!
What follows are lists of existing built-in properties and functions. Note that some aliases are omitted for properties with way too many aliases. If you want, you can also check out the source code to see the actual declarations for all the built-in objects.
You can check out the implementation notes for the expression parser, as well as the parser code itself, over at the WynnBuilder GitHub repository. You can also ask around on the Atlas Inc. Discord server if you want more details.