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