|
|
Строка 1: |
Строка 1: |
| local prototypes = mw.loadData("Module:Chemistry Lookup/data")
| |
|
| |
| local p = {} | | local p = {} |
| p.chem = prototypes.chem or {}
| | local JsonPageLoader = require('Module:JsonPageLoader') |
| p.react = prototypes.react or {}
| |
| p.groupDirection = prototypes.groupDirection or {}
| |
|
| |
|
| -- ===== Хелперы ===== | | -- Загружаем данные (json с рецептами) |
| local function tablelength(T)
| | local data = JsonPageLoader.load('react_prototypes.json') |
| local count = 0
| |
| for _ in pairs(T or {}) do count = count + 1 end
| |
| return count
| |
| end
| |
|
| |
|
| local function hchangelist(l, frame) | | -- Функция: превращает products/ reactants в массив |
| local out = "" | | local function normalizeDict(dict) |
| local len = tablelength(l) | | if type(dict) ~= "table" then return {} end |
| local i = 0
| | local arr = {} |
| for k, v in pairs(l) do | | for id, val in pairs(dict) do |
| i = i + 1
| | if type(val) == "table" then |
| if len == i and i ~= 1 then | | table.insert(arr, { id = id, amount = val.amount or 1 }) |
| out = out .. ", and " | | else |
| elseif i ~= 1 then | | -- если значение просто число (например Bruizine: 2) |
| out = out .. ", " | | table.insert(arr, { id = id, amount = val }) |
| end | | end |
| out = out .. frame:expandTemplate{ title = "HealthModifier", args = { adj = v, kind = k } }
| |
| end | | end |
| return out | | return arr |
| end
| |
| | |
| function p.readscalar(frame)
| |
| local a, b = frame.args[1], frame.args[2]
| |
| if not (a and b) or not p.chem[a] then return "" end
| |
| local v = p.chem[a][b]
| |
| if v == nil then return "" end
| |
| return mw.text.nowiki(tostring(v))
| |
| end | | end |
|
| |
|
| function p.readscalarreact(frame)
| | -- Функция: нормализует рецепт |
| local a, b = frame.args[1], frame.args[2]
| | local function normalizeRecipe(id, recipe) |
| if not (a and b) or not p.react[a] then return "" end
| | -- гарантируем, что у рецепта есть id |
| local v = p.react[a][b]
| | if not recipe.id then |
| if v == nil then return "" end
| | recipe.id = id |
| return mw.text.nowiki(tostring(v))
| |
| end
| |
| | |
| function p.getcolor(frame) | |
| local a = frame.args[1] | |
| if not a or not p.chem[a] or not p.chem[a].color then return "" end
| |
| return mw.text.nowiki(p.chem[a].color:sub(1, 7))
| |
| end
| |
| | |
| function p.gettextcolor(frame)
| |
| local a = frame.args[1]
| |
| if not a or not p.chem[a] or not p.chem[a].color then return mw.text.nowiki("#000") end | |
| local basecol = p.chem[a].color
| |
| local red = tonumber(basecol:sub(2, 3), 16) or 0
| |
| local grn = tonumber(basecol:sub(4, 5), 16) or 0
| |
| local blu = tonumber(basecol:sub(6, 7), 16) or 0
| |
| local luminance = math.sqrt(0.241*red*red + 0.691*grn*grn + 0.068*blu*blu)
| |
| if luminance > 100 then
| |
| return mw.text.nowiki("#000")
| |
| else
| |
| return mw.text.nowiki("#FFF")
| |
| end | | end |
| end
| |
|
| |
|
| function p.hasrecipe(frame)
| | -- нормализуем продукты и реагенты |
| local chem = frame.args[1] | | recipe.products = normalizeDict(recipe.products) |
| if not chem or not p.chem[chem] then return "" end | | recipe.reactants = normalizeDict(recipe.reactants) |
| return (p.chem[chem].recipes and p.chem[chem].recipes[1]) and "1" or ""
| |
| end
| |
|
| |
|
| function p.buildboxes(frame)
| | return recipe |
| local out = ""
| |
| local group = frame.args[1]
| |
| for k, v in pairs(p.chem) do
| |
| if type(v) == "table" then
| |
| if (group == nil) or (v.group == group) then
| |
| out = out .. frame:expandTemplate{ title = "Chembox", args = { prototype = k }}
| |
| end
| |
| end
| |
| end
| |
| return out | |
| end | | end |
|
| |
|
| | -- Основной билдер |
| function p.buildreactboxes(frame) | | function p.buildreactboxes(frame) |
| local out = "" | | local out = {} |
| for k, v in pairs(p.react) do
| |
| if type(v) == "table" and v.effects and tablelength(v.effects) ~= 0 then
| |
| out = out .. frame:expandTemplate{ title = "Reactionbox", args = { reaction = k }}
| |
| end
| |
| end
| |
| return out
| |
| end
| |
|
| |
|
| function p.buildrecipes(frame)
| | for id, recipe in pairs(data) do |
| local chem = frame.args[1]
| | if recipe.type == "reaction" then |
| if not chem or not p.chem[chem] then return "" end
| | local r = normalizeRecipe(id, recipe) |
| local out = ""
| |
| for _, recipe in pairs(p.chem[chem].recipes or {}) do | |
| out = out .. p.buildreaction(frame, recipe) | |
| end
| |
| return out
| |
| end
| |
|
| |
|
| function p.buildreactionext(frame)
| | -- строим красивую карточку рецепта |
| local react = frame.args[1]
| | table.insert(out, string.format("== %s ==\n", r.id)) |
| return p.buildreaction(frame, react)
| |
| end
| |
|
| |
|
| function p.buildreaction(frame, react)
| | if #r.reactants > 0 then |
| if not react or not p.react[react] then return "" end
| | table.insert(out, "'''Реагенты:''' ") |
| local data = p.react[react]
| | local reacts = {} |
| local args = {}
| | for _, v in ipairs(r.reactants) do |
| | table.insert(reacts, string.format("%s × %s", v.id, v.amount)) |
| | end |
| | table.insert(out, table.concat(reacts, ", ") .. "\n") |
| | end |
|
| |
|
| -- Реактанты
| | if #r.products > 0 then |
| local i = 0
| | table.insert(out, "'''Продукты:''' ") |
| for k, v in pairs(data.reactants or {}) do
| | local prods = {} |
| i = i + 1
| | for _, v in ipairs(r.products) do |
| local dest = p.groupDirection[(p.chem[k] or {}).group] or "Chemistry"
| | table.insert(prods, string.format("%s × %s", v.id, v.amount)) |
| args["component-" .. i] = frame:expandTemplate{
| | end |
| title = "Chem Recipe Component",
| | table.insert(out, table.concat(prods, ", ") .. "\n") |
| args = { reagent = k, amount = v.amount, dest = dest }
| | end |
| }
| |
| end
| |
| | |
| -- Продукты
| |
| i = 0
| |
| for k, v in pairs(data.products or {}) do
| |
| i = i + 1
| |
| local dest = p.groupDirection[(p.chem[k] or {}).group] or "Chemistry"
| |
| 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 }
| |
| end
| |
| | |
| local function scan_metab(chem)
| |
| local met = (p.chem[chem] or {}).metabolisms
| |
| if not met then return nil end
| |
| return met
| |
| end
| |
| | |
| function p.checksatiatesthirst(frame)
| |
| local chem = frame.args[1]
| |
| local met = scan_metab(chem)
| |
| if not met then return "" end
| |
| for _, v in pairs(met) do
| |
| for _, w in pairs(v.effects or {}) do
| |
| if w.id == "SatiateThirst" then return "1" end
| |
| end
| |
| end
| |
| return ""
| |
| end
| |
| | |
| function p.checksatiateshunger(frame)
| |
| local chem = frame.args[1]
| |
| local met = scan_metab(chem)
| |
| if not met then return "" end
| |
| for _, v in pairs(met) do
| |
| for _, w in pairs(v.effects or {}) do
| |
| if w.id == "SatiateHunger" then return "1" end | |
| end
| |
| end
| |
| return ""
| |
| end | |
|
| |
|
| function p.haseffects(frame)
| | if r.impact then |
| local chem = frame.args[1]
| | table.insert(out, "'''Импакт:''' " .. r.impact .. "\n") |
| local met = scan_metab(chem)
| |
| if not met then return "" end
| |
| for _, v in pairs(met) do
| |
| for _, w in pairs(v.effects or {}) do
| |
| if w.id ~= "SatiateHunger" and w.id ~= "SatiateThirst" then
| |
| return "1"
| |
| end | | end |
| end
| |
| end
| |
| return ""
| |
| end
| |
|
| |
|
| function p.getflavor(frame)
| | table.insert(out, "\n") |
| local chem = p.chem[frame.args[1]]
| |
| if not chem or not chem.flavor then
| |
| return ""
| |
| end
| |
| local flavor = p.flavors[chem.flavor]
| |
| if flavor and flavor.name then
| |
| return flavor.name
| |
| else
| |
| return chem.flavor
| |
| end
| |
| end
| |
| | |
| function p.getstatus(frame)
| |
| local chem = p.chem[frame.args[1]]
| |
| if not chem or not chem.metabolismGroup then
| |
| return ""
| |
| end
| |
| local status = p.status[chem.metabolismGroup]
| |
| if status and status.name then
| |
| return status.name
| |
| else
| |
| return chem.metabolismGroup
| |
| end
| |
| end
| |
| | |
| function p.geneffects(frame, chem)
| |
| if chem == nil then chem = frame.args[1] end
| |
| local met = scan_metab(chem)
| |
| if not met then return "" end
| |
| local out = ""
| |
| for k, v in pairs(met) do
| |
| out = out .. "<b>" .. k .. "</b> (" .. tostring(v.rate) .. " единиц в секунду)\n" ..
| |
| p.geneffectlist(v.effects or {}, frame, v.rate or 1)
| |
| end
| |
| return out
| |
| end
| |
| | |
| function p.geneffectlist(effects, frame, rate)
| |
| local out = ""
| |
| for _, w in pairs(effects or {}) do
| |
| if w.id == "HealthChange" then
| |
| out = out .. ":" .. p.genhealthchange(w, rate, frame) .. "\n" | |
| elseif w.id == "AdjustReagent" then
| |
| out = out .. ":" .. p.genadjustreagent(w, rate, frame) .. "\n"
| |
| elseif w.id == "FlammableReaction" then
| |
| out = out .. ":" .. p.genflammablereaction(w, frame) .. "\n"
| |
| elseif w.id == "AdjustTemperature" then
| |
| 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 |
| end | | end |
| return out
| |
| end
| |
|
| |
| function p.gensmokeareareactioneffect(r, frame)
| |
| local conds = nil
| |
| if r.conditions ~= nil then
| |
| conds = p.genconds(r.conditions, frame)
| |
| end
| |
| return frame:expandTemplate{ title = "SmokeAreaReactionEffect", args = { when = conds, prob = r.probability }}
| |
| end
| |
|
| |
| function p.genfoamareareactioneffect(r, frame)
| |
| local conds = nil
| |
| if r.conditions ~= nil then
| |
| conds = p.genconds(r.conditions, frame)
| |
| end
| |
| return frame:expandTemplate{ title = "FoamAreaReactionEffect", args = { when = conds, prob = r.probability }}
| |
| end
| |
|
| |
| function p.genexplosionreactioneffect(r, frame)
| |
| local conds = nil
| |
| if r.conditions ~= nil then
| |
| conds = p.genconds(r.conditions, frame)
| |
| end
| |
| return frame:expandTemplate{ title = "ExplosionReactionEffect", args = { when = conds, prob = r.probability }}
| |
| end
| |
|
| |
| function p.gengenericstatuseffect(r, frame)
| |
| local conds = nil
| |
| if r.conditions ~= nil then
| |
| conds = p.genconds(r.conditions, frame)
| |
| end
| |
| return frame:expandTemplate{
| |
| title = "GenericStatusEffect",
| |
| args = { key = r.Key, type = r.Type, time = r.Time, refresh = r.Refresh, when = conds, prob = r.probability }
| |
| }
| |
| end
| |
|
| |
|
| function p.genadjusttemperature(r, frame)
| | return table.concat(out, "") |
| local conds = nil
| |
| if r.conditions ~= nil then
| |
| 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)
| |
| local conds = nil
| |
| if r.conditions ~= nil then
| |
| conds = p.genconds(r.conditions, frame)
| |
| end
| |
| return frame:expandTemplate{ title = "FlammableReaction", args = { multiplier = r.Multiplier, when = conds, prob = r.probability }}
| |
| end
| |
| | |
| function p.genadjustreagent(r, rate, frame)
| |
| local conds = nil
| |
| if r.conditions ~= nil then
| |
| conds = p.genconds(r.conditions, frame)
| |
| 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 conds = nil
| |
| if r.conditions ~= nil then
| |
| 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)
| |
| local healst = {}
| |
| local dealst = {}
| |
| local r = 1.0 / (rate or 1)
| |
| | |
| if h.damage and h.damage.types 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 and h.damage.groups 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 p.genconds(conds, frame)
| |
| local out = ""
| |
| local len = tablelength(conds or {})
| |
| local i = 0
| |
| for _, c in pairs(conds or {}) 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(c, frame)
| |
| end
| |
| return out
| |
| end
| |
| | |
| function p.gencond(c, frame)
| |
| if not c or not c.id then return "" end
| |
| 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 | | end |
|
| |
|
| return p | | return p |