全站通知:
模块:Theater
刷
历
编
跳到导航
跳到搜索
local utils = require("Module:Utils")
local NPC = require("Module:NPC")
local p = {}
local createMovieQuote
local createMovieQuotes
local moviesData = mw.loadData('Module:Theater/data/movies')
local concessionsData = mw.loadData('Module:Theater/data/concessions')
local concessionTastesData = mw.loadData('Module:Theater/data/concession tastes')
local moviesReactionsData = mw.loadData('Module:Theater/data/movies reactions')
local dialogueData = mw.loadData('Module:Dialogue/data')
local movieNames = {
["spring_movie_0"] = "勇敢的小树苗",
["summer_movie_0"] = "草原之王之旅:大电影",
["fall_movie_0"] = "神秘事迹",
["winter_movie_0"] = "冷星牧场的奇迹",
["spring_movie_1"] = "自然奇观:探索我们这充满活力的世界",
["summer_movie_1"] = "温布斯",
["fall_movie_1"] = "它在雨中嚎叫",
["winter_movie_1"] = "祖祖城特快列车"
}
local concessionNames = {
["0"] = "棉花糖",
["1"] = "茉莉花茶",
["2"] = "Joja 可乐",
["3"] = "酸味史莱姆",
["4"] = "个人披萨",
["5"] = "芝士玉米片",
["6"] = "鲑鱼汉堡",
["7"] = "冰淇淋三明治",
["8"] = "爆米花",
["9"] = "薯条",
["10"] = "巧克力爆米花",
["11"] = "黑甘草糖",
["12"] = "星形饼干",
["13"] = "大糖球",
["14"] = "盐渍花生",
["15"] = "鹰嘴豆泥小吃包",
["16"] = "羽衣甘蓝汁",
["17"] = "苹果脆片",
["18"] = "意式面包沙拉",
["19"] = "松露爆米花",
["20"] = "卡布奇诺慕斯蛋糕",
["21"] = "Joja 玉米",
["22"] = "星之果实冰糕",
["23"] = "糖冰棍"
}
local movieNamesEn = {
["spring_movie_0"] = "The Brave Little Sapling",
["summer_movie_0"] = "Journey Of The Prairie King: The Motion Picture",
["fall_movie_0"] = "Mysterium",
["winter_movie_0"] = "The Miracle At Coldstar Ranch",
["spring_movie_1"] = "Natural Wonders: Exploring Our Vibrant World",
["summer_movie_1"] = "Wumbus",
["fall_movie_1"] = "It Howls In The Rain",
["winter_movie_1"] = "The Zuzu City Express"
}
local concessionNamesEn = {
["0"] = "Cotton Candy",
["1"] = "Jasmine Tea",
["2"] = "Joja Cola",
["3"] = "Sour Slimes",
["4"] = "Personal Pizza",
["5"] = "Nachos",
["6"] = "Salmon Burger",
["7"] = "Ice Cream Sandwich",
["8"] = "Popcorn",
["9"] = "Fries",
["10"] = "Chocolate Popcorn",
["11"] = "Black Licorice",
["12"] = "Star Cookie",
["13"] = "Rock Candy",
["14"] = "Salted Peanuts",
["15"] = "Hummus Snack Pack",
["16"] = "Kale Smoothie",
["17"] = "Apple Slices",
["18"] = "Panzanella Salad",
["19"] = "Truffle Popcorn",
["20"] = "Cappuccino Mousse Cake",
["21"] = "Joja Corn",
["22"] = "Stardrop Sorbet",
["23"] = "Rock Candy"
}
local function getCharacterName(character)
if not character then return "" end
character = character:gsub("^%l", string.upper)
local chineseName = NPC.getChineseName(character)
if chineseName then return chineseName end
return character
end
local function getMovieTags(movieId)
for _, movie in ipairs(moviesData) do
if movie.Id == movieId then return movie.Tags or {} end
end
return {}
end
local function getConcessionTags(concessionId)
for _, concession in ipairs(concessionsData) do
if concession.Id == concessionId then
return concession.ItemTags or {}
end
end
return {}
end
local function calculateMoviePreference(npcName, movieId)
local movieTags = getMovieTags(movieId)
local npcReactions = nil
for _, npcData in ipairs(moviesReactionsData) do
if npcData.NPCName == npcName then
npcReactions = npcData.Reactions
break
end
end
if not npcReactions then return "like" end
for _, reaction in ipairs(npcReactions) do
for _, tag in ipairs(movieTags) do
if reaction.Tag == tag then return reaction.Response end
end
if reaction.Tag == movieId then return reaction.Response end
end
for _, reaction in ipairs(npcReactions) do
local hasContent = false
for _ in pairs(reaction.Whitelist) do
hasContent = true
break
end
if reaction.Tag == "*" and not hasContent then return reaction.Response end
end
return "like"
end
local function calculateConcessionPreference(npcName, concessionId)
local concessionTags = getConcessionTags(concessionId)
local concessionName = nil
for _, concession in ipairs(concessionsData) do
if concession.Id == concessionId then
concessionName = concession.Name
break
end
end
local npcTastes = nil
local universalTastes = nil
for _, tasteData in ipairs(concessionTastesData) do
if tasteData.Name == npcName then
npcTastes = tasteData
elseif tasteData.Name == "*" then
universalTastes = tasteData
end
end
-- 合并 universalTastes 和 npcTastes,优先采用 npcTastes
local mergedTastes = {
DislikedTags = {},
LovedTags = {},
LikedTags = {}
}
-- 辅助函数:检查表中是否包含值
local function tableContains(tbl, val)
for _, v in ipairs(tbl) do
if v == val then return true end
end
return false
end
-- 先添加 universalTastes
if universalTastes then
for _, tag in ipairs(universalTastes.DislikedTags or {}) do
table.insert(mergedTastes.DislikedTags, tag)
end
for _, tag in ipairs(universalTastes.LovedTags or {}) do
table.insert(mergedTastes.LovedTags, tag)
end
for _, tag in ipairs(universalTastes.LikedTags or {}) do
table.insert(mergedTastes.LikedTags, tag)
end
end
-- 然后添加 npcTastes,覆盖冲突
if npcTastes then
for _, tag in ipairs(npcTastes.DislikedTags or {}) do
-- 从其他列表移除
for i = #mergedTastes.LovedTags, 1, -1 do
if mergedTastes.LovedTags[i] == tag then table.remove(mergedTastes.LovedTags, i) end
end
for i = #mergedTastes.LikedTags, 1, -1 do
if mergedTastes.LikedTags[i] == tag then table.remove(mergedTastes.LikedTags, i) end
end
-- 添加到 DislikedTags 如果不在
if not tableContains(mergedTastes.DislikedTags, tag) then
table.insert(mergedTastes.DislikedTags, tag)
end
end
for _, tag in ipairs(npcTastes.LovedTags or {}) do
for i = #mergedTastes.DislikedTags, 1, -1 do
if mergedTastes.DislikedTags[i] == tag then table.remove(mergedTastes.DislikedTags, i) end
end
for i = #mergedTastes.LikedTags, 1, -1 do
if mergedTastes.LikedTags[i] == tag then table.remove(mergedTastes.LikedTags, i) end
end
if not tableContains(mergedTastes.LovedTags, tag) then
table.insert(mergedTastes.LovedTags, tag)
end
end
for _, tag in ipairs(npcTastes.LikedTags or {}) do
for i = #mergedTastes.DislikedTags, 1, -1 do
if mergedTastes.DislikedTags[i] == tag then table.remove(mergedTastes.DislikedTags, i) end
end
for i = #mergedTastes.LovedTags, 1, -1 do
if mergedTastes.LovedTags[i] == tag then table.remove(mergedTastes.LovedTags, i) end
end
if not tableContains(mergedTastes.LikedTags, tag) then
table.insert(mergedTastes.LikedTags, tag)
end
end
end
local function checkPreference(tastes, tags, concessionName)
if not tastes then return nil end
if concessionName then
for _, disliked in ipairs(tastes.DislikedTags or {}) do
if disliked == concessionName then
return "dislike"
end
end
for _, loved in ipairs(tastes.LovedTags or {}) do
if loved == concessionName then return "love" end
end
for _, liked in ipairs(tastes.LikedTags or {}) do
if liked == concessionName then return "like" end
end
end
for _, tag in ipairs(tags) do
for _, disliked in ipairs(tastes.DislikedTags or {}) do
if disliked == tag then return "dislike" end
end
for _, loved in ipairs(tastes.LovedTags or {}) do
if loved == tag then return "love" end
end
for _, liked in ipairs(tastes.LikedTags or {}) do
if liked == tag then return "like" end
end
end
return nil
end
local preference = checkPreference(mergedTastes, concessionTags, concessionName)
return preference or "like"
end
local function getMovieYearSeason(movieId)
for _, movie in ipairs(moviesData) do
if movie.Id == movieId then
local yearText = ""
local seasonText = ""
if movie.YearRemainder == 0 then
yearText = "第一年"
elseif movie.YearRemainder == 1 then
yearText = "第二年"
else
yearText = "第" .. (movie.YearRemainder + 1) .. "年"
end
if movie.Seasons then
local seasons = {}
for i, season in ipairs(movie.Seasons) do
local cleanSeason = tostring(season):gsub("^%s*(.-)%s*$",
"%1")
if cleanSeason then
table.insert(seasons,
'<br><div style="white-space: nowrap;">' ..
utils.expandTemplate("Season",
{cleanSeason}) ..
'</div>')
end
end
seasonText = table.concat(seasons, "、")
end
return yearText .. seasonText
end
end
return ""
end
function p.getNPCMoviePreferences(frame)
local npcName = frame.args[1] or frame.args.npc
if not npcName then return "<!-- 错误:请提供NPC名称 -->" end
local displayName = npcName
local englishName = npcName
if NPC.getEnglishName(npcName) then
englishName = NPC.getEnglishName(npcName)
else
displayName = getCharacterName(npcName)
end
local loved = {}
local liked = {}
local disliked = {}
for _, movie in ipairs(moviesData) do
local preference = calculateMoviePreference(englishName, movie.Id)
local movieName = movieNames[movie.Id] or movie.Id
local yearSeason = getMovieYearSeason(movie.Id)
local movieDisplayName = movieName .. "(" .. yearSeason .. ")"
if preference == "love" then
table.insert(loved, movieDisplayName)
elseif preference == "like" then
table.insert(liked, movieDisplayName)
elseif preference == "dislike" then
table.insert(disliked, movieDisplayName)
end
end
local result = "=== " .. displayName .. "的电影喜好 ===\n"
if #loved > 0 then
result = result .. "'''最爱:'''" .. table.concat(loved, "、") ..
"\n\n"
end
if #liked > 0 then
result = result .. "'''喜欢:'''" .. table.concat(liked, "、") ..
"\n\n"
end
if #disliked > 0 then
result =
result .. "'''不喜欢:'''" .. table.concat(disliked, "、") ..
"\n\n"
end
return result
end
function p.getNPCConcessionPreferences(frame)
local npcName = frame.args[1] or frame.args.npc
if not npcName then return "<!-- 错误:请提供NPC名称 -->" end
local displayName = npcName
local englishName = npcName
if NPC.getEnglishName(npcName) then
englishName = NPC.getEnglishName(npcName)
else
displayName = getCharacterName(npcName)
end
local loved = {}
local liked = {}
local disliked = {}
for _, concession in ipairs(concessionsData) do
local preference = calculateConcessionPreference(englishName,
concession.Id)
local concessionName = concessionNames[concession.Id] or concession.Name
if preference == "love" then
table.insert(loved, concessionName)
elseif preference == "like" then
table.insert(liked, concessionName)
elseif preference == "dislike" then
table.insert(disliked, concessionName)
end
end
local result = "=== " .. displayName .. "的零食喜好 ===\n"
if #loved > 0 then
result = result .. "'''最爱:'''" .. table.concat(loved, "、") ..
"\n\n"
end
if #liked > 0 then
result = result .. "'''喜欢:'''" .. table.concat(liked, "、") ..
"\n\n"
end
if #disliked > 0 then
result =
result .. "'''不喜欢:'''" .. table.concat(disliked, "、") ..
"\n\n"
end
return result
end
function p.getMovieNPCPreferences(frame)
local movieId = frame.args[1] or frame.args.movie
if not movieId then return "<!-- 错误:请提供电影ID -->" end
local movieName = movieNames[movieId] or movieId
local yearSeason = getMovieYearSeason(movieId)
local loved = {}
local liked = {}
local disliked = {}
local allNPCs = {}
for _, npcData in ipairs(moviesReactionsData) do
table.insert(allNPCs, npcData.NPCName)
end
for _, npcName in ipairs(allNPCs) do
local preference = calculateMoviePreference(npcName, movieId)
if preference == "love" then
table.insert(loved, npcName)
elseif preference == "like" then
table.insert(liked, npcName)
elseif preference == "dislike" then
table.insert(disliked, npcName)
end
end
local result = "=== 《" .. movieName .. "》(" .. yearSeason ..
")的观众喜好 ===\n"
if #loved > 0 then
result = result .. "'''最爱:'''" .. table.concat(loved, "、") ..
"\n\n"
end
if #liked > 0 then
result = result .. "'''喜欢:'''" .. table.concat(liked, "、") ..
"\n\n"
end
if #disliked > 0 then
result =
result .. "'''不喜欢:'''" .. table.concat(disliked, "、") ..
"\n\n"
end
return result
end
function p.getConcessionNPCPreferences(frame)
local concessionId = frame.args[1] or frame.args.concession
if not concessionId then return "<!-- 错误:请提供零食ID -->" end
local concessionName = concessionNames[concessionId] or concessionId
local loved = {}
local liked = {}
local disliked = {}
local allNPCs = {}
for _, tasteData in ipairs(concessionTastesData) do
if tasteData.Name ~= "*" then
table.insert(allNPCs, tasteData.Name)
end
end
for _, npcName in ipairs(allNPCs) do
local preference = calculateConcessionPreference(npcName, concessionId)
if preference == "love" then
table.insert(loved, npcName)
elseif preference == "like" then
table.insert(liked, npcName)
elseif preference == "dislike" then
table.insert(disliked, npcName)
end
end
local result = "=== " .. concessionName .. "的受欢迎程度 ===\n"
if #loved > 0 then
result = result .. "'''最爱:'''" .. table.concat(loved, "、") ..
"\n\n"
end
if #liked > 0 then
result = result .. "'''喜欢:'''" .. table.concat(liked, "、") ..
"\n\n"
end
if #disliked > 0 then
result =
result .. "'''不喜欢:'''" .. table.concat(disliked, "、") ..
"\n\n"
end
return result
end
function p.getConcessionPrice(frame)
local concessionId = frame.args[1] or frame.args.concession
if not concessionId then return "<!-- 错误:请提供零食ID -->" end
for _, concession in ipairs(concessionsData) do
if concession.Id == concessionId then
local concessionName = concessionNames[concessionId] or
concession.Name
return concessionName .. "的价格:" ..
utils.expandTemplate("price", {concession.Price})
end
end
return "<!-- 错误:未找到零食ID " .. concessionId .. " -->"
end
function p.getMovieCranePrizes(frame)
local movieId = frame.args[1] or frame.args.movie
if not movieId then return "<!-- 错误:请提供电影ID -->" end
local movieName = movieNames[movieId] or movieId
local yearSeason = getMovieYearSeason(movieId)
for _, movie in ipairs(moviesData) do
if movie.Id == movieId then
local result = "=== 《" .. movieName .. "》(" .. yearSeason ..
")上映期间的娃娃机特殊物品 ===\n"
if movie.CranePrizes and #movie.CranePrizes > 0 then
for _, prize in ipairs(movie.CranePrizes) do
local rarity = ""
if prize.Rarity == 1 then
rarity = "(普通)"
elseif prize.Rarity == 2 then
rarity = "(稀有)"
elseif prize.Rarity == 3 then
rarity = "(豪华)"
end
local itemId = prize.ItemId
if itemId and itemId:match("%(F%)(%d+)") then
local furnitureId = itemId:match("%(F%)(%d+)")
result = result .. "* " ..
utils.expandTemplate("Name", {furnitureId}) ..
rarity .. "\n"
else
result =
result .. "* " .. (prize.Id or "未知物品") ..
rarity .. "\n"
end
end
else
result = result ..
"该电影上映期间没有特殊物品。\n"
end
return result
end
end
return "<!-- 错误:未找到电影ID " .. movieId .. " -->"
end
local function extractScriptDialogue(script)
if not script then return nil end
local messageDialogue = script:match('/message%s+"([^"]+)"')
if messageDialogue then return messageDialogue end
local complexMessage = script:match('/emote%s+[^/]+/message%s+"([^"]+)"')
if complexMessage then return complexMessage end
return nil
end
local function getMovieDialogueTexts(translationKey, script)
local textDialogues = {}
local scriptDialogues = {}
local processedKeys = {}
if translationKey and translationKey ~= "" then
if dialogueData then
local key = translationKey:match(
"%[LocalizedText Strings\\MovieReactions:(.+)%]")
if key and dialogueData.MovieReactions then
processedKeys[key] = true
if dialogueData.MovieReactions[key] then
table.insert(textDialogues, dialogueData.MovieReactions[key])
end
else
table.insert(textDialogues, translationKey)
end
else
table.insert(textDialogues, translationKey)
end
end
if script then
local scriptDialogue = extractScriptDialogue(script)
if scriptDialogue then
if scriptDialogue:match("%[LocalizedText") then
local scriptKey = scriptDialogue:match(
"%[LocalizedText Strings\\MovieReactions:(.+)%]")
if scriptKey and not processedKeys[scriptKey] then
local scriptTexts = getMovieDialogueTexts(scriptDialogue,
nil)
for _, text in ipairs(scriptTexts.textDialogues or {}) do
table.insert(scriptDialogues, text)
end
end
else
table.insert(scriptDialogues, scriptDialogue)
end
end
end
return {textDialogues = textDialogues, scriptDialogues = scriptDialogues}
end
local function cleanMovieText(text)
if not text or type(text) ~= "string" then return text, nil end
local emotion = nil
emotion = text:match("%$([hslua])$")
if not emotion then
emotion = text:match("%$(%d+)$")
if emotion then
local num = tonumber(emotion)
if not num or num < 0 or num > 15 then emotion = nil end
end
end
text = text:gsub("%$[hslua]$", "")
text = text:gsub("%$%d+$", "")
text = text:gsub("%$%{([^%^}]+)%^([^}]+)%}", "%1/%2")
text = text:gsub("\\\"", "\"")
text = text:gsub("\\n", "\n")
text = text:gsub("@", '<span class="player-name">玩家名</span>')
local has0 = text:find("{0}") ~= nil
local has2 = text:find("{2}") ~= nil
if has0 and has2 then
text = text:gsub("{0}", '<span class="player-name">电影名称</span>')
text = text:gsub("{2}", '<span class="player-name">人物名称</span>')
elseif has0 then
text = text:gsub("{0}", '<span class="player-name">_____</span>')
elseif has2 then
text = text:gsub("{2}", '<span class="player-name">_____</span>')
end
text = text:gsub("%%noturn",
'<span class="trigger-chance">(不转身)</span>')
text = text:gsub("%$[hbslaue]", "")
text = text:gsub("%$%d+", "")
text = text:gsub("##", "\n")
text = text:gsub("%s*%[%s*%d+%s*%]",
'<span class="refuse-item">(给予物品)</span>')
if text:match("^[^。!?]*在[^。!?]*。?%s*$") then
text = '<span class="action-description">' .. text .. '</span>'
end
if emotion then
if emotion == "h" then
emotion = "1"
elseif emotion == "s" then
emotion = "2"
elseif emotion == "u" then
emotion = "3"
elseif emotion == "l" then
emotion = "4"
elseif emotion == "a" then
emotion = "5"
end
end
return text, emotion
end
local function processMovieGenderDialogue(text, characterName, isFromScript)
if not text or type(text) ~= "string" then return text end
local hasInlineGender = text:find("%$%{[^%^}]+%^[^}]+%}%$")
if hasInlineGender then
local maleText = text:gsub("%$%{([^%^}]+)%^[^}]+%}%$", "%1")
local femaleText = text:gsub("%$%{[^%^}]+%^([^}]+)%}%$", "%1")
local maleResult = createMovieQuote(maleText ..
'<span class="trigger-chance">(男)</span>',
characterName, isFromScript)
local femaleResult = createMovieQuote(femaleText ..
'<span class="trigger-chance">(女)</span>',
characterName, isFromScript)
return maleResult .. "\n" .. femaleResult
end
if not text:find("%^") then
return createMovieQuote(text, characterName, isFromScript)
end
local caretPos = text:find("%^")
local beforeCaret = text:sub(1, caretPos - 1)
local afterCaret = text:sub(caretPos + 1)
local maleText = beforeCaret:match("^%s*(.-)%s*$") or ""
local femaleText = afterCaret:match("^%s*(.-)%s*$") or ""
local maleResult = createMovieQuote(maleText ..
'<span class="trigger-chance">(男)</span>',
characterName, isFromScript)
local femaleResult = createMovieQuote(femaleText ..
'<span class="trigger-chance">(女)</span>',
characterName, isFromScript)
return maleResult .. "\n" .. femaleResult
end
-- 处理单个对话片段(不包含分隔符)
local createMovieQuoteSingle = function(text, characterName, isFromScript)
if not text then return "" end
local cleanedText, emotion = cleanMovieText(text)
if isFromScript then
return utils.expandTemplate("Say", {"voiceover", cleanedText})
end
local chineseName = getCharacterName(characterName)
local portrait = characterName
if portrait then portrait = portrait:lower() end
if not emotion and characterName then emotion = "0" end
if emotion and portrait then
return utils.expandTemplate("Say", {
"left", chineseName, cleanedText, emotion, portrait
})
else
return utils.expandTemplate("Say", {"left", chineseName, cleanedText})
end
end
-- 处理包含分隔符的电影对话文本,分割为独立对话
local function processMovieDialogueWithSeparators(text, characterName, isFromScript)
if not text or type(text) ~= "string" then
return ""
end
-- 分割对话:#$b# 和 #$e# 都作为分隔符
local parts = {}
local currentPart = ""
local i = 1
while i <= #text do
if text:sub(i, i + 3) == "#$b#" then
if currentPart ~= "" then
table.insert(parts, currentPart)
currentPart = ""
end
i = i + 4
elseif text:sub(i, i + 3) == "#$e#" then
if currentPart ~= "" then
table.insert(parts, currentPart)
currentPart = ""
end
i = i + 4
else
currentPart = currentPart .. text:sub(i, i)
i = i + 1
end
end
-- 添加最后一部分
if currentPart ~= "" then
table.insert(parts, currentPart)
end
-- 如果没有分隔符,直接处理整个文本
if #parts <= 1 then
return createMovieQuoteSingle(text, characterName, isFromScript)
end
-- 处理每个独立的对话片段
local results = {}
for _, part in ipairs(parts) do
local trimmed = part:match("^%s*(.-)%s*$")
if trimmed and trimmed ~= "" then
-- 检查这个片段是否包含性别分支
if trimmed:find("%^") or trimmed:find("%$%{[^%^}]+%^[^}]+%}%$") then
-- 有性别分支,调用性别处理函数
table.insert(results, processMovieGenderDialogue(trimmed, characterName, isFromScript))
else
-- 没有性别分支,直接处理
table.insert(results, createMovieQuoteSingle(trimmed, characterName, isFromScript))
end
end
end
return table.concat(results, "\n")
end
createMovieQuote = function(text, characterName, isFromScript)
if not text then return "" end
-- 检查是否包含分隔符
if text:find("#%$[be]#") then
return processMovieDialogueWithSeparators(text, characterName, isFromScript)
else
return createMovieQuoteSingle(text, characterName, isFromScript)
end
end
createMovieQuotes = function(dialogues, characterName, isFromScript)
if not dialogues or #dialogues == 0 then return "" end
local result = {}
for _, dialogue in ipairs(dialogues) do
if dialogue:find("%^") or dialogue:find("%$%{[^%^}]+%^[^}]+%}%$") then
local quote = processMovieGenderDialogue(dialogue, characterName,
isFromScript)
if quote and quote ~= "" then table.insert(result, quote) end
else
local quote =
createMovieQuote(dialogue, characterName, isFromScript)
if quote and quote ~= "" then table.insert(result, quote) end
end
end
return table.concat(result, "\n")
end
local function processDialogueCategory(title, dialogues, englishName)
if not dialogues then return "" end
local dialogueContent = {}
if dialogues.BeforeMovie then
local result = getMovieDialogueTexts(dialogues.BeforeMovie.Text,
dialogues.BeforeMovie.Script)
local allQuotes = {}
if #result.textDialogues > 0 then
table.insert(allQuotes, createMovieQuotes(result.textDialogues,
englishName, false))
end
if #result.scriptDialogues > 0 then
table.insert(allQuotes, createMovieQuotes(result.scriptDialogues,
englishName, true))
end
if #allQuotes > 0 then
table.insert(dialogueContent, table.concat(allQuotes, "\n"))
end
end
if dialogues.DuringMovie then
local result = getMovieDialogueTexts(dialogues.DuringMovie.Text,
dialogues.DuringMovie.Script)
local allQuotes = {}
if #result.textDialogues > 0 then
table.insert(allQuotes, createMovieQuotes(result.textDialogues,
englishName, false))
end
if #result.scriptDialogues > 0 then
table.insert(allQuotes, createMovieQuotes(result.scriptDialogues,
englishName, true))
end
if #allQuotes > 0 then
table.insert(dialogueContent, table.concat(allQuotes, "\n"))
end
end
if dialogues.AfterMovie then
local result = getMovieDialogueTexts(dialogues.AfterMovie.Text,
dialogues.AfterMovie.Script)
local allQuotes = {}
if #result.textDialogues > 0 then
table.insert(allQuotes, createMovieQuotes(result.textDialogues,
englishName, false))
end
if #result.scriptDialogues > 0 then
table.insert(allQuotes, createMovieQuotes(result.scriptDialogues,
englishName, true))
end
if #allQuotes > 0 then
table.insert(dialogueContent, table.concat(allQuotes, "\n"))
end
end
if #dialogueContent > 0 then
local eventLabelContent =
'<div class="event-label show" style="display: block;">\n' ..
table.concat(dialogueContent, "\n") .. '\n</div>'
return utils.expandTemplate("Collapse",
{title, content = eventLabelContent})
end
return ""
end
function p.getNPCMovieDialogue(frame)
local npcName = frame.args[1] or frame.args.npc
if not npcName then return "<!-- 错误:请提供NPC名称 -->" end
local displayName = npcName
local englishName = npcName
if NPC.getEnglishName(npcName) then
englishName = NPC.getEnglishName(npcName)
else
displayName = getCharacterName(npcName)
end
-- 收集电影邀约对话
local inviteDialogues = {}
-- 1. 从NPC个人数据中获取MovieInvitation
if dialogueData and dialogueData[englishName] and dialogueData[englishName].MovieInvitation then
table.insert(inviteDialogues, {
type = "regular",
dialogue = dialogueData[englishName].MovieInvitation
})
end
-- 2. 从Strings/Characters获取婚后对话
if dialogueData and dialogueData["Strings/Characters"] then
local stringsData = dialogueData["Strings/Characters"]
local spouseKey = "MovieInvite_Spouse_" .. englishName
if stringsData[spouseKey] then
table.insert(inviteDialogues, {
type = "spouse",
dialogue = stringsData[spouseKey]
})
end
-- 3. 获取通用邀约对话(如果没有个人对话且没有婚后对话)
local hasRegularDialogue = false
for _, invite in ipairs(inviteDialogues) do
if invite.type == "regular" then
hasRegularDialogue = true
break
end
end
if not hasRegularDialogue then
-- 定义 child 和 rude NPC 列表
local childNPCs = {"Vincent", "Jas"}
local rudeNPCs = {"Abigail", "Alex", "Clint", "George", "Haley", "Pam", "Sebastian", "Shane", "Wizard"}
-- 检查是否为 child
local isChild = false
for _, child in ipairs(childNPCs) do
if englishName == child then
isChild = true
break
end
end
-- 检查是否为 rude
local isRude = false
for _, rude in ipairs(rudeNPCs) do
if englishName == rude then
isRude = true
break
end
end
-- 按优先级查找通用对话
local fallbackKeys = {
"MovieInvite_Invited_" .. englishName
}
-- 根据 NPC 类型添加相应的回退对话
if isChild then
table.insert(fallbackKeys, "MovieInvite_Invited_Child")
elseif isRude then
table.insert(fallbackKeys, "MovieInvite_Invited_Rude")
else
table.insert(fallbackKeys, "MovieInvite_Invited")
end
for _, key in ipairs(fallbackKeys) do
if stringsData[key] then
table.insert(inviteDialogues, {
type = "regular",
dialogue = stringsData[key]
})
break
end
end
end
end
local result = ""
-- 处理邀约对话
if #inviteDialogues > 0 then
local inviteContent = {}
local regularDialogues = {}
local spouseDialogues = {}
for _, invite in ipairs(inviteDialogues) do
if invite.type == "spouse" then
table.insert(spouseDialogues, invite.dialogue)
else
table.insert(regularDialogues, invite.dialogue)
end
end
-- 先输出常规对话
if #regularDialogues > 0 then
for _, dialogue in ipairs(regularDialogues) do
local quote = createMovieQuote(dialogue, englishName, false)
if quote and quote ~= "" then
table.insert(inviteContent, quote)
end
end
end
-- 再输出婚后对话
if #spouseDialogues > 0 then
table.insert(inviteContent, "'''婚后'''")
for _, dialogue in ipairs(spouseDialogues) do
local quote = createMovieQuote(dialogue, englishName, false)
if quote and quote ~= "" then
table.insert(inviteContent, quote)
end
end
end
if #inviteContent > 0 then
local eventLabelContent =
'<div class="event-label show" style="display: block;">\n' ..
table.concat(inviteContent, "\n") .. '\n</div>'
result = result .. utils.expandTemplate("Collapse",
{"发起邀约", content = eventLabelContent}) .. "\n"
end
end
local npcReactions = nil
for _, npcData in ipairs(moviesReactionsData) do
if npcData.NPCName == englishName then
npcReactions = npcData.Reactions
break
end
end
if not npcReactions then
return result .. "<!-- 错误:未找到NPC " .. displayName ..
" 的电影反应数据 -->"
end
local movieDialogues = {}
local reactionDialogues = {}
local genreDialogues = {}
local generalDialogues = {}
for _, reaction in ipairs(npcReactions) do
if reaction.SpecialResponses then
local tag = reaction.Tag
local movieName = movieNames[tag]
if movieName then
movieDialogues[movieName] = reaction.SpecialResponses
elseif tag == "*" then
generalDialogues["通用"] = reaction.SpecialResponses
elseif tag == "love" or tag == "like" or tag == "dislike" or tag ==
"seen_love" or tag == "seen_like" or tag == "seen_dislike" then
local categoryTitle = ""
if tag == "love" or tag == "seen_love" then
categoryTitle = "最爱的电影"
elseif tag == "dislike" or tag == "seen_dislike" then
categoryTitle = "不喜欢的电影"
elseif tag == "like" or tag == "seen_like" then
categoryTitle = "喜欢的电影"
end
if tag:match("^seen_") then
categoryTitle = categoryTitle .. "(已看过)"
end
reactionDialogues[categoryTitle] = reaction.SpecialResponses
else
local categoryTitle = ""
if tag == "family" then
categoryTitle = "家庭类电影"
elseif tag == "comedy" then
categoryTitle = "喜剧类电影"
elseif tag == "horror" then
categoryTitle = "恐怖类电影"
elseif tag == "action" then
categoryTitle = "动作类电影"
elseif tag == "sci-fi" then
categoryTitle = "科幻类电影"
elseif tag == "classic" then
categoryTitle = "经典类电影"
elseif tag == "romance" then
categoryTitle = "浪漫类电影"
elseif tag == "documentary" then
categoryTitle = "纪录片类电影"
elseif tag == "art" then
categoryTitle = "艺术类电影"
else
categoryTitle = tag .. "类电影"
end
genreDialogues[categoryTitle] = reaction.SpecialResponses
end
end
end
local outputTemplates = {}
for movieName, dialogues in pairs(movieDialogues) do
local collapseTemplate = processDialogueCategory(movieName, dialogues,
englishName)
if collapseTemplate ~= "" then
table.insert(outputTemplates, collapseTemplate)
end
end
for categoryTitle, dialogues in pairs(genreDialogues) do
local collapseTemplate = processDialogueCategory(categoryTitle,
dialogues, englishName)
if collapseTemplate ~= "" then
table.insert(outputTemplates, collapseTemplate)
end
end
local reactionOrder = {
"最爱的电影", "最爱的电影(已看过)", "喜欢的电影",
"喜欢的电影(已看过)", "不喜欢的电影",
"不喜欢的电影(已看过)"
}
for _, categoryTitle in ipairs(reactionOrder) do
if reactionDialogues[categoryTitle] then
local collapseTemplate = processDialogueCategory(categoryTitle,
reactionDialogues[categoryTitle],
englishName)
if collapseTemplate ~= "" then
table.insert(outputTemplates, collapseTemplate)
end
end
end
for dialogueType, dialogues in pairs(generalDialogues) do
local collapseTemplate = processDialogueCategory("通用及特殊",
dialogues, englishName)
if collapseTemplate ~= "" then
table.insert(outputTemplates, collapseTemplate)
end
end
if #outputTemplates > 0 then
result = result .. "\n" .. table.concat(outputTemplates, "\n\n")
end
return result
end
function p.getAllMoviesInfo(frame)
local result = "=== 所有电影信息 ===\n"
for _, movie in ipairs(moviesData) do
local movieName = movieNames[movie.Id] or movie.Id
local yearSeason = getMovieYearSeason(movie.Id)
result = result .. "\n==== " .. movieName .. "(" .. yearSeason ..
") ====\n"
result = result .. "* '''ID:'''" .. movie.Id .. "\n"
result = result .. "* '''季节:'''" ..
table.concat(movie.Seasons or {}, "、") .. "\n"
if movie.YearModulus and movie.YearRemainder then
local yearDesc = ""
if movie.YearModulus == 2 then
if movie.YearRemainder == 0 then
yearDesc = "第一年"
else
yearDesc = "第二年"
end
else
yearDesc = "每" .. movie.YearModulus .. "年,余数" ..
movie.YearRemainder
end
result = result .. "* '''年份:'''" .. yearDesc .. "\n"
end
if movie.Tags and #movie.Tags > 0 then
local tagNames = {}
for _, tag in ipairs(movie.Tags) do
local tagName = tag
if tag == "family" then
tagName = "家庭"
elseif tag == "comedy" then
tagName = "喜剧"
elseif tag == "horror" then
tagName = "恐怖"
elseif tag == "action" then
tagName = "动作"
elseif tag == "sci-fi" then
tagName = "科幻"
elseif tag == "classic" then
tagName = "经典"
elseif tag == "romance" then
tagName = "浪漫"
elseif tag == "documentary" then
tagName = "纪录片"
elseif tag == "art" then
tagName = "艺术"
end
table.insert(tagNames, tagName)
end
result = result .. "* '''类型:'''" ..
table.concat(tagNames, "、") .. "\n"
end
if movie.CranePrizes and #movie.CranePrizes > 0 then
result = result .. "* '''娃娃机特殊物品:'''" ..
#movie.CranePrizes .. "种\n"
end
end
return result
end
function p.getNPCCinemaTable(frame)
local npcName = frame.args[1] or frame.args.npc
if not npcName then return "<!-- 错误:请提供NPC名称 -->" end
local displayName = npcName
local englishName = npcName
if NPC.getEnglishName(npcName) then
englishName = NPC.getEnglishName(npcName)
else
displayName = getCharacterName(npcName)
end
local moviePreferences = {loved = {}, liked = {}, disliked = {}}
for _, movie in ipairs(moviesData) do
local movieName = movieNames[movie.Id] or movie.Id
local preference = calculateMoviePreference(englishName, movie.Id)
local yearSeason = getMovieYearSeason(movie.Id)
local movieDisplayName = movieName .. "(" .. yearSeason .. ")"
local movieEnglishName = movieNamesEn[movie.Id]:gsub(':', '')
local movieImageName = ""
if movieEnglishName then
movieImageName = "'" .. movieEnglishName .. "'.png"
end
local movieEntry = {
image = movieImageName,
name = movieName,
season = yearSeason,
yearRemainder = movie.YearRemainder or 0,
seasons = movie.Seasons or {}
}
if preference == "love" then
table.insert(moviePreferences.loved, movieEntry)
elseif preference == "like" then
table.insert(moviePreferences.liked, movieEntry)
elseif preference == "dislike" then
table.insert(moviePreferences.disliked, movieEntry)
end
end
local function sortMovies(movieList)
table.sort(movieList, function(a, b)
if a.yearRemainder ~= b.yearRemainder then
return a.yearRemainder < b.yearRemainder
end
local seasonOrder = {
spring = 0,
summer = 1,
fall = 2,
winter = 3,
Spring = 0,
Summer = 1,
Fall = 2,
Winter = 3
}
local aMinSeason = 4
local bMinSeason = 4
for _, season in ipairs(a.seasons) do
local seasonValue = seasonOrder[season]
if seasonValue and seasonValue < aMinSeason then
aMinSeason = seasonValue
end
end
for _, season in ipairs(b.seasons) do
local seasonValue = seasonOrder[season]
if seasonValue and seasonValue < bMinSeason then
bMinSeason = seasonValue
end
end
if aMinSeason == bMinSeason then return a.name < b.name end
return aMinSeason < bMinSeason
end)
end
sortMovies(moviePreferences.loved)
sortMovies(moviePreferences.liked)
sortMovies(moviePreferences.disliked)
local concessionPreferences = {loved = {}, liked = {}, disliked = {}}
for _, concession in ipairs(concessionsData) do
local preference = calculateConcessionPreference(englishName,
concession.Id)
local concessionName = concessionNames[concession.Id] or concession.Name
local concessionImageName = concession.Name .. ".png"
if concession.Name == "Joja Cola" then
concessionImageName = "Joja Cola (large).png"
end
local concessionEntry = {
image = concessionImageName,
name = concessionName
}
if preference == "love" then
table.insert(concessionPreferences.loved, concessionEntry)
elseif preference == "like" then
table.insert(concessionPreferences.liked, concessionEntry)
elseif preference == "dislike" then
table.insert(concessionPreferences.disliked, concessionEntry)
end
end
local movieTableHTML =
'<table class="wikitable" style="margin: 0; margin-top: 1em;">\n'
if #moviePreferences.loved > 0 then
movieTableHTML = movieTableHTML ..
'<tr><th colspan="2">最爱 <span style="font-size:smaller;">+200</span></th></tr>\n'
for _, movie in ipairs(moviePreferences.loved) do
movieTableHTML =
movieTableHTML .. '<tr><td>[[File:' .. movie.image ..
'|24px|link=]] ' .. movie.name ..
'</td><td style="text-align: center; padding: 2px 16px;">' ..
movie.season .. '</td></tr>\n'
end
end
if #moviePreferences.liked > 0 then
movieTableHTML = movieTableHTML ..
'<tr><th colspan="2">喜欢 <span style="font-size:smaller;">+100</span></th></tr>\n'
for _, movie in ipairs(moviePreferences.liked) do
movieTableHTML =
movieTableHTML .. '<tr><td>[[File:' .. movie.image ..
'|24px|link=]] ' .. movie.name ..
'</td><td style="text-align: center; padding: 2px 16px;">' ..
movie.season .. '</td></tr>\n'
end
end
if #moviePreferences.disliked > 0 then
movieTableHTML = movieTableHTML ..
'<tr><th colspan="2">不喜欢<span style="font-size:smaller;"></span></th></tr>\n'
for _, movie in ipairs(moviePreferences.disliked) do
movieTableHTML =
movieTableHTML .. '<tr><td>[[File:' .. movie.image ..
'|24px|link=]] ' .. movie.name ..
'</td><td style="text-align: center; padding: 2px 16px;">' ..
movie.season .. '</td></tr>\n'
end
end
movieTableHTML = movieTableHTML .. '</table>'
local lovedItems = {}
local likedItems = {}
local dislikedItems = {}
for i, concession in ipairs(concessionPreferences.loved) do
table.insert(lovedItems, '[[File:' .. concession.image ..
'|24px|link=]] ' .. concession.name .. '')
end
for i, concession in ipairs(concessionPreferences.liked) do
table.insert(likedItems, '[[File:' .. concession.image ..
'|24px|link=]] ' .. concession.name .. '')
end
for i, concession in ipairs(concessionPreferences.disliked) do
table.insert(dislikedItems, '[[File:' .. concession.image ..
'|24px|link=]] ' .. concession.name .. '')
end
local concessionTableHTML =
'<table class="wikitable" style="margin: 0; margin-top: 1em;">\n'
local likedCount = #likedItems
local dislikedCount = #dislikedItems
local leftBottomTitle, leftBottomItems, leftBottomIcon, leftBottomScore
local rightTitle, rightItems, rightIcon, rightScore
if likedCount <= dislikedCount then
leftBottomTitle = "喜欢"
leftBottomItems = likedItems
leftBottomIcon = "ConcessionLike.png"
leftBottomScore = "+25"
rightTitle = "不喜欢"
rightItems = dislikedItems
rightIcon = "ConcessionDislike.png"
rightScore = ""
else
leftBottomTitle = "不喜欢"
leftBottomItems = dislikedItems
leftBottomIcon = "ConcessionDislike.png"
leftBottomScore = ""
rightTitle = "喜欢"
rightItems = likedItems
rightIcon = "ConcessionLike.png"
rightScore = "+25"
end
concessionTableHTML = concessionTableHTML .. '<tr>\n'
concessionTableHTML = concessionTableHTML ..
'<th>[[File:ConcessionLove.png|24px|link=]] 最爱 <span style="font-size:smaller;">+50</span></th>\n'
concessionTableHTML = concessionTableHTML ..
'<th rowspan="1" style="vertical-align: top;">[[File:' ..
rightIcon .. '|24px|link=]] ' .. rightTitle ..
' <span style="font-size:smaller;">' .. rightScore ..
'</span></th>\n'
concessionTableHTML = concessionTableHTML .. '</tr>\n'
concessionTableHTML = concessionTableHTML ..
'<tr style="vertical-align: top;">\n'
concessionTableHTML = concessionTableHTML ..
'<td style="padding: 4px 6px;">' ..
table.concat(lovedItems, '<br>') .. '</td>\n'
concessionTableHTML = concessionTableHTML ..
'<td rowspan="3" style="padding: 4px 6px; vertical-align: top;">' ..
table.concat(rightItems, '<br>') .. '</td>\n'
concessionTableHTML = concessionTableHTML .. '</tr>\n'
concessionTableHTML = concessionTableHTML .. '<tr>\n'
concessionTableHTML = concessionTableHTML ..
'<th style="height: 30px;">[[File:' ..
leftBottomIcon .. '|24px|link=]] ' ..
leftBottomTitle ..
' <span style="font-size:smaller;">' ..
leftBottomScore .. '</span></th>\n'
concessionTableHTML = concessionTableHTML .. '</tr>\n'
concessionTableHTML = concessionTableHTML ..
'<tr style="vertical-align: top;">\n'
concessionTableHTML = concessionTableHTML ..
'<td style="padding: 4px 6px;">' ..
table.concat(leftBottomItems, '<br>') .. '</td>\n'
concessionTableHTML = concessionTableHTML .. '</tr>\n'
concessionTableHTML = concessionTableHTML .. '</table>'
local cinemaTableHTML =
'<div style="display: flex; flex-wrap: wrap; gap: 16px;">\n'
cinemaTableHTML = cinemaTableHTML .. '<div>\n' .. movieTableHTML ..
'\n</div>\n'
cinemaTableHTML = cinemaTableHTML .. '<div>\n' .. concessionTableHTML ..
'\n</div>\n'
cinemaTableHTML = cinemaTableHTML .. '</div>'
return cinemaTableHTML
end
return p

沪公网安备 31011002002714 号