Files
bl/logic/service/fight/new_options.go
昔念 0051ac0be8
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
```
feat(fight): 添加旧组队协议支持并优化战斗系统

- 实现了旧组队协议相关功能,包括GroupReadyFightFinish、GroupUseSkill、
  GroupUseItem、GroupChangePet和GroupEscape方法
- 新增组队战斗相关的入站信息结构体定义
- 实现了组队BOSS战斗逻辑,添加groupBossSlotLimit常量
- 重构宠物技能设置逻辑,调整金币消耗时机
- 优化战斗循环逻辑,添加对无行动槽位的处理
- 改进AI行动逻辑,增加多位置目标选择
2026-04-08 01:28:55 +08:00

153 lines
4.1 KiB
Go
Raw 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 fight
import (
"blazing/common/socket/errorcode"
"blazing/logic/service/common"
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"blazing/modules/player/model"
"time"
)
type FightOption func(*fightBuildOptions)
const (
// InputControllerBindingKeep 保持输入中现有的 Player 绑定,不做覆盖。
InputControllerBindingKeep = iota
// InputControllerBindingSingle 单侧全部站位由 players[0] 控制(双打单人多站位)。
InputControllerBindingSingle
// InputControllerBindingPerSlot 单侧按站位顺序绑定 players[i](组队每人一个站位)。
InputControllerBindingPerSlot
)
type fightBuildOptions struct {
owner common.PlayerI
opponent common.PlayerI
ourPlayers []common.PlayerI
oppPlayers []common.PlayerI
ourInputs []*input.Input
oppInputs []*input.Input
callback func(model.FightOverInfo)
startTime time.Time
fightInfo *info.Fightinfo
controllerBinding int
legacyGroupProtocol bool
}
// defaultFightBuildOptions 返回建战默认参数。
func defaultFightBuildOptions() *fightBuildOptions {
return &fightBuildOptions{
startTime: time.Now(),
controllerBinding: InputControllerBindingKeep,
}
}
// WithFightInputs 注入双方站位输入(当前建战主路径)。
func WithFightInputs(ourInputs, oppInputs []*input.Input) FightOption {
return func(opts *fightBuildOptions) {
opts.ourInputs = ourInputs
opts.oppInputs = oppInputs
}
}
// WithFightPlayersOnSide 显式指定双方操作者列表(可选)。
func WithFightPlayersOnSide(ourPlayers, oppPlayers []common.PlayerI) FightOption {
return func(opts *fightBuildOptions) {
opts.ourPlayers = ourPlayers
opts.oppPlayers = oppPlayers
}
}
// WithFightCallback 设置战斗结束回调。
func WithFightCallback(fn func(model.FightOverInfo)) FightOption {
return func(opts *fightBuildOptions) {
opts.callback = fn
}
}
// WithFightInfo 覆盖战斗信息(模式/状态等)。
func WithFightInfo(fightInfo info.Fightinfo) FightOption {
return func(opts *fightBuildOptions) {
opts.fightInfo = &fightInfo
}
}
// WithFightStartTime 指定战斗创建时间(测试/回放可用)。
func WithFightStartTime(startTime time.Time) FightOption {
return func(opts *fightBuildOptions) {
opts.startTime = startTime
}
}
// WithInputControllerBinding 设置站位控制绑定策略。
func WithInputControllerBinding(mode int) FightOption {
return func(opts *fightBuildOptions) {
opts.controllerBinding = mode
}
}
// WithLegacyGroupProtocol 设置是否使用旧组队协议 CMD。
func WithLegacyGroupProtocol(enabled bool) FightOption {
return func(opts *fightBuildOptions) {
opts.legacyGroupProtocol = enabled
}
}
func NewFightWithOptions(opts ...FightOption) (*FightC, errorcode.ErrorCode) {
buildOpts := defaultFightBuildOptions()
for _, opt := range opts {
if opt != nil {
opt(buildOpts)
}
}
return buildFight(buildOpts)
}
// uniquePlayersFromInputs 从输入中提取去重后的操作者列表。
func uniquePlayersFromInputs(inputs []*input.Input) []common.PlayerI {
if len(inputs) == 0 {
return nil
}
seen := make(map[uint32]struct{}, len(inputs))
players := make([]common.PlayerI, 0, len(inputs))
for _, in := range inputs {
if in == nil || in.Player == nil {
continue
}
userID := in.Player.GetInfo().UserID
if _, ok := seen[userID]; ok {
continue
}
seen[userID] = struct{}{}
players = append(players, in.Player)
}
return players
}
// normalizePlayers 归一化 owner/opponent 与双方 players。
// 若未显式传 players会尝试从 inputs 中自动提取。
func (o *fightBuildOptions) normalizePlayers() {
if len(o.ourPlayers) == 0 && len(o.ourInputs) > 0 {
o.ourPlayers = uniquePlayersFromInputs(o.ourInputs)
}
if len(o.oppPlayers) == 0 && len(o.oppInputs) > 0 {
o.oppPlayers = uniquePlayersFromInputs(o.oppInputs)
}
if len(o.ourPlayers) == 0 && o.owner != nil {
o.ourPlayers = []common.PlayerI{o.owner}
}
if len(o.oppPlayers) == 0 && o.opponent != nil {
o.oppPlayers = []common.PlayerI{o.opponent}
}
if o.owner == nil && len(o.ourPlayers) > 0 {
o.owner = o.ourPlayers[0]
}
if o.opponent == nil && len(o.oppPlayers) > 0 {
o.opponent = o.oppPlayers[0]
}
}