369 lines
11 KiB
Go
369 lines
11 KiB
Go
package info
|
||
|
||
import (
|
||
element "blazing/common/data/Element"
|
||
"blazing/common/data/xml/skill"
|
||
"blazing/common/utils/random"
|
||
|
||
"context"
|
||
"fmt"
|
||
"strconv"
|
||
"strings"
|
||
|
||
"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 // 真伤
|
||
}]()
|
||
|
||
// BattleSkillEntity 战斗技能实体
|
||
// 实现了战斗中技能的所有属性和行为,包括PP管理、技能使用、属性获取等
|
||
// 战斗中可以修改技能实体值,比如是否暴击,是否必中等
|
||
type BattleSkillEntity struct {
|
||
skill.Move
|
||
ctx context.Context
|
||
SideEffects []int
|
||
SideEffectArgs []int
|
||
PP int
|
||
InfinityPP bool
|
||
DamageZone map[EnumCategory]map[EnumsZoneType]map[EnumsZoneType][]float64 // 三维map 伤害类型-》增还是减-》加还是乘-》值
|
||
isCritical bool //技能是否暴击
|
||
ATTACK_COUNT_ZONE int //攻击次数
|
||
DamageValue decimal.Decimal // 伤害值
|
||
|
||
// 技能类型属性
|
||
//SkillType EnumCategory // 技能类型(物理/特殊/状态)
|
||
|
||
}
|
||
|
||
// CreateBattleSkillWithInfinity 创建战斗技能实例(可指定是否无限PP)
|
||
func CreateBattleSkillWithInfinity(id int, pp int) *BattleSkillEntity {
|
||
//如果PP是-1 ,那就是无限PP
|
||
// ID小于10001的视为无效技能
|
||
if id < 10001 {
|
||
return nil
|
||
}
|
||
|
||
// 从资源仓库获取技能数据
|
||
move, ok := skill.MovesConfig.Moves[id]
|
||
if !ok {
|
||
glog.Error(context.Background(), "技能ID无效", "id", id)
|
||
}
|
||
var ret BattleSkillEntity
|
||
// 解析副作用参数
|
||
sideEffectArgs := parseSideEffectArgs(move.SideEffectArg)
|
||
tt := strings.Split(move.SideEffect, " ")
|
||
rf, err := strSliceToIntSlice(tt)
|
||
if err == nil {
|
||
ret.SideEffects = rf
|
||
}
|
||
|
||
ret.SideEffectArgs = sideEffectArgs
|
||
ret.DamageZone = make(map[EnumCategory]map[EnumsZoneType]map[EnumsZoneType][]float64) //初始化第一层类型
|
||
|
||
for _, v := range enum.Values[EnumCategory](Category) {
|
||
ret.DamageZone[v] = make(map[EnumsZoneType]map[EnumsZoneType][]float64) //初始化第二层是否是加还是减
|
||
for _, t := range enum.Values[EnumsZoneType](DamageC) {
|
||
ret.DamageZone[v][t] = make(map[EnumsZoneType][]float64) //初始化第三层时乘还是加
|
||
for _, s := range enum.Values[EnumsZoneType](DamageC) {
|
||
ret.DamageZone[v][t][s] = make([]float64, 0) //初始化第四层 数组
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
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 *BattleSkillEntity) CanUse() bool {
|
||
return s.PP > 0
|
||
}
|
||
|
||
// 获取技能类型
|
||
func (s *BattleSkillEntity) Category() EnumCategory {
|
||
return EnumCategory(s.Move.Category)
|
||
}
|
||
|
||
// 获取技能属性
|
||
func (s *BattleSkillEntity) Type() element.ElementType {
|
||
return element.ElementType(s.Move.Type)
|
||
}
|
||
|
||
// 技能产生动作
|
||
func (u *BattleSkillEntity) NewBattleAction(ctx context.Context) {
|
||
|
||
ret := BattleAction{}
|
||
ctx = context.WithValue(ctx, BattleSkillEntityCtx, &ret) //添加用户到上下文
|
||
ret.ctx = ctx
|
||
|
||
}
|
||
|
||
// // 技能产生effect
|
||
// func (u *BattleSkillEntity) NewEffect(ctx context.Context)*node.EffectNode {
|
||
|
||
// ret := node.EffectNode{}
|
||
// ctx = context.WithValue(ctx, BattleSkillEntityCtx, &ret) //添加用户到上下文
|
||
// ret.ctx = ctx
|
||
|
||
// }
|
||
// 解析副作用参数字符串为整数列表
|
||
func parseSideEffectArgs(argsStr string) []int {
|
||
if argsStr == "" {
|
||
return []int{}
|
||
}
|
||
|
||
parts := strings.Fields(argsStr)
|
||
args := make([]int, 0, len(parts))
|
||
|
||
for _, part := range parts {
|
||
if num, err := strconv.Atoi(part); err == nil {
|
||
args = append(args, num)
|
||
}
|
||
}
|
||
|
||
return args
|
||
}
|
||
|
||
// 获取技能名称,为空时使用ID
|
||
func getSkillName(move *BattleSkillEntity) 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).(*BattleContainer1V1)
|
||
|
||
return battle.Rand
|
||
|
||
}
|
||
|
||
// 获得指定的+-区
|
||
func (s *BattleSkillEntity) GetAddValue(e EnumCategory, c EnumsZoneType) decimal.Decimal {
|
||
|
||
t, ok := s.DamageZone[e][c][DamageZone.add]
|
||
if ok {
|
||
var ttt decimal.Decimal
|
||
|
||
for _, v := range t {
|
||
t1 := decimal.NewFromFloat(v)
|
||
ttt.Add(t1)
|
||
}
|
||
return ttt
|
||
}
|
||
return decimal.NewFromFloat(0)
|
||
}
|
||
|
||
// 获得指定的*/区
|
||
func (s *BattleSkillEntity) GetMulValue(e EnumCategory, c EnumsZoneType) decimal.Decimal {
|
||
|
||
t, ok := s.DamageZone[e][c][DamageZone.nul]
|
||
if ok {
|
||
var ttt decimal.Decimal
|
||
|
||
for _, v := range t {
|
||
t1 := decimal.NewFromFloat(v)
|
||
ttt.Mul(t1)
|
||
}
|
||
return ttt
|
||
}
|
||
|
||
return decimal.NewFromFloat(0)
|
||
|
||
}
|
||
|
||
// 设置指定的值
|
||
// 三维map 伤害类型-》增还是减-》加还是乘-》值
|
||
func (s *BattleSkillEntity) PutDamageZone(e EnumCategory, dtype EnumsZoneType, value float64, ftype EnumsZoneType) {
|
||
s.DamageZone[e][dtype][ftype] = append(s.DamageZone[e][dtype][ftype], value)
|
||
// switch dtype { //判断伤害节点段
|
||
|
||
// //case Zone.Power: //特判乘算区的乘运算
|
||
|
||
// default:
|
||
// switch ftype { //判断设置哪个算区
|
||
|
||
// case true: // 乘算区
|
||
// old := s.GetAddValue(e)
|
||
|
||
// new := decimal.NewFromFloat(value)
|
||
// s.DamageZone[dtype] = float64(old.Add(new).IntPart())
|
||
|
||
// case false: // 加算区
|
||
// old := s.GetMulValue(e)
|
||
|
||
// new := decimal.NewFromFloat(value)
|
||
// s.DamageZone[dtype] = float64(old.Add(new).IntPart())
|
||
|
||
// }
|
||
// }
|
||
|
||
}
|
||
func (s *BattleSkillEntity) Pet() (*BattlePetEntity, bool) {
|
||
pet, ok := s.ctx.Value(Pet_O_Ctx).(*BattlePetEntity)
|
||
|
||
return pet, ok
|
||
|
||
}
|
||
|
||
// 暴击伤害 返回暴击率和是否暴击
|
||
func (s *BattleSkillEntity) CriticalRate() decimal.Decimal {
|
||
|
||
return decimal.NewFromFloat(2)
|
||
|
||
}
|
||
|
||
func (s *BattleSkillEntity) criticalrandom() decimal.Decimal {
|
||
//这里应该算上威力区
|
||
// 初始化随机值,范围217~255
|
||
|
||
randomnum := s.Random().NextLongN(39) + 217
|
||
// 10. 随机倍率,随机值除以255
|
||
randomFactor := decimal.NewFromInt(int64(randomnum)).Div(decimal.NewFromInt(255))
|
||
return randomFactor
|
||
|
||
}
|
||
|
||
// // 计算技能威力
|
||
// func (s *BattleSkillEntity) CalculatePower(p *BattlePetEntity) int64 {
|
||
|
||
// pet, _ := s.Pet()
|
||
|
||
// // 1. 计算等级因子 (level * 0.4 + 2)
|
||
// levelFactor := decimal.NewFromInt(int64(pet.Level)).
|
||
// Mul(decimal.NewFromFloat(0.4)).Add(decimal.NewFromInt(2))
|
||
|
||
// // 2. 计算威力因子 (基础威力 + 加算) * 乘算
|
||
|
||
// //powerAdd := decimal.NewFromFloat(s.GetAddValue(EnumCategory., true)) //威力加算区
|
||
|
||
// powerMul := decimal.NewFromFloat(s.DamageZone[DamageMultiplierZoneEnum.POWER_MUL]) //威力乘算区
|
||
// powerZone := decimal.NewFromInt(int64(s.Power)).Add(powerAdd).Mul(powerMul)
|
||
|
||
// var (
|
||
// attackDec decimal.Decimal //攻击值
|
||
// defenseDec decimal.Decimal //防御值
|
||
// damageReduction decimal.Decimal //伤害百分比减免
|
||
// )
|
||
// switch s.Category() { //判断技能类型
|
||
// case Category.PHYSICAL:
|
||
// attackDec = decimal.NewFromInt(int64(pet.UnitAttributes[AttrType.Attack].Value()))
|
||
// defenseDec = decimal.NewFromInt(int64(p.UnitAttributes[AttrType.Defense].Value()))
|
||
// damageReduction = decimal.NewFromFloat(s.DamageZone[DamageMultiplierZoneEnum.ATK_RESISTANCE])
|
||
|
||
// case Category.SPECIAL:
|
||
// attackDec = decimal.NewFromInt(int64(pet.UnitAttributes[AttrType.Attack].Value()))
|
||
// defenseDec = decimal.NewFromInt(int64(p.UnitAttributes[AttrType.Speed].Value()))
|
||
// damageReduction = decimal.NewFromFloat(s.DamageZone[DamageMultiplierZoneEnum.SP_ATK_RESISTANCE])
|
||
// }
|
||
// //攻击次数结算
|
||
// attackCount := decimal.NewFromFloat(s.DamageZone[DamageMultiplierZoneEnum.ATTACK_COUNT_ZONE])
|
||
// // 5. 基础伤害公式:等级因子 * 威力因子 * 攻击 / 防御 / 50 + 2,然后乘以攻击次数
|
||
// baseDamage := levelFactor.
|
||
// Mul(powerZone).
|
||
// Mul(attackDec).
|
||
// Div(defenseDec).
|
||
// Div(decimal.NewFromInt(50)).
|
||
// Add(decimal.NewFromInt(2)).
|
||
// Mul(attackCount)
|
||
|
||
// // 6. 同系加成(属性相同则乘以同系加成倍率,否则1)
|
||
// sameTypeBonus := decimal.NewFromFloat(1.0)
|
||
// if s.Type() == pet.Type() {
|
||
// sameTypeBonus = decimal.NewFromFloat(1.5)
|
||
// }
|
||
|
||
// t, _ := element.NewElementCalculator().GetOffensiveMultiplier(int(pet.Type()), int(pet.Type()))
|
||
|
||
// typeRate := decimal.NewFromFloat(t)
|
||
|
||
// // 8. 暴击倍率(暴击时使用暴击倍率,否则1)
|
||
|
||
// criticalRate := decimal.NewFromFloat(1.0)
|
||
// if s.isCritical {
|
||
// criticalRate = s.CriticalRate()
|
||
// }
|
||
|
||
// // 9. 技能特殊效果倍率
|
||
// specialEffect := decimal.NewFromFloat(s.DamageZone[DamageMultiplierZoneEnum.SPECIAL_EFFECT_MUL])
|
||
|
||
// // 11. 计算总伤害
|
||
// damage := baseDamage.
|
||
// Mul(sameTypeBonus). // 同属性加成
|
||
// Mul(typeRate). // 克制系数
|
||
// Mul(criticalRate). //暴击系数
|
||
// Mul(damageReduction). //减伤计算
|
||
// Mul(specialEffect). //特殊效果
|
||
// Mul(s.criticalrandom()) //随机波动
|
||
|
||
// // 12. 存储真实伤害到额外倍率,方便后续查询
|
||
// //context.PutExtraRate("REAL_DAMAGE", damage)
|
||
|
||
// // 13. 应用固定伤害减免,伤害不能低于0
|
||
// fixReduction := decimal.NewFromFloat(s.DamageZone[DamageMultiplierZoneEnum.DEFENSE_ZONE])
|
||
// if fixReduction.GreaterThan(decimal.Zero) {
|
||
// damage = damage.Sub(fixReduction)
|
||
// if damage.LessThan(decimal.Zero) {
|
||
// damage = decimal.Zero
|
||
// }
|
||
// }
|
||
|
||
// // 返回最终伤害(整数部分)
|
||
// return damage.IntPart()
|
||
|
||
// }
|