All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
feat(fight): 添加旧组队协议支持并优化战斗系统 - 实现了旧组队协议相关功能,包括GroupReadyFightFinish、GroupUseSkill、 GroupUseItem、GroupChangePet和GroupEscape方法 - 新增组队战斗相关的入站信息结构体定义 - 实现了组队BOSS战斗逻辑,添加groupBossSlotLimit常量 - 重构宠物技能设置逻辑,调整金币消耗时机 - 优化战斗循环逻辑,添加对无行动槽位的处理 - 改进AI行动逻辑,增加多位置目标选择
153 lines
4.1 KiB
Go
153 lines
4.1 KiB
Go
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]
|
||
}
|
||
}
|