feat(fight): 重构战斗系统技能逻辑与精灵切换功能

- 优化技能执行流程,统一使用 SelectSkillAction 作为技能载体
- 移除冗余的技能 ID 字段,简化数据结构
- 调整命中判断和技能效果触发机制,提升准确性
- 修改精灵切换与捕获相关方法参数格式
- 更新技能列表结构为动态数组以支持灵活长度
- 完善睡眠等异常状态的处理逻辑
- 修复战斗中技能 PP 扣减及副本还原问题
- 清理无用代码,如多余的 FindWithIndex 函数定义
- 强化验证码缓存键命名规则,增强安全性
This commit is contained in:
2025-10-26 20:56:03 +08:00
parent 2678cd9685
commit e75ecd413d
25 changed files with 195 additions and 184 deletions

10
common/utils/help.go Normal file
View 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
}

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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
}

View File

@@ -0,0 +1,11 @@
package action
func CanUse(s *SelectSkillAction) bool {
if s == nil {
return false
}
return s.Info.PP > 0
}

View File

@@ -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
}

View File

@@ -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) {

View File

@@ -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() {

View File

@@ -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
}

View File

@@ -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
}
// 默认添加回合

View File

@@ -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{}) //睡眠
}

View File

@@ -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,

View File

@@ -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

View File

@@ -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))

View File

@@ -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:"精灵捕获时间" `

View File

@@ -6,8 +6,8 @@ import (
)
type Ctx struct {
*Input //施加方
*action.BaseAction //action本身
*info.SkillEntity //技能
*info.DamageZone //伤害
*Input //施加方
*action.SelectSkillAction //action本身
*info.DamageZone //伤害
}

View File

@@ -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 { //属性技能不用算暴击

View File

@@ -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)

View File

@@ -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()

View File

@@ -8,7 +8,6 @@ import (
// 检查,激活,延后
// /基础节点
type EffectNode struct {
Effect
duration int // 默认为-1 持续回合/次0 = 即时生效,>0 = 回合数 ,负数是永久) \
Input *input.Input

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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]
}

View File

@@ -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
}

View File

@@ -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)})
}
}