diff --git a/logic/controller/map.go b/logic/controller/map.go index 96c39366..e05c423b 100644 --- a/logic/controller/map.go +++ b/logic/controller/map.go @@ -38,7 +38,6 @@ func (h Controller) MapHot(data *maphot.InInfo, c *player.Player) (result *mapho } func (h *Controller) MapLeave(data *maps.LeaveMapInboundInfo, c *player.Player) (result *info.LeaveMapOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的 - atomic.StoreUint32(&c.Canmon, 0) //data.Broadcast(c.Info.MapID, info.LeaveMapOutboundInfo{UserID: c.Info.UserID}) //同步广播 result = &info.LeaveMapOutboundInfo{ UserID: c.Info.UserID, @@ -52,6 +51,10 @@ func (h *Controller) MapLeave(data *maps.LeaveMapInboundInfo, c *player.Player) } func (h *Controller) MapList(data *maps.ListMapPlayerInboundInfo, c *player.Player) (result *info.ListMapPlayerOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的 atomic.StoreUint32(&c.Canmon, 2) + atomic.StoreUint32(&c.Canmon, 0) + if atomic.LoadUint32(&c.GetSpace().TimeBoss.Flag) == 1 { + defer c.SendPackCmd(2022, &c.GetSpace().TimeBoss) + } result = &info.ListMapPlayerOutboundInfo{ Player: c.GetSpace().GetInfo(), } diff --git a/logic/service/fight/info/info.go b/logic/service/fight/info/info.go index 88419fc5..3928b0a4 100644 --- a/logic/service/fight/info/info.go +++ b/logic/service/fight/info/info.go @@ -275,7 +275,9 @@ type FightOverInfo struct { // 3=isDraw 双方平手 // 4=isSysError 系统错误 // 5=isNpcEscape 精灵主动逃跑 - Winpet *model.PetInfo `struc:"skip"` + Winpet *model.PetInfo `struc:"skip"` + Round uint32 `struc:"skip"` + LastAttavue AttackValue `struc:"skip"` //7 切磋结束 Reason EnumBattleOverReason // 固定值0 WinnerId uint32 // 胜者的米米号 野怪为0 diff --git a/logic/service/maps/info/info.go b/logic/service/maps/info/info.go index 59ddfb43..1356eed9 100644 --- a/logic/service/maps/info/info.go +++ b/logic/service/maps/info/info.go @@ -37,7 +37,7 @@ 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 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;战斗退出后该值会变化) + Pos int `struc:"uint32" json:"pos" protobuf:"4,req,name=pos"` // 刷新坐标(类似野怪的位置ID,蘑菇怪初始为2; pos==200时候将会删除boss显示 } // 这里存储星球的map @@ -171,3 +171,7 @@ type S2C_50004 struct { Id uint32 `json:"id" protobuf:"1,req,name=id"` // 天气0没有,1是雨.2是雪 } +type S2C_2022 struct { + Flag uint32 `json:"flag" protobuf:"1,req,name=flag"` + ID uint32 `json:"id" protobuf:"2,req,name=id"` +} diff --git a/logic/service/space/in_out.go b/logic/service/space/in_out.go index 041a2ab6..144a813b 100644 --- a/logic/service/space/in_out.go +++ b/logic/service/space/in_out.go @@ -94,7 +94,7 @@ func (s *Space) Walk(c common.PlayerI, info *info.WalkOutInfo) { s.Broadcast(c, 2101, info) } -func (s *Space) gettimeboss(mapid uint32) { +func (s *Space) getfixboss(mapid uint32) { var t info.MapBossSInfo t.INFO = append(t.INFO, s.MapBossInfo) switch mapid { diff --git a/logic/service/space/space.go b/logic/service/space/space.go index ada371fe..3fcea5a4 100644 --- a/logic/service/space/space.go +++ b/logic/service/space/space.go @@ -18,10 +18,11 @@ type Space struct { CanRefresh bool //是否能够刷怪 Super uint32 //SuperValue *int32 - //ID uint32 // 地图ID + ID uint32 // 地图ID Name string //地图名称 Owner ARENA info.MapBossInfo + TimeBoss info.S2C_2022 } // NewSyncMap 创建一个新的玩家同步map @@ -81,7 +82,9 @@ func GetSpace(id uint32) *Space { if t.Super == 0 { t.Super = uint32(v.ID) } - t.gettimeboss(uint32(v.ID)) + t.ID = uint32(v.ID) + t.getfixboss(uint32(v.ID)) + //t.gettimeboss(uint32(v.ID)) _, ok := maphot[t.Super] if !ok { var t1 int32 diff --git a/logic/service/space/timeboss.go b/logic/service/space/timeboss.go new file mode 100644 index 00000000..f8c9047a --- /dev/null +++ b/logic/service/space/timeboss.go @@ -0,0 +1,232 @@ +package space + +import ( + "blazing/cool" + "math/rand" + "strconv" + "strings" + "sync" + "sync/atomic" + "time" +) + +// ========== 1. 定义TimeBoss的定时规则(补全周四-周六,新增周日规则) ========== +// TimeBossRule 单个BOSS的定时规则 +type TimeBossRule struct { + PetID uint32 // BOSS ID(对应XML的petID="261") + Week int // 星期(1=周一,2=周二...7=周日) + ShowHours []int // 出现小时(如12,17,18,24);周日填0-23表示每小时 + ShowMinute int // 出现分钟(如35,0) + LastTime int // 持续时间(分钟) + MapIDs []uint32 // 可选刷新地图ID列表(随机选一个) +} + +// 全局:261号BOSS的规则配置(补全周四-周六,新增周日) +var timeBossRules = []TimeBossRule{ + // 周一规则 + { + PetID: 261, + Week: 1, // 周一 + ShowHours: []int{12, 17, 18, 24}, // 12|17|18|24点35分 + ShowMinute: 35, // 35分 + LastTime: 40, // 持续40分钟 + MapIDs: []uint32{15, 105, 54}, // 随机选一个地图 + }, + // 周日规则(特殊:每小时刷新,持续10分钟) + { + PetID: 261, + Week: 2, // 周日 + ShowHours: generateHourRange(0, 23), // 0-23点(每小时) + ShowMinute: 33, // 每小时0分触发 + LastTime: 10, // 持续10分钟 + MapIDs: []uint32{15, 105, 54}, // 随机选一个地图 + }, + // 周二规则 + // { + // PetID: 261, + // Week: 2, // 周二 + // ShowHours: []int{17, 18, 24}, // 17|18|24点0分 + // ShowMinute: 0, // 0分 + // LastTime: 5, // 持续5分钟 + // MapIDs: []uint32{15, 105, 54}, + // }, + // 周三规则 + { + PetID: 261, + Week: 3, // 周三 + ShowHours: []int{17, 18, 24}, // 17|18|24点0分 + ShowMinute: 0, // 0分 + LastTime: 5, // 持续5分钟 + MapIDs: []uint32{15, 105, 54}, + }, + // 周四规则(和周一完全一致) + { + PetID: 261, + Week: 4, // 周四 + ShowHours: []int{12, 17, 18, 24}, // 12|17|18|24点35分 + ShowMinute: 35, // 35分 + LastTime: 40, // 持续40分钟 + MapIDs: []uint32{15, 105, 54}, + }, + // 周五规则(和周二完全一致) + { + PetID: 261, + Week: 5, // 周五 + ShowHours: []int{17, 18, 24}, // 17|18|24点0分 + ShowMinute: 0, // 0分 + LastTime: 5, // 持续5分钟 + MapIDs: []uint32{15, 105, 54}, + }, + // 周六规则(和周三完全一致) + { + PetID: 261, + Week: 6, // 周六 + ShowHours: []int{17, 18, 24}, // 17|18|24点0分 + ShowMinute: 0, // 0分 + LastTime: 5, // 持续5分钟 + MapIDs: []uint32{15, 105, 54}, + }, + // 周日规则(特殊:每小时刷新,持续10分钟) + { + PetID: 261, + Week: 7, // 周日 + ShowHours: generateHourRange(0, 23), // 0-23点(每小时) + ShowMinute: 0, // 每小时0分触发 + LastTime: 10, // 持续10分钟 + MapIDs: []uint32{15, 105, 54}, // 随机选一个地图 + }, +} + +// ========== 2. 全局变量(无修改,新增随机数生成器已存在) ========== +var ( + registeredCronIDs = make(map[string]bool) // 记录已注册的Cron任务ID + cronMu sync.Mutex // 保护registeredCronIDs的互斥锁 + randSource = rand.New(rand.NewSource(time.Now().UnixNano())) // 安全的随机数生成器 +) + +// ========== 3. 工具函数:生成0-23小时数组(适配周日每小时规则) ========== +// generateHourRange 生成从start到end的连续小时数组(如0-23) +func generateHourRange(start, end int) []int { + hours := make([]int, 0, end-start+1) + for i := start; i <= end; i++ { + hours = append(hours, i) + } + return hours +} + +// ========== 4. 原有方法:gettimeboss(无修改,自动适配新规则) ========== +func init() { // 忽略传入的mapid,随机选地图 + + // 遍历所有TimeBoss规则(包含周四-周六-周日) + for _, rule := range timeBossRules { + + // 为该规则的每个小时生成Cron任务 + for _, hour := range rule.ShowHours { + // 生成唯一Cron任务ID(避免重复注册) + cronID := genCronTaskID(rule.PetID, rule.Week, hour, rule.ShowMinute) + cronMu.Lock() + if registeredCronIDs[cronID] { + cronMu.Unlock() + continue // 已注册过,跳过 + } + registeredCronIDs[cronID] = true + cronMu.Unlock() + + // 转换规则为Cron表达式 + cronExpr := genCronExpr(rule.Week, hour, rule.ShowMinute) + + // 捕获当前循环的rule(避免闭包引用同一变量) + currentRule := rule + + // 注册Cron定时任务 + cool.Cron.AddFunc(cronExpr, func() { + // 1. 随机选一个地图ID + randomMapID := getRandomMapID(currentRule.MapIDs) + if randomMapID == 0 { + return // 无可用地图,跳过 + } + + sp := GetSpace(randomMapID) + if sp != nil { + // 2. 显示BOSS(指定随机地图广播) + sp.refushgaiya(true) + + // 3. 启动定时器:持续时间到后隐藏BOSS(同样指定地图) + time.AfterFunc(time.Duration(currentRule.LastTime)*time.Minute, func() { + sp.refushgaiya(false) + }) + } + + }) + } + } +} + +// ========== 5. 修改后的refushgaiya(指定地图广播) ========== +func (s *Space) refushgaiya(vis bool) { + + if !vis { + atomic.StoreUint32(&s.TimeBoss.Flag, 0) + } else { + atomic.StoreUint32(&s.TimeBoss.Flag, 1) + } + atomic.StoreUint32(&s.TimeBoss.ID, 261) + + // 只向指定地图广播(核心:不再全局广播) + s.Broadcast(nil, 2022, &s.TimeBoss) + +} + +// ========== 6. 工具函数(无修改,自动适配周日规则) ========== +// getRandomMapID 从地图列表中随机选一个 +func getRandomMapID(mapIDs []uint32) uint32 { + if len(mapIDs) == 0 { + return 0 + } + return mapIDs[randSource.Intn(len(mapIDs))] +} + +// genCronExpr 生成Cron表达式(自动适配周日的0值) +func genCronExpr(week, hour, minute int) string { + // 1. 处理小时:24点转为0点(Cron小时范围0-23) + cronHour := hour + if cronHour == 24 { + cronHour = 0 + } + + // 2. 处理星期:XML的7=周日 → Cron的0=周日,其余直接用 + cronWeek := week + if cronWeek == 7 { + cronWeek = 0 + } + + // 3. 生成Cron表达式(秒 分 时 日 月 周) + return strings.Join([]string{ + "0", // 秒(固定0,整分触发) + strconv.Itoa(minute), // 分 + strconv.Itoa(cronHour), // 时 + "?", // 日(不指定) + "*", // 月(每月) + strconv.Itoa(cronWeek), // 周 + }, " ") +} + +// genCronTaskID 生成唯一的Cron任务ID +func genCronTaskID(petID uint32, week, hour, minute int) string { + return strings.Join([]string{ + strconv.FormatUint(uint64(petID), 10), + strconv.Itoa(week), + strconv.Itoa(hour), + strconv.Itoa(minute), + }, "_") +} + +// containsMapID 检查mapid是否在列表中(备用) +func containsMapID(mapIDs []uint32, mapid uint32) bool { + for _, id := range mapIDs { + if id == mapid { + return true + } + } + return false +}