Crossfire Server, Trunk  1.75.0
mapper.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire map browser generator.
3  *
4  * Author: Nicolas Weeger <nicolas.weeger@laposte.net>, (C) 2006-2021.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
180 #include <ctype.h>
181 #include <errno.h>
182 #include <stdio.h>
183 #include <stdlib.h>
184 #include <string.h>
185 #include <strings.h>
186 #include <sys/stat.h>
187 #include <sys/types.h>
188 #include <time.h>
189 
190 #include "global.h"
191 #include "sproto.h"
192 #include "image.h"
193 #include "quest.h"
194 
195 extern "C" {
196 #include <gd.h>
197 #include <gdfonts.h>
198 #include <gdfontl.h>
199 #include <gdfontg.h>
200 }
201 
202 #include "inja.hpp"
203 #include <map>
204 #include <set>
205 
206 static std::vector<gdImagePtr> gdfaces;
207 
210  const char *name;
211  const char *message;
212  int x, y;
213 };
214 
216 typedef std::vector<struct_npc_info *> npc_list;
217 
220  struct struct_race **races;
221  size_t count;
222  size_t allocated;
223 };
224 
228  size_t count;
229  size_t allocated;
230 };
231 
235  size_t count;
236  size_t allocated;
237 };
238 
241  char *path;
242  char *name;
243  char *filename;
244  char *lore;
251 
253 
255 
258 
260  int height, width;
262  struct struct_map_info *tiles[4];
263 };
264 
267 
270 
273  char *name;
274  int power;
276  char *diff;
278 };
279 
280 static std::vector<struct_equipment *> special_equipment;
284 struct struct_race {
285  char *name;
286  int count;
288 };
289 
292 static std::set<std::string> reset_groups;
295 enum class SearchType {
296  Region = 1,
297  Map,
298  Item,
299  Monster,
300  Quest,
301  Count
302 };
303 
305 static std::string SearchName[int(SearchType::Count)] = {
306  "(invalid)",
307  "region",
308  "map",
309  "item",
310  "monster",
311  "quest",
312 };
313 
320  list->races = NULL;
321  list->count = 0;
322  list->allocated = 0;
323 }
324 
335 static void add_race_to_list(struct_race *race, struct_race_list *list, int check) {
336  if (check) {
337  size_t test;
338 
339  for (test = 0; test < list->count; test++) {
340  if (list->races[test] == race)
341  return;
342  }
343  }
344 
345  if (list->allocated == list->count) {
346  list->allocated += 50;
347  list->races = (struct_race **)realloc(list->races, sizeof(struct_race *)*list->allocated);
348  }
349  list->races[list->count] = race;
350  list->count++;
351 }
352 
354 static char root[500];
355 
357 static int pics_allocated;
358 
359 /* Options */
360 static int generate_pics = 1;
361 static int force_pics = 0;
362 static int sizes[] = {32, 16, 8, 4, 2};
363 static const int num_sizes = sizeof(sizes)/sizeof(int);
364 #define size_large sizes[0]
365 #define size_small sizes[1]
366 static int map_limit = -1;
367 static int show_maps = 0;
368 static int world_map = 1;
369 static int world_exit_info = 1;
370 static int tileset = 0;
371 static bool detail_quests = false;
372 static bool list_system_quests = false;
373 static bool display_rendered_template = false;
374 static bool build_search_file = false;
377 static int created_pics = 0;
378 static int cached_pics = 0;
382  OF_PNG = 0,
383  OF_JPG = 1
384 };
385 
387 static const char *output_extensions[] = {
388  ".png",
389  ".jpg"
390 };
391 
394 
396 static int jpeg_quality = -1;
397 
399 static int rawmaps = 0;
400 
402 static int warn_no_path = 0;
403 
408  int sum_x, sum_y, sum;
409  int is_world;
410 };
411 
412 static struct struct_region_info **regions = NULL;
413 static size_t region_count = 0;
414 static size_t region_allocated = 0;
416 static int list_unused_maps = 0;
417 static std::vector<char *> found_maps;
419 /* Path/exit info */
420 static gdImagePtr infomap;
422 static int color_linked_exit;
423 static int color_road;
424 static int color_blocking;
425 static int color_slowing;
427 static int **elevation_info;
428 static int elevation_min;
429 static int elevation_max;
431 /* Whether to compute links between regions or not (expensive). */
432 static bool do_regions_link = false;
433 /* Links between regions, key is source, value are destinations. */
434 static std::map<region *, std::set<region *>> region_links;
435 
437 #define S_DOOR 0
438 #define S_KEY 1
439 #define S_CONTAINER 2
440 #define S_DETECTOR 3
441 #define S_CONNECT 4
442 #define S_MAX 5
443 
446  char *slaying;
448 };
449 
451 static size_t slaying_count = 0;
452 static size_t slaying_allocated = 0;
460  list->maps = NULL;
461  list->count = 0;
462  list->allocated = 0;
463 }
464 
465 static void add_map(struct_map_info *info, struct_map_list *list);
466 
467 static int is_special_equipment(object *item) {
468  if (item->name == item->arch->clone.name && item->title == item->arch->clone.title)
469  return 0;
470  if (QUERY_FLAG(item, FLAG_NO_PICK))
471  return 0;
472  if (item->move_block == MOVE_ALL)
473  return 0;
474 
475  if (IS_SHIELD(item) || IS_WEAPON(item) || IS_ARMOR(item) || IS_ARROW(item) || (item->type == ROD) || (item->type == WAND) || (item->type == RING) || (item->type == AMULET))
476  return 1;
477 
478  return 0;
479 }
480 
487  struct_equipment *add = (struct_equipment *)calloc(1, sizeof(struct_equipment));
488 
489  init_map_list(&add->origin);
490  return add;
491 }
492 
499 static void free_equipment(struct_equipment *equip) {
500  free(equip->diff);
501  free(equip->name);
502  free(equip);
503 }
504 
513 static bool sort_equipment(const struct_equipment *l, const struct_equipment *r) {
514  int cmp = strcasecmp(l->name, r->name);
515  if (cmp)
516  return cmp < 0;
517  if (l->power != r->power)
518  return l->power < r->power;
519  if (l->calc_power != r->calc_power)
520  return l->calc_power < r->calc_power;
521 
522  return strcasecmp(l->diff, r->diff) < 0;
523 }
524 
534  assert(item);
535  auto existing = std::find_if(special_equipment.begin(), special_equipment.end(),
536  [&] (const auto *e) { return !sort_equipment(e, item) && !sort_equipment(item, e); });
537 
538  if (existing != special_equipment.end()) {
539  free_equipment(item);
540  return *existing;
541  }
542 
543  special_equipment.push_back(item);
544 
545  return item;
546 }
547 
557 static void add_one_item(object *item, struct_map_info *map) {
560  int x, y;
561  sstring name, namepl;
562  uint32_t nrof;
563  object *base;
564 
565  x = item->x;
566  y = item->y;
567  name = item->name;
568  namepl = item->name_pl;
569  nrof = item->nrof;
570 
571  if (item->artifact != NULL) {
572  const artifact *artifact;
573 
574  artifact = find_artifact(item, item->artifact);
575  if (artifact == NULL) {
576  LOG(llevError, "could not find artifact %s [%d] to save data\n", item->artifact, item->type);
577  base = arch_to_object(item->arch);
578  } else {
579  base = arch_to_object(item->arch);
581  }
582  }
583  else {
584  base = arch_to_object(item->arch);
585  }
586 
587  item->x = base->x;
588  item->y = base->y;
589  item->name = base->name;
590  item->name_pl = base->name_pl;
591  item->nrof = base->nrof;
592 
593  if (QUERY_FLAG(item, FLAG_IDENTIFIED) && !QUERY_FLAG(base, FLAG_IDENTIFIED)) {
595  SET_FLAG(base, FLAG_IDENTIFIED);
596  }
597  if (QUERY_FLAG(item, FLAG_UNPAID))
598  SET_FLAG(base, FLAG_UNPAID);
599  get_ob_diff(bf, item, base);
601 
602  add->diff = stringbuffer_finish(bf);
603 
604  item->x = x;
605  item->y = y;
606  item->name = name;
607  item->name_pl = namepl;
608  item->nrof = nrof;
609 
610  if (add->diff == NULL || strcmp(add->diff, "") == 0) {
611  free_equipment(add);
612  return;
613  }
614 
615  add->name = strdup(item->name);
616  add->power = item->item_power;
617  add->calc_power = calc_item_power(item);
618 
619  add = ensure_unique(add);
620  add_map(map, &add->origin);
621 }
622 
631 static void check_equipment(object *item, struct_map_info *map) {
632  if (is_special_equipment(item))
633  add_one_item(item, map);
634 
635  FOR_INV_PREPARE(item, inv)
636  check_equipment(inv, map);
637  FOR_INV_FINISH();
638 }
639 
648 static struct_race *get_race(const char *name) {
649  size_t test;
650  struct_race *item;
651 
652  for (test = 0; test < races.count; test++) {
653  if (strcmp(races.races[test]->name, name) == 0) {
654  races.races[test]->count++;
655  return races.races[test];
656  }
657  }
658 
659  item = (struct_race *)calloc(1, sizeof(struct_race));
660  item->name = strdup(name);
661  item->count = 1;
662  init_map_list(&item->origin);
663 
664  add_race_to_list(item, &races, 0);
665 
666  return item;
667 }
668 
677 static void add_monster(object *monster, struct_map_info *map) {
678  struct_race *race;
679 
680  if (monster->head && monster != monster->head)
681  return;
682 
683  map->min_monster = MIN(monster->level, map->min_monster);
684  map->max_monster = MAX(monster->level, map->max_monster);
685 
686  race = get_race(monster->name ? monster->name : "(null race)");
687  add_map(map, &race->origin);
688  add_race_to_list(race, &map->monsters, 1);
689 }
690 
699 static int sort_race(const void *a, const void *b) {
700  const struct_race *l = *(const struct_race **)a;
701  const struct_race *r = *(const struct_race **)b;
702  return strcasecmp(l->name, r->name);
703 }
704 
712 static int is_road(object *item) {
713  int test;
714  /* Archetypes used as roads. */
715  const char *roads[] = {
716  "cobblestones",
717  "flagstone",
718  "ice_stone",
719  "snow",
720  NULL };
721  const char *partial[] = {
722  "dirtroad_",
723  NULL };
724 
725  for (test = 0; partial[test] != NULL; test++) {
726  if (strstr(item->arch->name, partial[test]) != NULL)
727  return 1;
728  }
729 
730  if (!QUERY_FLAG(item, FLAG_IS_FLOOR))
731  return 0;
732 
733  for (test = 0; roads[test] != NULL; test++) {
734  if (strcmp(item->arch->name, roads[test]) == 0)
735  return 1;
736  }
737 
738  return 0;
739 }
740 
748 static int is_blocking(object *item) {
749  return item->move_block == MOVE_ALL ? 1 : 0;
750 }
751 
762 static int get_elevation_color(int elevation, gdImagePtr elevationmap) {
763  if (elevation > 0)
764  return gdImageColorResolve(elevationmap, 200*elevation/elevation_max, 0, 0);
765  else
766  return gdImageColorResolve(elevationmap, 0, 0, 200*elevation/elevation_min);
767 }
768 
777 static void do_exit_map(mapstruct *map) {
778  int tx, ty, x, y;
779  object *test;
780 
781  if (sscanf(map->path, "/world/world_%d_%d", &x, &y) != 2)
782  return;
783 
784  x -= 100;
785  y -= 100;
786 
787  for (tx = 0; tx < MAP_WIDTH(map); tx++) {
788  for (ty = 0; ty < MAP_HEIGHT(map); ty++) {
789  FOR_MAP_PREPARE(map, tx, ty, item) {
790  test = HEAD(item);
791 
792  // Do this before we check for blocked tiles,
793  // otherwise we don't receive elevation data for blocked tiles.
794  int elevation = item->elevation;
795  if (elevation != 0) {
796  elevation_min = MIN(elevation_min, elevation);
797  elevation_max = MAX(elevation_max, elevation);
798  elevation_info[x*50+tx][y*50+ty] = elevation;
799  }
800 
801  if (test->type == EXIT || test->type == TELEPORTER) {
802  if (!test->slaying)
803  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_unlinked_exit);
804  else
805  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_linked_exit);
806  } else if (is_road(test))
807  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_road);
808  else if (is_blocking(test)) {
809  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_blocking);
810  /* can't get on the spot, so no need to go on. */
811  break;
812  } else if (test->move_slow != 0)
813  gdImageSetPixel(infomap, x*50+tx, y*50+ty, color_slowing);
814 
815  } FOR_MAP_FINISH();
816  }
817  }
818 }
819 
820 void do_auto_apply(mapstruct *m);
821 
834 static void relative_path(const char *from, const char *to, char *result) {
835  const char *fslash;
836  const char *rslash;
837 
838  result[0] = '\0';
839 
840  fslash = strchr(from+1, '/');
841  if (!fslash) {
842  strcpy(result, to+1);
843  return;
844  }
845 
846  rslash = strchr(to+1, '/');
847  while (fslash && rslash && (fslash-from == rslash-to) && strncmp(from, to, fslash-from+1) == 0) {
848  from = fslash+1;
849  to = rslash+1;
850  fslash = strchr(fslash+1, '/');
851  rslash = strchr(rslash+1, '/');
852  }
853 
854  while (fslash) {
855  strcat(result, "../");
856  fslash = strchr(fslash+1, '/');
857  }
858  if (strlen(result) && result[strlen(result)-1] == '/' && *to == '/')
859  result[strlen(result)-1] = '\0';
860  strcat(result, to);
861 }
862 
873 static int compare_map_info(const struct_map_info *left, const struct_map_info *right) {
874  int c;
875 
876  if (left->tiled_group)
877  left = left->tiled_group;
878  if (right->tiled_group)
879  right = right->tiled_group;
880 
881  // Shortcut -- if both are the same pointer, return 0.
882  // This occurs when tiled maps of the same set are compared to each other.
883  if (left == right)
884  return 0;
885 
886  c = strcasecmp(left->name, right->name);
887  if (c)
888  return c;
889 
890  return strcasecmp(left->path, right->path);
891 }
892 
903 static int sort_map_info(const void *left, const void *right) {
904  const struct_map_info *l = *(const struct_map_info **)left;
905  const struct_map_info *r = *(const struct_map_info **)right;
906  return compare_map_info(l, r);
907 }
908 
919 static int sort_region(const void *left, const void *right) {
920  return strcmp((*((struct_region_info **)left))->reg->name, (*((struct_region_info **)right))->reg->name);
921 }
922 
923 /************************************
924  Start of quest-related definitions.
925 ************************************/
926 
930  char *description;
931  struct struct_quest *quest;
932 };
933 
935 struct struct_quest {
936  char *name;
937  char *description;
938  int number;
941 };
942 
943 static struct_quest **quests = NULL;
945 static int quests_count = 0;
947 static int quests_allocated = 0;
950  list->list = NULL;
951  list->count = 0;
952  list->allocated = 0;
953 }
954 
956  if (list->count == list->allocated) {
957  list->allocated += 10;
958  list->list = (struct_map_in_quest **)realloc(list->list, sizeof(struct_map_in_quest *)*list->allocated);
959  }
960  list->list[list->count++] = item;
961 }
962 
968 static struct_quest *find_quest_info(const char *name) {
969  int test;
970  for (test = 0; test < quests_count; test++) {
971  if (strcmp(quests[test]->name, name) == 0)
972  return quests[test];
973  }
974  return NULL;
975 }
976 
985 static struct_quest *get_quest_info(const char *name) {
987  if (add) {
988  return add;
989  }
990 
992  quests_allocated += 10;
993  quests = (struct_quest **)realloc(quests, sizeof(struct_quest *)*quests_allocated);
994  }
995  add = (struct_quest *)calloc(1, sizeof(struct_quest));
996  add->name = strdup(name);
997  add->number = quests_count;
999  quests[quests_count] = add;
1000  quests_count++;
1001  return add;
1002 }
1003 
1014 static void add_map_to_quest(struct_map_info *map, const char *name, const char *description) {
1015  struct_map_in_quest *add;
1016  struct_quest *quest = get_quest_info(name);
1017 
1018  add = (struct_map_in_quest *)calloc(1, sizeof(struct_map_in_quest));
1019  add->map = map;
1020  add->quest = quest;
1021  add->description = strdup(description);
1022  while (strlen(add->description) && add->description[strlen(add->description)-1] == '\n')
1023  add->description[strlen(add->description)-1] = '\0';
1024  add_to_struct_map_in_quest_list(&quest->maps, add);
1026 }
1027 
1036 static int sort_struct_map_in_quest(const void *left, const void *right) {
1037  int c;
1038 
1039  const struct_map_in_quest *l = *(const struct_map_in_quest **)left;
1040  const struct_map_in_quest *r = *(const struct_map_in_quest **)right;
1041  const struct_map_info *ml = l->map;
1042  const struct_map_info *mr = r->map;
1043 
1044  if (ml->tiled_group)
1045  ml = ml->tiled_group;
1046  if (mr->tiled_group)
1047  mr = mr->tiled_group;
1048 
1049  c = strcasecmp(ml->name, mr->name);
1050  if (c)
1051  return c;
1052 
1053  return strcasecmp(ml->path, mr->path);
1054 }
1055 
1064 static int sort_struct_quest(const void *left, const void *right) {
1065  const struct_quest *l = *(const struct_quest **)left;
1066  const struct_quest *r = *(const struct_quest **)right;
1067  return strcasecmp(l->name, r->name);
1068 }
1069 
1080 static void define_quest(const char *name, struct_map_info *mainmap, const char *description) {
1081  struct_quest *quest = get_quest_info(name);
1082 
1083  if (quest->description || quest->mainmap) {
1084  printf("warning, multiple quest definition for %s, found in %s and %s.\n", quest->name, quest->mainmap ? quest->mainmap->path : "(unknown map)", mainmap->path);
1085  return;
1086  }
1087  quest->description = strdup(description);
1088  while (strlen(quest->description) && quest->description[strlen(quest->description)-1] == '\n')
1089  quest->description[strlen(quest->description)-1] = '\0';
1090  quest->mainmap = mainmap;
1091 }
1092 
1100  char *start, *end, *next;
1101  char name[500];
1102  char description[500];
1103 
1104  start = strstr(map->lore, "@def");
1105  while (start) {
1106  description[0] = '\0';
1107  /* find name */
1108  end = strstr(start, "\n");
1109  if (end) {
1110  strncpy(name, start+5, end-start-5);
1111  name[end-start-5] = '\0';
1112  next = end+1;
1113  end = strstr(next, "@end");
1114  if (end) {
1115  strncpy(description, next, end-next);
1116  description[end-next] = '\0';
1117  /* need to erase the text. */
1118  memmove(start, end+4, strlen(map->lore)-(end-start+3));
1119  end = start;
1120  }
1121  else {
1122  strcpy(description, next);
1123  *start = '\0';
1124  end = NULL;
1125  }
1126  } else {
1127  strcpy(name, start);
1128  *start = '\0';
1129  end = NULL;
1130  }
1131 
1132  define_quest(name, map, description);
1133  start = end ? strstr(end, "@def") : NULL;
1134  }
1135 
1136  start = strstr(map->lore, "@quest");
1137  while (start) {
1138  description[0] = '\0';
1139  /* find name */
1140  end = strstr(start, "\n");
1141  if (end) {
1142  strncpy(name, start+7, end-start-7);
1143  name[end-start-7] = '\0';
1144  next = end+1;
1145  end = strstr(next, "@end");
1146  if (end) {
1147  strncpy(description, next, end-next);
1148  description[end-next] = '\0';
1149  /* need to erase the text. */
1150  memmove(start, end+4, strlen(map->lore)-(end-start+3));
1151  end = start;
1152  }
1153  else {
1154  strcpy(description, next);
1155  *start = '\0';
1156  end = NULL;
1157  }
1158  } else {
1159  strcpy(name, start);
1160  *start = '\0';
1161  end = NULL;
1162  }
1163 
1165  start = end ? strstr(end, "@quest") : NULL;
1166  }
1167 }
1168 
1169 /************************************
1170  End of quest-related definitions.
1171 ************************************/
1172 
1173 /*********
1174 NPC-related stuff
1175 ********/
1176 
1184 static struct_npc_info *create_npc_info(const object *npc) {
1185  struct_npc_info *info = (struct_npc_info *)calloc(1, sizeof(struct_npc_info));
1186 
1187  info->name = strdup(npc->name ? npc->name : "(null name)");
1188  info->message = strdup(npc->msg ? npc->msg : "(null msg)");
1189  info->x = npc->x;
1190  info->y = npc->y;
1191 
1192  return info;
1193 }
1194 
1202 static void add_npc_to_map(npc_list *list, const object *npc) {
1203  list->push_back(create_npc_info(npc));
1204 }
1205 /* end of NPC stuff */
1206 
1219  size_t map;
1220 
1221  for (map = 0; map < list->count; map++)
1222  if (list->maps[map] == info)
1223  return;
1224 
1225  if (list->count == list->allocated) {
1226  list->allocated += 50;
1227  list->maps = (struct_map_info **)realloc(list->maps, list->allocated*sizeof(struct_map_info *));
1228  }
1229  list->maps[list->count] = info;
1230  list->count++;
1231 }
1232 
1240  struct_map_info *add = (struct_map_info *)calloc(1, sizeof(struct_map_info));
1241 
1242  add->min_monster = 2000;
1243  init_map_list(&add->exits_to);
1244  init_map_list(&add->exits_from);
1245  init_map_list(&add->tiled_maps);
1247  init_race_list(&add->monsters);
1248  add->npcs = new npc_list();
1249  add->readable = new npc_list();
1250  add->tiled_group = NULL;
1251 
1252  return add;
1253 }
1254 
1263 
1264  add_map(add, &tiled_map_list);
1265  return add;
1266 }
1267 
1277 static void merge_tiled_maps(struct_map_info *map, struct_map_info *tiled_map) {
1278  size_t g;
1279  struct_map_info *group = tiled_map->tiled_group;
1280  struct_map_info *change;
1281 
1282  while (group->tiled_maps.count > 0) {
1283  change = group->tiled_maps.maps[group->tiled_maps.count-1];
1284  change->tiled_group = map->tiled_group;
1285  add_map(change, &map->tiled_group->tiled_maps);
1286  group->tiled_maps.count--;
1287  }
1288 
1289  for (g = 0; g < tiled_map_list.count; g++) {
1290  if (tiled_map_list.maps[g] == group) {
1291  if (g < tiled_map_list.count-1)
1294  free(group);
1295  return;
1296  }
1297  }
1298  printf("tiled_map not in tiled_map_list!");
1299  abort();
1300 
1301 }
1302 
1311 static struct_map_info *get_map_info(const char *path) {
1312  struct_map_info *add;
1313  char *tmp;
1314 
1315  for (size_t map = 0; map < maps_list.count; map++) {
1316  if (strcmp(maps_list.maps[map]->path, path) == 0)
1317  return maps_list.maps[map];
1318  }
1319 
1320  add = create_map_info();
1321  add->path = strdup(path);
1322  tmp = strrchr((char *)path, '/');
1323  if (tmp)
1324  add->filename = strdup(tmp+1);
1325  else
1326  add->filename = strdup(path);
1327 
1328  add_map(add, &maps_list);
1329  return add;
1330 }
1331 
1338 static void list_map(const char *path) {
1339  for (auto map = found_maps.begin(); map != found_maps.end(); ++map) {
1340  if (strcmp(path, *map) == 0) {
1341  free(*map);
1342  found_maps.erase(map);
1343  return;
1344  }
1345  }
1346  printf("Map processed but not found in directory reading? %s\n", path);
1347 }
1348 
1359 static void add_map_to_region(struct_map_info *map, region *reg) {
1360  size_t test;
1361  int x, y;
1362 
1363  for (test = 0; test < region_count; test++) {
1364  if (regions[test]->reg == reg)
1365  break;
1366  }
1367  if (test == region_count) {
1368  if (test == region_allocated) {
1369  region_allocated++;
1371  regions[test] = (struct_region_info *)calloc(1, sizeof(struct_region_info));
1372  }
1373  region_count++;
1374  regions[test]->reg = reg;
1375  }
1376  add_map(map, &regions[test]->maps_list);
1377  if (sscanf(map->path, "/world/world_%d_%d", &x, &y) == 2) {
1378  regions[test]->sum_x += (x-100);
1379  regions[test]->sum_y += (y-100);
1380  regions[test]->sum++;
1381  regions[test]->is_world = 1;
1382  }
1383 }
1384 
1393 static void save_picture(FILE *file, gdImagePtr pic) {
1394  if (output_format == OF_PNG)
1395  gdImagePng(pic, file);
1396  else
1397  gdImageJpeg(pic, file, jpeg_quality);
1398 }
1399 
1407 static void add_region_link(mapstruct *source, mapstruct *dest) {
1408  region *s, *d;
1409 
1410  s = get_region_by_map(source);
1411  d = get_region_by_map(dest);
1412  if (s == d)
1413  return;
1414 
1415  region_links[s].insert(d);
1416 }
1417 
1426 static int is_slaying(object *item) {
1427  return (item->type == LOCKED_DOOR || item->type == SPECIAL_KEY || item->type == CONTAINER || item->type == CHECK_INV);
1428 }
1429 
1430 
1439 static struct_slaying_info *get_slaying_struct(const char *slaying) {
1440  for (size_t l = 0; l < slaying_count; l++) {
1441  if (!strcmp(slaying_info[l]->slaying, slaying))
1442  return slaying_info[l];
1443  }
1445  slaying_allocated += 10;
1447  }
1448 
1449  struct_slaying_info *add = (struct_slaying_info *)calloc(1, sizeof(struct_slaying_info));
1450  add->slaying = strdup(slaying);
1451  for (size_t l = 0; l < S_MAX; l++)
1452  init_map_list(&add->maps[l]);
1453 
1454  slaying_info[slaying_count] = add;
1455  slaying_count++;
1456 
1457  return add;
1458 }
1459 
1470 static void add_map_to_slaying(struct_slaying_info *info, int item, struct_map_info *map) {
1471  add_map(map, &info->maps[item]);
1472 }
1473 
1482 static void add_slaying(struct_map_info *map, object *item) {
1483  struct_slaying_info *info;
1484 
1485  if (!item->slaying)
1486  /* can be undefined */
1487  return;
1488 
1489  info = get_slaying_struct(item->slaying);
1490  if (item->type == LOCKED_DOOR)
1491  add_map_to_slaying(info, S_DOOR, map);
1492  else if (item->type == SPECIAL_KEY)
1493  add_map_to_slaying(info, S_KEY, map);
1494  else if (item->type == CONTAINER)
1495  add_map_to_slaying(info, S_CONTAINER, map);
1496  else if (item->type == DETECTOR)
1497  add_map_to_slaying(info, S_DETECTOR, map);
1498  else
1499  add_map_to_slaying(info, S_CONNECT, map);
1500 }
1501 
1510 static void check_slaying_inventory(struct_map_info *map, object *item) {
1511  FOR_INV_PREPARE(item, inv) {
1512  if (is_slaying(inv))
1513  add_slaying(map, inv);
1514  check_slaying_inventory(map, inv);
1515  } FOR_INV_FINISH();
1516 }
1517 
1518 static void generate_picture_path(const char *path, size_t pic_size, char *out, size_t len) {
1519  snprintf(out, len, "%s%s.x%zu%s", root, path, pic_size + 1, output_extensions[output_format]);
1520 }
1521 
1522 static void write_pictures_from_real_size(const char *path, gdImagePtr real, int width, int height) {
1523  char picpath[MAX_BUF];
1524 
1525  generate_picture_path(path, 0, picpath, sizeof(picpath));
1526  make_path_to_file(picpath);
1527  FILE *out = fopen(picpath, "wb+");
1528  save_picture(out, real);
1529  fclose(out);
1530 
1531  for (size_t i = 1; i < num_sizes; i++) {
1532  generate_picture_path(path, i, picpath, sizeof(picpath));
1533  gdImagePtr small = gdImageCreateTrueColor(width*sizes[i], height*sizes[i]);
1534  gdImageCopyResampled(small, real, 0, 0, 0, 0, width*sizes[i], height*sizes[i], width*size_large, height*size_large);
1535  out = fopen(picpath, "wb+");
1536  save_picture(out, small);
1537  fclose(out);
1538  gdImageDestroy(small);
1539  }
1540 }
1541 
1550 static void process_map(struct_map_info *info) {
1551  mapstruct *m;
1552  int x, y, isworld;
1553  gdImagePtr pic = nullptr;
1554  struct stat stats;
1555  struct stat statspic;
1556  char exit_path[500];
1557  char tmppath[MAX_BUF];
1558  char picpath[num_sizes][MAX_BUF];
1559  int needpic = 0;
1560  struct_map_info *link;
1561 
1562  if (list_unused_maps)
1563  list_map(info->path);
1564 
1565  if (show_maps)
1566  printf(" processing map %s\n", info->path);
1567 
1568  m = ready_map_name(info->path, 0);
1569  if (!m) {
1570  printf("couldn't load map %s\n", info->path);
1571  return;
1572  }
1573 
1574  do_exit_map(m);
1575 
1576  if (!rawmaps)
1577  do_auto_apply(m);
1578 
1579  info->level = m->difficulty;
1580  if (m->maplore) {
1581  info->lore = strdup(m->maplore);
1582  process_map_lore(info);
1583  }
1584  if (m->reset_group) {
1585  info->reset_group = add_string(m->reset_group);
1586  reset_groups.insert(m->reset_group);
1587  }
1588 
1589  isworld = (sscanf(info->path, "/world/world_%d_%d", &x, &y) == 2);
1590 
1591  if (m->name)
1592  info->name = strdup(m->name);
1593  else
1594  info->name = strdup(info->filename);
1595 
1596  info->cfregion = get_region_by_map(m);
1597  add_map_to_region(info, info->cfregion);
1598 
1599  for (int i = 0; i < num_sizes; i++) {
1600  generate_picture_path(info->path, i, picpath[i], sizeof(picpath[i]));
1601  }
1602 
1603  if (force_pics)
1604  needpic = 1;
1605  else if (generate_pics) {
1606  create_pathname(info->path, tmppath, MAX_BUF);
1607  stat(tmppath, &stats);
1608  if (stat(picpath[0], &statspic) || (statspic.st_mtime < stats.st_mtime))
1609  needpic = 1;
1610  }
1611  else
1612  needpic = 0;
1613 
1614  if (needpic) {
1615  pic = gdImageCreateTrueColor(MAP_WIDTH(m)*size_large, MAP_HEIGHT(m)*size_large);
1616  created_pics++;
1617  }
1618  else
1619  cached_pics++;
1620 
1621  for (x = 0; x < 4; x++)
1622  if (m->tile_path[x] != NULL) {
1623  path_combine_and_normalize(m->path, m->tile_path[x], exit_path, sizeof(exit_path));
1624  create_pathname(exit_path, tmppath, MAX_BUF);
1625  if (stat(tmppath, &stats)) {
1626  printf(" map %s doesn't exist in map %s, for tile %d.\n", exit_path, info->path, x);
1627  }
1628 
1629  if (isworld) {
1630  link = get_map_info(exit_path);
1631  add_map(link, &info->exits_from);
1632  add_map(info, &link->exits_to);
1633 
1634  if (do_regions_link) {
1635  mapstruct *link = ready_map_name(exit_path, 0);
1636 
1637  if (link && link != m) {
1638  /* no need to link a map with itself. Also, if the exit points to the same map, we don't
1639  * want to reset it. */
1640  add_region_link(m, link);
1641  link->reset_time = 1;
1642  link->in_memory = MAP_IN_MEMORY;
1643  delete_map(link);
1644  }
1645  }
1646  } else {
1647  link = get_map_info(exit_path);
1648  info->tiles[x] = link;
1649  if (link->tiled_group) {
1650  if (info->tiled_group && link->tiled_group != info->tiled_group) {
1651  merge_tiled_maps(info, link);
1652  continue;
1653  }
1654  if (link->tiled_group == info->tiled_group) {
1655  continue;
1656  }
1657  if (!info->tiled_group) {
1658  add_map(info, &link->tiled_group->tiled_maps);
1659  continue;
1660  }
1661  }
1662 
1663  if (!info->tiled_group) {
1664  info->tiled_group = create_tiled_map();
1665  add_map(info, &info->tiled_group->tiled_maps);
1666  }
1667  link->tiled_group = info->tiled_group;
1668  add_map(link, &info->tiled_group->tiled_maps);
1669  }
1670  }
1671 
1672  info->width = MAP_WIDTH(m);
1673  info->height = MAP_HEIGHT(m);
1674 
1675  for (x = MAP_WIDTH(m)-1; x >= 0; x--)
1676  for (y = MAP_HEIGHT(m)-1; y >= 0; y--) {
1677  FOR_MAP_PREPARE(m, x, y, item) {
1678  if (item->type == EXIT || item->type == TELEPORTER || item->type == PLAYER_CHANGER) {
1679  char ep[500];
1680  const char *start;
1681 
1682  if (!item->slaying) {
1683  ep[0] = '\0';
1684  if (warn_no_path)
1685  printf(" exit without any path at %d, %d on %s\n", item->x, item->y, info->path);
1686  } else {
1687  memset(ep, 0, 500);
1688  if (strcmp(item->slaying, "/!"))
1689  strcpy(ep, EXIT_PATH(item));
1690  else {
1691  if (!item->msg) {
1692  printf(" random map without message in %s at %d, %d\n", info->path, item->x, item->y);
1693  } else {
1694  /* Some maps have a 'exit_on_final_map' flag, ignore it. */
1695  start = strstr(item->msg, "\nfinal_map ");
1696  if (!start && strncmp(item->msg, "final_map", strlen("final_map")) == 0)
1697  /* Message start is final_map, nice */
1698  start = item->msg;
1699  if (start) {
1700  char *end = strchr((char *)start+1, '\n');
1701 
1702  start += strlen("final_map")+2;
1703  strncpy(ep, start, end-start);
1704  }
1705  }
1706  }
1707 
1708  if (strlen(ep)) {
1709  path_combine_and_normalize(m->path, ep, exit_path, 500);
1710  create_pathname(exit_path, tmppath, MAX_BUF);
1711  if (stat(tmppath, &stats)) {
1712  printf(" map %s doesn't exist in map %s, at %d, %d.\n", ep, info->path, item->x, item->y);
1713  } else {
1714  link = get_map_info(exit_path);
1715  add_map(link, &info->exits_from);
1716  add_map(info, &link->exits_to);
1717 
1718  if (do_regions_link) {
1719  mapstruct *link = ready_map_name(exit_path, 0);
1720 
1721  if (link && link != m) {
1722  /* no need to link a map with itself. Also, if the exit points to the same map, we don't
1723  * want to reset it. */
1724  add_region_link(m, link);
1725  link->reset_time = 1;
1726  link->in_memory = MAP_IN_MEMORY;
1727  delete_map(link);
1728  }
1729  }
1730  }
1731  }
1732  }
1733  } else if (is_slaying(item))
1734  add_slaying(info, item);
1735 
1736  check_equipment(item, info);
1737 
1738  check_slaying_inventory(info, item);
1739 
1740  if (QUERY_FLAG(item, FLAG_MONSTER)) {
1741  /* need to get the "real" archetype, as the item's archetype can certainly be a temporary one. */
1742  archetype *arch = find_archetype(item->arch->name);
1743 
1744  add_monster(item, info);
1745  if (arch != NULL && (QUERY_FLAG(item, FLAG_UNAGGRESSIVE) || QUERY_FLAG(item, FLAG_FRIENDLY)) && (item->msg != arch->clone.msg) && (item->msg != NULL))
1746  add_npc_to_map(info->npcs, item);
1747  } else if ((item->type == SIGN || item->type == BOOK) && (item->msg != item->arch->clone.msg) && (item->msg != NULL)) {
1748  add_npc_to_map(info->readable, item);
1749  }
1750 
1751  if (item->invisible)
1752  continue;
1753 
1754  if (needpic) {
1755  int sx, sy, hx, hy;
1756 
1757  if (gdfaces.size() <= item->face->number)
1758  gdfaces.resize(item->face->number + 1, nullptr);
1759 
1760  if (gdfaces[item->face->number] == NULL) {
1761  face_sets *fs = find_faceset(get_face_fallback(tileset, item->face->number));
1762 
1763  gdfaces[item->face->number] = gdImageCreateFromPngPtr(fs->faces[item->face->number].datalen, fs->faces[item->face->number].data);
1764  pics_allocated++;
1765  }
1766  if (item->head || item->more) {
1767  object_get_multi_size(item, &sx, &sy, &hx, &hy);
1768  } else {
1769  hx = 0;
1770  hy = 0;
1771  }
1772  if (gdfaces[item->face->number] != NULL && ((!item->head && !item->more) || (item->arch->clone.x+hx == 0 && item->arch->clone.y+hy == 0))) {
1773  gdImageCopy(pic, gdfaces[item->face->number], x*size_large, y*size_large, 0, 0, gdfaces[item->face->number]->sx, gdfaces[item->face->number]->sy);
1774  }
1775  }
1776  } FOR_MAP_FINISH();
1777  }
1778 
1779  if (needpic) {
1781  gdImageDestroy(pic);
1782  info->pic_was_done = 1;
1783  }
1784 
1785  m->reset_time = 1;
1786  m->in_memory = MAP_IN_MEMORY;
1787  delete_map(m);
1788 }
1789 
1793 static void write_world_map(void) {
1794 #define SIZE 50
1795  int x, y;
1796  FILE *out;
1797  int wx, wy;
1798  char file[500];
1799  char mapleft[10], maptop[10], mapright[10], mapbottom[10], mappath[5000];
1800  char name[100];
1801  gdImagePtr pic;
1802  gdImagePtr small;
1803  gdFontPtr font;
1804  int color;
1805 
1806  if (!world_map)
1807  return;
1808 
1809  printf("Generating world map in world.html...");
1810  fflush(stdout);
1811 
1812  pic = gdImageCreateTrueColor(SIZE*30, SIZE*30);
1813 
1814  strcpy(file, root);
1815  strcat(file, "/world.html");
1816 
1817  wx = 100;
1818  wy = 100;
1819 
1820  for (y = 0; y < 30; y++) {
1821  for (x = 0; x < 30; x++) {
1822  snprintf(name, sizeof(name), "world_%d_%d", wx, wy);
1823  snprintf(mapleft, sizeof(mapleft), "%d", SIZE*x);
1824  snprintf(maptop, sizeof(maptop), "%d", SIZE*y);
1825  snprintf(mapright, sizeof(mapright), "%d", SIZE*(x+1)-1);
1826  snprintf(mapbottom, sizeof(mapbottom), "%d", SIZE*(y+1)-1);
1827 
1828  snprintf(mappath, sizeof(mappath), "%s/world/%s.x1%s", root, name, output_extensions[output_format]);
1829 
1830  out = fopen(mappath, "rb");
1831  if (!out) {
1832  printf("\n warning: large pic not found for world_%d_%d", wx, wy);
1833  wx++;
1834  continue;
1835  }
1836  if (output_format == OF_PNG)
1837  small = gdImageCreateFromPng(out);
1838  else
1839  small = gdImageCreateFromJpeg(out);
1840  fclose(out);
1841  if (!small) {
1842  printf("\n warning: pic not found for world_%d_%d", wx, wy);
1843  wx++;
1844  continue;
1845  }
1846  gdImageCopyResized(pic, small, SIZE*x, SIZE*y, 0, 0, SIZE, SIZE, small->sx, small->sy);
1847  gdImageDestroy(small);
1848 
1849  wx++;
1850  }
1851  wy++;
1852  wx = 100;
1853  }
1854 
1855  snprintf(mappath, sizeof(mappath), "%s/world_raw%s", root, output_extensions[output_format]);
1856  out = fopen(mappath, "wb+");
1857  save_picture(out, pic);
1858  fclose(out);
1859 
1860  /* Write region names. */
1861  small = gdImageCreateTrueColor(SIZE*30, SIZE*30);
1862  font = gdFontGetGiant();
1863  color = gdImageColorAllocateAlpha(pic, 255, 0, 0, 20);
1864  for (size_t region = 0; region < region_allocated; region++) {
1865  if (!regions[region]->is_world || regions[region]->sum == 0)
1866  continue;
1867 
1868  x = regions[region]->sum_x*SIZE/regions[region]->sum+SIZE/2-strlen(regions[region]->reg->name)*font->w/2;
1869  y = regions[region]->sum_y*SIZE/regions[region]->sum+SIZE/2-font->h/2;
1870  gdImageString(small, font, x, y, (unsigned char *)regions[region]->reg->name, color);
1871  gdImageString(pic, font, x, y, (unsigned char *)regions[region]->reg->name, color);
1872 
1873  /* For exit/road map, size isn't the same. */
1874  x = regions[region]->sum_x*50/regions[region]->sum+50/2-strlen(regions[region]->reg->name)*font->w/2;
1875  y = regions[region]->sum_y*50/regions[region]->sum+50/2-font->h/2;
1876  gdImageString(infomap, font, x, y, (unsigned char *)regions[region]->reg->name, color);
1877  }
1878 
1879  snprintf(mappath, sizeof(mappath), "%s/world_regions%s", root, output_extensions[output_format]);
1880  out = fopen(mappath, "wb+");
1881  save_picture(out, small);
1882  fclose(out);
1883  gdImageDestroy(small);
1884 
1885  snprintf(mappath, sizeof(mappath), "%s/world%s", root, output_extensions[output_format]);
1886  out = fopen(mappath, "wb+");
1887  save_picture(out, pic);
1888  fclose(out);
1889  gdImageDestroy(pic);
1890 
1891  printf(" done.\n");
1892 #undef SIZE
1893 }
1894 
1896 static void fix_map_names(void) {
1897  for (size_t map = 0; map < maps_list.count; map++) {
1898  if (maps_list.maps[map]->name)
1899  continue;
1900  if (!maps_list.maps[map]->filename) {
1901  printf("map without path!\n");
1902  abort();
1903  }
1904  maps_list.maps[map]->name = strdup(maps_list.maps[map]->filename);
1905  }
1906 }
1907 
1914 static void fix_tiled_map(void) {
1915  size_t map, tile;
1916  char name[500];
1917  char *slash, *test;
1918  region *cfregion;
1919 
1920  for (map = 0; map < tiled_map_list.count; map++) {
1921  if (tiled_map_list.maps[map]->tiled_maps.count == 0) {
1922  printf("empty tiled map group!");
1923  abort();
1924  }
1925 
1926  snprintf(name, sizeof(name), "tiled_map_group_%zu", map);
1927  tiled_map_list.maps[map]->filename = strdup(name);
1928 
1929  cfregion = NULL;
1930  test = NULL;
1931 
1932  for (tile = 0; tile < tiled_map_list.maps[map]->tiled_maps.count; tile++) {
1933  if (tiled_map_list.maps[map]->tiled_maps.maps[tile]->cfregion == NULL)
1934  /* map not processed, ignore it. */
1935  continue;
1936 
1937  if (!cfregion)
1938  cfregion = tiled_map_list.maps[map]->tiled_maps.maps[tile]->cfregion;
1939  else if (cfregion != tiled_map_list.maps[map]->tiled_maps.maps[tile]->cfregion) {
1940  printf("*** warning: tiled maps %s and %s not in same region (%s and %s).\n",
1943  cfregion = NULL;
1944  }
1945 
1946  if (strcmp(tiled_map_list.maps[map]->tiled_maps.maps[tile]->name, tiled_map_list.maps[map]->tiled_maps.maps[tile]->filename)) {
1947  /* map has a custom name, use it */
1948  if (!test)
1949  test = tiled_map_list.maps[map]->tiled_maps.maps[tile]->name;
1950  }
1951  }
1952 
1953  if (!test) {
1954  /* this can happen of course if only partial maps were processed, but well... */
1955  printf("*** warning: tiled map without any name. First map path %s\n", tiled_map_list.maps[map]->tiled_maps.maps[0]->path);
1956  test = name;
1957  }
1958 
1959  tiled_map_list.maps[map]->name = strdup(test);
1960  tiled_map_list.maps[map]->cfregion = cfregion;
1961 
1962  strncpy(name, tiled_map_list.maps[map]->tiled_maps.maps[0]->path, sizeof(name));
1963  slash = strrchr(name, '/');
1964  if (!slash)
1965  snprintf(name, sizeof(name), "/");
1966  else
1967  *(slash+1) = '\0';
1968  strncat(name, tiled_map_list.maps[map]->filename, sizeof(name) - strlen(name) - 1);
1969  tiled_map_list.maps[map]->path = strdup(name);
1970  }
1971 }
1972 
1983 static void fix_exits_for_map(struct_map_info *current, struct_map_list *from, int is_from) {
1984  int map, max;
1985  struct_map_info *group;
1986 
1987  max = from->count-1;
1988  for (map = max; map >= 0; map--) {
1989  if (from->maps[map]->tiled_group) {
1990  group = from->maps[map]->tiled_group;
1991  if (map != max)
1992  from->maps[map] = from->maps[max];
1993  from->count--;
1994  max--;
1995  add_map(group, from);
1996  add_map(current->tiled_group ? current->tiled_group : current, is_from ? &group->exits_to : &group->exits_from);
1997  }
1998  }
1999 }
2000 
2002 static void fix_exits_to_tiled_maps(void) {
2003  int map, max;
2004  struct_map_info *group;
2005 
2006  for (map = 0; static_cast<size_t>(map) < maps_list.count; map++) {
2009  }
2010 
2011  for (size_t region = 0; region < region_count; region++) {
2012  max = regions[region]->maps_list.count-1;
2013  for (map = max; map >= 0; map--) {
2014  if (regions[region]->maps_list.maps[map]->tiled_group) {
2015  group = regions[region]->maps_list.maps[map]->tiled_group;
2016  if (map != max)
2019  max--;
2020  add_map(group, &regions[region]->maps_list);
2021  }
2022  }
2023  }
2024 }
2025 
2030 static void fix_tiled_map_monsters(void) {
2031  int map, max;
2032  struct_map_info *group;
2033 
2034  for (size_t race = 0; race < races.count; race++) {
2035  max = races.races[race]->origin.count-1;
2036  for (map = max; map >= 0; map--) {
2037  if (races.races[race]->origin.maps[map]->tiled_group) {
2038  group = races.races[race]->origin.maps[map]->tiled_group;
2039  if (map != max)
2040  races.races[race]->origin.maps[map] = races.races[race]->origin.maps[max];
2041  races.races[race]->origin.count--;
2042  max--;
2043  add_map(group, &races.races[race]->origin);
2044  }
2045  }
2046  }
2047 
2048  for (map = 0; static_cast<size_t>(map) < maps_list.count; map++) {
2049  if (maps_list.maps[map]->tiled_group) {
2050  for (size_t race = 0; race < maps_list.maps[map]->monsters.count; race++) {
2052  }
2053  }
2054  }
2055 }
2056 
2058  size_t test;
2059  char picpath[500];
2060  struct stat stats;
2061 
2062  for (size_t size = 0; size < num_sizes; size++) {
2063  generate_picture_path(map->path, size, picpath, sizeof(picpath));
2064  if (stat(picpath, &stats))
2065  return 1;
2066  }
2067 
2068  for (test = 0; test < map->tiled_maps.count; test++) {
2069  if (map->tiled_maps.maps[test]->pic_was_done)
2070  return 1;
2071  }
2072 
2073  return 0;
2074 }
2075 
2088  int xmin = 0, xmax = 0, ymin = 0, ymax = 0, count, last;
2089  size_t tiled;
2090  char picpath[500];
2091  gdImagePtr large, load;
2092  FILE *out;
2093  struct_map_info *current;
2094 
2095  if (!generate_pics)
2096  return;
2097 
2098  printf(" Generating composite map for %s...", map->name);
2099  fflush(stdout);
2100 
2101  if (!tiled_map_need_pic(map)) {
2102  printf(" already uptodate.\n");
2103  return;
2104  }
2105 
2106  count = map->tiled_maps.count;
2107  if (count == 0) {
2108  printf("Tiled map without tiled maps?\n");
2109  abort();
2110  }
2111  map->tiled_maps.maps[0]->processed = 1;
2112  map->tiled_maps.maps[0]->tiled_x_from = 0;
2113  map->tiled_maps.maps[0]->tiled_y_from = 0;
2114 
2115  while (count > 0) {
2116  last = count;
2117 
2118  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2119  current = map->tiled_maps.maps[tiled];
2120  if (current->processed != 1)
2121  continue;
2122 
2123  count--;
2124 
2125  if ((current->tiles[0]) && (current->tiles[0]->processed == 0)) {
2126  current->tiles[0]->processed = 1;
2127  current->tiles[0]->tiled_x_from = current->tiled_x_from;
2128  current->tiles[0]->tiled_y_from = current->tiled_y_from-current->tiles[0]->height;
2129  }
2130  if ((current->tiles[1]) && (current->tiles[1]->processed == 0)) {
2131  current->tiles[1]->processed = 1;
2132  current->tiles[1]->tiled_x_from = current->tiled_x_from+current->width;
2133  current->tiles[1]->tiled_y_from = current->tiled_y_from;
2134  }
2135  if ((current->tiles[2]) && (current->tiles[2]->processed == 0)) {
2136  current->tiles[2]->processed = 1;
2137  current->tiles[2]->tiled_x_from = current->tiled_x_from;
2138  current->tiles[2]->tiled_y_from = current->tiled_y_from+current->height;
2139  }
2140  if ((current->tiles[3]) && (current->tiles[3]->processed == 0)) {
2141  current->tiles[3]->processed = 1;
2142  current->tiles[3]->tiled_x_from = current->tiled_x_from-current->tiles[3]->width;
2143  current->tiles[3]->tiled_y_from = current->tiled_y_from;
2144  }
2145  }
2146 
2147  if (last == count) {
2148  printf("do_tiled_map_picture: didn't process any map in %s (%d left)??\n", map->path, last);
2149  abort();
2150  }
2151  }
2152 
2153  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2154  if (map->tiled_maps.maps[tiled]->tiled_x_from < xmin)
2155  xmin = map->tiled_maps.maps[tiled]->tiled_x_from;
2156  if (map->tiled_maps.maps[tiled]->tiled_y_from < ymin)
2157  ymin = map->tiled_maps.maps[tiled]->tiled_y_from;
2158  if (map->tiled_maps.maps[tiled]->tiled_x_from+map->tiled_maps.maps[tiled]->width > xmax)
2159  xmax = map->tiled_maps.maps[tiled]->tiled_x_from+map->tiled_maps.maps[tiled]->width;
2160  if (map->tiled_maps.maps[tiled]->tiled_y_from+map->tiled_maps.maps[tiled]->height > ymax)
2161  ymax = map->tiled_maps.maps[tiled]->tiled_y_from+map->tiled_maps.maps[tiled]->height;
2162  }
2163 
2164  large = gdImageCreateTrueColor(size_large*(xmax-xmin), size_large*(ymax-ymin));
2165 
2166  for (tiled = 0; tiled < map->tiled_maps.count; tiled++) {
2167  generate_picture_path(map->tiled_maps.maps[tiled]->path, 0, picpath, sizeof(picpath));
2168 
2169  out = fopen(picpath, "rb");
2170  if (!out) {
2171  printf("\n do_tiled_map_picture: warning: pic file %s not found for %s (errno=%d)\n", picpath, map->tiled_maps.maps[tiled]->path, errno);
2172  continue;
2173  }
2174  if (output_format == OF_PNG)
2175  load = gdImageCreateFromPng(out);
2176  else
2177  load = gdImageCreateFromJpeg(out);
2178  fclose(out);
2179  if (!load) {
2180  printf("\n do_tiled_map_picture: warning: pic not found for %s\n", map->tiled_maps.maps[tiled]->path);
2181  continue;
2182  }
2183  gdImageCopy(large, load, size_large*(map->tiled_maps.maps[tiled]->tiled_x_from-xmin), size_large*(map->tiled_maps.maps[tiled]->tiled_y_from-ymin), 0, 0, load->sx, load->sy);
2184  gdImageDestroy(load);
2185  }
2186 
2187  write_pictures_from_real_size(map->path, large, xmax-xmin, ymax-ymin);
2188 
2189  gdImageDestroy(large);
2190 
2191  printf(" done.\n");
2192 }
2193 
2196 
2197  do_tiled_map_picture(map);
2198 
2201 // write_map_page(map);
2202 }
2203 
2205 static void write_tiled_maps(void) {
2206  printf("Writing tiled map information...\n");
2207 
2208  for (size_t map = 0; map < tiled_map_list.count; map++)
2210 
2211  printf(" done.\n");
2212 }
2213 
2214 static std::vector<quest_definition *> system_quests;
2215 
2216 static void quest_callback(const quest_definition *quest, void *) {
2217  if (list_system_quests || !quest->quest_is_system) {
2218  system_quests.push_back(const_cast<quest_definition *>(quest));
2219  }
2220 }
2221 
2222 static std::shared_ptr<inja::Environment> env;
2223 static nlohmann::json all_data;
2224 static std::set<std::string> rendered_templates;
2225 static std::map<struct_map_info *, std::string> reverse_maps;
2226 static std::map<region *, std::string> reverse_regions;
2233 static struct_map_info *find_map_by_key(const std::string &key) {
2234  auto found = std::find_if(reverse_maps.cbegin(), reverse_maps.cend(), [&key] (auto c) { return c.second == key; });
2235  if (found != reverse_maps.cend())
2236  return found->first;
2237  return nullptr;
2238 }
2239 
2245 static region *find_region_by_key(const std::string &key) {
2246  auto found = std::find_if(reverse_regions.cbegin(), reverse_regions.cend(), [&key] (auto c) { return c.second == key; });
2247  if (found != reverse_regions.cend())
2248  return found->first;
2249  return nullptr;
2250 }
2251 
2257 static nlohmann::json create_maps_array(struct_map_list &maps) {
2258  nlohmann::json result = nlohmann::json::array();
2259  for (size_t m = 0; m < maps.count; m++) {
2260  auto map = reverse_maps.find(maps.maps[m]);
2261  if (map != reverse_maps.end()) {
2262  result.push_back(map->second);
2263  }
2264  }
2265  return result;
2266 }
2267 
2273 static nlohmann::json create_npc_array(npc_list &list) {
2274  nlohmann::json result;
2275  for (size_t n = 0; n < list.size(); n++) {
2276  auto npc = list[n];
2277  result.push_back({
2278  { "name", npc->name },
2279  { "x", npc->x },
2280  { "y", npc->y },
2281  { "message", npc->message },
2282  });
2283  }
2284  return result;
2285 }
2286 
2292 static nlohmann::json create_race_array(struct_race_list &list) {
2293  nlohmann::json result;
2294  for (size_t n = 0; n < list.count; n++) {
2295  auto race = list.races[n];
2296  result.push_back({
2297  { "name", race->name },
2298  { "count", race->count },
2299  });
2300  }
2301  return result;
2302 }
2303 
2310  nlohmann::json ret = nlohmann::json::array();
2311  for (size_t m = 0; m < list.count; m++) {
2312  auto q = list.list[m];
2313  if (!q->map || !q->description)
2314  continue;
2315  ret.push_back({
2316  { "map", reverse_maps.find(q->map)->second },
2317  { "description", q->description },
2318  { "quest", q->quest->name },
2319  { "number", q->quest->number },
2320  });
2321  }
2322 
2323  return ret;
2324 }
2325 
2326 static const char *remove_trailing_slash(const char *path)
2327 {
2328  return path && path[0] == '/' ? path + 1 : path;
2329 }
2330 
2337 static nlohmann::json create_map_object(struct_map_info *map, const std::string &key) {
2338  return {
2339  { "_key", key },
2340  { "name", map->name },
2341  { "path", remove_trailing_slash(map->path) },
2342  { "region", map->cfregion ? reverse_regions[map->cfregion] : "reg_ffff" },
2343  { "level", map->level },
2344  { "reset_group", map->reset_group ? map->reset_group : "" },
2345  { "lore", map->lore && map->lore[0] ? map->lore : "" },
2346  { "exits_to", create_maps_array(map->exits_to) },
2347  { "exits_from", create_maps_array(map->exits_from) },
2348  { "npcs", create_npc_array(*map->npcs) },
2349  { "readables", create_npc_array(*map->readable) },
2350  { "monsters", create_race_array(map->monsters) },
2351  { "quests", create_map_in_quest_array(map->quests) },
2352  };
2353 }
2354 
2361 static nlohmann::json create_quest_object(struct_quest *quest, const std::string &key) {
2362  return {
2363  { "_key", key },
2364  { "number", quest->number },
2365  { "name", quest->name ? quest->name : "" },
2366  { "description", quest->description ? quest->description : "" },
2367  { "main_map", quest->mainmap ? reverse_maps.find(quest->mainmap)->second : "" },
2368  { "maps", create_map_in_quest_array(quest->maps) },
2369  };
2370 }
2371 
2377  char buf[50];
2378  for (size_t map = 0; map < list.count; map++) {
2379  auto cur = list.maps[map];
2380  if (cur->tiled_group)
2381  continue;
2382  snprintf(buf, sizeof(buf), "map_%04lu", map);
2383  reverse_maps.insert(std::make_pair(cur, buf));
2384  qsort(cur->exits_to.maps, cur->exits_to.count, sizeof(struct_map_info *), sort_map_info);
2385  qsort(cur->exits_from.maps, cur->exits_from.count, sizeof(struct_map_info *), sort_map_info);
2386  qsort(cur->monsters.races, cur->monsters.count, sizeof(struct_race *), sort_race);
2387  }
2388 }
2389 
2396  for (size_t map = 0; map < src.count; map++)
2397  add_map(src.maps[map], &dest);
2398 }
2399 
2405 static nlohmann::json create_region_array(const std::set<region *> &regions) {
2406  nlohmann::json ret = nlohmann::json::array();
2407  for (auto reg : regions) {
2408  auto r = reverse_regions.find(reg);
2409  if (r != reverse_regions.end()) {
2410  ret.push_back((*r).second);
2411  }
2412  }
2413  return ret;
2414 }
2415 
2416 static inja::TemplateStorage templateCache;
2417 static inja::Template get_template(const std::string &filename) {
2418  auto find = templateCache.find(filename);
2419  if (find != templateCache.end()) {
2420  return find->second;
2421  }
2422  inja::Template parsed = env->parse_template(filename);
2423  templateCache[filename] = parsed;
2424  return parsed;
2425 }
2426 
2431 static void fill_json(nlohmann::json &json) {
2432  nlohmann::json maps;
2433  char buf[10];
2434  struct_map_list all_maps;
2435  bool need_unknown_region = false;
2436  nlohmann::json search;
2437 
2438  init_map_list(&all_maps);
2439  append_map_list(all_maps, maps_list);
2440  append_map_list(all_maps, tiled_map_list);
2441  qsort(all_maps.maps, all_maps.count, sizeof(struct_map_info *), sort_map_info);
2442 
2443  fill_reverse_maps(all_maps);
2444 
2445  for (size_t reg = 0; reg < region_count; reg++) {
2446  auto region = regions[reg];
2447  snprintf(buf, sizeof(buf), "reg_%04lu", reg);
2448  reverse_regions.insert(std::make_pair(region->reg, buf));
2449  }
2450 
2451  for (size_t reg = 0; reg < region_count; reg++) {
2452  auto region = regions[reg];
2453  qsort(region->maps_list.maps, region->maps_list.count, sizeof(struct_map_info *), sort_map_info);
2454  nlohmann::json r = {
2455  { "_key", reverse_regions[region->reg] },
2456  { "_index", reg },
2457  { "name", region->reg->name },
2458  { "longname", region->reg->longname },
2459  { "description", region->reg->msg ? region->reg->msg : "" },
2460  { "maps", create_maps_array(region->maps_list) },
2461  { "links", create_region_array(region_links[region->reg]) },
2462  };
2463  json["regions"].push_back(r);
2464  auto link = env->render(get_template("search-links/region"), r);
2465  search["reg_" + std::to_string(reg)] = {
2466  { "type" , SearchType::Region },
2467  { "name", region->reg->longname },
2468  { "text", std::string(region->reg->msg ? region->reg->msg : "") },
2469  { "url", link },
2470  };
2471  }
2472 
2473  size_t map_index = 0;
2474  for (auto map : reverse_maps) {
2475  auto cur = map.first;
2476  if (cur->tiled_group)
2477  continue;
2478  if (cur->cfregion == nullptr)
2479  need_unknown_region = true;
2480  auto m = create_map_object(cur, map.second);
2481  m["_index"] = map_index;
2482  json["maps"].push_back(m);
2483  auto link = env->render(get_template("search-links/map"), m);
2484  search["map_" + std::to_string(map_index++)] = {
2485  { "type", SearchType::Map },
2486  { "name", cur->name },
2487  { "text", std::string(cur->lore ? cur->lore : "") },
2488  { "url", link },
2489  };
2490  }
2491 
2492  if (need_unknown_region) {
2493  json["regions"].push_back({
2494  { "_key", "reg_ffff" },
2495  { "name", "unknown" },
2496  { "longname", "unknown" },
2497  { "description", "unknown" },
2498  { "maps", nlohmann::json::array() },
2499  { "links", nlohmann::json::array() },
2500  });
2501  }
2502 
2503  json["reset_groups"] = nlohmann::json::array();
2504  for (const auto &rg : reset_groups) {
2505  json["reset_groups"].push_back(rg);
2506  }
2507 
2508  json["items"] = nlohmann::json::array();
2509  for (size_t idx = 0; idx < special_equipment.size(); idx++) {
2510  auto eq = special_equipment[idx];
2511  nlohmann::json item = {
2512  { "_index", idx },
2513  { "name", eq->name },
2514  { "power", eq->power },
2515  { "calc_power", eq->calc_power },
2516  { "diff", eq->diff },
2517  { "maps", create_maps_array(eq->origin) },
2518  };
2519  json["items"][idx] = item;
2520  auto link = env->render(get_template("search-links/item"), item);
2521  search["item_" + std::to_string(idx)] = {
2522  { "type", SearchType::Item },
2523  { "name", eq->name },
2524  { "url", link },
2525  };
2526  }
2527 
2528  json["monsters"] = nlohmann::json::array();
2529  for (size_t item = 0; item < races.count; item++) {
2530  auto race = races.races[item];
2531  qsort(race->origin.maps, race->origin.count, sizeof(struct_map_info *), sort_map_info);
2532  nlohmann::json m = {
2533  { "_index", item },
2534  { "name", race->name },
2535  { "count", race->count },
2536  { "maps", create_maps_array(race->origin) },
2537  };
2538  json["monsters"].push_back(m);
2539  auto link = env->render(get_template("search-links/monster"), m);
2540  search["monster_" + std::to_string(item)] = {
2541  { "type", SearchType::Monster },
2542  { "name", race->name },
2543  { "url", link },
2544  };
2545  }
2546 
2547  json["system_quests"] = nlohmann::json::array();
2548  for (size_t q = 0; q < system_quests.size(); q++) {
2549  auto quest = system_quests[q];
2550  nlohmann::json j({
2551  { "_index", q },
2552  { "code", quest->quest_code },
2553  { "title", quest->quest_title },
2554  { "description", quest->quest_description ? quest->quest_description : "" },
2555  { "replayable", quest->quest_restart },
2556  { "steps", nlohmann::json::array() },
2557  { "maps", nlohmann::json::array() },
2558  });
2559 
2560  if (detail_quests) {
2561  std::sort(quest->steps.begin(), quest->steps.end(), [] (auto left, auto right) { return left->step < right->step; });
2562  for (size_t s = 0; s < quest->steps.size(); s++) {
2563  j["steps"].push_back({
2564  { "description", quest->steps[s]->step_description ? quest->steps[s]->step_description : "" },
2565  { "is_completion", quest->steps[s]->is_completion_step ? true : false },
2566  });
2567  }
2568 
2569  auto qim = find_quest_info(quest->quest_code);
2570  if (qim) {
2571  for (size_t m = 0; m < qim->maps.count; m++) {
2572  auto map = reverse_maps.find(qim->maps.list[m]->map);
2573  assert(map != reverse_maps.end());
2574  j["maps"].push_back({
2575  { "description", qim->maps.list[m]->description },
2576  { "map", map->second },
2577  });
2578  }
2579  }
2580  }
2581  json["system_quests"].push_back(j);
2582  search["quest_" + std::to_string(q)] = {
2583  { "type", SearchType::Quest },
2584  { "name", quest->quest_title ? quest->quest_title : "" },
2585  { "text", quest->quest_description ? quest->quest_description : "" },
2586  { "url", "system_quests.html#q" + std::to_string(q) },
2587  };
2588  }
2589 
2590  json["slaying"] = nlohmann::json::array();
2591  for (size_t s = 0; s < slaying_count; s++) {
2592  auto info = slaying_info[s];
2593  json["slaying"].push_back({
2594  { "slaying", info->slaying },
2595  { "doors", create_maps_array(info->maps[S_DOOR]) },
2596  { "keys", create_maps_array(info->maps[S_KEY]) },
2597  { "containers", create_maps_array(info->maps[S_CONTAINER]) },
2598  { "detectors", create_maps_array(info->maps[S_DETECTOR]) },
2599  { "connections", create_maps_array(info->maps[S_CONNECT]) },
2600  });
2601  }
2602 
2603  json["quests"] = nlohmann::json::array();
2604  for (int quest = 0; quest < quests_count; quest++) {
2605  qsort(quests[quest]->maps.list, quests[quest]->maps.count, sizeof(struct_map_in_quest *), sort_struct_map_in_quest);
2606  char buf[100];
2607  snprintf(buf, sizeof(buf), "quest_%d", quests[quest]->number);
2608  json["quests"].push_back(create_quest_object(quests[quest], buf));
2609  }
2610 
2611  json["has_search"] = build_search_file;
2612  if (build_search_file) {
2613  std::string out(root);
2614  out += "/search_data.js";
2615  std::ofstream sf(out, std::ios_base::trunc);
2616  sf << "var search_data = " << search << ";" << std::endl;
2617  sf << "var search_type = { ";
2618  std::string sep;
2619  for (int i = 1; i < int(SearchType::Count); i++) {
2620  sf << sep << i << ": \"" << SearchName[i] << "\"";
2621  sep = ", ";
2622  }
2623  sf << " };" << std::endl;
2624  }
2625 }
2626 
2628 static std::vector<std::string> path_stack;
2629 
2630 void add_template_to_render(const std::string &template_name, const std::string &output_name, const std::string &param);
2631 
2637 static std::string path_from_current(const std::string &path) {
2638  auto p(path);
2639  char rel[1000];
2640  if (p[0] != '/')
2641  p = '/' + p;
2642  auto current(path_stack.back());
2643  if (current[0] != '/')
2644  current = '/' + current;
2645  relative_path(current.c_str(), p.c_str(), rel);
2646  return rel;
2647 }
2648 
2654 static nlohmann::json generate_page_and_link(inja::Arguments &args) {
2655  auto template_name = args.at(0)->get<std::string>();
2656  auto output_name(template_name);
2657  auto param = (args.size() > 1 ? args.at(1)->get<std::string>() : "");
2658 
2659  if (!param.empty()) {
2660  output_name = param + "_" + output_name;
2661  if (param.substr(0, 4) == "map_") {
2662  auto map = find_map_by_key(param);
2663  if (map != nullptr) {
2664  output_name = std::string(map->path + 1) + ".html";
2665  }
2666  }
2667  if (param.substr(0, 4) == "reg_") {
2668  auto reg = find_region_by_key(param);
2669  if (reg != nullptr) {
2670  output_name = std::string(reg->name) + ".html";
2671  }
2672  }
2673  }
2674 
2675  if (template_name != "search_data.js" && template_name != "search_index.js")
2676  add_template_to_render(template_name, output_name, param);
2677  return path_from_current(output_name);
2678 }
2679 
2685 static nlohmann::json generate_picture_link(inja::Arguments &args) {
2686  auto what = args.at(0)->get<std::string>();
2687  if (what.substr(0, 4) == "map_") {
2688  auto map = find_map_by_key(what);
2689  if (map == nullptr)
2690  return "";
2691  int size = 0;
2692  if (args.size() > 1) {
2693  size = args.at(1)->get<int>() - 1;
2694  }
2695  char picpath[1000];
2696  snprintf(picpath, sizeof(picpath), "%s.x%d%s", map->path, size + 1, output_extensions[output_format]);
2697  return path_from_current(picpath);
2698  }
2699  return "";
2700 }
2701 
2706 public:
2707  std::string template_name;
2708  std::string output_name;
2709  std::string param;
2710 };
2711 static std::vector<pageToRender> pages;
2719 void add_template_to_render(const std::string &template_name, const std::string &output_name, const std::string &param) {
2720  auto on(output_name);
2721  if (on[0] != '/')
2722  on = '/' + on;
2723  if (rendered_templates.find(on) != rendered_templates.end())
2724  return;
2725 
2726  rendered_templates.insert(on);
2727  pageToRender r;
2728  r.template_name = template_name;
2729  r.output_name = on;
2730  r.param = param;
2731  pages.push_back(r);
2732 }
2733 
2734 static std::vector<std::string> split(const std::string &field, const std::string &by) {
2735  std::vector<std::string> result;
2736  size_t start = 0, found;
2737  while ((found = field.find(by, start)) != std::string::npos) {
2738  result.push_back(field.substr(start, found - start));
2739  start = found + 1;
2740  }
2741  result.push_back(field.substr(start));
2742  return result;
2743 }
2744 
2745 static std::string templates_root("templates/");
2746 static std::vector<std::string> templates;
2751 static void init_renderer_env() {
2752  env = std::make_shared<inja::Environment>(templates_root, std::string(root) + "/");
2753  env->add_callback("link_to_page", generate_page_and_link);
2754  env->add_callback("substr", [] (inja::Arguments &args) {
2755  std::string str = args.at(0)->get<std::string>();
2756  size_t start = args.at(1)->get<size_t>();
2757  size_t len = args.size() > 2 ? args.at(2)->get<size_t>() : std::string::npos;
2758  return str.substr(start, len);
2759  });
2760  env->add_callback("picture", generate_picture_link);
2761  env->add_callback("pad", [] (inja::Arguments &args) {
2762  char buf[50];
2763  int val = args.at(0)->get<int>(), digits = args.at(1)->get<int>();
2764  snprintf(buf, sizeof(buf), "%0*d", digits, val);
2765  return std::string(buf);
2766  });
2767  env->add_callback("path_to_root", 0, [] (inja::Arguments &) {
2768  std::string root;
2769  auto current(path_stack.back());
2770  if (current[0] == '/')
2771  current = current.substr(1);
2772  size_t start = 0;
2773  while ((start = current.find('/', start)) != std::string::npos) {
2774  start++;
2775  root += "../";
2776  }
2777  return root;
2778  });
2779  env->add_callback("get_by_field", 3, [] (inja::Arguments &args) {
2780  const auto &src = args.at(0);
2781  auto field = args.at(1)->get<std::string>();
2782  const auto &value = args.at(2);
2783  auto found = std::find_if(src->begin(), src->end(), [&field, &value] (auto item) {
2784  return item[field] == *value;
2785  });
2786  if (found == src->end()) {
2787  return nlohmann::json();
2788  }
2789  return *found;
2790  });
2791  env->add_callback("get_list_by_field", 3, [] (inja::Arguments &args) {
2792  nlohmann::json ret = nlohmann::json::array();
2793  const auto &src = args.at(0);
2794  auto field = args.at(1)->get<std::string>();
2795  const auto filter = args.at(2);
2796  if (filter->is_array()) {
2797  std::copy_if(src->begin(), src->end(), std::back_inserter(ret), [&] (auto &item) {
2798  auto val = item[field];
2799  return std::find_if(filter->begin(), filter->end(), [&] (auto li) { return val == li; }) != filter->end();
2800  });
2801  } else {
2802  std::copy_if(src->begin(), src->end(), std::back_inserter(ret), [&] (auto &item) {
2803  return filter->get<std::string>() == item[field];
2804  });
2805  }
2806  return ret;
2807  });
2808  env->add_callback("sort", [] (inja::Arguments &args) {
2809  const auto &src = args.at(0);
2810  std::vector<nlohmann::json> ret;
2811  for (auto i : *src) {
2812  ret.push_back(i);
2813  }
2814  auto fields = split(args.at(1)->get<std::string>(), ",");
2815  bool invert = args.size() > 2 ? args.at(2)->get<bool>() : false;
2816  bool ignore_case = args.size() > 3 ? args.at(3)->get<bool>() : true;
2817  std::sort(ret.begin(), ret.end(), [&] (auto left, auto right) {
2818  for (auto field : fields) {
2819  nlohmann::json l = left[field], r = right[field];
2820  if (ignore_case && l.is_string() && r.is_string()) {
2821  std::string ls(l.get<std::string>()), rs(r.get<std::string>());
2822  std::transform(ls.begin(), ls.end(), ls.begin(), [](unsigned char c){ return std::tolower(c); });
2823  std::transform(rs.begin(), rs.end(), rs.begin(), [](unsigned char c){ return std::tolower(c); });
2824  if (ls == rs) {
2825  continue;
2826  }
2827  return invert ? (rs < ls) : (ls < rs);
2828  }
2829  if (r == l) {
2830  continue;
2831  }
2832  return invert ? (r < l) : (l < r);
2833  }
2834  return false;
2835  });
2836  return ret;
2837  });
2838 
2839  env->set_trim_blocks(true);
2840  env->set_lstrip_blocks(true);
2841 }
2842 
2844 static const char *ignore_path[] = {
2845  "/Info",
2846  "/editor",
2847  "/python",
2848  "/styles",
2849  "/templates",
2850  "/test",
2851  "/unlinked",
2852  NULL };
2853 
2855 static const char *ignore_name[] = {
2856  ".",
2857  "..",
2858  ".git",
2859  ".svn",
2860  "README",
2861  NULL };
2862 
2869 static void find_maps(const char *from) {
2870  struct dirent *file;
2871  struct stat statbuf;
2872  int status, ignore;
2873  char path[1024], full[HUGE_BUF];
2874  DIR *dir;
2875 
2876  for (ignore = 0; ignore_path[ignore] != NULL; ignore++) {
2877  if (strcmp(from, ignore_path[ignore]) == 0)
2878  return;
2879  }
2880 
2881  snprintf(path, sizeof(path), "%s/%s%s", settings.datadir, settings.mapdir, from);
2882  dir = opendir(path);
2883 
2884  if (dir) {
2885  for (file = readdir(dir); file; file = readdir(dir)) {
2886 
2887  for (ignore = 0; ignore_name[ignore] != NULL; ignore++) {
2888  if (strcmp(file->d_name, ignore_name[ignore]) == 0)
2889  break;
2890  }
2891  if (ignore_name[ignore] != NULL)
2892  continue;
2893 
2894  snprintf(full, sizeof(full), "%s/%s", path, file->d_name);
2895 
2896  status = stat(full, &statbuf);
2897  snprintf(full, sizeof(full), "%s/%s", from, file->d_name);
2898  if ((status != -1) && (S_ISDIR(statbuf.st_mode))) {
2899  find_maps(full);
2900  continue;
2901  }
2902  found_maps.push_back(strdup(full));
2903  }
2904  closedir(dir);
2905  }
2906 }
2907 
2909 static void dump_unused_maps(void) {
2910  FILE *dump;
2911  char path[1024];
2912 
2913  snprintf(path, sizeof(path), "%s/%s", root, "maps.unused");
2914  dump = fopen(path, "w+");
2915  if (dump == NULL) {
2916  printf("Unable to open file maps.unused!\n");
2917  return;
2918  }
2919  for (auto map = found_maps.cbegin(); map != found_maps.cend(); ++map) {
2920  fprintf(dump, "%s\n", *map);
2921  }
2922  fclose(dump);
2923  printf("%ld unused maps.\n", found_maps.size());
2924 }
2925 
2927 static void write_world_info(void) {
2928  FILE *file;
2929  char path[strlen(root) + 150 + strlen(output_extensions[output_format])];
2930  int x, y;
2931  gdImagePtr elevationmap;
2932 
2933  if (!world_exit_info)
2934  return;
2935 
2936 
2937  printf("Saving exit/blocking/road information...");
2938  snprintf(path, sizeof(path), "%s/%s%s", root, "world_info", output_extensions[output_format]);
2939  file = fopen(path, "wb+");
2940  save_picture(file, infomap);
2941  fclose(file);
2942  printf("done.\n");
2943  gdImageDestroy(infomap);
2944  infomap = NULL;
2945 
2946  if (elevation_min == 0 || elevation_max == 0) {
2947  puts("Error: Could not save elevation world map due to not finding any minimum or maximum elevation.");
2948  return;
2949  }
2950 
2951  elevationmap = gdImageCreateTrueColor(30*50, 30*50);;
2952 
2953  for (x = 0; x < 30*50; x++) {
2954  for (y = 0; y < 30*50; y++) {
2955  gdImageSetPixel(elevationmap, x, y, get_elevation_color(elevation_info[x][y], elevationmap));
2956  }
2957  }
2958 
2959  printf("Saving elevation world map...");
2960  snprintf(path, sizeof(path), "%s/%s%s", root, "world_elevation", output_extensions[output_format]);
2961  file = fopen(path, "wb+");
2962  save_picture(file, elevationmap);
2963  fclose(file);
2964  printf("done.\n");
2965  gdImageDestroy(elevationmap);
2966  elevationmap = NULL;
2967 }
2968 
2979 static int sort_slaying(const void *left, const void *right) {
2981  struct_slaying_info *r = *(struct_slaying_info **)right;
2982 
2983  return strcasecmp(l->slaying, r->slaying);
2984 }
2985 
2992 static void do_help(const char *program) {
2993  printf("Crossfire Mapper will generate pictures of maps, and create indexes for all maps and regions.\n\n");
2994  printf("Syntax: %s\n\n", program);
2995  printf("Optional arguments:\n");
2996  printf(" -nopics don't generate pictures.\n");
2997  printf(" -root=<path> destination path. Default 'html'.\n");
2998  printf(" -limit=<number> stop processing after this number of maps, -1 to do all maps (default).\n");
2999  printf(" -showmaps outputs the name of maps as they are processed.\n");
3000  printf(" -jpg[=quality] generate jpg pictures, instead of default png. Quality should be 0-95, -1 for automatic.\n");
3001  printf(" -forcepics force to regenerate pics, even if pics's date is after map's.\n");
3002  printf(" -addmap=<map> adds a map to process. Path is relative to map's directory root.\n");
3003  printf(" -rawmaps generates maps pics without items on random (shop, treasure) tiles.\n");
3004  printf(" -warnnopath inform when an exit has no path set.\n");
3005  printf(" -listunusedmaps finds all unused maps in the maps directory.\n");
3006  printf(" -noworldmap don't write the world map in world.png.\n");
3007  printf(" -noregionslink don't generate regions relation file.\n");
3008  printf(" -regionslink generate regions relation file.\n");
3009  printf(" -noexitmap don't generate map of exits.\n");
3010  printf(" -exitmap generate map of exits.\n");
3011  printf(" -tileset=<number> use specified tileset to generate the pictures. Default 0 (standard).\n");
3012  printf(" -details-quests list all quests steps. Default no.\n");
3013  printf(" -list-system-quests include 'system' quests in quest list. Default no.\n");
3014  printf(" -templates-dir=[dir] set the directory to get templates from. Default 'templates/'.\n");
3015  printf(" -add-template=[file] add a template to process. May be specified multiple times. If empty, 'index.html' is used.\n");
3016  printf(" -list-template-to-process display the name of the template about to be rendered. Useful for debugging.");
3017  printf("\n\n");
3018  exit(0);
3019 }
3020 
3029 static void do_parameters(int argc, char **argv) {
3030  int arg = 1;
3031  char path[500];
3032 
3033  root[0] = '\0';
3034 
3035  while (arg < argc) {
3036  if (strcmp(argv[arg], "-nopics") == 0)
3037  generate_pics = 0;
3038  else if (strncmp(argv[arg], "-root=", 6) == 0)
3039  strncpy(root, argv[arg]+6, 500);
3040  else if (strncmp(argv[arg], "-limit=", 7) == 0)
3041  map_limit = atoi(argv[arg]+7);
3042  else if (strcmp(argv[arg], "-showmaps") == 0)
3043  show_maps = 1;
3044  else if (strcmp(argv[arg], "-jpg") == 0) {
3046  if (argv[arg][4] == '=') {
3047  jpeg_quality = atoi(argv[arg]+5);
3048  if (jpeg_quality < 0)
3049  jpeg_quality = -1;
3050  }
3051  }
3052  else if (strcmp(argv[arg], "-forcepics") == 0)
3053  force_pics = 1;
3054  else if (strncmp(argv[arg], "-addmap=", 8) == 0) {
3055  if (*(argv[arg]+8) == '/')
3056  strncpy(path, argv[arg]+8, 500);
3057  else
3058  snprintf(path, 500, "/%s", argv[arg]+8);
3060  }
3061  else if (strcmp(argv[arg], "-rawmaps") == 0)
3062  rawmaps = 1;
3063  else if (strcmp(argv[arg], "-warnnopath") == 0)
3064  warn_no_path = 1;
3065  else if (strcmp(argv[arg], "-listunusedmaps") == 0)
3066  list_unused_maps = 1;
3067  else if (strcmp(argv[arg], "-noworldmap") == 0)
3068  world_map = 0;
3069  else if (strcmp(argv[arg], "-noregionslink") == 0)
3070  do_regions_link = false;
3071  else if (strcmp(argv[arg], "-regionslink") == 0)
3072  do_regions_link = true;
3073  else if (strcmp(argv[arg], "-noexitmap") == 0)
3074  world_exit_info = 0;
3075  else if (strcmp(argv[arg], "-exitmap") == 0)
3076  world_exit_info = 1;
3077  else if (strncmp(argv[arg], "-tileset=", 9) == 0) {
3078  tileset = atoi(argv[arg]+9);
3079  /* check of validity is done in main() as we need to actually have the sets loaded. */
3080  } else if (strcmp(argv[arg], "-detail-quests") == 0) {
3081  detail_quests = 1;
3082  } else if (strcmp(argv[arg], "-list-system-quests") == 0) {
3083  list_system_quests = 1;
3084  } else if (strncmp(argv[arg], "-templates-dir=", 15) == 0) {
3085  templates_root = argv[arg] + 15;
3086  } else if (strncmp(argv[arg], "-add-template=", 14) == 0) {
3087  templates.push_back(argv[arg] + 14);
3088  } else if (strcmp(argv[arg], "-list-template-to-process") == 0) {
3090  } else if (strncmp(argv[arg], "-build-search-data", 18) == 0) {
3091  build_search_file = true;
3092  } else
3093  do_help(argv[0]);
3094  arg++;
3095  }
3096  if (!strlen(root))
3097  strcpy(root, "html");
3098  if (root[strlen(root)-1] == '/')
3099  root[strlen(root)-1] = '\0';
3100  if (map_limit < -1)
3101  map_limit = -1;
3102 
3103  if (templates_root.empty()) {
3104  templates_root = "templates/";
3105  } else if (templates_root[templates_root.length() - 1] != '/') {
3106  templates_root.append("/");
3107  }
3108 }
3109 
3113 static void create_destination(void) {
3114  char dummy[502];
3115 
3116  strcpy(dummy, root);
3117  strcat(dummy, "/a");
3118  make_path_to_file(dummy);
3119 }
3120 
3129 static const char *yesno(int value) {
3130  return (value ? "yes" : "no");
3131 }
3132 
3133 int main(int argc, char **argv) {
3134  size_t current_map = 0, i;
3135  char max[50];
3136  region *dummy;
3137 
3141  pics_allocated = 0;
3142 
3143  do_parameters(argc, argv);
3144 
3145  printf("Initializing Crossfire data...\n");
3146 
3148 
3149  init_globals();
3150  init_library();
3151  init_readable();
3152 
3153  init_gods();
3154 
3155  /* Add a dummy region so unlinked maps can be identified. */
3156  dummy = get_region_struct();
3157  dummy->fallback = 1;
3158  dummy->name = strdup_local("unlinked");
3159  dummy->longname = strdup_local("This dummy region contains all maps without a region set.");
3160  dummy->longname = strdup_local("This dummy region contains all maps without a region set.");
3161  all_regions.push_back(dummy);
3162 
3163  printf("\n\n done.\n\n");
3164 
3165  if (!is_valid_faceset(tileset)) {
3166  printf("Erreor: invalid tileset %d!\n", tileset);
3167  exit(1);
3168  }
3169 
3170  if (templates.empty()) {
3171  templates.push_back("index.html");
3172  }
3173 
3175  gdfaces.resize(get_faces_count(), nullptr);
3176 
3177  if (map_limit != -1)
3178  snprintf(max, sizeof(max), "%d", map_limit);
3179  else
3180  strcpy(max, "(none)");
3181  printf("Crossfire map browser generator\n");
3182  printf("-------------------------------\n\n");
3183  printf("Parameters:\n");
3184  printf(" path to write files: %s\n", root);
3185  printf(" maximum number of maps to process: %s\n", max);
3186  printf(" will generate map picture: %s\n", yesno(generate_pics));
3187  printf(" will always generate map picture: %s\n", yesno(force_pics));
3188  printf(" picture output format: %s\n", output_extensions[output_format]);
3189  if (output_format == OF_JPG)
3190  printf(" JPEG quality: %d\n", jpeg_quality);
3191  printf(" show map being processed: %s\n", yesno(show_maps));
3192  printf(" generate raw maps: %s\n", yesno(rawmaps));
3193  printf(" warn of exit without path: %s\n", yesno(warn_no_path));
3194  printf(" list unused maps: %s\n", yesno(list_unused_maps));
3195  printf(" generate world map: %s\n", yesno(world_map));
3196  printf(" generate exit map: %s\n", yesno(world_exit_info));
3197  printf(" generate regions link file: %s\n", yesno(do_regions_link));
3198  printf(" tileset: %s\n", find_faceset(tileset)->fullname);
3199  printf(" detail quest steps: %s\n", yesno(detail_quests));
3200  printf(" list system quests: %s\n", yesno(list_system_quests));
3201  printf(" templates directory: %s\n", templates_root.c_str());
3202  printf(" templates to process: ");
3203  const char *sep = "";
3204  for (auto f : templates) {
3205  printf("%s%s", sep, f.c_str());
3206  sep = ", ";
3207  }
3208  printf("\n");
3209  printf(" display template to process: %s\n", yesno(display_rendered_template));
3210  printf("\n");
3211 
3212  if (list_unused_maps) {
3213  printf("listing all maps...");
3214  find_maps("");
3215  printf("done, %ld maps found.\n", found_maps.size());
3216  }
3217 
3218  /* exit/blocking information. */
3219  infomap = gdImageCreateTrueColor(30*50, 30*50);
3220  color_unlinked_exit = gdImageColorResolve(infomap, 255, 0, 0);
3221  color_linked_exit = gdImageColorResolve(infomap, 255, 255, 255);
3222  color_road = gdImageColorResolve(infomap, 0, 255, 0);
3223  color_blocking = gdImageColorResolve(infomap, 0, 0, 255);
3224  color_slowing = gdImageColorResolve(infomap, 0, 0, 127);
3225  elevation_info = (int **)calloc(50*30, sizeof(int *));
3226  for (i = 0; i < 50*30; i++)
3227  elevation_info[i] = (int *)calloc(50*30, sizeof(int));
3228  elevation_min = 0;
3229  elevation_max = 0;
3230 
3231  printf("browsing maps...\n");
3232 
3234 
3235  while (current_map < maps_list.count) {
3236  process_map(maps_list.maps[current_map++]);
3237  if (current_map%100 == 0) {
3238  printf(" %zu maps processed, %d map pictures created, %d map pictures were uptodate. %d faces used.\n", current_map, created_pics, cached_pics, pics_allocated);
3239  }
3240  if ((map_limit != -1) && (current_map == static_cast<size_t>(map_limit))) {
3241  printf(" --- map limit reached, stopping ---\n");
3242  break;
3243  }
3244  }
3245 
3246  printf(" finished map parsing, %zu maps processed, %d map pictures created, %d map pictures were uptodate. Total %d faces used.\n", current_map, created_pics, cached_pics, pics_allocated);
3247 
3248  if (list_unused_maps)
3249  dump_unused_maps();
3250 
3252  fix_map_names();
3253  fix_tiled_map();
3255  write_tiled_maps();
3256 
3257  write_world_map();
3258  write_world_info();
3259 
3261  qsort(regions, region_count, sizeof(struct_region_info *), sort_region);
3262  std::sort(special_equipment.begin(), special_equipment.end(), sort_equipment);
3264  qsort(races.races, races.count, sizeof(struct_race *), sort_race);
3265  qsort(quests, quests_count, sizeof(struct_quest *), sort_struct_quest);
3266 
3268  std::sort(system_quests.begin(), system_quests.end(), [] (const auto &left, const auto &right) { return strcmp(left->quest_code, right->quest_code) < 0; });
3269 
3271 
3273 
3274  for (auto file : templates) {
3275  if (!file.empty()) {
3276  add_template_to_render(file, file, "");
3277  }
3278  }
3279 
3280  const auto fullStart = time(nullptr);
3281  printf("rendering pages...");
3283  printf("\n");
3284  fflush(stdout);
3285 
3286  while (!pages.empty()) {
3287  auto p = pages.back();
3288  pages.pop_back();
3289  if (p.param.empty())
3290  all_data.erase("param");
3291  else
3292  all_data["param"] = p.param;
3293  const auto start = time(nullptr);
3295  printf(" rendering page %s (%s)... ", p.template_name.c_str(), p.param.c_str());
3296  fflush(stdout);
3297  }
3298  path_stack.push_back(p.output_name);
3299  inja::Template temp = get_template(p.template_name);
3300  env->write(temp, all_data, p.output_name);
3301  path_stack.pop_back();
3302  const auto elapsed = time(nullptr) - start;
3304  printf("took %ld seconds\n", elapsed);
3305  }
3306  }
3307 
3308  const auto elapsed = time(nullptr) - fullStart;
3309  printf(" done, took %ld seconds\n", elapsed);
3310 
3311  return 0;
3312 }
3313 
3315  int x, y;
3316 
3317  if (m == NULL)
3318  return;
3319 
3320  for (x = 0; x < MAP_WIDTH(m); x++)
3321  for (y = 0; y < MAP_HEIGHT(m); y++)
3322  FOR_MAP_PREPARE(m, x, y, tmp) {
3323  if (tmp->inv) {
3324  FOR_INV_PREPARE(tmp, invtmp) {
3325  if (QUERY_FLAG(invtmp, FLAG_AUTO_APPLY))
3326  apply_auto(invtmp);
3327  else if (invtmp->type == TREASURE && HAS_RANDOM_ITEMS(invtmp)) {
3328  while ((invtmp->stats.hp--) > 0)
3329  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
3330  invtmp->randomitems = NULL;
3331  } else if (invtmp
3332  && invtmp->arch
3333  && invtmp->type != TREASURE
3334  && invtmp->type != SPELL
3335  && invtmp->type != CLASS
3336  && HAS_RANDOM_ITEMS(invtmp)) {
3337  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
3338  /* Need to clear this so that we never try to create
3339  * treasure again for this object
3340  */
3341  invtmp->randomitems = NULL;
3342  }
3343  } FOR_INV_FINISH();
3344  /* This is really temporary - the code at the bottom will
3345  * also set randomitems to null. The problem is there are bunches
3346  * of maps/players already out there with items that have spells
3347  * which haven't had the randomitems set to null yet.
3348  * MSW 2004-05-13
3349  *
3350  * And if it's a spellbook, it's better to set randomitems to NULL too,
3351  * else you get two spells in the book ^_-
3352  * Ryo 2004-08-16
3353  */
3354  if (tmp->type == WAND
3355  || tmp->type == ROD
3356  || tmp->type == SCROLL
3357  || tmp->type == FIREWALL
3358  || tmp->type == POTION
3359  || tmp->type == ALTAR
3360  || tmp->type == SPELLBOOK)
3361  tmp->randomitems = NULL;
3362  }
3363 
3364  if (QUERY_FLAG(tmp, FLAG_AUTO_APPLY))
3365  apply_auto(tmp);
3366  else if ((tmp->type == TREASURE || (tmp->type == CONTAINER)) && HAS_RANDOM_ITEMS(tmp)) {
3367  while ((tmp->stats.hp--) > 0)
3368  create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
3369  tmp->randomitems = NULL;
3370  } else if (tmp->type == TIMED_GATE) {
3371  object *head = HEAD(tmp);
3372 
3373  if (QUERY_FLAG(head, FLAG_IS_LINKED)) {
3374  tmp->speed = 0;
3375  object_update_speed(tmp);
3376  }
3377  /* This function can be called everytime a map is loaded, even when
3378  * swapping back in. As such, we don't want to create the treasure
3379  * over and ove again, so after we generate the treasure, blank out
3380  * randomitems so if it is swapped in again, it won't make anything.
3381  * This is a problem for the above objects, because they have counters
3382  * which say how many times to make the treasure.
3383  */
3384  } else if (tmp
3385  && tmp->arch
3386  && tmp->type != PLAYER
3387  && tmp->type != TREASURE
3388  && tmp->type != SPELL
3389  && tmp->type != PLAYER_CHANGER
3390  && tmp->type != CLASS
3391  && HAS_RANDOM_ITEMS(tmp)) {
3392  create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
3393  tmp->randomitems = NULL;
3394  }
3395  } FOR_MAP_FINISH();
3396 
3397  for (x = 0; x < MAP_WIDTH(m); x++)
3398  for (y = 0; y < MAP_HEIGHT(m); y++)
3399  FOR_MAP_PREPARE(m, x, y, tmp) {
3400  if (tmp->above
3401  && (tmp->type == TRIGGER_BUTTON || tmp->type == TRIGGER_PEDESTAL))
3402  check_trigger(tmp, tmp->above);
3403  } FOR_MAP_FINISH();
3404 }
3405 
3406 #ifndef DOXYGEN_SHOULD_SKIP_THIS
3407 
3412 void draw_ext_info(int, int, const object *, uint8_t, uint8_t, const char *txt) {
3413  fprintf(logfile, "%s\n", txt);
3414 }
3415 
3416 void draw_ext_info_format(int, int, const object *, uint8_t, uint8_t, const char *format, ...) {
3417  va_list ap;
3418 
3419  va_start(ap, format);
3420  vfprintf(logfile, format, ap);
3421  va_end(ap);
3422 }
3423 
3424 void ext_info_map(int, const mapstruct *, uint8_t, uint8_t, const char *str1) {
3425  fprintf(logfile, "ext_info_map: %s\n", str1);
3426 }
3427 
3428 void move_firewall(object *) {
3429 }
3430 
3431 void emergency_save(int) {
3432 }
3433 
3434 void clean_tmp_files(void) {
3435 }
3436 
3437 void esrv_send_item(object *, object *) {
3438 }
3439 
3440 void dragon_ability_gain(object *, int, int) {
3441 }
3442 
3443 void set_darkness_map(mapstruct *) {
3444 }
3445 
3446 object *find_skill_by_number(object *, int) {
3447  return NULL;
3448 }
3449 
3450 void esrv_del_item(player *, object *) {
3451 }
3452 
3453 void esrv_update_item(int, object *, object *) {
3454 }
3455 
3456 void esrv_update_spells(player *) {
3457 }
3458 
3459 void rod_adjust(object *) {
3460 }
3461 
3462 /*
3463  * This a modified version of apply_auto: BOOK are not generated, so they don't pollute
3464  * the readable list.
3465  */
3466 int apply_auto(object *op) {
3467  object *tmp = NULL;
3468  int i;
3469 
3470  switch (op->type) {
3471  case SHOP_FLOOR:
3472  if (!HAS_RANDOM_ITEMS(op))
3473  return 0;
3474  do {
3475  i = 10; /* let's give it 10 tries */
3476  while ((tmp = generate_treasure(op->randomitems, op->stats.exp ? (int)op->stats.exp : MAX(op->map->difficulty, 5))) == NULL && --i)
3477  ;
3478  if (tmp == NULL)
3479  return 0;
3480  if (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED) || tmp->type == BOOK) {
3482  tmp = NULL;
3483  }
3484  } while (!tmp);
3485  SET_FLAG(tmp, FLAG_UNPAID);
3486  object_insert_in_map_at(tmp, op->map, NULL, 0, op->x, op->y);
3488  tmp = identify(tmp);
3489  break;
3490 
3491  case TREASURE:
3492  if (QUERY_FLAG(op, FLAG_IS_A_TEMPLATE))
3493  return 0;
3494 
3495  while ((op->stats.hp--) > 0)
3496  create_treasure(op->randomitems, op, 0, op->stats.exp ? (int)op->stats.exp : op->map == NULL ? 14 : op->map->difficulty, 0);
3497 
3498  /* If we generated an object and put it in this object inventory,
3499  * move it to the parent object as the current object is about
3500  * to disappear. An example of this item is the random_ *stuff
3501  * that is put inside other objects.
3502  */
3503  FOR_INV_PREPARE(op, tmp) {
3504  object_remove(tmp);
3505  if (op->env && tmp->type != BOOK)
3506  object_insert_in_ob(tmp, op->env);
3507  else
3509  }
3510  FOR_INV_FINISH();
3511  object_remove(op);
3513  break;
3514  }
3515  return tmp ? 1 : 0;
3516 }
3517 
3518 void apply_auto_fix(mapstruct *) {
3519 }
3520 
3522  return NULL;
3523 }
3524 
3525 player *find_player_partial_name(const char *) {
3526  return NULL;
3527 }
3528 
3529 Account_Chars *account_char_load(const char *) {
3530  return NULL;
3531 }
3532 
3534 }
3535 
3537 }
3538 
3539 void command_help(object *, const char *) {
3540 }
3541 
3542 void account_logout(const char *) {
3543 }
3544 
3545 #endif /* dummy DOXYGEN_SHOULD_SKIP_THIS */
get_race
static struct_race * get_race(const char *name)
Returns the race for specified name.
Definition: mapper.cpp:648
struct_map_info::tiles
struct struct_map_info * tiles[4]
Definition: mapper.cpp:262
CLASS
@ CLASS
Object for applying character class modifications to someone.
Definition: object.h:143
object::name_pl
sstring name_pl
The plural name of the object.
Definition: object.h:323
struct_region_info::sum_x
int sum_x
Definition: mapper.cpp:408
init_globals
void init_globals(void)
Initialises all global variables.
Definition: init.cpp:394
write_tiled_map_page
static void write_tiled_map_page(struct_map_info *map)
Writes the page for a tiled map group.
Definition: mapper.cpp:2195
fix_tiled_map_monsters
static void fix_tiled_map_monsters(void)
Makes all monsters point to tiled maps instead of map when appliable, and merge map monster to tiled ...
Definition: mapper.cpp:2030
do_auto_apply
void do_auto_apply(mapstruct *m)
Definition: mapper.cpp:3314
add_map
static void add_map(struct_map_info *info, struct_map_list *list)
Adds a map to specified array, if it isn't already.
Definition: mapper.cpp:1218
living::exp
int64_t exp
Experience.
Definition: living.h:47
HAS_RANDOM_ITEMS
#define HAS_RANDOM_ITEMS(op)
This return TRUE if object has still randomitems which could be expanded.
Definition: define.h:184
PLAYER
@ PLAYER
Definition: object.h:112
Settings::mapdir
const char * mapdir
Where the map files are.
Definition: global.h:253
global.h
FREE_OBJ_NO_DESTROY_CALLBACK
#define FREE_OBJ_NO_DESTROY_CALLBACK
Do not run the destroy callback.
Definition: object.h:545
settings
struct Settings settings
Server settings.
Definition: init.cpp:139
ignore_name
static const char * ignore_name[]
File names to ignore for map search.
Definition: mapper.cpp:2855
struct_equipment::diff
char * diff
Result of get_ob_diff() with the item's clone.
Definition: mapper.cpp:276
get_quest_info
static struct_quest * get_quest_info(const char *name)
Gets the information for a quest, create the field if needed.
Definition: mapper.cpp:985
find_region_by_key
static region * find_region_by_key(const std::string &key)
Get the region with the specified key, nullptr if not found.
Definition: mapper.cpp:2245
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:724
emergency_save
void emergency_save(int flag)
Save all players.
Definition: main.cpp:347
process_map_lore
static void process_map_lore(struct_map_info *map)
Extracts from the map's lore quest information if found.
Definition: mapper.cpp:1099
find_artifact
const artifact * find_artifact(const object *op, const char *name)
Searches and returns a specific artifact compatible with an object, NULL if not found.
Definition: artifact.cpp:589
llevError
@ llevError
Error, serious thing.
Definition: logger.h:11
get_region_struct
region * get_region_struct(void)
Allocates and zeros a region struct, this isn't free()'d anywhere, so might be a memory leak,...
Definition: region.cpp:293
mapstruct::difficulty
uint16_t difficulty
What level the player should be to play here.
Definition: map.h:333
region::fallback
int8_t fallback
Whether, in the event of a region not existing, this should be the one we fall back on as the default...
Definition: map.h:285
compare_map_info
static int compare_map_info(const struct_map_info *left, const struct_map_info *right)
Compares struct_map_info according to the map name or the path if equal.
Definition: mapper.cpp:873
path_from_current
static std::string path_from_current(const std::string &path)
Compute the relative path from the specified file to the current file.
Definition: mapper.cpp:2637
find_skill_by_number
object * find_skill_by_number(object *who, int skillno)
This returns the first skill pointer of the given subtype (the one that accumulates exp,...
Definition: main.cpp:375
MOVE_ALL
#define MOVE_ALL
Mask of all movement types.
Definition: define.h:398
WAND
@ WAND
Definition: object.h:225
quest_for_each
void quest_for_each(quest_op op, void *user)
Iterate over all quests.
Definition: assets.cpp:538
LOG
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
struct_region_info::is_world
int is_world
If set, this region has at least one map part of the world, thus region name should be written.
Definition: mapper.cpp:409
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
generate_picture_link
static nlohmann::json generate_picture_link(inja::Arguments &args)
Return the link to the picture of the specified item.
Definition: mapper.cpp:2685
struct_map_info::tiled_group
struct struct_map_info * tiled_group
Definition: mapper.cpp:259
build_search_file
static bool build_search_file
If set, will build the 'search_data.js' file.
Definition: mapper.cpp:374
struct_map_info::filename
char * filename
Filename of the map.
Definition: mapper.cpp:243
num_sizes
static const int num_sizes
Definition: mapper.cpp:363
player
One player.
Definition: player.h:105
add_slaying
static void add_slaying(struct_map_info *map, object *item)
Adds the item's information to the map.
Definition: mapper.cpp:1482
SearchType::Region
@ Region
strdup_local
#define strdup_local
Definition: compat.h:29
ready_map_name
mapstruct * ready_map_name(const char *name, int flags)
Makes sure the given map is loaded and swapped in.
Definition: map.cpp:1780
write_tiled_maps
static void write_tiled_maps(void)
Outputs all tiled map pages.
Definition: mapper.cpp:2205
first_map_path
char first_map_path[MAX_BUF]
The start-level.
Definition: init.cpp:120
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
struct_quest::maps
struct_map_in_quest_list maps
Maps part of this quest.
Definition: mapper.cpp:940
create_quest_object
static nlohmann::json create_quest_object(struct_quest *quest, const std::string &key)
Return a JSON quest object.
Definition: mapper.cpp:2361
create_map_info
static struct_map_info * create_map_info(void)
Returns an initialised struct_map_info.
Definition: mapper.cpp:1239
struct_race::count
int count
Number found on map.
Definition: mapper.cpp:286
TRIGGER_PEDESTAL
@ TRIGGER_PEDESTAL
Definition: object.h:139
struct_map_in_quest::map
struct_map_info * map
Linked map.
Definition: mapper.cpp:931
pageToRender::param
std::string param
Optional template parameter.
Definition: mapper.cpp:2709
S_CONNECT
#define S_CONNECT
Definition: mapper.cpp:441
write_pictures_from_real_size
static void write_pictures_from_real_size(const char *path, gdImagePtr real, int width, int height)
Definition: mapper.cpp:1522
region_links
static std::map< region *, std::set< region * > > region_links
Definition: mapper.cpp:434
get_face_fallback
int get_face_fallback(int faceset, uint16_t imageno)
This returns the set we will actually use when sending a face.
Definition: image.cpp:133
object::item_power
int8_t item_power
Power rating of the object.
Definition: object.h:372
Settings::datadir
const char * datadir
Read only data files.
Definition: global.h:250
c
static event_registration c
Definition: citylife.cpp:422
object::arch
struct archetype * arch
Pointer to archetype.
Definition: object.h:424
output_format
static enum output_format_type output_format
Selected output format.
Definition: mapper.cpp:393
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.cpp:57
quests_count
static int quests_count
Count of quests.
Definition: mapper.cpp:945
SHOP_FLOOR
@ SHOP_FLOOR
Definition: object.h:188
create_npc_array
static nlohmann::json create_npc_array(npc_list &list)
Return an array of NPC information.
Definition: mapper.cpp:2273
get_map_info
static struct_map_info * get_map_info(const char *path)
Gets or creates if required the info structure for a map.
Definition: mapper.cpp:1311
EXIT_PATH
#define EXIT_PATH(xyz)
Definition: define.h:433
fix_exits_to_tiled_maps
static void fix_exits_to_tiled_maps(void)
Changes all exits to maps in a tiled map to point directly to the tiled map.
Definition: mapper.cpp:2002
object::x
int16_t x
Definition: object.h:335
reverse_maps
static std::map< struct_map_info *, std::string > reverse_maps
Link between a map and its unique identifier.
Definition: mapper.cpp:2225
dump
static int dump(const std::set< std::string > &items, const char *name)
Definition: AssetsManager.cpp:42
gdfaces
static std::vector< gdImagePtr > gdfaces
Definition: mapper.cpp:206
struct_map_in_quest
Link between a quest and a map.
Definition: mapper.cpp:928
slaying_allocated
static size_t slaying_allocated
Allocated size of slaying_info.
Definition: mapper.cpp:452
give_artifact_abilities
void give_artifact_abilities(object *op, const object *artifact)
Fixes the given object, giving it the abilities and titles it should have due to the second artifact-...
Definition: artifact.cpp:230
object::map
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
get_equipment
static struct_equipment * get_equipment(void)
Gets an empty struct_equipment.
Definition: mapper.cpp:486
is_special_equipment
static int is_special_equipment(object *item)
Definition: mapper.cpp:467
TIMED_GATE
@ TIMED_GATE
Definition: object.h:133
region_allocated
static size_t region_allocated
Allocated size of regions.
Definition: mapper.cpp:414
struct_map_list
List of maps.
Definition: mapper.cpp:233
generate_page_and_link
static nlohmann::json generate_page_and_link(inja::Arguments &args)
Create a link to a page, generating it if needed.
Definition: mapper.cpp:2654
struct_equipment::origin
struct_map_list origin
Map(s) this item is found in.
Definition: mapper.cpp:277
generate_treasure
object * generate_treasure(treasurelist *t, int difficulty)
Generate a treasure from a list generating a single item.
Definition: treasure.cpp:295
fields
non standard information is not specified or uptime fields
Definition: arch-handbook.txt:204
find_faceset
face_sets * find_faceset(int id)
Definition: assets.cpp:327
artifact::item
object * item
Special values of the artifact.
Definition: artifact.h:15
root
static char root[500]
Path to store generated files.
Definition: mapper.cpp:354
create_map_in_quest_array
static nlohmann::json create_map_in_quest_array(struct_map_in_quest_list &list)
Return an array of map-in-quest items.
Definition: mapper.cpp:2309
time
non standard information is not specified or uptime this means how long since the executable has been started A particular host may have been running a server for quite a long time
Definition: arch-handbook.txt:206
yesno
static const char * yesno(int value)
Helper to write yes/no.
Definition: mapper.cpp:3129
AMULET
@ AMULET
Definition: object.h:144
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
CHECK_INV
@ CHECK_INV
b.t.
Definition: object.h:174
struct_map_info::name
char * name
Map's name as defined in the map file.
Definition: mapper.cpp:242
fix_map_names
static void fix_map_names(void)
Ensures all maps have a name (if there was a limit to map processing, some maps will have a NULL name...
Definition: mapper.cpp:1896
struct_slaying_info::maps
struct_map_list maps[S_MAX]
Definition: mapper.cpp:447
MIN
#define MIN(x, y)
Definition: compat.h:21
SIZE
#define SIZE
maps_list
static struct_map_list maps_list
Maps to process or found.
Definition: mapper.cpp:266
TREASURE
@ TREASURE
Definition: object.h:115
color_unlinked_exit
static int color_unlinked_exit
Color for exits without a path set.
Definition: mapper.cpp:421
Region
One region with bells.
Definition: cfcitybell.cpp:36
struct_region_info::sum_y
int sum_y
Definition: mapper.cpp:408
pages
static std::vector< pageToRender > pages
List of pages to render.
Definition: mapper.cpp:2711
list_unused_maps
static int list_unused_maps
If set, program will list maps found in directory but not linked from the first maps.
Definition: mapper.cpp:416
SearchType::Monster
@ Monster
esrv_update_spells
void esrv_update_spells(player *pl)
This looks for any spells the player may have that have changed their stats.
Definition: main.cpp:386
struct_map_info
Map information.
Definition: mapper.cpp:240
struct_map_info::min_monster
int min_monster
Definition: mapper.cpp:246
create_region_array
static nlohmann::json create_region_array(const std::set< region * > &regions)
Return an array of region identifiers.
Definition: mapper.cpp:2405
struct_region_info
Region information.
Definition: mapper.cpp:405
add_npc_to_map
static void add_npc_to_map(npc_list *list, const object *npc)
Add the specified NPC to the list.
Definition: mapper.cpp:1202
rod_adjust
void rod_adjust(object *rod)
Adjusts rod attributes.
Definition: main.cpp:390
monster
the faster the spell may be cast there are several other common only the caster may be affected by the spell The most common spell range is that of touch This denotes that the caster much touch the recipient of the spell in order to release the spell monster
Definition: spell-info.txt:45
region::name
char * name
Shortend name of the region as maps refer to it.
Definition: map.h:275
SIGN
@ SIGN
Definition: object.h:216
struct_equipment::name
char * name
Item's name.
Definition: mapper.cpp:273
TRIGGER_BUTTON
@ TRIGGER_BUTTON
Definition: object.h:137
object::title
sstring title
Of foo, etc.
Definition: object.h:325
mapstruct::path
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:355
struct_map_info::max_monster
int max_monster
Definition: mapper.cpp:246
quest_definition::quest_is_system
bool quest_is_system
If set then the quest isn't counted or listed.
Definition: quest.h:45
struct_slaying_info
slaying information.
Definition: mapper.cpp:445
buf
StringBuffer * buf
Definition: readable.cpp:1565
struct_equipment::calc_power
int calc_power
Item power calculated via calc_item_power().
Definition: mapper.cpp:275
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
Definition: object.cpp:2857
HUGE_BUF
#define HUGE_BUF
Used for messages - some can be quite long.
Definition: define.h:37
MAX
#define MAX(x, y)
Definition: compat.h:24
FLAG_NO_PICK
#define FLAG_NO_PICK
Object can't be picked up.
Definition: define.h:239
SearchType
SearchType
Search values, for the JS search engine.
Definition: mapper.cpp:295
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
force_pics
static int force_pics
To force picture regeneration even if map didn't change.
Definition: mapper.cpp:361
FLAG_IS_FLOOR
#define FLAG_IS_FLOOR
Can't see what's underneath this object.
Definition: define.h:302
world_exit_info
static int world_exit_info
If set, will generate a world map of exits.
Definition: mapper.cpp:369
draw_ext_info
vs only yadda is in because all tags get reset on the next draw_ext_info In the second since it is all in one draw_ext_info
Definition: media-tags.txt:61
sort_struct_quest
static int sort_struct_quest(const void *left, const void *right)
Sorts 2 struct_quest, on the map's name or path.
Definition: mapper.cpp:1064
struct_quest
One quest.
Definition: mapper.cpp:935
dragon_ability_gain
void dragon_ability_gain(object *who, int atnr, int level)
When a dragon-player gains a new stage of evolution, he gets some treasure.
Definition: main.cpp:365
struct_map_in_quest_list
Utility structure to group map-quest link structure.
Definition: mapper.cpp:226
region::longname
char * longname
Official title of the region, this might be defined to be the same as name.
Definition: map.h:281
struct_region_info::reg
region * reg
Region.
Definition: mapper.cpp:406
esrv_send_item
void esrv_send_item(object *pl, object *op)
Sends item's info to player.
Definition: main.cpp:354
SearchType::Quest
@ Quest
struct_map_in_quest::quest
struct struct_quest * quest
Point back to the quest.
Definition: mapper.cpp:933
FLAG_IS_A_TEMPLATE
#define FLAG_IS_A_TEMPLATE
Object has no ingame life until instantiated.
Definition: define.h:366
init_renderer_env
static void init_renderer_env()
Initialize env and set various callbacks and options.
Definition: mapper.cpp:2751
struct_quest::description
char * description
Description, from the main map's lore.
Definition: mapper.cpp:937
init_gods
void init_gods(void)
This takes a look at all of the archetypes to find the objects which correspond to the GODS (type GOD...
Definition: holy.cpp:59
object::y
int16_t y
Position in the map for this object.
Definition: object.h:335
m
static event_registration m
Definition: citylife.cpp:422
set_darkness_map
void set_darkness_map(mapstruct *m)
Set the darkness level for a map, based on the time of the day.
Definition: main.cpp:371
MAP_IN_MEMORY
#define MAP_IN_MEMORY
Map is fully loaded.
Definition: map.h:126
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.cpp:76
apply_auto_fix
void apply_auto_fix(mapstruct *m)
Go through the entire map (only the first time when an original map is loaded) and performs special a...
Definition: main.cpp:258
S_CONTAINER
#define S_CONTAINER
Definition: mapper.cpp:439
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects,...
Definition: object.cpp:1560
opendir
DIR * opendir(const char *)
struct_map_info::reset_group
sstring reset_group
Definition: mapper.cpp:250
templateCache
static inja::TemplateStorage templateCache
Definition: mapper.cpp:2416
regions
static struct struct_region_info ** regions
Found regions.
Definition: mapper.cpp:412
struct_npc_info::y
int y
Coordinates in the map.
Definition: mapper.cpp:212
struct_map_info::exits_from
struct_map_list exits_from
Definition: mapper.cpp:247
Settings::debug
LogLevel debug
Default debugging level.
Definition: global.h:245
detail_quests
static bool detail_quests
Whether to show all quests details or not.
Definition: mapper.cpp:371
ensure_unique
static struct_equipment * ensure_unique(struct_equipment *item)
Searches the item list for an identical item, except maps.
Definition: mapper.cpp:533
struct_npc_info::message
const char * message
NPC's message.
Definition: mapper.cpp:211
get_slaying_struct
static struct_slaying_info * get_slaying_struct(const char *slaying)
Returns a struct_slaying_info for specified slaying.
Definition: mapper.cpp:1439
generate_picture_path
static void generate_picture_path(const char *path, size_t pic_size, char *out, size_t len)
Definition: mapper.cpp:1518
OF_JPG
@ OF_JPG
JPG.
Definition: mapper.cpp:383
elevation_max
static int elevation_max
Lowest elevation found.
Definition: mapper.cpp:429
struct_map_info::pic_was_done
int pic_was_done
Definition: mapper.cpp:246
POTION
@ POTION
Definition: object.h:116
struct_npc_info
Information about a NPC with a custom message.
Definition: mapper.cpp:209
define_quest
static void define_quest(const char *name, struct_map_info *mainmap, const char *description)
Sets the main map for a quest.
Definition: mapper.cpp:1080
path_combine_and_normalize
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
Combines the 2 paths.
Definition: path.cpp:172
add_to_struct_map_in_quest_list
static void add_to_struct_map_in_quest_list(struct_map_in_quest_list *list, struct_map_in_quest *item)
Definition: mapper.cpp:955
do_tiled_map_picture
static void do_tiled_map_picture(struct_map_info *map)
Generates the large and small pictures for a tiled map.
Definition: mapper.cpp:2087
account_char_free
void account_char_free(Account_Chars *chars)
This frees all data associated with the character information.
Definition: account_char.cpp:345
archetype::clone
object clone
An object from which to do object_copy()
Definition: object.h:487
slaying_info
static struct_slaying_info ** slaying_info
Found slaying fields.
Definition: mapper.cpp:450
add_string
sstring add_string(const char *str)
This will add 'str' to the hash table.
Definition: shstr.cpp:124
races
static struct_race_list races
Monsters found in maps.
Definition: mapper.cpp:290
npc_list
std::vector< struct_npc_info * > npc_list
List of NPCs with a custom message.
Definition: mapper.cpp:216
object_get_multi_size
void object_get_multi_size(const object *ob, int *sx, int *sy, int *hx, int *hy)
Computes the size of a multitile object.
Definition: object.cpp:4744
main
int main(int argc, char **argv)
Definition: mapper.cpp:3133
HEAD
#define HEAD(op)
Returns the head part of an object.
Definition: object.h:607
output_extensions
static const char * output_extensions[]
Extensions depending on output format.
Definition: mapper.cpp:387
create_maps_array
static nlohmann::json create_maps_array(struct_map_list &maps)
Return an array of map identifiers.
Definition: mapper.cpp:2257
ROD
@ ROD
Definition: object.h:114
show_maps
static int show_maps
If set, will generate much information on map loaded.
Definition: mapper.cpp:367
CONTAINER
@ CONTAINER
Definition: object.h:236
system_quests
static std::vector< quest_definition * > system_quests
Definition: mapper.cpp:2214
get_elevation_color
static int get_elevation_color(int elevation, gdImagePtr elevationmap)
Gets the color for an elevation.
Definition: mapper.cpp:762
reset_groups
static std::set< std::string > reset_groups
All defined reset groups.
Definition: mapper.cpp:292
region::msg
char * msg
The description of the region.
Definition: map.h:283
init_readable
void init_readable(void)
Initialize linked lists utilized by message functions in tailor_readable_ob()
Definition: readable.cpp:904
S_MAX
#define S_MAX
Definition: mapper.cpp:442
quest_callback
static void quest_callback(const quest_definition *quest, void *)
Definition: mapper.cpp:2216
readdir
struct dirent * readdir(DIR *)
ext_info_map
void void ext_info_map(int color, const mapstruct *map, uint8_t type, uint8_t subtype, const char *str1)
Writes to everyone on the specified map.
Definition: main.cpp:334
LOCKED_DOOR
@ LOCKED_DOOR
Definition: object.h:128
struct_race::name
char * name
Monster's name.
Definition: mapper.cpp:285
dump
Structure used when dumping quests to stdout.
Definition: quest.cpp:847
is_slaying
static int is_slaying(object *item)
Is the slaying field relevant for this item?
Definition: mapper.cpp:1426
struct_equipment::power
int power
Item power as declared by the item itself.
Definition: mapper.cpp:274
create_race_array
static nlohmann::json create_race_array(struct_race_list &list)
Return an array of monster information.
Definition: mapper.cpp:2292
description
spell prayer lvl t sp speed range duration short description
Definition: spell-summary.txt:2
SPECIAL_KEY
@ SPECIAL_KEY
Definition: object.h:129
object_update_speed
void object_update_speed(object *op)
Updates the speed of an object.
Definition: object.cpp:1349
struct_race::origin
struct_map_list origin
Maps to find said monster.
Definition: mapper.cpp:287
color_slowing
static int color_slowing
Slows movement.
Definition: mapper.cpp:425
object::type
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:348
struct_map_info::quests
struct_map_in_quest_list quests
Definition: mapper.cpp:249
write_world_map
static void write_world_map(void)
Generates a big world map.
Definition: mapper.cpp:1793
FLAG_DAMNED
#define FLAG_DAMNED
The object is very cursed.
Definition: define.h:317
struct_map_info::width
int width
Definition: mapper.cpp:260
command_help
void command_help(object *op, const char *params)
Player is asking for some help.
Definition: c_misc.cpp:1772
add_map_to_quest
static void add_map_to_quest(struct_map_info *map, const char *name, const char *description)
Links a map to a quest.
Definition: mapper.cpp:1014
create_npc_info
static struct_npc_info * create_npc_info(const object *npc)
Create the struct_npc_info from the specified NPC.
Definition: mapper.cpp:1184
face_info::data
uint8_t * data
Image data.
Definition: image.h:11
move_firewall
void move_firewall(object *op)
Move for FIREWALL.
Definition: main.cpp:343
color_road
static int color_road
Road or equivalent.
Definition: mapper.cpp:423
tileset
static int tileset
Tileset to use to generate pics.
Definition: mapper.cpp:370
object_free
void object_free(object *ob, int flags)
Frees everything allocated by an object, removes it from the list of used objects,...
Definition: object.cpp:1592
FOR_INV_FINISH
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:671
is_blocking
static int is_blocking(object *item)
Checks if item blocks movement or not.
Definition: mapper.cpp:748
do_exit_map
static void do_exit_map(mapstruct *map)
Proceses exit / road / blocking information for specified map into the global infomap map.
Definition: mapper.cpp:777
create_destination
static void create_destination(void)
Ensures destination directory exists.
Definition: mapper.cpp:3113
struct_map_info::tiled_y_from
int tiled_y_from
Definition: mapper.cpp:261
struct_race_list::races
struct struct_race ** races
Races on the list.
Definition: mapper.cpp:220
FLAG_UNAGGRESSIVE
#define FLAG_UNAGGRESSIVE
Monster doesn't attack players.
Definition: define.h:272
check_slaying_inventory
static void check_slaying_inventory(struct_map_info *map, object *item)
Recursively checks if the object should be considered for slaying information.
Definition: mapper.cpp:1510
archetype
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
Definition: object.h:483
jpeg_quality
static int jpeg_quality
Quality for jpg pictures.
Definition: mapper.cpp:396
sproto.h
append_map_list
static void append_map_list(struct_map_list &dest, struct_map_list &src)
Append the contents of src to dest.
Definition: mapper.cpp:2395
struct_map_info::npcs
npc_list * npcs
Definition: mapper.cpp:256
IS_SHIELD
#define IS_SHIELD(op)
Definition: define.h:170
logfile
FILE * logfile
Used by server/daemon.c.
Definition: init.cpp:114
SearchType::Item
@ Item
BOOK
@ BOOK
Definition: object.h:119
rawmaps
static int rawmaps
Whether to generate raw pics or instancied ones.
Definition: mapper.cpp:399
init_struct_map_in_quest_list
static void init_struct_map_in_quest_list(struct_map_in_quest_list *list)
Definition: mapper.cpp:949
struct_race_list
Collection of races.
Definition: mapper.cpp:219
struct_race
One monster race in the maps.
Definition: mapper.cpp:284
delete_map
void delete_map(mapstruct *m)
Frees the map, including the mapstruct.
Definition: map.cpp:1708
struct_race_list::allocated
size_t allocated
Allocated space.
Definition: mapper.cpp:222
struct_map_list::maps
struct struct_map_info ** maps
Definition: mapper.cpp:234
RING
@ RING
Definition: object.h:190
struct_race_list::count
size_t count
Number of races.
Definition: mapper.cpp:221
fill_json
static void fill_json(nlohmann::json &json)
Add all global variables to the data available to templates.
Definition: mapper.cpp:2431
add_map_to_region
static void add_map_to_region(struct_map_info *map, region *reg)
Links a map to a region.
Definition: mapper.cpp:1359
image.h
struct_map_info::level
int level
Definition: mapper.cpp:246
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.cpp:2100
artifact
in that case they will be relative to whatever the PWD of the crossfire server process is You probably shouldn though Notes on Specific and settings file datadir Usually usr share crossfire Contains data that the server does not need to modify while such as the etc A default install will pack the artifact
Definition: server-directories.txt:47
FLAG_MONSTER
#define FLAG_MONSTER
Will attack players.
Definition: define.h:245
list_system_quests
static bool list_system_quests
Whether to show 'system' quests or not.
Definition: mapper.cpp:372
generate_pics
static int generate_pics
Whether to generate the picture or not.
Definition: mapper.cpp:360
MAP_WIDTH
#define MAP_WIDTH(m)
Map width.
Definition: map.h:73
create_map_object
static nlohmann::json create_map_object(struct_map_info *map, const std::string &key)
Return a JSON map object.
Definition: mapper.cpp:2337
struct_quest::mainmap
struct_map_info * mainmap
Map defining the quest.
Definition: mapper.cpp:939
env
static std::shared_ptr< inja::Environment > env
Rendering environment.
Definition: mapper.cpp:2222
MAX_BUF
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
S_KEY
#define S_KEY
Definition: mapper.cpp:438
sort_map_info
static int sort_map_info(const void *left, const void *right)
Sorts the struct_map_info according to the map name or the path if equal.
Definition: mapper.cpp:903
fill_reverse_maps
static void fill_reverse_maps(struct_map_list &list)
Fill the reverse_maps array with the provided list.
Definition: mapper.cpp:2376
d
How to Install a Crossfire Server on you must install a python script engine on your computer Python is the default script engine of Crossfire You can find the python engine you have only to install them The VisualC Crossfire settings are for d
Definition: INSTALL_WIN32.txt:13
is_valid_faceset
int is_valid_faceset(int fsn)
Checks specified faceset is valid.
Definition: image.cpp:117
esrv_del_item
void esrv_del_item(player *pl, object *ob)
Tells the client to delete an item.
Definition: main.cpp:381
struct_map_info::tiled_x_from
int tiled_x_from
Definition: mapper.cpp:261
pageToRender
One page to render, with its parameters.
Definition: mapper.cpp:2705
IS_WEAPON
#define IS_WEAPON(op)
Definition: define.h:163
path
pluglist shows those as well as a short text describing each the list will simply appear empty The keyword for the Python plugin is Python plugout< keyword > Unloads a given identified by its _keyword_ So if you want to unload the Python you need to do plugout Python plugin< libname > Loads a given whose _filename_ is libname So in the case of you d have to do a plugin cfpython so Note that all filenames are relative to the default plugin path(SHARE/plugins). Console messages. ----------------- When Crossfire starts
object::move_slow
MoveType move_slow
Movement types this slows down.
Definition: object.h:441
sort_slaying
static int sort_slaying(const void *left, const void *right)
Helper function to sort an array of struct_slaying_info.
Definition: mapper.cpp:2979
tiled_map_list
static struct_map_list tiled_map_list
Pseudo-maps grouping other maps.
Definition: mapper.cpp:269
add_race_to_list
static void add_race_to_list(struct_race *race, struct_race_list *list, int check)
Appends a race to a race list.
Definition: mapper.cpp:335
StringBuffer
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.cpp:25
to
**Media tags please refer to the protocol file in doc Developers protocol Quick for your pleasure an example[/b][i] This is an old full of dirt and partially destroyed[hand] My dear as you two years i had to leave quickly Words have come to me of powerful magic scrolls discovered in an old temple by my uncle I have moved to study them I not forgot your knowledge in ancient languages I need your help for[print][b] Some parts of document are to damaged to be readable[/b][arcane] Arghis[color=Red] k h[color=dark slate blue] ark[color=#004000] fido[/color][hand] please come as fast as possible my friend[print][b] The bottom of letter seems deliberatly shredded What is but not limited to
Definition: media-tags.txt:30
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
check_equipment
static void check_equipment(object *item, struct_map_info *map)
Checks if item and its inventory are worthy to be listed.
Definition: mapper.cpp:631
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:717
EXIT
@ EXIT
Definition: object.h:186
path_stack
static std::vector< std::string > path_stack
Path, relative to output root, of pages being generated.
Definition: mapper.cpp:2628
merge_tiled_maps
static void merge_tiled_maps(struct_map_info *map, struct_map_info *tiled_map)
Merge two tiled maps groups.
Definition: mapper.cpp:1277
cached_pics
static int cached_pics
Non recreated pics.
Definition: mapper.cpp:378
struct_map_list::allocated
size_t allocated
Definition: mapper.cpp:236
list_map
static void list_map(const char *path)
Marks specified path as processed.
Definition: mapper.cpp:1338
struct_map_info::exits_to
struct_map_list exits_to
Definition: mapper.cpp:248
region
This is a game region.
Definition: map.h:274
struct_map_info::lore
char * lore
Definition: mapper.cpp:244
rendered_templates
static std::set< std::string > rendered_templates
List of generated files, to not generate multiple times.
Definition: mapper.cpp:2224
check_trigger
int check_trigger(object *op, object *cause)
Definition: button.cpp:518
apply_auto
int apply_auto(object *op)
Map was just loaded, handle op's initialization.
Definition: main.cpp:211
quest.h
S_DETECTOR
#define S_DETECTOR
Definition: mapper.cpp:440
struct_map_info::path
char * path
Full path of the map from the start directory.
Definition: mapper.cpp:241
struct_map_in_quest_list::count
size_t count
Definition: mapper.cpp:228
maps
this information may not reflect the current implementation This brief document is meant to describe the operation of the crossfire as well as the form of the data The metaserver listens on port for tcp and on port for udp packets The server sends updates to the metaserver via udp The metaserver only does basic checking on the data that server sends It trusts the server for the ip name it provides The metaserver does add the ip address and also tracks the idle time(time since last packet received). The client gets its information from the metaserver through connecting by means of tcp. The client should retrieve http the body s content type is text plain The current metaserver implementation is in Perl But the metaserver could be in any language perl is fast enough for the amount of data that is being exchanged The response includes zero or more server entries Each entry begins with the line START_SERVER_DATA and ends with the line END_SERVER_DATA Between these lines key value pairs("key=value") may be present. The entries are sent in arbitrary order. A client should apply some ordering when displaying the entries to the user. TODO b additional information outside BEGIN_SERVER_DATA END_SERVER_DATA maps
Definition: arch-handbook.txt:189
object::slaying
sstring slaying
Which race to do double damage to.
Definition: object.h:327
init_map_list
static void init_map_list(struct_map_list *list)
Initialises a list structure.
Definition: mapper.cpp:459
all_regions
std::vector< region * > all_regions
Definition: init.cpp:108
add_region_link
static void add_region_link(mapstruct *source, mapstruct *dest)
Creates a link between two maps if they are on different regions.
Definition: mapper.cpp:1407
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Will help players.
Definition: define.h:246
clean_tmp_files
void clean_tmp_files(void)
Save unique maps and clean up temporary map files unless recycling temporary maps.
Definition: main.cpp:351
init_library
void init_library(void)
It is vital that init_library() is called by any functions using this library.
Definition: init.cpp:322
object::name
sstring name
The name of the object, obviously...
Definition: object.h:319
free_equipment
static void free_equipment(struct_equipment *equip)
Frees a struct_equipment.
Definition: mapper.cpp:499
created_pics
static int created_pics
Picture statistics.
Definition: mapper.cpp:377
size_large
#define size_large
Definition: mapper.cpp:364
add_map_to_slaying
static void add_map_to_slaying(struct_slaying_info *info, int item, struct_map_info *map)
Adds the specified map to the slaying information if not already present.
Definition: mapper.cpp:1470
struct_region_info::sum
int sum
Sum of locations, to compute name position.
Definition: mapper.cpp:408
struct_map_info::readable
npc_list * readable
Definition: mapper.cpp:257
IS_ARMOR
#define IS_ARMOR(op)
Definition: define.h:166
OF_PNG
@ OF_PNG
PNG, default value.
Definition: mapper.cpp:382
object::artifact
sstring artifact
If set, the item is the artifact with this name and the matching type.
Definition: object.h:322
struct_region_info::maps_list
struct_map_list maps_list
Maps in the region.
Definition: mapper.cpp:407
struct_map_info::processed
int processed
Definition: mapper.cpp:261
FIREWALL
@ FIREWALL
Definition: object.h:173
PLAYER_CHANGER
@ PLAYER_CHANGER
Definition: object.h:167
mapstruct
This is a game-map.
Definition: map.h:315
object::env
object * env
Pointer to the object which is the environment.
Definition: object.h:301
create_pathname
char * create_pathname(const char *name, char *buf, size_t size)
Get the full path to a map file.
Definition: map.cpp:104
sstring
const typedef char * sstring
Definition: sstring.h:2
save_picture
static void save_picture(FILE *file, gdImagePtr pic)
Saves a map to a file, based on jpg/png settings.
Definition: mapper.cpp:1393
display_rendered_template
static bool display_rendered_template
Whether to display the template to be rendered or not.
Definition: mapper.cpp:373
templates_root
static std::string templates_root("templates/")
Directory to get templates from, with a leading /.
FLAG_AUTO_APPLY
#define FLAG_AUTO_APPLY
Will be applied when created.
Definition: define.h:250
quest_definition
Definition of an in-game quest.
Definition: quest.h:37
struct_map_info::monsters
struct_race_list monsters
Definition: mapper.cpp:254
find_archetype
archetype * find_archetype(const char *name)
Definition: assets.cpp:265
elevation_info
static int ** elevation_info
All elevation spots in the "world_" maps.
Definition: mapper.cpp:427
color_blocking
static int color_blocking
Block all movement.
Definition: mapper.cpp:424
struct_map_in_quest::description
char * description
Description associated with the map for the quest.
Definition: mapper.cpp:932
get_template
static inja::Template get_template(const std::string &filename)
Definition: mapper.cpp:2417
mapstruct::in_memory
uint32_t in_memory
Combination of IN_MEMORY_xxx flags.
Definition: map.h:335
esrv_update_item
void esrv_update_item(int flags, object *pl, object *op)
Updates object *op for player *pl.
Definition: main.cpp:359
object::msg
sstring msg
If this is a book/sign/magic mouth/etc.
Definition: object.h:330
struct_map_info::tiled_maps
struct_map_list tiled_maps
Definition: mapper.cpp:252
region_count
static size_t region_count
Count of regions.
Definition: mapper.cpp:413
do_parameters
static void do_parameters(int argc, char **argv)
Handles command-line parameters.
Definition: mapper.cpp:3029
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
all_data
static nlohmann::json all_data
All JSON data available to templates.
Definition: mapper.cpp:2223
face_info::datalen
uint16_t datalen
Length of data.
Definition: image.h:12
add_monster
static void add_monster(object *monster, struct_map_info *map)
Adds a monster to the monster list.
Definition: mapper.cpp:677
struct_map_in_quest_list::list
struct struct_map_in_quest ** list
Definition: mapper.cpp:227
MAP_HEIGHT
#define MAP_HEIGHT(m)
Map height.
Definition: map.h:75
struct_quest::number
int number
Unique quest identifier.
Definition: mapper.cpp:938
pageToRender::template_name
std::string template_name
Template name to use.
Definition: mapper.cpp:2707
struct_map_info::cfregion
region * cfregion
Definition: mapper.cpp:245
get_ob_diff
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
Returns a pointer to a static string which contains all variables which are different in the two give...
Definition: object.cpp:4986
find_player_partial_name
player * find_player_partial_name(const char *plname)
Find a player by a partial name.
Definition: player.cpp:114
sort_race
static int sort_race(const void *a, const void *b)
Sort 2 struct_race.
Definition: mapper.cpp:699
do_regions_link
static bool do_regions_link
Definition: mapper.cpp:432
arch_to_object
object * arch_to_object(archetype *at)
Creates and returns a new object which is a copy of the given archetype.
Definition: arch.cpp:227
object_give_identified_properties
void object_give_identified_properties(object *op)
Ensure op has all its "identified" properties set.
Definition: item.cpp:1361
stats
Player Stats effect how well a character can survie and interact inside the crossfire world This section discusses the various stats
Definition: stats.txt:2
init_race_list
static void init_race_list(struct_race_list *list)
Blanks a struct_race_list.
Definition: mapper.cpp:319
process_map
static void process_map(struct_map_info *info)
Processes a map.
Definition: mapper.cpp:1550
quests_allocated
static int quests_allocated
Allocated items in quests.
Definition: mapper.cpp:947
strcasecmp
int strcasecmp(const char *s1, const char *s2)
SearchName
static std::string SearchName[int(SearchType::Count)]
Search names for types, for the JS search engine.
Definition: mapper.cpp:305
sizes
static int sizes[]
Definition: mapper.cpp:362
reverse_regions
static std::map< region *, std::string > reverse_regions
Link between a region and its unique identifier.
Definition: mapper.cpp:2226
get_region_by_map
region * get_region_by_map(mapstruct *m)
Gets a region from a map.
Definition: region.cpp:71
S_DOOR
#define S_DOOR
Connection/slaying information.
Definition: mapper.cpp:437
object::randomitems
struct treasurelist * randomitems
Items to be generated.
Definition: object.h:395
create_tiled_map
static struct_map_info * create_tiled_map(void)
Create a new tiled map and link it to the tiled map list.
Definition: mapper.cpp:1261
world_map
static int world_map
If set, will generate a world map.
Definition: mapper.cpp:368
templates
static std::vector< std::string > templates
List of template files to start processing from.
Definition: mapper.cpp:2746
ignore_path
static const char * ignore_path[]
Directories to ignore for map search.
Definition: mapper.cpp:2844
Account_Chars
Structure handling character information for an account.
Definition: account_char.h:27
struct_map_list::count
size_t count
Definition: mapper.cpp:235
slaying_count
static size_t slaying_count
Count of items in slaying_info.
Definition: mapper.cpp:451
add_template_to_render
void add_template_to_render(const std::string &template_name, const std::string &output_name, const std::string &param)
Push the specified template, with optional param, on the list of files to process.
Definition: mapper.cpp:2719
object_remove
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to.
Definition: object.cpp:1833
remove_trailing_slash
static const char * remove_trailing_slash(const char *path)
Definition: mapper.cpp:2326
a
Magical Runes Runes are magical inscriptions on the dungeon which cast a spell or detonate when something steps on them Flying objects don t detonate runes Beware ! Runes are invisible most of the time They are only visible occasionally ! There are several runes which are there are some special runes which may only be called with the invoke and people may apply it to read it Maybe useful for mazes ! This rune will not nor is it ordinarily invisible Partial Visibility of they ll be visible only part of the time They have a(your level/2) chance of being visible in any given round
infomap
static gdImagePtr infomap
World map with exits / roads / blocking / ...
Definition: mapper.cpp:420
sort_struct_map_in_quest
static int sort_struct_map_in_quest(const void *left, const void *right)
Sorts 2 struct_map_in_quest, on the map's name or path.
Definition: mapper.cpp:1036
struct_map_info::height
int height
Definition: mapper.cpp:260
ALTAR
@ ALTAR
Definition: object.h:127
player_get_delayed_buffer
SockList * player_get_delayed_buffer(player *pl)
Get a delayed socket buffer, that will be sent after the player's tick is complete.
Definition: player.cpp:4501
struct_npc_info::x
int x
Definition: mapper.cpp:212
relative_path
static void relative_path(const char *from, const char *to, char *result)
Computes the shortest path from one file to another.
Definition: mapper.cpp:834
FLAG_UNPAID
#define FLAG_UNPAID
Object hasn't been paid for yet.
Definition: define.h:236
dump_unused_maps
static void dump_unused_maps(void)
Writes the list of unused maps, maps found in the directories but not linked from the other maps.
Definition: mapper.cpp:2909
sort_region
static int sort_region(const void *left, const void *right)
Sorts an array of struct_region_info by region name.
Definition: mapper.cpp:919
special_equipment
static std::vector< struct_equipment * > special_equipment
Special equipment list.
Definition: mapper.cpp:280
make_path_to_file
void make_path_to_file(const char *filename)
Checks if any directories in the given path doesn't exist, and creates if necessary.
Definition: porting.cpp:164
FREE_OBJ_FREE_INVENTORY
#define FREE_OBJ_FREE_INVENTORY
Free inventory objects; if not set, drop inventory.
Definition: object.h:544
fix_exits_for_map
static void fix_exits_for_map(struct_map_info *current, struct_map_list *from, int is_from)
Changes for the list all maps to the tiled map they are part of, if applicable.
Definition: mapper.cpp:1983
account_char_load
Account_Chars * account_char_load(const char *account_name)
For a given account name, load the character information and return it.
Definition: account_char.cpp:135
SCROLL
@ SCROLL
Definition: object.h:226
archetype::name
sstring name
More definite name, like "generate_kobold".
Definition: object.h:484
FLAG_IS_LINKED
#define FLAG_IS_LINKED
The object is linked with other objects.
Definition: define.h:315
struct_npc_info::name
const char * name
NPC's name.
Definition: mapper.cpp:210
object::nrof
uint32_t nrof
Number of objects.
Definition: object.h:342
split
static std::vector< std::string > split(const std::string &field, const std::string &by)
Definition: mapper.cpp:2734
mapstruct::reset_time
uint32_t reset_time
Server time when map gets reset, seconds since epoch.
Definition: map.h:322
do_help
static void do_help(const char *program)
Prints usage information, and exit.
Definition: mapper.cpp:2992
object::stats
living stats
Str, Con, Dex, etc.
Definition: object.h:378
list
How to Install a Crossfire Server on you must install a python script engine on your computer Python is the default script engine of Crossfire You can find the python engine you have only to install them The VisualC Crossfire settings are for but you habe then to change the pathes in the VC settings Go in Settings C and Settings Link and change the optional include and libs path to the new python installation path o except the maps ! You must download a map package and install them the share folder Its must look like doubleclick on crossfire32 dsw There are projects in your libcross lib and plugin_python You need to compile all Easiest way is to select the plugin_python ReleaseLog as active this will compile all others too Then in Visual C press< F7 > to compile If you don t have an appropriate compiler you can try to get the the VC copies the crossfire32 exe in the crossfire folder and the plugin_python dll in the crossfire share plugins folder we will remove it when we get time for it o Last showing lots of weird write to the Crossfire mailing list
Definition: INSTALL_WIN32.txt:50
artifact
This is one artifact, ie one special item.
Definition: artifact.h:14
struct_quest::name
char * name
Quest's name.
Definition: mapper.cpp:936
get_faces_count
size_t get_faces_count()
Definition: assets.cpp:292
calc_item_power
int calc_item_power(const object *op)
This takes an object 'op' and figures out what its item_power rating should be.
Definition: item.cpp:235
write_world_info
static void write_world_info(void)
Writes the exit information world map.
Definition: mapper.cpp:2927
struct_map_in_quest_list::allocated
size_t allocated
Definition: mapper.cpp:229
tiled_map_need_pic
static int tiled_map_need_pic(struct_map_info *map)
Definition: mapper.cpp:2057
face_sets
Information about one face set.
Definition: image.h:17
SearchType::Count
@ Count
SPELL
@ SPELL
Definition: object.h:219
map_limit
static int map_limit
Maximum number of maps to browse, -1 for all.
Definition: mapper.cpp:366
closedir
int closedir(DIR *)
quests
static struct_quest ** quests
All quests in the game.
Definition: mapper.cpp:943
account_char_save
void account_char_save(Account_Chars *chars)
Saves the character information for the given account.
Definition: account_char.cpp:158
fix_tiled_map
static void fix_tiled_map(void)
Ensures all tiled maps have a name, a region, a filename and a path.
Definition: mapper.cpp:1914
FLAG_CURSED
#define FLAG_CURSED
The object is cursed.
Definition: define.h:316
output_format_type
output_format_type
Map output formats.
Definition: mapper.cpp:381
TELEPORTER
@ TELEPORTER
Definition: object.h:146
pics_allocated
static int pics_allocated
Number of created pictures for GD.
Definition: mapper.cpp:357
struct_equipment
One special item (weapon, shield, ...).
Definition: mapper.cpp:272
face_sets::faces
face_info * faces
images in this faceset
Definition: image.h:26
SockList
Contains the base information we use to make up a packet we want to send.
Definition: newclient.h:684
IS_ARROW
#define IS_ARROW(op)
Definition: define.h:178
SPELLBOOK
@ SPELLBOOK
Definition: object.h:208
object::move_block
MoveType move_block
What movement types this blocks.
Definition: object.h:437
found_maps
static std::vector< char * > found_maps
Maps found in directories.
Definition: mapper.cpp:417
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:664
living::hp
int16_t hp
Hit Points.
Definition: living.h:40
create_treasure
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
This calls the appropriate treasure creation function.
Definition: treasure.cpp:263
find_map_by_key
static struct_map_info * find_map_by_key(const std::string &key)
Get the map with the specified key, nullptr if not found.
Definition: mapper.cpp:2233
warn_no_path
static int warn_no_path
Whether to warn of exits without a path.
Definition: mapper.cpp:402
find_quest_info
static struct_quest * find_quest_info(const char *name)
Gets the information for a quest if it exists.
Definition: mapper.cpp:968
DETECTOR
@ DETECTOR
peterm: detector is an object which notices the presense of another object and is triggered like butt...
Definition: object.h:154
find_maps
static void find_maps(const char *from)
Recursively find all all maps in a directory.
Definition: mapper.cpp:2869
struct_slaying_info::slaying
char * slaying
Slaying value.
Definition: mapper.cpp:446
is_road
static int is_road(object *item)
Checks if object is considered a road or not.
Definition: mapper.cpp:712
elevation_min
static int elevation_min
Maximal elevation found.
Definition: mapper.cpp:428
color_linked_exit
static int color_linked_exit
Exit leading to another map.
Definition: mapper.cpp:422
sort_equipment
static bool sort_equipment(const struct_equipment *l, const struct_equipment *r)
Sort 2 struct_equipment.
Definition: mapper.cpp:513
add_one_item
static void add_one_item(object *item, struct_map_info *map)
Adds an item to the list of special items.
Definition: mapper.cpp:557
FLAG_IDENTIFIED
#define FLAG_IDENTIFIED
Player knows full info about item.
Definition: define.h:261
account_logout
void account_logout(const char *account_name)
Remove 'account_name' from the list of logged in accounts.
Definition: account.cpp:337
SearchType::Map
@ Map
pageToRender::output_name
std::string output_name
Output file name.
Definition: mapper.cpp:2708
identify
object * identify(object *op)
Identifies an item.
Definition: item.cpp:1426