Files
bl/logic/service/fight/input/input.go

196 lines
5.5 KiB
Go
Raw Normal View History

package input
import (
"blazing/common/utils"
"blazing/logic/service/common"
"blazing/logic/service/fight/info"
"fmt"
"math"
"github.com/gogf/gf/v2/util/gconv"
"github.com/jinzhu/copier"
)
type Input struct {
CanChange bool //是否可以死亡切换CanChange
CurrentPet *info.BattlePetEntity //当前精灵
AllPet []*info.BattlePetEntity
Player common.PlayerI
Finished bool //是否加载完成
*info.AttackValue
FightC common.FightI
// info.BattleActionI
Effects *utils.OrderedMap[int, Effect] //effects 实际上全局就是effect无限回合 //effects容器 技能的
//Damage decimal.Decimal //造成伤害
First bool //是否先手
}
func NewInput(c common.FightI, p common.PlayerI) *Input {
ret := &Input{FightC: c, Player: p}
t := ret.GetDamageEffect(0)
ret.AddEffect(t) //添加默认基类,实现继承
p.SetFightC(c) //给玩家设置战斗容器
ret.Effects = utils.NewOrderedMap[int, Effect]()
return ret
}
func (i *Input) GetPetInfo() *info.BattlePetEntity {
return i.CurrentPet
}
// 这个每回合都会调用
func (i *Input) InitAttackValue() {
i.AttackValue = info.NewAttackValue(i.Player.GetInfo().UserID)
}
func (i *Input) GetPet(id uint32) (ii *info.BattlePetEntity, Reason info.ChangePetInfo) {
for _, v := range i.AllPet {
if v.Info.CatchTime == uint32(id) {
copier.Copy(&Reason, &v.Info)
Reason.UserId = i.Player.GetInfo().UserID
ii = v
}
}
return
}
// GetStatusBonus 获取最高的状态倍率
// 遍历状态数组返回存在的状态中最高的倍率无状态则返回1.0
func (i *Input) GetStatusBonus() float64 {
// 异常状态倍率映射表(状态索引 -> 倍率)
var statusBonuses = map[info.EnumBattleStatus]float64{
info.BattleStatus.Paralysis: 1.5,
info.BattleStatus.Poisoned: 1.5,
info.BattleStatus.Sleep: 2.0,
// /info.BattleStatus.Frozen: 2.0,
}
maxBonus := 1.0 // 默认无状态倍率
for statusIdx := 0; statusIdx < 20; statusIdx++ {
t, ok := i.GetStatusEffect(statusIdx)
// 检查状态是否存在数组中值为1表示存在该状态
if ok && t.Stack() > 0 {
if bonus, exists := statusBonuses[info.EnumBattleStatus(statusIdx)]; exists && bonus > maxBonus {
maxBonus = bonus
}
}
}
return maxBonus
}
// 特殊胶囊必定成功
// CaptureParams 捕捉参数
// type CaptureParams struct {
// PetID int // 精灵ID
// MaxHP int // 目标最大HP
// CurrentHP int // 目标当前HP
// CatchRate int // 目标捕获率分子
// CatchDenom int // 捕获率分母如100、1000
// ItemID int // 使用的道具ID
// Statuses [20]byte // 异常状态数组存在的状态对应位置为1
// OwnedCount int // 已拥有数量(-1=保底0=锁定≥1=衰减)
// -1是保底模式0是锁定模式》0是衰减模式
// Capture 执行捕捉 ,捕捉精灵,使用的道具,模式
func (c *Input) Capture(pet *info.BattlePetEntity, ItemID uint32, ownerpet int) (bool, CaptureDetails) {
if getItemBonus(ItemID) >= 255 {
return true, CaptureDetails{
Success: true,
Mode: "特殊胶囊必定成功",
BaseRate: 100.0,
ModifiedRate: 100.0,
GuaranteeBonus: 0,
StatusBonus: c.GetStatusBonus(),
Details: fmt.Sprintf("道具ID=%d必定成功", ItemID),
}
}
// 锁定模式
if ownerpet == 0 {
return false, CaptureDetails{
Success: false,
Mode: "锁定模式",
BaseRate: 0,
ModifiedRate: 0,
GuaranteeBonus: 0,
StatusBonus: c.GetStatusBonus(),
Details: "已拥有数量为0无法捕捉",
}
}
// 计算基础捕捉率
baseRate := c.calcBaseRate(pet, ItemID)
denominator := c.Player.GetPlayerCaptureContext().Denominator
numerator := int(baseRate * float64(denominator))
// 衰减模式
if ownerpet > 0 {
decay := math.Pow(1-c.Player.GetPlayerCaptureContext().DecayFactor, float64(ownerpet))
baseRate *= decay
if baseRate < 0.01 {
baseRate = 0.01 // 最低1%成功率
}
numerator = int(baseRate * float64(denominator))
}
// 走统一保底判定
success, basePct, bonusPct := c.Player.Roll(numerator, denominator)
return success, CaptureDetails{
Success: success,
Mode: map[int]string{-1: "保底模式", 0: "锁定模式", 1: "衰减模式"}[ownerpet],
BaseRate: basePct,
ModifiedRate: basePct + bonusPct,
GuaranteeBonus: bonusPct,
StatusBonus: c.GetStatusBonus(),
Details: fmt.Sprintf("a=%d, 分子=%d, 分母=%d", c.calcBaseA(pet, ItemID), numerator, denominator),
}
}
// calcBaseA 按公式计算a值
func (c *Input) calcBaseA(pet *info.BattlePetEntity, ItemID uint32) int {
catchRate := gconv.Int(pet.CatchRate)
catchRate = (catchRate * c.Player.GetPlayerCaptureContext().Denominator) / 1000 // 归一化到1000分母
if catchRate < 3 {
catchRate = 3
}
currentHP := pet.Info.Hp
if currentHP <= 0 {
currentHP = 1
}
hpRatio := (3.0*float64(pet.Info.MaxHp) - 2.0*float64(currentHP)) / (3.0 * float64(pet.Info.MaxHp))
if hpRatio < 0 {
hpRatio = 0
}
itemBonus := getItemBonus(ItemID)
statusBonus := c.GetStatusBonus()
return int(hpRatio * float64(catchRate) * itemBonus * statusBonus)
}
// calcBaseRate 按公式计算基础成功率
func (c *Input) calcBaseRate(pet *info.BattlePetEntity, ItemID uint32) float64 {
if getItemBonus(ItemID) >= 255 {
return 1.0
}
a := c.calcBaseA(pet, ItemID)
if a >= 255 {
return 1.0
}
g := int(1048560.0 / math.Floor(math.Sqrt(math.Floor(math.Sqrt(math.Floor(16711680.0/float64(a)))))))
return math.Pow(float64(g)/65536.0, 4.0)
}