Starsector Nihilism Guidance
首页
GitHub 项目
首页
GitHub 项目
  • 首页
  • 基础及舰船相关
    • MOD 骨架和入口文件
    • 制作一艘基本舰船
    • 制作一艘航母与战机
    • 制作一艘相位舰
    • 制作火炮、光束与导弹
    • 为舰船加入内置武器、船插与战机
    • 补充描述文本
  • 无需入门的代码修改
    • 以船插为例初步熟悉代码
    • 制作完整船插
    • 制作最小战术系统
    • 为武器加入命中与光束特效
  • 势力与生涯星系
    • 注册一个势力
    • 配置势力舰队
    • 制作 MOD 入口类的最基础适配
    • 制作一个生涯星系
    • 补完描述文本
  • 战役与无代码对象
    • 制作测试战役装配
    • 为模拟战与标题画面加入装配
    • 为舰船加入外观风格
    • 制作一艘模块船
    • 制作一种星体类型
    • 制作一个自定义实体
  • 音频资源与播放
    • 准备 OGG 音频资源
    • 注册音频资源
    • 为游戏对象加入音频
  • Java 工程化
    • 确认 Java 与编译依赖
    • 迁移代码文件到 src
    • 配置 Gradle 工程
    • 构建 JAR 并声明产物
  • 全局服务
    • 制作 MOD 入口类
    • 使用 Global 访问游戏服务
    • 读取设置
    • 调用声音播放器
    • 记录和定位 MOD 日志
  • 战斗运行时
    • 读取战斗引擎状态
    • 读取战斗对象
    • 制作每帧战斗插件
    • 修改舰船数值
    • 配置武器脚本
    • 配置战斗监听器
    • 制作分层渲染插件
  • 战斗内容扩展
    • 详解舰船插件
    • 详解战术系统
    • 详解武器动画
  • 生涯世界与基础服务
    • 读取生涯世界状态
    • 构建生涯地点
    • 配置生涯势力
    • 放置生涯实体
  • 生涯舰队与舰队成员
    • 生成生涯舰队
    • 管理舰队中的成员
    • 舰队状态的重算过程
    • 维护舰队成员状态
    • 读取并修改舰船装配
  • 市场与商品
    • 创建生涯市场
    • 读写货舱内容
    • 注册市场商品
    • 实现专用子市场
    • 制作专用产业
    • 注册特殊物品
    • 实现市场条件
  • 人物与技能
    • 配置人物基础
    • 让人物承担角色
    • 制作角色技能
  • 生涯脚本与情报事件
    • 编写生涯逐帧脚本
    • 监听生涯事件
    • 选择生涯插件
    • 管理舰队活动情报
  • 酒吧事件与任务
    • 组织生涯交互对话
    • 实现对话插件
    • 接入酒吧事件
    • 构建阶段任务
    • 接入酒吧任务
  • Rules 系统、命令与内存
    • 组织 Rules 规则表
    • 编排 Rules 对话
    • 接入 Rules 生涯场景
    • 编写 Rules 命令
    • 使用 MemoryAPI 保存状态
  • 文件读取与写入
    • 读取 MOD 内文本
    • 读取 MOD 内 JSON 文件
    • 读取 MOD 内 CSV
    • 读写 common 数据
    • 实现本地化机制
  • 常用依赖库
    • 接入常用依赖库
    • 使用 LazyLib 几何工具
    • 使用 LazyLib 查询战场
    • 使用 LazyLib 保存公共 JSON
    • 注册 GraphicsLib 光照数据
    • 创建 GraphicsLib 动态光源
    • 制作 GraphicsLib 纹理映射
    • 配置 MagicLib 自动尾迹
    • 创建 MagicLib 运行时尾迹
    • 配置 MagicLib 数据赏金
    • 使用 MagicLib 辅助生涯开发
    • 使用 MagicLib 战斗小工具
  • 可选依赖与 Nexerelin
    • 接入可选依赖
    • 登记 Nexerelin 势力与外交配置
    • 配置 Nexerelin 的两种星区开局
    • 配置 Nexerelin 战略 AI 与扩张规模
    • 登记 Nexerelin 地面战单位与产业
    • 为 Nexerelin 特遣队添加命名与事件响应
    • 制作即时生效的 LunaLib 设置面板
  • 着色器与渲染
    • 使用 Java OpenGL
    • 使用 GLSL 进阶
    • 使用 VBO 和 VAO 保存顶点
    • 使用 SSBO 传递参数
    • 使用实例化进行绘制
    • 选择 BoxUtil 渲染方案

