1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 1997, 2005 - 3D Realms Entertainment
4 
5 This file is part of Shadow Warrior version 1.2
6 
7 Shadow Warrior is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 
16 See the GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 
22 Original Source: 1997 - Frank Maddin and Jim Norwood
23 Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
24 */
25 //-------------------------------------------------------------------------
26 #include "build.h"
27 
28 #include "names2.h"
29 #include "panel.h"
30 #include "game.h"
31 
32 #include "warp.h"
33 
34 ////////////////////////////////////////////////////////////////////////////////
35 //
36 // WARPING - PLANE STYLE
37 //
38 ////////////////////////////////////////////////////////////////////////////////
39 
40 extern BOOL Prediction;
41 
42 BOOL
WarpPlaneSectorInfo(short sectnum,SPRITEp * sp_ceiling,SPRITEp * sp_floor)43 WarpPlaneSectorInfo(short sectnum, SPRITEp *sp_ceiling, SPRITEp *sp_floor)
44     {
45     int i,nexti;
46     SPRITEp sp;
47 
48     *sp_floor = NULL;
49     *sp_ceiling = NULL;
50 
51     if (Prediction)
52         return(FALSE);
53 
54     if (!TEST(sector[sectnum].extra, SECTFX_WARP_SECTOR))
55         return(FALSE);
56 
57     TRAVERSE_SPRITE_STAT(headspritestat[STAT_WARP], i, nexti)
58         {
59         sp = &sprite[i];
60 
61         if (sp->sectnum == sectnum)
62             {
63             // skip - don't teleport
64             if (SP_TAG10(sp) == 1)
65                 continue;
66 
67             if (sp->hitag == WARP_CEILING_PLANE)
68                 {
69                 *sp_ceiling = sp;
70                 }
71             else
72             if (sp->hitag == WARP_FLOOR_PLANE)
73                 {
74                 *sp_floor = sp;
75                 }
76             }
77         }
78 
79     return(TRUE);
80     }
81 
82 SPRITEp
WarpPlane(LONGp x,LONGp y,LONGp z,SHORTp sectnum)83 WarpPlane(LONGp x, LONGp y, LONGp z, SHORTp sectnum)
84     {
85     SPRITEp sp_floor, sp_ceiling;
86 
87     if (Prediction)
88         return(NULL);
89 
90     if (!WarpPlaneSectorInfo(*sectnum, &sp_ceiling, &sp_floor))
91         return(NULL);
92 
93     if (sp_ceiling)
94         {
95         if (*z <= sp_ceiling->z)
96             {
97             return(WarpToArea(sp_ceiling, x, y, z, sectnum));
98             }
99         }
100 
101     if (sp_floor)
102         {
103         if (*z >= sp_floor->z)
104             {
105             return(WarpToArea(sp_floor, x, y, z, sectnum));
106             }
107         }
108 
109     return(NULL);
110     }
111 
112 SPRITEp
WarpToArea(SPRITEp sp_from,LONGp x,LONGp y,LONGp z,SHORTp sectnum)113 WarpToArea(SPRITEp sp_from, LONGp x, LONGp y, LONGp z, SHORTp sectnum)
114     {
115     int xoff;
116     int yoff;
117     int zoff;
118     short i, nexti;
119     SPRITEp sp = sp_from;
120     short match;
121     short to_tag = 0;
122     short match_rand[16];
123     int z_adj = 0;
124 
125     xoff = *x - sp->x;
126     yoff = *y - sp->y;
127     zoff = *z - sp->z;
128     match = sp->lotag;
129 
130 #if 0
131 TAG 2 = match
132 TAG 3 = Type
133     Sprite - 0,32 always teleports you to the center at the angle the sprite is facing
134     Offset - 1 always teleports you by the offset.  Does not touch the angle
135 TAG 4 = angle
136 TAG 5 to 8 = random match locations
137 #endif
138 
139     memset(match_rand,0,sizeof(match_rand));
140 
141     switch (sp->hitag)
142         {
143         case WARP_TELEPORTER:
144             to_tag = WARP_TELEPORTER;
145 
146             // if tag 5 has something this is a random teleporter
147             if (SP_TAG5(sp))
148                 {
149                 short ndx = 0;
150                 match_rand[ndx++] = SP_TAG2(sp);
151                 match_rand[ndx++] = SP_TAG5(sp);
152                 if (SP_TAG6(sp))
153                     match_rand[ndx++] = SP_TAG6(sp);
154                 if (SP_TAG7(sp))
155                     match_rand[ndx++] = SP_TAG7(sp);
156                 if (SP_TAG8(sp))
157                     match_rand[ndx++] = SP_TAG8(sp);
158 
159                 // reset the match you are looking for
160                 match = match_rand[RANDOM_RANGE(ndx)];
161                 }
162             break;
163         case WARP_CEILING_PLANE:
164             to_tag = WARP_FLOOR_PLANE;
165             // make sure you warp outside of warp plane
166             z_adj = -Z(2);
167             break;
168         case WARP_FLOOR_PLANE:
169             to_tag = WARP_CEILING_PLANE;
170             // make sure you warp outside of warp plane
171             z_adj = Z(2);
172             break;
173         }
174 
175     TRAVERSE_SPRITE_STAT(headspritestat[STAT_WARP], i, nexti)
176         {
177         SPRITEp sp = &sprite[i];
178 
179         if (sp->lotag == match && sp != sp_from)
180             {
181             // exp: WARP_CEILING or WARP_CEILING_PLANE
182             if (sp->hitag == to_tag)
183                 {
184                 // determine new x,y,z position
185                 *x = sp->x + xoff;
186                 *y = sp->y + yoff;
187                 *z = sp->z + zoff;
188 
189                 // make sure you warp outside of warp plane
190                 *z += z_adj;
191 
192                 // get new sector
193                 *sectnum = sp->sectnum;
194                 updatesector(*x, *y, sectnum);
195 
196                 ASSERT(*sectnum >= 0);
197                 return(sp);
198                 }
199             }
200         }
201 
202     return(NULL);
203     }
204 
205 ////////////////////////////////////////////////////////////////////////////////
206 //
207 // Warp - Teleporter style
208 //
209 ////////////////////////////////////////////////////////////////////////////////
210 
211 BOOL
WarpSectorInfo(short sectnum,SPRITEp * sp_warp)212 WarpSectorInfo(short sectnum, SPRITEp *sp_warp)
213     {
214     int i,nexti;
215     SPRITEp sp;
216 
217     *sp_warp = NULL;
218 
219     if (!TEST(sector[sectnum].extra, SECTFX_WARP_SECTOR))
220         return(FALSE);
221 
222     TRAVERSE_SPRITE_STAT(headspritestat[STAT_WARP], i, nexti)
223         {
224         sp = &sprite[i];
225 
226         if (sp->sectnum == sectnum)
227             {
228             // skip - don't teleport
229             if (SP_TAG10(sp) == 1)
230                 continue;
231 
232             if (sp->hitag == WARP_TELEPORTER)
233                 {
234                 *sp_warp = sp;
235                 }
236             }
237         }
238 
239     return(TRUE);
240     }
241 
242 SPRITEp
Warp(LONGp x,LONGp y,LONGp z,SHORTp sectnum)243 Warp(LONGp x, LONGp y, LONGp z, SHORTp sectnum)
244     {
245     SPRITEp sp_warp;
246 
247     if (Prediction)
248         return(NULL);
249 
250     if (!WarpSectorInfo(*sectnum, &sp_warp))
251         return(NULL);
252 
253     if (sp_warp)
254         {
255         return(WarpToArea(sp_warp, x, y, z, sectnum));
256         }
257 
258     return(NULL);
259     }
260