
物品收藏框架
这是一个共享框架模组,允许多个模组就物品收藏系统达成一致。
查看大图Item Favorite Framework
标记你想保留的物品,以及你不想保留的物品,只需一次。所有支持该框架的模组都会遵循这些标记。维护一个你追求装备的心愿单,并通过需求/贪婪/放弃掷骰公平地分配战利品。
[size=5][b]功能[/b][/size]
[list]
[*][b]收藏物品。[/b] 存放、堆叠和整理时会把它们留在你的物品栏中,破坏性功能永远不会提供它们。[/*]
[*][b]收藏物品栏格子。[/b] 你放在该格子里的任何东西都会留在原地。[/*]
[*][b]将物品标记为垃圾。[/b] 帮你清理的模组知道哪些可以扔掉。框架本身从不销毁任何东西。[/*]
[*][b]原版"放置堆叠"开箱即用。[/b] 容器按钮和对箱子按住使用键会把收藏品以及收藏格子中的任何东西留在你的物品栏中。[/*]
[*][b]可选:地上的垃圾不会被自动拾取。[/b] 你仍然可以手动拾取。[/*]
[*][b]Quick Stack Store Sort 的收藏会在每个角色首次加载时被复制过来。[/b][/*]
[*][b]心愿单。[/b] 标记你想要的物品。它们在任何地方出现都会带上一颗心,当有物品在你附近掉落或出现在你打开的箱子中时,你会收到通知。配合 Epic Loot,你可以指定稀有度、独特物品、套装或特定效果。[/*]
[*][b]共享心愿单。[/b] 在运行该模组的服务器上,每个人都能看到谁想要什么。[/*]
[*][b]需求 / 贪婪 / 放弃战利品掷骰。[/b] 当模组将掉落物交给框架时(Epic Loot 可以为其魔法物品这样做),它指定的玩家会进行掷骰。获胜者得到它;其他人不能先抢走。[/*]
[*][b]收藏和心愿单仅限客户端[/b],随你的角色保存。共享心愿单和战利品掷骰还需要服务器上也安装该模组;没有的话它们就保持关闭。[/*]
[/list]
[size=4][b]操作[/b][/size]
物品栏打开时,按住 [b]Alt[/b]:
[list]
[*][b]切换收藏[/b] - Alt + 左键点击物品
[img]https://github.com/MidnightsFX/ValheimItemFavoriteFramework/blob/master/docs/images/border_favorite.png?raw=true[/img][/*]
[*][b]切换格子收藏[/b] - Alt + 右键点击格子
[img]https://github.com/MidnightsFX/ValheimItemFavoriteFramework/blob/master/docs/images/border_slot.png?raw=true[/img] [img]https://github.com/MidnightsFX/ValheimItemFavoriteFramework/blob/master/docs/images/border_slot_favorite.png?raw=true[/img][/*]
[*][b]切换垃圾标记[/b] - Alt + 中键点击物品
[img]https://github.com/MidnightsFX/ValheimItemFavoriteFramework/blob/master/docs/images/border_trash.png?raw=true[/img][/*]
[*][b]切换垃圾标记(替代方式)[/b] - 左 Alt + 左 Ctrl + 左键点击物品
[img]https://github.com/MidnightsFX/ValheimItemFavoriteFramework/blob/master/docs/images/border_trash.png?raw=true[/img][/*]
[*][b]添加/移除心愿单[/b] - 左 Alt + 左 Shift + 左键点击物品
[img]https://github.com/MidnightsFX/ValheimItemFavoriteFramework/blob/master/docs/images/wishlist_heart.png?raw=true[/img][/*]
[/list]
物品也可以在打开的箱子内标记。格子只能在你自己物品栏中收藏。
当掷骰出现时,在掷骰窗口中投票(在物品栏、地图或聊天打开时点击它),使用 [b]F6[/b](需求)、[b]F7[/b](贪婪)和 [b]F8[/b](放弃),或在聊天中输入 [font=Courier New]/need[/font]、[font=Courier New]/greed[/font] 或 [font=Courier New]/pass[/font]。心愿单编辑器位于主菜单和暂停菜单的 [b]Mod Config[/b] 菜单中。
被标记的格子会获得编织边框:金色代表收藏物品,蓝色代表收藏格子,深红色代表垃圾,其图标也会变灰。收藏格子中放有标记物品时会编织两种颜色,格子蓝色在外,物品颜色在内。工具提示会说明原因。
[b]武器、护甲和工具是逐个标记的。[/b] 收藏你最好的剑不会影响其他任何剑,标记会跟随那把剑到任何地方:进入箱子、掉在地上、进入你的墓碑、经过升级。[b]可堆叠物品按类型标记[/b],所以收藏一堆树脂会收藏你所有的树脂。
收藏和垃圾是互斥的:设置一个之前先取消另一个。
[size=4][b]配置[/b][/size]
位于 [font=Courier New]BepInEx/config/MidnightsFX.ItemFavoriteFramework.cfg[/font]。第 1 到 6 节是每个客户端的设置:
[list]
[*][b]1 - Favoriting:[/b] 收藏按键、垃圾按键、中键垃圾标记、在容器内标记,以及工具提示行。[/*]
[*][b]2 - Colors:[/b] 边框颜色,以及垃圾图标变灰的程度。[/*]
[*][b]3 - Protection:[/b] 放置堆叠保护(默认开启)以及自动拾取时跳过垃圾(默认关闭)。[/*]
[*][b]4 - Compatibility:[/b] Quick Stack Store Sort 导入。[/*]
[*][b]5 - Wishlist:[/b] 心愿单按键、心形颜色、工具提示行、掉落和箱子通知,以及其他人是否可以看到你的心愿单。[/*]
[*][b]6 - Loot rolls:[/b] 投票按键、掷骰窗口、为心愿单物品预选需求,以及自动拾取你赢得的物品。[/*]
[/list]
第 [b]7 - Server[/b] 节由服务器设置并同步给所有人:是否允许战利品掷骰(默认关闭)、心愿单是否共享、掷骰和预留持续多长时间,以及各种限制。
控制台命令:[font=Courier New]iff-status[/font]、[font=Courier New]iff-list[/font]、[font=Courier New]iff-clear <favorites|trash|slots|all>[/font]、[font=Courier New]iff-import-qss [force][/font]、[font=Courier New]iff-wishlist[/font](以及 [font=Courier New]-list[/font]、[font=Courier New]-add[/font]、[font=Courier New]-remove[/font]、[font=Courier New]-clear[/font]、[font=Courier New]-show[/font])、[font=Courier New]iff-net-status[/font]、[font=Courier New]iff-roll-status[/font]、[font=Courier New]iff-roll-test[/font](管理员)、[font=Courier New]iff-need[/font]、[font=Courier New]iff-greed[/font]、[font=Courier New]iff-pass[/font]、[font=Courier New]iff-help[/font]。
[size=4][b]兼容性[/b][/size]
[list]
[*][b]Epic Loot:[/b] 附魔台会把收藏品排除在消耗物品的界面之外,例如献祭,并在它们上面显示一颗星。心愿单条目可以请求稀有度、独特物品、套装或效果,服务器可以让 Epic Loot 的魔法掉落物在附近玩家之间掷骰分配。[/*]
[*][b]Quick Stack Store Sort[/b] 也会在 Alt + 点击时收藏,两个模组会对同一次点击做出反应。首次导入后两组收藏是分开的,所以请解绑其中一个模组的收藏按键。[/*]
[*][b]AzuAutoStore[/b] 会在中键点击时存放物品,所以安装它时中键垃圾标记是关闭的。请改用左 Alt + 左 Ctrl + 左键点击。[/*]
[/list]
[line]
[size=5][b]致模组作者:API[/b][/size]
同样的指南在 GitHub 上,那里的代码更易读:[url=https://github.com/MidnightsFX/ValheimItemFavoriteFramework/blob/master/docs/API.md]docs/API.md[/url]。
Item Favorite Framework (IFF) 拥有三种玩家标记,并将它们暴露给其他模组:
[list]
[*][b]收藏物品[/b] - 设置方式(默认):Alt + 左键点击。适用于:特定物品(武器、护甲、工具——任何不可堆叠的东西),或整个物品类型(可堆叠物品)。[/*]
[*][b]垃圾标记[/b] - 设置方式(默认):Alt + 中键点击,或左 Alt + 左 Ctrl + 左键点击。适用于:与收藏相同的粒度。[/*]
[*][b]收藏格子[/b] - 设置方式(默认):Alt + 右键点击。适用于:玩家物品栏网格的一个格子。[/*]
[/list]
使用它,让你的模组永远不会移动或销毁玩家想要保留的东西:在存放、堆叠、整理、献祭或分解时跳过受保护的物品,并向玩家显示你已跳过。
模组还可以在物品上绘制自己的标记(API 2),读取和填充每个玩家的[b]心愿单[/b](想要物品的列表),并请求 IFF 在其指定的玩家之间运行 MMO 风格的[b]需求/贪婪/放弃战利品掷骰[/b](API 3)。
IFF 的插件 GUID 是 [font=Courier New]MidnightsFX.ItemFavoriteFramework[/font]。收藏、自定义标记和心愿单本身仅在客户端工作。共享心愿单和战利品掷骰还需要服务器上安装 IFF;没有它的服务器就永远不会提供这些功能。
[size=4][b]入门[/b][/size]
[size=3][b]三种接入方式[/b][/size]
[list]
[*][b][font=Courier New]ItemFavoriteFrameworkAPI.ItemFavorites[/font][/b] - 它是什么:一个小型垫片([url=https://github.com/MidnightsFX/ValheimItemFavoriteFramework/tree/master/ItemFavoriteFrameworkAPI][font=Courier New]ItemFavoriteFrameworkAPI/[/font][/url]),一次性将每个端点绑定到有类型的委托。用 ILRepack 打包该 DLL,或将其单一源文件复制到你的项目中。何时使用:几乎总是。IFF 未安装时也可以安全调用。[/*]
[*][b][font=Courier New]ItemFavoriteFramework.API[/font][/b] - 它是什么:[font=Courier New]ItemFavoriteFramework.dll[/font] 内的公开静态类。何时使用:你硬依赖 IFF 并直接引用其 DLL。[/*]
[*][b]反射[/b] - 它是什么:[font=Courier New]Type.GetType("ItemFavoriteFramework.API, ItemFavoriteFramework")[/font]。何时使用:你已经有自己的胶水代码。每个签名都可以用 [font=Courier New]Delegate.CreateDelegate[/font] 绑定。[/*]
[/list]
本页其余部分使用垫片。[i]不使用垫片调用 IFF[/i] 介绍了另外两种方式。
[size=3][b]设置垫片[/b][/size]
[list=1]
[*]通过以下两种方式之一将垫片添加到你的插件:
[list]
[*][b]复制[/b] [url=https://github.com/MidnightsFX/ValheimItemFavoriteFramework/blob/master/ItemFavoriteFrameworkAPI/src/ItemFavorites.cs][font=Courier New]ItemFavorites.cs[/font][/url] 到你的项目中。它是一个文件,除游戏外没有依赖。[/*]
[*][b]打包[/b] [font=Courier New]ItemFavoriteFrameworkAPI.dll[/font] 到你的插件中,使用 ILRepack。如何构建见[url=https://github.com/MidnightsFX/ValheimItemFavoriteFramework/blob/master/ItemFavoriteFrameworkAPI/README.md]垫片的 README[/url]。[/*]
[/list][/*]
[*]声明软依赖,让 IFF 在你的插件之前加载。[/*]
[*]调用它。[/*]
[/list]
[code]using System.Linq;
using BepInEx;
using ItemFavoriteFrameworkAPI;
[BepInPlugin("you.MyStorageMod", "My Storage Mod", "1.0.0")]
[BepInDependency(ItemFavorites.PluginGuid, BepInDependency.DependencyFlags.SoftDependency)]
public class MyStorageMod : BaseUnityPlugin {
private void Awake() {
Logger.LogInfo(ItemFavorites.IsLoaded()
? $"Item Favorite Framework {ItemFavorites.GetPluginVersion()} found, API {ItemFavorites.GetApiVersion()}."
: "Item Favorite Framework is not installed; nothing is protected.");
}
internal static void StoreAll(Inventory from, Inventory to) {
foreach (ItemDrop.ItemData item in from.GetAllItems().ToList()) {
if (ItemFavorites.IsProtected(item)) { continue; } // favorited, or in a favorited slot
// ... move it
}
}
}[/code]
垫片在首次调用时查找 IFF 一次,之后不再查找。没有软依赖,你的插件可能先加载,找不到任何东西,并在整个会话中保持无操作。
[size=3][b]当 IFF 缺失或较旧时[/b][/size]
当 IFF 未安装,或安装的 IFF 较旧且缺少该端点时,每个垫片方法都是安全的。它会返回默认值并且什么都不做:
[list]
[*][b]查询[/b] - [font=Courier New]false[/font]、[font=Courier New]0[/font]、空列表或 [font=Courier New]"[]"[/font][/*]
[*][b]更改和注册[/b] - [font=Courier New]false[/font][/*]
[*][b][font=Courier New]GetFavoriteIcon[/font]、[font=Courier New]GetTrashIcon[/font]、[font=Courier New]GetWishlistIcon[/font][/b] - [font=Courier New]null[/font][/*]
[*][b]颜色[/b] - IFF 的默认颜色[/*]
[*][b][font=Courier New]GetServerFeaturesJson[/font][/b] - [font=Courier New]{"iff":false}[/font][/*]
[*][b][font=Courier New]GetRollStateJson[/font][/b] - [font=Courier New]{"phase":"free"}[/font][/*]
[*][b][font=Courier New]CanPlayerPickUp[/font][/b] - [font=Courier New]true[/font][/*]
[*][b][font=Courier New]StartRoll[/font]、[font=Courier New]StartRollForItem[/font][/b] - [font=Courier New]false[/font],并将 [font=Courier New]error[/font] 设为 [font=Courier New]notInstalled[/font][/*]
[/list]
[font=Courier New]IsLoaded()[/font] 告诉你 IFF 是否存在。要使用比你支持的最旧 IFF 更新的功能,请检查:
[code]bool hasCustomMarks = ItemFavorites.HasEndpoint("RegisterMarkType"); // API 2 or later
bool hasWishlists = ItemFavorites.GetApiVersion() >= 3;[/code]
[size=4][b]每个端点遵循的规则[/b][/size]
[list]
[*][b]仅限主线程。[/b] 从 Unity 回调或 Harmony 补丁中调用,切勿从工作线程调用。[/*]
[*][b]本地玩家。[/b] 收藏、垃圾标记、格子和心愿单回答的是本地角色。在角色加载之前(主菜单、角色选择),查询返回 [font=Courier New]false[/font]、[font=Courier New]0[/font] 或空列表,更改会被拒绝,[font=Courier New]IsReady()[/font] 为 [font=Courier New]false[/font]。更改监听器会在角色标记加载后触发一次,因此 UI 可以等待它而不是轮询。[/*]
[*][b]尽早注册一次。[/b] 监听器、点击处理器、标记类型和提供者可以在 [font=Courier New]Awake[/font] 中添加。它们持续整个会话,跨登出和世界切换。[/*]
[*][b]委托按相等性保留。[/b] 添加同一个委托两次只会添加一次。要移除一个,传递相同的方法组,或将 lambda 保存在字段中:[/*]
[/list]
[code]private static readonly Action onMarksChanged = () => myPanel.Refresh();
ItemFavorites.AddChangedListener(onMarksChanged);
ItemFavorites.RemoveChangedListener(onMarksChanged);[/code]
[list]
[*][b]你的 bug 归你。[/b] 抛出异常的监听器、处理器或提供者会被记录,并标出声明类型,不会阻止其他项。[/*]
[/list]
[size=3][b]签名规则[/b][/size]
只有基元类型、[font=Courier New]string[/font]、原版/Unity 类型([font=Courier New]ItemDrop.ItemData[/font]、[font=Courier New]ItemDrop[/font]、[font=Courier New]Inventory[/font]、[font=Courier New]Character[/font]、[font=Courier New]Vector2i[/font]、[font=Courier New]Vector3[/font]、[font=Courier New]Sprite[/font]、[font=Courier New]Color[/font])、它们的列表,以及它们的 [font=Courier New]System.Func[/font]/[font=Courier New]Action[/font] 可以跨越边界。任何签名中都不出现 IFF 类型,因此消费者永远不需要 IFF 的程序集来编译。结构化数据以 JSON 字符串传输,返回多个值的端点使用 [font=Courier New]ref[/font] 参数(不是 [font=Courier New]out[/font]),以便反射调用者可以读取它们。现有签名永不改变;新增会提升 [font=Courier New]ApiVersion[/font]。
[size=3][b]读取 JSON[/b][/size]
任何 JSON 解析器都可以。Valheim 自带 Unity 的 [font=Courier New]JsonUtility[/font](以及 Newtonsoft.Json),所以你不需要额外的东西。[font=Courier New]JsonUtility[/font] 用公共字段填充 [font=Courier New][Serializable][/font] 类,并忽略你未声明的键,但它无法读取顶层数组,所以先包装一个。本页的示例使用这些辅助方法:
[code]using System;
using UnityEngine;
internal static class IffJson {
[Serializable]
private class Wrapper<T> { public T[] items; }
internal static T[] ReadArray<T>(string json) {
Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>("{\"items\":" + json + "}");
return wrapper?.items ?? new T[0];
}
}
[Serializable]
internal class PlayerRef {
public string player; // a player id: long.Parse(player)
public string name;
public bool self;
}[/code]
玩家 ID 在 IFF 的 JSON 中始终是字符串,因为 64 位 ID 在将数字读取为 double 的解析器中会丢失精度。你给 IFF 的 ID 列表可以使用字符串或数字。
[size=4][b]版本控制[/b][/size]
[code]int GetApiVersion() // 3; the shim returns 0 when IFF is missing
string GetPluginVersion() // "0.0.1"; the shim returns "" when IFF is missing
bool HasEndpoint(string) // whether the installed IFF has an endpoint of this name
bool IsReady() // the local character's marks are loaded
bool IsLoaded() // shim only: IFF is installed and its API was found
string GetPluginId() // ItemFavoriteFramework.API only; the shim has the constant PluginGuid
List<string> GetEndpointNames() // ItemFavoriteFramework.API only: every endpoint name, sorted[/code]
[list]
[*][b]API 1[/b] - 收藏、垃圾标记、收藏格子、更改监听器、图标和颜色[/*]
[*][b]API 2[/b] - 自定义标记、标记监听器、物品点击处理器[/*]
[*][b]API 3[/b] - 心愿单及其提供者、物品名称提供者、共享心愿单、战利品掷骰[/*]
[/list]
[size=4][b]收藏、垃圾和格子[/b][/size]
[size=3][b]标记如何被键控[/b][/size]
[list]
[*][b]不可堆叠的物品[/b]([font=Courier New]m_shared.m_maxStackSize <= 1[/font])是逐个标记的。标记存储在物品的 [font=Courier New]m_customData[/font] 中,并随它穿过箱子、掉落物和墓碑。它记录了哪个角色设置的,所以另一个玩家持有该物品时会看到它未被标记。[/*]
[*][b]可堆叠物品[/b]按类型([font=Courier New]m_shared.m_name[/font])标记,就像 Quick Stack Store Sort 那样:收藏一堆树脂会收藏所有树脂。原版合并堆叠时不比较自定义数据,所以每堆标记无法存活。[/*]
[*]查询会遵循两种来源,无论当前堆叠大小如何。从 Quick Stack Store Sort 导入的收藏是类型标记,即使是武器。[/*]
[*]收藏和垃圾永远不会同时适用。收藏优先,所以类型的垃圾标记永远不会移除单独收藏的物品。[/*]
[*][b]格子标记[/b]只存在于玩家自己的物品栏网格中。箱子里的物品永远不会"在收藏格子中",无论其 [font=Courier New]m_gridPos[/font] 如何。[/*]
[/list]
[size=3][b]查询[/b][/size]
[code]bool IsItemFavorited(ItemDrop.ItemData item) // this item, or its type, is favorited
bool IsItemTrashFlagged(ItemDrop.ItemData item) // never true for a favorited item
bool IsSlotFavorited(int x, int y) // a favorited cell of the player's grid
bool IsItemInFavoritedSlot(ItemDrop.ItemData item) // in the player's inventory, in a favorited cell
bool IsProtected(ItemDrop.ItemData item) // favorited OR in a favorited slot
int GetMarks(ItemDrop.ItemData item) // MarkItemFavorite(1) | MarkSlotFavorite(2) | MarkTrash(4)
List<ItemDrop.ItemData> GetFavoritedItems(Inventory inventory) // null = the player's inventory
List<ItemDrop.ItemData> GetTrashFlaggedItems(Inventory inventory)
List<ItemDrop.ItemData> GetProtectedItems(Inventory inventory)
List<Vector2i> GetFavoritedSlots() // sorted by row, then column[/code]
[font=Courier New]IsProtected[/font] 是大多数模组需要的那一项检查。网格单元格是 [font=Courier New](x, y)[/font],其中 [font=Courier New]x[/font] 是列,[font=Courier New]y[/font] 是行;[font=Courier New](0, 0)[/font] 是第一个快捷栏格子。
列表查询适用于任何物品栏,包括箱子:逐物品标记随物品移动,类型标记在任何地方都适用。只有格子标记仅限于玩家自己的物品栏,所以 [font=Courier New]GetProtectedItems(chest.GetInventory())[/font] 会列出箱子中的收藏品。
[font=Courier New]GetMarks[/font] 一次调用回答所有问题:
[code]int marks = ItemFavorites.GetMarks(item);
bool favorite = (marks & ItemFavorites.MarkItemFavorite) != 0;
bool inFavoritedSlot = (marks & ItemFavorites.MarkSlotFavorite) != 0;
bool trash = (marks & ItemFavorites.MarkTrash) != 0;[/code]
[size=3][b]更改[/b][/size]
[code]bool SetItemFavorited(ItemDrop.ItemData item, bool favorited)
bool SetItemTrashFlagged(ItemDrop.ItemData item, bool trashFlagged)
bool SetSlotFavorited(int x, int y, bool favorited)[/code]
当物品或格子之后处于请求的状态时,这些返回 [font=Courier New]true[/font],包括它已经是该状态时。更改被拒绝时返回 [font=Courier New]false[/font]:
[list]
[*]没有加载角色;[/*]
[*]物品为 null 或没有共享数据,或格子坐标为负;[/*]
[*]收藏和垃圾是互斥的,所以设置一个之前先清除另一个;[/*]
[*]角色的已保存标记无法读取。IFF 然后保持它们不变,供新版本恢复,并拒绝所有更改。[/*]
[/list]
与玩家点击相同的粒度适用:收藏可堆叠物品会收藏其整个类型。取消收藏物品会同时清除其自身标记和类型标记。
在玩家物品栏或打开的容器中的物品上设置的逐物品标记会立即保存该物品栏。对于任何其他位置的物品,会在该物品栏下次保存时保存。
[b]收藏你发放的奖励,这样全部存放永远不会把它扫进箱子。[/b]
[code]Player player = Player.m_localPlayer;
ItemDrop.ItemData reward = player.GetInventory().AddItem("SwordIron", 1, 2, 0, player.GetPlayerID(), player.GetPlayerName(), false);
if (reward != null && ItemFavorites.SetItemFavorited(reward, true) == false) {
Logger.LogDebug("The reward could not be favorited (no character loaded, or it is flagged as trash).");
}[/code]
[size=3][b]监听器[/b][/size]
[code]void AddChangedListener(Action listener)
void RemoveChangedListener(Action listener)[/code]
监听器在任何标记更改后以及角色标记加载后触发。它不携带负载,所以重新查询你显示的内容。
[code]private void Awake() => ItemFavorites.AddChangedListener(OnMarksChanged);
private void OnDestroy() => ItemFavorites.RemoveChangedListener(OnMarksChanged);
private void OnMarksChanged() {
if (myPanel.IsVisible()) { myPanel.Refresh(); }
}[/code]
要了解哪个物品更改了,请改用[i]标记监听器[/i]。
[size=3][b]UI 辅助方法[/b][/size]
[code]Sprite GetFavoriteIcon() // white star, dark outline: tint with GetFavoriteColor()
Sprite GetTrashIcon() // white X, dark outline: tint with GetTrashColor()
Color GetFavoriteColor() // the player's configured border colours
Color GetFavoritedSlotColor()
Color GetTrashColor()[/code]
图标在首次使用时构建并共享,所以不要销毁它们。每次绘制时读取颜色:玩家可以在游戏中更改它们。
[b]在收藏的列表条目上显示一颗星。[/b]
[code]star.sprite = ItemFavorites.GetFavoriteIcon();
star.color = ItemFavorites.GetFavoriteColor();
star.gameObject.SetActive(ItemFavorites.IsItemFavorited(item)); // always set it: rows are usually pooled[/code]
物品工具提示已经通过静态 [font=Courier New]ItemDrop.ItemData.GetTooltip[/font] 上的后缀从 IFF 获得"★ Favorited" / "Flagged as trash"行。不要添加你自己的。
[size=4][b]自定义标记(API 2)[/b][/size]
你自己的物品标记,像内置标记一样绘制和列出:你的颜色边框(优先级高于收藏和垃圾)、你在格子左上角的图标,以及你的工具提示行。
[code]bool RegisterMarkType(string id, string group, Color color, Sprite icon, string tooltipToken)
bool IsMarkTypeRegistered(string id)
bool HasCustomMark(ItemDrop.ItemData item, string id)
List<string> GetCustomMarks(ItemDrop.ItemData item) // in registration order
bool SetCustomMark(ItemDrop.ItemData item, string id, bool marked)[/code]
[list]
[*]使用命名空间 ID,不含空格、制表符或换行([font=Courier New]"mymod.loot.need"[/font])。[font=Courier New]RegisterMarkType[/font] 对空 ID 或含空白的 ID 返回 [font=Courier New]false[/font]。[/*]
[*]再次注册 ID 会更新其颜色、图标和工具提示;其组永不改变。[font=Courier New]icon[/font] 可以为 null(仅边框)。[font=Courier New]tooltipToken[/font] 是本地化令牌([font=Courier New]"$mymod_need"[/font])或纯文本,以标记的颜色显示,或为空表示无行。[/*]
[*]自定义标记存储在[b]物品实例上[/b],位于 [font=Courier New]m_customData["IFF.custom.<id>"][/font],包括可堆叠物品。它随物品移动,对每个玩家读取相同,不需要加载角色。它的含义由你决定:当你不再需要该物品时清除它。[/*]
[*]对于可堆叠物品,标记属于那一堆。当原版合并两堆时,它保留一堆的自定义数据并丢弃另一堆的,所以合并后的堆只有在存活的那堆有标记时才携带标记。[/*]
[*]使用相同非空 [font=Courier New]group[/font] 注册的标记是互斥的:设置一个会清除其他的。[/*]
[*]携带多个自定义标记的物品会用最先注册的那个绘制。[font=Courier New]GetCustomMarks[/font] 会列出全部。[/*]
[*][font=Courier New]SetCustomMark[/font] 在物品之后处于请求状态时返回 [font=Courier New]true[/font],对于无人注册的 ID 或无效物品返回 [font=Courier New]false[/font]。它像收藏一样保存物品的物品栏。[/*]
[/list]
[b]标记你的商店将出售的物品。[/b]
[code]// Once, in Awake or when your sprites are loaded.
ItemFavorites.RegisterMarkType("mymod.shop.sell", "", new Color(1f, 0.6f, 0.1f), sellIcon, "$mymod_marked_for_sale");
// When the player picks an item in your shop window.
ItemFavorites.SetCustomMark(item, "mymod.shop.sell", true);
// When the sale goes through or is cancelled. The mark would otherwise stay on the item.
ItemFavorites.SetCustomMark(item, "mymod.shop.sell", false);[/code]
[size=4][b]标记监听器和物品点击(API 2)[/b][/size]
[code]void AddMarkListener(Action<ItemDrop.ItemData, string, bool> listener) // item, mark id, now set
void RemoveMarkListener(Action<ItemDrop.ItemData, string, bool> listener)
void AddItemClickHandler(Func<Inventory, ItemDrop.ItemData, int, bool> handler)
void RemoveItemClickHandler(Func<Inventory, ItemDrop.ItemData, int, bool> handler)[/code]
[b]标记监听器[/b]会听到每个物品标记更改,在它发生之后:[font=Courier New]"favorite"[/font]、[font=Courier New]"trash"[/font]([font=Courier New]ItemFavorites.MarkIdFavorite[/font]、[font=Courier New]MarkIdTrash[/font])或自定义 ID。
[list]
[*]可堆叠物品上的类型标记会报告一次,针对设置它的那个物品,尽管该类型的每个物品都随之改变。[/*]
[*]设置分组自定义标记时,会先报告它清除的标记([font=Courier New]false[/font]),然后是新标记。[/*]
[*]格子标记不属于任何物品,不会被报告,用 [font=Courier New]iff-clear[/font] 一次清除所有也不会。[font=Courier New]AddChangedListener[/font] 仍会为它们全部触发。[/*]
[/list]
[b]物品点击处理器[/b]在任何物品栏格子上鼠标按下时被调用,带有网格的物品栏、格子中的物品(空时为 null)和按钮([font=Courier New]ItemFavorites.ButtonLeft[/font] 0、[font=Courier New]ButtonRight[/font] 1)。
[list]
[*]返回 [font=Courier New]true[/font] 以接过点击:原版的拾取、拆分或使用以及收藏点击随后会忽略它。[/*]
[*]处理器按添加顺序被询问,在 IFF 自己的点击之前,第一个返回 [font=Courier New]true[/font] 的获胜。抛出异常的算作不接过点击。[/*]
[*
正在加载版本记录…
正在加载评论…
评论在新手盒子客户端中发表,这里同步展示。