1 /**
2 * @file lighting.cpp
3 *
4 * Implementation of light and vision.
5 */
6 #include "all.h"
7
8 DEVILUTION_BEGIN_NAMESPACE
9
10 LightListStruct VisionList[MAXVISION];
11 BYTE lightactive[MAXLIGHTS];
12 LightListStruct LightList[MAXLIGHTS];
13 int numlights;
14 BYTE lightradius[16][128];
15 BOOL dovision;
16 int numvision;
17 char lightmax;
18 BOOL dolighting;
19 BYTE lightblock[64][16][16];
20 int visionid;
21 BYTE *pLightTbl;
22 BOOL lightflag;
23
24 /**
25 * CrawlTable specifies X- and Y-coordinate deltas from a missile target coordinate.
26 *
27 * n=4
28 *
29 * y
30 * ^
31 * | 1
32 * | 3#4
33 * | 2
34 * +-----> x
35 *
36 * n=16
37 *
38 * y
39 * ^
40 * | 314
41 * | B7 8C
42 * | F # G
43 * | D9 AE
44 * | 526
45 * +-------> x
46 */
47 const char CrawlTable[2749] = {
48 // clang-format off
49 1, // Table 0, offset 0
50 0, 0,
51 4, // Table 1, offset 3
52 0, 1, 0, -1, -1, 0, 1, 0,
53 16, // Table 2, offset 12
54 0, 2, 0, -2, -1, 2, 1, 2,
55 -1, -2, 1, -2, -1, 1, 1, 1,
56 -1, -1, 1, -1, -2, 1, 2, 1,
57 -2, -1, 2, -1, -2, 0, 2, 0,
58 24, // Table 3, offset 45
59 0, 3, 0, -3, -1, 3, 1, 3,
60 -1, -3, 1, -3, -2, 3, 2, 3,
61 -2, -3, 2, -3, -2, 2, 2, 2,
62 -2, -2, 2, -2, -3, 2, 3, 2,
63 -3, -2, 3, -2, -3, 1, 3, 1,
64 -3, -1, 3, -1, -3, 0, 3, 0,
65 32, // Table 4, offset 94
66 0, 4, 0, -4, -1, 4, 1, 4,
67 -1, -4, 1, -4, -2, 4, 2, 4,
68 -2, -4, 2, -4, -3, 4, 3, 4,
69 -3, -4, 3, -4, -3, 3, 3, 3,
70 -3, -3, 3, -3, -4, 3, 4, 3,
71 -4, -3, 4, -3, -4, 2, 4, 2,
72 -4, -2, 4, -2, -4, 1, 4, 1,
73 -4, -1, 4, -1, -4, 0, 4, 0,
74 40, // Table 5, offset 159
75 0, 5, 0, -5, -1, 5, 1, 5,
76 -1, -5, 1, -5, -2, 5, 2, 5,
77 -2, -5, 2, -5, -3, 5, 3, 5,
78 -3, -5, 3, -5, -4, 5, 4, 5,
79 -4, -5, 4, -5, -4, 4, 4, 4,
80 -4, -4, 4, -4, -5, 4, 5, 4,
81 -5, -4, 5, -4, -5, 3, 5, 3,
82 -5, -3, 5, -3, -5, 2, 5, 2,
83 -5, -2, 5, -2, -5, 1, 5, 1,
84 -5, -1, 5, -1, -5, 0, 5, 0,
85 48, // Table 6, offset 240
86 0, 6, 0, -6, -1, 6, 1, 6,
87 -1, -6, 1, -6, -2, 6, 2, 6,
88 -2, -6, 2, -6, -3, 6, 3, 6,
89 -3, -6, 3, -6, -4, 6, 4, 6,
90 -4, -6, 4, -6, -5, 6, 5, 6,
91 -5, -6, 5, -6, -5, 5, 5, 5,
92 -5, -5, 5, -5, -6, 5, 6, 5,
93 -6, -5, 6, -5, -6, 4, 6, 4,
94 -6, -4, 6, -4, -6, 3, 6, 3,
95 -6, -3, 6, -3, -6, 2, 6, 2,
96 -6, -2, 6, -2, -6, 1, 6, 1,
97 -6, -1, 6, -1, -6, 0, 6, 0,
98 56, // Table 7, offset 337
99 0, 7, 0, -7, -1, 7, 1, 7,
100 -1, -7, 1, -7, -2, 7, 2, 7,
101 -2, -7, 2, -7, -3, 7, 3, 7,
102 -3, -7, 3, -7, -4, 7, 4, 7,
103 -4, -7, 4, -7, -5, 7, 5, 7,
104 -5, -7, 5, -7, -6, 7, 6, 7,
105 -6, -7, 6, -7, -6, 6, 6, 6,
106 -6, -6, 6, -6, -7, 6, 7, 6,
107 -7, -6, 7, -6, -7, 5, 7, 5,
108 -7, -5, 7, -5, -7, 4, 7, 4,
109 -7, -4, 7, -4, -7, 3, 7, 3,
110 -7, -3, 7, -3, -7, 2, 7, 2,
111 -7, -2, 7, -2, -7, 1, 7, 1,
112 -7, -1, 7, -1, -7, 0, 7, 0,
113 64, // Table 8, offset 450
114 0, 8, 0, -8, -1, 8, 1, 8,
115 -1, -8, 1, -8, -2, 8, 2, 8,
116 -2, -8, 2, -8, -3, 8, 3, 8,
117 -3, -8, 3, -8, -4, 8, 4, 8,
118 -4, -8, 4, -8, -5, 8, 5, 8,
119 -5, -8, 5, -8, -6, 8, 6, 8,
120 -6, -8, 6, -8, -7, 8, 7, 8,
121 -7, -8, 7, -8, -7, 7, 7, 7,
122 -7, -7, 7, -7, -8, 7, 8, 7,
123 -8, -7, 8, -7, -8, 6, 8, 6,
124 -8, -6, 8, -6, -8, 5, 8, 5,
125 -8, -5, 8, -5, -8, 4, 8, 4,
126 -8, -4, 8, -4, -8, 3, 8, 3,
127 -8, -3, 8, -3, -8, 2, 8, 2,
128 -8, -2, 8, -2, -8, 1, 8, 1,
129 -8, -1, 8, -1, -8, 0, 8, 0,
130 72, // Table 9, offset 579
131 0, 9, 0, -9, -1, 9, 1, 9,
132 -1, -9, 1, -9, -2, 9, 2, 9,
133 -2, -9, 2, -9, -3, 9, 3, 9,
134 -3, -9, 3, -9, -4, 9, 4, 9,
135 -4, -9, 4, -9, -5, 9, 5, 9,
136 -5, -9, 5, -9, -6, 9, 6, 9,
137 -6, -9, 6, -9, -7, 9, 7, 9,
138 -7, -9, 7, -9, -8, 9, 8, 9,
139 -8, -9, 8, -9, -8, 8, 8, 8,
140 -8, -8, 8, -8, -9, 8, 9, 8,
141 -9, -8, 9, -8, -9, 7, 9, 7,
142 -9, -7, 9, -7, -9, 6, 9, 6,
143 -9, -6, 9, -6, -9, 5, 9, 5,
144 -9, -5, 9, -5, -9, 4, 9, 4,
145 -9, -4, 9, -4, -9, 3, 9, 3,
146 -9, -3, 9, -3, -9, 2, 9, 2,
147 -9, -2, 9, -2, -9, 1, 9, 1,
148 -9, -1, 9, -1, -9, 0, 9, 0,
149 80, // Table 10, offset 724
150 0, 10, 0, -10, -1, 10, 1, 10,
151 -1, -10, 1, -10, -2, 10, 2, 10,
152 -2, -10, 2, -10, -3, 10, 3, 10,
153 -3, -10, 3, -10, -4, 10, 4, 10,
154 -4, -10, 4, -10, -5, 10, 5, 10,
155 -5, -10, 5, -10, -6, 10, 6, 10,
156 -6, -10, 6, -10, -7, 10, 7, 10,
157 -7, -10, 7, -10, -8, 10, 8, 10,
158 -8, -10, 8, -10, -9, 10, 9, 10,
159 -9, -10, 9, -10, -9, 9, 9, 9,
160 -9, -9, 9, -9, -10, 9, 10, 9,
161 -10, -9, 10, -9, -10, 8, 10, 8,
162 -10, -8, 10, -8, -10, 7, 10, 7,
163 -10, -7, 10, -7, -10, 6, 10, 6,
164 -10, -6, 10, -6, -10, 5, 10, 5,
165 -10, -5, 10, -5, -10, 4, 10, 4,
166 -10, -4, 10, -4, -10, 3, 10, 3,
167 -10, -3, 10, -3, -10, 2, 10, 2,
168 -10, -2, 10, -2, -10, 1, 10, 1,
169 -10, -1, 10, -1, -10, 0, 10, 0,
170 88, // Table 11, offset 885
171 0, 11, 0, -11, -1, 11, 1, 11,
172 -1, -11, 1, -11, -2, 11, 2, 11,
173 -2, -11, 2, -11, -3, 11, 3, 11,
174 -3, -11, 3, -11, -4, 11, 4, 11,
175 -4, -11, 4, -11, -5, 11, 5, 11,
176 -5, -11, 5, -11, -6, 11, 6, 11,
177 -6, -11, 6, -11, -7, 11, 7, 11,
178 -7, -11, 7, -11, -8, 11, 8, 11,
179 -8, -11, 8, -11, -9, 11, 9, 11,
180 -9, -11, 9, -11, -10, 11, 10, 11,
181 -10, -11, 10, -11, -10, 10, 10, 10,
182 -10, -10, 10, -10, -11, 10, 11, 10,
183 -11, -10, 11, -10, -11, 9, 11, 9,
184 -11, -9, 11, -9, -11, 8, 11, 8,
185 -11, -8, 11, -8, -11, 7, 11, 7,
186 -11, -7, 11, -7, -11, 6, 11, 6,
187 -11, -6, 11, -6, -11, 5, 11, 5,
188 -11, -5, 11, -5, -11, 4, 11, 4,
189 -11, -4, 11, -4, -11, 3, 11, 3,
190 -11, -3, 11, -3, -11, 2, 11, 2,
191 -11, -2, 11, -2, -11, 1, 11, 1,
192 -11, -1, 11, -1, -11, 0, 11, 0,
193 96, // Table 12, offset 1062
194 0, 12, 0, -12, -1, 12, 1, 12,
195 -1, -12, 1, -12, -2, 12, 2, 12,
196 -2, -12, 2, -12, -3, 12, 3, 12,
197 -3, -12, 3, -12, -4, 12, 4, 12,
198 -4, -12, 4, -12, -5, 12, 5, 12,
199 -5, -12, 5, -12, -6, 12, 6, 12,
200 -6, -12, 6, -12, -7, 12, 7, 12,
201 -7, -12, 7, -12, -8, 12, 8, 12,
202 -8, -12, 8, -12, -9, 12, 9, 12,
203 -9, -12, 9, -12, -10, 12, 10, 12,
204 -10, -12, 10, -12, -11, 12, 11, 12,
205 -11, -12, 11, -12, -11, 11, 11, 11,
206 -11, -11, 11, -11, -12, 11, 12, 11,
207 -12, -11, 12, -11, -12, 10, 12, 10,
208 -12, -10, 12, -10, -12, 9, 12, 9,
209 -12, -9, 12, -9, -12, 8, 12, 8,
210 -12, -8, 12, -8, -12, 7, 12, 7,
211 -12, -7, 12, -7, -12, 6, 12, 6,
212 -12, -6, 12, -6, -12, 5, 12, 5,
213 -12, -5, 12, -5, -12, 4, 12, 4,
214 -12, -4, 12, -4, -12, 3, 12, 3,
215 -12, -3, 12, -3, -12, 2, 12, 2,
216 -12, -2, 12, -2, -12, 1, 12, 1,
217 -12, -1, 12, -1, -12, 0, 12, 0,
218 104, // Table 13, offset 1255
219 0, 13, 0, -13, -1, 13, 1, 13,
220 -1, -13, 1, -13, -2, 13, 2, 13,
221 -2, -13, 2, -13, -3, 13, 3, 13,
222 -3, -13, 3, -13, -4, 13, 4, 13,
223 -4, -13, 4, -13, -5, 13, 5, 13,
224 -5, -13, 5, -13, -6, 13, 6, 13,
225 -6, -13, 6, -13, -7, 13, 7, 13,
226 -7, -13, 7, -13, -8, 13, 8, 13,
227 -8, -13, 8, -13, -9, 13, 9, 13,
228 -9, -13, 9, -13, -10, 13, 10, 13,
229 -10, -13, 10, -13, -11, 13, 11, 13,
230 -11, -13, 11, -13, -12, 13, 12, 13,
231 -12, -13, 12, -13, -12, 12, 12, 12,
232 -12, -12, 12, -12, -13, 12, 13, 12,
233 -13, -12, 13, -12, -13, 11, 13, 11,
234 -13, -11, 13, -11, -13, 10, 13, 10,
235 -13, -10, 13, -10, -13, 9, 13, 9,
236 -13, -9, 13, -9, -13, 8, 13, 8,
237 -13, -8, 13, -8, -13, 7, 13, 7,
238 -13, -7, 13, -7, -13, 6, 13, 6,
239 -13, -6, 13, -6, -13, 5, 13, 5,
240 -13, -5, 13, -5, -13, 4, 13, 4,
241 -13, -4, 13, -4, -13, 3, 13, 3,
242 -13, -3, 13, -3, -13, 2, 13, 2,
243 -13, -2, 13, -2, -13, 1, 13, 1,
244 -13, -1, 13, -1, -13, 0, 13, 0,
245 112, // Table 14, offset 1464
246 0, 14, 0, -14, -1, 14, 1, 14,
247 -1, -14, 1, -14, -2, 14, 2, 14,
248 -2, -14, 2, -14, -3, 14, 3, 14,
249 -3, -14, 3, -14, -4, 14, 4, 14,
250 -4, -14, 4, -14, -5, 14, 5, 14,
251 -5, -14, 5, -14, -6, 14, 6, 14,
252 -6, -14, 6, -14, -7, 14, 7, 14,
253 -7, -14, 7, -14, -8, 14, 8, 14,
254 -8, -14, 8, -14, -9, 14, 9, 14,
255 -9, -14, 9, -14, -10, 14, 10, 14,
256 -10, -14, 10, -14, -11, 14, 11, 14,
257 -11, -14, 11, -14, -12, 14, 12, 14,
258 -12, -14, 12, -14, -13, 14, 13, 14,
259 -13, -14, 13, -14, -13, 13, 13, 13,
260 -13, -13, 13, -13, -14, 13, 14, 13,
261 -14, -13, 14, -13, -14, 12, 14, 12,
262 -14, -12, 14, -12, -14, 11, 14, 11,
263 -14, -11, 14, -11, -14, 10, 14, 10,
264 -14, -10, 14, -10, -14, 9, 14, 9,
265 -14, -9, 14, -9, -14, 8, 14, 8,
266 -14, -8, 14, -8, -14, 7, 14, 7,
267 -14, -7, 14, -7, -14, 6, 14, 6,
268 -14, -6, 14, -6, -14, 5, 14, 5,
269 -14, -5, 14, -5, -14, 4, 14, 4,
270 -14, -4, 14, -4, -14, 3, 14, 3,
271 -14, -3, 14, -3, -14, 2, 14, 2,
272 -14, -2, 14, -2, -14, 1, 14, 1,
273 -14, -1, 14, -1, -14, 0, 14, 0,
274 120, // Table 15, offset 1689
275 0, 15, 0, -15, -1, 15, 1, 15,
276 -1, -15, 1, -15, -2, 15, 2, 15,
277 -2, -15, 2, -15, -3, 15, 3, 15,
278 -3, -15, 3, -15, -4, 15, 4, 15,
279 -4, -15, 4, -15, -5, 15, 5, 15,
280 -5, -15, 5, -15, -6, 15, 6, 15,
281 -6, -15, 6, -15, -7, 15, 7, 15,
282 -7, -15, 7, -15, -8, 15, 8, 15,
283 -8, -15, 8, -15, -9, 15, 9, 15,
284 -9, -15, 9, -15, -10, 15, 10, 15,
285 -10, -15, 10, -15, -11, 15, 11, 15,
286 -11, -15, 11, -15, -12, 15, 12, 15,
287 -12, -15, 12, -15, -13, 15, 13, 15,
288 -13, -15, 13, -15, -14, 15, 14, 15,
289 -14, -15, 14, -15, -14, 14, 14, 14,
290 -14, -14, 14, -14, -15, 14, 15, 14,
291 -15, -14, 15, -14, -15, 13, 15, 13,
292 -15, -13, 15, -13, -15, 12, 15, 12,
293 -15, -12, 15, -12, -15, 11, 15, 11,
294 -15, -11, 15, -11, -15, 10, 15, 10,
295 -15, -10, 15, -10, -15, 9, 15, 9,
296 -15, -9, 15, -9, -15, 8, 15, 8,
297 -15, -8, 15, -8, -15, 7, 15, 7,
298 -15, -7, 15, -7, -15, 6, 15, 6,
299 -15, -6, 15, -6, -15, 5, 15, 5,
300 -15, -5, 15, -5, -15, 4, 15, 4,
301 -15, -4, 15, -4, -15, 3, 15, 3,
302 -15, -3, 15, -3, -15, 2, 15, 2,
303 -15, -2, 15, -2, -15, 1, 15, 1,
304 -15, -1, 15, -1, -15, 0, 15, 0,
305 (char)128, // Table 16, offset 1930
306 0, 16, 0, -16, -1, 16, 1, 16,
307 -1, -16, 1, -16, -2, 16, 2, 16,
308 -2, -16, 2, -16, -3, 16, 3, 16,
309 -3, -16, 3, -16, -4, 16, 4, 16,
310 -4, -16, 4, -16, -5, 16, 5, 16,
311 -5, -16, 5, -16, -6, 16, 6, 16,
312 -6, -16, 6, -16, -7, 16, 7, 16,
313 -7, -16, 7, -16, -8, 16, 8, 16,
314 -8, -16, 8, -16, -9, 16, 9, 16,
315 -9, -16, 9, -16, -10, 16, 10, 16,
316 -10, -16, 10, -16, -11, 16, 11, 16,
317 -11, -16, 11, -16, -12, 16, 12, 16,
318 -12, -16, 12, -16, -13, 16, 13, 16,
319 -13, -16, 13, -16, -14, 16, 14, 16,
320 -14, -16, 14, -16, -15, 16, 15, 16,
321 -15, -16, 15, -16, -15, 15, 15, 15,
322 -15, -15, 15, -15, -16, 15, 16, 15,
323 -16, -15, 16, -15, -16, 14, 16, 14,
324 -16, -14, 16, -14, -16, 13, 16, 13,
325 -16, -13, 16, -13, -16, 12, 16, 12,
326 -16, -12, 16, -12, -16, 11, 16, 11,
327 -16, -11, 16, -11, -16, 10, 16, 10,
328 -16, -10, 16, -10, -16, 9, 16, 9,
329 -16, -9, 16, -9, -16, 8, 16, 8,
330 -16, -8, 16, -8, -16, 7, 16, 7,
331 -16, -7, 16, -7, -16, 6, 16, 6,
332 -16, -6, 16, -6, -16, 5, 16, 5,
333 -16, -5, 16, -5, -16, 4, 16, 4,
334 -16, -4, 16, -4, -16, 3, 16, 3,
335 -16, -3, 16, -3, -16, 2, 16, 2,
336 -16, -2, 16, -2, -16, 1, 16, 1,
337 -16, -1, 16, -1, -16, 0, 16, 0,
338 (char)136, // Table 16, offset 2187
339 0, 17, 0, -17, -1, 17, 1, 17,
340 -1, -17, 1, -17, -2, 17, 2, 17,
341 -2, -17, 2, -17, -3, 17, 3, 17,
342 -3, -17, 3, -17, -4, 17, 4, 17,
343 -4, -17, 4, -17, -5, 17, 5, 17,
344 -5, -17, 5, -17, -6, 17, 6, 17,
345 -6, -17, 6, -17, -7, 17, 7, 17,
346 -7, -17, 7, -17, -8, 17, 8, 17,
347 -8, -17, 8, -17, -9, 17, 9, 17,
348 -9, -17, 9, -17, -10, 17, 10, 17,
349 -10, -17, 10, -17, -11, 17, 11, 17,
350 -11, -17, 11, -17, -12, 17, 12, 17,
351 -12, -17, 12, -17, -13, 17, 13, 17,
352 -13, -17, 13, -17, -14, 17, 14, 17,
353 -14, -17, 14, -17, -15, 17, 15, 17,
354 -15, -17, 15, -17, -16, 17, 16, 17,
355 -16, -17, 16, -17, -16, 16, 16, 16,
356 -16, -16, 16, -16, -17, 16, 17, 16,
357 -17, -16, 17, -16, -17, 15, 17, 15,
358 -17, -15, 17, -15, -17, 14, 17, 14,
359 -17, -14, 17, -14, -17, 13, 17, 13,
360 -17, -13, 17, -13, -17, 12, 17, 12,
361 -17, -12, 17, -12, -17, 11, 17, 11,
362 -17, -11, 17, -11, -17, 10, 17, 10,
363 -17, -10, 17, -10, -17, 9, 17, 9,
364 -17, -9, 17, -9, -17, 8, 17, 8,
365 -17, -8, 17, -8, -17, 7, 17, 7,
366 -17, -7, 17, -7, -17, 6, 17, 6,
367 -17, -6, 17, -6, -17, 5, 17, 5,
368 -17, -5, 17, -5, -17, 4, 17, 4,
369 -17, -4, 17, -4, -17, 3, 17, 3,
370 -17, -3, 17, -3, -17, 2, 17, 2,
371 -17, -2, 17, -2, -17, 1, 17, 1,
372 -17, -1, 17, -1, -17, 0, 17, 0,
373 (char)144, // Table 16, offset 2460
374 0, 18, 0, -18, -1, 18, 1, 18,
375 -1, -18, 1, -18, -2, 18, 2, 18,
376 -2, -18, 2, -18, -3, 18, 3, 18,
377 -3, -18, 3, -18, -4, 18, 4, 18,
378 -4, -18, 4, -18, -5, 18, 5, 18,
379 -5, -18, 5, -18, -6, 18, 6, 18,
380 -6, -18, 6, -18, -7, 18, 7, 18,
381 -7, -18, 7, -18, -8, 18, 8, 18,
382 -8, -18, 8, -18, -9, 18, 9, 18,
383 -9, -18, 9, -18, -10, 18, 10, 18,
384 -10, -18, 10, -18, -11, 18, 11, 18,
385 -11, -18, 11, -18, -12, 18, 12, 18,
386 -12, -18, 12, -18, -13, 18, 13, 18,
387 -13, -18, 13, -18, -14, 18, 14, 18,
388 -14, -18, 14, -18, -15, 18, 15, 18,
389 -15, -18, 15, -18, -16, 18, 16, 18,
390 -16, -18, 16, -18, -17, 18, 17, 18,
391 -17, -18, 17, -18, -17, 17, 17, 17,
392 -17, -17, 17, -17, -18, 17, 18, 17,
393 -18, -17, 18, -17, -18, 16, 18, 16,
394 -18, -16, 18, -16, -18, 15, 18, 15,
395 -18, -15, 18, -15, -18, 14, 18, 14,
396 -18, -14, 18, -14, -18, 13, 18, 13,
397 -18, -13, 18, -13, -18, 12, 18, 12,
398 -18, -12, 18, -12, -18, 11, 18, 11,
399 -18, -11, 18, -11, -18, 10, 18, 10,
400 -18, -10, 18, -10, -18, 9, 18, 9,
401 -18, -9, 18, -9, -18, 8, 18, 8,
402 -18, -8, 18, -8, -18, 7, 18, 7,
403 -18, -7, 18, -7, -18, 6, 18, 6,
404 -18, -6, 18, -6, -18, 5, 18, 5,
405 -18, -5, 18, -5, -18, 4, 18, 4,
406 -18, -4, 18, -4, -18, 3, 18, 3,
407 -18, -3, 18, -3, -18, 2, 18, 2,
408 -18, -2, 18, -2, -18, 1, 18, 1,
409 -18, -1, 18, -1, -18, 0, 18, 0,
410 // clang-format on
411 };
412
413 /*
414 * vCrawlTable specifies the X- Y-coordinate offsets of lighting visions.
415 * The last entry-pair is only for alignment.
416 */
417 const BYTE vCrawlTable[23][30] = {
418 // clang-format off
419 { 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0 },
420 { 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 1, 9, 1, 10, 1, 11, 1, 12, 1, 13, 1, 14, 1, 15, 1 },
421 { 1, 0, 2, 0, 3, 0, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 1, 10, 1, 11, 1, 12, 2, 13, 2, 14, 2, 15, 2 },
422 { 1, 0, 2, 0, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 2, 9, 2, 10, 2, 11, 2, 12, 2, 13, 3, 14, 3, 15, 3 },
423 { 1, 0, 2, 1, 3, 1, 4, 1, 5, 1, 6, 2, 7, 2, 8, 2, 9, 3, 10, 3, 11, 3, 12, 3, 13, 4, 14, 4, 0, 0 },
424 { 1, 0, 2, 1, 3, 1, 4, 1, 5, 2, 6, 2, 7, 3, 8, 3, 9, 3, 10, 4, 11, 4, 12, 4, 13, 5, 14, 5, 0, 0 },
425 { 1, 0, 2, 1, 3, 1, 4, 2, 5, 2, 6, 3, 7, 3, 8, 3, 9, 4, 10, 4, 11, 5, 12, 5, 13, 6, 14, 6, 0, 0 },
426 { 1, 1, 2, 1, 3, 2, 4, 2, 5, 3, 6, 3, 7, 4, 8, 4, 9, 5, 10, 5, 11, 6, 12, 6, 13, 7, 0, 0, 0, 0 },
427 { 1, 1, 2, 1, 3, 2, 4, 2, 5, 3, 6, 4, 7, 4, 8, 5, 9, 6, 10, 6, 11, 7, 12, 7, 12, 8, 13, 8, 0, 0 },
428 { 1, 1, 2, 2, 3, 2, 4, 3, 5, 4, 6, 5, 7, 5, 8, 6, 9, 7, 10, 7, 10, 8, 11, 8, 12, 9, 0, 0, 0, 0 },
429 { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 5, 7, 6, 8, 7, 9, 8, 10, 9, 11, 9, 11, 10, 0, 0, 0, 0, 0, 0 },
430 { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0 },
431 { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 9, 11, 10, 11, 0, 0, 0, 0, 0, 0 },
432 { 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 5, 7, 6, 8, 7, 9, 7, 10, 8, 10, 8, 11, 9, 12, 0, 0, 0, 0 },
433 { 1, 1, 1, 2, 2, 3, 2, 4, 3, 5, 4, 6, 4, 7, 5, 8, 6, 9, 6, 10, 7, 11, 7, 12, 8, 12, 8, 13, 0, 0 },
434 { 1, 1, 1, 2, 2, 3, 2, 4, 3, 5, 3, 6, 4, 7, 4, 8, 5, 9, 5, 10, 6, 11, 6, 12, 7, 13, 0, 0, 0, 0 },
435 { 0, 1, 1, 2, 1, 3, 2, 4, 2, 5, 3, 6, 3, 7, 3, 8, 4, 9, 4, 10, 5, 11, 5, 12, 6, 13, 6, 14, 0, 0 },
436 { 0, 1, 1, 2, 1, 3, 1, 4, 2, 5, 2, 6, 3, 7, 3, 8, 3, 9, 4, 10, 4, 11, 4, 12, 5, 13, 5, 14, 0, 0 },
437 { 0, 1, 1, 2, 1, 3, 1, 4, 1, 5, 2, 6, 2, 7, 2, 8, 3, 9, 3, 10, 3, 11, 3, 12, 4, 13, 4, 14, 0, 0 },
438 { 0, 1, 0, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 2, 8, 2, 9, 2, 10, 2, 11, 2, 12, 3, 13, 3, 14, 3, 15 },
439 { 0, 1, 0, 2, 0, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 1, 10, 1, 11, 2, 12, 2, 13, 2, 14, 2, 15 },
440 { 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 1, 8, 1, 9, 1, 10, 1, 11, 1, 12, 1, 13, 1, 14, 1, 15 },
441 { 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15 },
442 // clang-format on
443 };
444
445 /** RadiusAdj maps from vCrawlTable index to lighting vision radius adjustment. */
446 const BYTE RadiusAdj[23] = { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 4, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0 };
447
RotateRadius(int * x,int * y,int * dx,int * dy,int * lx,int * ly,int * bx,int * by)448 void RotateRadius(int *x, int *y, int *dx, int *dy, int *lx, int *ly, int *bx, int *by)
449 {
450 int swap;
451
452 *bx = 0;
453 *by = 0;
454
455 swap = *dx;
456 *dx = 7 - *dy;
457 *dy = swap;
458 swap = *lx;
459 *lx = 7 - *ly;
460 *ly = swap;
461
462 *x = *dx - *lx;
463 *y = *dy - *ly;
464
465 if (*x < 0) {
466 *x += 8;
467 *bx = 1;
468 }
469 if (*y < 0) {
470 *y += 8;
471 *by = 1;
472 }
473 }
474
SetLight(int x,int y,char v)475 void SetLight(int x, int y, char v)
476 {
477 if (LoadMapObjsFlag)
478 dPreLight[x][y] = v;
479 else
480 dLight[x][y] = v;
481 }
482
GetLight(int x,int y)483 char GetLight(int x, int y)
484 {
485 if (LoadMapObjsFlag)
486 return dPreLight[x][y];
487 else
488 return dLight[x][y];
489 }
490
DoLighting(int nXPos,int nYPos,int nRadius,int Lnum)491 void DoLighting(int nXPos, int nYPos, int nRadius, int Lnum)
492 {
493 int x, y, v, xoff, yoff, mult, radius_block;
494 int min_x, max_x, min_y, max_y;
495 int dist_x, dist_y, light_x, light_y, block_x, block_y, temp_x, temp_y;
496
497 xoff = 0;
498 yoff = 0;
499 light_x = 0;
500 light_y = 0;
501 block_x = 0;
502 block_y = 0;
503
504 if (Lnum >= 0) {
505 xoff = LightList[Lnum]._xoff;
506 yoff = LightList[Lnum]._yoff;
507 if (xoff < 0) {
508 xoff += 8;
509 nXPos--;
510 }
511 if (yoff < 0) {
512 yoff += 8;
513 nYPos--;
514 }
515 }
516
517 dist_x = xoff;
518 dist_y = yoff;
519
520 if (nXPos - 15 < 0) {
521 min_x = nXPos + 1;
522 } else {
523 min_x = 15;
524 }
525 if (nXPos + 15 > MAXDUNX) {
526 max_x = MAXDUNX - nXPos;
527 } else {
528 max_x = 15;
529 }
530 if (nYPos - 15 < 0) {
531 min_y = nYPos + 1;
532 } else {
533 min_y = 15;
534 }
535 if (nYPos + 15 > MAXDUNY) {
536 max_y = MAXDUNY - nYPos;
537 } else {
538 max_y = 15;
539 }
540
541 if (nXPos >= 0 && nXPos < MAXDUNX && nYPos >= 0 && nYPos < MAXDUNY) {
542 if (currlevel < 17) {
543 SetLight(nXPos, nYPos, 0);
544 } else if (GetLight(nXPos, nYPos) > lightradius[nRadius][0]) {
545 SetLight(nXPos, nYPos, lightradius[nRadius][0]);
546 }
547 }
548
549 mult = xoff + 8 * yoff;
550 for (y = 0; y < min_y; y++) {
551 for (x = 1; x < max_x; x++) {
552 radius_block = lightblock[mult][y][x];
553 if (radius_block < 128) {
554 temp_x = nXPos + x;
555 temp_y = nYPos + y;
556 v = lightradius[nRadius][radius_block];
557 if (temp_x >= 0 && temp_x < MAXDUNX && temp_y >= 0 && temp_y < MAXDUNY)
558 if (v < GetLight(temp_x, temp_y))
559 SetLight(temp_x, temp_y, v);
560 }
561 }
562 }
563 RotateRadius(&xoff, &yoff, &dist_x, &dist_y, &light_x, &light_y, &block_x, &block_y);
564 mult = xoff + 8 * yoff;
565 for (y = 0; y < max_y; y++) {
566 for (x = 1; x < max_x; x++) {
567 radius_block = lightblock[mult][y + block_y][x + block_x];
568 if (radius_block < 128) {
569 temp_x = nXPos + y;
570 temp_y = nYPos - x;
571 v = lightradius[nRadius][radius_block];
572 if (temp_x >= 0 && temp_x < MAXDUNX && temp_y >= 0 && temp_y < MAXDUNY)
573 if (v < GetLight(temp_x, temp_y))
574 SetLight(temp_x, temp_y, v);
575 }
576 }
577 }
578 RotateRadius(&xoff, &yoff, &dist_x, &dist_y, &light_x, &light_y, &block_x, &block_y);
579 mult = xoff + 8 * yoff;
580 for (y = 0; y < max_y; y++) {
581 for (x = 1; x < min_x; x++) {
582 radius_block = lightblock[mult][y + block_y][x + block_x];
583 if (radius_block < 128) {
584 temp_x = nXPos - x;
585 temp_y = nYPos - y;
586 v = lightradius[nRadius][radius_block];
587 if (temp_x >= 0 && temp_x < MAXDUNX && temp_y >= 0 && temp_y < MAXDUNY)
588 if (v < GetLight(temp_x, temp_y))
589 SetLight(temp_x, temp_y, v);
590 }
591 }
592 }
593 RotateRadius(&xoff, &yoff, &dist_x, &dist_y, &light_x, &light_y, &block_x, &block_y);
594 mult = xoff + 8 * yoff;
595 for (y = 0; y < min_y; y++) {
596 for (x = 1; x < min_x; x++) {
597 radius_block = lightblock[mult][y + block_y][x + block_x];
598 if (radius_block < 128) {
599 temp_x = nXPos - y;
600 temp_y = nYPos + x;
601 v = lightradius[nRadius][radius_block];
602 if (temp_x >= 0 && temp_x < MAXDUNX && temp_y >= 0 && temp_y < MAXDUNY)
603 if (v < GetLight(temp_x, temp_y))
604 SetLight(temp_x, temp_y, v);
605 }
606 }
607 }
608 }
609
DoUnLight(int nXPos,int nYPos,int nRadius)610 void DoUnLight(int nXPos, int nYPos, int nRadius)
611 {
612 int x, y, min_x, min_y, max_x, max_y;
613
614 nRadius++;
615 min_y = nYPos - nRadius;
616 max_y = nYPos + nRadius;
617 min_x = nXPos - nRadius;
618 max_x = nXPos + nRadius;
619
620 if (min_y < 0) {
621 min_y = 0;
622 }
623 if (max_y > MAXDUNY) {
624 max_y = MAXDUNY;
625 }
626 if (min_x < 0) {
627 min_x = 0;
628 }
629 if (max_x > MAXDUNX) {
630 max_x = MAXDUNX;
631 }
632
633 for (y = min_y; y < max_y; y++) {
634 for (x = min_x; x < max_x; x++) {
635 if (x >= 0 && x < MAXDUNX && y >= 0 && y < MAXDUNY)
636 dLight[x][y] = dPreLight[x][y];
637 }
638 }
639 }
640
DoUnVision(int nXPos,int nYPos,int nRadius)641 void DoUnVision(int nXPos, int nYPos, int nRadius)
642 {
643 int i, j, x1, y1, x2, y2;
644
645 nRadius++;
646 nRadius++; // increasing the radius even further here prevents leaving stray vision tiles behind and doesn't seem to affect monster AI - applying new vision happens in the same tick
647 y1 = nYPos - nRadius;
648 y2 = nYPos + nRadius;
649 x1 = nXPos - nRadius;
650 x2 = nXPos + nRadius;
651
652 if (y1 < 0) {
653 y1 = 0;
654 }
655 if (y2 > MAXDUNY) {
656 y2 = MAXDUNY;
657 }
658 if (x1 < 0) {
659 x1 = 0;
660 }
661 if (x2 > MAXDUNX) {
662 x2 = MAXDUNX;
663 }
664
665 for (i = x1; i < x2; i++) {
666 for (j = y1; j < y2; j++) {
667 dFlags[i][j] &= ~(BFLAG_VISIBLE | BFLAG_LIT);
668 }
669 }
670 }
671
DoVision(int nXPos,int nYPos,int nRadius,BOOL doautomap,BOOL visible)672 void DoVision(int nXPos, int nYPos, int nRadius, BOOL doautomap, BOOL visible)
673 {
674 BOOL nBlockerFlag;
675 int nCrawlX, nCrawlY, nLineLen, nTrans;
676 int j, k, v, x1adj, x2adj, y1adj, y2adj;
677
678 if (nXPos >= 0 && nXPos <= MAXDUNX && nYPos >= 0 && nYPos <= MAXDUNY) {
679 if (doautomap) {
680 if (dFlags[nXPos][nYPos] >= 0) {
681 SetAutomapView(nXPos, nXPos);
682 }
683 dFlags[nXPos][nYPos] |= BFLAG_EXPLORED;
684 }
685 if (visible) {
686 dFlags[nXPos][nYPos] |= BFLAG_LIT;
687 }
688 dFlags[nXPos][nYPos] |= BFLAG_VISIBLE;
689 }
690
691 for (v = 0; v < 4; v++) {
692 for (j = 0; j < 23; j++) {
693 nBlockerFlag = FALSE;
694 nLineLen = 2 * (nRadius - RadiusAdj[j]);
695 for (k = 0; k < nLineLen && !nBlockerFlag; k += 2) {
696 x1adj = 0;
697 x2adj = 0;
698 y1adj = 0;
699 y2adj = 0;
700 switch (v) {
701 case 0:
702 nCrawlX = nXPos + vCrawlTable[j][k];
703 nCrawlY = nYPos + vCrawlTable[j][k + 1];
704 if (vCrawlTable[j][k] > 0 && vCrawlTable[j][k + 1] > 0) {
705 x1adj = -1;
706 y2adj = -1;
707 }
708 break;
709 case 1:
710 nCrawlX = nXPos - vCrawlTable[j][k];
711 nCrawlY = nYPos - vCrawlTable[j][k + 1];
712 if (vCrawlTable[j][k] > 0 && vCrawlTable[j][k + 1] > 0) {
713 y1adj = 1;
714 x2adj = 1;
715 }
716 break;
717 case 2:
718 nCrawlX = nXPos + vCrawlTable[j][k];
719 nCrawlY = nYPos - vCrawlTable[j][k + 1];
720 if (vCrawlTable[j][k] > 0 && vCrawlTable[j][k + 1] > 0) {
721 x1adj = -1;
722 y2adj = 1;
723 }
724 break;
725 case 3:
726 nCrawlX = nXPos - vCrawlTable[j][k];
727 nCrawlY = nYPos + vCrawlTable[j][k + 1];
728 if (vCrawlTable[j][k] > 0 && vCrawlTable[j][k + 1] > 0) {
729 y1adj = -1;
730 x2adj = 1;
731 }
732 break;
733 }
734 if (nCrawlX >= 0 && nCrawlX < MAXDUNX && nCrawlY >= 0 && nCrawlY < MAXDUNY) {
735 nBlockerFlag = nBlockTable[dPiece[nCrawlX][nCrawlY]];
736 if ((x1adj + nCrawlX >= 0 && x1adj + nCrawlX < MAXDUNX && y1adj + nCrawlY >= 0 && y1adj + nCrawlY < MAXDUNY
737 && !nBlockTable[dPiece[x1adj + nCrawlX][y1adj + nCrawlY]])
738 || (x2adj + nCrawlX >= 0 && x2adj + nCrawlX < MAXDUNX && y2adj + nCrawlY >= 0 && y2adj + nCrawlY < MAXDUNY
739 && !nBlockTable[dPiece[x2adj + nCrawlX][y2adj + nCrawlY]])) {
740 if (doautomap) {
741 if (dFlags[nCrawlX][nCrawlY] >= 0) {
742 SetAutomapView(nCrawlX, nCrawlY);
743 }
744 dFlags[nCrawlX][nCrawlY] |= BFLAG_EXPLORED;
745 }
746 if (visible) {
747 dFlags[nCrawlX][nCrawlY] |= BFLAG_LIT;
748 }
749 dFlags[nCrawlX][nCrawlY] |= BFLAG_VISIBLE;
750 if (!nBlockerFlag) {
751 nTrans = dTransVal[nCrawlX][nCrawlY];
752 if (nTrans != 0) {
753 TransList[nTrans] = TRUE;
754 }
755 }
756 }
757 }
758 }
759 }
760 }
761 }
762
FreeLightTable()763 void FreeLightTable()
764 {
765 MemFreeDbg(pLightTbl);
766 }
767
InitLightTable()768 void InitLightTable()
769 {
770 assert(!pLightTbl);
771 pLightTbl = DiabloAllocPtr(LIGHTSIZE);
772 }
773
MakeLightTable()774 void MakeLightTable()
775 {
776 int i, j, k, l, lights, shade, l1, l2, cnt, rem, div;
777 double fs, fa;
778 BYTE col, max;
779 BYTE *tbl, *trn;
780 BYTE blood[16];
781
782 tbl = pLightTbl;
783 shade = 0;
784
785 if (light4flag) {
786 lights = 3;
787 } else {
788 lights = 15;
789 }
790
791 for (i = 0; i < lights; i++) {
792 *tbl++ = 0;
793 for (j = 0; j < 8; j++) {
794 col = 16 * j + shade;
795 max = 16 * j + 15;
796 for (k = 0; k < 16; k++) {
797 if (k != 0 || j != 0) {
798 *tbl++ = col;
799 }
800 if (col < max) {
801 col++;
802 } else {
803 max = 0;
804 col = 0;
805 }
806 }
807 }
808 for (j = 16; j < 20; j++) {
809 col = 8 * j + (shade >> 1);
810 max = 8 * j + 7;
811 for (k = 0; k < 8; k++) {
812 *tbl++ = col;
813 if (col < max) {
814 col++;
815 } else {
816 max = 0;
817 col = 0;
818 }
819 }
820 }
821 for (j = 10; j < 16; j++) {
822 col = 16 * j + shade;
823 max = 16 * j + 15;
824 for (k = 0; k < 16; k++) {
825 *tbl++ = col;
826 if (col < max) {
827 col++;
828 } else {
829 max = 0;
830 col = 0;
831 }
832 if (col == 255) {
833 max = 0;
834 col = 0;
835 }
836 }
837 }
838 if (light4flag) {
839 shade += 5;
840 } else {
841 shade++;
842 }
843 }
844
845 for (i = 0; i < 256; i++) {
846 *tbl++ = 0;
847 }
848
849 if (leveltype == DTYPE_HELL) {
850 tbl = pLightTbl;
851 for (i = 0; i < lights; i++) {
852 l1 = lights - i;
853 l2 = l1;
854 div = lights / l1;
855 rem = lights % l1;
856 cnt = 0;
857 blood[0] = 0;
858 col = 1;
859 for (j = 1; j < 16; j++) {
860 blood[j] = col;
861 l2 += rem;
862 if (l2 > l1 && j < 15) {
863 j++;
864 blood[j] = col;
865 l2 -= l1;
866 }
867 cnt++;
868 if (cnt == div) {
869 col++;
870 cnt = 0;
871 }
872 }
873 *tbl++ = 0;
874 for (j = 1; j <= 15; j++) {
875 *tbl++ = blood[j];
876 }
877 for (j = 15; j > 0; j--) {
878 *tbl++ = blood[j];
879 }
880 *tbl++ = 1;
881 tbl += 224;
882 }
883 *tbl++ = 0;
884 for (j = 0; j < 31; j++) {
885 *tbl++ = 1;
886 }
887 tbl += 224;
888 }
889 if (currlevel >= 17) {
890 tbl = pLightTbl;
891 for (i = 0; i < lights; i++) {
892 *tbl++ = 0;
893 for (j = 1; j < 16; j++)
894 *tbl++ = j;
895 tbl += 240;
896 }
897 *tbl++ = 0;
898 for (j = 1; j < 16; j++)
899 *tbl++ = 1;
900 tbl += 240;
901 }
902
903 trn = LoadFileInMem("PlrGFX\\Infra.TRN", NULL);
904 for (i = 0; i < 256; i++) {
905 *tbl++ = trn[i];
906 }
907 mem_free_dbg(trn);
908
909 trn = LoadFileInMem("PlrGFX\\Stone.TRN", NULL);
910 for (i = 0; i < 256; i++) {
911 *tbl++ = trn[i];
912 }
913 mem_free_dbg(trn);
914
915 for (i = 0; i < 8; i++) {
916 for (col = 226; col < 239; col++) {
917 if (i != 0 || col != 226) {
918 *tbl++ = col;
919 } else {
920 *tbl++ = 0;
921 }
922 }
923 *tbl++ = 0;
924 *tbl++ = 0;
925 *tbl++ = 0;
926 }
927 for (i = 0; i < 4; i++) {
928 col = 224;
929 for (j = 224; j < 239; j += 2) {
930 *tbl++ = col;
931 col += 2;
932 }
933 }
934 for (i = 0; i < 6; i++) {
935 for (col = 224; col < 239; col++) {
936 *tbl++ = col;
937 }
938 *tbl++ = 0;
939 }
940
941 for (j = 0; j < 16; j++) {
942 for (i = 0; i < 128; i++) {
943 if (i > (j + 1) * 8) {
944 lightradius[j][i] = 15;
945 } else {
946 fs = (double)15 * i / ((double)8 * (j + 1));
947 lightradius[j][i] = (BYTE)(fs + 0.5);
948 }
949 }
950 }
951
952 if (currlevel >= 17) {
953 for (j = 0; j < 16; j++) {
954 fa = (sqrt((double)(16 - j))) / 128;
955 fa *= fa;
956 for (i = 0; i < 128; i++) {
957 lightradius[15 - j][i] = 15 - (BYTE)(fa * (double)((128 - i) * (128 - i)));
958 if (lightradius[15 - j][i] > 15)
959 lightradius[15 - j][i] = 0;
960 lightradius[15 - j][i] = lightradius[15 - j][i] - (BYTE)((15 - j) / 2);
961 if (lightradius[15 - j][i] > 15)
962 lightradius[15 - j][i] = 0;
963 }
964 }
965 }
966 for (j = 0; j < 8; j++) {
967 for (i = 0; i < 8; i++) {
968 for (k = 0; k < 16; k++) {
969 for (l = 0; l < 16; l++) {
970 fs = (BYTE)sqrt((double)(8 * l - j) * (8 * l - j) + (8 * k - i) * (8 * k - i));
971 fs += fs < 0 ? -0.5 : 0.5;
972
973 lightblock[j * 8 + i][k][l] = fs;
974 }
975 }
976 }
977 }
978 }
979
980 #ifdef _DEBUG
ToggleLighting()981 void ToggleLighting()
982 {
983 int i;
984
985 lightflag ^= TRUE;
986
987 if (lightflag) {
988 memset(dLight, 0, sizeof(dLight));
989 } else {
990 memcpy(dLight, dPreLight, sizeof(dLight));
991 for (i = 0; i < MAX_PLRS; i++) {
992 if (plr[i].plractive && plr[i].plrlevel == currlevel) {
993 DoLighting(plr[i]._px, plr[i]._py, plr[i]._pLightRad, -1);
994 }
995 }
996 }
997 }
998 #endif
999
InitLightMax()1000 void InitLightMax()
1001 {
1002 if (light4flag) {
1003 lightmax = 3;
1004 } else {
1005 lightmax = 15;
1006 }
1007 }
1008
InitLighting()1009 void InitLighting()
1010 {
1011 int i;
1012
1013 numlights = 0;
1014 dolighting = FALSE;
1015 lightflag = FALSE;
1016
1017 for (i = 0; i < MAXLIGHTS; i++) {
1018 lightactive[i] = i;
1019 }
1020 }
1021
AddLight(int x,int y,int r)1022 int AddLight(int x, int y, int r)
1023 {
1024 int lid;
1025
1026 if (lightflag) {
1027 return NO_LIGHT;
1028 }
1029
1030 lid = NO_LIGHT;
1031
1032 if (numlights < MAXLIGHTS) {
1033 lid = lightactive[numlights++];
1034 LightList[lid]._lx = x;
1035 LightList[lid]._ly = y;
1036 LightList[lid]._lradius = r;
1037 LightList[lid]._xoff = 0;
1038 LightList[lid]._yoff = 0;
1039 LightList[lid]._ldel = FALSE;
1040 LightList[lid]._lunflag = FALSE;
1041 dolighting = TRUE;
1042 }
1043
1044 return lid;
1045 }
1046
AddUnLight(int i)1047 void AddUnLight(int i)
1048 {
1049 if (lightflag || i == NO_LIGHT) {
1050 return;
1051 }
1052
1053 LightList[i]._ldel = TRUE;
1054 dolighting = TRUE;
1055 }
1056
ChangeLightRadius(int i,int r)1057 void ChangeLightRadius(int i, int r)
1058 {
1059 if (lightflag || i == NO_LIGHT) {
1060 return;
1061 }
1062
1063 LightList[i]._lunflag = TRUE;
1064 LightList[i]._lunx = LightList[i]._lx;
1065 LightList[i]._luny = LightList[i]._ly;
1066 LightList[i]._lunr = LightList[i]._lradius;
1067 LightList[i]._lradius = r;
1068 dolighting = TRUE;
1069 }
1070
ChangeLightXY(int i,int x,int y)1071 void ChangeLightXY(int i, int x, int y)
1072 {
1073 if (lightflag || i == NO_LIGHT) {
1074 return;
1075 }
1076
1077 LightList[i]._lunflag = TRUE;
1078 LightList[i]._lunx = LightList[i]._lx;
1079 LightList[i]._luny = LightList[i]._ly;
1080 LightList[i]._lunr = LightList[i]._lradius;
1081 LightList[i]._lx = x;
1082 LightList[i]._ly = y;
1083 dolighting = TRUE;
1084 }
1085
ChangeLightOff(int i,int x,int y)1086 void ChangeLightOff(int i, int x, int y)
1087 {
1088 if (lightflag || i == NO_LIGHT) {
1089 return;
1090 }
1091
1092 LightList[i]._lunflag = TRUE;
1093 LightList[i]._lunx = LightList[i]._lx;
1094 LightList[i]._luny = LightList[i]._ly;
1095 LightList[i]._lunr = LightList[i]._lradius;
1096 LightList[i]._xoff = x;
1097 LightList[i]._yoff = y;
1098 dolighting = TRUE;
1099 }
1100
ChangeLight(int i,int x,int y,int r)1101 void ChangeLight(int i, int x, int y, int r)
1102 {
1103 if (lightflag || i == NO_LIGHT) {
1104 return;
1105 }
1106
1107 LightList[i]._lunflag = TRUE;
1108 LightList[i]._lunx = LightList[i]._lx;
1109 LightList[i]._luny = LightList[i]._ly;
1110 LightList[i]._lunr = LightList[i]._lradius;
1111 LightList[i]._lx = x;
1112 LightList[i]._ly = y;
1113 LightList[i]._lradius = r;
1114 dolighting = TRUE;
1115 }
1116
ProcessLightList()1117 void ProcessLightList()
1118 {
1119 int i, j;
1120 BYTE temp;
1121
1122 if (lightflag) {
1123 return;
1124 }
1125
1126 if (dolighting) {
1127 for (i = 0; i < numlights; i++) {
1128 j = lightactive[i];
1129 if (LightList[j]._ldel) {
1130 DoUnLight(LightList[j]._lx, LightList[j]._ly, LightList[j]._lradius);
1131 }
1132 if (LightList[j]._lunflag) {
1133 DoUnLight(LightList[j]._lunx, LightList[j]._luny, LightList[j]._lunr);
1134 LightList[j]._lunflag = FALSE;
1135 }
1136 }
1137 for (i = 0; i < numlights; i++) {
1138 j = lightactive[i];
1139 if (!LightList[j]._ldel) {
1140 DoLighting(LightList[j]._lx, LightList[j]._ly, LightList[j]._lradius, j);
1141 }
1142 }
1143 i = 0;
1144 while (i < numlights) {
1145 if (LightList[lightactive[i]]._ldel) {
1146 numlights--;
1147 temp = lightactive[numlights];
1148 lightactive[numlights] = lightactive[i];
1149 lightactive[i] = temp;
1150 } else {
1151 i++;
1152 }
1153 }
1154 }
1155
1156 dolighting = FALSE;
1157 }
1158
SavePreLighting()1159 void SavePreLighting()
1160 {
1161 memcpy(dPreLight, dLight, sizeof(dPreLight));
1162 }
1163
InitVision()1164 void InitVision()
1165 {
1166 int i;
1167
1168 numvision = 0;
1169 dovision = FALSE;
1170 visionid = 1;
1171
1172 for (i = 0; i < TransVal; i++) {
1173 TransList[i] = FALSE;
1174 }
1175 }
1176
AddVision(int x,int y,int r,BOOL mine)1177 int AddVision(int x, int y, int r, BOOL mine)
1178 {
1179 int vid = -1; // BUGFIX: if numvision >= MAXVISION behavior is undefined (fixed)
1180
1181 if (numvision < MAXVISION) {
1182 VisionList[numvision]._lx = x;
1183 VisionList[numvision]._ly = y;
1184 VisionList[numvision]._lradius = r;
1185 vid = visionid++;
1186 VisionList[numvision]._lid = vid;
1187 VisionList[numvision]._ldel = FALSE;
1188 VisionList[numvision]._lunflag = FALSE;
1189 VisionList[numvision]._lflags = mine != 0;
1190 numvision++;
1191 dovision = TRUE;
1192 }
1193
1194 return vid;
1195 }
1196
ChangeVisionRadius(int id,int r)1197 void ChangeVisionRadius(int id, int r)
1198 {
1199 int i;
1200
1201 for (i = 0; i < numvision; i++) {
1202 if (VisionList[i]._lid == id) {
1203 VisionList[i]._lunflag = TRUE;
1204 VisionList[i]._lunx = VisionList[i]._lx;
1205 VisionList[i]._luny = VisionList[i]._ly;
1206 VisionList[i]._lunr = VisionList[i]._lradius;
1207 VisionList[i]._lradius = r;
1208 dovision = TRUE;
1209 }
1210 }
1211 }
1212
ChangeVisionXY(int id,int x,int y)1213 void ChangeVisionXY(int id, int x, int y)
1214 {
1215 int i;
1216
1217 for (i = 0; i < numvision; i++) {
1218 if (VisionList[i]._lid == id) {
1219 VisionList[i]._lunflag = TRUE;
1220 VisionList[i]._lunx = VisionList[i]._lx;
1221 VisionList[i]._luny = VisionList[i]._ly;
1222 VisionList[i]._lunr = VisionList[i]._lradius;
1223 VisionList[i]._lx = x;
1224 VisionList[i]._ly = y;
1225 dovision = TRUE;
1226 }
1227 }
1228 }
1229
ProcessVisionList()1230 void ProcessVisionList()
1231 {
1232 int i;
1233 BOOL delflag;
1234
1235 if (dovision) {
1236 for (i = 0; i < numvision; i++) {
1237 if (VisionList[i]._ldel) {
1238 DoUnVision(VisionList[i]._lx, VisionList[i]._ly, VisionList[i]._lradius);
1239 }
1240 if (VisionList[i]._lunflag) {
1241 DoUnVision(VisionList[i]._lunx, VisionList[i]._luny, VisionList[i]._lunr);
1242 VisionList[i]._lunflag = FALSE;
1243 }
1244 }
1245 for (i = 0; i < TransVal; i++) {
1246 TransList[i] = FALSE;
1247 }
1248 for (i = 0; i < numvision; i++) {
1249 if (!VisionList[i]._ldel) {
1250 DoVision(
1251 VisionList[i]._lx,
1252 VisionList[i]._ly,
1253 VisionList[i]._lradius,
1254 VisionList[i]._lflags,
1255 VisionList[i]._lflags);
1256 }
1257 }
1258 do {
1259 delflag = FALSE;
1260 for (i = 0; i < numvision; i++) {
1261 if (VisionList[i]._ldel) {
1262 numvision--;
1263 if (numvision > 0 && i != numvision) {
1264 VisionList[i] = VisionList[numvision];
1265 }
1266 delflag = TRUE;
1267 }
1268 }
1269 } while (delflag);
1270 }
1271
1272 dovision = FALSE;
1273 }
1274
lighting_color_cycling()1275 void lighting_color_cycling()
1276 {
1277 int i, j, l;
1278 BYTE col;
1279 BYTE *tbl;
1280
1281 l = light4flag ? 4 : 16;
1282
1283 if (leveltype != DTYPE_HELL) {
1284 return;
1285 }
1286
1287 tbl = pLightTbl;
1288
1289 for (j = 0; j < l; j++) {
1290 tbl++;
1291 col = *tbl;
1292 for (i = 0; i < 30; i++) {
1293 tbl[0] = tbl[1];
1294 tbl++;
1295 }
1296 *tbl = col;
1297 tbl += 225;
1298 }
1299 }
1300
1301 DEVILUTION_END_NAMESPACE
1302