此站点为镜像站,如有编辑wiki的意愿请前往主站进行编辑。
加入Noita中文维基群获取更多wiki编辑上的帮助。
→加入游戏社区|Noita魔法群|
|Noita交流群|Noita贴吧|
与更多玩家一起游玩Noita。

全站通知:

模块:DataQuery

来自NoitaWIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索
Template-info.png 模块文档

该脚本使用的数据来源于模块:DataQuery/Enemies模块:DataQuery/Materials模块:DataQuery/Spells 一般来讲该模块只应使用于模板中。

使用

参数

参数 描述
q?tables 查询数据表,目前可用的为"Spells、Enemies和Materials"
combineResultAsRow 行转列,主要用于Infobox
default 当查询结果为空时,返回的数据
intro 拼接到结果之前的wiki文本
outro 拼接到结果之后的wiki文本
template 渲染每一行数据的模板
q?tier (法术专用)法术等级, 过滤方式为AND
q?id (法术专用)用法术id查询法术
q?noProbabilityZero (法术专用),当值为true时将过滤对应等级下生成权重为0的法术,注意因为这个原因,只有在指定搜索等级时才有用。
q?groupKey (法术和敌人)用于筛选一类法术或敌人, 过滤方式为AND
q?link (材料专用)用于筛选一类材料, 过滤方式为AND
q?tags (材料专用),用tag筛选一类材料,过滤方式为AND
q?name (法术、敌人和材料)查询名称,可使用半角逗号分隔以查询多个,可使用值为英文名、官方中文名;排他参数。
q?type (法术、敌人和材料)查询类型,可使用半角逗号分隔以查询多个;投射物(Projectile), 静态投射物(Static projectile), 被动(Passive), 实用(Utility), 投射修正(Projectile modifier), 材料(Material), 多重释放(Multicast);指定该参数时仍将应用其他过滤条件。敌人可查询类型为:杂项类,亡灵类,粘液类,蜘蛛类,席西类,机械类,支援类,炼金术师,元素魔物,法师类,游魂类,蠕虫类,被动生物,最终BOSS,小BOSS,BOSS召唤的小怪,平行世界的幻影,你,其他。材料可查询类型为:fire,static,sand,liquid,gas,plant,box2d,special,badjokes,hax。
q?herd (敌人、材料)查询对应herd的敌人,其实材料查询id也用了这个,算是一个名称不对实际效果的代码复用,过滤方式为AND
delimiter 在你所筛选的数据当中穿插文字。

示例

{{#invoke:DataQuery|main
|q?tables=Spells
|q?type=其他
|intro={{{!}} class="mw-collapsible" style="width:100%;"
{{!}}+
{{!}} <div style="display:flex;column-gap:0.8rem;row-gap:0.8rem;justify-content:center;flex-wrap:wrap">
|outro=</div>
{{!}}}
|template=SpellQuery/row2
|default=''There are no spells of the specified query.''
}}

{{#invoke:DataQuery|main
|q?tables=Enemies
|q?type=
|q?herd=slimes
|intro={{{!}} class="mw-collapsible" style="width:100%;"
{{!}}+
{{!}} <div style="display:flex;column-gap:0.5rem;row-gap:0.5rem;justify-content:center;flex-wrap:wrap">
|outro=</div>
{{!}}}
|template=EnemyQuery/row
|default=''未查询到数据''
}}

