feat: 实现每日签到功能并优化战斗和道具逻辑
This commit is contained in:
@@ -166,14 +166,7 @@ func refreshPetPaneKeepHP(currentPet *model.PetInfo, hp uint32) {
|
||||
|
||||
// handleRegularPetItem 处理普通宠物道具
|
||||
func (h Controller) handleRegularPetItem(itemID uint32, currentPet *model.PetInfo) errorcode.ErrorCode {
|
||||
handler := item.PetItemRegistry.GetHandler(itemID)
|
||||
if handler == nil {
|
||||
return errorcode.ErrorCodes.ErrItemUnusable
|
||||
}
|
||||
if !handler(itemID, currentPet) {
|
||||
return errorcode.ErrorCodes.ErrItemUnusable
|
||||
}
|
||||
return 0
|
||||
return item.PetItemRegistry.Handle(itemID, currentPet)
|
||||
}
|
||||
|
||||
// ResetNature 重置宠物性格
|
||||
|
||||
75
logic/service/fight/boss/NewSeIdx_247.go
Normal file
75
logic/service/fight/boss/NewSeIdx_247.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package effect
|
||||
|
||||
import (
|
||||
"blazing/logic/service/fight/action"
|
||||
"blazing/logic/service/fight/input"
|
||||
)
|
||||
|
||||
// 247. 固定增加体力/攻击/防御/特攻/特防/速度;(a1-a6: hp/atk/def/spatk/spdef/spd)
|
||||
type NewSel247 struct {
|
||||
NewSel0
|
||||
}
|
||||
|
||||
func (e *NewSel247) TurnStart(fattack *action.SelectSkillAction, sattack *action.SelectSkillAction) {
|
||||
if !e.IsOwner() {
|
||||
return
|
||||
}
|
||||
|
||||
pet := e.Ctx().Our.CurPet[0]
|
||||
if pet == nil {
|
||||
return
|
||||
}
|
||||
|
||||
hpBonus := uint32(e.Args()[0].IntPart())
|
||||
if hpBonus > 0 {
|
||||
pet.Info.MaxHp += hpBonus
|
||||
pet.Info.Hp += hpBonus
|
||||
}
|
||||
|
||||
for i, propIdx := range []int{0, 1, 2, 3, 4} {
|
||||
add := uint32(e.Args()[i+1].IntPart())
|
||||
if add == 0 {
|
||||
continue
|
||||
}
|
||||
pet.Info.Prop[propIdx] += add
|
||||
}
|
||||
}
|
||||
|
||||
func (e *NewSel247) TurnEnd() {
|
||||
if !e.IsOwner() {
|
||||
return
|
||||
}
|
||||
|
||||
pet := e.Ctx().Our.CurPet[0]
|
||||
if pet == nil {
|
||||
return
|
||||
}
|
||||
|
||||
hpBonus := uint32(e.Args()[0].IntPart())
|
||||
if hpBonus > 0 {
|
||||
if pet.Info.MaxHp > hpBonus {
|
||||
pet.Info.MaxHp -= hpBonus
|
||||
} else {
|
||||
pet.Info.MaxHp = 1
|
||||
}
|
||||
if pet.Info.Hp > pet.Info.MaxHp {
|
||||
pet.Info.Hp = pet.Info.MaxHp
|
||||
}
|
||||
}
|
||||
|
||||
for i, propIdx := range []int{0, 1, 2, 3, 4} {
|
||||
sub := uint32(e.Args()[i+1].IntPart())
|
||||
if sub == 0 {
|
||||
continue
|
||||
}
|
||||
if pet.Info.Prop[propIdx] > sub {
|
||||
pet.Info.Prop[propIdx] -= sub
|
||||
} else {
|
||||
pet.Info.Prop[propIdx] = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
input.InitEffect(input.EffectType.NewSel, 247, &NewSel247{})
|
||||
}
|
||||
@@ -11,9 +11,15 @@ type NewSel26 struct {
|
||||
}
|
||||
|
||||
func (e *NewSel26) TurnStart(fattack *action.SelectSkillAction, sattack *action.SelectSkillAction) {
|
||||
if !e.IsOwner() {
|
||||
return
|
||||
}
|
||||
e.Ctx().Our.CurPet[0].Info.Prop[int(e.Args()[0].IntPart())] += uint32(e.Args()[1].IntPart())
|
||||
}
|
||||
func (e *NewSel26) TurnEnd() {
|
||||
if !e.IsOwner() {
|
||||
return
|
||||
}
|
||||
e.Ctx().Our.CurPet[0].Info.Prop[int(e.Args()[0].IntPart())] -= uint32(e.Args()[1].IntPart())
|
||||
}
|
||||
func init() {
|
||||
|
||||
@@ -27,16 +27,26 @@ const (
|
||||
// 2. targetIndex 始终表示目标在所属阵营内的槽位。
|
||||
// 3. targetRelation 用来区分 targetIndex 属于敌方、自己还是队友。
|
||||
type FightActionEnvelope struct {
|
||||
ActionType FightActionType `json:"actionType"`
|
||||
ActorIndex int `json:"actorIndex"`
|
||||
TargetIndex int `json:"targetIndex"`
|
||||
TargetRelation uint8 `json:"targetRelation,omitempty"`
|
||||
SkillID uint32 `json:"skillId,omitempty"`
|
||||
ItemID uint32 `json:"itemId,omitempty"`
|
||||
CatchTime uint32 `json:"catchTime,omitempty"`
|
||||
Escape bool `json:"escape,omitempty"`
|
||||
Chat string `json:"chat,omitempty"`
|
||||
AtkType uint8 `json:"atkType,omitempty"`
|
||||
// ActionType 当前动作类型,例如 skill、item、change、escape、chat。
|
||||
ActionType FightActionType `json:"actionType"`
|
||||
// ActorIndex 发起动作的我方槽位。
|
||||
ActorIndex int `json:"actorIndex"`
|
||||
// TargetIndex 目标在所属阵营中的槽位下标。
|
||||
TargetIndex int `json:"targetIndex"`
|
||||
// TargetRelation 目标关系:0=对方,1=自己,2=队友。
|
||||
TargetRelation uint8 `json:"targetRelation,omitempty"`
|
||||
// SkillID 技能 ID;仅技能动作使用。
|
||||
SkillID uint32 `json:"skillId,omitempty"`
|
||||
// ItemID 道具 ID;仅道具动作使用。
|
||||
ItemID uint32 `json:"itemId,omitempty"`
|
||||
// CatchTime 精灵实例 ID;切宠或部分道具动作使用。
|
||||
CatchTime uint32 `json:"catchTime,omitempty"`
|
||||
// Escape 是否为逃跑动作;主要用于协议层兼容和调试。
|
||||
Escape bool `json:"escape,omitempty"`
|
||||
// Chat 聊天内容;仅聊天动作使用。
|
||||
Chat string `json:"chat,omitempty"`
|
||||
// AtkType 前端技能目标类型兜底值,沿用技能表 AtkType 定义。
|
||||
AtkType uint8 `json:"atkType,omitempty"`
|
||||
}
|
||||
|
||||
// NewSkillActionEnvelope 构造技能动作 envelope。
|
||||
|
||||
@@ -45,7 +45,7 @@ type FighterState struct {
|
||||
Level uint32 `json:"level"`
|
||||
// Anger 怒气值;当前服务端主链路暂未实际填充时默认为 0,先为协议对齐预留。
|
||||
Anger uint32 `json:"anger"`
|
||||
// Status 当前异常/增益状态回合数组;下标语义沿用现有战斗状态定义。
|
||||
// Status 当前异常或增益状态回合数组;下标语义沿用现有战斗状态定义。
|
||||
Status [20]int8 `json:"status"`
|
||||
// Prop 当前能力等级变化数组:攻击、防御、特攻、特防、速度、命中。
|
||||
Prop [6]int8 `json:"prop"`
|
||||
@@ -55,30 +55,42 @@ type FighterState struct {
|
||||
|
||||
// FightStateMeta 是统一状态包的公共元数据。
|
||||
type FightStateMeta struct {
|
||||
Round uint32 `json:"round"`
|
||||
Weather uint32 `json:"weather,omitempty"`
|
||||
WinnerID uint32 `json:"winnerId,omitempty"`
|
||||
Reason model.EnumBattleOverReason `json:"reason,omitempty"`
|
||||
LegacyCmd uint32 `json:"legacyCmd,omitempty"`
|
||||
// Round 当前回合数。
|
||||
Round uint32 `json:"round"`
|
||||
// Weather 当前天气或场地编号;当前主链路未填充时可为 0。
|
||||
Weather uint32 `json:"weather,omitempty"`
|
||||
// WinnerID 当前已确定的胜者 ID;未结束时通常为 0。
|
||||
WinnerID uint32 `json:"winnerId,omitempty"`
|
||||
// Reason 当前已确定的结束原因;未结束时通常为 0。
|
||||
Reason model.EnumBattleOverReason `json:"reason,omitempty"`
|
||||
// LegacyCmd 对应旧协议命令号,便于新旧包对照和过渡期调试。
|
||||
LegacyCmd uint32 `json:"legacyCmd,omitempty"`
|
||||
}
|
||||
|
||||
// FightSkillHurtState 保存技能结算后的左右两侧战报快照。
|
||||
// FightSkillHurtState 保存技能结算阶段的详细战报。
|
||||
type FightSkillHurtState struct {
|
||||
Left []model.AttackValue `json:"left,omitempty"`
|
||||
// Left 我方阵营本次技能结算后的攻击值快照列表。
|
||||
Left []model.AttackValue `json:"left,omitempty"`
|
||||
// Right 敌方阵营本次技能结算后的攻击值快照列表。
|
||||
Right []model.AttackValue `json:"right,omitempty"`
|
||||
}
|
||||
|
||||
// FightLoadState 保存加载进度信息。
|
||||
type FightLoadState struct {
|
||||
UserID uint32 `json:"userId"`
|
||||
// UserID 当前上报加载进度的玩家 ID。
|
||||
UserID uint32 `json:"userId"`
|
||||
// Percent 当前加载百分比。
|
||||
Percent uint32 `json:"percent"`
|
||||
}
|
||||
|
||||
// FightChatState 保存战斗内聊天信息。
|
||||
type FightChatState struct {
|
||||
SenderID uint32 `json:"senderId"`
|
||||
// SenderID 发言玩家 ID。
|
||||
SenderID uint32 `json:"senderId"`
|
||||
// SenderNickname 发言玩家昵称。
|
||||
SenderNickname string `json:"senderNickname"`
|
||||
Message string `json:"message"`
|
||||
// Message 聊天内容。
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// FightStateEnvelope 是统一出站状态结构。
|
||||
|
||||
@@ -24,6 +24,26 @@ import (
|
||||
"github.com/jinzhu/copier"
|
||||
)
|
||||
|
||||
func consumeLimitedPetEffects(pet *model.PetInfo) {
|
||||
if pet == nil || len(pet.EffectInfo) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
next := pet.EffectInfo[:0]
|
||||
for _, eff := range pet.EffectInfo {
|
||||
if eff.Status == 2 {
|
||||
if eff.LeftCount > 0 {
|
||||
eff.LeftCount--
|
||||
}
|
||||
if eff.LeftCount == 0 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
next = append(next, eff)
|
||||
}
|
||||
pet.EffectInfo = next
|
||||
}
|
||||
|
||||
func (f *FightC) battleLoop() {
|
||||
defer func() {
|
||||
if err := recover(); err != nil { // 恢复 panic,err 为 panic 错误值
|
||||
@@ -69,26 +89,28 @@ func (f *FightC) battleLoop() {
|
||||
tt.Alive(false) //将所有属性变化失效掉
|
||||
return true
|
||||
})
|
||||
if f.Info.Mode != info.BattleMode.PET_MELEE { //不是乱斗,传回血量
|
||||
for i := 0; i < len(ff.AllPet); i++ {
|
||||
for j := 0; j < len(ff.Player.GetInfo().PetList); j++ {
|
||||
if ff.Player.GetInfo().PetList[j].CatchTime == ff.AllPet[i].Info.CatchTime {
|
||||
|
||||
if ff.UserID == f.WinnerId {
|
||||
currentPet := ff.CurrentPet()
|
||||
if currentPet != nil && currentPet.Info.CatchTime == ff.Player.GetInfo().PetList[j].CatchTime {
|
||||
f.Winpet = &ff.Player.GetInfo().PetList[j]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ff.Player.GetInfo().PetList[j].Hp = utils.Min(ff.Player.GetInfo().PetList[j].MaxHp, ff.AllPet[i].Info.Hp)
|
||||
ff.Player.GetInfo().PetList[j].SkillList = ff.AllPet[i].Info.SkillList
|
||||
}
|
||||
|
||||
for i := 0; i < len(ff.AllPet); i++ {
|
||||
consumeLimitedPetEffects(&ff.AllPet[i].Info)
|
||||
for j := 0; j < len(ff.Player.GetInfo().PetList); j++ {
|
||||
if ff.Player.GetInfo().PetList[j].CatchTime != ff.AllPet[i].Info.CatchTime {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
ff.Player.GetInfo().PetList[j].EffectInfo = ff.AllPet[i].Info.EffectInfo
|
||||
if f.Info.Mode == info.BattleMode.PET_MELEE {
|
||||
continue
|
||||
}
|
||||
|
||||
if ff.UserID == f.WinnerId {
|
||||
currentPet := ff.CurrentPet()
|
||||
if currentPet != nil && currentPet.Info.CatchTime == ff.Player.GetInfo().PetList[j].CatchTime {
|
||||
f.Winpet = &ff.Player.GetInfo().PetList[j]
|
||||
}
|
||||
}
|
||||
|
||||
ff.Player.GetInfo().PetList[j].Hp = utils.Min(ff.Player.GetInfo().PetList[j].MaxHp, ff.AllPet[i].Info.Hp)
|
||||
ff.Player.GetInfo().PetList[j].SkillList = ff.AllPet[i].Info.SkillList
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
@@ -2,6 +2,7 @@ package item
|
||||
|
||||
import (
|
||||
"blazing/common/data/xmlres"
|
||||
"blazing/common/socket/errorcode"
|
||||
"blazing/common/utils"
|
||||
"blazing/modules/player/model"
|
||||
"strings"
|
||||
@@ -111,6 +112,62 @@ func nvfunc(itemid uint32, onpet *model.PetInfo) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func handleNewSeIdxPetItem(itemid uint32, onpet *model.PetInfo) errorcode.ErrorCode {
|
||||
itemCfg, ok := xmlres.ItemsMAP[int(itemid)]
|
||||
if !ok || itemCfg.NewSeIdx == 0 {
|
||||
return errorcode.ErrorCodes.ErrItemUnusable
|
||||
}
|
||||
|
||||
effectCfg, ok := xmlres.EffectMAP[itemCfg.NewSeIdx]
|
||||
if !ok {
|
||||
return errorcode.ErrorCodes.ErrSystemError
|
||||
}
|
||||
|
||||
effectStatus := byte(gconv.Int(effectCfg.Stat))
|
||||
effectIdx := uint16(itemCfg.NewSeIdx)
|
||||
leftCount := 1
|
||||
if effectCfg.Times != nil && *effectCfg.Times != "" {
|
||||
leftCount = gconv.Int(*effectCfg.Times)
|
||||
if leftCount <= 0 {
|
||||
leftCount = 1
|
||||
}
|
||||
}
|
||||
|
||||
limitedCount := 0
|
||||
for _, eff := range onpet.EffectInfo {
|
||||
if eff.Idx == effectIdx {
|
||||
return errorcode.ErrorCodes.ErrCannotInjectPillAgain
|
||||
}
|
||||
if eff.Status == 2 {
|
||||
limitedCount++
|
||||
}
|
||||
}
|
||||
if effectStatus == 2 && limitedCount >= 2 {
|
||||
return errorcode.ErrorCodes.ErrTooManyEnergyOrbs
|
||||
}
|
||||
|
||||
onpet.EffectInfo = append(onpet.EffectInfo, model.PetEffectInfo{
|
||||
ItemID: itemid,
|
||||
Idx: effectIdx,
|
||||
Status: effectStatus,
|
||||
LeftCount: byte(leftCount),
|
||||
EID: uint16(gconv.Int(effectCfg.Eid)),
|
||||
Args: effectCfg.ArgsS,
|
||||
})
|
||||
return 0
|
||||
}
|
||||
|
||||
func (r *PetItemHandlerRegistry) Handle(itemID uint32, onpet *model.PetInfo) errorcode.ErrorCode {
|
||||
handler := r.GetHandler(itemID)
|
||||
if handler != nil {
|
||||
if handler(itemID, onpet) {
|
||||
return 0
|
||||
}
|
||||
return errorcode.ErrorCodes.ErrItemUnusable
|
||||
}
|
||||
return handleNewSeIdxPetItem(itemID, onpet)
|
||||
}
|
||||
|
||||
// -------------------------- 6. 初始化注册器(注册所有处理器) --------------------------
|
||||
func init() {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user