2025-11-11 05:54:24 +00:00
|
|
|
|
package fight
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2025-12-21 17:18:33 +00:00
|
|
|
|
"blazing/common/data"
|
2025-11-19 16:11:02 +08:00
|
|
|
|
"blazing/common/socket/errorcode"
|
2025-11-25 16:36:55 +08:00
|
|
|
|
"blazing/common/utils"
|
2025-12-21 17:18:33 +00:00
|
|
|
|
"blazing/modules/config/service"
|
2026-01-19 18:51:56 +08:00
|
|
|
|
"blazing/modules/player/model"
|
2025-12-21 17:18:33 +00:00
|
|
|
|
|
2025-12-16 07:06:53 +00:00
|
|
|
|
"encoding/json"
|
2025-11-15 22:17:43 +00:00
|
|
|
|
|
2025-11-11 05:54:24 +00:00
|
|
|
|
"blazing/logic/service/common"
|
|
|
|
|
|
"blazing/logic/service/fight/action"
|
|
|
|
|
|
"blazing/logic/service/fight/info"
|
|
|
|
|
|
"blazing/logic/service/fight/input"
|
2025-11-25 16:36:55 +08:00
|
|
|
|
"blazing/logic/service/user"
|
2025-11-11 05:54:24 +00:00
|
|
|
|
"math/rand"
|
2025-11-11 15:21:45 +00:00
|
|
|
|
"sync"
|
2025-11-11 05:54:24 +00:00
|
|
|
|
"time"
|
|
|
|
|
|
|
2025-11-23 23:38:03 +00:00
|
|
|
|
"github.com/gogf/gf/v2/util/grand"
|
2025-11-11 05:54:24 +00:00
|
|
|
|
"github.com/jinzhu/copier"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
type FightC struct {
|
2025-11-29 19:26:56 +08:00
|
|
|
|
//准备战斗信息
|
|
|
|
|
|
ReadyInfo info.NoteReadyToFightInfo
|
|
|
|
|
|
//开始战斗信息
|
|
|
|
|
|
info.FightStartOutboundInfo
|
2025-11-20 15:19:13 +08:00
|
|
|
|
Info info.Fightinfo
|
|
|
|
|
|
IsReady bool
|
|
|
|
|
|
ownerID uint32 // 战斗发起者ID
|
|
|
|
|
|
Our *input.Input //始终等于房主ID
|
|
|
|
|
|
Opp *input.Input //对手ID
|
2025-12-01 23:31:48 +08:00
|
|
|
|
Switch map[uint32]*action.ActiveSwitchAction
|
2025-11-20 15:19:13 +08:00
|
|
|
|
startl sync.Once
|
2025-11-11 05:54:24 +00:00
|
|
|
|
rand *rand.Rand
|
|
|
|
|
|
StartTime time.Time
|
|
|
|
|
|
actionChan chan action.BattleActionI // 所有操作统一从这里进入
|
2025-12-10 18:37:32 +00:00
|
|
|
|
|
2025-11-11 11:45:09 +00:00
|
|
|
|
quit chan struct{}
|
2025-11-12 01:19:24 +08:00
|
|
|
|
over chan struct{}
|
2025-11-11 05:54:24 +00:00
|
|
|
|
First *input.Input
|
2025-12-31 03:16:58 +08:00
|
|
|
|
TrueFirst *input.Input
|
2025-11-11 05:54:24 +00:00
|
|
|
|
Second *input.Input
|
|
|
|
|
|
closefight bool
|
2025-11-11 15:21:45 +00:00
|
|
|
|
overl sync.Once
|
2025-11-13 02:43:00 +08:00
|
|
|
|
waittime int
|
2025-11-11 05:54:24 +00:00
|
|
|
|
info.FightOverInfo
|
2025-11-15 23:02:46 +00:00
|
|
|
|
//战斗结束的插装
|
2026-01-03 02:18:31 +08:00
|
|
|
|
callback func(info.FightOverInfo)
|
2025-11-11 05:54:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (f *FightC) Ownerid() uint32 {
|
|
|
|
|
|
|
|
|
|
|
|
return f.ownerID
|
|
|
|
|
|
}
|
|
|
|
|
|
func (f *FightC) GetInputByPlayer(c common.PlayerI, isOpposite bool) *input.Input {
|
|
|
|
|
|
// 判断当前玩家是否为我方玩家
|
|
|
|
|
|
isOurPlayer := c.GetInfo().UserID == f.ownerID
|
|
|
|
|
|
|
|
|
|
|
|
// 当isOurPlayer与isOpposite值不同时返回我方,相同时返回对方
|
|
|
|
|
|
if isOurPlayer != isOpposite {
|
|
|
|
|
|
return f.Our
|
|
|
|
|
|
}
|
|
|
|
|
|
return f.Opp
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (f *FightC) GetInputByAction(c action.BattleActionI, isOpposite bool) *input.Input {
|
|
|
|
|
|
// 判断动作所属玩家是否为我方
|
|
|
|
|
|
isOurAction := c.GetPlayerID() == f.Our.Player.GetInfo().UserID
|
|
|
|
|
|
|
|
|
|
|
|
// 根据isOpposite决定是否返回相反方向的输入
|
|
|
|
|
|
if isOurAction == !isOpposite {
|
|
|
|
|
|
return f.Our
|
|
|
|
|
|
}
|
|
|
|
|
|
return f.Opp
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 玩家使用技能
|
|
|
|
|
|
func (f *FightC) GetCurrPET(c common.PlayerI) *info.BattlePetEntity {
|
|
|
|
|
|
if f.Our.Player.GetInfo().UserID == c.GetInfo().UserID {
|
|
|
|
|
|
return f.Our.CurrentPet
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return f.Opp.CurrentPet
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
func (f *FightC) GetOpp(c common.PlayerI) *input.Input {
|
|
|
|
|
|
return f.GetInputByPlayer(c, true)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取随机数
|
|
|
|
|
|
func (f *FightC) GetRand() *rand.Rand {
|
|
|
|
|
|
|
|
|
|
|
|
return f.rand
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取随机数
|
|
|
|
|
|
func (f *FightC) IsFirst(play common.PlayerI) bool {
|
|
|
|
|
|
|
2025-12-31 03:16:58 +08:00
|
|
|
|
return f.TrueFirst.Player == play
|
2025-11-11 05:54:24 +00:00
|
|
|
|
}
|
2025-11-25 16:36:55 +08:00
|
|
|
|
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),
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2025-11-11 05:54:24 +00:00
|
|
|
|
|
|
|
|
|
|
// 加载进度
|
|
|
|
|
|
func (f *FightC) LoadPercent(c common.PlayerI, percent int32) {
|
2025-11-25 16:36:55 +08:00
|
|
|
|
if f.Info.Mode == info.BattleMode.PET_MELEE {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2025-11-19 16:11:02 +08:00
|
|
|
|
f.GetInputByPlayer(c, true).Player.SendPackCmd(2441, &info.LoadPercentOutboundInfo{
|
2025-11-11 05:54:24 +00:00
|
|
|
|
Id: c.GetInfo().UserID,
|
|
|
|
|
|
Percent: uint32(percent),
|
|
|
|
|
|
})
|
2025-11-18 20:52:04 +00:00
|
|
|
|
|
2025-11-11 05:54:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-25 16:36:55 +08:00
|
|
|
|
var meetpet = make(map[int]model.PetInfo)
|
|
|
|
|
|
|
2025-11-20 05:57:29 +08:00
|
|
|
|
func (f *FightC) initplayer(c common.PlayerI) (*input.Input, errorcode.ErrorCode) {
|
2025-11-11 05:54:24 +00:00
|
|
|
|
|
2025-11-20 05:57:29 +08:00
|
|
|
|
if !c.CanFight() {
|
|
|
|
|
|
return nil, errorcode.ErrorCodes.ErrNoEligiblePokemon
|
2025-11-11 05:54:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-15 01:53:51 +08:00
|
|
|
|
in := input.NewInput(f, c)
|
|
|
|
|
|
in.AllPet = make([]*info.BattlePetEntity, 0)
|
|
|
|
|
|
in.InitAttackValue()
|
2025-11-11 05:54:24 +00:00
|
|
|
|
for i := 0; i < len(c.GetInfo().PetList); i++ {
|
2025-11-15 23:02:46 +00:00
|
|
|
|
in.AllPet = append(in.AllPet, info.CreateBattlePetEntity(c.GetInfo().PetList[i], f.rand))
|
2025-11-11 05:54:24 +00:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-15 01:53:51 +08:00
|
|
|
|
in.SortPet()
|
2025-12-16 06:54:27 +00:00
|
|
|
|
if len(in.AllPet) == 0 {
|
|
|
|
|
|
return nil, errorcode.ErrorCodes.ErrNoEligiblePokemon
|
|
|
|
|
|
}
|
2025-11-11 05:54:24 +00:00
|
|
|
|
|
|
|
|
|
|
switch f.Info.Mode {
|
|
|
|
|
|
case info.BattleMode.SINGLE_MODE:
|
2025-11-15 01:53:51 +08:00
|
|
|
|
in.AllPet = in.AllPet[:1]
|
|
|
|
|
|
case info.BattleMode.PET_MELEE:
|
|
|
|
|
|
in.AllPet = make([]*info.BattlePetEntity, 0)
|
2025-12-16 06:54:27 +00:00
|
|
|
|
// if len(meetpet) == 0 {
|
|
|
|
|
|
// initmeetpet()
|
|
|
|
|
|
// }
|
2025-12-15 14:26:24 +08:00
|
|
|
|
r := service.NewMELEEService().Def()
|
2025-12-16 06:54:27 +00:00
|
|
|
|
if len(r) == 0 {
|
|
|
|
|
|
return nil, errorcode.ErrorCodes.ErrNoEligiblePokemon
|
|
|
|
|
|
}
|
2025-12-15 14:26:24 +08:00
|
|
|
|
for i, v := range r {
|
|
|
|
|
|
|
|
|
|
|
|
if v.Lv == 0 {
|
|
|
|
|
|
v.Lv = 100
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
// var effect int
|
|
|
|
|
|
// if len(v.Effect) > 0 {
|
|
|
|
|
|
// effect = int(v.Effect[0])
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
pet := model.GenPetInfo(int(v.MonID), 24, int(v.Nature), int(v.Effect[0]), int(v.Lv), nil)
|
2025-12-21 17:18:33 +00:00
|
|
|
|
var color data.GlowFilter
|
2025-12-16 07:06:53 +00:00
|
|
|
|
err := json.Unmarshal([]byte(v.Color), &color)
|
|
|
|
|
|
if err == nil {
|
|
|
|
|
|
pet.ShinyInfo = append(pet.ShinyInfo, color)
|
2025-12-15 14:26:24 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
if len(v.Prop) == 5 {
|
|
|
|
|
|
|
|
|
|
|
|
pet.Prop = [5]uint32(v.Prop)
|
|
|
|
|
|
|
2025-12-15 15:09:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if v.Hp != 0 {
|
|
|
|
|
|
pet.MaxHp = uint32(v.Hp)
|
|
|
|
|
|
|
2025-12-15 14:26:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
if len(v.SKill) != 0 {
|
|
|
|
|
|
|
|
|
|
|
|
for i := 0; i < 4; i++ {
|
|
|
|
|
|
if v.SKill[i] != 0 {
|
|
|
|
|
|
pet.SkillList[i].ID = v.SKill[i]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-25 16:36:55 +08:00
|
|
|
|
}
|
2025-12-15 14:26:24 +08:00
|
|
|
|
pet.CatchTime = c.GetInfo().UserID + uint32(i)*1000000
|
|
|
|
|
|
pet.Cure()
|
|
|
|
|
|
in.AllPet = append(in.AllPet, info.CreateBattlePetEntity(*pet, f.rand))
|
2025-11-15 01:53:51 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
2025-12-15 14:26:24 +08:00
|
|
|
|
// for i, v := range meetpet {
|
|
|
|
|
|
// v1 := v
|
|
|
|
|
|
// if len(in.AllPet) > 2 {
|
|
|
|
|
|
// break
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// v1.CatchTime = c.GetInfo().UserID + uint32(i)*1000000
|
|
|
|
|
|
// v1.Cure()
|
|
|
|
|
|
// in.AllPet = append(in.AllPet, info.CreateBattlePetEntity(v1, f.rand))
|
|
|
|
|
|
// }
|
2025-11-25 16:36:55 +08:00
|
|
|
|
|
2025-11-15 01:53:51 +08:00
|
|
|
|
//in.AllPet = in.AllPet[:3]
|
2025-11-11 05:54:24 +00:00
|
|
|
|
default:
|
|
|
|
|
|
}
|
2025-11-13 02:43:00 +08:00
|
|
|
|
|
2025-11-15 01:53:51 +08:00
|
|
|
|
in.CurrentPet = in.AllPet[0]
|
2025-11-20 05:57:29 +08:00
|
|
|
|
return in, 0
|
2025-11-15 01:53:51 +08:00
|
|
|
|
}
|
2025-11-11 05:54:24 +00:00
|
|
|
|
|
2025-11-15 01:53:51 +08:00
|
|
|
|
// RandomElfIDs 从1-2000中随机抽取n个不重复的精灵ID
|
|
|
|
|
|
func RandomElfIDs(n int) []int {
|
|
|
|
|
|
if n <= 0 || n > 2000 {
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
2025-11-11 05:54:24 +00:00
|
|
|
|
|
2025-11-15 01:53:51 +08:00
|
|
|
|
// 用map记录已抽取的ID,避免重复
|
|
|
|
|
|
used := make(map[int]struct{}, n)
|
|
|
|
|
|
ids := make([]int, 0, n)
|
2025-11-11 05:54:24 +00:00
|
|
|
|
|
2025-11-15 01:53:51 +08:00
|
|
|
|
for len(ids) < n {
|
|
|
|
|
|
// 生成1-2000的随机数
|
2025-11-23 23:38:03 +00:00
|
|
|
|
id := grand.Intn(2000) + 1 // rand.Intn(2000)生成0-1999,+1后为1-2000
|
2025-11-11 05:54:24 +00:00
|
|
|
|
|
2025-11-15 01:53:51 +08:00
|
|
|
|
// 检查是否已抽取
|
|
|
|
|
|
if _, exists := used[id]; !exists {
|
|
|
|
|
|
used[id] = struct{}{}
|
|
|
|
|
|
ids = append(ids, id)
|
2025-11-11 05:54:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-15 01:53:51 +08:00
|
|
|
|
return ids
|
|
|
|
|
|
}
|
|
|
|
|
|
func initfightready(in *input.Input) (info.FightUserInfo, []info.ReadyFightPetInfo) {
|
|
|
|
|
|
t := make([]info.ReadyFightPetInfo, len(in.AllPet))
|
|
|
|
|
|
userindo := info.FightUserInfo{
|
|
|
|
|
|
UserID: in.UserID,
|
|
|
|
|
|
Nick: in.Player.GetInfo().Nick,
|
|
|
|
|
|
}
|
2025-11-11 05:54:24 +00:00
|
|
|
|
|
2025-11-15 01:53:51 +08:00
|
|
|
|
for i := 0; i < len(in.AllPet); i++ {
|
2025-11-11 05:54:24 +00:00
|
|
|
|
|
2025-11-15 01:53:51 +08:00
|
|
|
|
err := copier.CopyWithOption(&t[i], &in.AllPet[i].Info, copier.Option{IgnoreEmpty: true, DeepCopy: true})
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
panic(err)
|
|
|
|
|
|
}
|
2025-11-11 05:54:24 +00:00
|
|
|
|
}
|
2025-11-12 01:19:24 +08:00
|
|
|
|
|
2025-11-15 01:53:51 +08:00
|
|
|
|
return userindo, t
|
2025-11-11 05:54:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 被击败的ID
|
2025-12-23 13:53:34 +00:00
|
|
|
|
func (f *FightC) IsWin(c *input.Input) bool {
|
2025-11-11 05:54:24 +00:00
|
|
|
|
|
2025-12-23 13:53:34 +00:00
|
|
|
|
for _, v := range f.GetInputByPlayer(c.Player, true).AllPet {
|
2025-11-11 05:54:24 +00:00
|
|
|
|
if !v.NotAlive { //如果存活
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 广播,并是否结束回合
|
|
|
|
|
|
func (f *FightC) Broadcast(t func(ff *input.Input)) {
|
|
|
|
|
|
|
|
|
|
|
|
t(f.Our)
|
|
|
|
|
|
t(f.Opp)
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2025-11-12 01:19:24 +08:00
|
|
|
|
|
|
|
|
|
|
func (f *FightC) GetOverChan() chan struct{} {
|
|
|
|
|
|
return f.over
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2025-12-10 18:37:32 +00:00
|
|
|
|
func (f *FightC) GetOverInfo() info.FightOverInfo {
|
|
|
|
|
|
return f.FightOverInfo
|
|
|
|
|
|
|
|
|
|
|
|
}
|