模块:Npc

来自乐园数据管理室

此模块的文档可以在模块:Npc/doc创建

local p = {}
local QueryHelper = require("Module:Xb2QueryHelper")
local html = require("Module:Html")
local BdatEnums = require("Module:BdatEnums")
local Flag = require("Module:Flag")
local Condition = require("Module:Condition")

local function processTalk(talkArr)
  local talkText = ""
  for _, row in ipairs(talkArr) do
    row = mw.ustring.gsub(row, "\n", "<br>")
    row = mw.ustring.gsub(row, "%[ML:Dash.*%]", "──")
    row = mw.ustring.gsub(row, "%[ML:Feeling .*%]", "")

    talkText = talkText .. "<li>" .. row .. "</li>"
  end
  return "<ul>" .. talkText .. "</ul>"
end

function p.main(frame)
  local out = ""

  local currentTitle = mw.title.getCurrentTitle()
  local npcName = currentTitle.text

  local npcs = QueryHelper.getNpcPopByNpcName(npcName)

  -- 过滤无出现地点的NPC
  local npcsWithoutNoPop = {}
  for _, npc in ipairs(npcs) do
    if #npc.Pops > 0 then
      table.insert(npcsWithoutNoPop, npc)
    end
  end

  -- mw.log(mw.text.jsonEncode(npcs, mw.text.JSON_PRETTY))
  -- mw.logObject(npcsWithoutNoPop)

  -- table.sort比较函数,相同要返回false,一直返回true会出错
  local sortFunc = function(a, b)
    -- 把任务id小于1000的隐式主线任务设为0,认为它不存在
    if a.QuestFlag <= 1000 then
      a.QuestFlag = 0
    end
    if b.QuestFlag <= 1000 then
      b.QuestFlag = 0
    end

    -- 不是任务的排前面
    if a.QuestFlag * b.QuestFlag == 0 and a.QuestFlag > 0 or b.QuestFlag > 0 then
      if a.QuestFlag == b.QuestFlag then
        return false
      else
        return a.QuestFlag < b.QuestFlag
      end
    end

    -- 按ScenarioFlagMin升序
    if a.ScenarioFlagMin > 0 and b.ScenarioFlagMin > 0 then
      if a.ScenarioFlagMin == b.ScenarioFlagMin then
        return false
      else
        return a.ScenarioFlagMin <= b.ScenarioFlagMin
      end
    end

    -- 按QuestFlag升序
    if a.QuestFlag > 1000 or b.QuestFlag > 1000 then
      if a.QuestFlag == b.QuestFlag then
        return false
      else
        return a.QuestFlag < b.QuestFlag
      end
    end

    return a.row_id < b.row_id
  end

  for _, npc in ipairs(npcsWithoutNoPop) do
    if #npcsWithoutNoPop > 1 then
      out = out .. html.h2("Npc: " .. npc.row_id)
    end

    -- NPC info and picture
    out = out .. '<div class="flex-wrap" style="justify-content: space-between;">'
    local race = BdatEnums.getNpcRaceName(npc)
    out =
      out ..
      html.wikitable(
        {"性别", "人种"},
        {
          {BdatEnums.Gender[npc.Gender], race}
        }
      )
    out = out .. "[[文件:NPC-" .. npc.row_id .. ".jpg|none|400px|上传NPC照片]]"
    out = out .. "</div>"

    -- 出现点
    table.sort(npc.Pops, sortFunc)
    for _, npcPop in ipairs(npc.Pops) do
      -- SMW
      mw.smw.set {PopID = npcPop.row_id}

      out = out .. html.h3("Pop: " .. npcPop.row_id)

      do -- 第一行:基本信息、条件
        local scenario
        if npcPop.ScenarioFlagMin > 0 or npcPop.ScenarioFlagMax > 0 then
          scenario =
            npcPop.ScenarioFlagMin == npcPop.ScenarioFlagMax and Flag.scenario(npcPop.ScenarioFlagMin) or
            Flag.scenario(npcPop.ScenarioFlagMin) .. " ~ " .. Flag.scenario(npcPop.ScenarioFlagMax)
        end

        local quest, questPhase = Flag.quest(npcPop.QuestFlag, npcPop.row_id > 40000)
        mw.smw.set {QuestDisplay = quest}

        local npcPopRowData = {
          world = BdatEnums.getWorldName(math.floor(npcPop.row_id / 1000)),
          timerange = table.concat(BdatEnums.getTimeRange(npcPop.TimeRange), ", "),
          scenario = scenario,
          quest = questPhase and (quest .. "#" .. questPhase) or quest,
          condition = Condition.getById(npcPop.Condition, npcPop.row_id > 40000),
          memberNum = npcPop.memberNum
        }

        local th = {
          {scope = "world", label = "地域"},
          {scope = "timerange", label = "时间段"}
        }
        if npcPopRowData.scenario then
          table.insert(th, {scope = "scenario", label = "主线剧情"})
        end
        if npcPopRowData.quest then
          table.insert(th, {scope = "quest", label = "任务"})
        end
        if npcPop.Group > 0 then
          table.insert(th, {scope = "memberNum", label = "人数"})
        end

        out = out .. '<div class="flex-wrap">'
        out = out .. html.wikitable(th, {npcPopRowData})

        if npcPop.Condition > 0 then
          local conditionText = Condition.getById(npcPop.Condition, npcPop.row_id > 40000)
          if conditionText then
            out =
              out ..
              html.wikitable(
                {"条件"},
                {
                  {conditionText}
                }
              )
          end
        end
        out = out .. "</div>"
      end

      do -- 第二行:对话、地图
        out = out .. '<div class="flex-wrap" style="justify-content: space-between;">'
        -- Talkable属性为true才显示对话
        if npcPop.Talkable then
          local languageTable = {
            {lan = "cn", label = "简"},
            {lan = "tw", label = "繁"},
            {lan = "jp", label = "日"}
          }

          local talkList = {}
          for _, v in ipairs(languageTable) do
            -- 设置语言
            QueryHelper.language = v.lan
            table.insert(talkList, QueryHelper.getDialogByEventId(npcPop.EventID))
          end
          -- 重置语言
          QueryHelper.language = "cn"

          -- 对话语句数大于0时才显示
          if #talkList[1] > 0 then
            out = out .. '<div class="xbxbtabs">'
            for i, v in ipairs(languageTable) do
              local tabslabel = v.label
              local tabsname = npcPop.EventID .. v.lan
              out =
                out ..
                '<div data-name="' ..
                  tabsname ..
                    '" data-label="' ..
                      tabslabel ..
                        '" >' ..
                          html.wikitable(
                            {"对话"},
                            {
                              {processTalk(talkList[i])}
                            }
                          ) ..
                            "</div>"
            end
            out = out .. "</div>"
          end
        end

        -- 地图
        out =
          out ..
          '<div style="flex-grow: 1;min-width: 360px;max-width: 640px;">' ..
            mw.ustring.format([[<div class="xb2map-npc" data-gmk-id="%s" ></div>]], npcPop.name) .. "</div>"

        out = out .. "</div>"
      end
    end

    -- SMW
    mw.smw.set {
      Race = race
    }
  end

  return out
end

return p