Atrinik Server  4.0
light.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * 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., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
30 #include <global.h>
31 #include <object.h>
32 
33 #define MAX_MASK_SIZE 81
34 #define NR_LIGHT_MASK 10
35 #define MAX_LIGHT_SOURCE 13
36 
37 static int lmask_x[MAX_MASK_SIZE] = {
38  0, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2, -2, -2, -2, -1,
39  0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3, -3, -3, -3, -3, -2, -1,
40  0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1, 0, -1, -2, -3, -4, -4, -4, -4, -4, -4, -4, -4, -4, -3, -2, -1
41 };
42 
43 static int lmask_y[MAX_MASK_SIZE] = {
44  0, -1, -1, 0, 1, 1, 1, 0, -1, -2, -2, -2, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2,
45  -3, -3, -3, -3, -2, -1, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3,
46  4, 4, 4, 4, 4, 3, 2, 1, 0, -1, -2, -3, -4, -4, -4, -4, -4, -4, -4, -4, -4, -3, -2, -1, 0, 1, 2, 3, 4, 4, 4, 4
47 };
48 
49 static int light_mask[MAX_LIGHT_SOURCE + 1] = {
50  0,
51  1,
52  2, 3,
53  4, 5, 6, 6,
54  7, 7, 8, 8,
55  8, 9
56 };
57 
58 static int light_mask_width[NR_LIGHT_MASK] = {
59  0, 1, 2, 2, 3,
60  3, 3, 4, 4, 4
61 };
62 
63 static int light_mask_size[NR_LIGHT_MASK] = {
64  0, 9, 25, 25, 49,
65  49, 49, 81, 81, 81
66 };
67 
68 static int light_masks[NR_LIGHT_MASK][MAX_MASK_SIZE] = {
69  {0,
70  0, 0, 0, 0, 0, 0, 0, 0,
71  0, 0, 0, 0, 0, 0, 0, 0,
72  0, 0, 0, 0, 0, 0, 0, 0,
73  0, 0, 0, 0, 0, 0, 0, 0,
74  0, 0, 0, 0, 0, 0, 0, 0,
75  0, 0, 0, 0, 0, 0, 0, 0,
76  0, 0, 0, 0, 0, 0, 0, 0,
77  0, 0, 0, 0, 0, 0, 0, 0,
78  0, 0, 0, 0, 0, 0, 0, 0,
79  0, 0, 0, 0, 0, 0, 0, 0, },
80  {40,
81  20, 20, 20, 20, 20, 20, 20, 20,
82  0, 0, 0, 0, 0, 0, 0, 0,
83  0, 0, 0, 0, 0, 0, 0, 0,
84  0, 0, 0, 0, 0, 0, 0, 0,
85  0, 0, 0, 0, 0, 0, 0, 0,
86  0, 0, 0, 0, 0, 0, 0, 0,
87  0, 0, 0, 0, 0, 0, 0, 0,
88  0, 0, 0, 0, 0, 0, 0, 0,
89  0, 0, 0, 0, 0, 0, 0, 0,
90  0, 0, 0, 0, 0, 0, 0, 0, },
91  {80,
92  40, 40, 40, 40, 40, 40, 40, 40,
93  20, 20, 20, 20, 20, 20, 20, 20,
94  20, 20, 20, 20, 20, 20, 20, 20,
95  0, 0, 0, 0, 0, 0, 0, 0,
96  0, 0, 0, 0, 0, 0, 0, 0,
97  0, 0, 0, 0, 0, 0, 0, 0,
98  0, 0, 0, 0, 0, 0, 0, 0,
99  0, 0, 0, 0, 0, 0, 0, 0,
100  0, 0, 0, 0, 0, 0, 0, 0,
101  0, 0, 0, 0, 0, 0, 0, 0, },
102  {160,
103  80, 80, 80, 80, 80, 80, 80, 80,
104  40, 40, 40, 40, 40, 40, 40, 40,
105  40, 40, 40, 40, 40, 40, 40, 40,
106  0, 0, 0, 0, 0, 0, 0, 0,
107  0, 0, 0, 0, 0, 0, 0, 0,
108  0, 0, 0, 0, 0, 0, 0, 0,
109  0, 0, 0, 0, 0, 0, 0, 0,
110  0, 0, 0, 0, 0, 0, 0, 0,
111  0, 0, 0, 0, 0, 0, 0, 0,
112  0, 0, 0, 0, 0, 0, 0, 0, },
113  {160,
114  80, 80, 80, 80, 80, 80, 80, 80,
115  40, 40, 40, 40, 40, 40, 40, 40,
116  40, 40, 40, 40, 40, 40, 40, 40,
117  20, 20, 20, 20, 20, 20, 20, 20,
118  20, 20, 20, 20, 20, 20, 20, 20,
119  20, 20, 20, 20, 20, 20, 20, 20,
120  0, 0, 0, 0, 0, 0, 0, 0,
121  0, 0, 0, 0, 0, 0, 0, 0,
122  0, 0, 0, 0, 0, 0, 0, 0,
123  0, 0, 0, 0, 0, 0, 0, 0, },
124  {320,
125  160, 160, 160, 160, 160, 160, 160, 160,
126  80, 80, 80, 80, 80, 80, 80, 80,
127  80, 80, 80, 80, 80, 80, 80, 80,
128  40, 40, 40, 40, 40, 40, 40, 40,
129  40, 40, 40, 40, 40, 40, 40, 40,
130  40, 40, 40, 40, 40, 40, 40, 40,
131  0, 0, 0, 0, 0, 0, 0, 0,
132  0, 0, 0, 0, 0, 0, 0, 0,
133  0, 0, 0, 0, 0, 0, 0, 0,
134  0, 0, 0, 0, 0, 0, 0, 0, },
135  {320,
136  160, 160, 160, 160, 160, 160, 160, 160,
137  80, 80, 80, 80, 80, 80, 80, 80,
138  80, 80, 80, 80, 80, 80, 80, 80,
139  40, 40, 40, 40, 40, 40, 40, 40,
140  40, 40, 40, 40, 40, 40, 40, 40,
141  40, 40, 40, 40, 40, 40, 40, 40,
142  0, 0, 0, 0, 0, 0, 0, 0,
143  0, 0, 0, 0, 0, 0, 0, 0,
144  0, 0, 0, 0, 0, 0, 0, 0,
145  0, 0, 0, 0, 0, 0, 0, 0, },
146  {320,
147  160, 160, 160, 160, 160, 160, 160, 160,
148  80, 80, 80, 80, 80, 80, 80, 80,
149  80, 80, 80, 80, 80, 80, 80, 80,
150  40, 40, 40, 40, 40, 40, 40, 40,
151  40, 40, 40, 40, 40, 40, 40, 40,
152  40, 40, 40, 40, 40, 40, 40, 40,
153  20, 20, 20, 20, 20, 20, 20, 20,
154  20, 20, 20, 20, 20, 20, 20, 20,
155  20, 20, 20, 20, 20, 20, 20, 20,
156  20, 20, 20, 20, 20, 20, 20, 20, },
157  {640,
158  320, 320, 320, 320, 320, 320, 320, 320,
159  160, 160, 160, 160, 160, 160, 160, 160,
160  160, 160, 160, 160, 160, 160, 160, 160,
161  80, 80, 80, 80, 80, 80, 80, 80,
162  80, 80, 80, 80, 80, 80, 80, 80,
163  80, 80, 80, 80, 80, 80, 80, 80,
164  40, 40, 40, 40, 40, 40, 40, 40,
165  40, 40, 40, 40, 40, 40, 40, 40,
166  40, 40, 40, 40, 40, 40, 40, 40,
167  40, 40, 40, 40, 40, 40, 40, 40, },
168  {1280,
169  640, 640, 640, 640, 640, 640, 640, 640,
170  160, 160, 160, 160, 160, 160, 160, 160,
171  160, 160, 160, 160, 160, 160, 160, 160,
172  80, 80, 80, 80, 80, 80, 80, 80,
173  80, 80, 80, 80, 80, 80, 80, 80,
174  80, 80, 80, 80, 80, 80, 80, 80,
175  40, 40, 40, 40, 40, 40, 40, 40,
176  40, 40, 40, 40, 40, 40, 40, 40,
177  40, 40, 40, 40, 40, 40, 40, 40,
178  40, 40, 40, 40, 40, 40, 40, 40, }
179 
180 };
181 
182 static int get_real_light_source_value(int l)
183 {
184  if (l > MAX_LIGHT_SOURCE) {
185  return light_mask[MAX_LIGHT_SOURCE];
186  }
187 
188  if (l < -MAX_LIGHT_SOURCE) {
189  return -light_mask[MAX_LIGHT_SOURCE];
190  }
191 
192  if (l < 0) {
193  return -light_mask[-l];
194  }
195 
196  return light_mask[l];
197 }
198 
199 static int light_mask_adjust(mapstruct *map, int x, int y, int intensity, int mod, mapstruct *restore_map, int other_only)
200 {
201  MapSpace *msp;
202  mapstruct *m;
203  int xt, yt, i, mlen, map_flag = 0;
204 
205  if (intensity < 0) {
206  mod = -mod;
207  }
208 
209  intensity = abs(intensity);
210  mlen = light_mask_size[intensity];
211 
212  for (i = 0; i < mlen; i++) {
213  xt = x + lmask_x[i];
214  yt = y + lmask_y[i];
215 
216  if (!(m = get_map_from_coord2(map, &xt, &yt))) {
217  if (xt) {
218  map_flag = 1;
219  }
220 
221  continue;
222  }
223 
224  if (restore_map && m != restore_map) {
225  continue;
226  }
227 
228  if (other_only && m == map) {
229  continue;
230  }
231 
232  /* This light mask crosses some tiled map borders */
233  if (m != map) {
234  map_flag = 1;
235  }
236 
237  msp = GET_MAP_SPACE_PTR(m, xt, yt);
238  msp->light_value += light_masks[intensity][i] * mod;
239  }
240 
241  return map_flag;
242 }
243 
257 void adjust_light_source(mapstruct *map, int x, int y, int light)
258 {
259  int nlm, olm;
260  MapSpace *msp1 = GET_MAP_SPACE_PTR(map, x, y);
261 
262  /* this happens, we don't change the intense of the old light mask */
263  /* old mask */
264  olm = get_real_light_source_value(msp1->light_source);
265  msp1->light_source += light;
266  /* new mask */
267  nlm = get_real_light_source_value(msp1->light_source);
268 
269  /* Old mask same as new one? not much to do */
270  if (nlm == olm) {
271  return;
272  }
273 
274  if (olm) {
275  /* Remove the old light mask */
276  light_mask_adjust(map, x, y, olm, -1, NULL, 0);
277 
278  /* Perhaps we are in this list - perhaps we are not */
279  if (msp1->prev_light) {
280  msp1->prev_light->next_light = msp1->next_light;
281  } else {
282  /* We are the list head */
283  if (map->first_light == msp1) {
284  map->first_light = msp1->next_light;
285  }
286  }
287 
288  /* Handle next link */
289  if (msp1->next_light) {
290  msp1->next_light->prev_light = msp1->prev_light;
291  }
292 
293  msp1->prev_light = NULL;
294  msp1->next_light = NULL;
295  }
296 
297  if (nlm) {
298  /* Add new light mask */
299  if (light_mask_adjust(map, x, y, nlm, 1, NULL, 0)) {
300  /* Don't chain if we are chained previous */
301  if (msp1->next_light || msp1->prev_light || map->first_light == msp1) {
302  return;
303  }
304 
305  /* We should be always unlinked here - so link it now */
306  msp1->next_light = map->first_light;
307 
308  if (map->first_light) {
309  msp1->next_light->prev_light = msp1;
310  }
311 
312  map->first_light = msp1;
313  }
314  }
315 }
316 
325 {
326  int i, intensity, x, y, reaching;
327  mapstruct *m;
328  MapSpace *tmp;
329 
330  for (i = 0; i < TILED_NUM_DIR; i++) {
331  m = map->tile_map[i];
332 
333  if (m && (m->in_memory == MAP_IN_MEMORY || m->in_memory == MAP_LOADING) && m->first_light) {
334  for (tmp = m->first_light; tmp; tmp = tmp->next_light) {
335  if (!tmp->first) {
336  continue;
337  }
338 
339  intensity = get_real_light_source_value(tmp->light_source);
340 
341  x = tmp->first->x;
342  y = tmp->first->y;
343  reaching = 1;
344 
345  switch (i) {
346  case TILED_NORTH:
347 
348  if (y + light_mask_width[abs(intensity)] < MAP_HEIGHT(m)) {
349  reaching = 0;
350  }
351 
352  break;
353 
354  case TILED_EAST:
355 
356  if (x - light_mask_width[abs(intensity)] >= 0) {
357  reaching = 0;
358  }
359 
360  break;
361 
362  case TILED_SOUTH:
363 
364  if (y - light_mask_width[abs(intensity)] >= 0) {
365  reaching = 0;
366  }
367 
368  break;
369 
370  case TILED_WEST:
371 
372  if (x + light_mask_width[abs(intensity)] < MAP_WIDTH(m)) {
373  reaching = 0;
374  }
375 
376  break;
377 
378  case TILED_NORTHEAST:
379 
380  if ((y + light_mask_width[abs(intensity)]) < MAP_HEIGHT(m) || (x - light_mask_width[abs(intensity)]) >= 0) {
381  reaching = 0;
382  }
383 
384  break;
385 
386  case TILED_SOUTHEAST:
387 
388  if ((x - light_mask_width[abs(intensity)]) >= 0 || (y - light_mask_width[abs(intensity)]) >= 0) {
389  reaching = 0;
390  }
391 
392  break;
393 
394  case TILED_SOUTHWEST:
395 
396  if ((y - light_mask_width[abs(intensity)]) >= 0 || (x + light_mask_width[abs(intensity)]) < MAP_WIDTH(m)) {
397  reaching = 0;
398  }
399 
400  break;
401 
402  case TILED_NORTHWEST:
403 
404  if ((y + light_mask_width[abs(intensity)]) < MAP_HEIGHT(m) || (x + light_mask_width[abs(intensity)]) < MAP_WIDTH(m)) {
405  reaching = 0;
406  }
407 
408  break;
409  }
410 
411  if (reaching) {
412  light_mask_adjust(m, x, y, intensity, 1, map, 0);
413  }
414  }
415  }
416  }
417 }
418 
425 {
426  MapSpace *tmp;
427 
428  for (tmp = map->first_light; tmp; tmp = tmp->next_light) {
429  if (!tmp->first) {
430  continue;
431  }
432 
433  light_mask_adjust(map, tmp->first->x, tmp->first->y, get_real_light_source_value(tmp->light_source), -1, NULL, 1);
434  }
435 
436  map->first_light = NULL;
437 }
#define TILED_NUM_DIR
Definition: global.h:210
#define MAP_IN_MEMORY
Definition: map.h:170
#define TILED_EAST
Definition: global.h:189
mapstruct * get_map_from_coord2(mapstruct *m, int *x, int *y)
Definition: map.c:2000
#define MAP_WIDTH(m)
Definition: map.h:120
int32_t light_value
Definition: map.h:375
uint32_t in_memory
Definition: map.h:627
MapSpace * first_light
Definition: map.h:577
#define TILED_SOUTHWEST
Definition: global.h:199
#define TILED_NORTH
Definition: global.h:187
#define TILED_SOUTH
Definition: global.h:191
int16_t y
Definition: object.h:276
#define TILED_NORTHEAST
Definition: global.h:195
int32_t light_source
Definition: map.h:369
struct mapdef * tile_map[TILED_NUM]
Definition: map.h:550
object * first
Definition: map.h:336
#define MAP_HEIGHT(m)
Definition: map.h:122
#define TILED_SOUTHEAST
Definition: global.h:197
int16_t x
Definition: object.h:273
void adjust_light_source(mapstruct *map, int x, int y, int light)
Definition: light.c:257
#define TILED_NORTHWEST
Definition: global.h:201
void remove_light_source_list(mapstruct *map)
Definition: light.c:424
struct MapSpace_s * next_light
Definition: map.h:354
struct MapSpace_s * prev_light
Definition: map.h:351
void check_light_source_list(mapstruct *map)
Definition: light.c:324
#define TILED_WEST
Definition: global.h:193
Definition: map.h:536
#define MAP_LOADING
Definition: map.h:174