Crossfire Client, Trunk
mapdata.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
19 #include "client.h"
20 
21 #include <assert.h>
22 #include <stdbool.h>
23 
24 #include "external.h"
25 #include "mapdata.h"
26 
31 
37 
39 int move_to_x = 0, move_to_y = 0;
40 bool move_to_attack = false;
41 
45 #define FOG_MAP_SIZE 512
46 
51 #define FOG_BORDER_MIN 128
52 
56 #define MAX_FACE_SIZE 16
57 
58 /* Max it can currently be. Important right now because
59  * animation has to look at everything that may be viewable,
60  * and reducing this size basically reduces processing it needs
61  * to do by 75% (64^2 vs 33^2)
62  */
63 #define CURRENT_MAX_VIEW 33
64 
78 struct BigCell {
79  struct BigCell *next;
80  struct BigCell *prev;
81 
84 
85  guint16 x, y;
86  guint8 layer;
87 };
88 
89 /* Global map rendering offsets used for local scroll prediction. */
92 int want_offset_x = 0;
93 int want_offset_y = 0;
94 
95 static void recenter_virtual_map_view(int diff_x, int diff_y);
96 static void mapdata_get_image_size(int face, guint8 *w, guint8 *h);
97 static void expand_need_update(int x, int y, int w, int h);
98 static void expand_need_update_from_layer(int x, int y, int layer);
99 
100 static int width; //< width of current map view
101 static int height; //< height of current map view
102 
107 static struct BigCell *bigfaces_head;
108 
115 
116 static struct Map the_map;
117 
121 static void clear_cells(int x, int y, int len_y) {
122  int clear_cells_i, j;
123  memset(mapdata_cell(x, y), 0, sizeof(struct MapCell)*len_y);
124 
125  for (clear_cells_i = 0; clear_cells_i < (len_y); clear_cells_i++) {
126  struct MapCell *cell = mapdata_cell(x, y+clear_cells_i);
127  for (j=0; j < MAXLAYERS; j++) {
128  cell->heads[j].size_x = 1;
129  cell->heads[j].size_y = 1;
130  }
131  }
132 }
133 
134 extern void mapdata_clear_label(int px, int py);
135 
139 inline struct MapCell *mapdata_cell(const int x, const int y) {
140  return &the_map._cells[x][y];
141 }
142 
146 bool mapdata_contains(int x, int y) {
147  if (x < 0 || y < 0 || the_map.width <= x || the_map.height <= y) {
148  return false;
149  }
150 
151  return true;
152 }
153 
154 bool mapdata_can_smooth(int x, int y, int layer) {
155  return (mapdata_cell(x, y)->heads[layer].face == 0 && layer > 0) ||
156  mapdata_cell(x, y)->smooth[layer];
157 }
158 
162 void mapdata_size(int *x, int *y) {
163  if (x != NULL) {
164  *x = the_map.width;
165  }
166 
167  if (y != NULL) {
168  *y = the_map.height;
169  }
170 }
171 
180 static void set_darkness(int x, int y, int darkness)
181 {
182  if (mapdata_cell(x, y)->darkness == darkness) {
183  return;
184  }
185 
186  mapdata_cell(x, y)->darkness = darkness;
187  mapdata_cell(x, y)->need_update = 1;
188 }
189 
195 void mapdata_clear(int x, int y) {
196  int px = pl_pos.x + x;
197  int py = pl_pos.y + y;
198  assert(0 <= px && px < the_map.width);
199  assert(0 <= py && py < the_map.height);
200 
201  if (mapdata_cell(px, py) == EMPTY)
202  return;
203 
204  if (mapdata_cell(px, py)->state == VISIBLE) {
205  mapdata_cell(px, py)->need_update = 1;
206  for (int i = 0; i < MAXLAYERS; i++) {
207  if (mapdata_cell(px, py)->heads[i].face) {
209  }
210  }
211  }
212 
213  mapdata_cell(px, py)->state = FOG;
214  mapdata_clear_label(px, py);
215 }
216 
217 static void mark_resmooth(int x, int y, int layer)
218 {
219  int sdx,sdy;
220  if (mapdata_cell(x, y)->smooth[layer]>1) {
221  for (sdx=-1; sdx<2; sdx++)
222  for (sdy=-1; sdy<2; sdy++)
223  if ( (sdx || sdy) /* ignore (0,0) */
224  && ( (x+sdx >0) && (x+sdx < the_map.width) && /* only inside map */
225  (y+sdy >0) && (y+sdy < the_map.height) ) ) {
226  mapdata_cell(x+sdx, y+sdy)->need_resmooth=1;
227  }
228  }
229 }
238 static void expand_clear_face(int x, int y, int w, int h, int layer)
239 {
240  int dx, dy;
241  struct MapCell *cell;
242 
243  assert(0 <= x && x < the_map.width);
244  assert(0 <= y && y < the_map.height);
245  assert(1 <= w && w <= MAX_FACE_SIZE);
246  assert(1 <= h && h <= MAX_FACE_SIZE);
247 
248  assert(0 <= x-w+1 && x-w+1 < the_map.width);
249  assert(0 <= y-h+1 && y-h+1 < the_map.height);
250 
251  cell = mapdata_cell(x, y);
252 
253  for (dx = 0; dx < w; dx++) {
254  for (dy = !dx; dy < h; dy++) {
255  struct MapCellTailLayer *tail = &mapdata_cell(x-dx, y-dy)->tails[layer];
256  assert(0 <= x-dx && x-dx < the_map.width);
257  assert(0 <= y-dy && y-dy < the_map.height);
258  assert(0 <= layer && layer < MAXLAYERS);
259 
260  /* Do not clear faces that already have been overwritten by another
261  * face.
262  */
263  if (tail->face == cell->heads[layer].face
264  && tail->size_x == dx
265  && tail->size_y == dy) {
266  tail->face = 0;
267  tail->size_x = 0;
268  tail->size_y = 0;
269  mapdata_cell(x-dx, y-dy)->need_update = 1;
270  }
271  mark_resmooth(x-dx,y-dy,layer);
272  }
273  }
274 
275  cell->heads[layer].face = 0;
276  cell->heads[layer].animation = 0;
277  cell->heads[layer].animation_speed = 0;
278  cell->heads[layer].animation_left = 0;
279  cell->heads[layer].animation_phase = 0;
280  cell->heads[layer].size_x = 1;
281  cell->heads[layer].size_y = 1;
282  cell->need_update = 1;
283  cell->need_resmooth = 1;
284  mark_resmooth(x,y,layer);
285 }
286 
293 static void expand_clear_face_from_layer(int x, int y, int layer)
294 {
295  const struct MapCellLayer *cell;
296 
297  assert(0 <= x && x < the_map.width);
298  assert(0 <= y && y < the_map.height);
299  assert(0 <= layer && layer < MAXLAYERS);
300 
301  cell = &mapdata_cell(x, y)->heads[layer];
302  if (cell->size_x && cell->size_y) {
303  expand_clear_face(x, y, cell->size_x, cell->size_y, layer);
304  }
305 }
306 
320 static void expand_set_face(int x, int y, int layer, gint16 face, int clear)
321 {
322  struct MapCell *cell;
323  int dx, dy;
324  guint8 w, h;
325 
326  assert(0 <= x && x < the_map.width);
327  assert(0 <= y && y < the_map.height);
328  assert(0 <= layer && layer < MAXLAYERS);
329 
330  cell = mapdata_cell(x, y);
331 
332  if (clear) {
333  expand_clear_face_from_layer(x, y, layer);
334  }
335 
336  mapdata_get_image_size(face, &w, &h);
337  assert(1 <= w && w <= MAX_FACE_SIZE);
338  assert(1 <= h && h <= MAX_FACE_SIZE);
339  cell->heads[layer].face = face;
340  cell->heads[layer].size_x = w;
341  cell->heads[layer].size_y = h;
342  cell->need_update=1;
343  mark_resmooth(x,y,layer);
344 
345  for (dx = 0; dx < w; dx++) {
346  for (dy = !dx; dy < h; dy++) {
347  struct MapCellTailLayer *tail = &mapdata_cell(x-dx, y-dy)->tails[layer];
348  assert(0 <= x-dx && x-dx < the_map.width);
349  assert(0 <= y-dy && y-dy < the_map.height);
350  assert(0 <= layer && layer < MAXLAYERS);
351 
352  tail->face = face;
353  tail->size_x = dx;
354  tail->size_y = dy;
355  mapdata_cell(x-dx, y-dy)->need_update = 1;
356  mark_resmooth(x-dx,y-dy,layer);
357  }
358  }
359 }
360 
371 static void expand_clear_bigface(int x, int y, int w, int h, int layer, int set_need_update)
372 {
373  int dx, dy;
374  struct MapCellLayer *head;
375 
376  assert(0 <= x && x < MAX_VIEW);
377  assert(0 <= y && y < MAX_VIEW);
378  assert(1 <= w && w <= MAX_FACE_SIZE);
379  assert(1 <= h && h <= MAX_FACE_SIZE);
380 
381  head = &bigfaces[x][y][layer].head;
382 
383  for (dx = 0; dx < w && dx <= x; dx++) {
384  for (dy = !dx; dy < h && dy <= y; dy++) {
385  struct MapCellTailLayer *tail = &bigfaces[x-dx][y-dy][layer].tail;
386  assert(0 <= x-dx && x-dx < MAX_VIEW);
387  assert(0 <= y-dy && y-dy < MAX_VIEW);
388  assert(0 <= layer && layer < MAXLAYERS);
389 
390  /* Do not clear faces that already have been overwritten by another
391  * face.
392  */
393  if (tail->face == head->face
394  && tail->size_x == dx
395  && tail->size_y == dy) {
396  tail->face = 0;
397  tail->size_x = 0;
398  tail->size_y = 0;
399 
400  if (0 <= x-dx && x-dx < width
401  && 0 <= y-dy && y-dy < height) {
402  assert(0 <= pl_pos.x+x-dx && pl_pos.x+x-dx < the_map.width);
403  assert(0 <= pl_pos.y+y-dy && pl_pos.y+y-dy < the_map.height);
404  if (set_need_update) {
405  mapdata_cell(pl_pos.x+x-dx, pl_pos.y+y-dy)->need_update = 1;
406  }
407  }
408  }
409  }
410  }
411 
412  head->face = 0;
413  head->size_x = 1;
414  head->size_y = 1;
415 }
416 
425 static void expand_clear_bigface_from_layer(int x, int y, int layer, int set_need_update)
426 {
427  struct BigCell *headcell;
428  const struct MapCellLayer *head;
429 
430  assert(0 <= x && x < MAX_VIEW);
431  assert(0 <= y && y < MAX_VIEW);
432  assert(0 <= layer && layer < MAXLAYERS);
433 
434  headcell = &bigfaces[x][y][layer];
435  head = &headcell->head;
436  if (head->face != 0) {
437  assert(headcell->prev != NULL || headcell == bigfaces_head);
438 
439  /* remove from bigfaces_head list */
440  if (headcell->prev != NULL) {
441  headcell->prev->next = headcell->next;
442  }
443  if (headcell->next != NULL) {
444  headcell->next->prev = headcell->prev;
445  }
446  if (bigfaces_head == headcell) {
447  assert(headcell->prev == NULL);
448  bigfaces_head = headcell->next;
449  } else {
450  assert(headcell->prev != NULL);
451  }
452  headcell->prev = NULL;
453  headcell->next = NULL;
454 
455  expand_clear_bigface(x, y, head->size_x, head->size_y, layer, set_need_update);
456  } else {
457  assert(headcell->prev == NULL && headcell != bigfaces_head);
458  assert(head->size_x == 1);
459  assert(head->size_y == 1);
460  }
461 }
462 
471 static void expand_set_bigface(int x, int y, int layer, gint16 face, int clear)
472 {
473  struct BigCell *headcell;
474  struct MapCellLayer *head;
475  int dx, dy;
476  guint8 w, h;
477 
478  assert(0 <= x && x < MAX_VIEW);
479  assert(0 <= y && y < MAX_VIEW);
480  assert(0 <= layer && layer < MAXLAYERS);
481 
482  headcell = &bigfaces[x][y][layer];
483  head = &headcell->head;
484  if (clear) {
485  expand_clear_bigface_from_layer(x, y, layer, 1);
486  }
487 
488  /* add to bigfaces_head list */
489  if (face != 0) {
490  assert(headcell->prev == NULL);
491  assert(headcell->next == NULL);
492  assert(headcell != bigfaces_head);
493  if (bigfaces_head != NULL) {
494  assert(bigfaces_head->prev == NULL);
495  bigfaces_head->prev = headcell;
496  }
497  headcell->next = bigfaces_head;
498  bigfaces_head = headcell;
499  }
500 
501  mapdata_get_image_size(face, &w, &h);
502  assert(1 <= w && w <= MAX_FACE_SIZE);
503  assert(1 <= h && h <= MAX_FACE_SIZE);
504  head->face = face;
505  head->size_x = w;
506  head->size_y = h;
507 
508  for (dx = 0; dx < w && dx <= x; dx++) {
509  for (dy = !dx; dy < h && dy <= y; dy++) {
510  struct MapCellTailLayer *tail = &bigfaces[x-dx][y-dy][layer].tail;
511  assert(0 <= x-dx && x-dx < MAX_VIEW);
512  assert(0 <= y-dy && y-dy < MAX_VIEW);
513  assert(0 <= layer && layer < MAXLAYERS);
514 
515  tail->face = face;
516  tail->size_x = dx;
517  tail->size_y = dy;
518 
519  if (0 <= x-dx && x-dx < width
520  && 0 <= y-dy && y-dy < height) {
521  assert(0 <= pl_pos.x+x-dx && pl_pos.x+x-dx < the_map.width);
522  assert(0 <= pl_pos.y+y-dy && pl_pos.y+y-dy < the_map.height);
523  mapdata_cell(pl_pos.x+x-dx, pl_pos.y+y-dy)->need_update = 1;
524  }
525  }
526  }
527 }
528 
536 static void expand_need_update(int x, int y, int w, int h)
537 {
538  int dx, dy;
539 
540  assert(0 <= x && x < the_map.width);
541  assert(0 <= y && y < the_map.height);
542  assert(1 <= w && w <= MAX_FACE_SIZE);
543  assert(1 <= h && h <= MAX_FACE_SIZE);
544 
545  assert(0 <= x-w+1 && x-w+1 < the_map.width);
546  assert(0 <= y-h+1 && y-h+1 < the_map.height);
547 
548  for (dx = 0; dx < w; dx++) {
549  for (dy = 0; dy < h; dy++) {
550  struct MapCell *cell = mapdata_cell(x-dx, y-dy);
551  assert(0 <= x-dx && x-dx < the_map.width);
552  assert(0 <= y-dy && y-dy < the_map.height);
553  cell->need_update = 1;
554  }
555  }
556 }
557 
564 static void expand_need_update_from_layer(int x, int y, int layer)
565 {
566  struct MapCellLayer *head;
567 
568  assert(0 <= x && x < the_map.width);
569  assert(0 <= y && y < the_map.height);
570  assert(0 <= layer && layer < MAXLAYERS);
571 
572  head = &mapdata_cell(x, y)->heads[layer];
573  if (head->face != 0) {
574  expand_need_update(x, y, head->size_x, head->size_y);
575  } else {
576  assert(head->size_x == 1);
577  assert(head->size_y == 1);
578  }
579 }
580 
585 static void mapdata_alloc(struct Map* const map, const int width, const int height) {
586  map->_cells = (struct MapCell **)g_new(struct MapCell, width * (height + 1));
587  g_assert(map->_cells != NULL); // g_new() always succeeds
588  map->width = width;
589  map->height = height;
590 
591  /* Skip past the first row of pointers to rows and assign the
592  * start of the actual map data
593  */
594  map->_cells[0] = (struct MapCell *)((char *)map->_cells+(sizeof(struct MapCell *)*map->width));
595 
596  /* Finish assigning the beginning of each row relative to the
597  * first row assigned above
598  */
599  for (int i = 0; i < map->width; i++) {
600  map->_cells[i] = map->_cells[0]+i*map->height;
601  }
602 }
603 
604 static void mapdata_init(void)
605 {
606  int x, y;
607  int i;
608 
610 
611  width = 0;
612  height = 0;
613  pl_pos.x = the_map.width/2-width/2;
614  pl_pos.y = the_map.height/2-height/2;
615 
616  for (x = 0; x < the_map.width; x++) {
617  clear_cells(x, 0, the_map.height);
618  }
619 
620  for (y = 0; y < MAX_VIEW; y++) {
621  for (x = 0; x < MAX_VIEW; x++) {
622  for (i = 0; i < MAXLAYERS; i++) {
623  bigfaces[x][y][i].next = NULL;
624  bigfaces[x][y][i].prev = NULL;
625  bigfaces[x][y][i].head.face = 0;
626  bigfaces[x][y][i].head.size_x = 1;
627  bigfaces[x][y][i].head.size_y = 1;
628  bigfaces[x][y][i].tail.face = 0;
629  bigfaces[x][y][i].tail.size_x = 0;
630  bigfaces[x][y][i].tail.size_y = 0;
631  bigfaces[x][y][i].x = x;
632  bigfaces[x][y][i].y = y;
633  bigfaces[x][y][i].layer = i;
634  }
635  }
636  }
637  bigfaces_head = NULL;
638 
639  global_offset_x = 0;
640  global_offset_y = 0;
641  want_offset_x = 0;
642  want_offset_y = 0;
643 }
644 
645 void mapdata_free(void) {
646  if (the_map._cells != NULL) {
647  g_free(the_map._cells);
648  the_map._cells = NULL;
649  the_map.width = 0;
650  the_map.height = 0;
651  }
652 }
653 
654 void mapdata_set_size(int viewx, int viewy)
655 {
656  mapdata_free();
657  mapdata_init();
658 
659  width = viewx;
660  height = viewy;
661  pl_pos.x = the_map.width/2-width/2;
662  pl_pos.y = the_map.height/2-height/2;
663 }
664 
665 int mapdata_is_inside(int x, int y)
666 {
667  return(x >= 0 && x < width && y >= 0 && y < height);
668 }
669 
670 /* mapdate_clear_space() is used by Map2Cmd()
671  * Basically, server has told us there is nothing on
672  * this space. So clear it.
673  */
674 void mapdata_clear_space(int x, int y)
675 {
676  int px, py;
677  int i;
678 
679  assert(0 <= x && x < MAX_VIEW);
680  assert(0 <= y && y < MAX_VIEW);
681 
682  px = pl_pos.x+x;
683  py = pl_pos.y+y;
684  assert(0 <= px && px < the_map.width);
685  assert(0 <= py && py < the_map.height);
686 
687  if (x < width && y < height) {
688  /* tile is visible */
689  /* visible tile is now blank ==> do not clear but mark as cleared */
690  mapdata_clear(x, y);
691  } else {
692  /* tile is invisible (outside view area, i.e. big face update) */
693 
694  for (i = 0; i < MAXLAYERS; i++) {
695  expand_set_bigface(x, y, i, 0, TRUE);
696  }
697  }
698 }
699 
700 
701 /* With map2, we basically process a piece of data at a time. Thus,
702  * for each piece, we don't know what the final state of the space
703  * will be. So once Map2Cmd() has processed all the information for
704  * a space, it calls mapdata_set_check_space() which can see if
705  * the space is cleared or other inconsistencies.
706  */
707 void mapdata_set_check_space(int x, int y)
708 {
709  int px, py;
710  int is_blank;
711  int i;
712  struct MapCell *cell;
713 
714  assert(0 <= x && x < MAX_VIEW);
715  assert(0 <= y && y < MAX_VIEW);
716 
717  px = pl_pos.x+x;
718  py = pl_pos.y+y;
719 
720  assert(0 <= px && px < the_map.width);
721  assert(0 <= py && py < the_map.height);
722 
723 
724  is_blank=1;
725  cell = mapdata_cell(px, py);
726  for (i=0; i < MAXLAYERS; i++) {
727  if (cell->heads[i].face>0 || cell->tails[i].face>0) {
728  is_blank=0;
729  break;
730  }
731  }
732 
733  if (cell->darkness != 0) {
734  is_blank=0;
735  }
736 
737  /* We only care if this space needs to be blanked out */
738  if (!is_blank) {
739  return;
740  }
741 
742  if (x < width && y < height) {
743  /* tile is visible */
744 
745  /* visible tile is now blank ==> do not clear but mark as cleared */
746  mapdata_clear(x, y);
747  }
748 }
749 
750 
751 
752 /* This just sets the darkness for a space.
753  * Used by Map2Cmd()
754  */
755 void mapdata_set_darkness(int x, int y, int darkness)
756 {
757  int px, py;
758 
759  assert(0 <= x && x < MAX_VIEW);
760  assert(0 <= y && y < MAX_VIEW);
761 
762  px = pl_pos.x+x;
763  py = pl_pos.y+y;
764  assert(0 <= px && px < the_map.width);
765  assert(0 <= py && py < the_map.height);
766 
767  /* Ignore darkness information for tile outside the viewable area: if
768  * such a tile becomes visible again, it is either "fog of war" (and
769  * darkness information is ignored) or it will be updated (including
770  * the darkness information).
771  */
772  if (darkness != -1 && x < width && y < height) {
773  set_darkness(px, py, 255-darkness);
774  }
775 }
776 
777 /* Sets smooth information for layer */
778 void mapdata_set_smooth(int x, int y, guint8 smooth, int layer)
779 {
780  static int dx[8]= {0,1,1,1,0,-1,-1,-1};
781  static int dy[8]= {-1,-1,0,1,1,1,0,-1};
782  int rx, ry, px, py, i;
783 
784  assert(0 <= x && x < MAX_VIEW);
785  assert(0 <= y && y < MAX_VIEW);
786 
787  px = pl_pos.x+x;
788  py = pl_pos.y+y;
789  assert(0 <= px && px < the_map.width);
790  assert(0 <= py && py < the_map.height);
791 
792  if (mapdata_cell(px, py)->smooth[layer] != smooth) {
793  for (i=0; i<8; i++) {
794  rx=px+dx[i];
795  ry=py+dy[i];
796  if ( (rx<0) || (ry<0) || (the_map.width<=rx) || (the_map.height<=ry)) {
797  continue;
798  }
799  mapdata_cell(rx, ry)->need_resmooth=1;
800  }
801  mapdata_cell(px, py)->need_resmooth=1;
802  mapdata_cell(px, py)->smooth[layer] = smooth;
803  }
804 }
805 
806 void mapdata_add_label(int x, int y, int subtype, const char *label) {
807  assert(0 <= x && x < MAX_VIEW);
808  assert(0 <= y && y < MAX_VIEW);
809  if (!(x < width && y < height))
810  return;
811 
812  int px = pl_pos.x + x;
813  int py = pl_pos.y + y;
814  assert(0 <= px && px < the_map.width);
815  assert(0 <= py && py < the_map.height);
816 
817  if (subtype == 0) {
818  mapdata_clear_label(px, py);
819  return;
820  }
821 
822  struct MapLabel *new = g_malloc(sizeof(struct MapLabel));
823  new->subtype = subtype;
824  new->label = g_strdup(label);
825  new->next = mapdata_cell(px, py)->label;
826  mapdata_cell(px, py)->label = new;
827  mapdata_cell(px, py)->need_update = 1;
828 }
829 
830 void mapdata_clear_label(int px, int py) {
831  while (mapdata_cell(px, py)->label != NULL) {
832  struct MapLabel *next = mapdata_cell(px, py)->label->next;
833  g_free(mapdata_cell(px, py)->label->label);
834  g_free(mapdata_cell(px, py)->label);
835  mapdata_cell(px, py)->label = next;
836  }
837 }
838 
844 void mapdata_clear_old(int x, int y)
845 {
846  assert(0 <= x && x < MAX_VIEW);
847  assert(0 <= y && y < MAX_VIEW);
848  if (!(x < width && y < height))
849  return;
850 
851  int px = pl_pos.x + x;
852  int py = pl_pos.y + y;
853  assert(0 <= px && px < the_map.width);
854  assert(0 <= py && py < the_map.height);
855 
856  // In theory we only have to do this if this is a fog of war tile, because
857  // the server remembers what tiles are visible to us and sends the
858  // appropriate darkness updates.
859  if (mapdata_cell(px, py)->state == FOG) {
860  mapdata_cell(px, py)->need_update = 1;
861  for (int i = 0; i < MAXLAYERS; i++) {
862  expand_clear_face_from_layer(px, py, i);
863  }
864  mapdata_cell(px, py)->darkness = 0;
865  mapdata_clear_label(px, py);
866  }
867 
868  mapdata_cell(px, py)->state = VISIBLE;
869 }
870 
871 /* This is vaguely related to the mapdata_set_face() above, but rather
872  * than take all the faces, takes 1 face and the layer this face is
873  * on. This is used by the Map2Cmd()
874  */
875 void mapdata_set_face_layer(int x, int y, gint16 face, int layer)
876 {
877  int px, py;
878 
879  assert(0 <= x && x < MAX_VIEW);
880  assert(0 <= y && y < MAX_VIEW);
881 
882  px = pl_pos.x+x;
883  py = pl_pos.y+y;
884  assert(0 <= px && px < the_map.width);
885  assert(0 <= py && py < the_map.height);
886 
887  if (x < width && y < height) {
888  mapdata_cell(px, py)->need_update = 1;
889  if (face >0) {
890  expand_set_face(px, py, layer, face, TRUE);
891  } else {
892  expand_clear_face_from_layer(px, py, layer);
893  }
894  } else {
895  expand_set_bigface(x, y, layer, face, TRUE);
896  }
897 }
898 
899 
900 /* This is vaguely related to the mapdata_set_face() above, but rather
901  * than take all the faces, takes 1 face and the layer this face is
902  * on. This is used by the Map2Cmd()
903  */
904 void mapdata_set_anim_layer(int x, int y, guint16 anim, guint8 anim_speed, int layer)
905 {
906  int px, py;
907  int i, face, animation, phase, speed_left;
908 
909  assert(0 <= x && x < MAX_VIEW);
910  assert(0 <= y && y < MAX_VIEW);
911 
912  px = pl_pos.x+x;
913  py = pl_pos.y+y;
914  assert(0 <= px && px < the_map.width);
915  assert(0 <= py && py < the_map.height);
916 
917  animation = anim & ANIM_MASK;
918  face = 0;
919 
920  /* Random animation is pretty easy */
921  if ((anim & ANIM_FLAGS_MASK) == ANIM_RANDOM) {
922  const guint8 num_animations = animations[animation].num_animations;
923  if (num_animations == 0) {
924  LOG(LOG_WARNING, "mapdata_set_anim_layer",
925  "animating object with zero animations");
926  return;
927  }
928  phase = g_random_int() % num_animations;
929  face = animations[animation].faces[phase];
930  speed_left = anim_speed % g_random_int();
931  } else if ((anim & ANIM_FLAGS_MASK) == ANIM_SYNC) {
932  animations[animation].speed = anim_speed;
933  phase = animations[animation].phase;
934  speed_left = animations[animation].speed_left;
935  face = animations[animation].faces[phase];
936  }
937 
938  if (x < width && y < height) {
939  mapdata_clear_old(x, y);
940  if (face >0) {
941  expand_set_face(px, py, layer, face, TRUE);
942  mapdata_cell(px, py)->heads[layer].animation = animation;
943  mapdata_cell(px, py)->heads[layer].animation_phase = phase;
944  mapdata_cell(px, py)->heads[layer].animation_speed = anim_speed;
945  mapdata_cell(px, py)->heads[layer].animation_left = speed_left;
946  } else {
947  expand_clear_face_from_layer(px, py, layer);
948  }
949  } else {
950  expand_set_bigface(x, y, layer, face, TRUE);
951  }
952 }
953 
954 
955 void mapdata_scroll(int dx, int dy)
956 {
957  script_pos.x += dx;
958  script_pos.y += dy;
959  int x, y;
960 
962 
964  struct BigCell *cell;
965 
966  /* Mark all tiles as "need_update" that are overlapped by a big face
967  * from outside the view area.
968  */
969  for (cell = bigfaces_head; cell != NULL; cell = cell->next) {
970  for (x = 0; x < cell->head.size_x; x++) {
971  for (y = !x; y < cell->head.size_y; y++) {
972  if (0 <= cell->x-x && cell->x-x < width
973  && 0 <= cell->y-y && cell->y-y < height) {
974  mapdata_cell(pl_pos.x+cell->x-x, pl_pos.y+cell->y-y)->need_update = 1;
975  }
976  }
977  }
978  }
979  } else {
980  /* Emulate map scrolling by redrawing all tiles. */
981  for (x = 0; x < width; x++) {
982  for (y = 0; y < height; y++) {
984  }
985  }
986  }
987 
988  pl_pos.x += dx;
989  pl_pos.y += dy;
990 
991  /* clear all newly visible tiles */
992  if (dx > 0) {
993  for (y = 0; y < height; y++) {
994  for (x = width-dx; x < width; x++) {
995  mapdata_clear(x, y);
996  }
997  }
998  } else {
999  for (y = 0; y < height; y++) {
1000  for (x = 0; x < -dx; x++) {
1001  mapdata_clear(x, y);
1002  }
1003  }
1004  }
1005 
1006  if (dy > 0) {
1007  for (x = 0; x < width; x++) {
1008  for (y = height-dy; y < height; y++) {
1009  mapdata_clear(x, y);
1010  }
1011  }
1012  } else {
1013  for (x = 0; x < width; x++) {
1014  for (y = 0; y < -dy; y++) {
1015  mapdata_clear(x, y);
1016  }
1017  }
1018  }
1019 
1020  /* Remove all big faces outside the view area. */
1021  while (bigfaces_head != NULL) {
1023  }
1024 
1025  run_move_to();
1026 }
1027 
1028 void mapdata_newmap(void)
1029 {
1030  script_pos.x = 0;
1031  script_pos.y = 0;
1032  int x, y;
1033 
1034  global_offset_x = 0;
1035  global_offset_y = 0;
1036  want_offset_x = 0;
1037  want_offset_y = 0;
1038 
1039  // Clear past predictions.
1040  memset(csocket.dir, -1, sizeof(csocket.dir));
1041 
1042  /* Clear the_map.cells[]. */
1043  for (x = 0; x < the_map.width; x++) {
1044  clear_cells(x, 0, the_map.height);
1045  for (y = 0; y < the_map.height; y++) {
1046  mapdata_cell(x, y)->need_update = 1;
1047  }
1048  }
1049 
1050  /* Clear bigfaces[]. */
1051  while (bigfaces_head != NULL) {
1053  }
1054 
1055  // Clear destination.
1056  clear_move_to();
1057 }
1058 
1062 static bool mapdata_has_tile(int x, int y, int layer) {
1063  if (0 <= x && x < width && 0 <= y && y < height) {
1064  if (0 <= layer && layer < MAXLAYERS) {
1065  return true;
1066  }
1067  }
1068 
1069  return false;
1070 }
1071 
1079 gint16 mapdata_face(int x, int y, int layer) {
1080  if (!mapdata_has_tile(x, y, layer)) {
1081  return 0;
1082  }
1083 
1084  return mapdata_cell(pl_pos.x+x, pl_pos.y+y)->heads[layer].face;
1085 }
1086 
1087 gint16 mapdata_face_info(int mx, int my, int layer, int *dx, int *dy) {
1088  struct MapCellLayer *head = &mapdata_cell(mx, my)->heads[layer];
1089  struct MapCellTailLayer *tail = &mapdata_cell(mx, my)->tails[layer];
1090  if (head->face != 0) {
1091  const int width = head->size_x, height = head->size_y;
1092  *dx = 1 - width, *dy = 1 - height;
1093  return head->face;
1094  } else if (tail->face != 0) {
1095  struct MapCellLayer *head_ptr = &mapdata_cell(mx + tail->size_x, my + tail->size_y)->heads[layer];
1096  const int width = head_ptr->size_x, height = head_ptr->size_y;
1097  *dx = tail->size_x - width + 1, *dy = tail->size_y - height + 1;
1098  return tail->face;
1099  } else {
1100  return 0;
1101  }
1102 }
1103 
1113 gint16 mapdata_bigface(int x, int y, int layer, int *ww, int *hh) {
1114  gint16 result;
1115 
1116  if (!mapdata_has_tile(x, y, layer)) {
1117  return 0;
1118  }
1119 
1120  result = mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].face;
1121  if (result != 0) {
1122  int clear_bigface;
1123  int dx = mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].size_x;
1124  int dy = mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].size_y;
1125  int w = mapdata_cell(pl_pos.x+x+dx, pl_pos.y+y+dy)->heads[layer].size_x;
1126  int h = mapdata_cell(pl_pos.x+x+dx, pl_pos.y+y+dy)->heads[layer].size_y;
1127  assert(1 <= w && w <= MAX_FACE_SIZE);
1128  assert(1 <= h && h <= MAX_FACE_SIZE);
1129  assert(0 <= dx && dx < w);
1130  assert(0 <= dy && dy < h);
1131 
1132  /* Now check if we are about to display an obsolete big face: such a
1133  * face has a cleared ("fog of war") head but the current tile is not
1134  * fog of war. Since the server would have sent an appropriate head
1135  * tile if it was already valid, just clear the big face and do not
1136  * return it.
1137  */
1138  if (mapdata_cell(pl_pos.x+x, pl_pos.y+y)->state == FOG) {
1139  /* Current face is a "fog of war" tile ==> do not clear
1140  * old information.
1141  */
1142  clear_bigface = 0;
1143  } else {
1144  if (x+dx < width && y+dy < height) {
1145  /* Clear face if current tile is valid but the
1146  * head is marked as cleared.
1147  */
1148  clear_bigface = mapdata_cell(pl_pos.x+x+dx, pl_pos.y+y+dy)->state == FOG;
1149  } else {
1150  /* Clear face if current tile is valid but the
1151  * head is not set.
1152  */
1153  clear_bigface = bigfaces[x+dx][y+dy][layer].head.face == 0;
1154  }
1155  }
1156 
1157  if (!clear_bigface) {
1158  *ww = w-1-dx;
1159  *hh = h-1-dy;
1160  return(result);
1161  }
1162 
1163  assert(mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].face == result);
1164  expand_clear_face_from_layer(pl_pos.x+x+dx, pl_pos.y+y+dy, layer);
1165  assert(mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].face == 0);
1166  }
1167 
1168  result = bigfaces[x][y][layer].tail.face;
1169  if (result != 0) {
1170  int dx = bigfaces[x][y][layer].tail.size_x;
1171  int dy = bigfaces[x][y][layer].tail.size_y;
1172  int w = bigfaces[x+dx][y+dy][layer].head.size_x;
1173  int h = bigfaces[x+dx][y+dy][layer].head.size_y;
1174  assert(0 <= dx && dx < w);
1175  assert(0 <= dy && dy < h);
1176  *ww = w-1-dx;
1177  *hh = h-1-dy;
1178  return(result);
1179  }
1180 
1181  *ww = 1;
1182  *hh = 1;
1183  return(0);
1184 }
1185 
1186 /* This is used by the opengl logic.
1187  * Basically the opengl code draws the the entire image,
1188  * and doesn't care if if portions are off the edge
1189  * (opengl takes care of that). So basically, this
1190  * function returns only if the head for a space is set,
1191  * otherwise, returns 0 - we don't care about the tails
1192  * or other details really.
1193  */
1194 gint16 mapdata_bigface_head(int x, int y, int layer, int *ww, int *hh) {
1195  gint16 result;
1196 
1197  if (!mapdata_has_tile(x, y, layer)) {
1198  return 0;
1199  }
1200 
1201  result = bigfaces[x][y][layer].head.face;
1202  if (result != 0) {
1203  int w = bigfaces[x][y][layer].head.size_x;
1204  int h = bigfaces[x][y][layer].head.size_y;
1205  *ww = w;
1206  *hh = h;
1207  return(result);
1208  }
1209 
1210  *ww = 1;
1211  *hh = 1;
1212  return(0);
1213 }
1214 
1223 static void recenter_virtual_map_view(int diff_x, int diff_y)
1224 {
1225  int new_x, new_y;
1226  int shift_x, shift_y;
1227  int src_x, src_y;
1228  int dst_x, dst_y;
1229  int len_x, len_y;
1230  int sx;
1231  int dx;
1232  int i;
1233 
1234  /* shift player position in virtual map */
1235  new_x = pl_pos.x+diff_x;
1236  new_y = pl_pos.y+diff_y;
1237 
1238  /* determine neccessary amount to shift */
1239 
1240  /* if(new_x < 1) is not possible: a big face may reach up to
1241  * (MAX_FACE_SIZE-1) tiles to the left of pl_pos. Therefore maintain a
1242  * border of at least MAX_FACE_SIZE to the left of the virtual map
1243  * edge.
1244  */
1245  if (new_x < MAX_FACE_SIZE) {
1246  shift_x = FOG_BORDER_MIN+MAX_FACE_SIZE-new_x;
1247  /* This yields: new_x+shift_x == FOG_BORDER_MIN+MAX_FACE_SIZE,
1248  * i.e. left border is FOG_BORDER_MIN+MAX_FACE_SIZE after
1249  * shifting.
1250  */
1251  } else if (new_x+MAX_VIEW > the_map.width) {
1252  shift_x = the_map.width-FOG_BORDER_MIN-MAX_VIEW-new_x;
1253  /* This yields: new_x+shift_x ==
1254  * the_map.width-FOG_BODER_MIN-MAX_VIEW, i.e. right border is
1255  * FOGBORDER_MIN after shifting.
1256  */
1257  } else {
1258  shift_x = 0;
1259  }
1260 
1261  /* Same as above but for y. */
1262  if (new_y < MAX_FACE_SIZE) {
1263  shift_y = FOG_BORDER_MIN+MAX_FACE_SIZE-new_y;
1264  } else if (new_y+MAX_VIEW > the_map.height) {
1265  shift_y = the_map.height-FOG_BORDER_MIN-MAX_VIEW-new_y;
1266  } else {
1267  shift_y = 0;
1268  }
1269 
1270  /* No shift neccessary? ==> nothing to do. */
1271  if (shift_x == 0 && shift_y == 0) {
1272  return;
1273  }
1274 
1275  /* If shifting at all: maintain a border size of FOG_BORDER_MIN to all
1276  * directions. For example: if pl_pos=30/MAX_FACE_SIZE, and map_scroll is
1277  * 0/-1: shift pl_pos to FOG_BORDER_MIN+1/FOG_BORDER_MIN+1, not to
1278  * 30/FOG_BORDER_MIN+1.
1279  */
1280  if (shift_x == 0) {
1281  if (new_x < FOG_BORDER_MIN+MAX_FACE_SIZE) {
1282  shift_x = FOG_BORDER_MIN+MAX_FACE_SIZE-new_x;
1283  } else if (new_x+MAX_VIEW+FOG_BORDER_MIN > the_map.width) {
1284  shift_x = the_map.width-FOG_BORDER_MIN-MAX_VIEW-new_x;
1285  }
1286  }
1287  if (shift_y == 0) {
1288  if (new_y < FOG_BORDER_MIN+MAX_FACE_SIZE) {
1289  shift_y = FOG_BORDER_MIN+MAX_FACE_SIZE-new_y;
1290  } else if (new_y+MAX_VIEW+FOG_BORDER_MIN > the_map.height) {
1291  shift_y = the_map.height-FOG_BORDER_MIN-MAX_VIEW-new_y;
1292  }
1293  }
1294 
1295  /* Shift for more than virtual map size? ==> clear whole virtual map
1296  * and recenter.
1297  */
1298  if (shift_x <= -the_map.width || shift_x >= the_map.width
1299  || shift_y <= -the_map.height || shift_y >= the_map.height) {
1300  for (dx = 0; dx < the_map.width; dx++) {
1301  clear_cells(dx, 0, the_map.height);
1302  }
1303 
1304  pl_pos.x = the_map.width/2-width/2;
1305  pl_pos.y = the_map.height/2-height/2;
1306  return;
1307  }
1308 
1309  /* Move player position. */
1310  pl_pos.x += shift_x;
1311  pl_pos.y += shift_y;
1312 
1313  /* Actually shift the virtual map by shift_x/shift_y */
1314  if (shift_x < 0) {
1315  src_x = -shift_x;
1316  dst_x = 0;
1317  len_x = the_map.width+shift_x;
1318  } else {
1319  src_x = 0;
1320  dst_x = shift_x;
1321  len_x = the_map.width-shift_x;
1322  }
1323 
1324  if (shift_y < 0) {
1325  src_y = -shift_y;
1326  dst_y = 0;
1327  len_y = the_map.height+shift_y;
1328  } else {
1329  src_y = 0;
1330  dst_y = shift_y;
1331  len_y = the_map.height-shift_y;
1332  }
1333 
1334  if (shift_x < 0) {
1335  for (sx = src_x, dx = dst_x, i = 0; i < len_x; sx++, dx++, i++) {
1336  /* srcx!=dstx ==> can use memcpy since source and
1337  * destination to not overlap.
1338  */
1339  memcpy(mapdata_cell(dx, dst_y), mapdata_cell(sx, src_y), len_y*sizeof(struct MapCell));
1340  }
1341  } else if (shift_x > 0) {
1342  for (sx = src_x+len_x-1, dx = dst_x+len_x-1, i = 0; i < len_x; sx--, dx--, i++) {
1343  /* srcx!=dstx ==> can use memcpy since source and
1344  * destination to not overlap.
1345  */
1346  memcpy(mapdata_cell(dx, dst_y), mapdata_cell(sx, src_y), len_y*sizeof(struct MapCell));
1347  }
1348  } else {
1349  assert(src_x == dst_x);
1350  for (dx = src_x, i = 0; i < len_x; dx++, i++) {
1351  /* srcx==dstx ==> use memmove since source and
1352  * destination probably do overlap.
1353  */
1354  memmove(mapdata_cell(dx, dst_y), mapdata_cell(dx, src_y), len_y*sizeof(struct MapCell));
1355  }
1356  }
1357 
1358  /* Clear newly opened area */
1359  for (dx = 0; dx < dst_x; dx++) {
1360  clear_cells(dx, 0, the_map.height);
1361  }
1362  for (dx = dst_x+len_x; dx < the_map.width; dx++) {
1363  clear_cells(dx, 0, the_map.height);
1364  }
1365  if (shift_y > 0) {
1366  for (dx = 0; dx < len_x; dx++) {
1367  clear_cells(dx+dst_x, 0, shift_y);
1368  }
1369  } else if (shift_y < 0) {
1370  for (dx = 0; dx < len_x; dx++) {
1371  clear_cells(dx+dst_x, the_map.height+shift_y, -shift_y);
1372  }
1373  }
1374 }
1375 
1380 static void mapdata_get_image_size(int face, guint8 *w, guint8 *h)
1381 {
1382  get_map_image_size(face, w, h);
1383  if (*w < 1) {
1384  *w = 1;
1385  }
1386  if (*h < 1) {
1387  *h = 1;
1388  }
1389  if (*w > MAX_FACE_SIZE) {
1390  *w = MAX_FACE_SIZE;
1391  }
1392  if (*h > MAX_FACE_SIZE) {
1393  *h = MAX_FACE_SIZE;
1394  }
1395 }
1396 
1397 /* This basically goes through all the map spaces and does the necessary
1398  * animation.
1399  */
1401 {
1402  int x, y, layer, face;
1403  struct MapCellLayer *cell;
1404 
1405 
1406  /* For synchronized animations, what we do is set the initial values
1407  * in the mapdata to the fields in the animations[] array. In this way,
1408  * the code below the iterates the spaces doesn't need to do anything
1409  * special. But we have to update the animations[] array here to
1410  * keep in sync.
1411  */
1412  for (x=0; x < MAXANIM; x++) {
1413  if (animations[x].speed) {
1414  animations[x].speed_left++;
1415  if (animations[x].speed_left >= animations[x].speed) {
1416  animations[x].speed_left=0;
1417  animations[x].phase++;
1418  if (animations[x].phase >= animations[x].num_animations) {
1419  animations[x].phase=0;
1420  }
1421  }
1422  }
1423  }
1424 
1425  for (x=0; x < MIN(width, CURRENT_MAX_VIEW); x++) {
1426  for (y=0; y < MIN(height, CURRENT_MAX_VIEW); y++) {
1427  struct MapCell *map_space = mapdata_cell(pl_pos.x + x, pl_pos.y + y);
1428 
1429  /* Short cut some processing here. It makes sense to me
1430  * not to animate stuff out of view
1431  */
1432  if (map_space->state != VISIBLE) {
1433  continue;
1434  }
1435 
1436  for (layer=0; layer<MAXLAYERS; layer++) {
1437  /* Using the cell structure just makes life easier here */
1438  cell = &map_space->heads[layer];
1439 
1440  if (cell->animation) {
1441  cell->animation_left++;
1442  if (cell->animation_left >= cell->animation_speed) {
1443  cell->animation_left=0;
1444  cell->animation_phase++;
1445  if (cell->animation_phase >= animations[cell->animation].num_animations) {
1446  cell->animation_phase=0;
1447  }
1448  face = animations[cell->animation].faces[cell->animation_phase];
1449 
1450  /* I don't think we send any to the client, but it is possible
1451  * for animations to have blank faces.
1452  */
1453  if (face >0) {
1454  expand_set_face(pl_pos.x + x, pl_pos.y + y, layer, face, FALSE);
1455  } else {
1456  expand_clear_face_from_layer(pl_pos.x + x, pl_pos.y + y , layer);
1457  }
1458  }
1459  }
1460  cell = &bigfaces[x][y][layer].head;
1461  if (cell->animation) {
1462  cell->animation_left++;
1463  if (cell->animation_left >= cell->animation_speed) {
1464  cell->animation_left=0;
1465  cell->animation_phase++;
1466  if (cell->animation_phase >= animations[cell->animation].num_animations) {
1467  cell->animation_phase=0;
1468  }
1469  face = animations[cell->animation].faces[cell->animation_phase];
1470 
1471  /* I don't think we send any to the client, but it is possible
1472  * for animations to have blank faces.
1473  */
1474  expand_set_bigface(x, y, layer, face, FALSE);
1475  }
1476  }
1477  }
1478  }
1479  }
1480 }
1481 
1487 void pl_mpos(int *px, int *py) {
1488  const int vw = use_config[CONFIG_MAPWIDTH];
1489  const int vh = use_config[CONFIG_MAPHEIGHT];
1490  *px = pl_pos.x + vw/2;
1491  *py = pl_pos.y + vh/2;
1492 }
1493 
1494 void set_move_to(int dx, int dy) {
1495  int old_move_to_x = move_to_x;
1496  int old_move_to_y = move_to_y;
1497 
1499  move_to_x += dx;
1500  move_to_y += dy;
1501 
1502  if (move_to_x == old_move_to_x && move_to_y == old_move_to_y) {
1503  // Detect double-click.
1504  move_to_attack = true;
1505  } else {
1506  move_to_attack = false;
1507  }
1508 }
1509 
1511  move_to_x = 0;
1512  move_to_y = 0;
1513  move_to_attack = false;
1514 }
1515 
1517  if (move_to_x == 0 && move_to_y == 0) {
1518  return true;
1519  }
1520 
1521  int px, py;
1522  pl_mpos(&px, &py);
1523  return !(move_to_x != px || move_to_y != py);
1524 }
1525 
1526 void run_move_to() {
1527  if (move_to_x == 0 && move_to_y == 0) {
1528  // If not moving to a tile, skip to avoid calling stop_run().
1529  return;
1530  }
1531 
1532  if (is_at_moveto()) {
1533  clear_move_to();
1534  stop_run();
1535  return;
1536  }
1537 
1538  int px, py;
1539  pl_mpos(&px, &py);
1540  int dx = move_to_x - px;
1541  int dy = move_to_y - py;
1542  int dir = relative_direction(dx, dy);
1543 
1544  if (move_to_attack) {
1545  run_dir(dir);
1546  } else {
1547  walk_dir(dir);
1548  }
1549 }
run_dir
void run_dir(int dir)
Definition: player.c:146
mapdata_cell
struct MapCell * mapdata_cell(const int x, const int y)
Get the stored map cell at the given map coordinate.
Definition: mapdata.c:139
Map::height
int height
Definition: mapdata.h:84
ANIM_SYNC
#define ANIM_SYNC
Definition: newclient.h:321
MapCellTailLayer::size_x
gint8 size_x
Definition: mapdata.h:38
mapdata_clear_space
void mapdata_clear_space(int x, int y)
Definition: mapdata.c:674
relative_direction
int relative_direction(int dx, int dy)
Given a relative tile coordinate, determine its compass direction.
Definition: map.c:560
LOG_WARNING
@ LOG_WARNING
Warning that something might not work.
Definition: client.h:438
Map
Definition: mapdata.h:80
PlayerPosition::x
int x
Definition: client.h:528
is_at_moveto
bool is_at_moveto()
Definition: mapdata.c:1516
want_offset_x
int want_offset_x
Definition: mapdata.c:92
mapdata_bigface
gint16 mapdata_bigface(int x, int y, int layer, int *ww, int *hh)
Return the face number of a multi-square pixmap at the given map tile.
Definition: mapdata.c:1113
external.h
mapdata_set_face_layer
void mapdata_set_face_layer(int x, int y, gint16 face, int layer)
Definition: mapdata.c:875
Animations::phase
guint8 phase
Definition: client.h:107
mapdata_clear_label
void mapdata_clear_label(int px, int py)
Definition: mapdata.c:830
move_to_x
int move_to_x
Move to coordinates on the current map.
Definition: mapdata.c:39
VISIBLE
@ VISIBLE
Definition: mapdata.h:45
mapdata_newmap
void mapdata_newmap(void)
Clears the map view.
Definition: mapdata.c:1028
mapdata_face
gint16 mapdata_face(int x, int y, int layer)
Return the face number of a single-square pixmap at the given map tile.
Definition: mapdata.c:1079
BigCell::head
struct MapCellLayer head
Definition: mapdata.c:82
expand_need_update
static void expand_need_update(int x, int y, int w, int h)
Mark a face as "need_update".
Definition: mapdata.c:536
Animations::num_animations
guint8 num_animations
Number of animations.
Definition: client.h:101
height
static int height
Definition: mapdata.c:101
MIN
#define MIN(X__, Y__)
Definition: client.h:618
mapdata_set_smooth
void mapdata_set_smooth(int x, int y, guint8 smooth, int layer)
Definition: mapdata.c:778
bigfaces_head
static struct BigCell * bigfaces_head
Contains the head of a list of all currently active big faces outside the view area.
Definition: mapdata.c:107
mapdata_set_check_space
void mapdata_set_check_space(int x, int y)
Definition: mapdata.c:707
mapdata_can_smooth
bool mapdata_can_smooth(int x, int y, int layer)
Definition: mapdata.c:154
move_to_attack
bool move_to_attack
Definition: mapdata.c:40
MapCellTailLayer::face
gint16 face
Definition: mapdata.h:37
expand_clear_face
static void expand_clear_face(int x, int y, int w, int h, int layer)
Clear a face from the_map.cells[].
Definition: mapdata.c:238
Animations::speed
guint8 speed
Definition: client.h:105
FOG_MAP_SIZE
#define FOG_MAP_SIZE
Size of virtual map.
Definition: mapdata.c:45
mapdata_alloc
static void mapdata_alloc(struct Map *const map, const int width, const int height)
Allocate and set up pointers for a map, with cells represented as a C-style multi-dimensional array.
Definition: mapdata.c:585
mapdata_clear_old
void mapdata_clear_old(int x, int y)
Prepare a map cell, which may contain old fog of war data, for new visible map data.
Definition: mapdata.c:844
expand_need_update_from_layer
static void expand_need_update_from_layer(int x, int y, int layer)
Mark a face as "need_update".
Definition: mapdata.c:564
PlayerPosition::y
int y
Definition: client.h:529
display_mapscroll
int display_mapscroll(int dx, int dy)
Definition: map.c:155
MapCell::state
enum MapCellState state
Definition: mapdata.h:71
FOG_BORDER_MIN
#define FOG_BORDER_MIN
After shifting the virtual map: new minimum distance of the view area to the new virtual map border.
Definition: mapdata.c:51
MapLabel::subtype
int subtype
Definition: mapdata.h:75
mapdata.h
global_offset_y
int global_offset_y
Definition: mapdata.c:91
expand_set_bigface
static void expand_set_bigface(int x, int y, int layer, gint16 face, int clear)
Update a face into bigfaces[].
Definition: mapdata.c:471
mapdata_init
static void mapdata_init(void)
Definition: mapdata.c:604
MapCellLayer::face
gint16 face
Definition: mapdata.h:19
recenter_virtual_map_view
static void recenter_virtual_map_view(int diff_x, int diff_y)
Check if current map position is out of bounds if shifted by (dx, dy).
Definition: mapdata.c:1223
MapCellTailLayer::size_y
gint8 size_y
Definition: mapdata.h:39
MapCell::heads
struct MapCellLayer heads[MAXLAYERS]
Definition: mapdata.h:64
mapdata_get_image_size
static void mapdata_get_image_size(int face, guint8 *w, guint8 *h)
Return the size of a face in tiles.
Definition: mapdata.c:1380
mapdata_size
void mapdata_size(int *x, int *y)
Determine the size of the internal fog-of-war map.
Definition: mapdata.c:162
ANIM_RANDOM
#define ANIM_RANDOM
Definition: newclient.h:320
move_to_y
int move_to_y
Definition: mapdata.c:39
mapdata_free
void mapdata_free(void)
Deallocate map data.
Definition: mapdata.c:645
MapCellLayer::animation_phase
guint8 animation_phase
Definition: mapdata.h:33
CONFIG_MAPSCROLL
#define CONFIG_MAPSCROLL
Use bitmap operations for map scrolling.
Definition: client.h:211
mapdata_has_tile
static bool mapdata_has_tile(int x, int y, int layer)
Check if the given map tile is a valid slot in the map array.
Definition: mapdata.c:1062
mapdata_set_anim_layer
void mapdata_set_anim_layer(int x, int y, guint16 anim, guint8 anim_speed, int layer)
Definition: mapdata.c:904
Map::_cells
struct MapCell ** _cells
Definition: mapdata.h:82
want_offset_y
int want_offset_y
Definition: mapdata.c:93
MapCell::smooth
guint8 smooth[MAXLAYERS]
Definition: mapdata.h:67
LOG
void LOG(LogLevel level, const char *origin, const char *format,...)
Log messages of a certain importance to stderr.
Definition: misc.c:111
global_offset_x
int global_offset_x
Definition: mapdata.c:90
mapdata_bigface_head
gint16 mapdata_bigface_head(int x, int y, int layer, int *ww, int *hh)
Definition: mapdata.c:1194
width
static int width
Definition: mapdata.c:100
walk_dir
void walk_dir(int dir)
Definition: player.c:173
MapLabel
Definition: mapdata.h:74
the_map
static struct Map the_map
Definition: mapdata.c:116
want_config
gint16 want_config[CONFIG_NUMS]
Definition: init.c:44
csocket
ClientSocket csocket
Definition: client.c:70
MapCell::darkness
guint8 darkness
Definition: mapdata.h:68
MapLabel::label
char * label
Definition: mapdata.h:76
expand_clear_bigface_from_layer
static void expand_clear_bigface_from_layer(int x, int y, int layer, int set_need_update)
Clear a face from bigfaces[].
Definition: mapdata.c:425
mapdata_face_info
gint16 mapdata_face_info(int mx, int my, int layer, int *dx, int *dy)
Return the face number of the pixmap in the given map cell and set the offset pointers to indicate wh...
Definition: mapdata.c:1087
MapCell
The heads[] in the mapcell is used for single part objects or the head piece for multipart.
Definition: mapdata.h:62
Map::width
int width
Definition: mapdata.h:83
mapdata_clear
void mapdata_clear(int x, int y)
Mark the given cell as cleared in response to a Map2 clear command.
Definition: mapdata.c:195
mark_resmooth
static void mark_resmooth(int x, int y, int layer)
Definition: mapdata.c:217
Animations::speed_left
guint8 speed_left
Definition: client.h:106
BigCell::next
struct BigCell * next
Definition: mapdata.c:79
get_map_image_size
void get_map_image_size(int face, guint8 *w, guint8 *h)
Definition: image.c:341
mapdata_is_inside
int mapdata_is_inside(int x, int y)
Checks whether the given coordinates are within the current display size (as set by mapdata_set_size)...
Definition: mapdata.c:665
stop_run
void stop_run()
Definition: player.c:141
mapdata_contains
bool mapdata_contains(int x, int y)
Determine whether the map data contains the given cell.
Definition: mapdata.c:146
FOG
@ FOG
Definition: mapdata.h:46
expand_clear_bigface
static void expand_clear_bigface(int x, int y, int w, int h, int layer, int set_need_update)
Clear a face from bigfaces[].
Definition: mapdata.c:371
MapCell::need_resmooth
guint8 need_resmooth
Definition: mapdata.h:70
map
static item * map
Definition: item.c:27
MapCellTailLayer
Definition: mapdata.h:36
set_move_to
void set_move_to(int dx, int dy)
Definition: mapdata.c:1494
Animations::faces
guint16 * faces
Definition: client.h:108
MapCell::tails
struct MapCellTailLayer tails[MAXLAYERS]
Definition: mapdata.h:65
MAX_FACE_SIZE
#define MAX_FACE_SIZE
Maximum size of a big face image in tiles.
Definition: mapdata.c:56
set_darkness
static void set_darkness(int x, int y, int darkness)
Update darkness information.
Definition: mapdata.c:180
bigfaces
static struct BigCell bigfaces[MAX_VIEW][MAX_VIEW][MAXLAYERS]
The variable bigfaces[] contains information about big faces (faces with a width or height >1).
Definition: mapdata.c:114
MapCellLayer
Definition: mapdata.h:18
CONFIG_MAPWIDTH
#define CONFIG_MAPWIDTH
Definition: client.h:201
mapdata_scroll
void mapdata_scroll(int dx, int dy)
Scrolls the map view.
Definition: mapdata.c:955
BigCell::layer
guint8 layer
Definition: mapdata.c:86
EMPTY
@ EMPTY
Definition: mapdata.h:44
clear_move_to
void clear_move_to()
Definition: mapdata.c:1510
ANIM_MASK
#define ANIM_MASK
AND'ing this with data from server gets us just the animation id.
Definition: newclient.h:329
MapCellLayer::size_x
gint8 size_x
Definition: mapdata.h:20
mapdata_set_size
void mapdata_set_size(int viewx, int viewy)
Initializes the module.
Definition: mapdata.c:654
mapdata_add_label
void mapdata_add_label(int x, int y, int subtype, const char *label)
Definition: mapdata.c:806
expand_clear_face_from_layer
static void expand_clear_face_from_layer(int x, int y, int layer)
Clear a face from the_map.cells[].
Definition: mapdata.c:293
BigCell::x
guint16 x
Definition: mapdata.c:85
pl_mpos
void pl_mpos(int *px, int *py)
Compute player position in map coordinates.
Definition: mapdata.c:1487
MapCellLayer::animation_left
guint8 animation_left
Definition: mapdata.h:32
MapCellLayer::size_y
gint8 size_y
Definition: mapdata.h:21
PlayerPosition
Definition: client.h:527
CURRENT_MAX_VIEW
#define CURRENT_MAX_VIEW
Definition: mapdata.c:63
mapdata_set_darkness
void mapdata_set_darkness(int x, int y, int darkness)
Definition: mapdata.c:755
use_config
gint16 use_config[CONFIG_NUMS]
Definition: client.h:245
ClientSocket::dir
gint8 dir[COMMAND_MAX]
Definition: client.h:136
MAXLAYERS
#define MAXLAYERS
The protocol supports 10 layers, so set MAXLAYERS accordingly.
Definition: mapdata.h:6
pl_pos
PlayerPosition pl_pos
Position of the player on the internal map.
Definition: mapdata.c:30
run_move_to
void run_move_to()
Definition: mapdata.c:1526
MAXANIM
#define MAXANIM
Definition: client.h:86
animations
Animations animations[MAXANIM]
Definition: commands.c:1156
ANIM_FLAGS_MASK
#define ANIM_FLAGS_MASK
Used only by the client.
Definition: newclient.h:323
clear_cells
static void clear_cells(int x, int y, int len_y)
Clear cells the_map.cells[x][y..y+len_y-1].
Definition: mapdata.c:121
CONFIG_MAPHEIGHT
#define CONFIG_MAPHEIGHT
Definition: client.h:202
expand_set_face
static void expand_set_face(int x, int y, int layer, gint16 face, int clear)
Update a face into the_map.cells[].
Definition: mapdata.c:320
MapLabel::next
struct MapLabel * next
Definition: mapdata.h:77
BigCell
The struct BigCell describes a tile outside the view area.
Definition: mapdata.c:78
MAX_VIEW
#define MAX_VIEW
Maximum size of view area a server could support.
Definition: mapdata.h:11
BigCell::tail
struct MapCellTailLayer tail
Definition: mapdata.c:83
mapdata_animation
void mapdata_animation(void)
Definition: mapdata.c:1400
BigCell::y
guint16 y
Definition: mapdata.c:85
MapCellLayer::animation_speed
guint8 animation_speed
Definition: mapdata.h:31
BigCell::prev
struct BigCell * prev
Definition: mapdata.c:80
MapCell::need_update
guint8 need_update
Definition: mapdata.h:69
client.h
MapCell::label
struct MapLabel * label
Definition: mapdata.h:66
MapCellLayer::animation
gint16 animation
Definition: mapdata.h:30
script_pos
PlayerPosition script_pos
Position of the player reported to client scripts.
Definition: mapdata.c:36