角色突破功能

This commit is contained in:
UnKownOwO
2023-02-03 22:02:38 +08:00
parent 34b87fadfc
commit 849fcdf93d
12 changed files with 436 additions and 155 deletions

View File

@@ -3,12 +3,14 @@ package constant
var ItemConstantConst *ItemConstant
type ItemConstant struct {
HCOIN uint32 // 原石 201
SCOIN uint32 // 摩拉 202
MCOIN uint32 // 创世结晶 203
RESIN uint32 // 树脂 106
LEGENDARY_KEY uint32 // 传说任务钥匙 107
HOME_COIN uint32 // 洞天宝钱 204
HCOIN uint32 // 原石 201
SCOIN uint32 // 摩拉 202
MCOIN uint32 // 创世结晶 203
RESIN uint32 // 树脂 106
LEGENDARY_KEY uint32 // 传说任务钥匙 107
HOME_COIN uint32 // 洞天宝钱 204
PLAYER_EXP uint32 // 冒险阅历 102
VIRTUAL_ITEM_PROP map[uint32]uint16 // 虚拟物品对应玩家的属性
}
func InitItemConstantConst() {
@@ -20,4 +22,14 @@ func InitItemConstantConst() {
ItemConstantConst.RESIN = 106
ItemConstantConst.LEGENDARY_KEY = 207
ItemConstantConst.HOME_COIN = 204
ItemConstantConst.PLAYER_EXP = 102
ItemConstantConst.VIRTUAL_ITEM_PROP = map[uint32]uint16{
ItemConstantConst.HCOIN: PlayerPropertyConst.PROP_PLAYER_HCOIN,
ItemConstantConst.SCOIN: PlayerPropertyConst.PROP_PLAYER_SCOIN,
ItemConstantConst.MCOIN: PlayerPropertyConst.PROP_PLAYER_MCOIN,
ItemConstantConst.RESIN: PlayerPropertyConst.PROP_PLAYER_RESIN,
ItemConstantConst.LEGENDARY_KEY: PlayerPropertyConst.PROP_PLAYER_LEGENDARY_KEY,
ItemConstantConst.HOME_COIN: PlayerPropertyConst.PROP_PLAYER_HOME_COIN,
ItemConstantConst.PLAYER_EXP: PlayerPropertyConst.PROP_PLAYER_EXP,
}
}

View File

@@ -25,6 +25,7 @@ type AvatarData struct {
InitialWeapon int32 `csv:"InitialWeapon,omitempty"` // 初始武器
WeaponType int32 `csv:"WeaponType,omitempty"` // 武器种类
SkillDepotId int32 `csv:"SkillDepotId,omitempty"` // 技能库ID
PromoteId int32 `csv:"PromoteId,omitempty"` // 角色突破ID
AbilityHashCodeList []int32
}

View File

@@ -10,13 +10,23 @@ import (
// 角色突破配置表
type AvatarPromoteData struct {
PromoteId int32 `csv:"PromoteId"` // 角色突破ID
PromoteLevel int32 `csv:"PromoteLevel,omitempty"` // 突破等级
LevelLimit int32 `csv:"LevelLimit,omitempty"` // 解锁等级上限
PromoteId int32 `csv:"PromoteId"` // 角色突破ID
PromoteLevel int32 `csv:"PromoteLevel,omitempty"` // 突破等级
CostCoin int32 `csv:"CostCoin,omitempty"` // 消耗金币
CostItemId1 int32 `csv:"CostItemId1,omitempty"` // [消耗物品]1ID
CostItemCount1 int32 `csv:"CostItemCount1,omitempty"` // [消耗物品]1数量
CostItemId2 int32 `csv:"CostItemId2,omitempty"` // [消耗物品]2ID
CostItemCount2 int32 `csv:"CostItemCount2,omitempty"` // [消耗物品]2数量
CostItemId3 int32 `csv:"CostItemId3,omitempty"` // [消耗物品]3ID
CostItemCount3 int32 `csv:"CostItemCount3,omitempty"` // [消耗物品]3数量
LevelLimit int32 `csv:"LevelLimit,omitempty"` // 解锁等级上限
MinPlayerLevel int32 `csv:"MinPlayerLevel,omitempty"` // 冒险等级要求
CostItemMap map[uint32]uint32 // 消耗物品列表
}
func (g *GameDataConfig) loadAvatarPromoteData() {
g.AvatarPromoteDataMap = make(map[int32]*AvatarPromoteData)
g.AvatarPromoteDataMap = make(map[int32]map[int32]*AvatarPromoteData)
data := g.readCsvFileData("AvatarPromoteData.csv")
var avatarPromoteDataList []*AvatarPromoteData
err := csvutil.Unmarshal(data, &avatarPromoteDataList)
@@ -26,7 +36,22 @@ func (g *GameDataConfig) loadAvatarPromoteData() {
}
for _, avatarPromoteData := range avatarPromoteDataList {
// list -> map
g.AvatarPromoteDataMap[avatarPromoteData.PromoteLevel] = avatarPromoteData
_, ok := g.AvatarPromoteDataMap[avatarPromoteData.PromoteId]
if !ok {
g.AvatarPromoteDataMap[avatarPromoteData.PromoteId] = make(map[int32]*AvatarPromoteData)
}
avatarPromoteData.CostItemMap = make(map[uint32]uint32, 3)
avatarPromoteData.CostItemMap[uint32(avatarPromoteData.CostItemId1)] = uint32(avatarPromoteData.CostItemCount1)
avatarPromoteData.CostItemMap[uint32(avatarPromoteData.CostItemId2)] = uint32(avatarPromoteData.CostItemCount2)
avatarPromoteData.CostItemMap[uint32(avatarPromoteData.CostItemId3)] = uint32(avatarPromoteData.CostItemCount3)
for itemId, count := range avatarPromoteData.CostItemMap {
// 两个值都不能为0
if itemId == 0 || count == 0 {
delete(avatarPromoteData.CostItemMap, itemId)
}
}
// 通过突破等级找到突破数据
g.AvatarPromoteDataMap[avatarPromoteData.PromoteId][avatarPromoteData.PromoteLevel] = avatarPromoteData
}
logger.Info("AvatarPromoteData count: %v", len(g.AvatarPromoteDataMap))
}

View File

@@ -24,24 +24,25 @@ type GameDataConfig struct {
jsonPrefix string
luaPrefix string
// 配置表数据
AvatarDataMap map[int32]*AvatarData // 角色
AvatarSkillDataMap map[int32]*AvatarSkillData // 角色技能
AvatarSkillDepotDataMap map[int32]*AvatarSkillDepotData // 角色技能库
DropGroupDataMap map[int32]*DropGroupData // 掉落组
GCGCharDataMap map[int32]*GCGCharData // 角色卡牌
GCGSkillDataMap map[int32]*GCGSkillData // 卡牌技能
SceneDataMap map[int32]*SceneData // 场景
ScenePointMap map[int32]*ScenePoint // 场景传送点
SceneTagDataMap map[int32]*SceneTagData // 场景地图图标
SceneMap map[int32]*Scene // 场景详情
WorldAreaDataMap map[int32]*WorldAreaData // 世界区域
GatherDataMap map[int32]*GatherData // 采集物
GatherDataPointTypeMap map[int32]*GatherData // 采集物场景节点索引
FetterDataMap map[int32]*FetterData // 角色资料解锁
FetterDataAvatarIdMap map[int32][]int32 // 角色资料解锁角色id索引
ItemDataMap map[int32]*ItemData // 统一道具
AvatarLevelDataMap map[int32]*AvatarLevelData // 角色等级
AvatarPromoteDataMap map[int32]*AvatarPromoteData // 角色突破
AvatarDataMap map[int32]*AvatarData // 角色
AvatarSkillDataMap map[int32]*AvatarSkillData // 角色技能
AvatarSkillDepotDataMap map[int32]*AvatarSkillDepotData // 角色技能库
DropGroupDataMap map[int32]*DropGroupData // 掉落组
GCGCharDataMap map[int32]*GCGCharData // 角色卡牌
GCGSkillDataMap map[int32]*GCGSkillData // 卡牌技能
SceneDataMap map[int32]*SceneData // 场景
ScenePointMap map[int32]*ScenePoint // 场景传送点
SceneTagDataMap map[int32]*SceneTagData // 场景地图图标
SceneMap map[int32]*Scene // 场景详情
WorldAreaDataMap map[int32]*WorldAreaData // 世界区域
GatherDataMap map[int32]*GatherData // 采集物
GatherDataPointTypeMap map[int32]*GatherData // 采集物场景节点索引
FetterDataMap map[int32]*FetterData // 角色资料解锁
FetterDataAvatarIdMap map[int32][]int32 // 角色资料解锁角色id索引
ItemDataMap map[int32]*ItemData // 统一道具
AvatarLevelDataMap map[int32]*AvatarLevelData // 角色等级
AvatarPromoteDataMap map[int32]map[int32]*AvatarPromoteData // 角色突破
PlayerLevelDataMap map[int32]*PlayerLevelData // 玩家等级
}
func InitGameDataConfig() {
@@ -117,6 +118,7 @@ func (g *GameDataConfig) load() {
g.loadItemData() // 统一道具
g.loadAvatarLevelData() // 角色等级
g.loadAvatarPromoteData() // 角色突破
g.loadPlayerLevelData() // 玩家等级
}
func (g *GameDataConfig) readCsvFileData(fileName string) []byte {

View File

@@ -0,0 +1,31 @@
package gdconf
import (
"fmt"
"hk4e/pkg/logger"
"github.com/jszwec/csvutil"
)
// 玩家等级配置表
type PlayerLevelData struct {
Level int32 `csv:"Level"` // 等级
Exp int32 `csv:"Exp,omitempty"` // 升到下一级所需经验
}
func (g *GameDataConfig) loadPlayerLevelData() {
g.PlayerLevelDataMap = make(map[int32]*PlayerLevelData)
data := g.readCsvFileData("PlayerLevelData.csv")
var playerLevelDataList []*PlayerLevelData
err := csvutil.Unmarshal(data, &playerLevelDataList)
if err != nil {
info := fmt.Sprintf("parse file error: %v", err)
panic(info)
}
for _, playerLevelData := range playerLevelDataList {
// list -> map
g.PlayerLevelDataMap[playerLevelData.Level] = playerLevelData
}
logger.Info("PlayerLevelData count: %v", len(g.PlayerLevelDataMap))
}

View File

@@ -56,6 +56,11 @@
"field_name": "SkillDepotId",
"field_type": "int32",
"origin_name": "技能库ID"
},
{
"field_name": "PromoteId",
"field_type": "int32",
"origin_name": "角色突破ID"
}
]
},
@@ -622,10 +627,75 @@
"field_type": "int32",
"origin_name": "突破等级"
},
{
"field_name": "CostCoin",
"field_type": "int32",
"origin_name": "消耗金币"
},
{
"field_name": "CostItemId1",
"field_type": "int32",
"origin_name": "[消耗物品]1ID"
},
{
"field_name": "CostItemCount1",
"field_type": "int32",
"origin_name": "[消耗物品]1数量"
},
{
"field_name": "CostItemId2",
"field_type": "int32",
"origin_name": "[消耗物品]2ID"
},
{
"field_name": "CostItemCount2",
"field_type": "int32",
"origin_name": "[消耗物品]2数量"
},
{
"field_name": "CostItemId3",
"field_type": "int32",
"origin_name": "[消耗物品]3ID"
},
{
"field_name": "CostItemCount3",
"field_type": "int32",
"origin_name": "[消耗物品]3数量"
},
{
"field_name": "CostItemId4",
"field_type": "int32",
"origin_name": "[消耗物品]4ID"
},
{
"field_name": "CostItemCount4",
"field_type": "int32",
"origin_name": "[消耗物品]4数量"
},
{
"field_name": "LevelLimit",
"field_type": "int32",
"origin_name": "解锁等级上限"
},
{
"field_name": "MinPlayerLevel",
"field_type": "int32",
"origin_name": "冒险等级要求"
}
]
},
{
"table_name": "PlayerLevelData",
"field_list": [
{
"field_name": "Level",
"field_type": "int32",
"origin_name": "等级"
},
{
"field_name": "Exp",
"field_type": "int32",
"origin_name": "升到下一级所需经验"
}
]
}

