diff --git a/docs/rh-log.txt b/docs/rh-log.txt index bc123c783..6b590a69d 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,17 @@ +March 20, 2008 (Changes by Graf Zahl) +- Fixed: A_CustomMissile with aimmode 2 ignored spawnofs_xy. +- Changed savegame versioning so that the written version is never lower + than the minmum one reported as compatible. +- Added mirrored movement modes for linked sectors. +- Added Eternity-style initialization for linked sectors as a new subtype + of Static_Init. +- Added linked sectors. The control sector determines how they move but if + any one of the linked sectors is blocked, movement for all linked sectors + will be affected. This will allow lifts consisting out of more than one + sector without the risk of breaking them if only one of the sectors is + blocked. +- Fixed: A_Mushroom created an actor on the stack. + March 19, 2008 - Fixed: lempar.c needs to specify the __cdecl calling convention for malloc and free under VC++. diff --git a/src/actionspecials.h b/src/actionspecials.h index efe7ad58e..3821b5e3b 100644 --- a/src/actionspecials.h +++ b/src/actionspecials.h @@ -48,6 +48,7 @@ DEFINE_SPECIAL(Ceiling_MoveToValue, 47, 3, 4) DEFINE_SPECIAL(Sector_Attach3dMidtex, 48, -1, -1) DEFINE_SPECIAL(GlassBreak, 49, 0, 1) DEFINE_SPECIAL(ExtraFloor_LightOnly, 50, -1, -1) +DEFINE_SPECIAL(Sector_SetLink, 51, 4, 4) DEFINE_SPECIAL(Plat_PerpetualRaise, 60, 3, 3) DEFINE_SPECIAL(Plat_Stop, 61, 1, 1) diff --git a/src/dsectoreffect.cpp b/src/dsectoreffect.cpp index e94050390..11a61c4f5 100644 --- a/src/dsectoreffect.cpp +++ b/src/dsectoreffect.cpp @@ -111,6 +111,12 @@ bool DMover::MoveAttached(int crush, fixed_t move, int floorOrCeiling, bool rese P_Scroll3dMidtex(m_Sector, crush, -move, !!floorOrCeiling); return false; } + if (!P_MoveLinkedSectors(m_Sector, crush, move, !!floorOrCeiling) && resetfailed) + { + P_MoveLinkedSectors(m_Sector, crush, -move, !!floorOrCeiling); + P_Scroll3dMidtex(m_Sector, crush, -move, !!floorOrCeiling); + return false; + } return true; } diff --git a/src/g_doom/a_fatso.cpp b/src/g_doom/a_fatso.cpp index d21e65d30..b5e686f46 100644 --- a/src/g_doom/a_fatso.cpp +++ b/src/g_doom/a_fatso.cpp @@ -134,15 +134,17 @@ void A_Mushroom (AActor *actor) A_Explode (actor); // First make normal explosion // Now launch mushroom cloud + AActor *target = Spawn("Mapspot", 0, 0, 0, NO_REPLACE); // We need something to aim at. + target->height = actor->height; for (i = -n; i <= n; i += 8) { for (j = -n; j <= n; j += 8) { - AActor target = *actor, *mo; - target.x += i << FRACBITS; // Aim in many directions from source - target.y += j << FRACBITS; - target.z += P_AproxDistance(i,j) << (FRACBITS+2); // Aim up fairly high - mo = P_SpawnMissile (actor, &target, spawntype); // Launch fireball + AActor *mo; + target->x = actor->x + (i << FRACBITS); // Aim in many directions from source + target->y = actor->y + (j << FRACBITS); + target->z = actor->z + (P_AproxDistance(i,j) << (FRACBITS+2)); // Aim up fairly high + mo = P_SpawnMissile (actor, target, spawntype); // Launch fireball if (mo != NULL) { mo->momx >>= 1; @@ -152,4 +154,5 @@ void A_Mushroom (AActor *actor) } } } + target->Destroy(); } diff --git a/src/p_3dmidtex.h b/src/p_3dmidtex.h index 215da2b3d..0b9497ec7 100644 --- a/src/p_3dmidtex.h +++ b/src/p_3dmidtex.h @@ -15,5 +15,11 @@ bool P_GetMidTexturePosition(const line_t *line, int sideno, fixed_t *ptextop, f bool P_Check3dMidSwitch(AActor *actor, line_t *line, int side); bool P_LineOpening_3dMidtex(AActor *thing, const line_t *linedef, fixed_t &opentop, fixed_t &openbottom); +bool P_MoveLinkedSectors(sector_t *sector, int crush, fixed_t move, bool ceiling); +void P_StartLinkedSectorInterpolations(sector_t *sector, bool ceiling); +void P_StopLinkedSectorInterpolations(sector_t *sector, bool ceiling); +bool P_AddSectorLinks(sector_t *control, int tag, INTBOOL ceiling, int movetype); +void P_AddSectorLinksByID(sector_t *control, int id, INTBOOL ceiling); + #endif diff --git a/src/p_linkedsectors.cpp b/src/p_linkedsectors.cpp new file mode 100644 index 000000000..b24ff3d15 --- /dev/null +++ b/src/p_linkedsectors.cpp @@ -0,0 +1,398 @@ +/* +** p_linkedsectors.cpp +** +** Linked sector movement +** +**--------------------------------------------------------------------------- +** Copyright 2008 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "templates.h" +#include "p_local.h" +#include "p_lnspec.h" + +enum +{ + // The different movement types. + LINK_NONE=0, + LINK_FLOOR=1, + LINK_CEILING=2, + LINK_BOTH=3, + LINK_FLOORMIRRORFLAG=4, + LINK_CEILINGMIRRORFLAG=8, + + LINK_FLOORMIRROR=5, + LINK_CEILINGMIRROR=10, + LINK_BOTHMIRROR=15, + + LINK_FLAGMASK = 15 + +}; + + +//============================================================================ +// +// Checks whether the other sector is linked to this one +// Used to ignore linked sectors in the FindNextLowest/Highest* +// functions +// +// NOTE: After looking at Eternity's code I discovered that this check +// is not done for the FindNext* function but instead only for +// FindLowestCeilingSurrounding where IMO it makes much less sense +// because the most frequent use of this feature is most likely lifts +// with a more detailed surface. Needs to be investigated! +// +//============================================================================ + +bool sector_t::IsLinked(sector_t *other, bool ceiling) const +{ + extsector_t::linked::plane &scrollplane = ceiling? e->Linked.Ceiling : e->Linked.Floor; + int flag = ceiling? LINK_CEILING : LINK_FLOOR; + + for(unsigned i = 0; i < scrollplane.Sectors.Size(); i++) + { + if (other == scrollplane.Sectors[i].Sector && scrollplane.Sectors[i].Type & flag) return true; + } + return false; +} + + +//============================================================================ +// +// Helper functions for P_MoveLinkedSectors +// +//============================================================================ + +static bool MoveCeiling(sector_t *sector, int crush, fixed_t move) +{ + sector->ceilingplane.ChangeHeight (move); + sector->ceilingtexz += move; + + if (P_ChangeSector(sector, crush, move, 1)) return false; + + // Don't let the ceiling go below the floor + if ((sector->ceilingplane.a | sector->ceilingplane.b | + sector->floorplane.a | sector->floorplane.b) == 0 && + sector->floortexz > sector->ceilingtexz) return false; + + return true; +} + +static bool MoveFloor(sector_t *sector, int crush, fixed_t move) +{ + sector->floorplane.ChangeHeight (move); + sector->floortexz += move; + + if (P_ChangeSector(sector, crush, move, 0)) return false; + + // Don't let the floor go above the ceiling + if ((sector->ceilingplane.a | sector->ceilingplane.b | + sector->floorplane.a | sector->floorplane.b) == 0 && + sector->floortexz > sector->ceilingtexz) return false; + + return true; +} + +//============================================================================ +// +// P_MoveLinkedSectors +// +// Moves all floors/ceilings linked to the control sector +// Important: All sectors must complete their movement +// even if a previous one already failed. +// +//============================================================================ + +bool P_MoveLinkedSectors(sector_t *sector, int crush, fixed_t move, bool ceiling) +{ + extsector_t::linked::plane &scrollplane = ceiling? sector->e->Linked.Ceiling : sector->e->Linked.Floor; + bool ok = true; + + for(unsigned i = 0; i < scrollplane.Sectors.Size(); i++) + { + switch(scrollplane.Sectors[i].Type) + { + case LINK_FLOOR: + ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, move); + break; + + case LINK_CEILING: + ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, move); + break; + + case LINK_BOTH: + if (move < 0) + { + ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, move); + ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, move); + } + else + { + ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, move); + ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, move); + } + break; + + case LINK_FLOORMIRROR: + ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, -move); + break; + + case LINK_CEILINGMIRROR: + ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, -move); + break; + + case LINK_BOTHMIRROR: + if (move > 0) + { + ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, -move); + ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, -move); + } + else + { + ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, -move); + ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, -move); + } + break; + + case LINK_FLOOR+LINK_CEILINGMIRROR: + ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, move); + ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, -move); + break; + + case LINK_CEILING+LINK_FLOORMIRROR: + ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, -move); + ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, move); + break; + + default: + // all other types are invalid and have to be elimintated in the attachment stage + break; + } + } + return ok; +} + +//============================================================================ +// +// P_StartLinkedSectorInterpolations +// +// Starts interpolators for every sector plane is being changed by moving +// this sector +// +//============================================================================ + +void P_StartLinkedSectorInterpolations(sector_t *sector, bool ceiling) +{ + extsector_t::linked::plane &scrollplane = ceiling? sector->e->Linked.Ceiling : sector->e->Linked.Floor; + + for(unsigned i = 0; i < scrollplane.Sectors.Size(); i++) + { + if (scrollplane.Sectors[i].Type & LINK_FLOOR) + { + setinterpolation(INTERP_SectorFloor, scrollplane.Sectors[i].Sector, false); + } + if (scrollplane.Sectors[i].Type & LINK_CEILING) + { + setinterpolation(INTERP_SectorCeiling, scrollplane.Sectors[i].Sector, false); + } + } +} + +//============================================================================ +// +// P_StopLinkedSectorInterpolations +// +// Stops interpolators for every sector plane is being changed by moving +// this sector +// +//============================================================================ + +void P_StopLinkedSectorInterpolations(sector_t *sector, bool ceiling) +{ + extsector_t::linked::plane &scrollplane = ceiling? sector->e->Linked.Ceiling : sector->e->Linked.Floor; + + for(unsigned i = 0; i < scrollplane.Sectors.Size(); i++) + { + if (scrollplane.Sectors[i].Type & LINK_FLOOR) + { + stopinterpolation(INTERP_SectorFloor, scrollplane.Sectors[i].Sector, false); + } + if (scrollplane.Sectors[i].Type & LINK_CEILING) + { + stopinterpolation(INTERP_SectorCeiling, scrollplane.Sectors[i].Sector, false); + } + } +} + + + +//============================================================================ +// +// AddSingleSector +// +// Adds a single sector to a scroll plane. Checks for invalid +// flag combinations if the sector is already added and removes it if necessary. +// +//============================================================================ + +static void AddSingleSector(extsector_t::linked::plane &scrollplane, sector_t *sector, int movetype) +{ + // First we have to check the list if the sector is already in it + // If so the move type may have to be adjusted or the link to be removed + + for(unsigned i = 0; i < scrollplane.Sectors.Size(); i++) + { + if (scrollplane.Sectors[i].Sector == sector) + { + int oldtype = scrollplane.Sectors[i].Type; + + if ((oldtype & (LINK_FLOOR|LINK_FLOORMIRROR)) && + (movetype & (LINK_FLOORMIRROR|LINK_FLOOR))) + { + // Invalid combination for floor. + movetype &= ~(LINK_FLOOR + LINK_FLOORMIRROR); + } + + if ((oldtype & (LINK_CEILING|LINK_CEILINGMIRROR)) && + (movetype == LINK_CEILINGMIRROR || movetype == LINK_CEILING)) + { + // Invalid combination for CEILING. + movetype &= ~(LINK_CEILING + LINK_CEILINGMIRROR); + } + + scrollplane.Sectors[i].Type |= movetype; + return; + } + } + + // The sector hasn't been attached yet so do it now + + FLinkedSector newlink = {sector, movetype}; + scrollplane.Sectors.Push(newlink); +} + +//============================================================================ +// +// RemoveTaggedSectors +// +// Remove all sectors with the given tag from the link list +// +//============================================================================ + +static void RemoveTaggedSectors(extsector_t::linked::plane &scrollplane, int tag) +{ + for(int i = scrollplane.Sectors.Size()-1; i>=0; i--) + { + if (scrollplane.Sectors[i].Sector->tag == tag) + { + scrollplane.Sectors.Delete(i); + } + } +} + + + +//============================================================================ +// +// P_AddSectorLink +// +// Links sector planes to a control sector based on the sector's tag +// +//============================================================================ + +bool P_AddSectorLinks(sector_t *control, int tag, INTBOOL ceiling, int movetype) +{ + int param = movetype; + + // can't be done if the control sector is moving. + if ((ceiling && control->ceilingdata) || (!ceiling && control->floordata)) return false; + + // Make sure we have only valid combinations + movetype &= LINK_FLAGMASK; + if ((movetype & LINK_FLOORMIRROR) == LINK_FLOORMIRRORFLAG) movetype &= ~LINK_FLOORMIRRORFLAG; + if ((movetype & LINK_CEILINGMIRROR) == LINK_CEILINGMIRRORFLAG) movetype &= ~LINK_CEILINGMIRRORFLAG; + + // Don't remove any sector if the parameter is invalid. + // Addition may still be performed based on the given value. + if (param != 0 && movetype == 0) return false; + + extsector_t::linked::plane &scrollplane = ceiling? control->e->Linked.Ceiling : control->e->Linked.Floor; + + if (movetype > 0) + { + for(int sec = -1; (sec = P_FindSectorFromTag(tag, sec)) >= 0; ) + { + // Don't attach to self! + if (control != §ors[sec]) + { + AddSingleSector(scrollplane, §ors[sec], movetype); + } + } + } + else + { + RemoveTaggedSectors(scrollplane, tag); + } + return true; +} + +//============================================================================ +// +// P_AddSectorLinksByID +// +// Links sector planes to a control sector based on a control linedef +// touching the sectors. This is the method Eternity uses and is here +// mostly so that the Eternity line types can be emulated +// +//============================================================================ + +void P_AddSectorLinksByID(sector_t *control, int id, INTBOOL ceiling) +{ + extsector_t::linked::plane &scrollplane = ceiling? control->e->Linked.Ceiling : control->e->Linked.Floor; + + for(int line = -1; (line = P_FindLineFromID(id, line)) >= 0; ) + { + line_t *ld = &lines[line]; + + if (ld->special == Static_Init && ld->args[1] == Init_SectorLink) + { + int movetype = ld->args[3]; + + // Make sure we have only valid combinations + movetype &= LINK_FLAGMASK; + if ((movetype & LINK_FLOORMIRROR) == LINK_FLOORMIRRORFLAG) movetype &= ~LINK_FLOORMIRRORFLAG; + if ((movetype & LINK_CEILINGMIRROR) == LINK_CEILINGMIRRORFLAG) movetype &= ~LINK_CEILINGMIRRORFLAG; + + if (movetype != 0 && ld->frontsector != NULL && ld->frontsector != control) + { + AddSingleSector(scrollplane, ld->frontsector, movetype); + } + } + } +} diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index e20dd4df8..cbef22134 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -53,6 +53,7 @@ #include "p_conversation.h" #include "a_strifeglobal.h" #include "r_translate.h" +#include "p_3dmidtex.h" #define FUNC(a) static int a (line_t *ln, AActor *it, bool backSide, \ int arg0, int arg1, int arg2, int arg3, int arg4) @@ -1873,6 +1874,21 @@ FUNC(LS_Sector_SetFriction) return true; } +FUNC(LS_Sector_SetLink) +// Sector_SetLink (controltag, linktag, floor/ceiling, movetype) +{ + if (arg0 != 0) // control tag == 0 is for static initialization and must not be handled here + { + int control = P_FindSectorFromTag(arg0, -1); + if (control != 0) + { + return P_AddSectorLinks(§ors[control], arg1, arg2, arg3); + } + } + return false; +} + + static void SetWallScroller (int id, int sidechoice, fixed_t dx, fixed_t dy) { if ((dx | dy) == 0) @@ -2843,7 +2859,7 @@ lnSpecFunc LineSpecials[256] = LS_NOP, // Sector_Attach3dMidtex LS_GlassBreak, LS_NOP, // 50: ExtraFloor_LightOnly - LS_NOP, // 51 + LS_Sector_SetLink, LS_NOP, // 52 LS_NOP, // 53 LS_NOP, // 54 diff --git a/src/p_lnspec.h b/src/p_lnspec.h index 75f1a169b..e6d705618 100644 --- a/src/p_lnspec.h +++ b/src/p_lnspec.h @@ -47,6 +47,7 @@ typedef enum { Init_Gravity = 0, Init_Color = 1, Init_Damage = 2, + Init_SectorLink = 3, NUM_STATIC_INITS, Init_TransferSky = 255 } staticinit_t; diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 90a05a33b..ac95be1f3 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -413,7 +413,9 @@ void extsector_t::Serialize(FArchive &arc) arc << Midtex.Floor.AttachedLines << Midtex.Floor.AttachedSectors << Midtex.Ceiling.AttachedLines - << Midtex.Ceiling.AttachedSectors; + << Midtex.Ceiling.AttachedSectors + << Linked.Floor.Sectors + << Linked.Ceiling.Sectors; } // diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index 7f8f98b13..3d951957a 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -25,6 +25,7 @@ #include "p_spec.h" #include "c_cvars.h" + // [RH] // P_NextSpecialSector() // @@ -170,7 +171,7 @@ fixed_t sector_t::FindNextHighestFloor (vertex_t **v) const { ofloor = other->floorplane.ZatPoint (check->v1); floor = floorplane.ZatPoint (check->v1); - if (ofloor > floor && ofloor - floor < heightdiff) + if (ofloor > floor && ofloor - floor < heightdiff && !IsLinked(other, false)) { heightdiff = ofloor - floor; height = ofloor; @@ -178,7 +179,7 @@ fixed_t sector_t::FindNextHighestFloor (vertex_t **v) const } ofloor = other->floorplane.ZatPoint (check->v2); floor = floorplane.ZatPoint (check->v2); - if (ofloor > floor && ofloor - floor < heightdiff) + if (ofloor > floor && ofloor - floor < heightdiff && !IsLinked(other, false)) { heightdiff = ofloor - floor; height = ofloor; @@ -227,7 +228,7 @@ fixed_t sector_t::FindNextLowestFloor (vertex_t **v) const other = other; ofloor = other->floorplane.ZatPoint (check->v1); floor = floorplane.ZatPoint (check->v1); - if (ofloor < floor && floor - ofloor < heightdiff) + if (ofloor < floor && floor - ofloor < heightdiff && !IsLinked(other, false)) { heightdiff = floor - ofloor; height = ofloor; @@ -235,7 +236,7 @@ fixed_t sector_t::FindNextLowestFloor (vertex_t **v) const } ofloor = other->floorplane.ZatPoint (check->v2); floor = floorplane.ZatPoint (check->v2); - if (ofloor < floor && floor - ofloor < heightdiff) + if (ofloor < floor && floor - ofloor < heightdiff && !IsLinked(other, false)) { heightdiff = floor - ofloor; height = ofloor; @@ -282,7 +283,7 @@ fixed_t sector_t::FindNextLowestCeiling (vertex_t **v) const { oceil = other->ceilingplane.ZatPoint (check->v1); ceil = ceilingplane.ZatPoint (check->v1); - if (oceil < ceil && ceil - oceil < heightdiff) + if (oceil < ceil && ceil - oceil < heightdiff && !IsLinked(other, true)) { heightdiff = ceil - oceil; height = oceil; @@ -290,7 +291,7 @@ fixed_t sector_t::FindNextLowestCeiling (vertex_t **v) const } oceil = other->ceilingplane.ZatPoint (check->v2); ceil = ceilingplane.ZatPoint (check->v2); - if (oceil < ceil && ceil - oceil < heightdiff) + if (oceil < ceil && ceil - oceil < heightdiff && !IsLinked(other, true)) { heightdiff = ceil - oceil; height = oceil; @@ -336,7 +337,7 @@ fixed_t sector_t::FindNextHighestCeiling (vertex_t **v) const { oceil = other->ceilingplane.ZatPoint (check->v1); ceil = ceilingplane.ZatPoint (check->v1); - if (oceil > ceil && oceil - ceil < heightdiff) + if (oceil > ceil && oceil - ceil < heightdiff && !IsLinked(other, true)) { heightdiff = oceil - ceil; height = oceil; @@ -344,7 +345,7 @@ fixed_t sector_t::FindNextHighestCeiling (vertex_t **v) const } oceil = other->ceilingplane.ZatPoint (check->v2); ceil = ceilingplane.ZatPoint (check->v2); - if (oceil > ceil && oceil - ceil < heightdiff) + if (oceil > ceil && oceil - ceil < heightdiff && !IsLinked(other, true)) { heightdiff = oceil - ceil; height = oceil; diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 11c50d1c8..8c3d7a44d 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1792,6 +1792,10 @@ void P_AdjustLine (line_t *ld) case Polyobj_ExplicitLine: ld->id = ld->args[4]; break; + + case Static_Init: + if (ld->args[1] == Init_SectorLink) ld->id = ld->args[0]; + break; } } } diff --git a/src/p_spec.cpp b/src/p_spec.cpp index c083383f1..620b605f9 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -1004,6 +1004,13 @@ void P_SpawnSpecials (void) P_Attach3dMidtexLinesToSector(lines[i].frontsector, lines[i].args[0], lines[i].args[1], !!lines[i].args[2]); break; + case Sector_SetLink: + if (lines[i].args[0] == 0) + { + P_AddSectorLinks(lines[i].frontsector, lines[i].args[1], lines[i].args[2], lines[i].args[3]); + } + break; + // [RH] ZDoom Static_Init settings case Static_Init: switch (lines[i].args[1]) @@ -1030,6 +1037,11 @@ void P_SpawnSpecials (void) } break; + case Init_SectorLink: + if (lines[i].args[3] == 0) + P_AddSectorLinksByID(lines[i].frontsector, lines[i].args[0], lines[i].args[2]); + break; + // killough 10/98: // // Support for sky textures being transferred from sidedefs. diff --git a/src/r_defs.h b/src/r_defs.h index 99a1f464a..596d058d7 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -270,6 +270,13 @@ struct FExtraLight struct line_s; struct sector_t; +struct FLinkedSector +{ + sector_t *Sector; + int Type; +}; + + struct extsector_t { // 3DMIDTEX information @@ -282,13 +289,14 @@ struct extsector_t } Floor, Ceiling; } Midtex; - // linked sectors - /* + // Linked sector information struct linked { - TArray Sectors; + struct plane + { + TArray Sectors; + } Floor, Ceiling; } Linked; - */ void Serialize(FArchive &arc); }; @@ -297,6 +305,7 @@ struct extsector_t struct sector_t { // Member functions + bool IsLinked(sector_t *other, bool ceiling) const; fixed_t FindLowestFloorSurrounding (vertex_t **v) const; fixed_t FindHighestFloorSurrounding (vertex_t **v) const; fixed_t FindNextHighestFloor (vertex_t **v) const; diff --git a/src/r_main.cpp b/src/r_main.cpp index 2413d863a..150304f5f 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1998,7 +1998,7 @@ void updateinterpolations() //Stick at beginning of domovethings } } -void setinterpolation(EInterpType type, void *posptr) +void setinterpolation(EInterpType type, void *posptr, bool dolinks) { FActiveInterpolation **interp_p; FActiveInterpolation *interp = FActiveInterpolation::FindInterpolation (type, posptr, interp_p); @@ -2010,21 +2010,43 @@ void setinterpolation(EInterpType type, void *posptr) *interp_p = interp; interp->CopyInterpToOld (); - if (type == INTERP_SectorFloor) P_Start3dMidtexInterpolations((sector_t*)posptr, false); - else if (type == INTERP_SectorCeiling) P_Start3dMidtexInterpolations((sector_t*)posptr, true); + if (dolinks) + { + if (type == INTERP_SectorFloor) + { + P_Start3dMidtexInterpolations((sector_t*)posptr, false); + P_StartLinkedSectorInterpolations((sector_t*)posptr, false); + } + else if (type == INTERP_SectorCeiling) + { + P_Start3dMidtexInterpolations((sector_t*)posptr, true); + P_StartLinkedSectorInterpolations((sector_t*)posptr, true); + } + } } -void stopinterpolation(EInterpType type, void *posptr) +void stopinterpolation(EInterpType type, void *posptr, bool dolinks) { FActiveInterpolation **interp_p; FActiveInterpolation *interp = FActiveInterpolation::FindInterpolation (type, posptr, interp_p); if (interp != NULL) { - if (type == INTERP_SectorFloor) P_Start3dMidtexInterpolations((sector_t*)posptr, false); - else if (type == INTERP_SectorCeiling) P_Start3dMidtexInterpolations((sector_t*)posptr, true); - *interp_p = interp->Next; delete interp; + + if (dolinks) + { + if (type == INTERP_SectorFloor) + { + P_Stop3dMidtexInterpolations((sector_t*)posptr, false); + P_StopLinkedSectorInterpolations((sector_t*)posptr, false); + } + else if (type == INTERP_SectorCeiling) + { + P_Stop3dMidtexInterpolations((sector_t*)posptr, true); + P_StopLinkedSectorInterpolations((sector_t*)posptr, true); + } + } } } diff --git a/src/r_main.h b/src/r_main.h index fdb3b636f..c4e9b4a41 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -242,8 +242,8 @@ private: static FActiveInterpolation *FindInterpolation(EInterpType, void *interptr, FActiveInterpolation **&interp_p); friend void updateinterpolations(); - friend void setinterpolation(EInterpType, void *interptr); - friend void stopinterpolation(EInterpType, void *interptr); + friend void setinterpolation(EInterpType, void *interptr, bool dolinks); + friend void stopinterpolation(EInterpType, void *interptr, bool dolinks); friend void dointerpolations(fixed_t smoothratio); friend void restoreinterpolations(); friend void clearinterpolations(); @@ -253,8 +253,8 @@ private: }; void updateinterpolations(); -void setinterpolation(EInterpType, void *interptr); -void stopinterpolation(EInterpType, void *interptr); +void setinterpolation(EInterpType, void *interptr, bool dolinks = true); +void stopinterpolation(EInterpType, void *interptr, bool dolinks = true); void dointerpolations(fixed_t smoothratio); void restoreinterpolations(); void clearinterpolations(); diff --git a/src/r_state.h b/src/r_state.h index c8544650c..ebd2d4a72 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -102,6 +102,13 @@ inline FArchive &operator<< (FArchive &arc, side_t *&side) return arc.SerializePointer (sides, (BYTE **)&side, sizeof(*sides)); } +inline FArchive &operator<< (FArchive &arc, FLinkedSector &link) +{ + arc << link.Sector << link.Type; + return arc; +} + + // // POV data. // diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 9aa406e14..87f1bc568 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -752,7 +752,11 @@ void A_CustomMissile(AActor * self) break; case 2: + self->x+=x; + self->y+=y; missile = P_SpawnMissileAngleZ(self, self->z+SpawnHeight, ti, self->angle, 0); + self->x-=x; + self->y-=y; // It is not necessary to use the correct angle here. // The only important thing is that the horizontal momentum is correct. diff --git a/src/version.h b/src/version.h index 83a79acc5..191aed244 100644 --- a/src/version.h +++ b/src/version.h @@ -75,10 +75,10 @@ // SAVESIG should match SAVEVER. // MINSAVEVER is the minimum level snapshot version that can be loaded. -#define MINSAVEVER 817 +#define MINSAVEVER 825 -#if SVN_REVISION_NUMBER == 0 -// This can happen if svnrevision is not updated properly (e.g. compiling while offline) +#if SVN_REVISION_NUMBER < MINSAVEVER +// Never write a savegame with a version lower than what we need #define SAVEVER MINSAVEVER #define MAKESAVESIG(x) "ZDOOMSAVE" #x #define SAVESIG MAKESAVESIG(SAVEVER) diff --git a/zdoom.vcproj b/zdoom.vcproj index bbde9cbd7..627aaf0ed 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + @@ -916,16 +920,6 @@ Outputs=""src/$(InputName).h"" /> - - - @@ -936,6 +930,16 @@ Outputs=""src/$(InputName).h"" /> + + + @@ -1526,16 +1530,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -1546,6 +1540,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -1570,16 +1574,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -1590,6 +1584,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -1614,16 +1618,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -1634,6 +1628,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -1658,16 +1662,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -1678,6 +1672,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -1702,16 +1706,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -1722,6 +1716,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -1882,14 +1886,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -1900,6 +1896,14 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + - - - @@ -2766,6 +2762,14 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> + + + @@ -2920,7 +2924,7 @@ />