From 9d2de92dd6139b861b10ea361fb23d98ddbe63ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <1@72wo.cn> Date: Sun, 7 Sep 2025 00:23:28 +0800 Subject: [PATCH] =?UTF-8?q?feat(fight):=20=E5=AE=9E=E7=8E=B0=E7=B2=BE?= =?UTF-8?q?=E7=81=B5=E5=88=87=E6=8D=A2=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=88=98=E6=96=97=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 ChangePet 方法实现精灵切换 - 优化战斗循环逻辑,支持精灵切换 - 修复一些战斗相关的 bug - 优化代码结构,提高可维护性 --- logic/controller/fight.go | 7 ++ logic/go.sum | 2 + logic/main.go | 2 + logic/service/ai.go | 3 + logic/service/fight/cmd.go | 5 + logic/service/fight/info/BattleAction.go | 42 ++++---- logic/service/fight/info/BattlePetEntity.go | 23 +++-- logic/service/fight/info/BattleSkillEntity.go | 14 +-- logic/service/fight/info/info.go | 22 ++++- logic/service/fightc.go | 98 ++++++++++++++++--- logic/service/player.go | 8 ++ modules/blazing/model/pet.go | 15 ++- 12 files changed, 193 insertions(+), 48 deletions(-) diff --git a/logic/controller/fight.go b/logic/controller/fight.go index be5f3e31e..03d62cafc 100644 --- a/logic/controller/fight.go +++ b/logic/controller/fight.go @@ -83,3 +83,10 @@ func (h Controller) Escape(data *fight.EscapeFightInboundInfo, c *service.Player c.FightC.Escape(c) return nil, 0 } + +// 切换精灵 +func (h Controller) ChangePet(data *fight.ChangePetInboundInfo, c *service.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { + + c.FightC.ChangePet(c, int32(data.CatchTime)) + return nil, 0 +} diff --git a/logic/go.sum b/logic/go.sum index 426ff8bdc..7c3d5b4ab 100644 --- a/logic/go.sum +++ b/logic/go.sum @@ -60,6 +60,8 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= diff --git a/logic/main.go b/logic/main.go index 559ffc21b..8cbf48264 100644 --- a/logic/main.go +++ b/logic/main.go @@ -8,6 +8,7 @@ import ( "github.com/gogf/gf/v2/os/gproc" _ "blazing/contrib/drivers/pgsql" + "blazing/logic/service" "blazing/cool" @@ -17,6 +18,7 @@ import ( ) func signalHandlerForMain(sig os.Signal) { + service.Fightpool.Release() fmt.Println("MainProcess is shutting down due to signal:", sig.String()) } diff --git a/logic/service/ai.go b/logic/service/ai.go index 0494094ef..d09136920 100644 --- a/logic/service/ai.go +++ b/logic/service/ai.go @@ -62,3 +62,6 @@ func (p *AI_player) GetPetInfo() []*model.PetInfo { func (p *AI_player) SendAttackValue(info.AttackValueS) { } +func (p *AI_player) SendChangePet(info.ChangePetInfo) { + +} diff --git a/logic/service/fight/cmd.go b/logic/service/fight/cmd.go index c947099b3..ccadc40c0 100644 --- a/logic/service/fight/cmd.go +++ b/logic/service/fight/cmd.go @@ -48,3 +48,8 @@ type UseSkillInboundInfo struct { // 技能id, SkillId uint32 } +type ChangePetInboundInfo struct { + Head service.TomeeHeader `cmd:"2407" struc:"[0]pad"` + // CatchTime 捕捉时间 + CatchTime uint32 `json:"catchTime"` +} diff --git a/logic/service/fight/info/BattleAction.go b/logic/service/fight/info/BattleAction.go index 48e4cfa20..0075af7b0 100644 --- a/logic/service/fight/info/BattleAction.go +++ b/logic/service/fight/info/BattleAction.go @@ -11,12 +11,13 @@ type EnumPlayerOperation int // 定义读秒倒计时期间玩家可执行的操作枚举 var PlayerOperations = enum.New[struct { - SystemGiveUp EnumPlayerOperation `enum:"-1"` // 系统选择放弃出手(比如没有PP) - SelectSkill EnumPlayerOperation `enum:"0"` // 选择技能-6到6 - ActiveSwitch EnumPlayerOperation `enum:"2"` // 主动切换(中切) - UsePotion EnumPlayerOperation `enum:"3"` // 使用药剂(捕捉、逃跑等) - Escape EnumPlayerOperation `enum:"4"` // 逃跑(等级最高,以及掉线) - PlayerOffline EnumPlayerOperation `enum:"5"` // 玩家掉线 + SystemGiveUp EnumPlayerOperation `enum:"-1"` // 系统选择放弃出手(比如没有PP) + SelectSkill EnumPlayerOperation `enum:"0"` // 选择技能-6到6 + ActiveSwitch EnumPlayerOperation `enum:"2"` // 主动切换(中切) + UsePotion EnumPlayerOperation `enum:"3"` // 使用药剂(捕捉、逃跑等) + Escape EnumPlayerOperation `enum:"4"` // 逃跑(等级最高,以及掉线) + PlayerOffline EnumPlayerOperation `enum:"5"` // 玩家掉线 + BeExpelledSwitch EnumPlayerOperation `enum:"6"` // 被驱逐切换 }]() // Compare 比较两个1v1战斗动作的执行优先级(核心逻辑) @@ -46,7 +47,7 @@ func Compare(a, b BattleActionI) (BattleActionI, BattleActionI) { } // 比较宠物相关属性(假设Value(4)返回速度相关值) - p2 = int(bskill.PetInfo.Value(4)) - int(askill.PetInfo.Value(4)) + p2 = int(bskill.PetInfo.Speed()) - int(askill.PetInfo.Speed()) if p2 > 0 { return b, a } else if p2 < 0 { @@ -82,15 +83,20 @@ func (s *SelectSkillAction) Priority() int { // ActiveSwitchAction 主动切换宠物的战斗动作 type ActiveSwitchAction struct { - PlayerID uint32 // 玩家ID - CurrentPet BattlePetEntity // 当前在场宠物 - TargetPet BattlePetEntity // 要切换上场的宠物 - SwitchReason string // 切换原因 + PlayerID uint32 // 玩家ID + Type bool //是否主动切换 + Reason ChangePetInfo + // CurrentPet BattlePetEntity // 当前在场宠物 + // TargetPet BattlePetEntity // 要切换上场的宠物 + // SwitchReason string // 切换原因 } // Priority 返回动作优先级 func (a *ActiveSwitchAction) Priority() int { - return int(PlayerOperations.ActiveSwitch) + if a.Type { + return int(PlayerOperations.ActiveSwitch) + } + return int(PlayerOperations.BeExpelledSwitch) } // Broadcast 广播切换宠物的动作信息 @@ -99,6 +105,12 @@ func (a *ActiveSwitchAction) Broadcast() { // // a.PlayerID, a.CurrentPet.Name, a.TargetPet.Name, a.SwitchReason) } +func (a *ActiveSwitchAction) GetPlayerID() uint32 { + return a.PlayerID + // fmt.Printf("玩家[%d]主动切换宠物:从%s切换到%s(原因:%s)\n", + // // a.PlayerID, a.CurrentPet.Name, a.TargetPet.Name, a.SwitchReason) +} + // UsePotionAction 使用药剂的战斗动作 type UsePotionAction struct { PlayerID uint32 // 玩家ID @@ -115,12 +127,6 @@ func (u *UsePotionAction) Priority() int { return int(PlayerOperations.UsePotion) } -// Broadcast 广播使用药剂的动作信息 -func (u *UsePotionAction) Broadcast() { - // fmt.Printf("玩家[%d]使用药剂:%s(ID:%d),目标:%s\n", - // u.PlayerID, u.PotionName, u.PotionID, u.TargetPet.Name) -} - // EscapeAction 逃跑的战斗动作 type EscapeAction struct { PlayerID uint32 // 玩家ID diff --git a/logic/service/fight/info/BattlePetEntity.go b/logic/service/fight/info/BattlePetEntity.go index 6ea7efed2..807e4e4f8 100644 --- a/logic/service/fight/info/BattlePetEntity.go +++ b/logic/service/fight/info/BattlePetEntity.go @@ -4,6 +4,8 @@ import ( element "blazing/common/data/Element" "blazing/common/data/xmlres" "blazing/modules/blazing/model" + "fmt" + "math/rand" "sync" "unsafe" ) @@ -23,19 +25,25 @@ func (a *BattlePetEntity) Value(tt uint32) uint32 { offsetAtk := unsafe.Offsetof(a.Info.Attack) // c字段的偏移量(通常为4+16=20) // 2. 将结构体指针转换为原始内存地址(uintptr) baseAddr := uintptr(unsafe.Pointer(&offsetAtk)) - + fmt.Println(*(*uint32)(unsafe.Pointer(&baseAddr))) addrA := unsafe.Pointer(baseAddr + 4*uintptr(tt)) //根据0是攻击 offsetAtkP := unsafe.Offsetof(a.Prop.Attack) // c字段的偏移量(通常为4+16=20) // 2. 将结构体指针转换为原始内存地址(uintptr) baseAddrp := uintptr(unsafe.Pointer(&offsetAtkP)) - + fmt.Println(*(*uint32)(unsafe.Pointer(&offsetAtkP))) addrB := unsafe.Pointer(baseAddrp + 4*uintptr(tt)) //根据0是攻击 - return uint32(calculateRealValue(int64(*(*uint32)(addrA)), int(*(*byte)(addrB)))) + fmt.Println(*(*uint32)(addrA)) + ret := uint32(calculateRealValue(int64(*(*uint32)(addrA)), int(*(*byte)(addrB)))) + return ret +} +func (a *BattlePetEntity) Speed() uint32 { + return uint32(calculateRealValue(int64(a.Info.Speed), int(a.Prop.Speed))) + } type BattlePetEntity struct { xmlres.PetInfo - Info *model.PetInfo //通过偏移赋值 + Info model.PetInfo //通过偏移赋值 statusConditions sync.Map // key: StatusCondition, value: int (剩余回合) Skills [4]*BattleSkillEntity // 技能槽(最多4个技能) @@ -45,13 +53,14 @@ type BattlePetEntity struct { } // 创建精灵实例 -func CreateBattlePetEntity(info *model.PetInfo) *BattlePetEntity { +func CreateBattlePetEntity(info *model.PetInfo, rand *rand.Source) *BattlePetEntity { ret := &BattlePetEntity{} ret.PetInfo = xmlres.PetMAP[int(info.ID)] //注入精灵信息 - ret.Info = info + ret.Info = *info for i := 0; i < 4; i++ { - ret.Skills[i] = CreateBattleSkillWithInfinity(info.SkillList[i].ID) + //todo 技能信息应该每回合进行深拷贝,保证每次的技能效果都是不一样的 + ret.Skills[i] = CreateBattleSkillWithInfinity(&info.SkillList[i], rand) } return ret diff --git a/logic/service/fight/info/BattleSkillEntity.go b/logic/service/fight/info/BattleSkillEntity.go index c8691d0e1..5a2b6f2db 100644 --- a/logic/service/fight/info/BattleSkillEntity.go +++ b/logic/service/fight/info/BattleSkillEntity.go @@ -3,6 +3,8 @@ package info import ( element "blazing/common/data/Element" "blazing/common/data/xmlres" + "blazing/modules/blazing/model" + "math/rand" "context" "fmt" @@ -39,26 +41,26 @@ type BattleSkillEntity struct { PP int DamageZone map[EnumCategory]map[EnumsZoneType]map[EnumsZoneType][]float64 // 三维map 伤害类型-》增还是减-》加还是乘-》值 DamageValue decimal.Decimal // 伤害值 - + Rand rand.Source // 技能类型属性 //SkillType EnumCategory // 技能类型(物理/特殊/状态) } // CreateBattleSkillWithInfinity 创建战斗技能实例(可指定是否无限PP) -func CreateBattleSkillWithInfinity(id uint32) *BattleSkillEntity { +func CreateBattleSkillWithInfinity(skill *model.SkillInfo, rand *rand.Source) *BattleSkillEntity { //如果PP是-1 ,那就是无限PP // ID小于10001的视为无效技能 - if id < 10001 { + if skill.ID < 10001 { return nil } var ret BattleSkillEntity // 从资源仓库获取技能数据 - move, ok := xmlres.SkillMap[int(id)] + move, ok := xmlres.SkillMap[int(skill.ID)] if !ok { - glog.Error(context.Background(), "技能ID无效", "id", id) + glog.Error(context.Background(), "技能ID无效", "id", skill.ID) } ret.Move = move // // 解析副作用参数 @@ -68,7 +70,7 @@ func CreateBattleSkillWithInfinity(id uint32) *BattleSkillEntity { // if err == nil { // ret.SideEffects = rf // } - + ret.PP = int(skill.PP) // ret.SideEffectArgs = sideEffectArgs ret.DamageZone = make(map[EnumCategory]map[EnumsZoneType]map[EnumsZoneType][]float64) //初始化第一层类型 diff --git a/logic/service/fight/info/info.go b/logic/service/fight/info/info.go index 357ae17bb..49b774008 100644 --- a/logic/service/fight/info/info.go +++ b/logic/service/fight/info/info.go @@ -5,6 +5,22 @@ import ( "fmt" ) +type ChangePetInfo struct { + // UserId 米米号,野怪为0 + UserId uint32 `json:"userId"` + // PetId 切换上场的精灵编号 + ID uint32 `fieldDesc:"当前对战精灵ID" ` + // PetName 精灵名字,固定16字节长度 + Name string `struc:"[16]byte"` + // Level 切换上场的精灵等级 + Level uint32 `json:"level"` + // Hp 切换上场的精灵当前生命值 + Hp uint32 `json:"hp"` + // MaxHp 切换上场的精灵最大生命值 + MaxHp uint32 `json:"maxHp"` + CatchTime uint32 `fieldDesc:"捕捉时间" ` +} + // FightPetInfo 战斗精灵信息结构体,FightPetInfo类 type FightPetInfo struct { // 用户ID(野怪为0),@UInt long @@ -42,8 +58,8 @@ type AttackValue struct { 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:"我方剩余血量"` + GainHp int32 `json:"gainHp" fieldDescription:"我方获得血量"` + RemainHp int32 `json:"remainHp" fieldDescription:"我方剩余血量"` MaxHp uint32 `json:"maxHp" fieldDescription:"我方最大血量"` State uint32 `json:"state" fieldDescription:"固定值0 需要后续测试"` SkillListLen uint32 `struc:"sizeof=SkillList"` @@ -76,7 +92,7 @@ type StatusDict struct { ImmuneToStatDrop_17 byte // 17: 免疫能力下降 ImmuneToAbnormal_18 byte // 18: 免疫异常状态 Paralyzed_19 byte // 19: 瘫痪 - Blind_20 byte // 20: 失明 + //Blind_20 byte // 20: 失明 } // 精灵的能力提升 diff --git a/logic/service/fightc.go b/logic/service/fightc.go index e850e72df..5fed836e8 100644 --- a/logic/service/fightc.go +++ b/logic/service/fightc.go @@ -5,12 +5,14 @@ import ( "blazing/logic/service/fight/info" "blazing/modules/blazing/model" "fmt" + "math" "math/rand" "time" "github.com/gogf/gf/v2/util/gconv" "github.com/jinzhu/copier" "github.com/mohae/deepcopy" + "github.com/panjf2000/ants/v2" ) type PlayerI interface { @@ -24,6 +26,7 @@ type PlayerI interface { SendNoteReadyToFightInfo(info.NoteReadyToFightInfo) SendFightEndInfo(info.FightOverInfo) SendAttackValue(info.AttackValueS) + SendChangePet(info.ChangePetInfo) } type FightC struct { @@ -56,6 +59,33 @@ func (f *FightC) Escape(c PlayerI) { f.actionChan <- ret } +// 切换精灵 主动和被驱逐 +func (f *FightC) ChangePet(c PlayerI, id int32) { + ret := &info.ActiveSwitchAction{ + PlayerID: c.ID(), + } + + rett := func(t PlayerI) { + for _, v := range t.GetPetInfo() { + if v.CatchTime == uint32(id) { + f.OurCurrentPet = info.CreateBattlePetEntity(v, f.Random()) //存入自己的精灵信息 + copier.Copy(&ret.Reason, &v) + ret.Reason.UserId = c.ID() + } + + } + } + if c == f.Our { + + rett(f.Our) + + } else { + + rett(f.Opp) + } + f.actionChan <- ret +} + // 玩家使用技能 func (f *FightC) UseSkill(c PlayerI, id int32) { ret := &info.SelectSkillAction{ @@ -106,7 +136,7 @@ func (f *FightC) ReadyFight(c PlayerI) { } } else { f.Opp = c - f.OppCurrentPet = info.CreateBattlePetEntity(c.GetPetInfo()[0]) + f.OppCurrentPet = info.CreateBattlePetEntity(c.GetPetInfo()[0], f.Random()) f.BFinished = true if f.AFinished { rrsult() @@ -122,15 +152,23 @@ func (f *FightC) ReadyFight(c PlayerI) { rrsult() } } -func (f *FightC) Random() { +func (f *FightC) Random() *rand.Source { //先产生战斗的随机数 // 组合「时间戳(纳秒精度)+ 双方ID + 回合数」生成种子 seed := f.StartTime.UnixNano() ^ int64(f.OwnerID) ^ int64(f.Our.ID()) ^ int64(f.Round) // 用异或运算混合多维度信息 - rand.Seed(seed) + ret := rand.NewSource(seed) + return &ret } +var Fightpool *ants.Pool + +func init() { + Fightpool, _ = ants.NewPool(math.MaxInt32) + //defer p.Release() +} + // 创建新战斗 func (f *FightC) NewFight(i *info.NoteReadyToFightInfo, plays PlayerI, mo *model.PetInfo) { @@ -138,9 +176,9 @@ func (f *FightC) NewFight(i *info.NoteReadyToFightInfo, plays PlayerI, mo *model f.Info = i f.StartTime = time.Now() f.actionChan = make(chan info.BattleActionI, 2) // 初始化全局操作通道 - f.OurCurrentPet = info.CreateBattlePetEntity(plays.GetPetInfo()[0]) + f.OurCurrentPet = info.CreateBattlePetEntity(plays.GetPetInfo()[0], f.Random()) if mo != nil { - f.OppCurrentPet = info.CreateBattlePetEntity(mo) + f.OppCurrentPet = info.CreateBattlePetEntity(mo, f.Random()) } switch i.FightId { @@ -152,7 +190,11 @@ func (f *FightC) NewFight(i *info.NoteReadyToFightInfo, plays PlayerI, mo *model plays.SendNoteReadyToFightInfo(*i) } - go f.battleLoop() // 起战斗循环 + rr := Fightpool.Submit(f.battleLoop) + if rr != nil { + panic(rr) + } + //go f.battleLoop() // 起战斗循环 } // 广播,并是否结束回合 @@ -164,6 +206,12 @@ func (f *FightC) Broadcast(t info.BattleActionI) bool { f.Our.SendFightEndInfo(ff.Reason) f.Opp.SendFightEndInfo(ff.Reason) return true + + case *info.ActiveSwitchAction: //切换精灵 + + f.Our.SendChangePet(ff.Reason) + f.Opp.SendChangePet(ff.Reason) + default: } @@ -177,7 +225,9 @@ func (f *FightC) BroadcastSkill(t info.AttackValueS) { // 战斗回合循环 func (f *FightC) battleLoop() { for { - f.Round++ //回合数自增 + f.Round++ //回合数自增 + // f.AFinished = false + // f.BFinished = false if f.Round > 250 { //回合数超过250,战斗平局结束 } @@ -191,7 +241,14 @@ func (f *FightC) battleLoop() { if action.GetPlayerID() != f.Our.ID() && action.GetPlayerID() != f.Opp.ID() { continue } + if a, isExpelled := action.(*info.ActiveSwitchAction); isExpelled { + fmt.Println("对方死亡切换") + f.Broadcast(a) + if !a.Type { + continue + } + } if action.GetPlayerID() == f.Our.ID() && f.Info.FightId == 3 { go f.Opp.GetAction() //获取AI的动作 @@ -204,7 +261,7 @@ func (f *FightC) battleLoop() { } actions[uint32(action.GetPlayerID())] = action - fmt.Printf("玩家%d 执行动作", action.GetPlayerID()) + fmt.Println("玩家%d 执行动作", action.GetPlayerID()) case <-timeout: fmt.Println("回合操作超时") @@ -212,7 +269,7 @@ func (f *FightC) battleLoop() { actions[f.Our.ID()] = &info.SystemGiveUpAction{PlayerID: f.Our.ID()} //系统选择出手 } if _, exists := actions[f.Opp.ID()]; !exists { - actions[f.Opp.ID()] = &info.SystemGiveUpAction{PlayerID: f.Our.ID()} //系统选择出手 + actions[f.Opp.ID()] = &info.SystemGiveUpAction{PlayerID: f.Opp.ID()} //系统选择出手 } } } @@ -236,6 +293,7 @@ func (f *FightC) battleLoop() { break } + var p_skill [2]*info.SelectSkillAction for i := 0; i < 2; i++ { @@ -271,19 +329,33 @@ func (f *FightC) battleLoop() { uint32(p_skill[i].Skill.ID), 1, 200, - 200, - 100, + 0, + int32(f.OurCurrentPet.Info.MaxHp), f.OurCurrentPet.Info.MaxHp, 0, 0, - f.OurCurrentPet.Info.SkillList[:], + []model.SkillInfo{}, 1, info.StatusDict{}, info.PropDict{}, } } - + p_skill[1].Attack = info.AttackValue{ + p_skill[1].PlayerID, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + []model.SkillInfo{}, + 0, + info.StatusDict{}, + info.PropDict{}, + } f.BroadcastSkill(info.AttackValueS{ p_skill[0].Attack, p_skill[1].Attack, }) diff --git a/logic/service/player.go b/logic/service/player.go index e39079905..92a13526c 100644 --- a/logic/service/player.go +++ b/logic/service/player.go @@ -154,6 +154,14 @@ func (p *Player) SendAttackValue(b info.AttackValueS) { p.SendPack(t1.Pack(&b)) //准备包由各自发,因为协议不一样 } + +func (p *Player) SendChangePet(b info.ChangePetInfo) { + t1 := NewTomeeHeader(2407, p.Info.UserID) + + p.SendPack(t1.Pack(&b)) //准备包由各自发,因为协议不一样 + +} + func (p *Player) Cheak(b error) { if b != nil { g.Log().Error(context.Background(), "出现错误", p.Info.UserID, b.Error()) diff --git a/modules/blazing/model/pet.go b/modules/blazing/model/pet.go index 2275843dc..2b6e1c234 100644 --- a/modules/blazing/model/pet.go +++ b/modules/blazing/model/pet.go @@ -3,6 +3,7 @@ package model import ( "blazing/common/data/xmlres" "blazing/cool" + "math" "math/rand" "time" @@ -23,6 +24,17 @@ type Pet struct { Data string `gorm:"type:text;not null;comment:'精灵全部数据'" json:"data"` } +func GetGaussRandomNum(min, max int64) int64 { + σ := (float64(min) + float64(max)) / 2 + μ := (float64(max) - σ) / 3 + rand.Seed(time.Now().UnixNano()) + x := rand.Float64() + x1 := rand.Float64() + a := math.Cos(2*math.Pi*x) * math.Sqrt((-2)*math.Log(x1)) + result := a*μ + σ + return int64(result) +} + // RandomInRange 从切片表示的范围中返回对应结果: // - 切片包含1个元素时,返回该元素本身 // - 切片包含2个元素时,从[min, max]闭区间随机生成一个整数(自动调整min和max顺序) @@ -41,7 +53,8 @@ func RandomInRange(rangeSlice []int) int { min, max = max, min } // 生成 [min, max] 区间的随机整数 - return (rand.Intn(int(max-min+1)) + int(min)) + + return int(GetGaussRandomNum(int64(min), int64(max))) //(rand.Intn(int(max-min+1)) + int(min)) default: // 其他长度返回0 return 0