Some more character investigations
This commit is contained in:
@@ -598,7 +598,8 @@ Ignoring them for now, here's a first guess at a header:
|
||||
| 24 | 2 | ??? - varies. Seems related to character/squad position? |
|
||||
| 26 | 2 | ??? - invariant `00 04` |
|
||||
| 28 | 4 | ??? - varies (0 vs 5) |
|
||||
| 32 | 4 | Number of thingies (26 vs 1) |
|
||||
| 32 | 1 | Number of thingies |
|
||||
| 33 | 3 | ???. With a Lord of Change on the map, only one byte works as thingies count |
|
||||
| 36 | 20 | Padding? |
|
||||
|
||||
56 bytes of data is interesting because the value of that first, ignored byte is
|
||||
@@ -625,7 +626,78 @@ Generating a map with no characters at all, the trailer is 2,447 bytes, and the
|
||||
mission title starts at 0x3B (59). So we can say we have 20 bytes of padding as
|
||||
a first approximation?
|
||||
|
||||
The "trailer trailer", for want of a better term, seems to be organised as:
|
||||
Here's where we're at with the per-character data, going from the padding values
|
||||
suggested above:
|
||||
|
||||
| Offset | Size | Meaning |
|
||||
| ------ | ---- | ------- |
|
||||
| 0 | 179 | ??? |
|
||||
| 179 | 80 | Character name |
|
||||
| 259 | 10 | Character attributes |
|
||||
| 269 | 495 | ??? |
|
||||
| 764 | 1(?) | Squad number? |
|
||||
| 765 | 927 | ??? |
|
||||
|
||||
There's still a lot of bytes to dig through, but this allows me to load the
|
||||
character names from Chapter01 correctly, with the exception of record 57 which
|
||||
just contains `\x02` and is then null-terminated all the way through. Looking
|
||||
at the bytes for one character record, I can easily correlate certain bytes to
|
||||
various attributes; that's just done in code for the moment.
|
||||
|
||||
Given two characters of the same time, just in different locations, differing
|
||||
values are seen at:
|
||||
|
||||
* `0x103 - 0x10c` (hodgepodge)
|
||||
* `0x178 - 0x1be` (hodgepodge)
|
||||
* `0x2fc` (0, 1) - squad number?
|
||||
|
||||
In Chapter01, picking a random character (Gorgon) and looking at his squadmates,
|
||||
they are all in the same squad, and no other characters are in that squad, so it
|
||||
looks pretty diagnostic to me. There's nothing in the UI to indicate the squad,
|
||||
though.
|
||||
|
||||
Now let's look for position. In my 2-character map, they're at 65,50 and 70,55.
|
||||
Within a character, I see those numbers repeated twice - around `0x1b{9,a}` and
|
||||
`0x1b{d,e}`.
|
||||
|
||||
Characters don't seem to take up multiple x,y squares, but they *can* take up
|
||||
multiple Z levels. So maybe this is a bounding box of some kind?
|
||||
|
||||
Adding a (tall) Lord of Change to the map gave me `02 36 45 00 02 37 45`, which
|
||||
doesn't quite match what my eyes are telling me for Z,Y,X. In addition, the data
|
||||
immediately after this offset changed into a large number of coordinate-like
|
||||
sets of values - far too many for it to actually be a bounding box. However, the
|
||||
first one remains good as a position specifier.
|
||||
|
||||
Down in `0x679` (Chaos Sorcerer) or `0x68D` (Lord of Change), the map coords for
|
||||
the *other* character appears, which is downright odd. For now, just use the
|
||||
first-indexed value.
|
||||
|
||||
How about their types? We need to be able to work out which animations to show,
|
||||
so they must be uniquely identified somehow. Ultramarine captain is animation
|
||||
group 12, while chaos lord is group... 14? Not certain. I don't see either of
|
||||
those numbers in a promising spot, anyway.
|
||||
|
||||
|
||||
I do see differences at around `0x170`:
|
||||
|
||||
```
|
||||
Ultramarine Captain: 00 00 00 00 00 00 00 00 50 03 00 00 00 00 00 00
|
||||
Chaos Lord: 00 00 00 00 11 01 00 00 47 03 00 04 00 00 02 00
|
||||
```
|
||||
|
||||
Maybe they're somewhat relevant, it's hard to say.
|
||||
|
||||
Thingies next: these aren't decoded at all yet, and the sizes seem to be
|
||||
variable.
|
||||
|
||||
| Offset | Size | Meaning |
|
||||
| ------ | ---- | ------- |
|
||||
| | | |
|
||||
|
||||
|
||||
Finally, the "trailer trailer", for want of a better term, seems to be organised
|
||||
as:
|
||||
|
||||
| Offset | Size | Meaning |
|
||||
| ----- | ---- | ------- |
|
||||
@@ -633,6 +705,8 @@ The "trailer trailer", for want of a better term, seems to be organised as:
|
||||
| 255 | 2048 | Briefing |
|
||||
| 2304 | 85 | ??? - each byte is 1 or 0. Spaced so it may be partly uint32 |
|
||||
|
||||
This duplicates the information found in the `.TXT` files. No idea what the end
|
||||
data is yet.
|
||||
|
||||
## Soldiers At War
|
||||
|
||||
|
@@ -102,5 +102,21 @@ func (m *Map) SpritesForCell(x, y, z int) ([]*Sprite, error) {
|
||||
sprites = append(sprites, sprite)
|
||||
}
|
||||
|
||||
// FIXME: this just marks character positions with sprite 19 for now.
|
||||
specialsObj, err := m.assets.Object("specials")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chrSpr, err := specialsObj.Sprite(19)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, chr := range m.raw.Characters {
|
||||
if chr.XPos == x && chr.YPos == y && z == 1 { // FIXME: sort out ZPos
|
||||
sprites = append(sprites, chrSpr)
|
||||
}
|
||||
}
|
||||
|
||||
return sprites, nil
|
||||
}
|
||||
|
@@ -67,8 +67,9 @@ type GameMap struct {
|
||||
TrailerUnknown3 int `struc:"uint16"`
|
||||
TrailerUnknown4 int `struc:"uint32"`
|
||||
|
||||
NumThingies int `struc:"uint32"`
|
||||
Padding1 []byte `struc:"[20]byte"`
|
||||
NumThingies int `struc:"byte"`
|
||||
TrailerUnknown5 []byte `struc:"[3]byte"`
|
||||
Padding1 []byte `struc:"[20]byte"`
|
||||
|
||||
// FIXME: The rest is trash until Character & Thingy are worked out
|
||||
|
||||
@@ -79,7 +80,7 @@ type GameMap struct {
|
||||
Briefing string `struc:"[2048]byte"`
|
||||
|
||||
// Maybe? each contains either 0 or 1? Hard to say
|
||||
TrailerUnknown5 []byte `struc:"[85]byte"`
|
||||
TrailerUnknown6 []byte `struc:"[85]byte"`
|
||||
}
|
||||
|
||||
type Cell struct {
|
||||
@@ -98,7 +99,29 @@ type Cell struct {
|
||||
}
|
||||
|
||||
type Character struct {
|
||||
Unknown1 int `struc:"uint32"`
|
||||
Unknown1 []byte `struc:"[179]byte"`
|
||||
Name string `struc:"[80]byte"`
|
||||
|
||||
// Attributes guessed by matching up numbers. Starts at 0x103
|
||||
WeaponSkill int `struc:"byte"`
|
||||
BallisticSkill int `struc:"byte"`
|
||||
Unknown2 byte `struc:"byte"`
|
||||
Leadership int `struc:"byte"`
|
||||
Toughness int `struc:"byte"`
|
||||
Strength int `struc:"byte"`
|
||||
ActionPoints int `struc:"byte"`
|
||||
Unknown3 byte `struc:"byte"`
|
||||
Unknown4 byte `struc:"byte"`
|
||||
Health int `struc:"byte"`
|
||||
|
||||
Unknown5 []byte `struc:"[91]byte"`
|
||||
Armor int `struc:"byte"`
|
||||
Unknown6 []byte `struc:"[84]byte"`
|
||||
YPos int `struc:"byte"` // These are actually much more complicated
|
||||
XPos int `struc:"byte"`
|
||||
Unknown7 []byte `struc:"[317]byte"`
|
||||
SquadNumber byte `struc:"byte"`
|
||||
Unknown8 []byte `struc:"[927]byte"`
|
||||
// TODO: each character may have a fixed number of subrecords for inventory
|
||||
}
|
||||
|
||||
@@ -289,13 +312,38 @@ func loadMapFile(filename string) (*GameMap, error) {
|
||||
}
|
||||
|
||||
// Trim any trailing nulls off of the strings
|
||||
trimRight(&out.SetName)
|
||||
trimRight(&out.Title)
|
||||
trimRight(&out.Briefing)
|
||||
nullTerminate(&out.SetName)
|
||||
nullTerminate(&out.Title)
|
||||
nullTerminate(&out.Briefing)
|
||||
|
||||
for i, chr := range out.Characters {
|
||||
nullTerminate(&chr.Name)
|
||||
fmt.Printf("Character %v: %s\n", i, chr.String())
|
||||
}
|
||||
|
||||
fmt.Printf("Mission Title: %q\n", out.Title)
|
||||
fmt.Printf("Mission Briefing: %q\n", out.Briefing)
|
||||
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func trimRight(s *string) {
|
||||
*s = strings.TrimRight(*s, "\x00")
|
||||
func nullTerminate(s *string) {
|
||||
sCpy := *s
|
||||
idx := strings.Index(sCpy, "\x00")
|
||||
if idx < 0 {
|
||||
return
|
||||
}
|
||||
|
||||
*s = sCpy[0:idx]
|
||||
}
|
||||
|
||||
func (c *Character) String() string {
|
||||
return fmt.Sprintf(
|
||||
"squad=%v pos=(%v,%v) name=%q\n\t%3d %3d %3d %3d %3d\n\t%3d %3d ??? ??? %3d\n",
|
||||
c.SquadNumber,
|
||||
c.XPos, c.YPos,
|
||||
c.Name,
|
||||
c.ActionPoints, c.Health, c.Armor, c.BallisticSkill, c.WeaponSkill,
|
||||
c.Strength, c.Toughness /*c.Initiative, c.Attacks,*/, c.Leadership,
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user