场景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

@@ -0,0 +1,24 @@
package constant
const (
GADGET_STATE_DEFAULT = 0
GADGET_STATE_GATHER_DROP = 1
GADGET_STATE_CHEST_LOCKED = 101
GADGET_STATE_CHEST_OPENED = 102
GADGET_STATE_CHEST_TRAP = 103
GADGET_STATE_CHEST_BRAMBLE = 104
GADGET_STATE_CHEST_FROZEN = 105
GADGET_STATE_CHEST_ROCK = 106
GADGET_STATE_GEAR_START = 201
GADGET_STATE_GEAR_STOP = 202
GADGET_STATE_GEAR_ACTION1 = 203
GADGET_STATE_GEAR_ACTION2 = 204
GADGET_STATE_CRYSTAL_RESONATE1 = 301
GADGET_STATE_CRYSTAL_RESONATE2 = 302
GADGET_STATE_CRYSTAL_EXPLODE = 303
GADGET_STATE_CRYSTAL_DRAIN = 304
GADGET_STATE_STATUE_ACTIVE = 401
GADGET_STATE_ACTION01 = 901
GADGET_STATE_ACTION02 = 902
GADGET_STATE_ACTION03 = 903
)

View File

@@ -2,6 +2,7 @@ package controller
import ( import (
"context" "context"
"net"
"net/http" "net/http"
"strconv" "strconv"
@@ -47,7 +48,17 @@ func NewController(dao *dao.Dao, discovery *rpc.DiscoveryClient) (r *Controller)
func (c *Controller) authorize() gin.HandlerFunc { func (c *Controller) authorize() gin.HandlerFunc {
return func(context *gin.Context) { return func(context *gin.Context) {
if context.Query("key") == "flswld" { addr := context.ClientIP()
if addr == "" {
addr = context.Request.RemoteAddr
}
ip := net.ParseIP(addr)
ipv4 := ip.To4()
if ip.IsLoopback() ||
ipv4[0] == 10 ||
ipv4[0] == 169 && ipv4[1] == 254 ||
ipv4[0] == 172 && ipv4[1] >= 16 && ipv4[1] <= 31 ||
ipv4[0] == 192 && ipv4[1] == 168 {
context.Next() context.Next()
return return
} }

View File

@@ -321,7 +321,7 @@ func (k *KcpConnectManager) getPlayerToken(req *proto.GetPlayerTokenReq, session
} }
} }
tokenVerifyRsp, err := httpclient.PostJson[controller.TokenVerifyRsp]( tokenVerifyRsp, err := httpclient.PostJson[controller.TokenVerifyRsp](
config.GetConfig().Hk4e.LoginSdkUrl+"/gate/token/verify?key=flswld", config.GetConfig().Hk4e.LoginSdkUrl+"/gate/token/verify",
&controller.TokenVerifyReq{ &controller.TokenVerifyReq{
AccountId: req.AccountUid, AccountId: req.AccountUid,
AccountToken: req.AccountToken, AccountToken: req.AccountToken,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -43,7 +43,7 @@ type InherentProudSkillOpens struct {
func (g *GameDataConfig) loadAvatarSkillDepotData() { func (g *GameDataConfig) loadAvatarSkillDepotData() {
g.AvatarSkillDepotDataMap = make(map[int32]*AvatarSkillDepotData) g.AvatarSkillDepotDataMap = make(map[int32]*AvatarSkillDepotData)
avatarSkillDepotDataList := make([]*AvatarSkillDepotData, 0) 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" playerElementsFilePath := g.jsonPrefix + "ability_group/AbilityGroup_Other_PlayerElementAbility.json"
playerElementsFile, err := os.ReadFile(playerElementsFilePath) playerElementsFile, err := os.ReadFile(playerElementsFilePath)
if err != nil { if err != nil {
@@ -113,7 +113,6 @@ func (g *GameDataConfig) loadAvatarSkillDepotData() {
} }
} }
} }
// list -> map
g.AvatarSkillDepotDataMap[avatarSkillDepotData.AvatarSkillDepotId] = avatarSkillDepotData g.AvatarSkillDepotDataMap[avatarSkillDepotData.AvatarSkillDepotId] = avatarSkillDepotData
} }
logger.Info("AvatarSkillDepotData count: %v", len(g.AvatarSkillDepotDataMap)) 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"} fileNameList := []string{"FettersData.txt", "FetterDataStory.txt", "FetterDataIformation.txt", "PhotographExpressionName.txt", "PhotographPoseName.txt"}
for _, fileName := range fileNameList { for _, fileName := range fileNameList {
fetterDataList := make([]*FetterData, 0) fetterDataList := make([]*FetterData, 0)
readTable[FetterData](g.tablePrefix+fileName, &fetterDataList) readTable[FetterData](g.txtPrefix+fileName, &fetterDataList)
for _, fetterData := range fetterDataList { for _, fetterData := range fetterDataList {
// list -> map
g.FetterDataMap[fetterData.FetterId] = fetterData g.FetterDataMap[fetterData.FetterId] = fetterData
fetterIdList := g.FetterDataAvatarIdMap[fetterData.AvatarId] fetterIdList := g.FetterDataAvatarIdMap[fetterData.AvatarId]
if fetterIdList == nil { 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 { type GameDataConfig struct {
// 配置表路径前缀 // 配置表路径前缀
tablePrefix string txtPrefix string
jsonPrefix string jsonPrefix string
luaPrefix string luaPrefix string
extPrefix 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 // 场景 SceneDataMap map[int32]*SceneData // 场景
ScenePointMap map[int32]*ScenePoint // 场景传送点
SceneTagDataMap map[int32]*SceneTagData // 场景标签
SceneLuaConfigMap map[int32]*SceneLuaConfig // 场景LUA配置 SceneLuaConfigMap map[int32]*SceneLuaConfig // 场景LUA配置
GroupMap map[int32]*Group // 场景LUA区块group索引 GroupMap map[int32]*Group // 场景LUA区块group索引
LuaStateLruMap map[int32]*LuaStateLru // 场景LUA虚拟机LRU内存淘汰 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 // 采集物 GatherDataMap map[int32]*GatherData // 采集物
GatherDataPointTypeMap 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 // 角色资料解锁 FetterDataMap map[int32]*FetterData // 角色资料解锁
FetterDataAvatarIdMap map[int32][]int32 // 角色资料解锁角色id索引 FetterDataAvatarIdMap map[int32][]int32 // 角色资料解锁角色id索引
ItemDataMap map[int32]*ItemData // 统一道具 ItemDataMap map[int32]*ItemData // 统一道具
@@ -61,7 +59,12 @@ type GameDataConfig struct {
ReliquaryMainDataMap map[int32]map[int32]*ReliquaryMainData // 圣遗物主属性 ReliquaryMainDataMap map[int32]map[int32]*ReliquaryMainData // 圣遗物主属性
ReliquaryAffixDataMap map[int32]map[int32]*ReliquaryAffixData // 圣遗物追加属性 ReliquaryAffixDataMap map[int32]map[int32]*ReliquaryAffixData // 圣遗物追加属性
QuestDataMap map[int32]*QuestData // 任务 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() { func InitGameDataConfig() {
@@ -95,13 +98,13 @@ func (g *GameDataConfig) loadAll() {
panic(info) panic(info)
} }
g.tablePrefix = pathPrefix + "/txt" g.txtPrefix = pathPrefix + "/txt"
dirInfo, err = os.Stat(g.tablePrefix) dirInfo, err = os.Stat(g.txtPrefix)
if err != nil || !dirInfo.IsDir() { if err != nil || !dirInfo.IsDir() {
info := fmt.Sprintf("open game data config txt dir error: %v", err) info := fmt.Sprintf("open game data config txt dir error: %v", err)
panic(info) panic(info)
} }
g.tablePrefix += "/" g.txtPrefix += "/"
g.jsonPrefix = pathPrefix + "/json" g.jsonPrefix = pathPrefix + "/json"
dirInfo, err = os.Stat(g.jsonPrefix) dirInfo, err = os.Stat(g.jsonPrefix)
@@ -131,34 +134,35 @@ func (g *GameDataConfig) loadAll() {
} }
func (g *GameDataConfig) load() { func (g *GameDataConfig) load() {
g.loadSceneData() // 场景
g.loadSceneLuaConfig() // 场景LUA配置
g.loadTriggerData() // 场景LUA触发器
g.loadScenePoint() // 场景传送点
g.loadSceneTagData() // 场景标签
g.loadGatherData() // 采集物
g.loadWorldAreaData() // 世界区域
g.loadAvatarData() // 角色 g.loadAvatarData() // 角色
g.loadAvatarSkillData() // 角色技能 g.loadAvatarSkillData() // 角色技能
g.loadAvatarSkillDepotData() // 角色技能库 g.loadAvatarSkillDepotData() // 角色技能库
g.loadDropGroupData() // 掉落组 卡池 临时的 g.loadFetterData() // 角色资料解锁
g.loadGCGCharData() // 角色卡牌 g.loadItemData() // 统一道具
g.loadGCGSkillData() // 卡牌技能 g.loadAvatarLevelData() // 角色等级
g.loadSceneData() // 场景 g.loadAvatarPromoteData() // 角色突破
g.loadScenePoint() // 场景传送点 g.loadPlayerLevelData() // 玩家等级
g.loadSceneTagData() // 场景地图图标 g.loadWeaponLevelData() // 武器等级
if config.GetConfig().Hk4e.LoadSceneLuaConfig { g.loadWeaponPromoteData() // 武器突破
g.loadSceneLuaConfig() // 场景LUA配置 g.loadRewardData() // 奖励
} g.loadAvatarCostumeData() // 角色时装
g.loadWorldAreaData() // 世界区域 g.loadAvatarFlycloakData() // 角色风之翼
g.loadGatherData() // 采集物 g.loadReliquaryMainData() // 圣遗物主属性
g.loadFetterData() // 角色资料解锁 g.loadReliquaryAffixData() // 圣遗物追加属性
g.loadItemData() // 统一道具 g.loadQuestData() // 任务
g.loadAvatarLevelData() // 角色等级 g.loadDropData() // 掉落
g.loadAvatarPromoteData() // 角色突破 g.loadMonsterDropData() // 怪物掉落
g.loadPlayerLevelData() // 玩家等级 g.loadChestDropData() // 宝箱掉落
g.loadWeaponLevelData() // 武器等级 g.loadGCGCharData() // 七圣召唤角色卡牌
g.loadWeaponPromoteData() // 武器突破 g.loadGCGSkillData() // 七圣召唤卡牌技能
g.loadRewardData() // 奖励 g.loadGachaDropGroupData() // 卡池掉落组 临时的
g.loadAvatarCostumeData() // 角色时装
g.loadAvatarFlycloakData() // 角色风之翼
g.loadReliquaryMainData() // 圣遗物主属性
g.loadReliquaryAffixData() // 圣遗物追加属性
g.loadQuestData() // 任务
g.loadTriggerData() // 场景LUA触发器
} }
// CSV相关 // CSV相关
@@ -191,6 +195,22 @@ func (a *IntArray) UnmarshalCSV(data []byte) error {
return nil 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) { func readExtCsv[T any](tablePath string, table *[]*T) {
fileData, err := os.ReadFile(tablePath) fileData, err := os.ReadFile(tablePath)
if err != nil { 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_NONE", lua.LNumber(constant.LUA_EVENT_NONE))
luaState.SetField(eventType, "EVENT_ENTER_REGION", lua.LNumber(constant.LUA_EVENT_ENTER_REGION)) 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_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() entityType := luaState.NewTable()
luaState.SetGlobal("EntityType", entityType) luaState.SetGlobal("EntityType", entityType)
@@ -287,11 +310,17 @@ func initLuaState(luaState *lua.LState) {
gadgetState := luaState.NewTable() gadgetState := luaState.NewTable()
luaState.SetGlobal("GadgetState", gadgetState) 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() visionLevelType := luaState.NewTable()
luaState.SetGlobal("VisionLevelType", visionLevelType) 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 { 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") logger.Info("start load conf")
InitGameDataConfig() InitGameDataConfig()
logger.Info("load conf finish") logger.Info("load conf finish")
time.Sleep(time.Second) time.Sleep(time.Minute)
} }
func CheckJsonLoop(path string, errorJsonFileList *[]string, totalJsonFileCount *int) { func CheckJsonLoop(path string, errorJsonFileList *[]string, totalJsonFileCount *int) {

View File

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

View File

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

View File

@@ -35,7 +35,7 @@ type ConfigSkillEffectValue struct {
func (g *GameDataConfig) loadGCGSkillData() { func (g *GameDataConfig) loadGCGSkillData() {
g.GCGSkillDataMap = make(map[int32]*GCGSkillData) g.GCGSkillDataMap = make(map[int32]*GCGSkillData)
gcgSkillDataList := make([]*GCGSkillData, 0) gcgSkillDataList := make([]*GCGSkillData, 0)
readTable[GCGSkillData](g.tablePrefix+"GCGSkillData.txt", &gcgSkillDataList) readTable[GCGSkillData](g.txtPrefix+"GCGSkillData.txt", &gcgSkillDataList)
for _, gcgSkillData := range gcgSkillDataList { for _, gcgSkillData := range gcgSkillDataList {
// 技能消耗整合进CostMap // 技能消耗整合进CostMap
gcgSkillData.CostMap = map[uint32]uint32{ gcgSkillData.CostMap = map[uint32]uint32{
@@ -97,7 +97,6 @@ func (g *GameDataConfig) loadGCGSkillData() {
} }
} }
} }
// list -> map
g.GCGSkillDataMap[gcgSkillData.SkillId] = gcgSkillData g.GCGSkillDataMap[gcgSkillData.SkillId] = gcgSkillData
} }
logger.Info("GCGSkillData count: %v", len(g.GCGSkillDataMap)) 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"} fileNameList := []string{"MaterialData.txt", "WeaponData.txt", "ReliquaryData.txt", "FurnitureExcelData.txt"}
for _, fileName := range fileNameList { for _, fileName := range fileNameList {
itemDataList := make([]*ItemData, 0) itemDataList := make([]*ItemData, 0)
readTable[ItemData](g.tablePrefix+fileName, &itemDataList) readTable[ItemData](g.txtPrefix+fileName, &itemDataList)
for _, itemData := range itemDataList { for _, itemData := range itemDataList {
// list -> map
itemData.SkillAffix = make([]int32, 0) itemData.SkillAffix = make([]int32, 0)
if itemData.SkillAffix1 != 0 { if itemData.SkillAffix1 != 0 {
itemData.SkillAffix = append(itemData.SkillAffix, itemData.SkillAffix1) 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() { func (g *GameDataConfig) loadPlayerLevelData() {
g.PlayerLevelDataMap = make(map[int32]*PlayerLevelData) g.PlayerLevelDataMap = make(map[int32]*PlayerLevelData)
playerLevelDataList := make([]*PlayerLevelData, 0) playerLevelDataList := make([]*PlayerLevelData, 0)
readTable[PlayerLevelData](g.tablePrefix+"PlayerLevelData.txt", &playerLevelDataList) readTable[PlayerLevelData](g.txtPrefix+"PlayerLevelData.txt", &playerLevelDataList)
for _, playerLevelData := range playerLevelDataList { for _, playerLevelData := range playerLevelDataList {
// list -> map
g.PlayerLevelDataMap[playerLevelData.Level] = playerLevelData g.PlayerLevelDataMap[playerLevelData.Level] = playerLevelData
} }
logger.Info("PlayerLevelData count: %v", len(g.PlayerLevelDataMap)) 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"} fileNameList := []string{"QuestData.txt", "QuestData_Exported.txt"}
for _, fileName := range fileNameList { for _, fileName := range fileNameList {
questDataList := make([]*QuestData, 0) questDataList := make([]*QuestData, 0)
readTable[QuestData](g.tablePrefix+fileName, &questDataList) readTable[QuestData](g.txtPrefix+fileName, &questDataList)
for _, questData := range questDataList { for _, questData := range questDataList {
// list -> map
// 领取条件 // 领取条件
questData.AcceptCondList = make([]*QuestCond, 0) questData.AcceptCondList = make([]*QuestCond, 0)
if questData.AcceptCondType1 != 0 { if questData.AcceptCondType1 != 0 {

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,9 +5,9 @@ import (
"sort" "sort"
"strconv" "strconv"
"sync" "sync"
"sync/atomic"
"time" "time"
"hk4e/common/config"
"hk4e/pkg/logger" "hk4e/pkg/logger"
lua "github.com/yuin/gopher-lua" lua "github.com/yuin/gopher-lua"
@@ -19,8 +19,6 @@ const (
SceneGroupLoaderLimit = 4 // 加载文件的并发数 此操作很耗内存 调大之前请确保你的机器内存足够 SceneGroupLoaderLimit = 4 // 加载文件的并发数 此操作很耗内存 调大之前请确保你的机器内存足够
) )
var OBJECT_ID_COUNTER uint64
type SceneLuaConfig struct { type SceneLuaConfig struct {
Id int32 Id int32
SceneConfig *SceneConfig // 地图配置 SceneConfig *SceneConfig // 地图配置
@@ -55,77 +53,27 @@ type BlockRange struct {
} }
type Group struct { type Group struct {
Id int32 `json:"id"` Id int32 `json:"id"`
RefreshId int32 `json:"refresh_id"` RefreshId int32 `json:"refresh_id"`
Area int32 `json:"area"` Area int32 `json:"area"`
Pos *Vector `json:"pos"` Pos *Vector `json:"pos"`
DynamicLoad bool `json:"dynamic_load"` DynamicLoad bool `json:"dynamic_load"`
IsReplaceable *Replaceable `json:"is_replaceable"` IsReplaceable *Replaceable `json:"is_replaceable"`
MonsterList []*Monster `json:"monsters"` // 怪物 MonsterMap map[int32]*Monster `json:"-"` // 怪物
NpcList []*Npc `json:"npcs"` // NPC NpcMap map[int32]*Npc `json:"-"` // NPC
GadgetList []*Gadget `json:"gadgets"` // 物件 GadgetMap map[int32]*Gadget `json:"-"` // 物件
RegionList []*Region `json:"regions"` RegionMap map[int32]*Region `json:"-"` // 区域
TriggerList []*Trigger `json:"triggers"` TriggerMap map[string]*Trigger `json:"-"` // 触发器
LuaStr string `json:"-"` GroupInitConfig *GroupInitConfig `json:"-"` // 初始化配置
LuaState *lua.LState `json:"-"` SuiteList []*Suite `json:"-"` // 小组配置
LuaStr string `json:"-"` // LUA原始字符串缓存
LuaState *lua.LState `json:"-"` // LUA虚拟机实例
} }
const ( type GroupInitConfig struct {
LuaStateLruKeepNum = 1000 Suite int32 `json:"suite"`
) EndSuite int32 `json:"end_suite"`
RandSuite bool `json:"rand_suite"`
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 Replaceable struct { type Replaceable struct {
@@ -141,7 +89,7 @@ type Monster struct {
Rot *Vector `json:"rot"` Rot *Vector `json:"rot"`
Level int32 `json:"level"` Level int32 `json:"level"`
AreaId int32 `json:"area_id"` AreaId int32 `json:"area_id"`
ObjectId uint64 `json:"-"` DropTag string `json:"drop_tag"` // 关联MonsterDropData表
} }
type Npc struct { type Npc struct {
@@ -150,18 +98,19 @@ type Npc struct {
Pos *Vector `json:"pos"` Pos *Vector `json:"pos"`
Rot *Vector `json:"rot"` Rot *Vector `json:"rot"`
AreaId int32 `json:"area_id"` AreaId int32 `json:"area_id"`
ObjectId uint64 `json:"-"`
} }
type Gadget struct { type Gadget struct {
ConfigId int32 `json:"config_id"` ConfigId int32 `json:"config_id"`
GadgetId int32 `json:"gadget_id"` GadgetId int32 `json:"gadget_id"`
Pos *Vector `json:"pos"` Pos *Vector `json:"pos"`
Rot *Vector `json:"rot"` Rot *Vector `json:"rot"`
Level int32 `json:"level"` Level int32 `json:"level"`
AreaId int32 `json:"area_id"` AreaId int32 `json:"area_id"`
PointType int32 `json:"point_type"` // 关联GatherData表 PointType int32 `json:"point_type"` // 关联GatherData表
ObjectId uint64 `json:"-"` State int32 `json:"state"`
VisionLevel int32 `json:"vision_level"`
DropTag string `json:"drop_tag"`
} }
type Region struct { type Region struct {
@@ -185,6 +134,22 @@ type Trigger struct {
TriggerCount int32 `json:"trigger_count"` 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) { func (g *GameDataConfig) loadGroup(group *Group, block *Block, sceneId int32, blockId int32) {
sceneLuaPrefix := g.luaPrefix + "scene/" sceneLuaPrefix := g.luaPrefix + "scene/"
sceneIdStr := strconv.Itoa(int(sceneId)) sceneIdStr := strconv.Itoa(int(sceneId))
@@ -197,55 +162,120 @@ func (g *GameDataConfig) loadGroup(group *Group, block *Block, sceneId int32, bl
} }
group.LuaStr = string(groupLuaData) group.LuaStr = string(groupLuaData)
luaState := newLuaState(group.LuaStr) 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 // monsters
group.MonsterList = make([]*Monster, 0) monsterList := make([]*Monster, 0)
ok := getSceneLuaConfigTable[*[]*Monster](luaState, "monsters", &group.MonsterList) ok = getSceneLuaConfigTable[*[]*Monster](luaState, "monsters", &monsterList)
if !ok { if !ok {
logger.Error("get monsters object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId) logger.Error("get monsters object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
luaState.Close() luaState.Close()
return return
} }
for _, monster := range group.MonsterList { group.MonsterMap = make(map[int32]*Monster)
monster.ObjectId = atomic.AddUint64(&OBJECT_ID_COUNTER, 1) for _, monster := range monsterList {
group.MonsterMap[monster.ConfigId] = monster
} }
// npcs // npcs
group.NpcList = make([]*Npc, 0) npcList := make([]*Npc, 0)
ok = getSceneLuaConfigTable[*[]*Npc](luaState, "npcs", &group.NpcList) ok = getSceneLuaConfigTable[*[]*Npc](luaState, "npcs", &npcList)
if !ok { if !ok {
logger.Error("get npcs object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId) logger.Error("get npcs object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
luaState.Close() luaState.Close()
return return
} }
for _, npc := range group.NpcList { group.NpcMap = make(map[int32]*Npc)
npc.ObjectId = atomic.AddUint64(&OBJECT_ID_COUNTER, 1) for _, npc := range npcList {
group.NpcMap[npc.ConfigId] = npc
} }
// gadgets // gadgets
group.GadgetList = make([]*Gadget, 0) gadgetList := make([]*Gadget, 0)
ok = getSceneLuaConfigTable[*[]*Gadget](luaState, "gadgets", &group.GadgetList) ok = getSceneLuaConfigTable[*[]*Gadget](luaState, "gadgets", &gadgetList)
if !ok { if !ok {
logger.Error("get gadgets object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId) logger.Error("get gadgets object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
luaState.Close() luaState.Close()
return return
} }
for _, gadget := range group.GadgetList { group.GadgetMap = make(map[int32]*Gadget)
gadget.ObjectId = atomic.AddUint64(&OBJECT_ID_COUNTER, 1) for _, gadget := range gadgetList {
group.GadgetMap[gadget.ConfigId] = gadget
} }
// regions // regions
group.RegionList = make([]*Region, 0) regionList := make([]*Region, 0)
ok = getSceneLuaConfigTable[*[]*Region](luaState, "regions", &group.RegionList) ok = getSceneLuaConfigTable[*[]*Region](luaState, "regions", &regionList)
if !ok { if !ok {
logger.Error("get regions object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId) logger.Error("get regions object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
luaState.Close() luaState.Close()
return return
} }
group.RegionMap = make(map[int32]*Region)
for _, region := range regionList {
group.RegionMap[region.ConfigId] = region
}
// triggers // triggers
group.TriggerList = make([]*Trigger, 0) triggerList := make([]*Trigger, 0)
ok = getSceneLuaConfigTable[*[]*Trigger](luaState, "triggers", &group.TriggerList) ok = getSceneLuaConfigTable[*[]*Trigger](luaState, "triggers", &triggerList)
if !ok { if !ok {
logger.Error("get triggers object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId) logger.Error("get triggers object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId)
luaState.Close() luaState.Close()
return 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() luaState.Close()
block.groupMapLoadLock.Lock() block.groupMapLoadLock.Lock()
block.GroupMap[group.Id] = group block.GroupMap[group.Id] = group
@@ -253,10 +283,12 @@ func (g *GameDataConfig) loadGroup(group *Group, block *Block, sceneId int32, bl
} }
func (g *GameDataConfig) loadSceneLuaConfig() { func (g *GameDataConfig) loadSceneLuaConfig() {
OBJECT_ID_COUNTER = 0
g.SceneLuaConfigMap = make(map[int32]*SceneLuaConfig) g.SceneLuaConfigMap = make(map[int32]*SceneLuaConfig)
g.GroupMap = make(map[int32]*Group) g.GroupMap = make(map[int32]*Group)
g.LuaStateLruMap = make(map[int32]*LuaStateLru) g.LuaStateLruMap = make(map[int32]*LuaStateLru)
if !config.GetConfig().Hk4e.LoadSceneLuaConfig {
return
}
sceneLuaPrefix := g.luaPrefix + "scene/" sceneLuaPrefix := g.luaPrefix + "scene/"
for _, sceneData := range g.SceneDataMap { for _, sceneData := range g.SceneDataMap {
sceneId := sceneData.SceneId sceneId := sceneData.SceneId
@@ -345,9 +377,9 @@ func (g *GameDataConfig) loadSceneLuaConfig() {
for _, scene := range g.SceneLuaConfigMap { for _, scene := range g.SceneLuaConfigMap {
for _, block := range scene.BlockMap { for _, block := range scene.BlockMap {
for _, group := range block.GroupMap { for _, group := range block.GroupMap {
monsterCount += len(group.MonsterList) monsterCount += len(group.MonsterMap)
npcCount += len(group.NpcList) npcCount += len(group.NpcMap)
gadgetCount += len(group.GadgetList) gadgetCount += len(group.GadgetMap)
groupCount++ groupCount++
} }
blockCount++ blockCount++
@@ -373,3 +405,61 @@ func GetSceneGroup(groupId int32) *Group {
} }
return groupConfig 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() { func (g *GameDataConfig) loadSceneTagData() {
g.SceneTagDataMap = make(map[int32]*SceneTagData) g.SceneTagDataMap = make(map[int32]*SceneTagData)
sceneTagDataList := make([]*SceneTagData, 0) sceneTagDataList := make([]*SceneTagData, 0)
readTable[SceneTagData](g.tablePrefix+"SceneTagData.txt", &sceneTagDataList) readTable[SceneTagData](g.txtPrefix+"SceneTagData.txt", &sceneTagDataList)
for _, sceneTagData := range sceneTagDataList { for _, sceneTagData := range sceneTagDataList {
// list -> map
g.SceneTagDataMap[sceneTagData.SceneTagId] = sceneTagData g.SceneTagDataMap[sceneTagData.SceneTagId] = sceneTagData
} }
logger.Info("SceneTagData count: %v", len(g.SceneTagDataMap)) logger.Info("SceneTagData count: %v", len(g.SceneTagDataMap))

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,12 +4,12 @@ import (
"image" "image"
"image/color" "image/color"
"image/jpeg" "image/jpeg"
"math"
"os" "os"
"sort" "sort"
"strconv" "strconv"
"time" "time"
"hk4e/common/constant"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/gs/model" "hk4e/gs/model"
@@ -297,8 +297,6 @@ func LoadFrameFile() error {
return nil return nil
} }
var OBJECT_ID_COUNTER uint64 = math.MaxUint64
func UpdateFrame(rgb bool) { func UpdateFrame(rgb bool) {
err := LoadFrameFile() err := LoadFrameFile()
if err != nil { if err != nil {
@@ -323,13 +321,12 @@ func UpdateFrame(rgb bool) {
for w := 0; w < SCREEN_WIDTH; w++ { for w := 0; w < SCREEN_WIDTH; w++ {
for h := 0; h < SCREEN_HEIGHT; h++ { for h := 0; h < SCREEN_HEIGHT; h++ {
// 创建像素点 // 创建像素点
OBJECT_ID_COUNTER++
if rgb { if rgb {
entityId := scene.CreateEntityGadgetNormal(&model.Vector{ entityId := scene.CreateEntityGadgetNormal(&model.Vector{
X: leftTopPos.X - float64(w)*SCREEN_DPI, X: leftTopPos.X - float64(w)*SCREEN_DPI,
Y: leftTopPos.Y - float64(h)*SCREEN_DPI, Y: leftTopPos.Y - float64(h)*SCREEN_DPI,
Z: leftTopPos.Z, Z: leftTopPos.Z,
}, new(model.Vector), uint32(FRAME_COLOR[w][h]), 271003, OBJECT_ID_COUNTER) }, new(model.Vector), uint32(FRAME_COLOR[w][h]), 271003, uint32(constant.GADGET_STATE_DEFAULT), 0)
SCREEN_ENTITY_ID_LIST = append(SCREEN_ENTITY_ID_LIST, entityId) SCREEN_ENTITY_ID_LIST = append(SCREEN_ENTITY_ID_LIST, entityId)
} else { } else {
if !FRAME[w][h] { if !FRAME[w][h] {
@@ -337,7 +334,7 @@ func UpdateFrame(rgb bool) {
X: leftTopPos.X - float64(w)*SCREEN_DPI, X: leftTopPos.X - float64(w)*SCREEN_DPI,
Y: leftTopPos.Y - float64(h)*SCREEN_DPI, Y: leftTopPos.Y - float64(h)*SCREEN_DPI,
Z: leftTopPos.Z, Z: leftTopPos.Z,
}, new(model.Vector), uint32(GADGET_ID), 271003, OBJECT_ID_COUNTER) }, new(model.Vector), uint32(GADGET_ID), 271003, uint32(constant.GADGET_STATE_DEFAULT), 0)
SCREEN_ENTITY_ID_LIST = append(SCREEN_ENTITY_ID_LIST, entityId) SCREEN_ENTITY_ID_LIST = append(SCREEN_ENTITY_ID_LIST, entityId)
} }
} }

View File

@@ -167,6 +167,11 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p
X: float64(motionInfo.Pos.X), X: float64(motionInfo.Pos.X),
Y: float64(motionInfo.Pos.Y), Y: float64(motionInfo.Pos.Y),
Z: float64(motionInfo.Pos.Z), Z: float64(motionInfo.Pos.Z),
})
g.TriggerCheck(player, player.Pos, &model.Vector{
X: float64(motionInfo.Pos.X),
Y: float64(motionInfo.Pos.Y),
Z: float64(motionInfo.Pos.Z),
}, sceneEntity.GetId()) }, sceneEntity.GetId())
// 更新玩家的位置信息 // 更新玩家的位置信息
player.Pos.X = float64(motionInfo.Pos.X) player.Pos.X = float64(motionInfo.Pos.X)
@@ -258,7 +263,7 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p
} }
} }
func (g *GameManager) AoiPlayerMove(player *model.Player, oldPos *model.Vector, newPos *model.Vector, entityId uint32) { func (g *GameManager) AoiPlayerMove(player *model.Player, oldPos *model.Vector, newPos *model.Vector) {
world := WORLD_MANAGER.GetWorldByID(player.WorldId) world := WORLD_MANAGER.GetWorldByID(player.WorldId)
if world == nil { if world == nil {
logger.Error("get player world is nil, uid: %v", player.PlayerID) logger.Error("get player world is nil, uid: %v", player.PlayerID)
@@ -281,167 +286,162 @@ func (g *GameManager) AoiPlayerMove(player *model.Player, oldPos *model.Vector,
oldVisionGroupMap := make(map[uint32]*gdconf.Group) oldVisionGroupMap := make(map[uint32]*gdconf.Group)
oldGroupList := aoiManager.GetObjectListByPos(float32(oldPos.X), 0.0, float32(oldPos.Z)) oldGroupList := aoiManager.GetObjectListByPos(float32(oldPos.X), 0.0, float32(oldPos.Z))
for groupId, groupAny := range oldGroupList { for groupId, groupAny := range oldGroupList {
group := groupAny.(*gdconf.Group) groupConfig := groupAny.(*gdconf.Group)
distance2D := math.Sqrt(math.Pow(oldPos.X-float64(group.Pos.X), 2.0) + math.Pow(oldPos.Z-float64(group.Pos.Z), 2.0)) distance2D := math.Sqrt((oldPos.X-float64(groupConfig.Pos.X))*(oldPos.X-float64(groupConfig.Pos.X)) +
(oldPos.Z-float64(groupConfig.Pos.Z))*(oldPos.Z-float64(groupConfig.Pos.Z)))
if distance2D > ENTITY_LOD { if distance2D > ENTITY_LOD {
continue continue
} }
if group.DynamicLoad { if groupConfig.DynamicLoad {
continue continue
} }
oldVisionGroupMap[uint32(groupId)] = group oldVisionGroupMap[uint32(groupId)] = groupConfig
} }
// 新位置视野范围内的group // 新位置视野范围内的group
newVisionGroupMap := make(map[uint32]*gdconf.Group) newVisionGroupMap := make(map[uint32]*gdconf.Group)
newGroupList := aoiManager.GetObjectListByPos(float32(newPos.X), 0.0, float32(newPos.Z)) newGroupList := aoiManager.GetObjectListByPos(float32(newPos.X), 0.0, float32(newPos.Z))
for groupId, groupAny := range newGroupList { for groupId, groupAny := range newGroupList {
group := groupAny.(*gdconf.Group) groupConfig := groupAny.(*gdconf.Group)
distance2D := math.Sqrt(math.Pow(newPos.X-float64(group.Pos.X), 2.0) + math.Pow(newPos.Z-float64(group.Pos.Z), 2.0)) distance2D := math.Sqrt((newPos.X-float64(groupConfig.Pos.X))*(newPos.X-float64(groupConfig.Pos.X)) +
(newPos.Z-float64(groupConfig.Pos.Z))*(newPos.Z-float64(groupConfig.Pos.Z)))
if distance2D > ENTITY_LOD { if distance2D > ENTITY_LOD {
continue continue
} }
if group.DynamicLoad { if groupConfig.DynamicLoad {
continue continue
} }
newVisionGroupMap[uint32(groupId)] = group newVisionGroupMap[uint32(groupId)] = groupConfig
} }
// 消失的场景实体 // 消失的场景实体
delEntityIdList := make([]uint32, 0) delEntityIdList := make([]uint32, 0)
for groupId, group := range oldVisionGroupMap { for groupId, groupConfig := range oldVisionGroupMap {
_, exist := newVisionGroupMap[groupId] _, exist := newVisionGroupMap[groupId]
if exist { if exist {
continue continue
} }
// 旧有新没有的group即为消失的 // 旧有新没有的group即为消失的
for _, monster := range group.MonsterList { group := scene.GetGroupById(groupId)
entity := scene.GetEntityByObjectId(monster.ObjectId) for _, entity := range group.GetAllEntity() {
if entity == nil {
continue
}
scene.DestroyEntity(entity.GetId())
delEntityIdList = append(delEntityIdList, entity.GetId())
}
for _, npc := range group.NpcList {
entity := scene.GetEntityByObjectId(npc.ObjectId)
if entity == nil {
continue
}
scene.DestroyEntity(entity.GetId())
delEntityIdList = append(delEntityIdList, entity.GetId())
}
for _, gadget := range group.GadgetList {
entity := scene.GetEntityByObjectId(gadget.ObjectId)
if entity == nil {
continue
}
scene.DestroyEntity(entity.GetId())
delEntityIdList = append(delEntityIdList, entity.GetId()) delEntityIdList = append(delEntityIdList, entity.GetId())
} }
g.RemoveGroup(scene, groupConfig)
} }
// 出现的场景实体 // 出现的场景实体
addEntityIdList := make([]uint32, 0) addEntityIdList := make([]uint32, 0)
for groupId, group := range newVisionGroupMap { for groupId, groupConfig := range newVisionGroupMap {
_, exist := oldVisionGroupMap[groupId] _, exist := oldVisionGroupMap[groupId]
if exist { if exist {
continue continue
} }
// 新有旧没有的group即为出现的 // 新有旧没有的group即为出现的
for _, monster := range group.MonsterList { g.AddSceneGroup(scene, groupConfig)
entityId := g.CreateConfigEntity(scene, monster.ObjectId, monster) group := scene.GetGroupById(groupId)
addEntityIdList = append(addEntityIdList, entityId) for _, entity := range group.GetAllEntity() {
} addEntityIdList = append(addEntityIdList, entity.GetId())
for _, npc := range group.NpcList {
entityId := g.CreateConfigEntity(scene, npc.ObjectId, npc)
addEntityIdList = append(addEntityIdList, entityId)
}
for _, gadget := range group.GadgetList {
entityId := g.CreateConfigEntity(scene, gadget.ObjectId, gadget)
addEntityIdList = append(addEntityIdList, entityId)
} }
} }
// 同步客户端消失和出现的场景实体 // 同步客户端消失和出现的场景实体
g.RemoveSceneEntityNotifyToPlayer(player, proto.VisionType_VISION_MISS, delEntityIdList) g.RemoveSceneEntityNotifyToPlayer(player, proto.VisionType_VISION_MISS, delEntityIdList)
g.AddSceneEntityNotify(player, proto.VisionType_VISION_MEET, addEntityIdList, false, false) g.AddSceneEntityNotify(player, proto.VisionType_VISION_MEET, addEntityIdList, false, false)
// 场景区域触发器 }
for _, group := range newVisionGroupMap {
for _, region := range group.RegionList { // TriggerCheck 场景区域触发器检测
shape := alg.NewShape() func (g *GameManager) TriggerCheck(player *model.Player, oldPos *model.Vector, newPos *model.Vector, entityId uint32) {
switch uint8(region.Shape) { world := WORLD_MANAGER.GetWorldByID(player.WorldId)
case constant.REGION_SHAPE_SPHERE: if world == nil {
shape.NewSphere(&alg.Vector3{X: region.Pos.X, Y: region.Pos.Y, Z: region.Pos.Z}, region.Radius) logger.Error("get player world is nil, uid: %v", player.PlayerID)
case constant.REGION_SHAPE_CUBIC: return
shape.NewCubic(&alg.Vector3{X: region.Pos.X, Y: region.Pos.Y, Z: region.Pos.Z}, }
&alg.Vector3{X: region.Size.X, Y: region.Size.Y, Z: region.Size.Z}) scene := world.GetSceneById(player.SceneId)
case constant.REGION_SHAPE_CYLINDER: for groupId, group := range scene.GetAllGroup() {
shape.NewCylinder(&alg.Vector3{X: region.Pos.X, Y: region.Pos.Y, Z: region.Pos.Z}, groupConfig := gdconf.GetSceneGroup(int32(groupId))
region.Radius, region.Height) if groupConfig == nil {
case constant.REGION_SHAPE_POLYGON: continue
vector2PointArray := make([]*alg.Vector2, 0) }
for _, vector := range region.PointArray { for suiteId := range group.GetAllSuite() {
// z就是y suiteConfig := groupConfig.SuiteList[suiteId-1]
vector2PointArray = append(vector2PointArray, &alg.Vector2{X: vector.X, Z: vector.Y}) for _, regionConfigId := range suiteConfig.RegionConfigIdList {
} regionConfig := groupConfig.RegionMap[regionConfigId]
shape.NewPolygon(&alg.Vector3{X: region.Pos.X, Y: region.Pos.Y, Z: region.Pos.Z}, shape := alg.NewShape()
vector2PointArray, region.Height) switch uint8(regionConfig.Shape) {
} case constant.REGION_SHAPE_SPHERE:
oldPosInRegion := shape.Contain(&alg.Vector3{ shape.NewSphere(&alg.Vector3{X: regionConfig.Pos.X, Y: regionConfig.Pos.Y, Z: regionConfig.Pos.Z}, regionConfig.Radius)
X: float32(oldPos.X), case constant.REGION_SHAPE_CUBIC:
Y: float32(oldPos.Y), shape.NewCubic(&alg.Vector3{X: regionConfig.Pos.X, Y: regionConfig.Pos.Y, Z: regionConfig.Pos.Z},
Z: float32(oldPos.Z), &alg.Vector3{X: regionConfig.Size.X, Y: regionConfig.Size.Y, Z: regionConfig.Size.Z})
}) case constant.REGION_SHAPE_CYLINDER:
newPosInRegion := shape.Contain(&alg.Vector3{ shape.NewCylinder(&alg.Vector3{X: regionConfig.Pos.X, Y: regionConfig.Pos.Y, Z: regionConfig.Pos.Z},
X: float32(newPos.X), regionConfig.Radius, regionConfig.Height)
Y: float32(newPos.Y), case constant.REGION_SHAPE_POLYGON:
Z: float32(newPos.Z), vector2PointArray := make([]*alg.Vector2, 0)
}) for _, vector := range regionConfig.PointArray {
if !oldPosInRegion && newPosInRegion { // z就是y
logger.Debug("player enter region: %v, uid: %v", region, player.PlayerID) vector2PointArray = append(vector2PointArray, &alg.Vector2{X: vector.X, Z: vector.Y})
for _, trigger := range group.TriggerList {
if trigger.Event != constant.LUA_EVENT_ENTER_REGION {
continue
} }
if trigger.Condition != "" { shape.NewPolygon(&alg.Vector3{X: regionConfig.Pos.X, Y: regionConfig.Pos.Y, Z: regionConfig.Pos.Z},
cond := CallLuaFunc(group.GetLuaState(), trigger.Condition, vector2PointArray, regionConfig.Height)
&LuaCtx{uid: player.PlayerID}, }
&LuaEvt{param1: region.ConfigId, targetEntityId: entityId}) oldPosInRegion := shape.Contain(&alg.Vector3{
if !cond { X: float32(oldPos.X),
Y: float32(oldPos.Y),
Z: float32(oldPos.Z),
})
newPosInRegion := shape.Contain(&alg.Vector3{
X: float32(newPos.X),
Y: float32(newPos.Y),
Z: float32(newPos.Z),
})
if !oldPosInRegion && newPosInRegion {
logger.Debug("player enter region: %v, uid: %v", regionConfig, player.PlayerID)
for _, triggerName := range suiteConfig.TriggerNameList {
triggerConfig := groupConfig.TriggerMap[triggerName]
if triggerConfig.Event != constant.LUA_EVENT_ENTER_REGION {
continue continue
} }
} if triggerConfig.Condition != "" {
logger.Debug("scene group trigger fire, trigger: %v, uid: %v", trigger, player.PlayerID) cond := CallLuaFunc(groupConfig.GetLuaState(), triggerConfig.Condition,
if trigger.Action != "" { &LuaCtx{uid: player.PlayerID},
logger.Debug("scene group trigger do action, trigger: %v, uid: %v", trigger, player.PlayerID) &LuaEvt{param1: regionConfig.ConfigId, targetEntityId: entityId})
ok := CallLuaFunc(group.GetLuaState(), trigger.Action, if !cond {
&LuaCtx{uid: player.PlayerID}, continue
&LuaEvt{}) }
if !ok {
logger.Error("trigger action fail, trigger: %v, uid: %v", trigger, player.PlayerID)
} }
logger.Debug("scene group trigger fire, trigger: %v, uid: %v", triggerConfig, player.PlayerID)
if triggerConfig.Action != "" {
logger.Debug("scene group trigger do action, trigger: %v, uid: %v", triggerConfig, player.PlayerID)
ok := CallLuaFunc(groupConfig.GetLuaState(), triggerConfig.Action,
&LuaCtx{uid: player.PlayerID},
&LuaEvt{})
if !ok {
logger.Error("trigger action fail, trigger: %v, uid: %v", triggerConfig, player.PlayerID)
}
}
g.TriggerFire(player, triggerConfig)
} }
g.TriggerFire(player, trigger) } else if oldPosInRegion && !newPosInRegion {
} logger.Debug("player leave region: %v, uid: %v", regionConfig, player.PlayerID)
} else if oldPosInRegion && !newPosInRegion { for _, triggerName := range suiteConfig.TriggerNameList {
logger.Debug("player leave region: %v, uid: %v", region, player.PlayerID) triggerConfig := groupConfig.TriggerMap[triggerName]
for _, trigger := range group.TriggerList { if triggerConfig.Event != constant.LUA_EVENT_LEAVE_REGION {
if trigger.Event != constant.LUA_EVENT_LEAVE_REGION {
continue
}
if trigger.Condition != "" {
cond := CallLuaFunc(group.GetLuaState(), trigger.Condition,
&LuaCtx{uid: player.PlayerID},
&LuaEvt{param1: region.ConfigId, targetEntityId: entityId})
if !cond {
continue continue
} }
} if triggerConfig.Condition != "" {
logger.Debug("scene group trigger fire, trigger: %v, uid: %v", trigger, player.PlayerID) cond := CallLuaFunc(groupConfig.GetLuaState(), triggerConfig.Condition,
if trigger.Action != "" { &LuaCtx{uid: player.PlayerID},
logger.Debug("scene group trigger do action, trigger: %v, uid: %v", trigger, player.PlayerID) &LuaEvt{param1: regionConfig.ConfigId, targetEntityId: entityId})
ok := CallLuaFunc(group.GetLuaState(), trigger.Action, if !cond {
&LuaCtx{uid: player.PlayerID}, continue
&LuaEvt{}) }
if !ok { }
logger.Error("trigger action fail, trigger: %v, uid: %v", trigger, player.PlayerID) logger.Debug("scene group trigger fire, trigger: %v, uid: %v", triggerConfig, player.PlayerID)
if triggerConfig.Action != "" {
logger.Debug("scene group trigger do action, trigger: %v, uid: %v", triggerConfig, player.PlayerID)
ok := CallLuaFunc(groupConfig.GetLuaState(), triggerConfig.Action,
&LuaCtx{uid: player.PlayerID},
&LuaEvt{})
if !ok {
logger.Error("trigger action fail, trigger: %v, uid: %v", triggerConfig, player.PlayerID)
}
} }
} }
} }

View File

@@ -382,7 +382,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab
} }
// 找到卡池对应的掉落组 // 找到卡池对应的掉落组
dropGroupDataConfig := gdconf.CONF.DropGroupDataMap[int32(gachaType)] dropGroupDataConfig := gdconf.CONF.GachaDropGroupDataMap[int32(gachaType)]
if dropGroupDataConfig == nil { if dropGroupDataConfig == nil {
logger.Error("drop group not found, drop id: %v", gachaType) logger.Error("drop group not found, drop id: %v", gachaType)
return false, 0 return false, 0
@@ -417,7 +417,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab
PurpleTimesFixValue = WeaponPurpleTimesFixValue PurpleTimesFixValue = WeaponPurpleTimesFixValue
} }
if gachaPoolInfo.OrangeTimes >= OrangeTimesFixThreshold || gachaPoolInfo.PurpleTimes >= PurpleTimesFixThreshold { if gachaPoolInfo.OrangeTimes >= OrangeTimesFixThreshold || gachaPoolInfo.PurpleTimes >= PurpleTimesFixThreshold {
fixDropGroupDataConfig := new(gdconf.DropGroupData) fixDropGroupDataConfig := new(gdconf.GachaDropGroupData)
fixDropGroupDataConfig.DropId = dropGroupDataConfig.DropId fixDropGroupDataConfig.DropId = dropGroupDataConfig.DropId
fixDropGroupDataConfig.WeightAll = dropGroupDataConfig.WeightAll fixDropGroupDataConfig.WeightAll = dropGroupDataConfig.WeightAll
// 计算4星和5星权重修正值 // 计算4星和5星权重修正值
@@ -430,7 +430,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab
addPurpleWeight = 0 addPurpleWeight = 0
} }
for _, drop := range dropGroupDataConfig.DropConfig { for _, drop := range dropGroupDataConfig.DropConfig {
fixDrop := new(gdconf.Drop) fixDrop := new(gdconf.GachaDrop)
fixDrop.Result = drop.Result fixDrop.Result = drop.Result
fixDrop.DropId = drop.DropId fixDrop.DropId = drop.DropId
fixDrop.IsEnd = drop.IsEnd fixDrop.IsEnd = drop.IsEnd
@@ -525,7 +525,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab
// 替换本次结果为5星大保底 // 替换本次结果为5星大保底
if gachaPoolInfo.MustGetUpOrange { if gachaPoolInfo.MustGetUpOrange {
logger.Debug("trigger must get up orange, uid: %v", userId) logger.Debug("trigger must get up orange, uid: %v", userId)
upOrangeDropGroupDataConfig := gdconf.CONF.DropGroupDataMap[upOrangeDropId] upOrangeDropGroupDataConfig := gdconf.CONF.GachaDropGroupDataMap[upOrangeDropId]
if upOrangeDropGroupDataConfig == nil { if upOrangeDropGroupDataConfig == nil {
logger.Error("drop group not found, drop id: %v", upOrangeDropId) logger.Error("drop group not found, drop id: %v", upOrangeDropId)
return false, 0 return false, 0
@@ -552,7 +552,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab
// 替换本次结果为4星大保底 // 替换本次结果为4星大保底
if gachaPoolInfo.MustGetUpPurple { if gachaPoolInfo.MustGetUpPurple {
logger.Debug("trigger must get up purple, uid: %v", userId) logger.Debug("trigger must get up purple, uid: %v", userId)
upPurpleDropGroupDataConfig := gdconf.CONF.DropGroupDataMap[upPurpleDropId] upPurpleDropGroupDataConfig := gdconf.CONF.GachaDropGroupDataMap[upPurpleDropId]
if upPurpleDropGroupDataConfig == nil { if upPurpleDropGroupDataConfig == nil {
logger.Error("drop group not found, drop id: %v", upPurpleDropId) logger.Error("drop group not found, drop id: %v", upPurpleDropId)
return false, 0 return false, 0
@@ -576,7 +576,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab
} }
// 走一次完整流程的掉落组 // 走一次完整流程的掉落组
func (g *GameManager) doFullRandDrop(dropGroupDataConfig *gdconf.DropGroupData) (bool, *gdconf.Drop) { func (g *GameManager) doFullRandDrop(dropGroupDataConfig *gdconf.GachaDropGroupData) (bool, *gdconf.GachaDrop) {
for { for {
drop := g.doRandDropOnce(dropGroupDataConfig) drop := g.doRandDropOnce(dropGroupDataConfig)
if drop == nil { if drop == nil {
@@ -588,7 +588,7 @@ func (g *GameManager) doFullRandDrop(dropGroupDataConfig *gdconf.DropGroupData)
return true, drop return true, drop
} }
// 进行下一步掉落流程 // 进行下一步掉落流程
dropGroupDataConfig = gdconf.CONF.DropGroupDataMap[drop.Result] dropGroupDataConfig = gdconf.CONF.GachaDropGroupDataMap[drop.Result]
if dropGroupDataConfig == nil { if dropGroupDataConfig == nil {
logger.Error("drop config tab exist error, invalid drop id: %v", drop.Result) logger.Error("drop config tab exist error, invalid drop id: %v", drop.Result)
return false, nil return false, nil
@@ -597,7 +597,7 @@ func (g *GameManager) doFullRandDrop(dropGroupDataConfig *gdconf.DropGroupData)
} }
// 进行单次随机掉落 // 进行单次随机掉落
func (g *GameManager) doRandDropOnce(dropGroupDataConfig *gdconf.DropGroupData) *gdconf.Drop { func (g *GameManager) doRandDropOnce(dropGroupDataConfig *gdconf.GachaDropGroupData) *gdconf.GachaDrop {
randNum := random.GetRandomInt32(0, dropGroupDataConfig.WeightAll-1) randNum := random.GetRandomInt32(0, dropGroupDataConfig.WeightAll-1)
sumWeight := int32(0) sumWeight := int32(0)
// 轮盘选择法 // 轮盘选择法

View File

@@ -242,6 +242,21 @@ func (g *GameManager) SceneInitFinishReq(player *model.Player, payloadMsg pb.Mes
player.SceneLoadState = model.SceneInitFinish player.SceneLoadState = model.SceneInitFinish
} }
func (g *GameManager) AddSceneGroup(scene *Scene, groupConfig *gdconf.Group) {
initSuiteId := int(groupConfig.GroupInitConfig.Suite)
if initSuiteId > len(groupConfig.SuiteList) {
return
}
scene.AddGroupSuite(uint32(groupConfig.Id), uint8(initSuiteId))
}
func (g *GameManager) RemoveGroup(scene *Scene, groupConfig *gdconf.Group) {
group := scene.GetGroupById(uint32(groupConfig.Id))
for suiteId := range group.GetAllSuite() {
scene.RemoveGroupSuite(uint32(groupConfig.Id), suiteId)
}
}
func (g *GameManager) EnterSceneDoneReq(player *model.Player, payloadMsg pb.Message) { func (g *GameManager) EnterSceneDoneReq(player *model.Player, payloadMsg pb.Message) {
logger.Debug("player enter scene done, uid: %v", player.PlayerID) logger.Debug("player enter scene done, uid: %v", player.PlayerID)
world := WORLD_MANAGER.GetWorldByID(player.WorldId) world := WORLD_MANAGER.GetWorldByID(player.WorldId)
@@ -275,22 +290,15 @@ func (g *GameManager) EnterSceneDoneReq(player *model.Player, payloadMsg pb.Mess
objectList := aoiManager.GetObjectListByPos(float32(player.Pos.X), 0.0, float32(player.Pos.Z)) objectList := aoiManager.GetObjectListByPos(float32(player.Pos.X), 0.0, float32(player.Pos.Z))
for _, groupAny := range objectList { for _, groupAny := range objectList {
group := groupAny.(*gdconf.Group) group := groupAny.(*gdconf.Group)
distance2D := math.Sqrt(math.Pow(player.Pos.X-float64(group.Pos.X), 2.0) + math.Pow(player.Pos.Z-float64(group.Pos.Z), 2.0)) distance2D := math.Sqrt((player.Pos.X-float64(group.Pos.X))*(player.Pos.X-float64(group.Pos.X)) +
(player.Pos.Z-float64(group.Pos.Z))*(player.Pos.Z-float64(group.Pos.Z)))
if distance2D > ENTITY_LOD { if distance2D > ENTITY_LOD {
continue continue
} }
if group.DynamicLoad { if group.DynamicLoad {
continue continue
} }
for _, monster := range group.MonsterList { g.AddSceneGroup(scene, group)
g.CreateConfigEntity(scene, monster.ObjectId, monster)
}
for _, npc := range group.NpcList {
g.CreateConfigEntity(scene, npc.ObjectId, npc)
}
for _, gadget := range group.GadgetList {
g.CreateConfigEntity(scene, gadget.ObjectId, gadget)
}
} }
} }
if player.SceneJump { if player.SceneJump {
@@ -385,64 +393,6 @@ func (g *GameManager) SceneEntityDrownReq(player *model.Player, payloadMsg pb.Me
g.SendMsg(cmd.SceneEntityDrownRsp, player.PlayerID, player.ClientSeq, sceneEntityDrownRsp) g.SendMsg(cmd.SceneEntityDrownRsp, player.PlayerID, player.ClientSeq, sceneEntityDrownRsp)
} }
// CreateConfigEntity 创建配置表里的实体
func (g *GameManager) CreateConfigEntity(scene *Scene, objectId uint64, entityConfig any) uint32 {
switch entityConfig.(type) {
case *gdconf.Monster:
monster := entityConfig.(*gdconf.Monster)
return scene.CreateEntityMonster(&model.Vector{
X: float64(monster.Pos.X),
Y: float64(monster.Pos.Y),
Z: float64(monster.Pos.Z),
}, &model.Vector{
X: float64(monster.Rot.X),
Y: float64(monster.Rot.Y),
Z: float64(monster.Rot.Z),
}, uint32(monster.MonsterId), uint8(monster.Level), g.GetTempFightPropMap(), uint32(monster.ConfigId), objectId)
case *gdconf.Npc:
npc := entityConfig.(*gdconf.Npc)
return scene.CreateEntityNpc(&model.Vector{
X: float64(npc.Pos.X),
Y: float64(npc.Pos.Y),
Z: float64(npc.Pos.Z),
}, &model.Vector{
X: float64(npc.Rot.X),
Y: float64(npc.Rot.Y),
Z: float64(npc.Rot.Z),
}, uint32(npc.NpcId), 0, 0, 0, uint32(npc.ConfigId), objectId)
case *gdconf.Gadget:
gadget := entityConfig.(*gdconf.Gadget)
// 70500000并不是实际的装置id 根据节点类型对应采集物配置表
if gadget.PointType != 0 && gadget.GadgetId == 70500000 {
gatherDataConfig := gdconf.GetGatherDataByPointType(gadget.PointType)
if gatherDataConfig == nil {
return 0
}
return scene.CreateEntityGadgetGather(&model.Vector{
X: float64(gadget.Pos.X),
Y: float64(gadget.Pos.Y),
Z: float64(gadget.Pos.Z),
}, &model.Vector{
X: float64(gadget.Rot.X),
Y: float64(gadget.Rot.Y),
Z: float64(gadget.Rot.Z),
}, uint32(gatherDataConfig.GadgetId), uint32(gatherDataConfig.GatherId), uint32(gadget.ConfigId), objectId)
} else {
return scene.CreateEntityGadgetNormal(&model.Vector{
X: float64(gadget.Pos.X),
Y: float64(gadget.Pos.Y),
Z: float64(gadget.Pos.Z),
}, &model.Vector{
X: float64(gadget.Rot.X),
Y: float64(gadget.Rot.Y),
Z: float64(gadget.Rot.Z),
}, uint32(gadget.GadgetId), uint32(gadget.ConfigId), objectId)
}
default:
return 0
}
}
func (g *GameManager) PacketPlayerEnterSceneNotifyLogin(player *model.Player, enterType proto.EnterType) *proto.PlayerEnterSceneNotify { func (g *GameManager) PacketPlayerEnterSceneNotifyLogin(player *model.Player, enterType proto.EnterType) *proto.PlayerEnterSceneNotify {
world := WORLD_MANAGER.GetWorldByID(player.WorldId) world := WORLD_MANAGER.GetWorldByID(player.WorldId)
scene := world.GetSceneById(player.SceneId) scene := world.GetSceneById(player.SceneId)
@@ -550,8 +500,8 @@ func (g *GameManager) AddSceneEntityNotifyBroadcast(player *model.Player, scene
continue continue
} }
g.SendMsg(cmd.SceneEntityAppearNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, sceneEntityAppearNotify) g.SendMsg(cmd.SceneEntityAppearNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, sceneEntityAppearNotify)
// logger.Debug("SceneEntityAppearNotify, uid: %v, type: %v, len: %v", logger.Debug("SceneEntityAppearNotify, uid: %v, type: %v, len: %v",
// scenePlayer.PlayerID, sceneEntityAppearNotify.AppearType, len(sceneEntityAppearNotify.EntityList)) scenePlayer.PlayerID, sceneEntityAppearNotify.AppearType, len(sceneEntityAppearNotify.EntityList))
} }
} }
@@ -561,8 +511,8 @@ func (g *GameManager) RemoveSceneEntityNotifyToPlayer(player *model.Player, visi
DisappearType: visionType, DisappearType: visionType,
} }
g.SendMsg(cmd.SceneEntityDisappearNotify, player.PlayerID, player.ClientSeq, sceneEntityDisappearNotify) g.SendMsg(cmd.SceneEntityDisappearNotify, player.PlayerID, player.ClientSeq, sceneEntityDisappearNotify)
// logger.Debug("SceneEntityDisappearNotify, uid: %v, type: %v, len: %v", logger.Debug("SceneEntityDisappearNotify, uid: %v, type: %v, len: %v",
// player.PlayerID, sceneEntityDisappearNotify.DisappearType, len(sceneEntityDisappearNotify.EntityList)) player.PlayerID, sceneEntityDisappearNotify.DisappearType, len(sceneEntityDisappearNotify.EntityList))
} }
func (g *GameManager) RemoveSceneEntityNotifyBroadcast(scene *Scene, visionType proto.VisionType, entityIdList []uint32) { func (g *GameManager) RemoveSceneEntityNotifyBroadcast(scene *Scene, visionType proto.VisionType, entityIdList []uint32) {
@@ -995,9 +945,9 @@ func (g *GameManager) PacketSceneGadgetInfoNormal(entity *Entity) *proto.SceneGa
gadgetEntity := entity.GetGadgetEntity() gadgetEntity := entity.GetGadgetEntity()
sceneGadgetInfo := &proto.SceneGadgetInfo{ sceneGadgetInfo := &proto.SceneGadgetInfo{
GadgetId: gadgetEntity.GetGadgetId(), GadgetId: gadgetEntity.GetGadgetId(),
GroupId: 0, GroupId: entity.GetGroupId(),
ConfigId: entity.GetConfigId(), ConfigId: entity.GetConfigId(),
GadgetState: 0, GadgetState: gadgetEntity.GetGadgetState(),
IsEnableInteract: true, IsEnableInteract: true,
AuthorityPeerId: 1, AuthorityPeerId: 1,
} }
@@ -1014,9 +964,9 @@ func (g *GameManager) PacketSceneGadgetInfoGather(entity *Entity) *proto.SceneGa
} }
sceneGadgetInfo := &proto.SceneGadgetInfo{ sceneGadgetInfo := &proto.SceneGadgetInfo{
GadgetId: gadgetEntity.GetGadgetId(), GadgetId: gadgetEntity.GetGadgetId(),
GroupId: 0, GroupId: entity.GetGroupId(),
ConfigId: entity.GetConfigId(), ConfigId: entity.GetConfigId(),
GadgetState: 0, GadgetState: gadgetEntity.GetGadgetState(),
IsEnableInteract: true, IsEnableInteract: true,
AuthorityPeerId: 1, AuthorityPeerId: 1,
Content: &proto.SceneGadgetInfo_GatherGadget{ Content: &proto.SceneGadgetInfo_GatherGadget{
@@ -1071,24 +1021,3 @@ func (g *GameManager) PacketDelTeamEntityNotify(scene *Scene, player *model.Play
} }
return delTeamEntityNotify return delTeamEntityNotify
} }
func (g *GameManager) GetTempFightPropMap() map[uint32]float32 {
fpm := map[uint32]float32{
constant.FIGHT_PROP_CUR_HP: float32(72.91699),
constant.FIGHT_PROP_PHYSICAL_SUB_HURT: float32(0.1),
constant.FIGHT_PROP_CUR_DEFENSE: float32(505.0),
constant.FIGHT_PROP_CUR_ATTACK: float32(45.679916),
constant.FIGHT_PROP_ICE_SUB_HURT: float32(0.1),
constant.FIGHT_PROP_BASE_ATTACK: float32(45.679916),
constant.FIGHT_PROP_MAX_HP: float32(72.91699),
constant.FIGHT_PROP_FIRE_SUB_HURT: float32(0.1),
constant.FIGHT_PROP_ELEC_SUB_HURT: float32(0.1),
constant.FIGHT_PROP_WIND_SUB_HURT: float32(0.1),
constant.FIGHT_PROP_ROCK_SUB_HURT: float32(0.1),
constant.FIGHT_PROP_GRASS_SUB_HURT: float32(0.1),
constant.FIGHT_PROP_WATER_SUB_HURT: float32(0.1),
constant.FIGHT_PROP_BASE_HP: float32(72.91699),
constant.FIGHT_PROP_BASE_DEFENSE: float32(505.0),
}
return fpm
}

View File

@@ -59,7 +59,7 @@ func (g *GameManager) CreateVehicleReq(player *model.Player, payloadMsg pb.Messa
// 创建载具实体 // 创建载具实体
pos := &model.Vector{X: float64(req.Pos.X), Y: float64(req.Pos.Y), Z: float64(req.Pos.Z)} pos := &model.Vector{X: float64(req.Pos.X), Y: float64(req.Pos.Y), Z: float64(req.Pos.Z)}
rot := &model.Vector{X: float64(req.Rot.X), Y: float64(req.Rot.Y), Z: float64(req.Rot.Z)} rot := &model.Vector{X: float64(req.Rot.X), Y: float64(req.Rot.Y), Z: float64(req.Rot.Z)}
entityId := scene.CreateEntityGadgetVehicle(player.PlayerID, pos, rot, req.VehicleId) entityId := scene.CreateEntityGadgetVehicle(player, pos, rot, req.VehicleId)
if entityId == 0 { if entityId == 0 {
logger.Error("vehicle entityId is 0, uid: %v", player.PlayerID) logger.Error("vehicle entityId is 0, uid: %v", player.PlayerID)
g.SendError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{}) g.SendError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{})

View File

@@ -717,14 +717,14 @@ func (w *World) RemoveWaitPlayer(uid uint32) {
func (w *World) CreateScene(sceneId uint32) *Scene { func (w *World) CreateScene(sceneId uint32) *Scene {
scene := &Scene{ scene := &Scene{
id: sceneId, id: sceneId,
world: w, world: w,
playerMap: make(map[uint32]*model.Player), playerMap: make(map[uint32]*model.Player),
entityMap: make(map[uint32]*Entity), entityMap: make(map[uint32]*Entity),
objectIdEntityMap: make(map[uint64]*Entity), groupMap: make(map[uint32]*Group),
gameTime: 18 * 60, gameTime: 18 * 60,
createTime: time.Now().UnixMilli(), createTime: time.Now().UnixMilli(),
meeoIndex: 0, meeoIndex: 0,
} }
w.sceneMap[sceneId] = scene w.sceneMap[sceneId] = scene
return scene return scene

View File

@@ -5,6 +5,7 @@ import (
"time" "time"
"hk4e/common/constant" "hk4e/common/constant"
"hk4e/gdconf"
"hk4e/gs/model" "hk4e/gs/model"
"hk4e/pkg/logger" "hk4e/pkg/logger"
"hk4e/protocol/cmd" "hk4e/protocol/cmd"
@@ -13,14 +14,40 @@ import (
// Scene 场景数据结构 // Scene 场景数据结构
type Scene struct { type Scene struct {
id uint32 id uint32
world *World world *World
playerMap map[uint32]*model.Player playerMap map[uint32]*model.Player
entityMap map[uint32]*Entity entityMap map[uint32]*Entity
objectIdEntityMap map[uint64]*Entity // 用于标识配置档里的唯一实体是否已被创建 groupMap map[uint32]*Group
gameTime uint32 // 游戏内提瓦特大陆的时间 gameTime uint32 // 游戏内提瓦特大陆的时间
createTime int64 // 场景创建时间 createTime int64 // 场景创建时间
meeoIndex uint32 // 客户端风元素染色同步协议的计数器 meeoIndex uint32 // 客户端风元素染色同步协议的计数器
}
type Group struct {
suiteMap map[uint8]*Suite
}
func (g *Group) GetAllSuite() map[uint8]*Suite {
return g.suiteMap
}
func (g *Group) GetAllEntity() map[uint32]*Entity {
entityMap := make(map[uint32]*Entity)
for _, suite := range g.suiteMap {
for _, entity := range suite.entityMap {
entityMap[entity.id] = entity
}
}
return entityMap
}
type Suite struct {
entityMap map[uint32]*Entity
}
func (s *Suite) GetAllEntity() map[uint32]*Entity {
return s.entityMap
} }
func (s *Scene) GetId() uint32 { func (s *Scene) GetId() uint32 {
@@ -39,6 +66,14 @@ func (s *Scene) GetAllEntity() map[uint32]*Entity {
return s.entityMap return s.entityMap
} }
func (s *Scene) GetGroupById(groupId uint32) *Group {
return s.groupMap[groupId]
}
func (s *Scene) GetAllGroup() map[uint32]*Group {
return s.groupMap
}
func (s *Scene) GetGameTime() uint32 { func (s *Scene) GetGameTime() uint32 {
return s.gameTime return s.gameTime
} }
@@ -161,7 +196,7 @@ func (s *Scene) CreateEntityAvatar(player *model.Player, avatarId uint32) uint32
avatarId: avatarId, avatarId: avatarId,
}, },
} }
s.CreateEntity(entity, 0) s.CreateEntity(entity)
return entity.id return entity.id
} }
@@ -179,15 +214,11 @@ func (s *Scene) CreateEntityWeapon() uint32 {
fightProp: nil, fightProp: nil,
entityType: constant.ENTITY_TYPE_WEAPON, entityType: constant.ENTITY_TYPE_WEAPON,
} }
s.CreateEntity(entity, 0) s.CreateEntity(entity)
return entity.id return entity.id
} }
func (s *Scene) CreateEntityMonster(pos, rot *model.Vector, monsterId uint32, level uint8, fightProp map[uint32]float32, configId uint32, objectId uint64) uint32 { func (s *Scene) CreateEntityMonster(pos, rot *model.Vector, monsterId uint32, level uint8, fightProp map[uint32]float32, configId, groupId uint32) uint32 {
_, exist := s.objectIdEntityMap[objectId]
if exist {
return 0
}
entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_MONSTER) entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_MONSTER)
entity := &Entity{ entity := &Entity{
id: entityId, id: entityId,
@@ -205,17 +236,13 @@ func (s *Scene) CreateEntityMonster(pos, rot *model.Vector, monsterId uint32, le
monsterId: monsterId, monsterId: monsterId,
}, },
configId: configId, configId: configId,
objectId: objectId, groupId: groupId,
} }
s.CreateEntity(entity, objectId) s.CreateEntity(entity)
return entity.id return entity.id
} }
func (s *Scene) CreateEntityNpc(pos, rot *model.Vector, npcId, roomId, parentQuestId, blockId, configId uint32, objectId uint64) uint32 { func (s *Scene) CreateEntityNpc(pos, rot *model.Vector, npcId, roomId, parentQuestId, blockId, configId, groupId uint32) uint32 {
_, exist := s.objectIdEntityMap[objectId]
if exist {
return 0
}
entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_NPC) entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_NPC)
entity := &Entity{ entity := &Entity{
id: entityId, id: entityId,
@@ -239,17 +266,13 @@ func (s *Scene) CreateEntityNpc(pos, rot *model.Vector, npcId, roomId, parentQue
BlockId: blockId, BlockId: blockId,
}, },
configId: configId, configId: configId,
objectId: objectId, groupId: groupId,
} }
s.CreateEntity(entity, objectId) s.CreateEntity(entity)
return entity.id return entity.id
} }
func (s *Scene) CreateEntityGadgetNormal(pos, rot *model.Vector, gadgetId uint32, configId uint32, objectId uint64) uint32 { func (s *Scene) CreateEntityGadgetNormal(pos, rot *model.Vector, gadgetId, gadgetState, configId, groupId uint32) uint32 {
_, exist := s.objectIdEntityMap[objectId]
if exist {
return 0
}
entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_GADGET) entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_GADGET)
entity := &Entity{ entity := &Entity{
id: entityId, id: entityId,
@@ -267,21 +290,18 @@ func (s *Scene) CreateEntityGadgetNormal(pos, rot *model.Vector, gadgetId uint32
}, },
entityType: constant.ENTITY_TYPE_GADGET, entityType: constant.ENTITY_TYPE_GADGET,
gadgetEntity: &GadgetEntity{ gadgetEntity: &GadgetEntity{
gadgetId: gadgetId, gadgetId: gadgetId,
gadgetType: GADGET_TYPE_NORMAL, gadgetState: gadgetState,
gadgetType: GADGET_TYPE_NORMAL,
}, },
configId: configId, configId: configId,
objectId: objectId, groupId: groupId,
} }
s.CreateEntity(entity, objectId) s.CreateEntity(entity)
return entity.id return entity.id
} }
func (s *Scene) CreateEntityGadgetGather(pos, rot *model.Vector, gadgetId uint32, gatherId uint32, configId uint32, objectId uint64) uint32 { func (s *Scene) CreateEntityGadgetGather(pos, rot *model.Vector, gadgetId, gadgetState, gatherId, configId, groupId uint32) uint32 {
_, exist := s.objectIdEntityMap[objectId]
if exist {
return 0
}
entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_GADGET) entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_GADGET)
entity := &Entity{ entity := &Entity{
id: entityId, id: entityId,
@@ -299,20 +319,21 @@ func (s *Scene) CreateEntityGadgetGather(pos, rot *model.Vector, gadgetId uint32
}, },
entityType: constant.ENTITY_TYPE_GADGET, entityType: constant.ENTITY_TYPE_GADGET,
gadgetEntity: &GadgetEntity{ gadgetEntity: &GadgetEntity{
gadgetId: gadgetId, gadgetId: gadgetId,
gadgetType: GADGET_TYPE_GATHER, gadgetState: gadgetState,
gadgetType: GADGET_TYPE_GATHER,
gadgetGatherEntity: &GadgetGatherEntity{ gadgetGatherEntity: &GadgetGatherEntity{
gatherId: gatherId, gatherId: gatherId,
}, },
}, },
configId: configId, configId: configId,
objectId: objectId, groupId: groupId,
} }
s.CreateEntity(entity, objectId) s.CreateEntity(entity)
return entity.id return entity.id
} }
func (s *Scene) CreateEntityGadgetClient(pos, rot *model.Vector, entityId uint32, configId, campId, campType, ownerEntityId, targetEntityId, propOwnerEntityId uint32) { func (s *Scene) CreateEntityGadgetClient(pos, rot *model.Vector, entityId, configId, campId, campType, ownerEntityId, targetEntityId, propOwnerEntityId uint32) {
entity := &Entity{ entity := &Entity{
id: entityId, id: entityId,
scene: s, scene: s,
@@ -340,15 +361,10 @@ func (s *Scene) CreateEntityGadgetClient(pos, rot *model.Vector, entityId uint32
}, },
}, },
} }
s.CreateEntity(entity, 0) s.CreateEntity(entity)
} }
func (s *Scene) CreateEntityGadgetVehicle(uid uint32, pos, rot *model.Vector, vehicleId uint32) uint32 { func (s *Scene) CreateEntityGadgetVehicle(player *model.Player, pos, rot *model.Vector, vehicleId uint32) uint32 {
player := USER_MANAGER.GetOnlineUser(uid)
if player == nil {
logger.Error("player is nil, uid: %v", uid)
return 0
}
entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_GADGET) entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_GADGET)
entity := &Entity{ entity := &Entity{
id: entityId, id: entityId,
@@ -377,18 +393,15 @@ func (s *Scene) CreateEntityGadgetVehicle(uid uint32, pos, rot *model.Vector, ve
}, },
}, },
} }
s.CreateEntity(entity, 0) s.CreateEntity(entity)
return entity.id return entity.id
} }
func (s *Scene) CreateEntity(entity *Entity, objectId uint64) { func (s *Scene) CreateEntity(entity *Entity) {
if len(s.entityMap) >= ENTITY_MAX_SEND_NUM && !ENTITY_NUM_UNLIMIT { if len(s.entityMap) >= ENTITY_MAX_SEND_NUM && !ENTITY_NUM_UNLIMIT {
logger.Error("above max scene entity num limit: %v, id: %v, pos: %v", ENTITY_MAX_SEND_NUM, entity.id, entity.pos) logger.Error("above max scene entity num limit: %v, id: %v, pos: %v", ENTITY_MAX_SEND_NUM, entity.id, entity.pos)
return return
} }
if objectId != 0 {
s.objectIdEntityMap[objectId] = entity
}
s.entityMap[entity.id] = entity s.entityMap[entity.id] = entity
} }
@@ -398,15 +411,145 @@ func (s *Scene) DestroyEntity(entityId uint32) {
return return
} }
delete(s.entityMap, entity.id) delete(s.entityMap, entity.id)
delete(s.objectIdEntityMap, entity.objectId)
} }
func (s *Scene) GetEntity(entityId uint32) *Entity { func (s *Scene) GetEntity(entityId uint32) *Entity {
return s.entityMap[entityId] return s.entityMap[entityId]
} }
func (s *Scene) GetEntityByObjectId(objectId uint64) *Entity { func (s *Scene) AddGroupSuite(groupId uint32, suiteId uint8) {
return s.objectIdEntityMap[objectId] groupConfig := gdconf.GetSceneGroup(int32(groupId))
if groupConfig == nil {
return
}
suiteConfig := groupConfig.SuiteList[suiteId-1]
suite := &Suite{
entityMap: make(map[uint32]*Entity),
}
for _, monsterConfigId := range suiteConfig.MonsterConfigIdList {
monster, exist := groupConfig.MonsterMap[monsterConfigId]
if !exist {
continue
}
entityId := s.createConfigEntity(uint32(groupConfig.Id), monster)
entity := s.GetEntity(entityId)
suite.entityMap[entityId] = entity
}
for _, gadgetConfigId := range suiteConfig.GadgetConfigIdList {
gadget, exist := groupConfig.GadgetMap[gadgetConfigId]
if !exist {
continue
}
entityId := s.createConfigEntity(uint32(groupConfig.Id), gadget)
entity := s.GetEntity(entityId)
suite.entityMap[entityId] = entity
}
for _, npc := range groupConfig.NpcMap {
entityId := s.createConfigEntity(uint32(groupConfig.Id), npc)
entity := s.GetEntity(entityId)
suite.entityMap[entityId] = entity
}
group, exist := s.groupMap[groupId]
if !exist {
group = &Group{
suiteMap: make(map[uint8]*Suite),
}
}
group.suiteMap[suiteId] = suite
}
func (s *Scene) RemoveGroupSuite(groupId uint32, suiteId uint8) {
group := s.groupMap[groupId]
if group == nil {
return
}
suite := group.suiteMap[suiteId]
if suite == nil {
return
}
for _, entity := range suite.entityMap {
s.DestroyEntity(entity.id)
}
delete(group.suiteMap, suiteId)
}
// 创建配置表里的实体
func (s *Scene) createConfigEntity(groupId uint32, entityConfig any) uint32 {
switch entityConfig.(type) {
case *gdconf.Monster:
monster := entityConfig.(*gdconf.Monster)
return s.CreateEntityMonster(&model.Vector{
X: float64(monster.Pos.X),
Y: float64(monster.Pos.Y),
Z: float64(monster.Pos.Z),
}, &model.Vector{
X: float64(monster.Rot.X),
Y: float64(monster.Rot.Y),
Z: float64(monster.Rot.Z),
}, uint32(monster.MonsterId), uint8(monster.Level), getTempFightPropMap(), uint32(monster.ConfigId), groupId)
case *gdconf.Npc:
npc := entityConfig.(*gdconf.Npc)
return s.CreateEntityNpc(&model.Vector{
X: float64(npc.Pos.X),
Y: float64(npc.Pos.Y),
Z: float64(npc.Pos.Z),
}, &model.Vector{
X: float64(npc.Rot.X),
Y: float64(npc.Rot.Y),
Z: float64(npc.Rot.Z),
}, uint32(npc.NpcId), 0, 0, 0, uint32(npc.ConfigId), groupId)
case *gdconf.Gadget:
gadget := entityConfig.(*gdconf.Gadget)
// 70500000并不是实际的装置id 根据节点类型对应采集物配置表
if gadget.PointType != 0 && gadget.GadgetId == 70500000 {
gatherDataConfig := gdconf.GetGatherDataByPointType(gadget.PointType)
if gatherDataConfig == nil {
return 0
}
return s.CreateEntityGadgetGather(&model.Vector{
X: float64(gadget.Pos.X),
Y: float64(gadget.Pos.Y),
Z: float64(gadget.Pos.Z),
}, &model.Vector{
X: float64(gadget.Rot.X),
Y: float64(gadget.Rot.Y),
Z: float64(gadget.Rot.Z),
}, uint32(gatherDataConfig.GadgetId), uint32(constant.GADGET_STATE_DEFAULT), uint32(gatherDataConfig.GatherId), uint32(gadget.ConfigId), groupId)
} else {
return s.CreateEntityGadgetNormal(&model.Vector{
X: float64(gadget.Pos.X),
Y: float64(gadget.Pos.Y),
Z: float64(gadget.Pos.Z),
}, &model.Vector{
X: float64(gadget.Rot.X),
Y: float64(gadget.Rot.Y),
Z: float64(gadget.Rot.Z),
}, uint32(gadget.GadgetId), uint32(gadget.State), uint32(gadget.ConfigId), groupId)
}
default:
return 0
}
}
func getTempFightPropMap() map[uint32]float32 {
fpm := map[uint32]float32{
constant.FIGHT_PROP_CUR_HP: float32(72.91699),
constant.FIGHT_PROP_PHYSICAL_SUB_HURT: float32(0.1),
constant.FIGHT_PROP_CUR_DEFENSE: float32(505.0),
constant.FIGHT_PROP_CUR_ATTACK: float32(45.679916),
constant.FIGHT_PROP_ICE_SUB_HURT: float32(0.1),
constant.FIGHT_PROP_BASE_ATTACK: float32(45.679916),
constant.FIGHT_PROP_MAX_HP: float32(72.91699),
constant.FIGHT_PROP_FIRE_SUB_HURT: float32(0.1),
constant.FIGHT_PROP_ELEC_SUB_HURT: float32(0.1),
constant.FIGHT_PROP_WIND_SUB_HURT: float32(0.1),
constant.FIGHT_PROP_ROCK_SUB_HURT: float32(0.1),
constant.FIGHT_PROP_GRASS_SUB_HURT: float32(0.1),
constant.FIGHT_PROP_WATER_SUB_HURT: float32(0.1),
constant.FIGHT_PROP_BASE_HP: float32(72.91699),
constant.FIGHT_PROP_BASE_DEFENSE: float32(505.0),
}
return fpm
} }
// Entity 场景实体数据结构 // Entity 场景实体数据结构
@@ -426,8 +569,8 @@ type Entity struct {
monsterEntity *MonsterEntity monsterEntity *MonsterEntity
npcEntity *NpcEntity npcEntity *NpcEntity
gadgetEntity *GadgetEntity gadgetEntity *GadgetEntity
configId uint32 // 配置相关 configId uint32 // LUA配置相关
objectId uint64 groupId uint32
} }
func (e *Entity) GetId() uint32 { func (e *Entity) GetId() uint32 {
@@ -502,6 +645,10 @@ func (e *Entity) GetConfigId() uint32 {
return e.configId return e.configId
} }
func (e *Entity) GetGroupId() uint32 {
return e.groupId
}
type AvatarEntity struct { type AvatarEntity struct {
uid uint32 uid uint32
avatarId uint32 avatarId uint32
@@ -533,6 +680,7 @@ type NpcEntity struct {
type GadgetEntity struct { type GadgetEntity struct {
gadgetType int gadgetType int
gadgetId uint32 gadgetId uint32
gadgetState uint32
gadgetClientEntity *GadgetClientEntity gadgetClientEntity *GadgetClientEntity
gadgetGatherEntity *GadgetGatherEntity gadgetGatherEntity *GadgetGatherEntity
gadgetVehicleEntity *GadgetVehicleEntity gadgetVehicleEntity *GadgetVehicleEntity
@@ -546,6 +694,10 @@ func (g *GadgetEntity) GetGadgetId() uint32 {
return g.gadgetId return g.gadgetId
} }
func (g *GadgetEntity) GetGadgetState() uint32 {
return g.gadgetState
}
func (g *GadgetEntity) GetGadgetClientEntity() *GadgetClientEntity { func (g *GadgetEntity) GetGadgetClientEntity() *GadgetClientEntity {
return g.gadgetClientEntity return g.gadgetClientEntity
} }

View File

@@ -161,9 +161,9 @@ func regionCubicContainPos(cubic *RegionCubic, pos *Vector3) bool {
// 检测一个点是否在球体内 // 检测一个点是否在球体内
func regionSphereContainPos(sphere *RegionSphere, pos *Vector3) bool { func regionSphereContainPos(sphere *RegionSphere, pos *Vector3) bool {
distance3D := math.Sqrt(math.Pow(float64(sphere.pos.X-pos.X), 2) + distance3D := math.Sqrt(float64(sphere.pos.X-pos.X)*float64(sphere.pos.X-pos.X) +
math.Pow(float64(sphere.pos.Y-pos.Y), 2) + float64(sphere.pos.Y-pos.Y)*float64(sphere.pos.Y-pos.Y) +
math.Pow(float64(sphere.pos.Z-pos.Z), 2)) float64(sphere.pos.Z-pos.Z)*float64(sphere.pos.Z-pos.Z))
if float32(distance3D) < sphere.radius { if float32(distance3D) < sphere.radius {
return true return true
} else { } else {
@@ -173,8 +173,8 @@ func regionSphereContainPos(sphere *RegionSphere, pos *Vector3) bool {
// 检测一个点是否在圆柱体内 // 检测一个点是否在圆柱体内
func regionCylinderContainPos(cylinder *RegionCylinder, pos *Vector3) bool { func regionCylinderContainPos(cylinder *RegionCylinder, pos *Vector3) bool {
distance2D := math.Sqrt(math.Pow(float64(cylinder.pos.X-pos.X), 2) + distance2D := math.Sqrt(float64(cylinder.pos.X-pos.X)*float64(cylinder.pos.X-pos.X) +
math.Pow(float64(cylinder.pos.Z-pos.Z), 2)) float64(cylinder.pos.Z-pos.Z)*float64(cylinder.pos.Z-pos.Z))
if float32(distance2D) >= cylinder.radius { if float32(distance2D) >= cylinder.radius {
return false return false
} }