Boss制作

黑西游-Boss开发

:::success{title=高效!非常高效}

  • 该功能为使用简单的Json配置(python dict),即可轻松实现《黑西游》新Boss注册
  • 原本需要2~3天的开发周期,现仅需***2小时***!
  • 现已支持使用灵免以太接口 :::

附件列表

:::warning{title=注意}

  • 由于早期框架问题,测试时必须要加载“黑西游-黑风山下”,“黑西游-广智”,“黑西游-虎先锋” :::
版本文件名称上传时间大小下载
2.2.1黑西游-测试环境2024-11-0261.3M下载
1.0.0黑西游-黑风山下2024-11-07265K下载
1.0.0黑西游-广智2024-11-07262K下载
1.0.0黑西游-小妖I2024-11-07180K下载
1.0.0黑西游-虎先锋2024-11-07340K下载
1.0.1黑西游-石先锋2024-11-02188K下载

调试设置

由于微软mojang原版沙子实体多线程bug,致使游戏持续弹出断言而崩溃游戏,需要前往菜单-设置-调试-断言显示一个模式对话关闭!

副包脚本文件结构

  • ***Scripts脚本文件夹
    • ***Common
      • __init__.py
      • config.py脚本配置文件
    • ModClient客户端文件夹
      • __init__.py
      • ClientEventList客户端监听事件列表(使用监听装饰器,不推荐在此处编写监听事件)
      • EventApi.py客户端监听事件装饰器
      • GlobalClientSystem.py客户端系统
    • ModServer服务端文件夹
      • __init__.py
      • EventApi.py服务端监听事件装饰器
      • ServerEventList服务端监听事件列表(使用监听装饰器,不推荐在此处编写监听事件)
      • heishenhua.py黑西游副包数据信息
      • GlobalServerSystem.py服务端系统
    • __init__.py
    • modMain.py脚本系统(不推荐在此处编写代码)

资产规范及导入

资产命名规范

:::error{title=特别注意} 一定要确保必要资产内容正确命名,否则直接在游戏内测试会出现异常! :::

名称命名格式示例备注
自定义动画animation.{RenderId}.{animationname}animation.ailian.pose2选择性注意,只需要保证正常注册实体动画即可。但推荐强制规范!
待机动画animation.{RenderId}.idleanimation.ailian.idle必要
行走动画animation.{RenderId}.walkanimation.ailian.walk必要
普通攻击动画animation.{RenderId}.attackanimation.ailian.attack必要
死亡动画animation.{RenderId}.deathanimation.ailian.death必要

资产内容规范

动画关键帧规范

:::warning{title=注意} 一定要严加检查该内容 :::

每个动画一定要确保首尾都有关键帧,否则游戏内实际表现将会异常

如果没有,需要手动先点击“将所有修改后的动画放入时间轴”,随后选择关键帧位置,再到关键帧选项中点击创建关键帧列

死亡动画规范

尸体死亡动画,即death动画的尾帧应当延长至3.5秒处!

使用自动化程序创建Boss

  • 选择自定义Boss实体自动化类型

  • 根据资产命名规范填写内容,随后导入模型、纹理,选择行为包、资源包,最后点击开始纸娃娃即可

  • 游戏内就会新增一个黑色的刷怪蛋,但此时他并没有动作等内容

导入动画文件并处理实体动画

