Files
bl/logic/service/fight/input.go
xinian 9c6f3988de
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
refactor: 重构 CurrentPet 为 CurPet
2026-04-04 04:34:43 +08:00

337 lines
7.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/common/utils"
"blazing/modules/player/model"
"blazing/logic/service/common"
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"blazing/logic/service/user"
"sync"
"sync/atomic"
"time"
"github.com/gogf/gf/v2/util/grand"
"github.com/jinzhu/copier"
)
type FightC struct {
//准备战斗信息
ReadyInfo model.NoteReadyToFightInfo
//开始战斗信息
info.FightStartOutboundInfo
Info info.Fightinfo
IsReady bool
ownerID uint32 // 战斗发起者ID
Our []*input.Input // 我方战斗位
Opp []*input.Input // 敌方战斗位
OurPlayers []common.PlayerI // 我方操作者
OppPlayers []common.PlayerI // 敌方操作者
Switch map[uint32]*action.ActiveSwitchAction
startl sync.Once
StartTime time.Time
actionMu sync.Mutex
actionNotify chan struct{}
acceptActions bool
pendingActions []action.BattleActionI // 待处理动作队列,同一玩家最多保留两段动作
actionRound atomic.Uint32
quit chan struct{}
over chan struct{}
First *input.Input
TrueFirst *input.Input
Second *input.Input
closefight bool
overl sync.Once
waittime int
model.FightOverInfo
//战斗结束的插装
callback func(model.FightOverInfo)
}
func (f *FightC) primaryOur() *input.Input {
if len(f.Our) == 0 {
return nil
}
return f.Our[0]
}
func (f *FightC) primaryOpp() *input.Input {
if len(f.Opp) == 0 {
return nil
}
return f.Opp[0]
}
func (f *FightC) primaryOurPlayer() common.PlayerI {
if len(f.OurPlayers) == 0 {
return nil
}
return f.OurPlayers[0]
}
func (f *FightC) primaryOppPlayer() common.PlayerI {
if len(f.OppPlayers) == 0 {
return nil
}
return f.OppPlayers[0]
}
func (f *FightC) selectInput(inputs []*input.Input, index int) *input.Input {
if len(inputs) == 0 {
return nil
}
if index >= 0 && index < len(inputs) && inputs[index] != nil {
return inputs[index]
}
for _, in := range inputs {
if in != nil {
return in
}
}
return nil
}
func (f *FightC) isPlayerInSide(players []common.PlayerI, userID uint32) bool {
for _, player := range players {
if player != nil && player.GetInfo().UserID == userID {
return true
}
}
return false
}
func (f *FightC) isOurPlayerID(userID uint32) bool {
if f.isPlayerInSide(f.OurPlayers, userID) {
return true
}
if f.isPlayerInSide(f.OppPlayers, userID) {
return false
}
return userID == f.ownerID
}
func (f *FightC) findInputByUserID(userID uint32) (*input.Input, bool) {
isOur := f.isOurPlayerID(userID)
if isOur {
if in := f.selectInput(f.Our, 0); in != nil {
return in, true
}
return nil, true
}
if in := f.selectInput(f.Opp, 0); in != nil {
return in, false
}
return nil, false
}
func (f *FightC) getInputByUserID(userID uint32, index int, isOpposite bool) *input.Input {
isOur := f.isOurPlayerID(userID)
if isOpposite {
if isOur {
return f.selectInput(f.Opp, index)
}
return f.selectInput(f.Our, index)
}
if isOur {
return f.selectInput(f.Our, index)
}
return f.selectInput(f.Opp, index)
}
func (f *FightC) Ownerid() uint32 {
return f.ownerID
}
func (f *FightC) GetInputByPlayer(c common.PlayerI, isOpposite bool) *input.Input {
if c == nil {
if isOpposite {
return f.primaryOpp()
}
return f.primaryOur()
}
return f.getInputByUserID(c.GetInfo().UserID, 0, isOpposite)
}
func (f *FightC) GetInputByAction(c action.BattleActionI, isOpposite bool) *input.Input {
if c == nil {
if isOpposite {
return f.primaryOpp()
}
return f.primaryOur()
}
index := c.GetActorIndex()
if isOpposite {
index = c.GetTargetIndex()
}
return f.getInputByUserID(c.GetPlayerID(), index, isOpposite)
}
// 玩家使用技能
func (f *FightC) GetCurrPET(c common.PlayerI) *info.BattlePetEntity {
in := f.GetInputByPlayer(c, false)
if in == nil {
return nil
}
return in.PrimaryCurPet()
}
func (f *FightC) GetOpp(c common.PlayerI) *input.Input {
return f.GetInputByPlayer(c, true)
}
// // 获取随机数
func (f *FightC) IsFirst(play common.PlayerI) bool {
return f.TrueFirst.Player == play
}
func (f *FightC) GetRound() uint32 {
return f.Round
}
func (f *FightC) Chat(c common.PlayerI, msg string) {
f.GetInputByPlayer(c, true).Player.SendPackCmd(50002, &user.ChatOutboundInfo{
SenderId: c.GetInfo().UserID,
SenderNickname: c.GetInfo().Nick,
Message: utils.RemoveLast(msg),
})
}
// 加载进度
func (f *FightC) LoadPercent(c common.PlayerI, percent int32) {
if f.Info.Mode == info.BattleMode.PET_MELEE {
return
}
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC {
return
}
f.GetInputByPlayer(c, true).Player.SendPackCmd(2441, &info.LoadPercentOutboundInfo{
Id: c.GetInfo().UserID,
Percent: uint32(percent),
})
}
func (f *FightC) initplayer(c common.PlayerI, b []model.PetInfo) (*input.Input, errorcode.ErrorCode) {
r := c.CanFight()
if c.CanFight() != 0 {
return nil, r
}
in := input.NewInput(f, c)
in.AllPet = make([]*info.BattlePetEntity, 0)
in.InitAttackValue()
for i := 0; i < len(b); i++ {
//玩家精灵重置到100等级
pet := b[i]
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
}
switch f.Info.Mode {
case info.BattleMode.SINGLE_MODE:
in.AllPet = in.AllPet[:1]
default:
}
in.SetCurPetAt(0, in.AllPet[0])
return in, 0
}
// RandomElfIDs 从1-2000中随机抽取n个不重复的精灵ID
func RandomElfIDs(n int) []int {
if n <= 0 || n > 2000 {
return nil
}
// 用map记录已抽取的ID避免重复
used := make(map[int]struct{}, n)
ids := make([]int, 0, n)
for len(ids) < n {
// 生成1-2000的随机数
id := grand.Intn(2000) + 1 // rand.Intn(2000)生成0-1999+1后为1-2000
// 检查是否已抽取
if _, exists := used[id]; !exists {
used[id] = struct{}{}
ids = append(ids, id)
}
}
return ids
}
func initfightready(in *input.Input) (model.FightUserInfo, []model.ReadyFightPetInfo) {
t := make([]model.ReadyFightPetInfo, len(in.AllPet))
userindo := model.FightUserInfo{
UserID: in.UserID,
Nick: in.Player.GetInfo().Nick,
}
for i := 0; i < len(in.AllPet); i++ {
err := copier.CopyWithOption(&t[i], &in.AllPet[i].Info, copier.Option{IgnoreEmpty: true, DeepCopy: true})
if err != nil {
panic(err)
}
}
return userindo, t
}
// 被击败的ID
func (f *FightC) IsWin(c *input.Input) bool {
for _, v := range f.GetInputByPlayer(c.Player, true).AllPet {
if v.Alive() { //如果存活
return false
}
}
return true
}
// 广播,并是否结束回合
func (f *FightC) Broadcast(t func(ff *input.Input)) {
for _, ff := range f.Our {
if ff != nil {
t(ff)
}
}
for _, ff := range f.Opp {
if ff != nil {
t(ff)
}
}
}
func (f *FightC) GetOverChan() chan struct{} {
return f.over
}
func (f *FightC) GetOverInfo() model.FightOverInfo {
return f.FightOverInfo
}
func (f *FightC) GetAttackValue(b bool) *model.AttackValue {
our := f.primaryOur()
if our == nil {
return nil
}
return f.GetInputByPlayer(our.Player, b).AttackValue
}