This repository has been archived on 2026-10-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Ananta-ps/internal/catalogs/enemy_ai_catalog4229938.go

181 lines
7.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package catalogs
import (
"encoding/json"
"os"
"path/filepath"
"sync"
)
var _ = json.RawMessage{}
var _ = sync.Mutex{}
var _ = os.ReadFile
var _ = filepath.Join
// Combat profile for one AgentConfig template, used to arm and skill a spawned enemy.
type EnemyAiProfile4229938 struct {
Id uint32 `json:"id"`
Name string `json:"name"`
// AgentConfig.AI — the AgentAIBehaviorSetsBattleAISBehaviorConfig row id.
Ai uint32 `json:"ai"`
// Behaviour tree name. The correct value per template, not a hostile/civilian guess.
Tree string `json:"tree"`
Battle string `json:"battle"`
// AgentConfig.InitWeaponId. 0 means the template authors no weapon.
Weapon uint32 `json:"weapon"`
// AgentConfig.InitWeaponSceneItemId — the scene item the weapon is built from.
WeaponSceneItem uint32 `json:"weaponSceneItem"`
// AgentConfig.EnemyOccurId, used as SyncUnitOccur.occurId. 0 for most templates.
Occur uint32 `json:"occur"`
Class uint32 `json:"class"`
// Every skill the behaviour set references. Kept for diagnostics.
Skills []uint32 `json:"skills"`
//
// The attacks this template actually gets, in priority order.
// Tier 1 is the donor's 29 curated standalone NPC attacks (SkillConfig CastType=1,
// non-looping) — those are the ones proven to animate when the server issues
// SyncUseTargetSkill. Tier 2 is this template's OWN remaining RelatedSkillIds, minus
// skills the designers marked dead in their Chinese names ("空技能", "不合适",
// "应该没用了", …). Tier 2 exists because bosses and elites have no tier-1 skill at
// all: their entire kit is CastType=0, so before this existed every boss silently fell
// back to the metallic guitarist's two swings.
// Budget scales with EnemyClassType: 6 for bosses/elites (2, 6), 4 for (4, 7), 3 for
// ordinary (1). Empty means the template has nothing usable at all.
//
Attacks []uint32 `json:"attacks"`
//
// Chinese SkillConfig names for Attacks, one per entry. Diagnostics only —
// the log prints them so a boss's move set can be read without opening the config.
//
AttackNames []string `json:"attackNames"`
// ---- 2026-09-26 Wave 2:战斗模式列(移植 7k-v0.5 EnemyAiCatalog4229938 同名概念)----
// AgentConfig.BattleAnimType —— 模板自带的 AnimationSetConfig id
// (7K 叫 TemplateBattleAnimSetTag,仅 GM follow-test animChoice==1 时用)。
TemplateBattleAnimSetTag uint32 `json:"templateBattleAnimSetTag"`
// 空手模式技能池 ∩ 本模板 RelatedSkillIds(≤2)。见生成脚本的 UNARMED 池。
UnarmedAttacks []uint32 `json:"unarmedAttacks"`
// 远程模式技能池 ∩ 本模板 RelatedSkillIds(≤2)。见生成脚本的 RANGED 池。
RangedAttacks []uint32 `json:"rangedAttacks"`
// 战斗模式:template(默认,模板原样)/ melee / ranged。
// 由 EnemyAiCatalog4229938.SelectCombatProfile 产生,目录行本身恒为 template。
CombatMode string `json:"combatMode"`
// 模式选择后的战斗动画集(AnimationSetConfig id,不是技能或动作 id)。
// 空手 = 325(十二面空手)/ 327(通用胖子空手);远程 = 337/338/340。0 = 不覆盖。
BattleAnimSetTag uint32 `json:"battleAnimSetTag"`
// 交战距离(米)。7K 默认 2.8;远程模式 = 18。Wave 4 警示 HUD Alert 档也要用它。
AttackRange float32 `json:"attackRange"`
// 跟随风格(7K GM follow-test 专用):guard / front / lateral / run。Wave 2 只存档不用。
FollowStyle string `json:"followStyle"`
// 跟随动画选择(7K GM follow-test 专用,AnimationSetConfig id)。Wave 2 只存档不用。
FollowAnimChoice uint32 `json:"followAnimChoice"`
}
//
// Per-template combat profile catalog, read from EnemyAiCatalog.json.
// That file is generated by _gen_enemy_ai_catalog.py, which projects the donor build's
// 57 MB AgentConfig.json plus AgentAIBehaviorSetsBattleAISBehaviorConfig.json down to the
// handful of fields the attack AI needs (about 950 KB for 3160 rows). The full table never
// has to ship with the server.
// Why per-template instead of one shared pool: a skill belongs to a skeleton. Lending one
// skeleton's swing to another produces a unit that closes in and then stands there, because
// the animation simply does not exist on that rig.
//
var (
EnemyAiCatalog4229938_cacheLock sync.RWMutex
EnemyAiCatalog4229938_cached = false
EnemyAiCatalog4229938_entries []any
)
// LoadEnemyAiCatalog4229938 loads catalog records from client config directory
func LoadEnemyAiCatalog4229938(configDir string) ([]any, error) {
EnemyAiCatalog4229938_cacheLock.RLock()
if EnemyAiCatalog4229938_cached {
defer EnemyAiCatalog4229938_cacheLock.RUnlock()
return EnemyAiCatalog4229938_entries, nil
}
EnemyAiCatalog4229938_cacheLock.RUnlock()
EnemyAiCatalog4229938_cacheLock.Lock()
defer EnemyAiCatalog4229938_cacheLock.Unlock()
if EnemyAiCatalog4229938_cached { return EnemyAiCatalog4229938_entries, nil }
filePath := filepath.Join(configDir, "EnemyAiCatalog.json.json")
data, err := os.ReadFile(filePath)
if err != nil {
return nil, err
}
var raw struct {
Records []json.RawMessage `json:"records"`
}
if err := json.Unmarshal(data, &raw); err != nil {
return nil, err
}
var result []any
for _, item := range raw.Records {
var m map[string]any
if err := json.Unmarshal(item, &m); err == nil {
result = append(result, m)
}
}
EnemyAiCatalog4229938_entries = result
EnemyAiCatalog4229938_cached = true
return result, nil
}
func EnemyAiCatalog4229938_BuildNameFallback() map[uint32]EnemyAiProfile4229938 {
// Catalog helper EnemyAiCatalog4229938_BuildNameFallback
return nil
}
//
// 按 id 取战斗档案;miss 时按同名变体兜底(见 NameFallback)。
// 单参数签名不变 ⇒ spawn、攻击 AI、警戒状态机三处调用点自动受益。
//
func EnemyAiCatalog4229938_Find(id uint32) *EnemyAiProfile4229938 {
// Catalog helper EnemyAiCatalog4229938_Find
return nil
}
// ---- 2026-09-26 Wave 2:战斗模式选择(移植 7k-v0.5 SelectCombatProfile,逐行对齐)----
func EnemyAiCatalog4229938_IsCombatMode(mode *string) bool {
// Catalog helper EnemyAiCatalog4229938_IsCombatMode
return false
}
// 7K GM follow-test 的合法值(AnimationSetConfig id,不是技能/动作 id)。Wave 2 只存档不用。
func EnemyAiCatalog4229938_IsFollowStyle(style *string) bool {
// Catalog helper EnemyAiCatalog4229938_IsFollowStyle
return false
}
func EnemyAiCatalog4229938_IsFollowAnimChoice(id uint32) bool {
// Catalog helper EnemyAiCatalog4229938_IsFollowAnimChoice
return false
}
//
// 按模式解析一个模板的战斗档案(移植 7k-v0.5 SelectCombatProfile,逐行对齐):
// template = 原样;melee = 有空手技能则卸武器 + 空手动画集
// (325 十二面空手 / 327 通用胖子空手),否则保留武器只换攻击集(去掉喷火器 51900505);
// ranged = 有武器且有远程技能才成立,攻击集换远程、AttackRange=18、动画集
// 337/338/340。条件不满足返回 null(调用方兜回 Find)。
//
func EnemyAiCatalog4229938_SelectCombatProfile(id uint32, mode string) *EnemyAiProfile4229938 {
// Catalog helper EnemyAiCatalog4229938_SelectCombatProfile
return nil
}
//
// spawn 链路统一入口:off → 模板原样(旧行为逐字节不变);否则按配置模式解析,
// 模式条件不满足兜回模板原样。武器 / 技能槽 / 攻击 AI / 战斗姿态四处共用这一份,
// 保证「看到的武器 = 手里的动画集 = 甩出来的技能」永远一致。
//
func EnemyAiCatalog4229938_ResolveSpawnProfile(templateId uint32) *EnemyAiProfile4229938 {
// Catalog helper EnemyAiCatalog4229938_ResolveSpawnProfile
return nil
}