From f6a305de7733961fda6faf309d83a0a23d3a2b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <1@72wo.cn> Date: Tue, 9 Dec 2025 14:52:55 +0800 Subject: [PATCH] =?UTF-8?q?```=20feat(fight):=20=E6=B7=BB=E5=8A=A0=20BOSS?= =?UTF-8?q?=20=E6=88=98=E6=96=97=E9=80=BB=E8=BE=91=E4=B8=8E=E5=9C=B0?= =?UTF-8?q?=E5=9B=BE=E4=BA=A4=E4=BA=92=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 fight_boss.go 中增加对 BOSS 血量是否为 0 的判断,避免无效赋值 - 在 map.go 中移除旧的测试代码,并将 Canmon 状态设置移至 MapList 方法中 - 新增 Attack_Boss 接口方法用于处理玩家攻击 BOSS 请求 - 修改 MapBossInfo 结构体字段类型 --- logic/controller/fight_boss.go | 6 ++- logic/controller/map.go | 31 ++++------- logic/service/maps/info/info.go | 12 +++-- logic/service/maps/maplist.go | 4 ++ logic/service/space/in_out.go | 84 +++++++++++++++++++++++++++++ logic/service/space/space.go | 8 ++- modules/blazing/model/sign.go | 44 +++++++++++++++ modules/blazing/model/signconfig.go | 40 ++++++++++++++ public/config/地图配置野怪.xml | 13 +++++ 9 files changed, 214 insertions(+), 28 deletions(-) create mode 100644 modules/blazing/model/sign.go create mode 100644 modules/blazing/model/signconfig.go diff --git a/logic/controller/fight_boss.go b/logic/controller/fight_boss.go index 0b082b296..b13be918e 100644 --- a/logic/controller/fight_boss.go +++ b/logic/controller/fight_boss.go @@ -84,8 +84,10 @@ func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *pla 0, bm.Lv) mo.CatchTime = uint32(i) - mo.Hp = uint32(bm.Hp) - mo.MaxHp = uint32(bm.Hp) + if bm.Hp != 0 { + mo.Hp = uint32(bm.Hp) + mo.MaxHp = uint32(bm.Hp) + } for _, v := range strings.Split(bm.NewSeIdxs, " ") { idx := gconv.Uint16(v) diff --git a/logic/controller/map.go b/logic/controller/map.go index 49671d7ce..96c393662 100644 --- a/logic/controller/map.go +++ b/logic/controller/map.go @@ -4,6 +4,7 @@ import ( "blazing/common/socket/errorcode" "sync/atomic" + "blazing/logic/service/fight" "blazing/logic/service/maphot" "blazing/logic/service/maps" "blazing/logic/service/maps/info" @@ -21,27 +22,9 @@ func (h *Controller) MapEnter(data *maps.InInfo, c *player.Player) (result *info result = info.NewOutInfo() c.Info.Pos = data.Point copier.Copy(result, c.Info) - atomic.StoreUint32(&c.Canmon, 2) + defer c.GetSpace().EnterMap(c) - // go func() { - - // for { - // <-time.After(time.Second * 5) - - // var t info.MapBossSInfo - // t.INFO = make([]info.MapBossInfo, 0) - // t.INFO = append(t.INFO, info.MapBossInfo{ - // Id: 47, - - // Hp: 1, - // Pos: 1, - // }) - // c.SendPackCmd(2021, &t) - - // } - - // }() return result, 0 } func (h Controller) MapHot(data *maphot.InInfo, c *player.Player) (result *maphot.OutInfo, err errorcode.ErrorCode) { @@ -68,10 +51,18 @@ func (h *Controller) MapLeave(data *maps.LeaveMapInboundInfo, c *player.Player) return } func (h *Controller) MapList(data *maps.ListMapPlayerInboundInfo, c *player.Player) (result *info.ListMapPlayerOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的 - + atomic.StoreUint32(&c.Canmon, 2) result = &info.ListMapPlayerOutboundInfo{ Player: c.GetSpace().GetInfo(), } return } +func (h *Controller) Attack_Boss(data *maps.AttackBossInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的 + + if atomic.LoadInt32(&c.GetSpace().MapBossInfo.Hp) > 0 { + atomic.AddInt32(&c.GetSpace().MapBossInfo.Hp, -1) + } + + return +} diff --git a/logic/service/maps/info/info.go b/logic/service/maps/info/info.go index eb4d54c40..59ddfb432 100644 --- a/logic/service/maps/info/info.go +++ b/logic/service/maps/info/info.go @@ -34,10 +34,10 @@ type MapBossSInfo struct { INFO []MapBossInfo } type MapBossInfo struct { - Id uint32 `json:"id" protobuf:"1,req,name=id"` // 需要刷新的BOSS精灵ID - Region uint32 `json:"region" protobuf:"2,req,name=region"` // 刷新区域(蘑菇怪为0) - Hp uint32 `json:"hp" protobuf:"3,req,name=hp"` // HP值(蘑菇怪为A,其他BOSS暂未明确用途,可能无实际作用) - Pos uint32 `json:"pos" protobuf:"4,req,name=pos"` // 刷新坐标(类似野怪的位置ID,蘑菇怪初始为2;战斗退出后该值会变化) + Id uint32 `json:"id" protobuf:"1,req,name=id"` // 需要刷新的BOSS精灵ID + Region uint32 `json:"region" protobuf:"2,req,name=region"` // 刷新区域(蘑菇怪为0) + Hp int32 `struc:"uint32" json:"hp" protobuf:"3,req,name=hp"` // HP值(蘑菇怪为A,其他BOSS暂未明确用途,可能无实际作用) + Pos int `struc:"uint32" json:"pos" protobuf:"4,req,name=pos"` // 刷新坐标(类似野怪的位置ID,蘑菇怪初始为2;战斗退出后该值会变化) } // 这里存储星球的map @@ -167,3 +167,7 @@ type LeaveMapOutboundInfo struct { // 米米号 UserID uint32 `struc:"uint32" fieldDesc:"米米号" json:"user_id"` } +type S2C_50004 struct { + Id uint32 `json:"id" protobuf:"1,req,name=id"` // 天气0没有,1是雨.2是雪 + +} diff --git a/logic/service/maps/maplist.go b/logic/service/maps/maplist.go index 53d0e63f8..d494d1890 100644 --- a/logic/service/maps/maplist.go +++ b/logic/service/maps/maplist.go @@ -5,3 +5,7 @@ import "blazing/logic/service/common" type ListMapPlayerInboundInfo struct { Head common.TomeeHeader `cmd:"2003" struc:"skip"` //切换地图 } + +type AttackBossInboundInfo struct { + Head common.TomeeHeader `cmd:"2412" struc:"skip"` //切换地图 +} diff --git a/logic/service/space/in_out.go b/logic/service/space/in_out.go index 8a8a4372b..041a2ab67 100644 --- a/logic/service/space/in_out.go +++ b/logic/service/space/in_out.go @@ -1,11 +1,14 @@ package space import ( + "blazing/cool" "blazing/logic/service/common" "blazing/logic/service/maps/info" maps "blazing/logic/service/maps/info" "sync/atomic" + "time" + "github.com/gogf/gf/v2/util/grand" "github.com/jinzhu/copier" "github.com/panjf2000/ants/v2" "golang.org/x/time/rate" @@ -24,6 +27,8 @@ func (s *Space) Broadcast(c common.PlayerI, cmd uint32, data any) { v.SendPackCmd(cmd, data) } + } else { + v.SendPackCmd(cmd, data) } return false @@ -89,3 +94,82 @@ func (s *Space) Walk(c common.PlayerI, info *info.WalkOutInfo) { s.Broadcast(c, 2101, info) } +func (s *Space) gettimeboss(mapid uint32) { + var t info.MapBossSInfo + t.INFO = append(t.INFO, s.MapBossInfo) + switch mapid { + case 12: + + s.MapBossInfo = info.MapBossInfo{ + Id: 47, + + Hp: 10, + } + + cool.Cron.ScheduleFunc(10*time.Second, func() { + s.MapBossInfo.Pos = (grand.Intn(4) + 1 + s.MapBossInfo.Pos) % 5 + println("pos", s.MapBossInfo.Pos, "hp", s.MapBossInfo.Hp) + + t.INFO[0] = s.MapBossInfo + s.Broadcast(nil, 2021, &t) + + }) + cool.Cron.ScheduleFunc(300*time.Second, func() { + + atomic.StoreInt32(&s.MapBossInfo.Hp, 10) + + }) + + case 32: + + s.MapBossInfo = info.MapBossInfo{ + Id: 70, + } + + cool.Cron.CustomFunc(s, func() { + + r := grand.Intn(3) + s.Broadcast(nil, 50004, &info.S2C_50004{Id: uint32(r)}) + if r == 1 { + s.MapBossInfo.Id = 70 + t.INFO[0] = s.MapBossInfo + + s.Broadcast(nil, 2021, &t) + } else { + s.MapBossInfo.Id = 0 + t.INFO[0] = s.MapBossInfo + s.Broadcast(nil, 2021, &t) + + } + }) + + case 108: + s.MapBossInfo = info.MapBossInfo{ + Id: 219, + } + + cool.Cron.ScheduleFunc(10*time.Second, func() { + s.MapBossInfo.Pos = (grand.Intn(6) + 1 + s.MapBossInfo.Pos) % 6 + t.INFO[0] = s.MapBossInfo + + s.Broadcast(nil, 2021, &t) + }) + default: + cool.Cron.ScheduleFunc(10*time.Second, func() { + + s.Broadcast(nil, 50004, &info.S2C_50004{Id: uint32(0)}) + + }) + + } + +} + +type leiyi struct { +} + +func (t *Space) Next(time.Time) time.Time { + + return time.Now().Add(time.Duration(grand.N(6, 30)) * time.Second) + +} diff --git a/logic/service/space/space.go b/logic/service/space/space.go index 953ec550e..ada371fea 100644 --- a/logic/service/space/space.go +++ b/logic/service/space/space.go @@ -5,6 +5,7 @@ import ( "blazing/common/utils" "blazing/logic/service/common" + "blazing/logic/service/maps/info" maps "blazing/logic/service/maps/info" csmap "github.com/mhmtszr/concurrent-swiss-map" @@ -20,12 +21,13 @@ type Space struct { //ID uint32 // 地图ID Name string //地图名称 Owner ARENA + info.MapBossInfo } // NewSyncMap 创建一个新的玩家同步map func NewSpace() *Space { - return &Space{ + ret := &Space{ User: csmap.New[uint32, common.PlayerI]( // set the number of map shards. the default value is 32. csmap.WithShardCount[uint32, common.PlayerI](32), @@ -57,6 +59,8 @@ func NewSpace() *Space { // csmap.WithSize[string, int](1000), ), } + + return ret } // 获取星球 @@ -77,7 +81,7 @@ func GetSpace(id uint32) *Space { if t.Super == 0 { t.Super = uint32(v.ID) } - + t.gettimeboss(uint32(v.ID)) _, ok := maphot[t.Super] if !ok { var t1 int32 diff --git a/modules/blazing/model/sign.go b/modules/blazing/model/sign.go new file mode 100644 index 000000000..1b4d67b17 --- /dev/null +++ b/modules/blazing/model/sign.go @@ -0,0 +1,44 @@ +package model + +import ( + "blazing/cool" +) + +// 表名常量(遵循小写+下划线的命名规范) +const TableNameSignInRecord = "player_sign_in_record" + +// SignInRecord 玩家签到明细记录表 +// 记录玩家每一次的签到行为,关联签到活动表 +type SignInRecord struct { + *cool.Model // 嵌入基础Model(主键、创建/更新时间等通用字段) + + // 核心关联字段 + PlayerID uint32 `gorm:"not null;index:idx_player_id;comment:'玩家ID'" json:"player_id"` + SignInID uint32 `gorm:"not null;index:idx_sign_in_id;comment:'关联的签到活动ID(对应player_sign_in表的SignInID)'" json:"sign_in_id"` + + IsCompleted bool `gorm:"not null;default:false;comment:'签到是否完成(0-未完成 1-已完成)'" json:"is_completed"` + //通过bitset来实现签到的进度记录 + SignInProgress []uint32 `gorm:"type:json;not null;comment:'签到进度(状压实现,存储每日签到状态)'" json:"sign_in_progress"` +} + +// TableName 指定表名(遵循现有规范) +func (*SignInRecord) TableName() string { + return TableNameSignInRecord +} + +// GroupName 指定表分组(与现有表保持一致的default分组) +func (*SignInRecord) GroupName() string { + return "default" +} + +// NewSignInRecord 创建签到明细记录实例(初始化基础Model) +func NewSignInRecord() *SignInRecord { + return &SignInRecord{ + Model: cool.NewModel(), + } +} + +// init 程序启动时自动创建表(与现有SignIn表初始化逻辑一致) +func init() { + cool.CreateTable(&SignInRecord{}) +} diff --git a/modules/blazing/model/signconfig.go b/modules/blazing/model/signconfig.go new file mode 100644 index 000000000..20f150ee2 --- /dev/null +++ b/modules/blazing/model/signconfig.go @@ -0,0 +1,40 @@ +package model + +import ( + "blazing/cool" +) + +// 表名常量(遵循现有命名规范:小写+下划线) +const TableNameSignIn = "player_sign_in" + +// SignIn 签到记录表 +// 核心字段:签到完成状态、状压签到进度、签到奖励脚本 +type SignIn struct { + *cool.Model // 嵌入基础Model(包含主键、创建/更新时间等通用字段) + SignInID uint32 `gorm:"not null;index:idx_sign_in_id;comment:'签到活动ID'" json:"sign_in_id"` + Status uint32 `gorm:"not null;default:0;comment:'签到状态(0-未完成 1-已完成)'" json:"status"` + //传入用户名,签到天数,给予奖励,这个搭配里程碑表实现 + RewardScript string `gorm:"type:varchar(512);default:'';comment:'签到奖励脚本(执行奖励发放的脚本内容)'" json:"reward_script"` +} + +// TableName 指定表名(遵循现有规范) +func (*SignIn) TableName() string { + return TableNameSignIn +} + +// GroupName 指定表分组(默认分组,与现有Item表/精灵特效表一致) +func (*SignIn) GroupName() string { + return "default" +} + +// NewSignIn 创建签到记录表实例(初始化基础Model) +func NewSignIn() *SignIn { + return &SignIn{ + Model: cool.NewModel(), + } +} + +// init 程序启动时自动创建表(与现有PlayerPetSpecialEffect表的初始化逻辑一致) +func init() { + cool.CreateTable(&SignIn{}) +} diff --git a/public/config/地图配置野怪.xml b/public/config/地图配置野怪.xml index 49872124b..b5fc3f3f7 100644 --- a/public/config/地图配置野怪.xml +++ b/public/config/地图配置野怪.xml @@ -1266,6 +1266,15 @@ eg: + + + + + + + @@ -3523,6 +3532,10 @@ eg: + + + +