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/gameserver/routers/game_router_companion_assist.go

127 lines
6.1 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 routers
import (
"context"
"sync"
)
var _ = sync.Mutex{}
var _ = context.Background
//
// 随从的服务端兜底驱动:跟随 + 协战。
// ⛑⛑⛑ 2026-10-01 定位到更正的解法,本文件已不再是默认路径
// (开关 gameplay.aether.companionServerDrive,默认 false):
// 随从模板用的是专属伴生行为树(晴 Companion_JiaMu_Shuangmawei、
// 盖斯 Companion_Guys),它们的行为集里没有 Behavior_Battle 和 RelatedSkillIds,
// 战斗能力写在那棵树的 C# 实现里,服务端查不到 ⇒ 硬喂招只能给到
// EnemyAiFallbackAttacks(金属吉他手那两下),这就是实机上看到的
// 「只有远程射击动作、也没有武器、打不出伤害」。
// 正解 = SyncAgentCompanionAI + SyncCompanionMaster + 模板自带的阵营
// (UnitCamp.PlayerDefault = 1,见 CompanionBind.cs),然后让客户端那棵树自己跑。
// ⛑⛑ 2026-10-01 更早的实机:只推 SyncCompanionMaster / SyncAgentCompanionAI 是不够的 ——
// 那两个包只登记「谁是谁的随从」,客户端不会因此给它下任何指令,实测就是站着不动的木桩。
// 当时补的就是这条用主线本来就有的敌人战斗指令驱动:
// SyncBattleAiS(68555063) 开/关战斗 AI
// SyncUnitLockTarget(68009754) 锁定谁
// SyncEnemyFightEdict(68882858) 给不给攻击令牌
// SyncEnemyBattleMoveTowardUnit(68792181) 朝谁移动
// 这四个包在 GameRouter.EnemyAiActions.cs:446-454 已经在用(驱动敌人追玩家)。
// 捐赠端 7k v0.5-2 那 323 行 GarmCompanionAi.cs 的核心也就是这行 ——
// 所以它不需要整体移植,主线把同样的包换个目标发就行。
// 跟随 = 没有敌人时把 target 留空、移动目标填主人 uid;
// 协战 = 选一个最近的敌人当 target,同时给攻击令牌。
//
// 由 OnMovementReport 调用:喂一条随从的真实坐标。
func GameRouter_CompanionAssist_NoteCompanionPosition(ctx context.Context, uid uint64, pos Vec3) any {
// Router implementation for GameRouter_CompanionAssist_NoteCompanionPosition
var zero any; return zero
}
// 取随从的真实坐标;没有或过期返回 false。
func GameRouter_CompanionAssist_TryGetCompanionPosition(ctx context.Context, uid uint64, pos Vec3) bool {
// Router implementation for GameRouter_CompanionAssist_TryGetCompanionPosition
return true
}
//
// 给刚绑好的随从起一个驱动 worker。失败不影响随从本身(它已经生成了)。
//
func GameRouter_CompanionAssist_StartCompanionAssist(ctx context.Context, uid uint64, ownerUnitId uint64) any {
// Router implementation for GameRouter_CompanionAssist_StartCompanionAssist
var zero any; return zero
}
// 让某个随从停手(解散 / 单位消失时用)。
func GameRouter_CompanionAssist_StopCompanionAssist(ctx context.Context, uid uint64) any {
// Router implementation for GameRouter_CompanionAssist_StopCompanionAssist
var zero any; return zero
}
func GameRouter_CompanionAssist_RunCompanionAssistAsync(ctx context.Context, uid uint64, ownerUnitId uint64) any {
// Router implementation for GameRouter_CompanionAssist_RunCompanionAssistAsync
var zero any; return zero
}
func GameRouter_CompanionAssist_TickCompanionAssistAsync(ctx context.Context, session *GameSession, world any, rt any, tick int32) any {
// Router implementation for GameRouter_CompanionAssist_TickCompanionAssistAsync
var zero any; return zero
}
//
// 贴身出招:SyncUnitSmoothFace 转身 + SyncUseTargetSkill 放招。
// 与主线 GameRouter.EnemyAiActions.cs:592-668 的那段逐行对齐(那套是调过的,别另写)。
// ⛑ 技能池来自 gameplay.aether.companionAttacks:随从没有自己的攻击模组
// (行为集里空),只能借通用池;换池子改配置即可,不用重编译。
//
func GameRouter_CompanionAssist_CastCompanionAsync(ctx context.Context, session *GameSession, rt any, targetPos Vec3, now int64) any {
// Router implementation for GameRouter_CompanionAssist_CastCompanionAsync
var zero any; return zero
}
//
// 从主线的本地敌人账本里挑一个最近的目标,并返回它当前的位置。挑不到返回 (0, 玩家坐标) = 跟随。
// ⛑ 排除:自己、玩家单位、已死单位;是否参战按离玩家的距离判断(随从离玩家太远就不打)。
//
func GameRouter_CompanionAssist_SelectCompanionTarget(ctx context.Context, session *GameSession, world any, rt any) any {
// Router implementation for GameRouter_CompanionAssist_SelectCompanionTarget
var zero any; return zero
}
func GameRouter_CompanionAssist_DistanceSq(ctx context.Context, a Vec3, b Vec3) float32 {
// Router implementation for GameRouter_CompanionAssist_DistanceSq
return 0
}
type CompanionAssistRuntime struct {
UnitId uint64 `json:"unitId"`
OwnerUnitId uint64 `json:"ownerUnitId"`
//
// 当前锁定的目标。初值必须是哨兵(不是 0):engagement 三件套只在目标变化时下发,
// 而"跟随"态的目标正是 0 —— 若初值也是 0,next != Target 恒为 false ⇒
// 整局一个 engagement 包都发不出去,包括"关掉战斗 AI"那条,随从就一直保持
// spawn 时的战斗姿态举着枪(2026-10-01 实机踩到)。
//
Target uint64 `json:"target"`
// 单调递增的 move 序号;契约里 MoveId/InstanceId 是 byte,落盘前截断。
MoveSeq uint32 `json:"moveSeq"`
NextMoveAt int64 `json:"nextMoveAt"`
//
// 估算锚点。服务端拿不到实体真实坐标(客户端不回传),只能这么估。
// spawn 用的是「全 0 pose = 落在玩家跟前」的约定 ⇒ 首帧拿玩家坐标当起点是准的。
//
Anchor Vec3 `json:"anchor"`
HasAnchor bool `json:"hasAnchor"`
MoveCount int32 `json:"moveCount"`
// 朝向(度)。出招前先转身用 —— 官方技能很多带 NoRotation=true。
Facing float32 `json:"facing"`
// 出招冷却到期时间(TickCount64)。
CastUntil int64 `json:"castUntil"`
// 下次允许出招的时间。
ActionAt int64 `json:"actionAt"`
// 出招实例号;契约里 instanceId 是 int,别写成 uint。
CastInstance int32 `json:"castInstance"`
CastCount int32 `json:"castCount"`
}