feat(capture): 重构捕捉系统,实现状态倍率计算和保底机制
This commit is contained in:
@@ -3,7 +3,10 @@ package input
|
||||
import (
|
||||
"blazing/logic/service/common"
|
||||
"blazing/logic/service/fight/info"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/mohae/deepcopy"
|
||||
"github.com/shopspring/decimal"
|
||||
@@ -39,14 +42,14 @@ func (i *Input) GetPetInfo() *info.BattlePetEntity {
|
||||
|
||||
// 这个每回合都会调用
|
||||
func (i *Input) InitAttackValue() {
|
||||
i.AttackValue = info.NewAttackValue(i.Player.ID())
|
||||
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.ID()
|
||||
Reason.UserId = i.Player.GetInfo().UserID
|
||||
|
||||
ii = v
|
||||
}
|
||||
@@ -55,3 +58,153 @@ func (i *Input) GetPet(id uint32) (ii *info.BattlePetEntity, Reason info.ChangeP
|
||||
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) > 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=衰减)
|
||||
// }
|
||||
// 胶囊配置(ItemID -> Bonus)
|
||||
// var capsuleBonuses = map[int]float64{
|
||||
// 300001: 1.0, // 普通精灵胶囊
|
||||
// 300002: 1.5, // 中级精灵胶囊
|
||||
// 300003: 2.0, // 高级精灵胶囊
|
||||
// 300004: 3.0, // 超级精灵胶囊
|
||||
// 300005: 4.0, // 特级精灵胶囊
|
||||
// 300006: 256.0, // 无敌精灵胶囊
|
||||
// 300007: 256.0, // 超能胶囊
|
||||
// 300008: 2.0, // 赫星精灵胶囊
|
||||
// 300009: 256.0, // 时空精灵胶囊
|
||||
// 300010: 256.0, // 无敌精灵胶囊Ω
|
||||
// }
|
||||
//
|
||||
|
||||
// -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user