场景group分suite加载、读取掉落表

This commit is contained in:
flswld
2023-03-21 23:03:00 +08:00
parent 62b929902d
commit f99d845d57
46 changed files with 1076 additions and 594 deletions

View File

@@ -13,13 +13,12 @@ type AvatarCostumeData struct {
func (g *GameDataConfig) loadAvatarCostumeData() {
g.AvatarCostumeDataMap = make(map[int32]*AvatarCostumeData)
avatarCostumeDataList := make([]*AvatarCostumeData, 0)
readTable[AvatarCostumeData](g.tablePrefix+"AvatarCostumeData.txt", &avatarCostumeDataList)
readTable[AvatarCostumeData](g.txtPrefix+"AvatarCostumeData.txt", &avatarCostumeDataList)
for _, avatarCostumeData := range avatarCostumeDataList {
// 屏蔽默认时装
if avatarCostumeData.ItemID == 0 {
continue
}
// list -> map
g.AvatarCostumeDataMap[avatarCostumeData.CostumeID] = avatarCostumeData
}
logger.Info("AvatarCostumeData count: %v", len(g.AvatarCostumeDataMap))

View File

@@ -43,7 +43,7 @@ type ConfigAvatarAbility struct {
func (g *GameDataConfig) loadAvatarData() {
g.AvatarDataMap = make(map[int32]*AvatarData)
avatarDataList := make([]*AvatarData, 0)
readTable[AvatarData](g.tablePrefix+"AvatarData.txt", &avatarDataList)
readTable[AvatarData](g.txtPrefix+"AvatarData.txt", &avatarDataList)
for _, avatarData := range avatarDataList {
// 读取战斗config解析技能并转化为哈希码
fileData, err := os.ReadFile(g.jsonPrefix + "avatar/" + avatarData.ConfigJson + ".json")
@@ -72,7 +72,6 @@ func (g *GameDataConfig) loadAvatarData() {
avatarData.PromoteRewardMap[uint32(promoteLevel)] = uint32(rewardId)
}
}
// list -> map
g.AvatarDataMap[avatarData.AvatarId] = avatarData
}
logger.Info("AvatarData count: %v", len(g.AvatarDataMap))

View File

@@ -13,9 +13,8 @@ type AvatarFlycloakData struct {
func (g *GameDataConfig) loadAvatarFlycloakData() {
g.AvatarFlycloakDataMap = make(map[int32]*AvatarFlycloakData)
avatarFlycloakDataList := make([]*AvatarFlycloakData, 0)
readTable[AvatarFlycloakData](g.tablePrefix+"AvatarFlycloakData.txt", &avatarFlycloakDataList)
readTable[AvatarFlycloakData](g.txtPrefix+"AvatarFlycloakData.txt", &avatarFlycloakDataList)
for _, avatarFlycloakData := range avatarFlycloakDataList {
// list -> map
g.AvatarFlycloakDataMap[avatarFlycloakData.FlycloakID] = avatarFlycloakData
}
logger.Info("AvatarFlycloakData count: %v", len(g.AvatarFlycloakDataMap))

View File

@@ -13,9 +13,8 @@ type AvatarLevelData struct {
func (g *GameDataConfig) loadAvatarLevelData() {
g.AvatarLevelDataMap = make(map[int32]*AvatarLevelData)
avatarLevelDataList := make([]*AvatarLevelData, 0)
readTable[AvatarLevelData](g.tablePrefix+"AvatarLevelData.txt", &avatarLevelDataList)
readTable[AvatarLevelData](g.txtPrefix+"AvatarLevelData.txt", &avatarLevelDataList)
for _, avatarLevelData := range avatarLevelDataList {
// list -> map
g.AvatarLevelDataMap[avatarLevelData.Level] = avatarLevelData
}
logger.Info("AvatarLevelData count: %v", len(g.AvatarLevelDataMap))

View File

@@ -26,9 +26,8 @@ type AvatarPromoteData struct {
func (g *GameDataConfig) loadAvatarPromoteData() {
g.AvatarPromoteDataMap = make(map[int32]map[int32]*AvatarPromoteData)
avatarPromoteDataList := make([]*AvatarPromoteData, 0)
readTable[AvatarPromoteData](g.tablePrefix+"AvatarPromoteData.txt", &avatarPromoteDataList)
readTable[AvatarPromoteData](g.txtPrefix+"AvatarPromoteData.txt", &avatarPromoteDataList)
for _, avatarPromoteData := range avatarPromoteDataList {
// list -> map
_, ok := g.AvatarPromoteDataMap[avatarPromoteData.PromoteId]
if !ok {
g.AvatarPromoteDataMap[avatarPromoteData.PromoteId] = make(map[int32]*AvatarPromoteData)

View File

@@ -17,9 +17,8 @@ type AvatarSkillData struct {
func (g *GameDataConfig) loadAvatarSkillData() {
g.AvatarSkillDataMap = make(map[int32]*AvatarSkillData)
avatarSkillDataList := make([]*AvatarSkillData, 0)
readTable[AvatarSkillData](g.tablePrefix+"AvatarSkillData.txt", &avatarSkillDataList)
readTable[AvatarSkillData](g.txtPrefix+"AvatarSkillData.txt", &avatarSkillDataList)
for _, avatarSkillData := range avatarSkillDataList {
// list -> map
g.AvatarSkillDataMap[avatarSkillData.AvatarSkillId] = avatarSkillData
}
logger.Info("AvatarSkillData count: %v", len(g.AvatarSkillDataMap))

View File

@@ -43,7 +43,7 @@ type InherentProudSkillOpens struct {
func (g *GameDataConfig) loadAvatarSkillDepotData() {
g.AvatarSkillDepotDataMap = make(map[int32]*AvatarSkillDepotData)
avatarSkillDepotDataList := make([]*AvatarSkillDepotData, 0)
readTable[AvatarSkillDepotData](g.tablePrefix+"AvatarSkillDepotData.txt", &avatarSkillDepotDataList)
readTable[AvatarSkillDepotData](g.txtPrefix+"AvatarSkillDepotData.txt", &avatarSkillDepotDataList)
playerElementsFilePath := g.jsonPrefix + "ability_group/AbilityGroup_Other_PlayerElementAbility.json"
playerElementsFile, err := os.ReadFile(playerElementsFilePath)
if err != nil {
@@ -113,7 +113,6 @@ func (g *GameDataConfig) loadAvatarSkillDepotData() {
}
}
}
// list -> map
g.AvatarSkillDepotDataMap[avatarSkillDepotData.AvatarSkillDepotId] = avatarSkillDepotData
}
logger.Info("AvatarSkillDepotData count: %v", len(g.AvatarSkillDepotDataMap))

39
gdconf/chest_drop_data.go Normal file
View File

@@ -0,0 +1,39 @@
package gdconf
import (
"hk4e/pkg/logger"
)
// ChestDropData 宝箱掉落配置表
type ChestDropData struct {
Level int32 `csv:"最小等级"`
DropTag string `csv:"总索引"`
DropId int32 `csv:"掉落ID,omitempty"`
DropCount int32 `csv:"掉落次数,omitempty"`
}
func (g *GameDataConfig) loadChestDropData() {
g.ChestDropDataMap = make(map[string]map[int32]*ChestDropData)
chestDropDataList := make([]*ChestDropData, 0)
readTable[ChestDropData](g.txtPrefix+"ChestDropData.txt", &chestDropDataList)
for _, chestDropData := range chestDropDataList {
_, exist := g.ChestDropDataMap[chestDropData.DropTag]
if !exist {
g.ChestDropDataMap[chestDropData.DropTag] = make(map[int32]*ChestDropData)
}
g.ChestDropDataMap[chestDropData.DropTag][chestDropData.Level] = chestDropData
}
logger.Info("ChestDropData count: %v", len(g.ChestDropDataMap))
}
func GetChestDropDataByDropTagAndLevel(dropTag string, level int32) *ChestDropData {
value, exist := CONF.ChestDropDataMap[dropTag]
if !exist {
return nil
}
return value[level]
}
func GetChestDropDataMap() map[string]map[int32]*ChestDropData {
return CONF.ChestDropDataMap
}

248
gdconf/drop_data.go Normal file
View File

@@ -0,0 +1,248 @@
package gdconf
import (
"fmt"
"hk4e/pkg/logger"
)
type SubDrop struct {
Id int32 // 子掉落ID
CountRange []int32 // 子掉落数量区间
Weight int32 // 子掉落权重
}
const (
RandomTypeChoose = 0
RandomTypeIndep = 1
RandomTypeIndepWeight = 10000
)
// DropData 掉落配置表
type DropData struct {
DropId int32 `csv:"掉落ID"`
RandomType int32 `csv:"随机方式,omitempty"` // 0:轮盘选择法掉落单个权重项 1:每个权重项独立随机(分母为10000)
DropLayer int32 `csv:"掉落层级,omitempty"`
SubDrop1Id int32 `csv:"子掉落1ID,omitempty"`
SubDrop1CountRange FloatArray `csv:"子掉落1数量区间,omitempty"`
SubDrop1Weight int32 `csv:"子掉落1权重,omitempty"`
SubDrop2Id int32 `csv:"子掉落2ID,omitempty"`
SubDrop2CountRange FloatArray `csv:"子掉落2数量区间,omitempty"`
SubDrop2Weight int32 `csv:"子掉落2权重,omitempty"`
SubDrop3Id int32 `csv:"子掉落3ID,omitempty"`
SubDrop3CountRange FloatArray `csv:"子掉落3数量区间,omitempty"`
SubDrop3Weight int32 `csv:"子掉落3权重,omitempty"`
SubDrop4Id int32 `csv:"子掉落4ID,omitempty"`
SubDrop4CountRange FloatArray `csv:"子掉落4数量区间,omitempty"`
SubDrop4Weight int32 `csv:"子掉落4权重,omitempty"`
SubDrop5Id int32 `csv:"子掉落5ID,omitempty"`
SubDrop5CountRange FloatArray `csv:"子掉落5数量区间,omitempty"`
SubDrop5Weight int32 `csv:"子掉落5权重,omitempty"`
SubDrop6Id int32 `csv:"子掉落6ID,omitempty"`
SubDrop6CountRange FloatArray `csv:"子掉落6数量区间,omitempty"`
SubDrop6Weight int32 `csv:"子掉落6权重,omitempty"`
SubDrop7Id int32 `csv:"子掉落7ID,omitempty"`
SubDrop7CountRange FloatArray `csv:"子掉落7数量区间,omitempty"`
SubDrop7Weight int32 `csv:"子掉落7权重,omitempty"`
SubDrop8Id int32 `csv:"子掉落8ID,omitempty"`
SubDrop8CountRange FloatArray `csv:"子掉落8数量区间,omitempty"`
SubDrop8Weight int32 `csv:"子掉落8权重,omitempty"`
SubDrop9Id int32 `csv:"子掉落9ID,omitempty"`
SubDrop9CountRange FloatArray `csv:"子掉落9数量区间,omitempty"`
SubDrop9Weight int32 `csv:"子掉落9权重,omitempty"`
SubDrop10Id int32 `csv:"子掉落10ID,omitempty"`
SubDrop10CountRange FloatArray `csv:"子掉落10数量区间,omitempty"`
SubDrop10Weight int32 `csv:"子掉落10权重,omitempty"`
SubDrop11Id int32 `csv:"子掉落11ID,omitempty"`
SubDrop11CountRange FloatArray `csv:"子掉落11数量区间,omitempty"`
SubDrop11Weight int32 `csv:"子掉落11权重,omitempty"`
SubDrop12Id int32 `csv:"子掉落12ID,omitempty"`
SubDrop12CountRange FloatArray `csv:"子掉落12数量区间,omitempty"`
SubDrop12Weight int32 `csv:"子掉落12权重,omitempty"`
SubDropList []*SubDrop // 子掉落列表
SubDropTotalWeight int32 // 总权重
}
func (g *GameDataConfig) loadDropData() {
g.DropDataMap = make(map[int32]*DropData)
fileNameList := []string{"DropLeafData.txt", "DropTreeData.txt"}
for _, fileName := range fileNameList {
dropDataList := make([]*DropData, 0)
readTable[DropData](g.txtPrefix+fileName, &dropDataList)
for _, dropData := range dropDataList {
// 子掉落列合并
dropData.SubDropList = make([]*SubDrop, 0)
if dropData.SubDrop1Id != 0 {
countRange := make([]int32, 0)
for _, v := range dropData.SubDrop1CountRange {
countRange = append(countRange, int32(v))
}
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
Id: dropData.SubDrop1Id,
CountRange: countRange,
Weight: dropData.SubDrop1Weight,
})
}
if dropData.SubDrop2Id != 0 {
countRange := make([]int32, 0)
for _, v := range dropData.SubDrop2CountRange {
countRange = append(countRange, int32(v))
}
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
Id: dropData.SubDrop2Id,
CountRange: countRange,
Weight: dropData.SubDrop2Weight,
})
}
if dropData.SubDrop3Id != 0 {
countRange := make([]int32, 0)
for _, v := range dropData.SubDrop3CountRange {
countRange = append(countRange, int32(v))
}
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
Id: dropData.SubDrop3Id,
CountRange: countRange,
Weight: dropData.SubDrop3Weight,
})
}
if dropData.SubDrop4Id != 0 {
countRange := make([]int32, 0)
for _, v := range dropData.SubDrop4CountRange {
countRange = append(countRange, int32(v))
}
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
Id: dropData.SubDrop4Id,
CountRange: countRange,
Weight: dropData.SubDrop4Weight,
})
}
if dropData.SubDrop5Id != 0 {
countRange := make([]int32, 0)
for _, v := range dropData.SubDrop5CountRange {
countRange = append(countRange, int32(v))
}
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
Id: dropData.SubDrop5Id,
CountRange: countRange,
Weight: dropData.SubDrop5Weight,
})
}
if dropData.SubDrop6Id != 0 {
countRange := make([]int32, 0)
for _, v := range dropData.SubDrop6CountRange {
countRange = append(countRange, int32(v))
}
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
Id: dropData.SubDrop6Id,
CountRange: countRange,
Weight: dropData.SubDrop6Weight,
})
}
if dropData.SubDrop7Id != 0 {
countRange := make([]int32, 0)
for _, v := range dropData.SubDrop7CountRange {
countRange = append(countRange, int32(v))
}
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
Id: dropData.SubDrop7Id,
CountRange: countRange,
Weight: dropData.SubDrop7Weight,
})
}
if dropData.SubDrop8Id != 0 {
countRange := make([]int32, 0)
for _, v := range dropData.SubDrop8CountRange {
countRange = append(countRange, int32(v))
}
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
Id: dropData.SubDrop8Id,
CountRange: countRange,
Weight: dropData.SubDrop8Weight,
})
}
if dropData.SubDrop9Id != 0 {
countRange := make([]int32, 0)
for _, v := range dropData.SubDrop9CountRange {
countRange = append(countRange, int32(v))
}
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
Id: dropData.SubDrop9Id,
CountRange: countRange,
Weight: dropData.SubDrop9Weight,
})
}
if dropData.SubDrop10Id != 0 {
countRange := make([]int32, 0)
for _, v := range dropData.SubDrop10CountRange {
countRange = append(countRange, int32(v))
}
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
Id: dropData.SubDrop10Id,
CountRange: countRange,
Weight: dropData.SubDrop10Weight,
})
}
if dropData.SubDrop11Id != 0 {
countRange := make([]int32, 0)
for _, v := range dropData.SubDrop11CountRange {
countRange = append(countRange, int32(v))
}
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
Id: dropData.SubDrop11Id,
CountRange: countRange,
Weight: dropData.SubDrop11Weight,
})
}
if dropData.SubDrop12Id != 0 {
countRange := make([]int32, 0)
for _, v := range dropData.SubDrop12CountRange {
countRange = append(countRange, int32(v))
}
dropData.SubDropList = append(dropData.SubDropList, &SubDrop{
Id: dropData.SubDrop12Id,
CountRange: countRange,
Weight: dropData.SubDrop12Weight,
})
}
if dropData.RandomType == RandomTypeChoose {
// 计算轮盘总权重
for _, subDrop := range dropData.SubDropList {
dropData.SubDropTotalWeight += subDrop.Weight
}
}
g.DropDataMap[dropData.DropId] = dropData
}
}
// 检查
for _, dropData := range g.DropDataMap {
if dropData.RandomType == RandomTypeIndep {
for _, subDrop := range dropData.SubDropList {
if subDrop.Weight > RandomTypeIndepWeight {
info := fmt.Sprintf("invalid weight for indep rand type, weight: %v, dropId: %v", subDrop.Weight, dropData.DropId)
panic(info)
}
}
}
for _, subDrop := range dropData.SubDropList {
// 掉落id优先在掉落表里找 找不到就去道具表里找
_, exist := g.DropDataMap[subDrop.Id]
if !exist {
_, exist := g.ItemDataMap[subDrop.Id]
if !exist {
info := fmt.Sprintf("drop item id not exist, itemId: %v, dropId: %v", subDrop.Id, dropData.DropId)
panic(info)
}
}
}
}
logger.Info("DropData count: %v", len(g.DropDataMap))
}
func GetDropDataById(dropId int32) *DropData {
return CONF.DropDataMap[dropId]
}
func GetDropDataMap() map[int32]*DropData {
return CONF.DropDataMap
}

