//------------------------------------------------------------------------- /* 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; bool WarpPlaneSectorInfo(short sectnum, SPRITEp *sp_ceiling, SPRITEp *sp_floor) { int i; SPRITEp sp; *sp_floor = nullptr; *sp_ceiling = nullptr; if (Prediction) return false; if (sectnum < 0 || !TEST(sector[sectnum].extra, SECTFX_WARP_SECTOR)) return false; StatIterator it(STAT_WARP); while ((i = it.NextIndex()) >= 0) { sp = &sprite[i]; if (sp->sectnum == sectnum) { // skip - don't teleport if (SP_TAG10(sp) == 1) continue; if (sp->hitag == WARP_CEILING_PLANE) { *sp_ceiling = sp; } else if (sp->hitag == WARP_FLOOR_PLANE) { *sp_floor = sp; } } } return true; } SPRITEp WarpPlane(int32_t* x, int32_t* y, int32_t* z, int16_t* sectnum) { SPRITEp sp_floor, sp_ceiling; if (Prediction) return nullptr; if (!WarpPlaneSectorInfo(*sectnum, &sp_ceiling, &sp_floor)) return nullptr; if (sp_ceiling) { if (*z <= sp_ceiling->z) { return WarpToArea(sp_ceiling, x, y, z, sectnum); } } if (sp_floor) { if (*z >= sp_floor->z) { return WarpToArea(sp_floor, x, y, z, sectnum); } } return nullptr; } SPRITEp WarpToArea(SPRITEp sp_from, int32_t* x, int32_t* y, int32_t* z, int16_t* sectnum) { int xoff; int yoff; int zoff; int i; SPRITEp sp = sp_from; short match; short to_tag = 0; short match_rand[16]; int z_adj = 0; xoff = *x - sp->x; yoff = *y - sp->y; zoff = *z - sp->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[RANDOM_RANGE(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; } StatIterator it(STAT_WARP); while ((i = it.NextIndex()) >= 0) { SPRITEp sp = &sprite[i]; if (sp->lotag == match && sp != sp_from) { // exp: WARP_CEILING or WARP_CEILING_PLANE if (sp->hitag == to_tag) { if ((unsigned)sp->sectnum >= MAXSECTORS) return nullptr; // determine new x,y,z position *x = sp->x + xoff; *y = sp->y + yoff; *z = sp->z + zoff; // make sure you warp outside of warp plane *z += z_adj; // get new sector *sectnum = sp->sectnum; updatesector(*x, *y, sectnum); return sp; } } } return nullptr; } //////////////////////////////////////////////////////////////////////////////// // // Warp - Teleporter style // //////////////////////////////////////////////////////////////////////////////// bool WarpSectorInfo(short sectnum, SPRITEp *sp_warp) { int i; SPRITEp sp; *sp_warp = nullptr; if (!TEST(sector[sectnum].extra, SECTFX_WARP_SECTOR)) return false; StatIterator it(STAT_WARP); while ((i = it.NextIndex()) >= 0) { sp = &sprite[i]; if (sp->sectnum == sectnum) { // skip - don't teleport if (SP_TAG10(sp) == 1) continue; if (sp->hitag == WARP_TELEPORTER) { *sp_warp = sp; } } } return true; } SPRITEp Warp(int32_t* x, int32_t* y, int32_t* z, int16_t* sectnum) { SPRITEp sp_warp; if (Prediction) return nullptr; if (!WarpSectorInfo(*sectnum, &sp_warp)) return nullptr; if (sp_warp) { return WarpToArea(sp_warp, x, y, z, sectnum); } return nullptr; } END_SW_NS