View File

@@ -67,6 +67,82 @@ func (g *GameManager) AddUserAvatar(userId uint32, avatarId uint32) {
g.SendMsg(cmd.AvatarAddNotify, userId, player.ClientSeq, avatarAddNotify)
}
// AvatarPromoteReq 角色突破请求
func (g *GameManager) AvatarPromoteReq(player *model.Player, payloadMsg pb.Message) {
logger.Debug("user promote, uid: %v", player.PlayerID)
req := payloadMsg.(*proto.AvatarPromoteReq)
// 是否拥有角色
avatar, ok := player.AvatarMap[player.GetAvatarIdByGuid(req.Guid)]
if !ok {
logger.Error("avatar error, avatarGuid: %v", req.Guid)
g.CommonRetError(cmd.AvatarPromoteRsp, player, &proto.AvatarUpgradeRsp{}, proto.Retcode_RET_CAN_NOT_FIND_AVATAR)
return
}
// 获取角色配置表
avatarDataConfig, ok := gdconf.CONF.AvatarDataMap[int32(avatar.AvatarId)]
if !ok {
logger.Error("avatar config error, avatarId: %v", avatar.AvatarId)
g.CommonRetError(cmd.AvatarPromoteRsp, player, &proto.AvatarUpgradeRsp{})
return
}
// 获取角色突破配置表
avatarPromoteDataMap, ok := gdconf.CONF.AvatarPromoteDataMap[avatarDataConfig.PromoteId]
if !ok {
logger.Error("avatar promote config error, promoteId: %v", avatarDataConfig.PromoteId)
g.CommonRetError(cmd.AvatarPromoteRsp, player, &proto.AvatarUpgradeRsp{})
return
}
// 获取角色突破下一级的配置表
avatarPromoteConfig, ok := avatarPromoteDataMap[int32(avatar.Promote+1)]
if !ok {
logger.Error("avatar promote config error, promoteLevel: %v", avatar.Promote)
g.CommonRetError(cmd.AvatarPromoteRsp, player, &proto.AvatarUpgradeRsp{})
return
}
// 将被消耗的物品列表
costItemList := make([]*UserItem, 0, len(avatarPromoteConfig.CostItemMap)+1)
// 突破材料是否足够并添加到消耗物品列表
for itemId, count := range avatarPromoteConfig.CostItemMap {
costItemList = append(costItemList, &UserItem{
ItemId: itemId,
ChangeCount: count,
})
}
// 消耗列表添加摩拉的消耗
costItemList = append(costItemList, &UserItem{
ItemId: constant.ItemConstantConst.SCOIN,
ChangeCount: uint32(avatarPromoteConfig.CostCoin),
})
// 突破材料以及摩拉是否足够
for _, item := range costItemList {
if player.GetItemCount(item.ItemId) < item.ChangeCount {
logger.Error("item count not enough, itemId: %v", item.ItemId)
g.CommonRetError(cmd.AvatarPromoteRsp, player, &proto.AvatarPromoteRsp{}, proto.Retcode_RET_SCOIN_NOT_ENOUGH)
return
}
}
// 冒险等级是否符合要求
if player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL] < uint32(avatarPromoteConfig.MinPlayerLevel) {
logger.Error("player level not enough, level: %v", player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL])
g.CommonRetError(cmd.AvatarPromoteRsp, player, &proto.AvatarPromoteRsp{})
return
}
// 消耗突破材料和摩拉
GAME_MANAGER.CostUserItem(player.PlayerID, costItemList)
// 角色突破等级+1
avatar.Promote++
// 角色更新面板
player.InitAvatarFightProp(avatar)
// 角色属性表更新通知
g.SendMsg(cmd.AvatarPropNotify, player.PlayerID, player.ClientSeq, g.PacketAvatarPropNotify(avatar))
avatarPromoteRsp := &proto.AvatarPromoteRsp{
Guid: req.Guid,
}
g.SendMsg(cmd.AvatarPromoteRsp, player.PlayerID, player.ClientSeq, avatarPromoteRsp)
}
// AvatarUpgradeReq 角色升级请求
func (g *GameManager) AvatarUpgradeReq(player *model.Player, payloadMsg pb.Message) {
logger.Debug("user upgrade, uid: %v", player.PlayerID)
@@ -106,8 +182,22 @@ func (g *GameManager) AvatarUpgradeReq(player *model.Player, payloadMsg pb.Messa
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{}, proto.Retcode_RET_SCOIN_NOT_ENOUGH)
return
}
// 获取角色配置表
avatarDataConfig, ok := gdconf.CONF.AvatarDataMap[int32(avatar.AvatarId)]
if !ok {
logger.Error("avatar config error, avatarId: %v", avatar.AvatarId)
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{})
return
}
// 获取角色突破配置表
avatarPromoteConfig, ok := gdconf.CONF.AvatarPromoteDataMap[int32(avatar.Promote)]
avatarPromoteDataMap, ok := gdconf.CONF.AvatarPromoteDataMap[avatarDataConfig.PromoteId]
if !ok {
logger.Error("avatar promote config error, promoteId: %v", avatarDataConfig.PromoteId)
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{})
return
}
// 获取角色突破等级对应的配置表
avatarPromoteConfig, ok := avatarPromoteDataMap[int32(avatar.Promote)]
if !ok {
logger.Error("avatar promote config error, promoteLevel: %v", avatar.Promote)
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{})
@@ -115,8 +205,8 @@ func (g *GameManager) AvatarUpgradeReq(player *model.Player, payloadMsg pb.Messa
}
// 角色等级是否达到限制
if avatar.Level >= uint8(avatarPromoteConfig.LevelLimit) {
logger.Error("avatar promote config error, promoteLevel: %v", avatar.Promote)
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{}, proto.Retcode_RET_AVATAR_LIMIT_LEVEL_ERROR)
logger.Error("avatar level ge level limit, level: %v", avatar.Level)
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{})
return
}
// 消耗升级材料以及摩拉
@@ -136,8 +226,10 @@ func (g *GameManager) AvatarUpgradeReq(player *model.Player, payloadMsg pb.Messa
for propType, propValue := range avatar.FightPropMap {
oldFightPropMap[propType] = propValue
}
// 角色添加经验
g.UpgradeUserAvatar(player.PlayerID, avatar.AvatarId, expCount)
avatarUpgradeRsp := &proto.AvatarUpgradeRsp{
CurLevel: uint32(avatar.Level),
OldLevel: uint32(oldLevel),
@@ -148,7 +240,7 @@ func (g *GameManager) AvatarUpgradeReq(player *model.Player, payloadMsg pb.Messa
g.SendMsg(cmd.AvatarUpgradeRsp, player.PlayerID, player.ClientSeq, avatarUpgradeRsp)
}
// UpgradeUserAvatar 用户角色升级
// UpgradeUserAvatar 玩家角色升级
func (g *GameManager) UpgradeUserAvatar(userId uint32, avatarId uint32, expCount uint32) {
player := USER_MANAGER.GetOnlineUser(userId)
if player == nil {
@@ -160,11 +252,22 @@ func (g *GameManager) UpgradeUserAvatar(userId uint32, avatarId uint32, expCount
logger.Error("avatar error, avatarId: %v", avatarId)
return
}
// 获取角色配置表
avatarDataConfig, ok := gdconf.CONF.AvatarDataMap[int32(avatar.AvatarId)]
if !ok {
logger.Error("avatar config error, avatarId: %v", avatar.AvatarId)
return
}
// 获取角色突破配置表
avatarPromoteConfig, ok := gdconf.CONF.AvatarPromoteDataMap[int32(avatar.Promote)]
avatarPromoteDataMap, ok := gdconf.CONF.AvatarPromoteDataMap[avatarDataConfig.PromoteId]
if !ok {
logger.Error("avatar promote config error, promoteId: %v", avatarDataConfig.PromoteId)
return
}
// 获取角色突破等级对应的配置表
avatarPromoteConfig, ok := avatarPromoteDataMap[int32(avatar.Promote)]
if !ok {
logger.Error("avatar promote config error, promoteLevel: %v", avatar.Promote)
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{})
return
}
// 角色增加经验
@@ -174,19 +277,17 @@ func (g *GameManager) UpgradeUserAvatar(userId uint32, avatarId uint32, expCount
// 获取角色等级配置表
avatarLevelConfig, ok := gdconf.CONF.AvatarLevelDataMap[int32(avatar.Level)]
if !ok {
logger.Error("avatar level config error, level: %v", avatar.Level)
g.CommonRetError(cmd.AvatarUpgradeRsp, player, &proto.AvatarUpgradeRsp{})
return
// 获取不到代表已经到达最大等级
break
}
// 角色当前等级未突破则跳出循环
if avatar.Level >= uint8(avatarPromoteConfig.LevelLimit) {
// 角色未突破溢出的经验处理
avatar.Exp = 0
break
}
// 角色经验小于升级所需的经验则跳出循环
if avatar.Exp > uint32(avatarLevelConfig.Exp) {
// 角色当前等级未突破则跳出循环
if avatar.Level >= uint8(avatarPromoteConfig.LevelLimit) {
// 角色未突破溢出的经验处理
avatar.Exp = uint32(avatarLevelConfig.Exp)
break
}
} else {
if avatar.Exp < uint32(avatarLevelConfig.Exp) {
break
}
// 角色等级提升

57
gs/game/player_base.go Normal file
View File

@@ -0,0 +1,57 @@
package game
import (
"hk4e/common/constant"
"hk4e/gdconf"
"hk4e/pkg/logger"
"hk4e/protocol/cmd"
"hk4e/protocol/proto"
)
// AddUserPlayerExp 基于玩家冒险阅历
func (g *GameManager) AddUserPlayerExp(userId uint32, expCount uint32) {
player := USER_MANAGER.GetOnlineUser(userId)
if player == nil {
logger.Error("player is nil, uid: %v", userId)
return
}
// 玩家增加冒险阅历
player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_EXP] += expCount
// 玩家升级
for {
playerLevel := player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL]
// 读取玩家等级配置表
playerLevelConfig, ok := gdconf.CONF.PlayerLevelDataMap[int32(playerLevel)]
if !ok {
// 获取不到代表已经到达最大等级
break
}
// 玩家冒险阅历不足则跳出循环
if player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_EXP] < uint32(playerLevelConfig.Exp) {
break
}
// 玩家增加冒险等阶
player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL]++
player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_EXP] -= uint32(playerLevelConfig.Exp)
// 更新玩家属性
playerPropNotify := &proto.PlayerPropNotify{
PropMap: make(map[uint32]*proto.PropValue),
}
playerPropNotify.PropMap[uint32(constant.PlayerPropertyConst.PROP_PLAYER_LEVEL)] = &proto.PropValue{
Type: uint32(constant.PlayerPropertyConst.PROP_PLAYER_LEVEL),
Val: int64(player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL]),
Value: &proto.PropValue_Ival{
Ival: int64(player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL]),
},
}
playerPropNotify.PropMap[uint32(constant.PlayerPropertyConst.PROP_PLAYER_EXP)] = &proto.PropValue{
Type: uint32(constant.PlayerPropertyConst.PROP_PLAYER_EXP),
Val: int64(player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_EXP]),
Value: &proto.PropValue_Ival{
Ival: int64(player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_EXP]),
},
}
g.SendMsg(cmd.PlayerPropNotify, userId, player.ClientSeq, playerPropNotify)
}
}

