```
fix(socket): 修复TCP连接处理中逻辑取反错误 修复了`handleTcp`函数中对`s.discorse`的判断条件错误,导致CORS配置未正确应用的问题。 feat(player): 增加地图切换标记支持 在`Player`结构体中新增`Changemap`字段,用于标识玩家是否切换过地图,并在相关业务逻辑中进行设置和判断。 feat(pet): 重构精灵生成与经验处理逻辑 将`GenPetInfo`方法从model包迁移至player包,增加个体值、性格、特性等随机生成逻辑,优化技能学习处理方式。 refactor(service): 优化定时任务与连接管理 使用`cool.Cron`替代原生ticker实现刷怪定时任务,优化连接获取方式,确保并发安全。 refactor(model): 移除冗余代码并优化结构 从`pet.go`中移除已迁移至`player`包的函数定义,精简模型结构,提升模块清晰度。 refactor(config): 更新部门及字典名称配置 将`base_sys_department.json`和
This commit is contained in:
@@ -150,7 +150,7 @@ func (s *Server) OnTraffic(c gnet.Conn) (action gnet.Action) {
|
||||
func (s *Server) handleTcp(conn gnet.Conn) (action gnet.Action) {
|
||||
|
||||
for {
|
||||
if !s.discorse {
|
||||
if s.discorse {
|
||||
handle(conn)
|
||||
}
|
||||
data, err := s.codec.Decode(conn)
|
||||
@@ -181,7 +181,7 @@ func (s *Server) handleTcp(conn gnet.Conn) (action gnet.Action) {
|
||||
}
|
||||
|
||||
func (s *Server) parser(c gnet.Conn, line []byte) {
|
||||
|
||||
c.Context().(*player.ClientData).IsCrossDomain = true
|
||||
//todo 这里待实现注入player实体
|
||||
s.handler.Handle(c, line)
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ func NewServer(options ...Option) *Server {
|
||||
workerPool: goroutine.Default(),
|
||||
bufferSize: 4096, //默认缓冲区大小
|
||||
multicore: true,
|
||||
discorse: true,
|
||||
//discorse: true,
|
||||
}
|
||||
for _, option := range options {
|
||||
option(server)
|
||||
@@ -52,7 +52,7 @@ func WithSocketCodec(codec codec.SocketCodec) Option {
|
||||
}
|
||||
func WithCORS() Option {
|
||||
return func(u *Server) {
|
||||
u.discorse = false
|
||||
u.discorse = true
|
||||
}
|
||||
}
|
||||
func WithSocketHandler(handler Handler) Option {
|
||||
|
||||
@@ -27,7 +27,7 @@ func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *pla
|
||||
petid = 7
|
||||
}
|
||||
|
||||
mo = model.GenPetInfo(
|
||||
mo = c.GenPetInfo(
|
||||
int(petid), 24, //24个体
|
||||
-1,
|
||||
0, //野怪没特性
|
||||
@@ -55,7 +55,7 @@ func (h Controller) OnPlayerFightNpcMonster(data *fight.FightNpcMonsterInboundIn
|
||||
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||
}
|
||||
mo := model.GenPetInfo(
|
||||
mo := c.GenPetInfo(
|
||||
int(refpet.Id), -1,
|
||||
-1,
|
||||
0, //野怪没特性
|
||||
|
||||
@@ -39,6 +39,7 @@ func (h *Controller) Login(data *user.MAIN_LOGIN_IN, c *player.Conn) (result *us
|
||||
t.Info = t.Service.Person(data.Head.UserID)
|
||||
t.Info.UserID = data.Head.UserID
|
||||
t.Onlinetime = uint32(time.Now().Unix()) //保存时间戳
|
||||
t.Changemap = true
|
||||
|
||||
share.ShareManager.SetUserOnline(data.Head.UserID, h.Port) //设置用户登录服务器
|
||||
|
||||
|
||||
@@ -36,7 +36,8 @@ func (h Controller) MapHot(data *maphot.InInfo, c *player.Player) (result *mapho
|
||||
}
|
||||
func (h *Controller) MapLeave(data *maps.LeaveMapInboundInfo, c *player.Player) (result *space.LeaveMapOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
|
||||
//result = &maps.LeaveMapOutboundInfo{UserID: c.GetUserID()}
|
||||
c.Canmon = false //可以刷怪
|
||||
c.Canmon = false
|
||||
c.Changemap = true //可以刷怪
|
||||
data.Broadcast(c.Info.MapID, space.LeaveMapOutboundInfo{UserID: c.Info.UserID}) //同步广播
|
||||
space.GetSpace(c.Info.MapID).User.Remove(c.Info.UserID)
|
||||
// 如果有正在运行的刷怪协程,发送停止信号
|
||||
|
||||
@@ -48,7 +48,7 @@ func (h *Controller) GetPetList(
|
||||
result.ShortInfoList = make([]pet.PetShortInfo, len(tt))
|
||||
for i, v := range tt {
|
||||
|
||||
copier.Copy(&result.ShortInfoList[i], &v)
|
||||
copier.Copy(&result.ShortInfoList[i], &v.Data)
|
||||
|
||||
}
|
||||
return result, 0
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/logic/service/fight/input"
|
||||
"blazing/logic/service/player"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
@@ -127,17 +128,18 @@ func (f *FightC) ReadyFight(c common.PlayerI) {
|
||||
}
|
||||
|
||||
switch f.Info.Status {
|
||||
case 1: //pvp
|
||||
case info.BattleStatus.FIGHT_WITH_PLAYER: //pvp
|
||||
|
||||
f.GetInputByPlayer(c, false).Finished = true
|
||||
if f.GetInputByPlayer(c, true).Finished {
|
||||
rrsult()
|
||||
}
|
||||
case 2: // 6v6
|
||||
case info.BattleStatus.FIGHT_WITH_BOSS: // 6v6
|
||||
rrsult()
|
||||
case 3: // 野怪战斗
|
||||
case info.BattleStatus.FIGHT_WITH_NPC: // 野怪战斗
|
||||
|
||||
//判断捕捉率大于0
|
||||
fmt.Println("CatchRate", xmlres.PetMAP[int(f.Info.OpponentPetList[0].ID)].CatchRate)
|
||||
if gconv.Int(xmlres.PetMAP[int(f.Info.OpponentPetList[0].ID)].CatchRate) > 0 {
|
||||
rett.Info2.Catchable = 1
|
||||
t, _ := f.Opp.Player.(*player.AI_player)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package player
|
||||
|
||||
import (
|
||||
"blazing/cool"
|
||||
"blazing/modules/blazing/model"
|
||||
"time"
|
||||
)
|
||||
@@ -14,28 +15,12 @@ func NewPlayer(opts ...PlayerOption) *Player {
|
||||
}
|
||||
p.monsters = generateThreeUniqueNumbers()
|
||||
|
||||
p.StopChan = make(chan struct{})
|
||||
|
||||
// 启动刷怪协程
|
||||
go func(stopChan chan struct{}) {
|
||||
|
||||
ticker := time.NewTicker(10 * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-stopChan:
|
||||
// 收到停止信号,退出协程
|
||||
return
|
||||
case <-ticker.C:
|
||||
// 刷新当前地图的怪物
|
||||
if p.Canmon && p.FightC == nil { //已经进入地图或者没在战斗中,就可以刷新怪
|
||||
p.SpawnMonsters()
|
||||
}
|
||||
|
||||
}
|
||||
p.StopChan = cool.Cron.ScheduleFunc(10*time.Second, func() {
|
||||
if p.Canmon && p.FightC == nil { //已经进入地图或者没在战斗中,就可以刷新怪
|
||||
p.SpawnMonsters()
|
||||
}
|
||||
}(p.StopChan)
|
||||
})
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(p)
|
||||
}
|
||||
|
||||
@@ -3,10 +3,13 @@ package player
|
||||
import (
|
||||
"blazing/common/data/xmlres"
|
||||
"blazing/logic/service/fight/info"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"blazing/modules/blazing/model"
|
||||
"math"
|
||||
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/jinzhu/copier"
|
||||
)
|
||||
|
||||
@@ -85,7 +88,7 @@ func (p *Player) AddPetExp(petinfo *model.PetInfo, addExp uint32) {
|
||||
//player.SendMessage(generatePetUpdateInfo(petEntity, originalExp+addExp-exp, addition))
|
||||
|
||||
// 处理技能学习
|
||||
canLearnSkillList := model.LastFourElements(petinfo.GetLevelRangeCanLearningSkills(originalLevel, petinfo.Level)) //获取最后四个技能,如果不足,那就取全部技能
|
||||
canLearnSkillList := LastFourElements(petinfo.GetLevelRangeCanLearningSkills(originalLevel, petinfo.Level)) //获取最后四个技能,如果不足,那就取全部技能
|
||||
|
||||
for i := 0; i < 4; i++ {
|
||||
|
||||
@@ -117,3 +120,115 @@ func (p *Player) AddPetExp(petinfo *model.PetInfo, addExp uint32) {
|
||||
|
||||
// return exp
|
||||
}
|
||||
|
||||
func LastFourElements[T any](s []T) []T {
|
||||
n := len(s)
|
||||
if n <= 4 {
|
||||
// 切片长度小于等于4时,返回整个切片
|
||||
return s
|
||||
}
|
||||
// 切片长度大于4时,返回最后4个元素(从n-4索引到末尾)
|
||||
return s[n-4:]
|
||||
}
|
||||
|
||||
// -1是随机
|
||||
// * @param petTypeId 精灵类型ID
|
||||
// * @param individualValue 个体值
|
||||
// * @param natureId 性格ID
|
||||
// * @param abilityTypeEnum 特性类型
|
||||
// * @param isShiny 是否为闪光
|
||||
// * @param level 等级
|
||||
// * @return 生成的精灵实体
|
||||
func (player *Player) GenPetInfo(id int, dv, natureId, abilityTypeEnum, shinyid, level int) *model.PetInfo {
|
||||
// 设置随机数种子,确保每次运行生成不同的随机数序列
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
p := &model.PetInfo{ID: uint32(id),
|
||||
|
||||
EffectInfo: make([]model.PetEffectInfo, 0),
|
||||
CatchTime: uint32(time.Now().Unix()),
|
||||
Level: uint32(level)} //等级
|
||||
|
||||
if shinyid != -1 {
|
||||
p.Shiny = uint32(shinyid)
|
||||
}
|
||||
if natureId != -1 {
|
||||
p.Nature = uint32(natureId)
|
||||
} else {
|
||||
p.Nature = uint32(rand.Intn(25))
|
||||
}
|
||||
if dv != -1 {
|
||||
p.Dv = uint32(dv)
|
||||
} else {
|
||||
p.Dv = uint32(CalculateIndividualValue(rand.New(rand.NewSource(time.Now().UnixNano()))))
|
||||
}
|
||||
|
||||
if abilityTypeEnum != -1 {
|
||||
if abilityTypeEnum != 0 {
|
||||
v := xmlres.PlayerEffectMAP[int(abilityTypeEnum)]
|
||||
p.EffectInfo = append(p.EffectInfo, model.PetEffectInfo{
|
||||
Idx: uint16(gconv.Int16(v.Idx)),
|
||||
Status: 1,
|
||||
EID: uint16(gconv.Int16(v.Eid)),
|
||||
Args: v.ArgsS,
|
||||
})
|
||||
}
|
||||
|
||||
} else {
|
||||
for i, v := range xmlres.PlayerEffectMAP {
|
||||
if rand.Intn(len(xmlres.PlayerEffectMAP)) == i {
|
||||
p.EffectInfo = append(p.EffectInfo, model.PetEffectInfo{
|
||||
Idx: uint16(gconv.Int16(v.Idx)),
|
||||
Status: 1,
|
||||
EID: uint16(gconv.Int16(v.Eid)),
|
||||
Args: v.ArgsS,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tttt := LastFourElements(p.GetLevelRangeCanLearningSkills(0, p.Level)) //获取最后四个技能,如果不足,那就取全部技能
|
||||
for i := 0; i < len(tttt); i++ {
|
||||
p.SkillList[i].ID = tttt[i]
|
||||
p.SkillList[i].PP = uint32(xmlres.SkillMap[int(tttt[i])].MaxPP)
|
||||
|
||||
}
|
||||
p.SkillListLen = uint32(len(tttt))
|
||||
p.CalculatePetPane()
|
||||
p.Hp = p.MaxHp
|
||||
player.AddPetExp(p, 0)
|
||||
return p
|
||||
}
|
||||
|
||||
// 除数数组(放大100倍)
|
||||
// 数组按递增顺序排列,用于判断个体值等级
|
||||
var divisors = []int{
|
||||
600, 1200, 1900, 2700, 3600, 4600, 5700, 6900, 8200, 9600,
|
||||
11100, 12700, 14400, 16200, 18100, 20100, 22100, 24000,
|
||||
25800, 27500, 29100, 30600, 32000, 33300, 34500, 35600,
|
||||
36600, 37500, 38300, 39000, 39600,
|
||||
}
|
||||
|
||||
// CalculateIndividual 根据给定的a值计算个体值
|
||||
// 返回值表示a大于等于多少个除数(范围:0-31)
|
||||
func CalculateIndividual(a int) int {
|
||||
individual := 0
|
||||
for _, divisor := range divisors {
|
||||
if a >= divisor {
|
||||
individual++
|
||||
} else {
|
||||
break // 数组是递增的,可提前跳出循环
|
||||
}
|
||||
}
|
||||
return individual
|
||||
}
|
||||
|
||||
// CalculateIndividualValue 计算个体值(0-31)
|
||||
// 接收外部随机数生成器,便于控制随机性和复用
|
||||
func CalculateIndividualValue(random *rand.Rand) int {
|
||||
// 生成0-40000的随机数,作为个体值计算的输入
|
||||
a := random.Intn(40001)
|
||||
return CalculateIndividual(a)
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/antlabs/timer"
|
||||
"github.com/gobwas/ws"
|
||||
"github.com/gobwas/ws/wsutil"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
@@ -59,17 +60,17 @@ func NewClientData() *ClientData {
|
||||
var Mainplayer = &utils.SyncMap[uint32, *Player]{} //玩家数据
|
||||
|
||||
func (c *Conn) SendPack(bytes []byte) error {
|
||||
if t, ok := c.MainConn.Context().(*ClientData); ok {
|
||||
if t, ok := c.GetConn().Context().(*ClientData); ok {
|
||||
if t.Wsmsg.Upgraded {
|
||||
// This is the echo server
|
||||
err := wsutil.WriteServerMessage(c.MainConn, ws.OpBinary, bytes)
|
||||
if err != nil {
|
||||
logging.Infof("conn[%v] [err=%v]", c.MainConn.RemoteAddr().String(), err.Error())
|
||||
logging.Infof("conn[%v] [err=%v]", c.GetConn().RemoteAddr().String(), err.Error())
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
|
||||
_, err := c.MainConn.Write(bytes)
|
||||
_, err := c.GetConn().Write(bytes)
|
||||
if err != nil {
|
||||
glog.Debug(context.Background(), err)
|
||||
|
||||
@@ -98,17 +99,18 @@ type Player struct {
|
||||
|
||||
loginChan chan struct{} // 登录完成通知通道
|
||||
|
||||
StopChan chan struct{} //停止刷怪协程
|
||||
StopChan timer.TimeNoder
|
||||
|
||||
context.Context
|
||||
PVPinfo *info.PVPinfo //当前邀请的玩家ID
|
||||
Onlinetime uint32 //当前登录时间
|
||||
OgreInfo *OgreInfo
|
||||
OgreInfo OgreInfo
|
||||
|
||||
Service *blservice.UserService
|
||||
HavePVPinfo []*Player
|
||||
monsters [3]int
|
||||
Canmon bool //可以刷怪
|
||||
Changemap bool //是否切换过地图
|
||||
}
|
||||
|
||||
// PlayerOption 定义配置 Player 的函数类型
|
||||
@@ -131,11 +133,9 @@ func (p *Player) SpawnMonsters() {
|
||||
// 创建数据包
|
||||
tt := NewTomeeHeader(2004, p.Info.UserID)
|
||||
|
||||
p.monsters, _, _ = replaceOneNumber(p.monsters)
|
||||
|
||||
p.genMonster(p.Info.MapID) //生成野怪
|
||||
|
||||
p.SendPack(tt.Pack(p.OgreInfo))
|
||||
p.SendPack(tt.Pack(&p.OgreInfo))
|
||||
|
||||
}
|
||||
|
||||
@@ -149,6 +149,8 @@ func RandomStringFromSlice(s []string) string {
|
||||
|
||||
// 应该根据怪物信息决定后端生成
|
||||
func (p *Player) genMonster(mapid uint32) {
|
||||
var oldnum, newNum int
|
||||
p.monsters, oldnum, newNum = replaceOneNumber(p.monsters)
|
||||
// 设置怪物信息
|
||||
t1 := OgreInfo{}
|
||||
mapss, ok := xmlres.MonsterMap[gconv.Int(mapid)]
|
||||
@@ -170,13 +172,18 @@ func (p *Player) genMonster(mapid uint32) {
|
||||
|
||||
}
|
||||
|
||||
t2 := OgreInfo{}
|
||||
for i := 0; i < 3; i++ {
|
||||
if p.Changemap {
|
||||
p.Changemap = false
|
||||
p.OgreInfo = OgreInfo{} //切地图清空
|
||||
for i := 0; i < 3; i++ {
|
||||
|
||||
t2.Data[p.monsters[i]] = t1.Data[p.monsters[i]]
|
||||
p.OgreInfo.Data[p.monsters[i]] = t1.Data[p.monsters[i]]
|
||||
}
|
||||
} else {
|
||||
p.OgreInfo.Data[oldnum] = OgrePetInfo{}
|
||||
p.OgreInfo.Data[newNum] = t1.Data[newNum]
|
||||
}
|
||||
|
||||
p.OgreInfo = &t2
|
||||
}
|
||||
|
||||
// 生成0-9之间三个不重复的随机数 进地图5s
|
||||
@@ -294,7 +301,8 @@ func (p *Player) Save() {
|
||||
|
||||
p.Service.Save(p.Info)
|
||||
LeaveMap(p)
|
||||
close(p.StopChan) //停止刷怪
|
||||
p.StopChan.Stop() //停止刷怪
|
||||
|
||||
p.IsLogin = false
|
||||
|
||||
Mainplayer.Delete(p.Info.UserID)
|
||||
|
||||
@@ -3,11 +3,10 @@ package player
|
||||
import "blazing/common/socket/errorcode"
|
||||
|
||||
func GetPlayer(c *Conn, userid uint32) *Player { //TODO 这里待优化,可能存在内存泄漏问题
|
||||
c.Mu.Lock()
|
||||
defer c.Mu.Unlock()
|
||||
|
||||
//检查player初始化,是否为conn初始后取map,防止二次连接后存在两个player
|
||||
|
||||
clientdata := c.MainConn.Context().(*ClientData)
|
||||
clientdata := c.GetConn().Context().(*ClientData)
|
||||
if clientdata.Player == nil {
|
||||
|
||||
clientdata.Player = NewPlayer(
|
||||
@@ -38,7 +37,7 @@ func KickPlayer(userid uint32) { //踢出玩家
|
||||
//实际上这里有个问题,会造成重复保存问题
|
||||
|
||||
player1.SendPack(head.Pack(nil))
|
||||
player1.MainConn.MainConn.Close()
|
||||
player1.MainConn.GetConn().Close()
|
||||
// clientdata.Player = player
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,13 @@ type Conn struct {
|
||||
Mu sync.Mutex
|
||||
}
|
||||
|
||||
func (c *Conn) GetConn() gnet.Conn {
|
||||
c.Mu.Lock()
|
||||
defer c.Mu.Unlock()
|
||||
return c.MainConn
|
||||
|
||||
}
|
||||
|
||||
func NewConn(c gnet.Conn) *Conn {
|
||||
return &Conn{MainConn: c}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"createTime": "2025-07-05 11:18:43.560949 +00:00",
|
||||
"updateTime": "2025-07-05 11:18:43.560949 +00:00",
|
||||
"deleted_at": null,
|
||||
"name": "COOL",
|
||||
"name": "SUN",
|
||||
"parentId": null,
|
||||
"orderNum": 0
|
||||
},
|
||||
|
||||
@@ -80,6 +80,7 @@ func (s *BaseSysUserService) ServiceAdd(ctx context.Context, req *cool.AddReq) (
|
||||
r = g.RequestFromCtx(ctx)
|
||||
reqmap = r.GetMap()
|
||||
)
|
||||
|
||||
// 如果reqmap["password"]不为空,则对密码进行md5加密
|
||||
if !r.Get("password").IsNil() {
|
||||
reqmap["password"] = gmd5.MustEncryptString(r.Get("password").String())
|
||||
@@ -89,6 +90,27 @@ func (s *BaseSysUserService) ServiceAdd(ctx context.Context, req *cool.AddReq) (
|
||||
return
|
||||
}
|
||||
data = g.Map{"id": lastInsertId}
|
||||
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
|
||||
|
||||
if !r.Get("roleIdList").IsNil() {
|
||||
inRoleIdSet := gset.NewFrom(r.Get("roleIdList").Ints())
|
||||
roleArray := garray.NewArray()
|
||||
inRoleIdSet.Iterator(func(v interface{}) bool {
|
||||
roleArray.PushRight(g.Map{
|
||||
"userId": gconv.Uint(lastInsertId),
|
||||
"roleId": gconv.Uint(v),
|
||||
})
|
||||
return true
|
||||
})
|
||||
|
||||
_, err = cool.DBM(model.NewBaseSysUserRole()).Fields("userId,roleId").Insert(roleArray)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -252,7 +274,7 @@ func NewBaseSysUserService() *BaseSysUserService {
|
||||
Extend: func(ctx g.Ctx, m *gdb.Model) *gdb.Model {
|
||||
return m.Group(`base_sys_user.id`)
|
||||
},
|
||||
KeyWordField: []string{"name", "username", "nickName"},
|
||||
KeyWordField: []string{"username", "email"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
50
modules/blazing/controller/admin/monster_get.go
Normal file
50
modules/blazing/controller/admin/monster_get.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"blazing/cool"
|
||||
"blazing/modules/blazing/model"
|
||||
"blazing/modules/blazing/service"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
type PetBagController struct {
|
||||
*cool.Controller
|
||||
}
|
||||
type PetGetReq struct {
|
||||
g.Meta `path:"/genpet" method:"POST"`
|
||||
// 新增:精灵相关参数(完全对齐自定义表单配置)
|
||||
PetTypeId int `json:"petTypeId" v:"required|min:1" comment:"精灵类型ID,必填,正整数(最小1,无0或负数类型),对应GenPetInfo的id参数"`
|
||||
IndividualValue int `json:"individualValue" v:"required|between:-1,31" comment:"精灵个体值,必填,范围-1~31(-1表示随机生成满个体,0~31为固定值,决定基础属性上限)"`
|
||||
NatureId int `json:"natureId" v:"required|between:-1,24" comment:"精灵性格ID,必填,范围-1~24(-1表示随机,0~24对应25种固定性格,影响属性加成)"`
|
||||
AbilityTypeEnum int `json:"abilityTypeEnum" v:"required|min:-1" comment:"精灵特性类型ID,必填,最小值-1(-1表示随机选择1个特性,0及以上为固定特性ID,需与PlayerEffectMAP匹配)"`
|
||||
IsShiny int `json:"isShiny" v:"min:-1" comment:"精灵异色(闪光)ID,必填,最小值-1(-1表示随机,0及以上为固定异色状态,稀有精灵特殊外观/属性),原表单hidden但需保留必填逻辑"`
|
||||
Level int `json:"level" v:"required|between:1,100" comment:"精灵等级,必填,范围1~100(常规游戏等级上限,影响精灵当前属性强度)"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
var task_info_controller = &PetBagController{
|
||||
&cool.Controller{
|
||||
Prefix: "/admin/monster/bag",
|
||||
Api: []string{"Delete", "Update", "Info", "List", "Page"},
|
||||
Service: service.NewPetService(),
|
||||
},
|
||||
}
|
||||
// 注册路由
|
||||
cool.RegisterController(task_info_controller)
|
||||
}
|
||||
func (c *PetBagController) GetSession(ctx context.Context, req *PetGetReq) (res *cool.BaseRes, err error) {
|
||||
|
||||
fmt.Println(req)
|
||||
var (
|
||||
admin = cool.GetAdmin(ctx)
|
||||
//r = g.RequestFromCtx(ctx)
|
||||
)
|
||||
t := model.GenPetInfo(
|
||||
req.PetTypeId, req.IndividualValue, req.NatureId, req.AbilityTypeEnum, req.IsShiny, req.Level)
|
||||
service.NewUserService(uint32(admin.UserId)).PetAdd(*t)
|
||||
return
|
||||
|
||||
}
|
||||
@@ -1,46 +1,9 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"blazing/common/data/xmlres"
|
||||
"blazing/cool"
|
||||
"math/rand"
|
||||
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
// 除数数组(放大100倍)
|
||||
// 数组按递增顺序排列,用于判断个体值等级
|
||||
var divisors = []int{
|
||||
600, 1200, 1900, 2700, 3600, 4600, 5700, 6900, 8200, 9600,
|
||||
11100, 12700, 14400, 16200, 18100, 20100, 22100, 24000,
|
||||
25800, 27500, 29100, 30600, 32000, 33300, 34500, 35600,
|
||||
36600, 37500, 38300, 39000, 39600,
|
||||
}
|
||||
|
||||
// CalculateIndividual 根据给定的a值计算个体值
|
||||
// 返回值表示a大于等于多少个除数(范围:0-31)
|
||||
func CalculateIndividual(a int) int {
|
||||
individual := 0
|
||||
for _, divisor := range divisors {
|
||||
if a >= divisor {
|
||||
individual++
|
||||
} else {
|
||||
break // 数组是递增的,可提前跳出循环
|
||||
}
|
||||
}
|
||||
return individual
|
||||
}
|
||||
|
||||
// CalculateIndividualValue 计算个体值(0-31)
|
||||
// 接收外部随机数生成器,便于控制随机性和复用
|
||||
func CalculateIndividualValue(random *rand.Rand) int {
|
||||
// 生成0-40000的随机数,作为个体值计算的输入
|
||||
a := random.Intn(40001)
|
||||
return CalculateIndividual(a)
|
||||
}
|
||||
|
||||
const TableNamePet = "pet"
|
||||
|
||||
// Pet mapped from table <pet>
|
||||
@@ -65,87 +28,6 @@ type PetS struct {
|
||||
Data []PetInfo `orm:"data" dc:"资源规格"`
|
||||
}
|
||||
|
||||
func LastFourElements[T any](s []T) []T {
|
||||
n := len(s)
|
||||
if n <= 4 {
|
||||
// 切片长度小于等于4时,返回整个切片
|
||||
return s
|
||||
}
|
||||
// 切片长度大于4时,返回最后4个元素(从n-4索引到末尾)
|
||||
return s[n-4:]
|
||||
}
|
||||
|
||||
// -1是随机
|
||||
// * @param petTypeId 精灵类型ID
|
||||
// * @param individualValue 个体值
|
||||
// * @param natureId 性格ID
|
||||
// * @param abilityTypeEnum 特性类型
|
||||
// * @param isShiny 是否为闪光
|
||||
// * @param level 等级
|
||||
// * @return 生成的精灵实体
|
||||
func GenPetInfo(id int, dv, natureId, abilityTypeEnum, shinyid, level int) *PetInfo {
|
||||
// 设置随机数种子,确保每次运行生成不同的随机数序列
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
p := &PetInfo{ID: uint32(id),
|
||||
|
||||
EffectInfo: make([]PetEffectInfo, 0),
|
||||
CatchTime: uint32(time.Now().Unix()),
|
||||
Level: uint32(level)} //等级
|
||||
|
||||
if shinyid != -1 {
|
||||
p.Shiny = uint32(shinyid)
|
||||
}
|
||||
if natureId != -1 {
|
||||
p.Nature = uint32(natureId)
|
||||
} else {
|
||||
p.Nature = uint32(rand.Intn(25))
|
||||
}
|
||||
if dv != -1 {
|
||||
p.Dv = uint32(dv)
|
||||
} else {
|
||||
p.Dv = uint32(CalculateIndividualValue(rand.New(rand.NewSource(time.Now().UnixNano()))))
|
||||
}
|
||||
|
||||
if abilityTypeEnum != -1 {
|
||||
if abilityTypeEnum != 0 {
|
||||
v := xmlres.PlayerEffectMAP[int(abilityTypeEnum)]
|
||||
p.EffectInfo = append(p.EffectInfo, PetEffectInfo{
|
||||
Idx: uint16(gconv.Int16(v.Idx)),
|
||||
Status: 1,
|
||||
EID: uint16(gconv.Int16(v.Eid)),
|
||||
Args: v.ArgsS,
|
||||
})
|
||||
}
|
||||
|
||||
} else {
|
||||
for i, v := range xmlres.PlayerEffectMAP {
|
||||
if rand.Intn(len(xmlres.PlayerEffectMAP)) == i {
|
||||
p.EffectInfo = append(p.EffectInfo, PetEffectInfo{
|
||||
Idx: uint16(gconv.Int16(v.Idx)),
|
||||
Status: 1,
|
||||
EID: uint16(gconv.Int16(v.Eid)),
|
||||
Args: v.ArgsS,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tttt := LastFourElements(p.GetLevelRangeCanLearningSkills(0, p.Level)) //获取最后四个技能,如果不足,那就取全部技能
|
||||
for i := 0; i < len(tttt); i++ {
|
||||
p.SkillList[i].ID = tttt[i]
|
||||
p.SkillList[i].PP = uint32(xmlres.SkillMap[int(tttt[i])].MaxPP)
|
||||
|
||||
}
|
||||
p.SkillListLen = uint32(len(tttt))
|
||||
p.CalculatePetPane()
|
||||
p.Hp = p.MaxHp
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// PetInfo 精灵信息结构(合并后的优化版本)
|
||||
type PetInfo struct {
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package service
|
||||
import (
|
||||
"blazing/cool"
|
||||
"blazing/modules/blazing/model"
|
||||
"context"
|
||||
)
|
||||
|
||||
// 获取精灵信息 0是仓库,1是背包,2是放生
|
||||
@@ -43,3 +44,23 @@ func (s *UserService) PetAdd(y model.PetInfo) {
|
||||
m1.Insert(player)
|
||||
|
||||
}
|
||||
|
||||
func NewPetService() *MonsterService {
|
||||
return &MonsterService{
|
||||
&cool.Service{
|
||||
Model: model.NewPet(),
|
||||
PageQueryOp: &cool.QueryOp{
|
||||
Where: func(ctx context.Context) [][]interface{} {
|
||||
var (
|
||||
admin = cool.GetAdmin(ctx)
|
||||
userId = admin.UserId
|
||||
)
|
||||
return [][]interface{}{
|
||||
{"player_id", userId, true},
|
||||
{"in_bag", 0, true},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"createTime": "2022-07-06 14:22:18.309000",
|
||||
"updateTime": "2022-07-06 14:22:18.309000",
|
||||
"typeId": 2,
|
||||
"name": "COOL",
|
||||
"name": "SUN",
|
||||
"orderNum": 1,
|
||||
"remark": null,
|
||||
"parentId": null
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
E:/newcode/blazing/public/assets/210.xml
|
||||
1
public/config/221.xml
Symbolic link
1
public/config/221.xml
Symbolic link
@@ -0,0 +1 @@
|
||||
E:/newcode/sun/public/assets/221.xml
|
||||
@@ -1 +1 @@
|
||||
E:/newcode/blazing/public/assets/226.xml
|
||||
E:/newcode/sun/public/assets/226.xml
|
||||
@@ -1 +1 @@
|
||||
E:/newcode/blazing/public/assets/227.xml
|
||||
E:/newcode/sun/public/assets/227.xml
|
||||
@@ -1 +1 @@
|
||||
E:/newcode/blazing/public/assets/43.xml
|
||||
E:/newcode/sun/public/assets/43.xml
|
||||
Reference in New Issue
Block a user