ataulien / ZenLib

Loading of proprietary formats used by the engine used by the games "Gothic" and "Gothic II"
MIT License
56 stars 24 forks source link

Some G2 worlds can not be parsed. #42

Open lmichaelis opened 4 years ago

lmichaelis commented 4 years ago

Some Gothic 2 worlds (see below) can not be parsed. The following std::runtime_error is thrown: Value name does not match expected name. Value:VISUALANIMODE Expected: CDSTATIC

The worlds that cannot be parsed are:

lmichaelis commented 4 years ago

Okay I have located the issue. In zCVob::readObjectData (here) the code for determining which properties to read relies on the WordVersion passed to the function. This causes the files mentioned above to be read as G1 ZENs but they actually contain G2 VOBs.

I don't think this is easily fixable because VOBs with different class names may have different versions refering to the class being used.

Edit: I have extracted all possible class names and corresponding versions for G1 and G2:

Class Name G1 G2 G2 Addon Same?
oCCSTrigger:zCTrigger:zCVob 24577 - - No
oCItem:zCVob 0 0 0 Yes
oCMobBed:oCMobInter:oCMOB:zCVob 61440 61440 61440 Yes
oCMobContainer:oCMobInter:oCMOB:zCVob 64513 64513 64513 Yes
oCMobDoor:oCMobInter:oCMOB:zCVob 64513 64513 64513 Yes
oCMobFire:oCMobInter:oCMOB:zCVob 18433 18433 18433 Yes
oCMobInter:oCMOB:zCVob 35585 35585 35585 Yes
oCMobLadder:oCMobInter:oCMOB:zCVob 35585 - 35585 No
oCMobSwitch:oCMobInter:oCMOB:zCVob 35585 35585 35585 Yes
oCMobWheel:oCMobInter:oCMOB:zCVob 35585 35585 35585 Yes
oCMOB:zCVob 47105 47105 47105 Yes
oCTouchDamage:zCTouchDamage:zCVob 36865 36865 36865 Yes
oCTriggerChangeLevel:zCTrigger:zCVob 24577 24577 24577 Yes
oCTriggerScript:zCTrigger:zCVob 24577 24577 24577 Yes
oCZoneMusicDefault:oCZoneMusic:zCVob 0 0 0 Yes
oCZoneMusic:zCVob 0 0 0 Yes
zCCodeMaster:zCVob 0 0 0 Yes
zCCSCamera:zCVob 30720 33793 33793 No
zCMessageFilter:zCVob 0 0 0 Yes
zCMoverControler:zCVob 0 - - No
zCMover:zCTrigger:zCVob 39936 39936 39936 Yes
zCPFXControler:zCVob 12289 52224 52224 No
zCTriggerList:zCTrigger:zCVob 59776 5505 5505 No
zCTrigger:zCVob 47105 47105 47105 Yes
zCVob 12289 52224 52224 No
zCVobAnimate:zCVob 12289 52224 52224 No
zCVobLensFlare:zCVob 64704 193 193 No
zCVobLevelCompo:zCVob 12289 52224 52224 No
zCVobLight:zCVob 46080 39168 39168 No
zCVobScreenFX:zCVob 12289 - - No
zCVobSoundDaytime:zCVobSound:zCVob 12289 12289 12289 Yes
zCVobSound:zCVob 12289 12289 12289 Yes
zCVobSpot:zCVob 12289 52224 52224 No
zCVobStair:zCVob 12289 - - No
zCVobStartpoint:zCVob 12289 52224 52224 No
zCZoneVobFarPlaneDefault:zCZoneVobFarPlane:zCVob 12289 52224 52224 No
zCZoneVobFarPlane:zCVob 12289 52224 52224 No
zCZoneZFogDefault:zCZoneZFog:zCVob 64704 5505 5505 No
zCZoneZFog:zCVob 64704 5505 5505 No
zCEarthquake:zCVob - 52224 52224 No
zCTriggerUntouch:zCVob - 193 193 No
zCTriggerWorldStart:zCVob - 52224 52224 No
lmichaelis commented 4 years ago

I propose the following solution: use the method below to determine if a chunk should be parsed using the G2 base zCVob definition.

    static bool isG2Vob(uint32_t version, WorldVersion world) {
            switch (version) {
                case 52224:
                case 5505:
                case 193:
                case 39168:
                case 33793:
                    return true;
                default:
                    return world != WorldVersion::VERSION_G1_08k;
            }
        }

Then replace this check with the above method. This is a crude solution and may need further consideration especially because "FIRETREE_MEDIUM.ZEN" from G2's"Worlds.vdf" cannot be parsed with this either. It contains a "zCVobSound:zCVob" chunk with version 12289 (G1) which uses the G2 specification (it has a "visualAniMode" entry etc.)