From 99748ba41e51e2d4d67c0ca53a2e3489bcb3e050 Mon Sep 17 00:00:00 2001 From: xinian Date: Mon, 6 Apr 2026 03:42:48 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E5=A5=96?= =?UTF-8?q?=E5=8A=B1=E5=8F=91=E6=94=BE=E9=80=BB=E8=BE=91=E5=B9=B6=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E7=AD=BE=E5=88=B0=E9=BB=98=E8=AE=A4=E5=A5=96=E5=8A=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- logic/controller/item_use.go | 12 +- logic/controller/user_cdk.go | 50 +++++---- logic/service/item/petuse.go | 39 +++++-- modules/config/model/sign.go | 2 +- modules/config/service/sign.go | 3 +- modules/player/service/cdk_reward.go | 123 +++++++++++++++++++++ modules/player/service/sign.go | 158 ++++++++++----------------- 7 files changed, 250 insertions(+), 137 deletions(-) create mode 100644 modules/player/service/cdk_reward.go diff --git a/logic/controller/item_use.go b/logic/controller/item_use.go index f54d511b1..874415e9b 100644 --- a/logic/controller/item_use.go +++ b/logic/controller/item_use.go @@ -43,12 +43,20 @@ func (h Controller) UsePetItemOutOfFight(data *C2S_USE_PET_ITEM_OUT_OF_FIGHT, c return nil, errorcode.ErrorCodes.ErrInsufficientItems } + oldHP := currentPet.Hp itemCfg, ok := xmlres.ItemsMAP[int(itemID)] if !ok { - return nil, errorcode.ErrorCodes.ErrSystemError + errcode := h.handleRegularPetItem(itemID, currentPet) + if errcode != 0 { + return nil, errcode + } + refreshPetPaneKeepHP(currentPet, oldHP) + c.Service.Item.UPDATE(itemID, -1) + result = &item.S2C_USE_PET_ITEM_OUT_OF_FIGHT{} + copier.Copy(&result, currentPet) + return result, 0 } - oldHP := currentPet.Hp var errcode errorcode.ErrorCode switch { case itemID == 300036: diff --git a/logic/controller/user_cdk.go b/logic/controller/user_cdk.go index d33becb9f..f2a96a4a1 100644 --- a/logic/controller/user_cdk.go +++ b/logic/controller/user_cdk.go @@ -2,20 +2,18 @@ package controller import ( "blazing/common/socket/errorcode" - "blazing/logic/service/player" + logicplayer "blazing/logic/service/player" "blazing/logic/service/user" - "blazing/modules/config/service" - "blazing/modules/player/model" + configservice "blazing/modules/config/service" + playerservice "blazing/modules/player/service" "time" ) // CDK 处理控制器请求。 -func (h Controller) CDK(data *C2S_GET_GIFT_COMPLETE, player *player.Player) (result *user.S2C_GET_GIFT_COMPLETE, err errorcode.ErrorCode) { +func (h Controller) CDK(data *C2S_GET_GIFT_COMPLETE, player *logicplayer.Player) (result *user.S2C_GET_GIFT_COMPLETE, err errorcode.ErrorCode) { result = &user.S2C_GET_GIFT_COMPLETE{} - cdkService := service.NewCdkService() - rewardPetService := service.NewPetRewardService() - itemRewardService := service.NewItemService() + cdkService := configservice.NewCdkService() now := time.Now() r := cdkService.Get(data.PassText) @@ -25,7 +23,6 @@ func (h Controller) CDK(data *C2S_GET_GIFT_COMPLETE, player *player.Player) (res if r.BindUserId != 0 && r.BindUserId != data.Head.UserID { return nil, errorcode.ErrorCodes.ErrMolecularCodeFrozen } - if r.ValidEndTime.Compare(now) == -1 { return nil, errorcode.ErrorCodes.ErrMolecularCodeExpired } @@ -36,28 +33,33 @@ func (h Controller) CDK(data *C2S_GET_GIFT_COMPLETE, player *player.Player) (res return nil, errorcode.ErrorCodes.ErrMolecularCodeGiftsGone } + reward, grantErr := playerservice.NewCdkService(data.Head.UserID).GrantConfigReward(uint32(r.ID)) + if grantErr != nil { + return nil, errorcode.ErrorCodes.ErrSystemError + } + result.Flag = 1 - for _, rewardID := range r.ElfRewardIds { - pet := rewardPetService.Get(rewardID) - if pet == nil { - continue + appendGift := func(giftID, count int64) { + if giftID == 0 || count <= 0 { + return } - - petInfo := model.GenPetInfo(int(pet.MonID), int(pet.DV), int(pet.Nature), int(pet.Effect), int(pet.Lv), nil, 0) - player.Service.Pet.PetAdd(petInfo, 0) - result.PetGift = append(result.PetGift, user.PetGiftInfo{PetID: petInfo.ID, CacthTime: petInfo.CatchTime}) + result.GiftList = append(result.GiftList, user.GiftInfo{GiftID: giftID, Count: count}) } - for _, rewardID := range r.ItemRewardIds { - itemInfo := itemRewardService.GetItemCount(rewardID) - player.ItemAdd(itemInfo.ItemId, itemInfo.ItemCnt) - result.GiftList = append(result.GiftList, user.GiftInfo{GiftID: itemInfo.ItemId, Count: itemInfo.ItemCnt}) + appendGift(1, reward.Coins) + appendGift(3, reward.ExpPool) + appendGift(5, reward.Gold) + appendGift(9, reward.EVPool) + for _, item := range reward.Items { + appendGift(item.ItemId, item.ItemCnt) } - if r.TitleRewardIds != 0 { - player.Service.Title.Give(r.TitleRewardIds) - result.Tile = r.TitleRewardIds + for _, pet := range reward.Pets { + result.PetGift = append(result.PetGift, user.PetGiftInfo{PetID: pet.PetID, CacthTime: pet.CatchTime}) } + if len(reward.TitleIDs) > 0 { + result.Tile = reward.TitleIDs[0] + } + player.Service.Cdk.Log(uint32(r.ID)) - return } diff --git a/logic/service/item/petuse.go b/logic/service/item/petuse.go index f97ba2d35..79cc0c27a 100644 --- a/logic/service/item/petuse.go +++ b/logic/service/item/petuse.go @@ -27,6 +27,11 @@ type SetHandler struct { Handler PetItemHandler } +var fallbackPetItemNewSeIdx = map[uint32]int{ + 300741: 1103, // 瞬杀能量珠 + 300854: 1103, // 瞬杀能量珠Ω +} + // PetItemHandlerRegistry 道具处理器注册器 type PetItemHandlerRegistry struct { exactHandlers map[uint32]PetItemHandler // 精确ID映射 @@ -112,12 +117,29 @@ func nvfunc(itemid uint32, onpet *model.PetInfo) bool { return true } -func handleNewSeIdxPetItem(itemid uint32, onpet *model.PetInfo) errorcode.ErrorCode { - itemCfg, ok := xmlres.ItemsMAP[int(itemid)] - if !ok { - return errorcode.ErrorCodes.ErrItemUnusable +func resolvePetItemNewSeIdx(itemid uint32) (itemCfg xmlres.Item, newSeIdx int, ok bool) { + itemCfg, ok = xmlres.ItemsMAP[int(itemid)] + if ok && itemCfg.NewSeIdx != 0 { + return itemCfg, itemCfg.NewSeIdx, true } - if itemCfg.NewSeIdx == 0 { + + if newSeIdx, ok = fallbackPetItemNewSeIdx[itemid]; ok { + return itemCfg, newSeIdx, true + } + + for idx, effectCfg := range xmlres.EffectMAP { + if effectCfg.ItemId == nil || gconv.Uint32(*effectCfg.ItemId) != itemid { + continue + } + return itemCfg, idx, true + } + + return itemCfg, 0, false +} + +func handleNewSeIdxPetItem(itemid uint32, onpet *model.PetInfo) errorcode.ErrorCode { + itemCfg, newSeIdx, ok := resolvePetItemNewSeIdx(itemid) + if ok && newSeIdx == 0 { if itemCfg.MaxHPUp > 0 { if !onpet.AddMaxHPUpEffect(itemid, itemCfg.MaxHPUp) { return errorcode.ErrorCodes.ErrCannotInjectPillAgain @@ -126,14 +148,17 @@ func handleNewSeIdxPetItem(itemid uint32, onpet *model.PetInfo) errorcode.ErrorC } return errorcode.ErrorCodes.ErrItemUnusable } + if !ok { + return errorcode.ErrorCodes.ErrItemUnusable + } - effectCfg, ok := xmlres.EffectMAP[itemCfg.NewSeIdx] + effectCfg, ok := xmlres.EffectMAP[newSeIdx] if !ok { return errorcode.ErrorCodes.ErrSystemError } effectStatus := byte(gconv.Int(effectCfg.Stat)) - effectIdx := uint16(itemCfg.NewSeIdx) + effectIdx := uint16(newSeIdx) leftCount := 1 if effectCfg.Times != nil && *effectCfg.Times != "" { leftCount = gconv.Int(*effectCfg.Times) diff --git a/modules/config/model/sign.go b/modules/config/model/sign.go index 1d43015fd..f708da02c 100644 --- a/modules/config/model/sign.go +++ b/modules/config/model/sign.go @@ -13,7 +13,7 @@ const ( type SignIn struct { *BaseConfig SignType uint32 `gorm:"not null;default:1;uniqueIndex:idx_sign_type_stage;comment:'签到类别(1-累计 2-连续)'" json:"sign_type"` - StageDays uint32 `gorm:"not null;default:1;uniqueIndex:idx_sign_type_stage;comment:'签到阶段天数(1/3/7/14/30)'" json:"stage_days"` + StageDays uint32 `gorm:"not null;default:1;uniqueIndex:idx_sign_type_stage;comment:'签到阶段天数(0/1/3/7/14/30)'" json:"stage_days"` CdkID uint32 `gorm:"not null;uniqueIndex;comment:'绑定的CDK配置ID'" json:"cdk_id"` } diff --git a/modules/config/service/sign.go b/modules/config/service/sign.go index fa9b3f239..c896f2f54 100644 --- a/modules/config/service/sign.go +++ b/modules/config/service/sign.go @@ -12,6 +12,7 @@ import ( ) var signStageDays = map[uint32]struct{}{ + 0: {}, 1: {}, 3: {}, 7: {}, @@ -50,7 +51,7 @@ func (s *SignInService) ModifyBefore(ctx context.Context, method string, param g stageDays := gconv.Uint32(param["stage_days"]) if _, ok := signStageDays[stageDays]; !ok { - return fmt.Errorf("签到阶段仅支持1、3、7、14、30天") + return fmt.Errorf("签到阶段仅支持0、1、3、7、14、30天") } cdkID := gconv.Uint32(param["cdk_id"]) diff --git a/modules/player/service/cdk_reward.go b/modules/player/service/cdk_reward.go new file mode 100644 index 000000000..9cba29764 --- /dev/null +++ b/modules/player/service/cdk_reward.go @@ -0,0 +1,123 @@ +package service + +import ( + "blazing/common/data" + baseservice "blazing/modules/base/service" + configservice "blazing/modules/config/service" + "blazing/modules/player/model" + "fmt" + "time" +) + +type CdkRewardPet struct { + PetID uint32 `json:"pet_id"` + CatchTime uint32 `json:"catch_time"` +} + +type CdkRewardResult struct { + CdkID uint32 `json:"cdk_id"` + Items []data.ItemInfo `json:"items,omitempty"` + Pets []CdkRewardPet `json:"pets,omitempty"` + TitleIDs []uint32 `json:"title_ids,omitempty"` + Coins int64 `json:"coins,omitempty"` + Gold int64 `json:"gold,omitempty"` + FreeGold int64 `json:"free_gold,omitempty"` + ExpPool int64 `json:"exp_pool,omitempty"` + EVPool int64 `json:"ev_pool,omitempty"` +} + +// GrantConfigReward 按 cdk 配置 ID 发放奖励,不处理兑换码次数和领取资格校验。 +func (s *CdkService) GrantConfigReward(cdkID uint32) (*CdkRewardResult, error) { + cfg := configservice.NewCdkService().GetByID(cdkID) + if cfg == nil { + return nil, fmt.Errorf("绑定的CDK不存在") + } + if cfg.BindUserId != 0 && cfg.BindUserId != s.userid { + return nil, fmt.Errorf("CDK已绑定其他用户") + } + if !cfg.ValidEndTime.IsZero() && cfg.ValidEndTime.Before(time.Now()) { + return nil, fmt.Errorf("绑定的CDK已过期") + } + + result := &CdkRewardResult{CdkID: cdkID} + infoService := NewInfoService(s.userid) + playerInfo := infoService.GetLogin() + if playerInfo == nil { + return nil, fmt.Errorf("玩家角色不存在") + } + + var ( + infoDirty bool + bagItems []data.ItemInfo + ) + + appendRewardItem := func(itemID uint32, count int64) { + if itemID == 0 || count <= 0 { + return + } + switch itemID { + case 1: + result.Coins += count + playerInfo.Coins += count + infoDirty = true + case 3: + result.ExpPool += count + playerInfo.ExpPool += count + infoDirty = true + case 5: + result.Gold += count + case 9: + result.EVPool += count + playerInfo.EVPool += count + infoDirty = true + default: + bagItems = append(bagItems, data.ItemInfo{ItemId: int64(itemID), ItemCnt: count}) + } + } + + for _, rewardID := range cfg.ItemRewardIds { + itemInfo := configservice.NewItemService().GetItemCount(rewardID) + appendRewardItem(uint32(itemInfo.ItemId), itemInfo.ItemCnt) + } + + if result.Gold != 0 { + baseservice.NewBaseSysUserService().UpdateGold(s.userid, result.Gold*100) + } + if result.FreeGold != 0 { + baseservice.NewBaseSysUserService().UpdateFreeGold(s.userid, result.FreeGold*100) + } + if len(bagItems) > 0 { + items, err := NewItemService(s.userid).AddItems(bagItems) + if err != nil { + return nil, err + } + result.Items = items + } + + for _, rewardID := range cfg.ElfRewardIds { + pet := configservice.NewPetRewardService().Get(rewardID) + if pet == nil { + continue + } + petInfo := model.GenPetInfo(int(pet.MonID), int(pet.DV), int(pet.Nature), int(pet.Effect), int(pet.Lv), nil, 0) + catchTime, err := NewPetService(s.userid).PetAdd(petInfo, 0) + if err != nil { + return nil, err + } + result.Pets = append(result.Pets, CdkRewardPet{ + PetID: uint32(pet.MonID), + CatchTime: catchTime, + }) + } + + if cfg.TitleRewardIds != 0 { + NewTitleService(s.userid).Give(cfg.TitleRewardIds) + result.TitleIDs = append(result.TitleIDs, cfg.TitleRewardIds) + } + + if infoDirty { + infoService.Save(*playerInfo) + } + + return result, nil +} diff --git a/modules/player/service/sign.go b/modules/player/service/sign.go index 59991e278..ab182ad77 100644 --- a/modules/player/service/sign.go +++ b/modules/player/service/sign.go @@ -3,7 +3,6 @@ package service import ( "blazing/common/data" "blazing/cool" - baseservice "blazing/modules/base/service" configmodel "blazing/modules/config/model" configservice "blazing/modules/config/service" "blazing/modules/player/model" @@ -101,6 +100,8 @@ func (s *SignService) Claim() (*SignClaimResult, error) { return nil, fmt.Errorf("今天已经签到过了") } + prevTotalDays := record.TotalDays + prevContinuousDays := record.ContinuousDays prevDate := record.LastSignDate record.LastSignDate = today record.TotalDays++ @@ -110,7 +111,7 @@ func (s *SignService) Claim() (*SignClaimResult, error) { record.ContinuousDays = 1 } - rewards, err := s.grantReachedStageRewards(record) + rewards, err := s.grantReachedStageRewards(record, prevTotalDays, prevContinuousDays) if err != nil { return nil, err } @@ -164,45 +165,47 @@ func (s *SignService) ResetAll() (*SignResetResult, error) { return result, nil } -func (s *SignService) grantReachedStageRewards(record *model.SignInRecord) ([]SignRewardResult, error) { +func (s *SignService) grantReachedStageRewards(record *model.SignInRecord, prevTotalDays, prevContinuousDays uint32) ([]SignRewardResult, error) { configs := configservice.NewSignInService().GetEnabled() if len(configs) == 0 { return nil, nil } - cdkLogService := NewCdkService(s.userid) - infoService := NewInfoService(s.userid) - playerInfo := infoService.GetLogin() - if playerInfo == nil { - return nil, fmt.Errorf("玩家角色不存在") + baseRewardBySignType := make(map[uint32]configmodel.SignIn) + for _, cfg := range configs { + if cfg.StageDays == 0 { + baseRewardBySignType[cfg.SignType] = cfg + } } - infoDirty := false + cdkLogService := NewCdkService(s.userid) results := make([]SignRewardResult, 0) for _, cfg := range configs { + if cfg.StageDays == 0 { + continue + } if !stageReached(cfg.SignType, cfg.StageDays, record) { continue } - if !cdkLogService.CanGet(cfg.CdkID) { + if stageReachedByDays(cfg.SignType, cfg.StageDays, prevTotalDays, prevContinuousDays) { continue } - reward, changed, err := s.applyCdkReward(cfg.CdkID, playerInfo) + rewardCdkID := cfg.CdkID + if !cdkLogService.CanGet(cfg.CdkID) { + baseCfg, ok := baseRewardBySignType[cfg.SignType] + if !ok || !cdkLogService.CanGet(baseCfg.CdkID) { + continue + } + rewardCdkID = baseCfg.CdkID + } + + reward, err := cdkLogService.GrantConfigReward(rewardCdkID) if err != nil { return nil, err } - reward.SignType = cfg.SignType - reward.StageDays = cfg.StageDays - reward.CdkID = cfg.CdkID - results = append(results, *reward) - if changed { - infoDirty = true - } - cdkLogService.Log(cfg.CdkID) - } - - if infoDirty { - infoService.Save(*playerInfo) + results = append(results, buildSignRewardResult(cfg.SignType, cfg.StageDays, reward)) + cdkLogService.Log(rewardCdkID) } sort.Slice(results, func(i, j int) bool { @@ -217,85 +220,26 @@ func (s *SignService) grantReachedStageRewards(record *model.SignInRecord) ([]Si return results, nil } -func (s *SignService) applyCdkReward(cdkID uint32, playerInfo *model.PlayerInfo) (*SignRewardResult, bool, error) { - cfg := configservice.NewCdkService().GetByID(cdkID) - if cfg == nil { - return nil, false, fmt.Errorf("绑定的CDK不存在") +func buildSignRewardResult(signType, stageDays uint32, reward *CdkRewardResult) SignRewardResult { + result := SignRewardResult{ + SignType: signType, + StageDays: stageDays, + CdkID: reward.CdkID, + Items: reward.Items, + TitleIDs: reward.TitleIDs, + Coins: reward.Coins, + Gold: reward.Gold, + FreeGold: reward.FreeGold, + ExpPool: reward.ExpPool, + EVPool: reward.EVPool, } - if cfg.BindUserId != 0 && cfg.BindUserId != s.userid { - return nil, false, fmt.Errorf("CDK已绑定其他用户") - } - if !cfg.ValidEndTime.IsZero() && cfg.ValidEndTime.Before(time.Now()) { - return nil, false, fmt.Errorf("绑定的CDK已过期") - } - - result := &SignRewardResult{} - var ( - infoDirty bool - bagItems []data.ItemInfo - ) - - appendRewardItem := func(itemID uint32, count int64) { - if itemID == 0 || count <= 0 { - return - } - switch itemID { - case 1: - result.Coins += count - playerInfo.Coins += count - infoDirty = true - case 3: - result.ExpPool += count - playerInfo.ExpPool += count - infoDirty = true - case 5: - result.Gold += count - case 9: - result.EVPool += count - playerInfo.EVPool += count - infoDirty = true - default: - bagItems = append(bagItems, data.ItemInfo{ItemId: int64(itemID), ItemCnt: count}) + if len(reward.Pets) > 0 { + result.PetIDs = make([]uint32, 0, len(reward.Pets)) + for _, pet := range reward.Pets { + result.PetIDs = append(result.PetIDs, pet.PetID) } } - - for _, rewardID := range cfg.ItemRewardIds { - itemInfo := configservice.NewItemService().GetItemCount(rewardID) - appendRewardItem(uint32(itemInfo.ItemId), itemInfo.ItemCnt) - } - - if result.Gold != 0 { - baseservice.NewBaseSysUserService().UpdateGold(s.userid, result.Gold*100) - } - if result.FreeGold != 0 { - baseservice.NewBaseSysUserService().UpdateFreeGold(s.userid, result.FreeGold*100) - } - if len(bagItems) > 0 { - items, err := NewItemService(s.userid).AddItems(bagItems) - if err != nil { - return nil, false, err - } - result.Items = items - } - - for _, rewardID := range cfg.ElfRewardIds { - pet := configservice.NewPetRewardService().Get(rewardID) - if pet == nil { - continue - } - petInfo := model.GenPetInfo(int(pet.MonID), int(pet.DV), int(pet.Nature), int(pet.Effect), int(pet.Lv), nil, 0) - if _, err := NewPetService(s.userid).PetAdd(petInfo, 0); err != nil { - return nil, false, err - } - result.PetIDs = append(result.PetIDs, uint32(pet.MonID)) - } - - if cfg.TitleRewardIds != 0 { - NewTitleService(s.userid).Give(cfg.TitleRewardIds) - result.TitleIDs = append(result.TitleIDs, cfg.TitleRewardIds) - } - - return result, infoDirty, nil + return result } func (s *SignService) buildState(record *model.SignInRecord) *SignState { @@ -312,6 +256,9 @@ func (s *SignService) buildState(record *model.SignInRecord) *SignState { cdkLogService := NewCdkService(s.userid) configs := configservice.NewSignInService().GetEnabled() for _, cfg := range configs { + if cfg.StageDays == 0 { + continue + } state.Stages = append(state.Stages, SignStageState{ SignType: cfg.SignType, StageDays: cfg.StageDays, @@ -324,14 +271,21 @@ func (s *SignService) buildState(record *model.SignInRecord) *SignState { } func stageReached(signType, stageDays uint32, record *model.SignInRecord) bool { - if record == nil || stageDays == 0 { + if record == nil { + return false + } + return stageReachedByDays(signType, stageDays, record.TotalDays, record.ContinuousDays) +} + +func stageReachedByDays(signType, stageDays, totalDays, continuousDays uint32) bool { + if stageDays == 0 { return false } switch signType { case configmodel.SignTypeContinuous: - return record.ContinuousDays >= stageDays + return continuousDays >= stageDays default: - return record.TotalDays >= stageDays + return totalDays >= stageDays } }