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