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

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

View File

@@ -167,6 +167,11 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p
X: float64(motionInfo.Pos.X),
Y: float64(motionInfo.Pos.Y),
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())
// 更新玩家的位置信息
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)
if world == nil {
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)
oldGroupList := aoiManager.GetObjectListByPos(float32(oldPos.X), 0.0, float32(oldPos.Z))
for groupId, groupAny := range oldGroupList {
group := 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))
groupConfig := groupAny.(*gdconf.Group)
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 {
continue
}
if group.DynamicLoad {
if groupConfig.DynamicLoad {
continue
}
oldVisionGroupMap[uint32(groupId)] = group
oldVisionGroupMap[uint32(groupId)] = groupConfig
}
// 新位置视野范围内的group
newVisionGroupMap := make(map[uint32]*gdconf.Group)
newGroupList := aoiManager.GetObjectListByPos(float32(newPos.X), 0.0, float32(newPos.Z))
for groupId, groupAny := range newGroupList {
group := 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))
groupConfig := groupAny.(*gdconf.Group)
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 {
continue
}
if group.DynamicLoad {
if groupConfig.DynamicLoad {
continue
}
newVisionGroupMap[uint32(groupId)] = group
newVisionGroupMap[uint32(groupId)] = groupConfig
}
// 消失的场景实体
delEntityIdList := make([]uint32, 0)
for groupId, group := range oldVisionGroupMap {
for groupId, groupConfig := range oldVisionGroupMap {
_, exist := newVisionGroupMap[groupId]
if exist {
continue
}
// 旧有新没有的group即为消失的
for _, monster := range group.MonsterList {
entity := scene.GetEntityByObjectId(monster.ObjectId)
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())
group := scene.GetGroupById(groupId)
for _, entity := range group.GetAllEntity() {
delEntityIdList = append(delEntityIdList, entity.GetId())
}
g.RemoveGroup(scene, groupConfig)
}
// 出现的场景实体
addEntityIdList := make([]uint32, 0)
for groupId, group := range newVisionGroupMap {
for groupId, groupConfig := range newVisionGroupMap {
_, exist := oldVisionGroupMap[groupId]
if exist {
continue
}
// 新有旧没有的group即为出现的
for _, monster := range group.MonsterList {
entityId := g.CreateConfigEntity(scene, monster.ObjectId, monster)
addEntityIdList = append(addEntityIdList, entityId)
}
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.AddSceneGroup(scene, groupConfig)
group := scene.GetGroupById(groupId)
for _, entity := range group.GetAllEntity() {
addEntityIdList = append(addEntityIdList, entity.GetId())
}
}
// 同步客户端消失和出现的场景实体
g.RemoveSceneEntityNotifyToPlayer(player, proto.VisionType_VISION_MISS, delEntityIdList)
g.AddSceneEntityNotify(player, proto.VisionType_VISION_MEET, addEntityIdList, false, false)
// 场景区域触发器
for _, group := range newVisionGroupMap {
for _, region := range group.RegionList {
shape := alg.NewShape()
switch uint8(region.Shape) {
case constant.REGION_SHAPE_SPHERE:
shape.NewSphere(&alg.Vector3{X: region.Pos.X, Y: region.Pos.Y, Z: region.Pos.Z}, region.Radius)
case constant.REGION_SHAPE_CUBIC:
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})
case constant.REGION_SHAPE_CYLINDER:
shape.NewCylinder(&alg.Vector3{X: region.Pos.X, Y: region.Pos.Y, Z: region.Pos.Z},
region.Radius, region.Height)
case constant.REGION_SHAPE_POLYGON:
vector2PointArray := make([]*alg.Vector2, 0)
for _, vector := range region.PointArray {
// z就是y
vector2PointArray = append(vector2PointArray, &alg.Vector2{X: vector.X, Z: vector.Y})
}
shape.NewPolygon(&alg.Vector3{X: region.Pos.X, Y: region.Pos.Y, Z: region.Pos.Z},
vector2PointArray, region.Height)
}
oldPosInRegion := shape.Contain(&alg.Vector3{
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", region, player.PlayerID)
for _, trigger := range group.TriggerList {
if trigger.Event != constant.LUA_EVENT_ENTER_REGION {
continue
}
// TriggerCheck 场景区域触发器检测
func (g *GameManager) TriggerCheck(player *model.Player, oldPos *model.Vector, newPos *model.Vector, entityId uint32) {
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
if world == nil {
logger.Error("get player world is nil, uid: %v", player.PlayerID)
return
}
scene := world.GetSceneById(player.SceneId)
for groupId, group := range scene.GetAllGroup() {
groupConfig := gdconf.GetSceneGroup(int32(groupId))
if groupConfig == nil {
continue
}
for suiteId := range group.GetAllSuite() {
suiteConfig := groupConfig.SuiteList[suiteId-1]
for _, regionConfigId := range suiteConfig.RegionConfigIdList {
regionConfig := groupConfig.RegionMap[regionConfigId]
shape := alg.NewShape()
switch uint8(regionConfig.Shape) {
case constant.REGION_SHAPE_SPHERE:
shape.NewSphere(&alg.Vector3{X: regionConfig.Pos.X, Y: regionConfig.Pos.Y, Z: regionConfig.Pos.Z}, regionConfig.Radius)
case constant.REGION_SHAPE_CUBIC:
shape.NewCubic(&alg.Vector3{X: regionConfig.Pos.X, Y: regionConfig.Pos.Y, Z: regionConfig.Pos.Z},
&alg.Vector3{X: regionConfig.Size.X, Y: regionConfig.Size.Y, Z: regionConfig.Size.Z})
case constant.REGION_SHAPE_CYLINDER:
shape.NewCylinder(&alg.Vector3{X: regionConfig.Pos.X, Y: regionConfig.Pos.Y, Z: regionConfig.Pos.Z},
regionConfig.Radius, regionConfig.Height)
case constant.REGION_SHAPE_POLYGON:
vector2PointArray := make([]*alg.Vector2, 0)
for _, vector := range regionConfig.PointArray {
// z就是y
vector2PointArray = append(vector2PointArray, &alg.Vector2{X: vector.X, Z: vector.Y})
}
if trigger.Condition != "" {
cond := CallLuaFunc(group.GetLuaState(), trigger.Condition,
&LuaCtx{uid: player.PlayerID},
&LuaEvt{param1: region.ConfigId, targetEntityId: entityId})
if !cond {
shape.NewPolygon(&alg.Vector3{X: regionConfig.Pos.X, Y: regionConfig.Pos.Y, Z: regionConfig.Pos.Z},
vector2PointArray, regionConfig.Height)
}
oldPosInRegion := shape.Contain(&alg.Vector3{
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
}
}
logger.Debug("scene group trigger fire, trigger: %v, uid: %v", trigger, player.PlayerID)
if trigger.Action != "" {
logger.Debug("scene group trigger do action, trigger: %v, uid: %v", trigger, player.PlayerID)
ok := CallLuaFunc(group.GetLuaState(), trigger.Action,
&LuaCtx{uid: player.PlayerID},
&LuaEvt{})
if !ok {
logger.Error("trigger action fail, trigger: %v, uid: %v", trigger, player.PlayerID)
if triggerConfig.Condition != "" {
cond := CallLuaFunc(groupConfig.GetLuaState(), triggerConfig.Condition,
&LuaCtx{uid: player.PlayerID},
&LuaEvt{param1: regionConfig.ConfigId, targetEntityId: entityId})
if !cond {
continue
}
}
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", region, player.PlayerID)
for _, trigger := range group.TriggerList {
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 {
} else if oldPosInRegion && !newPosInRegion {
logger.Debug("player leave region: %v, uid: %v", regionConfig, player.PlayerID)
for _, triggerName := range suiteConfig.TriggerNameList {
triggerConfig := groupConfig.TriggerMap[triggerName]
if triggerConfig.Event != constant.LUA_EVENT_LEAVE_REGION {
continue
}
}
logger.Debug("scene group trigger fire, trigger: %v, uid: %v", trigger, player.PlayerID)
if trigger.Action != "" {
logger.Debug("scene group trigger do action, trigger: %v, uid: %v", trigger, player.PlayerID)
ok := CallLuaFunc(group.GetLuaState(), trigger.Action,
&LuaCtx{uid: player.PlayerID},
&LuaEvt{})
if !ok {
logger.Error("trigger action fail, trigger: %v, uid: %v", trigger, player.PlayerID)
if triggerConfig.Condition != "" {
cond := CallLuaFunc(groupConfig.GetLuaState(), triggerConfig.Condition,
&LuaCtx{uid: player.PlayerID},
&LuaEvt{param1: regionConfig.ConfigId, targetEntityId: entityId})
if !cond {
continue
}
}
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 {
logger.Error("drop group not found, drop id: %v", gachaType)
return false, 0
@@ -417,7 +417,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab
PurpleTimesFixValue = WeaponPurpleTimesFixValue
}
if gachaPoolInfo.OrangeTimes >= OrangeTimesFixThreshold || gachaPoolInfo.PurpleTimes >= PurpleTimesFixThreshold {
fixDropGroupDataConfig := new(gdconf.DropGroupData)
fixDropGroupDataConfig := new(gdconf.GachaDropGroupData)
fixDropGroupDataConfig.DropId = dropGroupDataConfig.DropId
fixDropGroupDataConfig.WeightAll = dropGroupDataConfig.WeightAll
// 计算4星和5星权重修正值
@@ -430,7 +430,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab
addPurpleWeight = 0
}
for _, drop := range dropGroupDataConfig.DropConfig {
fixDrop := new(gdconf.Drop)
fixDrop := new(gdconf.GachaDrop)
fixDrop.Result = drop.Result
fixDrop.DropId = drop.DropId
fixDrop.IsEnd = drop.IsEnd
@@ -525,7 +525,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab
// 替换本次结果为5星大保底
if gachaPoolInfo.MustGetUpOrange {
logger.Debug("trigger must get up orange, uid: %v", userId)
upOrangeDropGroupDataConfig := gdconf.CONF.DropGroupDataMap[upOrangeDropId]
upOrangeDropGroupDataConfig := gdconf.CONF.GachaDropGroupDataMap[upOrangeDropId]
if upOrangeDropGroupDataConfig == nil {
logger.Error("drop group not found, drop id: %v", upOrangeDropId)
return false, 0
@@ -552,7 +552,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab
// 替换本次结果为4星大保底
if gachaPoolInfo.MustGetUpPurple {
logger.Debug("trigger must get up purple, uid: %v", userId)
upPurpleDropGroupDataConfig := gdconf.CONF.DropGroupDataMap[upPurpleDropId]
upPurpleDropGroupDataConfig := gdconf.CONF.GachaDropGroupDataMap[upPurpleDropId]
if upPurpleDropGroupDataConfig == nil {
logger.Error("drop group not found, drop id: %v", upPurpleDropId)
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 {
drop := g.doRandDropOnce(dropGroupDataConfig)
if drop == nil {
@@ -588,7 +588,7 @@ func (g *GameManager) doFullRandDrop(dropGroupDataConfig *gdconf.DropGroupData)
return true, drop
}
// 进行下一步掉落流程
dropGroupDataConfig = gdconf.CONF.DropGroupDataMap[drop.Result]
dropGroupDataConfig = gdconf.CONF.GachaDropGroupDataMap[drop.Result]
if dropGroupDataConfig == nil {
logger.Error("drop config tab exist error, invalid drop id: %v", drop.Result)
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)
sumWeight := int32(0)
// 轮盘选择法

View File

@@ -242,6 +242,21 @@ func (g *GameManager) SceneInitFinishReq(player *model.Player, payloadMsg pb.Mes
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) {
logger.Debug("player enter scene done, uid: %v", player.PlayerID)
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))
for _, groupAny := range objectList {
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 {
continue
}
if group.DynamicLoad {
continue
}
for _, monster := range group.MonsterList {
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)
}
g.AddSceneGroup(scene, group)
}
}
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)
}
// 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 {
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
scene := world.GetSceneById(player.SceneId)
@@ -550,8 +500,8 @@ func (g *GameManager) AddSceneEntityNotifyBroadcast(player *model.Player, scene
continue
}
g.SendMsg(cmd.SceneEntityAppearNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, sceneEntityAppearNotify)
// logger.Debug("SceneEntityAppearNotify, uid: %v, type: %v, len: %v",
// scenePlayer.PlayerID, sceneEntityAppearNotify.AppearType, len(sceneEntityAppearNotify.EntityList))
logger.Debug("SceneEntityAppearNotify, uid: %v, type: %v, len: %v",
scenePlayer.PlayerID, sceneEntityAppearNotify.AppearType, len(sceneEntityAppearNotify.EntityList))
}
}
@@ -561,8 +511,8 @@ func (g *GameManager) RemoveSceneEntityNotifyToPlayer(player *model.Player, visi
DisappearType: visionType,
}
g.SendMsg(cmd.SceneEntityDisappearNotify, player.PlayerID, player.ClientSeq, sceneEntityDisappearNotify)
// logger.Debug("SceneEntityDisappearNotify, uid: %v, type: %v, len: %v",
// player.PlayerID, sceneEntityDisappearNotify.DisappearType, len(sceneEntityDisappearNotify.EntityList))
logger.Debug("SceneEntityDisappearNotify, uid: %v, type: %v, len: %v",
player.PlayerID, sceneEntityDisappearNotify.DisappearType, len(sceneEntityDisappearNotify.EntityList))
}
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()
sceneGadgetInfo := &proto.SceneGadgetInfo{
GadgetId: gadgetEntity.GetGadgetId(),
GroupId: 0,
GroupId: entity.GetGroupId(),
ConfigId: entity.GetConfigId(),
GadgetState: 0,
GadgetState: gadgetEntity.GetGadgetState(),
IsEnableInteract: true,
AuthorityPeerId: 1,
}
@@ -1014,9 +964,9 @@ func (g *GameManager) PacketSceneGadgetInfoGather(entity *Entity) *proto.SceneGa
}
sceneGadgetInfo := &proto.SceneGadgetInfo{
GadgetId: gadgetEntity.GetGadgetId(),
GroupId: 0,
GroupId: entity.GetGroupId(),
ConfigId: entity.GetConfigId(),
GadgetState: 0,
GadgetState: gadgetEntity.GetGadgetState(),
IsEnableInteract: true,
AuthorityPeerId: 1,
Content: &proto.SceneGadgetInfo_GatherGadget{
@@ -1071,24 +1021,3 @@ func (g *GameManager) PacketDelTeamEntityNotify(scene *Scene, player *model.Play
}
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)}
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 {
logger.Error("vehicle entityId is 0, uid: %v", player.PlayerID)
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 {
scene := &Scene{
id: sceneId,
world: w,
playerMap: make(map[uint32]*model.Player),
entityMap: make(map[uint32]*Entity),
objectIdEntityMap: make(map[uint64]*Entity),
gameTime: 18 * 60,
createTime: time.Now().UnixMilli(),
meeoIndex: 0,
id: sceneId,
world: w,
playerMap: make(map[uint32]*model.Player),
entityMap: make(map[uint32]*Entity),
groupMap: make(map[uint32]*Group),
gameTime: 18 * 60,
createTime: time.Now().UnixMilli(),
meeoIndex: 0,
}
w.sceneMap[sceneId] = scene
return scene

View File

@@ -5,6 +5,7 @@ import (
"time"
"hk4e/common/constant"
"hk4e/gdconf"
"hk4e/gs/model"
"hk4e/pkg/logger"
"hk4e/protocol/cmd"
@@ -13,14 +14,40 @@ import (
// Scene 场景数据结构
type Scene struct {
id uint32
world *World
playerMap map[uint32]*model.Player
entityMap map[uint32]*Entity
objectIdEntityMap map[uint64]*Entity // 用于标识配置档里的唯一实体是否已被创建
gameTime uint32 // 游戏内提瓦特大陆的时间
createTime int64 // 场景创建时间
meeoIndex uint32 // 客户端风元素染色同步协议的计数器
id uint32
world *World
playerMap map[uint32]*model.Player
entityMap map[uint32]*Entity
groupMap map[uint32]*Group
gameTime uint32 // 游戏内提瓦特大陆的时间
createTime int64 // 场景创建时间
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 {
@@ -39,6 +66,14 @@ func (s *Scene) GetAllEntity() map[uint32]*Entity {
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 {
return s.gameTime
}
@@ -161,7 +196,7 @@ func (s *Scene) CreateEntityAvatar(player *model.Player, avatarId uint32) uint32
avatarId: avatarId,
},
}
s.CreateEntity(entity, 0)
s.CreateEntity(entity)
return entity.id
}
@@ -179,15 +214,11 @@ func (s *Scene) CreateEntityWeapon() uint32 {
fightProp: nil,
entityType: constant.ENTITY_TYPE_WEAPON,
}
s.CreateEntity(entity, 0)
s.CreateEntity(entity)
return entity.id
}
func (s *Scene) CreateEntityMonster(pos, rot *model.Vector, monsterId uint32, level uint8, fightProp map[uint32]float32, configId uint32, objectId uint64) uint32 {
_, exist := s.objectIdEntityMap[objectId]
if exist {
return 0
}
func (s *Scene) CreateEntityMonster(pos, rot *model.Vector, monsterId uint32, level uint8, fightProp map[uint32]float32, configId, groupId uint32) uint32 {
entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_MONSTER)
entity := &Entity{
id: entityId,
@@ -205,17 +236,13 @@ func (s *Scene) CreateEntityMonster(pos, rot *model.Vector, monsterId uint32, le
monsterId: monsterId,
},
configId: configId,
objectId: objectId,
groupId: groupId,
}
s.CreateEntity(entity, objectId)
s.CreateEntity(entity)
return entity.id
}
func (s *Scene) CreateEntityNpc(pos, rot *model.Vector, npcId, roomId, parentQuestId, blockId, configId uint32, objectId uint64) uint32 {
_, exist := s.objectIdEntityMap[objectId]
if exist {
return 0
}
func (s *Scene) CreateEntityNpc(pos, rot *model.Vector, npcId, roomId, parentQuestId, blockId, configId, groupId uint32) uint32 {
entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_NPC)
entity := &Entity{
id: entityId,
@@ -239,17 +266,13 @@ func (s *Scene) CreateEntityNpc(pos, rot *model.Vector, npcId, roomId, parentQue
BlockId: blockId,
},
configId: configId,
objectId: objectId,
groupId: groupId,
}
s.CreateEntity(entity, objectId)
s.CreateEntity(entity)
return entity.id
}
func (s *Scene) CreateEntityGadgetNormal(pos, rot *model.Vector, gadgetId uint32, configId uint32, objectId uint64) uint32 {
_, exist := s.objectIdEntityMap[objectId]
if exist {
return 0
}
func (s *Scene) CreateEntityGadgetNormal(pos, rot *model.Vector, gadgetId, gadgetState, configId, groupId uint32) uint32 {
entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_GADGET)
entity := &Entity{
id: entityId,
@@ -267,21 +290,18 @@ func (s *Scene) CreateEntityGadgetNormal(pos, rot *model.Vector, gadgetId uint32
},
entityType: constant.ENTITY_TYPE_GADGET,
gadgetEntity: &GadgetEntity{
gadgetId: gadgetId,
gadgetType: GADGET_TYPE_NORMAL,
gadgetId: gadgetId,
gadgetState: gadgetState,
gadgetType: GADGET_TYPE_NORMAL,
},
configId: configId,
objectId: objectId,
groupId: groupId,
}
s.CreateEntity(entity, objectId)
s.CreateEntity(entity)
return entity.id
}
func (s *Scene) CreateEntityGadgetGather(pos, rot *model.Vector, gadgetId uint32, gatherId uint32, configId uint32, objectId uint64) uint32 {
_, exist := s.objectIdEntityMap[objectId]
if exist {
return 0
}
func (s *Scene) CreateEntityGadgetGather(pos, rot *model.Vector, gadgetId, gadgetState, gatherId, configId, groupId uint32) uint32 {
entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_GADGET)
entity := &Entity{
id: entityId,
@@ -299,20 +319,21 @@ func (s *Scene) CreateEntityGadgetGather(pos, rot *model.Vector, gadgetId uint32
},
entityType: constant.ENTITY_TYPE_GADGET,
gadgetEntity: &GadgetEntity{
gadgetId: gadgetId,
gadgetType: GADGET_TYPE_GATHER,
gadgetId: gadgetId,
gadgetState: gadgetState,
gadgetType: GADGET_TYPE_GATHER,
gadgetGatherEntity: &GadgetGatherEntity{
gatherId: gatherId,
},
},
configId: configId,
objectId: objectId,
groupId: groupId,
}
s.CreateEntity(entity, objectId)
s.CreateEntity(entity)
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{
id: entityId,
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 {
player := USER_MANAGER.GetOnlineUser(uid)
if player == nil {
logger.Error("player is nil, uid: %v", uid)
return 0
}
func (s *Scene) CreateEntityGadgetVehicle(player *model.Player, pos, rot *model.Vector, vehicleId uint32) uint32 {
entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_GADGET)
entity := &Entity{
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
}
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 {
logger.Error("above max scene entity num limit: %v, id: %v, pos: %v", ENTITY_MAX_SEND_NUM, entity.id, entity.pos)
return
}
if objectId != 0 {
s.objectIdEntityMap[objectId] = entity
}
s.entityMap[entity.id] = entity
}
@@ -398,15 +411,145 @@ func (s *Scene) DestroyEntity(entityId uint32) {
return
}
delete(s.entityMap, entity.id)
delete(s.objectIdEntityMap, entity.objectId)
}
func (s *Scene) GetEntity(entityId uint32) *Entity {
return s.entityMap[entityId]
}
func (s *Scene) GetEntityByObjectId(objectId uint64) *Entity {
return s.objectIdEntityMap[objectId]
func (s *Scene) AddGroupSuite(groupId uint32, suiteId uint8) {
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 场景实体数据结构
@@ -426,8 +569,8 @@ type Entity struct {
monsterEntity *MonsterEntity
npcEntity *NpcEntity
gadgetEntity *GadgetEntity
configId uint32 // 配置相关
objectId uint64
configId uint32 // LUA配置相关
groupId uint32
}
func (e *Entity) GetId() uint32 {
@@ -502,6 +645,10 @@ func (e *Entity) GetConfigId() uint32 {
return e.configId
}
func (e *Entity) GetGroupId() uint32 {
return e.groupId
}
type AvatarEntity struct {
uid uint32
avatarId uint32
@@ -533,6 +680,7 @@ type NpcEntity struct {
type GadgetEntity struct {
gadgetType int
gadgetId uint32
gadgetState uint32
gadgetClientEntity *GadgetClientEntity
gadgetGatherEntity *GadgetGatherEntity
gadgetVehicleEntity *GadgetVehicleEntity
@@ -546,6 +694,10 @@ func (g *GadgetEntity) GetGadgetId() uint32 {
return g.gadgetId
}
func (g *GadgetEntity) GetGadgetState() uint32 {
return g.gadgetState
}
func (g *GadgetEntity) GetGadgetClientEntity() *GadgetClientEntity {
return g.gadgetClientEntity
}