基础格式与文件结构

1. 概述

本游戏采用 XML 文件作为数据定义的主要形式,允许开发者和模组作者通过结构化的文本文件创建、修改和扩展游戏内容。游戏启动时将扫描特定目录下的 XML 文件,并根据其类型和内容载入游戏。

2. 文件系统结构

游戏会从两个主要目录读取数据:Data/Mods/。这两个目录下包含一系列“包”(Packages),每个包代表一个独立的数据集合,可以是一个核心游戏模块,也可以是一个用户创建的模组。

文件目录结构示例:

├── Data/
│   ├── Pack1/                # 数据包示例 1
│   │   ├── About/            # 包信息目录
│   │   ├── Define/           # 数据定义目录
│   │   └── Translation/      # 翻译文件目录 (当前版本未实装)
│   └── Pack2/                # 数据包示例 2
│       ├── About/
│       ├── Define/
│       └── Translation/
└── Mods/
    ├── Mod1/                 # 模组包示例 1
    │   ├── About/
    │   ├── Define/
    │   └── Translation/
    └── Mod2/                 # 模组包示例 2
        ├── About/
        ├── Define/
        └── Translation/

目录说明:

  • Data/: 包含游戏的核心内容和官方扩展数据包。
  • Mods/: 包含用户自定义的模组数据包。
  • PackN/, ModN/: 每个子文件夹被视为一个独立的“包”。包名应当具有唯一性。
  • About/: 存放包的元数据(Metaproperties)。
  • Define/: 存放各种游戏对象的具体定义。
  • Translation/: 存放多语言翻译数据(当前版本未实装)。

3. XML 文件类型

当前游戏版本主要识别并处理以下三种类型的 XML 文件:

  • About 文件: 包含包的基本信息和加载依赖关系。
  • Define 文件: 包含游戏内的各种数据定义,如物品、角色、属性等。
  • Translation 文件: 用于多语言本地化(当前版本未实装)。

4. About XML 文件

About 文件是每个包的门户,它提供了包的基本信息以及游戏加载时所需的依赖和排序数据。

  • 文件位置: 每个包的 About/ 文件夹下。
  • 文件命名: 建议命名为 About.xml
  • 根元素: 必须以 <About> 为根。
  • 数量限制: 一个包中只能包含一个 About XML 文件。

典型 About 文件示例:

<?xml version="1.0" encoding="utf-8"?>
<About>
    <!-- 包的显示名称,用于用户界面 -->
    <name>核心</name>
    <!-- 包的详细描述,解释其功能或内容 -->
    <description>这是一个基础核心模块,除非有完整的代替,否则应该永远作为启动项</description>
    <!-- 包的版本号 -->
    <version>0.1</version>
    <!-- 包的唯一标识符,必须在所有包中全局唯一 -->
    <packID>core</packID>
    <!-- 加载排序和依赖关系定义 -->
    <sort>
        <!-- 定义本包加载前必须加载的包的packID列表 -->
        <necessary></necessary>
        <!-- 定义本包应该优先于哪些包加载,填写那些包的packID列表 -->
        <before></before>
        <!-- 定义本包应该在哪些包之后加载,填写那些包的packID列表 -->
        <after></after>
    </sort>
</About>

元素说明:

  • <name>: (String) 包的显示名称,会显示在游戏的用户界面中。
  • <description>: (String) 包的详细描述,用以解释其功能或内容。
  • <version>: (String) 包的版本号,遵循语义化版本控制(如 1.0.0)或简单版本号(如 0.1)。
  • <packID>: (String, 必填) 包的唯一标识符。这个 ID 在整个游戏的数据包和模组中必须是全局唯一的,用于识别包及其依赖关系。
  • <sort>: (Object) 包含加载排序和依赖关系的定义。
    • <necessary>: (Array of String) 定义了本包加载前必须加载的包的 packID 列表。如果这些包未能加载,本包将无法加载。
    • <before>: (Array of String) 定义了本包应该优先于哪些包加载。列表中填写其他包的 packID
    • <after>: (Array of String) 定义了本包应该在哪些包之后加载。列表中填写其他包的 packID

加载机制:

游戏启动时,会首先读取所有 About.xml 文件,构建一个包的依赖图。然后根据 necessary, before, after 标签中定义的规则,确定包的加载顺序。

  • 如果多个包定义了相同的 packID,游戏启动时会报错或仅加载其中一个。
  • 如果 necessary 的包缺失,则当前包无法加载。
  • beforeafter 标签用于调整加载顺序,以解决同名 Define 数据覆盖问题或确保特定功能的前提条件。

5. Define XML 文件

Define 文件是游戏内容的核心,用于定义游戏中的各种对象、属性和规则。

  • 文件位置: 每个包的 Define/ 文件夹下。
  • 文件命名: 可以根据内容自由命名,例如 Items.xml, Characters.xml 等。
  • 根元素: 其中的每个 XML 文件必须以 <Define> 为根。
  • 内容: 可以包含任意数量和类别的各种数据定义。

核心约定:

  • 基本属性: 所有的顶级定义都必须包含以下三个属性:
    • defName: (String, 必填) 定义的唯一名称。这个名称在 该类型的数据定义中 必须是全局唯一的。例如,所有 ImageDef 都有唯一的 defName,所有 WeaponDef 也有唯一的 defName,但 ImageDefWeaponDef 可以有相同的 defName(如 TestGunItemTestGun)。
    • label: (String) 定义的显示名称,用于游戏用户界面。
    • description: (String) 定义的详细描述,用于游戏用户界面或工具提示。
  • 覆盖机制: 如果不同包(或同一包内不同文件)中同一类型的数据定义了相同的 defName,则后加载的定义会覆盖先加载的定义。这允许模组轻松地修改或替换原版游戏内容。
  • 引用机制: 当一个定义的数据字段需要引用其他数据定义时,可以通过以下两种方式:
    • 引用 defName: 直接填写被引用定义的 defName。游戏会在加载时解析这些引用。
    • 嵌套定义(匿名定义): 直接在引用位置定义一个新的对象,该对象通常没有 defName,是当前定义的私有或匿名部分。

典型 Define 文件示例:

<?xml version="1.0" encoding="utf-8"?>
<Define>
    <!-- 图片定义 -->
    <ImageDef>
        <defName>TestGunItem</defName> <!-- 唯一标识符 -->
        <path>Resources\Item\TestGun.png</path> <!-- 图片路径 -->
    </ImageDef>

    <!-- 属性定义 -->
    <AttributesDef>
        <defName>TestGun</defName> <!-- 唯一标识符 -->
        <attack>10</attack>
        <defense>3</defense>
        <attackSpeed>3</attackSpeed>
        <attackRange>10</attackRange>
        <attackTargetCount>1</attackTargetCount>
    </AttributesDef>

    <!-- 武器定义 -->
    <WeaponDef>
        <defName>TestGun</defName> <!-- 全局唯一标识符 -->
        <label>测试枪</label> <!-- 显示名称 -->
        <description>一把测试用的枪</description> <!-- 详细描述 -->
        <!-- 引用属性定义,通过defName="TestGun"引用AttributesDef中定义的属性 -->
        <attributes>TestGun</attributes>
        <type>Ranged</type>
        <textures>
            <!-- 引用ImageDef中的图片定义 -->
            <li>TestGunItem</li>
        </textures>
        <!-- 引用子弹定义,通过defName="yellowBullet"引用BulletDef -->
        <bullet>yellowBullet</bullet>
    </WeaponDef>

    <!-- 子弹定义 -->
    <BulletDef>
        <defName>yellowBullet</defName>
        <label>黄色子弹</label>
        <description>一颗黄色的子弹</description>
        <!-- 嵌套定义属性,此处的属性是当前子弹特有的匿名属性,没有defName -->
        <attributes>
            <health>1</health>
            <moveSpeed>20</moveSpeed>
        </attributes>
        <!-- 嵌套定义纹理绘制顺序,包含多个匿名绘制状态定义 -->
        <drawingOrder>
            <idle_down>
                <textures>
                    <li>yellowBullet</li>
                </textures>
            </idle_down>
            <walk_down>
                <textures>
                    <li>yellowBullet</li>
                </textures>
            </walk_down>
        </drawingOrder>
    </BulletDef>
</Define>

示例解析:

  • ImageDef: 定义了一个图像资源。
    • defNameTestGunItem,表示这是图像定义的唯一标识。
    • path 指定了图像文件在文件系统中的相对路径。
  • AttributesDef: 定义了一组属性集。
    • defNameTestGun
    • 包含了攻击、防御等具体数值。
  • WeaponDef: 定义了一个武器对象。
    • defNameTestGun
    • labeldescription 提供显示文本。
    • <attributes>TestGun</attributes>: 这里通过 defName 引用了 AttributesDef 中名为 TestGun 的属性集。
    • <textures><li>TestGunItem</li></textures>: 引用了 ImageDef 中名为 TestGunItem 的图像定义。<textures> 标签下的 <li> 元素表示一个列表项。
    • <bullet>yellowBullet</bullet>: 引用了 BulletDef 中名为 yellowBullet 的子弹定义。
  • BulletDef: 定义了一个子弹对象。
    • defNameyellowBullet
    • <attributes>: 这里没有引用已有的 AttributesDef,而是直接在此嵌套定义了一组属性。这些属性是 yellowBullet 特有的,不与其他定义共享 defName
    • <drawingOrder>: 同样采用嵌套定义的方式,为不同的动画状态(如 idle_down, walk_down)定义了各自的纹理列表。

6. Translation XML 文件 (当前版本未实装)

此类型文件未来将用于实现游戏的多语言本地化。

  • 文件位置: 每个包的 Translation/ 文件夹下。
  • 根元素: 预期的根元素将是 <Translation> 或类似的元素。
  • 内容: 届时将包含键值对形式的翻译文本,用于替换游戏中硬编码的字符串或 Define 文件中的 labeldescription

在此章节中将会介绍各种定义类型及其使用方法

定义图片资源

在游戏配置文件中,您可以使用 <ImageDef> 元素来定义图片资源。每个 <ImageDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。

功能介绍

<ImageDef> 用于加载和配置游戏所需的各种图片资源,包括单张图片、切分后的子图以及调整图片加载时的各项参数。您可以通过它指定图片路径、切分方式、像素密度以及加载时的翻转行为。

参数说明

所有的参数都必须通过嵌套元素的方式进行赋值。

  • <defName> (必需,字符串)

    • 该图片定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
    • 作为匿名定义时,此字段可以省略。
  • <label> (可选,字符串)

    • 提供一个人类可读的标签,用于更好地理解该图片定义的用途。
  • <description> (可选,字符串)

    • 提供更详细的文本描述,解释该图片定义的具体内容或特殊用途。
  • <path> (必需,字符串)

    • 指定图片资源的实际存储路径。
    • 路径前缀约定:
      • otherPackID:相对地址: 表示加载 otherPackID 包下的相对路径图片资源。
      • 空前缀: 表示加载当前定义所在包的相对路径图片资源。
      • res:相对地址: 表示加载游戏编译过程中,项目 Resources 文件夹下的图片资源。res: 前缀的优先级高于包 ID 前缀。
  • <wCount> (必需,整数)

    • 指定将图片在水平方向上切分为多少个子图。要求图片的宽度可以被 wCount 整除。
  • <hCount> (必需,整数)

    • 指定将图片在垂直方向上切分为多少个子图。要求图片的高度可以被 hCount 整除。
    • wCounthCount 大于 1 时,图片将被切分为多个子图。子图按照从上到下,从左到右,从 0 开始的顺序进行编号。
  • <pixelsPerUnit> (可选,整数,默认为 16)

    • 定义图片在游戏世界中绘制时的像素密度。例如,如果设置为 16,则 16 像素宽的图片在绘制时将占据 1 个单位的宽度。
  • <flipX> (可选,布尔值,默认为 false)

    • 如果设置为 true,则在加载时沿 X 轴翻转图片。
    • 重要提示: 对于多子图图片,翻转操作是在图片被切分之后进行的。defName_0 始终代表翻转前的图片左上角子图。这意味着先进行裁剪,再对每个子图进行翻转。
  • <flipY> (可选,布尔值,默认为 false)

    • 如果设置为 true,则在加载时沿 Y 轴翻转图片。
    • 重要提示: 对于多子图图片,翻转操作是在图片被切分之后进行的。defName_0 始终代表翻转前的图片左上角子图。这意味着先进行裁剪,再对每个子图进行翻转。

引用方式

  • 当其他定义需要引用某个图片资源时:
    • defName: 始终代表完整图片(无论是否被切分)。
    • defName_编号: (例如 myImage_0, myImage_5) 引用对应的子图。

示例

示例 1:定义一张单图图片

<Define>
    <ImageDef>
        <defName>PlayerSprite</defName>
        <label>玩家角色图片</label>
        <description>用于绘制玩家角色的基本图片。</description>
        <path>Textures/Player/player_base.png</path>
        <pixelsPerUnit>32</pixelsPerUnit>
        <flipX>false</flipX>
        <flipY>false</flipY>
    </ImageDef>
</Define>

在其他定义中引用此图片:

  • 引用完整图片:PlayerSprite

示例 2:定义一张切分后的图片集

假设 enemy_sheet.png 是一张 128x64 像素的图集,包含 4x2 共 8 个子图。

<Define>
    <ImageDef>
        <defName>EnemySprites</defName>
        <label>敌人动画图集</label>
        <description>包含敌人的行走和攻击动画帧。</description>
        <path>res:Sprites/Enemies/enemy_sheet.png</path>
        <wCount>4</wCount>
        <hCount>2</hCount>
        <pixelsPerUnit>16</pixelsPerUnit>
    </ImageDef>
</Define>
  • 引用完整图集:EnemySprites
  • 引用第一个子图(左上角):EnemySprites_0
  • 引用第二个子图:EnemySprites_1
  • 引用第五个子图(第二行第一个):EnemySprites_4

示例 3:定义一张来自其他包的图片并翻转加载

<Define>
    <ImageDef>
        <defName>FlippedBackground</defName>
        <label>翻转的背景图</label>
        <description>从UI包加载并水平翻转的背景图片。</description>
        <path>UIPack:Backgrounds/main_bg.jpg</path>
        <wCount>1</wCount>
        <hCount>1</hCount>
        <pixelsPerUnit>100</pixelsPerUnit>
        <flipX>true</flipX>
    </ImageDef>
</Define>

在其他定义中引用此图片:

  • 引用完整图片:FlippedBackground

注意事项

  • 图片切分与翻转的顺序: 务必记住,flipXflipY 操作是在 wCounthCount 切分操作之后进行的。这意味着即使图片被翻转,defName_0 始终指向原始图片(未翻转前)的左上角子图,然后该子图才会被独立翻转。
  • 像素整除性: 确保您的图片尺寸可以被 wCounthCount 整除,否则切分可能不会按预期工作或导致错误。
  • 路径前缀优先级: res: 前缀的解析优先级最高,其次是包 ID 前缀,最后是当前包。
  • defName 唯一性: 强烈建议所有 <ImageDef>defName 都是全局唯一的,以避免在加载和引用时出现混淆或不确定的行为。如果存在重复的 defName,后加载的定义将会覆盖先加载的。
  • 匿名定义:ImageDef 作为其他定义的内部结构使用时,defName 可以省略,此时它将作为一个匿名的、局部可用的图片定义。在这种情况下,该图片无法通过名称在外部引用。

定义音频资源

在游戏配置文件中,您可以使用 <AudioDef> 元素来定义音频资源。每个 <AudioDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。

功能介绍

<AudioDef> 用于加载和配置游戏所需的各种音频资源,例如背景音乐、音效、语音等。您可以通过它指定音频文件的存储路径。

参数说明

所有的参数都必须通过嵌套元素的方式进行赋值。

  • <defName> (必需,字符串)

    • 该音频定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
    • 作为匿名定义时,此字段可以省略。
  • <label> (可选,字符串)

    • 提供一个人类可读的标签,用于更好地理解该音频定义的用途。
  • <description> (可选,字符串)

    • 提供更详细的文本描述,解释该音频定义的具体内容或特殊用途。
  • <path> (必需,字符串)

    • 指定音频资源的实际存储路径。
    • 路径前缀约定:
      • otherPackID:相对地址: 表示加载 otherPackID 包下的相对路径音频资源。
      • 空前缀: 表示加载当前定义所在包的相对路径音频资源。
      • res:相对地址: 表示加载游戏编译过程中,项目 Resources 文件夹下的音频资源。res: 前缀的优先级高于包 ID 前缀。

引用方式

  • 当其他定义需要引用某个音频资源时,始终使用该音频定义的 defName

示例

示例 1:定义背景音乐

<Define>
    <AudioDef>
        <defName>BackgroundMusic_MainTheme</defName>
        <label>主界面背景音乐</label>
        <description>应用于游戏主界面的循环背景音乐。</description>
        <path>Audio/BGM/main_theme.mp3</path>
    </AudioDef>
</Define>

在其他定义中引用此音频:BackgroundMusic_MainTheme

示例 2:定义一个来自 Resources 文件夹的音效

<Define>
    <AudioDef>
        <defName>UISound_Click</defName>
        <label>UI点击音效</label>
        <description>用于按钮点击时的反馈音效。</description>
        <path>res:Sounds/UI/click.wav</path>
    </AudioDef>
</Define>

在其他定义中引用此音频:UISound_Click

示例 3:定义一个来自其他包的语音文件

<Define>
    <AudioDef>
        <defName>Dialogue_Greeting</defName>
        <label>角色欢迎对话</label>
        <description>角色首次见面时的语音问候。</description>
        <path>DialoguePack:Voice/greet_player.ogg</path>
    </AudioDef>
</Define>

在其他定义中引用此音频:Dialogue_Greeting

注意事项

  • 路径前缀优先级: res: 前缀的解析优先级最高,其次是包 ID 前缀,最后是当前包。
  • defName 唯一性: 强烈建议所有 <AudioDef>defName 都是全局唯一的,以避免在加载和引用时出现混淆或不确定的行为。如果存在重复的 defName,后加载的定义将会覆盖先加载的。
  • 匿名定义:AudioDef 作为其他定义的内部结构使用时,defName 可以省略,此时它将作为一个匿名的、局部可用的音频定义。在这种情况下,该音频无法通过名称在外部引用。
  • 音频格式: 请确保您引用的音频文件格式是游戏引擎支持的格式(例如 .mp3, .wav, .ogg 等)。

XML 使用说明 - 定义属性集

在游戏配置文件中,您可以使用 <AttributesDef> 元素来定义一组角色或物品的属性。每个 <AttributesDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。

功能介绍

<AttributesDef> 用于封装和定义一系列常见的游戏属性,如生命值、移动速度、攻击力等。这使得在游戏中创建不同类型单位或物品时,可以方便地引用或调整这些基础属性。

参数说明

所有的参数都必须通过嵌套元素的方式进行赋值。

  • <defName> (必需,字符串)

    • 该属性集定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
    • 作为匿名定义时,此字段可以省略。
  • <label> (可选,字符串)

    • 提供一个人类可读的标签,用于更好地理解该属性集定义的用途。
  • <description> (可选,字符串)

    • 提供更详细的文本描述,解释该属性集定义的具体内容或特殊用途。
  • <health> (可选,整数,默认为 10)

    • 定义实体对象的生命值或耐久度。
  • <moveSpeed> (可选,浮点数,默认为 1)

    • 定义实体对象的移动速度。
  • <attack> (可选,整数,默认为 1)

    • 定义实体对象的攻击力。
  • <defense> (可选,整数,默认为 0)

    • 定义实体对象的防御力。
  • <attackSpeed> (可选,浮点数,默认为 2)

    • 定义实体对象的攻击速度,例如每秒攻击次数或攻击间隔。
  • <attackRange> (可选,浮点数,默认为 3)

    • 定义实体对象的攻击范围。
  • <attackTargetCount> (可选,整数,默认为 1)

    • 定义实体对象每次攻击可以命中的目标数量。

引用方式

  • 当其他定义需要引用某个属性集时,始终使用该属性集定义的 defName

示例

示例 1:定义一个基础敌人属性集

<Define>
    <AttributesDef>
        <defName>BasicEnemyAttributes</defName>
        <label>基础敌人属性</label>
        <description>小型敌人的默认属性配置。</description>
        <health>50</health>
        <moveSpeed>1.5</moveSpeed>
        <attack>10</attack>
        <defense>2</defense>
        <attackSpeed>1.8</attackSpeed>
        <attackRange>2.5</attackRange>
        <attackTargetCount>1</attackTargetCount>
    </AttributesDef>
</Define>

在其他定义中引用此属性集:BasicEnemyAttributes

示例 2:定义一个防御塔的属性集

<Define>
    <AttributesDef>
        <defName>DefenseTowerAttributes</defName>
        <label>防御塔属性</label>
        <description>用于炮塔的属性配置。</description>
        <health>200</health>
        <moveSpeed>0</moveSpeed> <!-- 塔不能移动 -->
        <attack>25</attack>
        <defense>10</defense>
        <attackSpeed>1.0</attackSpeed>
        <attackRange>7.0</attackRange>
        <attackTargetCount>1</attackTargetCount>
    </AttributesDef>
</Define>

在其他定义中引用此属性集:DefenseTowerAttributes

示例 3:在另一个定义中以内联方式定义属性集(匿名定义)

某些情况下,当一个属性集只在特定位置使用,且不需要全局引用时,可以作为另一个定义的子元素进行匿名定义,此时 <defName> 可省略。

<Define>
    <UnitDef>
        <defName>SpecialBossUnit</defName>
        <sprite>BossImage</sprite>
        <baseAttributes><!-- 匿名定义,没有 defName -->
            <health>1000</health>
            <moveSpeed>0.8</moveSpeed>
            <attack>50</attack>
            <defense>20</defense>
            <attackSpeed>0.5</attackSpeed>
            <attackRange>4.0</attackRange>
            <attackTargetCount>3</attackTargetCount>
        </baseAttributes>
    </UnitDef>
</Define>

在此示例中,<AttributesDef> 没有 defName,它的属性只供 SpecialBossUnit 使用。

注意事项

  • defName 唯一性: 强烈建议所有 <AttributesDef>defName 都是全局唯一的,以避免在加载和引用时出现混淆或不确定的行为。如果存在重复的 defName,后加载的定义将会覆盖先加载的。
  • 匿名定义:<AttributesDef> 作为其他定义的内部结构使用时,defName 可以省略,此时它将作为一个匿名的、局部可用的属性集定义。在这种情况下,该属性集无法通过名称在外部引用。
  • 默认值: 如果某个属性未在 XML 中明确定义,它将使用其默认值。在设计属性集时,可以只指定需要修改的属性,其他属性将沿用默认值。

XML 使用说明 - 定义行为树

在游戏配置文件中,您可以使用 <BehaviorTreeDef> 元素来定义角色的行为树逻辑。每个 <BehaviorTreeDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。

功能介绍

<BehaviorTreeDef> 用于构建复杂的AI行为逻辑,通过树状结构组织一系列行为节点。每个节点代表一个决策或行动,它们可以嵌套形成复杂的判断和执行流程。行为树支持多种定义方式,包括传统定义和更简洁的节点定义。行为树的根节点默认是 ThinkNode_Selector

参数说明

所有的参数都必须通过嵌套元素的方式进行赋值。

  • <defName> (必需,字符串)

    • 该行为树定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
    • 作为匿名定义时,此字段可以省略。
  • <label> (可选,字符串)

    • 提供一个人类可读的标签,用于更好地理解该行为树定义的用途。
  • <description> (可选,字符串)

    • 提供更详细的文本描述,解释该行为树定义的具体内容或特殊用途。
  • <childTree> (可选,行为树数组)

    • 包含当前行为树节点的子节点列表。每个子节点本身也是一个 <BehaviorTreeDef>
    • 数组的定义方式为 <childTree><li>元素1</li><li>元素2</li></childTree><li> 元素本身会被忽略。
  • <className> (可选,字符串,默认为 "ThinkNode_Selector")

    • 指定当前行为树 根节点 所使用的类名。如果省略,则默认为 ThinkNode_Selector。这些类是预定义好的行为节点类型,例如 ThinkNode_SelectorThinkNode_SequenceJobNode_AttackTarget 等。具体的可用类名将在下方“行为树节点类型”部分详细介绍。
  • <value> (可选,字符串)

    • 某些行为树类需要初始化参数,value 元素用于提供这些参数。例如,条件判断节点可能需要一个函数调用的字符串作为判断依据。当 <value> 用于根节点时,它将作为根节点的初始化参数。

特殊初始化方式 —— 使用 <Node> 元素

为了使行为树的定义更加简洁直观,当 <BehaviorTreeDef> 作为父级时,其子节点可以直接使用 <Node> 元素进行定义。

Node 元素参数说明:

  • className (属性,字符串)
    • 直接作为 <Node> 元素的属性指定子节点的类名。
  • value (属性,字符串)
    • 直接作为 <Node> 元素的属性指定子节点的初始化参数。

引用方式和匿名定义

行为树的子节点可以通过两种方式定义:

  1. 简便的匿名定义 (不支持引用)

    • 直接在 <BehaviorTreeDef> 内部或者其他 <Node> 元素下嵌套另一个 <Node> 元素来定义子节点。
    • 这种方式下,子节点没有 defName,只能作为当前父节点的直接子级使用,无法被其他行为树定义引用。
    • 语法:
      <Node className="子节点类名" value="子节点参数">
          <!-- 更多嵌套 Node 元素 -->
      </Node>
      
  2. 传统匿名定义 (支持引用)

    • <childTree> 元素内使用 <li> 元素包裹一个完整的 <BehaviorTreeDef> 结构。
    • 这种方式下,子节点可以拥有 defName,从而允许其他行为树定义引用它。当引用一个已命名的行为树定义作为子节点时,可以直接在 <li> 中放置被引用行为树的 defName
    • 语法:
      • 匿名子节点:
        <childTree>
            <li>
                <className>子节点类名</className>
                <value>子节点参数</value>
                <childTree>
                    <!-- ... 更多子节点 ... -->
                </childTree>
            </li>
        </childTree>
        
      • 引用命名子节点:
        <childTree>
            <li>引用行为树的defName</li>
        </childTree>
        

行为树节点类型

以下是当前可用的行为树节点类型:

  • ThinkNode_Selector: 选择节点。会不断从上到下尝试执行其子节点,直到某个子节点返回成功后,该选择节点重置并再次从第一个子节点开始判断。如果所有子节点都返回失败,则此选择节点返回失败。
  • ThinkNode_Sequence: 顺序节点。按顺序从上到下执行子节点。如果任何一个子节点返回失败,则此顺序节点重置并返回失败。只有所有子节点都成功执行后,此顺序节点才返回成功。
  • ThinkNode_Conditional: 条件节点。当其 value 中定义的条件满足(返回 true)时,它会像一个 ThinkNode_Selector 一样执行其子节点;否则返回失败。
  • ThinkNode_Branch: 分支节点。需要定义2到3个子节点。当第一个子节点返回 true 时,执行第二个子节点;否则,如果第三个子节点存在,则执行第三个子节点。如果子节点不足2个,则该分支节点总是返回失败。
  • ConstantNode_Failure: 常量节点。总是返回失败状态。
  • ConstantNode_Running: 常量节点。总是返回运行中状态。
  • ConstantNode_Success: 常量节点。总是返回成功状态。
  • JobNode_XXX: 工作节点。所有实际执行具体动作的叶节点都以 JobNode_ 为前缀。例如:
    • JobNode_MoveToAttackRange: 移动到攻击范围。
    • JobNode_AttackTarget: 攻击目标。
    • JobNode_Wander: 随机游荡。
    • JobNode_Idle: 空闲。
    • 注意: 具体的 JobNode_ 类型会根据游戏功能而定,请查阅相关文档获取完整列表。

示例

示例 1:使用 <Node> 元素的简便匿名定义

这是一个典型的怪物行为树,根节点使用默认的 ThinkNode_Selector

<Define>
    <BehaviorTreeDef>
        <defName>BasicMonsterBehavior</defName>
        <label>基本怪物行为</label>
        <description>定义了怪物在不同情况下的行为逻辑。</description>
        <!-- 根节点默认是 ThinkNode_Selector -->
        <Node className="ThinkNode_Conditional" value="HasEnemyInSight()"> <!-- 子节点1:条件 -->
            <Node className="ThinkNode_Sequence"> <!-- 条件满足时执行的序列 -->
                <Node className="ThinkNode_Conditional" value="HasWeapon()"> <!-- 更深一层的条件 -->
                    <Node className="JobNode_MoveToAttackRange"/> <!-- 行为:移动到攻击范围 -->
                    <Node className="JobNode_AttackTarget"/> <!-- 行为:攻击目标 -->
                </Node>
                <Node className="JobNode_FleeJob"/> <!-- 如果有敌人但没有武器,则逃跑 -->
            </Node>
        </Node>
        <Node className="ThinkNode_Sequence"> <!-- 子节点2:游荡和空闲 -->
            <Node className="JobNode_Wander"/> <!-- 行为:随机游荡 -->
            <Node className="JobNode_Idle"/> <!-- 行为:空闲 -->
        </Node>
    </BehaviorTreeDef>
</Define>

示例 2:修改根节点的工作类,并使用传统匿名定义方式 (支持引用)

这个示例展示了如何修改根节点的工作类为 ThinkNode_Sequence,并展示了如何引用一个预定义的子行为树。

假设我们有一个预定义的行为树叫做 AttackLogic

<Define>
    <BehaviorTreeDef>
        <defName>AttackLogic</defName>
        <label>攻击逻辑</label>
        <className>ThinkNode_Sequence</className>
        <childTree>
            <li>
                <className>JobNode_MoveToAttackRange</className>
            </li>
            <li>
                <className>JobNode_AttackTarget</className>
            </li>
        </childTree>
    </BehaviorTreeDef>
</Define>

现在,我们可以在另一个行为树中引用这个 AttackLogic,并自定义根节点类型:

<Define>
    <BehaviorTreeDef>
        <defName>AdvancedMonsterBehavior</defName>
        <label>进阶怪物行为</label>
        <description>定义了更复杂的怪物行为树,根节点为序列。</description>
        <className>ThinkNode_Sequence</className> <!-- 将根节点指定为 ThinkNode_Sequence -->
        <childTree>
           <li> <!-- 顺序节点1:检查敌人并决定攻击或逃跑 -->
                <className>ThinkNode_Conditional</className>
                <value>HasEnemyInSight()</value>
                <childTree>
                    <li> <!-- 在有敌人且有武器的情况下执行攻击逻辑,否则逃跑 -->
                        <className>ThinkNode_Branch</className>
                        <li> <className>ThinkNode_Conditional</className><value>HasWeapon()</value> </li> <!-- 条件:是否有武器 -->
                        <li>AttackLogic</li> <!-- 引用已定义的 AttackLogic 行为树 -->
                        <li> <className>JobNode_FleeJob</className> </li> <!-- 否则逃跑 -->
                    </li>
                </childTree>
            </li>
            <li> <!-- 顺序节点2:如果上层成功,则随后进行游荡和空闲 -->
                <className>ThinkNode_Sequence</className>
                <childTree>
                    <li>
                        <className>JobNode_Wander</className>
                    </li>
                    <li>
                        <className>JobNode_Idle</className>
                    </li>
                </childTree>
           </li>
        </childTree>
    </BehaviorTreeDef>
</Define>

在上述示例中,<li>AttackLogic</li> 直接引用了之前使用 defName 定义的 AttackLogic 行为树。

注意事项

  • 根节点的定义: <BehaviorTreeDef> 自身的 <className><value> 用于定义整个行为树的根节点。如果未指定 <className>,则根节点默认为 ThinkNode_Selector
  • defName 唯一性: defName 应该在同类型(BehaviorTreeDef)的全局范围内保持唯一。如果定义了同名的 defName,后加载的定义会覆盖先加载的。
  • 匿名定义与引用: 如果行为树子节点不需要被重用或在其他地方引用,简便的 <Node> 嵌套方式更简洁。如果子行为树可能被多个父行为树引用,或者需要更清晰的模块化结构,应使用带有 defName 的传统定义方式。
  • 类名可用性: <className> 中指定的类名必须是游戏代码中实际存在的行为树节点类。请查阅最新的游戏API文档或相关开发指南获取可用类名的详细列表。
  • ThinkNode_Branch 子节点数量: ThinkNode_Branch 节点要求至少有两个子节点才能正常工作(条件和执行体)。如果只有2个子节点,则当条件不满足时,该节点表现为失败。如果定义了3个子节点,则第一个子节点为条件,第二个为条件满足时执行,第三个为条件不满足时执行。如果子节点不足2个,ThinkNode_Branch 总是返回失败。

XML 使用说明 - 定义绘制结构树

在游戏配置文件中,您可以使用 <DrawNodeDef> 元素来定义复杂的绘制结构树。每个 <DrawNodeDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。

功能介绍

<DrawNodeDef> 用于构建游戏对象的视觉表现结构,可以组合多个纹理和子节点来形成复杂的身体结构、动画序列或可动部件。它支持纹理引用、节点定位和动画帧率设置。

参数说明

绝大多数参数都必须通过嵌套元素的方式进行赋值。nodeNamepositionFPS 允许在属性栏定义,这是为了方便紧凑的结构定义。

  • <defName> (必需,字符串)

    • 该绘制结构定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
    • 作为匿名定义时,此字段可以省略。
  • <label> (可选,字符串)

    • 提供一个人类可读的标签,用于更好地理解该绘制结构定义的用途。
  • <description> (可选,字符串)

    • 提供更详细的文本描述,解释该绘制结构定义的具体内容或特殊用途。
  • <textures> (可选,字符串数组)

    • 一个字符串数组,包含对 ImageDef 的引用。这些引用可以是完整的 ImageDefdefName,也可以是其子图的 defName_编号
    • 数组的定义方式为 <textures><li>元素1</li><li>元素2</li></textures><li> 元素本身会被忽略。
  • <nodes> (可选,绘制节点数组)

    • 一个 DrawNodeDef 数组,包含当前绘制结构树的子节点。每个子节点本身也是一个 <DrawNodeDef>,可以进一步定义其自身的纹理、位置和子节点。
    • 数组的定义方式为 <nodes><li>元素1</li><li>元素2</li></nodes><li> 元素本身会被忽略。
  • nodeName (属性,字符串)

    • 定义当前绘制节点的名称。此名称可用于在代码中标识或操作特定的绘制节点。允许在属性栏定义。
  • position (属性,Vector2 类型,默认为 (0, 0))

    • 定义当前绘制节点相对于其父节点的位置偏移。此参数只能在属性栏定义
    • 定义语法:
      • 位置值必须用括号 ()、方括号 [] 或不带包裹符号的形式表示。
      • 两个坐标之间可以用空格 、逗号 , 或分号 ; 分隔。
    • 例如:position="[1.5, -2]"position="(5; 10)"position="3 4.5"
  • FPS (属性,浮点数,默认为 5f)

    • textures 数组中包含多个纹理时,此参数定义纹理之间切换的帧率(每秒帧数),用于创建动画。允许在属性栏定义。

引用方式和匿名定义

  • 引用 ImageDef<textures> 数组中,您可以使用 ImageDefdefName 来引用完整的图片,或者使用 defName_编号 来引用图片切分后的特定子图。

  • 引用 DrawNodeDef<nodes> 数组中,您可以引用其他已定义的 <DrawNodeDef>,或者进行匿名定义。

    • 引用已命名定义: 直接在 <li> 元素中放置被引用 DrawNodeDefdefName
    • 匿名定义: 直接在 <li> 元素中定义子 DrawNodeDef 的所有属性和子元素。<li> 元素同时作为类型说明符和匿名定义的载体。

示例

示例 1:定义一个静态的身体区域(头部),包含单个纹理

<Define>
    <DrawNodeDef defName="HumanoidHead" nodeName="Head" position="[0, 1.5]">
        <label>人形生物头部</label>
        <description>定义了人形生物的头部结构,包含其纹理。</description>
        <textures>
            <li>HeadTexture</li> <!-- 假设 HeadTexture 是一个已定义的 ImageDef -->
        </textures>
    </DrawNodeDef>
</Define>

示例 2:定义一个具有动画的腿部,并作为另一个绘制节点的子节点

假设我们有一个 LegAnimationImageImageDef,它被切分成了多个子图(例如 LegAnimationImage_0LegAnimationImage_1 等)。

<Define>
    <DrawNodeDef defName="HumanoidLeg" nodeName="LeftLeg" position="[-0.5, -1]" FPS="8.0">
        <label>人形生物左腿</label>
        <description>定义了人形生物的左腿,包含一个简单的行走动画。</description>
        <textures>
            <li>LegAnimationImage_0</li>
            <li>LegAnimationImage_1</li>
            <li>LegAnimationImage_2</li>
            <!-- ...更多动画帧... -->
        </textures>
    </DrawNodeDef>

    <DrawNodeDef defName="HumanoidBody" nodeName="Body" position="[0, 0]">
        <label>人形生物身体</label>
        <description>定义了人形生物的身体部分。</description>
        <textures>
            <li>BodyTexture</li>
        </textures>
        <nodes>
            <li>HumanoidLeg</li> <!-- 引用已定义的 HumanoidLeg -->
            <li> <!-- 匿名定义右腿:直接在 <li> 标签中定义其属性和子元素 -->
                <textures>
                    <li>LegAnimationImage_0</li>
                    <li>LegAnimationImage_1</li>
                    <li>LegAnimationImage_2</li>
                </textures>
                <nodeName>RightLeg</nodeName>
                <position>[0.5, -1]</position>
                <FPS>8.0</FPS>
            </li>
        </nodes>
    </DrawNodeDef>
</Define>

示例 3:复杂的嵌套绘制结构 (已修正匿名定义格式)

<Define>
    <DrawNodeDef defName="PlayerCharacter" nodeName="Root" position="[0,0]">
        <label>玩家角色绘制</label>
        <description>定义了玩家角色的完整绘制结构。</description>
        <textures>
            <li>BasePelvisTexture</li>
        </textures>
        <nodes>
            <li>HumanoidHead</li> <!-- 引用示例1中的头部 -->
            <li>HumanoidBody</li> <!-- 引用示例2中的身体 -->
            <li> <!-- 匿名定义一个武器节点 -->
                <nodeName>WeaponHand</nodeName>
                <position>[0.8, -0.2]</position>
                <textures>
                    <li>SwordTexture</li>
                </textures>
                <nodes>
                    <li> <!-- 匿名定义武器尖端节点 -->
                        <nodeName>WeaponTip</nodeName>
                        <position>[0.5, 0]</position>
                        <!-- 只有位置,没有纹理 -->
                    </li>
                </nodes>
            </li>
        </nodes>
    </DrawNodeDef>
</Define>

复杂参数:position 属性定义

position 参数是一个 Vector2 类型,它只能通过属性的方式在 DrawNodeDef 标签中进行定义。其语法具有一定的灵活性。

语法规则:

  • 包裹符号: 可以使用 () (括号)、[] (方括号) 包裹 x 和 y 坐标,或者完全不使用包裹符号。
  • 分隔符: x 和 y 坐标之间可以使用空格 、逗号 , 或分号 ; 进行分隔。

常见示例:

  • 无包裹,空格分隔: position="1.5 -2.0"
  • 无包裹,逗号分隔: position="1.5,-2.0"
  • 无包裹,分号分隔: position="1.5;-2.0"
  • 括号包裹,逗号分隔: position="(1.5, -2.0)"
  • 方括号包裹,分号分隔: position="[1.5; -2.0]"
  • 整数值: position="10 5"
  • 浮点数: position="0.5 0.5"

注意事项: 当定义 position 时,请确保只在 DrawNodeDef 标签的属性部分进行定义,或者在数组中进行匿名定义时,作为 <li> 元素的属性进行定义。不要尝试通过 <position> 元素来定义,因为 Vector2 不是 Define 的子类,不支持元素定义方式。

XML 使用说明 - 定义绘制顺序集

在游戏配置文件中,您可以使用 <DrawingOrderDef> 元素来定义一个实体在不同状态和朝向下的绘制节点集合。每个 <DrawingOrderDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。

功能介绍

<DrawingOrderDef> 用于为游戏中的实体(如角色、单位)提供一套完整的、基于状态和朝向的视觉表现配置。它允许您为实体的“闲置”、“行走”、“近战攻击”、“远程攻击”和“死亡”等行为,以及“向上”、“向下”、“向左”、“向右”等朝向,指定不同的绘制结构 (DrawNodeDef)。这使得实体的行为和动画能够无缝地与视觉呈现相结合。

参数说明

所有的参数都必须通过嵌套元素的方式进行赋值。每个参数都期望一个 <DrawNodeDef> 引用或匿名定义,用于描述该特定状态和朝向下的绘制内容。

  • <defName> (必需,字符串)

    • 该绘制顺序集定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
    • 作为匿名定义时,此字段可以省略。
  • <label> (可选,字符串)

    • 提供一个人类可读的标签,用于更好地理解该绘制顺序集定义的用途。
  • <description> (可选,字符串)

    • 提供更详细的文本描述,解释该绘制顺序集的具体内容或特殊用途。
  • 闲置状态(Idle States)

    • <idle_down>:实体向下(前方)闲置时的绘制节点。
    • <idle_up>:实体向上(后方)闲置时的绘制节点。
    • <idle_left>:实体向左闲置时的绘制节点。
    • <idle_right>:实体向右闲置时的绘制节点。
  • 行走状态(Walk States)

    • <walk_down>:实体向下行走时的绘制节点。
    • <walk_up>:实体向上行走时的绘制节点。
    • <walk_left>:实体向左行走时的绘制节点。
    • <walk_right>:实体向右行走时的绘制节点。
  • 近战攻击状态(Melee Attack States)

    • <meleeAttack_down>:实体向下近战攻击时的绘制节点。
    • <meleeAttack_up>:实体向上近战攻击时的绘制节点。
    • <meleeAttack_left>:实体向左近战攻击时的绘制节点。
    • <meleeAttack_right>:实体向右近战攻击时的绘制节点。
  • 远程攻击状态(Ranged Attack States)

    • <rangedAttack_down>:实体向下远程攻击时的绘制节点。
    • <rangedAttack_up>:实体向上远程攻击时的绘制节点。
    • <rangedAttack_left>:实体向左远程攻击时的绘制节点。
    • <rangedAttack_right>:实体向右远程攻击时的绘制节点。
  • 死亡状态(Death States)

    • <death_down>:实体向下死亡时的绘制节点。
    • <death_up>:实体向上死亡时的绘制节点。
    • <death_left>:实体向左死亡时的绘制节点。
    • <death_right>:实体向右死亡时的绘制节点。

缺项替换机制

为了减少重复定义,<DrawingOrderDef> 内置了缺项替换机制。当某个特定的状态和朝向没有被明确定义时,系统会尝试寻找最接近的替代项。替换规则遵循以下优先级:

  1. 同一类别内替换: 替换不会跨越不同的行为类别(例如,idle_down 不会替换 walk_down)。
  2. 左右优先互相替换: 如果 _left_right 方向缺失,系统会优先使用同类别下的另一个左右方向。例如,如果 idle_left 缺失,会尝试使用 idle_right
  3. 上下优先互相替换: 如果 _up_down 方向缺失,系统会优先使用同类别下的另一个上下方向。例如,如果 idle_up 缺失,会尝试使用 idle_down

引用方式

  • 当其他定义(例如角色定义)需要使用这套绘制动画时,始终使用该绘制顺序集定义的 defName

示例

示例 1:一个完整的角色绘制顺序集定义

<Define>
    <!-- 假设 Character_Maid_Walk_0 到 Character_Maid_Walk_38 等 ImageDef 已经存在 -->
    <DrawingOrderDef>
        <defName>MaidDrawingOrder</defName>
        <label>女仆角色绘制顺序</label>
        <description>包含所有方向和状态的动画。</description>

        <!-- 闲置状态 -->
        <idle_up>
            <textures>
                <li>Character_Maid_Walk_37</li> <!-- 引用 ImageDef -->
            </textures>
        </idle_up>
        <idle_down>
            <textures>
                <li>Character_Maid_Walk_1</li>
            </textures>
        </idle_down>
        <idle_left>
            <textures>
                <li>Character_Maid_Walk_13</li>
            </textures>
        </idle_left>
        <idle_right>
            <textures>
                <li>Character_Maid_Walk_25</li>
            </textures>
        </idle_right>

        <!-- 行走状态 (动画) -->
        <walk_up>
            <FPS>5.0</FPS>
            <textures>
                <li>Character_Maid_Walk_36</li>
                <li>Character_Maid_Walk_37</li>
                <li>Character_Maid_Walk_38</li>
                <li>Character_Maid_Walk_37</li>
            </textures>
        </walk_up>
        <walk_down>
            <FPS>5.0</FPS>
            <textures>
                <li>Character_Maid_Walk_0</li>
                <li>Character_Maid_Walk_1</li>
                <li>Character_Maid_Walk_2</li>
                <li>Character_Maid_Walk_1</li>
            </textures>
        </walk_down>
        <walk_left>
            <FPS>5.0</FPS>
            <textures>
                <li>Character_Maid_Walk_12</li>
                <li>Character_Maid_Walk_13</li>
                <li>Character_Maid_Walk_14</li>
                <li>Character_Maid_Walk_13</li>
            </textures>
        </walk_left>
        <walk_right>
            <FPS>5.0</FPS>
            <textures>
                <li>Character_Maid_Walk_24</li>
                <li>Character_Maid_Walk_25</li>
                <li>Character_Maid_Walk_26</li>
                <li>Character_Maid_Walk_25</li>
            </textures>
        </walk_right>

        <!-- 近战攻击状态 (动画帧,假设testPawn_2,6,10,14是单帧或动画的第一帧) -->
        <meleeAttack_up>
            <textures>
                <li>testPawn_2</li>
            </textures>
        </meleeAttack_up>
        <meleeAttack_down>
            <textures>
                <li>testPawn_6</li>
            </textures>
        </meleeAttack_down>
        <meleeAttack_left>
            <textures>
                <li>testPawn_10</li>
            </textures>
        </meleeAttack_left>
        <meleeAttack_right>
            <textures>
                <li>testPawn_14</li>
            </textures>
        </meleeAttack_right>

        <!-- 远程攻击状态 -->
        <rangedAttack_up>
            <textures>
                <li>testPawn_3</li>
            </textures>
        </rangedAttack_up>
        <rangedAttack_down>
            <textures>
                <li>testPawn_7</li>
            </textures>
        </rangedAttack_down>
        <rangedAttack_left>
            <textures>
                <li>testPawn_11</li>
            </textures>
        </rangedAttack_left>
        <rangedAttack_right>
            <textures>
                <li>testPawn_15</li>
            </textures>
        </rangedAttack_right>

        <!-- 死亡状态 -->
        <death_down>
            <textures>
                <li>Character_Maid_Death_0</li>
            </textures>
            <FPS>2.0</FPS>
        </death_down>
        <!-- 其他死亡方向未定义,将使用 death_down 进行替换 -->
    </DrawingOrderDef>
</Define>

在其他定义中引用此绘制顺序集:MaidDrawingOrder

示例 2:利用缺项替换机制的简化定义

<Define>
    <DrawingOrderDef>
        <defName>SimpleMonsterDrawingOrder</defName>
        <label>简易怪物绘制</label>

        <!-- 闲置只定义向下和向左,上下、左右会自动替换 -->
        <idle_down>
            <textures>
                <li>Monster_Idle_Front</li>
            </textures>
        </idle_down>
        <idle_left>
            <textures>
                <li>Monster_Idle_Side</li>
            </textures>
        </idle_left>
        <!-- idle_up 会使用 idle_down -->
        <!-- idle_right 会使用 idle_left -->

        <!-- 行走只定义向下,所有行走方向都将使用此动画 -->
        <walk_down>
            <FPS>3.0</FPS>
            <textures>
                <li>Monster_Walk_Front_0</li>
                <li>Monster_Walk_Front_1</li>
            </textures>
        </walk_down>
        <!-- walk_up, walk_left, walk_right 都会使用 walk_down -->

        <!-- 死亡只定义向下 -->
        <death_down>
            <textures>
                <li>Monster_Death_0</li>
            </textures>
        </death_down>
    </DrawingOrderDef>
</Define>

此示例展示了如何通过省略部分朝向的定义,利用系统的替换机制来简化配置,尤其适用于那些在不同朝向表现差别不大的实体。

注意事项

  • defName 唯一性: 强烈建议所有 <DrawingOrderDef>defName 都是全局唯一的,以避免在加载和引用时出现混淆或不确定的行为。如果存在重复的 defName,后加载的定义将会覆盖先加载的。
  • 匿名定义:<DrawingOrderDef> 作为其他定义的内部结构使用时,defName 可以省略,此时它将作为一个匿名的、局部可用的绘制顺序集定义。在这种情况下,该绘制顺序集无法通过名称在外部引用。
  • DrawNodeDef 的内容: 每个 <DrawingOrderDef> 的子元素(如 <idle_down>)内部都期望一个 <DrawNodeDef> 的定义。这个 <DrawNodeDef> 可以是一个完整的匿名定义(如示例),也可以是一个对已存在的 <DrawNodeDef> 的引用(如果该字段被设计为允许引用)。在当前示例中,它是一个匿名 <DrawNodeDef>
  • 合理利用替换机制: 在设计 DrawingOrderDef 时,可以充分利用替换机制来减少 XML 长度,但也要注意不要过度简化,以防视觉表现过于僵硬。对于方向性强的动作(如攻击),通常建议为所有方向提供独特的绘制。

XML 使用说明 - 定义阵营关系

在游戏配置文件中,您可以使用 <AffiliationDef> 元素来定义不同阵营(Affiliation)之间的关系。每个 <AffiliationDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。

功能介绍

<AffiliationDef> 用于配置游戏中各个阵营(或势力)对于其他阵营的默认态度。通过定义友好、敌对和中立列表,可以构建复杂的势力关系网,影响实体之间的行为逻辑,例如攻击目标选择、协作或互动方式。

参数说明

所有参数都必须通过嵌套元素的方式进行赋值。

  • <defName> (必需,字符串)

    • 该阵营关系定义的唯一标识符。通常,这会是某个特定阵营的名称。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
    • 作为匿名定义时,此字段可以省略。
  • <label> (可选,字符串)

    • 提供一个人类可读的标签,用于更好地理解该阵营关系定义的用途。
  • <description> (可选,字符串)

    • 提供更详细的文本描述,解释该阵营关系定义的具体内容或特殊用途。
  • <defaultRelation> (可选,枚举类型,默认为 Neutral)

    • 定义本阵营对未在其他列表中明确指定的任何其他阵营的默认关系。
    • 可选值包括:
      • Neutral (中立)
      • Hostile (敌对)
      • Friendly (友好)
  • <hostileFactions> (可选,字符串数组)

    • 一个字符串数组,列出本阵营视为敌对的其他阵营的 defName
    • 数组的定义方式为 <hostileFactions><li>阵营1defName</li><li>阵营2defName</li></hostileFactions><li> 元素本身会被忽略。
  • <neutralFactions> (可选,字符串数组)

    • 一个字符串数组,列出本阵营视为中立的其他阵营的 defName
    • 数组的定义方式为 <neutralFactions><li>阵营1defName</li><li>阵营2defName</li></neutralFactions><li> 元素本身会被忽略。
  • <friendlyFactions> (可选,字符串数组)

    • 一个字符串数组,列出本阵营视为友好的其他阵营的 defName
    • 数组的定义方式为 <friendlyFactions><li>阵营1defName</li><li>阵营2defName</li></friendlyFactions><li> 元素本身会被忽略。

关系冲突与优先级

当一个目标阵营同时出现在多个关系列表中时(例如,既在 hostileFactions 又在 friendlyFactions 中),系统会根据预设的优先级规则来解决冲突,以确定最终的关系。

优先级顺序(从高到低):

  1. Friendly (友好)
  2. Hostile (敌对)
  3. Neutral (中立)

这意味着,如果一个阵营在 friendlyFactionshostileFactions 都被列出,它最终会被判定为 Friendly。只有当一个阵营未在任何特定列表中被提及,才会回落到 defaultRelation 定义的关系。

示例

示例 1:定义“Player”阵营的关系

<Define>
    <AffiliationDef defName="PlayerAffiliation">
        <label>玩家阵营</label>
        <description>玩家及其盟友的阵营。</description>
        <defaultRelation>Neutral</defaultRelation> <!-- 默认对所有未指定者中立 -->
        <hostileFactions>
            <li>MonsterAffiliation</li> <!-- 对 MonsterAffiliation 敌对 -->
            <li>BanditAffiliation</li> <!-- 对 BanditAffiliation 敌对 -->
        </hostileFactions>
        <friendlyFactions>
            <li>AllyAffiliation</li> <!-- 对 AllyAffiliation 友好 -->
        </friendlyFactions>
        <neutralFactions>
            <!-- 没有特别指定的,因为 defaultRelation 已经是 Neutral -->
            <!-- 假设将来可能某个阵营默认是Friendly,但这里想设置为Neutral,就可以在这里列出 -->
            <li>WildLifeAffiliation</li>
        </neutralFactions>
    </AffiliationDef>
</Define>

示例 2:利用优先级规则的定义

假设我们希望 SomeTroubledFactionPlayerAffiliation 友好,但由于配置失误,它也被列入了 hostileFactions

<Define>
    <AffiliationDef defName="SomeTroubledFaction">
        <label>麻烦的阵营</label>
        <description>一个关系复杂的阵营。</description>
        <defaultRelation>Neutral</defaultRelation>
        <friendlyFactions>
            <li>PlayerAffiliation</li> <!-- 明确对玩家友好 -->
        </friendlyFactions>
        <hostileFactions>
            <li>PlayerAffiliation</li> <!-- 错误地将玩家也列为敌对 -->
        </hostileFactions>
    </AffiliationDef>
</Define>

在此示例中,尽管 PlayerAffiliation 同时出现在 friendlyFactionshostileFactions 中,但由于 友好(Friendly)关系优先级高于敌对(Hostile)SomeTroubledFaction 最终会视为 PlayerAffiliation友好 阵营。

示例 3:仅定义敌对关系,其他默认为中立

<Define>
    <AffiliationDef defName="MonsterAffiliation">
        <label>怪物阵营</label>
        <description>对所有非同类阵营都敌对。</description>
        <defaultRelation>Hostile</defaultRelation> <!-- 假设怪物对所有未明确的都敌对 -->
        <friendlyFactions>
            <li>MonsterAffiliation</li> <!-- 对自己(同类)友好 -->
        </friendlyFactions>
        <!-- 不需要定义 hostileFactions,因为 defaultRelation 已经是 Hostile -->
    </AffiliationDef>
</Define>

注意事项

  • defName 唯一性: AffiliationDefdefName 通常应与游戏中实际存在的阵营ID或名称保持一致,并确保其全局唯一性。
  • 双向关系: 阵营关系默认是单向的。如果 A 阵营将 B 视为 Friendly,不代表 B 阵营也自动将 A 视为 Friendly。您需要在 B 阵营的 AffiliationDef 中单独配置其对 A 的关系。
  • 列表内容: hostileFactionsneutralFactionsfriendlyFactions 列表中应填入其他 AffiliationDefdefName
  • 优先级: 务必牢记友好的最高优先级,这在设计关系网时尤为关键,可以避免意外的冲突导致错误的阵营行为。

子弹定义 (<BulletDef>)

功能说明

子弹定义主要用于描述游戏中的投射物或子弹的特性。这些定义通常由远程武器引用,以指定武器发射物的行为、外观和属性。子弹不仅包含基本的名称和描述,还能够定义自身的移动速度、生命值等属性,以及在不同状态下显示的纹理。

可用参数

参数名类型默认值说明
defName字符串必需。该子弹定义的唯一标识符。
label字符串(空)可选。该子弹在游戏中显示的名称。
description字符串(空)可选。该子弹在游戏中的详细描述。
attributes定义(匿名定义默认值)定义子弹具体的战斗属性,如生命值、移动速度等。可以是引用或匿名定义。详见下文**attributes 字段**。
drawingOrder定义(空)定义子弹在不同状态和方向下的纹理绘制顺序。这是一个匿名嵌套定义。详见下文**drawingOrder 字段**。

示例

这是一个定义名为“yellowBullet”的子弹的例子,展示了属性和绘制顺序的嵌套定义:

<Define>
    <!-- 子弹纹理定义 -->
    <ImageDef>
        <defName>yellowBullet</defName>
        <path>Resources\Item\YellowBullet_down.png</path>
        <pixelsPerUnit>64</pixelsPerUnit>
    </ImageDef>

    <!-- 子弹定义 -->
    <BulletDef>
        <defName>yellowBullet</defName>
        <label>黄色子弹</label>
        <description>一颗黄色的子弹</description>
        <!-- 嵌套定义属性 -->
        <attributes>
            <health>1</health>
            <moveSpeed>20</moveSpeed>
            <attack>1</attack> <!-- 子弹也可以有自己的攻击力 -->
        </attributes>
        <!-- 嵌套定义纹理绘制顺序 -->
        <drawingOrder>
            <!-- 闲置向下状态的纹理 -->
            <idle_down>
                <textures>
                    <li>yellowBullet</li>
                </textures>
            </idle_down>
            <!-- 行走向下状态的纹理 -->
            <walk_down>
                <textures>
                    <li>yellowBullet</li>
                </textures>
            </walk_down>
        </drawingOrder>
    </BulletDef>
</Define>

复杂参数说明

attributes 字段 (子弹属性定义)
  • 说明:定义子弹的具体属性,如生命值、移动速度、攻击力等。可以是一个对预定义的 <AttributesDef>defName 引用,也可以是当前位置的匿名定义。
  • 引用方式
    <attributes>AttributesDef的defName</attributes>
    
  • 匿名定义方式
    <attributes>
        <health>1</health>
        <moveSpeed>20</moveSpeed>
        <attack>1</attack>
        <defense>0</defense>
        <attackSpeed>1</attackSpeed>
        <attackRange>1</attackRange>
        <attackTargetCount>1</attackTargetCount>
    </attributes>
    
drawingOrder 字段 (纹理绘制顺序定义)
  • 说明:这是一个匿名嵌套定义,用于指定子弹在不同游戏状态(如 idle_down, walk_down 等)下所使用的纹理。drawingOrder 下的每个子元素(例如 <idle_down>)都代表一个具体的动画状态或方向组,其内部可以定义该状态下的纹理列表。
  • 匿名定义方式
    <drawingOrder>
        <!-- 状态/方向名称 (例如:idle_down) -->
        <状态名称>
            <textures>
                <li>ImageDef的defName1</li>
                <li>ImageDef的defName2</li>
                <!-- ...更多纹理引用 -->
            </textures>
            <!-- 还可以添加其他与该状态相关的属性 -->
        </状态名称>
        <!-- ...可以定义更多状态/方向 -->
    </drawingOrder>
    
  • 示例
    <drawingOrder>
        <idle_down>
            <textures>
                <li>yellowBullet</li>
            </textures>
        </idle_down>
        <walk_down>
            <textures>
                <li>yellowBullet</li>
            </textures>
        </walk_down>
        <!-- 如果子弹有其他方向或动画,可以在此处添加 -->
        <idle_up>
            <textures>
                <li>yellowBullet_up</li>
            </textures>
        </idle_up>
    </drawingOrder>
    
    请注意,<textures> 元素中包含的是一系列 <li> 元素,每个 <li> 引用一个已定义的 <ImageDef>defName。这种结构使得子弹的动画和显示具有高度的灵活性。

物品定义 (ItemDef)

物品定义用于创建游戏中各种可交互的物品数据。它包含了物品的视觉表现、堆叠行为、稀有度以及可能附带的效果等属性。

参数说明

