fix(fight): 战斗修改

This commit is contained in:
1
2025-11-11 05:54:24 +00:00
parent c6e0d84c1d
commit 65758c799e
44 changed files with 656 additions and 731 deletions

View File

@@ -1,37 +0,0 @@
package main
import (
"fmt"
"github.com/xiaoqidun/qqwry"
"github.com/xiaoqidun/qqwry/assets"
"os"
)
func init() {
qqwry.LoadData(assets.QQWryIpdb)
}
func main() {
if len(os.Args) < 2 {
return
}
queryIp := os.Args[1]
location, err := qqwry.QueryIP(queryIp)
if err != nil {
fmt.Printf("错误:%v\n", err)
return
}
emptyVal := func(val string) string {
if val != "" {
return val
}
return "未知"
}
fmt.Printf("国家:%s省份%s城市%s区县%s运营商%s\n",
emptyVal(location.Country),
emptyVal(location.Province),
emptyVal(location.City),
emptyVal(location.District),
emptyVal(location.ISP),
)
}

View File

@@ -1,46 +0,0 @@
package main
import (
"encoding/json"
"flag"
"github.com/xiaoqidun/qqwry"
"github.com/xiaoqidun/qqwry/assets"
"net"
"net/http"
)
type resp struct {
Data *qqwry.Location `json:"data"`
Success bool `json:"success"`
Message string `json:"message"`
}
func init() {
qqwry.LoadData(assets.QQWryIpdb)
}
func main() {
listen := flag.String("listen", "127.0.0.1:80", "http server listen addr")
flag.Parse()
http.HandleFunc("/ip/", IpAPI)
if err := http.ListenAndServe(*listen, nil); err != nil {
panic(err)
}
}
func IpAPI(writer http.ResponseWriter, request *http.Request) {
ip := request.URL.Path[4:]
if ip == "" {
ip, _, _ = net.SplitHostPort(request.RemoteAddr)
}
response := &resp{}
location, err := qqwry.QueryIP(ip)
if err != nil {
response.Message = err.Error()
} else {
response.Data = location
response.Success = true
}
b, _ := json.MarshalIndent(response, "", " ")
_, _ = writer.Write(b)
}

View File

