編集の要約なし |
編集の要約なし |
||
1行目: | 1行目: | ||
+ | --- '''DropTables''' stores drop table data from the official WARFRAME drop table repository.<br /> |
||
+ | -- |
||
+ | -- On this Wiki, DropTables is used in: |
||
+ | -- * [[Template:RelicTable]] |
||
+ | -- |
||
+ | -- @module droptables |
||
+ | -- @alias p |
||
+ | -- @author [[User:Falterfire|Falterfire]] |
||
+ | -- @attribution [[User:Croquemorttime|Croquemorttime]] |
||
+ | -- @attribution [[User:Flaicher|Flaicher]] |
||
+ | -- @attribution [[User:FINNER|FINNER]] |
||
+ | -- @image |
||
+ | -- @require [[Module:DropTables/data]] |
||
+ | -- @require [[Module:Missions/data]] |
||
+ | -- @require [[Module:String]] |
||
+ | -- @require [[Module:Icon]] |
||
+ | -- @require [[Module:Shared]] |
||
+ | -- @require [[Module:Void]] |
||
+ | -- @release stable |
||
+ | -- <nowiki> |
||
+ | |||
--Rewritten version of Module:DropTables to work with new format of data. |
--Rewritten version of Module:DropTables to work with new format of data. |
||
18行目: | 39行目: | ||
local modCountCol = 3 -- If empty, default to 1. Normally only different for Endo |
local modCountCol = 3 -- If empty, default to 1. Normally only different for Endo |
||
-- in DropData["Enemies"].Avionics |
-- in DropData["Enemies"].Avionics |
||
+ | -- TODO: Remove this as avionics are now considered mods |
||
local aviNameCol = 1 -- Avionic name |
local aviNameCol = 1 -- Avionic name |
||
local aviChanceCol = 2 -- Avionic drop chance |
local aviChanceCol = 2 -- Avionic drop chance |
||
26行目: | 48行目: | ||
local synCostCol = 3 -- The reputation cost for the offering |
local synCostCol = 3 -- The reputation cost for the offering |
||
local synRankCol = 4 -- The required Syndicate Rank to purchase the offering |
local synRankCol = 4 -- The required Syndicate Rank to purchase the offering |
||
− | |||
local p = {} |
local p = {} |
||
33行目: | 54行目: | ||
local MissionData = mw.loadData( 'Module:Missions/data' ) |
local MissionData = mw.loadData( 'Module:Missions/data' ) |
||
local Icon = require( "Module:Icon" ) |
local Icon = require( "Module:Icon" ) |
||
+ | local String = require( "Module:String" ) |
||
local Shared = require( "Module:Shared" ) |
local Shared = require( "Module:Shared" ) |
||
local Void = require( "Module:Void" ) |
local Void = require( "Module:Void" ) |
||
local relicTooltipStart = "<span style=\"border-bottom: 1px dotted;\" class=\"relic-tooltip\" data-param=\"" |
local relicTooltipStart = "<span style=\"border-bottom: 1px dotted;\" class=\"relic-tooltip\" data-param=\"" |
||
− | local relicTooltipStartNoDot = |
+ | local relicTooltipStartNoDot = '<span class="tooltip" data-param2="Void" data-param="' |
local relicTooltipCenter = "\">" |
local relicTooltipCenter = "\">" |
||
local relicTooltipEnd = "</span>" |
local relicTooltipEnd = "</span>" |
||
+ | --- |
||
+ | -- @function p.getMValue |
||
function p.getMValue(theMission, ValName, noBreaks) |
function p.getMValue(theMission, ValName, noBreaks) |
||
if(type(theMission) == "string") then theMission = p.getMission(theMission) end |
if(type(theMission) == "string") then theMission = p.getMission(theMission) end |
||
75行目: | 99行目: | ||
end |
end |
||
+ | --- Goes by Type & Tier, Type & Name, or Alias |
||
− | --タイプとTier、タイプと名前、またはエイリアスで移動します。 |
||
− | --So ("Survival", "Easy"), ("Survival", "Tier 1"), or ("Survival1") |
+ | -- So ("Survival", "Easy"), ("Survival", "Tier 1"), or ("Survival1") all get the same thing |
+ | -- @function p.getMission |
||
function p.getMission(MissionType, MissionTier, MissionName) |
function p.getMission(MissionType, MissionTier, MissionName) |
||
for i, Miss in pairs(DropData["Missions"]) do |
for i, Miss in pairs(DropData["Missions"]) do |
||
− | --MissionTier |
+ | --If MissionTier is nil, the MissionType variable is the Alias so check against that instead |
if(MissionTier == nil) then |
if(MissionTier == nil) then |
||
if(MissionType == Miss.Alias or MissionType == Miss.Tier) and (Miss.Type == MissionName) then |
if(MissionType == Miss.Alias or MissionType == Miss.Tier) and (Miss.Type == MissionName) then |
||
97行目: | 122行目: | ||
end |
end |
||
+ | --- Basically pretending to be semi-object oriented |
||
− | --基本的には半オブジェクト指向のふりをしている |
||
+ | -- Calling this whenever I'm pulling drops from enemies and passing them around |
||
− | --敵からドロップを引いて渡している時にこれを呼び出す |
||
+ | -- NOTE: As of writing, this assumes enemies don't have Blueprint or other drops listed. |
||
− | --NOTE:書いている時点では、敵にブループリントなどのドロップが記載されていないことが前提となっている。 |
||
+ | -- TODO: buildEnemyDrop(), buildMissionDrop(), buildSyndicateDrop(), buildResourceDrop(), |
||
+ | -- and etc. can probably be in a single buildDrop function that passes in a table/function |
||
+ | -- argument telling how to format drops |
||
+ | -- @function buildEnemyDrop |
||
local function buildEnemyDrop(Enemy, Mod) |
local function buildEnemyDrop(Enemy, Mod) |
||
local drop = {EName = Enemy.Name, IName = Mod[modNameCol]} |
local drop = {EName = Enemy.Name, IName = Mod[modNameCol]} |
||
108行目: | 137行目: | ||
end |
end |
||
− | --Like above, but for mission drops |
+ | --- Like above, but for mission drops |
− | --Calling this whenever I'm pulling drops from missions and passing them around |
+ | -- Calling this whenever I'm pulling drops from missions and passing them around |
+ | -- @function buildMissionDrop |
||
local function buildMissionDrop(theMission, Rotation, Item) |
local function buildMissionDrop(theMission, Rotation, Item) |
||
local drop = {MType = theMission.Type, MTier = theMission.Tier} |
local drop = {MType = theMission.Type, MTier = theMission.Tier} |
||
122行目: | 152行目: | ||
end |
end |
||
− | --Like above, but for Syndicate Offerings |
+ | --- Like above, but for Syndicate Offerings |
+ | -- @function buildSyndicateDrop |
||
local function buildSyndicateDrop(theSyndicate, Item) |
local function buildSyndicateDrop(theSyndicate, Item) |
||
local drop = {SName = theSyndicate.Name, IName = Item[synNameCol]} |
local drop = {SName = theSyndicate.Name, IName = Item[synNameCol]} |
||
132行目: | 163行目: | ||
--Like above, but for Avionics |
--Like above, but for Avionics |
||
+ | -- TODO: Remove unused function as avionics are now considered as mods |
||
local function buildAvionicDrop(Enemy, Avionic) |
local function buildAvionicDrop(Enemy, Avionic) |
||
local drop = {EName = Enemy.Name, IName = Avionic[aviNameCol]} |
local drop = {EName = Enemy.Name, IName = Avionic[aviNameCol]} |
||
143行目: | 175行目: | ||
end |
end |
||
− | --Like above, but for resource drops |
+ | --- Like above, but for resource drops |
+ | -- @function buildResourceDrop |
||
local function buildResourceDrop(Enemy, Resource) |
local function buildResourceDrop(Enemy, Resource) |
||
local drop = {EName = Enemy.Name, IName = Resource[resourceNameCol]} |
local drop = {EName = Enemy.Name, IName = Resource[resourceNameCol]} |
||
170行目: | 203行目: | ||
--Links a Syndicate and returns it. |
--Links a Syndicate and returns it. |
||
--Doesn't actually do anything but add brackets right now |
--Doesn't actually do anything but add brackets right now |
||
+ | -- TODO: Remove this simple function since it is uneeded; can just concat the brackets when needed |
||
local function linkSyndicate(SName) |
local function linkSyndicate(SName) |
||
return '[['..SName..']]' |
return '[['..SName..']]' |
||
end |
end |
||
− | --Returns the real drop chance of a specific enemy drop |
+ | --- Returns the "real" drop chance of a specific enemy drop |
− | --This involves combining chance to drop mod/blueprint with chance of that specific item dropping |
+ | -- This involves combining chance to drop mod/blueprint with chance of that specific item dropping |
− | --So 3% Mod Chance + 37.94% Pressure Point chance = 1.1382% real chance |
+ | -- So 3% Mod Chance + 37.94% Pressure Point chance = 1.1382% real chance |
+ | -- @function getRealDropChance |
||
local function getRealDropChance(EnemyDrop) |
local function getRealDropChance(EnemyDrop) |
||
local odds1 = EnemyDrop[eChance1Col] |
local odds1 = EnemyDrop[eChance1Col] |
||
184行目: | 219行目: | ||
end |
end |
||
+ | --- |
||
+ | -- @function getAllModDrops |
||
local function getAllModDrops(enemyName) |
local function getAllModDrops(enemyName) |
||
local drops = {} |
local drops = {} |
||
203行目: | 240行目: | ||
end |
end |
||
− | --Custom table sort for reward tables |
+ | --- Custom table sort for reward tables |
− | --WIP, initial rules: |
+ | -- WIP, initial rules: |
− | --Sort first by type, then alphabetically within type, then by quantity |
+ | -- Sort first by type, then alphabetically within type, then by quantity |
− | --WIP try sorting first by drop chance... |
+ | -- WIP try sorting first by drop chance... |
+ | -- TODO: Finish this function |
||
+ | -- @function rewardTableSort |
||
local function rewardTableSort(theTable) |
local function rewardTableSort(theTable) |
||
local function sorter(r1, r2) |
local function sorter(r1, r2) |
||
− | + | if(r1.Chance == r2.Chance) then |
|
− | + | if(r1.Type == r2.Type) then |
|
− | + | if(r1.IName == r2.IName) then |
|
− | + | return r1.Count < r2.Count |
|
− | + | else |
|
− | + | return r1.IName < r2.IName |
|
− | end |
||
− | else |
||
− | return r1.Type < r2.Type |
||
− | end |
||
− | else |
||
− | return r1.Chance > r2.Chance |
||
− | end |
||
end |
end |
||
− | + | else |
|
+ | return r1.Type < r2.Type |
||
+ | end |
||
+ | else |
||
+ | return r1.Chance > r2.Chance |
||
+ | end |
||
+ | end |
||
+ | |||
table.sort(theTable, sorter) |
table.sort(theTable, sorter) |
||
end |
end |
||
− | --Custom table sort for Enemy tables |
+ | --- Custom table sort for Enemy tables |
− | --Rules: |
+ | -- Rules: |
− | --Sort first by Drop Chance, then alphabetically within Drop Chance with Endo being last |
+ | -- Sort first by Drop Chance, then alphabetically within Drop Chance with Endo being last |
+ | -- @function enemyTableSort |
||
local function enemyTableSort(theTable) |
local function enemyTableSort(theTable) |
||
local function sorter(r1, r2) |
local function sorter(r1, r2) |
||
− | + | if(r1.Chance == r2.Chance) then |
|
− | + | if(r1.Count == r2.Count) then |
|
− | + | return r1.IName < r2.IName |
|
− | + | else |
|
− | + | return r1.Count < r2.Count |
|
− | + | end |
|
− | + | else |
|
− | + | return r1.Chance > r2.Chance |
|
− | + | end |
|
− | + | end |
|
+ | |||
− | |||
table.sort(theTable, sorter) |
table.sort(theTable, sorter) |
||
end |
end |
||
+ | -- TODO: Remove this function and use M:Tooltips for tooltip functionality/building |
||
local function getModLink(ModName) |
local function getModLink(ModName) |
||
--Scorch and Seeker are both enemies and mods. Thanks DE. |
--Scorch and Seeker are both enemies and mods. Thanks DE. |
||
257行目: | 298行目: | ||
end |
end |
||
+ | -- TODO: Remove unused function as avionics are now considered as mods |
||
local function getAvionicLink(AName, AHouse) |
local function getAvionicLink(AName, AHouse) |
||
local result = '<span style="white-space:pre">[['..AName |
local result = '<span style="white-space:pre">[['..AName |
||
273行目: | 315行目: | ||
end |
end |
||
− | --Formats a string of text for a reward table |
+ | --- Formats a string of text for a reward table |
− | --(NOTE: ALWAYS USES TWO COLUMNS) |
+ | -- (NOTE: ALWAYS USES TWO COLUMNS) |
− | --Format is |
+ | -- Format is |
-- [Icon] [Quantity] [Item Name with Link] || [Drop Chance]] |
-- [Icon] [Quantity] [Item Name with Link] || [Drop Chance]] |
||
− | -- |
+ | -- With some slight variation based on drop type |
− | -- |
+ | -- Variation is mostly helpful for getting the right icon |
+ | -- TODO: Nested if/else code blocks can probably be formatted as a map |
||
+ | -- @function formatDropString |
||
local function formatDropString(drop) |
local function formatDropString(drop) |
||
local result = "" |
local result = "" |
||
286行目: | 330行目: | ||
iconText = Icon._Resource(drop.IName, nil, nil) |
iconText = Icon._Resource(drop.IName, nil, nil) |
||
if(drop.IName == "Mutalist Alad V Nav Coordinate") then |
if(drop.IName == "Mutalist Alad V Nav Coordinate") then |
||
− | result = result.."[[ |
+ | result = result.."[[Nav Coordinates#Mutalist Nav Coordinates|Mutalist Alad V Nav Coordinate]]" |
else |
else |
||
− | local pieces = |
+ | local pieces = String.split(drop.IName, "%s") |
local lastPiece = pieces[Shared.tableCount(pieces)] |
local lastPiece = pieces[Shared.tableCount(pieces)] |
||
if(lastPiece == "Lens") then |
if(lastPiece == "Lens") then |
||
319行目: | 363行目: | ||
local sp1, trash = string.find(drop.IName, " ") |
local sp1, trash = string.find(drop.IName, " ") |
||
local tier = string.sub(drop.IName, 1, sp1 - 1) |
local tier = string.sub(drop.IName, 1, sp1 - 1) |
||
− | iconText = relicTooltipStartNoDot..drop.IName..relicTooltipCenter..Icon._Item(tier, nil, "40x40") |
+ | iconText = relicTooltipStartNoDot..string.gsub(drop.IName," %(.+%)","")..relicTooltipCenter..Icon._Item(tier, nil, "40x40") |
− | result = result.."[["..string.gsub(drop.IName," |
+ | result = result.."[["..string.gsub(drop.IName," %(.+%)","").."|"..drop.IName.." Relic]]"..relicTooltipEnd |
elseif (dropType == "Credits") then |
elseif (dropType == "Credits") then |
||
iconText = Icon._Item("Credits", nil, nil) |
iconText = Icon._Item("Credits", nil, nil) |
||
result = result.."[[Credit Cache]]" |
result = result.."[[Credit Cache]]" |
||
elseif (dropType == "Blueprint") then |
elseif (dropType == "Blueprint") then |
||
− | local pieces = |
+ | local pieces = String.split(drop.IName, "%s") |
local BPType = pieces[2] |
local BPType = pieces[2] |
||
local BPName = pieces[1] |
local BPName = pieces[1] |
||
− | local linkString = |
+ | local linkString = String.split(drop.IName, "%s")[1] |
--Change the link for Eidolon Lenses from Eidolon to the correct page |
--Change the link for Eidolon Lenses from Eidolon to the correct page |
||
if linkString == 'Eidolon' then |
if linkString == 'Eidolon' then |
||
336行目: | 380行目: | ||
if (BPName == "Vidar" or BPName == "Lavan" or BPName == "Zetki") then |
if (BPName == "Vidar" or BPName == "Lavan" or BPName == "Zetki") then |
||
iconText = Icon._Item("Blueprint", nil, nil) |
iconText = Icon._Item("Blueprint", nil, nil) |
||
− | linkString=' |
+ | linkString='Railjack/Components' |
− | + | elseif (BPType == "Cerebrum") then |
|
− | + | iconText = Icon._Item("Neuroptics", nil, nil) -- see below |
|
− | elseif (BPType == " |
+ | elseif (BPType == "Carapace") then |
− | + | iconText = Icon._Item("Chassis", nil, nil) -- fix for nautilus icons |
|
− | elseif (BPName == " |
+ | elseif (BPName == "Forma") then |
− | iconText = Icon._Item(" |
+ | iconText = Icon._Item("Forma", nil, nil) |
elseif (BPName == "Miter" and BPType == "Chassis") then |
elseif (BPName == "Miter" and BPType == "Chassis") then |
||
--a workaround for displaying proper icons for Miter parts |
--a workaround for displaying proper icons for Miter parts |
||
411行目: | 455行目: | ||
iconText = Icon._Item("Blueprint", nil, nil) |
iconText = Icon._Item("Blueprint", nil, nil) |
||
linkString = "Ephemera" |
linkString = "Ephemera" |
||
− | + | elseif (BPName == "Arum") then |
|
− | + | -- workarounf for arum spinosa |
|
− | + | linkString = pieces[1].." "..pieces[2] |
|
− | + | if (pieces[3]=="Blueprint") then |
|
− | + | iconText = Icon._Item("Blueprint", nil, nil) -- this one is superfluous |
|
− | + | elseif (pieces[3]=="Guard") then |
|
− | + | iconText = Icon._Item("Pouch", nil, nil) |
|
− | + | elseif (pieces[3]=="Rivet") then |
|
− | + | iconText = Icon._Item("Link", nil, nil) |
|
− | + | end |
|
else |
else |
||
iconText = Icon._Item("Blueprint", nil, nil) |
iconText = Icon._Item("Blueprint", nil, nil) |
||
451行目: | 495行目: | ||
end |
end |
||
− | --Returns a table of all rewards for a given mission, split by rotation |
+ | --- Returns a table of all rewards for a given mission, split by rotation |
+ | -- @function getRewardsForMission |
||
local function getRewardsForMission(theMission) |
local function getRewardsForMission(theMission) |
||
local result = {} |
local result = {} |
||
471行目: | 516行目: | ||
end |
end |
||
+ | -- TODO: Should this be a public/exported function? |
||
function p.linkType(Type) |
function p.linkType(Type) |
||
return({ |
return({ |
||
478行目: | 524行目: | ||
end |
end |
||
+ | --- |
||
+ | -- @function p.getMissions |
||
function p.getMissions(compareFunction) |
function p.getMissions(compareFunction) |
||
local data = {} |
local data = {} |
||
488行目: | 536行目: | ||
end |
end |
||
− | --Gets the list of missions that give rewards for a specific Alias (ex Defense1) |
+ | --- Gets the list of missions that give rewards for a specific Alias (ex Defense1) |
+ | -- @function p.getMissionTable |
||
function p.getMissionTable(MissionAlias) |
function p.getMissionTable(MissionAlias) |
||
local data = {} |
local data = {} |
||
499行目: | 548行目: | ||
end |
end |
||
− | --Gets a list of missions with rewards for a given planet |
+ | --- Gets a list of missions with rewards for a given planet |
+ | -- @function p.getMissionsForPlanet |
||
function p.getMissionsForPlanet(Planet) |
function p.getMissionsForPlanet(Planet) |
||
local missions = {} |
local missions = {} |
||
523行目: | 573行目: | ||
end |
end |
||
− | --Returns the rewards for the A tier only for a mission |
+ | --- Returns the rewards for the A tier only for a mission |
− | --Handy for missions like Capture that have a single reward |
+ | -- Handy for missions like Capture that have a single reward |
− | --Returns as rows for a table with two columns |
+ | -- Returns as rows for a table with two columns |
− | --See the existing Capture rewards section for an example |
+ | -- See the existing Capture rewards section for an example |
+ | -- @function p.getSingleRotationRewards |
||
function p.getSingleRotationRewards(frame) |
function p.getSingleRotationRewards(frame) |
||
local MissionType = frame.args ~= nil and frame.args[1] |
local MissionType = frame.args ~= nil and frame.args[1] |
||
533行目: | 584行目: | ||
local theMission = p.getMission(MissionType, MissionCat) |
local theMission = p.getMission(MissionType, MissionCat) |
||
+ | assert(theMission ~= nil, 'p.getSingleRotationRewards(frame): Could not get mission of type "'..MissionType..'" and category "'..MissionCat..'"') |
||
− | if(theMission == nil) then |
||
− | return "ERROR: No mission found for those parameters" |
||
− | end |
||
local data = getRewardsForMission(theMission) |
local data = getRewardsForMission(theMission) |
||
554行目: | 603行目: | ||
end |
end |
||
− | --Returns the rewards for a given mission/tier |
+ | --- Returns the rewards for a given mission/tier |
− | --Returns as rows for a table with six columns, two for each rotation |
+ | -- Returns as rows for a table with six columns, two for each rotation |
− | --See existing Survival/Rewards/Normal_Mission for examples |
+ | -- See existing Survival/Rewards/Normal_Mission for examples |
− | --if Tier==AllTier it will call a specific function to merge all tiers together in a single A,B,C table |
+ | -- if Tier==AllTier it will call a specific function to merge all tiers together in a single A,B,C table |
+ | -- @function p.getRewardTable |
||
function p.getRewardTable(frame) |
function p.getRewardTable(frame) |
||
local MissionType = frame.args ~= nil and frame.args[1] |
local MissionType = frame.args ~= nil and frame.args[1] |
||
570行目: | 620行目: | ||
local theMission = p.getMission(MissionType, MissionCat) |
local theMission = p.getMission(MissionType, MissionCat) |
||
+ | assert(theMission ~= nil, 'p.getRewardTable(frame): Could not get mission of type "'..MissionType..'" and category "'..MissionCat..'"') |
||
− | if(theMission == nil) then |
||
− | return "ERROR: No mission found for those parameters" |
||
− | end |
||
local data = getRewardsForMission(theMission) |
local data = getRewardsForMission(theMission) |
||
615行目: | 663行目: | ||
end |
end |
||
− | --Gets a list of all the missions for a given MissionType and Tier |
+ | --- Gets a list of all the missions for a given MissionType and Tier |
+ | -- @function p.getMissionList |
||
function p.getMissionList(frame) |
function p.getMissionList(frame) |
||
local MissionType = frame.args ~= nil and frame.args[1] |
local MissionType = frame.args ~= nil and frame.args[1] |
||
628行目: | 677行目: | ||
local missionRecord = p.getMission(MissionType, MissionTier) |
local missionRecord = p.getMission(MissionType, MissionTier) |
||
+ | |||
− | if(missionRecord == nil) then |
||
− | + | assert(missionRecord ~= nil, 'p.getMissionList(frame): Could not figure out mission type "'..MissionType..'" and mission tier "'..MissionTier..'"') |
|
− | + | ||
local missions = p.getMissionTable(p.getMValue(missionRecord, "ALIAS")) |
local missions = p.getMissionTable(p.getMValue(missionRecord, "ALIAS")) |
||
640行目: | 689行目: | ||
end |
end |
||
− | --Gets a list of all the missions for a given MissionType and Tier |
+ | --- Gets a list of all the missions for a given MissionType and Tier |
+ | -- TODO: Rename this function as "p.getMissionList2" does not describe the functionality |
||
+ | -- @function p.getMissionList2 |
||
function p.getMissionList2(frame) |
function p.getMissionList2(frame) |
||
local MissionType = frame.args ~= nil and frame.args[1] |
local MissionType = frame.args ~= nil and frame.args[1] |
||
653行目: | 704行目: | ||
local missionRecord = p.getMission(MissionType, MissionTier) |
local missionRecord = p.getMission(MissionType, MissionTier) |
||
+ | |||
− | if(missionRecord == nil) then |
||
+ | assert(missionRecord ~= nil, 'p.getMissionList2(frame): Could not figure out mission type "'..MissionType..'" and mission tier "'..MissionTier..'"') |
||
− | return "ERROR: ミッションの種類がわかりませんでした" |
||
− | + | ||
local missions = p.getMissionTable(p.getMValue(missionRecord, "ALIAS")) |
local missions = p.getMissionTable(p.getMValue(missionRecord, "ALIAS")) |
||
666行目: | 717行目: | ||
end |
end |
||
+ | --- WIP get missions regardless of tier |
||
− | |||
+ | -- TODO: Finish this function or remove it entirely if not used |
||
− | |||
+ | -- @function p.getMissionAllTier |
||
− | --WIP get missions regardless of tier |
||
function p.getMissionAllTier(MissionType) |
function p.getMissionAllTier(MissionType) |
||
local a={} |
local a={} |
||
679行目: | 730行目: | ||
end |
end |
||
− | --WIP Gets a the reward table of all Mission for a given MissionType (all tiers) |
+ | --- WIP Gets a the reward table of all Mission for a given MissionType (all tiers) |
+ | -- TODO: Finish this function or remove it entirely if not used |
||
+ | -- @function p.getRewardTableAllTier |
||
function p.getRewardTableAllTier(frame) |
function p.getRewardTableAllTier(frame) |
||
local MissionType = frame.args ~= nil and frame.args[1] |
local MissionType = frame.args ~= nil and frame.args[1] |
||
− | |||
local theMissiont = p.getMissionAllTier(MissionType) |
local theMissiont = p.getMissionAllTier(MissionType) |
||
+ | |||
− | if(theMissiont == nil) then |
||
− | + | assert(theMissiont ~= nil, 'p.getRewardTableAllTier(frame): No mission found with type "'..MissionType..'"') |
|
− | end |
||
local result = "" |
local result = "" |
||
741行目: | 792行目: | ||
end |
end |
||
− | --WIP Gets a list of all Mission for a given MissionType (all tiers) |
+ | --- WIP Gets a list of all Mission for a given MissionType (all tiers) |
+ | -- TODO: Finish this function or remove it entirely if not used |
||
+ | -- @function p.getMissionListAllTier |
||
function p.getMissionListAllTier(frame) |
function p.getMissionListAllTier(frame) |
||
local MissionType = frame.args ~= nil and frame.args[1] |
local MissionType = frame.args ~= nil and frame.args[1] |
||
748行目: | 801行目: | ||
local missionRecordt = p.getMissionAllTier(MissionType) |
local missionRecordt = p.getMissionAllTier(MissionType) |
||
+ | |||
− | if(missionRecordt == nil) then |
||
− | + | assert(missionRecordt ~= nil, 'p.getMissionListAllTier(frame): Could not figure out mission type "'..MissionType..'"') |
|
− | + | ||
for i, missionRecord in pairs(missionRecordt) do |
for i, missionRecord in pairs(missionRecordt) do |
||
local missions = p.getMissionTable(p.getMValue(missionRecord, "ALIAS")) |
local missions = p.getMissionTable(p.getMValue(missionRecord, "ALIAS")) |
||
761行目: | 814行目: | ||
end |
end |
||
+ | --- Get a list of all missions that drop a given item |
||
− | |||
+ | -- @function getDropMissions |
||
− | |||
− | --Get a list of all missions that drop a given item |
||
local function getDropMissions(itemName) |
local function getDropMissions(itemName) |
||
local Drops = {} |
local Drops = {} |
||
787行目: | 839行目: | ||
end |
end |
||
+ | --- |
||
+ | -- @function getDropSyndicates |
||
local function getDropSyndicates(itemName) |
local function getDropSyndicates(itemName) |
||
local Drops = {} |
local Drops = {} |
||
803行目: | 857行目: | ||
end |
end |
||
− | --Returns an EnemyDrop object for each enemy that drops a given mod |
+ | --- Returns an EnemyDrop object for each enemy that drops a given mod |
+ | -- @function getDropEnemies |
||
local function getDropEnemies(itemName) |
local function getDropEnemies(itemName) |
||
local drops = {} |
local drops = {} |
||
829行目: | 884行目: | ||
end |
end |
||
+ | --- Gets the table used on Void Relic/ByMission |
||
− | |||
+ | -- Unlike getRewardTable, this is just the full table with all formatting |
||
− | --Gets the table used on Void Relic/ByMission |
||
+ | -- This is pretty ugly, but kinda have to do it this way |
||
− | --Unlike getRewardTable, this is just the full table with all formatting |
||
+ | -- (Unless you have a better solution, in which case by all means go ahead and fix it) |
||
− | --This is pretty ugly, but kinda have to do it this way |
||
+ | -- (I'm not exactly a Lua expert or a UI expert) |
||
− | --(Unless you have a better solution, in which case by all means go ahead and fix it) |
||
+ | -- TODO: Break up this function into smaller functions |
||
− | --(I'm not exactly a Lua expert or a UI expert) |
||
+ | -- @function p.getRelicTable |
||
function p.getRelicTable(frame) |
function p.getRelicTable(frame) |
||
+ | --Okay, so first up, need to know which planet this is for |
||
− | --さて、まず最初に、これがどの惑星のためのものかを知る必要があります。 |
||
local Planet = nil |
local Planet = nil |
||
if(frame ~= nil) then |
if(frame ~= nil) then |
||
Planet = frame.args ~= nil and frame.args[1] or frame |
Planet = frame.args ~= nil and frame.args[1] or frame |
||
end |
end |
||
− | --Planet == nil |
+ | --Planet == nil is standing in for 'all planets', so adding option to explicitly call 'all' |
if(Planet ~= nil and (Planet == "" or Planet == "All")) then |
if(Planet ~= nil and (Planet == "" or Planet == "All")) then |
||
Planet = nil |
Planet = nil |
||
865行目: | 921行目: | ||
--Now for the 'fun' part: Getting the list |
--Now for the 'fun' part: Getting the list |
||
for i, m in ipairs(missions) do |
for i, m in ipairs(missions) do |
||
+ | --For each mission, the first thing we're doing is setting up what it's called |
||
− | --各ミッションのために、まず最初にやっていることは、それが何と呼ばれているかを設定することです。 |
||
+ | --Or more accurately, what it appears as in the chart |
||
− | --より正確には、チャートのように表示されます。 |
||
local rowName = "" |
local rowName = "" |
||
local mAlias, theMission |
local mAlias, theMission |
||
− | + | if(Planet == nil) then |
|
− | + | --When showing all, the format is "Mission Type (Tier Name)" with link to mission type |
|
− | + | --For example, "[[Survival]] (Tier 1)" or "Spy (Lua)" |
|
− | + | if (m.Type== "Bounty" or m.Type== "Ghoul Bounty" or m.Type== "Onslaught") then |
|
− | + | rowName = p.linkType(m.Type).." ("..p.getMValue(m, "SHORTNAME")..")" |
|
− | + | else |
|
local mType = p.linkType(m.Type) |
local mType = p.linkType(m.Type) |
||
mType = string.gsub(mType, " %(Steel Path%)%]%]", "%]%] %(%[%[The Steel Path|Steel Path%]%]%)") |
mType = string.gsub(mType, " %(Steel Path%)%]%]", "%]%] %(%[%[The Steel Path|Steel Path%]%]%)") |
||
rowName = mType.." ("..p.getMValue(m, "NAME")..")" |
rowName = mType.." ("..p.getMValue(m, "NAME")..")" |
||
− | + | end |
|
− | + | theMission = m |
|
+ | else |
||
+ | local placeName = m.Node |
||
+ | |||
+ | --When showing a single planet, format is instead "Mission Name (Type)" |
||
+ | --For example, "Rusalka (Capture)" |
||
+ | --Mission type is still linked |
||
+ | --Dark Sector is also linked if appropriate |
||
+ | if (m.IsDarkSector == 1) then |
||
+ | rowName = placeName.." ([[Dark Sector|DS]] "..p.linkType(m.Type)..")" |
||
else |
else |
||
− | local placeName = m.Node |
||
− | |||
− | --単一惑星を表示する場合は、 "Mission Name (Type)"を表示します。 |
||
− | --For example, "Rusalka (Capture)" |
||
− | --Mission type is still linked |
||
− | --Dark Sector is also linked if appropriate |
||
− | if (m.IsDarkSector == 1) then |
||
− | rowName = placeName.." ([[Dark Sector|DS]] "..p.linkType(m.Type)..")" |
||
− | else |
||
local mType = p.linkType(m.Type) |
local mType = p.linkType(m.Type) |
||
mType = string.gsub(mType, "%[%[Cetus Bounty %(Steel Path%)%]%]", "%[%[The Steel Path|Steel Path%]%] %[%[Cetus Bounty|Bounty%]%]") |
mType = string.gsub(mType, "%[%[Cetus Bounty %(Steel Path%)%]%]", "%[%[The Steel Path|Steel Path%]%] %[%[Cetus Bounty|Bounty%]%]") |
||
899行目: | 955行目: | ||
mLevel = '<br />'..string.gsub(m.MinLevel, "<br />", " ") |
mLevel = '<br />'..string.gsub(m.MinLevel, "<br />", " ") |
||
end |
end |
||
+ | |||
− | |||
rowName = placeName..' ('..mType..')'..mLevel |
rowName = placeName..' ('..mType..')'..mLevel |
||
end |
end |
||
theMission = p.getMission(m.Tier, nil, m.Type) |
theMission = p.getMission(m.Tier, nil, m.Type) |
||
− | + | assert(theMission ~= nil, 'p.getRelicTable(frame): Could not get mission of tier "'..m.Tier..'" and type "'..m.Type..'"') |
|
+ | end |
||
− | return "ERROR: Could not Miss "..m.Tier |
||
− | + | local thisRow = nil |
|
+ | --This is where we get all the rewards for the mission |
||
− | end |
||
− | + | local drops = getRewardsForMission(theMission) |
|
+ | |||
− | --This is where we get all the rewards for the mission |
||
− | + | --Need to know if this is a single rotation |
|
+ | --Because if it is, just a checkmark instead of a letter |
||
− | |||
+ | local isSingleRot = Shared.tableCount(drops) == 1 |
||
− | --Need to know if this is a single rotation |
||
− | + | --For each mission, looping each rotation |
|
− | + | for rot, dropTable in Shared.skpairs(drops) do |
|
− | -- |
+ | --And each drop for each rotation |
− | for |
+ | for j, d in pairs(dropTable) do |
− | -- |
+ | --We only care if it's a relic |
− | + | if(d.Type == "Relic") then |
|
− | -- |
+ | --Set up the row if we don't have it yet |
− | + | --Mission will not be added to the grid unless it drops at least one relic |
|
− | + | --Avoids adding a row for something like Assassination that never gives relics |
|
− | + | if(thisRow == nil) then |
|
− | + | thisRow = {} |
|
− | + | end |
|
− | + | ||
− | + | --Example: "Lith A1" |
|
+ | local RelicText = d.IName |
||
+ | local RadiantRelic = "" |
||
+ | if (string.find(RelicText,"%(Radiant%)")~=nil) then |
||
+ | RadiantRelic = "*" |
||
+ | RelicText = string.gsub(RelicText,"%s%(Radiant%)","") |
||
+ | end |
||
+ | |||
+ | --Example: {"Lith", "A1"} |
||
+ | local RelicBits = String.split(RelicText, "%s") |
||
+ | --Example: "Lith" |
||
+ | local RTier = RelicBits[1] |
||
+ | --Example: "A1" |
||
+ | local RName = RelicBits[2] |
||
+ | |||
+ | --Make sure the relevant entry exists |
||
+ | if (thisRow[RelicText] == nil) then |
||
+ | thisRow[RelicText] = "" |
||
+ | end |
||
+ | |||
+ | --And then fill it in |
||
+ | if (isSingleRot) then |
||
+ | thisRow[RelicText] = "✔"..RadiantRelic |
||
+ | else |
||
+ | thisRow[RelicText] = thisRow[RelicText]..rot..RadiantRelic |
||
+ | end |
||
+ | |||
+ | --Adding drop rate info when hovering |
||
+ | --If the drop rate is under 1% we set it red |
||
+ | --Under 2%, orangered |
||
+ | local RelicTextColor = "inherit" |
||
+ | if (d.Chance < 1) then |
||
+ | RelicTextColor = "red" |
||
+ | elseif (d.Chance < 2) then |
||
+ | RelicTextColor = "orangered" |
||
+ | end |
||
+ | thisRow[RelicText] = "<span style=\"color:" .. RelicTextColor .. ";\" title=\"Drop rate : " .. d.Chance .. "%\">" .. thisRow[RelicText] .. "</span>" |
||
− | + | ||
− | + | --Also gotta add the Relic to our list if we don't have it yet |
|
− | + | if(Relics[RTier][RName] == nil) then |
|
− | + | Relics[RTier][RName] = RelicText |
|
− | RadiantRelic = "*" |
||
− | RelicText = string.gsub(RelicText,"%s%(Radiant%)","") |
||
− | end |
||
− | |||
− | --Example: {"Lith", "A1"} |
||
− | local RelicBits = Shared.splitString(RelicText, " ") |
||
− | --Example: "Lith" |
||
− | local RTier = RelicBits[1] |
||
− | --Example: "A1" |
||
− | local RName = RelicBits[2] |
||
− | |||
− | --Make sure the relevant entry exists |
||
− | if (thisRow[RelicText] == nil) then |
||
− | thisRow[RelicText] = "" |
||
− | end |
||
− | |||
− | --And then fill it in |
||
− | if (isSingleRot) then |
||
− | thisRow[RelicText] = "✔"..RadiantRelic |
||
− | else |
||
− | thisRow[RelicText] = thisRow[RelicText]..rot..RadiantRelic |
||
− | end |
||
− | |||
− | --Adding drop rate info when hovering |
||
− | --If the drop rate is under 1% we set it red |
||
− | --Under 2%, orangered |
||
− | local RelicTextColor = "inherit" |
||
− | if (d.Chance < 1) then |
||
− | RelicTextColor = "red" |
||
− | elseif (d.Chance < 2) then |
||
− | RelicTextColor = "orangered" |
||
− | end |
||
− | thisRow[RelicText] = "<span style=\"color:" .. RelicTextColor .. ";\" title=\"Drop rate : " .. d.Chance .. "%\">" .. thisRow[RelicText] .. "</span>" |
||
− | |||
− | |||
− | --Also gotta add the Relic to our list if we don't have it yet |
||
− | if(Relics[RTier][RName] == nil) then |
||
− | Relics[RTier][RName] = RelicText |
||
− | end |
||
end |
end |
||
end |
end |
||
end |
end |
||
+ | end |
||
− | + | if ( thisRow ~= nil ) then |
|
− | + | tableRows[rowName] = thisRow |
|
− | + | end |
|
end |
end |
||
1,037行目: | 1,091行目: | ||
end |
end |
||
+ | --- Function used for building Void Relic/DropLocation table |
||
− | |||
+ | -- TODO: Break up this function into smaller functions |
||
− | --Void Relic/DropLocation テーブルを構築するための関数です。 |
||
+ | -- @function p.getRelicByLocation |
||
function p.getRelicByLocation(frame) |
function p.getRelicByLocation(frame) |
||
local tier = frame.args ~= nil and frame.args[1] or frame |
local tier = frame.args ~= nil and frame.args[1] or frame |
||
− | local tierPieces = |
+ | local tierPieces = String.split(tier, "%s") |
--5/26/2018: You can now call on a single relic and get just the table |
--5/26/2018: You can now call on a single relic and get just the table |
||
+ | -- TODO: Use M:Table instead for table count/size |
||
if(Shared.tableCount(tierPieces) == 2) then |
if(Shared.tableCount(tierPieces) == 2) then |
||
tier = tierPieces[1] |
tier = tierPieces[1] |
||
1,052行目: | 1,108行目: | ||
local relicData = {} |
local relicData = {} |
||
+ | -- TODO: Refactor so there is at max 3 nested code blocks |
||
− | --私のほとんどの機能と同様に、これを2つの部分に分割します: |
||
+ | --As with most of my functions, breaking this into two parts: |
||
− | --まず、ミッションをこなして、各レリックのデータを集めましょう。 |
||
+ | --First, gather all the data for each relic by going through missions |
||
− | --全てのミッションのドロップを調べて レリックのドロップを探しています |
||
+ | --We're looking through all drops for all missions to find relic drops |
||
for i, theMission in pairs(DropData["Missions"]) do |
for i, theMission in pairs(DropData["Missions"]) do |
||
if(theMission.Rewards ~= nil and theMission.Ignore ~= true) then |
if(theMission.Rewards ~= nil and theMission.Ignore ~= true) then |
||
1,060行目: | 1,117行目: | ||
for rot, dropTable in Shared.skpairs(theMission.Rewards) do |
for rot, dropTable in Shared.skpairs(theMission.Rewards) do |
||
for j, drop in pairs(dropTable) do |
for j, drop in pairs(dropTable) do |
||
+ | --When we find a relic drop, make sure it's for the right tier |
||
− | --レリックドロップを見つけたら、それが正しいティアのものであることを確認してください |
||
if(drop[misTypeCol] == "Relic") then |
if(drop[misTypeCol] == "Relic") then |
||
--Example: {"Lith", "A1"} |
--Example: {"Lith", "A1"} |
||
− | local RelicBits = |
+ | local RelicBits = String.split(drop[misNameCol], "%s") |
--Example: "Lith" |
--Example: "Lith" |
||
local RTier = RelicBits[1] |
local RTier = RelicBits[1] |
||
1,098行目: | 1,155行目: | ||
!Rotation |
!Rotation |
||
!Chance]] |
!Chance]] |
||
+ | |||
− | |||
for RName, RTable in Shared.skpairs(relicData) do |
for RName, RTable in Shared.skpairs(relicData) do |
||
local tierLink = "\n|-\n| ".."[["..tier.." "..RName.."]]" |
local tierLink = "\n|-\n| ".."[["..tier.." "..RName.."]]" |
||
1,144行目: | 1,201行目: | ||
table.insert(result, "\n|}") |
table.insert(result, "\n|}") |
||
+ | |||
− | |||
+ | -- TODO: Remove all the newlines in elements that is inserted into table. |
||
+ | -- Can just concat newlines at the end here. |
||
return table.concat(result) |
return table.concat(result) |
||
end |
end |
||
+ | --- TODO: Break up this function into smaller functions |
||
+ | -- @function p.getSingleRelicByLocation |
||
function p.getSingleRelicByLocation(tier, name) |
function p.getSingleRelicByLocation(tier, name) |
||
local relicData = {Drops = {}, Rewards = Void.getRelic(tier, name).Drops} |
local relicData = {Drops = {}, Rewards = Void.getRelic(tier, name).Drops} |
||
1,164行目: | 1,225行目: | ||
if(drop[misTypeCol] == "Relic") then |
if(drop[misTypeCol] == "Relic") then |
||
--Example: {"Lith", "A1"} |
--Example: {"Lith", "A1"} |
||
− | local RelicBits = |
+ | local RelicBits = String.split(drop[misNameCol], "%s") |
--Example: "Lith" |
--Example: "Lith" |
||
local RTier = RelicBits[1] |
local RTier = RelicBits[1] |
||
1,209行目: | 1,270行目: | ||
types[i] = d.MType --p.linkType(d.MType) |
types[i] = d.MType --p.linkType(d.MType) |
||
if (d.MType == "Onslaught") then |
if (d.MType == "Onslaught") then |
||
− | missions[i] = p.getMValue(d.theMission, ' |
+ | missions[i] = p.getMValue(d.theMission, 'Tier') |
else |
else |
||
missions[i] = p.getMValue(d.theMission, 'Name') |
missions[i] = p.getMValue(d.theMission, 'Name') |
||
1,227行目: | 1,288行目: | ||
end |
end |
||
local num = string.gsub(chances[i],"%%","") |
local num = string.gsub(chances[i],"%%","") |
||
− | local ChancesBits = |
+ | local ChancesBits = String.split(num, ", ") |
− | + | local highchance |
|
if (table.getn(ChancesBits) <= 1) or (ChancesBits == nil) then |
if (table.getn(ChancesBits) <= 1) or (ChancesBits == nil) then |
||
highchance = tonumber(num) |
highchance = tonumber(num) |
||
1,246行目: | 1,307行目: | ||
local mType = p.linkType(types[i]) |
local mType = p.linkType(types[i]) |
||
mType = string.gsub(mType, " %(Steel Path%)%]%]", "%]%]<br />%(%[%[The Steel Path|Steel Path%]%]%)") |
mType = string.gsub(mType, " %(Steel Path%)%]%]", "%]%]<br />%(%[%[The Steel Path|Steel Path%]%]%)") |
||
+ | |||
− | |||
result = result.."\n|-\n|style=\"padding:10px;\"|"..mType |
result = result.."\n|-\n|style=\"padding:10px;\"|"..mType |
||
− | if(mlist == " |
+ | if(mlist == "") then |
result = result.."\n|style=\"padding:10px;\"|"..missions[i] |
result = result.."\n|style=\"padding:10px;\"|"..missions[i] |
||
else |
else |
||
1,264行目: | 1,325行目: | ||
end |
end |
||
+ | --- |
||
+ | -- @function p.getItemByMissionTable |
||
function p.getItemByMissionTable(frame) |
function p.getItemByMissionTable(frame) |
||
local theDrop = frame.args ~= nil and frame.args[1] or frame |
local theDrop = frame.args ~= nil and frame.args[1] or frame |
||
1,295行目: | 1,358行目: | ||
end |
end |
||
+ | --- |
||
+ | -- @function p.getItemByEnemyTable |
||
function p.getItemByEnemyTable(frame) |
function p.getItemByEnemyTable(frame) |
||
local theDrop = frame.args ~= nil and frame.args[1] or frame |
local theDrop = frame.args ~= nil and frame.args[1] or frame |
||
1,324行目: | 1,389行目: | ||
end |
end |
||
− | --Returns the list of drop locations used by the ModBox |
+ | --- Returns the list of drop locations used by the ModBox |
+ | -- TODO: Break up this function into smaller functions |
||
+ | -- @function p.getItemDropList |
||
function p.getItemDropList(frame) |
function p.getItemDropList(frame) |
||
local theDrop = frame.args ~= nil and frame.args[1] or frame |
local theDrop = frame.args ~= nil and frame.args[1] or frame |
||
1,361行目: | 1,428行目: | ||
end |
end |
||
− | table.sort(finalTable, function (r1, r2) |
+ | table.sort(finalTable, function (r1, r2) |
return r1 < r2 |
return r1 < r2 |
||
end) |
end) |
||
1,372行目: | 1,439行目: | ||
local mType = p.linkType(i) |
local mType = p.linkType(i) |
||
mType = string.gsub(mType, " %(Steel Path%)%]%]", "%]%] %(%[%[The Steel Path|Steel Path%]%]%)") |
mType = string.gsub(mType, " %(Steel Path%)%]%]", "%]%] %(%[%[The Steel Path|Steel Path%]%]%)") |
||
+ | |||
− | |||
result = result.."<br/>"..mType |
result = result.."<br/>"..mType |
||
1,385行目: | 1,452行目: | ||
ttip = ttip..'\\nRotation '..thisDrop.Rotation |
ttip = ttip..'\\nRotation '..thisDrop.Rotation |
||
if (thisDrop.Chance ~= nil) then |
if (thisDrop.Chance ~= nil) then |
||
− | + | ttip = ttip..': '..thisDrop.Chance.."%" |
|
+ | end |
||
− | end |
||
end |
end |
||
1,430行目: | 1,497行目: | ||
end |
end |
||
+ | --- |
||
+ | -- @function p.getItemByEnemyCount |
||
function p.getItemByEnemyCount(frame) |
function p.getItemByEnemyCount(frame) |
||
local theDrop = frame.args ~= nil and frame.args[1] or frame |
local theDrop = frame.args ~= nil and frame.args[1] or frame |
||
1,438行目: | 1,507行目: | ||
end |
end |
||
+ | --- |
||
+ | -- @function p.getItemByMissionCount |
||
function p.getItemByMissionCount(frame) |
function p.getItemByMissionCount(frame) |
||
local theDrop = frame.args ~= nil and frame.args[1] or frame |
local theDrop = frame.args ~= nil and frame.args[1] or frame |
||
1,446行目: | 1,517行目: | ||
end |
end |
||
+ | --- |
||
+ | -- @function p.getFullEnemyList |
||
function p.getFullEnemyList(frame) |
function p.getFullEnemyList(frame) |
||
local result = "All Enemies: " |
local result = "All Enemies: " |
||
1,462行目: | 1,535行目: | ||
end |
end |
||
+ | --- |
||
+ | -- @function p.getEnemyModDrops |
||
function p.getEnemyModDrops(frame) |
function p.getEnemyModDrops(frame) |
||
local EnemyName = frame.args ~= nil and frame.args[1] or frame |
local EnemyName = frame.args ~= nil and frame.args[1] or frame |
||
1,491行目: | 1,566行目: | ||
end |
end |
||
+ | -- TODO: Remove this function or move it to /validate subpage of /data |
||
function p.TestFrame(frame) |
function p.TestFrame(frame) |
||
local txt = "VALUES:\n\n" |
local txt = "VALUES:\n\n" |
2021年6月7日 (月) 02:33時点における版
このモジュールについての説明文ページを モジュール:DropTables/doc に作成できます
--- '''DropTables''' stores drop table data from the official WARFRAME drop table repository.<br />
--
-- On this Wiki, DropTables is used in:
-- * [[Template:RelicTable]]
--
-- @module droptables
-- @alias p
-- @author [[User:Falterfire|Falterfire]]
-- @attribution [[User:Croquemorttime|Croquemorttime]]
-- @attribution [[User:Flaicher|Flaicher]]
-- @attribution [[User:FINNER|FINNER]]
-- @image
-- @require [[Module:DropTables/data]]
-- @require [[Module:Missions/data]]
-- @require [[Module:String]]
-- @require [[Module:Icon]]
-- @require [[Module:Shared]]
-- @require [[Module:Void]]
-- @release stable
-- <nowiki>
--Rewritten version of Module:DropTables to work with new format of data.
--NOTE: I'm currently in the process of copying over a new data format
-- It should be easier to keep up to date, but things may be a bit screwy over the next hour or two
-- Please do not revert this update without checking with me.
-- (For the fastest response, ping me on the Wiki discord)
-- User:Falterfire, 1/6/18
--For reference:
-- in DropData["Missions"].Rewards
local misNameCol = 1 -- Name of the drop
local misTypeCol = 2 -- Type of thing dropped (IE Mod, Endo, Credits)
local misChanceCol = 3 -- Chance for the thing to drop
local misCountCol = 4 -- Number of things dropped. If empty, default to 1
-- in DropData["Enemies"].Mods
local modNameCol = 1 -- Name of the mod
local modChanceCol = 2 -- The chance of a mod dropping
local modCountCol = 3 -- If empty, default to 1. Normally only different for Endo
-- in DropData["Enemies"].Avionics
-- TODO: Remove this as avionics are now considered mods
local aviNameCol = 1 -- Avionic name
local aviChanceCol = 2 -- Avionic drop chance
local aviHouseCol = 3 -- Avionic house (optional if known)
-- in DropData["Syndicates"].Offerings
local synNameCol = 1 -- Name of the offering
local synTypeCol = 2 -- Type of offering
local synCostCol = 3 -- The reputation cost for the offering
local synRankCol = 4 -- The required Syndicate Rank to purchase the offering
local p = {}
local DropData = mw.loadData( 'Module:DropTables/data' )
local MissionData = mw.loadData( 'Module:Missions/data' )
local Icon = require( "Module:Icon" )
local String = require( "Module:String" )
local Shared = require( "Module:Shared" )
local Void = require( "Module:Void" )
local relicTooltipStart = "<span style=\"border-bottom: 1px dotted;\" class=\"relic-tooltip\" data-param=\""
local relicTooltipStartNoDot = '<span class="tooltip" data-param2="Void" data-param="'
local relicTooltipCenter = "\">"
local relicTooltipEnd = "</span>"
---
-- @function p.getMValue
function p.getMValue(theMission, ValName, noBreaks)
if(type(theMission) == "string") then theMission = p.getMission(theMission) end
if(theMission == nil) then return nil end
ValName = string.upper(ValName)
if(ValName == 'ALIAS') then
if(theMission.Alias ~= nil) then
return theMission.Alias
else
return theMission.Type..' - '..theMission.Tier
end
elseif(ValName == 'NAME') then
if(theMission.Name ~= nil) then
local mName = theMission.Name
if noBreaks == true then
mName = string.gsub(mName, "<br />", " ")
end
return mName
else
return theMission.Tier
end
elseif(ValName == 'SHORTNAME') then
if(theMission.ShortName ~= nil) then
return theMission.ShortName
else
return p.getMValue(theMission, 'NAME')
end
elseif(ValName == 'TIER') then
return theMission.Tier
elseif(ValName == 'TYPE') then
return theMission.Type
end
end
--- Goes by Type & Tier, Type & Name, or Alias
-- So ("Survival", "Easy"), ("Survival", "Tier 1"), or ("Survival1") all get the same thing
-- @function p.getMission
function p.getMission(MissionType, MissionTier, MissionName)
for i, Miss in pairs(DropData["Missions"]) do
--If MissionTier is nil, the MissionType variable is the Alias so check against that instead
if(MissionTier == nil) then
if(MissionType == Miss.Alias or MissionType == Miss.Tier) and (Miss.Type == MissionName) then
return Miss
elseif(MissionType == Miss.Alias) then
return Miss
elseif (Miss.Type == "Assassinate") and (Miss.Tier == MissionType) then --for the peculiar call p.getRelicTable does
return Miss
end
else
if(Miss.Type == MissionType and
(Miss.Tier == MissionTier or Miss.Name == MissionTier)) then
return Miss
end
end
end
end
--- Basically pretending to be semi-object oriented
-- Calling this whenever I'm pulling drops from enemies and passing them around
-- NOTE: As of writing, this assumes enemies don't have Blueprint or other drops listed.
-- TODO: buildEnemyDrop(), buildMissionDrop(), buildSyndicateDrop(), buildResourceDrop(),
-- and etc. can probably be in a single buildDrop function that passes in a table/function
-- argument telling how to format drops
-- @function buildEnemyDrop
local function buildEnemyDrop(Enemy, Mod)
local drop = {EName = Enemy.Name, IName = Mod[modNameCol]}
drop.Chance = (Enemy.ModChance * Mod[modChanceCol]) / 100
drop.Count = Mod[modCountCol] ~= nil and Mod[modCountCol] or 1
if(drop.IName == 'Endo') then drop.Type = 'Endo' else drop.Type = 'Mod' end
return drop
end
--- Like above, but for mission drops
-- Calling this whenever I'm pulling drops from missions and passing them around
-- @function buildMissionDrop
local function buildMissionDrop(theMission, Rotation, Item)
local drop = {MType = theMission.Type, MTier = theMission.Tier}
drop.Rotation = Rotation
drop.IName = Item[misNameCol]
drop.Chance = Item[misChanceCol]
drop.Count = Item[misCountCol] ~= nil and Item[misCountCol] or 1
drop.Type = Item[misTypeCol]
--Just go ahead and tag this on because who knows what we'll need from it
drop.theMission = theMission
return drop
end
--- Like above, but for Syndicate Offerings
-- @function buildSyndicateDrop
local function buildSyndicateDrop(theSyndicate, Item)
local drop = {SName = theSyndicate.Name, IName = Item[synNameCol]}
drop.Type = Item[synTypeCol]
drop.Cost = Item[synCostCol]
drop.Rank = Item[synRankCol]
return drop
end
--Like above, but for Avionics
-- TODO: Remove unused function as avionics are now considered as mods
local function buildAvionicDrop(Enemy, Avionic)
local drop = {EName = Enemy.Name, IName = Avionic[aviNameCol]}
drop.Chance = (Enemy.ModChance * Avionic[aviChanceCol]) / 100
drop.Count = 1
drop.Type = 'Avionic'
if (Avionic[aviHouseCol] ~= nil) then
drop.House = Avionic[aviHouseCol]
end
return drop
end
--- Like above, but for resource drops
-- @function buildResourceDrop
local function buildResourceDrop(Enemy, Resource)
local drop = {EName = Enemy.Name, IName = Resource[resourceNameCol]}
drop.Chance = (Enemy.ResourceChance * Resource[resourceChanceCol]) / 100
drop.Count = 1
drop.Type = 'Resource'
return drop
end
local function linkEnemy(EName)
--Cut off enemy names before parentheses while linking
local paren, trash = string.find(EName, "%(")
local Result = ""
if(paren ~= nil) then
Result = "[["..string.sub(EName, 1, paren - 2).."|"..EName.."]]"
elseif (EName == "Fissure Corrupted Enemy") then
Result = "[[Void Fissure|"..EName.."]]"
elseif (EName == "Dargyn" or EName == "Carrier") then
Result = "[["..EName.." (Enemy)".."|"..EName.."]]"
else
Result = "[["..EName.."]]"
end
return Result
end
--Links a Syndicate and returns it.
--Doesn't actually do anything but add brackets right now
-- TODO: Remove this simple function since it is uneeded; can just concat the brackets when needed
local function linkSyndicate(SName)
return '[['..SName..']]'
end
--- Returns the "real" drop chance of a specific enemy drop
-- This involves combining chance to drop mod/blueprint with chance of that specific item dropping
-- So 3% Mod Chance + 37.94% Pressure Point chance = 1.1382% real chance
-- @function getRealDropChance
local function getRealDropChance(EnemyDrop)
local odds1 = EnemyDrop[eChance1Col]
local odds2 = EnemyDrop[eChance2Col]
local result = ((odds1 * odds2) / 100)
return result
end
---
-- @function getAllModDrops
local function getAllModDrops(enemyName)
local drops = {}
for i, Enemy in pairs(DropData["Enemies"]) do
if(Enemy.Name == enemyName and Enemy.Mods ~= nil) then
for j, Mod in pairs(Enemy.Mods) do
local drop = buildEnemyDrop(Enemy, Mod)
table.insert(drops, drop)
end
end
if(Enemy.Name == enemyName and Enemy.Avionics ~= nil) then
for j, Avionic in pairs(Enemy.Avionics) do
local drop = buildAvionicDrop(Enemy, Avionic)
table.insert(drops, drop)
end
end
end
return drops
end
--- Custom table sort for reward tables
-- WIP, initial rules:
-- Sort first by type, then alphabetically within type, then by quantity
-- WIP try sorting first by drop chance...
-- TODO: Finish this function
-- @function rewardTableSort
local function rewardTableSort(theTable)
local function sorter(r1, r2)
if(r1.Chance == r2.Chance) then
if(r1.Type == r2.Type) then
if(r1.IName == r2.IName) then
return r1.Count < r2.Count
else
return r1.IName < r2.IName
end
else
return r1.Type < r2.Type
end
else
return r1.Chance > r2.Chance
end
end
table.sort(theTable, sorter)
end
--- Custom table sort for Enemy tables
-- Rules:
-- Sort first by Drop Chance, then alphabetically within Drop Chance with Endo being last
-- @function enemyTableSort
local function enemyTableSort(theTable)
local function sorter(r1, r2)
if(r1.Chance == r2.Chance) then
if(r1.Count == r2.Count) then
return r1.IName < r2.IName
else
return r1.Count < r2.Count
end
else
return r1.Chance > r2.Chance
end
end
table.sort(theTable, sorter)
end
-- TODO: Remove this function and use M:Tooltips for tooltip functionality/building
local function getModLink(ModName)
--Scorch and Seeker are both enemies and mods. Thanks DE.
--Also Sanctuary as mod VS Simaris's thing
--Also Antitoxin, mod vs gear
if(ModName == "Scorch" or ModName == "Seeker" or ModName == "Sanctuary" or ModName == "Antitoxin") then
return "<span class=\"mod-tooltip\" data-param=\""..ModName.."\" style=\"white-space:pre\">[["..ModName.." (Mod)".."|"..ModName.."]]</span>"
else
return "<span class=\"mod-tooltip\" data-param=\""..ModName.."\" style=\"white-space:pre\">[["..ModName.."]]</span>"
end
end
-- TODO: Remove unused function as avionics are now considered as mods
local function getAvionicLink(AName, AHouse)
local result = '<span style="white-space:pre">[['..AName
--Wiki name collisions are handled here
--Warhead is also an Archwing ability
if(AName == 'Warhead') then
result = result..' (Avionic)|'..AName
end
result = result..']]'
--Add the house if it was passed in
if (AHouse ~= nil) then
result = result..' ('..AHouse..')'
end
result = result..'</span>'
return result
end
--- Formats a string of text for a reward table
-- (NOTE: ALWAYS USES TWO COLUMNS)
-- Format is
-- [Icon] [Quantity] [Item Name with Link] || [Drop Chance]]
-- With some slight variation based on drop type
-- Variation is mostly helpful for getting the right icon
-- TODO: Nested if/else code blocks can probably be formatted as a map
-- @function formatDropString
local function formatDropString(drop)
local result = ""
local dropType = drop.Type
local iconText = ""
if(dropType == "Resource") then
iconText = Icon._Resource(drop.IName, nil, nil)
if(drop.IName == "Mutalist Alad V Nav Coordinate") then
result = result.."[[Nav Coordinates#Mutalist Nav Coordinates|Mutalist Alad V Nav Coordinate]]"
else
local pieces = String.split(drop.IName, "%s")
local lastPiece = pieces[Shared.tableCount(pieces)]
if(lastPiece == "Lens") then
if(pieces[1] == "Greater") then
iconText = Icon._Resource("Greater Focus Lens")
else
iconText = Icon._Resource("Focus Lens")
end
result = "[[Focus Lens|"..drop.IName.."]]"
else
result = result.."[["..drop.IName.."]]"
end
end
elseif (dropType == "Scene") then
--iconText = Icon._Item("Scene", nil, nil)
result = result.."[[Captura|"..drop.IName.."]]"
elseif (dropType == "Endo") then
iconText = Icon._Item("Endo", nil, nil)
result = result.."[[Endo]]"
elseif (dropType == "Ayatan Sculpture") then
--iconText = Icon._Item(drop.IName)
result = "[[Ayatan Sculpture|"..drop.IName.."]]"
elseif (dropType == "Mod") then
iconText = Icon._Item("Mods", nil, nil)
result = result..getModLink(drop.IName)
elseif (dropType == "Relic") then
--Grabbing everything before the first space to get tier
--That way I can get the right icon
--IE 'Lith' from 'Lith V1'
local sp1, trash = string.find(drop.IName, " ")
local tier = string.sub(drop.IName, 1, sp1 - 1)
iconText = relicTooltipStartNoDot..string.gsub(drop.IName," %(.+%)","")..relicTooltipCenter..Icon._Item(tier, nil, "40x40")
result = result.."[["..string.gsub(drop.IName," %(.+%)","").."|"..drop.IName.." Relic]]"..relicTooltipEnd
elseif (dropType == "Credits") then
iconText = Icon._Item("Credits", nil, nil)
result = result.."[[Credit Cache]]"
elseif (dropType == "Blueprint") then
local pieces = String.split(drop.IName, "%s")
local BPType = pieces[2]
local BPName = pieces[1]
local linkString = String.split(drop.IName, "%s")[1]
--Change the link for Eidolon Lenses from Eidolon to the correct page
if linkString == 'Eidolon' then
linkString = 'Focus Lens#Eidolon Lenses'
end
if (BPName == "Vidar" or BPName == "Lavan" or BPName == "Zetki") then
iconText = Icon._Item("Blueprint", nil, nil)
linkString='Railjack/Components'
elseif (BPType == "Cerebrum") then
iconText = Icon._Item("Neuroptics", nil, nil) -- see below
elseif (BPType == "Carapace") then
iconText = Icon._Item("Chassis", nil, nil) -- fix for nautilus icons
elseif (BPName == "Forma") then
iconText = Icon._Item("Forma", nil, nil)
elseif (BPName == "Miter" and BPType == "Chassis") then
--a workaround for displaying proper icons for Miter parts
iconText = Icon._Item("Stock", nil, nil)
elseif (BPName == "Miter" and BPType == "Handle") then
--because Miter has oddly named parts
iconText = Icon._Item("Receiver", nil, nil)
elseif (BPName == "Shedu" and BPType == "Chassis") then
--a workaround for displaying proper icons for Shedu parts
iconText = Icon._Item("Stock", nil, nil)
elseif (BPType == "Systems") then
iconText = Icon._Item("Systems", nil, nil)
elseif (BPType == "Chassis") then
iconText = Icon._Item("Chassis", nil, nil)
elseif (BPType == "Neuroptics") then
iconText = Icon._Item("Neuroptics", nil, nil)
elseif (BPType == "Fuselage") then
iconText = Icon._Item("Fuselage", nil, nil)
elseif (BPType == "Engines") then
iconText = Icon._Item("Engines", nil, nil)
elseif (BPType == "Avionics") then
iconText = Icon._Item("Avionics", nil, nil)
elseif (BPType == "Barrel") then
iconText = Icon._Item("Barrel", nil, nil)
elseif (BPType == "Stock") then
iconText = Icon._Item("Stock", nil, nil)
elseif (BPType == "Receiver") then
iconText = Icon._Item("Receiver", nil, nil)
elseif (BPType == "Blade") then
iconText = Icon._Item("Blade", nil, nil)
elseif (pieces[2] == "Wraith" or pieces[2] == "Vandal" or pieces[1] == "Carmine") then
--Now a workaround for Wraith & Vandal things to link them properly. U29.10 > now works with carmine penta
--In theory works for any Wraith/Vandal item
linkString = pieces[1].." "..pieces[2]
if(pieces[3] ~= "Blueprint") then
if (BPName == "Spectra" and pieces[Shared.tableCount(pieces)] == "Chassis") then
--a workaround for displaying proper icons for Spectra parts
iconText = Icon._Item("Stock", nil, nil)
elseif (BPName == "Spectra" and pieces[Shared.tableCount(pieces)] == "Handle") then
--because Spectra has oddly named parts
iconText = Icon._Item("Receiver", nil, nil)
else
iconText = Icon._Item(pieces[Shared.tableCount(pieces)], nil, nil)
end
else
iconText = Icon._Item("Blueprint", nil, nil)
end
elseif (BPName=="Ancient" or BPName=="Charger" or BPName=="Clem") then
iconText = Icon._Item("Blueprint", nil, nil)
linkString = "Specter"
elseif (pieces[3] == "Blueprint") then
--a workaround for Eidolon Lens BP or Twin Gremlins BP to link proper pages
--should work for other 3 part blueprint names as well
linkString = pieces[1].." "..pieces[2]
iconText = Icon._Item("Blueprint", nil, nil)
elseif (pieces[1] == "Equinox") then
--a workaround for Equinox's 4 piece names
if (pieces[3] == "Systems") then
iconText = Icon._Item("Systems", nil, nil)
elseif (pieces[3] == "Chassis") then
iconText = Icon._Item("Chassis", nil, nil)
elseif (pieces[3] == "Neuroptics") then
iconText = Icon._Item("Neuroptics", nil, nil)
else
iconText = Icon._Item("Blueprint", nil, nil)
end
elseif (pieces[3] == "Ephemera") then
iconText = Icon._Item("Blueprint", nil, nil)
linkString = "Ephemera"
elseif (BPName == "Arum") then
-- workarounf for arum spinosa
linkString = pieces[1].." "..pieces[2]
if (pieces[3]=="Blueprint") then
iconText = Icon._Item("Blueprint", nil, nil) -- this one is superfluous
elseif (pieces[3]=="Guard") then
iconText = Icon._Item("Pouch", nil, nil)
elseif (pieces[3]=="Rivet") then
iconText = Icon._Item("Link", nil, nil)
end
else
iconText = Icon._Item("Blueprint", nil, nil)
end
result = result.."[["..linkString.."|"..drop.IName.."]]"
elseif (dropType == "Fragments") then
-- iconText = Icon._Item("Mutate", nil, nil)
result = result.."[[Fragments|"..drop.IName.."]]"
elseif (dropType == "Item") then
if (string.find(drop.IName,"Sigil")~=nil) then
--iconText = Icon._Item(drop.IName)
result = result.."[[Sigils|"..drop.IName.."]]"
else
iconText = Icon._Item(drop.IName)
result = result.."[["..drop.IName.."]]"
end
else
result = result..drop.IName
end
if(drop.Count > 1) then
result = drop.Count.." "..result
end
result = iconText.." "..result.." || "..drop.Chance.."%"
return result
end
--- Returns a table of all rewards for a given mission, split by rotation
-- @function getRewardsForMission
local function getRewardsForMission(theMission)
local result = {}
if(theMission.Rewards ~= nil) then
for key, dropTable in Shared.skpairs(theMission.Rewards) do
local temp = {}
for i, drop in pairs(dropTable) do
table.insert(temp, buildMissionDrop(theMission, key, drop))
end
rewardTableSort(temp)
result[key] = temp
end
end
return result
end
-- TODO: Should this be a public/exported function?
function p.linkType(Type)
return({
Salvage="[[Infested Salvage|Salvage]]",
Rush="[[Rush (Archwing)|Rush]]",
})[Type] or "[["..Type.."]]"
end
---
-- @function p.getMissions
function p.getMissions(compareFunction)
local data = {}
for i, m in ipairs(MissionData["MissionDetails"]) do
if(compareFunction(m)) then
table.insert(data, m)
end
end
return data
end
--- Gets the list of missions that give rewards for a specific Alias (ex Defense1)
-- @function p.getMissionTable
function p.getMissionTable(MissionAlias)
local data = {}
for _, m in Shared.skpairs(MissionData["MissionDetails"]) do
if(m.Tier == MissionAlias) then
table.insert(data, m)
end
end
return data
end
--- Gets a list of missions with rewards for a given planet
-- @function p.getMissionsForPlanet
function p.getMissionsForPlanet(Planet)
local missions = {}
for _, m in pairs(MissionData["MissionDetails"]) do
if (m.Planet == Planet and m.Tier == 'Landscape') then
for i, n in ipairs(DropData["Missions"]) do
local mData = {Node = m.Node, Planet = m.Planet, Type = m.Type, IsDarkSector = m.IsDarkSector, Tileset = m.Tileset, Enemy = m.Enemy, MinLevel = m.MinLevel, MaxLevel = m.MaxLevel, Tier = m.Tier, Pic = m.Pic}
if (Planet == 'Earth') and (n.Type == 'Cetus Bounty' or n.Type == 'Cetus Bounty (Steel Path)' or n.Type == 'Ghoul Bounty') and (n.Ignore ~= true) then
mData.Type = n.Type; mData.Tier = n.Tier; mData.MinLevel = n.Name
table.insert(missions, mData)
elseif (Planet == 'Venus') and (n.Type == 'Orb Vallis Bounty' or n.Type == 'Orb Vallis Bounty (Steel Path)') and (n.Ignore ~= true) then
mData.Type = n.Type; mData.Tier = n.Tier; mData.MinLevel = n.Name
table.insert(missions, mData)
end
end
elseif (m.Planet == Planet and m.Tier ~= nil) then
table.insert(missions, m)
end
end
return missions
end
--- Returns the rewards for the A tier only for a mission
-- Handy for missions like Capture that have a single reward
-- Returns as rows for a table with two columns
-- See the existing Capture rewards section for an example
-- @function p.getSingleRotationRewards
function p.getSingleRotationRewards(frame)
local MissionType = frame.args ~= nil and frame.args[1]
local MissionCat = frame.args ~= nil and frame.args[2]
local result = ""
local theMission = p.getMission(MissionType, MissionCat)
assert(theMission ~= nil, 'p.getSingleRotationRewards(frame): Could not get mission of type "'..MissionType..'" and category "'..MissionCat..'"')
local data = getRewardsForMission(theMission)
if(data ~= nil and Shared.tableCount(data) > 0) then
local firstKey = nil
for k in pairs(data) do
if(firstKey == nil) then
firstKey = k
end
end
for i, drop in pairs(data[firstKey]) do
result = result.."\n|-\n| "..formatDropString(drop)
end
end
return result
end
--- Returns the rewards for a given mission/tier
-- Returns as rows for a table with six columns, two for each rotation
-- See existing Survival/Rewards/Normal_Mission for examples
-- if Tier==AllTier it will call a specific function to merge all tiers together in a single A,B,C table
-- @function p.getRewardTable
function p.getRewardTable(frame)
local MissionType = frame.args ~= nil and frame.args[1]
local MissionCat = frame.args ~= nil and frame.args[2]
local result = ""
if(MissionCat == "AllTier") then
result = p.getRewardTableAllTier(frame)
return result
end
local theMission = p.getMission(MissionType, MissionCat)
assert(theMission ~= nil, 'p.getRewardTable(frame): Could not get mission of type "'..MissionType..'" and category "'..MissionCat..'"')
local data = getRewardsForMission(theMission)
local RotA = data["A"]
local RotB = data["B"]
local RotC = data["C"]
--Goes through all three rotations to find which one has the most items
local ACount = Shared.tableCount(RotA)
local maxLen = ACount
local BCount = Shared.tableCount(RotB)
if(BCount > maxLen) then
maxLen = BCount
end
local CCount = Shared.tableCount(RotC)
if(CCount > maxLen) then
maxLen = CCount
end
--We need as many rows as the longest list has items
--So if any lists are shorter then after their last row the columns are just blank
for i=1, maxLen, 1 do
result = result.."\n|-"
if(RotA[i] ~= nil) then
result = result.."\n| align=\"right\" | "..formatDropString(RotA[i])
else
result = result.."\n| || "
end
if(RotB[i] ~= nil) then
result = result.."\n| align=\"right\" | "..formatDropString(RotB[i])
else
result = result.."\n| || "
end
if(RotC[i] ~= nil) then
result = result.."\n| align=\"right\" | "..formatDropString(RotC[i])
else
result = result.."\n| || "
end
end
return result
end
--- Gets a list of all the missions for a given MissionType and Tier
-- @function p.getMissionList
function p.getMissionList(frame)
local MissionType = frame.args ~= nil and frame.args[1]
local MissionTier = frame.args ~= nil and frame.args[2]
local result = ""
if(MissionTier == "AllTier") then
result = p.getMissionListAllTier(frame)
return result
end
local missionRecord = p.getMission(MissionType, MissionTier)
assert(missionRecord ~= nil, 'p.getMissionList(frame): Could not figure out mission type "'..MissionType..'" and mission tier "'..MissionTier..'"')
local missions = p.getMissionTable(p.getMValue(missionRecord, "ALIAS"))
for _, m in pairs(missions) do
result = result.."\n* "..m.Node..", [["..m.Planet.."]]"
end
return result
end
--- Gets a list of all the missions for a given MissionType and Tier
-- TODO: Rename this function as "p.getMissionList2" does not describe the functionality
-- @function p.getMissionList2
function p.getMissionList2(frame)
local MissionType = frame.args ~= nil and frame.args[1]
local MissionTier = frame.args ~= nil and frame.args[2]
local result = ""
if(MissionTier == "AllTier") then
result = p.getMissionListAllTier(frame)
return result
end
local missionRecord = p.getMission(MissionType, MissionTier)
assert(missionRecord ~= nil, 'p.getMissionList2(frame): Could not figure out mission type "'..MissionType..'" and mission tier "'..MissionTier..'"')
local missions = p.getMissionTable(p.getMValue(missionRecord, "ALIAS"))
for _, m in pairs(missions) do
result = result..m.Node..', '..m.Planet..[[\n
]]
end
return result
end
--- WIP get missions regardless of tier
-- TODO: Finish this function or remove it entirely if not used
-- @function p.getMissionAllTier
function p.getMissionAllTier(MissionType)
local a={}
for i, Miss in pairs(DropData["Missions"]) do
if(Miss.Type == MissionType) then
table.insert(a, Miss)
end
end
return a
end
--- WIP Gets a the reward table of all Mission for a given MissionType (all tiers)
-- TODO: Finish this function or remove it entirely if not used
-- @function p.getRewardTableAllTier
function p.getRewardTableAllTier(frame)
local MissionType = frame.args ~= nil and frame.args[1]
local theMissiont = p.getMissionAllTier(MissionType)
assert(theMissiont ~= nil, 'p.getRewardTableAllTier(frame): No mission found with type "'..MissionType..'"')
local result = ""
local RotA = {}
local RotB = {}
local RotC = {}
for i, theMission in pairs(theMissiont) do
local data = getRewardsForMission(theMission)
local RA = data["A"]
local RB = data["B"]
local RC = data["C"]
--for k,v in pairs(dd) do data[k] = v end
for k,v in pairs(RA) do table.insert(RotA, v) end
for k,v in pairs(RB) do table.insert(RotB, v) end
for k,v in pairs(RC) do table.insert(RotC, v) end
end
--Goes through all three rotations to find which one has the most items
local ACount = Shared.tableCount(RotA)
local maxLen = ACount
local BCount = Shared.tableCount(RotB)
if(BCount > maxLen) then
maxLen = BCount
end
local CCount = Shared.tableCount(RotC)
if(CCount > maxLen) then
maxLen = CCount
end
--We need as many rows as the longest list has items
--So if any lists are shorter then after their last row the columns are just blank
for i=1, maxLen, 1 do
result = result.."\n|-"
if(RotA[i] ~= nil) then
result = result.."\n| align=\"right\" | "..formatDropString(RotA[i])
else
result = result.."\n| || "
end
if(RotB[i] ~= nil) then
result = result.."\n| align=\"right\" | "..formatDropString(RotB[i])
else
result = result.."\n| || "
end
if(RotC[i] ~= nil) then
result = result.."\n| align=\"right\" | "..formatDropString(RotC[i])
else
result = result.."\n| || "
end
end
return result
end
--- WIP Gets a list of all Mission for a given MissionType (all tiers)
-- TODO: Finish this function or remove it entirely if not used
-- @function p.getMissionListAllTier
function p.getMissionListAllTier(frame)
local MissionType = frame.args ~= nil and frame.args[1]
local result = ""
local missionRecordt = p.getMissionAllTier(MissionType)
assert(missionRecordt ~= nil, 'p.getMissionListAllTier(frame): Could not figure out mission type "'..MissionType..'"')
for i, missionRecord in pairs(missionRecordt) do
local missions = p.getMissionTable(p.getMValue(missionRecord, "ALIAS"))
for _, m in pairs(missions) do
result = result.."\n* "..m.Node..", [["..m.Planet.."]]"
end
end
return result
end
--- Get a list of all missions that drop a given item
-- @function getDropMissions
local function getDropMissions(itemName)
local Drops = {}
--For each mission...
for i, theMission in pairs(DropData["Missions"]) do
--... if it has rewards...
if(theMission.Rewards ~= nil and theMission.Ignore ~= true) then
--... then for each rotation in the mission...
for key, dropTable in Shared.skpairs(theMission.Rewards) do
--... for each drop in the rotation...
for j, drop in pairs(dropTable) do
-- ... if the drop is the right item, add it to the list
if(drop[misNameCol] == itemName) then
table.insert(Drops, buildMissionDrop(theMission, key, drop))
end
end
end
end
end
return Drops
end
---
-- @function getDropSyndicates
local function getDropSyndicates(itemName)
local Drops = {}
for i, theSyndicate in pairs(DropData["Syndicates"]) do
if(theSyndicate.Offerings ~= nil and theSyndicate.Ignore ~= true) then
for i, Offering in pairs(theSyndicate.Offerings) do
if(Offering[synNameCol] == itemName) then
table.insert(Drops, buildSyndicateDrop(theSyndicate, Offering))
end
end
end
end
return Drops
end
--- Returns an EnemyDrop object for each enemy that drops a given mod
-- @function getDropEnemies
local function getDropEnemies(itemName)
local drops = {}
for i, Enemy in pairs(DropData["Enemies"]) do
if(Enemy.Mods ~= nil and Enemy.Ignore ~= true) then
for j, Mod in pairs(Enemy.Mods) do
if(Mod[modNameCol] == itemName) then
local drop = buildEnemyDrop(Enemy, Mod)
table.insert(drops, drop)
end
end
end
if(Enemy.Avionics ~= nil and Enemy.Ignore ~= true) then
for j, Avionic in pairs(Enemy.Avionics) do
if(Avionic[aviNameCol] == itemName) then
local drop = buildAvionicDrop(Enemy, Avionic)
table.insert(drops, drop)
end
end
end
end
return drops
end
--- Gets the table used on Void Relic/ByMission
-- Unlike getRewardTable, this is just the full table with all formatting
-- This is pretty ugly, but kinda have to do it this way
-- (Unless you have a better solution, in which case by all means go ahead and fix it)
-- (I'm not exactly a Lua expert or a UI expert)
-- TODO: Break up this function into smaller functions
-- @function p.getRelicTable
function p.getRelicTable(frame)
--Okay, so first up, need to know which planet this is for
local Planet = nil
if(frame ~= nil) then
Planet = frame.args ~= nil and frame.args[1] or frame
end
--Planet == nil is standing in for 'all planets', so adding option to explicitly call 'all'
if(Planet ~= nil and (Planet == "" or Planet == "All")) then
Planet = nil
end
--I have other functions to get the list of missions for all/planet
--So calling that here
local missions
if(Planet == nil) then
missions = {}
for i, m in pairs(DropData["Missions"]) do
if(m.Ignore ~= true) then
table.insert(missions, m)
end
end
else
missions = p.getMissionsForPlanet(Planet)
end
local tableRows = {}
local Relics = {["Lith"] = {}, ["Meso"] = {}, ["Neo"] = {}, ["Axi"] = {}}
--Now for the 'fun' part: Getting the list
for i, m in ipairs(missions) do
--For each mission, the first thing we're doing is setting up what it's called
--Or more accurately, what it appears as in the chart
local rowName = ""
local mAlias, theMission
if(Planet == nil) then
--When showing all, the format is "Mission Type (Tier Name)" with link to mission type
--For example, "[[Survival]] (Tier 1)" or "Spy (Lua)"
if (m.Type== "Bounty" or m.Type== "Ghoul Bounty" or m.Type== "Onslaught") then
rowName = p.linkType(m.Type).." ("..p.getMValue(m, "SHORTNAME")..")"
else
local mType = p.linkType(m.Type)
mType = string.gsub(mType, " %(Steel Path%)%]%]", "%]%] %(%[%[The Steel Path|Steel Path%]%]%)")
rowName = mType.." ("..p.getMValue(m, "NAME")..")"
end
theMission = m
else
local placeName = m.Node
--When showing a single planet, format is instead "Mission Name (Type)"
--For example, "Rusalka (Capture)"
--Mission type is still linked
--Dark Sector is also linked if appropriate
if (m.IsDarkSector == 1) then
rowName = placeName.." ([[Dark Sector|DS]] "..p.linkType(m.Type)..")"
else
local mType = p.linkType(m.Type)
mType = string.gsub(mType, "%[%[Cetus Bounty %(Steel Path%)%]%]", "%[%[The Steel Path|Steel Path%]%] %[%[Cetus Bounty|Bounty%]%]")
mType = string.gsub(mType, "%[%[Cetus Bounty%]%]", "%[%[Cetus Bounty|Bounty%]%]")
mType = string.gsub(mType, "%[%[Orb Vallis Bounty %(Steel Path%)%]%]", "%[%[The Steel Path|Steel Path%]%] %[%[Orb Vallis Bounty|Bounty%]%]")
mType = string.gsub(mType, "%[%[Orb Vallis Bounty%]%]", "%[%[Orb Vallis Bounty|Bounty%]%]")
local mLevel = ''
if (placeName == 'Plains of Eidolon' or placeName == 'Orb Vallis') then
mLevel = '<br />'..string.gsub(m.MinLevel, "<br />", " ")
end
rowName = placeName..' ('..mType..')'..mLevel
end
theMission = p.getMission(m.Tier, nil, m.Type)
assert(theMission ~= nil, 'p.getRelicTable(frame): Could not get mission of tier "'..m.Tier..'" and type "'..m.Type..'"')
end
local thisRow = nil
--This is where we get all the rewards for the mission
local drops = getRewardsForMission(theMission)
--Need to know if this is a single rotation
--Because if it is, just a checkmark instead of a letter
local isSingleRot = Shared.tableCount(drops) == 1
--For each mission, looping each rotation
for rot, dropTable in Shared.skpairs(drops) do
--And each drop for each rotation
for j, d in pairs(dropTable) do
--We only care if it's a relic
if(d.Type == "Relic") then
--Set up the row if we don't have it yet
--Mission will not be added to the grid unless it drops at least one relic
--Avoids adding a row for something like Assassination that never gives relics
if(thisRow == nil) then
thisRow = {}
end
--Example: "Lith A1"
local RelicText = d.IName
local RadiantRelic = ""
if (string.find(RelicText,"%(Radiant%)")~=nil) then
RadiantRelic = "*"
RelicText = string.gsub(RelicText,"%s%(Radiant%)","")
end
--Example: {"Lith", "A1"}
local RelicBits = String.split(RelicText, "%s")
--Example: "Lith"
local RTier = RelicBits[1]
--Example: "A1"
local RName = RelicBits[2]
--Make sure the relevant entry exists
if (thisRow[RelicText] == nil) then
thisRow[RelicText] = ""
end
--And then fill it in
if (isSingleRot) then
thisRow[RelicText] = "✔"..RadiantRelic
else
thisRow[RelicText] = thisRow[RelicText]..rot..RadiantRelic
end
--Adding drop rate info when hovering
--If the drop rate is under 1% we set it red
--Under 2%, orangered
local RelicTextColor = "inherit"
if (d.Chance < 1) then
RelicTextColor = "red"
elseif (d.Chance < 2) then
RelicTextColor = "orangered"
end
thisRow[RelicText] = "<span style=\"color:" .. RelicTextColor .. ";\" title=\"Drop rate : " .. d.Chance .. "%\">" .. thisRow[RelicText] .. "</span>"
--Also gotta add the Relic to our list if we don't have it yet
if(Relics[RTier][RName] == nil) then
Relics[RTier][RName] = RelicText
end
end
end
end
if ( thisRow ~= nil ) then
tableRows[rowName] = thisRow
end
end
local result = {}
local headerRow = {}
local headerFirst = true
--So this right here sets up the initial conditions of the table
--If you want to change the styling, you've gotta do it here
result = {'{| class="wikitable" '}
table.insert(result, 'style="width:100%; border=1px; text-align:center; font-size:11px;"\n|-')
--Slightly different text for all missions VS missions for a planet
if(Planet == nil) then
table.insert(result, '\n! rowspan="2" |Mission Type (Tier)')
else
table.insert(result, '\n! rowspan="2" |Node (Type)')
end
--Looping through each Relic tier
--Doing two things here:
--1. Setting up the header row with the list of relics
--2. Setting up the topmost row that has the name of each relic tier
for tier in Shared.relicLoop() do
local relicCount = Shared.tableCount(Relics[tier])
if(relicCount > 0) then
table.insert(result, ('\n! colspan="'..relicCount..'" |'..tier))
for rNum, trash in Shared.skpairs(Relics[tier]) do
if not headerFirst then
table.insert(headerRow, " || ")
end
headerFirst = false
table.insert(headerRow, (relicTooltipStart..tier..' '..rNum..relicTooltipCenter..'[['..tier..' '..rNum..'|'..rNum..']]'..relicTooltipEnd))
end
end
end
--Then add the second row to the list
local headerTemp = table.concat(headerRow)
table.insert(result, ("\n|-\n|"..headerTemp))
--And now, at long last, it's time to add all the good stuff
for mName, relicRow in Shared.skpairs(tableRows) do
table.insert(result, ("\n|-\n|"..mName))
for tier in Shared.relicLoop() do
for rNum, rName in Shared.skpairs(Relics[tier]) do
if(relicRow[rName] ~= nil) then
table.insert(result, ("||"..relicRow[rName]))
else
table.insert(result, "|| ")
end
end
end
end
--And the all-important coda
table.insert(result, "\n|}")
--And then ship it all back
return table.concat(result)
end
--- Function used for building Void Relic/DropLocation table
-- TODO: Break up this function into smaller functions
-- @function p.getRelicByLocation
function p.getRelicByLocation(frame)
local tier = frame.args ~= nil and frame.args[1] or frame
local tierPieces = String.split(tier, "%s")
--5/26/2018: You can now call on a single relic and get just the table
-- TODO: Use M:Table instead for table count/size
if(Shared.tableCount(tierPieces) == 2) then
tier = tierPieces[1]
local relic = tierPieces[2]
return p.getSingleRelicByLocation(tier, relic)
end
local relicData = {}
-- TODO: Refactor so there is at max 3 nested code blocks
--As with most of my functions, breaking this into two parts:
--First, gather all the data for each relic by going through missions
--We're looking through all drops for all missions to find relic drops
for i, theMission in pairs(DropData["Missions"]) do
if(theMission.Rewards ~= nil and theMission.Ignore ~= true) then
for rot, dropTable in Shared.skpairs(theMission.Rewards) do
for j, drop in pairs(dropTable) do
--When we find a relic drop, make sure it's for the right tier
if(drop[misTypeCol] == "Relic") then
--Example: {"Lith", "A1"}
local RelicBits = String.split(drop[misNameCol], "%s")
--Example: "Lith"
local RTier = RelicBits[1]
--Example: "A1"
local RName = RelicBits[2]
--Then if it is for the right tier, it needs to be added to our table of data
if(RTier == tier) then
--Create an entry for this relic if we don't have one yet
if(relicData[RName] == nil) then
relicData[RName] = { Drops = {}, Rewards = Void.getRelic(RTier, RName).Drops}
end
--Then add this drop to the relic's table
table.insert(relicData[RName].Drops, buildMissionDrop(theMission, rot, drop))
end
end
end
end
end
end
--Second, build the actual table being sent back
local result = {}
table.insert(result, [[
{| class="article-table" border="0" cellpadding="1" cellspacing="1" style="width: 100%;"
! Relic Name
! Drop locations]])
local rHeader = [[
{| cellpadding="2" cellspacing="0" class="sortable" style="width:100%;border:1px solid black; text-align:right;font-size:12px;"
!Type
!Category
!Rotation
!Chance]]
for RName, RTable in Shared.skpairs(relicData) do
local tierLink = "\n|-\n| ".."[["..tier.." "..RName.."]]"
table.insert(result, tierLink)
for i, reward in pairs(RTable.Rewards) do
local ItemName = Void.getItemName(reward.Item)
local PartName = Void.getPartName(reward.Part)
local itemLink = "\n* [["..ItemName.."|"..ItemName.." "..PartName.."]]"
table.insert(result, itemLink)
end
table.insert(result, "\n|\n")
table.insert(result, rHeader)
table.sort(RTable.Drops, function (d1, d2)
if(d1.MType == d2.MType) then
if(p.getMValue(d1.theMission, 'Name') == p.getMValue(d2.theMission, 'Name')) then
return d1.Rotation < d2.Rotation
else
return p.getMValue(d1.theMission, 'Name') < p.getMValue(d2.theMission, 'Name')
end
else
return d1.MType < d2.MType
end
end)
for i, d in pairs(RTable.Drops) do
local mType = p.linkType(d.MType)
mType = string.gsub(mType, " %(Steel Path%)%]%]", "%]%]<br />%(%[%[The Steel Path|Steel Path%]%]%)")
local mTypeLink = "\n|-\n|"..mType
table.insert(result, mTypeLink)
if (d.MType == "Bounty" or d.MType == "Ghoul Bounty" or d.MType == "Onslaught") then
local mNameLink = "||"..p.getMValue(d.theMission, 'ShortName')
table.insert(result, mNameLink)
else
local mNameLink = "||"..p.getMValue(d.theMission, 'Name')
table.insert(result, mNameLink)
end
local mRotC = "||"..d.Rotation.."||"..d.Chance.."%"
table.insert(result, mRotC)
end
table.insert(result, "\n|}")
end
table.insert(result, "\n|}")
-- TODO: Remove all the newlines in elements that is inserted into table.
-- Can just concat newlines at the end here.
return table.concat(result)
end
--- TODO: Break up this function into smaller functions
-- @function p.getSingleRelicByLocation
function p.getSingleRelicByLocation(tier, name)
local relicData = {Drops = {}, Rewards = Void.getRelic(tier, name).Drops}
local missionData = {}
local result = ""
--As with most of my functions, breaking this into two parts:
--First, gather all the data for each relic by going through missions
--We're looking through all drops for all missions to find relic drops
for i, theMission in pairs(DropData["Missions"]) do
if(theMission.Rewards ~= nil and theMission.Ignore ~= true) then
for rot, dropTable in Shared.skpairs(theMission.Rewards) do
for j, drop in pairs(dropTable) do
--When relic drop found, make sure it's for the right relic
if(drop[misTypeCol] == "Relic") then
--Example: {"Lith", "A1"}
local RelicBits = String.split(drop[misNameCol], "%s")
--Example: "Lith"
local RTier = RelicBits[1]
--Example: "A1"
local RName = RelicBits[2]
--Then if it is for the right tier, it needs to be added to our table of data
if(RTier == tier and RName == name) then
--Then add this drop to the relic's table
table.insert(relicData.Drops, buildMissionDrop(theMission, rot, drop))
end
end
end
end
end
end
--Second, build the actual table being sent back
local result = ''
result = "{| cellpadding=\"0\" cellspacing=\"0\" class=\"article-table sortable\" "
result = result.."style=\"width:100%;border:1px solid black;"
result = result.."text-align:left;font-size:12px;margin:12px 0 0 0;\""
result = result.."\n!style=\"color:#3a3a3a;\"|Mission "
result = result.."\n![[Mission_Rewards#Mission_Tier|<span style=\"color:#3a3a3a;\">Tier</span>]] "
result = result.."\n![[Mission_Rewards#Mission_Rotations|<span style=\"color:#3a3a3a;\">Rotations</span>]] "
result = result.."\n!style=\"color:#3a3a3a;\" data-sort-type=\"numeric\" | Chances "
table.sort(relicData.Drops, function (d1, d2)
if(d1.MType == d2.MType) then
if(p.getMValue(d1.theMission, 'Name') == p.getMValue(d2.theMission, 'Name')) then
return d1.Rotation < d2.Rotation
else
return p.getMValue(d1.theMission, 'Name') < p.getMValue(d2.theMission, 'Name')
end
else
return d1.MType < d2.MType
end
end)
local types = {}; local missions = {}
local rotations = {}; local chances = {}
for i, d in pairs(relicData.Drops) do
types[i] = d.MType --p.linkType(d.MType)
if (d.MType == "Onslaught") then
missions[i] = p.getMValue(d.theMission, 'Tier')
else
missions[i] = p.getMValue(d.theMission, 'Name')
end
rotations[i] = d.Rotation
chances[i] = d.Chance.."%"
end
local i = 1; while i <= table.getn(relicData.Drops) do
if types[i] == types[i+1] then
if missions[i] == missions[i+1] then
rotations[i+1] = rotations[i]..", "..rotations[i+1]
chances[i+1] = chances[i]..", "..chances[i+1]
types[i] = ''; missions[i] = '';
rotations[i] = ''; chances[i] = '';
end
end
local num = string.gsub(chances[i],"%%","")
local ChancesBits = String.split(num, ", ")
local highchance
if (table.getn(ChancesBits) <= 1) or (ChancesBits == nil) then
highchance = tonumber(num)
else
for j=1, (table.getn(ChancesBits) - 1) do
if tonumber(ChancesBits[j]) <= tonumber(ChancesBits[j+1]) then
highchance = tonumber(ChancesBits[j+1])
else
highchance = tonumber(ChancesBits[j])
end
end
end
if types[i] ~= '' then
local framepass={}
framepass["args"]={types[i],missions[i]}
local mlist= p.getMissionList2(framepass)
local mType = p.linkType(types[i])
mType = string.gsub(mType, " %(Steel Path%)%]%]", "%]%]<br />%(%[%[The Steel Path|Steel Path%]%]%)")
result = result.."\n|-\n|style=\"padding:10px;\"|"..mType
if(mlist == "") then
result = result.."\n|style=\"padding:10px;\"|"..missions[i]
else
result = result.."\n|style=\"padding:10px;\"|<span style=\"border-bottom: 1px dotted;\" class=\"basic-tooltip\" title=\""..mlist.."\">"..missions[i].."</span>"
end
result = result.."\n|style=\"padding:10px;\"|"..rotations[i]
result = result.."\n|style=\"padding:10px;\" data-sort-value=\""..highchance.."\"|"..chances[i]
end
i = i + 1
end
result = result.."\n|}"
return result
end
---
-- @function p.getItemByMissionTable
function p.getItemByMissionTable(frame)
local theDrop = frame.args ~= nil and frame.args[1] or frame
local Drops = getDropMissions(theDrop)
table.sort(Drops, function (d1, d2)
return d1.MType < d2.MType
end)
local rHeader
rHeader = "{| cellpadding=\"2\" cellspacing=\"0\" class=\"sortable\" "
rHeader = rHeader.."style=\"width:100%;border:1px solid black; "
rHeader = rHeader.."text-align:right;font-size:12px;\""
rHeader = rHeader.."\n!Type"
rHeader = rHeader.."\n!Category"
rHeader = rHeader.."\n!Rotation"
rHeader = rHeader.."\n!Chance"
local rTable = rHeader
for i, d in pairs(Drops) do
rTable = rTable.."\n|-\n|"..p.linkType(d.MType).."||"..p.getMValue(d.theMission, 'NAME')
rTable = rTable.."||"..d.Rotation.."||"..d.Chance.."%"
end
rTable = rTable.."\n|}"
return rTable
end
---
-- @function p.getItemByEnemyTable
function p.getItemByEnemyTable(frame)
local theDrop = frame.args ~= nil and frame.args[1] or frame
local Drops = getDropEnemies(theDrop)
table.sort(Drops, function (d1, d2)
return d1.EName < d2.EName
end)
local rHeader
rHeader = "{| cellpadding=\"2\" cellspacing=\"0\" class=\"sortable\" "
rHeader = rHeader.."style=\"width:100%;border:1px solid black; "
rHeader = rHeader.."text-align:right;font-size:12px;\""
rHeader = rHeader.."\n!Enemy"
rHeader = rHeader.."\n!Chance"
local rTable = rHeader
for i, d in pairs(Drops) do
rTable = rTable.."\n|-\n|"..linkEnemy(d.EName)
rTable = rTable.."||"..d.Chance.."%"
end
rTable = rTable.."\n|}"
return rTable
end
--- Returns the list of drop locations used by the ModBox
-- TODO: Break up this function into smaller functions
-- @function p.getItemDropList
function p.getItemDropList(frame)
local theDrop = frame.args ~= nil and frame.args[1] or frame
--little looparound for Scorch... add other exceptions after if needed
if(theDrop == "Scorch (Mod)") then theDrop = "Scorch" end
--First, get all the missions that drop this
local Drops = getDropMissions(theDrop)
table.sort(Drops, function (d1, d2)
return d1.MType < d2.MType
end)
local checked = {}
local result = ""
local space = " "
if(Shared.tableCount(Drops) > 0) then
local finalTable = {}
result = "'''Missions:'''" -- Voided to add more mods (example Syndicates)
--Going through and grouping the drops by Type
for i, Drop in pairs(Drops) do
local Alias = p.getMValue(Drop.theMission, 'ALIAS')
local MissionName = p.getMValue(Drop.theMission, 'SHORTNAME')
--This check prevents duplicating rows if the same item appears in multiple rotations of the same mission
if(checked[Alias] == nil) then
checked[Alias] = { Drop }
if(finalTable[Drop.MType] == nil) then
finalTable[Drop.MType] = {}
end
table.insert(finalTable[Drop.MType], Alias)
else
table.insert(checked[Alias], Drop)
end
end
table.sort(finalTable, function (r1, r2)
return r1 < r2
end)
--This is where all the items are put into the list
--Each mission type gets its own row, with the relevant tiers in parentheses
--For example "Spy (T1, T2, Lua)" or "Survival (DS1, DS2)"
for i, item in pairs(finalTable) do
table.sort(item)
local mType = p.linkType(i)
mType = string.gsub(mType, " %(Steel Path%)%]%]", "%]%] %(%[%[The Steel Path|Steel Path%]%]%)")
result = result.."<br/>"..mType
local tierList = ""
for j, alias in pairs(item) do
local drop1 = checked[alias][1]
local shortName = p.getMValue(drop1.theMission, 'SHORTNAME')
if shortName ~= "" then
local ttip = p.getMValue(drop1.theMission, 'NAME', true)
for k, thisDrop in pairs(checked[alias]) do
ttip = ttip..'\\nRotation '..thisDrop.Rotation
if (thisDrop.Chance ~= nil) then
ttip = ttip..': '..thisDrop.Chance.."%"
end
end
if j > 1 then tierList = tierList..', ' end
tierList = tierList..'<span style="border-bottom: 1px dotted;" class="basic-tooltip" title="'..ttip..'">'..shortName..'</span>'
end
end
if tierList ~= "" then result = result.." ("..tierList..")" end
end
end
local Drops = getDropSyndicates(theDrop)
if(Shared.tableCount(Drops) > 0) then
table.sort(Drops, function(d1, d2)
return d1.SName < d2.SName
end)
if(string.len(result) > 0) then result = result.."<br/>" end
result = result.."'''Syndicates:'''"
for i, Drop in pairs(Drops) do
result = result.."<br/>"..linkSyndicate(Drop.SName)..' '..Icon._Item("Standing","","x20")..' '..Shared.formatnum(Drop.Cost)
end
end
--Then all the enemies are added to the list if there are any
Drops = getDropEnemies(theDrop)
if(Shared.tableCount(Drops) > 0) then
table.sort(Drops, function (d1, d2)
return d1.EName < d2.EName
end)
if(string.len(result) > 0) then result = result.."<br/>" end
result = result.."'''Enemies:'''"
for i, Drop in pairs(Drops) do
result = result.."<br/>"..linkEnemy(Drop.EName)..space
if (Drop.Type == "Avionic" and Drop.House ~= nil) then
result = result.."("..Drop.House..")"..space
end
result = result..Drop.Chance.."%"
end
end
return result
end
---
-- @function p.getItemByEnemyCount
function p.getItemByEnemyCount(frame)
local theDrop = frame.args ~= nil and frame.args[1] or frame
local Drops = getDropEnemies(theDrop)
return Shared.tableCount(Drops)
end
---
-- @function p.getItemByMissionCount
function p.getItemByMissionCount(frame)
local theDrop = frame.args ~= nil and frame.args[1] or frame
local Drops = getDropMissions(theDrop)
return Shared.tableCount(Drops)
end
---
-- @function p.getFullEnemyList
function p.getFullEnemyList(frame)
local result = "All Enemies: "
local ENames = {}
for i, Enemy in pairs(DropData["Enemies"]) do
if(Enemy.Name ~= nil) then
table.insert(ENames, Enemy.Name)
end
end
table.sort(ENames, function(n1, n2) return n1 < n2 end)
for i, Name in pairs(ENames) do
result = result.."\n* "..linkEnemy(Name)
end
return result
end
---
-- @function p.getEnemyModDrops
function p.getEnemyModDrops(frame)
local EnemyName = frame.args ~= nil and frame.args[1] or frame
local Drops = getAllModDrops(EnemyName)
if(Shared.tableCount(Drops) == 0) then
return;
end
enemyTableSort(Drops)
local space = " "
local result = ""
for i, Drop in pairs(Drops) do
if i > 1 then result = result.."<br/>" end
if(Drop.IName == "Endo") then
if(Drop.Count<10) then
result = result.."[[Endo]]"
else
result = result..Drop.Count.." [[Endo]]"
end
elseif(Drop.Type == "Avionic") then
result = result..getAvionicLink(Drop.IName, Drop.House)
else
result = result..getModLink(Drop.IName)
end
result = result..space..Drop.Chance.."%"
end
return result
end
-- TODO: Remove this function or move it to /validate subpage of /data
function p.TestFrame(frame)
local txt = "VALUES:\n\n"
for key, val in Shared.skpairs(p) do
if(val ~= nil) then
if(type(val) == "string" or type(val) == "number") then
txt = txt..'\n* '..key..' = '..val
else
txt = txt..'\n* '..key..' is a '..type(val)
end
else
txt = txt..'\n* '..key..' is nil'
end
end
return txt
end
return p