View File

@@ -1,42 +0,0 @@
package gdconf
import (
"hk4e/pkg/logger"
)
// 当初写卡池算法的时候临时建立的表 以后再做迁移吧
type Drop struct {
DropId int32 `csv:"DropId"`
Weight int32 `csv:"Weight"`
Result int32 `csv:"Result"`
IsEnd bool `csv:"IsEnd"`
}
type DropGroupData struct {
DropId int32
WeightAll int32
DropConfig []*Drop
}
func (g *GameDataConfig) loadDropGroupData() {
g.DropGroupDataMap = make(map[int32]*DropGroupData)
fileNameList := []string{"DropGachaAvatarUp.csv", "DropGachaWeaponUp.csv", "DropGachaNormal.csv"}
for _, fileName := range fileNameList {
dropList := make([]*Drop, 0)
readExtCsv[Drop](g.extPrefix+fileName, &dropList)
for _, drop := range dropList {
dropGroupData, exist := g.DropGroupDataMap[drop.DropId]
if !exist {
dropGroupData = new(DropGroupData)
dropGroupData.DropId = drop.DropId
dropGroupData.WeightAll = 0
dropGroupData.DropConfig = make([]*Drop, 0)
g.DropGroupDataMap[drop.DropId] = dropGroupData
}
dropGroupData.WeightAll += drop.Weight
dropGroupData.DropConfig = append(dropGroupData.DropConfig, drop)
}
}
logger.Info("DropGroupData count: %v", len(g.DropGroupDataMap))
}

