mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-04 15:42:25 +08:00
完善场景物件交互协议
This commit is contained in:
72
common/constant/gadget_type.go
Normal file
72
common/constant/gadget_type.go
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
package constant
|
||||||
|
|
||||||
|
const (
|
||||||
|
GADGET_TYPE_NONE = 0
|
||||||
|
GADGET_TYPE_AVATAR = 1
|
||||||
|
GADGET_TYPE_MONSTER = 2
|
||||||
|
GADGET_TYPE_BULLET = 3
|
||||||
|
GADGET_TYPE_ATTACK_PHYISICAL_UNIT = 4
|
||||||
|
GADGET_TYPE_AOE = 5
|
||||||
|
GADGET_TYPE_CAMERA = 6
|
||||||
|
GADGET_TYPE_ENVIRO_AREA = 7
|
||||||
|
GADGET_TYPE_EQUIP = 8
|
||||||
|
GADGET_TYPE_MONSTER_EQUIP = 9
|
||||||
|
GADGET_TYPE_GRASS = 10
|
||||||
|
GADGET_TYPE_LEVEL = 11
|
||||||
|
GADGET_TYPE_NPC = 12
|
||||||
|
GADGET_TYPE_TRANS_POINT_FIRST = 13
|
||||||
|
GADGET_TYPE_TRANS_POINT_FIRST_GADGET = 14
|
||||||
|
GADGET_TYPE_TRANS_POINT_SECOND = 15
|
||||||
|
GADGET_TYPE_TRANS_POINT_SECOND_GADGET = 16
|
||||||
|
GADGET_TYPE_DROP_ITEM = 17
|
||||||
|
GADGET_TYPE_FIELD = 18
|
||||||
|
GADGET_TYPE_GADGET = 19
|
||||||
|
GADGET_TYPE_WATER = 20
|
||||||
|
GADGET_TYPE_GATHER_POINT = 21
|
||||||
|
GADGET_TYPE_GATHER_OBJECT = 22
|
||||||
|
GADGET_TYPE_AIRFLOW_FIELD = 23
|
||||||
|
GADGET_TYPE_SPEEDUP_FIELD = 24
|
||||||
|
GADGET_TYPE_GEAR = 25
|
||||||
|
GADGET_TYPE_CHEST = 26
|
||||||
|
GADGET_TYPE_ENERGY_BALL = 27
|
||||||
|
GADGET_TYPE_ELEM_CRYSTAL = 28
|
||||||
|
GADGET_TYPE_TIMELINE = 29
|
||||||
|
GADGET_TYPE_WORKTOP = 30
|
||||||
|
GADGET_TYPE_TEAM = 31
|
||||||
|
GADGET_TYPE_PLATFORM = 32
|
||||||
|
GADGET_TYPE_AMBER_WIND = 33
|
||||||
|
GADGET_TYPE_ENV_ANIMAL = 34
|
||||||
|
GADGET_TYPE_SEAL_GADGET = 35
|
||||||
|
GADGET_TYPE_TREE = 36
|
||||||
|
GADGET_TYPE_BUSH = 37
|
||||||
|
GADGET_TYPE_QUEST_GADGET = 38
|
||||||
|
GADGET_TYPE_LIGHTNING = 39
|
||||||
|
GADGET_TYPE_REWARD_POINT = 40
|
||||||
|
GADGET_TYPE_REWARD_STATUE = 41
|
||||||
|
GADGET_TYPE_MP_LEVEL = 42
|
||||||
|
GADGET_TYPE_WIND_SEED = 43
|
||||||
|
GADGET_TYPE_MP_PLAY_REWARD_POINT = 44
|
||||||
|
GADGET_TYPE_VIEW_POINT = 45
|
||||||
|
GADGET_TYPE_REMOTE_AVATAR = 46
|
||||||
|
GADGET_TYPE_GENERAL_REWARD_POINT = 47
|
||||||
|
GADGET_TYPE_PLAY_TEAM = 48
|
||||||
|
GADGET_TYPE_OFFERING_GADGET = 49
|
||||||
|
GADGET_TYPE_EYE_POINT = 50
|
||||||
|
GADGET_TYPE_MIRACLE_RING = 51
|
||||||
|
GADGET_TYPE_FOUNDATION = 52
|
||||||
|
GADGET_TYPE_WIDGET_GADGET = 53
|
||||||
|
GADGET_TYPE_VEHICLE = 54
|
||||||
|
GADGET_TYPE_SUB_EQUIP = 55
|
||||||
|
GADGET_TYPE_FISH_ROD = 56
|
||||||
|
GADGET_TYPE_CUSTOM_TILE = 57
|
||||||
|
GADGET_TYPE_FISH_POOL = 58
|
||||||
|
GADGET_TYPE_CUSTOM_GADGET = 59
|
||||||
|
GADGET_TYPE_BLACK_MUD = 60
|
||||||
|
GADGET_TYPE_ROGUELIKE_OPERATOR_GADGET = 61
|
||||||
|
GADGET_TYPE_NIGHT_CROW_GADGET = 62
|
||||||
|
GADGET_TYPE_PROJECTOR = 63
|
||||||
|
GADGET_TYPE_SCREEN = 64
|
||||||
|
GADGET_TYPE_ECHO_SHELL = 65
|
||||||
|
GADGET_TYPE_UI_INTERACT_GADGET = 66
|
||||||
|
GADGET_TYPE_PLACE_HOLDER = 99
|
||||||
|
)
|
||||||
46
gdconf/gadget_data.go
Normal file
46
gdconf/gadget_data.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package gdconf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"hk4e/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GadgetData 物件配置表
|
||||||
|
type GadgetData struct {
|
||||||
|
GadgetId int32 `csv:"ID"`
|
||||||
|
Type int32 `csv:"类型,omitempty"`
|
||||||
|
DefaultCamp int32 `csv:"默认阵营,omitempty"`
|
||||||
|
CanInteract int32 `csv:"能否交互,omitempty"`
|
||||||
|
Desc string `csv:"描述,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameDataConfig) loadGadgetData() {
|
||||||
|
g.GadgetDataMap = make(map[int32]*GadgetData)
|
||||||
|
fileNameList := []string{
|
||||||
|
"GadgetData_AbilitySpecial.txt",
|
||||||
|
"GadgetData_Affix.txt",
|
||||||
|
"GadgetData_Avatar.txt",
|
||||||
|
"GadgetData_Equip.txt",
|
||||||
|
"GadgetData_FishingRod.txt",
|
||||||
|
"GadgetData_Homeworld.txt",
|
||||||
|
"GadgetData_Level.txt",
|
||||||
|
"GadgetData_Monster.txt",
|
||||||
|
"GadgetData_Quest.txt",
|
||||||
|
"GadgetData_Vehicle.txt",
|
||||||
|
}
|
||||||
|
for _, fileName := range fileNameList {
|
||||||
|
gadgetDataList := make([]*GadgetData, 0)
|
||||||
|
readTable[GadgetData](g.txtPrefix+fileName, &gadgetDataList)
|
||||||
|
for _, gadgetData := range gadgetDataList {
|
||||||
|
g.GadgetDataMap[gadgetData.GadgetId] = gadgetData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.Info("GadgetData count: %v", len(g.GadgetDataMap))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetGadgetDataById(gadgetId int32) *GadgetData {
|
||||||
|
return CONF.GadgetDataMap[gadgetId]
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetGadgetDataMap() map[int32]*GadgetData {
|
||||||
|
return CONF.GadgetDataMap
|
||||||
|
}
|
||||||
@@ -63,6 +63,7 @@ type GameDataConfig struct {
|
|||||||
MonsterDropDataMap map[string]map[int32]*MonsterDropData // 怪物掉落
|
MonsterDropDataMap map[string]map[int32]*MonsterDropData // 怪物掉落
|
||||||
ChestDropDataMap map[string]map[int32]*ChestDropData // 宝箱掉落
|
ChestDropDataMap map[string]map[int32]*ChestDropData // 宝箱掉落
|
||||||
DungeonDataMap map[int32]*DungeonData // 地牢
|
DungeonDataMap map[int32]*DungeonData // 地牢
|
||||||
|
GadgetDataMap map[int32]*GadgetData // 物件
|
||||||
GCGCharDataMap map[int32]*GCGCharData // 七圣召唤角色卡牌
|
GCGCharDataMap map[int32]*GCGCharData // 七圣召唤角色卡牌
|
||||||
GCGSkillDataMap map[int32]*GCGSkillData // 七圣召唤卡牌技能
|
GCGSkillDataMap map[int32]*GCGSkillData // 七圣召唤卡牌技能
|
||||||
GachaDropGroupDataMap map[int32]*GachaDropGroupData // 卡池掉落组 临时的
|
GachaDropGroupDataMap map[int32]*GachaDropGroupData // 卡池掉落组 临时的
|
||||||
@@ -162,6 +163,7 @@ func (g *GameDataConfig) load() {
|
|||||||
g.loadMonsterDropData() // 怪物掉落
|
g.loadMonsterDropData() // 怪物掉落
|
||||||
g.loadChestDropData() // 宝箱掉落
|
g.loadChestDropData() // 宝箱掉落
|
||||||
g.loadDungeonData() // 地牢
|
g.loadDungeonData() // 地牢
|
||||||
|
g.loadGadgetData() // 物件
|
||||||
g.loadGCGCharData() // 七圣召唤角色卡牌
|
g.loadGCGCharData() // 七圣召唤角色卡牌
|
||||||
g.loadGCGSkillData() // 七圣召唤卡牌技能
|
g.loadGCGSkillData() // 七圣召唤卡牌技能
|
||||||
g.loadGachaDropGroupData() // 卡池掉落组 临时的
|
g.loadGachaDropGroupData() // 卡池掉落组 临时的
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ func NewGameManager(dao *dao.Dao, messageQueue *mq.MessageQueue, gsId uint32, gs
|
|||||||
TICK_MANAGER = NewTickManager()
|
TICK_MANAGER = NewTickManager()
|
||||||
COMMAND_MANAGER = NewCommandManager()
|
COMMAND_MANAGER = NewCommandManager()
|
||||||
GCG_MANAGER = NewGCGManager()
|
GCG_MANAGER = NewGCGManager()
|
||||||
RegLuaLibFunc()
|
RegLuaScriptLibFunc()
|
||||||
// 创建本服的Ai世界
|
// 创建本服的Ai世界
|
||||||
uid := AiBaseUid + gsId
|
uid := AiBaseUid + gsId
|
||||||
name := AiName
|
name := AiName
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ type LuaEvt struct {
|
|||||||
targetEntityId uint32
|
targetEntityId uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CallLuaFunc 调用LUA方法
|
||||||
func CallLuaFunc(luaState *lua.LState, luaFuncName string, luaCtx *LuaCtx, luaEvt *LuaEvt) bool {
|
func CallLuaFunc(luaState *lua.LState, luaFuncName string, luaCtx *LuaCtx, luaEvt *LuaEvt) bool {
|
||||||
ctx := luaState.NewTable()
|
ctx := luaState.NewTable()
|
||||||
luaState.SetField(ctx, "uid", lua.LNumber(luaCtx.uid))
|
luaState.SetField(ctx, "uid", lua.LNumber(luaCtx.uid))
|
||||||
@@ -72,7 +73,36 @@ func CallLuaFunc(luaState *lua.LState, luaFuncName string, luaCtx *LuaCtx, luaEv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegLuaLibFunc() {
|
// GetContextPlayer 获取上下文中的玩家对象
|
||||||
|
func GetContextPlayer(ctx *lua.LTable, luaState *lua.LState) *model.Player {
|
||||||
|
uid, ok := luaState.GetField(ctx, "uid").(lua.LNumber)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
player := USER_MANAGER.GetOnlineUser(uint32(uid))
|
||||||
|
return player
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetContextGroup 获取上下文中的场景组对象
|
||||||
|
func GetContextGroup(player *model.Player, ctx *lua.LTable, luaState *lua.LState) *Group {
|
||||||
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||||
|
if world == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
groupId, ok := luaState.GetField(ctx, "groupId").(lua.LNumber)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
scene := world.GetSceneById(player.SceneId)
|
||||||
|
group := scene.GetGroupById(uint32(groupId))
|
||||||
|
if group == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return group
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegLuaScriptLibFunc 注册LUA侧ScriptLib调用的Golang方法
|
||||||
|
func RegLuaScriptLibFunc() {
|
||||||
gdconf.RegScriptLibFunc("GetEntityType", GetEntityType)
|
gdconf.RegScriptLibFunc("GetEntityType", GetEntityType)
|
||||||
gdconf.RegScriptLibFunc("GetQuestState", GetQuestState)
|
gdconf.RegScriptLibFunc("GetQuestState", GetQuestState)
|
||||||
gdconf.RegScriptLibFunc("PrintLog", PrintLog)
|
gdconf.RegScriptLibFunc("PrintLog", PrintLog)
|
||||||
@@ -130,7 +160,7 @@ func PrintContextLog(luaState *lua.LState) int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
logInfo := luaState.ToString(2)
|
logInfo := luaState.ToString(2)
|
||||||
logger.Info("[LUA CTX LOG] %v [UID %v]", logInfo, uid)
|
logger.Info("[LUA CTX LOG] %v [UID: %v]", logInfo, uid)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,33 +280,7 @@ func MarkPlayerAction(luaState *lua.LState) int {
|
|||||||
param1 := luaState.ToInt(2)
|
param1 := luaState.ToInt(2)
|
||||||
param2 := luaState.ToInt(3)
|
param2 := luaState.ToInt(3)
|
||||||
param3 := luaState.ToInt(4)
|
param3 := luaState.ToInt(4)
|
||||||
logger.Debug("[MarkPlayerAction] [%v %v %v] uid: %v", param1, param2, param3, player.PlayerID)
|
logger.Debug("[MarkPlayerAction] [%v %v %v] [UID: %v]", param1, param2, param3, player.PlayerID)
|
||||||
luaState.Push(lua.LNumber(0))
|
luaState.Push(lua.LNumber(0))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetContextPlayer(ctx *lua.LTable, luaState *lua.LState) *model.Player {
|
|
||||||
uid, ok := luaState.GetField(ctx, "uid").(lua.LNumber)
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
player := USER_MANAGER.GetOnlineUser(uint32(uid))
|
|
||||||
return player
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetContextGroup(player *model.Player, ctx *lua.LTable, luaState *lua.LState) *Group {
|
|
||||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
|
||||||
if world == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
groupId, ok := luaState.GetField(ctx, "groupId").(lua.LNumber)
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
scene := world.GetSceneById(player.SceneId)
|
|
||||||
group := scene.GetGroupById(uint32(groupId))
|
|
||||||
if group == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return group
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -286,12 +286,68 @@ func (g *GameManager) PlayerQuitDungeonReq(player *model.Player, payloadMsg pb.M
|
|||||||
|
|
||||||
func (g *GameManager) GadgetInteractReq(player *model.Player, payloadMsg pb.Message) {
|
func (g *GameManager) GadgetInteractReq(player *model.Player, payloadMsg pb.Message) {
|
||||||
req := payloadMsg.(*proto.GadgetInteractReq)
|
req := payloadMsg.(*proto.GadgetInteractReq)
|
||||||
logger.Debug("GadgetInteractReq: %+v, uid: %v", req, player.PlayerID)
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||||
|
if world == nil {
|
||||||
|
logger.Error("get world is nil, worldId: %v, uid: %v", player.WorldId, player.PlayerID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
scene := world.GetSceneById(player.SceneId)
|
||||||
|
entity := scene.GetEntity(req.GadgetEntityId)
|
||||||
|
if entity == nil {
|
||||||
|
logger.Error("get entity is nil, entityId: %v, uid: %v", req.GadgetEntityId, player.PlayerID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if entity.GetEntityType() != constant.ENTITY_TYPE_GADGET {
|
||||||
|
logger.Error("entity type is not gadget, entityType: %v, uid: %v", entity.GetEntityType(), player.PlayerID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
gadgetEntity := entity.GetGadgetEntity()
|
||||||
|
gadgetDataConfig := gdconf.GetGadgetDataById(int32(gadgetEntity.GetGadgetId()))
|
||||||
|
if gadgetDataConfig == nil {
|
||||||
|
logger.Error("get gadget data config is nil, gadgetId: %v, uid: %v", gadgetEntity.GetGadgetId(), player.PlayerID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if gadgetDataConfig.CanInteract == 0 {
|
||||||
|
logger.Error("gadget can not be interact, gadgetId: %v, uid: %v", gadgetEntity.GetGadgetId(), player.PlayerID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
interactType := proto.InteractType_INTERACT_NONE
|
||||||
|
switch gadgetDataConfig.Type {
|
||||||
|
case constant.GADGET_TYPE_GADGET:
|
||||||
|
logger.Debug("==========GADGET_TYPE_GADGET==========")
|
||||||
|
// 掉落物捡起
|
||||||
|
interactType = proto.InteractType_INTERACT_PICK_ITEM
|
||||||
|
g.KillEntity(player, scene, entity.GetId(), proto.PlayerDieType_PLAYER_DIE_NONE)
|
||||||
|
case constant.GADGET_TYPE_ENERGY_BALL:
|
||||||
|
logger.Debug("==========GADGET_TYPE_ENERGY_BALL==========")
|
||||||
|
// 元素能量球吸收
|
||||||
|
interactType = proto.InteractType_INTERACT_PICK_ITEM
|
||||||
|
case constant.GADGET_TYPE_GATHER_OBJECT:
|
||||||
|
logger.Debug("==========GADGET_TYPE_GATHER_OBJECT==========")
|
||||||
|
// 采集物摘取
|
||||||
|
interactType = proto.InteractType_INTERACT_GATHER
|
||||||
|
g.KillEntity(player, scene, entity.GetId(), proto.PlayerDieType_PLAYER_DIE_NONE)
|
||||||
|
case constant.GADGET_TYPE_CHEST:
|
||||||
|
logger.Debug("==========GADGET_TYPE_CHEST==========")
|
||||||
|
// 宝箱开启
|
||||||
|
interactType = proto.InteractType_INTERACT_OPEN_CHEST
|
||||||
|
if req.OpType == proto.InterOpType_INTER_OP_FINISH {
|
||||||
|
// 宝箱交互结束 开启宝箱
|
||||||
|
g.SendMsg(cmd.WorldChestOpenNotify, player.PlayerID, player.ClientSeq, &proto.WorldChestOpenNotify{
|
||||||
|
GroupId: entity.GetGroupId(),
|
||||||
|
SceneId: scene.GetId(),
|
||||||
|
ConfigId: entity.GetConfigId(),
|
||||||
|
})
|
||||||
|
g.ChangeGadgetState(player, scene.GetId(), constant.GADGET_STATE_CHEST_OPENED)
|
||||||
|
g.KillEntity(player, scene, entity.GetId(), proto.PlayerDieType_PLAYER_DIE_NONE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rsp := &proto.GadgetInteractRsp{
|
rsp := &proto.GadgetInteractRsp{
|
||||||
GadgetEntityId: req.GadgetEntityId,
|
GadgetEntityId: req.GadgetEntityId,
|
||||||
InteractType: 0,
|
|
||||||
OpType: req.OpType,
|
|
||||||
GadgetId: req.GadgetId,
|
GadgetId: req.GadgetId,
|
||||||
|
OpType: req.OpType,
|
||||||
|
InteractType: interactType,
|
||||||
}
|
}
|
||||||
g.SendMsg(cmd.GadgetInteractRsp, player.PlayerID, player.ClientSeq, rsp)
|
g.SendMsg(cmd.GadgetInteractRsp, player.PlayerID, player.ClientSeq, rsp)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -429,7 +429,7 @@ func (s *Scene) createConfigEntity(groupId uint32, entityConfig any) uint32 {
|
|||||||
}, uint32(npc.NpcId), 0, 0, 0, uint32(npc.ConfigId), groupId)
|
}, uint32(npc.NpcId), 0, 0, 0, uint32(npc.ConfigId), groupId)
|
||||||
case *gdconf.Gadget:
|
case *gdconf.Gadget:
|
||||||
gadget := entityConfig.(*gdconf.Gadget)
|
gadget := entityConfig.(*gdconf.Gadget)
|
||||||
// 70500000并不是实际的装置id 根据节点类型对应采集物配置表
|
// 70500000并不是实际的物件id 根据节点类型对应采集物配置表
|
||||||
if gadget.PointType != 0 && gadget.GadgetId == 70500000 {
|
if gadget.PointType != 0 && gadget.GadgetId == 70500000 {
|
||||||
gatherDataConfig := gdconf.GetGatherDataByPointType(gadget.PointType)
|
gatherDataConfig := gdconf.GetGatherDataByPointType(gadget.PointType)
|
||||||
if gatherDataConfig == nil {
|
if gatherDataConfig == nil {
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ func (c *CmdProtoMap) registerAllMessage() {
|
|||||||
c.regMsg(GadgetInteractReq, func() any { return new(proto.GadgetInteractReq) }) // 物件交互请求
|
c.regMsg(GadgetInteractReq, func() any { return new(proto.GadgetInteractReq) }) // 物件交互请求
|
||||||
c.regMsg(GadgetInteractRsp, func() any { return new(proto.GadgetInteractRsp) }) // 物件交互响应
|
c.regMsg(GadgetInteractRsp, func() any { return new(proto.GadgetInteractRsp) }) // 物件交互响应
|
||||||
c.regMsg(GadgetStateNotify, func() any { return new(proto.GadgetStateNotify) }) // 物件状态更新通知
|
c.regMsg(GadgetStateNotify, func() any { return new(proto.GadgetStateNotify) }) // 物件状态更新通知
|
||||||
|
c.regMsg(WorldChestOpenNotify, func() any { return new(proto.WorldChestOpenNotify) }) // 宝箱开启通知
|
||||||
|
|
||||||
// 战斗与同步
|
// 战斗与同步
|
||||||
c.regMsg(AvatarFightPropNotify, func() any { return new(proto.AvatarFightPropNotify) }) // 角色战斗属性通知
|
c.regMsg(AvatarFightPropNotify, func() any { return new(proto.AvatarFightPropNotify) }) // 角色战斗属性通知
|
||||||
|
|||||||
Reference in New Issue
Block a user