diff --git a/src/actionspecials.h b/src/actionspecials.h index 7e783051e..bf6cc38b5 100644 --- a/src/actionspecials.h +++ b/src/actionspecials.h @@ -105,6 +105,7 @@ DEFINE_SPECIAL(Scroll_Texture_Down, 103, -1, -1, 2) DEFINE_SPECIAL(Ceiling_CrushAndRaiseSilentDist, 104, 3, 5, 5) DEFINE_SPECIAL(Door_WaitRaise, 105, 4, 5, 5) DEFINE_SPECIAL(Door_WaitClose, 106, 4, 5, 5) +DEFINE_SPECIAL(Line_SetPortalTarget, 107, 2, 2, 2) DEFINE_SPECIAL(Light_ForceLightning, 109, 1, 1, 1) DEFINE_SPECIAL(Light_RaiseByValue, 110, 2, 2, 2) diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index c74378f61..0061fd5dc 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -57,6 +57,7 @@ #include "d_net.h" #include "d_event.h" #include "gstrings.h" +#include "portal.h" #include "r_data/colormaps.h" #include "fragglescript/t_fs.h" @@ -3383,6 +3384,11 @@ FUNC(LS_Thing_SetConversation) return true; } +FUNC(LS_Line_SetPortalTarget) +// Line_SetPortalTarget(thisid, destid) +{ + return P_ChangePortal(ln, arg0, arg1); +} static lnSpecFunc LineSpecials[] = { @@ -3493,7 +3499,7 @@ static lnSpecFunc LineSpecials[] = /* 104 */ LS_Ceiling_CrushAndRaiseSilentDist, /* 105 */ LS_Door_WaitRaise, /* 106 */ LS_Door_WaitClose, - /* 107 */ LS_NOP, + /* 107 */ LS_Line_SetPortalTarget, /* 108 */ LS_NOP, /* 109 */ LS_Light_ForceLightning, /* 110 */ LS_Light_RaiseByValue, diff --git a/src/portal.cpp b/src/portal.cpp index bfb90cd14..fbbe5c95c 100644 --- a/src/portal.cpp +++ b/src/portal.cpp @@ -29,6 +29,24 @@ FArchive &operator<< (FArchive &arc, FLinePortal &port) } +static line_t *FindDestination(line_t *src, int tag) +{ + if (tag) + { + int lineno = -1; + FLineIdIterator it(tag); + + while ((lineno = it.Next()) >= 0) + { + if (&lines[lineno] != src) + { + return &lines[lineno]; + } + } + } + return NULL; +} + void P_SpawnLinePortal(line_t* line) { // portal destination is special argument #0 @@ -36,21 +54,7 @@ void P_SpawnLinePortal(line_t* line) if (line->args[2] >= PORTT_VISUAL && line->args[2] <= PORTT_LINKED) { - if (line->args[0] > 0) - { - int linenum = -1; - - for (int i = 0; i < numlines; i++) - { - if (&lines[i] == line) - continue; - if (tagManager.LineHasID(&lines[i], line->args[0])) - { - dst = &lines[i]; - break; - } - } - } + dst = FindDestination(line, line->args[0]); line->portalindex = linePortals.Reserve(1); FLinePortal *port = &linePortals.Last(); @@ -156,6 +160,45 @@ void P_FinalizePortals() } } +static bool ChangePortalLine(line_t *line, int destid) +{ + if (line->portalindex >= linePortals.Size()) return false; + FLinePortal *port = &linePortals[line->portalindex]; + if (port->mType == PORTT_LINKED) return false; // linked portals cannot be changed. + port->mDestination = FindDestination(line, destid); + if (port->mType == PORTT_INTERACTIVE) + { + FLinePortal *portd = &linePortals[port->mDestination->portalindex]; + if (portd != NULL && portd->mType == PORTT_INTERACTIVE && portd->mDestination == line) + { + // this is a 2-way interactive portal + port->mFlags = port->mDefFlags | PORTF_INTERACTIVE; + portd->mFlags = portd->mDefFlags | PORTF_INTERACTIVE; + } + else + { + port->mFlags = port->mDefFlags; + portd->mFlags = portd->mDefFlags; + } + } + return true; +} + + +bool P_ChangePortal(line_t *ln, int thisid, int destid) +{ + int lineno; + + if (thisid == 0) return ChangePortalLine(ln, destid); + FLineIdIterator it(thisid); + bool res = false; + while ((lineno = it.Next()) >= 0) + { + res |= ChangePortalLine(&lines[lineno], destid); + } + return res; +} + // [ZZ] lots of floats here to avoid overflowing a lot bool P_IntersectLines(fixed_t o1x, fixed_t o1y, fixed_t p1x, fixed_t p1y, fixed_t o2x, fixed_t o2y, fixed_t p2x, fixed_t p2y, diff --git a/src/portal.h b/src/portal.h index 6a947fd0e..53fb1c16e 100644 --- a/src/portal.h +++ b/src/portal.h @@ -52,6 +52,7 @@ extern TArray linePortals; void P_SpawnLinePortal(line_t* line); void P_FinalizePortals(); +bool P_ChangePortal(line_t *ln, int thisid, int destid); /* code ported from prototype */