Discover how frames are encoded, use that knowledge to (finally) get the viewport locked in
This commit is contained in:
@@ -28,7 +28,7 @@ var (
|
||||
|
||||
type env struct {
|
||||
gameMap *maps.GameMap
|
||||
set sets.MapSet
|
||||
set *sets.MapSet
|
||||
}
|
||||
|
||||
type runState struct {
|
||||
@@ -159,8 +159,8 @@ func present(win *pixelgl.Window, state *runState) {
|
||||
|
||||
// Draw the boundary
|
||||
rect := pixel.R(
|
||||
float64(gameMap.MinWidth)-1, float64(gameMap.MinLength)-1,
|
||||
float64(gameMap.MaxWidth)+1, float64(gameMap.MaxLength)+1,
|
||||
float64(gameMap.MinWidth)-0.5, float64(gameMap.MinLength)-0.5,
|
||||
float64(gameMap.MaxWidth)+0.5, float64(gameMap.MaxLength)+0.5,
|
||||
)
|
||||
|
||||
imd.Color = pixel.RGB(255, 0, 0)
|
||||
@@ -210,9 +210,10 @@ func makeColour(cell *maps.Cell, colIdx int) pixel.RGBA {
|
||||
scale = mult(0.004)
|
||||
case 14:
|
||||
scale = mult(0.004)
|
||||
case 15:
|
||||
scale = mult(1.0)
|
||||
default:
|
||||
scale = mult(0.01) // close to maximum resolution, low-value fields will be lost
|
||||
|
||||
}
|
||||
|
||||
col := scale(float64(cell.At(colIdx)))
|
||||
@@ -290,9 +291,9 @@ func runStep(win *pixelgl.Window, state *runState) *runState {
|
||||
log.Printf("%#v -> %d,%d", vec, x, y)
|
||||
cell := state.env.gameMap.Cells.At(x, y, state.zIdx)
|
||||
log.Printf(
|
||||
"x=%d y=%d z=%d Object0SurfaceArea=%d Object3CenterArea=%d (%s) SquadRelated=%d",
|
||||
"x=%d y=%d z=%d SurfaceTile=%d (%s) SurfaceFrame=%d SquadRelated=%d",
|
||||
x, y, state.zIdx,
|
||||
cell.Object0SurfaceArea, cell.Object3CenterArea, state.env.set.Palette[int(cell.Object3CenterArea)],
|
||||
cell.Surface.Index(), state.env.set.Palette[int(cell.Surface.Index())], cell.Surface.Frame(),
|
||||
cell.SquadRelated,
|
||||
)
|
||||
log.Printf("CellIdx%d=%d. Full cell data: %#v", state.cellIdx, cell.At(state.cellIdx), cell)
|
||||
|
@@ -287,7 +287,7 @@ Skipping the header we know about, we have data like this:
|
||||
|
||||
It would be very neat if the per-cell data started at 0x100 and took 16 bytes
|
||||
per coordinate, but to get objects in my map to line up properly with cells in
|
||||
WH40K_TD.exe, I've had to start parsing these rows at `0x0120` instead. Still
|
||||
WH40K_TD.exe, I've had to start parsing these rows at `0x0110` instead. Still
|
||||
tentative!
|
||||
|
||||
Total number of possible coordinates is 100x130x7 = 91,000 = 1,456,000 bytes.
|
||||
@@ -379,8 +379,8 @@ I've added a `view-map` command to explore the data graphically. Each of the 16
|
||||
bytes in a cell row must have a function; comparing a known map to how it looks
|
||||
in WH40K_TD.exe can help me to unravel that function.
|
||||
|
||||
Here's a side-by-side comparison of Chapter3.MAP, investigating CellIndex=3 and
|
||||
Z index = 0
|
||||
Here's an (out-of-date) side-by-side comparison of Chapter3.MAP, investigating
|
||||
CellIndex=3 and Z index = 0.
|
||||
|
||||

|
||||
|
||||
@@ -400,17 +400,15 @@ Investigation has so far suggested the following:
|
||||
* 0x40: Animated object
|
||||
* `Cell[2]` hasn't been seen with a value > 0 yet
|
||||
* `Cell[3]` Object 0 (Surface) Area (Sets/*.set lookup)
|
||||
* `Cell[4]` Unsure at present, but it varies between a narrow range of values.
|
||||
I've seen 128 - 147. Broadly matches the terrain layout.
|
||||
* `Cell[5]` Object 1 (Left) Area (Sets/*.set lookup) **ASSUMED**.
|
||||
* It's in the right place, and there seems to be correspondence, but not as
|
||||
neatly as the other 3 columns. Often off-by-1
|
||||
* `Cell[6]` Wide range of values, 0 - 161 observed. Seems to have identity with
|
||||
some blood splatters, etc
|
||||
* `Cell[4]` Object 0 (Surface) Sprite + ???
|
||||
* Bottom bits encode the sprite (frame number in the .obj file)
|
||||
* 0x80 is set too. A flag?
|
||||
* `Cell[5]` Object 1 (Left) Area (Sets/*.set lookup)
|
||||
* `Cell[6]` Object 1 (Surface) Sprite + ???
|
||||
* `Cell[7]` Object 2 (Right) Area (Sets/*.set lookup)
|
||||
* `Cell[8]` Wide range of values, 0 - 159 observed.
|
||||
* `Cell[6]` Object 2 (Right) Sprite + ???
|
||||
* `Cell[9]` Object 3 (Center) Area (Sets/*.set lookup)
|
||||
* `Cell[10]` Varies from 0 - 248. Unclear what for, broadly follows terrain
|
||||
* `Cell[10]` Object 3 (Right) Sprite + ???
|
||||
* `Cell[11]` all 255?
|
||||
* `Cell[12]` all 0?
|
||||
* `Cell[13]` all 0?
|
||||
@@ -435,10 +433,6 @@ So `CellIdx == 9` points to the center object's Area, looked up in the set file!
|
||||
|
||||

|
||||
|
||||
@@ -68,18 +68,28 @@ func (h Header) MapSetFilename() string {
|
||||
return string(h.SetName[0:idx:idx]) + ".set"
|
||||
}
|
||||
|
||||
type ObjRef struct {
|
||||
AreaByte byte
|
||||
FrameAndUnknownByte byte
|
||||
}
|
||||
|
||||
// The index into a set palette to retrieve the object
|
||||
func (o ObjRef) Index() int {
|
||||
return int(o.AreaByte)
|
||||
}
|
||||
|
||||
func (o ObjRef) Frame() int {
|
||||
return int(o.FrameAndUnknownByte - 0x80)
|
||||
}
|
||||
|
||||
type Cell struct {
|
||||
DoorAndCanisterRelated byte
|
||||
DoorLockAndReactorRelated byte
|
||||
Unknown2 byte
|
||||
Object0SurfaceArea byte
|
||||
Unknown4 byte
|
||||
Object1LeftArea byte
|
||||
Unknown6 byte
|
||||
Object2RightArea byte
|
||||
Unknown8 byte
|
||||
Object3CenterArea byte
|
||||
Unknown10 byte
|
||||
Surface ObjRef
|
||||
Left ObjRef
|
||||
Right ObjRef
|
||||
Center ObjRef
|
||||
Unknown11 byte
|
||||
Unknown12 byte
|
||||
Unknown13 byte
|
||||
@@ -96,21 +106,21 @@ func (c *Cell) At(n int) byte {
|
||||
case 2:
|
||||
return c.Unknown2
|
||||
case 3:
|
||||
return c.Object0SurfaceArea
|
||||
return c.Surface.AreaByte
|
||||
case 4:
|
||||
return c.Unknown4
|
||||
return c.Surface.FrameAndUnknownByte
|
||||
case 5:
|
||||
return c.Object1LeftArea
|
||||
return c.Left.AreaByte
|
||||
case 6:
|
||||
return c.Unknown6
|
||||
return c.Left.FrameAndUnknownByte
|
||||
case 7:
|
||||
return c.Object2RightArea
|
||||
return c.Right.AreaByte
|
||||
case 8:
|
||||
return c.Unknown8
|
||||
return c.Right.FrameAndUnknownByte
|
||||
case 9:
|
||||
return c.Object3CenterArea
|
||||
return c.Center.AreaByte
|
||||
case 10:
|
||||
return c.Unknown10
|
||||
return c.Center.FrameAndUnknownByte
|
||||
case 11:
|
||||
return c.Unknown11
|
||||
case 12:
|
||||
|
@@ -19,13 +19,13 @@ type MapSet struct {
|
||||
Palette []string
|
||||
}
|
||||
|
||||
func LoadSets(dir string) (map[string]MapSet, error) {
|
||||
func LoadSets(dir string) (map[string]*MapSet, error) {
|
||||
fis, err := ioutil.ReadDir(dir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := make(map[string]MapSet, len(fis))
|
||||
out := make(map[string]*MapSet, len(fis))
|
||||
|
||||
for _, fi := range fis {
|
||||
filename := filepath.Join(dir, fi.Name())
|
||||
@@ -48,35 +48,34 @@ func LoadSets(dir string) (map[string]MapSet, error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func LoadSet(filename string) (MapSet, error) {
|
||||
var out MapSet
|
||||
var err error
|
||||
func LoadSet(filename string) (*MapSet, error) {
|
||||
out := &MapSet{}
|
||||
|
||||
s, err := asciiscan.New(filename)
|
||||
if err != nil {
|
||||
return out, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer s.Close()
|
||||
|
||||
out.Description, err = s.ConsumeString()
|
||||
if err != nil {
|
||||
return out, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out.Defs, err = consumeDefs(s)
|
||||
if err != nil {
|
||||
return out, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for {
|
||||
str, err := s.ConsumeString()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
return out, nil
|
||||
}
|
||||
|
||||
return out, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out.Palette = append(out.Palette, str)
|
||||
|
Reference in New Issue
Block a user