Compare commits
10 Commits
61a135b3a7
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de6c700bb3 | ||
|
|
3232efd05a | ||
|
|
0c79fee8af | ||
|
|
3d77e146e9 | ||
|
|
a43a25c610 | ||
|
|
3cfde577eb | ||
|
|
85f9c02ced | ||
|
|
9f7fd83626 | ||
|
|
ee8b0a2182 | ||
|
|
6e95e014fa |
File diff suppressed because one or more lines are too long
@@ -19,20 +19,13 @@ func (h Controller) SavePetBagOrder(
|
|||||||
return nil, 0
|
return nil, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// PetRetrieveFromWarehouse 领回仓库精灵
|
// PetRetrieveFromWarehouse 从放生仓库领回精灵
|
||||||
func (h Controller) PetRetrieveFromWarehouse(
|
func (h Controller) PetRetrieveFromWarehouse(
|
||||||
data *PET_RETRIEVE, player *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
data *PET_RETRIEVE, player *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||||
if _, ok := player.FindPetBagSlot(data.CatchTime); ok {
|
if !player.Service.Pet.UpdateFree(data.CatchTime, 1, 0) {
|
||||||
return nil, 0
|
return nil, errorcode.ErrorCodes.ErrPokemonIDMismatch
|
||||||
}
|
}
|
||||||
|
|
||||||
petInfo := player.Service.Pet.PetInfoOneByCatchTime(data.CatchTime)
|
|
||||||
if petInfo == nil {
|
|
||||||
return nil, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
player.AddPetToAvailableBag(petInfo.Data)
|
|
||||||
|
|
||||||
return nil, 0
|
return nil, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,9 +48,8 @@ func (h Controller) PetReleaseToWarehouse(
|
|||||||
if inBag || inBackup || freeForbidden == 1 {
|
if inBag || inBackup || freeForbidden == 1 {
|
||||||
return nil, errorcode.ErrorCodes.ErrCannotReleaseNonWarehouse
|
return nil, errorcode.ErrorCodes.ErrCannotReleaseNonWarehouse
|
||||||
}
|
}
|
||||||
|
if !player.Service.Pet.UpdateFree(data.CatchTime, 0, 1) {
|
||||||
if !player.Service.Pet.UpdateFree(data.CatchTime, 1) {
|
return nil, errorcode.ErrorCodes.ErrCannotReleaseNonWarehouse
|
||||||
return nil, errorcode.ErrorCodes.ErrSystemError
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, 0
|
return nil, 0
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ func (e *Effect1181) OnSkill() bool {
|
|||||||
type Effect1182 struct{ node.EffectNode }
|
type Effect1182 struct{ node.EffectNode }
|
||||||
|
|
||||||
func (e *Effect1182) Skill_Use() bool {
|
func (e *Effect1182) Skill_Use() bool {
|
||||||
if len(e.Args()) < 2 || e.Ctx().Our == nil || e.Ctx().Our.CurPet[0] == nil || e.Ctx().Opp == nil || e.Ctx().Opp.CurPet[0] == nil {
|
if len(e.Args()) < 2 || e.Ctx().Our == nil || e.Ctx().Our.CurPet[0] == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,9 +153,15 @@ func (e *Effect1182) Skill_Use() bool {
|
|||||||
if targetHP.Cmp(alpacadecimal.Zero) < 0 {
|
if targetHP.Cmp(alpacadecimal.Zero) < 0 {
|
||||||
targetHP = alpacadecimal.Zero
|
targetHP = alpacadecimal.Zero
|
||||||
}
|
}
|
||||||
if e.Ctx().Opp.CurPet[0].GetHP().Cmp(targetHP) > 0 {
|
forEachEnemyTargetBySkill(e.Ctx().Our, e.Ctx().Opp, e.Ctx().SkillEntity, func(target *input.Input) bool {
|
||||||
e.Ctx().Opp.CurPet[0].Info.Hp = uint32(targetHP.IntPart())
|
if target == nil || target.CurrentPet() == nil {
|
||||||
}
|
return true
|
||||||
|
}
|
||||||
|
if target.CurrentPet().GetHP().Cmp(targetHP) > 0 {
|
||||||
|
target.CurrentPet().Info.Hp = uint32(targetHP.IntPart())
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
sub := e.Ctx().Our.InitEffect(input.EffectType.Sub, 1182, int(e.Args()[1].IntPart()))
|
sub := e.Ctx().Our.InitEffect(input.EffectType.Sub, 1182, int(e.Args()[1].IntPart()))
|
||||||
if sub != nil {
|
if sub != nil {
|
||||||
|
|||||||
@@ -10,20 +10,23 @@ type Effect169 struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *Effect169) OnSkill() bool {
|
func (e *Effect169) OnSkill() bool {
|
||||||
|
|
||||||
chance := e.Args()[1].IntPart()
|
chance := e.Args()[1].IntPart()
|
||||||
success, _, _ := e.Input.Player.Roll(int(chance), 100)
|
success, _, _ := e.Input.Player.Roll(int(chance), 100)
|
||||||
if success {
|
if success {
|
||||||
// 添加异常状态
|
e.ForEachOpponentSlot(func(target *input.Input) bool {
|
||||||
statusEffect := e.CarrierInput().InitEffect(input.EffectType.Status, int(e.Args()[2].IntPart())) // 以麻痹为例
|
if target == nil {
|
||||||
if statusEffect != nil {
|
return true
|
||||||
e.TargetInput().AddEffect(e.CarrierInput(), statusEffect)
|
}
|
||||||
}
|
statusEffect := e.CarrierInput().InitEffect(input.EffectType.Status, int(e.Args()[2].IntPart()))
|
||||||
|
if statusEffect != nil {
|
||||||
|
target.AddEffect(e.CarrierInput(), statusEffect)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
input.InitEffect(input.EffectType.Skill, 169, &Effect169{})
|
input.InitEffect(input.EffectType.Skill, 169, &Effect169{})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package effect
|
package effect
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"blazing/logic/service/fight/input"
|
||||||
"blazing/logic/service/fight/node"
|
"blazing/logic/service/fight/node"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -41,14 +42,16 @@ type Effect5 struct {
|
|||||||
// 技能触发时调用
|
// 技能触发时调用
|
||||||
// -----------------------------------------------------------
|
// -----------------------------------------------------------
|
||||||
func (e *Effect5) Skill_Use() bool {
|
func (e *Effect5) Skill_Use() bool {
|
||||||
|
|
||||||
// 概率判定
|
// 概率判定
|
||||||
ok, _, _ := e.Input.Player.Roll(e.SideEffectArgs[1], 100)
|
ok, _, _ := e.Input.Player.Roll(e.SideEffectArgs[1], 100)
|
||||||
if !ok {
|
if !ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Ctx().Opp.SetProp(e.Ctx().Our, int8(e.SideEffectArgs[0]), int8(e.SideEffectArgs[2]))
|
forEachEnemyTargetBySkill(e.Ctx().Our, e.Ctx().Opp, e.Ctx().SkillEntity, func(target *input.Input) bool {
|
||||||
|
target.SetProp(e.Ctx().Our, int8(e.SideEffectArgs[0]), int8(e.SideEffectArgs[2]))
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,15 +22,19 @@ type Effect76 struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *Effect76) OnSkill() bool {
|
func (e *Effect76) OnSkill() bool {
|
||||||
|
|
||||||
// 概率判定
|
// 概率判定
|
||||||
ok, _, _ := e.Input.Player.Roll(int(e.Args()[0].IntPart()), 100)
|
ok, _, _ := e.Input.Player.Roll(int(e.Args()[0].IntPart()), 100)
|
||||||
if !ok {
|
if !ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{
|
|
||||||
Type: info.DamageType.Fixed,
|
damage := alpacadecimal.NewFromInt(int64(e.SideEffectArgs[2]))
|
||||||
Damage: alpacadecimal.NewFromInt(int64(e.SideEffectArgs[2])),
|
forEachEnemyTargetBySkill(e.Ctx().Our, e.Ctx().Opp, e.Ctx().SkillEntity, func(target *input.Input) bool {
|
||||||
|
target.Damage(e.Ctx().Our, &info.DamageZone{
|
||||||
|
Type: info.DamageType.Fixed,
|
||||||
|
Damage: damage,
|
||||||
|
})
|
||||||
|
return true
|
||||||
})
|
})
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ var effectInfoByID = map[int]string{
|
|||||||
164: "{0}回合内若受到攻击则有{1}%概率令对手{2}",
|
164: "{0}回合内若受到攻击则有{1}%概率令对手{2}",
|
||||||
165: "{0}回合内每回合防御和特防等级+{1}",
|
165: "{0}回合内每回合防御和特防等级+{1}",
|
||||||
166: "{0}回合内若对手使用属性攻击则{2}%对手{1}等级{3}",
|
166: "{0}回合内若对手使用属性攻击则{2}%对手{1}等级{3}",
|
||||||
169: "{0}回合内每回合额外附加{1}%概率令对手{2}",
|
169: "{0}回合内每回合额外附加{1}%概率令对方阵营全体{2}",
|
||||||
170: "若先出手,则免疫当回合伤害并回复1/{0}的最大体力值",
|
170: "若先出手,则免疫当回合伤害并回复1/{0}的最大体力值",
|
||||||
171: "{0}回合内自身使用属性技能时能较快出手",
|
171: "{0}回合内自身使用属性技能时能较快出手",
|
||||||
172: "若后出手,则给予对方损伤的1/{0}会回复自己的体力",
|
172: "若后出手,则给予对方损伤的1/{0}会回复自己的体力",
|
||||||
|
|||||||
@@ -207,9 +207,15 @@ func registerSelfDamageOnSkillEffects() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{
|
forEachEnemyTargetBySkill(e.Ctx().Our, e.Ctx().Opp, e.Ctx().SkillEntity, func(target *input.Input) bool {
|
||||||
Type: info.DamageType.Fixed,
|
if target == nil || target.CurrentPet() == nil {
|
||||||
Damage: opponentDamage,
|
return true
|
||||||
|
}
|
||||||
|
target.Damage(e.Ctx().Our, &info.DamageZone{
|
||||||
|
Type: info.DamageType.Fixed,
|
||||||
|
Damage: opponentDamage,
|
||||||
|
})
|
||||||
|
return true
|
||||||
})
|
})
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
@@ -241,9 +247,15 @@ func registerSelfDamageSkillUseEffects() {
|
|||||||
Type: info.DamageType.Fixed,
|
Type: info.DamageType.Fixed,
|
||||||
Damage: damage,
|
Damage: damage,
|
||||||
})
|
})
|
||||||
e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{
|
forEachEnemyTargetBySkill(e.Ctx().Our, e.Ctx().Opp, e.Ctx().SkillEntity, func(target *input.Input) bool {
|
||||||
Type: info.DamageType.Fixed,
|
if target == nil || target.CurrentPet() == nil {
|
||||||
Damage: damage,
|
return true
|
||||||
|
}
|
||||||
|
target.Damage(e.Ctx().Our, &info.DamageZone{
|
||||||
|
Type: info.DamageType.Fixed,
|
||||||
|
Damage: damage,
|
||||||
|
})
|
||||||
|
return true
|
||||||
})
|
})
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
@@ -253,9 +265,23 @@ func registerSelfDamageSkillUseEffects() {
|
|||||||
Damage: alpacadecimal.NewFromInt(int64(e.Ctx().Our.CurPet[0].Info.MaxHp)),
|
Damage: alpacadecimal.NewFromInt(int64(e.Ctx().Our.CurPet[0].Info.MaxHp)),
|
||||||
})
|
})
|
||||||
damage := int64(grand.N(250, 300))
|
damage := int64(grand.N(250, 300))
|
||||||
e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{
|
forEachEnemyTargetBySkill(e.Ctx().Our, e.Ctx().Opp, e.Ctx().SkillEntity, func(target *input.Input) bool {
|
||||||
Type: info.DamageType.Fixed,
|
if target == nil {
|
||||||
Damage: alpacadecimal.Min(alpacadecimal.NewFromInt(damage), e.Ctx().Opp.CurPet[0].GetHP().Sub(alpacadecimal.NewFromInt(1))),
|
return true
|
||||||
|
}
|
||||||
|
targetPet := target.CurrentPet()
|
||||||
|
if targetPet == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
remainHP := targetPet.GetHP().Sub(alpacadecimal.NewFromInt(1))
|
||||||
|
if remainHP.Cmp(alpacadecimal.Zero) <= 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
target.Damage(e.Ctx().Our, &info.DamageZone{
|
||||||
|
Type: info.DamageType.Fixed,
|
||||||
|
Damage: alpacadecimal.Min(alpacadecimal.NewFromInt(damage), remainHP),
|
||||||
|
})
|
||||||
|
return true
|
||||||
})
|
})
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
@@ -280,15 +306,25 @@ func registerSelfDamageSkillUseEffects() {
|
|||||||
randomDamage = grand.N(minDamage, maxDamage)
|
randomDamage = grand.N(minDamage, maxDamage)
|
||||||
}
|
}
|
||||||
|
|
||||||
remainHP := e.Ctx().Opp.CurPet[0].GetHP().Sub(alpacadecimal.NewFromInt(1))
|
forEachEnemyTargetBySkill(e.Ctx().Our, e.Ctx().Opp, e.Ctx().SkillEntity, func(target *input.Input) bool {
|
||||||
if remainHP.Cmp(alpacadecimal.Zero) <= 0 {
|
if target == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
targetPet := target.CurrentPet()
|
||||||
|
if targetPet == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
remainHP := targetPet.GetHP().Sub(alpacadecimal.NewFromInt(1))
|
||||||
|
if remainHP.Cmp(alpacadecimal.Zero) <= 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
damage := alpacadecimal.Min(alpacadecimal.NewFromInt(int64(randomDamage)), remainHP)
|
damage := alpacadecimal.Min(alpacadecimal.NewFromInt(int64(randomDamage)), remainHP)
|
||||||
e.Ctx().Opp.Damage(e.Ctx().Our, &info.DamageZone{
|
target.Damage(e.Ctx().Our, &info.DamageZone{
|
||||||
Type: info.DamageType.Fixed,
|
Type: info.DamageType.Fixed,
|
||||||
Damage: damage,
|
Damage: damage,
|
||||||
|
})
|
||||||
|
return true
|
||||||
})
|
})
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
@@ -297,11 +333,17 @@ func registerSelfDamageSkillUseEffects() {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
applyAllPropDown(e.Ctx().Our, e.Ctx().Opp, int8(e.Args()[0].IntPart()))
|
forEachEnemyTargetBySkill(e.Ctx().Our, e.Ctx().Opp, e.Ctx().SkillEntity, func(target *input.Input) bool {
|
||||||
sub := e.Ctx().Our.InitEffect(input.EffectType.Sub, 1380, int(e.Args()[1].IntPart()), int(e.Args()[2].IntPart()))
|
if target == nil || target.CurrentPet() == nil {
|
||||||
if sub != nil {
|
return true
|
||||||
e.Ctx().Opp.AddEffect(e.Ctx().Our, sub)
|
}
|
||||||
}
|
applyAllPropDown(e.Ctx().Our, target, int8(e.Args()[0].IntPart()))
|
||||||
|
sub := e.Ctx().Our.InitEffect(input.EffectType.Sub, 1380, int(e.Args()[1].IntPart()), int(e.Args()[2].IntPart()))
|
||||||
|
if sub != nil {
|
||||||
|
target.AddEffect(e.Ctx().Our, sub)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
e.Ctx().Our.Damage(e.Ctx().Our, &info.DamageZone{
|
e.Ctx().Our.Damage(e.Ctx().Our, &info.DamageZone{
|
||||||
Type: info.DamageType.Fixed,
|
Type: info.DamageType.Fixed,
|
||||||
Damage: e.Ctx().Our.CurPet[0].GetHP(),
|
Damage: e.Ctx().Our.CurPet[0].GetHP(),
|
||||||
|
|||||||
34
logic/service/fight/effect/skill_target_helper.go
Normal file
34
logic/service/fight/effect/skill_target_helper.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package effect
|
||||||
|
|
||||||
|
import (
|
||||||
|
"blazing/logic/service/fight/info"
|
||||||
|
"blazing/logic/service/fight/input"
|
||||||
|
)
|
||||||
|
|
||||||
|
// forEachEnemyTargetBySkill 在普通情况下对单个目标生效;
|
||||||
|
// 当技能为 AtkType=3(仅自己)且当前目标仍在己方时,改为遍历敌方全部站位。
|
||||||
|
func forEachEnemyTargetBySkill(carrier, target *input.Input, skill *info.SkillEntity, fn func(*input.Input) bool) {
|
||||||
|
if fn == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if carrier == nil {
|
||||||
|
if target != nil {
|
||||||
|
fn(target)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if skill == nil || skill.XML.AtkType != 3 || !isSameSideTarget(carrier, target) {
|
||||||
|
if target != nil {
|
||||||
|
fn(target)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, opponent := range carrier.OpponentSlots() {
|
||||||
|
if opponent == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !fn(opponent) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
"blazing/logic/service/fight/action"
|
"blazing/logic/service/fight/action"
|
||||||
"blazing/logic/service/fight/info"
|
"blazing/logic/service/fight/info"
|
||||||
"blazing/logic/service/fight/input"
|
"blazing/logic/service/fight/input"
|
||||||
|
_ "blazing/logic/service/fight/itemover"
|
||||||
|
_ "blazing/logic/service/fight/rule"
|
||||||
"blazing/modules/player/model"
|
"blazing/modules/player/model"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
@@ -133,7 +135,20 @@ func (f *FightC) getSkillParticipants(skillAction *action.SelectSkillAction) (*i
|
|||||||
if skillAction == nil {
|
if skillAction == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return f.GetInputByAction(skillAction, false), f.GetInputByAction(skillAction, true)
|
attacker := f.GetInputByAction(skillAction, false)
|
||||||
|
defender := f.GetInputByAction(skillAction, true)
|
||||||
|
if attacker != nil && defender == attacker && shouldResolveOpponentAsTarget(skillAction.SkillEntity) {
|
||||||
|
if opponent, _ := attacker.OpponentSlotAtOrNextLiving(0); opponent != nil {
|
||||||
|
defender = opponent
|
||||||
|
} else if opponent := f.roundOpponentInput(attacker); opponent != nil {
|
||||||
|
defender = opponent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return attacker, defender
|
||||||
|
}
|
||||||
|
|
||||||
|
func shouldResolveOpponentAsTarget(skill *info.SkillEntity) bool {
|
||||||
|
return skill != nil && skill.XML.AtkType == 3
|
||||||
}
|
}
|
||||||
|
|
||||||
// setEffectSkillContext 统一设置技能阶段 effect 上下文。
|
// setEffectSkillContext 统一设置技能阶段 effect 上下文。
|
||||||
@@ -232,6 +247,15 @@ func (f *FightC) roundOpponentInput(attacker *input.Input) *input.Input {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func shouldSkipSecondAction(first, second *input.Input) bool {
|
||||||
|
if first == nil || second == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
firstPet := first.CurrentPet()
|
||||||
|
secondPet := second.CurrentPet()
|
||||||
|
return firstPet == nil || firstPet.Info.Hp <= 0 || secondPet == nil || secondPet.Info.Hp <= 0
|
||||||
|
}
|
||||||
|
|
||||||
// enterturn 处理战斗回合逻辑
|
// enterturn 处理战斗回合逻辑
|
||||||
// 回合有先手方和后手方,同时有攻击方和被攻击方
|
// 回合有先手方和后手方,同时有攻击方和被攻击方
|
||||||
func (f *FightC) enterturn(firstAttack, secondAttack *action.SelectSkillAction) {
|
func (f *FightC) enterturn(firstAttack, secondAttack *action.SelectSkillAction) {
|
||||||
@@ -333,6 +357,10 @@ func (f *FightC) enterturn(firstAttack, secondAttack *action.SelectSkillAction)
|
|||||||
if currentAction == nil {
|
if currentAction == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if shouldSkipSecondAction(f.First, f.Second) {
|
||||||
|
secondAttack = nil
|
||||||
|
continue
|
||||||
|
}
|
||||||
attacker, defender = f.getSkillParticipants(secondAttack)
|
attacker, defender = f.getSkillParticipants(secondAttack)
|
||||||
originalSkill = f.copySkill(secondAttack)
|
originalSkill = f.copySkill(secondAttack)
|
||||||
//取消后手历史效果
|
//取消后手历史效果
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ import (
|
|||||||
"blazing/modules/player/model"
|
"blazing/modules/player/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// <!--
|
||||||
|
// GBTL:
|
||||||
|
// 1. AtkNum:本技能同时攻击数量, 默认:1(不能为0)
|
||||||
|
// 2. AtkType:攻击类型: 0:所有人, 1:仅己方, 2:仅对方, 3:仅自己, 默认:2
|
||||||
|
// -->
|
||||||
const (
|
const (
|
||||||
groupCmdReadyToFight uint32 = 7555
|
groupCmdReadyToFight uint32 = 7555
|
||||||
groupCmdReadyFightFinish uint32 = 7556
|
groupCmdReadyFightFinish uint32 = 7556
|
||||||
@@ -492,15 +497,23 @@ func (f *FightC) sendLegacyRoundBroadcast(firstAttack, secondAttack *action.Sele
|
|||||||
if f == nil || !f.LegacyGroupProtocol {
|
if f == nil || !f.LegacyGroupProtocol {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if firstAttack != nil {
|
if f.legacySkillExecuted(firstAttack) {
|
||||||
f.sendLegacyGroupSkillHurt(firstAttack)
|
f.sendLegacyGroupSkillHurt(firstAttack)
|
||||||
}
|
}
|
||||||
if secondAttack != nil {
|
if f.legacySkillExecuted(secondAttack) {
|
||||||
f.sendLegacyGroupSkillHurt(secondAttack)
|
f.sendLegacyGroupSkillHurt(secondAttack)
|
||||||
}
|
}
|
||||||
f.sendLegacyGroupBoutDone()
|
f.sendLegacyGroupBoutDone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *FightC) legacySkillExecuted(skillAction *action.SelectSkillAction) bool {
|
||||||
|
if f == nil || skillAction == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
attacker := f.GetInputByAction(skillAction, false)
|
||||||
|
return attacker != nil && attacker.AttackValue != nil && attacker.AttackValue.SkillID != 0
|
||||||
|
}
|
||||||
|
|
||||||
func (f *FightC) sendLegacyGroupSkillHurt(skillAction *action.SelectSkillAction) {
|
func (f *FightC) sendLegacyGroupSkillHurt(skillAction *action.SelectSkillAction) {
|
||||||
if f == nil || !f.LegacyGroupProtocol || skillAction == nil {
|
if f == nil || !f.LegacyGroupProtocol || skillAction == nil {
|
||||||
return
|
return
|
||||||
@@ -580,10 +593,10 @@ func (f *FightC) buildLegacyGroupSkillAttackInfo(skillAction *action.SelectSkill
|
|||||||
if attackValue == nil {
|
if attackValue == nil {
|
||||||
attackValue = info.NewAttackValue(self.UserID)
|
attackValue = info.NewAttackValue(self.UserID)
|
||||||
}
|
}
|
||||||
if skillAction != nil && skillAction.SkillEntity != nil {
|
if attackValue.SkillID != 0 {
|
||||||
result.MoveID = uint32(skillAction.SkillEntity.XML.ID)
|
|
||||||
} else {
|
|
||||||
result.MoveID = attackValue.SkillID
|
result.MoveID = attackValue.SkillID
|
||||||
|
} else if skillAction != nil && skillAction.SkillEntity != nil {
|
||||||
|
result.MoveID = uint32(skillAction.SkillEntity.XML.ID)
|
||||||
}
|
}
|
||||||
result.IsCrit = attackValue.IsCritical
|
result.IsCrit = attackValue.IsCritical
|
||||||
result.EffectName = attackValue.State
|
result.EffectName = attackValue.State
|
||||||
|
|||||||
61
logic/service/fight/group_legacy_test.go
Normal file
61
logic/service/fight/group_legacy_test.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
package fight
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"blazing/logic/service/fight/action"
|
||||||
|
fightinfo "blazing/logic/service/fight/info"
|
||||||
|
"blazing/logic/service/fight/input"
|
||||||
|
"blazing/modules/player/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSendLegacyRoundBroadcastSkipsUnexecutedAction(t *testing.T) {
|
||||||
|
ourPlayer := &stubPlayer{info: model.PlayerInfo{UserID: 1001}}
|
||||||
|
oppPlayer := &stubPlayer{info: model.PlayerInfo{UserID: 2002}}
|
||||||
|
|
||||||
|
our := input.NewInput(nil, ourPlayer)
|
||||||
|
our.InitAttackValue()
|
||||||
|
our.AttackValue.SkillID = 111
|
||||||
|
our.SetCurPetAt(0, fightinfo.CreateBattlePetEntity(model.PetInfo{
|
||||||
|
ID: 11,
|
||||||
|
Hp: 80,
|
||||||
|
MaxHp: 100,
|
||||||
|
CatchTime: 101,
|
||||||
|
}))
|
||||||
|
|
||||||
|
opp := input.NewInput(nil, oppPlayer)
|
||||||
|
opp.InitAttackValue()
|
||||||
|
opp.SetCurPetAt(0, fightinfo.CreateBattlePetEntity(model.PetInfo{
|
||||||
|
ID: 22,
|
||||||
|
Hp: 0,
|
||||||
|
MaxHp: 100,
|
||||||
|
CatchTime: 202,
|
||||||
|
}))
|
||||||
|
|
||||||
|
fc := &FightC{
|
||||||
|
Our: []*input.Input{our},
|
||||||
|
Opp: []*input.Input{opp},
|
||||||
|
LegacyGroupProtocol: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
firstAttack := &action.SelectSkillAction{
|
||||||
|
BaseAction: action.BaseAction{PlayerID: ourPlayer.info.UserID, ActorIndex: 0, TargetIndex: 0},
|
||||||
|
}
|
||||||
|
secondAttack := &action.SelectSkillAction{
|
||||||
|
BaseAction: action.BaseAction{PlayerID: oppPlayer.info.UserID, ActorIndex: 0, TargetIndex: 0},
|
||||||
|
}
|
||||||
|
|
||||||
|
fc.sendLegacyRoundBroadcast(firstAttack, secondAttack)
|
||||||
|
|
||||||
|
for _, player := range []*stubPlayer{ourPlayer, oppPlayer} {
|
||||||
|
if len(player.sentCmds) != 2 {
|
||||||
|
t.Fatalf("expected one skill packet plus bout done, got %v", player.sentCmds)
|
||||||
|
}
|
||||||
|
if player.sentCmds[0] != groupCmdSkillHurt {
|
||||||
|
t.Fatalf("expected first packet to be skill hurt, got %d", player.sentCmds[0])
|
||||||
|
}
|
||||||
|
if player.sentCmds[1] != groupCmdBoutDone {
|
||||||
|
t.Fatalf("expected second packet to be bout done, got %d", player.sentCmds[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,7 +12,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type stubPlayer struct {
|
type stubPlayer struct {
|
||||||
info model.PlayerInfo
|
info model.PlayerInfo
|
||||||
|
sentCmds []uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*stubPlayer) ApplyPetDisplayInfo(*spaceinfo.SimpleInfo) {}
|
func (*stubPlayer) ApplyPetDisplayInfo(*spaceinfo.SimpleInfo) {}
|
||||||
@@ -26,7 +27,7 @@ func (*stubPlayer) SetFightC(common.FightI) {}
|
|||||||
func (*stubPlayer) QuitFight() {}
|
func (*stubPlayer) QuitFight() {}
|
||||||
func (*stubPlayer) MessWin(bool) {}
|
func (*stubPlayer) MessWin(bool) {}
|
||||||
func (*stubPlayer) CanFight() errorcode.ErrorCode { return 0 }
|
func (*stubPlayer) CanFight() errorcode.ErrorCode { return 0 }
|
||||||
func (*stubPlayer) SendPackCmd(uint32, any) {}
|
func (p *stubPlayer) SendPackCmd(cmd uint32, _ any) { p.sentCmds = append(p.sentCmds, cmd) }
|
||||||
func (*stubPlayer) GetPetInfo(uint32) []model.PetInfo { return nil }
|
func (*stubPlayer) GetPetInfo(uint32) []model.PetInfo { return nil }
|
||||||
|
|
||||||
func TestFightActionEnvelopeEncodedTargetIndex(t *testing.T) {
|
func TestFightActionEnvelopeEncodedTargetIndex(t *testing.T) {
|
||||||
|
|||||||
@@ -76,8 +76,12 @@ func (s *PetService) PetCount(flag int) int {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PetService) UpdateFree(catchTime, free uint32) bool {
|
func (s *PetService) UpdateFree(catchTime, fromFree, toFree uint32) bool {
|
||||||
res, err := s.dbm(s.Model).Where("catch_time", catchTime).Data("free", free).Update()
|
res, err := s.dbm(s.Model).
|
||||||
|
Where("catch_time", catchTime).
|
||||||
|
Where("free", fromFree).
|
||||||
|
Data("free", toFree).
|
||||||
|
Update()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ func (s *UserService) PetFusionTx(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := syncPetSnapshotBeforeDeleteTx(tx, userID, currentInfo, masterCatchTime); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := deletePetTx(tx, userID, masterCatchTime); err != nil {
|
if err := deletePetTx(tx, userID, masterCatchTime); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -82,6 +85,9 @@ func (s *UserService) PetFusionTx(
|
|||||||
}
|
}
|
||||||
result.CostItemUsed = used
|
result.CostItemUsed = used
|
||||||
if !used {
|
if !used {
|
||||||
|
if err := syncPetSnapshotBeforeDeleteTx(tx, userID, currentInfo, auxCatchTime); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := deletePetTx(tx, userID, auxCatchTime); err != nil {
|
if err := deletePetTx(tx, userID, auxCatchTime); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -223,6 +229,28 @@ func updatePetDataTx(tx gdb.TX, userID uint32, catchTime uint32, pet model.PetIn
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func syncPetSnapshotBeforeDeleteTx(tx gdb.TX, userID uint32, info model.PlayerInfo, catchTime uint32) error {
|
||||||
|
pet, ok := findPetDataSnapshotInPlayerInfo(info, catchTime)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return updatePetDataTx(tx, userID, catchTime, pet)
|
||||||
|
}
|
||||||
|
|
||||||
|
func findPetDataSnapshotInPlayerInfo(info model.PlayerInfo, catchTime uint32) (model.PetInfo, bool) {
|
||||||
|
for i := range info.PetList {
|
||||||
|
if info.PetList[i].CatchTime == catchTime {
|
||||||
|
return info.PetList[i], true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := range info.BackupPetList {
|
||||||
|
if info.BackupPetList[i].CatchTime == catchTime {
|
||||||
|
return info.BackupPetList[i], true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return model.PetInfo{}, false
|
||||||
|
}
|
||||||
|
|
||||||
func deletePetTx(tx gdb.TX, userID uint32, catchTime uint32) error {
|
func deletePetTx(tx gdb.TX, userID uint32, catchTime uint32) error {
|
||||||
res, err := tx.Model(model.NewPet()).
|
res, err := tx.Model(model.NewPet()).
|
||||||
Where("player_id", userID).
|
Where("player_id", userID).
|
||||||
|
|||||||
50
modules/player/service/pet_fusion_tx_test.go
Normal file
50
modules/player/service/pet_fusion_tx_test.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"blazing/modules/player/model"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFindPetDataSnapshotInPlayerInfo(t *testing.T) {
|
||||||
|
t.Run("pet list", func(t *testing.T) {
|
||||||
|
want := model.PetInfo{CatchTime: 1001, Level: 55}
|
||||||
|
info := model.PlayerInfo{
|
||||||
|
PetList: []model.PetInfo{want},
|
||||||
|
}
|
||||||
|
|
||||||
|
got, ok := findPetDataSnapshotInPlayerInfo(info, want.CatchTime)
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("expected pet snapshot in pet list")
|
||||||
|
}
|
||||||
|
if got.CatchTime != want.CatchTime || got.Level != want.Level {
|
||||||
|
t.Fatalf("unexpected pet snapshot: %+v", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("backup pet list", func(t *testing.T) {
|
||||||
|
want := model.PetInfo{CatchTime: 2002, Level: 66}
|
||||||
|
info := model.PlayerInfo{
|
||||||
|
BackupPetList: []model.PetInfo{want},
|
||||||
|
}
|
||||||
|
|
||||||
|
got, ok := findPetDataSnapshotInPlayerInfo(info, want.CatchTime)
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("expected pet snapshot in backup pet list")
|
||||||
|
}
|
||||||
|
if got.CatchTime != want.CatchTime || got.Level != want.Level {
|
||||||
|
t.Fatalf("unexpected pet snapshot: %+v", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("not found", func(t *testing.T) {
|
||||||
|
info := model.PlayerInfo{
|
||||||
|
PetList: []model.PetInfo{{CatchTime: 3003}},
|
||||||
|
BackupPetList: []model.PetInfo{{CatchTime: 4004}},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := findPetDataSnapshotInPlayerInfo(info, 9999)
|
||||||
|
if ok {
|
||||||
|
t.Fatal("expected missing pet snapshot")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user