{{#invoke:DataQuery|main
|q?tables=Enemies
|q?type=杂项类
|intro=
|outro=
|delimiter={{*}}
|template=EnemyNav/List
|default=''未查询到数据''

{{#invoke:DataQuery|main
|q?tables=Materials
|q?tags=sand_other,burnable
|intro=
|outro=
|delimiter={{*}}
|template=MaterialNav/List
|default=''未查询到数据''
}}

{{#invoke:DataQuery|main
|q?tables=Materials
|q?link=砖块
|combineResultAsRow=1
|template=Infobox material}}
}}
[[|法术复制]]
复制本次施法中已被施放的所有法术,除了另一个法术复制
[[|陶笛 - 音符 A]]
悦耳的音乐!
[[|陶笛 - 音符 B]]
悦耳的音乐!
[[|陶笛 - 音符 C]]
悦耳的音乐!
[[|陶笛 - 音符 D]]
悦耳的音乐!
[[|陶笛 - 音符 E]]
悦耳的音乐!
[[|陶笛 - 音符 F]]
悦耳的音乐!
[[|陶笛 - 音符 G#]]
悦耳的音乐!
[[|陶笛 - 音符 A2]]
悦耳的音乐!
[[|康特勒琴 - 音符A]]
悦耳的音乐!
[[|康特勒琴 - 音符D]]
悦耳的音乐!
[[|康特勒琴 - 音符D#]]
悦耳的音乐!
[[|康特勒琴 - 音符E]]
悦耳的音乐!
[[|康特勒琴 - 音符G]]
悦耳的音乐!
[[|随机法术]]
随机施放一个法术,任何法术都有可能!
[[|复制随机法术]]
随机施放魔杖中一个未用完或无次数限制法术的复制品,依然会扣除次数
[[|复制随机法术三次]]
随机施放三次魔杖中一个未用完或无次数限制法术的复制品,只会扣除一次使用次数
[[|复制三个随机法术]]
随机施放魔杖中三个未用完或无次数限制法术的复制品,三次随机可能重复选择,复制的法术各扣除一次使用次数
[[|万物之终结]]
请勿尝试该法术
[[|召唤传送门]]
召唤一个奇特的传送门,只有在四方佛像同时加持下才能维持稳定
[[|追加触发]]
令投射物在碰撞时施放另一法术
[[|追加定时]]
令投射物在短暂时间后施放另一法术
[[|追加失效触发]]
令投射物在失效时施放另一法术
[[|阿尔法]]
施放当前魔杖中第一个法术的复制品
[[|伽马]]
施放当前魔杖中最后一个法术的复制品
[[|陶]]
施放它后面两个法术的复制品
[[|欧米伽]]
施放当前魔杖中所有法术的复制品,跳过它自己和“魔杖刷新”法术
[[|缪]]
施放当前魔杖中所有修正法术的复制品,无视它们对延迟、充能与法力的影响,然后抽取一个法术
[[|斐]]
施放当前魔杖中所有投射物法术的复制品,无视它们对延迟、充能与法力的影响
[[|西格玛]]
施放当前魔杖中所有静态投射物法术的复制品,无视它们对延迟、充能与法力的影响,然后抽取一个法术
[[|泽塔]]
随机施放你另一魔杖中某个法术的复制品
[[|一分为二]]
施放魔杖中下一个法术的复制品两次
[[|一分为三]]
施放魔杖中下一个法术的复制品三次
[[|一分为四]]
施放魔杖中下一个法术的复制品四次
一分为十
[[|一分为十]]
施放魔杖中下一个法术的复制品十次
[[|条件 - 敌人数量]]
如果附近的敌人少于15个,则跳过下一法术
[[|条件 - 投射物数量]]
如果附近的投射物少于20个,则跳过下一法术
[[|条件 - 低生命值]]
如果剩余的生命值超过25%,则跳过下一法术
[[|条件 - 间隔]]
每隔两次这种法术被执行时,下个法术被跳过
[[|条件 - 结束]]
上一个条件法术的作用范围向后扩展到这里
[[|条件 - 否则]]
上一个条件法术的作用范围向后扩展到这里,若判断结果为是,则跳过下一法术
[[File:|link=|alt=遁入虚空|48px]]
[[|遁入虚空]]
施法者进入无界之界

酸液史莱姆

Happonuljaska

哈波努利亚斯卡

虚弱酸液史莱姆

Heikko happonuljaska

海科·哈波努利亚斯卡

史莱姆母体

Äitinuljaska

埃提奴利亚斯加

虚弱史莱姆母体

Heikko äitinuljaska

海科·埃提奴利亚斯加

激光史莱姆

Mulkkio

穆尔基奥

毒液史莱姆

Limanuljaska

利马努利亚斯卡

虚弱毒液史莱姆

Heikko limanuljaska

海科·利马努利亚斯卡

小触手怪

Pikkuturso

皮库图尔索

触手怪

Turso

图尔索

小呱呱

Konna

空纳

大呱呱

Jättikonna

甲提客尔娜

暗影泡泡

Varjokupla

瓦吉奥库普勒

地狱喷吐者

Helvetin sylkijä

黑勒瓦汀苏拉基亚

地狱凝视者

Helvetinkatse

黑勒瓦汀卡特瑟

天空凝视者

Taivaankatse

代万恩卡忒斯

大肥蛆

Toukka

托乌卡

腐灵

Pienkätyri

皮焉噶杜里

三眼

Kolmisilmä

科尔密斯尔玛

 •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  • 
 
 •  •  •  •  •  •  •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   •   • 


<infobox theme="material">

   <panel>
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
   </panel>

</infobox>


local p = {

}

function p.main(frame)--主函数
    local args = frame
    if frame == mw.getCurrentFrame() then
        args = require('Module:ProcessArgs').merge(true)
    else
        frame = mw.getCurrentFrame()
    end
    -- error(mw.dumpObject(args))

    local query = {}
    for k, v in pairs(args) do--k为字符串
        if string.sub(k, 0, 2) == 'q?' then--如果开头两个字符为q?
            query[string.sub(k, 3)] = v--那么将截取之后的字符串作为一个key值,赋值为v(参数)
        end
    end

    local result = p.queryData(query.tables, query)
    if result[1] == nil then
        -- metatable似乎被删除了,因此#result的结果是0
        --if not next(result) then
        return frame:preprocess(args.default or '')
    end
    if args.combineResultAsRow ~= nil then
        result = combineResultAsRow(result)
    end
    local tbl = {}
    for _, row in ipairs(result) do
        tbl[#tbl + 1] = frame:expandTemplate { title = args.template, args = row }
    end
    local intro = frame:preprocess(args.intro or '')
    local outro = frame:preprocess(args.outro or '')
    return intro .. table.concat(tbl, args.delimiter or '') .. outro
end

--- 移除前后空格
local function strip(s)
    if s == nil then
        return ''
    end
    return s:gsub("^%s+", ""):gsub("%s+$", "")
end
local function isNotEmpty(s)
    return s ~= nil and s ~= ''
end

---split
---根据指定的分隔符分隔, 返回table, 内容会经过小写转换及删除前后空格
---@param s string
---@param delim string
local function split(s, delim)
    if string.find(s, delim) == nil then
        return {
            strip(s):lower()
        }
    end
    local result = {}
    for ct in string.gmatch(s, '([^' .. delim .. ']+)') do
        ct = strip(ct):lower()
        result[#result + 1] = ct
    end
    return result
end

---splitNolower
---根据指定的分隔符分隔, 返回table, 会删除前后空格
---@param s string
---@param delim string
local function splitNolower(s, delim)
    if string.find(s, delim) == nil then
        return {
            strip(s)
        }
    end
    local result = {}
    for ct in string.gmatch(s, '([^' .. delim .. ']+)') do
        ct = strip(ct)
        result[#result + 1] = ct
    end
    return result
end

--- 将所有结果合为一个, 后边加数字区分, 比如 { name, img, name2, img2 }
--- 不适合太大的结果集
function combineResultAsRow(result)
    if #result == 1 then
        return result
    end
    local r = {}
    for i, row in ipairs(result) do
        local suffix = ''
        if i > 1 then
            suffix = tostring(i)
        end
        for k, v in pairs(row) do
            r[k .. suffix] = v
        end
    end
    return { r }
end

-- 返回是否需要过滤结果集,用于提升性能
local function hasAnyFilter(query)
    if isNotEmpty(query.tier) then
        return true
    end
    if isNotEmpty(query.groupKey) then
        query.groupKey = query.groupKey:lower()
        return true
    end
    return false
end

--- 返回给定的行是否是符合条件的数据
local function isAvailableRow(t, v, query)
	local noProZero = false
	if query.noProbabilityZero == "true" then
		noProZero = true
		--ProTable = split(v.spawnProbability, ',')
	end
    if isNotEmpty(query.tier) then
        anyFind = false
        local Exit = false
        for _, ct in pairs(query.tier) do
            if noProZero then--先判断排除权重0
    	    	local tempTier = split(v.spellTier,",")--获得等级表
    	    	for k,v2 in pairs(tempTier)do--遍历它
    	    		if v2 == ct then--当到需要判断的等级的时候
    	    			local ProTable = split(v.spawnProbability, ',')--获取权重表
    	    			if ProTable[k] == "0"then--如果是0
    	    				Exit = true
    	    				break--直接退出循环
    	    			end
    	    		end
    	    	end
            end
    	if Exit then
    		break	
    	end
            if string.find(v['spellTierPrepared'], '#' .. ct .. '#') ~= nil then
                anyFind = true
                break
            end
        end
        if not anyFind then
            return false
        end
    end
    if isNotEmpty(query.groupKey) then--如果有groupKey
        if string.find(v['sortKey'], query.groupKey) == nil then--判断是否有这个sortKey
            return false
        end
    end
    --if isNotEmpty(query.type) then
    --    if v['type'] ~= query.type then
    --        return false
    --    end
    --end
    return true
end

local function filter(t, query)
    if not hasAnyFilter(query) then--此函数返回真假值,真代表有query.tier或query.groupKey,此时if为假,即不返回t
        return t
    end
    local result = {}
    if (t == nil) then--如果t是空的,返回空结果
        return result
    end
    for _, v in pairs(t) do
        if isAvailableRow(t, v, query) then
            result[#result + 1] = v
        end
    end
    return result
end

--- 查询并过滤数据, 结果集未排序, 需要外部排序
function p.queryData(tables, query)--query为参数表
	local temp = mw.title.makeTitle("Module", "DataQuery/"..query.tables)--判断数据库是否存在
	if not temp.exists then--不存在返回空列表
		return {}	
	end
    local raw_data = mw.loadData("Module:DataQuery/"..query.tables)--读取指定数据库,该模块返回一个表
    local all_data_table = raw_data[tables]--从指定表索引中找到数据
    if isNotEmpty(query.tier) then--isNotEmpty为判空函数,如果不为空返回真,此举是在判断是否有tier
        query.tier = split(query.tier, ',')--将参数分割为表
    end
    if isNotEmpty(query.AnyMat) then
    	local result = {}
    	local AnyMat = query.AnyMat
    	query.AnyMat = nil
    	if AnyMat == "any_liquid" then
    		for _,v1 in pairs(all_data_table)do
    			if v1.liquidSand == "0" and v1.cellType == "liquid"	then
    				table.insert(result,v1)
    			end
    		end
    	elseif AnyMat == "any_powder" then
    		--[[
    		for _,v1 in pairs(all_data_table)do
    			
    		end]]
    	end
    	
    	return result
    end
   --tags
    if isNotEmpty(query.tags) then
    	local result = {}
    	local tags = query.tags
    	query.tags = nil
    	local tagsQuery = split(tags,',')
    	for _,v1 in pairs(all_data_table)do--原数据是一个二维表,因此要for循环两次
    		if v1["tags"] ~= nil then
    			local TagsList = split(v1["tags"],',')
    			for _,queryKey in pairs(tagsQuery)do
    				for _,TagsElm in pairs(TagsList)do
    				if(TagsElm == queryKey)then
    					result[#result + 1] = v1
    				end
    				end
    			end
    		end
    	end
    	return result
    end
    if isNotEmpty(query.name) then
        local result = {}
        local table_by_name = raw_data[tables .. '_Name']
        for _, ct in pairs(split(query.name, ',')) do
            result[#result + 1] = table_by_name[ct]
        end
        return result
    end
    if isNotEmpty(query.id) then
        local result = {}
        local table_by_id = raw_data[tables .. '_ID']
        for _, ct in pairs(splitNolower(query.id, ',')) do
            result[#result + 1] = table_by_id[ct]
        end
        return result
    end
    if isNotEmpty(query.type) then
        local type = query.type
        query.type = nil
        if string.find(type, ',') == nil then
            return filter(raw_data[tables .. '_Type'][strip(type):lower()], query)
        end
        local result = {}
        for _, ct in pairs(split(type, ',')) do
            local tree_table = raw_data[tables .. '_Type'][ct]
            if tree_table == nil then
                error("can't find type: '" .. ct .. "'")
            end
            for _, v in pairs(filter(tree_table, query)) do
                result[#result + 1] = v
            end
        end
        return result
    end
    if isNotEmpty(query.herd) then
        local herd = query.herd
        query.herd = nil
        if string.find(herd, ',') == nil then
            return filter(raw_data[tables .. '_Herd'][strip(herd):lower()], query)
        end
        local result = {}
        for _, ct in pairs(split(herd, ',')) do
            local tree_table = raw_data[tables .. '_Herd'][ct]
            if tree_table == nil then
                error("can't find herd: '" .. ct .. "'")
            end
            for _, v in pairs(filter(tree_table, query)) do
                result[#result + 1] = v
            end
        end
        return result
    end
    if isNotEmpty(query.link) then
        local link = query.link
        query.link = nil
        if string.find(link, ',') == nil then
            return filter(raw_data[tables .. '_Link'][strip(link):lower()], query)
        end
        local result = {}
        for _, ct in pairs(split(link, ',')) do
            local tree_table = raw_data[tables .. '_Link'][ct]
            if tree_table == nil then
                error("can't find link: '" .. ct .. "'")
            end
            for _, v in pairs(filter(tree_table, query)) do
                result[#result + 1] = v
            end
        end
        return result
    end
    return filter(all_data_table, query)
end

return p