1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: r_things.cpp 4469 2014-01-03 23:38:29Z dr_sean $
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 // Copyright (C) 2006-2014 by The Odamex Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // DESCRIPTION:
20 // Refresh of things, i.e. objects represented by sprites.
21 //
22 //-----------------------------------------------------------------------------
23
24
25 #include <stdio.h>
26 #include <stdlib.h>
27
28 #include "m_alloc.h"
29
30 #include "doomdef.h"
31 #include "m_swap.h"
32 #include "m_argv.h"
33
34 #include "i_system.h"
35 #include "z_zone.h"
36 #include "w_wad.h"
37
38 #include "r_local.h"
39
40 #include "c_console.h"
41 #include "c_cvars.h"
42 #include "c_dispatch.h"
43
44 #include "doomstat.h"
45
46 #include "v_video.h"
47
48 #include "cmdlib.h"
49 #include "s_sound.h"
50
51 extern fixed_t FocalLengthX, FocalLengthY;
52
53
54 #define MINZ (FRACUNIT*4)
55 #define BASEYCENTER (100)
56
57 #define MAX_SPRITE_FRAMES 29 // [RH] Macro-ized as in BOOM.
58 #define SPRITE_NEEDS_INFO MAXINT
59
60 //
61 // INITIALIZATION FUNCTIONS
62 //
63
64 // variables used to look up
65 // and range check thing_t sprites patches
66 spritedef_t* sprites;
67 int numsprites;
68
69 spriteframe_t sprtemp[MAX_SPRITE_FRAMES];
70 int maxframe;
71 static const char* spritename;
72
R_CacheSprite(spritedef_t * sprite)73 void R_CacheSprite (spritedef_t *sprite)
74 {
75 int i, r;
76 patch_t *patch;
77
78 DPrintf ("cache sprite %s\n",
79 sprite - sprites < NUMSPRITES ? sprnames[sprite - sprites] : "");
80 for (i = 0; i < sprite->numframes; i++)
81 {
82 for (r = 0; r < 8; r++)
83 {
84 if (sprite->spriteframes[i].width[r] == SPRITE_NEEDS_INFO)
85 {
86 if (sprite->spriteframes[i].lump[r] == -1)
87 I_Error ("Sprite %d, rotation %d has no lump", i, r);
88 patch = W_CachePatch (sprite->spriteframes[i].lump[r]);
89 sprite->spriteframes[i].width[r] = patch->width()<<FRACBITS;
90 sprite->spriteframes[i].offset[r] = patch->leftoffset()<<FRACBITS;
91 sprite->spriteframes[i].topoffset[r] = patch->topoffset()<<FRACBITS;
92 }
93 }
94 }
95 }
96
97 //
98 // R_InstallSpriteLump
99 // Local function for R_InitSprites.
100 //
101 // [RH] Removed checks for coexistance of rotation 0 with other
102 // rotations and made it look more like BOOM's version.
103 //
R_InstallSpriteLump(int lump,unsigned frame,unsigned rotation,BOOL flipped)104 static void R_InstallSpriteLump (int lump, unsigned frame, unsigned rotation, BOOL flipped)
105 {
106 if (frame >= MAX_SPRITE_FRAMES || rotation > 8)
107 I_FatalError ("R_InstallSpriteLump: Bad frame characters in lump %i", lump);
108
109 if ((int)frame > maxframe)
110 maxframe = frame;
111
112 if (rotation == 0)
113 {
114 // the lump should be used for all rotations
115 // false=0, true=1, but array initialised to -1
116 // allows doom to have a "no value set yet" boolean value!
117 int r;
118
119 for (r = 7; r >= 0; r--)
120 if (sprtemp[frame].lump[r] == -1)
121 {
122 sprtemp[frame].lump[r] = (short)(lump);
123 sprtemp[frame].flip[r] = (byte)flipped;
124 sprtemp[frame].rotate = false;
125 sprtemp[frame].width[r] = SPRITE_NEEDS_INFO;
126 }
127 }
128 else if (sprtemp[frame].lump[--rotation] == -1)
129 {
130 // the lump is only used for one rotation
131 sprtemp[frame].lump[rotation] = (short)(lump);
132 sprtemp[frame].flip[rotation] = (byte)flipped;
133 sprtemp[frame].rotate = true;
134 sprtemp[frame].width[rotation] = SPRITE_NEEDS_INFO;
135 }
136 }
137
138
139 // [RH] Seperated out of R_InitSpriteDefs()
R_InstallSprite(const char * name,int num)140 static void R_InstallSprite (const char *name, int num)
141 {
142 char sprname[5];
143 int frame;
144
145 if (maxframe == -1)
146 {
147 sprites[num].numframes = 0;
148 return;
149 }
150
151 strncpy (sprname, name, 4);
152 sprname[4] = 0;
153
154 maxframe++;
155
156 for (frame = 0 ; frame < maxframe ; frame++)
157 {
158 switch ((int)sprtemp[frame].rotate)
159 {
160 case -1:
161 // no rotations were found for that frame at all
162 I_FatalError ("R_InstallSprite: No patches found for %s frame %c", sprname, frame+'A');
163 break;
164
165 case 0:
166 // only the first rotation is needed
167 break;
168
169 case 1:
170 // must have all 8 frames
171 {
172 int rotation;
173
174 for (rotation = 0; rotation < 8; rotation++)
175 if (sprtemp[frame].lump[rotation] == -1)
176 I_FatalError ("R_InstallSprite: Sprite %s frame %c is missing rotations",
177 sprname, frame+'A');
178 }
179 break;
180 }
181 }
182
183 // allocate space for the frames present and copy sprtemp to it
184 sprites[num].numframes = maxframe;
185 sprites[num].spriteframes = (spriteframe_t *)
186 Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL);
187 memcpy (sprites[num].spriteframes, sprtemp, maxframe * sizeof(spriteframe_t));
188 }
189
190
191 //
192 // R_InitSpriteDefs
193 // Pass a null terminated list of sprite names
194 // (4 chars exactly) to be used.
195 // Builds the sprite rotation matrices to account
196 // for horizontally flipped sprites.
197 // Will report an error if the lumps are inconsistant.
198 // Only called at startup.
199 //
200 // Sprite lump names are 4 characters for the actor,
201 // a letter for the frame, and a number for the rotation.
202 // A sprite that is flippable will have an additional
203 // letter/number appended.
204 // The rotation character can be 0 to signify no rotations.
205 //
R_InitSpriteDefs(const char ** namelist)206 void R_InitSpriteDefs (const char **namelist)
207 {
208 // count the number of sprite names
209 for (numsprites = 0; namelist[numsprites]; numsprites++)
210 ;
211
212 if (!numsprites)
213 return;
214
215 sprites = (spritedef_t *)Z_Malloc(numsprites * sizeof(*sprites), PU_STATIC, NULL);
216
217 // scan all the lump names for each of the names,
218 // noting the highest frame letter.
219 // Just compare 4 characters as ints
220 for (int i = 0; i < numsprites; i++)
221 {
222 spritename = namelist[i];
223 memset (sprtemp, -1, sizeof(sprtemp));
224
225 maxframe = -1;
226 int intname = *(int *)namelist[i];
227
228 // scan the lumps,
229 // filling in the frames for whatever is found
230 for (int l = lastspritelump; l >= firstspritelump; l--)
231 {
232 if (*(int *)lumpinfo[l].name == intname)
233 {
234 R_InstallSpriteLump (l,
235 lumpinfo[l].name[4] - 'A', // denis - fixme - security
236 lumpinfo[l].name[5] - '0',
237 false);
238
239 if (lumpinfo[l].name[6])
240 R_InstallSpriteLump (l,
241 lumpinfo[l].name[6] - 'A',
242 lumpinfo[l].name[7] - '0',
243 true);
244 }
245 }
246
247 R_InstallSprite (namelist[i], i);
248 }
249 }
250
251 //
252 // GAME FUNCTIONS
253 //
254 int MaxVisSprites;
255 vissprite_t *vissprites;
256 vissprite_t *vissprite_p;
257 vissprite_t *lastvissprite;
258 int newvissprite;
259
260
261
262 //
263 // R_InitSprites
264 // Called at program start.
265 //
R_InitSprites(const char ** namelist)266 void R_InitSprites (const char **namelist)
267 {
268 MaxVisSprites = 128; // [RH] This is the initial default value. It grows as needed.
269
270 M_Free(vissprites);
271
272 vissprites = (vissprite_t *)Malloc (MaxVisSprites * sizeof(vissprite_t));
273 lastvissprite = &vissprites[MaxVisSprites];
274
275 R_InitSpriteDefs (namelist);
276 }
277
278 VERSION_CONTROL (r_things_cpp, "$Id: r_things.cpp 4469 2014-01-03 23:38:29Z dr_sean $")
279
280