Files
bl/logic/service/player/Monster.go
xinian c021b40fbe
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
feat: 增强踢人逻辑与BOSS脚本支持
优化踢人超时处理和僵尸连接清理,支持BOSS动作脚本并增加测试,修复事件匹配与战斗循环中的并发问题。
2026-04-05 21:59:22 +08:00

256 lines
5.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package player
import (
"blazing/common/utils"
configmodel "blazing/modules/config/model"
playermodel "blazing/modules/player/model"
"sync/atomic"
"time"
"github.com/gogf/gf/v2/util/grand"
"github.com/samber/lo"
)
func (p *Player) IsMatch(t configmodel.Event) bool {
if len(t.Weather) > 0 {
_, ok := lo.Find(t.Weather, func(item int32) bool {
return item == int32(p.GetSpace().MapBossSInfo.Wer)
})
if !ok {
// 不在同一天气下
return false
}
}
if t.StartTime != "" && t.EndTime != "" {
ok, _ := utils.IsCurrentTimeInRange(t.StartTime, t.EndTime)
if !ok {
return false
}
}
if len(t.Week) > 0 {
week := int32(time.Now().Weekday())
if week == 0 {
week = 7
}
_, ok := lo.Find(t.Week, func(item int32) bool {
return item == week
})
if !ok {
return false
}
}
if len(t.Sprites) > 0 && !matchPetIDInList(t.Sprites, p.Info.PetList, p.Info.BackupPetList) {
return false
}
if len(t.FirstSprites) > 0 {
if len(p.Info.PetList) == 0 {
return false
}
firstPetID := int32(p.Info.PetList[0].ID)
_, ok := lo.Find(t.FirstSprites, func(item int32) bool {
return item == firstPetID
})
if !ok {
return false
}
}
if len(t.MustTask) > 0 {
for _, taskID := range t.MustTask {
if p.Info.GetTask(int(taskID)) != playermodel.Completed {
return false
}
}
}
if len(t.MustItem) > 0 {
if p.Service == nil || p.Service.Item == nil {
return false
}
for _, itemID := range t.MustItem {
if p.Service.Item.CheakItem(uint32(itemID)) <= 0 {
return false
}
}
}
return true
}
func matchPetIDInList(targetIDs []int32, petLists ...[]playermodel.PetInfo) bool {
for _, pets := range petLists {
for _, pet := range pets {
petID := int32(pet.ID)
_, ok := lo.Find(targetIDs, func(item int32) bool {
return item == petID
})
if ok {
return true
}
}
}
return false
}
// 应该根据怪物信息决定后端生成
func (p *Player) GenMonster() {
if atomic.LoadUint32(&p.Canmon) == 0 { //已经进入地图或者没在战斗中,就可以刷新怪
return
}
var oldnum, newNum int
var replce []int
p.monsters, oldnum, newNum = replaceOneNumber(p.monsters)
replce = []int{newNum} //产生替换新的精灵
if atomic.CompareAndSwapUint32(&p.Canmon, 2, 1) {
p.Data = [9]OgrePetInfo{} //切地图清空
replce = p.monsters[:] //产生替换新的精灵
}
p.MapNPC.Reset(10 * time.Second)
p.Data[oldnum] = OgrePetInfo{} //切地图清空
for _, i := range replce {
if p.GetSpace().PitS == nil {
continue
}
ogreconfig, ok := p.GetSpace().PitS.Load(i) //service.NewMapPitService().GetData(p.Info.MapID, uint32(i))
if !ok {
continue
}
for _, v := range ogreconfig {
if !p.IsMatch(*v.Event) {
continue
}
p.Data[i] = OgrePetInfo{}
p.Data[i].ID = uint32(v.RefreshID[grand.Intn(len(v.RefreshID))])
if p.Data[i].ID != 0 {
p.Data[i].Lv = uint32(grand.N(v.MinLevel, v.MaxLevel))
if len(v.RefreshID) == 1 { //说明这里只固定刷一个,概率变尼尔尼奥,不是稀有精灵
nieo := grand.Meet(20, 1000)
if nieo {
p.Data[i].Ext = 77
if grand.Meet(1, 2) {
p.Data[i].Ext = 416
}
}
}
p.Data[i].HandleNPCFightSpecial(v.IsCapture)
break
}
}
}
if p != nil {
p.SendPackCmd(2004, &p.OgrePet)
}
}
// 生成0-9之间三个不重复的随机数 进地图5s
func generateThreeUniqueNumbers() [3]int {
selected := make(map[int]bool)
var result [3]int
index := 0
for index < 3 {
num := grand.Intn(9)
if !selected[num] {
selected[num] = true
result[index] = num
index++
}
}
return result
}
// 从三个数字中移除一个并从剩余6个数字中选一个补充 10s
func replaceOneNumber(original [3]int) ([3]int, int, int) {
// 随机选择要移除的索引0-2
removeIndex := grand.Intn(3)
removedNum := original[removeIndex]
// 找出所有不在原始数组中的数字(候选数字)
candidates := []int{}
originalMap := make(map[int]bool)
for _, num := range original {
originalMap[num] = true
}
for i := 0; i < 8; i++ {
if !originalMap[i] {
candidates = append(candidates, i)
}
}
// 从候选数字中随机选择一个
newNum := candidates[grand.Intn(len(candidates))]
// 创建新数组并替换数字
newNumbers := original
newNumbers[removeIndex] = newNum
return newNumbers, removedNum, newNum
}
func GenerateNormalizedColorMatrix() [20]uint8 {
var matrix [20]uint8
// ---------- R/G/B 通道:仅用 grand.N 生成整数(归一化映射) ----------
// 生成权重0~51对应归一化系数 0.0~0.2(不会溢出)
genWeight := func() uint8 { return uint8(grand.N(0, 2)) }
// 生成偏移0~25对应归一化系数 0.0~0.1(不会溢出)
genOffset := func() uint8 { return uint8(grand.N(0, 2)) }
// R 通道索引0-4
matrix[0] = genWeight()
matrix[1] = genWeight()
matrix[2] = genWeight()
matrix[3] = genWeight()
matrix[4] = genOffset()
// G 通道索引5-9
matrix[5] = genWeight()
matrix[6] = genWeight()
matrix[7] = genWeight()
matrix[8] = genWeight()
matrix[9] = genOffset()
// B 通道索引10-14
matrix[10] = genWeight()
matrix[11] = genWeight()
matrix[12] = genWeight()
matrix[13] = genWeight()
matrix[14] = genOffset()
// ---------- A 通道:固定归一化值(无随机) ----------
matrix[15] = 0 // 归一化系数 0.0
matrix[16] = 0 // 归一化系数 0.0
matrix[17] = 0 // 归一化系数 0.0
matrix[18] = 1 // 归一化系数 1.0(透明度权重不变)
matrix[19] = 0 // 归一化系数 0.0
return matrix
}