View File

@@ -48,14 +48,46 @@ func (g *GameManager) GetAllItemDataConfig() map[int32]*gdconf.ItemData {
return allItemDataConfig
}
// AddUserItem 玩家添加物品
func (g *GameManager) AddUserItem(userId uint32, itemList []*UserItem, isHint bool, hintReason uint16) {
player := USER_MANAGER.GetOnlineUser(userId)
if player == nil {
logger.Error("player is nil, uid: %v", userId)
return
}
playerPropNotify := &proto.PlayerPropNotify{
PropMap: make(map[uint32]*proto.PropValue),
}
for _, userItem := range itemList {
player.AddItem(userItem.ItemId, userItem.ChangeCount)
// 物品为虚拟物品则另外处理
switch userItem.ItemId {
case constant.ItemConstantConst.RESIN, constant.ItemConstantConst.LEGENDARY_KEY, constant.ItemConstantConst.HCOIN,
constant.ItemConstantConst.SCOIN, constant.ItemConstantConst.MCOIN, constant.ItemConstantConst.HOME_COIN:
// 树脂 传说任务钥匙 原石 摩拉 创世结晶 洞天宝钱
prop, ok := constant.ItemConstantConst.VIRTUAL_ITEM_PROP[userItem.ItemId]
if !ok {
continue
}
// 角色属性物品数量增加
player.PropertiesMap[prop] += userItem.ChangeCount
playerPropNotify.PropMap[uint32(prop)] = &proto.PropValue{
Type: uint32(prop),
Val: int64(player.PropertiesMap[prop]),
Value: &proto.PropValue_Ival{
Ival: int64(player.PropertiesMap[prop]),
},
}
case constant.ItemConstantConst.PLAYER_EXP:
// 冒险阅历
g.AddUserPlayerExp(userId, userItem.ChangeCount)
default:
// 普通物品直接进背包
player.AddItem(userItem.ItemId, userItem.ChangeCount)
}
}
if len(playerPropNotify.PropMap) > 0 {
g.SendMsg(cmd.PlayerPropNotify, userId, player.ClientSeq, playerPropNotify)
}
storeItemChangeNotify := &proto.StoreItemChangeNotify{
@@ -93,26 +125,6 @@ func (g *GameManager) AddUserItem(userId uint32, itemList []*UserItem, isHint bo
}
g.SendMsg(cmd.ItemAddHintNotify, userId, player.ClientSeq, itemAddHintNotify)
}
playerPropNotify := &proto.PlayerPropNotify{
PropMap: make(map[uint32]*proto.PropValue),
}
for _, userItem := range itemList {
isVirtualItem, prop := player.GetVirtualItemProp(userItem.ItemId)
if !isVirtualItem {
continue
}
playerPropNotify.PropMap[uint32(prop)] = &proto.PropValue{
Type: uint32(prop),
Val: int64(player.PropertiesMap[prop]),
Value: &proto.PropValue_Ival{
Ival: int64(player.PropertiesMap[prop]),
},
}
}
if len(playerPropNotify.PropMap) > 0 {
g.SendMsg(cmd.PlayerPropNotify, userId, player.ClientSeq, playerPropNotify)
}
}
func (g *GameManager) CostUserItem(userId uint32, itemList []*UserItem) {
@@ -121,8 +133,42 @@ func (g *GameManager) CostUserItem(userId uint32, itemList []*UserItem) {
logger.Error("player is nil, uid: %v", userId)
return
}
playerPropNotify := &proto.PlayerPropNotify{
PropMap: make(map[uint32]*proto.PropValue),
}
for _, userItem := range itemList {
player.CostItem(userItem.ItemId, userItem.ChangeCount)
// 物品为虚拟物品则另外处理
switch userItem.ItemId {
case constant.ItemConstantConst.RESIN, constant.ItemConstantConst.LEGENDARY_KEY, constant.ItemConstantConst.HCOIN,
constant.ItemConstantConst.SCOIN, constant.ItemConstantConst.MCOIN, constant.ItemConstantConst.HOME_COIN:
// 树脂 传说任务钥匙 原石 摩拉 创世结晶 洞天宝钱
prop, ok := constant.ItemConstantConst.VIRTUAL_ITEM_PROP[userItem.ItemId]
if !ok {
continue
}
// 角色属性物品数量增加
if player.PropertiesMap[prop] < userItem.ChangeCount {
player.PropertiesMap[prop] = 0
} else {
player.PropertiesMap[prop] -= userItem.ChangeCount
}
playerPropNotify.PropMap[uint32(prop)] = &proto.PropValue{
Type: uint32(prop),
Val: int64(player.PropertiesMap[prop]),
Value: &proto.PropValue_Ival{
Ival: int64(player.PropertiesMap[prop]),
},
}
case constant.ItemConstantConst.PLAYER_EXP:
// 冒险阅历应该也没人会去扣吧?
default:
// 普通物品直接扣除
player.CostItem(userItem.ItemId, userItem.ChangeCount)
}
}
if len(playerPropNotify.PropMap) > 0 {
g.SendMsg(cmd.PlayerPropNotify, userId, player.ClientSeq, playerPropNotify)
}
storeItemChangeNotify := &proto.StoreItemChangeNotify{
@@ -163,24 +209,4 @@ func (g *GameManager) CostUserItem(userId uint32, itemList []*UserItem) {
if len(storeItemDelNotify.GuidList) > 0 {
g.SendMsg(cmd.StoreItemDelNotify, userId, player.ClientSeq, storeItemDelNotify)
}
playerPropNotify := &proto.PlayerPropNotify{
PropMap: make(map[uint32]*proto.PropValue),
}
for _, userItem := range itemList {
isVirtualItem, prop := player.GetVirtualItemProp(userItem.ItemId)
if !isVirtualItem {
continue
}
playerPropNotify.PropMap[uint32(prop)] = &proto.PropValue{
Type: uint32(prop),
Val: int64(player.PropertiesMap[prop]),
Value: &proto.PropValue_Ival{
Ival: int64(player.PropertiesMap[prop]),
},
}
}
if len(playerPropNotify.PropMap) > 0 {
g.SendMsg(cmd.PlayerPropNotify, userId, player.ClientSeq, playerPropNotify)
}
}

View File

@@ -130,6 +130,7 @@ func (r *RouteManager) initRoute() {
r.registerRouter(cmd.GCGOperationReq, GAME_MANAGER.GCGOperationReq)
r.registerRouter(cmd.ObstacleModifyNotify, GAME_MANAGER.ObstacleModifyNotify)
r.registerRouter(cmd.AvatarUpgradeReq, GAME_MANAGER.AvatarUpgradeReq)
r.registerRouter(cmd.AvatarPromoteReq, GAME_MANAGER.AvatarPromoteReq)
}
func (r *RouteManager) RouteHandle(netMsg *mq.NetMsg) {

View File

@@ -1,8 +1,6 @@
package model
import (
"hk4e/common/constant"
)
import "hk4e/common/constant"
type Item struct {
ItemId uint32 `bson:"itemId"` // 道具id
@@ -26,8 +24,8 @@ func (p *Player) GetItemGuid(itemId uint32) uint64 {
}
func (p *Player) GetItemCount(itemId uint32) uint32 {
isVirtualItem, prop := p.GetVirtualItemProp(itemId)
if isVirtualItem {
prop, ok := constant.ItemConstantConst.VIRTUAL_ITEM_PROP[itemId]
if ok {
value := p.PropertiesMap[prop]
return value
} else {
@@ -39,73 +37,28 @@ func (p *Player) GetItemCount(itemId uint32) uint32 {
}
}
// 虚拟道具如下 实际值存在玩家的属性上
// 原石 201
// 摩拉 202
// 创世结晶 203
// 树脂 106
// 传说任务钥匙 107
// 洞天宝钱 204
func (p *Player) GetVirtualItemProp(itemId uint32) (isVirtualItem bool, prop uint16) {
switch itemId {
case 106:
return true, constant.PlayerPropertyConst.PROP_PLAYER_RESIN
case 107:
return true, constant.PlayerPropertyConst.PROP_PLAYER_LEGENDARY_KEY
case 201:
return true, constant.PlayerPropertyConst.PROP_PLAYER_HCOIN
case 202:
return true, constant.PlayerPropertyConst.PROP_PLAYER_SCOIN
case 203:
return true, constant.PlayerPropertyConst.PROP_PLAYER_MCOIN
case 204:
return true, constant.PlayerPropertyConst.PROP_PLAYER_HOME_COIN
default:
return false, 0
}
}
func (p *Player) AddItem(itemId uint32, count uint32) {
isVirtualItem, prop := p.GetVirtualItemProp(itemId)
if isVirtualItem {
value := p.PropertiesMap[prop]
value += count
p.PropertiesMap[prop] = value
} else {
itemInfo := p.ItemMap[itemId]
if itemInfo == nil {
itemInfo = &Item{
ItemId: itemId,
Count: 0,
Guid: p.GetNextGameObjectGuid(),
}
itemInfo := p.ItemMap[itemId]
if itemInfo == nil {
itemInfo = &Item{
ItemId: itemId,
Count: 0,
Guid: p.GetNextGameObjectGuid(),
}
itemInfo.Count += count
p.ItemMap[itemId] = itemInfo
}
itemInfo.Count += count
p.ItemMap[itemId] = itemInfo
}
func (p *Player) CostItem(itemId uint32, count uint32) {
isVirtualItem, prop := p.GetVirtualItemProp(itemId)
if isVirtualItem {
value := p.PropertiesMap[prop]
if value < count {
value = 0
} else {
value -= count
}
p.PropertiesMap[prop] = value
} else {
itemInfo := p.ItemMap[itemId]
if itemInfo == nil {
return
}
if itemInfo.Count < count {
itemInfo.Count = 0
} else {
itemInfo.Count -= count
}
p.ItemMap[itemId] = itemInfo
itemInfo := p.ItemMap[itemId]
if itemInfo == nil {
return
}
if itemInfo.Count < count {
itemInfo.Count = 0
} else {
itemInfo.Count -= count
}
p.ItemMap[itemId] = itemInfo
}

View File

@@ -224,6 +224,8 @@ func (c *CmdProtoMap) registerAllMessage() {
c.registerMessage(AvatarUpgradeReq, &proto.AvatarUpgradeReq{}) // 角色升级请求
c.registerMessage(AvatarUpgradeRsp, &proto.AvatarUpgradeRsp{}) // 角色升级通知
c.registerMessage(AvatarPropNotify, &proto.AvatarPropNotify{}) // 角色属性表更新通知
c.registerMessage(AvatarPromoteReq, &proto.AvatarPromoteReq{}) // 角色突破请求
c.registerMessage(AvatarPromoteRsp, &proto.AvatarPromoteRsp{}) // 角色突破响应
// 背包与道具
c.registerMessage(PlayerStoreNotify, &proto.PlayerStoreNotify{}) // 玩家背包数据通知