@@ -9,6 +9,7 @@ type FightI interface {
Over(c PlayerI, id info.EnumBattleOverReason) //逃跑
UseSkill(c PlayerI, id int32) //使用技能
GetCurrPET(c PlayerI) *info.BattlePetEntity //当前精灵
Ownerid() uint32
ReadyFight(c PlayerI) //是否准备战斗
ChangePet(c PlayerI, id uint32)

View File

@@ -56,7 +56,7 @@ func (f *FightC) ChangePet(c common.PlayerI, id uint32) {
f.GetInputByPlayer(c, true).Exec(func(t input.Effect) bool {
t.OnSwitchOut(input.Ctx{})
t.OnSwitchOut()
return true
})
@@ -72,7 +72,7 @@ func (f *FightC) ChangePet(c common.PlayerI, id uint32) {
f.GetInputByPlayer(c, true).Exec(func(t input.Effect) bool {
t.OnSwitchIn(input.Ctx{})
t.OnSwitchIn()
return true
})

View File

@@ -25,7 +25,7 @@ type NewSel1 struct {
NewSel0
}
func (e *NewSel0) BeferProp(in *input.Input, prop, level int8, ptype info.EnumAbilityOpType) bool {
func (e *NewSel0) BeferProp(in *input.Ctx, prop, level int8, ptype info.EnumAbilityOpType) bool {
//能力下降类
if level > 0 && ptype == info.AbilityOpType.SUB {

View File

@@ -23,7 +23,7 @@ func init() {
}
// 命中之后
func (e *Effect1) OnSkill(ctx input.Ctx) bool {
func (e *Effect1) OnSkill( ) bool {
if !e.Hit() {
return true
}

View File

@@ -51,7 +51,7 @@ func registerStatusEffects() {
// -----------------------------------------------------------
// 技能触发时调用
// -----------------------------------------------------------
func (e *Effect10) OnSkill(ctx input.Ctx) bool {
func (e *Effect10) OnSkill() bool {
if !e.Hit() {
return true
}
@@ -81,7 +81,7 @@ func (e *Effect10) OnSkill(ctx input.Ctx) bool {
}
eff.Duration(duration)
eff.SetArgs(ctx.Input) //输入参数是对方
ctx.AddEffect(eff)
eff.SetArgs(e.Ctx().Our) //输入参数是对方
e.Ctx().Opp.AddEffect(eff)
return true
}

View File

@@ -30,7 +30,7 @@ func (e *Effect117) SetArgs(t *input.Input, a ...int) {
e.EffectNode.Duration(e.EffectNode.SideEffectArgs[0])
}
func (e *Effect117) OnSkill(ctx input.Ctx) bool {
func (e *Effect117) OnSkill() bool {
if !e.Hit() {
return true
}
@@ -49,7 +49,7 @@ func (e *Effect117) OnSkill(ctx input.Ctx) bool {
duration := int(e.Input.FightC.GetRand().Int31n(3)) // 默认随机 1~3 回合
eff.Duration(duration)
ctx.AddEffect(eff)
e.Ctx().Opp.AddEffect(eff)
}
return true

View File

@@ -22,7 +22,7 @@ func init() {
// -----------------------------------------------------------
// 技能触发时调用
// -----------------------------------------------------------
func (e *Effect13) OnSkill(ctx input.Ctx) bool {
func (e *Effect13) OnSkill() bool {
if !e.Hit() {
return true
}
@@ -36,7 +36,7 @@ func (e *Effect13) OnSkill(ctx input.Ctx) bool {
}
eff.Duration(duration)
eff.SetArgs(ctx.Input)
ctx.AddEffect(eff)
eff.SetArgs(e.Ctx().Our)
e.Ctx().Opp.AddEffect(eff)
return true
}

View File

@@ -20,7 +20,7 @@ type Effect20 struct {
}
// 使用技能时不可被继承继承Miss和Hit就行
func (e *Effect20) OnSkill(input.Ctx) bool {
func (e *Effect20) OnSkill() bool {
ok, _, _ := e.Input.Player.Roll(e.SideEffectArgs[0], 100)
if !ok {
return true

View File

@@ -25,7 +25,7 @@ type Effect21 struct {
}
// 使用技能时不可被继承继承Miss和Hit就行
func (e *Effect21) OnSkill(input.Ctx) bool {
func (e *Effect21) OnSkill() bool {
if !e.Hit() {
return true
}
@@ -43,14 +43,14 @@ func (e *Effect21) OnSkill(input.Ctx) bool {
}
// 被攻击时候反弹
func (e *Effect21) Skill_Use(ctx input.Ctx) bool {
func (e *Effect21) Skill_Use_ex() bool {
//未命中
if !e.Hit() {
return true
}
//不是技能
if ctx.SkillEntity == nil {
if e.Ctx().SkillEntity == nil {
return true
}
//0血不触发
@@ -58,8 +58,10 @@ func (e *Effect21) Skill_Use(ctx input.Ctx) bool {
return true
}
ctx.DamageZone.Type = info.DamageType.Fixed
ctx.DamageZone.Damage = decimal.NewFromInt(int64(ctx.DamageZone.Damage.IntPart())).Div(decimal.NewFromInt(int64(e.SideEffectArgs[0])))
ctx.Input.Damage(ctx)
e.Ctx().Opp.Damage(&info.DamageZone{
Type: info.DamageType.Fixed,
Damage: decimal.NewFromInt(int64(e.Ctx().Opp.DamageZone.Damage.IntPart())).Div(decimal.NewFromInt(int64(e.SideEffectArgs[0]))),
})
return true
}

View File

@@ -23,13 +23,14 @@ type Effect28 struct {
node.EffectNode
}
func (e *Effect28) OnSkill(ctx input.Ctx) bool {
func (e *Effect28) OnSkill() bool {
if !e.Hit() {
return true
}
ctx.DamageZone.Type = info.DamageType.Fixed
ctx.DamageZone.Damage = decimal.NewFromInt(int64(ctx.CurrentPet.Info.Hp)).Div(decimal.NewFromInt(int64(e.SideEffectArgs[0])))
ctx.Input.Damage(ctx)
e.Ctx().Opp.Damage(&info.DamageZone{
Type: info.DamageType.Fixed,
Damage: decimal.NewFromInt(int64(e.Ctx().Opp.CurrentPet.Info.Hp)).Div(decimal.NewFromInt(int64(e.SideEffectArgs[0]))),
})
return true
}

View File

@@ -23,13 +23,15 @@ type Effect29 struct {
node.EffectNode
}
func (e *Effect29) OnSkill(ctx input.Ctx) bool {
func (e *Effect29) OnSkill() bool {
if !e.Hit() {
return true
}
ctx.DamageZone.Type = info.DamageType.Fixed
ctx.DamageZone.Damage = decimal.NewFromInt(int64(e.SideEffectArgs[0]))
ctx.Input.Damage(ctx)
e.Ctx().Opp.Damage(&info.DamageZone{
Type: info.DamageType.Fixed,
Damage: decimal.NewFromInt(int64(e.SideEffectArgs[0])),
})
return true
}

View File

@@ -23,14 +23,14 @@ type Effect31 struct {
node.EffectNode
}
func (e *Effect31) Damage_Mul(ctx input.Ctx) bool {
func (e *Effect31) Damage_Mul() bool {
if !e.Hit() {
return true
}
if ctx.DamageZone.Type == info.DamageType.Red {
if e.Ctx().DamageZone.Type == info.DamageType.Red {
n := int(e.Input.FightC.GetRand().Int31n(int32(e.SideEffectArgs[1]-e.SideEffectArgs[0]+1))) + e.SideEffectArgs[0]
ctx.DamageZone.Damage = ctx.DamageZone.Damage.Mul(decimal.NewFromInt(int64(n)))
e.Ctx().Our.DamageZone.Damage = e.Ctx().Our.DamageZone.Damage.Mul(decimal.NewFromInt(int64(n)))
}

View File

@@ -20,7 +20,7 @@ type Effect39 struct {
node.EffectNode
}
func (e *Effect39) OnSkill(ctx input.Ctx) bool {
func (e *Effect39) OnSkill() bool {
if !e.Hit() {
return true
}
@@ -30,6 +30,6 @@ func (e *Effect39) OnSkill(ctx input.Ctx) bool {
return true
}
ctx.DelPP(e.SideEffectArgs[1])
e.Ctx().Opp.DelPP(e.SideEffectArgs[1])
return true
}

View File

@@ -23,7 +23,7 @@ type Effect43 struct {
node.EffectNode
}
func (e *Effect43) OnSkill(ctx input.Ctx) bool {
func (e *Effect43) OnSkill() bool {
if !e.Hit() {
return true
}

View File

@@ -38,7 +38,7 @@ type EffectStat struct {
// -----------------------------------------------------------
// 技能触发时调用
// -----------------------------------------------------------
func (e *EffectStat) OnSkill(ctx input.Ctx) bool {
func (e *EffectStat) OnSkill() bool {
if !e.Hit() {
return true
}
@@ -74,10 +74,10 @@ func (e *EffectStat) OnSkill(ctx input.Ctx) bool {
// 执行属性变化
if e.Etype {
// 对方属性变化
ctx.SetProp(e.Input, int8(statIndex), int8(level), opType)
e.Ctx().Opp.SetProp(e.Ctx().Our, int8(statIndex), int8(level), opType)
} else {
// 自身属性变化
e.Input.SetProp(e.Input, int8(statIndex), int8(level), opType)
e.Ctx().Our.SetProp(e.Ctx().Our, int8(statIndex), int8(level), opType)
}
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,10 +23,13 @@ type Effect6 struct {
node.EffectNode
}
func (e *Effect6) Skill_Useed(ctx input.Ctx) bool {
// 我方使用效果
func (e *Effect6) Skill_Useed() bool {
ctx.DamageZone.Damage = ctx.DamageZone.Damage.Div(decimal.NewFromInt(int64(e.SideEffectArgs[0])))
e.Input.Damage(ctx)
e.Input.Damage(&info.DamageZone{
//这个对面计算前是在他的回合,所以后手也能拿到伤害
Damage: e.Ctx().Opp.DamageZone.Damage.Div(decimal.NewFromInt(int64(e.SideEffectArgs[0]))),
})
return true
}

View File

@@ -38,9 +38,9 @@ func registerRandomPower(effectID, min, max int) {
// -----------------------------------------------------------
// 命中时触发
// -----------------------------------------------------------
func (e *EffectRandomPower) Skill_Hit(ctx input.Ctx) bool {
func (e *EffectRandomPower) Skill_Hit() bool {
if e.Max <= e.Min {
ctx.SkillEntity.Power = e.Min
e.Ctx().SkillEntity.Power = e.Min
return true
}
@@ -52,6 +52,6 @@ func (e *EffectRandomPower) Skill_Hit(ctx input.Ctx) bool {
n = rand.Intn(e.Max-e.Min+1) + e.Min
}
ctx.SkillEntity.Power = n
e.Ctx().SkillEntity.Power = n
return true
}

View File

@@ -4,8 +4,6 @@ import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"blazing/logic/service/fight/node"
"fmt"
"sync"
"github.com/shopspring/decimal"
)
@@ -15,29 +13,30 @@ import (
*/
type Effect62 struct {
node.EffectNode
Hide bool // 是否隐藏 正常是命中就可用,镇魂歌是回合数到才可用
opp *input.Input
e *Effect62_sub
l sync.Once
// Hide bool // 是否隐藏 正常是命中就可用,镇魂歌是回合数到才可用
// opp *input.Input
// e *Effect62_sub
//l sync.Once
}
type Effect62_sub struct {
node.EffectNode
bindpet *info.BattlePetEntity
bind *input.Input
//bindpet *info.BattlePetEntity
//bind *input.Input
// Hide bool // 是否隐藏 正常是命中就可用,镇魂歌是回合数到才可用
}
// 这个实际上在对方回合执行的
func (e *Effect62_sub) OnSkill(ctx input.Ctx) bool {
func (e *Effect62_sub) OnSkill() bool {
//defer e.Alive(false)
if e.bindpet == e.bind.CurrentPet { //说明对方没有切换精灵
if e.Duration() == 0 { //说明对方没有切换精灵
//直接扣除所有血量OnSkill
ctx.DamageZone.Type = info.DamageType.Fixed
ctx.DamageZone.Damage = decimal.NewFromInt(int64(e.bind.CurrentPet.Info.MaxHp))
e.bind.Damage(ctx)
e.Ctx().Our.Damage(&info.DamageZone{
Type: info.DamageType.Fixed,
Damage: decimal.NewFromInt(int64(e.Ctx().Our.CurrentPet.Info.MaxHp)),
})
}
return true
@@ -50,56 +49,53 @@ func init() {
input.InitEffect(input.EffectType.Skill, 62, t)
}
func (e *Effect62) Turn_Start(ctx input.Ctx) {
//如果对面还是我方放技能时候的玩家
// if ctx.Player != e.opp.Player {
// return
// }
fmt.Println(e.Duration(), "镇魂歌剩余回合")
if e.Duration() != 0 { //说明还没到生效节点
e.Hide = true //隐藏效果
} else {
e.opp.AddEffect(e.e)
}
// if !e.Hide { //说明是自身回合//如果还在隐藏,就直接返回
// //t.Duration(e.SideEffectArgs[0])
// e.opp.AddEffect(e.e)
// //defer e.EffectNode.NotALive() //失效
// //应该是对方固定伤害等于自身血量
// //e.Input.Death() //本只死亡
// func (e *Effect62) Turn_Start() {
// //如果对面还是我方放技能时候的玩家
// // if ctx.Player != e.opp.Player {
// // return
// // }
// fmt.Println(e.Duration(), "镇魂歌剩余回合")
// if e.Duration() != 0 { //说明还没到生效节点
// e.Hide = true //隐藏效果
// } else {
// e.opp.AddEffect(e.e)
// }
// // if !e.Hide { //说明是自身回合//如果还在隐藏,就直接返回
// //否则触发秒杀 在对面使用技能后
// //return true
// }
}
func (e *Effect62) OnSkill(ctx input.Ctx) bool {
// // //t.Duration(e.SideEffectArgs[0])
// // e.opp.AddEffect(e.e)
// // //defer e.EffectNode.NotALive() //失效
// // //应该是对方固定伤害等于自身血量
// // //e.Input.Death() //本只死亡
// // //否则触发秒杀 在对面使用技能后
// // //return true
// // }
// }
// 魂印开局添加,然后切精灵不消失
func (e *Effect62) OnSkill() bool {
if !e.Hit() {
//e.Alive(false)
return true
}
e.l.Do(func() {
//e.Duration(1) //必须保持到下一回合,这样才会被复制
e.opp = ctx.Input
e.e = &Effect62_sub{
EffectNode: node.EffectNode{},
bindpet: ctx.CurrentPet,
bind: ctx.Input,
}
e.e.ID(e.ID() + int(input.EffectType.Sub)) //子效果ID
//e.e.EffectNode.Duration(e.EffectNode.SideEffectArgs[0])
//给对方添加我方施加的buff
e.e.SetArgs(e.Input, e.SideEffectArgs...)
})
//e.Duration(1) //必须保持到下一回合,这样才会被复制
// e.opp = ctx.Input
ee := &Effect62_sub{
// bindpet: ctx.CurrentPet,
// bind: ctx.Input,
}
ee.EffectNode.Duration(e.EffectNode.SideEffectArgs[0]) //给对方挂3回合子buff
ee.ID(e.ID() + int(input.EffectType.Sub)) //子效果ID
//e.e.EffectNode.Duration(e.EffectNode.SideEffectArgs[0])
//给对方添加我方施加的buff
ee.SetArgs(e.Ctx().Our, e.SideEffectArgs...)
e.Ctx().Opp.AddEffect(ee)
return true
}
func (e *Effect62) SetArgs(t *input.Input, a ...int) {
e.EffectNode.SetArgs(t, a...)
e.EffectNode.Duration(e.EffectNode.SideEffectArgs[0])
}
// // 因为对方切精灵,这个效果也要无效掉
// func (this *Effect62) OnSwitchIn(input.Ctx) bool {

View File

@@ -29,13 +29,13 @@ func (this *Effect67) OnDefeat(*input.Input, *info.SkillEntity) bool {
}
// 登场是下一只 减少对方下次出战精灵的最大体力1/n
func (this *Effect67) OnSwitchIn(input.Ctx) bool {
func (this *Effect67) OnSwitchIn() bool {
return true
}
// 下场不消除buff
func (this *Effect67) OnSwitchOut(input.Ctx) bool {
func (this *Effect67) OnSwitchOut() bool {
//下场默认清除effect
panic("not implemented") // TODO: Implement
}

View File

@@ -26,7 +26,7 @@ func init() {
}
func (e *Effect69) OnSkill(ctx input.Ctx) bool {
func (e *Effect69) OnSkill() bool {
t := &Effect69_sub{
EffectNode: node.EffectNode{},
@@ -34,7 +34,7 @@ func (e *Effect69) OnSkill(ctx input.Ctx) bool {
t.ID(e.ID() + int(input.EffectType.Sub)) //子效果ID
t.SetArgs(e.Input, e.SideEffectArgs...)
t.Duration(e.SideEffectArgs[0])
ctx.AddEffect(t)
e.Ctx().Opp.AddEffect(t)
return true
}

View File

@@ -23,19 +23,19 @@ type Effect7 struct {
node.EffectNode
}
func (e *Effect7) Skill_Hit_Pre(ctx input.Ctx) bool {
if ctx.CurrentPet.Info.Hp <= e.Input.CurrentPet.Info.Hp {
ctx.SkillEntity.Accuracy = 0
func (e *Effect7) Skill_Hit_Pre() bool {
if e.Ctx().Our.CurrentPet.Info.Hp <= e.Input.CurrentPet.Info.Hp {
e.Ctx().SkillEntity.Accuracy = 0
}
return true
}
func (e *Effect7) Damage_Floor(ctx input.Ctx) bool {
func (e *Effect7) Damage_Floor() bool {
if !e.Hit() {
return true
}
if ctx.DamageZone.Type == info.DamageType.Red {
ctx.DamageZone.Damage = decimal.NewFromInt(int64(ctx.CurrentPet.Info.Hp - e.Input.CurrentPet.Info.Hp))
if e.Ctx().DamageZone.Type == info.DamageType.Red {
e.Ctx().DamageZone.Damage = decimal.NewFromInt(int64(e.Ctx().Our.CurrentPet.Info.Hp - e.Ctx().Opp.CurrentPet.Info.Hp))
}

View File

@@ -25,9 +25,10 @@ type Effect8 struct {
}
// 伤害落实前触发,限制最大伤害
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))
func (e *Effect8) Damage_Floor() bool {
if e.Ctx().DamageZone.Type == info.DamageType.Red {
e.Ctx().DamageZone.Damage = decimal.NewFromInt(utils.Min(e.Ctx().DamageZone.Damage.IntPart(),
int64(e.Ctx().Opp.CurrentPet.Info.Hp)-1))
}

View File

@@ -26,17 +26,17 @@ type Effect9 struct {
UseSkillCount int //技能使用了多少次切换后置0
}
func (e *Effect9) Skill_Hit(ctx input.Ctx) bool {
if e.Skillid != 0 && ctx.SkillEntity.ID != e.Skillid {
func (e *Effect9) Skill_Hit() bool {
if e.Skillid != 0 && e.Ctx().SkillEntity.ID != e.Skillid {
e.Alive(false)
e.UseSkillCount = 0
return true
}
e.Skillid = ctx.SkillEntity.ID
e.Skillid = e.Ctx().SkillEntity.ID
add := e.EffectNode.SideEffectArgs[0] * e.UseSkillCount
ctx.SkillEntity.Power += utils.Min(add, e.EffectNode.SideEffectArgs[1])
e.Ctx().SkillEntity.Power += utils.Min(add, e.EffectNode.SideEffectArgs[1])
e.UseSkillCount++
return true

View File

@@ -31,9 +31,9 @@ type Effect96 struct {
StatusID int
}
func (e *Effect96) Skill_Hit(opp input.Ctx) bool {
if f := statusFuncRegistry.Get(e.StatusID); f != nil && f(e.Input, opp.Input) {
opp.Power *= 2
func (e *Effect96) Skill_Hit() bool {
if f := statusFuncRegistry.Get(e.StatusID); f != nil && f(e.Ctx().Our, e.Ctx().Opp) {
e.Ctx().SkillEntity.Power *= 2
}
return true
}

View File

@@ -20,7 +20,7 @@ type StatusNotSkill struct {
}
// 不能出手
func (e *StatusNotSkill) Skill_Hit_Pre(ctx input.Ctx) bool {
func (e *StatusNotSkill) Skill_Hit_Pre() bool {
return false
@@ -31,20 +31,20 @@ type StatusSleep struct { //睡眠不能出手 ,这个挂载到对面来实现
can bool
}
func (e *StatusSleep) Skill_Hit_Pre(ctx input.Ctx) bool {
e.StatusNotSkill.Skill_Hit_Pre(ctx)
func (e *StatusSleep) Skill_Hit_Pre() bool {
e.StatusNotSkill.Skill_Hit_Pre()
e.can = true
return false
}
func (e *StatusSleep) Skill_Use(ctx input.Ctx) bool {
func (e *StatusSleep) Skill_Use_ex() bool {
if !e.can {
return true
}
if ctx.SkillEntity == nil {
if e.Ctx().SkillEntity == nil {
return true
}
if ctx.SkillEntity.Category() != info.Category.STATUS {
if e.Ctx().SkillEntity.Category() != info.Category.STATUS {
t := e.Input.GetEffect(input.EffectType.Status, int(info.PetStatus.Sleep))
if t != nil {
t.Alive(false)
@@ -60,13 +60,15 @@ type DrainHP struct {
damage decimal.Decimal
}
func (e *DrainHP) Skill_Hit_Pre(input input.Ctx) bool {
func (e *DrainHP) Skill_Hit_Pre() bool {
e.damage = decimal.NewFromUint64(uint64(e.Input.CurrentPet.Info.MaxHp)).
Div(decimal.NewFromInt(8))
input.DamageZone.Type = info.DamageType.True
input.DamageZone.Damage = e.damage
e.Input.Damage(input)
e.Input.Damage(&info.DamageZone{
Type: info.DamageType.True,
Damage: e.damage,
})
return true
}
@@ -76,16 +78,16 @@ type DrainedHP struct {
DrainHP
}
func (e *DrainedHP) Skill_Hit_Pre(input input.Ctx) bool {
func (e *DrainedHP) Skill_Hit_Pre() bool {
if gconv.Int(e.Input.CurrentPet.Type) == 1 {
return true
}
e.DrainHP.Skill_Hit_Pre(input) //先调用父类扣血
e.DrainHP.Skill_Hit_Pre() //先调用父类扣血
//TODO 寄生种子 给对面回血待实现回血buff
//这个回血不属于任何类型,所以不会被阻止回血
input.Heal(nil, e.damage)
e.Ctx().Opp.Heal(nil, e.damage)
// input.CurrentPet.Info.Hp = -e.Input.CurrentPet.Info.MaxHp / 8
return true

View File

@@ -17,7 +17,7 @@ type Effect3 struct {
// ----------------------
// 执行时逻辑
// ----------------------
func (e *Effect3) OnSkill(ctx input.Ctx) bool {
func (e *Effect3) OnSkill() bool {
if !e.Hit() {
return true
}
@@ -26,10 +26,10 @@ func (e *Effect3) OnSkill(ctx input.Ctx) bool {
for i := 0; i < 6; i++ {
if e.Reverse {
// 对对手生效
ctx.SetProp(e.Input, int8(i), e.Level, e.OpType)
e.Ctx().Opp.SetProp(e.Ctx().Our, int8(i), e.Level, e.OpType)
} else {
// 对自己生效
e.Input.SetProp(ctx.Input, int8(i), e.Level, e.OpType)
e.Ctx().Our.SetProp(e.Ctx().Our, int8(i), e.Level, e.OpType)
}
}

View File

@@ -2,277 +2,41 @@ package fight
import (
"blazing/common/utils"
"blazing/cool"
"blazing/logic/service/common"
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"blazing/modules/blazing/model"
"context"
"fmt"
"math/rand"
"reflect"
"sort"
"time"
"github.com/barkimedes/go-deepcopy"
"github.com/jinzhu/copier"
"github.com/shopspring/decimal"
)
type FightC struct {
Info info.NoteReadyToFightInfo
IsReady bool
ownerID uint32 // 战斗发起者ID
Our *input.Input //始终等于房主ID
Opp *input.Input //对手ID
Switch []*action.ActiveSwitchAction
rand *rand.Rand
StartTime time.Time
actionChan chan action.BattleActionI // 所有操作统一从这里进入
Round int //回合数
overchan chan struct{}
First *input.Input
Second *input.Input
closefight bool
info.FightOverInfo
}
func (f *FightC) CanEscape() bool {
return f.Info.Status != info.BattleStatus.FIGHT_WITH_PLAYER
}
func (f *FightC) Ownerid() uint32 {
return f.ownerID
}
func (f *FightC) GetInputByPlayer(c common.PlayerI, isOpposite bool) *input.Input {
// 判断当前玩家是否为我方玩家
isOurPlayer := c.GetInfo().UserID == f.ownerID
// 当isOurPlayer与isOpposite值不同时返回我方相同时返回对方
if isOurPlayer != isOpposite {
return f.Our
}
return f.Opp
}
func (f *FightC) GetInputByAction(c action.BattleActionI, isOpposite bool) *input.Input {
// 判断动作所属玩家是否为我方
isOurAction := c.GetPlayerID() == f.Our.Player.GetInfo().UserID
// 根据isOpposite决定是否返回相反方向的输入
if isOurAction == !isOpposite {
return f.Our
}
return f.Opp
}
// 玩家使用技能
func (f *FightC) GetCurrPET(c common.PlayerI) *info.BattlePetEntity {
if f.Our.Player.GetInfo().UserID == c.GetInfo().UserID {
return f.Our.CurrentPet
} else {
return f.Opp.CurrentPet
}
}
// 获取随机数
func (f *FightC) GetRand() *rand.Rand {
return f.rand
}
// 获取随机数
func (f *FightC) IsFirst(play common.PlayerI) bool {
return f.First.Player == play
}
// 加载进度
func (f *FightC) LoadPercent(c common.PlayerI, percent int32) {
f.GetInputByPlayer(c, true).Player.SendLoadPercent(info.LoadPercentOutboundInfo{
Id: c.GetInfo().UserID,
Percent: uint32(percent),
})
}
func (f *FightC) initplayer(c common.PlayerI, opp bool) bool {
if len(c.GetInfo().PetList) == 0 {
return false
}
temp := input.NewInput(f, c)
temp.AllPet = make([]*info.BattlePetEntity, 0)
temp.InitAttackValue()
for i := 0; i < len(c.GetInfo().PetList); i++ {
temp.AllPet = append(temp.AllPet, info.CreateBattlePetEntity(&c.GetInfo().PetList[i], f.rand))
}
sort.Slice(temp.AllPet, func(i, j int) bool {
x, y := temp.AllPet[i], temp.AllPet[j]
// 若x血量>0且y血量=0则x排在前
if x.Info.Hp > 0 && y.Info.Hp <= 0 {
return true
}
// 若x血量=0且y血量>0则x排在后
if x.Info.Hp <= 0 && y.Info.Hp > 0 {
return false
}
// 同类型(都>0或都=0保持原有顺序
return i < j
})
switch f.Info.Mode {
case info.BattleMode.SINGLE_MODE:
temp.AllPet = temp.AllPet[:1]
default:
}
if opp {
f.Opp = temp //这里是对方的
copier.Copy(&f.Info.OpponentInfo, f.Opp.Player.GetInfo())
f.Info.OpponentPetList = make([]info.ReadyFightPetInfo, len(temp.AllPet))
for i := 0; i < len(temp.AllPet); i++ {
err := copier.CopyWithOption(&f.Info.OpponentPetList[i], &temp.AllPet[i].Info, copier.Option{IgnoreEmpty: true, DeepCopy: true})
if err != nil {
panic(err)
}
}
} else {
f.Our = temp
copier.Copy(&f.Info.OurInfo, f.Our.Player.GetInfo())
f.Info.OurPetList = make([]info.ReadyFightPetInfo, len(temp.AllPet))
for i := 0; i < len(temp.AllPet); i++ {
err := copier.CopyWithOption(&f.Info.OurPetList[i], &temp.AllPet[i].Info, copier.Option{IgnoreEmpty: true, DeepCopy: true})
if err != nil {
panic(err)
}
}
}
for _, v := range temp.AllPet {
if v.Info.Hp == 0 {
v.NotAlive = true
}
}
temp.CurrentPet = temp.AllPet[0]
return true
}
// 创建新战斗,邀请方和被邀请方,或者玩家和野怪方
func NewFight(mode, status info.EnumBattleMode, p1 common.PlayerI, p2 common.PlayerI) *FightC {
f := &FightC{}
f.ownerID = p1.GetInfo().UserID
f.overchan = make(chan struct{})
f.StartTime = time.Now()
seed := f.StartTime.UnixNano() ^ int64(p1.GetInfo().UserID) ^ int64(p2.GetInfo().UserID) // ^ int64(f.Round) // 用异或运算混合多维度信息
f.rand = rand.New(rand.NewSource(seed))
f.Info = info.NoteReadyToFightInfo{
Status: status,
}
f.Info.Status = status //房主
f.Info.Mode = mode
ok := f.initplayer(p1, false)
if !ok {
return nil
}
ok = f.initplayer(p2, true)
if !ok {
return nil
}
i := Fightpool.Free()
if i <= 0 {
Fightpool.Tune(Fightpool.Cap() + 1)
cool.Loger.Error(context.Background(), "Fightpool is full")
}
rr := Fightpool.Submit(f.battleLoop)
if rr != nil {
panic(rr)
}
f.Broadcast(func(ff *input.Input) {
ff.Player.SendNoteReadyToFightInfo(f.Info)
})
return f
}
// 被击败的ID
func (b *FightC) IsWin(c *input.Input, cache uint32) bool {
var tt []*info.BattlePetEntity
bbb := b.Our.AllPet
if c.Player.GetInfo().UserID == b.ownerID { //如果是房主
bbb = b.Opp.AllPet
}
for _, v := range bbb {
if v.Info.CatchTime == cache {
v.NotAlive = true
}
tt = append(tt, v)
}
for _, v := range tt {
if !v.NotAlive { //如果存活
return false
}
}
return true
}
// 广播,并是否结束回合
func (f *FightC) Broadcast(t func(ff *input.Input)) {
t(f.Our)
t(f.Opp)
}
// 处理技能攻击逻辑
func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *info.SkillEntity) {
a.AttackTimeC(attacker.GetProp(5, true)) //计算命中
defender.ExecCace(func(t input.Effect) bool { //计算闪避 ,然后修改对方命中),同时相当于计算属性无效这种
t.Skill_Hit_to(input.Ctx{ //计算命中后,我方强制改命中效果
Input: attacker,
SkillEntity: a,
})
t.Ctx().SkillEntity = a
t.Skill_Hit_ex()
return true
})
attacker.AttackValue.AttackTime = a.AttackTime //是否命中赋值
attacker.ExecCace(func(t input.Effect) bool { //计算命中 miss改命中
t.Calculate_Pre(input.Ctx{ //计算视为效果
Input: defender,
SkillEntity: a,
}) //相当于先调整基础命中,不光调整命中,这里还能调整技能属性,暴击率
//计算视为效果
t.Ctx().SkillEntity = a
t.Calculate_Pre() //相当于先调整基础命中,不光调整命中,这里还能调整技能属性,暴击率
return true
})
attacker.ExecCace(func(t input.Effect) bool { //计算命中 miss改命中
t.Skill_Hit(input.Ctx{ //计算变威力
Input: defender,
SkillEntity: a,
}) //相当于先调整基础命中,不光调整命中,这里还能调整技能属性,暴击率
//计算变威力
t.Ctx().SkillEntity = a
t.Skill_Hit() //相当于先调整基础命中,不光调整命中,这里还能调整技能属性,暴击率
return true
})
@@ -317,26 +81,18 @@ func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *info.Ski
// 扣减防御方血量
attacker.Exec(func(t input.Effect) bool {
t.Ctx().SkillEntity = a
t.OnSkill(input.Ctx{
Input: defender,
SkillEntity: a,
DamageZone: &info.DamageZone{}, //给个空的,方便传递
}) //调用伤害计算
t.OnSkill() //调用伤害计算
return true
})
defender.Damage(input.Ctx{
defender.Damage(&info.DamageZone{
Input: attacker,
SkillEntity: a,
DamageZone: &info.DamageZone{
Type: info.DamageType.Red,
Damage: attacker.DamageZone.Damage,
},
})
Damage: attacker.DamageZone.Damage,
},
)
//这里其实是受到致死伤害
//然后先触发死亡效果消除所有buff
//然后触发回神效果
@@ -427,13 +183,13 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
f.First.ExecCace(func(t input.Effect) bool { //回合开始前
//结算状态
t.Turn_Start(input.Ctx{Input: f.Second})
t.Turn_Start()
return true
})
f.Second.ExecCace(func(t input.Effect) bool { //回合开始前
//结算状态
t.Turn_Start(input.Ctx{Input: f.First})
t.Turn_Start()
return true
})
//开始回合操作
@@ -465,11 +221,8 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
canuseskillok := attacker.ExecCace(func(t input.Effect) bool { //这个是能否使用技能
//结算状态
//然后这里还可以处理自爆类
return t.Skill_Hit_Pre(input.Ctx{
Input: defender,
SkillEntity: currentskill,
DamageZone: &info.DamageZone{},
}) //返回本身结算,如果false,说明不能使用技能了
t.Ctx().SkillEntity = currentskill
return t.Skill_Hit_Pre() //返回本身结算,如果false,说明不能使用技能了
})
// 结算状态
@@ -492,20 +245,22 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
//技能使用后
defender.Exec(func(t input.Effect) bool {
t.Skill_Use(input.Ctx{Input: attacker, SkillEntity: currentskill, DamageZone: &info.DamageZone{
Type: info.DamageType.Red,
t.Ctx().SkillEntity = currentskill
t.Ctx().DamageZone = &info.DamageZone{
Damage: attacker.DamageZone.Damage,
}})
}
t.Skill_Use_ex()
return true
})
//技能使用后
attacker.Exec(func(t input.Effect) bool { //技能使用后的我方效果
t.Skill_Useed(input.Ctx{Input: defender, SkillEntity: currentskill, DamageZone: &info.DamageZone{
Type: info.DamageType.Red,
t.Ctx().SkillEntity = currentskill
t.Ctx().DamageZone = &info.DamageZone{
Damage: attacker.DamageZone.Damage,
}})
}
t.Skill_Useed()
return true
})
@@ -553,27 +308,16 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
}
f.First.GenSataus()
f.Second.GenSataus()
f.First.Exec(func(t input.Effect) bool { //这个是能否使用技能
//结算状态
t.Turn_End(input.Ctx{
Input: f.Second,
}) //返回本身结算,如果false,说明不能使用技能了
return true
})
f.Second.Exec(func(t input.Effect) bool { //这个是能否使用技能
//结算状态
t.Turn_End(input.Ctx{
Input: f.First,
f.Broadcast(func(ff *input.Input) {
ff.GenSataus()
ff.Exec(func(t input.Effect) bool { //这个是能否使用技能
//结算状态
t.Turn_End() //返回本身结算,如果false,说明不能使用技能了
return true
})
return true
ff.GenInfo()
})
f.First.GenInfo()
f.Second.GenInfo()
ret := info.AttackValueS{
FAttack: *f.First.AttackValue,

View File

@@ -31,7 +31,7 @@ var Category = enum.New[struct {
type EnumDamageType int
var DamageType = enum.New[struct {
Red EnumDamageType
Red EnumDamageType `enum:"0"`
Fixed EnumDamageType // 固定伤害
Percent EnumDamageType // 百分比伤害
True EnumDamageType // 真伤

View File

@@ -0,0 +1,246 @@
package fight
import (
"blazing/cool"
"blazing/logic/service/common"
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"context"
"math/rand"
"sort"
"time"
"github.com/jinzhu/copier"
)
type FightC struct {
Info info.NoteReadyToFightInfo
IsReady bool
ownerID uint32 // 战斗发起者ID
Our *input.Input //始终等于房主ID
Opp *input.Input //对手ID
Switch []*action.ActiveSwitchAction
rand *rand.Rand
StartTime time.Time
actionChan chan action.BattleActionI // 所有操作统一从这里进入
Round int //回合数
overchan chan struct{}
First *input.Input
Second *input.Input
closefight bool
info.FightOverInfo
}
func (f *FightC) CanEscape() bool {
return f.Info.Status != info.BattleStatus.FIGHT_WITH_PLAYER
}
func (f *FightC) Ownerid() uint32 {
return f.ownerID
}
func (f *FightC) GetInputByPlayer(c common.PlayerI, isOpposite bool) *input.Input {
// 判断当前玩家是否为我方玩家
isOurPlayer := c.GetInfo().UserID == f.ownerID
// 当isOurPlayer与isOpposite值不同时返回我方相同时返回对方
if isOurPlayer != isOpposite {
return f.Our
}
return f.Opp
}
func (f *FightC) GetInputByAction(c action.BattleActionI, isOpposite bool) *input.Input {
// 判断动作所属玩家是否为我方
isOurAction := c.GetPlayerID() == f.Our.Player.GetInfo().UserID
// 根据isOpposite决定是否返回相反方向的输入
if isOurAction == !isOpposite {
return f.Our
}
return f.Opp
}
// 玩家使用技能
func (f *FightC) GetCurrPET(c common.PlayerI) *info.BattlePetEntity {
if f.Our.Player.GetInfo().UserID == c.GetInfo().UserID {
return f.Our.CurrentPet
} else {
return f.Opp.CurrentPet
}
}
func (f *FightC) GetOpp(c common.PlayerI) *input.Input {
return f.GetInputByPlayer(c, true)
}
// 获取随机数
func (f *FightC) GetRand() *rand.Rand {
return f.rand
}
// 获取随机数
func (f *FightC) IsFirst(play common.PlayerI) bool {
return f.First.Player == play
}
// 加载进度
func (f *FightC) LoadPercent(c common.PlayerI, percent int32) {
f.GetInputByPlayer(c, true).Player.SendLoadPercent(info.LoadPercentOutboundInfo{
Id: c.GetInfo().UserID,
Percent: uint32(percent),
})
}
func (f *FightC) initplayer(c common.PlayerI, opp bool) bool {
if len(c.GetInfo().PetList) == 0 {
return false
}
temp := input.NewInput(f, c)
temp.AllPet = make([]*info.BattlePetEntity, 0)
temp.InitAttackValue()
for i := 0; i < len(c.GetInfo().PetList); i++ {
temp.AllPet = append(temp.AllPet, info.CreateBattlePetEntity(&c.GetInfo().PetList[i], f.rand))
}
sort.Slice(temp.AllPet, func(i, j int) bool {
x, y := temp.AllPet[i], temp.AllPet[j]
// 若x血量>0且y血量=0则x排在前
if x.Info.Hp > 0 && y.Info.Hp <= 0 {
return true
}
// 若x血量=0且y血量>0则x排在后
if x.Info.Hp <= 0 && y.Info.Hp > 0 {
return false
}
// 同类型(都>0或都=0保持原有顺序
return i < j
})
switch f.Info.Mode {
case info.BattleMode.SINGLE_MODE:
temp.AllPet = temp.AllPet[:1]
default:
}
if opp {
f.Opp = temp //这里是对方的
copier.Copy(&f.Info.OpponentInfo, f.Opp.Player.GetInfo())
f.Info.OpponentPetList = make([]info.ReadyFightPetInfo, len(temp.AllPet))
for i := 0; i < len(temp.AllPet); i++ {
err := copier.CopyWithOption(&f.Info.OpponentPetList[i], &temp.AllPet[i].Info, copier.Option{IgnoreEmpty: true, DeepCopy: true})
if err != nil {
panic(err)
}
}
} else {
f.Our = temp
copier.Copy(&f.Info.OurInfo, f.Our.Player.GetInfo())
f.Info.OurPetList = make([]info.ReadyFightPetInfo, len(temp.AllPet))
for i := 0; i < len(temp.AllPet); i++ {
err := copier.CopyWithOption(&f.Info.OurPetList[i], &temp.AllPet[i].Info, copier.Option{IgnoreEmpty: true, DeepCopy: true})
if err != nil {
panic(err)
}
}
}
for _, v := range temp.AllPet {
if v.Info.Hp == 0 {
v.NotAlive = true
}
}
f.Opp.SetOPP(f.Our)
f.Our.SetOPP(f.Opp)
temp.CurrentPet = temp.AllPet[0]
return true
}
// 创建新战斗,邀请方和被邀请方,或者玩家和野怪方
func NewFight(mode, status info.EnumBattleMode, p1 common.PlayerI, p2 common.PlayerI) *FightC {
f := &FightC{}
f.ownerID = p1.GetInfo().UserID
f.overchan = make(chan struct{})
f.StartTime = time.Now()
seed := f.StartTime.UnixNano() ^ int64(p1.GetInfo().UserID) ^ int64(p2.GetInfo().UserID) // ^ int64(f.Round) // 用异或运算混合多维度信息
f.rand = rand.New(rand.NewSource(seed))
f.Info = info.NoteReadyToFightInfo{
Status: status,
}
f.Info.Status = status //房主
f.Info.Mode = mode
ok := f.initplayer(p1, false)
if !ok {
return nil
}
ok = f.initplayer(p2, true)
if !ok {
return nil
}
i := Fightpool.Free()
if i <= 0 {
Fightpool.Tune(Fightpool.Cap() + 1)
cool.Loger.Error(context.Background(), "Fightpool is full")
}
rr := Fightpool.Submit(f.battleLoop)
if rr != nil {
panic(rr)
}
f.Broadcast(func(ff *input.Input) {
ff.Player.SendNoteReadyToFightInfo(f.Info)
})
return f
}
// 被击败的ID
func (b *FightC) IsWin(c *input.Input, cache uint32) bool {
var tt []*info.BattlePetEntity
bbb := b.Our.AllPet
if c.Player.GetInfo().UserID == b.ownerID { //如果是房主
bbb = b.Opp.AllPet
}
for _, v := range bbb {
if v.Info.CatchTime == cache {
v.NotAlive = true
}
tt = append(tt, v)
}
for _, v := range tt {
if !v.NotAlive { //如果存活
return false
}
}
return true
}
// 广播,并是否结束回合
func (f *FightC) Broadcast(t func(ff *input.Input)) {
t(f.Our)
t(f.Opp)
}

View File

@@ -40,7 +40,7 @@ func getItemBonus(itemID uint32) float64 {
// -1是保底模式0是锁定模式》0是衰减模式
// Capture 执行捕捉 ,捕捉精灵,使用的道具,模式
func (c *Input) Capture(pet *info.BattlePetEntity, ItemID uint32, ownerpet int) (bool, CaptureDetails) {
func (our *Input) Capture(pet *info.BattlePetEntity, ItemID uint32, ownerpet int) (bool, CaptureDetails) {
if getItemBonus(ItemID) >= 255 {
return true, CaptureDetails{
@@ -49,7 +49,7 @@ func (c *Input) Capture(pet *info.BattlePetEntity, ItemID uint32, ownerpet int)
BaseRate: 100.0,
ModifiedRate: 100.0,
GuaranteeBonus: 0,
StatusBonus: c.GetStatusBonus(),
StatusBonus: our.GetStatusBonus(),
Details: fmt.Sprintf("道具ID=%d必定成功", ItemID),
}
}
@@ -62,19 +62,19 @@ func (c *Input) Capture(pet *info.BattlePetEntity, ItemID uint32, ownerpet int)
BaseRate: 0,
ModifiedRate: 0,
GuaranteeBonus: 0,
StatusBonus: c.GetStatusBonus(),
StatusBonus: our.GetStatusBonus(),
Details: "已拥有数量为0无法捕捉",
}
}
// 计算基础捕捉率
baseRate := c.calcBaseRate(pet, ItemID)
denominator := c.Player.GetPlayerCaptureContext().Denominator
baseRate := our.calcBaseRate(pet, ItemID)
denominator := our.Player.GetPlayerCaptureContext().Denominator
numerator := int(baseRate * float64(denominator))
// 衰减模式
if ownerpet > 0 {
decay := math.Pow(1-c.Player.GetPlayerCaptureContext().DecayFactor, float64(ownerpet))
decay := math.Pow(1-our.Player.GetPlayerCaptureContext().DecayFactor, float64(ownerpet))
baseRate *= decay
if baseRate < 0.01 {
baseRate = 0.01 // 最低1%成功率
@@ -83,7 +83,7 @@ func (c *Input) Capture(pet *info.BattlePetEntity, ItemID uint32, ownerpet int)
}
// 走统一保底判定
success, basePct, bonusPct := c.Player.Roll(numerator, denominator)
success, basePct, bonusPct := our.Player.Roll(numerator, denominator)
return success, CaptureDetails{
Success: success,
@@ -91,15 +91,15 @@ func (c *Input) Capture(pet *info.BattlePetEntity, ItemID uint32, ownerpet int)
BaseRate: basePct,
ModifiedRate: basePct + bonusPct,
GuaranteeBonus: bonusPct,
StatusBonus: c.GetStatusBonus(),
Details: fmt.Sprintf("a=%d, 分子=%d, 分母=%d", c.calcBaseA(pet, ItemID), numerator, denominator),
StatusBonus: our.GetStatusBonus(),
Details: fmt.Sprintf("a=%d, 分子=%d, 分母=%d", our.calcBaseA(pet, ItemID), numerator, denominator),
}
}
// calcBaseA 按公式计算a值
func (c *Input) calcBaseA(pet *info.BattlePetEntity, ItemID uint32) int {
func (our *Input) calcBaseA(pet *info.BattlePetEntity, ItemID uint32) int {
catchRate := gconv.Int(pet.CatchRate)
catchRate = (catchRate * c.Player.GetPlayerCaptureContext().Denominator) / 1000 // 归一化到1000分母
catchRate = (catchRate * our.Player.GetPlayerCaptureContext().Denominator) / 1000 // 归一化到1000分母
if catchRate < 3 {
catchRate = 3
}
@@ -115,18 +115,18 @@ func (c *Input) calcBaseA(pet *info.BattlePetEntity, ItemID uint32) int {
}
itemBonus := getItemBonus(ItemID)
statusBonus := c.GetStatusBonus()
statusBonus := our.GetStatusBonus()
return int(hpRatio * float64(catchRate) * itemBonus * statusBonus)
}
// calcBaseRate 按公式计算基础成功率
func (c *Input) calcBaseRate(pet *info.BattlePetEntity, ItemID uint32) float64 {
func (our *Input) calcBaseRate(pet *info.BattlePetEntity, ItemID uint32) float64 {
if getItemBonus(ItemID) >= 255 {
return 1.0
}
a := c.calcBaseA(pet, ItemID)
a := our.calcBaseA(pet, ItemID)
if a >= 255 {
return 1.0
}

View File

@@ -5,8 +5,10 @@ import (
)
type Ctx struct {
*Input //施加方
*info.SkillEntity //action本身
Our *Input //施加方
Opp *Input //被施加方
*info.SkillEntity //action本身
*info.DamageZone //伤害
}

View File

@@ -45,9 +45,9 @@ func Geteffect(etype EnumEffectType, id int) Effect {
// * battle_lv: atk(0), def(1), sp_atk(2), sp_def(3), spd(4), accuracy(5)
// 是否需要真实提升
func (c *Input) GetProp(id int, istue bool) int {
func (our *Input) GetProp(id int, istue bool) int {
// 获取基础属性值
baseValue := int(c.AttackValue.Prop[id])
baseValue := int(our.AttackValue.Prop[id])
// 命中情况直接返回基础值(优先判断)
if id >= 5 {
@@ -60,7 +60,7 @@ func (c *Input) GetProp(id int, istue bool) int {
}
// 计算实际值(这里可以插入后续优化的函数调用)
realValue := info.CalculateRealValue(int(c.CurrentPet.Info.Prop[id]), baseValue)
realValue := info.CalculateRealValue(int(our.CurrentPet.Info.Prop[id]), baseValue)
// todo: 插入获取后处理函数,例如:
// realValue = postProcessValue(realValue, id, c)
@@ -69,11 +69,11 @@ func (c *Input) GetProp(id int, istue bool) int {
}
func (c *Input) GetEffect(etype EnumEffectType, id int) Effect {
func (our *Input) GetEffect(etype EnumEffectType, id int) Effect {
var ret []Effect
eid := id + int(etype)
for _, v := range c.Effects {
for _, v := range our.Effects {
if v.ID() == eid && v.Alive() {
ret = append(ret, v)
}
@@ -84,16 +84,16 @@ func (c *Input) GetEffect(etype EnumEffectType, id int) Effect {
}
return nil
}
func (c *Input) StatEffect_Exist(id int) bool {
t := c.GetEffect(EffectType.Status, id)
func (our *Input) StatEffect_Exist(id int) bool {
t := our.GetEffect(EffectType.Status, id)
if t == nil {
return false
}
return t.Alive()
}
func (c *Input) StatEffect_Exist_all() bool {
for _, v := range c.Effects {
func (our *Input) StatEffect_Exist_all() bool {
for _, v := range our.Effects {
if v.ID() >= int(EffectType.Status) && v.ID() < int(EffectType.Sub) && v.Alive() {
return true
}
@@ -102,10 +102,10 @@ func (c *Input) StatEffect_Exist_all() bool {
return false
}
func (c *Input) GetCurrAttr(id int) *model.PetInfo {
func (our *Input) GetCurrAttr(id int) *model.PetInfo {
//todo 获取前GetEffect
return c.CurrentPet.Info
return our.CurrentPet.Info
//todo 获取后GetEffect
}
@@ -124,23 +124,23 @@ func equalInts(a, b []int) bool {
}
return true
}
func (c *Input) AddEffects(e ...Effect) {
func (our *Input) AddEffects(e ...Effect) {
for _, v := range e {
// v.Alive()
c.AddEffect(v)
our.AddEffect(v)
}
}
func (c *Input) AddEffect(e Effect) {
func (our *Input) AddEffect(e Effect) {
e.Alive(true) //添加后默认激活
//todo 免疫
//TODO 先激活
fmt.Println("产生回合数", e.ID(), e.Duration())
// 如果已有同 ID 的效果,尝试叠加
for _, v := range c.Effects {
for _, v := range our.Effects {
if v == e {
return //完全相同,跳过执行
}
@@ -173,18 +173,20 @@ func (c *Input) AddEffect(e Effect) {
}
//无限叠加比如能力提升类buff
// 如果没有同 ID 的效果,直接添加
c.Effects = append(c.Effects, e)
our.Effects = append(our.Effects, e)
}
// ForEachEffectBool 遍历所有 Effect执行“无参数、返回 bool”的方法
// 参数 fn接收单个 Effect返回 bool如 func(e Effect) bool { return e.OnBattleStart() }
// 返回值:所有 Effect 的方法返回值列表
func (c *Input) Exec(fn func(Effect) bool) bool {
func (our *Input) Exec(fn func(Effect) bool) bool {
result := true
for _, value := range c.Effects {
for _, value := range our.Effects {
if value.Alive() {
value.Ctx().Our = our
value.Ctx().Opp = our.Opp
value.Ctx().DamageZone = &info.DamageZone{}
if !fn(value) { //存在false,但是仍然要向下执行
result = false //如果是false,说明存在阻止向下执行的effect比如免疫能力提升效果
}
@@ -195,10 +197,13 @@ func (c *Input) Exec(fn func(Effect) bool) bool {
return result
}
func (c *Input) ExecCace(fn func(Effect) bool) bool {
func (our *Input) ExecCace(fn func(Effect) bool) bool {
result := true
for _, value := range c.EffectCache {
for _, value := range our.EffectCache {
value.Ctx().Our = our
value.Ctx().Opp = our.Opp
value.Ctx().DamageZone = &info.DamageZone{}
if !fn(value) { //存在false,但是仍然要向下执行
result = false //如果是false,说明存在阻止向下执行的effect比如免疫能力提升效果
}
@@ -209,8 +214,8 @@ func (c *Input) ExecCace(fn func(Effect) bool) bool {
}
// 消除回合类效果 efftype 输入是消对方的还是自己的,false是自己,true是对方
func (c *Input) CancelTurn() {
for _, value := range c.Effects {
func (our *Input) CancelTurn() {
for _, value := range our.Effects {
if value.Duration() > 0 { //false是自身,true是对方,反转后为真就是自己的
//slice = append(slice[:i], slice[i+1:]...)
value.Alive(false)
@@ -221,13 +226,13 @@ func (c *Input) CancelTurn() {
}
// 消除全部
func (c *Input) CancelAll(in *Input) {
if in == c { //消除自身
c.Effects = make([]Effect, 0)
func (our *Input) CancelAll(in *Input) {
if in == our { //消除自身
our.Effects = make([]Effect, 0)
return
}
for _, value := range c.Effects {
for _, value := range our.Effects {
if value.GetInput() == in { //false是自身,true是对方,反转后为真就是自己的
//slice = append(slice[:i], slice[i+1:]...)
value.Alive(false)

View File

@@ -9,12 +9,11 @@ import (
"fmt"
"math/rand"
"github.com/brunoga/deep"
"github.com/shopspring/decimal"
)
// 计算暴击
func (u *Input) CalculateCrit(opp *Input, skill *info.SkillEntity) {
func (our *Input) CalculateCrit(opp *Input, skill *info.SkillEntity) {
skill.Crit = 0
if skill.Category() == info.Category.STATUS { //属性技能不用算暴击
@@ -23,15 +22,15 @@ func (u *Input) CalculateCrit(opp *Input, skill *info.SkillEntity) {
CritRate := utils.Max(skill.CritRate, 1)
//CritAtkFirst: 先出手时必定致命一击; 默认: 0
if skill.CritAtkFirst != 0 && u.FightC.IsFirst(u.Player) {
if skill.CritAtkFirst != 0 && our.FightC.IsFirst(our.Player) {
CritRate = 16
}
//CritAtkSecond: 后出手时必定致命一击; 默认: 0
if skill.CritAtkSecond != 0 && !u.FightC.IsFirst(u.Player) {
if skill.CritAtkSecond != 0 && !our.FightC.IsFirst(our.Player) {
CritRate = 16
}
// CritSelfHalfHp: 自身体力低于一半时必定致命一击; 默认: 0
if skill.CritSelfHalfHp != 0 && (u.CurrentPet.HP < int(u.CurrentPet.Info.MaxHp)/2) {
if skill.CritSelfHalfHp != 0 && (our.CurrentPet.HP < int(our.CurrentPet.Info.MaxHp)/2) {
CritRate = 16
}
// CritFoeHalfHp: 对方体力低于一半时必定致命一击; 默认: 0
@@ -40,88 +39,87 @@ func (u *Input) CalculateCrit(opp *Input, skill *info.SkillEntity) {
}
//todo 暴击伤害
if t, _, _ := u.Player.Roll(625*CritRate, 10000); t {
if t, _, _ := our.Player.Roll(625*CritRate, 10000); t {
skill.Crit = 1
}
}
// 恢复血量
func (u *Input) Heal(ac action.BattleActionI, value decimal.Decimal) {
func (our *Input) Heal(ac action.BattleActionI, value decimal.Decimal) {
//使用道具回血
if _, ok := ac.(*action.UseItemAction); !ok && ac != nil {
u.AttackValue.GainHp = int32(value.IntPart()) //道具有专门的回血包
our.AttackValue.GainHp = int32(value.IntPart()) //道具有专门的回血包
}
if value.IsPositive() {
u.CurrentPet.Info.Hp += uint32(value.IntPart())
our.CurrentPet.Info.Hp += uint32(value.IntPart())
u.CurrentPet.Info.Hp = utils.Min(u.CurrentPet.Info.Hp, u.CurrentPet.Info.MaxHp)
our.CurrentPet.Info.Hp = utils.Min(our.CurrentPet.Info.Hp, our.CurrentPet.Info.MaxHp)
} else {
if uint32(value.Abs().IntPart()) > u.CurrentPet.Info.Hp {
u.CurrentPet.Info.Hp = 0
if uint32(value.Abs().IntPart()) > our.CurrentPet.Info.Hp {
our.CurrentPet.Info.Hp = 0
} else {
u.CurrentPet.Info.Hp += uint32(value.IntPart())
our.CurrentPet.Info.Hp += uint32(value.IntPart())
}
}
}
func (u *Input) HealPP(value int) {
func (our *Input) HealPP(value int) {
for i := 0; i < len(u.CurrentPet.Info.SkillList); i++ {
for i := 0; i < len(our.CurrentPet.Info.SkillList); i++ {
u.CurrentPet.Info.SkillList[i].PP += uint32(value)
u.CurrentPet.Info.SkillList[i].PP = utils.Min(u.CurrentPet.Info.SkillList[i].PP, uint32(xmlres.SkillMap[int(u.CurrentPet.Info.SkillList[i].ID)].MaxPP))
our.CurrentPet.Info.SkillList[i].PP += uint32(value)
our.CurrentPet.Info.SkillList[i].PP = utils.Min(our.CurrentPet.Info.SkillList[i].PP, uint32(xmlres.SkillMap[int(our.CurrentPet.Info.SkillList[i].ID)].MaxPP))
}
}
func (u *Input) DelPP(value int) {
func (our *Input) DelPP(value int) {
for i := 0; i < len(u.CurrentPet.Info.SkillList); i++ {
if uint32(value) > u.CurrentPet.Info.SkillList[i].PP {
u.CurrentPet.Info.SkillList[i].PP = 0
for i := 0; i < len(our.CurrentPet.Info.SkillList); i++ {
if uint32(value) > our.CurrentPet.Info.SkillList[i].PP {
our.CurrentPet.Info.SkillList[i].PP = 0
} else {
u.CurrentPet.Info.SkillList[i].PP -= uint32(value)
our.CurrentPet.Info.SkillList[i].PP -= uint32(value)
}
}
}
// /红伤只允许调用一次来保持锁伤
// 伤害落实 // 血量扣减节点比如触发回神,反弹也在这里实现
func (u *Input) Damage(ctx Ctx) {
sub := deep.MustCopy(ctx.DamageZone) //拷贝伤害,避免直接上下文传递,便于附加伤害
tctx := Ctx{
DamageZone: sub,
Input: u,
}
func (our *Input) Damage(sub *info.DamageZone) {
// sub := deep.MustCopy(ctx.DamageZone) //拷贝伤害,避免直接上下文传递,便于附加伤害
// sub := ctx.DamageZone
//sub.BeforeADD = sub.Damage
ok := ctx.Input.Exec(func(t Effect) bool {
ok := our.Exec(func(t Effect) bool {
t.Ctx().DamageZone = sub
t.Damage_ADD(tctx) //红伤落实前,我方增伤
t.Damage_ADD() //红伤落实前,我方增伤
return true
})
//sub.BeforeMul = sub.Damage
if ok {
ok = ctx.Input.Exec(func(t Effect) bool {
t.Damage_Mul(tctx) //红伤落实前,我方增伤
ok = our.Exec(func(t Effect) bool {
t.Ctx().DamageZone = sub
t.Damage_Mul() //红伤落实前,我方增伤
return true
})
}
//sub.BeforeFloor = sub.Damage
if ok {
ok = ctx.Exec(func(t Effect) bool {
t.Damage_Floor(tctx) //红伤落实,内部有befer
ok = our.Exec(func(t Effect) bool {
t.Ctx().DamageZone = sub
t.Damage_Floor() //红伤落实,内部有befer
return true
})
@@ -129,9 +127,9 @@ func (u *Input) Damage(ctx Ctx) {
// sub.BeforeMul = sub.Damage
if ok {
ok = u.Exec(func(t Effect) bool {
t.Damage_DIV(ctx) //红伤落实,内部有befer
ok = our.Opp.Exec(func(t Effect) bool {
t.Ctx().DamageZone = sub
t.Damage_DIV_ex() //红伤落实,内部有befer
return true
})
@@ -139,9 +137,10 @@ func (u *Input) Damage(ctx Ctx) {
//sub.BeforeSUB = sub.Damage
if ok {
ok = u.Exec(func(t Effect) bool {
ok = our.Opp.Exec(func(t Effect) bool {
t.Ctx().DamageZone = sub
t.Damage_SUB(ctx)
t.Damage_SUB_ex()
return true
})
@@ -149,33 +148,33 @@ func (u *Input) Damage(ctx Ctx) {
// sub.BeforeLock = sub.Damage
if ok {
ok = ctx.Input.Exec(func(t Effect) bool {
ok = our.Opp.Exec(func(t Effect) bool {
t.Damage_Lock(tctx)
t.Damage_Lock()
return true
})
}
//sub.BeforeLocked = sub.Damage
if ok {
u.Exec(func(t Effect) bool {
our.Opp.Exec(func(t Effect) bool {
t.Damage_Locked(ctx)
t.Damage_Lock_ex()
return true
})
}
if ctx.DamageZone.Type == info.DamageType.Red { //红才会产生造成伤害
ctx.Input.DamageZone.Damage.Add(sub.Damage) // 叠加总伤害
ctx.AttackValue.LostHp = uint32(ctx.DamageZone.Damage.IntPart()) //红伤落实
if sub.Type == info.DamageType.Red { //红才会产生造成伤害
our.DamageZone.Damage.Add(sub.Damage) // 叠加总伤害
our.AttackValue.LostHp = uint32(sub.Damage.IntPart()) //红伤落实
}
if uint32(ctx.DamageZone.Damage.IntPart()) > u.CurrentPet.Info.Hp {
if uint32(sub.Damage.IntPart()) > our.CurrentPet.Info.Hp {
u.CurrentPet.Info.Hp = 0
our.CurrentPet.Info.Hp = 0
} else {
u.CurrentPet.Info.Hp = u.CurrentPet.Info.Hp - uint32(ctx.DamageZone.Damage.IntPart())
our.CurrentPet.Info.Hp = our.CurrentPet.Info.Hp - uint32(sub.Damage.IntPart())
}
//todo 待实现死亡effet
@@ -183,8 +182,9 @@ func (u *Input) Damage(ctx Ctx) {
}
// 施加方,类型,等级,操作类别,是否成功
func (u *Input) SetProp(in *Input, prop, level int8, ptype info.EnumAbilityOpType) (ret bool) {
canuseskill := u.Exec(func(t Effect) bool { //这个是能否使用技能
func (our *Input) SetProp(in *Input, prop, level int8, ptype info.EnumAbilityOpType) (ret bool) {
//in.Our = our //设置属性的角色是我方
canuseskill := our.Exec(func(t Effect) bool { //这个是能否使用技能
//结算状态
return t.Prop_Befer(in, prop, level, ptype) //返回本身结算,如果false,说明不能使用技能了
@@ -198,9 +198,9 @@ func (u *Input) SetProp(in *Input, prop, level int8, ptype info.EnumAbilityOpTyp
switch ptype {
case info.AbilityOpType.ADD:
newValue = utils.Min(u.AttackValue.Prop[prop]+int8(level), 6)
newValue = utils.Min(our.AttackValue.Prop[prop]+int8(level), 6)
if newValue > u.AttackValue.Prop[prop] {
if newValue > our.AttackValue.Prop[prop] {
fmt.Println("属性值会增加")
return true
} else {
@@ -209,8 +209,8 @@ func (u *Input) SetProp(in *Input, prop, level int8, ptype info.EnumAbilityOpTyp
}
case info.AbilityOpType.SUB:
newValue = utils.Max(u.AttackValue.Prop[prop]+int8(level), -6)
if newValue < u.AttackValue.Prop[prop] {
newValue = utils.Max(our.AttackValue.Prop[prop]+int8(level), -6)
if newValue < our.AttackValue.Prop[prop] {
fmt.Println("属性值会减少")
return true
} else {
@@ -219,12 +219,12 @@ func (u *Input) SetProp(in *Input, prop, level int8, ptype info.EnumAbilityOpTyp
}
case info.AbilityOpType.RESET:
if level > 0 && u.AttackValue.Prop[prop] > 0 { //消强
if level > 0 && our.AttackValue.Prop[prop] > 0 { //消强
newValue = 0
return true
}
if level < 0 && u.AttackValue.Prop[prop] < 0 { //解弱
if level < 0 && our.AttackValue.Prop[prop] < 0 { //解弱
newValue = 0
return true
}
@@ -237,19 +237,19 @@ func (u *Input) SetProp(in *Input, prop, level int8, ptype info.EnumAbilityOpTyp
case info.AbilityOpType.AbilityOpStealStrengthen:
temp := in.AttackValue.Prop[prop]
temp := our.Opp.AttackValue.Prop[prop]
if temp <= 0 { //对方没有强化
return false
}
if abfunc(prop, temp, info.AbilityOpType.ADD) { //把对面的强化等级添加自身
u.AttackValue.Prop[prop] = newValue //成功把 强化更新
in.SetProp(u, prop, 1, info.AbilityOpType.RESET) //吸取后消除对面强化
our.AttackValue.Prop[prop] = newValue //成功把 强化更新
our.Opp.SetProp(our, prop, 1, info.AbilityOpType.RESET) //吸取后消除对面强化
}
case info.AbilityOpType.AbilityOpReverse:
temp := u.AttackValue.Prop[prop]
temp := our.AttackValue.Prop[prop]
switch {
@@ -258,8 +258,8 @@ func (u *Input) SetProp(in *Input, prop, level int8, ptype info.EnumAbilityOpTyp
return false
}
if abfunc(prop, temp*2, info.AbilityOpType.SUB) {
u.AttackValue.Prop[prop] = newValue
if temp == -u.AttackValue.Prop[prop] { //成功到对应弱化
our.AttackValue.Prop[prop] = newValue
if temp == -our.AttackValue.Prop[prop] { //成功到对应弱化
return true
} else {
@@ -276,8 +276,8 @@ func (u *Input) SetProp(in *Input, prop, level int8, ptype info.EnumAbilityOpTyp
return false
}
if abfunc(prop, -temp*2, info.AbilityOpType.ADD) {
u.AttackValue.Prop[prop] = newValue
if temp == -u.AttackValue.Prop[prop] { //成功到对应强化
our.AttackValue.Prop[prop] = newValue
if temp == -our.AttackValue.Prop[prop] { //成功到对应强化
return true
} else {
@@ -292,21 +292,21 @@ func (u *Input) SetProp(in *Input, prop, level int8, ptype info.EnumAbilityOpTyp
}
case info.AbilityOpType.AbilityOpBounceWeaken:
temp := u.AttackValue.Prop[prop]
temp := our.AttackValue.Prop[prop]
if temp >= 0 { //没有弱化
return false
}
if in.SetProp(u, prop, temp, info.AbilityOpType.SUB) {
if our.Opp.SetProp(our, prop, temp, info.AbilityOpType.SUB) {
u.SetProp(u, prop, -1, info.AbilityOpType.RESET) //消除自身弱化
our.SetProp(our, prop, -1, info.AbilityOpType.RESET) //消除自身弱化
return true
}
default: //增加减少重置
if abfunc(prop, level, ptype) {
// 执行赋值
u.AttackValue.Prop[prop] = newValue
our.AttackValue.Prop[prop] = newValue
return true
}
@@ -314,17 +314,17 @@ func (u *Input) SetProp(in *Input, prop, level int8, ptype info.EnumAbilityOpTyp
return false
}
func (i *Input) GetAction(opp *Input) {
func (our *Input) GetAction(opp *Input) {
// 获取己方当前宠物和对方当前宠物
selfPet := i.FightC.GetCurrPET(i.Player)
selfPet := our.FightC.GetCurrPET(our.Player)
//没血就切换精灵
if selfPet.Info.Hp <= 0 {
for _, v := range i.AllPet {
if v.Info.Hp>0 {
i.FightC.ChangePet(i.Player,v.Info.CatchTime)
for _, v := range our.AllPet {
if v.Info.Hp > 0 {
our.FightC.ChangePet(our.Player, v.Info.CatchTime)
return
}
}
}
@@ -353,7 +353,7 @@ func (i *Input) GetAction(opp *Input) {
continue
}
// 计算技能对对方的伤害假设CalculatePower返回伤害值或需从技能中获取
damage := i.CalculatePower(opp, s)
damage := our.CalculatePower(opp, s)
if !s.CanUse() {
continue
@@ -379,21 +379,21 @@ func (i *Input) GetAction(opp *Input) {
// bestKillSkill = ks.skill
// }
// }
i.FightC.UseSkill(i.Player, int32(bestKillSkill.ID))
our.FightC.UseSkill(our.Player, int32(bestKillSkill.ID))
return
}
randomIdx := rand.Intn(len(allSkills))
chosenSkill := skills[randomIdx]
i.FightC.UseSkill(i.Player, int32(chosenSkill.ID))
our.FightC.UseSkill(our.Player, int32(chosenSkill.ID))
// i.FightC.UseSkill(i.Player, int32(bestSkill.skill.ID))
}
// 计算技能威力
func (i *Input) CalculatePower(deftype *Input, skill *info.SkillEntity) decimal.Decimal {
func (our *Input) CalculatePower(deftype *Input, skill *info.SkillEntity) decimal.Decimal {
// 1. 计算等级因子 (level * 0.4 + 2)
levelFactor := decimal.NewFromInt(int64(i.CurrentPet.Info.Level)).
levelFactor := decimal.NewFromInt(int64(our.CurrentPet.Info.Level)).
Mul(decimal.NewFromFloat(0.4)).Add(decimal.NewFromInt(2))
var (
@@ -404,12 +404,12 @@ func (i *Input) CalculatePower(deftype *Input, skill *info.SkillEntity) decimal.
switch skill.Category() { //判断技能类型
case info.Category.PHYSICAL:
attackDec = decimal.NewFromInt(int64(i.GetProp(0, false)))
attackDec = decimal.NewFromInt(int64(our.GetProp(0, false)))
defenseDec = decimal.NewFromInt(int64(deftype.GetProp(1, false)))
case info.Category.SPECIAL:
attackDec = decimal.NewFromInt(int64(i.GetProp(2, false)))
attackDec = decimal.NewFromInt(int64(our.GetProp(2, false)))
defenseDec = decimal.NewFromInt(int64(deftype.GetProp(3, false)))
default:
@@ -439,10 +439,10 @@ func (i *Input) CalculatePower(deftype *Input, skill *info.SkillEntity) decimal.
}
if skill.PwrBindDv != 0 {
if skill.PwrBindDv == 1 {
baseDamage = decimal.NewFromInt(int64(i.CurrentPet.Info.Dv * 5))
baseDamage = decimal.NewFromInt(int64(our.CurrentPet.Info.Dv * 5))
}
if skill.PwrBindDv == 2 {
baseDamage = decimal.NewFromInt(int64(i.CurrentPet.Info.Hp/3 + i.CurrentPet.Info.Dv))
baseDamage = decimal.NewFromInt(int64(our.CurrentPet.Info.Hp/3 + our.CurrentPet.Info.Dv))
}
}
@@ -454,7 +454,7 @@ func (i *Input) CalculatePower(deftype *Input, skill *info.SkillEntity) decimal.
}
if skill.DmgBindHpDv != 0 {
baseDamage = decimal.NewFromInt(int64(i.CurrentPet.Info.Hp/2 + i.CurrentPet.Info.Dv))
baseDamage = decimal.NewFromInt(int64(our.CurrentPet.Info.Hp/2 + our.CurrentPet.Info.Dv))
}
damage := baseDamage.

View File

@@ -2,6 +2,7 @@ package input
import (
"blazing/common/data/xmlres"
"blazing/logic/service/common"
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
@@ -15,8 +16,8 @@ type Input struct {
CurrentPet *info.BattlePetEntity //当前精灵
AllPet []*info.BattlePetEntity
Player common.PlayerI
Finished bool //是否加载完成
Opp *Input
Finished bool //是否加载完成
*info.AttackValue
FightC common.FightI
// info.BattleActionI
@@ -52,30 +53,35 @@ func NewInput(c common.FightI, p common.PlayerI) *Input {
return ret
}
func (i *Input) GetPetInfo() *info.BattlePetEntity {
func (our *Input) GetPetInfo() *info.BattlePetEntity {
return i.CurrentPet
return our.CurrentPet
}
func (input *Input) GenSataus() {
func (our *Input) SetOPP(t *Input) {
our.Opp = t
}
func (our *Input) GenSataus() {
for i := 0; i < 20; i++ { //堆叠状态剩余回合
t := input.GetEffect(EffectType.Status, i)
t := our.GetEffect(EffectType.Status, i)
if t != nil && t.Alive() { //状态都是叠层类的
input.Status[i] = int8(t.Duration())
our.Status[i] = int8(t.Duration())
}
}
}
func (input *Input) GenInfo() {
func (our *Input) GenInfo() {
input.RemainHp = int32(input.CurrentPet.Info.Hp)
input.SkillList = input.CurrentPet.Info.SkillList
our.RemainHp = int32(our.CurrentPet.Info.Hp)
our.SkillList = our.CurrentPet.Info.SkillList
// f.Second.SkillList = f.Second.CurrentPet.Info.SkillList
// f.Second.RemainHp = int32(f.Second.CurrentPet.Info.Hp)
@@ -83,24 +89,24 @@ func (input *Input) GenInfo() {
// ret.SAttack = *f.Second.AttackValue
}
func (i *Input) ResetAttackValue() {
i.AttackValue.SkillID = 0
i.AttackValue.IsCritical = 0
i.AttackValue.GainHp = 0
i.AttackValue.LostHp = 0
func (our *Input) ResetAttackValue() {
our.AttackValue.SkillID = 0
our.AttackValue.IsCritical = 0
our.AttackValue.GainHp = 0
our.AttackValue.LostHp = 0
}
// 这个每回合都会调用
func (i *Input) InitAttackValue() {
i.AttackValue = info.NewAttackValue(i.Player.GetInfo().UserID)
func (our *Input) InitAttackValue() {
our.AttackValue = info.NewAttackValue(our.Player.GetInfo().UserID)
}
func (i *Input) GetPet(id uint32) (ii *info.BattlePetEntity, Reason info.ChangePetInfo) {
for _, v := range i.AllPet {
func (our *Input) GetPet(id uint32) (ii *info.BattlePetEntity, Reason info.ChangePetInfo) {
for _, v := range our.AllPet {
if v.Info.CatchTime == uint32(id) {
copier.Copy(&Reason, &v.Info)
Reason.UserId = i.Player.GetInfo().UserID
Reason.UserId = our.Player.GetInfo().UserID
ii = v
}
@@ -112,7 +118,7 @@ func (i *Input) GetPet(id uint32) (ii *info.BattlePetEntity, Reason info.ChangeP
// GetStatusBonus 获取最高的状态倍率
// 遍历状态数组返回存在的状态中最高的倍率无状态则返回1.0
func (i *Input) GetStatusBonus() float64 {
func (our *Input) GetStatusBonus() float64 {
// 异常状态倍率映射表(状态索引 -> 倍率)
var statusBonuses = map[info.EnumBattleStatus]float64{
info.PetStatus.Paralysis: 1.5,
@@ -136,15 +142,15 @@ func (i *Input) GetStatusBonus() float64 {
return maxBonus
}
func (i *Input) initeffectcache() {
i.EffectCache = make([]Effect, 0) //先把上一回合数据清空,但是应该把本身延续类效果集成过来
func (our *Input) initeffectcache() {
our.EffectCache = make([]Effect, 0) //先把上一回合数据清空,但是应该把本身延续类效果集成过来
for _, v := range i.Effects {
for _, v := range our.Effects {
if v.Alive() { //说明存活效果而且是延续类效果,将之添加到初始化列表中
//这里添加的效果是已经生效的效果对effect的复制,相当于技能施的效果的前置比如改命中的效果等
i.EffectCache = append(i.EffectCache, v)
our.EffectCache = append(our.EffectCache, v)
}
@@ -153,8 +159,8 @@ func (i *Input) initeffectcache() {
}
// 解析并 施加effect
func (i *Input) Parseskill(defender *Input, skill *action.SelectSkillAction) {
i.initeffectcache() //这里说明是延续的效果,每次复制出来一个新的就好了
func (our *Input) Parseskill(defender *Input, skill *action.SelectSkillAction) {
our.initeffectcache() //这里说明是延续的效果,每次复制出来一个新的就好了
//i.NewEffects = make([]Effect, 0) //这里说明是新增的效果
temparg := skill.SideEffectArgS
@@ -165,7 +171,7 @@ func (i *Input) Parseskill(defender *Input, skill *action.SelectSkillAction) {
args := xmlres.EffectArgs[v]
//这里是给双方添加buff
if t != nil {
t.SetArgs(i, temparg[:args]...) //设置入参,施加方永远是我方
t.SetArgs(our, temparg[:args]...) //设置入参,施加方永远是我方
// if t.Owner() { //如果取反,说明是给对方添加的回合效果
// //实际上,owner永远为反,说明是对方给我添加的
@@ -178,7 +184,7 @@ func (i *Input) Parseskill(defender *Input, skill *action.SelectSkillAction) {
// }
//这里是临时缓存buff,后面确认命中后修改HIT状态
// t.Alive() //先让效果保持存活
i.EffectCache = append(i.EffectCache, t)
our.EffectCache = append(our.EffectCache, t)
// i.NewEffects = append(i.NewEffects, t)
}

View File

@@ -7,39 +7,39 @@ import (
type Effect interface {
Compare_Pre(fattack, sattack *action.SelectSkillAction) bool //比较前对优先级的修改
Fight_Start(ctx Ctx) bool //战斗开始
Turn_Start(ctx Ctx) //回合开始,注入特性
Fight_Start() bool //战斗开始
Turn_Start() //回合开始,注入特性
//技能命中前的返回值代表是否可以出手 ,对命中本身的修改应该是对上下文本身的修改
Skill_Hit_Pre(ctx Ctx) bool //对技能修改 行动开始前,注入视为等参数在这里实现
Skill_Hit(ctx Ctx) bool //这是是命中后的对技能的修改,比如变威力
Skill_Hit_to(ctx Ctx) bool // 技能命中前触发//预处理受击技能 被攻击方效果,比如受击时无效技能这样
Skill_Hit_Pre() bool //对技能修改 行动开始前,注入视为等参数在这里实现
Skill_Hit() bool //这是是命中后的对技能的修改,比如变威力
Skill_Hit_ex() bool // 技能命中前触发//预处理受击技能 被攻击方效果,比如受击时无效技能这样
Calculate_Pre(ctx Ctx) bool //视为 无视效果,相当于这里对敌方的修改
OnSkill(ctx Ctx) bool // 触发on miss onhit
Calculate_Pre() bool //视为 无视效果,相当于这里对敌方的修改
OnSkill() bool // 触发on miss onhit
//Skill_Can(ctx Ctx) bool //使用技能 可以取消用技能节点 技能无效节点锁定伤害加上
Damage_ADD(ctx Ctx) bool // 攻击前触发 ,这时候就是+区间
Damage_Mul(ctx Ctx) bool // 攻击触发
//Skill_Can() bool //使用技能 可以取消用技能节点 技能无效节点锁定伤害加上
Damage_ADD() bool // 攻击前触发 ,这时候就是+区间
Damage_Mul() 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_Use(ctx Ctx) bool //技能PP减少节点
Skill_Useed(ctx Ctx) bool //技能PP减少节点
Damage_Floor() bool // 保底伤害
Damage_DIV_ex() bool //受击前触发 这时候就是百分比减伤区间
Damage_SUB_ex() bool // 受击触发 这时候就是点数减伤
Damage_Lock() bool //锁定伤害
Damage_Lock_ex() bool //被动方锁定伤害
Damage_Shield() bool // 护盾值变化时触发
//Damage_Use() bool // 伤害作用
Skill_Use_ex() bool //技能PP减少节点
Skill_Useed() bool //技能PP减少节点
//OnDefeat(opp *Input) bool // 精灵被击败时触发
OnSwitchIn(ctx Ctx) bool // 精灵出战 / 上场时触发
OnSwitchOut(ctx Ctx) bool // 精灵下场时触发
// OnOwnerSwitchIn(ctx Ctx) bool // 所属玩家精灵出战时触发
// OnOwnerSwitchOut(ctx Ctx) bool // 所属玩家精灵下场时触发
OnSwitchIn() bool // 精灵出战 / 上场时触发
OnSwitchOut() bool // 精灵下场时触发
// OnOwnerSwitchIn() bool // 所属玩家精灵出战时触发
// OnOwnerSwitchOut() bool // 所属玩家精灵下场时触发
Turn_End(ctx Ctx) //回合结束计算
PreBattleEnd(ctx Ctx) bool //战斗结束前
OnBattleEnd(ctx Ctx) bool //战斗结束
Turn_End() //回合结束计算
PreBattleEnd() bool //战斗结束前
OnBattleEnd() bool //战斗结束
Prop_Befer(in *Input, prop, level int8, ptype info.EnumAbilityOpType) bool //锁定属性
//效果添加时候应该区分主动方和被动方来确认是主动添加的还是受击添加的
//boss是进入防守方才被添加抵御异常状态效果的boss免疫的实质是给挑战者挂载一个阻止添加给对手的debuff
@@ -49,7 +49,7 @@ type Effect interface {
// 治疗相关触发
Heal_Pre(action.BattleActionI, *int) bool // 治疗前触发 回复翻倍效果
//Heal(action.BattleActionI) bool // 治疗生效时触发 药剂反噬
Ctx() *Ctx
//回合数,然后次数另外维护
Duration(...int) int
Hit(...bool) bool

View File

@@ -7,6 +7,7 @@ import (
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"blazing/logic/service/player"
"fmt"
"time"

View File

@@ -1,28 +1,24 @@
package node
import (
"blazing/logic/service/fight/input"
)
// 切精灵返回false重写change方法来实现切换效果
// 精灵切换相关触发
func (e *EffectNode) OnSwitchIn(ctx input.Ctx) bool {
func (e *EffectNode) OnSwitchIn() bool {
//panic("not implemented") // TODO: Implement
return true
}
func (e *EffectNode) OnSwitchOut(ctx input.Ctx) bool {
func (e *EffectNode) OnSwitchOut() bool {
return true
}
func (e *EffectNode) OnOwnerSwitchIn(ctx input.Ctx) bool {
func (e *EffectNode) OnOwnerSwitchIn() bool {
return true
}
// 自身下场,清除掉技能效果
func (e *EffectNode) OnOwnerSwitchOut(ctx input.Ctx) bool {
// e.Input.AttackValue = info.NewAttackValue(e.Input.UserID)
func (e *EffectNode) OnOwnerSwitchOut() bool {
// e.Input.AttackValue = info.NewAttackValue(e.Input.UserID)
return true
}

View File

@@ -9,10 +9,10 @@ import (
func (e *EffectNode) Compare_Pre(fattack, sattack *action.SelectSkillAction) bool {
return false
}
func (e *EffectNode) Turn_Start(ctx input.Ctx) {
func (e *EffectNode) Turn_Start() {
//panic("not implemented") // TODO: Implement
}
func (e *EffectNode) Turn_End(ctx input.Ctx) {
func (e *EffectNode) Turn_End() {
if e.duration == 0 { // 保留 (负数表示永久)
@@ -21,7 +21,7 @@ func (e *EffectNode) Turn_End(ctx input.Ctx) {
} else {
e.trunl.Do(func() {
if ctx.Input.FightC.IsFirst(ctx.Input.Player) { //如果对方先手
if e.Ctx().Opp.FightC.IsFirst(e.Ctx().Opp.Player) { //如果对方先手
e.duration++
// e.Alive(true)
}

View File

@@ -1,38 +1,34 @@
package node
import (
"blazing/logic/service/fight/input"
)
func (e *EffectNode) Damage_ADD(ctx input.Ctx) bool {
func (e *EffectNode) Damage_ADD() bool {
return true
}
func (e *EffectNode) Damage_Mul(ctx input.Ctx) bool {
func (e *EffectNode) Damage_Mul() bool {
return true
}
func (e *EffectNode) Damage_Floor(ctx input.Ctx) bool {
func (e *EffectNode) Damage_Floor() bool {
return true
}
func (e *EffectNode) Damage_DIV(ctx input.Ctx) bool {
func (e *EffectNode) Damage_DIV_ex() bool {
return true
}
func (e *EffectNode) Damage_SUB(ctx input.Ctx) bool {
func (e *EffectNode) Damage_SUB_ex() bool {
return true
}
func (e *EffectNode) Damage_Lock(ctx input.Ctx) bool {
func (e *EffectNode) Damage_Lock() bool {
return true
}
func (e *EffectNode) Damage_Locked(ctx input.Ctx) bool {
func (e *EffectNode) Damage_Lock_ex() bool {
return true
}
func (e *EffectNode) Damage_Shield(ctx input.Ctx) bool {
func (e *EffectNode) Damage_Shield() bool {
return true
}

View File

@@ -1,18 +1,16 @@
package node
import "blazing/logic/service/fight/input"
// 回合结束一次性effect清楚掉
func (e *EffectNode) Fight_Start(ctx input.Ctx) bool {
func (e *EffectNode) Fight_Start() bool {
//战斗开始应该注入魂印
//panic("not implemented") // TODO: Implement
return true
}
func (e *EffectNode) PreBattleEnd(ctx input.Ctx) bool {
func (e *EffectNode) PreBattleEnd() bool {
panic("not implemented") // TODO: Implement
}
func (e *EffectNode) OnBattleEnd(ctx input.Ctx) bool {
func (e *EffectNode) OnBattleEnd() bool {
panic("not implemented") // TODO: Implement
}

View File

@@ -23,6 +23,7 @@ type EffectNode struct {
alive bool // 是否失效 effect返回值是否被取消是否被删除
hit bool
trunl sync.Once
ctx input.Ctx
//增加owner target如果owner target都为自身就回合效果结束后再使用回合效果
}
@@ -39,7 +40,11 @@ func (e *EffectNode) GetInput() *input.Input {
return e.Input
}
func (e *EffectNode) Ctx() *input.Ctx {
return &e.ctx
}
func (e *EffectNode) Stack(t ...int) int {
if len(t) > 0 {
e.stacks = t[0]

View File

@@ -5,23 +5,23 @@ import (
"blazing/logic/service/fight/input"
)
func (e *EffectNode) Skill_Pre(ctx input.Ctx) bool {
func (e *EffectNode) Skill_Pre() bool {
return true
}
func (e *EffectNode) Calculate_Pre(ctx input.Ctx) bool {
func (e *EffectNode) Calculate_Pre() bool {
return true
}
func (e *EffectNode) Skill_Hit_Pre(ctx input.Ctx) bool {
func (e *EffectNode) Skill_Hit_Pre() bool {
return true
}
func (e *EffectNode) Skill_Hit(ctx input.Ctx) bool {
func (e *EffectNode) Skill_Hit() bool {
return true
}
func (e *EffectNode) Skill_Hit_to(ctx input.Ctx) bool {
func (e *EffectNode) Skill_Hit_ex() bool {
return true
}
func (e *EffectNode) OnSkill(ctx input.Ctx) bool {
func (e *EffectNode) OnSkill() bool {
// if e.Effect != nil {
// if e.Hit() { //没命中
// e.Effect.OnHit(ctx.Input, ctx.SkillEntity)
@@ -32,15 +32,15 @@ func (e *EffectNode) OnSkill(ctx input.Ctx) bool {
return true
}
func (e *EffectNode) Skill_Can(ctx input.Ctx) bool {
func (e *EffectNode) Skill_Can() bool {
return e.Input.CurrentPet.HP != 0
}
func (e *EffectNode) Skill_Use(ctx input.Ctx) bool {
func (e *EffectNode) Skill_Use_ex() bool {
return true
}
func (e *EffectNode) Skill_Useed(ctx input.Ctx) bool {
func (e *EffectNode) Skill_Useed() bool {
// if e.Effect != nil {
// if e.Input.CurrentPet.Info.Hp == 0 {
// e.OnDefeat(ctx.Input, ctx.SkillEntity) //死亡