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} ret.Effects = utils.NewOrderedMap[int, Effect]() t := Geteffect(EffectType.Damage, 0) ret.AddEffect(t) //添加默认基类,实现继承 p.SetFightC(c) //给玩家设置战斗容器 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 := Geteffect(EffectType.Status, statusIdx) // 检查状态是否存在(数组中值为1表示存在该状态) if t.Effect.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) }