dgcor / DGEngine

An implementation of the Diablo 1 game engine
Other
252 stars 29 forks source link

Diablo 2 COF animation drawing order #28

Closed ghost closed 5 years ago

ghost commented 5 years ago

Diablo 2's COF animations aren't drawing the shield in the right order.

Diablo 2 sorceress Diablo 2 sorceress 2

This is either a bug in my COF decoder, or in the texturePack order in the configuration files for each player:

https://github.com/dgengin/DGEngine/blob/master/gamefilesd2/level/player/Sorceress/textures.json

This issue is to track the proper way to draw all of the COF animations of Diablo 2.

Can COF file layers be missing and be skipped when drawing (for instance, if the shield isn't equipped, you use a COF with a shield, but don't draw that layer)?

The order of the layers in the COF file isn't always the same, does this affect drawing?

I'm assuming the layers should be loaded in this order: HD, TR, LG, RA, LA, RH, LH, SH, S1, S2, S3, S4, S5, S6, S7, S8 And then the order indexes apply to these.

grantramsay commented 5 years ago

Before I start looking at DT1/DS1 tiles and forget:

The COF layers not showing correctly is just the direction mapping. COFs directions are mapped differently to DCCs (they are simple clockwise from down/South).

Replace this line in CompositeTexture.cpp with below for a quick demo/test of it working:

// Re-map COFs directions.
for (int cofDirection = 0; cofDirection < header.directions; cofDirection++)
{
    int newDirection = cofDirection;
    // TODO: 8 and 32 directions
    if (header.directions == 16)
    {
        // Re-map COF to DCC directions.
        // directionTable is similar to reverse getNormalizedDirection() function
        static const uint8_t directionTable[16] = {
            4, 8, 0, 9, 5, 10, 1, 11, 6, 12, 2, 13, 7, 14, 3, 15 };
        newDirection = directionTable[cofDirection];
    }

    int len = header.frames * header.layers;
    int destIdx = layersOrdersStartIdx + newDirection * len;
    fileStream.read((uint8_t*)layersOrders.data() + destIdx, len);
}

Just an example, you might want to implement it in a different way

(Edited for correctness as per following messages)

ghost commented 5 years ago

I tested and it works.

Isn't the order of the COF drawing indexes the same as the order of the DCC files?

What I did was to get a range from an index. I would think that geting a range and getting the drawing order based on that should work.

grantramsay commented 5 years ago

Sorry I was wrong about the DCC having a different only 8 directions, they both have 16 but the direction mapping is different to COF. Also should've been "clockwise" in previous comment...

I made a table to show the order (ignore bad COF in images, images are only to show DCC direction), things to note in the table:

DCC Direction DCC image COF (BANUHTH.COF) Re-mapped COF
0 0 RightArm Legs Torso LeftArm Special1 Head Special2 Shield RightArm Legs Torso LeftArm Special1 Head Special2 Shield
1 1 RightArm Legs Torso LeftArm Special1 Head Special2 Shield RightArm Legs Torso LeftArm Special1 Head Special2 Shield
2 2 RightArm Legs Torso LeftArm Special1 Head Special2 Shield Legs Shield LeftArm Torso RightArm Special2 Head Special1
3 3 RightArm Legs Torso LeftArm Special1 Head Special2 Shield Legs Shield LeftArm Torso RightArm Special2 Head Special1
4 4 RightArm Legs Torso LeftArm Special1 Head Special2 Shield RightArm Legs Torso LeftArm Special1 Head Special2 Shield
5 5 RightArm Legs Torso LeftArm Special1 Head Special2 Shield RightArm Legs Torso LeftArm Special1 Head Special2 Shield
6 6 RightArm Legs Torso LeftArm Special1 Head Special2 Shield Shield LeftArm Legs Torso RightArm Special2 Head Special1
7 7 RightArm Legs Shield Torso LeftArm Special1 Head Special2 Legs Shield LeftArm Torso RightArm Special2 Head Special1
8 8 Shield LeftArm Legs Torso RightArm Special2 Head Special1 RightArm Legs Torso LeftArm Special1 Head Special2 Shield
9 9 Shield LeftArm Legs Torso RightArm Special2 Head Special1 RightArm Legs Torso LeftArm Special1 Head Special2 Shield
10 10 Legs Shield LeftArm Torso RightArm Special2 Head Special1 RightArm Legs Torso LeftArm Special1 Head Special2 Shield
11 11 Legs Shield LeftArm Torso RightArm Special2 Head Special1 RightArm Legs Shield Torso LeftArm Special1 Head Special2
12 12 Legs Shield LeftArm Torso RightArm Special2 Head Special1 Shield LeftArm Legs Torso RightArm Special2 Head Special1
13 13 Legs Shield LeftArm Torso RightArm Special2 Head Special1 Legs Shield LeftArm Torso RightArm Special2 Head Special1
14 14 Legs Shield LeftArm Torso RightArm Special2 Head Special1 Legs Shield LeftArm Torso RightArm Special2 Head Special1
15 15 Legs Torso LeftArm RightArm Special1 Special2 Shield Head Legs Torso LeftArm RightArm Special1 Special2 Shield Head
ghost commented 5 years ago

Final question, does this re-mapping apply to all COFs or are there exceptions? Such as a 16 direction COF file where the order would be wrong with the re-ordering.

grantramsay commented 5 years ago

AFAIK it applies to all COFs. 8 and 32 directional COFs will also need to be mapped in a similar fashion

ghost commented 5 years ago

Where can I see what the 8 and 32 direction mapping array would be like so as to do both. Sometime in the future I plan on supporting more directions when moving the player.

grantramsay commented 5 years ago

16 (from above):

static const uint8_t directionTable[16] = {
        4, 8, 0, 9, 5, 10, 1, 11, 6, 12, 2, 13, 7, 14, 3, 15 };

8 would just be every second value (e.g. similar to your getNormalizedDirection() func):

static const uint8_t directionTable[8] = {
        4, 0, 5, 1, 6, 2, 7, 3 };

My guess for extrapolating that to 32 would be to insert values 16 -> 31 in every 2nd spot:

static const uint8_t directionTable[32] = {
        4, 16, 8, 17, 0, 18, 9, 19, 5, 20, 10, 21, 1, 22, 11, 23, 6, 24, 12, 25, 2, 26, 13, 27, 7, 28, 14, 29, 3, 30, 15, 31 };

Disclaimer: I could be wrong (I'll see if I can find a 32 directional texture and double check...)

grantramsay commented 5 years ago

With my quick look I couldn't find any 32 directional COF files :/ I had a dig though Riiablo and found what look to be equivalent (but reverse) translations, so I'd say the above is likely correct

ghost commented 5 years ago

fixed in 5667905