feat(fight): 添加效果工厂模式支持以解决闭包变量捕获问题 - 新增initskillFactory函数用于注册效果工厂 - 修改技能效果注册逻辑从直接实例化改为工厂模式 - 解决循环中闭包捕获变量导致的潜在问题 feat(fight): 实现对手输入获取逻辑优化回合处理 - 添加roundOpponentInput方法获取对手输入 - 重构enterturn方法中的先后手逻辑 - 确保攻击方和被攻击
This commit is contained in:
@@ -5,3 +5,7 @@ import "blazing/logic/service/fight/input"
|
||||
func initskill(id int, e input.Effect) {
|
||||
input.InitEffect(input.EffectType.Skill, id, e)
|
||||
}
|
||||
|
||||
func initskillFactory(id int, factory func() input.Effect) {
|
||||
input.InitEffectFactory(input.EffectType.Skill, id, factory)
|
||||
}
|
||||
|
||||
@@ -158,7 +158,10 @@ func registerSelfDamageSkillHitEffects() {
|
||||
}
|
||||
|
||||
for effectID, handler := range handlers {
|
||||
initskill(effectID, newSkillHitRegistrarEffect(handler))
|
||||
currentHandler := handler
|
||||
initskillFactory(effectID, func() input.Effect {
|
||||
return newSkillHitRegistrarEffect(currentHandler)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +226,10 @@ func registerSelfDamageOnSkillEffects() {
|
||||
}
|
||||
|
||||
for effectID, handler := range handlers {
|
||||
initskill(effectID, newOnSkillRegistrarEffect(handler))
|
||||
currentHandler := handler
|
||||
initskillFactory(effectID, func() input.Effect {
|
||||
return newOnSkillRegistrarEffect(currentHandler)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,7 +311,10 @@ func registerSelfDamageSkillUseEffects() {
|
||||
}
|
||||
|
||||
for effectID, handler := range handlers {
|
||||
initskill(effectID, newSkillUseRegistrarEffect(handler))
|
||||
currentHandler := handler
|
||||
initskillFactory(effectID, func() input.Effect {
|
||||
return newSkillUseRegistrarEffect(currentHandler)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,7 +348,10 @@ func registerSelfDamageComparePreOnSkillEffects() {
|
||||
}
|
||||
|
||||
for effectID, effect := range effects {
|
||||
initskill(effectID, effect)
|
||||
currentEffect := effect
|
||||
initskillFactory(effectID, func() input.Effect {
|
||||
return newComparePreOnSkillRegistrarEffect(currentEffect.comparePreHandler, currentEffect.onSkillHandler)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -198,6 +198,18 @@ func (f *FightC) buildNoteUseSkillOutboundInfo() info.NoteUseSkillOutboundInfo {
|
||||
return result
|
||||
}
|
||||
|
||||
func (f *FightC) roundOpponentInput(attacker *input.Input) *input.Input {
|
||||
if attacker == nil {
|
||||
return nil
|
||||
}
|
||||
for _, opponent := range attacker.OpponentSlots() {
|
||||
if opponent != nil {
|
||||
return opponent
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// enterturn 处理战斗回合逻辑
|
||||
// 回合有先手方和后手方,同时有攻击方和被攻击方
|
||||
func (f *FightC) enterturn(firstAttack, secondAttack *action.SelectSkillAction) {
|
||||
@@ -245,9 +257,11 @@ func (f *FightC) enterturn(firstAttack, secondAttack *action.SelectSkillAction)
|
||||
f.First, _ = f.getSkillParticipants(firstAttack)
|
||||
f.Second, _ = f.getSkillParticipants(secondAttack)
|
||||
case firstAttack != nil:
|
||||
f.First, f.Second = f.getSkillParticipants(firstAttack)
|
||||
f.First, _ = f.getSkillParticipants(firstAttack)
|
||||
f.Second = f.roundOpponentInput(f.First)
|
||||
case secondAttack != nil:
|
||||
f.First, f.Second = f.getSkillParticipants(secondAttack)
|
||||
f.First, _ = f.getSkillParticipants(secondAttack)
|
||||
f.Second = f.roundOpponentInput(f.First)
|
||||
}
|
||||
if f.First == nil {
|
||||
f.First = f.primaryOur()
|
||||
@@ -332,7 +346,6 @@ func (f *FightC) enterturn(firstAttack, secondAttack *action.SelectSkillAction)
|
||||
|
||||
}
|
||||
//先手权不一定出手
|
||||
|
||||
} else {
|
||||
f.setActionAttackValue(currentAction)
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ var EffectType = enum.New[struct {
|
||||
}]()
|
||||
|
||||
var NodeM = make(map[int64]Effect, 0)
|
||||
var NodeFactoryM = make(map[int64]func() Effect, 0)
|
||||
|
||||
func InitEffect(etype EnumEffectType, id int, t Effect) {
|
||||
pr := EffectIDCombiner{}
|
||||
@@ -41,6 +42,13 @@ func InitEffect(etype EnumEffectType, id int, t Effect) {
|
||||
|
||||
NodeM[pr.EffectID()] = t
|
||||
}
|
||||
|
||||
func InitEffectFactory(etype EnumEffectType, id int, factory func() Effect) {
|
||||
pr := EffectIDCombiner{}
|
||||
pr.Combine(etype, 0, gconv.Uint16(id))
|
||||
|
||||
NodeFactoryM[pr.EffectID()] = factory
|
||||
}
|
||||
func GeteffectIDs(etype EnumEffectType) []uint32 {
|
||||
|
||||
var ret []uint32 = make([]uint32, 0)
|
||||
@@ -60,6 +68,19 @@ func geteffect[T int | byte | uint16](etype EnumEffectType, id T) Effect {
|
||||
pr := EffectIDCombiner{}
|
||||
pr.Combine(etype, 0, gconv.Uint16(id))
|
||||
|
||||
if factory, ok := NodeFactoryM[pr.EffectID()]; ok {
|
||||
eff := factory()
|
||||
if eff == nil {
|
||||
return nil
|
||||
}
|
||||
eff.ID(pr)
|
||||
if etype == EffectType.Status {
|
||||
eff.CanStack(true)
|
||||
eff.Duration(grand.N(1, 2))
|
||||
}
|
||||
return eff
|
||||
}
|
||||
|
||||
//todo 获取前GetEffect
|
||||
ret, ok := NodeM[pr.EffectID()]
|
||||
if ok {
|
||||
|
||||
@@ -11,6 +11,12 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// TaskCompletionContext 封装任务完成时的上下文。
|
||||
// 这里除了保留任务配置和默认奖励,也给自定义任务完成逻辑暴露了返回包与开关位,
|
||||
// 用来兼容“固定发物品/精灵”之外的奖励场景。
|
||||
// 这套扩展最初是为任务发放特训技能、皮肤而补上的:
|
||||
// 特训奖励不能完全按静态表直发,需要结合额外条件做特判,
|
||||
// 例如通过挖矿/对话进度限制特训次数,满足条件后再允许完成任务。
|
||||
type TaskCompletionContext struct {
|
||||
TaskID uint32
|
||||
OutState int
|
||||
@@ -21,8 +27,12 @@ type TaskCompletionContext struct {
|
||||
SkipDefaultReward bool
|
||||
}
|
||||
|
||||
// TaskCompletionHandler 定义任务完成前的自定义处理器。
|
||||
// 处理器可用于补充校验、写入额外奖励,或在任务完全走自定义发奖时跳过默认奖励流程。
|
||||
type TaskCompletionHandler func(*Player, *TaskCompletionContext) errorcode.ErrorCode
|
||||
|
||||
// taskCompletionRegistry 按任务 ID 维护自定义完成处理器。
|
||||
// 默认任务仍然走 task 配表里的固定奖励;只有存在特判需求的任务才在这里注册。
|
||||
var taskCompletionRegistry = struct {
|
||||
sync.RWMutex
|
||||
handlers map[uint32]TaskCompletionHandler
|
||||
@@ -30,11 +40,16 @@ var taskCompletionRegistry = struct {
|
||||
handlers: make(map[uint32]TaskCompletionHandler),
|
||||
}
|
||||
|
||||
// taskRewardGrantResult 汇总本次任务实际发放的奖励,
|
||||
// 便于后续统一推送给前端展示。
|
||||
type taskRewardGrantResult struct {
|
||||
Pet *playermodel.PetInfo
|
||||
Items []data.ItemInfo
|
||||
}
|
||||
|
||||
// RegisterTaskCompletionHandler 注册任务完成时的自定义处理器。
|
||||
// 用于覆盖“任务奖励固定为物品和精灵”的旧模型,让指定任务在完成前后插入额外逻辑。
|
||||
// 当前这套机制主要服务于特训技能、皮肤等特殊奖励,以及需要额外次数/进度校验的任务。
|
||||
func RegisterTaskCompletionHandler(taskID uint32, handler TaskCompletionHandler) {
|
||||
if taskID == 0 || handler == nil {
|
||||
return
|
||||
@@ -45,6 +60,9 @@ func RegisterTaskCompletionHandler(taskID uint32, handler TaskCompletionHandler)
|
||||
taskCompletionRegistry.Unlock()
|
||||
}
|
||||
|
||||
// RegisterTaskTalkLimitHandler 注册一个基于挖矿/采集对话进度的完成限制。
|
||||
// 历史上特训任务需要通过挖矿次数限制可领取次数,因此复用了 Talk 进度作为准入条件。
|
||||
// 当指定 talkID 的进度不足 needCount 时,任务不能完成也不能领奖。
|
||||
func RegisterTaskTalkLimitHandler(taskID, talkID, needCount uint32) {
|
||||
RegisterTaskCompletionHandler(taskID, func(p *Player, _ *TaskCompletionContext) errorcode.ErrorCode {
|
||||
if p == nil || p.Service == nil || p.Service.Talk == nil {
|
||||
@@ -67,6 +85,7 @@ func (p *Player) getTaskGift(taskID int, outState int) *tasklogic.TaskResult {
|
||||
return tasklogic.GetTaskInfo(taskID, outState)
|
||||
}
|
||||
|
||||
// hasTaskCompletionHandler 判断任务是否存在自定义完成处理器。
|
||||
func hasTaskCompletionHandler(taskID uint32) bool {
|
||||
taskCompletionRegistry.RLock()
|
||||
_, ok := taskCompletionRegistry.handlers[taskID]
|
||||
@@ -74,6 +93,7 @@ func hasTaskCompletionHandler(taskID uint32) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
// getTaskCompletionHandler 获取任务的自定义完成处理器。
|
||||
func getTaskCompletionHandler(taskID uint32) TaskCompletionHandler {
|
||||
taskCompletionRegistry.RLock()
|
||||
handler := taskCompletionRegistry.handlers[taskID]
|
||||
@@ -81,6 +101,8 @@ func getTaskCompletionHandler(taskID uint32) TaskCompletionHandler {
|
||||
return handler
|
||||
}
|
||||
|
||||
// canCompleteTaskReward 判断任务是否具备可执行的奖励逻辑。
|
||||
// 只要存在默认奖励,或已注册自定义处理器,就允许进入完成流程。
|
||||
func (p *Player) canCompleteTaskReward(taskID, outState int) bool {
|
||||
if taskID <= 0 {
|
||||
return false
|
||||
@@ -88,6 +110,10 @@ func (p *Player) canCompleteTaskReward(taskID, outState int) bool {
|
||||
return p.getTaskGift(taskID, outState) != nil || hasTaskCompletionHandler(uint32(taskID))
|
||||
}
|
||||
|
||||
// ApplyTaskCompletion 执行任务完成时的奖励发放入口。
|
||||
// 流程分两层:
|
||||
// 1. 先执行自定义处理器,处理特训/皮肤/额外次数校验等特殊逻辑;
|
||||
// 2. 若未要求跳过默认奖励,再回落到原有的物品/精灵发奖逻辑。
|
||||
func (p *Player) ApplyTaskCompletion(taskID uint32, outState int, result *tasklogic.CompleteTaskOutboundInfo) (*taskRewardGrantResult, errorcode.ErrorCode) {
|
||||
if p == nil {
|
||||
return nil, errorcode.ErrorCodes.ErrSystemError
|
||||
@@ -125,6 +151,8 @@ func (p *Player) ApplyTaskCompletion(taskID uint32, outState int, result *tasklo
|
||||
return p.grantTaskReward(ctx.Reward, result), 0
|
||||
}
|
||||
|
||||
// grantTaskReward 发放 task 配表里的默认奖励。
|
||||
// 这里仍负责原有的固定奖励模型:物品、精灵、称号,以及配置里声明的任务宠奖励。
|
||||
func (p *Player) grantTaskReward(reward *tasklogic.TaskResult, result *tasklogic.CompleteTaskOutboundInfo) *taskRewardGrantResult {
|
||||
granted := &taskRewardGrantResult{
|
||||
Items: make([]data.ItemInfo, 0),
|
||||
@@ -169,6 +197,7 @@ func (p *Player) grantTaskReward(reward *tasklogic.TaskResult, result *tasklogic
|
||||
return granted
|
||||
}
|
||||
|
||||
// SendTaskCompletionBonus 将任务奖励转换为旧的奖励展示协议并推送给前端。
|
||||
func (p *Player) SendTaskCompletionBonus(bonusID uint32, granted *taskRewardGrantResult) {
|
||||
if p == nil {
|
||||
return
|
||||
|
||||
@@ -12,7 +12,7 @@ const TableNameServerList = "server_list"
|
||||
type ServerList struct {
|
||||
*cool.Model
|
||||
coolconfig.ServerList
|
||||
ServerShow *ServerShow `orm:"with:server_id=online_id" gorm:"-" json:"server_show,omitempty"`
|
||||
ServerShow *ServerShow `orm:"with:server_id=online_id" gorm:"-" json:"servershow,omitempty"`
|
||||
// isonline
|
||||
IsOnline uint8 `gorm:"column:isonline;default:0;comment:'是否在线'" json:"isonline"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user