所有物品定义都必须包含 defName 字段,作为其全局唯一标识。labeldescription 字段是可选的,用于提供更友好的显示名称和详细描述。

  • <defName>

    • 说明: 物品定义的唯一标识符。
    • 类型: 字符串
    • 示例: <defName>basicSword</defName>
  • <label> (可选)

    • 说明: 物品在游戏内显示的名称。
    • 类型: 字符串
    • 示例: <label>新手之剑</label>
  • <description> (可选)

    • 说明: 物品的详细描述或背景故事。
    • 类型: 字符串
    • 示例: <description>一把普通但结实的长剑。</description>
  • <FPS>

    • 说明: 物品动画的每秒帧数。
    • 类型: 浮点数
    • 默认值: 3.0
    • 示例: <FPS>6</FPS>
  • <textures>

    • 说明: 物品使用的纹理定义名列表。这些名称引用了 ImageDef 中已定义的纹理。
    • 类型: 字符串数组
    • 示例:
      <textures>
          <li>Item_SwordFrame1</li>
          <li>Item_SwordFrame2</li>
      </textures>
      
  • <rarity>

    • 说明: 物品的稀有度。
    • 类型: 枚举
    • 可选值: Common (普通), Uncommon (不寻常), Rare (稀有), Epic (史诗), Legendary (传说)
    • 默认值: Common
    • 示例: <rarity>Rare</rarity>
  • <maxStack>

    • 说明: 物品的最大堆叠数量。
    • 类型: 整数
    • 默认值: 10
    • 示例: <maxStack>99</maxStack>
  • <ssEquippable>

    • 说明: 物品是否可以被装备。
    • 类型: 布尔值
    • 默认值: false
    • 示例: <ssEquippable>true</ssEquippable>
  • <hediffs>

    • 说明: 物品在装备或使用时可能附加的效果列表。每个效果可以是已定义的 HediffDef 引用,也可以是匿名定义。
    • 类型: HediffDef 数组
    • 默认值: 空
    • 示例: 详见下方“复杂参数:<hediffs>

示例

<Define>
    <defName>healingPotion</defName>
    <label>治疗药水</label>
    <description>饮用后可以恢复少量生命值。</description>
    <FPS>1</FPS>
    <textures>
        <li>Potion_Red</li>
    </textures>
    <rarity>Common</rarity>
    <maxStack>5</maxStack>
    <ssEquippable>false</ssEquippable>
    <hediffs>
        <li>
            <time>5</time> <!-- 效果持续5秒 -->
            <stages>
                <li>
                    <start>0</start> <!-- 阶段从0秒开始 -->
                    <attributesOffset>
                        <healthOffset>10</healthOffset> <!-- 瞬间恢复10点生命 -->
                    </attributesOffset>
                </li>
            </stages>
        </li>
    </hediffs>
</Define>

<Define>
    <defName>advancedSword</defName>
    <label>锋利长剑</label>
    <description>一把制作精良的长剑,提供额外攻击力。</description>
    <FPS>2</FPS>
    <textures>
        <li>Sword_Advanced_Frame1</li>
        <li>Sword_Advanced_Frame2</li>
    </textures>
    <rarity>Uncommon</rarity>
    <maxStack>1</maxStack>
    <ssEquippable>true</ssEquippable>
    <hediffs>
        <!-- 引用已定义的装备效果 -->
        <li>Equip_AttackBoost</li>
    </hediffs>
</Define>

复杂参数:<hediffs>

<hediffs> 字段是一个列表,用于定义当物品被使用或装备时所能施加的生命体效果(Hediff)。列表中的每个元素可以是 已注册的 HediffDef 定义名,也可以是 直接嵌套定义的匿名 HediffDef

<HediffDef> (匿名或引用)

关于 HediffDef 的详细说明请参阅 HediffDef 文档。在此处,当作为匿名定义使用时,其包含以下子字段:

  • <time>

    • 说明: Hediff 的持续时间(秒)。如果设置为 -1,表示效果永久持续(例如装备效果)。
    • 类型: 浮点数
    • 默认值: -1.0
    • 示例: <time>10.5</time>
  • <stages>

    • 说明: Hediff 的发展阶段列表。每个阶段定义了效果在不同持续时间段内的属性修改。
    • 类型: HediffStageDef 数组
    • 示例: 详见下方 <HediffStageDef> 说明。
  • <comps>

    • 说明: 附加到此 Hediff 的组件列表,用于添加更复杂的行为和逻辑。
    • 类型: HediffCompDef 数组
    • 示例: 详见下方 <HediffCompDef> 说明。

<HediffStageDef> (匿名定义)

HediffStageDef 定义了 Hediff 特定阶段的属性修改。它作为 stages 字段的匿名子元素出现。

  • <start>

    • 说明: 该阶段开始的时间点(从 Hediff 施加开始计算的秒数)。
    • 类型: 浮点数
    • 示例: <start>0</start> (表示从Hediff开始时就进入此阶段)
  • <attributesOffset>

    • 说明: 该阶段对属性的偏移量定义。这是一个匿名 AttributesOffsetDef
    • 类型: AttributesOffsetDef
    • 示例: 详见下方 <AttributesOffsetDef> 说明。

<AttributesOffsetDef> (匿名定义)

AttributesOffsetDef 用于详细定义对角色属性的各种数值和百分比偏移。它作为 attributesOffset 字段的匿名子元素出现。

  • 绝对值偏移 (Added/Subtracted directly)

    • <healthOffset>: 生命值绝对偏移。
    • <moveSpeedOffset>: 移动速度绝对偏移。
    • <attackOffset>: 攻击力绝对偏移。
    • <defenseOffset>: 防御力绝对偏移。
    • <attackSpeedOffset>: 攻击速度绝对偏移。
    • <attackRangeOffset>: 攻击范围绝对偏移。
    • <attackTargetCountOffset>: 攻击目标数量绝对偏移。
    • 类型: 浮点数
    • 默认值: 0.0
    • 示例: <healthOffset>5</healthOffset> (增加5点生命值)
  • 百分比偏移 (Multiplied as a factor)

    • <healthPercentOffset>: 生命值百分比偏移 (例如 0.1 表示 +10%)。
    • <moveSpeedPercentOffset>: 移动速度百分比偏移。
    • <attackPercentOffset>: 攻击力百分比偏移。
    • <defensePercentOffset>: 防御力百分比偏移。
    • <attackSpeedPercentOffset>: 攻击速度百分比偏移。
    • <attackRangePercentOffset>: 攻击范围百分比偏移。
    • <attackTargetCountPercentOffset>: 攻击目标数量百分比偏移。
    • 类型: 浮点数
    • 默认值: 0.0
    • 示例: <attackPercentOffset>0.25</attackPercentOffset> (增加25%攻击力)

<HediffCompDef> (匿名定义)

HediffCompDef 定义了附加到 Hediff 上的组件,这些组件提供了除属性修改之外的额外行为。它作为 comps 字段的匿名子元素出现。

  • <compClass>

    • 说明: 组件的类名,用于在运行时创建对应的组件实例。
    • 类型: 字符串
    • 示例: <compClass>HediffComp_HealOverTime</compClass>
  • <properties>

    • 说明: 组件的初始化属性,通常是一个字符串,其具体格式和内容由 compClass 决定。
    • 类型: 字符串
    • 示例: <properties>amountPerSecond=1</properties>

<hediffs> 复杂示例

<hediffs>
    <li> <!-- 定义一个持续伤害效果 -->
        <time>15</time> <!-- 持续15秒 -->
        <label>中毒</label>
        <description>持续受到毒素伤害。</description>
        <stages>
            <li> <!-- 第一个阶段:开始时轻微中毒 -->
                <start>0</start>
                <attributesOffset>
                    <healthOffset>-0.5</healthOffset> <!-- 每秒损失0.5生命 -->
                    <moveSpeedPercentOffset>-0.1</moveSpeedPercentOffset> <!-- 移动速度降低10% -->
                </attributesOffset>
            </li>
            <li> <!-- 第二个阶段:5秒后加重中毒 -->
                <start>5</start>
                <attributesOffset>
                    <healthOffset>-1.0</healthOffset> <!-- 每秒损失1.0生命 -->
                    <moveSpeedPercentOffset>-0.2</moveSpeedPercentOffset>
                </attributesOffset>
            </li>
        </stages>
        <comps>
            <li> <!-- 附加一个每秒播放中毒动画的组件 -->
                <compClass>HediffComp_PlayEffect</compClass>
                <properties>effectName=PoisonCloud;interval=1</properties>
            </li>
        </comps>
    </li>
    <li> <!-- 引用一个已定义的 HediffDef -->
        <defName>Hediff_Regeneration</defName>
    </li>
</hediffs>

武器定义 (<WeaponDef>)

功能说明

武器定义用于描述游戏中的各种武器的特性,包括其攻击方式、属性、外观等。武器定义继承了物品定义 (<ItemDef>) 的所有基本特性,因此也拥有物品的通用属性,如堆叠数量、稀有度等。

可用参数

参数名类型默认值说明
defName字符串必需。该武器定义的唯一标识符。
label字符串(空)可选。该武器在游戏中显示的名称。
description字符串(空)可选。该武器在游戏中的详细描述。
FPS浮点数3定义武器显示动画的帧率。
textures字符串数组(空)引用多个 <ImageDef>defName,用于定义武器在世界或UI中的外观纹理。
rarity字符串Common定义武器的稀有度。详见下文**rarity 字段**。
maxStack整数10定义该武器的最大堆叠数量。
ssEquippable布尔值false定义该武器是否可被实体装备。
type字符串Melee定义武器的攻击类型,可以是“近战”或“远程”。详见下文**type 字段**。
attributes定义(匿名定义默认值)定义武器具体的战斗属性,如攻击力、防御力、攻击速度等。可以是引用或匿名定义。详见下文**attributes 字段**。
bullet定义仅当 typeRanged 时有效。定义远程武器发射的子弹特性。可以是引用或匿名定义。详见下文**bullet 字段**。
attackAnimation字符串数组(空)引用多个动画帧名的字符串数组,用于定义武器攻击时播放的专属动画序列。详见下文**attackAnimation 字段**。
attackDetectionTime浮点数0攻击判定时间点,表示攻击动画播放到该百分比时触发伤害或投射子弹。取值范围0到1。
useEntityAttackAnimation布尔值true是否使用实体自身的攻击动画,如果为 false 则使用武器自带的 attackAnimation

示例

这是一个定义名为“TestGun”的远程武器的例子:

<Define>
    <!-- 子弹定义,会被WeaponDef中bullet引用 -->
    <BulletDef>
        <defName>yellowBullet</defName>
        <label>黄色子弹</label>
        <description>一颗黄色的子弹</description>
        <!-- 嵌套定义属性 -->
        <attributes>
            <health>1</health>
            <moveSpeed>20</moveSpeed>
        </attributes>
        <!-- 嵌套定义纹理绘制顺序 -->
        <drawingOrder>
            <idle_down>
                <textures>
                    <li>yellowBullet</li>
                </textures>
            </idle_down>
            <walk_down>
                <textures>
                    <li>yellowBullet</li>
                </textures>
            </walk_down>
        </drawingOrder>
    </BulletDef>

    <!-- 属性定义,会被WeaponDef中attributes引用 -->
    <AttributesDef>
        <defName>TestGunAttributes</defName>
        <attack>10</attack>
        <defense>3</defense>
        <attackSpeed>1</attackSpeed>
        <attackRange>10</attackRange>
        <attackTargetCount>1</attackTargetCount>
    </AttributesDef>

    <!-- 武器定义 -->
    <WeaponDef>
        <defName>TestGun</defName>
        <label>测试枪</label>
        <description>一把测试用的枪</description>
        <!-- 引用属性定义 -->
        <attributes>TestGunAttributes</attributes>
        <type>Ranged</type>
        <FPS>10</FPS>
        <textures>
            <li>TestGunItem</li>
        </textures>
        <attackAnimation>
            <li>testGunAttackAnimation_0</li>
            <li>testGunAttackAnimation_1</li>
            <li>testGunAttackAnimation_2</li>
            <li>testGunAttackAnimation_3</li>
            <li>testGunAttackAnimation_4</li>
            <li>testGunAttackAnimation_5</li>
            <li>testGunAttackAnimation_6</li>
            <li>testGunAttackAnimation_7</li>
            <li>testGunAttackAnimation_8</li>
            <li>testGunAttackAnimation_9</li>
        </attackAnimation>
        <attackDetectionTime>0.5</attackDetectionTime>
        <maxStack>1</maxStack>
        <rarity>Uncommon</rarity>
        <bullet>yellowBullet</bullet> <!-- 引用子弹定义 -->
    </WeaponDef>
</Define>

复杂参数说明

type 字段
  • 说明:指定武器的攻击类型。
  • 可选值
    • Melee (近战武器)
    • Ranged (远程武器)
  • 示例
    <type>Ranged</type>
    
rarity 字段
  • 说明:指定该物品的稀有度。
  • 可选值
    • Common (普通)
    • Uncommon (不常见)
    • Rare (稀有)
    • Epic (史诗)
    • Legendary (传说)
  • 示例
    <rarity>Uncommon</rarity>
    
textures 字段 (图片定义引用数组)
  • 说明:用于指定武器在界面或游戏世界中显示的纹理。这是一个字符串数组,每个元素引用一个 <ImageDef>defName
  • 引用方式
    <textures>
        <li>ImageDef的defName1</li>
        <li>ImageDef的defName2</li>
        <!-- ...更多纹理引用 -->
    </textures>
    
  • 示例
    <textures>
        <li>TestGunItem</li>
    </textures>
    
attackAnimation 字段 (动画帧引用数组)
  • 说明:用于指定武器攻击时播放的动画帧序列。这是一个字符串数组,每个元素引用一个 <ImageDef> 定义的动画帧。通常,一个动画纹理会在其 defName 后拼接 _0, _1, _2 等来表示具体的帧。
  • 引用方式
    <attackAnimation>
        <li>ImageDef动画帧名1</li>
        <li>ImageDef动画帧名2</li>
        <!-- ...更多动画帧引用 -->
    </attackAnimation>
    
  • 示例
    <attackAnimation>
        <li>testGunAttackAnimation_0</li>
        <li>testGunAttackAnimation_1</li>
        <!-- ... -->
        <li>testGunAttackAnimation_9</li>
    </attackAnimation>
    
attributes 字段 (武器属性定义)
  • 说明:定义武器具体的战斗属性,如生命值、移动速度、攻击力、防御力、攻击速度、攻击范围和攻击目标数量。可以是一个对预定义的 <AttributesDef>defName 引用,也可以是当前位置的匿名定义。
  • 引用方式
    <attributes>AttributesDef的defName</attributes>
    
  • 匿名定义方式
    <attributes>
        <health>10</health>
        <moveSpeed>1</moveSpeed>
        <attack>1</attack>
        <defense>0</defense>
        <attackSpeed>2</attackSpeed>
        <attackRange>3</attackRange>
        <attackTargetCount>1</attackTargetCount>
    </attributes>
    
bullet 字段 (子弹定义)
  • 说明:仅当武器类型为 Ranged 时有效,用于定义该武器发射的子弹的特性。可以是一个对预定义的 <BulletDef>defName 引用,也可以是当前位置的匿名定义。
  • 引用方式
    <bullet>BulletDef的defName</bullet>
    
  • 匿名定义方式
    <bullet>
        <defName>匿名子弹名</defName> <!-- 匿名定义也可选择性声明defName -->
        <label>匿名子弹</label>
        <!-- 子弹的属性定义 (匿名定义) -->
        <attributes>
            <health>1</health>
            <moveSpeed>20</moveSpeed>
        </attributes>
        <!-- 嵌套定义纹理绘制顺序 (匿名定义) -->
        <drawingOrder>
            <idle_down>
                <textures>
                    <li>yellowBullet</li>
                </textures>
            </idle_down>
        </drawingOrder>
        <!-- 其他子弹独有属性 -->
    </bullet>
    

消息定义 (<MessageDef>)

功能说明

消息定义用于在游戏中创建各种提示文本或通知。通过定义消息,开发者可以控制文本的实际内容、显示类别(例如聊天气泡、屏幕中央大字等)以及文本的颜色,从而实现多样化的游戏内信息交互。

可用参数

参数名类型默认值说明
defName字符串必需。该消息定义的唯一标识符。
label字符串(空)可选。该消息的内部标识标签,通常用于编辑器预览。
description字符串(空)可选。该消息的详细描述或备注。
type字符串必需。定义消息的显示类别,如在实体上方显示或屏幕中央显示。详见下文**type 字段**。
text字符串必需。消息的实际文本内容。
color字符串(空)可选。消息文本的颜色,使用HTML颜色字符串格式。详见下文**color 字段**。

示例

这是一个定义了几种不同显示类别的消息的例子:

<Define>
    <MessageDef>
        <defName>InteractionHint</defName>
        <label>互动提示</label>
        <description>在NPC或可互动对象上方显示的简短提示</description>
        <type>FocusedEntityOverheadText</type>
        <text>按 [E] 互动</text>
        <color>#00FF00</color> <!-- 绿色文本 -->
    </MessageDef>

    <MessageDef>
        <defName>DialogueBubble</defName>
        <label>对话气泡</label>
        <description>NPC说话时显示的聊天气泡</description>
        <type>FocusedEntityChatBubble</type>
        <text>你好,初次见面!</text>
        <color>#FFFFFF</color> <!-- 白色文本 -->
    </MessageDef>

    <MessageDef>
        <defName>QuestComplete</defName>
        <label>任务完成通知</label>
        <description>任务完成时在屏幕中央显示的大型通知</description>
        <type>ScreenCenterLargeText</type>
        <text>任务完成!</text>
        <color>Gold</color> <!-- 金色文本 -->
    </MessageDef>

    <MessageDef>
        <defName>AmbientHint</defName>
        <label>环境提示</label>
        <description>右下角浮动的非干扰性提示</description>
        <type>PassiveHint</type>
        <text>区域发现:神秘森林</text>
        <color>LightGray</color> <!-- 浅灰色文本 -->
    </MessageDef>
</Define>

复杂参数说明

type 字段 (消息显示类别)
  • 说明:定义消息在游戏中的具体显示方式和位置。
  • 可选值
    • Default: 默认或未分类的显示方式。
    • FocusedEntityChatBubble: 显示在玩家当前焦点实体(如NPC或交互物)上方,以聊天气泡形式呈现。
    • FocusedEntityOverheadText: 显示在玩家当前焦点实体(如NPC或交互物)头顶,通常是简短的状态、名称或互动提示。
    • ScreenCenterLargeText: 大型文本显示在屏幕中央,通常用于重要通知、标题或剧情提示,需要玩家立即注意。
    • PassiveHint: 非焦点提示,通常以不易干扰的方式(如屏幕边缘、HUD小字或右下角浮动)显示,提供辅助信息、次要指引或环境提示。
  • 示例
    <type>FocusedEntityOverheadText</type>
    
color 字段 (文本颜色)
  • 说明:定义消息文本的颜色。颜色值必须是有效的HTML颜色字符串,支持多种格式:
    • 颜色名称:如 "Red", "Blue", "Green", "Gold", "LightGray" 等。
    • 十六进制RGB/RGBA值
      • #RRGGBB:例如 #FF0000 (红色), #00FF00 (绿色), #0000FF (蓝色)。
      • #AARRGGBB:例如 #80FF0000 (半透明红色)。
      • #RGB#ARGB:例如 #F00 (红色), #8F00 (半透明红色)。
  • 示例
    <color>#FF00FF</color> <!-- 紫色文本 -->
    <color>Blue</color>   <!-- 蓝色文本 -->
    <color>#FFFF0000</color> <!-- 不透明红色文本 -->
    

XML 使用说明 - 定义通用事件

在游戏配置文件中,您可以使用 <EventDef> 元素来定义各种可触发的游戏事件。每个 <EventDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。

功能介绍

<EventDef> 提供了一种灵活的机制来定义游戏中各种可执行的事件,从生成实体到触发故事情节。它通过指定一个事件处理类 (workClass) 及其配套的参数 (parameter) 来实现事件的定制化行为。

参数说明

所有参数都必须通过嵌套元素的方式进行赋值。

  • <defName> (必需,字符串)

    • 该事件定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
    • 作为匿名定义时,此字段可以省略。
  • <label> (可选,字符串)

    • 提供一个人类可读的标签,用于更好地理解该事件定义的用途。
  • <description> (可选,字符串)

    • 提供更详细的文本描述,解释该事件的具体内容或特殊用途。
  • <workClass> (必需,字符串)

    • 指定处理此事件逻辑的后端类名。此字符串必须精确匹配到游戏中对应的事件处理类。
    • 关于 workClass 类的详细讲解,请参阅稍后发布的第三章:核心工作类定义
  • <parameter> (必需,JSON 字符串)

    • 包含传递给 workClass 指定事件处理类的所有必要参数。这些参数必须以JSON (JavaScript Object Notation) 格式提供,并且其结构和内容完全取决于 workClass 所需的数据。

parameter 参数:JSON 格式详解

parameter 参数是一个 JSON 格式的字符串,其内部结构和字段名必须与 workClass 所期望的参数类型严格匹配。游戏引擎会负责解析这个 JSON 字符串,并将其映射到 workClass 内部对应的参数对象上。

JSON 格式的特点:

  • 键值对: 由键(字符串)和值组成,键和值之间用冒号 : 分隔。
  • 对象: 用大括号 {} 包裹,包含零个或多个键值对,键值对之间用逗号 , 分隔。
  • 数组: 用方括号 [] 包裹,包含零个或多个值,值之间用逗号 , 分隔。
  • 数据类型: 支持字符串、数字、布尔值(true/false)、JSON 对象、JSON 数组和 null。

编写规则:

  • 整个 JSON 结构必须是合法的。
  • 所有键(字段名)必须用双引号 "" 包裹。
  • 所有字符串值也必须用双引号 "" 包裹。数字、布尔值不需要。
  • JSON 内部可以包含换行符和缩进,以提高可读性,这些空白字符在解析时会被忽略。

示例

示例 1:生成多个怪物事件

此事件定义使用 Event_EntityGenerater 作为工作类,负责在地图外生成指定数量的怪物。parameter JSON 结构清晰地定义了要生成的实体类型、位置类型和数量。

<Define>
    <EventDef>
        <defName>Event_SpawnMonsterA1_3</defName>
        <label>生成3个A1型怪物</label>
        <description>在地图外生成3个编号为MonsterA1的怪物。</description>
        <workClass>Event_EntityGenerater</workClass>
        <parameter>
        {
            "DefinitionsToChooseFrom":[ 
                { "DefName":"MonsterA1", "DefTypeName":"MonsterDef" } 
            ],
            "LocationType":"OffMap",
            "Count":3
        }
        </parameter>
    </EventDef>
</Define>

parameter JSON 结构分析:

  • 这是一个 JSON 对象。
  • "DefinitionsToChooseFrom":一个 JSON 数组,其中每个元素都是一个 JSON 对象,包含要生成的实体的 DefName(定义名称)和 DefTypeName(定义类型名称)。
  • "LocationType":一个字符串,指定实体生成的位置类型。
  • "Count":一个数字,指定要生成的实体数量。

示例 2:触发特定故事情节事件

此示例展示了一个触发故事情节的事件,parameter 可能包含故事ID、参与者等信息。

<Define>
    <EventDef>
        <defName>Event_TriggerStory_LostChild</defName>
        <label>触发失踪儿童故事</label>
        <description>在一个随机地点触发一个关于失踪儿童的故事事件。</description>
        <workClass>Event_StoryManager</workClass>
        <parameter>
        {
            "StoryID": "LostChildScenario",
            "TriggerLocation": "Random",
            "Participants": [
                { "Role": "QuestGiver", "Faction": "PlayerAffiliation" },
                { "Role": "MissingChild", "DefName": "ChildPawnDef", "DefTypeName": "PawnDef" }
            ]
        }
        </parameter>
    </EventDef>
</Define>

注意事项

  • parameter 的严格性: parameter 中的 JSON 结构必须与 workClass 内部定义的参数类结构完全匹配,包括字段名的大小写和数据类型。任何不匹配都可能导致事件无法正确执行。
  • workClass 定义: workClass 对应的类必须在游戏中存在且可加载。错误的类名会导致事件无法实例化。
  • 可读性: 尽管 JSON 允许在一行中定义,但为了配置文件的可读性和易维护性,强烈建议使用多行和缩进来格式化 parameter 的内容。

故事定义 (<StoryDef>)

功能说明

故事定义用于组织和编排游戏中的故事情节流程。一个完整的故事由一系列按顺序执行的故事阶段 (<StoryStageDef>) 组成,每个阶段可以包含等待时间、触发特定事件或显示消息等。

可用参数

参数名类型默认值说明
defName字符串必需。该故事定义的唯一标识符。
label字符串(空)可选。该故事在游戏中显示的名称。
description字符串(空)可选。该故事的详细描述。
storyStage故事阶段数组必需。定义组成该故事的各个阶段。这是一个故事阶段的数组。详见下文**storyStage 字段**。

示例

这是一个定义了一个包含两个阶段的故事的例子:

<Define>
    <!-- 独立的事件和消息定义,供故事阶段引用 -->
    <EventDef>
        <defName>StartQuest_FirstEncounter</defName>
        <workClass>Event_StartQuest</workClass>
        <parameter>{"QuestId": "FirstEncounter"}</parameter>
    </EventDef>

    <MessageDef>
        <defName>WelcomeMessage</defName>
        <type>ScreenCenterLargeText</type>
        <text>欢迎来到这个世界!</text>
        <color>White</color>
    </MessageDef>

    <!-- 故事定义 -->
    <StoryDef>
        <defName>NewGameIntro</defName>
        <label>新手引导故事</label>
        <description>玩家初次进入游戏时的引导流程。</description>
        <storyStage>
            <li>
                <lastWaitTime>0</lastWaitTime>
                <nextWaitTime>3</nextWaitTime> <!-- 等待3秒 -->
                <messageDef>WelcomeMessage</messageDef> <!-- 引用消息定义 -->
            </li>
            <li>
                <lastWaitTime>3</lastWaitTime> <!-- 继承上一个阶段的nextWaitTime作为lastWaitTime,也可自定义 -->
                <nextWaitTime>0</nextWaitTime>
                <eventDef>StartQuest_FirstEncounter</eventDef> <!-- 引用事件定义 -->
            </li>
        </storyStage>
    </StoryDef>
</Define>

故事阶段定义 (<StoryStageDef>)

功能说明

故事阶段定义是构成完整故事的基本单元。每个阶段代表故事流程中的一个步骤,可以指定该阶段的持续时间(通过等待时间)、需要触发的特定事件、以及需要显示给玩家的消息。故事阶段通常作为 <StoryDef> 内部的匿名定义存在。

可用参数

参数名类型默认值说明
defName字符串可选。该故事阶段的唯一标识符。作为匿名定义时可省略。
label字符串(空)可选。该故事阶段的内部标识标签。
description字符串(空)可选。该故事阶段的详细描述。
lastWaitTime浮点数0当前阶段开始前必须等待的前一个阶段的结束时间点(秒)。
nextWaitTime浮点数0当前阶段结束前需要等待的时间(秒)。这个值通常作为下一个阶段的 lastWaitTime
eventDef定义可选。定义此阶段结束后要触发的事件。可以是预定义事件的引用或匿名定义。详见下文**eventDef 字段**。
messageDef定义可选。定义此阶段中要显示给玩家的消息。可以是预定义消息的引用或匿名定义。详见下文**messageDef 字段**。

复杂参数说明

storyStage 字段 (故事阶段数组)
  • 说明:这是一个数组,其内部每个 <li> 元素代表一个故事阶段的定义。通常,这些阶段定义会以匿名方式直接嵌套在 <li> 中。
  • 数组定义方式
    <storyStage>
        <li>
            <!-- 第一个故事阶段的定义 -->
            <lastWaitTime>0</lastWaitTime>
            <nextWaitTime>5</nextWaitTime>
            <messageDef>
                <type>ScreenCenterLargeText</type>
                <text>开始新篇章!</text>
            </messageDef>
        </li>
        <li>
            <!-- 第二个故事阶段的定义 -->
            <lastWaitTime>5</lastWaitTime>
            <nextWaitTime>0</nextWaitTime>
            <eventDef>
                <workClass>Event_SpawnMonster</workClass>
                <parameter>{"MonsterType": "Goblin", "Count": 3}</parameter>
            </eventDef>
        </li>
        <!-- ...更多故事阶段 -->
    </storyStage>
    
eventDef 字段 (事件定义)
  • 说明:指定当前故事阶段完成后触发的事件。它可以是已经预定义好的 事件定义defName 引用,也可以是在此处直接定义的匿名事件。
  • 引用方式
    <eventDef>EventDef的defName</eventDef>
    
  • 匿名定义方式
    <eventDef>
        <workClass>Event_SpawnItem</workClass>
        <parameter>{"ItemDefName": "HealingPotion", "Count": 1}</parameter>
    </eventDef>
    
messageDef 字段 (消息定义)
  • 说明:指定当前故事阶段需要显示给玩家的消息。它可以是已经预定义好的 消息定义defName 引用,也可以是在此处直接定义的匿名消息。
  • 引用方式
    <messageDef>MessageDef的defName</messageDef>
    
  • 匿名定义方式
    <messageDef>
        <type>PassiveHint</type>
        <text>你获得了新的任务目标!</text>
        <color>Yellow</color>
    </messageDef>
    

XML 使用说明 - 定义实体事件处理

在游戏配置文件中,您可以使用 <EntityEventDef> 元素来定义与游戏实体生命周期和行为相关的各种事件触发器。每个 <EntityEventDef> 元素都必须包含在顶层的 <Define> 元素之内,并遵循其通用的属性定义规则。

功能介绍

<EntityEventDef> 提供了一种强大的机制,用于在实体执行特定动作(如移动、攻击)、经历生命周期事件(如生成、死亡)或满足特定条件时,自动触发预设的游戏事件。这使得游戏的动态性和交互性大大增强,无需硬编码即可实现复杂的事件联动。

