2020-04-15 00:27:43 +01:00
|
|
|
# `Anim/WarHammer.ani`
|
|
|
|
|
2020-04-15 22:18:53 +01:00
|
|
|
This turns out to simply be an [`obj`](obj.md) file.
|
|
|
|
|
|
|
|
The first 1,064 sprites are all of the same Ultramarine, carryng a bolter. There
|
|
|
|
are eight "facing" orientations:
|
|
|
|
|
|
|
|
* North
|
|
|
|
* Northeast
|
|
|
|
* East
|
|
|
|
* Southeast
|
|
|
|
* South
|
|
|
|
* Southwest
|
|
|
|
* West
|
|
|
|
* Northwest
|
|
|
|
|
|
|
|
For each orientation, an action is pictured in a variable number of frames. The
|
|
|
|
final frame for each action appears to be "stationary".
|
|
|
|
|
|
|
|
* Walk (13 frames)
|
|
|
|
* Run (9 frames)
|
|
|
|
* Crouch down (8 frames)
|
|
|
|
* Stand up (8 frames)
|
|
|
|
* Take aim (standing) (6 frames)
|
|
|
|
* Fire (standing) (6 frames)
|
|
|
|
* Relax aim (standing) (6 frames)
|
|
|
|
* Throw grenade (standing) (18 frames)
|
|
|
|
* Take aim (crouched) (5 frames)
|
|
|
|
* Fire (crouched) (5 frames)
|
|
|
|
* Relax aim (crouched) (5 frames)
|
|
|
|
* Throw grenade (crouched) (17 frames)
|
|
|
|
* Draw melee weapon (standing) (10 frames)
|
|
|
|
* Strike down with melee weapon (standing) (8 frames)
|
|
|
|
* Stab with melee weapon (standing) (9 frames)
|
|
|
|
|
|
|
|
Added together and multiplied by 87, that's 1064.
|
|
|
|
|
|
|
|
The next sprite is a walking-north action for an ultramarine with a flamer. The
|
|
|
|
total number of frames for this character is 1120 - 56 additional frames, or 7
|
|
|
|
per orientation. Could be an extra action, or an extra frame per action.
|
|
|
|
|
|
|
|
Also notable is that while the bolter showed muzzle flash in the animation, the
|
|
|
|
flamer only showed a tiny hint of fire. I think the animation for spewing flame
|
|
|
|
is held elsewhere.
|
|
|
|
|
|
|
|
I strongly suspect the actions and the number of frames in each action are
|
|
|
|
configurable. So, what other files are implicated in its interpretation? Here's
|
|
|
|
a few possibilities:
|
2020-04-15 00:27:43 +01:00
|
|
|
|
2020-04-15 22:18:53 +01:00
|
|
|
* `Data/AniObDef.dat`
|
|
|
|
* `Data/Coordinates.dat`
|
|
|
|
* `Data/HasAction.dat`
|
|
|
|
* `Data/VehicDef.dat`
|
|
|
|
* `Data/WeapDef.dat`
|
2020-04-15 00:27:43 +01:00
|
|
|
- `Idx/WarHammer.idx`
|
|
|
|
|
2020-04-15 22:18:53 +01:00
|
|
|
## `Data/AniObDef.dat`
|
|
|
|
|
|
|
|
Including comments, this is 4098 lines, giving approx. 45 lines for each
|
2020-04-15 00:27:43 +01:00
|
|
|
of the ~188 characters in the `ani`. That doesn't seem many, and there's no
|
|
|
|
obvious correspondence between the commented-on names (`SMOKE01`?) and the
|
|
|
|
viewed frames... but then, I've not viewed all the frames.
|
|
|
|
|
2020-04-15 22:18:53 +01:00
|
|
|
|
|
|
|
## `Idx/WarHammer.idx`
|
|
|
|
|
|
|
|
`WarHammer.idx` (1,880,078 bytes, binary, so around 10KiB per character, in
|
|
|
|
theory) is more reasonable.
|
2020-04-15 00:27:43 +01:00
|
|
|
|
|
|
|
Here's a list of operations on the file when `WH40K_TD.EXE` is instructed to
|
|
|
|
place an Ultramarine squad:
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
|
|
|
```
|
|
|
|
# Operation 1
|
|
|
|
_llseek(34, 12, [12], SEEK_SET) = 0
|
|
|
|
read(34, "\0\30\0\0X\4\0\0\0\0\0\0", 12) = 12
|
|
|
|
|
|
|
|
# Operation 2
|
|
|
|
_llseek(34, 6144, [6144], SEEK_SET) = 0
|
|
|
|
read(34, "\2\6\1\0 L\0\0\r\0\0\0", 12) = 12
|
|
|
|
_llseek(34, 6156, [6156], SEEK_SET) = 0
|
|
|
|
read(34, "\2\6\2\0\202L\0\0\r\0\0\0", 12) = 12
|
|
|
|
_llseek(34, 6168, [6168], SEEK_SET) = 0
|
|
|
|
read(34, "\2\6\3\0\344L\0\0\r\0\0\0", 12) = 12
|
|
|
|
_llseek(34, 6180, [6180], SEEK_SET) = 0
|
|
|
|
read(34, "\2\6\4\0FM\0\0\r\0\0\0", 12) = 12
|
|
|
|
_llseek(34, 6192, [6192], SEEK_SET) = 0
|
|
|
|
read(34, "\2\6\5\0\250M\0\0\r\0\0\0", 12) = 12
|
|
|
|
|
|
|
|
# Operation 3
|
|
|
|
_llseek(34, 19880, [19880], SEEK_SET) = 0
|
|
|
|
read(34, "4\0@\0@\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20
|
|
|
|
read(34, "\0\0\6\0\4\0\0\0\6\0\4\0\0\0\6\0\4\0\0\0\5\0\4\0\0\0\5\0\4\0\0\0"..., 78) = 78
|
|
|
|
|
|
|
|
# Operation 4: repeat 1
|
|
|
|
# Operation 5: repeat 2
|
|
|
|
# Operation 6: repeat 3
|
|
|
|
|
|
|
|
# Operation 7
|
|
|
|
_llseek(34, 24, [24], SEEK_SET) = 0
|
|
|
|
read(34, "0\212\1\0X\4\0\0\210&\0\0", 12) = 12
|
|
|
|
|
|
|
|
# Operation 8
|
|
|
|
_llseek(34, 100912, [100912], SEEK_SET) = 0
|
|
|
|
read(34, "\2\6\1\0P\276\1\0\r\0\0\0", 12) = 12
|
|
|
|
_llseek(34, 100924, [100924], SEEK_SET) = 0
|
|
|
|
read(34, "\2\6\2\0\262\276\1\0\r\0\0\0", 12) = 12
|
|
|
|
_llseek(34, 100936, [100936], SEEK_SET) = 0
|
|
|
|
read(34, "\2\6\3\0\24\277\1\0\r\0\0\0", 12) = 12
|
|
|
|
_llseek(34, 100948, [100948], SEEK_SET) = 0
|
|
|
|
read(34, "\2\6\4\0v\277\1\0\r\0\0\0", 12) = 12
|
|
|
|
_llseek(34, 100960, [100960], SEEK_SET) = 0
|
|
|
|
read(34, "\2\6\5\0\330\277\1\0\r\0\0\0", 12) = 12
|
|
|
|
|
|
|
|
# Operation 9
|
|
|
|
_llseek(34, 114648, [114648], SEEK_SET) = 0
|
|
|
|
read(34, "4\0@\0@\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20
|
|
|
|
|
|
|
|
# Operation 10
|
|
|
|
_llseek(34, 114648, [114648], SEEK_SET) = 0
|
|
|
|
read(34, "4\0@\0@\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20
|
|
|
|
read(34, "\0\0\6\0\4\0\0\0\6\0\4\0\0\0\6\0\4\0\0\0\5\0\4\0\0\0\5\0\4\0\0\0"..., 78) = 78
|
|
|
|
|
|
|
|
|
|
|
|
# Operation 11: repeat 7
|
|
|
|
# Operation 12: repeat 8
|
|
|
|
# Operation 13: repeat 9
|
|
|
|
|
|
|
|
# lots of repeats
|
|
|
|
```
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
|
|
|
So what are we doing here? What did we read? Here's another view of it:
|
|
|
|
|
|
|
|
```
|
|
|
|
# Operation 1: read 12 bytes from 0x0C
|
|
|
|
|
|
|
|
0000000C 00 18 00 00 58 04 00 00 00 00 00 00 ....X.......
|
|
|
|
|
|
|
|
# Operation 7: read 12 bytes from offset 0x18
|
|
|
|
|
|
|
|
00000018 30 8A 01 00 58 04 00 00 88 26 00 00 0...X....&..
|
|
|
|
|
|
|
|
# Operation 2: 5 times, read 12 bytes from offset 0x1800
|
|
|
|
|
|
|
|
00001800 02 06 01 00 20 4C 00 00 0D 00 00 00 .... L......
|
|
|
|
0000180C 02 06 02 00 82 4C 00 00 0D 00 00 00 .....L......
|
|
|
|
00001818 02 06 03 00 E4 4C 00 00 0D 00 00 00 .....L......
|
|
|
|
00001824 02 06 04 00 46 4D 00 00 0D 00 00 00 ....FM......
|
|
|
|
00001830 02 06 05 00 A8 4D 00 00 0D 00 00 00 .....M......
|
|
|
|
|
|
|
|
# Operation 3a: read 20 bytes from offset 0x4DA8
|
|
|
|
|
|
|
|
00004DA8 34 00 40 00 40 00 01 00 00 00 00 00 4.@.@.......
|
|
|
|
00004DB4 00 00 00 00 00 00 00 00 ........
|
|
|
|
|
|
|
|
# Operation 3b: read 78 more bytes
|
|
|
|
|
|
|
|
00004DBC 00 00 06 00 04 00 00 00 06 00 04 00
|
|
|
|
00004DC8 00 00 06 00 04 00 00 00 05 00 04 00
|
|
|
|
00004DD4 00 00 05 00 04 00 00 00 03 00 04 00
|
|
|
|
00004DE0 00 00 04 00 FC FF 00 00 05 00 FC FF
|
|
|
|
00004DEC 00 00 06 00 FC FF 00 00 05 00 FC FF
|
|
|
|
00004DF8 00 00 06 00 FC FF 00 00 06 00 FC FF
|
|
|
|
00004E04 00 00 00 00 00 00
|
|
|
|
|
|
|
|
|
|
|
|
# Operation 8: 5 times, read 12 bytes from offset 0x18A30
|
|
|
|
|
|
|
|
00018A30 02 06 01 00 50 BE 01 00 0D 00 00 00 ....P.......
|
|
|
|
00018A3C 02 06 02 00 B2 BE 01 00 0D 00 00 00 ............
|
|
|
|
00018A48 02 06 03 00 14 BF 01 00 0D 00 00 00 ............
|
|
|
|
00018A54 02 06 04 00 76 BF 01 00 0D 00 00 00 ....v.......
|
|
|
|
00018A60 02 06 05 00 D8 BF 01 00 0D 00 00 00 ............
|
|
|
|
|
|
|
|
# Operation 9a: read 20 bytes from offset 0x1BFD8
|
|
|
|
|
|
|
|
0001BFD8 34 00 40 00 40 00 01 00 00 00 00 00 4.@.@.......
|
|
|
|
0001BFE4 00 00 00 00 00 00 00 00 ........
|
|
|
|
|
|
|
|
# Operation 9b: read 78 more bytes
|
|
|
|
|
|
|
|
0001BFEC 00 00 06 00 04 00 00 00 06 00 04 00
|
|
|
|
0001BFF8 00 00 06 00 04 00 00 00 05 00 04 00
|
|
|
|
0001C004 00 00 05 00 04 00 00 00 03 00 04 00
|
|
|
|
0001C010 00 00 04 00 FC FF 00 00 05 00 FC FF
|
|
|
|
0001C01C 00 00 06 00 FC FF 00 00 05 00 FC FF
|
|
|
|
0001C028 00 00 06 00 FC FF 00 00 06 00 FC FF
|
|
|
|
0001C034 00 00 00 00 00 00
|
|
|
|
```
|
|
|
|
|
|
|
|
Operation 1 contains `[18 00]`. Operation 2, at `0x1800`, contains `[A8 4D]` -
|
|
|
|
and operation 3 starts at `0x4DA8`. The pattern repeats for operations
|
|
|
|
7 -> 8 -> 9.
|
|
|
|
|
|
|
|
Assumimg operations 1 & 7 represent one type of record, while 2 & 8 represent
|
|
|
|
another, that would give us a 511-entry directory starting at 0xC. We know the
|
|
|
|
first 4 bytes represent an offset to find the type of record represented by
|
|
|
|
2 & 8. We don't know about the other 8 bytes.
|
|
|
|
|
|
|
|
| Offset | Size | Meaning |
|
|
|
|
| ------ | ---- | ------- |
|
|
|
|
| 0 | 4 | Position of type 2 record(s) |
|
|
|
|
| 4 | ? | Unknown |
|
|
|
|
|
|
|
|
The records represented by operations 2 & 8 both read 5x 12-byte records, but it
|
|
|
|
looks like they're arranged in blocks of 8. Nothing in type 1 records indicates
|
|
|
|
how many type 2 records there are.
|
|
|
|
|
|
|
|
| Offset | Size | Meaning |
|
|
|
|
| ------ | ---- | ------- |
|
|
|
|
| 0 | 2? | `02 06` - ??? |
|
|
|
|
| 2 | 2? | `n xx` - ??? `n` counts from 1 to 8 |
|
|
|
|
| 4 | 4 | Position of type 3 record |
|
2020-04-15 21:11:01 +01:00
|
|
|
| 8 | 4 | ??? |
|
2020-04-15 00:27:43 +01:00
|
|
|
|
|
|
|
The two type 3a and 3b records are identical to each other, it's hard to know
|
|
|
|
what's what.
|
|
|
|
|
|
|
|
None of the unknown numbers, however sliced, seem to be sprite indices for
|
|
|
|
`Anim/WarHammer.ani`.
|
|
|
|
|
2020-04-15 21:11:01 +01:00
|
|
|
Here's a trace of both `idx` and `ani` files when placing a single librarian for
|
|
|
|
me to dig into in more detail. No other files are touched when doing this.
|
2020-04-15 00:27:43 +01:00
|
|
|
|
|
|
|
<details>
|
|
|
|
|
|
|
|
```
|
2020-04-15 21:11:01 +01:00
|
|
|
_llseek(<WarHammer.idx>, 132, [132], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.idx>, "\x30\x7c\x09\x00\x98\x00\x00\x00\x88\xf8\x00\x00", 12) = 12
|
2020-04-15 00:27:43 +01:00
|
|
|
|
2020-04-15 21:11:01 +01:00
|
|
|
_llseek(<WarHammer.idx>, 132, [132], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.idx>, "\x30\x7c\x09\x00\x98\x00\x00\x00\x88\xf8\x00\x00", 12) = 12
|
|
|
|
|
|
|
|
_llseek(<WarHammer.idx>, 621616, [621616], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.idx>, "\x02\x01\x01\x33\x50\x83\x09\x00\x0d\x00\x00\x00", 12) = 12
|
|
|
|
|
|
|
|
_llseek(<WarHammer.idx>, 621628, [621628], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.idx>, "\x02\x01\x02\x33\xb2\x83\x09\x00\x0d\x00\x00\x00", 12) = 12
|
|
|
|
|
|
|
|
_llseek(<WarHammer.idx>, 621640, [621640], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.idx>, "\x02\x01\x03\x33\x14\x84\x09\x00\x0d\x00\x00\x00", 12) = 12
|
|
|
|
|
|
|
|
_llseek(<WarHammer.idx>, 621652, [621652], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.idx>, "\x02\x01\x04\x33\x76\x84\x09\x00\x0d\x00\x00\x00", 12) = 12
|
|
|
|
|
|
|
|
_llseek(<WarHammer.idx>, 621664, [621664], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.idx>, "\x02\x01\x05\x33\xd8\x84\x09\x00\x0d\x00\x00\x00", 12) = 12
|
|
|
|
|
|
|
|
_llseek(<WarHammer.idx>, 623832, [623832], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.idx>, "\x34\x00\x40\x00\x40\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 20) = 20
|
|
|
|
|
|
|
|
_llseek(<WarHammer.idx>, 0, [623852], SEEK_CUR) = 0
|
|
|
|
_llseek(<WarHammer.idx>, 623852, [623852], SEEK_SET) = 0
|
|
|
|
_llseek(<WarHammer.idx>, 623930, [623930], SEEK_SET) = 0
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509440, [509440], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\x0c\x4d\xb6\x09\x68\x0e\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509448, [509448], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\x74\x5b\xb6\x09\xfe\x0e\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509456, [509456], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\x72\x6a\xb6\x09\x67\x0f\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509464, [509464], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\xd9\x79\xb6\x09\xa9\x0f\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509472, [509472], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\x82\x89\xb6\x09\xbb\x0f\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509480, [509480], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\x3d\x99\xb6\x09\x08\x10\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509488, [509488], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\x45\xa9\xb6\x09\xd1\x0f\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509496, [509496], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\x16\xb9\xb6\x09\x01\x0f\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509504, [509504], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\x17\xc8\xb6\x09\xc4\x0e\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509512, [509512], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\xdb\xd6\xb6\x09\xe3\x0e\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509520, [509520], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\xbe\xe5\xb6\x09\x0c\x0f\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509528, [509528], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\xca\xf4\xb6\x09\x41\x0f\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509536, [509536], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\x0b\x04\xb7\x09\xa6\x0f\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509440, [509440], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\x0c\x4d\xb6\x09\x68\x0e\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 164448540, [164448540], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\xf7\x00\x0a\x01\x35\x00\x54\x00\x00\x00\x00\x00\x50\x0e\x00\x00\xd4\x71\x3b\x01\x00\x00\x00\x00\x80\x13\x87\x2a\x2a\x2b\x2a\x2b"..., 3688) = 3688
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509448, [509448], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\x74\x5b\xb6\x09\xfe\x0e\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 164452228, [164452228], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\xf5\x00\x08\x01\x37\x00\x57\x00\x00\x00\x00\x00\xe6\x0e\x00\x00\xd4\x71\x3b\x01\x00\x00\x00\x00\x80\x15\x03\x2a\x8a\x2b\x2a\x2c"..., 3838) = 3838
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509456, [509456], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\x72\x6a\xb6\x09\x67\x0f\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 164456066, [164456066], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\xf4\x00\x08\x01\x39\x00\x5a\x00\x00\x00\x00\x00\x4f\x0f\x00\x00\xd4\x71\x3b\x01\x00\x00\x00\x00\x80\x18\x81\x2a\x05\x2b\x80\x1b"..., 3943) = 3943
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509464, [509464], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\xd9\x79\xb6\x09\xa9\x0f\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 164460009, [164460009], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\xee\x00\x07\x01\x42\x00\x5b\x00\x00\x00\x00\x00\x91\x0f\x00\x00\xd4\x71\x3b\x01\x00\x00\x00\x00\x80\x22\x81\x2a\x80\x1f\x00\x80"..., 4009) = 4009
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509472, [509472], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\x82\x89\xb6\x09\xbb\x0f\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 164464018, [164464018], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\xee\x00\x0a\x01\x43\x00\x5c\x00\x00\x00\x00\x00\xa3\x0f\x00\x00\xd4\x71\x3b\x01\x00\x00\x00\x00\x80\x23\x03\x29\x03\x2b\x80\x1a"..., 4027) = 4027
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509480, [509480], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\x3d\x99\xb6\x09\x08\x10\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 164468045, [164468045], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\xec\x00\x09\x01\x43\x00\x5a\x00\x00\x00\x00\x00\xf0\x0f\x00\x00\xd4\x71\x3b\x01\x00\x00\x00\x00\x80\x24\x81\x2a\x80\x1e\x00\x80"..., 4104) = 4104
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509488, [509488], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\x45\xa9\xb6\x09\xd1\x0f\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 164472149, [164472149], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\xee\x00\x09\x01\x3f\x00\x56\x00\x00\x00\x00\x00\xb9\x0f\x00\x00\xd4\x71\x3b\x01\x00\x00\x00\x00\x80\x1d\x8a\x26\x26\x48\x29\x2a"..., 4049) = 4049
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509496, [509496], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\x16\xb9\xb6\x09\x01\x0f\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 164476198, [164476198], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\xf6\x00\x08\x01\x35\x00\x5b\x00\x00\x00\x00\x00\xe9\x0e\x00\x00\xd4\x71\x3b\x01\x00\x00\x00\x00\x80\x10\x81\x2a\x04\x2b\x86\x2a"..., 3841) = 3841
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509504, [509504], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\x17\xc8\xb6\x09\xc4\x0e\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 164480039, [164480039], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\xf7\x00\x07\x01\x33\x00\x5b\x00\x00\x00\x00\x00\xac\x0e\x00\x00\xd4\x71\x3b\x01\x00\x00\x00\x00\x80\x1b\x88\x2b\x2c\x2b\x2c\x2c"..., 3780) = 3780
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509512, [509512], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\xdb\xd6\xb6\x09\xe3\x0e\x00\x00", 8) = 8
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 164483819, [164483819], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\xf8\x00\x07\x01\x41\x00\x5f\x00\x00\x00\x00\x00\xcb\x0e\x00\x00\xd4\x71\x3b\x01\x00\x00\x00\x00\x80\x1c\x83\x2c\x2c\x2a\x80\x22"..., 3811) = 3811
|
|
|
|
|
|
|
|
_llseek(<WarHammer.ani>, 509520, [509520], SEEK_SET) = 0
|
|
|
|
read(<WarHammer.ani>, "\xbe\xe5\xb6\x09\x0c\x0f\x00\x00", 8) = 8
|
2020-04-15 00:27:43 +01:00
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
2020-04-15 22:18:53 +01:00
|
|
|
Notable is that we read from `idx` **before** we read from `ani` - so it does
|
|
|
|
seem like the former should tell us where to pull from the latter.
|
2020-04-15 21:11:01 +01:00
|
|
|
|
2020-04-15 22:18:53 +01:00
|
|
|
We still load 5 type 2 records, even though there's just a single librarian, and
|
|
|
|
8 compass points. Why 5? After looking in `idx`, we load 10 sprites from `ani`,
|
|
|
|
which is at least a multiple. Do any of the records we load from `idx` specify
|
|
|
|
sprite directory offsets that match?
|
2020-04-15 21:11:01 +01:00
|
|
|
|
2020-04-15 22:18:53 +01:00
|
|
|
## `Data/HasAction.dat`
|
2020-04-15 21:11:01 +01:00
|
|
|
|
|
|
|
This file seems relevant as it says whether or not particular animations exist
|
|
|
|
for the different types of character, which maps directly to what is stored in
|
|
|
|
the .ani file - and so must affect lookups thereof.
|
|
|
|
|
|
|
|
Fortunately, it's commented extensively. For each "Character Type", there are
|
|
|
|
36 different possible animations.
|
|
|
|
|
|
|
|
Here's a table representation of the data:
|
|
|
|
|
|
|
|
```
|
|
|
|
Tac Ass Dev Term Apo Tech Chp Lib Cpt CMar CLrd CChp CSrc CTrm Kbz BTh BL FHnd LoC Flm PHr BHr Cult
|
|
|
|
00 x x x x x x x x x x x x x x x x x x x x x x x
|
|
|
|
01 x x x x x x x x x x x x x x x x x x x x x x x
|
|
|
|
02 x x x x x x x x x x x x x x x x x x x x x x x
|
|
|
|
03
|
|
|
|
04
|
|
|
|
05
|
|
|
|
06 x x x x x x x x x x x x x x x x x x x x
|
|
|
|
07 x x x x x x x x x x x x x x x x x x x x x x x
|
|
|
|
08 x x x x x x x x x x x x x x x x
|
|
|
|
09
|
|
|
|
10
|
|
|
|
11
|
|
|
|
12
|
|
|
|
13
|
|
|
|
14 x x x x x x x x x x x x x
|
|
|
|
15 x x x x x x x x x x x x x
|
|
|
|
16 x x x x x x x x x x x x x
|
|
|
|
17 x x x x x x x x x x x x x
|
|
|
|
18 x x x x x x x x x x x x x
|
|
|
|
19 x x x x x x x x x x x x x
|
|
|
|
20 x x x x x x x x x x x x x
|
|
|
|
21 x x x x x x x x x x x x x
|
|
|
|
22 x x x x x x x x x x x x x x
|
|
|
|
23 x x x x x x x x x x x x x
|
|
|
|
24 x x x x x x x x x x x x x x x x
|
|
|
|
25 x x x x x x x x x x x x x x x x x x x x x x
|
|
|
|
26 x x x x x x x x x x x x x x x x x
|
|
|
|
27 x x x x x x x x x x x x x x x x x x x x x
|
|
|
|
28 x x x x x x x x x x x x x x
|
|
|
|
29 x x x
|
|
|
|
30 x
|
|
|
|
31 x
|
|
|
|
32 x x x
|
|
|
|
33 x x x x x x x x x x x x x x x x x x x x x
|
|
|
|
34 x x x x x x x x x x x x x x x x x x x x x x x
|
|
|
|
35 x x x x x x x
|
|
|
|
```
|
|
|
|
|
|
|
|
`WarHammer.ani` doesn't have blank sprites for the unchecked cells, so this must
|
|
|
|
surely be used to map between set-of-sprites and `AnimAction`.
|
|
|
|
|
|
|
|
I think we still need the data in `.idx` for a full picture, though. Things we
|
|
|
|
still need:
|
|
|
|
|
|
|
|
* Mapping of character type to sprite directory index in `WarHammer.ani`
|
|
|
|
* Number of frames in each AnimAction
|
|
|
|
|
|
|
|
Either of these could be hardcoded, or dynamic.
|