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