refactor(fight): 重构战斗模块
- 移除未使用的结构体和接口 - 优化战斗准备和邀请逻辑 - 调整玩家和怪物信息的处理方式 - 更新战斗相关的数据结构 - 重构战斗模式和邀请相关代码
This commit is contained in:
@@ -2,9 +2,9 @@ package socket
|
||||
|
||||
import (
|
||||
"blazing/common/utils"
|
||||
|
||||
"blazing/modules/blazing/model"
|
||||
"blazing/modules/blazing/service"
|
||||
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
@@ -41,6 +41,16 @@ func (c *Conn) SendPack(bytes []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type OgreInfo struct {
|
||||
Data [9]OgrePetInfo
|
||||
}
|
||||
|
||||
type OgrePetInfo struct {
|
||||
Id uint32
|
||||
Shiny uint32
|
||||
Lv uint32 `struc:"skip"` //等级
|
||||
}
|
||||
|
||||
type Player struct {
|
||||
MainConn *Conn
|
||||
|
||||
@@ -54,6 +64,9 @@ type Player struct {
|
||||
context.Context
|
||||
Playerinvite uint32 //当前邀请的玩家ID
|
||||
Onlinetime uint32 //当前登录时间
|
||||
OgreInfo *OgreInfo
|
||||
FightID string //绑定战斗标识
|
||||
//FightInfo info.NoteReadyToFightInfo
|
||||
}
|
||||
|
||||
// PlayerOption 定义配置 Player 的函数类型
|
||||
|
||||
@@ -4,6 +4,9 @@ import (
|
||||
"blazing/common/data/socket"
|
||||
"blazing/common/socket/errorcode"
|
||||
"blazing/common/socket/handler"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"blazing/logic/service/fight"
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/modules/blazing/model"
|
||||
@@ -11,15 +14,15 @@ import (
|
||||
"github.com/jinzhu/copier"
|
||||
)
|
||||
|
||||
func (h Controller) OnPlayerFightNpcMonster(data *fight.FightNpcMonsterInboundInfo, c *socket.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
func (h Controller) OnPlayerFightNpcMonster(data *info.FightNpcMonsterInboundInfo, c *socket.Player) (result *info.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
c.IsFighting = true
|
||||
t1 := handler.NewTomeeHeader(2503, c.Info.UserID)
|
||||
|
||||
ttt := info.NoteReadyToFightInfo{
|
||||
OwnerID: data.Head.UserID,
|
||||
FightId: 3,
|
||||
}
|
||||
ttt.OurInfo = info.FightUserInfo{UserID: c.Info.UserID, Nick: c.Info.Nick}
|
||||
|
||||
copier.Copy(&ttt.OurInfo, &c.Info)
|
||||
len := len(c.Info.PetList)
|
||||
ttt.OurPetList = make([]info.ReadyFightPetInfo, len)
|
||||
for i := 0; i < len; i++ {
|
||||
@@ -31,61 +34,49 @@ func (h Controller) OnPlayerFightNpcMonster(data *fight.FightNpcMonsterInboundIn
|
||||
}
|
||||
|
||||
ttt.OpponentInfo = info.FightUserInfo{UserID: 0}
|
||||
ttt.OpponentPetList = []info.ReadyFightPetInfo{{ID: 1,
|
||||
Level: 100,
|
||||
MaxHp: 100,
|
||||
SkillListLen: 4,
|
||||
Hp: 100}}
|
||||
for i := 0; i < 4; i++ {
|
||||
ttt.OpponentPetList[0].SkillList[i] = model.SkillInfo{ID: 10001, Pp: 1}
|
||||
refpet := c.OgreInfo.Data[data.Number]
|
||||
|
||||
dv := rand.New(rand.NewSource(time.Now().UnixNano())).Intn(32)
|
||||
mo := model.GenPetInfo(refpet.Id, uint32(dv), 0, 1006, refpet.Shiny, refpet.Lv)
|
||||
ttt.OpponentPetList = make([]info.ReadyFightPetInfo, 1)
|
||||
|
||||
err1 := copier.CopyWithOption(&ttt.OpponentPetList[0], &mo, copier.Option{IgnoreEmpty: true, DeepCopy: true})
|
||||
if err1 != nil {
|
||||
panic(err)
|
||||
}
|
||||
c.SendPack(t1.Pack(&ttt))
|
||||
|
||||
fight.NewFight(&ttt, c) //把两个玩家都传进去
|
||||
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// 准备战斗
|
||||
func (h Controller) OnReadyToFight(data *fight.ReadyToFightInboundInfo, c *socket.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
func (h Controller) OnReadyToFight(data *info.ReadyToFightInboundInfo, c *socket.Player) (result *info.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
|
||||
t1 := handler.NewTomeeHeader(2504, c.Info.UserID)
|
||||
rett := fight.FightStartOutboundInfo{
|
||||
IsCanAuto: 0,
|
||||
|
||||
Info2: fight.FightPetInfo{
|
||||
UserID: 0,
|
||||
ID: 1,
|
||||
Hp: 1000,
|
||||
MaxHp: 1000,
|
||||
Level: 1,
|
||||
CatchTime: 0,
|
||||
Catchable: 1,
|
||||
BattleLV: [6]byte{1, 1, 1, 1, 1, 1}},
|
||||
}
|
||||
copier.Copy(&rett.Info1, &c.Info.PetList[0])
|
||||
rett.Info1.UserID = c.Info.UserID
|
||||
c.SendPack(t1.Pack(&rett))
|
||||
fight.ReadyFight(c)
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// 接收战斗或者取消战斗的包
|
||||
func (h Controller) OnPlayerHandleFightInvite(data *fight.HandleFightInviteInboundInfo, c *socket.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
func (h Controller) OnPlayerHandleFightInvite(data *info.HandleFightInviteInboundInfo, c *socket.Player) (result *info.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// 使用技能包
|
||||
func (h Controller) UseSkill(data *fight.UseSkillInboundInfo, c *socket.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
func (h Controller) UseSkill(data *info.UseSkillInboundInfo, c *socket.Player) (result *info.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
// 战斗逃跑
|
||||
func (h Controller) Escape(data *fight.EscapeFightInboundInfo, c *socket.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
func (h Controller) Escape(data *info.EscapeFightInboundInfo, c *socket.Player) (result *info.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
|
||||
defer func() {
|
||||
//战斗结束Escape
|
||||
ttt := handler.NewTomeeHeader(2506, c.Info.UserID)
|
||||
|
||||
c.SendPack(ttt.Pack(&fight.FightOverInfo{
|
||||
c.SendPack(ttt.Pack(&info.FightOverInfo{
|
||||
Reason: 0,
|
||||
}))
|
||||
c.IsFighting = false
|
||||
|
||||
@@ -26,7 +26,7 @@ func (h Controller) OnGetRoomPetShowInfo(data *room.PetRoomListInboundInfo, c *s
|
||||
// 获取自己房间的家具
|
||||
func (h Controller) OnGetFitmentAll(data *room.FitmentAllInboundEmpty, c *socket.Player) (result *room.FitmentAllOutboundInfo, err errorcode.ErrorCode) {
|
||||
result = &room.FitmentAllOutboundInfo{}
|
||||
result.Fitments = make([]room.FitmentShowInfo, 0)
|
||||
result.Fitments = append(result.Fitments, room.FitmentShowInfo{Id: 500001, Status: 1, X: 1, Y: 1, Dir: 1})
|
||||
result.Fitments = make([]room.FitmentItemInfo, 0)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
package fight
|
||||
|
||||
import "blazing/logic/service/fight/info"
|
||||
|
||||
func NewBattle(i info.NoteReadyToFightInfo) {
|
||||
//调用技能产生effect参数后,创建effect实例,而非技能创建
|
||||
c := info.NewBattleContainer1v1(i) //创建战斗容器
|
||||
t := info.BattleSkillEntity{} //
|
||||
t.SideEffectArgs = []int{1, 2, 3}
|
||||
//先提交effecet后然后计算伤害
|
||||
|
||||
//物理和特殊,百分比和固定伤害也算,真实伤害不分类别,故直接扣血就行,不需要计算
|
||||
if t.Category() == info.Category.PHYSICAL || t.Category() == info.Category.SPECIAL {
|
||||
c.Effects.Exec(func(e info.Effect) bool {
|
||||
return e.PreDamage() //执行预处理效果
|
||||
})
|
||||
|
||||
// Apply pre-damage effects for pet sources
|
||||
// battle.applyEffects(context, EffectTrigger.PreDamage)
|
||||
// if (context.crit) {
|
||||
// battle.applyEffects(context, EffectTrigger.OnCritPreDamage) // Trigger crit pre-damage effects
|
||||
// }
|
||||
//假如说这里需要能力提升
|
||||
// c.Exec(func(e Effect) func() {
|
||||
// return e.OnBeforeAddMark()
|
||||
// })
|
||||
//添加印记前的效果如果有任何一个false,说明组织了添加效果
|
||||
//这里能力提升
|
||||
// c.Exec(func(e Effect) bool {
|
||||
// return e.OnAnyMarkAdded()
|
||||
// })
|
||||
|
||||
// var candidates []*Effect
|
||||
// for _, eff := range c.Effects {
|
||||
// if eff.Trigger == trigger {
|
||||
// candidates = append(candidates, eff)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 按优先级排序
|
||||
// sort.SliceStable(candidates, func(i, j int) bool {
|
||||
// return candidates[i].Priority > candidates[j].Priority
|
||||
// })
|
||||
|
||||
// // 执行
|
||||
// for _, eff := range candidates {
|
||||
// ctx.Effect = eff
|
||||
// keep := eff.Apply(ctx)
|
||||
|
||||
// if !keep {
|
||||
// // 持续回合结束 / 返回 false 的 effect 删除
|
||||
// c.removeEffect(eff)
|
||||
// }
|
||||
|
||||
// if ctx.Done {
|
||||
// break // 被拦截
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,102 +1,127 @@
|
||||
package fight
|
||||
|
||||
import (
|
||||
"blazing/common/data/socket"
|
||||
"blazing/common/socket/handler"
|
||||
"blazing/modules/blazing/model"
|
||||
"blazing/logic/service/fight/info"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jinzhu/copier"
|
||||
)
|
||||
|
||||
// 野怪对战包
|
||||
type FightNpcMonsterInboundInfo struct {
|
||||
Head handler.TomeeHeader `cmd:"2408" struc:"[0]pad"`
|
||||
// Number 地图刷新怪物结构体对应的序号(1-9的位置序号)
|
||||
// @UInt long类型,使用uint32保持无符号特性
|
||||
Number uint32 `fieldDesc:"地图刷新怪物结构体对应的序号 1 - 9 的位置序号" `
|
||||
var FightCache = make(map[string]*info.NoteReadyToFightInfo) //默认our是房主
|
||||
|
||||
func ReadyFight(c *socket.Player) {
|
||||
tt, _ := FightCache[c.FightID]
|
||||
t1 := handler.NewTomeeHeader(2504, c.Info.UserID)
|
||||
rett := info.FightStartOutboundInfo{
|
||||
IsCanAuto: 0,
|
||||
}
|
||||
copier.Copy(&rett.Info1, &c.Info.PetList[0]) //复制自己的信息
|
||||
switch tt.FightId { //判断战斗类型
|
||||
case 1:
|
||||
//1v1
|
||||
|
||||
if c.Info.UserID == tt.OwnerID { //这个时候是房主发来的消息
|
||||
tt.AFinished = true
|
||||
if tt.BFinished {
|
||||
|
||||
copier.Copy(&rett.Info2, &tt.OpponentPetList[0]) //复制对方信息
|
||||
c.SendPack(t1.Pack(&rett)) //给自己发
|
||||
tt.Opp.SendPack(t1.Pack(&rett)) //给对方发
|
||||
}
|
||||
|
||||
} else {
|
||||
tt.BFinished = true
|
||||
if tt.AFinished { //如果房主完成
|
||||
|
||||
copier.Copy(&rett.Info2, &tt.OurPetList[0]) //复制房主信息,因为这时候不是房主发来的消息
|
||||
c.SendPack(t1.Pack(&rett)) //给自己发
|
||||
tt.Our.SendPack(t1.Pack(&rett)) //给房主发
|
||||
}
|
||||
}
|
||||
|
||||
case 3: //野怪战斗
|
||||
|
||||
copier.Copy(&rett.Info2, &tt.OpponentPetList[0])
|
||||
rett.Info1.UserID = c.Info.UserID //用户ID复制进去
|
||||
c.SendPack(t1.Pack(&rett))
|
||||
}
|
||||
|
||||
}
|
||||
func NewFight(i *info.NoteReadyToFightInfo, plays *socket.Player) {
|
||||
|
||||
t12, _ := uuid.NewV7()
|
||||
uuid := strings.Replace(t12.String(), "-", "", -1) //绑定战斗ID
|
||||
FightCache[uuid] = i
|
||||
//先发送战斗准备包
|
||||
switch i.FightId {
|
||||
case 1:
|
||||
//1v1
|
||||
|
||||
case 3: //野怪战斗
|
||||
|
||||
t1 := handler.NewTomeeHeader(2503, plays.Info.UserID)
|
||||
|
||||
plays.FightID = uuid //绑定战斗ID
|
||||
plays.SendPack(t1.Pack(i)) //准备包由各自发,因为协议不一样
|
||||
|
||||
}
|
||||
|
||||
//调用技能产生effect参数后,创建effect实例,而非技能创建
|
||||
c := info.NewBattleContainer1v1(*i) //创建战斗容器
|
||||
t := info.BattleSkillEntity{} //
|
||||
t.SideEffectArgs = []int{1, 2, 3}
|
||||
//先提交effecet后然后计算伤害
|
||||
|
||||
//物理和特殊,百分比和固定伤害也算,真实伤害不分类别,故直接扣血就行,不需要计算
|
||||
if t.Category() == info.Category.PHYSICAL || t.Category() == info.Category.SPECIAL {
|
||||
c.Effects.Exec(func(e info.Effect) bool {
|
||||
return e.PreDamage() //执行预处理效果
|
||||
})
|
||||
|
||||
// Apply pre-damage effects for pet sources
|
||||
// battle.applyEffects(context, EffectTrigger.PreDamage)
|
||||
// if (context.crit) {
|
||||
// battle.applyEffects(context, EffectTrigger.OnCritPreDamage) // Trigger crit pre-damage effects
|
||||
// }
|
||||
//假如说这里需要能力提升
|
||||
// c.Exec(func(e Effect) func() {
|
||||
// return e.OnBeforeAddMark()
|
||||
// })
|
||||
//添加印记前的效果如果有任何一个false,说明组织了添加效果
|
||||
//这里能力提升
|
||||
// c.Exec(func(e Effect) bool {
|
||||
// return e.OnAnyMarkAdded()
|
||||
// })
|
||||
|
||||
// var candidates []*Effect
|
||||
// for _, eff := range c.Effects {
|
||||
// if eff.Trigger == trigger {
|
||||
// candidates = append(candidates, eff)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 按优先级排序
|
||||
// sort.SliceStable(candidates, func(i, j int) bool {
|
||||
// return candidates[i].Priority > candidates[j].Priority
|
||||
// })
|
||||
|
||||
// // 执行
|
||||
// for _, eff := range candidates {
|
||||
// ctx.Effect = eff
|
||||
// keep := eff.Apply(ctx)
|
||||
|
||||
// if !keep {
|
||||
// // 持续回合结束 / 返回 false 的 effect 删除
|
||||
// c.removeEffect(eff)
|
||||
// }
|
||||
|
||||
// if ctx.Done {
|
||||
// break // 被拦截
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
type NullOutboundInfo struct {
|
||||
}
|
||||
|
||||
// 准备战斗包
|
||||
type ReadyToFightInboundInfo struct {
|
||||
Head handler.TomeeHeader `cmd:"2404" struc:"[0]pad"`
|
||||
}
|
||||
|
||||
type FightStartOutboundInfo struct {
|
||||
// @UInt long类型
|
||||
IsCanAuto uint32 `fieldDesc:"是否自动 默认给0 怀疑是自动战斗器使用的" `
|
||||
|
||||
// 当前战斗精灵信息1(前端通过userid判断是否为我方)
|
||||
Info1 FightPetInfo `fieldDesc:"当前战斗精灵的信息 可能不准.看前端代码是以userid来判断哪个结构体是我方的" serialize:"struct"`
|
||||
|
||||
// 当前战斗精灵信息2(前端通过userid判断是否为我方)
|
||||
Info2 FightPetInfo `fieldDesc:"当前战斗精灵的信息 可能不准.看前端代码是以userid来判断哪个结构体是我方的" serialize:"struct"`
|
||||
}
|
||||
|
||||
// FightPetInfo 战斗精灵信息结构体,FightPetInfo类
|
||||
type FightPetInfo struct {
|
||||
// 用户ID(野怪为0),@UInt long
|
||||
UserID uint32 `fieldDesc:"用户ID 野怪为0" `
|
||||
|
||||
// 当前对战精灵ID,@UInt long
|
||||
ID uint32 `fieldDesc:"当前对战精灵ID" `
|
||||
|
||||
Name string `struc:"[16]byte"`
|
||||
// 精灵的捕获时间,@UInt long
|
||||
CatchTime uint32 `fieldDesc:"精灵的捕获时间" `
|
||||
|
||||
// 当前HP,@UInt long
|
||||
Hp uint32 `fieldDesc:"当前HP" `
|
||||
|
||||
// 最大HP,@UInt long
|
||||
MaxHp uint32 `fieldDesc:"最大HP" `
|
||||
|
||||
// 当前等级,@UInt long
|
||||
Level uint32 `fieldDesc:"当前等级" `
|
||||
|
||||
// 精灵是否能捕捉(1为能捕捉,0为不能捕捉),@UInt long
|
||||
Catchable uint32 `fieldDesc:"精灵是否能捕捉. 1为能捕捉 0为不能捕捉" `
|
||||
|
||||
// 战斗属性等级数组(6个单字节)
|
||||
// byte[],固定长度6,存储buff等级、攻击、速度等属性
|
||||
BattleLV [6]byte `fieldDesc:"这里实际上应该是6个单字节byte, 内容为buff等级 攻击 速度 特攻 防御 特防 命中等.但具体顺序未知可能需要测试. 具体数值为1-6等级" serialize:"fixedLength=6,type=byteArray"`
|
||||
}
|
||||
|
||||
// AttackValue 战斗中的攻击数值信息
|
||||
type AttackValue struct {
|
||||
UserID uint32 `json:"userId" fieldDescription:"玩家的米米号 与野怪对战userid = 0"`
|
||||
SkillID uint32 `json:"skillId" fieldDescription:"使用技能的id"`
|
||||
AttackTime uint32 `json:"attackTime" fieldDescription:"是否击中 如果为0 则miss 如果为1 则击中"`
|
||||
LostHp uint32 `json:"lostHp" fieldDescription:"我方造成的伤害"`
|
||||
GainHp uint32 `json:"gainHp" fieldDescription:"我方获得血量"`
|
||||
RemainHp uint32 `json:"remainHp" fieldDescription:"我方剩余血量"`
|
||||
MaxHp uint32 `json:"maxHp" fieldDescription:"我方最大血量"`
|
||||
State uint32 `json:"state" fieldDescription:"固定值0 需要后续测试"`
|
||||
SkillList []model.SkillInfo `json:"skillList" fieldDescription:"根据精灵的数据插入技能 最多4条 不定长"`
|
||||
IsCritical uint32 `json:"isCritical" fieldDescription:"是否暴击"`
|
||||
Status [20]byte `json:"status" fieldDescription:"20个字节 各种状态: 0:\"麻痹\",1:\"中毒\",2:\"烧伤\",4:\"寄生\",5:\"冻伤\",6:\"害怕\",7:\"疲惫\",8:\"睡眠\",9:\"石化\",10:\"混乱\",15:\"冰封\",16:\"流血\""`
|
||||
BattleLv [6]byte `json:"battleLv" fieldDescription:"6个单字节byte, 内容为buff等级 攻击 速度 特攻 防御 特防命中等. 但具体顺序未知可能需要测试. 具体数值为1-6等级"`
|
||||
// OwnerMaxShield uint32 `json:"ownerMaxShield" fieldDescription:"我方最大护盾"`
|
||||
// OwnerCurrentShield uint32 `json:"ownerCurrentShield" fieldDescription:"我方当前护盾"`
|
||||
}
|
||||
|
||||
// NoteUseSkillOutboundInfo 战斗技能使用通知的出站信息结构体
|
||||
type NoteUseSkillOutboundInfo struct {
|
||||
FirstAttackInfo AttackValue // 本轮先手的精灵在释放技能结束后的状态
|
||||
SecondAttackInfo AttackValue // 本轮后手的精灵在释放技能结束后的状态
|
||||
}
|
||||
|
||||
// 战斗逃跑
|
||||
type EscapeFightInboundInfo struct {
|
||||
Head handler.TomeeHeader `cmd:"2410" struc:"[0]pad"`
|
||||
}
|
||||
|
||||
// FightOverInfo 战斗结束信息结构体 2506
|
||||
type FightOverInfo struct {
|
||||
Reason uint32 // 固定值0
|
||||
WinnerId uint32 // 胜者的米米号 野怪为0
|
||||
TwoTimes uint32 // 双倍经验剩余次数
|
||||
ThreeTimes uint32 // 三倍经验剩余次数
|
||||
AutoFightTimes uint32 // 自动战斗剩余次数
|
||||
EnergyTimes uint32 // 能量吸收器剩余次数
|
||||
LearnTimes uint32 // 双倍学习器剩余次数
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
const Input_ctx = "player"
|
||||
|
||||
type BattleInputSourceEntity struct {
|
||||
FightUserInfo //用户信息
|
||||
FightUserInfo //用户信息
|
||||
PetEntities []*BattlePetEntity //宠物信息
|
||||
ctx context.Context //输入源的上下文
|
||||
ctx context.Context //输入源的上下文
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
package info
|
||||
|
||||
import (
|
||||
"blazing/modules/blazing/model"
|
||||
)
|
||||
|
||||
type FightUserInfo struct {
|
||||
// 用户ID(野怪为0),@UInt long
|
||||
UserID uint32 `fieldDesc:"userID 如果为野怪则为0" `
|
||||
|
||||
// 玩家名称(野怪为UTF-8的'-',固定16字节)
|
||||
// 使用[16]byte存储固定长度的字节数组
|
||||
Nick string `struc:"[16]byte"`
|
||||
}
|
||||
|
||||
// NoteReadyToFightInfo 战斗准备就绪消息结构体,NoteReadyToFightInfo
|
||||
type NoteReadyToFightInfo struct {
|
||||
//战斗发起者ID
|
||||
OwnerID uint32 `struc:"skip"`
|
||||
// 战斗类型ID(与野怪战斗为3,与人战斗为1,前端似乎未使用)
|
||||
// @UInt long
|
||||
FightId uint32 `fieldDesc:"战斗类型ID 但前端好像没有用到 与野怪战斗为3,与人战斗似乎是1" `
|
||||
|
||||
// 我方信息
|
||||
OurInfo FightUserInfo `fieldDesc:"我方信息" serialize:"struct"`
|
||||
OurPetListLen uint32 `struc:"sizeof=OurPetList"`
|
||||
// 我方携带精灵的信息
|
||||
// ArrayList<ReadyFightPetInfo>,使用切片模拟动态列表
|
||||
OurPetList []ReadyFightPetInfo `fieldDesc:"我方携带精灵的信息" serialize:"lengthFirst,lengthType=uint16,type=structArray"`
|
||||
|
||||
// 对方信息
|
||||
OpponentInfo FightUserInfo `fieldDesc:"对方信息" serialize:"struct"`
|
||||
OpponentPetListLen uint32 `struc:"sizeof=OpponentPetList"`
|
||||
// 敌方的精灵信息
|
||||
// 野怪战斗时:客户端接收此包前已生成精灵PetInfo,将部分信息写入该列表
|
||||
OpponentPetList []ReadyFightPetInfo `fieldDesc:"敌方的精灵信息 如果是野怪 那么再给客户端发送这个包体时就提前生成好了这只精灵的PetInfo,然后把从PetInfo中把部分信息写入到这个敌方的精灵信息中再发送这个包结构体" serialize:"lengthFirst,lengthType=uint16,type=structArray"`
|
||||
}
|
||||
|
||||
// ReadyFightPetInfo 准备战斗的精灵信息结构体,ReadyFightPetInfo类
|
||||
type ReadyFightPetInfo struct {
|
||||
// 精灵ID,@UInt long
|
||||
ID uint32 `fieldDesc:"精灵ID" `
|
||||
|
||||
// 精灵等级,@UInt long
|
||||
Level uint32 `fieldDesc:"精灵等级" `
|
||||
|
||||
// 精灵当前HP,@UInt long
|
||||
Hp uint32 `fieldDesc:"精灵HP" `
|
||||
|
||||
// 精灵最大HP,@UInt long
|
||||
MaxHp uint32 `fieldDesc:"最大HP" `
|
||||
SkillListLen uint32
|
||||
// 技能信息列表(固定4个元素,技能ID和剩余PP,无技能则为0)
|
||||
// List<SkillInfo>,初始化容量为4
|
||||
SkillList [4]model.SkillInfo `fieldDesc:"技能信息 技能ID跟剩余PP 固定32字节 没有给0" serialize:"fixedLength=4,type=structArray"`
|
||||
|
||||
// 精灵捕获时间,@UInt long
|
||||
CatchTime uint32 `fieldDesc:"精灵捕获时间" `
|
||||
|
||||
// 捕捉地图(固定给0),@UInt long
|
||||
CatchMap uint32 `fieldDesc:"捕捉地图 给0" `
|
||||
|
||||
// 固定给0,@UInt long
|
||||
CatchRect uint32 `fieldDesc:"给0" `
|
||||
|
||||
// 固定给0,@UInt long
|
||||
CatchLevel uint32 `fieldDesc:"给0" `
|
||||
SkinID uint32 `fieldDesc:"精灵皮肤ID" `
|
||||
Shiny uint32 `fieldDesc:"精灵是否闪" `
|
||||
}
|
||||
@@ -65,3 +65,16 @@ var BattleOverReason = enum.New[struct {
|
||||
PlayerCaptureSuccess EnumBattleOverReason `enum:"3"` //捕捉成功
|
||||
DefaultEnd EnumBattleOverReason `enum:"4"` //默认结束
|
||||
}]()
|
||||
|
||||
// 战斗模式
|
||||
|
||||
var BattleMode_PVP = enum.New[struct {
|
||||
PVP_1V1 EnumBattleMode `enum:"1"`
|
||||
PVP_6V6 EnumBattleMode `enum:"2"`
|
||||
}]()
|
||||
var Playerinvitemap map[uint32][]Playerinvite = make(map[uint32][]Playerinvite) //玩家邀请信息 ,比如一个玩家被多人邀请对战
|
||||
|
||||
type Playerinvite struct { //挂载到[]Playerinvite上? 被邀请者->邀请者
|
||||
InviteID uint32 // 邀请者
|
||||
InviteTime EnumBattleMode //游戏模式
|
||||
}
|
||||
|
||||
203
logic/service/fight/info/fight.go
Normal file
203
logic/service/fight/info/fight.go
Normal file
@@ -0,0 +1,203 @@
|
||||
package info
|
||||
|
||||
import (
|
||||
"blazing/common/data/socket"
|
||||
"blazing/common/socket/handler"
|
||||
"blazing/modules/blazing/model"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 野怪对战包
|
||||
type FightNpcMonsterInboundInfo struct {
|
||||
Head handler.TomeeHeader `cmd:"2408" struc:"[0]pad"`
|
||||
// Number 地图刷新怪物结构体对应的序号(1-9的位置序号)
|
||||
// @UInt long类型,使用uint32保持无符号特性
|
||||
Number uint32 `fieldDesc:"地图刷新怪物结构体对应的序号 1 - 9 的位置序号" `
|
||||
}
|
||||
|
||||
type NullOutboundInfo struct {
|
||||
}
|
||||
|
||||
// 准备战斗包
|
||||
type ReadyToFightInboundInfo struct {
|
||||
Head handler.TomeeHeader `cmd:"2404" struc:"[0]pad"`
|
||||
}
|
||||
|
||||
type FightStartOutboundInfo struct {
|
||||
// @UInt long类型
|
||||
IsCanAuto uint32 `fieldDesc:"是否自动 默认给0 怀疑是自动战斗器使用的" `
|
||||
|
||||
// 当前战斗精灵信息1(前端通过userid判断是否为我方)
|
||||
Info1 FightPetInfo `fieldDesc:"当前战斗精灵的信息 可能不准.看前端代码是以userid来判断哪个结构体是我方的" serialize:"struct"`
|
||||
|
||||
// 当前战斗精灵信息2(前端通过userid判断是否为我方)
|
||||
Info2 FightPetInfo `fieldDesc:"当前战斗精灵的信息 可能不准.看前端代码是以userid来判断哪个结构体是我方的" serialize:"struct"`
|
||||
}
|
||||
|
||||
// FightPetInfo 战斗精灵信息结构体,FightPetInfo类
|
||||
type FightPetInfo struct {
|
||||
// 用户ID(野怪为0),@UInt long
|
||||
UserID uint32 `fieldDesc:"用户ID 野怪为0" `
|
||||
|
||||
// 当前对战精灵ID,@UInt long
|
||||
ID uint32 `fieldDesc:"当前对战精灵ID" `
|
||||
|
||||
Name string `struc:"[16]byte"`
|
||||
// 精灵的捕获时间,@UInt long
|
||||
CatchTime uint32 `fieldDesc:"精灵的捕获时间" `
|
||||
|
||||
// 当前HP,@UInt long
|
||||
Hp uint32 `fieldDesc:"当前HP" `
|
||||
|
||||
// 最大HP,@UInt long
|
||||
MaxHp uint32 `fieldDesc:"最大HP" `
|
||||
|
||||
// 当前等级,@UInt long
|
||||
Level uint32 `fieldDesc:"当前等级" `
|
||||
|
||||
// 精灵是否能捕捉(1为能捕捉,0为不能捕捉),@UInt long
|
||||
Catchable uint32 `fieldDesc:"精灵是否能捕捉. 1为能捕捉 0为不能捕捉" `
|
||||
|
||||
// 战斗属性等级数组(6个单字节)
|
||||
// byte[],固定长度6,存储buff等级、攻击、速度等属性
|
||||
BattleLV [6]byte `fieldDesc:"这里实际上应该是6个单字节byte, 内容为buff等级 攻击 速度 特攻 防御 特防 命中等.但具体顺序未知可能需要测试. 具体数值为1-6等级" serialize:"fixedLength=6,type=byteArray"`
|
||||
}
|
||||
|
||||
// AttackValue 战斗中的攻击数值信息
|
||||
type AttackValue struct {
|
||||
UserID uint32 `json:"userId" fieldDescription:"玩家的米米号 与野怪对战userid = 0"`
|
||||
SkillID uint32 `json:"skillId" fieldDescription:"使用技能的id"`
|
||||
AttackTime uint32 `json:"attackTime" fieldDescription:"是否击中 如果为0 则miss 如果为1 则击中"`
|
||||
LostHp uint32 `json:"lostHp" fieldDescription:"我方造成的伤害"`
|
||||
GainHp uint32 `json:"gainHp" fieldDescription:"我方获得血量"`
|
||||
RemainHp uint32 `json:"remainHp" fieldDescription:"我方剩余血量"`
|
||||
MaxHp uint32 `json:"maxHp" fieldDescription:"我方最大血量"`
|
||||
State uint32 `json:"state" fieldDescription:"固定值0 需要后续测试"`
|
||||
SkillList []model.SkillInfo `json:"skillList" fieldDescription:"根据精灵的数据插入技能 最多4条 不定长"`
|
||||
IsCritical uint32 `json:"isCritical" fieldDescription:"是否暴击"`
|
||||
Status [20]byte `json:"status" fieldDescription:"20个字节 各种状态: 0:\"麻痹\",1:\"中毒\",2:\"烧伤\",4:\"寄生\",5:\"冻伤\",6:\"害怕\",7:\"疲惫\",8:\"睡眠\",9:\"石化\",10:\"混乱\",15:\"冰封\",16:\"流血\""`
|
||||
BattleLv [6]byte `json:"battleLv" fieldDescription:"6个单字节byte, 内容为buff等级 攻击 速度 特攻 防御 特防命中等. 但具体顺序未知可能需要测试. 具体数值为1-6等级"`
|
||||
// OwnerMaxShield uint32 `json:"ownerMaxShield" fieldDescription:"我方最大护盾"`
|
||||
// OwnerCurrentShield uint32 `json:"ownerCurrentShield" fieldDescription:"我方当前护盾"`
|
||||
}
|
||||
|
||||
// NoteUseSkillOutboundInfo 战斗技能使用通知的出站信息结构体
|
||||
type NoteUseSkillOutboundInfo struct {
|
||||
FirstAttackInfo AttackValue // 本轮先手的精灵在释放技能结束后的状态
|
||||
SecondAttackInfo AttackValue // 本轮后手的精灵在释放技能结束后的状态
|
||||
}
|
||||
|
||||
// 战斗逃跑
|
||||
type EscapeFightInboundInfo struct {
|
||||
Head handler.TomeeHeader `cmd:"2410" struc:"[0]pad"`
|
||||
}
|
||||
|
||||
// FightOverInfo 战斗结束信息结构体 2506
|
||||
type FightOverInfo struct {
|
||||
Reason uint32 // 固定值0
|
||||
WinnerId uint32 // 胜者的米米号 野怪为0
|
||||
TwoTimes uint32 // 双倍经验剩余次数
|
||||
ThreeTimes uint32 // 三倍经验剩余次数
|
||||
AutoFightTimes uint32 // 自动战斗剩余次数
|
||||
EnergyTimes uint32 // 能量吸收器剩余次数
|
||||
LearnTimes uint32 // 双倍学习器剩余次数
|
||||
}
|
||||
|
||||
// HandleFightInviteInboundInfo 处理战斗邀请的入站消息
|
||||
// 回空包就行
|
||||
type HandleFightInviteInboundInfo struct {
|
||||
Head handler.TomeeHeader `cmd:"2403" struc:"[0]pad"`
|
||||
UserID uint32 `json:"userId" codec:"userId,uint"` // 邀请我对战人的userid
|
||||
Flag uint32 `json:"flag" codec:"flag,uint"` // 1为同意对战 0为取消对战
|
||||
Mode uint32 `json:"mode" codec:"mode,uint"` // 战斗类型 1 = 1v1 2 = 6v6
|
||||
}
|
||||
|
||||
// 2502的回复包 PVP邀请消息
|
||||
type NoteHandleFightInviteOutboundInfo struct {
|
||||
UserID uint32
|
||||
Nickname string `struc:"[16]byte"` // 固定长度16字节
|
||||
Result uint32 // 0=拒绝 1=同意 2=在线超6小时 3=无出战精灵 4=不在线
|
||||
}
|
||||
|
||||
// 实现入站消息接口(Go中通过方法集隐式实现)
|
||||
type UseSkillInboundInfo struct {
|
||||
Head handler.TomeeHeader `cmd:"2405" struc:"[0]pad"`
|
||||
// 技能id,
|
||||
SkillId uint32
|
||||
}
|
||||
|
||||
type FightUserInfo struct {
|
||||
// 用户ID(野怪为0),@UInt long
|
||||
UserID uint32 `fieldDesc:"userID 如果为野怪则为0" `
|
||||
|
||||
// 玩家名称(野怪为UTF-8的'-',固定16字节)
|
||||
// 使用[16]byte存储固定长度的字节数组
|
||||
Nick string `struc:"[16]byte"`
|
||||
}
|
||||
|
||||
// NoteReadyToFightInfo 战斗准备就绪消息结构体,NoteReadyToFightInfo
|
||||
type NoteReadyToFightInfo struct {
|
||||
MAXPET uint32 `struc:"skip"` //,最大精灵数
|
||||
//战斗发起者ID
|
||||
OwnerID uint32 `struc:"skip"`
|
||||
|
||||
AFinished bool `struc:"skip"`
|
||||
BFinished bool `struc:"skip"`
|
||||
// 战斗类型ID(与野怪战斗为3,与人战斗为1,前端似乎未使用)
|
||||
// @UInt long
|
||||
FightId EnumBattleMode `fieldDesc:"战斗类型ID 但前端好像没有用到 与野怪战斗为3,与人战斗似乎是1" `
|
||||
|
||||
// 我方信息
|
||||
OurInfo FightUserInfo `fieldDesc:"我方信息" serialize:"struct"`
|
||||
Our *socket.Player `struc:"skip"`
|
||||
OurPetListLen uint32 `struc:"sizeof=OurPetList"`
|
||||
// 我方携带精灵的信息
|
||||
// ArrayList<ReadyFightPetInfo>,使用切片模拟动态列表
|
||||
OurPetList []ReadyFightPetInfo `fieldDesc:"我方携带精灵的信息" serialize:"lengthFirst,lengthType=uint16,type=structArray"`
|
||||
|
||||
// 对方信息
|
||||
OpponentInfo FightUserInfo `fieldDesc:"对方信息" serialize:"struct"`
|
||||
Opp *socket.Player `struc:"skip"`
|
||||
OpponentPetListLen uint32 `struc:"sizeof=OpponentPetList"`
|
||||
// 敌方的精灵信息
|
||||
// 野怪战斗时:客户端接收此包前已生成精灵PetInfo,将部分信息写入该列表
|
||||
OpponentPetList []ReadyFightPetInfo `fieldDesc:"敌方的精灵信息 如果是野怪 那么再给客户端发送这个包体时就提前生成好了这只精灵的PetInfo,然后把从PetInfo中把部分信息写入到这个敌方的精灵信息中再发送这个包结构体" serialize:"lengthFirst,lengthType=uint16,type=structArray"`
|
||||
}
|
||||
|
||||
// 当A和B都 这时候给双方回复开始战斗包
|
||||
func (t *NoteReadyToFightInfo) onBothFinished() {
|
||||
fmt.Println("A和B都已完成,触发onBothFinished")
|
||||
}
|
||||
|
||||
// ReadyFightPetInfo 准备战斗的精灵信息结构体,ReadyFightPetInfo类
|
||||
type ReadyFightPetInfo struct {
|
||||
// 精灵ID,@UInt long
|
||||
ID uint32 `fieldDesc:"精灵ID" `
|
||||
|
||||
// 精灵等级,@UInt long
|
||||
Level uint32 `fieldDesc:"精灵等级" `
|
||||
|
||||
// 精灵当前HP,@UInt long
|
||||
Hp uint32 `fieldDesc:"精灵HP" `
|
||||
|
||||
// 精灵最大HP,@UInt long
|
||||
MaxHp uint32 `fieldDesc:"最大HP" `
|
||||
SkillListLen uint32
|
||||
// 技能信息列表(固定4个元素,技能ID和剩余PP,无技能则为0)
|
||||
// List<SkillInfo>,初始化容量为4
|
||||
SkillList [4]model.SkillInfo `fieldDesc:"技能信息 技能ID跟剩余PP 固定32字节 没有给0" serialize:"fixedLength=4,type=structArray"`
|
||||
|
||||
// 精灵捕获时间,@UInt long
|
||||
CatchTime uint32 `fieldDesc:"精灵捕获时间" `
|
||||
|
||||
// 捕捉地图(固定给0),@UInt long
|
||||
CatchMap uint32 `fieldDesc:"捕捉地图 给0" `
|
||||
|
||||
// 固定给0,@UInt long
|
||||
CatchRect uint32 `fieldDesc:"给0" `
|
||||
|
||||
// 固定给0,@UInt long
|
||||
CatchLevel uint32 `fieldDesc:"给0" `
|
||||
SkinID uint32 `fieldDesc:"精灵皮肤ID" `
|
||||
Shiny uint32 `fieldDesc:"精灵是否闪" `
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package info
|
||||
|
||||
import "github.com/tnnmigga/enum"
|
||||
|
||||
// 战斗模式
|
||||
|
||||
var BattleMode_PVP = enum.New[struct {
|
||||
PVP_1V1 EnumBattleMode `enum:"1"`
|
||||
PVP_6V6 EnumBattleMode `enum:"2"`
|
||||
}]()
|
||||
var Playerinvitemap map[uint32][]Playerinvite = make(map[uint32][]Playerinvite) //玩家邀请信息 ,比如一个玩家被多人邀请对战
|
||||
|
||||
type Playerinvite struct { //挂载到[]Playerinvite上? 被邀请者->邀请者
|
||||
InviteID uint32 // 邀请者
|
||||
InviteTime EnumBattleMode //游戏模式
|
||||
}
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package fight
|
||||
|
||||
import "blazing/common/socket/handler"
|
||||
|
||||
// HandleFightInviteInboundInfo 处理战斗邀请的入站消息
|
||||
// 回空包就行
|
||||
type HandleFightInviteInboundInfo struct {
|
||||
Head handler.TomeeHeader `cmd:"2403" struc:"[0]pad"`
|
||||
UserID uint32 `json:"userId" codec:"userId,uint"` // 邀请我对战人的userid
|
||||
Flag uint32 `json:"flag" codec:"flag,uint"` // 1为同意对战 0为取消对战
|
||||
Mode uint32 `json:"mode" codec:"mode,uint"` // 战斗类型 1 = 1v1 2 = 6v6
|
||||
}
|
||||
|
||||
// 2502的回复包 PVP邀请消息
|
||||
type NoteHandleFightInviteOutboundInfo struct {
|
||||
UserID uint32
|
||||
Nickname string `struc:"[16]byte"` // 固定长度16字节
|
||||
Result uint32 // 0=拒绝 1=同意 2=在线超6小时 3=无出战精灵 4=不在线
|
||||
}
|
||||
|
||||
// 实现入站消息接口(Go中通过方法集隐式实现)
|
||||
type UseSkillInboundInfo struct {
|
||||
Head handler.TomeeHeader `cmd:"2405" struc:"[0]pad"`
|
||||
// 技能id,
|
||||
SkillId uint32
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package maps
|
||||
|
||||
type OgreInfo struct {
|
||||
Data [9]OgrePetInfo
|
||||
}
|
||||
|
||||
type OgrePetInfo struct {
|
||||
Id uint32
|
||||
Shiny uint32
|
||||
Lv uint32 `struc:"skip"` //等级
|
||||
}
|
||||
@@ -65,6 +65,7 @@ func (t *InInfo) SpawnMonsters(c *socket.Player, isfrist bool) {
|
||||
}
|
||||
t1 := t.genMonster(c.Info.MapID)
|
||||
if t1 != nil {
|
||||
c.OgreInfo = t1
|
||||
t1 := tt.Pack(t1)
|
||||
c.SendPack(t1)
|
||||
}
|
||||
@@ -80,16 +81,16 @@ func RandomStringFromSlice(s []string) string {
|
||||
}
|
||||
|
||||
// 应该根据怪物信息决定后端生成
|
||||
func (t *InInfo) genMonster(mapid uint32) *OgreInfo {
|
||||
func (t *InInfo) genMonster(mapid uint32) *socket.OgreInfo {
|
||||
// 设置怪物信息
|
||||
t1 := OgreInfo{}
|
||||
t1 := socket.OgreInfo{}
|
||||
mapss, ok := xmlres.MonsterMap[gconv.Int(mapid)]
|
||||
|
||||
if ok && mapss.Monsters != nil {
|
||||
for i, m := range mapss.Monsters.Monsters { //这里是9个
|
||||
id := strings.Split(m.ID, " ")
|
||||
lv := strings.Split(m.Lv, " ")
|
||||
ttt := OgrePetInfo{
|
||||
ttt := socket.OgrePetInfo{
|
||||
Id: gconv.Uint32(RandomStringFromSlice(id)),
|
||||
}
|
||||
if ttt.Id != 0 {
|
||||
@@ -102,7 +103,7 @@ func (t *InInfo) genMonster(mapid uint32) *OgreInfo {
|
||||
|
||||
}
|
||||
|
||||
t2 := OgreInfo{}
|
||||
t2 := socket.OgreInfo{}
|
||||
for i := 0; i < 3; i++ {
|
||||
|
||||
t2.Data[t.monsters[i]] = t1.Data[t.monsters[i]]
|
||||
|
||||
@@ -55,5 +55,17 @@ type FitmentAllInboundEmpty struct {
|
||||
type FitmentAllOutboundInfo struct {
|
||||
FitmentsLen uint32 `json:"fitmentsLen" struc:"sizeof=Fitments"`
|
||||
// 基地摆放物品的数组, 就算没有摆放物品, 也必带一个小屋的参数
|
||||
Fitments []FitmentShowInfo `codec:"auto" json:"fitments"`
|
||||
Fitments []FitmentItemInfo `codec:"auto" json:"fitments"`
|
||||
}
|
||||
|
||||
// FitmentItemInfo 对应Java的FitmentItemInfo类
|
||||
type FitmentItemInfo struct {
|
||||
// Id 家具id 或 默认房型id: 500001(对应Java的@UInt long id)
|
||||
Id uint32 `json:"id"`
|
||||
|
||||
// UsedCount 使用数量(默认房型id项目的使用数据固定为1)(对应Java的@UInt long usedCount)
|
||||
UsedCount uint32 `json:"usedCount"`
|
||||
|
||||
// AllCount 拥有数量(默认房型id项目的拥有数量固定为1)(对应Java的@UInt long allCount)
|
||||
AllCount uint32 `json:"allCount"`
|
||||
}
|
||||
|
||||
@@ -22,6 +22,16 @@ type Pet struct {
|
||||
Data string `gorm:"type:text;not null;comment:'精灵全部数据'" json:"data"`
|
||||
}
|
||||
|
||||
func LastFourElements[T any](s []T) []T {
|
||||
n := len(s)
|
||||
if n <= 4 {
|
||||
// 切片长度小于等于4时,返回整个切片
|
||||
return s
|
||||
}
|
||||
// 切片长度大于4时,返回最后4个元素(从n-4索引到末尾)
|
||||
return s[n-4:]
|
||||
}
|
||||
|
||||
// * @param petTypeId 精灵类型ID
|
||||
// * @param individualValue 个体值
|
||||
// * @param natureId 性格ID
|
||||
@@ -29,19 +39,19 @@ type Pet struct {
|
||||
// * @param isShiny 是否为闪光
|
||||
// * @param level 等级
|
||||
// * @return 生成的精灵实体
|
||||
func GenPetInfo(id, individual, natureId, abilityTypeEnum, shinyid, level uint32) *PetInfo {
|
||||
func GenPetInfo(id, dv, natureId, abilityTypeEnum, shinyid, level uint32) *PetInfo {
|
||||
|
||||
p := &PetInfo{ID: id,
|
||||
Shiny: shinyid, //闪光
|
||||
Nature: natureId, //性格
|
||||
Dv: individual,
|
||||
Dv: dv,
|
||||
EffectInfo: make([]PetEffectInfo, 0),
|
||||
CatchTime: uint32(time.Now().Unix()),
|
||||
Level: level} //等级
|
||||
|
||||
p.EffectInfo = append(p.EffectInfo, PetEffectInfo{ItemID: abilityTypeEnum})
|
||||
petxml := xmlres.PetMAP[int(id)]
|
||||
naxml := xmlres.NatureRootMap[int(natureId)]
|
||||
petxml := xmlres.PetMAP[int(id)]
|
||||
tttt := make([]uint32, 0)
|
||||
for _, v := range petxml.LearnableMoves.Moves {
|
||||
if p.Level >= uint32(v.LearningLv) {
|
||||
@@ -50,6 +60,7 @@ func GenPetInfo(id, individual, natureId, abilityTypeEnum, shinyid, level uint32
|
||||
}
|
||||
|
||||
}
|
||||
tttt = LastFourElements(tttt) //获取最后四个技能,如果不足,那就取全部技能
|
||||
for i := 0; i < len(tttt); i++ {
|
||||
p.SkillList[i].ID = tttt[i]
|
||||
p.SkillList[i].Pp = uint32(xmlres.SkillMap[int(tttt[i])].MaxPP)
|
||||
|
||||
BIN
public/oldswf/GroupFightDLL.swf
Normal file
BIN
public/oldswf/GroupFightDLL.swf
Normal file
Binary file not shown.
Reference in New Issue
Block a user