配置 Nexerelin 的两种星区开局

Corvus 的出生登记可以指向固定实体,随机星区的出生位置则来自本次生成的对象。本节为齿轮工业登记 Prime 和两组起始装配,再用规划器比较配置 ID、当前市场与舰队列表。规划器负责查询,Nexerelin 的开局流程负责实际放置和生成,两者的结果分别确认。

本节预期阅读时间:~18 分钟。

本节预期操作时间:~30 分钟。

学习目标

完成后,您将能够:

  • 在 SectorManager 就绪后区分 Corvus 与随机星区;
  • 登记固定出生实体,并从随机星区查询已有市场;
  • 为同一势力配置起始舰队并读取装配列表;
  • 区分固定类型、RANDOM 候选和未知类型的结果。

前置知识

  • [C3-S4] 的 GearIn 星系、Prime 行星与 GearIn_planet1;
  • [C4-S1] 的 GearIn_artizan_combat 装配;
  • [C19-S2] 的势力登记、模式资格和兼容查询;
  • [C7-S1] 的新档生成与生涯加载时机。

把固定出生点写到真实实体

在 MOD 的 data/config/exerelin/corvus_spawnpoints.csv 保存:

faction,system,entityID
gear_industry,GearIn,GearIn_planet1

system 保存星系名 GearIn,entityID 保存 [C3-S4] 创建的 GearIn_planet1;Prime 的显示名则是 GearIn Prime。库读取这份登记以后,普通 Corvus 放置分支通过实体 ID 从星区查询对象。出生入口使用实际实体 ID。

固定模式保留 GearInSystemGenerator 的生成调用,让该实体在玩家放置前存在。CSV 本身登记引用,实际对象仍由生成器创建。

让随机星区拥有生成资格

在 gear_industry.json 沿 [C19-S2] 的资格字段增加:

"marketSpawnWeight": 1

随机星区生成设置中启用齿轮工业,再启用势力权重并采用配置权重。marketSpawnWeight 此时参与程序化市场分配;关闭权重或采用随机权重时,分配使用对应设置。生成完成以后,NexUtilsFaction.getFactionMarkets("gear_industry") 才取得当前市场。

自定义星系生成器也可能为随机模式追加市场,程序化生成还有母星等分配步骤。因此,权重为 0 只改变相应分配,最终市场集合仍由实际生成过程确定。

填写两类起始舰队

在同一势力 JSON 根对象追加以下局部字段:

"startShipsSolo": [
    ["GearIn_artizan_combat"]
],
"startShipsCombatSmall": [
    ["GearIn_artizan_combat", "wolf_Starting"]
]

每个内层数组是一组装配 ID。startShipsSolo 对应 SOLO,startShipsCombatSmall 对应 COMBAT_SMALL;已有工匠装配负责示例身份,原版狼装配补一艘护卫舰。

Nexerelin 加载时确认装配能够取得。新档界面选择固定舰队类型,或者随机类型;开局舰船由库的实际生成流程建立。本节的规划器读取配置与地点,方便对照这些结果。

按模式查询地点与装配

保存完整 GearInNexStartPlanner 到 src/data/scripts/gearin/modcompat/GearInNexStartPlanner.java。它在生涯建立后查询数据,返回地点 ID 和装配列表。

地点查询与玩家实际出生

