This commit is contained in:
1
2025-09-30 10:34:41 +00:00
32 changed files with 447 additions and 395 deletions

View File

@@ -77,7 +77,7 @@ func StartServer() {
// testjsonrpc()
// })
err := http.ListenAndServe(rpcport, rpcServer)
err := http.ListenAndServe("0.0.0.0"+rpcport, rpcServer)
cool.Loger.Debug(context.Background(), "jsonrpc server fail", err)
}

View File

@@ -184,3 +184,22 @@ func (h Controller) SetPetExp(data *pet.PetSetExpInboundInfo, c *player.Player)
return &pet.PetSetExpOutboundInfo{}, 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 {
return item.CatchTime == data.CatchTime
})
if ok {
for i := 0; i < 4; 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)
}
}
}
return &pet.ChangeSkillOutInfo{
CatchTime: data.CatchTime,
}, 0
}

View File

@@ -10,6 +10,7 @@ require (
github.com/antlabs/stl v0.0.2 // indirect
github.com/antlabs/timer v0.1.4 // indirect
github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df // indirect
github.com/brunoga/deep v1.2.5 // indirect
github.com/butoften/array v1.0.9 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/clbanning/mxj/v2 v2.7.0 // indirect
@@ -29,6 +30,7 @@ require (
github.com/panjf2000/ants/v2 v2.11.3 // indirect
github.com/samber/lo v1.51.0 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/tiendc/go-deepcopy v1.7.1 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect

View File

@@ -10,6 +10,8 @@ github.com/badu/bus v1.0.3 h1:MViRRyuFraixfaI2rfAqrkQao7ZilyFz6HacbmPk1aE=
github.com/badu/bus v1.0.3/go.mod h1:77qc3Fi2qSUoakSR34PIWrTHB6gM2NJKceRsYUbx41Q=
github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0=
github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM=
github.com/brunoga/deep v1.2.5 h1:bigq4eooqbeJXfvTfZBn3AH3B1iW+rtetxVeh0GiLrg=
github.com/brunoga/deep v1.2.5/go.mod h1:GDV6dnXqn80ezsLSZ5Wlv1PdKAWAO4L5PnKYtv2dgaI=
github.com/butoften/array v1.0.9 h1:/kPHAc+fHz72u5B23p2W1RzIoT2eOYvhsY0tKMvsHEc=
github.com/butoften/array v1.0.9/go.mod h1:RgJ3XIUy/Z2rQllTkXmS4LtfqJeD3mjYJ4XoP3odTqM=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
@@ -60,6 +62,8 @@ github.com/samber/lo v1.51.0 h1:kysRYLbHy/MB7kQZf5DSN50JHmMsNEdeY24VzJFu7wI=
github.com/samber/lo v1.51.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/tiendc/go-deepcopy v1.7.1 h1:LnubftI6nYaaMOcaz0LphzwraqN8jiWTwm416sitff4=
github.com/tiendc/go-deepcopy v1.7.1/go.mod h1:4bKjNC2r7boYOkD2IOuZpYjmlDdzjbpTRyCx+goBCJQ=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=

View File

@@ -15,4 +15,6 @@ type FightI interface {
Capture(c PlayerI, id uint32)
GetRand() *rand.Rand
LoadPercent(c PlayerI, percent int32)
IsFirst(c PlayerI) bool
}

View File

@@ -13,17 +13,16 @@ type EnumPlayerOperation int
// 定义读秒倒计时期间玩家可执行的操作枚举
var PlayerOperations = enum.New[struct {
SystemGiveUp EnumPlayerOperation `enum:"-1"` // 系统选择放弃出手(比如没有PP)
SelectSkill EnumPlayerOperation `enum:"0"` // 选择技能-6到6
ActiveSwitch EnumPlayerOperation `enum:"2"` // 主动切换(中切)
UsePotion EnumPlayerOperation `enum:"3"` // 使用药剂(捕捉、逃跑等)
Escape EnumPlayerOperation `enum:"4"` // 逃跑(等级最高,以及掉线)
PlayerOffline EnumPlayerOperation `enum:"5"` // 玩家掉线
//SystemGiveUp EnumPlayerOperation `enum:"-1"` // 系统选择放弃出手(比如没有PP)
//系统放弃出手就是SKILL ID=0
SelectSkill EnumPlayerOperation `enum:"0"` // 选择技能-6到6
ActiveSwitch EnumPlayerOperation `enum:"2"` // 主动切换(中切)
UsePotion EnumPlayerOperation `enum:"3"` // 使用药剂(捕捉、逃跑等)
Escape EnumPlayerOperation `enum:"4"` // 逃跑(等级最高,以及掉线)
PlayerOffline EnumPlayerOperation `enum:"5"` // 玩家掉线
// BeExpelledSwitch EnumPlayerOperation `enum:"6"` // 被驱逐切换
}]()
// BattleActionI 战斗动作接口
type BattleActionI interface {
GetPlayerID() uint32
@@ -33,14 +32,10 @@ type BattleActionI interface {
// SelectSkillAction 选择技能的战斗动作
type SelectSkillAction struct {
PlayerID uint32 // 玩家ID
Skill *info.SkillEntity // 使用的技能
PetInfo *info.BattlePetEntity // 使用技能的宠物
Attack info.AttackValue
}
func (s *SelectSkillAction) GetPlayerID() uint32 {
return s.PlayerID
BaseAction
Skill *info.SkillEntity // 使用的技能
//PetInfo *info.BattlePetEntity // 使用技能的宠物
Attack info.AttackValue
}
// Priority 返回动作优先级
@@ -126,18 +121,6 @@ func (e *OverTimeAction) Priority() int {
return int(PlayerOperations.PlayerOffline)
}
// SystemGiveUpAction 系统强制放弃出手的动作
type SystemGiveUpAction struct {
BaseAction
Reason string // 放弃原因如没有PP值、宠物全部倒下等
LastPet info.BattlePetEntity // 最后在场的宠物
}
// Priority 返回动作优先级
func (s *SystemGiveUpAction) Priority() int {
return int(PlayerOperations.SystemGiveUp)
}
// PlayerOfflineAction 玩家掉线的战斗动作
type PlayerOfflineAction struct {
BaseAction

View File

@@ -1,9 +1,12 @@
package effect
import (
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"blazing/logic/service/fight/node"
"github.com/shopspring/decimal"
)
/**
@@ -23,6 +26,8 @@ func init() {
// 命中之后
func (e *Effect1) OnHit(opp *input.Input, skill *info.SkillEntity) {
e.Input.CurrentPet.Info.Hp += uint32(e.Input.DamageZone.Attack / 2)
e.Input.Heal(
&action.SelectSkillAction{}, (e.Input.DamageZone.Damage.Div(decimal.NewFromInt(2))),
)
}

View File

@@ -20,7 +20,7 @@ type Effect20 struct {
}
// 使用技能时不可被继承继承Miss和Hit就行
func (e *Effect20) OnSkill(opp *input.Input, skill *info.SkillEntity) {
func (e *Effect20) OnSkill(input.Ctx) {
e.Input.AddEffect(input.Geteffect(input.EffectType.Status, int(info.PetStatus.Tired)))
}

View File

@@ -54,7 +54,7 @@ func (e *Effect62) SetArgs(t *input.Input, a ...int) {
}
// 因为对方切精灵,这个效果也要无效掉
func (this *Effect62) OnSwitchIn() bool {
func (this *Effect62) OnSwitchIn(input.Ctx) bool {
if this.Hide { //如果还在隐藏,就直接返回
return true
}

View File

@@ -1,6 +1,7 @@
package effect
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"blazing/logic/service/fight/node"
)
@@ -22,19 +23,19 @@ func init() {
}
// 重写死亡,如果击败,就出触发死亡事件,判断是目标精灵
func (this *Effect67) OnDefeat() bool {
func (this *Effect67) OnDefeat(*input.Input, *info.SkillEntity) bool {
return true
}
// 登场是下一只 减少对方下次出战精灵的最大体力1/n
func (this *Effect67) OnSwitchIn() bool {
func (this *Effect67) OnSwitchIn(input.Ctx) bool {
return true
}
// 下场不消除buff
func (this *Effect67) OnSwitchOut() bool {
func (this *Effect67) OnSwitchOut(input.Ctx) bool {
//下场默认清除effect
panic("not implemented") // TODO: Implement
}

View File

@@ -14,7 +14,7 @@ import (
*/
func init() {
input.InitEffect(input.EffectType.Skill, 9, &Effect8{
input.InitEffect(input.EffectType.Skill, 8, &Effect8{
EffectNode: node.EffectNode{},
})
@@ -25,12 +25,11 @@ type Effect8 struct {
}
// 伤害落实前触发,限制最大伤害
func (e *Effect8) Attack(opp *input.Input, v *info.DamageZone) {
if v.Type == info.DamageType.Red {
v.Damage = decimal.NewFromInt(utils.Min(v.Damage.IntPart(), int64(opp.CurrentPet.Info.Hp)-1))
func (e *Effect8) Damage_Floor(ctx input.Ctx) bool {
if ctx.DamageZone.Type == info.DamageType.Red {
ctx.DamageZone.Damage = decimal.NewFromInt(utils.Min(ctx.DamageZone.Damage.IntPart(), int64(ctx.Input.CurrentPet.Info.Hp)-1))
}
return true
}

View File

@@ -30,11 +30,15 @@ type DrainHP struct {
func (e *DrainHP) OnTurnStart(opp *input.Input) {
e.Input.Damage(e.Input, info.DamageZone{
e.Input.Damage(input.Ctx{
Type: info.DamageType.Red,
Damage: decimal.NewFromUint64(uint64(opp.CurrentPet.Info.MaxHp)).
Div(decimal.NewFromInt(8)),
Input: opp,
DamageZone: &info.DamageZone{
Type: info.DamageType.Red,
Damage: decimal.NewFromUint64(uint64(opp.CurrentPet.Info.MaxHp)).
Div(decimal.NewFromInt(8)),
},
})
}

View File

@@ -1,7 +1,6 @@
package fight
import (
"blazing/common/data/xmlres"
"blazing/logic/service/common"
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
@@ -78,6 +77,17 @@ func (f *FightC) GetRand() *rand.Rand {
}
// 获取随机数
func (f *FightC) IsFirst(play common.PlayerI) bool {
if f.First.Player == play {
return true
}
return false
}
// 加载进度
func (f *FightC) LoadPercent(c common.PlayerI, percent int32) {
f.GetInputByPlayer(c, true).Player.SendLoadPercent(info.LoadPercentOutboundInfo{
@@ -323,8 +333,8 @@ func (f *FightC) battleLoop() {
f.closefight = true
case *action.ActiveSwitchAction: //切换上场的,切换方放弃出手
f.enterturn(BattleActionI[1],
&action.SystemGiveUpAction{BaseAction: action.NewBaseAction(BattleActionI[0].GetPlayerID())}) //切换,相当于后手直接出手
f.enterturn(BattleActionI[1].(*action.SelectSkillAction),
&action.SelectSkillAction{BaseAction: action.NewBaseAction(BattleActionI[0].GetPlayerID())}) //切换,相当于后手直接出手
case *action.UseItemAction: //使用道具
//fmt.Println(faction.ItemID)
@@ -333,7 +343,7 @@ func (f *FightC) battleLoop() {
case faction.ItemID >= 30001 && faction.ItemID <= 300010: //胶囊
//todo 将血量和技能pp传回enterturn
tt, ok := f.Our.Player.(*player.Player)
//tt, ok := f.Our.Player.(*player.Player)
mo, ism := f.Opp.Player.(*player.AI_player)
if ok && ism && mo.CanCapture { //如果获取玩家
@@ -369,11 +379,11 @@ func (f *FightC) battleLoop() {
// 其他情况
fmt.Println("ItemID 不在指定范围内")
}
f.enterturn(BattleActionI[1], &action.SystemGiveUpAction{BaseAction: action.NewBaseAction(BattleActionI[0].GetPlayerID())}) //切换,相当于后手直接出手
f.enterturn(BattleActionI[1].(*action.SelectSkillAction), &action.SelectSkillAction{BaseAction: action.NewBaseAction(BattleActionI[0].GetPlayerID())}) //切换,相当于后手直接出手
default: //选择技能或者放弃出手
//回合前操作,比如挂载buff
f.enterturn(BattleActionI[0], BattleActionI[1])
f.enterturn(BattleActionI[0].(*action.SelectSkillAction), BattleActionI[1].(*action.SelectSkillAction))
//回合后操作
}
@@ -382,52 +392,22 @@ func (f *FightC) battleLoop() {
}
// 解析并 施加effect
func (f *FightC) parseskill(attacker, defender *input.Input, id *action.SelectSkillAction) {
temparg := id.Skill.SideEffectArgS
for _, v := range id.Skill.SideEffectS {
t := input.Geteffect(input.EffectType.Skill, v)
args := xmlres.EffectArgs[v]
if t.ID != 0 && t.Effect.GetOwner() { //如果取反,说明是给对方添加的回合效果
//实际上,owner永远为反,说明是对方给我添加的
t.Effect.SetArgs(attacker, temparg[:args]...) //设置入参,施加方永远是我方
//给双方添加
defender.AddEffect(t)
} else {
t.Effect.SetArgs(attacker, temparg[:args]...) //设置入参
attacker.AddEffect(t)
}
temparg = temparg[args:]
}
}
func (f *FightC) initAttackers(fattack action.BattleActionI) {
// 伤害值
// 根据攻击方归属设置当前战斗的主/次攻击方属性
if fattack.GetPlayerID() == f.ownerID {
f.First, f.Second = f.Our, f.Opp // 攻击方为我方时,主攻击方是我方
} else {
f.First, f.Second = f.Opp, f.Our // 攻击方为对方时,主攻击方是对方
}
fmt.Println("先手", f.First.CurrentPet.Info.CatchTime, "后手", f.Second.CurrentPet.Info.CatchTime)
// TODO: 在这里调用技能结算逻辑
}
// 处理技能攻击逻辑
func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *action.SelectSkillAction) {
attacker.Exec(func(t input.Effect) bool { //计算命中
a.Skill.AttackTimeC(attacker.GetProp(5, true)) //计算命中
t.Skill_Pre(input.Ctx{
defender.Exec(func(t input.Effect) bool { //计算闪避 ,然后修改对方命中),同时相当于计算属性无效这种
t.Skill_Hit_to(input.Ctx{
Input: attacker,
SkillEntity: a.Skill, //相当于先调整基础命中,不光调整命中,这里还能调整技能属性,暴击率
})
return true
})
attacker.Exec(func(t input.Effect) bool { //计算命中 miss改命中
t.Skill_Hit(input.Ctx{ //计算变威力
Input: attacker,
SkillEntity: a.Skill,
}) //相当于先调整基础命中,不光调整命中,这里还能调整技能属性,暴击率
@@ -445,6 +425,7 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *action.S
return true
})
f.parseskill(attacker, defender, a) //是否miss都应该施加解析effect
// 记录技能信息
attacker.AttackValue.SkillID = uint32(a.Skill.ID) //获取技能ID
@@ -454,17 +435,19 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *action.S
if attacker.AttackValue.AttackTime > 0 { //如果命中
attacker.DamageZone.Damage = int(attacker.CalculatePower(defender, a.Skill).IntPart())
attacker.DamageZone.Damage = attacker.CalculatePower(defender, a.Skill)
attacker.AttackValue.IsCritical = a.Skill.Crit
if attacker.AttackValue.IsCritical == 1 {
attacker.DamageZone.Attack *= 2
//暴击翻倍
attacker.DamageZone.Damage = attacker.DamageZone.Damage.Mul(decimal.NewFromInt(2))
}
attacker.Exec(func(t input.Effect) bool {
//这里实现应该参考本地技能是否命中,然后
t.Hit(true) //我方效果命中
return true
@@ -482,13 +465,23 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *action.S
attacker.Exec(func(t input.Effect) bool {
t.OnSkill(defender, a.Skill) //调用伤害计算
t.OnSkill(input.Ctx{
Input: defender,
SkillEntity: a.Skill,
}) //调用伤害计算
return true
})
defender.Damage(attacker, a.Skill, info.DamageZone{
Type: info.DamageType.Red,
Damage: decimal.NewFromInt(int64(attacker.DamageZone.Attack)),
defender.Damage(input.Ctx{
Input: attacker,
SkillEntity: a.Skill,
DamageZone: &info.DamageZone{
Type: info.DamageType.Red,
Damage: attacker.DamageZone.Damage,
},
})
//这里其实是受到致死伤害
//然后先触发死亡效果消除所有buff
@@ -497,24 +490,55 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *action.S
//回合有先手方和后手方,同时有攻击方和被攻击方
func (f *FightC) enterturn(fattack, sattack BattleActionI) {
func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
if f.closefight { //战斗结束
return
}
f.initAttackers(fattack) //初始化先后手
var attacker, defender *input.Input
// 伤害值
// 根据攻击方归属设置当前战斗的主/次攻击方属性
if fattack.GetPlayerID() == f.ownerID {
f.First, f.Second = f.Our, f.Opp // 攻击方为我方时,主攻击方是我方
} else {
f.First, f.Second = f.Opp, f.Our // 攻击方为对方时,主攻击方是对方
}
fmt.Println("先手", f.First.CurrentPet.Info.CatchTime, "后手", f.Second.CurrentPet.Info.CatchTime)
//是否miss都应该施加解析effect
f.First.Parseskill(f.Second, fattack)
f.First.Exec(func(t input.Effect) bool { //回合开始前
//结算状态
t.Compare_Pre(fattack, sattack) //先结算技能的优先级
return true
})
switch {
case fattack.Skill.Priority < sattack.Skill.Priority:
fattack, sattack = sattack, fattack //互换先手权
case fattack.Skill.Priority == sattack.Skill.Priority:
if f.Second.GetProp(4, false) > f.First.GetProp(4, false) {
fattack, sattack = sattack, fattack //互换先手权
}
}
f.First.First = true
f.Second.First = false
//开始回合操作
for i := 0; i < 2; i++ {
var attackeraction BattleActionI
if i == 0 { //
attacker, defender = f.First, f.Second
attackeraction = fattack
attacker.First = true //先手技能
} else {
var attackeraction action.BattleActionI
if i != 0 {
attacker, defender = f.Second, f.First
attackeraction = sattack
attacker.First = false //先手技能
@@ -524,34 +548,47 @@ func (f *FightC) enterturn(fattack, sattack BattleActionI) {
attacker.Exec(func(t input.Effect) bool { //回合开始前
//结算状态
t.OnTurnStart(defender)
t.Turn_Start(input.Ctx{Input: attacker})
return true
})
skill, ok := attackeraction.(*SelectSkillAction)
skill, ok := attackeraction.(*action.SelectSkillAction)
canuseskill := true
if !ok || attacker.CurrentPet.Info.Hp <= 0 { //还有系统选择放弃出手的
attacker.AttackValue.SkillID = 0
canuseskill = false
}
oldskill, _ := deepcopy.Anything(skill.Skill) //备份技能
canuseskillok := attacker.Exec(func(t input.Effect) bool { //这个是能否使用技能
//结算状态
//然后这里还可以处理自爆类
return t.CanSkill(defender, skill) //返回本身结算,如果false,说明不能使用技能了
var oldskill interface{}
if ok {
oldskill, _ = deepcopy.Anything(skill.Skill) //备份技能
canuseskillok := attacker.Exec(func(t input.Effect) bool { //这个是能否使用技能
//结算状态
//然后这里还可以处理自爆类
return t.Skill_Hit_Pre(input.Ctx{
Input: attacker,
SkillEntity: skill.Skill,
}) //返回本身结算,如果false,说明不能使用技能了
})
if !canuseskill || !canuseskillok { //可以使用技能
f.parseskill(attacker, defender, a) //是否miss都应该施加解析effect
f.processSkillAttack(attacker, defender, skill)
skill.Skill = oldskill.(*info.SkillEntity) //还原技能效果
}
skill.Skill.Info.PP-- //减少PP
}
//技能使用后
defender.Exec(func(t input.Effect) bool {
t.Skill_Use(input.Ctx{Input: attacker})
return true
})
fmt.Println(i,
"玩家技能伤害:", attacker.DamageZone.Attack,
"玩家技能伤害:", attacker.DamageZone.Damage,
"自身剩余血量:", attacker.CurrentPet.Info.Hp,
"对手剩余血量:", defender.CurrentPet.Info.Hp,
)
@@ -583,13 +620,17 @@ func (f *FightC) enterturn(fattack, sattack BattleActionI) {
f.First.Exec(func(t input.Effect) bool { //这个是能否使用技能
//结算状态
t.TurnEnd(f.Second) //返回本身结算,如果false,说明不能使用技能了
t.Turn_End(input.Ctx{
Input: f.Second,
}) //返回本身结算,如果false,说明不能使用技能了
return true
})
f.Second.Exec(func(t input.Effect) bool { //这个是能否使用技能
//结算状态
t.TurnEnd(f.First) //返回本身结算,如果false,说明不能使用技能了
t.Turn_End(input.Ctx{
Input: f.First,
})
return true
})
f.First.AttackValue.RemainHp = int32(f.First.CurrentPet.Info.Hp)
@@ -619,7 +660,7 @@ func (f *FightC) enterturn(fattack, sattack BattleActionI) {
}
}
f.Switch = []*ActiveSwitchAction{}
f.Switch = []*action.ActiveSwitchAction{}
ff.Player.SendAttackValue(ret)
})

View File

@@ -85,4 +85,3 @@ func (u *BattlePetEntity) Type() *element.ElementCombination {
return ff
}

View File

@@ -51,9 +51,9 @@ type SkillEntity struct {
xmlres.Move
Info *model.SkillInfo
DamageValue decimal.Decimal // 伤害值
Rand *rand.Rand
Pet *BattlePetEntity
// DamageValue decimal.Decimal // 伤害值
Rand *rand.Rand
Pet *BattlePetEntity
//MaxValue func(ahp, bhp uint32) decimal.Decimal
Crit uint32
AttackTime uint32

View File

@@ -6,34 +6,36 @@ import (
)
type Effect interface {
Compare_Pre(fattack, sattack *action.SelectSkillAction) bool
Fight_Start(ctx Ctx) bool //战斗开始
Turn_Start(ctx Ctx) //回合开始,注入特性
Skill_Pre(ctx Ctx) //技能修改,比如变威力 行动开始前,注入视为等参数在这里实现
Skill_PreUse(ctx Ctx) // 技能命中前触发//预处理受击技能 被攻击方效果,比如受击时无效技能这样
OnSkill(ctx Ctx) // 触发on miss onhit
//技能命中前的返回值代表是否可以出手 ,对命中本身的修改应该是对上下文本身的修改
Skill_Hit_Pre(ctx Ctx) bool //技能修改 行动开始前,注入视为等参数在这里实现
Skill_Hit(ctx Ctx) bool //这是是命中后的对技能的修改,比如变威力
Skill_Hit_to(ctx Ctx) bool // 技能命中前触发//预处理受击技能 被攻击方效果,比如受击时无效技能这样
OnSkill(ctx Ctx) bool // 触发on miss onhit
CanSkill(ctx Ctx) bool //使用技能 可以取消用技能节点 技能无效节点锁定伤害加上
//Skill_Can(ctx Ctx) bool //使用技能 可以取消用技能节点 技能无效节点锁定伤害加上
Damage_ADD(ctx Ctx) bool // 攻击前触发 ,这时候就是+区间
Damage_Mul(ctx Ctx) bool // 攻击触发
Damage_Floor(ctx Ctx) bool // 保底伤害
Damage_DIV(ctx Ctx) bool //受击前触发 这时候就是百分比减伤区间
Damage_SUB(ctx Ctx) bool // 受击触发 这时候就是点数减伤
Damage_Lock(ctx Ctx) bool //锁定伤害
//Damage_Post(ctx Ctx) bool // 伤害结算后触发(血量扣除后),克制等重写伤害
Damage_Floor(ctx Ctx) bool // 保底伤害
Damage_DIV(ctx Ctx) bool //受击前触发 这时候就是百分比减伤区间
Damage_SUB(ctx Ctx) bool // 受击触发 这时候就是点数减伤
Damage_Lock(ctx Ctx) bool //锁定伤害
Damage_Locked(ctx Ctx) bool //被动方锁定伤害
Damage_Shield(ctx Ctx) bool // 护盾值变化时触发
Damage_Use(ctx Ctx) bool // 伤害作用
Skill_SubPP(ctx Ctx) bool //技能PP减少节点
OnDefeat(opp *Input) bool // 精灵被击败时触发
//Damage_Use(ctx Ctx) bool // 伤害作用
Skill_Use(ctx Ctx) bool //技能PP减少节点
Skill_Useed(ctx Ctx) bool //技能PP减少节点
//OnDefeat(opp *Input) bool // 精灵被击败时触发
OnSwitchIn(ctx Ctx) bool // 精灵出战 / 上场时触发
OnSwitchOut(ctx Ctx) bool // 精灵下场时触发
OnOwnerSwitchIn(ctx Ctx) bool // 所属玩家精灵出战时触发
OnOwnerSwitchOut(ctx Ctx) bool // 所属玩家精灵下场时触发
TurnEnd(ctx Ctx) //闪避率计算,,实际上是修改命中的判断
Turn_End(ctx Ctx) //回合结束计算
PreBattleEnd(ctx Ctx) bool //战斗结束前
OnBattleEnd(ctx Ctx) bool //战斗结束
Prop_Befer(in *Input, prop, level int8, ptype info.EnumAbilityOpType) bool //锁定属性
@@ -41,8 +43,8 @@ type Effect interface {
SetArgs(input *Input, param ...int)
// 治疗相关触发
Heal_Pre(*action.BaseAction) bool // 治疗前触发 回复翻倍效果
Heal(*action.BaseAction) bool // 治疗生效时触发 药剂反噬
Heal_Pre(action.BattleActionI) bool // 治疗前触发 回复翻倍效果
Heal(action.BattleActionI) bool // 治疗生效时触发 药剂反噬
//回合数,然后次数另外维护
Duration(...int) int

View File

@@ -3,6 +3,7 @@ package input
import (
element "blazing/common/data/Element"
"blazing/common/utils"
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"fmt"
@@ -18,7 +19,7 @@ func (u *Input) UseSkill(opp *Input, skill *info.SkillEntity) {
CritRate := utils.Max(skill.CritRate, 1)
//CritAtkFirst: 先出手时必定致命一击; 默认: 0
if skill.CritAtkFirst != 0 && u.First {
if skill.CritAtkFirst != 0 && u.FightC {
CritRate = 16
}
//CritAtkSecond: 后出手时必定致命一击; 默认: 0
@@ -41,12 +42,20 @@ func (u *Input) UseSkill(opp *Input, skill *info.SkillEntity) {
}
// 恢复血量
func (u *Input) Heal(ac action.BattleActionI, value decimal.Decimal) {
u.CurrentPet.Info.Hp += uint32(value.IntPart())
}
// 伤害落实 // 血量扣减节点比如触发回神,反弹也在这里实现
func (u *Input) Damage(ctx Ctx) {
ctx.Input.DamageZone.BeforeADD = ctx.DamageZone.Damage
ok := ctx.Input.Exec(func(t Effect) bool {
t.Damage_ADD(ctx) //红伤落实前,我方增伤
tctx := ctx
tctx.Input = u
t.Damage_ADD(tctx) //红伤落实前,我方增伤
return true
})
@@ -54,14 +63,25 @@ func (u *Input) Damage(ctx Ctx) {
ctx.Input.DamageZone.BeforeMul = ctx.DamageZone.Damage
if ok {
ok = ctx.Input.Exec(func(t Effect) bool {
tctx := ctx
tctx.Input = u
t.Damage_Mul(tctx) //红伤落实前,我方增伤
t.Damage_Mul(ctx) //红伤落实前,我方增伤
return true
})
}
ctx.Input.DamageZone.BeforeFloor = ctx.DamageZone.Damage
if ok {
ok = ctx.Exec(func(t Effect) bool {
tctx := ctx
tctx.Input = u
t.Damage_Floor(tctx) //红伤落实,内部有befer
return true
})
}
ctx.Input.DamageZone.BeforeMul = ctx.DamageZone.Damage //反弹伤害记录
ctx.Input.DamageZone.BeforeMul = ctx.DamageZone.Damage
if ok {
ok = u.Exec(func(t Effect) bool {
@@ -82,16 +102,27 @@ func (u *Input) Damage(ctx Ctx) {
}
ctx.Input.DamageZone.BeforeLock = ctx.DamageZone.Damage
if ok {
ok = ctx.Input.Exec(func(t Effect) bool {
tctx := ctx
tctx.Input = u
t.Damage_Lock(tctx)
return true
})
}
ctx.Input.DamageZone.BeforeLocked = ctx.DamageZone.Damage
if ok {
ok = u.Exec(func(t Effect) bool {
t.Damage_Lock(ctx)
t.Damage_Locked(ctx)
return true
})
}
if ctx.DamageZone.Type == info.DamageType.Red {
if ctx.DamageZone.Type == info.DamageType.Red { //红才会产生造成伤害
ctx.Input.DamageZone.Damage = ctx.DamageZone.Damage
ctx.AttackValue.LostHp = uint32(ctx.DamageZone.Damage.IntPart()) //红伤落实
}
@@ -99,7 +130,7 @@ func (u *Input) Damage(ctx Ctx) {
u.CurrentPet.Info.Hp = 0
} else {
u.CurrentPet.Info.Hp = u.CurrentPet.Info.Hp - ctx.AttackValue.LostHp
u.CurrentPet.Info.Hp = u.CurrentPet.Info.Hp - uint32(ctx.DamageZone.Damage.IntPart())
}
//todo 待实现死亡effet

View File

@@ -1,8 +1,10 @@
package input
import (
"blazing/common/data/xmlres"
"blazing/common/utils"
"blazing/logic/service/common"
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"github.com/jinzhu/copier"
@@ -10,27 +12,30 @@ import (
)
type Input struct {
CanChange bool //是否可以死亡切换CanChange
CurrentPet *info.BattlePetEntity //当前精灵
AllPet []*info.BattlePetEntity
Player common.PlayerI
Finished bool //是否加载完成
CanChange bool //是否可以死亡切换CanChange
CurrentPet *info.BattlePetEntity //当前精灵
AllPet []*info.BattlePetEntity
Player common.PlayerI
EffectCache []Effect
Finished bool //是否加载完成
*info.AttackValue
FightC common.FightI
// info.BattleActionI
Effects *utils.OrderedMap[int, Effect] //effects 实际上全局就是effect无限回合 //effects容器 技能的
DamageZone struct {
Damage decimal.Decimal //伤害
BeforeADD decimal.Decimal //攻击伤害
BeforeMul decimal.Decimal
BeforeDiv decimal.Decimal
BeforeSUB decimal.Decimal
BeforeLock decimal.Decimal //锁伤 先锁受击方,再锁攻击方 受击方免疫也是这么锁 免疫等于锁0
Damage decimal.Decimal //伤害
BeforeADD decimal.Decimal //攻击伤害
BeforeMul decimal.Decimal
BeforeFloor decimal.Decimal
BeforeDiv decimal.Decimal
BeforeSUB decimal.Decimal
BeforeLock decimal.Decimal //锁伤 先锁受击方,再锁攻击方 受击方免疫也是这么锁 免疫等于锁0
BeforeLocked decimal.Decimal
//BeforePost decimal.Decimal
//OldAttack int //攻击伤害被挡前伤害记录
} //伤害容器
First bool //是否先手
//First bool //是否先手
}
func NewInput(c common.FightI, p common.PlayerI) *Input {
@@ -95,3 +100,33 @@ func (i *Input) GetStatusBonus() float64 {
return maxBonus
}
// 解析并 施加effect
func (i *Input) Parseskill(defender *Input, skill *action.SelectSkillAction) {
temparg := skill.Skill.SideEffectArgS
for _, v := range skill.Skill.SideEffectS {
t := Geteffect(EffectType.Skill, v)
args := xmlres.EffectArgs[v]
if t.ID != 0 {
t.Effect.SetArgs(i, temparg[:args]...) //设置入参,施加方永远是我方
// if t.Effect.GetOwner() { //如果取反,说明是给对方添加的回合效果
// //实际上,owner永远为反,说明是对方给我添加的
// t.Effect.SetArgs(attacker, temparg[:args]...) //设置入参,施加方永远是我方
// //给双方添加
// defender.AddEffect(t)
// } else {
// t.Effect.SetArgs(attacker, temparg[:args]...) //设置入参
// attacker.AddEffect(t)
// }
//ret = append(ret, t.Effect)
i.EffectCache = append(i.EffectCache, t.Effect)
}
temparg = temparg[args:]
}
}

View File

@@ -6,7 +6,7 @@ import (
"blazing/modules/blazing/model"
"reflect"
"github.com/barkimedes/go-deepcopy"
"github.com/brunoga/deep"
"github.com/tnnmigga/enum"
)
@@ -31,7 +31,9 @@ func Geteffect(etype EnumEffectType, id int) *EffectID {
ret, ok := NodeM[id+int(etype)]
if ok {
//todo 获取前GetEffect
eff, _ := deepcopy.Anything(ret)
eff := deep.MustCopy(ret)
return &EffectID{
ID: id + int(etype),
Effect: eff.(Effect),

View File

@@ -1,31 +0,0 @@
package node
// 返回false阻止继续运行
// 回合开始
func (this *EffectNode) PreBattleStart() bool {
return true
}
// 返回false阻止继续运行
// 回合开始
func (this *EffectNode) OnBattleStart() bool {
return true
}
//回合结束前
func (this *EffectNode) PreBattleEnd() bool {
return true
}
//回合结束
func (this *EffectNode) OnBattleEnd() bool {
return true
}

View File

@@ -1,10 +1,13 @@
package node
import "blazing/logic/service/fight/action"
// 治疗相关触发
func (this *EffectNode) OnBeforeHeal() bool {
// 治疗前触发 回复翻倍效果
func (e *EffectNode) Heal_Pre(action.BattleActionI) bool {
panic("not implemented") // TODO: Implement
}
func (this *EffectNode) OnHeal() bool {
func (e *EffectNode) Heal(_ action.BattleActionI) bool {
panic("not implemented") // TODO: Implement
}

View File

@@ -1,12 +1,15 @@
package node
import "blazing/logic/service/fight/input"
// 切精灵返回false重写change方法来实现切换效果
// 精灵切换相关触发
func (e *EffectNode) OnSwitchIn() bool {
return true
func (e *EffectNode) OnSwitchIn(ctx input.Ctx) bool {
panic("not implemented") // TODO: Implement
}
func (e *EffectNode) OnSwitchOut() bool {
func (e *EffectNode) OnSwitchOut(ctx input.Ctx) bool {
//下场默认清除effect
if e.Owner { //清除对方的我方施加uff
e.NotALive()
@@ -14,13 +17,13 @@ func (e *EffectNode) OnSwitchOut() bool {
return true
}
func (e *EffectNode) OnOwnerSwitchIn() bool {
func (e *EffectNode) OnOwnerSwitchIn(ctx input.Ctx) bool {
return true
}
func (e *EffectNode) OnOwnerSwitchOut(ctx input.Ctx) bool {
//自身下场清除掉自身的回合效果
//this.GetBattle().Effects[this.GetInput().UserID].RemoveEffect(this)
e.NotALive()
return true
}
func (e *EffectNode) OnOwnerSwitchOut() bool {
return true
}

View File

@@ -1,18 +0,0 @@
package node
// 堆叠Stack相关触发
func (this *EffectNode) OnStackBefore() bool {
panic("not implemented") // TODO: Implement
}
func (this *EffectNode) OnStack() bool {
panic("not implemented") // TODO: Implement
}
func (this *EffectNode) OnBeforeConsumeStack() bool {
panic("not implemented") // TODO: Implement
}
func (this *EffectNode) OnConsumeStack() bool {
panic("not implemented") // TODO: Implement
}

View File

@@ -1,41 +1,21 @@
package node
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
)
// 回合开始前
func (e *EffectNode) PreTurnStart() bool {
return true
func (e *EffectNode) Turn_Start(ctx input.Ctx) {
panic("not implemented") // TODO: Implement
}
// 回合开始
func (e *EffectNode) OnTurnStart(opp *input.Input) {
//处理异常状态
}
func (e *EffectNode) OnActionEnd() bool {
//处理异常状态
return true
}
func (e *EffectNode) PreActionStart() bool {
//处理异常状态
return true
}
// 回合结束一次性effect清楚掉
func (e *EffectNode) TurnEnd(opp *input.Input) {
func (e *EffectNode) Turn_End(ctx input.Ctx) {
if e.duration == 0 { // 保留 (负数表示永久)
e.NotALive()
}
e.duration--
}
func (e *EffectNode) OnDefeat(*input.Input, *info.SkillEntity) bool {
panic("not implemented") // TODO: Implement
}

View File

@@ -1,43 +0,0 @@
package node
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
)
func (this *EffectNode) BeforeMultiHit() bool {
panic("not implemented") // TODO: Implement
}
// 回合结束前
func (this *EffectNode) BeforeCalculateDamage(opp *input.Input, skill *info.SkillEntity) {
panic("not implemented") // TODO: Implement
}
func (this *EffectNode) PreDamage() bool {
panic("not implemented") // TODO: Implement
}
func (this *EffectNode) CalculateDamage(opp *input.Input, skill *info.SkillEntity) {
panic("not implemented") // TODO: Implement
}
func (this *EffectNode) OnDamage() bool {
panic("not implemented") // TODO: Implement
}
func (this *EffectNode) Shield() bool {
panic("not implemented") // TODO: Implement
}
func (this *EffectNode) PostDamage() bool {
panic("not implemented") // TODO: Implement
}
func (this *EffectNode) OnDefeat() bool {
panic("not implemented") // TODO: Implement
}
func (this *EffectNode) BeferProp(in *input.Input, prop, level int8, ptype info.EnumAbilityOpType) bool {
return true
}

View File

@@ -1,48 +1,38 @@
package node
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
)
func (e *EffectNode) OnSkillPP() bool {
func (e *EffectNode) Damage_ADD(ctx input.Ctx) bool {
return true
}
func (e *EffectNode) Damage_Mul(ctx input.Ctx) bool {
return true
}
// 使用技能前
func (e *EffectNode) CanSkill(opp *input.Input) bool {
return e.Input.CurrentPet.HP != 0
func (e *EffectNode) Damage_Floor(ctx input.Ctx) bool {
return true
}
// 命中前 攻击伤害结算
func (e *EffectNode) PreSkill(opp *input.Input, skill *info.SkillEntity) {
}
func (e *EffectNode) PreAttacked(*input.Input, *info.SkillEntity) {
}
func (e *EffectNode) BeforeSkill(opp *input.Input, skill *info.SkillEntity) {
func (e *EffectNode) Damage_DIV(ctx input.Ctx) bool {
return true
}
// 使用技能时不可被继承继承Miss和Hit就行
func (e *EffectNode) OnSkill(opp *input.Input, skill *info.SkillEntity) {
if e.Hit() { //没命中
e.OnHit(opp, skill)
} else {
e.OnMiss(opp, skill)
}
func (e *EffectNode) Damage_SUB(ctx input.Ctx) bool {
return true
}
// miss
func (e *EffectNode) OnMiss(opp *input.Input, skill *info.SkillEntity) {
func (e *EffectNode) Damage_Lock(ctx input.Ctx) bool {
return true
}
type Effect interface {
OnMiss(opp *input.Input, skill *info.SkillEntity)
OnHit(opp *input.Input, skill *info.SkillEntity)
func (e *EffectNode) Damage_Locked(ctx input.Ctx) bool {
return true
}
func (e *EffectNode) Damage_Shield(ctx input.Ctx) bool {
return true
}

View File

@@ -0,0 +1,16 @@
package node
import "blazing/logic/service/fight/input"
// 回合结束一次性effect清楚掉
func (e *EffectNode) Fight_Start(ctx input.Ctx) bool {
panic("not implemented") // TODO: Implement
}
func (e *EffectNode) PreBattleEnd(ctx input.Ctx) bool {
panic("not implemented") // TODO: Implement
}
func (e *EffectNode) OnBattleEnd(ctx input.Ctx) bool {
panic("not implemented") // TODO: Implement
}

View File

@@ -1,30 +0,0 @@
package node
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
)
// 受击触发
func (this *EffectNode) Attack(*input.Input, *info.DamageZone) {
}
// 受击触发
func (this *EffectNode) BeforeAttack(*input.Input, *info.DamageZone) {
}
// 受击触发
func (this *EffectNode) Attacked(*input.Input, *info.DamageZone) {
}
// 受击触发
func (this *EffectNode) BeforeAttacked(*input.Input, *info.DamageZone) {
}
// 受击触发
func (this *EffectNode) FloorDamage(*input.Input, *info.DamageZone) {
}
// 受击触发
func (this *EffectNode) LockDamage(*input.Input, *info.DamageZone) {
}

View File

@@ -1,6 +1,7 @@
package node
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
)
@@ -29,20 +30,24 @@ func (this *EffectNode) Alive() bool {
return !this.notAlive
}
func (e *EffectNode) GetInput() *input.Input {
func (this *EffectNode) NotALive() {
this.notAlive = true
return e.Input
}
func (this *EffectNode) GetOwner() bool {
func (e *EffectNode) NotALive() {
return this.Owner
e.notAlive = true
}
func (this *EffectNode) SetOwner(b bool) {
func (e *EffectNode) GetOwner() bool {
this.Owner = b
return e.Owner
}
func (e *EffectNode) SetOwner(b bool) {
e.Owner = b
}
func (this *EffectNode) Stack(t ...int) int {
@@ -89,3 +94,9 @@ func (this *EffectNode) AttackTime(*input.Input, *input.Input) bool {
return true
}
func (e *EffectNode) EFFect_Befer() {
}
func (e *EffectNode) Prop_Befer(in *input.Input, prop int8, level int8, ptype info.EnumAbilityOpType) bool {
return true
}

View File

@@ -0,0 +1,53 @@
package node
import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
)
func (e *EffectNode) Skill_Pre(ctx input.Ctx) bool {
return true
}
func (e *EffectNode) Skill_PreUse(ctx input.Ctx) bool {
return true
}
func (e *EffectNode) OnSkill(ctx input.Ctx) bool {
if e.Effect != nil {
if e.Hit() { //没命中
e.OnHit(ctx.Input, ctx.SkillEntity)
} else {
e.OnMiss(ctx.Input, ctx.SkillEntity)
}
}
return true
}
func (e *EffectNode) Skill_Can(ctx input.Ctx) bool {
return e.Input.CurrentPet.HP != 0
}
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) //死亡
} else {
e.OnAlive(ctx.Input, ctx.SkillEntity) //存活
}
}
return true
}
type Effect interface {
OnMiss(opp *input.Input, skill *info.SkillEntity)
OnHit(opp *input.Input, skill *info.SkillEntity)
OnDefeat(opp *input.Input, skill *info.SkillEntity) bool //如果需要死亡
OnAlive(opp *input.Input, skill *info.SkillEntity) bool //如果需要存活
}

View File

@@ -23,32 +23,6 @@ func (f *FightC) Compare(a, b action.BattleActionI) (action.BattleActionI, actio
} else if p1 < 0 {
return a, b
}
_, ok := b.(*action.SystemGiveUpAction)
if ok {
if _, ok := a.(*action.SystemGiveUpAction); ok {
return b, a
}
return a, b
}
bskill := b.(*action.SelectSkillAction)
askill := a.(*action.SelectSkillAction)
// 如果是选择技能操作,进一步比较技能优先级和宠物属性
p2 := bskill.Skill.Priority - askill.Skill.Priority
if p2 > 0 {
return b, a
} else if p2 < 0 {
return a, b
}
p2 = int(f.Opp.GetProp(4, false)) - int(f.Our.GetProp(4, false))
if p2 > 0 {
return b, a
} else if p2 < 0 {
return a, b
}
return a, b // 速度相同时,发起方优先
}
@@ -108,16 +82,12 @@ func (f *FightC) ChangePet(c common.PlayerI, id uint32) {
// 玩家使用技能
func (f *FightC) UseSkill(c common.PlayerI, id int32) {
if id == 0 {
f.actionChan <- &action.SystemGiveUpAction{BaseAction: action.NewBaseAction(c.GetInfo().UserID)}
return
}
ret := &action.SelectSkillAction{
PlayerID: c.GetInfo().UserID,
}
ret.PetInfo = f.GetInputByPlayer(c, false).CurrentPet
//ret.PetInfo = f.GetInputByPlayer(c, false).CurrentPet
for _, v := range ret.PetInfo.Skills {
for _, v := range f.GetInputByPlayer(c, false).CurrentPet.Skills {
if v != nil && v.ID == int(id) {
ret.Skill = v

View File

@@ -0,0 +1,19 @@
package pet
import "blazing/logic/service/player"
// ChangeSkillInfo 技能变更信息
type ChangeSkillInfo struct {
Head player.TomeeHeader `cmd:"2312" struc:"[0]pad"`
CatchTime uint32 `json:"catchTime"` // 精灵生成时间
Reserved uint32 `json:"reserved"` // 填充字段默认为1
Reserved1 uint32 `json:"reserved1"` // 填充字段默认为1
HasSkill uint32 `json:"hasSkill"` // 拥有的技能id
ReplaceSkill uint32 `json:"replaceSkill"` // 替换技能的id
}
// ChangeSkillInfo 技能变更信息
type ChangeSkillOutInfo struct {
CatchTime uint32 `json:"catchTime"` // 精灵生成时间
}