refactor: 重构战斗方法调用方式

将战斗控制器的方法调用重构为直接在玩家接口上调用,
以简化代码结构并消除对 FightC 的直接依赖。
This commit is contained in:
xinian
2026-04-29 03:39:21 +08:00
parent 596d4024cc
commit 6c76b050b3
24 changed files with 248 additions and 83 deletions

View File

@@ -12,17 +12,15 @@ import (
// 进入超时空隧道 // 进入超时空隧道
func (h Controller) TimeMap(data *C2s_SP, c *player.Player) (result *S2C_SP, err errorcode.ErrorCode) { func (h Controller) TimeMap(data *C2s_SP, c *player.Player) (result *S2C_SP, err errorcode.ErrorCode) {
result = &S2C_SP{} result = &S2C_SP{}
mapPitService := service.NewMapPitService()
maps := service.NewMapService().GetTimeMap() maps := service.NewMapService().GetTimeMap()
result.MapList = make([]ServerInfo, len(maps)) result.MapList = make([]ServerInfo, len(maps))
for i, v := range maps { for i, mapInfo := range maps {
result.MapList[i].ID = v.MapID result.MapList[i].ID = mapInfo.MapID
result.MapList[i].DropItemIds = v.DropItemIds result.MapList[i].DropItemIds = mapInfo.DropItemIds
pits := service.NewMapPitService().GetDataALL(v.MapID) pits := mapPitService.GetDataALL(mapInfo.MapID)
for _, pit := range pits {
for _, v := range pits { result.MapList[i].Pet = append(result.MapList[i].Pet, pit.RefreshID...)
result.MapList[i].Pet = append(result.MapList[i].Pet, v.RefreshID...)
} }
result.MapList[i].Pet = lo.Union(result.MapList[i].Pet) result.MapList[i].Pet = lo.Union(result.MapList[i].Pet)
} }

View File

@@ -24,7 +24,7 @@ func (h Controller) OnReadyToFight(data *ReadyToFightInboundInfo, c *player.Play
if h.relayRemoteFightCommand(c, data.Head.CMD, data) { if h.relayRemoteFightCommand(c, data.Head.CMD, data) {
return nil, -1 return nil, -1
} }
go c.FightC.ReadyFight(c) go c.ReadyFight()
return nil, -1 return nil, -1
} }
@@ -36,7 +36,7 @@ func (h Controller) GroupReadyFightFinish(data *GroupReadyFightFinishInboundInfo
if h.relayRemoteFightCommand(c, data.Head.CMD, data) { if h.relayRemoteFightCommand(c, data.Head.CMD, data) {
return nil, -1 return nil, -1
} }
go c.FightC.ReadyFight(c) go c.ReadyFight()
return nil, -1 return nil, -1
} }
@@ -162,11 +162,11 @@ func (h Controller) Capture(data *CatchMonsterInboundInfo, c *player.Player) (re
} }
if c.GetSpace().IsTime { if c.GetSpace().IsTime {
if data.CapsuleId < 300009 { if data.CapsuleId < 300009 {
go c.FightC.UseSkill(c, 0) go c.UseSkill(0)
return nil, -1 return nil, -1
} }
} }
go c.FightC.Capture(c, data.CapsuleId) go c.Capture(data.CapsuleId)
return nil, -1 return nil, -1
} }
@@ -178,7 +178,7 @@ func (h Controller) LoadPercent(data *LoadPercentInboundInfo, c *player.Player)
if h.relayRemoteFightCommand(c, data.Head.CMD, data) { if h.relayRemoteFightCommand(c, data.Head.CMD, data) {
return nil, -1 return nil, -1
} }
go c.FightC.LoadPercent(c, int32(data.Percent)) go c.LoadPercent(int32(data.Percent))
return nil, -1 return nil, -1
} }
@@ -192,7 +192,7 @@ func (h Controller) UsePetItemInboundInfo(data *UsePetItemInboundInfo, c *player
} }
if c.GetSpace().IsTime { if c.GetSpace().IsTime {
if data.ItemId < 300009 { if data.ItemId < 300009 {
go c.FightC.UseSkill(c, 0) go c.UseSkill(0)
} }
} }

View File

@@ -27,15 +27,15 @@ func (h Controller) dispatchFightActionEnvelope(c *player.Player, envelope fight
switch envelope.ActionType { switch envelope.ActionType {
case fight.FightActionTypeSkill: case fight.FightActionTypeSkill:
go c.FightC.UseSkillAt(c, envelope.SkillID, envelope.ActorIndex, envelope.EncodedTargetIndex()) go c.UseSkillAt(envelope.SkillID, envelope.ActorIndex, envelope.EncodedTargetIndex())
case fight.FightActionTypeItem: case fight.FightActionTypeItem:
go c.FightC.UseItemAt(c, envelope.CatchTime, envelope.ItemID, envelope.ActorIndex, envelope.EncodedTargetIndex()) go c.UseItemAt(envelope.CatchTime, envelope.ItemID, envelope.ActorIndex, envelope.EncodedTargetIndex())
case fight.FightActionTypeChange: case fight.FightActionTypeChange:
go c.FightC.ChangePetAt(c, envelope.CatchTime, envelope.ActorIndex) go c.ChangePetAt(envelope.CatchTime, envelope.ActorIndex)
case fight.FightActionTypeEscape: case fight.FightActionTypeEscape:
go c.FightC.Over(c, model.BattleOverReason.PlayerEscape) go c.Over(model.BattleOverReason.PlayerEscape)
case fight.FightActionTypeChat: case fight.FightActionTypeChat:
go c.FightC.Chat(c, envelope.Chat) go c.Chat(envelope.Chat)
} }
} }

