diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c2c2f50..75362814 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## v1.2.0 (TBA) ### General +* Fix [#56](https://g1cp.org/issues/56): The water in the swamp is no longer partially invisible. * Fix [#58](https://g1cp.org/issues/58): Falling can no longer be interrupted by fight actions mid-air. * Fix [#194](https://g1cp.org/issues/194): NPCs now correctly pick up the weapon of their defeated opponent. diff --git a/docs/changelog_de.md b/docs/changelog_de.md index 9201509f..d8a609f9 100644 --- a/docs/changelog_de.md +++ b/docs/changelog_de.md @@ -2,6 +2,7 @@ ## v1.2.0 (TBA) ### General +* Fix [#56](https://g1cp.org/issues/56): Das Wasser im Sumpf ist nicht mehr teilweise unsichtbar. * Fix [#58](https://g1cp.org/issues/58): Fallen kann nicht mehr durch Kampfaktionen in der Luft unterbrochen werden. * Fix [#194](https://g1cp.org/issues/194): NSCs sammeln nun korrekt die Waffe ihres besiegten Gegners auf. * Fix [#235](https://g1cp.org/issues/235): Der Name im Magiebuch des Zaubers "Verwandlung Orc-Hund" heißt nun korrekt "Verwandlung Orkhund". diff --git a/src/Ninja/G1CP/Content/Fixes/Gamesave/fix056_SwampPortal.d b/src/Ninja/G1CP/Content/Fixes/Gamesave/fix056_SwampPortal.d new file mode 100644 index 00000000..52620ec2 --- /dev/null +++ b/src/Ninja/G1CP/Content/Fixes/Gamesave/fix056_SwampPortal.d @@ -0,0 +1,135 @@ +/* + * #56 Misplaced swamp portal + */ +func int G1CP_056_SwampPortal() { + var int applied; applied = 0; + + // zCRenderer::SetPolyDrawMode(zTRnd_PolyDrawMode const &) // WMAT == 1 + + // If getting the material instead is sufficient we can do this almost instantly with + const int zCClassDef__SearchHashTable = 5812912; //0x58B2B0 + const int zCMaterial__classDef = 8861992; //0x873928 + CALL_PtrParam(_@s("P:PSU01_")); + CALL_PutRetValTo(_@(matPtr)); + CALL__thiscall(zCMaterial__classDef, zCClassDef__SearchHashTable); + var int matPtr; + if (matPtr) { + var zCMaterial mat; mat = _^(matPtr); + /* + texture: 0 + matGroup: 0 + bspSectorFront: "PSU01" * + bspSectorBack: 0 + kambient: 0 + kdiffuse: -1 + bitfield: 0 + */ + + if (mat.bspSectorFront) { + var zCBspSector sector; sector = _^(mat.bspSectorFront); + + /* + sectorNodes_numInArray: 49 + sectorPortals_numInArray: 72 + sectorPortalInfo_numInArray: 0 + hasBigNoFade: 1868767232 + */ + + // sector.hasBigNoFade = sector.hasBigNoFade | ((1<<8)-1); + + // sector.sectorPortals_array = 0; + // sector.sectorPortals_numAlloc = 0; + // sector.sectorPortals_numInArray = 0; + + // sector.sectorName = "G1CP_disabled_sector"; + + // mat.bspSectorFront = 0; + }; + mat.color = zCOLOR_RED; + // mat._zCObject_objectName = "G1CP_disabled_material"; + }; + + + // ----------- + + + // Iterate over all polygons in the mesh (oof! Way too slow, re-write in assembly) + repeat(i, MEM_World.bspTree_numPolys); var int i; + var zCPolygon poly; poly = _^(MEM_ReadIntArray(MEM_World.bspTree_treePolyList, i)); + + // Find the occluder portal polygons + if (poly.bitfield[0] & (zCPolygon_bitfield_portalPoly | zCPolygon_bitfield_occluder)) + && (!(poly.bitfield[0] & zCPolygon_bitfield_ghostOccluder)) { + + // Check for correct material + if (poly.material) { + if (MEM_ReadInt(poly.material) == zCMaterial_vtbl) { + var zCMaterial mat; mat = _^(poly.material); + if (Hlp_StrCmp(mat._zCObject_objectName, "P:PSU01_")) { + + // --- DEBUG --- + // var int bbox[6]; + // const int zCPolygon__GetBBox3D = 5867456; //0x5987C0 + // CALL_PtrParam(_@(bbox)); + // CALL__thiscall(_@(poly), zCPolygon__GetBBox3D); + // var int ob; ob = DrawBBoxAddr(_@(bbox), zCOLOR_RED); + mat.color = zCOLOR_RED; + // --- DEBUG --- + + // How do we now remove these polygons? + + // Some of the failed attempts: + + /* mat._zCObject_refCtr -= 1; + if (mat._zCObject_refCtr <= 0) { + const int zCMaterial__delete = 5558384; //0x54D070 + CALL_IntParam(-1); + CALL__thiscall(poly.material, zCMaterial__delete); + }; */ + // poly.material = 0; + // poly.bitfield[0] = poly.bitfield[0] & ~(zCPolygon_bitfield_portalPoly + // | zCPolygon_bitfield_occluder); + // poly.bitfield[0] = poly.bitfield[0] | zCPolygon_bitfield_ghostOccluder; + // poly.bitfield[0] = poly.bitfield[0] & ~zCPolygon_bitfield_portalPoly; + // mat._zCObject_objectName = "G1CP_disabled"; + + // // Iterate over all vertices + // var int strBld; strBld = SB_New(); + // repeat(j, poly.bitfield[0] & zCPolygon_bitfield_polyNumVert); var int j; + // var int vertPtr; vertPtr = MEM_ReadIntArray(poly.vertex, j); + + // SB(" ["); + // SBf(MEM_ReadInt(vertPtr)); + // SB(", "); + // SBf(MEM_ReadInt(vertPtr+4)); + // SB(", "); + // SBf(MEM_ReadInt(vertPtr+8)); + // SB("] "); + // end; + // MEM_Info(SB_ToString()); + // SB_Destroy(); + + // At least one poly was adjusted + applied += 1; + }; + }; + }; + }; + end; + + return (applied > 0); +}; + + +/* + * Revert the changes + */ +func int G1CP_056_SwampPortalRevert() { + // Only revert if it was applied by the G1CP + if (!G1CP_IsFixApplied(56)) { + return FALSE; + }; + + // TODO + return FALSE; +}; diff --git a/src/Ninja/G1CP/Content/Fixes/gamesave.d b/src/Ninja/G1CP/Content/Fixes/gamesave.d index 211e36ae..5aa0b6ae 100644 --- a/src/Ninja/G1CP/Content/Fixes/gamesave.d +++ b/src/Ninja/G1CP/Content/Fixes/gamesave.d @@ -31,6 +31,7 @@ func void G1CP_GamesaveFixes_Apply() { G1CP_051_StonehengeCryptChest(); // #51 G1CP_052_UseWithItemNcGrindstone(); // #52 G1CP_055_ReactivateInExtremo(); // #55 + G1CP_056_SwampPortal(); // #56 G1CP_093_DE_LogEntryHoratio(); // #93 G1CP_121_DE_LogTopicShrikeHut(); // #121 G1CP_124_GateGuardId(); // #124 @@ -58,6 +59,7 @@ func void G1CP_GamesaveFixes_Revert() { G1CP_051_StonehengeCryptChestRevert(); // #51 G1CP_052_UseWithItemNcGrindstoneRevert(); // #52 G1CP_055_ReactivateInExtremoRevert(); // #55 + G1CP_056_SwampPortalRevert(); // #56 G1CP_093_DE_LogEntryHoratioRevert(); // #93 G1CP_121_DE_LogTopicShrikeHutRevert(); // #121 G1CP_124_GateGuardIdRevert(); // #124 diff --git a/src/Ninja/G1CP/Content/Tests/test056.d b/src/Ninja/G1CP/Content/Tests/test056.d new file mode 100644 index 00000000..1ff63b01 --- /dev/null +++ b/src/Ninja/G1CP/Content/Tests/test056.d @@ -0,0 +1,14 @@ +/* + * #56 Misplaced swamp portal + * + * There does not seem an easy way to test this fix programmatically, so this test relies on manual confirmation. + * + * Expected behavior: The water will no longer be invisible at that position. + */ +func void G1CP_Test_056() { + G1CP_Testsuite_CheckManual(); + var zCWaypoint wp; wp = G1CP_Testsuite_FindWaypoint("OW_PATH_BLOODFLY12_SPAWN01"); + G1CP_Testsuite_CheckPassed(); + + AI_Teleport(hero, wp.name); +}; diff --git a/src/Ninja/G1CP/Content_G1.src b/src/Ninja/G1CP/Content_G1.src index 5d175add..5a2f94e3 100644 --- a/src/Ninja/G1CP/Content_G1.src +++ b/src/Ninja/G1CP/Content_G1.src @@ -142,6 +142,7 @@ Content\Fixes\Gamesave\fix050_Pillar.d Content\Fixes\Gamesave\fix051_StonehengeCryptChest.d Content\Fixes\Gamesave\fix052_UseWithItemNcGrindstone.d Content\Fixes\Gamesave\fix055_ReactivateInExtremo.d +Content\Fixes\Gamesave\fix056_SwampPortal.d Content\Fixes\Gamesave\fix093_DE_LogEntryHoratio.d Content\Fixes\Gamesave\fix121_DE_LogTopicShrikeHut.d Content\Fixes\Gamesave\fix124_GateGuardId.d diff --git a/src/Ninja/G1CP/Testsuite.src b/src/Ninja/G1CP/Testsuite.src index c2c1766e..8525eaf4 100644 --- a/src/Ninja/G1CP/Testsuite.src +++ b/src/Ninja/G1CP/Testsuite.src @@ -51,6 +51,7 @@ Content\Tests\test050.d Content\Tests\test051.d Content\Tests\test052.d Content\Tests\test055.d +Content\Tests\test056.d Content\Tests\test058.d Content\Tests\test059.d Content\Tests\test060.d