Files
bl/logic/service/fight/info/BattleSkillEntity.go

242 lines
6.0 KiB
Go
Raw Normal View History

package info
import (
element "blazing/common/data/Element"
"blazing/common/data/xmlres"
"blazing/modules/blazing/model"
"math/rand"
"context"
"fmt"
"strconv"
"github.com/gogf/gf/v2/os/glog"
"github.com/shopspring/decimal"
"github.com/tnnmigga/enum"
)
const BattleSkillEntityCtx = "skill"
// EnumSkillType 技能类型枚举基础类型
type EnumCategory int
// SkillType 技能类型枚举实例使用enum包创建
// 与原Java枚举保持相同的数值映射PHYSICAL=1, SPECIAL=2, STATUS=4
var Category = enum.New[struct {
PHYSICAL EnumCategory `enum:"1"` // 物理攻击
SPECIAL EnumCategory `enum:"2"` // 特殊攻击
STATUS EnumCategory `enum:"4"` // 状态技能
Fixed EnumCategory // 固定伤害
Percent EnumCategory // 百分比伤害
True EnumCategory // 真伤
2025-09-07 05:58:47 +08:00
ALL EnumCategory //任何类型
}]()
// SkillEntity 战斗技能实体
// 实现了战斗中技能的所有属性和行为包括PP管理、技能使用、属性获取等
// 战斗中可以修改技能实体值,比如是否暴击,是否必中等
type SkillEntity struct {
xmlres.Move
Info *model.SkillInfo
DamageValue decimal.Decimal // 伤害值
2025-09-07 05:58:47 +08:00
Rand *rand.Rand
Pet *BattlePetEntity
//MaxValue func(ahp, bhp uint32) decimal.Decimal
Crit uint32
AttackTime uint32
}
// CreateSkill 创建战斗技能实例可指定是否无限PP
func CreateSkill(skill *model.SkillInfo, rand *rand.Rand, pet *BattlePetEntity) *SkillEntity {
//如果PP是-1 ,那就是无限PP
// ID小于10001的视为无效技能
if skill.ID < 10001 {
return nil
}
2025-09-07 05:58:47 +08:00
var ret SkillEntity
2025-09-07 05:58:47 +08:00
ret.Rand = rand
ret.Pet = pet
// 从资源仓库获取技能数据
move, ok := xmlres.SkillMap[int(skill.ID)]
if !ok {
glog.Error(context.Background(), "技能ID无效", "id", skill.ID)
}
ret.Move = move
// // 解析副作用参数
// sideEffectArgs := parseSideEffectArgs(move.SideEffectArg)
// tt := strings.Split(move.SideEffect, " ")
// rf, err := strSliceToIntSlice(tt)
// if err == nil {
// ret.SideEffects = rf
// }
ret.Info = skill
// ret.SideEffectArgs = sideEffectArgs
return &ret
}
// 将字符串切片转换为整数切片
func strSliceToIntSlice(strs []string) ([]int, error) {
intSlice := make([]int, 0, len(strs)) // 预分配容量,提高性能
for _, s := range strs {
// 将字符串转换为整数
num, err := strconv.Atoi(s)
if err != nil {
// 转换失败时返回错误(包含具体的错误信息和失败的字符串)
return nil, fmt.Errorf("无法将字符串 '%s' 转换为整数: %v", s, err)
}
intSlice = append(intSlice, num)
}
return intSlice, nil
}
// CanUse 检查技能是否可以使用PP是否充足
func (s *SkillEntity) CanUse() bool {
return s.Info.PP > 0
}
// 获取技能类型
func (s *SkillEntity) Category() EnumCategory {
return EnumCategory(s.Move.Category)
}
// 获取技能属性
func (s *SkillEntity) Type() *element.ElementCombination {
2025-09-07 05:58:47 +08:00
ret, _ := element.NewElementCombination(s.Move.Type)
return ret
}
// // 技能产生effect
// func (u *BattleSkillEntity) NewEffect(ctx context.Context)*node.EffectNode {
// ret := node.EffectNode{}
// ctx = context.WithValue(ctx, BattleSkillEntityCtx, &ret) //添加用户到上下文
// ret.ctx = ctx
// }
// 解析副作用参数字符串为整数列表
// 获取技能名称为空时使用ID
func getSkillName(move *SkillEntity) string {
if move.Name == "" {
return strconv.FormatInt(int64(move.ID), 10)
}
return move.Name
}
// 获取副作用列表,处理空值情况
// func getSideEffects(move *BattleSkillEntity) []int {
// if move.SideEffect == "" {
// return []int{}
// }
// return move.SideEffects
// }
type EnumsZoneType int
var DamageZone = enum.New[struct {
add EnumsZoneType // 加区
nul EnumsZoneType // 乘区
}]()
var DamageC = enum.New[struct {
boost EnumsZoneType //增伤区
reduction EnumsZoneType // 减伤区
}]()
// func (s *BattleSkillEntity) Random() *random.RandomXS128 {
// battle, _ := s.ctx.Value(BattleContainerCtx).(*Battle1V1)
// return battle.Rand
// }
// func (s *BattleSkillEntity) Pet() (*BattlePetEntity, bool) {
// pet, ok := s.ctx.Value(Pet_O_Ctx).(*BattlePetEntity)
// return pet, ok
// }
2025-09-07 05:58:47 +08:00
// 计算是否命中
func (s *SkillEntity) AttackTimeC(level int) {
s.AttackTime = 0 //先重置上一次的
if s.MustHit != 0 {
s.AttackTime = 2
}
if int64(s.GetAccuracy(level)) > s.Rand.Int63n(100) {
s.AttackTime = 1
2025-09-07 05:58:47 +08:00
}
2025-09-07 05:58:47 +08:00
}
func (s *SkillEntity) CriticalsameTypeBonus() decimal.Decimal {
2025-09-07 05:58:47 +08:00
// 6. 同系加成属性相同则乘以同系加成倍率否则1
sameTypeBonus := decimal.NewFromFloat(1.0)
if s.Type() == s.Pet.Type() { //使用本系
sameTypeBonus = decimal.NewFromFloat(1.5)
}
2025-09-07 05:58:47 +08:00
stype := s.Type()
ptype := s.Pet.Type()
2025-09-07 05:58:47 +08:00
if stype.Secondary == nil && ptype.Secondary != nil && (stype.Primary == ptype.Primary || stype.Primary == *ptype.Secondary) { //判断技能属性是否是精灵双属性之一
sameTypeBonus = decimal.NewFromFloat(1.5)
}
return sameTypeBonus
}
func (s *SkillEntity) Criticalrandom() decimal.Decimal {
2025-09-07 05:58:47 +08:00
randomnum := s.Rand.Int31n(39) + 217
// 10. 随机倍率随机值除以255
randomFactor := decimal.NewFromInt(int64(randomnum)).Div(decimal.NewFromInt(255))
return randomFactor
2025-09-07 05:58:47 +08:00
}
// Accuracy 优化版命中率计算(用绝对值和正负判断处理等级)
func (a *SkillEntity) GetAccuracy(level int) uint32 {
// 基础参数校验
if a.Accuracy == 0 {
return 0
}
if a.Accuracy >= 100 {
return 100
}
if level > 6 || level == 0 { //强化等级
return uint32(CalculateRealValue((a.Accuracy), level))
}
var temp float64
switch level {
case -1:
temp = 0.85
case -2:
temp = 0.7
case -3:
temp = 0.55
case -4:
temp = 0.45
case -5:
temp = 0.35
case -6:
temp = 0.25
}
return uint32(
decimal.NewFromInt(int64(a.Accuracy)). // 将b转为decimal类型
Mul(decimal.NewFromFloat(temp)). // 精确乘以0.85
Round(0). // 四舍五入到整数
IntPart(), // 转为int64
)
}