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 "game.h"
30 #include "tags.h"
31 #include "weapon.h"
32 #include "sprite.h"
33 #include "track.h"
34 
CopySectorWalls(short dest_sectnum,short src_sectnum)35 void CopySectorWalls(short dest_sectnum, short src_sectnum)
36     {
37     short dest_wall_num, src_wall_num, start_wall;
38 
39     dest_wall_num = sector[dest_sectnum].wallptr;
40     src_wall_num = sector[src_sectnum].wallptr;
41 
42     start_wall = dest_wall_num;
43 
44     do
45         {
46         wall[dest_wall_num].picnum = wall[src_wall_num].picnum;
47 
48         wall[dest_wall_num].xrepeat =       wall[src_wall_num].xrepeat;
49         wall[dest_wall_num].yrepeat =       wall[src_wall_num].yrepeat;
50         wall[dest_wall_num].overpicnum =    wall[src_wall_num].overpicnum;
51         wall[dest_wall_num].pal =           wall[src_wall_num].pal;
52         wall[dest_wall_num].cstat =         wall[src_wall_num].cstat;
53         wall[dest_wall_num].shade =         wall[src_wall_num].shade;
54         wall[dest_wall_num].xpanning =      wall[src_wall_num].xpanning;
55         wall[dest_wall_num].ypanning =      wall[src_wall_num].ypanning;
56         wall[dest_wall_num].hitag =         wall[src_wall_num].hitag;
57         wall[dest_wall_num].lotag =         wall[src_wall_num].lotag;
58         wall[dest_wall_num].extra =         wall[src_wall_num].extra;
59 
60         if (wall[dest_wall_num].nextwall >= 0 && wall[src_wall_num].nextwall >= 0)
61             {
62             wall[wall[dest_wall_num].nextwall].picnum = wall[wall[src_wall_num].nextwall].picnum;
63             wall[wall[dest_wall_num].nextwall].xrepeat = wall[wall[src_wall_num].nextwall].xrepeat;
64             wall[wall[dest_wall_num].nextwall].yrepeat = wall[wall[src_wall_num].nextwall].yrepeat;
65             wall[wall[dest_wall_num].nextwall].overpicnum = wall[wall[src_wall_num].nextwall].overpicnum;
66             wall[wall[dest_wall_num].nextwall].pal = wall[wall[src_wall_num].nextwall].pal;
67             wall[wall[dest_wall_num].nextwall].cstat = wall[wall[src_wall_num].nextwall].cstat;
68             wall[wall[dest_wall_num].nextwall].shade = wall[wall[src_wall_num].nextwall].shade;
69             wall[wall[dest_wall_num].nextwall].xpanning = wall[wall[src_wall_num].nextwall].xpanning;
70             wall[wall[dest_wall_num].nextwall].ypanning = wall[wall[src_wall_num].nextwall].ypanning;
71             wall[wall[dest_wall_num].nextwall].hitag = wall[wall[src_wall_num].nextwall].hitag;
72             wall[wall[dest_wall_num].nextwall].lotag = wall[wall[src_wall_num].nextwall].lotag;
73             wall[wall[dest_wall_num].nextwall].extra = wall[wall[src_wall_num].nextwall].extra;
74             }
75 
76         dest_wall_num = wall[dest_wall_num].point2;
77         src_wall_num = wall[src_wall_num].point2;
78         }
79     while(dest_wall_num != start_wall);
80     }
81 
CopySectorMatch(short match)82 void CopySectorMatch(short match)
83     {
84     short ed,nexted,ss,nextss;
85     SPRITEp dest_sp, src_sp;
86     SECTORp dsectp,ssectp;
87     short kill, nextkill;
88     SPRITEp k;
89 
90     TRAVERSE_SPRITE_STAT(headspritestat[STAT_COPY_DEST], ed, nexted)
91         {
92         dest_sp = &sprite[ed];
93         dsectp = &sector[dest_sp->sectnum];
94 
95         if (match != sprite[ed].lotag)
96             continue;
97 
98         TRAVERSE_SPRITE_STAT(headspritestat[STAT_COPY_SOURCE], ss, nextss)
99             {
100             src_sp = &sprite[ss];
101 
102             if (SP_TAG2(src_sp) == SPRITE_TAG2(ed) &&
103                 SP_TAG3(src_sp) == SPRITE_TAG3(ed))
104                 {
105                 short src_move, nextsrc_move;
106                 ssectp = &sector[src_sp->sectnum];
107 
108                 // !!!!!AAAAAAAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHHHHHHH
109                 // Don't kill anything you don't have to
110                 // this wall killing things on a Queue causing
111                 // invalid situations
112 
113                 #if 1
114                 // kill all sprites in the dest sector that need to be
115                 TRAVERSE_SPRITE_SECT(headspritesect[dest_sp->sectnum], kill, nextkill)
116                     {
117                     k = &sprite[kill];
118 
119                     // kill anything not invisible
120                     if (!TEST(k->cstat, CSTAT_SPRITE_INVISIBLE))
121                         {
122                         if (User[kill])
123                             {
124                             // be safe with the killing
125                             //SetSuicide(kill);
126                             }
127                         else
128                             {
129                             SpriteQueueDelete(kill); // new function to allow killing - hopefully
130                             KillSprite(kill);
131                             }
132                         }
133                     }
134                 #endif
135 
136                 CopySectorWalls(dest_sp->sectnum, src_sp->sectnum);
137 
138                 TRAVERSE_SPRITE_SECT(headspritesect[src_sp->sectnum], src_move, nextsrc_move)
139                     {
140                     // don't move ST1 Copy Tags
141                     if (SPRITE_TAG1(src_move) != SECT_COPY_SOURCE)
142                         {
143                         int sx,sy,dx,dy,src_xoff,src_yoff,trash;
144 
145                         // move sprites from source to dest - use center offset
146 
147                         // get center of src and dest sect
148                         SectorMidPoint(src_sp->sectnum, &sx, &sy, &trash);
149                         SectorMidPoint(dest_sp->sectnum, &dx, &dy, &trash);
150 
151                         // get offset
152                         src_xoff = sx - sprite[src_move].x;
153                         src_yoff = sy - sprite[src_move].y;
154 
155                         // move sprite to dest sector
156                         sprite[src_move].x = dx - src_xoff;
157                         sprite[src_move].y = dy - src_yoff;
158 
159                         // change sector
160                         changespritesect(src_move, dest_sp->sectnum);
161 
162                         // check to see if it moved on to a sector object
163                         if (TEST(sector[dest_sp->sectnum].extra, SECTFX_SECTOR_OBJECT))
164                             {
165                             SECTOR_OBJECTp sop;
166                             extern short GlobSpeedSO;
167 
168                             // find and add sprite to SO
169                             sop = DetectSectorObject(&sector[sprite[src_move].sectnum]);
170                             AddSpriteToSectorObject(src_move, sop);
171 
172                             // update sprites postions so they aren't in the
173                             // wrong place for one frame
174                             GlobSpeedSO = 0;
175                             RefreshPoints(sop, 0, 0, TRUE);
176                             }
177                         }
178                     }
179 
180                 // copy sector user if there is one
181                 if (SectUser[src_sp->sectnum] || SectUser[dest_sp->sectnum])
182                     {
183                     SECT_USERp ssectu = GetSectUser(src_sp->sectnum);
184                     SECT_USERp dsectu = GetSectUser(dest_sp->sectnum);
185 
186                     memcpy(dsectu, ssectu, sizeof(SECT_USER));
187                     }
188 
189                 dsectp->hitag = ssectp->hitag;
190                 dsectp->lotag = ssectp->lotag;
191 
192                 dsectp->floorz = ssectp->floorz;
193                 dsectp->ceilingz = ssectp->ceilingz;
194 
195                 dsectp->floorshade = ssectp->floorshade;
196                 dsectp->ceilingshade = ssectp->ceilingshade;
197 
198                 dsectp->floorpicnum = ssectp->floorpicnum;
199                 dsectp->ceilingpicnum = ssectp->ceilingpicnum;
200 
201                 dsectp->floorheinum = ssectp->floorheinum;
202                 dsectp->ceilingheinum = ssectp->ceilingheinum;
203 
204                 dsectp->floorpal = ssectp->floorpal;
205                 dsectp->ceilingpal = ssectp->ceilingpal;
206 
207                 dsectp->floorxpanning = ssectp->floorxpanning;
208                 dsectp->ceilingxpanning = ssectp->ceilingxpanning;
209 
210                 dsectp->floorypanning = ssectp->floorypanning;
211                 dsectp->ceilingypanning = ssectp->ceilingypanning;
212 
213                 dsectp->floorstat = ssectp->floorstat;
214                 dsectp->ceilingstat = ssectp->ceilingstat;
215 
216                 dsectp->extra = ssectp->extra;
217                 dsectp->visibility = ssectp->visibility;
218                 }
219             }
220         }
221 
222     // do this outside of processing loop for safety
223 
224     // kill all matching dest
225     TRAVERSE_SPRITE_STAT(headspritestat[STAT_COPY_DEST], ed, nexted)
226         {
227         if (match == sprite[ed].lotag)
228             KillSprite(ed);
229         }
230 
231     // kill all matching sources
232     TRAVERSE_SPRITE_STAT(headspritestat[STAT_COPY_SOURCE], ss, nextss)
233         {
234         if (match == sprite[ss].lotag)
235             KillSprite(ss);
236         }
237 
238     }
239