lawless/server/internal/battle/ai.go

82 行
1.8 KiB
Go

package battle
import (
"math/rand"
"sort"
)
// DefaultNormalAttack 返回普通攻击兜底技能
func DefaultNormalAttack(f *Fighter) *SkillInstance {
elem := f.Element
if elem == "" {
elem = "none"
}
return &SkillInstance{
InstanceID: "normal_attack",
SkillID: "normal_attack",
Name: "普通攻击",
DamageType: DamageTypePhysical,
Element: elem,
Alignment: f.Alignment,
ScalingAttr: "str",
BaseCoef: cfgFloat("combat.skill.normal_attack_coef", 1.0),
CD: 0,
Cost: 0,
TriggerRate: 1.0,
TargetType: TargetSingle,
}
}
// SelectSkill 按 GDD-03 ✅24 触发率机制选择技能
// 1. 候选池 = CD=0 且内力够的主动技能
// 2. 触发率 ≥100% 的候选必定释放,取最高者
// 3. 否则对每个候选独立掷骰,命中者取触发率最高者
// 4. 全部未命中或候选池为空则普通攻击
func SelectSkill(actor *Fighter, opponent *Fighter, normal *SkillInstance, rng *rand.Rand) *SkillInstance {
candidates := make([]*SkillInstance, 0, len(actor.Skills))
for _, s := range actor.Skills {
if s == nil {
continue
}
if s.CDRemaining <= 0 && actor.CanSpendMana(s.Cost) {
candidates = append(candidates, s)
}
}
if len(candidates) == 0 {
return normal
}
// 按触发率降序
sort.Slice(candidates, func(i, j int) bool {
return candidates[i].TriggerRate > candidates[j].TriggerRate
})
// 必发技能
if candidates[0].TriggerRate >= 1.0 {
return candidates[0]
}
// 独立掷骰
var best *SkillInstance
bestRate := 0.0
for _, s := range candidates {
rate := s.TriggerRate
if rate <= 0 {
continue
}
if rate > 1.0 {
rate = 1.0
}
if rng.Float64() < rate {
if best == nil || s.TriggerRate > bestRate {
best = s
bestRate = s.TriggerRate
}
}
}
if best != nil {
return best
}
return normal
}