View File

@@ -58,13 +58,7 @@ func (h Controller) UsePetItemOutOfFight(data *C2S_USE_PET_ITEM_OUT_OF_FIGHT, c
return nil, errcode return nil, errcode
} }
refreshPetPaneKeepHP(currentPet, oldHP) refreshPetPaneKeepHP(currentPet, oldHP)
if err := c.Service.Item.UPDATE(itemID, -1); err != nil { return finishUsePetItemOutOfFight(c, itemID, currentPet)
return nil, errorcode.ErrorCodes.ErrInsufficientItems
}
c.Service.Info.Save(*c.Info)
result = &item.S2C_USE_PET_ITEM_OUT_OF_FIGHT{}
copier.Copy(&result, currentPet)
return result, 0
} }
var errcode errorcode.ErrorCode var errcode errorcode.ErrorCode
@@ -93,11 +87,15 @@ func (h Controller) UsePetItemOutOfFight(data *C2S_USE_PET_ITEM_OUT_OF_FIGHT, c
return nil, errcode return nil, errcode
} }
return finishUsePetItemOutOfFight(c, itemID, currentPet)
}
func finishUsePetItemOutOfFight(c *player.Player, itemID uint32, currentPet *model.PetInfo) (*item.S2C_USE_PET_ITEM_OUT_OF_FIGHT, errorcode.ErrorCode) {
if err := c.Service.Item.UPDATE(itemID, -1); err != nil { if err := c.Service.Item.UPDATE(itemID, -1); err != nil {
return nil, errorcode.ErrorCodes.ErrInsufficientItems return nil, errorcode.ErrorCodes.ErrInsufficientItems
} }
c.Service.Info.Save(*c.Info) c.Service.Info.Save(*c.Info)
result = &item.S2C_USE_PET_ITEM_OUT_OF_FIGHT{} result := &item.S2C_USE_PET_ITEM_OUT_OF_FIGHT{}
copier.Copy(&result, currentPet) copier.Copy(&result, currentPet)
return result, 0 return result, 0
} }
@@ -124,22 +122,27 @@ func (h Controller) handleNeuronItem(currentPet *model.PetInfo, c *player.Player
// 炫彩碎片 处理神300212 // 炫彩碎片 处理神300212
func (h Controller) handlexuancaiItem(currentPet *model.PetInfo, c *player.Player) errorcode.ErrorCode { func (h Controller) handlexuancaiItem(currentPet *model.PetInfo, c *player.Player) errorcode.ErrorCode {
r, _ := element.Calculator.GetCombination(int(xmlres.PetMAP[int(currentPet.ID)].Type)) petCfg, ok := xmlres.PetMAP[int(currentPet.ID)]
if !ok {
return errorcode.ErrorCodes.ErrSystemError
}
r, _ := element.Calculator.GetCombination(int(petCfg.Type))
if r.Secondary != nil { if r.Secondary != nil {
return errorcode.ErrorCodes.ErrItemUnusable return errorcode.ErrorCodes.ErrItemUnusable
} }
itemid := uint32(currentPet.Type()) + 400686 shardItemID := uint32(currentPet.Type()) + 400686
items := c.Service.Item.CheakItem(itemid) items := c.Service.Item.CheakItem(shardItemID)
if items < 100 { if items < 100 {
return errorcode.ErrorCodes.ErrInsufficientItems return errorcode.ErrorCodes.ErrInsufficientItems
} }
ok := currentPet.FixShiny() ok = currentPet.FixShiny()
if !ok { if !ok {
return errorcode.ErrorCodes.ErrItemUnusable return errorcode.ErrorCodes.ErrItemUnusable
} }
if err := c.Service.Item.UPDATE(itemid, -100); err != nil { if err := c.Service.Item.UPDATE(shardItemID, -100); err != nil {
return errorcode.ErrorCodes.ErrInsufficientItems return errorcode.ErrorCodes.ErrInsufficientItems
} }
return 0 return 0

View File

@@ -40,7 +40,7 @@ func (ctl Controller) GetBreedPet(
} }
result = &pet.S2C_GET_BREED_PET{} result = &pet.S2C_GET_BREED_PET{}
compatibleFemaleIDs := buildBreedPetIDSet(service.NewEggService().GetData(malePet.ID)) compatibleFemaleIDs := buildBreedPetIDSet(breedConfigService.GetData(malePet.ID))
if len(compatibleFemaleIDs) == 0 { if len(compatibleFemaleIDs) == 0 {
return result, 0 return result, 0
} }
@@ -116,8 +116,12 @@ func buildBreedPetIDSet(ids []int32) map[uint32]struct{} {
} }
func canBreedPair(maleID, femaleID uint32) bool { func canBreedPair(maleID, femaleID uint32) bool {
_, ok := buildBreedPetIDSet(service.NewEggService().GetData(maleID))[femaleID] for _, id := range breedConfigService.GetData(maleID) {
return ok if uint32(id) == femaleID {
return true
}
}
return false
} }
// GetEggList 处理控制器请求。 // GetEggList 处理控制器请求。
@@ -144,7 +148,10 @@ const (
breedCost = 1000 breedCost = 1000
) )
var limiter *ratelimit.Rule = ratelimit.NewRule() var (
breedConfigService = service.NewEggService()
limiter = ratelimit.NewRule()
)
// 简单规则案例 // 简单规则案例
func init() { func init() {

View File

@@ -18,10 +18,9 @@ import (
// 返回: 基地家具信息和错误码 // 返回: 基地家具信息和错误码
func (h Controller) GetFitmentUsing(data *FitmentUseringInboundInfo, c *player.Player) (result *room.FitmentUseringOutboundInfo, err errorcode.ErrorCode) { func (h Controller) GetFitmentUsing(data *FitmentUseringInboundInfo, c *player.Player) (result *room.FitmentUseringOutboundInfo, err errorcode.ErrorCode) {
result = &room.FitmentUseringOutboundInfo{UserId: c.Info.UserID, RoomId: data.TargetUserID} result = &room.FitmentUseringOutboundInfo{UserId: c.Info.UserID, RoomId: data.TargetUserID}
result.Fitments = make([]model.FitmentShowInfo, 0)
result.Fitments = append(result.Fitments, model.FitmentShowInfo{Id: 500001, Status: 1, X: 1, Y: 1, Dir: 1})
roomInfo := c.Service.Room.Get(data.TargetUserID) roomInfo := c.Service.Room.Get(data.TargetUserID)
result.Fitments = make([]model.FitmentShowInfo, 0, len(roomInfo.PlacedItems)+1)
result.Fitments = append(result.Fitments, model.FitmentShowInfo{Id: 500001, Status: 1, X: 1, Y: 1, Dir: 1})
result.Fitments = append(result.Fitments, roomInfo.PlacedItems...) result.Fitments = append(result.Fitments, roomInfo.PlacedItems...)
return return
} }
@@ -32,8 +31,8 @@ func (h Controller) GetFitmentUsing(data *FitmentUseringInboundInfo, c *player.P
// 返回: 精灵展示列表和错误码 // 返回: 精灵展示列表和错误码
func (h Controller) GetRoomPetShowInfo(data *PetRoomListInboundInfo, c *player.Player) (result *room.PetRoomListOutboundInfo, err errorcode.ErrorCode) { func (h Controller) GetRoomPetShowInfo(data *PetRoomListInboundInfo, c *player.Player) (result *room.PetRoomListOutboundInfo, err errorcode.ErrorCode) {
result = &room.PetRoomListOutboundInfo{} result = &room.PetRoomListOutboundInfo{}
result.Pets = make([]pet.PetShortInfo, 0)
showPets := service.NewPetService(data.TargetUserID).GetShowPets() showPets := service.NewPetService(data.TargetUserID).GetShowPets()
result.Pets = make([]pet.PetShortInfo, 0, len(showPets))
for i := range showPets { for i := range showPets {
var petShortInfo pet.PetShortInfo var petShortInfo pet.PetShortInfo
copier.Copy(&petShortInfo, &showPets[i].Data) copier.Copy(&petShortInfo, &showPets[i].Data)
@@ -45,7 +44,6 @@ func (h Controller) GetRoomPetShowInfo(data *PetRoomListInboundInfo, c *player.P
// SetRoomPetShowInfo 设置基地展示精灵并返回最新展示列表cmd:2323 // SetRoomPetShowInfo 设置基地展示精灵并返回最新展示列表cmd:2323
func (h Controller) SetRoomPetShowInfo(data *C2S_PET_ROOM_SHOW, c *player.Player) (result *room.S2C_PET_ROOM_SHOW, err errorcode.ErrorCode) { func (h Controller) SetRoomPetShowInfo(data *C2S_PET_ROOM_SHOW, c *player.Player) (result *room.S2C_PET_ROOM_SHOW, err errorcode.ErrorCode) {
result = &room.S2C_PET_ROOM_SHOW{} result = &room.S2C_PET_ROOM_SHOW{}
result.PetShowList = make([]pet.PetShortInfo, 0)
catchTimes := make([]uint32, 0, len(data.PetShowList)) catchTimes := make([]uint32, 0, len(data.PetShowList))
seen := make(map[uint32]struct{}, len(data.PetShowList)) seen := make(map[uint32]struct{}, len(data.PetShowList))
@@ -68,6 +66,7 @@ func (h Controller) SetRoomPetShowInfo(data *C2S_PET_ROOM_SHOW, c *player.Player
} }
showPets := petSvc.GetShowPets() showPets := petSvc.GetShowPets()
result.PetShowList = make([]pet.PetShortInfo, 0, len(showPets))
for i := range showPets { for i := range showPets {
var petShortInfo pet.PetShortInfo var petShortInfo pet.PetShortInfo
copier.Copy(&petShortInfo, &showPets[i].Data) copier.Copy(&petShortInfo, &showPets[i].Data)
@@ -82,10 +81,10 @@ func (h Controller) SetRoomPetShowInfo(data *C2S_PET_ROOM_SHOW, c *player.Player
// 返回: 玩家所有家具列表和错误码 // 返回: 玩家所有家具列表和错误码
func (h Controller) GetAllFurniture(data *FitmentAllInboundEmpty, c *player.Player) (result *room.FitmentAllOutboundInfo, err errorcode.ErrorCode) { func (h Controller) GetAllFurniture(data *FitmentAllInboundEmpty, c *player.Player) (result *room.FitmentAllOutboundInfo, err errorcode.ErrorCode) {
result = &room.FitmentAllOutboundInfo{} result = &room.FitmentAllOutboundInfo{}
result.Fitments = make([]room.FitmentItemInfo, 0)
items := c.Service.Item.Get(500000, 600000) items := c.Service.Item.Get(500000, 600000)
roomData := c.Service.Room.Get(c.Info.UserID) roomData := c.Service.Room.Get(c.Info.UserID)
result.Fitments = make([]room.FitmentItemInfo, 0, len(items))
for _, item := range items { for _, item := range items {
var itemInfo room.FitmentItemInfo var itemInfo room.FitmentItemInfo
itemInfo.Id = item.ItemId itemInfo.Id = item.ItemId

View File

@@ -23,4 +23,19 @@ type PlayerI interface {
CanFight() errorcode.ErrorCode CanFight() errorcode.ErrorCode
SendPackCmd(uint32, any) SendPackCmd(uint32, any)
GetPetInfo(limitlevel uint32) []model.PetInfo GetPetInfo(limitlevel uint32) []model.PetInfo
Over(model.EnumBattleOverReason)
UseSkill(uint32)
UseSkillAt(uint32, int, int)
GetCurrPET() *info.BattlePetEntity
GetCurrPETAt(int) *info.BattlePetEntity
ReadyFight()
ChangePet(uint32)
ChangePetAt(uint32, int)
Capture(uint32)
LoadPercent(int32)
UseItem(uint32, uint32)
UseItemAt(uint32, uint32, int, int)
Chat(string)
IsFirst() bool
} }

View File

@@ -17,7 +17,7 @@ func (e *NewSel13) HookAction() bool {
} }
r := e.Ctx().Our.FightC.GetOverInfo() r := e.Ctx().Our.FightC.GetOverInfo()
if r.Round == uint32(e.Args()[0].IntPart()) { if r.Round == uint32(e.Args()[0].IntPart()) {
e.Ctx().Our.FightC.Over(e.Ctx().Our.Player, model.BattleOverReason.PlayerEscape) e.Ctx().Our.Player.Over(model.BattleOverReason.PlayerEscape)
return false //阻止技能释放 return false //阻止技能释放
} }

View File

@@ -94,7 +94,7 @@ func (e *Effect1395) SkillHit() bool {
if e.Ctx().SkillEntity == nil || e.Ctx().SkillEntity.Category() == info.Category.STATUS { if e.Ctx().SkillEntity == nil || e.Ctx().SkillEntity.Category() == info.Category.STATUS {
return true return true
} }
if !e.Ctx().Our.FightC.IsFirst(e.Ctx().Our.Player) { if !e.Ctx().Our.Player.IsFirst() {
return true return true
} }

View File

@@ -185,7 +185,7 @@ func (e *Effect1527) SkillHit() bool {
if e.Ctx().Our == nil || e.Ctx().Our.FightC == nil { if e.Ctx().Our == nil || e.Ctx().Our.FightC == nil {
return true return true
} }
if e.Ctx().Our.FightC.IsFirst(e.Ctx().Our.Player) { if e.Ctx().Our.Player.IsFirst() {
return true return true
} }

View File

@@ -27,7 +27,7 @@ type Effect116 struct {
func (e *Effect116) Skill_Use() bool { func (e *Effect116) Skill_Use() bool {
if e.Input.FightC.IsFirst(e.Input.Player) { if e.Input.Player.IsFirst() {
e.Ctx().Our.Heal(e.Ctx().Our, &action.SelectSkillAction{}, e.Ctx().Our.SumDamage.Div(alpacadecimal.NewFromInt(5))) e.Ctx().Our.Heal(e.Ctx().Our, &action.SelectSkillAction{}, e.Ctx().Our.SumDamage.Div(alpacadecimal.NewFromInt(5)))
} }

View File

@@ -27,7 +27,7 @@ type Effect117 struct {
func (e *Effect117) OnSkill() bool { func (e *Effect117) OnSkill() bool {
if e.Input.FightC.IsFirst(e.Input.Player) { if e.Input.Player.IsFirst() {
// 概率判定 // 概率判定
ok, _, _ := e.Input.Player.Roll(e.EffectNode.SideEffectArgs[1], 100) ok, _, _ := e.Input.Player.Roll(e.EffectNode.SideEffectArgs[1], 100)
if !ok { if !ok {

View File

@@ -27,7 +27,7 @@ func (e *Effect52) SkillHit_ex() bool {
return true return true
} }
if !e.Input.FightC.IsFirst(e.Ctx().Our.Player) { if !e.Ctx().Our.Player.IsFirst() {
return true return true
} }
e.Ctx().SkillEntity.SetMiss() e.Ctx().SkillEntity.SetMiss()

View File

@@ -61,7 +61,7 @@ func (e *Effect726) SkillHit_ex() bool {
if skill == nil || skill.Category() == info.Category.STATUS { if skill == nil || skill.Category() == info.Category.STATUS {
return true return true
} }
if !e.Ctx().Opp.FightC.IsFirst(e.Ctx().Opp.Player) { if !e.Ctx().Opp.Player.IsFirst() {
return true return true
} }

View File

@@ -44,10 +44,10 @@ func init() {
return o.CurPet[0].Info.Hp < (o.CurPet[0].Info.MaxHp / 2) return o.CurPet[0].Info.Hp < (o.CurPet[0].Info.MaxHp / 2)
}) })
registerStatusFunc(30, func(i, o *input.Input) bool { registerStatusFunc(30, func(i, o *input.Input) bool {
return !i.FightC.IsFirst(i.Player) return !i.Player.IsFirst()
}) })
registerStatusFunc(40, func(i, o *input.Input) bool { registerStatusFunc(40, func(i, o *input.Input) bool {
return i.FightC.IsFirst(i.Player) return i.Player.IsFirst()
}) })
registerStatusFunc(64, func(i, o *input.Input) bool { registerStatusFunc(64, func(i, o *input.Input) bool {
if i.StatEffect_Exist(info.PetStatus.Burned) { if i.StatEffect_Exist(info.PetStatus.Burned) {

View File

@@ -45,14 +45,14 @@ func (our *Input) GetAction() {
return return
} }
selfPet := our.FightC.GetCurrPETAt(our.Player, actorIndex) selfPet := our.Player.GetCurrPETAt(actorIndex)
if selfPet == nil { if selfPet == nil {
return return
} }
if selfPet.Info.Hp <= 0 { if selfPet.Info.Hp <= 0 {
for _, v := range our.AllPet { for _, v := range our.AllPet {
if v.Info.Hp > 0 { if v.Info.Hp > 0 {
our.FightC.ChangePetAt(our.Player, v.Info.CatchTime, actorIndex) our.Player.ChangePetAt(v.Info.CatchTime, actorIndex)
return return
} }
} }
@@ -106,9 +106,9 @@ func (our *Input) GetAction() {
} }
if usedskill != nil { if usedskill != nil {
our.FightC.UseSkillAt(our.Player, uint32(usedskill.XML.ID), actorIndex, targetIndex) our.Player.UseSkillAt(uint32(usedskill.XML.ID), actorIndex, targetIndex)
} else { } else {
our.FightC.UseSkillAt(our.Player, 0, actorIndex, targetIndex) our.Player.UseSkillAt(0, actorIndex, targetIndex)
} }
} }
@@ -132,7 +132,7 @@ func buildBossHookActionContext(our, opponent *Input, hookAction bool) *configmo
overInfo := our.FightC.GetOverInfo() overInfo := our.FightC.GetOverInfo()
ctx.Round = overInfo.Round ctx.Round = overInfo.Round
ctx.IsFirst = our.FightC.IsFirst(our.Player) ctx.IsFirst = our.Player.IsFirst()
if selfPet := our.CurrentPet(); selfPet != nil { if selfPet := our.CurrentPet(); selfPet != nil {
ctx.Our = &configmodel.BossHookPetContext{ ctx.Our = &configmodel.BossHookPetContext{
@@ -211,10 +211,10 @@ func applyBossScriptAction(our *Input, ctx *configmodel.BossHookActionContext, a
case "", "auto": case "", "auto":
return false return false
case "skill", "use_skill", "useskill": case "skill", "use_skill", "useskill":
our.FightC.UseSkillAt(our.Player, ctx.SkillID, actorIndex, targetIndex) our.Player.UseSkillAt(ctx.SkillID, actorIndex, targetIndex)
return true return true
case "switch", "change_pet", "changepet": case "switch", "change_pet", "changepet":
our.FightC.ChangePetAt(our.Player, ctx.CatchTime, actorIndex) our.Player.ChangePetAt(ctx.CatchTime, actorIndex)
return true return true
default: default:
return false return false

View File

@@ -27,11 +27,11 @@ func (our *Input) CalculateCrit(opp *Input, skill *info.SkillEntity) {
CritRate := utils.Max(skill.XML.CritRate, 1) CritRate := utils.Max(skill.XML.CritRate, 1)
//CritAtkFirst: 先出手时必定致命一击; 默认: 0 //CritAtkFirst: 先出手时必定致命一击; 默认: 0
if skill.XML.CritAtkFirst != 0 && our.FightC.IsFirst(our.Player) { if skill.XML.CritAtkFirst != 0 && our.Player.IsFirst() {
CritRate = 16 CritRate = 16
} }
//CritAtkSecond: 后出手时必定致命一击; 默认: 0 //CritAtkSecond: 后出手时必定致命一击; 默认: 0
if skill.XML.CritAtkSecond != 0 && !our.FightC.IsFirst(our.Player) { if skill.XML.CritAtkSecond != 0 && !our.Player.IsFirst() {
CritRate = 16 CritRate = 16
} }
// CritSelfHalfHp: 自身体力低于一半时必定致命一击; 默认: 0 // CritSelfHalfHp: 自身体力低于一半时必定致命一击; 默认: 0

View File

@@ -28,6 +28,20 @@ func (p *teamTestPlayer) MessWin(bool)
func (p *teamTestPlayer) CanFight() errorcode.ErrorCode { return 0 } func (p *teamTestPlayer) CanFight() errorcode.ErrorCode { return 0 }
func (p *teamTestPlayer) SendPackCmd(uint32, any) {} func (p *teamTestPlayer) SendPackCmd(uint32, any) {}
func (p *teamTestPlayer) GetPetInfo(uint32) []model.PetInfo { return nil } func (p *teamTestPlayer) GetPetInfo(uint32) []model.PetInfo { return nil }
func (p *teamTestPlayer) Over(model.EnumBattleOverReason) {}
func (p *teamTestPlayer) UseSkill(uint32) {}
func (p *teamTestPlayer) UseSkillAt(uint32, int, int) {}
func (p *teamTestPlayer) GetCurrPET() *fightinfo.BattlePetEntity { return nil }
func (p *teamTestPlayer) GetCurrPETAt(int) *fightinfo.BattlePetEntity { return nil }
func (p *teamTestPlayer) ReadyFight() {}
func (p *teamTestPlayer) ChangePet(uint32) {}
func (p *teamTestPlayer) ChangePetAt(uint32, int) {}
func (p *teamTestPlayer) Capture(uint32) {}
func (p *teamTestPlayer) LoadPercent(int32) {}
func (p *teamTestPlayer) UseItem(uint32, uint32) {}
func (p *teamTestPlayer) UseItemAt(uint32, uint32, int, int) {}
func (p *teamTestPlayer) Chat(string) {}
func (p *teamTestPlayer) IsFirst() bool { return false }
func TestLivingTeammatesFiltersSelfAndDeadSlots(t *testing.T) { func TestLivingTeammatesFiltersSelfAndDeadSlots(t *testing.T) {
owner := &Input{CurPet: []*fightinfo.BattlePetEntity{{Info: model.PetInfo{Hp: 10}}}} owner := &Input{CurPet: []*fightinfo.BattlePetEntity{{Info: model.PetInfo{Hp: 10}}}}

View File

@@ -483,28 +483,29 @@ func (m *manager) handleBattleCommand(payload pvpwire.BattleCommandPayload) {
if proxy == nil { if proxy == nil {
proxy = player.NewRPCPlayer(&model.PlayerInfo{UserID: payload.UserID}, 0, fightinfo.Fightinfo{}, payload.SessionID) proxy = player.NewRPCPlayer(&model.PlayerInfo{UserID: payload.UserID}, 0, fightinfo.Fightinfo{}, payload.SessionID)
} }
proxy.SetFightC(fightController)
switch payload.Command { switch payload.Command {
case pvpwire.CommandReady: case pvpwire.CommandReady:
go fightController.ReadyFight(proxy) go proxy.ReadyFight()
case pvpwire.CommandUseSkill: case pvpwire.CommandUseSkill:
go fightController.UseSkill(proxy, payload.SkillID) go proxy.UseSkill(payload.SkillID)
case pvpwire.CommandUseSkillAt: case pvpwire.CommandUseSkillAt:
go fightController.UseSkillAt(proxy, payload.SkillID, payload.ActorIndex, payload.TargetIndex) go proxy.UseSkillAt(payload.SkillID, payload.ActorIndex, payload.TargetIndex)
case pvpwire.CommandEscape: case pvpwire.CommandEscape:
go fightController.Over(proxy, model.EnumBattleOverReason(payload.Reason)) go proxy.Over(model.EnumBattleOverReason(payload.Reason))
case pvpwire.CommandChangePet: case pvpwire.CommandChangePet:
go fightController.ChangePet(proxy, payload.CatchTime) go proxy.ChangePet(payload.CatchTime)
case pvpwire.CommandChangePetAt: case pvpwire.CommandChangePetAt:
go fightController.ChangePetAt(proxy, payload.CatchTime, payload.ActorIndex) go proxy.ChangePetAt(payload.CatchTime, payload.ActorIndex)
case pvpwire.CommandLoadPercent: case pvpwire.CommandLoadPercent:
go fightController.LoadPercent(proxy, payload.Percent) go proxy.LoadPercent(payload.Percent)
case pvpwire.CommandUseItem: case pvpwire.CommandUseItem:
go fightController.UseItem(proxy, payload.CatchTime, payload.ItemID) go proxy.UseItem(payload.CatchTime, payload.ItemID)
case pvpwire.CommandUseItemAt: case pvpwire.CommandUseItemAt:
go fightController.UseItemAt(proxy, payload.CatchTime, payload.ItemID, payload.ActorIndex, payload.TargetIndex) go proxy.UseItemAt(payload.CatchTime, payload.ItemID, payload.ActorIndex, payload.TargetIndex)
case pvpwire.CommandChat: case pvpwire.CommandChat:
go fightController.Chat(proxy, payload.Message) go proxy.Chat(payload.Message)
} }
} }
@@ -516,13 +517,13 @@ func (m *manager) handleBattleClientCommand(payload pvpwire.BattleClientCommandP
switch payload.Cmd { switch payload.Cmd {
case 2404, 7556: case 2404, 7556:
go fightController.ReadyFight(proxy) go proxy.ReadyFight()
case 2405: case 2405:
var data struct { var data struct {
SkillId uint32 SkillId uint32
} }
if decodeBody(payload.Data, &data) { if decodeBody(payload.Data, &data) {
go fightController.UseSkillAt(proxy, data.SkillId, 0, fight.EncodeTargetIndex(0, true)) go proxy.UseSkillAt(data.SkillId, 0, fight.EncodeTargetIndex(0, true))
} }
case 7505: case 7505:
var data struct { var data struct {
@@ -540,7 +541,7 @@ func (m *manager) handleBattleClientCommand(payload pvpwire.BattleClientCommandP
data.TargetRelation, data.TargetRelation,
data.AtkType, data.AtkType,
) )
go fightController.UseSkillAt(proxy, envelope.SkillID, envelope.ActorIndex, envelope.EncodedTargetIndex()) go proxy.UseSkillAt(envelope.SkillID, envelope.ActorIndex, envelope.EncodedTargetIndex())
} }
case 7558: case 7558:
var data struct { var data struct {
@@ -555,7 +556,7 @@ func (m *manager) handleBattleClientCommand(payload pvpwire.BattleClientCommandP
targetRelation = fight.SkillTargetAlly targetRelation = fight.SkillTargetAlly
} }
envelope := fight.NewSkillActionEnvelope(data.SkillId, int(data.ActorIndex), int(data.TargetPos), targetRelation, 0) envelope := fight.NewSkillActionEnvelope(data.SkillId, int(data.ActorIndex), int(data.TargetPos), targetRelation, 0)
go fightController.UseSkillAt(proxy, envelope.SkillID, envelope.ActorIndex, envelope.EncodedTargetIndex()) go proxy.UseSkillAt(envelope.SkillID, envelope.ActorIndex, envelope.EncodedTargetIndex())
} }
case 2406: case 2406:
var data struct { var data struct {
@@ -563,7 +564,7 @@ func (m *manager) handleBattleClientCommand(payload pvpwire.BattleClientCommandP
ItemId uint32 `json:"itemId"` ItemId uint32 `json:"itemId"`
} }
if decodeBody(payload.Data, &data) { if decodeBody(payload.Data, &data) {
go fightController.UseItemAt(proxy, data.CatchTime, data.ItemId, 0, fight.EncodeTargetIndex(0, true)) go proxy.UseItemAt(data.CatchTime, data.ItemId, 0, fight.EncodeTargetIndex(0, true))
} }
case 7562: case 7562:
var data struct { var data struct {
@@ -571,14 +572,14 @@ func (m *manager) handleBattleClientCommand(payload pvpwire.BattleClientCommandP
ItemId uint32 ItemId uint32
} }
if decodeBody(payload.Data, &data) { if decodeBody(payload.Data, &data) {
go fightController.UseItemAt(proxy, 0, data.ItemId, int(data.ActorIndex), fight.EncodeTargetIndex(int(data.ActorIndex), false)) go proxy.UseItemAt(0, data.ItemId, int(data.ActorIndex), fight.EncodeTargetIndex(int(data.ActorIndex), false))
} }
case 2407: case 2407:
var data struct { var data struct {
CatchTime uint32 `json:"catchTime"` CatchTime uint32 `json:"catchTime"`
} }
if decodeBody(payload.Data, &data) { if decodeBody(payload.Data, &data) {
go fightController.ChangePetAt(proxy, data.CatchTime, 0) go proxy.ChangePetAt(data.CatchTime, 0)
} }
case 7563: case 7563:
var data struct { var data struct {
@@ -586,23 +587,23 @@ func (m *manager) handleBattleClientCommand(payload pvpwire.BattleClientCommandP
CatchTime uint32 CatchTime uint32
} }
if decodeBody(payload.Data, &data) { if decodeBody(payload.Data, &data) {
go fightController.ChangePetAt(proxy, data.CatchTime, int(data.ActorIndex)) go proxy.ChangePetAt(data.CatchTime, int(data.ActorIndex))
} }
case 2410, 7565: case 2410, 7565:
go fightController.Over(proxy, model.BattleOverReason.PlayerEscape) go proxy.Over(model.BattleOverReason.PlayerEscape)
case 2441: case 2441:
var data struct { var data struct {
Percent uint32 Percent uint32
} }
if decodeBody(payload.Data, &data) { if decodeBody(payload.Data, &data) {
go fightController.LoadPercent(proxy, int32(data.Percent)) go proxy.LoadPercent(int32(data.Percent))
} }
case 50002: case 50002:
var data struct { var data struct {
Message string `json:"message"` Message string `json:"message"`
} }
if decodeBody(payload.Data, &data) { if decodeBody(payload.Data, &data) {
go fightController.Chat(proxy, data.Message) go proxy.Chat(data.Message)
} }
} }
} }
@@ -623,6 +624,7 @@ func (m *manager) hostedFightAndProxy(sessionID string, userID uint32) (common.F
if proxy == nil { if proxy == nil {
proxy = player.NewRPCPlayer(&model.PlayerInfo{UserID: userID}, 0, fightinfo.Fightinfo{}, sessionID) proxy = player.NewRPCPlayer(&model.PlayerInfo{UserID: userID}, 0, fightinfo.Fightinfo{}, sessionID)
} }
proxy.SetFightC(fightController)
return fightController, proxy return fightController, proxy
} }

View File

@@ -29,6 +29,20 @@ func (*stubPlayer) MessWin(bool) {}
func (*stubPlayer) CanFight() errorcode.ErrorCode { return 0 } func (*stubPlayer) CanFight() errorcode.ErrorCode { return 0 }
func (p *stubPlayer) SendPackCmd(cmd uint32, _ any) { p.sentCmds = append(p.sentCmds, cmd) } func (p *stubPlayer) SendPackCmd(cmd uint32, _ any) { p.sentCmds = append(p.sentCmds, cmd) }
func (*stubPlayer) GetPetInfo(uint32) []model.PetInfo { return nil } func (*stubPlayer) GetPetInfo(uint32) []model.PetInfo { return nil }
func (*stubPlayer) Over(model.EnumBattleOverReason) {}
func (*stubPlayer) UseSkill(uint32) {}
func (*stubPlayer) UseSkillAt(uint32, int, int) {}
func (*stubPlayer) GetCurrPET() *fightinfo.BattlePetEntity { return nil }
func (*stubPlayer) GetCurrPETAt(int) *fightinfo.BattlePetEntity { return nil }
func (*stubPlayer) ReadyFight() {}
func (*stubPlayer) ChangePet(uint32) {}
func (*stubPlayer) ChangePetAt(uint32, int) {}
func (*stubPlayer) Capture(uint32) {}
func (*stubPlayer) LoadPercent(int32) {}
func (*stubPlayer) UseItem(uint32, uint32) {}
func (*stubPlayer) UseItemAt(uint32, uint32, int, int) {}
func (*stubPlayer) Chat(string) {}
func (*stubPlayer) IsFirst() bool { return false }
func TestFightActionEnvelopeEncodedTargetIndex(t *testing.T) { func TestFightActionEnvelopeEncodedTargetIndex(t *testing.T) {
self := NewSkillActionEnvelope(1, 2, 0, SkillTargetSelf, 0) self := NewSkillActionEnvelope(1, 2, 0, SkillTargetSelf, 0)

View File

@@ -16,6 +16,7 @@ type baseplayer struct {
Info *model.PlayerInfo Info *model.PlayerInfo
//canFight uint32 //canFight uint32
FightC common.FightI //绑定战斗标识 替代本身的是否战斗标记 //IsFighting bool FightC common.FightI //绑定战斗标识 替代本身的是否战斗标记 //IsFighting bool
self common.PlayerI
*info.PlayerCaptureContext *info.PlayerCaptureContext
Prop [6]int8 Prop [6]int8
} }
@@ -27,6 +28,17 @@ func newbaseplayer() baseplayer {
return ret return ret
} }
func (p *baseplayer) bindSelf(self common.PlayerI) {
p.self = self
}
func (p *baseplayer) fightPlayer() common.PlayerI {
if p.self != nil {
return p.self
}
return p
}
// GetInfo 获取玩家基础信息 // GetInfo 获取玩家基础信息
func (p *baseplayer) GetInfo() *model.PlayerInfo { func (p *baseplayer) GetInfo() *model.PlayerInfo {
return p.Info return p.Info
@@ -138,3 +150,101 @@ func (lw *baseplayer) SendLoadPercent(info.LoadPercentOutboundInfo) {
} }
func (p *baseplayer) ApplyPetDisplayInfo(out *spaceinfo.SimpleInfo) {} func (p *baseplayer) ApplyPetDisplayInfo(out *spaceinfo.SimpleInfo) {}
func (p *baseplayer) Over(reason model.EnumBattleOverReason) {
if p == nil || p.FightC == nil {
return
}
p.FightC.Over(p.fightPlayer(), reason)
}
func (p *baseplayer) UseSkill(id uint32) {
if p == nil || p.FightC == nil {
return
}
p.FightC.UseSkill(p.fightPlayer(), id)
}
func (p *baseplayer) UseSkillAt(id uint32, actorIndex, targetIndex int) {
if p == nil || p.FightC == nil {
return
}
p.FightC.UseSkillAt(p.fightPlayer(), id, actorIndex, targetIndex)
}
func (p *baseplayer) GetCurrPET() *info.BattlePetEntity {
if p == nil || p.FightC == nil {
return nil
}
return p.FightC.GetCurrPET(p.fightPlayer())
}
func (p *baseplayer) GetCurrPETAt(actorIndex int) *info.BattlePetEntity {
if p == nil || p.FightC == nil {
return nil
}
return p.FightC.GetCurrPETAt(p.fightPlayer(), actorIndex)
}
func (p *baseplayer) ReadyFight() {
if p == nil || p.FightC == nil {
return
}
p.FightC.ReadyFight(p.fightPlayer())
}
func (p *baseplayer) ChangePet(id uint32) {
if p == nil || p.FightC == nil {
return
}
p.FightC.ChangePet(p.fightPlayer(), id)
}
func (p *baseplayer) ChangePetAt(id uint32, actorIndex int) {
if p == nil || p.FightC == nil {
return
}
p.FightC.ChangePetAt(p.fightPlayer(), id, actorIndex)
}
func (p *baseplayer) Capture(id uint32) {
if p == nil || p.FightC == nil {
return
}
p.FightC.Capture(p.fightPlayer(), id)
}
func (p *baseplayer) LoadPercent(percent int32) {
if p == nil || p.FightC == nil {
return
}
p.FightC.LoadPercent(p.fightPlayer(), percent)
}
func (p *baseplayer) UseItem(catchTime, itemID uint32) {
if p == nil || p.FightC == nil {
return
}
p.FightC.UseItem(p.fightPlayer(), catchTime, itemID)
}
func (p *baseplayer) UseItemAt(catchTime, itemID uint32, actorIndex, targetIndex int) {
if p == nil || p.FightC == nil {
return
}
p.FightC.UseItemAt(p.fightPlayer(), catchTime, itemID, actorIndex, targetIndex)
}
func (p *baseplayer) Chat(msg string) {
if p == nil || p.FightC == nil {
return
}
p.FightC.Chat(p.fightPlayer(), msg)
}
func (p *baseplayer) IsFirst() bool {
if p == nil || p.FightC == nil {
return false
}
return p.FightC.IsFirst(p.fightPlayer())
}

View File

@@ -23,6 +23,7 @@ func NewPlayer(opts gnet.Conn) *Player {
HavePVPinfo: make([]common.PlayerI, 0), HavePVPinfo: make([]common.PlayerI, 0),
baseplayer: newbaseplayer(), baseplayer: newbaseplayer(),
} }
p.bindSelf(p)
p.PlayerCaptureContext = &info.PlayerCaptureContext{ p.PlayerCaptureContext = &info.PlayerCaptureContext{
Denominator: 1000, Denominator: 1000,
DecayFactor: 0.10, // 15%衰减率 DecayFactor: 0.10, // 15%衰减率
@@ -43,6 +44,7 @@ func NewAI_player(i *model.PlayerInfo) *AI_player {
ret := &AI_player{ ret := &AI_player{
baseplayer: newbaseplayer(), baseplayer: newbaseplayer(),
} }
ret.bindSelf(ret)
ret.Info = i ret.Info = i
//ret.Info.Nick = xmlres.PetMAP[int(m.ID)].DefName //ret.Info.Nick = xmlres.PetMAP[int(m.ID)].DefName

View File

@@ -27,6 +27,7 @@ func NewRPCPlayer(info *model.PlayerInfo, serviceID uint32, fightInfo info.Fight
fightinfo: fightInfo, fightinfo: fightInfo,
sessionID: sessionID, sessionID: sessionID,
} }
ret.bindSelf(ret)
ret.Info = info ret.Info = info
return ret return ret
} }

View File

@@ -46,7 +46,7 @@ func (p *Player) Save() {
} }
}() }()
p.FightC.Over(p, model.BattleOverReason.PlayerOffline) //玩家逃跑,但是不能锁线程 p.Over(model.BattleOverReason.PlayerOffline) //玩家逃跑,但是不能锁线程
}() }()
//<-ov //<-ov
select { select {