管理器尚未建立时,chooseSpawn 返回 null。Corvus 分支返回登记行中的实体 ID,登记行缺失时返回 null;随机分支遍历本势力市场,跳过没有主实体的市场,再选择规模最大者。

规模相同时保留先遇到的市场,集合顺序影响选择。这是本例自行采用的最大市场策略。库的普通随机开局还会使用母星或随机市场,背景指定位置、玩家选择的起点与随机出生开关也会改变实际放置。

规划器只返回地点 ID

Corvus 查询返回 CSV 里的 ID,尚未检查该实体是否存在;随机查询返回当前最大市场主实体。自有放置代码需要再取得实体,库的正常开局则继续使用自己的放置规则。

固定舰队和 RANDOM

局部取值为:

List<String> solo = planner.chooseFleet("gear_industry", "SOLO");
List<String> randomFleet = planner.chooseFleet("gear_industry", "RANDOM");

getStartFleetForType(fleetType, false, 0) 的索引 0 取该类型首组配置,false 关闭缺少类型时的备用舰队;缺少记录可返回 null。同一个固定类型在两种模式下使用相同配置列表。

RANDOM 从配置已提供且 canPickAsRandom 为 true 的类型中选择,本例是 SOLO 与 COMBAT_SMALL。CUSTOM 和 RANDOM 自身不进入随机候选。不同新档或请求可以得到不同列表。

未知类型怎样报告

API 内部通过 StartFleetType.getType(...) 解析字符串,忽略大小写;未知字符串抛出 IllegalArgumentException。直接让这次请求报告拼写问题即可,调用方据此修正输入。

需要观察异常时,通过 Console Commands 请求:

runcode new data.scripts.gearin.modcompat.GearInNexStartPlanner().chooseFleet("gear_industry", "GearIn_unknown_type");

这个命令在类型解析时报告输入问题,查询过程保留玩家当前的位置和舰队。自有放置入口根据地点查询结果取得实体,登记 ID 对应不到对象时再处理缺失状态。

在生涯加载后比较查询结果

Sector、Nexerelin 管理器与经济已建立后,在既有 onGameLoad(...) 的启用分支追加局部调用,添加自有角色类的 import,保留原初始化:

if (GearInCompatBridge.isNexerelinEnabled()) {
    GearInNexStartPlanner planner = new GearInNexStartPlanner();
    Global.getLogger(GearInModPlugin.class).info(
            "GearIn start: corvus=" + GearInNexCompat.isNexCorvusMode()
                    + " entity=" + planner.chooseSpawn("gear_industry")
                    + " solo=" + planner.chooseFleet("gear_industry", "SOLO")
                    + " combatSmall=" + planner.chooseFleet("gear_industry", "COMBAT_SMALL"));
}

固定类型读取同一份配置,地点查询按模式读取不同来源。日志确认这份输入,地图与开局舰队再确认实际生成结果,便能区分查询策略与库的开局规则。

完整最小例

出生点 CSV 与两类舰队字段采用前面的输入,规划器保存两种地点查询和固定索引的舰队取值:

完整成品:GearInNexStartPlanner
package data.scripts.gearin.modcompat;

import java.util.List;

import com.fs.starfarer.api.campaign.econ.MarketAPI;
import exerelin.campaign.SectorManager;
import exerelin.utilities.NexConfig;
import exerelin.utilities.NexUtilsFaction;
import exerelin.world.ExerelinCorvusLocations;

/** 在生涯已生成后查询出生实体与起始装配列表。 */
public final class GearInNexStartPlanner {
    public String chooseSpawn(String factionId) {
        SectorManager manager = SectorManager.getManager();
        if (manager == null) {
            return null;
        }
        if (manager.isCorvusMode()) {
            ExerelinCorvusLocations.SpawnPointEntry entry =
                    ExerelinCorvusLocations.getFactionSpawnPoint(factionId);
            return entry == null ? null : entry.entityId;
        }

        MarketAPI largest = null;
        for (MarketAPI market : NexUtilsFaction.getFactionMarkets(factionId)) {
            if (market.getPrimaryEntity() == null) {
                continue;
            }
            if (largest == null || market.getSize() > largest.getSize()) {
                largest = market;
            }
        }
        return largest == null ? null : largest.getPrimaryEntity().getId();
    }

