Files
bl/logic/service/fight/input/fight.go
昔念 55ff5c6119 ```
refactor(effect): 更新状态枚举类型为 EnumPetStatus

将多个技能效果文件中的 EnumBattleStatus 类型统一更新为 EnumPetStatus,
以更准确地反映其用途。同时修改了相关函数签名和变量声明。

此外,清理了部分注释格式,并补充了关于被动效果不能被免疫的说明。
```
2025-11-14 00:26:34 +08:00

475 lines
12 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 input
import (
element "blazing/common/data/Element"
"blazing/common/data/xmlres"
"blazing/common/utils"
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"fmt"
"math/rand"
"github.com/shopspring/decimal"
)
// 计算暴击
func (our *Input) CalculateCrit(opp *Input, skill *info.SkillEntity) {
skill.Crit = 0
if skill.Category() == info.Category.STATUS { //属性技能不用算暴击
return
}
CritRate := utils.Max(skill.CritRate, 1)
//CritAtkFirst: 先出手时必定致命一击; 默认: 0
if skill.CritAtkFirst != 0 && our.FightC.IsFirst(our.Player) {
CritRate = 16
}
//CritAtkSecond: 后出手时必定致命一击; 默认: 0
if skill.CritAtkSecond != 0 && !our.FightC.IsFirst(our.Player) {
CritRate = 16
}
// CritSelfHalfHp: 自身体力低于一半时必定致命一击; 默认: 0
if skill.CritSelfHalfHp != 0 && (our.CurrentPet.HP < int(our.CurrentPet.Info.MaxHp)/2) {
CritRate = 16
}
// CritFoeHalfHp: 对方体力低于一半时必定致命一击; 默认: 0
if skill.CritSelfHalfHp != 0 && (opp.CurrentPet.HP < int(opp.CurrentPet.Info.MaxHp)/2) {
CritRate = 16
}
//todo 暴击伤害
if t, _, _ := our.Player.Roll(625*CritRate, 10000); t {
skill.Crit = 1
}
}
// 恢复血量
func (our *Input) Heal(in *Input, ac action.BattleActionI, value decimal.Decimal) {
//使用道具回血
if _, ok := ac.(*action.UseItemAction); !ok &&
ac != nil &&
in == our {
our.AttackValue.GainHp = int32(value.IntPart()) //道具有专门的回血包
}
if value.IsPositive() {
our.CurrentPet.Info.Hp += uint32(value.IntPart())
our.CurrentPet.Info.Hp = utils.Min(our.CurrentPet.Info.Hp, our.CurrentPet.Info.MaxHp)
} else {
if uint32(value.Abs().IntPart()) > our.CurrentPet.Info.Hp {
our.CurrentPet.Info.Hp = 0
} else {
our.CurrentPet.Info.Hp += uint32(value.IntPart())
}
}
}
func (our *Input) HealPP(value int) {
for i := 0; i < len(our.CurrentPet.Info.SkillList); i++ {
our.CurrentPet.Info.SkillList[i].PP += uint32(value)
our.CurrentPet.Info.SkillList[i].PP = utils.Min(our.CurrentPet.Info.SkillList[i].PP, uint32(xmlres.SkillMap[int(our.CurrentPet.Info.SkillList[i].ID)].MaxPP))
}
}
func (our *Input) DelPP(value int) {
for i := 0; i < len(our.CurrentPet.Info.SkillList); i++ {
if uint32(value) > our.CurrentPet.Info.SkillList[i].PP {
our.CurrentPet.Info.SkillList[i].PP = 0
} else {
our.CurrentPet.Info.SkillList[i].PP -= uint32(value)
}
}
}
// /红伤只允许调用一次来保持锁伤
// 这个方法是对对方造成伤害
// 伤害落实 // 血量扣减节点比如触发回神,反弹也在这里实现
func (our *Input) Damage(in *Input, sub *info.DamageZone) {
if sub.Type == info.DamageType.Red { //每回合计算伤害的时候重置伤害
our.Opp.DamageZone.Damage = sub.Damage
}
// 对方对我方造成,需要吃到对方的加成
var ok bool
if our != in {
ok = our.Opp.Exec(func(t Effect) bool {
t.Damage_ADD(sub) //红伤落实前,我方增伤
return true
})
//sub.BeforeMul = sub.Damage
if ok {
ok = our.Opp.Exec(func(t Effect) bool {
t.Damage_Mul(sub) //红伤落实前,我方增伤
return true
})
}
//sub.BeforeFloor = sub.Damage
if ok {
ok = our.Opp.Exec(func(t Effect) bool {
t.Damage_Floor(sub) //红伤落实,内部有befer
return true
})
}
}
// sub.BeforeMul = sub.Damage
if ok {
ok = our.Exec(func(t Effect) bool {
t.Damage_DIV_ex(sub) //红伤落实,内部有befer
return true
})
}
//sub.BeforeSUB = sub.Damage
if ok {
ok = our.Exec(func(t Effect) bool {
t.Damage_SUB_ex(sub)
return true
})
}
// sub.BeforeLock = sub.Damage
if ok && in != our {
ok = our.Opp.Exec(func(t Effect) bool {
t.Damage_Lock(sub)
return true
})
}
//sub.BeforeLocked = sub.Damage
if ok {
our.Exec(func(t Effect) bool {
t.Damage_Lock_ex(sub)
return true
})
}
if sub.Type == info.DamageType.Red { //红才会产生造成伤害
our.Opp.DamageZone.Damage = sub.Damage // 叠加总伤害 这里相当于记录红伤
our.Opp.AttackValue.LostHp = uint32(our.Opp.DamageZone.Damage.IntPart()) //红伤落实
}
if uint32(sub.Damage.IntPart()) > our.CurrentPet.Info.Hp {
our.CurrentPet.Info.Hp = 0
} else {
our.CurrentPet.Info.Hp = our.CurrentPet.Info.Hp - uint32(sub.Damage.IntPart())
}
//todo 待实现死亡effet
}
// 攻击,防御,特供,特防,速度,命中
// 施加方,类型,等级,操作类别,是否成功
func (our *Input) SetProp(in *Input, prop, level int8, ptype info.EnumAbilityOpType) (ret bool) {
//in.Our = our //设置属性的角色是我方
canuseskill := our.Exec(func(t Effect) bool { //这个是能否使用技能
//结算状态
return t.Prop_Befer(in, prop, level, ptype) //返回本身结算,如果false,说明不能使用技能了
})
if !canuseskill {
return false
}
var newValue int8
abfunc := func(prop, level int8, ptype info.EnumAbilityOpType) (ret bool) {
switch ptype {
case info.AbilityOpType.ADD:
newValue = utils.Min(our.AttackValue.Prop[prop]+int8(level), 6)
if newValue > our.AttackValue.Prop[prop] {
fmt.Println("属性值会增加")
return true
} else {
fmt.Println("属性值不会增加")
return false
}
case info.AbilityOpType.SUB:
newValue = utils.Max(our.AttackValue.Prop[prop]+int8(level), -6)
if newValue < our.AttackValue.Prop[prop] {
fmt.Println("属性值会减少")
return true
} else {
fmt.Println("属性值不会增加")
return false
}
case info.AbilityOpType.RESET:
if level > 0 && our.AttackValue.Prop[prop] > 0 { //消强
newValue = 0
return true
}
if level < 0 && our.AttackValue.Prop[prop] < 0 { //解弱
newValue = 0
return true
}
}
return false
}
switch ptype {
case info.AbilityOpType.AbilityOpStealStrengthen:
temp := our.Opp.AttackValue.Prop[prop]
if temp <= 0 { //对方没有强化
return false
}
if abfunc(prop, temp, info.AbilityOpType.ADD) { //把对面的强化等级添加自身
our.AttackValue.Prop[prop] = newValue //成功把 强化更新
our.Opp.SetProp(our, prop, 1, info.AbilityOpType.RESET) //吸取后消除对面强化
}
case info.AbilityOpType.AbilityOpReverse:
temp := our.AttackValue.Prop[prop]
switch {
case level > 0: //反转强化
if temp <= 0 { //没有强化
return false
}
if abfunc(prop, temp*2, info.AbilityOpType.SUB) {
our.AttackValue.Prop[prop] = newValue
if temp == -our.AttackValue.Prop[prop] { //成功到对应弱化
return true
} else {
return true
}
} else { //自身免弱或已到-6
return false
}
default: //反转弱化
if temp >= 0 { //没有弱化
return false
}
if abfunc(prop, -temp*2, info.AbilityOpType.ADD) {
our.AttackValue.Prop[prop] = newValue
if temp == -our.AttackValue.Prop[prop] { //成功到对应强化
return true
} else {
return true
}
} else { //自身免弱或已到-6
return false
}
}
case info.AbilityOpType.AbilityOpBounceWeaken:
temp := our.AttackValue.Prop[prop]
if temp >= 0 { //没有弱化
return false
}
if our.Opp.SetProp(our, prop, temp, info.AbilityOpType.SUB) {
our.SetProp(our, prop, -1, info.AbilityOpType.RESET) //消除自身弱化
return true
}
default: //增加减少重置
if abfunc(prop, level, ptype) {
// 执行赋值
our.AttackValue.Prop[prop] = newValue
return true
}
}
return false
}
func (our *Input) GetAction(opp *Input) {
// 获取己方当前宠物和对方当前宠物
selfPet := our.FightC.GetCurrPET(our.Player)
//没血就切换精灵
if selfPet.Info.Hp <= 0 {
for _, v := range our.AllPet {
if v.Info.Hp > 0 {
our.FightC.ChangePet(our.Player, v.Info.CatchTime)
return
}
}
}
//oppPet := opp.FightC.GetCurrPET(opp.Player)
skills := selfPet.Skills
// 空技能列表直接返回,避免错误
if len(skills) == 0 {
return
}
// 步骤1计算所有技能的伤害并筛选出能秒杀对方的技能
var killableSkills []struct {
*info.SkillEntity // 技能对象假设原技能类型为skill
damage decimal.Decimal // 技能实际伤害
}
// 存储所有技能及伤害(用于后续筛选)
type skillWithDamage struct {
*info.SkillEntity
damage decimal.Decimal
}
allSkills := make([]skillWithDamage, 0, len(skills))
for _, s := range skills {
if s == nil {
continue
}
// 计算技能对对方的伤害假设CalculatePower返回伤害值或需从技能中获取
damage := our.CalculatePower(opp, s)
if !s.CanUse() {
continue
}
allSkills = append(allSkills, skillWithDamage{SkillEntity: s, damage: damage})
// 判断是否能秒杀(伤害 >= 对方当前生命值)
if uint32(damage.IntPart()) >= opp.CurrentPet.Info.Hp { // 假设oppPet.HP为对方当前剩余生命值
killableSkills = append(killableSkills, struct {
*info.SkillEntity
damage decimal.Decimal
}{s, damage})
}
}
// 若存在能秒杀的技能,优先使用(选权重最高的,避免浪费高伤害技能)
if len(killableSkills) > 0 {
bestKillSkill := killableSkills[0].SkillEntity
// maxWeight := killableSkills[0].SkillEntity.Weight // 假设技能有Weight字段表示权重
// for _, ks := range killableSkills[1:] {
// if ks.skill.Weight > maxWeight {
// maxWeight = ks.skill.Weight
// bestKillSkill = ks.skill
// }
// }
our.FightC.UseSkill(our.Player, int32(bestKillSkill.ID))
return
}
randomIdx := rand.Intn(len(allSkills))
chosenSkill := skills[randomIdx]
our.FightC.UseSkill(our.Player, int32(chosenSkill.ID))
// i.FightC.UseSkill(i.Player, int32(bestSkill.skill.ID))
}
// 计算技能威力
func (our *Input) CalculatePower(deftype *Input, skill *info.SkillEntity) decimal.Decimal {
// 1. 计算等级因子 (level * 0.4 + 2)
levelFactor := decimal.NewFromInt(int64(our.CurrentPet.Info.Level)).
Mul(decimal.NewFromFloat(0.4)).Add(decimal.NewFromInt(2))
var (
attackDec decimal.Decimal //攻击值
defenseDec decimal.Decimal //防御值
)
switch skill.Category() { //判断技能类型
case info.Category.PHYSICAL:
attackDec = decimal.NewFromInt(int64(our.GetProp(0, false)))
defenseDec = decimal.NewFromInt(int64(deftype.GetProp(1, false)))
case info.Category.SPECIAL:
attackDec = decimal.NewFromInt(int64(our.GetProp(2, false)))
defenseDec = decimal.NewFromInt(int64(deftype.GetProp(3, false)))
default:
return decimal.NewFromInt(0)
}
// 5. 基础伤害公式:等级因子 * 威力因子 * 攻击 / 防御 / 50 + 2
baseDamage := levelFactor.
Mul(decimal.NewFromInt(int64(skill.Power))).
Mul(attackDec).
Div(defenseDec).
Div(decimal.NewFromInt(50)).
Add(decimal.NewFromInt(2))
var typeRate decimal.Decimal
//fmt.Println(skill.Type().ID, deftype.CurrentPet.Type().ID)
t, _ := element.Calculator.GetOffensiveMultiplier(skill.Type().ID, deftype.CurrentPet.Type().ID)
typeRate = decimal.NewFromFloat(t)
// 8. DmgBindLv: 使对方受到的伤害值等于等级; 默认: 0
// 9. PwrBindDv: 1,威力power取决于潜力个体值*5; 2,威力power取决于最大体力*1/3+潜力(个体值); 默认: 0
// 10. PwrDouble: 攻击时,若对方处于异常状态, 则威力翻倍;
// 11. DmgBindHpDv: 造成的伤害等于自身剩余体力*1/2+潜力(个体值); 默认: 0
if skill.DmgBindLv != 0 {
baseDamage = decimal.NewFromInt(int64(deftype.CurrentPet.Info.Level))
}
if skill.PwrBindDv != 0 {
if skill.PwrBindDv == 1 {
baseDamage = decimal.NewFromInt(int64(our.CurrentPet.Info.Dv * 5))
}
if skill.PwrBindDv == 2 {
baseDamage = decimal.NewFromInt(int64(our.CurrentPet.Info.Hp/3 + our.CurrentPet.Info.Dv))
}
}
if skill.PwrDouble != 0 {
if deftype.StatEffect_Exist_all() {
baseDamage = baseDamage.Mul(decimal.NewFromInt(2))
}
}
if skill.DmgBindHpDv != 0 {
baseDamage = decimal.NewFromInt(int64(our.CurrentPet.Info.Hp/2 + our.CurrentPet.Info.Dv))
}
damage := baseDamage.
Mul(skill.CriticalsameTypeBonus()). // 同属性加成
Mul(typeRate). // 克制系数
Mul(skill.Criticalrandom()) //随机波动
return damage
}