refactor(fight): 重构暴击判断逻辑并优化伤害计算,添加泛型Max函数到utils包
This commit is contained in:
@@ -20,3 +20,18 @@ func ToSliceMap[T any, K comparable](slice []T, keyFunc func(T) K) map[K][]T {
|
|||||||
}
|
}
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 定义泛型约束:只允许数值类型(整数、浮点数等)
|
||||||
|
type Number interface {
|
||||||
|
int | int8 | int16 | int32 | int64 |
|
||||||
|
uint | uint8 | uint16 | uint32 | uint64 |
|
||||||
|
float32 | float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Max 泛型函数:接收两个同类型的 Number 参数,返回最大值
|
||||||
|
func Max[T Number](a, b T) T {
|
||||||
|
if a > b {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ type EffectNode struct {
|
|||||||
Success bool // 是否执行成功 成功XXX,失败XXX
|
Success bool // 是否执行成功 成功XXX,失败XXX
|
||||||
arget bool // 传出作用对象,默认0是自身,1是作用于对面
|
arget bool // 传出作用对象,默认0是自身,1是作用于对面
|
||||||
Flag int //过滤掉的战斗类型 pvp pve boss战斗,野怪全部生效
|
Flag int //过滤掉的战斗类型 pvp pve boss战斗,野怪全部生效
|
||||||
|
Alive bool // 是否失效 effect返回值是否被取消,是否被删除
|
||||||
//增加owner target,如果owner target都为自身,就回合效果结束后再使用回合效果
|
//增加owner target,如果owner target都为自身,就回合效果结束后再使用回合效果
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package info
|
|||||||
import (
|
import (
|
||||||
element "blazing/common/data/Element"
|
element "blazing/common/data/Element"
|
||||||
"blazing/common/data/xmlres"
|
"blazing/common/data/xmlres"
|
||||||
|
"blazing/common/utils"
|
||||||
"blazing/modules/blazing/model"
|
"blazing/modules/blazing/model"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@ type BattleSkillEntity struct {
|
|||||||
DamageValue decimal.Decimal // 伤害值
|
DamageValue decimal.Decimal // 伤害值
|
||||||
Rand *rand.Rand
|
Rand *rand.Rand
|
||||||
Pet *BattlePetEntity
|
Pet *BattlePetEntity
|
||||||
|
First bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateBattleSkillWithInfinity 创建战斗技能实例(可指定是否无限PP)
|
// CreateBattleSkillWithInfinity 创建战斗技能实例(可指定是否无限PP)
|
||||||
@@ -161,12 +163,7 @@ var DamageC = enum.New[struct {
|
|||||||
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// 暴击伤害 返回暴击率和是否暴击
|
|
||||||
func (s *BattleSkillEntity) IsCritical() (decimal.Decimal, bool) {
|
|
||||||
|
|
||||||
return decimal.NewFromFloat(1), true
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算是否命中
|
// 计算是否命中
|
||||||
func (s *BattleSkillEntity) AttackTime() uint32 {
|
func (s *BattleSkillEntity) AttackTime() uint32 {
|
||||||
@@ -204,7 +201,7 @@ func (s *BattleSkillEntity) criticalrandom() decimal.Decimal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 计算技能威力
|
// 计算技能威力
|
||||||
func (s *BattleSkillEntity) CalculatePower(deftype int) uint32 {
|
func (s *BattleSkillEntity) CalculatePower(deftype *BattlePetEntity) uint32 {
|
||||||
|
|
||||||
// 1. 计算等级因子 (level * 0.4 + 2)
|
// 1. 计算等级因子 (level * 0.4 + 2)
|
||||||
levelFactor := decimal.NewFromInt(int64(s.Pet.Info.Level)).
|
levelFactor := decimal.NewFromInt(int64(s.Pet.Info.Level)).
|
||||||
@@ -255,7 +252,7 @@ func (s *BattleSkillEntity) CalculatePower(deftype int) uint32 {
|
|||||||
Div(decimal.NewFromInt(50)).
|
Div(decimal.NewFromInt(50)).
|
||||||
Add(decimal.NewFromInt(2))
|
Add(decimal.NewFromInt(2))
|
||||||
|
|
||||||
t, _ := element.NewElementCalculator().GetOffensiveMultiplier(s.Type().ID, deftype)
|
t, _ := element.NewElementCalculator().GetOffensiveMultiplier(s.Type().ID, deftype.Type().ID)
|
||||||
|
|
||||||
typeRate := decimal.NewFromFloat(t)
|
typeRate := decimal.NewFromFloat(t)
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"blazing/common/data/xmlres"
|
"blazing/common/data/xmlres"
|
||||||
|
"blazing/common/utils"
|
||||||
"blazing/logic/service/fight/info"
|
"blazing/logic/service/fight/info"
|
||||||
"blazing/modules/blazing/model"
|
"blazing/modules/blazing/model"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -13,6 +14,7 @@ import (
|
|||||||
"github.com/jinzhu/copier"
|
"github.com/jinzhu/copier"
|
||||||
"github.com/mohae/deepcopy"
|
"github.com/mohae/deepcopy"
|
||||||
"github.com/panjf2000/ants/v2"
|
"github.com/panjf2000/ants/v2"
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PlayerI interface {
|
type PlayerI interface {
|
||||||
@@ -415,20 +417,8 @@ func (f *FightC) newBPET(input *Input) *BPET {
|
|||||||
AttackValue: info.NewAttackValue(input.Player.ID()),
|
AttackValue: info.NewAttackValue(input.Player.ID()),
|
||||||
Damage: 0,
|
Damage: 0,
|
||||||
}
|
}
|
||||||
} // 定义泛型约束:只允许数值类型(整数、浮点数等)
|
|
||||||
type Number interface {
|
|
||||||
int | int8 | int16 | int32 | int64 |
|
|
||||||
uint | uint8 | uint16 | uint32 | uint64 |
|
|
||||||
float32 | float64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Max 泛型函数:接收两个同类型的 Number 参数,返回最大值
|
|
||||||
func Max[T Number](a, b T) T {
|
|
||||||
if a > b {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
func (f *FightC) initAttackers(fattack, sattack info.BattleActionI) {
|
func (f *FightC) initAttackers(fattack, sattack info.BattleActionI) {
|
||||||
// 伤害值
|
// 伤害值
|
||||||
|
|
||||||
@@ -454,19 +444,39 @@ func (f *FightC) initAttackers(fattack, sattack info.BattleActionI) {
|
|||||||
// 处理技能攻击逻辑
|
// 处理技能攻击逻辑
|
||||||
func (f *FightC) processSkillAttack(attacker, defender *BPET, skill *info.SelectSkillAction) {
|
func (f *FightC) processSkillAttack(attacker, defender *BPET, skill *info.SelectSkillAction) {
|
||||||
f.parseskill(skill)
|
f.parseskill(skill)
|
||||||
spower := skill.Skill.CalculatePower(defender.Type().ID)
|
spower := skill.Skill.CalculatePower(defender.BattlePetEntity)
|
||||||
attacker.Damage = spower
|
attacker.Damage = spower
|
||||||
|
|
||||||
// 记录技能信息
|
// 记录技能信息
|
||||||
attacker.AttackValue.SkillID = uint32(skill.Skill.ID)
|
attacker.AttackValue.SkillID = uint32(skill.Skill.ID)
|
||||||
attacker.AttackValue.AttackTime = skill.Skill.AttackTime()
|
attacker.AttackValue.AttackTime = skill.Skill.AttackTime()
|
||||||
// 判断是否暴击
|
|
||||||
if _, ok := skill.Skill.IsCritical(); ok {
|
CritRate := utils.Max(skill.Skill.CritRate, 1)
|
||||||
|
CritRateR := f.rand.Int31n(16)
|
||||||
|
//CritAtkFirst: 先出手时必定致命一击; 默认: 0
|
||||||
|
if skill.Skill.CritAtkFirst != 0 && attacker == f.First {
|
||||||
|
CritRate = 16
|
||||||
|
}
|
||||||
|
//CritAtkSecond: 后出手时必定致命一击; 默认: 0
|
||||||
|
if skill.Skill.CritAtkSecond != 0 && attacker != f.First {
|
||||||
|
CritRate=16
|
||||||
|
}
|
||||||
|
// CritSelfHalfHp: 自身体力低于一半时必定致命一击; 默认: 0
|
||||||
|
if skill.Skill.CritSelfHalfHp != 0 && (attacker.CurrentPet.HP < int(attacker.CurrentPet.Info.MaxHp)/2) {
|
||||||
|
CritRate=16
|
||||||
|
}
|
||||||
|
// CritFoeHalfHp: 对方体力低于一半时必定致命一击; 默认: 0
|
||||||
|
if skill.Skill.CritSelfHalfHp != 0 && (defender.CurrentPet.HP < int(defender.CurrentPet.Info.MaxHp)/2) {
|
||||||
|
CritRate=16
|
||||||
|
}
|
||||||
|
|
||||||
|
//todo 暴击伤害
|
||||||
|
if CritRateR <= int32(CritRate) {
|
||||||
attacker.AttackValue.IsCritical = 1
|
attacker.AttackValue.IsCritical = 1
|
||||||
}
|
}
|
||||||
defender.CurrentPet.Info.Hp -= attacker.Damage
|
defender.CurrentPet.Info.Hp -= attacker.Damage
|
||||||
|
|
||||||
defender.CurrentPet.Info.Hp = Max((defender.CurrentPet.Info.Hp), 0)
|
defender.CurrentPet.Info.Hp = utils.Max((defender.CurrentPet.Info.Hp), 0)
|
||||||
// 扣减防御方血量
|
// 扣减防御方血量
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user