参数说明

所有参数都必须通过嵌套元素的方式进行赋值。

  • <defName> (必需,字符串)

    • 该实体事件定义的唯一标识符。在整个游戏配置中,此名称必须是全局唯一的,除非您有意覆盖现有定义。
    • 作为匿名定义时,此字段可以省略。
  • <label> (可选,字符串)

    • 提供一个人类可读的标签,用于更好地理解该实体事件定义的用途。
  • <description> (可选,字符串)

    • 提供更详细的文本描述,解释该实体事件定义的具体内容或特殊用途。

特定行为触发事件数组

以下字段都是可选的,每个字段都是一个事件数组,当实体发生对应行为时,数组中的所有事件都会被顺序触发。数组的定义方式为:<数组名><li>事件引用/匿名定义</li><li>事件引用/匿名定义</li></数组名>。数组元素可以是已定义的 EventDefdefName 字符串,也可以是直接在这里定义的匿名 EventDef

  • <onSpawnEvents> (可选,EventDef 数组)
    • 当实体首次生成时触发的一系列事件。
  • <onMoveForwardEvents> (可选,EventDef 数组)
    • 当实体向前移动时触发的一系列事件。
  • <onMoveBackwardEvents> (可选,EventDef 数组)
    • 当实体向后移动时触发的一系列事件。
  • <onMoveLeftEvents> (可选,EventDef 数组)
    • 当实体向左移动时触发的一系列事件。
  • <onMoveRightEvents> (可选,EventDef 数组)
    • 当实体向右移动时触发的一系列事件。
  • <onMeleeAttackEvents> (可选,EventDef 数组)
    • 当实体执行近战攻击时触发的一系列事件。
  • <onRangedAttackEvents> (可选,EventDef 数组)
    • 当实体执行远程攻击时触发的一系列事件。
  • <onHitEvents> (可选,EventDef 数组)
    • 当实体受到攻击或伤害时触发的一系列事件。
  • <onDeathEvents> (可选,EventDef 数组)
    • 当实体生命值归零并死亡时触发的一系列事件。

条件触发事件

  • <conditionalEvents> (可选,ConditionalEvent 数组)
    • 这是一个特殊的事件数组,其中的每个元素都是一个 <ConditionalEvent>。这些事件会在满足特定条件时才被触发。数组的定义方式与普通事件数组相同。
    • 关于 <conditionalEvents> 的详细讲解,请参阅条件事件详解

引用方式和匿名定义

  • EventDef 引用/匿名定义: 在所有事件数组字段中,数组的每个 <li> 元素都可以是以下两种形式之一:
    1. 字符串引用: 一个已定义的 EventDefdefName。例如:<li>Event_SpawnMonsterA1_3</li>
    2. 匿名定义: 直接在 <li> 内部定义一个 EventDef 的完整结构,此时该 EventDef 不需要 defName 字段。例如:
      <li>
          <workClass>Event_PlaySound</workClass>
          <parameter>{"SoundID":"HitSound"}</parameter>
      </li>
      
  • ConditionalEvent 匿名定义:<conditionalEvents> 数组中,每个 <li> 元素必须是一个匿名的 <ConditionalEvent> 定义。

示例

带有多种实体事件的定义

<Define>
    <!-- 预定义的事件,可被引用 -->
    <EventDef>
        <defName>Event_PlayDeathSound</defName>
        <workClass>Event_PlaySound</workClass>
        <parameter>{"SoundID":"DeathCry"}</parameter>
    </EventDef>

    <EventDef>
        <defName>Event_DropLoot</defName>
        <workClass>Event_ItemDrop</workClass>
        <parameter>{"LootTable":"MonsterLootTable_Basic"}</parameter>
    </EventDef>

    <!-- 实体事件定义示例 -->
    <EntityEventDef>
        <defName>MonsterA_Events</defName>
        <label>A型怪物事件集</label>
        <description>定义A型怪物在不同行为下的事件触发。</description>

        <!-- 实体生成时触发事件 -->
        <onSpawnEvents>
            <li>
                <workClass>Event_EntityGenerater</workClass>
                <parameter>
                {
                    "DefinitionsToChooseFrom":[ { "DefName":"Effect_SpawnSmoke", "DefTypeName":"EffectDef" } ],
                    "LocationType":"AtEntity",
                    "Count":1
                }
                </parameter>
            </li>
            <li>Event_MonsterSpawnAnnounce</li> <!-- 引用另一个 EventDef -->
        </onSpawnEvents>

        <!-- 实体死亡时触发事件 -->
        <onDeathEvents>
            <li>Event_PlayDeathSound</li>    <!-- 引用已定义的事件 -->
            <li>Event_DropLoot</li>          <!-- 引用已定义的事件 -->
            <li>
                <workClass>Event_CustomAnimation</workClass>
                <parameter>{"AnimationStyle":"DeathExplosion"}</parameter>
            </li>
        </onDeathEvents>

        <!-- 实体受击时触发一个匿名事件 -->
        <onHitEvents>
            <li>
                <workClass>Event_ScreenShake</workClass>
                <parameter>{"Intensity":0.5, "Duration":0.1}</parameter>
            </li>
        </onHitEvents>
      
        <!-- 条件事件示例 -->
        <conditionalEvents>
            <li>
                <parameter>HasLowHealth()</parameter>
                <eventDefs>
                    <li>Event_MonsterFlee</li>
                    <li>
                        <workClass>Event_ApplyBuff</workClass>
                        <parameter>{"BuffDefName":"FearBuff"}</parameter>
                    </li>
                </eventDefs>
            </li>
            <li>
                <parameter>IsNightTime()</parameter>
                <eventDefs>
                    <li>Event_EnhanceMonsterStrength</li>
                </eventDefs>
            </li>
        </conditionalEvents>

    </EntityEventDef>
</Define>

条件事件详解

<conditionalEvents> 字段是一个特殊的数组,它包含零个或多个 <ConditionalEvent> 定义。每个 <ConditionalEvent> 允许您定义一个条件,当该条件为真时,就会触发一系列与之关联的事件。

参数说明(ConditionalEvent)

每个 <ConditionalEvent> 都必须是一个匿名定义,包含以下参数:

  • <parameter> (必需,字符串)

    • 这是一个字符串,其内容是一个条件表达式。这个表达式的语法和可用的函数与行为树中的条件判断非常相似。它将由游戏引擎进行求值,如果结果为真,则触发 eventDefs 中的事件。
    • 关于可用的条件表达式和语法,请参阅行为树章节
  • <eventDefs> (必需,EventDef 数组)

    • 这是一个事件数组,其中包含当 <parameter> 中定义的条件为真时需要触发的所有事件。其定义方式与上面描述的事件数组完全相同,可以引用已定义的 EventDef,也可以直接匿名定义。

示例 (conditionalEvents)

<conditionalEvents>
    <li>
        <!-- 条件:拥有低生命值 -->
        <parameter>HasLowHealth()</parameter>
        <eventDefs>
            <li>Event_MonsterFlee</li> <!-- 引用一个逃跑事件 -->
            <li>
                <workClass>Event_ApplyBuff</workClass>
                <parameter>{"BuffDefName":"FearBuff"}</parameter>
            </li>
        </eventDefs>
    </li>
    <li>
        <!-- 条件:是夜晚 -->
        <parameter>IsNightTime()</parameter>
        <eventDefs>
            <li>Event_EnhanceMonsterStrength</li> <!-- 引用一个增强力量的事件 -->
        </eventDefs>
    </li>
</conditionalEvents>

好的,我将根据你提供的 CharacterDef 更新文档,并新增 defaultWeapon 字段的说明。


角色定义 (CharacterDef)

CharacterDef 用于定义游戏中的各类角色实体,例如玩家、NPC、敌人等。它继承了基础的实体定义,并额外提供了内部维度(体内场景)和默认武器的配置。

根元素: <Define>

DefName: 必需,全局唯一的字符串,用于标识特定的角色定义。

Label: 可选,字符串,用于在游戏中显示的角色名称。

Description: 可选,字符串,对角色的详细描述。


参数说明

<attributes>

角色的基础属性集合。这是一个匿名定义,直接在 attributes 元素下定义各项属性。

字段说明:

  • <health>: 整数,角色的生命值,默认为10。
  • <moveSpeed>: 浮点数,角色的移动速度,默认为1。
  • <attack>: 整数,角色的攻击力,默认为1。
  • <defense>: 整数,角色的防御力,默认为0。
  • <attackSpeed>: 浮点数,角色的攻击速度(每次攻击的冷却时间),默认为2。
  • <attackRange>: 浮点数,角色的攻击范围,默认为3。
  • <attackTargetCount>: 整数,角色每次攻击能命中的目标数量,默认为1。

示例:

<attributes>
    <health>100</health>
    <moveSpeed>2.5</moveSpeed>
    <attack>15</attack>
</attributes>

<drawingOrder>

定义角色在不同状态下(例如:闲置、行走、近战攻击、远程攻击、死亡)和不同朝向时的绘制方式。这是一个匿名定义,直接在 drawingOrder 元素下定义各种绘制节点。每个状态-朝向组合(如 idle_downwalk_up)都是一个 DrawNodeDef 类型。

字段说明:

  • <idle_down>, <idle_up>, <idle_left>, <idle_right>: 闲置状态下,角色朝向下方、上方、左方、右方时的绘制节点。
  • <walk_down>, <walk_up>, <walk_left>, <walk_right>: 行走状态下,角色朝向下方、上方、左方、右方时的绘制节点。
  • <meleeAttack_down>, <meleeAttack_up>, <meleeAttack_left>, <meleeAttack_right>: 近战攻击状态下,角色朝向下方、上方、左方、右方时的绘制节点。
  • <rangedAttack_down>, <rangedAttack_up>, <rangedAttack_left>, <rangedAttack_right>: 远程攻击状态下,角色朝向下方、上方、左方、右方时的绘制节点。
  • <death_down>, <death_up>, <death_left>, <death_right>: 死亡状态下,角色朝向下方、上方、左方、右方时的绘制节点。

示例:

<drawingOrder>
    <idle_down>
        <textures>
            <li>Character_Maid_Walk_1</li>
        </textures>
    </idle_down>
    <walk_down>
        <FPS>5.0</FPS>
        <textures>
            <li>Character_Maid_Walk_0</li>
            <li>Character_Maid_Walk_1</li>
            <li>Character_Maid_Walk_2</li>
            <li>Character_Maid_Walk_1</li>
        </textures>
    </walk_down>
    <!-- 其他状态和朝向的绘制定义 -->
</drawingOrder>

<behaviorTree>

定义角色的行为逻辑树。这是一个匿名定义,直接在 behaviorTree 元素下定义行为树的根节点。其结构与 BehaviorTreeDef 一致。

示例:

<behaviorTree>
    <className>ThinkNode_Selector</className>
    <childTree>
        <li>
            <className>ThinkNode_Conditional</className>
            <value>HasWeapon()</value>
            <childTree>
                <li>
                    <className>JobGiver_AttackJob</className>
                </li>
            </childTree>
        </li>
        <li>
            <className>ThinkNode_Sequence</className>
            <childTree>
                <li><className>JobGiver_Wander</className></li>
                <li><className>JobGiver_Idle</className></li>
            </childTree>
        </li>
    </childTree>
</behaviorTree>

<affiliation>

指定角色的所属阵营。可以引用一个现有的 AffiliationDefdefName,或者直接在此处进行匿名定义

作为引用:

<affiliation>player</affiliation> <!-- 引用名为 "player" 的 AffiliationDef -->

作为匿名定义:

<affiliation>
    <defaultRelation>Friendly</defaultRelation>
    <hostileFactions>
        <li>monster</li>
    </hostileFactions>
</affiliation>

<defaultWeapon>

定义角色在背包没有选择任何武器时,默认使用的武器。可以引用一个现有的 WeaponDefdefName,或者直接在此处进行匿名定义

作为引用:

<defaultWeapon>BasicSword</defaultWeapon> <!-- 引用名为 "BasicSword" 的 WeaponDef -->

作为匿名定义:

<defaultWeapon>
    <label>默认拳头</label>
    <attack>1</attack>
    <attackRange>0.8</attackRange>
    <!-- 其他 WeaponDef 属性,具体字段取决于 WeaponDef 的定义 -->
</defaultWeapon>

<eventDef>

定义角色在特定事件发生时触发的行为。这是一个 EntityEventDef 类型的匿名定义

示例:

<eventDef>
    <onDeathEvents>
        <li>
            <workClass>CreateEffect</workClass>
            <parameter>ExplosionEffect</parameter>
        </li>
        <li>
            <workClass>DropItems</workClass>
            <parameter>Gold,5-10</parameter>
        </li>
    </onDeathEvents>
</eventDef>

<colliderSize>

字符串,定义角色的碰撞体大小,通常为 "宽,高" 格式。例如 "1.0,1.0"。

<colliderPosition>

字符串,定义角色的碰撞体相对角色中心的位置偏移,通常为 "x,y" 格式。例如 "0.0,0.5"。

<insideDimensionDef>

引用一个 DimensionDefdefName,指定当角色进行“体内场景”战斗时所使用的维度定义。

示例:

<insideDimensionDef>CellularDimension</insideDimensionDef> <!-- 引用名为 "CellularDimension" 的 DimensionDef -->

示例

<Define>
    <defName>maid</defName>
    <label>女仆</label>
    <description>一个可爱的女仆角色</description>

    <!-- 角色基础属性的匿名定义 -->
    <attributes>
        <health>100</health>
        <moveSpeed>2</moveSpeed>
        <attack>10</attack>
        <defense>5</defense>
        <attackRange>1.5</attackRange>
    </attributes>

    <!-- 角色所属阵营,引用现有定义 -->
    <affiliation>player</affiliation>

    <!-- 角色默认武器,引用现有定义 -->
    <defaultWeapon>MaidDuster</defaultWeapon>

    <!-- 角色不同状态和朝向的绘制指令的匿名定义 -->
    <drawingOrder>
        <!-- 闲置状态 -->
        <idle_up>
            <textures>
                <li>Character_Maid_Walk_37</li>              
            </textures>
        </idle_up>
        <idle_down>
            <textures>
                <li>Character_Maid_Walk_1</li>
            </textures>
        </idle_down>
        <idle_left>
            <textures>
                <li>Character_Maid_Walk_13</li>
            </textures>
        </idle_left>
        <idle_right>
            <textures>
                <li>Character_Maid_Walk_25</li>
            </textures>
        </idle_right>

        <!-- 行走状态 -->
        <walk_up>
            <FPS>5.0</FPS>
            <textures>
                <li>Character_Maid_Walk_36</li>
                <li>Character_Maid_Walk_37</li>
                <li>Character_Maid_Walk_38</li>
                <li>Character_Maid_Walk_37</li>
            </textures>
        </walk_up>
        <walk_down>
            <FPS>5.0</FPS>
            <textures>
                <li>Character_Maid_Walk_0</li>
                <li>Character_Maid_Walk_1</li>
                <li>Character_Maid_Walk_2</li>
                <li>Character_Maid_Walk_1</li>
            </textures>
        </walk_down>
        <walk_left>
            <FPS>5.0</FPS>
            <textures>
                <li>Character_Maid_Walk_12</li>
                <li>Character_Maid_Walk_13</li>
                <li>Character_Maid_Walk_14</li>
                <li>Character_Maid_Walk_13</li>
            </textures>
        </walk_left>
        <walk_right>
            <FPS>5.0</FPS>
            <textures>
                <li>Character_Maid_Walk_24</li>
                <li>Character_Maid_Walk_25</li>
                <li>Character_Maid_Walk_26</li>
                <li>Character_Maid_Walk_25</li>
            </textures>
        </walk_right>

        <!-- 近战攻击状态 -->
        <meleeAttack_down>
            <textures>
                <li>testPawn_6</li>
            </textures>
        </meleeAttack_down>
        <!-- 忽略其他攻击状态以作演示 -->
    </drawingOrder>

    <!-- 角色行为树的匿名定义 -->
    <behaviorTree>
        <className>ThinkNode_Selector</className>
        <childTree>
            <!-- 尝试攻击 -->
            <li>
                <className>ThinkNode_Sequence</className>
                <childTree>
                    <li><className>JobNode_MoveToAttackRange</className></li>
                    <li><className>JobNode_AttackTarget</className></li>
                </childTree>
            </li>
            <!-- 否则,漫无目的地游荡和闲置 -->
            <li>
                <className>ThinkNode_Sequence</className>
                <childTree>
                    <li><className>JobNode_Wander</className></li>
                    <li><className>JobNode_Idle</className></li>
                </childTree>
            </li>
        </childTree>
    </behaviorTree>

    <!-- 角色碰撞体信息 -->
    <colliderSize>1.0,1.5</colliderSize>
    <colliderPosition>0.0,0.75</colliderPosition>

    <!-- 角色体内场景定义 -->
    <insideDimensionDef>PlayerBodyDimension</insideDimensionDef>
</Define>

MonsterDef (怪物定义)

MonsterDef 用于定义游戏中的怪物实体。它继承了基础的实体定义 EntityDef,并在此基础上增加了怪物特有的武器配置。

根元素: <Define>

DefName: 必需,全局唯一的字符串,用于标识特定的怪物定义。

Label: 可选,字符串,用于在游戏中显示的怪物名称。

Description: 可选,字符串,对怪物的详细描述。


参数说明

MonsterDef 继承了 EntityDef 的所有参数:

  • <attributes>: 怪物的基础属性,这是一个 AttributesDef 类型的匿名定义
  • <drawingOrder>: 怪物的绘制指令,这是一个 DrawingOrderDef 类型的匿名定义
  • <behaviorTree>: 怪物的行为逻辑树,这是一个 BehaviorTreeDef 类型的匿名定义
  • <affiliation>: 怪物的所属阵营,可以引用一个现有的 AffiliationDefdefName,或在此处进行匿名定义
  • <eventDef>: 怪物特定事件触发的行为,这是一个 EntityEventDef 类型的匿名定义
  • <colliderSize>: 字符串,定义角色的碰撞体大小,通常为 "宽,高" 格式。例如 "1.0,1.0"。
  • <colliderPosition>: 字符串,定义角色的碰撞体相对角色中心的位置偏移,通常为 "x,y" 格式。例如 "0.0,0.5"。
  • <insideDimensionDef>: 引用一个 DimensionDefdefName,指定当怪物进行“体内场景”战斗时所使用的维度定义。

除了继承的参数外,MonsterDef 还有一个特有的参数:

<weapon>

定义怪物默认持有的武器。这是一个 WeaponDef 类型的匿名定义

WeaponDef 包含的字段说明:

  • <type>: 字符串,武器的类型。"Melee" (近战武器) 或 "Ranged" (远程武器)。默认为 "Melee"。
  • <attributes>: 武器提供的额外属性加成或改变。这是一个 AttributesDef 类型的匿名定义,与怪物自身的 attributes 结构相同,用于修正武器相关的属性,例如武器的攻击力、攻击速度和攻击范围。 示例:
    <attributes>
        <attack>5</attack>
        <attackSpeed>1.5</attackSpeed>
        <attackRange>2</attackRange>
    </attributes>
    
  • <bullet>: 如果武器类型为“Ranged”,则需要定义发射的子弹。可以引用一个现有的 BulletDefdefName,或者直接在此处进行匿名定义作为引用:
    <bullet>ArrowBullet</bullet> <!-- 引用名为 "ArrowBullet" 的 BulletDef -->
    
    作为匿名定义:
    <bullet>
        <defName>FireballWeaponBullet</defName> <!-- 匿名定义也需要defName -->
        <image>Bullet_Fireball</image>
        <speed>10</speed>
        <damage>15</damage>
    </bullet>
    
  • <attackAnimation>: 字符串数组,指定武器的攻击动画帧。每个 <li> 元素内是一个贴图的 defName示例:
    <attackAnimation>
        <li>Weapon_Sword_Swing_1</li>
        <li>Weapon_Sword_Swing_2</li>
    </attackAnimation>
    
  • <attackDetectionTime>: 浮点数,攻击判定发生的时间点,相对攻击动画开始的秒数。默认为0。
  • <useEntityAttackAnimation>: 布尔值,如果为 true,则优先使用怪物自身的攻击动画,武器的 attackAnimation 将被忽略。默认为 true

示例

<MonsterDef>
    <defName>chicken</defName>
    <label>不大聪明</label>
    <description>一只弱小的鸡,但可能很狡猾。</description>

    <attributes>
        <health>20</health>
        <moveSpeed>1.5</moveSpeed>
        <attack>5</attack>
        <defense>0</defense>
    </attributes>

    <drawingOrder>
        <!-- 鸡的各种状态绘制,此处省略具体细节 -->
        <idle_down>
            <textures><li>Chicken_Idle_0</li></textures>
        </idle_down>
        <walk_down>
            <FPS>8.0</FPS>
            <textures>
                <li>Chicken_Walk_0</li>
                <li>Chicken_Walk_1</li>
                <li>Chicken_Walk_2</li>
            </textures>
        </walk_down>
        <meleeAttack_down>
            <textures><li>Chicken_Attack_0</li><li>Chicken_Attack_1</li></textures>
            <FPS>10.0</FPS>
        </meleeAttack_down>
    </drawingOrder>

    <behaviorTree>
        <className>ThinkNode_Selector</className>
        <childTree>
            <!-- 发现敌人则攻击 -->
            <li>
                <className>ThinkNode_Conditional</className>
                <value>HasTarget()</value>
                <childTree>
                    <li><className>JobGiver_AttackJob</className></li>
                </childTree>
            </li>
            <!-- 否则随机漫游 -->
            <li>
                <className>ThinkNode_Sequence</className>
                <childTree>
                    <li><className>JobGiver_Wander</className></li>
                    <li><className>JobGiver_Idle</className></li>
                </childTree>
            </li>
        </childTree>
    </behaviorTree>

    <affiliation>monster</affiliation>

    <colliderSize>0.8,0.8</colliderSize>
    <colliderPosition>0.0,0.4</colliderPosition>

    <!-- 怪物默认持有的武器的匿名定义 -->
    <weapon>
        <type>Melee</type>
        <attributes>
            <attack>2</attack> <!-- 武器提供2点额外攻击力 -->
            <attackRange>0.8</attackRange> <!-- 武器的攻击范围 -->
            <attackSpeed>1.0</attackSpeed>
        </attributes>
        <!-- 鸡的攻击使用自身的动画,不单独定义武器动画 -->
        <useEntityAttackAnimation>true</useEntityAttackAnimation> 
        <attackDetectionTime>0.2</attackDetectionTime> <!-- 攻击动画播放0.2秒后进行判定 -->
    </weapon>
</MonsterDef>

建筑定义 (<BuildingDef>)

功能说明

建筑定义用于在游戏中创建各种静态或动态的建筑对象。它继承自 实体定义 (<EntityDef>),这意味着建筑也具备通常实体的属性、行为和外观。 BuildingDef 特别之处在于其 buildingType 字段,它决定了建筑是作为背景瓦片存在(Static),还是作为一个可互动、有碰撞、可触发事件的实体(Dynamic)。当 buildingTypeDynamic 时,建筑可以拥有一个激活按键 (activateKey) 和检测范围 (detectionRadius),允许玩家在靠近时触发预定义的事件。

可用参数

由于 <BuildingDef> 继承自 <EntityDef>,它包含了所有 <EntityDef> 的参数,以及自身特有的参数。

BuildingDef 自身参数
参数名类型默认值说明
defName字符串必需。该建筑定义的唯一标识符。
label字符串(空)可选。该建筑在游戏中显示的名称。
description字符串(空)可选。该建筑的详细描述。
buildingType枚举 (字符串)Static必需。建筑类型,决定其作为瓦片还是实体。详见下文**buildingType 字段**。
slowDown浮点数0.0可选。当实体经过此建筑时,移动速度降低的百分比(0为不减速,1为完全停止)。
tile定义可选。当 buildingTypeStatic 时使用,定义建筑作为什么 瓦片定义。详见下文**tile 字段**。
activateKey字符串 (KeyCode)F可选。当 buildingTypeDynamic 时,玩家在触发器范围内用于激活事件的按键。
detectionRadius浮点数3.0可选。当 buildingTypeDynamic 时,玩家可激活此建筑的触发器范围。
triggerPosition字符串(空)可选。当 buildingTypeDynamic 时,触发器中心的相对坐标(例如:"0,0")。
triggerEvents事件定义数组可选。当 buildingTypeDynamic 且被 activateKey 触发时,将要执行的 事件定义 数组。详见下文**triggerEvents 字段**。
继承自 EntityDef 的参数
参数名类型默认值说明
attributes定义(匿名定义默认值)定义实体的战斗属性(如生命值、移动速度等)。可以是引用或匿名定义。
drawingOrder定义(空)定义实体在不同状态和方向下的纹理绘制顺序。这是一个匿名嵌套定义。
behaviorTree定义(空)可选。定义实体的 行为树,控制其AI行为。可以是引用或匿名定义。
affiliation定义(空)可选。定义实体的 阵营,影响其与世界其他实体的交互。可以是引用或匿名定义。
eventDef定义(空)可选。定义实体特有的 事件。可以是引用或匿名定义。
colliderSize字符串(空)可选。定义实体的碰撞体大小(例如:"1,1"表示一个1x1的方形碰撞体)。
colliderPosition字符串(空)可选。定义实体的碰撞体相对于实体的中心偏移(例如:"0,0")。

示例

静态建筑示例 (装饰墙)
<Define>
    <!-- 瓦片定义,用于静态建筑 -->
    <TileDef>
        <defName>DecorativeWallTile</defName>
        <label>装饰墙</label>
        <texture>Resources/Terrain/Wall_Decorative.png</texture>
        <movementCost>1</movementCost>
    </TileDef>

    <!-- 静态建筑定义,直接作为瓦片存在 -->
    <BuildingDef>
        <defName>DecorativeWall</defName>
        <label>装饰墙</label>
        <description>一堵漂亮的装饰性墙壁,没有任何互动功能。</description>
        <buildingType>Static</buildingType>
        <tile>DecorativeWallTile</tile> <!-- 引用上面定义的瓦片 -->
        <slowDown>0.5</slowDown> <!-- 经过时减速 -->
    </BuildingDef>
</Define>
动态建筑示例 (可互动终端)
<Define>
    <!-- 图像定义 -->
    <ImageDef>
        <defName>TerminalTexture</defName>
        <path>Resources/Buildings/Terminal.png</path>
    </ImageDef>

    <!-- 事件定义 -->
    <EventDef>
        <defName>OpenShopEvent</defName>
        <workClass>Event_OpenUI</workClass>
        <parameter>{"UIName":"ShopPanel"}</parameter>
    </EventDef>

    <!-- 动态建筑定义,可互动 -->
    <BuildingDef>
        <defName>InteractiveTerminal</defName>
        <label>数据终端</label>
        <description>一个可以访问商店功能的数据终端。</description>
        <buildingType>Dynamic</buildingType>
        <!-- 继承自EntityDef的属性 -->
        <attributes>
            <health>100</health>
            <defense>5</defense>
            <!-- 动态建筑默认没有移动速度 -->
        </attributes>
        <drawingOrder>
            <idle_down>
                <textures>
                    <li>TerminalTexture</li>
                </textures>
            </idle_down>
        </drawingOrder>
        <!-- 碰撞体 -->
        <colliderSize>1,1</colliderSize>
        <colliderPosition>0.5,0.5</colliderPosition>

        <!-- BuildingDef 自身的互动属性 -->
        <activateKey>E</activateKey>
        <detectionRadius>1.5</detectionRadius>
        <triggerPosition>0,0</triggerPosition>
        <triggerEvents>
            <li>OpenShopEvent</li> <!-- 引用上方定义的事件 -->
        </triggerEvents>
    </BuildingDef>
</Define>

复杂参数说明

buildingType 字段 (建筑类型)
  • 说明:这是一个枚举值,决定了建筑在游戏中的表现形式:
    • Static: 静态建筑。这类建筑被视为地图的背景瓦片,不具备独立的实体属性(如生命值、碰撞体),不会移动,也不受伤害。它们主要用于填充地图,定义可通行区域或视觉效果。当 buildingTypeStatic 时,tile 字段是必需的,它定义了这个静态建筑所代表的实际 瓦片定义
    • Dynamic: 动态建筑。这类建筑被视为一个独立的游戏实体,拥有自己的属性 (attributes)、外观 (drawingOrder)、碰撞体 (colliderSize, colliderPosition),可以被破坏,也可以进行互动。当 buildingTypeDynamic 时,activateKeydetectionRadiustriggerPositiontriggerEvents 等字段可用于定义其互动逻辑。
  • 示例
    <buildingType>Static</buildingType>
    <buildingType>Dynamic</buildingType>
    
tile 字段 (瓦片定义)
  • 说明:当 buildingType 设置为 Static 时,此字段必需。它指定了该静态建筑所使用的底层 瓦片定义。可以是预定义瓦片的 defName 引用,也可以是当前位置的匿名定义。
  • 引用方式
    <tile>TileDef的defName</tile>
    
  • 匿名定义方式
    <tile>
        <label>草地</label>
        <texture>Resources/Terrain/Grass.png</texture>
        <movementCost>1</movementCost>
        <isWalkable>true</isWalkable>
    </tile>
    
triggerEvents 字段 (触发事件数组)
  • 说明:这是一个数组,当 buildingTypeg 为 Dynamic 且玩家在建筑的 detectionRadius 范围内按下 activateKey 时,数组中的所有 事件定义 将按顺序被触发。每个 <li> 元素可以引用一个已定义的事件 defName 或进行匿名定义。
  • 数组定义方式
    <triggerEvents>
        <li>EventDef的defName1</li>
        <li>EventDef的defName2</li>
        <li>
            <!-- 匿名定义一个事件 -->
            <workClass>Event_PlaySound</workClass>
            <parameter>{"SoundId":"ActivateBuildingSound"}</parameter>
        </li>
    </triggerEvents>
    

规则瓦片定义 (<TileDef>)

功能说明

