STS2 mod pets (advanced notes)

Last updated:

Published on

.tscn layout for NCreatureVisuals, Harmony patch for CreateVisuals, pet positioning and HP bar. Uses generic your-mod paths. Body in Chinese.

本文说明如何在 STS2 模组中创建可召唤的 mod 宠物(Pet),包括场景结构、视觉加载、定位和血条显示。路径与类名均为占位,请替换为你自己的 mod。


1. 场景文件(.tscn

结构

场景根节点使用 Node2D(不挂脚本),包含以下 unique name 子节点:

子节点名类型unique_name_in_owner用途
VisualsAnimatedSprite2DSpineSpriteBody,播放 idle/attack/hurt/die 动画
BoundsControl碰撞/悬停区域,决定 Hitbox 和血条宽度
CenterPosMarker2DVFX 生成位置
IntentPosMarker2D意图图标位置
OrbPosMarker2D(可选)宝珠位置,缺失时引擎用 IntentPos
TalkPosMarker2D(可选)对话气泡位置

NCreatureVisuals._Ready() 通过 % 查找(GetNode<T>("%Name"))获取这些节点,unique_name_in_owner = true 必须设置。

参考尺寸(官方宠物风格)

Visuals: position=(-19,-23), scale=(0.26,0.26)  # SpineSprite
Bounds:  offset_left=-116, offset_top=-204, offset_right=116, offset_bottom=0  # 232×204
CenterPos: position=(-15,-109)
IntentPos: position=(0,-218)

文件位置示例:your-mod-patch/scenes/creature_visuals/my_pet.tscn


2. MonsterModel

继承 MonsterModel,定义 HP、动画状态机、召唤后的初始 Power 等。

csharp
public sealed class MyPet : MonsterModel
{
    public override int MinInitialHp => 40;
    public override int MaxInitialHp => 40;

    public override async Task AfterAddedToRoom()
    {
        await base.AfterAddedToRoom();
        await PowerCmd.Apply<MinionPower>(Creature, 1m, Creature, null);
        // ... 其他 Power
    }

    protected override MonsterMoveStateMachine GenerateMoveStateMachine() { /* ... */ }
    public override CreatureAnimator GenerateAnimator(MegaSprite controller) { /* ... */ }
}

动画状态

GenerateAnimator 中使用的动画名必须与 .tscnSpriteFrames 动画名一致:

动画名用途loop
idle / idle_loop待机
idle_damaged受伤待机(可选,HP 切换用)
attack攻击
hurt受击
die死亡
dead_loop死亡后循环

3. 视觉加载(Harmony Patch)

Harmony 的通用约定(补丁目标、Prefix/Postfix、PatchAll、参数注入)见 Harmony 补丁基础

为什么需要 Patch

MonsterModel.CreateVisuals() 调用 PackedScene.Instantiate<NCreatureVisuals>(),要求场景根节点类型是 NCreatureVisuals。但 Godot 4 不自动扫描 mod DLL 的 ScriptPathAttribute,场景根节点只能是 Node2D,导致转型失败。且 CreateVisuals() 不是 virtual,无法 override。

实现方式

通过 Harmony Prefix 拦截 MonsterModel.CreateVisuals(),手动完成节点迁移:

csharp
var source = scene.Instantiate();
var visuals = new NCreatureVisuals();
visuals.Name = source.Name;
foreach (var child in new List<Node>(source.GetChildren()))
{
    source.RemoveChild(child);
    visuals.AddChild(child);
    child.Owner = visuals;
}
source.QueueFree();

关键child.Owner = visuals 必须设置,否则 NCreatureVisuals._Ready()%Visuals%Bounds 等查找会失败。

Prefix 阶段节点状态

Prefix 中创建的 NCreatureVisuals 尚未进入场景树(_Ready() 未执行),Body 等属性可能为 null。若需在 Prefix 中操作节点,直接遍历子节点查找。

注册新宠物

在你维护的 ScenePaths 字典中增加:类名 → res:// 场景路径

调用链

卡牌.OnPlay()
  → PlayerCmd.AddPet<T>()
    → CreatureCmd.Add()
      → NCreature.Create()
        → Creature.CreateVisuals()
          → MonsterModel.CreateVisuals()  ← Harmony Prefix 在此拦截

4. 宠物定位(Harmony Patch)

引擎默认行为

NCombatRoom.AddCreature() 对非 Osty 类宠物可能堆叠在玩家前方并隐藏血条ToggleIsInteractable(false))。mod 若需要独立位置与可见血条,可在 Postfix 中重新定位并 ToggleIsInteractable(true)

注册

在自定义 HashSet<string> 或等价结构中登记你的 MonsterModel 类名。

定位参数(示例)

参数说明
偏移相对玩家节点,向右/向上为常见友方宠物摆放
多宠物可用固定间距递增

5. HP 视觉切换(可选)

若使用主 mod + 补丁 mod 双 PCK:可通过同一路径场景覆盖、运行时 GD.Load 补纹理等方式切换立绘/动画。注意 Godot 导出 PCK 时只打包本项目内资源,跨项目引用须在运行时加载。


6. 添加新宠物的步骤清单

  1. 准备动画素材与 .tscn(符合上文节点结构)。
  2. 实现 MonsterModel 子类。
  3. 实现召唤卡牌:PlayerCmd.AddPet<T>()
  4. 注册视觉 Patch 的场景映射。
  5. 若需要:注册定位 / 血条 Patch。
  6. DevMode 等工具实机验证。

7. 引擎约束(摘要)

约束应对
CreateVisuals 非 virtualHarmony Prefix
场景根不能是 mod C# 类型根节点 Node2D + Patch 迁移到 NCreatureVisuals
非 Osty 宠物血条可能被隐藏Postfix 中 ToggleIsInteractable(true)
Prefix 阶段属性未初始化子节点遍历

8. 游戏源码参考

命名空间
MonsterModelMegaCrit.Sts2.Core.Models
NCreatureVisualsMegaCrit.Sts2.Core.Nodes.Combat
NCreatureMegaCrit.Sts2.Core.Nodes.Combat
NCombatRoomMegaCrit.Sts2.Core.Nodes.Rooms
OstyMegaCrit.Sts2.Core.Models.Monsters