Notice: This module is currently in limited alpha-testing. Currently this module only supports weapons, armors, and accessories. Support for ability materia, consumables, and enhancer units are pending.
This module is a work in progress. Do not convert pages which contain information that the module cannot display, however please do inform CodeHydro of the name of a such a page so that he may add support for such information.
- Data/testcases
- Data/testcases/1
- Data/testcases/10
- Data/testcases/11
- Data/testcases/12
- Data/testcases/2
- Data/testcases/3
- Data/testcases/4
- Data/testcases/5
- Data/testcases/6
- Data/testcases/7
- Data/testcases/8
- Data/testcases/9
- Data/testcases/A
- Data/testcases/abilities
- Data/testcases/abilities/1
- Data/testcases/abilities/10
- Data/testcases/abilities/2
- Data/testcases/abilities/3
- Data/testcases/abilities/4
- Data/testcases/abilities/5
- Data/testcases/abilities/6
- Data/testcases/abilities/7
- Data/testcases/abilities/8
- Data/testcases/abilities/9
- Data/testcases/abilities/A
- Data/testcases/abilities/B
- Data/testcases/abilities/C
- Data/testcases/abilities/D
- Data/testcases/abilities/E
- Data/testcases/abilities/F
- Data/testcases/abilities/G
- Data/testcases/abilities/H
- Data/testcases/abilities/I
- Data/testcases/items/1
- Data/testcases/span
Module:Data standardizes the output of various article pages and allows those pages to be transcluded like a Template so that updating that one page may automatically sync the information across all pages.
When using this module, the #invoke tag must be wrapped inside an onlyinclude tag, which must not contain any newline characters outside of the #invoke tag.
Good: | Bad: |
<onlyinclude>{{#invoke:Data|func ... }}</onlyinclude> |
<onlyinclude> {{#invoke:Data|func ... }} </onlyinclude> |
Contents
Usage for Equipment
Empty template
Below is an empty template with commonly used parameters for equipment. Click inside to select all.
<onlyinclude>{{#invoke:Data|item <!--For details on how this module works, visit http://exvius.gamepedia.com/Module:Data--> |name = <!-- only necessary for testcases; defaults to page title if blank --> |image = <!-- leave blank unless image is not at File:icon-[name].png --> |desc = <!--Statistics--> |type = |HP = |MP = |ATK = |DEF = |MAG = |SPR = |element= |resist = |effect = |ability= |warning= <!--Notes--> |notes = <!--Crafting Recipe--> |recipe = |buy_rec= |rec_gil= |rec_mat= <!--Usage--> |usage = |quest = <!--How to obtain--> |buy_gil= |quartz = |shop = |drop = |steal = |explore= |chest = |reward = |trust = |STMR = |obtain = <!--Equippable By--> |used_by= }}</onlyinclude> <!--Add unique categories and unique sections below-->
Data page (#invoke page)
Intro section | ||||||||||||||||||||||||
Parameter | Description | |||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
name |
Takes the name of the item | |||||||||||||||||||||||
image |
Usually left blank. Allows the specification of an image file when the image name does not match the form File:Icon-name.png where name is replaced with the value passed to |name= .
| |||||||||||||||||||||||
desc |
Takes the description (or "story") of the item | |||||||||||||||||||||||
Statistics section | ||||||||||||||||||||||||
Parameter | Description | |||||||||||||||||||||||
type |
Takes the type of equipment (case sensitive). For weapons and armor, enter only the value normally displayed in parenthesis. For example, type = Great Sword produces:
| |||||||||||||||||||||||
HP MP ATK DEF MAG SPR |
Takes either a whole number or a percentage value. For items that grant both a fixed and a percentage stat, enter both fixed and percentage parts with a + character between them.
| |||||||||||||||||||||||
element
|
Takes whatever element the weapon bestows upon the unit's attacks.
| |||||||||||||||||||||||
resist
|
Takes a list of resistances separated by commas. Status ailments are autolinked.
| |||||||||||||||||||||||
ability effect
|
Takes a list of ability/effect values separated by commas. Values that do not contain For
Note that eventually it is planned for tooltips (as shown above for Fire) to be automatically generated when autolinked once Module:Data has been extended to abilities. | |||||||||||||||||||||||
Warning
|
Takes a value which is appended to the end of the Additional effects bullet without autolink. This value is shown in bold in categories.
Example on category pages:
| |||||||||||||||||||||||
Notes section | ||||||||||||||||||||||||
Parameter | Description | |||||||||||||||||||||||
notes |
Enter any additional information related to the item. For example, this may include details on any unique ability it grants. | |||||||||||||||||||||||
Crafting Recipe section | ||||||||||||||||||||||||
Parameter | Description | |||||||||||||||||||||||
recipe
|
Takes a list of locations or events (separated by commas) where the recipe can be obtained. This list will appear in the "How to Obtain" section.
| |||||||||||||||||||||||
buy_rec |
Enter the cost to purchase the recipe from a shop. | |||||||||||||||||||||||
rec_gil |
Enter the cost to use the recipe to craft the item. | |||||||||||||||||||||||
rec_mat |
Takes a list of materials required to craft and their quantity, separated by commas. | |||||||||||||||||||||||
time |
Enter the time it takes to craft the item. This parameter is no longer in use. | |||||||||||||||||||||||
| ||||||||||||||||||||||||
Usage section | ||||||||||||||||||||||||
Parameter | Description | |||||||||||||||||||||||
usage |
Separate groups with semi-colons and items with commas. First item in group should be the group title, separated from the list with a colon. Autolinked.
| |||||||||||||||||||||||
quest |
Separate values with commas. Autolinked.
| |||||||||||||||||||||||
How to obtain section | ||||||||||||||||||||||||
Parameter | Description | |||||||||||||||||||||||
buy_gil quartz |
Enter the purchase cost of the item. If |quartz= is given, then |buy_gil= will be ignored and the Shops subsection will be replaced by Fat Chocobo. Item/item2 modes will show start quartz as the currency automatically.
| |||||||||||||||||||||||
shop drop steal explore chest reward |
Enter location values separated by commas.
Location values which do not contain Note that the table form of | |||||||||||||||||||||||
trust |
Takes the name of the unit that provides this item as a Trust Mastery Reward. | |||||||||||||||||||||||
STMR |
Takes the name of the unit that provides this item as a Super Trust Mastery Reward. | |||||||||||||||||||||||
obtain |
| |||||||||||||||||||||||
Equippable By section | ||||||||||||||||||||||||
Parameter | Description | |||||||||||||||||||||||
used_by
|
Enter Units that can use the item, separated by commas. This is usually meant for equipment that is locked to a specific unit.
|
Usage for Abilities
Empty template
Below is an empty template with commonly used parameters for abilities. Click inside to select all.
<onlyinclude>{{#invoke:Data|item <!--For details on how this module works, visit http://exvius.gamepedia.com/Module:Data--> |name = <!-- only necessary for testcases; defaults to page title if blank --> |image = <!--Ability_#.png--> <!--Statistics--> |type = <!--Active, Passive, White, Black, Green, or Blue--> |mag_lv = |effect = <!--For unconditional passive stats, use HP/MP/ATK etc. parameters instead.--> |chain = |hits = |atk_frm= <!--rarely given--> |MP_cost= |filter = |HP = |MP = <!--Do not enter MP cost here. This is for the likes of MP +10%.--> |ATK = |DEF = |MAG = |SPR = |evade_p= |evade_m= <!--Abilities--> |ability= <!--Notes--> |notes = <!--Crafting Recipe--> |recipe = |buy_rec= |rec_gil= |rec_mat= <!--Usage--> |usage = |quest = <!--How to obtain--> |buy_gil= |quartz = |shop = |chest = |reward = |equip = |materia= |learn = <!-- ! Name !! Min rarity !! Level --> |esper = <!-- ! Name !! Min rarity --> |enable = |trust = |STMR = |obtain = <!--Equippable By--> |used_by= <!--Ability Awakening |Unit Name+1= awk_mat= Power/Tech/White/etc.,t1[,t2,t3...],gil MP_cost= 5 one enemy => all enemies --> }}</onlyinclude> <!--Add unique categories and unique sections below-->
Data page (#invoke page)
Intro section | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Parameter | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
name |
Takes the name of the item | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
image |
Takes the image used by the item. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Statistics section | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Parameter | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type |
Takes the ability's type (Case Sensitive). The valid types are Active , Passive , White , Black , Green , Blue .
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mag_lv |
Takes a number representing the magic level.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
effect |
Takes a list of effects separated by new line characters. All effects are passed to this parameter EXCEPT:
For effects that enable other skills, you may also list special instructions called Overrides, which will be discussed in greater detail later.
OverridesOverride instructions may be used in two ways to:
Usually overrides have no visible effect outside of Unlike awakening overrides (which can override all parameters), enabled effect overrides can only override the following parameters:
You do not need to override all three. Any remaining data will be fetched from the page if available or replaced with They can take the form Also unlike with awakening overrides, multi-line values must be kept on the same line, using | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
chain |
Takes a chaining family name. Finds the corresponding chaining family and autolinks to it.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
hits |
Takes the number of hits. For randomized abilities, separate the hit count for each ability with either / or ; (interchangeable).
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
atk_frm |
Takes the frame (delay in 1/60 seconds) of each hit. Frames can be separated by either If there are fewer
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MP_cost |
Takes a number for the MP cost of the ability. For MP bonuses, use |MP=
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
filter |
Highlights specified abilities. Finds the corresponding abilities within a given page's table and is controlled by a "Filter" button that highlights the background color of the specified abilities. Used for distinguishing 2 or more abilities can be multi-cast.
Multi-cast spells are not included. Page translation currently does not work as the original name is required (e.g. use
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Passive Stats | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
HP |
Takes a percentage value. This is for stat bonuses that have no requirements and are usable by any unit. Conditional bonuses (for example "when equipped with a Robe", should be defined in |effect= .
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MP
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ATK
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DEF
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MAG
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SPR
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
evade_p
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
evade_m
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Abilities section | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Parameter | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ability |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Notes section | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Parameter | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
notes |
Enter additional notes about the ability, such as how it stacks and interacts with equipment or other abilities. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Crafting Recipe section | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Parameter | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
recipe |
Takes a list of locations or events (separated by commas) where the recipe can be obtained. This list will appear in the "How to Obtain" section. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buy_rec |
Takes the cost to purchase the recipe from a shop. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
rec_gil |
Takes the cost to use the recipe to craft the item. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
rec_mat |
Takes a list of materials required to craft and their quantity, separated by commas. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Usage section | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Parameter | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
usage |
Takes separate groups with semi-colons and items with commas. First item in group should be the group title, separated from the list with a colon. Autolinked. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
quest |
Takes separate values with commas. Autolinked. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
How to obtain section | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Parameter | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buy_gil |
Enter the purchase cost of the item. If |quartz= is given, then |buy_gil= will be ignored and the Shops subsection will be replaced by Fat Chocobo. Item/item2 modes will show start quartz as the currency automatically
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
quartz
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
shop |
Takes location values separated by commas.
Location values which do not contain Tables may be entered using alternative markup as shown below: |learn = ! Name !! Min rarity !! Level [[Leah]] $ {{Rarity|1}} $ 1 [[Anastasis]] $ {{Rarity|2}} $ 1 [[Fina]] $ {{Rarity|2}} $ 1 [[Gimlee]] $ {{Rarity|2}} $ 3 [[Ovelia]] $ {{Rarity|3}} $ 1 [[Luna]] $ {{Rarity|3}} $ 25 [[Vanille]] $ {{Rarity|4}} $ 1 [[Agrias]] $ {{Rarity|4}} $ 7 Also accepts wikitable markup when |esper ={{#invoke:wikitable|main|class="wikitable sortable" style="text-align:center;" ! Name !! Min rarity |- | [[Carbuncle]] || {{Rarity|1}} |- | [[Lakshmi]] || {{Rarity|1}} |- | [[Shiva]] || {{Rarity|1}} |- | [[Siren]] || {{Rarity|1}} }}
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
chest
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
reward
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
equip
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
materia
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
learn
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
esper
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
enable |
Takes ability values separated by commas. Autolinked. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
trust |
Takes the name of the unit that provides this ability as a Trust Mastery Reward. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
STMR |
Takes the name of the unit that provides this ability as a Super Trust Mastery Reward. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
obtain |
Takes separate groups with semi-colons and items with commas for any other method of obtaining the ability, such as premium bundles. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Equippable By section | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Parameter | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
used_by |
Takes a comma separated list of units that can use this ability. This is usually meant for Ability Materia that is locked to a specific unit. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Ability Awakening section | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Parameter | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Awakening parameters are the only parameters relevant to abilities which are not included the Empty Template due to the uniqueness of awakenings. To be properly handled, the name of the parameter must have the form Awakening parameters take a series of instructions, separated by newline characters, and are read sequentially. Though a little complex at first glance, writing these instructions should be fairly easy once you've learned the syntax. There are four basic instructions:
For the most part, bold and | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Instruction | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Replace |
Replace takes the form Any replacements made are cascaded to the next awakening level, so replacements should be adjusted accordingly, as shown in this example from Curaga:
Because replacements are based on the output, not the input, autolinked text must be manually linked in order to match. For example, based on Lovely Guard+1 for Marie:
If a replacement is a success on last section of the ability's page, it is usually successful on the Ability Awakening page as well, however, because bold and strikeouts are not stripped between awakening levels for the latter page, you will need to include the autobolded output when replacing text the text surrounding an autobolded substring [insert Unlimited example]] Replace instruction from previous awakening levels do not survive recalculations, which can be triggered by override instructions (described in Override). However, those in the current awakening will be applied after any recalculation is done (and before append instructions).
If B is omitted, this becomes a Strikeout instruction. Note that the first letter of the next word will be automatically capitalized if the striked text is from the beginning of the output. Example from Pray (Replace instruction highlighted; blank comment is optional but helps readability):
If A is omitted (
If A contains
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Override |
Override changes the value of any parameter (or sets the value when one is not there). This instruction takes the form Will trigger a recalculation if overridden parameter is either If the original unawakened effect is contained within the recalculated effect, then the original part will be unbolded. Conversely, if the recalculated effect is found within the base effect, the new effect will remain unbolded (See Chaos Wave) Example from Tri-beam Laser:[tip 2] |Ace+2= awk_mat= Power,23,15,12,4,2,500000 effect = Randomly use: (30%) Tri-beam Laser (white) (30%) Tri-beam Laser (yellow) (30%) Tri-beam Laser (orange) (10%) Tri-beam Laser (red) Decrease fire, lightning, and light resistance (75%) for 3 turns to all enemies ability= {{{effect}}} Magic damage (4.2x) with ignore SPR (25%) to all enemies Magic damage (5.6x) with ignore SPR (25%) to all enemies Magic damage (22.5x) with ignore SPR (25%) to all enemies
Any Replace or Append instructions from previous awakenings will be lost upon recalculation, though those listed for the current awakening will be applied after recalculation (even if listed before a recalculating override). Recalculation is always done after all overrides have been processed. Finally, although the awakening overrides resemble enabled effect overrides from the Statistics section, you cannot use the form | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Append |
Append instructions are lines which do not contain any operators ( Example from Pray:
Empty lines are ignored. If a gap is desired, you may simply enter Appended effects have partial auto-linking for killers, equipment, and status ailments, but NOT for enabled abilities. They are also not pattern processed for auto-tables. (Full auto-linking and auto-table require overrides instead.) Append instructions from previous awakening levels will not survive recalculation, however those in the current awakening will be applied after any recalculation is done (and after any Replace instructions). Finally, do not use append instructions to add lines such as | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Import |
Import all instructions from another awakening parameter simply by entering the target parameter name as the first line by itself. Must be the first instruction. You may include additional instructions afterwards. Example from Curaga:
Note how |
- ↑ In the past, overriding #Passive Stats triggered recalculation. This is no longer the case.
- ↑ Note that
{{{effect}}}
can be used in lieu of retyping the original effect (at least for single-line effects).
Usage for Items
Empty template
Below is an empty template with commonly used parameters for items. Click inside to select all.
<onlyinclude>{{#invoke:Data/testcases|item <!--For details on how this module works, visit http://exvius.gamepedia.com/Module:Data--> |name = |image = <!-- leave blank unless image is not at File:icon-[name].png --> |desc = <!--Statistics--> |type =Item |effect =Revive one KO'd ally (20% HP) <!--Notes--> |notes =*When used on a [[:Category:Reapers|reaper]] enemy, it kills them instantly. <!--Crafting Recipe--> |recipe = |buy_rec= |rec_gil= |rec_mat= <!--Usage--> |usage = |quest = <!--How to obtain NOTE: Info displayed in this section will not be listed in any particular order. Parameter numbers do not affect the order they will appear on the page. Module:Data does not preserve order to reduce server load.--> |buy_gil= |quartz = |shop = |drop = |steal = |explore= |chest = |trust = |obtain = <!--Equippable By--> |used_by= }}</onlyinclude> <!--Add unique categories and unique sections below-->
Tranclusion (modes)
Any supported item can be transcluded into wiki pages in the form of table rows. This allows quick creation of item tables (such as a shop table) while keeping data consistent across all pages. The following modes are supported when transcluding Module:Data item pages:
Mode | Description | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
item
|
Used for shop pages. This mode is the default whenever equipment pages are transcluded onto non-category pages. Non-equipment pages default to |mode=typeless instead.
| ||||||||||||||||||||||
item2
|
Similar to item mode, except an icon will be included
| ||||||||||||||||||||||
recipe
|
Used for recipes sold in shops.
| ||||||||||||||||||||||
typeless
|
Variant of |mode=item which skips the type column and sets colspan=2 on the statistics cell. This mode automatically applied for non-equipment.
[example] | ||||||||||||||||||||||
category
|
This mode is generally only explicitly declared to emulate category displays on non-category namespace. When an item page is transcluded in category namespace, Module:Data will use category mode automatically. Psuedo-category pages for abilities such as Ability Materia and Special Abilities (Passive) also default to this mode.
| ||||||||||||||||||||||
tooltip
|
Used to make a tooltip. This is the only mode that cannot be customized or extended.
| ||||||||||||||||||||||
custom
|
Creates a table row with no default cells. See #Extension and customization | ||||||||||||||||||||||
fetch
|
Similar to custom except that cells will not be placed on a new table row. | ||||||||||||||||||||||
For abilities only | |||||||||||||||||||||||
conditional
|
[placeholder] | ||||||||||||||||||||||
awaken
|
[placeholder] |
Parameters
The following parameters can also be used on {{:page|parameter=value}}
tags:
Parameter | Applies to | Description | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
sep
|
|mode=fetch
|
By default, each parameter is separated by | |||||||||||||
limit
|
|mode=item
|
Indicates the number of items available in the shop. This value will be displayed under the Price value of the item. Enter an integer or the ∞ symbol (using Setting
| |||||||||||||
skill
|
|mode=awaken
|
See Meteor#Ability Awakening and Terra#Ability Awakening (Terra does not learn Meteor directly but can access the awakened versions via the awakening of Unlock Magic) | |||||||||||||
rowspan
|
|mode=category
|
This parameter is used only for magic abilities to display |mag_lv= , which is not shown by default. This should only be set on the first ability of the magic level.
Example: {| class=wikitable {{:Aeroja|mode=category|rowspan=2}} {{:Stonja|mode=category}} |}
| |||||||||||||
page
|
all transclusions |
This parameter instructs the module to behave as though it were transcluded onto the page specified. In this manner, you may emulate how the item appears on another page without actually placing it on that page, particularly useful for displaying innate abilities (a view that cannot be accessed via |
For magic words, see #Extension and customization.
Wrappers
Creating tables and their headers can be simplified by using , automatically creating the proper table headers and allows you to define any desired table headers. The wrapper takes the following parameters
Parameter | Description |
---|---|
mode |
The type of table you want to create. This will determine which table headers are used for this table. The following modes are available:
|
name |
The title of the table. If the title is Item Shop or Ability Shop , the table will adjust accordingly to only include relevant columns.
|
name# |
Use instead of name if you want multiple titles to divide your rows. Each instance should look like |name1=My first title |name2=my Second title |name3=my Third title and so on in the position you wish you see the table header.
|
[Transcluded Rows] | The rows you want to insert into the table using the matching transclusion modes. |
Example:
{{#invoke:Data|wrap|mode=shop|name1=First Title| {{:Wizard's Staff}} {{:Wizard's Staff|mode=recipe|limit=1}} {{:Earrings}} |name2=Second Title| {{:Ring of the Lucii|mode=item2}} {{:Gaia Gear|mode=item2}} |name3=Ability Shop| {{:Cure}} {{:Miracle Step}} }}
First Title | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Name | Type | Description | Price | |||||||||
Wizard's Staff | Staff | ATK+13, MAG+6, SPR+32 Ability: FireFire
|
![]() | |||||||||
Recipe for Wizard's Staff | - | - | ![]() (Limit: 1) | |||||||||
Earrings | Accessory | DEF+3, MAG +20% | ![]() | |||||||||
Second Title | ||||||||||||
Name | Type | Description | Price | |||||||||
![]() |
Accessory | MAG+3, SPR+3, ATK +30%, MAG +30% Effect: Holy (FFXV)Holy (FFXV)
Ability: AlternaAlterna
|
![]() | |||||||||
![]() |
Robe | DEF+20, MAG+5, SPR+5 Resistance: Wind (-50%), Earth (+50%), Petrify (+30%) |
![]() | |||||||||
Ability Shop | ||||||||||||
Name | Description | Price | ||||||||||
Cure | Magic Abilities | Heal (150 HP, 3x) to one ally | ![]() | |||||||||
Miracle Step | Special Abilities (Passive) | Increase MP (20%) and MAG/SPR (10%) Increase physical evasion (5%) |
![]() |
Extension and customization
Each table can be extended to include additional information by providing the attribute's name as parameters. If the transclusion uses mode=custom
, these parameters are required in order to display a table row.
The data in the cells can be further modified using the format parameter@custom text %s
. Anything after the @
will be displayed in the cell, and the parameter will be displayed in place of %s
. The parameter may be omitted if the cell only contains custom text. If you want to include the @ symbol in your text, you can use \@
.
Example: Simple Extension
{| class="wikitable sortable" ! colspan="8" | Weapon Shop extended |- ! Name !! Type !! Description !! Price !! ATK !! MAG !! DEF !! SPR {{:Wizard's Staff|mode=item|ATK|MAG|DEF|SPR}} {{:Malboro Wand|mode=item|ATK|MAG|DEF|SPR}} {{:Earrings|mode=item|ATK|MAG|DEF|SPR}} |}
Weapon Shop extended | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
Name | Type | Description | Price | ATK | MAG | DEF | SPR | |||
Wizard's Staff | Staff | ATK+13, MAG+6, SPR+32 Ability: FireFire
|
![]() |
13 | 6 | - | 32 | |||
Malboro Wand | Staff | ATK+15, SPR+60 Effect: Blind (10%), Poison (10%) Ability: JinxJinx
Exclusive: Vanille |
![]() |
15 | - | - | 60 | |||
Earrings | Accessory | DEF+3, MAG +20% | ![]() |
- | 20% | 3 | - |
Example: Custom Table
{| class="wikitable" ! colspan="6" | Custom |- ! Name !! Comment !! ATK !! MAG !! DEF !! SPR {{:Wizard's Staff|mode=custom|name|@Custom Text \@ this location|ATK|MAG|DEF|SPR}} {{:Malboro Wand|mode=custom|name@The name of this item is %s!|@|ATK|MAG|DEF|SPR}} {{:Earrings|mode=custom|name@[[%s]]|@The above line is blank|ATK|MAG|DEF|SPR}} |}
Custom | |||||
---|---|---|---|---|---|
Name | Comment | ATK | MAG | DEF | SPR |
Wizard's Staff | Custom Text @ this location | 13 | 6 | - | 32 |
The name of this item is Malboro Wand! | 15 | - | - | 60 | |
Earrings | The above line is blank | - | 20% | 3 | - |
Example: Fetching Data
{{:Wizard's Staff|mode=fetch|sep=,|name|ATK|MAG|DEF|SPR}}
Wizard's Staff,13,6,-,32
Magic Words
In addition to parameter names, you may also pass magic words for more complex output:
Applies to | magic word | Description | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
LINK
|
Shows the item name with a link. |
| ||||||||||||||||||
TYPE
|
Shows the item's type with link to category. |
| |||||||||||||||||||
STATS
|
Shows formatted stats and effects. |
| |||||||||||||||||||
ICON
|
Shows a linked icon. |
| |||||||||||||||||||
BADGE
|
Shows a linked name, icon, and category. |
| |||||||||||||||||||
|mode=exclusiveFX
|
rowonly
|
Omits the table wrap. Used when table has multiple rows. Example: {| class="wikitable" style="text-align:center;" width="100%" ! Icon !! Name !! Type !! Effect {{:Crimson Saber|mode=exclusiveFX|rowonly}} {{:Rain's Clothes|mode=exclusiveFX|rowonly}} |}
| |||||||||||||||||||
|mode=awaken
|
table
|
Shows full table given Awakened Ability. | |||||||||||||||||||
conditional
|
Shows "Conditional" header along with row. Used for abilities unlocked by other abilities. |
The above documentation is transcluded from Module:Data/doc. (edit | history)
local p = {
disable_tooltip = {
["Category:Trust Master Rewards"] = 1,
["Category:Super Trust Master Rewards"] = 1,
["Category:Armors"] = 1,
["Category:Weapons"] = 1,
["Category:Fire"] = 1,
["Category:Fire/2"] = 1,
["Category:Accessories"] = 1
},
stat_order = {'HP','MP','ATK','DEF','MAG','SPR'},
equipment = {
_class ={'Weapon', 'Armor', 'Accessory'},
_plural = {Clothes = 'Clothes', Staff = 'Staves'},
Dagger = 1,
Sword = 1,
["Great Sword"] = 1,
Katana = 1,
Staff = 1,
Rod = 1,
Bow = 1,
Axe = 1,
Hammer = 1,
Spear = 1,
Instrument = 1,
Whip = 1,
["Throwing Weapon"] = 1,
Gun = 1,
Mace = 1,
Fist = 1,
["Light Shield"] = 2,
["Heavy Shield"] = 2,
Hat = 2,
Helm = 2,
Clothes = 2,
["Light Armor"] = 2,
["Heavy Armor"] = 2,
Robe = 2,
Accessory = 3
},
ability = {
_class = {"Special Ability", "Magic Ability"},
Active = 1,
Passive = 1,
White = 2,
Black = 2,
Green = 2,
Blue = 2
},
ailment = {
Poison = 1,
Blind = 1,
Sleep = 1,
Silence = 1,
Paralyze = 1,
Confuse = 1,
Disease = 1,
Petrify = 1
},
killer = {
--Special thanks to FencerTJ for category names (except he forgot humans)
Avians = 'bird',
Plants = "plantoid",
Aquatics = "aqua",
Beasts = "brute",
Demons = "cysidus",
Dragons = "dra[cg]o",
Fairies = "[sf][pa]ir",--spirit or fairy
Insects = "bug",
Machinas = "m[ae]ch",
Stones = "lith",
Reapers = "undead",
Humans = "man-?"
},
patterns = {
--Not all patterns here. Just those used more than once.
wikilink = '%[%[[^%[%]]+%]%]',
only = '%(%[%[([%w ]+)%]%] only%)',
enable = '([^\n]*Enable skill[^\n]-: )([^\n]+)',
multi_break = '[^<]?%s-/?%s*([^>]?.-[^<])%s*/%s-[^>]-',
rng_enable = '\n%(%d+%%%) +[^\n]+: Enable? ',
event = '%(%[?%[?Event[^,]-%)%s*%[?%[?'
},
template = {
evade = 'Increase %s evasion (%s)'
}
}
local result = {}
function result:_(v)
--simplified version of mw:en:Module:Buffer
if v and v ~= '' then table.insert(self, v) end
return self
end
local esc_seq = string.char(127,4,127,2)
function p.item(frame)
local args, p_args, flags, currentTitle, namespace, invokePage = {}, frame:getParent().args, {}
if p_args.page or args.page then
--No worries. Scribunto is sandboxed, so overwriting mw.title.getCurrentTitle won't affect any other #invokes
local emulate = mw.title.new(p_args.page or args.page)
mw.title.getCurrentTitle = function() return emulate end
end
for k, v in pairs(frame.args) do
--Basic cleaning of arguments and argument grouping
v = mw.text.trim(v)
if v and v~='' and v~='-' then args[k] = v end
end
local stats_sorted, stats = {}, {HP = {}, MP = {}, ATK = {}, DEF = {}, MAG = {}, SPR = {}}
for k, v in pairs(stats) do
--grab percents and integers in the form such that DEF+7, DEF+50% is entered as 'DEF=7+50%'
if args[k] then
v[2] = args[k]:match'%-?%d+%%'
if v[2] then v[1] = args[k]:match'^%+?(%-?%d+)%+'--tolerate ATK=+10
else table.insert(v, args[k]:match'^%+?(%-?%d+)$') end
end
end
if p.equipment[args.type] then
for i = 1, 2 do
--show percentage stats after integer stats
for _, v in ipairs(p.stat_order) do--this line controls order of stats
table.insert(
stats_sorted,
stats[v][i] and (i==1 and '%s+%s' or '[[%s +%s]]'):format(v, stats[v][i])
)
end
end
end
local function link(v, hide_disambiguation)
--[[
Autolinks if does not contain a link. If hide_disambiguation evals true, links "Page (Disambigation)" as
"Page (Disambigation)|Page"
]]
return v and (v:find(p.patterns.wikilink) and v
or hide_disambiguation and v:find'%b()' and v:gsub('([^%(]+) %(([^%)]+)%)', '[[%1 (%2)|%1]]')
or v:gsub('^(.-) -( ?\\?%+?%d?)$', function(a, b)
if v == invokePage then a, b = v, ''
elseif b:sub(2, 2) ~= '+' or not tonumber(b:sub(3, 3)) then a, b = a .. b, '' end
return ('[[%s]]%s'):format(a, b):gsub('\\%+', '+')
end, 1))
end
local function chain_link(v, effect)
if effect then
return "{{Chain|" .. v .. "}}"
else
return "[[Chaining/" .. v .. "|" .. v .."]]"
end
end
local function tooltip_link(v, hide_disambiguation)
--Makes tooltip link.
if v == currentTitle then return "'''" .. v .. "'''" end
local fetch, only = {title = ':' .. v, args = {'effect', 'ability', mode = 'fetch'}}
only = frame:expandTemplate(fetch):match('%[%[' .. args.name:gsub('%p', '%%%1') .. '%f[|%]][^%]]-%]%] *%((.- only)%)')
or frame:expandTemplate(
fetch,
rawset(fetch.args, 2, nil),
rawset(fetch.args, 1, 'warning')
):match'[^,]+ only'
only = only and ' (' .. only .. ')' or ''
return ('{{:%s|mode=tooltip%s}}')
:format(v, hide_disambiguation and '' or '|full_pg=1')
.. only
end
local function link2tooltip(v, hide_disambiguation)
--checks all links for Module:Data and replaces them with tooltips when possible. Only use when non-Module:Data pages may be passed
for lookback, wikilink, page in v:gmatch'(.?)(%[%[([^:#][^|%]]+)|?[^%]]*%]%])' do
if lookback ~= '(' and not (page:find':[^ _]' or page:find'#' or stats[page:match'(.+) %+%d'] or mw.title.new(page).redirectTarget) then
-- disable tooltips for various pages to get around template size limit
if currentTitle == "Category:Weapons" or currentTitle == "Category:Super Trust Master Rewards" or
currentTitle == "Category:Trust Master Rewards" or currentTitle == "Category:Armors" or
p.disable_tooltip[currentTitle]
then
local tooltip = ""
else
local tooltip = frame:preprocess('{{msgnw::' .. page .. '}}')
if tooltip:lower():find'#invoke:data%s*|%s*item' then
v = v:gsub(wikilink:gsub('%p', '%%%1'), tooltip_link(page, hide_disambiguation):gsub('%p', '%%%1'))
end
end
end
end
return v
end
local function split_link(v, hide_disambiguation, sep, alt_link_func)
--Splits v by commas and joins with sep (or comma if omitted). Links using link() unless passed alt_link_func
local t = {}
for s in mw.text.gsplit(v:gsub("\\,", esc_seq), ',%s*') do
s = mw.text.trim(s)
if s ~= '' then table.insert(t, (alt_link_func or link)(s, hide_disambiguation)) end
end
return table.concat(t, sep or ', '):gsub(esc_seq, ',')
end
local function multi_split(v, head_format, sep, headless_sep)
--Splits by ';' and passes each to split_link(). If first item prefixed by 'text:', treats 'text' as group name
local result = {_=result._}
for x in mw.text.gsplit(v, ';') do
local group, list = x:gsub('\\:', esc_seq):match'^([^:]+): -(.+)$'
group, list = group:gsub(esc_seq, ':'), list:gsub(esc_seq, ':')
result
:_(group and head_format:format(group) or headless_sep)
:_(split_link(list or x, nil, group and sep or headless_sep, group == 'Equipment' and tooltip_link))
:_'\n'
end
return table.concat(result)
end
local function ailment_link(v, hide_disambiguation)
--Autolinks ailments. When hide_disambiguation is nil or true, also autolinks non-ailments.
local status, chance = v:match'^([^%(]-) ?%(([^%)%(]-)%)'
if status and (p.ailment)[status] then
return ('[[Status Ailments#%s|%s]] (%s)'):format(status, status, chance)
elseif status and v:find' status ailments? ' then return (v:gsub(' (status ailments?) ', ' [[Status Ailments|%1]] ', 1)) end
if hide_disambiguation == false then return v end--for args.resist
return link(v, hide_disambiguation)
end
local function materia_ailment_link(v)
--auto-links ailments for materia.
if v then for i, pattern in ipairs{
'Cures? [^\n<]+ to ',
'Inflicts? [^\n<]+ %(',
'Increase resistance to [^\n<]+ %(',
'Increase [^\n<]+ resistance %(',
'[Rr]emove '
} do if v:find(pattern) then
for ailment in pairs(p.ailment) do
v = v:gsub(
" ('*)" .. ailment:lower(),
(' %s1[[Status Ailments#%s|%s]]'):format('%', ailment, ailment:lower()),
1
)
end
flags.groupStatusCure, v =
flags.groupStatusCure or i == 1 and v:find'all allies',
v:gsub(" ('*)(status ailments?)('*) ", ' %1[[Status Ailments|%2]]%3 ', 1)
break
end end end
return v
end
local function icon(v)
--Makes item image. If passed a string, links to it. If passed true, links to the #invoke page (not name param)
return (v and '[[File:%s|%s|link=%s]]' or '[[File:%s|%s]]'):format(
args.image or ('Icon-%s.png'):format(args.name),
args.name or '',
v == true and invokePage or v
)
end
local function smallicon(v)
--Makes 32x32px item image. If passed a string, links to it. If passed true, links to the #invoke page (not name param)
return (v and '[[File:%s|%s|link=%s|32x32px]]' or '[[File:%s|%s|32x32px]]'):format(
args.image or ('Icon-%s.png'):format(args.name),
args.name or '',
v == true and invokePage or v
)
end
local function recipe()
return args.rec_mat and link2tooltip(frame:preprocess(split_link(args.rec_mat, nil, '<br>', function(v)
local item, quantity, found_img = v:match'(.-) ?%(?(%d+)%)?$'
found_img = mw.text.decode(frame:preprocess('{{msgnw::'.. (item or v) ..'}}')):match'|%s*image%s*=%s*([^<]-%.png)'
return ('{{Item|%s|%s%s}}'):format(item or v, quantity or 1, found_img and '|image=' .. found_img or '')
end)), true)
end
local function widget_sort_stats(close)
--provide html element attributes for Widget:Sort_Stats
local sortdata = {}
for k, v in pairs(stats) do if v[1] or v[2] then
table.insert(sortdata, 'data-'..k..'="'..args[k]..'"')
end end
if args.evade then table.insert(sortdata, 'data-evade="'..args.evade..'"') end
return ' style="text-align:left" class=stats_cell ' .. table.concat(sortdata, ' ') .. (close or ' | ')
end
local function stats_cell(mode_tooltip)
--generates stats cell used on category/shop pages for equipment; if mode_tooltip, hide_disambiguation and return stats table without concat
local only, lines =
args.warning and args.warning:match"Useable by '?'?'?(%a+)'?'?'? only",
{stats_sorted[1] and table.concat(stats_sorted, ', '), _=result._}
lines
:_(args.element and 'Element: ' .. args.element)
:_(args.resist and 'Resistance: ' .. split_link(args.resist, false, nil, ailment_link))
:_(args.effect and 'Effect: ' .. link2tooltip(split_link(args.effect, mode_tooltip, nil, ailment_link), mode_tooltip))
:_(args.ability and 'Ability: ' .. link2tooltip(split_link(args.ability, mode_tooltip), mode_tooltip))--use tooltip_link after module used on all ability pages
:_(args.warning and (only and
("'''%ss only'''"):format(mw.getContentLanguage():ucfirst(only))
or ("'''%s'''"):format(args.warning):gsub(", ?", "<br>")
))
:_(args.used_by and 'Exclusive: ' .. split_link(args.used_by))
return mode_tooltip and lines or lines[1] and table.concat(lines, '<br>')
end
local function randomized_table(v)
--takes a string with multiple lines (separated by <br> or \n) and appends effects to each line from each double bullet in args.ability.
local s = v:gsub('<br ?/?>', '\n')
--if not s:find'\n(%([^\n]+)' then return v end
return args.ability and s:find'\n%(' and
'<table style="margin:0"><tr><td colspan=3>'
.. s
:gsub('\n\n+', '\n')
:gsub("\n%f[%w '{<]", '</td></tr></table>', 1)
:gsub("'''", '')
:gsub('%%', '%%%%')
:gsub(
"\n(%([^\n]+)",
'</td></tr><tr style="vertical-align:top"><td style="white-space:nowrap;padding-left:3em;text-indent:-3em">%1</td><td> - </td><td>%%s'
)
:gsub('(%) +%w+[- ] *%w+[- ] *)(%(?[%w]+)', '%1<wbr>%2')
:format(select(2, unpack(mw.text.split(materia_ailment_link(args.ability):gsub('\n', ''), "%*.-%*%*"))))
.. (not v:find'</table>' and '</td></tr></table>' or '')
or v
end
local function effect_auto_link(v)
--autolink killers, equipment masteries and wields, and status ailments in materia effects
if v:find' killer ' or v:find' against ' then
for cat, initial in pairs(p.killer) do
local match = v:match(" '*(" .. cat:sub(1, -1):lower() .. "%l?)")
or v:match(" '*(" .. initial .. "%l*)")
v = match and v:gsub(match, ('[[:Category:%s|%s]]'):format(cat, match), 1) or v
end
elseif v:find'Increase .- equipped with' or v:find'Enable dual wielding' then
for cat in pairs(p.equipment) do
local match = v:match("'*([%a,']+ +'*" .. cat:lower() .. (cat:sub(-1)=='y' and '?i?e?s?)' or 's?)'))
or cat == 'Staff' and
v:match("'*([%a,']+ +'*staves)")
v = match and match:sub(1, 5) ~= 'great' and v:gsub(
match:gsub("^.- '*", '', 1),
('[[:Category:%s|%s]]'):format(
(p.equipment._plural[cat]
or cat:gsub('y$', 'ie') .. 's'
),
match:gsub("^.- '*", '', 1)
),
1
) or v
end
else v = materia_ailment_link(v) end
return v
end
local function passive_stat_boost(effects)
local list, group, last_percent = {[true] = {}, [false] = {}}, {[true] = {}, [false] = {}}, {[true] = {}, [false] = {}}
for i = 1, #p.stat_order do
if args[p.stat_order[i]] then
local positive = tonumber(args[p.stat_order[i]]:match"^'*(%-?%d*)%%'*$") > 0
if group[positive][1] then
if last_percent[positive] ~= args[p.stat_order[i]] then
table.insert(list[positive], ('%s (%s)'):format(table.concat(group[positive], '/'), last_percent[positive]))
group[positive], last_percent[positive] = {}, args[p.stat_order[i]]
end
else last_percent[positive] = args[p.stat_order[i]] end
table.insert(group[positive], p.stat_order[i])
effects[args[p.stat_order[i]]] = (effects[args[p.stat_order[i]]] or 0) + 1
end
end
for _, positive in ipairs{false, true} do
if group[positive][1] then
table.insert(effects, 1, (('%screase %s%s%s (%s)')
:format(
positive and 'In' or 'De',
table.concat(list[positive], ', '),
list[positive][1] and ' and ' or '',
table.concat(group[positive], '/'),
last_percent[positive]
)
:gsub('%(%-', '(')
))
end
end
return effects
end
local function materia_effects(mode_tooltip, no_chain)
--generates ability materia effects. If passed true as, returns effects as a table without concat.
local effects, transcluded, show_table =
args.effect and mw.text.split(args.effect, '%s*\n%s*') or {},
invokePage ~= currentTitle,
args.ability and (args.type ~= 'Passive' or args.mode == 'category')
for k, v in ipairs(effects) do
local enable, skills = v:match(p.patterns.enable)
if enable then
effects[k] = args.effect:match(p.patterns.wikilink) and
effects[k]:gsub('(\\?)\\,', '%1,')
or enable .. split_link(skills)
while v:find((effects[k + 1] or ''):match'%[(.+)%]%S*%s*=' or '^%$$') do table.remove(effects, k + 1) end
elseif transcluded and args.ability and (v:find':[\n<][b%(][r%d]' or v:find'[Cc]ounter') then
if v:gsub('<br ?/?>', '\n'):find'^[^\n]+:\n%(' then
effects[k] = show_table and randomized_table(v) or v
elseif args.type == 'Passive' then
for name, effect in args.ability:gmatch'%* *([^\n]-) *\n%*%*%s*([^\n]+)' do
effects[k] = v:gsub(
name:gsub('%p', '%%%1'),
'{{tooltip|2=%1|1=%1<br>' .. effect:gsub('%%', '%%%1'):gsub('Randomly use:<br ?/?>', '') .. ' |style=white-space:nowrap}}'
)
end
end
else effects[k] = effect_auto_link(v) end
end
if not no_chain then
if args.chain then table.insert(effects, chain_link(args.chain, true)) end
end
--Note: Below inserted in backwards order to the front of the effects table
if args.evade_m then table.insert(effects, 1, p.template.evade:format('magic', args.evade_m)) end
if args.evade_p then table.insert(effects, 1, p.template.evade:format('physical', args.evade_p)) end
passive_stat_boost(effects)
if args.used_by and not args.learn and args.mode and args.mode ~= 'exclusiveFX' then
table.insert(effects, 'Exclusive: ' .. split_link(args.used_by))
end
return mode_tooltip and effects or effects[1] and table.concat(effects, '<br>'):gsub('(</table>)<br>', '%1')
end
local function type_link(parens)
--makes [[:Category:Weapons]] ([[:Category:Guns]]). If parens is true, places them in parenthesis
return p.ability[args.type] and '[['
.. p.ability._class[p.ability[args.type]]:sub(1, -2)
.. (p.ability[args.type] == 1 and 'ies (%s)]]' or 'ies]]')
:format(args.type)
or p.equipment[args.type] and (parens and ' ([[:Category:%s|%s]])' or '[[:Category:%s|%s]]'):format(
p.equipment._plural[args.type] or args.type:gsub('y$', 'ie') .. 's',
args.type
)
or args.usage and '[[:Category:Materials]]' or '[[Miscellaneous Items]]'
end
local function multi_break(s)
--takes args.hits or arg.MP_cost and splits them by backslash or semicolon, inserting same number of breaks per item as in args.ability
if s and not tonumber(s) and s:find(p.patterns.multi_break) then
local hits = ('/ ' .. s .. ' /'):gmatch(p.patterns.multi_break)
s = {}
for v in mw.text.gsplit(
args.ability
or args.effect:gsub('\nIf used after[^\n]+:', '<br>'):gsub(':\n', '<br>'),
args.ability and '\n%*%*' or '\n'
) do
table.insert(s, ('<br>'):rep(select(2, v:gsub('<br ?/?>', '')) + 1))
table.insert(s, (hits()))
end
if not args.ability then table.remove(s, 1) end
s = table.concat(s)
end
return '\n| ' .. (s or '-')
end
local frame_tooltip = '[[#.|{{Tooltip|style=text-align:left' .. frame:callParserFunction('#tag:nowiki', ';') .. 'white-space:nowrap|hideicon=|'
local function attack_frames(hits, v)
--[[
pass args.hits as first param. Reads args.atk_frm and makes tooltip.
Also recursively splits and tooltips args.atk_frm by / or ; characters if such are present in args.hits
]]
hits = hits ~= '' and hits ~= '-' and hits
if hits and args.atk_frm then
if not v and hits:find(p.patterns.multi_break) then
local split = {
hits = ('/ ' .. hits .. ' /'):gmatch(p.patterns.multi_break),
a_frames = ('/ ' .. args.atk_frm .. ' /'):gmatch(p.patterns.multi_break)
}
for hit_count in split.hits do
local animation = split.a_frames()
table.insert(split, animation and tonumber(hit_count) and attack_frames(hit_count, animation) or hit_count)
end
hits = table.concat(split, ' / ')
else
local output, frames = {_=result._}, mw.text.split(v or args.atk_frm, ' ?[,%-] ?')
output
:_(frame_tooltip)
:_(#frames > 1 and 'Frame delay: ' or 'Attack frame: ')
:_(frames[1])
if #frames > 1 then
for i = 2, #frames do output:_(-tonumber(frames[i]) + tonumber(frames[i - 1])) end
output
:_'<br>Attack frames: '
:_(table.concat(frames, '-'))
else output:_(table.concat(frames, nil, 2, #frames)) end
hits = table.concat(output:_'|':_(mw.text.trim(hits)):_'}}]]')
end
end
return hits
end
local froms, hasExclusiveFX, learned = {
--[[
{parameter name, how-to-obtain title, flag}
Set flag for sources that would not place an ability in Category:Items and to exclude source from how-to-obtain cell for mode=category
1 = list parameter for equipable sources
2 = non-equipment sources or non-list parameter
]]
{'drop', 'Dropped from'},
{'steal', 'Stolen from'},
{'explore', 'Collected from'},
{'shop', args.quartz and 'Star Quartz' or 'Shop'},
{'recipe', 'Recipe'},
{'chest', 'Chest'},
{'reward', 'Reward'},
{'equip', 'Equipment', 1},
{'materia', 'Ability Materia', 1},
{'learn', 'Learned by', 2},
{'esper', 'Esper', 2},--because not a comma-separates list
{'enable', 'Enabled by', 2}
},
args.effect and--do not check used_by here
args.effect:match(p.patterns.only)
or args.ability and args.ability:match(p.patterns.only)--use match() not find()
currentTitle, namespace, invokePage =
mw.title.getCurrentTitle().fullText,
mw.title.getCurrentTitle().namespace,
frame:getParent():getTitle()
args.name = args.name or not invokePage:find':' and invokePage
args.mode = args.mode
or p_args.mode
or currentTitle == 'Module:Data' and 'demo'
or currentTitle == 'Ability Awakening' and 'awaken'
or (namespace == 14
or p.ability[args.type] and (
currentTitle == 'Ability Materia'
or currentTitle == (p.ability[args.type] == 1 and
('Special Abilities (%s)'):format(args.type)
or 'Magic Abilities'
)
)
) and 'category'
or invokePage ~= currentTitle and (
(args.recipe or args.reward) and (args.recipe or args.reward):find(
p.patterns.event
.. currentTitle:gsub('_', ' '):gsub('%p', '%%%1')
) and 'event'
or (hasExclusiveFX == currentTitle or args.used_by and args.used_by:find(currentTitle)) and 'exclusiveFX'
or p.equipment[args.type] and 'item'
or 'typeless'
)
local function format_skill_args()
--simplifies pattern matching by allowing newlines and <br> to be used interchangeably
args.effect = args.effect and args.effect
:gsub('(([^\n]+)\n%()', function(match, prev_line)
if prev_line:find'=' then return match end
return prev_line .. '<br>('
end)
:gsub('\n+(If used after)', '\n<br>%1')
if args.ability and not args.ability:find('\n*', 1, 1) then
--automatically takes names from effect param for randomized abilities and transcludes effect if line == '[data]'
local a = mw.text.split(args.ability, '\n')
if a[2] then
args.ability = {}
for name in args.effect:gmatch'<br ?/?>%([^\n<]+%) ([^\n<]+)' do
local abil = table.remove(a, 1)
if abil == '[data]' then
abil = frame:expandTemplate{title = ':' .. name:match'%[%[(.-)[|%]]', args = {'STATS', mode = 'fetch'}}
end
table.insert(args.ability, ('*%s\n**%s'):format(name, abil or 'NO DATA'))
end
args.ability = table.concat(args.ability, '\n')
end
end
end
local function format_split_args(v) return v and v:gsub(' ?; ?', ' / '):gsub(' +', ' '):gsub('^ ?/', '- /'):gsub('/ /', '/ - /') end
if p.ability[args.type] then
learned = not p_args.mode and args.learn and invokePage ~= currentTitle and {args.learn:match('\n|? *%[%[' .. currentTitle .. '.-|?[$|]?%s*(<[^\n]+>)%s*|?[$|] ?(%d%d?%d?)')}
args.hits, args.atk_frm, args.MP_cost =
args.hits and (
args.hits:find'^[dD][^/;]*$' and
((args.mode or learned and learned[1]) and 'D' or 'Default unit attack')
or format_split_args(args.hits)
),
args.atk_frm and format_split_args(args.atk_frm),
args.MP_cost and
format_split_args(args.MP_cost)
or args.type == 'Active' and 0
format_skill_args()
end
if learned and learned[1] then
--Display when transcluded onto a page listed in args.learn
local unmerge, hits = args.type ~= 'Passive' or p_args[1] == 'unmerge'
result
:_'|-\n|'
:_(learned[1])
:_'\n|'
:_(learned[2])
:_'\n|'
:_(icon(true))
:_'\n|align=left|'
:_(link(args.name, true))
:_'\n|align=left'
:_(unmerge and '|' or ' colspan=3|')
if args.filter then
result
:_'{{#Widget:Filter|skills='
:_(args.filter)
:_'}}'
end
result
:_(materia_effects():gsub("(%) with [^\n:]+): ?<br ?/?> ?%([^\n]+", '%1'))--save random counter info for mode=conditional
if unmerge then
result
:_(multi_break(attack_frames(args.hits)))
:_(multi_break(args.MP_cost))
end
elseif args.mode and args.mode ~= 'demo' then
local function BADGE()
return ('<p style="text-align:center">%s<br>%s<br>(%s)</p>'):format(
icon(true),
link(invokePage ~= args.name and invokePage .. '|' .. args.name or invokePage),
type_link()
)
end
local function STATS(b)
local v = (p.equipment[args.type] and stats_cell or materia_effects)()
return not (b or p_args.sep or args.mode == 'fetch' or p_args[1] == 'STATS') and v and widget_sort_stats() .. v or v
end
local function extend(sep)
--Reads customization parameters from parent frame. Def = default value, sep = separator
local magic_words = {
STATS = {STATS},
ICON = {icon, true},
TYPE = {type_link},
LINK = {link, table.concat({invokePage, args.name}, '|')},
RECIPE = {recipe},
BADGE = {BADGE}
}
for _, v in ipairs(p_args) do
_ = mw.text.trim(mw.text.killMarkers(v))
if _ ~= '' then
local a, b = v:gsub('\\@', esc_seq):match'^(.-)@(.*)'
result:_(sep or '\n| '):_(
a and (a~='' and
((args[a] or magic_words[a]) and
b:gsub(esc_seq, '@'):format(
frame.args[a] ~= '' and frame.args[a]
or args[a]
or magic_words[a][1](unpack(a == 'STATS' and {nil, b} or magic_words[a], 2))
)
or '-')
or b and b:gsub(esc_seq, '@'))
or frame.args[_] ~= '' and frame.args[_]--return unprocessed non-empty args
or args[_]--for auto args
or magic_words[v] and magic_words[v][1](unpack(magic_words[v], 2))
or p_args.default or '-'
)
end
end
end
if args.mode == 'category' then
--Display when on category page
local obtain, equipped = {}, {}
for i = 1, #froms do
if args[froms[i][1]] and froms[i][3] ~= 2 then
table.insert(froms[i][3] and equipped or obtain,
froms[i][3] and
split_link(args[froms[i][1]]:gsub('%]%] %([^%)]+%)', ']]'), nil, froms[i][3] and '<br>')
or ("'''%s:''' %s"):format(
froms[i][2],
split_link(args[froms[i][1]])
))
end
end
if args.esper then
for esper in args.esper:gmatch'%[%[[^:]-%]%]' do table.insert(equipped, esper) end
end
table.insert(obtain, args.trust and ("'''TMR:''' [[%s]]"):format(args.trust))
table.insert(obtain, args.STMR and ("'''STMR:''' [[%s]]"):format(args.STMR))
table.insert(obtain, args.obtain and multi_split(args.obtain, "'''%s''': ", ', ', '<br ?/?>'))
result
:_'|-\n|'
:_(tonumber(p_args.rowspan) and ('rowspan=%s style="text-align:center"| %s ||')
:format(p_args.rowspan, args.mag_lv or '')
)
:_(args.image and p.ability[args.type] and 'data-sort-value=' .. args.image:match'_(%d+)%.')
:_((' align=center|%s|| %s || '):format(
icon(true),
link(args.name, true)
))
:_((p.equipment[args.type] or args.type == 'Passive') and widget_sort_stats())
:_(p.equipment[args.type] and stats_cell()
or materia_effects())
:_' \n| '
:_(p.ability[args.type] and result
:_(args.MP_cost and ('style="text-align:center"| %s ||'):format(args.MP_cost) or '')
:_(equipped[1] and table.concat(equipped, '<br>') or '-')
:_' || '
and nil
)
:_(obtain[1] and table.concat(obtain, '<br>') or '-')
extend()
elseif args.mode == 'exclusiveFX' then
--Display when current page title matches name of the unit which benefits from an exclusive effect
result
:_(p_args[1] ~= 'rowonly' and ("{| class=wikitable style='text-align:center;width:100%'\n!" ..
(p.equipment[args.type] and "Icon!!Name!!Type!!Effect"
or "style='width:50px'|Icon!!style='width:130px'|Name!!Effect!!style='width:50px'|Hits{{tooltip|style=white-space:nowrap|D {{=}} Default unit attack}}!!style='width:50px'|MP")
))
:_"\n|-\n|"
:_(icon(true))
:_'\n| '
:_(link(args.name, true))
:_'\n|'
:_(p.equipment[args.type] and type_link() ..'\n|')
:_(widget_sort_stats())
:_(p.equipment[args.type] and
(stats_cell() or '')--in case stats_cell() returns nil
or table.concat{
materia_effects(),
multi_break(attack_frames(args.hits)),
multi_break(args.MP_cost)
}
)
if p_args[1] ~= 'rowonly' then result:_'\n|}' end
elseif args.mode == 'conditional' then
local function conditional_row(rowspan, activator)
result
:_'|-\n|colspan=3'
:_(rowspan and result:_' rowspan=' and rowspan)
:_'|Activated by<br>'
:_(activator ~= '' and activator
or args.enable and split_link(args.enable)
or link(args.name, true)
)
:_'||style="text-align:left"| '
end
local ability_count, isPassive, randomized_counter, unmerge =
args.ability and select(2, ('\n'..args.ability):gsub("%*'''", 0)),
args.type == 'Passive',
args.effect and args.effect:match"Chance to counter[^\n]+with '?'?'?(.-)'?'?'?:<br ?/?>%(%d+%%",
p_args[1] == 'unmerge'
if args.ability then
conditional_row()
if randomized_counter then
result
:_(randomized_counter)
:_'\n|style="text-align:left"| '
:_(randomized_table(materia_effects()):gsub("Chance to counter[^\n]-:", 'Randomly use:'))
:_(multi_break(attack_frames(args.hits)))
:_(multi_break(args.MP_cost))
else
if ability_count > 0 then table.insert(result, 2, ' rowspan=' .. ability_count) end
if args.ability and not args.hits and args.ability:find'>Hits:' then
args.hits, args.MP_cost = {}
for line in args.ability:gmatch'\n%*%*[^\n]+' do
local a, b, h = line:find'<br ?/?>Hits: *(.+)'
if a then
local offset = args.ability:find(line, 3, 1)
args.ability = args.ability:sub(1, offset + a - 2) .. args.ability:sub(offset + b)
table.insert(args.hits, h)
else table.insert(args.hits, '-') end
end
args.hits = table.concat(args.hits, ' / '):gsub('Default unit attack', 'D')
end
result
:_(args.ability and materia_ailment_link(args.ability)
:gsub("\n%* *'''(.-)'''", '|-\n|style="text-align:left"| %1')
:gsub("%* *'''(.-)'''", '%1')
:gsub('%*%*', '| style="text-align:left"'
.. (isPassive and not (args.hits or args.MP_cost or unmerge) and
' colspan=3| '
or '| '
))
)
if unmerge or args.hits or args.MP_cost then
result
:_(multi_break(attack_frames(args.hits)))
:_(multi_break(args.MP_cost))
end
end
elseif args.enable then
if p_args.rowspan == '0' then result:_'|-\n|style="text-align:left"| '
else conditional_row(tonumber(p_args.rowspan)) end
result
:_(link(args.name, true))
:_'\n|style="text-align:left"| '
if args.filter then
result
:_'{{#Widget:Filter|skills='
:_(args.filter)
:_'}}'
end
result
:_(materia_effects())
:_(multi_break(attack_frames(args.hits)))
:_(multi_break(args.MP_cost))
else for line in args.effect:gsub('<br ?/?>%s*%(', '\n('):gmatch'[^\n]*Enable[^\n]+' do if not line:find'%].*=' then
local skills, ability_count = (select(2, line:match(p.patterns.enable)) or line:match' of (.+)')
:gsub('([^\\]), *', '%1@$#')
result:_(result[1] and '\n')
conditional_row(
ability_count > 0 and ability_count + 1,
(line:gsub('\\:', esc_seq):match'^%(%d+%%%) *(.-):' or ''):gsub(esc_seq, ':')
)
for k, v in ipairs(mw.text.split(skills, '@$#')) do--no gsplit because k needed
if k > 1 then result:_'\n|-\n|style="text-align:left"| ' end
local title, page = (v:match'%[%[(.-)[|%]\]' or v):gsub('\\,', ',')
page = mw.title.new(title).exists and frame:expandTemplate{title = ':' .. title, args = {page = title}}
:gsub('Default unit attack', 'D')
local override, page_effect =
frame.args.effect:match('\n%s*effect%[' .. title:gsub('%p', '%%%1') .. '%]%s*=%s*([^\n]+)')
or frame.args.effect:match('\n%s*%[' .. title:gsub('%p', '%%%1') .. '%]effect%s*=%s*([^\n]+)'),
page and page:match("'''Effect:'''\n:([^*=]+)\n")
args.effect = (override or page_effect or 'ERROR - No page or override found for ' .. link(title)):gsub('\\n', '\n')
result
:_(page and link(v, true) or v)--when all abilities use Data, replace all with:
--:_('{{:'..v..'|mode=fetch|STATS|{{tooltip|{{{hits}}}|Attack frame(s): {{{atk_frm}}}}}|MP}}')
:_'\n|style="text-align:left"| '
:_(page and override and '<span class="ttip">')
:_(args.effect)
:_(override and page_effect and
"<span class=tip style='width:40em'><u>Automated Warning</u><br>A page exists for ''"
.. link(v)
.. "'' but an override has been set on ''"
.. link(invokePage)
.. "''. If the effect shown is the same as the following, please remove the override:<table class=wikitable style='margin:auto' ><tr><td>"
.. page_effect
.. "</td></tr></table></span></span>")
--args.atk_frm = args.effect:match('\n%s*atk_frm%[' .. title:gsub('%p', '%%%1') .. '%]%s*=%s*([^\n]+)') or args.atk_frm
for i, m in ipairs{{'Hits', 'hits'}, {'MP', 'MP_cost'}} do
result:_(multi_break(
frame.args.effect:match('\n%s*' .. m[2] .. '%[' .. title:gsub('%p', '%%%1') .. '%]%s*=%s*([^\n]+)')
or frame.args.effect:match('\n%s*%[' .. title:gsub('%p', '%%%1') .. '%]' .. m[2] .. '%s*=%s*([^\n]+)')
or page and page:match("'''" .. m[1] .. ":''' ([^\n]+)")
or '-'
))
end
end
end end end
elseif args.mode == 'awaken' then
local function bold(v)
return v and ((v:find"'''" or v:find'</?b>') and v or ("'''%s'''"):format(v)) or ''
end
local function unbold(v, manual_bold)--removes striked text and all tags except those that start with a t (table)
if manual_bold then return v end
return v and (v
:gsub("'''", '')
:gsub('<br><b><s%b></s></b><br>', '\n')
:gsub('<s%b></s>', '')
:gsub('%b<>', function(tag)
if tag == '<wbr>' or tag:find'^</?t' then return tag
elseif tag:sub(2, 3) == 'br' then return '\n' end
return ''
end)
:gsub('font-weight:bold;', '')
)
end
local function calculate_effects()
return unbold(materia_effects())
end
local unit, o_args, passive_stats, effects, new_effects =
p_args[1] ~= 'table' and p_args[1] ~= 'conditional' and p_args[1] or currentTitle == 'Ability Awakening' and 'Error - unspecified unit',
{},
{},
unbold(materia_effects()):gsub('\n', '<br>')
new_effects, passive_stats.lines = effects, passive_stat_boost{}
local function parse_awakening(input)
local to_replace, to_append, recalc, manual_bold = {}, {}
if input then
for _, v in next, {'effect', 'ability'} do
_ = '%s+' .. v .. '%s*=%s*([^=]+%f[\n])([^=]+=?)'
local m, m2, m3 = ('\n' .. input):match(_)
if not m then
_ = '%s+' .. v .. '%s*=%s*([^\n]*)'
m3 = ('\n' .. input):match(_)
end
if m or m3 then
input, args[v], o_args[v], recalc, manual_bold =
('\n' .. input):gsub(_, m2 and m2:find'=' and '%2' or ''),
(m3 or (m2:find'=' and m or m .. m2):gsub('\n%(', '<br>(')):gsub('\\n', '\n'),
args[v],
true,
manual_bold or (m or m3):find"'''" or (m or m3):find"<b>"
end
end
end
input = input and mw.text.split(input, '%s*\n%s*') or {'awk_mat=NO DATA,0'}
for i = 1, #input do
if i == 1 and args[input[i]] then parse_awakening(args[input[i]])
else
local diff = mw.text.split(input[i], '%s*=>%s*')
if diff[2] then
table.insert(to_replace, {diff[1]:gsub('\\n', '\n'), diff[2]:gsub('\\n', '\n')})
else
diff = mw.text.split(input[i], '%s*=%s*')
if diff[2] then
diff[2] = diff[2]:gsub('\\n', '\n')
if diff[2] == '' then diff[2] = nil end
if ({hits=1,atk_frm=1,MP_cost=1})[diff[1]] then diff[2] = format_split_args(diff[2]) end
if stats[diff[1]] then
if diff[2] == '0' or diff[2] == '0%' then diff[2] = nil end
if args[diff[1]] then passive_stats.lines[args[diff[1]]] = passive_stats.lines[args[diff[1]]] - 1 end
o_args[diff[1]], args[diff[1]], passive_stats.changed, passive_stats[diff[1]] = args[diff[1]], diff[2], true, true
elseif (diff[1] == 'chain') then
new_effects = mw.text.split(new_effects, new_effects:find'\n' and '\n' or '<br>')
table.insert(new_effects, chain_link(diff[2], true))
new_effects = table.concat(new_effects, '<br>')
elseif (diff[1] == 'evade_p' or diff[1] == 'evade_m') then
if not recalc and args[diff[1]] ~= diff[2] then
local physical, v, evade = diff[1] == 'evade_p' and 'physical', diff[2]--:gsub('%%', '%%%%')
evade = physical or 'magic'
if args[diff[1]] then
table.insert(to_replace, {
new_effects:match(p.template.evade:format(evade, '[^(]+'):gsub('[()]', '%%%1')),
p.template.evade:format(evade, (#(frame.args[diff[1]] or '') > 0 or not unit and args[diff[1]]) and bold(v) or v)
})
else
new_effects = mw.text.split(new_effects, new_effects:find'\n' and '\n' or '<br>')
table.insert(
new_effects,
1 + #passive_stats.lines + (not physical and args.evade_p and 1 or 0),
bold(p.template.evade:format(evade, v))
)
new_effects = table.concat(new_effects, '<br>')
end
end
args[diff[1]] = diff[2]--no recalc
elseif not args[diff[1]] or unbold(diff[2]) ~= unbold(args[diff[1]]) then
o_args[diff[1]], args[diff[1]] =
args[diff[1]] or '0',
({awk_mat=1,name=1,atk_frm=1})[diff[1]] and diff[2] or bold(diff[2])
end
elseif input[i] ~= '' then table.insert(to_append, input[i]) end
end
end
end
if recalc then
if args.ability then
format_skill_args()
new_effects = frame.args.ability and frame.args.ability ~= '' and bold(unbold(materia_effects(), manual_bold))
or unbold(materia_effects(), manual_bold)
:gsub('(<table style=")', '%1font-weight:bold;')
:gsub('(</table>)(.+)', "%1'''%2'''" )
:gsub('^(.+)(<table)', "'''%1'''%2")
else new_effects = bold(unbold(materia_effects(), manual_bold)) end
new_effects, passive_stats.changed = frame:preprocess(new_effects)
local a, b = new_effects:find(effects, 1, 1)
if not a then a, b = new_effects:find(frame.args.effect, 1, 1) end
if a and (not frame.args.ability or frame.args.ability == '') then
new_effects = new_effects:sub(1, a - 1)
.. '<span style="font-weight:normal">' .. effects .. '</span>'
.. new_effects:sub(b + 1)
else
--Unbold if override effect is found in original (assume strikethrough was undesired)
local plain = unbold(new_effects)
if effects:find(plain, 1, 1) or frame.args.effect:find(plain, 1, 1) then new_effects = plain end
end
elseif passive_stats.changed then
new_effects = mw.text.split(new_effects, new_effects:find'\n' and '\n' or '<br>')
local new_lines = passive_stat_boost{to_replace = unit and passive_stats.lines.to_replace or {}}
if #new_lines > #passive_stats.lines then
for n = 1, #new_lines do
local a = new_lines[n]:sub(1, 3)
if not table.concat(passive_stats.lines):find(a) then new_lines[n] = bold(new_lines[n]) end
end
elseif #new_lines < #passive_stats.lines then
for n = 1, #passive_stats.lines do
local a = passive_stats.lines[n]:match'(%u%l%l)rease '
if not table.concat(new_lines):find(a) then
table.insert(new_lines, select(a == 'Inc' and 1 or 2, 1, ("<b><s>%s</s></b>"):format(passive_stats.lines[n])))
end
end
end
for n = 1, #passive_stats.lines do table.remove(new_effects, 1) end
table.insert(new_effects, 1, table.concat(new_lines, '<br>'))
new_effects = table.concat(new_effects, '<br>')
for _, stat in ipairs(p.stat_order) do
if args[stat] then
if passive_stats.lines[args[stat]] == 0 or not passive_stats.lines[args[stat]] then
local percent = args[stat]:sub((args[stat]:find'%d'))
table.insert(new_lines.to_replace, {percent, percent})
end
passive_stats.lines[args[stat]] = (passive_stats.lines[args[stat]] or 0) + 1
end
if passive_stats[stat] and (
not o_args[stat]
or args[stat] and (
o_args[stat]:sub(1, 1) == '-' and args[stat]:sub(1, 1) ~= '-'
or o_args[stat]:sub(1, 1) ~= '-' and args[stat]:sub(1, 1) == '-'
)
) then table.insert(new_lines.to_replace, {stat, stat}) end
end
for n = 1, #new_lines.to_replace do table.insert(to_replace, n, new_lines.to_replace[n]) end
if unit then new_lines.to_replace = {}
else
for n = 1, #new_lines do new_lines[n] = unbold(new_lines[n]) end
passive_stats = {}
end
passive_stats.lines, passive_stats.changed = new_lines
end
for _, diff in ipairs(to_replace) do
local a, b = new_effects:find(diff[1], 1, 1)
if not a then
a, b = new_effects:find(diff[1]:gsub('<br>', '\n'), 1, 1)
if not a then
a, b = new_effects:find(diff[1]:gsub('\n', '<br>'), 1, 1)
if not a then
a, b = new_effects:find(diff[1]:gsub("'''", ''), 1, 1)
if not a then a, b = new_effects:find(unbold(diff[1]), 1, 1) end
end
end
end
if a then
if diff[1] == '' then new_effects = new_effects .. ' ' .. bold(diff[2])
else
if diff[2] == '' then diff[2] = ("<b><s>%s</s></b>"):format(diff[1]:gsub('\n', '<br>'))
else--no bold if inside bold line
local line = new_effects:gsub('<br>', '\n'):match('[^\n]*' .. diff[1]:gsub('%p', '%%%1') .. '[^\n]*')
if not line then line = new_effects:gsub('<br>', '\n'):match('[^\n]*' .. unbold(diff[1]):gsub('%p', '%%%1') .. '[^\n]*') end
if line:sub(1, 3) ~= "'''" or line:sub(-3) ~= "'''" or line:match"^'?'?'?(.-)'?'?'?$":find"'''" then diff[2] = bold(diff[2]) end
end
new_effects = new_effects:sub(1, a - 1)
.. diff[2]
.. (diff[2] == '' and (a == 1 or new_effects:find('\n' .. diff[1], 1, 1)) and
new_effects:sub(b + 1, b + 2):upper()
.. new_effects:sub(b + 3)
or new_effects:sub(b + 1)
)
end
elseif diff[1] == '^' then new_effects = bold(diff[2]) .. ' ' .. new_effects:sub(1, 1):lower() .. new_effects:sub(2)
else table.insert(to_append, "''Error - Unable to find: ''" .. bold(diff[1])) end
end
for k, v in ipairs(to_append) do to_append[k] = bold(effect_auto_link(v)) end
table.insert(to_append, 1, to_replace[1] and effect_auto_link(new_effects) or new_effects)
new_effects = table.concat(to_append, '<br>'):gsub('\n', '<br>'):gsub("'''/'''", '/')
return new_effects
end
local function missing_plus(unit, i) return 'awk_mat=NO DATA,0\nWarning: {{param|' .. unit .. '+' .. i .. '}} undefined' end
if unit then
for i = 1, tonumber(args.max_plus or p_args.max_plus) or 2 do
new_effects = parse_awakening(args[unit .. '+' .. i] or missing_plus(unit, i))
end
new_effects = new_effects:gsub("'+''(''%b'''')'''+"--[[looks wrong but isn't]], "%1"):gsub(("'"):rep(6),'')
local function arg_change(i)
return o_args[i] and ("<br>'''%s %sed to %s'''"):format(
({hits = 'Hit count', MP_cost = 'MP cost'})[i],
tonumber(unbold(args[i])) and
(tonumber(unbold(o_args[i])) > tonumber(unbold(args[i])) and ' reduc' or ' increas')
or 'chang',
unbold(args[i])
) or ''
end
result
:_(p_args[2] and (p_args[2] == 'table' and
'{|class=wikitable\n!Unit!!Abilities!!class=spacer|Base Effects!!class=spacer|Awakening'
or '|-class=subheader\n!colspan=4|'))
:_'\n|-\n|'
:_(p_args[2] and
('rowspan=%s style="text-align:center"|{{Sprite|%s}}<br>[[%s]]\n|')
:format(tonumber(p_args[2]) or tonumber(p_args[3]) or 3, unit, unit))
:_(link(args.name, true))
:_'<br>('
:_(args.awk_mat and args.awk_mat:match'^[^,]+' or '<b>awk_mat</b> undefined')
:_')\n| '
:_(args.ability and effects:sub(1, 7) ~= '<table ' and randomized_table(effects) or effects)
:_'\n| '
:_(args[unit .. '+1'] and new_effects or "''No data for unit named'' " .. bold(unit))
:_((arg_change'hits' .. arg_change'MP_cost'):sub(new_effects:sub(-8) == '</table>' and 5 or 1))
else
if p_args[1] == 'table' then
result:_'{|style="text-align:center;width:100%" class=wikitable\n|-\n!Name!!class=spacer|Effect!!style="width:50px"|{{tooltip|D {{=}} Default unit attack|Hits}}!!style="width:50px"|MP!!style="width:50px"|Type'
for i = 1, 5 do result:_'!!style="width:20px"|T':_(i) end
result:_'!!style="width:100px"|Gil'
elseif p_args[1] == 'conditional' then result:_'|-\n! colspan="11" | Conditional\n|-'
else result:_'|-class=subheader\n!colspan=11|' end
local last_atk_frm = args.atk_frm
for i = 1, tonumber(args.max_plus or p_args.max_plus) or 2 do
new_effects = unbold(new_effects)
parse_awakening(args[(p_args.skill or currentTitle) .. '+' .. i] or missing_plus(p_args.skill or currentTitle, i))
result
:_'\n|-\n|'
:_(link(args.name, true))
:_' +'
:_(i)
:_'\n|style="text-align:left"| '
:_(new_effects
:gsub("'''''%b'''''''", "'''%1'''")
:gsub(("'"):rep(6),'')
:gsub('\n', '<br>')
)
:_(atk_frm ~= args.atk_frm and
(function()
last_atk_frm = args.atk_frm
return multi_break(attack_frames(args.hits)):gsub('[FA]', function(m)return'New '..m:lower()end)
end)()
or multi_break(args.hits)
)
:_(multi_break(args.MP_cost))
if args.awk_mat then
local mats = mw.text.split(args.awk_mat, '%s*,%s*')
for c = 1, #mats - 1 do result:_'\n|':_(mats[c]) end
result
:_'\n|'
:_((' -\n|'):rep(7 - #mats))
:_(frame:expandTemplate{title='Gil', args = {mats[#mats]}})
else
result:_'\n|colspan=7|'
if p_args.skill then
if currentTitle ~= invokePage then result
:_'via '
:_(link(p_args.skill))
:_' +'
:_(i)
else result:_' -'end
else result:_'<b>awk_mat</b> undefined' end
end
args.MP_cost, args.hits = unbold(args.MP_cost), unbold(args.hits)
end
end
elseif args.mode == 'event' then
result
:_'|-\n|'
:_(BADGE())
:_'\n| '
:_(p.equipment[args.type] and stats_cell()
or materia_effects())
if args.recipe then result:_'\n| ':_(recipe()) end
extend()
elseif args.mode == 'custom' then
result:_'|-'
extend()
elseif args.mode == 'fetch' then
extend(p_args.sep)
if p_args.sep ~= '' then table.remove(result, 1) end--removes first sep
elseif args.mode == 'tooltip' then
local wikilink, tip, lines =
link(args.name, not p_args.full_pg),
mw.html.create'td',
(p.equipment[args.type] and stats_cell or materia_effects)(true)
lines[1] = stats_sorted[1] and p.equipment[args.type] and
'Stats: ' .. lines[1]
:gsub('%((%-%d+%%?)%)', '(<span style="color:#f00">%1</span>)')
:gsub('([^ ])(%+%d+%%?)', '%1<span style="color:#0f0">%2</span>')
or lines[1]
for i = 1, #lines do
if lines[i]:find'^<table' then
tip:node(lines[i]:gsub('(<table style=")', '%1font-size:8.5px;'))
lines.table = true
else tip
:tag'div'
:css{
--['padding-left']='2ex',
--['text-indent']='-2ex',
['font-size']=lines.table and '8.5px' or nil
}
:wikitext(lines[i])
end
end
--tip:css{background = '#014'}
return frame:preprocess(tostring(mw.html.create'span'
:addClass'ttip'
:tag'span'
:addClass'mobileonly'
:wikitext(wikilink)
:done()
:tag'span'
:addClass'nomobile'
:wikitext(wikilink)
:done()
:tag'span'
:addClass'tip module-tooltip'
:tag'table'
:tag'tr'
:tag'td'
:css{width='90px',['text-align']='center',['vertical-align']='top',padding='12px 6px 0'}
:attr{rowspan=2}
:wikitext(icon'')
:done()
:tag'td'
:css{font='15px Lato, sans-serif',['font-weight']='700',height='30px'}
:node(args.name:gsub(' %(%w+%)', ''))
:node((p.equipment[args.type] or p.ability[args.type] == 2) and mw.html.create'span'
:css{position='absolute',right='8px',top='5px'}
:wikitext(
frame:expandTemplate{
title = p.equipment[args.type] and 'Equip' or 'Affinity',
args = {args.type == 'Throwing Weapon' and
'Throwing'
or args.type
}
},
p.ability[args.type] and ' Lvl ' .. args.mag_lv .. ' '
)
)
:done()
:done()
:tag'tr'
:node(tip)
:allDone()
))
elseif args.mode == 'imagetooltip' then
local wikilink, tip, lines =
link(args.name, not p_args.full_pg),
mw.html.create'td',
(p.equipment[args.type] and stats_cell or materia_effects)(true)
lines[1] = stats_sorted[1] and p.equipment[args.type] and
'Stats: ' .. lines[1]
:gsub('%((%-%d+%%?)%)', '(<span style="color:#f00">%1</span>)')
:gsub('([^ ])(%+%d+%%?)', '%1<span style="color:#0f0">%2</span>')
or lines[1]
for i = 1, #lines do
if lines[i]:find'^<table' then
tip:node(lines[i]:gsub('(<table style=")', '%1font-size:8.5px;'))
lines.table = true
else tip
:tag'div'
:css{
--['padding-left']='2ex',
--['text-indent']='-2ex',
['font-size']=lines.table and '8.5px' or nil
}
:wikitext(lines[i])
end
end
--tip:css{background = '#014'}
return frame:preprocess(tostring(mw.html.create'span'
:addClass'ttip tooltip-hide-icon'
:tag'span'
:addClass'mobileonly'
:wikitext(smallicon(true))
:done()
:tag'span'
:addClass'nomobile'
:wikitext(smallicon(true))
:done()
:tag'span'
:addClass'tip module-tooltip'
:tag'table'
:tag'tr'
:tag'td'
:css{width='90px',['text-align']='center',['vertical-align']='top',padding='12px 6px 0'}
:attr{rowspan=2}
:wikitext(icon'')
:done()
:tag'td'
:css{font='15px Lato, sans-serif',['font-weight']='700',height='30px'}
:node(args.name:gsub(' %(%w+%)', ''))
:node((p.equipment[args.type] or p.ability[args.type] == 2) and mw.html.create'span'
:css{position='absolute',right='8px',top='5px'}
:wikitext(
frame:expandTemplate{
title = p.equipment[args.type] and 'Equip' or 'Affinity',
args = {args.type == 'Throwing Weapon' and
'Throwing'
or args.type
}
},
p.ability[args.type] and ' Lvl ' .. args.mag_lv .. ' '
)
)
:done()
:done()
:tag'tr'
:node(tip)
:allDone()
))
else
--Display when on a shop page (mode = recipe/item/item2/typeless)
result
:_(('|-\n| %s@\n| %s %s')--don't remove spaces
:gsub('@', args.mode == 'item2' and '{{item|%%s}}' or '%%s')
:format(
args.mode == 'recipe' and 'Recipe for '
or '',
args.mode == 'item2' and args.name or link(args.name, true),
(args.mode == 'typeless' or args.mode == 'recipe') and
(p.equipment[args.type] and '-\n| ' or 'colspan=2' .. (args.mode == 'recipe' and '| ' or ''))
or type_link() .. '\n|',
args.mode == 'recipe' and '-'
or widget_sort_stats() .. (
p.equipment[args.type] and stats_cell()
or materia_effects()
or (args.usage or args.awk_mat) and 'Material'
or '-'
)))
:_(p_args.limit ~= '0' and ('\n|{{%s|%s}}%s'):format(
args.quartz and 'Star Quartz' or 'Gil',
args.quartz
or ({item=1,item2=1})[args.mode] and args.buy_gil
or args.mode == 'recipe' and args.buy_rec
or '?',
p_args.limit and ('<br>(Limit: %s)'):format(p_args.limit) or ''
))
extend()
end
else
--info displayed on item (invoke) page
result
:_'__NOTOC__\n__NOEDITSECTION__'
:_((args.image or args.name) and ('<div class="frame-%s">\n%s\n</div>'):format(
p.equipment[args.type] and 'equip' or p.ability[args.type] and 'ability' or 'item',
icon()
))
:_(args.desc and '\n\n' .. args.desc)
if args.mode then table.remove(result, 1) end--mode = demo
if args.type then
if p.equipment[args.type] then
local materia = {args.effect}
table.insert(materia, args.ability)
for k, v in ipairs(materia) do materia[k] = split_link(v, true, nil, ailment_link) end
result
:_"\n== Statistics ==\n*'''Type:''' "
:_(args.type == 'Accessory' and '[[:Category:Accessories|Accessory]]'
or p.equipment._class[p.equipment[args.type]] .. type_link(true))
:_"\n*'''Stats:''' "
:_(stats_sorted[1] and table.concat(stats_sorted, ', ') or '-')
:_"\n*'''Element:''' "
:_(args.element or '-')
:_"\n*'''Resistance:''' "
:_(args.resist and split_link(args.resist, false, nil, ailment_link) or '-')
:_"\n*'''Additional effect:''' "
:_(#materia > 0 and
link2tooltip(args.ability and (--replace link2tooltip after all abilities use Data
args.effect and
"%s and enable use of %s"
or 'Enable use of %s'
):format(unpack(materia))
or materia[1], true) .. (args.warning and ', ' .. args.warning or '')
or args.warning
or '-'
)
elseif p.ability[args.type] then
flags.rng_enable = args.effect and args.effect:find'%(%d+%%%) [^\n]*Enable' and not args.ability
result
:_"\n== Statistics ==\n*'''Type:''' "
:_(p.ability._class[p.ability[args.type]])
:_' ('
:_(args.type)
:_(p.ability[args.type] == 2 and ' Magic Lv ' .. args.mag_lv)
:_")\n*'''Effect:'''\n:"
:_(materia_effects(false, true))
:_(args.chain and "\n*'''Chaining Family:''' " .. chain_link(args.chain))
:_(args.hits and "\n*'''Hits:''' " .. attack_frames(args.hits))
:_(args.MP_cost and "\n*'''MP:''' " .. args.MP_cost)
if args.ability or flags.rng_enable then
result
:_'\n==Abilities==\n'
:_(args.ability and materia_ailment_link(args.ability))
if flags.rng_enable then
local r, fake_parent = result, {
getTitle = function() return currentTitle end,
args = {mode = 'conditional'},
getParent = frame.getParent
}
function frame.getParent() return fake_parent end
result = {_ = result._}
frame.getParent, result = fake_parent.getParent, r
:_'{|class=wikitable style="text-align:center;width:100%"\n|-\n! colspan="3" | Condition !! width="130px" | Name !! class="spacer" | Effect !! width="50px" | Hits {{Tooltip|D {{=}} Default unit attack}} !! width="50px" | MP\n'
:_(p.item(frame))
:_'\n|}'
end
end
elseif args.type == 'Item' and args.effect then
result
:_'\n== Effect ==\n'
:_(materia_effects())
end
end
result
:_(args.notes and '\n==Notes==\n')
:_(args.notes)
:_'\n==Crafting recipe==\n'
:_(args.recipe and args.recipe ~= 'none' and
('{|class=wikitable style="text-align:center"\n!Materials!!Gil\n|-\n|align=left|%s\n||{{Gil|%s}}\n|}'):format(
recipe() or '{{param|rec_mat}} is undefined',
args.rec_gil or '?')
or 'None'
)
:_((args.usage or args.quest) and result
:_"\n==Usage=="
:_(args.awk_mat and "\n''Awakening Material''\n:*" .. split_link(args.quest, nil, '\n:*'))
:_(args.usage and "\n''Crafting Material''" .. multi_split(args.usage, "\n:''%s''\n::*", '\n::*', '\n:*'))
:_(args.quest and "\n''Involved in Quest''\n:*" .. split_link(args.quest, nil, '\n:*'))
and nil
)
:_"\n==How to obtain=="
local function simpleTable(v)
local rows = mw.text.split(v, '\n+')
for k, r in ipairs(rows) do
local cells = mw.text.split(r, "%$")
for i, c in ipairs(cells) do
if c:find'^ *%[%[.+%]%] *$' then cells[i] = 'style="text-align:left"| ' .. c end
end
rows[k] = table.concat(cells, ' || ')
end
result
:_'{|class="wikitable sortable" style="text-align:center"\n'
:_(table.concat(rows, '\n|-\n| '))
:_'\n|}'
end
for i = 1, #froms do
if args[froms[i][1]] then
flags.isItem = flags.isItem or not froms[i][3]
result
:_"\n''"
:_(froms[i][2])
:_"''\n:"
if args[froms[i][1]]:find'^{|' then
result:_(args[froms[i][1]])
elseif args[froms[i][1]]:find'^!' then
simpleTable(args[froms[i][1]])
else result
:_"*"
:_(split_link(args[froms[i][1]], nil, '\n:*', froms[i][1] == 'equip' and tooltip_link))
end
end
end
result
:_(args.trust and ("\n''Trust Master Reward''\n:*[[%s]]"):format(args.trust))
:_(args.STMR and ("\n''Super Trust Master Reward''\n:*[[%s]]"):format(args.STMR))
:_(args.obtain and multi_split(args.obtain, "\n''%s''\n:*", '\n:*', '\n*'))
:_(args.used_by and "\n==Equippable By==\n:*" .. split_link(args.used_by, nil, '\n:*'))
if args.learn then
local awk = {}
for name in args.learn:gmatch'\n|? *%[%[([^%]|]+)' do
if args[name .. '+1'] then table.insert(awk, {name}) end
end
if args.enable then for skill in args.enable:gsub('\\,', '@$'):gmatch'%f[%w][^,]+' do
if args[skill .. '+1'] then table.insert(awk, {skill:gsub('@$', ','), isSkill = true}) end
end end
if awk[1] then
table.sort(awk, function(a, b) return a[1] < b[1] end)
local fake_parent = {
getTitle = function() return currentTitle end,
args = {'table', mode = 'awaken'}
}
function frame.getParent() return fake_parent end
local r, wide_tab = result:_'\n==Ability Awakening==',
'width:200%%;margin-right:-99vh;%1"%2 mw-collapsible mw-collapsed" data-expandtext="Show table (hidden on testcase pages only due to width)"\n|+'
for k, name in ipairs(awk) do
result, fake_parent.args.page, fake_parent.args.skill =
setmetatable({}, {__index = r}),
select(name.isSkill and 1 or 2, invokePage, name[1])
awk, fake_parent.args[1] = k== 1 and
p.item(frame)
:gsub('!Name', '!style="width:5em"|Unit/Skill!%1', 1)
:gsub(currentTitle:find'testcases/' and 'width:100%%([^"]*" class=)(wikitable)' or '^$',
wide_tab,
1
)
or p.item(frame)
:gsub('(colspan=)(%d+)', function(a,b)return a..b+1 end, 1)--future maintenance proof
r:_'\n':_(awk:gsub(
'(%|%[%[.-%]%] %+)',
'|rowspan=' .. select(2, awk:gsub('[^|]%[%[([^%]|]+)%]%] ?%+1', '')) * 3 + 2 .. '|'
.. (name.isSkill and
'{{:' .. name[1] .. '|mode=fetch|ICON}}'
or '{{sprite|' .. name[1] .. '}}'
) .. '<br>'.. link(name[1]) ..'|%1',
1
))
for conditional in awk:gmatch'[^|]%[%[([^%]|]+)%]%] ?%+1' do
local m = ''
for n in awk:gmatch('%[%[' .. conditional .. '%]%] ?%+%s') do m = m < n and n or m end
r:_'\n':_(frame
:expandTemplate{title = ':' .. conditional, args = {
mode = 'awaken',
skill = args.name,
max_plus = m
}}
:gsub('undefined', '%1 at ' .. link(conditional))
)
end
end
result = r:_'\n|}'
end
end
local categories = {''}
if args.type then
if p.ability[args.type] then
table.insert(categories, 'Module:Data Ability')
if flags.isItem or args.trust or args.STMR or args.obtain then
table.insert(categories, 'Items')
table.insert(categories, 'Ability Materia')
elseif args.esper or args.equip then table.insert(categories, 'Ability Materia') end
if p.ability[args.type] == 1 then
table.insert(categories, ('%s (%s)'):format(
p.ability._class[p.ability[args.type]]:sub(1, -2) .. 'ies',
args.type
))
else
table.insert(categories, 'Magic')
table.insert(categories, args.type .. ' Magic')
table.insert(categories, args.type .. ' Magic Level ' .. args.mag_lv)
end
else
table.insert(categories, 'Items')
if p.equipment[args.type] then
table.insert(categories, 'Equipment')
if args.type == 'Accessory' then
table.insert(categories, 'Accessories')
else
table.insert(categories, p.equipment._class[p.equipment[args.type]] .. 's')
table.insert(categories, p.equipment._plural[args.type] or args.type .. 's')
end
else
if args.usage or args.awk_mat then table.insert(categories, 'Materials') end
end
end
end
for _, arg in ipairs{'recipe', 'reward', 'chest'} do
if args[arg] and args[arg]:find(p.patterns.event) then table.insert(categories, 'Event Items') break end
end
for _, k in ipairs{
--{arg key, category name}, if key is not nil, put in cat
{'recipe', 'Crafting Recipes'},
{'buy_gil', 'Purchasables'},
{'trust', 'Trust Master Rewards'},
{'STMR', 'Super Trust Master Rewards'},
{hasExclusiveFX and 'effect' or 'used_by', 'Unit Exclusive Items'},
{'awk_mat', 'Awakening Materials'},
{'usage', 'Crafting Materials'},
{'quest', 'Quest Items'},
{'equip', 'Equipment-given Abilities'},
{'esper', 'Esper-given Abilities'}
} do
if args[k[1]] then table.insert(categories, k[2]) end
end
result
:_((namespace ~= 0 and --escape catagories if not on main namespace
table.concat(categories, ']]\n[[:Category:'):gsub('%[C', '[:C')
or table.concat(categories, ']]\n[[Category:')
):sub(3, -1))
:_']]'
end
return frame:preprocess(table.concat(result))
end
function p.wrap(frame)
if frame.args.mode == 'shop' then
result
:_'{|class=wikitable'
for k, v in ipairs(frame.args) do
local name = k==1 and frame.args.name or frame.args['name'..k] or ''
result
:_'\n|-\n!colspan=4| '
:_(name)
:_'\n|-\n!Name!!'
:_((name == 'Item Shop' or name == 'Ability Shop') and
'colspan=2| '
or 'Type!!'
)
:_'Description!!Price'
:_(v)
end
result:_'\n|}'
end
return frame:preprocess(table.concat(result))
end
function p.find(frame)
local data, bad, title, result, this = {}, {}, mw.title.getCurrentTitle().fullText
local p_args = frame:getParent().args --warning suppress--
this = mw.text.decode(frame:preprocess('{{msgnw::' .. (frame.args[1] or mw.title.getCurrentTitle().fullText) .. '}}'))
if title:find'User:' or not title:find':' and not title:find'/' then
for m, p, l in this:gmatch'|%s*%[(%b[])%] *(.)(%d?)' do
m = m:sub(2, -2):match'^[^|]+'
if not (m:find':[^ _]' or m:find'#') and (p ~= '+' or l ~= '2') then
local page = mw.text.decode(frame:preprocess('{{msgnw::' .. m .. '}}')):gsub('<!%-%b--%->', '')
if page:lower():find'<onlyinclude>%s*{{#invoke:data|item' and (not title:find'Abilit' or page:find'Ability_%d+%.png') then
if this:sub(1, 99):find'Unit Infobox' then
table.insert(page:find(title) and data or bad, p == '+' and tonumber(l) and m .. '|mode=awaken' or m)
else
if title == 'Ability Awakening' then
for awk in page:gmatch'|%s*([^\n]-)%+1%s*=' do
if not this:find(m .. '|'.. awk, 1, 1) then
local rowspan = this:match(
'rowspan%s*=%s*["\']?(%d+)[^\n]+'
.. awk .. '[^\n]+\n|%s*%[%[' .. m
)
table.insert(data, m .. '|' .. awk
.. (rowspan and '|' .. rowspan or ''))
end
end
else
local rowspan
if title:find'Abilit' and page:find'mag_lv%s*=%s*%d' then
rowspan = this:match('rowspan=["\']?(%d+)[^\n]+\n|[^\n]+|' .. m)
end
table.insert(data, rowspan and
m .. '|rowspan=' .. rowspan
or m
)
end
end
end
end
end
end
if(p_args["max-rarity"]) then
local notNVRarity = not p_args["max-rarity"]:find "NV"
end
if not p_args.suppressmdwarnings then --warning suppress--
if data[1] then
result = '{{Unfinished Module Data|text=Please transclude these skills to this page: '
.. '\n<pre style="margin:0 !important;padding:0 !important;box-shadow:none;background:transparent !important">{{:'
.. table.concat(data, '}}\n{{:')
.. '}}</pre>}}'
end
if bad[1] then
result = (result or '')
.. '{{Unfinished Module Data|text=Please add this unit to these pages: '
.. '[['
.. table.concat(bad, ']], [[')
.. ']]}}'
end
end --warning suppress--
local count = #data
if bad[1] then count = '*'
elseif #data > 9 then count = mw.ustring.char(('A'):byte() + #data - 10) end
return result and frame:preprocess(result) .. (not this:find'{{Unreleased}}' and '[[Category:Pages needing a Module:Data transclusion|' .. count.. ']]' or '')
--following script can be used on pages like Special Abilities Passive in edit mode
--javascript:for(i=0,m=document.querySelector('div>pre').innerHTML.match(/[^{}:][^{}\n]+?(?=\}\})/g);m[i];i++)wpTextbox1.value=wpTextbox1.value.replace(new RegExp('\\n\\|\\-.*?\\n?.*?\n?.*?\\[\\[('+m[i].replace(/([^\w\s])/g, "\\$1")+')(\]\]|\\|)[\\s\\S]*?(?=\\n(\\|(\\-|\\})|\\{\\{:))'), "\n{{:$1}}");
end
return p