Для документации этого модуля может быть создана страница Модуль:Chemistry Lookup/doc
local loader = require("Module:JsonPageLoader")
-- Загружаем данные из JSON файлов
local chem_data = loader.load("User:FireBot/chem_prototypes.json")
local react_data = loader.load("User:FireBot/react_prototypes.json")
local status_data = loader.load("User:FireBot/chem_status.json")
local p = {}
-- Основные данные
p.chem = chem_data
p.react = react_data
p.status = status_data
-- Направления групп для навигации
p.groupDirection = {
Drinks = "Drinks",
Foods = "Cooking",
}
-- Функция для чтения скалярного значения из химических данных
function p.readscalar(frame)
local chem_id = frame.args[1]
local property = frame.args[2]
if p.chem[chem_id] and p.chem[chem_id][property] then
return mw.text.nowiki(tostring(p.chem[chem_id][property]))
end
return ""
end
-- Функция для чтения скалярного значения из данных реакций
function p.readscalarreact(frame)
local react_id = frame.args[1]
local property = frame.args[2]
if p.react[react_id] and p.react[react_id][property] then
return mw.text.nowiki(tostring(p.react[react_id][property]))
end
return ""
end
-- Получение цвета химического вещества
function p.getcolor(frame)
local chem_id = frame.args[1]
if p.chem[chem_id] and p.chem[chem_id].color then
local color = p.chem[chem_id].color
-- Обрезаем до 7 символов (#RRGGBB)
return mw.text.nowiki(color:sub(1, 7))
end
return "#FFFFFF"
end
-- Получение цвета текста на основе яркости фона
function p.gettextcolor(frame)
local chem_id = frame.args[1]
if not (p.chem[chem_id] and p.chem[chem_id].color) then
return "#000"
end
local basecol = p.chem[chem_id].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
-- Проверка наличия рецепта у химического вещества
function p.hasrecipe(frame)
local chem_id = frame.args[1]
if p.chem[chem_id] and p.chem[chem_id].recipes then
return #p.chem[chem_id].recipes > 0
end
return false
end
-- Построение блоков для химических веществ
function p.buildboxes(frame)
local group = frame.args[1]
local out = ""
for k, v in pairs(p.chem) do
if group == nil or (v.group and v.group == group) then
out = out .. frame:expandTemplate{
title = "Chembox",
args = { prototype = k }
}
end
end
return out
end
-- Построение блоков реакций
function p.buildreactboxes(frame)
local out = ""
for k, v in pairs(p.react) do
if v.effects and p.tablelength(v.effects) > 0 then
out = out .. frame:expandTemplate{
title = "Reactionbox",
args = { reaction = k }
}
end
end
return out
end
-- Построение рецептов для химического вещества
function p.buildrecipes(frame)
local chem_id = frame.args[1]
local out = ""
if p.chem[chem_id] and p.chem[chem_id].recipes then
for _, recipe_id in pairs(p.chem[chem_id].recipes) do
out = out .. p.buildreaction(frame, recipe_id)
end
end
return out
end
-- Построение конкретной реакции
function p.buildreactionext(frame)
local react_id = frame.args[1]
return p.buildreaction(frame, react_id)
end
-- Основная функция построения реакции
function p.buildreaction(frame, react_id)
if not p.react[react_id] then
return ""
end
local data = p.react[react_id]
local args = {}
-- Обрабатываем реагенты
local i = 0
if data.reactants then
for reagent_id, reagent_data in pairs(data.reactants) do
i = i + 1
local dest = "Chemistry"
if p.chem[reagent_id] and p.chem[reagent_id].group and p.groupDirection[p.chem[reagent_id].group] then
dest = p.groupDirection[p.chem[reagent_id].group]
end
args["component-" .. i] = frame:expandTemplate{
title = "Chem Recipe Component",
args = {
reagent = reagent_id,
amount = reagent_data.amount or reagent_data,
dest = dest
}
}
end
end
-- Обрабатываем продукты
i = 0
if data.products then
for product_id, amount in pairs(data.products) do
i = i + 1
local dest = "Chemistry"
if p.chem[product_id] and p.chem[product_id].group and p.groupDirection[p.chem[product_id].group] then
dest = p.groupDirection[p.chem[product_id].group]
end
args["result-" .. i] = frame:expandTemplate{
title = "Chem Recipe Component",
args = {
reagent = product_id,
amount = amount,
dest = dest
}
}
end
end
-- Обрабатываем эффекты
if data.effects then
args.effects = p.geneffectlist(data.effects, frame, 1)
end
return frame:expandTemplate{ title = "Chem Box Recipe", args = args }
end
-- Проверка на утоление жажды
function p.checksatiatesthirst(frame)
local chem_id = frame.args[1]
if not (p.chem[chem_id] and p.chem[chem_id].metabolisms) then
return ""
end
for _, metabolism in pairs(p.chem[chem_id].metabolisms) do
if metabolism.effects then
for _, effect in pairs(metabolism.effects) do
if effect.id == "SatiateThirst" then
return "1"
end
end
end
end
return ""
end
-- Проверка на утоление голода
function p.checksatiateshunger(frame)
local chem_id = frame.args[1]
if not (p.chem[chem_id] and p.chem[chem_id].metabolisms) then
return ""
end
for _, metabolism in pairs(p.chem[chem_id].metabolisms) do
if metabolism.effects then
for _, effect in pairs(metabolism.effects) do
if effect.id == "SatiateHunger" then
return "1"
end
end
end
end
return ""
end
-- Проверка наличия эффектов (кроме голода/жажды)
function p.haseffects(frame)
local chem_id = frame.args[1]
if not (p.chem[chem_id] and p.chem[chem_id].metabolisms) then
return ""
end
for _, metabolism in pairs(p.chem[chem_id].metabolisms) do
if metabolism.effects then
for _, effect in pairs(metabolism.effects) do
if effect.id ~= "SatiateHunger" and effect.id ~= "SatiateThirst" then
return "1"
end
end
end
end
return ""
end
-- Генерация эффектов
function p.geneffects(frame, chem_id)
if chem_id == nil then
chem_id = frame.args[1]
end
if not (p.chem[chem_id] and p.chem[chem_id].metabolisms) then
return ""
end
local out = ""
for metabolism_type, metabolism_data in pairs(p.chem[chem_id].metabolisms) do
local rate = metabolism_data.rate or 0.5
out = out .. "<b>" .. metabolism_type .. "</b> (" .. rate .. " единиц в секунду)\n"
if metabolism_data.effects then
out = out .. p.geneffectlist(metabolism_data.effects, frame, rate)
end
end
return out
end
-- Генерация списка эффектов
function p.geneffectlist(effects, frame, rate)
local out = ""
for _, effect in pairs(effects) do
if effect.id == "HealthChange" then
out = out .. ":" .. p.genhealthchange(effect, rate, frame) .. "\n"
elseif effect.id == "AdjustReagent" then
out = out .. ":" .. p.genadjustreagent(effect, rate, frame) .. "\n"
elseif effect.id == "FlammableReaction" then
out = out .. ":" .. p.genflammablereaction(effect, frame) .. "\n"
elseif effect.id == "AdjustTemperature" then
out = out .. ":" .. p.genadjusttemperature(effect, frame) .. "\n"
elseif effect.id == "GenericStatusEffect" then
out = out .. ":" .. p.gengenericstatuseffect(effect, frame) .. "\n"
elseif effect.id == "ExplosionReactionEffect" then
out = out .. ":" .. p.genexplosionreactioneffect(effect, frame) .. "\n"
elseif effect.id == "FoamAreaReactionEffect" then
out = out .. ":" .. p.genfoamareareactioneffect(effect, frame) .. "\n"
elseif effect.id == "SmokeAreaReactionEffect" then
out = out .. ":" .. p.gensmokeareareactioneffect(effect, frame) .. "\n"
elseif effect.id == "ModifyBleedAmount" then
out = out .. ":" .. p.genmodifybleedamount(effect, frame) .. "\n"
end
end
return out
end
-- Генераторы для различных типов эффектов
function p.gensmokeareareactioneffect(effect, frame)
local conds = ""
if effect.conditions then
conds = p.genconds(effect.conditions, frame)
end
return frame:expandTemplate{
title = "SmokeAreaReactionEffect",
args = {
when = conds,
prob = effect.probability
}
}
end
function p.genfoamareareactioneffect(effect, frame)
local conds = ""
if effect.conditions then
conds = p.genconds(effect.conditions, frame)
end
return frame:expandTemplate{
title = "FoamAreaReactionEffect",
args = {
when = conds,
prob = effect.probability
}
}
end
function p.genexplosionreactioneffect(effect, frame)
local conds = ""
if effect.conditions then
conds = p.genconds(effect.conditions, frame)
end
return frame:expandTemplate{
title = "ExplosionReactionEffect",
args = {
when = conds,
prob = effect.probability
}
}
end
function p.gengenericstatuseffect(effect, frame)
local conds = ""
if effect.conditions then
conds = p.genconds(effect.conditions, frame)
end
return frame:expandTemplate{
title = "GenericStatusEffect",
args = {
key = effect.Key,
type = effect.Type,
time = effect.Time,
refresh = effect.Refresh,
when = conds,
prob = effect.probability
}
}
end
function p.genadjusttemperature(effect, frame)
local conds = ""
if effect.conditions then
conds = p.genconds(effect.conditions, frame)
end
return frame:expandTemplate{
title = "AdjustTemperature",
args = {
amount = effect.Amount,
when = conds,
prob = effect.probability
}
}
end
function p.genflammablereaction(effect, frame)
local conds = ""
if effect.conditions then
conds = p.genconds(effect.conditions, frame)
end
return frame:expandTemplate{
title = "FlammableReaction",
args = {
multiplier = effect.Multiplier,
when = conds,
prob = effect.probability
}
}
end
function p.genadjustreagent(effect, rate, frame)
local conds = ""
if effect.conditions then
conds = p.genconds(effect.conditions, frame)
end
return frame:expandTemplate{
title = "AdjustReagent",
args = {
amount = effect.Amount,
reagent = effect.Reagent,
when = conds,
prob = effect.probability
}
}
end
function p.genmodifybleedamount(effect, frame)
local conds = ""
if effect.conditions then
conds = p.genconds(effect.conditions, frame)
end
return frame:expandTemplate{
title = "ModifyBleedAmount",
args = {
amount = effect.Amount,
when = conds,
prob = effect.probability
}
}
end
function p.genhealthchange(effect, rate, frame)
local healst = {}
local dealst = {}
local r = 1.0 / rate
if effect.damage and effect.damage.types then
for damage_type, amount in pairs(effect.damage.types) do
if amount < 0 then
healst[damage_type] = amount * r
else
dealst[damage_type] = amount * r
end
end
end
if effect.damage and effect.damage.groups then
for damage_group, amount in pairs(effect.damage.groups) do
if amount < 0 then
healst[damage_group] = amount * r
else
dealst[damage_group] = amount * r
end
end
end
local heals = p.hchangelist(healst, frame)
local deals = p.hchangelist(dealst, frame)
local conds = ""
if effect.conditions then
conds = p.genconds(effect.conditions, frame)
end
return frame:expandTemplate{
title = "HealthChange",
args = {
heals = heals,
deals = deals,
when = conds,
prob = effect.probability
}
}
end
function p.hchangelist(changes, frame)
local out = ""
local len = p.tablelength(changes)
local i = 0
for damage_type, amount in pairs(changes) do
i = i + 1
if len == i and i ~= 1 then
out = out .. ", and "
elseif i ~= 1 then
out = out .. ", "
end
out = out .. p.hchange(damage_type, amount, frame)
end
return out
end
function p.hchange(damage_type, amount, frame)
return frame:expandTemplate{
title = "HealthModifier",
args = {
adj = amount,
kind = damage_type
}
}
end
function p.genconds(conditions, frame)
local out = ""
local len = p.tablelength(conditions)
local i = 0
for _, condition in pairs(conditions) 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(condition, frame)
end
return out
end
function p.gencond(condition, frame)
if condition.id == "TotalDamage" then
return frame:expandTemplate{
title = "TotalDamage",
args = {
min = condition.Min,
max = condition.Max
}
}
elseif condition.id == "ReagentThreshold" then
return frame:expandTemplate{
title = "ReagentThreshold",
args = {
min = condition.Min,
max = condition.Max,
reagent = condition.Reagent
}
}
elseif condition.id == "OrganType" then
return frame:expandTemplate{
title = "OrganType",
args = {
shouldhave = condition.ShouldHave,
type = condition.Type
}
}
elseif condition.id == "Temperature" then
return frame:expandTemplate{
title = "Temperature",
args = {
min = condition.Min,
max = condition.Max
}
}
end
return ""
end
-- Вспомогательные функции
function p.tablelength(table)
local count = 0
for _ in pairs(table) do
count = count + 1
end
return count
end
function p.has_value(tab, val)
for _, value in ipairs(tab) do
if value[1] == val then
return true
end
end
return false
end
function p.strsplit(inputstr, separator)
if separator == nil then
separator = ","
end
local t = {}
for str in string.gmatch(inputstr, "([^"..separator.."]+)") do
table.insert(t, str)
end
return t
end
-- Функции для работы со статусами химических веществ
function p.getmetabolizertype(frame)
local type_id = frame.args[1]
if p.status[type_id] and p.status[type_id].type == "metabolizerType" then
return p.status[type_id].name or type_id
end
return ""
end
function p.getmetabolismgroup(frame)
local group_id = frame.args[1]
if p.status[group_id] and p.status[group_id].type == "metabolismGroup" then
return p.status[group_id].name or group_id
end
return ""
end
function p.getmixingcategory(frame)
local category_id = frame.args[1]
if p.status[category_id] and p.status[category_id].type == "mixingCategory" then
return p.status[category_id].verbText or category_id
end
return ""
end
function p.getreactivegroup(frame)
local group_id = frame.args[1]
if p.status[group_id] and p.status[group_id].type == "reactiveGroup" then
return group_id
end
return ""
end
return p