2025-12-10 13:54:51 +00:00
|
|
|
|
package player
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2026-03-02 01:36:16 +08:00
|
|
|
|
"blazing/common/utils"
|
2026-04-05 21:59:22 +08:00
|
|
|
|
configmodel "blazing/modules/config/model"
|
|
|
|
|
|
playermodel "blazing/modules/player/model"
|
2025-12-10 13:54:51 +00:00
|
|
|
|
"sync/atomic"
|
2025-12-16 08:35:22 +00:00
|
|
|
|
"time"
|
2025-12-10 13:54:51 +00:00
|
|
|
|
|
|
|
|
|
|
"github.com/gogf/gf/v2/util/grand"
|
2025-12-28 14:40:17 +00:00
|
|
|
|
"github.com/samber/lo"
|
2025-12-10 13:54:51 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
2026-04-05 21:59:22 +08:00
|
|
|
|
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
|
|
|
|
|
|
}
|
2026-02-25 16:18:10 +08:00
|
|
|
|
}
|
2026-04-05 21:59:22 +08:00
|
|
|
|
|
2026-03-02 01:36:16 +08:00
|
|
|
|
if t.StartTime != "" && t.EndTime != "" {
|
|
|
|
|
|
ok, _ := utils.IsCurrentTimeInRange(t.StartTime, t.EndTime)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-02-25 16:18:10 +08:00
|
|
|
|
|
2026-04-05 21:59:22 +08:00
|
|
|
|
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
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 16:18:10 +08:00
|
|
|
|
return true
|
2026-04-05 21:59:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-12-10 13:54:51 +00:00
|
|
|
|
|
2026-04-05 21:59:22 +08:00
|
|
|
|
return false
|
2025-12-10 13:54:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 应该根据怪物信息决定后端生成
|
2026-01-20 02:25:02 +08:00
|
|
|
|
func (p *Player) GenMonster() {
|
2026-02-07 16:56:43 +08:00
|
|
|
|
|
2025-12-16 08:35:22 +00:00
|
|
|
|
if atomic.LoadUint32(&p.Canmon) == 0 { //已经进入地图或者没在战斗中,就可以刷新怪
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2026-02-20 23:33:24 +08:00
|
|
|
|
|
2025-12-10 13:54:51 +00:00
|
|
|
|
var oldnum, newNum int
|
2025-12-28 14:40:17 +00:00
|
|
|
|
var replce []int
|
2025-12-10 13:54:51 +00:00
|
|
|
|
p.monsters, oldnum, newNum = replaceOneNumber(p.monsters)
|
2025-12-28 14:40:17 +00:00
|
|
|
|
replce = []int{newNum} //产生替换新的精灵
|
|
|
|
|
|
if atomic.CompareAndSwapUint32(&p.Canmon, 2, 1) {
|
2026-02-03 00:23:51 +08:00
|
|
|
|
|
2026-02-23 04:12:12 +08:00
|
|
|
|
p.Data = [9]OgrePetInfo{} //切地图清空
|
|
|
|
|
|
replce = p.monsters[:] //产生替换新的精灵
|
2025-12-28 14:40:17 +00:00
|
|
|
|
|
|
|
|
|
|
}
|
2026-02-03 00:23:51 +08:00
|
|
|
|
p.MapNPC.Reset(10 * time.Second)
|
2026-02-23 04:12:12 +08:00
|
|
|
|
p.Data[oldnum] = OgrePetInfo{} //切地图清空
|
2026-02-23 04:07:23 +08:00
|
|
|
|
|
2026-02-25 16:18:10 +08:00
|
|
|
|
for _, i := range replce {
|
2026-03-03 00:31:36 +08:00
|
|
|
|
if p.GetSpace().PitS == nil {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
2026-03-02 23:59:15 +08:00
|
|
|
|
|
|
|
|
|
|
ogreconfig, ok := p.GetSpace().PitS.Load(i) //service.NewMapPitService().GetData(p.Info.MapID, uint32(i))
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
2026-03-17 18:24:50 +08:00
|
|
|
|
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))])
|
2025-12-28 14:40:17 +00:00
|
|
|
|
|
2026-03-17 18:24:50 +08:00
|
|
|
|
if p.Data[i].ID != 0 {
|
2025-12-14 20:32:54 +08:00
|
|
|
|
|
2026-03-17 18:24:50 +08:00
|
|
|
|
p.Data[i].Lv = uint32(grand.N(v.MinLevel, v.MaxLevel))
|
2026-02-26 00:05:43 +08:00
|
|
|
|
|
2026-03-17 18:24:50 +08:00
|
|
|
|
if len(v.RefreshID) == 1 { //说明这里只固定刷一个,概率变尼尔尼奥,不是稀有精灵
|
2025-12-10 13:54:51 +00:00
|
|
|
|
|
2026-03-17 18:24:50 +08:00
|
|
|
|
nieo := grand.Meet(20, 1000)
|
|
|
|
|
|
if nieo {
|
|
|
|
|
|
p.Data[i].Ext = 77
|
|
|
|
|
|
if grand.Meet(1, 2) {
|
|
|
|
|
|
p.Data[i].Ext = 416
|
|
|
|
|
|
}
|
2025-12-10 13:54:51 +00:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2026-03-17 18:24:50 +08:00
|
|
|
|
p.Data[i].HandleNPCFightSpecial(v.IsCapture)
|
|
|
|
|
|
break
|
2026-02-23 04:04:32 +08:00
|
|
|
|
|
2025-12-10 13:54:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2026-02-25 16:18:10 +08:00
|
|
|
|
|
2026-02-07 16:56:43 +08:00
|
|
|
|
if p != nil {
|
2026-02-23 04:12:12 +08:00
|
|
|
|
p.SendPackCmd(2004, &p.OgrePet)
|
2026-02-07 16:56:43 +08:00
|
|
|
|
}
|
2025-12-10 13:54:51 +00:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 生成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
|
|
|
|
|
|
}
|
2025-12-14 19:23:26 +08:00
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
}
|