    public List<String> chooseFleet(String factionId, String fleetType) {
        return NexConfig.getFactionConfig(factionId)
                .getStartFleetForType(fleetType, false, 0);
    }
}

验证方案

前置数据:Console Commands 已启用,准备 Corvus 与随机星区两种新档;固定验证采用普通背景、默认出生点并关闭随机出生,权重验证启用配置势力权重。

  1. 保存出生 CSV、市场权重、起始舰队字段、规划器与日志调用,构建并重启,选择齿轮工业的 SOLO 开局。
  2. 创建 Corvus 新档,观察玩家出生位置,再搜索 GearIn start 中的实体与两类装配列表。
  3. 创建随机星区新档并启用齿轮工业,查看其已有市场,比较日志选择的最大规模市场主实体。
  4. 选择 COMBAT_SMALL 创建新档,再多次使用 RANDOM,核对舰队列表来自已配置的两类。
  5. 执行正文未知类型命令,观察类型异常;用未配置的合法类型查询,观察返回 null。
  6. 在没有齿轮工业市场的专用随机测试生涯查询出生点,确认返回 null;制作这类输入时也保持自定义生成器不追加市场。

预期结果:

  • 固定模式登记解析到 GearIn 星系的 GearIn_planet1,玩家位置对应固定出生入口;
  • 随机规划返回当前有效最大市场的主实体,规模并列时采用集合中先遇到者;
  • SOLO 与 COMBAT_SMALL 分别返回工匠单舰、工匠和狼的列表,两种模式的固定配置一致;
  • RANDOM 从已有可随机类型选择;未知类型产生解析异常,未配置合法类型可返回 null;
  • 管理器或有效市场未就绪时出生查询返回 null。

故障分析

  • Corvus 找不到出生实体:星系名称、实体 ID 或生成时机与 CSV 不一致。

    • 解决方案:使用 GearIn 与 GearIn_planet1,确认生成器在玩家放置前完成。
  • 规划器将尚未建立的生涯当作随机模式:管理器未就绪时就选择地点。

    • 解决方案:等待 SectorManager 建立,再查询出生点。
  • 随机模式取得 null:当前本势力市场集合为空,或候选没有主实体。

    • 解决方案:核对本次生成中齿轮工业的启用、权重和实际市场,再进行放置。
  • 起始列表缺少配置舰船:字段名、装配 ID 或合法类型没有对应配置。

    • 解决方案:核对 startShipsSolo、startShipsCombatSmall 与已加载装配。
  • 类型查询抛出 IllegalArgumentException:请求字符串不是 StartFleetType 能识别的类型。

    • 解决方案:使用 SOLO、COMBAT_SMALL 或 RANDOM 等实际类型,修正调用输入。

总结

出生登记、市场权重与起始装配分别提供开局输入。规划器在生成后返回配置 ID 或当前最大市场,并读取固定类型的装配列表;Nexerelin 再按实际开局选择完成放置与舰队生成。查询和生成各自对应来源,两个模式的结果也就能分别解释。

建议参考项

  • exerelin.campaign.SectorManager:管理器与 isCorvusMode;
  • exerelin.world.ExerelinCorvusLocations:固定出生行查询;
  • exerelin.utilities.NexUtilsFaction:getFactionMarkets 取得当前市场;
  • exerelin.utilities.NexFactionConfig:getStartFleetForType、StartFleetType 和起始舰队集合;
  • data/config/exerelin/corvus_spawnpoints.csv:固定出生点登记。
在 GitHub 上编辑此页
上次更新: 2026/10/14 12:25
贡献者: 1847905557
上一页
登记 Nexerelin 势力与外交配置
下一页
配置 Nexerelin 战略 AI 与扩张规模