Files
bl/logic/service/fight/effect/1097_1101.go
xinian 78a68148ce
Some checks failed
ci/woodpecker/push/my-first-workflow Pipeline failed
chore: update fight logic and effect implementations
2026-04-05 02:25:44 +08:00

599 lines
14 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package effect
import (
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"blazing/logic/service/fight/node"
"blazing/modules/player/model"
"github.com/alpacahq/alpacadecimal"
"github.com/gogf/gf/v2/util/grand"
)
var hundred = alpacadecimal.NewFromInt(100)
// Effect 1097: 造成的攻击伤害若低于280则令对手疲惫未击败对手则令对手下1回合使用的攻击技能无效;
// 技能结束后对手体力值高于0则50%进行一次额外行动以触发星皇之怒
type Effect1097 struct {
node.EffectNode
starFuryActive bool
}
func (e *Effect1097) Skill_Use() bool {
source := e.SourceInput()
target := e.TargetInput()
if source == nil || target == nil {
return true
}
skill := e.Ctx().SkillEntity
if skill == nil || skill.Category() == info.Category.STATUS {
return true
}
if skill.AttackTime != 0 && source.SumDamage.Cmp(alpacadecimal.NewFromInt(280)) < 0 {
tiredEffect := source.InitEffect(input.EffectType.Status, int(info.PetStatus.Tired))
if tiredEffect != nil {
tiredEffect.Duration(1)
target.AddEffect(source, tiredEffect)
}
}
if target.CurPet[0].Info.Hp > 0 {
disableAttack := source.InitEffect(input.EffectType.Sub, 1097, 1, 0)
if disableAttack != nil {
target.AddEffect(source, disableAttack)
}
}
if e.starFuryActive {
if target.CurPet[0].Info.Hp <= 0 {
return true
}
success, _, _ := source.Player.Roll(50, 100)
if success {
blindEffect := source.InitEffect(input.EffectType.Status, int(info.PetStatus.Blind))
if blindEffect != nil {
target.AddEffect(source, blindEffect)
}
return true
}
disableStatus := source.InitEffect(input.EffectType.Sub, 1097, 2, 1)
if disableStatus != nil {
target.AddEffect(source, disableStatus)
}
return true
}
if target.CurPet[0].Info.Hp <= 0 {
return true
}
success, _, _ := source.Player.Roll(50, 100)
if !success {
return true
}
furySkill := cloneSkillEntity(skill)
if furySkill == nil {
return true
}
if furySkill.Category() != info.Category.STATUS {
furySkill.XML.Power = halvePower(furySkill.XML.Power)
}
e.starFuryActive = true
executeExtraSkill(source, target, furySkill)
e.starFuryActive = false
return true
}
// Effect 1097 sub: 令对手攻击技能或属性技能失效
type Effect1097Sub struct {
node.EffectNode
armed bool
mode int
}
func (e *Effect1097Sub) SetArgs(t *input.Input, a ...int) {
e.EffectNode.SetArgs(t, a...)
if len(a) > 0 {
e.Duration(a[0])
}
if len(a) > 1 {
e.mode = a[1]
}
}
func (e *Effect1097Sub) ActionStart(a, b *action.SelectSkillAction) bool {
if e.Ctx().SkillEntity == nil {
return true
}
switch e.mode {
case 0:
if !e.armed || e.Ctx().SkillEntity.Category() == info.Category.STATUS {
return true
}
e.Ctx().SkillEntity.SetMiss()
case 1:
if e.Ctx().SkillEntity.Category() != info.Category.STATUS {
return true
}
e.Ctx().SkillEntity.SetNoSide()
}
return true
}
func (e *Effect1097Sub) TurnEnd() {
if e.mode == 0 && !e.armed {
e.armed = true
}
e.EffectNode.TurnEnd()
}
// Effect 1098: 致命一击率提升20%每次使用增加20%最高100%打出致命一击后令自身下2次技能触发的星皇之怒威力不再减少;
// 技能结束后对手体力值高于0则50%进行一次额外行动以触发星皇之怒
type Effect1098 struct {
node.EffectNode
critChance int
fullPowerFuryCount int
starFuryActive bool
}
func (e *Effect1098) SetArgs(t *input.Input, a ...int) {
e.EffectNode.SetArgs(t, a...)
if old := t.GetEffect(input.EffectType.Skill, 1098); old != nil {
if prev, ok := old.(*Effect1098); ok {
e.critChance = prev.critChance
e.fullPowerFuryCount = prev.fullPowerFuryCount
}
}
if e.critChance <= 0 {
e.critChance = 20
}
}
func (e *Effect1098) SkillHit() bool {
source := e.SourceInput()
if source == nil {
return true
}
if e.Ctx().SkillEntity == nil || e.Ctx().SkillEntity.Category() == info.Category.STATUS {
return true
}
success, _, _ := source.Player.Roll(e.critChance, 100)
if success {
e.Ctx().SkillEntity.XML.CritRate = 16
}
return true
}
func (e *Effect1098) Skill_Use() bool {
source := e.SourceInput()
target := e.TargetInput()
if source == nil || target == nil {
return true
}
skill := e.Ctx().SkillEntity
if skill == nil {
return true
}
if skill.Category() != info.Category.STATUS && skill.Crit != 0 {
e.fullPowerFuryCount = 2
}
if e.critChance < 100 {
e.critChance += 20
if e.critChance > 100 {
e.critChance = 100
}
}
if e.starFuryActive {
priorityEffect := source.InitEffect(input.EffectType.Sub, 1098, 2)
if priorityEffect != nil {
source.AddEffect(source, priorityEffect)
}
return true
}
if target.CurPet[0].Info.Hp <= 0 {
return true
}
success, _, _ := source.Player.Roll(50, 100)
if !success {
return true
}
furySkill := cloneSkillEntity(skill)
if furySkill == nil {
return true
}
if furySkill.Category() != info.Category.STATUS {
if e.fullPowerFuryCount > 0 {
e.fullPowerFuryCount--
} else {
furySkill.XML.Power = halvePower(furySkill.XML.Power)
}
}
e.starFuryActive = true
executeExtraSkill(source, target, furySkill)
e.starFuryActive = false
return true
}
// Effect 1098 sub: 下2次自身使用的攻击技能先制+2
type Effect1098Sub struct {
node.EffectNode
remaining int
}
func (e *Effect1098Sub) SetArgs(t *input.Input, a ...int) {
e.EffectNode.SetArgs(t, a...)
e.Duration(-1)
if len(a) > 0 {
e.remaining = a[0]
}
}
func (e *Effect1098Sub) ComparePre(fattack, sattack *action.SelectSkillAction) bool {
if e.remaining <= 0 {
e.Alive(false)
return true
}
source := e.SourceInput()
if source == nil {
return true
}
current := actionByPlayer(fattack, sattack, source.UserID)
if current == nil || current.SkillEntity == nil || current.SkillEntity.Category() == info.Category.STATUS {
return true
}
current.SkillEntity.XML.Priority += 2
e.remaining--
if e.remaining <= 0 {
e.Alive(false)
}
return true
}
// Effect 1099: 消除对手能力提升状态,消除成功则自身免疫下{0}次受到的异常状态
type Effect1099 struct {
node.EffectNode
}
func (e *Effect1099) Skill_Use() bool {
source := e.SourceInput()
target := e.TargetInput()
if source == nil || target == nil {
return true
}
cleared := false
for i, level := range target.Prop[:] {
if level <= 0 {
continue
}
if target.SetProp(source, int8(i), 0) {
cleared = true
}
}
if !cleared {
return true
}
immuneEffect := source.InitEffect(input.EffectType.Sub, 1099, int(e.Args()[0].IntPart()))
if immuneEffect != nil {
source.AddEffect(source, immuneEffect)
}
return true
}
// Effect 1099 sub: 免疫下N次异常状态
type Effect1099Sub struct {
node.EffectNode
remaining int
}
func (e *Effect1099Sub) SetArgs(t *input.Input, a ...int) {
e.EffectNode.SetArgs(t, a...)
e.Duration(-1)
if len(a) > 0 {
e.remaining = a[0]
}
}
func (e *Effect1099Sub) EFFect_Befer(in *input.Input, effEffect input.Effect) bool {
if e.remaining <= 0 {
e.Alive(false)
return true
}
if in != e.OpponentInput() || !input.IS_Stat(effEffect) {
return true
}
e.remaining--
if e.remaining <= 0 {
e.Alive(false)
}
return false
}
// Effect 1100: {0}回合内若对手使用属性技能则随机进入烧伤、冻伤、中毒、麻痹、害怕、睡眠中的一种异常状态,未触发则下{1}回合造成的伤害提高{2}%
type Effect1100 struct {
RoundEffectArg0Base
triggered bool
}
func (e *Effect1100) Skill_Use_ex() bool {
source := e.SourceInput()
target := e.TargetInput()
if source == nil || target == nil {
return true
}
if e.Ctx().SkillEntity == nil || e.Ctx().SkillEntity.Category() != info.Category.STATUS {
return true
}
e.triggered = true
statusEffect := source.InitEffect(input.EffectType.Status, randomStatus1100())
if statusEffect != nil {
target.AddEffect(source, statusEffect)
}
return true
}
func (e *Effect1100) TurnEnd() {
source := e.SourceInput()
if !e.triggered && e.Duration() == 1 {
if source == nil {
e.EffectNode.TurnEnd()
return
}
boostEffect := source.InitEffect(input.EffectType.Sub, 1100, int(e.Args()[1].IntPart()), int(e.Args()[2].IntPart()))
if boostEffect != nil {
source.AddEffect(source, boostEffect)
}
}
e.EffectNode.TurnEnd()
}
// Effect 1100 sub: 下M回合造成的伤害提高K%
type Effect1100Sub struct {
node.EffectNode
percent alpacadecimal.Decimal
}
func (e *Effect1100Sub) SetArgs(t *input.Input, a ...int) {
e.EffectNode.SetArgs(t, a...)
if len(a) > 0 {
e.Duration(a[0])
}
if len(a) > 1 {
e.percent = alpacadecimal.NewFromInt(int64(a[1]))
}
}
func (e *Effect1100Sub) Damage_Mul(zone *info.DamageZone) bool {
if zone == nil || zone.Type != info.DamageType.Red {
return true
}
zone.Damage = zone.Damage.Mul(hundred.Add(e.percent)).Div(hundred)
return true
}
// Effect 1101: 命中后{0}%秒杀对方若MISS则自身死亡使对手随机{1}个技能的PP值归零且全属性-{2}
type Effect1101 struct {
node.EffectNode
}
func (e *Effect1101) DamageFloor(zone *info.DamageZone) bool {
source := e.SourceInput()
target := e.OpponentInput()
if zone == nil || zone.Type != info.DamageType.Red {
return true
}
if e.Ctx().SkillEntity == nil || e.Ctx().SkillEntity.AttackTime == 0 {
return true
}
if source == nil {
return true
}
success, _, _ := source.Player.Roll(int(e.Args()[0].IntPart()), 100)
if !success {
return true
}
if target == nil {
return true
}
zone.Damage = target.CurPet[0].GetMaxHP()
return true
}
func (e *Effect1101) Skill_Use() bool {
source := e.SourceInput()
target := e.TargetInput()
if source == nil || target == nil {
return true
}
if e.Ctx().SkillEntity != nil && e.Ctx().SkillEntity.AttackTime == 0 {
source.CurPet[0].Info.Hp = 0
}
zeroRandomSkillPP(target, int(e.Args()[1].IntPart()))
applyAllPropDown(source, target, int8(e.Args()[2].IntPart()))
return true
}
func executeExtraSkill(attacker, defender *input.Input, skill *info.SkillEntity) {
if attacker == nil || defender == nil || skill == nil || attacker.CurPet[0].Info.Hp == 0 {
return
}
skill.XML.MustHit = 1
skill.AttackTimeC(attacker.Prop[5])
defender.ExecWithOpponent(attacker, func(effect input.Effect) bool {
effect.Ctx().SkillEntity = skill
effect.SkillHit_ex()
return true
})
attacker.ExecWithOpponent(defender, func(effect input.Effect) bool {
effect.Ctx().SkillEntity = skill
effect.SkillHit()
return true
})
var originalProps [2][6]int8
var originalPetInfo [2]model.PetInfo
originalProps[0], originalProps[1] = attacker.Prop, defender.Prop
originalPetInfo[0], originalPetInfo[1] = attacker.CurPet[0].Info, defender.CurPet[0].Info
attacker.ExecWithOpponent(defender, func(effect input.Effect) bool {
effect.Ctx().SkillEntity = skill
effect.CalculatePre()
return true
})
var sumDamage alpacadecimal.Decimal
if skill.AttackTime != 0 {
sumDamage = attacker.CalculatePower(defender, skill)
attacker.CalculateCrit(defender, skill)
attacker.IsCritical = skill.Crit
}
attacker.Prop, defender.Prop = originalProps[0], originalProps[1]
attacker.CurPet[0].Info, defender.CurPet[0].Info = originalPetInfo[0], originalPetInfo[1]
if attacker.IsCritical == 1 {
if skill.Category() == info.Category.PHYSICAL && defender.Prop[1] > 0 {
defender.Prop[1] = 0
} else if skill.Category() == info.Category.SPECIAL && defender.Prop[3] > 0 {
defender.Prop[3] = 0
}
sumDamage = sumDamage.Mul(alpacadecimal.NewFromInt(2))
}
attacker.ExecWithOpponent(defender, func(effect input.Effect) bool {
effect.Ctx().SkillEntity = skill
effect.OnSkill()
return true
})
defender.Damage(attacker, &info.DamageZone{
Type: info.DamageType.Red,
Damage: sumDamage,
})
if defender.CurPet[0].Info.Hp > 0 {
defender.ExecWithOpponent(attacker, func(effect input.Effect) bool {
effect.Ctx().SkillEntity = skill
effect.Skill_Use_ex()
return true
})
}
if attacker.CurPet[0].Info.Hp > 0 {
attacker.ExecWithOpponent(defender, func(effect input.Effect) bool {
effect.Ctx().SkillEntity = skill
effect.Skill_Use()
return true
})
}
defender.ExecWithOpponent(attacker, func(effect input.Effect) bool {
effect.Ctx().SkillEntity = skill
effect.Action_end_ex()
return true
})
attacker.ExecWithOpponent(defender, func(effect input.Effect) bool {
effect.Ctx().SkillEntity = skill
effect.Action_end()
return true
})
}
func halvePower(power int) int {
if power <= 1 {
return 1
}
power /= 2
if power <= 0 {
return 1
}
return power
}
func actionByPlayer(fattack, sattack *action.SelectSkillAction, playerID uint32) *action.SelectSkillAction {
if fattack != nil && fattack.PlayerID == playerID {
return fattack
}
if sattack != nil && sattack.PlayerID == playerID {
return sattack
}
return nil
}
func randomStatus1100() int {
statusTypes := []int{
int(info.PetStatus.Burned),
int(info.PetStatus.Frozen),
int(info.PetStatus.Poisoned),
int(info.PetStatus.Paralysis),
int(info.PetStatus.Fear),
int(info.PetStatus.Sleep),
}
return statusTypes[grand.Intn(len(statusTypes))]
}
func zeroRandomSkillPP(target *input.Input, count int) {
if target == nil || count <= 0 {
return
}
skills := target.CurPet[0].Info.SkillList
if len(skills) == 0 {
return
}
if count > len(skills) {
count = len(skills)
}
indexes := grand.Perm(len(skills))
for _, idx := range indexes[:count] {
target.CurPet[0].Info.SkillList[idx].PP = 0
}
}
func applyAllPropDown(owner, target *input.Input, level int8) {
if owner == nil || target == nil || level <= 0 {
return
}
for i := range target.Prop {
target.SetProp(owner, int8(i), -level)
}
}
func init() {
input.InitEffect(input.EffectType.Skill, 1097, &Effect1097{})
input.InitEffect(input.EffectType.Sub, 1097, &Effect1097Sub{})
input.InitEffect(input.EffectType.Skill, 1098, &Effect1098{})
input.InitEffect(input.EffectType.Sub, 1098, &Effect1098Sub{})
input.InitEffect(input.EffectType.Skill, 1099, &Effect1099{})
input.InitEffect(input.EffectType.Sub, 1099, &Effect1099Sub{})
input.InitEffect(input.EffectType.Skill, 1100, &Effect1100{})
input.InitEffect(input.EffectType.Sub, 1100, &Effect1100Sub{})
input.InitEffect(input.EffectType.Skill, 1101, &Effect1101{})
}