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 "keys.h"
29 #include "names2.h"
30 //#include "panel.h"
31 #include "game.h"
32 #include "tags.h"
33 #include "mathutil.h"
34 #include "weapon.h"
35 #include "sprite.h"
36
37 //#include "ai.h"
38
39 SECTOR_OBJECTp DetectSectorObjectByWall(WALLp);
40
SOwallmove(SECTOR_OBJECTp sop,SPRITEp sp,WALLp find_wallp,int dist,int * nx,int * ny)41 void SOwallmove(SECTOR_OBJECTp sop, SPRITEp sp, WALLp find_wallp, int dist, int *nx, int *ny)
42 {
43 int j,k,wallcount;
44 WALLp wp;
45 short startwall,endwall;
46 SECTORp *sectp;
47
48 if (TEST(sop->flags, SOBJ_SPRITE_OBJ))
49 return;
50
51 wallcount = 0;
52 for (sectp = sop->sectp, j = 0; *sectp; sectp++, j++)
53 {
54 startwall = (*sectp)->wallptr;
55 endwall = startwall + (*sectp)->wallnum - 1;
56
57 // move all walls in sectors back to the original position
58 for (wp = &wall[startwall], k = startwall; k <= endwall; wp++, k++)
59 {
60 // find the one wall we want to adjust
61 if (wp == find_wallp)
62 {
63 short ang;
64 // move orig x and y in saved angle
65 ASSERT(User[sp - sprite]);
66 ang = User[sp - sprite]->sang;
67
68 *nx = ((dist * sintable[NORM_ANGLE(ang + 512)])>>14);
69 *ny = ((dist * sintable[ang])>>14);
70
71 sop->xorig[wallcount] -= *nx;
72 sop->yorig[wallcount] -= *ny;
73
74 SET(sop->flags, SOBJ_UPDATE_ONCE);
75 return;
76 }
77
78 wallcount++;
79 }
80 }
81 }
82
DoWallMove(SPRITEp sp)83 int DoWallMove(SPRITEp sp)
84 {
85 int dist,nx,ny;
86 short shade1,shade2,ang,picnum1,picnum2;
87 WALLp wallp;
88 short prev_wall;
89 BOOL found = FALSE;
90 short dang;
91 BOOL SOsprite = FALSE;
92
93 dist = SP_TAG13(sp);
94 ang = SP_TAG4(sp);
95 picnum1 = SP_TAG5(sp);
96 picnum2 = SP_TAG6(sp);
97 shade1 = SP_TAG7(sp);
98 shade2 = SP_TAG8(sp);
99 dang = ((int)SP_TAG10(sp)) << 3;
100
101 if (dang)
102 ang = NORM_ANGLE(ang + (RANDOM_RANGE(dang) - dang/2));
103
104 nx = (dist * sintable[NORM_ANGLE(ang + 512)])>>14;
105 ny = (dist * sintable[ang])>>14;
106
107 for (wallp = wall; wallp < &wall[numwalls]; wallp++)
108 {
109 if (wallp->x == sp->x && wallp->y == sp->y)
110 {
111 found = TRUE;
112
113 if (TEST(wallp->extra, WALLFX_SECTOR_OBJECT))
114 {
115 SECTOR_OBJECTp sop;
116 sop = DetectSectorObjectByWall(wallp);
117 ASSERT(sop);
118 SOwallmove(sop, sp, wallp, dist, &nx, &ny);
119
120 SOsprite = TRUE;
121 }
122 else
123 {
124 wallp->x = sp->x + nx;
125 wallp->y = sp->y + ny;
126 }
127
128 if (shade1)
129 wallp->shade = shade1;
130 if (picnum1)
131 wallp->picnum = picnum1;
132
133 // find the previous wall
134 prev_wall = PrevWall(wallp - wall);
135 if (shade2)
136 wall[prev_wall].shade = shade2;
137 if (picnum2)
138 wall[prev_wall].picnum = picnum2;
139 }
140 }
141
142 SP_TAG9(sp)--;
143 if ((signed char)SP_TAG9(sp) <= 0)
144 {
145 KillSprite(sp - sprite);
146 }
147 else
148 {
149 if (SOsprite)
150 {
151 // move the sprite offset from center
152 User[sp - sprite]->sx -= nx;
153 User[sp - sprite]->sy -= ny;
154 }
155 else
156 {
157 sp->x += nx;
158 sp->y += ny;
159 }
160 }
161
162 return(found);
163 }
164
CanSeeWallMove(SPRITEp wp,short match)165 BOOL CanSeeWallMove(SPRITEp wp, short match)
166 {
167 short i,nexti;
168 BOOL found = FALSE;
169 SPRITEp sp;
170
171 TRAVERSE_SPRITE_STAT(headspritestat[STAT_WALL_MOVE_CANSEE], i, nexti)
172 {
173 sp = &sprite[i];
174
175 if (SP_TAG2(sp) == match)
176 {
177 found = TRUE;
178
179 if (cansee(wp->x,wp->y,wp->z,wp->sectnum,sp->x,sp->y,sp->z,sp->sectnum))
180 {
181 return(TRUE);
182 }
183 }
184 }
185
186 if (found)
187 return(FALSE);
188 else
189 return(TRUE);
190 }
191
DoWallMoveMatch(short match)192 int DoWallMoveMatch(short match)
193 {
194 SPRITEp sp;
195 short i,nexti;
196 BOOL found = FALSE;
197
198 // just all with the same matching tags
199 TRAVERSE_SPRITE_STAT(headspritestat[STAT_WALL_MOVE], i, nexti)
200 {
201 sp = &sprite[i];
202
203 if (SP_TAG2(sp) == match)
204 {
205 found = TRUE;
206 DoWallMove(sp);
207 }
208 }
209
210 return(found);
211 }
212
213
214 #include "saveable.h"
215
216 static saveable_code saveable_wallmove_code[] = {
217 SAVE_CODE(DoWallMove),
218 SAVE_CODE(CanSeeWallMove),
219 SAVE_CODE(DoWallMoveMatch),
220 };
221
222 saveable_module saveable_wallmove = {
223 // code
224 saveable_wallmove_code,
225 SIZ(saveable_wallmove_code),
226
227 // data
228 NULL,0
229 };
230