2025-09-21 14:56:37 +00:00
|
|
|
|
package input
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"blazing/common/data/xmlres"
|
2025-09-26 18:39:59 +00:00
|
|
|
|
"blazing/logic/service/fight/info"
|
|
|
|
|
|
"fmt"
|
|
|
|
|
|
"math"
|
2025-09-21 14:56:37 +00:00
|
|
|
|
|
|
|
|
|
|
"github.com/gogf/gf/v2/util/gconv"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// 异常状态常量定义(对应数组索引)
|
|
|
|
|
|
const (
|
|
|
|
|
|
StatusParalysis = 0 // 麻痹
|
|
|
|
|
|
StatusPoison = 1 // 中毒
|
|
|
|
|
|
StatusSleep = 8 // 睡眠
|
|
|
|
|
|
StatusFreeze = 3 // 冰冻
|
|
|
|
|
|
// 预留其他状态到19
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// getItemBonus 获取道具倍率
|
|
|
|
|
|
func getItemBonus(itemID uint32) float64 {
|
|
|
|
|
|
if bonus, ok := xmlres.ItemsMAP[int(itemID)]; ok {
|
|
|
|
|
|
return gconv.Float64(bonus.Bonus)
|
|
|
|
|
|
}
|
|
|
|
|
|
return 1.0
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-26 18:39:59 +00:00
|
|
|
|
// 特殊胶囊必定成功
|
|
|
|
|
|
// 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 执行捕捉 ,捕捉精灵,使用的道具,模式
|
2025-11-11 05:54:24 +00:00
|
|
|
|
func (our *Input) Capture(pet *info.BattlePetEntity, ItemID uint32, ownerpet int) (bool, CaptureDetails) {
|
2026-04-08 01:28:55 +08:00
|
|
|
|
captureCtx := our.Player.GetPlayerCaptureContext()
|
|
|
|
|
|
if captureCtx == nil {
|
|
|
|
|
|
captureCtx = info.NewPlayerCaptureContext()
|
|
|
|
|
|
}
|
2025-09-26 18:39:59 +00:00
|
|
|
|
|
|
|
|
|
|
if getItemBonus(ItemID) >= 255 {
|
|
|
|
|
|
return true, CaptureDetails{
|
|
|
|
|
|
Success: true,
|
|
|
|
|
|
Mode: "特殊胶囊必定成功",
|
|
|
|
|
|
BaseRate: 100.0,
|
|
|
|
|
|
ModifiedRate: 100.0,
|
|
|
|
|
|
GuaranteeBonus: 0,
|
2025-11-11 05:54:24 +00:00
|
|
|
|
StatusBonus: our.GetStatusBonus(),
|
2025-09-26 18:39:59 +00:00
|
|
|
|
Details: fmt.Sprintf("道具ID=%d,必定成功", ItemID),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 锁定模式
|
|
|
|
|
|
if ownerpet == 0 {
|
|
|
|
|
|
return false, CaptureDetails{
|
|
|
|
|
|
Success: false,
|
|
|
|
|
|
Mode: "锁定模式",
|
|
|
|
|
|
BaseRate: 0,
|
|
|
|
|
|
ModifiedRate: 0,
|
|
|
|
|
|
GuaranteeBonus: 0,
|
2025-11-11 05:54:24 +00:00
|
|
|
|
StatusBonus: our.GetStatusBonus(),
|
2025-09-26 18:39:59 +00:00
|
|
|
|
Details: "已拥有数量为0,无法捕捉",
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 计算基础捕捉率
|
2025-11-11 05:54:24 +00:00
|
|
|
|
baseRate := our.calcBaseRate(pet, ItemID)
|
2026-04-08 01:28:55 +08:00
|
|
|
|
denominator := captureCtx.Denominator
|
2025-09-26 18:39:59 +00:00
|
|
|
|
numerator := int(baseRate * float64(denominator))
|
|
|
|
|
|
|
|
|
|
|
|
// 衰减模式
|
|
|
|
|
|
if ownerpet > 0 {
|
2026-04-08 01:28:55 +08:00
|
|
|
|
decay := math.Pow(1-captureCtx.DecayFactor, float64(ownerpet))
|
2025-09-26 18:39:59 +00:00
|
|
|
|
baseRate *= decay
|
|
|
|
|
|
if baseRate < 0.01 {
|
|
|
|
|
|
baseRate = 0.01 // 最低1%成功率
|
|
|
|
|
|
}
|
|
|
|
|
|
numerator = int(baseRate * float64(denominator))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 走统一保底判定
|
2026-04-08 01:28:55 +08:00
|
|
|
|
success, basePct, bonusPct := captureCtx.Roll(numerator, denominator)
|
2025-09-26 18:39:59 +00:00
|
|
|
|
|
|
|
|
|
|
return success, CaptureDetails{
|
|
|
|
|
|
Success: success,
|
|
|
|
|
|
Mode: map[int]string{-1: "保底模式", 0: "锁定模式", 1: "衰减模式"}[ownerpet],
|
|
|
|
|
|
BaseRate: basePct,
|
|
|
|
|
|
ModifiedRate: basePct + bonusPct,
|
|
|
|
|
|
GuaranteeBonus: bonusPct,
|
2025-11-11 05:54:24 +00:00
|
|
|
|
StatusBonus: our.GetStatusBonus(),
|
|
|
|
|
|
Details: fmt.Sprintf("a=%d, 分子=%d, 分母=%d", our.calcBaseA(pet, ItemID), numerator, denominator),
|
2025-09-26 18:39:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// calcBaseA 按公式计算a值
|
2025-11-11 05:54:24 +00:00
|
|
|
|
func (our *Input) calcBaseA(pet *info.BattlePetEntity, ItemID uint32) int {
|
2026-04-08 01:28:55 +08:00
|
|
|
|
captureCtx := our.Player.GetPlayerCaptureContext()
|
|
|
|
|
|
if captureCtx == nil {
|
|
|
|
|
|
captureCtx = info.NewPlayerCaptureContext()
|
|
|
|
|
|
}
|
2025-09-26 18:39:59 +00:00
|
|
|
|
catchRate := gconv.Int(pet.CatchRate)
|
2026-04-08 01:28:55 +08:00
|
|
|
|
catchRate = (catchRate * captureCtx.Denominator) / 1000 // 归一化到1000分母
|
2025-09-26 18:39:59 +00:00
|
|
|
|
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)
|
2025-11-11 05:54:24 +00:00
|
|
|
|
statusBonus := our.GetStatusBonus()
|
2025-09-26 18:39:59 +00:00
|
|
|
|
|
|
|
|
|
|
return int(hpRatio * float64(catchRate) * itemBonus * statusBonus)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// calcBaseRate 按公式计算基础成功率
|
2025-11-11 05:54:24 +00:00
|
|
|
|
func (our *Input) calcBaseRate(pet *info.BattlePetEntity, ItemID uint32) float64 {
|
2025-09-26 18:39:59 +00:00
|
|
|
|
if getItemBonus(ItemID) >= 255 {
|
|
|
|
|
|
return 1.0
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-11 05:54:24 +00:00
|
|
|
|
a := our.calcBaseA(pet, ItemID)
|
2025-09-26 18:39:59 +00:00
|
|
|
|
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)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-21 14:56:37 +00:00
|
|
|
|
// CaptureDetails 捕捉详情
|
|
|
|
|
|
type CaptureDetails struct {
|
|
|
|
|
|
Success bool
|
|
|
|
|
|
Mode string
|
|
|
|
|
|
BaseRate float64
|
|
|
|
|
|
ModifiedRate float64
|
|
|
|
|
|
GuaranteeBonus float64 // 百分比
|
|
|
|
|
|
StatusBonus float64 // 状态倍率
|
|
|
|
|
|
Details string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// func main() {
|
|
|
|
|
|
// ctx := NewPlayerCaptureContext()
|
|
|
|
|
|
// fmt.Println("=== 精灵捕捉系统测试(状态数组版) ===")
|
|
|
|
|
|
|
|
|
|
|
|
// // 测试1:不同异常状态组合
|
|
|
|
|
|
// fmt.Println("\n--- 异常状态测试 ---")
|
|
|
|
|
|
// // 无异常状态
|
|
|
|
|
|
// var noStatus [20]byte
|
|
|
|
|
|
// // 中毒状态
|
|
|
|
|
|
// var poisonStatus [20]byte
|
|
|
|
|
|
// poisonStatus[StatusPoison] = 1
|
|
|
|
|
|
// // 睡眠+冰冻状态(取最高倍率2.0)
|
|
|
|
|
|
// var multipleStatus [20]byte
|
|
|
|
|
|
// multipleStatus[StatusSleep] = 1
|
|
|
|
|
|
// multipleStatus[StatusFreeze] = 1
|
|
|
|
|
|
|
|
|
|
|
|
// statusTests := []struct {
|
|
|
|
|
|
// name string
|
|
|
|
|
|
// status [20]byte
|
|
|
|
|
|
// }{
|
|
|
|
|
|
// {"无异常状态", noStatus},
|
|
|
|
|
|
// {"中毒状态", poisonStatus},
|
|
|
|
|
|
// {"睡眠+冰冻状态", multipleStatus},
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// for _, test := range statusTests {
|
|
|
|
|
|
// params := CaptureParams{
|
|
|
|
|
|
// PetID: 1001,
|
|
|
|
|
|
// MaxHP: 100,
|
|
|
|
|
|
// CurrentHP: 10,
|
|
|
|
|
|
// CatchRate: 50,
|
|
|
|
|
|
// CatchDenom: 100,
|
|
|
|
|
|
// ItemID: 300001,
|
|
|
|
|
|
// Statuses: test.status,
|
|
|
|
|
|
// OwnedCount: -1,
|
|
|
|
|
|
// }
|
|
|
|
|
|
// _, details := ctx.Capture(params)
|
|
|
|
|
|
// fmt.Printf("%s: 状态倍率=%.1f | 基础成功率=%.2f%%\n",
|
|
|
|
|
|
// test.name, details.StatusBonus, details.BaseRate)
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// // 测试2:无敌胶囊
|
|
|
|
|
|
// fmt.Println("\n--- 无敌胶囊测试 ---")
|
|
|
|
|
|
// invincibleParams := CaptureParams{
|
|
|
|
|
|
// PetID: 9999,
|
|
|
|
|
|
// MaxHP: 1000,
|
|
|
|
|
|
// CurrentHP: 1000,
|
|
|
|
|
|
// CatchRate: 1,
|
|
|
|
|
|
// CatchDenom: 1000,
|
|
|
|
|
|
// ItemID: 300006,
|
|
|
|
|
|
// Statuses: noStatus,
|
|
|
|
|
|
// OwnedCount: -1,
|
|
|
|
|
|
// }
|
|
|
|
|
|
// success, details := ctx.Capture(invincibleParams)
|
|
|
|
|
|
// fmt.Printf("捕捉结果: %v | 模式: %s | 成功率: %.2f%%\n",
|
|
|
|
|
|
// success, details.Mode, details.ModifiedRate)
|
|
|
|
|
|
|
|
|
|
|
|
// // 测试3:锁定模式
|
|
|
|
|
|
// fmt.Println("\n--- 锁定模式测试 ---")
|
|
|
|
|
|
// lockParams := CaptureParams{
|
|
|
|
|
|
// PetID: 1002,
|
|
|
|
|
|
// MaxHP: 50,
|
|
|
|
|
|
// CurrentHP: 1,
|
|
|
|
|
|
// CatchRate: 100,
|
|
|
|
|
|
// CatchDenom: 100,
|
|
|
|
|
|
// ItemID: 300003,
|
|
|
|
|
|
// Statuses: poisonStatus,
|
|
|
|
|
|
// OwnedCount: 0,
|
|
|
|
|
|
// }
|
|
|
|
|
|
// success, details = ctx.Capture(lockParams)
|
|
|
|
|
|
// fmt.Printf("捕捉结果: %v | 模式: %s | 成功率: %.2f%%\n",
|
|
|
|
|
|
// success, details.Mode, details.ModifiedRate)
|
|
|
|
|
|
|
|
|
|
|
|
// // 测试4:衰减模式
|
|
|
|
|
|
// fmt.Println("\n--- 衰减模式测试 ---")
|
|
|
|
|
|
// decayParams := CaptureParams{
|
|
|
|
|
|
// PetID: 1003,
|
|
|
|
|
|
// MaxHP: 100,
|
|
|
|
|
|
// CurrentHP: 10,
|
|
|
|
|
|
// CatchRate: 50,
|
|
|
|
|
|
// CatchDenom: 100,
|
|
|
|
|
|
// ItemID: 300002,
|
|
|
|
|
|
// Statuses: multipleStatus,
|
|
|
|
|
|
// OwnedCount: 1,
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// for i := 1; i <= 5; i++ {
|
|
|
|
|
|
// decayParams.OwnedCount = i
|
|
|
|
|
|
// success, details := ctx.Capture(decayParams)
|
|
|
|
|
|
// fmt.Printf("拥有%d只 - 结果: %v | 基础成功率: %.2f%% | 实际成功率: %.2f%%\n",
|
|
|
|
|
|
// i, success, details.BaseRate, details.ModifiedRate)
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|