规则瓦片定义用于创建一种智能瓦片,它能根据周围相邻瓦片的类型自动改变其自身的纹理、动画、碰撞体和属性。这种机制极大地简化了地图的绘制工作,尤其适用于那些需要平滑过渡或形成复杂图案的自然地形(如水体、草地边缘、道路等)。每个规则瓦片都包含一系列规则 (rules),系统会根据这些规则来决定在特定邻居条件下应该显示哪种外观。

可用参数

参数名类型默认值说明
defName字符串必需。该规则瓦片定义的唯一标识符。
label字符串(空)可选。该瓦片在游戏中显示的名称。
description字符串(空)可选。该瓦片的详细描述。
collider枚举 (字符串)None必需。瓦片的默认碰撞体类型。详见下文**collider 字段**。
texture字符串(空)可选。瓦片的默认纹理路径或名称,当没有规则匹配时使用。
tileCost浮点数0.0可选。当实体进入该瓦片时,其移动速度降低的百分比(0为不减速,1为完全停止)。
rules规则瓦片规则定义数组必需。定义瓦片如何根据邻居生成不同外观。详见下文**rules 字段**。

示例

这是一个定义了水体规则瓦片的例子,它根据周围水瓦片或非水瓦片的存在来选择不同的纹理:

<Define>
    <TileDef>
        <defName>Water</defName>
        <label>水面</label>
        <description>地图上的水体瓦片,构成河流和湖泊的背景。</description>
        <collider>Grid</collider> <!-- 水面具有网格碰撞体 -->
        <texture>tileMap_37</texture> <!-- 默认纹理或中心水纹理 -->
        <tileCost>0.5</tileCost> <!-- 经过水面时,移动速度减慢50% -->
        <rules>
            <!-- 规则1:周围八个方向都是水瓦片时,显示完整的中心水面 -->
            <rule>
                <neighborConditions>
                    <li>This</li><li>This</li><li>This</li>
                    <li>This</li>                 <li>This</li>
                    <li>This</li><li>This</li><li>This</li>
                </neighborConditions>
                <animationTextures>
                    <li>tileMap_37</li>
                </animationTextures>
                <outputCollider>Grid</outputCollider>
            </rule>

            <!-- 规则2:顶部无水瓦片,形成水体顶部边缘 -->
            <rule>
                <neighborConditions>
                    <li>Any</li><li>NotThis</li><li>Any</li>
                    <li>This</li>                 <li>This</li>
                    <li>This</li><li>This</li><li>This</li>
                </neighborConditions>
                <animationTextures>
                    <li>tileMap_19</li>
                </animationTextures>
                <outputCollider>Grid</outputCollider>
            </rule>

            <!-- 规则3:左侧无水瓦片,形成水体左侧边缘 -->
            <rule>
                <neighborConditions>
                    <li>Any</li><li>This</li><li>This</li>
                    <li>NotThis</li>                 <li>This</li>
                    <li>Any</li><li>This</li><li>This</li>
                </neighborConditions>
                <animationTextures>
                    <li>tileMap_36</li>
                </animationTextures>
                <outputCollider>Grid</outputCollider>
            </rule>
             <!-- ... 更多规则,定义了水体不同边缘和角的纹理 -->

             <!-- 规则10:左上无水瓦片,顶中和左中是水瓦片,形成左上角内凹 -->
            <rule>
                <neighborConditions>
                    <li>NotThis</li><li>This</li><li>Any</li>
                    <li>This</li>                 <li>This</li>
                    <li>Any</li><li>This</li><li>This</li>
                </neighborConditions>
                <animationTextures>
                    <li>tileMap_90</li>
                </animationTextures>
                <outputCollider>Grid</outputCollider>
            </rule>

            <!-- 规则20:完全独立的水单元,孤立于所有其他瓦片 -->
            <rule>
                <neighborConditions>
                    <li>Any</li><li>NotThis</li><li>Any</li>
                    <li>NotThis</li>                 <li>NotThis</li>
                    <li>Any</li><li>NotThis</li><li>Any</li>
                </neighborConditions>
                <animationTextures>
                    <li>tileMap_73</li> <!-- 示例:孤立水图标 -->
                </animationTextures>
                <outputCollider>Grid</outputCollider>
            </rule>
        </rules>
    </TileDef>
</Define>

规则瓦片规则定义 (<RuleTileRuleDef>)

功能说明

每个规则瓦片规则定义(通常作为 规则瓦片定义 (<TileDef>) 内部的匿名定义存在)规定了在满足特定邻居条件时,该瓦片应该采用何种外观、动画、碰撞体和变换方式。规则按顺序评估,第一个匹配的规则将被应用。

可用参数

参数名类型默认值说明
defName字符串可选。该规则的唯一标识符(作为匿名定义时可省略)。
label字符串(空)可选。该规则的描述性标签。
description字符串(空)可选。该规则的详细描述。
neighborConditions邻居条件枚举数组[Any,Any,...,Any]必需。定义周围八个方向(中心瓦片周围的3x3网格,去除自身)的瓦片条件。详见下文**neighborConditions 字段**。
neighborConditionExtend邻居条件定义数组可选。用于定义更复杂或非标准位置的邻居条件。详见下文**neighborConditionExtend 字段**。
outputType枚举 (字符串)Single可选。瓦片的输出类型,例如单个精灵、固定动画或随机精灵。
transform枚举 (字符串)Fixed可选。输出精灵的变换方式,例如固定方向或随机旋转。
outputCollider枚举 (字符串)None可选。此规则生效时,瓦片采用的碰撞体类型。会覆盖 TileDef 中的 collider 值。
chance浮点数0.5可选。当多个规则匹配时,此规则被选中的相对概率。
animationTextures字符串列表可选。当 outputTypeAnimation 时,定义动画帧的纹理路径或名称列表。
animationSpeed浮点数1.0可选。动画播放速度。
tileCost浮点数0.0可选。此规则生效时,瓦片的移动成本(减速率0-1)。会覆盖 TileDef 中的 tileCost 值。

复杂参数说明

collider 字段 (瓦片碰撞体类型)
  • 说明:定义瓦片的碰撞体类型。
  • 可选值
    • None: 无碰撞体,实体可以自由穿过。
    • Grid: 网格碰撞体,通常用于阻挡实体移动。
    • Sprite: 使用瓦片纹理的像素数据生成碰撞体,提供更精确的碰撞区域。
  • 示例
    <collider>Grid</collider>
    
rules 字段 (规则瓦片规则定义数组)
  • 说明:这是一个数组,每个 <li> 元素包含一个 规则瓦片规则定义。这些规则会按顺序进行评估,直到找到第一个满足条件的规则并应用其输出。
  • 数组定义方式
    <rules>
        <rule>
            <!-- 规则1的匿名定义 -->
            <neighborConditions>
                <li>Any</li><li>NotThis</li><li>Any</li>
                <li>This</li>                 <li>This</li>
                <li>This</li><li>This</li><li>This</li>
            </neighborConditions>
            <animationTextures>
                <li>tileMap_19</li>
            </animationTextures>
        </rule>
        <rule>
            <!-- 规则2的匿名定义 -->
            <neighborConditions>
                <li>Any</li><li>This</li><li>This</li>
                <li>NotThis</li>                 <li>This</li>
                <li>Any</li><li>This</li><li>This</li>
            </neighborConditions>
            <animationTextures>
                <li>tileMap_36</li>
            </animationTextures>
        </rule>
        <!-- ... 更多规则 -->
    </rules>
    
neighborConditions 字段 (邻居条件数组)
  • 说明:这是一个固定大小为8的数组,按顺时针方向定义了中心瓦片周围八个邻居的条件,从左上角开始。 瓦片位置(数字代表数组索引): [0] [1] [2] [7] [.] [3] (. 是当前瓦片自身) [6] [5] [4]
  • 相邻条件类型 (NeighborConditionType)
    • Any: 任何类型的瓦片都可以。
    • This: 邻居瓦片必须与当前规则瓦片定义的是同类型瓦片。
    • NotThis: 邻居瓦片不能是当前规则瓦片定义的是同类型瓦片。
  • 数组定义方式
    <neighborConditions>
        <li>This</li><li>This</li><li>This</li>     <!-- 左上、上、右上 -->
        <li>This</li>                 <li>This</li>     <!-- 左、右 -->
        <li>This</li><li>This</li><li>This</li>     <!-- 左下、下、右下 -->
    </neighborConditions>
    
    这个例子表示要求所有八个邻居都是当前瓦片类型。
neighborConditionExtend 字段 (扩展邻居条件数组)
  • 说明:这是一个数组,允许定义除了标准8个邻居之外,任意偏移位置的邻居条件。每个 <li> 元素包含一个 邻居条件定义 (<NeighborConditionDef>) 的匿名定义或引用。
  • 数组定义方式
    <neighborConditionExtend>
        <li>
            <position>2,0</position> <!-- 距离中心瓦片右侧2格的瓦片 -->
            <Type>NotThis</Type>
        </li>
        <li>
            <!-- 引用已定义的扩展邻居条件 -->
            <defName>FarNeighborIsGrass</defName>
        </li>
    </neighborConditionExtend>
    
outputCollider 字段 (输出碰撞体) 与 tileCost 字段 (瓦片移动成本)
  • 说明:这些字段允许你在特定规则生效时,动态地改变瓦片的碰撞体类型和移动成本(减速率)。如果规则中定义了这些值,它们将覆盖 TileDef 中对应的默认值。
  • 示例
    <outputCollider>Grid</outputCollider>
    <tileCost>0.8</tileCost> <!-- 当此规则生效时,移动减速80% -->
    
animationTextures 字段 (动画精灵列表)
  • 说明:这是一个字符串列表,指定了动画的每一帧所使用的纹理资源路径或名称。当规则的 outputTypeAnimation 时,这些纹理会按顺序播放,形成动画效果。
  • 列表定义方式
    <animationTextures>
        <li>tileMap_37</li>
        <li>tileMap_38</li>
        <li>tileMap_39</li>
    </animationTextures>
    

邻居条件定义 (<NeighborConditionDef>)

功能说明

邻居条件定义通常作为 规则瓦片规则定义 (<RuleTileRuleDef>)neighborConditionExtend 字段的匿名定义或引用,用于指定除了标准8个方向之外的、任意偏移位置的瓦片需要满足的条件。

可用参数

参数名类型默认值说明
defName字符串可选。该邻居条件的唯一标识符(作为匿名定义时可省略)。
label字符串(空)可选。该邻居条件的描述性标签。
description字符串(空)可选。该邻居条件的详细描述。
position字符串必需。相对于中心瓦片的位置偏移,格式为 "X,Y"(例如:"1,0"表示右侧一格,"-1,1"表示左上角对角线一格)。
Type枚举 (字符串)Any必需。该位置上的瓦片需要满足的条件。详见上文**neighborConditions 字段中的相邻条件类型 (NeighborConditionType)**。

示例

这是一个定义了一个扩展邻居条件的例子:

<!-- 在 RuleTileRuleDef 中的使用 -->
<rule>
    <!-- ...其他规则条件... -->
    <neighborConditionExtend>
        <li>
            <position>2,0</position> <!-- 距离中心瓦片右侧2格的瓦片 -->
            <Type>NotThis</Type>     <!-- 要求右侧2格的瓦片不能是当前规则瓦片类型 -->
        </li>
        <li>
            <position>0,-3</position> <!-- 距离中心瓦片下方3格的瓦片 -->
            <Type>This</Type>        <!-- 要求下方3格的瓦片必须是当前规则瓦片类型 -->
        </li>
    </neighborConditionExtend>
    <!-- ...其他输出属性... -->
</rule>

地图生成器定义 (<MapGeneratorDef>)

功能说明

地图生成器定义用于配置负责生成游戏地图不同元素的逻辑。每个地图生成器都指定了一个具体的工作类 (workClass),该工作类会根据提供的配置值 (value) 来执行地图的某一部分生成任务,例如生成地形、放置建筑、植被等。这些生成器是模块化的,可以组合起来构建复杂的地图布局。

可用参数

参数名类型默认值说明
defName字符串必需。该地图生成器定义的唯一标识符。
label字符串(空)可选。该生成器在游戏中显示的名称。
description字符串(空)可选。该生成器的详细描述。
workClass字符串必需。指定处理地图生成逻辑的后端类名。详见下文**workClass 字段**。
valueJSON字符串必需。包含传递给 workClass 的所有必要参数。详见下文**value 字段 (JSON 格式详解)**。

示例

以下展示了几种不同类型的地图生成器定义:

<Define>
    <!-- 树木地图生成器 -->
    <MapGeneratorDef>
        <defName>TreeGenerator</defName>
        <label>树木地图生成器</label>
        <description>一个简单的树木地图生成器,根据密度填充地图为树木。</description>
        <workClass>PlantMapGenerator</workClass>
        <value>
            {
                "tileDefName":"Tree",           <!-- 要生成的树木TileDef名称 -->
                "mapCellSizeX":50,              <!-- 地图的X轴大小 -->
                "mapCellSizeY":50,              <!-- 地图的Y轴大小 -->
                "requiredBaseTileDefName":"Grass", <!-- 必须在什么基础地形上生成 -->
                "density":0.2,                  <!-- 树木的生成密度 -->
                "threshold":0,                  <!-- 生成阈值,用于控制perlin噪声或随机性 -->
                "Scale":5                       <!-- 用于perlin噪声的缩放因子 -->
            }
        </value>
    </MapGeneratorDef>

    <!-- 基地建筑生成器 - 放置特定模式的建筑 -->
    <MapGeneratorDef>
        <defName>BaseBuildingGenerator</defName>
        <label>基地建筑生成器</label>
        <description>一个简单的基地建筑生成器,根据预定义模式放置建筑。</description>
        <workClass>BuildingMapGenerator</workClass>
        <value>
            {
                "defName":"ConcreteWall",  <!-- 默认填充的实体DefName -->
                "positionX":9,             <!-- 建筑模式的起始X坐标 -->
                "positionY":20,            <!-- 建筑模式的起始Y坐标 -->
                "mapping":                 <!-- 数字与DefName的映射关系 -->
                {
                    "1":"ConcreteWall",
                    "2":"SkillTreeShop",
                    "3":"StartPoint"
                },
                "pattern": [               <!-- 建筑布局模式,0代表不放置,1-9代表按mapping放置 -->
                        [2,0,0,0,0,0,0,0,0,0,0,0,0,3],
                        [1,0,0,0,0,0,0,0,0,0,0,0,0,1],
                        [1,0,0,0,0,0,0,0,0,0,0,0,0,1],
                        [1,0,0,0,0,0,0,0,0,0,0,0,0,1],
                        [1,0,0,0,0,0,0,0,0,0,0,0,0,1],
                        [1,0,0,0,0,0,0,0,0,0,0,0,0,1],
                        [1,0,0,0,0,0,0,0,0,0,0,0,0,1],
                        [1,0,0,0,0,0,0,0,0,0,0,0,0,1],
                        [1,0,0,0,0,0,0,0,0,0,0,0,0,1],
                        [1,1,1,1,1,1,1,1,1,1,1,1,1,1]
                    ]
            }
        </value>
    </MapGeneratorDef>

    <!-- 基地地板填充生成器 -->
    <MapGeneratorDef>
        <defName>BaseFloorFiller</defName>
        <label>基地地板填充</label>
        <description>一个简单的基地地板填充生成器,填充指定区域为基地地板。</description>
        <workClass>BasicTerrainMapGenerator</workClass>
        <value>
        {
            "tileDefName":"BaseFloor",    <!-- 要填充的TileDef名称 -->
            "mapCellSizeX":30,            <!-- 填充区域的X轴大小 -->
            "mapCellSizeY":30,            <!-- 填充区域的Y轴大小 -->
            "threshold":-1,               <!-- 生成阈值,-1常用于完全填充 -->
            "Scale":2,                    <!-- 缩放因子 -->
            "offsetX":0,                  <!-- 填充区域的X轴偏移 -->
            "offsetY":0                   <!-- 填充区域的Y轴偏移 -->
        }
        </value>
    </MapGeneratorDef>

    <!-- 基地顶部墙面绘制生成器 -->
    <MapGeneratorDef>
        <defName>BaseUpWallFiller</defName>
        <label>基地顶部墙面绘制</label>
        <description>在地图顶部绘制一层基地墙面。</description>
        <workClass>BasicTerrainMapGenerator</workClass>
        <value>
        {
            "tileDefName":"BaseWall",     <!-- 要填充的TileDef名称 -->
            "mapCellSizeX":30,            <!-- 墙面区域的X轴大小 -->
            "mapCellSizeY":1,             <!-- 墙面区域的Y轴大小 -->
            "threshold":-1,               <!-- 生成阈值 -->
            "Scale":2,                    <!-- 缩放因子 -->
            "originX":0,                  <!-- 墙面起始X坐标 -->
            "originY":30                  <!-- 墙面起始Y坐标 -->
        }
        </value>
    </MapGeneratorDef>
</Define>

复杂参数说明

workClass 字段 (工作类)
  • 说明:指定负责实际地图生成逻辑的后端类名。此字符串必须精确匹配到游戏中对应的地图生成器类。不同的 workClass 会需要不同结构的 value 参数。
  • 示例
    <workClass>PlantMapGenerator</workClass>
    <workClass>BuildingMapGenerator</workClass>
    <workClass>BasicTerrainMapGenerator</workClass>
    
  • 注意workClass 定义的详细讲解将在 第三章:核心工作类定义 中提供。
value 字段 (JSON 格式详解)
  • 说明:这是一个 JSON 格式的字符串,包含了传递给 workClass 指定的地图生成器类的所有必要参数。value 的内部结构和字段名必须与 workClass 所期望的参数类型严格匹配。

  • JSON 格式的特点

    • 键值对:由键(字符串)和值组成,键和值之间用冒号 : 分隔。
    • 对象:用大括号 {} 包裹,包含零个或多个键值对,键值对之间用逗号 , 分隔。
    • 数组:用方括号 [] 包裹,包含零个或多个值,值之间用逗号 , 分隔。
    • 数据类型:支持字符串、数字、布尔值 (true/false)、JSON 对象、JSON 数组和 null
  • 编写规则

    • 整个 JSON 结构必须是合法的。
    • 所有键(字段名)必须用双引号 "" 包裹。
    • 所有字符串值也必须用双引号 "" 包裹。数字、布尔值不需要。
    • JSON 内部可以包含换行符和缩进,以提高可读性,这些空白字符在解析时会被忽略。
  • 不同 workClass 对应的 value 结构示例

    • PlantMapGeneratorvalue (如 TreeGenerator 示例所示):

      {
          "tileDefName":"Tree",
          "mapCellSizeX":50,
          "mapCellSizeY":50,
          "requiredBaseTileDefName":"Grass",
          "density":0.2,
          "threshold":0,
          "Scale":5
      }
      

      这些参数通常用于控制植被的类型、生成范围、密度以及基于Perlin噪声的分布。

    • BuildingMapGeneratorvalue (如 BaseBuildingGenerator 示例所示):

      {
          "defName":"ConcreteWall",
          "positionX":9,
          "positionY":20,
          "mapping":
          {
              "1":"ConcreteWall",
              "2":"SkillTreeShop",
              "3":"StartPoint"
          },
          "pattern": [
                  [2,0,0,0,0,0,0,0,0,0,0,0,0,3],
              ]
      }
      

      这些参数通常用于定义一个二维的建筑放置模式,通过 mapping 将模式中的数字映射到具体的实体定义。

    • BasicTerrainMapGeneratorvalue (如 BaseFloorFiller 示例所示):

      {
          "tileDefName":"BaseFloor",
          "mapCellSizeX":30,
          "mapCellSizeY":30,
          "threshold":-1,
          "Scale":2,
          "offsetX":0,
          "offsetY":0
      }
      

      这些参数通常用于在指定区域填充单一类型的地形或方块,通过 mapCellSizeX, mapCellSizeY, offsetX, offsetY 来定义区域范围。

  • 注意事项

    • value 中的 JSON 结构必须与 workClass 内部定义的参数类结构完全匹配,包括字段名的大小写和数据类型。任何不匹配都可能导致地图生成器无法正确执行。
    • 为了配置文件的可读性和易维护性,强烈建议使用多行和缩进来格式化 value 的内容。

维度定义 (<DimensionDef>)

功能说明

维度定义用于配置游戏中的一个独立“维度”或“地图”,它是一个可玩的游戏区域。每个维度都会指定一套地图生成器 (mapGenerators) 来构建其地形、放置初始建筑或植被等。此外,它还可以关联一个故事情节 (story) 作为该维度的开场或主线,并包含用于游戏启动界面展示的图标 (icon) 和玩家是否可以在游戏开始时选择该维度的标志 (canSelect)。

可用参数

参数名类型默认值说明
defName字符串必需。该维度定义的唯一标识符。
label字符串(空)可选。该维度在游戏中显示的名称。
description字符串(空)可选。该维度的详细描述。
mapGenerators地图生成器数组必需。定义构建此维度的地图生成器链。详见下文**mapGenerators 字段**。
icon字符串(空)可选。用于在游戏开始界面选择地图时显示的图标路径。
canSelect布尔值true可选。指示玩家是否可以在游戏开始时直接选择该维度作为起始地图。
story定义可选。关联到该维度的一个故事情节定义,常用于开场引导或主线剧情。详见下文**story 字段**。

示例

这是一个定义了一个可选择的、包含多个地图生成器和开场故事的维度示例:

<Define>
    <!-- 引用或匿名定义的地图生成器 -->
    <MapGeneratorDef defName="GrasslandsTerrain">
        <workClass>BasicTerrainMapGenerator</workClass>
        <value>{"tileDefName":"Grass", "mapCellSizeX":100, "mapCellSizeY":100, "threshold":-1, "Scale":1}</value>
    </MapGeneratorDef>
  
    <MapGeneratorDef defName="ForestScatter">
        <workClass>PlantMapGenerator</workClass>
        <value>{"tileDefName":"Tree", "mapCellSizeX":100, "mapCellSizeY":100, "requiredBaseTileDefName":"Grass", "density":0.3, "threshold":0.1, "Scale":10}</value>
    </MapGeneratorDef>

    <!-- 引用或匿名定义的故事 -->
    <StoryDef defName="StartingSequence">
        <storyStage>
            <li>
                <nextWaitTime>3</nextWaitTime>
                <messageDef defName="WelcomeMessage"/> <!-- 引用已定义的消息 -->
            </li>
            <li>
                <lastWaitTime>3</lastWaitTime>
                <nextWaitTime>0</nextWaitTime>
                <eventDef defName="SpawnPlayerBase"/> <!-- 引用已定义的事件 -->
            </li>
        </storyStage>
    </StoryDef>

    <!-- 维度定义 -->
    <DimensionDef>
        <defName>ForestDimension</defName>
        <label>茂密森林</label>
        <description>一个绿意盎然、植被茂密的维度,适合喜爱自然风光的玩家。</description>
        <icon>UI/DimensionIcons/ForestMap</icon> <!-- 图标路径 -->
        <canSelect>true</canSelect> <!-- 玩家可以从菜单中选择此地图 -->
        <mapGenerators>
            <li>GrasslandsTerrain</li> <!-- 引用已定义的地图生成器 -->
            <li>ForestScatter</li>
            <li>
                <!-- 匿名定义的地图生成器,用于在特定位置生成起始点 -->
                <workClass>BuildingMapGenerator</workClass>
                <value>
                    {
                        "defName":"StartPoint",
                        "positionX":50,
                        "positionY":50,
                        "mapping":{"1":"StartPoint"},
                        "pattern":[[1]]
                    }
                </value>
            </li>
        </mapGenerators>
        <story>StartingSequence</story> <!-- 引用已定义的故事 -->
    </DimensionDef>

    <DimensionDef>
        <defName>TutorialDimension</defName>
        <label>新手教学</label>
        <description>带领新玩家熟悉游戏基础操作的教学维度。</description>
        <icon>UI/DimensionIcons/TutorialMap</icon>
        <canSelect>false</canSelect> <!-- 此地图仅在特定条件下加载,玩家不能手动选择 -->
        <mapGenerators>
            <li>
                <workClass>BasicTerrainMapGenerator</workClass>
                <value>{"tileDefName":"TutorialGround", "mapCellSizeX":30, "mapCellSizeY":30, "threshold":-1, "Scale":1}</value>
            </li>
            <!-- ...更多教学地图生成器 -->
        </mapGenerators>
        <story>
            <!-- 匿名定义一个简单的教学故事 -->
            <storyStage>
                <li>
                    <nextWaitTime>5</nextWaitTime>
                    <messageDef>
                        <type>ScreenCenterLargeText</type>
                        <text>欢迎来到教学!</text>
                        <color>Yellow</color>
                    </messageDef>
                </li>
            </storyStage>
        </story>
    </DimensionDef>
</Define>

复杂参数说明

mapGenerators 字段 (地图生成器数组)
  • 说明:这是一个数组,包含了用于构建当前维度的所有 地图生成器定义。数组中的 <li> 元素会按顺序执行。每个 <li> 都可以通过引用已定义的地图生成器 defName 或直接进行匿名定义来指定一个地图生成器。
  • 数组定义方式
    <mapGenerators>
        <li>MapGeneratorDef的defName1</li>
        <li>MapGeneratorDef的defName2</li>
        <li>
            <!-- 匿名定义一个地图生成器 -->
            <workClass>AnotherMapGeneratorClass</workClass>
            <value>
                {
                    "paramA": "valueA",
                    "paramB": 123
                }
            </value>
        </li>
    </mapGenerators>
    
story 字段 (故事定义)
  • 说明:关联到该维度的 故事定义。这可以是一个预定义故事的 defName 引用,也可以是在此处直接定义的匿名故事。通常用于在进入该维度时播放开场剧情或设置主线任务。
  • 引用方式
    <story>StoryDef的defName</story>
    
  • 匿名定义方式
    <story>
        <storyStage>
            <li>
                <nextWaitTime>5</nextWaitTime>
                <messageDef>
                    <type>ScreenCenterLargeText</type>
                    <text>新世界,新冒险!</text>
                </messageDef>
            </li>
        </storyStage>
    </story>
    

技能树定义 (<SkillTreeDef>)

功能说明

技能树定义用于构建游戏中的技能树系统,它定义了技能树中的独立节点。每个技能节点可以有特定的标签 (tag)、在用户界面中的位置 (position)、解锁所需的成本 (cost),并可选地绑定到特定阵营 (faction)。更重要的是,每个技能节点可以定义一系列前置技能 (prerequisites),以及成功解锁后能带来的增益,例如解锁新的武器 (unlockedWeapons) 或获得特定的状态效果/增益/减益 (unlockedHediffs)。

可用参数

参数名类型默认值说明
defName字符串必需。该技能树节点定义的唯一标识符。
label字符串(空)可选。该技能节点在游戏中显示的名称。
description字符串(空)可选。该技能节点的详细描述。
tag字符串Default可选。用于对技能进行分类或分组的标签(例如:"Combat", "Crafting", "Exploration")。
position字符串(空)可选。该技能节点在技能树UI中的相对位置,通常为"X,Y"格式(如"100,50")。
cost整数10可选。解锁该技能节点所需消耗的资源点数或其他成本。
faction定义可选。指定此技能节点仅对特定 阵营定义 生效。可以是引用或匿名定义。详见下文**faction 字段**。
prerequisites技能树定义数组可选。解锁此技能节点前必须先解锁的所有 技能树定义 数组。可以是引用或匿名定义。详见下文**prerequisites 字段**。
unlockedWeapons武器定义数组可选。解锁此技能后获得的 武器定义 数组。可以是引用或匿名定义。详见下文**unlockedWeapons 字段**。
unlockedHediffsHediff定义数组可选。解锁此技能后获得的 Hediff 定义 数组(如增益状态、新能力等)。可以是引用或匿名定义。详见下文**unlockedHediffs 字段**。

示例

这是一个完整的技能树定义示例,展示了不同技能节点之间的依赖关系以及解锁内容:

<Define>
    <!-- 阵营定义 (如果需要) -->
    <AffiliationDef>
        <defName>PlayerFaction</defName>
        <label>玩家阵营</label>
    </AffiliationDef>

    <!-- 武器定义 (如果需要) -->
    <WeaponDef>
        <defName>BasicPistol</defName>
        <label>基础手枪</label>
        <!-- ...其他武器属性... -->
    </WeaponDef>

    <WeaponDef>
        <defName>AdvancedRifle</defName>
        <label>高级步枪</label>
        <!-- ...其他武器属性... -->
    </WeaponDef>

    <!-- Hediff 定义 (如果需要) -->
    <HediffDef>
        <defName>IncreasedHealthBuff</defName>
        <label>生命值强化</label>
        <!-- ...其他Hediff属性... -->
    </HediffDef>

    <HediffDef>
        <defName>FastReloadBuff</defName>
        <label>快速换弹</label>
        <!-- ...其他Hediff属性... -->
    </HediffDef>

    <!-- 技能树节点定义 -->
    <SkillTreeDef>
        <defName>BasicCombat</defName>
        <label>基础战斗训练</label>
        <description>提高基础战斗能力。</description>
        <tag>Combat</tag>
        <position>100,100</position>
        <cost>5</cost>
        <faction>PlayerFaction</faction> <!-- 引用阵营 -->
        <unlockedWeapons>
            <li>BasicPistol</li> <!-- 解锁基础手枪 -->
        </unlockedWeapons>
        <unlockedHediffs>
            <li>
                <!-- 匿名定义一个生命值强化 Hediff -->
                <defName>MinorHealthBoost</defName>
                <label>微量生命值提升</label>
                <description>永久提升少量生命值上限。</description>
                <isPermanent>true</isPermanent>
                <effect>HealthMax_Add_5</effect>
            </li>
        </unlockedHediffs>
    </SkillTreeDef>

    <SkillTreeDef>
        <defName>AdvancedMarksmanship</defName>
        <label>高级射击技巧</label>
        <description>解锁高级武器并提高射击精度。</description>
        <tag>Combat</tag>
        <position>250,150</position>
        <cost>15</cost>
        <faction>PlayerFaction</faction>
        <prerequisites>
            <li>BasicCombat</li> <!-- 前置技能:基础战斗训练 -->
        </prerequisites>
        <unlockedWeapons>
            <li>AdvancedRifle</li> <!-- 解锁高级步枪 -->
        </unlockedWeapons>
        <unlockedHediffs>
            <li>FastReloadBuff</li> <!-- 解锁快速换弹 Hediff -->
        </unlockedHediffs>
    </SkillTreeDef>

    <SkillTreeDef>
        <defName>MedicalExpertise</defName>
        <label>医疗专精</label>
        <description>提高医疗效率和治疗能力。</description>
        <tag>Support</tag>
        <position>100,300</position>
        <cost>10</cost>
        <faction>PlayerFaction</faction>
        <unlockedHediffs>
            <li>
                <!-- 匿名定义一个治疗效果提升 Hediff -->
                <defName>HealingEfficiency</defName>
                <label>治疗效率提升</label>
                <effect>HealingRate_Multiply_1.2</effect>
                <description>治疗物品和能力效果提高20%。</description>
            </li>
        </unlockedHediffs>
    </SkillTreeDef>
