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:
@@ -12,20 +12,107 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// 创建新战斗,邀请方和被邀请方,或者玩家和野怪方
|
||||
func NewFight(p1, p2 common.PlayerI, b1, b2 []model.PetInfo, fn func(model.FightOverInfo)) (*FightC, errorcode.ErrorCode) {
|
||||
// NewFightSingleControllerN 创建 N 打战斗(单人控制多站位)。
|
||||
// ourPetsBySlot/oppPetsBySlot 的每个元素代表一个站位携带的宠物列表。
|
||||
func NewFightSingleControllerN(
|
||||
ourController common.PlayerI,
|
||||
oppController common.PlayerI,
|
||||
ourPetsBySlot [][]model.PetInfo,
|
||||
oppPetsBySlot [][]model.PetInfo,
|
||||
fn func(model.FightOverInfo),
|
||||
) (*FightC, errorcode.ErrorCode) {
|
||||
if ourController == nil || oppController == nil {
|
||||
return nil, errorcode.ErrorCodes.ErrSystemBusyTryLater
|
||||
}
|
||||
fightInfo := ourController.Getfightinfo()
|
||||
|
||||
ourInputs, err := buildSideInputsByController(ourController, ourPetsBySlot, fightInfo.Mode)
|
||||
if err > 0 {
|
||||
return nil, err
|
||||
}
|
||||
oppInputs, err := buildSideInputsByController(oppController, oppPetsBySlot, fightInfo.Mode)
|
||||
if err > 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewFightWithOptions(
|
||||
WithFightPlayers(p1, p2),
|
||||
WithFightPets(b1, b2),
|
||||
WithFightInputs(ourInputs, oppInputs),
|
||||
WithFightPlayersOnSide(
|
||||
[]common.PlayerI{ourController},
|
||||
[]common.PlayerI{oppController},
|
||||
),
|
||||
WithInputControllerBinding(InputControllerBindingSingle),
|
||||
WithFightCallback(fn),
|
||||
WithFightInfo(fightInfo),
|
||||
)
|
||||
}
|
||||
|
||||
// NewFightPerSlotControllerN 创建 N 打战斗(多人各控制一个站位)。
|
||||
// ourPlayers/oppPlayers 与 ourPetsBySlot/oppPetsBySlot 按站位一一对应。
|
||||
func NewFightPerSlotControllerN(
|
||||
ourPlayers []common.PlayerI,
|
||||
oppPlayers []common.PlayerI,
|
||||
ourPetsBySlot [][]model.PetInfo,
|
||||
oppPetsBySlot [][]model.PetInfo,
|
||||
fn func(model.FightOverInfo),
|
||||
) (*FightC, errorcode.ErrorCode) {
|
||||
if len(ourPlayers) == 0 || len(oppPlayers) == 0 {
|
||||
return nil, errorcode.ErrorCodes.ErrSystemBusyTryLater
|
||||
}
|
||||
if len(ourPlayers) != len(ourPetsBySlot) || len(oppPlayers) != len(oppPetsBySlot) {
|
||||
return nil, errorcode.ErrorCodes.ErrSystemBusyTryLater
|
||||
}
|
||||
|
||||
fightInfo := ourPlayers[0].Getfightinfo()
|
||||
ourInputs, err := buildSideInputsByPlayers(ourPlayers, ourPetsBySlot, fightInfo.Mode)
|
||||
if err > 0 {
|
||||
return nil, err
|
||||
}
|
||||
oppInputs, err := buildSideInputsByPlayers(oppPlayers, oppPetsBySlot, fightInfo.Mode)
|
||||
if err > 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewFightWithOptions(
|
||||
WithFightInputs(ourInputs, oppInputs),
|
||||
WithFightPlayersOnSide(ourPlayers, oppPlayers),
|
||||
WithInputControllerBinding(InputControllerBindingPerSlot),
|
||||
WithFightCallback(fn),
|
||||
WithFightInfo(fightInfo),
|
||||
)
|
||||
}
|
||||
|
||||
// 创建新战斗,邀请方和被邀请方,或者玩家和野怪方
|
||||
func NewFight(p1, p2 common.PlayerI, b1, b2 []model.PetInfo, fn func(model.FightOverInfo)) (*FightC, errorcode.ErrorCode) {
|
||||
if p1 == nil || p2 == nil {
|
||||
return nil, errorcode.ErrorCodes.ErrSystemBusyTryLater
|
||||
}
|
||||
fightInfo := p1.Getfightinfo()
|
||||
ourInput, err := buildInputFromPets(p1, b1, fightInfo.Mode)
|
||||
if err > 0 {
|
||||
return nil, err
|
||||
}
|
||||
oppInput, err := buildInputFromPets(p2, b2, fightInfo.Mode)
|
||||
if err > 0 {
|
||||
return nil, err
|
||||
}
|
||||
return NewFightWithOptions(
|
||||
WithFightInputs([]*input.Input{ourInput}, []*input.Input{oppInput}),
|
||||
WithFightCallback(fn),
|
||||
WithFightInfo(fightInfo),
|
||||
)
|
||||
}
|
||||
|
||||
// buildFight 基于已准备好的双方 Inputs 构建战斗实例。
|
||||
// 约束:opts.ourInputs/opts.oppInputs 必须非空。
|
||||
func buildFight(opts *fightBuildOptions) (*FightC, errorcode.ErrorCode) {
|
||||
if opts == nil || opts.owner == nil || opts.opponent == nil {
|
||||
if opts == nil {
|
||||
return nil, errorcode.ErrorCodes.ErrSystemBusyTryLater
|
||||
}
|
||||
opts.normalizePlayers()
|
||||
if opts.owner == nil || opts.opponent == nil {
|
||||
return nil, errorcode.ErrorCodes.ErrSystemBusyTryLater
|
||||
}
|
||||
|
||||
f := &FightC{}
|
||||
f.ownerID = opts.owner.GetInfo().UserID
|
||||
@@ -45,17 +132,14 @@ func buildFight(opts *fightBuildOptions) (*FightC, errorcode.ErrorCode) {
|
||||
}
|
||||
f.ReadyInfo.Status = f.Info.Status
|
||||
|
||||
var err errorcode.ErrorCode
|
||||
f.Our, err = f.buildFightInputs(opts.owner, opts.ourPets, opts.ourInputs)
|
||||
if err > 0 {
|
||||
return nil, err
|
||||
if len(opts.ourInputs) == 0 || len(opts.oppInputs) == 0 {
|
||||
return nil, errorcode.ErrorCodes.ErrSystemBusyTryLater
|
||||
}
|
||||
f.Opp, err = f.buildFightInputs(opts.opponent, opts.oppPets, opts.oppInputs)
|
||||
if err > 0 {
|
||||
return nil, err
|
||||
}
|
||||
f.bindInputFightContext(f.Our)
|
||||
f.bindInputFightContext(f.Opp)
|
||||
f.Our = opts.ourInputs
|
||||
f.Opp = opts.oppInputs
|
||||
f.bindInputControllers(f.Our, f.OurPlayers, opts.controllerBinding)
|
||||
f.bindInputControllers(f.Opp, f.OppPlayers, opts.controllerBinding)
|
||||
f.bindInputFightContext(f.Our, f.Opp)
|
||||
f.linkTeamViews()
|
||||
f.linkOppInputs()
|
||||
|
||||
@@ -106,13 +190,94 @@ func buildFight(opts *fightBuildOptions) (*FightC, errorcode.ErrorCode) {
|
||||
return f, 0
|
||||
}
|
||||
|
||||
func (f *FightC) buildFightInputs(defaultPlayer common.PlayerI, pets []model.PetInfo, existing []*input.Input) ([]*input.Input, errorcode.ErrorCode) {
|
||||
if len(existing) > 0 {
|
||||
return existing, 0
|
||||
// bindInputControllers 按配置模式重绑站位控制者(Input.Player)。
|
||||
// Keep: 不改;Single: 全部绑定 players[0];PerSlot: 按下标绑定 players[i]。
|
||||
func (f *FightC) bindInputControllers(inputs []*input.Input, players []common.PlayerI, mode int) {
|
||||
if len(inputs) == 0 || len(players) == 0 {
|
||||
return
|
||||
}
|
||||
in, err := f.initplayer(defaultPlayer, pets)
|
||||
if err > 0 {
|
||||
return nil, err
|
||||
switch mode {
|
||||
case InputControllerBindingSingle:
|
||||
controller := players[0]
|
||||
for _, in := range inputs {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
in.Player = controller
|
||||
}
|
||||
case InputControllerBindingPerSlot:
|
||||
for idx, in := range inputs {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
if idx < len(players) && players[idx] != nil {
|
||||
in.Player = players[idx]
|
||||
continue
|
||||
}
|
||||
in.Player = players[0]
|
||||
}
|
||||
default:
|
||||
// keep existing input player binding
|
||||
}
|
||||
return []*input.Input{in}, 0
|
||||
}
|
||||
|
||||
// buildInputFromPets 根据玩家与宠物列表构建一个站位 Input。
|
||||
func buildInputFromPets(c common.PlayerI, pets []model.PetInfo, mode uint32) (*input.Input, errorcode.ErrorCode) {
|
||||
if c == nil {
|
||||
return nil, errorcode.ErrorCodes.ErrSystemBusyTryLater
|
||||
}
|
||||
if r := c.CanFight(); r != 0 {
|
||||
return nil, r
|
||||
}
|
||||
|
||||
in := input.NewInput(nil, c)
|
||||
in.AllPet = make([]*info.BattlePetEntity, 0, len(pets))
|
||||
in.InitAttackValue()
|
||||
for _, pet := range pets {
|
||||
entity := info.CreateBattlePetEntity(pet)
|
||||
entity.BindController(c.GetInfo().UserID)
|
||||
in.AllPet = append(in.AllPet, entity)
|
||||
}
|
||||
|
||||
in.SortPet()
|
||||
if len(in.AllPet) == 0 {
|
||||
return nil, errorcode.ErrorCodes.ErrNoEligiblePokemon
|
||||
}
|
||||
if mode == info.BattleMode.SINGLE_MODE {
|
||||
in.AllPet = in.AllPet[:1]
|
||||
}
|
||||
in.SetCurPetAt(0, in.AllPet[0])
|
||||
return in, 0
|
||||
}
|
||||
|
||||
// buildSideInputsByController 用同一控制者构建多个站位输入(单人多站位)。
|
||||
func buildSideInputsByController(controller common.PlayerI, petsBySlot [][]model.PetInfo, mode uint32) ([]*input.Input, errorcode.ErrorCode) {
|
||||
if controller == nil || len(petsBySlot) == 0 {
|
||||
return nil, errorcode.ErrorCodes.ErrSystemBusyTryLater
|
||||
}
|
||||
inputs := make([]*input.Input, 0, len(petsBySlot))
|
||||
for _, slotPets := range petsBySlot {
|
||||
in, err := buildInputFromPets(controller, slotPets, mode)
|
||||
if err > 0 {
|
||||
return nil, err
|
||||
}
|
||||
inputs = append(inputs, in)
|
||||
}
|
||||
return inputs, 0
|
||||
}
|
||||
|
||||
// buildSideInputsByPlayers 按站位玩家一一对应构建输入(多人分站位)。
|
||||
func buildSideInputsByPlayers(players []common.PlayerI, petsBySlot [][]model.PetInfo, mode uint32) ([]*input.Input, errorcode.ErrorCode) {
|
||||
if len(players) == 0 || len(players) != len(petsBySlot) {
|
||||
return nil, errorcode.ErrorCodes.ErrSystemBusyTryLater
|
||||
}
|
||||
inputs := make([]*input.Input, 0, len(players))
|
||||
for idx := range players {
|
||||
in, err := buildInputFromPets(players[idx], petsBySlot[idx], mode)
|
||||
if err > 0 {
|
||||
return nil, err
|
||||
}
|
||||
inputs = append(inputs, in)
|
||||
}
|
||||
return inputs, 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user