refactor(fight): 重构战斗模块
- 移除 BattleStateMachine 和 BattleUnit 相关代码 - 新增 BattleContainer 和 DamageContext 结构体 - 重构伤害计算逻辑,使用高精度 decimal 进行计算 - 更新随机数生成器,支持基于用户和时间的种子生成 - 优化战斗信息结构,增加 OwnerID 字段
This commit is contained in:
@@ -13,6 +13,7 @@ func (h Controller) OnPlayerFightNpcMonster(data *fight.FightNpcMonsterInboundIn
|
|||||||
c.IsFighting = true
|
c.IsFighting = true
|
||||||
t1 := handler.NewTomeeHeader(2503, c.UserID)
|
t1 := handler.NewTomeeHeader(2503, c.UserID)
|
||||||
ttt := info.NoteReadyToFightInfo{
|
ttt := info.NoteReadyToFightInfo{
|
||||||
|
OwnerID: data.Head.UserID,
|
||||||
FightId: 3,
|
FightId: 3,
|
||||||
}
|
}
|
||||||
ttt.OurInfo = info.FightUserInfo{UserID: c.UserID}
|
ttt.OurInfo = info.FightUserInfo{UserID: c.UserID}
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
package battle
|
|
||||||
|
|
||||||
const (
|
|
||||||
StateStart BattleState = iota
|
|
||||||
StatePlayerTurn
|
|
||||||
StateEnemyTurn
|
|
||||||
StateEnd
|
|
||||||
)
|
|
||||||
|
|
||||||
type BattleStateMachine struct {
|
|
||||||
State BattleState
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fsm *BattleStateMachine) Next() {
|
|
||||||
switch fsm.State {
|
|
||||||
case StateStart:
|
|
||||||
fsm.State = StatePlayerTurn
|
|
||||||
case StatePlayerTurn:
|
|
||||||
fsm.State = StateEnemyTurn
|
|
||||||
case StateEnemyTurn:
|
|
||||||
fsm.State = StatePlayerTurn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +1,13 @@
|
|||||||
package battle
|
package battle
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"blazing/logic/service/fight/battle/skill/effect"
|
"blazing/logic/service/fight/battle/random"
|
||||||
"math/rand/v2"
|
"blazing/logic/service/fight/info"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BattleState int
|
|
||||||
|
|
||||||
// ==== 基础数据结构 ====
|
|
||||||
|
|
||||||
type BattleUnit struct {
|
|
||||||
Name string
|
|
||||||
Level int
|
|
||||||
Atk int
|
|
||||||
Def int
|
|
||||||
MaxHP int
|
|
||||||
HP int
|
|
||||||
Buffs map[string]effect.Effect
|
|
||||||
|
|
||||||
IsCritical bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewBattleUnit(name string, level, atk, def, maxHP int) *BattleUnit {
|
|
||||||
return &BattleUnit{
|
|
||||||
Name: name,
|
|
||||||
Level: level,
|
|
||||||
Atk: atk,
|
|
||||||
Def: def,
|
|
||||||
MaxHP: maxHP,
|
|
||||||
HP: maxHP,
|
|
||||||
Buffs: make(map[string]effect.Effect),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==== 战斗上下文 ====
|
|
||||||
|
|
||||||
type BattleContext struct {
|
type BattleContext struct {
|
||||||
Rand *rand.Rand
|
Rand random.RandomXS128
|
||||||
}
|
same []info.FightUserInfo //同阵营
|
||||||
|
|
||||||
// ==== 技能 ====
|
opposite []info.FightUserInfo //不同阵营
|
||||||
|
|
||||||
type Skill struct {
|
|
||||||
Name string
|
|
||||||
Type SkillType
|
|
||||||
Power int
|
|
||||||
IsAttack bool
|
|
||||||
Attacker *BattleUnit
|
|
||||||
Defender *BattleUnit
|
|
||||||
Effects []Effect
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,38 @@
|
|||||||
package battle
|
package battle
|
||||||
|
|
||||||
|
import "blazing/logic/service/fight/info"
|
||||||
|
|
||||||
type BattleContainer struct {
|
type BattleContainer struct {
|
||||||
FightUserInfo
|
BattleContext
|
||||||
|
ownerid uint32
|
||||||
}
|
}
|
||||||
b.Turn++
|
|
||||||
fmt.Printf("=== 回合 %d 开始 ===\n", b.Turn)
|
//返回房主信息
|
||||||
b.PublishTrigger(EffectTrigger.TurnStart, containers)
|
func (b *BattleContainer) Owner() *info.FightUserInfo {
|
||||||
fmt.Println("=== 玩家操作阶段 ===")
|
|
||||||
b.PublishTrigger(EffectTrigger.TurnEnd, containers)
|
return &b.same[0]
|
||||||
fmt.Printf("=== 回合 %d 结束 ===\n\n", b.Turn)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//返回邀请者信息,比如野怪
|
||||||
|
func (b *BattleContainer) Target() *info.FightUserInfo {
|
||||||
|
|
||||||
|
return &b.opposite[0]
|
||||||
|
}
|
||||||
|
func NewBattleContainer(i info.NoteReadyToFightInfo) *BattleContainer {
|
||||||
|
|
||||||
|
ret := BattleContainer{}
|
||||||
|
ret.same = make([]info.FightUserInfo, 0) //初始化本阵营
|
||||||
|
ret.opposite = make([]info.FightUserInfo, 0) //初始化敌方阵营
|
||||||
|
ret.same = append(ret.same, i.OurInfo)
|
||||||
|
ret.opposite = append(ret.same, i.OpponentInfo)
|
||||||
|
ret.ownerid = i.OwnerID //房主ID
|
||||||
|
return &ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// b.Turn++
|
||||||
|
// fmt.Printf("=== 回合 %d 开始 ===\n", b.Turn)
|
||||||
|
// b.PublishTrigger(EffectTrigger.TurnStart, containers)
|
||||||
|
// fmt.Println("=== 玩家操作阶段 ===")
|
||||||
|
// b.PublishTrigger(EffectTrigger.TurnEnd, containers)
|
||||||
|
// fmt.Printf("=== 回合 %d 结束 ===\n\n", b.Turn)
|
||||||
|
// }
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
package damage
|
|
||||||
|
|
||||||
import "math/rand"
|
|
||||||
|
|
||||||
// ==== 伤害计算 ====
|
|
||||||
|
|
||||||
func CalculateDamage(attacker, defender *BattleUnit, power int, isCritical bool, r *rand.Rand) int {
|
|
||||||
randomFactor := float64(r.Intn(39)+217) / 255.0
|
|
||||||
levelZone := float64(attacker.Level*2) / float64(attacker.Level+defender.Level)
|
|
||||||
base := ((float64(attacker.Atk) * float64(power) / float64(defender.Def)) / 50.0) + 2
|
|
||||||
|
|
||||||
crit := 1.0
|
|
||||||
if isCritical {
|
|
||||||
crit = 1.5
|
|
||||||
}
|
|
||||||
|
|
||||||
damage := int((base*levelZone*randomFactor)*crit + 0.5)
|
|
||||||
if damage < 1 {
|
|
||||||
damage = 1
|
|
||||||
}
|
|
||||||
return damage
|
|
||||||
}
|
|
||||||
@@ -1,277 +0,0 @@
|
|||||||
package damage
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
|
||||||
|
|
||||||
"github.com/shopspring/decimal"
|
|
||||||
"github.com/tnnmigga/enum"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SkillType 技能类型枚举,区分物理和特殊技能
|
|
||||||
type SkillType int
|
|
||||||
|
|
||||||
const (
|
|
||||||
PHYSICAL SkillType = iota + 1 // 物理技能
|
|
||||||
SPECIAL // 特殊技能
|
|
||||||
)
|
|
||||||
|
|
||||||
// DamageMultiplierZone 伤害乘算区枚举,使用enum包定义
|
|
||||||
type DamageMultiplierZone int
|
|
||||||
|
|
||||||
var DamageMultiplierZoneEnum = enum.New[struct {
|
|
||||||
POWER_ADDITION_ZONE DamageMultiplierZone // 威力加算区,直接加成威力值
|
|
||||||
POWER_MULTIPLIER_ZONE DamageMultiplierZone // 威力乘算区,倍率调整(如威力倍数)
|
|
||||||
ATK_RESISTANCE_ZONE DamageMultiplierZone // 物理伤害减免乘区,默认1,减伤50%对应0.5
|
|
||||||
SP_ATK_RESISTANCE_ZONE DamageMultiplierZone // 特殊伤害减免乘区,默认1,减伤50%对应0.5
|
|
||||||
SPECIAL_EFFECT_MULTIPLIER_ZONE DamageMultiplierZone // 特殊效果乘算区,如Boss减伤等
|
|
||||||
ATTACK_COUNT_ZONE DamageMultiplierZone // 攻击次数乘算区,如攻击2次对应2
|
|
||||||
FIX_DAMAGE_RESISTANCE_ZONE DamageMultiplierZone // 固定伤害减免区,直接减固定值
|
|
||||||
}]()
|
|
||||||
|
|
||||||
// Code 返回枚举对应整数值
|
|
||||||
func (z DamageMultiplierZone) Code() int {
|
|
||||||
return int(z)
|
|
||||||
}
|
|
||||||
|
|
||||||
// String 返回枚举名称字符串,方便调试打印
|
|
||||||
func (z DamageMultiplierZone) String() string {
|
|
||||||
switch z {
|
|
||||||
case DamageMultiplierZoneEnum.POWER_ADDITION_ZONE:
|
|
||||||
return "POWER_ADDITION_ZONE"
|
|
||||||
case DamageMultiplierZoneEnum.POWER_MULTIPLIER_ZONE:
|
|
||||||
return "POWER_MULTIPLIER_ZONE"
|
|
||||||
case DamageMultiplierZoneEnum.ATK_RESISTANCE_ZONE:
|
|
||||||
return "ATK_RESISTANCE_ZONE"
|
|
||||||
case DamageMultiplierZoneEnum.SP_ATK_RESISTANCE_ZONE:
|
|
||||||
return "SP_ATK_RESISTANCE_ZONE"
|
|
||||||
case DamageMultiplierZoneEnum.SPECIAL_EFFECT_MULTIPLIER_ZONE:
|
|
||||||
return "SPECIAL_EFFECT_MULTIPLIER_ZONE"
|
|
||||||
case DamageMultiplierZoneEnum.ATTACK_COUNT_ZONE:
|
|
||||||
return "ATTACK_COUNT_ZONE"
|
|
||||||
case DamageMultiplierZoneEnum.FIX_DAMAGE_RESISTANCE_ZONE:
|
|
||||||
return "FIX_DAMAGE_RESISTANCE_ZONE"
|
|
||||||
default:
|
|
||||||
return fmt.Sprintf("Unknown(DamageMultiplierZone=%d)", z)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromCode 根据整数值获取枚举
|
|
||||||
func FromCode(code int) (DamageMultiplierZone, error) {
|
|
||||||
switch code {
|
|
||||||
case 1:
|
|
||||||
return DamageMultiplierZoneEnum.POWER_ADDITION_ZONE, nil
|
|
||||||
case 2:
|
|
||||||
return DamageMultiplierZoneEnum.POWER_MULTIPLIER_ZONE, nil
|
|
||||||
case 3:
|
|
||||||
return DamageMultiplierZoneEnum.ATK_RESISTANCE_ZONE, nil
|
|
||||||
case 4:
|
|
||||||
return DamageMultiplierZoneEnum.SP_ATK_RESISTANCE_ZONE, nil
|
|
||||||
case 5:
|
|
||||||
return DamageMultiplierZoneEnum.SPECIAL_EFFECT_MULTIPLIER_ZONE, nil
|
|
||||||
case 6:
|
|
||||||
return DamageMultiplierZoneEnum.ATTACK_COUNT_ZONE, nil
|
|
||||||
case 7:
|
|
||||||
return DamageMultiplierZoneEnum.FIX_DAMAGE_RESISTANCE_ZONE, nil
|
|
||||||
default:
|
|
||||||
return 0, fmt.Errorf("未知的DamageMultiplierZone代码: %d", code)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pet 接口,表示战斗中的宠物实体,包含等级、类型和名称等
|
|
||||||
type Pet interface {
|
|
||||||
Level() int64
|
|
||||||
Type() SkillType
|
|
||||||
Name() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// SkillInterface 接口,表示技能实体,包含技能类型和名称
|
|
||||||
type SkillInterface interface {
|
|
||||||
SkillType() SkillType
|
|
||||||
Name() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// DamageContext 伤害计算上下文,包含攻击方、防御方宠物,技能信息,以及各种计算参数
|
|
||||||
type DamageContext struct {
|
|
||||||
attackerPet Pet // 攻击宠物
|
|
||||||
defenderPet Pet // 防御宠物
|
|
||||||
skill SkillInterface // 技能
|
|
||||||
|
|
||||||
Type SkillType // 技能属性类型(物理或特殊)
|
|
||||||
BasePower int64 // 基础威力值
|
|
||||||
Attack int64 // 攻击力
|
|
||||||
Defense int64 // 防御力
|
|
||||||
CriticalRate float64 // 暴击倍率,默认2.0倍
|
|
||||||
SameTypeRate float64 // 同系加成倍率,默认1.5倍
|
|
||||||
Random int // 随机值,默认-1表示未设置
|
|
||||||
|
|
||||||
otherRates map[DamageMultiplierZone]decimal.Decimal // 各伤害乘算区倍率,使用高精度decimal
|
|
||||||
extraRates map[string]decimal.Decimal // 额外倍率,支持自定义key
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDamageContext 构造函数,初始化默认值
|
|
||||||
func NewDamageContext(attackerPet, defenderPet Pet, skill SkillInterface) *DamageContext {
|
|
||||||
ctx := &DamageContext{
|
|
||||||
attackerPet: attackerPet,
|
|
||||||
defenderPet: defenderPet,
|
|
||||||
skill: skill,
|
|
||||||
CriticalRate: 2.0,
|
|
||||||
SameTypeRate: 1.5,
|
|
||||||
Random: -1,
|
|
||||||
otherRates: make(map[DamageMultiplierZone]decimal.Decimal),
|
|
||||||
extraRates: make(map[string]decimal.Decimal),
|
|
||||||
}
|
|
||||||
ctx.initOtherRates()
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
// initOtherRates 初始化伤害乘算区的默认倍率值
|
|
||||||
func (c *DamageContext) initOtherRates() {
|
|
||||||
c.otherRates[DamageMultiplierZoneEnum.POWER_ADDITION_ZONE] = decimal.Zero // 威力加成,默认0
|
|
||||||
c.otherRates[DamageMultiplierZoneEnum.POWER_MULTIPLIER_ZONE] = decimal.NewFromInt(1) // 威力倍率,默认1
|
|
||||||
c.otherRates[DamageMultiplierZoneEnum.ATK_RESISTANCE_ZONE] = decimal.NewFromInt(1) // 物理减伤,默认1
|
|
||||||
c.otherRates[DamageMultiplierZoneEnum.SP_ATK_RESISTANCE_ZONE] = decimal.NewFromInt(1) // 特殊减伤,默认1
|
|
||||||
c.otherRates[DamageMultiplierZoneEnum.SPECIAL_EFFECT_MULTIPLIER_ZONE] = decimal.NewFromInt(1) // 特殊效果倍率,默认1
|
|
||||||
c.otherRates[DamageMultiplierZoneEnum.ATTACK_COUNT_ZONE] = decimal.NewFromInt(1) // 攻击次数,默认1
|
|
||||||
c.otherRates[DamageMultiplierZoneEnum.FIX_DAMAGE_RESISTANCE_ZONE] = decimal.Zero // 固定减伤,默认0
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetOtherRate 获取指定伤害乘算区的倍率
|
|
||||||
func (c *DamageContext) GetOtherRate(zone DamageMultiplierZone) decimal.Decimal {
|
|
||||||
if val, ok := c.otherRates[zone]; ok {
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
return decimal.NewFromInt(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PutOtherRate 设置指定伤害乘算区的倍率,支持链式调用
|
|
||||||
func (c *DamageContext) PutOtherRate(zone DamageMultiplierZone, value decimal.Decimal) *DamageContext {
|
|
||||||
switch zone {
|
|
||||||
case DamageMultiplierZoneEnum.FIX_DAMAGE_RESISTANCE_ZONE:
|
|
||||||
// 固定伤害减免区,累加
|
|
||||||
c.otherRates[zone] = c.GetOtherRate(zone).Add(value)
|
|
||||||
case DamageMultiplierZoneEnum.ATTACK_COUNT_ZONE:
|
|
||||||
// 攻击次数区,直接覆盖
|
|
||||||
c.otherRates[zone] = value
|
|
||||||
case DamageMultiplierZoneEnum.ATK_RESISTANCE_ZONE, DamageMultiplierZoneEnum.SP_ATK_RESISTANCE_ZONE:
|
|
||||||
// 减伤乘算区,乘法叠加(只当value>0时)
|
|
||||||
if value.GreaterThan(decimal.Zero) {
|
|
||||||
c.otherRates[zone] = c.GetOtherRate(zone).Mul(value)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// 其他乘算区,加法叠加,且不小于0.1
|
|
||||||
r := c.GetOtherRate(zone).Add(value)
|
|
||||||
if r.LessThan(decimal.NewFromFloat(0.1)) {
|
|
||||||
r = decimal.NewFromFloat(0.1)
|
|
||||||
}
|
|
||||||
c.otherRates[zone] = r
|
|
||||||
}
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomValue 获取当前随机值,-1表示未设置
|
|
||||||
func (c *DamageContext) RandomValue() int {
|
|
||||||
return c.Random
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetRandomValue 设置随机值,支持链式调用
|
|
||||||
func (c *DamageContext) SetRandomValue(r int) *DamageContext {
|
|
||||||
c.Random = r
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// PutExtraRate 设置自定义额外倍率
|
|
||||||
func (c *DamageContext) PutExtraRate(key string, value decimal.Decimal) {
|
|
||||||
c.extraRates[key] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetExtraRate 获取自定义额外倍率,返回倍率和是否存在
|
|
||||||
func (c *DamageContext) GetExtraRate(key string) (decimal.Decimal, bool) {
|
|
||||||
val, ok := c.extraRates[key]
|
|
||||||
return val, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate 伤害计算函数,返回最终伤害整数值
|
|
||||||
func Calculate(random *rand.Rand, context *DamageContext, isCritical bool) int64 {
|
|
||||||
// 初始化随机值,范围217~255
|
|
||||||
if context.RandomValue() == -1 {
|
|
||||||
context.SetRandomValue(random.Intn(39) + 217)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. 计算等级因子 (level * 0.4 + 2)
|
|
||||||
levelFactor := decimal.NewFromInt(context.attackerPet.Level()).Mul(decimal.NewFromFloat(0.4)).Add(decimal.NewFromInt(2))
|
|
||||||
|
|
||||||
// 2. 计算威力因子 (基础威力 + 加算) * 乘算
|
|
||||||
powerAdd := context.GetOtherRate(DamageMultiplierZoneEnum.POWER_ADDITION_ZONE)
|
|
||||||
powerMul := context.GetOtherRate(DamageMultiplierZoneEnum.POWER_MULTIPLIER_ZONE)
|
|
||||||
powerZone := decimal.NewFromInt(context.BasePower).Add(powerAdd).Mul(powerMul)
|
|
||||||
|
|
||||||
// 3. 根据技能类型获取对应减伤乘算
|
|
||||||
damageReduction := decimal.NewFromFloat(1)
|
|
||||||
switch context.skill.SkillType() {
|
|
||||||
case PHYSICAL:
|
|
||||||
damageReduction = context.GetOtherRate(DamageMultiplierZoneEnum.ATK_RESISTANCE_ZONE)
|
|
||||||
case SPECIAL:
|
|
||||||
damageReduction = context.GetOtherRate(DamageMultiplierZoneEnum.SP_ATK_RESISTANCE_ZONE)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. 攻击次数倍率
|
|
||||||
attackCount := context.GetOtherRate(DamageMultiplierZoneEnum.ATTACK_COUNT_ZONE)
|
|
||||||
|
|
||||||
attackDec := decimal.NewFromInt(context.Attack)
|
|
||||||
defenseDec := decimal.NewFromInt(context.Defense)
|
|
||||||
|
|
||||||
// 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 context.Type == context.attackerPet.Type() {
|
|
||||||
sameTypeBonus = decimal.NewFromFloat(context.SameTypeRate)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 7. 属性克制倍率(示例写死1.2,实际业务中请替换成具体逻辑)
|
|
||||||
typeRate := decimal.NewFromFloat(1.2)
|
|
||||||
|
|
||||||
// 8. 暴击倍率(暴击时使用暴击倍率,否则1)
|
|
||||||
criticalRate := decimal.NewFromFloat(1.0)
|
|
||||||
if isCritical {
|
|
||||||
criticalRate = decimal.NewFromFloat(context.CriticalRate)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 9. 技能特殊效果倍率
|
|
||||||
specialEffect := context.GetOtherRate(DamageMultiplierZoneEnum.SPECIAL_EFFECT_MULTIPLIER_ZONE)
|
|
||||||
|
|
||||||
// 10. 随机倍率,随机值除以255
|
|
||||||
randomFactor := decimal.NewFromInt(int64(context.Random)).Div(decimal.NewFromInt(255))
|
|
||||||
|
|
||||||
// 11. 计算总伤害
|
|
||||||
damage := baseDamage.
|
|
||||||
Mul(sameTypeBonus).
|
|
||||||
Mul(typeRate).
|
|
||||||
Mul(criticalRate).
|
|
||||||
Mul(damageReduction).
|
|
||||||
Mul(specialEffect).
|
|
||||||
Mul(randomFactor)
|
|
||||||
|
|
||||||
// 12. 存储真实伤害到额外倍率,方便后续查询
|
|
||||||
context.PutExtraRate("REAL_DAMAGE", damage)
|
|
||||||
|
|
||||||
// 13. 应用固定伤害减免,伤害不能低于0
|
|
||||||
fixReduction := context.GetOtherRate(DamageMultiplierZoneEnum.FIX_DAMAGE_RESISTANCE_ZONE)
|
|
||||||
if fixReduction.GreaterThan(decimal.Zero) {
|
|
||||||
damage = damage.Sub(fixReduction)
|
|
||||||
if damage.LessThan(decimal.Zero) {
|
|
||||||
damage = decimal.Zero
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 返回最终伤害(整数部分)
|
|
||||||
return damage.IntPart()
|
|
||||||
}
|
|
||||||
@@ -28,6 +28,13 @@ func NewRandomXS128() *RandomXS128 {
|
|||||||
return NewRandomXS128WithSeed(seed)
|
return NewRandomXS128WithSeed(seed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 基于用户名和时间创建
|
||||||
|
func NewRandomXS128WithUser(user, time int64) *RandomXS128 {
|
||||||
|
|
||||||
|
seed := uint64(user)<<32 | uint64(time)
|
||||||
|
return NewRandomXS128WithSeed(seed)
|
||||||
|
}
|
||||||
|
|
||||||
// NewRandomXS128WithSeed 用单个 uint64 种子创建生成器
|
// NewRandomXS128WithSeed 用单个 uint64 种子创建生成器
|
||||||
func NewRandomXS128WithSeed(seed uint64) *RandomXS128 {
|
func NewRandomXS128WithSeed(seed uint64) *RandomXS128 {
|
||||||
seed0 := murmurHash3(seed)
|
seed0 := murmurHash3(seed)
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ var LifeType = enum.New[struct {
|
|||||||
// 容器:存放多个效果
|
// 容器:存放多个效果
|
||||||
// ========================
|
// ========================
|
||||||
type EffectContainer struct {
|
type EffectContainer struct {
|
||||||
GlobalEffects []*Effect // 全局常驻/回合/次数效果
|
//GlobalEffects []*Effect // 全局常驻/回合/次数效果
|
||||||
Effects []*Effect //effects
|
Effects []*Effect //effects 实际上全局就是effect无限回合
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加效果
|
// 添加效果
|
||||||
|
|||||||
@@ -2,9 +2,22 @@ package info
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"blazing/modules/blazing/model"
|
"blazing/modules/blazing/model"
|
||||||
|
"math/rand/v2"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
|
"github.com/tnnmigga/enum"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DamageMultiplierZone 伤害乘算区枚举,使用enum包定义
|
||||||
|
type DamageMultiplierZone int
|
||||||
|
|
||||||
|
var DamageMultiplierZoneEnum = enum.New[struct {
|
||||||
|
POWER_ADDITION_ZONE DamageMultiplierZone // 威力加算区,直接加成威力值
|
||||||
|
POWER_MULTIPLIER_ZONE DamageMultiplierZone // 威力乘算区,倍率调整(如威力倍数)
|
||||||
|
|
||||||
|
}]()
|
||||||
|
|
||||||
type BattlePetEntity struct {
|
type BattlePetEntity struct {
|
||||||
// /host *BattleInputSourceEntity // 宠物的主人(输入源)
|
// /host *BattleInputSourceEntity // 宠物的主人(输入源)
|
||||||
//uuid string // 唯一标识
|
//uuid string // 唯一标识
|
||||||
@@ -48,7 +61,7 @@ type BattlePetEntity struct {
|
|||||||
petImmunityBuffs map[string]int // 免疫buff效果ID -> 剩余回合 (-1表示永久)
|
petImmunityBuffs map[string]int // 免疫buff效果ID -> 剩余回合 (-1表示永久)
|
||||||
|
|
||||||
IsDead bool // 是否死亡
|
IsDead bool // 是否死亡
|
||||||
|
otherRates map[DamageMultiplierZone]decimal.Decimal // 各伤害乘算区倍率,使用高精度decimal
|
||||||
// 战斗开始时拥有的特殊buff
|
// 战斗开始时拥有的特殊buff
|
||||||
//battleStartHavingBuffs []buff.BattleBuffInterface
|
//battleStartHavingBuffs []buff.BattleBuffInterface
|
||||||
}
|
}
|
||||||
@@ -85,3 +98,109 @@ func (b *BattlePetEntity) calculateRealValue(value int64, stat int) int64 {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CalculatePower(random *rand.Rand, context *DamageContext, isCritical bool) int64 {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate 伤害计算函数,返回最终伤害整数值
|
||||||
|
func Calculate(random *rand.Rand, context *DamageContext, isCritical bool) int64 {
|
||||||
|
// 初始化随机值,范围217~255
|
||||||
|
if context.RandomValue() == -1 {
|
||||||
|
context.SetRandomValue(random.Intn(39) + 217)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 计算等级因子 (level * 0.4 + 2)
|
||||||
|
levelFactor := decimal.NewFromInt(context.attackerPet.Level()).Mul(decimal.NewFromFloat(0.4)).Add(decimal.NewFromInt(2))
|
||||||
|
|
||||||
|
// 2. 计算威力因子 (基础威力 + 加算) * 乘算
|
||||||
|
powerAdd := context.GetOtherRate(DamageMultiplierZoneEnum.POWER_ADDITION_ZONE)
|
||||||
|
powerMul := context.GetOtherRate(DamageMultiplierZoneEnum.POWER_MULTIPLIER_ZONE)
|
||||||
|
powerZone := decimal.NewFromInt(context.BasePower).Add(powerAdd).Mul(powerMul)
|
||||||
|
|
||||||
|
// 3. 根据技能类型获取对应减伤乘算
|
||||||
|
damageReduction := decimal.NewFromFloat(1)
|
||||||
|
switch context.skill.SkillType() {
|
||||||
|
case PHYSICAL:
|
||||||
|
damageReduction = context.GetOtherRate(DamageMultiplierZoneEnum.ATK_RESISTANCE_ZONE)
|
||||||
|
case SPECIAL:
|
||||||
|
damageReduction = context.GetOtherRate(DamageMultiplierZoneEnum.SP_ATK_RESISTANCE_ZONE)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 攻击次数倍率
|
||||||
|
attackCount := context.GetOtherRate(DamageMultiplierZoneEnum.ATTACK_COUNT_ZONE)
|
||||||
|
|
||||||
|
attackDec := decimal.NewFromInt(context.Attack)
|
||||||
|
defenseDec := decimal.NewFromInt(context.Defense)
|
||||||
|
|
||||||
|
// 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 context.Type == context.attackerPet.Type() {
|
||||||
|
sameTypeBonus = decimal.NewFromFloat(context.SameTypeRate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. 属性克制倍率(示例写死1.2,实际业务中请替换成具体逻辑)
|
||||||
|
typeRate := decimal.NewFromFloat(1.2)
|
||||||
|
|
||||||
|
// 8. 暴击倍率(暴击时使用暴击倍率,否则1)
|
||||||
|
criticalRate := decimal.NewFromFloat(1.0)
|
||||||
|
if isCritical {
|
||||||
|
criticalRate = decimal.NewFromFloat(context.CriticalRate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 9. 技能特殊效果倍率
|
||||||
|
specialEffect := context.GetOtherRate(DamageMultiplierZoneEnum.SPECIAL_EFFECT_MULTIPLIER_ZONE)
|
||||||
|
|
||||||
|
// 10. 随机倍率,随机值除以255
|
||||||
|
randomFactor := decimal.NewFromInt(int64(context.Random)).Div(decimal.NewFromInt(255))
|
||||||
|
|
||||||
|
// 11. 计算总伤害
|
||||||
|
damage := baseDamage.
|
||||||
|
Mul(sameTypeBonus).
|
||||||
|
Mul(typeRate).
|
||||||
|
Mul(criticalRate).
|
||||||
|
Mul(damageReduction).
|
||||||
|
Mul(specialEffect).
|
||||||
|
Mul(randomFactor)
|
||||||
|
|
||||||
|
// 12. 存储真实伤害到额外倍率,方便后续查询
|
||||||
|
context.PutExtraRate("REAL_DAMAGE", damage)
|
||||||
|
|
||||||
|
// 13. 应用固定伤害减免,伤害不能低于0
|
||||||
|
fixReduction := context.GetOtherRate(DamageMultiplierZoneEnum.FIX_DAMAGE_RESISTANCE_ZONE)
|
||||||
|
if fixReduction.GreaterThan(decimal.Zero) {
|
||||||
|
damage = damage.Sub(fixReduction)
|
||||||
|
if damage.LessThan(decimal.Zero) {
|
||||||
|
damage = decimal.Zero
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回最终伤害(整数部分)
|
||||||
|
return damage.IntPart()
|
||||||
|
}
|
||||||
|
|
||||||
|
// func CalculateDamage(attacker, defender *BattleUnit, power int, isCritical bool, r *rand.Rand) int {
|
||||||
|
// randomFactor := float64(r.Intn(39)+217) / 255.0
|
||||||
|
// levelZone := float64(attacker.Level*2) / float64(attacker.Level+defender.Level)
|
||||||
|
// base := ((float64(attacker.Atk) * float64(power) / float64(defender.Def)) / 50.0) + 2
|
||||||
|
|
||||||
|
// crit := 1.0
|
||||||
|
// if isCritical {
|
||||||
|
// crit = 1.5
|
||||||
|
// }
|
||||||
|
|
||||||
|
// damage := int((base*levelZone*randomFactor)*crit + 0.5)
|
||||||
|
// if damage < 1 {
|
||||||
|
// damage = 1
|
||||||
|
// }
|
||||||
|
// return damage
|
||||||
|
// }
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import (
|
|||||||
|
|
||||||
// NoteReadyToFightInfo 战斗准备就绪消息结构体,对应Java的NoteReadyToFightInfo
|
// NoteReadyToFightInfo 战斗准备就绪消息结构体,对应Java的NoteReadyToFightInfo
|
||||||
type NoteReadyToFightInfo struct {
|
type NoteReadyToFightInfo struct {
|
||||||
|
//战斗发起者ID
|
||||||
|
OwnerID uint32 `struc:"skip"`
|
||||||
// 战斗类型ID(与野怪战斗为3,与人战斗为1,前端似乎未使用)
|
// 战斗类型ID(与野怪战斗为3,与人战斗为1,前端似乎未使用)
|
||||||
// 对应Java的@UInt long
|
// 对应Java的@UInt long
|
||||||
FightId uint32 `fieldDesc:"战斗类型ID 但前端好像没有用到 与野怪战斗为3,与人战斗似乎是1" `
|
FightId uint32 `fieldDesc:"战斗类型ID 但前端好像没有用到 与野怪战斗为3,与人战斗似乎是1" `
|
||||||
|
|||||||
Reference in New Issue
Block a user