diff --git a/source/build/include/build.h b/source/build/include/build.h index c61b66484..120ecfebd 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -428,6 +428,10 @@ int32_t cansee(int32_t x1, int32_t y1, int32_t z1, int16_t sect1, int32_t x2, int32_t y2, int32_t z2, int16_t sect2); int32_t inside(int32_t x, int32_t y, int sectnum); void dragpoint(int pointhighlight, int32_t dax, int32_t day, uint8_t flags = 0); +inline void dragpoint(walltype* pointhighlight, int32_t dax, int32_t day, uint8_t flags = 0) +{ + dragpoint(int(pointhighlight - wall), dax, day, 0); +} int32_t try_facespr_intersect(uspriteptr_t const spr, vec3_t const in, int32_t vx, int32_t vy, int32_t vz, vec3_t * const intp, int32_t strictly_smaller_than_p); diff --git a/source/core/version.h b/source/core/version.h index 1ab4f4fcc..2e71395ab 100644 --- a/source/core/version.h +++ b/source/core/version.h @@ -74,7 +74,7 @@ const char *GetVersionString(); #define MINSAVEVER_SW 13 #define MINSAVEVER_PS 15 -#define SAVEVER_DN3D 11 +#define SAVEVER_DN3D 12 #define SAVEVER_BLD 11 #define SAVEVER_SW 13 #define SAVEVER_PS 15 diff --git a/source/games/duke/src/actors.cpp b/source/games/duke/src/actors.cpp index 168aa0769..fec099f7a 100644 --- a/source/games/duke/src/actors.cpp +++ b/source/games/duke/src/actors.cpp @@ -4276,8 +4276,9 @@ void handle_se20(DDukeActor* actor) } } - dragpoint(t[1], wall[t[1]].x + x, wall[t[1]].y + l); - dragpoint(t[2], wall[t[2]].x + x, wall[t[2]].y + l); + auto& wal = actor->temp_walls; + dragpoint(wal[0], wal[0]->x + x, wal[0]->y + l); + dragpoint(wal[1], wal[1]->x + x, wal[1]->y + l); for (int p = connecthead; p >= 0; p = connectpoint2[p]) if (ps[p].cursectnum == s->sectnum && ps[p].on_ground) @@ -4709,9 +4710,10 @@ void handle_se128(DDukeActor *actor) { int* t = &actor->temp_data[0]; - auto wal = &wall[t[2]]; + auto wal = actor->temp_walls[0]; + if (!wal) return; // E4L1 contains an uninitialized SE128 which would crash without this. -// if (wal->cstat | 32) // this has always been bugged, the condition can never be false. + //if (wal->cstat | 32) // this has always been bugged, the condition can never be false. { wal->cstat &= (255 - 32); wal->cstat |= 16; @@ -4724,15 +4726,16 @@ void handle_se128(DDukeActor *actor) // else return; wal->overpicnum++; - if (wal->nextwall >= 0) - wal->nextWall()->overpicnum++; + auto nextwal = wal->nextWall(); + if (nextwal) + nextwal->overpicnum++; if (t[0] < t[1]) t[0]++; else { wal->cstat &= (128 + 32 + 8 + 4 + 2); - if (wal->nextwall >= 0) - wal->nextWall()->cstat &= (128 + 32 + 8 + 4 + 2); + if (nextwal) + nextwal->cstat &= (128 + 32 + 8 + 4 + 2); deletesprite(actor); } } diff --git a/source/games/duke/src/actors_d.cpp b/source/games/duke/src/actors_d.cpp index 866d006a1..8fbee700c 100644 --- a/source/games/duke/src/actors_d.cpp +++ b/source/games/duke/src/actors_d.cpp @@ -3745,7 +3745,7 @@ void moveeffectors_d(void) //STATNUM 3 } break; - case 128: //SE to control glass breakage + case SE_128_GLASS_BREAKING: handle_se128(act); break; diff --git a/source/games/duke/src/actors_r.cpp b/source/games/duke/src/actors_r.cpp index e8f5672a9..51f8e1750 100644 --- a/source/games/duke/src/actors_r.cpp +++ b/source/games/duke/src/actors_r.cpp @@ -3633,7 +3633,7 @@ void moveeffectors_r(void) //STATNUM 3 } break; - case 128: //SE to control glass breakage + case SE_128_GLASS_BREAKING: handle_se128(act); break; diff --git a/source/games/duke/src/constants.h b/source/games/duke/src/constants.h index d88db1693..2ada74e68 100644 --- a/source/games/duke/src/constants.h +++ b/source/games/duke/src/constants.h @@ -87,6 +87,7 @@ enum SE_48_LIGHT_SWITCH = 48, SE_49_POINT_LIGHT = 49, SE_50_SPOT_LIGHT = 50, + SE_128_GLASS_BREAKING = 128, SE_130 = 130, SE_131 = 131, }; diff --git a/source/games/duke/src/savegame.cpp b/source/games/duke/src/savegame.cpp index 924dffe1f..55278b9b1 100644 --- a/source/games/duke/src/savegame.cpp +++ b/source/games/duke/src/savegame.cpp @@ -293,7 +293,27 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, DDukeActor& w, DDu ("temp_actor", w.temp_actor, def->temp_actor) ("seek_actor", w.seek_actor, def->seek_actor) .Array("temp_data", w.temp_data, def->temp_data, 6) + .Array("temo_wall", w.temp_walls, def->temp_walls,2) + ("temp_sect", w.temp_sect, def->temp_sect) .EndObject(); + +#ifdef OLD_SAVEGAME + // compat handling + if (SaveVersion < 12 && arc.isReading()) + { + if (w.s->picnum == SECTOREFFECTOR) + { + if (w.s->lotag == SE_20_STRETCH_BRIDGE) + { + for (int i : {0, 1}) w.temp_walls[i] = &wall[w.temp_data[i+1]]; + } + if (w.s->lotag == SE_128_GLASS_BREAKING) + { + w.temp_walls[0] = &wall[w.temp_data[2]]; + } + } + } +#endif } return arc; } diff --git a/source/games/duke/src/sectors_d.cpp b/source/games/duke/src/sectors_d.cpp index 6bca6ec07..f4e71744b 100644 --- a/source/games/duke/src/sectors_d.cpp +++ b/source/games/duke/src/sectors_d.cpp @@ -723,7 +723,7 @@ void checkhitwall_d(DDukeActor* spr, int dawallnum, int x, int y, int z, int atw auto spawned = EGS(sn, x, y, z, SECTOREFFECTOR, 0, 0, 0, ps[0].angle.ang.asbuild(), 0, 0, spr, 3); spawned->s->lotag = 128; spawned->temp_data[1] = 5; - spawned->temp_data[2] = dawallnum; + spawned->temp_walls[0] = wal; S_PlayActorSound(GLASS_BREAKING, spawned); return; } diff --git a/source/games/duke/src/sectors_r.cpp b/source/games/duke/src/sectors_r.cpp index bdf8111da..be7f0ae59 100644 --- a/source/games/duke/src/sectors_r.cpp +++ b/source/games/duke/src/sectors_r.cpp @@ -1040,9 +1040,9 @@ void checkhitwall_r(DDukeActor* spr, int dawallnum, int x, int y, int z, int atw wal->nextWall()->cstat = 0; auto spawned = EGS(sn, x, y, z, SECTOREFFECTOR, 0, 0, 0, ps[0].angle.ang.asbuild(), 0, 0, spr, 3); - spawned->s->lotag = 128; + spawned->s->lotag = SE_128_GLASS_BREAKING; spawned->temp_data[1] = 2; - spawned->temp_data[2] = dawallnum; + spawned->temp_walls[0] = wal; S_PlayActorSound(GLASS_BREAKING, spawned); return; } @@ -1057,9 +1057,9 @@ void checkhitwall_r(DDukeActor* spr, int dawallnum, int x, int y, int z, int atw wal->nextWall()->cstat = 0; auto spawned = EGS(sn, x, y, z, SECTOREFFECTOR, 0, 0, 0, ps[0].angle.ang.asbuild(), 0, 0, spr, 3); - spawned->s->lotag = 128; + spawned->s->lotag = SE_128_GLASS_BREAKING; spawned->temp_data[1] = 2; - spawned->temp_data[2] = dawallnum; + spawned->temp_walls[0] = wal; S_PlayActorSound(GLASS_BREAKING, spawned); return; } diff --git a/source/games/duke/src/spawn.cpp b/source/games/duke/src/spawn.cpp index 0fa9705f2..a74b060f7 100644 --- a/source/games/duke/src/spawn.cpp +++ b/source/games/duke/src/spawn.cpp @@ -796,6 +796,7 @@ void spawneffector(DDukeActor* actor) case SE_20_STRETCH_BRIDGE: { int q; + walltype* closewall = nullptr; startwall = sectp->wallptr; endwall = startwall + sectp->wallnum; @@ -803,37 +804,31 @@ void spawneffector(DDukeActor* actor) //find the two most clostest wall x's and y's q = 0x7fffffff; - for (s = startwall; s < endwall; s++) + for (auto& wal : wallsofsector(sectp)) { - x = wall[s].x; - y = wall[s].y; - - d = FindDistance2D(sp->x - x, sp->y - y); + d = FindDistance2D(sp->x - wal.x, sp->y - wal.y); if (d < q) { q = d; - clostest = s; + closewall = &wal; } } - t[1] = clostest; + actor->temp_walls[0] = closewall; q = 0x7fffffff; - for (s = startwall; s < endwall; s++) + for (auto& wal : wallsofsector(sectp)) { - x = wall[s].x; - y = wall[s].y; - - d = FindDistance2D(sp->x - x, sp->y - y); - if (d < q && s != t[1]) + d = FindDistance2D(sp->x - wal.x, sp->y - wal.y); + if (d < q && &wal != actor->temp_walls[0]) { q = d; - clostest = s; + closewall = &wal; } } - t[2] = clostest; + actor->temp_walls[1] = closewall; StartInterpolation(sect, Interp_Sect_FloorPanX); StartInterpolation(sect, Interp_Sect_FloorPanY); break; diff --git a/source/games/duke/src/types.h b/source/games/duke/src/types.h index d83760e95..e70fd75f2 100644 --- a/source/games/duke/src/types.h +++ b/source/games/duke/src/types.h @@ -35,6 +35,10 @@ struct DDukeActor int palvals; }; int temp_data[6]; + // Some SE's stored indices in temp_data. For purposes of clarity avoid that. These variables are meant to store these elements now + walltype* temp_walls[2]; // SE20 + SE128 + sectortype* temp_sect; + DDukeActor* temp_actor, *seek_actor; spritetype* s; // direct reference to the corresponding sprite.