pre cw with probe and a bunch script to read game behavior
This commit is contained in:
1 parent
5120219ae2
commit
da8a32f60d
310 files changed
+219693
-872
No files matched your search
@@ -11,10 +11,19 @@ import (
|
||||
type sceneMetadata struct {
|
||||
ClientVersion string `json:"client_version"`
|
||||
Floors map[uint32]struct {
|
||||
StartAnchor *AnchorItem `json:"start_anchor"`
|
||||
Monsters map[uint32]map[uint32]TeleportInfo `json:"monsters"`
|
||||
GroupCount int `json:"group_count"`
|
||||
Groups map[uint32]struct {
|
||||
MapTeleportEntryID uint32 `json:"map_teleport_entry_id"`
|
||||
DimensionID *uint32 `json:"dimension_id"`
|
||||
DimensionGroups map[uint32][]uint32 `json:"dimension_groups"`
|
||||
GroupProperties map[uint32]map[string]GroupPropertyRule `json:"group_properties"`
|
||||
SavedValues map[string]int32 `json:"saved_values"`
|
||||
SavedValueRules map[string]GroupPropertyRule `json:"saved_value_rules"`
|
||||
EntrySavedValues map[uint32]map[string]int32 `json:"entry_saved_values"`
|
||||
Props map[uint32][]ScenePropInfo `json:"props"`
|
||||
StartAnchor *AnchorItem `json:"start_anchor"`
|
||||
FloorDefaultAnchor *AnchorItem `json:"floor_default_anchor"`
|
||||
Monsters map[uint32]map[uint32]TeleportInfo `json:"monsters"`
|
||||
GroupCount int `json:"group_count"`
|
||||
Groups map[uint32]struct {
|
||||
LoadSide string `json:"load_side"`
|
||||
Deleted bool `json:"is_deleted"`
|
||||
} `json:"groups"`
|
||||
@@ -50,17 +59,86 @@ func applySceneMetadata(res *JsonConfig) {
|
||||
LogInfo("[SCENE] Incomplete group metadata for floor %d; not applied", floorID)
|
||||
continue
|
||||
}
|
||||
if target := floor.MapTeleportEntryID; target != 0 {
|
||||
entrance, exists := res.MapEntrances[target]
|
||||
canonical := fmt.Sprintf("P%d_F%d", planeID, floorID)
|
||||
if exists && entrance.PlaneID == planeID && entrance.FloorID == floorID &&
|
||||
entrance.EntranceType == "Town" && res.LevelOutputConfigs[target][canonical] != nil {
|
||||
if res.MapTeleportEntrances == nil {
|
||||
res.MapTeleportEntrances = map[uint32]uint32{}
|
||||
}
|
||||
res.MapTeleportEntrances[floorID] = target
|
||||
res.MapDefaultEntranceMap[floorID] = target
|
||||
} else {
|
||||
LogInfo("[SCENE] Map teleport entrance %d is not a configured Town on floor %d; routing override not applied", target, floorID)
|
||||
}
|
||||
}
|
||||
if floor.StartAnchor != nil {
|
||||
res.SceneAnchors[entryID] = []AnchorItem{*floor.StartAnchor}
|
||||
}
|
||||
if floor.FloorDefaultAnchor != nil && floor.FloorDefaultAnchor.ID != 0 {
|
||||
if res.SceneDefaultAnchors == nil {
|
||||
res.SceneDefaultAnchors = map[uint32]AnchorItem{}
|
||||
}
|
||||
res.SceneDefaultAnchors[floorID] = *floor.FloorDefaultAnchor
|
||||
}
|
||||
if floor.GroupProperties != nil {
|
||||
scene.GroupProperties = floor.GroupProperties
|
||||
}
|
||||
if floor.DimensionID != nil {
|
||||
scene.DimensionID = *floor.DimensionID
|
||||
}
|
||||
var dimensionGroups map[uint32]bool
|
||||
if floor.DimensionGroups != nil {
|
||||
ids, exists := floor.DimensionGroups[scene.DimensionID]
|
||||
if !exists || len(ids) == 0 {
|
||||
LogInfo("[SCENE] Missing group membership for floor %d dimension %d; scene override not applied", floorID, scene.DimensionID)
|
||||
continue
|
||||
}
|
||||
dimensionGroups = make(map[uint32]bool, len(ids))
|
||||
for _, id := range ids {
|
||||
dimensionGroups[id] = true
|
||||
}
|
||||
}
|
||||
if floor.SavedValues != nil {
|
||||
// RuntimeDimension exports the actual DefaultValue, not MaxValue.
|
||||
// This applies only to floors with a complete captured override.
|
||||
scene.SavedValues = floor.SavedValues
|
||||
}
|
||||
if overrides, exists := floor.EntrySavedValues[entryID]; exists {
|
||||
entrance, known := res.MapEntrances[entryID]
|
||||
valid := known && entrance.FloorID == floorID && entrance.PlaneID == planeID
|
||||
values := make(map[string]int32, len(floor.SavedValues))
|
||||
for key, value := range floor.SavedValues {
|
||||
values[key] = value
|
||||
}
|
||||
for key, value := range overrides {
|
||||
rule, known := floor.SavedValueRules[key]
|
||||
if !known || value < rule.MinValue || value > rule.MaxValue {
|
||||
valid = false
|
||||
break
|
||||
}
|
||||
values[key] = value
|
||||
}
|
||||
if valid {
|
||||
// Never mutate the shared floor defaults: entrances sharing a
|
||||
// floor can intentionally represent different story states.
|
||||
scene.SavedValues = values
|
||||
} else {
|
||||
LogInfo("[SCENE] Invalid saved-value profile entry=%d floor=%d; override not applied", entryID, floorID)
|
||||
}
|
||||
}
|
||||
for groupID := range scene.Scenes {
|
||||
group, exists := floor.Groups[groupID]
|
||||
if !exists || group.Deleted || group.LoadSide == "Client" {
|
||||
if !exists || group.Deleted || group.LoadSide == "Client" || (dimensionGroups != nil && !dimensionGroups[groupID]) {
|
||||
delete(scene.Scenes, groupID)
|
||||
LogInfo("[SCENE] Excluded group entry=%d floor=%d group=%d present=%t deleted=%t side=%s", entryID, floorID, groupID, exists, group.Deleted, group.LoadSide)
|
||||
continue
|
||||
}
|
||||
data := scene.Scenes[groupID]
|
||||
if floor.Props != nil {
|
||||
data.Props = floor.Props[groupID]
|
||||
}
|
||||
for index := range data.Monsters {
|
||||
monster := &data.Monsters[index]
|
||||
if placement, ok := floor.Monsters[groupID][monster.InstID]; ok {
|
||||
@@ -69,6 +147,16 @@ func applySceneMetadata(res *JsonConfig) {
|
||||
}
|
||||
scene.Scenes[groupID] = data
|
||||
}
|
||||
// Resource updates may introduce server props in previously empty groups.
|
||||
for groupID, props := range floor.Props {
|
||||
group, exists := floor.Groups[groupID]
|
||||
if !exists || group.Deleted || group.LoadSide == "Client" || (dimensionGroups != nil && !dimensionGroups[groupID]) {
|
||||
continue
|
||||
}
|
||||
data := scene.Scenes[groupID]
|
||||
data.Props = props
|
||||
scene.Scenes[groupID] = data
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user