599 lines
14 KiB
Go
599 lines
14 KiB
Go
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{})
|
||
}
|