</Define>

复杂参数说明

faction 字段 (阵营定义)
  • 说明:可选。指定此技能节点仅对特定 阵营定义 内的实体生效或可见。
  • 引用方式
    <faction>AffiliationDef的defName</faction>
    
  • 匿名定义方式
    <faction>
        <defName>AncientRace</defName>
        <label>古老文明</label>
        <description>一个古老而神秘的阵营。</description>
        <!-- ...更多阵营属性... -->
    </faction>
    
prerequisites 字段 (技能树定义数组)
  • 说明:这是一个数组,包含了解锁当前技能节点所需要预先解锁的所有 技能树定义。数组中的每个 <li> 元素可以引用一个已定义的技能树 defName 或直接进行匿名定义。
  • 数组定义方式
    <prerequisites>
        <li>RequiredSkillOne</li> <!-- 引用前置技能 -->
        <li>RequiredSkillTwo</li>
        <li>
            <!-- 匿名定义一个简单前置技能 -->
            <defName>MinorEndurance</defName>
            <label>小幅耐力</label>
            <cost>2</cost>
        </li>
    </prerequisites>
    
unlockedWeapons 字段 (武器定义数组)
  • 说明:这是一个数组,包含了成功解锁当前技能节点后,玩家将(或可以)获得的 武器定义。数组中的每个 <li> 元素可以引用一个已定义的武器 defName 或直接进行匿名定义。
  • 数组定义方式
    <unlockedWeapons>
        <li>PlasmaRifle</li> <!-- 解锁等离子步枪 -->
        <li>
            <!-- 匿名定义一个临时解锁的武器 -->
            <defName>TemporaryFlamethrower</defName>
            <label>临时火焰喷射器</label>
            <duration>600</duration> <!-- 可用时间 -->
            <!-- ...其他武器属性... -->
        </li>
    </unlockedWeapons>
    
unlockedHediffs 字段 (Hediff定义数组)
  • 说明:这是一个数组,包含了成功解锁当前技能节点后,实体将获得的所有 Hediff 定义(状态效果、增益、减益、新能力等)。数组中的每个 <li> 元素可以引用一个已定义的 Hediff defName 或直接进行匿名定义。
  • 数组定义方式
    <unlockedHediffs>
        <li>AdrenalineRush</li> <!-- 解锁肾上腺素激增状态 -->
        <li>
            <!-- 匿名定义一个移动速度提升 Hediff -->
            <defName>EnhancedSpeed</defName>
            <label>增强速度</label>
            <isPermanent>true</isPermanent>
            <effect>MoveSpeed_Multiply_1.1</effect>
            <description>永久提升10%移动速度。</description>
        </li>
    </unlockedHediffs>
    

健康定义 (<HediffDef>)

功能说明

健康定义(HediffDef)用于定义游戏中各种状态效果、增益或减益。它可以是一个临时的加速效果,一个持续的毒素伤害,一个永久的生命值上限提升,或者其他任何能在一段时间内或永久影响实体属性或行为的状态。Hediff可以具有多个发展阶段,并在不同的阶段表现出不同的效果。

可用参数

参数名类型默认值说明
defName字符串必需。该健康定义(Hediff)的唯一标识符。
label字符串(空)可选。该状态效果在游戏中显示的名称。
description字符串(空)可选。该状态效果的详细描述。
time浮点数-1.0必需。状态效果的持续时间(秒)。设置为 -1 表示该效果是永久性的。
stagesHediff阶段定义数组可选。定义该Hediff在不同时间点所表现出的效果阶段。详见下文**stages 字段**。
compsHediff组件定义数组可选。为该Hediff附加额外的功能组件,实现复杂行为。详见下文**comps 字段**。

示例

示例1:简单的临时加速效果
<Define>
    <HediffDef>
        <defName>TemporarySpeedBoost</defName>
        <label>加速</label>
        <description>暂时提升移动速度。</description>
        <time>10</time> <!-- 持续10秒 -->
        <stages>
            <li>
                <start>0</start> <!-- 从 Hediff 出现时立即生效 -->
                <attributesOffset>
                    <moveSpeedPercentOffset>0.5</moveSpeedPercentOffset> <!-- 移动速度提升50% -->
                </attributesOffset>
            </li>
        </stages>
    </HediffDef>
</Define>
示例2:具有多个阶段的毒素效果
<Define>
    <HediffDef>
        <defName>ToxicExposure</defName>
        <label>毒素暴露</label>
        <description>受到毒素影响,随时间恶化。</description>
        <time>30</time> <!-- 总持续30秒 -->
        <stages>
            <li>
                <start>0</start> <!-- 0-10秒:轻微阶段 -->
                <label>轻度中毒</label>
                <attributesOffset>
                    <moveSpeedPercentOffset>-0.1</moveSpeedPercentOffset> <!-- 10%减速 -->
                </attributesOffset>
            </li>
            <li>
                <start>10</start> <!-- 10-20秒:中度阶段 -->
                <label>中度中毒</label>
                <attributesOffset>
                    <moveSpeedPercentOffset>-0.25</moveSpeedPercentOffset> <!-- 25%减速 -->
                    <healthOffset>-0.1</healthOffset> <!-- 每秒损失0.1生命值(通过Comp实现) -->
                </attributesOffset>
            </li>
            <li>
                <start>20</start> <!-- 20-30秒:重度阶段 -->
                <label>重度中毒</label>
                <attributesOffset>
                    <moveSpeedPercentOffset>-0.5</moveSpeedPercentOffset> <!-- 50%减速 -->
                    <attackPercentOffset>-0.2</attackPercentOffset> <!-- 攻击力降低20% -->
                    <healthOffset>-0.3</healthOffset> <!-- 每秒损失0.3生命值 -->
                </attributesOffset>
            </li>
        </stages>
        <comps>
            <li>
                <!-- 范例:一个自定义组件,负责根据attributesOffset.healthOffset属性造成持续伤害 -->
                <compClass>HediffComp_DamageOverTime</compClass> 
                <properties>{"damageType":"Poison", "tickInterval":1.0}</properties>
            </li>
        </comps>
    </HediffDef>
</Define>

Hediff阶段定义 (<HediffStageDef>)

功能说明

Hediff阶段定义(HediffStageDef)用于描述一个特定状态效果在不同发展阶段的具体属性偏移。一个具有多个阶段的Hediff可以在其持续时间内,随着时间的推移从一个阶段过渡到另一个阶段,从而表现出不同的效果。

可用参数

参数名类型默认值说明
defName字符串可选。该阶段的唯一标识符(作为匿名定义时可省略)。
label字符串(空)可选。该阶段在游戏中显示的名称。
description字符串(空)可选。该阶段的详细描述。
start浮点数0.0必需。该阶段开始的时间点。例如,如果所属Hediff的总持续时间为10秒,start 为5,则此阶段从Hediff出现5秒后开始生效。对于永久性Hediff (HediffDef.time 为 -1),阶段按其 start 值从小到大顺序匹配,直到某个 start 值大于当前Hediff已持续时间或匹配到最后一个阶段。
attributesOffset属性偏移定义(匿名定义默认值)必需。定义此阶段对实体属性造成的偏移量。可以是引用或匿名定义。详见下文**attributesOffset 字段**。

复杂参数说明

attributesOffset 字段 (属性偏移定义)
  • 说明:这是一个 属性偏移定义 (<AttributesOffsetDef>) 的匿名定义或引用。它详细说明了该 Hediff 阶段对实体各项属性(如生命值、移动速度、攻击力等)造成的具体影响,包括绝对值偏移和百分比偏移。
  • 匿名定义方式
    <attributesOffset>
        <healthOffset>-5</healthOffset> <!-- 生命值上限减少5 -->
        <moveSpeedPercentOffset>0.2</moveSpeedPercentOffset> <!-- 移动速度提高20% -->
    </attributesOffset>
    

属性偏移定义 (<AttributesOffsetDef>)

功能说明

属性偏移定义(AttributesOffsetDef)是一个辅助定义,通常作为 Hediff阶段定义 (<HediffStageDef>) 中的匿名定义,用于详细指定对实体各项属性的修改量。这些修改可以是直接的数值增减(绝对值偏移),也可以是基于现有属性值的百分比增减(百分比偏移)。

可用参数

参数名类型默认值说明
defName字符串可选。该偏移定义的唯一标识符(作为匿名定义时可省略)。
label字符串(空)可选。该偏移的描述性标签。
description字符串(空)可选。该偏移的详细描述。
healthOffset浮点数0.0生命值上限的绝对值偏移量。
moveSpeedOffset浮点数0.0移动速度的绝对值偏移量。
attackOffset浮点数0.0攻击力的绝对值偏移量。
defenseOffset浮点数0.0防御力的绝对值偏移量。
attackSpeedOffset浮点数0.0攻击速度的绝对值偏移量。
attackRangeOffset浮点数0.0攻击范围的绝对值偏移量。
attackTargetCountOffset浮点数0.0攻击目标数量的绝对值偏移量。
healthPercentOffset浮点数0.0生命值上限的百分比偏移量(例如 0.1 表示 +10%,-0.5 表示 -50%)。
moveSpeedPercentOffset浮点数0.0移动速度的百分比偏移量。
attackPercentOffset浮点数0.0攻击力的百分比偏移量。
defensePercentOffset浮点数0.0防御力的百分比偏移量。
attackSpeedPercentOffset浮点数0.0攻击速度的百分比偏移量。
attackRangePercentOffset浮点数0.0攻击范围的百分比偏移量。
attackTargetCountPercentOffset浮点数0.0攻击目标数量的百分比偏移量。

示例

<!-- 作为 HediffStageDef 内部的匿名定义 -->
<attributesOffset>
    <healthOffset>50</healthOffset>               <!-- 生命值上限增加50 -->
    <moveSpeedPercentOffset>0.15</moveSpeedPercentOffset> <!-- 移动速度增加15% -->
    <attackOffset>10</attackOffset>               <!-- 攻击力增加10 -->
    <defensePercentOffset>-0.05</defensePercentOffset> <!-- 防御力降低5% -->
</attributesOffset>

Hediff组件定义 (<HediffCompDef>)

功能说明

Hediff组件定义(HediffCompDef)允许你为 健康定义 (<HediffDef>) 附加更复杂和动态的行为逻辑。每个组件都是一个独立的模块,可以实现特定功能,例如持续伤害、特殊效果触发、周期性事件等。

可用参数

参数名类型默认值说明
defName字符串可选。该组件定义的唯一标识符(作为匿名定义时可省略)。
label字符串(空)可选。该组件的描述性标签。
description字符串(空)可选。该组件的详细描述。
compClass字符串必需。该组件对应的C#类名。此字符串用于在代码中实例化具体的行为组件。
properties字符串(空)可选。一个自定义属性字符串,通常是JSON格式,用于向 compClass 传递配置参数,以进一步定制组件的行为。

示例

这是一个定义了一个持续造成伤害的Hediff组件的例子:

<!-- 作为 HediffDef 内部的匿名定义 -->
<comps>
    <li>
        <compClass>HediffComp_DamageOverTime</compClass>
        <properties>
            {"damageAmount": 2.5, "damageInterval": 1.0, "damageType": "Burn"}
        </properties>
    </li>
    <li>
        <!-- 另一个组件,例如周期性清除其他Debuff -->
        <compClass>HediffComp_PeriodicCleanse</compClass>
        <properties>
            {"cleanseInterval": 5.0, "cleanseChance": 0.8, "targetHediffTags": ["DebuffTag"]}
        </properties>
    </li>
</comps>

复杂参数说明

properties 字段 (属性字符串)
  • 说明:这是一个字符串字段,用于向 compClass 指定的组件传递自定义的配置数据。该字符串内容通常期望是JSON格式,以便组件可以在运行时解析这些数据来配置其行为。例如,一个伤害组件可能需要 damageAmounttickInterval 参数。
  • 示例
    <properties>
        {"key1": "value1", "key2": 123, "key3": true, "nestedObject": {"subKey": "subValue"}}
    </properties>
    
    组件的C#代码会负责解析这段JSON字符串并将其映射到自身的属性上。

工作类定义

地图生成器

事件工作类

行为树节点

地图生成器工作类 (BasicTerrainMapGenerator)

功能说明

BasicTerrainMapGenerator 是一个基础地形地图生成器工作类,它基于柏林噪声(Perlin Noise)算法来生成地图的特定区域。通过配置不同的参数,您可以控制生成瓦片的类型、密度、大小和分布,从而创建出多样化的地形,如草地、沙漠、水域或山脉。

该生成器通过 MapGeneratorDef 中的 workClass 字段引用,其具体的行为由 value 字段中提供的 JSON 配置来控制。

可用参数

BasicTerrainMapGenerator 通过解析 MapGeneratorDefvalue 字段里的 JSON 配置来工作。此 JSON 配置对应 BasicTerrainGeneratorConfig

JSON参数名XML参数名 (N/A)类型默认值说明
tileDefNameN/A字符串DefaultTerrainTile必需。符合柏林噪声条件的区域将填充的 瓦片定义 (TileDef)defName
thresholdN/A浮点数0.0柏林噪声的最小阈值(-1到1之间),噪声值高于此值才可能放置 tileDefName 指定的瓦片。
maxThresholdN/A浮点数1.0柏林噪声的最大阈值(-1到1之间),噪声值低于此值才可能放置 tileDefName 指定的瓦片。
ElseTileDefNameN/A字符串无 (null)可选。当柏林噪声值不满足 thresholdmaxThreshold 范围时,该区域将填充的 瓦片定义 (TileDef) defName。如果为 null 则不放置任何瓦片。
scaleN/A浮点数0.1柏林噪声的缩放因子。值越大,地形特征(如山脉、湖泊)的尺寸越小;值越小,特征尺寸越大。
offsetXN/A浮点数0.0柏林噪声在X轴上的偏移量,用于改变噪声图案的起始位置。
offsetYN/A浮点数0.0柏林噪声在Y轴上的偏移量,用于改变噪声图案的起始位置。
mapCellSizeXN/A整数100地图生成区域的宽度(以单元格数量计)。
mapCellSizeYN/A整数100地图生成区域的高度(以单元格数量计)。
targetDimensionN/A枚举 (字符串)Base指定生成瓦片的目标地图层。详见下文**MapDimension 枚举**。
originXN/A整数0地图生成区域的左上角X坐标(以单元格数量计)。
originYN/A整数0地图生成区域的左上角Y坐标(以单元格数量计)。

示例

以下是一个 MapGeneratorDef 的示例,它使用了 BasicTerrainMapGenerator 来生成一个基础的草地地图:

<Define>
    <!-- 其他 TileDef 定义... -->
  
    <TileDef>
        <defName>Grass</defName>
        <label>草地</label>
        <texture>tileMap_Grass</texture>
        <collider>None</collider>
        <tileCost>0</tileCost>
    </TileDef>

    <MapGeneratorDef>
        <defName>GrassBase</defName>
        <label>草地基础生成器</label>
        <description>使用柏林噪声生成一个均匀的草地基础地形。</description>
        <workClass>BasicTerrainMapGenerator</workClass>
        <value>
        {
            "tileDefName":"Grass",           // 符合条件的区域填充为"Grass"瓦片
            "mapCellSizeX":100,              // 生成区域宽度100格
            "mapCellSizeY":100,              // 生成区域高度100格
            "threshold":-1.0,                 // 柏林噪声的最小阈值。设为-1.0表示只要噪声值不低于-1.0且不高于maxThreshold,就放置瓦片
            "maxThreshold":1.0,               // 柏林噪声的最大阈值。设为1.0表示只要噪声值不高于1.0且不低于threshold,就放置瓦片
            "scale":7.0,                     // 柏林噪声缩放因子,7.0会生成较小的特征
            "targetDimension":"Base",        // 在基础地形层生成
            "originX":0,                     // 从地图的(0,0)点开始生成
            "originY":0
        }
        </value>
    </MapGeneratorDef>

    <MapGeneratorDef>
        <defName>BasicWaterAndLand</defName>
        <label>基础水陆生成器</label>
        <description>使用柏林噪声生成水域和陆地交错的地形。</description>
        <workClass>BasicTerrainMapGenerator</workClass>
        <value>
        {
            "tileDefName":"Water",             // 噪声在 [0.0, 0.2) 区间放置水瓦片
            "ElseTileDefName":"Grass",         // 噪声在其他区间放置草地瓦片
            "threshold":0.0,                   // 噪声值大于等于0.0
            "maxThreshold":0.2,                // 噪声值小于0.2
            "scale":0.05,                      // 较大的地形特征,形成大片水域和陆地
            "offsetX":100.0,                   // 额外偏移量,使每次生成的地形不同
            "offsetY":50.0,
            "mapCellSizeX":200,                // 生成区域宽度200格
            "mapCellSizeY":200,                // 生成区域高度200格
            "targetDimension":"Base"           // 在基础地形层生成
        }
        </value>
    </MapGeneratorDef>
</Define>

复杂参数说明

value 字段 (JSON配置)
  • 说明MapGeneratorDef 中的 value 字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了 BasicTerrainGeneratorConfig 的所有配置参数,用于指导 BasicTerrainMapGenerator 的具体生成行为。您需要确保提供的JSON字符串是语法正确的。
  • JSON属性与C#映射关系
    • threshold:在JSON中,用于配置C#类中的 MinThreshold 属性。
    • 其他JSON属性名(如 tileDefName, scale 等)与C#类中的对应属性名一致(忽略大小写差异,JSON通常使用驼峰式命名)。
  • 示例:请参考上方的 MapGeneratorDef 示例中 value 标签内的内容。
MapDimension 枚举 (地图层级)
  • 说明:这是一个枚举类型,用于指定 BasicTerrainGeneratorConfig 生成瓦片的目标地图层。不同的层级用于区分不同类型的地图元素,以便于渲染和逻辑处理。
  • 可选值
    • Base: 基础地形层,通常用于放置地面、水体等主要地形瓦片。
    • Building: 建筑层,通常用于放置建筑结构、墙壁等可互动或阻挡的瓦片。
    • Plant: 植物层,通常用于放置树木、草丛等植被瓦片。
  • 示例
    "targetDimension":"Base"
    
    "targetDimension":"Plant"
    

建筑地图生成器工作类 (BuildingMapGenerator)

功能说明

BuildingMapGenerator 是一个专门用于在地图上生成预定义建筑图案的工作类。它通过解析一个JSON格式的配置,将一个二维整数数组表示的图案(pattern)映射到具体的瓦片或建筑定义(mapping),然后将这些瓦片放置在地图的指定位置。这使得您可以轻松地在地图上放置复杂的预设结构,如房间、堡垒或其他定型建筑。

该生成器通过 MapGeneratorDef 中的 workClass 字段引用,其具体的行为由 value 字段中提供的 JSON 配置来控制。

可用参数

BuildingMapGenerator 通过解析 MapGeneratorDefvalue 字段里的 JSON 配置来工作。此 JSON 配置对应 BuildingGeneratorConfig

JSON参数名XML参数名 (N/A)类型默认值说明
defNameN/A字符串可选。此建筑图案配置的内部名称。
mappingN/A字典 (int -> string)必需。将 pattern 数组中的整数值映射到 瓦片定义 (TileDef)建筑定义 (BuildingDef)defName 的字典。详见下文**mapping 字段**。
patternN/A二维整数数组必需。一个二维整数数组,表示建筑的布局图案。数组中的每个整数值都应在 mapping 字典中找到对应的定义。详见下文**pattern 字段**。
baseTileDefNameN/A字符串可选。生成建筑图案所需的基底瓦片类型(例如,必须在"Grass"瓦片上建造)。如果指定,生成器会在放置建筑前检查下方瓦片是否匹配。
autoExpandN/A布尔值false可选。如果为 true,生成器会在指定 positionX/positionY 附近寻找一个合适的空闲区域来放置建筑。如果为 false,则严格按照 positionX/positionY 放置。
positionXN/A整数必需。建筑图案放置起始位置的X坐标(左上角)。
positionYN/A整数必需。建筑图案放置起始位置的Y坐标(左上角)。

示例

以下是一个 MapGeneratorDef 示例,它使用了 BuildingMapGenerator 来生成一个简单的方形房间:

<Define>
    <!-- 瓦片定义示例 -->
    <TileDef>
        <defName>Grass</defName>
        <label>草地</label>
        <texture>tileMap_Grass</texture>
        <collider>None</collider>
        <tileCost>0</tileCost>
    </TileDef>
    <BuildingDef>
        <defName>WoodWall</defName>
        <label>木墙</label>
        <description>坚固的木制墙壁。</description>
        <!-- ... 其他建筑属性 ... -->
    </BuildingDef>
    <BuildingDef>
        <defName>WoodDoor</defName>
        <label>木门</label>
        <description>一扇普通的木门。</description>
        <!-- ... 其他建筑属性 ... -->
    </BuildingDef>
    <BuildingDef>
        <defName>Empty</defName>
        <label>空</label>
        <description>表示空单元格。</description>
        <!-- 一个特殊的空定义,用于mapping中的0 -->
    </BuildingDef>

    <MapGeneratorDef>
        <defName>SimpleRoomGenerator</defName>
        <label>简单房间生成器</label>
        <description>在指定位置生成一个木制房间。</description>
        <workClass>BuildingMapGenerator</workClass>
        <value>
        {
            "defName":"SquareWoodRoom",       // 建筑图案的内部名称
            "mapping":{                       // 整数到瓦片/建筑定义的映射
                "0":"Empty",                  // 0表示地板(空地)
                "1":"WoodWall",               // 1表示木墙
                "2":"WoodDoor"                // 2表示木门
            },
            "pattern":[                       // 2D整数数组定义房间布局
                [1,1,1,1,1],
                [1,0,0,0,1],
                [1,0,2,0,1],
                [1,0,0,0,1],
                [1,1,1,1,1]
            ],
            "baseTileDefName":"Grass",        // 房间必须建在草地上
            "autoExpand":false,               // 不自动扩展搜索区域,严格按坐标放置
            "positionX":50,                   // 放置在地图的X坐标50
            "positionY":50                    // 放置在地图的Y坐标50
        }
        </value>
    </MapGeneratorDef>
</Define>

复杂参数说明

value 字段 (JSON配置)
  • 说明MapGeneratorDef 中的 value 字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串容纳了 BuildingGeneratorConfig 的所有配置参数,用于指导 BuildingMapGenerator 的具体生成行为。您需要确保提供的JSON字符串是语法正确的。
  • JSON属性与C#映射关系
    • 所有JSON属性名(如 defName, mapping, pattern 等)与C#类中的对应属性名一致(JSON通常使用驼峰式命名)。
  • 示例:请参考上方的 MapGeneratorDef 示例中 value 标签内的内容。
mapping 字段 (图案值到定义名称的映射)
  • 说明:这是一个JSON对象,用于将 pattern 数组中的整数编码映射到具体的瓦片或建筑定义的 defName。在JSON中,字典的键必须是字符串,但 BuildingGeneratorConfig 在内部会将其解析为整数键。
    • 例如,"1":"WoodWall" 表示在 pattern 中值为1的单元格将被替换为 WoodWall 建筑。
    • 您可以根据需要定义 0 对应一个空地瓦片或特殊的Empty建筑定义。
  • JSON定义方式
    "mapping":{
        "0":"FloorTile",
        "1":"Wall",
        "2":"Door"
    }
    
pattern 字段 (建筑图案)
  • 说明:这是一个JSON格式的二维数组,由多个整数数组组成,代表了建筑的行和列。每个整数值都必须在 mapping 字典中找到对应的 defName
    • 数组的第一个维度代表行,第二个维度代表列。
    • 图案的左上角(pattern[0][0])将放置在 positionXpositionY 指定的地图坐标处。
  • JSON定义方式
    "pattern":[
        [1,1,1],
        [1,0,1],
        [1,1,1]
    ]
    

条件瓦片生成器工作类 (ConditionalTileGenerator)

功能说明

ConditionalTileGenerator 是一个高级地图生成器工作类,它允许您在地图的指定区域内,根据预设的条件(例如:下方是否存在特定瓦片类型或柏林噪声值是否达到阈值)有选择性地放置新的瓦片。这使得您可以创建更动态和有逻辑的地形生成规则,例如:在水域边缘生成芦苇,或在草地上随机分布小石块。

该生成器通过 MapGeneratorDef 中的 workClass 字段引用,其具体的行为由 value 字段中提供的 JSON 配置来控制。

可用参数

ConditionalTileGenerator 通过解析 MapGeneratorDefvalue 字段里的 JSON 配置来工作。此 JSON 配置对应 ConditionalTileGeneratorConfig

JSON参数名XML参数名 (N/A)类型默认值说明
outputTileDefNameN/A字符串必需。符合所有条件时,要放置的 瓦片定义 (TileDef)defName
outputLayerN/A字符串必需。放置 outputTileDefName 瓦片的目标地图层。可选值有 "base", "building", "plant"。详见下文**outputLayer/conditionLayer 字段**。
conditionTileDefNamesN/A字符串列表可选。如果非空,则只有在目标层(由 conditionLayer 指定)的当前位置存在列表中任意一个 TileDef 时,才可能生成 outputTileDefName。如果为空,则不检查此瓦片条件。
conditionLayerN/A字符串可选。当 conditionTileDefNames 非空时,检查条件瓦片的地图层。可选值有 "base", "building", "plant"。详见下文**outputLayer/conditionLayer 字段**。
positionXN/A整数必需。要进行条件检查和瓦片生成操作的矩形区域的起始X坐标(左上角)。
positionYN/A整数必需。要进行条件检查和瓦片生成操作的矩形区域的起始Y坐标(左上角)。
widthN/A整数1必需。生成区域的宽度(单元格数量)。
heightN/A整数1必需。生成区域的高度(单元格数量)。
usePerlinNoiseN/A布尔值false可选。如果为 true,则在放置瓦片前会进行柏林噪声检查。详见下文柏林噪声配置 (Perlin Noise)
perlinScaleN/A浮点数10.0usePerlinNoisetrue 时,柏林噪声的缩放因子(频率)。值越大,地形特征越粗糙;值越小,特征越平滑。
perlinThresholdN/A浮点数0.5usePerlinNoisetrue 时,柏林噪声的阈值(0.0到1.0之间)。只有柏林噪声值高于此阈值的格子才会生成瓦片。
perlinOffsetXN/A浮点数0.0usePerlinNoisetrue 时,柏林噪声的X轴偏移。
perlinOffsetYN/A浮点数0.0usePerlinNoisetrue 时,柏林噪声的Y轴偏移。

示例

以下是一个 MapGeneratorDef 的示例,它使用了 ConditionalTileGenerator 在特定区域的沙地上生成一些仙人掌:

<Define>
    <!-- 瓦片定义示例 -->
  
    <TileDef>
        <defName>Sand</defName>
        <label>沙地</label>
        <texture>tileMap_Sand</texture>
    </TileDef>
    <!-- 注意:CactusBuildingDef 应该是 BuildingDef 类型,这里简化为 TileDef -->
    <TileDef>
        <defName>Cactus</defName>
        <label>仙人掌</label>
        <texture>tileMap_Cactus</texture>
        <outputLayer>plant</outputLayer>
    </TileDef>

    <MapGeneratorDef>
        <defName>GenerateCactiOnSand</defName>
        <label>在沙地上生成仙人掌</label>
        <description>在地图特定沙地区域内随机生成仙人掌。</description>
        <workClass>ConditionalTileGenerator</workClass>
        <value>
        {
            "outputTileDefName":"Cactus",        // 生成仙人掌
            "outputLayer":"plant",               // 放置在植物层
            "conditionTileDefNames":["Sand"],    // 条件:下方必须是沙地
            "conditionLayer":"base",             // 检查基础层是否有沙地
            "positionX":10,                      // 检查区域的起始X坐标
            "positionY":10,                      // 检查区域的起始Y坐标
            "width":50,                          // 检查区域宽度50格
            "height":50,                         // 检查区域高度50格
            "usePerlinNoise":true,               // 使用柏林噪声进行随机性检查
            "perlinScale":20.0,                  // 柏林噪声频率,数值越大越粗糙(点状分布)
            "perlinThreshold":0.6,               // 只有噪声值高于0.6才生成仙人掌,控制密度
            "perlinOffsetX":100.0,               // 噪声X轴偏移
            "perlinOffsetY":200.0                // 噪声Y轴偏移
        }
        </value>
    </MapGeneratorDef>
</Define>

复杂参数说明

value 字段 (JSON配置)
  • 说明MapGeneratorDef 中的 value 字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了 ConditionalTileGeneratorConfig 的所有配置参数,用于指导 ConditionalTileGenerator 的具体生成行为。您需要确保提供的JSON字符串是语法正确的。
  • JSON属性与C#映射关系
    • 所有JSON属性名(如 outputTileDefName, conditionTileDefNames 等)与C#类中的对应属性名一致(JSON通常使用驼峰式命名)。
  • 示例:请参考上方的 MapGeneratorDef 示例中 value 标签内的内容。
