feat(fight): 重构战斗系统技能逻辑与精灵切换功能
- 优化技能执行流程,统一使用 SelectSkillAction 作为技能载体 - 移除冗余的技能 ID 字段,简化数据结构 - 调整命中判断和技能效果触发机制,提升准确性 - 修改精灵切换与捕获相关方法参数格式 - 更新技能列表结构为动态数组以支持灵活长度 - 完善睡眠等异常状态的处理逻辑 - 修复战斗中技能 PP 扣减及副本还原问题 - 清理无用代码,如多余的 FindWithIndex 函数定义 - 强化验证码缓存键命名规则,增强安全性
This commit is contained in:
10
common/utils/help.go
Normal file
10
common/utils/help.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package utils
|
||||
|
||||
func FindWithIndex[T any](slice []T, predicate func(item T) bool) (int, *T, bool) {
|
||||
for i := range slice {
|
||||
if predicate(slice[i]) {
|
||||
return i, &slice[i], true
|
||||
}
|
||||
}
|
||||
return -1, nil, false
|
||||
}
|
||||
@@ -157,13 +157,13 @@ func (h Controller) ChangePet(data *fight.ChangePetInboundInfo, c *player.Player
|
||||
// 切换精灵
|
||||
func (h Controller) Capture(data *fight.CatchMonsterInboundInfo, c *player.Player) (result *info.CatchMonsterOutboundInfo, err errorcode.ErrorCode) {
|
||||
|
||||
c.FightC.Capture(c, (data.CapsuleId))
|
||||
c.FightC.Capture(c, data.CapsuleId)
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// 切换精灵
|
||||
// 加载进度
|
||||
func (h Controller) LoadPercent(data *fight.LoadPercentInboundInfo, c *player.Player) (result *info.LoadPercentOutboundInfo, err errorcode.ErrorCode) {
|
||||
|
||||
c.FightC.LoadPercent(c, (int32(data.Percent)))
|
||||
c.FightC.LoadPercent(c, int32(data.Percent))
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package controller
|
||||
import (
|
||||
"blazing/common/data/xmlres"
|
||||
"blazing/common/socket/errorcode"
|
||||
"blazing/common/utils"
|
||||
|
||||
"blazing/logic/service/pet"
|
||||
"blazing/logic/service/player"
|
||||
@@ -122,7 +123,7 @@ func (h *Controller) PlayerShowPet(
|
||||
func (h *Controller) PetOneCure(
|
||||
data *pet.PetOneCureInboundInfo, c *player.Player) (result *pet.PetOneCureOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的
|
||||
|
||||
_, onpet, ok := FindWithIndex(c.Info.PetList, func(item model.PetInfo) bool {
|
||||
_, onpet, ok := utils.FindWithIndex(c.Info.PetList, func(item model.PetInfo) bool {
|
||||
return item.CatchTime == data.CatchTime
|
||||
})
|
||||
if ok {
|
||||
@@ -158,16 +159,9 @@ func (h *Controller) PetFirst(
|
||||
|
||||
// FindWithIndex 遍历slice,找到第一个满足条件的元素
|
||||
// 返回:索引、元素指针、是否找到
|
||||
func FindWithIndex[T any](slice []T, predicate func(item T) bool) (int, *T, bool) {
|
||||
for i := range slice {
|
||||
if predicate(slice[i]) {
|
||||
return i, &slice[i], true
|
||||
}
|
||||
}
|
||||
return -1, nil, false
|
||||
}
|
||||
|
||||
func (h Controller) SetPetExp(data *pet.PetSetExpInboundInfo, c *player.Player) (result *pet.PetSetExpOutboundInfo, err errorcode.ErrorCode) {
|
||||
_, onpet, ok := FindWithIndex(c.Info.PetList, func(item model.PetInfo) bool {
|
||||
_, onpet, ok := utils.FindWithIndex(c.Info.PetList, func(item model.PetInfo) bool {
|
||||
return item.CatchTime == data.CatchTime
|
||||
})
|
||||
if ok {
|
||||
@@ -180,11 +174,11 @@ func (h Controller) SetPetExp(data *pet.PetSetExpInboundInfo, c *player.Player)
|
||||
}, 0
|
||||
}
|
||||
func (h Controller) SetPetSkill(data *pet.ChangeSkillInfo, c *player.Player) (result *pet.ChangeSkillOutInfo, err errorcode.ErrorCode) {
|
||||
_, onpet, ok := FindWithIndex(c.Info.PetList, func(item model.PetInfo) bool {
|
||||
_, onpet, ok := utils.FindWithIndex(c.Info.PetList, func(item model.PetInfo) bool {
|
||||
return item.CatchTime == data.CatchTime
|
||||
})
|
||||
if ok {
|
||||
for i := 0; i < 4; i++ {
|
||||
for i := 0; i < len(onpet.SkillList); i++ {
|
||||
if onpet.SkillList[i].ID == data.HasSkill {
|
||||
onpet.SkillList[i].ID = data.ReplaceSkill
|
||||
onpet.SkillList[i].PP = uint32(xmlres.SkillMap[int(onpet.SkillList[i].ID)].MaxPP)
|
||||
|
||||
@@ -32,9 +32,8 @@ type BattleActionI interface {
|
||||
|
||||
// SelectSkillAction 选择技能的战斗动作
|
||||
type SelectSkillAction struct {
|
||||
ID uint32 //技能ID
|
||||
BaseAction
|
||||
Skill *info.SkillEntity // 使用的技能
|
||||
*info.SkillEntity // 使用的技能
|
||||
//PetInfo *info.BattlePetEntity // 使用技能的宠物
|
||||
Attack info.AttackValue
|
||||
}
|
||||
|
||||
11
logic/service/fight/action/help.go
Normal file
11
logic/service/fight/action/help.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package action
|
||||
|
||||
func CanUse(s *SelectSkillAction) bool {
|
||||
if s == nil {
|
||||
return false
|
||||
|
||||
}
|
||||
|
||||
return s.Info.PP > 0
|
||||
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package effect
|
||||
|
||||
import (
|
||||
"blazing/logic/service/fight/action"
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/logic/service/fight/input"
|
||||
"blazing/logic/service/fight/node"
|
||||
|
||||
@@ -18,16 +17,19 @@ type Effect1 struct {
|
||||
|
||||
func init() {
|
||||
ret := &Effect1{}
|
||||
ret.Effect = ret
|
||||
|
||||
input.InitEffect(input.EffectType.Skill, 1, ret)
|
||||
|
||||
}
|
||||
|
||||
// 命中之后
|
||||
func (e *Effect1) OnHit(opp *input.Input, skill *info.SkillEntity) {
|
||||
func (e *Effect1) OnSkill(ctx input.Ctx) bool {
|
||||
if !e.Hit() {
|
||||
return true
|
||||
}
|
||||
|
||||
e.Input.Heal(
|
||||
&action.SelectSkillAction{}, e.Input.DamageZone.Damage.Div(decimal.NewFromInt(2)),
|
||||
)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ func newp(t1 info.EnumBattleStatus) *Effect10 {
|
||||
Status: t1,
|
||||
}
|
||||
|
||||
t.Effect = t
|
||||
return t
|
||||
}
|
||||
|
||||
@@ -51,7 +50,7 @@ func init() {
|
||||
input.InitEffect(input.EffectType.Skill, 114, newp(info.PetStatus.Flammable))
|
||||
|
||||
}
|
||||
func (e *Effect10) OnHit(opp *input.Input, skill *info.SkillEntity) {
|
||||
func (e *Effect10) OnSkill(ctx input.Ctx) bool {
|
||||
t, _, _ := e.Input.Player.Roll(e.EffectNode.SideEffectArgs[0], 100)
|
||||
if t {
|
||||
|
||||
@@ -61,11 +60,11 @@ func (e *Effect10) OnHit(opp *input.Input, skill *info.SkillEntity) {
|
||||
if eff.ID != 0 {
|
||||
eff.Effect.Duration(int(t1))
|
||||
|
||||
opp.AddEffect(eff)
|
||||
ctx.AddEffect(eff)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
func (e *Effect10) OnMiss(opp *input.Input, skill *info.SkillEntity) {
|
||||
|
||||
|
||||
@@ -13,16 +13,20 @@ type Effect3 struct {
|
||||
Etype info.EnumAbilityOpType
|
||||
}
|
||||
|
||||
func (e *Effect3) OnHit(opp *input.Input, skill *info.SkillEntity) {
|
||||
func (e *Effect3) OnSkill(ctx input.Ctx) bool {
|
||||
|
||||
if !e.Hit() {
|
||||
return true
|
||||
}
|
||||
for i := 0; i < 6; i++ {
|
||||
if e.Rev {
|
||||
opp.SetProp(e.Input, int8(i), e.Level, e.Etype)
|
||||
ctx.SetProp(e.Input, int8(i), e.Level, e.Etype)
|
||||
} else {
|
||||
e.Input.SetProp(opp, int8(i), e.Level, e.Etype)
|
||||
e.Input.SetProp(ctx.Input, int8(i), e.Level, e.Etype)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func neweffect3(rev bool, level int8, etype info.EnumAbilityOpType) *Effect3 {
|
||||
@@ -31,7 +35,7 @@ func neweffect3(rev bool, level int8, etype info.EnumAbilityOpType) *Effect3 {
|
||||
Level: level,
|
||||
Etype: etype,
|
||||
}
|
||||
ret.Effect = ret
|
||||
|
||||
return ret
|
||||
}
|
||||
func init() {
|
||||
|
||||
@@ -20,7 +20,7 @@ func NewEffectStat(b bool) input.Effect {
|
||||
EffectNode: node.EffectNode{},
|
||||
Etype: b,
|
||||
}
|
||||
ret.Effect = ret
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -40,11 +40,13 @@ type EffectStat struct {
|
||||
// addrA := unsafe.Pointer(baseAddr + 4) //根据攻击算其他字段
|
||||
// *(*uint32)(addrA) = 100
|
||||
// }
|
||||
func (e *EffectStat) OnHit(opp *input.Input, skill *info.SkillEntity) {
|
||||
|
||||
func (e *EffectStat) OnSkill(ctx input.Ctx) bool {
|
||||
if !e.Hit() {
|
||||
return true
|
||||
}
|
||||
t, _, _ := e.Input.Player.Roll(e.EffectNode.SideEffectArgs[1], 100)
|
||||
if !t { //没触发
|
||||
return
|
||||
return true
|
||||
}
|
||||
ptype := info.AbilityOpType.ADD
|
||||
if e.EffectNode.SideEffectArgs[2] < 0 {
|
||||
@@ -54,7 +56,7 @@ func (e *EffectStat) OnHit(opp *input.Input, skill *info.SkillEntity) {
|
||||
e.Input.SetProp(e.Input, int8(e.EffectNode.SideEffectArgs[0]), int8(e.EffectNode.SideEffectArgs[2]), ptype)
|
||||
|
||||
} else { //对方
|
||||
opp.SetProp(e.Input, int8(e.EffectNode.SideEffectArgs[0]), int8(e.EffectNode.SideEffectArgs[2]), ptype)
|
||||
ctx.SetProp(e.Input, int8(e.EffectNode.SideEffectArgs[0]), int8(e.EffectNode.SideEffectArgs[2]), ptype)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package effect
|
||||
|
||||
import (
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/logic/service/fight/input"
|
||||
"blazing/logic/service/fight/node"
|
||||
)
|
||||
@@ -21,12 +20,15 @@ func init() {
|
||||
Owner: true,
|
||||
},
|
||||
}
|
||||
t.Effect = t
|
||||
|
||||
input.InitEffect(input.EffectType.Skill, 62, t)
|
||||
|
||||
}
|
||||
|
||||
func (e *Effect62) OnHit(*input.Input, *info.SkillEntity) {
|
||||
func (e *Effect62) OnSkill(ctx input.Ctx) bool {
|
||||
if !e.Hit() {
|
||||
return true
|
||||
}
|
||||
if e.Duration() != 1 { //说明还没到生效节点
|
||||
e.Hide = true //隐藏效果
|
||||
} else {
|
||||
@@ -42,7 +44,7 @@ func (e *Effect62) OnHit(*input.Input, *info.SkillEntity) {
|
||||
//否则触发秒杀 在对面使用技能后
|
||||
//return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// 默认添加回合
|
||||
|
||||
@@ -19,11 +19,28 @@ type StatusNotSkill struct {
|
||||
}
|
||||
|
||||
// 不能出手
|
||||
func (e *StatusNotSkill) Skill_Hit_Pre(input.Ctx) bool {
|
||||
func (e *StatusNotSkill) Skill_Hit_Pre(ctx input.Ctx) bool {
|
||||
if e.EffectStatus.Status == info.PetStatus.Sleep {
|
||||
|
||||
ctx.AddEffect(&input.EffectID{ //对对方添加出手解除效果
|
||||
ID: -1,
|
||||
Effect: &StatusSleep{},
|
||||
})
|
||||
|
||||
}
|
||||
return false
|
||||
|
||||
}
|
||||
|
||||
type StatusSleep struct { //睡眠不能出手
|
||||
node.EffectNode
|
||||
}
|
||||
|
||||
func (e *StatusSleep) Skill_Useed(input.Ctx) bool {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// 扣血类
|
||||
type DrainHP struct {
|
||||
EffectStatus
|
||||
@@ -65,9 +82,9 @@ func init() {
|
||||
}
|
||||
input.InitEffect(input.EffectType.Status, int(info.PetStatus.DrainHP), &EffectStatus{}) //寄生种子
|
||||
|
||||
tt(info.PetStatus.Paralysis, &StatusNotSkill{})
|
||||
tt(info.PetStatus.Tired, &StatusNotSkill{})
|
||||
tt(info.PetStatus.Fear, &StatusNotSkill{})
|
||||
tt(info.PetStatus.Petrified, &StatusNotSkill{})
|
||||
|
||||
tt(info.PetStatus.Paralysis, &StatusNotSkill{}) //麻痹
|
||||
tt(info.PetStatus.Tired, &StatusNotSkill{}) //疲惫
|
||||
tt(info.PetStatus.Fear, &StatusNotSkill{}) //害怕
|
||||
tt(info.PetStatus.Petrified, &StatusNotSkill{}) //石化
|
||||
input.InitEffect(input.EffectType.Status, 8, &StatusSleep{}) //睡眠
|
||||
}
|
||||
|
||||
@@ -329,27 +329,12 @@ func (f *FightC) battleLoop() {
|
||||
|
||||
// 如果后手不是技能,替换成空技能(放弃出手)
|
||||
if _, ok := BattleActionI[1].(*action.SelectSkillAction); !ok {
|
||||
BattleActionI[1] = &action.SelectSkillAction{
|
||||
ID: 0,
|
||||
BaseAction: action.NewBaseAction(BattleActionI[1].GetPlayerID()),
|
||||
}
|
||||
|
||||
f.enterturn(&action.SelectSkillAction{ //双方均放弃出手
|
||||
ID: 0,
|
||||
BaseAction: action.NewBaseAction(BattleActionI[1].GetPlayerID()),
|
||||
},
|
||||
&action.SelectSkillAction{
|
||||
ID: 0,
|
||||
BaseAction: action.NewBaseAction(BattleActionI[0].GetPlayerID()),
|
||||
})
|
||||
f.enterturn(nil, nil) //双方都不出手
|
||||
|
||||
} else {
|
||||
|
||||
f.enterturn(BattleActionI[1].(*action.SelectSkillAction), //后手方先手,先手方放弃出手
|
||||
&action.SelectSkillAction{
|
||||
ID: 0,
|
||||
BaseAction: action.NewBaseAction(BattleActionI[0].GetPlayerID()),
|
||||
})
|
||||
//后手方先手,先手方放弃出手
|
||||
f.enterturn(BattleActionI[1].(*action.SelectSkillAction), nil)
|
||||
|
||||
}
|
||||
|
||||
@@ -385,45 +370,15 @@ func (f *FightC) battleLoop() {
|
||||
fmt.Println("ItemID 不在指定范围内")
|
||||
}
|
||||
|
||||
// 回合逻辑:另一方只要不是技能,也放弃出手
|
||||
leftAction := BattleActionI[0]
|
||||
rightAction := BattleActionI[1]
|
||||
|
||||
if _, ok := rightAction.(*action.SelectSkillAction); !ok {
|
||||
rightAction = &action.SelectSkillAction{
|
||||
ID: 0,
|
||||
BaseAction: action.NewBaseAction(rightAction.GetPlayerID()),
|
||||
}
|
||||
if _, ok := BattleActionI[1].(*action.SelectSkillAction); !ok {
|
||||
f.enterturn(nil, nil)
|
||||
} else {
|
||||
f.enterturn(BattleActionI[1].(*action.SelectSkillAction), nil)
|
||||
}
|
||||
|
||||
if _, ok := leftAction.(*action.SelectSkillAction); !ok {
|
||||
leftAction = &action.SelectSkillAction{
|
||||
ID: 0,
|
||||
BaseAction: action.NewBaseAction(leftAction.GetPlayerID()),
|
||||
}
|
||||
}
|
||||
|
||||
f.enterturn(leftAction.(*action.SelectSkillAction), rightAction.(*action.SelectSkillAction))
|
||||
|
||||
default: // 双方都是技能或者默认情况
|
||||
leftAction := BattleActionI[0]
|
||||
rightAction := BattleActionI[1]
|
||||
|
||||
// 双方只要不是技能,就放弃出手
|
||||
if _, ok := leftAction.(*action.SelectSkillAction); !ok {
|
||||
leftAction = &action.SelectSkillAction{
|
||||
ID: 0,
|
||||
BaseAction: action.NewBaseAction(leftAction.GetPlayerID()),
|
||||
}
|
||||
}
|
||||
if _, ok := rightAction.(*action.SelectSkillAction); !ok {
|
||||
rightAction = &action.SelectSkillAction{
|
||||
ID: 0,
|
||||
BaseAction: action.NewBaseAction(rightAction.GetPlayerID()),
|
||||
}
|
||||
}
|
||||
|
||||
f.enterturn(leftAction.(*action.SelectSkillAction), rightAction.(*action.SelectSkillAction))
|
||||
f.enterturn(BattleActionI[0].(*action.SelectSkillAction), BattleActionI[1].(*action.SelectSkillAction))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -436,28 +391,28 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *action.S
|
||||
attacker.Exec(func(t input.Effect) bool { //计算命中 miss改命中
|
||||
|
||||
t.Skill_Hit_Pre(input.Ctx{ //调基础命中
|
||||
Input: defender,
|
||||
SkillEntity: a.Skill,
|
||||
Input: defender,
|
||||
SelectSkillAction: a,
|
||||
}) //相当于先调整基础命中,不光调整命中,这里还能调整技能属性,暴击率
|
||||
|
||||
return true
|
||||
})
|
||||
a.Skill.AttackTimeC(attacker.GetProp(5, true)) //计算命中
|
||||
defender.Exec(func(t input.Effect) bool { //计算闪避 ,然后修改对方命中),同时相当于计算属性无效这种
|
||||
a.AttackTimeC(attacker.GetProp(5, true)) //计算命中
|
||||
defender.Exec(func(t input.Effect) bool { //计算闪避 ,然后修改对方命中),同时相当于计算属性无效这种
|
||||
t.Skill_Hit_to(input.Ctx{ //计算命中后,我方强制改命中效果
|
||||
Input: attacker,
|
||||
SkillEntity: a.Skill,
|
||||
Input: attacker,
|
||||
SelectSkillAction: a,
|
||||
})
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
attacker.AttackValue.AttackTime = a.Skill.AttackTime //是否命中赋值
|
||||
attacker.Exec(func(t input.Effect) bool { //计算命中 miss改命中
|
||||
attacker.AttackValue.AttackTime = a.AttackTime //是否命中赋值
|
||||
attacker.Exec(func(t input.Effect) bool { //计算命中 miss改命中
|
||||
|
||||
t.Skill_Hit(input.Ctx{ //计算变威力
|
||||
Input: attacker,
|
||||
SkillEntity: a.Skill,
|
||||
Input: attacker,
|
||||
SelectSkillAction: a,
|
||||
}) //相当于先调整基础命中,不光调整命中,这里还能调整技能属性,暴击率
|
||||
|
||||
return true
|
||||
@@ -466,20 +421,20 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *action.S
|
||||
//技能miss+效果生效 这里属于强制改命中效果,但是正常来说,技能miss掉后效果也应该失效
|
||||
//技能失效+效果失效
|
||||
// 记录技能信息
|
||||
attacker.AttackValue.SkillID = uint32(a.Skill.ID) //获取技能ID
|
||||
if attacker.AttackValue.AttackTime > 0 { //如果命中
|
||||
attacker.UseSkill(defender, a.Skill) //暴击计算
|
||||
attacker.AttackValue.IsCritical = a.Skill.Crit
|
||||
attacker.AttackValue.SkillID = uint32(a.ID) //获取技能ID
|
||||
if attacker.AttackValue.AttackTime > 0 { //如果命中
|
||||
attacker.UseSkill(defender, a) //暴击计算
|
||||
attacker.AttackValue.IsCritical = a.Crit
|
||||
attacker.Exec(func(t input.Effect) bool { //计算命中 miss改命中
|
||||
|
||||
t.Calculate_Pre(input.Ctx{ //计算视为效果
|
||||
Input: defender,
|
||||
SkillEntity: a.Skill,
|
||||
Input: defender,
|
||||
SelectSkillAction: a,
|
||||
}) //相当于先调整基础命中,不光调整命中,这里还能调整技能属性,暴击率
|
||||
|
||||
return true
|
||||
})
|
||||
attacker.DamageZone.Damage = attacker.CalculatePower(defender, a.Skill)
|
||||
attacker.DamageZone.Damage = attacker.CalculatePower(defender, a.SkillEntity)
|
||||
|
||||
if attacker.AttackValue.IsCritical == 1 {
|
||||
|
||||
@@ -488,16 +443,14 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *action.S
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
for _, e := range attacker.EffectCache {
|
||||
//这里实现应该参考本地技能是否命中,然后
|
||||
e.Hit(a.Skill.AttackTime != 0) //我方效果命中
|
||||
e.Hit(a.AttackTime != 0) //我方效果命中
|
||||
}
|
||||
for _, t := range defender.EffectCache {
|
||||
if t.GetInput() == attacker { //如果取反,说明是给对方添加的回合效果
|
||||
t.Hit(a.Skill.AttackTime != 0)
|
||||
t.Hit(a.AttackTime != 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -505,8 +458,8 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *action.S
|
||||
attacker.Exec(func(t input.Effect) bool {
|
||||
|
||||
t.OnSkill(input.Ctx{
|
||||
Input: defender,
|
||||
SkillEntity: a.Skill,
|
||||
Input: defender,
|
||||
SelectSkillAction: a,
|
||||
}) //调用伤害计算
|
||||
|
||||
return true
|
||||
@@ -516,7 +469,7 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *action.S
|
||||
|
||||
Input: attacker,
|
||||
|
||||
SkillEntity: a.Skill,
|
||||
SelectSkillAction: a,
|
||||
DamageZone: &info.DamageZone{
|
||||
Type: info.DamageType.Red,
|
||||
Damage: attacker.DamageZone.Damage,
|
||||
@@ -533,6 +486,12 @@ func IsNil(x interface{}) bool {
|
||||
rv := reflect.ValueOf(x)
|
||||
return rv.Kind() == reflect.Ptr && rv.IsNil()
|
||||
}
|
||||
func copyskill(t *action.SelectSkillAction) *action.SelectSkillAction {
|
||||
|
||||
oldskill, _ := deepcopy.Anything(t) //备份技能
|
||||
|
||||
return oldskill.(*action.SelectSkillAction)
|
||||
}
|
||||
|
||||
//回合有先手方和后手方,同时有攻击方和被攻击方
|
||||
|
||||
@@ -554,10 +513,9 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
|
||||
}
|
||||
f.First.InitAttackValue()
|
||||
f.Second.InitAttackValue()
|
||||
fmt.Println("房主", fattack.ID, "挑战者", sattack.ID)
|
||||
|
||||
switch {
|
||||
case sattack.ID != 0:
|
||||
case sattack != nil:
|
||||
|
||||
f.Second.Parseskill(f.Second, sattack) //解析到临时数据
|
||||
|
||||
@@ -568,7 +526,7 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
|
||||
return true
|
||||
})
|
||||
switch {
|
||||
case fattack.ID != 0: //房主也放弃出手
|
||||
case fattack != nil: //房主也放弃出手
|
||||
//是否miss都应该施加解析effect
|
||||
f.First.Parseskill(f.Second, fattack) //解析到临时数据
|
||||
|
||||
@@ -580,11 +538,11 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
|
||||
})
|
||||
switch {
|
||||
|
||||
case fattack.Skill.Priority < sattack.Skill.Priority:
|
||||
case fattack.SkillEntity.Priority < sattack.SkillEntity.Priority:
|
||||
|
||||
fattack, sattack = sattack, fattack //互换先手权
|
||||
f.First, f.Second = f.Second, f.First
|
||||
case fattack.Skill.Priority == sattack.Skill.Priority:
|
||||
case fattack.SkillEntity.Priority == sattack.SkillEntity.Priority:
|
||||
|
||||
if f.Second.GetProp(4, false) > f.First.GetProp(4, false) {
|
||||
fattack, sattack = sattack, fattack //互换先手权
|
||||
@@ -615,25 +573,28 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
|
||||
})
|
||||
//开始回合操作
|
||||
for i := 0; i < 2; i++ {
|
||||
var oldskill interface{}
|
||||
if i == 0 { //
|
||||
var oldskill *action.SelectSkillAction //原始技能
|
||||
var currentskill *action.SelectSkillAction //当前技能
|
||||
if i == 0 { //
|
||||
attacker, defender = f.First, f.Second
|
||||
oldskill = copyskill(fattack)
|
||||
currentskill = fattack
|
||||
|
||||
oldskill, _ = deepcopy.Anything(fattack.Skill) //备份技能
|
||||
} else {
|
||||
attacker, defender = f.Second, f.First
|
||||
oldskill, _ = deepcopy.Anything(sattack.Skill) //备份技能
|
||||
oldskill = copyskill(sattack)
|
||||
currentskill = sattack
|
||||
}
|
||||
|
||||
canuseskill := true
|
||||
// 实际上攻击方 还有系统选择放弃出手的
|
||||
if IsNil(oldskill) || attacker.CurrentPet.Info.Hp <= 0 {
|
||||
if IsNil(currentskill) || attacker.CurrentPet.Info.Hp <= 0 {
|
||||
|
||||
// attacker.AttackValue.SkillID = 0
|
||||
canuseskill = false
|
||||
|
||||
} else {
|
||||
if !oldskill.(*info.SkillEntity).CanUse() {
|
||||
if !action.CanUse(currentskill) {
|
||||
// attacker.AttackValue.SkillID = 0
|
||||
canuseskill = false
|
||||
}
|
||||
@@ -643,21 +604,17 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
|
||||
//结算状态
|
||||
//然后这里还可以处理自爆类
|
||||
return t.Skill_Hit_Pre(input.Ctx{
|
||||
Input: attacker,
|
||||
SkillEntity: fattack.Skill,
|
||||
Input: defender,
|
||||
SelectSkillAction: currentskill,
|
||||
}) //返回本身结算,如果false,说明不能使用技能了
|
||||
|
||||
})
|
||||
if canuseskill && canuseskillok { //可以使用技能
|
||||
if i == 0 { //
|
||||
f.processSkillAttack(attacker, defender, fattack)
|
||||
fattack.Skill = oldskill.(*info.SkillEntity) //还原技能效果
|
||||
fattack.Skill.Info.PP-- //减少PP
|
||||
} else {
|
||||
f.processSkillAttack(attacker, defender, sattack)
|
||||
sattack.Skill = oldskill.(*info.SkillEntity) //还原技能效果
|
||||
sattack.Skill.Info.PP-- //减少PP
|
||||
}
|
||||
|
||||
f.processSkillAttack(attacker, defender, currentskill)
|
||||
currentskill = oldskill
|
||||
fmt.Printf("技能4 %p\n", currentskill)
|
||||
currentskill.Info.PP--
|
||||
|
||||
}
|
||||
|
||||
@@ -668,6 +625,13 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
|
||||
return true
|
||||
})
|
||||
|
||||
//技能使用后
|
||||
attacker.Exec(func(t input.Effect) bool { //技能使用后的我方效果
|
||||
t.Skill_Useed(input.Ctx{Input: defender, SelectSkillAction: currentskill})
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
fmt.Println(i,
|
||||
// "玩家技能:", oldskill.(*info.SkillEntity).ID,
|
||||
"玩家技能伤害:", attacker.DamageZone.Damage,
|
||||
@@ -715,6 +679,8 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
|
||||
return true
|
||||
})
|
||||
f.First.AttackValue.RemainHp = int32(f.First.CurrentPet.Info.Hp)
|
||||
f.First.AttackValue.SkillList = f.First.CurrentPet.Info.SkillList
|
||||
f.First.AttackValue.SkillList[0].PP = 0
|
||||
f.Second.AttackValue.RemainHp = int32(f.Second.CurrentPet.Info.Hp)
|
||||
ret := info.AttackValueS{
|
||||
FAttack: *f.First.AttackValue,
|
||||
|
||||
@@ -3,6 +3,7 @@ package info
|
||||
import (
|
||||
element "blazing/common/data/Element"
|
||||
"blazing/common/data/xmlres"
|
||||
"fmt"
|
||||
|
||||
"blazing/modules/blazing/model"
|
||||
"math/rand"
|
||||
@@ -40,9 +41,11 @@ func CreateBattlePetEntity(info *model.PetInfo, rand *rand.Rand) *BattlePetEntit
|
||||
|
||||
ret.PetInfo = xmlres.PetMAP[int(info.ID)] //注入精灵信息
|
||||
ret.Info = info
|
||||
for i := 0; i < 4; i++ {
|
||||
for i := 0; i < len(info.SkillList); i++ {
|
||||
//todo 技能信息应该每回合进行深拷贝,保证每次的技能效果都是不一样的
|
||||
fmt.Printf("技能1 %p\n", &info.SkillList[i])
|
||||
ret.Skills[i] = CreateSkill(&info.SkillList[i], rand, ret)
|
||||
fmt.Printf("技能3 %p\n", ret.Skills[i].Info)
|
||||
}
|
||||
|
||||
return ret
|
||||
|
||||
@@ -71,7 +71,7 @@ func CreateSkill(skill *model.SkillInfo, rand *rand.Rand, pet *BattlePetEntity)
|
||||
}
|
||||
|
||||
ret.Info = skill
|
||||
|
||||
fmt.Printf("技能2 %p\n", ret.Info)
|
||||
return &ret
|
||||
}
|
||||
|
||||
@@ -189,7 +189,6 @@ func (s *SkillEntity) Criticalrandom() decimal.Decimal {
|
||||
// Accuracy 优化版命中率计算(用绝对值和正负判断处理等级)
|
||||
func (a *SkillEntity) GetAccuracy(level int) uint32 {
|
||||
// 基础参数校验
|
||||
|
||||
|
||||
if level >= 0 { //强化等级
|
||||
return uint32(CalculateRealValue((a.Accuracy), level))
|
||||
|
||||
@@ -238,10 +238,10 @@ type ReadyFightPetInfo struct {
|
||||
|
||||
// 精灵最大HP,@UInt long
|
||||
MaxHp uint32 `fieldDesc:"最大HP" `
|
||||
SkillListLen uint32
|
||||
SkillListLen uint32 `struc:"sizeof=SkillList"`
|
||||
// 技能信息列表(固定4个元素,技能ID和剩余PP,无技能则为0)
|
||||
// List<SkillInfo>,初始化容量为4
|
||||
SkillList [4]model.SkillInfo `fieldDesc:"技能信息 技能ID跟剩余PP 固定32字节 没有给0" serialize:"fixedLength=4,type=structArray"`
|
||||
SkillList []model.SkillInfo `fieldDesc:"技能信息 技能ID跟剩余PP 固定32字节 没有给0" serialize:"fixedLength=4,type=structArray"`
|
||||
|
||||
// 精灵捕获时间,@UInt long
|
||||
CatchTime uint32 `fieldDesc:"精灵捕获时间" `
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
)
|
||||
|
||||
type Ctx struct {
|
||||
*Input //施加方
|
||||
*action.BaseAction //action本身
|
||||
*info.SkillEntity //技能
|
||||
*info.DamageZone //伤害
|
||||
*Input //施加方
|
||||
*action.SelectSkillAction //action本身
|
||||
|
||||
*info.DamageZone //伤害
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
func (u *Input) UseSkill(opp *Input, skill *info.SkillEntity) {
|
||||
func (u *Input) UseSkill(opp *Input, skill *action.SelectSkillAction) {
|
||||
|
||||
skill.Crit = 0
|
||||
if skill.Category() == info.Category.STATUS { //属性技能不用算暴击
|
||||
|
||||
@@ -67,6 +67,7 @@ func (i *Input) InitAttackValue() {
|
||||
if old != nil {
|
||||
i.AttackValue.Prop = old.Prop
|
||||
i.AttackValue.Status = old.Status
|
||||
i.AttackValue.SkillList = old.SkillList
|
||||
}
|
||||
|
||||
}
|
||||
@@ -113,9 +114,9 @@ func (i *Input) GetStatusBonus() float64 {
|
||||
// 解析并 施加effect
|
||||
func (i *Input) Parseskill(defender *Input, skill *action.SelectSkillAction) {
|
||||
i.EffectCache = make([]Effect, 0) //先把上一回合数据清空
|
||||
temparg := skill.Skill.SideEffectArgS
|
||||
temparg := skill.SideEffectArgS
|
||||
|
||||
for _, v := range skill.Skill.SideEffectS {
|
||||
for _, v := range skill.SideEffectS {
|
||||
|
||||
t := Geteffect(EffectType.Skill, v)
|
||||
|
||||
|
||||
@@ -21,7 +21,9 @@ func (e *EffectNode) OnOwnerSwitchIn(ctx input.Ctx) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
//自身下场,清除掉技能效果
|
||||
func (e *EffectNode) OnOwnerSwitchOut(ctx input.Ctx) bool {
|
||||
e.Input.AttackValue = nil
|
||||
//自身下场清除掉自身的回合效果
|
||||
//this.GetBattle().Effects[this.GetInput().UserID].RemoveEffect(this)
|
||||
e.NotALive()
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
// 检查,激活,延后
|
||||
// /基础节点
|
||||
type EffectNode struct {
|
||||
Effect
|
||||
duration int // 默认为-1 持续回合/次(0 = 即时生效,>0 = 回合数 ,负数是永久) \
|
||||
|
||||
Input *input.Input
|
||||
|
||||
@@ -22,13 +22,13 @@ func (e *EffectNode) Skill_Hit_to(ctx input.Ctx) bool {
|
||||
return true
|
||||
}
|
||||
func (e *EffectNode) OnSkill(ctx input.Ctx) bool {
|
||||
if e.Effect != nil {
|
||||
if e.Hit() { //没命中
|
||||
e.Effect.OnHit(ctx.Input, ctx.SkillEntity)
|
||||
} else {
|
||||
e.Effect.OnMiss(ctx.Input, ctx.SkillEntity)
|
||||
}
|
||||
}
|
||||
// if e.Effect != nil {
|
||||
// if e.Hit() { //没命中
|
||||
// e.Effect.OnHit(ctx.Input, ctx.SkillEntity)
|
||||
// } else {
|
||||
// e.Effect.OnMiss(ctx.Input, ctx.SkillEntity)
|
||||
// }
|
||||
// }
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -41,15 +41,16 @@ func (e *EffectNode) Skill_Use(ctx input.Ctx) bool {
|
||||
return true
|
||||
}
|
||||
func (e *EffectNode) Skill_Useed(ctx input.Ctx) bool {
|
||||
if e.Effect != nil {
|
||||
if e.Input.CurrentPet.Info.Hp == 0 {
|
||||
e.OnDefeat(ctx.Input, ctx.SkillEntity) //死亡
|
||||
// if e.Effect != nil {
|
||||
// if e.Input.CurrentPet.Info.Hp == 0 {
|
||||
// e.OnDefeat(ctx.Input, ctx.SkillEntity) //死亡
|
||||
|
||||
} else {
|
||||
e.OnAlive(ctx.Input, ctx.SkillEntity) //存活
|
||||
}
|
||||
// } else {
|
||||
// e.OnAlive(ctx.Input, ctx.SkillEntity) //存活
|
||||
// }
|
||||
|
||||
}
|
||||
// }
|
||||
// return true
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -93,11 +93,11 @@ func (f *FightC) UseSkill(c common.PlayerI, id int32) {
|
||||
BaseAction: action.NewBaseAction(c.GetInfo().UserID),
|
||||
}
|
||||
//ret.PetInfo = f.GetInputByPlayer(c, false).CurrentPet
|
||||
ret.ID = uint32(id)
|
||||
|
||||
for _, v := range f.GetInputByPlayer(c, false).CurrentPet.Skills {
|
||||
|
||||
if v != nil && v.ID == int(id) {
|
||||
ret.Skill = v
|
||||
ret.SkillEntity = v
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
@@ -55,14 +55,14 @@ func (p *Player) AddPetExp(petinfo *model.PetInfo, addExp uint32, bro bool) {
|
||||
// 处理技能学习
|
||||
canLearnSkillList := LastFourElements(petinfo.GetLevelRangeCanLearningSkills(originalLevel, petinfo.Level)) //获取最后四个技能,如果不足,那就取全部技能
|
||||
|
||||
for i := 0; i < 4; i++ {
|
||||
for i := 0; i < len(petinfo.SkillList); i++ {
|
||||
|
||||
if petinfo.SkillList[i].ID == 0 {
|
||||
if len(canLearnSkillList) != 0 {
|
||||
skid := canLearnSkillList[len(canLearnSkillList)-1]
|
||||
petinfo.SkillList[i].ID = skid
|
||||
petinfo.SkillList[i].PP = uint32(xmlres.SkillMap[int(skid)].MaxPP)
|
||||
petinfo.SkillListLen += 1
|
||||
|
||||
canLearnSkillList = canLearnSkillList[:len(canLearnSkillList)-1]
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ func (s *BaseSysLoginService) Login(ctx context.Context, req *v1.BaseOpenLoginRe
|
||||
baseSysUser = model.NewBaseSysUser()
|
||||
)
|
||||
|
||||
vcode, _ := cool.CacheManager.Get(ctx, captchaId)
|
||||
vcode, _ := cool.CacheManager.Get(ctx, "login:"+captchaId)
|
||||
if vcode.String() != verifyCode {
|
||||
err = gerror.New("验证码错误")
|
||||
return
|
||||
@@ -82,7 +82,7 @@ func (*BaseSysLoginService) Captcha(req *v1.BaseOpenCaptchaReq) (interface{}, er
|
||||
|
||||
result.Data = `data:image/svg+xml;base64,` + svgbase64
|
||||
result.CaptchaId = guid.S()
|
||||
cool.CacheManager.Set(ctx, result.CaptchaId, captchaText, 1800*time.Second)
|
||||
cool.CacheManager.Set(ctx, "login:"+result.CaptchaId, captchaText, 1800*time.Second)
|
||||
cool.Loger.Debug(ctx, "验证码", result.CaptchaId, captchaText)
|
||||
return result, err
|
||||
}
|
||||
|
||||
@@ -95,9 +95,10 @@ type PetInfo struct {
|
||||
|
||||
// 速度学习力(@UInt long → uint32)
|
||||
EvSpeed uint32 `fieldDesc:"速度学习力" `
|
||||
SkillListLen uint32
|
||||
SkillListLen uint32 `struc:"sizeof=SkillList"`
|
||||
|
||||
// 技能信息:固定4条,空则赋值0(固定长度List → [4]SkillInfo,零值即符合“赋值0”)
|
||||
SkillList [4]SkillInfo
|
||||
SkillList []SkillInfo
|
||||
|
||||
// 捕捉时间(@UInt long → 若为时间戳用uint32;若需时间类型可改为time.Time,需配合序列化处理)
|
||||
CatchTime uint32 `fieldDesc:"捕捉时间" `
|
||||
@@ -295,13 +296,12 @@ func GenPetInfo(
|
||||
|
||||
// ---- 技能学习 ----
|
||||
skills := LastFourElements(p.GetLevelRangeCanLearningSkills(0, p.Level)) // 最后四个技能
|
||||
p.SkillListLen = uint32(len(skills))
|
||||
|
||||
for i := 0; i < len(skills) && i < len(p.SkillList); i++ {
|
||||
for i := 0; i < len(skills) && i < 4; i++ {
|
||||
skillID := skills[i]
|
||||
if info, ok := xmlres.SkillMap[int(skillID)]; ok {
|
||||
p.SkillList[i].ID = skillID
|
||||
p.SkillList[i].PP = uint32(info.MaxPP)
|
||||
p.SkillList = append(p.SkillList, SkillInfo{ID: skillID, PP: uint32(info.MaxPP)})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user