refactor: 统一战斗报文发送逻辑
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
This commit is contained in:
@@ -291,7 +291,7 @@ func (f *FightC) ReadyFight(c common.PlayerI) {
|
||||
}
|
||||
input.Finished = true
|
||||
if f.checkBothPlayersReady(c) {
|
||||
f.startLegacyGroupBattle()
|
||||
f.startBattle(f.FightStartOutboundInfo)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -369,23 +369,8 @@ func (f *FightC) startBattle(startInfo info.FightStartOutboundInfo) {
|
||||
go f.battleLoop()
|
||||
|
||||
// 向双方广播战斗开始信息
|
||||
if f.LegacyGroupProtocol {
|
||||
f.Broadcast(func(ff *input.Input) {
|
||||
f.sendLegacyGroupStart(ff.Player)
|
||||
})
|
||||
} else {
|
||||
f.Broadcast(func(ff *input.Input) {
|
||||
ff.Player.SendPackCmd(2504, &startInfo)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (f *FightC) startLegacyGroupBattle() {
|
||||
f.startl.Do(func() {
|
||||
go f.battleLoop()
|
||||
f.Broadcast(func(ff *input.Input) {
|
||||
f.sendLegacyGroupStart(ff.Player)
|
||||
f.sendFightPacket(ff.Player, fightPacketStart, &startInfo)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -426,7 +426,7 @@ func (f *FightC) enterturn(firstAttack, secondAttack *action.SelectSkillAction)
|
||||
for _, switchAction := range f.Switch {
|
||||
if fighter.Player.GetInfo().UserID != switchAction.Reason.UserId {
|
||||
// println("切精灵", switchAction.Reason.UserId, switchAction.Reason.ID)
|
||||
fighter.Player.SendPackCmd(2407, &switchAction.Reason)
|
||||
f.sendFightPacket(fighter.Player, fightPacketChangePetSuccess, &switchAction.Reason)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -434,14 +434,14 @@ func (f *FightC) enterturn(firstAttack, secondAttack *action.SelectSkillAction)
|
||||
if f.closefight && f.Info.Mode == info.BattleMode.PET_MELEE {
|
||||
// f.Broadcast(func(fighter *input.Input) {
|
||||
// if fighter.UserID != f.WinnerId {
|
||||
// fighter.Player.SendPackCmd(2505, &attackValueResult)
|
||||
// f.sendFightPacket(fighter.Player, 2505, groupCmdSkillHurt, /&attackValueResult)
|
||||
// }
|
||||
|
||||
// })
|
||||
return
|
||||
}
|
||||
f.Broadcast(func(fighter *input.Input) {
|
||||
fighter.Player.SendPackCmd(2505, &attackValueResult)
|
||||
f.sendFightPacket(fighter.Player, fightPacketSkillResult, &attackValueResult)
|
||||
fighter.CanChange = 0
|
||||
})
|
||||
if f.closefight {
|
||||
|
||||
@@ -3,11 +3,8 @@ package fight
|
||||
import (
|
||||
"blazing/logic/service/common"
|
||||
"blazing/logic/service/fight/action"
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/logic/service/fight/input"
|
||||
"blazing/modules/player/model"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -39,6 +36,38 @@ const (
|
||||
groupModelPlayerMulti uint32 = 6
|
||||
)
|
||||
|
||||
type fightPacketKind uint8
|
||||
|
||||
type legacyEscapeSuccessInfo struct {
|
||||
UserID uint32 `struc:"uint32"`
|
||||
Nick string `struc:"[16]byte"`
|
||||
Side uint8 `struc:"uint8"`
|
||||
ActorIndex uint8 `struc:"uint8"`
|
||||
}
|
||||
|
||||
type legacyBoutDoneInfo struct {
|
||||
Round uint32 `struc:"uint32"`
|
||||
}
|
||||
|
||||
type legacySpriteDieInfo struct {
|
||||
Flag uint8 `struc:"uint8"`
|
||||
Side uint8 `struc:"uint8"`
|
||||
ActorIndex uint8 `struc:"uint8"`
|
||||
Reserve uint8 `struc:"uint8"`
|
||||
HasBackup uint32 `struc:"uint32"`
|
||||
}
|
||||
|
||||
const (
|
||||
fightPacketReady fightPacketKind = iota
|
||||
fightPacketStart
|
||||
fightPacketSkillResult
|
||||
fightPacketOver
|
||||
fightPacketChangePetSuccess
|
||||
fightPacketUseItem
|
||||
fightPacketChat
|
||||
fightPacketLoadPercentNotice
|
||||
)
|
||||
|
||||
func groupModelByFight(f *FightC) uint32 {
|
||||
if f == nil {
|
||||
return groupModelBoss
|
||||
@@ -55,374 +84,139 @@ func groupModelByFight(f *FightC) uint32 {
|
||||
}
|
||||
}
|
||||
|
||||
func writeUint8(buf *bytes.Buffer, v uint8) {
|
||||
_ = buf.WriteByte(v)
|
||||
}
|
||||
|
||||
func writeUint32(buf *bytes.Buffer, v uint32) {
|
||||
_ = binary.Write(buf, binary.BigEndian, v)
|
||||
}
|
||||
|
||||
func writeInt32(buf *bytes.Buffer, v int32) {
|
||||
_ = binary.Write(buf, binary.BigEndian, v)
|
||||
}
|
||||
|
||||
func writeFixedString16(buf *bytes.Buffer, s string) {
|
||||
raw := make([]byte, 16)
|
||||
copy(raw, []byte(s))
|
||||
_, _ = buf.Write(raw)
|
||||
}
|
||||
|
||||
func buildPacket(cmd uint32, userID uint32, payload []byte) []byte {
|
||||
header := common.NewTomeeHeader(cmd, userID)
|
||||
totalLen := uint32(17 + len(payload))
|
||||
header.Len = totalLen
|
||||
buf := make([]byte, totalLen)
|
||||
binary.BigEndian.PutUint32(buf[0:4], totalLen)
|
||||
buf[4] = header.Version
|
||||
binary.BigEndian.PutUint32(buf[5:9], cmd)
|
||||
binary.BigEndian.PutUint32(buf[9:13], userID)
|
||||
binary.BigEndian.PutUint32(buf[13:17], 0)
|
||||
copy(buf[17:], payload)
|
||||
return buf
|
||||
}
|
||||
|
||||
func (f *FightC) sendLegacyGroupReady() {
|
||||
f.Broadcast(func(ff *input.Input) {
|
||||
if ff == nil || ff.Player == nil {
|
||||
return
|
||||
}
|
||||
sendLegacyPacket(ff.Player, groupCmdReadyToFight, f.buildLegacyGroupReadyPayload())
|
||||
})
|
||||
}
|
||||
|
||||
func (f *FightC) sendLegacyGroupStart(player common.PlayerI) {
|
||||
if player == nil {
|
||||
return
|
||||
}
|
||||
sendLegacyPacket(player, groupCmdStartFight, f.buildLegacyGroupStartPayload())
|
||||
}
|
||||
|
||||
func (f *FightC) sendLegacyGroupOver(player common.PlayerI, over *model.FightOverInfo) {
|
||||
if player == nil {
|
||||
return
|
||||
}
|
||||
sendLegacyPacket(player, groupCmdFightOver, f.buildLegacyGroupOverPayload(over))
|
||||
if over == nil {
|
||||
over = &model.FightOverInfo{}
|
||||
}
|
||||
f.sendFightPacket(player, fightPacketOver, over)
|
||||
}
|
||||
|
||||
func sendLegacyPacket(player common.PlayerI, cmd uint32, payload []byte) {
|
||||
func (f *FightC) fightPacketCmd(kind fightPacketKind) uint32 {
|
||||
switch kind {
|
||||
case fightPacketReady:
|
||||
if f != nil && f.LegacyGroupProtocol {
|
||||
return groupCmdReadyToFight
|
||||
}
|
||||
return 2503
|
||||
case fightPacketStart:
|
||||
if f != nil && f.LegacyGroupProtocol {
|
||||
return groupCmdStartFight
|
||||
}
|
||||
return 2504
|
||||
case fightPacketSkillResult:
|
||||
if f != nil && f.LegacyGroupProtocol {
|
||||
return groupCmdSkillHurt
|
||||
}
|
||||
return 2505
|
||||
case fightPacketOver:
|
||||
if f != nil && f.LegacyGroupProtocol {
|
||||
return groupCmdFightOver
|
||||
}
|
||||
return 2506
|
||||
case fightPacketChangePetSuccess:
|
||||
if f != nil && f.LegacyGroupProtocol {
|
||||
return groupCmdChangePetSuc
|
||||
}
|
||||
return 2407
|
||||
case fightPacketUseItem:
|
||||
if f != nil && f.LegacyGroupProtocol {
|
||||
return groupCmdUseItem
|
||||
}
|
||||
return 2406
|
||||
case fightPacketChat:
|
||||
if f != nil && f.LegacyGroupProtocol {
|
||||
return groupCmdChat
|
||||
}
|
||||
return 50002
|
||||
case fightPacketLoadPercentNotice:
|
||||
if f != nil && f.LegacyGroupProtocol {
|
||||
return groupCmdLoadPercentNotice
|
||||
}
|
||||
return 2441
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FightC) sendFightPacket(player common.PlayerI, kind fightPacketKind, payload any) {
|
||||
if player == nil {
|
||||
return
|
||||
}
|
||||
if sender, ok := player.(interface{ SendPack([]byte) error }); ok {
|
||||
_ = sender.SendPack(buildPacket(cmd, player.GetInfo().UserID, payload))
|
||||
cmd := f.fightPacketCmd(kind)
|
||||
if cmd == 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FightC) buildLegacyGroupReadyPayload() []byte {
|
||||
var (
|
||||
buf bytes.Buffer
|
||||
users [][]*input.Input
|
||||
)
|
||||
|
||||
writeUint32(&buf, groupModelByFight(f))
|
||||
users = [][]*input.Input{f.Our, f.Opp}
|
||||
for sideIndex, sideInputs := range users {
|
||||
writeUint8(&buf, 1)
|
||||
var leaderID uint32
|
||||
if len(sideInputs) > 0 && sideInputs[0] != nil && sideInputs[0].Player != nil {
|
||||
leaderID = sideInputs[0].Player.GetInfo().UserID
|
||||
}
|
||||
writeUint32(&buf, leaderID)
|
||||
writeUint8(&buf, 1)
|
||||
if leaderID == 0 {
|
||||
writeUint32(&buf, 0)
|
||||
writeFixedString16(&buf, "boss")
|
||||
} else {
|
||||
writeUint32(&buf, leaderID)
|
||||
writeFixedString16(&buf, sideInputs[0].Player.GetInfo().Nick)
|
||||
}
|
||||
writeUint32(&buf, uint32(len(sideInputs)))
|
||||
for _, slot := range sideInputs {
|
||||
if slot == nil || slot.CurrentPet() == nil {
|
||||
continue
|
||||
}
|
||||
currentPet := slot.CurrentPet()
|
||||
writeUint32(&buf, currentPet.Info.ID)
|
||||
writeUint32(&buf, uint32(len(currentPet.Info.SkillList)))
|
||||
for _, skill := range currentPet.Info.SkillList {
|
||||
writeUint32(&buf, skill.ID)
|
||||
}
|
||||
}
|
||||
if sideIndex == 0 && len(sideInputs) == 0 {
|
||||
writeUint32(&buf, 0)
|
||||
writeFixedString16(&buf, "")
|
||||
writeUint32(&buf, 0)
|
||||
}
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func (f *FightC) buildLegacyGroupStartPayload() []byte {
|
||||
var (
|
||||
buf bytes.Buffer
|
||||
sides [][]*input.Input
|
||||
)
|
||||
|
||||
writeUint8(&buf, 0)
|
||||
sides = [][]*input.Input{f.Our, f.Opp}
|
||||
for sideIndex, sideInputs := range sides {
|
||||
writeUint8(&buf, uint8(len(sideInputs)))
|
||||
for pos, slot := range sideInputs {
|
||||
if slot == nil || slot.CurrentPet() == nil {
|
||||
continue
|
||||
}
|
||||
currentPet := slot.CurrentPet()
|
||||
writeUint8(&buf, uint8(sideIndex+1))
|
||||
writeUint8(&buf, uint8(pos))
|
||||
if slot.Player != nil {
|
||||
writeUint32(&buf, slot.Player.GetInfo().UserID)
|
||||
} else {
|
||||
writeUint32(&buf, 0)
|
||||
}
|
||||
writeUint8(&buf, 0)
|
||||
writeUint32(&buf, currentPet.Info.ID)
|
||||
writeUint32(&buf, currentPet.Info.CatchTime)
|
||||
writeUint32(&buf, currentPet.Info.Hp)
|
||||
writeUint32(&buf, currentPet.Info.MaxHp)
|
||||
writeUint32(&buf, currentPet.Info.Level)
|
||||
writeUint32(&buf, 0)
|
||||
writeUint32(&buf, 1)
|
||||
}
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func (f *FightC) buildLegacyGroupOverPayload(over *model.FightOverInfo) []byte {
|
||||
var (
|
||||
buf bytes.Buffer
|
||||
winnerID uint32
|
||||
endReason uint32
|
||||
playerInfo *model.PlayerInfo
|
||||
)
|
||||
if over != nil {
|
||||
winnerID = over.WinnerId
|
||||
endReason = uint32(over.Reason)
|
||||
}
|
||||
if our := f.primaryOurPlayer(); our != nil {
|
||||
playerInfo = our.GetInfo()
|
||||
}
|
||||
writeUint8(&buf, 0)
|
||||
writeUint32(&buf, endReason)
|
||||
writeUint32(&buf, winnerID)
|
||||
writeUint32(&buf, 0)
|
||||
if playerInfo != nil {
|
||||
writeUint32(&buf, uint32(playerInfo.TwoTimes))
|
||||
writeUint32(&buf, uint32(playerInfo.ThreeTimes))
|
||||
writeUint32(&buf, playerInfo.AutoFightTime)
|
||||
writeUint32(&buf, 0)
|
||||
writeUint32(&buf, uint32(playerInfo.EnergyTime))
|
||||
writeUint32(&buf, playerInfo.LearnTimes)
|
||||
} else {
|
||||
for i := 0; i < 6; i++ {
|
||||
writeUint32(&buf, 0)
|
||||
}
|
||||
}
|
||||
return buf.Bytes()
|
||||
player.SendPackCmd(cmd, payload)
|
||||
}
|
||||
|
||||
func (f *FightC) SendLegacyEscapeSuccess(player common.PlayerI, actorIndex int) {
|
||||
if f == nil || !f.LegacyGroupProtocol || player == nil {
|
||||
return
|
||||
}
|
||||
payload := f.buildLegacyEscapePayload(player, actorIndex)
|
||||
f.Broadcast(func(ff *input.Input) {
|
||||
if ff == nil || ff.Player == nil {
|
||||
return
|
||||
}
|
||||
sendLegacyPacket(ff.Player, groupCmdEscapeSuc, payload)
|
||||
})
|
||||
}
|
||||
|
||||
func (f *FightC) buildLegacyEscapePayload(player common.PlayerI, actorIndex int) []byte {
|
||||
var buf bytes.Buffer
|
||||
side := uint8(1)
|
||||
if !f.isOurPlayerID(player.GetInfo().UserID) {
|
||||
side = 2
|
||||
}
|
||||
writeUint32(&buf, player.GetInfo().UserID)
|
||||
writeFixedString16(&buf, player.GetInfo().Nick)
|
||||
writeUint8(&buf, side)
|
||||
writeUint8(&buf, uint8(actorIndex))
|
||||
return buf.Bytes()
|
||||
payload := legacyEscapeSuccessInfo{
|
||||
UserID: player.GetInfo().UserID,
|
||||
Nick: player.GetInfo().Nick,
|
||||
Side: side,
|
||||
ActorIndex: uint8(actorIndex),
|
||||
}
|
||||
f.Broadcast(func(ff *input.Input) {
|
||||
if ff == nil || ff.Player == nil {
|
||||
return
|
||||
}
|
||||
ff.Player.SendPackCmd(groupCmdEscapeSuc, &payload)
|
||||
})
|
||||
}
|
||||
|
||||
func (f *FightC) sendLegacyRoundBroadcast(firstAttack, secondAttack *action.SelectSkillAction) {
|
||||
if f == nil || !f.LegacyGroupProtocol {
|
||||
return
|
||||
}
|
||||
if firstAttack != nil {
|
||||
f.sendLegacyGroupSkillHurt(firstAttack)
|
||||
}
|
||||
if secondAttack != nil {
|
||||
f.sendLegacyGroupSkillHurt(secondAttack)
|
||||
}
|
||||
f.sendLegacyGroupBoutDone()
|
||||
}
|
||||
|
||||
func (f *FightC) sendLegacyGroupSkillHurt(skillAction *action.SelectSkillAction) {
|
||||
var payload []byte
|
||||
if skillAction == nil {
|
||||
return
|
||||
}
|
||||
payload = f.buildLegacyGroupSkillHurtPayload(skillAction)
|
||||
if len(payload) == 0 {
|
||||
return
|
||||
}
|
||||
f.Broadcast(func(ff *input.Input) {
|
||||
if ff == nil || ff.Player == nil {
|
||||
return
|
||||
}
|
||||
sendLegacyPacket(ff.Player, groupCmdSkillHurt, payload)
|
||||
})
|
||||
}
|
||||
|
||||
func (f *FightC) buildLegacyGroupSkillHurtPayload(skillAction *action.SelectSkillAction) []byte {
|
||||
var buf bytes.Buffer
|
||||
attacker := f.GetInputByAction(skillAction, false)
|
||||
defender := f.GetInputByAction(skillAction, true)
|
||||
if attacker == nil || defender == nil || attacker.AttackValue == nil || defender.AttackValue == nil {
|
||||
return nil
|
||||
}
|
||||
writeUint8(&buf, 0)
|
||||
f.writeLegacySkillHurtInfo(&buf, skillAction, attacker, defender, true)
|
||||
f.writeLegacySkillHurtInfo(&buf, skillAction, defender, attacker, false)
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func (f *FightC) writeLegacySkillHurtInfo(buf *bytes.Buffer, skillAction *action.SelectSkillAction, self *input.Input, opponent *input.Input, isAttacker bool) {
|
||||
var (
|
||||
moveID uint32
|
||||
attackVal *model.AttackValue
|
||||
currentPet *info.BattlePetEntity
|
||||
side uint8
|
||||
pos uint8
|
||||
)
|
||||
if self == nil || buf == nil {
|
||||
return
|
||||
}
|
||||
if self.AttackValue == nil {
|
||||
attackVal = info.NewAttackValue(self.UserID)
|
||||
} else {
|
||||
attackVal = self.AttackValue
|
||||
}
|
||||
currentPet = self.CurrentPet()
|
||||
side = 1
|
||||
if !f.isOurPlayerID(self.UserID) {
|
||||
side = 2
|
||||
}
|
||||
pos = uint8(self.TeamSlotIndex())
|
||||
moveID = attackVal.SkillID
|
||||
if isAttacker {
|
||||
if skillAction != nil && skillAction.SkillEntity != nil {
|
||||
moveID = uint32(skillAction.SkillEntity.XML.ID)
|
||||
}
|
||||
writeUint8(buf, 0)
|
||||
} else {
|
||||
writeUint8(buf, 1)
|
||||
moveID = 0
|
||||
}
|
||||
writeUint8(buf, side)
|
||||
writeUint8(buf, pos)
|
||||
writeUint32(buf, self.UserID)
|
||||
for i := 0; i < 20; i++ {
|
||||
writeUint8(buf, uint8(attackVal.Status[i]))
|
||||
}
|
||||
writeUint8(buf, 0)
|
||||
writeUint8(buf, 0)
|
||||
for i := 0; i < 6; i++ {
|
||||
writeUint8(buf, uint8(attackVal.Prop[i]))
|
||||
}
|
||||
if currentPet != nil {
|
||||
writeUint32(buf, currentPet.Info.ID)
|
||||
} else {
|
||||
writeUint32(buf, 0)
|
||||
}
|
||||
writeUint32(buf, moveID)
|
||||
if currentPet != nil {
|
||||
writeUint32(buf, currentPet.Info.Hp)
|
||||
writeUint32(buf, currentPet.Info.MaxHp)
|
||||
writeUint32(buf, uint32(len(currentPet.Info.SkillList)))
|
||||
for _, skill := range currentPet.Info.SkillList {
|
||||
writeUint32(buf, skill.ID)
|
||||
writeUint32(buf, skill.PP)
|
||||
}
|
||||
} else {
|
||||
writeUint32(buf, uint32(maxInt32(attackVal.RemainHp)))
|
||||
writeUint32(buf, attackVal.MaxHp)
|
||||
writeUint32(buf, uint32(len(attackVal.SkillList)))
|
||||
for _, skill := range attackVal.SkillList {
|
||||
writeUint32(buf, skill.ID)
|
||||
writeUint32(buf, skill.PP)
|
||||
}
|
||||
}
|
||||
writeUint32(buf, attackVal.State)
|
||||
if isAttacker {
|
||||
writeUint32(buf, attackVal.IsCritical)
|
||||
writeUint32(buf, attackVal.State)
|
||||
writeUint32(buf, 1)
|
||||
writeInt32(buf, int32(attackVal.LostHp))
|
||||
writeInt32(buf, attackVal.GainHp)
|
||||
}
|
||||
writeUint32(buf, 0)
|
||||
}
|
||||
|
||||
func (f *FightC) sendLegacyGroupBoutDone() {
|
||||
var buf bytes.Buffer
|
||||
if f == nil || !f.LegacyGroupProtocol {
|
||||
return
|
||||
}
|
||||
writeUint32(&buf, f.Round)
|
||||
payload := legacyBoutDoneInfo{Round: f.Round}
|
||||
f.Broadcast(func(ff *input.Input) {
|
||||
if ff == nil || ff.Player == nil {
|
||||
return
|
||||
}
|
||||
sendLegacyPacket(ff.Player, groupCmdBoutDone, buf.Bytes())
|
||||
ff.Player.SendPackCmd(groupCmdBoutDone, &payload)
|
||||
})
|
||||
}
|
||||
|
||||
func (f *FightC) sendLegacySpriteDie(in *input.Input, hasBackup bool) {
|
||||
var (
|
||||
buf bytes.Buffer
|
||||
side uint8
|
||||
data uint32
|
||||
)
|
||||
if f == nil || !f.LegacyGroupProtocol || in == nil {
|
||||
return
|
||||
}
|
||||
side = 1
|
||||
side := uint8(1)
|
||||
if !f.isOurPlayerID(in.UserID) {
|
||||
side = 2
|
||||
}
|
||||
var data uint32
|
||||
if hasBackup {
|
||||
data = 1
|
||||
}
|
||||
writeUint8(&buf, 1)
|
||||
writeUint8(&buf, side)
|
||||
writeUint8(&buf, uint8(in.TeamSlotIndex()))
|
||||
writeUint8(&buf, 1)
|
||||
writeUint32(&buf, data)
|
||||
payload := legacySpriteDieInfo{
|
||||
Flag: 1,
|
||||
Side: side,
|
||||
ActorIndex: uint8(in.TeamSlotIndex()),
|
||||
Reserve: 1,
|
||||
HasBackup: data,
|
||||
}
|
||||
f.Broadcast(func(ff *input.Input) {
|
||||
if ff == nil || ff.Player == nil {
|
||||
return
|
||||
}
|
||||
sendLegacyPacket(ff.Player, groupCmdSpriteDie, buf.Bytes())
|
||||
ff.Player.SendPackCmd(groupCmdSpriteDie, &payload)
|
||||
})
|
||||
}
|
||||
|
||||
func maxInt32(v int32) int32 {
|
||||
if v < 0 {
|
||||
return 0
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
@@ -276,6 +276,9 @@ func (f *FightC) setActionAttackValue(act action.BattleActionI) {
|
||||
}
|
||||
attacker.AttackValue.ActorIndex = uint32(act.GetActorIndex())
|
||||
targetIndex, _ := DecodeTargetIndex(act.GetTargetIndex())
|
||||
if _, resolvedIndex, ok := f.resolveActionTarget(act); ok && resolvedIndex >= 0 {
|
||||
targetIndex = resolvedIndex
|
||||
}
|
||||
attacker.AttackValue.TargetIndex = uint32(targetIndex)
|
||||
}
|
||||
|
||||
@@ -316,6 +319,25 @@ func (f *FightC) GetInputByPlayerAt(c common.PlayerI, actorIndex int, isOpposite
|
||||
return f.getInputByUserID(c.GetInfo().UserID, actorIndex, isOpposite)
|
||||
}
|
||||
|
||||
func (f *FightC) resolveActionTarget(c action.BattleActionI) (*input.Input, int, bool) {
|
||||
if c == nil {
|
||||
return nil, -1, false
|
||||
}
|
||||
attacker := f.getInputByUserID(c.GetPlayerID(), c.GetActorIndex(), false)
|
||||
if attacker == nil {
|
||||
return nil, -1, false
|
||||
}
|
||||
encodedTargetIndex := c.GetTargetIndex()
|
||||
targetIndex, targetIsOpposite := DecodeTargetIndex(encodedTargetIndex)
|
||||
if !targetIsOpposite {
|
||||
return attacker.TeamSlotAt(targetIndex), targetIndex, false
|
||||
}
|
||||
if target, resolvedIndex := attacker.OpponentSlotAtOrNextLiving(targetIndex); target != nil {
|
||||
return target, resolvedIndex, true
|
||||
}
|
||||
return attacker.OpponentSlotAt(targetIndex), targetIndex, true
|
||||
}
|
||||
|
||||
func (f *FightC) GetInputByAction(c action.BattleActionI, isOpposite bool) *input.Input {
|
||||
if c == nil {
|
||||
if isOpposite {
|
||||
@@ -327,8 +349,8 @@ func (f *FightC) GetInputByAction(c action.BattleActionI, isOpposite bool) *inpu
|
||||
if !isOpposite {
|
||||
return f.getInputByUserID(c.GetPlayerID(), index, false)
|
||||
}
|
||||
targetIndex, targetIsOpposite := DecodeTargetIndex(c.GetTargetIndex())
|
||||
return f.getInputByUserID(c.GetPlayerID(), targetIndex, targetIsOpposite)
|
||||
target, _, _ := f.resolveActionTarget(c)
|
||||
return target
|
||||
}
|
||||
|
||||
// 玩家使用技能
|
||||
@@ -377,7 +399,7 @@ func (f *FightC) GetRound() uint32 {
|
||||
}
|
||||
func (f *FightC) Chat(c common.PlayerI, msg string) {
|
||||
|
||||
f.GetInputByPlayer(c, true).Player.SendPackCmd(50002, &user.ChatOutboundInfo{
|
||||
f.sendFightPacket(f.GetInputByPlayer(c, true).Player, fightPacketChat, &user.ChatOutboundInfo{
|
||||
SenderId: c.GetInfo().UserID,
|
||||
SenderNickname: c.GetInfo().Nick,
|
||||
Message: utils.RemoveLast(msg),
|
||||
@@ -392,7 +414,7 @@ func (f *FightC) LoadPercent(c common.PlayerI, percent int32) {
|
||||
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC {
|
||||
return
|
||||
}
|
||||
f.GetInputByPlayer(c, true).Player.SendPackCmd(2441, &info.LoadPercentOutboundInfo{
|
||||
f.sendFightPacket(f.GetInputByPlayer(c, true).Player, fightPacketLoadPercentNotice, &info.LoadPercentOutboundInfo{
|
||||
Id: c.GetInfo().UserID,
|
||||
Percent: uint32(percent),
|
||||
})
|
||||
|
||||
@@ -69,6 +69,20 @@ func (our *Input) HasLivingTeammate() bool {
|
||||
return len(our.LivingTeammates()) > 0
|
||||
}
|
||||
|
||||
// TeamSlotAt 返回指定己方站位。
|
||||
func (our *Input) TeamSlotAt(index int) *Input {
|
||||
if our == nil {
|
||||
return nil
|
||||
}
|
||||
if index >= 0 && index < len(our.Team) {
|
||||
return our.Team[index]
|
||||
}
|
||||
if index == 0 {
|
||||
return our
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// OpponentSlotAt 返回指定敌方站位。
|
||||
func (our *Input) OpponentSlotAt(index int) *Input {
|
||||
if our == nil {
|
||||
@@ -83,6 +97,50 @@ func (our *Input) OpponentSlotAt(index int) *Input {
|
||||
return nil
|
||||
}
|
||||
|
||||
func nextLivingSlotIndex(slots []*Input, start int) int {
|
||||
if len(slots) == 0 {
|
||||
return -1
|
||||
}
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
if start >= len(slots) {
|
||||
start = 0
|
||||
}
|
||||
|
||||
availableIndex := -1
|
||||
for offset := 0; offset < len(slots); offset++ {
|
||||
idx := (start + offset) % len(slots)
|
||||
slot := slots[idx]
|
||||
if slot == nil {
|
||||
continue
|
||||
}
|
||||
if availableIndex < 0 {
|
||||
availableIndex = idx
|
||||
}
|
||||
current := slot.CurrentPet()
|
||||
if current != nil && current.Info.Hp > 0 {
|
||||
return idx
|
||||
}
|
||||
}
|
||||
return availableIndex
|
||||
}
|
||||
|
||||
// OpponentSlotAtOrNextLiving 返回指定敌方站位;若该目标已死亡,则顺延到下一只存活精灵。
|
||||
func (our *Input) OpponentSlotAtOrNextLiving(index int) (*Input, int) {
|
||||
if our == nil {
|
||||
return nil, -1
|
||||
}
|
||||
if len(our.OppTeam) == 0 {
|
||||
return our.OpponentSlotAt(index), index
|
||||
}
|
||||
resolvedIndex := nextLivingSlotIndex(our.OppTeam, index)
|
||||
if resolvedIndex < 0 {
|
||||
return nil, -1
|
||||
}
|
||||
return our.OppTeam[resolvedIndex], resolvedIndex
|
||||
}
|
||||
|
||||
// RandomOpponentSlotIndex 返回一个可用的敌方站位下标,优先从存活站位中随机。
|
||||
func (our *Input) RandomOpponentSlotIndex() int {
|
||||
if our == nil {
|
||||
|
||||
@@ -174,11 +174,7 @@ func (f *FightC) battleLoop() {
|
||||
//大乱斗,给个延迟
|
||||
//<-time.After(1000)
|
||||
f.Broadcast(func(ff *input.Input) {
|
||||
if f.LegacyGroupProtocol {
|
||||
f.sendLegacyGroupOver(ff.Player, &f.FightOverInfo)
|
||||
} else {
|
||||
ff.Player.SendPackCmd(2506, &f.FightOverInfo)
|
||||
}
|
||||
f.sendFightPacket(ff.Player, fightPacketOver, &f.FightOverInfo)
|
||||
|
||||
ff.Player.QuitFight()
|
||||
|
||||
@@ -264,7 +260,7 @@ func (f *FightC) collectPlayerActions(expectedSlots map[actionSlotKey]struct{})
|
||||
ret.Reason = reason
|
||||
ret.Reason.ActorIndex = uint32(ret.ActorIndex)
|
||||
|
||||
selfinput.Player.SendPackCmd(2407, &ret.Reason)
|
||||
f.sendFightPacket(selfinput.Player, fightPacketChangePetSuccess, &ret.Reason)
|
||||
|
||||
f.Switch[key] = ret
|
||||
|
||||
@@ -285,7 +281,7 @@ func (f *FightC) collectPlayerActions(expectedSlots map[actionSlotKey]struct{})
|
||||
selfinput.CanChange = 0
|
||||
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC && paction.GetPlayerID() == 0 {
|
||||
f.Switch = make(map[actionSlotKey]*action.ActiveSwitchAction)
|
||||
f.Our[0].Player.SendPackCmd(2407, &ret.Reason)
|
||||
f.sendFightPacket(f.Our[0].Player, fightPacketChangePetSuccess, &ret.Reason)
|
||||
//println("AI出手死切")
|
||||
f.triggerNPCActions() // boss出手后获取出招
|
||||
|
||||
@@ -606,7 +602,7 @@ func (f *FightC) handleItemAction(a *action.UseItemAction) {
|
||||
if currentPet == nil {
|
||||
return
|
||||
}
|
||||
ff.Player.SendPackCmd(2406, &info.UsePetIteminfo{
|
||||
f.sendFightPacket(ff.Player, fightPacketUseItem, &info.UsePetIteminfo{
|
||||
UserID: source.UserID,
|
||||
ChangeHp: int32(addhp),
|
||||
ItemID: uint32(item.ID),
|
||||
@@ -621,7 +617,7 @@ func (f *FightC) handleItemAction(a *action.UseItemAction) {
|
||||
if currentPet == nil {
|
||||
return
|
||||
}
|
||||
ff.Player.SendPackCmd(2406, &info.UsePetIteminfo{
|
||||
f.sendFightPacket(ff.Player, fightPacketUseItem, &info.UsePetIteminfo{
|
||||
UserID: source.UserID,
|
||||
|
||||
ItemID: uint32(item.ID),
|
||||
|
||||
@@ -196,13 +196,9 @@ func buildFight(opts *fightBuildOptions) (*FightC, errorcode.ErrorCode) {
|
||||
}
|
||||
f.FightStartOutboundInfo = f.buildFightStartInfo()
|
||||
|
||||
if f.LegacyGroupProtocol {
|
||||
f.sendLegacyGroupReady()
|
||||
} else {
|
||||
f.Broadcast(func(ff *input.Input) {
|
||||
ff.Player.SendPackCmd(2503, &f.ReadyInfo)
|
||||
})
|
||||
}
|
||||
f.Broadcast(func(ff *input.Input) {
|
||||
f.sendFightPacket(ff.Player, fightPacketReady, &f.ReadyInfo)
|
||||
})
|
||||
|
||||
cool.Cron.AfterFunc(loadtime, func() {
|
||||
our := f.primaryOur()
|
||||
@@ -220,11 +216,7 @@ func buildFight(opts *fightBuildOptions) (*FightC, errorcode.ErrorCode) {
|
||||
f.WinnerId = opp.Player.GetInfo().UserID
|
||||
}
|
||||
f.Broadcast(func(ff *input.Input) {
|
||||
if f.LegacyGroupProtocol {
|
||||
f.sendLegacyGroupOver(ff.Player, &f.FightOverInfo)
|
||||
} else {
|
||||
ff.Player.SendPackCmd(2506, &f.FightOverInfo)
|
||||
}
|
||||
f.sendFightPacket(ff.Player, fightPacketOver, &f.FightOverInfo)
|
||||
ff.Player.QuitFight()
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user