feat(fight): 实现精灵切换功能并优化战斗逻辑
- 新增 ChangePet 方法实现精灵切换 - 优化战斗循环逻辑,支持精灵切换 - 修复一些战斗相关的 bug - 优化代码结构,提高可维护性
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) //初始化第一层类型
|
||||
|
||||
|
||||
@@ -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: 失明
|
||||
}
|
||||
|
||||
// 精灵的能力提升
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user