package controller import ( element "blazing/common/data/Element" "blazing/common/data/xmlres" "blazing/common/socket/errorcode" "blazing/logic/service/fight" "blazing/logic/service/item" "blazing/logic/service/player" "blazing/modules/player/model" "github.com/jinzhu/copier" ) const ( // ItemDefaultLeftTime 道具默认剩余时间(毫秒) ItemDefaultLeftTime = 360000 // UniversalNatureItemID 全能性格转化剂Ω UniversalNatureItemID uint32 = 300136 ) // GetUserItemList 获取用户道具列表 // data: 包含分页参数的输入信息 // c: 当前玩家对象 // 返回: 道具列表和错误码 func (h Controller) GetUserItemList(data *ItemListInboundInfo, c *player.Player) (result *item.ItemListOutboundInfo, err errorcode.ErrorCode) { result = &item.ItemListOutboundInfo{ ItemList: c.Service.Item.GetUserItemList(data.Param1, data.Param2, ItemDefaultLeftTime), } return result, 0 } // UsePetItemOutOfFight 战斗外使用宠物道具 // data: 包含道具ID和宠物捕获时间的输入信息 // c: 当前玩家对象 // 返回: 使用后的宠物信息和错误码 func (h Controller) UsePetItemOutOfFight(data *C2S_USE_PET_ITEM_OUT_OF_FIGHT, c *player.Player) (result *item.S2C_USE_PET_ITEM_OUT_OF_FIGHT, err errorcode.ErrorCode) { slot, found := c.FindPetBagSlot(data.CatchTime) if !found { return nil, errorcode.ErrorCodes.Err10401 } currentPet := slot.PetInfoPtr() if currentPet == nil { return nil, errorcode.ErrorCodes.Err10401 } itemID := uint32(data.ItemID) if c.Service.Item.CheakItem(itemID) == 0 { return nil, errorcode.ErrorCodes.ErrInsufficientItems } oldHP := currentPet.Hp itemCfg, ok := xmlres.ItemsMAP[int(itemID)] if !ok { errcode := h.handleRegularPetItem(itemID, currentPet) if errcode != 0 { return nil, errcode } refreshPetPaneKeepHP(currentPet, oldHP) if err := c.Service.Item.UPDATE(itemID, -1); err != nil { return nil, errorcode.ErrorCodes.ErrInsufficientItems } c.Service.Info.Save(*c.Info) result = &item.S2C_USE_PET_ITEM_OUT_OF_FIGHT{} copier.Copy(&result, currentPet) return result, 0 } var errcode errorcode.ErrorCode switch { case itemID == 300036: errcode = h.handleNeuronItem(currentPet, c) if errcode == 0 { refreshPetPaneKeepHP(currentPet, oldHP) } case itemID == 300212: errcode = h.handlexuancaiItem(currentPet, c) case itemCfg.Bonus != 0: errcode = errorcode.ErrorCodes.ErrItemUnusable case itemCfg.HP != 0: errcode = h.handleRecoverHPItemOutOfFight(itemCfg.HP, currentPet) case itemCfg.PP != 0: errcode = h.handleRecoverPPItemOutOfFight(itemCfg.PP, currentPet) default: errcode = h.handleRegularPetItem(itemID, currentPet) if errcode == 0 { refreshPetPaneKeepHP(currentPet, oldHP) } } if errcode != 0 { return nil, errcode } if err := c.Service.Item.UPDATE(itemID, -1); err != nil { return nil, errorcode.ErrorCodes.ErrInsufficientItems } c.Service.Info.Save(*c.Info) result = &item.S2C_USE_PET_ITEM_OUT_OF_FIGHT{} copier.Copy(&result, currentPet) return result, 0 } // handleNeuronItem 处理神经元道具的特殊逻辑 func (h Controller) handleNeuronItem(currentPet *model.PetInfo, c *player.Player) errorcode.ErrorCode { if currentPet.OldCatchTime == 0 { return errorcode.ErrorCodes.ErrSystemError } originalCatchTime := currentPet.CatchTime oldPet := c.Service.Pet.PetInfoOneUnscoped(currentPet.OldCatchTime) if oldPet == nil { return errorcode.ErrorCodes.ErrCannotRevertSpirit } copier.CopyWithOption(currentPet, oldPet.Data, copier.Option{DeepCopy: true}) currentPet.CatchTime = originalCatchTime currentPet.ShinyInfo = oldPet.Data.ShinyInfo currentPet.EffectInfo = oldPet.Data.EffectInfo return 0 } // 炫彩碎片 处理神300212 func (h Controller) handlexuancaiItem(currentPet *model.PetInfo, c *player.Player) errorcode.ErrorCode { r, _ := element.Calculator.GetCombination(int(xmlres.PetMAP[int(currentPet.ID)].Type)) if r.Secondary != nil { return errorcode.ErrorCodes.ErrItemUnusable } itemid := uint32(currentPet.Type()) + 400686 items := c.Service.Item.CheakItem(itemid) if items < 100 { return errorcode.ErrorCodes.ErrInsufficientItems } ok := currentPet.FixShiny() if !ok { return errorcode.ErrorCodes.ErrItemUnusable } if err := c.Service.Item.UPDATE(itemid, -100); err != nil { return errorcode.ErrorCodes.ErrInsufficientItems } return 0 } func (h Controller) handleRecoverHPItemOutOfFight(recoverHP int, currentPet *model.PetInfo) errorcode.ErrorCode { if currentPet.Hp >= currentPet.MaxHp { return errorcode.ErrorCodes.ErrItemUnusable } currentPet.ModelHP(int64(recoverHP)) if currentPet.Hp == 0 { currentPet.Hp = 1 } return 0 } func (h Controller) handleRecoverPPItemOutOfFight(recoverPP int, currentPet *model.PetInfo) errorcode.ErrorCode { if !canRecoverPP(currentPet) { return errorcode.ErrorCodes.ErrItemUnusable } currentPet.HealPP(recoverPP) return 0 } func canRecoverPP(currentPet *model.PetInfo) bool { for _, skill := range currentPet.SkillList { skillCfg, ok := xmlres.SkillMap[int(skill.ID)] if ok && skill.PP < uint32(skillCfg.MaxPP) { return true } } return false } func refreshPetPaneKeepHP(currentPet *model.PetInfo, hp uint32) { currentPet.CalculatePetPane(100) if hp > currentPet.MaxHp { currentPet.Hp = currentPet.MaxHp return } currentPet.Hp = hp } // handleRegularPetItem 处理普通宠物道具 func (h Controller) handleRegularPetItem(itemID uint32, currentPet *model.PetInfo) errorcode.ErrorCode { return item.PetItemRegistry.Handle(itemID, currentPet) } // ResetNature 重置宠物性格 // data: 包含道具ID和宠物捕获时间的输入信息 // c: 当前玩家对象 // 返回: 无数据和错误码 func (h Controller) ResetNature(data *C2S_PET_RESET_NATURE, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { slot, found := c.FindPetBagSlot(data.CatchTime) if !found { return nil, errorcode.ErrorCodes.Err10401 } currentPet := slot.PetInfoPtr() if currentPet == nil { return nil, errorcode.ErrorCodes.Err10401 } if data.ItemId != UniversalNatureItemID { return nil, errorcode.ErrorCodes.ErrItemUnusable } if _, ok := xmlres.NatureRootMap[int(data.Nature)]; !ok { return nil, errorcode.ErrorCodes.ErrItemUnusable } if c.Service.Item.CheakItem(data.ItemId) <= 0 { return nil, errorcode.ErrorCodes.ErrInsufficientItems } currentHP := currentPet.Hp currentPet.Nature = data.Nature refreshPetPaneKeepHP(currentPet, currentHP) if err := c.Service.Item.UPDATE(data.ItemId, -1); err != nil { return nil, errorcode.ErrorCodes.ErrInsufficientItems } c.Service.Info.Save(*c.Info) return result, 0 } // ============================== // 双倍经验加速器相关方法 // ============================== // UseSpeedupItem 使用双倍经验加速器 // data: 包含使用的双倍经验物品ID的输入信息 // c: 当前玩家对象 // 返回: 无数据(响应包单独组装)和错误码 // 说明:根据物品ID区分双倍/三倍经验加速器,使用后扣减道具并更新玩家剩余次数 func (h Controller) UseSpeedupItem(data *C2S_USE_SPEEDUP_ITEM, c *player.Player) (result *item.S2C_USE_SPEEDUP_ITEM, err errorcode.ErrorCode) { // 1. 校验道具是否存在且数量充足 itemCount := c.Service.Item.CheakItem(data.ItemID) if itemCount <= 0 { return nil, errorcode.ErrorCodes.ErrInsufficientItems } result = &item.S2C_USE_SPEEDUP_ITEM{} // 2. 核心业务逻辑:根据物品ID更新双倍/三倍经验剩余次数 // (注:需根据你的道具配置表,补充 ItemID 与双倍/三倍的映射逻辑) switch data.ItemID { case 300027: // 假设1001是双倍经验加速器道具ID if c.Info.TwoTimes != 0 { return nil, errorcode.ErrorCodes.ErrItemInUse } case 300067: if c.Info.TwoTimes != 0 { return nil, errorcode.ErrorCodes.ErrItemInUse } case 300051: // 假设1002是三倍经验加速器道具ID if c.Info.ThreeTimes != 0 { return nil, errorcode.ErrorCodes.ErrItemInUse } case 300115: if c.Info.ThreeTimes != 0 { return nil, errorcode.ErrorCodes.ErrItemInUse } default: return nil, errorcode.ErrorCodes.ErrSystemError // 未知道具ID } // 3. 扣减道具(数量-1) if err := c.Service.Item.UPDATE(data.ItemID, -1); err != nil { return nil, errorcode.ErrorCodes.ErrInsufficientItems } switch data.ItemID { case 300027: // 假设1001是双倍经验加速器道具ID c.Info.TwoTimes += 50 // 玩家对象新增 TwoTimesExp 字段存储双倍剩余次数 case 300067: c.Info.TwoTimes += 25 // 玩家对象新增 TwoTimesExp 字段存储双倍剩余次数 case 300051: // 假设1002是三倍经验加速器道具ID c.Info.ThreeTimes += 50 // 玩家对象新增 ThreeTimesExp 字段存储三倍剩余次数 case 300115: c.Info.ThreeTimes += 30 // 玩家对象新增 ThreeTimesExp 字段存储三倍剩余次数 } result.ThreeTimes = uint32(c.Info.ThreeTimes) // 返回三倍经验剩余次数 result.TwoTimes = uint32(c.Info.TwoTimes) // 返回双倍经验剩余次数 // 4. (可选)持久化玩家经验次数(根据你的项目存储逻辑补充) // c.Service.Player.SaveExpTimes(c) // 5. 返回无数据结果和成功错误码 return result, 0 } // ============================== // 能量吸收器相关方法 // ============================== // UseEnergyXishou 使用能量吸收器 // data: 包含使用的能量吸收器物品ID的输入信息 // c: 当前玩家对象 // 返回: 无数据(响应包单独组装)和错误码 // 说明:使用后扣减道具并更新玩家能量吸收器剩余次数 func (h Controller) UseEnergyXishou(data *C2S_USE_ENERGY_XISHOU, c *player.Player) (result *item.S2C_USE_ENERGY_XISHOU, err errorcode.ErrorCode) { // 1. 校验道具是否存在且数量充足 itemCount := c.Service.Item.CheakItem(data.ItemID) if itemCount <= 0 { return nil, errorcode.ErrorCodes.ErrInsufficientItems } if c.Info.EnergyTime != 0 { return nil, errorcode.ErrorCodes.ErrItemInUse } // 2. 核心业务逻辑:更新能量吸收器剩余次数 // (注:可根据道具ID配置不同的次数加成,此处默认+1) if err := c.Service.Item.UPDATE(data.ItemID, -1); err != nil { return nil, errorcode.ErrorCodes.ErrInsufficientItems } c.Info.EnergyTime += 40 // 玩家对象新增 EnergyTimes 字段存储能量吸收剩余次数 result = &item.S2C_USE_ENERGY_XISHOU{ EnergyTimes: uint32(c.Info.EnergyTime), } // 4. (可选)持久化玩家能量次数 // c.Service.Player.SaveEnergyTimes(c) // 5. 返回无数据结果和成功错误码 return result, 0 } // ============================== // 自动战斗仪相关方法 // ============================== // UseAutoFightItem 使用自动战斗仪 // data: 包含使用的自动战斗仪物品ID的输入信息 // c: 当前玩家对象 // 返回: 无数据(响应包单独组装)和错误码 // 说明:使用后扣减道具,开启自动战斗(flag设为3)并更新剩余次数 func (h Controller) UseAutoFightItem(data *C2S_USE_AUTO_FIGHT_ITEM, c *player.Player) (result *item.S2C_USE_AUTO_FIGHT_ITEM, err errorcode.ErrorCode) { // 1. 校验道具是否存在且数量充足 itemCount := c.Service.Item.CheakItem(data.ItemID) if itemCount <= 0 { return nil, errorcode.ErrorCodes.ErrInsufficientItems } if c.Info.AutoFightTime != 0 { return nil, errorcode.ErrorCodes.ErrItemInUse } if err := c.Service.Item.UPDATE(data.ItemID, -1); err != nil { return nil, errorcode.ErrorCodes.ErrInsufficientItems } result = &item.S2C_USE_AUTO_FIGHT_ITEM{} // 2. 核心业务逻辑:开启自动战斗 + 更新剩余次数 c.Info.AutoFight = 3 // 按需求设置自动战斗flag为3(需测试) if data.ItemID == 300028 { c.Info.AutoFightTime += 100 } result.AutoFight = 1 switch data.ItemID { case 300028: c.Info.AutoFightTime += 100 case 300068: c.Info.AutoFightTime += 50 } result.AutoFightTimes = c.Info.AutoFightTime return result, 0 }