文件结构

  • behavior_pack_***行为包
    • resource_pack_***资源包
      • animation_controllers动画控制器文件夹
        • {EntityId}.animation_controllers.json实体动画控制器文件
      • animations动画文件夹(如果没有需要手动创建)
        • {EntityId}.animation.json实体动画文件
      • entity实体外观文件夹
        • death实体的尸体外观文件夹
            {EntityId}.json实体的尸体外观文件
        • {EntityId}.json实体外观文件

    导入动画文件

    • 使用blockbench打开实体bbmodel工程文件,并将实体动画导出,并将文件命名满足上面文件结构中的格式:{EntityId}.animation.json

    • 打开所导出的动画文件,复制至上面文件结构中对应的位置。打开并根据资产命名规范来对动画id进行修改

    注册实体动画

    • 打开实体外观文件,注册实体连招动画,在"animations"中输入key: 动画id,其中key为该实体动画唯一标识符,指向了动画id,可以理解为key是对动画id的重命名行为。
      将你认为合适的连招动作,注册在该实体外观文件中,如7-12行所示,共6个连招动画。
    {
        "format_version": "1.10.0",
        "minecraft:client_entity": {
            "description":{
                ...
                "animations": {
                    "attack1": "animation.shixianfeng.attack1",
                    "attack2": "animation.shixianfeng.attack2",
                    "attack4": "animation.shixianfeng.attack4",
                    "attack5": "animation.shixianfeng.attack5",
                    "attack6": "animation.shixianfeng.attack6",
                    "attack7": "animation.shixianfeng.attack7",
    
                    "look_at_target": "animation.dfm_common.look_at_target",
                    "idle": "animation.shixianfeng.idle",
                    "walk": "animation.shixianfeng.walk",
                    "attack": "animation.shixianfeng.attack3",
                    "death": "animation.shixianfeng.death",
                    "states_controller": "controller.animation.shixianfeng.states"
                },
                ...
            }
        }
    }
    

    修改动画控制器

    • 打开实体动画控制器文件states下所有的都是该实体的动画机状态,每个状态有对应的动画,转化条件等。
      找到combo_attack动画机状态的animations列表,根据格式,依次添加连招动画,其中key注册实体动画中的重命名,value为条件,格式为query.mod.combo == n,n为连超动画数量、次第取值,从1开始(包含1),步距为1.

    :::warning{title=注意} 自带的custom_combo_attack": "query.mod.combo == 1应当进行删除 :::

    {
        "format_version": "1.10.0",
        "animation_controllers": {
            "controller.animation.shixianfeng.states": {
                "initial_state": "idle",
                "states": {
                    "combo_attack": {
    					"animations": [
    						{
    							"attack1": "query.mod.combo == 1"
    						},
    						{
    							"attack2": "query.mod.combo == 2"
    						},
    						{
    							"attack4": "query.mod.combo == 3"
    						},
    						{
    							"attack5": "query.mod.combo == 4"
    						},
    						{
    							"attack6": "query.mod.combo == 5"
    						},
    						{
    							"attack7": "query.mod.combo == 6"
    						}
    					],
    					"transitions": [
    						{
    							"idle": "!query.mod.combo"
    						}
    					],
    					"blend_transition": 0.15
    				},
                    ...
                }
            }
        }
    }
    

    编写Boss数据信息

    :::warning{title=连招顺序} 根据修改动画控制器中的动画id对应的valuequery.mod.combo == n,根据n的数字从小到大排列 :::

    key数据类型说明
    ModNamestr副包模组名称
    ClientSystemNamestr副包客户端名称
    ServerSystemNamestr副包服务端名称
    CustomAttackFunctionNamestr重写Boss实体攻击逻辑,需要在副包服务端定义一个同名函数并接收一个EntityId的参数
    CustomFeatureRulestrBoss生成的结构规则名称
    CustomSpawnOffsettuple(float, float)Boss生成的结构对应点位的偏移
    ComboTimerlist连招动画时间列表,根据修改动画控制器中按照n的从小到大填写该连招动画的时长
    AttackCDfloat延迟连招逻辑
    DamageTimerListlist[list]对应连招顺序填写该连招动画造成伤害的时间
    AttackDictlist[dict]对应连招顺序填写该连招攻击的配置信息
    • AttackDict 连招攻击配置说明
    key数据类型说明备注
    Radiusfloat攻击距离最小为3
    IsCanSeebool是否可视才造成攻击-
    Damageint造成的伤害-
    BetweenAnglefloat攻击角度0.0~360.0
    SfxDictdictlist攻击特效列表-
    • 攻击特效列表说明
    key数据类型说明备注
    FaceCamarabool是否面向摄像机-
    Idstr特效Id-
    Offsettuple特效坐标偏移三元数组
    Rottuple特效角度偏移三元数组
    Scaletuple特效大小乘积三元数组
    IsJsonbool是否根据json播放特效
    • CustomFeatureRule填写说明
      • 使用接口GetCustomFeatureRulesByPos获取Boss需要生成的CustomFeatureRule

      • 启动测试环境,在游戏内挑选黑西游建筑群的合适Boss生成坐标并填写进GetCustomFeatureRulesByPos接口参数中,随后根据下表填写接口的CustomFeatureRuleId参数,print获取的特征id结果,将结果复制到ComboAttackEntityDict的CustomFeatureRule处

        建筑群多结构自定义特征id
        黑风山(上)custom:heifengshan2_1_106aa1e63ed7409d8a05acd27f34bc49
        黑风山(下)custom:heifengshan3_1_fbb32b30c05b4db2a15dbc955a7e0d42
        黄风岭custom:huangfengling_1_c265f52ba53e4df698764da218665648
      • 随后使用接口GetCustomFeatureRulesPos,获取特征坐标,忽略y坐标考虑,仅需对xz坐标进行计算,得出xz偏移位置:CustomSpawnOffset

    # -*- coding:utf-8 -*-
    ComboAttackEntityDict = {
        'ModName': 'shixianfeng',
        'ClientSystemName': 'shixianfengClientSystem',
        'ServerSystemName': 'shixianfengServerSystem',
        # 'CustomAttackFunctionName': 'BaiYiXiuShiAttack',  # 一个参数EntityId,不填则使用默认连招模式
        'CustomFeatureRule': 'custom:huangfengling_1489_c265f52ba53e4df698764da218665648',  # 自定义生成特征的区块位置
        'CustomSpawnOffset': (0, -6),  # 区块对应的xz偏移位置
        'ComboTimer': [5.25, 5, 4.5, 2.54, 2.5, 2.54],  # 连招动画时间
        'AttackCD': 0,  # 延迟几秒再连击
        'DamageTimerList': [
            [2.04, 3.88],
            [1.04, 2.63, 3.63],
            [2.08, 3.38],
            [1.38],
            [1.5],
            [1.38]
        ],  # 连招伤害触发时间
        'AttackDict': [
            {
                'Radius': 7.5,
                'IsCanSee': True,
                'Damage': 80,
                'BetweenAngle': 150,
                'SfxList': [
                    {
                        'Id': 'youhun_attack',
                        'FaceCamara': True,
                        'Offset': (-3, 3, 0),
                        'Rot': (0, 0, 0),
                        'Scale': (3, 3, 3),
                        'IsJson': True
                    },
                    {
                        'Id': 'youhun_attack2',
                        'FaceCamara': True,
                        'Offset': (-4, 3, 0),
                        'Rot': (0, 0, 0),
                        'Scale': (2.5, 2.5, 2.5),
                        'IsJson': True
                    }
                ]
            },
            {
                'Radius': 7.5,
                'IsCanSee': True,
                'Damage': 80,
                'BetweenAngle': 150,
                'SfxList': [
                    {
                        'Id': 'youhun_attack',
                        'FaceCamara': True,
                        'Offset': (-3, 3, 0),
                        'Rot': (0, 0, 0),
                        'Scale': (3, 3, 3),
                        'IsJson': True
                    },
                    {
                        'Id': 'youhun_attack2',
                        'FaceCamara': True,
                        'Offset': (-4, 3, 0),
                        'Rot': (0, 0, 0),
                        'Scale': (2.5, 2.5, 2.5),
                        'IsJson': True
                    }
                ]
            },
            {
                'Radius': 7.5,
                'IsCanSee': True,
                'Damage': 80,
                'BetweenAngle': 150,
                'SfxList': [
                    {
                        'Id': 'youhun_attack',
                        'FaceCamara': True,
                        'Offset': (-3, 3, 0),
                        'Rot': (0, 0, 0),
                        'Scale': (3, 3, 3),
                        'IsJson': True
                    },
                    {
                        'Id': 'youhun_attack2',
                        'FaceCamara': True,
                        'Offset': (-4, 3, 0),
                        'Rot': (0, 0, 0),
                        'Scale': (2.5, 2.5, 2.5),
                        'IsJson': True
                    }
                ]
            },
            {
                'Radius': 7.5,
                'IsCanSee': True,
                'Damage': 80,
                'BetweenAngle': 150,
                'SfxList': [
                    {
                        'Id': 'youhun_attack',
                        'FaceCamara': True,
                        'Offset': (-3, 3, 0),
                        'Rot': (0, 0, 0),
                        'Scale': (3, 3, 3),
                        'IsJson': True
                    },
                    {
                        'Id': 'youhun_attack2',
                        'FaceCamara': True,
                        'Offset': (-4, 3, 0),
                        'Rot': (0, 0, 0),
                        'Scale': (2.5, 2.5, 2.5),
                        'IsJson': True
                    }
                ]
            },
            {
                'Radius': 7.5,
                'IsCanSee': True,
                'Damage': 80,
                'BetweenAngle': 150,
                'SfxList': [
                    {
                        'Id': 'youhun_attack',
                        'FaceCamara': True,
                        'Offset': (-3, 3, 0),
                        'Rot': (0, 0, 0),
                        'Scale': (3, 3, 3),
                        'IsJson': True
                    },
                    {
                        'Id': 'youhun_attack2',
                        'FaceCamara': True,
                        'Offset': (-4, 3, 0),
                        'Rot': (0, 0, 0),
                        'Scale': (2.5, 2.5, 2.5),
                        'IsJson': True
                    }
                ]
            },
            {
                'Radius': 7.5,
                'IsCanSee': True,
                'Damage': 80,
                'BetweenAngle': 150,
                'SfxList': [
                    {
                        'Id': 'youhun_attack',
                        'FaceCamara': True,
                        'Offset': (-3, 3, 0),
                        'Rot': (0, 0, 0),
                        'Scale': (3, 3, 3),
                        'IsJson': True
                    },
                    {
                        'Id': 'youhun_attack2',
                        'FaceCamara': True,
                        'Offset': (-4, 3, 0),
                        'Rot': (0, 0, 0),
                        'Scale': (2.5, 2.5, 2.5),
                        'IsJson': True
                    }
                ]
            }
        ]
    }
    

    服务端脚本注册Boss实体

    获取主包服务端实例,使用RegisterBoss接口进行注册。

    RegisterBoss

    服务端

    • 描述
      向黑西游·悟空主包注册自定义Boss

    • 参数

    key数据类型说明
    EntityIdStrstr实体IdStr名称,例如"minecraft:zombie"
    ComboAttackEntityDictdict编写Boss数据信息
    • 返回值

    • 备注

    • 示例

    # -*- coding:utf-8 -*-
    import ...
    
    from heishenhua import ComboAttackEntityDict
    
    compFactory = serverApi.GetEngineCompFactory()
    ServerSystem = serverApi.GetServerSystemCls()
    levelId = serverApi.GetLevelId()
    compTimer = serverApi.GetEngineCompFactory().CreateGame(levelId)
    compCmd = serverApi.GetEngineCompFactory().CreateCommand(levelId)
    
    class shixianfengServerSystem(ServerSystem, ServerLingmienAether):
    
        def __init__(self, namespace, systemName):
            ...
            self.LA = self.GetLASys('密钥')
            self.AddTimes = 0
            self.MianPack = None
            self.GetMainPackSystem()
    
        def GetMainPackSystem(self):
            logging.debug('{0}'.format(self.AddTimes))
            try:
                self.MianPack = serverApi.GetSystem('heishenhua', 'heishenhuaServerSystem')
                if self.AddTimes <= 10:
                    if not self.MianPack:
                        compTimer.AddTimer(1.0, self.GetMainPackSystem)
                        self.AddTimes += 1
                    else:
                        self.MianPack.RegisterBoss('dfm:shixianfeng', ComboAttackEntityDict)
            except Exception as e:
                if self.AddTimes <= 10:
                    compTimer.AddTimer(1.0, self.GetMainPackSystem)
                    logging.critical('异常:{0}'.format(e))
    

    大功告成,进行测试

    初界团队
    更新于 2025-07-22
    上一篇 没有了
    下一篇 没有了
    评论交流

    文档目录

    黑西游二创文档