Module:CalcStat

From Lotro-Wiki.com
Jump to navigation Jump to search

Overview

CalcStat calculates game stats using a single access function. It originated from the LotroPlan spreadsheet project, initially developed by Giseldah in 2013 (see this forum thread). This module implements the Standard Progression and other progressions, enabling accurate in-game stat calculations directly within the Wiki.

Key Features:

  • Calculates game stats based on various progressions.
  • Includes expression parsing for complex stat derivations.
  • Supports various formatting options for wiki-friendly display of results.

See Also: CalcStat on LoTROInterface - Plugin download page.

Current Version: 2.4.13f

Installation

Retrieving sources

To get the sources, you have two main options:

  1. Direct Download: Download the source code directly from LoTROInterface. The source files will be within the downloaded zip file.
  2. LOTRO Plugin Compendium: Install via LOTRO Plugin Compendium. If installed via Plugin Compendium, the source files can be found in your plugins directory under Giseldah\CalcStat.

Note: Regardless of the installation method, you will need to compile the Lua code for use in the Wiki (see instructions below).

Creating the Wiki Lua Code

To generate the Lua code for Module:CalcStat (the Wiki module), you need to compile the source file calcstat.csv. This is done using the compiler script statdcmp.vbs provided with the source files. Follow these steps to compile the code:

  1. Locate the compiler script: Ensure you have access to the source files from either installation method above. The compiler script statdcmp.vbs is located within these source files.
  2. Run the compiler script: Execute the statdcmp.vbs script on a Windows system.
  3. Select output option: When prompted by the script, choose option 6: "Lua-script (Lotro-Wiki Module)".
  4. Select stats inclusion: Next, choose option 1 to "include all stats".
  5. Locate the output file: The compiler will generate a file named CalcStat.lua. This CalcStat.lua file contains the Lua code for Module:CalcStat and is ready to be copied into the module page.

Important: These compilation steps are necessary to create the Wiki-compatible Lua code from the provided source data.

Usage

{{#invoke:CalcStat|calc|StatName or Expression|Level|NorC|Format|Display}}

Standard CalcStat Parameters

  • StatName or Expression (mandatory): reference to the stat to be calculated or a CalcStat Expression instead. See stat sections below for some of the stat possibilities. The calcstat.csv file contains the complete list (best viewed with a spreadsheet application), but be warned that it's very complex and some stats are only intermediate/internal calculations.
  • Level: can be a character level, item level, virtue rank, etc.
  • NorC: optional parameter. can be either number or text, depending on stat.

Specific Parameters for Wiki use

Assuming a value of 12345.016:
  1. %'d displays a thousand separated number for main stats (whole numbers; rounded down when fractured) like: 12,345
  2. %'+d displays a thousand separated number for main stats (whole numbers; rounded down when fractured) with a forced sign like: +12,345
  3. %.0f (default) displays a number for rating stats (fractured numbers; normal rounding to given precision 0 decimals) like: 12345
  4. %+.0f displays a number for rating stats (fractured numbers; normal rounding to given precision 0 decimals) with a forced sign like: +12345
  5. %'.1f displays a thousand separated number for DPS (fractured numbers; normal rounding to given precision 1 decimal) like: 12,345.0
  6. %'.0.1f displays a thousand separated number (fractured numbers; normal rounding to given precision maximum 1 decimal / removing trailing zeroes up to minimum precision 0 ) like: 12,345
  7. %'.1.2f displays a thousand separated number (fractured numbers; normal rounding to given precision maximum 2 decimal / removing trailing zeroes up to minimum precision 1 ) like: 12,345.02
  • Display: option for display of percentages and other:
  1. AddP: Display Additive Percentage (with a 0.0002 correction).
  2. AddP100: Mutltiply by 100 & display as Additive Percentage (with a 0.0002 correction).
  3. MultiP: Display Multiplier Percentage (with a 0.0002 correction).
  4. MultiP100: Mutltiply by 100 & display as Multiplier Percentage (with a 0.0002 correction).
  5. Worth: Displays value in gold/silver/copper (from number value in format ..ggggssscc).
  6. Corr: Correction. 0.0002 is added to any fractured number (this is the default for numbers).
  7. NoAdj: No adjustments - to override any defaults.

Default Number Formatting for Wiki

Module:CalcStat and most depending modules automatically attempt to apply appropriate number formatting based on keywords found in the StatName or Expression, unless an overriding Format parameter is provided. This ensures a sensible default display for various stat types.
The following table outlines the default formatting rules, in order of detection (non-case sensitive). Note that if a detected sequence is followed by the character 'P', the formatting is skipped.

Sequences Format Notes
ARMOURLOW, CLOTHARMOUR %'d Specific Armour values on items.
ARMOUR%a+, %w+ARMOUR %.0f Targeting non item related Armour values.
MAIN, AGILITY, FATE, MIGHT, VITALITY, WILL, ARMOUR %'d Targeting whole number main stats with a thousand separator.
WPNDMGMIN, WPNDMGMAX, SKILLPOWERCOST %'.0f Fractured stats requiring thousand separator and 0 decimals.
WPNDPS %'.1f Same as above, but with 1 decimal.
ICMR, ICPR, NCMR, NCPR, POWER %.0.3f Regeneration and Power stats with 0-3 decimals.
(No match) %.0f Default format if no sequence is detected.

Expressions

CalcStat Expressions provide a powerful way to create custom stat calculations beyond simple stat selection. They allow you to combine stats, constants, operations, and functions to derive new values and result texts.

Introduction

A StatName in CalcStat is essentially a predefined expression linked to an internal identifier. Expressions allow you to define your own calculations directly within the #invoke call. You can for example do some simple calculations:

{{#invoke:CalcStat|calc|1+1}}

2

{{#invoke:CalcStat|calc|5*-3^2^-2+28*(4/6+1)+1/3*2|||%.0.8f|NoAdj}}

40.75296327

Magic Words

Note that in Wiki the pipe character '|' and equal sign '=' are processed as part of the #invoke argument parsing. If you want to use these in your Expressions code then you need to use {{!}} or {{=}} respectively.
Tip: if you number all arguments to the invoke like this then you don't need to use {{=}} for using the equal sign (still need to use {{!}}).

{{#invoke:CalcStat|calc|1=StatName or Expression|2=Level|3=NorC|4=Format|5=Display}}

For example:

{{#invoke:CalcStat|calc|1=with($A=$L+$N:$A+2)|2=100|3=|4=Level: %.0f|5=NOADJ}}

Level: 103

Comments

You can add comments to expressions if you place them between /* */.
For example:

{{#invoke:CalcStat|calc|/* lol */}}

Translation error in CalcStat:Expressions invoked by Module:CalcStat
Code: 12 (Missing expression)
Obviously, this gives not an error because of the comment, but because we didn't supply any expression at all.

{{#invoke:CalcStat|calc|5 /* let's add something to this lowly value */ + 1 /* can we do more please? */ + 4 /* ok, fine*/}}

10

Operators

In expressions you can use the same operators as used in Lua version 5.1, minus the '#'. They are also processed in the same order of priority and direction.
Syntax in expressions is not case-sensitive, so AND and Or are fine.
From low to high priority:

Operators Processing direction Notes
or
and
< > <= >= ~= ==
.. string concatenation
+ -
* / % % is modulo/remainder
not - unary -
^

Of course you can also use parentheses () and what is in-between will have priority above all else.

Constants/values

Numbers

Accepted as valid numbers are:

  • a series of digits. (like 123)
  • a series of digits including a decimal dot '.', but not at the edges. (like 0.123, but not .123)

Strings

Strings are encapsulated between double quotes: "tekst".
Accepted escape characters in strings are:

  • \q or \" double quote
  • \\ backslash
  • \n new line

Booleans

Booleans are True and False, non-case-sensitive.

Variables

In CalcStat you have variables which can be used in expressions:

  • L - stands for some kind of level, rank, etc. It's value is equal to the parameter which you supply in the template.
  • N - an extra number value defined in the NorC parameter. N is automatically detected when NorC can be converted to a number.
  • C - a text string from the NorC parameter: anything which is not a number.

These variables can be used in expressions by prefixing a $ sign, so like $L, $N, $C.

{{#invoke:CalcStat|calc|"(L)evel {{=}} "..$L.." and (N)umber {{=}} "..$N|5|9.5}} ('=' between {{}} to avoid processing of '=' characters by Wiki)

(L)evel = 5 and (N)umber = 9.5

{{#invoke:CalcStat|calc|$L*($N+1)+5.30106|5|9.5|%.1.2f|NoAdj}}

57.8

Using Stats

You can use CalcStat stat values in your own expression by using the name of the stat with the @ prefix. Any number attached at the back is interpreted as being the $L to pass to the stat calculation (current $L is passed by default if nothing is specified).

{{#invoke:CalcStat|calc|"1 point of player level Might at level 130: "..@MightT130}}

1 point of player level Might at level 130: 300

{{#invoke:CalcStat|calc|"1 point of item level Might at ilvl 130: "..@Might130}}

1 point of item level Might at ilvl 130: 50

You can also pass a $N parameter to the stat by attaching a # sign followed by a number for the $N to pass. If you only attach a # with no number after it then current $N is passed to the stat.

{{#invoke:CalcStat|calc|"2.6 points of player level Critical Rating at level 100: "..@CritHitT100#2.6}}

2.6 points of player level Critical Rating at level 100: 1180

{{#invoke:CalcStat|calc|"2.6 points of item level Critical Rating at ilvl 100: "..@CritHit100#2.6}}

2.6 points of item level Critical Rating at ilvl 100: 538.33331298828

Instead of a number for $L and $N, you might want to pass an expression. In that case just use parentheses () instead of the numbers.
This is also the way that you can pass a tekst parameter $C (any string expression containing things like constants "tekst", current $C or a stat which returns a string)

{{#invoke:CalcStat|calc|"1/2 points of item level Critical Rating at ilvl "..$L..": "..@CritHit#(1/2)|123}}

1/2 points of item level Critical Rating at ilvl 123: 131.67500305176

{{#invoke:CalcStat|calc|"Armour value for heavy incomparable boots at ilvl "..$L..": "..@Armour#($C)|412|HBT}}

Armour value for heavy incomparable boots at ilvl 412: 2344

{{#invoke:CalcStat|calc|"At ilvl "..$L..", @Vitality#2 is "..@Vitality#2.." and 2*@Vitality#1 equals "..2*@Vitality#1.."... "..iif(@Vitality#2{{=}}{{=}}2*@Vitality#1,"Ok.","It's not the same!")|468}}

At ilvl 468, @Vitality#2 is 863 and 2*@Vitality#1 equals 862... It's not the same!

Functions

Adding functions is an ongoing process. These are the functions currently supported:

Name Notes
Abs(<number expression>) Absolute value (make positive).
Afd(<number expression>, <display option string expression>) Adjust for display. See Specific parameters for Wiki use. Default is "Corr".
Afd(<number expression>)
CalcStat(<Stat name string expression>, <Level number expression>, <NorC expression>) Can be used instead of the shortcut @StatName(Level)#(NorC).
CalcStat(<Stat name string expression>, <Level number expression>)
CalcStat(<Stat name string expression>)
Ceil(<number expression>) Rounds value up to whole number.
Choose(<index number expression>, <parameter list>) Chooses a parameter (any expression), based on the first which is the index.
DecSng(<number expression>) Converts a standard double float precision value to the decimal presentation of the equivalent single float value.
EquSng(<number expression>) Converts a standard double float precision value to equivalent single float value.
Floor(<number expression>) Rounds value down to whole number.
Format(<expression>, "format string") Format to specific text output. See also Specific parameters for Wiki use. Default is "%.0f" for numbers.
Format(<expression>)
GraphVal(<Interpolation Key number expression>, <Point Key number expression1>, <Point Value number expression1>, ..etc) Derives a Value from a set of graph points by interpolation.
IIf(<logical expression>, <expression1>, <expression2>) If the logical expression is true then returns expression1, otherwise expression2.
Log10(<number expression>) Gives the base-10 logarithm.
Min(<number expression1>, <number expression2>) Returns the smallest of 2 numbers.
Max(<number expression1>, <number expression2>) Returns the largest of 2 numbers.
Replace(<Source string expression>, <Search string expression1>, <Replacement expression1>, ...etc) Replaces all occurrences of Search string <> in Source string with Replacement boolean/number/string <>. Processes multiple search & replace pairs.
Round(<Value number expression>, <Decimals number expression>) Rounds a number value, optionally to a specified number of decimals.
Round(<Value number expression>)
RoundUp(<Value number expression>, <Decimals number expression>) Rounds a number value upward, optionally to a specified number of decimals.
RoundUp(<Value number expression>)
RoundDown(<Value number expression>, <Decimals number expression>) Rounds a number value downward, optionally to a specified number of decimals.
RoundDown(<Value number expression>)
RoundLotro(<Value number expression>) Rounds a number value upward using a 3 digit precision.
RoundProg(<Value number expression>) Rounds a number value to a varying amount of decimals, which depends on the value.
SESel(<test expression>, <interval expression1>, <result expression1>, ..etc, <otherwise expression>) Smaller-Equal Select: see below.
Sqrt(<number expression>) Gives the square root.
Switch(<test expression>, case <comparison expression1>: <result expression1>, case..etc, default: <otherwise expression>) Returns a value when a comparison is true.
Until(<initial variable assignment list>: <loop variable assignment list>: <loop termination condition logical expression>: <result expression>) Executes an Until loop until a termination condition is met and returns a processing result.
While(<initial variable assignment list>: <loop execution condition logical expression>: <loop variable assignment list>: <result expression>) Executes a While loop while an execution condition is met and returns a processing result.
With(<variable assignment list>:<result expression>) Assigns values to (custom) variables and returns a value based on these.

Choose

The first parameter is the index into the remaining parameters. An index value of 1 selects parameter 2 etc. Gives an error when the index is out of bounce.

{{#invoke:CalcStat|calc|
Choose(
     $L,
          "Adam",
          "Cindy",
          "Sandy",
          "Thom"
)
|2}}

Cindy

DecSng

DecSng constrains a double float number(64bit) to the decimal presentation value (8 significant digits) of a single precision number(32bit).

{{#invoke:CalcStat|calc|"Normal double: "..$L.."<br>".."Decimal presentation single: "..DecSng($L)|5.3333333333333333333}}

Normal double: 5.3333333333333
Decimal presentation single: 5.3333335

EquSng

Calculations in CalcStat are done with double float numbers(64bit), but the game client uses single precision(32bit). EquSng constrains a double float number to the precision of an equivalent single float number. See also IEEE-754 Floating Point Converter.

{{#invoke:CalcStat|calc|"Normal double: "..$L.."<br>".."Equivalent single: "..EquSng($L)|5.3333333333333333333}}

Normal double: 5.3333333333333
Equivalent single: 5.3333334922791

GraphVal

This function calculates a Value (Y-coordinate) from a set of graph points for a given Key (X-coordinate), by using Linear Interpolation.
Graph points (Key,Value) are first sorted by Key (should be whole numbers and each being unique) and then the Interpolation Key is used to determine the two calculation interval points.
Through these two points you can draw an imaginary line and from this line the Interpolation Value will be calculated using the Interpolation Key.
Stat progressions are almost always using these graphs (linear lines connecting points), except where exponential growth is required.

Note: Linear Extrapolation will be used when the key is outside the bounds of the first or last point, by either using the first two points or the last two points (a minimum amount of two points is mandatory).

The following example defines graph points (1,2), (30,20), (50,50), (100,120) and (999,200). Using $L (40) as the Interpolation Key, it's determined that the two points are (30,20) and (50,50), because the Key is between 30 and 50. From these two points 35 is calculated (40 is exactly in the middle of 30-50, so the interpolated value will also be in the middle of 20-50).

{{#invoke:CalcStat|calc|
GraphVal($L,
1,2,
30,20,
50,50,
100,120,
999,200
)
|40}}

35

Replace

Replaces text parts inside a text with other texts. Note that text replacements proceed from left to right, in sequential order.

{{#invoke:CalcStat|calc|
Replace("Rune-keeper 1","-","","k","K","1",2)
}}

RuneKeeper 2

SESel

Smaller-Equal Select. This function works like Switch, but is more focused on breaking up a range into intervals. It behaves like a Switch(operand1, case <= operand2: operand3, case <= operand4: operand5, etc default: operandn) with the last parameter being the default (value for the remaining/top interval).

{{#invoke:CalcStat|calc|
SESel(
     $L,
         75, 1,
        100, 2,
        105, 3,
        120, 4,
        130, 5,
             6
)
|121}}

5

Switch

You can combine multiple cases for one result value/expression, like with <100 and >120 in this example. Note that after 'default' nothing will be processed.
Also, in Expressions only the parts which need to be processed are being processed, so comparisons are executed top-down until true and then the single result value is evaluated.
The same for the IIf function: only the condition is being evaluated and then one of the results will be processed depending on the outcome.

{{#invoke:CalcStat|calc|
$L..": "..
switch(
    $L,
        case < 20:
            iif($L < 10, "smaller than 10", "smaller than 20, but equal or larger than 10"),
        case < 30:
            "smaller than 30",
        case < 100:
        case > 120:
            "smaller than 100 or larger than 120",
        default:
            "in the range of 100 to 120"
)
|15}}

15: smaller than 20, but equal or larger than 10

Until

This is a Do..Until loop so the loop condition is checked after processing the variable assignment list inside the loop and the loop cycles until the termination condition becomes true.
You can use the initial variable assignments to setup a loop control variable, like a counter, and a result variable, which you can change inside the loop and return at the end of the processing.
The Until function has a counterpart in While(), which checks for an execution condition to be true before each cycle is run.
The maximum number of cycles is limited to 1000.

{{#invoke:CalcStat|calc|
Until(
     $NameRows{{=}}"", $NameIdx{{=}}1:
          $Name{{=}}Choose($NameIdx,"Rose","William","Kees",""),
          $NameRows{{=}}$NameRows..Iif($Name{{=}}{{=}}"","",
               $NameIdx..". "..$Name.."<br>"
          ),
          $NameIdx{{=}}$NameIdx+1:
     $Name{{=}}{{=}}"":
     $NameRows
)
}}

1. Rose
2. William
3. Kees

While

This is a While..Do loop so the loop condition is checked before processing the variable assignment list inside the loop and the loop cycles while the execution condition stays true.
You can use the initial variable assignments to setup a loop control variable, like a counter, and a result variable, which you can change inside the loop and return at the end of the processing.
The While function has a counterpart in Until(), which checks for a termination condition to be true at the end of each cycle.
The maximum number of cycles is limited to 1000.

{{#invoke:CalcStat|calc|
With(
     $iLvl{{=}}512:
          "<u>Item Stats at iLvl "..$iLvl.."</u><br>"..
          While(
               $Result{{=}}"", $Index{{=}}1:
               $Index<{{=}}5:
                    $StatName{{=}}Choose($Index,"Agility","Fate","Might","Vitality","Will"),
                    $Result{{=}}$Result..$Index..". "..$StatName..": "..CalcStat($StatName,$iLvl).."<br>",
                    $Index{{=}}$Index+1:
               $Result
          )
)
}}

Item Stats at iLvl 512
1. Agility: 823
2. Fate: 675
3. Might: 823
4. Vitality: 801
5. Will: 823

With

You can assign values to multiple variables separated by a comma, which you can name anything you like(only alphabetical characters). The With function returns the value of the expression after the ':'.

{{#invoke:CalcStat|calc|
With(
    $LplusTen {{=}} $L+10,
    $LminusFive {{=}} $L-5:
        $LplusTen*2+$LminusFive*3
)
|8}}

45
Note that no such thing as a variable scope exists in these expressions, so all variables are 'global'. This means that these variables are permanent and do exist outside the With function.
Also, nothing stands in the way of changing predefined variables as $L with the same impact. Avoid doing this as it may lead to unpredictable results.

{{#invoke:CalcStat|calc|
With(
    $L {{=}} $L+1:
        $L
)
+2*$L
|3}}

12

Stats

These (most of the normalized)stats are only a part of the collection. A full list can be found in the calcstat.csv file, which is in the ..\The Lord of the Rings Online\Plugins\Giseldah\CalcStat directory when you have installed the plugin.

Rating to Percentage and vice versa

All rating percentages related stat names kind of look the same. The first part of the name is the type of percentage and the part at the end selects the data or calculation for it.

First Part Notes
Block Block Chance
BPE Block/Parry/Evade Chance (general reference)
CritDef Critical Defence
CritHit Critical Hit Chance
CritMagn Critical/Devastating Hit Magnitude
DevHit Devastating Hit Chance
Evade Evade Chance
Finesse Finesse
InDmg Another ring was made.. (depreciated)
InHeal Incoming Healing
MitHeavy Mitigation Heavy classes (general reference)
MitLight Mitigation Light classes (general reference)
MitMedium Mitigation Medium classes (general reference)
OutDmg Outgoing Damage (general reference)
OutHeal Outgoing Healing
Parry Parry Chance
PartBlock Partial Block Chance
PartBlockMit Partial Block Mitigation
PartBPE Partial Block/Parry/Evade Chance (general reference)
PartEvade Partial Evade Chance
PartEvadeMit Partial Evade Mitigation
PartMit Partial Block/Parry/Evade Mitigation (general reference)
PartParry Partial Parry Chance
PartParryMit Partial Parry Mitigation
PhyDmg Physical Damage
PhyMitH Physical Mitigation Heavy classes
PhyMitL Physical Mitigation Light classes
PhyMitM Physical Mitigation Medium classes
Resist Resistance
TacDmg Tactical Damage
TacMitH Tactical Mitigation Heavy classes
TacMitL Tactical Mitigation Light classes
TacMitM Tactical Mitigation Medium classes
End Part L NorC Notes
PBonus PlayerLvl Percentage Bonus
PPRat PlayerLvl N=percentage Percentage to Rating
PRatP PlayerLvl N=rating Rating to Percentage
PRatPA PlayerLvl A
PRatPB PlayerLvl B-rating
PRatPC PlayerLvl C (curve constant)
PRatPCap PlayerLvl Percentage Cap
PRatPCapR PlayerLvl Percentage Cap Rating (rating required)

General references are not preferred to be used. However, if you want to refer to BPE chances in general without being specific about one of the three then go ahead.

Examples

Calculating the basic Evade Chance percentage for 30000 Evade rating at player level 107.

{{#invoke:CalcStat|calc|EvadePRatP|107|30000|%.1f%%|AddP}}

13.0%

You should also add the percentage bonus like with Partial Evade Mitigation (Partial Mitigations are currently the only one with a 0.1 bonus):

{{#invoke:CalcStat|calc|@PartEvadeMitPRatP#+@PartEvadeMitPBonus|107|30000|%.1f%%|AddP}}

35.1%

Calculating the Evade rating required to reach 10.5% Evade Chance (without accounting for any PBONUS) at player level 120.

{{#invoke:CalcStat|calc|EvadePPRat|120|10.5|%f|NoAdj}}

16578.947368

The previous rating should be rounded up, so you could use the expression:

{{#invoke:CalcStat|calc|Ceil(@EvadePPRat#)|120|10.5|%f|NoAdj}}

16579

Main

Many stats have a player level and an item level version. I first created calculations for item stats, so the names for those are the most straightforward. For player stats I appended a 'T' at the name, which stands for Traits. That category is much too narrow though: these stats are used anywhere where stats are player level related like in Effects.
Notes:

  • Stat Main is the general reference here. This stat is equal to Agility, Might and Will. Fate & Vitality stats are currently on different progressions.
  • The N parameter should contain the number of stat points. Default for N is 1, so if you don't supply a specific number then you get the standard 1 point. Note that, in general, because of internal 3 digit rounding introduced a while ago, N * (1 point of Stat) is not same as (N points of Stat) anymore.
  • Main stat values are always whole numbers. Module:CalcStatTable tries to apply format %'d, so whole number format with thousand separator, based on the statname. Module:CalcStat treats them like any other number.
Item level stat
StatName L NorC Notes
Agility ItemLvl N=points
Fate ItemLvl N=points
Main ItemLvl N=points (general reference)
Might ItemLvl N=points
Vitality ItemLvl N=points
Will ItemLvl N=points
Player level stat
StatName L NorC Notes
AgilityT PlayerLvl N=points
FateT PlayerLvl N=points
MainT PlayerLvl N=points (general reference)
MightT PlayerLvl N=points
VitalityT PlayerLvl N=points
WillT PlayerLvl N=points

Percentage Ratings

Notes:

  • The N parameter should contain the number of stat points. Default for N is 1, so if you don't supply a specific number then you get the standard 1 point. Note that, in general, because of internal 3 digit rounding introduced a while ago, N * (1 point of Stat) is not same as (N points of Stat) anymore.
  • Rating stat values are fractured numbers. Module:CalcStat applies the format %.0f as default, so fractured number format rounded to 0 decimals.
Item level stat
StatName L NorC Notes
AcidMit ItemLvl N=points Acid Mitigation
Armour ItemLvl C=code See Armour section.
ArmourLow ItemLvl C=code (Decrepit) See Armour section.
-
Block ItemLvl N=points Block Rating
BPE ItemLvl N=points Block/Parry/Evade Rating (general reference)
CritDef ItemLvl N=points Critical Defence
CritHit ItemLvl N=points Critical Rating
CryResist ItemLvl N=points Cry Resist Rating
DiseaseResist ItemLvl N=points Disease Resist Rating
DmgTypeMit ItemLvl N=points (Acid/Fire/etc) Mitigation (general reference)
Evade ItemLvl N=points Evade Rating
FearResist ItemLvl N=points Fear Resist Rating
Finesse ItemLvl N=points Finesse Rating
FireMit ItemLvl N=points Fire Mitigation
FrostMit ItemLvl N=points Frost Mitigation
InHeal ItemLvl N=points Incoming Healing Rating
LightMit ItemLvl N=points Light Mitigation
LightningMit ItemLvl N=points Lightning Mitigation
Mastery ItemLvl N=points Mastery Rating (general reference)
OrcMit ItemLvl N=points Orc-Craft Mitigation
OutHeal ItemLvl N=points Outgoing Healing Rating
Parry ItemLvl N=points Parry Rating
PhyMas ItemLvl N=points Physical Mastery Rating
PhyMit ItemLvl N=points Physical Mitigation
PhyResist ItemLvl N=points Physical Resist Rating
PoisonResist ItemLvl N=points Poison Resist Rating
Resist ItemLvl N=points Resistance Rating
ResistAdd ItemLvl N=points (Cry/Song/etc) Resist Rating (general reference)
ShadowMit ItemLvl N=points Shadow Mitigation
SongResist ItemLvl N=points Song Resist Rating
TacMas ItemLvl N=points Tactical Mastery Rating
TacMit ItemLvl N=points Tactical Mitigation
TacResist ItemLvl N=points Tactical Resist Rating
WoundResist ItemLvl N=points Wound Resist Rating
Player level stat
StatName L NorC Notes
AcidMitT PlayerLvl N=points Acid Mitigation
ArmourT PlayerLvl N=points Armour Value
-
ArmourPenT PlayerLvl N=points Armour Penetration
BlockT PlayerLvl N=points Block Rating
BPET PlayerLvl N=points Block/Parry/Evade Rating (general reference)
CritDefT PlayerLvl N=points Critical Defence
CritHitT PlayerLvl N=points Critical Rating
CryResistT PlayerLvl N=points Cry Resist Rating
DiseaseResistT PlayerLvl N=points Disease Resist Rating
DmgTypeMitT PlayerLvl N=points (Acid/Fire/etc) Mitigation (general reference)
EvadeT PlayerLvl N=points Evade Rating
FearResistT PlayerLvl N=points Fear Resist Rating
FinesseT PlayerLvl N=points Finesse Rating
FireMitT PlayerLvl N=points Fire Mitigation
FrostMitT PlayerLvl N=points Frost Mitigation
InHealT PlayerLvl N=points Incoming Healing Rating
LightMitT PlayerLvl N=points Light Mitigation
LightningMitT PlayerLvl N=points Lightning Mitigation
MasteryT PlayerLvl N=points Mastery Rating (general reference)
-
OutHealT PlayerLvl N=points Outgoing Healing Rating
ParryT PlayerLvl N=points Parry Rating
PhyMasT PlayerLvl N=points Physical Mastery Rating
PhyMitT PlayerLvl N=points Physical Mitigation
PhyResistT PlayerLvl N=points Physical Resist Rating
PoisonResistT PlayerLvl N=points Poison Resist Rating
ResistT PlayerLvl N=points Resistance Rating
ResistAddT PlayerLvl N=points (Cry/Song/etc) Resist Rating (general reference)
ShadowMitT PlayerLvl N=points Shadow Mitigation
SongResistT PlayerLvl N=points Song Resist Rating
TacMasT PlayerLvl N=points Tactical Mastery Rating
TacMitT PlayerLvl N=points Tactical Mitigation
TacResistT PlayerLvl N=points Tactical Resist Rating
WoundResistT PlayerLvl N=points Wound Resist Rating

Health & Energy

Notes:

  • The N parameter should contain the number of stat points. Default for N is 1, so if you don't supply a specific number then you get the standard 1 point.
  • Health & Energy stat values are fractured numbers. Module:CalcStat applies the format %.0f as default, so fractured number format rounded to 0 decimals.
Item level stat
StatName L NorC Notes
Morale ItemLvl N=points Maximum Morale
ICMR ItemLvl N=points In-Combat Morale Regeneration
NCMR ItemLvl N=points Non-Combat Morale Regeneration
Power ItemLvl N=points Maximum Power
ICPR ItemLvl N=points In-Combat Power Regeneration
NCPR ItemLvl N=points Non-Combat Power Regeneration
Player level stat
StatName L NorC Notes
MoraleT PlayerLvl N=points Maximum Morale
ICMRT PlayerLvl N=points In-Combat Morale Regeneration
NCMRT PlayerLvl N=points Non-Combat Morale Regeneration
PowerT PlayerLvl N=points Maximum Power
ICPRT PlayerLvl N=points In-Combat Power Regeneration
NCPRT PlayerLvl N=points Non-Combat Power Regeneration
SkillPowerCost PlayerLvl N=points Skill use Power Cost[1]
  1. See Skill Power Cost Calculation for a table with cost values. If you know the value in the skill's tooltip then you can look it up in this table and determine the amount of points it represents.

Examples

Showing 3.5 points worth of Skill Power Cost at level cap.

[{{#invoke:CalcStat|calc|SkillPowerCost|{{Level Cap}}|3.5}} at Level {{Level Cap}}]

[471 at Level 150]

Showing Skill Power Cost at level cap for a channeled skill needs an additional format, because it needs to be rounded down (d takes the integer/whole number part only):

[{{#invoke:CalcStat|calc|SkillPowerCost|{{Level Cap}}|0.05|%'d}} at Level {{Level Cap}}]

[7 at Level 150]

Armour (on wearable items)

For armour on items we have 2 normalized stats, of which Armour is the most common used by far. Some lower level items can have a type which I call 'decrepit' armour. A kind of half functioning armour whatever. An example is this item: Item:Dannasen's Shirt. The StatName for this type of armour is ArmourLow. Furthermore, we have a 3rd depreciated / old stat armour which has the StatName 'ClothArmour'.

Item level stat
StatName L NorC Notes
Armour ItemLvl C=code Normal armour
ArmourLow ItemLvl C=code Decrepit armour
ClothArmour ItemLvl Id 1879073002

The normalized stats work with an 'ArmourCode', which is passed by using the C parameter (NorC). It's a letter code which consists out of 3 parts as shown in the table below. You need to choose one of the options for each position and just put them together in sequence. For example, rare medium gloves has the code MGP. A heavy incomparable shield is HShT.
Notes:

  • A special case is the CLoak/back item. This item is currently always medium(used to be light) and therefore doesn't have a category attached. These items are like CLP, CLG, etc.
  • The ArmourLow/Decrepit armour uses only 2 positions. It has it's own unique quality, so position 3 is omitted. Codes for these are like MC, HB, etc.
  • Armour on items is always a whole number (and should be displayed with a thousand separator, which should be specified in the format: %'d). The player level counterpart ArmourT behaves more like a rating and gives a fractured result (default format will be fine).
  • ClothArmour only needs the item level. No armour codes required. It's a very simple Armour value = item level up to a maximum of 50.
  • Be aware that the armour code for an item is not directly linked to how the item is displayed. Sometimes, SSG can make an error or wants to give less armour than is appropriate for the item. For instance, it has happened that gold cloaks (CLG) received the armour values for incomparable versions (CLT). I can't remember more than one quality level difference.
  • For shields: MSh, Medium Shield aka Warden Shield. LSh, Light Shield aka Shield (as for minstrels and captains). HSh, Heavy Shield.. yes.

Armour codes:

Position 1:
Category
L ight
M edium
H eavy

nothing for CLoak
Position 2:
Type/Slot
H elmet (head)
S houlders
CL oak (back)
C hest
G loves (hands)
L eggings (legs)
B oots (feet)
Sh ield
Position 3:
Quality
W hite (normal)
Y ellow (uncommon)
P urple (rare)
T eal (incomparable)
G old (epic)

nothing for Decrepit

Weapon

These stats cover most weapons. Some low level weapons are on other progressions.

Item level stat
StatName L NorC Notes
CombatBaseTacDPS ItemLvl (Li2)Tactical Damage Rating
CombatBaseTacHPS ItemLvl (Li2)Tactical Healing Rating
CombatInHeal ItemLvl (Li2)Incoming Healing Rating (currently: @InHeal#2)
WpnDmgMax ItemLvl C=code (Physical) Weapon Damage Maximum
WpnDmgMin ItemLvl C=code (Physical) Weapon Damage Minimum
WpnDPS ItemLvl C=code (Physical) Weapon DPS

The physical weapon damage stats work with a 'WeaponCode', which is passed by using the C parameter (NorC). It's a letter code which consists out of 3 parts as shown in the table below. You need to choose one of the options for each position and just put them together in sequence. For example, a Li2(Legendary Item new style) bow has the code HBG.
Notes:

  • DPS for a bow is the same as for a two-hander. The difference is the larger variance (difference between min and max damage) in damage.
  • These weapon stats are all fractured numbers. Module:CalcStatTable applies format %'.0f, so fractured number format with thousand separator, to both WpnDmg stats. WpnDPS gets %'.1f which is like the others but with one decimal. Module:CalcStat treats them like any other number.

Weapon codes:

Position 1:
Category
L ight
H eavy
Position 2:
Type
B ow
O ne-handed
T wo-handed
Position 3:
Quality
W hite (normal)
Y ellow (uncommon)
P urple (rare)
T eal (incomparable)
G old (epic)

Creep

<First Part>C at level cap automatically returns <First Part>CI at an item level, which is currently relevant for the requested amount of points in N. In general this is 525, but many exceptions exist which still use the old 515.
<First Part>CI has only been validated for 485(U37), 510(U38), 515(U38.1) and 520(U42). All the Raw versions are rarely used. In those few cases you need to round the fractured values upward to the nearest number dividable by 10.

First Part Notes
Agility
Armour Armour Value
Block Block Rating
BPE Block/Parry/Evade Rating (general reference)
CritDef Critical Defence
CritHit Critical Rating
Evade Evade Rating
Fate
Finesse Finesse Rating
ICMR In-Combat Morale Regeneration
ICPR In-Combat Power Regeneration
Main Agility/Fate/Might/Will (general reference)
Mastery Physical/Tactical Mastery Rating (general reference)
Might
Parry Parry Rating
PhyMas Physical Mastery Rating
PhyMit Physical Mitigation
Resist Resistance Rating
TacMas Tactical Mastery Rating
TacMit Tactical Mitigation
Vitality
Will
End Part L NorC Notes
C PlayerLvl N=points Values only make sense at level cap(150)
CRaw PlayerLvl N=points Non-rounded version
CI ItemLvl N=points Item Level is normally 525, by exception 515
CIRaw ItemLvl N=points Non-rounded version

Examples

Normally:

{{#invoke:CalcStat|calc|ResistC|150|0.6}}

3480

{{#invoke:CalcStat|calc|ResistCI|515|0.6}}

3070

{{#invoke:CalcStat|calc|ResistCI|520|0.6}}

3270

Exception for N=2.4:

{{#invoke:CalcStat|calc|ResistC|150|2.4}}

12300

{{#invoke:CalcStat|calc|ResistCI|515|2.4}}

12300

{{#invoke:CalcStat|calc|ResistCI|520|2.4}}

13100

Raw value:

{{#invoke:CalcStat|calc|ResistCRaw|150|2.4|%f|NoAdj}}

12245.224490

{{#invoke:CalcStat|calc|RoundUp(@ResistCRaw#,-1)|150|2.4|%f|NoAdj}}

12250.000000

Class Data

CalcStat can provide various class related data/stats. The stats can be accessed by using a class name plus 'CD' (Class Data) as a prefix.
The following names are being used:

Class Name
Beorning
Brawler
Burglar
Captain
Champion
Guardian
Hunter
LoreMaster
Mariner
Minstrel
RuneKeeper
Warden

So for example, the correct prefix for a Rune-keeper would be: RuneKeeperCD
In plugins, the prefix can be obtained by using the stat ClassName, with L = ClassId. ClassId is the number which is returned by Player.GetClass(), see GetClass.

Class Data is usually provided in a flexible open way. For instance, a class might have some rating contribution from a main stat, but maybe it hasn't. CalcStat always returns a 0 value when a stat doesn't exists.
Statname postfixes are in a pattern. You need to provide (main) stat and rating stat names like they are in use elsewhere.

Last Part/Postfix Pattern L NorC Notes
<Stat1>To<Stat2> PlayerLvl Stat contribution factor to an other stat. Like MightToBlock, TacMasToOutHeal, FateToCritHit, VitalityToMorale, ArmourToTacMit, etc.
Base<Stat> PlayerLvl Base Stats are stats which you automatically get based on your level. Like BaseAgility, BasePower, BaseMorale, BaseICMR, etc.
CalcTypeComPhyMit PlayerLvl Calculation Type to be used for calculating Common Physical Mitigation percentage.
CalcTypeNonPhyMit PlayerLvl Calculation Type to be used for calculating Non-common Physical Mitigation percentage.
CalcTypeTacMit PlayerLvl Calculation Type to be used for calculating Tactical Mitigation percentage.
CanBlock PlayerLvl Gives 1, if the class is normally able to block at specified level.
HasPower PlayerLvl Normally 1, except for Beorning: 0.

Examples

Calculating the Fate to Critical Rating contribution factor for a Lore-master at player level 91.

{{#invoke:CalcStat|calc|LoreMasterCDFateToCritHit|91||%.0.2f|NoAdj}}

0

Calculating the Base ICMR for a Champion at player level 12.

{{#invoke:CalcStat|calc|ChampionCDBaseICMR|12||%.0.2f|NoAdj}}

0.2

Tactical Mitigation Calculation Type for a Beorning.

{{#invoke:CalcStat|calc|BeorningCDCalcTypeTacMit}}

27

You can use the following mapping for getting to the related stat name for percentage calculations:

Calculation
Type
First Part
Stat Name
12 PhyMitL
13 PhyMitM
14 PhyMitH
25 TacMitL
26 TacMitM
27 TacMitH

Race Data

CalcStat can also provide a few race related data/stats. The stats can be accessed by using a race name plus 'RD' (Race Data) as a prefix.
The following names are being used:

Race Name
Beorning
Dwarf
Elf
HighElf
Hobbit
Man
Hunter
StoutAxe

So for example, the correct prefix for a Stout-axe would be: StoutAxeRD
In plugins, the prefix can be obtained by using the stat RaceName, with L = RaceId. RaceId is the number which is returned by Player.GetRace(), see GetRace.

Race Data is query based like Class Data.
Statname postfixes are in a pattern. You need to provide (main) stat and rating stat names like they are in use elsewhere.

Last Part/Postfix Pattern L NorC Notes
Trait<Stat> PlayerLvl These stats are an accumulation based on (passive) Racial Skills / Characteristics. Examples are TraitFate, TraitVitality, etc.

Examples

Calculating the Trait ICMR for a Dwarf at player level 10.

{{#invoke:CalcStat|calc|DwarfRDTraitICMR|10||%.0.2f|NoAdj}}

0.17

This stat is based on  Unwearying in Battle which can also be calculated with:

{{#invoke:CalcStat|calc|DwarfUnwearBattleICMR|10||%.0.2f|NoAdj}}

0.17

Wiki specific use cases

Negative predefined stat in -[x at Level ...]

In case of a debuff effect, a predefined CalcStat stat has usually a negative value, so it can be used in a table without issues. However, in the case of -[x at Level ...] you run into trouble, because you would get a double minus sign like -[-x at Level ...].
For this we have a couple of solutions:

  • Turn a statname into an expression. Any statname passed which can not not be identified as such, meaning not being composed of only a series of alphanumerical characters, is treated as an expression. As soon as you apply maths like multiplication * etc. this will be automatically the case. What you can do with a negative number is negating it with a minus sign in front of it. However, to use stats in expressions, you'll need to prefix any statnames with the '@' sign first. Also, if needed, to pass a NorC parameter the statname needs to have a '#' appended as well.
  • Less appealing aesthetically, but effective is just removing the '-' outside the brackets.

Examples

In this example '-@' is prefixed, so firstly the stat is recognized as a stat in an expression and then a negation calculation is performed on it. Also, '#' is appended because a ranknumber '3' needs to be passed.

{{color|deeppink|-[{{#invoke:CalcStat|calc|-@HntArmourRendParry#|{{Level Cap}}|3}} at Level {{Level Cap}}] Parry Rating}}

-[15200 at Level 150] Parry Rating

Here, no rank is required, so it's fine to leave out the '#' (wouldn't hurt either, but just not needed).

-[{{#invoke:CalcStat|calc|-@BrgAllInOnExpFinesse|{{Level Cap}}}} at Level {{Level Cap}}] Finesse Rating

-[881 at Level 150] Finesse Rating

Note that with expressions, in many cases you'll need to handle formatting: specify format %'d for main stats for the thousand separator to appear and use %.0.3f for 3 decimals max in power stats. Default is %.0f which simply displays whole numbers without decimals and thousand separators, like in the examples above.

Matching trait/effect stats points from in-game numbers

Predefined stats already have a points amount defined and are tested with game data on a regular bases. You want to prefer to always use these if available. However, where not available, you can use the general stats as described in this article. With this you might have a problem with finding the right amount of stat points when you try to match numbers from tool-tips in-game. Be aware that:

  • Stat point amounts are always 'nice'. They usually can have 1 decimal and steps of 0.2 is a common thing (in more rare cases 0.1). SkillPowerCost can have 2 decimals in the lower region. See Skill Power Cost Calculation for all point amounts.
  • You might have stats buffed by a trait or other effect.
  • Trait/effect(+skill) stats are usually character level stats, so they need the 'T' postfix stat versions. However in some cases, devs chose to use item stats instead. This might have happened intentionally, because the stat will become much lower, perhaps the desired point amount was not available (in the database) to them at a critical time, or it's just a bug. In these cases, you will notice that you need weird point amounts when applying character level statnames. When you get this: try the item level version instead.

Error Codes

Module:CalcStat

Code Description Notes
1001 Missing stat name or expression When no stat name or expression has been given in the template.

CalcStat

Code Description Notes
-1 Missing stat name No stat name has been passed to the function.
-2 Illegal stat name The passed stat name is not a valid name.
-3 Illegal level The passed level parameter is not a number.
-4 Illegal N or C The passed NorC parameter is not a number or text type.

Expressions

Code Description Notes
1 Too many variables used When the number of variables exceeds the maximum(1000).
2 Syntax error Expected to find something logical, but failed to do so.
3 Invalid number of operands When the number of parameters given to an operation/function does not meet expectations.
4 Invalid operand type When a type of a parameter given to an operation/function is not of an expected type.
5 Out of range Within a Choose function, when a selection can't be made based on current index parameter and the number of provided data parameters.
6 Execution error Didn't find an expression result operand, likely because of a problem during translation.
7 Unknown unary operator Based on it's position, a character sequence/token is likely an unary operator (a calculation based on 1 value), but it can't be recognized.
8 Unknown binary operator Based on it's position, a character sequence/token is likely a binary operator (a calculation based on 2 values), but it can't be recognized.
9 Missing binary operator A second value in a binary operation was expected, but not found.
10 Unidentified operand Something was found, but it's not of a recognized identity.
11 Unknown function The used function is not supported.
12 Missing expression Expected a valid expression, but nothing was given like in () with no content.
13 Non-matching operand type Might be when trying to compare two values of different types, like a string and a number.
14 Uninitialized variable When a variable is used in an expression, but it didn't got a value assigned, like in a With construction.
15 Reached maximum processing requests The maximum number of processing requests has been reached during translation (max 10000) or during execution (max 10000 in Wiki and 100000 in Lotro-client plugin).
16 Missing Switch Default expression The Switch construct was not closed with a mandatory Default expression.
17 Missing Switch Case condition A Case condition was expected in a Switch construct, but couldn't be found.
18 Syntax error in Switch Expected a Case or Default inside a Switch construction, but found something else.
19 Missing assignment variable Expected a variable to assign a value to in an assignment group.
20 Missing assignment token '=' A variable was found in an assignment group, but an assignment token is missing.
21 Missing assignment expression A variable assignment was found, but the value or expression to assign is missing.
22 Missing SEsel Default expression SEsel function call detected without the mandatory default expression in the last parameter.
23 Too many parameter groups Parameter groups are like in Until constructs, separated by ':' (so 4 groups for Until).
24 Missing parameter group(s) A parameter group like variable assignments is allowed to be empty, but like with Until, you will always need a fixed number of ":" separators to separate the required number of groups.
25 Parameter group after Switch Default No new Case condition should come after a Default 'condition'.
26 Invalid stat reference Invalid reference like @ Statname (space between @ and name).
27 Double defined level in stat reference When at the same time an attached level and a level expression are used in a stat reference, like @Statname100(200). Either use @Statname100 or @Statname(200) in this case.
28 Unknown error A run-time error occurred in native code.
29 Missing Translation object A public function was called in native code, without providing the mandatory Translation object.
30 Graph point Key already exists Keys (X-coordinates) in the graph points should be unique, but a double value was encountered.

-- Created by Giseldah

local p = {} --p stands for package

-- local used library functions
local mathabs = math.abs
local mathceil = math.ceil
local mathfloor = math.floor
local mathfrexp = math.frexp
local mathhuge = math.huge
local mathldexp = math.ldexp
local mathlog10 = math.log10
local mathmax = math.max
local mathmin = math.min
local mathmodf = math.modf
local mathsqrt = math.sqrt
local strfind = string.find
local strformat = string.format
local strgsub = string.gsub
local strmatch = string.match
local strreverse = string.reverse
local strsub = string.sub
local strupper = string.upper
local tableconcat = table.concat
local tableinsert = table.insert
local tableremove = table.remove
local tablesort = table.sort

-- ****************************** Start CalcStat ******************************

-- removes leading and trailing white space characters from a string
local function trim(s)
	if type(s) == "string" then
		return strmatch(s,"^()%s*$") and "" or strmatch(s,"^%s*(.*%S)")
	else
		return ""
	end
end

-- **************** Misc. floating point support functions ****************

-- Floating point numbers bring errors into the calculation, both inside the Lotro-client and in this function collection. This is why a 100% match with the stats in Lotro is impossible.
-- Anyway, to compensate for some errors, we use a calculation deviation correction value. This makes for instance 24.49999999 round to 25, as it's assumed that 24.5 was intended as outcome of a formula.
local DblCalcDev = 0.00000001

-- Misc. functions for floating point rounding.
-- 2nd parameter is number of decimals.

local function CorrectDbl(dNum,dCorrection,dDec)
	local lSign = 1
	if dNum < 0 then
		lSign = -1
	end
	if -DblCalcDev <= dDec and dDec <= DblCalcDev then
		return lSign*mathfloor(lSign*dNum+dCorrection)
	else
		local lFactor
		if dDec >= 0.0 then
			lFactor = 10^mathfloor(dDec+DblCalcDev)
			return lSign*mathfloor((lSign*lFactor)*dNum+dCorrection)/lFactor
		else
			lFactor = 10^mathfloor(-dDec+DblCalcDev)
			return lSign*mathfloor((lSign/lFactor)*dNum+dCorrection)*lFactor
		end
	end
end

local function RoundDbl(dNum,vDec)
	if vDec == nil then
		return CorrectDbl(dNum,0.5+DblCalcDev,0.0)
	else
		return CorrectDbl(dNum,0.5+DblCalcDev,vDec)
	end
end

local function RoundDblDown(dNum,vDec)
	if vDec == nil then
		return CorrectDbl(dNum,DblCalcDev,0.0)
	else
		return CorrectDbl(dNum,DblCalcDev,vDec)
	end
end

local function RoundDblUp(dNum,vDec)
	if vDec == nil then
		return CorrectDbl(dNum,1.0-DblCalcDev,0.0)
	else
		return CorrectDbl(dNum,1.0-DblCalcDev,vDec)
	end
end

local function RoundDblLotro(dNum)
	local dCorrection = 1.0-DblCalcDev
	local lSign = 1
	if dNum < 0 then
		lSign = -1
	end

	local lNumCeiled = mathfloor(lSign*dNum+dCorrection)
	if lNumCeiled <= 1000 then
		return lSign*lNumCeiled
	end

	local lFactor = 1
	local lTestNum = mathfloor(lNumCeiled/1000)
	while lTestNum > 0 do
		lTestNum = mathfloor(lTestNum/10)
		lFactor = lFactor*10
	end

	return lSign*mathfloor(lNumCeiled/lFactor+dCorrection)*lFactor
end

local function RoundDblProg(dNum)
	if -DblCalcDev <= dNum and dNum <= DblCalcDev then
		return 0.0
	end

	local dCorrection = 0.5+DblCalcDev
	local lSign = 1
	if dNum < 0.0 then
		lSign = -1
	end

	local dTestNum = dNum/(0.5*(lSign*63))
	local lDec = -mathfloor(mathlog10(dTestNum))

	if lDec == 0 then
		return lSign*mathfloor(lSign*dNum+dCorrection)
	else
		local lFactor
		if lDec > 0 then
			lFactor = 10^lDec
			return lSign*mathfloor((lSign*lFactor)*dNum+dCorrection)/lFactor
		else
			lFactor = 10^(-lDec)
			return lSign*mathfloor((lSign/lFactor)*dNum+dCorrection)*lFactor
		end
	end
end

-- Constants for single-precision floating-point calculations
local IEEE754_MANTISSA_SIZE = 23 -- 23 bits for single-precision IEEE 754
local IEEE754_MANTISSA_BITSCALE = 2^IEEE754_MANTISSA_SIZE -- Scales mantissa [0,1) to bits value
local IEEE754_MANTISSA_VALUESCALE = 2^-IEEE754_MANTISSA_SIZE -- Scales mantissa bits value to [0,1)
local IEEE754_EXPONENT_SIZE = 8 -- 8 bits for single-precision IEEE 754
local IEEE754_MIN_NORMAL_EXPONENT = 2-2^(IEEE754_EXPONENT_SIZE-1) -- Smallest exponent for normalized numbers
local IEEE754_MAX_NORMAL_EXPONENT = 2^(IEEE754_EXPONENT_SIZE-1)-1 -- Largest exponent for normalized numbers

-- Converts a double-precision value into the equivalent of a single-precision value
local function EquSng(vVal)
	-- Handle special cases (zero, infinity, NaN)
	if vVal == 0 then
		return 0.0
	elseif vVal == mathhuge then
		return mathhuge
	elseif vVal == -mathhuge then
		return -mathhuge
	elseif vVal ~= vVal then
		return 0/0  -- NaN
	end

	-- Get the sign and absolute value of the (double float) number
	local nSign
	local nValAbs
	if vVal < 0 then
		nSign = -1.0
		nValAbs = -vVal
	else
		nSign = 1.0
		nValAbs = vVal
	end

	-- Explicit leading 1 used for calculating the single float value: will be 1(normalized value) or 0(subnormal number)
	local nLeadingOne -- tbd
	-- Use math.frexp to get mantissa and exponent, where nValAbs = mantissa * 2^exponent, with mantissa in the range [0.5,1.0)
	local nMantissa, nExponent = mathfrexp(nValAbs)
	-- math.frexp did not return a mantissa value in the right interval for a normalized number
	nMantissa = nMantissa*2.0 -- Transform mantissa from [0.5,1.0) to [1.0,2.0) for now. Later becomes implicit leading 1.0 + [0.0,1.0) for normalized numbers.
	nExponent = nExponent-1 -- Mantissa became larger by factor 2^1, need to compensate for this in the exponent.

	if nExponent > IEEE754_MAX_NORMAL_EXPONENT then
		-- Overflow to infinity
		return (nSign == -1.0) and -mathhuge or mathhuge
	elseif nExponent < IEEE754_MIN_NORMAL_EXPONENT then
		-- Subnormal number
		nLeadingOne = 0.0
		nMantissa = mathldexp(nMantissa,nExponent-IEEE754_MIN_NORMAL_EXPONENT) -- Transfer old exponent into mantissa and extract new exponent(MIN_NORMAL_EXPONENT) in one go
		nExponent = IEEE754_MIN_NORMAL_EXPONENT
	else
		-- Normalized number
		nLeadingOne = 1.0 -- Transfer 1 from mantissa to 'explicit leading 1'
		nMantissa = nMantissa-1.0 -- Mantissa is now in the interval [0.0,1.0)
	end

	-- Scale mantissa to bitfield representation integer
	local nFraction; nMantissa, nFraction = mathmodf(nMantissa*IEEE754_MANTISSA_BITSCALE)
	-- Round to nearest, ties to even (sticky to even)
    if nFraction > 0.5 or (nFraction == 0.5 and nMantissa%2 ~= 0) then
        nMantissa = nMantissa+1 -- Round-up if fraction is larger than 0.5 or if fraction is 0.5 and current mantissa is not an even number
    end
	-- Handle overflow
	if nMantissa == IEEE754_MANTISSA_BITSCALE then
		-- Overflow in mantissa
		if nLeadingOne == 0.0 then
			-- Subnormal number: transform to Normalized number
			nLeadingOne = 1.0
		else
			-- Normalized number: increment exponent
			nExponent = nExponent+1
			if nExponent > IEEE754_MAX_NORMAL_EXPONENT then
				-- Overflow to infinity
				return (nSign == -1.0) and -mathhuge or mathhuge
			end
		end
		nMantissa = 0 -- Reset mantissa
	end

	return nSign*mathldexp(nLeadingOne+nMantissa*IEEE754_MANTISSA_VALUESCALE,nExponent)
end

-- Converts a double value into the decimal representation of an equivalent single float value
local function DecSng(vVal)
	local dVal = EquSng(vVal)
	if dVal == 0.0 then
		-- return 0 when 0
		return 0.0
	end
	-- calculate decimals interval for a max total of 8 digit precision
	-- 0.09#######: 9 to 2
	-- 0.9#######: 8 to 1
	-- 9.#######: 7 to 0
	-- 9#.######: 6 to -1
	-- 9##.#####: 5 to -2 etc
	local iDecMin = 8-(mathfloor(mathlog10(mathabs(dVal)))+1)
	local iDecMax = iDecMin-7
	-- result always needs to be rounded at least once, even if the result is not the same as the original equiv. float value
	local dResult = CorrectDbl(dVal,0.5,iDecMin)
	-- search for the least number of decimals, while still keeping the same single value
	local dTest
	for iDec = iDecMin-1,iDecMax,-1 do
		dTest = CorrectDbl(dVal,0.5,iDec) -- test value with ever less precision
		if dTest ~= dResult then
			if EquSng(dTest) == dVal then
				dResult = dTest
			else
				-- (test)value contains no longer the same single value
				break
			end
		end
	end
	return dResult
end

-- ****************** Calculation Type support functions ******************

-- DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
-- DataTableValue: Takes a value from an array table.
local function DataTableValue(vDataArray,dIndex)
	local iIndex = RoundDbl(dIndex)
	if iIndex <= 1 then
		return vDataArray[1]
	elseif iIndex > #vDataArray then
		return vDataArray[#vDataArray]
	else
		return vDataArray[iIndex]
	end
end

-- EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
-- ExpFmod: Exponential function based on percentage.
-- Common percentage values are around ~5.5% for between levels and ~20% jumps between level segments.
local function ExpFmod(dVal,dLstart,dPlvl,dLvl,vDec,vAdd)
	local dRng = dLvl-dLstart+1.0
	if dRng <= DblCalcDev then
		return dVal
	else
		local dFac = 1.0+dPlvl/100.0
		local dAdd
		if vAdd == nil then
			dAdd = 0.0
		else
			dAdd = vAdd
		end
		if vDec == nil then
			local dFacExp = dFac^dRng
			return dVal*dFacExp+dAdd*((dFacExp-1.0)/(dFac-1.0))
		else
			local dResult = dVal
			local dLm = dLstart-DblCalcDev
			while dLm <= dLvl do
				dResult = RoundDbl(dResult*dFac+dAdd,vDec)
				dLm = dLm+1.0
			end
			return dResult
		end
	end
end

-- PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
-- CalcPercAB: Calculates the percentage out of a rating based on the AB formula.
local function CalcPercAB(dA,dB,dPCap,dR)
	if dR <= DblCalcDev then
		return 0.0
	else
		local dResult = dA/(1.0+dB/dR)
		if dResult >= dPCap-DblCalcDev then
			return dPCap
		else
			return dResult
		end
	end
end

-- RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
-- CalcRatAB: Calculates the rating out of a percentage based on the AB formula.
local function CalcRatAB(dA,dB,dCapR,dP)
	if dP <= DblCalcDev then
		return 0.0
	else
		local dResult = dB/(dA/dP-1.0)
		if dResult >= dCapR-DblCalcDev then
			return dCapR
		else
			return dResult
		end
	end
end

local CalcStat
local LinFmod

-- SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
-- StatLinInter: (Normalized) Stat Linear Interpolating
local function StatLinInter(sPntMP,sProgScheme,sProgBase,sAdj,dLvl,vNorC,vRoundType)
	-- parameter processing
	local dN = 1.0
	local sC = ""
	if type(vNorC) == "number" then
		dN = vNorC
	elseif type(vNorC) == "string" then
		sC = vNorC
	end
	local iRoundType = 0
	if type(vRoundType) == "number" then
		iRoundType = vRoundType
	end
	local dProgScheme = CalcStat(sProgScheme,dLvl)
	if type(dProgScheme) ~= "table" then
		return 0.0
	end

	-- find level interval
	local dLvlMinus = dLvl-DblCalcDev
	local iPointIndexHigh = 2
	local iPointIndexMax = #dProgScheme[1]
	while iPointIndexHigh < iPointIndexMax do
		if dLvlMinus <= dProgScheme[1][iPointIndexHigh] then
			break
		end
		iPointIndexHigh = iPointIndexHigh+1
	end
	local iPointIndexLow = iPointIndexHigh-1

	local dAccessLvlLow = dProgScheme[1][iPointIndexLow]
	local dAccessLvlHigh = dProgScheme[1][iPointIndexHigh]
	local dBaseLvlLow = dProgScheme[2][iPointIndexLow]
	local dBaseLvlHigh = dProgScheme[2][iPointIndexHigh]

	-- get values from base progression
	local dValLow = CalcStat(sProgBase,dBaseLvlLow,sC)
	local dValHigh = CalcStat(sProgBase,dBaseLvlHigh,sC)

	-- graph point multiplications
	if type(sPntMP) == "string" and sPntMP ~= "" then
		dValLow = dValLow*CalcStat(sPntMP,dAccessLvlLow,sC)
		dValHigh = dValHigh*CalcStat(sPntMP,dAccessLvlHigh,sC)
	end
	if type(sAdj) == "string" and sAdj ~= "" then
		dValLow = dValLow*CalcStat(sAdj,dAccessLvlLow,sC)
		dValHigh = dValHigh*CalcStat(sAdj,dAccessLvlHigh,sC)
	end
	dValLow = dValLow*dN
	dValHigh = dValHigh*dN

	-- graph point roundings
	if iRoundType == 0 then
		dValLow = RoundDblLotro(dValLow)
		dValHigh = RoundDblLotro(dValHigh)
	elseif iRoundType == 1 then
		if -100.0 <= dValLow and dValLow <= 100.0 then
			dValLow = RoundDblUp(dValLow,2)
		elseif -1000.0 <= dValLow and dValLow <= 1000.0 then
			dValLow = RoundDblUp(dValLow,1)
		else
			dValLow = RoundDblLotro(dValLow)
		end
		if -100.0 <= dValHigh and dValHigh <= 100.0 then
			dValHigh = RoundDblUp(dValHigh,2)
		elseif -1000.0 <= dValHigh and dValHigh <= 1000.0 then
			dValHigh = RoundDblUp(dValHigh,1)
		else
			dValHigh = RoundDblLotro(dValHigh)
		end
	elseif iRoundType == 2 then
		dValLow = RoundDblLotro(dValLow)
		if dValLow == -1.0 then
			dValLow = -2.0
		end
		dValHigh = RoundDblLotro(dValHigh)
		if dValHigh == -1.0 then
			dValHigh = -2.0
		end
	elseif iRoundType == 3 then
		dValLow = RoundDblProg(dValLow)
		dValHigh = RoundDblProg(dValHigh)
	elseif iRoundType == 4 then
		dValLow = RoundDbl(dValLow,0)
		dValHigh = RoundDbl(dValHigh,0)
	end

	-- return interpolated value from the calculated graph points
	return LinFmod(1.0,dValLow,dValHigh,dAccessLvlLow,dAccessLvlHigh,dLvl)
end

-- TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
-- LinFmod: Linear line function between 2 points with some optional modifications.
-- Connects point (dLstart,dVal*dFstart) with (dLend,dVal*dFend).
-- Usually used with dVal=1 and dFstart/dFend containing unrelated points or dVal=# and dFstart/dFend containing multiplier factors.
-- Modification for in-between points on the line: rounding.
LinFmod = function(dVal,dFstart,dFend,dLstart,dLend,dLvl,vDec)
	if type(vDec) == "string" then
		local sRoundType = strupper(vDec)
		if sRoundType == "P" then
			return LinFmod(1.0,RoundDblProg(dVal*dFstart),RoundDblProg(dVal*dFend),dLstart,dLend,dLvl)
		elseif sRoundType == "L" then
			return LinFmod(1.0,RoundDblLotro(dVal*dFstart),RoundDblLotro(dVal*dFend),dLstart,dLend,dLvl)
		else
			return LinFmod(1.0,dVal*dFstart,dVal*dFend,dLstart,dLend,dLvl)
		end
	end
	if dLstart-DblCalcDev <= dLvl and dLvl <= dLstart+DblCalcDev then
		return dVal*dFstart
	elseif dLend-DblCalcDev <= dLvl and dLvl <= dLend+DblCalcDev then
		return dVal*dFend
	elseif dLstart == dLend then
		return 0.0
	elseif vDec == nil then
		return dVal*(dFstart*(dLend-dLvl)+(dLvl-dLstart)*dFend)/(dLend-dLstart)
	else
		return RoundDbl(dVal*(dFstart*(dLend-dLvl)+(dLvl-dLstart)*dFend)/(dLend-dLstart),vDec)
	end
end

-- **************** Parameter "C" decode support functions ****************

-- ArmCodeIndex: returns a specified index from an Armour Code.
-- sACode string:
-- 1st position: H=heavy, M=medium, L=light
-- 2nd position: H=head, S=shoulders, CL=cloak/back, C=chest, G=gloves, L=leggings, B=boots, Sh=shield
-- 3rd position: W=white/common, Y=yellow/uncommon, P=purple/rare, T=teal/blue/incomparable, G=gold/legendary/epic
-- Note: no such thing exists as a heavy, medium or light cloak, so no H/M/L in cloak codes (cloaks go automatically in the M class since U23, although historically this was L)
local function ArmCodeIndex(sACode,iI)
	if sACode == nil or iI == nil then
		return 0
	end
	if type(sACode) ~= "string" or type(iI) ~= "number" then
		return 0
	end

	local sArmCode = strmatch(sACode,"(%a+)")
	if not sArmCode then
		return 0
	end
	sArmCode = strupper(sArmCode).."    "

	local sArmCat = strsub(sArmCode,1,1)
	local sArmType = strsub(sArmCode,2,2)
	local sArmCol = strsub(sArmCode,3,3)

	if sArmType == "S" and sArmCol == "H" then
		sArmType = "SH"
		sArmCol = strsub(sArmCode,4,4)
	elseif sArmCat == "C" and sArmType == "L" then
		sArmCat = "M"
		sArmType = "CL"
	elseif sArmType then
		sArmType = " "..sArmType
	end

	local result = 0
	if iI == 1 then
		if sArmCat then
			result = strfind("HML",sArmCat)
		end
	elseif iI == 2 then
		if sArmType then
			result = strfind(" H SCL C G L BSH",sArmType)
			if result then
				result = (result+1)/2
			end
		end
	elseif iI == 3 then
		if sArmCol then
			result = strfind("WYPTG",sArmCol)
		end
	end

	if result then
		return result
	else
		return 0
	end
end

-- QualityCodeIndex: returns a quality index from a Quality Code.
-- sQCode string: W=white/common, Y=yellow/uncommon, P=purple/rare, T=teal/blue/incomparable, G=gold/legendary/epic
local function QualityCodeIndex(sQCode)
	if sQCode == nil then
		return 0
	end
	if type(sQCode) ~= "string" then
		return 0
	end

	local sQtyCode = strmatch(sQCode,"(%a+)")
	if not sQtyCode then
		return 0
	end
	sQtyCode = strupper(sQtyCode).." "

	local sQtyCol = strsub(sQtyCode,1,1)

	local result = 0
	if sQtyCol then
		result = strfind("WYPTG",sQtyCol)
	end

	if result then
		return result
	else
		return 0
	end
end

-- WpnCodeIndex: returns a specified index from a Weapon Code.
-- sWCode string:
-- 1st position: H=heavy, L=light
-- 2nd position: O=one-handed, T=two-handed, B=bow
-- 3rd position: W=white/common, Y=yellow/uncommon, P=purple/rare, T=teal/blue/incomparable, G=gold/legendary/epic
local function WpnCodeIndex(sWCode,iI)
	if sWCode == nil or iI == nil then
		return 0
	end
	if type(sWCode) ~= "string" or type(iI) ~= "number" then
		return 0
	end

	local sWpnCode = strmatch(sWCode,"(%a+)")
	if not sWpnCode then
		return 0
	end
	sWpnCode = strupper(sWpnCode).."   "

	local sWpnCat = strsub(sWpnCode,1,1)
	local sWpnType = strsub(sWpnCode,2,2)
	local sWpnCol = strsub(sWpnCode,3,3)

	local result = 0
	if iI == 1 then
		if sWpnCat then
			result = strfind("HL",sWpnCat)
		end
	elseif iI == 2 then
		if sWpnType then
			result = strfind("OTB",sWpnType)
		end
	elseif iI == 3 then
		if sWpnCol then
			result = strfind("WYPTG",sWpnCol)
		end
	end

	if result then
		return result
	else
		return 0
	end
end

-- RomanRankDecode: converts a string with a Roman number in characters, to an integer number.
-- used for Legendary Item Title calculation.
local RomanCharsToValues = {["M"]=1000,["CM"]=900,["D"]=500,["CD"]=400,["C"]=100,["XC"]=90,["L"]=50,["XL"]=40,["X"]=10,["IX"]=9,["V"]=5,["IV"]=4,["I"]=1}
local function RomanRankDecode(sNumber)
	if sNumber ~= nil and type(sNumber) == "string" and sNumber ~= "" then
		for sRomanRankChar, iRomanRankValue in pairs(RomanCharsToValues) do
			if strsub(strupper(sNumber),1,#sRomanRankChar) == sRomanRankChar then
				return iRomanRankValue+RomanRankDecode(strsub(sNumber,#sRomanRankChar+1))
			end
		end
	end
	return 0
end

-- ************************ Main CalcStat function ************************

CalcStat = function(SName,SLvl,SParam)
	-- process parameters and parameter defaults

	local sStatName = trim(SName)
	if sStatName == "" then
		return 0, {Source = "CalcStat", Code = -1, Message = "Missing stat name"}
	end

	local SN
	repeat
		SN = strmatch(sStatName,"^-?%a%w*%a$") -- allow nested digits in stat name and a starting -
		if SN then break end
		SN = strmatch(sStatName,"^-?%a$") -- to allow single character stat name as well
		if SN then break end
		return 0, {Source = "CalcStat", Code = -2, Message = "Illegal stat name", Detail = "Stat '"..sStatName.."'"}
	until true
	SN = strupper(SN) -- uppercase and trimmed for keyword matching
	
	local L = 1.0 -- default L
	if type(SLvl) == "number" then
		L = SLvl
	elseif type(SLvl) ~= "nil" then
		return 0, {Source = "CalcStat", Code = -3, Message = "Illegal level", Detail = "Stat '"..SN.."' [Level:"..type(SLvl)..", Expecting:number,nil]"}
	end
	local Lm = L-DblCalcDev
	local Lp = L+DblCalcDev

	local N = 1.0 -- default N
	local C = "" -- default C
	if type(SParam) == "number" then
		N = SParam
	elseif type(SParam) == "string" then
		C = SParam
	elseif type(SParam) ~= "nil" then
		return 0, {Source = "CalcStat", Code = -4, Message = "Illegal N or C", Detail = "Stat '"..SN.."' [N or C:"..type(SParam)..", Expecting:number,string,nil]"}
	end

	local Result = 0.0

	-- binary search tree (generated code)

	if SN < "MINSTRELCDARMOURTOCOMPHYMIT" then
		if SN < "CPTSHIELDPHYMAS" then
			if SN < "BRAWLERCDVITALITYTONCMR" then
				if SN < "BEORNINGCDARMOURTYPE" then
					if SN < "AWARDILVLDB" then
						if SN < "ARMOURPROGB" then
							if SN < "AGILITYC" then
								if SN < "ADJITEMMAS" then
									if SN < "ADJCREEPITEM" then
										if SN < "ACIDMIT" then
											if SN == "-VERSION" then
												Result = "2.4.13f"
											end
										elseif SN > "ACIDMIT" then
											if SN == "ACIDMITT" then
												Result = CalcStat("DmgTypeMitT",L,N)
											end
										else
											Result = CalcStat("DmgTypeMit",L,N)
										end
									elseif SN > "ADJCREEPITEM" then
										if SN < "ADJCREEPITEMPOWER" then
											if SN == "ADJCREEPITEMMIT" then
												if 450 <= Lp and Lm <= 499 then
													Result = 0.9235
												elseif 500 <= Lp and Lm <= 500 then
													Result = 0.9215
												elseif 549 <= Lp and Lm <= 549 then
													Result = 0.9913
												else
													Result = 1
												end
											end
										elseif SN > "ADJCREEPITEMPOWER" then
											if SN == "ADJITEM" then
												if 499 <= Lp and Lm <= 550 then
													Result = 0.9
												else
													Result = 1
												end
											end
										else
											if 450 <= Lp and Lm <= 499 then
												Result = 0.9
											elseif 500 <= Lp and Lm <= 500 then
												Result = 0.9
											elseif 549 <= Lp and Lm <= 549 then
												Result = 0.9775
											else
												Result = 1
											end
										end
									else
										if 450 <= Lp and Lm <= 499 then
											Result = 0.92253
										elseif 500 <= Lp and Lm <= 500 then
											Result = 0.923
										elseif 549 <= Lp and Lm <= 549 then
											Result = 0.9902
										else
											Result = 1
										end
									end
								elseif SN > "ADJITEMMAS" then
									if SN < "ADJTRAITMIT" then
										if SN < "ADJTRAIT" then
											if SN == "ADJITEMMIT" then
												if 499 <= Lp and Lm <= 499 then
													Result = 0.78
												elseif 500 <= Lp and Lm <= 550 then
													Result = 0.7
												else
													Result = 1
												end
											end
										elseif SN > "ADJTRAIT" then
											if SN == "ADJTRAITMAS" then
												if 141 <= Lp and Lm <= 141 then
													Result = 0.9
												elseif 150 <= Lp and Lm <= 160 then
													Result = 0.8235
												else
													Result = 1
												end
											end
										else
											if 141 <= Lp and Lm <= 150 then
												Result = 0.9
											else
												Result = 1
											end
										end
									elseif SN > "ADJTRAITMIT" then
										if SN < "ADJVIRTUEMORALE" then
											if SN == "ADJVIRTUEMAS" then
												if Lm <= 0 then
													Result = 0
												elseif 399 <= Lp and Lm <= 399 then
													Result = 1.098
												elseif 499 <= Lp and Lm <= 499 then
													Result = 0.9
												elseif 500 <= Lp and Lm <= 550 then
													Result = 0.8235
												else
													Result = 1
												end
											end
										elseif SN > "ADJVIRTUEMORALE" then
											if SN == "AGILITY" then
												Result = CalcStat("Main",L,N)
											end
										else
											if Lm <= 0 then
												Result = 0
											elseif 50 <= Lp and Lm <= 50 then
												Result = 2
											elseif 60 <= Lp and Lm <= 80 then
												Result = 1.5
											elseif 499 <= Lp and Lm <= 499 then
												Result = 0.9475
											else
												Result = 1
											end
										end
									else
										if 141 <= Lp and Lm <= 141 then
											Result = 0.78
										elseif 150 <= Lp and Lm <= 160 then
											Result = 0.7
										else
											Result = 1
										end
									end
								else
									if 499 <= Lp and Lm <= 499 then
										Result = 0.9
									elseif 500 <= Lp and Lm <= 550 then
										Result = 0.8235
									else
										Result = 1
									end
								end
							elseif SN > "AGILITYC" then
								if SN < "ARMOURCI" then
									if SN < "ARMCATMP" then
										if SN < "AGILITYT" then
											if SN == "AGILITYCI" then
												Result = CalcStat("MainCI",L,N)
											end
										elseif SN > "AGILITYT" then
											if SN == "ALIGNMENTNAME" then
												if 1 <= Lp and Lm <= 1 then
													Result = "Good"
												elseif 2 <= Lp and Lm <= 2 then
													Result = "Neutral"
												elseif 3 <= Lp and Lm <= 3 then
													Result = "Evil"
												else
													Result = ""
												end
											end
										else
											Result = CalcStat("MainT",L,N)
										end
									elseif SN > "ARMCATMP" then
										if SN < "ARMOUR" then
											if SN == "ARMCATPROGB" then
												if 1 <= Lp and Lm <= 1 then
													Result = CalcStat("ProgBArmourHeavy",N)
												elseif 2 <= Lp and Lm <= 2 then
													Result = CalcStat("ProgBArmourMedium",N)
												elseif 3 <= Lp and Lm <= 3 then
													Result = CalcStat("ProgBArmourLight",N)
												end
											end
										elseif SN > "ARMOUR" then
											if SN == "ARMOURC" then
												Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("ArmourCI",CalcStat("ArmourCILvlFilter",N),N),0)
											end
										else
											Result = RoundDblDown(StatLinInter("ArmourPntMP","ItemPntS","ArmourProgB","AdjItemMit",L,C,0))
										end
									else
										Result = CalcStat("PntMPArmour",L)
									end
								elseif SN > "ARMOURCI" then
									if SN < "ARMOURLOW" then
										if SN < "ARMOURCIRAW" then
											if SN == "ARMOURCILVLFILTER" then
												if 5.6 <= Lp and Lm <= 5.6 then
													Result = 515
												else
													Result = CalcStat("CreepILvlCurr",L)
												end
											end
										elseif SN > "ARMOURCIRAW" then
											if SN == "ARMOURCRAW" then
												Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("ArmourCIRaw",CalcStat("ArmourCILvlFilter",N),N),99)
											end
										else
											Result = StatLinInter("PntMPArmourC","ItemPntS","ProgBArmour","AdjCreepItemMit",L,N,4)
										end
									elseif SN > "ARMOURLOW" then
										if SN < "ARMOURPENT" then
											if SN == "ARMOURLOWPNTMP" then
												Result = CalcStat("ArmTypeMP",ArmCodeIndex(C,2))*CalcStat("ArmQtyLowMP",ArmCodeIndex(C,2))*CalcStat("ArmCatMP",ArmCodeIndex(C,1))
											end
										elseif SN > "ARMOURPENT" then
											if SN == "ARMOURPNTMP" then
												Result = CalcStat("ArmTypeMP",ArmCodeIndex(C,2))*CalcStat("ArmQtyMP",ArmCodeIndex(C,3),ArmCodeIndex(C,2))*CalcStat("ArmCatMP",ArmCodeIndex(C,1))
											end
										else
											Result = EquSng(StatLinInter("PntMPArmourPenT","TraitPntS","ProgBArmour","",L,N,0))
										end
									else
										Result = RoundDblDown(StatLinInter("ArmourLowPntMP","ItemPntS","ArmourProgB","AdjItemMit",L,C,0))
									end
								else
									Result = RoundDblLotro(CalcStat("ArmourCIRaw",L,N))
								end
							else
								Result = CalcStat("MainC",L,N)
							end
						elseif SN > "ARMOURPROGB" then
							if SN < "AWARDILVLB" then
								if SN < "ARMQTYUNCOMMP" then
									if SN < "ARMQTYINCOMPMP" then
										if SN < "ARMQTYCOMMMP" then
											if SN == "ARMOURT" then
												Result = EquSng(StatLinInter("PntMPArmourT","TraitPntS","ProgBArmour","AdjTraitMit",L,N,0))
											end
										elseif SN > "ARMQTYCOMMMP" then
											if SN == "ARMQTYEPICMP" then
												if 1 <= Lp and Lm <= 8 then
													Result = DataTableValue({1,1,1,1,1,1.002,1,1},L)
												end
											end
										else
											if 1 <= Lp and Lm <= 8 then
												Result = DataTableValue({22/30,22/30,0.8,0.8,0.76,0.804,0.8,0.7},L)
											end
										end
									elseif SN > "ARMQTYINCOMPMP" then
										if SN < "ARMQTYMP" then
											if SN == "ARMQTYLOWMP" then
												if 1 <= Lp and Lm <= 8 then
													Result = DataTableValue({12/33,12/33,12/33,12/33,12/33,0.996*12/33,12/33,12/33},L)
												end
											end
										elseif SN > "ARMQTYMP" then
											if SN == "ARMQTYRAREMP" then
												if 1 <= Lp and Lm <= 8 then
													Result = DataTableValue({26/30,26/30,0.9,0.9,0.88,0.9,0.9,0.8},L)
												end
											end
										else
											if 1 <= Lp and Lm <= 1 then
												Result = CalcStat("ArmQtyCommMP",N)
											elseif 2 <= Lp and Lm <= 2 then
												Result = CalcStat("ArmQtyUncomMP",N)
											elseif 3 <= Lp and Lm <= 3 then
												Result = CalcStat("ArmQtyRareMP",N)
											elseif 4 <= Lp and Lm <= 4 then
												Result = CalcStat("ArmQtyIncompMP",N)
											elseif 5 <= Lp and Lm <= 5 then
												Result = CalcStat("ArmQtyEpicMP",N)
											end
										end
									else
										if 1 <= Lp and Lm <= 8 then
											Result = DataTableValue({28/30,28/30,0.95,0.95,0.94,0.948,0.95,0.95},L)
										end
									end
								elseif SN > "ARMQTYUNCOMMP" then
									if SN < "AWARDILVLAA" then
										if SN < "AUTOLVLTOILVL" then
											if SN == "ARMTYPEMP" then
												if 1 <= Lp and Lm <= 8 then
													Result = DataTableValue({9,9,20,30,15,25,12,32.726},L)
												end
											end
										elseif SN > "AUTOLVLTOILVL" then
											if SN == "AWARDILVLA" then
												if Lm <= 75 then
													Result = L
												elseif Lm <= 94 then
													Result = 5*L-304
												elseif Lm <= 95 then
													Result = 173
												elseif Lm <= 100 then
													Result = 5*L-304
												elseif Lm <= 101 then
													Result = 197
												elseif Lm <= 104 then
													Result = 4*L-206
												elseif Lm <= 105 then
													Result = 218
												elseif Lm <= 110 then
													Result = RoundDbl(LinFmod(1,295,303.8,106,110,L))
												elseif Lm <= 115 then
													Result = 304
												elseif Lm <= 119 then
													Result = RoundDbl(LinFmod(1,345,357,116,119,L))
												elseif Lm <= 120 then
													Result = 359
												elseif Lm <= 130 then
													Result = 395
												elseif Lm <= 140 then
													Result = RoundDbl(LinFmod(1,445.4,455.4,131,140,L))
												elseif Lm <= 150 then
													Result = RoundDbl(LinFmod(1,479.4,491.4,141,150,L))
												else
													Result = CalcStat("AwardILvlA",150)
												end
											end
										else
											Result = CalcStat("AwardILvlCC",L)
										end
									elseif SN > "AWARDILVLAA" then
										if SN < "AWARDILVLAC" then
											if SN == "AWARDILVLAB" then
												if 75 <= Lp and Lm <= 75 then
													Result = CalcStat("AwardILvlA",L)+1
												else
													Result = CalcStat("AwardILvlA",L)
												end
											end
										elseif SN > "AWARDILVLAC" then
											if SN == "AWARDILVLAOLD" then
												Result = CalcStat("AwardILvlA",L)
											end
										else
											if 75 <= Lp and Lm <= 75 then
												Result = CalcStat("AwardILvlA",L)+2
											else
												Result = CalcStat("AwardILvlA",L)
											end
										end
									else
										if 75 <= Lp and Lm <= 75 then
											Result = CalcStat("AwardILvlA",L)+3
										else
											Result = CalcStat("AwardILvlA",L)
										end
									end
								else
									if 1 <= Lp and Lm <= 8 then
										Result = DataTableValue({22/30,22/30,0.85,0.85,0.82,0.852,0.85,0.75},L)
									end
								end
							elseif SN > "AWARDILVLB" then
								if SN < "AWARDILVLCE" then
									if SN < "AWARDILVLCA" then
										if SN < "AWARDILVLBOLD" then
											if SN == "AWARDILVLBA" then
												Result = CalcStat("AwardILvlB",L)
											end
										elseif SN > "AWARDILVLBOLD" then
											if SN == "AWARDILVLC" then
												if Lm <= 75 then
													Result = CalcStat("AwardILvlB",L)
												else
													Result = CalcStat("AwardILvlA",L)
												end
											end
										else
											Result = CalcStat("AwardILvlB",L)
										end
									elseif SN > "AWARDILVLCA" then
										if SN < "AWARDILVLCC" then
											if SN == "AWARDILVLCB" then
												if Lm <= 10 then
													Result = CalcStat("AwardILvlA",1)
												elseif Lm <= 85 then
													Result = CalcStat("AwardILvlA",L)-10
												elseif 96 <= Lp and Lm <= 99 then
													Result = CalcStat("AwardILvlA",L)+4
												elseif 100 <= Lp and Lm <= 100 then
													Result = CalcStat("AwardILvlA",L)+6
												else
													Result = CalcStat("AwardILvlA",L)
												end
											end
										elseif SN > "AWARDILVLCC" then
											if SN == "AWARDILVLCD" then
												if Lm <= 8 then
													Result = CalcStat("AwardILvlA",1)
												elseif Lm <= 85 then
													Result = CalcStat("AwardILvlA",L)-8
												elseif Lm <= 100 then
													Result = CalcStat("AwardILvlA",L)-4
												elseif Lm <= 105 then
													Result = CalcStat("AwardILvlA",L)+4
												else
													Result = CalcStat("AwardILvlA",L)
												end
											end
										else
											Result = CalcStat("AwardILvlC",L)
										end
									else
										if Lm <= 8 then
											Result = CalcStat("AwardILvlA",1)
										elseif Lm <= 85 then
											Result = CalcStat("AwardILvlA",L)-8
										elseif 96 <= Lp and Lm <= 100 then
											Result = CalcStat("AwardILvlA",L)+4
										else
											Result = CalcStat("AwardILvlA",L)
										end
									end
								elseif SN > "AWARDILVLCE" then
									if SN < "AWARDILVLCI" then
										if SN < "AWARDILVLCG" then
											if SN == "AWARDILVLCF" then
												if Lm <= 140 then
													Result = CalcStat("AwardILvlC",L)
												elseif Lm <= 150 then
													Result = RoundDbl(LinFmod(1,500.4,517.4,141,150,L))
												else
													Result = CalcStat("AwardILvlCF",150)
												end
											end
										elseif SN > "AWARDILVLCG" then
											if SN == "AWARDILVLCH" then
												if Lm <= 140 then
													Result = CalcStat("AwardILvlC",L)
												elseif Lm <= 150 then
													Result = RoundDbl(LinFmod(1,500.4,525.4,141,150,L))
												else
													Result = CalcStat("AwardILvlCH",150)
												end
											end
										else
											if Lm <= 140 then
												Result = CalcStat("AwardILvlC",L)
											elseif Lm <= 150 then
												Result = RoundDbl(LinFmod(1,500.4,520.4,141,150,L))
											else
												Result = CalcStat("AwardILvlCG",150)
											end
										end
									elseif SN > "AWARDILVLCI" then
										if SN < "AWARDILVLD" then
											if SN == "AWARDILVLCJ" then
												if Lm <= 140 then
													Result = CalcStat("AwardILvlC",L)
												elseif Lm <= 150 then
													Result = RoundDbl(LinFmod(1,500.4,535.4,141,150,L))
												else
													Result = CalcStat("AwardILvlCJ",150)
												end
											end
										elseif SN > "AWARDILVLD" then
											if SN == "AWARDILVLDA" then
												if 106 <= Lp and Lm <= 115 then
													Result = RoundDbl(LinFmod(1,300,336.5,106,115,L))
												else
													Result = CalcStat("AwardILvlD",L)
												end
											end
										else
											if Lm <= 105 then
												Result = CalcStat("AwardILvlC",L)
											elseif Lm <= 115 then
												Result = 300
											else
												Result = CalcStat("AwardILvlA",L)
											end
										end
									else
										if Lm <= 140 then
											Result = CalcStat("AwardILvlC",L)
										elseif Lm <= 150 then
											Result = RoundDbl(LinFmod(1,500.4,530.4,141,150,L))
										else
											Result = CalcStat("AwardILvlCI",150)
										end
									end
								else
									if Lm <= 140 then
										Result = CalcStat("AwardILvlC",L)
									elseif Lm <= 150 then
										Result = RoundDbl(LinFmod(1,500.4,512.4,141,150,L))
									else
										Result = CalcStat("AwardILvlCE",150)
									end
								end
							else
								if Lm <= 4 then
									Result = CalcStat("AwardILvlA",1)
								elseif Lm <= 50 then
									Result = CalcStat("AwardILvlA",L-4)
								elseif Lm <= 54 then
									Result = CalcStat("AwardILvlA",51)
								elseif Lm <= 75 then
									Result = CalcStat("AwardILvlA",L-4)
								elseif Lm <= 95 then
									Result = CalcStat("AwardILvlA",L)+4
								else
									Result = CalcStat("AwardILvlA",L)
								end
							end
						else
							Result = CalcStat("ArmCatProgB",ArmCodeIndex(C,1),L)
						end
					elseif SN > "AWARDILVLDB" then
						if SN < "AWARDLVLCAP" then
							if SN < "AWARDILVLGA" then
								if SN < "AWARDILVLEB" then
									if SN < "AWARDILVLDF" then
										if SN < "AWARDILVLDD" then
											if SN == "AWARDILVLDC" then
												if 106 <= Lp and Lm <= 110 then
													Result = RoundDbl(LinFmod(1,300,320,106,115,L))
												elseif 111 <= Lp and Lm <= 115 then
													Result = CalcStat("AwardILvlDC",110)
												else
													Result = CalcStat("AwardILvlD",L)
												end
											end
										elseif SN > "AWARDILVLDD" then
											if SN == "AWARDILVLDE" then
												if 106 <= Lp and Lm <= 115 then
													Result = RoundDbl(LinFmod(1,300.4,326.4,106,115,L))
												else
													Result = CalcStat("AwardILvlD",L)
												end
											end
										else
											if 106 <= Lp and Lm <= 114 then
												Result = RoundDbl(LinFmod(1,300,327,106,115,L))
											elseif 115 <= Lp and Lm <= 115 then
												Result = CalcStat("AwardILvlD",115)+30
											else
												Result = CalcStat("AwardILvlD",L)
											end
										end
									elseif SN > "AWARDILVLDF" then
										if SN < "AWARDILVLE" then
											if SN == "AWARDILVLDG" then
												if 106 <= Lp and Lm <= 114 then
													Result = RoundDbl(LinFmod(1,300,336,106,115,L))
												elseif 115 <= Lp and Lm <= 115 then
													Result = CalcStat("AwardILvlD",115)+40
												else
													Result = CalcStat("AwardILvlD",L)
												end
											end
										elseif SN > "AWARDILVLE" then
											if SN == "AWARDILVLEA" then
												if 116 <= Lp and Lm <= 119 then
													Result = RoundDbl(LinFmod(1,350,378,116,120,L))
												elseif 120 <= Lp and Lm <= 120 then
													Result = CalcStat("AwardILvlE",120)+26
												else
													Result = CalcStat("AwardILvlE",L)
												end
											end
										else
											if Lm <= 115 then
												Result = CalcStat("AwardILvlC",L)
											elseif Lm <= 120 then
												Result = 350
											else
												Result = CalcStat("AwardILvlA",L)
											end
										end
									else
										if 106 <= Lp and Lm <= 110 then
											Result = CalcStat("AwardILvlDF",111)
										elseif 111 <= Lp and Lm <= 115 then
											Result = RoundDbl(LinFmod(1,299.5,320.5,106,115,L))
										else
											Result = CalcStat("AwardILvlD",L)
										end
									end
								elseif SN > "AWARDILVLEB" then
									if SN < "AWARDILVLF" then
										if SN < "AWARDILVLED" then
											if SN == "AWARDILVLEC" then
												if 116 <= Lp and Lm <= 120 then
													Result = RoundDbl(LinFmod(1,350,382,116,120,L))
												else
													Result = CalcStat("AwardILvlE",L)
												end
											end
										elseif SN > "AWARDILVLED" then
											if SN == "AWARDILVLEE" then
												if 116 <= Lp and Lm <= 119 then
													Result = RoundDbl(LinFmod(1,350,366,116,120,L))
												elseif 120 <= Lp and Lm <= 120 then
													Result = CalcStat("AwardILvlE",120)+14
												else
													Result = CalcStat("AwardILvlE",L)
												end
											end
										else
											if 116 <= Lp and Lm <= 120 then
												Result = RoundDbl(LinFmod(1,350,370,116,120,L))
											else
												Result = CalcStat("AwardILvlE",L)
											end
										end
									elseif SN > "AWARDILVLF" then
										if SN < "AWARDILVLFB" then
											if SN == "AWARDILVLFA" then
												if Lm <= 9 then
													Result = RoundDbl(LinFmod(1,0.5,4.5,1,9,L))
												elseif Lm <= 19 then
													Result = LinFmod(1,6,15,10,19,L)
												elseif Lm <= 23 then
													Result = RoundDbl(LinFmod(1,15.5,17,20,23,L))
												elseif Lm <= 49 then
													Result = LinFmod(1,18,43,24,49,L)
												elseif Lm <= 65 then
													Result = LinFmod(1,43,58,50,65,L)
												elseif Lm <= 75 then
													Result = LinFmod(1,60,69,66,75,L)
												elseif Lm <= 84 then
													Result = CalcStat("AwardILvlF",L)
												elseif Lm <= 85 then
													Result = 120
												elseif Lm <= 93 then
													Result = CalcStat("AwardILvlF",L)
												elseif Lm <= 95 then
													Result = LinFmod(1,166,172,94,95,L)
												elseif Lm <= 119 then
													Result = CalcStat("AwardILvlF",L)
												elseif Lm <= 120 then
													Result = 368
												elseif Lm <= 129 then
													Result = RoundDbl(LinFmod(1,400,423,121,129,L))
												elseif Lm <= 130 then
													Result = 424
												elseif Lm <= 135 then
													Result = LinFmod(1,450,462,131,135,L)
												elseif Lm <= 139 then
													Result = LinFmod(1,463,472,136,139,L)
												elseif Lm <= 140 then
													Result = 473
												elseif Lm <= 150 then
													Result = RoundDbl(LinFmod(1,500.4,504.4,141,150,L))
												else
													Result = CalcStat("AwardILvlFA",150)
												end
											end
										elseif SN > "AWARDILVLFB" then
											if SN == "AWARDILVLG" then
												if Lm <= 120 then
													Result = CalcStat("AwardILvlC",L)
												elseif Lm <= 130 then
													Result = 400
												else
													Result = CalcStat("AwardILvlA",L)
												end
											end
										else
											if Lm <= 40 then
												Result = LinFmod(1,1,40,1,40,L)
											elseif Lm <= 45 then
												Result = LinFmod(1,40,44,41,45,L)
											elseif Lm <= 50 then
												Result = RoundDbl(LinFmod(1,45.4,47,46,50,L))
											elseif Lm <= 55 then
												Result = RoundDbl(LinFmod(1,51,54.4,51,55,L))
											elseif Lm <= 60 then
												Result = RoundDbl(LinFmod(1,54,57.4,56,60,L))
											elseif Lm <= 75 then
												Result = LinFmod(1,58,72,61,75,L)
											elseif Lm <= 84 then
												Result = CalcStat("AwardILvlF",L)
											elseif Lm <= 85 then
												Result = 122
											elseif Lm <= 93 then
												Result = CalcStat("AwardILvlF",L)
											elseif Lm <= 95 then
												Result = LinFmod(1,168,174,94,95,L)
											elseif Lm <= 119 then
												Result = CalcStat("AwardILvlF",L)
											elseif Lm <= 120 then
												Result = 380
											elseif Lm <= 125 then
												Result = LinFmod(1,400,416,121,125,L)
											elseif Lm <= 129 then
												Result = LinFmod(1,418,430,126,129,L)
											elseif Lm <= 130 then
												Result = 432
											elseif Lm <= 135 then
												Result = RoundDbl(LinFmod(1,450.4,463.8,131,135,L))
											elseif Lm <= 138 then
												Result = RoundDbl(LinFmod(1,465.8,472.8,136,138,L))
											elseif Lm <= 140 then
												Result = 475
											elseif Lm <= 150 then
												Result = RoundDbl(LinFmod(1,500.4,526.4,141,150,L))
											else
												Result = CalcStat("AwardILvlFB",150)
											end
										end
									else
										if Lm <= 75 then
											Result = 0
										elseif Lm <= 84 then
											Result = LinFmod(1,78,118,76,84,L)
										elseif Lm <= 85 then
											Result = 0
										elseif Lm <= 93 then
											Result = RoundDbl(LinFmod(1,129.4,163,86,93,L))
										elseif Lm <= 95 then
											Result = 0
										elseif Lm <= 100 then
											Result = RoundDbl(LinFmod(1,175,198.4,95,100,L))
										elseif Lm <= 104 then
											Result = LinFmod(1,201,213,101,104,L)
										elseif Lm <= 105 then
											Result = 220
										elseif Lm <= 114 then
											Result = RoundDbl(LinFmod(1,300,323,106,114,L))
										elseif Lm <= 115 then
											Result = 324
										elseif Lm <= 119 then
											Result = RoundDbl(LinFmod(1,349.6,368.4,116,120,L))
										end
									end
								else
									if 116 <= Lp and Lm <= 119 then
										Result = RoundDbl(LinFmod(1,350,390,116,120,L))
									elseif 120 <= Lp and Lm <= 120 then
										Result = CalcStat("AwardILvlE",120)+38
									else
										Result = CalcStat("AwardILvlE",L)
									end
								end
							elseif SN > "AWARDILVLGA" then
								if SN < "AWARDILVLIA" then
									if SN < "AWARDILVLGE" then
										if SN < "AWARDILVLGC" then
											if SN == "AWARDILVLGB" then
												if 121 <= Lp and Lm <= 130 then
													Result = RoundDbl(LinFmod(1,400.4,418.4,121,130,L))
												else
													Result = CalcStat("AwardILvlG",L)
												end
											end
										elseif SN > "AWARDILVLGC" then
											if SN == "AWARDILVLGD" then
												if 121 <= Lp and Lm <= 130 then
													Result = RoundDbl(LinFmod(1,400.4,426.4,121,130,L))
												else
													Result = CalcStat("AwardILvlG",L)
												end
											end
										else
											if 121 <= Lp and Lm <= 130 then
												Result = RoundDbl(LinFmod(1,400.4,408.3,121,130,L))
											else
												Result = CalcStat("AwardILvlG",L)
											end
										end
									elseif SN > "AWARDILVLGE" then
										if SN < "AWARDILVLH" then
											if SN == "AWARDILVLGF" then
												if 121 <= Lp and Lm <= 130 then
													Result = RoundDbl(LinFmod(1,400.4,440.4,121,130,L))
												else
													Result = CalcStat("AwardILvlG",L)
												end
											end
										elseif SN > "AWARDILVLH" then
											if SN == "AWARDILVLI" then
												if Lm <= 44 then
													Result = 1
												elseif Lm <= 55 then
													Result = 52
												elseif Lm <= 75 then
													Result = RoundDblDown((L-56)/5)*5+60
												elseif Lm <= 85 then
													Result = RoundDblDown((L-76)/5)*29+100
												elseif Lm <= 95 then
													Result = RoundDblDown((L-86)/5)*20+155
												elseif Lm <= 100 then
													Result = RoundDblDown((L-96)/4)*10+190
												elseif Lm <= 105 then
													Result = RoundDblDown((L-101)/4)*35+215
												elseif Lm <= 110 then
													Result = CalcStat("LvlToILvl",106)+15
												elseif Lm <= 115 then
													Result = CalcStat("LvlToILvl",115)
												elseif Lm <= 119 then
													Result = CalcStat("LvlToILvl",116)+15
												elseif Lm <= 120 then
													Result = CalcStat("LvlToILvl",120)
												elseif Lm <= 125 then
													Result = CalcStat("LvlToILvl",121)+15
												elseif Lm <= 130 then
													Result = CalcStat("LvlToILvl",130)
												elseif Lm <= 135 then
													Result = CalcStat("LvlToILvl",131)+15
												elseif Lm <= 140 then
													Result = CalcStat("LvlToILvl",140)
												elseif Lm <= 145 then
													Result = CalcStat("LvlToILvl",141)+15
												elseif Lm <= 150 then
													Result = CalcStat("LvlToILvl",150)
												else
													Result = CalcStat("AwardILvlI",150)
												end
											end
										else
											if Lm <= 4 then
												Result = CalcStat("AwardILvlA",1)
											elseif Lm <= 50 then
												Result = CalcStat("AwardILvlA",L-4)
											elseif Lm <= 54 then
												Result = CalcStat("AwardILvlA",51)
											elseif Lm <= 75 then
												Result = CalcStat("AwardILvlA",L-4)
											else
												Result = L-4
											end
										end
									else
										if 121 <= Lp and Lm <= 130 then
											Result = RoundDbl(LinFmod(1,400.4,434.4,121,130,L))
										else
											Result = CalcStat("AwardILvlG",L)
										end
									end
								elseif SN > "AWARDILVLIA" then
									if SN < "AWARDILVLJC" then
										if SN < "AWARDILVLJA" then
											if SN == "AWARDILVLJ" then
												if Lm <= 130 then
													Result = CalcStat("AwardILvlC",L)
												elseif Lm <= 140 then
													Result = RoundDbl(LinFmod(1,450.4,460.4,131,140,L))
												else
													Result = CalcStat("AwardILvlA",L)
												end
											end
										elseif SN > "AWARDILVLJA" then
											if SN == "AWARDILVLJB" then
												if 131 <= Lp and Lm <= 140 then
													Result = RoundDbl(LinFmod(1,450.4,470.4,131,140,L))
												else
													Result = CalcStat("AwardILvlJ",L)
												end
											end
										else
											if 131 <= Lp and Lm <= 140 then
												Result = RoundDbl(LinFmod(1,450.4,465.4,131,140,L))
											else
												Result = CalcStat("AwardILvlJ",L)
											end
										end
									elseif SN > "AWARDILVLJC" then
										if SN < "AWARDILVLK" then
											if SN == "AWARDILVLJD" then
												if 131 <= Lp and Lm <= 140 then
													Result = RoundDbl(LinFmod(1,450.4,480.4,131,140,L))
												else
													Result = CalcStat("AwardILvlJ",L)
												end
											end
										elseif SN > "AWARDILVLK" then
											if SN == "AWARDILVLL" then
												if Lm <= 50 then
													Result = CalcStat("AwardILvlB",L)
												elseif Lm <= 54 then
													Result = CalcStat("AwardILvlA",L)-3
												elseif Lm <= 74 then
													Result = CalcStat("AwardILvlA",L)-4
												elseif Lm <= 75 then
													Result = CalcStat("AwardILvlA",L)-5
												elseif Lm <= 95 then
													Result = CalcStat("AwardILvlA",L)-1
												elseif Lm <= 115 then
													Result = CalcStat("AwardILvlA",L)-2
												elseif Lm <= 120 then
													Result = CalcStat("AwardILvlA",L)
												elseif Lm <= 130 then
													Result = RoundDbl(LinFmod(1,397,400,121,130,L))
												elseif Lm <= 134 then
													Result = CalcStat("AwardILvlA",L)
												elseif Lm <= 137 then
													Result = DataTableValue({449,450,450},L-134)
												elseif Lm <= 140 then
													Result = CalcStat("AwardILvlL",L-3)
												elseif Lm <= 145 then
													Result = RoundDbl(LinFmod(1,495.4,500.4,141,145,L))
												elseif Lm <= 150 then
													Result = RoundDbl(LinFmod(1,500.5,502,146,150,L))
												else
													Result = CalcStat("AwardILvlL",150)
												end
											end
										else
											Result = CalcStat("CombatBaseTacHPSLvlToILvl",L)
										end
									else
										if 131 <= Lp and Lm <= 140 then
											Result = RoundDbl(LinFmod(1,450.4,475.4,131,140,L))
										else
											Result = CalcStat("AwardILvlJ",L)
										end
									end
								else
									if Lm <= 44 then
										Result = CalcStat("AwardILvlI",L)
									elseif Lm <= 55 then
										Result = RoundDblDown((L-45)/6)+51
									elseif Lm <= 90 then
										Result = CalcStat("AwardILvlI",L)
									elseif Lm <= 104 then
										Result = RoundDblDown((L-91)/5)*25+165
									elseif Lm <= 105 then
										Result = CalcStat("LvlToILvl",L)
									elseif Lm <= 110 then
										Result = CalcStat("LvlToILvl",106)+15
									elseif Lm <= 115 then
										Result = CalcStat("LvlToILvl",115)-20
									elseif Lm <= 120 then
										Result = CalcStat("LvlToILvl",116)+15
									elseif Lm <= 125 then
										Result = CalcStat("LvlToILvl",121)+15
									elseif Lm <= 130 then
										Result = CalcStat("LvlToILvl",130)-20
									elseif Lm <= 135 then
										Result = CalcStat("LvlToILvl",131)+15
									elseif Lm <= 140 then
										Result = CalcStat("LvlToILvl",140)-4
									elseif Lm <= 150 then
										Result = CalcStat("LvlToILvl",141)+15
									else
										Result = CalcStat("AwardILvlIA",150)
									end
								end
							else
								if 121 <= Lp and Lm <= 130 then
									Result = RoundDbl(LinFmod(1,400.4,412.4,121,130,L))
								else
									Result = CalcStat("AwardILvlG",L)
								end
							end
						elseif SN > "AWARDLVLCAP" then
							if SN < "BATTLELOREPHYMAS" then
								if SN < "BASEFATE" then
									if SN < "BALANCEOFMANBLOCK" then
										if SN < "AXEARMOURREND" then
											if SN == "AWARDLVLTOILVL" then
												Result = CalcStat("AwardILvlC",L)
											end
										elseif SN > "AXEARMOURREND" then
											if SN == "AXEARMRENDPOS" then
												if Lm <= 7 then
													Result = RoundDbl(LinFmod(1,0.5,3.25,1,7,L))
												elseif Lm <= 14 then
													Result = RoundDbl(LinFmod(1,3.75,8.5,8,14,L))
												elseif Lm <= 30 then
													Result = RoundDbl(LinFmod(1,9,24.7,15,30,L))
												elseif Lm <= 39 then
													Result = RoundDbl(LinFmod(1,26.5,37,31,39,L))
												elseif Lm <= 50 then
													Result = RoundDbl(LinFmod(1,38.5,53,40,50,L))
												elseif Lm <= 52 then
													Result = 53
												elseif Lm <= 60 then
													Result = RoundDbl(LinFmod(1,53.2,64.8,53,60,L))
												elseif Lm <= 77 then
													Result = RoundDbl(LinFmod(1,66.15,94.8,61,77,L))
												elseif Lm <= 113 then
													Result = RoundDbl(RoundDbl(L/3-0.5)*1.95+44.1)
												elseif Lm <= 141 then
													Result = 116
												elseif Lm <= 181 then
													Result = RoundDbl(RoundDbl(L/4)*2+46)
												elseif Lm <= 217 then
													Result = RoundDbl(RoundDbl(L/4)*2+45)
												elseif Lm <= 221 then
													Result = 153
												elseif Lm <= 299 then
													Result = 155
												elseif Lm <= 308 then
													Result = RoundDbl(RoundDbl(L/2.6-0.4)*2-73)
												elseif Lm <= 317 then
													Result = RoundDbl(RoundDbl(L/2.74-0.75)*2-60)
												elseif Lm <= 325 then
													Result = 172
												elseif Lm <= 326 then
													Result = 174
												elseif 327 <= Lp and Lm <= 599 then
													Result = EquSng(ExpFmod(CalcStat("AxeArmRendPos",326),327,1,L,1))
												else
													Result = CalcStat("AxeArmRendPos",599)
												end
											end
										else
											Result = -CalcStat("AxeArmRendPos",L)
										end
									elseif SN > "BALANCEOFMANBLOCK" then
										if SN < "BALANCEOFMANPARRY" then
											if SN == "BALANCEOFMANEVADE" then
												Result = CalcStat("EvadeT",L,1.0)
											end
										elseif SN > "BALANCEOFMANPARRY" then
											if SN == "BASEAGILITY" then
												Result = CalcStat("BaseMain",L,N)
											end
										else
											Result = CalcStat("ParryT",L,0.8)
										end
									else
										Result = CalcStat("BlockT",L,0.8)
									end
								elseif SN > "BASEFATE" then
									if SN < "BASEPOWER" then
										if SN < "BASEMIGHT" then
											if SN == "BASEMAIN" then
												if Lm <= 95 then
													Result = RoundDbl(CalcStat("ProgBMainBase",L)*N)
												else
													Result = RoundDbl(RoundDbl(CalcStat("ProgBMainBase",L))*N)
												end
											end
										elseif SN > "BASEMIGHT" then
											if SN == "BASEMORALE" then
												if Lm <= 95 then
													Result = RoundDblDown(CalcStat("ProgBHealth",L)*10)
												else
													Result = RoundDbl(RoundDbl(CalcStat("ProgBHealth",L))*10)
												end
											end
										else
											Result = CalcStat("BaseMain",L,N)
										end
									elseif SN > "BASEPOWER" then
										if SN < "BASEWILL" then
											if SN == "BASEVITALITY" then
												if Lm <= 95 then
													Result = RoundDbl(CalcStat("ProgBHealth",L)*1.5)
												else
													Result = RoundDbl(RoundDbl(CalcStat("ProgBHealth",L))*1.5)
												end
											end
										elseif SN > "BASEWILL" then
											if SN == "BATTLELOREMAS" then
												if Lm <= 105 then
													Result = CalcStat("Mastery",L,2.5)
												elseif 120 <= Lp and Lm <= 120 or 130 <= Lp and Lm <= 130 then
													Result = CalcStat("MasteryT",L,1.6)
												else
													Result = CalcStat("MasteryT",L,1.2)
												end
											end
										else
											Result = CalcStat("BaseMain",L,N)
										end
									else
										if Lm <= 95 then
											Result = RoundDblDown(CalcStat("ProgBEnergy",L)*10)
										else
											Result = RoundDbl(CalcStat("ProgBEnergy",L)*10)
										end
									end
								else
									if Lm <= 95 then
										Result = RoundDbl(CalcStat("ProgBEnergy",L)*7.0)
									else
										Result = RoundDbl(RoundDbl(CalcStat("ProgBEnergy",L),1)*7.0)
									end
								end
							elseif SN > "BATTLELOREPHYMAS" then
								if SN < "BEORNINGCDAGILITYTOCRITHIT" then
									if SN < "BEOFATE" then
										if SN < "BEOBEARFORMCRITDEF" then
											if SN == "BATTLELORETACMAS" then
												Result = CalcStat("BattleLoreMas",L)
											end
										elseif SN > "BEOBEARFORMCRITDEF" then
											if SN == "BEOEMISSARYFATE" then
												Result = CalcStat("FateT",L,1.0)
											end
										else
											Result = CalcStat("CritDefT",L,0.4)
										end
									elseif SN > "BEOFATE" then
										if SN < "BEOFEWINNUMBERFATE" then
											if SN == "BEOFERALPRESFATE" then
												Result = CalcStat("FateT",L,1.0)
											end
										elseif SN > "BEOFEWINNUMBERFATE" then
											if SN == "BEOMIGHTOFTHEWILDMIGHT" then
												Result = CalcStat("MightT",L,1.0)
											end
										else
											Result = -CalcStat("FateT",L,0.4)
										end
									else
										Result = CalcStat("FateT",L,CalcStat("Trait567810Choice",N)*0.4)
									end
								elseif SN > "BEORNINGCDAGILITYTOCRITHIT" then
									if SN < "BEORNINGCDAGILITYTOPHYMAS" then
										if SN < "BEORNINGCDAGILITYTOFINESSE" then
											if SN == "BEORNINGCDAGILITYTOEVADE" then
												Result = 1
											end
										elseif SN > "BEORNINGCDAGILITYTOFINESSE" then
											if SN == "BEORNINGCDAGILITYTOOUTHEAL" then
												Result = 2
											end
										else
											Result = 1
										end
									elseif SN > "BEORNINGCDAGILITYTOPHYMAS" then
										if SN < "BEORNINGCDARMOURTONONPHYMIT" then
											if SN == "BEORNINGCDARMOURTOCOMPHYMIT" then
												Result = 1
											end
										elseif SN > "BEORNINGCDARMOURTONONPHYMIT" then
											if SN == "BEORNINGCDARMOURTOTACMIT" then
												Result = 0.2
											end
										else
											Result = 0.2
										end
									else
										Result = 2
									end
								else
									Result = 2
								end
							else
								Result = CalcStat("BattleLoreMas",L)
							end
						else
							Result = 150
						end
					else
						if 106 <= Lp and Lm <= 115 then
							Result = RoundDbl(LinFmod(1,300,345,106,115,L))
						else
							Result = CalcStat("AwardILvlD",L)
						end
					end
				elseif SN > "BEORNINGCDARMOURTYPE" then
					if SN < "BLOCKT" then
						if SN < "BEORNINGCDWILLTOFINESSE" then
							if SN < "BEORNINGCDFATETOICMR" then
								if SN < "BEORNINGCDBASENCPR" then
									if SN < "BEORNINGCDBASEICPR" then
										if SN < "BEORNINGCDBASEFATE" then
											if SN == "BEORNINGCDBASEAGILITY" then
												Result = CalcStat("ClassBaseAgilityM",L)
											end
										elseif SN > "BEORNINGCDBASEFATE" then
											if SN == "BEORNINGCDBASEICMR" then
												Result = CalcStat("ClassBaseICMRM",L)
											end
										else
											Result = CalcStat("ClassBaseFate",L)
										end
									elseif SN > "BEORNINGCDBASEICPR" then
										if SN < "BEORNINGCDBASEMORALE" then
											if SN == "BEORNINGCDBASEMIGHT" then
												Result = CalcStat("ClassBaseMightM",L)
											end
										elseif SN > "BEORNINGCDBASEMORALE" then
											if SN == "BEORNINGCDBASENCMR" then
												Result = CalcStat("ClassBaseNCMRM",L)
											end
										else
											Result = CalcStat("ClassBaseMorale",L)
										end
									else
										Result = CalcStat("ClassBaseICPR",L)
									end
								elseif SN > "BEORNINGCDBASENCPR" then
									if SN < "BEORNINGCDCALCTYPECOMPHYMIT" then
										if SN < "BEORNINGCDBASEVITALITY" then
											if SN == "BEORNINGCDBASEPOWER" then
												Result = 10
											end
										elseif SN > "BEORNINGCDBASEVITALITY" then
											if SN == "BEORNINGCDBASEWILL" then
												Result = CalcStat("ClassBaseWillM",L)
											end
										else
											Result = CalcStat("ClassBaseVitality",L)
										end
									elseif SN > "BEORNINGCDCALCTYPECOMPHYMIT" then
										if SN < "BEORNINGCDCALCTYPETACMIT" then
											if SN == "BEORNINGCDCALCTYPENONPHYMIT" then
												Result = 14
											end
										elseif SN > "BEORNINGCDCALCTYPETACMIT" then
											if SN == "BEORNINGCDCANBLOCK" then
												if 6 <= Lp then
													Result = 1
												end
											end
										else
											Result = 27
										end
									else
										Result = 14
									end
								else
									Result = CalcStat("ClassBaseNCPR",L)
								end
							elseif SN > "BEORNINGCDFATETOICMR" then
								if SN < "BEORNINGCDMIGHTTOPHYMIT" then
									if SN < "BEORNINGCDMIGHTTOEVADE" then
										if SN < "BEORNINGCDFATETONCMR" then
											if SN == "BEORNINGCDFATETOMORALE" then
												Result = 2.5
											end
										elseif SN > "BEORNINGCDFATETONCMR" then
											if SN == "BEORNINGCDMIGHTTOCRITHIT" then
												Result = 1
											end
										else
											Result = 0.12
										end
									elseif SN > "BEORNINGCDMIGHTTOEVADE" then
										if SN < "BEORNINGCDMIGHTTOPARRY" then
											if SN == "BEORNINGCDMIGHTTOOUTHEAL" then
												Result = 3
											end
										elseif SN > "BEORNINGCDMIGHTTOPARRY" then
											if SN == "BEORNINGCDMIGHTTOPHYMAS" then
												Result = 3
											end
										else
											Result = 1
										end
									else
										Result = 2
									end
								elseif SN > "BEORNINGCDMIGHTTOPHYMIT" then
									if SN < "BEORNINGCDTACMASTOOUTHEAL" then
										if SN < "BEORNINGCDPHYMITTOCOMPHYMIT" then
											if SN == "BEORNINGCDMIGHTTOTACMIT" then
												Result = 1
											end
										elseif SN > "BEORNINGCDPHYMITTOCOMPHYMIT" then
											if SN == "BEORNINGCDPHYMITTONONPHYMIT" then
												Result = 1
											end
										else
											Result = 1
										end
									elseif SN > "BEORNINGCDTACMASTOOUTHEAL" then
										if SN < "BEORNINGCDVITALITYTOMORALE" then
											if SN == "BEORNINGCDVITALITYTOICMR" then
												Result = 0.012
											end
										elseif SN > "BEORNINGCDVITALITYTOMORALE" then
											if SN == "BEORNINGCDVITALITYTONCMR" then
												Result = 0.12
											end
										else
											Result = 4.5
										end
									else
										Result = 1
									end
								else
									Result = 1
								end
							else
								Result = 0.04
							end
						elseif SN > "BEORNINGCDWILLTOFINESSE" then
							if SN < "BLACKARROWCDCALCTYPENONPHYMIT" then
								if SN < "BEORNINGRDPSVTWONAME" then
									if SN < "BEORNINGCDWILLTORESIST" then
										if SN < "BEORNINGCDWILLTOPHYMAS" then
											if SN == "BEORNINGCDWILLTOOUTHEAL" then
												Result = 1
											end
										elseif SN > "BEORNINGCDWILLTOPHYMAS" then
											if SN == "BEORNINGCDWILLTOPHYMIT" then
												Result = 1.5
											end
										else
											Result = 1
										end
									elseif SN > "BEORNINGCDWILLTORESIST" then
										if SN < "BEORNINGRDPSVONEFATE" then
											if SN == "BEORNINGCDWILLTOTACMIT" then
												Result = 1.5
											end
										elseif SN > "BEORNINGRDPSVONEFATE" then
											if SN == "BEORNINGRDPSVONENAME" then
												Result = "Emissary"
											end
										else
											Result = CalcStat("BeoEmissaryFate",L)
										end
									else
										Result = 1
									end
								elseif SN > "BEORNINGRDPSVTWONAME" then
									if SN < "BEOTHICKHIDEVITALITY" then
										if SN < "BEORNINGRDTRAITMIGHT" then
											if SN == "BEORNINGRDTRAITFATE" then
												Result = CalcStat("BeoFewinNumberFate",L)
											end
										elseif SN > "BEORNINGRDTRAITMIGHT" then
											if SN == "BEORNINGRDTRAITVITALITY" then
												Result = CalcStat("BeoThickHideVitality",L)
											end
										else
											Result = CalcStat("BeoMightoftheWildMight",L)
										end
									elseif SN > "BEOTHICKHIDEVITALITY" then
										if SN < "BLACKARROWCANBLOCK" then
											if SN == "BEOVITALITYINCREASE" then
												Result = CalcStat("VitalityT",L,CalcStat("Trait567810Choice",N)*0.4)
											end
										elseif SN > "BLACKARROWCANBLOCK" then
											if SN == "BLACKARROWCDCALCTYPECOMPHYMIT" then
												Result = 13
											end
										else
											Result = 1
										end
									else
										Result = CalcStat("VitalityT",L,1.0)
									end
								else
									Result = ""
								end
							elseif SN > "BLACKARROWCDCALCTYPENONPHYMIT" then
								if SN < "BLOCKPBONUS" then
									if SN < "BLOCKC" then
										if SN < "BLACKARROWCDHASPOWER" then
											if SN == "BLACKARROWCDCALCTYPETACMIT" then
												Result = 27
											end
										elseif SN > "BLACKARROWCDHASPOWER" then
											if SN == "BLOCK" then
												Result = CalcStat("BPE",L,N)
											end
										else
											Result = 1
										end
									elseif SN > "BLOCKC" then
										if SN < "BLOCKCIRAW" then
											if SN == "BLOCKCI" then
												Result = CalcStat("BPECI",L,N)
											end
										elseif SN > "BLOCKCIRAW" then
											if SN == "BLOCKCRAW" then
												Result = CalcStat("BPECRAW",L,N)
											end
										else
											Result = CalcStat("BPECIRAW",L,N)
										end
									else
										Result = CalcStat("BPEC",L,N)
									end
								elseif SN > "BLOCKPBONUS" then
									if SN < "BLOCKPRATPB" then
										if SN < "BLOCKPRATP" then
											if SN == "BLOCKPPRAT" then
												Result = CalcStat("BPEPPRat",L,N)
											end
										elseif SN > "BLOCKPRATP" then
											if SN == "BLOCKPRATPA" then
												Result = CalcStat("BPEPRatPA",L)
											end
										else
											Result = CalcStat("BPEPRatP",L,N)
										end
									elseif SN > "BLOCKPRATPB" then
										if SN < "BLOCKPRATPCAP" then
											if SN == "BLOCKPRATPC" then
												Result = CalcStat("BPEPRatPC",L)
											end
										elseif SN > "BLOCKPRATPCAP" then
											if SN == "BLOCKPRATPCAPR" then
												Result = CalcStat("BPEPRatPCapR",L)
											end
										else
											Result = CalcStat("BPEPRatPCap",L)
										end
									else
										Result = CalcStat("BPEPRatPB",L)
									end
								else
									Result = CalcStat("BPEPBonus",L)
								end
							else
								Result = 14
							end
						else
							Result = 1
						end
					elseif SN > "BLOCKT" then
						if SN < "BRAWLERCDARMOURTOCOMPHYMIT" then
							if SN < "BRATDEVHIT" then
								if SN < "BPEPRATP" then
									if SN < "BPECILVLFILTER" then
										if SN < "BPEC" then
											if SN == "BPE" then
												Result = EquSng(StatLinInter("PntMPBPE","ItemPntS","ProgBBPE","AdjItem",L,N,0))
											end
										elseif SN > "BPEC" then
											if SN == "BPECI" then
												Result = RoundDblLotro(CalcStat("BPECIRaw",L,N))
											end
										else
											Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("BPECI",CalcStat("BPECILvlFilter",N),N),0)
										end
									elseif SN > "BPECILVLFILTER" then
										if SN < "BPECRAW" then
											if SN == "BPECIRAW" then
												Result = StatLinInter("PntMPBPEC","ItemPntS","ProgBBPE","AdjCreepItem",L,N,4)
											end
										elseif SN > "BPECRAW" then
											if SN == "BPEPPRAT" then
												Result = CalcRatAB(CalcStat("BPEPRatPA",L),CalcStat("BPEPRatPB",L),CalcStat("BPEPRatPCapR",L),N)
											end
										else
											Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("BPECIRaw",CalcStat("BPECILvlFilter",N),N),99)
										end
									else
										if 3.8 <= Lp and Lm <= 3.8 or 4 <= Lp and Lm <= 4 or 4.6 <= Lp and Lm <= 4.6 or 6.2 <= Lp and Lm <= 6.2 or 8 <= Lp and Lm <= 8 or 12 <= Lp and Lm <= 12 then
											Result = 515
										else
											Result = CalcStat("CreepILvlCurr",L)
										end
									end
								elseif SN > "BPEPRATP" then
									if SN < "BPEPRATPCAP" then
										if SN < "BPEPRATPB" then
											if SN == "BPEPRATPA" then
												Result = 39
											end
										elseif SN > "BPEPRATPB" then
											if SN == "BPEPRATPC" then
												Result = 0.5
											end
										else
											Result = CalcStat("BRatRounded",L,"BRatStandard")
										end
									elseif SN > "BPEPRATPCAP" then
										if SN < "BPET" then
											if SN == "BPEPRATPCAPR" then
												Result = CalcStat("BPEPRatPB",L)*CalcStat("BPEPRatPC",L)
											end
										elseif SN > "BPET" then
											if SN == "BRATCRITMAGN" then
												Result = CalcStat("StdProgRatings",L,600)
											end
										else
											Result = EquSng(StatLinInter("PntMPBPE","TraitPntS","ProgBBPE","AdjTrait",L,N,0))
										end
									else
										Result = 13
									end
								else
									Result = CalcPercAB(CalcStat("BPEPRatPA",L),CalcStat("BPEPRatPB",L),CalcStat("BPEPRatPCap",L),N)
								end
							elseif SN > "BRATDEVHIT" then
								if SN < "BRATPROGB" then
									if SN < "BRATMITLIGHT" then
										if SN < "BRATMITHEAVY" then
											if SN == "BRATEXTRA" then
												Result = CalcStat("StdProgRatings",L,300)
											end
										elseif SN > "BRATMITHEAVY" then
											if SN == "BRATMITIGATIONS" then
												if Lm <= 50 then
													Result = LinFmod(1,(N*CalcStat("BRatStandard",1))*7/6-50.4,N*CalcStat("BRatStandard",50),1,50,L,"P")
												else
													Result = StatLinInter("","StdPntS","BRatStandard","",L,N,3)
												end
											end
										else
											Result = CalcStat("BRatStandard",L)
										end
									elseif SN > "BRATMITLIGHT" then
										if SN < "BRATOUTHEAL" then
											if SN == "BRATMITMEDIUM" then
												Result = CalcStat("BRatMitigations",L,0.833)
											end
										elseif SN > "BRATOUTHEAL" then
											if SN == "BRATPARTBPE" then
												Result = CalcStat("StdProgRatings",L,350)
											end
										else
											Result = CalcStat("StdProgRatings",L,450)
										end
									else
										Result = CalcStat("BRatMitigations",L,0.666)
									end
								elseif SN > "BRATPROGB" then
									if SN < "BRAWLERCDAGILITYTOEVADE" then
										if SN < "BRATSTANDARD" then
											if SN == "BRATROUNDED" then
												if Lm <= 50 then
													Result = RoundDbl(CalcStat(C,L))
												elseif Lm <= 105 then
													Result = RoundDbl(CalcStat(C,L),-1)
												elseif Lm <= 115 then
													Result = RoundDbl(CalcStat(C,L),-2)
												elseif Lm <= 130 then
													Result = RoundDbl(CalcStat(C,L),-1)
												elseif Lm <= 150 then
													Result = RoundDbl(CalcStat(C,L),-2)
												else
													Result = RoundDbl(CalcStat(C,L))
												end
											end
										elseif SN > "BRATSTANDARD" then
											if SN == "BRAWLERCDAGILITYTOCRITHIT" then
												Result = 2
											end
										else
											Result = CalcStat("StdProgRatings",L,200)
										end
									elseif SN > "BRAWLERCDAGILITYTOEVADE" then
										if SN < "BRAWLERCDAGILITYTOOUTHEAL" then
											if SN == "BRAWLERCDAGILITYTOFINESSE" then
												Result = 1
											end
										elseif SN > "BRAWLERCDAGILITYTOOUTHEAL" then
											if SN == "BRAWLERCDAGILITYTOPHYMAS" then
												Result = 2
											end
										else
											Result = 2
										end
									else
										Result = 2
									end
								else
									if Lm <= 50 then
										Result = RoundDbl(CalcStat(C,L))
									else
										Result = CalcStat(C,L)
									end
								end
							else
								Result = CalcStat("StdProgRatings",L,400)
							end
						elseif SN > "BRAWLERCDARMOURTOCOMPHYMIT" then
							if SN < "BRAWLERCDCALCTYPENONPHYMIT" then
								if SN < "BRAWLERCDBASEMIGHT" then
									if SN < "BRAWLERCDBASEAGILITY" then
										if SN < "BRAWLERCDARMOURTOTACMIT" then
											if SN == "BRAWLERCDARMOURTONONPHYMIT" then
												Result = 0.2
											end
										elseif SN > "BRAWLERCDARMOURTOTACMIT" then
											if SN == "BRAWLERCDARMOURTYPE" then
												Result = 3
											end
										else
											Result = 0.2
										end
									elseif SN > "BRAWLERCDBASEAGILITY" then
										if SN < "BRAWLERCDBASEICMR" then
											if SN == "BRAWLERCDBASEFATE" then
												Result = CalcStat("ClassBaseFate",L)
											end
										elseif SN > "BRAWLERCDBASEICMR" then
											if SN == "BRAWLERCDBASEICPR" then
												Result = CalcStat("ClassBaseICPR",L)
											end
										else
											Result = CalcStat("ClassBaseICMRL",L)
										end
									else
										Result = CalcStat("ClassBaseAgilityM",L)
									end
								elseif SN > "BRAWLERCDBASEMIGHT" then
									if SN < "BRAWLERCDBASEPOWER" then
										if SN < "BRAWLERCDBASENCMR" then
											if SN == "BRAWLERCDBASEMORALE" then
												Result = CalcStat("ClassBaseMorale",L)
											end
										elseif SN > "BRAWLERCDBASENCMR" then
											if SN == "BRAWLERCDBASENCPR" then
												Result = CalcStat("ClassBaseNCPR",L)
											end
										else
											Result = CalcStat("ClassBaseNCMRL",L)
										end
									elseif SN > "BRAWLERCDBASEPOWER" then
										if SN < "BRAWLERCDBASEWILL" then
											if SN == "BRAWLERCDBASEVITALITY" then
												Result = CalcStat("ClassBaseVitality",L)
											end
										elseif SN > "BRAWLERCDBASEWILL" then
											if SN == "BRAWLERCDCALCTYPECOMPHYMIT" then
												Result = 14
											end
										else
											Result = CalcStat("ClassBaseWillL",L)
										end
									else
										Result = CalcStat("ClassBasePower",L)
									end
								else
									Result = CalcStat("ClassBaseMightH",L)
								end
							elseif SN > "BRAWLERCDCALCTYPENONPHYMIT" then
								if SN < "BRAWLERCDMIGHTTOPARRY" then
									if SN < "BRAWLERCDHASPOWER" then
										if SN < "BRAWLERCDFATETONCPR" then
											if SN == "BRAWLERCDCALCTYPETACMIT" then
												Result = 27
											end
										elseif SN > "BRAWLERCDFATETONCPR" then
											if SN == "BRAWLERCDFATETOPOWER" then
												Result = 1
											end
										else
											Result = 0.07
										end
									elseif SN > "BRAWLERCDHASPOWER" then
										if SN < "BRAWLERCDMIGHTTOEVADE" then
											if SN == "BRAWLERCDMIGHTTOCRITHIT" then
												Result = 1
											end
										elseif SN > "BRAWLERCDMIGHTTOEVADE" then
											if SN == "BRAWLERCDMIGHTTOOUTHEAL" then
												Result = 3
											end
										else
											Result = 1
										end
									else
										Result = 1
									end
								elseif SN > "BRAWLERCDMIGHTTOPARRY" then
									if SN < "BRAWLERCDPHYMITTOCOMPHYMIT" then
										if SN < "BRAWLERCDMIGHTTOPHYMIT" then
											if SN == "BRAWLERCDMIGHTTOPHYMAS" then
												Result = 3
											end
										elseif SN > "BRAWLERCDMIGHTTOPHYMIT" then
											if SN == "BRAWLERCDMIGHTTOTACMIT" then
												Result = 1
											end
										else
											Result = 1
										end
									elseif SN > "BRAWLERCDPHYMITTOCOMPHYMIT" then
										if SN < "BRAWLERCDTACMASTOOUTHEAL" then
											if SN == "BRAWLERCDPHYMITTONONPHYMIT" then
												Result = 1
											end
										elseif SN > "BRAWLERCDTACMASTOOUTHEAL" then
											if SN > "BRAWLERCDVITALITYTOICMR" then
												if SN == "BRAWLERCDVITALITYTOMORALE" then
													Result = 4.5
												end
											elseif SN == "BRAWLERCDVITALITYTOICMR" then
												Result = 0.012
											end
										else
											Result = 1
										end
									else
										Result = 1
									end
								else
									Result = 1
								end
							else
								Result = 14
							end
						else
							Result = 1
						end
					else
						Result = CalcStat("BPET",L,N)
					end
				else
					Result = 3
				end
			elseif SN > "BRAWLERCDVITALITYTONCMR" then
				if SN < "CHAMPIONCDBASEICMR" then
					if SN < "BURGLARCDVITALITYTONCMR" then
						if SN < "BURGLARCDAGILITYTOTACMIT" then
							if SN < "BRWINNSTRCLEVTECHFINESSE" then
								if SN < "BRGALLINONEXPFINESSE" then
									if SN < "BRAWLERCDWILLTOPHYMIT" then
										if SN < "BRAWLERCDWILLTOOUTHEAL" then
											if SN == "BRAWLERCDWILLTOFINESSE" then
												Result = 1
											end
										elseif SN > "BRAWLERCDWILLTOOUTHEAL" then
											if SN == "BRAWLERCDWILLTOPHYMAS" then
												Result = 1
											end
										else
											Result = 1
										end
									elseif SN > "BRAWLERCDWILLTOPHYMIT" then
										if SN < "BRAWLERCDWILLTOTACMIT" then
											if SN == "BRAWLERCDWILLTORESIST" then
												Result = 1
											end
										elseif SN > "BRAWLERCDWILLTOTACMIT" then
											if SN == "BRGALLINFINESSE" then
												Result = CalcStat("Finesse",L,2)
											end
										else
											Result = 1.5
										end
									else
										Result = 1.5
									end
								elseif SN > "BRGALLINONEXPFINESSE" then
									if SN < "BRGTRICKCNTDEFBPE" then
										if SN < "BRGREVWEAKNFINESSE" then
											if SN == "BRGREVWEAKNCRITDEF" then
												Result = -CalcStat("CritDefT",L,0.4)
											end
										elseif SN > "BRGREVWEAKNFINESSE" then
											if SN == "BRGREVWEAKNRESIST" then
												Result = -CalcStat("ResistT",L,0.4)
											end
										else
											Result = -CalcStat("FinesseT",L,0.4)
										end
									elseif SN > "BRGTRICKCNTDEFBPE" then
										if SN < "BRWAGGPOSTUREPHYMIT" then
											if SN == "BRGTRICKCNTDEFCRITDEF" then
												Result = -CalcStat("CritDefT",L,0.8)
											end
										elseif SN > "BRWAGGPOSTUREPHYMIT" then
											if SN == "BRWDEFPOSTUREPHYMAS" then
												Result = -CalcStat("PhyMasT",L,4)
											end
										else
											Result = -CalcStat("PhyMitT",L,3)
										end
									else
										Result = -CalcStat("BPET",L,1.2)
									end
								else
									Result = -CalcStat("Finesse",L,2)
								end
							elseif SN > "BRWINNSTRCLEVTECHFINESSE" then
								if SN < "BRWTACMIT" then
									if SN < "BRWRETINTENSITYCRITHIT" then
										if SN < "BRWMAELSTROMMIGHT" then
											if SN == "BRWINNSTRPRECISIONCRITHIT" then
												Result = CalcStat("CritHitT",L,CalcStat("Trait13510Choice",N)*0.2)
											end
										elseif SN > "BRWMAELSTROMMIGHT" then
											if SN == "BRWMIGHTINCREASE" then
												Result = CalcStat("MightT",L,CalcStat("Trait567810Choice",N)*0.4)
											end
										else
											Result = CalcStat("MightT",L,2)
										end
									elseif SN > "BRWRETINTENSITYCRITHIT" then
										if SN < "BRWSHAREISBALANCEFINESSE" then
											if SN == "BRWRETPRECISIONFINESSE" then
												Result = CalcStat("FinesseT",L,CalcStat("Trait234Choice",N))
											end
										elseif SN > "BRWSHAREISBALANCEFINESSE" then
											if SN == "BRWSHAREISHEAVYCRITHIT" then
												Result = CalcStat("BrwInnStrPrecisionCritHit",L,3)
											end
										else
											Result = CalcStat("BrwInnStrClevTechFinesse",L,3)
										end
									else
										Result = CalcStat("CritHitT",L,CalcStat("Trait234Choice",N))
									end
								elseif SN > "BRWTACMIT" then
									if SN < "BURGLARCDAGILITYTOOUTHEAL" then
										if SN < "BURGLARCDAGILITYTOCRITHIT" then
											if SN == "BRWVITALITYINCREASE" then
												Result = CalcStat("VitalityT",L,CalcStat("Trait567810Choice",N)*0.4)
											end
										elseif SN > "BURGLARCDAGILITYTOCRITHIT" then
											if SN == "BURGLARCDAGILITYTOEVADE" then
												Result = 2
											end
										else
											Result = 1
										end
									elseif SN > "BURGLARCDAGILITYTOOUTHEAL" then
										if SN < "BURGLARCDAGILITYTOPHYMAS" then
											if SN == "BURGLARCDAGILITYTOPARRY" then
												Result = 1
											end
										elseif SN > "BURGLARCDAGILITYTOPHYMAS" then
											if SN == "BURGLARCDAGILITYTOPHYMIT" then
												Result = 1
											end
										else
											Result = 3
										end
									else
										Result = 3
									end
								else
									Result = CalcStat("TacMitT",L,CalcStat("Trait12345Choice",N)*0.4)
								end
							else
								Result = CalcStat("FinesseT",L,CalcStat("Trait13510Choice",N)*0.2)
							end
						elseif SN > "BURGLARCDAGILITYTOTACMIT" then
							if SN < "BURGLARCDCALCTYPECOMPHYMIT" then
								if SN < "BURGLARCDBASEICPR" then
									if SN < "BURGLARCDARMOURTYPE" then
										if SN < "BURGLARCDARMOURTONONPHYMIT" then
											if SN == "BURGLARCDARMOURTOCOMPHYMIT" then
												Result = 1
											end
										elseif SN > "BURGLARCDARMOURTONONPHYMIT" then
											if SN == "BURGLARCDARMOURTOTACMIT" then
												Result = 0.2
											end
										else
											Result = 0.2
										end
									elseif SN > "BURGLARCDARMOURTYPE" then
										if SN < "BURGLARCDBASEFATE" then
											if SN == "BURGLARCDBASEAGILITY" then
												Result = CalcStat("ClassBaseAgilityH",L)
											end
										elseif SN > "BURGLARCDBASEFATE" then
											if SN == "BURGLARCDBASEICMR" then
												Result = CalcStat("ClassBaseICMRL",L)
											end
										else
											Result = CalcStat("ClassBaseFate",L)
										end
									else
										Result = 2
									end
								elseif SN > "BURGLARCDBASEICPR" then
									if SN < "BURGLARCDBASENCPR" then
										if SN < "BURGLARCDBASEMORALE" then
											if SN == "BURGLARCDBASEMIGHT" then
												Result = CalcStat("ClassBaseMightM",L)
											end
										elseif SN > "BURGLARCDBASEMORALE" then
											if SN == "BURGLARCDBASENCMR" then
												Result = CalcStat("ClassBaseNCMRL",L)
											end
										else
											Result = CalcStat("ClassBaseMorale",L)
										end
									elseif SN > "BURGLARCDBASENCPR" then
										if SN < "BURGLARCDBASEVITALITY" then
											if SN == "BURGLARCDBASEPOWER" then
												Result = CalcStat("ClassBasePower",L)
											end
										elseif SN > "BURGLARCDBASEVITALITY" then
											if SN == "BURGLARCDBASEWILL" then
												Result = CalcStat("ClassBaseWillL",L)
											end
										else
											Result = CalcStat("ClassBaseVitality",L)
										end
									else
										Result = CalcStat("ClassBaseNCPR",L)
									end
								else
									Result = CalcStat("ClassBaseICPR",L)
								end
							elseif SN > "BURGLARCDCALCTYPECOMPHYMIT" then
								if SN < "BURGLARCDMIGHTTOFINESSE" then
									if SN < "BURGLARCDFATETOPOWER" then
										if SN < "BURGLARCDCALCTYPETACMIT" then
											if SN == "BURGLARCDCALCTYPENONPHYMIT" then
												Result = 13
											end
										elseif SN > "BURGLARCDCALCTYPETACMIT" then
											if SN == "BURGLARCDFATETONCPR" then
												Result = 0.07
											end
										else
											Result = 26
										end
									elseif SN > "BURGLARCDFATETOPOWER" then
										if SN < "BURGLARCDMIGHTTOCRITHIT" then
											if SN == "BURGLARCDHASPOWER" then
												Result = 1
											end
										elseif SN > "BURGLARCDMIGHTTOCRITHIT" then
											if SN == "BURGLARCDMIGHTTOEVADE" then
												Result = 1
											end
										else
											Result = 1.5
										end
									else
										Result = 1
									end
								elseif SN > "BURGLARCDMIGHTTOFINESSE" then
									if SN < "BURGLARCDPHYMITTONONPHYMIT" then
										if SN < "BURGLARCDMIGHTTOPHYMAS" then
											if SN == "BURGLARCDMIGHTTOOUTHEAL" then
												Result = 2
											end
										elseif SN > "BURGLARCDMIGHTTOPHYMAS" then
											if SN == "BURGLARCDPHYMITTOCOMPHYMIT" then
												Result = 1
											end
										else
											Result = 2
										end
									elseif SN > "BURGLARCDPHYMITTONONPHYMIT" then
										if SN < "BURGLARCDVITALITYTOICMR" then
											if SN == "BURGLARCDTACMASTOOUTHEAL" then
												Result = 1
											end
										elseif SN > "BURGLARCDVITALITYTOICMR" then
											if SN == "BURGLARCDVITALITYTOMORALE" then
												Result = 4.5
											end
										else
											Result = 0.012
										end
									else
										Result = 1
									end
								else
									Result = 1.5
								end
							else
								Result = 13
							end
						else
							Result = 1
						end
					elseif SN > "BURGLARCDVITALITYTONCMR" then
						if SN < "CAPTAINCDFATETONCPR" then
							if SN < "CAPTAINCDARMOURTYPE" then
								if SN < "CAPTAINCDAGILITYTOCRITHIT" then
									if SN < "BURGLARCDWILLTOPHYMAS" then
										if SN < "BURGLARCDWILLTOFINESSE" then
											if SN == "BURGLARCDWILLTOCRITHIT" then
												Result = 0.5
											end
										elseif SN > "BURGLARCDWILLTOFINESSE" then
											if SN == "BURGLARCDWILLTOOUTHEAL" then
												Result = 2
											end
										else
											Result = 1.5
										end
									elseif SN > "BURGLARCDWILLTOPHYMAS" then
										if SN < "BURGLARCDWILLTORESIST" then
											if SN == "BURGLARCDWILLTOPHYMIT" then
												Result = 1
											end
										elseif SN > "BURGLARCDWILLTORESIST" then
											if SN == "C" then
												Result = C
											end
										else
											Result = 1
										end
									else
										Result = 2
									end
								elseif SN > "CAPTAINCDAGILITYTOCRITHIT" then
									if SN < "CAPTAINCDAGILITYTOTACMAS" then
										if SN < "CAPTAINCDAGILITYTOPARRY" then
											if SN == "CAPTAINCDAGILITYTOFINESSE" then
												Result = 1
											end
										elseif SN > "CAPTAINCDAGILITYTOPARRY" then
											if SN == "CAPTAINCDAGILITYTOPHYMAS" then
												Result = 2
											end
										else
											Result = 1
										end
									elseif SN > "CAPTAINCDAGILITYTOTACMAS" then
										if SN < "CAPTAINCDARMOURTONONPHYMIT" then
											if SN == "CAPTAINCDARMOURTOCOMPHYMIT" then
												Result = 1
											end
										elseif SN > "CAPTAINCDARMOURTONONPHYMIT" then
											if SN == "CAPTAINCDARMOURTOTACMIT" then
												Result = 0.2
											end
										else
											Result = 0.2
										end
									else
										Result = 2
									end
								else
									Result = 2
								end
							elseif SN > "CAPTAINCDARMOURTYPE" then
								if SN < "CAPTAINCDBASENCPR" then
									if SN < "CAPTAINCDBASEICPR" then
										if SN < "CAPTAINCDBASEFATE" then
											if SN == "CAPTAINCDBASEAGILITY" then
												Result = CalcStat("ClassBaseAgilityL",L)
											end
										elseif SN > "CAPTAINCDBASEFATE" then
											if SN == "CAPTAINCDBASEICMR" then
												Result = CalcStat("ClassBaseICMRM",L)
											end
										else
											Result = CalcStat("ClassBaseFate",L)
										end
									elseif SN > "CAPTAINCDBASEICPR" then
										if SN < "CAPTAINCDBASEMORALE" then
											if SN == "CAPTAINCDBASEMIGHT" then
												Result = CalcStat("ClassBaseMightH",L)
											end
										elseif SN > "CAPTAINCDBASEMORALE" then
											if SN == "CAPTAINCDBASENCMR" then
												Result = CalcStat("ClassBaseNCMRM",L)
											end
										else
											Result = CalcStat("ClassBaseMorale",L)
										end
									else
										Result = CalcStat("ClassBaseICPR",L)
									end
								elseif SN > "CAPTAINCDBASENCPR" then
									if SN < "CAPTAINCDCALCTYPECOMPHYMIT" then
										if SN < "CAPTAINCDBASEVITALITY" then
											if SN == "CAPTAINCDBASEPOWER" then
												Result = CalcStat("ClassBasePower",L)
											end
										elseif SN > "CAPTAINCDBASEVITALITY" then
											if SN == "CAPTAINCDBASEWILL" then
												Result = CalcStat("ClassBaseWillM",L)
											end
										else
											Result = CalcStat("ClassBaseVitality",L)
										end
									elseif SN > "CAPTAINCDCALCTYPECOMPHYMIT" then
										if SN < "CAPTAINCDCALCTYPETACMIT" then
											if SN == "CAPTAINCDCALCTYPENONPHYMIT" then
												Result = 14
											end
										elseif SN > "CAPTAINCDCALCTYPETACMIT" then
											if SN == "CAPTAINCDCANBLOCK" then
												if 15 <= Lp then
													Result = 1
												end
											end
										else
											Result = 27
										end
									else
										Result = 14
									end
								else
									Result = CalcStat("ClassBaseNCPR",L)
								end
							else
								Result = 3
							end
						elseif SN > "CAPTAINCDFATETONCPR" then
							if SN < "CAPTAINCDWILLTOFINESSE" then
								if SN < "CAPTAINCDMIGHTTOTACMAS" then
									if SN < "CAPTAINCDMIGHTTOCRITHIT" then
										if SN < "CAPTAINCDHASPOWER" then
											if SN == "CAPTAINCDFATETOPOWER" then
												Result = 1
											end
										elseif SN > "CAPTAINCDHASPOWER" then
											if SN == "CAPTAINCDMIGHTTOBLOCK" then
												Result = 2
											end
										else
											Result = 1
										end
									elseif SN > "CAPTAINCDMIGHTTOCRITHIT" then
										if SN < "CAPTAINCDMIGHTTOPHYMAS" then
											if SN == "CAPTAINCDMIGHTTOPARRY" then
												Result = 1
											end
										elseif SN > "CAPTAINCDMIGHTTOPHYMAS" then
											if SN == "CAPTAINCDMIGHTTOPHYMIT" then
												Result = 1
											end
										else
											Result = 3
										end
									else
										Result = 1
									end
								elseif SN > "CAPTAINCDMIGHTTOTACMAS" then
									if SN < "CAPTAINCDTACMASTOOUTHEAL" then
										if SN < "CAPTAINCDPHYMITTOCOMPHYMIT" then
											if SN == "CAPTAINCDMIGHTTOTACMIT" then
												Result = 1
											end
										elseif SN > "CAPTAINCDPHYMITTOCOMPHYMIT" then
											if SN == "CAPTAINCDPHYMITTONONPHYMIT" then
												Result = 1
											end
										else
											Result = 1
										end
									elseif SN > "CAPTAINCDTACMASTOOUTHEAL" then
										if SN < "CAPTAINCDVITALITYTOMORALE" then
											if SN == "CAPTAINCDVITALITYTOICMR" then
												Result = 0.012
											end
										elseif SN > "CAPTAINCDVITALITYTOMORALE" then
											if SN == "CAPTAINCDVITALITYTONCMR" then
												Result = 0.12
											end
										else
											Result = 4.5
										end
									else
										Result = 1
									end
								else
									Result = 3
								end
							elseif SN > "CAPTAINCDWILLTOFINESSE" then
								if SN < "CHAMPIONCDAGILITYTOOUTHEAL" then
									if SN < "CAPTAINCDWILLTOTACMAS" then
										if SN < "CAPTAINCDWILLTOPHYMIT" then
											if SN == "CAPTAINCDWILLTOPHYMAS" then
												Result = 1
											end
										elseif SN > "CAPTAINCDWILLTOPHYMIT" then
											if SN == "CAPTAINCDWILLTORESIST" then
												Result = 1
											end
										else
											Result = 1.5
										end
									elseif SN > "CAPTAINCDWILLTOTACMAS" then
										if SN < "CHAMPIONCDAGILITYTOCRITHIT" then
											if SN == "CAPTAINCDWILLTOTACMIT" then
												Result = 1.5
											end
										elseif SN > "CHAMPIONCDAGILITYTOCRITHIT" then
											if SN == "CHAMPIONCDAGILITYTOFINESSE" then
												Result = 1
											end
										else
											Result = 2
										end
									else
										Result = 1
									end
								elseif SN > "CHAMPIONCDAGILITYTOOUTHEAL" then
									if SN < "CHAMPIONCDARMOURTONONPHYMIT" then
										if SN < "CHAMPIONCDAGILITYTOPHYMAS" then
											if SN == "CHAMPIONCDAGILITYTOPARRY" then
												Result = 1
											end
										elseif SN > "CHAMPIONCDAGILITYTOPHYMAS" then
											if SN == "CHAMPIONCDARMOURTOCOMPHYMIT" then
												Result = 1
											end
										else
											Result = 2
										end
									elseif SN > "CHAMPIONCDARMOURTONONPHYMIT" then
										if SN < "CHAMPIONCDARMOURTYPE" then
											if SN == "CHAMPIONCDARMOURTOTACMIT" then
												Result = 0.2
											end
										elseif SN > "CHAMPIONCDARMOURTYPE" then
											if SN > "CHAMPIONCDBASEAGILITY" then
												if SN == "CHAMPIONCDBASEFATE" then
													Result = CalcStat("ClassBaseFate",L)
												end
											elseif SN == "CHAMPIONCDBASEAGILITY" then
												Result = CalcStat("ClassBaseAgilityM",L)
											end
										else
											Result = 3
										end
									else
										Result = 0.2
									end
								else
									Result = 2
								end
							else
								Result = 1
							end
						else
							Result = 0.07
						end
					else
						Result = 0.12
					end
				elseif SN > "CHAMPIONCDBASEICMR" then
					if SN < "CLASSBASENCMRH" then
						if SN < "CHAMPIONCDWILLTORESIST" then
							if SN < "CHAMPIONCDMIGHTTOCRITHIT" then
								if SN < "CHAMPIONCDBASEWILL" then
									if SN < "CHAMPIONCDBASENCMR" then
										if SN < "CHAMPIONCDBASEMIGHT" then
											if SN == "CHAMPIONCDBASEICPR" then
												Result = CalcStat("ClassBaseICPR",L)
											end
										elseif SN > "CHAMPIONCDBASEMIGHT" then
											if SN == "CHAMPIONCDBASEMORALE" then
												Result = CalcStat("ClassBaseMorale",L)
											end
										else
											Result = CalcStat("ClassBaseMightH",L)
										end
									elseif SN > "CHAMPIONCDBASENCMR" then
										if SN < "CHAMPIONCDBASEPOWER" then
											if SN == "CHAMPIONCDBASENCPR" then
												Result = CalcStat("ClassBaseNCPR",L)
											end
										elseif SN > "CHAMPIONCDBASEPOWER" then
											if SN == "CHAMPIONCDBASEVITALITY" then
												Result = CalcStat("ClassBaseVitality",L)
											end
										else
											Result = CalcStat("ClassBasePower",L)
										end
									else
										Result = CalcStat("ClassBaseNCMRH",L)
									end
								elseif SN > "CHAMPIONCDBASEWILL" then
									if SN < "CHAMPIONCDCANBLOCK" then
										if SN < "CHAMPIONCDCALCTYPENONPHYMIT" then
											if SN == "CHAMPIONCDCALCTYPECOMPHYMIT" then
												Result = 14
											end
										elseif SN > "CHAMPIONCDCALCTYPENONPHYMIT" then
											if SN == "CHAMPIONCDCALCTYPETACMIT" then
												Result = 27
											end
										else
											Result = 14
										end
									elseif SN > "CHAMPIONCDCANBLOCK" then
										if SN < "CHAMPIONCDFATETOPOWER" then
											if SN == "CHAMPIONCDFATETONCPR" then
												Result = 0.07
											end
										elseif SN > "CHAMPIONCDFATETOPOWER" then
											if SN == "CHAMPIONCDHASPOWER" then
												Result = 1
											end
										else
											Result = 1
										end
									else
										if 6 <= Lp then
											Result = 1
										end
									end
								else
									Result = CalcStat("ClassBaseWillL",L)
								end
							elseif SN > "CHAMPIONCDMIGHTTOCRITHIT" then
								if SN < "CHAMPIONCDTACMASTOOUTHEAL" then
									if SN < "CHAMPIONCDMIGHTTOPHYMIT" then
										if SN < "CHAMPIONCDMIGHTTOPARRY" then
											if SN == "CHAMPIONCDMIGHTTOOUTHEAL" then
												Result = 3
											end
										elseif SN > "CHAMPIONCDMIGHTTOPARRY" then
											if SN == "CHAMPIONCDMIGHTTOPHYMAS" then
												Result = 3
											end
										else
											Result = 3
										end
									elseif SN > "CHAMPIONCDMIGHTTOPHYMIT" then
										if SN < "CHAMPIONCDPHYMITTOCOMPHYMIT" then
											if SN == "CHAMPIONCDMIGHTTOTACMIT" then
												Result = 1
											end
										elseif SN > "CHAMPIONCDPHYMITTOCOMPHYMIT" then
											if SN == "CHAMPIONCDPHYMITTONONPHYMIT" then
												Result = 1
											end
										else
											Result = 1
										end
									else
										Result = 1
									end
								elseif SN > "CHAMPIONCDTACMASTOOUTHEAL" then
									if SN < "CHAMPIONCDWILLTOFINESSE" then
										if SN < "CHAMPIONCDVITALITYTOMORALE" then
											if SN == "CHAMPIONCDVITALITYTOICMR" then
												Result = 0.012
											end
										elseif SN > "CHAMPIONCDVITALITYTOMORALE" then
											if SN == "CHAMPIONCDVITALITYTONCMR" then
												Result = 0.12
											end
										else
											Result = 4.5
										end
									elseif SN > "CHAMPIONCDWILLTOFINESSE" then
										if SN < "CHAMPIONCDWILLTOPHYMAS" then
											if SN == "CHAMPIONCDWILLTOOUTHEAL" then
												Result = 1
											end
										elseif SN > "CHAMPIONCDWILLTOPHYMAS" then
											if SN == "CHAMPIONCDWILLTOPHYMIT" then
												Result = 1.5
											end
										else
											Result = 1
										end
									else
										Result = 1
									end
								else
									Result = 1
								end
							else
								Result = 1
							end
						elseif SN > "CHAMPIONCDWILLTORESIST" then
							if SN < "CHPSTALWBLADEVITALITY" then
								if SN < "CHISELCRITHITHOLD" then
									if SN < "CHICKENCDCALCTYPENONPHYMIT" then
										if SN < "CHICKENCANBLOCK" then
											if SN == "CHAMPIONCDWILLTOTACMIT" then
												Result = 1.5
											end
										elseif SN > "CHICKENCANBLOCK" then
											if SN == "CHICKENCDCALCTYPECOMPHYMIT" then
												Result = 14
											end
										else
											Result = 1
										end
									elseif SN > "CHICKENCDCALCTYPENONPHYMIT" then
										if SN < "CHICKENCDHASPOWER" then
											if SN == "CHICKENCDCALCTYPETACMIT" then
												Result = 27
											end
										elseif SN > "CHICKENCDHASPOWER" then
											if SN == "CHISELCRITHITH" then
												if Lm <= 140 then
													Result = CalcStat("U371LegacyStatFix",L,"ChiselCritHitHOld")
												else
													Result = CalcStat("ChiselCritHitH",140)
												end
											end
										else
											Result = 1
										end
									else
										Result = 14
									end
								elseif SN > "CHISELCRITHITHOLD" then
									if SN < "CHPCONTRBURNICPR" then
										if SN < "CHISELCRITHITLOLD" then
											if SN == "CHISELCRITHITL" then
												if Lm <= 140 then
													Result = CalcStat("U371LegacyStatFix",L,"ChiselCritHitLOld")
												else
													Result = CalcStat("ChiselCritHitL",140)
												end
											end
										elseif SN > "CHISELCRITHITLOLD" then
											if SN == "CHP2HWPNBLOCK" then
												Result = CalcStat("BlockT",L,4)
											end
										else
											if Lm <= 105 then
												Result = RoundDbl(16.16*L)
											else
												Result = CalcStat("ProgExtHighLinExpRnd",L,CalcStat("ChiselCritHitLOld",105))
											end
										end
									elseif SN > "CHPCONTRBURNICPR" then
										if SN < "CHPFLURRYINCRCRITHIT" then
											if SN == "CHPFINESSEINCREASE" then
												Result = CalcStat("FinesseT",L,CalcStat("Trait12345Choice",N)*0.4)
											end
										elseif SN > "CHPFLURRYINCRCRITHIT" then
											if SN == "CHPMIGHTINCREASE" then
												Result = CalcStat("MightT",L,CalcStat("Trait567810Choice",N)*0.4)
											end
										else
											Result = CalcStat("CritHitT",L,2.4)
										end
									else
										Result = CalcStat("ICPRT",L,0.4)
									end
								else
									if Lm <= 105 then
										Result = RoundDbl(24.24*L)
									else
										Result = CalcStat("ProgExtHighLinExpRnd",L,CalcStat("ChiselCritHitHOld",105))
									end
								end
							elseif SN > "CHPSTALWBLADEVITALITY" then
								if SN < "CLASSBASEICMRL" then
									if SN < "CLASSBASEAGILITYL" then
										if SN < "CHPUNBREAKTIERPTS" then
											if SN == "CHPUNBREAKTACMIT" then
												Result = CalcStat("TacMitT",L,CalcStat("ChpUnbreakTierPts",N))
											end
										elseif SN > "CHPUNBREAKTIERPTS" then
											if SN == "CLASSBASEAGILITYH" then
												Result = CalcStat("BaseAgility",L,1.5)
											end
										else
											if 1 <= Lp and Lm <= 10 then
												Result = 0.4*L
											end
										end
									elseif SN > "CLASSBASEAGILITYL" then
										if SN < "CLASSBASEFATE" then
											if SN == "CLASSBASEAGILITYM" then
												Result = CalcStat("BaseAgility",L,1.0)
											end
										elseif SN > "CLASSBASEFATE" then
											if SN == "CLASSBASEICMRH" then
												Result = 0.2
											end
										else
											Result = CalcStat("BaseFate",L)
										end
									else
										Result = CalcStat("BaseAgility",L,0.5)
									end
								elseif SN > "CLASSBASEICMRL" then
									if SN < "CLASSBASEMIGHTH" then
										if SN < "CLASSBASEICPR" then
											if SN == "CLASSBASEICMRM" then
												Result = 0.175
											end
										elseif SN > "CLASSBASEICPR" then
											if SN == "CLASSBASEICPRADJ" then
												if Lm <= 1 then
													Result = 1.5
												elseif Lm <= 20 then
													Result = 1.1
												else
													Result = 1
												end
											end
										else
											Result = EquSng(StatLinInter("PntMPClassBaseICPR","ClassBasePowerRegenPntS","ProgBICPR","ClassBaseICPRAdj",L,N,99))
										end
									elseif SN > "CLASSBASEMIGHTH" then
										if SN < "CLASSBASEMIGHTM" then
											if SN == "CLASSBASEMIGHTL" then
												Result = CalcStat("BaseMight",L,0.5)
											end
										elseif SN > "CLASSBASEMIGHTM" then
											if SN == "CLASSBASEMORALE" then
												Result = CalcStat("BaseMorale",L)
											end
										else
											Result = CalcStat("BaseMight",L,1.0)
										end
									else
										Result = CalcStat("BaseMight",L,1.5)
									end
								else
									Result = 0.15
								end
							else
								Result = CalcStat("VitalityT",L,CalcStat("Trait567810Choice",N)*0.4)
							end
						else
							Result = 1
						end
					elseif SN > "CLASSBASENCMRH" then
						if SN < "COMBATDAMAGEMOD" then
							if SN < "COMBATBASETACDPS" then
								if SN < "CLASSBASEWILLH" then
									if SN < "CLASSBASENCPRADJ" then
										if SN < "CLASSBASENCMRM" then
											if SN == "CLASSBASENCMRL" then
												Result = 1
											end
										elseif SN > "CLASSBASENCMRM" then
											if SN == "CLASSBASENCPR" then
												Result = EquSng(StatLinInter("PntMPClassBaseNCPR","ClassBasePowerRegenPntS","ProgBNCPR","ClassBaseNCPRAdj",L,N,99))
											end
										else
											Result = 1
										end
									elseif SN > "CLASSBASENCPRADJ" then
										if SN < "CLASSBASEPOWERREGENPNTS" then
											if SN == "CLASSBASEPOWER" then
												Result = CalcStat("BasePower",L)
											end
										elseif SN > "CLASSBASEPOWERREGENPNTS" then
											if SN == "CLASSBASEVITALITY" then
												Result = CalcStat("BaseVitality",L)
											end
										else
											Result = {{1,20,50,60,65,75,85,95,100,105,115,120,130,140,150},{1,20,50,60,65,75,85,95,100,105,115,120,130,140,150}}
										end
									else
										if Lm <= 1 then
											Result = 1.5
										elseif Lm <= 20 then
											Result = 1.1
										else
											Result = 1
										end
									end
								elseif SN > "CLASSBASEWILLH" then
									if SN < "CLOTHARMOUR" then
										if SN < "CLASSBASEWILLM" then
											if SN == "CLASSBASEWILLL" then
												Result = CalcStat("BaseWill",L,0.5)
											end
										elseif SN > "CLASSBASEWILLM" then
											if SN == "CLASSNAME" then
												if 23 <= Lp and Lm <= 23 then
													Result = "Guardian"
												elseif 24 <= Lp and Lm <= 24 then
													Result = "Captain"
												elseif 31 <= Lp and Lm <= 31 then
													Result = "Minstrel"
												elseif 40 <= Lp and Lm <= 40 then
													Result = "Burglar"
												elseif 52 <= Lp and Lm <= 52 then
													Result = "Warleader"
												elseif 71 <= Lp and Lm <= 71 then
													Result = "Reaver"
												elseif 126 <= Lp and Lm <= 126 then
													Result = "Stalker"
												elseif 127 <= Lp and Lm <= 127 then
													Result = "Weaver"
												elseif 128 <= Lp and Lm <= 128 then
													Result = "Defiler"
												elseif 162 <= Lp and Lm <= 162 then
													Result = "Hunter"
												elseif 172 <= Lp and Lm <= 172 then
													Result = "Champion"
												elseif 179 <= Lp and Lm <= 179 then
													Result = "Blackarrow"
												elseif 185 <= Lp and Lm <= 185 then
													Result = "LoreMaster"
												elseif 192 <= Lp and Lm <= 192 then
													Result = "Chicken"
												elseif 193 <= Lp and Lm <= 193 then
													Result = "RuneKeeper"
												elseif 194 <= Lp and Lm <= 194 then
													Result = "Warden"
												elseif 214 <= Lp and Lm <= 214 then
													Result = "Beorning"
												elseif 215 <= Lp and Lm <= 215 then
													Result = "Brawler"
												elseif 216 <= Lp and Lm <= 216 then
													Result = "Mariner"
												else
													Result = ""
												end
											end
										else
											Result = CalcStat("BaseWill",L,1.0)
										end
									elseif SN > "CLOTHARMOUR" then
										if SN < "COMBATBASEPHYDPS" then
											if SN == "COMBATBASEDPSMINUSLOW" then
												Result = CalcStat("ProgBDamage",L)-CalcStat("ProgBDamage",50)
											end
										elseif SN > "COMBATBASEPHYDPS" then
											if SN == "COMBATBASEPHYDPSITEMPNTS" then
												Result = {{1,50,60,65,75,125,175,200,222,300,301,350,351,400,401,450,451,500,501,550,551,600},{1,50,60,65,75,85,95,100,105,105,106,115,116,120,121,130,131,140,141,150,151,160}}
											end
										else
											if Lm <= 600 then
												Result = StatLinInter("","CombatBasePhyDPSItemPntS","ProgBDamage","",L,N,99)
											elseif Lm <= 650 then
												Result = RoundDblDown(RoundDblUp((L-50)/5.5)*36.7-2811,-1)
											else
												Result = CalcStat("CombatBasePhyDPS",650)
											end
										end
									else
										if Lm <= 50 then
											Result = L
										else
											Result = 50
										end
									end
								else
									Result = CalcStat("BaseWill",L,1.5)
								end
							elseif SN > "COMBATBASETACDPS" then
								if SN < "COMBATBASETACHPSCURVES" then
									if SN < "COMBATBASETACDPSRAWITEMPNTS" then
										if SN < "COMBATBASETACDPSNOCLASS" then
											if SN == "COMBATBASETACDPSBYLEVEL" then
												if Lm <= 50 then
													Result = EquSng(CalcStat("ProgBDamage",L))
												else
													Result = CalcStat("CombatBaseTacDPSByLevel",50)
												end
											end
										elseif SN > "COMBATBASETACDPSNOCLASS" then
											if SN == "COMBATBASETACDPSRAW" then
												if Lm <= 46 then
													Result = 0.5
												elseif Lm <= 50 then
													Result = LinFmod(1,0.5,0.8,47,50,L)
												elseif Lm <= 51 then
													Result = 1
												elseif Lm <= 599 then
													Result = StatLinInter("","CombatBaseTacDPSRawItemPntS","CombatBaseDPSMinusLow","",L,N,99)
												elseif Lm <= 649 then
													Result = RoundDblDown(RoundDblUp((L-49)/5.5)*36.7-2831,-1)
												else
													Result = CalcStat("CombatBaseTacDPSRaw",649)
												end
											end
										else
											if Lm <= 50 then
												Result = L
											else
												Result = CalcStat("CombatBaseTacDPSNoClass",50)
											end
										end
									elseif SN > "COMBATBASETACDPSRAWITEMPNTS" then
										if SN < "COMBATBASETACHPSBYLEVEL" then
											if SN == "COMBATBASETACHPS" then
												if Lm <= 56 then
													Result = EquSng(CalcStat("CombatBaseTacHPSRaw",L))
												else
													Result = EquSng(DecSng(CalcStat("CombatBaseTacHPSRaw",L)))
												end
											end
										elseif SN > "COMBATBASETACHPSBYLEVEL" then
											if SN == "COMBATBASETACHPSBYLEVELRAW" then
												if Lm <= 46 then
													Result = CalcStat("CombatBaseTacHPSCurves",L)
												else
													Result = CalcStat("CombatBaseTacHPSByLevelRaw",46)
												end
											end
										else
											Result = EquSng(CalcStat("CombatBaseTacHPSByLevelRaw",L))
										end
									else
										Result = {{1,50,60,65,75,125,175,200,222,299,300,349,350,399,400,449,450,499,500,549,550,599},{1,50,60,65,75,85,95,100,105,105,106,115,116,120,121,130,131,140,141,150,151,160}}
									end
								elseif SN > "COMBATBASETACHPSCURVES" then
									if SN < "COMBATBASEWPNDPS" then
										if SN < "COMBATBASETACHPSNOCLASS" then
											if SN == "COMBATBASETACHPSLVLTOILVL" then
												if Lm <= 75 then
													Result = LinFmod(1,1,75,1,75,L)
												elseif Lm <= 100 then
													Result = LinFmod(1,75,200,75,100,L)
												elseif Lm <= 104 then
													Result = RoundDbl(LinFmod(1,201.3,214.3,101,104,L))
												elseif Lm <= 105 then
													Result = 222
												else
													Result = RoundDbl(CalcStat("LvlToILvl",L))
												end
											end
										elseif SN > "COMBATBASETACHPSNOCLASS" then
											if SN == "COMBATBASETACHPSRAW" then
												if Lm <= 49 then
													Result = CalcStat("CombatBaseTacHPSCurves",L)-CalcStat("CombatBaseTacHPSByLevelRaw",L)
												elseif Lm <= 55 then
													Result = 0.5
												elseif Lm <= 599 then
													Result = CalcStat("CommonTacHPS",L)-CalcStat("CombatBaseTacHPSByLevelRaw",L)
												elseif Lm <= 649 then
													Result = (RoundDblUp((4*L+2)/22)*678-RoundDblUp((L+1)/22))*0.175-11734.1-CalcStat("CombatBaseTacHPSByLevelRaw",L)
												else
													Result = CalcStat("CombatBaseTacHPSRaw",649)
												end
											end
										else
											Result = EquSng(CalcStat("CombatBaseTacHPSByLevelRaw",L)+CalcStat("CombatBaseTacHPSRaw",CalcStat("CombatBaseTacHPSLvlToILvl",L)))
										end
									elseif SN > "COMBATBASEWPNDPS" then
										if SN < "COMBATBASEWPNDPSCATTYPEMP" then
											if SN == "COMBATBASEWPNDPSBASE" then
												Result = EquSng(DecSng(CalcStat("CombatBaseWpnDPSCatTypeMP",WpnCodeIndex(C,1)*4+WpnCodeIndex(C,2))*CalcStat("CombatBasePhyDPS",L)*1.08))
											end
										elseif SN > "COMBATBASEWPNDPSCATTYPEMP" then
											if SN == "COMBATBASEWPNDPSQTYMP" then
												if 1 <= Lp and Lm <= 5 then
													Result = EquSng(DataTableValue({1,1.02,1.04,1.08,1.12},L))
												end
											end
										else
											if 9 <= Lp and Lm <= 9 then
												Result = 0.9
											elseif 5 <= Lp and Lm <= 5 then
												Result = 1
											elseif 10 <= Lp and Lm <= 11 then
												Result = 1.2
											elseif 6 <= Lp and Lm <= 7 then
												Result = 1.4
											else
												Result = 1
											end
										end
									else
										Result = EquSng(CalcStat("CombatBaseWpnDPSBase",L,C)*CalcStat("CombatBaseWpnDPSQtyMP",WpnCodeIndex(C,3)))
									end
								else
									if Lm <= 25 then
										Result = (13*L+85)*(81-L)/3920
									else
										Result = (13*L+85)*(75-L)/3500
									end
								end
							else
								Result = EquSng(DecSng(CalcStat("CombatBaseTacDPSRaw",L)))
							end
						elseif SN > "COMBATDAMAGEMOD" then
							if SN < "COMBATDAMAGEMODPLAYERSADJ" then
								if SN < "COMBATDAMAGEMODMPDMGADJ" then
									if SN < "COMBATDAMAGEMODHEALTHLOWADJ" then
										if SN < "COMBATDAMAGEMODHEALTHITEM" then
											if SN == "COMBATDAMAGEMODENERGY" then
												Result = EquSng(StatLinInter("PntMPCombatDamageMod","TraitPntSVital","ProgBEnergy","",L,N,2))
											end
										elseif SN > "COMBATDAMAGEMODHEALTHITEM" then
											if SN == "COMBATDAMAGEMODHEALTHLOW" then
												Result = EquSng(StatLinInter("PntMPCombatDamageMod","TraitPntSVital","ProgBHealth","CombatDamageModHealthLowAdj",L,N,99))
											end
										else
											Result = EquSng(StatLinInter("PntMPCombatDamageMod","ItemPntSClassic","ProgBHealth","",L,N,0))
										end
									elseif SN > "COMBATDAMAGEMODHEALTHLOWADJ" then
										if SN < "COMBATDAMAGEMODHEALTHMEDIUMADJ" then
											if SN == "COMBATDAMAGEMODHEALTHMEDIUM" then
												Result = EquSng(StatLinInter("PntMPCombatDamageMod","TraitPntSVital","ProgBHealth","CombatDamageModHealthMediumAdj",L,N,99))
											end
										elseif SN > "COMBATDAMAGEMODHEALTHMEDIUMADJ" then
											if SN == "COMBATDAMAGEMODMPDMG" then
												Result = EquSng(StatLinInter("PntMPCombatDamageMod","TraitPntSVital","ProgBDamageNoImp","CombatDamageModMPDmgAdj",L,N,2))
											end
										else
											if Lm <= 1 then
												Result = 0.36
											elseif Lm <= 25 then
												Result = 0.54
											elseif Lm <= 50 then
												Result = 0.72
											else
												Result = 0.9
											end
										end
									else
										if Lm <= 1 then
											Result = 0.144
										elseif Lm <= 25 then
											Result = 0.324
										elseif Lm <= 50 then
											Result = 0.576
										else
											Result = 0.9
										end
									end
								elseif SN > "COMBATDAMAGEMODMPDMGADJ" then
									if SN < "COMBATDAMAGEMODPETS" then
										if SN < "COMBATDAMAGEMODMPHEALADJ" then
											if SN == "COMBATDAMAGEMODMPHEAL" then
												Result = EquSng(StatLinInter("PntMPCombatDamageMod","TraitPntSVital","ProgBHealth","CombatDamageModMPHealAdj",L,N,2))
											end
										elseif SN > "COMBATDAMAGEMODMPHEALADJ" then
											if SN == "COMBATDAMAGEMODNPCS" then
												Result = EquSng(StatLinInter("PntMPCombatDamageMod","TraitPntSVital","ProgBDamageNoImp","",L,N,99))
											end
										else
											if Lm <= 141 then
												Result = 1
											else
												Result = 0.71
											end
										end
									elseif SN > "COMBATDAMAGEMODPETS" then
										if SN < "COMBATDAMAGEMODPETSRND" then
											if SN == "COMBATDAMAGEMODPETSADJ" then
												if Lm <= 1 then
													Result = 1
												elseif Lm <= 25 then
													Result = 0.4
												elseif Lm <= 50 then
													Result = 0.5
												elseif Lm <= 60 then
													Result = 0.6
												elseif Lm <= 65 then
													Result = 0.7
												elseif Lm <= 75 then
													Result = 0.8
												elseif Lm <= 85 then
													Result = 0.85
												elseif Lm <= 95 then
													Result = 0.9
												elseif Lm <= 100 then
													Result = 0.95
												else
													Result = 1
												end
											end
										elseif SN > "COMBATDAMAGEMODPETSRND" then
											if SN == "COMBATDAMAGEMODPLAYERS" then
												Result = EquSng(StatLinInter("PntMPCombatDamageMod","TraitPntSVital","ProgBDamageNoImp","CombatDamageModPlayersAdj",L,N,99))
											end
										else
											Result = EquSng(StatLinInter("PntMPCombatDamageMod","TraitPntSVital","ProgBDamageNoImp","CombatDamageModPetsAdj",L,N,2))
										end
									else
										Result = EquSng(StatLinInter("PntMPCombatDamageMod","TraitPntSVital","ProgBDamageNoImp","CombatDamageModPetsAdj",L,N,99))
									end
								else
									if Lm <= 141 then
										Result = 1
									else
										Result = 0.875
									end
								end
							elseif SN > "COMBATDAMAGEMODPLAYERSADJ" then
								if SN < "CPTCOVFATE" then
									if SN < "CONSTSTATC" then
										if SN < "COMMONTACHPS" then
											if SN == "COMBATINHEAL" then
												Result = CalcStat("InHeal",L,2.0)
											end
										elseif SN > "COMMONTACHPS" then
											if SN == "COMMONTACHPSITEMPNTS" then
												Result = {{1,50,60,65,75,125,175,200,222,299,300,349,350,399,400,449,450,499,500,549,550,599},{1,50,60,65,75,85,95,100,105,105,106,115,116,120,121,130,131,140,141,150,151,160}}
											end
										else
											Result = StatLinInter("PntMPTacHPS","CommonTacHPSItemPntS","ProgBTacHPS","",L,N,99)
										end
									elseif SN > "CONSTSTATC" then
										if SN < "CPTBLADEPHYMAS" then
											if SN == "CPTBLADECRITDEF" then
												Result = CalcStat("CritDefT",L,0.8)
											end
										elseif SN > "CPTBLADEPHYMAS" then
											if SN == "CPTBLADETACMAS" then
												Result = CalcStat("TacMasT",L,0.8)
											end
										else
											Result = CalcStat("PhyMasT",L,1.2)
										end
									else
										Result = CalcStat(C,1,L)
									end
								elseif SN > "CPTCOVFATE" then
									if SN < "CPTCRITDEF" then
										if SN < "CPTCOVPHYMIT" then
											if SN == "CPTCOVMAIN" then
												Result = CalcStat("MainT",L,0.4)
											end
										elseif SN > "CPTCOVPHYMIT" then
											if SN == "CPTCOVVITALITY" then
												Result = CalcStat("VitalityT",L,0.4)
											end
										else
											Result = CalcStat("PhyMitT",L,2.4)
										end
									elseif SN > "CPTCRITDEF" then
										if SN < "CPTIDOMEMAIN" then
											if SN == "CPTIDOMEFATE" then
												Result = CalcStat("FateT",L,0.4)
											end
										elseif SN > "CPTIDOMEMAIN" then
											if SN > "CPTIDOMEVITALITY" then
												if SN == "CPTSHIELDCRITDEF" then
													Result = CalcStat("CritDefT",L,1.2)
												end
											elseif SN == "CPTIDOMEVITALITY" then
												Result = CalcStat("VitalityT",L,0.4)
											end
										else
											Result = CalcStat("MainT",L,0.4)
										end
									else
										Result = CalcStat("CritDef",L,0.6)
									end
								else
									Result = CalcStat("FateT",L,0.4)
								end
							else
								if Lm <= 1 then
									Result = 0.8
								elseif Lm <= 25 then
									Result = 0.9
								else
									Result = 1
								end
							end
						else
							Result = EquSng(StatLinInter("PntMPCombatDamageMod","TraitPntSVital","ProgBDamageNoImp","",L,N,2))
						end
					else
						Result = 2
					end
				else
					Result = CalcStat("ClassBaseICMRH",L)
				end
			else
				Result = 0.12
			end
		elseif SN > "CPTSHIELDPHYMAS" then
			if SN < "HNTCAMPFIRENCMR" then
				if SN < "EVADEPRATP" then
					if SN < "CRITMAGNPRATPCAP" then
						if SN < "CRITDEFCI" then
							if SN < "CREEPAUDACITYTACDMGP" then
								if SN < "CREEPAUDACITYCOST" then
									if SN < "CPTSONGTACMAS" then
										if SN < "CPTSONGCRITDEF" then
											if SN == "CPTSHIELDTACMAS" then
												Result = CalcStat("TacMasT",L,0.8)
											end
										elseif SN > "CPTSONGCRITDEF" then
											if SN == "CPTSONGPHYMAS" then
												Result = CalcStat("PhyMasT",L,0.8)
											end
										else
											Result = CalcStat("CritDefT",L,0.8)
										end
									elseif SN > "CPTSONGTACMAS" then
										if SN < "CPTSTANDALONETACMAS" then
											if SN == "CPTSTANDALONEPHYMAS" then
												Result = CalcStat("PhyMasT",L,1.2)
											end
										elseif SN > "CPTSTANDALONETACMAS" then
											if SN == "CREEPAUDACITYCCDP" then
												if 1 <= Lp and Lm <= 16 then
													Result = 0.5
												elseif 17 <= Lp and Lm <= 60 then
													Result = 0.4
												end
											end
										else
											Result = CalcStat("TacMasT",L,0.8)
										end
									else
										Result = CalcStat("TacMasT",L,1.2)
									end
								elseif SN > "CREEPAUDACITYCOST" then
									if SN < "CREEPAUDACITYMELREDP" then
										if SN < "CREEPAUDACITYDMGP" then
											if SN == "CREEPAUDACITYCOSTBASE" then
												if 1 <= Lp and Lm <= 2 then
													Result = 2*L
												elseif 3 <= Lp and Lm <= 9 then
													Result = 2*L-1
												elseif 10 <= Lp and Lm <= 15 then
													Result = 3*L
												elseif 16 <= Lp and Lm <= 25 then
													Result = 6*L
												elseif 26 <= Lp and Lm <= 29 then
													Result = 9*L
												elseif 30 <= Lp and Lm <= 36 then
													Result = 300
												end
											end
										elseif SN > "CREEPAUDACITYDMGP" then
											if SN == "CREEPAUDACITYMELDMGP" then
												Result = CalcStat("CreepAudacityDmgP",L)
											end
										else
											if 1 <= Lp and Lm <= 10 then
												Result = LinFmod(1,1,1.2,1,10,L)
											elseif 11 <= Lp and Lm <= 36 then
												Result = LinFmod(1,1.2,1.25,10,36,L)
											elseif 37 <= Lp and Lm <= 41 then
												Result = LinFmod(1,1.25,1.3,36,41,L)
											elseif 42 <= Lp and Lm <= 60 then
												Result = LinFmod(1,1.3,1.25,41,60,L)
											end
										end
									elseif SN > "CREEPAUDACITYMELREDP" then
										if SN < "CREEPAUDACITYRNGDMGP" then
											if SN == "CREEPAUDACITYREDP" then
												if 1 <= Lp and Lm <= 10 then
													Result = LinFmod(1,0.5,0.5,1,10,L)
												elseif 11 <= Lp and Lm <= 36 then
													Result = LinFmod(1,0.5,0.5,10,36,L)
												elseif 37 <= Lp and Lm <= 41 then
													Result = LinFmod(1,0.5,0.5,36,41,L)
												elseif 42 <= Lp and Lm <= 60 then
													Result = LinFmod(1,0.5,0.5,41,60,L)
												end
											end
										elseif SN > "CREEPAUDACITYRNGDMGP" then
											if SN == "CREEPAUDACITYRNGREDP" then
												Result = CalcStat("CreepAudacityRedP",L)
											end
										else
											Result = CalcStat("CreepAudacityDmgP",L)
										end
									else
										Result = CalcStat("CreepAudacityRedP",L)
									end
								else
									Result = CalcStat("CreepAudacityCostBase",L)*25
								end
							elseif SN > "CREEPAUDACITYTACDMGP" then
								if SN < "CREEPBATPROMTACDMGP" then
									if SN < "CREEPBATPROMMELDMGP" then
										if SN < "CREEPBATPROMDMGP" then
											if SN == "CREEPAUDACITYTACREDP" then
												Result = CalcStat("CreepAudacityRedP",L)
											end
										elseif SN > "CREEPBATPROMDMGP" then
											if SN == "CREEPBATPROMHEALTHP" then
												Result = CalcStat("CreepBatPromVitalP",L)
											end
										else
											if 1 <= Lp and Lm <= 5 then
												Result = LinFmod(1,0.005,0.02,1,5,L)
											elseif 6 <= Lp and Lm <= 10 then
												Result = LinFmod(1,0.02,0.045,5,10,L)
											elseif 11 <= Lp and Lm <= 15 then
												Result = LinFmod(1,0.045,0.075,10,15,L)
											end
										end
									elseif SN > "CREEPBATPROMMELDMGP" then
										if SN < "CREEPBATPROMPOWERP" then
											if SN == "CREEPBATPROMOUTHEALP" then
												if 1 <= Lp and Lm <= 5 then
													Result = LinFmod(1,0.02,0.1,1,5,L)
												elseif 6 <= Lp and Lm <= 10 then
													Result = LinFmod(1,0.1,0.15,5,10,L)
												elseif 11 <= Lp and Lm <= 15 then
													Result = LinFmod(1,0.15,0.2,10,15,L)
												end
											end
										elseif SN > "CREEPBATPROMPOWERP" then
											if SN == "CREEPBATPROMRNGDMGP" then
												Result = CalcStat("CreepBatPromDmgP",L)
											end
										else
											Result = CalcStat("CreepBatPromVitalP",L)
										end
									else
										Result = CalcStat("CreepBatPromDmgP",L)
									end
								elseif SN > "CREEPBATPROMTACDMGP" then
									if SN < "CREEPTRAITPNTS" then
										if SN < "CREEPILVLCURR" then
											if SN == "CREEPBATPROMVITALP" then
												if 1 <= Lp and Lm <= 5 then
													Result = LinFmod(1,1.02,1.1,1,5,L)
												elseif 6 <= Lp and Lm <= 10 then
													Result = LinFmod(1,1.1,1.15,5,10,L)
												elseif 11 <= Lp and Lm <= 15 then
													Result = LinFmod(1,1.15,1.2,10,15,L)
												end
											end
										elseif SN > "CREEPILVLCURR" then
											if SN == "CREEPITEMPNTS" then
												Result = {{500,549},{141,150}}
											end
										else
											Result = 525
										end
									elseif SN > "CREEPTRAITPNTS" then
										if SN < "CRITDEF" then
											if SN == "CREEPTRAITPROGB" then
												Result = LinFmod(1,0.01,1,1,CalcStat("LevelCap",L),L)
											end
										elseif SN > "CRITDEF" then
											if SN == "CRITDEFC" then
												Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("CritDefCI",CalcStat("CritDefCILvlFilter",N),N),0)
											end
										else
											Result = EquSng(StatLinInter("PntMPCritDef","ItemPntS","ProgBCritDef","AdjItem",L,N,0))
										end
									else
										Result = {{1,150},{1,150}}
									end
								else
									Result = CalcStat("CreepBatPromDmgP",L)
								end
							else
								Result = CalcStat("CreepAudacityDmgP",L)
							end
						elseif SN > "CRITDEFCI" then
							if SN < "CRITHITCIRAW" then
								if SN < "CRITDEFPRATPC" then
									if SN < "CRITDEFPPRAT" then
										if SN < "CRITDEFCIRAW" then
											if SN == "CRITDEFCILVLFILTER" then
												if 4 <= Lp and Lm <= 4 or 4.6 <= Lp and Lm <= 4.6 or 5.6 <= Lp and Lm <= 5.6 or 6.2 <= Lp and Lm <= 6.2 or 8.4 <= Lp and Lm <= 8.4 or 11.2 <= Lp and Lm <= 11.2 or 14 <= Lp and Lm <= 14 then
													Result = 515
												elseif 2.8 <= Lp and Lm <= 2.8 then
													Result = 520
												else
													Result = CalcStat("CreepILvlCurr",L)
												end
											end
										elseif SN > "CRITDEFCIRAW" then
											if SN == "CRITDEFCRAW" then
												Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("CritDefCIRaw",CalcStat("CritDefCILvlFilter",N),N),99)
											end
										else
											Result = StatLinInter("PntMPCritDefC","ItemPntS","ProgBCritDef","AdjCreepItem",L,N,4)
										end
									elseif SN > "CRITDEFPPRAT" then
										if SN < "CRITDEFPRATPA" then
											if SN == "CRITDEFPRATP" then
												Result = CalcPercAB(CalcStat("CritDefPRatPA",L),CalcStat("CritDefPRatPB",L),CalcStat("CritDefPRatPCap",L),N)
											end
										elseif SN > "CRITDEFPRATPA" then
											if SN == "CRITDEFPRATPB" then
												Result = CalcStat("BRatRounded",L,"BRatStandard")
											end
										else
											Result = 240
										end
									else
										Result = CalcRatAB(CalcStat("CritDefPRatPA",L),CalcStat("CritDefPRatPB",L),CalcStat("CritDefPRatPCapR",L),N)
									end
								elseif SN > "CRITDEFPRATPC" then
									if SN < "CRITHIT" then
										if SN < "CRITDEFPRATPCAPR" then
											if SN == "CRITDEFPRATPCAP" then
												Result = 80
											end
										elseif SN > "CRITDEFPRATPCAPR" then
											if SN == "CRITDEFT" then
												Result = EquSng(StatLinInter("PntMPCritDef","TraitPntS","ProgBCritDef","AdjTrait",L,N,0))
											end
										else
											Result = CalcStat("CritDefPRatPB",L)*CalcStat("CritDefPRatPC",L)
										end
									elseif SN > "CRITHIT" then
										if SN < "CRITHITCI" then
											if SN == "CRITHITC" then
												Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("CritHitCI",CalcStat("CritHitCILvlFilter",N),N),0)
											end
										elseif SN > "CRITHITCI" then
											if SN == "CRITHITCILVLFILTER" then
												if 2.2 <= Lp and Lm <= 2.2 or 3.8 <= Lp and Lm <= 3.8 or 4.6 <= Lp and Lm <= 4.6 or 5.2 <= Lp and Lm <= 5.2 or 10.4 <= Lp and Lm <= 10.4 or 15.6 <= Lp and Lm <= 15.6 then
													Result = 515
												else
													Result = CalcStat("CreepILvlCurr",L)
												end
											end
										else
											Result = RoundDblLotro(CalcStat("CritHitCIRaw",L,N))
										end
									else
										Result = EquSng(StatLinInter("PntMPCritHit","ItemPntS","ProgBCritHit","AdjItem",L,N,0))
									end
								else
									Result = 0.5
								end
							elseif SN > "CRITHITCIRAW" then
								if SN < "CRITHITPRATPCAP" then
									if SN < "CRITHITPRATP" then
										if SN < "CRITHITOLD" then
											if SN == "CRITHITCRAW" then
												Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("CritHitCIRaw",CalcStat("CritHitCILvlFilter",N),N),99)
											end
										elseif SN > "CRITHITOLD" then
											if SN == "CRITHITPPRAT" then
												Result = CalcRatAB(CalcStat("CritHitPRatPA",L),CalcStat("CritHitPRatPB",L),CalcStat("CritHitPRatPCapR",L),N)
											end
										else
											Result = CalcStat("CritHit",L,N)
										end
									elseif SN > "CRITHITPRATP" then
										if SN < "CRITHITPRATPB" then
											if SN == "CRITHITPRATPA" then
												Result = 75
											end
										elseif SN > "CRITHITPRATPB" then
											if SN == "CRITHITPRATPC" then
												Result = 0.5
											end
										else
											Result = CalcStat("BRatRounded",L,"BRatExtra")
										end
									else
										Result = CalcPercAB(CalcStat("CritHitPRatPA",L),CalcStat("CritHitPRatPB",L),CalcStat("CritHitPRatPCap",L),N)
									end
								elseif SN > "CRITHITPRATPCAP" then
									if SN < "CRITMAGNPRATP" then
										if SN < "CRITHITT" then
											if SN == "CRITHITPRATPCAPR" then
												Result = CalcStat("CritHitPRatPB",L)*CalcStat("CritHitPRatPC",L)
											end
										elseif SN > "CRITHITT" then
											if SN == "CRITMAGNPPRAT" then
												Result = CalcRatAB(CalcStat("CritMagnPRatPA",L),CalcStat("CritMagnPRatPB",L),CalcStat("CritMagnPRatPCapR",L),N)
											end
										else
											Result = EquSng(StatLinInter("PntMPCritHit","TraitPntS","ProgBCritHit","AdjTrait",L,N,0))
										end
									elseif SN > "CRITMAGNPRATP" then
										if SN < "CRITMAGNPRATPB" then
											if SN == "CRITMAGNPRATPA" then
												Result = 225
											end
										elseif SN > "CRITMAGNPRATPB" then
											if SN == "CRITMAGNPRATPC" then
												Result = 0.5
											end
										else
											Result = CalcStat("BRatRounded",L,"BRatCritMagn")
										end
									else
										Result = CalcPercAB(CalcStat("CritMagnPRatPA",L),CalcStat("CritMagnPRatPB",L),CalcStat("CritMagnPRatPCap",L),N)
									end
								else
									Result = 25
								end
							else
								Result = StatLinInter("PntMPCritHitC","ItemPntS","ProgBCritHit","AdjCreepItem",L,N,4)
							end
						else
							Result = RoundDblLotro(CalcStat("CritDefCIRaw",L,N))
						end
					elseif SN > "CRITMAGNPRATPCAP" then
						if SN < "DWARFRDTRAITNCMR" then
							if SN < "DISEASERESIST" then
								if SN < "DEFILERCDHASPOWER" then
									if SN < "DEFILERCANBLOCK" then
										if SN < "CRYRESIST" then
											if SN == "CRITMAGNPRATPCAPR" then
												Result = CalcStat("CritMagnPRatPB",L)*CalcStat("CritMagnPRatPC",L)
											end
										elseif SN > "CRYRESIST" then
											if SN == "CRYRESISTT" then
												Result = CalcStat("ResistAddT",L,N)
											end
										else
											Result = CalcStat("ResistAdd",L,N)
										end
									elseif SN > "DEFILERCANBLOCK" then
										if SN < "DEFILERCDCALCTYPENONPHYMIT" then
											if SN == "DEFILERCDCALCTYPECOMPHYMIT" then
												Result = 13
											end
										elseif SN > "DEFILERCDCALCTYPENONPHYMIT" then
											if SN == "DEFILERCDCALCTYPETACMIT" then
												Result = 27
											end
										else
											Result = 14
										end
									else
										Result = 1
									end
								elseif SN > "DEFILERCDHASPOWER" then
									if SN < "DEVHITPRATPB" then
										if SN < "DEVHITPRATP" then
											if SN == "DEVHITPPRAT" then
												Result = CalcRatAB(CalcStat("DevHitPRatPA",L),CalcStat("DevHitPRatPB",L),CalcStat("DevHitPRatPCapR",L),N)
											end
										elseif SN > "DEVHITPRATP" then
											if SN == "DEVHITPRATPA" then
												Result = 30
											end
										else
											Result = CalcPercAB(CalcStat("DevHitPRatPA",L),CalcStat("DevHitPRatPB",L),CalcStat("DevHitPRatPCap",L),N)
										end
									elseif SN > "DEVHITPRATPB" then
										if SN < "DEVHITPRATPCAP" then
											if SN == "DEVHITPRATPC" then
												Result = 0.5
											end
										elseif SN > "DEVHITPRATPCAP" then
											if SN == "DEVHITPRATPCAPR" then
												Result = CalcStat("DevHitPRatPB",L)*CalcStat("DevHitPRatPC",L)
											end
										else
											Result = 10
										end
									else
										Result = CalcStat("BRatRounded",L,"BRatDevHit")
									end
								else
									Result = 1
								end
							elseif SN > "DISEASERESIST" then
								if SN < "DWARFRDPSVONENAME" then
									if SN < "DWARFENDURVITALITY" then
										if SN < "DMGTYPEMIT" then
											if SN == "DISEASERESISTT" then
												Result = CalcStat("ResistAddT",L,N)
											end
										elseif SN > "DMGTYPEMIT" then
											if SN == "DMGTYPEMITT" then
												Result = EquSng(StatLinInter("PntMPDmgTypeMitT","TraitPntS","ProgBMitigation","AdjTraitMit",L,N,0))
											end
										else
											Result = EquSng(StatLinInter("PntMPDmgTypeMit","ItemPntS","ProgBMitigation","AdjItemMit",L,N,0))
										end
									elseif SN > "DWARFENDURVITALITY" then
										if SN < "DWARFLOSTDWARFKDSFATE" then
											if SN == "DWARFFATEFULDWARFFATE" then
												Result = CalcStat("FateT",L,1.0)
											end
										elseif SN > "DWARFLOSTDWARFKDSFATE" then
											if SN == "DWARFRDPSVONEFATE" then
												Result = CalcStat("DwarfFatefulDwarfFate",L)
											end
										else
											Result = -CalcStat("FateT",L,0.4)
										end
									else
										Result = CalcStat("VitalityT",L,1.0)
									end
								elseif SN > "DWARFRDPSVONENAME" then
									if SN < "DWARFRDTRAITFATE" then
										if SN < "DWARFRDPSVTWONAME" then
											if SN == "DWARFRDPSVTWOBLOCK" then
												Result = CalcStat("DwarfShieldBrwlBlock",L)
											end
										elseif SN > "DWARFRDPSVTWONAME" then
											if SN == "DWARFRDTRAITAGILITY" then
												Result = CalcStat("DwarfStockyAgility",L)
											end
										else
											Result = "Shield Brawler"
										end
									elseif SN > "DWARFRDTRAITFATE" then
										if SN < "DWARFRDTRAITICPR" then
											if SN == "DWARFRDTRAITICMR" then
												Result = CalcStat("DwarfUnwearBattleICMR",L)
											end
										elseif SN > "DWARFRDTRAITICPR" then
											if SN == "DWARFRDTRAITMIGHT" then
												Result = CalcStat("DwarfSturdinessMight",L)
											end
										else
											Result = CalcStat("DwarfUnwearBattleICPR",L)
										end
									else
										Result = CalcStat("DwarfLostDwarfKdsFate",L)
									end
								else
									Result = "Fateful Dwarf"
								end
							else
								Result = CalcStat("ResistAdd",L,N)
							end
						elseif SN > "DWARFRDTRAITNCMR" then
							if SN < "ELFRDPSVONEFATE" then
								if SN < "DWARFSTURDINESSVITALITY" then
									if SN < "DWARFSHIELDBRWLBLOCK" then
										if SN < "DWARFRDTRAITPHYMITP" then
											if SN == "DWARFRDTRAITNCPR" then
												Result = CalcStat("DwarfUnwearBattleNCPR",L)
											end
										elseif SN > "DWARFRDTRAITPHYMITP" then
											if SN == "DWARFRDTRAITVITALITY" then
												Result = CalcStat("DwarfSturdinessVitality",L)
											end
										else
											Result = CalcStat("DwarfSturdinessPhyMitP",L)
										end
									elseif SN > "DWARFSHIELDBRWLBLOCK" then
										if SN < "DWARFSTURDINESSMIGHT" then
											if SN == "DWARFSTOCKYAGILITY" then
												Result = -CalcStat("AgilityT",L,0.4)
											end
										elseif SN > "DWARFSTURDINESSMIGHT" then
											if SN == "DWARFSTURDINESSPHYMITP" then
												Result = 1
											end
										else
											Result = CalcStat("MightT",L,1.0)
										end
									else
										Result = CalcStat("BlockT",L,0.8)
									end
								elseif SN > "DWARFSTURDINESSVITALITY" then
									if SN < "DWARFUNWEARBATTLENCPR" then
										if SN < "DWARFUNWEARBATTLEICPR" then
											if SN == "DWARFUNWEARBATTLEICMR" then
												Result = CalcStat("ICMRT",L,0.6)
											end
										elseif SN > "DWARFUNWEARBATTLEICPR" then
											if SN == "DWARFUNWEARBATTLENCMR" then
												Result = -CalcStat("NCMRT",L,0.4)
											end
										else
											Result = CalcStat("ICPRT",L,0.6)
										end
									elseif SN > "DWARFUNWEARBATTLENCPR" then
										if SN < "ELFFADINGFIRSTBORNFATE" then
											if SN == "ELFAGILITYWOODSAGILITY" then
												Result = CalcStat("AgilityT",L,1.0)
											end
										elseif SN > "ELFFADINGFIRSTBORNFATE" then
											if SN == "ELFFRIENDOFMANFATE" then
												Result = CalcStat("FateT",L,1.0)
											end
										else
											Result = -CalcStat("FateT",L,0.4)
										end
									else
										Result = -CalcStat("NCPRT",L,0.4)
									end
								else
									Result = CalcStat("VitalityT",L,1.0)
								end
							elseif SN > "ELFRDPSVONEFATE" then
								if SN < "ELFSORROWFIRSTBORNNCMR" then
									if SN < "ELFRDTRAITFATE" then
										if SN < "ELFRDPSVTWONAME" then
											if SN == "ELFRDPSVONENAME" then
												Result = "Friend Of Man"
											end
										elseif SN > "ELFRDPSVTWONAME" then
											if SN == "ELFRDTRAITAGILITY" then
												Result = CalcStat("ElfAgilityWoodsAgility",L)
											end
										else
											Result = ""
										end
									elseif SN > "ELFRDTRAITFATE" then
										if SN < "ELFRDTRAITNCMR" then
											if SN == "ELFRDTRAITMORALE" then
												Result = CalcStat("ElfSorrowFirstbornMorale",L)
											end
										elseif SN > "ELFRDTRAITNCMR" then
											if SN == "ELFSORROWFIRSTBORNMORALE" then
												Result = -CalcStat("MoraleT",L,0.4)
											end
										else
											Result = CalcStat("ElfSorrowFirstbornNCMR",L)
										end
									else
										Result = CalcStat("ElfFadingFirstbornFate",L)
									end
								elseif SN > "ELFSORROWFIRSTBORNNCMR" then
									if SN < "EVADECIRAW" then
										if SN < "EVADEC" then
											if SN == "EVADE" then
												Result = CalcStat("BPE",L,N)
											end
										elseif SN > "EVADEC" then
											if SN == "EVADECI" then
												Result = CalcStat("BPECI",L,N)
											end
										else
											Result = CalcStat("BPEC",L,N)
										end
									elseif SN > "EVADECIRAW" then
										if SN < "EVADEPBONUS" then
											if SN == "EVADECRAW" then
												Result = CalcStat("BPECRAW",L,N)
											end
										elseif SN > "EVADEPBONUS" then
											if SN == "EVADEPPRAT" then
												Result = CalcStat("BPEPPRat",L,N)
											end
										else
											Result = CalcStat("BPEPBonus",L)
										end
									else
										Result = CalcStat("BPECIRAW",L,N)
									end
								else
									Result = -CalcStat("NCMRT",L,0.4)
								end
							else
								Result = CalcStat("ElfFriendOfManFate",L)
							end
						else
							Result = CalcStat("DwarfUnwearBattleNCMR",L)
						end
					else
						Result = 75
					end
				elseif SN > "EVADEPRATP" then
					if SN < "GRDTENDERIZET4CRITHIT" then
						if SN < "FOODNCMRM" then
							if SN < "FINESSECILVLFILTER" then
								if SN < "FATEC" then
									if SN < "EVADEPRATPCAP" then
										if SN < "EVADEPRATPB" then
											if SN == "EVADEPRATPA" then
												Result = CalcStat("BPEPRatPA",L)
											end
										elseif SN > "EVADEPRATPB" then
											if SN == "EVADEPRATPC" then
												Result = CalcStat("BPEPRatPC",L)
											end
										else
											Result = CalcStat("BPEPRatPB",L)
										end
									elseif SN > "EVADEPRATPCAP" then
										if SN < "EVADET" then
											if SN == "EVADEPRATPCAPR" then
												Result = CalcStat("BPEPRatPCapR",L)
											end
										elseif SN > "EVADET" then
											if SN == "FATE" then
												Result = RoundDblDown(StatLinInter("PntMPFate","ItemPntSVital","ProgBFate","",L,N,0))
											end
										else
											Result = CalcStat("BPET",L,N)
										end
									else
										Result = CalcStat("BPEPRatPCap",L)
									end
								elseif SN > "FATEC" then
									if SN < "FEARRESISTT" then
										if SN < "FATET" then
											if SN == "FATECI" then
												Result = CalcStat("MainCI",L,N)
											end
										elseif SN > "FATET" then
											if SN == "FEARRESIST" then
												Result = CalcStat("ResistAdd",L,N)
											end
										else
											Result = RoundDblDown(StatLinInter("PntMPFate","TraitPntSVital","ProgBFate","",L,N,0))
										end
									elseif SN > "FEARRESISTT" then
										if SN < "FINESSEC" then
											if SN == "FINESSE" then
												Result = EquSng(StatLinInter("PntMPFinesse","ItemPntS","ProgBFinesse","AdjItem",L,N,0))
											end
										elseif SN > "FINESSEC" then
											if SN == "FINESSECI" then
												Result = RoundDblLotro(CalcStat("FinesseCIRaw",L,N))
											end
										else
											Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("FinesseCI",CalcStat("FinesseCILvlFilter",N),N),0)
										end
									else
										Result = CalcStat("ResistAddT",L,N)
									end
								else
									Result = CalcStat("MainC",L,N)
								end
							elseif SN > "FINESSECILVLFILTER" then
								if SN < "FINESSEPRATPCAP" then
									if SN < "FINESSEPRATP" then
										if SN < "FINESSECRAW" then
											if SN == "FINESSECIRAW" then
												Result = StatLinInter("PntMPFinesseC","ItemPntS","ProgBFinesse","AdjCreepItem",L,N,4)
											end
										elseif SN > "FINESSECRAW" then
											if SN == "FINESSEPPRAT" then
												Result = CalcRatAB(CalcStat("FinessePRatPA",L),CalcStat("FinessePRatPB",L),CalcStat("FinessePRatPCapR",L),N)
											end
										else
											Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("FinesseCIRaw",CalcStat("FinesseCILvlFilter",N),N),99)
										end
									elseif SN > "FINESSEPRATP" then
										if SN < "FINESSEPRATPB" then
											if SN == "FINESSEPRATPA" then
												Result = 150
											end
										elseif SN > "FINESSEPRATPB" then
											if SN == "FINESSEPRATPC" then
												Result = 0.5
											end
										else
											Result = CalcStat("BRatRounded",L,"BRatStandard")
										end
									else
										Result = CalcPercAB(CalcStat("FinessePRatPA",L),CalcStat("FinessePRatPB",L),CalcStat("FinessePRatPCap",L),N)
									end
								elseif SN > "FINESSEPRATPCAP" then
									if SN < "FIREMITT" then
										if SN < "FINESSET" then
											if SN == "FINESSEPRATPCAPR" then
												Result = CalcStat("FinessePRatPB",L)*CalcStat("FinessePRatPC",L)
											end
										elseif SN > "FINESSET" then
											if SN == "FIREMIT" then
												Result = CalcStat("DmgTypeMit",L,N)
											end
										else
											Result = EquSng(StatLinInter("PntMPFinesseT","TraitPntS","ProgBFinesse","AdjTrait",L,N,0))
										end
									elseif SN > "FIREMITT" then
										if SN < "FOODNCMRH" then
											if SN == "FOODNCMRBASEPROG" then
												if Lm <= 1 then
													Result = (N*70.2+210)/60
												elseif Lm <= 2 then
													Result = (N*84+216)/120
												else
													Result = (N*83.7+270)/90
												end
											end
										elseif SN > "FOODNCMRH" then
											if SN == "FOODNCMRL" then
												Result = EquSng(CalcStat("FoodNCMRProg",L,2)*N)
											end
										else
											Result = EquSng(CalcStat("FoodNCMRProg",L,1)*N)
										end
									else
										Result = CalcStat("DmgTypeMitT",L,N)
									end
								else
									Result = 50
								end
							else
								if 3 <= Lp and Lm <= 3 or 3.6 <= Lp and Lm <= 3.6 or 6.2 <= Lp and Lm <= 6.2 or 7.2 <= Lp and Lm <= 7.2 or 10.8 <= Lp and Lm <= 10.8 or 14.4 <= Lp and Lm <= 14.4 then
									Result = 515
								else
									Result = CalcStat("CreepILvlCurr",L)
								end
							end
						elseif SN > "FOODNCMRM" then
							if SN < "FREEPAUDACITYTACDMGP" then
								if SN < "FREEPAUDACITYCCDP" then
									if SN < "FOODNCPRL" then
										if SN < "FOODNCPRBASEPROG" then
											if SN == "FOODNCMRPROG" then
												if Lm <= 50 then
													Result = CalcStat("FoodNCMRBaseProg",N,L)
												elseif Lm <= 52 then
													Result = CalcStat("FoodNCMRBaseProg",N,50)
												elseif Lm <= 77 then
													Result = CalcStat("FoodNCMRBaseProg",N,L-3)
												elseif Lm <= 111 then
													Result = CalcStat("FoodNCMRBaseProg",N,RoundDbl((L+143)/3))
												elseif Lm <= 140 then
													Result = CalcStat("FoodNCMRBaseProg",N,85)
												elseif Lm <= 217 then
													Result = CalcStat("FoodNCMRBaseProg",N,RoundDbl((L+200)/4))
												elseif Lm <= 221 then
													Result = CalcStat("FoodNCMRBaseProg",N,104)
												elseif Lm <= 299 then
													Result = CalcStat("FoodNCMRBaseProg",N,105)
												elseif Lm <= 320 then
													Result = CalcStat("FoodNCMRBaseProg",N,RoundDbl((L-53)/(7/3)))
												elseif Lm <= 325 then
													Result = CalcStat("FoodNCMRBaseProg",N,114)
												elseif Lm <= 326 then
													Result = CalcStat("FoodNCMRBaseProg",N,115)
												elseif 327 <= Lp then
													Result = ExpFmod(CalcStat("FoodNCMRProg",326,N),327,1,L,1)
												end
											end
										elseif SN > "FOODNCPRBASEPROG" then
											if SN == "FOODNCPRH" then
												Result = EquSng(CalcStat("FoodNCPRProg",L,1)*N)
											end
										else
											if Lm <= 1 then
												Result = (N*75+300)/60
											elseif Lm <= 2 then
												Result = (N*100+350)/120
											else
												Result = (N*90+337.5)/90
											end
										end
									elseif SN > "FOODNCPRL" then
										if SN < "FOODNCPRPROG" then
											if SN == "FOODNCPRM" then
												Result = EquSng(CalcStat("FoodNCPRProg",L,3)*N)
											end
										elseif SN > "FOODNCPRPROG" then
											if SN == "FOODRESIST" then
												Result = EquSng(StatLinInter("PntMPFoodResist","ItemPntS","ProgBResist","AdjItem",L,N,0))
											end
										else
											if Lm <= 1 then
												Result = CalcStat("FoodNCPRBaseProg",N,L)
											elseif Lm <= 6 then
												Result = CalcStat("FoodNCPRBaseProg",N,L)-0.25
											elseif Lm <= 24 then
												Result = CalcStat("FoodNCPRBaseProg",N,L)-0.5
											elseif Lm <= 48 then
												Result = CalcStat("FoodNCPRBaseProg",N,L)-0.75
											elseif Lm <= 61 then
												Result = RoundDblDown(CalcStat("FoodNCPRProg",48,N))+1
											elseif Lm <= 66 then
												Result = RoundDblDown(CalcStat("FoodNCPRProg",48,N))+2
											elseif Lm <= 72 then
												Result = RoundDblDown(CalcStat("FoodNCPRProg",48,N))+3
											elseif Lm <= 326 then
												Result = RoundDblDown(CalcStat("FoodNCPRProg",48,N))+4
											elseif 327 <= Lp then
												Result = ExpFmod(CalcStat("FoodNCPRProg",326,N),327,1,L,1)
											end
										end
									else
										Result = EquSng(CalcStat("FoodNCPRProg",L,2)*N)
									end
								elseif SN > "FREEPAUDACITYCCDP" then
									if SN < "FREEPAUDACITYMORALEP" then
										if SN < "FREEPAUDACITYMELDMGP" then
											if SN == "FREEPAUDACITYDMGP" then
												if 1 <= Lp and Lm <= 16 then
													Result = 0.75
												elseif 17 <= Lp and Lm <= 36 then
													Result = LinFmod(1,1.15,1.25,17,36,L)
												elseif 37 <= Lp and Lm <= 60 then
													Result = CalcStat("FreepAudacityDmgP",36)
												end
											end
										elseif SN > "FREEPAUDACITYMELDMGP" then
											if SN == "FREEPAUDACITYMELREDP" then
												Result = CalcStat("FreepAudacityRedP",L)
											end
										else
											Result = CalcStat("FreepAudacityDmgP",L)
										end
									elseif SN > "FREEPAUDACITYMORALEP" then
										if SN < "FREEPAUDACITYRNGDMGP" then
											if SN == "FREEPAUDACITYREDP" then
												if 1 <= Lp and Lm <= 16 then
													Result = 1.5
												elseif 17 <= Lp and Lm <= 36 then
													Result = 0.5
												elseif 37 <= Lp and Lm <= 60 then
													Result = CalcStat("FreepAudacityRedP",36)
												end
											end
										elseif SN > "FREEPAUDACITYRNGDMGP" then
											if SN == "FREEPAUDACITYRNGREDP" then
												Result = CalcStat("FreepAudacityRedP",L)
											end
										else
											Result = CalcStat("FreepAudacityDmgP",L)
										end
									else
										if 1 <= Lp and Lm <= 16 then
											Result = LinFmod(1,0.5,1.3,1,16,L)
										elseif 17 <= Lp and Lm <= 36 then
											Result = 1.4
										elseif 37 <= Lp and Lm <= 60 then
											Result = CalcStat("FreepAudacityMoraleP",36)
										end
									end
								else
									if 1 <= Lp and Lm <= 16 then
										Result = 0.5
									elseif 17 <= Lp and Lm <= 36 then
										Result = 0.4
									elseif 37 <= Lp and Lm <= 60 then
										Result = CalcStat("FreepAudacityCCDP",36)
									end
								end
							elseif SN > "FREEPAUDACITYTACDMGP" then
								if SN < "FREEPBATPROMVITALP" then
									if SN < "FREEPBATPROMMELDMGP" then
										if SN < "FREEPBATPROMDMGP" then
											if SN == "FREEPAUDACITYTACREDP" then
												Result = CalcStat("FreepAudacityRedP",L)
											end
										elseif SN > "FREEPBATPROMDMGP" then
											if SN == "FREEPBATPROMHEALTHP" then
												Result = CalcStat("FreepBatPromVitalP",L)
											end
										else
											if 1 <= Lp and Lm <= 1 then
												Result = 0.005
											elseif 2 <= Lp and Lm <= 14 then
												Result = LinFmod(1,0.005,0.065,2,14,L)
											elseif 15 <= Lp and Lm <= 15 then
												Result = 0.075
											end
										end
									elseif SN > "FREEPBATPROMMELDMGP" then
										if SN < "FREEPBATPROMRNGDMGP" then
											if SN == "FREEPBATPROMPOWERP" then
												Result = CalcStat("FreepBatPromVitalP",L)
											end
										elseif SN > "FREEPBATPROMRNGDMGP" then
											if SN == "FREEPBATPROMTACDMGP" then
												Result = CalcStat("FreepBatPromDmgP",L)
											end
										else
											Result = CalcStat("FreepBatPromDmgP",L)
										end
									else
										Result = CalcStat("FreepBatPromDmgP",L)
									end
								elseif SN > "FREEPBATPROMVITALP" then
									if SN < "GRDRELENTLASSFINESSE" then
										if SN < "FROSTMITT" then
											if SN == "FROSTMIT" then
												Result = CalcStat("DmgTypeMit",L,N)
											end
										elseif SN > "FROSTMITT" then
											if SN == "GRDCRITDEF" then
												Result = CalcStat("CritDef",L)
											end
										else
											Result = CalcStat("DmgTypeMitT",L,N)
										end
									elseif SN > "GRDRELENTLASSFINESSE" then
										if SN < "GRDTENDERIZET2CRITHIT" then
											if SN == "GRDTENDERIZECRITHIT" then
												Result = CalcStat("CritHitT",L,CalcStat("Trait12345Choice",N)*0.2)
											end
										elseif SN > "GRDTENDERIZET2CRITHIT" then
											if SN == "GRDTENDERIZET3CRITHIT" then
												Result = CalcStat("CritHitT",L,CalcStat("Trait357912Choice",N)*0.2)
											end
										else
											Result = CalcStat("CritHitT",L,CalcStat("Trait12345Choice",N)*0.4)
										end
									else
										Result = CalcStat("FinesseT",L,CalcStat("Trait12345Choice",N)*0.2)
									end
								else
									if 1 <= Lp and Lm <= 5 then
										Result = LinFmod(1,1.02,1.1,1,5,L)
									elseif 6 <= Lp and Lm <= 10 then
										Result = LinFmod(1,1.1,1.15,5,10,L)
									elseif 11 <= Lp and Lm <= 15 then
										Result = LinFmod(1,1.15,1.2,10,15,L)
									end
								end
							else
								Result = CalcStat("FreepAudacityDmgP",L)
							end
						else
							Result = EquSng(CalcStat("FoodNCMRProg",L,3)*N)
						end
					elseif SN > "GRDTENDERIZET4CRITHIT" then
						if SN < "GUARDIANCDMIGHTTOOUTHEAL" then
							if SN < "GUARDIANCDBASEMIGHT" then
								if SN < "GUARDIANCDARMOURTOCOMPHYMIT" then
									if SN < "GUARDIANCDAGILITYTOFINESSE" then
										if SN < "GRDWARDTACTTACMIT" then
											if SN == "GRDTENDERIZET5CRITHIT" then
												Result = CalcStat("CritHitT",L,CalcStat("Trait58121620Choice",N)*0.2)
											end
										elseif SN > "GRDWARDTACTTACMIT" then
											if SN == "GUARDIANCDAGILITYTOCRITHIT" then
												Result = 2
											end
										else
											Result = CalcStat("TacMitT",L,CalcStat("Trait12345Choice",N)*0.2)
										end
									elseif SN > "GUARDIANCDAGILITYTOFINESSE" then
										if SN < "GUARDIANCDAGILITYTOPARRY" then
											if SN == "GUARDIANCDAGILITYTOOUTHEAL" then
												Result = 2
											end
										elseif SN > "GUARDIANCDAGILITYTOPARRY" then
											if SN == "GUARDIANCDAGILITYTOPHYMAS" then
												Result = 2
											end
										else
											Result = 1
										end
									else
										Result = 1
									end
								elseif SN > "GUARDIANCDARMOURTOCOMPHYMIT" then
									if SN < "GUARDIANCDBASEAGILITY" then
										if SN < "GUARDIANCDARMOURTOTACMIT" then
											if SN == "GUARDIANCDARMOURTONONPHYMIT" then
												Result = 0.2
											end
										elseif SN > "GUARDIANCDARMOURTOTACMIT" then
											if SN == "GUARDIANCDARMOURTYPE" then
												Result = 3
											end
										else
											Result = 0.2
										end
									elseif SN > "GUARDIANCDBASEAGILITY" then
										if SN < "GUARDIANCDBASEICMR" then
											if SN == "GUARDIANCDBASEFATE" then
												Result = CalcStat("ClassBaseFate",L)
											end
										elseif SN > "GUARDIANCDBASEICMR" then
											if SN == "GUARDIANCDBASEICPR" then
												Result = CalcStat("ClassBaseICPR",L)
											end
										else
											Result = CalcStat("ClassBaseICMRH",L)
										end
									else
										Result = CalcStat("ClassBaseAgilityM",L)
									end
								else
									Result = 1
								end
							elseif SN > "GUARDIANCDBASEMIGHT" then
								if SN < "GUARDIANCDCALCTYPENONPHYMIT" then
									if SN < "GUARDIANCDBASEPOWER" then
										if SN < "GUARDIANCDBASENCMR" then
											if SN == "GUARDIANCDBASEMORALE" then
												Result = CalcStat("ClassBaseMorale",L)
											end
										elseif SN > "GUARDIANCDBASENCMR" then
											if SN == "GUARDIANCDBASENCPR" then
												Result = CalcStat("ClassBaseNCPR",L)
											end
										else
											Result = CalcStat("ClassBaseNCMRH",L)
										end
									elseif SN > "GUARDIANCDBASEPOWER" then
										if SN < "GUARDIANCDBASEWILL" then
											if SN == "GUARDIANCDBASEVITALITY" then
												Result = CalcStat("ClassBaseVitality",L)
											end
										elseif SN > "GUARDIANCDBASEWILL" then
											if SN == "GUARDIANCDCALCTYPECOMPHYMIT" then
												Result = 14
											end
										else
											Result = CalcStat("ClassBaseWillL",L)
										end
									else
										Result = CalcStat("ClassBasePower",L)
									end
								elseif SN > "GUARDIANCDCALCTYPENONPHYMIT" then
									if SN < "GUARDIANCDFATETOPOWER" then
										if SN < "GUARDIANCDCANBLOCK" then
											if SN == "GUARDIANCDCALCTYPETACMIT" then
												Result = 27
											end
										elseif SN > "GUARDIANCDCANBLOCK" then
											if SN == "GUARDIANCDFATETONCPR" then
												Result = 0.07
											end
										else
											Result = 1
										end
									elseif SN > "GUARDIANCDFATETOPOWER" then
										if SN < "GUARDIANCDMIGHTTOBLOCK" then
											if SN == "GUARDIANCDHASPOWER" then
												Result = 1
											end
										elseif SN > "GUARDIANCDMIGHTTOBLOCK" then
											if SN == "GUARDIANCDMIGHTTOCRITHIT" then
												Result = 1
											end
										else
											Result = 1
										end
									else
										Result = 1
									end
								else
									Result = 14
								end
							else
								Result = CalcStat("ClassBaseMightH",L)
							end
						elseif SN > "GUARDIANCDMIGHTTOOUTHEAL" then
							if SN < "GUARDIANCDWILLTOTACMIT" then
								if SN < "GUARDIANCDVITALITYTOICMR" then
									if SN < "GUARDIANCDMIGHTTOTACMIT" then
										if SN < "GUARDIANCDMIGHTTOPHYMAS" then
											if SN == "GUARDIANCDMIGHTTOPARRY" then
												Result = 2
											end
										elseif SN > "GUARDIANCDMIGHTTOPHYMAS" then
											if SN == "GUARDIANCDMIGHTTOPHYMIT" then
												Result = 1
											end
										else
											Result = 3
										end
									elseif SN > "GUARDIANCDMIGHTTOTACMIT" then
										if SN < "GUARDIANCDPHYMITTONONPHYMIT" then
											if SN == "GUARDIANCDPHYMITTOCOMPHYMIT" then
												Result = 1
											end
										elseif SN > "GUARDIANCDPHYMITTONONPHYMIT" then
											if SN == "GUARDIANCDTACMASTOOUTHEAL" then
												Result = 1
											end
										else
											Result = 1
										end
									else
										Result = 1
									end
								elseif SN > "GUARDIANCDVITALITYTOICMR" then
									if SN < "GUARDIANCDWILLTOOUTHEAL" then
										if SN < "GUARDIANCDVITALITYTONCMR" then
											if SN == "GUARDIANCDVITALITYTOMORALE" then
												Result = 4.5
											end
										elseif SN > "GUARDIANCDVITALITYTONCMR" then
											if SN == "GUARDIANCDWILLTOFINESSE" then
												Result = 1
											end
										else
											Result = 0.12
										end
									elseif SN > "GUARDIANCDWILLTOOUTHEAL" then
										if SN < "GUARDIANCDWILLTOPHYMIT" then
											if SN == "GUARDIANCDWILLTOPHYMAS" then
												Result = 1
											end
										elseif SN > "GUARDIANCDWILLTOPHYMIT" then
											if SN == "GUARDIANCDWILLTORESIST" then
												Result = 1
											end
										else
											Result = 1.5
										end
									else
										Result = 1
									end
								else
									Result = 0.012
								end
							elseif SN > "GUARDIANCDWILLTOTACMIT" then
								if SN < "HIGHELFRDPSVTWONAME" then
									if SN < "HELFSORROWUNDYINGWILL" then
										if SN < "HELFPEACEELDARMORALE" then
											if SN == "HELFFADINGFIRSTBORNFATE" then
												Result = -CalcStat("FateT",L,0.4)
											end
										elseif SN > "HELFPEACEELDARMORALE" then
											if SN == "HELFPEACEELDARNCMR" then
												Result = CalcStat("NCMRT",L,0.6)
											end
										else
											Result = CalcStat("MoraleT",L,1.0)
										end
									elseif SN > "HELFSORROWUNDYINGWILL" then
										if SN < "HIGHELFRDPSVONENAME" then
											if SN == "HELFTHOSEWHOREMAINWILL" then
												Result = CalcStat("WillT",L,1.0)
											end
										elseif SN > "HIGHELFRDPSVONENAME" then
											if SN == "HIGHELFRDPSVONEWILL" then
												Result = CalcStat("HElfThoseWhoRemainWill",L)
											end
										else
											Result = "Those Who Remain"
										end
									else
										Result = -CalcStat("WillT",L,0.4)
									end
								elseif SN > "HIGHELFRDPSVTWONAME" then
									if SN < "HIGHELFRDTRAITWILL" then
										if SN < "HIGHELFRDTRAITMORALE" then
											if SN == "HIGHELFRDTRAITFATE" then
												Result = CalcStat("HElfFadingFirstbornFate",L)
											end
										elseif SN > "HIGHELFRDTRAITMORALE" then
											if SN == "HIGHELFRDTRAITNCMR" then
												Result = CalcStat("HElfPeaceEldarNCMR",L)
											end
										else
											Result = CalcStat("HElfPeaceEldarMorale",L)
										end
									elseif SN > "HIGHELFRDTRAITWILL" then
										if SN < "HNTARMOURRENDEVADE" then
											if SN == "HNTARMOURRENDBLOCK" then
												Result = -CalcStat("ShieldBlock",L,CalcStat("Trait23456Choice",N)*0.4)
											end
										elseif SN > "HNTARMOURRENDEVADE" then
											if SN > "HNTARMOURRENDPARRY" then
												if SN == "HNTBREACHFINDERRNGMIT" then
													Result = (-20)*L
												end
											elseif SN == "HNTARMOURRENDPARRY" then
												Result = -CalcStat("ParryT",L,CalcStat("Trait23456Choice",N)*0.4)
											end
										else
											Result = -CalcStat("EvadeT",L,CalcStat("Trait23456Choice",N)*0.4)
										end
									else
										Result = CalcStat("HElfSorrowUndyingWill",L)
									end
								else
									Result = ""
								end
							else
								Result = 1.5
							end
						else
							Result = 3
						end
					else
						Result = CalcStat("CritHitT",L,CalcStat("Trait47101316Choice",N)*0.2)
					end
				else
					Result = CalcStat("BPEPRatP",L,N)
				end
			elseif SN > "HNTCAMPFIRENCMR" then
				if SN < "LOREMASTERCDBASEFATE" then
					if SN < "ICMRC" then
						if SN < "HUNTERCDBASEICPR" then
							if SN < "HOBSMALLSIZEMIGHT" then
								if SN < "HOBBITRDPSVONENAME" then
									if SN < "HNTRAPIDFIREPHYMAS" then
										if SN < "HNTPRECISIONSTANCEFINESSE" then
											if SN == "HNTCAMPFIRENCPR" then
												Result = CalcStat("NCPRT",L,1.2)
											end
										elseif SN > "HNTPRECISIONSTANCEFINESSE" then
											if SN == "HNTPURGEPOISONRESIST" then
												Result = CalcStat("PoisonResistT",L,4)
											end
										else
											Result = CalcStat("FinesseT",L,1.6)
										end
									elseif SN > "HNTRAPIDFIREPHYMAS" then
										if SN < "HNTSTRENGTHSTANCECRITHIT" then
											if SN == "HNTRAPIDFIRESEL" then
												if 1 <= Lp and Lm <= 8 then
													Result = L+2
												elseif 9 <= Lp and Lm <= 10 then
													Result = 2*L-6
												end
											end
										elseif SN > "HNTSTRENGTHSTANCECRITHIT" then
											if SN == "HOBBITRDPSVONEMIGHT" then
												Result = CalcStat("HobHobbitStatureMight",L)
											end
										else
											Result = CalcStat("CritHitT",L,4)
										end
									else
										Result = CalcStat("PhyMasT",L,CalcStat("HntRapidFireSel",N)*0.2)
									end
								elseif SN > "HOBBITRDPSVONENAME" then
									if SN < "HOBBITRDTRAITVITALITY" then
										if SN < "HOBBITRDTRAITMIGHT" then
											if SN == "HOBBITRDPSVTWONAME" then
												Result = ""
											end
										elseif SN > "HOBBITRDTRAITMIGHT" then
											if SN == "HOBBITRDTRAITNCMR" then
												Result = CalcStat("HobRapidRecoveryNCMR",L)
											end
										else
											Result = CalcStat("HobSmallSizeMight",L)
										end
									elseif SN > "HOBBITRDTRAITVITALITY" then
										if SN < "HOBHOBBITTOUGHNVITALITY" then
											if SN == "HOBHOBBITSTATUREMIGHT" then
												Result = CalcStat("MightT",L,1.0)
											end
										elseif SN > "HOBHOBBITTOUGHNVITALITY" then
											if SN == "HOBRAPIDRECOVERYNCMR" then
												Result = CalcStat("NCMRT",L,0.6)
											end
										else
											Result = CalcStat("VitalityT",L,1.0)
										end
									else
										Result = CalcStat("HobHobbitToughnVitality",L)
									end
								else
									Result = "Hobbit-stature"
								end
							elseif SN > "HOBSMALLSIZEMIGHT" then
								if SN < "HUNTERCDAGILITYTOTACMIT" then
									if SN < "HUNTERCDAGILITYTOOUTHEAL" then
										if SN < "HUNTERCDAGILITYTOCRITHIT" then
											if SN == "HOPEMORALEP" then
												if Lm <= 5 then
													Result = DataTableValue({-0.99,-0.97,-0.95,-0.9,-0.85,-0.8,-0.65,-0.6,-0.5,-0.4,-0.3,-0.2,-0.15,-0.1,-0.05,0,0.01,0.02,0.03,0.04,0.05},L+16)
												else
													Result = CalcStat("HopeMoraleP",5)
												end
											end
										elseif SN > "HUNTERCDAGILITYTOCRITHIT" then
											if SN == "HUNTERCDAGILITYTOEVADE" then
												Result = 2
											end
										else
											Result = 1
										end
									elseif SN > "HUNTERCDAGILITYTOOUTHEAL" then
										if SN < "HUNTERCDAGILITYTOPHYMAS" then
											if SN == "HUNTERCDAGILITYTOPARRY" then
												Result = 1
											end
										elseif SN > "HUNTERCDAGILITYTOPHYMAS" then
											if SN == "HUNTERCDAGILITYTOPHYMIT" then
												Result = 1
											end
										else
											Result = 3
										end
									else
										Result = 3
									end
								elseif SN > "HUNTERCDAGILITYTOTACMIT" then
									if SN < "HUNTERCDARMOURTYPE" then
										if SN < "HUNTERCDARMOURTONONPHYMIT" then
											if SN == "HUNTERCDARMOURTOCOMPHYMIT" then
												Result = 1
											end
										elseif SN > "HUNTERCDARMOURTONONPHYMIT" then
											if SN == "HUNTERCDARMOURTOTACMIT" then
												Result = 0.2
											end
										else
											Result = 0.2
										end
									elseif SN > "HUNTERCDARMOURTYPE" then
										if SN < "HUNTERCDBASEFATE" then
											if SN == "HUNTERCDBASEAGILITY" then
												Result = CalcStat("ClassBaseAgilityH",L)
											end
										elseif SN > "HUNTERCDBASEFATE" then
											if SN == "HUNTERCDBASEICMR" then
												Result = CalcStat("ClassBaseICMRM",L)
											end
										else
											Result = CalcStat("ClassBaseFate",L)
										end
									else
										Result = 2
									end
								else
									Result = 1
								end
							else
								Result = -CalcStat("MightT",L,0.4)
							end
						elseif SN > "HUNTERCDBASEICPR" then
							if SN < "HUNTERCDMIGHTTOFINESSE" then
								if SN < "HUNTERCDCALCTYPECOMPHYMIT" then
									if SN < "HUNTERCDBASENCPR" then
										if SN < "HUNTERCDBASEMORALE" then
											if SN == "HUNTERCDBASEMIGHT" then
												Result = CalcStat("ClassBaseMightM",L)
											end
										elseif SN > "HUNTERCDBASEMORALE" then
											if SN == "HUNTERCDBASENCMR" then
												Result = CalcStat("ClassBaseNCMRM",L)
											end
										else
											Result = CalcStat("ClassBaseMorale",L)
										end
									elseif SN > "HUNTERCDBASENCPR" then
										if SN < "HUNTERCDBASEVITALITY" then
											if SN == "HUNTERCDBASEPOWER" then
												Result = CalcStat("ClassBasePower",L)
											end
										elseif SN > "HUNTERCDBASEVITALITY" then
											if SN == "HUNTERCDBASEWILL" then
												Result = CalcStat("ClassBaseWillL",L)
											end
										else
											Result = CalcStat("ClassBaseVitality",L)
										end
									else
										Result = CalcStat("ClassBaseNCPR",L)
									end
								elseif SN > "HUNTERCDCALCTYPECOMPHYMIT" then
									if SN < "HUNTERCDFATETOPOWER" then
										if SN < "HUNTERCDCALCTYPETACMIT" then
											if SN == "HUNTERCDCALCTYPENONPHYMIT" then
												Result = 13
											end
										elseif SN > "HUNTERCDCALCTYPETACMIT" then
											if SN == "HUNTERCDFATETONCPR" then
												Result = 0.07
											end
										else
											Result = 26
										end
									elseif SN > "HUNTERCDFATETOPOWER" then
										if SN < "HUNTERCDMIGHTTOCRITHIT" then
											if SN == "HUNTERCDHASPOWER" then
												Result = 1
											end
										elseif SN > "HUNTERCDMIGHTTOCRITHIT" then
											if SN == "HUNTERCDMIGHTTOEVADE" then
												Result = 1
											end
										else
											Result = 1.5
										end
									else
										Result = 1
									end
								else
									Result = 13
								end
							elseif SN > "HUNTERCDMIGHTTOFINESSE" then
								if SN < "HUNTERCDVITALITYTONCMR" then
									if SN < "HUNTERCDPHYMITTONONPHYMIT" then
										if SN < "HUNTERCDMIGHTTOPHYMAS" then
											if SN == "HUNTERCDMIGHTTOOUTHEAL" then
												Result = 2
											end
										elseif SN > "HUNTERCDMIGHTTOPHYMAS" then
											if SN == "HUNTERCDPHYMITTOCOMPHYMIT" then
												Result = 1
											end
										else
											Result = 2
										end
									elseif SN > "HUNTERCDPHYMITTONONPHYMIT" then
										if SN < "HUNTERCDVITALITYTOICMR" then
											if SN == "HUNTERCDTACMASTOOUTHEAL" then
												Result = 1
											end
										elseif SN > "HUNTERCDVITALITYTOICMR" then
											if SN == "HUNTERCDVITALITYTOMORALE" then
												Result = 4.5
											end
										else
											Result = 0.012
										end
									else
										Result = 1
									end
								elseif SN > "HUNTERCDVITALITYTONCMR" then
									if SN < "HUNTERCDWILLTOPHYMAS" then
										if SN < "HUNTERCDWILLTOFINESSE" then
											if SN == "HUNTERCDWILLTOCRITHIT" then
												Result = 0.5
											end
										elseif SN > "HUNTERCDWILLTOFINESSE" then
											if SN == "HUNTERCDWILLTOOUTHEAL" then
												Result = 2
											end
										else
											Result = 1.5
										end
									elseif SN > "HUNTERCDWILLTOPHYMAS" then
										if SN < "HUNTERCDWILLTORESIST" then
											if SN == "HUNTERCDWILLTOPHYMIT" then
												Result = 1
											end
										elseif SN > "HUNTERCDWILLTORESIST" then
											if SN == "ICMR" then
												Result = EquSng(StatLinInter("PntMPICMR","ItemPntSVital","ProgBICMR","",L,N,1))
											end
										else
											Result = 1
										end
									else
										Result = 2
									end
								else
									Result = 0.12
								end
							else
								Result = 1.5
							end
						else
							Result = CalcStat("ClassBaseICPR",L)
						end
					elseif SN > "ICMRC" then
						if SN < "ITEMPNTS" then
							if SN < "INDMGPRATPA" then
								if SN < "ICPRC" then
									if SN < "ICMRCRAW" then
										if SN < "ICMRCILVLFILTER" then
											if SN == "ICMRCI" then
												Result = RoundDblLotro(CalcStat("ICMRCIRaw",L,N))
											end
										elseif SN > "ICMRCILVLFILTER" then
											if SN == "ICMRCIRAW" then
												Result = StatLinInter("PntMPICMRC","ItemPntS","ProgBICMR","AdjCreepItem",L,N,4)
											end
										else
											if 0 <= Lp and Lm <= 0 then
												Result = 515
											else
												Result = CalcStat("CreepILvlCurr",L)
											end
										end
									elseif SN > "ICMRCRAW" then
										if SN < "ICMRT" then
											if SN == "ICMRDEBUFFT" then
												Result = EquSng(StatLinInter("PntMPICMRDebuffT","TraitPntSVital","ProgBICMR","",L,N,99))
											end
										elseif SN > "ICMRT" then
											if SN == "ICPR" then
												Result = EquSng(StatLinInter("PntMPICPR","ItemPntSVital","ProgBICPR","",L,N,99))
											end
										else
											Result = EquSng(StatLinInter("PntMPICMR","TraitPntSVital","ProgBICMR","",L,N,1))
										end
									else
										Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("ICMRCIRaw",CalcStat("ICMRCILvlFilter",N),N),99)
									end
								elseif SN > "ICPRC" then
									if SN < "ICPRCRAW" then
										if SN < "ICPRCILVLFILTER" then
											if SN == "ICPRCI" then
												Result = RoundDblLotro(CalcStat("ICPRCIRaw",L,N))
											end
										elseif SN > "ICPRCILVLFILTER" then
											if SN == "ICPRCIRAW" then
												Result = StatLinInter("PntMPICPRC","ItemPntS","ProgBICPR","AdjCreepItemPower",L,N,4)
											end
										else
											if 0 <= Lp and Lm <= 0 then
												Result = 515
											else
												Result = CalcStat("CreepILvlCurr",L)
											end
										end
									elseif SN > "ICPRCRAW" then
										if SN < "INDMGPPRAT" then
											if SN == "ICPRT" then
												Result = EquSng(StatLinInter("PntMPICPR","TraitPntSVital","ProgBICPR","",L,N,99))
											end
										elseif SN > "INDMGPPRAT" then
											if SN == "INDMGPRATP" then
												Result = CalcPercAB(CalcStat("InDmgPRatPA",L),CalcStat("InDmgPRatPB",L),CalcStat("InDmgPRatPCap",L),N)
											end
										else
											Result = CalcRatAB(CalcStat("InDmgPRatPA",L),CalcStat("InDmgPRatPB",L),CalcStat("InDmgPRatPCapR",L),N)
										end
									else
										Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("ICPRCIRaw",CalcStat("ICPRCILvlFilter",N),N),99)
									end
								else
									Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("ICPRCI",CalcStat("ICPRCILvlFilter",N),N),0)
								end
							elseif SN > "INDMGPRATPA" then
								if SN < "INHEALPRATPA" then
									if SN < "INDMGPRATPCAPR" then
										if SN < "INDMGPRATPC" then
											if SN == "INDMGPRATPB" then
												Result = CalcStat("BRatRounded",L,"BRatStandard")
											end
										elseif SN > "INDMGPRATPC" then
											if SN == "INDMGPRATPCAP" then
												Result = 400
											end
										else
											Result = 0.5
										end
									elseif SN > "INDMGPRATPCAPR" then
										if SN < "INHEALPPRAT" then
											if SN == "INHEAL" then
												Result = EquSng(StatLinInter("PntMPInHeal","ItemPntS","ProgBInHeal","AdjItem",L,N,0))
											end
										elseif SN > "INHEALPPRAT" then
											if SN == "INHEALPRATP" then
												Result = CalcPercAB(CalcStat("InHealPRatPA",L),CalcStat("InHealPRatPB",L),CalcStat("InHealPRatPCap",L),N)
											end
										else
											Result = CalcRatAB(CalcStat("InHealPRatPA",L),CalcStat("InHealPRatPB",L),CalcStat("InHealPRatPCapR",L),N)
										end
									else
										Result = CalcStat("InDmgPRatPB",L)*CalcStat("InDmgPRatPC",L)
									end
								elseif SN > "INHEALPRATPA" then
									if SN < "INHEALPRATPCAPR" then
										if SN < "INHEALPRATPC" then
											if SN == "INHEALPRATPB" then
												Result = CalcStat("BRatRounded",L,"BRatStandard")
											end
										elseif SN > "INHEALPRATPC" then
											if SN == "INHEALPRATPCAP" then
												Result = 25
											end
										else
											Result = 0.5
										end
									elseif SN > "INHEALPRATPCAPR" then
										if SN < "INSTRMORALE" then
											if SN == "INHEALT" then
												Result = EquSng(StatLinInter("PntMPInHeal","TraitPntS","ProgBInHeal","AdjTrait",L,N,0))
											end
										elseif SN > "INSTRMORALE" then
											if SN == "INSTRPOWER" then
												if Lm <= 9 then
													Result = RoundDbl(0.95*L+12.6)
												elseif Lm <= 18 then
													Result = RoundDbl(1.95*L+3)
												elseif Lm <= 26 then
													Result = RoundDbl(2.95*L-15.55)
												elseif Lm <= 35 then
													Result = RoundDbl(3.95*L-42.15)
												elseif Lm <= 42 then
													Result = RoundDbl(4.95*L-77.7)
												elseif Lm <= 45 then
													Result = RoundDbl(5.95*L-120.35)
												elseif Lm <= 105 then
													Result = RoundDbl(6*L-124)
												else
													Result = CalcStat("ProgExtMpExpRnd",L,CalcStat("InstrPower",105))
												end
											end
										else
											if Lm <= 105 then
												Result = RoundDbl(4.04*L)
											else
												Result = CalcStat("ProgExtLowExpRnd",L,CalcStat("InstrMorale",105))
											end
										end
									else
										Result = CalcStat("InHealPRatPB",L)*CalcStat("InHealPRatPC",L)
									end
								else
									Result = 75
								end
							else
								Result = 1200
							end
						elseif SN > "ITEMPNTS" then
							if SN < "LMHEARTYDIETMORALE" then
								if SN < "LI2REFORGECOST" then
									if SN < "ITEMPNTSVITAL" then
										if SN < "ITEMPNTSVIRTUEMASTERY" then
											if SN == "ITEMPNTSCLASSIC" then
												Result = {{1,25,50,60,79,80,200,225,300,349,350,399,400,449,450,499,500,549,550,599},{1,25,50,60,75,76,100,105,106,115,116,120,121,130,131,140,141,150,151,160}}
											end
										elseif SN > "ITEMPNTSVIRTUEMASTERY" then
											if SN == "ITEMPNTSVIRTUEMORALE" then
												Result = {{0,1,2,50,80,200,225,300,349,350,399,400,449,450,499,500,549,550,599},{0,1,2,50,76,100,105,106,115,116,120,121,130,131,140,141,150,151,160}}
											end
										else
											Result = {{0,1,25,50,79,80,200,225,300,349,399,400,449,450,499,500,549,550,599},{0,1,25,50,75,76,100,105,106,115,116,121,130,131,140,141,150,151,160}}
										end
									elseif SN > "ITEMPNTSVITAL" then
										if SN < "LEVELCAP" then
											if SN == "L" then
												Result = L
											end
										elseif SN > "LEVELCAP" then
											if SN == "LI2ILVLCAP" then
												Result = 530
											end
										else
											Result = 150
										end
									else
										Result = {{1,25,50,60,79,80,200,225,300,349,350,399,400,449,450,499,500,549,550,599},{1,25,50,60,75,76,100,105,106,115,116,120,121,130,131,140,141,150,151,160}}
									end
								elseif SN > "LI2REFORGECOST" then
									if SN < "LIGHTMITT" then
										if SN < "LI2REFORGEILVL" then
											if SN == "LI2REFORGECOSTSEG" then
												if Lm <= 0 then
													Result = 0
												elseif 1 <= Lp and Lm <= 12 then
													Result = DataTableValue({1,1.2,1.4,1.7,2.1,2.5,3,3.6,4.3,5.1,6.4,7.5},L)
												elseif Lm <= 22 then
													Result = LinFmod(1,8,35,13,22,L)
												elseif Lm <= 41 then
													Result = LinFmod(1,35.7,48.3,23,41,L)
												elseif Lm <= 43 then
													Result = LinFmod(1,50,60,42,43,L)
												elseif Lm <= 48 then
													Result = RoundDbl(LinFmod(1,62.6,77,44,48,L))
												elseif Lm <= 53 then
													Result = RoundDbl(LinFmod(1,80,99,49,53,L))
												elseif Lm <= 55 then
													Result = LinFmod(1,103.5,109,54,55,L)
												elseif Lm <= 61 then
													Result = RoundDbl(LinFmod(1,113.6,145,56,61,L))
												elseif Lm <= 120 then
													Result = LinFmod(1,153,849,62,120,L)
												elseif Lm <= 130 then
													Result = LinFmod(1,855,909,121,130,L)
												else
													Result = LinFmod(1,914,1009,131,150,L)
												end
											end
										elseif SN > "LI2REFORGEILVL" then
											if SN == "LIGHTMIT" then
												Result = CalcStat("DmgTypeMit",L,N)
											end
										else
											if Lm <= 145 then
												Result = CalcStat("AwardILvlI",L)
											else
												Result = N
											end
										end
									elseif SN > "LIGHTMITT" then
										if SN < "LIGHTNINGMITT" then
											if SN == "LIGHTNINGMIT" then
												Result = CalcStat("DmgTypeMit",L,N)
											end
										elseif SN > "LIGHTNINGMITT" then
											if SN == "LMANCIENTWISDOMWILL" then
												if Lm <= 105 then
													Result = RoundDbl(1.1*L)
												else
													Result = CalcStat("ProgExtLowExpRnd",L,CalcStat("LmAncientWisdomWill",105))
												end
											end
										else
											Result = CalcStat("DmgTypeMitT",L,N)
										end
									else
										Result = CalcStat("DmgTypeMitT",L,N)
									end
								else
									Result = RoundDbl(CalcStat("Li2ReforgeCostSeg",L)*(L+9)*12.5)
								end
							elseif SN > "LMHEARTYDIETMORALE" then
								if SN < "LOREMASTERCDAGILITYTOCRITHIT" then
									if SN < "LMSWSTAFFBUGPARRY" then
										if SN < "LMPREPFORWARTACMAS" then
											if SN == "LMHEARTYDIETMORALECHOICE" then
												if 1 <= Lp and Lm <= 6 then
													Result = DataTableValue({0.4,1,1.6,2.4,3.2,3.2},L)
												end
											end
										elseif SN > "LMPREPFORWARTACMAS" then
											if SN == "LMSWSTAFFBUGMORALE" then
												if Lm <= 105 then
													Result = RoundDbl(LinFmod(1,16.2,696.9,1,105,L))
												else
													Result = CalcStat("ProgExtLowExpRnd",L,CalcStat("LmSwStaffBugMorale",105))
												end
											end
										else
											Result = CalcStat("TacMasT",L,CalcStat("Trait12345Choice",N)*0.4)
										end
									elseif SN > "LMSWSTAFFBUGPARRY" then
										if SN < "LOE" then
											if SN == "LMSWSTAFFBUGPARRYOLD" then
												if Lm <= 105 then
													Result = RoundDbl(44.44*L)
												else
													Result = CalcStat("ProgExtHighLinExpRnd",L,CalcStat("LmSwStaffBugParryOld",105))
												end
											end
										elseif SN > "LOE" then
											if SN == "LOEPASSIVE" then
												if 116 <= Lp and Lm <= 119 then
													Result = 20*L-2300
												elseif 120 <= Lp then
													Result = CalcStat("LoEPassive",119)
												end
											end
										else
											Result = 2*N
										end
									else
										if Lm <= 140 then
											Result = CalcStat("U371LegacyStatFix",L,"LmSwStaffBugParryOld")
										else
											Result = CalcStat("LMSwStaffBugParry",140)
										end
									end
								elseif SN > "LOREMASTERCDAGILITYTOCRITHIT" then
									if SN < "LOREMASTERCDARMOURTOCOMPHYMIT" then
										if SN < "LOREMASTERCDAGILITYTOFINESSE" then
											if SN == "LOREMASTERCDAGILITYTOEVADE" then
												Result = 1
											end
										elseif SN > "LOREMASTERCDAGILITYTOFINESSE" then
											if SN == "LOREMASTERCDAGILITYTOTACMAS" then
												Result = 2
											end
										else
											Result = 1
										end
									elseif SN > "LOREMASTERCDARMOURTOCOMPHYMIT" then
										if SN < "LOREMASTERCDARMOURTOTACMIT" then
											if SN == "LOREMASTERCDARMOURTONONPHYMIT" then
												Result = 0.2
											end
										elseif SN > "LOREMASTERCDARMOURTOTACMIT" then
											if SN > "LOREMASTERCDARMOURTYPE" then
												if SN == "LOREMASTERCDBASEAGILITY" then
													Result = CalcStat("ClassBaseAgilityL",L)
												end
											elseif SN == "LOREMASTERCDARMOURTYPE" then
												Result = 1
											end
										else
											Result = 0.2
										end
									else
										Result = 1
									end
								else
									Result = 2
								end
							else
								Result = CalcStat("Morale",L,CalcStat("LmHeartyDietMoraleChoice",N))
							end
						else
							Result = {{1,25,50,79,80,200,225,300,349,350,399,400,449,450,499,500,549,550,599},{1,25,50,75,76,100,105,106,115,116,120,121,130,131,140,141,150,151,160}}
						end
					else
						Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("ICMRCI",CalcStat("ICMRCILvlFilter",N),N),0)
					end
				elseif SN > "LOREMASTERCDBASEFATE" then
					if SN < "MARINERCDAGILITYTOPHYMAS" then
						if SN < "LVLBONUSMORRES" then
							if SN < "LOREMASTERCDMIGHTTOCRITHIT" then
								if SN < "LOREMASTERCDBASEVITALITY" then
									if SN < "LOREMASTERCDBASEMORALE" then
										if SN < "LOREMASTERCDBASEICPR" then
											if SN == "LOREMASTERCDBASEICMR" then
												Result = CalcStat("ClassBaseICMRL",L)
											end
										elseif SN > "LOREMASTERCDBASEICPR" then
											if SN == "LOREMASTERCDBASEMIGHT" then
												Result = CalcStat("ClassBaseMightM",L)
											end
										else
											Result = CalcStat("ClassBaseICPR",L)
										end
									elseif SN > "LOREMASTERCDBASEMORALE" then
										if SN < "LOREMASTERCDBASENCPR" then
											if SN == "LOREMASTERCDBASENCMR" then
												Result = CalcStat("ClassBaseNCMRL",L)
											end
										elseif SN > "LOREMASTERCDBASENCPR" then
											if SN == "LOREMASTERCDBASEPOWER" then
												Result = CalcStat("ClassBasePower",L)
											end
										else
											Result = CalcStat("ClassBaseNCPR",L)
										end
									else
										Result = CalcStat("ClassBaseMorale",L)
									end
								elseif SN > "LOREMASTERCDBASEVITALITY" then
									if SN < "LOREMASTERCDCALCTYPETACMIT" then
										if SN < "LOREMASTERCDCALCTYPECOMPHYMIT" then
											if SN == "LOREMASTERCDBASEWILL" then
												Result = CalcStat("ClassBaseWillH",L)
											end
										elseif SN > "LOREMASTERCDCALCTYPECOMPHYMIT" then
											if SN == "LOREMASTERCDCALCTYPENONPHYMIT" then
												Result = 12
											end
										else
											Result = 12
										end
									elseif SN > "LOREMASTERCDCALCTYPETACMIT" then
										if SN < "LOREMASTERCDFATETOPOWER" then
											if SN == "LOREMASTERCDFATETONCPR" then
												Result = 0.07
											end
										elseif SN > "LOREMASTERCDFATETOPOWER" then
											if SN == "LOREMASTERCDHASPOWER" then
												Result = 1
											end
										else
											Result = 1
										end
									else
										Result = 25
									end
								else
									Result = CalcStat("ClassBaseVitality",L)
								end
							elseif SN > "LOREMASTERCDMIGHTTOCRITHIT" then
								if SN < "LOREMASTERCDVITALITYTOMORALE" then
									if SN < "LOREMASTERCDPHYMITTOCOMPHYMIT" then
										if SN < "LOREMASTERCDMIGHTTOPARRY" then
											if SN == "LOREMASTERCDMIGHTTOFINESSE" then
												Result = 1.5
											end
										elseif SN > "LOREMASTERCDMIGHTTOPARRY" then
											if SN == "LOREMASTERCDMIGHTTOTACMAS" then
												Result = 2
											end
										else
											Result = 1
										end
									elseif SN > "LOREMASTERCDPHYMITTOCOMPHYMIT" then
										if SN < "LOREMASTERCDTACMASTOOUTHEAL" then
											if SN == "LOREMASTERCDPHYMITTONONPHYMIT" then
												Result = 1
											end
										elseif SN > "LOREMASTERCDTACMASTOOUTHEAL" then
											if SN == "LOREMASTERCDVITALITYTOICMR" then
												Result = 0.012
											end
										else
											Result = 1
										end
									else
										Result = 1
									end
								elseif SN > "LOREMASTERCDVITALITYTOMORALE" then
									if SN < "LOREMASTERCDWILLTOPHYMIT" then
										if SN < "LOREMASTERCDWILLTOCRITHIT" then
											if SN == "LOREMASTERCDVITALITYTONCMR" then
												Result = 0.12
											end
										elseif SN > "LOREMASTERCDWILLTOCRITHIT" then
											if SN == "LOREMASTERCDWILLTOEVADE" then
												Result = 2
											end
										else
											Result = 1
										end
									elseif SN > "LOREMASTERCDWILLTOPHYMIT" then
										if SN < "LOREMASTERCDWILLTOTACMAS" then
											if SN == "LOREMASTERCDWILLTORESIST" then
												Result = 1
											end
										elseif SN > "LOREMASTERCDWILLTOTACMAS" then
											if SN == "LOREMASTERCDWILLTOTACMIT" then
												Result = 1
											end
										else
											Result = 3
										end
									else
										Result = 1
									end
								else
									Result = 4.5
								end
							else
								Result = 1.5
							end
						elseif SN > "LVLBONUSMORRES" then
							if SN < "MANFOURTHAGEWILL" then
								if SN < "MAINC" then
									if SN < "LVLEXPCOST" then
										if SN < "LVLBONUSPOWRES" then
											if SN == "LVLBONUSPHYDMG" then
												Result = EquSng(0.1)
											end
										elseif SN > "LVLBONUSPOWRES" then
											if SN == "LVLBONUSTACDMG" then
												Result = EquSng(0.1)
											end
										else
											Result = CalcStat("SkillPowerCost",L,N)
										end
									elseif SN > "LVLEXPCOST" then
										if SN < "LVLTOILVL" then
											if SN == "LVLEXPCOSTTOT" then
												if 1 <= Lp then
													Result = CalcStat("LvlExpCostTot",L-1)+CalcStat("LvlExpCost",L)
												end
											end
										elseif SN > "LVLTOILVL" then
											if SN == "MAIN" then
												Result = RoundDblDown(StatLinInter("PntMPMain","ItemPntS","ProgBMain","AdjItem",L,N,0))
											end
										else
											if Lm <= 106 then
												Result = LinFmod(1,225,300,105,106,L)
											elseif Lm <= 115 then
												Result = LinFmod(1,300,349,106,115,L)
											elseif Lm <= 116 then
												Result = LinFmod(1,349,350,115,116,L)
											elseif Lm <= 120 then
												Result = LinFmod(1,350,399,116,120,L)
											elseif Lm <= 121 then
												Result = LinFmod(1,399,400,120,121,L)
											elseif Lm <= 130 then
												Result = LinFmod(1,400,449,121,130,L)
											elseif Lm <= 131 then
												Result = LinFmod(1,449,450,130,131,L)
											elseif Lm <= 140 then
												Result = LinFmod(1,450,499,131,140,L)
											elseif Lm <= 141 then
												Result = LinFmod(1,499,500,140,141,L)
											else
												Result = LinFmod(1,500,549,141,150,L)
											end
										end
									else
										if Lm <= 1 then
											Result = 0
										elseif Lm <= 5 then
											Result = RoundDbl(12.5*L*L+12.5666666666667*L+24.8666666666667)
										elseif Lm <= 10 then
											Result = RoundDbl(33.8*L*L-179.48*L+452.6)
										elseif Lm <= 15 then
											Result = RoundDbl(55.05*L*L-583.77*L+2370.5)
										elseif Lm <= 20 then
											Result = RoundDbl(76.2*L*L-1196.96*L+6809)
										elseif Lm <= 25 then
											Result = RoundDbl(97.4*L*L-2023*L+14849.8)
										elseif Lm <= 30 then
											Result = RoundDbl(118.7*L*L-3066.02 *L+27612.8)
										elseif Lm <= 35 then
											Result = RoundDbl(139.95*L*L-4319.23*L+46084.1)
										elseif Lm <= 40 then
											Result = RoundDbl(161.2*L*L-5785.04*L+71356.2)
										elseif Lm <= 45 then
											Result = RoundDbl(182.5*L*L-7467.38*L+104569.8)
										elseif Lm <= 50 then
											Result = RoundDbl(203.8*L*L-9363.48*L+146761.8)
										elseif Lm <= 55 then
											Result = RoundDbl(225.05*L*L-11467.77*L+198851.3)
										elseif Lm <= 60 then
											Result = RoundDbl(246.3*L*L-13784.46*L+261988)
										elseif 61 <= Lp and Lm <= 70 then
											Result = RoundDbl(ExpFmod(CalcStat("LvlExpCost",60),61,5.071,L,nil,3.485))
										elseif 71 <= Lp and Lm <= 75 then
											Result = RoundDbl(ExpFmod(CalcStat("LvlExpCost",70),71,5.072,L,nil,-0.95))
										elseif 76 <= Lp then
											Result = ExpFmod(CalcStat("LvlExpCost",75),76,5,L,0,-0.5)
										end
									end
								elseif SN > "MAINC" then
									if SN < "MAINCRAW" then
										if SN < "MAINCILVLFILTER" then
											if SN == "MAINCI" then
												Result = RoundDblLotro(CalcStat("MainCIRaw",L,N))
											end
										elseif SN > "MAINCILVLFILTER" then
											if SN == "MAINCIRAW" then
												Result = StatLinInter("PntMPMainC","ItemPntS","ProgBMain","AdjCreepItem",L,N,4)
											end
										else
											if -19.5 <= Lp and Lm <= -19.5 or 19.5 <= Lp and Lm <= 19.5 then
												Result = 520
											else
												Result = CalcStat("CreepILvlCurr",L)
											end
										end
									elseif SN > "MAINCRAW" then
										if SN < "MANDIMMANKINDWILL" then
											if SN == "MAINT" then
												Result = RoundDblDown(StatLinInter("PntMPMain","TraitPntS","ProgBMain","AdjTrait",L,N,0))
											end
										elseif SN > "MANDIMMANKINDWILL" then
											if SN == "MANEASILYINSPINHEALP" then
												Result = 5
											end
										else
											Result = -CalcStat("WillT",L,0.4)
										end
									else
										Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("MainCIRaw",CalcStat("MainCILvlFilter",N),N),99)
									end
								else
									Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("MainCI",CalcStat("MainCILvlFilter",N),N),0)
								end
							elseif SN > "MANFOURTHAGEWILL" then
								if SN < "MANRDTRAITFATE" then
									if SN < "MANRDPSVTWOBLOCK" then
										if SN < "MANRDPSVONENAME" then
											if SN == "MANGIFTOFMENFATE" then
												Result = CalcStat("FateT",L,1.0)
											end
										elseif SN > "MANRDPSVONENAME" then
											if SN == "MANRDPSVONEWILL" then
												Result = CalcStat("ManFourthAgeWill",L)
											end
										else
											Result = "Man of the Fourth Age"
										end
									elseif SN > "MANRDPSVTWOBLOCK" then
										if SN < "MANRDPSVTWONAME" then
											if SN == "MANRDPSVTWOEVADE" then
												Result = CalcStat("BalanceOfManEvade",L)
											end
										elseif SN > "MANRDPSVTWONAME" then
											if SN == "MANRDPSVTWOPARRY" then
												Result = CalcStat("BalanceOfManParry",L)
											end
										else
											Result = "Balance of Man"
										end
									else
										Result = CalcStat("BalanceOfManBlock",L)
									end
								elseif SN > "MANRDTRAITFATE" then
									if SN < "MANSTRONGMENMIGHT" then
										if SN < "MANRDTRAITMIGHT" then
											if SN == "MANRDTRAITINHEALP" then
												Result = CalcStat("ManEasilyInspInHealP",L)
											end
										elseif SN > "MANRDTRAITMIGHT" then
											if SN == "MANRDTRAITWILL" then
												Result = CalcStat("ManDimMankindWill",L)
											end
										else
											Result = CalcStat("ManStrongMenMight",L)
										end
									elseif SN > "MANSTRONGMENMIGHT" then
										if SN < "MARINERCDAGILITYTOOUTHEAL" then
											if SN == "MARINERCDAGILITYTOCRITHIT" then
												Result = 1
											end
										elseif SN > "MARINERCDAGILITYTOOUTHEAL" then
											if SN == "MARINERCDAGILITYTOPARRY" then
												Result = 3
											end
										else
											Result = 3
										end
									else
										Result = CalcStat("MightT",L,1.0)
									end
								else
									Result = CalcStat("ManGiftOfMenFate",L)
								end
							else
								Result = CalcStat("WillT",L,1.0)
							end
						else
							Result = EquSng(0.1)
						end
					elseif SN > "MARINERCDAGILITYTOPHYMAS" then
						if SN < "MARINERCDVITALITYTOICMR" then
							if SN < "MARINERCDBASEVITALITY" then
								if SN < "MARINERCDBASEFATE" then
									if SN < "MARINERCDARMOURTONONPHYMIT" then
										if SN < "MARINERCDAGILITYTOTACMIT" then
											if SN == "MARINERCDAGILITYTOPHYMIT" then
												Result = 1
											end
										elseif SN > "MARINERCDAGILITYTOTACMIT" then
											if SN == "MARINERCDARMOURTOCOMPHYMIT" then
												Result = 1
											end
										else
											Result = 1
										end
									elseif SN > "MARINERCDARMOURTONONPHYMIT" then
										if SN < "MARINERCDARMOURTYPE" then
											if SN == "MARINERCDARMOURTOTACMIT" then
												Result = 0.2
											end
										elseif SN > "MARINERCDARMOURTYPE" then
											if SN == "MARINERCDBASEAGILITY" then
												Result = CalcStat("ClassBaseAgilityM",L)
											end
										else
											Result = 2
										end
									else
										Result = 0.2
									end
								elseif SN > "MARINERCDBASEFATE" then
									if SN < "MARINERCDBASEMORALE" then
										if SN < "MARINERCDBASEICPR" then
											if SN == "MARINERCDBASEICMR" then
												Result = CalcStat("ClassBaseICMRL",L)
											end
										elseif SN > "MARINERCDBASEICPR" then
											if SN == "MARINERCDBASEMIGHT" then
												Result = CalcStat("ClassBaseMightM",L)
											end
										else
											Result = CalcStat("ClassBaseICPR",L)
										end
									elseif SN > "MARINERCDBASEMORALE" then
										if SN < "MARINERCDBASENCPR" then
											if SN == "MARINERCDBASENCMR" then
												Result = CalcStat("ClassBaseNCMRL",L)
											end
										elseif SN > "MARINERCDBASENCPR" then
											if SN == "MARINERCDBASEPOWER" then
												Result = CalcStat("ClassBasePower",L)
											end
										else
											Result = CalcStat("ClassBaseNCPR",L)
										end
									else
										Result = CalcStat("ClassBaseMorale",L)
									end
								else
									Result = CalcStat("ClassBaseFate",L)
								end
							elseif SN > "MARINERCDBASEVITALITY" then
								if SN < "MARINERCDMIGHTTOCRITHIT" then
									if SN < "MARINERCDCALCTYPETACMIT" then
										if SN < "MARINERCDCALCTYPECOMPHYMIT" then
											if SN == "MARINERCDBASEWILL" then
												Result = CalcStat("ClassBaseWillM",L)
											end
										elseif SN > "MARINERCDCALCTYPECOMPHYMIT" then
											if SN == "MARINERCDCALCTYPENONPHYMIT" then
												Result = 13
											end
										else
											Result = 13
										end
									elseif SN > "MARINERCDCALCTYPETACMIT" then
										if SN < "MARINERCDFATETOPOWER" then
											if SN == "MARINERCDFATETONCPR" then
												Result = 0.07
											end
										elseif SN > "MARINERCDFATETOPOWER" then
											if SN == "MARINERCDHASPOWER" then
												Result = 1
											end
										else
											Result = 1
										end
									else
										Result = 26
									end
								elseif SN > "MARINERCDMIGHTTOCRITHIT" then
									if SN < "MARINERCDMIGHTTOPHYMAS" then
										if SN < "MARINERCDMIGHTTOOUTHEAL" then
											if SN == "MARINERCDMIGHTTOFINESSE" then
												Result = 1.5
											end
										elseif SN > "MARINERCDMIGHTTOOUTHEAL" then
											if SN == "MARINERCDMIGHTTOPARRY" then
												Result = 1
											end
										else
											Result = 2
										end
									elseif SN > "MARINERCDMIGHTTOPHYMAS" then
										if SN < "MARINERCDPHYMITTONONPHYMIT" then
											if SN == "MARINERCDPHYMITTOCOMPHYMIT" then
												Result = 1
											end
										elseif SN > "MARINERCDPHYMITTONONPHYMIT" then
											if SN == "MARINERCDTACMASTOOUTHEAL" then
												Result = 1
											end
										else
											Result = 1
										end
									else
										Result = 2
									end
								else
									Result = 1.5
								end
							else
								Result = CalcStat("ClassBaseVitality",L)
							end
						elseif SN > "MARINERCDVITALITYTOICMR" then
							if SN < "MASTERYT" then
								if SN < "MARINERCDWILLTORESIST" then
									if SN < "MARINERCDWILLTOFINESSE" then
										if SN < "MARINERCDVITALITYTONCMR" then
											if SN == "MARINERCDVITALITYTOMORALE" then
												Result = 4.5
											end
										elseif SN > "MARINERCDVITALITYTONCMR" then
											if SN == "MARINERCDWILLTOCRITHIT" then
												Result = 0.5
											end
										else
											Result = 0.12
										end
									elseif SN > "MARINERCDWILLTOFINESSE" then
										if SN < "MARINERCDWILLTOPHYMAS" then
											if SN == "MARINERCDWILLTOOUTHEAL" then
												Result = 2
											end
										elseif SN > "MARINERCDWILLTOPHYMAS" then
											if SN == "MARINERCDWILLTOPHYMIT" then
												Result = 1
											end
										else
											Result = 2
										end
									else
										Result = 1.5
									end
								elseif SN > "MARINERCDWILLTORESIST" then
									if SN < "MASTERYCILVLFILTER" then
										if SN < "MASTERYC" then
											if SN == "MASTERY" then
												Result = EquSng(StatLinInter("PntMPMastery","ItemPntS","ProgBMastery","AdjItemMas",L,N,0))
											end
										elseif SN > "MASTERYC" then
											if SN == "MASTERYCI" then
												Result = RoundDblLotro(CalcStat("MasteryCIRaw",L,N))
											end
										else
											Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("MasteryCI",CalcStat("MasteryCILvlFilter",N),N),0)
										end
									elseif SN > "MASTERYCILVLFILTER" then
										if SN < "MASTERYCRAW" then
											if SN == "MASTERYCIRAW" then
												Result = StatLinInter("PntMPMasteryC","ItemPntS","ProgBMastery","AdjCreepItem",L,N,4)
											end
										elseif SN > "MASTERYCRAW" then
											if SN == "MASTERYOLD" then
												Result = CalcStat("Mastery",L,N)
											end
										else
											Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("MasteryCIRaw",CalcStat("MasteryCILvlFilter",N),N),99)
										end
									else
										if 4.6 <= Lp and Lm <= 4.6 or 4.8 <= Lp and Lm <= 4.8 or 7 <= Lp and Lm <= 7 or 9.6 <= Lp and Lm <= 9.6 or 14.4 <= Lp and Lm <= 14.4 then
											Result = 515
										else
											Result = CalcStat("CreepILvlCurr",L)
										end
									end
								else
									Result = 1
								end
							elseif SN > "MASTERYT" then
								if SN < "MINCOURAGERESIST" then
									if SN < "MIGHTCI" then
										if SN < "MIGHT" then
											if SN == "MATHOMLVLTOILVL" then
												Result = CalcStat("AwardLvlToILvl",L)
											end
										elseif SN > "MIGHT" then
											if SN == "MIGHTC" then
												Result = CalcStat("MainC",L,N)
											end
										else
											Result = CalcStat("Main",L,N)
										end
									elseif SN > "MIGHTCI" then
										if SN < "MINCOMPOSURERESIST" then
											if SN == "MIGHTT" then
												Result = CalcStat("MainT",L,N)
											end
										elseif SN > "MINCOMPOSURERESIST" then
											if SN == "MINCOMPOSURETACMIT" then
												Result = CalcStat("TacMitT",L,1.0)
											end
										else
											Result = CalcStat("ResistT",L,1.6)
										end
									else
										Result = CalcStat("MainCI",L,N)
									end
								elseif SN > "MINCOURAGERESIST" then
									if SN < "MINPIERCINGBALFINESSE" then
										if SN < "MINECHOESBATTLERESIST" then
											if SN == "MINECHOESBATTLECRITDEF" then
												Result = -CalcStat("CritDefT",L,2.0)
											end
										elseif SN > "MINECHOESBATTLERESIST" then
											if SN == "MINENDMORALE" then
												Result = CalcStat("MoraleT",L,CalcStat("Trait12345Choice",N)*0.8)
											end
										else
											Result = -CalcStat("SongResistT",L,1.0)
										end
									elseif SN > "MINPIERCINGBALFINESSE" then
										if SN < "MINSTRELCDAGILITYTOEVADE" then
											if SN == "MINSTRELCDAGILITYTOCRITHIT" then
												Result = 2
											end
										elseif SN > "MINSTRELCDAGILITYTOEVADE" then
											if SN > "MINSTRELCDAGILITYTOFINESSE" then
												if SN == "MINSTRELCDAGILITYTOTACMAS" then
													Result = 2
												end
											elseif SN == "MINSTRELCDAGILITYTOFINESSE" then
												Result = 1
											end
										else
											Result = 1
										end
									else
										Result = CalcStat("FinesseT",L,CalcStat("Trait12345Choice",N)*0.4)
									end
								else
									Result = CalcStat("FearResistT",L,1.0)
								end
							else
								Result = EquSng(StatLinInter("PntMPMastery","TraitPntS","ProgBMastery","AdjTraitMas",L,N,0))
							end
						else
							Result = 0.012
						end
					else
						Result = 3
					end
				else
					Result = CalcStat("ClassBaseFate",L)
				end
			else
				Result = CalcStat("NCMRT",L,1.2)
			end
		else
			Result = CalcStat("PhyMasT",L,0.8)
		end
	elseif SN > "MINSTRELCDARMOURTOCOMPHYMIT" then
		if SN < "TACMITHPRATPCAPR" then
			if SN < "PNTMPCLASSBASEICPR" then
				if SN < "PARTBLOCKPRATPCAP" then
					if SN < "MITLIGHTPRATPCAP" then
						if SN < "MINSTRELCDWILLTOBLOCK" then
							if SN < "MINSTRELCDCALCTYPENONPHYMIT" then
								if SN < "MINSTRELCDBASEMIGHT" then
									if SN < "MINSTRELCDBASEAGILITY" then
										if SN < "MINSTRELCDARMOURTOTACMIT" then
											if SN == "MINSTRELCDARMOURTONONPHYMIT" then
												Result = 0.2
											end
										elseif SN > "MINSTRELCDARMOURTOTACMIT" then
											if SN == "MINSTRELCDARMOURTYPE" then
												Result = 1
											end
										else
											Result = 0.2
										end
									elseif SN > "MINSTRELCDBASEAGILITY" then
										if SN < "MINSTRELCDBASEICMR" then
											if SN == "MINSTRELCDBASEFATE" then
												Result = CalcStat("ClassBaseFate",L)
											end
										elseif SN > "MINSTRELCDBASEICMR" then
											if SN == "MINSTRELCDBASEICPR" then
												Result = CalcStat("ClassBaseICPR",L)
											end
										else
											Result = CalcStat("ClassBaseICMRL",L)
										end
									else
										Result = CalcStat("ClassBaseAgilityM",L)
									end
								elseif SN > "MINSTRELCDBASEMIGHT" then
									if SN < "MINSTRELCDBASEPOWER" then
										if SN < "MINSTRELCDBASENCMR" then
											if SN == "MINSTRELCDBASEMORALE" then
												Result = CalcStat("ClassBaseMorale",L)
											end
										elseif SN > "MINSTRELCDBASENCMR" then
											if SN == "MINSTRELCDBASENCPR" then
												Result = CalcStat("ClassBaseNCPR",L)
											end
										else
											Result = CalcStat("ClassBaseNCMRL",L)
										end
									elseif SN > "MINSTRELCDBASEPOWER" then
										if SN < "MINSTRELCDBASEWILL" then
											if SN == "MINSTRELCDBASEVITALITY" then
												Result = CalcStat("ClassBaseVitality",L)
											end
										elseif SN > "MINSTRELCDBASEWILL" then
											if SN == "MINSTRELCDCALCTYPECOMPHYMIT" then
												Result = 12
											end
										else
											Result = CalcStat("ClassBaseWillH",L)
										end
									else
										Result = CalcStat("ClassBasePower",L)
									end
								else
									Result = CalcStat("ClassBaseMightL",L)
								end
							elseif SN > "MINSTRELCDCALCTYPENONPHYMIT" then
								if SN < "MINSTRELCDMIGHTTOTACMAS" then
									if SN < "MINSTRELCDFATETOPOWER" then
										if SN < "MINSTRELCDCANBLOCK" then
											if SN == "MINSTRELCDCALCTYPETACMIT" then
												Result = 25
											end
										elseif SN > "MINSTRELCDCANBLOCK" then
											if SN == "MINSTRELCDFATETONCPR" then
												Result = 0.07
											end
										else
											if 20 <= Lp then
												Result = 1
											end
										end
									elseif SN > "MINSTRELCDFATETOPOWER" then
										if SN < "MINSTRELCDMIGHTTOCRITHIT" then
											if SN == "MINSTRELCDHASPOWER" then
												Result = 1
											end
										elseif SN > "MINSTRELCDMIGHTTOCRITHIT" then
											if SN == "MINSTRELCDMIGHTTOOUTHEAL" then
												Result = 2
											end
										else
											Result = 1
										end
									else
										Result = 1
									end
								elseif SN > "MINSTRELCDMIGHTTOTACMAS" then
									if SN < "MINSTRELCDTACMASTOOUTHEAL" then
										if SN < "MINSTRELCDPHYMITTOCOMPHYMIT" then
											if SN == "MINSTRELCDMIGHTTOTACMIT" then
												Result = 1
											end
										elseif SN > "MINSTRELCDPHYMITTOCOMPHYMIT" then
											if SN == "MINSTRELCDPHYMITTONONPHYMIT" then
												Result = 1
											end
										else
											Result = 1
										end
									elseif SN > "MINSTRELCDTACMASTOOUTHEAL" then
										if SN < "MINSTRELCDVITALITYTOMORALE" then
											if SN == "MINSTRELCDVITALITYTOICMR" then
												Result = 0.012
											end
										elseif SN > "MINSTRELCDVITALITYTOMORALE" then
											if SN == "MINSTRELCDVITALITYTONCMR" then
												Result = 0.12
											end
										else
											Result = 4.5
										end
									else
										Result = 1
									end
								else
									Result = 2
								end
							else
								Result = 12
							end
						elseif SN > "MINSTRELCDWILLTOBLOCK" then
							if SN < "MINTOTRESISTSEL" then
								if SN < "MINTIMEECHOESBATTLERESIST" then
									if SN < "MINSTRELCDWILLTORESIST" then
										if SN < "MINSTRELCDWILLTOEVADE" then
											if SN == "MINSTRELCDWILLTOCRITHIT" then
												Result = 1
											end
										elseif SN > "MINSTRELCDWILLTOEVADE" then
											if SN == "MINSTRELCDWILLTOPHYMIT" then
												Result = 1
											end
										else
											Result = 1
										end
									elseif SN > "MINSTRELCDWILLTORESIST" then
										if SN < "MINSTRELCDWILLTOTACMIT" then
											if SN == "MINSTRELCDWILLTOTACMAS" then
												Result = 3
											end
										elseif SN > "MINSTRELCDWILLTOTACMIT" then
											if SN == "MINTACMAS" then
												Result = CalcStat("TacMasT",L,CalcStat("Trait123455Choice",N)*0.4)
											end
										else
											Result = 1
										end
									else
										Result = 1
									end
								elseif SN > "MINTIMEECHOESBATTLERESIST" then
									if SN < "MINTOTFATESEL" then
										if SN < "MINTOTCRITHITSEL" then
											if SN == "MINTOTCRITHIT" then
												Result = CalcStat("CritHitT",L,CalcStat("MinToTCritHitSel",N))
											end
										elseif SN > "MINTOTCRITHITSEL" then
											if SN == "MINTOTFATE" then
												Result = CalcStat("FateT",L,CalcStat("MinToTFateSel",N))
											end
										else
											if 1 <= Lp and Lm <= 5 then
												Result = DataTableValue({0,0,0,0.4,0.6},L)
											end
										end
									elseif SN > "MINTOTFATESEL" then
										if SN < "MINTOTFINESSESEL" then
											if SN == "MINTOTFINESSE" then
												Result = CalcStat("FinesseT",L,CalcStat("MinToTFinesseSel",N))
											end
										elseif SN > "MINTOTFINESSESEL" then
											if SN == "MINTOTRESIST" then
												Result = CalcStat("ResistT",L,CalcStat("MinToTResistSel",N))
											end
										else
											if 1 <= Lp and Lm <= 5 then
												Result = DataTableValue({0,0,0.2,0.4,0.6},L)
											end
										end
									else
										if 1 <= Lp and Lm <= 5 then
											Result = DataTableValue({0.2,0.3,0.4,0.5,0.6},L)
										end
									end
								else
									Result = -CalcStat("SongResistT",L,0.6)
								end
							elseif SN > "MINTOTRESISTSEL" then
								if SN < "MITHEAVYPRATPCAP" then
									if SN < "MITHEAVYPRATP" then
										if SN < "MINTOTVITALITYSEL" then
											if SN == "MINTOTVITALITY" then
												Result = CalcStat("VitalityT",L,CalcStat("MinToTVitalitySel",N))
											end
										elseif SN > "MINTOTVITALITYSEL" then
											if SN == "MITHEAVYPPRAT" then
												Result = CalcRatAB(CalcStat("MitHeavyPRatPA",L),CalcStat("MitHeavyPRatPB",L),CalcStat("MitHeavyPRatPCapR",L),N)
											end
										else
											if 1 <= Lp and Lm <= 5 then
												Result = DataTableValue({0,0,0,0,0.4},L)
											end
										end
									elseif SN > "MITHEAVYPRATP" then
										if SN < "MITHEAVYPRATPB" then
											if SN == "MITHEAVYPRATPA" then
												Result = 180
											end
										elseif SN > "MITHEAVYPRATPB" then
											if SN == "MITHEAVYPRATPC" then
												Result = 0.5
											end
										else
											Result = CalcStat("BRatRounded",L,"BRatMitHeavy")
										end
									else
										Result = CalcPercAB(CalcStat("MitHeavyPRatPA",L),CalcStat("MitHeavyPRatPB",L),CalcStat("MitHeavyPRatPCap",L),N)
									end
								elseif SN > "MITHEAVYPRATPCAP" then
									if SN < "MITLIGHTPRATP" then
										if SN < "MITIGATION" then
											if SN == "MITHEAVYPRATPCAPR" then
												Result = CalcStat("MitHeavyPRatPB",L)*CalcStat("MitHeavyPRatPC",L)
											end
										elseif SN > "MITIGATION" then
											if SN == "MITLIGHTPPRAT" then
												Result = CalcRatAB(CalcStat("MitLightPRatPA",L),CalcStat("MitLightPRatPB",L),CalcStat("MitLightPRatPCapR",L),N)
											end
										else
											Result = EquSng(StatLinInter("PntMPMitigation","ItemPntS","ProgBMitigation","AdjItemMit",L,N,0))
										end
									elseif SN > "MITLIGHTPRATP" then
										if SN < "MITLIGHTPRATPB" then
											if SN == "MITLIGHTPRATPA" then
												Result = 120
											end
										elseif SN > "MITLIGHTPRATPB" then
											if SN == "MITLIGHTPRATPC" then
												Result = 0.5
											end
										else
											Result = CalcStat("BRatRounded",L,"BRatMitLight")
										end
									else
										Result = CalcPercAB(CalcStat("MitLightPRatPA",L),CalcStat("MitLightPRatPB",L),CalcStat("MitLightPRatPCap",L),N)
									end
								else
									Result = 60
								end
							else
								if 1 <= Lp and Lm <= 5 then
									Result = DataTableValue({0,0.2,0.3,0.4,0.5},L)
								end
							end
						else
							Result = 1
						end
					elseif SN > "MITLIGHTPRATPCAP" then
						if SN < "OUTHEALPRATPC" then
							if SN < "NCPR" then
								if SN < "MITMEDIUMPRATPCAPR" then
									if SN < "MITMEDIUMPRATPA" then
										if SN < "MITMEDIUMPPRAT" then
											if SN == "MITLIGHTPRATPCAPR" then
												Result = CalcStat("MitLightPRatPB",L)*CalcStat("MitLightPRatPC",L)
											end
										elseif SN > "MITMEDIUMPPRAT" then
											if SN == "MITMEDIUMPRATP" then
												Result = CalcPercAB(CalcStat("MitMediumPRatPA",L),CalcStat("MitMediumPRatPB",L),CalcStat("MitMediumPRatPCap",L),N)
											end
										else
											Result = CalcRatAB(CalcStat("MitMediumPRatPA",L),CalcStat("MitMediumPRatPB",L),CalcStat("MitMediumPRatPCapR",L),N)
										end
									elseif SN > "MITMEDIUMPRATPA" then
										if SN < "MITMEDIUMPRATPC" then
											if SN == "MITMEDIUMPRATPB" then
												Result = CalcStat("BRatRounded",L,"BRatMitMedium")
											end
										elseif SN > "MITMEDIUMPRATPC" then
											if SN == "MITMEDIUMPRATPCAP" then
												Result = 50
											end
										else
											Result = 0.5
										end
									else
										Result = 150
									end
								elseif SN > "MITMEDIUMPRATPCAPR" then
									if SN < "MORALETADJ" then
										if SN < "MORALEADJ" then
											if SN == "MORALE" then
												Result = EquSng(StatLinInter("PntMPMorale","ItemPntSVital","ProgBMorale","MoraleAdj",L,N,0))
											end
										elseif SN > "MORALEADJ" then
											if SN == "MORALET" then
												Result = EquSng(StatLinInter("PntMPMorale","TraitPntSVital","ProgBMorale","MoraleTAdj",L,N,0))
											end
										else
											if Lm <= 25 then
												Result = 0.5
											elseif Lm <= 50 then
												Result = 0.6
											elseif Lm <= 60 then
												Result = 0.7
											elseif Lm <= 79 then
												Result = 0.8
											elseif Lm <= 80 then
												Result = 0.9
											else
												Result = 1
											end
										end
									elseif SN > "MORALETADJ" then
										if SN < "NCMR" then
											if SN == "N" then
												Result = N
											end
										elseif SN > "NCMR" then
											if SN == "NCMRT" then
												Result = EquSng(StatLinInter("PntMPNCMR","TraitPntSVital","ProgBNCMR","",L,N,1))
											end
										else
											Result = EquSng(StatLinInter("PntMPNCMR","ItemPntSVital","ProgBNCMR","",L,N,1))
										end
									else
										if Lm <= 25 then
											Result = 0.5
										elseif Lm <= 50 then
											Result = 0.6
										elseif Lm <= 60 then
											Result = 0.7
										elseif Lm <= 65 then
											Result = 0.8
										elseif Lm <= 75 then
											Result = 0.9
										else
											Result = 1
										end
									end
								else
									Result = CalcStat("MitMediumPRatPB",L)*CalcStat("MitMediumPRatPC",L)
								end
							elseif SN > "NCPR" then
								if SN < "OUTDMGPRATPC" then
									if SN < "OUTDMGPPRAT" then
										if SN < "OFFSET" then
											if SN == "NCPRT" then
												Result = EquSng(StatLinInter("PntMPNCPR","TraitPntSVital","ProgBNCPR","",L,N,99))
											end
										elseif SN > "OFFSET" then
											if SN == "ORCMIT" then
												Result = EquSng(StatLinInter("PntMPOrcMit","ItemPntS","ProgBMitigation","AdjItemMit",L,N,0))
											end
										else
											Result = L+N
										end
									elseif SN > "OUTDMGPPRAT" then
										if SN < "OUTDMGPRATPA" then
											if SN == "OUTDMGPRATP" then
												Result = CalcPercAB(CalcStat("OutDmgPRatPA",L),CalcStat("OutDmgPRatPB",L),CalcStat("OutDmgPRatPCap",L),N)
											end
										elseif SN > "OUTDMGPRATPA" then
											if SN == "OUTDMGPRATPB" then
												Result = CalcStat("BRatRounded",L,"BRatExtra")
											end
										else
											Result = 600
										end
									else
										Result = CalcRatAB(CalcStat("OutDmgPRatPA",L),CalcStat("OutDmgPRatPB",L),CalcStat("OutDmgPRatPCapR",L),N)
									end
								elseif SN > "OUTDMGPRATPC" then
									if SN < "OUTHEALPPRAT" then
										if SN < "OUTDMGPRATPCAPR" then
											if SN == "OUTDMGPRATPCAP" then
												Result = 200
											end
										elseif SN > "OUTDMGPRATPCAPR" then
											if SN == "OUTHEAL" then
												Result = EquSng(StatLinInter("PntMPOutHeal","ItemPntS","ProgBOutHeal","AdjItem",L,N,0))
											end
										else
											Result = CalcStat("OutDmgPRatPB",L)*CalcStat("OutDmgPRatPC",L)
										end
									elseif SN > "OUTHEALPPRAT" then
										if SN < "OUTHEALPRATPA" then
											if SN == "OUTHEALPRATP" then
												Result = CalcPercAB(CalcStat("OutHealPRatPA",L),CalcStat("OutHealPRatPB",L),CalcStat("OutHealPRatPCap",L),N)
											end
										elseif SN > "OUTHEALPRATPA" then
											if SN == "OUTHEALPRATPB" then
												Result = CalcStat("BRatRounded",L,"BRatOutHeal")
											end
										else
											Result = 210
										end
									else
										Result = CalcRatAB(CalcStat("OutHealPRatPA",L),CalcStat("OutHealPRatPB",L),CalcStat("OutHealPRatPCapR",L),N)
									end
								else
									Result = 0.5
								end
							else
								Result = EquSng(StatLinInter("PntMPNCPR","ItemPntSClassic","ProgBNCPR","",L,N,99))
							end
						elseif SN > "OUTHEALPRATPC" then
							if SN < "PARRYPRATPCAPR" then
								if SN < "PARRYCRAW" then
									if SN < "PARRY" then
										if SN < "OUTHEALPRATPCAPR" then
											if SN == "OUTHEALPRATPCAP" then
												Result = 70
											end
										elseif SN > "OUTHEALPRATPCAPR" then
											if SN == "OUTHEALT" then
												Result = EquSng(StatLinInter("PntMPOutHeal","TraitPntS","ProgBOutHeal","AdjTrait",L,N,0))
											end
										else
											Result = CalcStat("OutHealPRatPB",L)*CalcStat("OutHealPRatPC",L)
										end
									elseif SN > "PARRY" then
										if SN < "PARRYCI" then
											if SN == "PARRYC" then
												Result = CalcStat("BPEC",L,N)
											end
										elseif SN > "PARRYCI" then
											if SN == "PARRYCIRAW" then
												Result = CalcStat("BPECIRAW",L,N)
											end
										else
											Result = CalcStat("BPECI",L,N)
										end
									else
										Result = CalcStat("BPE",L,N)
									end
								elseif SN > "PARRYCRAW" then
									if SN < "PARRYPRATPA" then
										if SN < "PARRYPPRAT" then
											if SN == "PARRYPBONUS" then
												Result = CalcStat("BPEPBonus",L)
											end
										elseif SN > "PARRYPPRAT" then
											if SN == "PARRYPRATP" then
												Result = CalcStat("BPEPRatP",L,N)
											end
										else
											Result = CalcStat("BPEPPRat",L,N)
										end
									elseif SN > "PARRYPRATPA" then
										if SN < "PARRYPRATPC" then
											if SN == "PARRYPRATPB" then
												Result = CalcStat("BPEPRatPB",L)
											end
										elseif SN > "PARRYPRATPC" then
											if SN == "PARRYPRATPCAP" then
												Result = CalcStat("BPEPRatPCap",L)
											end
										else
											Result = CalcStat("BPEPRatPC",L)
										end
									else
										Result = CalcStat("BPEPRatPA",L)
									end
								else
									Result = CalcStat("BPECRAW",L,N)
								end
							elseif SN > "PARRYPRATPCAPR" then
								if SN < "PARTBLOCKMITPRATPCAP" then
									if SN < "PARTBLOCKMITPRATP" then
										if SN < "PARTBLOCKMITPBONUS" then
											if SN == "PARRYT" then
												Result = CalcStat("BPET",L,N)
											end
										elseif SN > "PARTBLOCKMITPBONUS" then
											if SN == "PARTBLOCKMITPPRAT" then
												Result = CalcStat("PartMitPPRat",L,N)
											end
										else
											Result = CalcStat("PartMitPBonus",L)
										end
									elseif SN > "PARTBLOCKMITPRATP" then
										if SN < "PARTBLOCKMITPRATPB" then
											if SN == "PARTBLOCKMITPRATPA" then
												Result = CalcStat("PartMitPRatPA",L)
											end
										elseif SN > "PARTBLOCKMITPRATPB" then
											if SN == "PARTBLOCKMITPRATPC" then
												Result = CalcStat("PartMitPRatPC",L)
											end
										else
											Result = CalcStat("PartMitPRatPB",L)
										end
									else
										Result = CalcStat("PartMitPRatP",L,N)
									end
								elseif SN > "PARTBLOCKMITPRATPCAP" then
									if SN < "PARTBLOCKPRATP" then
										if SN < "PARTBLOCKPBONUS" then
											if SN == "PARTBLOCKMITPRATPCAPR" then
												Result = CalcStat("PartMitPRatPCapR",L)
											end
										elseif SN > "PARTBLOCKPBONUS" then
											if SN == "PARTBLOCKPPRAT" then
												Result = CalcStat("PartBPEPPRat",L,N)
											end
										else
											Result = CalcStat("PartBPEPBonus",L)
										end
									elseif SN > "PARTBLOCKPRATP" then
										if SN < "PARTBLOCKPRATPB" then
											if SN == "PARTBLOCKPRATPA" then
												Result = CalcStat("PartBPEPRatPA",L)
											end
										elseif SN > "PARTBLOCKPRATPB" then
											if SN == "PARTBLOCKPRATPC" then
												Result = CalcStat("PartBPEPRatPC",L)
											end
										else
											Result = CalcStat("PartBPEPRatPB",L)
										end
									else
										Result = CalcStat("PartBPEPRatP",L,N)
									end
								else
									Result = CalcStat("PartMitPRatPCap",L)
								end
							else
								Result = CalcStat("BPEPRatPCapR",L)
							end
						else
							Result = 0.5
						end
					else
						Result = 40
					end
				elseif SN > "PARTBLOCKPRATPCAP" then
					if SN < "PERKNCMR" then
						if SN < "PARTFINESSEPPRAT" then
							if SN < "PARTEVADEMITPRATPCAPR" then
								if SN < "PARTBPEPRATPCAPR" then
									if SN < "PARTBPEPRATPA" then
										if SN < "PARTBPEPPRAT" then
											if SN == "PARTBLOCKPRATPCAPR" then
												Result = CalcStat("PartBPEPRatPCapR",L)
											end
										elseif SN > "PARTBPEPPRAT" then
											if SN == "PARTBPEPRATP" then
												Result = CalcPercAB(CalcStat("PartBPEPRatPA",L),CalcStat("PartBPEPRatPB",L),CalcStat("PartBPEPRatPCap",L),N)
											end
										else
											Result = CalcRatAB(CalcStat("PartBPEPRatPA",L),CalcStat("PartBPEPRatPB",L),CalcStat("PartBPEPRatPCapR",L),N)
										end
									elseif SN > "PARTBPEPRATPA" then
										if SN < "PARTBPEPRATPC" then
											if SN == "PARTBPEPRATPB" then
												Result = CalcStat("BRatRounded",L,"BRatPartBPE")
											end
										elseif SN > "PARTBPEPRATPC" then
											if SN == "PARTBPEPRATPCAP" then
												Result = 25
											end
										else
											Result = 0.5
										end
									else
										Result = 75
									end
								elseif SN > "PARTBPEPRATPCAPR" then
									if SN < "PARTEVADEMITPRATPA" then
										if SN < "PARTEVADEMITPPRAT" then
											if SN == "PARTEVADEMITPBONUS" then
												Result = CalcStat("PartMitPBonus",L)
											end
										elseif SN > "PARTEVADEMITPPRAT" then
											if SN == "PARTEVADEMITPRATP" then
												Result = CalcStat("PartMitPRatP",L,N)
											end
										else
											Result = CalcStat("PartMitPPRat",L,N)
										end
									elseif SN > "PARTEVADEMITPRATPA" then
										if SN < "PARTEVADEMITPRATPC" then
											if SN == "PARTEVADEMITPRATPB" then
												Result = CalcStat("PartMitPRatPB",L)
											end
										elseif SN > "PARTEVADEMITPRATPC" then
											if SN == "PARTEVADEMITPRATPCAP" then
												Result = CalcStat("PartMitPRatPCap",L)
											end
										else
											Result = CalcStat("PartMitPRatPC",L)
										end
									else
										Result = CalcStat("PartMitPRatPA",L)
									end
								else
									Result = CalcStat("PartBPEPRatPB",L)*CalcStat("PartBPEPRatPC",L)
								end
							elseif SN > "PARTEVADEMITPRATPCAPR" then
								if SN < "PARTEVADEPRATPCAPR" then
									if SN < "PARTEVADEPRATPA" then
										if SN < "PARTEVADEPPRAT" then
											if SN == "PARTEVADEPBONUS" then
												Result = CalcStat("PartBPEPBonus",L)
											end
										elseif SN > "PARTEVADEPPRAT" then
											if SN == "PARTEVADEPRATP" then
												Result = CalcStat("PartBPEPRatP",L,N)
											end
										else
											Result = CalcStat("PartBPEPPRat",L,N)
										end
									elseif SN > "PARTEVADEPRATPA" then
										if SN < "PARTEVADEPRATPC" then
											if SN == "PARTEVADEPRATPB" then
												Result = CalcStat("PartBPEPRatPB",L)
											end
										elseif SN > "PARTEVADEPRATPC" then
											if SN == "PARTEVADEPRATPCAP" then
												Result = CalcStat("PartBPEPRatPCap",L)
											end
										else
											Result = CalcStat("PartBPEPRatPC",L)
										end
									else
										Result = CalcStat("PartBPEPRatPA",L)
									end
								elseif SN > "PARTEVADEPRATPCAPR" then
									if SN < "PARTFINESSEDMGPRATPB" then
										if SN < "PARTFINESSEDMGPRATP" then
											if SN == "PARTFINESSEDMGPPRAT" then
												Result = CalcRatAB(CalcStat("PartFinesseDmgPRatPA",L),CalcStat("PartFinesseDmgPRatPB",L),CalcStat("PartFinesseDmgPRatPCapR",L),N)
											end
										elseif SN > "PARTFINESSEDMGPRATP" then
											if SN == "PARTFINESSEDMGPRATPA" then
												Result = 150
											end
										else
											Result = CalcPercAB(CalcStat("PartFinesseDmgPRatPA",L),CalcStat("PartFinesseDmgPRatPB",L),CalcStat("PartFinesseDmgPRatPCap",L),N)
										end
									elseif SN > "PARTFINESSEDMGPRATPB" then
										if SN < "PARTFINESSEDMGPRATPCAP" then
											if SN == "PARTFINESSEDMGPRATPC" then
												Result = 0.5
											end
										elseif SN > "PARTFINESSEDMGPRATPCAP" then
											if SN == "PARTFINESSEDMGPRATPCAPR" then
												Result = CalcStat("PartFinesseDmgPRatPB",L)*CalcStat("PartFinesseDmgPRatPC",L)
											end
										else
											Result = 50
										end
									else
										Result = CalcStat("BRatRounded",L,"BRatStandard")
									end
								else
									Result = CalcStat("PartBPEPRatPCapR",L)
								end
							else
								Result = CalcStat("PartMitPRatPCapR",L)
							end
						elseif SN > "PARTFINESSEPPRAT" then
							if SN < "PARTPARRYMITPPRAT" then
								if SN < "PARTMITPPRAT" then
									if SN < "PARTFINESSEPRATPC" then
										if SN < "PARTFINESSEPRATPA" then
											if SN == "PARTFINESSEPRATP" then
												Result = CalcPercAB(CalcStat("PartFinessePRatPA",L),CalcStat("PartFinessePRatPB",L),CalcStat("PartFinessePRatPCap",L),N)
											end
										elseif SN > "PARTFINESSEPRATPA" then
											if SN == "PARTFINESSEPRATPB" then
												Result = CalcStat("BRatRounded",L,"BRatStandard")
											end
										else
											Result = 150
										end
									elseif SN > "PARTFINESSEPRATPC" then
										if SN < "PARTFINESSEPRATPCAPR" then
											if SN == "PARTFINESSEPRATPCAP" then
												Result = 50
											end
										elseif SN > "PARTFINESSEPRATPCAPR" then
											if SN == "PARTMITPBONUS" then
												Result = 0.1
											end
										else
											Result = CalcStat("PartFinessePRatPB",L)*CalcStat("PartFinessePRatPC",L)
										end
									else
										Result = 0.5
									end
								elseif SN > "PARTMITPPRAT" then
									if SN < "PARTMITPRATPC" then
										if SN < "PARTMITPRATPA" then
											if SN == "PARTMITPRATP" then
												Result = CalcPercAB(CalcStat("PartMitPRatPA",L),CalcStat("PartMitPRatPB",L),CalcStat("PartMitPRatPCap",L),N)
											end
										elseif SN > "PARTMITPRATPA" then
											if SN == "PARTMITPRATPB" then
												Result = CalcStat("BRatRounded",L,"BRatPartBPE")
											end
										else
											Result = 105
										end
									elseif SN > "PARTMITPRATPC" then
										if SN < "PARTMITPRATPCAPR" then
											if SN == "PARTMITPRATPCAP" then
												Result = 35
											end
										elseif SN > "PARTMITPRATPCAPR" then
											if SN == "PARTPARRYMITPBONUS" then
												Result = CalcStat("PartMitPBonus",L)
											end
										else
											Result = CalcStat("PartMitPRatPB",L)*CalcStat("PartMitPRatPC",L)
										end
									else
										Result = 0.5
									end
								else
									Result = CalcRatAB(CalcStat("PartMitPRatPA",L),CalcStat("PartMitPRatPB",L),CalcStat("PartMitPRatPCapR",L),N)
								end
							elseif SN > "PARTPARRYMITPPRAT" then
								if SN < "PARTPARRYPPRAT" then
									if SN < "PARTPARRYMITPRATPC" then
										if SN < "PARTPARRYMITPRATPA" then
											if SN == "PARTPARRYMITPRATP" then
												Result = CalcStat("PartMitPRatP",L,N)
											end
										elseif SN > "PARTPARRYMITPRATPA" then
											if SN == "PARTPARRYMITPRATPB" then
												Result = CalcStat("PartMitPRatPB",L)
											end
										else
											Result = CalcStat("PartMitPRatPA",L)
										end
									elseif SN > "PARTPARRYMITPRATPC" then
										if SN < "PARTPARRYMITPRATPCAPR" then
											if SN == "PARTPARRYMITPRATPCAP" then
												Result = CalcStat("PartMitPRatPCap",L)
											end
										elseif SN > "PARTPARRYMITPRATPCAPR" then
											if SN == "PARTPARRYPBONUS" then
												Result = CalcStat("PartBPEPBonus",L)
											end
										else
											Result = CalcStat("PartMitPRatPCapR",L)
										end
									else
										Result = CalcStat("PartMitPRatPC",L)
									end
								elseif SN > "PARTPARRYPPRAT" then
									if SN < "PARTPARRYPRATPC" then
										if SN < "PARTPARRYPRATPA" then
											if SN == "PARTPARRYPRATP" then
												Result = CalcStat("PartBPEPRatP",L,N)
											end
										elseif SN > "PARTPARRYPRATPA" then
											if SN == "PARTPARRYPRATPB" then
												Result = CalcStat("PartBPEPRatPB",L)
											end
										else
											Result = CalcStat("PartBPEPRatPA",L)
										end
									elseif SN > "PARTPARRYPRATPC" then
										if SN < "PARTPARRYPRATPCAPR" then
											if SN == "PARTPARRYPRATPCAP" then
												Result = CalcStat("PartBPEPRatPCap",L)
											end
										elseif SN > "PARTPARRYPRATPCAPR" then
											if SN == "PERKMORALE" then
												if 1 <= Lp and Lm <= 4 then
													Result = DataTableValue({10,20,30,40},L)
												end
											end
										else
											Result = CalcStat("PartBPEPRatPCapR",L)
										end
									else
										Result = CalcStat("PartBPEPRatPC",L)
									end
								else
									Result = CalcStat("PartBPEPPRat",L,N)
								end
							else
								Result = CalcStat("PartMitPPRat",L,N)
							end
						else
							Result = CalcRatAB(CalcStat("PartFinessePRatPA",L),CalcStat("PartFinessePRatPB",L),CalcStat("PartFinessePRatPCapR",L),N)
						end
					elseif SN > "PERKNCMR" then
						if SN < "PHYMITHPRATPCAP" then
							if SN < "PHYMASCIRAW" then
								if SN < "PHYDMGPRATPA" then
									if SN < "PERKTACMIT" then
										if SN < "PERKPHYMIT" then
											if SN == "PERKNCPR" then
												Result = CalcStat("FoodNCPRL",L)
											end
										elseif SN > "PERKPHYMIT" then
											if SN == "PERKPOWER" then
												if 1 <= Lp and Lm <= 4 then
													Result = DataTableValue({10,20,30,40},L)
												end
											end
										else
											Result = CalcStat("PhyMitT",L,0.2*N)
										end
									elseif SN > "PERKTACMIT" then
										if SN < "PHYDMGPPRAT" then
											if SN == "PHYDMGPBONUS" then
												Result = CalcStat("OutDmgPBonus",L)
											end
										elseif SN > "PHYDMGPPRAT" then
											if SN == "PHYDMGPRATP" then
												Result = CalcStat("OutDmgPRatP",L,N)
											end
										else
											Result = CalcStat("OutDmgPPRat",L,N)
										end
									else
										Result = CalcStat("TacMitT",L,0.2*N)
									end
								elseif SN > "PHYDMGPRATPA" then
									if SN < "PHYDMGPRATPCAPR" then
										if SN < "PHYDMGPRATPC" then
											if SN == "PHYDMGPRATPB" then
												Result = CalcStat("OutDmgPRatPB",L)
											end
										elseif SN > "PHYDMGPRATPC" then
											if SN == "PHYDMGPRATPCAP" then
												Result = CalcStat("OutDmgPRatPCap",L)
											end
										else
											Result = CalcStat("OutDmgPRatPC",L)
										end
									elseif SN > "PHYDMGPRATPCAPR" then
										if SN < "PHYMASC" then
											if SN == "PHYMAS" then
												Result = CalcStat("Mastery",L,N)
											end
										elseif SN > "PHYMASC" then
											if SN == "PHYMASCI" then
												Result = CalcStat("MasteryCI",L,N)
											end
										else
											Result = CalcStat("MasteryC",L,N)
										end
									else
										Result = CalcStat("OutDmgPRatPCapR",L)
									end
								else
									Result = CalcStat("OutDmgPRatPA",L)
								end
							elseif SN > "PHYMASCIRAW" then
								if SN < "PHYMITCIRAW" then
									if SN < "PHYMIT" then
										if SN < "PHYMASOLD" then
											if SN == "PHYMASCRAW" then
												Result = CalcStat("MasteryCRaw",L,N)
											end
										elseif SN > "PHYMASOLD" then
											if SN == "PHYMAST" then
												Result = CalcStat("MasteryT",L,N)
											end
										else
											Result = CalcStat("Mastery",L,N)
										end
									elseif SN > "PHYMIT" then
										if SN < "PHYMITCI" then
											if SN == "PHYMITC" then
												Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("PhyMitCI",CalcStat("PhyMitCILvlFilter",N),N),0)
											end
										elseif SN > "PHYMITCI" then
											if SN == "PHYMITCILVLFILTER" then
												if 3.8 <= Lp and Lm <= 3.8 or 8.2 <= Lp and Lm <= 8.2 or 14.4 <= Lp and Lm <= 14.4 or 19.1 <= Lp and Lm <= 19.1 or 23.125 <= Lp and Lm <= 23.125 or 26.5 <= Lp and Lm <= 26.5 then
													Result = 515
												else
													Result = CalcStat("CreepILvlCurr",L)
												end
											end
										else
											Result = RoundDblLotro(CalcStat("PhyMitCIRaw",L,N))
										end
									else
										Result = EquSng(StatLinInter("PntMPPhyMit","ItemPntS","ProgBMitigation","AdjItemMit",L,N,0))
									end
								elseif SN > "PHYMITCIRAW" then
									if SN < "PHYMITHPRATP" then
										if SN < "PHYMITHPBONUS" then
											if SN == "PHYMITCRAW" then
												Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("PhyMitCIRaw",CalcStat("PhyMitCILvlFilter",N),N),99)
											end
										elseif SN > "PHYMITHPBONUS" then
											if SN == "PHYMITHPPRAT" then
												Result = CalcStat("MitHeavyPPRat",L,N)
											end
										else
											Result = CalcStat("MitHeavyPBonus",L)
										end
									elseif SN > "PHYMITHPRATP" then
										if SN < "PHYMITHPRATPB" then
											if SN == "PHYMITHPRATPA" then
												Result = CalcStat("MitHeavyPRatPA",L)
											end
										elseif SN > "PHYMITHPRATPB" then
											if SN == "PHYMITHPRATPC" then
												Result = CalcStat("MitHeavyPRatPC",L)
											end
										else
											Result = CalcStat("MitHeavyPRatPB",L)
										end
									else
										Result = CalcStat("MitHeavyPRatP",L,N)
									end
								else
									Result = StatLinInter("PntMPPhyMitC","ItemPntS","ProgBMitigation","AdjCreepItemMit",L,N,4)
								end
							else
								Result = CalcStat("MasteryCIRaw",L,N)
							end
						elseif SN > "PHYMITHPRATPCAP" then
							if SN < "PHYMITMPRATPCAP" then
								if SN < "PHYMITLPRATPCAP" then
									if SN < "PHYMITLPRATP" then
										if SN < "PHYMITLPBONUS" then
											if SN == "PHYMITHPRATPCAPR" then
												Result = CalcStat("MitHeavyPRatPCapR",L)
											end
										elseif SN > "PHYMITLPBONUS" then
											if SN == "PHYMITLPPRAT" then
												Result = CalcStat("MitLightPPRat",L,N)
											end
										else
											Result = CalcStat("MitLightPBonus",L)
										end
									elseif SN > "PHYMITLPRATP" then
										if SN < "PHYMITLPRATPB" then
											if SN == "PHYMITLPRATPA" then
												Result = CalcStat("MitLightPRatPA",L)
											end
										elseif SN > "PHYMITLPRATPB" then
											if SN == "PHYMITLPRATPC" then
												Result = CalcStat("MitLightPRatPC",L)
											end
										else
											Result = CalcStat("MitLightPRatPB",L)
										end
									else
										Result = CalcStat("MitLightPRatP",L,N)
									end
								elseif SN > "PHYMITLPRATPCAP" then
									if SN < "PHYMITMPRATP" then
										if SN < "PHYMITMPBONUS" then
											if SN == "PHYMITLPRATPCAPR" then
												Result = CalcStat("MitLightPRatPCapR",L)
											end
										elseif SN > "PHYMITMPBONUS" then
											if SN == "PHYMITMPPRAT" then
												Result = CalcStat("MitMediumPPRat",L,N)
											end
										else
											Result = CalcStat("MitMediumPBonus",L)
										end
									elseif SN > "PHYMITMPRATP" then
										if SN < "PHYMITMPRATPB" then
											if SN == "PHYMITMPRATPA" then
												Result = CalcStat("MitMediumPRatPA",L)
											end
										elseif SN > "PHYMITMPRATPB" then
											if SN == "PHYMITMPRATPC" then
												Result = CalcStat("MitMediumPRatPC",L)
											end
										else
											Result = CalcStat("MitMediumPRatPB",L)
										end
									else
										Result = CalcStat("MitMediumPRatP",L,N)
									end
								else
									Result = CalcStat("MitLightPRatPCap",L)
								end
							elseif SN > "PHYMITMPRATPCAP" then
								if SN < "PLAYERBASEPHYMAS" then
									if SN < "PHYRESISTT" then
										if SN < "PHYMITT" then
											if SN == "PHYMITMPRATPCAPR" then
												Result = CalcStat("MitMediumPRatPCapR",L)
											end
										elseif SN > "PHYMITT" then
											if SN == "PHYRESIST" then
												Result = CalcStat("ResistAdd",L,N)
											end
										else
											Result = EquSng(StatLinInter("PntMPPhyMit","TraitPntS","ProgBMitigation","AdjTraitMit",L,N,0))
										end
									elseif SN > "PHYRESISTT" then
										if SN < "PLAYERBASEMORALE" then
											if SN == "PLAYERBASEEVADE" then
												Result = 1
											end
										elseif SN > "PLAYERBASEMORALE" then
											if SN == "PLAYERBASEPARRY" then
												Result = 3
											end
										else
											Result = 52.5
										end
									else
										Result = CalcStat("ResistAddT",L,N)
									end
								elseif SN > "PLAYERBASEPHYMAS" then
									if SN < "PNTMPARMOURPENT" then
										if SN < "PNTMPARMOUR" then
											if SN == "PLAYERBASETACMAS" then
												Result = 11.5
											end
										elseif SN > "PNTMPARMOUR" then
											if SN == "PNTMPARMOURC" then
												Result = 20/1200
											end
										else
											Result = 4.4/1200
										end
									elseif SN > "PNTMPARMOURPENT" then
										if SN < "PNTMPARMOURVIRTUES" then
											if SN == "PNTMPARMOURT" then
												Result = 25/1200
											end
										elseif SN > "PNTMPARMOURVIRTUES" then
											if SN > "PNTMPBPE" then
												if SN == "PNTMPBPEC" then
													Result = 20/1200
												end
											elseif SN == "PNTMPBPE" then
												Result = 42/1200
											end
										else
											Result = 24/1200
										end
									else
										Result = 72/1200
									end
								else
									Result = 11.5
								end
							else
								Result = CalcStat("MitMediumPRatPCap",L)
							end
						else
							Result = CalcStat("MitHeavyPRatPCap",L)
						end
					else
						Result = CalcStat("FoodNCMRL",L)
					end
				else
					Result = CalcStat("PartBPEPRatPCap",L)
				end
			elseif SN > "PNTMPCLASSBASEICPR" then
				if SN < "RIVERHOBBITRDTRAITFROSTMITP" then
					if SN < "PROGBINHEAL" then
						if SN < "PNTMPPHYMITC" then
							if SN < "PNTMPICMRDEBUFFT" then
								if SN < "PNTMPDMGTYPEMITT" then
									if SN < "PNTMPCRITDEFC" then
										if SN < "PNTMPCOMBATDAMAGEMOD" then
											if SN == "PNTMPCLASSBASENCPR" then
												Result = 0.5
											end
										elseif SN > "PNTMPCOMBATDAMAGEMOD" then
											if SN == "PNTMPCRITDEF" then
												Result = 40/1200
											end
										else
											Result = 0.5
										end
									elseif SN > "PNTMPCRITDEFC" then
										if SN < "PNTMPCRITHITC" then
											if SN == "PNTMPCRITHIT" then
												Result = 20/1200
											end
										elseif SN > "PNTMPCRITHITC" then
											if SN == "PNTMPDMGTYPEMIT" then
												Result = 24/1200
											end
										else
											Result = 20/1200
										end
									else
										Result = 0.01667
									end
								elseif SN > "PNTMPDMGTYPEMITT" then
									if SN < "PNTMPFINESSET" then
										if SN < "PNTMPFINESSE" then
											if SN == "PNTMPFATE" then
												Result = 2.5
											end
										elseif SN > "PNTMPFINESSE" then
											if SN == "PNTMPFINESSEC" then
												Result = 0.01667
											end
										else
											Result = 40/1200
										end
									elseif SN > "PNTMPFINESSET" then
										if SN < "PNTMPICMR" then
											if SN == "PNTMPFOODRESIST" then
												Result = 30/1200
											end
										elseif SN > "PNTMPICMR" then
											if SN == "PNTMPICMRC" then
												Result = 23.5/1200
											end
										else
											Result = 0.03
										end
									else
										Result = 36/1200
									end
								else
									Result = 60/1200
								end
							elseif SN > "PNTMPICMRDEBUFFT" then
								if SN < "PNTMPMITIGATION" then
									if SN < "PNTMPMAIN" then
										if SN < "PNTMPICPRC" then
											if SN == "PNTMPICPR" then
												Result = 0.125
											end
										elseif SN > "PNTMPICPRC" then
											if SN == "PNTMPINHEAL" then
												Result = 40/1200
											end
										else
											Result = 23.5/1200
										end
									elseif SN > "PNTMPMAIN" then
										if SN < "PNTMPMASTERY" then
											if SN == "PNTMPMAINC" then
												Result = 199.75/1200
											end
										elseif SN > "PNTMPMASTERY" then
											if SN == "PNTMPMASTERYC" then
												Result = 20/1200
											end
										else
											Result = 17/1200
										end
									else
										Result = 0.5
									end
								elseif SN > "PNTMPMITIGATION" then
									if SN < "PNTMPNCPR" then
										if SN < "PNTMPMORALEVIRTUES" then
											if SN == "PNTMPMORALE" then
												Result = 2
											end
										elseif SN > "PNTMPMORALEVIRTUES" then
											if SN == "PNTMPNCMR" then
												Result = 0.3
											end
										else
											Result = 1.5
										end
									elseif SN > "PNTMPNCPR" then
										if SN < "PNTMPOUTHEAL" then
											if SN == "PNTMPORCMIT" then
												Result = 19.2/1200
											end
										elseif SN > "PNTMPOUTHEAL" then
											if SN == "PNTMPPHYMIT" then
												Result = 36/1200
											end
										else
											Result = 30/1200
										end
									else
										Result = 1
									end
								else
									Result = 28/1200
								end
							else
								Result = 0.076
							end
						elseif SN > "PNTMPPHYMITC" then
							if SN < "PROGBARMOUR" then
								if SN < "PNTMPTACMITC" then
									if SN < "PNTMPRESISTC" then
										if SN < "PNTMPPOWERT" then
											if SN == "PNTMPPOWER" then
												Result = 2
											end
										elseif SN > "PNTMPPOWERT" then
											if SN == "PNTMPRESIST" then
												Result = 36/1200
											end
										else
											Result = 1.333
										end
									elseif SN > "PNTMPRESISTC" then
										if SN < "PNTMPTACHPS" then
											if SN == "PNTMPSHIELDBLOCK" then
												Result = 80/1200
											end
										elseif SN > "PNTMPTACHPS" then
											if SN == "PNTMPTACMIT" then
												Result = 36/1200
											end
										else
											Result = 0.175
										end
									else
										Result = 20/1200
									end
								elseif SN > "PNTMPTACMITC" then
									if SN < "POISONRESIST" then
										if SN < "PNTMPVITALITYC" then
											if SN == "PNTMPVITALITY" then
												Result = 0.35
											end
										elseif SN > "PNTMPVITALITYC" then
											if SN == "PNTMPVITALITYT" then
												Result = 0.45
											end
										else
											Result = 398.6/1200
										end
									elseif SN > "POISONRESIST" then
										if SN < "POWER" then
											if SN == "POISONRESISTT" then
												Result = CalcStat("ResistAddT",L,N)
											end
										elseif SN > "POWER" then
											if SN == "POWERT" then
												Result = EquSng(StatLinInter("PntMPPowerT","TraitPntSVital","ProgBPower","",L,N,0))
											end
										else
											Result = EquSng(StatLinInter("PntMPPower","ItemPntSVital","ProgBPower","",L,N,0))
										end
									else
										Result = CalcStat("ResistAdd",L,N)
									end
								else
									Result = 20/1200
								end
							elseif SN > "PROGBARMOUR" then
								if SN < "PROGBDAMAGENOIMP" then
									if SN < "PROGBBPE" then
										if SN < "PROGBARMOURLIGHT" then
											if SN == "PROGBARMOURHEAVY" then
												Result = CalcStat("BRatProgB",L,"BRatMitHeavy")
											end
										elseif SN > "PROGBARMOURLIGHT" then
											if SN == "PROGBARMOURMEDIUM" then
												Result = CalcStat("BRatProgB",L,"BRatMitMedium")
											end
										else
											Result = CalcStat("BRatProgB",L,"BRatMitLight")
										end
									elseif SN > "PROGBBPE" then
										if SN < "PROGBCRITHIT" then
											if SN == "PROGBCRITDEF" then
												Result = CalcStat("BRatProgB",L,"BRatStandard")
											end
										elseif SN > "PROGBCRITHIT" then
											if SN == "PROGBDAMAGE" then
												Result = CalcStat("StdProgDamage",L,2.0)
											end
										else
											Result = CalcStat("BRatProgB",L,"BRatExtra")
										end
									else
										Result = CalcStat("BRatProgB",L,"BRatStandard")
									end
								elseif SN > "PROGBDAMAGENOIMP" then
									if SN < "PROGBFINESSE" then
										if SN < "PROGBENERGY" then
											if SN == "PROGBDAMAGENOIMPADJ" then
												if Lm <= 50 then
													Result = LinFmod(1,1.25,3,1,50,L)
												elseif Lm <= 100 then
													Result = LinFmod(1,3,4.5,50,100,L)
												else
													Result = LinFmod(1,4.5,5,100,140,L)
												end
											end
										elseif SN > "PROGBENERGY" then
											if SN == "PROGBFATE" then
												Result = CalcStat("ProgBEnergy",L)
											end
										else
											Result = CalcStat("StdProgEnergy",L,2.0)
										end
									elseif SN > "PROGBFINESSE" then
										if SN < "PROGBICMR" then
											if SN == "PROGBHEALTH" then
												Result = CalcStat("StdProgHealth",L,4.0)
											end
										elseif SN > "PROGBICMR" then
											if SN == "PROGBICPR" then
												Result = CalcStat("ProgBEnergy",L)
											end
										else
											Result = CalcStat("ProgBHealth",L)
										end
									else
										Result = CalcStat("BRatProgB",L,"BRatStandard")
									end
								else
									Result = StatLinInter("","TraitPntSVital","ProgBDamage","ProgBDamageNoImpAdj",L,N,99)
								end
							else
								Result = CalcStat("BRatProgB",L,"BRatMitMedium")
							end
						else
							Result = 20/1200
						end
					elseif SN > "PROGBINHEAL" then
						if SN < "REPFATEL" then
							if SN < "PROGEXTCOMLOWRND" then
								if SN < "PROGBOUTHEAL" then
									if SN < "PROGBMITIGATION" then
										if SN < "PROGBMAINBASE" then
											if SN == "PROGBMAIN" then
												Result = CalcStat("StdProgRatings",L,1.75)
											end
										elseif SN > "PROGBMAINBASE" then
											if SN == "PROGBMASTERY" then
												Result = CalcStat("BRatProgB",L,"BRatExtra")
											end
										else
											if 141 <= Lp and Lm <= 150 then
												Result = LinFmod(CalcStat("StdProgRatings",140,1.0),1.15,2,141,150,L,"P")
											else
												Result = CalcStat("StdProgRatings",L,1.0)
											end
										end
									elseif SN > "PROGBMITIGATION" then
										if SN < "PROGBNCMR" then
											if SN == "PROGBMORALE" then
												Result = CalcStat("ProgBHealth",L)
											end
										elseif SN > "PROGBNCMR" then
											if SN == "PROGBNCPR" then
												Result = CalcStat("ProgBEnergy",L)
											end
										else
											Result = CalcStat("ProgBHealth",L)
										end
									else
										Result = CalcStat("BRatProgB",L,"BRatMitMedium")
									end
								elseif SN > "PROGBOUTHEAL" then
									if SN < "PROGBVITALITY" then
										if SN < "PROGBRESIST" then
											if SN == "PROGBPOWER" then
												Result = CalcStat("ProgBEnergy",L)
											end
										elseif SN > "PROGBRESIST" then
											if SN == "PROGBTACHPS" then
												Result = CalcStat("ProgBHealth",L)
											end
										else
											Result = CalcStat("BRatProgB",L,"BRatExtra")
										end
									elseif SN > "PROGBVITALITY" then
										if SN < "PROGEXTCOMHIGHRND" then
											if SN == "PROGEXTCOMHIGHRAW" then
												if 121 <= Lp and Lm <= 121 then
													Result = ExpFmod(N,121,20,L,nil)
												elseif 122 <= Lp and Lm <= 125 then
													Result = ExpFmod(CalcStat("ProgExtComHighRaw",121,N),122,5.5,L,nil)
												elseif 126 <= Lp and Lm <= 126 then
													Result = ExpFmod(CalcStat("ProgExtComHighRaw",125,N),126,20,L,nil)
												elseif 127 <= Lp and Lm <= 130 then
													Result = ExpFmod(CalcStat("ProgExtComHighRaw",126,N),127,5.5,L,nil)
												elseif 131 <= Lp and Lm <= 131 then
													Result = ExpFmod(CalcStat("ProgExtComHighRaw",130,N),131,20,L,nil)
												elseif 132 <= Lp and Lm <= 150 then
													Result = ExpFmod(CalcStat("ProgExtComHighRaw",131,N),132,5.5,L,nil)
												elseif 151 <= Lp then
													Result = CalcStat("ProgExtComHighRaw",150,N)
												end
											end
										elseif SN > "PROGEXTCOMHIGHRND" then
											if SN == "PROGEXTCOMLOWRAW" then
												if 116 <= Lp and Lm <= 116 then
													Result = ExpFmod(N,116,20,L,nil)
												elseif 117 <= Lp and Lm <= 120 then
													Result = ExpFmod(CalcStat("ProgExtComLowRaw",116,N),117,5.5,L,nil)
												elseif 121 <= Lp then
													Result = CalcStat("ProgExtComHighRaw",L,CalcStat("ProgExtComLowRaw",120,N))
												end
											end
										else
											if 121 <= Lp and Lm <= 121 then
												Result = ExpFmod(N,121,20,L,0)
											elseif 122 <= Lp and Lm <= 125 then
												Result = ExpFmod(CalcStat("ProgExtComHighRnd",121,N),122,5.5,L,0)
											elseif 126 <= Lp and Lm <= 126 then
												Result = ExpFmod(CalcStat("ProgExtComHighRnd",125,N),126,20,L,0)
											elseif 127 <= Lp and Lm <= 130 then
												Result = ExpFmod(CalcStat("ProgExtComHighRnd",126,N),127,5.5,L,0)
											elseif 131 <= Lp and Lm <= 131 then
												Result = ExpFmod(CalcStat("ProgExtComHighRnd",130,N),131,20,L,0)
											elseif 132 <= Lp and Lm <= 150 then
												Result = ExpFmod(CalcStat("ProgExtComHighRnd",131,N),132,5.5,L,0)
											elseif 151 <= Lp then
												Result = CalcStat("ProgExtComHighRnd",150,N)
											end
										end
									else
										Result = CalcStat("ProgBHealth",L)
									end
								else
									Result = CalcStat("BRatProgB",L,"BRatOutHeal")
								end
							elseif SN > "PROGEXTCOMLOWRND" then
								if SN < "REAVERCDCALCTYPENONPHYMIT" then
									if SN < "PROGEXTMPEXPRND" then
										if SN < "PROGEXTLOWEXPRND" then
											if SN == "PROGEXTHIGHLINEXPRND" then
												if 106 <= Lp and Lm <= 115 then
													Result = LinFmod(N,2,4,106,115,L,-1)
												elseif 116 <= Lp then
													Result = CalcStat("ProgExtComLowRnd",L,CalcStat("ProgExtHighLinExpRnd",115,N))
												end
											end
										elseif SN > "PROGEXTLOWEXPRND" then
											if SN == "PROGEXTMEDEXPRAW" then
												if 106 <= Lp and Lm <= 106 then
													Result = ExpFmod(N,106,10,L,nil)
												elseif 107 <= Lp and Lm <= 115 then
													Result = ExpFmod(CalcStat("ProgExtMedExpRaw",106,N),107,5.5,L,nil)
												elseif 116 <= Lp then
													Result = CalcStat("ProgExtComLowRaw",L,CalcStat("ProgExtMedExpRaw",115,N))
												end
											end
										else
											if 106 <= Lp and Lm <= 115 then
												Result = ExpFmod(N,106,5.5,L,0)
											elseif 116 <= Lp then
												Result = CalcStat("ProgExtComLowRnd",L,CalcStat("ProgExtLowExpRnd",115,N))
											end
										end
									elseif SN > "PROGEXTMPEXPRND" then
										if SN < "REAVERCANBLOCK" then
											if SN == "RACENAME" then
												if 6 <= Lp and Lm <= 6 then
													Result = "Uruk"
												elseif 7 <= Lp and Lm <= 7 then
													Result = "Orc"
												elseif 12 <= Lp and Lm <= 12 then
													Result = "Spider"
												elseif 23 <= Lp and Lm <= 23 then
													Result = "Man"
												elseif 27 <= Lp and Lm <= 27 then
													Result = "Critter"
												elseif 65 <= Lp and Lm <= 65 then
													Result = "Elf"
												elseif 66 <= Lp and Lm <= 66 then
													Result = "Warg"
												elseif 73 <= Lp and Lm <= 73 then
													Result = "Dwarf"
												elseif 81 <= Lp and Lm <= 81 then
													Result = "Hobbit"
												elseif 114 <= Lp and Lm <= 114 then
													Result = "Beorning"
												elseif 117 <= Lp and Lm <= 117 then
													Result = "HighElf"
												elseif 120 <= Lp and Lm <= 120 then
													Result = "StoutAxe"
												elseif 125 <= Lp and Lm <= 125 then
													Result = "RiverHobbit"
												else
													Result = ""
												end
											end
										elseif SN > "REAVERCANBLOCK" then
											if SN == "REAVERCDCALCTYPECOMPHYMIT" then
												Result = 13
											end
										else
											Result = 1
										end
									else
										if 106 <= Lp and Lm <= 114 then
											Result = ExpFmod(N,106,7.5,L,0)
										elseif 115 <= Lp and Lm <= 115 then
											Result = 2*N
										elseif 116 <= Lp and Lm <= 119 then
											Result = ExpFmod(CalcStat("ProgExtMpExpRnd",115,N),116,25,L,0)
										elseif 120 <= Lp and Lm <= 120 then
											Result = RoundDbl((16/3)*N)
										elseif 121 <= Lp then
											Result = CalcStat("ProgExtComHighRnd",L,CalcStat("ProgExtMpExpRnd",120,N))
										end
									end
								elseif SN > "REAVERCDCALCTYPENONPHYMIT" then
									if SN < "REPAGILITYL" then
										if SN < "REAVERCDHASPOWER" then
											if SN == "REAVERCDCALCTYPETACMIT" then
												Result = 27
											end
										elseif SN > "REAVERCDHASPOWER" then
											if SN == "REPAGILITYH" then
												Result = CalcStat("RepMainH",L)
											end
										else
											Result = 1
										end
									elseif SN > "REPAGILITYL" then
										if SN < "REPCRITHIT" then
											if SN == "REPCRITDEF" then
												if Lm <= 50 then
													Result = LinFmod(1,900,1488,1,50,L)
												elseif Lm <= 85 then
													Result = LinFmod(1,1488,1908,50,85,L)
												elseif Lm <= 105 then
													Result = LinFmod(1,1908,2148,85,105,L)
												else
													Result = LinFmod(1,2148,2328,105,120,L)
												end
											end
										elseif SN > "REPCRITHIT" then
											if SN == "REPFATEH" then
												Result = CalcStat("RepMainH",L)
											end
										else
											if Lm <= 50 then
												Result = LinFmod(1,300,496,1,50,L)
											elseif Lm <= 85 then
												Result = LinFmod(1,496,636,50,85,L)
											elseif Lm <= 105 then
												Result = LinFmod(1,636,716,85,105,L)
											else
												Result = LinFmod(1,716,776,105,120,L)
											end
										end
									else
										Result = CalcStat("RepMainL",L)
									end
								else
									Result = 14
								end
							else
								if 116 <= Lp and Lm <= 116 then
									Result = ExpFmod(N,116,20,L,0)
								elseif 117 <= Lp and Lm <= 120 then
									Result = ExpFmod(CalcStat("ProgExtComLowRnd",116,N),117,5.5,L,0)
								elseif 121 <= Lp then
									Result = CalcStat("ProgExtComHighRnd",L,CalcStat("ProgExtComLowRnd",120,N))
								end
							end
						elseif SN > "REPFATEL" then
							if SN < "RESISTC" then
								if SN < "REPTACMIT" then
									if SN < "REPMIGHTH" then
										if SN < "REPMAINH" then
											if SN == "REPFINESSE" then
												if Lm <= 50 then
													Result = LinFmod(1,322,557,1,50,L)
												elseif Lm <= 85 then
													Result = LinFmod(1,557,749.9477,50,85,L)
												elseif Lm <= 105 then
													Result = LinFmod(1,749.9477,859.1634,85,105,L)
												else
													Result = LinFmod(1,859.1634,939.2549,105,120,L)
												end
											end
										elseif SN > "REPMAINH" then
											if SN == "REPMAINL" then
												if Lm <= 50 then
													Result = RoundDblDown(LinFmod(1,53,102,1,50,L))
												elseif Lm <= 85 then
													Result = RoundDblDown(LinFmod(1,102,137,50,85,L))
												elseif Lm <= 105 then
													Result = RoundDblDown(LinFmod(1,137,157,85,105,L))
												else
													Result = RoundDblDown(LinFmod(1,157,172,105,120,L))
												end
											end
										else
											if Lm <= 50 then
												Result = RoundDblDown(LinFmod(1,80,153,1,50,L))
											elseif Lm <= 85 then
												Result = RoundDblDown(LinFmod(1,153,206,50,85,L))
											elseif Lm <= 105 then
												Result = RoundDblDown(LinFmod(1,206,236,85,105,L))
											else
												Result = RoundDblDown(LinFmod(1,236,258,105,120,L))
											end
										end
									elseif SN > "REPMIGHTH" then
										if SN < "REPMORALE" then
											if SN == "REPMIGHTL" then
												Result = CalcStat("RepMainL",L)
											end
										elseif SN > "REPMORALE" then
											if SN == "REPPOWER" then
												if Lm <= 50 then
													Result = LinFmod(1,94,212,1,50,L)
												elseif Lm <= 85 then
													Result = LinFmod(1,212,296,50,85,L)
												elseif Lm <= 105 then
													Result = LinFmod(1,296,344,85,105,L)
												else
													Result = LinFmod(1,344,380,105,120,L)
												end
											end
										else
											if Lm <= 50 then
												Result = LinFmod(1,187,427,1,50,L)
											elseif Lm <= 85 then
												Result = LinFmod(1,427,599,50,85,L)
											elseif Lm <= 105 then
												Result = LinFmod(1,599,697,85,105,L)
											else
												Result = LinFmod(1,697,770,105,120,L)
											end
										end
									else
										Result = CalcStat("RepMainH",L)
									end
								elseif SN > "REPTACMIT" then
									if SN < "REPWILLL" then
										if SN < "REPVITALITYL" then
											if SN == "REPVITALITYH" then
												Result = CalcStat("RepMainH",L)
											end
										elseif SN > "REPVITALITYL" then
											if SN == "REPWILLH" then
												Result = CalcStat("RepMainH",L)
											end
										else
											Result = CalcStat("RepMainL",L)
										end
									elseif SN > "REPWILLL" then
										if SN < "RESISTADD" then
											if SN == "RESIST" then
												Result = EquSng(StatLinInter("PntMPResist","ItemPntS","ProgBResist","AdjItem",L,N,0))
											end
										elseif SN > "RESISTADD" then
											if SN == "RESISTADDT" then
												Result = CalcStat("ResistT",L,N)
											end
										else
											Result = CalcStat("Resist",L,N)
										end
									else
										Result = CalcStat("RepMainL",L)
									end
								else
									if Lm <= 50 then
										Result = LinFmod(1,675,1116,1,50,L)
									elseif Lm <= 85 then
										Result = LinFmod(1,1116,1431,50,85,L)
									elseif Lm <= 105 then
										Result = LinFmod(1,1431,1611,85,105,L)
									else
										Result = LinFmod(1,1611,1746,105,120,L)
									end
								end
							elseif SN > "RESISTC" then
								if SN < "RESISTPRATPB" then
									if SN < "RESISTCRAW" then
										if SN < "RESISTCILVLFILTER" then
											if SN == "RESISTCI" then
												Result = RoundDblLotro(CalcStat("ResistCIRaw",L,N))
											end
										elseif SN > "RESISTCILVLFILTER" then
											if SN == "RESISTCIRAW" then
												Result = StatLinInter("PntMPResistC","ItemPntS","ProgBResist","AdjCreepItem",L,N,4)
											end
										else
											if 2.4 <= Lp and Lm <= 2.4 or 3.2 <= Lp and Lm <= 3.2 or 4 <= Lp and Lm <= 4 or 8 <= Lp and Lm <= 8 or 12 <= Lp and Lm <= 12 then
												Result = 515
											else
												Result = CalcStat("CreepILvlCurr",L)
											end
										end
									elseif SN > "RESISTCRAW" then
										if SN < "RESISTPRATP" then
											if SN == "RESISTPPRAT" then
												Result = CalcRatAB(CalcStat("ResistPRatPA",L),CalcStat("ResistPRatPB",L),CalcStat("ResistPRatPCapR",L),N)
											end
										elseif SN > "RESISTPRATP" then
											if SN == "RESISTPRATPA" then
												Result = 150
											end
										else
											Result = CalcPercAB(CalcStat("ResistPRatPA",L),CalcStat("ResistPRatPB",L),CalcStat("ResistPRatPCap",L),N)
										end
									else
										Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("ResistCIRaw",CalcStat("ResistCILvlFilter",N),N),99)
									end
								elseif SN > "RESISTPRATPB" then
									if SN < "RESISTT" then
										if SN < "RESISTPRATPCAP" then
											if SN == "RESISTPRATPC" then
												Result = 0.5
											end
										elseif SN > "RESISTPRATPCAP" then
											if SN == "RESISTPRATPCAPR" then
												Result = CalcStat("ResistPRatPB",L)*CalcStat("ResistPRatPC",L)
											end
										else
											Result = 50
										end
									elseif SN > "RESISTT" then
										if SN < "RIVERHOBBITRDPSVONEWILL" then
											if SN == "RIVERHOBBITRDPSVONENAME" then
												Result = "Seen the World"
											end
										elseif SN > "RIVERHOBBITRDPSVONEWILL" then
											if SN > "RIVERHOBBITRDPSVTWONAME" then
												if SN == "RIVERHOBBITRDTRAITAGILITY" then
													Result = CalcStat("RivHobSlipperyAgility",L)
												end
											elseif SN == "RIVERHOBBITRDPSVTWONAME" then
												Result = ""
											end
										else
											Result = CalcStat("RivHobSeenWorldWill",L)
										end
									else
										Result = EquSng(StatLinInter("PntMPResist","TraitPntS","ProgBResist","AdjTrait",L,N,0))
									end
								else
									Result = CalcStat("BRatRounded",L,"BRatExtra")
								end
							else
								Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("ResistCI",CalcStat("ResistCILvlFilter",N),N),0)
							end
						else
							Result = CalcStat("RepMainL",L)
						end
					else
						Result = CalcStat("BRatProgB",L,"BRatStandard")
					end
				elseif SN > "RIVERHOBBITRDTRAITFROSTMITP" then
					if SN < "STATC" then
						if SN < "RUNEKEEPERCDFATETONCPR" then
							if SN < "RUNEKEEPERCDARMOURTOTACMIT" then
								if SN < "RKDETERMINATIONWILL" then
									if SN < "RIVHOBSECLUSIONWILL" then
										if SN < "RIVERHOBBITRDTRAITWILL" then
											if SN == "RIVERHOBBITRDTRAITMORALE" then
												Result = CalcStat("RivHobHardyHolbMorale",L)
											end
										elseif SN > "RIVERHOBBITRDTRAITWILL" then
											if SN == "RIVHOBHARDYHOLBMORALE" then
												Result = CalcStat("MoraleT",L,1.0)
											end
										else
											Result = CalcStat("RivHobSeclusionWill",L)
										end
									elseif SN > "RIVHOBSECLUSIONWILL" then
										if SN < "RIVHOBSLIPPERYAGILITY" then
											if SN == "RIVHOBSEENWORLDWILL" then
												Result = CalcStat("WillT",L,1.0)
											end
										elseif SN > "RIVHOBSLIPPERYAGILITY" then
											if SN == "RIVHOBSWIMMERFROSTMITP" then
												Result = 1
											end
										else
											Result = CalcStat("AgilityT",L,1.0)
										end
									else
										Result = -CalcStat("WillT",L,0.4)
									end
								elseif SN > "RKDETERMINATIONWILL" then
									if SN < "RUNEKEEPERCDAGILITYTOFINESSE" then
										if SN < "RUNEKEEPERCDAGILITYTOCRITHIT" then
											if SN == "RKFORTUNESMILESFATE" then
												Result = CalcStat("FateT",L,CalcStat("Trait567810Choice",N)*0.4)
											end
										elseif SN > "RUNEKEEPERCDAGILITYTOCRITHIT" then
											if SN == "RUNEKEEPERCDAGILITYTOEVADE" then
												Result = 1
											end
										else
											Result = 2
										end
									elseif SN > "RUNEKEEPERCDAGILITYTOFINESSE" then
										if SN < "RUNEKEEPERCDARMOURTOCOMPHYMIT" then
											if SN == "RUNEKEEPERCDAGILITYTOTACMAS" then
												Result = 2
											end
										elseif SN > "RUNEKEEPERCDARMOURTOCOMPHYMIT" then
											if SN == "RUNEKEEPERCDARMOURTONONPHYMIT" then
												Result = 0.2
											end
										else
											Result = 1
										end
									else
										Result = 1
									end
								else
									Result = CalcStat("WillT",L,CalcStat("Trait567810Choice",N)*0.4)
								end
							elseif SN > "RUNEKEEPERCDARMOURTOTACMIT" then
								if SN < "RUNEKEEPERCDBASENCMR" then
									if SN < "RUNEKEEPERCDBASEICMR" then
										if SN < "RUNEKEEPERCDBASEAGILITY" then
											if SN == "RUNEKEEPERCDARMOURTYPE" then
												Result = 1
											end
										elseif SN > "RUNEKEEPERCDBASEAGILITY" then
											if SN == "RUNEKEEPERCDBASEFATE" then
												Result = CalcStat("ClassBaseFate",L)
											end
										else
											Result = CalcStat("ClassBaseAgilityL",L)
										end
									elseif SN > "RUNEKEEPERCDBASEICMR" then
										if SN < "RUNEKEEPERCDBASEMIGHT" then
											if SN == "RUNEKEEPERCDBASEICPR" then
												Result = CalcStat("ClassBaseICPR",L)
											end
										elseif SN > "RUNEKEEPERCDBASEMIGHT" then
											if SN == "RUNEKEEPERCDBASEMORALE" then
												Result = CalcStat("ClassBaseMorale",L)
											end
										else
											Result = CalcStat("ClassBaseMightM",L)
										end
									else
										Result = CalcStat("ClassBaseICMRL",L)
									end
								elseif SN > "RUNEKEEPERCDBASENCMR" then
									if SN < "RUNEKEEPERCDBASEWILL" then
										if SN < "RUNEKEEPERCDBASEPOWER" then
											if SN == "RUNEKEEPERCDBASENCPR" then
												Result = CalcStat("ClassBaseNCPR",L)
											end
										elseif SN > "RUNEKEEPERCDBASEPOWER" then
											if SN == "RUNEKEEPERCDBASEVITALITY" then
												Result = CalcStat("ClassBaseVitality",L)
											end
										else
											Result = CalcStat("ClassBasePower",L)
										end
									elseif SN > "RUNEKEEPERCDBASEWILL" then
										if SN < "RUNEKEEPERCDCALCTYPENONPHYMIT" then
											if SN == "RUNEKEEPERCDCALCTYPECOMPHYMIT" then
												Result = 12
											end
										elseif SN > "RUNEKEEPERCDCALCTYPENONPHYMIT" then
											if SN == "RUNEKEEPERCDCALCTYPETACMIT" then
												Result = 25
											end
										else
											Result = 12
										end
									else
										Result = CalcStat("ClassBaseWillH",L)
									end
								else
									Result = CalcStat("ClassBaseNCMRL",L)
								end
							else
								Result = 0.2
							end
						elseif SN > "RUNEKEEPERCDFATETONCPR" then
							if SN < "RUNEKEEPERCDWILLTORESIST" then
								if SN < "RUNEKEEPERCDPHYMITTONONPHYMIT" then
									if SN < "RUNEKEEPERCDMIGHTTOOUTHEAL" then
										if SN < "RUNEKEEPERCDHASPOWER" then
											if SN == "RUNEKEEPERCDFATETOPOWER" then
												Result = 1
											end
										elseif SN > "RUNEKEEPERCDHASPOWER" then
											if SN == "RUNEKEEPERCDMIGHTTOCRITHIT" then
												Result = 1
											end
										else
											Result = 1
										end
									elseif SN > "RUNEKEEPERCDMIGHTTOOUTHEAL" then
										if SN < "RUNEKEEPERCDMIGHTTOTACMIT" then
											if SN == "RUNEKEEPERCDMIGHTTOTACMAS" then
												Result = 2
											end
										elseif SN > "RUNEKEEPERCDMIGHTTOTACMIT" then
											if SN == "RUNEKEEPERCDPHYMITTOCOMPHYMIT" then
												Result = 1
											end
										else
											Result = 1
										end
									else
										Result = 2
									end
								elseif SN > "RUNEKEEPERCDPHYMITTONONPHYMIT" then
									if SN < "RUNEKEEPERCDVITALITYTONCMR" then
										if SN < "RUNEKEEPERCDVITALITYTOICMR" then
											if SN == "RUNEKEEPERCDTACMASTOOUTHEAL" then
												Result = 1
											end
										elseif SN > "RUNEKEEPERCDVITALITYTOICMR" then
											if SN == "RUNEKEEPERCDVITALITYTOMORALE" then
												Result = 4.5
											end
										else
											Result = 0.012
										end
									elseif SN > "RUNEKEEPERCDVITALITYTONCMR" then
										if SN < "RUNEKEEPERCDWILLTOEVADE" then
											if SN == "RUNEKEEPERCDWILLTOCRITHIT" then
												Result = 1
											end
										elseif SN > "RUNEKEEPERCDWILLTOEVADE" then
											if SN == "RUNEKEEPERCDWILLTOPHYMIT" then
												Result = 1
											end
										else
											Result = 2
										end
									else
										Result = 0.12
									end
								else
									Result = 1
								end
							elseif SN > "RUNEKEEPERCDWILLTORESIST" then
								if SN < "SKILLPOWERCOSTMOUNTED" then
									if SN < "SHADOWMITT" then
										if SN < "RUNEKEEPERCDWILLTOTACMIT" then
											if SN == "RUNEKEEPERCDWILLTOTACMAS" then
												Result = 3
											end
										elseif SN > "RUNEKEEPERCDWILLTOTACMIT" then
											if SN == "SHADOWMIT" then
												Result = CalcStat("DmgTypeMit",L,N)
											end
										else
											Result = 1
										end
									elseif SN > "SHADOWMITT" then
										if SN < "SHIELDBRAWLERBLOCK" then
											if SN == "SHIELDBLOCK" then
												Result = EquSng(StatLinInter("PntMPShieldBlock","ItemPntS","ProgBBPE","AdjItem",L,N,0))
											end
										elseif SN > "SHIELDBRAWLERBLOCK" then
											if SN == "SKILLPOWERCOST" then
												if Lm <= 140 then
													Result = CalcStat("CombatDamageModEnergy",L,0.64*N)
												else
													Result = CalcStat("CombatDamageModEnergy",L,1.05*0.64*N)
												end
											end
										else
											Result = CalcStat("DwarfShieldBrwlBlock",L)
										end
									else
										Result = CalcStat("DmgTypeMitT",L,N)
									end
								elseif SN > "SKILLPOWERCOSTMOUNTED" then
									if SN < "STALKERCDCALCTYPECOMPHYMIT" then
										if SN < "SONGRESISTT" then
											if SN == "SONGRESIST" then
												Result = CalcStat("ResistAdd",L,N)
											end
										elseif SN > "SONGRESISTT" then
											if SN == "STALKERCANBLOCK" then
												Result = 1
											end
										else
											Result = CalcStat("ResistAddT",L,N)
										end
									elseif SN > "STALKERCDCALCTYPECOMPHYMIT" then
										if SN < "STALKERCDCALCTYPETACMIT" then
											if SN == "STALKERCDCALCTYPENONPHYMIT" then
												Result = 14
											end
										elseif SN > "STALKERCDCALCTYPETACMIT" then
											if SN == "STALKERCDHASPOWER" then
												Result = 1
											end
										else
											Result = 27
										end
									else
										Result = 13
									end
								else
									Result = CalcStat("CombatDamageModEnergy",L,0.64*N)
								end
							else
								Result = 1
							end
						else
							Result = 0.07
						end
					elseif SN > "STATC" then
						if SN < "STOUTWRBLACKLSHADOWMITP" then
							if SN < "STOUTAXERDTRAITAGILITY" then
								if SN < "STDPOWERRAW" then
									if SN < "STDMORALERAW" then
										if SN < "STDMORALEL" then
											if SN == "STDMORALEH" then
												if Lm <= 105 then
													Result = RoundDbl(2*CalcStat("StdMoraleRaw",L))
												else
													Result = CalcStat("ProgExtLowExpRnd",L,CalcStat("StdMoraleH",105))
												end
											end
										elseif SN > "STDMORALEL" then
											if SN == "STDMORALEM" then
												if Lm <= 105 then
													Result = RoundDbl(1.5*CalcStat("StdMoraleRaw",L))
												else
													Result = CalcStat("ProgExtLowExpRnd",L,CalcStat("StdMoraleM",105))
												end
											end
										else
											if Lm <= 105 then
												Result = RoundDbl(CalcStat("StdMoraleRaw",L))
											else
												Result = CalcStat("ProgExtLowExpRnd",L,CalcStat("StdMoraleL",105))
											end
										end
									elseif SN > "STDMORALERAW" then
										if SN < "STDPOWERH" then
											if SN == "STDPNTS" then
												Result = {{1,50,60,65,75,85,95,100,105,106,115,116,120,121,130,131,140,141,150,151,160},{1,50,60,65,75,85,95,100,105,106,115,116,120,121,130,131,140,141,150,151,160}}
											end
										elseif SN > "STDPOWERH" then
											if SN == "STDPOWERL" then
												if Lm <= 105 then
													Result = RoundDbl(CalcStat("StdPowerRaw",L))
												else
													Result = CalcStat("ProgExtLowExpRnd",L,CalcStat("StdPowerL",105))
												end
											end
										else
											if Lm <= 105 then
												Result = RoundDbl(2*CalcStat("StdPowerRaw",L))
											else
												Result = CalcStat("ProgExtLowExpRnd",L,CalcStat("StdPowerH",105))
											end
										end
									else
										if Lm <= 50 then
											Result = LinFmod(1,7.51,227.59,1,50,L)
										else
											Result = LinFmod(1,227.59,1327.5,50,105,L)
										end
									end
								elseif SN > "STDPOWERRAW" then
									if SN < "STDPROGRATINGS" then
										if SN < "STDPROGENERGY" then
											if SN == "STDPROGDAMAGE" then
												if Lm <= 50 then
													Result = LinFmod(N,1,10,1,50,L,"P")
												elseif Lm <= 60 then
													Result = LinFmod(CalcStat("StdProgDamage",50,N),1,1.33,50,60,L,"P")
												elseif Lm <= 65 then
													Result = LinFmod(CalcStat("StdProgDamage",60,N),1,1.095,60,65,L,"P")
												elseif Lm <= 75 then
													Result = LinFmod(CalcStat("StdProgDamage",65,N),1,1.33,65,75,L,"P")
												elseif Lm <= 85 then
													Result = LinFmod(CalcStat("StdProgDamage",75,N),1,1.33,75,85,L,"P")
												elseif Lm <= 95 then
													Result = LinFmod(CalcStat("StdProgDamage",85,N),1,1.33,85,95,L,"P")
												elseif Lm <= 100 then
													Result = LinFmod(CalcStat("StdProgDamage",95,N),1,1.25,95,100,L,"P")
												elseif Lm <= 105 then
													Result = LinFmod(CalcStat("StdProgDamage",100,N),1,1.25,100,105,L,"P")
												elseif Lm <= 115 then
													Result = LinFmod(CalcStat("StdProgDamage",105,N),1.1,1.33,106,115,L,"P")
												elseif Lm <= 120 then
													Result = LinFmod(CalcStat("StdProgDamage",115,N),1.1,1.25,116,120,L,"P")
												elseif Lm <= 130 then
													Result = LinFmod(CalcStat("StdProgDamage",120,N),1.1,1.33,121,130,L,"P")
												elseif Lm <= 140 then
													Result = LinFmod(CalcStat("StdProgDamage",130,N),1.1,1.5,131,140,L,"P")
												elseif Lm <= 150 then
													Result = LinFmod(CalcStat("StdProgDamage",140,N),1.1,1.5,141,150,L,"P")
												else
													Result = LinFmod(CalcStat("StdProgDamage",150,N),1.1,1.5,151,160,L,"P")
												end
											end
										elseif SN > "STDPROGENERGY" then
											if SN == "STDPROGHEALTH" then
												if Lm <= 50 then
													Result = LinFmod(N,1,7.5,1,50,L,"P")
												elseif Lm <= 60 then
													Result = LinFmod(CalcStat("StdProgHealth",50,N),1,1.33,50,60,L,"P")
												elseif Lm <= 65 then
													Result = LinFmod(CalcStat("StdProgHealth",60,N),1,1.25,60,65,L,"P")
												elseif Lm <= 75 then
													Result = LinFmod(CalcStat("StdProgHealth",65,N),1,1.5,65,75,L,"P")
												elseif Lm <= 85 then
													Result = LinFmod(CalcStat("StdProgHealth",75,N),1,1.5,75,85,L,"P")
												elseif Lm <= 95 then
													Result = LinFmod(CalcStat("StdProgHealth",85,N),1,1.33,85,95,L,"P")
												elseif Lm <= 100 then
													Result = LinFmod(CalcStat("StdProgHealth",95,N),1,1.5,95,100,L,"P")
												elseif Lm <= 105 then
													Result = LinFmod(CalcStat("StdProgHealth",100,N),1,1.333,100,105,L,"P")
												elseif Lm <= 115 then
													Result = LinFmod(CalcStat("StdProgHealth",105,N),1.1,1.5,106,115,L,"P")
												elseif Lm <= 120 then
													Result = LinFmod(CalcStat("StdProgHealth",115,N),1.15,1.25,116,120,L,"P")
												elseif Lm <= 130 then
													Result = LinFmod(CalcStat("StdProgHealth",120,N),1.15,1.5,121,130,L,"P")
												elseif Lm <= 140 then
													Result = LinFmod(CalcStat("StdProgHealth",130,N),1.15,2,131,140,L,"P")
												elseif Lm <= 150 then
													Result = LinFmod(CalcStat("StdProgHealth",140,N),1.15,2,141,150,L,"P")
												else
													Result = LinFmod(CalcStat("StdProgHealth",150,N),1,2,151,160,L,"P")
												end
											end
										else
											if Lm <= 50 then
												Result = LinFmod(N,1,2,1,50,L,"P")
											elseif Lm <= 60 then
												Result = LinFmod(CalcStat("StdProgEnergy",50,N),1,1.33,50,60,L,"P")
											elseif Lm <= 65 then
												Result = LinFmod(CalcStat("StdProgEnergy",60,N),1,1.25,60,65,L,"P")
											elseif Lm <= 75 then
												Result = LinFmod(CalcStat("StdProgEnergy",65,N),1,1.5,65,75,L,"P")
											elseif Lm <= 85 then
												Result = LinFmod(CalcStat("StdProgEnergy",75,N),1,1.5,75,85,L,"P")
											elseif Lm <= 95 then
												Result = LinFmod(CalcStat("StdProgEnergy",85,N),1,1.33,85,95,L,"P")
											elseif Lm <= 100 then
												Result = LinFmod(CalcStat("StdProgEnergy",95,N),1,1.315,95,100,L,"P")
											elseif Lm <= 105 then
												Result = LinFmod(CalcStat("StdProgEnergy",100,N),1,1.333,100,105,L,"P")
											elseif Lm <= 115 then
												Result = LinFmod(CalcStat("StdProgEnergy",105,N),1.1,1.5,106,115,L,"P")
											elseif Lm <= 120 then
												Result = LinFmod(CalcStat("StdProgEnergy",115,N),1.15,1.25,116,120,L,"P")
											elseif Lm <= 130 then
												Result = LinFmod(CalcStat("StdProgEnergy",120,N),1.15,1.5,121,130,L,"P")
											elseif Lm <= 140 then
												Result = LinFmod(CalcStat("StdProgEnergy",130,N),1.15,2,131,140,L,"P")
											elseif Lm <= 150 then
												Result = LinFmod(CalcStat("StdProgEnergy",140,N),1.15,2,141,150,L,"P")
											else
												Result = LinFmod(CalcStat("StdProgEnergy",150,N),1,2,151,160,L,"P")
											end
										end
									elseif SN > "STDPROGRATINGS" then
										if SN < "STOUTAXERDPSVONEVITALITY" then
											if SN == "STOUTAXERDPSVONENAME" then
												Result = "Unwritten Destiny"
											end
										elseif SN > "STOUTAXERDPSVONEVITALITY" then
											if SN == "STOUTAXERDPSVTWONAME" then
												Result = ""
											end
										else
											Result = CalcStat("StoutUnwritDestVitality",L)
										end
									else
										if Lm <= 50 then
											Result = LinFmod(N,1,10,1,50,L,"P")
										elseif Lm <= 60 then
											Result = LinFmod(CalcStat("StdProgRatings",50,N),1,1.5,50,60,L,"P")
										elseif Lm <= 65 then
											Result = LinFmod(CalcStat("StdProgRatings",60,N),1,1.335,60,65,L,"P")
										elseif Lm <= 75 then
											Result = LinFmod(CalcStat("StdProgRatings",65,N),1,1.5,65,75,L,"P")
										elseif Lm <= 85 then
											Result = LinFmod(CalcStat("StdProgRatings",75,N),1,1.5,75,85,L,"P")
										elseif Lm <= 95 then
											Result = LinFmod(CalcStat("StdProgRatings",85,N),1,1.445,85,95,L,"P")
										elseif Lm <= 100 then
											Result = LinFmod(CalcStat("StdProgRatings",95,N),1,1.39,95,100,L,"P")
										elseif Lm <= 105 then
											Result = LinFmod(CalcStat("StdProgRatings",100,N),1,1.33,100,105,L,"P")
										elseif Lm <= 115 then
											Result = LinFmod(CalcStat("StdProgRatings",105,N),1.1,1.5,106,115,L,"P")
										elseif Lm <= 120 then
											Result = LinFmod(CalcStat("StdProgRatings",115,N),1.15,1.25,116,120,L,"P")
										elseif Lm <= 130 then
											Result = LinFmod(CalcStat("StdProgRatings",120,N),1.15,1.5,121,130,L,"P")
										elseif Lm <= 140 then
											Result = LinFmod(CalcStat("StdProgRatings",130,N),1.15,2,131,140,L,"P")
										elseif Lm <= 150 then
											Result = LinFmod(CalcStat("StdProgRatings",140,N),1.3,2.205,141,150,L,"P")
										else
											Result = LinFmod(CalcStat("StdProgRatings",150,N),1,2,151,160,L,"P")
										end
									end
								else
									if Lm <= 50 then
										Result = LinFmod(1,3,91.0375,1,50,L)
									else
										Result = LinFmod(1,91.0375,421,50,105,L)
									end
								end
							elseif SN > "STOUTAXERDTRAITAGILITY" then
								if SN < "STOUTDOOMDRASAFATE" then
									if SN < "STOUTAXERDTRAITPHYMITP" then
										if SN < "STOUTAXERDTRAITFATE" then
											if SN == "STOUTAXERDTRAITDISEASERESISTP" then
												Result = CalcStat("StoutWrBlackLDiseaseResistP",L)
											end
										elseif SN > "STOUTAXERDTRAITFATE" then
											if SN == "STOUTAXERDTRAITMIGHT" then
												Result = CalcStat("StoutWrBlackLMight",L)
											end
										else
											Result = CalcStat("StoutDoomDrasaFate",L)
										end
									elseif SN > "STOUTAXERDTRAITPHYMITP" then
										if SN < "STOUTAXERDTRAITVITALITY" then
											if SN == "STOUTAXERDTRAITSHADOWMITP" then
												Result = CalcStat("StoutWrBlackLShadowMitP",L)
											end
										elseif SN > "STOUTAXERDTRAITVITALITY" then
											if SN == "STOUTAXERDTRAITWILL" then
												Result = CalcStat("StoutUnyieldingWill",L)
											end
										else
											Result = CalcStat("StoutShadowEyeVitality",L)
										end
									else
										Result = CalcStat("StoutUnyieldingPhyMitP",L)
									end
								elseif SN > "STOUTDOOMDRASAFATE" then
									if SN < "STOUTUNYIELDINGWILL" then
										if SN < "STOUTUNWRITDESTVITALITY" then
											if SN == "STOUTSHADOWEYEVITALITY" then
												Result = -CalcStat("VitalityT",L,0.4)
											end
										elseif SN > "STOUTUNWRITDESTVITALITY" then
											if SN == "STOUTUNYIELDINGPHYMITP" then
												Result = 1
											end
										else
											Result = CalcStat("VitalityT",L,1.0)
										end
									elseif SN > "STOUTUNYIELDINGWILL" then
										if SN < "STOUTWRBLACKLDISEASERESISTP" then
											if SN == "STOUTWRBLACKLAGILITY" then
												Result = CalcStat("AgilityT",L,1.0)
											end
										elseif SN > "STOUTWRBLACKLDISEASERESISTP" then
											if SN == "STOUTWRBLACKLMIGHT" then
												Result = CalcStat("MightT",L,1.0)
											end
										else
											Result = 1
										end
									else
										Result = CalcStat("WillT",L,1.0)
									end
								else
									Result = -CalcStat("FateT",L,0.4)
								end
							else
								Result = CalcStat("StoutWrBlackLAgility",L)
							end
						elseif SN > "STOUTWRBLACKLSHADOWMITP" then
							if SN < "TACMASCIRAW" then
								if SN < "TACDMGPRATPA" then
									if SN < "T2PENRESIST" then
										if SN < "T2PENBPE" then
											if SN == "T2PENARMOUR" then
												Result = CalcStat("T2penMit",L)
											end
										elseif SN > "T2PENBPE" then
											if SN == "T2PENMIT" then
												if Lm <= 115 then
													Result = RoundDblDown(L*13.5)*-5
												else
													Result = EquSng(DecSng(CalcStat("ProgExtComLowRaw",L,CalcStat("T2PenMit",115))))
												end
											end
										else
											if Lm <= 115 then
												Result = (-40)*L
											else
												Result = EquSng(DecSng(CalcStat("ProgExtComLowRaw",L,CalcStat("T2PenBPE",115))))
											end
										end
									elseif SN > "T2PENRESIST" then
										if SN < "TACDMGPPRAT" then
											if SN == "TACDMGPBONUS" then
												Result = CalcStat("OutDmgPBonus",L)
											end
										elseif SN > "TACDMGPPRAT" then
											if SN == "TACDMGPRATP" then
												Result = CalcStat("OutDmgPRatP",L,N)
											end
										else
											Result = CalcStat("OutDmgPPRat",L,N)
										end
									else
										if Lm <= 115 then
											Result = (-90)*L
										else
											Result = EquSng(DecSng(CalcStat("ProgExtComLowRaw",L,CalcStat("T2PenResist",115))))
										end
									end
								elseif SN > "TACDMGPRATPA" then
									if SN < "TACDMGPRATPCAPR" then
										if SN < "TACDMGPRATPC" then
											if SN == "TACDMGPRATPB" then
												Result = CalcStat("OutDmgPRatPB",L)
											end
										elseif SN > "TACDMGPRATPC" then
											if SN == "TACDMGPRATPCAP" then
												Result = CalcStat("OutDmgPRatPCap",L)
											end
										else
											Result = CalcStat("OutDmgPRatPC",L)
										end
									elseif SN > "TACDMGPRATPCAPR" then
										if SN < "TACMASC" then
											if SN == "TACMAS" then
												Result = CalcStat("Mastery",L,N)
											end
										elseif SN > "TACMASC" then
											if SN == "TACMASCI" then
												Result = CalcStat("MasteryCI",L,N)
											end
										else
											Result = CalcStat("MasteryC",L,N)
										end
									else
										Result = CalcStat("OutDmgPRatPCapR",L)
									end
								else
									Result = CalcStat("OutDmgPRatPA",L)
								end
							elseif SN > "TACMASCIRAW" then
								if SN < "TACMITCIRAW" then
									if SN < "TACMIT" then
										if SN < "TACMASOLD" then
											if SN == "TACMASCRAW" then
												Result = CalcStat("MasteryCRaw",L,N)
											end
										elseif SN > "TACMASOLD" then
											if SN == "TACMAST" then
												Result = CalcStat("MasteryT",L,N)
											end
										else
											Result = CalcStat("Mastery",L,N)
										end
									elseif SN > "TACMIT" then
										if SN < "TACMITCI" then
											if SN == "TACMITC" then
												Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("TacMitCI",CalcStat("TacMitCILvlFilter",N),N),0)
											end
										elseif SN > "TACMITCI" then
											if SN == "TACMITCILVLFILTER" then
												if 3.8 <= Lp and Lm <= 3.8 or 5.6 <= Lp and Lm <= 5.6 or 6.9 <= Lp and Lm <= 6.9 or 12.9 <= Lp and Lm <= 12.9 or 17.3 <= Lp and Lm <= 17.3 or 24.225 <= Lp and Lm <= 24.225 then
													Result = 515
												else
													Result = CalcStat("CreepILvlCurr",L)
												end
											end
										else
											Result = RoundDblLotro(CalcStat("TacMitCIRaw",L,N))
										end
									else
										Result = EquSng(StatLinInter("PntMPTacMit","ItemPntS","ProgBMitigation","AdjItemMit",L,N,0))
									end
								elseif SN > "TACMITCIRAW" then
									if SN < "TACMITHPRATP" then
										if SN < "TACMITHPBONUS" then
											if SN == "TACMITCRAW" then
												Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("TacMitCIRaw",CalcStat("TacMitCILvlFilter",N),N),99)
											end
										elseif SN > "TACMITHPBONUS" then
											if SN == "TACMITHPPRAT" then
												Result = CalcStat("MitHeavyPPRat",L,N)
											end
										else
											Result = CalcStat("MitHeavyPBonus",L)
										end
									elseif SN > "TACMITHPRATP" then
										if SN < "TACMITHPRATPB" then
											if SN == "TACMITHPRATPA" then
												Result = CalcStat("MitHeavyPRatPA",L)
											end
										elseif SN > "TACMITHPRATPB" then
											if SN > "TACMITHPRATPC" then
												if SN == "TACMITHPRATPCAP" then
													Result = CalcStat("MitHeavyPRatPCap",L)
												end
											elseif SN == "TACMITHPRATPC" then
												Result = CalcStat("MitHeavyPRatPC",L)
											end
										else
											Result = CalcStat("MitHeavyPRatPB",L)
										end
									else
										Result = CalcStat("MitHeavyPRatP",L,N)
									end
								else
									Result = StatLinInter("PntMPTacMitC","ItemPntS","ProgBMitigation","AdjCreepItemMit",L,N,4)
								end
							else
								Result = CalcStat("MasteryCIRaw",L,N)
							end
						else
							Result = 1
						end
					else
						Result = CalcStat(C,L)
					end
				else
					Result = CalcStat("RivHobSwimmerFrostMitP",L)
				end
			else
				Result = 0.25
			end
		elseif SN > "TACMITHPRATPCAPR" then
			if SN < "WARDENCDMIGHTTOCRITHIT" then
				if SN < "VIRTVALOURPHYMAS" then
					if SN < "VIRTCONFIDENCEFINESSE" then
						if SN < "TOMEVITALITYDEC" then
							if SN < "TACMITMPRATPCAPR" then
								if SN < "TACMITLPRATPCAPR" then
									if SN < "TACMITLPRATPA" then
										if SN < "TACMITLPPRAT" then
											if SN == "TACMITLPBONUS" then
												Result = CalcStat("MitLightPBonus",L)
											end
										elseif SN > "TACMITLPPRAT" then
											if SN == "TACMITLPRATP" then
												Result = CalcStat("MitLightPRatP",L,N)
											end
										else
											Result = CalcStat("MitLightPPRat",L,N)
										end
									elseif SN > "TACMITLPRATPA" then
										if SN < "TACMITLPRATPC" then
											if SN == "TACMITLPRATPB" then
												Result = CalcStat("MitLightPRatPB",L)
											end
										elseif SN > "TACMITLPRATPC" then
											if SN == "TACMITLPRATPCAP" then
												Result = CalcStat("MitLightPRatPCap",L)
											end
										else
											Result = CalcStat("MitLightPRatPC",L)
										end
									else
										Result = CalcStat("MitLightPRatPA",L)
									end
								elseif SN > "TACMITLPRATPCAPR" then
									if SN < "TACMITMPRATPA" then
										if SN < "TACMITMPPRAT" then
											if SN == "TACMITMPBONUS" then
												Result = CalcStat("MitMediumPBonus",L)
											end
										elseif SN > "TACMITMPPRAT" then
											if SN == "TACMITMPRATP" then
												Result = CalcStat("MitMediumPRatP",L,N)
											end
										else
											Result = CalcStat("MitMediumPPRat",L,N)
										end
									elseif SN > "TACMITMPRATPA" then
										if SN < "TACMITMPRATPC" then
											if SN == "TACMITMPRATPB" then
												Result = CalcStat("MitMediumPRatPB",L)
											end
										elseif SN > "TACMITMPRATPC" then
											if SN == "TACMITMPRATPCAP" then
												Result = CalcStat("MitMediumPRatPCap",L)
											end
										else
											Result = CalcStat("MitMediumPRatPC",L)
										end
									else
										Result = CalcStat("MitMediumPRatPA",L)
									end
								else
									Result = CalcStat("MitLightPRatPCapR",L)
								end
							elseif SN > "TACMITMPRATPCAPR" then
								if SN < "TOMETOTALFATE" then
									if SN < "TOMEFATE" then
										if SN < "TACRESIST" then
											if SN == "TACMITT" then
												Result = EquSng(StatLinInter("PntMPTacMit","TraitPntS","ProgBMitigation","AdjTraitMit",L,N,0))
											end
										elseif SN > "TACRESIST" then
											if SN == "TACRESISTT" then
												Result = CalcStat("ResistAddT",L,N)
											end
										else
											Result = CalcStat("ResistAdd",L,N)
										end
									elseif SN > "TOMEFATE" then
										if SN < "TOMEMAIN" then
											if SN == "TOMEFATEDEC" then
												Result = CalcStat("TomeTotalFateDec",L)-CalcStat("TomeTotalFateDec",L-1)
											end
										elseif SN > "TOMEMAIN" then
											if SN == "TOMEMAINDEC" then
												Result = CalcStat("TomeTotalMainDec",L)-CalcStat("TomeTotalMainDec",L-1)
											end
										else
											Result = CalcStat("TomeMainDec",RomanRankDecode(C))
										end
									else
										Result = CalcStat("TomeFateDec",RomanRankDecode(C))
									end
								elseif SN > "TOMETOTALFATE" then
									if SN < "TOMETOTALMAINDEC" then
										if SN < "TOMETOTALLEVEL" then
											if SN == "TOMETOTALFATEDEC" then
												Result = CalcStat("FateT",CalcStat("TomeTotalLevel",L),2.0)
											end
										elseif SN > "TOMETOTALLEVEL" then
											if SN == "TOMETOTALMAIN" then
												Result = CalcStat("TomeTotalMainDec",RomanRankDecode(C))
											end
										else
											if 1 <= Lp and Lm <= 23 then
												Result = DataTableValue({4,15,27,38,48,54,60,63,67,71,75,78,85,90,95,98,101,104,106,110,114,116,121},L)
											end
										end
									elseif SN > "TOMETOTALMAINDEC" then
										if SN < "TOMETOTALVITALITYDEC" then
											if SN == "TOMETOTALVITALITY" then
												Result = CalcStat("TomeTotalVitalityDec",RomanRankDecode(C))
											end
										elseif SN > "TOMETOTALVITALITYDEC" then
											if SN == "TOMEVITALITY" then
												Result = CalcStat("TomeVitalityDec",RomanRankDecode(C))
											end
										else
											Result = CalcStat("VitalityT",CalcStat("TomeTotalLevel",L),2.0)
										end
									else
										Result = CalcStat("MainT",CalcStat("TomeTotalLevel",L),2.0)
									end
								else
									Result = CalcStat("TomeTotalFateDec",RomanRankDecode(C))
								end
							else
								Result = CalcStat("MitMediumPRatPCapR",L)
							end
						elseif SN > "TOMEVITALITYDEC" then
							if SN < "TRAIT56789CHOICE" then
								if SN < "TRAIT1234CHOICE" then
									if SN < "TPENRESIST" then
										if SN < "TPENBPE" then
											if SN == "TPENARMOUR" then
												Result = -CalcStat("ArmourPenT",L,CalcStat("TpenChoice",N))
											end
										elseif SN > "TPENBPE" then
											if SN == "TPENCHOICE" then
												if 1 <= Lp then
													Result = DataTableValue({0.5,1,2},L)
												end
											end
										else
											Result = -CalcStat("BPET",L,CalcStat("TpenChoice",N))
										end
									elseif SN > "TPENRESIST" then
										if SN < "TRAIT12345CHOICE" then
											if SN == "TRAIT123455CHOICE" then
												if 1 <= Lp and Lm <= 6 then
													Result = DataTableValue({1,2,3,4,5,5},L)
												end
											end
										elseif SN > "TRAIT12345CHOICE" then
											if SN == "TRAIT12347CHOICE" then
												if 1 <= Lp and Lm <= 5 then
													Result = DataTableValue({1,2,3,4,7},L)
												end
											end
										else
											if 1 <= Lp and Lm <= 5 then
												Result = DataTableValue({1,2,3,4,5},L)
											end
										end
									else
										Result = -CalcStat("ResistT",L,CalcStat("TpenChoice",N)*2)
									end
								elseif SN > "TRAIT1234CHOICE" then
									if SN < "TRAIT234CHOICE" then
										if SN < "TRAIT13510CHOICE" then
											if SN == "TRAIT123CHOICE" then
												if 1 <= Lp and Lm <= 3 then
													Result = DataTableValue({1,2,3},L)
												end
											end
										elseif SN > "TRAIT13510CHOICE" then
											if SN == "TRAIT23456CHOICE" then
												if 1 <= Lp and Lm <= 5 then
													Result = DataTableValue({2,3,4,5,6},L)
												end
											end
										else
											if 1 <= Lp and Lm <= 4 then
												Result = DataTableValue({1,3,5,10},L)
											end
										end
									elseif SN > "TRAIT234CHOICE" then
										if SN < "TRAIT47101316CHOICE" then
											if SN == "TRAIT357912CHOICE" then
												if 1 <= Lp and Lm <= 5 then
													Result = DataTableValue({3,5,7,9,12},L)
												end
											end
										elseif SN > "TRAIT47101316CHOICE" then
											if SN == "TRAIT567810CHOICE" then
												if 1 <= Lp and Lm <= 5 then
													Result = DataTableValue({5,6,7,8,10},L)
												end
											end
										else
											if 1 <= Lp and Lm <= 5 then
												Result = DataTableValue({4,7,10,13,16},L)
											end
										end
									else
										if 1 <= Lp and Lm <= 3 then
											Result = DataTableValue({2,3,4},L)
										end
									end
								else
									if 1 <= Lp and Lm <= 4 then
										Result = DataTableValue({1,2,3,4},L)
									end
								end
							elseif SN > "TRAIT56789CHOICE" then
								if SN < "VIRTCHARITYVITALITY" then
									if SN < "U371LEGACYSTATFIX" then
										if SN < "TRAITPNTS" then
											if SN == "TRAIT58121620CHOICE" then
												if 1 <= Lp and Lm <= 5 then
													Result = DataTableValue({5,8,12,16,20},L)
												end
											end
										elseif SN > "TRAITPNTS" then
											if SN == "TRAITPNTSVITAL" then
												Result = {{1,25,50,60,65,75,85,95,100,105,115,120,130,140,141,150},{1,25,50,60,65,75,85,95,100,105,115,120,130,140,141,150}}
											end
										else
											Result = {{1,25,50,60,65,75,85,95,100,105,115,120,130,131,140,141,150},{1,25,50,60,65,75,85,95,100,105,115,120,130,131,140,141,150}}
										end
									elseif SN > "U371LEGACYSTATFIX" then
										if SN < "VIRTCHARITYPHYMIT" then
											if SN == "VARMOUR" then
												Result = RoundDbl(StatLinInter("PntMPArmourVirtues","ItemPntS","ProgBArmourLight","AdjItemMit",L,N,0))
											end
										elseif SN > "VIRTCHARITYPHYMIT" then
											if SN == "VIRTCHARITYRESIST" then
												Result = CalcStat("VSResistH",L)
											end
										else
											Result = CalcStat("VSPhyMitM",L)
										end
									else
										if Lm <= 2 then
											Result = 0
										else
											Result = RoundDblUp(CalcStat(C,L-2)*0.07)
										end
									end
								elseif SN > "VIRTCHARITYVITALITY" then
									if SN < "VIRTCOMPASSIONTACMIT" then
										if SN < "VIRTCOMPASSIONARMOUR" then
											if SN == "VIRTCHARITYVPMORALE" then
												Result = CalcStat("VSVPMorale",L)
											end
										elseif SN > "VIRTCOMPASSIONARMOUR" then
											if SN == "VIRTCOMPASSIONPHYMIT" then
												Result = CalcStat("VSPhyMitH",L)
											end
										else
											Result = CalcStat("VSArmourL",L)
										end
									elseif SN > "VIRTCOMPASSIONTACMIT" then
										if SN < "VIRTCONFIDENCECRITHIT" then
											if SN == "VIRTCOMPASSIONVPMORALE" then
												Result = CalcStat("VSVPMorale",L)
											end
										elseif SN > "VIRTCONFIDENCECRITHIT" then
											if SN == "VIRTCONFIDENCEEVADE" then
												Result = CalcStat("VSEvadeL",L)
											end
										else
											Result = CalcStat("VSCritHitH",L)
										end
									else
										Result = CalcStat("VSTacMitM",L)
									end
								else
									Result = CalcStat("VSVitalityL",L)
								end
							else
								if 1 <= Lp and Lm <= 5 then
									Result = DataTableValue({5,6,7,8,9},L)
								end
							end
						else
							Result = CalcStat("TomeTotalVitalityDec",L)-CalcStat("TomeTotalVitalityDec",L-1)
						end
					elseif SN > "VIRTCONFIDENCEFINESSE" then
						if SN < "VIRTHONOURVPMORALE" then
							if SN < "VIRTFIDELITYPHYMIT" then
								if SN < "VIRTDISCIPLINEINHEAL" then
									if SN < "VIRTDETERMINATIONCRITHIT" then
										if SN < "VIRTCONFIDENCEVPTACMAS" then
											if SN == "VIRTCONFIDENCEVPPHYMAS" then
												Result = CalcStat("VSVPPhyMas",L)
											end
										elseif SN > "VIRTCONFIDENCEVPTACMAS" then
											if SN == "VIRTDETERMINATIONAGILITY" then
												Result = CalcStat("VSAgilityH",L)
											end
										else
											Result = CalcStat("VSVPTacMas",L)
										end
									elseif SN > "VIRTDETERMINATIONCRITHIT" then
										if SN < "VIRTDETERMINATIONVPPHYMAS" then
											if SN == "VIRTDETERMINATIONPHYMAS" then
												Result = CalcStat("VSPhyMasM",L)
											end
										elseif SN > "VIRTDETERMINATIONVPPHYMAS" then
											if SN == "VIRTDETERMINATIONVPTACMAS" then
												Result = CalcStat("VSVPTacMas",L)
											end
										else
											Result = CalcStat("VSVPPhyMas",L)
										end
									else
										Result = CalcStat("VSCritHitL",L)
									end
								elseif SN > "VIRTDISCIPLINEINHEAL" then
									if SN < "VIRTEMPATHYARMOUR" then
										if SN < "VIRTDISCIPLINERESIST" then
											if SN == "VIRTDISCIPLINEPHYMIT" then
												Result = CalcStat("VSPhyMitL",L)
											end
										elseif SN > "VIRTDISCIPLINERESIST" then
											if SN == "VIRTDISCIPLINEVPMORALE" then
												Result = CalcStat("VSVPMorale",L)
											end
										else
											Result = CalcStat("VSResistH",L)
										end
									elseif SN > "VIRTEMPATHYARMOUR" then
										if SN < "VIRTEMPATHYRESIST" then
											if SN == "VIRTEMPATHYCRITDEF" then
												Result = CalcStat("VSCritDefM",L)
											end
										elseif SN > "VIRTEMPATHYRESIST" then
											if SN == "VIRTEMPATHYVPMORALE" then
												Result = CalcStat("VSVPMorale",L)
											end
										else
											Result = CalcStat("VSResistL",L)
										end
									else
										Result = CalcStat("VSArmourH",L)
									end
								else
									Result = CalcStat("VSInHealM",L)
								end
							elseif SN > "VIRTFIDELITYPHYMIT" then
								if SN < "VIRTHONESTYCRITHIT" then
									if SN < "VIRTFORTITUDECRITDEF" then
										if SN < "VIRTFIDELITYVITALITY" then
											if SN == "VIRTFIDELITYTACMIT" then
												Result = CalcStat("VSTacMitH",L)
											end
										elseif SN > "VIRTFIDELITYVITALITY" then
											if SN == "VIRTFIDELITYVPMORALE" then
												Result = CalcStat("VSVPMorale",L)
											end
										else
											Result = CalcStat("VSVitalityM",L)
										end
									elseif SN > "VIRTFORTITUDECRITDEF" then
										if SN < "VIRTFORTITUDERESIST" then
											if SN == "VIRTFORTITUDEMORALE" then
												Result = CalcStat("VSMoraleH",L)
											end
										elseif SN > "VIRTFORTITUDERESIST" then
											if SN == "VIRTFORTITUDEVPMORALE" then
												Result = CalcStat("VSVPMorale",L)
											end
										else
											Result = CalcStat("VSResistL",L)
										end
									else
										Result = CalcStat("VSCritDefM",L)
									end
								elseif SN > "VIRTHONESTYCRITHIT" then
									if SN < "VIRTHONESTYWILL" then
										if SN < "VIRTHONESTYVPPHYMAS" then
											if SN == "VIRTHONESTYTACMAS" then
												Result = CalcStat("VSTacMasH",L)
											end
										elseif SN > "VIRTHONESTYVPPHYMAS" then
											if SN == "VIRTHONESTYVPTACMAS" then
												Result = CalcStat("VSVPTacMas",L)
											end
										else
											Result = CalcStat("VSVPPhyMas",L)
										end
									elseif SN > "VIRTHONESTYWILL" then
										if SN < "VIRTHONOURMORALE" then
											if SN == "VIRTHONOURCRITDEF" then
												Result = CalcStat("VSCritDefL",L)
											end
										elseif SN > "VIRTHONOURMORALE" then
											if SN == "VIRTHONOURTACMIT" then
												Result = CalcStat("VSTacMitM",L)
											end
										else
											Result = CalcStat("VSMoraleH",L)
										end
									else
										Result = CalcStat("VSWillM",L)
									end
								else
									Result = CalcStat("VSCritHitL",L)
								end
							else
								Result = CalcStat("VSPhyMitL",L)
							end
						elseif SN > "VIRTHONOURVPMORALE" then
							if SN < "VIRTLOYALTYVPMORALE" then
								if SN < "VIRTINNOCENCEVPMORALE" then
									if SN < "VIRTIDEALISMVPMORALE" then
										if SN < "VIRTIDEALISMINHEAL" then
											if SN == "VIRTIDEALISMFATE" then
												Result = CalcStat("VSFateH",L)
											end
										elseif SN > "VIRTIDEALISMINHEAL" then
											if SN == "VIRTIDEALISMMORALE" then
												Result = CalcStat("VSMoraleL",L)
											end
										else
											Result = CalcStat("VSInHealM",L)
										end
									elseif SN > "VIRTIDEALISMVPMORALE" then
										if SN < "VIRTINNOCENCERESIST" then
											if SN == "VIRTINNOCENCEPHYMIT" then
												Result = CalcStat("VSPhyMitH",L)
											end
										elseif SN > "VIRTINNOCENCERESIST" then
											if SN == "VIRTINNOCENCETACMIT" then
												Result = CalcStat("VSTacMitL",L)
											end
										else
											Result = CalcStat("VSResistM",L)
										end
									else
										Result = CalcStat("VSVPMorale",L)
									end
								elseif SN > "VIRTINNOCENCEVPMORALE" then
									if SN < "VIRTJUSTICEVPMORALE" then
										if SN < "VIRTJUSTICEMORALE" then
											if SN == "VIRTJUSTICEICMR" then
												Result = CalcStat("VSICMRH",L)
											end
										elseif SN > "VIRTJUSTICEMORALE" then
											if SN == "VIRTJUSTICETACMIT" then
												Result = CalcStat("VSTacMitL",L)
											end
										else
											Result = CalcStat("VSMoraleM",L)
										end
									elseif SN > "VIRTJUSTICEVPMORALE" then
										if SN < "VIRTLOYALTYINHEAL" then
											if SN == "VIRTLOYALTYARMOUR" then
												Result = CalcStat("VSArmourM",L)
											end
										elseif SN > "VIRTLOYALTYINHEAL" then
											if SN == "VIRTLOYALTYVITALITY" then
												Result = CalcStat("VSVitalityH",L)
											end
										else
											Result = CalcStat("VSInHealL",L)
										end
									else
										Result = CalcStat("VSVPMorale",L)
									end
								else
									Result = CalcStat("VSVPMorale",L)
								end
							elseif SN > "VIRTLOYALTYVPMORALE" then
								if SN < "VIRTPATIENCEVPMORALE" then
									if SN < "VIRTMERCYVPMORALE" then
										if SN < "VIRTMERCYFATE" then
											if SN == "VIRTMERCYEVADE" then
												Result = CalcStat("VSEvadeH",L)
											end
										elseif SN > "VIRTMERCYFATE" then
											if SN == "VIRTMERCYVITALITY" then
												Result = CalcStat("VSVitalityL",L)
											end
										else
											Result = CalcStat("VSFateM",L)
										end
									elseif SN > "VIRTMERCYVPMORALE" then
										if SN < "VIRTPATIENCEEVADE" then
											if SN == "VIRTPATIENCECRITHIT" then
												Result = CalcStat("VSCritHitL",L)
											end
										elseif SN > "VIRTPATIENCEEVADE" then
											if SN == "VIRTPATIENCEPOWER" then
												Result = CalcStat("VSPowerH",L)
											end
										else
											Result = CalcStat("VSEvadeM",L)
										end
									else
										Result = CalcStat("VSVPMorale",L)
									end
								elseif SN > "VIRTPATIENCEVPMORALE" then
									if SN < "VIRTTOLERANCERESIST" then
										if SN < "VIRTRNKCOSTTOT" then
											if SN == "VIRTRNKCOST" then
												if Lm <= 0 then
													Result = 0
												elseif Lm <= 10 then
													Result = 1000
												elseif Lm <= 60 then
													Result = RoundDbl(18*L+878,-2)
												elseif Lm <= 73 then
													Result = RoundDbl(18.75*L+878,-2)
												elseif Lm <= 90 then
													Result = RoundDbl(17.45*L+878,-2)
												else
													Result = 2500
												end
											end
										elseif SN > "VIRTRNKCOSTTOT" then
											if SN == "VIRTTOLERANCEPHYMIT" then
												Result = CalcStat("VSPhyMitL",L)
											end
										else
											if 1 <= Lp then
												Result = CalcStat("VirtRnkCostTot",L-1)+CalcStat("VirtRnkCost",L)
											end
										end
									elseif SN > "VIRTTOLERANCERESIST" then
										if SN < "VIRTTOLERANCEVPMORALE" then
											if SN == "VIRTTOLERANCETACMIT" then
												Result = CalcStat("VSTacMitH",L)
											end
										elseif SN > "VIRTTOLERANCEVPMORALE" then
											if SN > "VIRTVALOURCRITHIT" then
												if SN == "VIRTVALOURFINESSE" then
													Result = CalcStat("VSFinesseM",L)
												end
											elseif SN == "VIRTVALOURCRITHIT" then
												Result = CalcStat("VSCritHitL",L)
											end
										else
											Result = CalcStat("VSVPMorale",L)
										end
									else
										Result = CalcStat("VSResistM",L)
									end
								else
									Result = CalcStat("VSVPMorale",L)
								end
							else
								Result = CalcStat("VSVPMorale",L)
							end
						else
							Result = CalcStat("VSVPMorale",L)
						end
					else
						Result = CalcStat("VSFinesseM",L)
					end
				elseif SN > "VIRTVALOURPHYMAS" then
					if SN < "VSINHEALL" then
						if SN < "VMMASTERYPSV" then
							if SN < "VIRTZEALPHYMAS" then
								if SN < "VIRTWITCRITHIT" then
									if SN < "VIRTWISDOMTACMAS" then
										if SN < "VIRTVALOURVPTACMAS" then
											if SN == "VIRTVALOURVPPHYMAS" then
												Result = CalcStat("VSVPPhyMas",L)
											end
										elseif SN > "VIRTVALOURVPTACMAS" then
											if SN == "VIRTWISDOMFINESSE" then
												Result = CalcStat("VSFinesseL",L)
											end
										else
											Result = CalcStat("VSVPTacMas",L)
										end
									elseif SN > "VIRTWISDOMTACMAS" then
										if SN < "VIRTWISDOMVPTACMAS" then
											if SN == "VIRTWISDOMVPPHYMAS" then
												Result = CalcStat("VSVPPhyMas",L)
											end
										elseif SN > "VIRTWISDOMVPTACMAS" then
											if SN == "VIRTWISDOMWILL" then
												Result = CalcStat("VSWillH",L)
											end
										else
											Result = CalcStat("VSVPTacMas",L)
										end
									else
										Result = CalcStat("VSTacMasM",L)
									end
								elseif SN > "VIRTWITCRITHIT" then
									if SN < "VIRTWITVPPHYMAS" then
										if SN < "VIRTWITPHYMAS" then
											if SN == "VIRTWITFINESSE" then
												Result = CalcStat("VSFinesseH",L)
											end
										elseif SN > "VIRTWITPHYMAS" then
											if SN == "VIRTWITTACMAS" then
												Result = CalcStat("VSTacMasL",L)
											end
										else
											Result = CalcStat("VSPhyMasL",L)
										end
									elseif SN > "VIRTWITVPPHYMAS" then
										if SN < "VIRTZEALCRITHIT" then
											if SN == "VIRTWITVPTACMAS" then
												Result = CalcStat("VSVPTacMas",L)
											end
										elseif SN > "VIRTZEALCRITHIT" then
											if SN == "VIRTZEALMIGHT" then
												Result = CalcStat("VSMightH",L)
											end
										else
											Result = CalcStat("VSCritHitL",L)
										end
									else
										Result = CalcStat("VSVPPhyMas",L)
									end
								else
									Result = CalcStat("VSCritHitM",L)
								end
							elseif SN > "VIRTZEALPHYMAS" then
								if SN < "VITALITYCIRAW" then
									if SN < "VITALITYADJ" then
										if SN < "VIRTZEALVPTACMAS" then
											if SN == "VIRTZEALVPPHYMAS" then
												Result = CalcStat("VSVPPhyMas",L)
											end
										elseif SN > "VIRTZEALVPTACMAS" then
											if SN == "VITALITY" then
												Result = RoundDblDown(StatLinInter("PntMPVitality","ItemPntSVital","ProgBVitality","VitalityAdj",L,N,0))
											end
										else
											Result = CalcStat("VSVPTacMas",L)
										end
									elseif SN > "VITALITYADJ" then
										if SN < "VITALITYCI" then
											if SN == "VITALITYC" then
												Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("VitalityCI",CalcStat("VitalityCILvlFilter",N),N),0)
											end
										elseif SN > "VITALITYCI" then
											if SN == "VITALITYCILVLFILTER" then
												if 0 <= Lp and Lm <= 0 then
													Result = 515
												else
													Result = CalcStat("CreepILvlCurr",L)
												end
											end
										else
											Result = RoundDblLotro(CalcStat("VitalityCIRaw",L,N))
										end
									else
										if Lm <= 25 then
											Result = 0.5
										elseif Lm <= 50 then
											Result = 0.6
										elseif Lm <= 60 then
											Result = 0.7
										elseif Lm <= 79 then
											Result = 0.8
										elseif Lm <= 80 then
											Result = 0.9
										else
											Result = 1
										end
									end
								elseif SN > "VITALITYCIRAW" then
									if SN < "VMASTERY" then
										if SN < "VITALITYT" then
											if SN == "VITALITYCRAW" then
												Result = StatLinInter("","CreepTraitPntS","CreepTraitProgB","",L,CalcStat("VitalityCIRaw",CalcStat("VitalityCILvlFilter",N),N),99)
											end
										elseif SN > "VITALITYT" then
											if SN == "VITALITYTADJ" then
												if Lm <= 25 then
													Result = 0.5
												elseif Lm <= 50 then
													Result = 0.6
												elseif Lm <= 60 then
													Result = 0.7
												elseif Lm <= 65 then
													Result = 0.8
												elseif Lm <= 75 then
													Result = 0.9
												else
													Result = 1
												end
											end
										else
											Result = RoundDblDown(StatLinInter("PntMPVitalityT","TraitPntSVital","ProgBVitality","VitalityTAdj",L,N,0))
										end
									elseif SN > "VMASTERY" then
										if SN < "VMHIGH" then
											if SN == "VMASTERYOLD" then
												Result = CalcStat("VMastery",L,N)
											end
										elseif SN > "VMHIGH" then
											if SN == "VMLOW" then
												if 1 <= Lp then
													Result = CalcStat(C,CalcStat("VRnkToILvl",L),0.6)
												end
											end
										else
											if 1 <= Lp then
												Result = CalcStat(C,CalcStat("VRnkToILvl",L),2.0)
											end
										end
									else
										Result = EquSng(StatLinInter("PntMPMastery","ItemPntSVirtueMastery","ProgBMastery","AdjVirtueMas",L,N,0))
									end
								else
									Result = StatLinInter("PntMPVitalityC","ItemPntS","ProgBVitality","AdjCreepItem",L,N,4)
								end
							else
								Result = CalcStat("VSPhyMasM",L)
							end
						elseif SN > "VMMASTERYPSV" then
							if SN < "VSCRITHITH" then
								if SN < "VSAGILITYL" then
									if SN < "VRNKCAP" then
										if SN < "VMMORALEPSV" then
											if SN == "VMMEDIUM" then
												if 1 <= Lp then
													Result = CalcStat(C,CalcStat("VRnkToILvl",L),1.0)
												end
											end
										elseif SN > "VMMORALEPSV" then
											if SN == "VMORALE" then
												Result = EquSng(StatLinInter("PntMPMoraleVirtues","ItemPntSVirtueMorale","ProgBMorale","AdjVirtueMorale",L,N,0))
											end
										else
											if 1 <= Lp then
												Result = CalcStat("VMorale",CalcStat("VRnkToILvl",L),0.3)
											end
										end
									elseif SN > "VRNKCAP" then
										if SN < "VRNKTOILVL" then
											if SN == "VRNKLVLCAP" then
												if Lm <= 4 then
													Result = 2
												elseif Lm <= 110 then
													Result = RoundDblDown(L/2)
												elseif Lm <= 139 then
													Result = L-55
												elseif Lm <= 140 then
													Result = L-54
												elseif Lm <= 149 then
													Result = L-53
												else
													Result = 98
												end
											end
										elseif SN > "VRNKTOILVL" then
											if SN == "VSAGILITYH" then
												Result = CalcStat("VMHigh",L,"Agility")
											end
										else
											if Lm <= 0 then
												Result = 0
											elseif Lm <= 38 then
												Result = LinFmod(1,4,78,1,38,L)
											elseif Lm <= 48 then
												Result = LinFmod(1,78,178,38,48,L)
											elseif Lm <= 49 then
												Result = LinFmod(1,178,190,48,49,L)
											elseif Lm <= 50 then
												Result = LinFmod(1,190,210,49,50,L)
											elseif Lm <= 51 then
												Result = LinFmod(1,210,222,50,51,L)
											elseif Lm <= 52 then
												Result = LinFmod(1,222,236,51,52,L)
											elseif Lm <= 53 then
												Result = LinFmod(1,236,260,52,53,L)
											elseif Lm <= 55 then
												Result = LinFmod(1,260,292,53,55,L)
											elseif Lm <= 68 then
												Result = LinFmod(1,292,396,55,68,L)
											else
												Result = LinFmod(1,396,706,68,130,L)
											end
										end
									else
										Result = 96
									end
								elseif SN > "VSAGILITYL" then
									if SN < "VSARMOURM" then
										if SN < "VSARMOURH" then
											if SN == "VSAGILITYM" then
												Result = CalcStat("VMMedium",L,"Agility")
											end
										elseif SN > "VSARMOURH" then
											if SN == "VSARMOURL" then
												Result = CalcStat("VMLow",L,"Varmour")
											end
										else
											Result = CalcStat("VMHigh",L,"Varmour")
										end
									elseif SN > "VSARMOURM" then
										if SN < "VSCRITDEFL" then
											if SN == "VSCRITDEFH" then
												Result = CalcStat("VMHigh",L,"CritDef")
											end
										elseif SN > "VSCRITDEFL" then
											if SN == "VSCRITDEFM" then
												Result = CalcStat("VMMedium",L,"CritDef")
											end
										else
											Result = CalcStat("VMLow",L,"CritDef")
										end
									else
										Result = CalcStat("VMMedium",L,"Varmour")
									end
								else
									Result = CalcStat("VMLow",L,"Agility")
								end
							elseif SN > "VSCRITHITH" then
								if SN < "VSFATEM" then
									if SN < "VSEVADEL" then
										if SN < "VSCRITHITM" then
											if SN == "VSCRITHITL" then
												Result = CalcStat("VMLow",L,"CritHit")
											end
										elseif SN > "VSCRITHITM" then
											if SN == "VSEVADEH" then
												Result = CalcStat("VMHigh",L,"Evade")
											end
										else
											Result = CalcStat("VMMedium",L,"CritHit")
										end
									elseif SN > "VSEVADEL" then
										if SN < "VSFATEH" then
											if SN == "VSEVADEM" then
												Result = CalcStat("VMMedium",L,"Evade")
											end
										elseif SN > "VSFATEH" then
											if SN == "VSFATEL" then
												Result = CalcStat("VMLow",L,"Fate")
											end
										else
											Result = CalcStat("VMHigh",L,"Fate")
										end
									else
										Result = CalcStat("VMLow",L,"Evade")
									end
								elseif SN > "VSFATEM" then
									if SN < "VSICMRH" then
										if SN < "VSFINESSEL" then
											if SN == "VSFINESSEH" then
												Result = CalcStat("VMHigh",L,"Finesse")
											end
										elseif SN > "VSFINESSEL" then
											if SN == "VSFINESSEM" then
												Result = CalcStat("VMMedium",L,"Finesse")
											end
										else
											Result = CalcStat("VMLow",L,"Finesse")
										end
									elseif SN > "VSICMRH" then
										if SN < "VSICMRM" then
											if SN == "VSICMRL" then
												Result = CalcStat("VMLow",L,"ICMR")
											end
										elseif SN > "VSICMRM" then
											if SN == "VSINHEALH" then
												Result = CalcStat("VMHigh",L,"InHeal")
											end
										else
											Result = CalcStat("VMMedium",L,"ICMR")
										end
									else
										Result = CalcStat("VMHigh",L,"ICMR")
									end
								else
									Result = CalcStat("VMMedium",L,"Fate")
								end
							else
								Result = CalcStat("VMHigh",L,"CritHit")
							end
						else
							if 1 <= Lp then
								Result = CalcStat("VMastery",CalcStat("VRnkToILvl",L),0.2)
							end
						end
					elseif SN > "VSINHEALL" then
						if SN < "VSWILLH" then
							if SN < "VSPOWERM" then
								if SN < "VSPHYMASH" then
									if SN < "VSMIGHTM" then
										if SN < "VSMIGHTH" then
											if SN == "VSINHEALM" then
												Result = CalcStat("VMMedium",L,"InHeal")
											end
										elseif SN > "VSMIGHTH" then
											if SN == "VSMIGHTL" then
												Result = CalcStat("VMLow",L,"Might")
											end
										else
											Result = CalcStat("VMHigh",L,"Might")
										end
									elseif SN > "VSMIGHTM" then
										if SN < "VSMORALEL" then
											if SN == "VSMORALEH" then
												Result = CalcStat("VMHigh",L,"VMorale")
											end
										elseif SN > "VSMORALEL" then
											if SN == "VSMORALEM" then
												Result = CalcStat("VMMedium",L,"VMorale")
											end
										else
											Result = CalcStat("VMLow",L,"VMorale")
										end
									else
										Result = CalcStat("VMMedium",L,"Might")
									end
								elseif SN > "VSPHYMASH" then
									if SN < "VSPHYMITL" then
										if SN < "VSPHYMASM" then
											if SN == "VSPHYMASL" then
												Result = CalcStat("VMLow",L,"PhyMas")
											end
										elseif SN > "VSPHYMASM" then
											if SN == "VSPHYMITH" then
												Result = CalcStat("VMHigh",L,"PhyMit")
											end
										else
											Result = CalcStat("VMMedium",L,"PhyMas")
										end
									elseif SN > "VSPHYMITL" then
										if SN < "VSPOWERH" then
											if SN == "VSPHYMITM" then
												Result = CalcStat("VMMedium",L,"PhyMit")
											end
										elseif SN > "VSPOWERH" then
											if SN == "VSPOWERL" then
												Result = CalcStat("VMLow",L,"Power")
											end
										else
											Result = CalcStat("VMHigh",L,"Power")
										end
									else
										Result = CalcStat("VMLow",L,"PhyMit")
									end
								else
									Result = CalcStat("VMHigh",L,"PhyMas")
								end
							elseif SN > "VSPOWERM" then
								if SN < "VSTACMITL" then
									if SN < "VSTACMASH" then
										if SN < "VSRESISTL" then
											if SN == "VSRESISTH" then
												Result = CalcStat("VMHigh",L,"Resist")
											end
										elseif SN > "VSRESISTL" then
											if SN == "VSRESISTM" then
												Result = CalcStat("VMMedium",L,"Resist")
											end
										else
											Result = CalcStat("VMLow",L,"Resist")
										end
									elseif SN > "VSTACMASH" then
										if SN < "VSTACMASM" then
											if SN == "VSTACMASL" then
												Result = CalcStat("VMLow",L,"TacMas")
											end
										elseif SN > "VSTACMASM" then
											if SN == "VSTACMITH" then
												Result = CalcStat("VMHigh",L,"TacMit")
											end
										else
											Result = CalcStat("VMMedium",L,"TacMas")
										end
									else
										Result = CalcStat("VMHigh",L,"TacMas")
									end
								elseif SN > "VSTACMITL" then
									if SN < "VSVITALITYM" then
										if SN < "VSVITALITYH" then
											if SN == "VSTACMITM" then
												Result = CalcStat("VMMedium",L,"TacMit")
											end
										elseif SN > "VSVITALITYH" then
											if SN == "VSVITALITYL" then
												Result = CalcStat("VMLow",L,"Vitality")
											end
										else
											Result = CalcStat("VMHigh",L,"Vitality")
										end
									elseif SN > "VSVITALITYM" then
										if SN < "VSVPPHYMAS" then
											if SN == "VSVPMORALE" then
												Result = CalcStat("VMMoralePsv",L)
											end
										elseif SN > "VSVPPHYMAS" then
											if SN == "VSVPTACMAS" then
												Result = CalcStat("VMMasteryPsv",L)
											end
										else
											Result = CalcStat("VMMasteryPsv",L)
										end
									else
										Result = CalcStat("VMMedium",L,"Vitality")
									end
								else
									Result = CalcStat("VMLow",L,"TacMit")
								end
							else
								Result = CalcStat("VMMedium",L,"Power")
							end
						elseif SN > "VSWILLH" then
							if SN < "WARDENCDBASEICMR" then
								if SN < "WARDENCDAGILITYTOPHYMIT" then
									if SN < "WARDENCDAGILITYTOCRITHIT" then
										if SN < "VSWILLM" then
											if SN == "VSWILLL" then
												Result = CalcStat("VMLow",L,"Will")
											end
										elseif SN > "VSWILLM" then
											if SN == "WARDENCDAGILITYTOBLOCK" then
												Result = 2
											end
										else
											Result = CalcStat("VMMedium",L,"Will")
										end
									elseif SN > "WARDENCDAGILITYTOCRITHIT" then
										if SN < "WARDENCDAGILITYTOPARRY" then
											if SN == "WARDENCDAGILITYTOOUTHEAL" then
												Result = 3
											end
										elseif SN > "WARDENCDAGILITYTOPARRY" then
											if SN == "WARDENCDAGILITYTOPHYMAS" then
												Result = 3
											end
										else
											Result = 1
										end
									else
										Result = 1
									end
								elseif SN > "WARDENCDAGILITYTOPHYMIT" then
									if SN < "WARDENCDARMOURTOTACMIT" then
										if SN < "WARDENCDARMOURTOCOMPHYMIT" then
											if SN == "WARDENCDAGILITYTOTACMIT" then
												Result = 1
											end
										elseif SN > "WARDENCDARMOURTOCOMPHYMIT" then
											if SN == "WARDENCDARMOURTONONPHYMIT" then
												Result = 0.2
											end
										else
											Result = 1
										end
									elseif SN > "WARDENCDARMOURTOTACMIT" then
										if SN < "WARDENCDBASEAGILITY" then
											if SN == "WARDENCDARMOURTYPE" then
												Result = 2
											end
										elseif SN > "WARDENCDBASEAGILITY" then
											if SN == "WARDENCDBASEFATE" then
												Result = CalcStat("ClassBaseFate",L)
											end
										else
											Result = CalcStat("ClassBaseAgilityH",L)
										end
									else
										Result = 0.2
									end
								else
									Result = 1
								end
							elseif SN > "WARDENCDBASEICMR" then
								if SN < "WARDENCDBASEWILL" then
									if SN < "WARDENCDBASENCMR" then
										if SN < "WARDENCDBASEMIGHT" then
											if SN == "WARDENCDBASEICPR" then
												Result = CalcStat("ClassBaseICPR",L)
											end
										elseif SN > "WARDENCDBASEMIGHT" then
											if SN == "WARDENCDBASEMORALE" then
												Result = CalcStat("ClassBaseMorale",L)
											end
										else
											Result = CalcStat("ClassBaseMightM",L)
										end
									elseif SN > "WARDENCDBASENCMR" then
										if SN < "WARDENCDBASEPOWER" then
											if SN == "WARDENCDBASENCPR" then
												Result = CalcStat("ClassBaseNCPR",L)
											end
										elseif SN > "WARDENCDBASEPOWER" then
											if SN == "WARDENCDBASEVITALITY" then
												Result = CalcStat("ClassBaseVitality",L)
											end
										else
											Result = CalcStat("ClassBasePower",L)
										end
									else
										Result = CalcStat("ClassBaseNCMRH",L)
									end
								elseif SN > "WARDENCDBASEWILL" then
									if SN < "WARDENCDCANBLOCK" then
										if SN < "WARDENCDCALCTYPENONPHYMIT" then
											if SN == "WARDENCDCALCTYPECOMPHYMIT" then
												Result = 13
											end
										elseif SN > "WARDENCDCALCTYPENONPHYMIT" then
											if SN == "WARDENCDCALCTYPETACMIT" then
												Result = 26
											end
										else
											Result = 13
										end
									elseif SN > "WARDENCDCANBLOCK" then
										if SN < "WARDENCDFATETOPOWER" then
											if SN == "WARDENCDFATETONCPR" then
												Result = 0.07
											end
										elseif SN > "WARDENCDFATETOPOWER" then
											if SN > "WARDENCDHASPOWER" then
												if SN == "WARDENCDMIGHTTOBLOCK" then
													Result = 1
												end
											elseif SN == "WARDENCDHASPOWER" then
												Result = 1
											end
										else
											Result = 1
										end
									else
										Result = 1
									end
								else
									Result = CalcStat("ClassBaseWillL",L)
								end
							else
								Result = CalcStat("ClassBaseICMRH",L)
							end
						else
							Result = CalcStat("VMHigh",L,"Will")
						end
					else
						Result = CalcStat("VMLow",L,"InHeal")
					end
				else
					Result = CalcStat("VSPhyMasH",L)
				end
			elseif SN > "WARDENCDMIGHTTOCRITHIT" then
				if SN < "WORTHTABK" then
					if SN < "WORTHTABAQ" then
						if SN < "WORTHEXT" then
							if SN < "WARDINGLOREPHYMIT" then
								if SN < "WARDENCDVITALITYTOMORALE" then
									if SN < "WARDENCDPHYMITTOCOMPHYMIT" then
										if SN < "WARDENCDMIGHTTOOUTHEAL" then
											if SN == "WARDENCDMIGHTTOFINESSE" then
												Result = 1.5
											end
										elseif SN > "WARDENCDMIGHTTOOUTHEAL" then
											if SN == "WARDENCDMIGHTTOPHYMAS" then
												Result = 2
											end
										else
											Result = 2
										end
									elseif SN > "WARDENCDPHYMITTOCOMPHYMIT" then
										if SN < "WARDENCDTACMASTOOUTHEAL" then
											if SN == "WARDENCDPHYMITTONONPHYMIT" then
												Result = 1
											end
										elseif SN > "WARDENCDTACMASTOOUTHEAL" then
											if SN == "WARDENCDVITALITYTOICMR" then
												Result = 0.012
											end
										else
											Result = 1
										end
									else
										Result = 1
									end
								elseif SN > "WARDENCDVITALITYTOMORALE" then
									if SN < "WARDENCDWILLTOPHYMAS" then
										if SN < "WARDENCDWILLTOFINESSE" then
											if SN == "WARDENCDVITALITYTONCMR" then
												Result = 0.12
											end
										elseif SN > "WARDENCDWILLTOFINESSE" then
											if SN == "WARDENCDWILLTOOUTHEAL" then
												Result = 1
											end
										else
											Result = 1
										end
									elseif SN > "WARDENCDWILLTOPHYMAS" then
										if SN < "WARDENCDWILLTORESIST" then
											if SN == "WARDENCDWILLTOPHYMIT" then
												Result = 1.5
											end
										elseif SN > "WARDENCDWILLTORESIST" then
											if SN == "WARDENCDWILLTOTACMIT" then
												Result = 1.5
											end
										else
											Result = 1
										end
									else
										Result = 1
									end
								else
									Result = 4.5
								end
							elseif SN > "WARDINGLOREPHYMIT" then
								if SN < "WEAVERCDCALCTYPECOMPHYMIT" then
									if SN < "WARLEADERCDCALCTYPENONPHYMIT" then
										if SN < "WARLEADERCANBLOCK" then
											if SN == "WARDINGLORETACMIT" then
												if Lm <= 105 then
													Result = CalcStat("Mitigation",L,1.6)
												elseif 120 <= Lp and Lm <= 120 or 130 <= Lp and Lm <= 130 then
													Result = CalcStat("TacMitT",L,1.6)
												else
													Result = CalcStat("TacMitT",L,1.2)
												end
											end
										elseif SN > "WARLEADERCANBLOCK" then
											if SN == "WARLEADERCDCALCTYPECOMPHYMIT" then
												Result = 14
											end
										else
											Result = 1
										end
									elseif SN > "WARLEADERCDCALCTYPENONPHYMIT" then
										if SN < "WARLEADERCDHASPOWER" then
											if SN == "WARLEADERCDCALCTYPETACMIT" then
												Result = 27
											end
										elseif SN > "WARLEADERCDHASPOWER" then
											if SN == "WEAVERCANBLOCK" then
												Result = 1
											end
										else
											Result = 1
										end
									else
										Result = 14
									end
								elseif SN > "WEAVERCDCALCTYPECOMPHYMIT" then
									if SN < "WILL" then
										if SN < "WEAVERCDCALCTYPETACMIT" then
											if SN == "WEAVERCDCALCTYPENONPHYMIT" then
												Result = 14
											end
										elseif SN > "WEAVERCDCALCTYPETACMIT" then
											if SN == "WEAVERCDHASPOWER" then
												Result = 1
											end
										else
											Result = 27
										end
									elseif SN > "WILL" then
										if SN < "WILLCI" then
											if SN == "WILLC" then
												Result = CalcStat("MainC",L,N)
											end
										elseif SN > "WILLCI" then
											if SN == "WILLT" then
												Result = CalcStat("MainT",L,N)
											end
										else
											Result = CalcStat("MainCI",L,N)
										end
									else
										Result = CalcStat("Main",L,N)
									end
								else
									Result = 13
								end
							else
								if Lm <= 105 then
									Result = CalcStat("Mitigation",L,1.6)
								elseif 120 <= Lp and Lm <= 120 or 130 <= Lp and Lm <= 130 then
									Result = CalcStat("PhyMitT",L,1.6)
								else
									Result = CalcStat("PhyMitT",L,1.2)
								end
							end
						elseif SN > "WORTHEXT" then
							if SN < "WORTHTABAB" then
								if SN < "WORTHMPF" then
									if SN < "WORTHMPB" then
										if SN < "WORTHEXT8LIN" then
											if SN == "WORTHEXT4LIN" then
												if Lm <= 501 then
													Result = CalcStat("WorthExt",L,C)
												elseif Lm <= 601 then
													Result = CalcStat("WorthExt",501,C)+(L-501)*4
												end
											end
										elseif SN > "WORTHEXT8LIN" then
											if SN == "WORTHMPA" then
												if 1 <= Lp and Lm <= 5 then
													Result = EquSng(DataTableValue({1,1.1,1.15,1.2,1.3},L))
												end
											end
										else
											if Lm <= 501 then
												Result = CalcStat("WorthExt",L,C)
											elseif Lm <= 601 then
												Result = CalcStat("WorthExt",501,C)+(L-501)*8
											end
										end
									elseif SN > "WORTHMPB" then
										if SN < "WORTHMPD" then
											if SN == "WORTHMPC" then
												if 1 <= Lp and Lm <= 5 then
													Result = EquSng(DataTableValue({1,1,1,1,1},L))
												end
											end
										elseif SN > "WORTHMPD" then
											if SN == "WORTHMPE" then
												if 1 <= Lp and Lm <= 5 then
													Result = EquSng(DataTableValue({1,1.1,1.15,1.2,1.25},L))
												end
											end
										else
											if 1 <= Lp and Lm <= 5 then
												Result = EquSng(DataTableValue({1,1,1,2,3},L))
											end
										end
									else
										if 1 <= Lp and Lm <= 5 then
											Result = EquSng(DataTableValue({1,1.2,2,3,4},L))
										end
									end
								elseif SN > "WORTHMPF" then
									if SN < "WORTHMPJ" then
										if SN < "WORTHMPH" then
											if SN == "WORTHMPG" then
												if 1 <= Lp and Lm <= 5 then
													Result = EquSng(DataTableValue({1,2,3,4,5},L))
												end
											end
										elseif SN > "WORTHMPH" then
											if SN == "WORTHMPI" then
												if 1 <= Lp and Lm <= 5 then
													Result = EquSng(DataTableValue({1,2,2.5,3,10},L))
												end
											end
										else
											if 1 <= Lp and Lm <= 5 then
												Result = EquSng(DataTableValue({1,1.2,1.8,3.2,5},L))
											end
										end
									elseif SN > "WORTHMPJ" then
										if SN < "WORTHTABA" then
											if SN == "WORTHMPK" then
												if 1 <= Lp and Lm <= 5 then
													Result = EquSng(DataTableValue({1,1.2,1.3,1.35,1.4},L))
												end
											end
										elseif SN > "WORTHTABA" then
											if SN == "WORTHTABAA" then
												Result = CalcStat("WorthTabD",L)+20
											end
										else
											if Lm <= 1 then
												Result = 1
											else
												Result = CalcStat("WorthTabAF",L)
											end
										end
									else
										if 1 <= Lp and Lm <= 5 then
											Result = EquSng(DataTableValue({1,1,1,1,5},L))
										end
									end
								else
									if 1 <= Lp and Lm <= 5 then
										Result = EquSng(DataTableValue({0.5,1,1.25,1.5,2},L))
									end
								end
							elseif SN > "WORTHTABAB" then
								if SN < "WORTHTABAJ" then
									if SN < "WORTHTABAF" then
										if SN < "WORTHTABAD" then
											if SN == "WORTHTABAC" then
												Result = CalcStat("WorthTabE",L)-30
											end
										elseif SN > "WORTHTABAD" then
											if SN == "WORTHTABAE" then
												Result = CalcStat("WorthTabE",L)
											end
										else
											Result = 7*L+100
										end
									elseif SN > "WORTHTABAF" then
										if SN < "WORTHTABAH" then
											if SN == "WORTHTABAG" then
												Result = CalcStat("WorthTabAF",L)+25
											end
										elseif SN > "WORTHTABAH" then
											if SN == "WORTHTABAI" then
												if Lm <= 16 then
													Result = 10.73*L+54.3
												elseif Lm <= 34 then
													Result = 10.735*L+54
												elseif Lm <= 35 then
													Result = 429
												elseif Lm <= 41 then
													Result = 10.65*L+57.1
												elseif Lm <= 49 then
													Result = 10.7*L+55.3
												else
													Result = 9*L+141
												end
											end
										else
											if Lm <= 49 then
												Result = CalcStat("WorthTabALBase",L+7)-66
											else
												Result = 9*L+72
											end
										end
									else
										if Lm <= 49 then
											Result = 2.5*L
										else
											Result = 3*L-25
										end
									end
								elseif SN > "WORTHTABAJ" then
									if SN < "WORTHTABAM" then
										if SN < "WORTHTABAL" then
											if SN == "WORTHTABAK" then
												if Lm <= 49 then
													Result = CalcStat("WorthTabALBase",L+1)
												else
													Result = 9*L+78
												end
											end
										elseif SN > "WORTHTABAL" then
											if SN == "WORTHTABALBASE" then
												Result = 9.86*L+23.51+RoundDbl(L*0.1+0.3)*0.4
											end
										else
											if Lm <= 49 then
												Result = CalcStat("WorthTabALBase",L)
											else
												Result = 9*L+69
											end
										end
									elseif SN > "WORTHTABAM" then
										if SN < "WORTHTABAO" then
											if SN == "WORTHTABAN" then
												if Lm <= 50 then
													Result = 8.25*L+27.75
												else
													Result = 8*L+40
												end
											end
										elseif SN > "WORTHTABAO" then
											if SN == "WORTHTABAP" then
												Result = CalcStat("WorthTabAQ",L)
											end
										else
											Result = CalcStat("WorthTabE",L)
										end
									else
										Result = CalcStat("WorthTabB",L)
									end
								else
									Result = CalcStat("WorthTabAH",L)
								end
							else
								Result = 7*L+50
							end
						else
							if Lm <= 360 then
								Result = RoundDbl(CalcStat("StatC",L,C))
							elseif Lm <= 601 then
								Result = RoundDbl(CalcStat("StatC",L-1,C))
							end
						end
					elseif SN > "WORTHTABAQ" then
						if SN < "WORTHTABBU" then
							if SN < "WORTHTABBE" then
								if SN < "WORTHTABAY" then
									if SN < "WORTHTABAU" then
										if SN < "WORTHTABAS" then
											if SN == "WORTHTABAR" then
												Result = CalcStat("WorthTabD",L)+37.5
											end
										elseif SN > "WORTHTABAS" then
											if SN == "WORTHTABAT" then
												if Lm <= 4 then
													Result = RoundDbl(3*L+20,-1)
												elseif Lm <= 7 then
													Result = 60
												elseif Lm <= 10 then
													Result = 100
												elseif Lm <= 13 then
													Result = 180
												elseif Lm <= 16 then
													Result = 270
												elseif Lm <= 19 then
													Result = 310
												elseif Lm <= 40 then
													Result = RoundDbl(3.2*L+274,-1)
												elseif Lm <= 43 then
													Result = 400
												elseif Lm <= 53 then
													Result = RoundDbl(1.9*L+334,-1)
												elseif Lm <= 56 then
													Result = 460
												elseif Lm <= 59 then
													Result = 480
												else
													Result = 20*L-680
												end
											end
										else
											Result = CalcStat("WorthTabU",L)
										end
									elseif SN > "WORTHTABAU" then
										if SN < "WORTHTABAW" then
											if SN == "WORTHTABAV" then
												if Lm <= 4 then
													Result = RoundDbl(3*L+20,-1)
												elseif Lm <= 7 then
													Result = 70
												elseif Lm <= 10 then
													Result = 140
												elseif Lm <= 13 then
													Result = 270
												elseif Lm <= 16 then
													Result = 400
												elseif Lm <= 19 then
													Result = 460
												elseif Lm <= 25 then
													Result = RoundDbl(3*L+447.5,-1)
												elseif Lm <= 46 then
													Result = RoundDbl(3.2*L+455,-1)
												elseif Lm <= 50 then
													Result = 620
												else
													Result = 20*L-360
												end
											end
										elseif SN > "WORTHTABAW" then
											if SN == "WORTHTABAX" then
												if Lm <= 16 then
													Result = 10.75*L+54
												elseif Lm <= 34 then
													Result = 10.75*L+53.7
												elseif Lm <= 35 then
													Result = 429
												elseif Lm <= 41 then
													Result = 10.65*L+57.1
												elseif Lm <= 49 then
													Result = 10.68*L+56.25
												else
													Result = 12*L-9
												end
											end
										else
											if Lm <= 1 then
												Result = 50
											elseif Lm <= 49 then
												Result = 2.5*L+102.5
											elseif Lm <= 80 then
												Result = 3*L+78
											elseif Lm <= 120 then
												Result = 2.97*L+79.5
											else
												Result = 3*L+75
											end
										end
									else
										Result = CalcStat("WorthTabBN",L)*1.25
									end
								elseif SN > "WORTHTABAY" then
									if SN < "WORTHTABBA" then
										if SN < "WORTHTABAZBASE" then
											if SN == "WORTHTABAZ" then
												if Lm <= 10 then
													Result = CalcStat("WorthTabAZBase",L)*62.5
												elseif Lm <= 65 then
													Result = CalcStat("WorthTabAZBase",L)*125
												else
													Result = CalcStat("WorthTabAZBase",L)*25
												end
											end
										elseif SN > "WORTHTABAZBASE" then
											if SN == "WORTHTABB" then
												if Lm <= 50 then
													Result = 8.25*L+22.25
												else
													Result = 8*L+35
												end
											end
										else
											if Lm <= 44 then
												Result = RoundDbl(0.0525*L+0.7)
											elseif Lm <= 65 then
												Result = RoundDbl(0.19*L-4.85)
											elseif Lm <= 81 then
												Result = RoundDbl(0.19*L+28.15)
											else
												Result = RoundDbl(0.19*L+28.15+RoundDbl(L*0.05-4.55)*0.2)
											end
										end
									elseif SN > "WORTHTABBA" then
										if SN < "WORTHTABBC" then
											if SN == "WORTHTABBB" then
												if Lm <= 1 then
													Result = 40
												elseif Lm <= 10 then
													Result = RoundDbl(0.35*L-0.1)*20
												elseif Lm <= 13 then
													Result = 100
												elseif Lm <= 19 then
													Result = RoundDbl(0.35*L+1.6)*20
												elseif Lm <= 25 then
													Result = RoundDbl(2*L+150,-1)
												elseif Lm <= 40 then
													Result = RoundDbl(2*L+164,-1)
												elseif Lm <= 49 then
													Result = RoundDbl(L+201,-1)
												else
													Result = 20*L-740
												end
											end
										elseif SN > "WORTHTABBC" then
											if SN == "WORTHTABBD" then
												Result = CalcStat("WorthTabK",L)+1
											end
										else
											if Lm <= 34 then
												Result = RoundDbl(L/15+0.8)*3750+1250
											elseif Lm <= 35 then
												Result = 100000
											else
												Result = 125500
											end
										end
									else
										Result = 5*L+385
									end
								else
									Result = 5*L
								end
							elseif SN > "WORTHTABBE" then
								if SN < "WORTHTABBM" then
									if SN < "WORTHTABBI" then
										if SN < "WORTHTABBG" then
											if SN == "WORTHTABBF" then
												Result = CalcStat("WorthTabAV",L)+20
											end
										elseif SN > "WORTHTABBG" then
											if SN == "WORTHTABBH" then
												if Lm <= 80 then
													Result = RoundDbl(0.05*L-0.05)+RoundDbl(0.05*L+0.45)
												else
													Result = RoundDbl(0.05*L-0.1)+RoundDbl(0.05*L+0.45)
												end
											end
										else
											if Lm <= 7 then
												Result = RoundDbl(0.2*L-0.4)*2+1
											elseif Lm <= 16 then
												Result = RoundDbl(L/3-2)*6
											elseif Lm <= 22 then
												Result = RoundDbl(L/3+1)*3
											elseif Lm <= 25 then
												Result = RoundDbl(L/3+1)*3-2
											elseif Lm <= 80 then
												Result = RoundDbl(L/3+18)-2
											else
												Result = L-37
											end
										end
									elseif SN > "WORTHTABBI" then
										if SN < "WORTHTABBK" then
											if SN == "WORTHTABBJ" then
												Result = RoundDbl(0.1*L+0.45)*3
											end
										elseif SN > "WORTHTABBK" then
											if SN == "WORTHTABBL" then
												if Lm <= 35 then
													Result = 126600
												elseif Lm <= 46 then
													Result = 150600
												elseif Lm <= 47 then
													Result = 180720
												else
													Result = 150600
												end
											end
										else
											if Lm <= 10 then
												Result = RoundDbl(0.1*L+0.45)
											else
												Result = RoundDbl(0.1*L-0.6)*2
											end
										end
									else
										Result = CalcStat("WorthTabG",L)-25
									end
								elseif SN > "WORTHTABBM" then
									if SN < "WORTHTABBQ" then
										if SN < "WORTHTABBO" then
											if SN == "WORTHTABBN" then
												if Lm <= 1 then
													Result = 400
												else
													Result = 20*L+800
												end
											end
										elseif SN > "WORTHTABBO" then
											if SN == "WORTHTABBP" then
												if Lm <= 10 then
													Result = 156.25*L+1562.5
												elseif Lm <= 20 then
													Result = 312.5*L
												elseif Lm <= 30 then
													Result = 625*L-6250
												elseif Lm <= 40 then
													Result = 1250*L-25000
												else
													Result = 2500*L-75000
												end
											end
										else
											if Lm <= 10 then
												Result = 10
											elseif Lm <= 40 then
												Result = RoundDbl(0.1*L-0.55)*50-25
											elseif Lm <= 80 then
												Result = RoundDbl(0.1*L-0.55)*50
											else
												Result = RoundDbl(0.1*L-0.55)*25+175
											end
										end
									elseif SN > "WORTHTABBQ" then
										if SN < "WORTHTABBS" then
											if SN == "WORTHTABBR" then
												if Lm <= 49 then
													Result = CalcStat("WorthTabBQ",L)*2
												else
													Result = 4*L+250
												end
											end
										elseif SN > "WORTHTABBS" then
											if SN == "WORTHTABBT" then
												Result = 62500
											end
										else
											Result = CalcStat("WorthTabBR",L)*2
										end
									else
										if Lm <= 1 then
											Result = 50
										elseif Lm <= 49 then
											Result = RoundDbl(2.5*L+100)
										else
											Result = 3*L+75
										end
									end
								else
									if Lm <= 1 then
										Result = 10
									else
										Result = 20*L-20
									end
								end
							else
								if Lm <= 1 then
									Result = 60
								elseif Lm <= 7 then
									Result = RoundDbl(L/3)*40+30
								elseif Lm <= 13 then
									Result = RoundDbl(L/3)*130-210
								elseif Lm <= 19 then
									Result = RoundDbl(L/3)*60+140
								elseif Lm <= 25 then
									Result = RoundDbl(L/3)*10+480
								elseif Lm <= 46 then
									Result = RoundDbl(L/3)*10+490
								elseif Lm <= 50 then
									Result = 660
								else
									Result = 20*L-320
								end
							end
						elseif SN > "WORTHTABBU" then
							if SN < "WORTHTABCJ" then
								if SN < "WORTHTABCB" then
									if SN < "WORTHTABBY" then
										if SN < "WORTHTABBW" then
											if SN == "WORTHTABBV" then
												if Lm <= 29 then
													Result = 1250
												else
													Result = RoundDbl(0.05*L-1)*2500
												end
											end
										elseif SN > "WORTHTABBW" then
											if SN == "WORTHTABBX" then
												if Lm <= 10 then
													Result = RoundDbl(0.1*L+0.45)*3
												elseif Lm <= 140 then
													Result = RoundDbl(0.1*L-0.6)*6
												else
													Result = RoundDbl(0.1*L+0.4)*4+22
												end
											end
										else
											if Lm <= 1 then
												Result = 645
											elseif Lm <= 9 then
												Result = 20*L+980
											else
												Result = 50*L+920
											end
										end
									elseif SN > "WORTHTABBY" then
										if SN < "WORTHTABC" then
											if SN == "WORTHTABBZ" then
												if Lm <= 10 then
													Result = 27.42*L+273.1
												elseif Lm <= 20 then
													Result = 54.69*L
												elseif Lm <= 30 then
													Result = 109.35*L-1093
												elseif Lm <= 40 then
													Result = 218.75*L-4375
												elseif Lm <= 80 then
													Result = 437.5*L-13125
												else
													Result = 437*L-13085
												end
											end
										elseif SN > "WORTHTABC" then
											if SN == "WORTHTABCA" then
												if Lm <= 10 then
													Result = 7.25*L+72.25
												elseif Lm <= 20 then
													Result = 14.49*L+0.11
												elseif Lm <= 30 then
													Result = 29*L-290
												elseif Lm <= 35 then
													Result = 57.99*L-1160.16
												elseif Lm <= 40 then
													Result = 57.99*L-1160.12
												elseif Lm <= 80 then
													Result = 115.94*L-3478.2
												else
													Result = 116*L-3483
												end
											end
										else
											Result = CalcStat("WorthTabD",L)+20
										end
									else
										Result = 90000
									end
								elseif SN > "WORTHTABCB" then
									if SN < "WORTHTABCF" then
										if SN < "WORTHTABCD" then
											if SN == "WORTHTABCC" then
												Result = CalcStat("WorthTabBK",L)*5
											end
										elseif SN > "WORTHTABCD" then
											if SN == "WORTHTABCE" then
												Result = CalcStat("WorthTabBN",L)*10
											end
										else
											Result = CalcStat("WorthTabBK",L)*25
										end
									elseif SN > "WORTHTABCF" then
										if SN < "WORTHTABCH" then
											if SN == "WORTHTABCG" then
												Result = 20
											end
										elseif SN > "WORTHTABCH" then
											if SN == "WORTHTABCI" then
												Result = 40000
											end
										else
											Result = 50000
										end
									else
										if Lm <= 20 then
											Result = RoundDbl(0.1*L-0.55)*600+200
										elseif Lm <= 40 then
											Result = RoundDbl(0.1*L-0.55)*1000-500
										elseif Lm <= 60 then
											Result = RoundDbl(0.1*L-0.55)*2000-4000
										elseif Lm <= 70 then
											Result = 8500
										elseif Lm <= 140 then
											Result = RoundDbl(0.1*L-0.55)*2500-7500
										elseif Lm <= 200 then
											Result = RoundDbl(0.1*L-0.55)*3000-14000
										else
											Result = RoundDbl(0.1*L-0.55)*2500-3500
										end
									end
								else
									Result = 0.1
								end
							elseif SN > "WORTHTABCJ" then
								if SN < "WORTHTABCR" then
									if SN < "WORTHTABCN" then
										if SN < "WORTHTABCL" then
											if SN == "WORTHTABCK" then
												Result = 15000
											end
										elseif SN > "WORTHTABCL" then
											if SN == "WORTHTABCM" then
												Result = 7500
											end
										else
											Result = 12500
										end
									elseif SN > "WORTHTABCN" then
										if SN < "WORTHTABCP" then
											if SN == "WORTHTABCO" then
												Result = CalcStat("WorthTabAB",L)
											end
										elseif SN > "WORTHTABCP" then
											if SN == "WORTHTABCQ" then
												if Lm <= 10 then
													Result = RoundDbl(0.3*L+0.2)*2
												elseif Lm <= 16 then
													Result = RoundDbl(0.25*L-1)*6
												elseif Lm <= 22 then
													Result = RoundDbl(0.3*L+5.5)*2
												elseif Lm <= 50 then
													Result = RoundDbl((1/6)*L+8.75)*2
												elseif Lm <= 80 then
													Result = RoundDbl((1/3)*L-11.5)*6
												else
													Result = RoundDbl(0.25*L-4.6)*6
												end
											end
										else
											Result = 1
										end
									else
										Result = RoundDbl(0.1*L+0.5)*10000
									end
								elseif SN > "WORTHTABCR" then
									if SN < "WORTHTABF" then
										if SN < "WORTHTABD" then
											if SN == "WORTHTABCS" then
												Result = CalcStat("WorthTabBR",L)*3
											end
										elseif SN > "WORTHTABD" then
											if SN == "WORTHTABE" then
												if Lm <= 9 then
													Result = 30*L+50
												else
													Result = 7*L+280
												end
											end
										else
											if Lm <= 49 then
												Result = 7.5*L
											else
												Result = 8*L-25
											end
										end
									elseif SN > "WORTHTABF" then
										if SN < "WORTHTABH" then
											if SN == "WORTHTABG" then
												if Lm <= 1 then
													Result = 50
												else
													Result = CalcStat("WorthTabAF",L)+100
												end
											end
										elseif SN > "WORTHTABH" then
											if SN > "WORTHTABI" then
												if SN == "WORTHTABJ" then
													if Lm <= 4 then
														Result = 2.5*L+7.5
													elseif Lm <= 5 then
														Result = 23
													else
														Result = 4*L
													end
												end
											elseif SN == "WORTHTABI" then
												if Lm <= 4 then
													Result = 1
												elseif Lm <= 10 then
													Result = 0.7*L-1
												elseif Lm <= 15 then
													Result = 1.4*L-7
												elseif Lm <= 24 then
													Result = 1.25*L-5
												elseif Lm <= 49 then
													Result = 2.5*L-35
												else
													Result = 3*L-60
												end
											end
										else
											if Lm <= 2 then
												Result = L
											elseif Lm <= 9 then
												Result = 1.48*L-2.85
											elseif Lm <= 11 then
												Result = 2.5*L-13
											elseif Lm <= 24 then
												Result = 2.5*L-10
											else
												Result = 5*L-70
											end
										end
									else
										Result = 0.1
									end
								else
									Result = CalcStat("WorthTabM",L)-15
								end
							else
								Result = 20000
							end
						else
							if Lm <= 80 then
								Result = 20*L+300
							else
								Result = 10*L+1100
							end
						end
					else
						if Lm <= 10 then
							Result = 7.5*L+60
						elseif Lm <= 49 then
							Result = 5.5*L+80
						else
							Result = 6*L+55
						end
					end
				elseif SN > "WORTHTABK" then
					if SN < "WORTHVALBU" then
						if SN < "WORTHVALAP" then
							if SN < "WORTHVALA" then
								if SN < "WORTHTABS" then
									if SN < "WORTHTABO" then
										if SN < "WORTHTABM" then
											if SN == "WORTHTABL" then
												Result = CalcStat("WorthTabB",L)+19.25
											end
										elseif SN > "WORTHTABM" then
											if SN == "WORTHTABN" then
												Result = CalcStat("WorthTabAF",L)+25
											end
										else
											if Lm <= 9 then
												Result = 10*L+11
											elseif Lm <= 49 then
												Result = 4*L+65
											else
												Result = 5*L+15
											end
										end
									elseif SN > "WORTHTABO" then
										if SN < "WORTHTABQ" then
											if SN == "WORTHTABP" then
												Result = CalcStat("WorthTabE",L)
											end
										elseif SN > "WORTHTABQ" then
											if SN == "WORTHTABR" then
												if Lm <= 9 then
													Result = 12*L+30
												else
													Result = 7*L+75
												end
											end
										else
											Result = 7*L+25
										end
									else
										Result = CalcStat("WorthTabB",L)+11
									end
								elseif SN > "WORTHTABS" then
									if SN < "WORTHTABW" then
										if SN < "WORTHTABU" then
											if SN == "WORTHTABT" then
												if Lm <= 1 then
													Result = 54
												elseif Lm <= 17 then
													Result = 10.73*L+43.57
												elseif Lm <= 35 then
													Result = 10.735*L+43.265
												elseif Lm <= 36 then
													Result = 429
												elseif Lm <= 42 then
													Result = 10.65*L+46.45
												elseif Lm <= 49 then
													Result = 10.7*L+44.6
												else
													Result = 9*L+130
												end
											end
										elseif SN > "WORTHTABU" then
											if SN == "WORTHTABV" then
												Result = CalcStat("WorthTabB",L)-2.75
											end
										else
											if Lm <= 10 then
												Result = 9*L+20
											elseif Lm <= 49 then
												Result = 5.5*L+55
											else
												Result = 6*L+30
											end
										end
									elseif SN > "WORTHTABW" then
										if SN < "WORTHTABY" then
											if SN == "WORTHTABX" then
												Result = CalcStat("WorthTabAF",L)+75
											end
										elseif SN > "WORTHTABY" then
											if SN == "WORTHTABZ" then
												Result = CalcStat("WorthTabR",L)-15
											end
										else
											Result = CalcStat("WorthTabD",L)+30
										end
									else
										Result = CalcStat("WorthTabD",L)+25
									end
								else
									Result = CalcStat("WorthTabD",L)+17.5
								end
							elseif SN > "WORTHVALA" then
								if SN < "WORTHVALAH" then
									if SN < "WORTHVALAD" then
										if SN < "WORTHVALAB" then
											if SN == "WORTHVALAA" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAA")))
											end
										elseif SN > "WORTHVALAB" then
											if SN == "WORTHVALAC" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAC")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAB")))
										end
									elseif SN > "WORTHVALAD" then
										if SN < "WORTHVALAF" then
											if SN == "WORTHVALAE" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAE")))
											end
										elseif SN > "WORTHVALAF" then
											if SN == "WORTHVALAG" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAG")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAF")))
										end
									else
										Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAD")))
									end
								elseif SN > "WORTHVALAH" then
									if SN < "WORTHVALAL" then
										if SN < "WORTHVALAJ" then
											if SN == "WORTHVALAI" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt8Lin",L,"WorthTabAI")))
											end
										elseif SN > "WORTHVALAJ" then
											if SN == "WORTHVALAK" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt8Lin",L,"WorthTabAK")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt8Lin",L,"WorthTabAJ")))
										end
									elseif SN > "WORTHVALAL" then
										if SN < "WORTHVALAN" then
											if SN == "WORTHVALAM" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAM")))
											end
										elseif SN > "WORTHVALAN" then
											if SN == "WORTHVALAO" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAO")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAN")))
										end
									else
										Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt8Lin",L,"WorthTabAL")))
									end
								else
									Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt8Lin",L,"WorthTabAH")))
								end
							else
								Result = RoundDbl(EquSng(CalcStat("WorthMpA",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabA")))
							end
						elseif SN > "WORTHVALAP" then
							if SN < "WORTHVALBE" then
								if SN < "WORTHVALAX" then
									if SN < "WORTHVALAT" then
										if SN < "WORTHVALAR" then
											if SN == "WORTHVALAQ" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAQ")))
											end
										elseif SN > "WORTHVALAR" then
											if SN == "WORTHVALAS" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAS")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAR")))
										end
									elseif SN > "WORTHVALAT" then
										if SN < "WORTHVALAV" then
											if SN == "WORTHVALAU" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAU")))
											end
										elseif SN > "WORTHVALAV" then
											if SN == "WORTHVALAW" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpA",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAW")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAV")))
										end
									else
										Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAT")))
									end
								elseif SN > "WORTHVALAX" then
									if SN < "WORTHVALBA" then
										if SN < "WORTHVALAZ" then
											if SN == "WORTHVALAY" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpA",QualityCodeIndex(C))*CalcStat("WorthExt4Lin",L,"WorthTabAY")))
											end
										elseif SN > "WORTHVALAZ" then
											if SN == "WORTHVALB" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabB")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpA",QualityCodeIndex(C))*CalcStat("WorthExt4Lin",L,"WorthTabAZ")))
										end
									elseif SN > "WORTHVALBA" then
										if SN < "WORTHVALBC" then
											if SN == "WORTHVALBB" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBB")))
											end
										elseif SN > "WORTHVALBC" then
											if SN == "WORTHVALBD" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBD")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpE",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBC")))
										end
									else
										Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt4Lin",L,"WorthTabBA")))
									end
								else
									Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAX")))
								end
							elseif SN > "WORTHVALBE" then
								if SN < "WORTHVALBM" then
									if SN < "WORTHVALBI" then
										if SN < "WORTHVALBG" then
											if SN == "WORTHVALBF" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBF")))
											end
										elseif SN > "WORTHVALBG" then
											if SN == "WORTHVALBH" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt4Lin",L,"WorthTabBH")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpA",QualityCodeIndex(C))*CalcStat("WorthExt4Lin",L,"WorthTabBG")))
										end
									elseif SN > "WORTHVALBI" then
										if SN < "WORTHVALBK" then
											if SN == "WORTHVALBJ" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt4Lin",L,"WorthTabBJ")))
											end
										elseif SN > "WORTHVALBK" then
											if SN == "WORTHVALBL" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpE",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBL")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt4Lin",L,"WorthTabBK")))
										end
									else
										Result = RoundDbl(EquSng(CalcStat("WorthMpA",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBI")))
									end
								elseif SN > "WORTHVALBM" then
									if SN < "WORTHVALBQ" then
										if SN < "WORTHVALBO" then
											if SN == "WORTHVALBN" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBN")))
											end
										elseif SN > "WORTHVALBO" then
											if SN == "WORTHVALBP" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBP")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpG",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBO")))
										end
									elseif SN > "WORTHVALBQ" then
										if SN < "WORTHVALBS" then
											if SN == "WORTHVALBR" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpE",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBR")))
											end
										elseif SN > "WORTHVALBS" then
											if SN == "WORTHVALBT" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBT")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpE",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBS")))
										end
									else
										Result = RoundDbl(EquSng(CalcStat("WorthMpE",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBQ")))
									end
								else
									Result = RoundDbl(EquSng(CalcStat("WorthMpA",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBM")))
								end
							else
								Result = RoundDbl(EquSng(CalcStat("WorthMpJ",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBE")))
							end
						else
							Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabAP")))
						end
					elseif SN > "WORTHVALBU" then
						if SN < "WORTHVALJ" then
							if SN < "WORTHVALCJ" then
								if SN < "WORTHVALCB" then
									if SN < "WORTHVALBY" then
										if SN < "WORTHVALBW" then
											if SN == "WORTHVALBV" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpD",QualityCodeIndex(C))*CalcStat("WorthExt4Lin",L,"WorthTabBV")))
											end
										elseif SN > "WORTHVALBW" then
											if SN == "WORTHVALBX" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt4Lin",L,"WorthTabBX")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBW")))
										end
									elseif SN > "WORTHVALBY" then
										if SN < "WORTHVALC" then
											if SN == "WORTHVALBZ" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBZ")))
											end
										elseif SN > "WORTHVALC" then
											if SN == "WORTHVALCA" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabCA")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabC")))
										end
									else
										Result = RoundDbl(EquSng(CalcStat("WorthMpE",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabBY")))
									end
								elseif SN > "WORTHVALCB" then
									if SN < "WORTHVALCF" then
										if SN < "WORTHVALCD" then
											if SN == "WORTHVALCC" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt4Lin",L,"WorthTabCC")))
											end
										elseif SN > "WORTHVALCD" then
											if SN == "WORTHVALCE" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpH",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabCE")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt4Lin",L,"WorthTabCD")))
										end
									elseif SN > "WORTHVALCF" then
										if SN < "WORTHVALCH" then
											if SN == "WORTHVALCG" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabCG")))
											end
										elseif SN > "WORTHVALCH" then
											if SN == "WORTHVALCI" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabCI")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabCH")))
										end
									else
										Result = RoundDbl(EquSng(CalcStat("WorthMpA",QualityCodeIndex(C))*CalcStat("WorthExt4Lin",L,"WorthTabCF")))
									end
								else
									Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabCB")))
								end
							elseif SN > "WORTHVALCJ" then
								if SN < "WORTHVALCR" then
									if SN < "WORTHVALCN" then
										if SN < "WORTHVALCL" then
											if SN == "WORTHVALCK" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabCK")))
											end
										elseif SN > "WORTHVALCL" then
											if SN == "WORTHVALCM" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabCM")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabCL")))
										end
									elseif SN > "WORTHVALCN" then
										if SN < "WORTHVALCP" then
											if SN == "WORTHVALCO" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabCO")))
											end
										elseif SN > "WORTHVALCP" then
											if SN == "WORTHVALCQ" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpK",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabCQ")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpA",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabCP")))
										end
									else
										Result = RoundDbl(EquSng(CalcStat("WorthMpI",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabCN")))
									end
								elseif SN > "WORTHVALCR" then
									if SN < "WORTHVALF" then
										if SN < "WORTHVALD" then
											if SN == "WORTHVALCS" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpE",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabCS")))
											end
										elseif SN > "WORTHVALD" then
											if SN == "WORTHVALE" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabE")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabD")))
										end
									elseif SN > "WORTHVALF" then
										if SN < "WORTHVALH" then
											if SN == "WORTHVALG" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabG")))
											end
										elseif SN > "WORTHVALH" then
											if SN == "WORTHVALI" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpA",QualityCodeIndex(C))*CalcStat("WorthExt4Lin",L,"WorthTabI")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpA",QualityCodeIndex(C))*CalcStat("WorthExt4Lin",L,"WorthTabH")))
										end
									else
										Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabF")))
									end
								else
									Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabCR")))
								end
							else
								Result = RoundDbl(EquSng(CalcStat("WorthMpC",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabCJ")))
							end
						elseif SN > "WORTHVALJ" then
							if SN < "WORTHVALZ" then
								if SN < "WORTHVALR" then
									if SN < "WORTHVALN" then
										if SN < "WORTHVALL" then
											if SN == "WORTHVALK" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabK")))
											end
										elseif SN > "WORTHVALL" then
											if SN == "WORTHVALM" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabM")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabL")))
										end
									elseif SN > "WORTHVALN" then
										if SN < "WORTHVALP" then
											if SN == "WORTHVALO" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabO")))
											end
										elseif SN > "WORTHVALP" then
											if SN == "WORTHVALQ" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabQ")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabP")))
										end
									else
										Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabN")))
									end
								elseif SN > "WORTHVALR" then
									if SN < "WORTHVALV" then
										if SN < "WORTHVALT" then
											if SN == "WORTHVALS" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabS")))
											end
										elseif SN > "WORTHVALT" then
											if SN == "WORTHVALU" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabU")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt8Lin",L,"WorthTabT")))
										end
									elseif SN > "WORTHVALV" then
										if SN < "WORTHVALX" then
											if SN == "WORTHVALW" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabW")))
											end
										elseif SN > "WORTHVALX" then
											if SN == "WORTHVALY" then
												Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabY")))
											end
										else
											Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabX")))
										end
									else
										Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabV")))
									end
								else
									Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabR")))
								end
							elseif SN > "WORTHVALZ" then
								if SN < "WRDCRITDEF" then
									if SN < "WPNDMGMIN" then
										if SN < "WOUNDRESISTT" then
											if SN == "WOUNDRESIST" then
												Result = CalcStat("ResistAdd",L,N)
											end
										elseif SN > "WOUNDRESISTT" then
											if SN == "WPNDMGMAX" then
												Result = EquSng((2/(2-CalcStat("WpnDPSVarianceType",WpnCodeIndex(C,2))))*CalcStat("CombatBaseWpnDPS",L,C))
											end
										else
											Result = CalcStat("ResistAddT",L,N)
										end
									elseif SN > "WPNDMGMIN" then
										if SN < "WPNDPSVARIANCETYPE" then
											if SN == "WPNDPS" then
												Result = CalcStat("CombatBaseWpnDPS",L,C)
											end
										elseif SN > "WPNDPSVARIANCETYPE" then
											if SN == "WRDBATSTRIKESCRITDEF" then
												Result = -CalcStat("CritDefT",L,CalcStat("Trait123Choice",N)*0.4)
											end
										else
											if 1 <= Lp and Lm <= 3 then
												Result = EquSng(DataTableValue({0.25,0.25,0.25},L))
											end
										end
									else
										Result = EquSng(((2-2*CalcStat("WpnDPSVarianceType",WpnCodeIndex(C,2)))/(2-CalcStat("WpnDPSVarianceType",WpnCodeIndex(C,2))))*CalcStat("CombatBaseWpnDPS",L,C))
									end
								elseif SN > "WRDCRITDEF" then
									if SN < "WRDRECKLESSNCRITHIT" then
										if SN < "WRDIMPRBLADESPARRY" then
											if SN == "WRDFINESSE" then
												Result = CalcStat("FinesseT",L,CalcStat("Trait12345Choice",N)*0.4)
											end
										elseif SN > "WRDIMPRBLADESPARRY" then
											if SN == "WRDPHYMAS" then
												Result = CalcStat("PhyMasT",L,CalcStat("Trait123455Choice",N)*0.4)
											end
										else
											Result = CalcStat("ParryT",L,2.8)
										end
									elseif SN > "WRDRECKLESSNCRITHIT" then
										if SN < "WRDSHIELDTACTCRITDEF" then
											if SN == "WRDSHIELDMASBLOCK" then
												Result = CalcStat("BlockT",L,2.8)
											end
										elseif SN > "WRDSHIELDTACTCRITDEF" then
											if SN > "WRDSTDYOURGRBLOCK" then
												if SN == "WRDSTDYOURGRPARRY" then
													Result = CalcStat("ParryT",L,CalcStat("Trait1234Choice",N)*0.4)
												end
											elseif SN == "WRDSTDYOURGRBLOCK" then
												Result = CalcStat("BlockT",L,CalcStat("Trait1234Choice",N)*0.4)
											end
										else
											Result = CalcStat("CritDefT",L,2)
										end
									else
										Result = CalcStat("CritHitT",L,2.4)
									end
								else
									Result = CalcStat("CritDefT",L,1.0)
								end
							else
								Result = RoundDbl(EquSng(CalcStat("WorthMpB",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabZ")))
							end
						else
							Result = RoundDbl(EquSng(CalcStat("WorthMpA",QualityCodeIndex(C))*CalcStat("WorthExt",L,"WorthTabJ")))
						end
					else
						Result = RoundDbl(EquSng(CalcStat("WorthMpF",QualityCodeIndex(C))*CalcStat("WorthExt4Lin",L,"WorthTabBU")))
					end
				else
					if Lm <= 9 then
						Result = 12*L+24
					else
						Result = 7*L+74
					end
				end
			else
				Result = 1.5
			end
		else
			Result = CalcStat("MitHeavyPRatPCapR",L)
		end
	else
		Result = 1
	end

	return Result
end

-- to be used by other modules
-- misc.
p.trim = trim
-- floating point / rounding functions
p.DblCalcDev = DblCalcDev
p.RoundDbl = RoundDbl
p.RoundDblDown = RoundDblDown
p.RoundDblUp = RoundDblUp
p.RoundDblLotro = RoundDblLotro
p.RoundDblProg = RoundDblProg
p.EquSng = EquSng
p.DecSng = DecSng
-- calculation type functions
p.DataTableValue = DataTableValue
p.ExpFmod = ExpFmod
p.CalcPercAB = CalcPercAB
p.CalcRatAB = CalcRatAB
p.StatLinInter = StatLinInter
p.LinFmod = LinFmod
-- main function
p.CalcStat = CalcStat

-- ******************************* End CalcStat *******************************

-- ******************** Start Formatting/Display Support **********************

-- small number correction for display purposes only (like in-game)
local function correctvalue(nValue)
	if (nValue % 1) == 0 then
		return nValue -- don't adjust whole numbers
	elseif nValue < -DblCalcDev then
		return nValue-0.0002
	elseif nValue > DblCalcDev then
		return nValue+0.0002
	else
		return 0
	end
end

-- uses a template to output value(format ..ggggssscc) as currency (..gggg gold sss silver cc copper)
local function currencyvalue(nValue,frame,sTemplateTitle)
	local nTemp = mathfloor(nValue+0.5+DblCalcDev)
	local nCopper = nTemp%100
	nTemp = (nTemp-nCopper)/100
	local nSilver = nTemp%1000
	nTemp = (nTemp-nSilver)/1000
	local nGold = nTemp

	local aTemplateArgs
	if nGold > 0 then
		aTemplateArgs = {g=nGold,s=nSilver,c=nCopper}
	elseif nSilver > 0 then
		aTemplateArgs = {s=nSilver,c=nCopper}
	else
		aTemplateArgs = {c=nCopper}
	end

	return frame:expandTemplate{title=sTemplateTitle,args=aTemplateArgs}
end

local function adjustfordisplay(sOption,xValue,frame,bTable)
	local xTemp = xValue
	local bTableDisplay = false
	if type(bTable) == "boolean" then
		bTableDisplay = bTable
	end
	if type(xTemp) == "number" then
		-- optional display options for percentages
		-- for display purposes only (same as in-game)
		if sOption == "MULTIP" then
			-- multiplier percentage
			xTemp = correctvalue(xTemp-100)
		elseif sOption == "MULTIP100" then
			-- multiplier percentage & multiply by 100
			xTemp = correctvalue(xTemp*100-100)
		elseif sOption == "ADDP" then
			-- additive percentage
			xTemp = correctvalue(xTemp)
		elseif sOption == "ADDP100" then
			-- additive percentage & multiply by 100
			xTemp = correctvalue(xTemp*100)
		elseif sOption == "WORTH" then
			-- currency display
			if frame then
				if bTableDisplay then
					xTemp = currencyvalue(xTemp,frame,"Cost")
				else
					xTemp = currencyvalue(xTemp,frame,"Worth")
				end
			end
		elseif sOption == "CORR" then
			-- fractured value which needs a correction for rounded display
			xTemp = correctvalue(xTemp)
		elseif sOption == "NOADJ" then
			-- no adjustment
		end
	end
	return xTemp
end

local function AddCommas(pre,post) return pre..strreverse(strgsub(strreverse(post),"(%d%d%d)","%1,")) end
local function SplitDecimal(str) return strgsub(str,"^(%d)(%d+)",AddCommas) end
local function ReformatThousSep(str) return strgsub(str,"[%d%.]+",SplitDecimal) end

-- adds trailing zero removal option (set minimum precision): %.0.3f
-- adds thousand separator option to formatting: %'d
local function stringformatvalue(sFormat,xValue)
	if type(xValue) == "number" then
		local sPreFormat = sFormat

		local bPostThousSep = strfind(sPreFormat,"%%'")
		if bPostThousSep then
			sPreFormat = strgsub(sPreFormat,"%%'","%%")
		end

		local bPostFormatTrailZeroes = strfind(sPreFormat,".%d+.%d+%a")
		local nTrailZeroesMinPrec

		if bPostFormatTrailZeroes then
			local _, _, sTrailZeroesMinPrec = strfind(sPreFormat,".(%d+).%d+%a")
			nTrailZeroesMinPrec = tonumber(sTrailZeroesMinPrec)
			sPreFormat = strgsub(sPreFormat,".%d+(.%d+%a)","%1")
		end

		local sPostFormat = strformat(sPreFormat,xValue)

		if bPostFormatTrailZeroes then
			local sTrailZeroesGetDecimals = "%d+(.%d+)"
			local sTrailZeroesSetDecimals = "(%d+).%d+"
			local _, _, sDotDecimals = strfind(sPostFormat,sTrailZeroesGetDecimals)

			while sDotDecimals and #sDotDecimals > nTrailZeroesMinPrec+1 and strsub(sDotDecimals,-1,-1) == "0" do
				sDotDecimals = strsub(sDotDecimals,1,-2)
			end

			if sDotDecimals == "." then
				sPostFormat = strgsub(sPostFormat,sTrailZeroesSetDecimals,"%1")
			elseif sDotDecimals then
				sPostFormat = strgsub(sPostFormat,sTrailZeroesSetDecimals,"%1"..sDotDecimals)
			end
		end

		if bPostThousSep then
			sPostFormat = ReformatThousSep(sPostFormat)
		end

		return sPostFormat
	else
		return strformat(sFormat,xValue)
	end
end

local function findstatname(sStatName,aStats)
	for _, sStat in ipairs(aStats) do
		sSNmatch, sPmatch = strmatch(sStatName,"("..sStat..")(P?)")
		if sSNmatch and sPmatch ~= "P" then
			-- found statname and without p(ercent) behind it
			return true
		end
	end
	return false
end

local function statdefaultformat(sStatName)
	-- armour main stats: whole number with thousand separator
	if findstatname(sStatName,{"ARMOURLOW","CLOTHARMOUR"}) then
		return "%'d"
	end
	-- player level armour: whole number without thousand separator
	if findstatname(sStatName,{"ARMOUR%a+","%w+ARMOUR"}) then
		return "%.0f"
	end
	-- main stats: whole number with thousand separator
	if findstatname(sStatName,{"MAIN","AGILITY","FATE","MIGHT","VITALITY","WILL","ARMOUR"}) then
		return "%'d"
	end
	-- fractured stats: whole number with thousand separator
	if findstatname(sStatName,{"WPNDMGMIN","WPNDMGMAX","SKILLPOWERCOST"}) then
		return "%'.0f"
	end
	-- fractured stats: thousand separator and 1 decimal
	if findstatname(sStatName,{"WPNDPS"}) then
		return "%'.1f"
	end
	-- fractured stats: minimum no decimals and maximum 3 decimals
	if findstatname(sStatName,{"ICMR","ICPR","NCMR","NCPR","POWER"}) then
		return "%.0.3f"
	end
	-- default: whole number without thousand separator
	return "%.0f"
end

local function statdefaultdisplay(sStatName)
	if findstatname(sStatName,{"WORTHVAL"}) then
		return "WORTH"
	end
	return "CORR"
end

local function DisplayableStatValue(sSN,xValue,sFormat,sDisplay,frame,bTable)
	local result = xValue

	-- display option. default = "CORR" for numbers.
	local sStatDisplay = ""
	if sDisplay then
		sStatDisplay = sDisplay
	end
	if (sStatDisplay == "") and (type(result) == "number") then
		sStatDisplay = statdefaultdisplay(sSN,bTable)
	end
	if sStatDisplay ~= "" then
		result = adjustfordisplay(sStatDisplay,result,frame,bTable)
	end

	-- optional format string. default = "%.0f" for numbers.
	local sStatFormat = ""
	if sFormat then
		sStatFormat = sFormat
	end
	if (sStatFormat == "") and (type(result) == "number") then
		sStatFormat = statdefaultformat(sSN,bTable)
	end
	if sStatFormat ~= "" then
		result = stringformatvalue(sStatFormat,result,frame,bTable)
	end

	return result
end

local EXPRERR_AT_TRANSLATION = 1
local EXPRERR_AT_EXECUTION = 2
local EXPRERR_AT_INITIALIZATION = 3
-- Fields:
-- Source - text describing origin
-- Code - error code number
-- Message - error text
-- Detail - detailed description
-- Stage - Expressions stage
local function DisplayableError(e,nl)
	local sNewLine = "<br>"
	if nl then sNewLine = nl end
	local aDisplay = {}
	if e.Stage then
		local aErrStage = {"Translation error","Execution error","Initialization error"}
		tableinsert(aDisplay,aErrStage[e.Stage])
	else
		tableinsert(aDisplay,"Error")
	end
	if e.Source then
		tableinsert(aDisplay," in ")
		tableinsert(aDisplay,e.Source)
	end
	tableinsert(aDisplay,sNewLine)
	if e.Code then
		tableinsert(aDisplay,"Code: ")
		tableinsert(aDisplay,e.Code)
		if e.Message then
			tableinsert(aDisplay," (")
			tableinsert(aDisplay,e.Message)
			tableinsert(aDisplay,")")
		end
		tableinsert(aDisplay,sNewLine)
	elseif e.Message then
		tableinsert(aDisplay,e.Message)
		tableinsert(aDisplay,sNewLine)
	end
	if e.Detail then
		tableinsert(aDisplay,"Detail: ")
		tableinsert(aDisplay,e.Detail)
		tableinsert(aDisplay,sNewLine)
	end
	return tableconcat(aDisplay)
end

-- to be used by other modules
p.DisplayableStatValue = DisplayableStatValue
p.DisplayableError = DisplayableError

-- ********************* End Formatting/Display Support ***********************

-- *********************** Start CalcStat Expressions *************************

local ERR =
	{
		TOOMANYVARIABLES = {1, "Too many variables used"},
		SYNTAX = {2, "Syntax error"},
		INVALIDOPCOUNT = {3, "Invalid number of operands"},
		INVALIDOPTYPE = {4, "Invalid operand type"},
		OUTOFRANGE = {5, "Out of range"},
		EXECUTION = {6, "Execution error"},
		UNKNOWNUNARY = {7, "Unknown unary operator"},
		UNKNOWNBINARY = {8, "Unknown binary operator"},
		MISSINGBINARY = {9, "Missing binary operator"},
		MISSINGOPERAND = {10, "Unidentified operand"},
		UNKNOWNFUNCTION = {11, "Unknown function"},
		MISSINGEXPRESSION = {12, "Missing expression"},
		NONMATCHINGOPTYPE = {13, "Non-matching operand type"},
		UNINITIALIZEDVARIABLE = {14, "Uninitialized variable"},
		MAXPROCESSING = {15, "Reached maximum processing requests"},
		MISSINGSWITCHDEFAULT = {16, "Missing Switch Default expression"},
		MISSINGSWITCHCONDITION = {17, "Missing Switch Case condition"},
		SYNTAXSWITCH = {18, "Syntax error in Switch"},
		MISSINGASSIGNVARIABLE = {19, "Missing assignment variable"},
		MISSINGASSIGNSIGN = {20, "Missing assignment token '='"},
		MISSINGASSIGNEXPRESSION = {21, "Missing assignment expression"},
		MISSINGSESELDEFAULT = {22, "Missing SEsel Default expression"},
		PARAMGROUPSOVERFLOW = {23, "Too many parameter groups"},
		MISSINGPARAMGROUPS = {24, "Missing parameter group(s)"},
		SWITCHGROUPSOVERFLOW = {25, "Parameter group after Switch Default"},
		CALCSTATSHORTSYNTAX = {26, "Invalid stat reference"},
		CALCSTATSHORTDOUBLELVL = {27, "Double defined level in stat reference"},
		UNKNOWNERROR = {28, "Unknown error"},
		MISSINGTRANSLATION = {29, "Missing Translation object"},
		DOUBLEGRAPHKEY = {30, "Graph point Key already exists"}
	}

local TRANS_EXPRESSION = 1 -- source expression
local TRANS_EXPRWIP = 2 -- expression in various stages of decomposition during translation - will contain result operand [n] when successfully finished
local TRANS_RESULTOP = 3 -- index of result operand
local TRANS_ERROR = 4 -- encountered error during translation or execution
local TRANS_OPERATIONS = 5 -- extracted operations, to be performed on..
local TRANS_OPERANDS = 6 -- extracted operands
local TRANS_OPSOURCEIDX = 7 -- search index: key=operand source, value=operand index
local TRANS_VARIABLES = 8 -- extracted and preset variables
local TRANS_VARNAMEIDX = 9 -- search index: key=variable name, value=variable index
local TRANS_OPERANDREQUESTS = 10 -- processed number of operand requests
local TRANS_MAXOPERANDREQUESTS = 11 -- maximum number of operand requests allowed in each execution
local TRANS_EXECUTIONS = 12 -- number of executions run

local OPERAND_VALUE = 1 -- current value of operand
local OPERAND_OPERATION = 2 -- operation (index) which gives value to this operand (negative indicates a variable index instead)
local OPERAND_DEPENDSON = 3 -- set of variables (indexes) on which operand depends for it's value

local VAR_NAME = 1 -- name of variable
local VAR_VALUE = 2 -- current value of variable
local VAR_OPERANDS = 3 -- set of operands which depend on this variable

local OPERATION_DEFINITION = 1 -- index into aOperationDefs table
local OPERATION_OPERANDS = 2 -- parameter operand indexes into TRANS_OPERANDS
local OPERATION_RESULTOP = 3 -- result operand index into TRANS_OPERANDS

local OPERATION_FORMAT_UNARY = 1 -- like: operator op2 - always needs 1 operand
local OPERATION_FORMAT_BINARY = 2 -- like: op1 operator op2 - always needs 2 operands
local OPERATION_FORMAT_FUNCTION = 3 -- like functionname(op1,op2,op3,etc) - needs an unspecified number of operands
local OPERATION_FORMAT_SWITCH = 4 -- like Switch($L, case<=10: case>=100: 25, default: 13)
local OPERATION_FORMAT_WITH = 5 -- like With($A=@Agility#2, $B=20: IIf($A>$B,$A,$B))
local OPERATION_FORMAT_UNTIL = 6 -- like Until(init vars:loop vars:end condition:return value)
local OPERATION_FORMAT_WHILE = 7 -- like While(init vars:run condition:loop vars:return value)

local OPERATIONDEF_OPERATOR = 1 -- simple mathematical/logical or functions/branching/loops
local OPERATIONDEF_FORMAT = 2 -- type of operation
local OPERATIONDEF_EXECUTE = 3 -- execution function, which performs the operation
local aOperationDefs
-- Operation Definition 'sections' for optimized scanning
local nOpDefUnaryStart, nOpDefUnaryEnd = 1, 3
local nOpDefBinaryStart, nOpDefBinaryEnd = 4, 18
local nOpDefFunctionStart, nOpDefFunctionEnd = 19, 0

local TYPEBOOL = "boolean"
local TYPENUM = "number"
local TYPENUMBOOLSTR = "number;boolean;string"
local TYPENUMSTR = "number;string"
local TYPEOP1 = "operand1"
local TYPESTR = "string"

local function RaiseExternalError(aTranslation,e)
	if aTranslation[TRANS_EXECUTIONS] == 0 then
		e.Stage = EXPRERR_AT_TRANSLATION
	else
		e.Stage = EXPRERR_AT_EXECUTION
	end
	aTranslation[TRANS_ERROR] = e
	error(e,0)
end

local function SetExpressionsError(aTranslation,aERR,sDetail)
	local e = {}
	e.Source = "CalcStat:Expressions"
	if aTranslation[TRANS_EXECUTIONS] == 0 then
		e.Stage = EXPRERR_AT_TRANSLATION
	else
		e.Stage = EXPRERR_AT_EXECUTION
	end
	e.Code = aERR[1]
	e.Message = aERR[2]
	if sDetail then
		if trim(sDetail) ~= "" then
			e.Detail = sDetail
		end
	elseif trim(aTranslation[TRANS_EXPRWIP]) ~= "" then
		e.Detail = trim(aTranslation[TRANS_EXPRWIP])
	end
	aTranslation[TRANS_ERROR] = e
end

local function RaiseExpressionsError(aTranslation,aERR,sDetail)
	SetExpressionsError(aTranslation,aERR,sDetail)
	error(aTranslation[TRANS_ERROR],0)
end

-- to be used by public functions: return either a valid value/object or an Error object depending on internal error condition
local function ErrorProtectedCall(aTranslation,fProtFunction,xFuncParam)
	local bWithoutError, xResult = pcall(fProtFunction,aTranslation,xFuncParam)
	if bWithoutError then
		return xResult
	elseif type(xResult) == "table" then
		-- xResult is a CalcStat/Expressions error object
		return nil, xResult
	else
		-- might be a programming error
		SetExpressionsError(aTranslation,ERR.UNKNOWNERROR,xResult)
		return nil, aTranslation[TRANS_ERROR]
	end
end

-- executes a single operation and stores the outcome in a (intermediate) result operand
local function ExecuteOperation(aTranslation,aOperation)
	local xResult = aOperationDefs[aOperation[OPERATION_DEFINITION]][OPERATIONDEF_EXECUTE](aTranslation,aOperation)
	-- store result in result operand
	aTranslation[TRANS_OPERANDS][aOperation[OPERATION_RESULTOP]][OPERAND_VALUE] = xResult
end

local function GetOperandValue(aTranslation,nOp)
	if aTranslation[TRANS_OPERANDREQUESTS] >= aTranslation[TRANS_MAXOPERANDREQUESTS] then
		RaiseExpressionsError(aTranslation,ERR.MAXPROCESSING)
	end
	aTranslation[TRANS_OPERANDREQUESTS] = aTranslation[TRANS_OPERANDREQUESTS]+1
	local aOperand = aTranslation[TRANS_OPERANDS][nOp]
	if aOperand[OPERAND_VALUE] == nil then
		-- need to get the value from an operation (a constant would always have a value)
		if aOperand[OPERAND_OPERATION] < 0 then
			-- need to get value from variable
			local aVar = aTranslation[TRANS_VARIABLES][-aOperand[OPERAND_OPERATION]]
			if aVar[VAR_VALUE] == nil then
				RaiseExpressionsError(aTranslation,ERR.UNINITIALIZEDVARIABLE,"$"..aVar[VAR_NAME])
			end
			aOperand[OPERAND_VALUE] = aVar[VAR_VALUE]
		else
			-- we should get the value when we execute its operation
			ExecuteOperation(aTranslation,aTranslation[TRANS_OPERATIONS][aOperand[OPERAND_OPERATION]])
		end
	end
	return aOperand[OPERAND_VALUE]
end

local function SetVariableValue(aTranslation,nVar,xNewValue)
	local aVar = aTranslation[TRANS_VARIABLES][nVar]
	local xOldValue = aVar[VAR_VALUE]
	local bNew
	if type(xOldValue) ~= type(xNewValue) then
		bNew = true
	else
		bNew = (xOldValue ~= xNewValue)
	end
	if bNew then
		-- store new value
		aVar[VAR_VALUE] = xNewValue
		-- nullify registered operands values
		local aTransOperands = aTranslation[TRANS_OPERANDS]
		for nOp, _ in pairs(aVar[VAR_OPERANDS]) do
			-- sets value of registered operand to nil
			aTransOperands[nOp][OPERAND_VALUE] = nil
		end
		return xOldValue
	end
end

-- sets a variable(from it's operand) to a value and nullifies depending operands' values, so they'll be recalculated at execution time
local function SetExpressionVariableByOperand(aTranslation,nVarOpIdx,xNewValue)
	return SetVariableValue(aTranslation,-aTranslation[TRANS_OPERANDS][nVarOpIdx][OPERAND_OPERATION],xNewValue)
end

local function ErrorDisplayOperation(aOperation)
	local sDisp = aOperationDefs[aOperation[OPERATION_DEFINITION]][OPERATIONDEF_OPERATOR]
	if nOpDefUnaryStart <= aOperation[OPERATION_DEFINITION] and aOperation[OPERATION_DEFINITION] <= nOpDefUnaryEnd then return "Unary operation '"..sDisp.."'"
	elseif nOpDefBinaryStart <= aOperation[OPERATION_DEFINITION] and aOperation[OPERATION_DEFINITION] <= nOpDefBinaryEnd then return "Binary operation '"..sDisp.."'"
	elseif nOpDefFunctionStart <= aOperation[OPERATION_DEFINITION] and aOperation[OPERATION_DEFINITION] <= nOpDefFunctionEnd then return "Function '"..sDisp.."'"
	else return "" end
end

local function ErrorDisplayOperand(xOperand)
	if type(xOperand) == "string" then
		local sDisp = "\""..xOperand.."\""
		if #sDisp > 20 then
			return strsub(sDisp,1,18)..".."
		else
			return sDisp
		end
	elseif type(xOperand) == "boolean" then if xOperand then return "True" else return "False" end
	else return ""..xOperand end
end

local PARAMDEF_TYPE = 1 -- allowed operand type(s)
local PARAMDEF_REQUIRED = 2 -- parameter/operand is required (optional if false)
local PARAMDEF_DEFAULT = 3 -- default value

-- executes operation function on provided operands under constraints of parameter definitions
local function ExecDefault(aTranslation,aOperation,fTheFunc,aParamDefs)
	local aOperands = aOperation[OPERATION_OPERANDS]
	local nOpCount = #aOperands
	local nOpMinCount, nOpMaxCount = 0, #aParamDefs
	for _, aParamDef in ipairs(aParamDefs) do
		if aParamDef[PARAMDEF_REQUIRED] then
			nOpMinCount = nOpMinCount+1
		else
			break -- remainder must be non-required - no need to check further
		end
	end
	if nOpCount < nOpMinCount or nOpMaxCount < nOpCount  then
		if nOpMinCount == nOpMaxCount then
			RaiseExpressionsError(aTranslation,ERR.INVALIDOPCOUNT,ErrorDisplayOperation(aOperation).." [Operand count:"..nOpCount..", Expecting:"..nOpMinCount.."]")
		else
			RaiseExpressionsError(aTranslation,ERR.INVALIDOPCOUNT,ErrorDisplayOperation(aOperation).." [Operand count:"..nOpCount..", Expecting:"..nOpMinCount.."-"..nOpMaxCount.."]")
		end
	end
	local xOperand = {nil,nil,nil} -- maximum is 3 operands
	local sTypeParam, nTypeOp, sTypeOp
	for nParam, aParamDef in ipairs(aParamDefs) do
		if aParamDef[PARAMDEF_REQUIRED] or nParam <= nOpCount then
			xOperand[nParam] = GetOperandValue(aTranslation,aOperands[nParam])
			sTypeParam = type(xOperand[nParam])
			if strsub(aParamDef[PARAMDEF_TYPE],1,7) == "operand" then
				nTypeOp = tonumber(strsub(aParamDef[PARAMDEF_TYPE],8,-1))
				sTypeOp = type(xOperand[nTypeOp])
				if sTypeOp ~= sTypeParam then
					RaiseExpressionsError(aTranslation,ERR.NONMATCHINGOPTYPE,ErrorDisplayOperation(aOperation).." [Operand"..nParam.."("..ErrorDisplayOperand(xOperand[nParam])..")"..":"..sTypeParam..", Expecting same type as Operand"..nTypeOp.."("..ErrorDisplayOperand(xOperand[nTypeOp])..")"..":"..sTypeOp.."]")
				end
			else
				if not strfind(aParamDef[PARAMDEF_TYPE],sTypeParam) then
					RaiseExpressionsError(aTranslation,ERR.INVALIDOPTYPE,ErrorDisplayOperation(aOperation).." [Operand"..nParam.."("..ErrorDisplayOperand(xOperand[nParam])..")"..":"..sTypeParam..", Expecting:"..aParamDef[PARAMDEF_TYPE].."]")
				end
			end
		else
			xOperand[nParam] = aParamDef[PARAMDEF_DEFAULT]
		end
	end
	if xOperand[3] ~= nil then return fTheFunc(xOperand[1],xOperand[2],xOperand[3])
	elseif xOperand[2] ~= nil then return fTheFunc(xOperand[1],xOperand[2])
	elseif xOperand[1] ~= nil then return fTheFunc(xOperand[1])
	else return fTheFunc()
	end
end

-- executes a loop operation with pre-condition (While) or post-condition (Until)
local function ExecLoopOp(aTranslation,aOperation,bPreCondition)
	local aOperands = aOperation[OPERATION_OPERANDS]
	local xOperand, sTypeOp
	-- process initial variable assignments
	local nInitVarCount = GetOperandValue(aTranslation,aOperands[1])
	local nInitVarOpIdx = 2
	for nInitVarIdx = 1, nInitVarCount do
		xOperand = GetOperandValue(aTranslation,aOperands[nInitVarOpIdx+1])
		SetExpressionVariableByOperand(aTranslation,aOperands[nInitVarOpIdx],xOperand)
		nInitVarOpIdx = nInitVarOpIdx+2
	end
	-- init indexes
	local nLoopCondOpIdx
	local nLoopVarCount
	local nLoopVarOpIdxInit
	local nResultingOpIdx
	if bPreCondition then
		nLoopCondOpIdx = nInitVarOpIdx
		nLoopVarCount = GetOperandValue(aTranslation,aOperands[nInitVarOpIdx+1])
		nLoopVarOpIdxInit = nInitVarOpIdx+2
		nResultingOpIdx = nInitVarOpIdx+2+nLoopVarCount*2
	else
		nLoopVarCount = GetOperandValue(aTranslation,aOperands[nInitVarOpIdx])
		nLoopCondOpIdx = nInitVarOpIdx+nLoopVarCount*2+1
		nLoopVarOpIdxInit = nInitVarOpIdx+1
		nResultingOpIdx = nLoopCondOpIdx+1
	end
	local nLoopVarOpIdx
	while true do
		if bPreCondition then
			-- process pre-loop condition
			xOperand = GetOperandValue(aTranslation,aOperands[nLoopCondOpIdx])
			sTypeOp = type(xOperand)
			if not strfind(TYPEBOOL,sTypeOp) then
				RaiseExpressionsError(aTranslation,ERR.INVALIDOPTYPE,ErrorDisplayOperation(aOperation).." [Loop Condition Operand("..ErrorDisplayOperand(xOperand)..")"..":"..sTypeOp..", Expecting:"..TYPEBOOL.."]")
			end
			if not xOperand then
				break -- end of loop if false
			end
		end
		-- process loop variable assignments
		nLoopVarOpIdx = nLoopVarOpIdxInit
		for nLoopVarIdx = 1, nLoopVarCount do
			xOperand = GetOperandValue(aTranslation,aOperands[nLoopVarOpIdx+1])
			SetExpressionVariableByOperand(aTranslation,aOperands[nLoopVarOpIdx],xOperand)
			nLoopVarOpIdx = nLoopVarOpIdx+2
		end
		if not bPreCondition then
			-- process post-loop condition
			xOperand = GetOperandValue(aTranslation,aOperands[nLoopCondOpIdx])
			sTypeOp = type(xOperand)
			if not strfind(TYPEBOOL,sTypeOp) then
				RaiseExpressionsError(aTranslation,ERR.INVALIDOPTYPE,ErrorDisplayOperation(aOperation).." [Loop Condition Operand("..ErrorDisplayOperand(xOperand)..")"..":"..sTypeOp..", Expecting:"..TYPEBOOL.."]")
			end
			if xOperand then
				break -- end of loop if true
			end
		end
	end
	-- process result
	xOperand = GetOperandValue(aTranslation,aOperands[nResultingOpIdx])
	return xOperand
end

-- list of operation definitions
-- longer function names/operators should come first in the list if one starts with the other: like '<=' before '<' or 'ROUNDUP' before 'ROUND'

aOperationDefs = {

{"NOT",OPERATION_FORMAT_UNARY, -- 1
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,function(xOperand) return not xOperand end,{{TYPEBOOL,true}})
end
},

{"-",OPERATION_FORMAT_UNARY, -- 2
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,function(xOperand) return -xOperand end,{{TYPENUM,true}})
end
},

{"+",OPERATION_FORMAT_UNARY, -- 3
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,function(xOperand) return xOperand end,{{TYPENUM,true}})
end
},

{"..",OPERATION_FORMAT_BINARY, -- 4
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,
		function(xOperand1,xOperand2)
			if type(xOperand1) == "boolean" then
				if xOperand1 then
					xOperand1 = "True"
				else
					xOperand1 = "False"
				end
			end
			if type(xOperand2) == "boolean" then
				if xOperand2 then
					xOperand2 = "True"
				else
					xOperand2 = "False"
				end
			end
			return xOperand1..""..xOperand2
		end,
		{{TYPENUMBOOLSTR,true},{TYPENUMBOOLSTR,true}})
end
},

{"OR",OPERATION_FORMAT_BINARY, -- 5
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,function(xOperand1,xOperand2) return xOperand1 or xOperand2 end,{{TYPEBOOL,true},{TYPEBOOL,true}})
end
},

{"AND",OPERATION_FORMAT_BINARY, -- 6
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,function(xOperand1,xOperand2) return xOperand1 and xOperand2 end,{{TYPEBOOL,true},{TYPEBOOL,true}})
end
},

{">=",OPERATION_FORMAT_BINARY, -- 7
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,function(xOperand1,xOperand2) return xOperand1 >= xOperand2 end,{{TYPENUMSTR,true},{TYPEOP1,true}})
end
},

{"<=",OPERATION_FORMAT_BINARY, -- 8
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,function(xOperand1,xOperand2) return xOperand1 <= xOperand2 end,{{TYPENUMSTR,true},{TYPEOP1,true}})
end
},

{"==",OPERATION_FORMAT_BINARY, -- 9
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,function(xOperand1,xOperand2) return xOperand1 == xOperand2 end,{{TYPENUMSTR,true},{TYPEOP1,true}})
end
},

{"~=",OPERATION_FORMAT_BINARY, -- 10
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,function(xOperand1,xOperand2) return xOperand1 ~= xOperand2 end,{{TYPENUMSTR,true},{TYPEOP1,true}})
end
},

{">",OPERATION_FORMAT_BINARY, -- 11
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,function(xOperand1,xOperand2) return xOperand1 > xOperand2 end,{{TYPENUMSTR,true},{TYPEOP1,true}})
end
},

{"<",OPERATION_FORMAT_BINARY, -- 12
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,function(xOperand1,xOperand2) return xOperand1 < xOperand2 end,{{TYPENUMSTR,true},{TYPEOP1,true}})
end
},

{"-",OPERATION_FORMAT_BINARY, -- 13
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,function(xOperand1,xOperand2) return xOperand1 - xOperand2 end,{{TYPENUM,true},{TYPENUM,true}})
end
},

{"+",OPERATION_FORMAT_BINARY, -- 14
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,function(xOperand1,xOperand2) return xOperand1 + xOperand2 end,{{TYPENUM,true},{TYPENUM,true}})
end
},

{"%",OPERATION_FORMAT_BINARY, -- 15
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,function(xOperand1,xOperand2) return xOperand1 % xOperand2 end,{{TYPENUM,true},{TYPENUM,true}})
end
},

{"*",OPERATION_FORMAT_BINARY, -- 16
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,function(xOperand1,xOperand2) return xOperand1 * xOperand2 end,{{TYPENUM,true},{TYPENUM,true}})
end
},

{"/",OPERATION_FORMAT_BINARY, -- 17
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,function(xOperand1,xOperand2) return xOperand1 / xOperand2 end,{{TYPENUM,true},{TYPENUM,true}})
end
},

{"^",OPERATION_FORMAT_BINARY, -- 18
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,function(xOperand1,xOperand2) return xOperand1 ^ xOperand2 end,{{TYPENUM,true},{TYPENUM,true}})
end
},

-- from here only functions -- 19

{"CALCSTAT",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,
		function(sStatName,nLvl,xNorC)
			local xResult, e = CalcStat(sStatName,nLvl,xNorC)
			if e then
				-- pass error encountered in CalcStat
				RaiseExternalError(aTranslation,e)
			end
			return xResult
		end,
		{{TYPESTR,true},{TYPENUM,false},{TYPENUMSTR,false}})
end
},

{"IIF",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	local aOperands = aOperation[OPERATION_OPERANDS]
	local nOpCount = #aOperands
	local nOpMinCount, nOpMaxCount = 3, 3
	if nOpCount < nOpMinCount or nOpMaxCount < nOpCount then
		RaiseExpressionsError(aTranslation,ERR.INVALIDOPCOUNT,ErrorDisplayOperation(aOperation).." [Operand count:"..nOpCount..", Expecting:"..nOpMinCount.."]")
	end
	local xOperand, sTypeOp
	xOperand = GetOperandValue(aTranslation,aOperands[1])
	sTypeOp = type(xOperand)
	if not strfind(TYPEBOOL,sTypeOp) then
		RaiseExpressionsError(aTranslation,ERR.INVALIDOPTYPE,ErrorDisplayOperation(aOperation).." [Condition Operand("..ErrorDisplayOperand(xOperand)..")"..":"..sTypeOp..", Expecting:"..TYPEBOOL.."]")
	end
	if xOperand then
		xOperand = GetOperandValue(aTranslation,aOperands[2])
	else
		xOperand = GetOperandValue(aTranslation,aOperands[3])
	end
	return xOperand
end
},

{"ABS",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,mathabs,{{TYPENUM,true}})
end
},

{"CEIL",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,mathceil,{{TYPENUM,true}})
end
},

{"FLOOR",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,mathfloor,{{TYPENUM,true}})
end
},

{"LOG10",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,mathlog10,{{TYPENUM,true}})
end
},

{"MAX",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,mathmax,{{TYPENUM,true},{TYPENUM,true}})
end
},

{"MIN",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,mathmin,{{TYPENUM,true},{TYPENUM,true}})
end
},

{"SQRT",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,mathsqrt,{{TYPENUM,true}})
end
},

{"AFD",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,
		function(xOperand1,xOperand2)
			return adjustfordisplay(strupper(xOperand2),xOperand1)
		end,
		{{TYPENUMBOOLSTR,true},{TYPESTR,false,"CORR"}})
end
},

{"FORMAT",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,
		function(xOperand1,xOperand2)
			if xOperand2 == nil then
				if type(xOperand1) == "number" then
					xOperand2 = "%.0f" --default: number without decimals
				elseif type(xOperand1) == "string" then
					xOperand2 = "%s" --default: just same string
				end
			end
			return stringformatvalue(xOperand2,xOperand1)
		end,
		{{TYPENUMSTR,true},{TYPESTR,false}})
end
},

{"SWITCH",OPERATION_FORMAT_SWITCH,
function (aTranslation,aOperation)
	local aOperands = aOperation[OPERATION_OPERANDS]
	local nOpCount = #aOperands
	local xOperand, sTypeOp
	for nOp = 1, nOpCount, 2 do
		-- process logical + result operand pairs
		-- default logical is a constant true, so will always be the result once encountered
		xOperand = GetOperandValue(aTranslation,aOperands[nOp])
		sTypeOp = type(xOperand)
		if not strfind(TYPEBOOL,sTypeOp) then
			RaiseExpressionsError(aTranslation,ERR.INVALIDOPTYPE,ErrorDisplayOperation(aOperation).." [Condition Operand("..ErrorDisplayOperand(xOperand)..")"..":"..sTypeOp..", Expecting:"..TYPEBOOL.."]")
		end
		if xOperand then
			xOperand = GetOperandValue(aTranslation,aOperands[nOp+1])
			return xOperand
		end
	end
end
},

{"SESEL",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	local aOperands = aOperation[OPERATION_OPERANDS]
	local nOpCount = #aOperands
	local nOpMinCount = 2
	if nOpCount < nOpMinCount then
		RaiseExpressionsError(aTranslation,ERR.INVALIDOPCOUNT,ErrorDisplayOperation(aOperation).." [Operand count:"..nOpCount..", Expecting at least:"..nOpMinCount.."(even number)]")
	end
	local xOperand, xCompOperand
	local sTypeParam, nTypeOp, sTypeOp
	nTypeOp = 1
	xCompOperand = GetOperandValue(aTranslation,aOperands[nTypeOp])
	sTypeOp = type(xCompOperand)
	if not strfind(TYPENUMSTR,sTypeOp) then
		RaiseExpressionsError(aTranslation,ERR.INVALIDOPTYPE,ErrorDisplayOperation(aOperation).." [Compare Operand("..ErrorDisplayOperand(xCompOperand)..")"..":"..sTypeOp..", Expecting:"..TYPENUMSTR.."]")
	end
	if sTypeOp == "number" then
		-- compare number value minus a little for small discrepancies
		-- like 79.0000001 should be treated like 79 so <= 79
		xCompOperand = xCompOperand-DblCalcDev
	end
	for nOp = 2, nOpCount, 2 do
		xOperand = GetOperandValue(aTranslation,aOperands[nOp])
		if nOp == nOpCount then
			-- last operand is default value
			return xOperand
		end
		sTypeParam = type(xOperand)
		if sTypeOp ~= sTypeParam then
			RaiseExpressionsError(aTranslation,ERR.NONMATCHINGOPTYPE,ErrorDisplayOperation(aOperation).." [Operand"..nOp.."("..ErrorDisplayOperand(xOperand)..")"..":"..sTypeParam..", Expecting same type as Compare Operand("..ErrorDisplayOperand(xCompOperand)..")"..":"..sTypeOp.."]")
		end
		if xCompOperand <= xOperand then
			xOperand = GetOperandValue(aTranslation,aOperands[nOp+1])
			return xOperand
		end
	end
	-- doesn't include a default operand
	RaiseExpressionsError(aTranslation,ERR.MISSINGSESELDEFAULT)
end
},

{"WITH",OPERATION_FORMAT_WITH,
function (aTranslation,aOperation)
	local aOperands = aOperation[OPERATION_OPERANDS]
	local xOperand
	-- process initial variable assignments
	local nInitVarCount = GetOperandValue(aTranslation,aOperands[1])
	local nInitVarOpIdx = 2
	for nInitVarIdx = 1, nInitVarCount do
		xOperand = GetOperandValue(aTranslation,aOperands[nInitVarOpIdx+1])
		SetExpressionVariableByOperand(aTranslation,aOperands[nInitVarOpIdx],xOperand)
		nInitVarOpIdx = nInitVarOpIdx+2
	end
	-- last operand is result value
	xOperand = GetOperandValue(aTranslation,aOperands[#aOperands])
	return xOperand
end
},

{"WHILE",OPERATION_FORMAT_WHILE,
function (aTranslation,aOperation)
	return ExecLoopOp(aTranslation,aOperation,true)
end
},

{"CHOOSE",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	local aOperands = aOperation[OPERATION_OPERANDS]
	local nOpCount = #aOperands
	local nOpMinCount = 2
	if nOpCount < nOpMinCount then
		RaiseExpressionsError(aTranslation,ERR.INVALIDOPCOUNT,ErrorDisplayOperation(aOperation).." [Operand count:"..nOpCount..", Expecting at least:"..nOpMinCount.."]")
	end
	local xOperand, sTypeOp
	xOperand = GetOperandValue(aTranslation,aOperands[1])
	sTypeOp = type(xOperand)
	if not strfind(TYPENUM,sTypeOp) then
		RaiseExpressionsError(aTranslation,ERR.INVALIDOPTYPE,ErrorDisplayOperation(aOperation).." [Index Operand("..ErrorDisplayOperand(xOperand)..")"..":"..sTypeOp..", Expecting:"..TYPENUM.."]")
	end
	xOperand = mathfloor(xOperand+0.5+DblCalcDev)
	if xOperand < 1 or nOpCount-1 < xOperand then
		RaiseExpressionsError(aTranslation,ERR.OUTOFRANGE,ErrorDisplayOperation(aOperation).." [Index Operand:"..ErrorDisplayOperand(xOperand)..", Expecting:1-"..(nOpCount-1).."]")
	end
	xOperand = GetOperandValue(aTranslation,aOperands[1+xOperand])
	return xOperand
end
},

{"REPLACE",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	local aOperands = aOperation[OPERATION_OPERANDS]
	local nOpCount = #aOperands
	local nOpMinCount = 3
	if nOpCount < nOpMinCount then
		RaiseExpressionsError(aTranslation,ERR.INVALIDOPCOUNT,ErrorDisplayOperation(aOperation).." [Operand count:"..nOpCount..", Expecting at least:"..nOpMinCount.."(odd number)]")
	end
	if nOpCount % 2 == 0 then
		RaiseExpressionsError(aTranslation,ERR.INVALIDOPCOUNT,ErrorDisplayOperation(aOperation).." [Operand count:"..nOpCount..", Expecting an odd number]")
	end
	local xOperand, sTypeOp
	xOperand = GetOperandValue(aTranslation,aOperands[1])
	sTypeOp = type(xOperand)
	if not strfind(TYPESTR,sTypeOp) then
		RaiseExpressionsError(aTranslation,ERR.INVALIDOPTYPE,ErrorDisplayOperation(aOperation).." [Source Operand("..ErrorDisplayOperand(xOperand)..")"..":"..sTypeOp..", Expecting:"..TYPESTR.."]")
	end
	local sResultText = xOperand
	local sSearchText, sReplacingText
	local sSearch, sReplace
	for nOp = 2, nOpCount, 2 do
		xOperand = GetOperandValue(aTranslation,aOperands[nOp])
		sTypeOp = type(xOperand)
		if not strfind(TYPESTR,sTypeOp) then
			RaiseExpressionsError(aTranslation,ERR.INVALIDOPTYPE,ErrorDisplayOperation(aOperation).." [Search Operand"..nOp.."("..ErrorDisplayOperand(xOperand)..")"..":"..sTypeOp..", Expecting:"..TYPESTR.."]")
		end
		sSearchText = xOperand
		if sSearchText ~= "" then
			xOperand = GetOperandValue(aTranslation,aOperands[nOp+1])
			sTypeOp = type(xOperand)
			if not strfind(TYPENUMBOOLSTR,sTypeOp) then
				RaiseExpressionsError(aTranslation,ERR.INVALIDOPTYPE,ErrorDisplayOperation(aOperation).." [Replace Operand"..(nOp+1).."("..ErrorDisplayOperand(xOperand)..")"..":"..sTypeOp..", Expecting:"..TYPENUMBOOLSTR.."]")
			end
			if type(xOperand) == "number" then
				sReplacingText = tostring(xOperand)
			elseif type(xOperand) == "boolean" then
				if xOperand then
					sReplacingText = "True"
				else
					sReplacingText = "False"
				end
			else
				sReplacingText = xOperand
			end
			sSearch = strgsub(sSearchText,"[%(%)%.%%%+%-%*%?%[%^%$%]]","%%%1")
			sReplace = strgsub(sReplacingText,"%%","%%%%")
			sResultText = strgsub(sResultText,sSearch,sReplace)
		end
	end
	return sResultText
end
},

{"GRAPHVAL",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	local aOperands = aOperation[OPERATION_OPERANDS]
	local nOpCount = #aOperands
	local nOpMinCount = 5 -- 1 for level + 2 * graphpoints (2)
	if nOpCount < nOpMinCount then
		RaiseExpressionsError(aTranslation,ERR.INVALIDOPCOUNT,ErrorDisplayOperation(aOperation).." [Operand count:"..nOpCount..", Expecting at least:"..nOpMinCount.."(odd number)]")
	end
	if nOpCount % 2 == 0 then
		RaiseExpressionsError(aTranslation,ERR.INVALIDOPCOUNT,ErrorDisplayOperation(aOperation).." [Operand count:"..nOpCount..", Expecting an odd number]")
	end
	local xOperand, sTypeOp
	xOperand = GetOperandValue(aTranslation,aOperands[1])
	sTypeOp = type(xOperand)
	if not strfind(TYPENUM,sTypeOp) then
		RaiseExpressionsError(aTranslation,ERR.INVALIDOPTYPE,ErrorDisplayOperation(aOperation).." [Key Operand("..ErrorDisplayOperand(xOperand)..")"..":"..sTypeOp..", Expecting:"..TYPENUM.."]")
	end
	local iKey = RoundDbl(xOperand) -- key should be a whole number
	local aGraphPoints = {}
	local aNewPoint
	for nOp = 2, nOpCount, 2 do
		aNewPoint = {}
		xOperand = GetOperandValue(aTranslation,aOperands[nOp])
		sTypeOp = type(xOperand)
		if not strfind(TYPENUM,sTypeOp) then
			RaiseExpressionsError(aTranslation,ERR.INVALIDOPTYPE,ErrorDisplayOperation(aOperation).." [Point Key Operand"..nOp.."("..ErrorDisplayOperand(xOperand)..")"..":"..sTypeOp..", Expecting:"..TYPENUM.."]")
		end
		aNewPoint.Key = RoundDbl(xOperand) -- key should be a whole number
		-- graph point key should be unique: check if already exists
		for _, aGraphPoint in pairs(aGraphPoints) do
			if aGraphPoint.Key == aNewPoint.Key then
				-- key already exists, double defined
				RaiseExpressionsError(aTranslation,ERR.DOUBLEGRAPHKEY,ErrorDisplayOperation(aOperation).." [Point Key Operand"..nOp.."("..ErrorDisplayOperand(xOperand)..")]")
			end
		end
		xOperand = GetOperandValue(aTranslation,aOperands[nOp+1])
		sTypeOp = type(xOperand)
		if not strfind(TYPENUM,sTypeOp) then
			RaiseExpressionsError(aTranslation,ERR.INVALIDOPTYPE,ErrorDisplayOperation(aOperation).." [Point Value Operand"..(nOp+1).."("..ErrorDisplayOperand(xOperand)..")"..":"..sTypeOp..", Expecting:"..TYPENUM.."]")
		end
		aNewPoint.Value = xOperand
		tableinsert(aGraphPoints,aNewPoint)
	end
	-- make sure that point keys are in ascending order
	tablesort(aGraphPoints,function(p1,p2) return p1.Key < p2.Key end)
	-- find key interval
	local iPointIndexSecond = 2
	local iPointIndexMax = #aGraphPoints
	while iPointIndexSecond < iPointIndexMax do
		if iKey <= aGraphPoints[iPointIndexSecond].Key then
			break
		end
		iPointIndexSecond = iPointIndexSecond+1
	end
	local iPointIndexFirst = iPointIndexSecond-1
	local aFirstPoint = aGraphPoints[iPointIndexFirst]
	local aSecondPoint = aGraphPoints[iPointIndexSecond]
	-- interpolate value
	return LinFmod(1.0,aFirstPoint.Value,aSecondPoint.Value,aFirstPoint.Key,aSecondPoint.Key,iKey)
end
},

{"UNTIL",OPERATION_FORMAT_UNTIL,
function (aTranslation,aOperation)
	return ExecLoopOp(aTranslation,aOperation,false)
end
},

{"ROUNDDOWN",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,RoundDblDown,{{TYPENUM,true},{TYPENUM,false,0}})
end
},

{"ROUNDLOTRO",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,RoundDblLotro,{{TYPENUM,true}})
end
},

{"ROUNDPROG",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,RoundDblProg,{{TYPENUM,true}})
end
},

{"ROUNDUP",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,RoundDblUp,{{TYPENUM,true},{TYPENUM,false,0}})
end
},

{"ROUND",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,RoundDbl,{{TYPENUM,true},{TYPENUM,false,0}})
end
},

{"EQUSNG",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,EquSng,{{TYPENUM,true}})
end
},

{"DECSNG",OPERATION_FORMAT_FUNCTION,
function (aTranslation,aOperation)
	return ExecDefault(aTranslation,aOperation,DecSng,{{TYPENUM,true}})
end
}

}

nOpDefFunctionEnd = #aOperationDefs
 
local OPPRIOGRP_OPERATIONDEF_IDS = 1 -- set of operation definition IDs (indexes)
local OPPRIOGRP_SCANDIRECTION = 2
local OPPRIOGRP_SCANFORMAT = 3

local SCANDIRECTION_LEFTRIGHT = 1
local SCANDIRECTION_RIGHTLEFT = 2

-- defines priority process order and scan direction for grouped binary and unary operations
-- same as Lua operation order, highest priority first
-- you can't mix unary and binary operations in the same group: it's either all unary or all binary
local aOperationPriorityGroups =
	{
		{{[18]=true},SCANDIRECTION_RIGHTLEFT,OPERATION_FORMAT_BINARY}, -- POWER
		{{[1]=true,[2]=true,[3]=true},SCANDIRECTION_RIGHTLEFT,OPERATION_FORMAT_UNARY}, -- LOGICNEG,NEGATE,POSITIVE
		{{[16]=true,[17]=true,[15]=true},SCANDIRECTION_LEFTRIGHT,OPERATION_FORMAT_BINARY}, -- MULTIPLY,DIVIDE,MOD
		{{[14]=true,[13]=true},SCANDIRECTION_LEFTRIGHT,OPERATION_FORMAT_BINARY}, -- ADD,SUBSTRACT
		{{[4]=true},SCANDIRECTION_RIGHTLEFT,OPERATION_FORMAT_BINARY}, -- CONCAT
		{{[12]=true,[11]=true,[8]=true,[7]=true,[10]=true,[9]=true},SCANDIRECTION_LEFTRIGHT,OPERATION_FORMAT_BINARY}, -- SMTH,GRTH,SMEQTH,GREQTH,NOTEQUALS,EQUALS
		{{[6]=true},SCANDIRECTION_LEFTRIGHT,OPERATION_FORMAT_BINARY}, -- AND
		{{[5]=true},SCANDIRECTION_LEFTRIGHT,OPERATION_FORMAT_BINARY} -- OR
	}

-- returns operand number from operand string like 9 from "[9]"
local function OPStonumber(sOPS)
	if sOPS == nil then
		return
	else
		local sOPn = strmatch(sOPS,"^%s*%[(%d+)%]%s*$")
		if sOPn then
			return tonumber(sOPn)
		else
			return
		end
	end
end

-- returns operand string from operand number/string like "[9]" from 9
local function OPNtostring(xOPN)
	if xOPN == nil then
		return
	else
		return "["..xOPN.."]"
	end
end

local function CreateConstantOperand(aTranslation,sSource,xValue)
	local nOp = aTranslation[TRANS_OPSOURCEIDX][sSource]
	if not nOp then
		-- add new operand if not exists yet
		nOp = #aTranslation[TRANS_OPERANDS]+1
		aTranslation[TRANS_OPERANDS][nOp] = {xValue}
		aTranslation[TRANS_OPSOURCEIDX][sSource] = nOp -- store source+index into operand source searchindex
	end
	return nOp
end

local function CreateBooleanConstant(aTranslation,bConstant)
	if bConstant then
		return CreateConstantOperand(aTranslation,"TRUE",true)
	else
		return CreateConstantOperand(aTranslation,"FALSE",false)
	end
end

-- detects a boolean value in a text, creates an operand for it and returns operand index
-- if the value already exists then it returns the existing operand index
-- pattern matches FALSE, TRUE
local function FetchBooleanConstant(aTranslation,sExpression)
	local sSource = strmatch(sExpression,"%s*(FALSE)%s*")
	if not sSource then
		sSource = strmatch(sExpression,"%s*(TRUE)%s*")
	end
	if sSource == "TRUE" then
		return OPNtostring(CreateConstantOperand(aTranslation,"TRUE",true))
	else
		return OPNtostring(CreateConstantOperand(aTranslation,"FALSE",false))
	end
end

local function CreateNumberConstant(aTranslation,nConstant)
	return CreateConstantOperand(aTranslation,tostring(nConstant),nConstant)
end

-- detects a number value in a text, creates an operand for it and returns operand index
-- if the value already exists then it returns the existing operand index
-- pattern matches the minimal 9 and 9.9 or more digits
local function FetchNumberConstant(aTranslation,sExpression)
	local sSource = strmatch(sExpression,"%s*(%d+%.%d+)%s*")
	if not sSource then
		sSource = strmatch(sExpression,"%s*(%d+)%s*")
	end
	return OPNtostring(CreateConstantOperand(aTranslation,sSource,tonumber(sSource)))
end

local function CreateStringConstant(aTranslation,sConstant)
	return CreateConstantOperand(aTranslation,"\""..sConstant.."\"",sConstant)
end

-- detects a string value in a text, creates an operand for it and returns operand index
-- if the value already exists then it returns the existing operand index
-- pattern matches characters between ""
local function FetchStringConstant(aTranslation,sExpression)
	local sSource = strmatch(sExpression,"%s*(\".-\")%s*")
	return OPNtostring(CreateConstantOperand(aTranslation,sSource,strgsub(strsub(sSource,2,-2),"\\.",
				function(sEscapeChar)
					if sEscapeChar == "\\n" then return "\n"
					elseif sEscapeChar == "\\q" then return "\""
					elseif sEscapeChar == "\\\\" then return "\\"
					else return ""
					end
				end)))
end

-- register operand to variables as dependable
local function RegisterOperandWithVars(aTranslation,nOp)
	local aTransVars = aTranslation[TRANS_VARIABLES]
	for nVar, _ in pairs(aTranslation[TRANS_OPERANDS][nOp][OPERAND_DEPENDSON]) do
		-- operand depends on this variable
		aTransVars[nVar][VAR_OPERANDS][nOp] = true -- register operand number in variable as dependable
	end
end

-- if an operand for the variable already exists then it returns the existing operand index
-- operand index is registered with the variable's entry in the variable table
-- dependson flag ensures that every operand that uses this operand will also depend on the variable and be registered as such
local function CreateVariableOperand(aTranslation,sVarName)
	local nVar = aTranslation[TRANS_VARNAMEIDX][sVarName]
	if not nVar then
		-- add new 'on the fly' variable. inside With function?
		nVar = #aTranslation[TRANS_VARIABLES]+1
		if nVar > 1000 then
			RaiseExpressionsError(aTranslation,ERR.TOOMANYVARIABLES)
		end
		aTranslation[TRANS_VARIABLES][nVar] = {sVarName,nil,{}}
		aTranslation[TRANS_VARNAMEIDX][sVarName] = nVar -- store name+index into variable name searchindex
	end
	local nOp = aTranslation[TRANS_OPSOURCEIDX][sVarName]
	if not nOp then
		-- add new operand if not exists yet
		nOp = #aTranslation[TRANS_OPERANDS]+1
		aTranslation[TRANS_OPERANDS][nOp] = {nil,-nVar,{[nVar] = true}} -- negative operation index: value needs to be picked up from variable
		aTranslation[TRANS_OPSOURCEIDX][sVarName] = nOp -- store source+index into operand source searchindex
		RegisterOperandWithVars(aTranslation,nOp) -- register operand with variable(s) it depends on
	end
	return nOp
end

-- detects a variable in a text, creates an operand for it and returns operand index
-- pattern matches the minimal $A (or with more letters)
local function FetchVariableOperand(aTranslation,sVar)
	return OPNtostring(CreateVariableOperand(aTranslation,strmatch(sVar,"%s*%$(%a+)%s*")))
end

-- splits an expression into (parameter)parts, based on a splitting token
-- calls a supplied function for each detected part
-- tokens in nested expressions between () are ignored
local function DecomposeParameters(aTranslation,sParams,sSplitToken,fDecomposeParameter)
	local nParam = 0
	local nLevel = 0 -- to keep track of nested ()
	local nLastToken = 0
	local sSearchChars = "([%(%)"..sSplitToken.."])"
	local nCharIndex = 0
	while true do
		nCharIndex, _, sChar = strfind(sParams,sSearchChars,nCharIndex+1)
		if not sChar then
			-- last parameter at the end
			fDecomposeParameter(strsub(sParams,nLastToken+1),nParam+1,true)
			return
		elseif sChar == "(" then
			nLevel = nLevel+1
		elseif sChar == ")" then
			nLevel = nLevel-1
		elseif nLevel == 0 then
			-- we have a parameter when we detect a splitting token at level 0
			nParam = nParam+1
			fDecomposeParameter(strsub(sParams,nLastToken+1,nCharIndex-1),nParam,false)
			nLastToken = nCharIndex
		end
	end
end

local CreateExpressionOperand
local DecomposeExpression

-- sParams = param1,param2,etc
-- returns an array with operand numbers, containing parameter expression results
local function DecomposeFunctionParameters(aTranslation,sParams)
	-- extract parameters
	local aParamOps = {}

	local DecomposeFunctionParameter = function(sParam,nParam,bIsLastParam)
		aParamOps[#aParamOps+1] = CreateExpressionOperand(aTranslation,sParam)
	end

	DecomposeParameters(aTranslation,sParams,",",DecomposeFunctionParameter)

	return aParamOps
end

-- transform CASE>=compexpr1:CASE<=compexpr2:..etc:resultexpr
-- expand to: (testexpr>=compexpr1)OR(testexpr<=compexpr2)OR..etc
local function DecomposeCaseConditions(aTranslation,sParams,sTestOp,aParamOps)
	local sCombinedExpr = ""
	local sCompareExpr
	local sNewExpr

	local DecomposeCaseCondition = function(sParam,nParam,bIsLastParam)
		if bIsLastParam and nParam < 2 then
			-- not enough parameter groups
			RaiseExpressionsError(aTranslation,ERR.MISSINGPARAMGROUPS,sParams)
		elseif bIsLastParam then
			-- add combined logical expression
			aParamOps[#aParamOps+1] = CreateExpressionOperand(aTranslation,sCombinedExpr)
			-- add last: should be result expression
			aParamOps[#aParamOps+1] = CreateExpressionOperand(aTranslation,sParam)
		else
			-- construct combined logical expression
			sCompareExpr = strmatch(sParam,"^%s*CASE%s*(.-)%s*$")
			if not sCompareExpr or sCompareExpr == "" then
				RaiseExpressionsError(aTranslation,ERR.MISSINGSWITCHCONDITION,sParam)
			end
			sNewExpr = DecomposeExpression(aTranslation,sTestOp.." "..sCompareExpr)
			if sCombinedExpr == "" then
				sCombinedExpr = sNewExpr
			else
				sCombinedExpr = sCombinedExpr.." OR "..sNewExpr
			end
		end
	end

	DecomposeParameters(aTranslation,sParams,":",DecomposeCaseCondition)
end

-- SWITCH(testexpr,CASE>=compexpr1:CASE<=compexpr2:resultexpr1,DEFAULT:resultexpr2)
-- expand to: SWITCH((testexpr>=compexpr1)OR(testexpr<=compexpr2),resultexpr1,True,resultexpr2)
-- parameter results should be like bBoolean1,xValue1,bBoolean2,xValue2,bBoolean3,xValue3,etc
local function DecomposeSwitchParameters(aTranslation,sParams)
	-- extract parameters
	local aParamOps = {}
	local sTestOp
	local sDefaultExpr
	local bDefaultDone = false

	local DecomposeSwitchParameter = function(sParam,nParam,bIsLastParam)
		if bIsLastParam and nParam < 2 then
			-- not enough parameter groups
			RaiseExpressionsError(aTranslation,ERR.MISSINGPARAMGROUPS,sParams)
		elseif nParam == 1 then
			-- should be test expression
			sTestOp = DecomposeExpression(aTranslation,sParam)
		elseif not bDefaultDone then
			-- test for CASE or DEFAULT at the start
			if strmatch(sParam,"^%s*CASE") then
				-- CASE parameter, possibly multiple conditions
				-- CASE>=compexpr1:CASE<=compexpr2:resultexpr1
				DecomposeCaseConditions(aTranslation,sParam,sTestOp,aParamOps)
			elseif strmatch(sParam,"^%s*DEFAULT") then
				-- default parameter
				-- DEFAULT:resultexpr2
				sDefaultExpr = strmatch(sParam,"^%s*DEFAULT%s*:%s*(.-)%s*$")
				if not sDefaultExpr or sDefaultExpr == "" then
					RaiseExpressionsError(aTranslation,ERR.MISSINGSWITCHDEFAULT,sParam)
				end
				-- add true parameter operand
				aParamOps[#aParamOps+1] = CreateBooleanConstant(aTranslation,true)
				-- add default result parameter operand
				aParamOps[#aParamOps+1] = CreateExpressionOperand(aTranslation,sDefaultExpr)
				-- default done, should be last
				bDefaultDone = true
			else
				RaiseExpressionsError(aTranslation,ERR.SYNTAXSWITCH,sParam)
			end
		else
			-- too many parameter groups (after being closed by a default)
			if sParam == "" then
				RaiseExpressionsError(aTranslation,ERR.SWITCHGROUPSOVERFLOW,sParams)
			else
				RaiseExpressionsError(aTranslation,ERR.SWITCHGROUPSOVERFLOW,sParam)
			end
		end
	end

	DecomposeParameters(aTranslation,sParams,",",DecomposeSwitchParameter)

	if not bDefaultDone then
		-- didn't include a default condition
		RaiseExpressionsError(aTranslation,ERR.MISSINGSWITCHDEFAULT,sParams)
	end

	return aParamOps
end

-- var1=varexpr1, var2=varexpr2, etc.
-- expand to: varcount, var1, varexpr1, var2, varexpr2, etc.
local function DecomposeVarAssignments(aTranslation,sParams,aParamOps)
	local nVarCountOpIdx = #aParamOps+1
	aParamOps[nVarCountOpIdx] = -1 -- reserve position for assignment count

	local DecomposeVarAssignment = function(sParam,nParam,bIsLastParam)
		local sVar, sVarExpr = strmatch(sParam,"^%s*(%[%d+%])%s*=%s*(.-)%s*$") -- variable should already be an operand
		if not sVar or sVarExpr == "" then
			sVar = strmatch(sParam,"^%s*(%[%d+%])")
			if not sVar then
				RaiseExpressionsError(aTranslation,ERR.MISSINGASSIGNVARIABLE,sParam)
			end
			sVar = strmatch(sParam,"^%s*(%[%d+%])%s*=")
			if not sVar then
				RaiseExpressionsError(aTranslation,ERR.MISSINGASSIGNSIGN,sParam)
			end
			RaiseExpressionsError(aTranslation,ERR.MISSINGASSIGNEXPRESSION,sParam)
		end
		-- add variable operand
		aParamOps[#aParamOps+1] = OPStonumber(sVar)
		-- add assigned expression
		aParamOps[#aParamOps+1] = CreateExpressionOperand(aTranslation,sVarExpr)
	end

	DecomposeParameters(aTranslation,sParams,",",DecomposeVarAssignment)

	-- store variable assignment count
	aParamOps[nVarCountOpIdx] = CreateNumberConstant(aTranslation,(#aParamOps-nVarCountOpIdx)/2)
end

-- WITH(var1=varexpr1, var2=varexpr2, etc. : resultexpr)
-- expand to: WITH(varcount, var1, varexpr1, var2, varexpr2, etc. , resultexpr)
-- parameter results should be like a pair for each variable assignment plus one result operand at the end
local function DecomposeWithParameters(aTranslation,sParams)
	-- extract parameters
	local aParamOps = {}

	local DecomposeWithParameter = function(sParam,nParam,bIsLastParam)
		if bIsLastParam and nParam < 2 then
			-- not enough parameter groups
			RaiseExpressionsError(aTranslation,ERR.MISSINGPARAMGROUPS,sParams)
		elseif nParam == 1 then
			-- should be variable assignments
			DecomposeVarAssignments(aTranslation,sParam,aParamOps)
		elseif nParam == 2 then
			-- should be the result expression
			-- add result parameter operand
			aParamOps[#aParamOps+1] = CreateExpressionOperand(aTranslation,sParam)
		elseif nParam == 3 then
			-- too many parameter groups
			if sParam == "" then
				RaiseExpressionsError(aTranslation,ERR.PARAMGROUPSOVERFLOW,sParams)
			else
				RaiseExpressionsError(aTranslation,ERR.PARAMGROUPSOVERFLOW,sParam)
			end
		end
	end

	DecomposeParameters(aTranslation,sParams,":",DecomposeWithParameter)

	return aParamOps
end

-- WHILE(initvar1=varexpr1, initvar2=varexpr2, etc. : loopconditionexpr : loopvar1=varexp1, loopvar2=varexp2, etc. : resultexpr)
-- expand to: WHILE(initvarcount, initvar1, initvarexpr1, initvar2, initvarexpr2, etc. , loopconditionexpr, loopvarcount, loopvar1, loopvarexpr1, loopvar2, loopvarexpr2, etc. , resultexpr)
-- UNTIL(initvar1=varexpr1, initvar2=varexpr2, etc. : loopvar1=varexp1, loopvar2=varexp2, etc. : loopconditionexpr : resultexpr)
-- expand to: UNTIL(initvarcount, initvar1, initvarexpr1, initvar2, initvarexpr2, etc., loopvarcount, loopvar1, loopvarexpr1, loopvar2, loopvarexpr2, etc. , loopconditionexpr , resultexpr)
-- parameter results should be like a pair for each variable assignment plus one operand for loopcondition and one for result at the end
local function DecomposeLoopParameters(aTranslation,sParams,bPreCondition)
	-- extract parameters
	local aParamOps = {}

	local DecomposeLoopParameter = function(sParam,nParam,bIsLastParam)
		if bIsLastParam and nParam < 4 then
			-- not enough parameter groups
			RaiseExpressionsError(aTranslation,ERR.MISSINGPARAMGROUPS,sParams)
		elseif nParam == 1 then
			-- should be initial variable assignments
			DecomposeVarAssignments(aTranslation,sParam,aParamOps)
		elseif (nParam == 2 and bPreCondition) or (nParam == 3 and not bPreCondition) then
			-- should be loop condition expression
			aParamOps[#aParamOps+1] = CreateExpressionOperand(aTranslation,sParam)
		elseif (nParam == 3 and bPreCondition) or (nParam == 2 and not bPreCondition) then
			-- should be loop variable assignments
			DecomposeVarAssignments(aTranslation,sParam,aParamOps)
		elseif nParam == 4 then
			-- should be the result expression
			-- add result parameter operand
			aParamOps[#aParamOps+1] = CreateExpressionOperand(aTranslation,sParam)
		elseif nParam == 5 then
			-- too many parameter groups
			if sParam == "" then
				RaiseExpressionsError(aTranslation,ERR.PARAMGROUPSOVERFLOW,sParams)
			else
				RaiseExpressionsError(aTranslation,ERR.PARAMGROUPSOVERFLOW,sParam)
			end
		end
	end

	DecomposeParameters(aTranslation,sParams,":",DecomposeLoopParameter)

	return aParamOps
end

-- compose combined dependson for multiple operands
local function CombineOperandsDependsOn(aTranslation,aOperands)
	local aDependsOn
	if aOperands then
		local aOpDependsOn
		for _, nOp in ipairs(aOperands) do
			if nOp then
				aOpDependsOn = aTranslation[TRANS_OPERANDS][nOp][OPERAND_DEPENDSON]
				if aOpDependsOn then
					if not aDependsOn then
						aDependsOn = {}
					end
					for nVar, _ in pairs(aOpDependsOn) do
						aDependsOn[nVar] = true
					end
				end
			end
		end
	end
	return aDependsOn
end

local function CreateOperation(aTranslation,sSource,nOperationDef,aOperands)
	-- test if a result not yet exists for this source
	local nResultOp = aTranslation[TRANS_OPSOURCEIDX][sSource]
	if not nResultOp then
		-- index result operand
		nResultOp = #aTranslation[TRANS_OPERANDS]+1
		aTranslation[TRANS_OPSOURCEIDX][sSource] = nResultOp -- store source+index into operand source searchindex
		-- define the operation
		local aOperation = {nOperationDef,aOperands,nResultOp}
		-- create combined depends-on for result operand
		local aDependsOn = CombineOperandsDependsOn(aTranslation,aOperands)
		if aDependsOn then
			-- depends on variable(s), so operation needs to be stored, but not executed now
			local nResultOperation = #aTranslation[TRANS_OPERATIONS]+1
			aTranslation[TRANS_OPERATIONS][nResultOperation] = aOperation -- store in operation table
			aTranslation[TRANS_OPERANDS][nResultOp] = {nil,nResultOperation,aDependsOn} -- define operand
			RegisterOperandWithVars(aTranslation,nResultOp) -- register result operand with variable(s) it depends on
		else
			-- does not depend on any variable, so operand values should be all constants
			-- calculate constant value now, no need to store the operation
			aTranslation[TRANS_OPERANDS][nResultOp] = {nil} -- define operand, will hold only a result
			ExecuteOperation(aTranslation,aOperation) -- execute the operation
		end
	end
	return nResultOp
end

local function GetSourceParameterOperands(aParamOps)
	local sSource = ""
	for _, nOp in ipairs(aParamOps) do
		if sSource ~= "" then
			sSource = sSource..","
		end
		if nOp then
			sSource = sSource..OPNtostring(nOp)
		end
	end
	return sSource
end

-- sName = name of function like CALCSTAT, LINFMOD, etc.
-- sParams = param1,param2,etc (normally)
-- parameters need to be extracted and each treated like an expression (which should return a result in an operand)
-- an operation for this function needs to be created, which takes a list of operands (the parameters) and gives a result in an operand
local function DecomposeFunction(aTranslation,sName,sParams)
	 -- set focus for error reporting
	aTranslation[TRANS_EXPRWIP] = sName.."("..sParams..")"

	-- get function definition
	local nOperationDef
	local nFunctionFormat
	for nOpDef = nOpDefUnaryStart, nOpDefFunctionEnd do
		if aOperationDefs[nOpDef][OPERATIONDEF_OPERATOR] == sName then
			nFunctionFormat = aOperationDefs[nOpDef][OPERATIONDEF_FORMAT]
			if nFunctionFormat == OPERATION_FORMAT_UNARY or nFunctionFormat == OPERATION_FORMAT_BINARY then
				-- this is not a function, but a basic operation followed by parantheses, like: NOT ($A < 10)
				return aTranslation[TRANS_EXPRWIP] -- return unaltered so they can be processed as basic operations later
			end
			nOperationDef = nOpDef
			break
		end
	end
	if not nOperationDef then
		-- unknown function
		RaiseExpressionsError(aTranslation,ERR.UNKNOWNFUNCTION)
	end

	-- get an array with parameter operand numbers
	local aParamOps
	if nFunctionFormat == OPERATION_FORMAT_SWITCH then
		aParamOps = DecomposeSwitchParameters(aTranslation,sParams) -- Switch($L, case<=10: case>=100: 25, default: 13)
	elseif nFunctionFormat == OPERATION_FORMAT_WITH then
		aParamOps = DecomposeWithParameters(aTranslation,sParams) -- With($A=@Agility#2, $B=20: IIf($A>$B,$A,$B))
	elseif nFunctionFormat == OPERATION_FORMAT_WHILE then
		aParamOps = DecomposeLoopParameters(aTranslation,sParams,true)
	elseif nFunctionFormat == OPERATION_FORMAT_UNTIL then
		aParamOps = DecomposeLoopParameters(aTranslation,sParams,false)
	else
		aParamOps = DecomposeFunctionParameters(aTranslation,sParams) -- sName(operand1, operand2, etc.)
	end

	-- compose funcname([n],[n],etc) as source identifier
	local sSource = sName.."("..GetSourceParameterOperands(aParamOps)..")"

	-- create an operation for this function (returns result operand number)
	local nResultOp = CreateOperation(aTranslation,sSource,nOperationDef,aParamOps)

	return OPNtostring(nResultOp)
end

-- extract operation from expression snippet in Work in Progress
local function ExtractOpDefWIP(aTranslation,nOpDefStart,nOpDefEnd)
	local sOperator, nTestLen
	for nOpDef = nOpDefStart, nOpDefEnd do
		sOperator = aOperationDefs[nOpDef][OPERATIONDEF_OPERATOR]
		nTestLen = #sOperator
		if strsub(aTranslation[TRANS_EXPRWIP],1,nTestLen) == sOperator then
			-- remove found operator from operators and remove any leading whitespace
			aTranslation[TRANS_EXPRWIP] = strmatch(strsub(aTranslation[TRANS_EXPRWIP],nTestLen+1),"%s*(.*)")
			return nOpDef
		end
	end
end

-- extract unary operations from expression snippet in Work in Progress
local function ExtractUnaryOpDefsWIP(aTranslation)
	local aOpDefs = {}
	local nOpDefCount = 0
	local nUnaryOpDef
	while aTranslation[TRANS_EXPRWIP] ~= "" do
		nUnaryOpDef = ExtractOpDefWIP(aTranslation,nOpDefUnaryStart,nOpDefUnaryEnd)
		if not nUnaryOpDef then
			-- something was there, but not a valid unary operation
			RaiseExpressionsError(aTranslation,ERR.UNKNOWNUNARY)
		end	
		-- store unary operation definition index
		nOpDefCount = nOpDefCount+1
		aOpDefs[nOpDefCount] = nUnaryOpDef
	end
	return aOpDefs
end

local ELEMENT_OPERAND = 1 -- operand in expression element
local ELEMENT_UNARYOPDEFS = 2 -- unary operations to be performed on this operand
local ELEMENT_BINARYOPDEF = 3 -- binary operation to be performed on this operand and the one in the next element

-- create a list of Expression Elements out of an Expression
-- <unary operator 1>..<unary operator N>[<operand>]<binary operator> --> Element = {<operand>,{<unary operation definitions>},<binary operation definition>}
-- or at the end this is
-- <unary operator 1>..<unary operator N>[<operand>] --> Element = {<operand>,{<unary operation definitions>},nil}
local function CreateElementsFromExpression(aTranslation,sExpression)
	local sTempExpr = trim(sExpression) -- trim leading/trailing white space
	local aElements = {}
	local nElemIndex = 0
	local aElement
	local sBinaryOpSearch = "^(.-)%s*%[(%d+)%]%s*(.-)%s*%[(%d+)%]%s*(.-)$" -- binary operation search from the left
	local sUnaryOpSearch = "^(.-)%s*%[(%d+)%]%s*(.-)$" -- unary operation search from the left
	local sLeft, sFoundOperand1, sMiddle, sFoundOperand2, sRight

	while sTempExpr ~= "" do
		-- try to find a binary operation, involving 2 operands
		sLeft, sFoundOperand1, sMiddle, sFoundOperand2, sRight = strmatch(sTempExpr,sBinaryOpSearch)
		if sFoundOperand1 and sFoundOperand2 then
			-- process operand1
			aElement = {tonumber(sFoundOperand1),nil,nil}
			if sLeft ~= "" then
				-- process unaries for operand1
				aTranslation[TRANS_EXPRWIP] = sLeft
				aElement[ELEMENT_UNARYOPDEFS] = ExtractUnaryOpDefsWIP(aTranslation)
			end
			if sMiddle == "" then
				-- syntax error: missing binary operation
				RaiseExpressionsError(aTranslation,ERR.MISSINGBINARY,sTempExpr)
			end
			-- extract the binary operation, but leave any unaries for operand in next element
			aTranslation[TRANS_EXPRWIP] = sMiddle
			aElement[ELEMENT_BINARYOPDEF] = ExtractOpDefWIP(aTranslation,nOpDefBinaryStart,nOpDefBinaryEnd)
			if not aElement[ELEMENT_BINARYOPDEF] then
				RaiseExpressionsError(aTranslation,ERR.UNKNOWNBINARY)
			end
			-- more to be processed in next cycle
			sTempExpr = aTranslation[TRANS_EXPRWIP]..OPNtostring(sFoundOperand2)..sRight
		else
			-- else try to find a single operand (should be at the end of the expression)
			sLeft, sFoundOperand1, sRight = strmatch(sTempExpr,sUnaryOpSearch)
			if not sFoundOperand1 then
				-- syntax error: didn't find any operand - something's there, but not an operand
				RaiseExpressionsError(aTranslation,ERR.MISSINGOPERAND,sTempExpr)
			end
			-- process the operand
			aElement = {tonumber(sFoundOperand1),nil,nil}
			if sLeft ~= "" then
				-- process unaries
				aTranslation[TRANS_EXPRWIP] = sLeft
				aElement[ELEMENT_UNARYOPDEFS] = ExtractUnaryOpDefsWIP(aTranslation)
			end
			sTempExpr = sRight -- should be empty..
		end
		nElemIndex = nElemIndex+1
		aElements[nElemIndex] = aElement
	end

	return aElements
end

local function CreateExpressionFromElements(aElements)
	local aResult = {}
	for _, aElement in ipairs(aElements) do
		if aElement[ELEMENT_UNARYOPDEFS] then
			-- unary operatordefid(s)
			for _, o in ipairs(aElement[ELEMENT_UNARYOPDEFS]) do
				tableinsert(aResult,aOperationDefs[o][OPERATIONDEF_OPERATOR])
			end
		end
		if aElement[ELEMENT_OPERAND] then
			-- operand number
			tableinsert(aResult,OPNtostring(aElement[ELEMENT_OPERAND]))
		end
		if aElement[ELEMENT_BINARYOPDEF] then
			-- binary operatordefid
			tableinsert(aResult,aOperationDefs[aElement[ELEMENT_BINARYOPDEF]][OPERATIONDEF_OPERATOR])
		end
	end
	return tableconcat(aResult)
end

-- decomposes an Element's unary operations
local function ProcessUnaryOperations(aTranslation,aElement,nOperationPriorityGroup)
	local aUnaryOperators = aElement[ELEMENT_UNARYOPDEFS]

	local aOperationPriorityGroup = aOperationPriorityGroups[nOperationPriorityGroup]
	local aOperationDefIds = aOperationPriorityGroup[OPPRIOGRP_OPERATIONDEF_IDS] -- need to search for operators in this set
	local nScanDirection = aOperationPriorityGroup[OPPRIOGRP_SCANDIRECTION] -- from which direction to search
	local nScanFormat = aOperationPriorityGroup[OPPRIOGRP_SCANFORMAT] -- search binary or unary operations

	if nScanFormat ~= OPERATION_FORMAT_UNARY then
		-- nothing to do here if not a unary group
		return
	end

	local nStart, nEnd, nStep, nCurrent
	local nUnaryOperator

	-- process unary operators in given element, which belong to the given priority group
	if nScanDirection == SCANDIRECTION_RIGHTLEFT then
		nStart, nEnd, nStep = #aUnaryOperators, 1, -1
	elseif nScanDirection == SCANDIRECTION_LEFTRIGHT then
		nStart, nEnd, nStep = 1, #aUnaryOperators, 1
	end
	nCurrent = nStart-nStep
	repeat
		nCurrent = nCurrent+nStep
		nUnaryOperator = aUnaryOperators[nCurrent]
		if aOperationDefIds[nUnaryOperator] then
			-- unary operator is in current prio group
			-- create the unary operation
			aElement[ELEMENT_OPERAND] = CreateOperation(aTranslation,
														aOperationDefs[nUnaryOperator][OPERATIONDEF_OPERATOR]..OPNtostring(aElement[ELEMENT_OPERAND]),
														nUnaryOperator,
														{aElement[ELEMENT_OPERAND]})
			-- remove unary operation
			tableremove(aUnaryOperators,nCurrent) -- will also shift all remaining unaries right, one position to the left
			if nScanDirection == SCANDIRECTION_LEFTRIGHT then
				-- need to re-do current index unary if from left to right only, because unaries have shifted
				 -- also, the list has been shortened by 1
				nCurrent, nEnd = nCurrent-nStep, nEnd-nStep
			end
		end
	until nCurrent == nEnd

	if #aUnaryOperators == 0 then
		aElement[ELEMENT_UNARYOPDEFS] = nil -- all done, no need to re-visit in the future
	end
end

-- decomposes a simple expression in unary and binary operations
local function CreateBasicOperations(aTranslation,sExpression)
	-- turn the expression in a list of Elements. each Element contains an Operand, usually a Binary Operator (not the last one) & a list of possible Unary operators.
	-- like -10+24/-32 is turned into 3 elements:
	-- Element 1: operand holding value '10', binary operator '+', unary operator '-': -10+
	-- Element 2: operand holding value '24', binary operator '/', unary operator nil: 24/
	-- Element 3: operand holding value '32', binary operator nil, unary operator '-': -32
	local aElements = CreateElementsFromExpression(aTranslation,sExpression)

	-- the Elements must now be turned into the right sequence of operations.
	-- in the example above we have 4 recognised operators (2 binary and 2 unary), so for this we need to create 4 operations,
	-- BUT in sequence of the right priority (division before addition etc) - for this we have priority groups, each for a defined set of operators [OPPRIOGRP_OPERATIONDEF_IDS]
	-- AND in process order from left or right direction - which is also defined in each priority group [OPPRIOGRP_SCANDIRECTION]

	local aOperationDefIds, nScanDirection, nScanFormat
	local nStart, nEnd, nStep, nCurrent
	local aPrimaryElem, aSecondaryElem, nBinaryOperator

	-- cycle all operator priority groups, in sequence from high to low priority
	for nOperationPriorityGroup, aOperationPriorityGroup in ipairs(aOperationPriorityGroups) do
		aOperationDefIds = aOperationPriorityGroup[OPPRIOGRP_OPERATIONDEF_IDS] -- need to search for operators in this set
		nScanDirection = aOperationPriorityGroup[OPPRIOGRP_SCANDIRECTION] -- from which direction to search
		nScanFormat = aOperationPriorityGroup[OPPRIOGRP_SCANFORMAT] -- search binary or unary operations

		-- process all operators in all elements, which belong to current priority group
		if nScanDirection == SCANDIRECTION_RIGHTLEFT then
			nStart, nEnd, nStep = #aElements, 1, -1
		elseif nScanDirection == SCANDIRECTION_LEFTRIGHT then
			nStart, nEnd, nStep = 1, #aElements, 1
		end
		nCurrent = nStart-nStep
		repeat
			nCurrent = nCurrent+nStep
			if nScanFormat == OPERATION_FORMAT_BINARY then
				aPrimaryElem = aElements[nCurrent]
				nBinaryOperator = aPrimaryElem[ELEMENT_BINARYOPDEF]
				if nBinaryOperator then
					if aOperationDefIds[nBinaryOperator] then
						-- binary operator is in current prio group
						aSecondaryElem = aElements[nCurrent+1]
						-- check for unary operators on secondary operand
						if aSecondaryElem[ELEMENT_UNARYOPDEFS] then
							-- always process any unary operators on secondary operand first
							ProcessUnaryOperations(aTranslation,aSecondaryElem,2) --group 2 contains the unary operations
						end
						-- create the binary operation
						aPrimaryElem[ELEMENT_OPERAND] = CreateOperation(aTranslation,
																		OPNtostring(aPrimaryElem[ELEMENT_OPERAND])..aOperationDefs[nBinaryOperator][OPERATIONDEF_OPERATOR]..OPNtostring(aSecondaryElem[ELEMENT_OPERAND]),
																		nBinaryOperator,
																		{aPrimaryElem[ELEMENT_OPERAND],aSecondaryElem[ELEMENT_OPERAND]})
						-- move any binary operation from secondary to primary element
						aPrimaryElem[ELEMENT_BINARYOPDEF] = aSecondaryElem[ELEMENT_BINARYOPDEF]
						-- remove secondary element
						tableremove(aElements,nCurrent+1) -- will also shift all remaining elements right, one position to the left
						if nScanDirection == SCANDIRECTION_LEFTRIGHT then
							-- need to re-do current index element if from left to right only, because elements have shifted
							-- also, the list has been shortened by 1
							nCurrent, nEnd = nCurrent-nStep, nEnd-nStep
						end
					end
				end
			elseif nScanFormat == OPERATION_FORMAT_UNARY then
				aPrimaryElem = aElements[nCurrent]
				if aPrimaryElem[ELEMENT_UNARYOPDEFS] then
					ProcessUnaryOperations(aTranslation,aPrimaryElem,nOperationPriorityGroup)
				end
			end
		until nCurrent == nEnd
	end

	return CreateExpressionFromElements(aElements) -- should only return "[nResultOp]"
end

-- removes number and boolean constant values from an expression text and replaces them with operand identifiers (indexes in operand table)
-- for example " TRUE , 1.55 " will look something like "[1],[2]"
-- operands with indexes 1 and 2 have then been created in the operand table
local function CreateConstantOperands(aTranslation,sExpression)
	local sReplExpr = sExpression
	-- booleans
	sReplExpr = strgsub(sReplExpr,"%s*FALSE%s*",function(sBoolean) return FetchBooleanConstant(aTranslation,sBoolean) end)
	sReplExpr = strgsub(sReplExpr,"%s*TRUE%s*",function(sBoolean) return FetchBooleanConstant(aTranslation,sBoolean) end)
	-- numbers
	sReplExpr = strgsub(sReplExpr,"%s*%d+%.%d+%s*",function(sNumber) return FetchNumberConstant(aTranslation,sNumber) end)
	-- problem: numbers without dot in operand references [n]
	sReplExpr = strgsub(sReplExpr,"(%s*)([^%d]?)(%d+)([^%d]?)(%s*)",function(sStart,sTest1,sNumber,sTest2,sEnd) if not (sTest1 == "[" and sTest2 == "]") then return sStart..sTest1..FetchNumberConstant(aTranslation,sNumber)..sTest2..sEnd end end) -- just %s*%d+%s* would match n in [n]
	return sReplExpr
end

local function DecomposeParantheses(aTranslation,sExpression)
	local sReplExpr = strgsub(sExpression,"%s*(%b())%s*",function(sNestedExpr) return DecomposeExpression(aTranslation,strsub(sNestedExpr,2,-2)) end)
	return sReplExpr
end

local function DecomposeFunctions(aTranslation,sExpression)
	local sReplExpr = strgsub(sExpression,"%s*(%a+%w*)%s*(%b())%s*",function(sName,sParams) return DecomposeFunction(aTranslation,sName,strsub(sParams,2,-2)) end)
	return sReplExpr
end

-- recursive function which decomposes (parts of) an expression
CreateExpressionOperand = function(aTranslation,sExpression)
	local nStage = 1
	local nResultOp
	local sTempExpr = sExpression
	while true do
		aTranslation[TRANS_EXPRWIP] = sTempExpr
		if nStage == 1 then
			-- check initial state
			if trim(sTempExpr) == "" then
				RaiseExpressionsError(aTranslation,ERR.MISSINGEXPRESSION)
			end
		elseif nStage == 2 then
			-- process functions funcname(expr1,expr2,expr3,..)
			sTempExpr = DecomposeFunctions(aTranslation,sTempExpr)
		elseif nStage == 3 then
			-- process parantheses (expr)
			sTempExpr = DecomposeParantheses(aTranslation,sTempExpr)
		elseif nStage == 4 then
			-- create operands from remaining constant types (number, boolean)
			-- not sooner because of possible numbers in function names
			sTempExpr = CreateConstantOperands(aTranslation,sTempExpr)
		elseif nStage == 5 then
			-- create simple (unary/binary) operations, now we only have operands to work with
			sTempExpr = CreateBasicOperations(aTranslation,sTempExpr)
		elseif nStage == 6 then
			-- still don't have a result operand
			RaiseExpressionsError(aTranslation,ERR.SYNTAX)
		end
		-- contains only [n] ?
		nResultOp = OPStonumber(sTempExpr)
		if nResultOp then
			-- expression contains final result operand
			return nResultOp
		end
		nStage = nStage+1
	end
end

DecomposeExpression = function(aTranslation,sExpression)
	return OPNtostring(CreateExpressionOperand(aTranslation,sExpression))
end

-- removes all variable references from the expression and replaces them with operand identifiers (indexes in operand table)
-- for example "blah blah $TY lefhoihfoe $HIG fslhf" will look like "blah blah [1] lefhoihfoe [2] fslhf"
-- operands with indexes 1 and 2 have then been created in the operand table
local function CreateVariableOperands(aTranslation,sExpression)
	local sReplExpr = strgsub(sExpression,"%s*%$%a+%s*",function(sVar) return FetchVariableOperand(aTranslation,sVar) end)
	return sReplExpr
end

-- replaces the short stat notations for the calcstat function, like @STATNAME# etc
-- the short notations will be replaced by the normal CALCSTAT("STATNAME",$L,$N) or more complex
-- while we are at it, any variable operand use for $L/$N implicated or constant number operands detected, are being processed on the fly
local function GatherCalcStatShorts(aTranslation,sExpression,aProcExpr)
	local nExprIndex = 1
	local nLastIndex
	local nPatEnd, sSN, sL, sHash, sNorC
	local nSNLevelStart, sSNLevel
	while true do
		nLastIndex = nExprIndex
		nExprIndex = strfind(sExpression,"@",nExprIndex,true)
		if not nExprIndex then
			if #sExpression >= nLastIndex then
				-- add remaining text part after last short
				tableinsert(aProcExpr,strsub(sExpression,nLastIndex))
			end
			return
		end
		if nExprIndex > nLastIndex then
			-- add text part between previous and current short
			tableinsert(aProcExpr,strsub(sExpression,nLastIndex,nExprIndex-1))
		end
		nExprIndex = nExprIndex+1

		-- get stat name & optional attached level
		_, nPatEnd, sSN = strfind(sExpression,"^(-?%a%w*)%s*",nExprIndex)
		if not sSN then
			-- syntax error
			RaiseExpressionsError(aTranslation,ERR.CALCSTATSHORTSYNTAX,strsub(sExpression,nExprIndex-1) )
		end
		nExprIndex = nPatEnd+1

		tableinsert(aProcExpr,"CALCSTAT(")

		-- test for attached level number constant in sSN
		nSNLevelStart, _, sSNLevel = strfind(sSN,"(%d+)$")
		-- test for level expression
		_, nPatEnd, sL = strfind(sExpression,"^(%b())%s*",nExprIndex)
		-- process stat name and level
		if sL then
			-- found level expression
			nExprIndex = nPatEnd+1
			if sSNLevel then
				-- found attached level, which is double when we have a level expression as well
				RaiseExpressionsError(aTranslation,ERR.CALCSTATSHORTDOUBLELVL,"@"..sSN..sL)
			end
			sSN = FetchStringConstant(aTranslation,"\""..sSN.."\"") -- transform statname to string constant
			tableinsert(aProcExpr,sSN)
			tableinsert(aProcExpr,",")
			-- contains level expression between parantheses
			GatherCalcStatShorts(aTranslation,strmatch(sL,"^%(%s*(.-)%s*%)$"),aProcExpr) -- remove parantheses, get expression
		else
			if sSNLevel then
				-- split off number constant from stat name
				sSN = strsub(sSN,1,nSNLevelStart-1) -- first part minus level
				sL = FetchNumberConstant(aTranslation,sSNLevel) -- transform level to number constant
			else
				-- no level number constant found, so use default variable $L
				sL = FetchVariableOperand(aTranslation,"$L") -- create level variable (or get if already exists)
			end
			-- process stat name
			sSN = FetchStringConstant(aTranslation,"\""..sSN.."\"") -- transform statname to string constant
			tableinsert(aProcExpr,sSN)
			tableinsert(aProcExpr,",")
			tableinsert(aProcExpr,sL)
		end
		
		-- test for hash
		_, nPatEnd, sHash = strfind(sExpression,"^(#)%s*",nExprIndex)
		-- process NorC
		if sHash then
			nExprIndex = nPatEnd+1
			tableinsert(aProcExpr,",")
			-- test for NorC expression
			_, nPatEnd, sNorC = strfind(sExpression,"^(%b())%s*",nExprIndex)
			if sNorC then
				nExprIndex = nPatEnd+1
				-- contains NorC expression between parantheses
				GatherCalcStatShorts(aTranslation,strmatch(sNorC,"^%(%s*(.-)%s*%)$"),aProcExpr) -- remove parantheses, get expression
			else
				-- test for N constant with decimals
				_, nPatEnd, sNorC = strfind(sExpression,"^(%d+%.%d+)%s*",nExprIndex)
				if not sNorC then
					-- test for N constant without decimals
					_, nPatEnd, sNorC = strfind(sExpression,"^(%d+)%s*",nExprIndex)
				end
				if sNorC then
					nExprIndex = nPatEnd+1
					-- contains N number constant
					sNorC = FetchNumberConstant(aTranslation,sNorC) -- transform value for $N to number constant
				else
					-- only hash
					sNorC = FetchVariableOperand(aTranslation,"$N") -- create N variable (or get if already exists)
				end
				tableinsert(aProcExpr,sNorC)
			end
		end

		tableinsert(aProcExpr,")")
	end
end

local function ReplaceCalcStatShorts(aTranslation,sExpression)
	local aProcExpr = {}
	GatherCalcStatShorts(aTranslation,sExpression,aProcExpr)
	return tableconcat(aProcExpr)
end

-- extracts string operands from the expression and replaces them with the operand index indicator '[n]'
local function CreateStringConstants(aTranslation,sExpression)
	return strgsub(strgsub(sExpression,"\\.",function(sEscapeChar)
					if sEscapeChar == "\\\"" then return "\\q"
					else return sEscapeChar
					end
				end),"%s*\".-\"%s*",function(sString) return FetchStringConstant(aTranslation,sString) end)
end

-- sets a variable to a value and nullifies depending operands' values, so they'll be recalculated at execution time
local function SetExpressionVariable(aTranslation,sVarName,xNewValue)
	if type(aTranslation) ~= "table" then
		return nil, {Source = "CalcStat:Expressions", Stage = EXPRERR_AT_INITIALIZATION, Code = ERR.MISSINGTRANSLATION[1], Message = ERR.MISSINGTRANSLATION[2], Detail = "Function 'SetExpressionVariable'"}
	end
	if type(sVarName) ~= "string" then return end
	local nVar = aTranslation[TRANS_VARNAMEIDX][strupper(sVarName)]
	if nVar then
		return SetVariableValue(aTranslation,nVar,xNewValue)
	end
end

-- sets the values of multiple variables (table keys = variable names, table values = variable values)
local function SetExpressionVariables(aTranslation,aSetVariables)
	if type(aTranslation) ~= "table" then
		return nil, {Source = "CalcStat:Expressions", Stage = EXPRERR_AT_INITIALIZATION, Code = ERR.MISSINGTRANSLATION[1], Message = ERR.MISSINGTRANSLATION[2], Detail = "Function 'SetExpressionVariables'"}
	end
	if type(aSetVariables) ~= "table" then return end
	local nVar
	for sVarName, xNewValue in pairs(aSetVariables) do
		if type(sVarName) ~= "string" then return end
		nVar = aTranslation[TRANS_VARNAMEIDX][strupper(sVarName)]
		if nVar then
			SetVariableValue(aTranslation,nVar,xNewValue)
		end
	end
end

-- process translation stages
local function ProcessExpression(aTranslation,sExpression)
	local nStage = 1
	local nResultOp
	local sTempExpr = sExpression
	while true do
		aTranslation[TRANS_EXPRWIP] = sTempExpr
		if nStage == 1 then
			-- check initial state
			if type(sTempExpr) ~= "string" then
				RaiseExpressionsError(aTranslation,ERR.MISSINGEXPRESSION,"Expression:"..type(sTempExpr)..", Expecting:string")
			end
		elseif nStage == 2 then
			-- remove comments between /* */
			sTempExpr = trim(strgsub(sTempExpr,"(/%*.-%*/)",""))
			if sTempExpr == "" then
				-- nothing left there
				RaiseExpressionsError(aTranslation,ERR.MISSINGEXPRESSION,"")
			end
		elseif nStage == 3 then
			-- create operands for string constants
			sTempExpr = CreateStringConstants(aTranslation,sTempExpr)
		elseif nStage == 4 then
			-- convert expression to uppercase now we have processed the strings +
			-- replace CalcStat shorts: @StatName etc with function call expressions
			sTempExpr = ReplaceCalcStatShorts(aTranslation,strupper(sTempExpr))
		elseif nStage == 5 then
			-- create operands for variables
			sTempExpr = CreateVariableOperands(aTranslation,sTempExpr)
		elseif nStage == 6 then
			-- extract operations - returns "[n]", with indicating operand index n containing the final result
			sTempExpr = DecomposeExpression(aTranslation,sTempExpr)
		elseif nStage == 7 then
			-- still don't have a result operand
			RaiseExpressionsError(aTranslation,ERR.SYNTAX)
		end
		-- contains only [n] ?
		nResultOp = OPStonumber(sTempExpr)
		if nResultOp then
			-- expression contains final result operand
			aTranslation[TRANS_EXPRWIP] = OPNtostring(nResultOp)
			aTranslation[TRANS_RESULTOP] = nResultOp
			-- check availability TIMESTAMP variable
			if not os then
				-- if not: set to unsupported (when referenced at all)
				SetExpressionVariable(aTranslation,"TIMESTAMP","<unsupported>")
			end
			return aTranslation
		end
		nStage = nStage+1
	end
end

-- translates an expression to an intermediate object, given a definition of runtime variables.
-- resulting object may be evaluated/executed (see ExecuteExpression()), while providing runtime variables with values.
local function TranslateExpression(sExpression,aInitVariables)
	-- basic initialization of translation object
	local aTranslation =
		{
			sExpression, -- TRANS_EXPRESSION Original expression which translation will represent
			"", -- TRANS_EXPRWIP expression work in progress: expression in various states of translation
			0, -- TRANS_RESULTOP operand index which will hold the result
			nil, -- TRANS_ERROR indicating last error during translation or execution
			{}, -- TRANS_OPERATIONS Operations table
			{}, -- TRANS_OPERANDS Operands table
			{}, -- TRANS_OPSOURCEIDX Operands table index on operand source
			{}, -- TRANS_VARIABLES Variables table
			{}, -- TRANS_VARNAMEIDX Variables table index on variable name
			0, -- TRANS_OPERANDREQUESTS current number of requests for an operand
			10000, -- TRANS_MAXOPERANDREQUESTS maximum number of requests for an operand (should be enough for translating an expression)
			0 -- TRANS_EXECUTIONS executions counter
		}
	if type(aInitVariables) == "table" then
		-- populate variable table with supplied variables
		local aTransVars = aTranslation[TRANS_VARIABLES]
		local aTransVarNameIdx = aTranslation[TRANS_VARNAMEIDX]
		local sVarName
		for INITVAR_NAME, INITVAR_VALUE in pairs(aInitVariables) do
			sVarName = strupper(INITVAR_NAME)
			aTransVars[#aTransVars+1] =
				{
					sVarName, -- OPERAND_VALUE variable's name
					INITVAR_VALUE, -- OPERAND_OPERATION initial value
					{} -- OPERAND_DEPENDSON set of operands which rely on variable's value
				}
			aTransVarNameIdx[sVarName] = #aTransVars -- store name+index into variable name searchindex
		end
	end
	return ErrorProtectedCall(aTranslation,ProcessExpression,sExpression)
end

-- execute translated expression and return result
-- needs a translation object, optionally number of maximum operand requests, default: 10000
local function ExecuteExpression(aTranslation,aSetVariables,nMaxOpRequests)
	if type(aTranslation) ~= "table" then
		return nil, {Source = "CalcStat:Expressions", Stage = EXPRERR_AT_EXECUTION, Code = ERR.MISSINGTRANSLATION[1], Message = ERR.MISSINGTRANSLATION[2], Detail = "Function 'ExecuteExpression'"}
	end
	aTranslation[TRANS_EXECUTIONS] = aTranslation[TRANS_EXECUTIONS]+1
	if type(aSetVariables) == "table" then
		SetExpressionVariables(aTranslation,aSetVariables)
	end
	-- check availability TIMESTAMP variable
	if os then
		-- if so: set execution time now (when referenced at all)
		SetExpressionVariable(aTranslation,"TIMESTAMP",strgsub(os.date("%H:%M, %d %B %Y (UTC)"),", 0",", "))
	end
	 -- init operand request counter
	aTranslation[TRANS_OPERANDREQUESTS] = 0
	if type(nMaxOpRequests) == "number" then
		aTranslation[TRANS_MAXOPERANDREQUESTS] = nMaxOpRequests
	else
		aTranslation[TRANS_MAXOPERANDREQUESTS] = 10000
	end
	return ErrorProtectedCall(aTranslation,GetOperandValue,aTranslation[TRANS_RESULTOP])
end

-- translate and execute for a one time expression evaluation result
local function OneShotExpression(sExpression,aInitVariables,nMaxOpRequests)
	local xResult
	-- translate expression
	local aTranslation, e = TranslateExpression(sExpression,aInitVariables)
	if not e then
		-- execute expression
		xResult, e = ExecuteExpression(aTranslation,nil,nMaxOpRequests)
	end
	return xResult, e
end

-- to be used by other modules
p.SetExpressionVariable = SetExpressionVariable -- sets the value of a variable (if it exists - doesn't create a new one)
p.SetExpressionVariables = SetExpressionVariables -- sets the values of multiple variables at once (if they exists - doesn't create new ones)
p.TranslateExpression = TranslateExpression -- translates an expression and returns translated object / interpreter code
p.ExecuteExpression = ExecuteExpression -- executes translated object / interpreter code and returns result value
p.OneShotExpression = OneShotExpression -- translate and execute for a one time expression evaluation result

-- ************************ End CalcStat Expressions **************************

-- ********************** from here EXTRA for Wiki use ************************

-- Error sources
local ERRSOURCE_MODULE = "Module:CalcStat"

-- to be called by #invoke
function p.calc(frame)
	local sStatNameOrExpression, sLevel, sNorC, sFormat, sDisplay = frame.args[1], frame.args[2], frame.args[3], frame.args[4], frame.args[5] -- get parameters passed to #invoke

	-- did we get something? a stat name or expression is mandatory
	sStatNameOrExpression = trim(sStatNameOrExpression)
	if sStatNameOrExpression == "" then
		return DisplayableError({Source = ERRSOURCE_MODULE, Code = 1001, Message = "Missing stat name or expression"})
	end

	-- test for stat name or expression
	local bUseExpression = false
	local sSN
	repeat
		sSN = strmatch(sStatNameOrExpression,"^-?%a%w*%a$") -- allow nested digits in stat name and a starting -
		if sSN then	break end
		sSN = strmatch(sStatNameOrExpression,"^-?%a$") -- to allow single character stat name
		if sSN then	break end
		bUseExpression = true
		sSN = sStatNameOrExpression
	until true
	sSN = strupper(sSN) -- uppercase and trimmed for keyword matching

	-- L (optional)
	local nL = 1 -- default
	if sLevel then
		local nLtest = tonumber(sLevel)
		if nLtest then
			nL = nLtest
		end
	end

	-- NorC (optional)
	local xNorC
	local nN = 1 -- default
	local sC = "" -- default
	if sNorC then
		local nNtest = tonumber(sNorC)
		if nNtest then
			-- optional N
			xNorC = nNtest
			nN = nNtest
		else
			-- optional C
			xNorC = sNorC
			sC = sNorC
		end
	end

	-- Format (optional)
	sFormat = sFormat or ""
	-- Display (optional)
	sDisplay = strupper(trim(sDisplay)) -- uppercase and trimmed for keyword matching

	-- calculate result
	local xResult, e
	if bUseExpression then
		-- invoke does not contain a valid stat name
		-- so try for an expression instead with variables $L, $N and $C:
		xResult, e = OneShotExpression(sStatNameOrExpression,{
				L = nL,
				N = nN,
				C = sC
			})
	else
		xResult, e = CalcStat(sSN,nL,xNorC)
	end
	
	-- return result
	if e then
		e.Source = e.Source.." invoked by "..ERRSOURCE_MODULE
		return DisplayableError(e)
	else
		if type(xResult) == "boolean" then
			-- convert boolean to string result
			if xResult then
				xResult = "True"
			else
				xResult = "False"
			end
		end
		return DisplayableStatValue(sSN,xResult,sFormat,sDisplay,frame)
	end
end

return p