feat(item): 新增性格道具支持与相关逻辑调整

新增对特定性格道具的支持,包括 Nature 和 NatureSet 属性解析,
并优化精灵融合、任务奖励、战斗捕捉等流程中的宠物添加方式。
同时修复部分战斗逻辑及数据结构引用问题。
This commit is contained in:
2025-12-03 22:05:28 +08:00
parent e694848c0d
commit 8d7d9da0bf
16 changed files with 691 additions and 1105 deletions

View File

@@ -47,7 +47,8 @@ type Item struct {
YuanshenDegrade int `xml:"YuanshenDegrade,attr,omitempty"` // 融合精灵还原标识(融合精灵还原药剂)
EvRemove int `xml:"EvRemove,attr,omitempty"` // 学习力遗忘类型(各类学习力遗忘剂)
bShowPetBag int `xml:"bShowPetBag,attr,omitempty"` // 宠物背包显示标识(副融合精灵保留药剂等)
Nature int `xml:"Nature,attr,omitempty"`
NatureSet string `xml:"NatureSet,attr,omitempty"`
Pet *Pet `xml:"pet,omitempty"` // 精灵属性子节点
TeamPK *TeamPK `xml:"teamPK,omitempty"` // 要塞保卫战子节点
}

View File

@@ -31,6 +31,7 @@ type PetInfo struct {
YieldingEV string `xml:"YieldingEV,attr"` // 努力值奖励,格式为"HP Atk Def SpAtk SpDef Spd"
EvolvesFrom int `xml:"EvolvesFrom,attr"` // 进化前的怪物ID
EvolvesTo uint32 `xml:"EvolvesTo,attr"` // 进化后的怪物ID
EvolvFlag int `xml:"EvolvFlag,attr"` //<!-- EvolvFlag: 0 - 直接进化(等级到了就进化); 1~49 - 触发进化,默认值: 0 (默认直接进化) -->
EvolvingLv int `xml:"EvolvingLv,attr"` // 进化等级
FreeForbidden int `xml:"FreeForbidden,attr"` // 是否禁止放生
FuseMaster int `xml:"FuseMaster,attr"` // 是否可作为融合主素材
@@ -45,15 +46,15 @@ type PetInfo struct {
LearnableMoves LearnableMoves `xml:"LearnableMoves"` // 可学习的技能
}
func (basic *PetInfo) GetBasic() uint32 {
return basic.Atk +
return basic.Atk +
basic.Def +
basic.SpAtk +
basic.SpDef +
basic.Spd +
uint32(basic.HP)
}
// Monsters 表示所有怪物的集合
type Monsters struct {
XMLName xml.Name `xml:"Monsters"`

View File

@@ -56,7 +56,7 @@ func (h Controller) PetFusion(data *pet.C2S_PetFusion, c *player.Player) (result
dv2 := decimal.NewFromInt(1).Div(decimal.NewFromInt(3)).Mul(decimal.NewFromInt(int64(Auxpetinfo.Dv)))
dv := dv1.Add(dv2).Add(decimal.NewFromInt(1)).IntPart()
r := model.GenPetInfo(resid, int(dv), int(natureId), effect, -1, 1)
c.Service.Pet.PetAdd(*r)
c.Service.Pet.PetAdd(r)
c.Pet_del(Auxpetinfo.CatchTime)
c.Pet_del(Mcatchpetinfo.CatchTime)
//todo材料扣除

View File

@@ -125,7 +125,7 @@ func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *pla
PetID := moinfo.PetList[0].ID
newm1 := model.GenPetInfo(int(PetID), -1, -1, 0, 0, 1)
c.Service.Pet.PetAdd(*newm1)
c.Service.Pet.PetAdd(newm1)
c.SendPackCmd(8004, &info.S2C_GET_BOSS_MONSTER{
BonusID: uint32(taskid),
@@ -192,7 +192,7 @@ func (h Controller) OnPlayerFightNpcMonster(data *fight.FightNpcMonsterInboundIn
}
evs := gconv.Uint32s(strings.Split(xmlres.PetMAP[int(mo.ID)].YieldingEV, " "))
items.EV = lo.Sum(evs)
items.EV = lo.Sum(evs) - 1
c.Info.EVPool += lo.Sum(evs) //给予累计学习力
foi.Winpet.AddEV(evs)

View File

@@ -1,12 +1,15 @@
package controller
import (
"blazing/common/data/xmlres"
"blazing/common/socket/errorcode"
"blazing/logic/service/fight"
"blazing/logic/service/item"
"blazing/logic/service/player"
"blazing/modules/blazing/model"
"strings"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/grand"
"github.com/jinzhu/copier"
)
@@ -48,6 +51,17 @@ func (h Controller) ItemUsePet(data *item.C2S_USE_PET_ITEM_OUT_OF_FIGHT, c *play
//性格随机
case itemID == 300025:
onpet.Nature = uint32(grand.Intn(25))
case itemID >= 240042 && itemID <= 240056:
if xmlres.ItemsMAP[int(itemID)].Nature != 0 {
onpet.Nature = uint32(xmlres.ItemsMAP[int(itemID)].Nature)
}
if xmlres.ItemsMAP[int(itemID)].NatureSet != "" {
rr := strings.Split(xmlres.ItemsMAP[int(itemID)].NatureSet, " ")
onpet.Nature = gconv.Uint32(rr[grand.Intn(len(rr))-1])
}
default:
// 无效ID处理
return nil, errorcode.ErrorCodes.ErrSystemError

View File

@@ -77,9 +77,10 @@ func (h Controller) Complete_Task(data *task.CompleteTaskInboundInfo, c *player.
if tt.PetTypeId != 0 {
r := model.GenPetInfo(int(tt.PetTypeId), 31, -1, 0, 0, 50)
result.CaptureTime = r.CatchTime
result.PetTypeId = r.ID
c.Service.Pet.PetAdd(*r)
c.Service.Pet.PetAdd(r)
result.CaptureTime = r.CatchTime //这个写到后面,方便捕捉时间被修改后造成的时间不对问题
}
ret := c.ItemAdd(result.ItemList...) //获取成功的条目

View File

@@ -137,6 +137,10 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
// 神罗、圣华登场时魂免“登场时xx”等效果
//阿枫的效果也在这里判断
if f.closefight {
return
}
f.Broadcast(func(ff *input.Input) {
ff.Exec(func(t input.Effect) bool { //回合开始前
@@ -242,6 +246,7 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
e.Alive(true)
}
currentskill = nil
} else {
f.processSkillAttack(attacker, defender, currentskill)
@@ -374,9 +379,6 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
})
ff.GenInfo()
})
// if f.closefight {
// return
// }
ret := info.AttackValueS{
@@ -396,6 +398,9 @@ func (f *FightC) enterturn(fattack, sattack *action.SelectSkillAction) {
})
f.Switch = make(map[uint32]*action.ActiveSwitchAction)
if f.closefight && f.Info.Mode == info.BattleMode.PET_MELEE {
return
}
f.Broadcast(func(ff *input.Input) {
ff.Player.SendPackCmd(2505, &ret)
})

View File

@@ -47,7 +47,7 @@ func CreateBattlePetEntity(info model.PetInfo, rand *rand.Rand) *BattlePetEntity
for i := 0; i < len(info.SkillList); i++ {
//todo 技能信息应该每回合进行深拷贝,保证每次的技能效果都是不一样的
ret.Skills[info.SkillList[i].ID] = CreateSkill(&info.SkillList[i], rand, ret)
ret.Skills[info.SkillList[i].ID] = CreateSkill(info.SkillList[i], rand, ret)
}

View File

@@ -47,7 +47,7 @@ type DamageZone struct {
// 战斗中可以修改技能实体值,比如是否暴击,是否必中等
type SkillEntity struct {
xmlres.Move
Info *model.SkillInfo
Info model.SkillInfo
// DamageValue decimal.Decimal // 伤害值
Rand *rand.Rand
@@ -59,7 +59,7 @@ type SkillEntity struct {
}
// CreateSkill 创建战斗技能实例可指定是否无限PP
func CreateSkill(skill *model.SkillInfo, rand *rand.Rand, pet *BattlePetEntity) *SkillEntity {
func CreateSkill(skill model.SkillInfo, rand *rand.Rand, pet *BattlePetEntity) *SkillEntity {
var ret SkillEntity
ret.Rand = rand

View File

@@ -99,6 +99,7 @@ var BattleOverReason = enum.New[struct {
NOTwind EnumBattleOverReason `enum:"3"` //打成平手
DefaultEnd EnumBattleOverReason `enum:"4"` //默认结束
PlayerEscape EnumBattleOverReason `enum:"5"` //逃跑
Cacthok EnumBattleOverReason `enum:"6"`
}]()
// 战斗模式

View File

@@ -130,7 +130,7 @@ var meetpet = make(map[int]model.PetInfo)
func initmeetpet() {
meetpet = make(map[int]model.PetInfo)
for i, v := range xmlres.PetMAP {
if v.EvolvesTo == 0 && v.ID < 2000 {
if v.EvolvesTo == 0 && v.EvolvFlag == 0 && v.ID < 2000 {
r := model.GenPetInfo(int(v.ID), 24, -1, -1, -1, 100)
meetpet[i] = *r
}

View File

@@ -70,6 +70,18 @@ func (f *FightC) battleLoop() {
}
})
if f.Reason == info.BattleOverReason.Cacthok {
f.Our.Player.(*player.Player).Service.Pet.PetAdd(&f.Opp.CurrentPet.Info)
f.Our.Player.SendPackCmd(2409, &info.CatchMonsterOutboundInfo{
CatchTime: uint32(f.Opp.CurrentPet.Info.CatchTime),
PetId: uint32(f.Opp.CurrentPet.ID),
})
}
//f.Reason = info.BattleOverReason.PlayerCaptureSuccess
//f.WinnerId = 0 //捕捉成功不算胜利
if f.callback != nil {
f.callback(&f.FightOverInfo) //先执行回调,再执行返回信息,在回调内修改战斗判断
@@ -246,20 +258,10 @@ func (f *FightC) handleItemAction(a *action.UseItemAction) {
if f.Opp.CanCapture > 0 { //可以捕捉
f.Opp.CurrentPet.CatchRate = f.Opp.CanCapture
ok, res := f.Our.Capture(f.Opp.CurrentPet, a.ItemID, -1)
ok, _ := f.Our.Capture(f.Opp.CurrentPet, a.ItemID, -1)
our := f.Our.Player.(*player.Player)
if ok {
fmt.Println(res)
our.Service.Pet.PetAdd(f.Opp.CurrentPet.Info)
our.SendPack(common.NewTomeeHeader(2409, f.ownerID).Pack(&info.CatchMonsterOutboundInfo{
CatchTime: uint32(f.Opp.CurrentPet.Info.CatchTime),
PetId: uint32(f.Opp.CurrentPet.ID),
}))
//f.Reason = info.BattleOverReason.PlayerCaptureSuccess
//f.WinnerId = 0 //捕捉成功不算胜利
f.Reason = info.BattleOverReason.Cacthok
f.closefight = true
} else {
our.SendPack(common.NewTomeeHeader(2409, f.ownerID).Pack(&info.CatchMonsterOutboundInfo{}))

View File

@@ -43,7 +43,7 @@ func (c *PetBagController) GetSession(ctx context.Context, req *PetGetReq) (res
t := model.GenPetInfo(
req.PetTypeId, req.IndividualValue, req.NatureId, req.AbilityTypeEnum, req.IsShiny, req.Level)
service.NewUserService(uint32(admin.UserId)).Pet.PetAdd(*t)
service.NewUserService(uint32(admin.UserId)).Pet.PetAdd(t)
return
}

View File

@@ -78,6 +78,7 @@ type PetInfo struct {
// 捕捉时间(@UInt long → 若为时间戳用uint32若需时间类型可改为time.Time需配合序列化处理
CatchTime uint32 //`json:"-"` // 显式忽略,不参与序列化
OldCatchTime uint32 `struc:"skip" fieldDesc:"旧捕捉时间" `
// 捕捉地图(@UInt long → uint32
CatchMap uint32 `fieldDesc:"捕捉地图" `
@@ -295,6 +296,7 @@ func calculateExperience(level uint32, baseValue uint32) uint32 {
type PetEffectInfo struct {
ItemID uint32 `struc:"uint32" json:"item_id"` //如果是能量珠,就显示
Idx uint16 `struc:"skip" json:"new_se_idx"`
Type byte `struc:"skip" json:"type"` //pvp pve特性区分,待前端修改实现
Status byte `struc:"byte" json:"status"` //特性为1,能量珠为2
LeftCount byte `struc:"byte" json:"left_count"` //剩余次数
EID uint16 `struc:"uint16" json:"effect_id"` //特效ID

View File

@@ -55,13 +55,13 @@ func (s *PetService) Pet_del(cachetime uint32) {
cool.DBM(s.Model).Where("player_id", s.userid).Where("catch_time", cachetime).Delete()
}
func (s *PetService) PetAdd(y model.PetInfo) {
func (s *PetService) PetAdd(y *model.PetInfo) {
for {
m1 := cool.DBM(s.Model).Where("player_id", s.userid)
var player model.PetEX
player.PlayerID = s.userid
player.Data = y
player.Data = *y
player.CatchTime = y.CatchTime
player.Free = 0

File diff suppressed because it is too large Load Diff