Module:CalcStat
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:
- Direct Download: Download the source code directly from LoTROInterface. The source files will be within the downloaded zip file.
- 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:
- 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. - Run the compiler script: Execute the
statdcmp.vbs
script on a Windows system. - Select output option: When prompted by the script, choose option 6: "Lua-script (Lotro-Wiki Module)".
- Select stats inclusion: Next, choose option 1 to "include all stats".
- Locate the output file: The compiler will generate a file named
CalcStat.lua
. ThisCalcStat.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. Thecalcstat.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
Format
: optional format string. Default for number results is%.0f
. See also Printf_format_string.
- Assuming a value of 12345.016:
%'d
displays a thousand separated number for main stats (whole numbers; rounded down when fractured) like: 12,345%'+d
displays a thousand separated number for main stats (whole numbers; rounded down when fractured) with a forced sign like: +12,345%.0f
(default) displays a number for rating stats (fractured numbers; normal rounding to given precision 0 decimals) like: 12345%+.0f
displays a number for rating stats (fractured numbers; normal rounding to given precision 0 decimals) with a forced sign like: +12345%'.1f
displays a thousand separated number for DPS (fractured numbers; normal rounding to given precision 1 decimal) like: 12,345.0%'.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%'.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:
AddP
: Display Additive Percentage (with a 0.0002 correction).AddP100
: Mutltiply by 100 & display as Additive Percentage (with a 0.0002 correction).MultiP
: Display Multiplier Percentage (with a 0.0002 correction).MultiP100
: Mutltiply by 100 & display as Multiplier Percentage (with a 0.0002 correction).Worth
: Displays value in gold/silver/copper (from number value in format ..ggggssscc).Corr
: Correction. 0.0002 is added to any fractured number (this is the default for numbers).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.
|
|
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.
|
|
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.
|
|
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.
|
|
- ↑ 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: |
|
Position 2: |
|
Position 3: |
|
---|
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: |
|
Position 2: |
|
Position 3: |
|
---|
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.
|
|
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