欢迎大家来到沙石镇时光中文维基!本站编辑权限开放,欢迎加入中文维基 QQ 群「沙海时光」:372816689
目前正在进行全站数据更新,期间可能会存在显示异常的问题。
模块:Gift
注意
目前该页面的代码逻辑与英维有一定差异,待更新。
由于该模块已被广泛使用,更新代码需要完全调试好确定无误再操作。
Functions
Giftable
If the first parameter is empty, it will use {{PAGENAME}}.
| Source | Result |
|---|---|
{{#invoke:Gift|Giftable|驼牛奶}}
|
1 |
{{#invoke:Gift|Giftable|妮雅的香包}}
|
(empty) |
{{#invoke:Gift|Giftable|驼牛奶|yes|no}}
|
yes |
{{#invoke:Gift|Giftable|妮雅的香包|1|0}}
|
0 |
ItemRelationshipTableContent
Used in Template:Gifted_item.
Usually you only to use {{gifted item|驼牛奶}}
Source:
{|class="prettytable" style="text-align:center;"
|-
!style="width:18%;"|{{i|Gifting|Social gift|size=50px}}
![[Character]]s
|-
{{#invoke:Gift|ItemRelationshipTableContent|驼牛奶}}
|}
Result:
| |
人物 |
|---|---|
| | |
| | |
| | |
| |
How to update data
See Module:AssetItemPrototypeItem and Module:ItemId.
local Helper = require("Module:Helper")
local ItemHelper = require("Module:ItemHelper")
local ItemModule = require("Module:Item")
local ImageUnifier = require("Module:ImageUnifier")
local cache = require "mw.ext.LuaCache"
local NpcProtoData = require("Module:NpcProtoData")
local GiftData = Helper.LazyLoad("Module:AssetSendGiftDataGift")
local GiftItem = Helper.LazyLoad("Module:AssetGiftItemDataGiftItem")
local ItemId = Helper.LazyLoad("Module:ItemId")
local AssetNpcProtoDatas = Helper.LazyLoad("Module:AssetNpcProtoDatas")
local AssetItemChinese = Helper.LoadAsset("Module:AssetItemChinese")
local KEY_PREFIX = "Module:Gift"
local EXP_TIME = 172800
local favorLevels = {
"Excellent",
"Like",
"Neutral",
"Dislike",
"Hate",
"Refuse"
}
local qualityNames = {
green = 1,
blue = 2,
purple = 3,
outstanding = 1,
perfect = 2,
rare = 3
}
local specialGifts = {
[ItemId["道歉小熊"]] = true,
[ItemId["枯树枝"]] = true,
[ItemId["同心结"]] = true,
[ItemId["聚会邀请函"]] = true
}
local ChoiceType = {
None = -1,
Leave = 0,
Talk = 1,
Gift = 2,
BranchMissionSubmit = 3,
MainMissionSubmit = 4,
Research = 5,
PK = 6,
Play = 7,
Date = 8,
CancelPlay = 9,
CancelDate = 10,
Interaction = 11,
Photo = 12,
BranchMissionReceive = 13,
MainMissionReceive = 14,
ResetProficiencyPoint = 15,
AnimalCardFight = 16,
OpenStore = 17,
InquiryCooking = 18,
Interactive = 19,
EG_None = 256,
EG_Chat = 257,
EG_Stop = 258,
EG_Parise = 259,
EG_CasualTalk = 260,
EG_AskWork = 261,
EG_AskLike = 262,
EG_Eat = 263,
EG_HandInHand = 264,
EG_Waist = 265,
EG_Sleep = 266,
EG_AskPast = 267,
CustomStart = 1000,
CustomType1 = 1000,
CustomType2 = 1001,
CustomType3 = 1002,
CustomType4 = 1003,
CustomEnd = 1004,
CustomType5 = 1004,
MagicMirror_Hire = 2000,
MagicMirror_Chip = 2001,
MagicMirror_Weather = 2002,
MagicMirror_Cosmetic = 2003,
RidableStay = 100000000,
RidableHome = 100000001,
RidableFollow = 100000002,
RidableView = 100000003,
RidableInteractive = 100000004,
Pet_Recruit = 200000000,
Pet_Default = 200000001,
Pet_Dispatch = 200000002,
Pet_Disport = 200000003,
Pet_Follow = 200000004
}
-- APIs Part --
local p = {}
p.Giftable = function(frame)
local hash = Helper.HashArgs(frame.args)
local cacheKey = KEY_PREFIX .. "Giftable" .. hash
if (cache.get(cacheKey)) then
local result = cache.get(cacheKey)
return result
end
local args = parseArgs(frame)
local yes = frame.args[2]
if yes == nil or yes == "" then
yes = "1"
end
local no = frame.args[3]
if no == nil or no == "" then
no = ""
end
local result
if GiftItem[args.itemId] == nil then
result = no
else
result = yes
end
cache.set(cacheKey, result, EXP_TIME)
return result
end
p.ItemRelationshipTableContent = function(frame)
local cacheKey = KEY_PREFIX .. "ItemRelationshipTableContent" .. frame.args[1]
if (cache.get(cacheKey)) then
local result = cache.get(cacheKey)
return result
end
local args = parseArgs(frame)
if GiftItem[args.itemId] == nil then
error(args.itemName .. ' ' .. args.itemId .. " is not giftable")
end
local results = getGiftRelationshipForEachNpc(args.itemId, args.quality)
local result = formatItemRelationshipTable(results)
cache.set(cacheKey, result, EXP_TIME)
return result
end
p.CharacterGiftTableContent = function(frame)
local npcName = frame.args.character
if npcName == nil or npcName == "" then
npcName = mw.getCurrentFrame():getParent():getTitle()
end
local rowTemplate = frame.args.row
local npcId = p.getNpcId(npcName)
local cacheKey = KEY_PREFIX .. "CharacterGiftTableContent" .. npcId
local paramater = frame.args.row
if paramater ~= nil and paramater ~= "" then
cacheKey = cacheKey .."|" .. paramater
end
local result = cache.get(cacheKey)
function contains(str, substr)
local pos = string.find(str, substr)
if pos then
return true
else
return false
end
end
if (result) and contains(result, 'gift-list') then
return result
end
local levelItems = {}
for itemId, _ in pairs(GiftItem) do
if ItemHelper.isImplemented(itemId) and not specialGifts[itemId] then
local result = getGiftRelationship(npcId, itemId, ItemHelper.getBaseQuality(itemId))
if result.special then
if levelItems[result.level] == nil then
levelItems[result.level] = {}
end
local itemName = ItemHelper.getName(itemId)
table.insert(levelItems[result.level], {
name = itemName,
value = result.value
})
end
end
end
local rowArgs = {}
for _, level in ipairs(favorLevels) do
local items = levelItems[level] or {}
table.sort(items, function(a, b)
if a.value == b.value then
return a.name < b.name
else
return a.value > b.value
end
end)
local formatItems = Helper.Map(items, function(item)
if item.value > 0 then
return ItemHelper.addIconAndLink(item.name) .. " (+" .. item.value .. ")"
else
return ItemHelper.addIconAndLink(item.name) .. " (" .. item.value .. ")"
end
end)
local itemsStr = table.concat(formatItems, "<br>")
local levelStr = level
if levelStr == "Excellent" then
levelStr = "非常喜欢"
elseif levelStr == "Like" then
levelStr = "喜欢"
elseif levelStr == "Neutral" then
levelStr = "一般"
elseif levelStr == "Dislike" then
levelStr = "不喜欢"
elseif levelStr == "Hate" then
levelStr = "讨厌"
elseif levelStr == "Refuse" then
levelStr = "拒绝"
end
if levelStr ~= "一般" then
table.insert(rowArgs, {
level = levelStr,
items = itemsStr
})
end
end
local rows = Helper.Map(rowArgs, function(args)
return Helper.ExpandTemplate(rowTemplate, args)
end)
local result = table.concat(rows, "\n|-\n")
cache.set(cacheKey, result, EXP_TIME)
return result
end
p.AllGifts = function(frame)
local cacheKey = KEY_PREFIX .. "AllGifts"
if (cache.get(cacheKey)) then
local result = cache.get(cacheKey)
return result
end
local keys = {}
local rows = {}
for name, id in pairs(ItemId) do
if GiftItem[id] ~= nil and ItemHelper.isImplemented(id) and name ~= "party invitation" then
local quality = ItemHelper.getBaseQuality(id)
local item = ItemHelper.addIconAndLink(name)
local baseNeutralValue = tostring(getGiftFavor(id, quality, 0, "Neutral"))
local results = getGiftRelationshipForEachNpc(id, quality)
local notes = formatUniversal(results)
local row = "|-\n|" .. item .. "||" .. baseNeutralValue .. "||" .. notes
local key = ItemHelper.getSortKey(id)
table.insert(keys, key)
rows[key] = row
end
end
table.sort(keys)
local sortedRows = {}
for i, key in ipairs(keys) do
sortedRows[i] = rows[key]
end
local result = table.concat(sortedRows, "\n")
cache.set(cacheKey, result, EXP_TIME)
return result
end
p.characters_table = function()
local ret = "<div class='table-responsive w-auto'>\n"
ret = ret .. "<table class='table prettytable fandom-table sortable w-auto'>\n"
ret = ret .. "<tr>" .. "<th class='align-middle text-center'>Name</th>"
.. "<th class='align-middle text-center'>Birthday</th>"
.. "<th class='align-middle text-center unsortable'>Gift Preferences</th>" .. "</tr>\n"
for npcId, assetNpcProtoData in pairs(AssetNpcProtoDatas) do
if (hasGiftInteractChoice(assetNpcProtoData.interactChoice)) then
local row
local npcName = getText(assetNpcProtoData.nameID)
local cacheKey = KEY_PREFIX .. "characters_table" .. npcId
if (cache.get(cacheKey)) then
row = cache.get(cacheKey)
end
if (row) then
else
row = ""
local season = NpcProtoData.season({
args = {
[1] = npcName
}
})
local birthday = assetNpcProtoData.birthday
local splitBirthday = {}
-- Split the string by the '.' delimiter and add the parts to a table
for part in string.gmatch(birthday, "([^%.]+)") do
table.insert(splitBirthday, part)
end
-- If the second part has only one character, add a leading zero
if #splitBirthday == 2 and #splitBirthday[2] == 1 then
splitBirthday[2] = "0" .. splitBirthday[2]
end
-- Join the parts back together with a '.' separator
birthday = table.concat(splitBirthday, ".")
local levelItems = {}
for itemId, _ in pairs(GiftItem) do
if ItemHelper.isImplemented(itemId) and not specialGifts[itemId] then
local result = getGiftRelationship(npcId, itemId, ItemHelper.getBaseQuality(itemId))
if (result) then
if result.special then
if levelItems[result.level] == nil then
levelItems[result.level] = {}
end
local itemName = ItemHelper.getName(itemId)
table.insert(levelItems[result.level], {
name = itemName,
value = result.value
})
end
end
end
end
local levelItemsCount = 0
for k, v in pairs(levelItems) do
levelItemsCount = levelItemsCount + 1
end
if (levelItems and levelItemsCount >= 1) then
row = row .. "<tr>\n"
row = row .. "<th id='" .. npcName .. "' class='text-center'><div>" .. ImageUnifier.GetImagesMain({
npcName
}, {
link = npcName
}, "large", false) .. "</div><div>[[" .. npcName
.. "]]</div></th><td class='text-center' data-sort-value='" .. birthday
.. "'><div class='m-1'>" .. ImageUnifier.GetImagesMain({
"Season " .. season
}, {
link = "Calendar#" .. season
}, "medium", false)
.. "</div><div class='m-1'>" .. birthday .. "</div>"
.. "</td><td class='align-middle text-center'>"
local rowArgs = {}
for _, level in ipairs(favorLevels) do
local items = levelItems[level] or {}
-- hide Neutrals, and empty Refuse
if (level == "Refuse" and #items <= 0) then
items = nil
elseif (level == "Neutral") then
items = nil
else
end
if (items) then
table.sort(items, function(a, b)
if a.value == b.value then
return a.name < b.name
else
return a.value > b.value
end
end)
local formatItems = Helper.Map(items, function(item)
if item.value > 0 then
return ItemHelper.addIconAndLink(item.name) .. " (+" .. item.value .. ")"
else
return ItemHelper.addIconAndLink(item.name) .. " (" .. item.value .. ")"
end
end)
local itemsStr = table.concat(formatItems, "<br>")
if level == "Excellent" then
table.insert(rowArgs, {
level = "Love",
items = itemsStr
})
else
table.insert(rowArgs, {
level = level,
items = itemsStr
})
end
else
end
end
for i, rowArg in pairs(rowArgs) do
local level = rowArg.level
local items = rowArg.items
local levelIcon
if (level == "Love") then
levelIcon = "非常喜欢"
elseif (level == "Like") then
levelIcon = "喜欢"
elseif (level == "Neutral") then
levelIcon = "喜欢"
elseif (level == "Dislike") then
levelIcon = "不喜欢"
elseif (level == "Hate") then
levelIcon = "讨厌"
elseif (level == "Refuse") then
levelIcon = "不喜欢"
end
if (i == 1) then
else
row = row .. "<hr class='m-1' style='border:0px solid; border-top:1px solid #f1cf6280;'>\n"
end
row = row .. "<div class='row'><div class='col-1 fw-bold m-1'><div>\n"
.. ImageUnifier.GetImagesMain({
levelIcon
}, {
link = ""
}, "small", false) .. "</div><div>" .. level
.. "</div></div><div class='col text-start m-1' style='-moz-column-count:2;-webkit-column-count:2;'>\n"
row = row .. items .. "\n"
row = row .. "</div></div>\n"
end
row = row .. "</td>\n"
row = row .. "</tr>\n"
cache.set(cacheKey, row, EXP_TIME)
else
end
end
ret = ret .. row .. "\n"
end
end
ret = ret .. "</table>\n"
ret = ret .. "</div>\n"
return ret
end
-- Formatting Part --
function parseArgs(frame)
local args = {}
if frame.args[1] and frame.args[1] ~= "" then
args.itemName = frame.args[1]
else
args.itemName = frame:getParent():getTitle()
end
args.itemId = ItemHelper.getId(args.itemName)
if args.itemId == nil then
error("Cannot find item " .. args.itemName)
end
local hasArg = {}
for key, value in pairs(frame.args) do
if key ~= 1 then
hasArg[value:lower()] = true
end
end
for name, value in pairs(qualityNames) do
if hasArg[name] then
args.quality = value
end
end
return args
end
function formatItemRelationshipTable(results)
local levelOrder = {
Excellent = 1,
Like = 2,
Neutral = 3,
Dislike = 4,
Hate = 5,
Refuse = 6
}
local rows = {}
local rps = {}
for npcName, result in pairs(results) do
local key
if result.level == "Refuse" then
key = levelOrder.Refuse * 1000
else
key = levelOrder[result.level] * 1000 - result.value
end
if rows[key] == nil then
rows[key] = {}
rps[key] = result
end
table.insert(rows[key], npcName)
end
local rowKeys = {}
for key, _ in pairs(rows) do
table.insert(rowKeys, key)
end
table.sort(rowKeys)
local rowTexts = {}
for _, key in ipairs(rowKeys) do
local value = rps[key].value
local level = rps[key].level
if level == "Excellent" then
level = "Love"
end
local icons = {
Love = "非常喜欢",
Like = "喜欢",
Neutral = "喜欢",
Dislike = "不喜欢",
Hate = "讨厌",
Refuse = "不喜欢"
}
local pre = {
Love = "非常喜欢",
Like = "喜欢",
Neutral = "一般",
Dislike = "不喜欢",
Hate = "讨厌",
Refuse = "拒绝"
}
local icon = ImageUnifier.GetImagesMain({
icons[level]
}, {
link = "gifting"
}, "24px")
local col1 = "|" .. icon .. " '''" .. pre[level]
if level ~= "Refuse" then
if value > 0 then
col1 = col1 .. " (+" .. value .. ")'''"
else
col1 = col1 .. " (" .. value .. ")'''"
end
end
local npcs = {}
local npcNames = rows[key]
table.sort(npcNames)
for _, npcName in ipairs(npcNames) do
local icon = ImageUnifier.GetImagesMain({
npcName
}, {
link = npcName
}, "text")
local npc = icon .. "[[" .. npcName .. "]]"
if level == "Refuse" and results[npcName].value ~= 0 then
npc = npc .. " (" .. results[npcName].value .. ")"
end
table.insert(npcs, npc)
end
local col2 = "|style=\"text-align:left\"|" .. table.concat(npcs, " • ")
table.insert(rowTexts, col1 .. "\n" .. col2)
end
return table.concat(rowTexts, "\n|-\n")
end
function formatUniversal(results)
local levelCount = {}
local total = 0
for _, result in pairs(results) do
if levelCount[result.level] == nil then
levelCount[result.level] = 0
end
levelCount[result.level] = levelCount[result.level] + 1
total = total + 1
end
local universalLevel = nil
for level, count in pairs(levelCount) do
if total - count <= 3 then
universalLevel = level
break
end
end
if universalLevel == nil then
return ""
end
local exceptNpcs = {}
for npcName, result in pairs(results) do
if result.level ~= universalLevel then
table.insert(exceptNpcs, npcName)
end
end
table.sort(exceptNpcs)
if universalLevel == "Excellent" then
universalLevel = "Love"
end
local ret = "Universal " .. universalLevel:lower()
if #exceptNpcs > 0 then
ret = ret .. " except [[" .. table.concat(exceptNpcs, "]], [[") .. "]]"
end
return ret
end
-- Main Part --
function getGiftRelationshipForEachNpc(itemId, quality)
local hash = Helper.HashArgs(itemId, quality)
local cacheKey = KEY_PREFIX .. "getGiftRelationshipForEachNpc" .. hash
if (cache.get(cacheKey)) then
local result = cache.get(cacheKey)
return result
end
local ret = {}
for npcId, npc in pairs(AssetNpcProtoDatas) do
if (hasGiftInteractChoice(npc.interactChoice)) then
local npcName = getText(npc.nameID)
local giftRelationship = getGiftRelationship(npcId, itemId, quality)
if (npcName and giftRelationship) then
ret[npcName] = giftRelationship
else
end
end
end
cache.set(cacheKey, ret, EXP_TIME)
return ret
end
function getGiftRelationship(npcId, itemId, quality)
local hash = Helper.HashArgs(npcId, itemId, quality)
local cacheKey = KEY_PREFIX .. "getGiftRelationship" .. hash
if (cache.get(cacheKey)) then
local result = cache.get(cacheKey)
return result
end
local giftData = GiftData[npcId]
local gain = getGiftGainInfo(npcId, giftData, itemId)
if (gain) then
local value = getGiftFavor(itemId, quality, gain.value, gain.level)
local isSpecial = (gain.value ~= 0 or gain.level ~= "Neutral")
local result = {
value = value,
level = gain.level,
special = isSpecial
}
cache.set(cacheKey, result, EXP_TIME)
return result
else
end
end
-- Helper Part --
function getGiftGainInfo(npcId, giftData, itemId)
local giftItem = GiftItem[itemId]
local levels = {
"Excellent",
"Like",
"Dislike",
"Hate",
"Refuse"
}
for _, level in ipairs(levels) do
if giftData and anyTagId(giftData["TagId" .. level], giftItem.tagA) then
return {
value = getGiftGainValue(giftData["FavorValues_" .. level], giftItem),
level = level
}
end
end
if (giftData) then
return {
value = getGiftGainValue(giftData.FavorValues_Neutral, giftItem),
level = "Neutral"
}
else
end
end
function anyTagId(list1, list2)
if (list1) then
for _, x in ipairs(list1) do
if (list2) then
for _, y in ipairs(list2) do
if x == y then
return true
end
end
end
end
end
return false
end
function getGiftGainValue(giftFavorValue, giftItemData)
if (giftFavorValue and giftFavorValue.SpecialValues) then
for _, special in ipairs(giftFavorValue.SpecialValues) do
if (giftItemData and giftItemData.tagB) then
for _, tag in ipairs(giftItemData.tagB) do
if tag == special.InventoryTagID then
return special.GainValue
end
end
end
end
end
return giftFavorValue.DefaultGainValue
end
function getGiftFavor(itemId, gradeType, originalFavor, resultType)
local hash = Helper.HashArgs(itemId, gradeType, originalFavor, resultType)
local cacheKey = KEY_PREFIX .. "getGiftFavor" .. hash
if (cache.get(cacheKey)) then
local result = cache.get(cacheKey)
return result
end
if (resultType) then
local result
if resultType == "Hate" then
result = -5 + originalFavor
end
if (result) then
else
if resultType == "Refuse" then
result = originalFavor
end
if (result) then
else
local low = {
Dislike = -3,
Neutral = 1,
Like = 5,
Excellent = 10
}
local high = {
Dislike = -1,
Neutral = 5,
Like = 10,
Excellent = 20
}
local ret = low[resultType] + (high[resultType] - low[resultType]) * getRegularFavor(itemId, gradeType)
+ originalFavor
-- round to even
local floor = math.floor(ret)
if ret - floor == 0.5 then
if floor % 2 == 1 then
result = floor + 1
else
result = floor
end
end
if (result) then
else
result = math.floor(ret + 0.5)
end
end
end
cache.set(cacheKey, result, EXP_TIME)
return result
end
end
function getRegularFavor(itemId, gradeType)
local hash = Helper.HashArgs(itemId, gradeType)
local cacheKey = KEY_PREFIX .. "getRegularFavor" .. hash
if (cache.get(cacheKey)) then
local result = cache.get(cacheKey)
return result
end
local sellPrice = ItemModule.getSellPrice(itemId, gradeType, true)
if (sellPrice) then
local x = sellPrice ^ 1.1
local result = x / (x + 50)
cache.set(cacheKey, result, EXP_TIME)
return result
end
end
function getText(id)
if (AssetItemChinese[id]) then
return AssetItemChinese[id]
end
end
function hasGiftInteractChoice(interactChoice)
for k, v in pairs(interactChoice) do
if (v == 2 or ChoiceType[v] == 2) then
return true
end
end
end
p.getNpcId = function(name)
for npcId, npc in pairs(AssetNpcProtoDatas) do
if (getText(npc.nameID) and name and getText(npc.nameID):lower() == name:lower()) then
return npcId
else
end
end
end
--
p.debug = function()
Helper.ExpandTemplate = Helper.ExpandTemplateDebug
local args = {
row = "CharacterGiftTable/row",
character = "Logan"
}
local frame = {
args = args
}
-- for a,b in pairs(AssetNpcProtoDatas)do
-- local cacheKey = "Module:Gift" .. "characters_table" .. a
-- cache.delete(cacheKey)
-- end
local result = p.characters_table(frame)
mw.log(result)
end
return p

沪公网安备 31011002002714 号