View File

@@ -16,9 +16,8 @@ func (g *GameDataConfig) loadFetterData() {
fileNameList := []string{"FettersData.txt", "FetterDataStory.txt", "FetterDataIformation.txt", "PhotographExpressionName.txt", "PhotographPoseName.txt"}
for _, fileName := range fileNameList {
fetterDataList := make([]*FetterData, 0)
readTable[FetterData](g.tablePrefix+fileName, &fetterDataList)
readTable[FetterData](g.txtPrefix+fileName, &fetterDataList)
for _, fetterData := range fetterDataList {
// list -> map
g.FetterDataMap[fetterData.FetterId] = fetterData
fetterIdList := g.FetterDataAvatarIdMap[fetterData.AvatarId]
if fetterIdList == nil {

View File

@@ -0,0 +1,42 @@
package gdconf
import (
"hk4e/pkg/logger"
)
// 当初写卡池算法的时候临时建立的表 以后再做迁移吧
type GachaDrop struct {
DropId int32 `csv:"DropId"`
Weight int32 `csv:"Weight"`
Result int32 `csv:"Result"`
IsEnd bool `csv:"IsEnd"`
}
type GachaDropGroupData struct {
DropId int32
WeightAll int32
DropConfig []*GachaDrop
}
func (g *GameDataConfig) loadGachaDropGroupData() {
g.GachaDropGroupDataMap = make(map[int32]*GachaDropGroupData)
fileNameList := []string{"GachaDropAvatarUp.csv", "GachaDropWeaponUp.csv", "GachaDropNormal.csv"}
for _, fileName := range fileNameList {
gachaDropList := make([]*GachaDrop, 0)
readExtCsv[GachaDrop](g.extPrefix+fileName, &gachaDropList)
for _, gachaDrop := range gachaDropList {
gachaDropGroupData, exist := g.GachaDropGroupDataMap[gachaDrop.DropId]
if !exist {
gachaDropGroupData = new(GachaDropGroupData)
gachaDropGroupData.DropId = gachaDrop.DropId
gachaDropGroupData.WeightAll = 0
gachaDropGroupData.DropConfig = make([]*GachaDrop, 0)
g.GachaDropGroupDataMap[gachaDrop.DropId] = gachaDropGroupData
}
gachaDropGroupData.WeightAll += gachaDrop.Weight
gachaDropGroupData.DropConfig = append(gachaDropGroupData.DropConfig, gachaDrop)
}
}
logger.Info("GachaDropGroupData count: %v", len(g.GachaDropGroupDataMap))
}

View File

@@ -27,26 +27,24 @@ var CONF_RELOAD *GameDataConfig = nil
type GameDataConfig struct {
// 配置表路径前缀
tablePrefix string
jsonPrefix string
luaPrefix string
extPrefix string
txtPrefix string
jsonPrefix string
luaPrefix string
extPrefix 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 // 场景标签
SceneLuaConfigMap map[int32]*SceneLuaConfig // 场景LUA配置
GroupMap map[int32]*Group // 场景LUA区块group索引
LuaStateLruMap map[int32]*LuaStateLru // 场景LUA虚拟机LRU内存淘汰
WorldAreaDataMap map[int32]*WorldAreaData // 世界区域
TriggerDataMap map[int32]*TriggerData // 场景LUA触发器
ScenePointMap map[int32]*ScenePoint // 场景传送点
SceneTagDataMap map[int32]*SceneTagData // 场景标签
GatherDataMap map[int32]*GatherData // 采集物
GatherDataPointTypeMap map[int32]*GatherData // 采集物场景节点索引
WorldAreaDataMap map[int32]*WorldAreaData // 世界区域
AvatarDataMap map[int32]*AvatarData // 角色
AvatarSkillDataMap map[int32]*AvatarSkillData // 角色技能
AvatarSkillDepotDataMap map[int32]*AvatarSkillDepotData // 角色技能库
FetterDataMap map[int32]*FetterData // 角色资料解锁
FetterDataAvatarIdMap map[int32][]int32 // 角色资料解锁角色id索引
ItemDataMap map[int32]*ItemData // 统一道具
@@ -61,7 +59,12 @@ type GameDataConfig struct {
ReliquaryMainDataMap map[int32]map[int32]*ReliquaryMainData // 圣遗物主属性
ReliquaryAffixDataMap map[int32]map[int32]*ReliquaryAffixData // 圣遗物追加属性
QuestDataMap map[int32]*QuestData // 任务
TriggerDataMap map[int32]*TriggerData // 场景LUA触发器
DropDataMap map[int32]*DropData // 掉落
MonsterDropDataMap map[string]map[int32]*MonsterDropData // 怪物掉落
ChestDropDataMap map[string]map[int32]*ChestDropData // 宝箱掉落
GCGCharDataMap map[int32]*GCGCharData // 七圣召唤角色卡牌
GCGSkillDataMap map[int32]*GCGSkillData // 七圣召唤卡牌技能
GachaDropGroupDataMap map[int32]*GachaDropGroupData // 卡池掉落组 临时的
}
func InitGameDataConfig() {
@@ -95,13 +98,13 @@ func (g *GameDataConfig) loadAll() {
panic(info)
}
g.tablePrefix = pathPrefix + "/txt"
dirInfo, err = os.Stat(g.tablePrefix)
g.txtPrefix = pathPrefix + "/txt"
dirInfo, err = os.Stat(g.txtPrefix)
if err != nil || !dirInfo.IsDir() {
info := fmt.Sprintf("open game data config txt dir error: %v", err)
panic(info)
}
g.tablePrefix += "/"
g.txtPrefix += "/"
g.jsonPrefix = pathPrefix + "/json"
dirInfo, err = os.Stat(g.jsonPrefix)
@@ -131,34 +134,35 @@ func (g *GameDataConfig) loadAll() {
}
func (g *GameDataConfig) load() {
g.loadSceneData() // 场景
g.loadSceneLuaConfig() // 场景LUA配置
g.loadTriggerData() // 场景LUA触发器
g.loadScenePoint() // 场景传送点
g.loadSceneTagData() // 场景标签
g.loadGatherData() // 采集物
g.loadWorldAreaData() // 世界区域
g.loadAvatarData() // 角色
g.loadAvatarSkillData() // 角色技能
g.loadAvatarSkillDepotData() // 角色技能库
g.loadDropGroupData() // 掉落组 卡池 临时的
g.loadGCGCharData() // 角色卡牌
g.loadGCGSkillData() // 卡牌技能
g.loadSceneData() // 场景
g.loadScenePoint() // 场景传送点
g.loadSceneTagData() // 场景地图图标
if config.GetConfig().Hk4e.LoadSceneLuaConfig {
g.loadSceneLuaConfig() // 场景LUA配置
}
g.loadWorldAreaData() // 世界区域
g.loadGatherData() // 采集物
g.loadFetterData() // 角色资料解锁
g.loadItemData() // 统一道具
g.loadAvatarLevelData() // 角色等级
g.loadAvatarPromoteData() // 角色突破
g.loadPlayerLevelData() // 玩家等级
g.loadWeaponLevelData() // 武器等级
g.loadWeaponPromoteData() // 武器突破
g.loadRewardData() // 奖励
g.loadAvatarCostumeData() // 角色时装
g.loadAvatarFlycloakData() // 角色风之翼
g.loadReliquaryMainData() // 圣遗物主属性
g.loadReliquaryAffixData() // 圣遗物追加属性
g.loadQuestData() // 任务
g.loadTriggerData() // 场景LUA触发器
g.loadFetterData() // 角色资料解锁
g.loadItemData() // 统一道具
g.loadAvatarLevelData() // 角色等级
g.loadAvatarPromoteData() // 角色突破
g.loadPlayerLevelData() // 玩家等级
g.loadWeaponLevelData() // 武器等级
g.loadWeaponPromoteData() // 武器突破
g.loadRewardData() // 奖励
g.loadAvatarCostumeData() // 角色时装
g.loadAvatarFlycloakData() // 角色风之翼
g.loadReliquaryMainData() // 圣遗物主属性
g.loadReliquaryAffixData() // 圣遗物追加属性
g.loadQuestData() // 任务
g.loadDropData() // 掉落
g.loadMonsterDropData() // 怪物掉落
g.loadChestDropData() // 宝箱掉落
g.loadGCGCharData() // 七圣召唤角色卡牌
g.loadGCGSkillData() // 七圣召唤卡牌技能
g.loadGachaDropGroupData() // 卡池掉落组 临时的
}
// CSV相关
@@ -191,6 +195,22 @@ func (a *IntArray) UnmarshalCSV(data []byte) error {
return nil
}
type FloatArray []float32
func (a *FloatArray) UnmarshalCSV(data []byte) error {
str := string(data)
str = strings.ReplaceAll(str, " ", "")
floatStrList := splitStringArray(str)
for _, floatStr := range floatStrList {
v, err := strconv.ParseFloat(floatStr, 32)
if err != nil {
panic(err)
}
*a = append(*a, float32(v))
}
return nil
}
func readExtCsv[T any](tablePath string, table *[]*T) {
fileData, err := os.ReadFile(tablePath)
if err != nil {
@@ -260,6 +280,9 @@ func initLuaState(luaState *lua.LState) {
luaState.SetField(eventType, "EVENT_NONE", lua.LNumber(constant.LUA_EVENT_NONE))
luaState.SetField(eventType, "EVENT_ENTER_REGION", lua.LNumber(constant.LUA_EVENT_ENTER_REGION))
luaState.SetField(eventType, "EVENT_LEAVE_REGION", lua.LNumber(constant.LUA_EVENT_LEAVE_REGION))
luaState.SetField(eventType, "EVENT_ANY_MONSTER_DIE", lua.LNumber(constant.LUA_EVENT_ANY_MONSTER_DIE))
luaState.SetField(eventType, "EVENT_ANY_MONSTER_LIVE", lua.LNumber(constant.LUA_EVENT_ANY_MONSTER_LIVE))
luaState.SetField(eventType, "EVENT_QUEST_START", lua.LNumber(constant.LUA_EVENT_QUEST_START))
entityType := luaState.NewTable()
luaState.SetGlobal("EntityType", entityType)
@@ -287,11 +310,17 @@ func initLuaState(luaState *lua.LState) {
gadgetState := luaState.NewTable()
luaState.SetGlobal("GadgetState", gadgetState)
luaState.SetField(gadgetState, "NONE", lua.LNumber(0))
luaState.SetField(gadgetState, "Default", lua.LNumber(constant.GADGET_STATE_DEFAULT))
luaState.SetField(gadgetState, "ChestLocked", lua.LNumber(constant.GADGET_STATE_CHEST_LOCKED))
luaState.SetField(gadgetState, "GearStart", lua.LNumber(constant.GADGET_STATE_GEAR_START))
luaState.SetField(gadgetState, "GearStop", lua.LNumber(constant.GADGET_STATE_GEAR_STOP))
visionLevelType := luaState.NewTable()
luaState.SetGlobal("VisionLevelType", visionLevelType)
luaState.SetField(visionLevelType, "NONE", lua.LNumber(0))
luaState.SetField(visionLevelType, "VISION_LEVEL_NEARBY", lua.LNumber(1))
luaState.SetField(visionLevelType, "VISION_LEVEL_NORMAL", lua.LNumber(2))
luaState.SetField(visionLevelType, "VISION_LEVEL_REMOTE", lua.LNumber(3))
luaState.SetField(visionLevelType, "VISION_LEVEL_LITTLE_REMOTE", lua.LNumber(4))
}
func newLuaState(luaStr string) *lua.LState {

View File

@@ -1,54 +0,0 @@
AvatarId,GachaItemId,Name
int32,int32,string
角色id,卡池道具id,角色名称
10000002,1002,神里绫华
10000003,1003,
10000006,1006,丽莎
10000014,1014,芭芭拉
10000015,1015,凯亚
10000016,1016,迪卢克
10000020,1020,雷泽
10000021,1021,安柏
10000022,1022,温迪
10000023,1023,香菱
10000024,1024,北斗
10000025,1025,行秋
10000026,1026,
10000027,1027,凝光
10000029,1029,可莉
10000030,1030,钟离
10000031,1031,菲谢尔
10000032,1032,班尼特
10000033,1033,达达利亚
10000034,1034,诺艾尔
10000035,1035,七七
10000036,1036,重云
10000037,1037,甘雨
10000038,1038,阿贝多
10000039,1039,迪奥娜
10000041,1041,莫娜
10000042,1042,刻晴
10000043,1043,砂糖
10000044,1044,辛焱
10000045,1045,罗莎莉亚
10000046,1046,胡桃
10000047,1047,枫原万叶
10000048,1048,烟绯
10000049,1049,宵宫
10000050,1050,托马
10000051,1051,优菈
10000052,1052,雷电将军
10000053,1053,早柚
10000054,1054,珊瑚宫心海
10000055,1055,五郎
10000056,1056,九条裟罗
10000057,1057,荒泷一斗
10000058,1058,八重神子
10000062,1062,埃洛伊
10000063,1063,申鹤
10000064,1064,云堇
10000065,1065,久歧忍
10000066,1066,神里绫人
10000067,1067,柯莱
10000068,1068,多莉
10000069,1069,提纳里
1 AvatarId GachaItemId Name
2 int32 int32 string
3 角色id 卡池道具id 角色名称
4 10000002 1002 神里绫华
5 10000003 1003
6 10000006 1006 丽莎
7 10000014 1014 芭芭拉
8 10000015 1015 凯亚
9 10000016 1016 迪卢克
10 10000020 1020 雷泽
11 10000021 1021 安柏
12 10000022 1022 温迪
13 10000023 1023 香菱
14 10000024 1024 北斗
15 10000025 1025 行秋
16 10000026 1026
17 10000027 1027 凝光
18 10000029 1029 可莉
19 10000030 1030 钟离
20 10000031 1031 菲谢尔
21 10000032 1032 班尼特
22 10000033 1033 达达利亚
23 10000034 1034 诺艾尔
24 10000035 1035 七七
25 10000036 1036 重云
26 10000037 1037 甘雨
27 10000038 1038 阿贝多
28 10000039 1039 迪奥娜
29 10000041 1041 莫娜
30 10000042 1042 刻晴
31 10000043 1043 砂糖
32 10000044 1044 辛焱
33 10000045 1045 罗莎莉亚
34 10000046 1046 胡桃
35 10000047 1047 枫原万叶
36 10000048 1048 烟绯
37 10000049 1049 宵宫
38 10000050 1050 托马
39 10000051 1051 优菈
40 10000052 1052 雷电将军
41 10000053 1053 早柚
42 10000054 1054 珊瑚宫心海
43 10000055 1055 五郎
44 10000056 1056 九条裟罗
45 10000057 1057 荒泷一斗
46 10000058 1058 八重神子
47 10000062 1062 埃洛伊
48 10000063 1063 申鹤
49 10000064 1064 云堇
50 10000065 1065 久歧忍
51 10000066 1066 神里绫人
52 10000067 1067 柯莱
53 10000068 1068 多莉
54 10000069 1069 提纳里

View File

@@ -25,7 +25,7 @@ func TestInitGameDataConfig(t *testing.T) {
logger.Info("start load conf")
InitGameDataConfig()
logger.Info("load conf finish")
time.Sleep(time.Second)
time.Sleep(time.Minute)
}
func CheckJsonLoop(path string, errorJsonFileList *[]string, totalJsonFileCount *int) {

View File

@@ -8,17 +8,16 @@ import (
type GatherData struct {
PointType int32 `csv:"挂节点类型"`
GatherId int32 `csv:"ID"`
GadgetId int32 `csv:"采集物ID"`
ItemId int32 `csv:"获得物品ID"`
GadgetId int32 `csv:"采集物ID,omitempty"`
ItemId int32 `csv:"获得物品ID,omitempty"`
}
func (g *GameDataConfig) loadGatherData() {
g.GatherDataMap = make(map[int32]*GatherData)
gatherDataList := make([]*GatherData, 0)
readTable[GatherData](g.tablePrefix+"GatherData.txt", &gatherDataList)
readTable[GatherData](g.txtPrefix+"GatherData.txt", &gatherDataList)
g.GatherDataPointTypeMap = make(map[int32]*GatherData)
for _, gatherData := range gatherDataList {
// list -> map
g.GatherDataMap[gatherData.GatherId] = gatherData
g.GatherDataPointTypeMap[gatherData.PointType] = gatherData
}

View File

@@ -22,7 +22,7 @@ type GCGCharData struct {
func (g *GameDataConfig) loadGCGCharData() {
g.GCGCharDataMap = make(map[int32]*GCGCharData)
gcgCharDataList := make([]*GCGCharData, 0)
readTable[GCGCharData](g.tablePrefix+"GCGCharData.txt", &gcgCharDataList)
readTable[GCGCharData](g.txtPrefix+"GCGCharData.txt", &gcgCharDataList)
for _, gcgCharData := range gcgCharDataList {
// 将TagId整合进TagList
gcgCharData.TagList = make([]uint32, 0, 5)
@@ -35,7 +35,6 @@ func (g *GameDataConfig) loadGCGCharData() {
}
gcgCharData.TagList = append(gcgCharData.TagList, uint32(tagId))
}
// list -> map
g.GCGCharDataMap[gcgCharData.CharId] = gcgCharData
}
logger.Info("GCGCharData count: %v", len(g.GCGCharDataMap))

View File

@@ -35,7 +35,7 @@ type ConfigSkillEffectValue struct {
func (g *GameDataConfig) loadGCGSkillData() {
g.GCGSkillDataMap = make(map[int32]*GCGSkillData)
gcgSkillDataList := make([]*GCGSkillData, 0)
readTable[GCGSkillData](g.tablePrefix+"GCGSkillData.txt", &gcgSkillDataList)
readTable[GCGSkillData](g.txtPrefix+"GCGSkillData.txt", &gcgSkillDataList)
for _, gcgSkillData := range gcgSkillDataList {
// 技能消耗整合进CostMap
gcgSkillData.CostMap = map[uint32]uint32{
@@ -97,7 +97,6 @@ func (g *GameDataConfig) loadGCGSkillData() {
}
}
}
// list -> map
g.GCGSkillDataMap[gcgSkillData.SkillId] = gcgSkillData
}
logger.Info("GCGSkillData count: %v", len(g.GCGSkillDataMap))

View File

@@ -38,9 +38,8 @@ func (g *GameDataConfig) loadItemData() {
fileNameList := []string{"MaterialData.txt", "WeaponData.txt", "ReliquaryData.txt", "FurnitureExcelData.txt"}
for _, fileName := range fileNameList {
itemDataList := make([]*ItemData, 0)
readTable[ItemData](g.tablePrefix+fileName, &itemDataList)
readTable[ItemData](g.txtPrefix+fileName, &itemDataList)
for _, itemData := range itemDataList {
// list -> map
itemData.SkillAffix = make([]int32, 0)
if itemData.SkillAffix1 != 0 {
itemData.SkillAffix = append(itemData.SkillAffix, itemData.SkillAffix1)

View File

@@ -0,0 +1,39 @@
package gdconf
import (
"hk4e/pkg/logger"
)
// MonsterDropData 怪物掉落配置表
type MonsterDropData struct {
Level int32 `csv:"最小等级"`
DropTag string `csv:"总索引"`
DropId int32 `csv:"掉落ID,omitempty"`
DropCount int32 `csv:"掉落次数,omitempty"`
}
func (g *GameDataConfig) loadMonsterDropData() {
g.MonsterDropDataMap = make(map[string]map[int32]*MonsterDropData)
monsterDropDataList := make([]*MonsterDropData, 0)
readTable[MonsterDropData](g.txtPrefix+"MonsterDropData.txt", &monsterDropDataList)
for _, monsterDropData := range monsterDropDataList {
_, exist := g.MonsterDropDataMap[monsterDropData.DropTag]
if !exist {
g.MonsterDropDataMap[monsterDropData.DropTag] = make(map[int32]*MonsterDropData)
}
g.MonsterDropDataMap[monsterDropData.DropTag][monsterDropData.Level] = monsterDropData
}
logger.Info("MonsterDropData count: %v", len(g.MonsterDropDataMap))
}
func GetMonsterDropDataByDropTagAndLevel(dropTag string, level int32) *MonsterDropData {
value, exist := CONF.MonsterDropDataMap[dropTag]
if !exist {
return nil
}
return value[level]
}
func GetMonsterDropDataMap() map[string]map[int32]*MonsterDropData {
return CONF.MonsterDropDataMap
}

View File

@@ -13,9 +13,8 @@ type PlayerLevelData struct {
func (g *GameDataConfig) loadPlayerLevelData() {
g.PlayerLevelDataMap = make(map[int32]*PlayerLevelData)
playerLevelDataList := make([]*PlayerLevelData, 0)
readTable[PlayerLevelData](g.tablePrefix+"PlayerLevelData.txt", &playerLevelDataList)
readTable[PlayerLevelData](g.txtPrefix+"PlayerLevelData.txt", &playerLevelDataList)
for _, playerLevelData := range playerLevelDataList {
// list -> map
g.PlayerLevelDataMap[playerLevelData.Level] = playerLevelData
}
logger.Info("PlayerLevelData count: %v", len(g.PlayerLevelDataMap))

View File

@@ -75,9 +75,8 @@ func (g *GameDataConfig) loadQuestData() {
fileNameList := []string{"QuestData.txt", "QuestData_Exported.txt"}
for _, fileName := range fileNameList {
questDataList := make([]*QuestData, 0)
readTable[QuestData](g.tablePrefix+fileName, &questDataList)
readTable[QuestData](g.txtPrefix+fileName, &questDataList)
for _, questData := range questDataList {
// list -> map
// 领取条件
questData.AcceptCondList = make([]*QuestCond, 0)
if questData.AcceptCondType1 != 0 {

View File

@@ -15,14 +15,13 @@ type ReliquaryAffixData struct {
func (g *GameDataConfig) loadReliquaryAffixData() {
g.ReliquaryAffixDataMap = make(map[int32]map[int32]*ReliquaryAffixData)
reliquaryAffixDataList := make([]*ReliquaryAffixData, 0)
readTable[ReliquaryAffixData](g.tablePrefix+"ReliquaryAffixData.txt", &reliquaryAffixDataList)
readTable[ReliquaryAffixData](g.txtPrefix+"ReliquaryAffixData.txt", &reliquaryAffixDataList)
for _, reliquaryAffixData := range reliquaryAffixDataList {
// 通过主属性库ID找到
_, ok := g.ReliquaryAffixDataMap[reliquaryAffixData.AppendPropDepotId]
if !ok {
g.ReliquaryAffixDataMap[reliquaryAffixData.AppendPropDepotId] = make(map[int32]*ReliquaryAffixData)
}
// list -> map
g.ReliquaryAffixDataMap[reliquaryAffixData.AppendPropDepotId][reliquaryAffixData.AppendPropId] = reliquaryAffixData
}
logger.Info("ReliquaryAffixData count: %v", len(g.ReliquaryAffixDataMap))

View File

@@ -15,14 +15,13 @@ type ReliquaryMainData struct {
func (g *GameDataConfig) loadReliquaryMainData() {
g.ReliquaryMainDataMap = make(map[int32]map[int32]*ReliquaryMainData)
reliquaryMainDataList := make([]*ReliquaryMainData, 0)
readTable[ReliquaryMainData](g.tablePrefix+"ReliquaryMainData.txt", &reliquaryMainDataList)
readTable[ReliquaryMainData](g.txtPrefix+"ReliquaryMainData.txt", &reliquaryMainDataList)
for _, reliquaryMainData := range reliquaryMainDataList {
// 通过主属性库ID找到
_, ok := g.ReliquaryMainDataMap[reliquaryMainData.MainPropDepotId]
if !ok {
g.ReliquaryMainDataMap[reliquaryMainData.MainPropDepotId] = make(map[int32]*ReliquaryMainData)
}
// list -> map
g.ReliquaryMainDataMap[reliquaryMainData.MainPropDepotId][reliquaryMainData.MainPropId] = reliquaryMainData
}
logger.Info("ReliquaryMainData count: %v", len(g.ReliquaryMainDataMap))

View File

@@ -32,9 +32,8 @@ type RewardData struct {
func (g *GameDataConfig) loadRewardData() {
g.RewardDataMap = make(map[int32]*RewardData)
rewardDataList := make([]*RewardData, 0)
readTable[RewardData](g.tablePrefix+"RewardData.txt", &rewardDataList)
readTable[RewardData](g.txtPrefix+"RewardData.txt", &rewardDataList)
for _, rewardData := range rewardDataList {
// list -> map
// 奖励物品整合
rewardData.RewardItemMap = map[uint32]uint32{
uint32(rewardData.RewardItem1ID): uint32(rewardData.RewardItem1Count),

View File

@@ -13,9 +13,8 @@ type SceneData struct {
func (g *GameDataConfig) loadSceneData() {
g.SceneDataMap = make(map[int32]*SceneData)
sceneDataList := make([]*SceneData, 0)
readTable[SceneData](g.tablePrefix+"SceneData.txt", &sceneDataList)
readTable[SceneData](g.txtPrefix+"SceneData.txt", &sceneDataList)
for _, sceneData := range sceneDataList {
// list -> map
g.SceneDataMap[sceneData.SceneId] = sceneData
}
logger.Info("SceneData count: %v", len(g.SceneDataMap))

View File

@@ -5,9 +5,9 @@ import (
"sort"
"strconv"
"sync"
"sync/atomic"
"time"
"hk4e/common/config"
"hk4e/pkg/logger"
lua "github.com/yuin/gopher-lua"
@@ -19,8 +19,6 @@ const (
SceneGroupLoaderLimit = 4 // 加载文件的并发数 此操作很耗内存 调大之前请确保你的机器内存足够
)
var OBJECT_ID_COUNTER uint64
type SceneLuaConfig struct {
Id int32
SceneConfig *SceneConfig // 地图配置
@@ -55,77 +53,27 @@ type BlockRange struct {
}
type Group struct {
Id int32 `json:"id"`
RefreshId int32 `json:"refresh_id"`
Area int32 `json:"area"`
Pos *Vector `json:"pos"`
DynamicLoad bool `json:"dynamic_load"`
IsReplaceable *Replaceable `json:"is_replaceable"`
MonsterList []*Monster `json:"monsters"` // 怪物
NpcList []*Npc `json:"npcs"` // NPC
GadgetList []*Gadget `json:"gadgets"` // 物件
RegionList []*Region `json:"regions"`
TriggerList []*Trigger `json:"triggers"`
LuaStr string `json:"-"`
LuaState *lua.LState `json:"-"`
Id int32 `json:"id"`
RefreshId int32 `json:"refresh_id"`
Area int32 `json:"area"`
Pos *Vector `json:"pos"`
DynamicLoad bool `json:"dynamic_load"`
IsReplaceable *Replaceable `json:"is_replaceable"`
MonsterMap map[int32]*Monster `json:"-"` // 怪物
NpcMap map[int32]*Npc `json:"-"` // NPC
GadgetMap map[int32]*Gadget `json:"-"` // 物件
RegionMap map[int32]*Region `json:"-"` // 区域
TriggerMap map[string]*Trigger `json:"-"` // 触发器
GroupInitConfig *GroupInitConfig `json:"-"` // 初始化配置
SuiteList []*Suite `json:"-"` // 小组配置
LuaStr string `json:"-"` // LUA原始字符串缓存
LuaState *lua.LState `json:"-"` // LUA虚拟机实例
}
const (
LuaStateLruKeepNum = 1000
)
type LuaStateLru struct {
GroupId int32
AccessTime int64
}
type LuaStateLruList []*LuaStateLru
func (l LuaStateLruList) Len() int {
return len(l)
}
func (l LuaStateLruList) Less(i, j int) bool {
return l[i].AccessTime < l[j].AccessTime
}
func (l LuaStateLruList) Swap(i, j int) {
l[i], l[j] = l[j], l[i]
}
func LuaStateLruRemove() {
removeNum := len(CONF.LuaStateLruMap) - LuaStateLruKeepNum
if removeNum <= 0 {
return
}
luaStateLruList := make(LuaStateLruList, 0)
for _, luaStateLru := range CONF.LuaStateLruMap {
luaStateLruList = append(luaStateLruList, luaStateLru)
}
sort.Stable(luaStateLruList)
for i := 0; i < removeNum; i++ {
luaStateLru := luaStateLruList[i]
group := GetSceneGroup(luaStateLru.GroupId)
group.LuaState = nil
delete(CONF.LuaStateLruMap, luaStateLru.GroupId)
}
logger.Info("lua state lru remove finish, remove num: %v", removeNum)
}
func (g *Group) GetLuaState() *lua.LState {
CONF.LuaStateLruMap[g.Id] = &LuaStateLru{
GroupId: g.Id,
AccessTime: time.Now().UnixMilli(),
}
if g.LuaState == nil {
g.LuaState = newLuaState(g.LuaStr)
scriptLib := g.LuaState.NewTable()
g.LuaState.SetGlobal("ScriptLib", scriptLib)
for _, scriptLibFunc := range SCRIPT_LIB_FUNC_LIST {
g.LuaState.SetField(scriptLib, scriptLibFunc.fnName, g.LuaState.NewFunction(scriptLibFunc.fn))
}
}
return g.LuaState
type GroupInitConfig struct {
Suite int32 `json:"suite"`
EndSuite int32 `json:"end_suite"`
RandSuite bool `json:"rand_suite"`
}
type Replaceable struct {
@@ -141,7 +89,7 @@ type Monster struct {
Rot *Vector `json:"rot"`
Level int32 `json:"level"`
AreaId int32 `json:"area_id"`
ObjectId uint64 `json:"-"`
DropTag string `json:"drop_tag"` // 关联MonsterDropData表
}
type Npc struct {
@@ -150,18 +98,19 @@ type Npc struct {
Pos *Vector `json:"pos"`
Rot *Vector `json:"rot"`
AreaId int32 `json:"area_id"`
ObjectId uint64 `json:"-"`
}
type Gadget struct {
ConfigId int32 `json:"config_id"`
GadgetId int32 `json:"gadget_id"`
Pos *Vector `json:"pos"`
Rot *Vector `json:"rot"`
Level int32 `json:"level"`
AreaId int32 `json:"area_id"`
PointType int32 `json:"point_type"` // 关联GatherData表
ObjectId uint64 `json:"-"`
ConfigId int32 `json:"config_id"`
GadgetId int32 `json:"gadget_id"`
Pos *Vector `json:"pos"`
Rot *Vector `json:"rot"`
Level int32 `json:"level"`
AreaId int32 `json:"area_id"`
PointType int32 `json:"point_type"` // 关联GatherData表
State int32 `json:"state"`
VisionLevel int32 `json:"vision_level"`
DropTag string `json:"drop_tag"`
}
type Region struct {
@@ -185,6 +134,22 @@ type Trigger struct {
TriggerCount int32 `json:"trigger_count"`
}
type SuiteLuaTable struct {
MonsterConfigIdList any `json:"monsters"` // 怪物
GadgetConfigIdList any `json:"gadgets"` // 物件
RegionConfigIdList any `json:"regions"` // 区域
TriggerNameList any `json:"triggers"` // 触发器
RandWeight int32 `json:"rand_weight"`
}
type Suite struct {
MonsterConfigIdList []int32
GadgetConfigIdList []int32
RegionConfigIdList []int32
TriggerNameList []string
RandWeight int32
}
func (g *GameDataConfig) loadGroup(group *Group, block *Block, sceneId int32, blockId int32) {
sceneLuaPrefix := g.luaPrefix + "scene/"
sceneIdStr := strconv.Itoa(int(sceneId))
@@ -197,55 +162,120 @@ func (g *GameDataConfig) loadGroup(group *Group, block *Block, sceneId int32, bl
}
group.LuaStr = string(groupLuaData)
luaState := newLuaState(group.LuaStr)
// init_config
group.GroupInitConfig = new(GroupInitConfig)
ok := getSceneLuaConfigTable[*GroupInitConfig](luaState, "init_config", group.GroupInitConfig)
if !ok {
logger.Error("get init_config object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
luaState.Close()
return
}
// monsters
group.MonsterList = make([]*Monster, 0)
ok := getSceneLuaConfigTable[*[]*Monster](luaState, "monsters", &group.MonsterList)
monsterList := make([]*Monster, 0)
ok = getSceneLuaConfigTable[*[]*Monster](luaState, "monsters", &monsterList)
if !ok {
logger.Error("get monsters object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
luaState.Close()
return
}
for _, monster := range group.MonsterList {
monster.ObjectId = atomic.AddUint64(&OBJECT_ID_COUNTER, 1)
group.MonsterMap = make(map[int32]*Monster)
for _, monster := range monsterList {
group.MonsterMap[monster.ConfigId] = monster
}
// npcs
group.NpcList = make([]*Npc, 0)
ok = getSceneLuaConfigTable[*[]*Npc](luaState, "npcs", &group.NpcList)
npcList := make([]*Npc, 0)
ok = getSceneLuaConfigTable[*[]*Npc](luaState, "npcs", &npcList)
if !ok {
logger.Error("get npcs object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
luaState.Close()
return
}
for _, npc := range group.NpcList {
npc.ObjectId = atomic.AddUint64(&OBJECT_ID_COUNTER, 1)
group.NpcMap = make(map[int32]*Npc)
for _, npc := range npcList {
group.NpcMap[npc.ConfigId] = npc
}
// gadgets
group.GadgetList = make([]*Gadget, 0)
ok = getSceneLuaConfigTable[*[]*Gadget](luaState, "gadgets", &group.GadgetList)
gadgetList := make([]*Gadget, 0)
ok = getSceneLuaConfigTable[*[]*Gadget](luaState, "gadgets", &gadgetList)
if !ok {
logger.Error("get gadgets object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
luaState.Close()
return
}
for _, gadget := range group.GadgetList {
gadget.ObjectId = atomic.AddUint64(&OBJECT_ID_COUNTER, 1)
group.GadgetMap = make(map[int32]*Gadget)
for _, gadget := range gadgetList {
group.GadgetMap[gadget.ConfigId] = gadget
}
// regions
group.RegionList = make([]*Region, 0)
ok = getSceneLuaConfigTable[*[]*Region](luaState, "regions", &group.RegionList)
regionList := make([]*Region, 0)
ok = getSceneLuaConfigTable[*[]*Region](luaState, "regions", &regionList)
if !ok {
logger.Error("get regions object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
luaState.Close()
return
}
group.RegionMap = make(map[int32]*Region)
for _, region := range regionList {
group.RegionMap[region.ConfigId] = region
}
// triggers
group.TriggerList = make([]*Trigger, 0)
ok = getSceneLuaConfigTable[*[]*Trigger](luaState, "triggers", &group.TriggerList)
triggerList := make([]*Trigger, 0)
ok = getSceneLuaConfigTable[*[]*Trigger](luaState, "triggers", &triggerList)
if !ok {
logger.Error("get triggers object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
luaState.Close()
return
}
group.TriggerMap = make(map[string]*Trigger)
for _, trigger := range triggerList {
group.TriggerMap[trigger.Name] = trigger
}
// suites
suiteLuaTableList := make([]*SuiteLuaTable, 0)
ok = getSceneLuaConfigTable[*[]*SuiteLuaTable](luaState, "suites", &suiteLuaTableList)
if !ok {
logger.Error("get suites object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
luaState.Close()
return
}
if len(suiteLuaTableList) == 0 {
logger.Info("get suites object is nil, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
}
group.SuiteList = make([]*Suite, 0)
for _, suiteLuaTable := range suiteLuaTableList {
suite := &Suite{
MonsterConfigIdList: make([]int32, 0),
GadgetConfigIdList: make([]int32, 0),
RegionConfigIdList: make([]int32, 0),
TriggerNameList: make([]string, 0),
RandWeight: suiteLuaTable.RandWeight,
}
idAnyList, ok := suiteLuaTable.MonsterConfigIdList.([]any)
if ok {
for _, idAny := range idAnyList {
suite.MonsterConfigIdList = append(suite.MonsterConfigIdList, int32(idAny.(float64)))
}
}
idAnyList, ok = suiteLuaTable.GadgetConfigIdList.([]any)
if ok {
for _, idAny := range idAnyList {
suite.GadgetConfigIdList = append(suite.GadgetConfigIdList, int32(idAny.(float64)))
}
}
idAnyList, ok = suiteLuaTable.RegionConfigIdList.([]any)
if ok {
for _, idAny := range idAnyList {
suite.RegionConfigIdList = append(suite.RegionConfigIdList, int32(idAny.(float64)))
}
}
nameAnyList, ok := suiteLuaTable.TriggerNameList.([]any)
if ok {
for _, nameAny := range nameAnyList {
suite.TriggerNameList = append(suite.TriggerNameList, nameAny.(string))
}
}
group.SuiteList = append(group.SuiteList, suite)
}
luaState.Close()
block.groupMapLoadLock.Lock()
block.GroupMap[group.Id] = group
@@ -253,10 +283,12 @@ func (g *GameDataConfig) loadGroup(group *Group, block *Block, sceneId int32, bl
}
func (g *GameDataConfig) loadSceneLuaConfig() {
OBJECT_ID_COUNTER = 0
g.SceneLuaConfigMap = make(map[int32]*SceneLuaConfig)
g.GroupMap = make(map[int32]*Group)
g.LuaStateLruMap = make(map[int32]*LuaStateLru)
if !config.GetConfig().Hk4e.LoadSceneLuaConfig {
return
}
sceneLuaPrefix := g.luaPrefix + "scene/"
for _, sceneData := range g.SceneDataMap {
sceneId := sceneData.SceneId
@@ -345,9 +377,9 @@ func (g *GameDataConfig) loadSceneLuaConfig() {
for _, scene := range g.SceneLuaConfigMap {
for _, block := range scene.BlockMap {
for _, group := range block.GroupMap {
monsterCount += len(group.MonsterList)
npcCount += len(group.NpcList)
gadgetCount += len(group.GadgetList)
monsterCount += len(group.MonsterMap)
npcCount += len(group.NpcMap)
gadgetCount += len(group.GadgetMap)
groupCount++
}
blockCount++
@@ -373,3 +405,61 @@ func GetSceneGroup(groupId int32) *Group {
}
return groupConfig
}
const (
LuaStateLruKeepNum = 10
)
type LuaStateLru struct {
GroupId int32
AccessTime int64
}
type LuaStateLruList []*LuaStateLru
func (l LuaStateLruList) Len() int {
return len(l)
}
func (l LuaStateLruList) Less(i, j int) bool {
return l[i].AccessTime < l[j].AccessTime
}
func (l LuaStateLruList) Swap(i, j int) {
l[i], l[j] = l[j], l[i]
}
func LuaStateLruRemove() {
removeNum := len(CONF.LuaStateLruMap) - LuaStateLruKeepNum
if removeNum <= 0 {
return
}
luaStateLruList := make(LuaStateLruList, 0)
for _, luaStateLru := range CONF.LuaStateLruMap {
luaStateLruList = append(luaStateLruList, luaStateLru)
}
sort.Stable(luaStateLruList)
for i := 0; i < removeNum; i++ {
luaStateLru := luaStateLruList[i]
group := GetSceneGroup(luaStateLru.GroupId)
group.LuaState = nil
delete(CONF.LuaStateLruMap, luaStateLru.GroupId)
}
logger.Info("lua state lru remove finish, remove num: %v", removeNum)
}
func (g *Group) GetLuaState() *lua.LState {
CONF.LuaStateLruMap[g.Id] = &LuaStateLru{
GroupId: g.Id,
AccessTime: time.Now().UnixMilli(),
}
if g.LuaState == nil {
g.LuaState = newLuaState(g.LuaStr)
scriptLib := g.LuaState.NewTable()
g.LuaState.SetGlobal("ScriptLib", scriptLib)
for _, scriptLibFunc := range SCRIPT_LIB_FUNC_LIST {
g.LuaState.SetField(scriptLib, scriptLibFunc.fnName, g.LuaState.NewFunction(scriptLibFunc.fn))
}
}
return g.LuaState
}

View File

@@ -13,9 +13,8 @@ type SceneTagData struct {
func (g *GameDataConfig) loadSceneTagData() {
g.SceneTagDataMap = make(map[int32]*SceneTagData)
sceneTagDataList := make([]*SceneTagData, 0)
readTable[SceneTagData](g.tablePrefix+"SceneTagData.txt", &sceneTagDataList)
readTable[SceneTagData](g.txtPrefix+"SceneTagData.txt", &sceneTagDataList)
for _, sceneTagData := range sceneTagDataList {
// list -> map
g.SceneTagDataMap[sceneTagData.SceneTagId] = sceneTagData
}
logger.Info("SceneTagData count: %v", len(g.SceneTagDataMap))

View File

@@ -15,7 +15,7 @@ type TriggerData struct {
func (g *GameDataConfig) loadTriggerData() {
g.TriggerDataMap = make(map[int32]*TriggerData)
triggerDataList := make([]*TriggerData, 0)
readTable[TriggerData](g.tablePrefix+"TriggerData.txt", &triggerDataList)
readTable[TriggerData](g.txtPrefix+"TriggerData.txt", &triggerDataList)
for _, triggerData := range triggerDataList {
g.TriggerDataMap[triggerData.TriggerId] = triggerData
}

View File

@@ -19,9 +19,8 @@ type WeaponLevelData struct {
func (g *GameDataConfig) loadWeaponLevelData() {
g.WeaponLevelDataMap = make(map[int32]*WeaponLevelData)
weaponLevelDataList := make([]*WeaponLevelData, 0)
readTable[WeaponLevelData](g.tablePrefix+"WeaponLevelData.txt", &weaponLevelDataList)
readTable[WeaponLevelData](g.txtPrefix+"WeaponLevelData.txt", &weaponLevelDataList)
for _, weaponLevelData := range weaponLevelDataList {
// list -> map
weaponLevelData.ExpByStarMap = map[uint32]uint32{
1: uint32(weaponLevelData.ExpByStar1),
2: uint32(weaponLevelData.ExpByStar2),

View File

@@ -24,9 +24,8 @@ type WeaponPromoteData struct {
func (g *GameDataConfig) loadWeaponPromoteData() {
g.WeaponPromoteDataMap = make(map[int32]map[int32]*WeaponPromoteData)
weaponPromoteDataList := make([]*WeaponPromoteData, 0)
readTable[WeaponPromoteData](g.tablePrefix+"WeaponPromoteData.txt", &weaponPromoteDataList)
readTable[WeaponPromoteData](g.txtPrefix+"WeaponPromoteData.txt", &weaponPromoteDataList)
for _, weaponPromoteData := range weaponPromoteDataList {
// list -> map
_, ok := g.WeaponPromoteDataMap[weaponPromoteData.PromoteId]
if !ok {
g.WeaponPromoteDataMap[weaponPromoteData.PromoteId] = make(map[int32]*WeaponPromoteData)

View File

@@ -15,9 +15,8 @@ type WorldAreaData struct {
func (g *GameDataConfig) loadWorldAreaData() {
g.WorldAreaDataMap = make(map[int32]*WorldAreaData)
worldAreaDataList := make([]*WorldAreaData, 0)
readTable[WorldAreaData](g.tablePrefix+"WorldAreaData.txt", &worldAreaDataList)
readTable[WorldAreaData](g.txtPrefix+"WorldAreaData.txt", &worldAreaDataList)
for _, worldAreaData := range worldAreaDataList {
// list -> map
g.WorldAreaDataMap[worldAreaData.WorldAreaId] = worldAreaData
}
logger.Info("WorldAreaData count: %v", len(g.WorldAreaDataMap))