feat: 支持多站位战斗控制绑定模式
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
This commit is contained in:
@@ -11,6 +11,15 @@ import (
|
||||
|
||||
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
|
||||
@@ -18,37 +27,25 @@ type fightBuildOptions struct {
|
||||
ourPlayers []common.PlayerI
|
||||
oppPlayers []common.PlayerI
|
||||
|
||||
ourPets []model.PetInfo
|
||||
oppPets []model.PetInfo
|
||||
|
||||
ourInputs []*input.Input
|
||||
oppInputs []*input.Input
|
||||
|
||||
callback func(model.FightOverInfo)
|
||||
startTime time.Time
|
||||
fightInfo *info.Fightinfo
|
||||
|
||||
controllerBinding int
|
||||
}
|
||||
|
||||
// defaultFightBuildOptions 返回建战默认参数。
|
||||
func defaultFightBuildOptions() *fightBuildOptions {
|
||||
return &fightBuildOptions{
|
||||
startTime: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
func WithFightPlayers(owner, opponent common.PlayerI) FightOption {
|
||||
return func(opts *fightBuildOptions) {
|
||||
opts.owner = owner
|
||||
opts.opponent = opponent
|
||||
}
|
||||
}
|
||||
|
||||
func WithFightPets(ourPets, oppPets []model.PetInfo) FightOption {
|
||||
return func(opts *fightBuildOptions) {
|
||||
opts.ourPets = ourPets
|
||||
opts.oppPets = oppPets
|
||||
startTime: time.Now(),
|
||||
controllerBinding: InputControllerBindingKeep,
|
||||
}
|
||||
}
|
||||
|
||||
// WithFightInputs 注入双方站位输入(当前建战主路径)。
|
||||
func WithFightInputs(ourInputs, oppInputs []*input.Input) FightOption {
|
||||
return func(opts *fightBuildOptions) {
|
||||
opts.ourInputs = ourInputs
|
||||
@@ -56,6 +53,7 @@ func WithFightInputs(ourInputs, oppInputs []*input.Input) FightOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithFightPlayersOnSide 显式指定双方操作者列表(可选)。
|
||||
func WithFightPlayersOnSide(ourPlayers, oppPlayers []common.PlayerI) FightOption {
|
||||
return func(opts *fightBuildOptions) {
|
||||
opts.ourPlayers = ourPlayers
|
||||
@@ -63,24 +61,34 @@ func WithFightPlayersOnSide(ourPlayers, oppPlayers []common.PlayerI) FightOption
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
func NewFightWithOptions(opts ...FightOption) (*FightC, errorcode.ErrorCode) {
|
||||
buildOpts := defaultFightBuildOptions()
|
||||
for _, opt := range opts {
|
||||
@@ -91,11 +99,46 @@ func NewFightWithOptions(opts ...FightOption) (*FightC, errorcode.ErrorCode) {
|
||||
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]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user