From 804e0dfc1aedb004e20b2e9c2ab213b6c9245b30 Mon Sep 17 00:00:00 2001 From: UnKownOwO <80520429@qq.com> Date: Tue, 14 Feb 2023 21:27:27 +0800 Subject: [PATCH] =?UTF-8?q?=E6=97=B6=E8=A3=85=E3=80=81=E9=A3=8E=E4=B9=8B?= =?UTF-8?q?=E7=BF=BC=E8=AF=BB=E8=A1=A8=EF=BC=8Cgive=E5=91=BD=E4=BB=A4?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20=E4=BF=AE=E5=A4=8D=E4=BA=86=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E6=9B=BF=E6=8D=A2=E5=9C=A3=E9=81=97=E7=89=A9=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gdconf/avatar_costume_data.go | 52 +++++++++++++++++ gdconf/avatar_flycloak_data.go | 48 +++++++++++++++ gdconf/game_data_config.go | 4 ++ gdconf/table_struct_mapping.json | 30 ++++++++++ gs/game/command_controller.go | 87 ++++++++++++++++++---------- gs/game/command_gm.go | 40 +++++++++++-- gs/game/player_avatar.go | 75 ------------------------ gs/game/player_costume.go | 79 +++++++++++++++++++++++++ gs/game/player_equip.go | 46 +++++++-------- gs/game/player_flycloak.go | 78 +++++++++++++++++++++++++ gs/game/player_login.go | 24 -------- protocol/cmd/cmd_id_proto_obj_map.go | 18 ++++-- 12 files changed, 415 insertions(+), 166 deletions(-) create mode 100644 gdconf/avatar_costume_data.go create mode 100644 gdconf/avatar_flycloak_data.go create mode 100644 gs/game/player_costume.go create mode 100644 gs/game/player_flycloak.go diff --git a/gdconf/avatar_costume_data.go b/gdconf/avatar_costume_data.go new file mode 100644 index 00000000..6b558495 --- /dev/null +++ b/gdconf/avatar_costume_data.go @@ -0,0 +1,52 @@ +package gdconf + +import ( + "fmt" + + "hk4e/pkg/logger" + + "github.com/jszwec/csvutil" +) + +// AvatarCostumeData 角色时装配置表 +type AvatarCostumeData struct { + CostumeID int32 `csv:"CostumeID"` // 时装ID + ItemID int32 `csv:"ItemID,omitempty"` // 道具ID +} + +func (g *GameDataConfig) loadAvatarCostumeData() { + g.AvatarCostumeDataMap = make(map[int32]*AvatarCostumeData) + data := g.readCsvFileData("AvatarCostumeData.csv") + var avatarCostumeDataList []*AvatarCostumeData + err := csvutil.Unmarshal(data, &avatarCostumeDataList) + if err != nil { + info := fmt.Sprintf("parse file error: %v", err) + panic(info) + } + for _, avatarCostumeData := range avatarCostumeDataList { + // 屏蔽默认时装 + if avatarCostumeData.ItemID == 0 { + continue + } + // list -> map + g.AvatarCostumeDataMap[avatarCostumeData.CostumeID] = avatarCostumeData + } + logger.Info("AvatarCostumeData count: %v", len(g.AvatarCostumeDataMap)) +} + +func GetAvatarCostumeDataById(costumeId int32) *AvatarCostumeData { + return CONF.AvatarCostumeDataMap[costumeId] +} + +func GetAvatarCostumeDataByItemId(itemId int32) *AvatarCostumeData { + for _, data := range CONF.AvatarCostumeDataMap { + if data.ItemID == itemId { + return data + } + } + return nil +} + +func GetAvatarCostumeDataMap() map[int32]*AvatarCostumeData { + return CONF.AvatarCostumeDataMap +} diff --git a/gdconf/avatar_flycloak_data.go b/gdconf/avatar_flycloak_data.go new file mode 100644 index 00000000..89a6cdee --- /dev/null +++ b/gdconf/avatar_flycloak_data.go @@ -0,0 +1,48 @@ +package gdconf + +import ( + "fmt" + + "hk4e/pkg/logger" + + "github.com/jszwec/csvutil" +) + +// AvatarFlycloakData 角色风之翼配置表 +type AvatarFlycloakData struct { + FlycloakID int32 `csv:"FlycloakID"` // 风之翼ID + ItemID int32 `csv:"ItemID,omitempty"` // 道具ID +} + +func (g *GameDataConfig) loadAvatarFlycloakData() { + g.AvatarFlycloakDataMap = make(map[int32]*AvatarFlycloakData) + data := g.readCsvFileData("AvatarFlycloakData.csv") + var avatarFlycloakDataList []*AvatarFlycloakData + err := csvutil.Unmarshal(data, &avatarFlycloakDataList) + if err != nil { + info := fmt.Sprintf("parse file error: %v", err) + panic(info) + } + for _, avatarFlycloakData := range avatarFlycloakDataList { + // list -> map + g.AvatarFlycloakDataMap[avatarFlycloakData.FlycloakID] = avatarFlycloakData + } + logger.Info("AvatarFlycloakData count: %v", len(g.AvatarFlycloakDataMap)) +} + +func GetAvatarFlycloakDataById(flycloakId int32) *AvatarFlycloakData { + return CONF.AvatarFlycloakDataMap[flycloakId] +} + +func GetAvatarFlycloakDataByItemId(itemId int32) *AvatarFlycloakData { + for _, data := range CONF.AvatarFlycloakDataMap { + if data.ItemID == itemId { + return data + } + } + return nil +} + +func GetAvatarFlycloakDataMap() map[int32]*AvatarFlycloakData { + return CONF.AvatarFlycloakDataMap +} diff --git a/gdconf/game_data_config.go b/gdconf/game_data_config.go index 2aa63fbd..a49e2d1b 100644 --- a/gdconf/game_data_config.go +++ b/gdconf/game_data_config.go @@ -46,6 +46,8 @@ type GameDataConfig struct { WeaponLevelDataMap map[int32]*WeaponLevelData // 武器等级 WeaponPromoteDataMap map[int32]map[int32]*WeaponPromoteData // 角色突破 RewardDataMap map[int32]*RewardData // 奖励 + AvatarCostumeDataMap map[int32]*AvatarCostumeData // 角色时装 + AvatarFlycloakDataMap map[int32]*AvatarFlycloakData // 角色风之翼 } func InitGameDataConfig() { @@ -125,6 +127,8 @@ func (g *GameDataConfig) load() { g.loadWeaponLevelData() // 武器等级 g.loadWeaponPromoteData() // 武器突破 g.loadRewardData() // 奖励 + g.loadAvatarCostumeData() // 角色时装 + g.loadAvatarFlycloakData() // 角色风之翼 } func (g *GameDataConfig) readCsvFileData(fileName string) []byte { diff --git a/gdconf/table_struct_mapping.json b/gdconf/table_struct_mapping.json index 30438270..ef3c5c06 100644 --- a/gdconf/table_struct_mapping.json +++ b/gdconf/table_struct_mapping.json @@ -923,5 +923,35 @@ "origin_name": "Reward道具8数量" } ] + }, + { + "table_name": "AvatarCostumeData", + "field_list": [ + { + "field_name": "CostumeID", + "field_type": "int32", + "origin_name": "时装ID" + }, + { + "field_name": "ItemID", + "field_type": "int32", + "origin_name": "道具ID" + } + ] + }, + { + "table_name": "AvatarFlycloakData", + "field_list": [ + { + "field_name": "FlycloakID", + "field_type": "int32", + "origin_name": "风之翼ID" + }, + { + "field_name": "ItemID", + "field_type": "int32", + "origin_name": "道具ID" + } + ] } ] diff --git a/gs/game/command_controller.go b/gs/game/command_controller.go index 37595536..ab6fbb95 100644 --- a/gs/game/command_controller.go +++ b/gs/game/command_controller.go @@ -1,6 +1,7 @@ package game import ( + "hk4e/gdconf" "strconv" "strings" @@ -11,8 +12,8 @@ import ( func (c *CommandManager) HelpCommand(cmd *CommandMessage) { c.SendMessage(cmd.Executor, "========== 帮助 / Help ==========\n\n"+ - "传送:/tp [-u ] [-s <场景ID>] -x <坐标X> -y <坐标Y> -z <坐标Z>\n\n"+ - "给予:/give [-u ] [-c <数量>] -i <物品ID|武器ID|角色ID/item/weapon/avatar/all>\n", + "传送:tp [--u ] [--s <场景ID>] {--t <目标UID> | --x <坐标X> | --y <坐标Y> | --z <坐标Z>}\n\n"+ + "给予:give [--u ] [--c <数量>] --i \n", ) } @@ -76,7 +77,7 @@ func (c *CommandManager) TeleportCommand(cmd *CommandMessage) { sceneId = player.SceneId } } else { - c.SendMessage(cmd.Executor, "玩家不在线,UID: %v。", v) + c.SendMessage(cmd.Executor, "玩家不在线,UID:%v。", v) return } } @@ -94,7 +95,7 @@ func (c *CommandManager) TeleportCommand(cmd *CommandMessage) { // 目标玩家属于非本地玩家 if !USER_MANAGER.GetRemoteUserOnlineState(uint32(uid)) { // 全服不存在该在线玩家 - c.SendMessage(cmd.Executor, "目标玩家不在线,UID: %v。", v) + c.SendMessage(cmd.Executor, "目标玩家不在线,UID:%v。", v) return } } @@ -182,7 +183,7 @@ func (c *CommandManager) TeleportCommand(cmd *CommandMessage) { } // GiveCommand 给予物品命令 -// give [--u ] [--c ] --i <物品ID/item/weapon/reliquary/avatar/all> +// give [--u ] [--c ] --i func (c *CommandManager) GiveCommand(cmd *CommandMessage) { // 执行者如果不是玩家则必须输入UID player, ok := cmd.Executor.(*model.Player) @@ -193,13 +194,13 @@ func (c *CommandManager) GiveCommand(cmd *CommandMessage) { // 判断是否填写必备参数 if cmd.Args["i"] == "" { - c.SendMessage(cmd.Executor, "参数不足,正确用法:%v [--u ] [--c <数量>] --i <物品ID / item / weapon / reliquary / avatar / all>。", cmd.Name) + c.SendMessage(cmd.Executor, "参数不足,正确用法:%v [--u ] [--c <数量>] --i 。", cmd.Name) return } // 初始值 - count := uint32(1) // 数量 - itemId := uint32(0) // 物品Id + count := uint32(1) // 数量 + id := uint32(0) // id // 给予物品的模式 // once 单个 / all 所有物品 // item 物品 / weapon 武器 @@ -217,7 +218,7 @@ func (c *CommandManager) GiveCommand(cmd *CommandMessage) { if user := USER_MANAGER.GetOnlineUser(uint32(uid)); user != nil { player = user } else { - c.SendMessage(cmd.Executor, "目标玩家不在线,UID: %v。", v) + c.SendMessage(cmd.Executor, "目标玩家不在线,UID:%v。", v) return } } @@ -228,16 +229,16 @@ func (c *CommandManager) GiveCommand(cmd *CommandMessage) { } case "i": switch v { - case "all", "item", "avatar", "weapon", "reliquary": + case "item", "物品", "weapon", "武器", "reliquary", "圣遗物", "avatar", "角色", "costume", "时装", "flycloak", "风之翼", "all", "全部": // 将模式修改为参数的值 mode = v default: - var id uint64 - if id, err = strconv.ParseUint(v, 10, 32); err != nil { - c.SendMessage(cmd.Executor, "参数 --%v 有误,允许内容: <物品ID / item / weapon / reliquary / avatar / all>。", k) + var tempId uint64 + if tempId, err = strconv.ParseUint(v, 10, 32); err != nil { + c.SendMessage(cmd.Executor, "参数 --%v 有误,允许内容:。", k) return } - itemId = uint32(id) + id = uint32(tempId) } default: c.SendMessage(cmd.Executor, "参数 --%v 冗余。", k) @@ -254,58 +255,80 @@ func (c *CommandManager) GiveCommand(cmd *CommandMessage) { switch mode { case "once": // 判断是否为物品 - _, ok := GAME_MANAGER.GetAllItemDataConfig()[int32(itemId)] + _, ok := GAME_MANAGER.GetAllItemDataConfig()[int32(id)] if ok { // 给予玩家物品 - c.GMAddUserItem(player.PlayerID, itemId, count) - c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 物品ID: %v 数量: %v。", player.PlayerID, itemId, count) + c.GMAddUserItem(player.PlayerID, id, count) + c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 物品ID:%v 数量:%v。", player.PlayerID, id, count) return } // 判断是否为武器 - _, ok = GAME_MANAGER.GetAllWeaponDataConfig()[int32(itemId)] + _, ok = GAME_MANAGER.GetAllWeaponDataConfig()[int32(id)] if ok { // 给予玩家武器 - c.GMAddUserWeapon(player.PlayerID, itemId, count) - c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 武器ID:%v 数量:%v。", player.PlayerID, itemId, count) + c.GMAddUserWeapon(player.PlayerID, id, count) + c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 武器 物品ID:%v 数量:%v。", player.PlayerID, id, count) return } // 判断是否为圣遗物 - _, ok = GAME_MANAGER.GetAllReliquaryDataConfig()[int32(itemId)] + _, ok = GAME_MANAGER.GetAllReliquaryDataConfig()[int32(id)] if ok { // 给予玩家圣遗物 - c.GMAddUserReliquary(player.PlayerID, itemId, count) - c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 圣遗物ID:%v 数量:%v。", player.PlayerID, itemId, count) + c.GMAddUserReliquary(player.PlayerID, id, count) + c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 圣遗物 物品ID:%v 数量:%v。", player.PlayerID, id, count) return } // 判断是否为角色 - _, ok = GAME_MANAGER.GetAllAvatarDataConfig()[int32(itemId)] + _, ok = GAME_MANAGER.GetAllAvatarDataConfig()[int32(id)] if ok { // 给予玩家角色 - c.GMAddUserAvatar(player.PlayerID, itemId) - c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 角色ID:%v 数量:%v。", player.PlayerID, itemId, count) + c.GMAddUserAvatar(player.PlayerID, id) + c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 角色ID:%v 数量:%v。", player.PlayerID, id, count) + return + } + // 判断是否为时装 + if gdconf.GetAvatarCostumeDataById(int32(id)) != nil { + // 给予玩家角色 + c.GMAddUserCostume(player.PlayerID, id) + c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 时装ID:%v 数量:%v。", player.PlayerID, id, count) + return + } + // 判断是否为风之翼 + if gdconf.GetAvatarFlycloakDataById(int32(id)) != nil { + // 给予玩家角色 + c.GMAddUserFlycloak(player.PlayerID, id) + c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 风之翼ID:%v 数量:%v。", player.PlayerID, id, count) return } // 都执行到这里那肯定是都不匹配 - c.SendMessage(cmd.Executor, "物品ID:%v 不存在。", itemId) - case "item": + c.SendMessage(cmd.Executor, "ID:%v 不存在。", id) + case "item", "物品": // 给予玩家所有物品 c.GMAddUserAllItem(player.PlayerID, count) c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 所有物品 数量:%v。", player.PlayerID, count) - case "weapon": + case "weapon", "武器": // 给予玩家所有武器 c.GMAddUserAllWeapon(player.PlayerID, count) c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 所有武器 数量:%v。", player.PlayerID, count) - case "reliquary": + case "reliquary", "圣遗物": // 给予玩家所有圣遗物 c.GMAddUserAllReliquary(player.PlayerID, count) c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 所有圣遗物 数量:%v。", player.PlayerID, count) - case "avatar": + case "avatar", "角色": // 给予玩家所有角色 c.GMAddUserAllAvatar(player.PlayerID) c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 所有角色。", player.PlayerID) - case "all": + case "costume", "时装": + // 给予玩家所有角色 + c.GMAddUserAllCostume(player.PlayerID) + c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 所有时装。", player.PlayerID) + case "flycloak", "风之翼": + // 给予玩家所有角色 + c.GMAddUserAllFlycloak(player.PlayerID) + c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 所有风之翼。", player.PlayerID) + case "all", "全部": // 给予玩家所有内容 c.GMAddUserAllEvery(player.PlayerID, count, count) // TODO 武器额外获取数量 c.SendMessage(cmd.Executor, "已给予玩家 UID:%v, 所有内容。", player.PlayerID) diff --git a/gs/game/command_gm.go b/gs/game/command_gm.go index 825ea3c9..1f300c0b 100644 --- a/gs/game/command_gm.go +++ b/gs/game/command_gm.go @@ -2,6 +2,7 @@ package game import ( "hk4e/common/constant" + "hk4e/gdconf" "hk4e/gs/model" "hk4e/pkg/logger" ) @@ -43,24 +44,31 @@ func (c *CommandManager) GMAddUserWeapon(userId, itemId, itemCount uint32) { func (c *CommandManager) GMAddUserReliquary(userId, itemId, itemCount uint32) { // 圣遗物数量 for i := uint32(0); i < itemCount; i++ { - // 给予武器 + // 给予圣遗物 GAME_MANAGER.AddUserReliquary(userId, itemId) } } // GMAddUserAvatar 给予玩家角色 func (c *CommandManager) GMAddUserAvatar(userId, avatarId uint32) { - player := USER_MANAGER.GetOnlineUser(userId) - if player == nil { - logger.Error("player is nil, uid: %v", userId) - return - } // 添加角色 GAME_MANAGER.AddUserAvatar(userId, avatarId) // TODO 设置角色 等以后做到角色升级之类的再说 // avatar := player.AvatarMap[avatarId] } +// GMAddUserCostume 给予玩家时装 +func (c *CommandManager) GMAddUserCostume(userId, costumeId uint32) { + // 添加时装 + GAME_MANAGER.AddUserCostume(userId, costumeId) +} + +// GMAddUserFlycloak 给予玩家风之翼 +func (c *CommandManager) GMAddUserFlycloak(userId, flycloakId uint32) { + // 添加风之翼 + GAME_MANAGER.AddUserFlycloak(userId, flycloakId) +} + // GMAddUserAllItem 给予玩家所有物品 func (c *CommandManager) GMAddUserAllItem(userId, itemCount uint32) { // 猜猜这样做为啥不行? @@ -98,12 +106,32 @@ func (c *CommandManager) GMAddUserAllAvatar(userId uint32) { } } +// GMAddUserAllCostume 给予玩家所有时装 +func (c *CommandManager) GMAddUserAllCostume(userId uint32) { + for costumeId := range gdconf.GetAvatarCostumeDataMap() { + c.GMAddUserCostume(userId, uint32(costumeId)) + } +} + +// GMAddUserAllFlycloak 给予玩家所有风之翼 +func (c *CommandManager) GMAddUserAllFlycloak(userId uint32) { + for flycloakId := range gdconf.GetAvatarFlycloakDataMap() { + c.GMAddUserFlycloak(userId, uint32(flycloakId)) + } +} + // GMAddUserAllEvery 给予玩家所有内容 func (c *CommandManager) GMAddUserAllEvery(userId uint32, itemCount uint32, weaponCount uint32) { // 给予玩家所有物品 c.GMAddUserAllItem(userId, itemCount) // 给予玩家所有武器 c.GMAddUserAllWeapon(userId, itemCount) + // 给予玩家所有圣遗物 + c.GMAddUserAllReliquary(userId, itemCount) // 给予玩家所有角色 c.GMAddUserAllAvatar(userId) + // 给予玩家所有时装 + c.GMAddUserAllCostume(userId) + // 给予玩家所有风之翼 + c.GMAddUserAllFlycloak(userId) } diff --git a/gs/game/player_avatar.go b/gs/game/player_avatar.go index 344c4a23..c087d3d0 100644 --- a/gs/game/player_avatar.go +++ b/gs/game/player_avatar.go @@ -359,81 +359,6 @@ func (g *GameManager) PacketAvatarPropNotify(avatar *model.Avatar) *proto.Avatar return avatarPropNotify } -func (g *GameManager) AvatarChangeCostumeReq(player *model.Player, payloadMsg pb.Message) { - logger.Debug("user change avatar costume, uid: %v", player.PlayerID) - req := payloadMsg.(*proto.AvatarChangeCostumeReq) - avatarGuid := req.AvatarGuid - costumeId := req.CostumeId - - exist := false - for _, v := range player.CostumeList { - if v == costumeId { - exist = true - } - } - if costumeId == 0 { - exist = true - } - if !exist { - return - } - - avatar := player.GameObjectGuidMap[avatarGuid].(*model.Avatar) - avatar.Costume = req.CostumeId - - world := WORLD_MANAGER.GetWorldByID(player.WorldId) - scene := world.GetSceneById(player.SceneId) - - avatarChangeCostumeNotify := new(proto.AvatarChangeCostumeNotify) - avatarChangeCostumeNotify.EntityInfo = g.PacketSceneEntityInfoAvatar(scene, player, avatar.AvatarId) - for _, scenePlayer := range scene.GetAllPlayer() { - g.SendMsg(cmd.AvatarChangeCostumeNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, avatarChangeCostumeNotify) - } - - avatarChangeCostumeRsp := &proto.AvatarChangeCostumeRsp{ - AvatarGuid: req.AvatarGuid, - CostumeId: req.CostumeId, - } - g.SendMsg(cmd.AvatarChangeCostumeRsp, player.PlayerID, player.ClientSeq, avatarChangeCostumeRsp) -} - -func (g *GameManager) AvatarWearFlycloakReq(player *model.Player, payloadMsg pb.Message) { - logger.Debug("user change avatar fly cloak, uid: %v", player.PlayerID) - req := payloadMsg.(*proto.AvatarWearFlycloakReq) - avatarGuid := req.AvatarGuid - flycloakId := req.FlycloakId - - exist := false - for _, v := range player.FlyCloakList { - if v == flycloakId { - exist = true - } - } - if !exist { - return - } - - avatar := player.GameObjectGuidMap[avatarGuid].(*model.Avatar) - avatar.FlyCloak = req.FlycloakId - - world := WORLD_MANAGER.GetWorldByID(player.WorldId) - scene := world.GetSceneById(player.SceneId) - - avatarFlycloakChangeNotify := &proto.AvatarFlycloakChangeNotify{ - AvatarGuid: avatarGuid, - FlycloakId: flycloakId, - } - for _, scenePlayer := range scene.GetAllPlayer() { - g.SendMsg(cmd.AvatarFlycloakChangeNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, avatarFlycloakChangeNotify) - } - - avatarWearFlycloakRsp := &proto.AvatarWearFlycloakRsp{ - AvatarGuid: req.AvatarGuid, - FlycloakId: req.FlycloakId, - } - g.SendMsg(cmd.AvatarWearFlycloakRsp, player.PlayerID, player.ClientSeq, avatarWearFlycloakRsp) -} - func (g *GameManager) UpdateUserAvatarFightProp(userId uint32, avatarId uint32) { player := USER_MANAGER.GetOnlineUser(userId) if player == nil { diff --git a/gs/game/player_costume.go b/gs/game/player_costume.go new file mode 100644 index 00000000..c80c44df --- /dev/null +++ b/gs/game/player_costume.go @@ -0,0 +1,79 @@ +package game + +import ( + "hk4e/gs/model" + "hk4e/pkg/logger" + "hk4e/protocol/cmd" + "hk4e/protocol/proto" + + pb "google.golang.org/protobuf/proto" +) + +// AddUserCostume 给予玩家时装 +func (g *GameManager) AddUserCostume(userId uint32, costumeId uint32) { + player := USER_MANAGER.GetOnlineUser(userId) + if player == nil { + logger.Error("player is nil, uid: %v", userId) + return + } + // 验证玩家是否已拥有该时装 + for _, costume := range player.CostumeList { + if costume == costumeId { + logger.Error("player has costume, costumeId: %v", costumeId) + return + } + } + player.CostumeList = append(player.CostumeList, costumeId) + + avatarGainCostumeNotify := &proto.AvatarGainCostumeNotify{ + CostumeId: costumeId, + } + g.SendMsg(cmd.AvatarGainCostumeNotify, userId, player.ClientSeq, avatarGainCostumeNotify) +} + +// AvatarChangeCostumeReq 角色更换时装请求 +func (g *GameManager) AvatarChangeCostumeReq(player *model.Player, payloadMsg pb.Message) { + logger.Debug("user change avatar costume, uid: %v", player.PlayerID) + req := payloadMsg.(*proto.AvatarChangeCostumeReq) + + // 确保角色存在 + avatar, ok := player.GameObjectGuidMap[req.AvatarGuid].(*model.Avatar) + if !ok { + logger.Error("avatar error, avatarGuid: %v", req.AvatarGuid) + g.SendError(cmd.AvatarChangeCostumeRsp, player, &proto.AvatarChangeCostumeRsp{}, proto.Retcode_RET_COSTUME_AVATAR_ERROR) + return + } + + exist := false + for _, v := range player.CostumeList { + if v == req.CostumeId { + exist = true + } + } + if req.CostumeId == 0 { + exist = true + } + if !exist { + logger.Error("costume not exist, costumeId: %v", req.CostumeId) + g.SendError(cmd.AvatarChangeCostumeRsp, player, &proto.AvatarChangeCostumeRsp{}, proto.Retcode_RET_NOT_HAS_COSTUME) + return + } + + // 设置角色时装 + avatar.Costume = req.CostumeId + + world := WORLD_MANAGER.GetWorldByID(player.WorldId) + scene := world.GetSceneById(player.SceneId) + + avatarChangeCostumeNotify := new(proto.AvatarChangeCostumeNotify) + avatarChangeCostumeNotify.EntityInfo = g.PacketSceneEntityInfoAvatar(scene, player, avatar.AvatarId) + for _, scenePlayer := range scene.GetAllPlayer() { + g.SendMsg(cmd.AvatarChangeCostumeNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, avatarChangeCostumeNotify) + } + + avatarChangeCostumeRsp := &proto.AvatarChangeCostumeRsp{ + AvatarGuid: req.AvatarGuid, + CostumeId: req.CostumeId, + } + g.SendMsg(cmd.AvatarChangeCostumeRsp, player.PlayerID, player.ClientSeq, avatarChangeCostumeRsp) +} diff --git a/gs/game/player_equip.go b/gs/game/player_equip.go index 62d2ad33..32ff21c0 100644 --- a/gs/game/player_equip.go +++ b/gs/game/player_equip.go @@ -149,30 +149,30 @@ func (g *GameManager) WearUserAvatarReliquary(userId uint32, avatarId uint32, re return } // 角色已装备的圣遗物 - avatarCurReliquary, ok := avatar.EquipReliquaryMap[uint8(reliquaryConfig.ReliquaryType)] - if ok { - if reliquary.AvatarId != 0 { - // 圣遗物在别的角色身上 - targetReliquaryAvatar, ok := player.AvatarMap[reliquary.AvatarId] - if !ok { - logger.Error("avatar error, avatarId: %v", reliquary.AvatarId) - return - } + avatarCurReliquary := avatar.EquipReliquaryMap[uint8(reliquaryConfig.ReliquaryType)] + if reliquary.AvatarId != 0 { + // 圣遗物在别的角色身上 + targetReliquaryAvatar, ok := player.AvatarMap[reliquary.AvatarId] + if !ok { + logger.Error("avatar error, avatarId: %v", reliquary.AvatarId) + return + } + // 确保目前角色已装备圣遗物 + if avatarCurReliquary != nil { // 卸下角色已装备的圣遗物 player.TakeOffReliquary(avatarId, avatarCurReliquary.ReliquaryId) - - // 将目标圣遗物的角色卸下圣遗物 - player.TakeOffReliquary(targetReliquaryAvatar.AvatarId, reliquary.ReliquaryId) // 将目标圣遗物的角色装备当前角色曾装备的圣遗物 player.WearReliquary(targetReliquaryAvatar.AvatarId, avatarCurReliquary.ReliquaryId) - - // 更新目标圣遗物角色的装备 - avatarEquipChangeNotify := g.PacketAvatarEquipChangeNotifyByReliquary(targetReliquaryAvatar, avatarCurReliquary) - g.SendMsg(cmd.AvatarEquipChangeNotify, userId, player.ClientSeq, avatarEquipChangeNotify) - } else { - // 角色当前有圣遗物则卸下 - player.TakeOffReliquary(avatarId, avatarCurReliquary.ReliquaryId) } + // 将目标圣遗物的角色卸下圣遗物 + player.TakeOffReliquary(targetReliquaryAvatar.AvatarId, reliquary.ReliquaryId) + + // 更新目标圣遗物角色的装备 + avatarEquipChangeNotify := g.PacketAvatarEquipChangeNotifyByReliquary(targetReliquaryAvatar, targetReliquaryAvatar.EquipReliquaryMap[uint8(reliquaryConfig.ReliquaryType)]) + g.SendMsg(cmd.AvatarEquipChangeNotify, userId, player.ClientSeq, avatarEquipChangeNotify) + } else { + // 角色当前有圣遗物则卸下 + player.TakeOffReliquary(avatarId, avatarCurReliquary.ReliquaryId) } // 角色装备圣遗物 player.WearReliquary(avatarId, reliquaryId) @@ -206,6 +206,7 @@ func (g *GameManager) WearUserAvatarWeapon(userId uint32, avatarId uint32, weapo } // 角色已装备的武器 avatarCurWeapon := avatar.EquipWeapon + // 武器需要确保双方都装备才能替换不然会出问题 if avatarCurWeapon != nil { if weapon.AvatarId != 0 { // 武器在别的角色身上 @@ -216,11 +217,10 @@ func (g *GameManager) WearUserAvatarWeapon(userId uint32, avatarId uint32, weapo } // 卸下角色已装备的武器 player.TakeOffWeapon(avatarId, avatarCurWeapon.WeaponId) - - // 将目标武器的角色卸下武器 - player.TakeOffWeapon(targetWeaponAvatar.AvatarId, weapon.WeaponId) // 将目标武器的角色装备当前角色曾装备的武器 player.WearWeapon(targetWeaponAvatar.AvatarId, avatarCurWeapon.WeaponId) + // 将目标武器的角色卸下武器 + player.TakeOffWeapon(targetWeaponAvatar.AvatarId, weapon.WeaponId) // 更新目标武器角色的装备 weaponEntityId := uint32(0) @@ -228,7 +228,7 @@ func (g *GameManager) WearUserAvatarWeapon(userId uint32, avatarId uint32, weapo if worldAvatar != nil { weaponEntityId = worldAvatar.GetWeaponEntityId() } - avatarEquipChangeNotify := g.PacketAvatarEquipChangeNotifyByWeapon(targetWeaponAvatar, avatarCurWeapon, weaponEntityId) + avatarEquipChangeNotify := g.PacketAvatarEquipChangeNotifyByWeapon(targetWeaponAvatar, targetWeaponAvatar.EquipWeapon, weaponEntityId) g.SendMsg(cmd.AvatarEquipChangeNotify, userId, player.ClientSeq, avatarEquipChangeNotify) } else { // 角色当前有武器则卸下 diff --git a/gs/game/player_flycloak.go b/gs/game/player_flycloak.go new file mode 100644 index 00000000..08d16719 --- /dev/null +++ b/gs/game/player_flycloak.go @@ -0,0 +1,78 @@ +package game + +import ( + "hk4e/gs/model" + "hk4e/pkg/logger" + "hk4e/protocol/cmd" + "hk4e/protocol/proto" + + pb "google.golang.org/protobuf/proto" +) + +// AddUserFlycloak 给予玩家风之翼 +func (g *GameManager) AddUserFlycloak(userId uint32, flyCloakId uint32) { + player := USER_MANAGER.GetOnlineUser(userId) + if player == nil { + logger.Error("player is nil, uid: %v", userId) + return + } + // 验证玩家是否已拥有该风之翼 + for _, flycloak := range player.FlyCloakList { + if flycloak == flyCloakId { + logger.Error("player has flycloak, flycloakId: %v", flyCloakId) + return + } + } + player.FlyCloakList = append(player.FlyCloakList, flyCloakId) + + avatarGainFlycloakNotify := &proto.AvatarGainFlycloakNotify{ + FlycloakId: flyCloakId, + } + g.SendMsg(cmd.AvatarGainFlycloakNotify, userId, player.ClientSeq, avatarGainFlycloakNotify) +} + +// AvatarWearFlycloakReq 角色装备风之翼请求 +func (g *GameManager) AvatarWearFlycloakReq(player *model.Player, payloadMsg pb.Message) { + logger.Debug("user change avatar fly cloak, uid: %v", player.PlayerID) + req := payloadMsg.(*proto.AvatarWearFlycloakReq) + + // 确保角色存在 + avatar, ok := player.GameObjectGuidMap[req.AvatarGuid].(*model.Avatar) + if !ok { + logger.Error("avatar error, avatarGuid: %v", req.AvatarGuid) + g.SendError(cmd.AvatarWearFlycloakRsp, player, &proto.AvatarWearFlycloakRsp{}, proto.Retcode_RET_CAN_NOT_FIND_AVATAR) + return + } + + exist := false + for _, v := range player.FlyCloakList { + if v == req.FlycloakId { + exist = true + } + } + if !exist { + logger.Error("flycloak not exist, flycloakId: %v", req.FlycloakId) + g.SendError(cmd.AvatarWearFlycloakRsp, player, &proto.AvatarWearFlycloakRsp{}, proto.Retcode_RET_NOT_HAS_FLYCLOAK) + return + } + + // 设置角色风之翼 + avatar.FlyCloak = req.FlycloakId + + world := WORLD_MANAGER.GetWorldByID(player.WorldId) + scene := world.GetSceneById(player.SceneId) + + avatarFlycloakChangeNotify := &proto.AvatarFlycloakChangeNotify{ + AvatarGuid: req.AvatarGuid, + FlycloakId: req.FlycloakId, + } + for _, scenePlayer := range scene.GetAllPlayer() { + g.SendMsg(cmd.AvatarFlycloakChangeNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, avatarFlycloakChangeNotify) + } + + avatarWearFlycloakRsp := &proto.AvatarWearFlycloakRsp{ + AvatarGuid: req.AvatarGuid, + FlycloakId: req.FlycloakId, + } + g.SendMsg(cmd.AvatarWearFlycloakRsp, player.PlayerID, player.ClientSeq, avatarWearFlycloakRsp) +} diff --git a/gs/game/player_login.go b/gs/game/player_login.go index b23758aa..76dda55c 100644 --- a/gs/game/player_login.go +++ b/gs/game/player_login.go @@ -361,31 +361,7 @@ func (g *GameManager) CreatePlayer(userId uint32, nickName string, mainCharAvata player.PropertiesMap[constant.PLAYER_PROP_IS_MP_MODE_AVAILABLE] = 1 player.FlyCloakList = make([]uint32, 0) - player.FlyCloakList = append(player.FlyCloakList, 140001) - player.FlyCloakList = append(player.FlyCloakList, 140002) - player.FlyCloakList = append(player.FlyCloakList, 140003) - player.FlyCloakList = append(player.FlyCloakList, 140004) - player.FlyCloakList = append(player.FlyCloakList, 140005) - player.FlyCloakList = append(player.FlyCloakList, 140006) - player.FlyCloakList = append(player.FlyCloakList, 140007) - player.FlyCloakList = append(player.FlyCloakList, 140008) - player.FlyCloakList = append(player.FlyCloakList, 140009) - player.FlyCloakList = append(player.FlyCloakList, 140010) - player.CostumeList = make([]uint32, 0) - player.CostumeList = append(player.CostumeList, 200301) - player.CostumeList = append(player.CostumeList, 201401) - player.CostumeList = append(player.CostumeList, 202701) - player.CostumeList = append(player.CostumeList, 204201) - player.CostumeList = append(player.CostumeList, 200302) - player.CostumeList = append(player.CostumeList, 202101) - player.CostumeList = append(player.CostumeList, 204101) - player.CostumeList = append(player.CostumeList, 204501) - player.CostumeList = append(player.CostumeList, 201601) - player.CostumeList = append(player.CostumeList, 203101) - player.CostumeList = append(player.CostumeList, 200201) - player.CostumeList = append(player.CostumeList, 200601) - player.CostumeList = append(player.CostumeList, 208201) player.SafePos = &model.Vector{X: 2747, Y: 194, Z: -1719} player.Pos = &model.Vector{X: 2747, Y: 194, Z: -1719} diff --git a/protocol/cmd/cmd_id_proto_obj_map.go b/protocol/cmd/cmd_id_proto_obj_map.go index a60c123b..52689a33 100644 --- a/protocol/cmd/cmd_id_proto_obj_map.go +++ b/protocol/cmd/cmd_id_proto_obj_map.go @@ -214,12 +214,6 @@ func (c *CmdProtoMap) registerAllMessage() { // 角色 c.registerMessage(AvatarDataNotify, &proto.AvatarDataNotify{}) // 角色信息通知 c.registerMessage(AvatarAddNotify, &proto.AvatarAddNotify{}) // 角色新增通知 - c.registerMessage(AvatarChangeCostumeReq, &proto.AvatarChangeCostumeReq{}) // 角色换装请求 - c.registerMessage(AvatarChangeCostumeRsp, &proto.AvatarChangeCostumeRsp{}) // 角色换装响应 - c.registerMessage(AvatarChangeCostumeNotify, &proto.AvatarChangeCostumeNotify{}) // 角色换装通知 - c.registerMessage(AvatarWearFlycloakReq, &proto.AvatarWearFlycloakReq{}) // 角色换风之翼请求 - c.registerMessage(AvatarWearFlycloakRsp, &proto.AvatarWearFlycloakRsp{}) // 角色换风之翼响应 - c.registerMessage(AvatarFlycloakChangeNotify, &proto.AvatarFlycloakChangeNotify{}) // 角色换风之翼通知 c.registerMessage(AvatarLifeStateChangeNotify, &proto.AvatarLifeStateChangeNotify{}) // 角色存活状态改变通知 c.registerMessage(AvatarUpgradeReq, &proto.AvatarUpgradeReq{}) // 角色升级请求 c.registerMessage(AvatarUpgradeRsp, &proto.AvatarUpgradeRsp{}) // 角色升级通知 @@ -229,6 +223,18 @@ func (c *CmdProtoMap) registerAllMessage() { c.registerMessage(AvatarPromoteGetRewardReq, &proto.AvatarPromoteGetRewardReq{}) // 角色突破获取奖励请求 c.registerMessage(AvatarPromoteGetRewardRsp, &proto.AvatarPromoteGetRewardRsp{}) // 角色突破获取奖励响应 + // 时装 + c.registerMessage(AvatarChangeCostumeReq, &proto.AvatarChangeCostumeReq{}) // 角色换装请求 + c.registerMessage(AvatarChangeCostumeRsp, &proto.AvatarChangeCostumeRsp{}) // 角色换装响应 + c.registerMessage(AvatarChangeCostumeNotify, &proto.AvatarChangeCostumeNotify{}) // 角色换装通知 + c.registerMessage(AvatarGainCostumeNotify, &proto.AvatarGainCostumeNotify{}) // 角色获得时装通知 + + // 风之翼 + c.registerMessage(AvatarWearFlycloakReq, &proto.AvatarWearFlycloakReq{}) // 角色换风之翼请求 + c.registerMessage(AvatarWearFlycloakRsp, &proto.AvatarWearFlycloakRsp{}) // 角色换风之翼响应 + c.registerMessage(AvatarFlycloakChangeNotify, &proto.AvatarFlycloakChangeNotify{}) // 角色换风之翼通知 + c.registerMessage(AvatarGainFlycloakNotify, &proto.AvatarGainFlycloakNotify{}) // 角色获得风之翼通知 + // 背包与道具 c.registerMessage(PlayerStoreNotify, &proto.PlayerStoreNotify{}) // 玩家背包数据通知 c.registerMessage(StoreWeightLimitNotify, &proto.StoreWeightLimitNotify{}) // 背包容量上限通知