| Строка 1: |
Строка 1: |
| local prototypes = mw.loadData("Module:Chemistry Lookup/data")
| |
|
| |
| local p = {} | | local p = {} |
| p.chem = prototypes.chem
| | local mw = mw |
| p.react = prototypes.react
| | local html = mw.html |
| p.groupDirection = prototypes.groupDirection
| |
|
| |
|
| function p.readscalar(frame) | | local function getArgs(frame) |
| return mw.text.nowiki(p.chem[frame.args[1]][frame.args[2]])
| | if type(frame) == "table" and frame.args then return frame.args end |
| | return mw.getCurrentFrame():getParent().args or {} |
| end | | end |
|
| |
|
| function p.readscalarreact(frame) | | local function splitLines(s) |
| if p.react[frame.args[1]][frame.args[2]] ~= nil then
| | local t = {} |
| return mw.text.nowiki(p.react[frame.args[1]][frame.args[2]])
| | if not s then return t end |
| else
| | for line in mw.text.gsplit(s, "\n") do |
| return ""
| | line = mw.text.trim(line) |
| end
| | if line ~= "" then table.insert(t, line) end |
| | end |
| | return t |
| end | | end |
|
| |
|
| function p.getcolor(frame) | | local function parseLineToItem(l) |
| return mw.text.nowiki(p.chem[frame.args[1]].color:sub(1, 7))
| | local name, qty = mw.ustring.match(l, "^(.*)%s*%[%s*([%d,%.]+)%s*%]%s*$") |
| | if not name then name = l; qty = "1" end |
| | return { name = mw.text.trim(name), qty = qty or "1" } |
| end | | end |
|
| |
|
| function p.gettextcolor(frame) | | local function parseRecipeString(recipeStr) |
| local basecol = p.chem[frame.args[1]].color
| | if not recipeStr or recipeStr == "" then return {} end |
| local red = tonumber(basecol:sub(2, 3), 16)
| | local lines = splitLines(recipeStr) |
| local grn = tonumber(basecol:sub(4, 5), 16)
| | local steps = {} |
| local blu = tonumber(basecol:sub(6, 7), 16)
| | local currentInputs = {} |
| local luminance = math.sqrt(0.241*red*red + 0.691*grn*grn + 0.068*blu*blu)
| | local i = 1 |
| if luminance > 100 then
| | while i <= #lines do |
| return mw.text.nowiki("#000")
| | local line = lines[i] |
| else
| | local lower = mw.ustring.lower(line) |
| return mw.text.nowiki("#FFF")
| | if lower:find("смеш") then |
| end
| | if #currentInputs > 0 then |
| | local outputs = {} |
| | i = i + 1 |
| | while i <= #lines do |
| | local nextLine = lines[i] |
| | local nextLower = mw.ustring.lower(nextLine) |
| | if nextLower:find("смеш") then break end |
| | table.insert(outputs, parseLineToItem(nextLine)) |
| | i = i + 1 |
| | end |
| | table.insert(steps, { |
| | inputs = currentInputs, |
| | outputs = outputs, |
| | action = mw.text.trim(line) |
| | }) |
| | currentInputs = {} |
| | else |
| | i = i + 1 |
| | end |
| | else |
| | table.insert(currentInputs, parseLineToItem(line)) |
| | i = i + 1 |
| | end |
| | end |
| | if #currentInputs > 0 then |
| | table.insert(steps, { inputs = currentInputs, outputs = {}, action = "" }) |
| | end |
| | return steps |
| end | | end |
|
| |
|
| function p.hasrecipe(frame)
| | local FILE_PATTERN = "(%[%[File:[^]]+%]%])" |
| return p.chem[frame.args[1]]["recipes"][1] ~= nil
| |
| end
| |
|
| |
|
| function p.buildboxes(frame) | | local function buildRecipeStepHtml(rec) |
| local out = ""
| | if not rec or (#rec.inputs == 0 and #rec.outputs == 0) then return nil end |
| local group = frame.args[1]
| |
| for k in pairs(p.chem) do
| |
| if p.chem[k].group == group then
| |
| out = out .. frame:expandTemplate{ title = "Chembox", args = { prototype = k }}
| |
| elseif group == nil then
| |
| out = out .. frame:expandTemplate{ title = "Chembox", args = { prototype = k }}
| |
| end
| |
| end
| |
| return out
| |
| end | |
|
| |
|
| function p.buildreactboxes(frame)
| | local inner = html.create("div"):addClass("chem-recipe") |
| local out = ""
| |
| for k in pairs(p.react) do
| |
| if tablelength(p.react[k].effects) ~= 0 then
| |
| out = out .. frame:expandTemplate{ title = "Reactionbox", args = { reaction = k }}
| |
| end
| |
| end
| |
| return out
| |
| end
| |
|
| |
|
| function p.buildrecipes(frame)
| | local inputsDiv = html.create("div"):addClass("recipe-inputs") |
| local chem = frame.args[1]
| | for _, it in ipairs(rec.inputs) do |
| local out = ""
| | local item = inputsDiv:tag("div"):addClass("recipe-item") |
| for id, recipe in pairs(p.chem[chem].recipes) do
| | item:wikitext('[[File:Beaker.png|class=chem-beaker]] ' .. it.name .. ' [' .. it.qty .. ']') |
| out = out .. p.buildreaction(frame, recipe)
| | end |
| end
| | inner:node(inputsDiv) |
| return out
| |
| end
| |
|
| |
|
| function p.buildreactionext(frame)
| | if rec.action and rec.action ~= "" then |
| local react = frame.args[1]
| | local actionDiv = inner:tag("div"):addClass("recipe-action") |
| return p.buildreaction(frame, react)
| | local content = actionDiv:tag("div"):addClass("recipe-action-content") |
| end
| |
|
| |
|
| function p.buildreaction(frame, react)
| | local sprite = '[[File:Beaker.png|class=chem-beaker]]' |
| local data = p.react[react]
| | local actionText = rec.action |
| local dest = "Chemistry"
| |
| local args = {}
| |
| local i = 0
| |
| args["prototype"] = frame.args[1]
| |
| for k,v in pairs(data.reactants) do
| |
| i = i + 1
| |
| local dest = "Chemistry"
| |
| if (p.groupDirection[p.chem[k].group] ~= nil) then
| |
| dest = p.groupDirection[p.chem[k].group]
| |
| end
| |
| args["component-" .. i] = frame:expandTemplate{ title = "Chem Recipe Component", args = { reagent = k, amount = v.amount, dest = dest }}
| |
| end
| |
| i = 0
| |
| for k,v in pairs(data.products) do
| |
| i = i + 1
| |
| local dest = "Chemistry"
| |
| if (p.groupDirection[p.chem[k].group] ~= nil) then
| |
| dest = p.groupDirection[p.chem[k].group]
| |
| end
| |
| args["result-" .. i] = frame:expandTemplate{ title = "Chem Recipe Component", args = { reagent = k, amount = v, dest = dest }}
| |
| end
| |
|
| |
| if data.effects ~= nil then
| |
| args.effects = p.geneffectlist(data.effects, frame, 1)
| |
| end
| |
|
| |
|
| return frame:expandTemplate{ title = "Chem Box Recipe", args = args}
| | local customSprite = mw.ustring.match(actionText, FILE_PATTERN) |
| end | | if customSprite then |
| | sprite = customSprite |
| | actionText = mw.text.trim(mw.ustring.gsub(actionText, FILE_PATTERN, "")) |
| | end |
|
| |
|
| function p.checksatiatesthirst(frame)
| | content:tag("div"):addClass("action-sprite"):wikitext(sprite) |
| local chem = frame.args[1]
| | content:tag("div"):addClass("action-text"):wikitext(actionText) |
| local met = p.chem[chem].metabolisms
| | end |
| if met == nil then
| |
| return ""
| |
| end
| |
| for k, v in pairs(met) do
| |
| for l, w in pairs(v.effects) do
| |
| if w.id == "SatiateThirst" then
| |
| return "1"
| |
| end
| |
| end
| |
| end
| |
| return ""
| |
| end | |
|
| |
|
| function p.checksatiateshunger(frame)
| | local outputsDiv = html.create("div"):addClass("recipe-outputs") |
| local chem = frame.args[1]
| | for _, it in ipairs(rec.outputs) do |
| local met = p.chem[chem].metabolisms
| | local item = outputsDiv:tag("div"):addClass("recipe-item") |
| if met == nil then
| | item:wikitext('[[File:Beaker.png|class=chem-beaker]] ' .. it.name .. ' [' .. it.qty .. ']') |
| return ""
| | end |
| end
| | inner:node(outputsDiv) |
| for k, v in pairs(met) do
| |
| for l, w in pairs(v.effects) do
| |
| if w.id == "SatiateHunger" then
| |
| return "1"
| |
| end
| |
| end
| |
| end
| |
| return ""
| |
| end
| |
|
| |
|
| function p.haseffects(frame)
| | return inner |
| local chem = frame.args[1]
| |
| local met = p.chem[chem].metabolisms
| |
| if met == nil then
| |
| return ""
| |
| end
| |
| for k, v in pairs(met) do
| |
| for l, w in pairs(v.effects) do
| |
| if w.id ~= "SatiateHunger" and w.id ~= "SatiateThirst" then
| |
| return "1"
| |
| end
| |
| end
| |
| end
| |
| return ""
| |
| end | | end |
|
| |
|
| function p.geneffects(frame, chem) | | local function buildEffectsHtml(effects) |
| if chem == nil then
| | if not effects or effects == "" or effects == "Нет" then return nil end |
| chem = frame.args[1]
| | local container = html.create("div"):addClass("chem-effects-block") |
| end
| | local heading = html.create("div"):addClass("chem-heading"):attr("data-kind", "effects") |
| local met = p.chem[chem].metabolisms
| | local hcontent = heading:tag("div"):addClass("chem-heading-content") |
| if met == nil then
| | hcontent:tag("span"):addClass("heading-text"):wikitext("Эффекты") |
| return ""
| | hcontent:tag("span"):addClass("collapse-btn"):wikitext("развернуть") |
| end
| | container:node(heading) |
| local out = ""
| |
| for k, v in pairs(met) do
| |
| out = out .. "<b>" .. k .. "</b> (" .. v.rate .. " единиц в секунду)\n" .. p.geneffectlist(v.effects, frame, v.rate)
| |
| end
| |
| return out
| |
| end
| |
|
| |
|
| function p.geneffectlist(effects, frame, rate)
| | local collapsible = html.create("div"):addClass("collapsible collapsed"):attr("data-kind", "effects") |
| local out = ""
| | local inner = html.create("div"):addClass("chem-effects") |
| for l, w in pairs(effects) do
| | for effect in mw.text.gsplit(effects, "[;\n]") do |
| -- Popup Message is ignored on purpose
| | effect = mw.text.trim(effect) |
| if w.id == "HealthChange" then
| | if effect ~= "" then |
| out = out .. ":" .. p.genhealthchange(w, rate, frame) .. "\n"
| | inner:tag("div"):addClass("chem-effect-line"):wikitext(effect) |
| elseif w.id == "AdjustReagent" then
| | end |
| out = out .. ":" .. p.genadjustreagent(w, rate, frame) .. "\n"
| | end |
| elseif w.id == "FlammableReaction" then
| | collapsible:node(inner) |
| out = out .. ":" .. p.genflammablereaction(w, frame) .. "\n"
| | container:node(collapsible) |
| elseif w.id == "AdjustTemperature" then
| | return container |
| out = out .. ":" .. p.genadjusttemperature(w, frame) .. "\n"
| |
| elseif w.id == "GenericStatusEffect" then
| |
| out = out .. ":" .. p.gengenericstatuseffect(w, frame) .. "\n"
| |
| elseif w.id == "ExplosionReactionEffect" then
| |
| out = out .. ":" .. p.genexplosionreactioneffect(w, frame) .. "\n"
| |
| elseif w.id == "FoamAreaReactionEffect" then
| |
| out = out .. ":" .. p.genfoamareareactioneffect(w, frame) .. "\n"
| |
| elseif w.id == "SmokeAreaReactionEffect" then
| |
| out = out .. ":" .. p.gensmokeareareactioneffect(w, frame) .. "\n"
| |
| elseif w.id == "ModifyBleedAmount" then
| |
| out = out .. ":" .. p.genmodifybleedamount(w, frame) .. "\n"
| |
| end
| |
| end
| |
| return out
| |
| end | | end |
|
| |
|
| function p.gensmokeareareactioneffect(r, frame) | | function p.card(frame) |
| if r.conditions ~= nil then
| | local args = getArgs(frame) |
| conds = p.genconds(r.conditions, frame)
| | local name = args.name or "—" |
| end
| | local color = args.color or "#8cf" |
| return frame:expandTemplate{ title = "SmokeAreaReactionEffect", args = { when = conds, prob = r.probability }}
| | local border = args.border or "#444" |
| end
| | local desc = args.desc or "" |
|
| |
|
| function p.genfoamareareactioneffect(r, frame)
| | local variants = {} |
| if r.conditions ~= nil then
| | local i = 1 |
| conds = p.genconds(r.conditions, frame)
| | while true do |
| end
| | local key = i == 1 and "recipe" or ("recipe" .. i) |
| return frame:expandTemplate{ title = "FoamAreaReactionEffect", args = { when = conds, prob = r.probability }}
| | local recipeStr = args[key] |
| end | | if not recipeStr then break end |
| | local steps = parseRecipeString(recipeStr) |
| | if #steps > 0 then |
| | table.insert(variants, {id = i, steps = steps}) |
| | end |
| | i = i + 1 |
| | end |
|
| |
|
| function p.genexplosionreactioneffect(r, frame)
| | local container = html.create("div"):addClass("chem-card") |
| if r.conditions ~= nil then
| | container:attr("style", "border-color:" .. border .. "; --card-accent:" .. color) |
| conds = p.genconds(r.conditions, frame)
| | container:tag("div"):addClass("chem-name-header"):wikitext(name) |
| end
| |
| return frame:expandTemplate{ title = "ExplosionReactionEffect", args = { when = conds, prob = r.probability }}
| |
| end
| |
|
| |
|
| function p.gengenericstatuseffect(r, frame)
| | if #variants > 0 then |
| if r.conditions ~= nil then
| | local recipeBlock = html.create("div"):addClass("chem-recipe-block") |
| conds = p.genconds(r.conditions, frame)
| | local heading = html.create("div"):addClass("chem-heading"):attr("data-kind", "recipe") |
| end
| | local hcontent = heading:tag("div"):addClass("chem-heading-content") |
| return frame:expandTemplate{ title = "GenericStatusEffect", args = { key = r.Key, type = r.Type, time = r.Time, temperature = r.Temperature, ammount = r.Ammount, deleteReagent = r.DeleteReagent , refresh = r.Refresh, when = conds, prob = r.probability }}
| | hcontent:tag("span"):addClass("heading-text"):wikitext("Рецепты") |
| end
| | hcontent:tag("span"):addClass("collapse-btn"):wikitext("развернуть") |
| | recipeBlock:node(heading) |
|
| |
|
| function p.genadjusttemperature(r, frame)
| | local collapsible = html.create("div"):addClass("collapsible collapsed"):attr("data-kind", "recipe") |
| if r.conditions ~= nil then
| | local stepsContainer = html.create("div"):addClass("chem-recipe-steps") |
| conds = p.genconds(r.conditions, frame)
| |
| end
| |
| return frame:expandTemplate{ title = "AdjustTemperature", args = { amount = r.Amount, when = conds, prob = r.probability }}
| |
| end
| |
|
| |
|
| function p.genflammablereaction(r, frame)
| | for vidx, variant in ipairs(variants) do |
| if r.conditions ~= nil then
| | if #variants > 1 then |
| conds = p.genconds(r.conditions, frame)
| | local varHeader = stepsContainer:tag("div"):addClass("recipe-variant-header") |
| end
| | varHeader:wikitext("Вариант " .. vidx) |
| return frame:expandTemplate{ title = "FlammableReaction", args = { multiplier = r.Multiplier, when = conds, prob = r.probability }}
| | end |
| end | |
|
| |
|
| function p.genflammablereaction(r, frame)
| | for _, rec in ipairs(variant.steps) do |
| if r.conditions ~= nil then
| | local step = buildRecipeStepHtml(rec) |
| conds = p.genconds(r.conditions, frame)
| | if step then stepsContainer:node(step) end |
| end
| | end |
| return frame:expandTemplate{ title = "FlammableReaction", args = { multiplier = r.Multiplier, when = conds, prob = r.probability }}
| | end |
| end | |
|
| |
|
| function p.genadjustreagent(r, rate, frame)
| | collapsible:node(stepsContainer) |
| if r.conditions ~= nil then
| | recipeBlock:node(collapsible) |
| conds = p.genconds(r.conditions, frame)
| | container:node(recipeBlock) |
| end
| | end |
| return frame:expandTemplate{ title = "AdjustReagent", args = { amount = r.Amount, reagent = r.Reagent, when = conds, prob = r.probability }}
| |
| end | |
|
| |
|
| function p.genmodifybleedamount(r, frame)
| | local effectsBlock = buildEffectsHtml(args.effects) |
| if r.conditions ~= nil then
| | if effectsBlock then container:node(effectsBlock) end |
| conds = p.genconds(r.conditions, frame)
| |
| end
| |
| return frame:expandTemplate{ title = "ModifyBleedAmount", args = { amount = r.Amount, when = conds, prob = r.probability }}
| |
| end | |
|
| |
|
| function p.genhealthchange(h, rate, frame)
| | if desc ~= "" then |
| local healst = {}
| | container:tag("div"):addClass("chem-desc"):wikitext(desc) |
| local dealst = {}
| |
| local r = 1.0 / rate
| |
| if h.damage.types ~= nil then
| |
| for k, v in pairs(h.damage.types) do
| |
| if v < 0 then
| |
| healst[k] = v * r
| |
| else
| |
| dealst[k] = v * r
| |
| end
| |
| end
| |
| end
| |
|
| |
| if h.damage.groups ~= nil then
| |
| for k, v in pairs(h.damage.groups) do
| |
| if v < 0 then
| |
| healst[k] = v * r
| |
| else
| |
| dealst[k] = v * r
| |
| end
| |
| end
| |
| end
| |
|
| |
| local heals = hchangelist(healst, frame)
| |
| local deals = hchangelist(dealst, frame)
| |
| local conds = nil
| |
| if h.conditions ~= nil then
| |
| conds = p.genconds(h.conditions, frame)
| |
| end
| |
| return frame:expandTemplate{ title = "HealthChange", args = { heals = heals, deals = deals, when = conds, prob = h.probability }}
| |
| end
| |
| | |
| function hchangelist(l, frame)
| |
| out = ""
| |
| local len = tablelength(l)
| |
| local i = 0
| |
| for k, v in pairs(l) do
| |
| i = i + 1
| |
| if len == i and i ~= 1 then
| |
| out = out .. ", and "
| |
| elseif i ~= 1 then
| |
| out = out .. ", "
| |
| end
| |
| out = out .. hchange(k, v, frame)
| |
| end
| |
| return out
| |
| end
| |
| | |
| -- So we can make it fancy later
| |
| function hchange(ty, amnt, frame)
| |
| return frame:expandTemplate{ title = "HealthModifier", args = { adj = amnt, kind = ty } }
| |
| end
| |
| | |
| function p.genconds(conds, frame)
| |
| out = ""
| |
| local len = tablelength(conds)
| |
| local i = 0
| |
| for k, v in pairs(conds) do
| |
| i = i + 1
| |
| if len == i and i ~= 1 then
| |
| out = out .. ", and "
| |
| elseif i ~= 1 then
| |
| out = out .. ", "
| |
| end
| |
| out = out .. p.gencond(v, frame)
| |
| end
| |
| return out
| |
| end
| |
| | |
| function p.gencond(c, frame)
| |
| if c.id == "TotalDamage" then
| |
| return frame:expandTemplate{ title = "TotalDamage", args = { min = c.Min, max = c.Max } }
| |
| elseif c.id == "ReagentThreshold" then
| |
| return frame:expandTemplate{ title = "ReagentThreshold", args = { min = c.Min, max = c.Max, reagent = c.Reagent } }
| |
| elseif c.id == "OrganType" then
| |
| return frame:expandTemplate{ title = "OrganType", args = { shouldhave = c.ShouldHave, type = c.Type } }
| |
| elseif c.id == "Temperature" then
| |
| return frame:expandTemplate{ title = "Temperature", args = { min = c.Min, max = c.Max } }
| |
| end
| |
| return ""
| |
| end
| |
| | |
| function tablelength(T)
| |
| local count = 0
| |
| for _ in pairs(T) do count = count + 1 end
| |
| return count
| |
| end
| |
| | |
| function has_value(tab, val)
| |
| for index, value in ipairs(tab) do
| |
| if value[1] == val then
| |
| return true
| |
| end
| |
| end | | end |
|
| |
|
| return false | | return tostring(container) |
| end
| |
| | |
| function strsplit(inputstr, seperator)
| |
| if seperator == nil then
| |
| seperator = ","
| |
| end
| |
| local t={}
| |
| for str in string.gmatch(inputstr, "([^"..seperator.."]+)") do
| |
| table.insert(t, str)
| |
| end
| |
| return t
| |
| end | | end |
|
| |
|
| |
|
| return p | | return p |