outputLayer / conditionLayer 字段 (地图层级字符串)
  • 说明:这两个字段都用于指定地图的层级。这是一个字符串值,而不是一个枚举数字。
  • 可选值
    • "base": 基础地形层,用于放置地面、水体等。
    • "building": 建筑层,用于放置建筑结构、墙壁等。
    • "plant": 植物层,用于放置树木、草丛等植被。
  • 示例
    "outputLayer":"plant"
    
    "conditionLayer":"base"
    
conditionTileDefNames 字段 (条件瓦片定义列表)
  • 说明:这是一个JSON数组,包含一个或多个 瓦片定义 (TileDef)defName 字符串。当 ConditionalTileGenerator 检查一个格子时,如果该格子在 conditionLayer 指定的层上拥有此列表中任意一个 defName 对应的瓦片,则条件检查通过。
  • JSON定义方式
    "conditionTileDefNames":["Grass", "Dirt", "Sand"]
    
    上述配置表示,如果下方瓦片是“Grass”、“Dirt”或“Sand”中的任意一种,则条件满足。
柏林噪声配置 (usePerlinNoise, perlinScale, perlinThreshold, perlinOffsetX, perlinOffsetY)
  • 说明:当 usePerlinNoise 设置为 true 时,生成器会在每个候选位置计算一个柏林噪声值。只有当这个噪声值高于 perlinThreshold 时,瓦片才会被放置。这为生成过程引入了自然的随机性和分布模式。
    • perlinScale:控制柏林噪声的“粒度”。值越大,噪声图案变化越快,特征越小;值越小,图案变化越慢,特征越大。
    • perlinThreshold:决定瓦片放置的密度。较高的阈值意味着只有噪声值非常高的位置才能放置瓦片,从而导致稀疏分布;较低的阈值则会生成更密集的瓦片。
    • perlinOffsetX, perlinOffsetY:用于偏移柏林噪声的起始点,可以改变生成图案的位置,每次生成都可以使用不同的偏移值来获得不同的随机布局。
  • 示例
    "usePerlinNoise":true,
    "perlinScale":15.0,
    "perlinThreshold":0.7,
    "perlinOffsetX":50.0,
    "perlinOffsetY":120.0
    

植物地图生成器工作类 (PlantMapGenerator)

功能说明

PlantMapGenerator 是一个专门用于在地图上生成植物(如草丛、树木、灌木等)的工作类。它结合了柏林噪声(Perlin Noise)和概率密度来控制植物的分布,并可以指定植物生长的基础瓦片类型。这使得您可以创建茂密的森林、稀疏的草地或只在特定土壤上生长的植被。

该生成器通过 MapGeneratorDef 中的 workClass 字段引用,其具体的行为由 value 字段中提供的 JSON 配置来控制。

可用参数

PlantMapGenerator 通过解析 MapGeneratorDefvalue 字段里的 JSON 配置来工作。此 JSON 配置对应 PlantGeneratorConfig

JSON参数名XML参数名 (N/A)类型默认值说明
tileDefNameN/A字符串DefaultPlantTile必需。要生成的 植物瓦片定义 (TileDef)defName。通常此瓦片定义会放置在 plant 层。
scaleN/A浮点数0.08柏林噪声的缩放因子。值越大,植物群落分布越细碎;值越小,群落范围越大越连贯。
thresholdN/A浮点数0.3柏林噪声的阈值(-1到1之间)。只有柏林噪声值高于此阈值的格子才优先考虑生成植物。
densityN/A浮点数0.6植物生成概率(0.0到1.0之间)。在所有条件(包括柏林噪声和基础瓦片)都满足的情况下,该格子最终生成植物的概率。
offsetXN/A浮点数0.0柏林噪声在X轴上的偏移量,用于改变噪声图案的起始位置。
offsetYN/A浮点数0.0柏林噪声在Y轴上的偏移量,用于改变噪声图案的起始位置。
requiredBaseTileDefNamesN/A字符串列表无 (null)可选。一个字符串列表,包含植物必须生长其上的 基础瓦片定义 (TileDef)defName。如果指定,只有当当前位置的基础层瓦片是列表中任意一个时,才可能生成植物。如果为空,则不检查此条件。
mapCellSizeXN/A整数100地图生成区域的宽度(以单元格数量计)。
mapCellSizeYN/A整数100地图生成区域的高度(以单元格数量计)。
preventOverlapN/A布尔值true可选。如果为 true,生成器会避免在已经有植物瓦片的格子上再次生成植物。

示例

以下是一个 MapGeneratorDef 的示例,它使用了 PlantMapGenerator 在草地和泥土上生成一些稀疏的树木:

<Define>
    <!-- 瓦片定义示例 -->
  
    <TileDef>
        <defName>Grass</defName>
        <label>草地</label>
        <texture>tileMap_Grass</texture>
        <collider>None</collider>
        <tileCost>0</tileCost>
    </TileDef>
    <TileDef>
        <defName>Dirt</defName>
        <label>泥土</label>
        <texture>tileMap_Dirt</texture>
        <collider>None</collider>
        <tileCost>0</tileCost>
    </TileDef>
    <TileDef>
        <defName>TreePine</defName>
        <label>松树</label>
        <texture>plant_TreePine</texture>
        <outputLayer>plant</outputLayer> <!-- 植物通常放置在 plant 层 -->
    </TileDef>

    <MapGeneratorDef>
        <defName>GenerateSparsePineForest</defName>
        <label>生成稀疏松树林</label>
        <description>在草地和泥土上生成稀疏的松树林。</description>
        <workClass>PlantMapGenerator</workClass>
        <value>
        {
            "tileDefName":"TreePine",                     // 要生成的植物是松树
            "scale":0.05,                                 // 柏林噪声缩放因子,值较小,形成更大的森林斑块
            "threshold":0.2,                              // 柏林噪声阈值,控制整体分布区域
            "density":0.3,                                // 密度0.3,表示较为稀疏的树木
            "offsetX":10.0,                               // 噪声X轴偏移
            "offsetY":20.0,                               // 噪声Y轴偏移
            "requiredBaseTileDefNames":["Grass", "Dirt"], // 必须生长在草地或泥土上
            "mapCellSizeX":200,                           // 区域宽度200格
            "mapCellSizeY":200,                           // 区域高度200格
            "preventOverlap":true                         // 防止树木重叠
        }
        </value>
    </MapGeneratorDef>
</Define>

复杂参数说明

value 字段 (JSON配置)
  • 说明MapGeneratorDef 中的 value 字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了 PlantGeneratorConfig 的所有配置参数,用于指导 PlantMapGenerator 的具体生成行为。您需要确保提供的JSON字符串是语法正确的。
  • JSON属性与C#映射关系
    • 所有JSON属性名(如 tileDefName, scale 等)与C#类中的对应属性名一致(JSON通常使用驼峰式命名)。
  • 示例:请参考上方的 MapGeneratorDef 示例中 value 标签内的内容。
requiredBaseTileDefNames 字段 (所需基础瓦片定义列表)
  • 说明:这是一个JSON数组,包含一个或多个 瓦片定义 (TileDef)defName 字符串。PlantMapGenerator 在尝试在某个格子生成植物之前,会检查该格子在基础层的瓦片是否与此列表中的任意一个 defName 匹配。
  • JSON定义方式
    "requiredBaseTileDefNames":["ForestSoil", "FertileLand"]
    
    上述配置表示,植物只会在 "ForestSoil" 或 "FertileLand" 瓦片上生成。如果此列表为空或未指定,则不进行基础瓦片检查。
柏林噪声配置 (scale, threshold, offsetX, offsetY)
  • 说明:这些参数用于控制柏林噪声的生成和应用,从而影响植物的分布。
    • scale:控制噪声的“频率”或“粒度”。
      • 值越大 (例如 0.5-1.0):柏林噪声图案变化迅速,导致生成的植物群落更小、更分散、更“点状”。适合生成稀疏分布的小草丛或零星的野花。
      • 值越小 (例如 0.01-0.1):柏林噪声图案变化平缓,导致生成的植物群落更大、更连贯。适合生成大片森林或草地。
    • threshold:柏林噪声的阈值(-1到1)。只有当柏林噪声值高于此阈值时,该位置才被认为是适合生成植物的区域。
      • 值越高 (接近1):只有噪声值非常高的“峰值”区域才能生成植物,导致植物非常稀疏,只出现在少数高点。
      • 值越低 (接近-1):几乎所有区域的噪声值都可能高于阈值,导致植物覆盖范围更广。
    • offsetX, offsetY:用于在地图上“移动”柏林噪声图案的起始点。每次生成地图或在不同区域生成植物时,改变这些值可以获得不同的随机分布模式,避免重复。
  • 总而言之scale 决定了植物群落的大小和连续性,threshold 决定了植物群落的密集程度和覆盖范围。density 在满足柏林噪声条件后,再次引入一个随机性层,进一步稀释植物的实际生成数量。
  • 示例
    "scale":0.1,
    "threshold":0.4,
    "offsetX":500.0,
    "offsetY":300.0
    

实体生成器事件工作类 (Event_EntityGenerater)

功能说明

Event_EntityGenerater 是一个功能强大的事件工作类,它用于在游戏世界中生成各种类型的实体(如角色、怪物、建筑、物品等)。此事件配置高度灵活,允许您指定要生成的实体数量、哪些实体定义可供选择(将从中随机选取),以及实体生成的具体位置类型和相关参数。它支持在地图内外、特定坐标周围、目标实体周围或随机位置生成实体,为游戏事件、环境填充和动态内容生成提供了核心支持。

该事件工作类通过 EventDef 中的 workClass 字段引用,其具体的行为由 parameter 字段中提供的 JSON 配置来控制。

可用参数

Event_EntityGenerater 通过解析 EventDefparameter 字段里的 JSON 配置来工作。此 JSON 配置对应 EntityGenerateConfig 数据结构。

EntityGenerateConfig 字段列表
JSON参数名XML参数名 (N/A)类型默认值说明
DefinitionsToChooseFromN/AList<EntityDefinitionEntry>必需。一个列表,包含可供随机选择生成的实体定义条目。每个条目都指定一个实体 defName 和其 DefType
CountN/A整数1可选。要生成的实体总数。每次调用 Run 时,系统将尝试生成该数量的实体。
LocationTypeN/AEntitySpawnLocationTypeNone可选。指定实体生成的位置类型。请参见下方的 EntitySpawnLocationType 枚举说明。
CenterCoordinatesN/AVector3(0,0,0)可选。仅当 LocationTypeAroundSpecificCoordinates 时生效。指定生成区域的中心坐标。
RadiusN/A浮点数10.0f可选。仅当 LocationTypeAroundSpecificCoordinatesAroundTargetEntity 时生效。指定以中心点或目标实体为圆心的生成半径。
BuildingTypeDefNameN/A字符串null可选。仅当 LocationTypeInsideSpecificBuildingType 时生效。指定目标建筑的建筑定义 (BuildingDef) defName。当前未实现。
TargetFactionDefNameN/A字符串null可选。仅当 LocationTypeAroundTargetEntity 时生效。指定目标派系的派系定义 (FactionDef) defName。系统将会在该派系的随机一个实体周围生成。
SpawnPointTileMapDefNameN/A字符串null可选。仅当 LocationTypeAtPredefinedSpawnPoint 时生效。指定预定义生成点的 defName。当前未实现。
OffMapOffsetN/A浮点数5.0f可选。仅当 LocationTypeOffMap 时生效。指定实体应在地图边界之外的额外偏移量。
EntityDefinitionEntry 内部字段列表 (在 DefinitionsToChooseFrom 列表中使用)
JSON参数名XML参数名 (N/A)类型默认值说明
DefNameN/A字符串必需。要生成的具体实体定义的 defName
DefTypeN/AEntityDefTypeIdentifierNone必需。此 DefName 对应的实体定义类型。请参见下方的 EntityDefTypeIdentifier 枚举说明。

EntitySpawnLocationType (枚举)

指定实体生成的可能位置类型。

  • None (0): 未指定或无效的生成位置类型。
  • OffMap: 在地图的可玩区域边界之外按随机方向生成实体。
  • InsideSpecificBuildingType: 在指定类型建筑的内部或附近生成实体。当前未实现。
  • AroundSpecificCoordinates: 在指定 CenterCoordinates 周围 Radius 范围内生成实体。
  • AroundTargetEntity: 在指定 TargetFactionDefName 派系中的一个随机实体周围 Radius 范围内生成实体。
  • RandomlyOnMap: 在地图上的随机可生成点生成实体。
  • AtPredefinedSpawnPoint: 在预定义的生成点(通过 SpawnPointTileMapDefName 指定)生成实体。当前未实现。

EntityDefTypeIdentifier (枚举)

指定支持的实体定义类型标识符,用于 EntityDefinitionEntry 中。

  • None (0): 未指定或无效的实体定义类型。
  • CharacterDef: 角色定义类型 (例如:NPC、玩家)。
  • MonsterDef: 怪物定义类型 (例如:敌人、野兽)。
  • BuildingDef: 建筑定义类型 (例如:墙壁、工作台)。
  • BulletDef: 子弹定义类型 (例如:投射物)。
  • ItemDef: 物品定义类型 (用于可拾取物,例如:材料、普通工具)。
  • WeaponDef: 武器定义类型 (继承自 ItemDef 的特殊物品,例如:刀剑、弓箭)。

示例

以下是 EventDef 的示例,展示了 Event_EntityGenerater 的不同用法:

<Define>
    <!-- 假设已有 Character_Villager, Monster_Wolf, Item_GoldBar 等 [实体定义](DefineTypes.md) -->

    <!-- 示例1: 在地图外生成3只狼 -->
    <EventDef>
        <defName>SpawnWolvesOffMap</defName>
        <label>在地图外生成狼</label>
        <description>在地图边界外生成3只野狼。</description>
        <workClass>Event_EntityGenerater</workClass>
        <parameter>
        {
            "DefinitionsToChooseFrom": [
                {"DefName": "Monster_Wolf", "DefType": "MonsterDef"}
            ],
            "Count": 3,
            "LocationType": "OffMap",
            "OffMapOffset": 8.0
        }
        </parameter>
    </EventDef>

    <!-- 示例2: 在特定坐标附近生成单个村民 -->
    <EventDef>
        <defName>SpawnVillagerAtCamp</defName>
        <label>在营地生成村民</label>
        <description>在指定营地坐标附近生成一个村民。</description>
        <workClass>Event_EntityGenerater</workClass>
        <parameter>
        {
            "DefinitionsToChooseFrom": [
                {"DefName": "Character_Villager", "DefType": "CharacterDef"}
            ],
            "Count": 1,
            "LocationType": "AroundSpecificCoordinates",
            "CenterCoordinates": {"x": 50.0, "y": 30.0, "z": 0.0},
            "Radius": 5.0
        }
        </parameter>
    </EventDef>

    <!-- 示例3: 在玩家派系实体周围生成2个金条 (随机选择) -->
    <EventDef>
        <defName>PlayerFactionGoldDrop</defName>
        <label>玩家派系金条掉落</label>
        <description>在玩家派系中的一个随机实体周围生成2个金条。</description>
        <workClass>Event_EntityGenerater</workClass>
        <parameter>
        {
            "DefinitionsToChooseFrom": [
                {"DefName": "Item_GoldBar", "DefType": "ItemDef"}
            ],
            "Count": 2,
            "LocationType": "AroundTargetEntity",
            "TargetFactionDefName": "Faction_Player",
            "Radius": 3.0
        }
        </parameter>
    </EventDef>

    <!-- 示例4: 在地图上随机位置生成一棵树 (建筑) -->
    <EventDef>
        <defName>SpawnRandomTree</defName>
        <label>随机生成树</label>
        <description>在地图上的随机位置生成一棵树。</description>
        <workClass>Event_EntityGenerater</workClass>
        <parameter>
        {
            "DefinitionsToChooseFrom": [
                {"DefName": "Building_Tree", "DefType": "BuildingDef"}
            ],
            "Count": 1,
            "LocationType": "RandomlyOnMap"
        }
        </parameter>
    </EventDef>

    <!-- 示例5: 混合生成:3个敌人或2个宝箱,在地图任意位置随机生成 -->
    <EventDef>
        <defName>MixedRandomGeneration</defName>
        <label>混合随机生成</label>
        <description>在地图随机位置生成3个怪物(可能狼或熊)或2个宝箱。</description>
        <workClass>Event_EntityGenerater</workClass>
        <parameter>
        {
            "DefinitionsToChooseFrom": [
                {"DefName": "Monster_Wolf", "DefType": "MonsterDef"},
                {"DefName": "Monster_Bear", "DefType": "MonsterDef"},
                {"DefName": "Item_TreasureChest", "DefType": "ItemDef"}
            ],
            "Count": 3,
            "LocationType": "RandomlyOnMap"
        }
        </parameter>
    </EventDef>
</Define>

复杂参数说明

parameter 字段 (JSON配置)
  • 说明EventDef 中的 parameter 字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了 EntityGenerateConfig 的所有配置参数,用于指导 Event_EntityGenerater 的具体行为。您需要确保提供的JSON字符串是语法正确的,并且其内容符合 EntityGenerateConfig 的结构。
  • JSON属性与C#映射关系
    • 所有JSON属性名(如 DefinitionsToChooseFrom, Count 等)与C#内部数据类 EntityGenerateConfig 中的对应属性名一致(JSON通常使用驼峰式命名)。
  • Vector3 的JSON表示: 在JSON中,Vector3 类型的字段需要以一个包含 x, y, z 三个浮点数字段的JSON对象形式表示。
    • 例如:"CenterCoordinates": { "x": 50.0, "y": 30.0, "z": 0.0 }
  • 枚举值的JSON表示: 在JSON中,所有枚举类型(如 LocationType, DefType)都应以其字符串名称来表示。
    • 例如:"LocationType": "OffMap"
    • 例如:"DefType": "MonsterDef"
DefinitionsToChooseFrom 字段 (实体定义列表 - 必填)
  • 说明:这是一个必需的列表,其中包含一个或多个 EntityDefinitionEntry 对象。每次生成实体时,Event_EntityGenerater 会从这个列表中随机选择一个实体定义来生成。
  • EntityDefinitionEntry 结构:每个对象都需要包含:
    • "DefName" (字符串):具体的实体定义名称(例如 "Monster_Wolf"),此名称必须在 实体定义 (Define) 中能够找到对应条目。
    • "DefType" (EntityDefTypeIdentifier 枚举):此 DefName 所属的实体定义类型(例如 "MonsterDef")。这是为了帮助系统正确查找并实例化对应的定义。
LocationType 字段 (生成位置类型 - 关键)
  • 说明:这个字段是实体生成位置逻辑的核心。根据您选择的 LocationType,其他相关的定位参数(如 CenterCoordinates, Radius, TargetFactionDefName 等)才会生效。请仔细查阅上述 EntitySpawnLocationType 枚举的说明,并根据您的需求选择合适的位置类型。
  • 当前未实现的类型:请注意 InsideSpecificBuildingTypeAtPredefinedSpawnPoint 当前未实现,如果使用这些类型,事件将无法正常生成实体并返回错误。

打开UI界面事件工作类 (Event_OpenUI)

功能说明

Event_OpenUI 是一个事件工作类,它的主要功能是根据给定的名称打开一个用户界面(UI)。这使得您可以在游戏中的特定事件发生时,弹出预设的UI面板,例如:完成任务后打开奖励界面、点击NPC时显示对话框、或者触发特定条件时打开商店或背包界面。

该事件工作类通过 EventDef 中的 workClass 字段引用,其具体的行为由 parameter 字段中提供的 JSON 配置来控制。

可用参数

Event_OpenUI 通过解析 EventDefparameter 字段里的 JSON 配置来工作。此 JSON 配置对应一个内部的数据结构。

JSON参数名XML参数名 (N/A)类型默认值说明
uiNameN/A字符串必需。要打开的UI界面的内部名称。此名称应与游戏UI系统注册的某个界面名称精确匹配。

示例

以下是一个 EventDef 示例,展示了如何使用 Event_OpenUI 在事件触发时打开一个名为“PlayerInventoryUI”的玩家背包界面:

<Define>
    <EventDef>
        <defName>OpenPlayerInventoryEvent</defName>
        <label>打开玩家背包</label>
        <description>触发时打开玩家的背包界面。</description>
        <workClass>Event_OpenUI</workClass>
        <parameter>
        {
            "uiName": "PlayerInventoryUI" // 指定要打开的UI名称
        }
        </parameter>
    </EventDef>

    <EventDef>
        <defName>OpenSettingsPanelEvent</defName>
        <label>打开设置面板</label>
        <description>触发时打开游戏的设置面板。</description>
        <workClass>Event_OpenUI</workClass>
        <parameter>
        {
            "uiName": "SettingsPanel" // 指定要打开的UI名称
        }
        </parameter>
    </EventDef>
</Define>

复杂参数说明

parameter 字段 (JSON配置)
  • 说明EventDef 中的 parameter 字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了 Event_OpenUI 的所有配置参数,用于指导其具体行为。您需要确保提供的JSON字符串是语法正确的。
  • JSON属性与C#映射关系
    • 所有JSON属性名(如 uiName)与C#内部数据类中的对应属性名一致(JSON通常使用驼峰式命名)。
  • 示例:请参考上方的 EventDef 示例中 parameter 标签内的内容。
uiName 字段 (UI界面名称)
  • 说明:此字段是一个字符串,其值必须与游戏UI系统中实际注册的UI界面的唯一标识符(名称)精确匹配。如果提供了不正确的名称,系统将无法找到并打开对应的界面。
  • 命名约定uiName 的具体命名约定取决于游戏UI框架的实现。通常建议使用清晰、一致的名称,例如 MainMenuUIQuestLogPanelShopWindow 等。
  • 示例
    "uiName": "GameHelpDialog"
    

播放音频事件工作类 (Event_PlayAudio)

功能说明

Event_PlayAudio 是一个事件工作类,用于在游戏中的特定时刻播放音频片段。它提供了丰富的配置选项,允许您精确控制音频的播放方式,包括音量、是否循环、空间混合(2D或3D音效)、播放延迟,以及是否将音效关联到触发事件的实体上,或在播放结束后自动销毁。这使得您可以为各种游戏事件(如用户界面交互、技能施放、环境音效、背景音乐片段等)添加动态的听觉反馈。

该事件工作类通过 EventDef 中的 workClass 字段引用,其具体的行为由 parameter 字段中提供的 JSON 配置来控制。

可用参数

Event_PlayAudio 通过解析 EventDefparameter 字段里的 JSON 配置来工作。此 JSON 配置对应 AudioEventConfig

JSON参数名XML参数名 (N/A)类型默认值说明
audioClipNameN/A字符串必需。要播放的音频资源或 音频定义 (AudioDef)defName。系统将通过此名称获取实际的音频数据。
volumeN/A浮点数1.0播放音量(0.0到1.0之间)。1.0 为最大音量。
loopN/A布尔值false如果为 true,音频将循环播放直到被其他逻辑停止。
spatialBlendN/A浮点数0.0空间混合因子(0.0到1.0之间)。0.0 为完全2D音效(不受听者位置影响),1.0 为完全3D音效(受听者位置和距离影响)。
attachToInitiatorN/A布尔值true如果存在触发此事件的实体(发起者),当此项为 true 时,音频播放器会尝试附加到该发起者上,使其成为一个3D音源(即使 spatialBlend0.0,也依然会跟随发起者移动而移动)。
delayN/A浮点数0.0播放前的延迟秒数。
destroyAfterPlayN/A布尔值true如果是非循环播放的音效,并且系统临时创建了一个音频源来播放它,当此项为 true 时,会在播放结束后自动销毁这个临时的音频源以节省资源。

示例

以下是 EventDef 的示例,展示了 Event_PlayAudio 的不同用法:

<Define>
    <!-- 假设已有 Sound_ButtonClick 和 Sound_AmbientWind 等 [音频定义 (AudioDef)](AudioDef.md) -->

    <EventDef>
        <defName>PlayButtonClickSound</defName>
        <label>播放按钮点击音效</label>
        <description>在UI点击时播放短促的按钮点击音效。</description>
        <workClass>Event_PlayAudio</workClass>
        <parameter>
        {
            "audioClipName": "Sound_ButtonClick", // 要播放的音频定义名
            "volume": 0.8,                        // 音量为0.8
            "loop": false,                        // 不循环
            "spatialBlend": 0.0,                  // 2D音效
            "attachToInitiator": false            // UI音效通常不依附于发起者
        }
        </parameter>
    </EventDef>

    <EventDef>
        <defName>PlayAmbientWindSound</defName>
        <label>播放环境风声</label>
        <description>在地图特定区域播放循环环境风声。</description>
        <workClass>Event_PlayAudio</workClass>
        <parameter>
        {
            "audioClipName": "Sound_AmbientWind", // 播放环境风声
            "volume": 0.5,                        // 音量为0.5
            "loop": true,                         // 循环播放
            "spatialBlend": 1.0,                  // 3D音效,受位置影响
            "attachToInitiator": true             // 依附于事件发起者(例如一个风源实体)
        }
        </parameter>
    </EventDef>

    <EventDef>
        <defName>PlayDelayedWarningSound</defName>
        <label>播放延迟警告音效</label>
        <description>在5秒延迟后播放一个警告音效。</description>
        <workClass>Event_PlayAudio</workClass>
        <parameter>
        {
            "audioClipName": "Sound_Warning",
            "volume": 1.0,
            "delay": 5.0,                         // 延迟5秒播放
            "destroyAfterPlay": true              // 播放完成后自动销毁
        }
        </parameter>
    </EventDef>
</Define>

复杂参数说明

parameter 字段 (JSON配置)
  • 说明EventDef 中的 parameter 字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了 AudioEventConfig 的所有配置参数,用于指导 Event_PlayAudio 的具体行为。您需要确保提供的JSON字符串是语法正确的。
  • JSON属性与C#映射关系
    • 所有JSON属性名(如 audioClipName, volume 等)与C#内部数据类中的对应属性名一致(JSON通常使用驼峰式命名)。
  • 示例:请参考上方的 EventDef 示例中 parameter 标签内的内容。
volumespatialBlend 字段 (浮点数范围)
  • 说明:这两个字段都接受浮点数,但其值应限制在特定的有效范围内。
    • volume:值应介于 0.0(静音)到 1.0(最大音量)之间。超出此范围的值可能会被截断或导致非预期行为。
    • spatialBlend:值应介于 0.0(完全2D)到 1.0(完全3D)之间。
  • 示例
    "volume": 0.75,         // 75%音量
    "spatialBlend": 0.5     // 混合音效,2D与3D各一半
    
loop, attachToInitiator, destroyAfterPlay 字段 (布尔值开关)
  • 说明:这些字段是布尔值开关,接受 truefalse
    • loop:控制音频是否重复播放。
    • attachToInitiator:当一个实体触发事件时,这个选项决定了音频源是否附加到该实体上。这常用于使音效跟随实体移动,或使3D音效从实体位置发出。
    • destroyAfterPlay:主要用于非循环音效。如果为 true,系统在播放完毕后会自动清理临时创建的音频源。如果为 false,则需要其他逻辑手动清理,否则可能造成资源泄露。
  • 示例
    "loop": true,
    "attachToInitiator": true,
    "destroyAfterPlay": false
    

物品生成事件工作类 (Event_ItemGenerater)

功能说明

Event_ItemGenerater 是一个用于在游戏世界中生成物品的事件工作类。它允许您指定要生成的物品类型及其精确的生成位置。这对于实现诸如掉落物品、奖励物品、场景互动生成物品等功能非常有用。

该事件工作类通过 EventDef 中的 workClass 字段引用,其具体的行为由 parameter 字段中提供的 JSON 配置来控制。

可用参数

Event_ItemGenerater 通过解析 EventDefparameter 字段里的 JSON 配置来工作。此 JSON 配置对应 ItemSpawnData 数据结构。

ItemSpawnData 字段列表
JSON参数名XML参数名 (N/A)类型默认值说明
itemDefNameN/A字符串必需。要生成的物品的定义名称 (ItemDefdefName)。例如:"IRON_SWORD"。
positionN/AVector3null可选。物品生成的绝对世界坐标。如果提供了此字段,将优先使用此位置。
relativeOffsetN/AVector3null可选。物品相对于事件触发者 (initiator) 的偏移坐标。仅当 initiator 存在且 position 未设置时生效。

示例

以下是 EventDef 的示例,展示了 Event_ItemGenerater 的不同用法:

<Define>
    <!-- 假设已有 ItemDef: WoodenSword, HealthPotion -->

    <!-- 示例1: 在玩家击败怪物后掉落一个木剑 (相对坐标) -->
    <EventDef>
        <defName>DropWoodenSwordOnDefeat</defName>
        <label>掉落木剑</label>
        <description>在怪物死亡位置附近掉落一把木剑。</description>
        <workClass>Event_ItemGenerater</workClass>
        <parameter>
        {
            "itemDefName": "WoodenSword",
            "relativeOffset": {"x": 0.5, "y": 0.0, "z": 0.0}
        }
        </parameter>
    </EventDef>

    <!-- 示例2: 在地图的固定坐标生成一个生命药水 -->
    <EventDef>
        <defName>SpawnHealthPotionAtLocation</defName>
        <label>生成生命药水</label>
        <description>在地图的特定区域生成一个生命药水。</description>
        <workClass>Event_ItemGenerater</workClass>
        <parameter>
        {
            "itemDefName": "HealthPotion",
            "position": {"x": 10.0, "y": 5.0, "z": 0.0}
        }
        </parameter>
    </EventDef>

    <!-- 示例3: 在没有任何指定位置的情况下,直接在触发者实体上生成一个物品 (使用触发者位置) -->
    <EventDef>
        <defName>SpawnKeyOnInitiator</defName>
        <label>生成钥匙</label>
        <description>在触发表格的实体所在位置生成一把钥匙。</description>
        <workClass>Event_ItemGenerater</workClass>
        <parameter>
        {
            "itemDefName": "Key_Dungeon"
        }
        </parameter>
    </EventDef>

