```
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful

fix(fight): 修复单输入战斗中效果处理逻辑错误

- 在Effect201的OnSkill方法中调整了多输入战斗检查的位置,
  确保单输入战斗中的单目标效果被正确忽略

- 添加了针对单输入战斗中单目标效果的测试用例

- 移除了重复的多输入战斗检查代码

feat(fight): 添加战斗初始化时捕获标识
This commit is contained in:
昔念
2026-04-13 09:59:09 +08:00
parent e1a994ba11
commit e161e3626f
7 changed files with 84 additions and 7 deletions

View File

@@ -83,6 +83,10 @@ func (e *Effect201) OnSkill() bool {
return true
}
if !carrier.IsMultiInputBattle() {
return true
}
divisorIndex := len(args) - 1
if len(args) > 1 {
divisorIndex = 1
@@ -110,10 +114,6 @@ func (e *Effect201) OnSkill() bool {
return true
}
if !carrier.IsMultiInputBattle() {
return true
}
team := carrier.Team
if len(team) == 0 {
team = []*input.Input{carrier}

View File

@@ -42,6 +42,27 @@ func TestEffect201HealAllIgnoredInSingleInputBattle(t *testing.T) {
}
}
func TestEffect201SingleTargetIgnoredInSingleInputBattle(t *testing.T) {
carrier := newEffect201TestInput(40, 100)
opponent := newEffect201TestInput(60, 100)
carrier.Team = []*input.Input{carrier}
carrier.OppTeam = []*input.Input{opponent}
eff := &Effect201{}
eff.SetArgs(carrier, 2)
eff.EffectNode.EffectContextHolder.Ctx = input.Ctx{
LegacySides: input.LegacySides{Our: carrier, Opp: opponent},
EffectBinding: input.EffectBinding{Carrier: carrier, Source: carrier},
}
if !eff.OnSkill() {
t.Fatalf("expected effect to finish successfully")
}
if got := carrier.CurrentPet().Info.Hp; got != 40 {
t.Fatalf("expected single-input single-target heal to be ignored, got hp %d", got)
}
}
func TestEffect201HealAllWorksInMultiInputBattle(t *testing.T) {
carrier := newEffect201TestInput(40, 100)
ally := newEffect201TestInput(10, 80)

View File

@@ -484,6 +484,9 @@ func initfightready(in *input.Input) (model.FightUserInfo, []model.ReadyFightPet
if err != nil {
panic(err)
}
if i == 0 && in.CanCapture > 0 {
t[i].IsCapture = uint32(in.CanCapture)
}
}
return userindo, t

View File

@@ -297,9 +297,6 @@ func buildFight(opts *fightBuildOptions) (*FightC, errorcode.ErrorCode) {
f.bindInputFightContext(f.Our, f.Opp)
f.linkTeamViews()
f.ReadyInfo.OurInfo, f.ReadyInfo.OurPetList = initfightready(f.primaryOur())
f.ReadyInfo.OpponentInfo, f.ReadyInfo.OpponentPetList = initfightready(f.primaryOpp())
loadtime := 120 * time.Second
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC {
if opp := f.primaryOpp(); opp != nil {
@@ -313,6 +310,9 @@ func buildFight(opts *fightBuildOptions) (*FightC, errorcode.ErrorCode) {
}
}
}
f.ReadyInfo.OurInfo, f.ReadyInfo.OurPetList = initfightready(f.primaryOur())
f.ReadyInfo.OpponentInfo, f.ReadyInfo.OpponentPetList = initfightready(f.primaryOpp())
f.FightStartOutboundInfo = f.buildFightStartInfo()
f.BroadcastPlayers(func(p common.PlayerI) {

View File

@@ -51,6 +51,9 @@ func (p *Player) IsMatch(t configmodel.Event) bool {
if len(p.Info.PetList) == 0 {
return false
}
if p.Info.PetList[0].Hp == 0 {
return false
}
firstPetID := int32(p.Info.PetList[0].ID)
_, ok := lo.Find(t.FirstSprites, func(item int32) bool {

View File

@@ -0,0 +1,49 @@
package player
import (
configmodel "blazing/modules/config/model"
playermodel "blazing/modules/player/model"
"testing"
)
func TestIsMatchFirstSpritesRequiresLivingLeadPet(t *testing.T) {
player := &Player{
baseplayer: baseplayer{
Info: &playermodel.PlayerInfo{
PetList: []playermodel.PetInfo{
{ID: 1001, Hp: 0},
{ID: 2002, Hp: 100},
},
},
},
}
event := configmodel.Event{
FirstSprites: []int32{1001},
}
if player.IsMatch(event) {
t.Fatalf("expected dead lead pet to fail FirstSprites match")
}
}
func TestIsMatchFirstSpritesAcceptsLivingLeadPet(t *testing.T) {
player := &Player{
baseplayer: baseplayer{
Info: &playermodel.PlayerInfo{
PetList: []playermodel.PetInfo{
{ID: 1001, Hp: 100},
{ID: 2002, Hp: 100},
},
},
},
}
event := configmodel.Event{
FirstSprites: []int32{1001},
}
if !player.IsMatch(event) {
t.Fatalf("expected living lead pet to pass FirstSprites match")
}
}