diff --git a/logic/controller/fight_boss野怪和地图怪.go b/logic/controller/fight_boss野怪和地图怪.go index 5f14f8969..8e9a41b3a 100644 --- a/logic/controller/fight_boss野怪和地图怪.go +++ b/logic/controller/fight_boss野怪和地图怪.go @@ -43,7 +43,7 @@ func (Controller) PlayerFightBoss(req *ChallengeBossInboundInfo, p *player.Playe } p.Fightinfo.Status = fightinfo.BattleMode.FIGHT_WITH_NPC - p.Fightinfo.Mode = fightinfo.BattleMode.MULTI_MODE + p.Fightinfo.Mode = resolveMapNodeFightMode(mapNode) ai := player.NewAI_player(monsterInfo) ai.CanCapture = resolveBossCaptureRate(bossConfigs[0].IsCapture, leadMonsterID) @@ -76,12 +76,23 @@ func startMapBossFight( oppPets := ai.GetPetInfo(0) if mapNode != nil && mapNode.IsGroupBoss != 0 { if len(ourPets) > 0 && len(oppPets) > 0 { - return fight.NewLegacyGroupFightSingleController(p, ai, ourPets, oppPets, groupBossSlotLimit, fn) + slotLimit := groupBossSlotLimit + if mapNode.PkFlag != 0 { + slotLimit = 1 + } + return fight.NewLegacyGroupFightSingleController(p, ai, ourPets, oppPets, slotLimit, fn) } } return fight.NewFight(p, ai, ourPets, oppPets, fn) } +func resolveMapNodeFightMode(mapNode *configmodel.MapNode) uint32 { + if mapNode != nil && mapNode.PkFlag != 0 { + return fightinfo.BattleMode.SINGLE_MODE + } + return fightinfo.BattleMode.MULTI_MODE +} + // OnPlayerFightNpcMonster 战斗野怪 func (Controller) OnPlayerFightNpcMonster(req *FightNpcMonsterInboundInfo, p *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { if err = p.CanFight(); err != 0 { diff --git a/logic/controller/user_task.go b/logic/controller/user_task.go index 97ff8aa62..06c88c325 100644 --- a/logic/controller/user_task.go +++ b/logic/controller/user_task.go @@ -77,31 +77,16 @@ func (h Controller) CompleteTask(data1 *CompleteTaskInboundInfo, c *player.Playe // if service.NewTaskService().IsAcceptable(data1.TaskId) == nil { // return nil, errorcode.ErrorCodes.ErrSystemError // } - c.Info.SetTask(int(data1.TaskId), model.Completed) - result = &task.CompleteTaskOutboundInfo{ TaskId: data1.TaskId, ItemList: make([]data.ItemInfo, 0), } - taskInfo := task.GetTaskInfo(int(data1.TaskId), int(data1.OutState)) - if taskInfo == nil { - return nil, errorcode.ErrorCodes.ErrNeedCompleteTaskForPrize + if _, err = c.ApplyTaskCompletion(data1.TaskId, int(data1.OutState), result); err != 0 { + return nil, err } - - if taskInfo.Pet != nil { - - c.Service.Pet.PetAdd(taskInfo.Pet, 0) - result.CaptureTime = taskInfo.Pet.CatchTime - result.PetTypeId = taskInfo.Pet.ID - } - - for _, item := range taskInfo.ItemList { - success := c.ItemAdd(item.ItemId, item.ItemCnt) - if success { - result.ItemList = append(result.ItemList, item) - } - + if taskErr := c.Info.SetTask(int(data1.TaskId), model.Completed); taskErr != nil { + return nil, errorcode.ErrorCodes.ErrSystemError } return result, 0 //通过PUB/SUB回包 diff --git a/logic/service/player/boss.go b/logic/service/player/boss.go index de8f040cc..8c536e2ae 100644 --- a/logic/service/player/boss.go +++ b/logic/service/player/boss.go @@ -1,23 +1,11 @@ package player import ( - "blazing/logic/service/fight/info" - "blazing/logic/service/task" "blazing/modules/player/model" "github.com/pointernil/bitset32" ) -// 辅助函数:获取任务奖励,封装逻辑便于复用和统一检查 -// 返回nil表示无奖励 -func (p *Player) getTaskGift(taskID int, ot int) *task.TaskResult { - // 防御性检查:taskID非法时直接返回nil - if taskID <= 0 { - return nil - } - return task.GetTaskInfo(taskID, ot) -} - // SptCompletedTask 完成任务(单分支) // 优化点:仅当奖励存在时,才完成任务并发放奖励 func (p *Player) SptCompletedTask(taskID int, ot int) { @@ -29,15 +17,17 @@ func (p *Player) SptCompletedTask(taskID int, ot int) { return } - // 2. 核心逻辑:先检查奖励是否存在,无奖励则直接返回(不完成任务) - gift := p.getTaskGift(taskID, ot) - if gift == nil { + if !p.canCompleteTaskReward(taskID, ot) { + return + } + + granted, err := p.ApplyTaskCompletion(uint32(taskID), ot, nil) + if err != 0 { return } - // 3. 奖励存在时,才标记任务完成 + 发放奖励 p.Info.SetTask(taskID, model.Completed) - p.bossgive(taskID, ot) + p.SendTaskCompletionBonus(uint32(taskID), granted) } // TawerCompletedTask 完成塔类任务(多分支) @@ -48,10 +38,12 @@ func (p *Player) TawerCompletedTask(taskID int, ot int) { } // 处理默认分支(ot=-1):仅奖励存在时才完成主任务 if p.Info.GetTask(taskID) != model.Completed { - defaultGift := p.getTaskGift(taskID, -1) - if defaultGift != nil { // 奖励存在才标记主任务完成 - p.Info.SetTask(taskID, model.Completed) - p.bossgive(taskID, -1) + if p.canCompleteTaskReward(taskID, -1) { + granted, err := p.ApplyTaskCompletion(uint32(taskID), -1, nil) + if err == 0 { + p.Info.SetTask(taskID, model.Completed) + p.SendTaskCompletionBonus(uint32(taskID), granted) + } } } @@ -61,53 +53,19 @@ func (p *Player) TawerCompletedTask(taskID int, ot int) { return } - // 核心检查:指定分支的奖励是否存在 - branchGift := p.getTaskGift(taskID, ot) - if branchGift == nil { + if !p.canCompleteTaskReward(taskID, ot) { return } r := bitset32.From(taskData.Data) if !r.Test(uint(ot)) { r.Set(uint(ot)) - p.bossgive(taskID, ot) + granted, rewardErr := p.ApplyTaskCompletion(uint32(taskID), ot, nil) + if rewardErr != 0 { + return + } + p.SendTaskCompletionBonus(uint32(taskID), granted) taskData.Data = r.Bytes() _ = p.Service.Task.SetTask(taskData) } } - -// bossgive 发放任务奖励(逻辑保持不变,仅补充注释) -func (p *Player) bossgive(taskID int, ot int) { - gift := p.getTaskGift(taskID, ot) - if gift == nil { - return - } - - res := &info.S2C_GET_BOSS_MONSTER{ - BonusID: uint32(taskID), - } - - // 发放宠物奖励 - if gift.Pet != nil { - p.Service.Pet.PetAdd(gift.Pet, 0) - res.PetID = gift.Pet.ID - res.CaptureTm = gift.Pet.CatchTime - } - - // 发放道具奖励(仅成功添加的道具才返回给前端) - for _, item := range gift.ItemList { - if success := p.ItemAdd(item.ItemId, item.ItemCnt); success { - res.AddItemInfo(item) - } - } - - // 发放称号奖励 - if gift.Title != 0 { - p.GiveTitle(gift.Title) - } - - // 发送奖励通知给前端 - if res.HasReward() { - p.SendPackCmd(8004, res) - } -} diff --git a/logic/service/player/task_completion.go b/logic/service/player/task_completion.go new file mode 100644 index 000000000..743da6192 --- /dev/null +++ b/logic/service/player/task_completion.go @@ -0,0 +1,193 @@ +package player + +import ( + "blazing/common/data" + "blazing/common/socket/errorcode" + fightinfo "blazing/logic/service/fight/info" + tasklogic "blazing/logic/service/task" + configmodel "blazing/modules/config/model" + configservice "blazing/modules/config/service" + playermodel "blazing/modules/player/model" + "sync" +) + +type TaskCompletionContext struct { + TaskID uint32 + OutState int + Config *configmodel.TaskConfig + Reward *tasklogic.TaskResult + Result *tasklogic.CompleteTaskOutboundInfo + + SkipDefaultReward bool +} + +type TaskCompletionHandler func(*Player, *TaskCompletionContext) errorcode.ErrorCode + +var taskCompletionRegistry = struct { + sync.RWMutex + handlers map[uint32]TaskCompletionHandler +}{ + handlers: make(map[uint32]TaskCompletionHandler), +} + +type taskRewardGrantResult struct { + Pet *playermodel.PetInfo + Items []data.ItemInfo +} + +func RegisterTaskCompletionHandler(taskID uint32, handler TaskCompletionHandler) { + if taskID == 0 || handler == nil { + return + } + + taskCompletionRegistry.Lock() + taskCompletionRegistry.handlers[taskID] = handler + taskCompletionRegistry.Unlock() +} + +func RegisterTaskTalkLimitHandler(taskID, talkID, needCount uint32) { + RegisterTaskCompletionHandler(taskID, func(p *Player, _ *TaskCompletionContext) errorcode.ErrorCode { + if p == nil || p.Service == nil || p.Service.Talk == nil { + return errorcode.ErrorCodes.ErrSystemError + } + + currentCount, ok := p.Service.Talk.Progress(int(talkID)) + if !ok || currentCount < needCount { + return errorcode.ErrorCodes.ErrNeedCompleteTaskForPrize + } + + return 0 + }) +} + +func (p *Player) getTaskGift(taskID int, outState int) *tasklogic.TaskResult { + if taskID <= 0 { + return nil + } + return tasklogic.GetTaskInfo(taskID, outState) +} + +func hasTaskCompletionHandler(taskID uint32) bool { + taskCompletionRegistry.RLock() + _, ok := taskCompletionRegistry.handlers[taskID] + taskCompletionRegistry.RUnlock() + return ok +} + +func getTaskCompletionHandler(taskID uint32) TaskCompletionHandler { + taskCompletionRegistry.RLock() + handler := taskCompletionRegistry.handlers[taskID] + taskCompletionRegistry.RUnlock() + return handler +} + +func (p *Player) canCompleteTaskReward(taskID, outState int) bool { + if taskID <= 0 { + return false + } + return p.getTaskGift(taskID, outState) != nil || hasTaskCompletionHandler(uint32(taskID)) +} + +func (p *Player) ApplyTaskCompletion(taskID uint32, outState int, result *tasklogic.CompleteTaskOutboundInfo) (*taskRewardGrantResult, errorcode.ErrorCode) { + if p == nil { + return nil, errorcode.ErrorCodes.ErrSystemError + } + + ctx := &TaskCompletionContext{ + TaskID: taskID, + OutState: outState, + Config: configservice.NewTaskService().Get(int(taskID), outState), + Reward: tasklogic.GetTaskInfo(int(taskID), outState), + Result: result, + } + + if ctx.Reward == nil && !hasTaskCompletionHandler(taskID) { + return nil, errorcode.ErrorCodes.ErrNeedCompleteTaskForPrize + } + + if handler := getTaskCompletionHandler(taskID); handler != nil { + if err := handler(p, ctx); err != 0 { + return nil, err + } + } + + if ctx.SkipDefaultReward { + if result != nil { + result.ItemLen = uint32(len(result.ItemList)) + } + return &taskRewardGrantResult{Items: make([]data.ItemInfo, 0)}, 0 + } + + if ctx.Reward == nil { + return nil, errorcode.ErrorCodes.ErrNeedCompleteTaskForPrize + } + + return p.grantTaskReward(ctx.Reward, result), 0 +} + +func (p *Player) grantTaskReward(reward *tasklogic.TaskResult, result *tasklogic.CompleteTaskOutboundInfo) *taskRewardGrantResult { + granted := &taskRewardGrantResult{ + Items: make([]data.ItemInfo, 0), + } + + if reward == nil { + if result != nil { + result.ItemLen = uint32(len(result.ItemList)) + } + return granted + } + + if reward.Pet != nil { + p.Service.Pet.PetAdd(reward.Pet, 0) + granted.Pet = reward.Pet + if result != nil { + result.CaptureTime = reward.Pet.CatchTime + result.PetTypeId = reward.Pet.ID + } + } + + for _, item := range reward.ItemList { + if !p.ItemAdd(item.ItemId, item.ItemCnt) { + continue + } + granted.Items = append(granted.Items, item) + if result != nil { + result.ItemList = append(result.ItemList, item) + } + } + + if reward.Title != 0 { + p.GiveTitle(reward.Title) + } + if reward.RewardPetID != 0 { + p.GrantTaskPetRewards(reward.RewardPetID, reward.TrainSkillIDs, reward.SkinIDs) + } + + if result != nil { + result.ItemLen = uint32(len(result.ItemList)) + } + return granted +} + +func (p *Player) SendTaskCompletionBonus(bonusID uint32, granted *taskRewardGrantResult) { + if p == nil { + return + } + + res := &fightinfo.S2C_GET_BOSS_MONSTER{ + BonusID: bonusID, + } + if granted != nil && granted.Pet != nil { + res.PetID = granted.Pet.ID + res.CaptureTm = granted.Pet.CatchTime + } + if granted != nil { + for _, item := range granted.Items { + res.AddItemInfo(item) + } + } + + if res.HasReward() { + p.SendPackCmd(8004, res) + } +} diff --git a/logic/service/player/task_reward.go b/logic/service/player/task_reward.go new file mode 100644 index 000000000..1be2c58e2 --- /dev/null +++ b/logic/service/player/task_reward.go @@ -0,0 +1,115 @@ +package player + +import "blazing/modules/player/model" + +func applyTaskRewardToPetInfo(pet *model.PetInfo, trainSkillIDs, skinIDs []uint32) bool { + if pet == nil { + return false + } + + changed := false + + mergedSkills := mergeTaskRewardIDs(pet.ExtSKill, trainSkillIDs) + if len(mergedSkills) != len(pet.ExtSKill) { + pet.ExtSKill = mergedSkills + changed = true + } + + mergedSkins := mergeTaskRewardIDs(pet.ExtSkin, skinIDs) + if len(mergedSkins) != len(pet.ExtSkin) { + pet.ExtSkin = mergedSkins + changed = true + } + + if pet.SkinID == 0 { + for _, skinID := range mergedSkins { + if skinID == 0 { + continue + } + pet.SkinID = skinID + changed = true + break + } + } + + return changed +} + +func mergeTaskRewardIDs(dst []uint32, src []uint32) []uint32 { + if len(src) == 0 { + return dst + } + + seen := make(map[uint32]struct{}, len(dst)+len(src)) + result := make([]uint32, 0, len(dst)+len(src)) + + for _, id := range dst { + if id == 0 { + continue + } + if _, ok := seen[id]; ok { + continue + } + seen[id] = struct{}{} + result = append(result, id) + } + + for _, id := range src { + if id == 0 { + continue + } + if _, ok := seen[id]; ok { + continue + } + seen[id] = struct{}{} + result = append(result, id) + } + + return result +} + +func (p *Player) GrantTaskPetRewards(targetPetID uint32, trainSkillIDs, skinIDs []uint32) bool { + if p == nil || targetPetID == 0 || (len(trainSkillIDs) == 0 && len(skinIDs) == 0) { + return false + } + + changed := false + + for i := range p.Info.PetList { + if p.Info.PetList[i].ID != targetPetID { + continue + } + if applyTaskRewardToPetInfo(&p.Info.PetList[i], trainSkillIDs, skinIDs) { + changed = true + } + } + + for i := range p.Info.BackupPetList { + if p.Info.BackupPetList[i].ID != targetPetID { + continue + } + if applyTaskRewardToPetInfo(&p.Info.BackupPetList[i], trainSkillIDs, skinIDs) { + changed = true + } + } + + if p.Service == nil || p.Service.Pet == nil { + return changed + } + + allPets := p.Service.Pet.PetInfo(0) + for i := range allPets { + if allPets[i].Data.ID != targetPetID { + continue + } + if !applyTaskRewardToPetInfo(&allPets[i].Data, trainSkillIDs, skinIDs) { + continue + } + allPets[i].Data.CatchTime = allPets[i].CatchTime + if p.Service.Pet.Update(allPets[i].Data) { + changed = true + } + } + + return changed +} diff --git a/logic/service/task/task.go b/logic/service/task/task.go index b8566fcd9..f9c358b59 100644 --- a/logic/service/task/task.go +++ b/logic/service/task/task.go @@ -10,8 +10,11 @@ import ( type TaskResult struct { Pet *model.PetInfo `json:"petTypeId" description:"发放的精灵ID"` // 发放的精灵ID, - ItemList []data.ItemInfo `json:"itemList" description:"发放物品的数组"` // 发放物品的数组, - Title uint32 `json:"title" description:"称号奖励"` + ItemList []data.ItemInfo `json:"itemList" description:"发放物品的数组"` // 发放物品的数组, + Title uint32 `json:"title" description:"称号奖励"` + RewardPetID uint32 `json:"rewardPetId" description:"宠物相关奖励目标精灵ID"` + TrainSkillIDs []uint32 `json:"trainSkillIds" description:"特训技能奖励"` + SkinIDs []uint32 `json:"skinIds" description:"皮肤奖励"` } func GetTaskInfo(id, ot int) *TaskResult { @@ -26,6 +29,12 @@ func GetTaskInfo(id, ot int) *TaskResult { if pet != nil { ret.Pet = model.GenPetInfo(int(pet.MonID), int(pet.DV), int(pet.Nature), int(pet.Effect), int(pet.Lv), nil, 0) } + ret.RewardPetID = r.RewardPetID + ret.TrainSkillIDs = append(ret.TrainSkillIDs, r.TrainSkillIDs...) + ret.SkinIDs = append(ret.SkinIDs, r.SkinIDs...) + if ret.Pet != nil { + applyTaskRewardPetExtras(ret.Pet, ret.TrainSkillIDs, ret.SkinIDs) + } for _, itemID := range r.ItemRewardIds { iteminfo := service.NewItemService().GetItemCount(itemID) @@ -39,3 +48,59 @@ func GetTaskInfo(id, ot int) *TaskResult { return ret } + +func applyTaskRewardPetExtras(pet *model.PetInfo, trainSkillIDs, skinIDs []uint32) { + if pet == nil { + return + } + + if merged := mergeTaskRewardIDs(pet.ExtSKill, trainSkillIDs); len(merged) != len(pet.ExtSKill) { + pet.ExtSKill = merged + } + + mergedSkins := mergeTaskRewardIDs(pet.ExtSkin, skinIDs) + if len(mergedSkins) != len(pet.ExtSkin) { + pet.ExtSkin = mergedSkins + } + if pet.SkinID == 0 { + for _, skinID := range mergedSkins { + if skinID != 0 { + pet.SkinID = skinID + break + } + } + } +} + +func mergeTaskRewardIDs(dst []uint32, src []uint32) []uint32 { + if len(src) == 0 { + return dst + } + + seen := make(map[uint32]struct{}, len(dst)+len(src)) + result := make([]uint32, 0, len(dst)+len(src)) + + for _, id := range dst { + if id == 0 { + continue + } + if _, ok := seen[id]; ok { + continue + } + seen[id] = struct{}{} + result = append(result, id) + } + + for _, id := range src { + if id == 0 { + continue + } + if _, ok := seen[id]; ok { + continue + } + seen[id] = struct{}{} + result = append(result, id) + } + + return result +} diff --git a/modules/config/model/glow.go b/modules/config/model/glow.go index bcd843ae0..4b003d446 100644 --- a/modules/config/model/glow.go +++ b/modules/config/model/glow.go @@ -71,6 +71,10 @@ func roundFloat32(val float32, decimals int) float32 { return float32(math.Round(float64(val*shift))) / shift } +func randomFloat32Range(r *rand.Rand, min, max float32) float32 { + return min + float32(r.Float64())*(max-min) +} + // 预处理矩阵:自动修正越界参数,确保合规 func ProcessOffspringMatrix(mat [4][5]float32) [4][5]float32 { var processedMat [4][5]float32 @@ -118,71 +122,62 @@ func calculateMatrixHash(mm MonsterMatrix) string { return hex.EncodeToString(h.Sum(nil)) } -// GenerateRandomParentMatrix 调整随机参数范围,解决暗色问题,贴合你的示例 +// GenerateRandomParentMatrix 生成色域更大的父矩阵,同时抬高黑场避免整只精灵发黑 func GenerateRandomParentMatrix() MonsterMatrix { - // 1. 保留高熵种子逻辑(确保唯一性,不变) salt := "player-matrix-random-seed" now := time.Now().UnixNano() randomNum := rand.Int63() seed := now ^ randomNum ^ int64(hashString(salt)) r := rand.New(rand.NewSource(seed)) - // 2. 调整随机参数范围(贴合你的示例,解决暗色问题) - // 对比你的示例:亮度大多在[-30,30],对比度[0.7,1.7],饱和度[0.4,1.4],偏移[-10,10] - params := struct { - brightness float32 // 从[-125,125]调整为[-30,60],避免过低亮度 - contrast float32 // 从[0.4,2.2]调整为[0.7,1.7],贴合你的示例 - saturation float32 // 从[0.1,2.0]调整为[0.4,1.4],避免低饱和度灰暗 - hueRotate float32 // 从[-180,180]调整为[-50,50],减少极端色相导致的暗沉 - rOffset float32 // 从[-50,50]调整为[-10,10],避免亮度偏移过大 - gOffset float32 // 同上 - bOffset float32 // 同上 - }{ - brightness: float32(r.Float64()*90 - 30), // [-30, 60](贴合示例亮度范围,减少暗色) - contrast: float32(r.Float64()*1.0 + 0.7), // [0.7, 1.7](与你的示例完全匹配) - saturation: float32(r.Float64()*1.0 + 0.4), // [0.4, 1.4](与你的示例完全匹配) - hueRotate: float32(r.Float64()*100 - 50), // [-50, 50](避免极端色相) - rOffset: float32(r.Float64()*20 - 10), // [-10, 10](小幅亮度偏移,贴合示例) - gOffset: float32(r.Float64()*20 - 10), // 同上 - bOffset: float32(r.Float64()*20 - 10), // 同上 + matrix := newIdentityMatrix() + dominant := r.Intn(3) + accent := (dominant + 1 + r.Intn(2)) % 3 + baseLift := randomFloat32Range(r, 10, 24) + + for row := 0; row < 3; row++ { + for col := 0; col < 3; col++ { + value := randomFloat32Range(r, -0.22, 0.22) + if row == col { + value = randomFloat32Range(r, 0.8, 1.45) + } + if row == dominant && col == dominant { + value += randomFloat32Range(r, 0.35, 0.7) + } + if row == accent && col == accent { + value += randomFloat32Range(r, 0.1, 0.3) + } + if row == dominant && col != row { + value += randomFloat32Range(r, -0.12, 0.28) + } + matrix[row][col] = clampFloat32(roundFloat32(value, FloatPrecision), MatrixMinVal, MatrixMaxVal) + } } - // 3. 矩阵计算逻辑不变(确保与你的示例参数分布一致) - matrix := newIdentityMatrix() - contrast := params.contrast - matrix[0][0] *= contrast - matrix[1][1] *= contrast - matrix[2][2] *= contrast + matrix[0][4] = baseLift + randomFloat32Range(r, -5, 10) + matrix[1][4] = baseLift + randomFloat32Range(r, -5, 10) + matrix[2][4] = baseLift + randomFloat32Range(r, -5, 10) + matrix[dominant][4] += randomFloat32Range(r, 8, 18) + matrix[accent][4] += randomFloat32Range(r, 2, 8) - sat := params.saturation - grayR, grayG, grayB := float32(0.299)*(1-sat), float32(0.587)*(1-sat), float32(0.114)*(1-sat) - matrix[0][0] = grayR + sat*matrix[0][0] - matrix[0][1], matrix[0][2] = grayG, grayB - matrix[1][0] = grayR - matrix[1][1] = grayG + sat*matrix[1][1] - matrix[1][2] = grayB - matrix[2][0] = grayR - matrix[2][1] = grayG - matrix[2][2] = grayB + sat*matrix[2][2] + avgBrightness := (matrix[0][4] + matrix[1][4] + matrix[2][4]) / 3 + if avgBrightness < 12 { + lift := 12 - avgBrightness + randomFloat32Range(r, 0, 6) + for row := 0; row < 3; row++ { + matrix[row][4] += lift + } + } + if matrix[dominant][4] < 16 { + matrix[dominant][4] = 16 + randomFloat32Range(r, 0, 10) + } - angle := params.hueRotate * float32(math.Pi) / 180 - cos, sin := float32(math.Cos(float64(angle))), float32(math.Sin(float64(angle))) - r1, g1, b1 := matrix[0][0], matrix[0][1], matrix[0][2] - r2, g2, b2 := matrix[1][0], matrix[1][1], matrix[1][2] + for row := 0; row < 3; row++ { + for col := 0; col < 3; col++ { + matrix[row][col] = clampFloat32(roundFloat32(matrix[row][col], FloatPrecision), MatrixMinVal, MatrixMaxVal) + } + matrix[row][4] = clampFloat32(roundFloat32(matrix[row][4], FloatPrecision), BrightnessMinVal, BrightnessMaxVal) + } - matrix[0][0] = r1*cos - r2*sin - matrix[0][1] = r1*sin + r2*cos - matrix[1][0] = g1*cos - g2*sin - matrix[1][1] = g1*sin + g2*cos - matrix[2][0] = b1*cos - b2*sin - matrix[2][1] = b1*sin + b2*cos - - // 亮度偏移:范围缩小后,避免过暗/过亮 - matrix[0][4] = params.brightness + params.rOffset - matrix[1][4] = params.brightness + params.gOffset - matrix[2][4] = params.brightness + params.bOffset - - // 4. 封装为MonsterMatrix(不变) parent := MonsterMatrix{ Matrix: matrix, Hash: "", diff --git a/modules/config/model/map_node.go b/modules/config/model/map_node.go index e55bfb99b..71a73bd0f 100644 --- a/modules/config/model/map_node.go +++ b/modules/config/model/map_node.go @@ -32,6 +32,7 @@ type MapNode struct { IsBroadcast uint32 `gorm:"type:int;default:0;comment:'广播模型ID(0表示不广播)'" json:"is_broadcast"` IsGroupBoss uint32 `gorm:"type:int;default:0;comment:'是否为组队Boss(0否1是)'" json:"is_group_boss" description:"是否为组队Boss"` + PkFlag uint32 `gorm:"type:int;default:0;comment:'是否单精灵对战(0否1是)'" json:"pk_flag" description:"是否单精灵对战"` TriggerPlotID uint32 `gorm:"default:0;comment:'触发剧情ID(0表示无剧情)'" json:"trigger_plot_id" description:"触发剧情ID"` diff --git a/modules/config/model/task.go b/modules/config/model/task.go index 567f410d3..2f5a050ab 100644 --- a/modules/config/model/task.go +++ b/modules/config/model/task.go @@ -26,6 +26,9 @@ type TaskConfig struct { // 奖励配置 ItemRewardIds []uint32 `gorm:"not null;type:jsonb;default:'[]';comment:'绑定奖励物品ID数组,关联item_gift表主键'" json:"item_reward_ids" description:"奖励物品数组"` ElfRewardIds uint32 `gorm:"not null;default:0;comment:'绑定奖励精灵ID,关联elf_gift表主键'" json:"elf_reward_ids" description:"绑定奖励精灵ID"` + RewardPetID uint32 `gorm:"not null;default:0;comment:'宠物相关奖励生效的目标精灵ID,0表示不对已有精灵发放'" json:"reward_pet_id" description:"目标精灵ID"` + TrainSkillIDs []uint32 `gorm:"not null;type:jsonb;default:'[]';comment:'任务奖励的特训技能ID数组'" json:"train_skill_ids" description:"特训技能奖励数组"` + SkinIDs []uint32 `gorm:"not null;type:jsonb;default:'[]';comment:'任务奖励的皮肤ID数组'" json:"skin_ids" description:"皮肤奖励数组"` //绑定奖励 TitleRewardIds uint32 `gorm:"not null;default:0;comment:'绑定奖励称号'" json:"title_reward_ids" description:"绑定奖励称号"` diff --git a/modules/config/service/shiny.go b/modules/config/service/shiny.go index bafde121f..71f9e8a12 100644 --- a/modules/config/service/shiny.go +++ b/modules/config/service/shiny.go @@ -2,7 +2,6 @@ package service import ( "blazing/common/data" - "blazing/common/utils" "blazing/cool" "blazing/modules/config/model" "context" @@ -43,18 +42,52 @@ func (s *ShinyService) ModifyBefore(ctx context.Context, method string, param g. } return nil } -func (s *ShinyService) RandShiny(id uint32) *data.GlowFilter { +func (s *ShinyService) listByPetID(id uint32) []model.ColorfulSkin { var ret []model.ColorfulSkin - // 执行 Raw SQL 并扫描返回值 dbm_enable(s.Model). Wheref(`bind_elf_ids @> ?::jsonb`, id). - Wheref(`jsonb_typeof(bind_elf_ids) = ?`, "array").Scan(&ret) + Wheref(`jsonb_typeof(bind_elf_ids) = ?`, "array"). + Scan(&ret) + + return ret +} + +func pickColorfulSkinByWeight(items []model.ColorfulSkin) *model.ColorfulSkin { + if len(items) == 0 { + return nil + } + + totalWeight := 0 + for _, item := range items { + if item.ElfProbability > 0 { + totalWeight += int(item.ElfProbability) + } + } + if totalWeight <= 0 { + return &items[grand.Intn(len(items))] + } + + randomValue := grand.Intn(totalWeight) + for i := range items { + weight := int(items[i].ElfProbability) + if weight <= 0 { + continue + } + if randomValue < weight { + return &items[i] + } + randomValue -= weight + } + + return &items[0] +} + +func (s *ShinyService) RandShiny(id uint32) *data.GlowFilter { + ret := s.listByPetID(id) for _, v := range ret { - //print(v.ID) - id := v.ID if grand.Meet(int(v.ElfProbability), 1000) { @@ -74,32 +107,16 @@ func (s *ShinyService) RandShiny(id uint32) *data.GlowFilter { var t = data.GetDef() - t.ColorMatrixFilter = model.GenerateRandomOffspringMatrix().Get() + t.ColorMatrixFilter = model.GenerateRandomParentMatrix().Get() return &t } func (s *ShinyService) RandomByWeightShiny(id uint32) *data.GlowFilter { - - var ret []model.ColorfulSkin - - // 执行 Raw SQL 并扫描返回值 - dbm_enable(s.Model). - Wheref(`bind_elf_ids @> ?::jsonb`, id). - Wheref(`jsonb_typeof(bind_elf_ids) = ?`, "array").Scan(&ret) - if len(ret) == 0 { + r := pickColorfulSkinByWeight(s.listByPetID(id)) + if r == nil { return nil } - var rets []model.ColorfulSkin - var props []int - - for _, v := range ret { - rets = append(rets, v) - props = append(props, int(v.ElfProbability)) - - } - - r, _ := utils.RandomByWeight(rets, props) if cool.Config.ServerInfo.IsVip == 0 { m := cool.DBM(s.Model).Where("id", r.ID) m.Increment("refresh_count", 1) diff --git a/modules/model.test b/modules/model.test new file mode 100755 index 000000000..88eb630d8 Binary files /dev/null and b/modules/model.test differ diff --git a/modules/player/service/talk.go b/modules/player/service/talk.go index 3c381f44d..fe6e3f4a9 100644 --- a/modules/player/service/talk.go +++ b/modules/player/service/talk.go @@ -3,6 +3,7 @@ package service import ( "blazing/common/utils" "blazing/cool" + configmodel "blazing/modules/config/model" config "blazing/modules/config/service" "blazing/modules/player/model" @@ -27,54 +28,58 @@ func (s *TalkService) reset(flag int) { s.dbm(s.Model).Where("talk_id", flag).Data("count", 0, "last_reset_time", gtime.Now()).Update() } -//实现挖矿次数确认 - -func (s *TalkService) Cheak(mapid uint32, flag int) (int, bool) { - - m1 := s.dbm(s.Model) - +func (s *TalkService) progress(flag int) (uint32, *model.Talk, *configmodel.MineralCollectionConfig, bool) { var talks *model.Talk - m1.Where("talk_id", flag).Scan(&talks) + s.dbm(s.Model).Where("talk_id", flag).Scan(&talks) + + cfg := config.NewTalkConfigService().GetCache(flag) + if cfg == nil { + return 0, talks, nil, false + } if talks == nil { - - return 0, true //如果表里没有记载数据,那么就可以直接挖矿 + return 0, nil, cfg, true } - c := config.NewTalkConfigService().GetCache(flag) - - //因为这个是挖一次更新一次,而且是实时更新的,如果更新日期是今天,那么就可以确认不用再重置,否则就需要重置挖矿记录 - if c == nil { - return 0, false //没在地图 - } - switch c.Limit { + switch cfg.Limit { case 0: if !utils.IsToday(talks.LastResetTime) { - s.reset(flag) - return int(0), true + return 0, talks, cfg, true } - case 1: if !utils.IsWEEK(talks.LastResetTime) { - s.reset(flag) - return int(0), true + return 0, talks, cfg, true } case 2: if !utils.IsMon(talks.LastResetTime) { - s.reset(flag) - return int(0), true + return 0, talks, cfg, true } } - if uint32(mapid) != c.MapID { + return talks.Count, talks, cfg, true +} + +func (s *TalkService) Progress(flag int) (uint32, bool) { + count, _, _, ok := s.progress(flag) + return count, ok +} + +//实现挖矿次数确认 + +func (s *TalkService) Cheak(mapid uint32, flag int) (int, bool) { + count, _, cfg, ok := s.progress(flag) + if !ok || cfg == nil { return 0, false //没在地图 } - if talks.Count >= c.DailyCollectCount { + if uint32(mapid) != cfg.MapID { + return 0, false //没在地图 + } + if count >= cfg.DailyCollectCount { return 0, false } - return int(talks.Count), true //int(config.MaxDailyCnt - talks.Count) + return int(count), true //int(config.MaxDailyCnt - talks.Count) } diff --git a/modules/service.test b/modules/service.test new file mode 100755 index 000000000..813bcbbe3 Binary files /dev/null and b/modules/service.test differ