Stardew
全站通知:

模组:鱼类数据

来自星露谷物语
跳到导航 跳到搜索

此页面解释游戏如何存储和解析鱼数据,包括生成机制。这是面向模组开发者的高级指南。

解析鱼类生成条件

游戏会检查两个位置来决定玩家钓鱼时生成何种鱼类。这仅适用于正常鱼类;计算生成传说鱼类的概率时,在检查这两个位置之前还会单独检查地点代码。 (由BobberBarGameLocation::getFish的逆向工程可知)

生成地点

每种鱼类都归属于地点内的一片区域,且仅当玩家处在该区域内时才会生成。GameLocation::getFishingLocation定义了每个区域的地块坐标。对于每个游戏区域,它都可以被重写。现定义了如下区域:

  • 煤矿森林:
    • 池塘(区域#1,从地块(0, 0)(52, 42),包括边界);
    • 河流 (区域#0,匹配森林的其他区域)
  • 岛屿西部
    • 淡水(区域#2,从地块(36, 0)(36, 80),包括边界);
    • 海洋(区域#0,匹配其他位置)
  • 其他所有地点只有区域-1,所以从哪里钓鱼都无影响。

可在给定地点生成的鱼由Data\Locations.xnb中用斜杠分隔的数据定义。具体而言,有如下的字段索引:4(春季),5(夏季),6(秋季),7(冬季)。每个字段都包含<int fishID>(匹配Data\Fish.xnb)+<int areaID>(或-1表示任何区域)整数对。例如,煤矿森林夏季的鱼数据为153 -1 145 0 144 -1 138 0 132 0 706 0 704 0 702 0。其可被解析为:

区域
153 -1 绿藻 任何区域(池塘或河流)
145 0 太阳鱼 河流
144 -1 狗鱼 任何区域(池塘或河流)
138 0 虹鳟鱼 河流
132 0 鲷鱼 河流
706 0 西鲱 河流
704 0 麻哈脂鲤 河流
702 0 鲢鱼 河流

鱼类数据和生成规则

鱼类数据和生成规则是存储在Data\Fish.xnb中的字段。包括两种不同格式。

若第二个字段为trap,则这种鱼只能用蟹笼捕获,且使用如下格式:

索引 语法 示例 内容
0 <name> Lobster 鱼的名称
1 <type> trap 必须为trap,以指示需要使用蟹笼
2 <chance> .05 抓到此鱼的概率。介于0到1之间。只有当文件中之前列出的鱼都没有被判定选中时,才会依此概率判定此鱼选中与否。
3 688 .45 689 .35 690 .35 未使用。
4 <location> ocean 能抓到此鱼的水体类型。为freshwaterocean
5 <min size> 2 此鱼可能的最小和最大长度,单位为英寸。用于统计钓鱼数据。非英语语言下,乘2.54转换为厘米。
6 <max size> 20

否则,该鱼类可以用钓竿捕获,且使用如下格式:

索引 语法 示例 内容
0 <name> Pufferfish 鱼的名称。
1 <chance to dart> 80 鱼在钓鱼小游戏中以多高频率猛冲;介于15(鲤鱼)和100(冰川鱼)之间。
2 <darting randomness> floater 钓鱼小游戏中浮标以何种模式运动;取值为mixedsmoothfloatersinker,或dart
3 <min size> 1 此鱼可能的最小和最大长度,单位为英寸。用于统计钓鱼数据。非英语语言下,乘2.54转换为厘米。.
4 <max size> 36
5 [<min time> <max time>]+ 1200 1600 一天中生成该鱼的时间。包括最小值,不包括最大值。可以指定多个范围。
6 [<season>]+ summer 未使用;季节数据会从Data/Locations读取。
7 <weather> sunny 生成该鱼的天气。sunnyrainy,或both.
8 <locations> 690 .4 685 .1 未使用;地点会从Data/Locations读取。
9 <max depth> 4 以最大概率抓住此类型的鱼的最小水深;用于计算生成率(见下文)。
10 <spawn multiplier> .3 用于计算生成率的生成率乘数(见下文)。
11 <depth multiplier> .5 用于计算生成率的深度乘数(见下文)。
12 <fishing level> 0 鱼出现所需的最低钓鱼等级
13 <first-catch tutorial eligible> true 可否出现在第一次钓鱼教程中。

生成概率

鱼类生成率的计算详见游戏文件[1]。每次玩家投掷钓竿时,会生成一个包含该地点所有可用鱼类的队列(包括藻类、海草、垃圾、秘密纸条、齐豆等)。随后,按照特定优先级(例如“鱼王 > 普通鱼类 > 秘密纸条 > 垃圾”)进行排序,再随机打乱同一优先级的不同鱼类。游戏将按顺序遍历该队伍,对于队伍中的每种鱼类,在经过对季节、位置、水深、钓鱼等级、魔法鱼饵等要素的检查后,将进行第一次随机性判定计算选择此种鱼类的概率。若选中,游戏将进行一些其他判定,例如鱼饵类型、是否只能钓起1条等,并进行第二次随机性判定。此方法会根据多重因素随机地生成true或false,以决定能否钓起此鱼,其机制较为复杂,见下文。若最终未能选中钓起的物品,则在非教程模式下返回空,否则返回太阳鱼

在上文中,第一次随机性判定的概率由SpawnFishData::GetChance方法和Data/Locations.xnb中的鱼类数据给出,计算公式为{概率} = ChanceModifiers({Chance} + {CuriosityLureBuff} + {当日运气}) * {SpecificBaitMultiplier} + {SpecificBaitBuff} + {ChanceBoostPerLuckLevel} * {运气等级},其中英文参数均为Data/Locations.xnb中的对应字段。

第二次随机性的概率由GameLocation::CheckGenericFishRequirements方法和Data/Fish.xnb中的鱼类数据给出,其计算较复杂。首先,计算{概率} = {生成率乘数} - max(0, {最小水深} - {实际水深}) * {深度乘数} * {生成率乘数} + {钓鱼等级} / 50。若为训练用钓竿,则在此基础上乘1.1,但最高不超过0.9 。若此时概率仍小于0.25且有珍稀诱钩增益,则判断是否为该收益是否为默认值。若是,则采用新概率 = 原概率 * 0.17 / 0.25 + 0.17 / 2来更新概率,否则直接在原概率的基础上增加该鱼类特有的珍稀诱钩增益(CuriosityLureBuff)。若使用针对性鱼饵,则再将此概率乘1.66 。若还受每日运气影响则加上每日运气。最后再应用概率修饰器(若有)。

1.6版本中鱼类生成的相对概率计算更为复杂。

鱼缸鱼类

鱼缸中的鱼类可通过Data/AquariumFish资源来编辑:

索引 字段 目的
0 贴图索引 LooseSprites/AquariumFish 贴图集中该贴图的索引,从左上角的贴图为0开始计数。
1 类型 鱼的类型。影响鱼的行为。可能的取值为:
说明
鳗鱼
头足类
爬行类
底栖类
鱼类
置顶爬行类 用于贴图延伸到底板下面的爬行类。这类鱼总被贴到离玻璃最近的位置且置于其他鱼类上方,以避免排序问题。U
2
3–5
空闲动画
猛冲动画
鱼类空闲(2)或猛冲(3–5)时使用的动画。为一系列空格分隔的帧,每个帧都是LooseSprites/AquariumFish贴图集中的贴图索引。每帧持续125毫秒。例如,黄貂鱼的空闲动画为70 70 70 71 71 72

冲刺动画分列三个字段:起始(3)、保持(4)和结束(5)。

7 帽子位置 在此贴图上放置帽子的像素位置。为包含XY值的对象。自定义的鱼缸鱼类也能戴帽子,就像原版游戏中的海胆

参考

  1. 鱼类上钩的概率计算涉及:Data/Locations.xnbSpawnFishData::GetChanceData/Fish.xnbGameLocation::CheckGenericFishRequirements;通过这4个文件路径可以得到各个地方各种鱼类的基础数据并计算出钓上的概率