feat(common/utils): 添加时间范围检查工具函数 添加了 IsCurrentTimeInRange 函数用于判断当前时间是否在指定的 HH:MM 时间区间内,支持当前日期的时间比较功能。 refactor(logic/controller): 重构 Boss 挑战逻辑并集成配置服务 - 集成 service 模块替代原有硬编码逻辑 - 重构 PlayerFightBoss 方法,使用新的配置数据结构 - 移除已废弃的 processMonID 函数和相关注释代码 refactor(logic/space): 优化地图 Boss 信息管理和天气系统 - 更新地图 Boss 数据
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand/v2"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/gogf/gf/v2/util/grand"
|
||||
@@ -122,3 +123,31 @@ func RandomByProbs[T any](natureSet []T, probs []string) (T, error) {
|
||||
// 3. 调用核心函数,复用概率计算逻辑
|
||||
return RandomByWeight(natureSet, probInts)
|
||||
}
|
||||
|
||||
// IsCurrentTimeInRange 判断当前时间是否在 startStr 和 endStr 表示的时间区间内(格式:HH:MM)
|
||||
// 返回值:true=在区间内,false=不在区间内,error=时间解析失败
|
||||
func IsCurrentTimeInRange(startStr, endStr string) (bool, error) {
|
||||
// 1. 解析开始和结束时间字符串为 time.Time 对象(日期用当前日期)
|
||||
now := time.Now()
|
||||
location := now.Location() // 使用当前时区,避免时区偏差
|
||||
|
||||
// 解析开始时间(HH:MM)
|
||||
startTime, err := time.ParseInLocation("15:04", startStr, location)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("解析开始时间 %s 失败:%w", startStr, err)
|
||||
}
|
||||
// 解析结束时间(HH:MM)
|
||||
endTime, err := time.ParseInLocation("15:04", endStr, location)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("解析结束时间 %s 失败:%w", endStr, err)
|
||||
}
|
||||
|
||||
// 2. 把开始/结束时间的日期替换为当前日期(只保留时分)
|
||||
startToday := time.Date(now.Year(), now.Month(), now.Day(),
|
||||
startTime.Hour(), startTime.Minute(), 0, 0, location)
|
||||
endToday := time.Date(now.Year(), now.Month(), now.Day(),
|
||||
endTime.Hour(), endTime.Minute(), 0, 0, location)
|
||||
|
||||
// 3. 比较当前时间是否在 [startToday, endToday] 区间内
|
||||
return now.After(startToday) && now.Before(endToday), nil
|
||||
}
|
||||
|
||||
@@ -10,145 +10,155 @@ import (
|
||||
"blazing/logic/service/fight/info"
|
||||
|
||||
"blazing/logic/service/player"
|
||||
"blazing/modules/config/service"
|
||||
"blazing/modules/player/model"
|
||||
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/gogf/gf/v2/util/grand"
|
||||
)
|
||||
|
||||
// processMonID 处理怪物ID字符串,如果是多个ID则随机选择一个
|
||||
func processMonID(bm string) string {
|
||||
// 按空格分割字符串
|
||||
monid := strings.Split(bm, " ")
|
||||
|
||||
// 过滤分割后可能的空字符串(如连续空格导致的空元素)
|
||||
filtered := make([]string, 0, len(monid))
|
||||
for _, m := range monid {
|
||||
if m != "" {
|
||||
filtered = append(filtered, m)
|
||||
}
|
||||
}
|
||||
monid = filtered
|
||||
|
||||
var selected string
|
||||
switch len(monid) {
|
||||
case 0:
|
||||
// 无元素时,可返回空或默认值(根据业务需求调整)
|
||||
selected = ""
|
||||
case 1:
|
||||
// 长度为1时,取第一个(唯一的元素)
|
||||
selected = monid[0]
|
||||
default:
|
||||
// 长度大于1时,随机选取一个
|
||||
randomIdx := grand.Intn(len(monid))
|
||||
selected = monid[randomIdx]
|
||||
}
|
||||
return selected
|
||||
}
|
||||
|
||||
// PlayerFightBoss 挑战地图boss
|
||||
// data: 包含挑战Boss信息的输入数据
|
||||
// player: 当前玩家对象
|
||||
// 返回: 战斗结果和错误码
|
||||
// func (Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, p *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
// r := p.CanFight()
|
||||
// if p.CanFight() != 0 {
|
||||
// return nil, r
|
||||
// }
|
||||
// var monster *model.PetInfo
|
||||
// monsterInfo := &model.PlayerInfo{}
|
||||
func (Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, p *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
r := p.CanFight()
|
||||
if p.CanFight() != 0 {
|
||||
return nil, r
|
||||
}
|
||||
var monster *model.PetInfo
|
||||
monsterInfo := &model.PlayerInfo{}
|
||||
|
||||
// var taskID int
|
||||
// var canCapture int
|
||||
// mdata, ok := xmlres.MonsterMap[int(p.Info.MapID)]
|
||||
// if !ok {
|
||||
// return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||
// }
|
||||
// if len(mdata.Bosses) == 0 {
|
||||
// return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||
// }
|
||||
// for _, bc := range mdata.Bosses {
|
||||
var taskID int
|
||||
var canCapture int
|
||||
mdata := service.NewMapNodeService().GetDataNode(p.Info.MapID, data.BossId)
|
||||
if mdata == nil {
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||
}
|
||||
|
||||
// if bc.Id == nil {
|
||||
bosinfo := service.NewBossService().Get(mdata.BossIds[0])
|
||||
if bosinfo == nil {
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||
}
|
||||
dv := 24
|
||||
if bosinfo[0].IsCapture == 1 {
|
||||
dv = -1
|
||||
}
|
||||
for i, bm := range bosinfo {
|
||||
|
||||
// bc.Id = gconv.PtrInt(0)
|
||||
// }
|
||||
monster = model.GenPetInfo(
|
||||
gconv.Int(bm.MonID), dv, //24个体
|
||||
-1,
|
||||
0, //野怪没特性
|
||||
|
||||
// if (bc.Id == nil && data.BossId == 0) || uint32(*bc.Id) == data.BossId { //打默认第一个boss
|
||||
// if bc.TaskID != nil {
|
||||
// taskID = *bc.TaskID
|
||||
// }
|
||||
int(bm.Lv), nil, 0)
|
||||
monster.CatchTime = uint32(i)
|
||||
if bm.Hp != 0 {
|
||||
monster.Hp = uint32(bm.Hp)
|
||||
monster.MaxHp = uint32(bm.Hp)
|
||||
}
|
||||
|
||||
// for i, bm := range bc.BossMon {
|
||||
for _, v := range bm.Effect {
|
||||
idx := gconv.Uint16(v)
|
||||
|
||||
// dv := 24
|
||||
// if bc.BossCatchable == 1 {
|
||||
// dv = -1
|
||||
// }
|
||||
if idx == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// monster = model.GenPetInfo(
|
||||
// gconv.Int(processMonID(bm.MonID)), dv, //24个体
|
||||
// -1,
|
||||
// 0, //野怪没特性
|
||||
EID, args := service.NewEffectService().Args(uint32(idx))
|
||||
monster.EffectInfo = append(monster.EffectInfo, model.PetEffectInfo{
|
||||
Idx: idx,
|
||||
EID: gconv.Uint16(EID),
|
||||
Args: gconv.Ints(args),
|
||||
})
|
||||
}
|
||||
monsterInfo.PetList = append(monsterInfo.PetList, *monster)
|
||||
}
|
||||
if bosinfo[0].IsCapture == 1 {
|
||||
canCapture = xmlres.PetMAP[int(monster.ID)].CatchRate
|
||||
if grand.Meet(1, 500) {
|
||||
monsterInfo.PetList[0].RandomByWeightShiny()
|
||||
}
|
||||
|
||||
// bm.Lv, nil, 0)
|
||||
// monster.CatchTime = uint32(i)
|
||||
// if bm.Hp != 0 {
|
||||
// monster.Hp = uint32(bm.Hp)
|
||||
// monster.MaxHp = uint32(bm.Hp)
|
||||
// }
|
||||
}
|
||||
monsterInfo.Nick = mdata.NodeName //xmlres.PetMAP[int(monster.ID)].DefName
|
||||
// for _, bc := range mdata.Bosses {
|
||||
|
||||
// for _, v := range strings.Split(bm.NewSeIdxs, " ") {
|
||||
// idx := gconv.Uint16(v)
|
||||
// if bc.Id == nil {
|
||||
|
||||
// if idx == 0 {
|
||||
// continue
|
||||
// }
|
||||
// bc.Id = gconv.PtrInt(0)
|
||||
// }
|
||||
|
||||
// EID, args := service.NewEffectService().Args(uint32(idx))
|
||||
// monster.EffectInfo = append(monster.EffectInfo, model.PetEffectInfo{
|
||||
// Idx: idx,
|
||||
// EID: gconv.Uint16(EID),
|
||||
// Args: gconv.Ints(args),
|
||||
// })
|
||||
// }
|
||||
// monsterInfo.PetList = append(monsterInfo.PetList, *monster)
|
||||
// }
|
||||
// if bc.BossCatchable == 1 {
|
||||
// canCapture = xmlres.PetMAP[int(monster.ID)].CatchRate
|
||||
// if grand.Meet(1, 500) {
|
||||
// monsterInfo.PetList[0].RandomByWeightShiny()
|
||||
// }
|
||||
// if (bc.Id == nil && data.BossId == 0) || uint32(*bc.Id) == data.BossId { //打默认第一个boss
|
||||
// if bc.TaskID != nil {
|
||||
// taskID = *bc.TaskID
|
||||
// }
|
||||
|
||||
// }
|
||||
// monsterInfo.Nick = bc.Name //xmlres.PetMAP[int(monster.ID)].DefName
|
||||
// break
|
||||
// }
|
||||
// for i, bm := range bc.BossMon {
|
||||
|
||||
// }
|
||||
// if len(monsterInfo.PetList) == 0 {
|
||||
// return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||
// }
|
||||
// p.Fightinfo.Status = info.BattleMode.FIGHT_WITH_NPC
|
||||
// p.Fightinfo.Mode = info.BattleMode.MULTI_MODE
|
||||
// monster = model.GenPetInfo(
|
||||
// gconv.Int(processMonID(bm.MonID)), dv, //24个体
|
||||
// -1,
|
||||
// 0, //野怪没特性
|
||||
|
||||
// ai := player.NewAI_player(monsterInfo)
|
||||
// ai.CanCapture = canCapture
|
||||
// ai.Prop[0] = 2
|
||||
// fight.NewFight(p, ai, func(foi info.FightOverInfo) {
|
||||
// if taskID != 0 {
|
||||
// if foi.Reason == 0 && foi.WinnerId == p.Info.UserID {
|
||||
// p.SptCompletedTask(taskID, 1)
|
||||
// bm.Lv, nil, 0)
|
||||
// monster.CatchTime = uint32(i)
|
||||
// if bm.Hp != 0 {
|
||||
// monster.Hp = uint32(bm.Hp)
|
||||
// monster.MaxHp = uint32(bm.Hp)
|
||||
// }
|
||||
|
||||
// }
|
||||
// }
|
||||
// for _, v := range strings.Split(bm.NewSeIdxs, " ") {
|
||||
// idx := gconv.Uint16(v)
|
||||
|
||||
// //p.Done.Exec(model.MilestoneMode.BOSS, []uint32{p.Info.MapID, data.BossId, uint32(foi.Reason)}, nil)
|
||||
// if idx == 0 {
|
||||
// continue
|
||||
// }
|
||||
|
||||
// })
|
||||
// EID, args := service.NewEffectService().Args(uint32(idx))
|
||||
// monster.EffectInfo = append(monster.EffectInfo, model.PetEffectInfo{
|
||||
// Idx: idx,
|
||||
// EID: gconv.Uint16(EID),
|
||||
// Args: gconv.Ints(args),
|
||||
// })
|
||||
// }
|
||||
// monsterInfo.PetList = append(monsterInfo.PetList, *monster)
|
||||
// }
|
||||
// if bc.BossCatchable == 1 {
|
||||
// canCapture = xmlres.PetMAP[int(monster.ID)].CatchRate
|
||||
// if grand.Meet(1, 500) {
|
||||
// monsterInfo.PetList[0].RandomByWeightShiny()
|
||||
// }
|
||||
|
||||
// return nil, -1
|
||||
// }
|
||||
// }
|
||||
// monsterInfo.Nick = bc.Name //xmlres.PetMAP[int(monster.ID)].DefName
|
||||
// break
|
||||
// }
|
||||
|
||||
// }
|
||||
if len(monsterInfo.PetList) == 0 {
|
||||
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
|
||||
}
|
||||
p.Fightinfo.Status = info.BattleMode.FIGHT_WITH_NPC
|
||||
p.Fightinfo.Mode = info.BattleMode.MULTI_MODE
|
||||
|
||||
ai := player.NewAI_player(monsterInfo)
|
||||
ai.CanCapture = canCapture
|
||||
ai.Prop[0] = 2
|
||||
fight.NewFight(p, ai, func(foi info.FightOverInfo) {
|
||||
if taskID != 0 {
|
||||
if foi.Reason == 0 && foi.WinnerId == p.Info.UserID {
|
||||
p.SptCompletedTask(taskID, 1)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//p.Done.Exec(model.MilestoneMode.BOSS, []uint32{p.Info.MapID, data.BossId, uint32(foi.Reason)}, nil)
|
||||
|
||||
})
|
||||
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// OnPlayerFightNpcMonster 战斗野怪
|
||||
// data: 包含战斗野怪信息的输入数据
|
||||
|
||||
@@ -68,19 +68,19 @@ func (h Controller) GetMapPlayerList(data *space.ListMapPlayerInboundInfo, c *pl
|
||||
if atomic.LoadUint32(&c.GetSpace().TimeBoss.Flag) == 1 {
|
||||
c.SendPackCmd(2022, &c.GetSpace().TimeBoss)
|
||||
}
|
||||
if c.GetSpace().MapBossInfo.Pos != 200 {
|
||||
var t info.MapBossSInfo
|
||||
t.INFO = append(t.INFO, c.GetSpace().MapBossInfo)
|
||||
c.SendPackCmd(2021, &t)
|
||||
if len(c.GetSpace().MapBossSInfo.INFO) > 0 {
|
||||
c.SendPackCmd(2021, &c.GetSpace().MapBossSInfo)
|
||||
|
||||
}
|
||||
c.SendPackCmd(50004, &info.S2C_50004{Id: uint32(c.GetSpace().Weather)}) //获取天气
|
||||
|
||||
return nil, -1
|
||||
}
|
||||
func (h Controller) AttackBoss(data *space.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)
|
||||
for _, v := range c.GetSpace().MapBossSInfo.INFO {
|
||||
if atomic.LoadInt32(&v.Hp) > 0 {
|
||||
atomic.AddInt32(&v.Hp, -1)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
|
||||
func (p *Player) IsMatch(t model.Event) bool {
|
||||
_, ok := lo.Find(t.Weather, func(item int32) bool {
|
||||
return item == int32(p.GetSpace().Weather)
|
||||
return item == int32(p.GetSpace().MapBossSInfo.Wer)
|
||||
})
|
||||
if !ok {
|
||||
// 不在同一天气下
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
package space
|
||||
|
||||
import (
|
||||
"blazing/cool"
|
||||
"blazing/logic/service/space/info"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/util/grand"
|
||||
)
|
||||
|
||||
func (s *Space) getfixboss(mapid uint32) {
|
||||
|
||||
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(s.Name, "pos", s.MapBossInfo.Pos, "hp", s.MapBossInfo.Hp)
|
||||
var t info.MapBossSInfo
|
||||
t.INFO = append(t.INFO, s.MapBossInfo)
|
||||
|
||||
s.Broadcast(nil, 2021, &t)
|
||||
|
||||
})
|
||||
cool.Cron.ScheduleFunc(300*time.Second, func() {
|
||||
|
||||
atomic.StoreInt32(&s.MapBossInfo.Hp, 10)
|
||||
|
||||
})
|
||||
|
||||
case 108:
|
||||
s.MapBossInfo = info.MapBossInfo{
|
||||
Id: 219,
|
||||
}
|
||||
|
||||
cool.Cron.ScheduleFunc(10*time.Second, func() {
|
||||
var t info.MapBossSInfo
|
||||
s.MapBossInfo.Pos = (grand.Intn(6) + 1 + s.MapBossInfo.Pos) % 6
|
||||
t.INFO = append(t.INFO, s.MapBossInfo)
|
||||
|
||||
s.Broadcast(nil, 2021, &t)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package space
|
||||
|
||||
import (
|
||||
"blazing/logic/service/space/info"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/util/grand"
|
||||
)
|
||||
|
||||
func (s *Space) getwerboss() {
|
||||
println("天气变化地图", s.Name, "pos", s.MapBossInfo.Pos, "wer", s.Weather)
|
||||
switch s.ID {
|
||||
case 12:
|
||||
|
||||
case 32:
|
||||
|
||||
s.MapBossInfo = info.MapBossInfo{
|
||||
Id: 70,
|
||||
}
|
||||
|
||||
var t info.MapBossSInfo
|
||||
s.MapBossInfo.Id = 70
|
||||
if s.Weather == 1 {
|
||||
s.MapBossInfo.Pos = 0
|
||||
|
||||
} else {
|
||||
|
||||
s.MapBossInfo.Pos = 200
|
||||
|
||||
}
|
||||
t.INFO = append(t.INFO, s.MapBossInfo)
|
||||
|
||||
s.Broadcast(nil, 2021, &t)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (t *Space) Next(time.Time) time.Time {
|
||||
|
||||
return time.Now().Add(grand.D(6*time.Second, 30*time.Second))
|
||||
|
||||
}
|
||||
@@ -30,15 +30,21 @@ type WalkOutInfo struct {
|
||||
}
|
||||
|
||||
type MapBossSInfo struct {
|
||||
Wer int32 `struc:"uint32"`
|
||||
InfoLen uint32 `struc:"sizeof=INFO" json:"info_len"`
|
||||
|
||||
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 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==200时候将会删除boss显示
|
||||
Id uint32 `json:"id" protobuf:"1,req,name=id"` // 需要刷新的BOSS精灵ID
|
||||
Region uint32 `json:"region" protobuf:"2,req,name=region"` //index,直接给boss的节点ID
|
||||
Hp int32 `struc:"uint32" json:"hp" protobuf:"3,req,name=hp"` // HP值(蘑菇怪为A,其他BOSS暂未明确用途,可能无实际作用)
|
||||
Pos model.Pos
|
||||
IsShow int32 `struc:"uint32" json:"is_show"` // 雷伊首次出现的时候给2,正常精灵给1,雷伊是否首次出现的判断是否首次刷新,
|
||||
PosInfo []model.Pos `struc:"skip"`
|
||||
MaxHP int `struc:"skip"`
|
||||
PosIndex uint32 `struc:"skip"`
|
||||
Wer []int32 `struc:"skip"`
|
||||
}
|
||||
|
||||
// 这里存储星球的map
|
||||
@@ -166,10 +172,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是雪
|
||||
|
||||
}
|
||||
type S2C_2022 struct {
|
||||
Flag uint32 `json:"flag" protobuf:"1,req,name=flag"`
|
||||
ID uint32 `json:"id" protobuf:"2,req,name=id"`
|
||||
|
||||
@@ -5,11 +5,19 @@ import (
|
||||
"blazing/common/utils"
|
||||
"blazing/cool"
|
||||
"blazing/modules/config/service"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"blazing/logic/service/common"
|
||||
"blazing/logic/service/space/info"
|
||||
|
||||
infomodel "blazing/modules/player/model"
|
||||
|
||||
"github.com/gogf/gf/v2/util/grand"
|
||||
csmap "github.com/mhmtszr/concurrent-swiss-map"
|
||||
"github.com/samber/lo"
|
||||
"github.com/tnnmigga/enum"
|
||||
)
|
||||
|
||||
@@ -30,10 +38,12 @@ type Space struct {
|
||||
ID uint32 // 地图ID
|
||||
Name string //地图名称
|
||||
Owner ARENA
|
||||
info.MapBossInfo
|
||||
info.MapBossSInfo
|
||||
IsChange bool
|
||||
|
||||
TimeBoss info.S2C_2022
|
||||
Weather uint32
|
||||
IsTime bool
|
||||
//Weather uint32
|
||||
IsTime bool
|
||||
//CanWeather uint32
|
||||
}
|
||||
|
||||
@@ -67,8 +77,7 @@ func GetSpace(id uint32) *Space {
|
||||
ret.Super = uint32(v.ID)
|
||||
}
|
||||
ret.ID = uint32(v.ID)
|
||||
ret.getfixboss(uint32(v.ID))
|
||||
//t.gettimeboss(uint32(v.ID))
|
||||
|
||||
_, ok := maphot[ret.Super]
|
||||
if !ok {
|
||||
var t1 int32
|
||||
@@ -84,9 +93,12 @@ func GetSpace(id uint32) *Space {
|
||||
|
||||
r := service.NewMapService().GetData(ret.ID)
|
||||
if r != nil {
|
||||
|
||||
if r.IsTimeSpace != 0 {
|
||||
ret.IsTime = true
|
||||
}
|
||||
ret.MapBossSInfo = info.MapBossSInfo{}
|
||||
ret.MapBossSInfo.INFO = make([]info.MapBossInfo, 0)
|
||||
if len(r.WeatherType) > 1 {
|
||||
// ret.CanWeather = 1
|
||||
cool.Cron.CustomFunc(ret, func() {
|
||||
@@ -99,16 +111,67 @@ func GetSpace(id uint32) *Space {
|
||||
neww, _ = utils.RandomByWeight(r.WeatherType, []uint32{8, 1, 1})
|
||||
}
|
||||
|
||||
if neww != ret.Weather {
|
||||
ret.Broadcast(nil, 50004, &info.S2C_50004{Id: uint32(neww)})
|
||||
ret.Weather = neww
|
||||
ret.getwerboss()
|
||||
if neww != uint32(ret.MapBossSInfo.Wer) {
|
||||
ret.IsChange = true
|
||||
ret.MapBossSInfo.Wer = int32(neww)
|
||||
|
||||
} else {
|
||||
ret.IsChange = false
|
||||
}
|
||||
|
||||
//}
|
||||
|
||||
})
|
||||
}
|
||||
for _, v := range service.NewMapNodeService().GetData(ret.ID) {
|
||||
|
||||
if v.IsBroadcast != 0 { //说明是地图怪
|
||||
info := info.MapBossInfo{
|
||||
|
||||
Region: v.NodeID, //这个是注册的index
|
||||
Hp: v.HP,
|
||||
PosInfo: ParseCoordinateString(v.Pos),
|
||||
MaxHP: int(v.HP),
|
||||
Wer: v.Weather,
|
||||
}
|
||||
bossid := uint32(service.NewBossService().Get(v.BossIds[0])[0].MonID)
|
||||
info.Id = bossid
|
||||
ret.MapBossSInfo.INFO = append(ret.MapBossSInfo.INFO, info)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if len(ret.MapBossSInfo.INFO) > 0 {
|
||||
cool.Cron.ScheduleFunc(10*time.Second, func() {
|
||||
|
||||
for i := 0; i < len(ret.MapBossSInfo.INFO); i++ {
|
||||
s := len(ret.MapBossSInfo.INFO[i].PosInfo)
|
||||
ret.MapBossSInfo.INFO[i].Pos = ret.MapBossSInfo.INFO[i].PosInfo[(grand.Intn(s-1)+1+int(ret.MapBossSInfo.INFO[i].PosIndex))%s]
|
||||
|
||||
_, ok := lo.Find(ret.MapBossSInfo.INFO[i].Wer, func(item int32) bool {
|
||||
return item == ret.MapBossSInfo.Wer
|
||||
})
|
||||
if ok {
|
||||
ret.MapBossSInfo.INFO[i].IsShow = 1
|
||||
if ret.IsChange {
|
||||
ret.MapBossSInfo.INFO[i].IsShow = 2
|
||||
}
|
||||
} else {
|
||||
ret.MapBossSInfo.INFO[i].IsShow = 0
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ret.Broadcast(nil, 2021, &ret.MapBossSInfo)
|
||||
|
||||
})
|
||||
cool.Cron.ScheduleFunc(300*time.Second, func() {
|
||||
for _, v := range ret.MapBossSInfo.INFO {
|
||||
atomic.StoreInt32(&v.Hp, int32(v.MaxHP))
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -117,3 +180,53 @@ func GetSpace(id uint32) *Space {
|
||||
}
|
||||
|
||||
var planetmap = csmap.New[uint32, *Space]()
|
||||
|
||||
func ParseCoordinateString(s string) []infomodel.Pos {
|
||||
// 存储解析后的坐标
|
||||
var points []infomodel.Pos
|
||||
|
||||
// 空字符串处理
|
||||
if strings.TrimSpace(s) == "" {
|
||||
return points
|
||||
}
|
||||
|
||||
// 第一步:按竖线分割成单个坐标字符串
|
||||
coordStrs := strings.Split(s, "|")
|
||||
for _, coordStr := range coordStrs {
|
||||
// 去除首尾空格(兼容可能的格式不规范)
|
||||
coordStr = strings.TrimSpace(coordStr)
|
||||
if coordStr == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 第二步:按逗号分割X、Y值
|
||||
xy := strings.Split(coordStr, ",")
|
||||
if len(xy) != 2 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 第三步:转换为整数
|
||||
xStr := strings.TrimSpace(xy[0])
|
||||
yStr := strings.TrimSpace(xy[1])
|
||||
|
||||
x, err := strconv.Atoi(xStr)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
y, err := strconv.Atoi(yStr)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 添加到切片
|
||||
points = append(points, infomodel.Pos{X: uint32(x), Y: uint32(y)})
|
||||
}
|
||||
|
||||
return points
|
||||
}
|
||||
func (t *Space) Next(time.Time) time.Time {
|
||||
|
||||
return time.Now().Add(grand.D(6*time.Second, 30*time.Second))
|
||||
|
||||
}
|
||||
|
||||
@@ -15,13 +15,14 @@ type MapConfig struct {
|
||||
// 核心字段
|
||||
MapID uint32 `gorm:"not null;primaryKey;comment:'地图唯一ID(主键)'" json:"map_id" description:"地图ID"`
|
||||
|
||||
WeatherType []uint32 `gorm:"type:int[];comment:'天气类型( 1-雨天,2-雪天)'" json:"weather_type"`
|
||||
WeatherType []uint32 `gorm:"type:int[];comment:'天气类型( 0 晴天,1-雨天,2-雪天)'" json:"weather_type"`
|
||||
//是否超时空
|
||||
IsTimeSpace int `gorm:"type:int;default:0;comment:'是否超时空'" json:"is_time_space"`
|
||||
|
||||
// 掉落物配置
|
||||
DropItemIds []uint32 `gorm:"type:int[];comment:'掉落物IDs" json:"drop_item_ids"`
|
||||
Remark string `gorm:"type:varchar(255);default:'';comment:'性别配置备注(如:默认性别规则)'" json:"remark"` // 调整注释
|
||||
|
||||
Remark string `gorm:"type:varchar(255);default:'';comment:'性别配置备注(如:默认性别规则)'" json:"remark"` // 调整注释
|
||||
}
|
||||
|
||||
// -------------------------- 核心配套方法(遵循项目规范)--------------------------
|
||||
|
||||
@@ -31,11 +31,13 @@ type MapNode struct {
|
||||
NodeName string `gorm:"type:varchar(100);default:'';comment:'节点名称'" json:"node_name" description:"节点名称"`
|
||||
//节点激活脚本
|
||||
|
||||
PositionX float64 `gorm:"not null;default:0;comment:'节点X坐标'" json:"position_x" description:"X坐标"`
|
||||
PositionY float64 `gorm:"not null;default:0;comment:'节点Y坐标'" json:"position_y" description:"Y坐标"`
|
||||
Pos string `gorm:"type:varchar(255);default:'';comment:'位置'" json:"pos"`
|
||||
HP int32 `gorm:"type:int;default:0;comment:'血量'" json:"hp" description:"血量"`
|
||||
|
||||
WinBonusID int `gorm:"type:int;default:0;comment:'胜利奖励ID'" json:"win_bonus_id"`
|
||||
FailBonusID int `gorm:"type:int;default:0;comment:'失败奖励ID'" json:"fail_bonus_id"`
|
||||
//是否需要广播,比如雷伊
|
||||
IsBroadcast int `gorm:"type:int;default:0;comment:'是否需要广播'" json:"is_broadcast"`
|
||||
// 剧情相关配置
|
||||
TriggerPlotID uint32 `gorm:"default:0;comment:'触发剧情ID(0表示无剧情)'" json:"trigger_plot_id" description:"触发剧情ID"`
|
||||
//BindPlotIDs []uint32 `gorm:"type:int[];comment:'绑定的剧情ID列表'" json:"bind_plot_ids" description:"绑定剧情ID列表"`
|
||||
|
||||
@@ -20,10 +20,18 @@ func NewMapNodeService() *MapNodeService {
|
||||
},
|
||||
}
|
||||
}
|
||||
func (s *MapNodeService) GetData(mapid, pos uint32) []model.MapNode {
|
||||
func (s *MapNodeService) GetData(mapid uint32) []model.MapNode {
|
||||
|
||||
var pet []model.MapNode //一个特性应该是唯一的,但是我们要获取默认随机特性
|
||||
dbm_enable(s.Model).Where("map_id", mapid).Wheref(`pos @> ARRAY[?]::integer[]`, pos).Scan(&pet)
|
||||
dbm_enable(s.Model).Where("map_id", mapid).Scan(&pet)
|
||||
|
||||
return pet
|
||||
|
||||
}
|
||||
func (s *MapNodeService) GetDataNode(mapid, node uint32) *model.MapNode {
|
||||
|
||||
var pet *model.MapNode //一个特性应该是唯一的,但是我们要获取默认随机特性
|
||||
dbm_enable(s.Model).Where("map_id", mapid).Where("node_id", node).Scan(&pet)
|
||||
|
||||
return pet
|
||||
|
||||
|
||||
Reference in New Issue
Block a user