//------------------------------------------------------------------------- /* Copyright (C) 1997, 2005 - 3D Realms Entertainment This file is part of Shadow Warrior version 1.2 Shadow Warrior is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Original Source: 1997 - Frank Maddin and Jim Norwood Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms */ //------------------------------------------------------------------------- #include "ns.h" #include "build.h" #include "names2.h" #include "panel.h" #include "misc.h" BEGIN_SW_NS //////////////////////////////////////////////////////////////////////////////// // // WARPING - PLANE STYLE // //////////////////////////////////////////////////////////////////////////////// extern bool Prediction; DSWActor* WarpToArea(DSWActor* sp_from, int32_t* x, int32_t* y, int32_t* z, sectortype** sect); bool WarpPlaneSectorInfo(sectortype* sect, DSWActor** sp_ceiling, DSWActor** sp_floor) { *sp_floor = nullptr; *sp_ceiling = nullptr; if (Prediction) return false; if (sect== nullptr || !TEST(sect->extra, SECTFX_WARP_SECTOR)) return false; SWStatIterator it(STAT_WARP); while (auto actor = it.Next()) { auto sp = &actor->s(); if (sp->sector() == sect) { // skip - don't teleport if (SP_TAG10(sp) == 1) continue; if (sp->hitag == WARP_CEILING_PLANE) { *sp_ceiling = actor; } else if (sp->hitag == WARP_FLOOR_PLANE) { *sp_floor = actor; } } } return true; } DSWActor* WarpPlane(int32_t* x, int32_t* y, int32_t* z, sectortype** sect) { DSWActor* sp_floor,* sp_ceiling; if (Prediction) return nullptr; if (!WarpPlaneSectorInfo(*sect, &sp_ceiling, &sp_floor)) return nullptr; if (sp_ceiling) { if (*z <= sp_ceiling->spr.pos.Z) { return WarpToArea(sp_ceiling, x, y, z, sect); } } if (sp_floor) { if (*z >= sp_floor->spr.pos.Z) { return WarpToArea(sp_floor, x, y, z, sect); } } return nullptr; } DSWActor* WarpToArea(DSWActor* sp_from, int32_t* x, int32_t* y, int32_t* z, sectortype** sect) { int xoff; int yoff; int zoff; SPRITEp const sp = &sp_from->s(); short match; short to_tag = 0; short match_rand[16]; int z_adj = 0; xoff = *x - sp->pos.X; yoff = *y - sp->pos.Y; zoff = *z - sp->pos.Z; match = sp->lotag; #if 0 TAG 2 = match TAG 3 = Type Sprite - 0,32 always teleports you to the center at the angle the sprite is facing Offset - 1 always teleports you by the offset.Does not touch the angle TAG 4 = angle TAG 5 to 8 = random match locations #endif memset(match_rand,0,sizeof(match_rand)); switch (sp->hitag) { case WARP_TELEPORTER: to_tag = WARP_TELEPORTER; // if tag 5 has something this is a random teleporter if (SP_TAG5(sp)) { short ndx = 0; match_rand[ndx++] = SP_TAG2(sp); match_rand[ndx++] = SP_TAG5(sp); if (SP_TAG6(sp)) match_rand[ndx++] = SP_TAG6(sp); if (SP_TAG7(sp)) match_rand[ndx++] = SP_TAG7(sp); if (SP_TAG8(sp)) match_rand[ndx++] = SP_TAG8(sp); // reset the match you are looking for match = match_rand[RandomRange(ndx)]; } break; case WARP_CEILING_PLANE: to_tag = WARP_FLOOR_PLANE; // make sure you warp outside of warp plane z_adj = -Z(2); break; case WARP_FLOOR_PLANE: to_tag = WARP_CEILING_PLANE; // make sure you warp outside of warp plane z_adj = Z(2); break; } SWStatIterator it(STAT_WARP); while (auto actor = it.Next()) { auto spi = &actor->s(); if (spi->lotag == match && actor != sp_from) { // exp: WARP_CEILING or WARP_CEILING_PLANE if (spi->hitag == to_tag) { if (!spi->insector()) return nullptr; // determine new x,y,z position *x = spi->pos.X + xoff; *y = spi->pos.Y + yoff; *z = spi->pos.Z + zoff; // make sure you warp outside of warp plane *z += z_adj; // get new sector *sect = spi->sector(); updatesector(*x, *y, sect); return actor; } } } return nullptr; } //////////////////////////////////////////////////////////////////////////////// // // Warp - Teleporter style // //////////////////////////////////////////////////////////////////////////////// bool WarpSectorInfo(sectortype* sect, DSWActor** sp_warp) { *sp_warp = nullptr; if (!sect || !TEST(sect->extra, SECTFX_WARP_SECTOR)) return false; SWStatIterator it(STAT_WARP); while (auto actor = it.Next()) { auto sp = &actor->s(); if (sp->sector() == sect) { // skip - don't teleport if (SP_TAG10(sp) == 1) continue; if (sp->hitag == WARP_TELEPORTER) { *sp_warp = actor; } } } return true; } DSWActor* Warp(int32_t* x, int32_t* y, int32_t* z, sectortype** sect) { DSWActor* sp_warp; if (Prediction) return nullptr; if (!WarpSectorInfo(*sect, &sp_warp)) return nullptr; if (sp_warp) { return WarpToArea(sp_warp, x, y, z, sect); } return nullptr; } END_SW_NS