</Define>

复杂参数说明

parameter 字段 (JSON配置)
  • 说明EventDef 中的 parameter 字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了 ItemSpawnData 的所有配置参数,用于指导 Event_ItemGenerater 的具体行为。您需要确保提供的JSON字符串是语法正确的,并且其内容符合 ItemSpawnData 的结构。
  • JSON属性与C#映射关系
    • 所有JSON属性名(如 itemDefName, position 等)与C#内部数据类 ItemSpawnData 中的对应属性名一致(JSON通常使用驼峰式命名)。
位置 (position, relativeOffset) 逻辑

物品的生成位置遵循以下优先级和逻辑:

  1. 绝对位置 (position):如果 position 字段被设定,则物品将精确地生成在该世界坐标。这是定位的最高优先级。
  2. 相对偏移 (relativeOffset):如果 position 未设置,但 relativeOffset 字段被设定,并且事件有一个 initiator (触发者实体),则物品将生成在 initiator 的位置加上 relativeOffset
  3. 触发者位置:如果 positionrelativeOffset 都未设置,但事件有一个 initiator,则物品将生成在 initiator 的当前位置。
  4. 错误处理:如果上述所有条件均不满足(即未提供 position,没有 relativeOffset 或没有 initiator),则物品生成会失败并抛出异常,因为系统无法确定一个有效的生成位置。
Vector3 的JSON表示
  • 在JSON中,Vector3 类型的字段(如 positionrelativeOffset)需要以一个包含 x, y, z 三个浮点数字段的JSON对象形式表示。
  • 例如:"position": { "x": 10.0, "y": 5.0, "z": 0.0 }

消息显示事件工作类 (Event_MessageWorkClass)

功能说明

Event_MessageWorkClass 是一个用于在游戏界面上显示文本消息的事件工作类。它提供灵活的配置选项,允许您定义消息的内容、显示类别(决定其在UI上的呈现方式)、文本颜色以及持续显示的时长。这使得开发者能够通过游戏事件轻松地向玩家传达提示、警告、剧情信息或任何其他文本内容。

该事件工作类通过 EventDef 中的 workClass 字段引用,其具体的行为由 parameter 字段中提供的 JSON 配置来控制。

可用参数

Event_MessageWorkClass 通过解析 EventDefparameter 字段里的 JSON 配置来工作。此 JSON 配置对应 MessageData

JSON参数名XML参数名 (N/A)类型默认值说明
messageN/A字符串必需。要显示的消息文本内容。
typeN/APromptDisplayCategory必需。消息的显示类别,决定了消息在UI中的呈现方式。请参见下方的 PromptDisplayCategory 枚举说明。
colorN/A字符串null可选。消息文本的颜色。必须是一个有效的HTML颜色字符串格式(例如 "#RRGGBB""#RRGGBBAA")。如果省略,将使用系统默认颜色。
showTimeN/A浮点数null可选。消息在屏幕上显示的持续时长(秒)。如果省略,将使用 DisplayMessage API 的默认时长(通常为3秒)。

PromptDisplayCategory (枚举)

PromptDisplayCategory 枚举定义了消息的不同显示类别,这将影响消息在游戏界面上的具体呈现方式(例如位置、大小、动画等)。

  • 请查阅具体游戏UI系统文档以获取 PromptDisplayCategory 的详细枚举值及其对应的显示效果。
    • 示例可能的枚举值(实际请以游戏代码为准):
      • SystemMessage: 系统通知,通常位于屏幕中央或顶部。
      • Warning: 警告信息,可能以黄色或红色高亮显示。
      • QuestUpdate: 任务更新提示。
      • Dialogue: 对话或剧情文本。
      • FloatingText: 浮动在实体上方的文本,如伤害数字。

示例

以下是 EventDef 的示例,展示了 Event_MessageWorkClass 的不同用法:

<Define>
    <!-- 假设 PromptDisplayCategory 枚举类型包含 SystemMessage, Warning, QuestUpdate 值 -->

    <!-- 示例1: 显示一个普通的系统消息 -->
    <EventDef>
        <defName>ShowSystemWelcomeMessage</defName>
        <label>显示欢迎消息</label>
        <description>在游戏开始时显示一条欢迎系统消息。</description>
        <workClass>Event_MessageWorkClass</workClass>
        <parameter>
        {
            "message": "欢迎来到奇幻世界!",
            "type": "SystemMessage"
        }
        </parameter>
    </EventDef>

    <!-- 示例2: 显示一个红色的警告消息,持续5秒 -->
    <EventDef>
        <defName>ShowCriticalWarning</defName>
        <label>显示严重警告</label>
        <description>在发生严重错误时显示红色警告。</description>
        <workClass>Event_MessageWorkClass</workClass>
        <parameter>
        {
            "message": "危险!敌人正在逼近!",
            "type": "Warning",
            "color": "#FF0000",
            "showTime": 5.0
        }
        </parameter>
    </EventDef>

    <!-- 示例3: 显示一个绿色的任务更新消息 -->
    <EventDef>
        <defName>ShowQuestCompleted</defName>
        <label>显示任务完成提示</label>
        <description>任务完成后显示绿色提示。</description>
        <workClass>Event_MessageWorkClass</workClass>
        <parameter>
        {
            "message": "主线任务:探索之始 完成!",
            "type": "QuestUpdate",
            "color": "#00FF00"
        }
        </parameter>
    </EventDef>
</Define>

复杂参数说明

parameter 字段 (JSON配置)
  • 说明EventDef 中的 parameter 字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了 MessageData 的所有配置参数,用于指导 Event_MessageWorkClass 的具体行为。您需要确保提供的JSON字符串是语法正确的,并且其内容符合 MessageData 的结构。
  • JSON属性与C#映射关系
    • 所有JSON属性名(如 message, type 等)与C#内部数据类 MessageData 中的对应属性名一致(JSON通常使用驼峰式命名)。
  • 枚举值的JSON表示: 在JSON中,枚举类型 PromptDisplayCategory 的值应以其字符串名称来表示。
    • 例如:"type": "SystemMessage"
color 字段 (HTML颜色字符串)
  • 说明:如果需要为消息文本指定颜色,可以使用 color 字段。这个字段的值必须是有效的HTML颜色字符串
    • 支持的格式
      • "#RRGGBB":六位十六进制RGB值,例如 "#FF0000" (红色)。
      • "#RRGGBBAA":八位十六进制RGBA值(包含透明度),例如 "#00FF0080" (半透明绿色)。
    • 注意事项:如果您提供的颜色字符串格式不正确,Event_MessageWorkClass 在初始化时会报错,导致事件无法运行。

临时动画事件工作类 (Event_TemporaryAnimationWorkClass)

功能说明

Event_TemporaryAnimationWorkClass 是一个功能强大的事件工作类,用于在游戏世界或UI界面上播放各种临时动画效果。它支持多种动画内容类型(文本、精灵序列和DrawNode定义),并提供了灵活的配置选项,允许您精确控制动画的位置、生命周期、帧率以及是否将其附加到触发事件的实体上。这使得开发者能够通过事件系统轻松地实现诸如飘字、特效、物品拾取提示、短暂的视觉反馈等效果。

该事件工作类通过 EventDef 中的 workClass 字段引用,其具体的行为由 parameter 字段中提供的 JSON 配置来控制。

可用参数

Event_TemporaryAnimationWorkClass 通过解析 EventDefparameter 字段里的 JSON 配置来工作。此 JSON 配置对应 TemporaryAnimationData 数据结构。

TemporaryAnimationData 字段列表
JSON参数名XML参数名 (N/A)类型默认值说明
contentTypeN/AAnimationContentType必需。动画内容的类型。决定了使用 textContentspriteNamesdrawNodeDefName 字段。请参见下方的 AnimationContentType 枚举说明。
isUIAnimationN/A布尔false可选。指示动画是否作为UI元素显示在Canvas上。如果为 true,动画将适配屏幕坐标。
textContentN/A字符串null可选。当 contentTypeText 时使用。动画的文本内容。
spriteNamesN/A字符串数组 (string[])null可选。当 contentTypeSprite 时使用。组成动画的精灵资源名称数组,将按顺序播放以形成帧动画。
drawNodeDefNameN/A字符串null可选。当 contentTypeDrawNode 时使用。DrawNode定义 (DrawNodeDef)defName,用于渲染复杂图像或粒子效果。
positionN/AVector3null可选。动画的绝对世界初始位置。如果设置,将优先使用此位置。
relativeOffsetN/AVector3null可选。动画相对于事件触发者 (initiator) 的偏移坐标。仅在 initiator 存在且 position 未设置时生效。
parentToInitiatorN/A布尔false可选。指示动画是否应设置为事件触发者 (initiator) 的子对象。如果触发者不存在,此设置无效。
lifeTimeN/A浮点数3.0f可选。动画的生命周期(秒)。动画将在此时间后自动销毁。如果省略,默认为3秒。
fpsN/A浮点数3.0f可选。精灵动画或DrawNode动画的帧率(每秒更新次数)。如果省略,默认为3帧/秒。文本动画通常不使用此参数。
AnimationContentType (枚举)

定义临时动画的内容类型,这会影响您需要提供哪些具体内容字段。

  • Text: 动画内容为文本字符串。此时需要提供 textContent 字段。
  • Sprite: 动画内容为一系列精灵,用于播放帧动画。此时需要提供 spriteNames 字段。
  • DrawNode: 动画内容为DrawNodeDef定义,用于更复杂的图像或粒子效果。此时需要提供 drawNodeDefName 字段。

示例

以下是 EventDef 的示例,展示了 Event_TemporaryAnimationWorkClass 的不同用法:

<Define>
    <!-- 假设已有DrawNode_ExplosionEffect, Sprite_Coin1, Sprite_Coin2, Sprite_Coin3 等资源 -->

    <!-- 示例1: 在怪物死亡位置生成一个“命中”文本动画 (相对于触发者) -->
    <EventDef>
        <defName>SpawnHitTextOnDeath</defName>
        <label>显示命中文本</label>
        <description>在怪物死亡时显示“命中”文本。</description>
        <workClass>Event_TemporaryAnimationWorkClass</workClass>
        <parameter>
        {
            "contentType": "Text",
            "textContent": "命中!",
            "relativeOffset": {"x": 0.5, "y": 1.0, "z": 0.0},
            "lifeTime": 1.5,
            "isUIAnimation": false
        }
        </parameter>
    </EventDef>

    <!-- 示例2: 在特定坐标播放一个金币收集的UI动画 (精灵序列) -->
    <EventDef>
        <defName>SpawnCoinCollectAnimation</defName>
        <label>金币收集动画</label>
        <description>在屏幕固定位置播放金币收集UI动画。</description>
        <workClass>Event_TemporaryAnimationWorkClass</workClass>
        <parameter>
        {
            "contentType": "Sprite",
            "isUIAnimation": true,
            "spriteNames": ["Sprite_Coin1", "Sprite_Coin2", "Sprite_Coin3"],
            "position": {"x": 100.0, "y": 200.0, "z": 0.0},
            "lifeTime": 1.0,
            "fps": 10.0
        }
        </parameter>
    </EventDef>

    <!-- 示例3: 在敌人身上播放爆炸DrawNode动画,并将其设为敌人子对象 -->
    <EventDef>
        <defName>SpawnExplosionEffect</defName>
        <label>爆炸特效</label>
        <description>在敌人头上播放爆炸DrawNode动画。</description>
        <workClass>Event_TemporaryAnimationWorkClass</workClass>
        <parameter>
        {
            "contentType": "DrawNode",
            "drawNodeDefName": "DrawNode_ExplosionEffect",
            "relativeOffset": {"x": 0.0, "y": 0.5, "z": 0.0},
            "parentToInitiator": true,
            "lifeTime": 0.8,
            "fps": 15.0
        }
        </parameter>
    </EventDef>

    <!-- 示例4: 在地图随机位置显示一个“提示”文本,无触发者 -->
    <EventDef>
        <defName>ShowRandomHint</defName>
        <label>随机提示</label>
        <description>在地图随机位置显示一个提示文本。</description>
        <workClass>Event_TemporaryAnimationWorkClass</workClass>
        <parameter>
        {
            "contentType": "Text",
            "textContent": "小心前方!",
            "position": {"x": 20.0, "y": 80.0, "z": 0.0},
            "lifeTime": 2.0
        }
        </parameter>
    </EventDef>
</Define>

复杂参数说明

parameter 字段 (JSON配置)
  • 说明EventDef 中的 parameter 字段是一个特别说明,它不使用标准的XML元素赋值方式,而是直接作为文本内容包含一个JSON格式的字符串。这个JSON字符串包含了 TemporaryAnimationData 的所有配置参数,用于指导 Event_TemporaryAnimationWorkClass 的具体行为。您需要确保提供的JSON字符串是语法正确的,并且其内容符合 TemporaryAnimationData 的结构。
  • JSON属性与C#映射关系
    • 所有JSON属性名(如 contentType, isUIAnimation 等)与C#内部数据类 TemporaryAnimationData 中的对应属性名一致(JSON通常使用驼峰式命名)。
  • Vector3 的JSON表示: 在JSON中,Vector3 类型的字段需要以一个包含 x, y, z 三个浮点数字段的JSON对象形式表示。
    • 例如:"position": { "x": 50.0, "y": 30.0, "z": 0.0 }
  • 字符串数组的JSON表示spriteNames 字段是一个字符串数组,应以JSON数组的形式表示。
    • 例如:"spriteNames": ["Sprite_Frame1", "Sprite_Frame2", "Sprite_Frame3"]
  • 枚举值的JSON表示: 在JSON中,所有枚举类型(如 contentType)都应以其字符串名称来表示。
    • 例如:"contentType": "Sprite"
contentType 字段及其相关内容字段

contentType 字段是动画的核心配置,它决定了动画将显示何种内容。根据您选择的 contentType,以下字段中的且仅其中的一个是必需的,其余字段将被忽略:

  • contentTypeText
    • textContent (字符串):必须提供动画要显示的文本内容。
    • 例如:"contentType": "Text", "textContent": "伤害!"
  • contentTypeSprite
    • spriteNames (字符串数组) :必须提供组成帧动画的单个精灵名称列表。这些名称必须是游戏资源管理系统可识别的有效精灵名称。动画将按列表顺序循环播放这些精灵。
    • 例如:"contentType": "Sprite", "spriteNames": ["FX_Dust1", "FX_Dust2"]
  • contentTypeDrawNode
    • drawNodeDefName (字符串):必须提供 DrawNodeDefdefNameDrawNodeDef 是一种更复杂的图形定义,可以用于创建包含多个图层、动态效果或粒子系统的动画。
    • 例如:"contentType": "DrawNode", "drawNodeDefName": "DrawNode_HealEffect"
位置 (position, relativeOffset) 与父级 (parentToInitiator) 逻辑

动画的生成位置和父级关系遵循以下优先级和逻辑:

  1. 绝对位置 (position):如果 position 字段被设定,则动画将精确地生成在该世界坐标。这是定位的最高优先级。
  2. 相对偏移 (relativeOffset):如果 position 未设置,但 relativeOffset 字段被设定,并且事件有一个 initiator (触发者实体),则动画将生成在 initiator 的位置加上 relativeOffset
  3. 触发者位置:如果 positionrelativeOffset 都未设置,但事件有一个 initiator,则动画将生成在 initiator 的当前位置。
  4. 默认位置:如果上述所有条件均不满足(即未提供 position,没有 relativeOffset 或没有 initiator),动画将默认生成在世界坐标 (0,0,0) 处,并会输出警告日志。
  5. 父级设置 (parentToInitiator):如果 parentToInitiator 设置为 true 并且事件有一个 initiator,则生成的动画对象将会被设置为 initiator 的子对象,这意味着动画会随 initiator 移动。如果 initiator 不存在,即使设置为 true,动画也不会有父级,并会输出警告。

AI行为树叶节点:攻击目标 (JobNode_AttackTarget)

功能说明

JobNode_AttackTarget 是一个 AI 行为树的叶节点,它指示执行该行为树的实体 (SelfEntity) 寻找到其视野范围内最近的一个敌对目标,并对其发起一次攻击。如果未能找到有效的敌对目标,或者在攻击前目标失效(例如已死亡),则该节点会返回失败。此节点通常用于定义需要主动攻击敌人的行为逻辑链中。

该节点无需任何自定义参数,其行为完全基于 SelfEntity 的当前状态、其与环境中其他实体的关系以及攻击能力。

可用参数

无需配置参数。JobNode_AttackTarget 节点无需任何额外配置即可工作。它的逻辑是自动寻找并攻击 SelfEntity (当前执行行为树的实体)最近的敌对目标。

行为树节点状态 (Status) 返回值

JobNode_AttackTarget 节点执行完毕后,会返回以下状态:

  • 成功 (Success)
    • 成功在当前区域找到一个有效的敌对实体。
    • SelfEntity 成功地对该敌对实体发起了一次攻击尝试。
  • 失败 (Failure)
    • 在当前维度中未找到任何有效的敌对实体。
    • 找到了敌对实体,但在尝试攻击前该实体变得无效(例如,它已死亡或离开区域)。
    • SelfEntity 由于其他原因无法发起攻击(例如,攻击冷却中、没有武器或攻击能力等)。

示例

以下是一个 BehaviorTreeDef 的示例,展示了 JobNode_AttackTarget 如何在一个基本的怪物行为中被使用:

<Define>
    <BehaviorTreeDef>
        <defName>BasicMonsterBehavior</defName>
        <label>基础怪物行为</label>
        <description>怪物寻路并攻击最近的敌人,或者徘徊和空闲。</description>
        <!-- 根节点下的行为逻辑 -->
      
        <!-- 条件分支:如果怪物有武器,则尝试攻击 -->
        <Node className="ThinkNode_Conditional" value="HasWeapon()">
            <!-- 序列节点:先移动到攻击范围,再执行攻击 -->
            <childTree>
                <li>
                    <className>ThinkNode_Sequence</className>
                    <childTree>
                        <li>
                            <!-- 移动到攻击范围,如果距离太远就移动,否则直接成功 -->
                            <className>JobNode_MoveToAttackRange</className>
                        </li>
                        <li>
                            <!-- 攻击最近的敌对目标 -->
                            <className>JobNode_AttackTarget</className> 
                        </li>
                    </childTree>
                </li>
            </childTree>
        </Node>

        <!-- 默认行为:如果上述攻击条件不满足,则徘徊和空闲 -->
        <Node className="ThinkNode_Sequence">
            <childTree>
                <li>
                    <!-- 随机徘徊一段时间 -->
                    <className>JobNode_Wander</className>
                </li>
                <li>
                    <!-- 空闲一段时间 -->
                    <className>JobNode_Idle</className>
                </li>
            </childTree>
        </Node>
    </BehaviorTreeDef>
</Define>

在上述示例中,JobNode_AttackTarget 被放置在一个序列节点中。这意味着它只会在 JobNode_MoveToAttackRange 成功执行(即实体已到达攻击范围或无需移动)之后才会尝试执行。整个攻击序列又被包含在一个条件节点 ThinkNode_Conditional 中,确保只有当怪物拥有武器时才会执行攻击行为。

AI行为树叶节点:空闲 (JobNode_Idle)

功能说明

JobNode_Idle 是一个 AI 行为树的叶节点,它指示执行该行为树的实体 (SelfEntity) 进入一段时间的空闲状态。在此期间,实体不会执行任何特定的动作,而是保持“待命”状态,直到预设的空闲时间结束。此节点通常用于填充行为链中需要实体暂停或等待的间隙,例如在完成一个任务后等待下一个指示,或者单纯地在没有其他紧急任务时进行放松。

JobNode_Idle 节点可以通过一个可选的参数来指定空闲的持续时间(以游戏帧为单位)。如果未指定,它将使用基类默认的空闲时间。

可用参数

JobNode_Idle 节点允许通过 BehaviorTreeDefNode 元素的 value 属性来配置其空闲持续时间。

参数名XML参数名 (value 属性)类型默认值说明
TimeoutFramesvalue整数180可选。指定实体将保持空闲状态的帧数。180帧大约对应3秒的游戏时间(假设60帧/秒)。如果未指定此参数,则默认使用基类设定的 180 帧。

行为树节点状态 (Status) 返回值

JobNode_Idle 节点执行完毕后,会返回以下状态:

  • 运行中 (Running)
    • 空闲时间尚未结束。实体将继续保持空闲状态,并在下一个行为树tick时再次执行此节点。
  • 成功 (Success)
    • 预设的空闲时间已全部耗尽。实体已完成空闲任务,可以继续执行行为树中的下一个节点。

示例

以下是一个 BehaviorTreeDef 的示例,展示了 JobNode_Idle 如何在一个怪物行为中被使用:

<Define>
    <BehaviorTreeDef>
        <defName>MonsterPatrolBehavior</defName>
        <label>怪物巡逻行为</label>
        <description>怪物在巡逻和空闲之间切换。</description>
      
        <!-- 序列节点:先移动到巡逻点,然后空闲 -->
        <Node className="ThinkNode_Sequence">
            <childTree>
                <li>
                    <!-- 移动到一个预定义的巡逻点 -->
                    <className>JobNode_MoveToPatrolPoint</className>
                    <!-- 假设此处 JobNode_MoveToPatrolPoint 也有自己的value或子节点配置 -->
                </li>
                <li>
                    <!-- 空闲150帧 (2.5秒) -->
                    <className>JobNode_Idle</className>
                    <value>150</value> 
                </li>
            </childTree>
        </Node>

        <!-- 另外一个序列节点,展示不指定value的Idle -->
        <Node className="ThinkNode_Sequence">
            <childTree>
                <li>
                    <!-- 执行某个任务 -->
                    <className>JobNode_PerformTask</className>
                </li>
                <li>
                    <!-- 空闲默认的180帧 (3秒) -->
                    <className>JobNode_Idle</className> 
                </li>
            </childTree>
        </Node>
    </BehaviorTreeDef>
</Define>

在上述示例中:

  • 第一个 JobNode_Idle 通过 value 属性指定了 150 帧的空闲时间。
  • 第二个 JobNode_Idle 没有指定 value 属性,因此它将使用基类默认的 180 帧空闲时间。

复杂参数说明

value 属性 (空闲帧数)
  • 说明:在 BehaviorTreeDefNode 元素中,JobNode_Idle 节点的 value 属性用于直接指定空闲的帧数。它应该是一个可以被解析为整数的字符串。
  • 用法
    • <className>JobNode_Idle</className><value>300</value>:表示实体将空闲 300 帧(约 5 秒)。
    • <className>JobNode_Idle</className>:表示实体将空闲默认的 180 帧(约 3 秒)。
  • 注意事项value 属性预期接收一个纯数字字符串。如果字符串无法解析为整数,JobNode_Idle 将退回到使用默认的空闲帧数。

AI行为树叶节点:移动到攻击范围 (JobNode_MoveToAttackRange)

功能说明

JobNode_MoveToAttackRange 是一个 AI 行为树的叶节点,它指示执行该行为树的实体 (SelfEntity) 寻找其视野范围内最近的敌对目标,然后计算一个合适的移动位置,使其自身能够进入该敌对目标的攻击距离边缘。此节点的目的是确保 SelfEntity 能够移动到可以成功攻击敌人的位置,而不会过于接近或远离。它还包含路径设置、持续移动管理以及卡住检测的逻辑,以应对复杂的寻路情况。

该节点无需任何自定义参数,其行为完全基于 SelfEntity 的当前状态、其与环境中其他实体的关系、攻击范围 (SelfEntity.AttributesNow.attackRange) 以及寻路能力。

可用参数

无需配置参数。JobNode_MoveToAttackRange 节点无需任何额外配置即可工作。它的逻辑是自动寻找最近的敌对目标,并计算确保 SelfEntity 能够到达其攻击范围内的最佳位置。

行为树节点状态 (Status) 返回值

JobNode_MoveToAttackRange 节点执行完毕后,会返回以下状态:

  • 运行中 (Running)
    • 节点已找到目标并设置了路径,SelfEntity 正在向目标攻击范围移动。
    • SelfEntity 因卡住而被节点检测到,正在重新规划路径。
  • 成功 (Success)
    • SelfEntity 已经成功移动到其最近敌对目标的攻击范围边缘。
  • 失败 (Failure)
    • 在当前维度中未找到任何有效的敌对实体。
    • 找到了敌对实体,但在尝试设置路径或移动过程中该实体变得无效(例如,它已死亡或离开区域)。

示例

以下是一个 BehaviorTreeDef 的示例,展示了 JobNode_MoveToAttackRange 如何在一个基本的怪物行为中与 JobNode_AttackTarget 节点配合使用:

<Define>
    <BehaviorTreeDef>
        <defName>MonsterAggressiveBehavior</defName>
        <label>怪物侵略性行为</label>
        <description>怪物主动移动到攻击范围并攻击。</description>
      
        <!-- 条件分支:如果怪物有武器,则尝试攻击 -->
        <Node className="ThinkNode_Conditional" value="HasWeapon()">
            <childTree>
                <li>
                    <!-- 序列节点:先移动到攻击范围,再执行攻击 -->
                    <className>ThinkNode_Sequence</className>
                    <childTree>
                        <li>
                            <!-- 移动到攻击范围边缘,此节点会持续运行直到成功或失败 -->
                            <className>JobNode_MoveToAttackRange</className>
                        </li>
                        <li>
                            <!-- 成功进入攻击范围后,攻击目标一次 -->
                            <className>JobNode_AttackTarget</className> 
                        </li>
                    </childTree>
                </li>
            </childTree>
        </Node>

        <!-- 如果没有武器,或者攻击行为失败,则执行默认的徘徊空闲行为 -->
        <Node className="ThinkNode_Sequence">
            <childTree>
                <li>
                    <!-- 随机徘徊 -->
                    <className>JobNode_Wander</className>
                </li>
                <li>
                    <!-- 空闲一段时间 -->
                    <className>JobNode_Idle</className>
                </li>
            </childTree>
        </Node>
    </BehaviorTreeDef>
</Define>

在上述示例中,JobNode_MoveToAttackRange 被放置在一个序列节点中,位于 JobNode_AttackTarget 之前。这意味着只有当实体成功移动到攻击范围后,JobNode_AttackTarget 才会被执行。这种组合确保了实体在能够有效攻击敌人之前,会先尝试达到最佳的战斗位置,并且能够智能处理寻路过程中的卡住情况。

AI行为树叶节点:徘徊 (JobNode_Wander)

功能说明

JobNode_Wander 是一个 AI 行为树的叶节点,它指示执行该行为树的实体 (SelfEntity) 在其当前位置附近随机选择一个可达的目标点,并移动到该点。一旦到达目标点,该节点即告成功。此节点也包含了卡住检测机制,如果实体在徘徊过程中长时间未移动,则判定为卡住并返回失败,以便行为树可以尝试其他行为。

此节点常用于实现实体的默认空闲行为,如生物在地图上漫无目的地行走,或NPC在没有特定任务时在区域内巡逻。

可用参数

无需配置参数。JobNode_Wander 节点不接受任何来自XML的额外配置。其所有行为(例如徘徊的最大范围、最小移动距离、寻找目标点的尝试次数、卡住检测的阈值和帧数等)均由节点内部的默认逻辑和常量控制。

行为树节点状态 (Status) 返回值

JobNode_Wander 节点执行完毕后,会返回以下状态:

  • 运行中 (Running)
    • 节点已成功找到一个徘徊目标点,并且 SelfEntity 正在向该目标点移动。
    • SelfEntity 尚未到达目标点,但仍在尝试移动。
  • 成功 (Success)
    • SelfEntity 已经成功到达其当前徘徊的目标点。
  • 失败 (Failure)
    • 在经过多次尝试后,未能找到一个有效且可达的随机徘徊目标点。这通常发生在实体被困在一个无法移动的区域时。
    • SelfEntity 在向目标点移动的过程中被检测到卡住(长时间未移动)。

示例

以下是一个 BehaviorTreeDef 的示例,展示了 JobNode_Wander 如何在一个行为链中被使用:

<Define>
    <BehaviorTreeDef>
        <defName>PassiveAnimalBehavior</defName>
        <label>被动动物行为</label>
        <description>动物在没有威胁时,会随机徘徊并短暂空闲。</description>
      
        <!-- 序列节点:先徘徊,然后空闲 -->
        <Node className="ThinkNode_Sequence">
            <childTree>
                <li>
                    <!-- 随机徘徊到附近一个点 -->
                    <className>JobNode_Wander</className>
                </li>
                <li>
                    <!-- 徘徊结束后,空闲120帧 (约2秒) -->
                    <className>JobNode_Idle</className>
                    <value>120</value> 
                </li>
            </childTree>
        </Node>
    </BehaviorTreeDef>

    <BehaviorTreeDef>
        <defName>MonsterDefaultPatrol</defName>
        <label>怪物默认巡逻</label>
        <description>怪物在没有敌人时,会进行随机巡逻。</description>
      
        <!-- 条件节点:如果没有敌人,则执行巡逻 -->
        <Node className="ThinkNode_Conditional" value="!HasHostileTarget()">
            <childTree>
                <li>
                    <!-- 随机徘徊 -->
                    <className>JobNode_Wander</className>
                </li>
            </childTree>
        </Node>
        <!-- 如果有敌人,则可能执行攻击行为(由其他节点定义) -->
    </BehaviorTreeDef>
</Define>

在上述示例中:

  • 第一个 BehaviorTreeDef 演示了一个被动动物的行为,它会先通过 JobNode_Wander 移动到附近一个点,然后通过 JobNode_Idle 暂停一段预设的时间。
  • 第二个 BehaviorTreeDef 展示了 JobNode_Wander 如何在 ThinkNode_Conditional 内部作为默认的巡逻行为,只有在没有敌对目标时才会触发。

复杂参数说明

由于 JobNode_Wander 节点没有任何可直接通过 XML 配置的参数,因此本节不适用。其内部行为逻辑(如徘徊范围、卡住检测等)均已预设。