From b4a8048b857f8940f03251c2dd1af92d5a4e5519 Mon Sep 17 00:00:00 2001 From: xinian Date: Tue, 31 Mar 2026 06:51:40 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=88=98=E6=96=97?= =?UTF-8?q?=E6=95=88=E6=9E=9C800-814=E5=8F=8A=E4=BC=98=E5=8C=96=E9=81=93?= =?UTF-8?q?=E5=85=B7=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- logic/controller/action_大师杯.go | 182 ++++++++-------- logic/controller/action_炫彩碎片.go | 18 +- logic/controller/item_use.go | 82 +++++++- logic/service/fight/effect/800_804.go | 291 ++++++++++++++++++++++++++ logic/service/fight/effect/805_809.go | 145 +++++++++++++ logic/service/fight/effect/810_814.go | 161 ++++++++++++++ modules/player/service/item.go | 61 ++++++ 7 files changed, 841 insertions(+), 99 deletions(-) create mode 100644 logic/service/fight/effect/800_804.go create mode 100644 logic/service/fight/effect/805_809.go create mode 100644 logic/service/fight/effect/810_814.go diff --git a/logic/controller/action_大师杯.go b/logic/controller/action_大师杯.go index 4b870e643..eedff6310 100644 --- a/logic/controller/action_大师杯.go +++ b/logic/controller/action_大师杯.go @@ -11,119 +11,134 @@ import ( "github.com/pointernil/bitset32" ) -func (h Controller) DASHIbei(data *C2s_MASTER_REWARDS, c *player.Player) (result *S2C_MASTER_REWARDS, err errorcode.ErrorCode) { +const ( + masterCupTaskID uint32 = 111 + masterCupRewardItemMin uint32 = 80000000 + masterCupRewardItemMax uint32 = 80000015 +) + +var masterCupRewardElementOrder = [...]uint32{1, 2, 3, 5, 11, 4, 6, 7, 9} + +var masterCupRequiredItems = map[uint32][]ItemS{ + 8: { + {ItemId: 80000001, ItemCnt: 100}, + {ItemId: 80000002, ItemCnt: 20}, + {ItemId: 80000003, ItemCnt: 20}, + {ItemId: 80000005, ItemCnt: 20}, + {ItemId: 80000011, ItemCnt: 20}, + }, + 7: { + {ItemId: 80000001, ItemCnt: 20}, + {ItemId: 80000002, ItemCnt: 20}, + {ItemId: 80000003, ItemCnt: 100}, + {ItemId: 80000005, ItemCnt: 20}, + {ItemId: 80000011, ItemCnt: 20}, + }, + 1: { + {ItemId: 80000001, ItemCnt: 20}, + {ItemId: 80000002, ItemCnt: 100}, + {ItemId: 80000003, ItemCnt: 20}, + {ItemId: 80000005, ItemCnt: 20}, + {ItemId: 80000011, ItemCnt: 20}, + }, +} + +func (h Controller) DASHIbei(req *C2s_MASTER_REWARDS, c *player.Player) (result *S2C_MASTER_REWARDS, err errorcode.ErrorCode) { + _ = req result = &S2C_MASTER_REWARDS{} - //草","水","火","电","战斗","飞行","机械","地面","冰" - // 按顺序:草、水、火、电、战斗、飞行、机械、地面、冰 - var ElementTypeNumbers = []int{1, 2, 3, 5, 11, 4, 6, 7, 9} - items := c.Service.Item.Get(80000000, 80000000+15) - result.Reward = make([]uint32, 9) - for i := 0; i < 9; i++ { - - for _, v1 := range items { - if ElementTypeNumbers[i]+80000000 == int(v1.ItemId) { - result.Reward[i] = uint32(v1.ItemCnt) - } - - } - } + items := c.Service.Item.Get(masterCupRewardItemMin, masterCupRewardItemMax) + result.Reward = buildMasterCupRewards(items) return } -func (h Controller) DASHIbeiR(data *C2s_MASTER_REWARDSR, c *player.Player) (result *S2C_MASTER_REWARDSR, err errorcode.ErrorCode) { + +func (h Controller) DASHIbeiR(req *C2s_MASTER_REWARDSR, c *player.Player) (result *S2C_MASTER_REWARDSR, err errorcode.ErrorCode) { result = &S2C_MASTER_REWARDSR{} - //ids := []uint32{8, 7, 1, 9, 14, 15, 16, 17, 18, 2, 3, 4, 5, 6, 10, 11, 12, 13} - - tt, ok := nedds[data.ElementType] + requiredItems, ok := masterCupRequiredItems[req.ElementType] if !ok { return nil, errorcode.ErrorCode(errorcode.ErrorCodes.ErrSystemError) } - taskInfo := task.GetTaskInfo(int(111), int(data.ElementType)) + taskInfo := task.GetTaskInfo(int(masterCupTaskID), int(req.ElementType)) if taskInfo == nil { return nil, errorcode.ErrorCodes.ErrNeedCompleteTaskForPrize } - for _, v := range tt { - - if c.Service.Item.CheakItem(v.ItemId) < int64(v.ItemCnt) { - return nil, errorcode.ErrorCode(errorcode.ErrorCodes.ErrInsufficientItems) - - } - + if !hasEnoughMasterCupItems(c, requiredItems) { + return nil, errorcode.ErrorCode(errorcode.ErrorCodes.ErrInsufficientItems) } - c.Service.Task.Exec(uint32(111), func(te *model.Task) bool { - r := bitset32.From(te.Data) - // 分支未完成时,标记完成并发放奖励 - if !r.Test(uint(data.ElementType)) { - for _, v := range tt { - - c.Service.Item.UPDATE(v.ItemId, -int(v.ItemCnt)) - - } - r.Set(uint(data.ElementType)) - te.Data = r.Bytes() - - 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) - } - - } - - return true - } else { + result.ItemList = make([]data.ItemInfo, 0, len(taskInfo.ItemList)) + c.Service.Task.Exec(masterCupTaskID, func(te *model.Task) bool { + progress := bitset32.From(te.Data) + if progress.Test(uint(req.ElementType)) { err = errorcode.ErrorCode(errorcode.ErrorCodes.ErrAwardAlreadyClaimed) + return false } - return false + + consumeMasterCupItems(c, requiredItems) + progress.Set(uint(req.ElementType)) + te.Data = progress.Bytes() + + if taskInfo.Pet != nil { + c.Service.Pet.PetAdd(taskInfo.Pet, 0) + result.CaptureTime = taskInfo.Pet.CatchTime + result.PetTypeId = taskInfo.Pet.ID + } + + appendMasterCupRewardItems(c, result, taskInfo.ItemList) + return true }) return } -var nedds = map[uint32][]ItemS{ - 8: []ItemS{ - {ItemId: 80000001, ItemCnt: 100}, - {ItemId: 80000002, ItemCnt: 20}, - {ItemId: 80000003, ItemCnt: 20}, - {ItemId: 80000005, ItemCnt: 20}, - {ItemId: 80000011, ItemCnt: 20}}, - 7: []ItemS{ - {ItemId: 80000001, ItemCnt: 20}, - {ItemId: 80000002, ItemCnt: 20}, - {ItemId: 80000003, ItemCnt: 100}, - {ItemId: 80000005, ItemCnt: 20}, - {ItemId: 80000011, ItemCnt: 20}}, - 1: []ItemS{ - {ItemId: 80000001, ItemCnt: 20}, - {ItemId: 80000002, ItemCnt: 100}, - {ItemId: 80000003, ItemCnt: 20}, - {ItemId: 80000005, ItemCnt: 20}, - {ItemId: 80000011, ItemCnt: 20}}, -} - -type NeddItemS struct { - index uint32 - needitem []ItemS -} type ItemS struct { ItemId uint32 ItemCnt uint32 } +func buildMasterCupRewards(items []model.Item) []uint32 { + itemCounts := make(map[uint32]uint32, len(items)) + for _, item := range items { + itemCounts[item.ItemId] = uint32(item.ItemCnt) + } + + rewards := make([]uint32, len(masterCupRewardElementOrder)) + for i, elementType := range masterCupRewardElementOrder { + rewards[i] = itemCounts[masterCupRewardItemMin+elementType] + } + + return rewards +} + +func hasEnoughMasterCupItems(c *player.Player, requiredItems []ItemS) bool { + for _, item := range requiredItems { + if c.Service.Item.CheakItem(item.ItemId) < int64(item.ItemCnt) { + return false + } + } + + return true +} + +func consumeMasterCupItems(c *player.Player, requiredItems []ItemS) { + for _, item := range requiredItems { + c.Service.Item.UPDATE(item.ItemId, -int(item.ItemCnt)) + } +} + +func appendMasterCupRewardItems(c *player.Player, result *S2C_MASTER_REWARDSR, itemList []data.ItemInfo) { + for _, item := range itemList { + if c.ItemAdd(item.ItemId, item.ItemCnt) { + result.ItemList = append(result.ItemList, item) + } + } +} + type C2s_MASTER_REWARDS struct { Head common.TomeeHeader `cmd:"2611" struc:"skip"` //玩家登录 - } // OutInfo 表示地图热度的出站消息 @@ -131,6 +146,7 @@ type S2C_MASTER_REWARDS struct { ReLen uint32 `struc:"sizeof=Reward"` Reward []uint32 `json:"Reward"` } + type C2s_MASTER_REWARDSR struct { Head common.TomeeHeader `cmd:"2612" struc:"skip"` //玩家登录 ElementType uint32 diff --git a/logic/controller/action_炫彩碎片.go b/logic/controller/action_炫彩碎片.go index 8e8d5f905..a51599a2c 100644 --- a/logic/controller/action_炫彩碎片.go +++ b/logic/controller/action_炫彩碎片.go @@ -45,6 +45,8 @@ func (h Controller) GET_XUANCAI(data *C2s_GET_XUANCAI, c *player.Player) (result return nil, errorcode.ErrorCode(errorcode.ErrorCodes.ErrDailyGiftLimit) } c.Info.SetTask(13, model.Completed) + selectedItems := make([]uint32, 0, 10) + itemMask := make(map[uint32]uint32, 10) // 循环直到选中10个元素 for selectedCount < 10 { // 随机生成0~14的位索引(对应1~15号元素) @@ -54,14 +56,20 @@ func (h Controller) GET_XUANCAI(data *C2s_GET_XUANCAI, c *player.Player) (result // 检查该位是否未被选中(避免重复) if (result.Status & mask) == 0 { - - if c.ItemAdd(400686+int64(randBitIdx)+1, 1) { - result.Status |= mask // 标记该位为选中 - } - + itemID := uint32(400686 + randBitIdx + 1) + selectedItems = append(selectedItems, itemID) + itemMask[itemID] = mask selectedCount++ // 选中数+1 } } + + successItems, addErr := c.Service.Item.AddUniqueItems(selectedItems) + if addErr != nil { + return nil, errorcode.ErrorCode(errorcode.ErrorCodes.ErrSystemError200007) + } + for _, itemID := range successItems { + result.Status |= itemMask[itemID] + } return } diff --git a/logic/controller/item_use.go b/logic/controller/item_use.go index 2fe88e0bc..1db177769 100644 --- a/logic/controller/item_use.go +++ b/logic/controller/item_use.go @@ -46,29 +46,46 @@ func (h Controller) UsePetItemOutOfFight(data *item.C2S_USE_PET_ITEM_OUT_OF_FIGH return nil, errorcode.ErrorCodes.Err10401 } - if c.Service.Item.CheakItem(uint32(data.ItemID)) == 0 { + itemID := uint32(data.ItemID) + if c.Service.Item.CheakItem(itemID) == 0 { return nil, errorcode.ErrorCodes.ErrSystemError } + itemCfg, ok := xmlres.ItemsMAP[int(itemID)] + if !ok { + return nil, errorcode.ErrorCodes.ErrSystemError + } + + oldHP := currentPet.Hp var errcode errorcode.ErrorCode - switch data.ItemID { - case 300036: + switch { + case itemID == 300036: errcode = h.handleNeuronItem(currentPet, c) - case 300212: + 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(uint32(data.ItemID), currentPet) + errcode = h.handleRegularPetItem(itemID, currentPet) + if errcode == 0 { + refreshPetPaneKeepHP(currentPet, oldHP) + } } if errcode != 0 { return nil, errcode } - c.Service.Item.UPDATE(uint32(data.ItemID), -1) + c.Service.Item.UPDATE(itemID, -1) result = &item.S2C_USE_PET_ITEM_OUT_OF_FIGHT{} - currentPet.CalculatePetPane(100) copier.Copy(&result, currentPet) - // defer c.Service.Info.Save(*c.Info) return result, 0 } @@ -113,14 +130,56 @@ func (h Controller) handlexuancaiItem(currentPet *model.PetInfo, c *player.Playe 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 { handler := item.PetItemRegistry.GetHandler(itemID) if handler == nil { - return errorcode.ErrorCodes.ErrSystemError + return errorcode.ErrorCodes.ErrItemUnusable } if !handler(itemID, currentPet) { - return errorcode.ErrorCodes.ErrSystemError + return errorcode.ErrorCodes.ErrItemUnusable } return 0 } @@ -139,8 +198,9 @@ func (h Controller) ResetNature(data *item.C2S_PET_RESET_NATURE, c *player.Playe return nil, errorcode.ErrorCodes.ErrSystemError } + currentHP := currentPet.Hp currentPet.Nature = data.Nature - currentPet.CalculatePetPane(100) + refreshPetPaneKeepHP(currentPet, currentHP) c.Service.Item.UPDATE(data.ItemId, -1) return result, 0 } diff --git a/logic/service/fight/effect/800_804.go b/logic/service/fight/effect/800_804.go new file mode 100644 index 000000000..746eff5bd --- /dev/null +++ b/logic/service/fight/effect/800_804.go @@ -0,0 +1,291 @@ +package effect + +import ( + "blazing/logic/service/fight/action" + "blazing/logic/service/fight/info" + "blazing/logic/service/fight/input" + "blazing/logic/service/fight/node" + + "github.com/alpacahq/alpacadecimal" +) + +// Effect 800: {0}回合内若对手使用属性技能,则下{1}回合自身受到的伤害不超过{2} +type Effect800 struct { + node.EffectNode +} + +func (e *Effect800) Skill_Use() bool { + if len(e.Args()) < 3 { + return true + } + + effect := e.Ctx().Our.InitEffect(input.EffectType.Sub, 800, int(e.Args()[0].IntPart()), int(e.Args()[1].IntPart()), int(e.Args()[2].IntPart())) + if effect != nil { + e.Ctx().Our.AddEffect(e.Ctx().Our, effect) + } + return true +} + +type Effect800Sub struct { + node.EffectNode + watchRounds int + capRounds int + capDamage alpacadecimal.Decimal +} + +func (e *Effect800Sub) SetArgs(t *input.Input, a ...int) { + e.EffectNode.SetArgs(t, a...) + e.Duration(-1) + if len(a) > 0 { + e.watchRounds = a[0] + } + if len(a) > 1 { + e.capRounds = 0 + } + if len(a) > 2 { + e.capDamage = alpacadecimal.NewFromInt(int64(a[2])) + } +} + +func (e *Effect800Sub) Skill_Use_ex() bool { + if e.watchRounds <= 0 || len(e.Args()) < 3 || e.Ctx().SkillEntity == nil { + return true + } + if e.Ctx().SkillEntity.Category() != info.Category.STATUS { + return true + } + + e.capRounds = int(e.Args()[1].IntPart()) + return true +} + +func (e *Effect800Sub) DamageLockEx(zone *info.DamageZone) bool { + if e.capRounds <= 0 || zone == nil || zone.Type != info.DamageType.Red { + return true + } + if zone.Damage.Cmp(e.capDamage) <= 0 { + return true + } + + zone.Damage = e.capDamage + return true +} + +func (e *Effect800Sub) TurnEnd() { + if e.watchRounds > 0 { + e.watchRounds-- + } + if e.capRounds > 0 { + e.capRounds-- + } + if e.watchRounds <= 0 && e.capRounds <= 0 { + e.Alive(false) + } +} + +// Effect 801: 消除对手能力提升,消除成功则下{0}回合必定先出手、下{1}回合造成的伤害恢复自身体力 +type Effect801 struct { + node.EffectNode +} + +func (e *Effect801) Skill_Use() bool { + if len(e.Args()) < 2 || !clearPositiveProps(e.Ctx().Opp, e.Ctx().Our) { + return true + } + + effect := e.Ctx().Our.InitEffect(input.EffectType.Sub, 801, int(e.Args()[0].IntPart()), int(e.Args()[1].IntPart())) + if effect != nil { + e.Ctx().Our.AddEffect(e.Ctx().Our, effect) + } + return true +} + +type Effect801Sub struct { + node.EffectNode + priorityRounds int + drainRounds int +} + +func (e *Effect801Sub) SetArgs(t *input.Input, a ...int) { + e.EffectNode.SetArgs(t, a...) + e.Duration(-1) + if len(a) > 0 { + e.priorityRounds = a[0] + } + if len(a) > 1 { + e.drainRounds = a[1] + } +} + +func (e *Effect801Sub) ComparePre(fattack, sattack *action.SelectSkillAction) bool { + if e.priorityRounds <= 0 { + return true + } + + current := actionByPlayer(fattack, sattack, e.Ctx().Our.UserID) + if current == nil || current.SkillEntity == nil { + return true + } + current.SkillEntity.XML.Priority = 999999 + return true +} + +func (e *Effect801Sub) Action_end() bool { + if e.drainRounds <= 0 || e.Ctx().SkillEntity == nil { + return true + } + if e.Ctx().SkillEntity.Category() == info.Category.STATUS || e.Ctx().Our.SumDamage.Cmp(alpacadecimal.Zero) <= 0 { + return true + } + + e.Ctx().Our.Heal(e.Ctx().Our, &action.SelectSkillAction{}, e.Ctx().Our.SumDamage) + return true +} + +func (e *Effect801Sub) TurnEnd() { + if e.priorityRounds > 0 { + e.priorityRounds-- + } + if e.drainRounds > 0 { + e.drainRounds-- + } + if e.priorityRounds <= 0 && e.drainRounds <= 0 { + e.Alive(false) + } +} + +// Effect 802: {0}回合内免疫控制类异常状态 +type Effect802 struct { + RoundEffectArg0Base +} + +func (e *Effect802) EFFect_Befer(in *input.Input, effEffect input.Effect) bool { + if in != e.Ctx().Opp || !input.IS_Stat(effEffect) { + return true + } + if !isControlStatus800(statusIDFromEffect800(effEffect)) { + return true + } + return false +} + +func statusIDFromEffect800(eff input.Effect) int { + if eff == nil { + return 0 + } + return int(eff.ID().Suffix()) +} + +func isControlStatus800(statusID int) bool { + switch info.EnumPetStatus(statusID) { + case info.PetStatus.Paralysis, + info.PetStatus.Tired, + info.PetStatus.Fear, + info.PetStatus.Petrified, + info.PetStatus.Sleep: + return true + default: + return false + } +} + +// Effect 803: 命中后{0}%令对手{1},未触发则恢复自身最大体力的1/{2}体力且{3}回合内自身受到的伤害不超过{4} +type Effect803 struct { + node.EffectNode +} + +func (e *Effect803) OnSkill() bool { + if len(e.Args()) < 5 { + return true + } + + success, _, _ := e.Input.Player.Roll(int(e.Args()[0].IntPart()), 100) + if success { + addStatusByID(e.Ctx().Our, e.Ctx().Opp, int(e.Args()[1].IntPart())) + return true + } + if e.Args()[2].Cmp(alpacadecimal.Zero) > 0 { + e.Ctx().Our.Heal(e.Ctx().Our, &action.SelectSkillAction{}, e.Ctx().Our.CurrentPet.GetMaxHP().Div(e.Args()[2])) + } + + effect := e.Ctx().Our.InitEffect(input.EffectType.Sub, 803, int(e.Args()[3].IntPart()), int(e.Args()[4].IntPart())) + if effect != nil { + e.Ctx().Our.AddEffect(e.Ctx().Our, effect) + } + return true +} + +type Effect803Sub struct { + RoundEffectArg0Base +} + +func (e *Effect803Sub) DamageLockEx(zone *info.DamageZone) bool { + if zone == nil || zone.Type != info.DamageType.Red || len(e.Args()) < 2 { + return true + } + if zone.Damage.Cmp(e.Args()[1]) <= 0 { + return true + } + zone.Damage = e.Args()[1] + return true +} + +// Effect 804: {0}回合内自身能力提升状态被消除或吸取时,令对手全属性-{1} +type Effect804 struct { + node.EffectNode +} + +func (e *Effect804) Skill_Use() bool { + if len(e.Args()) < 2 { + return true + } + + effect := e.Ctx().Our.InitEffect(input.EffectType.Sub, 804, int(e.Args()[0].IntPart()), int(e.Args()[1].IntPart())) + if effect != nil { + e.Ctx().Our.AddEffect(e.Ctx().Our, effect) + } + return true +} + +type Effect804Sub struct { + RoundEffectArg0Base + triggered bool +} + +func (e *Effect804Sub) PropBefer(in *input.Input, prop int8, level int8) bool { + if len(e.Args()) < 2 || in != e.Ctx().Our || e.triggered { + return true + } + if int(prop) < 0 || int(prop) >= len(e.Ctx().Our.Prop) { + return true + } + if level > 0 || e.Ctx().Our.Prop[prop] <= 0 { + return true + } + + e.triggered = true + applyAllPropDown(e.Ctx().Our, e.Ctx().Opp, int8(e.Args()[1].IntPart())) + return true +} + +func (e *Effect804Sub) Action_end() bool { + e.triggered = false + return true +} + +func (e *Effect804Sub) Action_end_ex() bool { + e.triggered = false + return true +} + +func init() { + input.InitEffect(input.EffectType.Skill, 800, &Effect800{}) + input.InitEffect(input.EffectType.Sub, 800, &Effect800Sub{}) + input.InitEffect(input.EffectType.Skill, 801, &Effect801{}) + input.InitEffect(input.EffectType.Sub, 801, &Effect801Sub{}) + input.InitEffect(input.EffectType.Skill, 802, &Effect802{}) + input.InitEffect(input.EffectType.Skill, 803, &Effect803{}) + input.InitEffect(input.EffectType.Sub, 803, &Effect803Sub{}) + input.InitEffect(input.EffectType.Skill, 804, &Effect804{}) + input.InitEffect(input.EffectType.Sub, 804, &Effect804Sub{}) +} diff --git a/logic/service/fight/effect/805_809.go b/logic/service/fight/effect/805_809.go new file mode 100644 index 000000000..dc8717326 --- /dev/null +++ b/logic/service/fight/effect/805_809.go @@ -0,0 +1,145 @@ +package effect + +import ( + "blazing/logic/service/fight/action" + "blazing/logic/service/fight/info" + "blazing/logic/service/fight/input" + "blazing/logic/service/fight/node" + + "github.com/alpacahq/alpacadecimal" +) + +// Effect 805: 消除对手能力提升状态,消除成功则令对手随机{0}项技能PP值归零 +type Effect805 struct { + node.EffectNode +} + +func (e *Effect805) Skill_Use() bool { + if len(e.Args()) == 0 || !clearPositiveProps(e.Ctx().Opp, e.Ctx().Our) { + return true + } + zeroRandomSkillPP(e.Ctx().Opp, int(e.Args()[0].IntPart())) + return true +} + +// Effect 806: {0}回合内若对手使用攻击技能则使用后令自身全属性+{1} +type Effect806 struct { + node.EffectNode +} + +func (e *Effect806) Skill_Use() bool { + if len(e.Args()) < 2 { + return true + } + + effect := e.Ctx().Our.InitEffect(input.EffectType.Sub, 806, int(e.Args()[0].IntPart()), int(e.Args()[1].IntPart())) + if effect != nil { + e.Ctx().Our.AddEffect(e.Ctx().Our, effect) + } + return true +} + +type Effect806Sub struct { + RoundEffectArg0Base +} + +func (e *Effect806Sub) Skill_Use_ex() bool { + if len(e.Args()) < 2 || e.Ctx().SkillEntity == nil { + return true + } + if e.Ctx().SkillEntity.Category() == info.Category.STATUS { + return true + } + applyAllPropUp(e.Ctx().Our, int8(e.Args()[1].IntPart())) + return true +} + +// Effect 807: 附加对手上次造成伤害数值的固定伤害 +type Effect807 struct { + node.EffectNode +} + +func (e *Effect807) OnSkill() bool { + if e.Ctx().Opp.SumDamage.Cmp(alpacadecimal.Zero) <= 0 { + return true + } + + e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{ + Type: info.DamageType.Fixed, + Damage: e.Ctx().Opp.SumDamage, + }) + return true +} + +// Effect 808: 自身每处于一种能力提升状态则附加{0}点固定伤害 +type Effect808 struct { + node.EffectNode +} + +func (e *Effect808) OnSkill() bool { + if len(e.Args()) == 0 { + return true + } + count := 0 + for _, v := range e.Ctx().Our.Prop[:] { + if v > 0 { + count++ + } + } + if count <= 0 { + return true + } + + damage := e.Args()[0].Mul(alpacadecimal.NewFromInt(int64(count))) + if damage.Cmp(alpacadecimal.Zero) <= 0 { + return true + } + + e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{ + Type: info.DamageType.Fixed, + Damage: damage, + }) + return true +} + +// Effect 809: 使对手下次使用的攻击技能失效 +type Effect809 struct { + node.EffectNode +} + +func (e *Effect809) Skill_Use() bool { + effect := e.Ctx().Our.InitEffect(input.EffectType.Sub, 809) + if effect != nil { + e.Ctx().Opp.AddEffect(e.Ctx().Our, effect) + } + return true +} + +type Effect809Sub struct { + node.EffectNode +} + +func (e *Effect809Sub) SetArgs(t *input.Input, a ...int) { + e.EffectNode.SetArgs(t, a...) + e.Duration(-1) +} + +func (e *Effect809Sub) ActionStart(a, b *action.SelectSkillAction) bool { + if e.Ctx().SkillEntity == nil || e.Ctx().SkillEntity.Category() == info.Category.STATUS { + return true + } + + e.Ctx().SkillEntity.SetMiss() + e.Alive(false) + return true +} + +func init() { + input.InitEffect(input.EffectType.Skill, 805, &Effect805{}) + input.InitEffect(input.EffectType.Skill, 806, &Effect806{}) + input.InitEffect(input.EffectType.Sub, 806, &Effect806Sub{}) + input.InitEffect(input.EffectType.Skill, 807, &Effect807{}) + input.InitEffect(input.EffectType.Skill, 808, &Effect808{}) + input.InitEffect(input.EffectType.Skill, 809, &Effect809{}) + input.InitEffect(input.EffectType.Sub, 809, &Effect809Sub{}) +} diff --git a/logic/service/fight/effect/810_814.go b/logic/service/fight/effect/810_814.go new file mode 100644 index 000000000..8d23d4faf --- /dev/null +++ b/logic/service/fight/effect/810_814.go @@ -0,0 +1,161 @@ +package effect + +import ( + "blazing/logic/service/fight/action" + "blazing/logic/service/fight/info" + "blazing/logic/service/fight/input" + "blazing/logic/service/fight/node" + + "github.com/alpacahq/alpacadecimal" +) + +// Effect 810: 每次命中对手后此技能威力下降{0}点 +type Effect810 struct { + node.EffectNode + powerDown int + skillID int +} + +func (e *Effect810) SkillHit() bool { + if len(e.Args()) == 0 || e.Ctx().SkillEntity == nil || e.Ctx().SkillEntity.Category() == info.Category.STATUS { + return true + } + currentSkillID := e.Ctx().SkillEntity.XML.ID + if e.skillID != 0 && e.skillID != currentSkillID { + e.skillID = 0 + e.powerDown = 0 + } + e.skillID = currentSkillID + + power := e.Ctx().SkillEntity.XML.Power - e.powerDown + if power < 1 { + power = 1 + } + e.Ctx().SkillEntity.XML.Power = power + return true +} + +func (e *Effect810) Skill_Use() bool { + if len(e.Args()) == 0 || e.Ctx().SkillEntity == nil || e.Ctx().SkillEntity.Category() == info.Category.STATUS { + return true + } + if e.Ctx().SkillEntity.AttackTime == 0 { + return true + } + e.powerDown += int(e.Args()[0].IntPart()) + return true +} + +// Effect 811: 使自身下次受到的伤害减少n点,n等于本回合自身造成的伤害 +type Effect811 struct { + node.EffectNode +} + +func (e *Effect811) Skill_Use() bool { + if e.Ctx().Our.SumDamage.Cmp(alpacadecimal.Zero) <= 0 { + return true + } + + effect := e.Ctx().Our.InitEffect(input.EffectType.Sub, 811, int(e.Ctx().Our.SumDamage.IntPart())) + if effect != nil { + e.Ctx().Our.AddEffect(e.Ctx().Our, effect) + } + return true +} + +type Effect811Sub struct { + node.EffectNode +} + +func (e *Effect811Sub) SetArgs(t *input.Input, a ...int) { + e.EffectNode.SetArgs(t, a...) + e.Duration(-1) +} + +func (e *Effect811Sub) DamageSubEx(zone *info.DamageZone) bool { + if zone == nil || zone.Type != info.DamageType.Red || len(e.Args()) == 0 { + return true + } + if zone.Damage.Cmp(e.Args()[0]) > 0 { + zone.Damage = zone.Damage.Sub(e.Args()[0]) + } else { + zone.Damage = alpacadecimal.Zero + } + e.Alive(false) + return true +} + +// Effect 812: 自身速度能力每提升1段,则回合结束时减少对手1/{0}最大体力 +type Effect812 struct { + node.EffectNode +} + +func (e *Effect812) TurnEnd() { + if len(e.Args()) == 0 || e.Args()[0].Cmp(alpacadecimal.Zero) <= 0 { + return + } + if e.Ctx().Our.Prop[4] <= 0 { + return + } + + base := e.Ctx().Opp.CurrentPet.GetMaxHP().Div(e.Args()[0]) + damage := base.Mul(alpacadecimal.NewFromInt(int64(e.Ctx().Our.Prop[4]))) + if damage.Cmp(alpacadecimal.Zero) <= 0 { + return + } + + e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{ + Type: info.DamageType.Percent, + Damage: damage, + }) +} + +// Effect 813: 将自身的能力下降状态双倍反馈给对手 +type Effect813 struct { + node.EffectNode +} + +func (e *Effect813) OnSkill() bool { + for i, v := range e.Ctx().Our.Prop[:] { + if v >= 0 { + continue + } + e.Ctx().Opp.SetProp(e.Ctx().Our, int8(i), v*2) + } + return true +} + +// Effect 814: 先出手时附加自身双防值总和{0}%的百分比伤害 +type Effect814 struct { + node.EffectNode +} + +func (e *Effect814) OnSkill() bool { + if len(e.Args()) == 0 || !e.IsFirst() { + return true + } + if e.Ctx().SkillEntity == nil || e.Ctx().SkillEntity.Category() == info.Category.STATUS { + return true + } + + totalDefense := e.Ctx().Our.GetProp(1).Add(e.Ctx().Our.GetProp(3)) + damage := totalDefense.Mul(e.Args()[0]).Div(hundred) + if damage.Cmp(alpacadecimal.Zero) <= 0 { + return true + } + + e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{ + Type: info.DamageType.Fixed, + Damage: damage, + }) + return true +} + +func init() { + input.InitEffect(input.EffectType.Skill, 810, &Effect810{}) + input.InitEffect(input.EffectType.Skill, 811, &Effect811{}) + input.InitEffect(input.EffectType.Sub, 811, &Effect811Sub{}) + input.InitEffect(input.EffectType.Skill, 812, &Effect812{}) + input.InitEffect(input.EffectType.Skill, 813, &Effect813{}) + input.InitEffect(input.EffectType.Skill, 814, &Effect814{}) +} diff --git a/modules/player/service/item.go b/modules/player/service/item.go index 81fcd4ade..a00795a3b 100644 --- a/modules/player/service/item.go +++ b/modules/player/service/item.go @@ -5,6 +5,8 @@ import ( "blazing/modules/player/model" "context" + dictservice "blazing/modules/dict/service" + "github.com/gogf/gf/v2/frame/g" ) @@ -58,6 +60,65 @@ func (s *ItemService) UPDATE(id uint32, count int) error { return nil } +// AddUniqueItems 为一组互不重复的物品各增加 1 个。 +// 返回值只包含本次实际成功增加的物品 id。 +func (s *ItemService) AddUniqueItems(ids []uint32) ([]uint32, error) { + if len(ids) == 0 { + return nil, nil + } + + currentItems := s.CheakItemM(ids...) + currentMap := make(map[uint32]int64, len(currentItems)) + for _, item := range currentItems { + currentMap[item.ItemId] = item.ItemCnt + } + + updateIDs := make([]uint32, 0, len(ids)) + insertData := g.List{} + successIDs := make([]uint32, 0, len(ids)) + + for _, id := range ids { + if id == 0 { + continue + } + + itemmax := dictservice.NewDictInfoService().GetMax(int64(id)) + if itemmax == 0 { + continue + } + if currentMap[id]+1 > int64(itemmax) { + continue + } + + successIDs = append(successIDs, id) + if _, ok := currentMap[id]; ok { + updateIDs = append(updateIDs, id) + continue + } + + insertData = append(insertData, g.Map{ + "player_id": s.userid, + "item_id": id, + "item_cnt": 1, + "is_vip": cool.Config.ServerInfo.IsVip, + }) + } + + if len(updateIDs) > 0 { + if _, err := s.dbm(s.Model).WhereIn("item_id", updateIDs).Increment("item_cnt", 1); err != nil { + return nil, err + } + } + + if len(insertData) > 0 { + if _, err := s.dbm(s.Model).Data(insertData).Insert(); err != nil { + return nil, err + } + } + + return successIDs, nil +} + // func (s *ItemService) UPDATEM(ids map[uint32]int) { // if cool.Config.ServerInfo.IsVip != 0 {